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.UpdateCompilerConfigs();
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; };
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
250 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
252 ToolSeparator separator4 { this };
256 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
258 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
260 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
262 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
264 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
266 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
268 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
270 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
272 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
275 class IDEMainFrame : Window
277 background = formColor;
278 borderStyle = sizable;
282 minClientSize = { 600, 300 };
284 icon = { ":icon.png" };
285 text = titleECEREIDE;
289 anchor = { top = 0, right = 0, bottom = 0 };
292 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
299 isActiveClient = true;
301 direction = vertical;
302 background = formColor;
303 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
311 ((IDEWorkSpace)master).toolBar = null;
314 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
317 define ide = ideMainFrame.ideWorkSpace;
319 class IDEWorkSpace : Window
321 background = Color { 85, 85, 85 };
324 hasVertScroll = true;
325 hasHorzScroll = true;
327 isActiveClient = true;
328 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
332 MenuItem * driverItems, * skinItems;
333 StatusField pos { width = 150 };
334 StatusField ovr, caps, num;
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 };
348 Debugger debugger { };
350 ProjectView projectView;
352 OutputView outputView
356 void OnGotoError(char * line)
361 void OnCodeLocationParseAndGoTo(char * line)
363 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
366 bool OnKeyDown(Key key, unichar ch)
371 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
372 ide.ShowCodeEditor();
375 ide.projectView.stopBuild = true;
379 OutputView::OnKeyDown(key, ch);
386 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
389 ide.RepositionWindows(false);
393 bool OnClose(bool parentClosing)
397 ide.RepositionWindows(false);
398 return parentClosing;
402 CallStackView callStackView
404 parent = this, font = { panelFont.faceName, panelFont.size };
406 void OnGotoLine(char * line)
409 stackLvl = atoi(line);
410 ide.debugger.GoToStackFrameLine(stackLvl, true);
413 void OnSelectFrame(int lineNumber)
415 ide.debugger.SelectFrame(lineNumber);
418 void OnToggleBreakpoint()
420 Debugger debugger = ide.debugger;
421 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
423 int line = debugger.activeFrame.line;
424 char name[MAX_LOCATION];
426 // TOFIX: Improve on this, don't use only filename, make a function
427 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
428 if(ide && ide.workspace)
430 for(p : ide.workspace.projects)
432 if(p.topNode.Find(name, false))
440 for(p : ide.workspace.projects)
442 if(IsPathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
450 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
453 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
454 if(codeEditor) { codeEditor.Update(null); Activate(); }
459 bool OnKeyDown(Key key, unichar ch)
463 case escape: ide.ShowCodeEditor(); break;
468 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
471 ide.RepositionWindows(false);
475 bool OnClose(bool parentClosing)
479 ide.RepositionWindows(false);
480 return parentClosing;
483 void OnRedraw(Surface surface)
486 int lineCursor, lineTopFrame, activeThread, hitThread;
487 int lineH, scrollY, boxH;
489 Breakpoint bp = null;
490 Debugger debugger = ide.debugger;
491 Frame activeFrame = debugger.activeFrame;
494 scrollY = editBox.scroll.y;
495 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
497 activeThread = debugger.activeThread;
498 hitThread = debugger.hitThread;
499 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
501 if(activeFrame && activeFrame.absoluteFile)
503 for(i : ide.workspace.breakpoints; i.type == user)
505 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
506 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
507 activeFrame.line == i.line)
516 DrawLineMarginIcon(surface,
517 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
518 lineCursor /*1*/, lineH, scrollY, boxH);
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);
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;
530 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
531 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
532 if(editBox.horzScroll && editBox.horzScroll.visible)
534 surface.SetBackground(control);
535 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
540 WatchesView watchesView { parent = this };
541 ThreadsView threadsView
543 parent = this, font = { panelFont.faceName, panelFont.size };
545 bool OnKeyDown(Key key, unichar ch)
549 case escape: ide.ShowCodeEditor(); break;
554 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
557 ide.RepositionWindows(false);
561 bool OnClose(bool parentClosing)
565 ide.RepositionWindows(false);
566 return parentClosing;
569 void OnSelectThread(int threadId)
572 ide.debugger.SelectThread(threadId);
575 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
578 Debugger debugger = ide.debugger;
579 *activeThread = debugger.activeThread;
580 *hitThread = debugger.hitThread;
581 *signalThread = debugger.signalThread;
586 BreakpointsView breakpointsView { parent = this };
588 ToolBox toolBox { parent = this };
589 Sheet sheet { parent = this };
592 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
594 Menu fileMenu { menu, $"File", f, hasMargin = true };
597 fileMenu, $"New", n, ctrlN;
598 bitmap = { ":actions/docNew.png" };
599 bool NotifySelect(MenuItem selection, Modifiers mods)
601 Window document = (Window)NewCodeEditor(this, normal, false);
602 document.NotifySaved = DocumentSaved;
606 MenuItem fileOpenItem
608 fileMenu, $"Open...", o, ctrlO;
609 bitmap = { ":actions/docOpen.png" };
610 bool NotifySelect(MenuItem selection, Modifiers mods)
612 if(!projectView && ideSettings.ideFileDialogLocation)
613 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
616 if(ideFileDialog.Modal() == ok)
618 bool gotWhatWeWant = false;
620 int numSelections = ideFileDialog.numSelections;
621 char ** multiFilePaths = ideFileDialog.multiFilePaths;
623 for(c = 0; c < numSelections; c++)
625 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
626 gotWhatWeWant = true;
629 MessageBox { type = yesNo, master = this, text = $"Error opening file",
630 contents = $"Open a different file?" }.Modal() == no)
632 if(!projectView && gotWhatWeWant)
633 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
643 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
644 MenuDivider { fileMenu };
645 MenuItem fileSaveItem
647 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
649 // For the toolbar button; clients can still override that for the menu item
650 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
652 Window w = activeClient;
654 w.MenuFileSave(null, 0);
658 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
659 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
660 MenuDivider { fileMenu };
663 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
664 bool NotifySelect(MenuItem selection, Modifiers mods)
666 findInFilesDialog.replaceMode = false;
667 findInFilesDialog.Show();
671 MenuItem replaceInFiles
673 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
674 bool NotifySelect(MenuItem selection, Modifiers mods)
676 findInFilesDialog.replaceMode = true;
677 findInFilesDialog.Show();
681 MenuDivider { fileMenu };
682 MenuItem globalSettingsItem
684 fileMenu, $"Global Settings...", g;
685 bool NotifySelect(MenuItem selection, Modifiers mods)
687 globalSettingsDialog.master = this;
688 if(ide.workspace && ide.workspace.compiler)
689 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
690 else if(ideSettings.defaultCompiler)
691 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
692 globalSettingsDialog.Modal();
696 MenuDivider { fileMenu };
697 Menu recentFiles { fileMenu, $"Recent Files", r };
698 Menu recentProjects { fileMenu, $"Recent Projects", p };
699 MenuDivider { fileMenu };
702 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
704 bool NotifySelect(MenuItem selection, Modifiers mods)
706 ideMainFrame.Destroy(0);
711 bool FileRecentFile(MenuItem selection, Modifiers mods)
714 for(file : ideSettings.recentFiles)
716 if(id == selection.id)
718 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
719 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
720 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
722 // it never gets in here!!!
723 char * command = PrintString("ide ", file);
728 OpenFile(file, normal, true, null, no, normal);
736 bool FileRecentProject(MenuItem selection, Modifiers mods)
739 for(file : ideSettings.recentProjects)
741 if(id == selection.id)
743 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
744 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
745 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
747 // it never gets in here!!!
748 char * command = PrintString("ide ", file);
753 OpenFile(file, normal, true, null, no, normal);
761 MenuPlacement editMenu { menu, $"Edit", e };
763 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
764 MenuItem projectNewItem
766 projectMenu, $"New...", n, Key { n, true, true };
767 bitmap = { ":actions/projNew.png" };
768 bool NotifySelect(MenuItem selection, Modifiers mods)
770 if(!DontTerminateDebugSession($"New Project"))
771 if(MenuWindowCloseAll(null, 0))
773 NewProjectDialog newProjectDialog;
777 projectView.visible = false;
778 if(!projectView.Destroy(0))
782 newProjectDialog = { master = this };
783 newProjectDialog.Modal();
786 ideSettings.AddRecentProject(projectView.fileName);
787 ide.UpdateRecentMenus();
788 settingsContainer.Save();
794 MenuItem projectOpenItem
796 projectMenu, $"Open...", o, Key { o, true, true };
797 bitmap = { ":actions/projOpen.png" };
798 bool NotifySelect(MenuItem selection, Modifiers mods)
800 if(ideSettings.ideProjectFileDialogLocation)
801 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
803 ideProjectFileDialog.text = openProjectFileDialogTitle;
804 if(ideProjectFileDialog.Modal() == ok)
806 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
807 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
812 MenuItem projectQuickItem
814 projectMenu, $"Quick...", q, f7, disabled = true;
815 bool NotifySelect(MenuItem selection, Modifiers mods)
818 QuickProjectDialog{ this }.Modal();
822 MenuItem projectAddItem
824 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
825 bitmap = { ":actions/projAdd.png" };
827 bool NotifySelect(MenuItem selection, Modifiers mods)
829 if(ideSettings.ideProjectFileDialogLocation)
830 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
832 ideProjectFileDialog.text = addProjectFileDialogTitle;
835 if(ideProjectFileDialog.Modal() == ok)
837 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
839 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
840 contents = $"Add a different project?" }.Modal() == no)
851 MenuItem projectCloseItem
853 projectMenu, $"Close", c, disabled = true;
854 bool NotifySelect(MenuItem selection, Modifiers mods)
858 if(!ide.DontTerminateDebugSession($"Project Close"))
860 if(findInFilesDialog)
861 findInFilesDialog.SearchStop();
862 projectView.visible = false;
863 if(projectView.Destroy(0))
864 MenuWindowCloseAll(null, 0);
866 char workingDir[MAX_LOCATION];
867 GetWorkingDir(workingDir, MAX_LOCATION);
868 findInFilesDialog.currentDirectory = workingDir;
869 ideMainFrame.text = titleECEREIDE;
876 MenuDivider { projectMenu };
877 MenuItem activeCompilerItem
879 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
880 bool NotifySelect(MenuItem selection, Modifiers mods)
882 projectView.MenuCompiler(null, mods);
886 MenuItem projectActiveConfigItem
888 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
889 bool NotifySelect(MenuItem selection, Modifiers mods)
891 projectView.MenuConfig(projectView.active ? selection : null, mods);
895 MenuItem projectSettingsItem
897 projectMenu, $"Settings...", s, altF7, disabled = true;
898 bool NotifySelect(MenuItem selection, Modifiers mods)
900 projectView.MenuSettings(projectView.active ? selection : null, mods);
904 MenuDivider { projectMenu };
905 MenuItem projectBrowseFolderItem
907 projectMenu, $"Browse Project Folder", p, disabled = true;
908 bool NotifySelect(MenuItem selection, Modifiers mods)
911 projectView.MenuBrowseFolder(null, mods);
915 MenuDivider { projectMenu };
916 MenuItem projectRunItem
918 projectMenu, $"Run", r, ctrlF5, disabled = true;
919 bitmap = { ":actions/run.png" };
920 bool NotifySelect(MenuItem selection, Modifiers mods)
923 projectView.Run(null, mods);
927 MenuItem projectBuildItem
929 projectMenu, $"Build", b, f7, disabled = true;
930 bitmap = { ":actions/build.png" };
931 bool NotifySelect(MenuItem selection, Modifiers mods)
934 projectView.ProjectBuild(projectView.active ? selection : null, mods);
938 MenuItem projectLinkItem
940 projectMenu, $"Relink", l, disabled = true;
941 bitmap = { ":actions/relink.png" };
942 bool NotifySelect(MenuItem selection, Modifiers mods)
945 projectView.ProjectLink(projectView.active ? selection : null, mods);
949 MenuItem projectRebuildItem
951 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
952 bitmap = { ":actions/rebuild.png" };
953 bool NotifySelect(MenuItem selection, Modifiers mods)
956 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
960 MenuItem projectCleanItem
962 projectMenu, $"Clean", e, disabled = true;
963 bitmap = { ":actions/clean.png" };
964 bool NotifySelect(MenuItem selection, Modifiers mods)
969 projectView.ProjectClean(projectView.active ? selection : null, mods);
974 MenuItem projectRealCleanItem
976 projectMenu, $"Real Clean", disabled = true;
977 bitmap = { ":actions/clean.png" };
978 bool NotifySelect(MenuItem selection, Modifiers mods)
983 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
988 MenuItem projectRegenerateItem
990 projectMenu, $"Regenerate Makefile", m, disabled = true;
991 bitmap = { ":actions/regMakefile.png" };
992 bool NotifySelect(MenuItem selection, Modifiers mods)
995 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
999 MenuItem projectCompileItem;
1000 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1001 MenuItem debugStartResumeItem
1003 debugMenu, $"Start", s, f5, disabled = true;
1004 bitmap = { ":actions/debug.png" };
1005 NotifySelect = MenuDebugStart;
1007 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1011 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1012 if(!projectView.DebugStart())
1013 debugStartResumeItem.disabled = false; // same exception
1017 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1020 projectView.DebugResume();
1023 MenuItem debugRestartItem
1025 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1026 bitmap = { ":actions/restart.png" };
1027 bool NotifySelect(MenuItem selection, Modifiers mods)
1030 projectView.DebugRestart();
1034 MenuItem debugBreakItem
1036 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1037 bitmap = { ":actions/pause.png" };
1038 bool NotifySelect(MenuItem selection, Modifiers mods)
1041 projectView.DebugBreak();
1045 MenuItem debugStopItem
1047 debugMenu, $"Stop", p, shiftF5, disabled = true;
1048 bitmap = { ":actions/stopDebug.png" };
1049 bool NotifySelect(MenuItem selection, Modifiers mods)
1052 projectView.DebugStop();
1056 MenuDivider { debugMenu };
1057 MenuItem debugStepIntoItem
1059 debugMenu, $"Step Into", i, f11, disabled = true;
1060 bitmap = { ":actions/stepInto.png" };
1061 bool NotifySelect(MenuItem selection, Modifiers mods)
1064 projectView.DebugStepInto();
1068 MenuItem debugStepOverItem
1070 debugMenu, $"Step Over", v, f10, disabled = true;
1071 bitmap = { ":actions/stepOver.png" };
1072 bool NotifySelect(MenuItem selection, Modifiers mods)
1075 projectView.DebugStepOver(false);
1079 MenuItem debugStepOutItem
1081 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1082 bitmap = { ":actions/stepOut.png" };
1083 bool NotifySelect(MenuItem selection, Modifiers mods)
1086 projectView.DebugStepOut(false);
1090 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1091 MenuItem debugSkipStepOverItem
1093 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1094 bool NotifySelect(MenuItem selection, Modifiers mods)
1097 projectView.DebugStepOver(true);
1101 MenuItem debugSkipStepOutItem
1103 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1104 bitmap = { ":actions/skipBreaks.png" };
1105 bool NotifySelect(MenuItem selection, Modifiers mods)
1108 projectView.DebugStepOut(true);
1112 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1113 //MenuDivider { debugMenu };
1114 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1115 MenuPlacement imageMenu { menu, $"Image", i };
1116 Menu viewMenu { menu, $"View", v };
1117 MenuItem viewProjectItem
1119 viewMenu, $"Project View", j, alt0, disabled = true;
1120 bool NotifySelect(MenuItem selection, Modifiers mods)
1124 projectView.visible = true;
1125 projectView.Activate();
1130 MenuPlacement { viewMenu, $"View Designer" };
1131 MenuPlacement { viewMenu, $"View Code" };
1132 MenuPlacement { viewMenu, $"View Properties" };
1133 MenuPlacement { viewMenu, $"View Methods" };
1134 MenuItem viewDesignerItem
1136 viewMenu, $"View Designer", d, f8;
1137 bool NotifySelect(MenuItem selection, Modifiers mods)
1139 Window client = activeClient;
1140 Class dataType = client._class;
1141 if(!strcmp(dataType.name, "Designer"))
1143 client.visible = true;
1147 ((CodeEditor)client).ViewDesigner();
1151 MenuItem viewCodeItem
1153 viewMenu, $"View Code", c, f8;
1154 bool NotifySelect(MenuItem selection, Modifiers mods)
1156 Window client = activeClient;
1157 Class dataType = client._class;
1158 if(!strcmp(dataType.name, "Designer"))
1159 client = ((Designer)client).codeEditor;
1162 // Do this after so the caret isn't moved yet...
1163 client.visible = true;
1167 MenuItem viewPropertiesItem
1169 viewMenu, $"View Properties", p, f4;
1170 bool NotifySelect(MenuItem selection, Modifiers mods)
1172 sheet.visible = true;
1173 sheet.sheetSelected = properties;
1178 MenuItem viewMethodsItem
1180 viewMenu, $"View Methods", m, f4;
1181 bool NotifySelect(MenuItem selection, Modifiers mods)
1183 sheet.visible = true;
1184 sheet.sheetSelected = methods;
1189 MenuItem viewToolBoxItem
1191 viewMenu, $"View Toolbox", x, f12;
1192 bool NotifySelect(MenuItem selection, Modifiers mods)
1194 toolBox.visible = true;
1199 MenuItem viewOutputItem
1201 viewMenu, $"Output", o, alt2;
1202 bool NotifySelect(MenuItem selection, Modifiers mods)
1208 MenuItem viewWatchesItem
1210 viewMenu, $"Watches", w, alt3;
1211 bool NotifySelect(MenuItem selection, Modifiers mods)
1217 MenuItem viewThreadsItem
1219 viewMenu, $"Threads", t, alt4;
1220 bool NotifySelect(MenuItem selection, Modifiers mods)
1226 MenuItem viewBreakpointsItem
1228 viewMenu, $"Breakpoints", b, alt5;
1229 bool NotifySelect(MenuItem selection, Modifiers mods)
1231 breakpointsView.Show();
1235 MenuItem viewCallStackItem
1237 viewMenu, $"Call Stack", s, alt7;
1238 bool NotifySelect(MenuItem selection, Modifiers mods)
1240 callStackView.Show();
1244 MenuItem viewAllDebugViews
1246 viewMenu, $"All Debug Views", a, alt9;
1247 bool NotifySelect(MenuItem selection, Modifiers mods)
1252 callStackView.Show();
1253 breakpointsView.Show();
1257 #ifdef GDB_DEBUG_GUI
1258 MenuDivider { viewMenu };
1259 MenuItem viewGDBItem
1261 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1262 bool NotifySelect(MenuItem selection, Modifiers mods)
1269 MenuDivider { viewMenu };
1270 MenuItem viewColorPicker
1272 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1273 bool NotifySelect(MenuItem selection, Modifiers mods)
1275 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1276 colorPicker.Create();
1280 MenuDivider { viewMenu };
1284 viewMenu, "Full Screen", f, checkable = true;
1286 bool NotifySelect(MenuItem selection, Modifiers mods)
1288 app.fullScreen ^= true;
1290 anchor = { 0, 0, 0, 0 };
1295 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1296 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1297 Menu windowMenu { menu, $"Window", w };
1298 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1299 MenuDivider { windowMenu };
1300 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1301 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1302 MenuDivider { windowMenu };
1303 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1304 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1305 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1306 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1307 MenuDivider { windowMenu };
1308 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1309 Menu helpMenu { menu, $"Help", h };
1312 helpMenu, $"API Reference", r, f1;
1313 bool NotifySelect(MenuItem selection, Modifiers mods)
1315 Execute("documentor");
1319 MenuDivider { helpMenu };
1322 helpMenu, $"About...", a;
1323 bool NotifySelect(MenuItem selection, Modifiers mods)
1325 AboutIDE { master = this }.Modal();
1330 property ToolBox toolBox
1332 get { return toolBox; }
1335 property Sheet sheet
1337 get { return sheet; }
1340 property Project project
1342 get { return projectView ? projectView.project : null; }
1345 property Workspace workspace
1347 get { return projectView ? projectView.workspace : null; }
1350 FindInFilesDialog findInFilesDialog
1352 master = this, parent = this;
1353 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1357 #ifdef GDB_DEBUG_GUI
1360 master = this, parent = this;
1361 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1363 void OnCommand(char * string)
1366 ide.debugger.SendGDBCommand(string);
1371 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1373 //app.driver = app.drivers[selection.id];
1375 app.driver = selection.id ? "OpenGL" : "X";
1377 app.driver = selection.id ? "OpenGL" : "GDI";
1379 delete ideSettings.displayDriver;
1380 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1382 settingsContainer.Save();
1383 //SetDriverAndSkin();
1387 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1389 app.skin = app.skins[selection.id];
1394 void SetDriverAndSkin()
1397 for(c = 0; c < app.numSkins; c++)
1398 if(!strcmp(app.skins[c], app.skin))
1400 skinItems[c].checked = true;
1403 for(c = 0; c < app.numDrivers; c++)
1404 if(!strcmp(app.drivers[c], app.driver))
1406 driverItems[c].checked = true;
1411 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1413 Project project = workspace.projects.firstIterator.data;
1414 projectView = ProjectView
1417 fileName = fileName;
1419 void NotifyDestroyed(Window window, DialogResult result)
1422 text = titleECEREIDE;
1427 projectView.Create();
1428 RepositionWindows(false);
1430 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1431 projectView.workspace = workspace;
1432 projectView.project = project;
1433 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1437 ide.breakpointsView.LoadFromWorkspace();
1438 ide.watchesView.LoadFromWorkspace();
1440 findInFilesDialog.projectNodeField.userData = projectView;
1443 char fileName[MAX_LOCATION];
1444 strcpy(fileName, project.topNode.path);
1445 PathCat(fileName, project.topNode.name);
1450 bool GetDebugMenusDisabled()
1454 Project project = projectView.project;
1456 if(project.GetTargetType(project.config) == executable)
1463 void RepositionWindows(bool expand)
1468 bool inDebugMode = debugger.isActive;
1469 bool callStackVisible = expand ? false : callStackView.visible;
1470 bool threadsVisible = expand ? false : threadsView.visible;
1471 bool watchesVisible = expand ? false : watchesView.visible;
1472 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1473 bool toolBoxVisible = toolBox.visible;
1474 bool outputVisible = expand ? false : outputView.visible;
1475 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1476 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1478 for(child = firstChild; child; child = child.next)
1480 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1481 child._class == class(Sheet) || child._class == class(ProjectView))
1483 Anchor anchor = child.anchor;
1484 anchor.top = topDistance;
1485 anchor.bottom = bottomDistance;
1486 if(child._class == class(CodeEditor) || child._class == class(Designer))
1488 anchor.right = toolBoxVisible ? 150 : 0;
1490 child.anchor = anchor;
1494 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1495 child._class == class(BreakpointsView))
1496 child.visible = false;
1499 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1504 bool ShowCodeEditor()
1507 activeClient.Activate();
1508 else if(projectView)
1510 projectView.visible = true;
1511 projectView.Activate();
1515 sheet.visible = true;
1521 bool ShouldStopBuild()
1523 return projectView.stopBuild;
1526 void DocumentSaved(Window document, char * fileName)
1528 ideSettings.AddRecentFile(fileName);
1529 ide.UpdateRecentMenus();
1530 ide.AdjustFileMenus();
1531 settingsContainer.Save();
1534 bool Window::OnFileModified(FileChange fileChange, char * param)
1537 sprintf(temp, $"The document %s was modified by another application.\n"
1538 "Would you like to reload it and lose your changes?", this.fileName);
1539 if(MessageBox { type = yesNo, master = this/*.parent*/,
1540 text = $"Document has been modified", contents = temp }.Modal() == yes)
1542 char * fileName = CopyString(this.fileName);
1543 WindowState state = this.state;
1544 Anchor anchor = this.anchor;
1545 Size size = this.size;
1547 this.modifiedDocument = false;
1549 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1552 this.anchor = anchor;
1554 this.SetState(state, true, 0);
1562 void UpdateMakefiles()
1566 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1567 for(prj : workspace.projects)
1568 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1573 void UpdateCompilerConfigs()
1577 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1578 projectView.ShowOutputBuildLog(true);
1579 projectView.DisplayCompiler(compiler, false);
1580 for(prj : workspace.projects)
1581 projectView.ProjectPrepareCompiler(prj, compiler);
1588 bool unavailable = !project;
1590 projectAddItem.disabled = unavailable;
1591 toolBar.buttonAddProject.disabled = unavailable;
1593 activeCompilerItem.disabled = unavailable;
1594 projectActiveConfigItem.disabled = unavailable;
1595 projectSettingsItem.disabled = unavailable;
1597 projectBrowseFolderItem.disabled = unavailable;
1599 viewProjectItem.disabled = unavailable;
1606 property bool hasOpenedCodeEditors
1611 for(w = firstChild; w; w = w.next)
1612 if(w._class == class(CodeEditor) &&
1613 w.isDocument && !w.closing && w.visible && w.created &&
1614 w.fileName && w.fileName[0])
1620 void AdjustFileMenus()
1622 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1624 projectQuickItem.disabled = unavailable;
1627 void AdjustBuildMenus()
1629 bool unavailable = project && projectView.buildInProgress;
1631 projectNewItem.disabled = unavailable;
1632 toolBar.buttonNewProject.disabled = unavailable;
1633 projectOpenItem.disabled = unavailable;
1634 toolBar.buttonOpenProject.disabled = unavailable;
1636 unavailable = !project || projectView.buildInProgress;
1638 projectCloseItem.disabled = unavailable;
1639 // toolBar.buttonCloseProject.disabled = unavailable;
1641 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1642 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1643 projectBuildItem.disabled = unavailable;
1644 toolBar.buttonBuild.disabled = unavailable;
1645 projectLinkItem.disabled = unavailable;
1646 toolBar.buttonReLink.disabled = unavailable;
1647 projectRebuildItem.disabled = unavailable;
1648 toolBar.buttonRebuild.disabled = unavailable;
1649 projectCleanItem.disabled = unavailable;
1650 toolBar.buttonClean.disabled = unavailable;
1651 projectRealCleanItem.disabled = unavailable;
1652 // toolBar.buttonRealClean.disabled = unavailable;
1653 projectRegenerateItem.disabled = unavailable;
1654 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1655 projectCompileItem.disabled = unavailable;
1657 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1660 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); if(menu) menu.disabled = unavailable;
1661 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1662 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1663 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1664 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1665 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1666 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
1667 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
1668 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
1669 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
1670 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
1671 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
1672 projectView.popupMenu.Update(null);
1676 void AdjustDebugMenus()
1678 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1679 projectView.buildInProgress == buildingMainProject;
1680 bool active = ide.debugger.isActive;
1681 bool executing = ide.debugger.state == running;
1682 //bool holding = ide.debugger.state == stopped;
1684 debugStartResumeItem.disabled = unavailable || executing;
1685 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1686 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1689 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1690 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1693 debugBreakItem.disabled = unavailable || !executing;
1694 debugStopItem.disabled = unavailable || !active;
1695 debugRestartItem.disabled = unavailable || !active;
1698 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1699 toolBar.buttonDebugStop.disabled = unavailable || !active;
1700 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1703 debugStepIntoItem.disabled = unavailable || executing;
1704 debugStepOverItem.disabled = unavailable || executing;
1705 debugStepOutItem.disabled = unavailable || executing || !active;
1706 debugSkipStepOverItem.disabled = unavailable || executing;
1707 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1710 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1711 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1712 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1713 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1714 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1716 if((Designer)GetActiveDesigner())
1718 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1721 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1722 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1727 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1729 char tempString[MAX_LOCATION];
1730 strcpy(tempString, directory);
1731 if(saveSettings && !projectView)
1733 ideSettings.ideFileDialogLocation = directory;
1734 settingsContainer.Save();
1737 ideFileDialog.currentDirectory = tempString;
1738 codeEditorFileDialog.currentDirectory = tempString;
1739 codeEditorFormFileDialog.currentDirectory = tempString;
1742 void ChangeProjectFileDialogDirectory(char * directory)
1744 ideSettings.ideProjectFileDialogLocation = directory;
1745 settingsContainer.Save();
1748 Window FindWindow(char * filePath)
1750 Window document = null;
1752 // TOCHECK: Do we need to change slashes here?
1753 for(document = firstChild; document; document = document.next)
1755 char * fileName = document.fileName;
1756 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1758 document.visible = true;
1759 document.Activate();
1766 bool DontTerminateDebugSession(char * title)
1768 if(debugger.isActive)
1770 if(MessageBox { type = yesNo, master = ide,
1771 contents = $"Do you want to terminate the debugging session in progress?",
1772 text = title }.Modal() == no)
1775 MessageBox msg { type = yesNo, master = ide,
1776 contents = "Do you want to terminate the debugging session in progress?",
1778 if(msg.Modal() == no)
1790 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1792 char extension[MAX_EXTENSION] = "";
1793 Window document = null;
1794 bool isProject = false;
1795 bool needFileModified = true;
1796 char winFilePath[MAX_LOCATION];
1797 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1801 GetExtension(filePath, extension);
1805 strcpy(extension, type);
1807 if(strcmp(extension, ProjectExtension))
1809 for(document = firstChild; document; document = document.next)
1811 char * fileName = document.fileName;
1812 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1814 document.visible = true;
1816 document.Activate();
1822 if(createIfFails == whatever)
1824 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1826 needFileModified = false;
1827 if(openMethod == normal)
1829 if(DontTerminateDebugSession($"Open Project"))
1832 if(MenuWindowCloseAll(null, 0))
1836 projectView.visible = false;
1837 projectView.Destroy(0);
1838 // Where did this come from? projectView = null;
1845 Workspace workspace = null;
1847 if(FileExists(filePath))
1849 if(!strcmp(extension, ProjectExtension))
1851 char workspaceFile[MAX_LOCATION];
1852 strcpy(workspaceFile, filePath);
1853 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1854 workspace = LoadWorkspace(workspaceFile, filePath);
1856 else if(!strcmp(extension, WorkspaceExtension))
1857 workspace = LoadWorkspace(filePath, null);
1860 //project = LoadProject(filePath, null);
1865 char absolutePath[MAX_LOCATION];
1866 CreateProjectView(workspace, filePath);
1867 document = projectView;
1869 workspace.DropInvalidBreakpoints();
1872 ide.projectView.ShowOutputBuildLog(true);
1874 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1875 ide.projectView.DisplayCompiler(compiler, false);
1878 UpdateCompilerConfigs();
1881 char newWorkingDir[MAX_LOCATION];
1882 StripLastDirectory(filePath, newWorkingDir);
1883 ChangeFileDialogsDirectory(newWorkingDir, false);
1886 document.fileName = filePath;
1888 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1890 // this crashes on starting ide with epj file, solution please?
1891 // app.UpdateDisplay();
1893 workspace.holdTracking = true;
1894 for(ofi : workspace.openedFiles)
1896 if(ofi.state != closed)
1898 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1901 char fileName[MAX_LOCATION];
1903 GetLastDirectory(ofi.path, fileName);
1904 node = projectView.project.topNode.Find(fileName, true);
1906 node.EnsureVisible();
1910 workspace.holdTracking = false;
1912 workspace.timer.Start();
1914 findInFilesDialog.mode = FindInFilesMode::project;
1915 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1918 char location[MAX_LOCATION];
1919 StripLastDirectory(ide.project.topNode.path, location);
1920 ChangeProjectFileDialogDirectory(location);
1924 if(projectView.debugger)
1925 projectView.debugger.EvaluateWatches();
1932 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1934 ideProjectFileDialog.text = openProjectFileDialogTitle;
1935 if(ideProjectFileDialog.Modal() == cancel)
1937 filePath = ideProjectFileDialog.filePath;
1938 GetExtension(filePath, extension);
1949 else if(openMethod == add)
1954 char slashFilePath[MAX_LOCATION];
1955 GetSlashPathBuffer(slashFilePath, filePath);
1956 for(p : workspace.projects)
1958 if(!fstrcmp(p.filePath, slashFilePath))
1966 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1967 contents = $"This project is already present in workspace." }.Modal();
1971 prj = LoadProject(filePath, null);
1974 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1975 prj.StartMonitoring();
1976 workspace.projects.Add(prj);
1978 projectView.AddNode(prj.topNode, null);
1979 workspace.modified = true;
1981 findInFilesDialog.AddProjectItem(prj);
1982 projectView.ShowOutputBuildLog(true);
1983 projectView.DisplayCompiler(compiler, false);
1984 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1988 char location[MAX_LOCATION];
1989 StripLastDirectory(prj.topNode.path, location);
1990 ChangeProjectFileDialogDirectory(location);
1993 // projectView is associated with the main project and not with the one just added but
1994 return projectView; // just to let the caller know something was opened
2002 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2003 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2004 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2006 if(FileExists(filePath))
2007 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2008 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2009 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2012 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2015 else if(!strcmp(extension, "3ds"))
2017 if(FileExists(filePath))
2018 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2019 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2020 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2024 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2027 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2028 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2029 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2030 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2031 !strcmp(extension, "js"))
2033 CodeEditor editor { parent = this, state = state, visible = false };
2034 editor.updatingCode = true;
2035 if(editor.LoadFile(filePath))
2038 editor.visible = true;
2042 needFileModified = false;
2046 CodeEditor editor { parent = this, state = state, visible = false };
2047 if(editor.LoadFile(filePath))
2050 editor.visible = true;
2054 needFileModified = false;
2057 if(document && (document._class == class(PictureEdit) ||
2058 document._class == class(ModelView)))
2063 document.fileName = filePath;
2064 if(workspace && !workspace.holdTracking)
2065 workspace.UpdateOpenedFileInfo(filePath, opened);
2069 if(!document && createIfFails != no)
2071 if(createIfFails != yes && !needFileModified &&
2072 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2073 createIfFails = yes;
2074 if(createIfFails == yes || createIfFails == whatever)
2076 document = (Window)NewCodeEditor(this, state, true);
2078 document.fileName = filePath;
2084 if(projectView && document._class == class(CodeEditor) && workspace)
2086 int lineNumber, position;
2088 CodeEditor editor = (CodeEditor)document;
2089 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2090 editor.openedFileInfo.holdTracking = true;
2091 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2092 position = Max(editor.openedFileInfo.position - 1, 0);
2093 editor.editBox.GoToLineNum(lineNumber);
2094 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2095 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2096 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2097 editor.editBox.scroll = scroll;
2098 editor.openedFileInfo.holdTracking = false;
2101 if(needFileModified)
2102 document.OnFileModified = OnFileModified;
2103 document.NotifySaved = DocumentSaved;
2106 ideSettings.AddRecentProject(document.fileName);
2108 ideSettings.AddRecentFile(document.fileName);
2109 ide.UpdateRecentMenus();
2110 ide.AdjustFileMenus();
2111 settingsContainer.Save();
2119 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2120 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2122 if(!parentClosing && ide.workspace)
2123 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2126 bool ModelView::ModelViewOnClose(bool parentClosing)
2128 if(!parentClosing && ide.workspace)
2129 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2132 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2134 if(!parentClosing && ide.workspace)
2135 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2140 void OnUnloadGraphics(Window window)
2142 display.ClearMaterials();
2143 display.ClearTextures();
2144 display.ClearMeshes();
2148 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2150 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2151 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2155 bool OnKeyDown(Key key, unichar ch)
2160 projectView.Update(null);
2163 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2166 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2172 void GoToError(const char * line)
2175 projectView.GoToError(line);
2178 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2181 char *colon = strchr(text, ':');
2182 char filePath[MAX_LOCATION];
2183 char completePath[MAX_LOCATION];
2184 int line = 0, col = 0;
2189 char * close = strchr(text, ')');
2193 strncpy(name, &text[4], close - text - 4);
2194 name[close - text - 4] = '\0';
2195 for(p : ide.workspace.projects)
2197 if(!strcmp(p.name, name))
2207 prj = project ? project : (dir ? null : ide.project);
2208 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2210 path = (colon - 1 > path) ? colon - 1 : path;
2211 colon = strstr(colon + 1, ":");
2213 while(isspace(*path)) path++;
2216 strncpy(filePath, path, colon - path);
2217 filePath[colon - path] = '\0';
2218 line = atoi(colon + 1);
2219 colon = strstr(colon + 1, ":");
2221 col = atoi(colon + 1);
2223 else if(path - 1 >= path && *(path - 1) == '\"')
2225 colon = strchr(path, '\"');
2228 strncpy(filePath, path, colon - path);
2229 filePath[colon - path] = '\0';
2234 strcpy(completePath, prj.topNode.path);
2235 else if(dir && dir[0])
2236 strcpy(completePath, dir);
2238 completePath[0] = '\0';
2239 PathCat(completePath, filePath);
2241 if(FileExists(completePath).isFile)
2243 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2244 if(codeEditor && line)
2246 EditBox editBox = codeEditor.editBox;
2247 editBox.GoToLineNum(line - 1);
2248 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2253 void OnRedraw(Surface surface)
2255 Bitmap bitmap = back.bitmap;
2257 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2260 void SheetSelected(SheetType sheetSelected)
2262 if(activeChild == sheet)
2264 if(sheetSelected == methods)
2266 viewPropertiesItem.accelerator = f4;
2267 viewPropertiesItem.parent = viewMenu;
2268 viewMethodsItem.parent = null;
2272 viewMethodsItem.accelerator = f4;
2273 viewMethodsItem.parent = viewMenu;
2274 viewPropertiesItem.parent = null;
2279 viewMethodsItem.parent = viewMenu;
2280 viewPropertiesItem.parent = viewMenu;
2281 if(sheetSelected == methods)
2283 viewMethodsItem.accelerator = f4;
2284 viewPropertiesItem.accelerator = 0;
2288 viewMethodsItem.accelerator = 0;
2289 viewPropertiesItem.accelerator = f4;
2294 void OnActivateClient(Window client, Window previous)
2296 //if(!client || client != previous)
2299 if(!client || client != previous)
2302 dataType = previous._class;
2303 if(previous && !strcmp(dataType.name, "CodeEditor"))
2305 ((CodeEditor)previous).UpdateFormCode();
2307 else if(previous && !strcmp(dataType.name, "Designer"))
2309 ((Designer)previous).codeEditor.UpdateFormCode();
2314 dataType = client._class;
2315 if(client && !strcmp(dataType.name, "CodeEditor"))
2317 CodeEditor codeEditor = (CodeEditor)client;
2318 SetPrivateModule(codeEditor.privateModule);
2319 SetCurrentContext(codeEditor.globalContext);
2320 SetTopContext(codeEditor.globalContext);
2321 SetGlobalContext(codeEditor.globalContext);
2323 SetDefines(&codeEditor.defines);
2324 SetImports(&codeEditor.imports);
2326 SetActiveDesigner(codeEditor.designer);
2328 sheet.codeEditor = codeEditor;
2329 toolBox.codeEditor = codeEditor;
2331 viewDesignerItem.parent = viewMenu;
2332 if(activeChild != codeEditor)
2334 viewCodeItem.parent = viewMenu;
2335 viewDesignerItem.accelerator = 0;
2336 viewCodeItem.accelerator = f8;
2340 viewCodeItem.parent = null;
2341 viewDesignerItem.accelerator = f8;
2344 else if(client && !strcmp(dataType.name, "Designer"))
2346 CodeEditor codeEditor = ((Designer)client).codeEditor;
2349 SetPrivateModule(codeEditor.privateModule);
2350 SetCurrentContext(codeEditor.globalContext);
2351 SetTopContext(codeEditor.globalContext);
2352 SetGlobalContext(codeEditor.globalContext);
2353 SetDefines(&codeEditor.defines);
2354 SetImports(&codeEditor.imports);
2358 SetPrivateModule(null);
2359 SetCurrentContext(null);
2360 SetTopContext(null);
2361 SetGlobalContext(null);
2366 SetActiveDesigner((Designer)client);
2368 sheet.codeEditor = codeEditor;
2369 toolBox.codeEditor = codeEditor;
2371 viewCodeItem.parent = viewMenu;
2372 if(activeChild != client)
2374 viewDesignerItem.parent = viewMenu;
2375 viewDesignerItem.accelerator = f8;
2376 viewCodeItem.accelerator = 0;
2380 viewDesignerItem.parent = null;
2381 viewCodeItem.accelerator = f8;
2387 sheet.codeEditor = null;
2388 toolBox.codeEditor = null;
2389 SetActiveDesigner(null);
2391 viewDesignerItem.parent = null;
2392 viewCodeItem.parent = null;
2395 SheetSelected(sheet.sheetSelected);
2398 projectCompileItem = null;
2403 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2405 CodeEditor codeEditor = (CodeEditor)client;
2406 EditBox editBox = codeEditor.editBox;
2408 statusBar.AddField(pos);
2410 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2411 statusBar.AddField(caps);
2413 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2414 statusBar.AddField(ovr);
2416 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2417 statusBar.AddField(num);
2419 //statusBar.text = "Ready";
2421 if(projectView && projectView.project)
2423 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2427 sprintf(name, $"Compile %s", node.name);
2428 projectCompileItem =
2430 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2432 bool NotifySelect(MenuItem selection, Modifiers mods)
2436 bool result = false;
2437 ProjectNode node = null;
2438 for(p : ide.workspace.projects)
2440 node = projectView.GetNodeFromWindow(activeClient, p);
2441 //if(node && projectView.Compile(node.project, node, mods.ctrl && mods.shift))
2444 List<ProjectNode> nodes { };
2446 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, normal);
2454 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2459 projectMenu.AddDynamic(projectCompileItem, ide, false);
2465 caps = ovr = num = null;
2470 bool OnClose(bool parentClosing)
2472 //return !projectView.buildInProgress;
2473 if(projectView && projectView.buildInProgress)
2475 if(DontTerminateDebugSession($"Close IDE"))
2477 if(findInFilesDialog)
2478 findInFilesDialog.SearchStop();
2481 workspace.timer.Stop();
2484 ideMainFrame.Destroy(0);
2491 bool passThrough = false;
2492 bool debugStart = false;
2493 DynamicString passArgs { };
2494 for(c = 1; c<app.argc; c++)
2496 if(!strcmp(app.argv[c], "-debug-start"))
2498 else if(!passThrough && !strcmp(app.argv[c], "-@"))
2500 else if(passThrough)
2502 passArgs.concat(" ");
2503 passArgs.concat(app.argv[c]);
2507 char fullPath[MAX_LOCATION];
2508 char parentPath[MAX_LOCATION];
2509 char ext[MAX_EXTENSION];
2511 FileAttribs dirAttribs;
2512 GetWorkingDir(fullPath, MAX_LOCATION);
2513 PathCat(fullPath, app.argv[c]);
2514 StripLastDirectory(fullPath, parentPath);
2515 GetExtension(app.argv[c], ext);
2516 isProject = !strcmpi(ext, "epj");
2518 if(isProject && c > (debugStart ? 2 : 1)) continue;
2520 // Create directory for projects (only)
2521 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2523 if(isProject && !FileExists(fullPath))
2525 // The NewProject will handle directory creation
2526 /*if(!dirAttribs.isDirectory)
2528 MakeDir(parentPath);
2529 dirAttribs = FileExists(parentPath);
2531 if(dirAttribs.isDirectory)*/
2533 char name[MAX_LOCATION];
2534 NewProjectDialog newProjectDialog;
2538 projectView.visible = false;
2539 if(!projectView.Destroy(0))
2543 newProjectDialog = { master = this };
2545 strcpy(name, app.argv[c]);
2546 StripExtension(name);
2547 GetLastDirectory(name, name);
2548 newProjectDialog.projectName.contents = name;
2549 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2550 newProjectDialog.locationEditBox.path = parentPath;
2551 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2553 newProjectDialog.Modal();
2556 ideSettings.AddRecentProject(projectView.fileName);
2557 ide.UpdateRecentMenus();
2558 settingsContainer.Save();
2561 // Open only one project
2565 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2569 if(passThrough && projectView && projectView.project && workspace)
2570 workspace.commandLineArgs = passArgs;
2573 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
2579 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2582 projectView.visible = false;
2583 projectView.Destroy(0);
2586 #ifdef GDB_DEBUG_GUI
2587 gdbDialog.Destroy(0);
2592 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2596 char * oldPaths[128];
2597 String oldList = new char[maxPathLen];
2598 Array<String> newExePaths { };
2599 //Map<String, bool> exePathExists { };
2601 #if defined(__unix__) || defined(__APPLE__)
2602 Array<String> newLibPaths { };
2603 Map<String, bool> libPathExists { };
2608 for(prj : workspace.projects)
2610 DirExpression targetDirExp;
2612 // SKIP FIRST PROJECT...
2613 if(prj == workspace.projects.firstIterator.data) continue;
2615 // NOTE: Right now the additional project config dir will be
2616 // obtained when the debugger is started, so toggling it
2617 // while building will change which library gets used.
2618 // To go with the initial state, e.g. when F5 was pressed,
2619 // we nould need to keep a list of all project's active
2620 // config upon startup.
2621 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2623 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2627 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2628 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2632 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2633 if(cfg.targetType == sharedLibrary && cfg.debug)
2637 if(targetDirExp.dir)
2639 char buffer[MAX_LOCATION];
2640 #if defined(__WIN32__)
2641 Array<String> paths = newExePaths;
2643 Array<String> paths = newLibPaths;
2645 GetSystemPathBuffer(buffer, prj.topNode.path);
2646 PathCat(buffer, targetDirExp.dir);
2649 if(!fstrcmp(p, buffer))
2656 paths.Add(CopyString(buffer));
2658 delete targetDirExp;
2662 for(item : compiler.executableDirs)
2665 for(p : newExePaths)
2667 if(!fstrcmp(p, item))
2674 newExePaths.Add(CopySystemPath(item));
2677 GetEnvironment("PATH", oldList, maxPathLen);
2679 printf("Old value of PATH: %s\n", oldList);
2681 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2682 for(c = 0; c < count; c++)
2685 for(p : newExePaths)
2687 if(!fstrcmp(p, oldPaths[c]))
2694 newExePaths.Add(CopySystemPath(oldPaths[c]));
2698 for(path : newExePaths)
2699 len += strlen(path) + 1;
2700 newList = new char[len + 1];
2702 for(path : newExePaths)
2704 strcat(newList, path);
2705 strcat(newList, pathListSep);
2707 newList[len - 1] = '\0';
2708 SetEnvironment("PATH", newList);
2710 printf("New value of PATH: %s\n", newList);
2717 #if defined(__unix__) || defined(__APPLE__)
2719 for(item : compiler.libraryDirs)
2721 if(!libPathExists[item]) // fstrcmp should be used
2723 newLibPaths.Add(item);
2724 libPathExists[item] = true;
2728 #if defined(__APPLE__)
2729 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2731 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2734 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2736 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2737 for(c = 0; c < count; c++)
2739 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2741 newLibPaths.Add(oldPaths[c]);
2742 libPathExists[oldPaths[c]] = true;
2747 for(path : newLibPaths)
2748 len += strlen(path) + 1;
2749 newList = new char[len + 1];
2751 for(path : newLibPaths)
2753 strcat(newList, path);
2754 strcat(newList, pathListSep);
2756 newList[len - 1] = '\0';
2757 #if defined(__APPLE__)
2758 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2760 SetEnvironment("LD_LIBRARY_PATH", newList);
2763 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2768 delete libPathExists;
2771 if(compiler.distccEnabled && compiler.distccHosts)
2772 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2777 void DestroyTemporaryProjectDir()
2779 if(tmpPrjDir && tmpPrjDir[0])
2781 if(FileExists(tmpPrjDir).isDirectory)
2782 DestroyDir(tmpPrjDir);
2783 property::tmpPrjDir = null;
2789 // Graphics Driver Menu
2793 app.currentSkin.selectionColor = selectionColor;
2794 app.currentSkin.selectionText = selectionText;
2798 driverItems = new MenuItem[app.numDrivers];
2799 for(c = 0; c < app.numDrivers; c++)
2801 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2802 driverItems[c].id = c;
2803 driverItems[c].isRadio = true;
2806 driverItems = new MenuItem[2];
2807 #if defined(__unix__)
2808 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2809 driverItems[0].id = 0;
2810 driverItems[0].isRadio = true;
2812 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2813 driverItems[0].id = 0;
2814 driverItems[0].isRadio = true;
2816 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2817 driverItems[1].id = 1;
2818 driverItems[1].isRadio = true;
2820 /* skinItems = new MenuItem[app.numSkins];
2821 for(c = 0; c < app.numSkins; c++)
2823 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2824 skinItems[c].id = c;
2825 skinItems[c].isRadio = true;
2828 ideFileDialog.master = this;
2829 ideProjectFileDialog.master = this;
2831 //SetDriverAndSkin();
2835 void UpdateRecentMenus()
2838 Menu fileMenu = menu.FindMenu($"File");
2839 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2840 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2841 char itemName[MAX_LOCATION + 4];
2844 recentFiles.Clear();
2847 for(recent : ideSettings.recentFiles)
2849 sprintf(itemName, "%d %s", 1 + c, recent);
2850 MakeSystemPath(itemName);
2851 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2855 recentProjects.Clear();
2857 for(recent : ideSettings.recentProjects)
2859 sprintf(itemName, "%d %s", 1 + c, recent);
2860 MakeSystemPath(itemName);
2861 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2874 void DestroyDir(char * path)
2876 RecursiveDeleteFolderFSI fsi { };
2881 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2883 bool preserveRootFolder;
2885 void OutFolder(char * folderPath, bool isRoot)
2887 if(!(preserveRootFolder && isRoot))
2888 RemoveDir(folderPath);
2891 bool OnFile(char * filePath)
2893 DeleteFile(filePath);
2898 class IDEApp : GuiApplication
2900 //driver = "Win32Console";
2901 // driver = "OpenGL";
2906 SetLoggingMode(stdOut, null);
2907 //SetLoggingMode(debug, null);
2909 settingsContainer.Load();
2910 #if defined(__unix__) || defined(__APPLE__)
2911 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2913 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2915 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2919 desktop.text = titleECEREIDE;
2922 for(c = 1; c<app.argc; c++)
2924 char fullPath[MAX_LOCATION];
2925 GetWorkingDir(fullPath, MAX_LOCATION);
2926 PathCat(fullPath, app.argv[c]);
2927 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2934 IDEMainFrame ideMainFrame { };
2936 define app = ((IDEApp)__thisModule);
2938 define titleECEREIDE = $"ECERE IDE (Debug)";
2940 define titleECEREIDE = $"ECERE IDE";