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 projectView.popupMenu.Update(null);
1673 void AdjustDebugMenus()
1675 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1676 projectView.buildInProgress == buildingMainProject;
1677 bool active = ide.debugger.isActive;
1678 bool executing = ide.debugger.state == running;
1679 //bool holding = ide.debugger.state == stopped;
1681 debugStartResumeItem.disabled = unavailable || executing;
1682 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1683 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1686 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1687 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1690 debugBreakItem.disabled = unavailable || !executing;
1691 debugStopItem.disabled = unavailable || !active;
1692 debugRestartItem.disabled = unavailable || !active;
1695 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1696 toolBar.buttonDebugStop.disabled = unavailable || !active;
1697 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1700 debugStepIntoItem.disabled = unavailable || executing;
1701 debugStepOverItem.disabled = unavailable || executing;
1702 debugStepOutItem.disabled = unavailable || executing || !active;
1703 debugSkipStepOverItem.disabled = unavailable || executing;
1704 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1707 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1708 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1709 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1710 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1711 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1713 if((Designer)GetActiveDesigner())
1715 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1718 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1719 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1724 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1726 char tempString[MAX_LOCATION];
1727 strcpy(tempString, directory);
1728 if(saveSettings && !projectView)
1730 ideSettings.ideFileDialogLocation = directory;
1731 settingsContainer.Save();
1734 ideFileDialog.currentDirectory = tempString;
1735 codeEditorFileDialog.currentDirectory = tempString;
1736 codeEditorFormFileDialog.currentDirectory = tempString;
1739 void ChangeProjectFileDialogDirectory(char * directory)
1741 ideSettings.ideProjectFileDialogLocation = directory;
1742 settingsContainer.Save();
1745 Window FindWindow(char * filePath)
1747 Window document = null;
1749 // TOCHECK: Do we need to change slashes here?
1750 for(document = firstChild; document; document = document.next)
1752 char * fileName = document.fileName;
1753 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1755 document.visible = true;
1756 document.Activate();
1763 bool DontTerminateDebugSession(char * title)
1765 if(debugger.isActive)
1767 if(MessageBox { type = yesNo, master = ide,
1768 contents = $"Do you want to terminate the debugging session in progress?",
1769 text = title }.Modal() == no)
1772 MessageBox msg { type = yesNo, master = ide,
1773 contents = "Do you want to terminate the debugging session in progress?",
1775 if(msg.Modal() == no)
1787 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1789 char extension[MAX_EXTENSION] = "";
1790 Window document = null;
1791 bool isProject = false;
1792 bool needFileModified = true;
1793 char winFilePath[MAX_LOCATION];
1794 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1798 GetExtension(filePath, extension);
1802 strcpy(extension, type);
1804 if(strcmp(extension, ProjectExtension))
1806 for(document = firstChild; document; document = document.next)
1808 char * fileName = document.fileName;
1809 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1811 document.visible = true;
1813 document.Activate();
1819 if(createIfFails == whatever)
1821 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1823 needFileModified = false;
1824 if(openMethod == normal)
1826 if(DontTerminateDebugSession($"Open Project"))
1829 if(MenuWindowCloseAll(null, 0))
1833 projectView.visible = false;
1834 projectView.Destroy(0);
1835 // Where did this come from? projectView = null;
1842 Workspace workspace = null;
1844 if(FileExists(filePath))
1846 if(!strcmp(extension, ProjectExtension))
1848 char workspaceFile[MAX_LOCATION];
1849 strcpy(workspaceFile, filePath);
1850 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1851 workspace = LoadWorkspace(workspaceFile, filePath);
1853 else if(!strcmp(extension, WorkspaceExtension))
1854 workspace = LoadWorkspace(filePath, null);
1857 //project = LoadProject(filePath, null);
1862 char absolutePath[MAX_LOCATION];
1863 CreateProjectView(workspace, filePath);
1864 document = projectView;
1866 workspace.DropInvalidBreakpoints();
1869 ide.projectView.ShowOutputBuildLog(true);
1871 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1872 ide.projectView.DisplayCompiler(compiler, false);
1875 UpdateCompilerConfigs();
1878 char newWorkingDir[MAX_LOCATION];
1879 StripLastDirectory(filePath, newWorkingDir);
1880 ChangeFileDialogsDirectory(newWorkingDir, false);
1883 document.fileName = filePath;
1885 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1887 // this crashes on starting ide with epj file, solution please?
1888 // app.UpdateDisplay();
1890 workspace.holdTracking = true;
1891 for(ofi : workspace.openedFiles)
1893 if(ofi.state != closed)
1895 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1898 char fileName[MAX_LOCATION];
1900 GetLastDirectory(ofi.path, fileName);
1901 node = projectView.project.topNode.Find(fileName, true);
1903 node.EnsureVisible();
1907 workspace.holdTracking = false;
1909 workspace.timer.Start();
1911 findInFilesDialog.mode = FindInFilesMode::project;
1912 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1915 char location[MAX_LOCATION];
1916 StripLastDirectory(ide.project.topNode.path, location);
1917 ChangeProjectFileDialogDirectory(location);
1921 if(projectView.debugger)
1922 projectView.debugger.EvaluateWatches();
1929 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1931 ideProjectFileDialog.text = openProjectFileDialogTitle;
1932 if(ideProjectFileDialog.Modal() == cancel)
1934 filePath = ideProjectFileDialog.filePath;
1935 GetExtension(filePath, extension);
1946 else if(openMethod == add)
1951 char slashFilePath[MAX_LOCATION];
1952 GetSlashPathBuffer(slashFilePath, filePath);
1953 for(p : workspace.projects)
1955 if(!fstrcmp(p.filePath, slashFilePath))
1963 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1964 contents = $"This project is already present in workspace." }.Modal();
1968 prj = LoadProject(filePath, null);
1971 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1972 prj.StartMonitoring();
1973 workspace.projects.Add(prj);
1975 projectView.AddNode(prj.topNode, null);
1976 workspace.modified = true;
1978 findInFilesDialog.AddProjectItem(prj);
1979 projectView.ShowOutputBuildLog(true);
1980 projectView.DisplayCompiler(compiler, false);
1981 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1985 char location[MAX_LOCATION];
1986 StripLastDirectory(prj.topNode.path, location);
1987 ChangeProjectFileDialogDirectory(location);
1990 // projectView is associated with the main project and not with the one just added but
1991 return projectView; // just to let the caller know something was opened
1999 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2000 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2001 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2003 if(FileExists(filePath))
2004 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2005 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2006 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2009 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2012 else if(!strcmp(extension, "3ds"))
2014 if(FileExists(filePath))
2015 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2016 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2017 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2021 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2024 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2025 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2026 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2027 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2028 !strcmp(extension, "js"))
2030 CodeEditor editor { parent = this, state = state, visible = false };
2031 editor.updatingCode = true;
2032 if(editor.LoadFile(filePath))
2035 editor.visible = true;
2039 needFileModified = false;
2043 CodeEditor editor { parent = this, state = state, visible = false };
2044 if(editor.LoadFile(filePath))
2047 editor.visible = true;
2051 needFileModified = false;
2054 if(document && (document._class == class(PictureEdit) ||
2055 document._class == class(ModelView)))
2060 document.fileName = filePath;
2061 if(workspace && !workspace.holdTracking)
2062 workspace.UpdateOpenedFileInfo(filePath, opened);
2066 if(!document && createIfFails != no)
2068 if(createIfFails != yes && !needFileModified &&
2069 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2070 createIfFails = yes;
2071 if(createIfFails == yes || createIfFails == whatever)
2073 document = (Window)NewCodeEditor(this, state, true);
2075 document.fileName = filePath;
2081 if(projectView && document._class == class(CodeEditor) && workspace)
2083 int lineNumber, position;
2085 CodeEditor editor = (CodeEditor)document;
2086 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2087 editor.openedFileInfo.holdTracking = true;
2088 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2089 position = Max(editor.openedFileInfo.position - 1, 0);
2090 editor.editBox.GoToLineNum(lineNumber);
2091 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2092 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2093 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2094 editor.editBox.scroll = scroll;
2095 editor.openedFileInfo.holdTracking = false;
2098 if(needFileModified)
2099 document.OnFileModified = OnFileModified;
2100 document.NotifySaved = DocumentSaved;
2103 ideSettings.AddRecentProject(document.fileName);
2105 ideSettings.AddRecentFile(document.fileName);
2106 ide.UpdateRecentMenus();
2107 ide.AdjustFileMenus();
2108 settingsContainer.Save();
2116 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2117 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2119 if(!parentClosing && ide.workspace)
2120 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2123 bool ModelView::ModelViewOnClose(bool parentClosing)
2125 if(!parentClosing && ide.workspace)
2126 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2129 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2131 if(!parentClosing && ide.workspace)
2132 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2137 void OnUnloadGraphics(Window window)
2139 display.ClearMaterials();
2140 display.ClearTextures();
2141 display.ClearMeshes();
2145 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2147 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2148 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2152 bool OnKeyDown(Key key, unichar ch)
2157 projectView.Update(null);
2160 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2163 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2169 void GoToError(const char * line)
2172 projectView.GoToError(line);
2175 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2178 char *colon = strchr(text, ':');
2179 char filePath[MAX_LOCATION];
2180 char completePath[MAX_LOCATION];
2181 int line = 0, col = 0;
2186 char * close = strchr(text, ')');
2190 strncpy(name, &text[4], close - text - 4);
2191 name[close - text - 4] = '\0';
2192 for(p : ide.workspace.projects)
2194 if(!strcmp(p.name, name))
2204 prj = project ? project : (dir ? null : ide.project);
2205 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2207 path = (colon - 1 > path) ? colon - 1 : path;
2208 colon = strstr(colon + 1, ":");
2210 while(isspace(*path)) path++;
2213 strncpy(filePath, path, colon - path);
2214 filePath[colon - path] = '\0';
2215 line = atoi(colon + 1);
2216 colon = strstr(colon + 1, ":");
2218 col = atoi(colon + 1);
2220 else if(path - 1 >= path && *(path - 1) == '\"')
2222 colon = strchr(path, '\"');
2225 strncpy(filePath, path, colon - path);
2226 filePath[colon - path] = '\0';
2231 strcpy(completePath, prj.topNode.path);
2232 else if(dir && dir[0])
2233 strcpy(completePath, dir);
2235 completePath[0] = '\0';
2236 PathCat(completePath, filePath);
2238 if(FileExists(completePath).isFile)
2240 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2241 if(codeEditor && line)
2243 EditBox editBox = codeEditor.editBox;
2244 editBox.GoToLineNum(line - 1);
2245 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2250 void OnRedraw(Surface surface)
2252 Bitmap bitmap = back.bitmap;
2254 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2257 void SheetSelected(SheetType sheetSelected)
2259 if(activeChild == sheet)
2261 if(sheetSelected == methods)
2263 viewPropertiesItem.accelerator = f4;
2264 viewPropertiesItem.parent = viewMenu;
2265 viewMethodsItem.parent = null;
2269 viewMethodsItem.accelerator = f4;
2270 viewMethodsItem.parent = viewMenu;
2271 viewPropertiesItem.parent = null;
2276 viewMethodsItem.parent = viewMenu;
2277 viewPropertiesItem.parent = viewMenu;
2278 if(sheetSelected == methods)
2280 viewMethodsItem.accelerator = f4;
2281 viewPropertiesItem.accelerator = 0;
2285 viewMethodsItem.accelerator = 0;
2286 viewPropertiesItem.accelerator = f4;
2291 void OnActivateClient(Window client, Window previous)
2293 //if(!client || client != previous)
2296 if(!client || client != previous)
2299 dataType = previous._class;
2300 if(previous && !strcmp(dataType.name, "CodeEditor"))
2302 ((CodeEditor)previous).UpdateFormCode();
2304 else if(previous && !strcmp(dataType.name, "Designer"))
2306 ((Designer)previous).codeEditor.UpdateFormCode();
2311 dataType = client._class;
2312 if(client && !strcmp(dataType.name, "CodeEditor"))
2314 CodeEditor codeEditor = (CodeEditor)client;
2315 SetPrivateModule(codeEditor.privateModule);
2316 SetCurrentContext(codeEditor.globalContext);
2317 SetTopContext(codeEditor.globalContext);
2318 SetGlobalContext(codeEditor.globalContext);
2320 SetDefines(&codeEditor.defines);
2321 SetImports(&codeEditor.imports);
2323 SetActiveDesigner(codeEditor.designer);
2325 sheet.codeEditor = codeEditor;
2326 toolBox.codeEditor = codeEditor;
2328 viewDesignerItem.parent = viewMenu;
2329 if(activeChild != codeEditor)
2331 viewCodeItem.parent = viewMenu;
2332 viewDesignerItem.accelerator = 0;
2333 viewCodeItem.accelerator = f8;
2337 viewCodeItem.parent = null;
2338 viewDesignerItem.accelerator = f8;
2341 else if(client && !strcmp(dataType.name, "Designer"))
2343 CodeEditor codeEditor = ((Designer)client).codeEditor;
2346 SetPrivateModule(codeEditor.privateModule);
2347 SetCurrentContext(codeEditor.globalContext);
2348 SetTopContext(codeEditor.globalContext);
2349 SetGlobalContext(codeEditor.globalContext);
2350 SetDefines(&codeEditor.defines);
2351 SetImports(&codeEditor.imports);
2355 SetPrivateModule(null);
2356 SetCurrentContext(null);
2357 SetTopContext(null);
2358 SetGlobalContext(null);
2363 SetActiveDesigner((Designer)client);
2365 sheet.codeEditor = codeEditor;
2366 toolBox.codeEditor = codeEditor;
2368 viewCodeItem.parent = viewMenu;
2369 if(activeChild != client)
2371 viewDesignerItem.parent = viewMenu;
2372 viewDesignerItem.accelerator = f8;
2373 viewCodeItem.accelerator = 0;
2377 viewDesignerItem.parent = null;
2378 viewCodeItem.accelerator = f8;
2384 sheet.codeEditor = null;
2385 toolBox.codeEditor = null;
2386 SetActiveDesigner(null);
2388 viewDesignerItem.parent = null;
2389 viewCodeItem.parent = null;
2392 SheetSelected(sheet.sheetSelected);
2395 projectCompileItem = null;
2400 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2402 CodeEditor codeEditor = (CodeEditor)client;
2403 EditBox editBox = codeEditor.editBox;
2405 statusBar.AddField(pos);
2407 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2408 statusBar.AddField(caps);
2410 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2411 statusBar.AddField(ovr);
2413 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2414 statusBar.AddField(num);
2416 //statusBar.text = "Ready";
2418 if(projectView && projectView.project)
2420 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2424 sprintf(name, $"Compile %s", node.name);
2425 projectCompileItem =
2427 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2429 bool NotifySelect(MenuItem selection, Modifiers mods)
2433 bool result = false;
2434 ProjectNode node = null;
2435 for(p : ide.workspace.projects)
2437 node = projectView.GetNodeFromWindow(activeClient, p);
2438 if(node && projectView.Compile(node, mods.ctrl && mods.shift))
2445 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2450 projectMenu.AddDynamic(projectCompileItem, ide, false);
2456 caps = ovr = num = null;
2461 bool OnClose(bool parentClosing)
2463 //return !projectView.buildInProgress;
2464 if(projectView && projectView.buildInProgress)
2466 if(DontTerminateDebugSession($"Close IDE"))
2468 if(findInFilesDialog)
2469 findInFilesDialog.SearchStop();
2472 workspace.timer.Stop();
2475 ideMainFrame.Destroy(0);
2482 for(c = 1; c<app.argc; c++)
2484 char fullPath[MAX_LOCATION];
2485 char parentPath[MAX_LOCATION];
2486 char ext[MAX_EXTENSION];
2488 FileAttribs dirAttribs;
2489 GetWorkingDir(fullPath, MAX_LOCATION);
2490 PathCat(fullPath, app.argv[c]);
2491 StripLastDirectory(fullPath, parentPath);
2492 GetExtension(app.argv[c], ext);
2493 isProject = !strcmpi(ext, "epj");
2495 if(isProject && c > 1) continue;
2497 // Create directory for projects (only)
2498 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2500 if(isProject && !FileExists(fullPath))
2502 // The NewProject will handle directory creation
2503 /*if(!dirAttribs.isDirectory)
2505 MakeDir(parentPath);
2506 dirAttribs = FileExists(parentPath);
2508 if(dirAttribs.isDirectory)*/
2510 char name[MAX_LOCATION];
2511 NewProjectDialog newProjectDialog;
2515 projectView.visible = false;
2516 if(!projectView.Destroy(0))
2520 newProjectDialog = { master = this };
2522 strcpy(name, app.argv[c]);
2523 StripExtension(name);
2524 GetLastDirectory(name, name);
2525 newProjectDialog.projectName.contents = name;
2526 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2527 newProjectDialog.locationEditBox.path = parentPath;
2528 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2530 newProjectDialog.Modal();
2533 ideSettings.AddRecentProject(projectView.fileName);
2534 ide.UpdateRecentMenus();
2535 settingsContainer.Save();
2538 // Open only one project
2542 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2550 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2553 projectView.visible = false;
2554 projectView.Destroy(0);
2557 #ifdef GDB_DEBUG_GUI
2558 gdbDialog.Destroy(0);
2563 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2567 char * oldPaths[128];
2568 String oldList = new char[maxPathLen];
2569 Array<String> newExePaths { };
2570 //Map<String, bool> exePathExists { };
2572 #if defined(__unix__) || defined(__APPLE__)
2573 Array<String> newLibPaths { };
2574 Map<String, bool> libPathExists { };
2579 for(prj : workspace.projects)
2581 DirExpression targetDirExp;
2583 // SKIP FIRST PROJECT...
2584 if(prj == workspace.projects.firstIterator.data) continue;
2586 // NOTE: Right now the additional project config dir will be
2587 // obtained when the debugger is started, so toggling it
2588 // while building will change which library gets used.
2589 // To go with the initial state, e.g. when F5 was pressed,
2590 // we nould need to keep a list of all project's active
2591 // config upon startup.
2592 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2594 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2598 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2599 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2603 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2604 if(cfg.targetType == sharedLibrary && cfg.debug)
2608 if(targetDirExp.dir)
2610 char buffer[MAX_LOCATION];
2611 #if defined(__WIN32__)
2612 Array<String> paths = newExePaths;
2614 Array<String> paths = newLibPaths;
2616 GetSystemPathBuffer(buffer, prj.topNode.path);
2617 PathCat(buffer, targetDirExp.dir);
2620 if(!fstrcmp(p, buffer))
2627 paths.Add(CopyString(buffer));
2629 delete targetDirExp;
2633 for(item : compiler.executableDirs)
2636 for(p : newExePaths)
2638 if(!fstrcmp(p, item))
2645 newExePaths.Add(CopySystemPath(item));
2648 GetEnvironment("PATH", oldList, maxPathLen);
2650 printf("Old value of PATH: %s\n", oldList);
2652 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2653 for(c = 0; c < count; c++)
2656 for(p : newExePaths)
2658 if(!fstrcmp(p, oldPaths[c]))
2665 newExePaths.Add(CopySystemPath(oldPaths[c]));
2669 for(path : newExePaths)
2670 len += strlen(path) + 1;
2671 newList = new char[len + 1];
2673 for(path : newExePaths)
2675 strcat(newList, path);
2676 strcat(newList, pathListSep);
2678 newList[len - 1] = '\0';
2679 SetEnvironment("PATH", newList);
2681 printf("New value of PATH: %s\n", newList);
2688 #if defined(__unix__) || defined(__APPLE__)
2690 for(item : compiler.libraryDirs)
2692 if(!libPathExists[item]) // fstrcmp should be used
2694 newLibPaths.Add(item);
2695 libPathExists[item] = true;
2699 #if defined(__APPLE__)
2700 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2702 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2705 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2707 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2708 for(c = 0; c < count; c++)
2710 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2712 newLibPaths.Add(oldPaths[c]);
2713 libPathExists[oldPaths[c]] = true;
2718 for(path : newLibPaths)
2719 len += strlen(path) + 1;
2720 newList = new char[len + 1];
2722 for(path : newLibPaths)
2724 strcat(newList, path);
2725 strcat(newList, pathListSep);
2727 newList[len - 1] = '\0';
2728 #if defined(__APPLE__)
2729 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2731 SetEnvironment("LD_LIBRARY_PATH", newList);
2734 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2739 delete libPathExists;
2742 if(compiler.distccEnabled && compiler.distccHosts)
2743 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2748 void DestroyTemporaryProjectDir()
2750 if(tmpPrjDir && tmpPrjDir[0])
2752 if(FileExists(tmpPrjDir).isDirectory)
2753 DestroyDir(tmpPrjDir);
2754 property::tmpPrjDir = null;
2760 // Graphics Driver Menu
2764 app.currentSkin.selectionColor = selectionColor;
2765 app.currentSkin.selectionText = selectionText;
2769 driverItems = new MenuItem[app.numDrivers];
2770 for(c = 0; c < app.numDrivers; c++)
2772 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2773 driverItems[c].id = c;
2774 driverItems[c].isRadio = true;
2777 driverItems = new MenuItem[2];
2778 #if defined(__unix__)
2779 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2780 driverItems[0].id = 0;
2781 driverItems[0].isRadio = true;
2783 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2784 driverItems[0].id = 0;
2785 driverItems[0].isRadio = true;
2787 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2788 driverItems[1].id = 1;
2789 driverItems[1].isRadio = true;
2791 /* skinItems = new MenuItem[app.numSkins];
2792 for(c = 0; c < app.numSkins; c++)
2794 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2795 skinItems[c].id = c;
2796 skinItems[c].isRadio = true;
2799 ideFileDialog.master = this;
2800 ideProjectFileDialog.master = this;
2802 //SetDriverAndSkin();
2806 void UpdateRecentMenus()
2809 Menu fileMenu = menu.FindMenu($"File");
2810 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2811 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2812 char itemName[MAX_LOCATION + 4];
2815 recentFiles.Clear();
2818 for(recent : ideSettings.recentFiles)
2820 sprintf(itemName, "%d %s", 1 + c, recent);
2821 MakeSystemPath(itemName);
2822 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2826 recentProjects.Clear();
2828 for(recent : ideSettings.recentProjects)
2830 sprintf(itemName, "%d %s", 1 + c, recent);
2831 MakeSystemPath(itemName);
2832 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2845 void DestroyDir(char * path)
2847 RecursiveDeleteFolderFSI fsi { };
2852 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2854 bool preserveRootFolder;
2856 void OutFolder(char * folderPath, bool isRoot)
2858 if(!(preserveRootFolder && isRoot))
2859 RemoveDir(folderPath);
2862 bool OnFile(char * filePath)
2864 DeleteFile(filePath);
2869 class IDEApp : GuiApplication
2871 //driver = "Win32Console";
2872 // driver = "OpenGL";
2877 SetLoggingMode(stdOut, null);
2878 //SetLoggingMode(debug, null);
2880 settingsContainer.Load();
2881 #if defined(__unix__) || defined(__APPLE__)
2882 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2884 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2886 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2890 desktop.text = titleECEREIDE;
2893 for(c = 1; c<app.argc; c++)
2895 char fullPath[MAX_LOCATION];
2896 GetWorkingDir(fullPath, MAX_LOCATION);
2897 PathCat(fullPath, app.argv[c]);
2898 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2905 IDEMainFrame ideMainFrame { };
2907 define app = ((IDEApp)__thisModule);
2909 define titleECEREIDE = $"ECERE IDE (Debug)";
2911 define titleECEREIDE = $"ECERE IDE";