1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11866 $
6  * $Id: main.cpp 11866 2019-09-29 16:10:16Z fuscated $
7  * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/src/main.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #include "app.h"
13 #include "appglobals.h"
14 #include "batchbuild.h"
15 #include "cbart_provider.h"
16 #include "cbauibook.h"
17 #include "cbstyledtextctrl.h"
18 #include "compilersettingsdlg.h"
19 #include "debuggersettingsdlg.h"
20 #include "dlgabout.h"
21 #include "dlgaboutplugin.h"
22 #include "environmentsettingsdlg.h"
23 #include "infopane.h"
24 #include "infowindow.h"
25 #include "main.h"
26 #include "notebookstyles.h"
27 #include "printdlg.h"
28 #include "scriptconsole.h"
29 #include "scriptingsettingsdlg.h"
30 #include "startherepage.h"
31 #include "switcherdlg.h"
32 #include "cbstatusbar.h"
33 #include "loggers.h"
34 
35 #include <wx/display.h>
36 #include <wx/dnd.h>
37 #include <wx/fileconf.h>
38 #include <wx/filename.h>
39 #include <wx/gdicmn.h>
40 #include <wx/printdlg.h>
41 #include <wx/sstream.h>
42 #include <wx/tipdlg.h>
43 #include <wx/tokenzr.h>
44 #include <wx/xrc/xmlres.h>
45 
46 #include <annoyingdialog.h>
47 #include <cbexception.h>
48 #include <cbplugin.h>
49 #include <cbproject.h>
50 #include <cbworkspace.h>
51 #include <ccmanager.h>
52 #include <configmanager.h>
53 #include <debuggermanager.h>
54 #include <editorcolourset.h>
55 #include <editormanager.h>
56 #include <filefilters.h>
57 #include <globals.h>
58 #include <logmanager.h>
59 #include <personalitymanager.h>
60 #include <pluginmanager.h>
61 #include <projectmanager.h>
62 #include <scriptingmanager.h>
63 #include <sdk_events.h>
64 #include <templatemanager.h>
65 #include <toolsmanager.h>
66 #include <uservarmanager.h>
67 
68 #include "debugger_interface_creator.h"
69 #include "debuggermenu.h"
70 
71 #include "cbcolourmanager.h"
72 #include "editorconfigurationdlg.h"
73 #include "projectmanagerui.h"
74 
75 class cbFileDropTarget : public wxFileDropTarget
76 {
77 public:
cbFileDropTarget(MainFrame * frame)78     cbFileDropTarget(MainFrame *frame):m_frame(frame){}
OnDropFiles(wxCoord x,wxCoord y,const wxArrayString & filenames)79     bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) override
80     {
81         if (!m_frame) return false;
82         return m_frame->OnDropFiles(x,y,filenames);
83     }
84 private:
85     MainFrame* m_frame;
86 };
87 
88 const static wxString gDefaultLayout = _T("Code::Blocks default");
89 static wxString gDefaultLayoutData; // this will keep the "hardcoded" default layout
90 static wxString gDefaultMessagePaneLayoutData; // this will keep default layout
91 
92 const static wxString gMinimalLayout = _T("Code::Blocks minimal");
93 static wxString gMinimalLayoutData; // this will keep the "hardcoded" default layout
94 static wxString gMinimalMessagePaneLayoutData; // this will keep default layout
95 
96 // In <wx/defs.h> wxID_FILE[X] exists only from 1..9,
97 // so create our own here with a *continuous* numbering!
98 // The wxID_FILE[X] enum usually starts at 5050 until 5059,
99 // followed by wxID_OK starting at 5100. (wxWidgets v2.6, v2.8 and v2.9)
100 // so we use the space in between starting from 5060
101 // and hoping it doesn't change too much in <wx/defs.h> ;-)
102 enum
103 {
104     wxID_CBFILE01   = 5060, // Recent files...
105     wxID_CBFILE02, // 5061
106     wxID_CBFILE03, // 5062
107     wxID_CBFILE04, // 5063
108     wxID_CBFILE05, // 5064
109     wxID_CBFILE06, // 5065
110     wxID_CBFILE07, // 5066
111     wxID_CBFILE08, // 5067
112     wxID_CBFILE09, // 5068
113     wxID_CBFILE10, // 5069
114     wxID_CBFILE11, // 5070
115     wxID_CBFILE12, // 5071
116     wxID_CBFILE13, // 5072
117     wxID_CBFILE14, // 5073
118     wxID_CBFILE15, // 5074
119     wxID_CBFILE16, // 5075
120     wxID_CBFILE17, // 5076  // Starting here for recent projects...
121     wxID_CBFILE18, // 5077
122     wxID_CBFILE19, // 5078
123     wxID_CBFILE20, // 5079
124     wxID_CBFILE21, // 5080
125     wxID_CBFILE22, // 5081
126     wxID_CBFILE23, // 5082
127     wxID_CBFILE24, // 5083
128     wxID_CBFILE25, // 5084
129     wxID_CBFILE26, // 5085
130     wxID_CBFILE27, // 5086
131     wxID_CBFILE28, // 5087
132     wxID_CBFILE29, // 5088
133     wxID_CBFILE30, // 5089
134     wxID_CBFILE31, // 5090
135     wxID_CBFILE32  // 5091
136 };
137 
138 int idToolNew                           = XRCID("idToolNew");
139 int idFileNew                           = XRCID("idFileNew");
140 int idFileNewEmpty                      = XRCID("idFileNewEmpty");
141 int idFileNewProject                    = XRCID("idFileNewProject");
142 int idFileNewTarget                     = XRCID("idFileNewTarget");
143 int idFileNewFile                       = XRCID("idFileNewFile");
144 int idFileNewCustom                     = XRCID("idFileNewCustom");
145 int idFileNewUser                       = XRCID("idFileNewUser");
146 int idFileOpen                          = XRCID("idFileOpen");
147 int idFileReopen                        = XRCID("idFileReopen");
148 int idFileOpenRecentFileClearHistory    = XRCID("idFileOpenRecentFileClearHistory");
149 int idFileOpenRecentProjectClearHistory = XRCID("idFileOpenRecentProjectClearHistory");
150 int idFileImportProjectDevCpp           = XRCID("idFileImportProjectDevCpp");
151 int idFileImportProjectMSVC             = XRCID("idFileImportProjectMSVC");
152 int idFileImportProjectMSVCWksp         = XRCID("idFileImportProjectMSVCWksp");
153 int idFileImportProjectMSVS             = XRCID("idFileImportProjectMSVS");
154 int idFileImportProjectMSVSWksp         = XRCID("idFileImportProjectMSVSWksp");
155 int idFileSave                          = XRCID("idFileSave");
156 int idFileSaveAs                        = XRCID("idFileSaveAs");
157 int idFileReopenProject                 = XRCID("idFileReopenProject");
158 int idFileSaveProject                   = XRCID("idFileSaveProject");
159 int idFileSaveProjectAs                 = XRCID("idFileSaveProjectAs");
160 int idFileSaveProjectTemplate           = XRCID("idFileSaveProjectTemplate");
161 int idFileOpenDefWorkspace              = XRCID("idFileOpenDefWorkspace");
162 int idFileSaveWorkspace                 = XRCID("idFileSaveWorkspace");
163 int idFileSaveWorkspaceAs               = XRCID("idFileSaveWorkspaceAs");
164 int idFileSaveAll                       = XRCID("idFileSaveAll");
165 int idFileCloseWorkspace                = XRCID("idFileCloseWorkspace");
166 int idFileClose                         = XRCID("idFileClose");
167 int idFileCloseAll                      = XRCID("idFileCloseAll");
168 int idFileCloseProject                  = XRCID("idFileCloseProject");
169 int idFilePrintSetup                    = XRCID("idFilePrintSetup");
170 int idFilePrint                         = XRCID("idFilePrint");
171 int idFileExit                          = XRCID("idFileExit");
172 
173 int idEditUndo                    = XRCID("idEditUndo");
174 int idEditRedo                    = XRCID("idEditRedo");
175 int idEditClearHistory            = XRCID("idEditClearHistory");
176 int idEditCopy                    = XRCID("idEditCopy");
177 int idEditCut                     = XRCID("idEditCut");
178 int idEditPaste                   = XRCID("idEditPaste");
179 int idEditSwapHeaderSource        = XRCID("idEditSwapHeaderSource");
180 int idEditGotoMatchingBrace       = XRCID("idEditGotoMatchingBrace");
181 int idEditHighlightMode           = XRCID("idEditHighlightMode");
182 int idEditHighlightModeText       = XRCID("idEditHighlightModeText");
183 int idEditBookmarks               = XRCID("idEditBookmarks");
184 int idEditBookmarksToggle         = XRCID("idEditBookmarksToggle");
185 int idEditBookmarksPrevious       = XRCID("idEditBookmarksPrevious");
186 int idEditBookmarksNext           = XRCID("idEditBookmarksNext");
187 int idEditBookmarksClearAll       = XRCID("idEditBookmarksClearAll");
188 int idEditFolding                 = XRCID("idEditFolding");
189 int idEditFoldAll                 = XRCID("idEditFoldAll");
190 int idEditUnfoldAll               = XRCID("idEditUnfoldAll");
191 int idEditToggleAllFolds          = XRCID("idEditToggleAllFolds");
192 int idEditFoldBlock               = XRCID("idEditFoldBlock");
193 int idEditUnfoldBlock             = XRCID("idEditUnfoldBlock");
194 int idEditToggleFoldBlock         = XRCID("idEditToggleFoldBlock");
195 int idEditEOLMode                 = XRCID("idEditEOLMode");
196 int idEditEOLCRLF                 = XRCID("idEditEOLCRLF");
197 int idEditEOLCR                   = XRCID("idEditEOLCR");
198 int idEditEOLLF                   = XRCID("idEditEOLLF");
199 int idEditEncoding                = XRCID("idEditEncoding");
200 int idEditEncodingDefault         = XRCID("idEditEncodingDefault");
201 int idEditEncodingUseBom          = XRCID("idEditEncodingUseBom");
202 int idEditEncodingAscii           = XRCID("idEditEncodingAscii");
203 int idEditEncodingUtf7            = XRCID("idEditEncodingUtf7");
204 int idEditEncodingUtf8            = XRCID("idEditEncodingUtf8");
205 int idEditEncodingUnicode         = XRCID("idEditEncodingUnicode");
206 int idEditEncodingUtf16           = XRCID("idEditEncodingUtf16");
207 int idEditEncodingUtf32           = XRCID("idEditEncodingUtf32");
208 int idEditEncodingUnicode16BE     = XRCID("idEditEncodingUnicode16BE");
209 int idEditEncodingUnicode16LE     = XRCID("idEditEncodingUnicode16LE");
210 int idEditEncodingUnicode32BE     = XRCID("idEditEncodingUnicode32BE");
211 int idEditEncodingUnicode32LE     = XRCID("idEditEncodingUnicode32LE");
212 int idEditSpecialCommands         = XRCID("idEditSpecialCommands");
213 int idEditSpecialCommandsMovement = XRCID("idEditSpecialCommandsMovement");
214 int idEditParaUp                  = XRCID("idEditParaUp");
215 int idEditParaUpExtend            = XRCID("idEditParaUpExtend");
216 int idEditParaDown                = XRCID("idEditParaDown");
217 int idEditParaDownExtend          = XRCID("idEditParaDownExtend");
218 int idEditWordPartLeft            = XRCID("idEditWordPartLeft");
219 int idEditWordPartLeftExtend      = XRCID("idEditWordPartLeftExtend");
220 int idEditWordPartRight           = XRCID("idEditWordPartRight");
221 int idEditWordPartRightExtend     = XRCID("idEditWordPartRightExtend");
222 int idEditSpecialCommandsZoom     = XRCID("idEditSpecialCommandsZoom");
223 int idEditZoomIn                  = XRCID("idEditZoomIn");
224 int idEditZoomOut                 = XRCID("idEditZoomOut");
225 int idEditZoomReset               = XRCID("idEditZoomReset");
226 int idEditSpecialCommandsLine     = XRCID("idEditSpecialCommandsLine");
227 int idEditLineCut                 = XRCID("idEditLineCut");
228 int idEditLineDelete              = XRCID("idEditLineDelete");
229 int idEditLineDuplicate           = XRCID("idEditLineDuplicate");
230 int idEditLineTranspose           = XRCID("idEditLineTranspose");
231 int idEditLineCopy                = XRCID("idEditLineCopy");
232 int idEditLinePaste               = XRCID("idEditLinePaste");
233 int idEditLineUp                  = XRCID("idEditLineUp");
234 int idEditLineDown                = XRCID("idEditLineDown");
235 int idEditSpecialCommandsCase     = XRCID("idEditSpecialCommandsCase");
236 int idEditUpperCase               = XRCID("idEditUpperCase");
237 int idEditLowerCase               = XRCID("idEditLowerCase");
238 int idEditSpecialCommandsOther    = XRCID("idEditSpecialCommandsOther");
239 int idEditInsertNewLine           = XRCID("idEditInsertNewLine");
240 int idEditGotoLineEnd             = XRCID("idEditGotoLineEnd");
241 int idEditInsertNewLineBelow      = XRCID("idEditInsertNewLineBelow");
242 int idEditInsertNewLineAbove      = XRCID("idEditInsertNewLineAbove");
243 int idEditSelectAll               = XRCID("idEditSelectAll");
244 int idEditSelectNext              = XRCID("idEditSelectNext");
245 int idEditSelectNextSkip          = XRCID("idEditSelectNextSkip");
246 int idEditCommentSelected         = XRCID("idEditCommentSelected");
247 int idEditUncommentSelected       = XRCID("idEditUncommentSelected");
248 int idEditToggleCommentSelected   = XRCID("idEditToggleCommentSelected");
249 int idEditStreamCommentSelected   = XRCID("idEditStreamCommentSelected");
250 int idEditBoxCommentSelected      = XRCID("idEditBoxCommentSelected");
251 int idEditShowCallTip             = XRCID("idEditShowCallTip");
252 int idEditCompleteCode            = wxNewId();
253 
254 int idViewLayoutDelete       = XRCID("idViewLayoutDelete");
255 int idViewLayoutSave         = XRCID("idViewLayoutSave");
256 int idViewToolbars           = XRCID("idViewToolbars");
257 int idViewToolFit            = XRCID("idViewToolFit");
258 int idViewToolOptimize       = XRCID("idViewToolOptimize");
259 int idViewToolMain           = XRCID("idViewToolMain");
260 int idViewToolDebugger       = XRCID("idViewToolDebugger");
261 int idViewManager            = XRCID("idViewManager");
262 int idViewLogManager         = XRCID("idViewLogManager");
263 int idViewStartPage          = XRCID("idViewStartPage");
264 int idViewStatusbar          = XRCID("idViewStatusbar");
265 int idViewScriptConsole      = XRCID("idViewScriptConsole");
266 int idViewHideEditorTabs     = XRCID("idViewHideEditorTabs");
267 int idViewFocusEditor        = XRCID("idViewFocusEditor");
268 int idViewFocusManagement    = XRCID("idViewFocusManagement");
269 int idViewFocusLogsAndOthers = XRCID("idViewFocusLogsAndOthers");
270 int idViewSwitchTabs         = XRCID("idViewSwitchTabs");
271 int idViewFullScreen         = XRCID("idViewFullScreen");
272 
273 int idSearchFind                    = XRCID("idSearchFind");
274 int idSearchFindInFiles             = XRCID("idSearchFindInFiles");
275 int idSearchFindNext                = XRCID("idSearchFindNext");
276 int idSearchFindPrevious            = XRCID("idSearchFindPrevious");
277 int idSearchFindSelectedNext        = XRCID("idSearchFindSelectedNext");
278 int idSearchFindSelectedPrevious    = XRCID("idSearchFindSelectedPrevious");
279 int idSearchReplace                 = XRCID("idSearchReplace");
280 int idSearchReplaceInFiles          = XRCID("idSearchReplaceInFiles");
281 int idSearchGotoLine                = XRCID("idSearchGotoLine");
282 int idSearchGotoNextChanged         = XRCID("idSearchGotoNextChanged");
283 int idSearchGotoPreviousChanged     = XRCID("idSearchGotoPreviousChanged");
284 
285 int idSettingsEnvironment    = XRCID("idSettingsEnvironment");
286 int idSettingsGlobalUserVars = XRCID("idSettingsGlobalUserVars");
287 int idSettingsEditor         = XRCID("idSettingsEditor");
288 int idSettingsCompiler       = XRCID("idSettingsCompiler");
289 int idSettingsDebugger       = XRCID("idSettingsDebugger");
290 int idPluginsManagePlugins   = XRCID("idPluginsManagePlugins");
291 int idSettingsScripting      = XRCID("idSettingsScripting");
292 
293 int idHelpTips    = XRCID("idHelpTips");
294 int idHelpPlugins = XRCID("idHelpPlugins");
295 
296 int idLeftSash              = XRCID("idLeftSash");
297 int idBottomSash            = XRCID("idBottomSash");
298 int idCloseFullScreen       = XRCID("idCloseFullScreen");
299 
300 int idGetGlobalAccels   = XRCID("idGetGlobalAccels");
301 
302 int idFileNext              = wxNewId();
303 int idFilePrev              = wxNewId();
304 int idShiftTab              = wxNewId();
305 int idCtrlAltTab            = wxNewId();
306 int idStartHerePageLink     = wxNewId();
307 int idHighlightButton       = wxNewId();
308 
BEGIN_EVENT_TABLE(MainFrame,wxFrame)309 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
310     EVT_ERASE_BACKGROUND(MainFrame::OnEraseBackground)
311     EVT_SIZE(MainFrame::OnSize)
312     EVT_CLOSE(MainFrame::OnApplicationClose)
313 
314     EVT_UPDATE_UI(idFileOpen,                          MainFrame::OnFileMenuUpdateUI)
315     EVT_UPDATE_UI(idFileOpenRecentFileClearHistory,    MainFrame::OnFileMenuUpdateUI)
316     EVT_UPDATE_UI(idFileOpenRecentProjectClearHistory, MainFrame::OnFileMenuUpdateUI)
317     EVT_UPDATE_UI(idFileSave,                          MainFrame::OnFileMenuUpdateUI)
318     EVT_UPDATE_UI(idFileSaveAs,                        MainFrame::OnFileMenuUpdateUI)
319     EVT_UPDATE_UI(idFileOpenDefWorkspace,              MainFrame::OnFileMenuUpdateUI)
320     EVT_UPDATE_UI(idFileSaveWorkspace,                 MainFrame::OnFileMenuUpdateUI)
321     EVT_UPDATE_UI(idFileSaveWorkspaceAs,               MainFrame::OnFileMenuUpdateUI)
322     EVT_UPDATE_UI(idFileCloseWorkspace,                MainFrame::OnFileMenuUpdateUI)
323     EVT_UPDATE_UI(idFileClose,                         MainFrame::OnFileMenuUpdateUI)
324     EVT_UPDATE_UI(idFileCloseAll,                      MainFrame::OnFileMenuUpdateUI)
325     EVT_UPDATE_UI(idFilePrintSetup,                    MainFrame::OnFileMenuUpdateUI)
326     EVT_UPDATE_UI(idFilePrint,                         MainFrame::OnFileMenuUpdateUI)
327 
328     EVT_UPDATE_UI(idFileReopenProject,          MainFrame::OnFileMenuUpdateUI)
329     EVT_UPDATE_UI(idFileSaveProject,            MainFrame::OnFileMenuUpdateUI)
330     EVT_UPDATE_UI(idFileSaveProjectAs,          MainFrame::OnFileMenuUpdateUI)
331     EVT_UPDATE_UI(idFileSaveProjectTemplate,    MainFrame::OnFileMenuUpdateUI)
332     EVT_UPDATE_UI(idFileSaveAll,                MainFrame::OnFileMenuUpdateUI)
333     EVT_UPDATE_UI(idFileCloseProject,           MainFrame::OnFileMenuUpdateUI)
334 
335     EVT_UPDATE_UI(idEditUndo,                  MainFrame::OnEditMenuUpdateUI)
336     EVT_UPDATE_UI(idEditRedo,                  MainFrame::OnEditMenuUpdateUI)
337     EVT_UPDATE_UI(idEditClearHistory,          MainFrame::OnEditMenuUpdateUI)
338     EVT_UPDATE_UI(idEditCopy,                  MainFrame::OnEditMenuUpdateUI)
339     EVT_UPDATE_UI(idEditCut,                   MainFrame::OnEditMenuUpdateUI)
340     EVT_UPDATE_UI(idEditPaste,                 MainFrame::OnEditMenuUpdateUI)
341     EVT_UPDATE_UI(idEditSwapHeaderSource,      MainFrame::OnEditMenuUpdateUI)
342     EVT_UPDATE_UI(idEditGotoMatchingBrace,     MainFrame::OnEditMenuUpdateUI)
343     EVT_UPDATE_UI(idEditFoldAll,               MainFrame::OnEditMenuUpdateUI)
344     EVT_UPDATE_UI(idEditUnfoldAll,             MainFrame::OnEditMenuUpdateUI)
345     EVT_UPDATE_UI(idEditToggleAllFolds,        MainFrame::OnEditMenuUpdateUI)
346     EVT_UPDATE_UI(idEditFoldBlock,             MainFrame::OnEditMenuUpdateUI)
347     EVT_UPDATE_UI(idEditUnfoldBlock,           MainFrame::OnEditMenuUpdateUI)
348     EVT_UPDATE_UI(idEditToggleFoldBlock,       MainFrame::OnEditMenuUpdateUI)
349     EVT_UPDATE_UI(idEditEOLCRLF,               MainFrame::OnEditMenuUpdateUI)
350     EVT_UPDATE_UI(idEditEOLCR,                 MainFrame::OnEditMenuUpdateUI)
351     EVT_UPDATE_UI(idEditEOLLF,                 MainFrame::OnEditMenuUpdateUI)
352     EVT_UPDATE_UI(idEditEncoding,              MainFrame::OnEditMenuUpdateUI)
353     EVT_UPDATE_UI(idEditSelectAll,             MainFrame::OnEditMenuUpdateUI)
354     EVT_UPDATE_UI(idEditSelectNext,            MainFrame::OnEditMenuUpdateUI)
355     EVT_UPDATE_UI(idEditSelectNextSkip,        MainFrame::OnEditMenuUpdateUI)
356     EVT_UPDATE_UI(idEditBookmarksToggle,       MainFrame::OnEditMenuUpdateUI)
357     EVT_UPDATE_UI(idEditBookmarksNext,         MainFrame::OnEditMenuUpdateUI)
358     EVT_UPDATE_UI(idEditBookmarksPrevious,     MainFrame::OnEditMenuUpdateUI)
359     EVT_UPDATE_UI(idEditBookmarksClearAll,     MainFrame::OnEditMenuUpdateUI)
360     EVT_UPDATE_UI(idEditCommentSelected,       MainFrame::OnEditMenuUpdateUI)
361     EVT_UPDATE_UI(idEditUncommentSelected,     MainFrame::OnEditMenuUpdateUI)
362     EVT_UPDATE_UI(idEditToggleCommentSelected, MainFrame::OnEditMenuUpdateUI)
363     EVT_UPDATE_UI(idEditStreamCommentSelected, MainFrame::OnEditMenuUpdateUI)
364     EVT_UPDATE_UI(idEditBoxCommentSelected,    MainFrame::OnEditMenuUpdateUI)
365     EVT_UPDATE_UI(idEditShowCallTip,           MainFrame::OnEditMenuUpdateUI)
366     EVT_UPDATE_UI(idEditCompleteCode,          MainFrame::OnEditMenuUpdateUI)
367 
368     EVT_UPDATE_UI(idSearchFind,                 MainFrame::OnSearchMenuUpdateUI)
369     EVT_UPDATE_UI(idSearchFindInFiles,          MainFrame::OnSearchMenuUpdateUI)
370     EVT_UPDATE_UI(idSearchFindNext,             MainFrame::OnSearchMenuUpdateUI)
371     EVT_UPDATE_UI(idSearchFindPrevious,         MainFrame::OnSearchMenuUpdateUI)
372     EVT_UPDATE_UI(idSearchFindSelectedNext,     MainFrame::OnSearchMenuUpdateUI)
373     EVT_UPDATE_UI(idSearchFindSelectedPrevious, MainFrame::OnSearchMenuUpdateUI)
374     EVT_UPDATE_UI(idSearchReplace,              MainFrame::OnSearchMenuUpdateUI)
375     EVT_UPDATE_UI(idSearchReplaceInFiles,       MainFrame::OnSearchMenuUpdateUI)
376     EVT_UPDATE_UI(idSearchGotoLine,             MainFrame::OnSearchMenuUpdateUI)
377     EVT_UPDATE_UI(idSearchGotoNextChanged,      MainFrame::OnSearchMenuUpdateUI)
378     EVT_UPDATE_UI(idSearchGotoPreviousChanged,  MainFrame::OnSearchMenuUpdateUI)
379 
380     EVT_UPDATE_UI(idViewToolMain,           MainFrame::OnViewMenuUpdateUI)
381     EVT_UPDATE_UI(idViewLogManager,         MainFrame::OnViewMenuUpdateUI)
382     EVT_UPDATE_UI(idViewStartPage,          MainFrame::OnViewMenuUpdateUI)
383     EVT_UPDATE_UI(idViewManager,            MainFrame::OnViewMenuUpdateUI)
384     EVT_UPDATE_UI(idViewStatusbar,          MainFrame::OnViewMenuUpdateUI)
385     EVT_UPDATE_UI(idViewScriptConsole,      MainFrame::OnViewMenuUpdateUI)
386     EVT_UPDATE_UI(idViewHideEditorTabs,     MainFrame::OnViewMenuUpdateUI)
387     EVT_UPDATE_UI(idViewFocusEditor,        MainFrame::OnViewMenuUpdateUI)
388     EVT_UPDATE_UI(idViewFocusManagement,    MainFrame::OnViewMenuUpdateUI)
389     EVT_UPDATE_UI(idViewFocusLogsAndOthers, MainFrame::OnViewMenuUpdateUI)
390     EVT_UPDATE_UI(idViewFullScreen,         MainFrame::OnViewMenuUpdateUI)
391 
392     EVT_MENU(idFileNewEmpty,   MainFrame::OnFileNewWhat)
393     EVT_MENU(idFileNewProject, MainFrame::OnFileNewWhat)
394     EVT_MENU(idFileNewTarget,  MainFrame::OnFileNewWhat)
395     EVT_MENU(idFileNewFile,    MainFrame::OnFileNewWhat)
396     EVT_MENU(idFileNewCustom,  MainFrame::OnFileNewWhat)
397     EVT_MENU(idFileNewUser,    MainFrame::OnFileNewWhat)
398 
399     EVT_MENU(idToolNew,                           MainFrame::OnFileNew)
400     EVT_MENU(idFileOpen,                          MainFrame::OnFileOpen)
401     EVT_MENU(idFileOpenRecentProjectClearHistory, MainFrame::OnFileOpenRecentProjectClearHistory)
402     EVT_MENU(idFileOpenRecentFileClearHistory,    MainFrame::OnFileOpenRecentClearHistory)
403     EVT_MENU_RANGE(wxID_CBFILE01, wxID_CBFILE16,  MainFrame::OnFileReopen)
404     EVT_MENU_RANGE(wxID_CBFILE17, wxID_CBFILE32,  MainFrame::OnFileReopenProject)
405     EVT_MENU(idFileImportProjectDevCpp,           MainFrame::OnFileImportProjectDevCpp)
406     EVT_MENU(idFileImportProjectMSVC,             MainFrame::OnFileImportProjectMSVC)
407     EVT_MENU(idFileImportProjectMSVCWksp,         MainFrame::OnFileImportProjectMSVCWksp)
408     EVT_MENU(idFileImportProjectMSVS,             MainFrame::OnFileImportProjectMSVS)
409     EVT_MENU(idFileImportProjectMSVSWksp,         MainFrame::OnFileImportProjectMSVSWksp)
410     EVT_MENU(idFileSave,                          MainFrame::OnFileSave)
411     EVT_MENU(idFileSaveAs,                        MainFrame::OnFileSaveAs)
412     EVT_MENU(idFileSaveProject,                   MainFrame::OnFileSaveProject)
413     EVT_MENU(idFileSaveProjectAs,                 MainFrame::OnFileSaveProjectAs)
414     EVT_MENU(idFileSaveProjectTemplate,           MainFrame::OnFileSaveProjectTemplate)
415     EVT_MENU(idFileOpenDefWorkspace,              MainFrame::OnFileOpenDefWorkspace)
416     EVT_MENU(idFileSaveWorkspace,                 MainFrame::OnFileSaveWorkspace)
417     EVT_MENU(idFileSaveWorkspaceAs,               MainFrame::OnFileSaveWorkspaceAs)
418     EVT_MENU(idFileSaveAll,                       MainFrame::OnFileSaveAll)
419     EVT_MENU(idFileCloseWorkspace,                MainFrame::OnFileCloseWorkspace)
420     EVT_MENU(idFileClose,                         MainFrame::OnFileClose)
421     EVT_MENU(idFileCloseAll,                      MainFrame::OnFileCloseAll)
422     EVT_MENU(idFileCloseProject,                  MainFrame::OnFileCloseProject)
423     EVT_MENU(idFilePrint,                         MainFrame::OnFilePrint)
424     EVT_MENU(idFileExit,                          MainFrame::OnFileQuit)
425     EVT_MENU(idFileNext,                          MainFrame::OnFileNext)
426     EVT_MENU(idFilePrev,                          MainFrame::OnFilePrev)
427 
428     EVT_MENU(idEditUndo,                  MainFrame::OnEditUndo)
429     EVT_MENU(idEditRedo,                  MainFrame::OnEditRedo)
430     EVT_MENU(idEditClearHistory,          MainFrame::OnEditClearHistory)
431     EVT_MENU(idEditCopy,                  MainFrame::OnEditCopy)
432     EVT_MENU(idEditCut,                   MainFrame::OnEditCut)
433     EVT_MENU(idEditPaste,                 MainFrame::OnEditPaste)
434     EVT_MENU(idEditSwapHeaderSource,      MainFrame::OnEditSwapHeaderSource)
435     EVT_MENU(idEditGotoMatchingBrace,     MainFrame::OnEditGotoMatchingBrace)
436     EVT_MENU(idEditHighlightModeText,     MainFrame::OnEditHighlightMode)
437     EVT_MENU(idEditFoldAll,               MainFrame::OnEditFoldAll)
438     EVT_MENU(idEditUnfoldAll,             MainFrame::OnEditUnfoldAll)
439     EVT_MENU(idEditToggleAllFolds,        MainFrame::OnEditToggleAllFolds)
440     EVT_MENU(idEditFoldBlock,             MainFrame::OnEditFoldBlock)
441     EVT_MENU(idEditUnfoldBlock,           MainFrame::OnEditUnfoldBlock)
442     EVT_MENU(idEditToggleFoldBlock,       MainFrame::OnEditToggleFoldBlock)
443     EVT_MENU(idEditEOLCRLF,               MainFrame::OnEditEOLMode)
444     EVT_MENU(idEditEOLCR,                 MainFrame::OnEditEOLMode)
445     EVT_MENU(idEditEOLLF,                 MainFrame::OnEditEOLMode)
446     EVT_MENU(idEditEncodingDefault,       MainFrame::OnEditEncoding)
447     EVT_MENU(idEditEncodingUseBom,        MainFrame::OnEditEncoding)
448     EVT_MENU(idEditEncodingAscii,         MainFrame::OnEditEncoding)
449     EVT_MENU(idEditEncodingUtf7,          MainFrame::OnEditEncoding)
450     EVT_MENU(idEditEncodingUtf8,          MainFrame::OnEditEncoding)
451     EVT_MENU(idEditEncodingUnicode,       MainFrame::OnEditEncoding)
452     EVT_MENU(idEditEncodingUtf16,         MainFrame::OnEditEncoding)
453     EVT_MENU(idEditEncodingUtf32,         MainFrame::OnEditEncoding)
454     EVT_MENU(idEditEncodingUnicode16BE,   MainFrame::OnEditEncoding)
455     EVT_MENU(idEditEncodingUnicode16LE,   MainFrame::OnEditEncoding)
456     EVT_MENU(idEditEncodingUnicode32BE,   MainFrame::OnEditEncoding)
457     EVT_MENU(idEditEncodingUnicode32LE,   MainFrame::OnEditEncoding)
458     EVT_MENU(idEditParaUp,                MainFrame::OnEditParaUp)
459     EVT_MENU(idEditParaUpExtend,          MainFrame::OnEditParaUpExtend)
460     EVT_MENU(idEditParaDown,              MainFrame::OnEditParaDown)
461     EVT_MENU(idEditParaDownExtend,        MainFrame::OnEditParaDownExtend)
462     EVT_MENU(idEditWordPartLeft,          MainFrame::OnEditWordPartLeft)
463     EVT_MENU(idEditWordPartLeftExtend,    MainFrame::OnEditWordPartLeftExtend)
464     EVT_MENU(idEditWordPartRight,         MainFrame::OnEditWordPartRight)
465     EVT_MENU(idEditWordPartRightExtend,   MainFrame::OnEditWordPartRightExtend)
466     EVT_MENU(idEditZoomIn,                MainFrame::OnEditZoomIn)
467     EVT_MENU(idEditZoomOut,               MainFrame::OnEditZoomOut)
468     EVT_MENU(idEditZoomReset,             MainFrame::OnEditZoomReset)
469     EVT_MENU(idEditLineCut,               MainFrame::OnEditLineCut)
470     EVT_MENU(idEditLineDelete,            MainFrame::OnEditLineDelete)
471     EVT_MENU(idEditLineDuplicate,         MainFrame::OnEditLineDuplicate)
472     EVT_MENU(idEditLineTranspose,         MainFrame::OnEditLineTranspose)
473     EVT_MENU(idEditLineCopy,              MainFrame::OnEditLineCopy)
474     EVT_MENU(idEditLinePaste,             MainFrame::OnEditLinePaste)
475     EVT_MENU(idEditLineUp,                MainFrame::OnEditLineMove)
476     EVT_MENU(idEditLineDown,              MainFrame::OnEditLineMove)
477     EVT_MENU(idEditUpperCase,             MainFrame::OnEditUpperCase)
478     EVT_MENU(idEditLowerCase,             MainFrame::OnEditLowerCase)
479     EVT_MENU(idEditInsertNewLine,         MainFrame::OnEditInsertNewLine)
480     EVT_MENU(idEditGotoLineEnd,           MainFrame::OnEditGotoLineEnd)
481     EVT_MENU(idEditInsertNewLineBelow,    MainFrame::OnEditInsertNewLineBelow)
482     EVT_MENU(idEditInsertNewLineAbove,    MainFrame::OnEditInsertNewLineAbove)
483     EVT_MENU(idEditSelectAll,             MainFrame::OnEditSelectAll)
484     EVT_MENU(idEditSelectNext,            MainFrame::OnEditSelectNext)
485     EVT_MENU(idEditSelectNextSkip,        MainFrame::OnEditSelectNextSkip)
486     EVT_MENU(idEditBookmarksToggle,       MainFrame::OnEditBookmarksToggle)
487     EVT_MENU(idEditBookmarksNext,         MainFrame::OnEditBookmarksNext)
488     EVT_MENU(idEditBookmarksPrevious,     MainFrame::OnEditBookmarksPrevious)
489     EVT_MENU(idEditBookmarksClearAll,     MainFrame::OnEditBookmarksClearAll)
490     EVT_MENU(idEditCommentSelected,       MainFrame::OnEditCommentSelected)
491     EVT_MENU(idEditUncommentSelected,     MainFrame::OnEditUncommentSelected)
492     EVT_MENU(idEditToggleCommentSelected, MainFrame::OnEditToggleCommentSelected)
493     EVT_MENU(idEditStreamCommentSelected, MainFrame::OnEditStreamCommentSelected)
494     EVT_MENU(idEditBoxCommentSelected,    MainFrame::OnEditBoxCommentSelected)
495     EVT_MENU(idEditShowCallTip,           MainFrame::OnEditShowCallTip)
496     EVT_MENU(idEditCompleteCode,          MainFrame::OnEditCompleteCode)
497 
498     EVT_MENU(idSearchFind,                  MainFrame::OnSearchFind)
499     EVT_MENU(idSearchFindInFiles,           MainFrame::OnSearchFind)
500     EVT_MENU(idSearchFindNext,              MainFrame::OnSearchFindNext)
501     EVT_MENU(idSearchFindPrevious,          MainFrame::OnSearchFindNext)
502     EVT_MENU(idSearchFindSelectedNext,      MainFrame::OnSearchFindNextSelected)
503     EVT_MENU(idSearchFindSelectedPrevious,  MainFrame::OnSearchFindNextSelected)
504     EVT_MENU(idSearchReplace,               MainFrame::OnSearchReplace)
505     EVT_MENU(idSearchReplaceInFiles,        MainFrame::OnSearchReplace)
506     EVT_MENU(idSearchGotoLine,              MainFrame::OnSearchGotoLine)
507     EVT_MENU(idSearchGotoNextChanged,       MainFrame::OnSearchGotoNextChanged)
508     EVT_MENU(idSearchGotoPreviousChanged,   MainFrame::OnSearchGotoPrevChanged)
509 
510     EVT_MENU(idViewLayoutSave,            MainFrame::OnViewLayoutSave)
511     EVT_MENU(idViewLayoutDelete,          MainFrame::OnViewLayoutDelete)
512     EVT_MENU(idViewToolFit,               MainFrame::OnViewToolbarsFit)
513     EVT_MENU(idViewToolOptimize,          MainFrame::OnViewToolbarsOptimize)
514     EVT_MENU(idViewToolMain,              MainFrame::OnToggleBar)
515     EVT_MENU(idViewToolDebugger,          MainFrame::OnToggleBar)
516     EVT_MENU(idViewLogManager,            MainFrame::OnToggleBar)
517     EVT_MENU(idViewManager,               MainFrame::OnToggleBar)
518     EVT_MENU(idViewStatusbar,             MainFrame::OnToggleStatusBar)
519     EVT_MENU(idViewScriptConsole,         MainFrame::OnViewScriptConsole)
520     EVT_MENU(idViewHideEditorTabs,        MainFrame::OnViewHideEditorTabs)
521     EVT_MENU(idViewFocusEditor,           MainFrame::OnFocusEditor)
522     EVT_MENU(idViewFocusManagement,       MainFrame::OnFocusManagement)
523     EVT_MENU(idViewFocusLogsAndOthers,    MainFrame::OnFocusLogsAndOthers)
524     EVT_MENU(idViewSwitchTabs,            MainFrame::OnSwitchTabs)
525     EVT_MENU(idViewFullScreen,            MainFrame::OnToggleFullScreen)
526     EVT_MENU(idViewStartPage,             MainFrame::OnToggleStartPage)
527 
528     EVT_MENU(idSettingsEnvironment,    MainFrame::OnSettingsEnvironment)
529     EVT_MENU(idSettingsGlobalUserVars, MainFrame::OnGlobalUserVars)
530     EVT_MENU(idSettingsEditor,         MainFrame::OnSettingsEditor)
531     EVT_MENU(idSettingsCompiler,       MainFrame::OnSettingsCompiler)
532     EVT_MENU(idSettingsDebugger,       MainFrame::OnSettingsDebugger)
533     EVT_MENU(idPluginsManagePlugins,   MainFrame::OnSettingsPlugins)
534     EVT_MENU(idSettingsScripting,      MainFrame::OnSettingsScripting)
535 
536     EVT_MENU(wxID_ABOUT, MainFrame::OnHelpAbout)
537     EVT_MENU(idHelpTips, MainFrame::OnHelpTips)
538 
539     EVT_MENU(idStartHerePageLink,     MainFrame::OnStartHereLink)
540 
541     EVT_CBAUIBOOK_LEFT_DCLICK(ID_NBEditorManager, MainFrame::OnNotebookDoubleClick)
542     EVT_NOTEBOOK_PAGE_CHANGED(ID_NBEditorManager, MainFrame::OnPageChanged)
543 
544     // Highlightbutton
545     EVT_BUTTON(idHighlightButton, MainFrame::OnHighlightMenu)
546     /// CloseFullScreen event handling
547     EVT_BUTTON(idCloseFullScreen, MainFrame::OnToggleFullScreen)
548 
549     /// Shift-Tab bug workaround
550     EVT_MENU(idShiftTab,   MainFrame::OnShiftTab)
551     EVT_MENU(idCtrlAltTab, MainFrame::OnCtrlAltTab)
552 
553     // Let plugins get copy of global accelerators
554     EVT_MENU(idGetGlobalAccels,       MainFrame::OnGetGlobalAccels)
555 
556     /// Used for mouse right click in the free area of MainFrame
557     EVT_RIGHT_UP(MainFrame::OnMouseRightUp)
558 
559 END_EVENT_TABLE()
560 
561 MainFrame::MainFrame(wxWindow* parent)
562        : wxFrame(parent, -1, _T("MainWin"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE),
563        m_LayoutManager(this),
564        m_pAccel(nullptr),
565        m_filesHistory(_("&File"), wxT("/recent_files"), idFileOpenRecentFileClearHistory, wxID_CBFILE01),
566        m_projectsHistory(_("&File"), wxT("/recent_projects"), idFileOpenRecentProjectClearHistory, wxID_CBFILE17),
567        m_pCloseFullScreenBtn(nullptr),
568        m_pEdMan(nullptr),
569        m_pPrjMan(nullptr),
570        m_pPrjManUI(nullptr),
571        m_pLogMan(nullptr),
572        m_pInfoPane(nullptr),
573        m_pToolbar(nullptr),
574        m_ToolsMenu(nullptr),
575        m_HelpPluginsMenu(nullptr),
576        m_ScanningForPlugins(false),
577        m_StartupDone(false), // one-time flag
578        m_InitiatedShutdown(false),
579        m_AutoHideLockCounter(0),
580        m_LastCtrlAltTabWindow(0),
581        m_LastLayoutIsTemp(false),
582        m_pScriptConsole(nullptr),
583        m_pBatchBuildDialog(nullptr),
584        // Highlightbutton
585        m_pHighlightButton(nullptr)
586 {
587     Manager::Get(this); // provide manager with handle to MainFrame (this)
588 
589     // register event sinks
590     RegisterEvents();
591 
592     // New: Allow drag and drop of files into the editor
593     SetDropTarget(new cbFileDropTarget(this));
594 
595     // Accelerator table
596     m_AccelCount = 8;
597     m_pAccelEntries.reset(new wxAcceleratorEntry[m_AccelCount]);
598     m_pAccelEntries[0].Set(wxACCEL_CTRL | wxACCEL_SHIFT,  (int) 'W', idFileCloseAll);
599     m_pAccelEntries[1].Set(wxACCEL_CTRL | wxACCEL_SHIFT,  WXK_F4,    idFileCloseAll);
600     m_pAccelEntries[2].Set(wxACCEL_CTRL,                  (int) 'W', idFileClose);
601     m_pAccelEntries[3].Set(wxACCEL_CTRL,                  WXK_F4,    idFileClose);
602     m_pAccelEntries[4].Set(wxACCEL_CTRL,                  WXK_F6,    idFileNext);
603     m_pAccelEntries[5].Set(wxACCEL_CTRL | wxACCEL_SHIFT,  WXK_F6,    idFilePrev);
604     m_pAccelEntries[6].Set(wxACCEL_SHIFT,                 WXK_TAB,   idShiftTab);
605     m_pAccelEntries[7].Set(wxACCEL_CTRL | wxACCEL_ALT,    WXK_TAB,   idCtrlAltTab);
606     m_pAccel.reset(new wxAcceleratorTable(m_AccelCount, m_pAccelEntries.get()));
607 
608     SetAcceleratorTable(*m_pAccel);
609 
610     // add file filters for supported projects/workspaces
611     FileFilters::AddDefaultFileFilters();
612 
613     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
614     CreateIDE();
615 
616 #ifdef __WXMSW__
617     SetIcon(wxICON(A_MAIN_ICON));
618 #else
619     SetIcon(wxIcon(app_xpm));
620 #endif // __WXMSW__
621 
622     // even it is possible that the statusbar is not visible at the moment, create the statusbar so the plugins can create their own fields on the it:
623     DoCreateStatusBar();
624     SetStatusText(_("Welcome to ")+ appglobals::AppName + _T("!"));
625 
626     wxStatusBar *sb = GetStatusBar();
627     if (sb)
628         sb->Show(cfg->ReadBool(_T("/main_frame/statusbar"), true));
629 
630     SetTitle(appglobals::AppName + _T(" v") + appglobals::AppVersion);
631 
632     LoadWindowSize();
633     ScanForPlugins();
634     CreateToolbars();
635 
636     Manager::Get()->GetCCManager();
637 
638     // save default view
639     wxString deflayout = cfg->Read(_T("/main_frame/layout/default"));
640     if (deflayout.IsEmpty())
641         cfg->Write(_T("/main_frame/layout/default"), gDefaultLayout);
642     gDefaultLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
643     gDefaultMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
644     SaveViewLayout(gDefaultLayout, gDefaultLayoutData, gDefaultMessagePaneLayoutData);
645 
646     // generate default minimal layout
647     wxAuiPaneInfoArray& panes = m_LayoutManager.GetAllPanes();
648     for (size_t i = 0; i < panes.GetCount(); ++i)
649     {
650         wxAuiPaneInfo& info = panes[i];
651         if (!(info.name == _T("MainPane")))
652             info.Hide();
653     }
654     gMinimalLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
655     gMinimalMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
656     SaveViewLayout(gMinimalLayout, gMinimalLayoutData, gMinimalMessagePaneLayoutData);
657 
658     LoadWindowState();
659 
660     ShowHideStartPage();
661 
662     RegisterScriptFunctions();
663     RunStartupScripts();
664 
665     Manager::Get()->GetLogManager()->DebugLog(_T("Initializing plugins..."));
666 }
667 
~MainFrame()668 MainFrame::~MainFrame()
669 {
670     SetAcceleratorTable(wxNullAcceleratorTable);
671 
672     DeInitPrinting();
673 
674     delete m_debuggerMenuHandler;
675     delete m_debuggerToolbarHandler;
676 }
677 
RegisterEvents()678 void MainFrame::RegisterEvents()
679 {
680     Manager* m = Manager::Get();
681 
682     m->RegisterEventSink(cbEVT_EDITOR_UPDATE_UI,       new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorUpdateUI));
683 
684     m->RegisterEventSink(cbEVT_PROJECT_ACTIVATE,       new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectActivated));
685     m->RegisterEventSink(cbEVT_PROJECT_OPEN,           new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectOpened));
686     m->RegisterEventSink(cbEVT_PROJECT_CLOSE,          new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectClosed));
687     m->RegisterEventSink(cbEVT_EDITOR_CLOSE,           new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorClosed));
688     m->RegisterEventSink(cbEVT_EDITOR_OPEN,            new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorOpened));
689     m->RegisterEventSink(cbEVT_EDITOR_ACTIVATED,       new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorActivated));
690     m->RegisterEventSink(cbEVT_EDITOR_SAVE,            new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorSaved));
691     m->RegisterEventSink(cbEVT_EDITOR_MODIFIED,        new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorModified));
692 
693     m->RegisterEventSink(cbEVT_ADD_DOCK_WINDOW,        new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestDockWindow));
694     m->RegisterEventSink(cbEVT_REMOVE_DOCK_WINDOW,     new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestUndockWindow));
695     m->RegisterEventSink(cbEVT_SHOW_DOCK_WINDOW,       new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestShowDockWindow));
696     m->RegisterEventSink(cbEVT_HIDE_DOCK_WINDOW,       new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestHideDockWindow));
697     m->RegisterEventSink(cbEVT_DOCK_WINDOW_VISIBILITY, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnDockWindowVisibility));
698 
699     m->RegisterEventSink(cbEVT_PLUGIN_ATTACHED,        new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginLoaded));
700     m->RegisterEventSink(cbEVT_PLUGIN_RELEASED,        new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginUnloaded));
701     m->RegisterEventSink(cbEVT_PLUGIN_INSTALLED,       new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginInstalled));
702     m->RegisterEventSink(cbEVT_PLUGIN_UNINSTALLED,     new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginUninstalled));
703 
704     m->RegisterEventSink(cbEVT_UPDATE_VIEW_LAYOUT,     new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutUpdate));
705     m->RegisterEventSink(cbEVT_QUERY_VIEW_LAYOUT,      new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutQuery));
706     m->RegisterEventSink(cbEVT_SWITCH_VIEW_LAYOUT,     new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutSwitch));
707 
708     m->RegisterEventSink(cbEVT_ADD_LOG_WINDOW,         new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnAddLogWindow));
709     m->RegisterEventSink(cbEVT_REMOVE_LOG_WINDOW,      new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnRemoveLogWindow));
710     m->RegisterEventSink(cbEVT_HIDE_LOG_WINDOW,        new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnHideLogWindow));
711     m->RegisterEventSink(cbEVT_SWITCH_TO_LOG_WINDOW,   new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnSwitchToLogWindow));
712     m->RegisterEventSink(cbEVT_GET_ACTIVE_LOG_WINDOW,  new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnGetActiveLogWindow));
713     m->RegisterEventSink(cbEVT_SHOW_LOG_MANAGER,       new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnShowLogManager));
714     m->RegisterEventSink(cbEVT_HIDE_LOG_MANAGER,       new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnHideLogManager));
715     m->RegisterEventSink(cbEVT_LOCK_LOG_MANAGER,       new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnLockLogManager));
716     m->RegisterEventSink(cbEVT_UNLOCK_LOG_MANAGER,     new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnUnlockLogManager));
717 }
718 
ShowTips(bool forceShow)719 void MainFrame::ShowTips(bool forceShow)
720 {
721     bool showAtStartup = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/show_tips"), false);
722     if (forceShow || showAtStartup)
723     {
724         wxString tipsFile = ConfigManager::GetDataFolder() + _T("/tips.txt");
725         long tipsIndex = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/next_tip"), 0);
726         wxTipProvider* tipProvider = wxCreateFileTipProvider(tipsFile, tipsIndex);
727         showAtStartup = wxShowTip(this, tipProvider, showAtStartup);
728         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/show_tips"), showAtStartup);
729         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/next_tip"), (int)tipProvider->GetCurrentTip());
730         delete tipProvider;
731     }
732 }
733 
CreateIDE()734 void MainFrame::CreateIDE()
735 {
736     int leftW = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_width"), 200);
737     wxSize clientsize = GetClientSize();
738 
739     // Create CloseFullScreen Button, and hide it initially
740     m_pCloseFullScreenBtn = new wxButton(this, idCloseFullScreen, _( "Close full screen" ), wxDefaultPosition );
741     m_pCloseFullScreenBtn->Show( false );
742 
743     // management panel
744     m_pPrjMan = Manager::Get()->GetProjectManager();
745     if (!Manager::IsBatchBuild())
746     {
747         m_pPrjManUI = new ProjectManagerUI;
748         m_LayoutManager.AddPane( m_pPrjManUI->GetNotebook(),
749                                  wxAuiPaneInfo().Name(wxT("ManagementPane")).Caption(_("Management")).
750                                      BestSize(wxSize(leftW, clientsize.GetHeight())).
751                                      MinSize(wxSize(100,100)).Left().Layer(1) );
752     }
753     else
754         m_pPrjManUI = new BatchProjectManagerUI;
755     m_pPrjMan->SetUI(m_pPrjManUI);
756 
757     const double actualScaleFactor = cbGetActualContentScaleFactor(*this);
758     const int targetHeight = floor(16 * actualScaleFactor);
759     const int uiSize16 = cbFindMinSize16to64(targetHeight);
760 
761     // All message posted before this call are either lost or sent to stdout/stderr.
762     // On windows stdout and stderr aren't accessible.
763     SetupGUILogging(uiSize16);
764 
765     {
766         wxString msg = wxString::Format(wxT("Loaded config file '%s'"),
767                                         CfgMgrBldr::Get()->GetConfigFile().wx_str());
768         Manager::Get()->GetLogManager()->Log(msg);
769     }
770 
771     SetupDebuggerUI();
772 
773     {
774         // Setup the art provider with the images stored in manager_resources.zip
775         const wxString prefix = ConfigManager::GetDataFolder()
776                               + wxT("/manager_resources.zip#zip:/images");
777         cbArtProvider *provider = new cbArtProvider(prefix);
778 
779         provider->AddMapping(wxT("sdk/select_target"), wxT("select_target.png"));
780         provider->AddMapping(wxT("sdk/missing_icon"), wxT("missing_icon.png"));
781 
782         wxArtProvider::Push(provider);
783     }
784 
785     {
786         // Setup the art provider for the main menu. Use scaling factor detection to determine the
787         // size of the images. Also do this here when we have a main window (probably this doesn't
788         // help us much, because the window hasn't been shown yet).
789 
790         Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::Menus);
791         Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
792                                          Manager::UIComponent::Menus);
793 
794         Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::Main);
795         Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
796                                          Manager::UIComponent::Main);
797 
798         const wxString prefix = ConfigManager::GetDataFolder() + wxT("/resources.zip#zip:/images");
799         cbArtProvider *provider = new cbArtProvider(prefix);
800 
801         provider->AddMapping(wxT("core/file_open"), wxT("fileopen.png"));
802         provider->AddMapping(wxT("core/file_new"), wxT("filenew.png"));
803         provider->AddMapping(wxT("core/history_clear"), wxT("history_clear.png"));
804         provider->AddMapping(wxT("core/file_save"), wxT("filesave.png"));
805         provider->AddMapping(wxT("core/file_save_as"), wxT("filesaveas.png"));
806         provider->AddMapping(wxT("core/file_save_all"), wxT("filesaveall.png"));
807         provider->AddMapping(wxT("core/file_close"), wxT("fileclose.png"));
808         provider->AddMapping(wxT("core/file_print"), wxT("fileprint.png"));
809         provider->AddMapping(wxT("core/exit"), wxT("exit.png"));
810         provider->AddMapping(wxT("core/undo"), wxT("undo.png"));
811         provider->AddMapping(wxT("core/redo"), wxT("redo.png"));
812         provider->AddMapping(wxT("core/edit_cut"), wxT("editcut.png"));
813         provider->AddMapping(wxT("core/edit_copy"), wxT("editcopy.png"));
814         provider->AddMapping(wxT("core/edit_paste"), wxT("editpaste.png"));
815         provider->AddMapping(wxT("core/bookmark_add"), wxT("bookmark_add.png"));
816         provider->AddMapping(wxT("core/find"), wxT("filefind.png"));
817         provider->AddMapping(wxT("core/find_in_files"), wxT("findf.png"));
818         provider->AddMapping(wxT("core/find_next"), wxT("filefindnext.png"));
819         provider->AddMapping(wxT("core/find_prev"), wxT("filefindprev.png"));
820         provider->AddMapping(wxT("core/search_replace"), wxT("searchreplace.png"));
821         provider->AddMapping(wxT("core/search_replace_in_files"), wxT("searchreplacef.png"));
822         provider->AddMapping(wxT("core/goto"), wxT("goto.png"));
823         provider->AddMapping(wxT("core/manage_plugins"), wxT("plug.png"));
824         provider->AddMapping(wxT("core/help_info"), wxT("info.png"));
825         provider->AddMapping(wxT("core/help_idea"), wxT("idea.png"));
826 
827         provider->AddMapping(wxT("core/dbg/run"), wxT("dbgrun.png"));
828         provider->AddMapping(wxT("core/dbg/pause"), wxT("dbgpause.png"));
829         provider->AddMapping(wxT("core/dbg/stop"), wxT("dbgstop.png"));
830         provider->AddMapping(wxT("core/dbg/run_to"), wxT("dbgrunto.png"));
831         provider->AddMapping(wxT("core/dbg/next"), wxT("dbgnext.png"));
832         provider->AddMapping(wxT("core/dbg/step"), wxT("dbgstep.png"));
833         provider->AddMapping(wxT("core/dbg/step_out"), wxT("dbgstepout.png"));
834         provider->AddMapping(wxT("core/dbg/next_inst"), wxT("dbgnexti.png"));
835         provider->AddMapping(wxT("core/dbg/step_inst"), wxT("dbgstepi.png"));
836         provider->AddMapping(wxT("core/dbg/window"), wxT("dbgwindow.png"));
837         provider->AddMapping(wxT("core/dbg/info"), wxT("dbginfo.png"));
838 
839         provider->AddMappingF(wxT("core/folder_open"), wxT("tree/%dx%d/folder_open.png"));
840         provider->AddMappingF(wxT("core/gear"), wxT("infopane/%dx%d/misc.png"));
841 
842         wxArtProvider::Push(provider);
843     }
844 
845     {
846         // Setup toolbar sizes
847         const int configSize = cbHelpers::ReadToolbarSizeFromConfig();
848         const int scaledSize = cbFindMinSize16to64(configSize * actualScaleFactor);
849         Manager::Get()->SetImageSize(scaledSize, Manager::UIComponent::Toolbars);
850         Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
851                                          Manager::UIComponent::Toolbars);
852     }
853 
854     CreateMenubar();
855 
856     m_pEdMan  = Manager::Get()->GetEditorManager();
857     m_pLogMan = Manager::Get()->GetLogManager();
858 
859     // editor manager
860     m_LayoutManager.AddPane(m_pEdMan->GetNotebook(), wxAuiPaneInfo().Name(wxT("MainPane")).
861                             CentrePane());
862 
863     // script console
864     m_pScriptConsole = new ScriptConsole(this, -1);
865     m_LayoutManager.AddPane(m_pScriptConsole, wxAuiPaneInfo().Name(wxT("ScriptConsole")).
866                             Caption(_("Scripting console")).Float().MinSize(100,100).FloatingPosition(300, 200).Hide());
867 
868     DoUpdateLayout();
869     DoUpdateLayoutColours();
870     DoUpdateEditorStyle();
871 
872     m_pEdMan->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
873     if (m_pPrjManUI->GetNotebook())
874         m_pPrjManUI->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
875 
876     Manager::Get()->GetColourManager()->Load();
877 }
878 
879 
SetupGUILogging(int uiSize16)880 void MainFrame::SetupGUILogging(int uiSize16)
881 {
882     // allow new docked windows to use be 3/4 of the available space, the default (0.3) is sometimes too small, especially for "Logs & others"
883     m_LayoutManager.SetDockSizeConstraint(0.75,0.75);
884 
885     int bottomH = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_height"), 150);
886     wxSize clientsize = GetClientSize();
887 
888     LogManager* mgr = Manager::Get()->GetLogManager();
889     Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::InfoPaneNotebooks);
890     Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
891                                      Manager::UIComponent::InfoPaneNotebooks);
892 
893     if (!Manager::IsBatchBuild())
894     {
895         m_pInfoPane = new InfoPane(this);
896         m_LayoutManager.AddPane(m_pInfoPane, wxAuiPaneInfo().
897                                   Name(wxT("MessagesPane")).Caption(_("Logs & others")).
898                                   BestSize(wxSize(clientsize.GetWidth(), bottomH)).//MinSize(wxSize(50,50)).
899                                   Bottom());
900 
901         wxWindow* log;
902 
903         for (size_t i = LogManager::app_log; i < LogManager::max_logs; ++i)
904         {
905             if ((log = mgr->Slot(i).GetLogger()->CreateControl(m_pInfoPane)))
906                 m_pInfoPane->AddLogger(mgr->Slot(i).GetLogger(), log, mgr->Slot(i).title, mgr->Slot(i).icon);
907         }
908 
909         m_findReplace.CreateSearchLog();
910     }
911     else
912     {
913         m_pBatchBuildDialog = new BatchLogWindow(this, _("Code::Blocks - Batch build"));
914         wxSizer* s = new wxBoxSizer(wxVERTICAL);
915         m_pInfoPane = new InfoPane(m_pBatchBuildDialog);
916         s->Add(m_pInfoPane, 1, wxEXPAND);
917         m_pBatchBuildDialog->SetSizer(s);
918 
919         // setting &g_null_log causes the app to crash on exit for some reason...
920         mgr->SetLog(new NullLogger, LogManager::app_log);
921         mgr->SetLog(new NullLogger, LogManager::debug_log);
922     }
923 
924     mgr->NotifyUpdate();
925     m_pInfoPane->SetDropTarget(new cbFileDropTarget(this));
926 }
927 
SetupDebuggerUI()928 void MainFrame::SetupDebuggerUI()
929 {
930     m_debuggerMenuHandler = new DebuggerMenuHandler;
931     m_debuggerToolbarHandler = new DebuggerToolbarHandler(m_debuggerMenuHandler);
932     m_debuggerMenuHandler->SetEvtHandlerEnabled(false);
933     m_debuggerToolbarHandler->SetEvtHandlerEnabled(false);
934     wxWindow* window = Manager::Get()->GetAppWindow();
935     if (window)
936     {
937         window->PushEventHandler(m_debuggerMenuHandler);
938         window->PushEventHandler(m_debuggerToolbarHandler);
939     }
940     m_debuggerMenuHandler->SetEvtHandlerEnabled(true);
941     m_debuggerToolbarHandler->SetEvtHandlerEnabled(true);
942 
943     if (!Manager::IsBatchBuild())
944     {
945         Manager::Get()->GetDebuggerManager()->SetInterfaceFactory(new DebugInterfaceFactory);
946         m_debuggerMenuHandler->RegisterDefaultWindowItems();
947     }
948 }
949 
950 DECLARE_INSTANCE_TYPE(MainFrame);
951 
RegisterScriptFunctions()952 void MainFrame::RegisterScriptFunctions()
953 {
954     SqPlus::SQClassDef<MainFrame>("MainFrame").
955                     func(&MainFrame::Open, "Open");
956 
957     SqPlus::BindVariable(this, "App", SqPlus::VAR_ACCESS_READ_ONLY);
958 }
959 
RunStartupScripts()960 void MainFrame::RunStartupScripts()
961 {
962     ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("scripting"));
963     wxArrayString keys = mgr->EnumerateKeys(_T("/startup_scripts"));
964 
965     for (size_t i = 0; i < keys.GetCount(); ++i)
966     {
967         ScriptEntry se;
968         wxString ser;
969         if (mgr->Read(_T("/startup_scripts/") + keys[i], &ser))
970         {
971             se.SerializeIn(ser);
972             if (!se.enabled)
973                 continue;
974 
975             try
976             {
977                 wxString startup = se.script;
978                 if (wxFileName(se.script).IsRelative())
979                     startup = ConfigManager::LocateDataFile(se.script, sdScriptsUser | sdScriptsGlobal);
980                 if (!startup.IsEmpty())
981                 {
982                     if (!se.registered)
983                         Manager::Get()->GetScriptingManager()->LoadScript(startup);
984                     else if (!se.menu.IsEmpty())
985                         Manager::Get()->GetScriptingManager()->RegisterScriptMenu(se.menu, startup, false);
986                     else
987                         Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script/function '%s' not loaded: invalid configuration"), se.script.wx_str()));
988                 }
989                 else
990                     Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script '%s' not found"), se.script.wx_str()));
991             }
992             catch (SquirrelError& exception)
993             {
994                 Manager::Get()->GetScriptingManager()->DisplayErrors(&exception);
995             }
996         }
997     }
998 }
999 
PluginsUpdated(cb_unused cbPlugin * plugin,cb_unused int status)1000 void MainFrame::PluginsUpdated(cb_unused cbPlugin* plugin, cb_unused int status)
1001 {
1002     Freeze();
1003 
1004     // menu
1005     RecreateMenuBar();
1006 
1007     // update view->toolbars because we re-created the menubar
1008     PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1009     for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1010     {
1011         cbPlugin* plug = plugins[i]->plugin;
1012         const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plug);
1013         if (!info)
1014             continue;
1015 
1016         if (m_PluginsTools[plug]) // if plugin has a toolbar
1017         {
1018             // toolbar exists; add the menu item
1019             wxMenu* viewToolbars = nullptr;
1020             GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
1021             if (viewToolbars)
1022             {
1023                 if (viewToolbars->FindItem(info->title) != wxNOT_FOUND)
1024                     continue;
1025                 wxMenuItem* item = AddPluginInMenus(viewToolbars, plug,
1026                                                     (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
1027                                                     -1, true);
1028                 if (item)
1029                 {
1030                     item->Check(IsWindowReallyShown(m_PluginsTools[plug]));
1031                 }
1032             }
1033         }
1034     }
1035 
1036     Thaw();
1037 }
1038 
RecreateMenuBar()1039 void MainFrame::RecreateMenuBar()
1040 {
1041     Freeze();
1042 
1043     wxMenuBar* m = GetMenuBar();
1044     SetMenuBar(nullptr); // unhook old menubar
1045     CreateMenubar(); // create new menubar
1046     delete m; // delete old menubar
1047 
1048     // update layouts menu
1049     for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
1050     {
1051         if (it->first.IsEmpty())
1052             continue;
1053         SaveViewLayout(it->first, it->second,
1054                        m_LayoutMessagePane[it->first],
1055                        it->first == m_LastLayoutName);
1056     }
1057 
1058     Thaw();
1059 }
1060 
CreateMenubar()1061 void MainFrame::CreateMenubar()
1062 {
1063     CodeBlocksEvent event(cbEVT_MENUBAR_CREATE_BEGIN);
1064     Manager::Get()->ProcessEvent(event);
1065 
1066     int tmpidx;
1067     wxMenuBar* mbar=nullptr;
1068     wxMenu *tools=nullptr, *plugs=nullptr, *pluginsM=nullptr;
1069     wxMenuItem *tmpitem=nullptr;
1070 
1071     wxXmlResource* xml_res = wxXmlResource::Get();
1072     wxString resPath = ConfigManager::GetDataFolder();
1073     xml_res->Load(resPath + _T("/resources.zip#zip:main_menu.xrc"));
1074     Manager::Get()->GetLogManager()->DebugLog(_T("Loading menubar..."));
1075     mbar = xml_res->LoadMenuBar(_T("main_menu_bar"));
1076     if (!mbar)
1077         mbar = new wxMenuBar(); // Some error happened.
1078     if (mbar)
1079         SetMenuBar(mbar);
1080 
1081     // Find Menus that we'll change later
1082 
1083     tmpidx = mbar->FindMenu(_("&Edit"));
1084     if (tmpidx!=wxNOT_FOUND)
1085     {
1086         wxMenu *hl = nullptr;
1087         mbar->FindItem(idEditHighlightModeText, &hl);
1088         if (hl)
1089         {
1090             EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
1091             if (colour_set)
1092             {
1093                 wxArrayString langs = colour_set->GetAllHighlightLanguages();
1094                 for (size_t i = 0; i < langs.GetCount(); ++i)
1095                 {
1096                     if (i > 0 && !(i % 20))
1097                         hl->Break(); // break into columns every 20 items
1098                     int id = wxNewId();
1099                     hl->AppendRadioItem(id, langs[i],
1100                                 wxString::Format(_("Switch highlighting mode for current document to \"%s\""), langs[i].wx_str()));
1101                     Connect(id, -1, wxEVT_COMMAND_MENU_SELECTED,
1102                             (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
1103                             &MainFrame::OnEditHighlightMode);
1104                 }
1105             }
1106         }
1107         const wxLanguageInfo* info = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1108         wxMenu* editMenu = mbar->GetMenu(tmpidx);
1109         if (   info
1110             && ( ( info->Language >= wxLANGUAGE_CHINESE
1111                   && info->Language <= wxLANGUAGE_CHINESE_TAIWAN )
1112                 || info->Language == wxLANGUAGE_JAPANESE
1113                 || info->Language == wxLANGUAGE_KOREAN ) )
1114         {
1115             editMenu->Append(idEditCompleteCode, _("Complete code\tShift-Space"));
1116         }
1117         else
1118             editMenu->Append(idEditCompleteCode, _("Complete code\tCtrl-Space"));
1119     }
1120 
1121     tmpidx = mbar->FindMenu(_("&Tools"));
1122     if (tmpidx!=wxNOT_FOUND)
1123         tools = mbar->GetMenu(tmpidx);
1124 
1125     tmpidx = mbar->FindMenu(_("P&lugins"));
1126     if (tmpidx!=wxNOT_FOUND)
1127         plugs = mbar->GetMenu(tmpidx);
1128 
1129     if ((tmpitem = mbar->FindItem(idHelpPlugins,nullptr)))
1130         pluginsM = tmpitem->GetSubMenu();
1131 
1132     m_ToolsMenu       = tools    ? tools    : new wxMenu();
1133     m_PluginsMenu     = plugs    ? plugs    : new wxMenu();
1134     m_HelpPluginsMenu = pluginsM ? pluginsM : new wxMenu();
1135 
1136     // core modules: create menus
1137     if (!Manager::IsBatchBuild())
1138         static_cast<ProjectManagerUI*>(m_pPrjManUI)->CreateMenu(mbar);
1139     Manager::Get()->GetDebuggerManager()->SetMenuHandler(m_debuggerMenuHandler);
1140 
1141     // ask all plugins to rebuild their menus
1142     PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1143     for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1144     {
1145         cbPlugin* plug = plugins[i]->plugin;
1146         if (plug && plug->IsAttached())
1147         {
1148             if (plug->GetType() == ptTool)
1149                 DoAddPlugin(plug);
1150             else
1151             {
1152                 AddPluginInHelpPluginsMenu(plug);
1153                 try
1154                 {
1155                     plug->BuildMenu(mbar);
1156                 }
1157                 catch (cbException& e)
1158                 {
1159                     e.ShowErrorMessage();
1160                 }
1161             }
1162         }
1163     }
1164 
1165     Manager::Get()->GetToolsManager()->BuildToolsMenu(m_ToolsMenu);
1166 
1167     // Ctrl+Tab workaround for non windows platforms:
1168     if ((platform::carbon) || (platform::gtk))
1169     {
1170         // Find the menu item for tab switching:
1171         tmpidx = mbar->FindMenu(_("&View"));
1172         if (tmpidx != wxNOT_FOUND)
1173         {
1174             wxMenu* view = mbar->GetMenu(tmpidx);
1175             wxMenuItem* switch_item = view->FindItem(idViewSwitchTabs);
1176             if (switch_item)
1177             {
1178                 // Change the accelerator for this menu item:
1179                 wxString accel;
1180                 if      (platform::carbon)
1181                     accel = wxT("Alt+Tab");
1182                 else if (platform::gtk)
1183                     accel = wxT("Ctrl+,");
1184                 switch_item->SetItemLabel(wxString(_("S&witch tabs")) + wxT("\t") + accel);
1185             }
1186         }
1187     }
1188 
1189     SetMenuBar(mbar);
1190     InitializeRecentFilesHistory();
1191 
1192     CodeBlocksEvent event2(cbEVT_MENUBAR_CREATE_END);
1193     Manager::Get()->ProcessEvent(event2);
1194 }
1195 
CreateToolbars()1196 void MainFrame::CreateToolbars()
1197 {
1198     if (m_pToolbar)
1199     {
1200         SetToolBar(nullptr);
1201         m_pToolbar = nullptr;
1202     }
1203 
1204     wxXmlResource* xml_res = wxXmlResource::Get();
1205     wxString resPath = ConfigManager::GetDataFolder();
1206     xml_res->Load(resPath + _T("/resources.zip#zip:main_toolbar.xrc"));
1207     Manager::Get()->GetLogManager()->DebugLog(_T("Loading toolbar..."));
1208 
1209     m_pToolbar = Manager::Get()->CreateEmptyToolbar();
1210     Manager::Get()->AddonToolBar(m_pToolbar, _T("main_toolbar"));
1211 
1212     m_pToolbar->Realize();
1213 
1214     // Right click on the main toolbar will popup a context menu
1215     m_pToolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1216 
1217     m_pToolbar->SetInitialSize();
1218 
1219     // Right click on the debugger toolbar will popup a context menu
1220     m_debuggerToolbarHandler->GetToolbar()->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1221 
1222     std::vector<ToolbarInfo> toolbars;
1223 
1224     toolbars.push_back(ToolbarInfo(m_pToolbar, wxAuiPaneInfo().Name(wxT("MainToolbar")).Caption(_("Main Toolbar")), 0));
1225     toolbars.push_back(ToolbarInfo(m_debuggerToolbarHandler->GetToolbar(),
1226                                    wxAuiPaneInfo(). Name(wxT("DebuggerToolbar")).Caption(_("Debugger Toolbar")),
1227                                    2));
1228 
1229     // ask all plugins to rebuild their toolbars
1230     PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1231     for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1232     {
1233         cbPlugin* plug = plugins[i]->plugin;
1234         if (plug && plug->IsAttached())
1235         {
1236             ToolbarInfo info = DoAddPluginToolbar(plug);
1237             if (info.toolbar)
1238             {
1239                 toolbars.push_back(info);
1240                 // support showing context menu of the plugins' toolbar
1241                 info.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1242                                       wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1243             }
1244         }
1245     }
1246 
1247     std::sort(toolbars.begin(), toolbars.end());
1248 
1249     int row = 0, position = 0, rowLength = 0;
1250     int maxLength = GetSize().x;
1251 
1252     for (std::vector<ToolbarInfo>::iterator it = toolbars.begin(); it != toolbars.end(); ++it)
1253     {
1254         rowLength += it->toolbar->GetSize().x;
1255         if (rowLength >= maxLength)
1256         {
1257             row++;
1258             position = 0;
1259             rowLength = it->toolbar->GetSize().x;
1260         }
1261         wxAuiPaneInfo paneInfo(it->paneInfo);
1262         m_LayoutManager.AddPane(it->toolbar, paneInfo.ToolbarPane().Top().Row(row).Position(position));
1263 
1264         position += it->toolbar->GetSize().x;
1265     }
1266     DoUpdateLayout();
1267 
1268     Manager::ProcessPendingEvents();
1269     SetToolBar(nullptr);
1270 }
1271 
AddToolbarItem(int id,const wxString & title,const wxString & shortHelp,const wxString & longHelp,const wxString & image)1272 void MainFrame::AddToolbarItem(int id, const wxString& title, const wxString& shortHelp, const wxString& longHelp, const wxString& image)
1273 {
1274     m_pToolbar->AddTool(id, title, cbLoadBitmap(image, wxBITMAP_TYPE_PNG));
1275     m_pToolbar->SetToolShortHelp(id, shortHelp);
1276     m_pToolbar->SetToolLongHelp(id, longHelp);
1277 }
1278 
ScanForPlugins()1279 void MainFrame::ScanForPlugins()
1280 {
1281     m_ScanningForPlugins = true;
1282     m_PluginIDsMap.clear();
1283 
1284     PluginManager* m_PluginManager = Manager::Get()->GetPluginManager();
1285 
1286     // user paths first
1287     wxString path = ConfigManager::GetPluginsFolder(false);
1288     Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1289     int count = m_PluginManager->ScanForPlugins(path);
1290 
1291     // global paths
1292     path = ConfigManager::GetPluginsFolder(true);
1293     Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1294     count += m_PluginManager->ScanForPlugins(path);
1295 
1296     // actually load plugins
1297     if (count > 0)
1298     {
1299         Manager::Get()->GetLogManager()->Log(_("Loading:"));
1300         m_PluginManager->LoadAllPlugins();
1301     }
1302 
1303     CodeBlocksEvent event(cbEVT_PLUGIN_LOADING_COMPLETE);
1304     Manager::Get()->GetPluginManager()->NotifyPlugins(event);
1305     m_ScanningForPlugins = false;
1306 }
1307 
AddPluginInMenus(wxMenu * menu,cbPlugin * plugin,wxObjectEventFunction callback,int pos,bool checkable)1308 wxMenuItem* MainFrame::AddPluginInMenus(wxMenu* menu, cbPlugin* plugin, wxObjectEventFunction callback, int pos, bool checkable)
1309 {
1310     wxMenuItem* item = nullptr;
1311     if (!plugin || !menu)
1312         return item;
1313 
1314     const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1315     if (!info)
1316         return nullptr;
1317 
1318     PluginIDsMap::iterator it;
1319     for (it = m_PluginIDsMap.begin(); it != m_PluginIDsMap.end(); ++it)
1320     {
1321         if (it->second == info->name)
1322         {
1323             item = menu->FindItem(it->first);
1324             if (item)
1325                 return item;
1326         }
1327     }
1328 
1329     int id = wxNewId();
1330     wxString title = info->title + (menu == m_HelpPluginsMenu ? _T("...") : wxEmptyString);
1331     m_PluginIDsMap[id] = info->name;
1332     if (pos == -1)
1333         pos = menu->GetMenuItemCount();
1334 
1335     while(!item)
1336     {
1337         if (!pos || title.CmpNoCase(menu->FindItemByPosition(pos - 1)->GetItemLabelText()) > 0)
1338             item = menu->Insert(pos, id, title, wxEmptyString, checkable ? wxITEM_CHECK : wxITEM_NORMAL);
1339 
1340         --pos;
1341     }
1342 
1343     Connect( id,  wxEVT_COMMAND_MENU_SELECTED, callback );
1344     return item;
1345 }
1346 
AddPluginInPluginsMenu(cbPlugin * plugin)1347 void MainFrame::AddPluginInPluginsMenu(cbPlugin* plugin)
1348 {
1349     // "Plugins" menu is special case because it contains "Manage plugins",
1350     // which must stay at the end of the menu
1351     // So we insert entries, not append...
1352 
1353     // this will insert a separator when the first plugin is added in the "Plugins" menu
1354     if (m_PluginsMenu->GetMenuItemCount() == 1)
1355          m_PluginsMenu->Insert(0, wxID_SEPARATOR, _T(""));
1356 
1357     AddPluginInMenus(m_PluginsMenu, plugin,
1358                     (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnPluginsExecuteMenu,
1359                     m_PluginsMenu->GetMenuItemCount() - 2);
1360 }
1361 
AddPluginInHelpPluginsMenu(cbPlugin * plugin)1362 void MainFrame::AddPluginInHelpPluginsMenu(cbPlugin* plugin)
1363 {
1364     AddPluginInMenus(m_HelpPluginsMenu, plugin,
1365                     (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnHelpPluginMenu);
1366 }
1367 
1368 
1369 namespace
1370 {
1371 struct ToolbarFitInfo
1372 {
1373     int row;
1374     wxRect rect;
1375     wxWindow *window;
1376 
operator <__anon5b41abdd0211::ToolbarFitInfo1377     bool operator<(const ToolbarFitInfo &r) const
1378     {
1379         if (row < r.row)
1380             return true;
1381         else if (row == r.row)
1382             return rect.x < r.rect.x;
1383         else
1384             return false;
1385     }
1386 };
1387 
CollectToolbars(std::set<ToolbarFitInfo> & result,wxAuiManager & layoutManager)1388 static void CollectToolbars(std::set<ToolbarFitInfo> &result, wxAuiManager &layoutManager)
1389 {
1390     const wxAuiPaneInfoArray &panes = layoutManager.GetAllPanes();
1391     for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1392     {
1393         const wxAuiPaneInfo &info = panes[ii];
1394         if (info.IsToolbar() && info.IsShown())
1395         {
1396             ToolbarFitInfo f;
1397             f.row = info.dock_row;
1398             f.rect = info.rect;
1399             f.window = info.window;
1400             result.insert(f);
1401         }
1402     }
1403 }
1404 
1405 struct ToolbarRowInfo
1406 {
ToolbarRowInfo__anon5b41abdd0211::ToolbarRowInfo1407     ToolbarRowInfo() {}
ToolbarRowInfo__anon5b41abdd0211::ToolbarRowInfo1408     ToolbarRowInfo(int width_, int position_) : width(width_), position(position_) {}
1409 
1410     int width, position;
1411 };
1412 
1413 // Function which tries to make all toolbars visible.
FitToolbars(wxAuiManager & layoutManager,wxWindow * mainFrame)1414 static void FitToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
1415 {
1416     std::set<ToolbarFitInfo> sorted;
1417     CollectToolbars(sorted, layoutManager);
1418     if (sorted.empty())
1419         return;
1420 
1421     int maxWidth = mainFrame->GetSize().x;
1422     int gripperSize =  layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
1423 
1424     // move all toolbars to the left as possible and add the non-fitting to a list
1425     std::vector<ToolbarRowInfo> rows;
1426     std::vector<wxWindow*> nonFitingToolbars;
1427     for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
1428     {
1429         wxAuiPaneInfo &pane = layoutManager.GetPane(it->window);
1430         int row = pane.dock_row;
1431         while (static_cast<int>(rows.size()) <= row)
1432             rows.push_back(ToolbarRowInfo(0, 0));
1433 
1434         int maxX = rows[row].width + it->window->GetBestSize().x + gripperSize;
1435         if (maxX > maxWidth)
1436             nonFitingToolbars.push_back(it->window);
1437         else
1438         {
1439             rows[row].width = maxX;
1440             pane.Position(rows[row].position++);
1441         }
1442     }
1443 
1444     // move the non-fitting toolbars at the bottom
1445     int lastRow = rows.empty() ? 0 : (rows.size() - 1);
1446     int position = rows.back().position, maxX = rows.back().width;
1447     for (std::vector<wxWindow*>::iterator it = nonFitingToolbars.begin(); it != nonFitingToolbars.end(); ++it)
1448     {
1449         maxX += (*it)->GetBestSize().x;
1450         maxX += gripperSize;
1451         if (maxX > maxWidth)
1452         {
1453             position = 0;
1454             lastRow++;
1455             maxX = (*it)->GetBestSize().x + gripperSize;
1456         }
1457         layoutManager.GetPane(*it).Position(position++).Row(lastRow);
1458     }
1459 }
1460 
1461 // Function which tries to minimize the space used by the toolbars.
1462 // Also it can be used to show toolbars which have gone outside the window.
OptimizeToolbars(wxAuiManager & layoutManager,wxWindow * mainFrame)1463 static void OptimizeToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
1464 {
1465     std::set<ToolbarFitInfo> sorted;
1466     CollectToolbars(sorted, layoutManager);
1467     if (sorted.empty())
1468         return;
1469 
1470     int maxWidth = mainFrame->GetSize().x;
1471     int lastRow = 0, position = 0, maxX = 0;
1472     int gripperSize =  layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
1473 
1474     for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
1475     {
1476         maxX += it->window->GetBestSize().x;
1477         maxX += gripperSize;
1478         if (maxX > maxWidth)
1479         {
1480             position = 0;
1481             lastRow++;
1482             maxX = it->window->GetBestSize().x + gripperSize;
1483         }
1484         layoutManager.GetPane(it->window).Position(position++).Row(lastRow);
1485     }
1486 }
1487 
1488 } // anomymous namespace
1489 
LoadWindowState()1490 void MainFrame::LoadWindowState()
1491 {
1492     wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1493     for (size_t i = 0; i < subs.GetCount(); ++i)
1494     {
1495         wxString name = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/name"));
1496         wxString layout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/data"));
1497         wxString layoutMP = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/dataMessagePane"));
1498         SaveViewLayout(name, layout, layoutMP);
1499     }
1500     wxString deflayout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
1501     LoadViewLayout(deflayout);
1502 
1503     DoFixToolbarsLayout();
1504 
1505     // Fit toolbars on load to prevent gaps if toolbar sizes have changed. The most common reason
1506     // for toolbar change would be change of the size of the icons in the toolbar.
1507     FitToolbars(m_LayoutManager, this);
1508 
1509     // load manager and messages selected page
1510     if (m_pPrjManUI->GetNotebook())
1511         m_pPrjManUI->GetNotebook()->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_selection"), 0));
1512     m_pInfoPane->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_selection"), 0));
1513 
1514     // Cryogen 23/3/10 wxAuiNotebook can't set it's own tab position once instantiated, for some reason. This code fails in InfoPane::InfoPane().
1515     // Moved here as this seems like a resonable place to do UI setup. Feel free to move it elsewhere.
1516     if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/infopane_tabs_bottom"), false))
1517         m_pInfoPane->SetWindowStyleFlag(m_pInfoPane->GetWindowStyleFlag() | wxAUI_NB_BOTTOM);
1518 }
1519 
LoadWindowSize()1520 void MainFrame::LoadWindowSize()
1521 {
1522 #ifndef __WXMAC__
1523     int x = 0;
1524     int y = 0;
1525 #else
1526     int x = 0;
1527     int y = wxSystemSettings::GetMetric(wxSYS_MENU_Y, this); // make sure it doesn't hide under the menu bar
1528 #endif
1529     int w = 1000;
1530     int h = 800;
1531 
1532     // obtain display index used last time
1533     int last_display_index = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/display"), 0);
1534     // load window size and position
1535     wxRect rect(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left"),   x),
1536                 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/top"),    y),
1537                 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/width"),  w),
1538                 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/height"), h));
1539     // maximize if needed
1540     bool maximized = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/main_frame/layout/maximized"), true);
1541     Maximize(maximized); // toggle
1542 
1543     // set display, size and position
1544     int display_index_window = wxDisplay::GetFromWindow(this); // C::B usually starts on primary display...
1545     // ...but try to use display that was used last time, if still available:
1546     if ((last_display_index>=0) && (last_display_index<static_cast<int>(wxDisplay::GetCount())))
1547         display_index_window = static_cast<int>(last_display_index);
1548     int display_index = ((display_index_window>=0) ? display_index_window : 0);
1549 
1550     wxDisplay disp(display_index); // index might be wxNOT_FOUND (=-1) due to GetFromWindow call
1551     if (maximized)
1552     {
1553         rect = disp.GetClientArea(); // apply from display, overriding settings above
1554         rect.width  -= 100;
1555         rect.height -= 100;
1556     }
1557     else
1558     {
1559         // Adjust to actual screen size. This is useful for portable C::B versions,
1560         // where the window might be out of screen when saving on a two-monitor
1561         // system an re-opening on a one-monitor system (on Windows, at least).
1562         wxRect displayRect = disp.GetClientArea();
1563         if ((displayRect.GetLeft() + displayRect.GetWidth())  < rect.GetLeft())   rect.SetLeft  (displayRect.GetLeft()  );
1564         if ((displayRect.GetLeft() + displayRect.GetWidth())  < rect.GetRight())  rect.SetRight (displayRect.GetRight() );
1565         if ((displayRect.GetTop()  + displayRect.GetHeight()) < rect.GetTop())    rect.SetTop   (displayRect.GetTop()   );
1566         if ((displayRect.GetTop()  + displayRect.GetHeight()) < rect.GetBottom()) rect.SetBottom(displayRect.GetBottom());
1567     }
1568 
1569     SetSize(rect);
1570 }
1571 
SaveWindowState()1572 void MainFrame::SaveWindowState()
1573 {
1574     DoCheckCurrentLayoutForChanges(false);
1575 
1576     // first delete all previous layouts, otherwise they might remain
1577     // if the new amount of layouts is less than the previous, because only the first layouts will be overwritten
1578     wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1579     for (size_t i = 0; i < subs.GetCount(); ++i)
1580     {
1581         Manager::Get()->GetConfigManager(_T("app"))->DeleteSubPath(_T("/main_frame/layout/") + subs[i]);
1582     }
1583 
1584     int count = 0;
1585     for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
1586     {
1587         if (it->first.IsEmpty())
1588             continue;
1589         ++count;
1590         wxString key = wxString::Format(_T("/main_frame/layout/view%d/"), count);
1591         Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("name"), it->first);
1592         Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("data"), it->second);
1593 
1594         if (!m_LayoutMessagePane[it->first].IsEmpty())
1595             Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("dataMessagePane"), m_LayoutMessagePane[it->first]);
1596     }
1597 
1598     // save manager and messages selected page
1599     if (m_pPrjManUI->GetNotebook())
1600     {
1601         int selection = m_pPrjManUI->GetNotebook()->GetSelection();
1602         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left_block_selection"), selection);
1603     }
1604     Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/bottom_block_selection"), m_pInfoPane->GetSelection());
1605 
1606     // save display, window size and position
1607     Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/display"),   wxDisplay::GetFromWindow(this));
1608     if (!IsMaximized() && !IsIconized())
1609     {
1610         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left"),   GetPosition().x);
1611         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/top"),    GetPosition().y);
1612         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/width"),  GetSize().x);
1613         Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/height"), GetSize().y);
1614     }
1615     Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/maximized"), IsMaximized());
1616 }
1617 
LoadViewLayout(const wxString & name,bool isTemp)1618 void MainFrame::LoadViewLayout(const wxString& name, bool isTemp)
1619 {
1620     if (m_LastLayoutName != name && !DoCheckCurrentLayoutForChanges(true))
1621         return;
1622 
1623     m_LastLayoutIsTemp = isTemp;
1624 
1625     wxString layout = m_LayoutViews[name];
1626     wxString layoutMP = m_LayoutMessagePane[name];
1627     if (layoutMP.IsEmpty())
1628         layoutMP = m_LayoutMessagePane[gDefaultLayout];
1629     if (layout.IsEmpty())
1630     {
1631         layout = m_LayoutViews[gDefaultLayout];
1632         SaveViewLayout(name, layout, layoutMP, false);
1633         DoSelectLayout(name);
1634     }
1635     else
1636         DoSelectLayout(name);
1637 
1638     // first load taborder of MessagePane, so LoadPerspective can restore the last selected tab
1639     m_pInfoPane->LoadTabOrder(layoutMP);
1640 
1641     // We have to force an update here, because the m_LayoutManager.GetAllPanes()
1642     // would not report correct values if not updated here.
1643     m_LayoutManager.LoadPerspective(layout, true);
1644 
1645     // If we load a layout we have to check if the window is on a valid display
1646     // and has valid size. This can happen if a user moves a layout file from a
1647     // multi display setup to a single display setup. The size has to be checked
1648     // because it is possible that the target display has a lower resolution then
1649     // the source display.
1650     const wxAuiPaneInfoArray& windowArray = m_LayoutManager.GetAllPanes();
1651     for (size_t i = 0; i < windowArray.GetCount(); ++i)
1652     {
1653         cbFixWindowSizeAndPlace(windowArray.Item(i).frame);
1654     }
1655 
1656     DoUpdateLayout();
1657 
1658     m_PreviousLayoutName = m_LastLayoutName;
1659     m_LastLayoutName = name;
1660     m_LastLayoutData = layout;
1661     m_LastMessagePaneLayoutData = layoutMP;
1662 
1663     CodeBlocksLayoutEvent evt(cbEVT_SWITCHED_VIEW_LAYOUT);
1664     evt.layout = name;
1665     Manager::Get()->ProcessEvent(evt);
1666 }
1667 
SaveViewLayout(const wxString & name,const wxString & layout,const wxString & layoutMP,bool select)1668 void MainFrame::SaveViewLayout(const wxString& name, const wxString& layout, const wxString& layoutMP, bool select)
1669 {
1670     if (name.IsEmpty())
1671         return;
1672     m_LayoutViews[name] = layout;
1673     m_LayoutMessagePane[name] = layoutMP;
1674     wxMenu* viewLayouts = nullptr;
1675     GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1676     if (viewLayouts && viewLayouts->FindItem(name) == wxNOT_FOUND)
1677     {
1678         int id = wxNewId();
1679         viewLayouts->InsertCheckItem(viewLayouts->GetMenuItemCount() - 3, id, name, wxString::Format(_("Switch to %s perspective"), name.wx_str()));
1680         Connect( id,  wxEVT_COMMAND_MENU_SELECTED,
1681             (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnViewLayout);
1682         m_PluginIDsMap[id] = name;
1683     }
1684     if (select)
1685     {
1686         DoSelectLayout(name);
1687         m_LastLayoutName = name;
1688     }
1689 }
1690 
LayoutDifferent(const wxString & layout1,const wxString & layout2,const wxString & delimiter)1691 bool MainFrame::LayoutDifferent(const wxString& layout1,const wxString& layout2,const wxString& delimiter)
1692 {
1693     wxStringTokenizer strTok;
1694     unsigned long j;
1695 
1696     strTok.SetString(layout1, delimiter);
1697     wxArrayString arLayout1;
1698     while(strTok.HasMoreTokens())
1699     {
1700         wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1701         while(strTokColon.HasMoreTokens())
1702         {
1703             wxString theToken = strTokColon.GetNextToken();
1704             if (theToken.StartsWith(_T("state=")))
1705             {
1706                 theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1707                 theToken.ToULong(&j);
1708                 // we filter out the hidden/show state
1709                 theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1710             }
1711                arLayout1.Add(theToken);
1712         }
1713     }
1714 
1715     strTok.SetString(layout2, delimiter);
1716     wxArrayString arLayout2;
1717     while(strTok.HasMoreTokens())
1718     {
1719         wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1720         while(strTokColon.HasMoreTokens())
1721         {
1722             wxString theToken = strTokColon.GetNextToken();
1723             if (theToken.StartsWith(_T("state=")))
1724             {
1725                 theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1726                 theToken.ToULong(&j);
1727                 // we filter out the hidden/show state
1728                 theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1729             }
1730                arLayout2.Add(theToken);
1731         }
1732     }
1733 
1734     arLayout1.Sort();
1735     arLayout2.Sort();
1736 
1737     return arLayout1 != arLayout2;
1738 }
1739 
LayoutMessagePaneDifferent(const wxString & layout1,const wxString & layout2,bool checkSelection)1740 bool MainFrame::LayoutMessagePaneDifferent(const wxString& layout1,const wxString& layout2, bool checkSelection)
1741 {
1742     wxStringTokenizer strTok;
1743     wxArrayString arLayout1;
1744     wxArrayString arLayout2;
1745 
1746     strTok.SetString(layout1.BeforeLast('|'), _T(";"));
1747     while (strTok.HasMoreTokens())
1748     {
1749         arLayout1.Add(strTok.GetNextToken());
1750     }
1751 
1752     strTok.SetString(layout2.BeforeLast('|'), _T(";"));
1753     while (strTok.HasMoreTokens())
1754     {
1755         arLayout2.Add(strTok.GetNextToken());
1756     }
1757 
1758     if (checkSelection)
1759     {
1760         arLayout1.Add(layout1.AfterLast('|'));
1761         arLayout2.Add(layout2.AfterLast('|'));
1762     }
1763     arLayout1.Sort();
1764     arLayout2.Sort();
1765 
1766     return arLayout1 != arLayout2;
1767 }
1768 
DoCheckCurrentLayoutForChanges(bool canCancel)1769 bool MainFrame::DoCheckCurrentLayoutForChanges(bool canCancel)
1770 {
1771     DoFixToolbarsLayout();
1772     wxString lastlayout = m_LayoutManager.SavePerspective();
1773     wxString lastmessagepanelayout = m_pInfoPane->SaveTabOrder();
1774     if (!m_LastLayoutName.IsEmpty() &&
1775         (LayoutDifferent(lastlayout, m_LastLayoutData) ||
1776          LayoutMessagePaneDifferent(lastmessagepanelayout, m_LastMessagePaneLayoutData, Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/save_selection_change_in_mp"), true)) ))
1777     {
1778         AnnoyingDialog dlg(_("Layout changed"),
1779                             wxString::Format(_("The perspective '%s' has changed. Do you want to save it?"), m_LastLayoutName.wx_str()),
1780                             wxART_QUESTION,
1781                             canCancel ? AnnoyingDialog::YES_NO_CANCEL : AnnoyingDialog::YES_NO,
1782                             // partial fix for bug 18970 (fix is incomplete to prevent the user from saving 'rtCANCEL')
1783                             canCancel ? AnnoyingDialog::rtYES : AnnoyingDialog::rtSAVE_CHOICE);
1784         switch (dlg.ShowModal())
1785         {
1786             case AnnoyingDialog::rtYES:
1787                 SaveViewLayout(m_LastLayoutName, lastlayout, lastmessagepanelayout, false);
1788                 break;
1789             case AnnoyingDialog::rtCANCEL:
1790                 DoSelectLayout(m_LastLayoutName);
1791                 return false;
1792             default:
1793                 break;
1794         }
1795     }
1796     return true;
1797 }
1798 
DoFixToolbarsLayout()1799 void MainFrame::DoFixToolbarsLayout()
1800 {
1801     // The AUI layout system remembers toolbar sizes. In most circumstances we don't want this
1802     // feature. So we want to disable it and this is what is done in this function.
1803     // This function has effect after a toolbar size change.
1804     //
1805     // To do it we need to do two passes:
1806     // 1. reset the best/min sizes loaded from the layout file.
1807     // 2. set new best size
1808     //
1809     // The reset operation is needed because wxAUI does nothing when the values for min/best sizes
1810     // aren't equal to wxDefaultSize.
1811     // I'm not really sure why we need the second pass. :(
1812 
1813     wxAuiPaneInfoArray &panes = m_LayoutManager.GetAllPanes();
1814     for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1815     {
1816         wxAuiPaneInfo &info = panes[ii];
1817         if (info.IsToolbar() && info.IsShown())
1818         {
1819             info.best_size = wxDefaultSize;
1820             info.min_size = wxDefaultSize;
1821         }
1822     }
1823 
1824     // This is needed in order to auto shrink the toolbars to fit the icons with as little space as
1825     // possible.
1826     m_LayoutManager.Update();
1827 
1828     for (size_t i = 0; i < panes.GetCount(); ++i)
1829     {
1830         wxAuiPaneInfo& info = panes[i];
1831         if (info.IsToolbar())
1832         {
1833             info.best_size = info.window->GetBestSize();
1834             info.floating_size = wxDefaultSize;
1835         }
1836     }
1837 
1838     // If we don't do this toolbars would be empty during initial startup or after
1839     // View -> Perspective -> Save current.
1840     m_LayoutManager.Update();
1841 }
1842 
DoSelectLayout(const wxString & name)1843 void MainFrame::DoSelectLayout(const wxString& name)
1844 {
1845     wxMenu* viewLayouts = nullptr;
1846     GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1847     if (viewLayouts)
1848     {
1849         wxMenuItemList& items = viewLayouts->GetMenuItems();
1850         for (size_t i = 0; i < items.GetCount(); ++i)
1851         {
1852             if (!items[i]->IsCheckable())
1853                 continue;
1854 #if wxCHECK_VERSION(3, 0, 0)
1855             items[i]->Check(items[i]->GetItemLabel().IsSameAs(name));
1856 #else
1857             items[i]->Check(items[i]->GetText().IsSameAs(name));
1858 #endif
1859         }
1860 
1861         if (!m_LastLayoutIsTemp)
1862             Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/default"), name);
1863     }
1864 }
1865 
DoAddPluginStatusField(cbPlugin * plugin)1866 void MainFrame::DoAddPluginStatusField(cbPlugin* plugin)
1867 {
1868     cbStatusBar *sbar = (cbStatusBar *)GetStatusBar();
1869     if (!sbar)
1870         return;
1871     plugin->CreateStatusField(sbar);
1872     sbar->AdjustFieldsSize();
1873 }
1874 
InitToolbar(wxToolBar * tb)1875 inline void InitToolbar(wxToolBar *tb)
1876 {
1877     tb->SetInitialSize();
1878 }
1879 
DoAddPluginToolbar(cbPlugin * plugin)1880 ToolbarInfo MainFrame::DoAddPluginToolbar(cbPlugin* plugin)
1881 {
1882     ToolbarInfo info;
1883     info.toolbar = Manager::Get()->CreateEmptyToolbar();
1884     if (plugin->BuildToolBar(info.toolbar))
1885     {
1886         info.priority = plugin->GetToolBarPriority();
1887         SetToolBar(nullptr);
1888         InitToolbar(info.toolbar);
1889 
1890         // add View->Toolbars menu item for toolbar
1891         wxMenu* viewToolbars = nullptr;
1892         GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
1893         if (viewToolbars)
1894         {
1895             wxMenuItem* item = AddPluginInMenus(viewToolbars, plugin,
1896                                                 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
1897                                                 -1, true);
1898             if (item)
1899             {
1900                 item->Check(true);
1901                 m_PluginsTools[plugin] = info.toolbar;
1902             }
1903         }
1904 
1905         const PluginInfo* pluginInfo = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1906         if (!pluginInfo)
1907             cbThrow(_T("No plugin info?!?"));
1908 
1909         info.paneInfo.Name(pluginInfo->name + _T("Toolbar")).Caption(pluginInfo->title + _(" Toolbar"));
1910     }
1911     else
1912     {
1913         delete info.toolbar;
1914         info.toolbar = nullptr;
1915     }
1916     return info;
1917 }
1918 
DoAddPlugin(cbPlugin * plugin)1919 void MainFrame::DoAddPlugin(cbPlugin* plugin)
1920 {
1921     //Manager::Get()->GetLogManager()->DebugLog(_T("Adding plugin: %s"), plugin->GetInfo()->name.wx_str());
1922     AddPluginInHelpPluginsMenu(plugin);
1923     if (plugin->GetType() == ptTool)
1924     {
1925         AddPluginInPluginsMenu(plugin);
1926     }
1927     // offer menu and toolbar space for other plugins
1928     else
1929     {
1930         // menu
1931         try
1932         {
1933             wxMenuBar* mbar = GetMenuBar();
1934             plugin->BuildMenu(mbar);
1935         }
1936         catch (cbException& e)
1937         {
1938             e.ShowErrorMessage();
1939         }
1940         // Don't load the toolbars during the initial loading of the plugins, this code should be executed
1941         // only when a single plugins is loaded from the Plugins -> Manager ... window.
1942         if (!m_ScanningForPlugins)
1943         {
1944             // Create the toolbar for the plugin if there is one.
1945             const ToolbarInfo &toolbarInfo = DoAddPluginToolbar(plugin);
1946             if (toolbarInfo.toolbar)
1947             {
1948                 // Place the new toolbar at the bottom of the toolbar pane. Try to reuse the last row
1949                 // if there is enough space in it, otherwise place the new toolbar at a new row.
1950                 int row = 0;
1951                 const wxAuiPaneInfoArray &panes = m_LayoutManager.GetAllPanes();
1952                 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1953                 {
1954                     const wxAuiPaneInfo &info = panes[ii];
1955                     if (info.IsToolbar())
1956                         row = std::max(row, info.dock_row);
1957                 }
1958                 int minX = 100000, maxX = -100000;
1959                 int position = 0;
1960                 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1961                 {
1962                     const wxAuiPaneInfo &info = panes[ii];
1963                     if (info.IsToolbar() && info.dock_row == row && info.window)
1964                     {
1965                         const wxPoint &pt = info.window->GetPosition();
1966                         minX = std::min(minX, pt.x + info.window->GetSize().x);
1967                         maxX = std::max(maxX, pt.x + info.window->GetSize().x);
1968                         position = std::max(position, info.dock_pos);
1969                     }
1970                 }
1971                 if (maxX + toolbarInfo.toolbar->GetSize().x <= GetSize().x)
1972                     position++;
1973                 else
1974                 {
1975                     row++;
1976                     position = 0;
1977                 }
1978                 wxAuiPaneInfo paneInfo(toolbarInfo.paneInfo);
1979                 m_LayoutManager.AddPane(toolbarInfo.toolbar, paneInfo. ToolbarPane().Top().Row(row).Position(position));
1980                 // Add the event handler for mouse right click
1981                 toolbarInfo.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1982                                              wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1983 
1984                 DoUpdateLayout();
1985             }
1986         }
1987         DoAddPluginStatusField(plugin);
1988     }
1989 }
1990 
Open(const wxString & filename,bool addToHistory)1991 bool MainFrame::Open(const wxString& filename, bool addToHistory)
1992 {
1993     wxFileName fn(filename);
1994     fn.Normalize(); // really important so that two same files with different names are not loaded twice
1995     wxString name = fn.GetFullPath();
1996     LogManager *logger = Manager::Get()->GetLogManager();
1997     logger->DebugLog(_T("Opening file ") + name);
1998     bool ret = OpenGeneric(name, addToHistory);
1999     if (!ret)
2000         logger->LogError(wxString::Format(wxT("Opening file '%s' failed!"), name.wx_str()));
2001 
2002     return ret;
2003 }
2004 
ShowOpenFileDialog(const wxString & caption,const wxString & filter)2005 wxString MainFrame::ShowOpenFileDialog(const wxString& caption, const wxString& filter)
2006 {
2007     wxFileDialog dlg(this,
2008                      caption,
2009                      wxEmptyString,
2010                      wxEmptyString,
2011                      filter,
2012                      wxFD_OPEN | compatibility::wxHideReadonly);
2013     wxString sel;
2014     PlaceWindow(&dlg);
2015     if (dlg.ShowModal() == wxID_OK)
2016         sel = dlg.GetPath();
2017     return sel;
2018 }
2019 
OpenGeneric(const wxString & filename,bool addToHistory)2020 bool MainFrame::OpenGeneric(const wxString& filename, bool addToHistory)
2021 {
2022     if (filename.IsEmpty())
2023         return false;
2024 
2025     wxFileName fname(filename); fname.ClearExt(); fname.SetExt(_T("cbp"));
2026     switch ( FileTypeOf(filename) )
2027     {
2028         //
2029         // Workspace
2030         //
2031         case ftCodeBlocksWorkspace:
2032             // verify that it's not the same as the one already open
2033             if (filename == Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename())
2034                 return true;
2035             else
2036             {
2037                 if ( DoCloseCurrentWorkspace() )
2038                 {
2039                     wxBusyCursor wait; // loading a worspace can take some time -> showhourglass
2040                     ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
2041                     bool ret = Manager::Get()->GetProjectManager()->LoadWorkspace(filename);
2042                     if (!ret)
2043                         ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
2044                     else if (addToHistory)
2045                         m_projectsHistory.AddToHistory(Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename());
2046                     return ret;
2047                 }
2048                 else
2049                     return false;
2050             }
2051             break;
2052 
2053         //
2054         // Project
2055         //
2056         case ftCodeBlocksProject:
2057         {
2058             // Make a check whether the project exists in current workspace
2059             cbProject* prj = Manager::Get()->GetProjectManager()->IsOpen(fname.GetFullPath());
2060             if (!prj)
2061             {
2062                 wxBusyCursor wait; // loading a workspace can take some time -> showhourglass
2063                 return DoOpenProject(filename, addToHistory);
2064             }
2065             else
2066             {
2067                 // NOTE (Morten#1#): A message here will prevent batch-builds from working and is shown sometimes even if correct
2068                 Manager::Get()->GetProjectManager()->SetProject(prj, false);
2069                 return true;
2070             }
2071         }
2072         //
2073         // Source files
2074         //
2075         case ftHeader:
2076             // fallthrough
2077         case ftSource:
2078             // fallthrough
2079         case ftTemplateSource:
2080             // fallthrough
2081         case ftResource:
2082             return DoOpenFile(filename, addToHistory);
2083         //
2084         // For all other files, ask MIME plugin for a suitable handler
2085         //
2086         default:
2087         {
2088             cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
2089             // warn user that "Files extension handler" is disabled
2090             if (!plugin)
2091             {
2092                 cbMessageBox(_("Could not open file ") + filename + _(",\nbecause no extension handler could be found."), _("Error"), wxICON_ERROR);
2093                 return false;
2094             }
2095             if (plugin->OpenFile(filename) == 0)
2096             {
2097                 m_filesHistory.AddToHistory(filename);
2098                 return true;
2099             }
2100             return false;
2101         }
2102     }
2103     return true;
2104 }
2105 
DoOpenProject(const wxString & filename,bool addToHistory)2106 bool MainFrame::DoOpenProject(const wxString& filename, bool addToHistory)
2107 {
2108 //    Manager::Get()->GetLogManager()->DebugLog(_T("Opening project '%s'"), filename.wx_str());
2109     if (!wxFileExists(filename))
2110     {
2111         cbMessageBox(_("The project file does not exist..."), _("Error"), wxICON_ERROR);
2112         return false;
2113     }
2114 
2115     ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
2116     cbProject* prj = Manager::Get()->GetProjectManager()->LoadProject(filename, true);
2117     if (prj)
2118     {
2119         if (addToHistory)
2120             m_projectsHistory.AddToHistory(prj->GetFilename());
2121         return true;
2122     }
2123     ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
2124     return false;
2125 }
2126 
DoOpenFile(const wxString & filename,bool addToHistory)2127 bool MainFrame::DoOpenFile(const wxString& filename, bool addToHistory)
2128 {
2129     cbEditor* ed = Manager::Get()->GetEditorManager()->Open(filename);
2130     if (ed)
2131     {
2132         // Cryogen 24/3/10 Activate the editor after opening. Partial fix for bug #14087.
2133         ed->Activate();
2134         if (addToHistory)
2135             m_filesHistory.AddToHistory(ed->GetFilename());
2136         return true;
2137     }
2138     return false;
2139 }
2140 
DoCloseCurrentWorkspace()2141 bool MainFrame::DoCloseCurrentWorkspace()
2142 {
2143     return Manager::Get()->GetProjectManager()->CloseWorkspace();
2144 }
2145 
DoCreateStatusBar()2146 void MainFrame::DoCreateStatusBar()
2147 {
2148     wxClientDC dc(this);
2149     wxFont font = dc.GetFont();
2150     int h;
2151     size_t num = 0;
2152 
2153     wxCoord widths[16]; // 16 max
2154     widths[num++] = -1; // main field
2155 
2156     dc.GetTextExtent(_(" Highlight Button "),                &widths[num++], &h);
2157     dc.GetTextExtent(_(" Windows (CR+LF) "),                 &widths[num++], &h);
2158     dc.GetTextExtent(_(" WINDOWS-1252 "),                    &widths[num++], &h);
2159     dc.GetTextExtent(_(" Line 12345, Col 123, Pos 123456 "), &widths[num++], &h);
2160     dc.GetTextExtent(_(" Overwrite "),                       &widths[num++], &h);
2161     dc.GetTextExtent(_(" Modified "),                        &widths[num++], &h);
2162     dc.GetTextExtent(_(" Read/Write "),                      &widths[num++], &h);
2163     dc.GetTextExtent(_(" name_of_profile "),                 &widths[num++], &h);
2164 
2165     wxStatusBar* sb = CreateStatusBar(num);
2166     if (!sb)
2167         return;
2168 
2169     SetStatusWidths(num, widths);
2170 
2171     // Highlightbutton
2172     wxRect rect;
2173     if (sb->GetFieldRect(1, rect))
2174     {
2175         m_pHighlightButton = new wxButton(sb, idHighlightButton, wxT("bla"), wxDefaultPosition, wxDefaultSize,
2176                                           wxBORDER_NONE|wxBU_LEFT|wxBU_EXACTFIT);
2177         // Adjust status bar height to fit the button.
2178         // This affects wx3.x build more than wx2.8 builds. At least on wxGTK.
2179         const int height = std::max(sb->GetMinHeight(), m_pHighlightButton->GetClientSize().GetHeight());
2180         sb->SetMinHeight(height);
2181     }
2182 }
2183 
2184 /// Change the label of a button only if it has really changed. This is used for status bar button,
2185 /// because if we always set the label there is flickering while scrolling in the editor.
2186 /// I've observed the flickering on wxGTK and I don't know if it is present on the other ports.
changeButtonLabel(wxButton & button,const wxString & text)2187 static void changeButtonLabel(wxButton &button, const wxString &text)
2188 {
2189     if (text != button.GetLabel())
2190         button.SetLabel(text);
2191 }
2192 
DoUpdateStatusBar()2193 void MainFrame::DoUpdateStatusBar()
2194 {
2195     if (!GetStatusBar())
2196         return;
2197     if (Manager::IsAppShuttingDown())
2198         return;
2199 
2200     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
2201     wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
2202     if (ed)
2203     {
2204         cbStyledTextCtrl * const control = ed->GetControl();
2205 
2206         int panel = 0;
2207         int pos = control->GetCurrentPos();
2208         wxString msg;
2209         SetStatusText(ed->GetFilename(), panel++);
2210 
2211         // Highlightbutton
2212         if (m_pHighlightButton)
2213         {
2214             EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
2215             if (colour_set)
2216                 changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(ed->GetLanguage()));
2217             else
2218                 changeButtonLabel(*m_pHighlightButton, wxEmptyString);
2219         }
2220         // EOL mode
2221         panel++;
2222         switch (control->GetEOLMode())
2223         {
2224             case wxSCI_EOL_CRLF: msg = _T("Windows (CR+LF)"); break;
2225             case wxSCI_EOL_CR:   msg = _T("Mac (CR)");        break;
2226             case wxSCI_EOL_LF:   msg = _T("Unix (LF)");       break;
2227             default:                                          break;
2228         }
2229         SetStatusText(msg, panel++);
2230         SetStatusText(ed->GetEncodingName(), panel++);
2231         msg.Printf(_("Line %d, Col %d, Pos %d"), control->GetCurrentLine() + 1, control->GetColumn(pos) + 1, pos);
2232         SetStatusText(msg, panel++);
2233         SetStatusText(control->GetOvertype() ? _("Overwrite") : _("Insert"), panel++);
2234 #if wxCHECK_VERSION(3, 0, 0)
2235         SetStatusText(ed->GetModified() ? _("Modified") : _T(""), panel++);
2236 #else
2237         SetStatusText(ed->GetModified() ? _("Modified") : wxEmptyString, panel++);
2238 #endif
2239         SetStatusText(control->GetReadOnly() ? _("Read only") : _("Read/Write"), panel++);
2240         SetStatusText(personality, panel++);
2241     }
2242     else
2243     {
2244         int panel = 0;
2245         EditorBase *eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
2246         if ( eb )
2247             SetStatusText(eb->GetFilename(), panel++);
2248         else
2249             SetStatusText(_("Welcome to ") + appglobals::AppName + _T("!"), panel++);
2250 
2251         // Highlightbutton
2252         if (m_pHighlightButton)
2253             changeButtonLabel(*m_pHighlightButton, wxEmptyString);
2254         panel++;
2255 
2256         SetStatusText(wxEmptyString, panel++);
2257         SetStatusText(wxEmptyString, panel++);
2258         SetStatusText(wxEmptyString, panel++);
2259         SetStatusText(wxEmptyString, panel++);
2260         SetStatusText(wxEmptyString, panel++);
2261         SetStatusText(wxEmptyString, panel++);
2262         SetStatusText(personality, panel++);
2263     }
2264 }
2265 
DoUpdateEditorStyle(cbAuiNotebook * target,const wxString & prefix,long defaultStyle)2266 void MainFrame::DoUpdateEditorStyle(cbAuiNotebook* target, const wxString& prefix, long defaultStyle)
2267 {
2268     if (!target)
2269         return;
2270 
2271     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2272     target->SetTabCtrlHeight(1);
2273 
2274     long nbstyle = cfg->ReadInt(_T("/environment/tabs_style"), 0);
2275     switch (nbstyle)
2276     {
2277         case 1: // simple style
2278             target->SetArtProvider(new wxAuiSimpleTabArt());
2279             break;
2280 
2281         case 2: // VC 7.1 style
2282             target->SetArtProvider(new NbStyleVC71());
2283             break;
2284 
2285         case 3: // Firefox 2 style
2286             target->SetArtProvider(new NbStyleFF2());
2287             break;
2288 
2289         default: // default style
2290             #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
2291             target->SetArtProvider(new NbStyleGTK());
2292             #else
2293             target->SetArtProvider(new wxAuiDefaultTabArt());
2294             #endif
2295             break;
2296     }
2297 
2298     target->SetTabCtrlHeight(-1);
2299 
2300     nbstyle = defaultStyle;
2301     if (cfg->ReadBool(_T("/environment/") + prefix + _T("_tabs_bottom")))
2302         nbstyle |= wxAUI_NB_BOTTOM;
2303 
2304     if (cfg->ReadBool(_T("/environment/tabs_list")))
2305         nbstyle |= wxAUI_NB_WINDOWLIST_BUTTON;
2306 
2307     target->SetWindowStyleFlag(nbstyle);
2308 }
2309 
DoUpdateEditorStyle()2310 void MainFrame::DoUpdateEditorStyle()
2311 {
2312     long style = wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_MIDDLE_CLICK_CLOSE;
2313     long closestyle = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/environment/tabs_closestyle"), 0);
2314     switch (closestyle)
2315     {
2316         case 1: // current tab
2317             style |= wxAUI_NB_CLOSE_ON_ACTIVE_TAB;
2318             break;
2319 
2320         case 2: // right side
2321             style |= wxAUI_NB_CLOSE_BUTTON;
2322             break;
2323 
2324         default: // all tabs (default)
2325             style |= wxAUI_NB_CLOSE_ON_ALL_TABS;
2326             break;
2327     }
2328 
2329     cbAuiNotebook* an = Manager::Get()->GetEditorManager()->GetNotebook();
2330 
2331     DoUpdateEditorStyle(an, _T("editor"), style | wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN);
2332     if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/hide_editor_tabs"),false))
2333         an->SetTabCtrlHeight(0);
2334 
2335     an = m_pInfoPane;
2336     DoUpdateEditorStyle(an, _T("infopane"), style);
2337 
2338     an = m_pPrjManUI->GetNotebook();
2339     DoUpdateEditorStyle(an, _T("project"), wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_TAB_MOVE);
2340 }
2341 
DoUpdateLayoutColours()2342 void MainFrame::DoUpdateLayoutColours()
2343 {
2344     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2345     wxAuiDockArt* art = m_LayoutManager.GetArtProvider();
2346 
2347 #ifndef __WXGTK__
2348     m_LayoutManager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_ALLOW_ACTIVE_PANE | wxAUI_MGR_TRANSPARENT_DRAG);
2349 #else // #ifndef __WXGTK__
2350     // workaround for a wxWidgets-bug that makes C::B crash when a floating window gets docked and composite-effects are enabled
2351     m_LayoutManager.SetFlags((wxAUI_MGR_DEFAULT | wxAUI_MGR_ALLOW_ACTIVE_PANE | wxAUI_MGR_TRANSPARENT_DRAG | wxAUI_MGR_VENETIAN_BLINDS_HINT)& ~wxAUI_MGR_TRANSPARENT_HINT);
2352 #endif // #ifndef __WXGTK__
2353 
2354     art->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE,                 cfg->ReadInt(_T("/environment/aui/border_size"), art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE)));
2355     art->SetMetric(wxAUI_DOCKART_SASH_SIZE,                        cfg->ReadInt(_T("/environment/aui/sash_size"), art->GetMetric(wxAUI_DOCKART_SASH_SIZE)));
2356     art->SetMetric(wxAUI_DOCKART_CAPTION_SIZE,                     cfg->ReadInt(_T("/environment/aui/caption_size"), art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE)));
2357     art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR,            cfg->ReadColour(_T("/environment/aui/active_caption_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR)));
2358     art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR,   cfg->ReadColour(_T("/environment/aui/active_caption_gradient_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR)));
2359     art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR,       cfg->ReadColour(_T("/environment/aui/active_caption_text_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR)));
2360     art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR,          cfg->ReadColour(_T("/environment/aui/inactive_caption_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR)));
2361     art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR, cfg->ReadColour(_T("/environment/aui/inactive_caption_gradient_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR)));
2362     art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR,     cfg->ReadColour(_T("/environment/aui/inactive_caption_text_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR)));
2363 
2364     DoUpdateLayout();
2365 }
2366 
DoUpdateLayout()2367 void MainFrame::DoUpdateLayout()
2368 {
2369     if (!m_StartupDone)
2370         return;
2371 
2372     DoFixToolbarsLayout();
2373 }
2374 
DoUpdateAppTitle()2375 void MainFrame::DoUpdateAppTitle()
2376 {
2377     EditorBase* ed = Manager::Get()->GetEditorManager() ? Manager::Get()->GetEditorManager()->GetActiveEditor() : nullptr;
2378     cbProject* prj = nullptr;
2379     if (ed && ed->IsBuiltinEditor())
2380     {
2381         ProjectFile* prjf = ((cbEditor*)ed)->GetProjectFile();
2382         if (prjf)
2383             prj = prjf->GetParentProject();
2384     }
2385     else
2386         prj = Manager::Get()->GetProjectManager() ? Manager::Get()->GetProjectManager()->GetActiveProject() : nullptr;
2387     wxString projname;
2388     wxString edname;
2389     wxString fulltitle;
2390     if (ed || prj)
2391     {
2392         if (prj)
2393         {
2394             if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2395                 projname = wxString(_T(" [")) + prj->GetTitle() + _T("]");
2396             else
2397                 projname = wxString(_T(" (")) + prj->GetTitle() + _T(")");
2398         }
2399         if (ed)
2400             edname = ed->GetTitle();
2401         fulltitle = edname + projname;
2402         if (!fulltitle.IsEmpty())
2403             fulltitle.Append(_T(" - "));
2404     }
2405     fulltitle.Append(appglobals::AppName);
2406     fulltitle.Append(_T(" "));
2407     fulltitle.Append(appglobals::AppVersion);
2408     SetTitle(fulltitle);
2409 }
2410 
ShowHideStartPage(bool forceHasProject,int forceState)2411 void MainFrame::ShowHideStartPage(bool forceHasProject, int forceState)
2412 {
2413 //    Manager::Get()->GetLogManager()->LogWarning(_("Toggling start page"));
2414     if (Manager::IsBatchBuild())
2415         return;
2416 
2417     // we use the 'forceHasProject' param because when a project is opened
2418     // the EVT_PROJECT_OPEN event is fired *before* ProjectManager::GetProjects()
2419     // and ProjectManager::GetActiveProject() are updated...
2420 
2421     if (m_InitiatedShutdown)
2422     {
2423         EditorBase* sh = Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle);
2424         if (sh)
2425             sh->Destroy();
2426         return;
2427     }
2428 
2429     bool show = !forceHasProject &&
2430                 Manager::Get()->GetProjectManager()->GetProjects()->GetCount() == 0 &&
2431                 Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/start_here_page"), true);
2432 
2433     if (forceState<0)
2434         show = false;
2435     if (forceState>0)
2436         show = true;
2437 
2438     EditorBase* sh = Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle);
2439     if (show)
2440     {
2441         if (!sh)
2442         {
2443             sh = new StartHerePage(this, m_projectsHistory, m_filesHistory,
2444                                    Manager::Get()->GetEditorManager()->GetNotebook());
2445         }
2446         else
2447             static_cast<StartHerePage*>(sh)->Reload();
2448     }
2449     else if (!show && sh)
2450         sh->Destroy();
2451 
2452     DoUpdateAppTitle();
2453 }
2454 
ShowHideScriptConsole()2455 void MainFrame::ShowHideScriptConsole()
2456 {
2457     if (Manager::IsBatchBuild())
2458         return;
2459     bool isVis = IsWindowReallyShown(m_pScriptConsole);
2460     CodeBlocksDockEvent evt(isVis ? cbEVT_HIDE_DOCK_WINDOW : cbEVT_SHOW_DOCK_WINDOW);
2461     evt.pWindow = m_pScriptConsole;
2462     Manager::Get()->ProcessEvent(evt);
2463 }
2464 
OnStartHereLink(wxCommandEvent & event)2465 void MainFrame::OnStartHereLink(wxCommandEvent& event)
2466 {
2467     wxCommandEvent evt;
2468     evt.SetId(idFileNewProject);
2469     wxString link = event.GetString();
2470     if (link.IsSameAs(_T("CB_CMD_NEW_PROJECT")))
2471         OnFileNewWhat(evt);
2472     else if (link.IsSameAs(_T("CB_CMD_OPEN_PROJECT")))
2473         DoOnFileOpen(true);
2474 //    else if (link.IsSameAs(_T("CB_CMD_CONF_ENVIRONMENT")))
2475 //        OnSettingsEnvironment(evt);
2476 //    else if (link.IsSameAs(_T("CB_CMD_CONF_EDITOR")))
2477 //        Manager::Get()->GetEditorManager()->Configure();
2478 //    else if (link.IsSameAs(_T("CB_CMD_CONF_COMPILER")))
2479 //        OnSettingsCompilerDebugger(evt);
2480     else if (link.StartsWith(_T("CB_CMD_OPEN_HISTORY_")))
2481     {
2482         RecentItemsList *recent;
2483         recent = link.StartsWith(_T("CB_CMD_OPEN_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2484         unsigned long item;
2485         link.AfterLast(_T('_')).ToULong(&item);
2486         --item;
2487         const wxString &filename = recent->GetHistoryFile(item);
2488         if (!filename.empty())
2489         {
2490             if ( !OpenGeneric(filename, true) )
2491                 recent->AskToRemoveFileFromHistory(item);
2492         }
2493     }
2494     else if (link.StartsWith(_T("CB_CMD_DELETE_HISTORY_")))
2495     {
2496         RecentItemsList *recent;
2497         recent = link.StartsWith(_T("CB_CMD_DELETE_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2498         unsigned long item;
2499         link.AfterLast(_T('_')).ToULong(&item);
2500         --item;
2501         recent->AskToRemoveFileFromHistory(item, false);
2502     }
2503     else if (link.IsSameAs(_T("CB_CMD_TIP_OF_THE_DAY")))
2504         ShowTips(true);
2505 }
2506 
InitializeRecentFilesHistory()2507 void MainFrame::InitializeRecentFilesHistory()
2508 {
2509     m_filesHistory.Initialize();
2510     m_projectsHistory.Initialize();
2511 }
2512 
TerminateRecentFilesHistory()2513 void MainFrame::TerminateRecentFilesHistory()
2514 {
2515     m_filesHistory.TerminateHistory();
2516     m_projectsHistory.TerminateHistory();
2517 }
2518 
GetEditorDescription(EditorBase * eb)2519 wxString MainFrame::GetEditorDescription(EditorBase* eb)
2520 {
2521     wxString descr = wxEmptyString;
2522     cbProject* prj = NULL;
2523     if (eb && eb->IsBuiltinEditor())
2524     {
2525         ProjectFile* prjf = ((cbEditor*)eb)->GetProjectFile();
2526         if (prjf)
2527             prj = prjf->GetParentProject();
2528     }
2529     else
2530         prj = Manager::Get()->GetProjectManager() ? Manager::Get()->GetProjectManager()->GetActiveProject() : nullptr;
2531     if (prj)
2532     {
2533         descr = wxString(_("Project: ")) + _T("<b>") + prj->GetTitle() + _T("</b>");
2534         if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2535             descr += wxString(_(" (Active)"));
2536         descr += wxString(_T("<br>"));
2537     }
2538     if (eb)
2539         descr += eb->GetFilename();
2540     return descr;
2541 }
2542 
2543 ////////////////////////////////////////////////////////////////////////////////
2544 // event handlers
2545 ////////////////////////////////////////////////////////////////////////////////
2546 
OnPluginsExecuteMenu(wxCommandEvent & event)2547 void MainFrame::OnPluginsExecuteMenu(wxCommandEvent& event)
2548 {
2549     wxString pluginName = m_PluginIDsMap[event.GetId()];
2550     if (!pluginName.IsEmpty())
2551         Manager::Get()->GetPluginManager()->ExecutePlugin(pluginName);
2552     else
2553         Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2554 }
2555 
OnHelpPluginMenu(wxCommandEvent & event)2556 void MainFrame::OnHelpPluginMenu(wxCommandEvent& event)
2557 {
2558     wxString pluginName = m_PluginIDsMap[event.GetId()];
2559     if (!pluginName.IsEmpty())
2560     {
2561         const PluginInfo* pi = Manager::Get()->GetPluginManager()->GetPluginInfo(pluginName);
2562         if (!pi)
2563         {
2564             Manager::Get()->GetLogManager()->DebugLog(_T("No plugin info for ") + pluginName);
2565             return;
2566         }
2567         dlgAboutPlugin dlg(this, pi);
2568         PlaceWindow(&dlg);
2569         dlg.ShowModal();
2570     }
2571     else
2572         Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2573 }
2574 
OnFileNewWhat(wxCommandEvent & event)2575 void MainFrame::OnFileNewWhat(wxCommandEvent& event)
2576 {
2577     int id = event.GetId();
2578     if (id != idFileNewEmpty)
2579     {
2580         // wizard-based
2581 
2582         TemplateOutputType tot = totProject;
2583         if      (id == idFileNewProject) tot = totProject;
2584         else if (id == idFileNewTarget)  tot = totTarget;
2585         else if (id == idFileNewFile)    tot = totFiles;
2586         else if (id == idFileNewCustom)  tot = totCustom;
2587         else if (id == idFileNewUser)    tot = totUser;
2588         else                             return;
2589 
2590         wxString filename;
2591         cbProject* prj = TemplateManager::Get()->New(tot, &filename);
2592         // verify that the open files are still in sync
2593         // the new file might have overwritten an existing one)
2594         Manager::Get()->GetEditorManager()->CheckForExternallyModifiedFiles();
2595 
2596         // If both are empty it means that the wizard has failed
2597         if (!prj && filename.IsEmpty())
2598             return;
2599 
2600         // Send the new project event
2601         CodeBlocksEvent evtNew(cbEVT_PROJECT_NEW, 0, prj);
2602         Manager::Get()->GetPluginManager()->NotifyPlugins(evtNew);
2603 
2604         if (prj)
2605         {
2606             prj->Save();
2607             prj->SaveAllFiles();
2608         }
2609 
2610         if (!filename.IsEmpty())
2611         {
2612             if (prj)
2613                 m_projectsHistory.AddToHistory(filename);
2614             else
2615                 m_filesHistory.AddToHistory(filename);
2616         }
2617         if (prj && tot == totProject) // Created project should be parsed
2618         {
2619             CodeBlocksEvent evtOpen(cbEVT_PROJECT_OPEN, 0, prj);
2620             Manager::Get()->GetPluginManager()->NotifyPlugins(evtOpen);
2621         }
2622         return;
2623     }
2624 
2625     // new empty file quick shortcut code below
2626 
2627     cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
2628     if (project)
2629         wxSetWorkingDirectory(project->GetBasePath());
2630     cbEditor* ed = Manager::Get()->GetEditorManager()->New();
2631 
2632     // initially start change-collection if configured on empty files
2633     if (ed)
2634         ed->GetControl()->SetChangeCollection(Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true));
2635 
2636     if (ed && ed->IsOK())
2637         m_filesHistory.AddToHistory(ed->GetFilename());
2638 
2639     if (!ed || !project)
2640         return;
2641 
2642     wxString oldname = ed->GetFilename();
2643     if (cbMessageBox(_("Do you want to add this new file in the active project (has to be saved first)?"),
2644                     _("Add file to project"),
2645                     wxYES_NO | wxICON_QUESTION) == wxID_YES &&
2646         ed->SaveAs() && ed->IsOK())
2647     {
2648         wxArrayInt targets;
2649         if (Manager::Get()->GetProjectManager()->AddFileToProject(ed->GetFilename(), project, targets) != 0)
2650         {
2651             ProjectFile* pf = project->GetFileByFilename(ed->GetFilename(), false);
2652             ed->SetProjectFile(pf);
2653             m_pPrjManUI->RebuildTree();
2654         }
2655     }
2656     // verify that the open files are still in sync
2657     // the new file might have overwritten an existing one)
2658     Manager::Get()->GetEditorManager()->CheckForExternallyModifiedFiles();
2659 }
2660 
OnDropFiles(wxCoord,wxCoord,const wxArrayString & files)2661 bool MainFrame::OnDropFiles(wxCoord /*x*/, wxCoord /*y*/, const wxArrayString& files)
2662 {
2663     bool success = true; // Safe case initialisation
2664 
2665     // first check to see if a workspace is passed. If so, only this will be loaded
2666     wxString foundWorkspace;
2667     for (unsigned int i = 0; i < files.GetCount(); ++i)
2668     {
2669         FileType ft = FileTypeOf(files[i]);
2670         if (ft == ftCodeBlocksWorkspace || ft == ftMSVC6Workspace || ft == ftMSVC7Workspace)
2671         {
2672             foundWorkspace = files[i];
2673             break;
2674         }
2675     }
2676 
2677     if (!foundWorkspace.IsEmpty())
2678       success &= OpenGeneric(foundWorkspace);
2679     else
2680     {
2681         wxBusyCursor useless;
2682         wxPaintEvent e;
2683         ProcessEvent(e);
2684         for (unsigned int i = 0; i < files.GetCount(); ++i)
2685           success &= OpenGeneric(files[i]);
2686     }
2687     return success;
2688 }
2689 
OnFileNew(cb_unused wxCommandEvent & event)2690 void MainFrame::OnFileNew(cb_unused wxCommandEvent& event)
2691 {
2692     wxMenu* popup = nullptr;
2693     wxMenuBar* bar = GetMenuBar();
2694     if (!bar)
2695         return;
2696 
2697     bar->FindItem(idFileNewProject, &popup);
2698     if (popup)
2699     {
2700         popup = CopyMenu(popup);
2701         if (popup)
2702         {
2703             PopupMenu(popup); // this will lead us in OnFileNewWhat() - the meat is there ;)
2704             delete popup;
2705         }
2706     }
2707 }
2708 
2709 // in case we are opening a project (bProject == true) we do not want to interfere
2710 // with 'last type of files' (probably the call was open (existing) project on the
2711 // start here page --> so we know it's a project --> set the filter accordingly
2712 // but as said don't force the 'last used type of files' to change, that should
2713 // only change when an open file is carried out (so (source) file <---> project (file) )
2714 // TODO : when regular file open and user manually sets filter to project files --> will change
2715 //      the last type : is that expected behaviour ???
DoOnFileOpen(bool bProject)2716 void MainFrame::DoOnFileOpen(bool bProject)
2717 {
2718     wxString Filters = FileFilters::GetFilterString();
2719     // the value returned by GetIndexForFilterAll() is updated by GetFilterString()
2720     int StoredIndex = FileFilters::GetIndexForFilterAll();
2721     wxString Path;
2722     ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("app"));
2723     if (mgr)
2724     {
2725         if (!bProject)
2726         {
2727             wxString Filter = mgr->Read(_T("/file_dialogs/file_new_open/filter"));
2728             if (!Filter.IsEmpty())
2729                 FileFilters::GetFilterIndexFromName(Filters, Filter, StoredIndex);
2730             Path = mgr->Read(_T("/file_dialogs/file_new_open/directory"), Path);
2731         }
2732         else
2733             FileFilters::GetFilterIndexFromName(Filters, _("Code::Blocks project/workspace files"), StoredIndex);
2734     }
2735     wxFileDialog dlg(this,
2736                             _("Open file"),
2737                             Path,
2738                             wxEmptyString,
2739                             Filters,
2740                             wxFD_OPEN | wxFD_MULTIPLE | compatibility::wxHideReadonly);
2741     dlg.SetFilterIndex(StoredIndex);
2742 
2743     PlaceWindow(&dlg);
2744     if (dlg.ShowModal() == wxID_OK)
2745     {
2746         // store the last used filter and directory
2747         // as said : don't do this in case of an 'open project'
2748         if (mgr && !bProject)
2749         {
2750             int Index = dlg.GetFilterIndex();
2751             wxString Filter;
2752             if (FileFilters::GetFilterNameFromIndex(Filters, Index, Filter))
2753                 mgr->Write(_T("/file_dialogs/file_new_open/filter"), Filter);
2754             wxString Test = dlg.GetDirectory();
2755             mgr->Write(_T("/file_dialogs/file_new_open/directory"), dlg.GetDirectory());
2756         }
2757         wxArrayString files;
2758         dlg.GetPaths(files);
2759         OnDropFiles(0,0,files);
2760     }
2761 }
2762 
OnFileOpen(cb_unused wxCommandEvent & event)2763 void MainFrame::OnFileOpen(cb_unused wxCommandEvent& event)
2764 {
2765     DoOnFileOpen(false); // through file menu (not sure if we are opening a project)
2766 }
2767 
OnFileReopenProject(wxCommandEvent & event)2768 void MainFrame::OnFileReopenProject(wxCommandEvent& event)
2769 {
2770     size_t id = event.GetId() - wxID_CBFILE17;
2771     wxString fname = m_projectsHistory.GetHistoryFile(id);
2772     if (!OpenGeneric(fname, true))
2773         m_projectsHistory.AskToRemoveFileFromHistory(id);
2774 }
2775 
OnFileOpenRecentProjectClearHistory(cb_unused wxCommandEvent & event)2776 void MainFrame::OnFileOpenRecentProjectClearHistory(cb_unused wxCommandEvent& event)
2777 {
2778     m_projectsHistory.ClearHistory();
2779 }
2780 
OnFileReopen(wxCommandEvent & event)2781 void MainFrame::OnFileReopen(wxCommandEvent& event)
2782 {
2783     size_t id = event.GetId() - wxID_CBFILE01;
2784     wxString fname = m_filesHistory.GetHistoryFile(id);
2785     if (!OpenGeneric(fname, true))
2786         m_filesHistory.AskToRemoveFileFromHistory(id);
2787 }
2788 
OnFileOpenRecentClearHistory(cb_unused wxCommandEvent & event)2789 void MainFrame::OnFileOpenRecentClearHistory(cb_unused wxCommandEvent& event)
2790 {
2791     m_filesHistory.ClearHistory();
2792 }
2793 
OnFileSave(cb_unused wxCommandEvent & event)2794 void MainFrame::OnFileSave(cb_unused wxCommandEvent& event)
2795 {
2796     if (!Manager::Get()->GetEditorManager()->SaveActive())
2797     {
2798         wxString msg;
2799         msg.Printf(_("File %s could not be saved..."), Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename().wx_str());
2800         cbMessageBox(msg, _("Error saving file"), wxICON_ERROR);
2801     }
2802     DoUpdateStatusBar();
2803 }
2804 
OnFileSaveAs(cb_unused wxCommandEvent & event)2805 void MainFrame::OnFileSaveAs(cb_unused wxCommandEvent& event)
2806 {
2807     Manager::Get()->GetEditorManager()->SaveActiveAs();
2808     DoUpdateStatusBar();
2809 }
2810 
OnFileSaveProject(cb_unused wxCommandEvent & event)2811 void MainFrame::OnFileSaveProject(cb_unused wxCommandEvent& event)
2812 {
2813     // no need to call SaveActiveProjectAs(), because this is handled in cbProject::Save()
2814     ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2815     if (prjManager->SaveActiveProject())
2816         m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2817     DoUpdateStatusBar();
2818     DoUpdateAppTitle();
2819 }
2820 
OnFileSaveProjectAs(cb_unused wxCommandEvent & event)2821 void MainFrame::OnFileSaveProjectAs(cb_unused wxCommandEvent& event)
2822 {
2823     ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2824     if (prjManager->SaveActiveProjectAs())
2825         m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2826     DoUpdateStatusBar();
2827     DoUpdateAppTitle();
2828 }
2829 
OnFileSaveAll(cb_unused wxCommandEvent & event)2830 void MainFrame::OnFileSaveAll(cb_unused wxCommandEvent& event)
2831 {
2832     Manager::Get()->GetConfigManager(_T("app"))->Flush();
2833     Manager::Get()->GetEditorManager()->SaveAll();
2834     ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2835     prjManager->SaveAllProjects();
2836 
2837     if (prjManager->GetWorkspace()->GetModified()
2838         && !prjManager->GetWorkspace()->IsDefault()
2839         && prjManager->SaveWorkspace())
2840     {
2841         m_projectsHistory.AddToHistory(prjManager->GetWorkspace()->GetFilename());
2842     }
2843     DoUpdateStatusBar();
2844     DoUpdateAppTitle();
2845 }
2846 
OnFileSaveProjectTemplate(cb_unused wxCommandEvent & event)2847 void MainFrame::OnFileSaveProjectTemplate(cb_unused wxCommandEvent& event)
2848 {
2849     TemplateManager::Get()->SaveUserTemplate(Manager::Get()->GetProjectManager()->GetActiveProject());
2850 }
2851 
OnFileCloseProject(cb_unused wxCommandEvent & event)2852 void MainFrame::OnFileCloseProject(cb_unused wxCommandEvent& event)
2853 {
2854     // we 're not actually shutting down here, but we want to check if the
2855     // active project is still opening files (still busy)
2856     if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
2857     {
2858         wxBell();
2859         return;
2860     }
2861     Manager::Get()->GetProjectManager()->CloseActiveProject();
2862     DoUpdateStatusBar();
2863 }
2864 
OnFileImportProjectDevCpp(cb_unused wxCommandEvent & event)2865 void MainFrame::OnFileImportProjectDevCpp(cb_unused wxCommandEvent& event)
2866 {
2867     OpenGeneric(ShowOpenFileDialog(_("Import Dev-C++ project"), FileFilters::GetFilterString(_T('.') + FileFilters::DEVCPP_EXT)), false);
2868 }
2869 
OnFileImportProjectMSVC(cb_unused wxCommandEvent & event)2870 void MainFrame::OnFileImportProjectMSVC(cb_unused wxCommandEvent& event)
2871 {
2872     OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_EXT)), false);
2873 }
2874 
OnFileImportProjectMSVCWksp(cb_unused wxCommandEvent & event)2875 void MainFrame::OnFileImportProjectMSVCWksp(cb_unused wxCommandEvent& event)
2876 {
2877     OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 workspace"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_WORKSPACE_EXT)), false);
2878 }
2879 
OnFileImportProjectMSVS(cb_unused wxCommandEvent & event)2880 void MainFrame::OnFileImportProjectMSVS(cb_unused wxCommandEvent& event)
2881 {
2882     OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_EXT)), false);
2883 }
2884 
OnFileImportProjectMSVSWksp(cb_unused wxCommandEvent & event)2885 void MainFrame::OnFileImportProjectMSVSWksp(cb_unused wxCommandEvent& event)
2886 {
2887     OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ solution"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_WORKSPACE_EXT)), false);
2888 }
2889 
OnFileOpenDefWorkspace(cb_unused wxCommandEvent & event)2890 void MainFrame::OnFileOpenDefWorkspace(cb_unused wxCommandEvent& event)
2891 {
2892     ProjectManager *pman = Manager::Get()->GetProjectManager();
2893     if (!pman->GetWorkspace()->IsDefault() && !pman->LoadWorkspace())
2894     {
2895         // do not add the default workspace in recent projects list
2896         // it's always one menu click away
2897         cbMessageBox(_("Can't open default workspace (file exists?)"), _("Warning"), wxICON_WARNING);
2898     }
2899 }
2900 
OnFileSaveWorkspace(cb_unused wxCommandEvent & event)2901 void MainFrame::OnFileSaveWorkspace(cb_unused wxCommandEvent& event)
2902 {
2903     ProjectManager *pman = Manager::Get()->GetProjectManager();
2904     if (pman->SaveWorkspace())
2905         m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2906 }
2907 
OnFileSaveWorkspaceAs(cb_unused wxCommandEvent & event)2908 void MainFrame::OnFileSaveWorkspaceAs(cb_unused wxCommandEvent& event)
2909 {
2910     ProjectManager *pman = Manager::Get()->GetProjectManager();
2911     if (pman->SaveWorkspaceAs(_T("")))
2912         m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2913 }
2914 
OnFileCloseWorkspace(cb_unused wxCommandEvent & event)2915 void MainFrame::OnFileCloseWorkspace(cb_unused wxCommandEvent& event)
2916 {
2917     DoCloseCurrentWorkspace();
2918 }
2919 
OnFileClose(cb_unused wxCommandEvent & event)2920 void MainFrame::OnFileClose(cb_unused wxCommandEvent& event)
2921 {
2922     Manager::Get()->GetEditorManager()->CloseActive();
2923     DoUpdateStatusBar();
2924     Refresh();
2925 }
2926 
OnFileCloseAll(cb_unused wxCommandEvent & event)2927 void MainFrame::OnFileCloseAll(cb_unused wxCommandEvent& event)
2928 {
2929     Manager::Get()->GetEditorManager()->CloseAll();
2930     DoUpdateStatusBar();
2931 }
2932 
OnFileNext(cb_unused wxCommandEvent & event)2933 void MainFrame::OnFileNext(cb_unused wxCommandEvent& event)
2934 {
2935     Manager::Get()->GetEditorManager()->ActivateNext();
2936     DoUpdateStatusBar();
2937 }
2938 
OnFilePrev(cb_unused wxCommandEvent & event)2939 void MainFrame::OnFilePrev(cb_unused wxCommandEvent& event)
2940 {
2941     Manager::Get()->GetEditorManager()->ActivatePrevious();
2942     DoUpdateStatusBar();
2943 }
2944 
OnFilePrint(cb_unused wxCommandEvent & event)2945 void MainFrame::OnFilePrint(cb_unused wxCommandEvent& event)
2946 {
2947     PrintDialog dlg(this);
2948     PlaceWindow(&dlg);
2949     if (dlg.ShowModal() == wxID_OK)
2950         Manager::Get()->GetEditorManager()->Print(dlg.GetPrintScope(), dlg.GetPrintColourMode(), dlg.GetPrintLineNumbers());
2951 }
2952 
OnFileQuit(cb_unused wxCommandEvent & event)2953 void MainFrame::OnFileQuit(cb_unused wxCommandEvent& event)
2954 {
2955     Close(false);
2956 }
2957 
OnEraseBackground(wxEraseEvent & event)2958 void MainFrame::OnEraseBackground(wxEraseEvent& event)
2959 {
2960     // for flicker-free display
2961     event.Skip();
2962 }
2963 
OnSize(wxSizeEvent & event)2964 void MainFrame::OnSize(wxSizeEvent& event)
2965 {
2966     // Highlightbutton
2967     if (m_pHighlightButton)
2968     {
2969         wxRect rect;
2970         if ( GetStatusBar()->GetFieldRect(1, rect) )
2971         {
2972             m_pHighlightButton->SetPosition(rect.GetPosition());
2973             m_pHighlightButton->SetSize(rect.GetSize());
2974         }
2975     }
2976 
2977     // for flicker-free display
2978     event.Skip();
2979 }
2980 
OnApplicationClose(wxCloseEvent & event)2981 void MainFrame::OnApplicationClose(wxCloseEvent& event)
2982 {
2983     if (m_InitiatedShutdown)
2984         return;
2985 
2986     CodeBlocksEvent evt(cbEVT_APP_START_SHUTDOWN);
2987     Manager::Get()->ProcessEvent(evt);
2988 
2989     m_InitiatedShutdown = true;
2990     Manager::BlockYields(true);
2991 
2992     {
2993         // Check if any compiler plugin is building and ask the user if he/she wants to stop it.
2994         bool hasRunning = cbHasRunningCompilers(Manager::Get()->GetPluginManager());
2995         if (hasRunning)
2996         {
2997             int result = cbMessageBox(_("Currently compiling. Stop compilation and exit?"),
2998                                       _("Question"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION,
2999                                       this);
3000             if (result == wxID_YES)
3001                 cbStopRunningCompilers(Manager::Get()->GetPluginManager());
3002             else
3003             {
3004                 event.Veto();
3005                 wxBell();
3006                 m_InitiatedShutdown = false;
3007                 Manager::BlockYields(false);
3008                 return;
3009             }
3010         }
3011     }
3012 
3013     if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
3014     {
3015         event.Veto();
3016         wxBell();
3017         m_InitiatedShutdown = false;
3018         Manager::BlockYields(false);
3019         return;
3020     }
3021 
3022     if (!DoCloseCurrentWorkspace())
3023     {
3024         event.Veto();
3025         m_InitiatedShutdown = false;
3026         Manager::BlockYields(false);
3027         return;
3028     }
3029 
3030     Manager::SetAppShuttingDown(true);
3031 
3032     Manager::Get()->GetLogManager()->DebugLog(_T("Deinitializing plugins..."));
3033     CodeBlocksEvent evtShutdown(cbEVT_APP_START_SHUTDOWN);
3034     Manager::Get()->ProcessEvent(evtShutdown);
3035     Manager::Yield();
3036 
3037     if (!Manager::IsBatchBuild())
3038         SaveWindowState();
3039 
3040     if (m_pPrjManUI->GetNotebook())
3041         m_LayoutManager.DetachPane(m_pPrjManUI->GetNotebook());
3042     m_LayoutManager.DetachPane(m_pInfoPane);
3043     m_LayoutManager.DetachPane(Manager::Get()->GetEditorManager()->GetNotebook());
3044 
3045     m_LayoutManager.UnInit();
3046     TerminateRecentFilesHistory();
3047 
3048     // remove all other event handlers from this window
3049     // this stops it from crashing, when no plugins are loaded
3050     while (GetEventHandler() != this)
3051         PopEventHandler(false);
3052 
3053     // Hide the window
3054     Hide();
3055 
3056     if (!Manager::IsBatchBuild())
3057     {
3058         m_pInfoPane->Destroy();
3059         m_pInfoPane = nullptr;
3060     }
3061 
3062     // Disconnect the mouse right click event handler for toolbars, this should be done before the plugin is
3063     // unloaded in Manager::Shutdown().
3064     PluginToolbarsMap::iterator it;
3065     for( it = m_PluginsTools.begin(); it != m_PluginsTools.end(); ++it )
3066     {
3067         wxToolBar* toolbar = it->second;
3068         if (toolbar)//Disconnect the mouse right click event handler before the toolbar is destroyed
3069         {
3070             bool result = toolbar->Disconnect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick));
3071             cbAssert(result);
3072         }
3073     }
3074 
3075     Manager::Shutdown(); // Shutdown() is not Free(), Manager is automatically destroyed at exit
3076 
3077     Destroy();
3078 }
3079 
OnEditSwapHeaderSource(cb_unused wxCommandEvent & event)3080 void MainFrame::OnEditSwapHeaderSource(cb_unused wxCommandEvent& event)
3081 {
3082     Manager::Get()->GetEditorManager()->SwapActiveHeaderSource();
3083     DoUpdateStatusBar();
3084 }
3085 
OnEditGotoMatchingBrace(cb_unused wxCommandEvent & event)3086 void MainFrame::OnEditGotoMatchingBrace(cb_unused wxCommandEvent& event)
3087 {
3088     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3089     if (ed)
3090         ed->GotoMatchingBrace();
3091 }
3092 
OnEditBookmarksToggle(cb_unused wxCommandEvent & event)3093 void MainFrame::OnEditBookmarksToggle(cb_unused wxCommandEvent& event)
3094 {
3095     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3096     if (ed && ed->IsBuiltinEditor())
3097         static_cast<cbEditor*>(ed)->ToggleBookmark();
3098 }
3099 
OnEditBookmarksNext(cb_unused wxCommandEvent & event)3100 void MainFrame::OnEditBookmarksNext(cb_unused wxCommandEvent& event)
3101 {
3102     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3103     if (ed && ed->IsBuiltinEditor())
3104         static_cast<cbEditor*>(ed)->GotoNextBookmark();
3105 }
3106 
OnEditBookmarksPrevious(cb_unused wxCommandEvent & event)3107 void MainFrame::OnEditBookmarksPrevious(cb_unused wxCommandEvent& event)
3108 {
3109     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3110     if (ed && ed->IsBuiltinEditor())
3111         static_cast<cbEditor*>(ed)->GotoPreviousBookmark();
3112 }
3113 
OnEditBookmarksClearAll(cb_unused wxCommandEvent & event)3114 void MainFrame::OnEditBookmarksClearAll(cb_unused wxCommandEvent& event)
3115 {
3116     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3117     if (ed && ed->IsBuiltinEditor())
3118         static_cast<cbEditor*>(ed)->ClearAllBookmarks();
3119 }
3120 
OnEditUndo(cb_unused wxCommandEvent & event)3121 void MainFrame::OnEditUndo(cb_unused wxCommandEvent& event)
3122 {
3123     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3124     if (ed && ed->CanUndo())
3125     {
3126         cbEditor* cbEd = Manager::Get()->GetEditorManager()->GetBuiltinEditor(ed);
3127         if (cbEd && cbEd->GetControl()->AutoCompActive())
3128             cbEd->GetControl()->AutoCompCancel();
3129         ed->Undo();
3130     }
3131 }
3132 
OnEditRedo(cb_unused wxCommandEvent & event)3133 void MainFrame::OnEditRedo(cb_unused wxCommandEvent& event)
3134 {
3135     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3136     if (ed)
3137         ed->Redo();
3138 }
3139 
OnEditClearHistory(cb_unused wxCommandEvent & event)3140 void MainFrame::OnEditClearHistory(cb_unused wxCommandEvent& event)
3141 {
3142     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3143     if (ed)
3144         ed->ClearHistory();
3145 }
3146 
OnEditCopy(cb_unused wxCommandEvent & event)3147 void MainFrame::OnEditCopy(cb_unused wxCommandEvent& event)
3148 {
3149     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3150     if (ed)
3151         ed->Copy();
3152 }
3153 
OnEditCut(cb_unused wxCommandEvent & event)3154 void MainFrame::OnEditCut(cb_unused wxCommandEvent& event)
3155 {
3156     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3157     if (ed)
3158         ed->Cut();
3159 }
3160 
OnEditPaste(cb_unused wxCommandEvent & event)3161 void MainFrame::OnEditPaste(cb_unused wxCommandEvent& event)
3162 {
3163     EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3164     if (ed)
3165         ed->Paste();
3166 }
3167 
OnEditParaUp(cb_unused wxCommandEvent & event)3168 void MainFrame::OnEditParaUp(cb_unused wxCommandEvent& event)
3169 {
3170     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3171     if (ed)
3172         ed->GetControl()->ParaUp();
3173 }
3174 
OnEditParaUpExtend(cb_unused wxCommandEvent & event)3175 void MainFrame::OnEditParaUpExtend(cb_unused wxCommandEvent& event)
3176 {
3177     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3178     if (ed)
3179         ed->GetControl()->ParaUpExtend();
3180 }
3181 
OnEditParaDown(cb_unused wxCommandEvent & event)3182 void MainFrame::OnEditParaDown(cb_unused wxCommandEvent& event)
3183 {
3184     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3185     if (ed)
3186         ed->GetControl()->ParaDown();
3187 }
3188 
OnEditParaDownExtend(cb_unused wxCommandEvent & event)3189 void MainFrame::OnEditParaDownExtend(cb_unused wxCommandEvent& event)
3190 {
3191     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3192     if (ed)
3193         ed->GetControl()->ParaDownExtend();
3194 }
3195 
OnEditWordPartLeft(cb_unused wxCommandEvent & event)3196 void MainFrame::OnEditWordPartLeft(cb_unused wxCommandEvent& event)
3197 {
3198     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3199     if (ed)
3200         ed->GetControl()->WordPartLeft();
3201 }
3202 
OnEditWordPartLeftExtend(cb_unused wxCommandEvent & event)3203 void MainFrame::OnEditWordPartLeftExtend(cb_unused wxCommandEvent& event)
3204 {
3205     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3206     if (ed)
3207         ed->GetControl()->WordPartLeftExtend();
3208 }
3209 
OnEditWordPartRight(cb_unused wxCommandEvent & event)3210 void MainFrame::OnEditWordPartRight(cb_unused wxCommandEvent& event)
3211 {
3212     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3213     if (ed)
3214         ed->GetControl()->WordPartRight();
3215 }
3216 
OnEditWordPartRightExtend(cb_unused wxCommandEvent & event)3217 void MainFrame::OnEditWordPartRightExtend(cb_unused wxCommandEvent& event)
3218 {
3219     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3220     if (ed)
3221         ed->GetControl()->WordPartRightExtend();
3222 }
3223 
OnEditZoomIn(cb_unused wxCommandEvent & event)3224 void MainFrame::OnEditZoomIn(cb_unused wxCommandEvent& event)
3225 {
3226     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3227     if (ed)
3228         ed->GetControl()->ZoomIn();
3229 }
3230 
OnEditZoomOut(cb_unused wxCommandEvent & event)3231 void MainFrame::OnEditZoomOut(cb_unused wxCommandEvent& event)
3232 {
3233     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3234     if (ed)
3235         ed->GetControl()->ZoomOut();
3236 }
3237 
OnEditZoomReset(cb_unused wxCommandEvent & event)3238 void MainFrame::OnEditZoomReset(cb_unused wxCommandEvent& event)
3239 {
3240     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3241     if (ed)
3242         ed->GetControl()->SetZoom(0);
3243 }
3244 
OnEditLineCut(cb_unused wxCommandEvent & event)3245 void MainFrame::OnEditLineCut(cb_unused wxCommandEvent& event)
3246 {
3247     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3248     if (ed)
3249         ed->GetControl()->LineCut();
3250 }
3251 
OnEditLineDelete(cb_unused wxCommandEvent & event)3252 void MainFrame::OnEditLineDelete(cb_unused wxCommandEvent& event)
3253 {
3254     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3255     if (ed)
3256         ed->GetControl()->LineDelete();
3257 }
3258 
OnEditLineDuplicate(cb_unused wxCommandEvent & event)3259 void MainFrame::OnEditLineDuplicate(cb_unused wxCommandEvent& event)
3260 {
3261     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3262     if (ed)
3263         ed->GetControl()->LineDuplicate();
3264 }
3265 
OnEditLineTranspose(cb_unused wxCommandEvent & event)3266 void MainFrame::OnEditLineTranspose(cb_unused wxCommandEvent& event)
3267 {
3268     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3269     if (ed)
3270         ed->GetControl()->LineTranspose();
3271 }
3272 
OnEditLineCopy(cb_unused wxCommandEvent & event)3273 void MainFrame::OnEditLineCopy(cb_unused wxCommandEvent& event)
3274 {
3275     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3276     if (ed)
3277         ed->GetControl()->LineCopy();
3278 }
3279 
OnEditLinePaste(cb_unused wxCommandEvent & event)3280 void MainFrame::OnEditLinePaste(cb_unused wxCommandEvent& event)
3281 {
3282     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3283     if (ed)
3284     {
3285         //We want to undo all in one step
3286         ed->GetControl()->BeginUndoAction();
3287 
3288         int pos = ed->GetControl()->GetCurrentPos();
3289         int line = ed->GetControl()->LineFromPosition(pos);
3290         ed->GetControl()->GotoLine(line);
3291         int column = pos - ed->GetControl()->GetCurrentPos();
3292         ed->GetControl()->Paste();
3293         pos = ed->GetControl()->GetCurrentPos();
3294         ed->GetControl()->GotoPos(pos+column);
3295 
3296         ed->GetControl()->EndUndoAction();
3297     }
3298 }
3299 
OnEditLineMove(wxCommandEvent & event)3300 void MainFrame::OnEditLineMove(wxCommandEvent& event)
3301 {
3302     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3303     if (!ed)
3304         return;
3305 
3306     // TODO (mortenmacfly##): Exclude rectangle selection here or not? What behaviour the majority of users expect here???
3307     cbStyledTextCtrl* stc = ed->GetControl();
3308     if (!stc || /*stc->SelectionIsRectangle() ||*/ (stc->GetSelections() > 1))
3309         return;
3310     if (stc->GetLineCount() < 3) // why are you trying to move lines anyways?
3311         return;
3312 
3313     // note that these function calls are a much simpler, however
3314     // they cause text to unnecessarily be marked as modified
3315 //    if (event.GetId() == idEditLineUp)
3316 //        stc->MoveSelectedLinesUp();
3317 //    else
3318 //        stc->MoveSelectedLinesDown();
3319 
3320     int startPos = stc->PositionFromLine(stc->LineFromPosition(stc->GetSelectionStart()));
3321     int endPos   = stc->LineFromPosition(stc->GetSelectionEnd()); // is line
3322     if (   stc->GetSelectionEnd() == stc->PositionFromLine(endPos)          // end is in first column
3323         && stc->PositionFromLine(endPos) != stc->GetLineEndPosition(endPos) // this line has text
3324         && endPos > stc->LineFromPosition(startPos) )                       // start and end are on different lines
3325     {
3326         --endPos; // do not unexpectedly select another line
3327     }
3328     const bool isLastLine = (endPos == stc->GetLineCount() - 1);
3329     // warning: stc->GetLineEndPosition(endPos) yields strange results for CR LF (see bug 18892)
3330     endPos = (  isLastLine ? stc->GetLineEndPosition(endPos)
3331               : stc->PositionFromLine(endPos + 1) - 1 ); // is position
3332     if (event.GetId() == idEditLineUp)
3333     {
3334         if (stc->LineFromPosition(startPos) < 1)
3335             return; // cannot move up (we are at the top), exit
3336         stc->BeginUndoAction();
3337         const int offset     = (isLastLine ? startPos - stc->GetLineEndPosition(stc->LineFromPosition(startPos) - 1) : 0);
3338         const int lineLength = startPos - stc->PositionFromLine(stc->LineFromPosition(startPos) - 1);
3339         const wxString line  = stc->GetTextRange(startPos - lineLength - offset,
3340                                                  startPos - offset);
3341         stc->InsertText(endPos + (isLastLine ? 0 : 1), line);
3342         // warning: line.Length() != lineLength if multibyte characters are used
3343         stc->DeleteRange(startPos - lineLength, lineLength);
3344         startPos -= lineLength;
3345         endPos   -= lineLength;
3346         stc->EndUndoAction();
3347     }
3348     else // event.GetId() == idEditLineDown
3349     {
3350         if (isLastLine)
3351             return; // cannot move down (we are at the bottom), exit
3352         stc->BeginUndoAction();
3353         const int lineLength = stc->PositionFromLine(stc->LineFromPosition(endPos + 1) + 1) - endPos - 1;
3354         const wxString line  = stc->GetTextRange(endPos + 1,
3355                                                  endPos + 1 + lineLength);
3356         stc->InsertText(startPos, line);
3357         // warning: line.Length() != lineLength if multibyte characters are used
3358         startPos += lineLength;
3359         endPos   += lineLength;
3360         stc->DeleteRange(endPos + 1, lineLength);
3361         stc->EndUndoAction();
3362     }
3363     stc->SetSelectionVoid(startPos, endPos);
3364 }
3365 
OnEditUpperCase(cb_unused wxCommandEvent & event)3366 void MainFrame::OnEditUpperCase(cb_unused wxCommandEvent& event)
3367 {
3368     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3369     if (ed)
3370         ed->GetControl()->UpperCase();
3371 }
3372 
OnEditLowerCase(cb_unused wxCommandEvent & event)3373 void MainFrame::OnEditLowerCase(cb_unused wxCommandEvent& event)
3374 {
3375     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3376     if (ed)
3377         ed->GetControl()->LowerCase();
3378 }
3379 
OnEditInsertNewLine(wxCommandEvent & event)3380 void MainFrame::OnEditInsertNewLine(wxCommandEvent& event)
3381 {
3382     OnEditGotoLineEnd(event);
3383     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3384     if (ed)
3385     {
3386         cbStyledTextCtrl* stc = ed->GetControl();
3387         if (stc->AutoCompActive())
3388             stc->AutoCompCancel();
3389         stc->NewLine();
3390     }
3391 }
3392 
OnEditGotoLineEnd(cb_unused wxCommandEvent & event)3393 void MainFrame::OnEditGotoLineEnd(cb_unused wxCommandEvent& event)
3394 {
3395     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3396     if (ed)
3397     {
3398         cbStyledTextCtrl* stc = ed->GetControl();
3399         if (stc->AutoCompActive())
3400             stc->AutoCompCancel();
3401         stc->LineEnd();
3402     }
3403 }
3404 
InsertNewLine(bool below)3405 static void InsertNewLine(bool below)
3406 {
3407     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3408     if (ed)
3409     {
3410         cbStyledTextCtrl* stc = ed->GetControl();
3411         stc->BeginUndoAction();
3412         if (stc->AutoCompActive())
3413             stc->AutoCompCancel();
3414 
3415         if (below)
3416         {
3417             stc->LineEndDisplay();
3418             int pos = stc->GetCurrentPos();
3419             stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3420             stc->LineDown();
3421         }
3422         else
3423         {
3424             stc->HomeDisplay();
3425             int pos = stc->GetCurrentPos();
3426             stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3427             stc->EndUndoAction();
3428         }
3429         stc->EndUndoAction();
3430     }
3431 }
3432 
OnEditInsertNewLineBelow(cb_unused wxCommandEvent & event)3433 void MainFrame::OnEditInsertNewLineBelow(cb_unused wxCommandEvent& event)
3434 {
3435     InsertNewLine(true);
3436 }
3437 
OnEditInsertNewLineAbove(cb_unused wxCommandEvent & event)3438 void MainFrame::OnEditInsertNewLineAbove(cb_unused wxCommandEvent& event)
3439 {
3440     InsertNewLine(false);
3441 }
3442 
OnEditSelectAll(cb_unused wxCommandEvent & event)3443 void MainFrame::OnEditSelectAll(cb_unused wxCommandEvent& event)
3444 {
3445     EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3446     if (eb)
3447         eb->SelectAll();
3448 }
3449 
3450 namespace
3451 {
3452 
3453 struct EditorSelection
3454 {
3455     long caret, anchor;
3456 
Empty__anon5b41abdd0311::EditorSelection3457     bool Empty() const { return caret == anchor; }
IsReversed__anon5b41abdd0311::EditorSelection3458     bool IsReversed() const { return caret < anchor; }
3459 
GetStart__anon5b41abdd0311::EditorSelection3460     long GetStart() const { return std::min(caret, anchor); }
GetEnd__anon5b41abdd0311::EditorSelection3461     long GetEnd() const { return std::max(caret, anchor); }
3462 
Contains__anon5b41abdd0311::EditorSelection3463     bool Contains(const EditorSelection &selection) const
3464     {
3465         return !(GetEnd() < selection.GetStart() || GetStart() > selection.GetEnd());
3466     }
3467 };
3468 
SelectNext(cbStyledTextCtrl * control,const wxString & selectedText,long selectionEnd,bool reversed)3469 bool SelectNext(cbStyledTextCtrl *control, const wxString &selectedText, long selectionEnd, bool reversed)
3470 {
3471     // always match case and try to match whole words if they have no special characters
3472     int flag = wxSCI_FIND_MATCHCASE;
3473     if (selectedText.find_first_of(wxT(";:\"'`~@#$%^,-+*/\\=|!?&*(){}[]")) == wxString::npos)
3474         flag |= wxSCI_FIND_WHOLEWORD;
3475 
3476     int endPos = 0; // we need this to work properly with multibyte characters
3477     int eof = control->GetLength();
3478     int pos = control->FindText(selectionEnd, eof, selectedText, flag, &endPos);
3479     if (pos != wxSCI_INVALID_POSITION)
3480     {
3481         control->SetAdditionalSelectionTyping(true);
3482         control->SetMultiPaste(true);
3483         control->IndicatorClearRange(pos, endPos - pos);
3484         if (reversed)
3485             control->AddSelection(pos, endPos);
3486         else
3487             control->AddSelection(endPos, pos);
3488         control->MakeNearbyLinesVisible(control->LineFromPosition(pos));
3489         return true;
3490     }
3491     else
3492     {
3493         InfoWindow::Display(_("Select Next Occurrence"), _("No more available"));
3494         return false;
3495     }
3496 }
3497 
GetSelectionInEditor(EditorSelection & selection,cbStyledTextCtrl * control)3498 bool GetSelectionInEditor(EditorSelection &selection, cbStyledTextCtrl *control)
3499 {
3500     int main = control->GetMainSelection();
3501     int count = control->GetSelections();
3502     if (main >=0 && main < count)
3503     {
3504         selection.caret = control->GetSelectionNCaret(main);
3505         selection.anchor = control->GetSelectionNAnchor(main);
3506         return true;
3507     }
3508     else
3509         return false;
3510 }
3511 
3512 } // anonymous namespace
3513 
OnEditSelectNext(cb_unused wxCommandEvent & event)3514 void MainFrame::OnEditSelectNext(cb_unused wxCommandEvent& event)
3515 {
3516     EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3517     if (!eb || !eb->IsBuiltinEditor())
3518         return;
3519     cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3520 
3521     EditorSelection selection;
3522     if (!GetSelectionInEditor(selection, control))
3523         return;
3524 
3525     if (!selection.Empty())
3526     {
3527         const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3528         SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed());
3529     }
3530     else
3531     {
3532         // Select word at the cursor position if there is nothing selected.
3533         const int start = control->WordStartPosition(selection.caret, true);
3534         const int end = control->WordEndPosition(selection.caret, true);
3535         control->SetSelection(start, end);
3536     }
3537 }
3538 
OnEditSelectNextSkip(cb_unused wxCommandEvent & event)3539 void MainFrame::OnEditSelectNextSkip(cb_unused wxCommandEvent& event)
3540 {
3541     EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3542     if (!eb || !eb->IsBuiltinEditor())
3543         return;
3544     cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3545 
3546     EditorSelection selection;
3547     if (!GetSelectionInEditor(selection, control))
3548         return;
3549 
3550     ConfigManager *cfgEditor = Manager::Get()->GetConfigManager(wxT("editor"));
3551     bool highlightOccurrences = cfgEditor->ReadBool(wxT("/highlight_occurrence/enabled"), true);
3552 
3553     // Select the next occurrence first. This prevents a cursor created at the beginning of the
3554     // file when the user uses the command when there is a single selection. Scintilla always makes
3555     // sure that there is at least one selection/cursor. So if we clear all selections it creates a
3556     // cursor at the beginning of the file.
3557     const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3558     if (!SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed()))
3559         return; // If there is no new selection don't deselect the current one.
3560 
3561     // store the selections in a vector except for the current one
3562     typedef std::vector<EditorSelection> Selections;
3563     Selections selections;
3564     int count = control->GetSelections();
3565     for (int ii = 0; ii < count; ++ii)
3566     {
3567         EditorSelection item;
3568         item.caret = control->GetSelectionNCaret(ii);
3569         item.anchor = control->GetSelectionNAnchor(ii);
3570 
3571         if (!item.Contains(selection))
3572             selections.push_back(item);
3573         else if (highlightOccurrences)
3574         {
3575             // Restore the indicator for the highlight occurrences if they are enabled.
3576             control->IndicatorFillRange(item.GetStart(), item.GetEnd());
3577         }
3578     }
3579 
3580     control->ClearSelections();
3581     Selections::const_iterator it = selections.begin();
3582     int index = 0;
3583     if (it != selections.end() && control->GetSelections() > 0)
3584     {
3585         control->SetSelectionNAnchor(index, it->anchor);
3586         control->SetSelectionNCaret(index, it->caret);
3587         ++index;
3588         ++it;
3589     }
3590     for (; it != selections.end(); ++it)
3591     {
3592         control->AddSelection(it->caret, it->anchor);
3593         ++index;
3594     }
3595 }
3596 
3597 /* This is a shameless rip-off of the original OnEditCommentSelected function,
3598  * now more suitingly named OnEditToggleCommentSelected (because that's what
3599  * it does :)
3600  */
OnEditCommentSelected(cb_unused wxCommandEvent & event)3601 void MainFrame::OnEditCommentSelected(cb_unused wxCommandEvent& event)
3602 {
3603     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3604     if (!ed)
3605         return;
3606 
3607     cbStyledTextCtrl* stc = ed->GetControl();
3608     if (!stc)
3609         return;
3610 
3611     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3612     if (!colour_set)
3613         return;
3614 
3615     CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3616     if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3617         return;
3618 
3619     stc->BeginUndoAction();
3620     if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3621     {
3622         int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3623         int endLine   = stc->LineFromPosition( stc->GetSelectionEnd() );
3624         int curLine=startLine;
3625         /**
3626             Fix a glitch: when selecting multiple lines and the caret
3627             is at the start of the line after the last line selected,
3628             the code would, wrongly, (un)comment that line too.
3629             This fixes it.
3630         */
3631         if (startLine != endLine && // selection is more than one line
3632             stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3633         {
3634             // don't take into account the line the caret is on,
3635             // because it contains no selection (caret_column == 0)...
3636             --endLine;
3637         }
3638 
3639         while( curLine <= endLine )
3640         {
3641             // For each line: comment.
3642             if (comment.lineComment!=wxEmptyString)
3643                 stc->InsertText( stc->PositionFromLine( curLine ), comment.lineComment );
3644             else // if the language doesn't support line comments use stream comments
3645             {
3646                 stc->InsertText( stc->PositionFromLine( curLine ), comment.streamCommentStart );
3647                 stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd );
3648             }
3649             ++curLine;
3650         } // end while
3651         stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3652     }
3653     stc->EndUndoAction();
3654 }
3655 
3656 /* See above (OnEditCommentSelected) for details. */
OnEditUncommentSelected(cb_unused wxCommandEvent & event)3657 void MainFrame::OnEditUncommentSelected(cb_unused wxCommandEvent& event)
3658 {
3659     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3660     if (!ed)
3661         return;
3662 
3663     cbStyledTextCtrl* stc = ed->GetControl();
3664     if (!stc)
3665         return;
3666 
3667     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3668     if (!colour_set)
3669         return;
3670 
3671     CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3672     if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3673         return;
3674 
3675     stc->BeginUndoAction();
3676     if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3677     {
3678         int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3679         int endLine   = stc->LineFromPosition( stc->GetSelectionEnd() );
3680         int curLine   = startLine;
3681         /**
3682             Fix a glitch: when selecting multiple lines and the caret
3683             is at the start of the line after the last line selected,
3684             the code would, wrongly, (un)comment that line too.
3685             This fixes it.
3686         */
3687         if (startLine != endLine && // selection is more than one line
3688         stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3689         {
3690             // don't take into account the line the caret is on,
3691             // because it contains no selection (caret_column == 0)...
3692             --endLine;
3693         }
3694 
3695         while( curLine <= endLine )
3696         {
3697             // For each line: if it is commented, uncomment.
3698             wxString strLine = stc->GetLine( curLine );
3699 
3700             bool startsWithComment;
3701             bool endsWithComment;
3702 
3703             // check for line comment
3704             startsWithComment = strLine.Strip( wxString::leading ).StartsWith( comment.lineComment );
3705             if ( startsWithComment )
3706             {      // we know the comment is there (maybe preceded by white space)
3707                 int Pos = strLine.Find(comment.lineComment);
3708                 int start = stc->PositionFromLine( curLine ) + Pos;
3709                 int end = start + comment.lineComment.Length();
3710                 stc->SetTargetStart( start );
3711                 stc->SetTargetEnd( end );
3712                 stc->ReplaceTarget( wxEmptyString );
3713             }
3714 
3715             // check for stream comment
3716             startsWithComment = strLine.Strip( wxString::leading  ).StartsWith( comment.streamCommentStart ); // check for stream comment start
3717             endsWithComment = strLine.Strip( wxString::trailing ).EndsWith( comment.streamCommentEnd); // check for stream comment end
3718             if ( startsWithComment && endsWithComment )
3719             {
3720                 int Pos;
3721                 int start;
3722                 int end;
3723 
3724                 // we know the start comment is there (maybe preceded by white space)
3725                 Pos = strLine.Find(comment.streamCommentStart);
3726                 start = stc->PositionFromLine( curLine ) + Pos;
3727                 end = start + comment.streamCommentStart.Length();
3728                 stc->SetTargetStart( start );
3729                 stc->SetTargetEnd( end );
3730                 stc->ReplaceTarget( wxEmptyString );
3731 
3732                 // we know the end comment is there too (maybe followed by white space)
3733                 // attention!! we have to subtract the length of the comment we already removed
3734                 Pos = strLine.rfind(comment.streamCommentEnd,strLine.npos) - comment.streamCommentStart.Length();
3735                 start = stc->PositionFromLine( curLine ) + Pos;
3736                 end = start + comment.streamCommentEnd.Length();
3737                 stc->SetTargetStart( start );
3738                 stc->SetTargetEnd( end );
3739                 stc->ReplaceTarget( wxEmptyString );
3740             }
3741             ++curLine;
3742         } // end while
3743         stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3744     }
3745     stc->EndUndoAction();
3746 }
3747 
OnEditToggleCommentSelected(cb_unused wxCommandEvent & event)3748 void MainFrame::OnEditToggleCommentSelected(cb_unused wxCommandEvent& event)
3749 {
3750     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3751     if (!ed)
3752         return;
3753 
3754     cbStyledTextCtrl* stc = ed->GetControl();
3755     if (!stc)
3756         return;
3757 
3758     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3759     if (!colour_set)
3760         return;
3761 
3762     wxString comment = colour_set->GetCommentToken( ed->GetLanguage() ).lineComment;
3763     if (comment==wxEmptyString)
3764         return;
3765 
3766     stc->BeginUndoAction();
3767     if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3768     {
3769         int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3770         int endLine   = stc->LineFromPosition( stc->GetSelectionEnd() );
3771         int curLine   = startLine;
3772         /**
3773             Fix a glitch: when selecting multiple lines and the caret
3774             is at the start of the line after the last line selected,
3775             the code would, wrongly, (un)comment that line too.
3776             This fixes it.
3777         */
3778         if (startLine != endLine && // selection is more than one line
3779         stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3780         {
3781             // don't take into account the line the caret is on,
3782             // because it contains no selection (caret_column == 0)...
3783             --endLine;
3784         }
3785 
3786         bool doComment = false;
3787         while( curLine <= endLine )
3788         {
3789             // Check is any of the selected lines is commented
3790             wxString strLine = stc->GetLine( curLine );
3791             int commentPos = strLine.Strip( wxString::leading ).Find( comment );
3792 
3793             if (commentPos != 0)
3794             {
3795                 // At least one line is not commented, so comment the whole selection
3796                 // (else if all lines are commented, uncomment the selection)
3797                 doComment = true;
3798                 break;
3799             }
3800             ++curLine;
3801         }
3802 
3803         curLine = startLine;
3804         while( curLine <= endLine )
3805         {
3806             if (doComment)
3807                 stc->InsertText( stc->PositionFromLine( curLine ), comment );
3808             else
3809             {
3810                 // we know the comment is there (maybe preceded by white space)
3811                 wxString strLine = stc->GetLine( curLine );
3812                 int Pos = strLine.Find(comment);
3813                 int start = stc->PositionFromLine( curLine ) + Pos;
3814                 int end = start + comment.Length();
3815                 stc->SetTargetStart( start );
3816                 stc->SetTargetEnd( end );
3817                 stc->ReplaceTarget( wxEmptyString );
3818             }
3819             ++curLine;
3820         }
3821         stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3822     }
3823     stc->EndUndoAction();
3824 }
3825 
OnEditStreamCommentSelected(cb_unused wxCommandEvent & event)3826 void MainFrame::OnEditStreamCommentSelected(cb_unused wxCommandEvent& event)
3827 {
3828     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3829     if (!ed)
3830         return;
3831 
3832     cbStyledTextCtrl* stc = ed->GetControl();
3833     if (!stc)
3834         return;
3835 
3836     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3837     if (!colour_set)
3838         return;
3839 
3840     CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3841     if (comment.streamCommentStart==wxEmptyString)
3842         return;
3843 
3844     stc->BeginUndoAction();
3845     if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3846     {
3847         int startPos = stc->GetSelectionStart();
3848         int endPos   = stc->GetSelectionEnd();
3849         if ( startPos == endPos )
3850         {   // if nothing selected stream comment current *word* first
3851             startPos = stc->WordStartPosition(stc->GetCurrentPos(), true);
3852             endPos   = stc->WordEndPosition  (stc->GetCurrentPos(), true);
3853             if ( startPos == endPos )
3854             {   // if nothing selected stream comment current *line*
3855                 startPos = stc->PositionFromLine  (stc->LineFromPosition(startPos));
3856                 endPos   = stc->GetLineEndPosition(stc->LineFromPosition(startPos));
3857             }
3858         }
3859         else
3860         {
3861             /**
3862                 Fix a glitch: when selecting multiple lines and the caret
3863                 is at the start of the line after the last line selected,
3864                 the code would, wrongly, (un)comment that line too.
3865                 This fixes it.
3866             */
3867             if (stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3868             {
3869                 // don't take into account the line the caret is on,
3870                 // because it contains no selection (caret_column == 0)...
3871                 --endPos;
3872             }
3873         }
3874         // stream comment block
3875         int p1 = startPos - 1;
3876         while (stc->GetCharAt(p1) == _T(' ') && p1 > 0)
3877             --p1;
3878         p1 -= 1;
3879         int p2 = endPos;
3880         while (stc->GetCharAt(p2) == _T(' ') && p2 < stc->GetLength())
3881             ++p2;
3882         const wxString start = stc->GetTextRange(p1, p1 + comment.streamCommentStart.Length());
3883         const wxString end = stc->GetTextRange(p2, p2 + comment.streamCommentEnd.Length());
3884         if (start == comment.streamCommentStart && end == comment.streamCommentEnd)
3885         {
3886             stc->SetTargetStart(p1);
3887             stc->SetTargetEnd(p2 + 2);
3888             wxString target = stc->GetTextRange(p1 + 2, p2);
3889             stc->ReplaceTarget(target);
3890             stc->GotoPos(p1 + target.Length());
3891         }
3892         else
3893         {
3894             stc->InsertText( startPos, comment.streamCommentStart );
3895             // we already inserted some characters so out endPos changed
3896             startPos += comment.streamCommentStart.Length();
3897             endPos += comment.streamCommentStart.Length();
3898             stc->InsertText( endPos, comment.streamCommentEnd );
3899             stc->SetSelectionVoid(startPos,endPos);
3900         }
3901 
3902     }
3903     stc->EndUndoAction();
3904 }
3905 
OnEditBoxCommentSelected(cb_unused wxCommandEvent & event)3906 void MainFrame::OnEditBoxCommentSelected(cb_unused wxCommandEvent& event)
3907 {
3908     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3909     if (!ed)
3910         return;
3911 
3912     cbStyledTextCtrl* stc = ed->GetControl();
3913     if (!stc)
3914         return;
3915 
3916     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3917     if (!colour_set)
3918         return;
3919 
3920     CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3921     if (comment.boxCommentStart==wxEmptyString)
3922         return;
3923 
3924     stc->BeginUndoAction();
3925     if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3926     {
3927         int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3928         int endLine   = stc->LineFromPosition( stc->GetSelectionEnd() );
3929         int curLine   = startLine;
3930         /**
3931             Fix a glitch: when selecting multiple lines and the caret
3932             is at the start of the line after the last line selected,
3933             the code would, wrongly, (un)comment that line too.
3934             This fixes it.
3935         */
3936         if (startLine != endLine && // selection is more than one line
3937         stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3938         {
3939             // don't take into account the line the caret is on,
3940             // because it contains no selection (caret_column == 0)...
3941             --endLine;
3942         }
3943 
3944 
3945 
3946         if (startLine == endLine) // if selection is only one line ...
3947         {
3948             // ... then insert streamcomment tokens at the beginning and the end of the line
3949             stc->InsertText( stc->PositionFromLine  ( curLine ), comment.streamCommentStart );
3950             stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd   );
3951         }
3952         else // selection is more than one line
3953         {
3954             // insert boxcomment start token
3955             stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentStart );
3956             ++curLine; // we already commented the first line about 9 lines above
3957             while( curLine <= endLine )
3958             {
3959                 // For each line: comment.
3960                 stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentMid );
3961                 ++curLine;
3962             } // end while
3963 
3964             // insert boxcomment end token and add a new line character
3965             stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentEnd + GetEOLStr(stc->GetEOLMode()) );
3966         } // end if
3967         stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3968     }
3969     stc->EndUndoAction();
3970 }
3971 
OnEditShowCallTip(cb_unused wxCommandEvent & event)3972 void MainFrame::OnEditShowCallTip(cb_unused wxCommandEvent& event)
3973 {
3974     CodeBlocksEvent evt(cbEVT_SHOW_CALL_TIP);
3975     Manager::Get()->ProcessEvent(evt);
3976 }
3977 
OnEditCompleteCode(cb_unused wxCommandEvent & event)3978 void MainFrame::OnEditCompleteCode(cb_unused wxCommandEvent& event)
3979 {
3980     CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
3981     Manager::Get()->ProcessEvent(evt);
3982 }
3983 
OnEditHighlightMode(wxCommandEvent & event)3984 void MainFrame::OnEditHighlightMode(wxCommandEvent& event)
3985 {
3986     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3987     if (!ed)
3988         return;
3989 
3990     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3991     if (!colour_set)
3992         return;
3993 
3994     HighlightLanguage lang = colour_set->GetHighlightLanguage(_T(""));
3995     if (event.GetId() != idEditHighlightModeText)
3996     {
3997         wxMenu* hl = nullptr;
3998         GetMenuBar()->FindItem(idEditHighlightModeText, &hl);
3999         if (hl)
4000         {
4001             wxMenuItem* item = hl->FindItem(event.GetId());
4002             if (item)
4003                 lang = colour_set->GetHighlightLanguage(item->GetItemLabelText());
4004         }
4005     }
4006     // Highlightbutton
4007     if (m_pHighlightButton)
4008         changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(lang));
4009     ed->SetLanguage(lang, true);
4010     Manager::Get()->GetCCManager()->NotifyPluginStatus();
4011 }
4012 
OnEditFoldAll(cb_unused wxCommandEvent & event)4013 void MainFrame::OnEditFoldAll(cb_unused wxCommandEvent& event)
4014 {
4015     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4016     if (ed)
4017         ed->FoldAll();
4018 }
4019 
OnEditUnfoldAll(cb_unused wxCommandEvent & event)4020 void MainFrame::OnEditUnfoldAll(cb_unused wxCommandEvent& event)
4021 {
4022     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4023     if (ed)
4024         ed->UnfoldAll();
4025 }
4026 
OnEditToggleAllFolds(cb_unused wxCommandEvent & event)4027 void MainFrame::OnEditToggleAllFolds(cb_unused wxCommandEvent& event)
4028 {
4029     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4030     if (ed)
4031         ed->ToggleAllFolds();
4032 }
4033 
OnEditFoldBlock(cb_unused wxCommandEvent & event)4034 void MainFrame::OnEditFoldBlock(cb_unused wxCommandEvent& event)
4035 {
4036     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4037     if (ed)
4038         ed->FoldBlockFromLine();
4039 }
4040 
OnEditUnfoldBlock(cb_unused wxCommandEvent & event)4041 void MainFrame::OnEditUnfoldBlock(cb_unused wxCommandEvent& event)
4042 {
4043     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4044     if (ed)
4045         ed->UnfoldBlockFromLine();
4046 }
4047 
OnEditToggleFoldBlock(cb_unused wxCommandEvent & event)4048 void MainFrame::OnEditToggleFoldBlock(cb_unused wxCommandEvent& event)
4049 {
4050     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4051     if (ed)
4052         ed->ToggleFoldBlockFromLine();
4053 }
4054 
OnEditEOLMode(wxCommandEvent & event)4055 void MainFrame::OnEditEOLMode(wxCommandEvent& event)
4056 {
4057     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4058     if (ed)
4059     {
4060         int mode = -1;
4061 
4062         if (event.GetId() == idEditEOLCRLF)
4063             mode = wxSCI_EOL_CRLF;
4064         else if (event.GetId() == idEditEOLCR)
4065             mode = wxSCI_EOL_CR;
4066         else if (event.GetId() == idEditEOLLF)
4067             mode = wxSCI_EOL_LF;
4068 
4069         if (mode != -1 && mode != ed->GetControl()->GetEOLMode())
4070         {
4071             ed->GetControl()->BeginUndoAction();
4072             ed->GetControl()->ConvertEOLs(mode);
4073             ed->GetControl()->SetEOLMode(mode);
4074             ed->GetControl()->EndUndoAction();
4075         }
4076     }
4077 }
4078 
OnEditEncoding(wxCommandEvent & event)4079 void MainFrame::OnEditEncoding(wxCommandEvent& event)
4080 {
4081     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4082     if (!ed)
4083         return;
4084 
4085     if ( event.GetId() == idEditEncodingUseBom )
4086     {
4087         ed->SetUseBom( !ed->GetUseBom() );
4088         return;
4089     }
4090 
4091     wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
4092 
4093     if ( event.GetId() == idEditEncodingDefault )
4094         encoding = wxFONTENCODING_SYSTEM;
4095     else if ( event.GetId() == idEditEncodingAscii )
4096         encoding = wxFONTENCODING_ISO8859_1;
4097     else if ( event.GetId() == idEditEncodingUtf7 )
4098         encoding = wxFONTENCODING_UTF7;
4099     else if ( event.GetId() == idEditEncodingUtf8 )
4100         encoding = wxFONTENCODING_UTF8;
4101     else if ( event.GetId() == idEditEncodingUtf16 )
4102         encoding = wxFONTENCODING_UTF16;
4103     else if ( event.GetId() == idEditEncodingUtf32 )
4104         encoding = wxFONTENCODING_UTF32;
4105     else if ( event.GetId() == idEditEncodingUnicode )
4106         encoding = wxFONTENCODING_UNICODE;
4107     else if ( event.GetId() == idEditEncodingUnicode16BE )
4108         encoding = wxFONTENCODING_UTF16BE;
4109     else if ( event.GetId() == idEditEncodingUnicode16LE )
4110         encoding = wxFONTENCODING_UTF16LE;
4111     else if ( event.GetId() == idEditEncodingUnicode32BE )
4112         encoding = wxFONTENCODING_UTF32BE;
4113     else if ( event.GetId() == idEditEncodingUnicode32LE )
4114         encoding = wxFONTENCODING_UTF32LE;
4115 
4116     ed->SetEncoding(encoding);
4117 }
4118 
OnViewLayout(wxCommandEvent & event)4119 void MainFrame::OnViewLayout(wxCommandEvent& event)
4120 {
4121     LoadViewLayout(m_PluginIDsMap[event.GetId()]);
4122 }
4123 
OnViewLayoutSave(cb_unused wxCommandEvent & event)4124 void MainFrame::OnViewLayoutSave(cb_unused wxCommandEvent& event)
4125 {
4126     wxString def = m_LastLayoutName;
4127     if ( def.empty() )
4128         def = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
4129     wxString name = cbGetTextFromUser(_("Enter the name for this perspective"), _("Save current perspective"), def);
4130     if (!name.IsEmpty())
4131     {
4132         DoFixToolbarsLayout();
4133         SaveViewLayout(name,
4134                        m_LayoutManager.SavePerspective(),
4135                        m_pInfoPane->SaveTabOrder(),
4136                        true);
4137     }
4138 }
4139 
OnViewLayoutDelete(cb_unused wxCommandEvent & event)4140 void MainFrame::OnViewLayoutDelete(cb_unused wxCommandEvent& event)
4141 {
4142     if (m_LastLayoutName == gDefaultLayout)
4143     {
4144         if (cbMessageBox(_("The default perspective cannot be deleted. It can always be reverted to "
4145                         "a predefined state though.\nDo you want to revert it now?"),
4146                         _("Confirmation"),
4147                         wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4148         {
4149             m_LayoutViews[gDefaultLayout] = gDefaultLayoutData;
4150             m_LayoutMessagePane[gDefaultLayout] = gDefaultMessagePaneLayoutData;
4151             LoadViewLayout(gDefaultLayout);
4152         }
4153         return;
4154     }
4155 
4156     if (m_LastLayoutName == gMinimalLayout)
4157     {
4158         if (cbMessageBox(_("The minimal layout cannot be deleted. It can always be reverted to "
4159                         "a predefined state though.\nDo you want to revert it now?"),
4160                         _("Confirmation"),
4161                         wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4162         {
4163             wxString tempLayout = m_PreviousLayoutName;
4164             m_LayoutViews[gMinimalLayout] = gMinimalLayoutData;
4165             m_LayoutMessagePane[gMinimalLayout] = gMinimalMessagePaneLayoutData;
4166             LoadViewLayout(gMinimalLayout);
4167             m_PreviousLayoutName = tempLayout;
4168         }
4169         return;
4170     }
4171 
4172     if (cbMessageBox(wxString::Format(_("Are you really sure you want to delete the perspective '%s'?"), m_LastLayoutName.wx_str()),
4173                     _("Confirmation"),
4174                     wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4175     {
4176         // first delete it from the hashmap
4177         LayoutViewsMap::iterator it = m_LayoutViews.find(m_LastLayoutName);
4178         if (it != m_LayoutViews.end())
4179             m_LayoutViews.erase(it);
4180         it = m_LayoutMessagePane.find(m_LastLayoutName);
4181         if (it != m_LayoutMessagePane.end())
4182             m_LayoutMessagePane.erase(it);
4183 
4184         // now delete the menu item too
4185         wxMenu* viewLayouts = nullptr;
4186         GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
4187         if (viewLayouts)
4188         {
4189             int id = viewLayouts->FindItem(m_LastLayoutName);
4190             if (id != wxNOT_FOUND)
4191                 viewLayouts->Delete(id);
4192             // delete the id from the map too
4193             PluginIDsMap::iterator it2 = m_PluginIDsMap.find(id);
4194             if (it2 != m_PluginIDsMap.end())
4195                 m_PluginIDsMap.erase(it2);
4196         }
4197 
4198         cbMessageBox(wxString::Format(_("Perspective '%s' deleted.\nWill now revert to perspective '%s'..."), m_LastLayoutName.wx_str(), gDefaultLayout.wx_str()),
4199                         _("Information"), wxICON_INFORMATION);
4200 
4201         // finally, revert to the default layout
4202         m_LastLayoutName = gDefaultLayout; // do not ask to save old layout ;)
4203         LoadViewLayout(gDefaultLayout);
4204     }
4205 }
4206 
OnNotebookDoubleClick(cb_unused CodeBlocksEvent & event)4207 void MainFrame::OnNotebookDoubleClick(cb_unused CodeBlocksEvent& event)
4208 {
4209     if (m_LastLayoutName == gMinimalLayout)
4210         LoadViewLayout(m_PreviousLayoutName.IsEmpty()?Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/environment/view/layout_to_toggle"),gDefaultLayout):m_PreviousLayoutName);
4211     else
4212     {
4213         ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
4214         if (cfg->ReadBool(_T("/environment/view/dbl_clk_maximize"), true))
4215             LoadViewLayout(gMinimalLayout);
4216     }
4217 }
4218 
OnViewScriptConsole(cb_unused wxCommandEvent & event)4219 void MainFrame::OnViewScriptConsole(cb_unused wxCommandEvent& event)
4220 {
4221     ShowHideScriptConsole();
4222 }
4223 
OnViewHideEditorTabs(cb_unused wxCommandEvent & event)4224 void MainFrame::OnViewHideEditorTabs(cb_unused wxCommandEvent& event)
4225 {
4226 	cbAuiNotebook* nb = Manager::Get()->GetEditorManager()->GetNotebook();
4227 	if (nb)
4228 	{
4229 		bool hide_editor_tabs = nb->GetTabCtrlHeight() > 0;
4230 
4231 		if (hide_editor_tabs)
4232 			nb->SetTabCtrlHeight(0);
4233 		else
4234 			nb->SetTabCtrlHeight(-1);
4235 
4236 		Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/environment/hide_editor_tabs"), hide_editor_tabs);
4237 	}
4238 }
4239 
OnSearchFind(wxCommandEvent & event)4240 void MainFrame::OnSearchFind(wxCommandEvent& event)
4241 {
4242     bool bDoMultipleFiles = (event.GetId() == idSearchFindInFiles);
4243     if (!bDoMultipleFiles)
4244         bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4245     m_findReplace.ShowFindDialog(false, bDoMultipleFiles);
4246 }
4247 
OnSearchFindNext(wxCommandEvent & event)4248 void MainFrame::OnSearchFindNext(wxCommandEvent& event)
4249 {
4250     bool bNext = !(event.GetId() == idSearchFindPrevious);
4251     m_findReplace.FindNext(bNext, nullptr, nullptr, false);
4252 }
4253 
OnSearchFindNextSelected(wxCommandEvent & event)4254 void MainFrame::OnSearchFindNextSelected(wxCommandEvent& event)
4255 {
4256     bool bNext = !(event.GetId() == idSearchFindSelectedPrevious);
4257     m_findReplace.FindSelectedText(bNext);
4258 }
4259 
OnSearchReplace(wxCommandEvent & event)4260 void MainFrame::OnSearchReplace(wxCommandEvent& event)
4261 {
4262     bool bDoMultipleFiles = (event.GetId() == idSearchReplaceInFiles);
4263     if (!bDoMultipleFiles)
4264         bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4265     m_findReplace.ShowFindDialog(true, bDoMultipleFiles);
4266 }
4267 
OnSearchGotoLine(cb_unused wxCommandEvent & event)4268 void MainFrame::OnSearchGotoLine(cb_unused wxCommandEvent& event)
4269 {
4270     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4271     if (!ed)
4272         return;
4273 
4274     int max = ed->GetControl()->LineFromPosition(ed->GetControl()->GetLength()) + 1;
4275 
4276     /**
4277     @remarks We use wxGetText instead of wxGetNumber because wxGetNumber *must*
4278     provide an initial line number...which doesn't make sense, and just keeps the
4279     user deleting the initial line number everytime he instantiates the dialog.
4280     However, this is just a temporary hack, because the default dialog used isn't
4281     that suitable either.
4282     */
4283     wxString strLine = cbGetTextFromUser( wxString::Format(_("Line (1 - %d): "), max),
4284                                         _("Goto line"),
4285                                         _T( "" ),
4286                                         this );
4287     long int line = 0;
4288     strLine.ToLong(&line);
4289     if ( line >= 1 && line <= max )
4290     {
4291         ed->UnfoldBlockFromLine(line - 1);
4292         ed->GotoLine(line - 1);
4293     }
4294 }
4295 
OnSearchGotoNextChanged(cb_unused wxCommandEvent & event)4296 void MainFrame::OnSearchGotoNextChanged(cb_unused wxCommandEvent& event)
4297 {
4298     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4299     if (ed)
4300         ed->GotoNextChanged();
4301 }
4302 
OnSearchGotoPrevChanged(cb_unused wxCommandEvent & event)4303 void MainFrame::OnSearchGotoPrevChanged(cb_unused wxCommandEvent& event)
4304 {
4305     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4306     if (ed)
4307         ed->GotoPreviousChanged();
4308 }
4309 
OnHelpAbout(wxCommandEvent & WXUNUSED (event))4310 void MainFrame::OnHelpAbout(wxCommandEvent& WXUNUSED(event))
4311 {
4312     dlgAbout dlg(this);
4313     PlaceWindow(&dlg, pdlHead);
4314     dlg.ShowModal();
4315 }
4316 
OnHelpTips(cb_unused wxCommandEvent & event)4317 void MainFrame::OnHelpTips(cb_unused wxCommandEvent& event)
4318 {
4319     ShowTips(true);
4320 }
4321 
OnFileMenuUpdateUI(wxUpdateUIEvent & event)4322 void MainFrame::OnFileMenuUpdateUI(wxUpdateUIEvent& event)
4323 {
4324     if (Manager::IsAppShuttingDown())
4325     {
4326         event.Skip();
4327         return;
4328     }
4329 
4330     if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
4331     {
4332         event.Enable(false);
4333         return;
4334     }
4335 
4336     EditorManager *editorManager = Manager::Get()->GetEditorManager();
4337     EditorBase *ed = (editorManager ? editorManager->GetActiveEditor() : nullptr);
4338     EditorBase *sh = (editorManager ? editorManager->GetEditor(g_StartHereTitle) : nullptr);
4339 
4340     const int id = event.GetId();
4341 
4342     // Single file related menu items
4343     if (id == idFileClose || id == idFileCloseAll || id == idFileSaveAs)
4344         event.Enable(ed && ed != sh);
4345     else if (id == idFileSave)
4346         event.Enable(ed && ed->GetModified());
4347     else if (id == idFilePrint)
4348         event.Enable(editorManager && editorManager->GetBuiltinActiveEditor());
4349     else if (id == idFileOpen)
4350         event.Enable(true);
4351     else
4352     {
4353         ProjectManager *projectManager = Manager::Get()->GetProjectManager();
4354         cbProject *project = (projectManager ? projectManager->GetActiveProject() : nullptr);
4355         if (project && project->GetCurrentlyCompilingTarget())
4356         {
4357             event.Enable(false);
4358             return;
4359         }
4360 
4361         // Project related menu items
4362         if (id == idFileReopenProject)
4363             event.Enable(true);
4364         else if (id == idFileCloseProject || id == idFileSaveProjectAs || id == idFileSaveProjectTemplate)
4365             event.Enable(project != nullptr);
4366         else if (id == idFileSaveProject)
4367             event.Enable(project && project->GetModified());
4368         else if (id == idFileOpenDefWorkspace || id == idFileSaveWorkspaceAs || id == idFileSaveAll)
4369             event.Enable(true);
4370         else
4371         {
4372             // Workspace related menu items
4373             const cbWorkspace *workspace = Manager::Get()->GetProjectManager()->GetWorkspace();
4374 
4375             if (id == idFileSaveWorkspace)
4376                 event.Enable(workspace && workspace->GetModified());
4377             else if (id == idFileCloseWorkspace)
4378                 event.Enable(workspace != nullptr);
4379             else
4380                 event.Skip();
4381         }
4382     }
4383 }
4384 
OnEditMenuUpdateUI(wxUpdateUIEvent & event)4385 void MainFrame::OnEditMenuUpdateUI(wxUpdateUIEvent& event)
4386 {
4387     if (Manager::IsAppShuttingDown())
4388     {
4389         event.Skip();
4390         return;
4391     }
4392 
4393     cbEditor*   ed = NULL;
4394     EditorBase* eb = NULL;
4395     bool hasSel    = false;
4396     bool canUndo   = false;
4397     bool canRedo   = false;
4398     bool canPaste  = false;
4399     bool canCut    = false;
4400     bool canSelAll = false;
4401 
4402     if (Manager::Get()->GetEditorManager() && !Manager::IsAppShuttingDown())
4403     {
4404         ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4405         eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
4406     }
4407 
4408     wxMenuBar* mbar = GetMenuBar();
4409 
4410     if (eb)
4411     {
4412         canUndo   = eb->CanUndo();
4413         canRedo   = eb->CanRedo();
4414         hasSel    = eb->HasSelection();
4415         canPaste  = eb->CanPaste();
4416         canCut    = !eb->IsReadOnly() && hasSel;
4417         canSelAll = eb->CanSelectAll();
4418     }
4419 
4420     mbar->Enable(idEditUndo,                  canUndo);
4421     mbar->Enable(idEditRedo,                  canRedo);
4422     mbar->Enable(idEditClearHistory,          canUndo || canRedo);
4423     mbar->Enable(idEditCut,                   canCut);
4424     mbar->Enable(idEditCopy,                  hasSel);
4425     mbar->Enable(idEditPaste,                 canPaste);
4426     mbar->Enable(idEditSwapHeaderSource,      ed);
4427     mbar->Enable(idEditGotoMatchingBrace,     ed);
4428     mbar->Enable(idEditHighlightMode,         ed);
4429     mbar->Enable(idEditSelectAll,             canSelAll);
4430     mbar->Enable(idEditSelectNext,            ed);
4431     mbar->Enable(idEditSelectNextSkip,        hasSel);
4432     mbar->Enable(idEditBookmarks,             ed);
4433     mbar->Enable(idEditFolding,               ed &&
4434                                               Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/folding/show_folds"), false));
4435     mbar->Enable(idEditEOLMode,               ed);
4436     mbar->Enable(idEditEncoding,              ed);
4437     mbar->Enable(idEditSpecialCommands,       ed);
4438     mbar->Enable(idEditSpecialCommandsCase,   ed && hasSel);
4439     mbar->Enable(idEditCommentSelected,       ed);
4440     mbar->Enable(idEditUncommentSelected,     ed);
4441     mbar->Enable(idEditToggleCommentSelected, ed);
4442     mbar->Enable(idEditStreamCommentSelected, ed);
4443     mbar->Enable(idEditBoxCommentSelected,    ed);
4444     mbar->Enable(idEditShowCallTip,           ed);
4445     mbar->Enable(idEditCompleteCode,          ed);
4446 
4447     if (ed)
4448     {
4449         // OK... this was the strangest/silliest/most-frustrating bug ever in the computer programs history...
4450         // Under wxGTK it seems that if you try to Check() a menu item if its container Menu is disabled,
4451         // you enter an endless message loop eating 100% CPU...
4452         // DARN!
4453         // This fixes the dreaded 'linux-hang-on-close-project' bug.
4454 
4455         switch (ed->GetControl()->GetEOLMode())
4456         {
4457             case wxSCI_EOL_CRLF:
4458                 mbar->Check(idEditEOLCRLF, true);
4459                 break;
4460             case wxSCI_EOL_CR:
4461                 mbar->Check(idEditEOLCR,   true);
4462                 break;
4463             case wxSCI_EOL_LF:
4464                 mbar->Check(idEditEOLLF,   true);
4465                 break;
4466             default:
4467                 (platform::windows ? mbar->Check(idEditEOLCRLF, true) : mbar->Check(idEditEOLLF,   true));
4468                 break;
4469         }
4470 
4471         bool defenc = ed && (   ed->GetEncoding() == wxFONTENCODING_SYSTEM
4472                              || ed->GetEncoding() == wxLocale::GetSystemEncoding() );
4473 
4474         mbar->Check(idEditEncodingDefault,     defenc);
4475         mbar->Check(idEditEncodingUseBom,      ed && ed->GetUseBom());
4476         mbar->Check(idEditEncodingAscii,       ed && ed->GetEncoding() == wxFONTENCODING_ISO8859_1);
4477         mbar->Check(idEditEncodingUtf7,        ed && ed->GetEncoding() == wxFONTENCODING_UTF7);
4478         mbar->Check(idEditEncodingUtf8,        ed && ed->GetEncoding() == wxFONTENCODING_UTF8);
4479         mbar->Check(idEditEncodingUnicode,     ed && ed->GetEncoding() == wxFONTENCODING_UNICODE);
4480         mbar->Check(idEditEncodingUtf16,       ed && ed->GetEncoding() == wxFONTENCODING_UTF16);
4481         mbar->Check(idEditEncodingUtf32,       ed && ed->GetEncoding() == wxFONTENCODING_UTF32);
4482         mbar->Check(idEditEncodingUnicode16BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16BE);
4483         mbar->Check(idEditEncodingUnicode16LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16LE);
4484         mbar->Check(idEditEncodingUnicode32BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32BE);
4485         mbar->Check(idEditEncodingUnicode32LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32LE);
4486 
4487         wxMenu* hl = nullptr;
4488         mbar->FindItem(idEditHighlightModeText, &hl);
4489         if (hl)
4490         {
4491             EditorColourSet* colour_set = ed->GetColourSet();
4492             if (colour_set)
4493             {
4494                 int item = hl->FindItem(colour_set->GetLanguageName(ed->GetLanguage()));
4495                 if (item != wxNOT_FOUND)
4496                     mbar->Check(item, true);
4497             }
4498         }
4499     }
4500 
4501     if (m_pToolbar)
4502     {
4503         m_pToolbar->EnableTool(idEditUndo,  canUndo);
4504         m_pToolbar->EnableTool(idEditRedo,  canRedo);
4505         m_pToolbar->EnableTool(idEditCut,   canCut);
4506         m_pToolbar->EnableTool(idEditCopy,  hasSel);
4507         m_pToolbar->EnableTool(idEditPaste, canPaste);
4508     }
4509 
4510     event.Skip();
4511 }
4512 
OnViewMenuUpdateUI(wxUpdateUIEvent & event)4513 void MainFrame::OnViewMenuUpdateUI(wxUpdateUIEvent& event)
4514 {
4515     if (Manager::IsAppShuttingDown())
4516     {
4517         event.Skip();
4518         return;
4519     }
4520 
4521     wxMenuBar* mbar   = GetMenuBar();
4522     cbEditor*  ed     = Manager::Get()->GetEditorManager() ? Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor() : nullptr;
4523     bool       manVis = m_LayoutManager.GetPane(m_pPrjManUI->GetNotebook()).IsShown();
4524 
4525     mbar->Check(idViewManager,             manVis);
4526     mbar->Check(idViewLogManager,          m_LayoutManager.GetPane(m_pInfoPane).IsShown());
4527     mbar->Check(idViewStartPage,           Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle)!=NULL);
4528     mbar->Check(idViewStatusbar,           GetStatusBar() && GetStatusBar()->IsShown());
4529     mbar->Check(idViewScriptConsole,       m_LayoutManager.GetPane(m_pScriptConsole).IsShown());
4530     mbar->Check(idViewHideEditorTabs,      Manager::Get()->GetEditorManager()->GetNotebook()->GetTabCtrlHeight() == 0);
4531     mbar->Check(idViewFullScreen,          IsFullScreen());
4532     mbar->Enable(idViewFocusEditor,        ed);
4533     mbar->Enable(idViewFocusManagement,    manVis);
4534     mbar->Enable(idViewFocusLogsAndOthers, m_pInfoPane->IsShown());
4535 
4536     // toolbars
4537     wxMenu* viewToolbars = nullptr;
4538     GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
4539     if (viewToolbars)
4540     {
4541         SetChecksForViewToolbarsMenu(*viewToolbars);
4542     }
4543 
4544     event.Skip();
4545 }
4546 
OnSearchMenuUpdateUI(wxUpdateUIEvent & event)4547 void MainFrame::OnSearchMenuUpdateUI(wxUpdateUIEvent& event)
4548 {
4549     if (Manager::IsAppShuttingDown())
4550     {
4551         event.Skip();
4552         return;
4553     }
4554 
4555     cbEditor* ed = Manager::Get()->GetEditorManager()
4556                  ? Manager::Get()->GetEditorManager()->GetBuiltinEditor(
4557                      Manager::Get()->GetEditorManager()->GetActiveEditor() ) : nullptr;
4558 
4559     bool enableGoto = false;
4560     if (ed)
4561         enableGoto = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true)
4562                    && (ed->CanUndo() || ed->CanRedo());
4563 
4564     wxMenuBar* mbar = GetMenuBar();
4565 
4566     // 'Find' and 'Replace' are always enabled for (find|replace)-in-files
4567     // (idSearchFindInFiles and idSearchReplaceInFiles)
4568 
4569     mbar->Enable(idSearchFind,                  ed);
4570     mbar->Enable(idSearchFindNext,              ed);
4571     mbar->Enable(idSearchFindPrevious,          ed);
4572     mbar->Enable(idSearchFindSelectedNext,      ed);
4573     mbar->Enable(idSearchFindSelectedPrevious,  ed);
4574     mbar->Enable(idSearchReplace,               ed);
4575     mbar->Enable(idSearchGotoLine,              ed);
4576     mbar->Enable(idSearchGotoNextChanged,       enableGoto);
4577     mbar->Enable(idSearchGotoPreviousChanged,   enableGoto);
4578 
4579     event.Skip();
4580 }
4581 
4582 
OnEditorUpdateUI(CodeBlocksEvent & event)4583 void MainFrame::OnEditorUpdateUI(CodeBlocksEvent& event)
4584 {
4585     if (Manager::IsAppShuttingDown())
4586     {
4587         event.Skip();
4588         return;
4589     }
4590 
4591     if (Manager::Get()->GetEditorManager() && event.GetEditor() == Manager::Get()->GetEditorManager()->GetActiveEditor())
4592     {
4593 #if wxCHECK_VERSION(3, 0, 0)
4594         // Execute the code to update the status bar outside of the paint event for scintilla.
4595         // Executing this function directly in the event handler causes redraw problems on Windows.
4596         CallAfter(&MainFrame::DoUpdateStatusBar);
4597 #else
4598         DoUpdateStatusBar();
4599 #endif // defined(__wxMSW__) && wxCHECK_VERSION(3, 0, 0)
4600     }
4601 
4602     event.Skip();
4603 }
4604 
OnViewToolbarsFit(cb_unused wxCommandEvent & event)4605 void MainFrame::OnViewToolbarsFit(cb_unused wxCommandEvent& event)
4606 {
4607     FitToolbars(m_LayoutManager, this);
4608     DoUpdateLayout();
4609 }
4610 
OnViewToolbarsOptimize(cb_unused wxCommandEvent & event)4611 void MainFrame::OnViewToolbarsOptimize(cb_unused wxCommandEvent& event)
4612 {
4613     OptimizeToolbars(m_LayoutManager, this);
4614     DoUpdateLayout();
4615 }
4616 
OnToggleBar(wxCommandEvent & event)4617 void MainFrame::OnToggleBar(wxCommandEvent& event)
4618 {
4619     wxWindow* win = nullptr;
4620     bool toolbar = false;
4621     if (event.GetId() == idViewManager)
4622         win = m_pPrjManUI->GetNotebook();
4623     else if (event.GetId() == idViewLogManager)
4624         win = m_pInfoPane;
4625     else if (event.GetId() == idViewToolMain)
4626     {
4627         win = m_pToolbar;
4628         toolbar = true;
4629     }
4630     else if (event.GetId() == idViewToolDebugger)
4631     {
4632         win = m_debuggerToolbarHandler->GetToolbar();
4633         toolbar = true;
4634     }
4635     else
4636     {
4637         wxString pluginName = m_PluginIDsMap[event.GetId()];
4638         if (!pluginName.IsEmpty())
4639         {
4640             cbPlugin* plugin = Manager::Get()->GetPluginManager()->FindPluginByName(pluginName);
4641             if (plugin)
4642             {
4643                 win = m_PluginsTools[plugin];
4644                 toolbar = true;
4645             }
4646         }
4647     }
4648 
4649     if (win)
4650     {
4651         // For checked menu items, event.IsChecked() will not reflect the actual status of the menu item
4652         //  when this event was previously event.Skip()'ed after the menu item change.
4653         bool isShown = m_LayoutManager.GetPane(win).IsShown();
4654 
4655         // use last visible size as BestSize, Logs & others does no longer "forget" it's size
4656         if (!isShown)
4657              m_LayoutManager.GetPane(win).BestSize(win->GetSize());
4658 
4659         m_LayoutManager.GetPane(win).Show(not isShown); //toggle
4660         if (toolbar)
4661             FitToolbars(m_LayoutManager, this);
4662         DoUpdateLayout();
4663     }
4664 }
4665 
OnToggleStatusBar(cb_unused wxCommandEvent & event)4666 void MainFrame::OnToggleStatusBar(cb_unused wxCommandEvent& event)
4667 {
4668     cbStatusBar* sb = (cbStatusBar*)GetStatusBar();
4669     if (!sb) return;
4670 
4671     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
4672     const bool show = !cfg->ReadBool(_T("/main_frame/statusbar"), true);
4673     cfg->Write(_T("/main_frame/statusbar"), show);
4674 
4675     DoUpdateStatusBar();
4676     sb->Show(show);
4677     if ( show ) SendSizeEvent();
4678     DoUpdateLayout();
4679 }
4680 
OnFocusEditor(cb_unused wxCommandEvent & event)4681 void MainFrame::OnFocusEditor(cb_unused wxCommandEvent& event)
4682 {
4683     EditorManager* edman = Manager::Get()->GetEditorManager();
4684     cbAuiNotebook* nb = edman?edman->GetNotebook():nullptr;
4685     if (nb)
4686         nb->FocusActiveTabCtrl();
4687 }
4688 
OnFocusManagement(cb_unused wxCommandEvent & event)4689 void MainFrame::OnFocusManagement(cb_unused wxCommandEvent& event)
4690 {
4691     cbAuiNotebook* nb = m_pPrjManUI ? m_pPrjManUI->GetNotebook() : nullptr;
4692     if (nb)
4693         nb->FocusActiveTabCtrl();
4694 }
4695 
OnFocusLogsAndOthers(cb_unused wxCommandEvent & event)4696 void MainFrame::OnFocusLogsAndOthers(cb_unused wxCommandEvent& event)
4697 {
4698     if (m_pInfoPane)
4699         m_pInfoPane->FocusActiveTabCtrl();
4700 }
4701 
OnSwitchTabs(cb_unused wxCommandEvent & event)4702 void MainFrame::OnSwitchTabs(cb_unused wxCommandEvent& event)
4703 {
4704     // Get the notebook from the editormanager:
4705     cbAuiNotebook* nb = Manager::Get()->GetEditorManager()->GetNotebook();
4706     if (!nb)
4707         return;
4708 
4709     // Create container and add all open editors:
4710     wxSwitcherItems items;
4711     items.AddGroup(_("Open files"), wxT("editors"));
4712     if (!Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/tabs_stacked_based_switching")))
4713     {   // Switch tabs editor with tab order
4714         for (size_t i = 0; i < nb->GetPageCount(); ++i)
4715         {
4716             wxString title = nb->GetPageText(i);
4717             wxWindow* window = nb->GetPage(i);
4718 
4719             items.AddItem(title, title, GetEditorDescription(static_cast<EditorBase*> (window)), i, nb->GetPageBitmap(i)).SetWindow(window);
4720         }
4721 
4722         // Select the focused editor:
4723         int idx = items.GetIndexForFocus();
4724         if (idx != wxNOT_FOUND)
4725             items.SetSelection(idx);
4726     }
4727     else
4728     {   // Switch tabs editor with last used order
4729         int index = 0;
4730         cbNotebookStack* body;
4731         for (body = Manager::Get()->GetEditorManager()->GetNotebookStack(); body != NULL; body = body->next)
4732         {
4733             index = nb->GetPageIndex(body->window);
4734             if (index == wxNOT_FOUND)
4735                 continue;
4736             wxString title = nb->GetPageText(index);
4737             items.AddItem(title, title, GetEditorDescription(static_cast<EditorBase*> (body->window)), index, nb->GetPageBitmap(index)).SetWindow(body->window);
4738         }
4739 
4740         // Select the focused editor:
4741         if(items.GetItemCount() > 2)
4742             items.SetSelection(2); // CTRL + TAB directly select the last editor, not the current one
4743         else
4744             items.SetSelection(items.GetItemCount()-1);
4745     }
4746 
4747     // Create the switcher dialog
4748     wxSwitcherDialog dlg(items, wxGetApp().GetTopWindow());
4749 
4750     // Ctrl+Tab workaround for non windows platforms:
4751     if      (platform::cocoa)
4752         dlg.SetModifierKey(WXK_ALT);
4753     else if (platform::gtk)
4754         dlg.SetExtraNavigationKey(wxT(','));
4755 
4756     // Finally show the dialog:
4757     int answer = dlg.ShowModal();
4758 
4759     // If necessary change the selected editor:
4760     if ((answer == wxID_OK) && (dlg.GetSelection() != -1))
4761     {
4762         wxSwitcherItem& item = items.GetItem(dlg.GetSelection());
4763         wxWindow* win = item.GetWindow();
4764         if (win)
4765         {
4766             nb->SetSelection(item.GetId());
4767             win->SetFocus();
4768         }
4769     }
4770 }
4771 
OnToggleStartPage(cb_unused wxCommandEvent & event)4772 void MainFrame::OnToggleStartPage(cb_unused wxCommandEvent& event)
4773 {
4774 
4775     int toggle=-1;
4776     if(Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle)==NULL)
4777     {
4778         toggle=1;
4779     }
4780     ShowHideStartPage(false,toggle);
4781 }
4782 
OnToggleFullScreen(cb_unused wxCommandEvent & event)4783 void MainFrame::OnToggleFullScreen(cb_unused wxCommandEvent& event)
4784 {
4785     ShowFullScreen( !IsFullScreen(), wxFULLSCREEN_NOTOOLBAR// | wxFULLSCREEN_NOSTATUSBAR
4786                     | wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION );
4787 
4788     // Create full screen-close button if we're in full screen
4789     if ( IsFullScreen() )
4790     {
4791         //
4792         // Show the button to the bottom-right of the container
4793         //
4794         wxSize containerSize = GetClientSize();
4795         wxSize buttonSize = m_pCloseFullScreenBtn->GetSize();
4796 
4797         // Align
4798         m_pCloseFullScreenBtn->Move( containerSize.GetWidth() - buttonSize.GetWidth(),
4799                     containerSize.GetHeight() - buttonSize.GetHeight() );
4800 
4801         m_pCloseFullScreenBtn->Show( true );
4802         m_pCloseFullScreenBtn->Raise();
4803     }
4804     else
4805         m_pCloseFullScreenBtn->Show( false );
4806 }
4807 
OnPluginInstalled(CodeBlocksEvent & event)4808 void MainFrame::OnPluginInstalled(CodeBlocksEvent& event)
4809 {
4810     PluginsUpdated(event.GetPlugin(), Installed);
4811 }
4812 
OnPluginUninstalled(CodeBlocksEvent & event)4813 void MainFrame::OnPluginUninstalled(CodeBlocksEvent& event)
4814 {
4815     if (Manager::IsAppShuttingDown())
4816         return;
4817     PluginsUpdated(event.GetPlugin(), Uninstalled);
4818 }
4819 
OnPluginLoaded(CodeBlocksEvent & event)4820 void MainFrame::OnPluginLoaded(CodeBlocksEvent& event)
4821 {
4822     cbPlugin* plug = event.GetPlugin();
4823     if (plug)
4824     {
4825         DoAddPlugin(plug);
4826         const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plug);
4827         wxString msg = info ? info->title : wxString(_("<Unknown plugin>"));
4828         Manager::Get()->GetLogManager()->DebugLog(F(_T("%s plugin activated"), msg.wx_str()));
4829     }
4830 }
4831 
OnPluginUnloaded(CodeBlocksEvent & event)4832 void MainFrame::OnPluginUnloaded(CodeBlocksEvent& event)
4833 {
4834     if (Manager::IsAppShuttingDown())
4835         return;
4836 
4837     cbPlugin* plugin = event.GetPlugin();
4838 
4839     cbStatusBar *sb = (cbStatusBar*)GetStatusBar();
4840     if ( sb )
4841         sb->RemoveField(plugin);
4842 
4843     // remove toolbar, if any
4844     if (m_PluginsTools[plugin])
4845     {
4846         // Disconnect the mouse right click event handler before the toolbar is destroyed
4847         bool result = m_PluginsTools[plugin]->Disconnect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick));
4848         cbAssert(result);
4849         m_LayoutManager.DetachPane(m_PluginsTools[plugin]);
4850         m_PluginsTools[plugin]->Destroy();
4851         m_PluginsTools.erase(plugin);
4852         DoUpdateLayout();
4853     }
4854 
4855     PluginsUpdated(plugin, Unloaded);
4856 }
4857 
OnSettingsEnvironment(cb_unused wxCommandEvent & event)4858 void MainFrame::OnSettingsEnvironment(cb_unused wxCommandEvent& event)
4859 {
4860     bool needRestart = false;
4861     const int originalToolbarSize = cbHelpers::ReadToolbarSizeFromConfig();
4862 
4863     EnvironmentSettingsDlg dlg(this, m_LayoutManager.GetArtProvider());
4864     PlaceWindow(&dlg);
4865     if (dlg.ShowModal() == wxID_OK)
4866     {
4867         DoUpdateEditorStyle();
4868         DoUpdateLayoutColours();
4869 
4870         {
4871             ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
4872             const int newToolbarSize = cfg->ReadInt(_T("/environment/toolbar_size"),
4873                                                     cbHelpers::defaultToolbarSize);
4874             needRestart = (newToolbarSize != originalToolbarSize);
4875         }
4876 
4877         Manager::Get()->GetLogManager()->NotifyUpdate();
4878         Manager::Get()->GetEditorManager()->RecreateOpenEditorStyles();
4879         Manager::Get()->GetCCManager()->UpdateEnvSettings();
4880         m_pPrjManUI->RebuildTree();
4881         ShowHideStartPage();
4882 
4883         CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4884         event2.SetInt(cbSettingsType::Environment);
4885         Manager::Get()->ProcessEvent(event2);
4886     }
4887     if (needRestart)
4888         cbMessageBox(_("Code::Blocks needs to be restarted for the changes to take effect."), _("Information"), wxICON_INFORMATION);
4889 }
4890 
OnGlobalUserVars(cb_unused wxCommandEvent & event)4891 void MainFrame::OnGlobalUserVars(cb_unused wxCommandEvent& event)
4892 {
4893     Manager::Get()->GetUserVariableManager()->Configure();
4894 }
4895 
OnSettingsEditor(cb_unused wxCommandEvent & event)4896 void MainFrame::OnSettingsEditor(cb_unused wxCommandEvent& event)
4897 {
4898     // editor lexers loading takes some time; better reflect this with a hourglass
4899     wxBeginBusyCursor();
4900 
4901     EditorConfigurationDlg dlg(Manager::Get()->GetAppWindow());
4902     PlaceWindow(&dlg);
4903 
4904     // done, restore pointer
4905     wxEndBusyCursor();
4906 
4907     if (dlg.ShowModal() == wxID_OK)
4908     {
4909         Manager::Get()->GetEditorManager()->RecreateOpenEditorStyles();
4910 
4911         CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4912         event2.SetInt(cbSettingsType::Editor);
4913         Manager::Get()->ProcessEvent(event2);
4914     }
4915 }
4916 
OnSettingsCompiler(cb_unused wxCommandEvent & event)4917 void MainFrame::OnSettingsCompiler(cb_unused wxCommandEvent& event)
4918 {
4919     CompilerSettingsDlg dlg(this);
4920     PlaceWindow(&dlg);
4921     if (dlg.ShowModal() == wxID_OK)
4922     {
4923         CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4924         event2.SetInt(cbSettingsType::Compiler);
4925         Manager::Get()->ProcessEvent(event2);
4926     }
4927 }
4928 
OnSettingsDebugger(cb_unused wxCommandEvent & event)4929 void MainFrame::OnSettingsDebugger(cb_unused wxCommandEvent& event)
4930 {
4931     DebuggerSettingsDlg dlg(this);
4932     PlaceWindow(&dlg);
4933     if (dlg.ShowModal() == wxID_OK)
4934     {
4935         CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4936         event2.SetInt(cbSettingsType::Debugger);
4937         Manager::Get()->ProcessEvent(event2);
4938     }
4939 }
4940 
OnSettingsPlugins(cb_unused wxCommandEvent & event)4941 void MainFrame::OnSettingsPlugins(cb_unused wxCommandEvent& event)
4942 {
4943     if (Manager::Get()->GetPluginManager()->Configure() == wxID_OK)
4944     {
4945         CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4946         event2.SetInt(cbSettingsType::Plugins);
4947         Manager::Get()->ProcessEvent(event2);
4948     }
4949 }
4950 
OnSettingsScripting(cb_unused wxCommandEvent & event)4951 void MainFrame::OnSettingsScripting(cb_unused wxCommandEvent& event)
4952 {
4953     ScriptingSettingsDlg dlg(this);
4954     if (dlg.ShowModal() == wxID_OK)
4955         RunStartupScripts();
4956 }
4957 
OnProjectActivated(CodeBlocksEvent & event)4958 void MainFrame::OnProjectActivated(CodeBlocksEvent& event)
4959 {
4960     DoUpdateAppTitle();
4961     event.Skip();
4962 }
4963 
OnProjectOpened(CodeBlocksEvent & event)4964 void MainFrame::OnProjectOpened(CodeBlocksEvent& event)
4965 {
4966     ShowHideStartPage(true);
4967     event.Skip();
4968 }
4969 
OnEditorOpened(CodeBlocksEvent & event)4970 void MainFrame::OnEditorOpened(CodeBlocksEvent& event)
4971 {
4972     DoUpdateAppTitle();
4973     event.Skip();
4974 }
4975 
OnEditorActivated(CodeBlocksEvent & event)4976 void MainFrame::OnEditorActivated(CodeBlocksEvent& event)
4977 {
4978     DoUpdateAppTitle();
4979     DoUpdateStatusBar();
4980 
4981     EditorBase *editor = event.GetEditor();
4982     if (editor && editor->IsBuiltinEditor())
4983     {
4984         ConfigManager* cfgEditor = Manager::Get()->GetConfigManager(_T("editor"));
4985         if (cfgEditor->ReadBool(_T("/sync_editor_with_project_manager"), false))
4986         {
4987             ProjectFile* pf = static_cast<cbEditor*>(editor)->GetProjectFile();
4988             if (pf)
4989                 m_pPrjManUI->ShowFileInTree(*pf);
4990         }
4991     }
4992 
4993     event.Skip();
4994 }
4995 
OnEditorClosed(CodeBlocksEvent & event)4996 void MainFrame::OnEditorClosed(CodeBlocksEvent& event)
4997 {
4998     DoUpdateAppTitle();
4999     DoUpdateStatusBar();
5000     event.Skip();
5001 }
5002 
OnEditorSaved(CodeBlocksEvent & event)5003 void MainFrame::OnEditorSaved(CodeBlocksEvent& event)
5004 {
5005     DoUpdateAppTitle();
5006     event.Skip();
5007 }
5008 
OnEditorModified(CodeBlocksEvent & event)5009 void MainFrame::OnEditorModified(CodeBlocksEvent& event)
5010 {
5011     DoUpdateAppTitle();
5012     event.Skip();
5013 }
5014 
OnProjectClosed(CodeBlocksEvent & event)5015 void MainFrame::OnProjectClosed(CodeBlocksEvent& event)
5016 {
5017     ShowHideStartPage();
5018     event.Skip();
5019 }
5020 
OnPageChanged(wxNotebookEvent & event)5021 void MainFrame::OnPageChanged(wxNotebookEvent& event)
5022 {
5023     DoUpdateAppTitle();
5024     event.Skip();
5025 }
5026 
OnShiftTab(cb_unused wxCommandEvent & event)5027 void MainFrame::OnShiftTab(cb_unused wxCommandEvent& event)
5028 {
5029     // Must make sure it's cbEditor and not EditorBase
5030     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
5031     if (ed)
5032         ed->DoUnIndent();
5033 }
5034 
OnCtrlAltTab(cb_unused wxCommandEvent & event)5035 void MainFrame::OnCtrlAltTab(cb_unused wxCommandEvent& event)
5036 {
5037     wxCommandEvent dummy;
5038     switch (m_LastCtrlAltTabWindow)
5039     {
5040       case 1:  // Focus is on the Mgmt. panel -> Cycle to Editor
5041         m_LastCtrlAltTabWindow = 2;
5042         OnFocusEditor(dummy);
5043         break;
5044       case 2:  // Focus is on the Editor -> Cycle to Logs & others
5045         m_LastCtrlAltTabWindow = 3;
5046         OnFocusLogsAndOthers(dummy);
5047         break;
5048       case 3:  // Focus is on Logs & others -> fall through
5049       default: // Focus (cycle to) the Mgmt. panel
5050         m_LastCtrlAltTabWindow = 1;
5051         OnFocusManagement(dummy);
5052     }
5053 }
5054 
OnRequestDockWindow(CodeBlocksDockEvent & event)5055 void MainFrame::OnRequestDockWindow(CodeBlocksDockEvent& event)
5056 {
5057     if (Manager::IsAppShuttingDown())
5058         return;
5059 
5060     wxAuiPaneInfo info;
5061     wxString name = event.name;
5062     if (name.IsEmpty())
5063     {
5064         static int idx = 0;
5065         name = wxString::Format(_T("UntitledPane%d"), ++idx);
5066     }
5067 // TODO (mandrav##): Check for existing pane with the same name
5068     info.Name(name);
5069     info.Caption(event.title.IsEmpty() ? name : event.title);
5070     switch (event.dockSide)
5071     {
5072         case CodeBlocksDockEvent::dsLeft:     info.Left();   break;
5073         case CodeBlocksDockEvent::dsRight:    info.Right();  break;
5074         case CodeBlocksDockEvent::dsTop:      info.Top();    break;
5075         case CodeBlocksDockEvent::dsBottom:   info.Bottom(); break;
5076         case CodeBlocksDockEvent::dsFloating: info.Float();  break;
5077         case CodeBlocksDockEvent::dsUndefined: // fall through
5078         default:                                             break;
5079     }
5080     info.Show(event.shown);
5081     info.BestSize(event.desiredSize);
5082     info.FloatingSize(event.floatingSize);
5083     info.FloatingPosition(event.floatingPos);
5084     info.MinSize(event.minimumSize);
5085     info.Layer(event.stretch ? 1 : 0);
5086 
5087     if (event.row != -1)
5088         info.Row(event.row);
5089     if (event.column != -1)
5090         info.Position(event.column);
5091     info.CloseButton(event.hideable ? true : false);
5092     m_LayoutManager.AddPane(event.pWindow, info);
5093     DoUpdateLayout();
5094 }
5095 
OnRequestUndockWindow(CodeBlocksDockEvent & event)5096 void MainFrame::OnRequestUndockWindow(CodeBlocksDockEvent& event)
5097 {
5098     wxAuiPaneInfo info = m_LayoutManager.GetPane(event.pWindow);
5099     if (info.IsOk())
5100     {
5101         m_LayoutManager.DetachPane(event.pWindow);
5102         DoUpdateLayout();
5103     }
5104 }
5105 
OnRequestShowDockWindow(CodeBlocksDockEvent & event)5106 void MainFrame::OnRequestShowDockWindow(CodeBlocksDockEvent& event)
5107 {
5108     m_LayoutManager.GetPane(event.pWindow).Show();
5109     DoUpdateLayout();
5110 
5111     CodeBlocksDockEvent evt(cbEVT_DOCK_WINDOW_VISIBILITY);
5112     evt.pWindow = event.pWindow;
5113     Manager::Get()->ProcessEvent(evt);
5114 }
5115 
OnRequestHideDockWindow(CodeBlocksDockEvent & event)5116 void MainFrame::OnRequestHideDockWindow(CodeBlocksDockEvent& event)
5117 {
5118     m_LayoutManager.GetPane(event.pWindow).Hide();
5119     DoUpdateLayout();
5120 
5121     CodeBlocksDockEvent evt(cbEVT_DOCK_WINDOW_VISIBILITY);
5122     evt.pWindow = event.pWindow;
5123     Manager::Get()->ProcessEvent(evt);
5124 }
5125 
OnDockWindowVisibility(cb_unused CodeBlocksDockEvent & event)5126 void MainFrame::OnDockWindowVisibility(cb_unused CodeBlocksDockEvent& event)
5127 {
5128 //    if (m_ScriptConsoleID != -1 && event.GetId() == m_ScriptConsoleID)
5129 //        ShowHideScriptConsole();
5130 }
5131 
OnLayoutUpdate(cb_unused CodeBlocksLayoutEvent & event)5132 void MainFrame::OnLayoutUpdate(cb_unused CodeBlocksLayoutEvent& event)
5133 {
5134     DoUpdateLayout();
5135 }
5136 
OnLayoutQuery(CodeBlocksLayoutEvent & event)5137 void MainFrame::OnLayoutQuery(CodeBlocksLayoutEvent& event)
5138 {
5139     event.layout = !m_LastLayoutName.IsEmpty() ? m_LastLayoutName : gDefaultLayout;
5140     event.StopPropagation();
5141 }
5142 
OnLayoutSwitch(CodeBlocksLayoutEvent & event)5143 void MainFrame::OnLayoutSwitch(CodeBlocksLayoutEvent& event)
5144 {
5145     LoadViewLayout(event.layout, true);
5146 }
5147 
OnAddLogWindow(CodeBlocksLogEvent & event)5148 void MainFrame::OnAddLogWindow(CodeBlocksLogEvent& event)
5149 {
5150     if (Manager::IsAppShuttingDown())
5151         return;
5152     wxWindow* p = event.window;
5153     if (p)
5154         m_pInfoPane->AddNonLogger(p, event.title, event.icon);
5155     else
5156     {
5157         p = event.logger->CreateControl(m_pInfoPane);
5158         if (p)
5159             m_pInfoPane->AddLogger(event.logger, p, event.title, event.icon);
5160     }
5161     Manager::Get()->GetLogManager()->NotifyUpdate();
5162 }
5163 
OnRemoveLogWindow(CodeBlocksLogEvent & event)5164 void MainFrame::OnRemoveLogWindow(CodeBlocksLogEvent& event)
5165 {
5166     if (Manager::IsAppShuttingDown())
5167         return;
5168     if (event.window)
5169         m_pInfoPane->DeleteNonLogger(event.window);
5170     else
5171         m_pInfoPane->DeleteLogger(event.logger);
5172 }
5173 
OnHideLogWindow(CodeBlocksLogEvent & event)5174 void MainFrame::OnHideLogWindow(CodeBlocksLogEvent& event)
5175 {
5176     if (event.window)
5177         m_pInfoPane->HideNonLogger(event.window);
5178     else if (event.logger)
5179         m_pInfoPane->Hide(event.logger);
5180 }
5181 
OnSwitchToLogWindow(CodeBlocksLogEvent & event)5182 void MainFrame::OnSwitchToLogWindow(CodeBlocksLogEvent& event)
5183 {
5184     if (event.window)
5185         m_pInfoPane->ShowNonLogger(event.window);
5186     else if (event.logger)
5187         m_pInfoPane->Show(event.logger);
5188 }
5189 
OnGetActiveLogWindow(CodeBlocksLogEvent & event)5190 void MainFrame::OnGetActiveLogWindow(CodeBlocksLogEvent& event)
5191 {
5192     bool is_logger;
5193     int page_index = m_pInfoPane->GetCurrentPage(is_logger);
5194 
5195     event.logger = nullptr;
5196     event.window = nullptr;
5197 
5198     if (is_logger)
5199         event.logger = m_pInfoPane->GetLogger(page_index);
5200     else
5201         event.window = m_pInfoPane->GetWindow(page_index);
5202 }
5203 
OnShowLogManager(cb_unused CodeBlocksLogEvent & event)5204 void MainFrame::OnShowLogManager(cb_unused CodeBlocksLogEvent& event)
5205 {
5206     if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false))
5207         return;
5208 
5209     m_LayoutManager.GetPane(m_pInfoPane).Show(true);
5210     DoUpdateLayout();
5211 }
5212 
OnHideLogManager(cb_unused CodeBlocksLogEvent & event)5213 void MainFrame::OnHideLogManager(cb_unused CodeBlocksLogEvent& event)
5214 {
5215     if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false) ||
5216            m_AutoHideLockCounter > 0)
5217         return;
5218 
5219     m_LayoutManager.GetPane(m_pInfoPane).Show(false);
5220     DoUpdateLayout();
5221 }
5222 
OnLockLogManager(cb_unused CodeBlocksLogEvent & event)5223 void MainFrame::OnLockLogManager(cb_unused CodeBlocksLogEvent& event)
5224 {
5225     if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false))
5226         return;
5227     ++m_AutoHideLockCounter;
5228 }
5229 
OnUnlockLogManager(cb_unused CodeBlocksLogEvent & event)5230 void MainFrame::OnUnlockLogManager(cb_unused CodeBlocksLogEvent& event)
5231 {
5232     if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false) &&
5233            m_AutoHideLockCounter > 0)
5234         return;
5235     if (--m_AutoHideLockCounter == 0)
5236     {
5237         m_LayoutManager.GetPane(m_pInfoPane).Show(false);
5238         DoUpdateLayout();
5239     }
5240 }
5241 
5242 // Highlight Button
OnHighlightMenu(cb_unused wxCommandEvent & event)5243 void MainFrame::OnHighlightMenu(cb_unused wxCommandEvent& event)
5244 {
5245     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
5246     if (!ed) return;
5247 
5248     EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
5249     if (!colour_set) return;
5250 
5251     wxMenu* hl = nullptr;
5252     GetMenuBar()->FindItem(idEditHighlightModeText, &hl);
5253     if (!hl)
5254         return;
5255 
5256     wxMenu mm;
5257     const wxMenuItemList &menuItems = hl->GetMenuItems();
5258 
5259     const wxString selectLanguageName = colour_set->GetLanguageName(ed->GetLanguage());
5260 
5261     for (size_t ii = 0; ii < menuItems.GetCount(); ++ii)
5262     {
5263         if (ii > 0 && (ii % 20) == 0)
5264             mm.Break(); // break into columns every 20 items
5265 
5266         const wxMenuItem *item = menuItems[ii];
5267         wxMenuItem *newItem = mm.Append(item->GetId(), item->GetItemLabel(), item->GetHelp(),
5268                                         item->GetKind());
5269         if (item->GetItemLabel() == selectLanguageName)
5270             newItem->Check(true);
5271     }
5272 
5273     wxRect rect;
5274     GetStatusBar()->GetFieldRect(1, rect);
5275     PopupMenu(&mm, GetStatusBar()->GetPosition() + rect.GetPosition());
5276 }
5277 
StartupDone()5278 void MainFrame::StartupDone()
5279 {
5280     m_StartupDone = true;
5281     DoUpdateLayout();
5282 }
5283 
OnCreateStatusBar(int number,long style,wxWindowID id,const wxString & name)5284 wxStatusBar* MainFrame::OnCreateStatusBar(int number, long style, wxWindowID id, const wxString& name)
5285 {
5286     cbStatusBar* sb = new cbStatusBar(this, id, style, name);
5287     sb->SetFieldsCount(number);
5288 
5289     return sb;
5290 }
5291 
5292 // Let the user toggle the toolbar from the context menu
OnMouseRightUp(wxMouseEvent & event)5293 void MainFrame::OnMouseRightUp(wxMouseEvent& event)
5294 {
5295     PopupToggleToolbarMenu();
5296     event.Skip();
5297 }
5298 
OnToolBarRightClick(wxCommandEvent & event)5299 void MainFrame::OnToolBarRightClick(wxCommandEvent& event)
5300 {
5301     PopupToggleToolbarMenu();
5302     event.Skip();
5303 }
5304 
PopupToggleToolbarMenu()5305 void MainFrame::PopupToggleToolbarMenu()
5306 {
5307     wxMenuBar* menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
5308     int idx = menuBar->FindMenu(_("&View"));
5309     if (idx == wxNOT_FOUND)
5310         return;
5311     wxMenu* viewMenu = menuBar->GetMenu(idx);
5312     idx = viewMenu->FindItem(_("Toolbars"));
5313     if (idx == wxNOT_FOUND)
5314         return;
5315 
5316     // Clone the View -> Toolbars menu and show it as popup.
5317     wxMenu* toolbarMenu = viewMenu->FindItem(idx)->GetSubMenu();
5318     wxMenu menu;
5319     for (size_t ii = 0; ii < toolbarMenu->GetMenuItemCount(); ++ii)
5320     {
5321         wxMenuItem *old = toolbarMenu->FindItemByPosition(ii);
5322         if (!old)
5323             continue;
5324         wxMenuItem *item;
5325         item = new wxMenuItem(&menu, old->GetId(), old->GetItemLabelText(), old->GetHelp(), old->GetKind());
5326         menu.Append(item);
5327     }
5328     SetChecksForViewToolbarsMenu(menu);
5329     PopupMenu(&menu);
5330 }
5331 
SetChecksForViewToolbarsMenu(wxMenu & menu)5332 void MainFrame::SetChecksForViewToolbarsMenu(wxMenu &menu)
5333 {
5334     for (size_t i = 0; i < menu.GetMenuItemCount(); ++i)
5335     {
5336         wxMenuItem* item = menu.GetMenuItems()[i];
5337         wxString pluginName = m_PluginIDsMap[item->GetId()];
5338         if (!pluginName.IsEmpty())
5339         {
5340             cbPlugin* plugin = Manager::Get()->GetPluginManager()->FindPluginByName(pluginName);
5341             if (plugin)
5342                 item->Check(m_LayoutManager.GetPane(m_PluginsTools[plugin]).IsShown());
5343         }
5344     }
5345 
5346     menu.Check(idViewToolMain,     m_LayoutManager.GetPane(m_pToolbar).IsShown());
5347     menu.Check(idViewToolDebugger, m_LayoutManager.GetPane(m_debuggerToolbarHandler->GetToolbar(false)).IsShown());
5348 }
5349 
OnGetGlobalAccels(wxCommandEvent & event)5350 void MainFrame::OnGetGlobalAccels(wxCommandEvent& event)
5351 {
5352     event.SetInt(m_AccelCount);
5353     void* pUserVector = event.GetClientData();
5354 
5355     // vector<MyClass*>& v = *reinterpret_cast<vector<MyClass*> *>(voidPointerName);
5356     std::vector<wxAcceleratorEntry>& globalAccels = *reinterpret_cast<std::vector<wxAcceleratorEntry> *>(pUserVector);
5357     event.SetInt(m_AccelCount);
5358     for (size_t ii=0; ii < m_AccelCount; ++ii)
5359         globalAccels.push_back(m_pAccelEntries[ii]);
5360     return;
5361 }
5362