Author Topic: Improvement in TabSwitcher  (Read 31770 times)

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #15 on: January 12, 2010, 08:18:46 pm »
Oops... I mean exactly way 4, but don`t understand that post correctly (I don`t know English well). Of course we must simply change event handler depending on checkbox in Environment settings panel. (with using dynamic event handling, or with simply IF-THEN-ELSE in static handler).
In earliest version s it was in "Notebook appearance", if I`m not mistake.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Improvement in TabSwitcher
« Reply #16 on: January 12, 2010, 09:03:03 pm »
Morten, where is last version of this patch ?
I need to be at home and need to have some spare time for that. Both is not the case atm... be patient.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #17 on: January 12, 2010, 09:04:04 pm »
I agree with you....
I re-install old 8.02 version....
I fact, this option was used as Use Smart Tab-switching scheme. I can re-add it !
Where are you come from ? I'm french, not english...

It was removed when notebook was changed ?

If then else is the simplest way, no need to make it complicated !
Looking for a new patch.....
Post here in few hours....

Another thing : the window that is opened when we press CTRL+TAB is bugged .. if the mouse is over, even if the mouse not moved, select automatically a window that the user doesn't want.

Ok ?

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #18 on: January 12, 2010, 10:10:22 pm »
SmartTabSwitch is now using by Alt+Left/Right. I don`t know why. wxFlatNotebook has a build-in tab stack which was used by tab switcher. In wxAuiNotebook this feature is missed.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #19 on: January 12, 2010, 10:50:43 pm »
What should I do ? put this check box again ? Another way ?
Where are you from ?

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #20 on: January 12, 2010, 11:04:05 pm »
I think you should place check box with something like "Use stack-based CTRL-TAB".

I`m from Russia.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #21 on: January 12, 2010, 11:25:36 pm »
Nice to meet you Alatar.
I have added "Use stacked based tab-switching" into Setting/Environment/Notebooks appearance
Correct (need to test) the bug of opened dialog with window list : the user need to move the mouse to select an item.
Do you see this problem ? Put your mouse over the 4th item and select CTRL+TAB, you will see, you always select the 4th item.... To correctly use CTRL+TAB your mouse must not be in the middle of the screen, else it doesn't work.

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #22 on: January 13, 2010, 06:18:28 am »
It is not a bug, it is a feature =) I think this must be controlled in Settings to.  Something like "Select document in tab switcher when mouse hover".
« Last Edit: January 13, 2010, 11:11:53 am by Alatar »

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #23 on: January 13, 2010, 09:56:20 am »
It is not a bug, it is a feature =) I think this must be controls in Settings to.  Something like "Select document in tab switcher when mouse hover".
Yes, when mouse is over.... but if your mouse is in the center on the window and you don't touch it, you are not able to select the item you want, its takes automatically the item under the mouse, even you don't move the mouse. If you press CTRL+TAB and select another item and unpress CTRL, it don't select the highlight item because the mouse is over another one..... For me it is a bug !
I modify it : you can choose item with the mouse ONLY if you move the mouse over a rect of 3 pixel width/height. If you unpress CTRL and don't move the mouse, it don't try to select the item under the mouse cursor, let the current selected one....
Testing and propose a patch here....
With : this patch
and  : "Use stacked based tab-switching" added option into Setting/Environment/Notebooks appearance

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #24 on: January 13, 2010, 11:10:32 am »
you can choose item with the mouse ONLY if you move the mouse over a rect of 3 pixel width/height.

Good idea.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #25 on: January 13, 2010, 12:38:03 pm »
Ok, tested ! It's work perfectly.
This patch contains :
- "Use stacked based tab-switching" added option into Setting/Environment/Notebooks appearance
- Depending of option "Use stacked based tab-switching", the CTRL+TAB has old comportment if unchecked, if checked it has the stacked  tab switching comportment.
- Bug fix : When window selection opened (when pressing CTRL+TAB), it doesn't select the item under the mouse cursor automatically, only if the user move the mouse cursor more that 3 pixels width/height.
- Bug fix : When window selection is open (when pressing CTRL+TAB), when selecting an item with the mouse (just move, without pressing button), if the user select another window by pressing CTRL+TAB again, release CTRL now select the highlight item not the item under the mouse cursor.
Patch :
Code
Index: src/include/editormanager.h
===================================================================
--- src/include/editormanager.h (revision 6080)
+++ src/include/editormanager.h (working copy)
@@ -45,6 +45,20 @@
 struct cbFindReplaceData;
 
 /*
+ * Struct for store tabs stack info
+ */
+struct cbNotebookStack
+{
+    cbNotebookStack(wxWindow* a_pWindow = NULL)
+        : m_pWindow (a_pWindow),
+          m_pNextNotebookStack (NULL)
+    {}
+
+    wxWindow*           m_pWindow;
+    cbNotebookStack*    m_pNextNotebookStack;
+};
+
+/*
  * No description
  */
 class DLLIMPORT EditorManager : public Mgr<EditorManager>, public wxEvtHandler
@@ -59,6 +73,7 @@
         virtual void operator=(const EditorManager& rhs){ cbThrow(_T("Can't assign an EditorManager* !!!")); }
 
         wxAuiNotebook* GetNotebook(){ return m_pNotebook; }
+        cbNotebookStack* GetNotebookStack();
         void CreateMenu(wxMenuBar* menuBar);
         void ReleaseMenu(wxMenuBar* menuBar);
         void Configure();
@@ -174,6 +189,9 @@
         wxFileName FindHeaderSource(const wxArrayString& candidateFilesArray, const wxFileName& activeFile, bool& isCandidate);
 
         wxAuiNotebook* m_pNotebook;
+        cbNotebookStack* m_pNotebookStackHead;
+        cbNotebookStack* m_pNotebookStackTail;
+        size_t m_nNotebookStackSize;
         cbFindReplaceData* m_LastFindReplaceData;
         EditorColourSet* m_Theme;
         ListCtrlLogger* m_pSearchLog;
Index: src/sdk/editormanager.cpp
===================================================================
--- src/sdk/editormanager.cpp (revision 6080)
+++ src/sdk/editormanager.cpp (working copy)
@@ -156,6 +156,9 @@
 
 EditorManager::EditorManager()
         : m_pNotebook(0L),
+        m_pNotebookStackHead(new cbNotebookStack),
+        m_pNotebookStackTail(m_pNotebookStackHead),
+        m_nNotebookStackSize(0),
         m_LastFindReplaceData(0L),
         m_pSearchLog(0),
         m_SearchLogIndex(-1),
@@ -192,6 +195,55 @@
     Manager::Get()->GetConfigManager(_T("editor"))->Write(_T("/zoom"), m_zoom);
 }
 
+cbNotebookStack* EditorManager::GetNotebookStack()
+{
+    bool bFounded = false;
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+
+    while(m_nNotebookStackSize != m_pNotebook->GetPageCount()) //Sync stack with Notebook
+    {
+        if(m_nNotebookStackSize < m_pNotebook->GetPageCount())
+        {
+            for(size_t i = 0; i<m_pNotebook->GetPageCount(); ++i)
+            {
+                pWindow = m_pNotebook->GetPage(i);
+                bFounded = false;
+                for (pNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack; pNotebookStack != NULL; pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+                {
+                    if(pWindow == pNotebookStack->m_pWindow)
+                    {
+                        bFounded = true;
+                        break;
+                    }
+                }
+                if(!bFounded)
+                {
+                    m_pNotebookStackTail->m_pNextNotebookStack = new cbNotebookStack(pWindow);
+                    m_pNotebookStackTail = m_pNotebookStackTail->m_pNextNotebookStack;
+                    ++m_nNotebookStackSize;
+                }
+            }
+        }
+        if(m_nNotebookStackSize > m_pNotebook->GetPageCount())
+        {
+            for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+            {
+                if(m_pNotebook->GetPageIndex(pNotebookStack->m_pWindow) == wxNOT_FOUND)
+                {
+                    pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+                    delete pNotebookStack;
+                    --m_nNotebookStackSize;
+                    pNotebookStack = pPrevNotebookStack;
+                }
+            }
+        }
+    }
+
+    return m_pNotebookStackHead->m_pNextNotebookStack;
+}
+
 void EditorManager::CreateMenu(wxMenuBar* menuBar)
 {
 }
@@ -2510,6 +2562,32 @@
     CodeBlocksEvent evt(cbEVT_EDITOR_ACTIVATED, -1, 0, eb);
     Manager::Get()->GetPluginManager()->NotifyPlugins(evt);
 
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+    pWindow = m_pNotebook->GetPage(event.GetSelection());
+    for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+    {
+        if(pWindow == pNotebookStack->m_pWindow)
+        {
+            if(m_pNotebookStackTail == pNotebookStack)
+            {
+                m_pNotebookStackTail = pPrevNotebookStack;
+            }
+            pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+            pNotebookStack->m_pNextNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack;
+            m_pNotebookStackHead->m_pNextNotebookStack = pNotebookStack;
+            break;
+        }
+    }
+    if((m_pNotebookStackHead->m_pNextNotebookStack == NULL)||(pWindow != m_pNotebookStackHead->m_pNextNotebookStack->m_pWindow))
+    {
+        pNotebookStack = new cbNotebookStack(pWindow);
+        pNotebookStack->m_pNextNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack;
+        m_pNotebookStackHead->m_pNextNotebookStack = pNotebookStack;
+        ++m_nNotebookStackSize;
+    }
+
     // focus editor on next update event
     m_pData->m_SetFocusFlag = true;
 
@@ -2539,6 +2617,21 @@
         if (!QueryClose(eb))
             event.Veto();
     }
+
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+    pWindow = m_pNotebook->GetPage(event.GetSelection());
+    for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+    {
+        if(pWindow == pNotebookStack->m_pWindow)
+        {
+            pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+            delete pNotebookStack;
+            --m_nNotebookStackSize;
+            break;
+        }
+    }
     event.Skip(); // allow others to process it too
 }
 
Index: src/src/environmentsettingsdlg.cpp
===================================================================
--- src/src/environmentsettingsdlg.cpp (revision 6080)
+++ src/src/environmentsettingsdlg.cpp (working copy)
@@ -170,6 +170,7 @@
     // tab "Notebook"
     XRCCTRL(*this, "cmbEditorTabs", wxComboBox)->SetSelection(cfg->ReadInt(_T("/environment/tabs_style"), 0));
     XRCCTRL(*this, "chkListTabs", wxCheckBox)->SetValue(cfg->ReadBool(_T("/environment/tabs_list"), 0));
+    XRCCTRL(*this, "chkStackedBasedTabSwitching", wxCheckBox)->SetValue(cfg->ReadBool(_T("/environment/stacked_based_tab_switching"), 0));
 
     // tab "Docking"
     XRCCTRL(*this, "spnAuiBorder", wxSpinCtrl)->SetValue(cfg->ReadInt(_T("/environment/aui/border_size"), m_pArt->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE)));
@@ -409,6 +410,7 @@
         // tab "Appearence"
         cfg->Write(_T("/environment/tabs_style"),           (int)XRCCTRL(*this, "cmbEditorTabs", wxComboBox)->GetSelection());
         cfg->Write(_T("/environment/tabs_list"),           (bool)XRCCTRL(*this, "chkListTabs", wxCheckBox)->GetValue());
+        cfg->Write(_T("/environment/stacked_based_tab_switching"),(bool)XRCCTRL(*this, "chkStackedBasedTabSwitching", wxCheckBox)->GetValue());
         cfg->Write(_T("/environment/aui/border_size"),          (int)XRCCTRL(*this, "spnAuiBorder", wxSpinCtrl)->GetValue());
         cfg->Write(_T("/environment/aui/sash_size"),            (int)XRCCTRL(*this, "spnAuiSash", wxSpinCtrl)->GetValue());
         cfg->Write(_T("/environment/aui/caption_size"),         (int)XRCCTRL(*this, "spnAuiCaption", wxSpinCtrl)->GetValue());
Index: src/src/main.cpp
===================================================================
--- src/src/main.cpp (revision 6080)
+++ src/src/main.cpp (working copy)
@@ -4010,27 +4010,64 @@
     // Create container and add all open editors:
     wxSwitcherItems items;
     items.AddGroup(_("Open files"), wxT("editors"));
-    for (size_t i = 0; i < nb->GetPageCount(); ++i)
-    {
-        wxString title = nb->GetPageText(i);
-        wxWindow* window = nb->GetPage(i);
 
-        items.AddItem(title, title, i, nb->GetPageBitmap(i)).SetWindow(window);
+    ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("app"));
+    if (!pCfg->ReadBool(_T("/environment/stacked_based_tab_switching")))
+    {   // Switch tabs editor with tab order
+        for (size_t i = 0; i < nb->GetPageCount(); ++i)
+        {
+            wxString title = nb->GetPageText(i);
+            wxWindow* window = nb->GetPage(i);
+
+            items.AddItem(title, title, i, nb->GetPageBitmap(i)).SetWindow(window);
+        }
+
+        // Select the focused editor:
+        int idx = items.GetIndexForFocus();
+        if (idx != wxNOT_FOUND)
+        {
+            items.SetSelection(idx);
+        }
     }
+    else
+    {   // Switch tabs editor with last used order
+        size_t nIndex = 0;
+        cbNotebookStack* pNotebookStack;
+        for (pNotebookStack = Manager::Get()->GetEditorManager()->GetNotebookStack() ; pNotebookStack != NULL; pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+        {
+            nIndex = nb->GetPageIndex(pNotebookStack->m_pWindow);
+            if (nIndex == (size_t) wxNOT_FOUND)
+            {
+                continue;
+            }
+            wxString title = nb->GetPageText(nIndex);
 
-    // Select the focused editor:
-    int idx = items.GetIndexForFocus();
-    if (idx != wxNOT_FOUND)
-        items.SetSelection(idx);
+            items.AddItem(title, title, nIndex, nb->GetPageBitmap(nIndex)).SetWindow(pNotebookStack->m_pWindow);
+        }
 
+        // Select the focused editor:
+        if(items.GetItemCount() > 2)
+        {   // CTRL + TAB directly select the last editor, not the current one
+            items.SetSelection(2);
+        }
+        else
+        {
+            items.SetSelection(items.GetItemCount()-1);
+        }
+    }
+
     // Create the switcher dialog
     wxSwitcherDialog dlg(items, wxGetApp().GetTopWindow());
 
     // Ctrl+Tab workaround for non windows platforms:
     if (platform::cocoa)
+    {
         dlg.SetModifierKey(WXK_ALT);
+    }
     else if (platform::gtk)
+    {
         dlg.SetExtraNavigationKey(wxT(','));
+    }
 
     // Finally show the dialog:
     int answer = dlg.ShowModal();
Index: src/src/resources/env_settings.xrc
===================================================================
--- src/src/resources/env_settings.xrc (revision 6080)
+++ src/src/resources/env_settings.xrc (working copy)
@@ -398,6 +398,13 @@
  <flag>wxALL|wxALIGN_LEFT|wxALIGN_TOP</flag>
  <border>8</border>
  </object>
+ <object class="sizeritem">
+ <object class="wxCheckBox" name="chkStackedBasedTabSwitching">
+ <label>Use stacked based tab-switching</label>
+ </object>
+ <flag>wxALL|wxALIGN_LEFT|wxALIGN_TOP</flag>
+ <border>8</border>
+ </object>
  </object>
  </object>
  <label>Notebooks appearance</label>
Index: src/src/switcherdlg.cpp
===================================================================
--- src/src/switcherdlg.cpp (revision 6080)
+++ src/src/switcherdlg.cpp (working copy)
@@ -509,26 +509,45 @@
 
         Refresh();
     }
-    else
-    {
-        int idx = m_items.HitTest(event.GetPosition());
+    else if (event.GetButton() == wxMOUSE_BTN_NONE)
+    {   // Mouse move
+        bool bCanSelectItem = true;
+        if (m_ptMouse.x != -2 && m_ptMouse.y != -2)
+        {   // If ==-2 => Don't select item on mouse pointer : used when user select the window with keyboard
+            if (m_ptMouse.x != -1 && m_ptMouse.y != -1)
+            {   // If ==-1 => The client already move the mouse, select the item under the mouse cursor
+                wxPoint ptCurrent = ClientToScreen(event.GetPosition());
+                if (abs(ptCurrent.x - m_ptMouse.x) >= 3 || abs(ptCurrent.y - m_ptMouse.y) >= 3)
+                {   // the user has moved the mouse over a 3 pixels square
+                    m_ptMouse.x = m_ptMouse.y = -1; // Accept to select an item
+                }
+                else
+                {   // Select this item is not allowed for the moment, the user must move the mouse
+                    bCanSelectItem = false;
+                }
+            }
 
-        if (idx != wxNOT_FOUND)
-        {
-            m_items.SetSelection(idx);
+            if (bCanSelectItem)
+            {
+                int idx = m_items.HitTest(event.GetPosition());
 
-            GenerateSelectionEvent();
+                if (idx != wxNOT_FOUND)
+                {
+                    m_items.SetSelection(idx);
 
-            Refresh();
-        }
+                    GenerateSelectionEvent();
 
-        if (event.LeftDown())
-        {
-            SendCloseEvent();
-
-            SetFocus();
+                    Refresh();
+                }
+            }
         }
     }
+    else if (event.LeftDown())
+    {
+        m_ptMouse.x = m_ptMouse.y = -1; // Accept to select an item
+        SendCloseEvent();
+        SetFocus();
+    }
 }
 
 void wxMultiColumnListCtrl::OnChar(wxKeyEvent& WXUNUSED(event))
@@ -541,6 +560,8 @@
     {
         if (event.GetKeyCode() == GetModifierKey())
         {
+            // The window will close, don't select the item under mouse pointer
+            m_ptMouse.x = m_ptMouse.y = -2;
             SendCloseEvent();
         }
         event.Skip();
@@ -549,6 +570,9 @@
 
     if (event.GetKeyCode() == WXK_ESCAPE || event.GetKeyCode() == WXK_RETURN)
     {
+        // The window will close, don't select the item under mouse pointer
+        m_ptMouse.x = m_ptMouse.y = -2;
+
         if (event.GetKeyCode() == WXK_ESCAPE)
             m_items.SetSelection(-1);
 
@@ -802,6 +826,7 @@
     m_overallSize = wxSize(200, 100);
     m_modifierKey = WXK_CONTROL;
     m_extraNavigationKey = 0;
+    m_ptMouse = wxGetMousePosition();
 }
 
 /*!
Index: src/src/switcherdlg.h
===================================================================
--- src/src/switcherdlg.h (revision 6080)
+++ src/src/switcherdlg.h (working copy)
@@ -233,7 +233,15 @@
     void SendCloseEvent();
 
 protected:
-
+    /**
+     * Mouse point initialized on Init function.
+     *
+     * Used because if the mouse is over the dialog when it's opened, it automatically
+     * select the item under the mouse pointer.
+     * Recording the mouse pointer position when the dialog is opened prevent this :
+     * select the item only if the user move the mouse.
+    */
+    wxPoint             m_ptMouse;
     wxSwitcherItems     m_items;
     wxSize              m_overallSize;
     int                 m_extraNavigationKey;

Thanks for all to give me Feedback.
I place comments into my Codeblocks source patch. I don't see very often comments into source code (specially into .h), I don't know if it's good or not to place comments (into javadoc format).

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #26 on: January 14, 2010, 10:31:42 pm »
Added new version of patch to tracker - http://developer.berlios.de/patch/index.php?func=detailpatch&patch_id=2902&group_id=5358

Included all changes from Feneck91`s last patch.
Some code cleanup, simplify code in functions GetNotebookStack(), OnPageChanged() and OnPageClose().
Added stack deletion and rebuild stack function.
If we not using stack based tab switching, we don`t manage stack. But I don`t know, where should I rebuild stack, when it turn on in settings. For now I place this code into EnvironmentSettingsDlg::EndModal(), but it seems wrong - there are no such code. Marting, what do you think?

Feneck91, by the way, don`t use long camel case names for local variables - this is not Code::Blocks style =) .

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #27 on: January 15, 2010, 05:03:59 am »
Code
Feneck91, by the way, don`t use long camel case names for local variables
I'm sorry, I didn't understand. What is camel  case name ?

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 60
Re: Improvement in TabSwitcher
« Reply #28 on: January 15, 2010, 05:57:26 am »
I'm sorry, I didn't understand. What is camel  case name ?
ItIsSameAsMixedCase ;)
http://en.wikipedia.org/wiki/CamelCase

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Improvement in TabSwitcher
« Reply #29 on: January 15, 2010, 06:38:08 am »
Code
Feneck91, by the way, don`t use [b]long[/b] camel case names for local variables
I'm sorry, I didn't understand. What is camel  case name ?
I think whar he meant was the long names. As variable names that are too long make the code harder to read.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ