ide: removed redundant activation of output view during build and other actions....
[sdk] / ide / src / ide.ec
1 #ifdef ECERE_STATIC
2 public import static "ecere"
3 public import static "ec"
4 #else
5 public import "ecere"
6 public import "ec"
7 #endif
8
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
12 import "ActiveCompilerDialog"
13
14 #ifdef GDB_DEBUG_GUI
15 import "GDBDialog"
16 #endif
17
18 import "Project"
19 import "ProjectActiveConfig"
20 import "ProjectConfig"
21 import "ProjectNode"
22 import "NodeProperties"
23 import "ProjectSettings"
24 import "ProjectView"
25 import "Workspace"
26
27 import "CodeEditor"
28 import "Designer"
29 import "ToolBox"
30 import "Sheet"
31
32 import "Debugger"
33
34 import "OutputView"
35 import "BreakpointsView"
36 import "CallStackView"
37 import "ThreadsView"
38 import "WatchesView"
39
40 #ifndef NO3D
41 import "ModelView"
42 #endif
43 import "PictureEdit"
44
45 import "about"
46
47 import "FileSystemIterator"
48
49 #if defined(__WIN32__)
50 define pathListSep = ";";
51 #else
52 define pathListSep = ":";
53 #endif
54
55 define maxPathLen = 65 * MAX_LOCATION;
56
57 class PathBackup : struct
58 {
59    String oldLDPath;
60    String oldPath;
61
62    PathBackup()
63    {
64       oldPath = new char[maxPathLen];
65       oldLDPath = new char[maxPathLen];
66
67       GetEnvironment("PATH", oldPath, maxPathLen);
68 #if defined(__APPLE__)
69       GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
70 #else
71       GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
72 #endif
73    }
74
75    ~PathBackup()
76    {
77       SetEnvironment("PATH", oldPath);
78 #if defined(__APPLE__)
79       SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
80 #else
81       SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
82 #endif
83       delete oldPath;
84       delete oldLDPath;
85    }
86 };
87
88 enum OpenCreateIfFails { no, yes, something, whatever };
89 enum OpenMethod { normal, add };
90
91 static Array<FileFilter> fileFilters
92 { [
93    { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
94    { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
95    { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
96    { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
97    { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
98    { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
99    { $"3D Studio Model Files (*.3ds)", "3ds" },
100    { $"All files", null }
101 ] };
102
103 static Array<FileType> fileTypes
104 { [
105    { $"Based on extension", null },
106    { $"Text",               "txt" },
107    { $"Image",              "jpg" },
108    { $"3D Studio Model",    "3ds" }
109 ] };
110
111 static Array<FileFilter> projectFilters
112 { [
113    { $"Project Files (*.epj)", ProjectExtension }
114 ] };
115
116 static Array<FileType> projectTypes
117 { [
118    { $"Project File", ProjectExtension }
119 ] };
120
121 static Array<FileFilter> findInFilesFileFilters
122 { [
123    { $"eC Files (*.ec, *.eh)", "ec, eh" },
124    { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
125    { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
126    { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
127    { $"Text files (*.txt)", "txt" },
128    { $"All files", null }
129 ] };
130
131 FileDialog ideFileDialog
132 {
133    type = multiOpen, text = $"Open";
134    types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
135 };
136
137 define openProjectFileDialogTitle = $"Open Project";
138 define addProjectFileDialogTitle = $"Open Additional Project";
139 FileDialog ideProjectFileDialog
140 {
141    type = open;
142    types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
143 };
144
145 GlobalSettingsDialog globalSettingsDialog
146 {
147    ideSettings = ideSettings;
148    settingsContainer = settingsContainer;
149
150    void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
151    {
152       switch(globalSettingsChange)
153       {
154          case editorSettings:
155          {
156             Window child;
157             for(child = ide.firstChild; child; child = child.next)
158             {
159                if(child._class == class(CodeEditor))
160                {
161                   CodeEditor codeEditor = (CodeEditor) child;
162                   codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
163                   // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
164                   codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
165                   codeEditor.OnPostCreate(); // Update editBox margin size
166                }
167             }
168             break;
169          }
170          case projectOptions:
171             break;
172          case compilerSettings:
173          {
174             ide.UpdateMakefiles();
175             break;
176          }
177       }
178    }
179 };
180
181 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
182 {
183    int lineY;
184    if(line)
185    {
186       lineY = (line - 1) * lineH;
187       if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
188       {
189          Bitmap bitmap = resource.bitmap;
190          if(bitmap)
191             surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
192       }
193    }
194 }
195
196 #define IDEItem(x)   (&((IDEWorkSpace)0).x)
197
198 class IDEToolbar : ToolBar
199 {
200    /* File options */
201    // New
202    ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
203    // Open
204    ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
205    // Close
206    // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
207    // Save
208    ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
209    // Save All
210    ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
211
212    ToolSeparator separator1 { this };
213
214    /* Edit options */
215    // Cut
216    // Copy 
217    // Paste
218    // Undo
219    // Redo
220
221    // ToolSeparator separator2 { this };
222
223    /* Project  options */
224    // New project
225    ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
226    // Open project
227    ToolButton buttonOpenProject { this, toolTip = $"Open project", menuItemPtr = IDEItem(projectOpenItem) };
228    // Add project to workspace
229    ToolButton buttonAddProject { this, toolTip = $"Add project to workspace", menuItemPtr = IDEItem(projectAddItem), disabled = true; };
230    // Close project
231    // ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
232
233    ToolSeparator separator3 { this };
234
235    /* Build/Execution options */
236    // Build
237    ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
238    // Re-link
239    ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
240    // Rebuild
241    ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
242    // Clean
243    ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
244    // Real Clean
245    // ToolButton buttonRealClean { this, toolTip = $"Real clean project", menuItemPtr = IDEItem(projectRealCleanItem), disabled = true; };
246    // Regenerate Makefile
247    ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
248    // Compile actual file
249    // Execute
250    ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
251
252    ToolSeparator separator4 { this };
253
254    /* Debug options */
255    // Start/Resume
256    ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
257    // Restart
258    ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
259    // Pause
260    ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
261    // Stop
262    ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
263    // Breakpoints
264    //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
265    // F11
266    ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
267    // F10
268    ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
269    // Shift+F11
270    ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
271    // Shift+F10
272    ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
273 }
274
275 class IDEMainFrame : Window
276 {
277    background = formColor;
278    borderStyle = sizable;
279    hasMaximize = true;
280    hasMinimize = true;
281    hasClose = true;
282    minClientSize = { 600, 300 };
283    hasMenuBar = true;
284    icon = { ":icon.png" };
285    text = titleECEREIDE;
286 #if 0 //def _DEBUG
287    //stayOnTop = true;
288    size = { 800, 600 };
289    anchor = { top = 0, right = 0, bottom = 0 };
290 #else
291    state = maximized;
292    anchor = { left = 0, top = 0, right = 0, bottom = 0 };
293 #endif
294
295    Stacker stack
296    {
297       this;
298       menu = { };
299       isActiveClient = true;
300       gap = 0;
301       direction = vertical;
302       background = formColor;
303       anchor = { left = 0, top = 0, right = 0, bottom = 0 };
304    };
305    IDEToolbar toolBar
306    {
307       stack, ideWorkSpace;
308
309       void OnDestroy(void)
310       {
311          ((IDEWorkSpace)master).toolBar = null;
312       }
313    };
314    IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
315 }
316
317 define ide = ideMainFrame.ideWorkSpace;
318
319 class IDEWorkSpace : Window
320 {
321    background = Color { 85, 85, 85 };
322
323    //tabCycle = true;
324    hasVertScroll = true;
325    hasHorzScroll = true;
326    hasStatusBar = true;
327    isActiveClient = true;
328    anchor = { left = 0, top = 0, right = 0, bottom = 0 };
329    menu = Menu {  };
330    IDEToolbar toolBar;
331
332    MenuItem * driverItems, * skinItems;
333    StatusField pos { width = 150 };
334    StatusField ovr, caps, num;
335
336    BitmapResource back                 { ":ecereBack.jpg", window = this };
337    BitmapResource bmpBp                { ":codeMarks/breakpoint.png", window = this };
338    BitmapResource bmpBpDisabled        { ":codeMarks/breakpointDisabled.png", window = this };
339    BitmapResource bmpBpHalf            { ":codeMarks/breakpointHalf.png", window = this };
340    BitmapResource bmpBpHalfDisabled    { ":codeMarks/breakpointHalfDisabled.png", window = this };
341    BitmapResource bmpCursor            { ":codeMarks/cursor.png", window = this };
342    BitmapResource bmpCursorError       { ":codeMarks/cursorError.png", window = this };
343    BitmapResource bmpTopFrame          { ":codeMarks/topFrame.png", window = this };
344    BitmapResource bmpTopFrameError     { ":codeMarks/topFrameError.png", window = this };
345    BitmapResource bmpTopFrameHalf      { ":codeMarks/topFrameHalf.png", window = this };
346    BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
347    
348    Debugger debugger { };
349
350    ProjectView projectView;
351
352    OutputView outputView
353    {
354       parent = this;
355
356       void OnGotoError(char * line)
357       {
358          ide.GoToError(line);
359       }
360
361       void OnCodeLocationParseAndGoTo(char * line)
362       {
363          ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
364       }
365
366       bool OnKeyDown(Key key, unichar ch)
367       {
368          switch(key)
369          {
370             case escape: 
371                if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
372                   ide.ShowCodeEditor(); 
373                break;
374             case ctrlS:
375                ide.projectView.stopBuild = true;
376                break;
377             default:
378             {
379                OutputView::OnKeyDown(key, ch);
380                break;
381             }
382          }
383          return true;
384       }
385
386       bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
387       {
388          if(active)
389             ide.RepositionWindows(false);
390          return true;
391       }
392
393       bool OnClose(bool parentClosing)
394       {
395          visible = false;
396          if(!parentClosing)
397             ide.RepositionWindows(false);
398          return parentClosing;
399       }
400    };
401
402    CallStackView callStackView
403    {
404       parent = this, font = { panelFont.faceName, panelFont.size };
405
406       void OnGotoLine(char * line)
407       {
408          int stackLvl;
409          stackLvl = atoi(line);
410          ide.debugger.GoToStackFrameLine(stackLvl, true);
411       }
412
413       void OnSelectFrame(int lineNumber)
414       {
415          ide.debugger.SelectFrame(lineNumber);
416       }
417
418       void OnToggleBreakpoint()
419       {
420          Debugger debugger = ide.debugger;
421          if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
422          {
423             int line = debugger.activeFrame.line;
424             char name[MAX_LOCATION];
425             Project prj = null;
426             // TOFIX: Improve on this, don't use only filename, make a function
427             GetLastDirectory(debugger.activeFrame.absoluteFile, name);
428             if(ide && ide.workspace)
429             {
430                for(p : ide.workspace.projects)
431                {
432                   if(p.topNode.Find(name, false))
433                   {
434                      prj = p;
435                      break;
436                   }
437                }
438                if(!prj)
439                {
440                   for(p : ide.workspace.projects)
441                   {
442                      if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
443                      {
444                         prj = p;
445                         break;
446                      }
447                   }
448                }
449             }
450             debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
451             Update(null);
452             {
453                CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
454                if(codeEditor) { codeEditor.Update(null); Activate(); }
455             }
456          }
457       }
458
459       bool OnKeyDown(Key key, unichar ch)
460       {
461          switch(key)
462          {
463             case escape: ide.ShowCodeEditor(); break;
464          }
465          return true;
466       }
467
468       bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
469       {
470          if(active)
471             ide.RepositionWindows(false);
472          return true;
473       }
474
475       bool OnClose(bool parentClosing)
476       {
477          visible = false;
478          if(!parentClosing)
479             ide.RepositionWindows(false);
480          return parentClosing;
481       }
482
483       void OnRedraw(Surface surface)
484       {
485          bool error;
486          int lineCursor, lineTopFrame, activeThread, hitThread;
487          int lineH, scrollY, boxH;
488          BitmapResource bmp;
489          Breakpoint bp = null;
490          Debugger debugger = ide.debugger;
491          Frame activeFrame = debugger.activeFrame;
492
493          boxH = clientSize.h;
494          scrollY = editBox.scroll.y;
495          displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
496
497          activeThread = debugger.activeThread;
498          hitThread = debugger.hitThread;
499          debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
500
501          if(activeFrame && activeFrame.absoluteFile)
502          {
503             for(i : ide.workspace.breakpoints; i.type == user)
504             {
505                if(i.absoluteFilePath && i.absoluteFilePath[0] && 
506                   !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
507                   activeFrame.line == i.line)
508                {
509                   bp = i;
510                   break;
511                }
512             }
513          }
514
515          if(bp)
516             DrawLineMarginIcon(surface,
517                   /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
518                   lineCursor /*1*/, lineH, scrollY, boxH);
519
520          /*
521          if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
522             DrawLineMarginIcon(surface,
523                   (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
524                   1, lineH, scrollY, boxH);
525          */
526          DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
527          if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
528             bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
529          else
530             bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
531          DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
532          if(editBox.horzScroll && editBox.horzScroll.visible)
533          {
534             surface.SetBackground(control);
535             surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
536          }
537       }
538    };
539    
540    WatchesView watchesView { parent = this };
541    ThreadsView threadsView
542    {
543       parent = this, font = { panelFont.faceName, panelFont.size };
544
545       bool OnKeyDown(Key key, unichar ch)
546       {
547          switch(key)
548          {
549             case escape: ide.ShowCodeEditor(); break;
550          }
551          return true;
552       }
553
554       bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
555       {
556          if(active)
557             ide.RepositionWindows(false);
558          return true;
559       }
560
561       bool OnClose(bool parentClosing)
562       {
563          visible = false;
564          if(!parentClosing)
565             ide.RepositionWindows(false);
566          return parentClosing;
567       }
568
569       void OnSelectThread(int threadId)
570       {
571          if(threadId)
572             ide.debugger.SelectThread(threadId);
573       }
574
575       bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
576       {
577          bool result = false;
578          Debugger debugger = ide.debugger;
579          *activeThread = debugger.activeThread;
580          *hitThread = debugger.hitThread;
581          *signalThread = debugger.signalThread;
582          result = true;
583          return result;
584       }
585    };
586    BreakpointsView breakpointsView { parent = this };
587
588    ToolBox toolBox { parent = this };
589    Sheet sheet { parent = this };
590
591    char * tmpPrjDir;
592    property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
593
594    Menu fileMenu { menu, $"File", f, hasMargin = true };
595       MenuItem fileNewItem
596       {
597          fileMenu, $"New", n, ctrlN;
598          bitmap = { ":actions/docNew.png" };
599          bool NotifySelect(MenuItem selection, Modifiers mods)
600          {
601             Window document = (Window)NewCodeEditor(this, normal, false);
602             document.NotifySaved = DocumentSaved;
603             return true;
604          }
605       }
606       MenuItem fileOpenItem
607       {
608          fileMenu, $"Open...", o, ctrlO;
609          bitmap = { ":actions/docOpen.png" };
610          bool NotifySelect(MenuItem selection, Modifiers mods)
611          {
612             if(!projectView && ideSettings.ideFileDialogLocation)
613                ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
614             for(;;)
615             {
616                if(ideFileDialog.Modal() == ok)
617                {
618                   bool gotWhatWeWant = false;
619                   int c;
620                   int numSelections = ideFileDialog.numSelections;
621                   char ** multiFilePaths = ideFileDialog.multiFilePaths;
622
623                   for(c = 0; c < numSelections; c++)
624                   {
625                      if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
626                         gotWhatWeWant = true;
627                   }
628                   if(gotWhatWeWant ||
629                      MessageBox { type = yesNo, master = this, text = $"Error opening file", 
630                      contents = $"Open a different file?" }.Modal() == no)
631                   {
632                      if(!projectView && gotWhatWeWant)
633                         ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
634                      break;
635                   }
636                }
637                else
638                   break;
639             }
640             return true;
641          }
642       }
643       MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
644       MenuDivider { fileMenu };
645       MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" } };
646       MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
647       MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
648       MenuDivider { fileMenu };
649       MenuItem findInFiles
650       {
651          fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
652          bool NotifySelect(MenuItem selection, Modifiers mods)
653          {
654             findInFilesDialog.replaceMode = false;
655             findInFilesDialog.Show();
656             return true;
657          }
658       }
659       MenuItem replaceInFiles
660       {
661          fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
662          bool NotifySelect(MenuItem selection, Modifiers mods)
663          {
664             findInFilesDialog.replaceMode = true;
665             findInFilesDialog.Show();
666             return true;
667          }
668       }
669       MenuDivider { fileMenu };
670       MenuItem globalSettingsItem
671       {
672          fileMenu, $"Global Settings...", g;
673          bool NotifySelect(MenuItem selection, Modifiers mods)
674          {
675             globalSettingsDialog.master = this;
676             if(ide.workspace && ide.workspace.compiler)
677                globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
678             else if(ideSettings.defaultCompiler)
679                globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
680             globalSettingsDialog.Modal();
681             return true;
682          }
683       }
684       MenuDivider { fileMenu };
685       Menu recentFiles { fileMenu, $"Recent Files", r };
686       Menu recentProjects { fileMenu, $"Recent Projects", p };
687       MenuDivider { fileMenu };
688       MenuItem exitItem
689       {
690          fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
691
692          bool NotifySelect(MenuItem selection, Modifiers mods)
693          {
694             ideMainFrame.Destroy(0);
695             return true;
696          }
697       };
698
699       bool FileRecentFile(MenuItem selection, Modifiers mods)
700       {
701          int id = 0;
702          for(file : ideSettings.recentFiles)
703          {
704             if(id == selection.id)
705             {
706                OpenFile(file, normal, true, null, no, normal);
707                break;
708             }
709             id++;
710          }
711          return true;
712       }
713
714       bool FileRecentProject(MenuItem selection, Modifiers mods)
715       {
716          int id = 0;
717          for(file : ideSettings.recentProjects)
718          {
719             if(id == selection.id)
720             {
721                OpenFile(file, normal, true, null, no, normal);
722                break;
723             }
724             id++;
725          }
726          return true;
727       }
728
729    MenuPlacement editMenu { menu, $"Edit", e };
730    
731    Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
732       MenuItem projectNewItem
733       {
734          projectMenu, $"New...", n, Key { n, true, true };
735          bitmap = { ":actions/projNew.png" };
736          bool NotifySelect(MenuItem selection, Modifiers mods)
737          {
738             if(!DontTerminateDebugSession($"New Project"))
739                if(MenuWindowCloseAll(null, 0))
740                {
741                   NewProjectDialog newProjectDialog;
742
743                   if(projectView)
744                   {
745                      projectView.visible = false;
746                      if(!projectView.Destroy(0))
747                         return true;
748                   }
749                   
750                   newProjectDialog = { master = this };
751                   newProjectDialog.Modal();
752                   if(projectView)
753                   {
754                      ideSettings.AddRecentProject(projectView.fileName);
755                      ide.UpdateRecentMenus();
756                      settingsContainer.Save();
757                   }
758                }
759             return true;
760          }
761       }
762       MenuItem projectOpenItem
763       {
764          projectMenu, $"Open...", o, Key { o, true, true };
765          bitmap = { ":actions/projOpen.png" };
766          bool NotifySelect(MenuItem selection, Modifiers mods)
767          {
768             if(ideSettings.ideProjectFileDialogLocation)
769                ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
770
771             ideProjectFileDialog.text = openProjectFileDialogTitle;
772             if(ideProjectFileDialog.Modal() == ok)
773             {
774                OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
775                //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
776             }
777             return true;
778          }
779       }
780       MenuItem projectQuickItem
781       {
782          projectMenu, $"Quick...", q, f7;
783          bool NotifySelect(MenuItem selection, Modifiers mods)
784          {
785             if(!projectView)
786                QuickProjectDialog{ this }.Modal();
787             return true;
788          }
789       }
790       MenuItem projectAddItem
791       {
792          projectMenu, $"Add project to workspace...", a, Key { a, true, true };
793          bitmap = { ":actions/projAdd.png" };
794          disabled = true;
795          bool NotifySelect(MenuItem selection, Modifiers mods)
796          {
797             if(ideSettings.ideProjectFileDialogLocation)
798                ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
799
800             ideProjectFileDialog.text = addProjectFileDialogTitle;
801             for(;;)
802             {
803                if(ideProjectFileDialog.Modal() == ok)
804                {
805                   if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
806                      break;
807                   if(MessageBox { type = yesNo, master = this, text = $"Error opening project file", 
808                         contents = $"Add a different project?" }.Modal() == no)
809                   {
810                      break;
811                   }
812                }
813                else
814                   break;
815             }
816             return true;
817          }
818       }
819       MenuItem projectCloseItem
820       {
821          projectMenu, $"Close", c, disabled = true;
822          bool NotifySelect(MenuItem selection, Modifiers mods)
823          {
824             if(projectView)
825             {
826                if(!ide.DontTerminateDebugSession($"Project Close"))
827                {
828                   if(findInFilesDialog)
829                      findInFilesDialog.SearchStop();
830                   projectView.visible = false;
831                   if(projectView.Destroy(0))
832                      MenuWindowCloseAll(null, 0);
833                   {
834                      char workingDir[MAX_LOCATION];
835                      GetWorkingDir(workingDir, MAX_LOCATION);
836                      findInFilesDialog.currentDirectory = workingDir;
837                      ideMainFrame.text = titleECEREIDE;
838                   }
839                }
840             }
841             return true;
842          }
843       }
844       MenuDivider { projectMenu };
845       MenuItem activeCompilerItem
846       {
847          projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
848          bool NotifySelect(MenuItem selection, Modifiers mods)
849          {
850             projectView.MenuCompiler(null, mods);
851             return true;
852          }
853       }
854       MenuItem projectActiveConfigItem
855       {
856          projectMenu, $"Active Configuration...", g, altF5, disabled = true;
857          bool NotifySelect(MenuItem selection, Modifiers mods)
858          {
859             projectView.MenuConfig(projectView.active ? selection : null, mods);
860             return true;
861          }
862       }
863       MenuItem projectSettingsItem
864       {
865          projectMenu, $"Settings...", s, altF7, disabled = true;
866          bool NotifySelect(MenuItem selection, Modifiers mods)
867          {
868             projectView.MenuSettings(projectView.active ? selection : null, mods);
869             return true;
870          }
871       }
872       MenuDivider { projectMenu };
873       MenuItem projectBrowseFolderItem
874       {
875          projectMenu, $"Browse Project Folder", p, disabled = true;
876          bool NotifySelect(MenuItem selection, Modifiers mods)
877          {
878             if(projectView)
879                projectView.MenuBrowseFolder(null, mods);
880             return true;
881          }
882       }
883       MenuDivider { projectMenu };
884       MenuItem projectRunItem
885       {
886          projectMenu, $"Run", r, ctrlF5, disabled = true;
887          bitmap = { ":actions/run.png" };
888          bool NotifySelect(MenuItem selection, Modifiers mods)
889          {
890             if(projectView)
891                projectView.Run(null, mods);
892             return true;
893          }
894       }
895       MenuItem projectBuildItem
896       {
897          projectMenu, $"Build", b, f7, disabled = true;
898          bitmap = { ":actions/build.png" };
899          bool NotifySelect(MenuItem selection, Modifiers mods)
900          {
901             if(projectView)
902                projectView.ProjectBuild(projectView.active ? selection : null, mods);
903             return true;
904          }
905       }
906       MenuItem projectLinkItem
907       {
908          projectMenu, $"Relink", l, disabled = true;
909          bitmap = { ":actions/relink.png" };
910          bool NotifySelect(MenuItem selection, Modifiers mods)
911          {
912             if(projectView)
913                projectView.ProjectLink(projectView.active ? selection : null, mods);
914             return true;
915          }
916       }
917       MenuItem projectRebuildItem
918       {
919          projectMenu, $"Rebuild", d, shiftF7, disabled = true;
920          bitmap = { ":actions/rebuild.png" };
921          bool NotifySelect(MenuItem selection, Modifiers mods)
922          {
923             if(projectView)
924                projectView.ProjectRebuild(projectView.active ? selection : null, mods);
925             return true;
926          }
927       }
928       MenuItem projectCleanItem
929       {
930          projectMenu, $"Clean", e, disabled = true;
931          bitmap = { ":actions/clean.png" };
932          bool NotifySelect(MenuItem selection, Modifiers mods)
933          {
934             if(projectView)
935             {
936                debugger.Stop();
937                projectView.ProjectClean(projectView.active ? selection : null, mods);
938             }
939             return true;
940          }
941       }
942       MenuItem projectRealCleanItem
943       {
944          projectMenu, $"Real Clean", disabled = true;
945          bitmap = { ":actions/clean.png" };
946          bool NotifySelect(MenuItem selection, Modifiers mods)
947          {
948             if(projectView)
949             {
950                debugger.Stop();
951                projectView.ProjectRealClean(projectView.active ? selection : null, mods);
952             }
953             return true;
954          }
955       }
956       MenuItem projectRegenerateItem
957       {
958          projectMenu, $"Regenerate Makefile", m, disabled = true;
959          bitmap = { ":actions/regMakefile.png" };
960          bool NotifySelect(MenuItem selection, Modifiers mods)
961          {
962             if(projectView)
963                projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
964             return true;
965          }
966       }
967       MenuItem projectCompileItem;
968    Menu debugMenu { menu, $"Debug", d, hasMargin = true };
969       MenuItem debugStartResumeItem
970       {
971          debugMenu, $"Start", s, f5, disabled = true;
972          bitmap = { ":actions/debug.png" };
973          NotifySelect = MenuDebugStart;
974       }
975       bool MenuDebugStart(MenuItem selection, Modifiers mods)
976       {
977          if(projectView)
978          {
979             debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
980             if(!projectView.DebugStart())
981                debugStartResumeItem.disabled = false; // same exception
982          }
983          return true;
984       }
985       bool MenuDebugResume(MenuItem selection, Modifiers mods)
986       {
987          if(projectView)
988             projectView.DebugResume();
989          return true;
990       }
991       MenuItem debugRestartItem
992       {
993          debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
994          bitmap = { ":actions/restart.png" };
995          bool NotifySelect(MenuItem selection, Modifiers mods)
996          {
997             if(projectView)
998                projectView.DebugRestart();
999             return true;
1000          }
1001       }
1002       MenuItem debugBreakItem
1003       {
1004          debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1005          bitmap = { ":actions/pause.png" };
1006          bool NotifySelect(MenuItem selection, Modifiers mods)
1007          {
1008             if(projectView)
1009                projectView.DebugBreak();
1010             return true;
1011          }
1012       }
1013       MenuItem debugStopItem
1014       {
1015          debugMenu, $"Stop", p, shiftF5, disabled = true;
1016          bitmap = { ":actions/stopDebug.png" };
1017          bool NotifySelect(MenuItem selection, Modifiers mods)
1018          {
1019             if(projectView)
1020                projectView.DebugStop();
1021             return true;
1022          }
1023       }
1024       MenuDivider { debugMenu };
1025       MenuItem debugStepIntoItem
1026       {
1027          debugMenu, $"Step Into", i, f11, disabled = true;
1028          bitmap = { ":actions/stepInto.png" };
1029          bool NotifySelect(MenuItem selection, Modifiers mods)
1030          {
1031             if(projectView)
1032                projectView.DebugStepInto();
1033             return true;
1034          }
1035       }
1036       MenuItem debugStepOverItem
1037       {
1038          debugMenu, $"Step Over", v, f10, disabled = true;
1039          bitmap = { ":actions/stepOver.png" };
1040          bool NotifySelect(MenuItem selection, Modifiers mods)
1041          {
1042             if(projectView)
1043                projectView.DebugStepOver(false);
1044             return true;
1045          }
1046       }
1047       MenuItem debugStepOutItem
1048       {
1049          debugMenu, $"Step Out", o, shiftF11, disabled = true;
1050          bitmap = { ":actions/stepOut.png" };
1051          bool NotifySelect(MenuItem selection, Modifiers mods)
1052          {
1053             if(projectView)
1054                projectView.DebugStepOut(false);
1055             return true;
1056          }
1057       }
1058       MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1059       MenuItem debugSkipStepOverItem
1060       {
1061          debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1062          bool NotifySelect(MenuItem selection, Modifiers mods)
1063          {
1064             if(projectView)
1065                projectView.DebugStepOver(true);
1066             return true;
1067          }
1068       }
1069       MenuItem debugSkipStepOutItem
1070       {
1071          debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1072          bitmap = { ":actions/skipBreaks.png" };
1073          bool NotifySelect(MenuItem selection, Modifiers mods)
1074          {
1075             if(projectView)
1076                projectView.DebugStepOut(true);
1077             return true;
1078          }
1079       }
1080       MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1081       //MenuDivider { debugMenu };
1082       //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1083    MenuPlacement imageMenu { menu, $"Image", i };
1084    Menu viewMenu { menu, $"View", v };
1085       MenuItem viewProjectItem
1086       {
1087          viewMenu, $"Project View", j, alt0, disabled = true;
1088          bool NotifySelect(MenuItem selection, Modifiers mods)
1089          {
1090             if(projectView)
1091             {
1092                projectView.visible = true;
1093                projectView.Activate();
1094             }
1095             return true;
1096          }
1097       }
1098       MenuPlacement { viewMenu, $"View Designer" };
1099       MenuPlacement { viewMenu, $"View Code" };
1100       MenuPlacement { viewMenu, $"View Properties" };
1101       MenuPlacement { viewMenu, $"View Methods" };
1102       MenuItem viewDesignerItem
1103       {
1104          viewMenu, $"View Designer", d, f8;
1105          bool NotifySelect(MenuItem selection, Modifiers mods)
1106          {
1107             Window client = activeClient;
1108             Class dataType = client._class;
1109             if(!strcmp(dataType.name, "Designer"))
1110             {
1111                client.visible = true;
1112                client.Activate();
1113             }
1114             else
1115                ((CodeEditor)client).ViewDesigner();
1116             return true;
1117          }
1118       }
1119       MenuItem viewCodeItem
1120       {
1121          viewMenu, $"View Code", c, f8;
1122          bool NotifySelect(MenuItem selection, Modifiers mods)
1123          {
1124             Window client = activeClient;
1125             Class dataType = client._class;
1126             if(!strcmp(dataType.name, "Designer"))
1127                client = ((Designer)client).codeEditor;
1128
1129             client.Activate();
1130             // Do this after so the caret isn't moved yet...
1131             client.visible = true;
1132             return true;
1133          }
1134       }
1135       MenuItem viewPropertiesItem
1136       {
1137          viewMenu, $"View Properties", p, f4;
1138          bool NotifySelect(MenuItem selection, Modifiers mods)
1139          {
1140             sheet.visible = true;
1141             sheet.sheetSelected = properties;
1142             sheet.Activate();
1143             return true;
1144          }
1145       }
1146       MenuItem viewMethodsItem
1147       {
1148          viewMenu, $"View Methods", m, f4;
1149          bool NotifySelect(MenuItem selection, Modifiers mods)
1150          {
1151             sheet.visible = true;
1152             sheet.sheetSelected = methods;
1153             sheet.Activate();
1154             return true;
1155          }
1156       }
1157       MenuItem viewToolBoxItem
1158       {
1159          viewMenu, $"View Toolbox", x, f12;
1160          bool NotifySelect(MenuItem selection, Modifiers mods)
1161          {
1162             toolBox.visible = true;
1163             toolBox.Activate();
1164             return true;
1165          }
1166       }
1167       MenuItem viewOutputItem
1168       {
1169          viewMenu, $"Output", o, alt2;
1170          bool NotifySelect(MenuItem selection, Modifiers mods)
1171          {
1172             outputView.Show();
1173             return true;
1174          }
1175       }
1176       MenuItem viewWatchesItem
1177       {
1178          viewMenu, $"Watches", w, alt3;
1179          bool NotifySelect(MenuItem selection, Modifiers mods)
1180          {
1181             watchesView.Show();
1182             return true;
1183          }
1184       }
1185       MenuItem viewThreadsItem
1186       {
1187          viewMenu, $"Threads", t, alt4;
1188          bool NotifySelect(MenuItem selection, Modifiers mods)
1189          {
1190             threadsView.Show();
1191             return true;
1192          }
1193       }
1194       MenuItem viewBreakpointsItem
1195       {
1196          viewMenu, $"Breakpoints", b, alt5;
1197          bool NotifySelect(MenuItem selection, Modifiers mods)
1198          {
1199             breakpointsView.Show();
1200             return true;
1201          }
1202       }
1203       MenuItem viewCallStackItem
1204       {
1205          viewMenu, $"Call Stack", s, alt7;
1206          bool NotifySelect(MenuItem selection, Modifiers mods)
1207          {
1208             callStackView.Show();
1209             return true;
1210          }
1211       }
1212       MenuItem viewAllDebugViews
1213       {
1214          viewMenu, $"All Debug Views", a, alt9;
1215          bool NotifySelect(MenuItem selection, Modifiers mods)
1216          {
1217             outputView.Show();
1218             watchesView.Show();
1219             threadsView.Show();
1220             callStackView.Show();
1221             breakpointsView.Show();
1222             return true;
1223          }
1224       }
1225 #ifdef GDB_DEBUG_GUI
1226       MenuDivider { viewMenu };
1227       MenuItem viewGDBItem
1228       {
1229          viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1230          bool NotifySelect(MenuItem selection, Modifiers mods)
1231          {
1232             gdbDialog.Show();
1233             return true;
1234          }
1235       }
1236 #endif
1237       MenuDivider { viewMenu };
1238       MenuItem viewColorPicker
1239       {
1240          viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1241          bool NotifySelect(MenuItem selection, Modifiers mods)
1242          {
1243             ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1244             colorPicker.Create();
1245             return true;
1246          }
1247       }
1248       MenuDivider { viewMenu };
1249       /*
1250       MenuItem
1251       {
1252          viewMenu, "Full Screen", f, checkable = true;
1253
1254          bool NotifySelect(MenuItem selection, Modifiers mods)
1255          {
1256             app.fullScreen ^= true;
1257             SetDriverAndSkin();
1258             anchor = { 0, 0, 0, 0 };
1259             return true;
1260          }
1261       };
1262       */
1263       Menu driversMenu { viewMenu, $"Graphics Driver", v };
1264       //Menu skinsMenu { viewMenu, "GUI Skins", k };
1265    Menu windowMenu { menu, $"Window", w };
1266       MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1267       MenuDivider { windowMenu };
1268       MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1269       MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1270       MenuDivider { windowMenu };
1271       MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1272       MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1273       MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1274       MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1275       MenuDivider { windowMenu };
1276       MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1277    Menu helpMenu { menu, $"Help", h };
1278       MenuItem
1279       {
1280          helpMenu, $"API Reference", r, f1;
1281          bool NotifySelect(MenuItem selection, Modifiers mods)
1282          {
1283             Execute("documentor");
1284             return true;
1285          }
1286       }
1287       MenuDivider { helpMenu };
1288       MenuItem
1289       {
1290          helpMenu, $"About...", a;
1291          bool NotifySelect(MenuItem selection, Modifiers mods)
1292          {
1293             AboutIDE { master = this }.Modal();
1294             return true;
1295          }
1296       }
1297
1298    property ToolBox toolBox
1299    {
1300       get { return toolBox; }
1301    }
1302
1303    property Sheet sheet
1304    {
1305       get { return sheet; }
1306    }
1307
1308    property Project project
1309    {
1310       get { return projectView ? projectView.project : null; }
1311    }
1312
1313    property Workspace workspace
1314    {
1315       get { return projectView ? projectView.workspace : null; }
1316    }
1317
1318    FindInFilesDialog findInFilesDialog
1319    {
1320       master = this, parent = this;
1321       filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1322       filter = 1;
1323    };
1324
1325 #ifdef GDB_DEBUG_GUI
1326    GDBDialog gdbDialog
1327    {
1328       master = this, parent = this;
1329       anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1330
1331       void OnCommand(char * string)
1332       {
1333          if(ide)
1334             ide.debugger.SendGDBCommand(string);
1335       }
1336    };
1337 #endif
1338    
1339    bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1340    {
1341       //app.driver = app.drivers[selection.id];
1342 #ifdef __unix__
1343       app.driver = selection.id ? "OpenGL" : "X";
1344 #else
1345       app.driver = selection.id ? "OpenGL" : "GDI";
1346 #endif
1347       delete ideSettings.displayDriver;
1348       ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1349
1350       settingsContainer.Save();
1351       //SetDriverAndSkin();
1352       return true;
1353    }
1354
1355    bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1356    {
1357       app.skin = app.skins[selection.id];
1358       SetDriverAndSkin();
1359       return true;
1360    }
1361
1362    void SetDriverAndSkin()
1363    {
1364       int c;
1365       for(c = 0; c < app.numSkins; c++)
1366          if(!strcmp(app.skins[c], app.skin))
1367          {
1368             skinItems[c].checked = true;
1369             break;
1370          }
1371       for(c = 0; c < app.numDrivers; c++)
1372          if(!strcmp(app.drivers[c], app.driver))
1373          {
1374             driverItems[c].checked = true;
1375             break;
1376          }
1377    }
1378
1379    ProjectView CreateProjectView(Workspace workspace, char * fileName)
1380    {
1381       Project project = workspace.projects.firstIterator.data;
1382       projectView = ProjectView
1383       {
1384          this;
1385          fileName = fileName;
1386          
1387          void NotifyDestroyed(Window window, DialogResult result)
1388          {
1389             projectView = null;
1390             text = titleECEREIDE;
1391             
1392             AdjustMenus();
1393          }
1394       };
1395       projectView.Create();
1396       RepositionWindows(false);
1397
1398       // Leave it after Create to avoid flicker due to seeing IDE without a project view
1399       projectView.workspace = workspace;
1400       projectView.project = project;
1401       ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1402
1403       AdjustMenus();
1404
1405       ide.breakpointsView.LoadFromWorkspace();
1406       ide.watchesView.LoadFromWorkspace();
1407
1408       findInFilesDialog.projectNodeField.userData = projectView;
1409
1410       {
1411          char fileName[MAX_LOCATION];
1412          strcpy(fileName, project.topNode.path);
1413          PathCat(fileName, project.topNode.name);
1414       }
1415       return projectView;
1416    }
1417
1418    bool GetDebugMenusDisabled()
1419    {
1420       if(projectView)
1421       {
1422          Project project = projectView.project;
1423          if(project)
1424             if(project.GetTargetType(project.config) == executable)
1425                return false;
1426            
1427       }
1428       return true;
1429    }
1430
1431    void RepositionWindows(bool expand)
1432    {
1433       if(this)
1434       {
1435          Window child;
1436          bool inDebugMode = debugger.isActive;
1437          bool callStackVisible = expand ? false : callStackView.visible;
1438          bool threadsVisible = expand ? false : threadsView.visible;
1439          bool watchesVisible = expand ? false : watchesView.visible;
1440          bool breakpointsVisible = expand ? false : breakpointsView.visible;
1441          bool toolBoxVisible = toolBox.visible;
1442          bool outputVisible = expand ? false : outputView.visible;
1443          int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1444          int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1445          
1446          for(child = firstChild; child; child = child.next)
1447          {
1448             if(child._class == class(CodeEditor) || child._class == class(Designer) || 
1449                child._class == class(Sheet) || child._class == class(ProjectView))
1450             {
1451                Anchor anchor = child.anchor;
1452                anchor.top = topDistance;
1453                anchor.bottom = bottomDistance;
1454                if(child._class == class(CodeEditor) || child._class == class(Designer))
1455                {
1456                   anchor.right = toolBoxVisible ? 150 : 0;
1457                }
1458                child.anchor = anchor;
1459             }
1460             else if(expand)
1461             {
1462                if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) || 
1463                   child._class == class(BreakpointsView))
1464                   child.visible = false;
1465             }
1466          }
1467          // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1468          Update(null);
1469       }
1470    }
1471
1472    bool ShowCodeEditor()
1473    {
1474       if(activeClient)
1475          activeClient.Activate();
1476       else if(projectView)
1477       { 
1478          projectView.visible = true;
1479          projectView.Activate();
1480       }
1481       else
1482       {
1483          sheet.visible = true;
1484          sheet.Activate();
1485       }
1486       return false;
1487    }
1488
1489    bool ShouldStopBuild()
1490    {
1491       return projectView.stopBuild;
1492    }
1493
1494    void DocumentSaved(Window document, char * fileName)
1495    {
1496       ideSettings.AddRecentFile(fileName);
1497       ide.UpdateRecentMenus();
1498       settingsContainer.Save();
1499    }
1500
1501    bool Window::OnFileModified(FileChange fileChange, char * param)
1502    {
1503       char temp[4096];
1504       sprintf(temp, $"The document %s was modified by another application.\n"
1505             "Would you like to reload it and lose your changes?", this.fileName);
1506       if(MessageBox { type = yesNo, master = this/*.parent*/,
1507             text = $"Document has been modified", contents = temp }.Modal() == yes)
1508       {
1509          char * fileName = CopyString(this.fileName);
1510          WindowState state = this.state;
1511          Anchor anchor = this.anchor;
1512          Size size = this.size;
1513
1514          this.modifiedDocument = false;
1515          this.Destroy(0);
1516          this = ide.OpenFile(fileName, normal, true, null, no, normal);
1517          if(this)
1518          {
1519             this.anchor = anchor;
1520             this.size = size;
1521             this.SetState(state, true, 0);
1522          }
1523          delete fileName;
1524          return true;
1525       }
1526       return true;
1527    }
1528
1529    void UpdateMakefiles()
1530    {
1531       if(workspace)
1532       {
1533          CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1534          projectView.ShowOutputBuildLog(true);
1535          projectView.DisplayCompiler(compiler, false);
1536          for(prj : workspace.projects)
1537             projectView.ProjectUpdateMakefileForAllConfigs(prj);
1538          delete compiler;
1539       }
1540    }
1541
1542    void AdjustMenus()
1543    {
1544       bool unavailable = !project;
1545
1546       projectQuickItem.disabled           = !unavailable;
1547
1548       projectAddItem.disabled             = unavailable;
1549       toolBar.buttonAddProject.disabled   = unavailable;
1550
1551       activeCompilerItem.disabled         = unavailable;
1552       projectActiveConfigItem.disabled    = unavailable;
1553       projectSettingsItem.disabled        = unavailable;
1554
1555       projectBrowseFolderItem.disabled    = unavailable;
1556
1557       viewProjectItem.disabled            = unavailable;
1558
1559       AdjustBuildMenus();
1560       AdjustDebugMenus();
1561    }
1562
1563    void AdjustBuildMenus()
1564    {
1565       bool unavailable = project && projectView.buildInProgress;
1566
1567       projectNewItem.disabled             = unavailable;
1568       toolBar.buttonNewProject.disabled   = unavailable;
1569       projectOpenItem.disabled            = unavailable;
1570       toolBar.buttonOpenProject.disabled  = unavailable;
1571
1572       unavailable = !project || projectView.buildInProgress;
1573
1574       projectCloseItem.disabled           = unavailable;
1575       // toolBar.buttonCloseProject.disabled = unavailable;
1576
1577       projectRunItem.disabled    = unavailable || project.GetTargetType(project.config) != executable;
1578       toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1579       projectBuildItem.disabled                 = unavailable;
1580       toolBar.buttonBuild.disabled              = unavailable;
1581       projectLinkItem.disabled                  = unavailable;
1582       toolBar.buttonReLink.disabled             = unavailable;
1583       projectRebuildItem.disabled               = unavailable;
1584       toolBar.buttonRebuild.disabled            = unavailable;
1585       projectCleanItem.disabled                 = unavailable;
1586       toolBar.buttonClean.disabled              = unavailable;
1587       projectRealCleanItem.disabled             = unavailable;
1588       // toolBar.buttonRealClean.disabled          = unavailable;
1589       projectRegenerateItem.disabled            = unavailable;
1590       toolBar.buttonRegenerateMakefile.disabled = unavailable;
1591       projectCompileItem.disabled               = unavailable;
1592
1593       if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1594       {
1595          MenuItem menu;
1596          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0);      if(menu) menu.disabled = unavailable;
1597          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0);       if(menu) menu.disabled = unavailable;
1598          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0);    if(menu) menu.disabled = unavailable;
1599          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0);      if(menu) menu.disabled = unavailable;
1600          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0);  if(menu) menu.disabled = unavailable;
1601          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1602          projectView.popupMenu.Update(null);
1603       }
1604    }
1605
1606    void AdjustDebugMenus()
1607    {
1608       bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1609                projectView.buildInProgress == buildingMainProject;
1610       bool active = ide.debugger.isActive;
1611       bool executing = ide.debugger.state == running;
1612       //bool holding = ide.debugger.state == stopped;
1613
1614       debugStartResumeItem.disabled       = unavailable || executing;
1615       debugStartResumeItem.text           = active ? $"Resume" : $"Start";
1616       debugStartResumeItem.NotifySelect   = active ? MenuDebugResume : MenuDebugStart;
1617       if(toolBar)
1618       {
1619          toolBar.buttonDebugStartResume.disabled      = unavailable || executing;
1620          toolBar.buttonDebugStartResume.toolTip       = active ? $"Resume" : $"Start";
1621       }
1622
1623       debugBreakItem.disabled             = unavailable || !executing;
1624       debugStopItem.disabled              = unavailable || !active;
1625       debugRestartItem.disabled           = unavailable || !active;
1626       if(toolBar)
1627       {
1628          toolBar.buttonDebugPause.disabled            = unavailable || !executing;
1629          toolBar.buttonDebugStop.disabled             = unavailable || !active;
1630          toolBar.buttonDebugRestart.disabled          = unavailable || !active;
1631       }
1632
1633       debugStepIntoItem.disabled          = unavailable || executing;
1634       debugStepOverItem.disabled          = unavailable || executing;
1635       debugStepOutItem.disabled           = unavailable || executing || !active;
1636       debugSkipStepOverItem.disabled      = unavailable || executing;
1637       debugSkipStepOutItem.disabled       = unavailable || executing || !active;
1638       if(toolBar)
1639       {
1640          toolBar.buttonDebugStepInto.disabled         = unavailable || executing;
1641          toolBar.buttonDebugStepOver.disabled         = unavailable || executing;
1642          toolBar.buttonDebugStepOut.disabled          = unavailable || executing || !active;
1643          toolBar.buttonDebugSkipStepOver.disabled     = unavailable || executing;
1644          // toolBar.buttonDebugSkipStepOutItem.disabled  = unavailable || executing;
1645       }
1646       if((Designer)GetActiveDesigner())
1647       {
1648          CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1649          if(codeEditor)
1650          {
1651             codeEditor.debugRunToCursor.disabled      = unavailable || executing;
1652             codeEditor.debugSkipRunToCursor.disabled  = unavailable || executing;
1653          }
1654       }
1655    }
1656
1657    void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1658    {
1659       char tempString[MAX_LOCATION];
1660       strcpy(tempString, directory);
1661       if(saveSettings && !projectView)
1662       {
1663          ideSettings.ideFileDialogLocation = directory;
1664          settingsContainer.Save();
1665       }
1666
1667       ideFileDialog.currentDirectory = tempString;
1668       codeEditorFileDialog.currentDirectory = tempString;
1669       codeEditorFormFileDialog.currentDirectory = tempString;
1670    }
1671
1672    void ChangeProjectFileDialogDirectory(char * directory)
1673    {
1674       ideSettings.ideProjectFileDialogLocation = directory;
1675       settingsContainer.Save();
1676    }
1677
1678    Window FindWindow(char * filePath)
1679    {
1680       Window document = null;
1681
1682       // TOCHECK: Do we need to change slashes here?
1683       for(document = firstChild; document; document = document.next)
1684       {
1685          char * fileName = document.fileName;
1686          if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1687          {
1688             document.visible = true;
1689             document.Activate();
1690             return document;
1691          }
1692       }
1693       return null;
1694    }
1695
1696    bool DontTerminateDebugSession(char * title)
1697    {
1698       if(debugger.isActive)
1699       {
1700          if(MessageBox { type = yesNo, master = ide, 
1701                            contents = $"Do you want to terminate the debugging session in progress?", 
1702                            text = title }.Modal() == no)
1703             return true;
1704          /*
1705          MessageBox msg { type = yesNo, master = ide, 
1706                            contents = "Do you want to terminate the debugging session in progress?", 
1707                            text = title };
1708          if(msg.Modal() == no)
1709          {
1710             msg.Destroy(0);
1711             delete msg;
1712             return true;
1713          }
1714          msg.Destroy(0);
1715          delete msg;*/
1716       }
1717       return false;
1718    }
1719
1720    Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1721    {
1722       char extension[MAX_EXTENSION] = "";
1723       Window document = null;
1724       bool isProject = false;
1725       bool needFileModified = true;
1726       char winFilePath[MAX_LOCATION];
1727       char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1728
1729       if(!type)
1730       {
1731          GetExtension(filePath, extension);
1732          strlwr(extension);
1733       }
1734       else
1735          strcpy(extension, type);
1736
1737       if(strcmp(extension, ProjectExtension))
1738       {
1739          for(document = firstChild; document; document = document.next)
1740          {
1741             char * fileName = document.fileName;
1742             if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1743             {
1744                document.visible = true;
1745                if(visible)
1746                   document.Activate();
1747                return document;
1748             }
1749          }
1750       }
1751
1752       if(createIfFails == whatever)
1753          ;
1754       else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1755       {
1756          if(openMethod == normal)
1757          {
1758             if(DontTerminateDebugSession($"Open Project"))
1759                return null;
1760             isProject = true;
1761             if(MenuWindowCloseAll(null, 0))
1762             {
1763                if(projectView)
1764                {
1765                   projectView.visible = false;
1766                   projectView.Destroy(0);
1767                   // Where did this come from? projectView = null;
1768                }
1769                if(!projectView)
1770                {
1771                   for(;;)
1772                   {
1773                      Project project;
1774                      Workspace workspace = null;
1775                      
1776                      if(FileExists(filePath))
1777                      {
1778                         if(!strcmp(extension, ProjectExtension))
1779                         {
1780                            char workspaceFile[MAX_LOCATION];
1781                            strcpy(workspaceFile, filePath);
1782                            ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1783                            workspace = LoadWorkspace(workspaceFile, filePath);
1784                         }
1785                         else if(!strcmp(extension, WorkspaceExtension))
1786                            workspace = LoadWorkspace(filePath, null);
1787                         else
1788                            return null;
1789                         //project = LoadProject(filePath);
1790                      }
1791                      
1792                      if(workspace)
1793                      {
1794                         char absolutePath[MAX_LOCATION];
1795                         CreateProjectView(workspace, filePath);
1796                         document = projectView;
1797
1798                         workspace.DropInvalidBreakpoints();
1799                         workspace.Save();
1800
1801                         ide.projectView.ShowOutputBuildLog(true);
1802                         {
1803                            CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1804                            ide.projectView.DisplayCompiler(compiler, false);
1805                            delete compiler;
1806                         }
1807                         UpdateMakefiles();
1808                         {
1809                            char newWorkingDir[MAX_LOCATION];
1810                            StripLastDirectory(filePath, newWorkingDir);
1811                            ChangeFileDialogsDirectory(newWorkingDir, false);
1812                         }
1813                         if(document)
1814                            document.fileName = filePath;
1815
1816                         ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1817
1818                         // this crashes on starting ide with epj file, solution please?
1819                         // app.UpdateDisplay();
1820
1821                         workspace.holdTracking = true;
1822                         for(ofi : workspace.openedFiles)
1823                         {
1824                            if(ofi.state != closed)
1825                            {
1826                               Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1827                               if(file)
1828                               {
1829                                  char fileName[MAX_LOCATION];
1830                                  ProjectNode node;
1831                                  GetLastDirectory(ofi.path, fileName);
1832                                  node = projectView.project.topNode.Find(fileName, true);
1833                                  if(node)
1834                                     node.EnsureVisible();
1835                               }
1836                            }
1837                         }
1838                         workspace.holdTracking = false;
1839
1840                         workspace.timer.Start();
1841
1842                         findInFilesDialog.mode = FindInFilesMode::project;
1843                         findInFilesDialog.currentDirectory = ide.project.topNode.path;
1844                         
1845                         {
1846                            char location[MAX_LOCATION];
1847                            StripLastDirectory(ide.project.topNode.path, location);
1848                            ChangeProjectFileDialogDirectory(location);
1849                         }
1850                         
1851                         /*
1852                         if(projectView.debugger)
1853                            projectView.debugger.EvaluateWatches();
1854                         */
1855                         
1856                         break;
1857                      }
1858                      else 
1859                      {
1860                         if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1861                         {
1862                            ideProjectFileDialog.text = openProjectFileDialogTitle;
1863                            if(ideProjectFileDialog.Modal() == cancel)
1864                               return null;
1865                            filePath = ideProjectFileDialog.filePath;
1866                            GetExtension(filePath, extension);
1867                         }
1868                         else
1869                            return null;
1870                      }
1871                   }
1872                }
1873             }
1874             else
1875                return document;
1876          }
1877          else if(openMethod == add)
1878          {
1879             if(workspace)
1880             {
1881                Project prj = null;
1882                char slashFilePath[MAX_LOCATION];
1883                GetSlashPathBuffer(slashFilePath, filePath);
1884                for(p : workspace.projects)
1885                {
1886                   if(!fstrcmp(p.filePath, slashFilePath))
1887                   {
1888                      prj = p;
1889                      break;
1890                   }
1891                }
1892                if(prj)
1893                {
1894                   MessageBox { type = ok, parent = parent, master = this, text = $"Same Project", 
1895                         contents = $"This project is already present in workspace." }.Modal();
1896                }
1897                else
1898                {
1899                   prj = LoadProject(filePath);
1900                   if(prj)
1901                   {
1902                      CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1903                      workspace.projects.Add(prj);
1904                      if(projectView)
1905                         projectView.AddNode(prj.topNode, null);
1906                      workspace.modified = true;
1907                      workspace.Save();
1908                      findInFilesDialog.AddProjectItem(prj);
1909                      projectView.ShowOutputBuildLog(true);
1910                      projectView.DisplayCompiler(compiler, false);
1911                      projectView.ProjectUpdateMakefileForAllConfigs(prj);
1912                      delete compiler;
1913
1914                      {
1915                         char location[MAX_LOCATION];
1916                         StripLastDirectory(prj.topNode.path, location);
1917                         ChangeProjectFileDialogDirectory(location);
1918                      }
1919
1920                      // projectView is associated with the main project and not with the one just added but
1921                      return projectView; // just to let the caller know something was opened
1922                   }
1923                }
1924             }
1925             else
1926                return null;
1927          }
1928       }
1929       else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1930             !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1931             !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1932       {
1933          if(FileExists(filePath))
1934             document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, 
1935                                        hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, 
1936                                        visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1937                                     };
1938          if(!document)
1939             MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1940       }
1941 #ifndef NO3D
1942       else if(!strcmp(extension, "3ds"))
1943       {
1944          if(FileExists(filePath))
1945             document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, 
1946                                     hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, 
1947                                     visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1948                                     };
1949
1950          if(!document)
1951             MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1952       }
1953 #endif
1954       else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1955             !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1956             !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1957             !strcmp(extension, "css") || !strcmp(extension, "php") ||
1958             !strcmp(extension, "js"))
1959       {
1960          CodeEditor editor { parent = this, state = state, visible = false };
1961          editor.updatingCode = true;
1962          if(editor.LoadFile(filePath))
1963          {
1964             document = editor;
1965             editor.visible = true;
1966          }
1967          else
1968             delete editor;
1969          needFileModified = false;
1970       }
1971       else
1972       {
1973          CodeEditor editor { parent = this, state = state, visible = false };
1974          if(editor.LoadFile(filePath))
1975          {
1976             document = editor;
1977             editor.visible = true;
1978          }
1979          else
1980             delete editor;
1981          needFileModified = false;
1982       }
1983
1984       if(document && (document._class == class(PictureEdit) ||
1985             document._class == class(ModelView)))
1986       {
1987          document.Create();
1988          if(document)
1989          {
1990             document.fileName = filePath;
1991             if(workspace && !workspace.holdTracking)
1992                workspace.UpdateOpenedFileInfo(filePath, opened);
1993          }
1994       }
1995       
1996       if(!document && createIfFails != no)
1997       {
1998          if(createIfFails != yes && !needFileModified && 
1999                MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2000             createIfFails = yes;
2001          if(createIfFails == yes || createIfFails == whatever)
2002          {
2003             document = (Window)NewCodeEditor(this, state, true);
2004             if(document)
2005                document.fileName = filePath;
2006          }
2007       }
2008
2009       if(document)
2010       {
2011          if(projectView && document._class == class(CodeEditor) && workspace)
2012          {
2013             int lineNumber, position;
2014             Point scroll;
2015             CodeEditor editor = (CodeEditor)document;
2016             editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2017             editor.openedFileInfo.holdTracking = true;
2018             lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2019             position = Max(editor.openedFileInfo.position - 1, 0);
2020             editor.editBox.GoToLineNum(lineNumber);
2021             editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2022             scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2023             scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2024             editor.editBox.scroll = scroll;
2025             editor.openedFileInfo.holdTracking = false;
2026          }
2027          
2028          if(needFileModified)
2029             document.OnFileModified = OnFileModified;
2030          document.NotifySaved = DocumentSaved;
2031          
2032          if(isProject)
2033             ideSettings.AddRecentProject(document.fileName);
2034          else
2035             ideSettings.AddRecentFile(document.fileName);
2036          ide.UpdateRecentMenus();
2037          settingsContainer.Save();
2038          
2039          return document;
2040       }
2041       else
2042          return null;
2043    }
2044
2045    // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2046    /*bool Window::GenericDocumentOnClose(bool parentClosing)
2047    {
2048       if(!parentClosing && ide.workspace)
2049          ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2050       return true;
2051    }*/
2052    bool ModelView::ModelViewOnClose(bool parentClosing)
2053    {
2054       if(!parentClosing && ide.workspace)
2055          ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2056       return true;
2057    }
2058    bool PictureEdit::PictureEditOnClose(bool parentClosing)
2059    {
2060       if(!parentClosing && ide.workspace)
2061          ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2062       return true;
2063    }
2064
2065    /*
2066    void OnUnloadGraphics(Window window)
2067    {
2068       display.ClearMaterials();
2069       display.ClearTextures();
2070       display.ClearMeshes();
2071    }
2072    */
2073
2074    bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2075    {
2076       caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2077       num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2078       return true;
2079    }
2080
2081    bool OnKeyDown(Key key, unichar ch)
2082    {
2083       switch(key)
2084       {
2085          case b:
2086             projectView.Update(null);
2087             break;
2088          case capsLock:
2089             caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2090             break;
2091          case numLock:
2092             num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2093             break;
2094       }
2095       return true;
2096    }
2097
2098    void GoToError(const char * line)
2099    {
2100       if(projectView)
2101          projectView.GoToError(line);
2102    }
2103
2104    void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2105    {
2106       char *path = text;
2107       char *colon = strchr(text, ':');
2108       char filePath[MAX_LOCATION];
2109       char completePath[MAX_LOCATION];
2110       int line = 0, col = 0;
2111       Project prj = null;
2112
2113       if(text[3] == '(')
2114       {
2115          char * close = strchr(text, ')');
2116          if(close)
2117          {
2118             char name[256];
2119             strncpy(name, &text[4], close - text - 4);
2120             name[close - text - 4] = '\0';
2121             for(p : ide.workspace.projects)
2122             {
2123                if(!strcmp(p.name, name))
2124                {
2125                   path = close + 1;
2126                   prj = p;
2127                   break;
2128                }
2129             }
2130          }
2131       }
2132       if(!prj)
2133          prj = project ? project : (dir ? null : ide.project);
2134       if(colon && (colon[1] == '/' || colon[1] == '\\'))
2135       {
2136          path = (colon - 1 > path) ? colon - 1 : path;
2137          colon = strstr(colon + 1, ":");
2138       }
2139       while(isspace(*path)) path++;
2140       if(colon)
2141       {
2142          strncpy(filePath, path, colon - path);
2143          filePath[colon - path] = '\0';
2144          line = atoi(colon + 1);
2145          colon = strstr(colon + 1, ":");
2146          if(colon)
2147             col = atoi(colon + 1);
2148       }
2149       else if(path - 1 >= path && *(path - 1) == '\"')
2150       {
2151          colon = strchr(path, '\"');
2152          if(colon)
2153          {
2154             strncpy(filePath, path, colon - path);
2155             filePath[colon - path] = '\0';
2156          }
2157       }
2158
2159       if(prj)
2160          strcpy(completePath, prj.topNode.path);
2161       else if(dir && dir[0])
2162          strcpy(completePath, dir);
2163       else
2164          completePath[0] = '\0';
2165       PathCat(completePath, filePath);
2166
2167       if(FileExists(completePath).isFile)
2168       {
2169          CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2170          if(codeEditor && line)
2171          {
2172             EditBox editBox = codeEditor.editBox;
2173             editBox.GoToLineNum(line - 1);
2174             editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2175          }
2176       }
2177    }
2178
2179    void OnRedraw(Surface surface)
2180    {
2181       Bitmap bitmap = back.bitmap;
2182       if(bitmap)
2183          surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2184    }
2185
2186    void SheetSelected(SheetType sheetSelected)
2187    {
2188       if(activeChild == sheet)
2189       {
2190          if(sheetSelected == methods)
2191          {
2192             viewPropertiesItem.accelerator = f4;
2193             viewPropertiesItem.parent = viewMenu;
2194             viewMethodsItem.parent = null;
2195          }
2196          else
2197          {
2198             viewMethodsItem.accelerator = f4;
2199             viewMethodsItem.parent = viewMenu;
2200             viewPropertiesItem.parent = null;
2201          }
2202       }
2203       else
2204       {
2205          viewMethodsItem.parent = viewMenu;
2206          viewPropertiesItem.parent = viewMenu;
2207          if(sheetSelected == methods)
2208          {
2209             viewMethodsItem.accelerator = f4;
2210             viewPropertiesItem.accelerator = 0;
2211          }
2212          else
2213          {
2214             viewMethodsItem.accelerator = 0;
2215             viewPropertiesItem.accelerator = f4;
2216          }
2217       }
2218    }
2219
2220    void OnActivateClient(Window client, Window previous)
2221    {
2222       //if(!client || client != previous)
2223       {
2224          Class dataType;
2225          if(!client || client != previous)
2226          {
2227             if(previous)
2228                dataType = previous._class;
2229             if(previous && !strcmp(dataType.name, "CodeEditor"))
2230             {
2231                ((CodeEditor)previous).UpdateFormCode();
2232             }
2233             else if(previous && !strcmp(dataType.name, "Designer"))
2234             {
2235                ((Designer)previous).codeEditor.UpdateFormCode();
2236             }
2237          }
2238
2239          if(client)
2240             dataType = client._class;
2241          if(client && !strcmp(dataType.name, "CodeEditor"))
2242          {
2243             CodeEditor codeEditor = (CodeEditor)client;
2244             SetPrivateModule(codeEditor.privateModule);
2245             SetCurrentContext(codeEditor.globalContext);
2246             SetTopContext(codeEditor.globalContext);
2247             SetGlobalContext(codeEditor.globalContext);
2248             
2249             SetDefines(&codeEditor.defines);
2250             SetImports(&codeEditor.imports);
2251
2252             SetActiveDesigner(codeEditor.designer);
2253             
2254             sheet.codeEditor = codeEditor;
2255             toolBox.codeEditor = codeEditor;
2256
2257             viewDesignerItem.parent = viewMenu;
2258             if(activeChild != codeEditor)
2259             {
2260                viewCodeItem.parent = viewMenu;
2261                viewDesignerItem.accelerator = 0;
2262                viewCodeItem.accelerator = f8;
2263             }
2264             else
2265             {
2266                viewCodeItem.parent = null;
2267                viewDesignerItem.accelerator = f8;
2268             }
2269          }
2270          else if(client && !strcmp(dataType.name, "Designer"))
2271          {
2272             CodeEditor codeEditor = ((Designer)client).codeEditor;
2273             if(codeEditor)
2274             {
2275                SetPrivateModule(codeEditor.privateModule);
2276                SetCurrentContext(codeEditor.globalContext);
2277                SetTopContext(codeEditor.globalContext);
2278                SetGlobalContext(codeEditor.globalContext);
2279                SetDefines(&codeEditor.defines);
2280                SetImports(&codeEditor.imports);
2281             }
2282             else
2283             {
2284                SetPrivateModule(null);
2285                SetCurrentContext(null);
2286                SetTopContext(null);
2287                SetGlobalContext(null);
2288                SetDefines(null);
2289                SetImports(null);
2290             }
2291
2292             SetActiveDesigner((Designer)client);
2293
2294             sheet.codeEditor = codeEditor;
2295             toolBox.codeEditor = codeEditor;
2296
2297             viewCodeItem.parent = viewMenu;
2298             if(activeChild != client)
2299             {
2300                viewDesignerItem.parent = viewMenu;
2301                viewDesignerItem.accelerator = f8;
2302                viewCodeItem.accelerator = 0;
2303             }
2304             else
2305             {
2306                viewDesignerItem.parent = null;
2307                viewCodeItem.accelerator = f8;
2308             }
2309          }
2310          else
2311          {
2312             if(sheet)
2313                sheet.codeEditor = null;
2314             toolBox.codeEditor = null;
2315             SetActiveDesigner(null);
2316
2317             viewDesignerItem.parent = null;
2318             viewCodeItem.parent = null;
2319          }
2320          if(sheet)
2321             SheetSelected(sheet.sheetSelected);
2322       }
2323
2324       projectCompileItem = null;
2325
2326       if(statusBar)
2327       {
2328          statusBar.Clear();
2329          if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2330          {
2331             CodeEditor codeEditor = (CodeEditor)client;
2332             EditBox editBox = codeEditor.editBox;
2333
2334             statusBar.AddField(pos);
2335
2336             caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2337             statusBar.AddField(caps);
2338
2339             ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2340             statusBar.AddField(ovr);
2341
2342             num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2343             statusBar.AddField(num);
2344
2345             //statusBar.text = "Ready";
2346
2347             if(projectView && projectView.project)
2348             {
2349                ProjectNode node = projectView.GetNodeFromWindow(client, null);
2350                if(node)
2351                {
2352                   char name[1024];
2353                   sprintf(name, $"Compile %s", node.name);
2354                   projectCompileItem = 
2355                   {
2356                      copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2357
2358                      bool NotifySelect(MenuItem selection, Modifiers mods)
2359                      {
2360                         if(projectView)
2361                         {
2362                            ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2363                            if(node)
2364                               projectView.Compile(node);
2365                         }
2366                         return true;
2367                      }
2368                   };
2369                   projectMenu.AddDynamic(projectCompileItem, ide, false);
2370                }
2371             }
2372          }
2373          else
2374          {
2375             caps = ovr = num = null;
2376          }
2377       }
2378    }
2379
2380    bool OnClose(bool parentClosing)
2381    {
2382       //return !projectView.buildInProgress;
2383       if(projectView && projectView.buildInProgress)
2384          return false;
2385       if(DontTerminateDebugSession($"Close IDE"))
2386          return false;
2387       if(findInFilesDialog)
2388          findInFilesDialog.SearchStop();
2389       if(workspace)
2390       {
2391          workspace.timer.Stop();
2392          workspace.Save();
2393       }
2394       ideMainFrame.Destroy(0);
2395       return true;
2396    }
2397
2398    bool OnPostCreate()
2399    {
2400       int c;
2401       for(c = 1; c<app.argc; c++)
2402       {
2403          char fullPath[MAX_LOCATION];
2404          char parentPath[MAX_LOCATION];
2405          char ext[MAX_EXTENSION];
2406          bool isProject;
2407          FileAttribs dirAttribs;
2408          GetWorkingDir(fullPath, MAX_LOCATION);
2409          PathCat(fullPath, app.argv[c]);
2410          StripLastDirectory(fullPath, parentPath);
2411          GetExtension(app.argv[c], ext);
2412          isProject = !strcmpi(ext, "epj");
2413
2414          if(isProject && c > 1) continue;
2415
2416          // Create directory for projects (only)
2417          if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2418          {
2419             if(isProject && !FileExists(fullPath))
2420             {
2421                // The NewProject will handle directory creation
2422                /*if(!dirAttribs.isDirectory)
2423                {
2424                   MakeDir(parentPath);
2425                   dirAttribs = FileExists(parentPath);
2426                }
2427                if(dirAttribs.isDirectory)*/
2428                {
2429                   char name[MAX_LOCATION];
2430                   NewProjectDialog newProjectDialog;
2431
2432                   if(projectView)
2433                   {
2434                      projectView.visible = false;
2435                      if(!projectView.Destroy(0))
2436                         return true;
2437                   }
2438
2439                   newProjectDialog = { master = this };
2440
2441                   strcpy(name, app.argv[c]);
2442                   StripExtension(name);
2443                   GetLastDirectory(name, name);
2444                   newProjectDialog.projectName.contents = name;
2445                   newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2446                   newProjectDialog.locationEditBox.path = parentPath;
2447                   newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2448
2449                   newProjectDialog.Modal();
2450                   if(projectView)
2451                   {
2452                      ideSettings.AddRecentProject(projectView.fileName);
2453                      ide.UpdateRecentMenus();
2454                      settingsContainer.Save();
2455                   }
2456                }
2457                // Open only one project
2458                break;
2459             }
2460             else
2461                ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2462          }
2463       }
2464       return true;
2465    }
2466
2467    void OnDestroy()
2468    {
2469       // IS THIS NEEDED? WASN'T HERE BEFORE...  Crashes on getting node's projectView otherwise
2470       if(projectView)
2471       {
2472          projectView.visible = false;
2473          projectView.Destroy(0);
2474          projectView = null;
2475       }
2476 #ifdef GDB_DEBUG_GUI
2477       gdbDialog.Destroy(0);
2478       delete gdbDialog;
2479 #endif
2480    }
2481
2482    void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2483    {
2484       int c, len, count;
2485       char * newList;
2486       char * oldPaths[128];
2487       String oldList = new char[maxPathLen];
2488       Array<String> newExePaths { };
2489       //Map<String, bool> exePathExists { };
2490       bool found = false;
2491 #if defined(__unix__) || defined(__APPLE__)
2492       Array<String> newLibPaths { };
2493       Map<String, bool> libPathExists { };
2494 #endif
2495
2496       if(projectsDirs)
2497       {
2498          for(prj : workspace.projects)
2499          {
2500             DirExpression targetDirExp;
2501
2502             // SKIP FIRST PROJECT...
2503             if(prj == workspace.projects.firstIterator.data) continue;
2504
2505             // NOTE: Right now the additional project config dir will be
2506             //       obtained when the debugger is started, so toggling it
2507             //       while building will change which library gets used.
2508             //       To go with the initial state, e.g. when F5 was pressed,
2509             //       we nould need to keep a list of all project's active
2510             //       config upon startup.
2511             targetDirExp = prj.GetTargetDir(compiler, prj.config);
2512
2513             /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2514                cfg = prj.config;
2515             else
2516             {
2517                for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2518                   if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2519                      break;
2520                if(!cfg)
2521                {
2522                   for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2523                      if(cfg.targetType == sharedLibrary && cfg.debug)
2524                         break;
2525                }
2526             }*/
2527             if(targetDirExp.dir)
2528             {
2529                char buffer[MAX_LOCATION];
2530 #if defined(__WIN32__)
2531                Array<String> paths = newExePaths;
2532 #else
2533                Array<String> paths = newLibPaths;
2534 #endif
2535                GetSystemPathBuffer(buffer, prj.topNode.path);
2536                PathCat(buffer, targetDirExp.dir);
2537                for(p : paths)
2538                {
2539                   if(!fstrcmp(p, buffer))
2540                   {
2541                      found = true;
2542                      break;
2543                   }
2544                }
2545                if(!found)
2546                   paths.Add(CopyString(buffer));
2547             }
2548             delete targetDirExp;
2549          }
2550       }
2551
2552       for(item : compiler.executableDirs)
2553       {
2554          found = false;
2555          for(p : newExePaths)
2556          {
2557             if(!fstrcmp(p, item))
2558             {
2559                found = true;
2560                break;
2561             }
2562          }
2563          if(!found)
2564             newExePaths.Add(CopySystemPath(item));
2565       }
2566
2567       GetEnvironment("PATH", oldList, maxPathLen);
2568 /*#ifdef _DEBUG
2569       printf("Old value of PATH: %s\n", oldList);
2570 #endif*/
2571       count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2572       for(c = 0; c < count; c++)
2573       {
2574          found = false;
2575          for(p : newExePaths)
2576          {
2577             if(!fstrcmp(p, oldPaths[c]))
2578             {
2579                found = true;
2580                break;
2581             }
2582          }
2583          if(!found)
2584             newExePaths.Add(CopySystemPath(oldPaths[c]));
2585       }
2586
2587       len = 0;
2588       for(path : newExePaths)
2589          len += strlen(path) + 1;
2590       newList = new char[len + 1];
2591       newList[0] = '\0';
2592       for(path : newExePaths)
2593       {
2594          strcat(newList, path);
2595          strcat(newList, pathListSep);
2596       }
2597       newList[len - 1] = '\0';
2598       SetEnvironment("PATH", newList);
2599 /*#ifdef _DEBUG
2600       printf("New value of PATH: %s\n", newList);
2601 #endif*/
2602       delete newList;
2603
2604       newExePaths.Free();
2605       delete newExePaths;
2606
2607 #if defined(__unix__) || defined(__APPLE__)
2608
2609       for(item : compiler.libraryDirs)
2610       {
2611          if(!libPathExists[item])  // fstrcmp should be used
2612          {
2613             newLibPaths.Add(item);
2614             libPathExists[item] = true;
2615          }
2616       }
2617
2618 #if defined(__APPLE__)
2619       GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2620 #else
2621       GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2622 #endif
2623 /*#ifdef _DEBUG
2624       printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2625 #endif*/
2626       count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2627       for(c = 0; c < count; c++)
2628       {
2629          if(!libPathExists[oldPaths[c]])  // fstrcmp should be used
2630          {
2631             newLibPaths.Add(oldPaths[c]);
2632             libPathExists[oldPaths[c]] = true;
2633          }
2634       }
2635
2636       len = 0;
2637       for(path : newLibPaths)
2638          len += strlen(path) + 1;
2639       newList = new char[len + 1];
2640       newList[0] = '\0';
2641       for(path : newLibPaths)
2642       {
2643          strcat(newList, path);
2644          strcat(newList, pathListSep);
2645       }
2646       newList[len - 1] = '\0';
2647 #if defined(__APPLE__)
2648       SetEnvironment("DYLD_LIBRARY_PATH", newList);
2649 #else
2650       SetEnvironment("LD_LIBRARY_PATH", newList);
2651 #endif
2652 /*#ifdef _DEBUG
2653       printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2654 #endif*/
2655       delete newList;
2656
2657       delete newLibPaths;
2658       delete libPathExists;
2659 #endif
2660
2661       if(compiler.distccEnabled && compiler.distccHosts)
2662          SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2663
2664       delete oldList;
2665    }
2666
2667    void DestroyTemporaryProjectDir()
2668    {
2669       if(tmpPrjDir && tmpPrjDir[0])
2670       {
2671          if(FileExists(tmpPrjDir).isDirectory)
2672             DestroyDir(tmpPrjDir);
2673          property::tmpPrjDir = null;
2674       }
2675    }
2676
2677    IDEWorkSpace()
2678    {
2679       // Graphics Driver Menu
2680       int c;
2681
2682       /*
2683       app.currentSkin.selectionColor = selectionColor;
2684       app.currentSkin.selectionText = selectionText;
2685       */
2686
2687 /*
2688       driverItems = new MenuItem[app.numDrivers];
2689       for(c = 0; c < app.numDrivers; c++)
2690       {
2691          driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2692          driverItems[c].id = c;
2693          driverItems[c].isRadio = true;         
2694       }
2695 */
2696       driverItems = new MenuItem[2];
2697 #if defined(__unix__)
2698          driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2699          driverItems[0].id = 0;
2700          driverItems[0].isRadio = true;         
2701 #else
2702          driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2703          driverItems[0].id = 0;
2704          driverItems[0].isRadio = true;         
2705 #endif
2706          driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2707          driverItems[1].id = 1;
2708          driverItems[1].isRadio = true;         
2709
2710 /*      skinItems = new MenuItem[app.numSkins];
2711       for(c = 0; c < app.numSkins; c++)
2712       {
2713          skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2714          skinItems[c].id = c;
2715          skinItems[c].isRadio = true;         
2716       }
2717 */
2718       ideFileDialog.master = this;
2719       ideProjectFileDialog.master = this;
2720
2721       //SetDriverAndSkin();
2722       return true;
2723    }
2724
2725    void UpdateRecentMenus()
2726    {
2727       int c;
2728       Menu fileMenu = menu.FindMenu($"File");
2729       Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2730       Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2731       char itemName[MAX_LOCATION + 4];
2732       MenuItem item;
2733
2734       recentFiles.Clear();
2735       c = 0;
2736
2737       for(recent : ideSettings.recentFiles)
2738       {
2739          sprintf(itemName, "%d %s", 1 + c, recent);
2740          MakeSystemPath(itemName);
2741          recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2742          c++;
2743       }
2744
2745       recentProjects.Clear();
2746       c = 0;
2747       for(recent : ideSettings.recentProjects)
2748       {
2749          sprintf(itemName, "%d %s", 1 + c, recent);
2750          MakeSystemPath(itemName);
2751          recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2752          c++;
2753       }
2754    }
2755
2756    ~IDEWorkSpace()
2757    {
2758       delete driverItems;
2759       delete skinItems;
2760       delete ideSettings;
2761    }
2762 }
2763
2764 void DestroyDir(char * path)
2765 {
2766    RecursiveDeleteFolderFSI fsi { };
2767    fsi.Iterate(path);
2768    delete fsi;
2769 }
2770
2771 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2772 {
2773    bool preserveRootFolder;
2774
2775    void OutFolder(char * folderPath, bool isRoot)
2776    {
2777       if(!(preserveRootFolder && isRoot))
2778          RemoveDir(folderPath);
2779    }
2780
2781    bool OnFile(char * filePath)
2782    {
2783       DeleteFile(filePath);
2784       return true;
2785    }
2786 }
2787
2788 class IDEApp : GuiApplication
2789 {
2790    //driver = "Win32Console";
2791    // driver = "OpenGL";
2792    // skin = "Aqua";
2793    //skin = "TVision";
2794    bool Init()
2795    {
2796       SetLoggingMode(stdOut, null);
2797       //SetLoggingMode(debug, null);
2798
2799       settingsContainer.Load();
2800 #if defined(__unix__) || defined(__APPLE__)
2801       app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2802 #else
2803       app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2804 #endif
2805       ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2806
2807       SetInIDE(true);
2808
2809       desktop.text = titleECEREIDE;
2810       /*
2811       int c;
2812       for(c = 1; c<app.argc; c++)
2813       {
2814          char fullPath[MAX_LOCATION];
2815          GetWorkingDir(fullPath, MAX_LOCATION);
2816          PathCat(fullPath, app.argv[c]);
2817          ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2818       }
2819       */
2820       return true;
2821    }
2822 }
2823
2824 IDEMainFrame ideMainFrame { };
2825
2826 define app = ((IDEApp)__thisModule);
2827 #ifdef _DEBUG
2828 define titleECEREIDE = $"ECERE IDE (Debug)";
2829 #else
2830 define titleECEREIDE = $"ECERE IDE";
2831 #endif