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::FileCompile, 0); if(menu) menu.disabled = unavailable;
1667 projectView.popupMenu.Update(null);
1671 void AdjustDebugMenus()
1673 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1674 projectView.buildInProgress == buildingMainProject;
1675 bool active = ide.debugger.isActive;
1676 bool executing = ide.debugger.state == running;
1677 //bool holding = ide.debugger.state == stopped;
1679 debugStartResumeItem.disabled = unavailable || executing;
1680 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1681 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1684 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1685 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1688 debugBreakItem.disabled = unavailable || !executing;
1689 debugStopItem.disabled = unavailable || !active;
1690 debugRestartItem.disabled = unavailable || !active;
1693 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1694 toolBar.buttonDebugStop.disabled = unavailable || !active;
1695 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1698 debugStepIntoItem.disabled = unavailable || executing;
1699 debugStepOverItem.disabled = unavailable || executing;
1700 debugStepOutItem.disabled = unavailable || executing || !active;
1701 debugSkipStepOverItem.disabled = unavailable || executing;
1702 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1705 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1706 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1707 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1708 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1709 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1711 if((Designer)GetActiveDesigner())
1713 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1716 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1717 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1722 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1724 char tempString[MAX_LOCATION];
1725 strcpy(tempString, directory);
1726 if(saveSettings && !projectView)
1728 ideSettings.ideFileDialogLocation = directory;
1729 settingsContainer.Save();
1732 ideFileDialog.currentDirectory = tempString;
1733 codeEditorFileDialog.currentDirectory = tempString;
1734 codeEditorFormFileDialog.currentDirectory = tempString;
1737 void ChangeProjectFileDialogDirectory(char * directory)
1739 ideSettings.ideProjectFileDialogLocation = directory;
1740 settingsContainer.Save();
1743 Window FindWindow(char * filePath)
1745 Window document = null;
1747 // TOCHECK: Do we need to change slashes here?
1748 for(document = firstChild; document; document = document.next)
1750 char * fileName = document.fileName;
1751 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1753 document.visible = true;
1754 document.Activate();
1761 bool DontTerminateDebugSession(char * title)
1763 if(debugger.isActive)
1765 if(MessageBox { type = yesNo, master = ide,
1766 contents = $"Do you want to terminate the debugging session in progress?",
1767 text = title }.Modal() == no)
1770 MessageBox msg { type = yesNo, master = ide,
1771 contents = "Do you want to terminate the debugging session in progress?",
1773 if(msg.Modal() == no)
1785 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1787 char extension[MAX_EXTENSION] = "";
1788 Window document = null;
1789 bool isProject = false;
1790 bool needFileModified = true;
1791 char winFilePath[MAX_LOCATION];
1792 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1796 GetExtension(filePath, extension);
1800 strcpy(extension, type);
1802 if(strcmp(extension, ProjectExtension))
1804 for(document = firstChild; document; document = document.next)
1806 char * fileName = document.fileName;
1807 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1809 document.visible = true;
1811 document.Activate();
1817 if(createIfFails == whatever)
1819 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1821 needFileModified = false;
1822 if(openMethod == normal)
1824 if(DontTerminateDebugSession($"Open Project"))
1827 if(MenuWindowCloseAll(null, 0))
1831 projectView.visible = false;
1832 projectView.Destroy(0);
1833 // Where did this come from? projectView = null;
1840 Workspace workspace = null;
1842 if(FileExists(filePath))
1844 if(!strcmp(extension, ProjectExtension))
1846 char workspaceFile[MAX_LOCATION];
1847 strcpy(workspaceFile, filePath);
1848 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1849 workspace = LoadWorkspace(workspaceFile, filePath);
1851 else if(!strcmp(extension, WorkspaceExtension))
1852 workspace = LoadWorkspace(filePath, null);
1855 //project = LoadProject(filePath);
1860 char absolutePath[MAX_LOCATION];
1861 CreateProjectView(workspace, filePath);
1862 document = projectView;
1864 workspace.DropInvalidBreakpoints();
1867 ide.projectView.ShowOutputBuildLog(true);
1869 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1870 ide.projectView.DisplayCompiler(compiler, false);
1873 UpdateCompilerConfigs();
1876 char newWorkingDir[MAX_LOCATION];
1877 StripLastDirectory(filePath, newWorkingDir);
1878 ChangeFileDialogsDirectory(newWorkingDir, false);
1881 document.fileName = filePath;
1883 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1885 // this crashes on starting ide with epj file, solution please?
1886 // app.UpdateDisplay();
1888 workspace.holdTracking = true;
1889 for(ofi : workspace.openedFiles)
1891 if(ofi.state != closed)
1893 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1896 char fileName[MAX_LOCATION];
1898 GetLastDirectory(ofi.path, fileName);
1899 node = projectView.project.topNode.Find(fileName, true);
1901 node.EnsureVisible();
1905 workspace.holdTracking = false;
1907 workspace.timer.Start();
1909 findInFilesDialog.mode = FindInFilesMode::project;
1910 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1913 char location[MAX_LOCATION];
1914 StripLastDirectory(ide.project.topNode.path, location);
1915 ChangeProjectFileDialogDirectory(location);
1919 if(projectView.debugger)
1920 projectView.debugger.EvaluateWatches();
1927 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1929 ideProjectFileDialog.text = openProjectFileDialogTitle;
1930 if(ideProjectFileDialog.Modal() == cancel)
1932 filePath = ideProjectFileDialog.filePath;
1933 GetExtension(filePath, extension);
1944 else if(openMethod == add)
1949 char slashFilePath[MAX_LOCATION];
1950 GetSlashPathBuffer(slashFilePath, filePath);
1951 for(p : workspace.projects)
1953 if(!fstrcmp(p.filePath, slashFilePath))
1961 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1962 contents = $"This project is already present in workspace." }.Modal();
1966 prj = LoadProject(filePath);
1969 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1970 prj.StartMonitoring();
1971 workspace.projects.Add(prj);
1973 projectView.AddNode(prj.topNode, null);
1974 workspace.modified = true;
1976 findInFilesDialog.AddProjectItem(prj);
1977 projectView.ShowOutputBuildLog(true);
1978 projectView.DisplayCompiler(compiler, false);
1979 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1983 char location[MAX_LOCATION];
1984 StripLastDirectory(prj.topNode.path, location);
1985 ChangeProjectFileDialogDirectory(location);
1988 // projectView is associated with the main project and not with the one just added but
1989 return projectView; // just to let the caller know something was opened
1997 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1998 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1999 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2001 if(FileExists(filePath))
2002 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2003 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2004 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2007 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2010 else if(!strcmp(extension, "3ds"))
2012 if(FileExists(filePath))
2013 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2014 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2015 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2019 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2022 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2023 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2024 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2025 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2026 !strcmp(extension, "js"))
2028 CodeEditor editor { parent = this, state = state, visible = false };
2029 editor.updatingCode = true;
2030 if(editor.LoadFile(filePath))
2033 editor.visible = true;
2037 needFileModified = false;
2041 CodeEditor editor { parent = this, state = state, visible = false };
2042 if(editor.LoadFile(filePath))
2045 editor.visible = true;
2049 needFileModified = false;
2052 if(document && (document._class == class(PictureEdit) ||
2053 document._class == class(ModelView)))
2058 document.fileName = filePath;
2059 if(workspace && !workspace.holdTracking)
2060 workspace.UpdateOpenedFileInfo(filePath, opened);
2064 if(!document && createIfFails != no)
2066 if(createIfFails != yes && !needFileModified &&
2067 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2068 createIfFails = yes;
2069 if(createIfFails == yes || createIfFails == whatever)
2071 document = (Window)NewCodeEditor(this, state, true);
2073 document.fileName = filePath;
2079 if(projectView && document._class == class(CodeEditor) && workspace)
2081 int lineNumber, position;
2083 CodeEditor editor = (CodeEditor)document;
2084 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2085 editor.openedFileInfo.holdTracking = true;
2086 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2087 position = Max(editor.openedFileInfo.position - 1, 0);
2088 editor.editBox.GoToLineNum(lineNumber);
2089 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2090 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2091 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2092 editor.editBox.scroll = scroll;
2093 editor.openedFileInfo.holdTracking = false;
2096 if(needFileModified)
2097 document.OnFileModified = OnFileModified;
2098 document.NotifySaved = DocumentSaved;
2101 ideSettings.AddRecentProject(document.fileName);
2103 ideSettings.AddRecentFile(document.fileName);
2104 ide.UpdateRecentMenus();
2105 ide.AdjustFileMenus();
2106 settingsContainer.Save();
2114 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2115 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2117 if(!parentClosing && ide.workspace)
2118 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2121 bool ModelView::ModelViewOnClose(bool parentClosing)
2123 if(!parentClosing && ide.workspace)
2124 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2127 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2129 if(!parentClosing && ide.workspace)
2130 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2135 void OnUnloadGraphics(Window window)
2137 display.ClearMaterials();
2138 display.ClearTextures();
2139 display.ClearMeshes();
2143 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2145 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2146 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2150 bool OnKeyDown(Key key, unichar ch)
2155 projectView.Update(null);
2158 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2161 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2167 void GoToError(const char * line)
2170 projectView.GoToError(line);
2173 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2176 char *colon = strchr(text, ':');
2177 char filePath[MAX_LOCATION];
2178 char completePath[MAX_LOCATION];
2179 int line = 0, col = 0;
2184 char * close = strchr(text, ')');
2188 strncpy(name, &text[4], close - text - 4);
2189 name[close - text - 4] = '\0';
2190 for(p : ide.workspace.projects)
2192 if(!strcmp(p.name, name))
2202 prj = project ? project : (dir ? null : ide.project);
2203 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2205 path = (colon - 1 > path) ? colon - 1 : path;
2206 colon = strstr(colon + 1, ":");
2208 while(isspace(*path)) path++;
2211 strncpy(filePath, path, colon - path);
2212 filePath[colon - path] = '\0';
2213 line = atoi(colon + 1);
2214 colon = strstr(colon + 1, ":");
2216 col = atoi(colon + 1);
2218 else if(path - 1 >= path && *(path - 1) == '\"')
2220 colon = strchr(path, '\"');
2223 strncpy(filePath, path, colon - path);
2224 filePath[colon - path] = '\0';
2229 strcpy(completePath, prj.topNode.path);
2230 else if(dir && dir[0])
2231 strcpy(completePath, dir);
2233 completePath[0] = '\0';
2234 PathCat(completePath, filePath);
2236 if(FileExists(completePath).isFile)
2238 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2239 if(codeEditor && line)
2241 EditBox editBox = codeEditor.editBox;
2242 editBox.GoToLineNum(line - 1);
2243 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2248 void OnRedraw(Surface surface)
2250 Bitmap bitmap = back.bitmap;
2252 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2255 void SheetSelected(SheetType sheetSelected)
2257 if(activeChild == sheet)
2259 if(sheetSelected == methods)
2261 viewPropertiesItem.accelerator = f4;
2262 viewPropertiesItem.parent = viewMenu;
2263 viewMethodsItem.parent = null;
2267 viewMethodsItem.accelerator = f4;
2268 viewMethodsItem.parent = viewMenu;
2269 viewPropertiesItem.parent = null;
2274 viewMethodsItem.parent = viewMenu;
2275 viewPropertiesItem.parent = viewMenu;
2276 if(sheetSelected == methods)
2278 viewMethodsItem.accelerator = f4;
2279 viewPropertiesItem.accelerator = 0;
2283 viewMethodsItem.accelerator = 0;
2284 viewPropertiesItem.accelerator = f4;
2289 void OnActivateClient(Window client, Window previous)
2291 //if(!client || client != previous)
2294 if(!client || client != previous)
2297 dataType = previous._class;
2298 if(previous && !strcmp(dataType.name, "CodeEditor"))
2300 ((CodeEditor)previous).UpdateFormCode();
2302 else if(previous && !strcmp(dataType.name, "Designer"))
2304 ((Designer)previous).codeEditor.UpdateFormCode();
2309 dataType = client._class;
2310 if(client && !strcmp(dataType.name, "CodeEditor"))
2312 CodeEditor codeEditor = (CodeEditor)client;
2313 SetPrivateModule(codeEditor.privateModule);
2314 SetCurrentContext(codeEditor.globalContext);
2315 SetTopContext(codeEditor.globalContext);
2316 SetGlobalContext(codeEditor.globalContext);
2318 SetDefines(&codeEditor.defines);
2319 SetImports(&codeEditor.imports);
2321 SetActiveDesigner(codeEditor.designer);
2323 sheet.codeEditor = codeEditor;
2324 toolBox.codeEditor = codeEditor;
2326 viewDesignerItem.parent = viewMenu;
2327 if(activeChild != codeEditor)
2329 viewCodeItem.parent = viewMenu;
2330 viewDesignerItem.accelerator = 0;
2331 viewCodeItem.accelerator = f8;
2335 viewCodeItem.parent = null;
2336 viewDesignerItem.accelerator = f8;
2339 else if(client && !strcmp(dataType.name, "Designer"))
2341 CodeEditor codeEditor = ((Designer)client).codeEditor;
2344 SetPrivateModule(codeEditor.privateModule);
2345 SetCurrentContext(codeEditor.globalContext);
2346 SetTopContext(codeEditor.globalContext);
2347 SetGlobalContext(codeEditor.globalContext);
2348 SetDefines(&codeEditor.defines);
2349 SetImports(&codeEditor.imports);
2353 SetPrivateModule(null);
2354 SetCurrentContext(null);
2355 SetTopContext(null);
2356 SetGlobalContext(null);
2361 SetActiveDesigner((Designer)client);
2363 sheet.codeEditor = codeEditor;
2364 toolBox.codeEditor = codeEditor;
2366 viewCodeItem.parent = viewMenu;
2367 if(activeChild != client)
2369 viewDesignerItem.parent = viewMenu;
2370 viewDesignerItem.accelerator = f8;
2371 viewCodeItem.accelerator = 0;
2375 viewDesignerItem.parent = null;
2376 viewCodeItem.accelerator = f8;
2382 sheet.codeEditor = null;
2383 toolBox.codeEditor = null;
2384 SetActiveDesigner(null);
2386 viewDesignerItem.parent = null;
2387 viewCodeItem.parent = null;
2390 SheetSelected(sheet.sheetSelected);
2393 projectCompileItem = null;
2398 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2400 CodeEditor codeEditor = (CodeEditor)client;
2401 EditBox editBox = codeEditor.editBox;
2403 statusBar.AddField(pos);
2405 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2406 statusBar.AddField(caps);
2408 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2409 statusBar.AddField(ovr);
2411 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2412 statusBar.AddField(num);
2414 //statusBar.text = "Ready";
2416 if(projectView && projectView.project)
2418 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2422 sprintf(name, $"Compile %s", node.name);
2423 projectCompileItem =
2425 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2427 bool NotifySelect(MenuItem selection, Modifiers mods)
2431 bool result = false;
2432 ProjectNode node = null;
2433 for(p : ide.workspace.projects)
2435 node = projectView.GetNodeFromWindow(activeClient, p);
2436 if(node && projectView.Compile(node))
2443 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2448 projectMenu.AddDynamic(projectCompileItem, ide, false);
2454 caps = ovr = num = null;
2459 bool OnClose(bool parentClosing)
2461 //return !projectView.buildInProgress;
2462 if(projectView && projectView.buildInProgress)
2464 if(DontTerminateDebugSession($"Close IDE"))
2466 if(findInFilesDialog)
2467 findInFilesDialog.SearchStop();
2470 workspace.timer.Stop();
2473 ideMainFrame.Destroy(0);
2480 for(c = 1; c<app.argc; c++)
2482 char fullPath[MAX_LOCATION];
2483 char parentPath[MAX_LOCATION];
2484 char ext[MAX_EXTENSION];
2486 FileAttribs dirAttribs;
2487 GetWorkingDir(fullPath, MAX_LOCATION);
2488 PathCat(fullPath, app.argv[c]);
2489 StripLastDirectory(fullPath, parentPath);
2490 GetExtension(app.argv[c], ext);
2491 isProject = !strcmpi(ext, "epj");
2493 if(isProject && c > 1) continue;
2495 // Create directory for projects (only)
2496 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2498 if(isProject && !FileExists(fullPath))
2500 // The NewProject will handle directory creation
2501 /*if(!dirAttribs.isDirectory)
2503 MakeDir(parentPath);
2504 dirAttribs = FileExists(parentPath);
2506 if(dirAttribs.isDirectory)*/
2508 char name[MAX_LOCATION];
2509 NewProjectDialog newProjectDialog;
2513 projectView.visible = false;
2514 if(!projectView.Destroy(0))
2518 newProjectDialog = { master = this };
2520 strcpy(name, app.argv[c]);
2521 StripExtension(name);
2522 GetLastDirectory(name, name);
2523 newProjectDialog.projectName.contents = name;
2524 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2525 newProjectDialog.locationEditBox.path = parentPath;
2526 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2528 newProjectDialog.Modal();
2531 ideSettings.AddRecentProject(projectView.fileName);
2532 ide.UpdateRecentMenus();
2533 settingsContainer.Save();
2536 // Open only one project
2540 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2548 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2551 projectView.visible = false;
2552 projectView.Destroy(0);
2555 #ifdef GDB_DEBUG_GUI
2556 gdbDialog.Destroy(0);
2561 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2565 char * oldPaths[128];
2566 String oldList = new char[maxPathLen];
2567 Array<String> newExePaths { };
2568 //Map<String, bool> exePathExists { };
2570 #if defined(__unix__) || defined(__APPLE__)
2571 Array<String> newLibPaths { };
2572 Map<String, bool> libPathExists { };
2577 for(prj : workspace.projects)
2579 DirExpression targetDirExp;
2581 // SKIP FIRST PROJECT...
2582 if(prj == workspace.projects.firstIterator.data) continue;
2584 // NOTE: Right now the additional project config dir will be
2585 // obtained when the debugger is started, so toggling it
2586 // while building will change which library gets used.
2587 // To go with the initial state, e.g. when F5 was pressed,
2588 // we nould need to keep a list of all project's active
2589 // config upon startup.
2590 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2592 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2596 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2597 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2601 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2602 if(cfg.targetType == sharedLibrary && cfg.debug)
2606 if(targetDirExp.dir)
2608 char buffer[MAX_LOCATION];
2609 #if defined(__WIN32__)
2610 Array<String> paths = newExePaths;
2612 Array<String> paths = newLibPaths;
2614 GetSystemPathBuffer(buffer, prj.topNode.path);
2615 PathCat(buffer, targetDirExp.dir);
2618 if(!fstrcmp(p, buffer))
2625 paths.Add(CopyString(buffer));
2627 delete targetDirExp;
2631 for(item : compiler.executableDirs)
2634 for(p : newExePaths)
2636 if(!fstrcmp(p, item))
2643 newExePaths.Add(CopySystemPath(item));
2646 GetEnvironment("PATH", oldList, maxPathLen);
2648 printf("Old value of PATH: %s\n", oldList);
2650 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2651 for(c = 0; c < count; c++)
2654 for(p : newExePaths)
2656 if(!fstrcmp(p, oldPaths[c]))
2663 newExePaths.Add(CopySystemPath(oldPaths[c]));
2667 for(path : newExePaths)
2668 len += strlen(path) + 1;
2669 newList = new char[len + 1];
2671 for(path : newExePaths)
2673 strcat(newList, path);
2674 strcat(newList, pathListSep);
2676 newList[len - 1] = '\0';
2677 SetEnvironment("PATH", newList);
2679 printf("New value of PATH: %s\n", newList);
2686 #if defined(__unix__) || defined(__APPLE__)
2688 for(item : compiler.libraryDirs)
2690 if(!libPathExists[item]) // fstrcmp should be used
2692 newLibPaths.Add(item);
2693 libPathExists[item] = true;
2697 #if defined(__APPLE__)
2698 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2700 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2703 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2705 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2706 for(c = 0; c < count; c++)
2708 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2710 newLibPaths.Add(oldPaths[c]);
2711 libPathExists[oldPaths[c]] = true;
2716 for(path : newLibPaths)
2717 len += strlen(path) + 1;
2718 newList = new char[len + 1];
2720 for(path : newLibPaths)
2722 strcat(newList, path);
2723 strcat(newList, pathListSep);
2725 newList[len - 1] = '\0';
2726 #if defined(__APPLE__)
2727 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2729 SetEnvironment("LD_LIBRARY_PATH", newList);
2732 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2737 delete libPathExists;
2740 if(compiler.distccEnabled && compiler.distccHosts)
2741 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2746 void DestroyTemporaryProjectDir()
2748 if(tmpPrjDir && tmpPrjDir[0])
2750 if(FileExists(tmpPrjDir).isDirectory)
2751 DestroyDir(tmpPrjDir);
2752 property::tmpPrjDir = null;
2758 // Graphics Driver Menu
2762 app.currentSkin.selectionColor = selectionColor;
2763 app.currentSkin.selectionText = selectionText;
2767 driverItems = new MenuItem[app.numDrivers];
2768 for(c = 0; c < app.numDrivers; c++)
2770 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2771 driverItems[c].id = c;
2772 driverItems[c].isRadio = true;
2775 driverItems = new MenuItem[2];
2776 #if defined(__unix__)
2777 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2778 driverItems[0].id = 0;
2779 driverItems[0].isRadio = true;
2781 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2782 driverItems[0].id = 0;
2783 driverItems[0].isRadio = true;
2785 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2786 driverItems[1].id = 1;
2787 driverItems[1].isRadio = true;
2789 /* skinItems = new MenuItem[app.numSkins];
2790 for(c = 0; c < app.numSkins; c++)
2792 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2793 skinItems[c].id = c;
2794 skinItems[c].isRadio = true;
2797 ideFileDialog.master = this;
2798 ideProjectFileDialog.master = this;
2800 //SetDriverAndSkin();
2804 void UpdateRecentMenus()
2807 Menu fileMenu = menu.FindMenu($"File");
2808 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2809 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2810 char itemName[MAX_LOCATION + 4];
2813 recentFiles.Clear();
2816 for(recent : ideSettings.recentFiles)
2818 sprintf(itemName, "%d %s", 1 + c, recent);
2819 MakeSystemPath(itemName);
2820 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2824 recentProjects.Clear();
2826 for(recent : ideSettings.recentProjects)
2828 sprintf(itemName, "%d %s", 1 + c, recent);
2829 MakeSystemPath(itemName);
2830 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2843 void DestroyDir(char * path)
2845 RecursiveDeleteFolderFSI fsi { };
2850 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2852 bool preserveRootFolder;
2854 void OutFolder(char * folderPath, bool isRoot)
2856 if(!(preserveRootFolder && isRoot))
2857 RemoveDir(folderPath);
2860 bool OnFile(char * filePath)
2862 DeleteFile(filePath);
2867 class IDEApp : GuiApplication
2869 //driver = "Win32Console";
2870 // driver = "OpenGL";
2875 SetLoggingMode(stdOut, null);
2876 //SetLoggingMode(debug, null);
2878 settingsContainer.Load();
2879 #if defined(__unix__) || defined(__APPLE__)
2880 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2882 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2884 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2888 desktop.text = titleECEREIDE;
2891 for(c = 1; c<app.argc; c++)
2893 char fullPath[MAX_LOCATION];
2894 GetWorkingDir(fullPath, MAX_LOCATION);
2895 PathCat(fullPath, app.argv[c]);
2896 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2903 IDEMainFrame ideMainFrame { };
2905 define app = ((IDEApp)__thisModule);
2907 define titleECEREIDE = $"ECERE IDE (Debug)";
2909 define titleECEREIDE = $"ECERE IDE";