2 public import static "ecere"
3 public import static "ec"
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
12 import "ActiveCompilerDialog"
19 import "ProjectActiveConfig"
20 import "ProjectConfig"
22 import "NodeProperties"
23 import "ProjectSettings"
35 import "BreakpointsView"
36 import "CallStackView"
47 import "FileSystemIterator"
49 #if defined(__WIN32__)
50 define pathListSep = ";";
52 define pathListSep = ":";
55 define maxPathLen = 65 * MAX_LOCATION;
57 class PathBackup : struct
64 oldPath = new char[maxPathLen];
65 oldLDPath = new char[maxPathLen];
67 GetEnvironment("PATH", oldPath, maxPathLen);
68 #if defined(__APPLE__)
69 GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
71 GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
77 SetEnvironment("PATH", oldPath);
78 #if defined(__APPLE__)
79 SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
81 SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
88 enum OpenCreateIfFails { no, yes, something, whatever };
89 enum OpenMethod { normal, add };
91 static Array<FileFilter> fileFilters
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 }
103 static Array<FileType> fileTypes
105 { $"Based on extension", null },
108 { $"3D Studio Model", "3ds" }
111 static Array<FileFilter> projectFilters
113 { $"Project Files (*.epj)", ProjectExtension }
116 static Array<FileType> projectTypes
118 { $"Project File", ProjectExtension }
121 static Array<FileFilter> findInFilesFileFilters
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 }
131 FileDialog ideFileDialog
133 type = multiOpen, text = $"Open";
134 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
137 define openProjectFileDialogTitle = $"Open Project";
138 define addProjectFileDialogTitle = $"Open Additional Project";
139 FileDialog ideProjectFileDialog
142 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
145 GlobalSettingsDialog globalSettingsDialog
147 ideSettings = ideSettings;
148 settingsContainer = settingsContainer;
150 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
152 switch(globalSettingsChange)
157 for(child = ide.firstChild; child; child = child.next)
159 if(child._class == class(CodeEditor))
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
172 case compilerSettings:
174 ide.UpdateMakefiles();
181 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
186 lineY = (line - 1) * lineH;
187 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
189 Bitmap bitmap = resource.bitmap;
191 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
196 #define IDEItem(x) (&((IDEWorkSpace)0).x)
198 class IDEToolbar : ToolBar
202 ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
204 ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
206 // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
208 ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
210 ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
212 ToolSeparator separator1 { this };
221 //ToolSeparator separator2 { this };
223 /* Project options */
225 ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
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; };
231 //ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
233 ToolSeparator separator3 { this };
235 /* Build/Execution options */
237 ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
239 ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
241 ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
243 ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
244 // Regenerate Makefile
245 ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
246 // Compile actual file
248 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
250 ToolSeparator separator4 { this };
254 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
256 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
258 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
260 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
262 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
264 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
266 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
268 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
270 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
273 class IDEMainFrame : Window
275 background = activeBorder;
276 borderStyle = sizable;
280 minClientSize = { 600, 300 };
282 icon = { ":icon.png" };
283 text = titleECEREIDE;
287 anchor = { top = 0, right = 0, bottom = 0 };
290 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
297 isActiveClient = true;
299 direction = vertical;
300 background = activeBorder;
301 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
309 ((IDEWorkSpace)master).toolBar = null;
312 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
315 define ide = ideMainFrame.ideWorkSpace;
317 class IDEWorkSpace : Window
319 background = Color { 85, 85, 85 };
322 hasVertScroll = true;
323 hasHorzScroll = true;
325 isActiveClient = true;
326 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
330 MenuItem * driverItems, * skinItems;
331 StatusField pos { width = 150 };
332 StatusField ovr, caps, num;
334 BitmapResource back { ":ecereBack.jpg", window = this };
335 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
336 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
337 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
338 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
339 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
340 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
341 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
342 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
343 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
344 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
346 Debugger debugger { };
348 ProjectView projectView;
350 OutputView outputView
354 void OnGotoError(char * line)
359 void OnCodeLocationParseAndGoTo(char * line)
361 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
364 bool OnKeyDown(Key key, unichar ch)
369 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
370 ide.ShowCodeEditor();
373 ide.projectView.stopBuild = true;
377 OutputView::OnKeyDown(key, ch);
384 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
387 ide.RepositionWindows(false);
391 bool OnClose(bool parentClosing)
395 ide.RepositionWindows(false);
396 return parentClosing;
400 CallStackView callStackView
402 parent = this, font = { panelFont.faceName, panelFont.size };
404 void OnGotoLine(char * line)
407 stackLvl = atoi(line);
408 ide.debugger.GoToStackFrameLine(stackLvl, true);
411 void OnSelectFrame(int lineNumber)
413 ide.debugger.SelectFrame(lineNumber);
416 void OnToggleBreakpoint()
418 Debugger debugger = ide.debugger;
419 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
421 int line = debugger.activeFrame.line;
422 char name[MAX_LOCATION];
424 // TOFIX: Improve on this, don't use only filename, make a function
425 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
426 if(ide && ide.workspace)
428 for(p : ide.workspace.projects)
430 if(p.topNode.Find(name, false))
438 for(p : ide.workspace.projects)
440 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
448 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
451 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
452 if(codeEditor) { codeEditor.Update(null); Activate(); }
457 bool OnKeyDown(Key key, unichar ch)
461 case escape: ide.ShowCodeEditor(); break;
466 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
469 ide.RepositionWindows(false);
473 bool OnClose(bool parentClosing)
477 ide.RepositionWindows(false);
478 return parentClosing;
481 void OnRedraw(Surface surface)
484 int lineCursor, lineTopFrame, activeThread, hitThread;
485 int lineH, scrollY, boxH;
487 Breakpoint bp = null;
488 Debugger debugger = ide.debugger;
489 Frame activeFrame = debugger.activeFrame;
492 scrollY = editBox.scroll.y;
493 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
495 activeThread = debugger.activeThread;
496 hitThread = debugger.hitThread;
497 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
499 if(activeFrame && activeFrame.absoluteFile)
501 for(i : ide.workspace.breakpoints; i.type == user)
503 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
504 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
505 activeFrame.line == i.line)
514 DrawLineMarginIcon(surface,
515 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
516 lineCursor /*1*/, lineH, scrollY, boxH);
519 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
520 DrawLineMarginIcon(surface,
521 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
522 1, lineH, scrollY, boxH);
524 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
525 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
526 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
528 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
529 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
530 if(editBox.horzScroll && editBox.horzScroll.visible)
532 surface.SetBackground(control);
533 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
538 WatchesView watchesView { parent = this };
539 ThreadsView threadsView
541 parent = this, font = { panelFont.faceName, panelFont.size };
543 bool OnKeyDown(Key key, unichar ch)
547 case escape: ide.ShowCodeEditor(); break;
552 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
555 ide.RepositionWindows(false);
559 bool OnClose(bool parentClosing)
563 ide.RepositionWindows(false);
564 return parentClosing;
567 void OnSelectThread(int threadId)
570 ide.debugger.SelectThread(threadId);
573 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
576 Debugger debugger = ide.debugger;
577 *activeThread = debugger.activeThread;
578 *hitThread = debugger.hitThread;
579 *signalThread = debugger.signalThread;
584 BreakpointsView breakpointsView { parent = this };
586 ToolBox toolBox { parent = this };
587 Sheet sheet { parent = this };
590 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
592 Menu fileMenu { menu, $"File", f, hasMargin = true };
595 fileMenu, $"New", n, ctrlN;
596 bitmap = { ":actions/docNew.png" };
597 bool NotifySelect(MenuItem selection, Modifiers mods)
599 Window document = (Window)NewCodeEditor(this, normal, false);
600 document.NotifySaved = DocumentSaved;
604 MenuItem fileOpenItem
606 fileMenu, $"Open...", o, ctrlO;
607 bitmap = { ":actions/docOpen.png" };
608 bool NotifySelect(MenuItem selection, Modifiers mods)
610 if(!projectView && ideSettings.ideFileDialogLocation)
611 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
614 if(ideFileDialog.Modal() == ok)
616 bool gotWhatWeWant = false;
618 int numSelections = ideFileDialog.numSelections;
619 char ** multiFilePaths = ideFileDialog.multiFilePaths;
621 for(c = 0; c < numSelections; c++)
623 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
624 gotWhatWeWant = true;
627 MessageBox { type = yesNo, master = this, text = $"Error opening file",
628 contents = $"Open a different file?" }.Modal() == no)
630 if(!projectView && gotWhatWeWant)
631 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
641 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
642 MenuDivider { fileMenu };
643 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" } };
644 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
645 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
646 MenuDivider { fileMenu };
649 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
650 bool NotifySelect(MenuItem selection, Modifiers mods)
652 findInFilesDialog.replaceMode = false;
653 findInFilesDialog.Show();
657 MenuItem replaceInFiles
659 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
660 bool NotifySelect(MenuItem selection, Modifiers mods)
662 findInFilesDialog.replaceMode = true;
663 findInFilesDialog.Show();
667 MenuDivider { fileMenu };
668 MenuItem globalSettingsItem
670 fileMenu, $"Global Settings...", g;
671 bool NotifySelect(MenuItem selection, Modifiers mods)
673 globalSettingsDialog.master = this;
674 if(ide.workspace && ide.workspace.compiler)
675 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
676 else if(ideSettings.defaultCompiler)
677 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
678 globalSettingsDialog.Modal();
682 MenuDivider { fileMenu };
683 Menu recentFiles { fileMenu, $"Recent Files", r };
684 Menu recentProjects { fileMenu, $"Recent Projects", p };
685 MenuDivider { fileMenu };
688 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
690 bool NotifySelect(MenuItem selection, Modifiers mods)
692 ideMainFrame.Destroy(0);
697 bool FileRecentFile(MenuItem selection, Modifiers mods)
700 for(file : ideSettings.recentFiles)
702 if(id == selection.id)
704 OpenFile(file, normal, true, null, no, normal);
712 bool FileRecentProject(MenuItem selection, Modifiers mods)
715 for(file : ideSettings.recentProjects)
717 if(id == selection.id)
719 OpenFile(file, normal, true, null, no, normal);
727 MenuPlacement editMenu { menu, $"Edit", e };
729 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
730 MenuItem projectNewItem
732 projectMenu, $"New...", n, Key { n, true, true };
733 bitmap = { ":actions/projNew.png" };
734 bool NotifySelect(MenuItem selection, Modifiers mods)
736 if(!DontTerminateDebugSession($"New Project"))
737 if(MenuWindowCloseAll(null, 0))
739 NewProjectDialog newProjectDialog;
743 projectView.visible = false;
744 if(!projectView.Destroy(0))
748 newProjectDialog = { master = this };
749 newProjectDialog.Modal();
752 ideSettings.AddRecentProject(projectView.fileName);
753 ide.UpdateRecentMenus();
754 settingsContainer.Save();
760 MenuItem projectOpenItem
762 projectMenu, $"Open...", o, Key { o, true, true };
763 bitmap = { ":actions/projOpen.png" };
764 bool NotifySelect(MenuItem selection, Modifiers mods)
766 if(ideSettings.ideProjectFileDialogLocation)
767 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
769 ideProjectFileDialog.text = openProjectFileDialogTitle;
770 if(ideProjectFileDialog.Modal() == ok)
772 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
773 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
778 MenuItem projectQuickItem
780 projectMenu, $"Quick...", q, f7;
781 bool NotifySelect(MenuItem selection, Modifiers mods)
784 QuickProjectDialog{ this }.Modal();
788 MenuItem projectAddItem
790 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
791 bitmap = { ":actions/projAdd.png" };
793 bool NotifySelect(MenuItem selection, Modifiers mods)
795 if(ideSettings.ideProjectFileDialogLocation)
796 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
798 ideProjectFileDialog.text = addProjectFileDialogTitle;
801 if(ideProjectFileDialog.Modal() == ok)
803 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
805 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
806 contents = $"Add a different project?" }.Modal() == no)
817 MenuItem projectCloseItem
819 projectMenu, $"Close", c, disabled = true;
820 bool NotifySelect(MenuItem selection, Modifiers mods)
824 if(!ide.DontTerminateDebugSession($"Project Close"))
826 if(findInFilesDialog)
827 findInFilesDialog.SearchStop();
828 projectView.visible = false;
829 if(projectView.Destroy(0))
830 MenuWindowCloseAll(null, 0);
832 char workingDir[MAX_LOCATION];
833 GetWorkingDir(workingDir, MAX_LOCATION);
834 findInFilesDialog.currentDirectory = workingDir;
835 ideMainFrame.text = titleECEREIDE;
842 MenuDivider { projectMenu };
843 MenuItem activeCompilerItem
845 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
846 bool NotifySelect(MenuItem selection, Modifiers mods)
848 projectView.MenuCompiler(null, mods);
852 MenuItem projectActiveConfigItem
854 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
855 bool NotifySelect(MenuItem selection, Modifiers mods)
857 projectView.MenuConfig(projectView.active ? selection : null, mods);
861 MenuItem projectSettingsItem
863 projectMenu, $"Settings...", s, altF7, disabled = true;
864 bool NotifySelect(MenuItem selection, Modifiers mods)
866 projectView.MenuSettings(projectView.active ? selection : null, mods);
870 MenuDivider { projectMenu };
871 MenuItem projectBrowseFolderItem
873 projectMenu, $"Browse Project Folder", p, disabled = true;
874 bool NotifySelect(MenuItem selection, Modifiers mods)
877 projectView.MenuBrowseFolder(null, mods);
881 MenuDivider { projectMenu };
882 MenuItem projectRunItem
884 projectMenu, $"Run", r, ctrlF5, disabled = true;
885 bitmap = { ":actions/run.png" };
886 bool NotifySelect(MenuItem selection, Modifiers mods)
889 projectView.Run(null, mods);
893 MenuItem projectBuildItem
895 projectMenu, $"Build", b, f7, disabled = true;
896 bitmap = { ":actions/build.png" };
897 bool NotifySelect(MenuItem selection, Modifiers mods)
900 projectView.ProjectBuild(projectView.active ? selection : null, mods);
904 MenuItem projectLinkItem
906 projectMenu, $"Relink", l, disabled = true;
907 bitmap = { ":actions/relink.png" };
908 bool NotifySelect(MenuItem selection, Modifiers mods)
911 projectView.ProjectLink(projectView.active ? selection : null, mods);
915 MenuItem projectRebuildItem
917 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
918 bitmap = { ":actions/rebuild.png" };
919 bool NotifySelect(MenuItem selection, Modifiers mods)
922 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
926 MenuItem projectCleanItem
928 projectMenu, $"Clean", e, disabled = true;
929 bitmap = { ":actions/clean.png" };
930 bool NotifySelect(MenuItem selection, Modifiers mods)
935 projectView.ProjectClean(projectView.active ? selection : null, mods);
940 MenuItem projectRegenerateItem
942 projectMenu, $"Regenerate Makefile", m, disabled = true;
943 bitmap = { ":actions/regMakefile.png" };
944 bool NotifySelect(MenuItem selection, Modifiers mods)
947 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
951 MenuItem projectCompileItem;
952 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
953 MenuItem debugStartResumeItem
955 debugMenu, $"Start", s, f5, disabled = true;
956 bitmap = { ":actions/debug.png" };
957 NotifySelect = MenuDebugStart;
959 bool MenuDebugStart(MenuItem selection, Modifiers mods)
963 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
964 if(!projectView.DebugStart())
965 debugStartResumeItem.disabled = false; // same exception
969 bool MenuDebugResume(MenuItem selection, Modifiers mods)
972 projectView.DebugResume();
975 MenuItem debugRestartItem
977 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
978 bitmap = { ":actions/restart.png" };
979 bool NotifySelect(MenuItem selection, Modifiers mods)
982 projectView.DebugRestart();
986 MenuItem debugBreakItem
988 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
989 bitmap = { ":actions/pause.png" };
990 bool NotifySelect(MenuItem selection, Modifiers mods)
993 projectView.DebugBreak();
997 MenuItem debugStopItem
999 debugMenu, $"Stop", p, shiftF5, disabled = true;
1000 bitmap = { ":actions/stopDebug.png" };
1001 bool NotifySelect(MenuItem selection, Modifiers mods)
1004 projectView.DebugStop();
1008 MenuDivider { debugMenu };
1009 MenuItem debugStepIntoItem
1011 debugMenu, $"Step Into", i, f11, disabled = true;
1012 bitmap = { ":actions/stepInto.png" };
1013 bool NotifySelect(MenuItem selection, Modifiers mods)
1016 projectView.DebugStepInto();
1020 MenuItem debugStepOverItem
1022 debugMenu, $"Step Over", v, f10, disabled = true;
1023 bitmap = { ":actions/stepOver.png" };
1024 bool NotifySelect(MenuItem selection, Modifiers mods)
1027 projectView.DebugStepOver(false);
1031 MenuItem debugStepOutItem
1033 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1034 bitmap = { ":actions/stepOut.png" };
1035 bool NotifySelect(MenuItem selection, Modifiers mods)
1038 projectView.DebugStepOut(false);
1042 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1043 MenuItem debugSkipStepOverItem
1045 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1046 bool NotifySelect(MenuItem selection, Modifiers mods)
1049 projectView.DebugStepOver(true);
1053 MenuItem debugSkipStepOutItem
1055 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1056 bitmap = { ":actions/skipBreaks.png" };
1057 bool NotifySelect(MenuItem selection, Modifiers mods)
1060 projectView.DebugStepOut(true);
1064 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1065 //MenuDivider { debugMenu };
1066 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1067 MenuPlacement imageMenu { menu, $"Image", i };
1068 Menu viewMenu { menu, $"View", v };
1069 MenuItem viewProjectItem
1071 viewMenu, $"Project View", j, alt0, disabled = true;
1072 bool NotifySelect(MenuItem selection, Modifiers mods)
1076 projectView.visible = true;
1077 projectView.Activate();
1082 MenuPlacement { viewMenu, $"View Designer" };
1083 MenuPlacement { viewMenu, $"View Code" };
1084 MenuPlacement { viewMenu, $"View Properties" };
1085 MenuPlacement { viewMenu, $"View Methods" };
1086 MenuItem viewDesignerItem
1088 viewMenu, $"View Designer", d, f8;
1089 bool NotifySelect(MenuItem selection, Modifiers mods)
1091 Window client = activeClient;
1092 Class dataType = client._class;
1093 if(!strcmp(dataType.name, "Designer"))
1095 client.visible = true;
1099 ((CodeEditor)client).ViewDesigner();
1103 MenuItem viewCodeItem
1105 viewMenu, $"View Code", c, f8;
1106 bool NotifySelect(MenuItem selection, Modifiers mods)
1108 Window client = activeClient;
1109 Class dataType = client._class;
1110 if(!strcmp(dataType.name, "Designer"))
1111 client = ((Designer)client).codeEditor;
1114 // Do this after so the caret isn't moved yet...
1115 client.visible = true;
1119 MenuItem viewPropertiesItem
1121 viewMenu, $"View Properties", p, f4;
1122 bool NotifySelect(MenuItem selection, Modifiers mods)
1124 sheet.visible = true;
1125 sheet.sheetSelected = properties;
1130 MenuItem viewMethodsItem
1132 viewMenu, $"View Methods", m, f4;
1133 bool NotifySelect(MenuItem selection, Modifiers mods)
1135 sheet.visible = true;
1136 sheet.sheetSelected = methods;
1141 MenuItem viewToolBoxItem
1143 viewMenu, $"View Toolbox", x, f12;
1144 bool NotifySelect(MenuItem selection, Modifiers mods)
1146 toolBox.visible = true;
1151 MenuItem viewOutputItem
1153 viewMenu, $"Output", o, alt2;
1154 bool NotifySelect(MenuItem selection, Modifiers mods)
1160 MenuItem viewWatchesItem
1162 viewMenu, $"Watches", w, alt3;
1163 bool NotifySelect(MenuItem selection, Modifiers mods)
1169 MenuItem viewThreadsItem
1171 viewMenu, $"Threads", t, alt4;
1172 bool NotifySelect(MenuItem selection, Modifiers mods)
1178 MenuItem viewBreakpointsItem
1180 viewMenu, $"Breakpoints", b, alt5;
1181 bool NotifySelect(MenuItem selection, Modifiers mods)
1183 breakpointsView.Show();
1187 MenuItem viewCallStackItem
1189 viewMenu, $"Call Stack", s, alt7;
1190 bool NotifySelect(MenuItem selection, Modifiers mods)
1192 callStackView.Show();
1196 MenuItem viewAllDebugViews
1198 viewMenu, $"All Debug Views", a, alt9;
1199 bool NotifySelect(MenuItem selection, Modifiers mods)
1204 callStackView.Show();
1205 breakpointsView.Show();
1209 #ifdef GDB_DEBUG_GUI
1210 MenuDivider { viewMenu };
1211 MenuItem viewGDBItem
1213 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1214 bool NotifySelect(MenuItem selection, Modifiers mods)
1221 MenuDivider { viewMenu };
1222 MenuItem viewColorPicker
1224 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1225 bool NotifySelect(MenuItem selection, Modifiers mods)
1227 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1228 colorPicker.Create();
1232 MenuDivider { viewMenu };
1236 viewMenu, "Full Screen", f, checkable = true;
1238 bool NotifySelect(MenuItem selection, Modifiers mods)
1240 app.fullScreen ^= true;
1242 anchor = { 0, 0, 0, 0 };
1247 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1248 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1249 Menu windowMenu { menu, $"Window", w };
1250 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1251 MenuDivider { windowMenu };
1252 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1253 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1254 MenuDivider { windowMenu };
1255 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1256 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1257 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1258 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1259 MenuDivider { windowMenu };
1260 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1261 Menu helpMenu { menu, $"Help", h };
1264 helpMenu, $"API Reference", r, f1;
1265 bool NotifySelect(MenuItem selection, Modifiers mods)
1267 Execute("documentor");
1271 MenuDivider { helpMenu };
1274 helpMenu, $"About...", a;
1275 bool NotifySelect(MenuItem selection, Modifiers mods)
1277 AboutIDE { master = this }.Modal();
1282 property ToolBox toolBox
1284 get { return toolBox; }
1287 property Sheet sheet
1289 get { return sheet; }
1292 property Project project
1294 get { return projectView ? projectView.project : null; }
1297 property Workspace workspace
1299 get { return projectView ? projectView.workspace : null; }
1302 FindInFilesDialog findInFilesDialog
1304 master = this, parent = this;
1305 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1309 #ifdef GDB_DEBUG_GUI
1312 master = this, parent = this;
1313 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1315 void OnCommand(char * string)
1318 ide.debugger.SendGDBCommand(string);
1323 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1325 //app.driver = app.drivers[selection.id];
1327 app.driver = selection.id ? "OpenGL" : "X";
1329 app.driver = selection.id ? "OpenGL" : "GDI";
1331 delete ideSettings.displayDriver;
1332 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1334 settingsContainer.Save();
1335 //SetDriverAndSkin();
1339 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1341 app.skin = app.skins[selection.id];
1346 void SetDriverAndSkin()
1349 for(c = 0; c < app.numSkins; c++)
1350 if(!strcmp(app.skins[c], app.skin))
1352 skinItems[c].checked = true;
1355 for(c = 0; c < app.numDrivers; c++)
1356 if(!strcmp(app.drivers[c], app.driver))
1358 driverItems[c].checked = true;
1363 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1365 Project project = workspace.projects.firstIterator.data;
1366 projectView = ProjectView
1369 fileName = fileName;
1371 void NotifyDestroyed(Window window, DialogResult result)
1374 text = titleECEREIDE;
1379 projectView.Create();
1380 RepositionWindows(false);
1382 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1383 projectView.workspace = workspace;
1384 projectView.project = project;
1385 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1389 ide.breakpointsView.LoadFromWorkspace();
1390 ide.watchesView.LoadFromWorkspace();
1392 findInFilesDialog.projectNodeField.userData = projectView;
1395 char fileName[MAX_LOCATION];
1396 strcpy(fileName, project.topNode.path);
1397 PathCat(fileName, project.topNode.name);
1402 bool GetDebugMenusDisabled()
1406 Project project = projectView.project;
1408 if(project.GetTargetType(project.config) == executable)
1415 void RepositionWindows(bool expand)
1420 bool inDebugMode = debugger.isActive;
1421 bool callStackVisible = expand ? false : callStackView.visible;
1422 bool threadsVisible = expand ? false : threadsView.visible;
1423 bool watchesVisible = expand ? false : watchesView.visible;
1424 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1425 bool toolBoxVisible = toolBox.visible;
1426 bool outputVisible = expand ? false : outputView.visible;
1427 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1428 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1430 for(child = firstChild; child; child = child.next)
1432 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1433 child._class == class(Sheet) || child._class == class(ProjectView))
1435 Anchor anchor = child.anchor;
1436 anchor.top = topDistance;
1437 anchor.bottom = bottomDistance;
1438 if(child._class == class(CodeEditor) || child._class == class(Designer))
1440 anchor.right = toolBoxVisible ? 150 : 0;
1442 child.anchor = anchor;
1446 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1447 child._class == class(BreakpointsView))
1448 child.visible = false;
1451 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1456 bool ShowCodeEditor()
1459 activeClient.Activate();
1460 else if(projectView)
1462 projectView.visible = true;
1463 projectView.Activate();
1467 sheet.visible = true;
1473 bool ShouldStopBuild()
1475 return projectView.stopBuild;
1478 void DocumentSaved(Window document, char * fileName)
1480 ideSettings.AddRecentFile(fileName);
1481 ide.UpdateRecentMenus();
1482 settingsContainer.Save();
1485 bool Window::OnFileModified(FileChange fileChange, char * param)
1488 sprintf(temp, $"The document %s was modified by another application.\n"
1489 "Would you like to reload it and lose your changes?", this.fileName);
1490 if(MessageBox { type = yesNo, master = this/*.parent*/,
1491 text = $"Document has been modified", contents = temp }.Modal() == yes)
1493 char * fileName = CopyString(this.fileName);
1494 WindowState state = this.state;
1495 Anchor anchor = this.anchor;
1496 Size size = this.size;
1498 this.modifiedDocument = false;
1500 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1503 this.anchor = anchor;
1505 this.SetState(state, true, 0);
1513 void UpdateMakefiles()
1517 for(prj : workspace.projects)
1519 bool first = prj == workspace.projects.firstIterator.data;
1520 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1527 bool unavailable = !project;
1529 projectQuickItem.disabled = !unavailable;
1531 projectAddItem.disabled = unavailable;
1532 ((IDEMainFrame)master).toolBar.buttonAddProject.disabled = unavailable;
1534 activeCompilerItem.disabled = unavailable;
1535 projectActiveConfigItem.disabled = unavailable;
1536 projectSettingsItem.disabled = unavailable;
1538 projectBrowseFolderItem.disabled = unavailable;
1540 viewProjectItem.disabled = unavailable;
1546 void AdjustBuildMenus()
1548 bool unavailable = project && projectView.buildInProgress;
1550 projectNewItem.disabled = unavailable;
1551 toolBar.buttonNewProject.disabled = unavailable;
1552 projectOpenItem.disabled = unavailable;
1553 toolBar.buttonOpenProject.disabled = unavailable;
1555 unavailable = !project || projectView.buildInProgress;
1557 projectCloseItem.disabled = unavailable;
1558 // toolBar.buttonCloseProject.disabled = unavailable;
1560 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1561 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1562 projectBuildItem.disabled = unavailable;
1563 toolBar.buttonBuild.disabled = unavailable;
1564 projectLinkItem.disabled = unavailable;
1565 toolBar.buttonReLink.disabled = unavailable;
1566 projectRebuildItem.disabled = unavailable;
1567 toolBar.buttonRebuild.disabled = unavailable;
1568 projectCleanItem.disabled = unavailable;
1569 toolBar.buttonClean.disabled = unavailable;
1570 projectRegenerateItem.disabled = unavailable;
1571 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1572 projectCompileItem.disabled = unavailable;
1575 void AdjustDebugMenus()
1577 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1578 projectView.buildInProgress == buildingMainProject;
1579 bool active = ide.debugger.isActive;
1580 bool executing = ide.debugger.state == running;
1581 //bool holding = ide.debugger.state == stopped;
1583 debugStartResumeItem.disabled = unavailable || executing;
1585 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1587 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1589 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1590 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1592 debugBreakItem.disabled = unavailable || !executing;
1594 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1595 debugStopItem.disabled = unavailable || !active;
1597 toolBar.buttonDebugStop.disabled = unavailable || !active;
1598 debugRestartItem.disabled = unavailable || !active;
1600 toolBar.buttonDebugRestart.disabled =unavailable || !active;
1602 debugStepIntoItem.disabled = unavailable || executing;
1604 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1605 debugStepOverItem.disabled = unavailable || executing;
1607 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1608 debugStepOutItem.disabled = unavailable || executing || !active;
1610 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1611 debugSkipStepOverItem.disabled = unavailable || executing;
1613 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1614 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1616 if((Designer)GetActiveDesigner())
1618 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1621 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1622 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1627 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1629 char tempString[MAX_LOCATION];
1630 strcpy(tempString, directory);
1631 if(saveSettings && !projectView)
1633 ideSettings.ideFileDialogLocation = directory;
1634 settingsContainer.Save();
1637 ideFileDialog.currentDirectory = tempString;
1638 codeEditorFileDialog.currentDirectory = tempString;
1639 codeEditorFormFileDialog.currentDirectory = tempString;
1642 void ChangeProjectFileDialogDirectory(char * directory)
1644 ideSettings.ideProjectFileDialogLocation = directory;
1645 settingsContainer.Save();
1648 Window FindWindow(char * filePath)
1650 Window document = null;
1652 // TOCHECK: Do we need to change slashes here?
1653 for(document = firstChild; document; document = document.next)
1655 char * fileName = document.fileName;
1656 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1658 document.visible = true;
1659 document.Activate();
1666 bool DontTerminateDebugSession(char * title)
1668 if(debugger.isActive)
1670 if(MessageBox { type = yesNo, master = ide,
1671 contents = $"Do you want to terminate the debugging session in progress?",
1672 text = title }.Modal() == no)
1675 MessageBox msg { type = yesNo, master = ide,
1676 contents = "Do you want to terminate the debugging session in progress?",
1678 if(msg.Modal() == no)
1690 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1692 char extension[MAX_EXTENSION] = "";
1693 Window document = null;
1694 bool isProject = false;
1695 bool needFileModified = true;
1696 char winFilePath[MAX_LOCATION];
1697 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1701 GetExtension(filePath, extension);
1705 strcpy(extension, type);
1707 if(strcmp(extension, ProjectExtension))
1709 for(document = firstChild; document; document = document.next)
1711 char * fileName = document.fileName;
1712 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1714 document.visible = true;
1715 document.Activate();
1721 if(createIfFails == whatever)
1723 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1725 if(openMethod == normal)
1727 if(DontTerminateDebugSession($"Open Project"))
1730 if(MenuWindowCloseAll(null, 0))
1734 projectView.visible = false;
1735 projectView.Destroy(0);
1736 // Where did this come from? projectView = null;
1743 Workspace workspace = null;
1745 if(FileExists(filePath))
1747 if(!strcmp(extension, ProjectExtension))
1749 char workspaceFile[MAX_LOCATION];
1750 strcpy(workspaceFile, filePath);
1751 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1752 workspace = LoadWorkspace(workspaceFile, filePath);
1754 else if(!strcmp(extension, WorkspaceExtension))
1755 workspace = LoadWorkspace(filePath, null);
1758 //project = LoadProject(filePath);
1763 char absolutePath[MAX_LOCATION];
1764 CreateProjectView(workspace, filePath);
1765 document = projectView;
1767 workspace.DropInvalidBreakpoints();
1770 ide.projectView.ShowOutputBuildLog(true);
1772 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1773 ide.projectView.DisplayCompiler(compiler, false);
1778 char newWorkingDir[MAX_LOCATION];
1779 StripLastDirectory(filePath, newWorkingDir);
1780 ChangeFileDialogsDirectory(newWorkingDir, false);
1783 document.fileName = filePath;
1785 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1787 // this crashes on starting ide with epj file, solution please?
1788 // app.UpdateDisplay();
1790 workspace.holdTracking = true;
1791 for(ofi : workspace.openedFiles)
1793 if(ofi.state != closed)
1795 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1798 char fileName[MAX_LOCATION];
1800 GetLastDirectory(ofi.path, fileName);
1801 node = projectView.project.topNode.Find(fileName, true);
1803 node.EnsureVisible();
1807 workspace.holdTracking = false;
1809 workspace.timer.Start();
1811 findInFilesDialog.mode = FindInFilesMode::project;
1812 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1815 char location[MAX_LOCATION];
1816 StripLastDirectory(ide.project.topNode.path, location);
1817 ChangeProjectFileDialogDirectory(location);
1821 if(projectView.debugger)
1822 projectView.debugger.EvaluateWatches();
1829 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1831 ideProjectFileDialog.text = openProjectFileDialogTitle;
1832 if(ideProjectFileDialog.Modal() == cancel)
1834 filePath = ideProjectFileDialog.filePath;
1835 GetExtension(filePath, extension);
1846 else if(openMethod == add)
1851 char slashFilePath[MAX_LOCATION];
1852 GetSlashPathBuffer(slashFilePath, filePath);
1853 for(p : workspace.projects)
1855 if(!fstrcmp(p.filePath, slashFilePath))
1863 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1864 contents = $"This project is already present in workspace." }.Modal();
1868 prj = LoadProject(filePath);
1871 workspace.projects.Add(prj);
1873 projectView.AddNode(prj.topNode, null);
1874 workspace.modified = true;
1876 findInFilesDialog.AddProjectItem(prj);
1877 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1880 char location[MAX_LOCATION];
1881 StripLastDirectory(prj.topNode.path, location);
1882 ChangeProjectFileDialogDirectory(location);
1885 // projectView is associated with the main project and not with the one just added but
1886 return projectView; // just to let the caller know something was opened
1894 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1895 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1896 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1898 if(FileExists(filePath))
1899 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1900 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1901 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1904 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1907 else if(!strcmp(extension, "3ds"))
1909 if(FileExists(filePath))
1910 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1911 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1912 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1916 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1919 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1920 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1921 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1922 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1923 !strcmp(extension, "js"))
1925 CodeEditor editor { parent = this, state = state, visible = false };
1926 editor.updatingCode = true;
1927 if(editor.LoadFile(filePath))
1930 editor.visible = true;
1934 needFileModified = false;
1938 CodeEditor editor { parent = this, state = state, visible = false };
1939 if(editor.LoadFile(filePath))
1942 editor.visible = true;
1946 needFileModified = false;
1949 if(document && (document._class == class(PictureEdit) ||
1950 document._class == class(ModelView)))
1955 document.fileName = filePath;
1956 if(workspace && !workspace.holdTracking)
1957 workspace.UpdateOpenedFileInfo(filePath, opened);
1961 if(!document && createIfFails != no)
1963 if(createIfFails != yes && !needFileModified &&
1964 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1965 createIfFails = yes;
1966 if(createIfFails == yes || createIfFails == whatever)
1968 document = (Window)NewCodeEditor(this, state, true);
1970 document.fileName = filePath;
1976 if(projectView && document._class == class(CodeEditor) && workspace)
1978 int lineNumber, position;
1980 CodeEditor editor = (CodeEditor)document;
1981 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1982 editor.openedFileInfo.holdTracking = true;
1983 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1984 position = Max(editor.openedFileInfo.position - 1, 0);
1985 editor.editBox.GoToLineNum(lineNumber);
1986 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1987 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1988 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1989 editor.editBox.scroll = scroll;
1990 editor.openedFileInfo.holdTracking = false;
1993 if(needFileModified)
1994 document.OnFileModified = OnFileModified;
1995 document.NotifySaved = DocumentSaved;
1998 ideSettings.AddRecentProject(document.fileName);
2000 ideSettings.AddRecentFile(document.fileName);
2001 ide.UpdateRecentMenus();
2002 settingsContainer.Save();
2010 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2011 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2013 if(!parentClosing && ide.workspace)
2014 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2017 bool ModelView::ModelViewOnClose(bool parentClosing)
2019 if(!parentClosing && ide.workspace)
2020 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2023 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2025 if(!parentClosing && ide.workspace)
2026 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2031 void OnUnloadGraphics(Window window)
2033 display.ClearMaterials();
2034 display.ClearTextures();
2035 display.ClearMeshes();
2039 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2041 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2042 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2046 bool OnKeyDown(Key key, unichar ch)
2051 projectView.Update(null);
2054 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2057 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2063 void GoToError(const char * line)
2066 projectView.GoToError(line);
2069 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2072 char *colon = strchr(text, ':');
2073 char filePath[MAX_LOCATION];
2074 char completePath[MAX_LOCATION];
2075 int line = 0, col = 0;
2080 char * close = strchr(text, ')');
2084 strncpy(name, &text[4], close - text - 4);
2085 name[close - text - 4] = '\0';
2086 for(p : ide.workspace.projects)
2088 if(!strcmp(p.name, name))
2098 prj = project ? project : (dir ? null : ide.project);
2099 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2101 path = (colon - 1 > path) ? colon - 1 : path;
2102 colon = strstr(colon + 1, ":");
2104 while(isspace(*path)) path++;
2107 strncpy(filePath, path, colon - path);
2108 filePath[colon - path] = '\0';
2109 line = atoi(colon + 1);
2110 colon = strstr(colon + 1, ":");
2112 col = atoi(colon + 1);
2114 else if(path - 1 >= path && *(path - 1) == '\"')
2116 colon = strchr(path, '\"');
2119 strncpy(filePath, path, colon - path);
2120 filePath[colon - path] = '\0';
2125 strcpy(completePath, prj.topNode.path);
2126 else if(dir && dir[0])
2127 strcpy(completePath, dir);
2129 completePath[0] = '\0';
2130 PathCat(completePath, filePath);
2132 if(FileExists(completePath).isFile)
2134 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2135 if(codeEditor && line)
2137 EditBox editBox = codeEditor.editBox;
2138 editBox.GoToLineNum(line - 1);
2139 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2144 void OnRedraw(Surface surface)
2146 Bitmap bitmap = back.bitmap;
2148 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2151 void SheetSelected(SheetType sheetSelected)
2153 if(activeChild == sheet)
2155 if(sheetSelected == methods)
2157 viewPropertiesItem.accelerator = f4;
2158 viewPropertiesItem.parent = viewMenu;
2159 viewMethodsItem.parent = null;
2163 viewMethodsItem.accelerator = f4;
2164 viewMethodsItem.parent = viewMenu;
2165 viewPropertiesItem.parent = null;
2170 viewMethodsItem.parent = viewMenu;
2171 viewPropertiesItem.parent = viewMenu;
2172 if(sheetSelected == methods)
2174 viewMethodsItem.accelerator = f4;
2175 viewPropertiesItem.accelerator = 0;
2179 viewMethodsItem.accelerator = 0;
2180 viewPropertiesItem.accelerator = f4;
2185 void OnActivateClient(Window client, Window previous)
2187 //if(!client || client != previous)
2190 if(!client || client != previous)
2193 dataType = previous._class;
2194 if(previous && !strcmp(dataType.name, "CodeEditor"))
2196 ((CodeEditor)previous).UpdateFormCode();
2198 else if(previous && !strcmp(dataType.name, "Designer"))
2200 ((Designer)previous).codeEditor.UpdateFormCode();
2205 dataType = client._class;
2206 if(client && !strcmp(dataType.name, "CodeEditor"))
2208 CodeEditor codeEditor = (CodeEditor)client;
2209 SetPrivateModule(codeEditor.privateModule);
2210 SetCurrentContext(codeEditor.globalContext);
2211 SetTopContext(codeEditor.globalContext);
2212 SetGlobalContext(codeEditor.globalContext);
2214 SetDefines(&codeEditor.defines);
2215 SetImports(&codeEditor.imports);
2217 SetActiveDesigner(codeEditor.designer);
2219 sheet.codeEditor = codeEditor;
2220 toolBox.codeEditor = codeEditor;
2222 viewDesignerItem.parent = viewMenu;
2223 if(activeChild != codeEditor)
2225 viewCodeItem.parent = viewMenu;
2226 viewDesignerItem.accelerator = 0;
2227 viewCodeItem.accelerator = f8;
2231 viewCodeItem.parent = null;
2232 viewDesignerItem.accelerator = f8;
2235 else if(client && !strcmp(dataType.name, "Designer"))
2237 CodeEditor codeEditor = ((Designer)client).codeEditor;
2240 SetPrivateModule(codeEditor.privateModule);
2241 SetCurrentContext(codeEditor.globalContext);
2242 SetTopContext(codeEditor.globalContext);
2243 SetGlobalContext(codeEditor.globalContext);
2244 SetDefines(&codeEditor.defines);
2245 SetImports(&codeEditor.imports);
2249 SetPrivateModule(null);
2250 SetCurrentContext(null);
2251 SetTopContext(null);
2252 SetGlobalContext(null);
2257 SetActiveDesigner((Designer)client);
2259 sheet.codeEditor = codeEditor;
2260 toolBox.codeEditor = codeEditor;
2262 viewCodeItem.parent = viewMenu;
2263 if(activeChild != client)
2265 viewDesignerItem.parent = viewMenu;
2266 viewDesignerItem.accelerator = f8;
2267 viewCodeItem.accelerator = 0;
2271 viewDesignerItem.parent = null;
2272 viewCodeItem.accelerator = f8;
2278 sheet.codeEditor = null;
2279 toolBox.codeEditor = null;
2280 SetActiveDesigner(null);
2282 viewDesignerItem.parent = null;
2283 viewCodeItem.parent = null;
2286 SheetSelected(sheet.sheetSelected);
2289 projectCompileItem = null;
2294 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2296 CodeEditor codeEditor = (CodeEditor)client;
2297 EditBox editBox = codeEditor.editBox;
2299 statusBar.AddField(pos);
2301 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2302 statusBar.AddField(caps);
2304 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2305 statusBar.AddField(ovr);
2307 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2308 statusBar.AddField(num);
2310 //statusBar.text = "Ready";
2312 if(projectView && projectView.project)
2314 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2318 sprintf(name, $"Compile %s", node.name);
2319 projectCompileItem =
2321 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2323 bool NotifySelect(MenuItem selection, Modifiers mods)
2327 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2329 projectView.Compile(node);
2334 projectMenu.AddDynamic(projectCompileItem, ide, false);
2340 caps = ovr = num = null;
2345 bool OnClose(bool parentClosing)
2347 //return !projectView.buildInProgress;
2348 if(projectView && projectView.buildInProgress)
2350 if(DontTerminateDebugSession($"Close IDE"))
2352 if(findInFilesDialog)
2353 findInFilesDialog.SearchStop();
2356 workspace.timer.Stop();
2359 ideMainFrame.Destroy(0);
2366 for(c = 1; c<app.argc; c++)
2368 char fullPath[MAX_LOCATION];
2369 GetWorkingDir(fullPath, MAX_LOCATION);
2370 PathCat(fullPath, app.argv[c]);
2371 if(FileExists(fullPath))
2372 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2379 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2382 projectView.visible = false;
2383 projectView.Destroy(0);
2386 #ifdef GDB_DEBUG_GUI
2387 gdbDialog.Destroy(0);
2392 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2396 char * oldPaths[128];
2397 String oldList = new char[maxPathLen];
2398 Array<String> newExePaths { };
2399 //Map<String, bool> exePathExists { };
2401 #if defined(__unix__) || defined(__APPLE__)
2402 Array<String> newLibPaths { };
2403 Map<String, bool> libPathExists { };
2408 for(prj : workspace.projects)
2410 DirExpression targetDirExp;
2412 // SKIP FIRST PROJECT...
2413 if(prj == workspace.projects.firstIterator.data) continue;
2415 // NOTE: Right now the additional project config dir will be
2416 // obtained when the debugger is started, so toggling it
2417 // while building will change which library gets used.
2418 // To go with the initial state, e.g. when F5 was pressed,
2419 // we nould need to keep a list of all project's active
2420 // config upon startup.
2421 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2423 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2427 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2428 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2432 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2433 if(cfg.targetType == sharedLibrary && cfg.debug)
2437 if(targetDirExp.dir)
2439 char buffer[MAX_LOCATION];
2440 #if defined(__WIN32__)
2441 Array<String> paths = newExePaths;
2443 Array<String> paths = newLibPaths;
2445 GetSystemPathBuffer(buffer, prj.topNode.path);
2446 PathCat(buffer, targetDirExp.dir);
2449 if(!fstrcmp(p, buffer))
2456 paths.Add(CopyString(buffer));
2458 delete targetDirExp;
2462 for(item : compiler.executableDirs)
2465 for(p : newExePaths)
2467 if(!fstrcmp(p, item))
2474 newExePaths.Add(CopySystemPath(item));
2477 GetEnvironment("PATH", oldList, maxPathLen);
2479 printf("Old value of PATH: %s\n", oldList);
2481 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2482 for(c = 0; c < count; c++)
2485 for(p : newExePaths)
2487 if(!fstrcmp(p, oldPaths[c]))
2494 newExePaths.Add(CopySystemPath(oldPaths[c]));
2498 for(path : newExePaths)
2499 len += strlen(path) + 1;
2500 newList = new char[len + 1];
2502 for(path : newExePaths)
2504 strcat(newList, path);
2505 strcat(newList, pathListSep);
2507 newList[len - 1] = '\0';
2508 SetEnvironment("PATH", newList);
2510 printf("New value of PATH: %s\n", newList);
2517 #if defined(__unix__) || defined(__APPLE__)
2519 for(item : compiler.libraryDirs)
2521 if(!libPathExists[item]) // fstrcmp should be used
2523 newLibPaths.Add(item);
2524 libPathExists[item] = true;
2528 #if defined(__APPLE__)
2529 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2531 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2534 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2536 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2537 for(c = 0; c < count; c++)
2539 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2541 newLibPaths.Add(oldPaths[c]);
2542 libPathExists[oldPaths[c]] = true;
2547 for(path : newLibPaths)
2548 len += strlen(path) + 1;
2549 newList = new char[len + 1];
2551 for(path : newLibPaths)
2553 strcat(newList, path);
2554 strcat(newList, pathListSep);
2556 newList[len - 1] = '\0';
2557 #if defined(__APPLE__)
2558 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2560 SetEnvironment("LD_LIBRARY_PATH", newList);
2563 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2568 delete libPathExists;
2571 if(compiler.distccEnabled && compiler.distccHosts)
2572 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2577 void DestroyTemporaryProjectDir()
2579 if(tmpPrjDir && tmpPrjDir[0])
2581 if(FileExists(tmpPrjDir).isDirectory)
2582 DestroyDir(tmpPrjDir);
2583 property::tmpPrjDir = null;
2589 // Graphics Driver Menu
2593 app.currentSkin.selectionColor = selectionColor;
2594 app.currentSkin.selectionText = selectionText;
2598 driverItems = new MenuItem[app.numDrivers];
2599 for(c = 0; c < app.numDrivers; c++)
2601 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2602 driverItems[c].id = c;
2603 driverItems[c].isRadio = true;
2606 driverItems = new MenuItem[2];
2607 #if defined(__unix__)
2608 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2609 driverItems[0].id = 0;
2610 driverItems[0].isRadio = true;
2612 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2613 driverItems[0].id = 0;
2614 driverItems[0].isRadio = true;
2616 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2617 driverItems[1].id = 1;
2618 driverItems[1].isRadio = true;
2620 /* skinItems = new MenuItem[app.numSkins];
2621 for(c = 0; c < app.numSkins; c++)
2623 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2624 skinItems[c].id = c;
2625 skinItems[c].isRadio = true;
2628 ideFileDialog.master = this;
2629 ideProjectFileDialog.master = this;
2631 //SetDriverAndSkin();
2635 void UpdateRecentMenus()
2638 Menu fileMenu = menu.FindMenu($"File");
2639 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2640 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2641 char itemName[MAX_LOCATION + 4];
2644 recentFiles.Clear();
2647 for(recent : ideSettings.recentFiles)
2649 sprintf(itemName, "%d %s", 1 + c, recent);
2650 MakeSystemPath(itemName);
2651 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2655 recentProjects.Clear();
2657 for(recent : ideSettings.recentProjects)
2659 sprintf(itemName, "%d %s", 1 + c, recent);
2660 MakeSystemPath(itemName);
2661 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2674 void DestroyDir(char * path)
2676 RecursiveDeleteFolderFSI fsi { };
2681 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2683 bool preserveRootFolder;
2685 void OutFolder(char * folderPath, bool isRoot)
2687 if(!(preserveRootFolder && isRoot))
2688 RemoveDir(folderPath);
2691 bool OnFile(char * filePath)
2693 DeleteFile(filePath);
2698 class IDEApp : GuiApplication
2700 //driver = "Win32Console";
2701 // driver = "OpenGL";
2706 SetLoggingMode(stdOut, null);
2707 //SetLoggingMode(debug, null);
2709 settingsContainer.Load();
2710 #if defined(__unix__) || defined(__APPLE__)
2711 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2713 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2715 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2719 desktop.text = titleECEREIDE;
2722 for(c = 1; c<app.argc; c++)
2724 char fullPath[MAX_LOCATION];
2725 GetWorkingDir(fullPath, MAX_LOCATION);
2726 PathCat(fullPath, app.argv[c]);
2727 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2734 IDEMainFrame ideMainFrame { };
2736 define app = ((IDEApp)__thisModule);
2738 define titleECEREIDE = $"ECERE IDE (Debug)";
2740 define titleECEREIDE = $"ECERE IDE";