2 public import static "ecere"
3 public import static "ec"
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
18 import "ProjectConfig"
20 import "NodeProperties"
21 import "ProjectSettings"
33 import "BreakpointsView"
34 import "CallStackView"
45 import "FileSystemIterator"
47 #if defined(__WIN32__)
48 define pathListSep = ";";
50 define pathListSep = ":";
53 define maxPathLen = 65 * MAX_LOCATION;
55 class PathBackup : struct
62 oldPath = new char[maxPathLen];
63 oldLDPath = new char[maxPathLen];
65 GetEnvironment("PATH", oldPath, maxPathLen);
66 #if defined(__APPLE__)
67 GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
69 GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
75 SetEnvironment("PATH", oldPath);
76 #if defined(__APPLE__)
77 SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
79 SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
86 enum OpenCreateIfFails { no, yes, something, whatever };
87 enum OpenMethod { normal, add };
89 static Array<FileFilter> fileFilters
91 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
92 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
93 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
94 { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
95 { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
96 { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
97 { $"3D Studio Model Files (*.3ds)", "3ds" },
98 { $"All files", null }
101 static Array<FileType> fileTypes
103 { $"Based on extension", null },
106 { $"3D Studio Model", "3ds" }
109 static Array<FileFilter> projectFilters
111 { $"Project Files (*.epj)", ProjectExtension }
114 static Array<FileType> projectTypes
116 { $"Project File", ProjectExtension }
119 static Array<FileFilter> findInFilesFileFilters
121 { $"eC Files (*.ec, *.eh)", "ec, eh" },
122 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
123 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
124 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
125 { $"Text files (*.txt)", "txt" },
126 { $"All files", null }
129 FileDialog ideFileDialog
131 type = multiOpen, text = $"Open";
132 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
135 define openProjectFileDialogTitle = $"Open Project";
136 define addProjectFileDialogTitle = $"Open Additional Project";
137 FileDialog ideProjectFileDialog
140 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
143 GlobalSettingsDialog globalSettingsDialog
145 ideSettings = ideSettings;
146 settingsContainer = settingsContainer;
148 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
150 switch(globalSettingsChange)
155 for(child = ide.firstChild; child; child = child.next)
157 if(child._class == class(CodeEditor))
159 CodeEditor codeEditor = (CodeEditor) child;
160 codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
161 // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
162 codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
163 codeEditor.OnPostCreate(); // Update editBox margin size
170 case compilerSettings:
172 ide.UpdateCompilerConfigs(true);
179 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
184 lineY = (line - 1) * lineH;
185 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
187 Bitmap bitmap = resource.bitmap;
189 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
194 #define IDEItem(x) (&((IDEWorkSpace)0).x)
196 class IDEToolbar : ToolBar
200 ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
202 ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
204 // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
206 ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
208 ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
210 ToolSeparator separator1 { this };
219 // ToolSeparator separator2 { this };
221 /* Project options */
223 ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
225 ToolButton buttonOpenProject { this, toolTip = $"Open project", menuItemPtr = IDEItem(projectOpenItem) };
226 // Add project to workspace
227 ToolButton buttonAddProject { this, toolTip = $"Add project to workspace", menuItemPtr = IDEItem(projectAddItem), disabled = true; };
229 // ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
231 ToolSeparator separator3 { this };
233 /* Build/Execution options */
235 ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
237 ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
239 ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
241 ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
243 // ToolButton buttonRealClean { this, toolTip = $"Real clean project", menuItemPtr = IDEItem(projectRealCleanItem), disabled = true; };
244 // Regenerate Makefile
245 ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
246 // Compile actual file
248 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
249 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
250 ToolButton buttonInstall { this, toolTip = $"Install", menuItemPtr = IDEItem(projectInstallItem), disabled = true; };
253 ToolSeparator separator4 { this };
257 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
259 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
261 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
263 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
265 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
267 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
269 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
271 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
273 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
275 ToolSeparator separator5 { this };
277 Window spacer5 { this, size = { 4 } };
281 this, toolTip = $"Active Configuration(s)", size = { 160 }, disabled = true;
282 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
285 ide.workspace.SelectActiveConfig(row.string);
290 Window spacer6 { this, size = { 4 } };
292 DropBox activeCompiler
294 this, toolTip = $"Active Compiler", size = { 160 }, disabled = true;
295 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
297 if(ide.workspace && ide.projectView && row && strcmp(row.string, ide.workspace.compiler))
299 bool silent = ide.projectView.buildInProgress == none ? false : true;
300 CompilerConfig compiler = ideSettings.GetCompilerConfig(row.string);
301 ide.workspace.compiler = row.string;
302 ide.projectView.ShowOutputBuildLog(!silent);
304 ide.projectView.DisplayCompiler(compiler, false);
305 for(prj : ide.workspace.projects)
306 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
308 ide.workspace.Save();
314 DropBox activeBitDepth
316 this, toolTip = $"Active Bit Depth", size = { 60 }, disabled = true;
317 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
319 if(ide.workspace && ide.projectView && row)
321 bool silent = ide.projectView.buildInProgress == none ? false : true;
322 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
323 ide.workspace.bitDepth = (int)row.tag;
324 ide.projectView.ShowOutputBuildLog(!silent);
326 ide.projectView.DisplayCompiler(compiler, false);
327 for(prj : ide.workspace.projects)
328 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
330 ide.workspace.Save();
336 Window spacer7 { this, size = { 4 } };
341 row = activeBitDepth.AddString("Auto");
343 activeBitDepth.AddString("32 bit").tag = 32;
344 activeBitDepth.AddString("64 bit").tag = 64;
345 activeBitDepth.currentRow = row;
350 class IDEMainFrame : Window
352 background = formColor;
353 borderStyle = sizable;
357 minClientSize = { 600, 300 };
359 icon = { ":icon.png" };
360 text = titleECEREIDE;
364 anchor = { top = 0, right = 0, bottom = 0 };
367 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
374 isActiveClient = true;
376 direction = vertical;
377 background = formColor;
378 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
386 ((IDEWorkSpace)master).toolBar = null;
389 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
392 define ide = ideMainFrame.ideWorkSpace;
394 class IDEWorkSpace : Window
396 background = Color { 85, 85, 85 };
399 hasVertScroll = true;
400 hasHorzScroll = true;
402 isActiveClient = true;
403 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
407 MenuItem * driverItems, * skinItems;
408 StatusField pos { width = 150 };
409 StatusField ovr, caps, num;
412 BitmapResource back { ":ecereBack.jpg", window = this };
413 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
414 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
415 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
416 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
417 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
418 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
419 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
420 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
421 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
422 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
424 Debugger debugger { };
426 ProjectView projectView;
428 OutputView outputView
432 void OnGotoError(char * line, bool noParsing)
434 ide.GoToError(line, noParsing);
437 void OnCodeLocationParseAndGoTo(char * line)
439 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
442 bool OnKeyDown(Key key, unichar ch)
447 if(activeBox != findBox || !ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
448 ide.ShowCodeEditor();
452 OutputView::OnKeyDown(key, ch);
459 bool OnClose(bool parentClosing)
463 ide.RepositionWindows(false);
464 return parentClosing;
468 CallStackView callStackView
470 parent = this, font = { panelFont.faceName, panelFont.size };
472 void OnSelectFrame(int frameIndex)
474 ide.debugger.GoToStackFrameLine(frameIndex, true);
476 ide.debugger.SelectFrame(frameIndex);
479 void OnToggleBreakpoint()
481 Debugger debugger = ide.debugger;
482 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
484 int line = debugger.activeFrame.line;
485 char name[MAX_LOCATION];
487 // TOFIX: Improve on this, don't use only filename, make a function
488 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
489 if(ide && ide.workspace)
491 for(p : ide.workspace.projects)
493 if(p.topNode.Find(name, false))
501 for(p : ide.workspace.projects)
503 if(IsPathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
511 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
514 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
515 if(codeEditor) { codeEditor.Update(null); Activate(); }
520 bool OnKeyDown(Key key, unichar ch)
524 case escape: ide.ShowCodeEditor(); break;
529 bool OnClose(bool parentClosing)
533 ide.RepositionWindows(false);
534 return parentClosing;
537 void OnRedraw(Surface surface)
539 Debugger debugger = ide.debugger;
540 Frame activeFrame = debugger.activeFrame;
544 int lineCursor, lineTopFrame, activeThread, hitThread;
545 int lineH, scrollY, boxH;
547 Breakpoint bp = null;
550 scrollY = editBox.scroll.y;
551 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
552 activeThread = debugger.activeThread;
553 hitThread = debugger.hitThread;
554 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
556 // TODO: improve bp drawing... it should be visible even if it's not on the activeFrame
557 if(activeFrame.absoluteFile)
559 for(i : ide.workspace.breakpoints; i.type == user)
561 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
562 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
563 activeFrame.line == i.line)
571 DrawLineMarginIcon(surface,
572 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
573 lineCursor /*1*/, lineH, scrollY, boxH);
575 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
576 DrawLineMarginIcon(surface,
577 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
578 1, lineH, scrollY, boxH);
580 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
581 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
582 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
584 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
585 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
587 if(editBox.horzScroll && editBox.horzScroll.visible)
589 surface.SetBackground(control);
590 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
595 WatchesView watchesView { parent = this };
596 ThreadsView threadsView
598 parent = this, font = { panelFont.faceName, panelFont.size };
600 bool OnKeyDown(Key key, unichar ch)
604 case escape: ide.ShowCodeEditor(); break;
609 bool OnClose(bool parentClosing)
613 ide.RepositionWindows(false);
614 return parentClosing;
617 void OnSelectThread(int threadId)
620 ide.debugger.SelectThread(threadId);
623 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
626 Debugger debugger = ide.debugger;
627 *activeThread = debugger.activeThread;
628 *hitThread = debugger.hitThread;
629 *signalThread = debugger.signalThread;
634 BreakpointsView breakpointsView { parent = this };
636 ToolBox toolBox { parent = this };
637 Sheet sheet { parent = this };
640 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
642 Menu fileMenu { menu, $"File", f, hasMargin = true };
645 fileMenu, $"New", n, ctrlN;
646 bitmap = { ":actions/docNew.png" };
647 bool NotifySelect(MenuItem selection, Modifiers mods)
649 Window document = (Window)NewCodeEditor(this, normal, false);
650 document.NotifySaved = DocumentSaved;
654 MenuItem fileOpenItem
656 fileMenu, $"Open...", o, ctrlO;
657 bitmap = { ":actions/docOpen.png" };
658 bool NotifySelect(MenuItem selection, Modifiers mods)
660 if(!projectView && ideSettings.ideFileDialogLocation)
661 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
664 if(ideFileDialog.Modal() == ok)
666 bool gotWhatWeWant = false;
668 int numSelections = ideFileDialog.numSelections;
669 char ** multiFilePaths = ideFileDialog.multiFilePaths;
671 for(c = 0; c < numSelections; c++)
673 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift))
674 gotWhatWeWant = true;
677 MessageBox { type = yesNo, master = this, text = $"Error opening file",
678 contents = $"Open a different file?" }.Modal() == no)
680 if(!projectView && gotWhatWeWant)
681 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
682 ide.RepositionWindows(false);
692 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
693 MenuDivider { fileMenu };
694 MenuItem fileSaveItem
696 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
698 // For the toolbar button; clients can still override that for the menu item
699 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
701 Window w = activeClient;
703 w.MenuFileSave(null, 0);
707 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
708 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
709 MenuDivider { fileMenu };
712 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
713 bool NotifySelect(MenuItem selection, Modifiers mods)
715 findInFilesDialog.replaceMode = false;
716 findInFilesDialog.Show();
720 MenuItem replaceInFiles
722 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
723 bool NotifySelect(MenuItem selection, Modifiers mods)
725 findInFilesDialog.replaceMode = true;
726 findInFilesDialog.Show();
730 MenuDivider { fileMenu };
731 MenuItem globalSettingsItem
733 fileMenu, $"Global Settings...", g;
734 bool NotifySelect(MenuItem selection, Modifiers mods)
736 globalSettingsDialog.master = this;
737 if(ide.workspace && ide.workspace.compiler)
738 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
739 else if(ideSettings.defaultCompiler)
740 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
741 globalSettingsDialog.Modal();
745 MenuDivider { fileMenu };
746 Menu recentFiles { fileMenu, $"Recent Files", r };
747 Menu recentProjects { fileMenu, $"Recent Projects", p };
748 MenuDivider { fileMenu };
751 fileMenu, $"Exit", x, altF4;
753 bool NotifySelect(MenuItem selection, Modifiers mods)
755 ideMainFrame.Destroy(0);
760 bool FileRecentFile(MenuItem selection, Modifiers mods)
763 for(file : ideSettings.recentFiles)
765 if(id == selection.id)
768 char extension[MAX_EXTENSION] = "";
769 GetExtension(file, extension);
770 isProjectFile = (!strcmpi(extension, "epj") || !strcmpi(extension, "ews"));
773 char * command = PrintString("ide ", isProjectFile ? "-t " : "", file);
779 OpenFile(file, normal, true, isProjectFile ? "txt" : null, no, normal, mods.ctrl && mods.shift);
780 ide.RepositionWindows(false);
789 bool FileRecentProject(MenuItem selection, Modifiers mods)
792 for(file : ideSettings.recentProjects)
794 if(id == selection.id)
798 char * command = PrintString("ide ", file);
803 OpenFile(file, normal, true, null, no, normal, mods.ctrl && mods.shift);
811 MenuPlacement editMenu { menu, $"Edit", e };
813 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
814 MenuItem projectNewItem
816 projectMenu, $"New...", n, Key { n, true, true };
817 bitmap = { ":actions/projNew.png" };
818 bool NotifySelect(MenuItem selection, Modifiers mods)
820 if(!DontTerminateDebugSession($"New Project"))
823 NewProjectDialog newProjectDialog { master = this };
824 incref newProjectDialog;
825 result = newProjectDialog.Modal();
830 newProjectDialog.CreateNewProject();
833 ideSettings.AddRecentProject(projectView.fileName);
834 ide.UpdateRecentMenus();
835 settingsContainer.Save();
839 delete newProjectDialog;
844 MenuItem projectOpenItem
846 projectMenu, $"Open...", o, Key { o, true, true };
847 bitmap = { ":actions/projOpen.png" };
848 bool NotifySelect(MenuItem selection, Modifiers mods)
850 if(ideSettings.ideProjectFileDialogLocation)
851 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
853 ideProjectFileDialog.text = openProjectFileDialogTitle;
854 if(ideProjectFileDialog.Modal() == ok)
856 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift);
857 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
862 MenuItem projectQuickItem
864 projectMenu, $"Quick...", q, f7, disabled = true;
865 bool NotifySelect(MenuItem selection, Modifiers mods)
868 QuickProjectDialog { this }.Modal();
872 MenuItem projectAddItem
874 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
875 bitmap = { ":actions/projAdd.png" };
877 bool NotifySelect(MenuItem selection, Modifiers mods)
879 if(ideSettings.ideProjectFileDialogLocation)
880 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
882 ideProjectFileDialog.text = addProjectFileDialogTitle;
885 if(ideProjectFileDialog.Modal() == ok)
887 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add, mods.ctrl && mods.shift))
889 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
890 contents = $"Add a different project?" }.Modal() == no)
901 MenuItem projectCloseItem
903 projectMenu, $"Close", c, disabled = true;
904 bool NotifySelect(MenuItem selection, Modifiers mods)
908 if(!ide.DontTerminateDebugSession($"Project Close"))
914 MenuDivider { projectMenu };
915 MenuItem projectSettingsItem
917 projectMenu, $"Settings...", s, altF7, disabled = true;
918 bool NotifySelect(MenuItem selection, Modifiers mods)
920 projectView.MenuSettings(projectView.active ? selection : null, mods);
924 MenuDivider { projectMenu };
925 MenuItem projectBrowseFolderItem
927 projectMenu, $"Browse Project Folder", p, disabled = true;
928 bool NotifySelect(MenuItem selection, Modifiers mods)
931 projectView.MenuBrowseFolder(null, mods);
935 MenuDivider { projectMenu };
936 MenuItem projectRunItem
938 projectMenu, $"Run", r, ctrlF5, disabled = true;
939 bitmap = { ":actions/run.png" };
940 bool NotifySelect(MenuItem selection, Modifiers mods)
943 projectView.Run(null, mods);
947 MenuItem projectBuildItem
949 projectMenu, $"Build", b, f7, disabled = true;
950 bitmap = { ":actions/build.png" };
951 bool NotifySelect(MenuItem selection, Modifiers mods)
955 if(projectView.buildInProgress == none)
956 projectView.ProjectBuild(projectView.active ? selection : null, mods);
958 projectView.stopBuild = true;
963 MenuItem projectLinkItem
965 projectMenu, $"Relink", l, disabled = true;
966 bitmap = { ":actions/relink.png" };
967 bool NotifySelect(MenuItem selection, Modifiers mods)
970 projectView.ProjectLink(projectView.active ? selection : null, mods);
974 MenuItem projectRebuildItem
976 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
977 bitmap = { ":actions/rebuild.png" };
978 bool NotifySelect(MenuItem selection, Modifiers mods)
981 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
985 MenuItem projectCleanTargetItem
987 projectMenu, $"Clean Target", g, disabled = true;
988 bitmap = { ":actions/clean.png" };
989 bool NotifySelect(MenuItem selection, Modifiers mods)
994 projectView.ProjectCleanTarget(projectView.active ? selection : null, mods);
999 MenuItem projectCleanItem
1001 projectMenu, $"Clean", e, disabled = true;
1002 bitmap = { ":actions/clean.png" };
1003 bool NotifySelect(MenuItem selection, Modifiers mods)
1008 projectView.ProjectClean(projectView.active ? selection : null, mods);
1013 MenuItem projectRealCleanItem
1015 projectMenu, $"Real Clean", disabled = true;
1016 bitmap = { ":actions/clean.png" };
1017 bool NotifySelect(MenuItem selection, Modifiers mods)
1022 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
1027 MenuItem projectRegenerateItem
1029 projectMenu, $"Regenerate Makefile", m, disabled = true;
1030 bitmap = { ":actions/regMakefile.png" };
1031 bool NotifySelect(MenuItem selection, Modifiers mods)
1034 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
1038 MenuItem projectInstallItem
1040 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
1041 projectMenu, $"Install", t, disabled = true;
1043 bitmap = { ":status/software-update-available.png" };
1044 bool NotifySelect(MenuItem selection, Modifiers mods)
1047 projectView.ProjectInstall(projectView.active ? selection : null, mods);
1051 MenuItem projectCompileItem;
1052 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1053 MenuItem debugStartResumeItem
1055 debugMenu, $"Start", s, f5, disabled = true;
1056 bitmap = { ":actions/debug.png" };
1057 NotifySelect = MenuDebugStart;
1059 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1063 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1064 if(!projectView.DebugStart())
1065 debugStartResumeItem.disabled = false; // same exception
1069 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1072 projectView.DebugResume();
1075 MenuItem debugRestartItem
1077 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1078 bitmap = { ":actions/restart.png" };
1079 bool NotifySelect(MenuItem selection, Modifiers mods)
1082 projectView.DebugRestart();
1086 MenuItem debugBreakItem
1088 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1089 bitmap = { ":actions/pause.png" };
1090 bool NotifySelect(MenuItem selection, Modifiers mods)
1092 if(projectView && projectView.buildInProgress != none)
1095 projectView.DebugBreak();
1099 MenuItem debugStopItem
1101 debugMenu, $"Stop", p, shiftF5, disabled = true;
1102 bitmap = { ":actions/stopDebug.png" };
1103 bool NotifySelect(MenuItem selection, Modifiers mods)
1106 projectView.DebugStop();
1111 MenuDivider { debugMenu };
1112 MenuItem debugUseValgrindItem
1114 debugMenu, $"Use Valgrind", d, disabled = true, checkable = true;
1115 bool NotifySelect(MenuItem selection, Modifiers mods)
1119 ide.workspace.useValgrind = selection.checked;
1120 ide.workspace.Save();
1122 ide.AdjustValgrindMenus();
1126 Menu debugValgrindLeakCheckItem { debugMenu, $"Valgrind Leak Check", h };
1127 MenuItem debugValgrindNoLeakCheckItem { debugValgrindLeakCheckItem, $"No" , f, id = ValgrindLeakCheck::no , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1128 MenuItem debugValgrindSummaryLeakCheckItem { debugValgrindLeakCheckItem, $"Summary", f, id = ValgrindLeakCheck::summary, checkable = true, disabled = true; NotifySelect = ValgrindLCSelect, checked = true; }
1129 MenuItem debugValgrindYesLeakCheckItem { debugValgrindLeakCheckItem, $"Yes" , f, id = ValgrindLeakCheck::yes , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1130 MenuItem debugValgrindFullLeakCheckItem { debugValgrindLeakCheckItem, $"Full" , f, id = ValgrindLeakCheck::full , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1131 bool ValgrindLCSelect(MenuItem selection, Modifiers mods)
1135 if(selection.checked)
1137 ValgrindLeakCheck vgLeakCheck = (ValgrindLeakCheck)selection.id;
1139 debugValgrindNoLeakCheckItem.checked = debugValgrindNoLeakCheckItem.id == vgLeakCheck;
1140 debugValgrindSummaryLeakCheckItem.checked = debugValgrindSummaryLeakCheckItem.id == vgLeakCheck;
1141 debugValgrindYesLeakCheckItem.checked = debugValgrindYesLeakCheckItem.id == vgLeakCheck;
1142 debugValgrindFullLeakCheckItem.checked = debugValgrindFullLeakCheckItem.id == vgLeakCheck;
1144 ide.workspace.vgLeakCheck = vgLeakCheck;
1145 ide.workspace.Save();
1148 selection.checked = true;
1152 Menu debugValgrindRedzoneSizeItem { debugMenu, $"Valgrind Redzone Size", z };
1153 MenuItem debugValgrindRS0Item { debugValgrindRedzoneSizeItem, $"0" , f, id = 0, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect, checked = true; }
1154 MenuItem debugValgrindRS16Item { debugValgrindRedzoneSizeItem, $"16" , f, id = 16, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1155 MenuItem debugValgrindRS32Item { debugValgrindRedzoneSizeItem, $"32" , f, id = 32, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1156 MenuItem debugValgrindRS64Item { debugValgrindRedzoneSizeItem, $"64" , f, id = 64, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1157 MenuItem debugValgrindRS128Item { debugValgrindRedzoneSizeItem, $"128", f, id = 128, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1158 MenuItem debugValgrindRS256Item { debugValgrindRedzoneSizeItem, $"256", f, id = 256, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1159 MenuItem debugValgrindRS512Item { debugValgrindRedzoneSizeItem, $"512", f, id = 512, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1160 bool ValgrindRSSelect(MenuItem selection, Modifiers mods)
1164 if(selection.checked)
1166 int vgRedzoneSize = (int)selection.id;
1168 debugValgrindRS0Item.checked = debugValgrindRS0Item.id == vgRedzoneSize;
1169 debugValgrindRS16Item.checked = debugValgrindRS16Item.id == vgRedzoneSize;
1170 debugValgrindRS32Item.checked = debugValgrindRS32Item.id == vgRedzoneSize;
1171 debugValgrindRS64Item.checked = debugValgrindRS64Item.id == vgRedzoneSize;
1172 debugValgrindRS128Item.checked = debugValgrindRS128Item.id == vgRedzoneSize;
1173 debugValgrindRS256Item.checked = debugValgrindRS256Item.id == vgRedzoneSize;
1174 debugValgrindRS512Item.checked = debugValgrindRS512Item.id == vgRedzoneSize;
1176 ide.workspace.vgRedzoneSize = vgRedzoneSize;
1177 ide.workspace.Save();
1180 selection.checked = true;
1184 MenuItem debugValgrindTrackOriginsItem
1186 debugMenu, $"Valgrind Track Origins", k, checkable = true, disabled = true;
1187 bool NotifySelect(MenuItem selection, Modifiers mods)
1191 ide.workspace.vgTrackOrigins = selection.checked;
1192 ide.workspace.Save();
1198 MenuDivider { debugMenu };
1199 MenuItem debugStepIntoItem
1201 debugMenu, $"Step Into", i, f11, disabled = true;
1202 bitmap = { ":actions/stepInto.png" };
1203 bool NotifySelect(MenuItem selection, Modifiers mods)
1206 projectView.DebugStepInto();
1210 MenuItem debugStepOverItem
1212 debugMenu, $"Step Over", v, f10, disabled = true;
1213 bitmap = { ":actions/stepOver.png" };
1214 bool NotifySelect(MenuItem selection, Modifiers mods)
1217 projectView.DebugStepOver(false);
1221 MenuItem debugStepOutItem
1223 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1224 bitmap = { ":actions/stepOut.png" };
1225 bool NotifySelect(MenuItem selection, Modifiers mods)
1228 projectView.DebugStepOut(false);
1232 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1233 MenuItem debugSkipStepOverItem
1235 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1236 bool NotifySelect(MenuItem selection, Modifiers mods)
1239 projectView.DebugStepOver(true);
1243 MenuItem debugSkipStepOutItem
1245 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1246 bitmap = { ":actions/skipBreaks.png" };
1247 bool NotifySelect(MenuItem selection, Modifiers mods)
1250 projectView.DebugStepOut(true);
1254 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1255 MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", l };
1256 //MenuDivider { debugMenu };
1257 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1258 MenuPlacement imageMenu { menu, $"Image", i };
1259 Menu viewMenu { menu, $"View", v };
1260 MenuItem viewProjectItem
1262 viewMenu, $"Project View", j, alt0, disabled = true;
1263 bool NotifySelect(MenuItem selection, Modifiers mods)
1267 projectView.visible = true;
1268 projectView.Activate();
1273 MenuPlacement { viewMenu, $"View Designer" };
1274 MenuPlacement { viewMenu, $"View Code" };
1275 MenuPlacement { viewMenu, $"View Properties" };
1276 MenuPlacement { viewMenu, $"View Methods" };
1277 MenuItem viewDesignerItem
1279 viewMenu, $"View Designer", d, f8;
1280 bool NotifySelect(MenuItem selection, Modifiers mods)
1282 Window client = activeClient;
1283 Class dataType = client._class;
1284 if(!strcmp(dataType.name, "Designer"))
1286 client.visible = true;
1290 ((CodeEditor)client).ViewDesigner();
1294 MenuItem viewCodeItem
1296 viewMenu, $"View Code", c, f8;
1297 bool NotifySelect(MenuItem selection, Modifiers mods)
1299 Window client = activeClient;
1300 Class dataType = client._class;
1301 if(!strcmp(dataType.name, "Designer"))
1302 client = ((Designer)client).codeEditor;
1305 // Do this after so the caret isn't moved yet...
1306 client.visible = true;
1310 MenuItem viewPropertiesItem
1312 viewMenu, $"View Properties", p, f4;
1313 bool NotifySelect(MenuItem selection, Modifiers mods)
1315 sheet.visible = true;
1316 sheet.sheetSelected = properties;
1321 MenuItem viewMethodsItem
1323 viewMenu, $"View Methods", m, f4;
1324 bool NotifySelect(MenuItem selection, Modifiers mods)
1326 sheet.visible = true;
1327 sheet.sheetSelected = methods;
1332 MenuItem viewToolBoxItem
1334 viewMenu, $"View Toolbox", x, f12;
1335 bool NotifySelect(MenuItem selection, Modifiers mods)
1337 toolBox.visible = true;
1342 MenuItem viewOutputItem
1344 viewMenu, $"Output", o, alt2;
1345 bool NotifySelect(MenuItem selection, Modifiers mods)
1351 MenuItem viewWatchesItem
1353 viewMenu, $"Watches", w, alt3;
1354 bool NotifySelect(MenuItem selection, Modifiers mods)
1360 MenuItem viewThreadsItem
1362 viewMenu, $"Threads", t, alt4;
1363 bool NotifySelect(MenuItem selection, Modifiers mods)
1369 MenuItem viewBreakpointsItem
1371 viewMenu, $"Breakpoints", b, alt5;
1372 bool NotifySelect(MenuItem selection, Modifiers mods)
1374 breakpointsView.Show();
1378 MenuItem viewCallStackItem
1380 viewMenu, $"Call Stack", s, alt7;
1381 bool NotifySelect(MenuItem selection, Modifiers mods)
1383 callStackView.Show();
1387 MenuItem viewAllDebugViews
1389 viewMenu, $"All Debug Views", a, alt9;
1390 bool NotifySelect(MenuItem selection, Modifiers mods)
1395 callStackView.Show();
1396 breakpointsView.Show();
1400 #ifdef GDB_DEBUG_GUI
1401 MenuDivider { viewMenu };
1402 MenuItem viewGDBItem
1404 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1405 bool NotifySelect(MenuItem selection, Modifiers mods)
1412 MenuDivider { viewMenu };
1413 MenuItem viewColorPicker
1415 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1416 bool NotifySelect(MenuItem selection, Modifiers mods)
1418 ColorPicker colorPicker { master = this };
1419 colorPicker.Modal();
1423 MenuDivider { viewMenu };
1427 viewMenu, "Full Screen", f, checkable = true;
1429 bool NotifySelect(MenuItem selection, Modifiers mods)
1431 app.fullScreen ^= true;
1433 anchor = { 0, 0, 0, 0 };
1438 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1439 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1440 Menu windowMenu { menu, $"Window", w };
1441 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1442 MenuDivider { windowMenu };
1443 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1444 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1445 MenuDivider { windowMenu };
1446 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1447 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1448 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1449 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1450 MenuDivider { windowMenu };
1451 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1452 Menu helpMenu { menu, $"Help", h };
1455 helpMenu, $"API Reference", r, f1;
1456 bool NotifySelect(MenuItem selection, Modifiers mods)
1460 char * p = new char[MAX_LOCATION];
1462 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
1463 PathCat(p, "documentor");
1464 #if defined(__WIN32__)
1465 ChangeExtension(p, "exe", p);
1467 if(!FileExists(p).isFile)
1468 strcpy(p, "documentor");
1470 documentor = DualPipeOpen({ input = true, output = true, showWindow = true }, p);
1475 Process_ShowWindows(documentor.GetProcessID());
1476 // documentor.Puts("Activate\n");
1481 MenuDivider { helpMenu };
1484 helpMenu, $"Ecere Tao of Programming [work in progress]", t;
1485 bool NotifySelect(MenuItem selection, Modifiers mods)
1487 FindAndShellOpenInstalledFile("doc", "Ecere Tao of Programming [work in progress].pdf");
1491 MenuDivider { helpMenu };
1494 helpMenu, $"Documentation Folder", d;
1495 bool NotifySelect(MenuItem selection, Modifiers mods)
1497 FindAndShellOpenInstalledFolder("doc");
1503 helpMenu, $"Samples Folder", s;
1504 bool NotifySelect(MenuItem selection, Modifiers mods)
1506 FindAndShellOpenInstalledFolder("samples");
1512 helpMenu, $"Extras Folder", x;
1513 bool NotifySelect(MenuItem selection, Modifiers mods)
1515 FindAndShellOpenInstalledFolder("extras");
1519 MenuDivider { helpMenu };
1522 helpMenu, $"Community Forums", f;
1523 bool NotifySelect(MenuItem selection, Modifiers mods)
1525 ShellOpen("http://ecere.com/forums");
1529 MenuDivider { helpMenu };
1532 helpMenu, $"About...", a;
1533 bool NotifySelect(MenuItem selection, Modifiers mods)
1535 AboutIDE { master = this }.Modal();
1540 property ToolBox toolBox
1542 get { return toolBox; }
1545 property Sheet sheet
1547 get { return sheet; }
1550 property Project project
1552 get { return projectView ? projectView.project : null; }
1555 property Workspace workspace
1557 get { return projectView ? projectView.workspace : null; }
1560 FindInFilesDialog findInFilesDialog
1563 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1569 #ifdef GDB_DEBUG_GUI
1572 master = this, parent = this;
1573 //anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1575 void OnCommand(char * string)
1578 ide.debugger.SendGDBCommand(string);
1583 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1585 //app.driver = app.drivers[selection.id];
1586 #if defined(__unix__) || defined(__APPLE__)
1587 app.driver = selection.id ? "OpenGL" : "X";
1589 app.driver = selection.id ? "OpenGL" : "GDI";
1591 delete ideSettings.displayDriver;
1592 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1594 settingsContainer.Save();
1595 //SetDriverAndSkin();
1599 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1601 app.skin = app.skins[selection.id];
1606 void SetDriverAndSkin()
1609 for(c = 0; c < app.numSkins; c++)
1610 if(!strcmp(app.skins[c], app.skin))
1612 skinItems[c].checked = true;
1615 for(c = 0; c < app.numDrivers; c++)
1616 if(!strcmp(app.drivers[c], app.driver))
1618 driverItems[c].checked = true;
1623 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1625 Project project = workspace.projects.firstIterator.data;
1626 projectView = ProjectView
1629 fileName = fileName;
1631 void NotifyDestroyed(Window window, DialogResult result)
1634 text = titleECEREIDE;
1639 projectView.Create();
1640 RepositionWindows(false);
1642 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1643 projectView.workspace = workspace;
1644 projectView.project = project;
1645 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1649 ide.breakpointsView.LoadFromWorkspace();
1650 ide.watchesView.LoadFromWorkspace();
1652 findInFilesDialog.projectNodeField.userData = projectView;
1655 char fileName[MAX_LOCATION];
1656 strcpy(fileName, project.topNode.path);
1657 PathCat(fileName, project.topNode.name);
1664 projectView.visible = false;
1665 if((!projectView || projectView.created == false || projectView.Destroy(0)) && MenuWindowCloseAll(null, 0))
1667 if(findInFilesDialog)
1669 char workingDir[MAX_LOCATION];
1670 GetWorkingDir(workingDir, MAX_LOCATION);
1671 findInFilesDialog.SearchStop();
1672 findInFilesDialog.currentDirectory = workingDir;
1674 ideMainFrame.text = titleECEREIDE;
1681 void RepositionWindows(bool expand)
1686 bool inDebugMode = debugger.isActive;
1687 bool callStackVisible = expand ? false : callStackView.visible;
1688 bool threadsVisible = expand ? false : threadsView.visible;
1689 bool watchesVisible = expand ? false : watchesView.visible;
1690 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1691 bool toolBoxVisible = toolBox.visible;
1692 bool outputVisible = expand ? false : outputView.visible;
1693 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1694 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1696 for(child = firstChild; child; child = child.next)
1698 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1699 child._class == class(Sheet) || child._class == class(ProjectView))
1701 Anchor anchor = child.anchor;
1702 anchor.top = topDistance;
1703 anchor.bottom = bottomDistance;
1704 if(child._class == class(CodeEditor) || child._class == class(Designer))
1707 anchor.right = toolBoxVisible ? 150 : 0;
1709 child.anchor = anchor;
1713 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1714 child._class == class(BreakpointsView))
1715 child.visible = false;
1718 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1723 bool ShowCodeEditor()
1726 activeClient.Activate();
1727 else if(projectView)
1729 projectView.visible = true;
1730 projectView.Activate();
1734 sheet.visible = true;
1740 void DocumentSaved(Window document, char * fileName)
1742 ideSettings.AddRecentFile(fileName);
1743 ide.UpdateRecentMenus();
1744 ide.AdjustFileMenus();
1745 settingsContainer.Save();
1748 bool Window::OnFileModified(FileChange fileChange, char * param)
1751 sprintf(temp, $"The document %s was modified by another application.\n"
1752 "Would you like to reload it and lose your changes?", this.fileName);
1753 if(MessageBox { type = yesNo, master = this/*.parent*/,
1754 text = $"Document has been modified", contents = temp }.Modal() == yes)
1756 bool noParsing = (this._class == class(CodeEditor) && ((CodeEditor)this).noParsing) ? true : false;
1757 char * fileName = CopyString(this.fileName);
1758 WindowState state = this.state;
1759 Anchor anchor = this.anchor;
1760 Size size = this.size;
1762 this.modifiedDocument = false;
1764 this = ide.OpenFile(fileName, normal, true, null, no, normal, noParsing);
1767 this.anchor = anchor;
1769 this.SetState(state, true, 0);
1777 void UpdateMakefiles()
1781 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1782 for(prj : workspace.projects)
1783 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1788 void UpdateCompilerConfigs(bool mute)
1790 UpdateToolBarActiveCompilers();
1793 bool silent = mute || (ide.projectView.buildInProgress == none ? false : true);
1794 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1797 projectView.ShowOutputBuildLog(true);
1798 projectView.DisplayCompiler(compiler, false);
1800 for(prj : workspace.projects)
1801 projectView.ProjectPrepareCompiler(prj, compiler, silent);
1806 void UpdateToolBarActiveCompilers()
1808 toolBar.activeCompiler.Clear();
1809 for(compiler : ideSettings.compilerConfigs)
1811 DataRow row = toolBar.activeCompiler.AddString(compiler.name);
1812 if(workspace && workspace.compiler && !strcmp(compiler.name, workspace.compiler))
1813 toolBar.activeCompiler.currentRow = row;
1815 if(!toolBar.activeCompiler.currentRow && toolBar.activeCompiler.firstRow)
1816 toolBar.activeCompiler.SelectRow(toolBar.activeCompiler.firstRow);
1819 void UpdateToolBarActiveConfigs(bool selectionOnly)
1821 bool commonSelected = false;
1822 DataRow row = toolBar.activeConfig.currentRow;
1824 row = toolBar.activeConfig.FindRow(1);
1827 toolBar.activeConfig.Clear();
1828 row = toolBar.activeConfig.AddString($"(Mixed)");
1833 char * configName = null;
1836 Map<String, int> configs { }; // TOIMP: just need sort but using map until containers have sort
1837 for(prj : workspace.projects)
1839 for(cfg : prj.configurations)
1842 configs[cfg.name] = 1;
1847 toolBar.activeConfig.AddString(&name);
1851 if(projectView && projectView.project)
1853 for(prj : workspace.projects)
1855 if(prj.config && prj.config.name)
1857 configName = prj.config.name;
1863 commonSelected = true;
1864 for(prj : workspace.projects)
1866 if(prj.config && (!prj.config.name || strcmp(prj.config.name, configName)))
1868 commonSelected = false;
1876 commonSelected = false;
1877 for(row = toolBar.activeConfig.firstRow; row; row = row.next)
1879 if(!strcmp(row.string, configName))
1881 toolBar.activeConfig.currentRow = row;
1882 commonSelected = true;
1889 toolBar.activeConfig.Sort(null, 0);
1891 toolBar.activeConfig.currentRow = row;
1896 bool unavailable = !project;
1898 projectAddItem.disabled = unavailable;
1899 toolBar.buttonAddProject.disabled = unavailable;
1901 projectSettingsItem.disabled = unavailable;
1903 projectBrowseFolderItem.disabled = unavailable;
1905 viewProjectItem.disabled = unavailable;
1907 toolBar.activeConfig.disabled = unavailable;
1908 toolBar.activeCompiler.disabled = unavailable;
1909 toolBar.activeBitDepth.disabled = unavailable;
1912 debugUseValgrindItem.disabled = unavailable;
1913 AdjustValgrindMenus();
1922 void AdjustValgrindMenus()
1924 bool unavailable = !project || !debugUseValgrindItem.checked;
1925 debugValgrindNoLeakCheckItem.disabled = unavailable;
1926 debugValgrindSummaryLeakCheckItem.disabled = unavailable;
1927 debugValgrindYesLeakCheckItem.disabled = unavailable;
1928 debugValgrindFullLeakCheckItem.disabled = unavailable;
1930 debugValgrindTrackOriginsItem.disabled = unavailable;
1932 debugValgrindRS0Item.disabled = unavailable;
1933 debugValgrindRS16Item.disabled = unavailable;
1934 debugValgrindRS32Item.disabled = unavailable;
1935 debugValgrindRS64Item.disabled = unavailable;
1936 debugValgrindRS128Item.disabled = unavailable;
1937 debugValgrindRS256Item.disabled = unavailable;
1938 debugValgrindRS512Item.disabled = unavailable;
1942 property bool hasOpenedCodeEditors
1947 for(w = firstChild; w; w = w.next)
1948 if(w._class == class(CodeEditor) &&
1949 w.isDocument && !w.closing && w.visible && w.created &&
1950 w.fileName && w.fileName[0])
1956 void AdjustFileMenus()
1958 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1960 projectQuickItem.disabled = unavailable;
1963 void AdjustBuildMenus()
1965 bool unavailable = project && projectView.buildInProgress;
1966 bool naForRun = unavailable || !project || project.GetTargetType(project.config) != executable;
1968 projectNewItem.disabled = unavailable;
1969 toolBar.buttonNewProject.disabled = unavailable;
1970 projectOpenItem.disabled = unavailable;
1971 toolBar.buttonOpenProject.disabled = unavailable;
1973 unavailable = !project || projectView.buildInProgress;
1975 projectCloseItem.disabled = unavailable;
1976 // toolBar.buttonCloseProject.disabled = unavailable;
1978 projectRunItem.disabled = naForRun;
1979 toolBar.buttonRun.disabled = naForRun;
1981 projectBuildItem.disabled = false;
1982 projectBuildItem.text = unavailable ? $"Stop Build" : $"Build";
1983 projectBuildItem.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
1985 projectLinkItem.disabled = unavailable;
1986 toolBar.buttonReLink.disabled = unavailable;
1987 projectRebuildItem.disabled = unavailable;
1988 toolBar.buttonRebuild.disabled = unavailable;
1989 projectCleanItem.disabled = unavailable;
1990 toolBar.buttonClean.disabled = unavailable;
1991 projectCleanTargetItem.disabled = unavailable;
1992 projectRealCleanItem.disabled = unavailable;
1993 // toolBar.buttonRealClean.disabled = unavailable;
1994 projectRegenerateItem.disabled = unavailable;
1995 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1996 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
1997 projectInstallItem.disabled = unavailable;
1998 toolBar.buttonInstall.disabled = unavailable;
2000 projectCompileItem.disabled = unavailable;
2002 AdjustPopupBuildMenus();
2005 void AdjustPopupBuildMenus()
2007 bool unavailable = !project || projectView.buildInProgress;
2009 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
2012 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0);
2015 menu.disabled = false;
2016 menu.text = unavailable ? $"Stop Build" : $"Build";
2017 menu.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
2020 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
2021 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
2022 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectCleanTarget, 0); if(menu) menu.disabled = unavailable;
2023 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
2024 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
2025 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
2026 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, 0); if(menu) menu.disabled = unavailable;
2027 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
2028 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
2029 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
2030 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
2031 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
2032 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
2033 projectView.popupMenu.Update(null);
2037 property bool areDebugMenusUnavailable { get {
2039 project.GetTargetType(project.config) != executable ||
2040 projectView.buildInProgress == buildingMainProject;
2043 property bool isBreakpointTogglingUnavailable { get {
2047 property bool isDebuggerExecuting { get {
2051 return ide.debugger.state == running;
2054 void AdjustDebugMenus()
2056 bool unavailable = areDebugMenusUnavailable;
2057 bool active = debugger.isActive;
2058 bool bpNoToggle = isBreakpointTogglingUnavailable;
2059 bool executing = isDebuggerExecuting;
2060 //bool holding = debugger.state == stopped;
2062 debugStartResumeItem.disabled = unavailable || executing;
2063 debugStartResumeItem.text = active ? $"Resume" : $"Start";
2064 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
2067 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
2068 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
2071 debugBreakItem.disabled = unavailable || !executing;
2072 debugStopItem.disabled = unavailable || !active;
2073 debugRestartItem.disabled = unavailable || !active;
2076 toolBar.buttonDebugPause.disabled = unavailable || !executing;
2077 toolBar.buttonDebugStop.disabled = unavailable || !active;
2078 toolBar.buttonDebugRestart.disabled = unavailable || !active;
2081 debugStepIntoItem.disabled = unavailable || executing;
2082 debugStepOverItem.disabled = unavailable || executing;
2083 debugStepOutItem.disabled = unavailable || executing || !active;
2084 debugSkipStepOverItem.disabled = unavailable || executing;
2085 debugSkipStepOutItem.disabled = unavailable || executing || !active;
2088 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
2089 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
2090 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
2091 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
2092 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
2094 if((Designer)GetActiveDesigner())
2096 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
2098 codeEditor.AdjustDebugMenus(unavailable, bpNoToggle, executing);
2102 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
2104 char tempString[MAX_LOCATION];
2105 strcpy(tempString, directory);
2106 if(saveSettings && !projectView)
2108 ideSettings.ideFileDialogLocation = directory;
2109 settingsContainer.Save();
2112 ideFileDialog.currentDirectory = tempString;
2113 codeEditorFileDialog.currentDirectory = tempString;
2114 codeEditorFormFileDialog.currentDirectory = tempString;
2117 void ChangeProjectFileDialogDirectory(char * directory)
2119 ideSettings.ideProjectFileDialogLocation = directory;
2120 settingsContainer.Save();
2123 Window FindWindow(char * filePath)
2125 Window document = null;
2127 // TOCHECK: Do we need to change slashes here?
2128 for(document = firstChild; document; document = document.next)
2130 char * fileName = document.fileName;
2131 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
2133 document.visible = true;
2134 document.Activate();
2141 bool DontTerminateDebugSession(char * title)
2143 if(debugger.isActive)
2145 if(MessageBox { type = yesNo, master = ide,
2146 contents = $"Do you want to terminate the debugging session in progress?",
2147 text = title }.Modal() == no)
2150 MessageBox msg { type = yesNo, master = ide,
2151 contents = "Do you want to terminate the debugging session in progress?",
2153 if(msg.Modal() == no)
2165 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod, bool noParsing)
2167 char extension[MAX_EXTENSION] = "";
2168 Window document = null;
2169 bool isProject = false;
2170 bool needFileModified = true;
2171 char winFilePath[MAX_LOCATION];
2172 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
2176 GetExtension(filePath, extension);
2180 strcpy(extension, type);
2182 if(strcmp(extension, ProjectExtension))
2184 for(document = firstChild; document; document = document.next)
2186 char * fileName = document.fileName;
2187 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
2189 document.visible = true;
2191 document.Activate();
2197 if(createIfFails == whatever)
2199 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
2201 needFileModified = false;
2202 if(openMethod == normal)
2204 if(DontTerminateDebugSession($"Open Project"))
2214 Workspace workspace = null;
2216 if(FileExists(filePath))
2218 if(!strcmp(extension, ProjectExtension))
2220 char workspaceFile[MAX_LOCATION];
2221 strcpy(workspaceFile, filePath);
2222 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
2223 workspace = LoadWorkspace(workspaceFile, filePath);
2225 else if(!strcmp(extension, WorkspaceExtension))
2226 workspace = LoadWorkspace(filePath, null);
2229 //project = LoadProject(filePath, null);
2234 char absolutePath[MAX_LOCATION];
2235 CreateProjectView(workspace, filePath);
2236 document = projectView;
2238 workspace.DropInvalidBreakpoints();
2241 ide.projectView.ShowOutputBuildLog(true);
2243 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2244 ide.projectView.DisplayCompiler(compiler, false);
2247 UpdateCompilerConfigs(false);
2250 char newWorkingDir[MAX_LOCATION];
2251 StripLastDirectory(filePath, newWorkingDir);
2252 ChangeFileDialogsDirectory(newWorkingDir, false);
2255 document.fileName = filePath;
2257 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
2259 // this crashes on starting ide with epj file, solution please?
2260 // app.UpdateDisplay();
2262 workspace.holdTracking = true;
2263 for(ofi : workspace.openedFiles)
2265 if(ofi.state != closed)
2267 Window file = OpenFile(ofi.path, normal, true, null, no, normal, noParsing);
2270 char fileName[MAX_LOCATION];
2272 GetLastDirectory(ofi.path, fileName);
2273 node = projectView.project.topNode.Find(fileName, true);
2275 node.EnsureVisible();
2279 ide.RepositionWindows(false);
2280 workspace.holdTracking = false;
2282 workspace.timer.Start();
2284 findInFilesDialog.mode = FindInFilesMode::project;
2285 findInFilesDialog.currentDirectory = ide.project.topNode.path;
2288 char location[MAX_LOCATION];
2289 StripLastDirectory(ide.project.topNode.path, location);
2290 ChangeProjectFileDialogDirectory(location);
2294 if(projectView.debugger)
2295 projectView.debugger.EvaluateWatches();
2302 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
2304 ideProjectFileDialog.text = openProjectFileDialogTitle;
2305 if(ideProjectFileDialog.Modal() == cancel)
2307 filePath = ideProjectFileDialog.filePath;
2308 GetExtension(filePath, extension);
2319 else if(openMethod == add)
2324 char slashFilePath[MAX_LOCATION];
2325 GetSlashPathBuffer(slashFilePath, filePath);
2326 for(p : workspace.projects)
2328 if(!fstrcmp(p.filePath, slashFilePath))
2336 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
2337 contents = $"This project is already present in workspace." }.Modal();
2341 prj = LoadProject(filePath, null);
2344 char * activeConfigName = null;
2345 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
2346 prj.StartMonitoring();
2347 workspace.projects.Add(prj);
2348 if(toolBar.activeConfig.currentRow && toolBar.activeConfig.currentRow != toolBar.activeConfig.firstRow &&
2349 toolBar.activeConfig.currentRow.string && toolBar.activeConfig.currentRow.string[0])
2350 activeConfigName = toolBar.activeConfig.currentRow.string;
2351 if(activeConfigName)
2353 for(cfg : prj.configurations)
2355 if(cfg.name && !strcmp(cfg.name, activeConfigName))
2363 projectView.AddNode(prj.topNode, null);
2364 workspace.modified = true;
2366 findInFilesDialog.AddProjectItem(prj);
2367 projectView.ShowOutputBuildLog(true);
2368 projectView.DisplayCompiler(compiler, false);
2369 projectView.ProjectUpdateMakefileForAllConfigs(prj);
2373 char location[MAX_LOCATION];
2374 StripLastDirectory(prj.topNode.path, location);
2375 ChangeProjectFileDialogDirectory(location);
2378 // projectView is associated with the main project and not with the one just added but
2379 return projectView; // just to let the caller know something was opened
2387 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2388 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2389 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2391 if(FileExists(filePath))
2392 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2393 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2394 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2397 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2400 else if(!strcmp(extension, "3ds"))
2402 if(FileExists(filePath))
2403 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2404 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2405 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2409 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2412 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2413 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2414 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2415 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2416 !strcmp(extension, "js"))
2418 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2419 editor.updatingCode = true;
2420 if(editor.LoadFile(filePath))
2423 editor.visible = true;
2427 needFileModified = false;
2431 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2432 if(editor.LoadFile(filePath))
2435 editor.visible = true;
2439 needFileModified = false;
2442 if(document && (document._class == class(PictureEdit) ||
2443 document._class == class(ModelView)))
2448 document.fileName = filePath;
2449 if(workspace && !workspace.holdTracking)
2450 workspace.UpdateOpenedFileInfo(filePath, opened);
2454 if(!document && createIfFails != no)
2456 if(createIfFails != yes && !needFileModified &&
2457 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2458 createIfFails = yes;
2459 if(createIfFails == yes || createIfFails == whatever)
2461 document = (Window)NewCodeEditor(this, state, true);
2463 document.fileName = filePath;
2469 if(projectView && document._class == class(CodeEditor) && workspace)
2471 int lineNumber, position;
2473 CodeEditor editor = (CodeEditor)document;
2474 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2475 editor.openedFileInfo.holdTracking = true;
2476 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2477 position = Max(editor.openedFileInfo.position - 1, 0);
2478 editor.editBox.GoToLineNum(lineNumber);
2479 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2480 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2481 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2482 editor.editBox.scroll = scroll;
2483 editor.openedFileInfo.holdTracking = false;
2486 if(needFileModified)
2487 document.OnFileModified = OnFileModified;
2488 document.NotifySaved = DocumentSaved;
2491 ideSettings.AddRecentProject(document.fileName);
2493 ideSettings.AddRecentFile(document.fileName);
2494 ide.UpdateRecentMenus();
2495 ide.AdjustFileMenus();
2496 settingsContainer.Save();
2504 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2505 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2507 if(!parentClosing && ide.workspace)
2508 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2511 bool ModelView::ModelViewOnClose(bool parentClosing)
2513 if(!parentClosing && ide.workspace)
2514 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2517 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2519 if(!parentClosing && ide.workspace)
2520 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2525 void OnUnloadGraphics(Window window)
2527 display.ClearMaterials();
2528 display.ClearTextures();
2529 display.ClearMeshes();
2533 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2535 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2536 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2540 bool OnKeyDown(Key key, unichar ch)
2545 projectView.Update(null);
2548 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2551 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2557 void GoToError(const char * line, bool noParsing)
2560 projectView.GoToError(line, noParsing);
2563 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2567 char *colon = strchr(text, ':');
2568 char filePath[MAX_LOCATION] = "";
2569 char completePath[MAX_LOCATION];
2570 int line = 0, col = 0;
2571 int len = strlen(text);
2573 FileAttribs fileAttribs;
2575 // support for valgrind output
2576 if((s = strstr(text, "==")) && (s = strstr(s+2, "==")) && (s = strstr(s+2, ":")) && (s = strstr(s+1, ":")))
2587 /*for(s=colon; *s; s++)
2596 //line = atoi(colon+1);
2598 // support for "Found n match(es) in "file/path";
2599 else if(path[len-1] == '\"' && strstr(path, $"Found %d match%s in \"%s\"%s\n\n"."Found") && strstr(path, $"match") && strstr(path, $"in") && (s = strstr(path, "\"")) && s != path+len-1)
2605 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2607 path = (colon - 1 > path) ? colon - 1 : path;
2608 colon = strstr(colon + 1, ":");
2610 if(*path == '*' && (s = strchr(path+1, '*')))
2612 while(isspace(*path)) path++;
2616 char * close = strchr(path, ')');
2620 strncpy(name, path+1, close - path - 1);
2621 name[close - path - 1] = '\0';
2622 for(p : ide.workspace.projects)
2624 if(!strcmp(p.name, name))
2634 prj = project ? project : (dir ? null : ide.project);
2637 strncpy(filePath, path, colon - path);
2638 filePath[colon - path] = '\0';
2639 line = atoi(colon + 1);
2640 colon = strstr(colon + 1, ":");
2642 col = atoi(colon + 1);
2644 else if(path - 1 >= text && *(path - 1) == '\"')
2646 colon = strchr(path, '\"');
2649 strncpy(filePath, path, colon - path);
2650 filePath[colon - path] = '\0';
2653 else if(path && !colon)
2655 strcpy(filePath, path);
2661 strcpy(completePath, prj.topNode.path);
2662 else if(dir && dir[0])
2663 strcpy(completePath, dir);
2665 completePath[0] = '\0';
2666 PathCat(completePath, filePath);
2668 if((fileAttribs = FileExists(completePath)))
2669 CodeLocationGoTo(completePath, fileAttribs, line, col);
2670 else if(ide.workspace)
2673 for(p : ide.workspace.projects)
2675 strcpy(completePath, p.topNode.path);
2676 PathCat(completePath, filePath);
2677 if((fileAttribs = FileExists(completePath)).isFile)
2679 CodeLocationGoTo(completePath, fileAttribs, line, col);
2686 for(p : ide.workspace.projects)
2688 ProjectNode node = p.topNode.Find(filePath, false);
2691 node.GetFullFilePath(completePath);
2692 if((fileAttribs = FileExists(completePath)).isFile)
2694 CodeLocationGoTo(completePath, fileAttribs, line, col);
2704 void CodeLocationGoTo(const char * path, const FileAttribs fileAttribs, int line, int col)
2706 if(fileAttribs.isFile)
2708 char ext[MAX_EXTENSION];
2709 GetExtension(path, ext);
2710 if(!strcmp(ext, "mp3") || !strcmp(ext, "flac") || !strcmp(ext, "ogg") || !strcmp(ext, "avi") || !strcmp(ext, "mkv"))
2712 else if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") || !strcmp(ext, "dll") || !strcmp(ext, "exe"))
2714 char dirPath[MAX_LOCATION];
2715 StripLastDirectory(path, dirPath);
2720 CodeEditor codeEditor = (CodeEditor)OpenFile(path, normal, true, ext, no, normal, false);
2721 if(codeEditor && line)
2723 EditBox editBox = codeEditor.editBox;
2724 editBox.GoToLineNum(line - 1);
2725 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2729 else if(fileAttribs.isDirectory)
2733 void OnRedraw(Surface surface)
2735 Bitmap bitmap = back.bitmap;
2737 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2740 void SheetSelected(SheetType sheetSelected)
2742 if(activeChild == sheet)
2744 if(sheetSelected == methods)
2746 viewPropertiesItem.accelerator = f4;
2747 viewPropertiesItem.parent = viewMenu;
2748 viewMethodsItem.parent = null;
2752 viewMethodsItem.accelerator = f4;
2753 viewMethodsItem.parent = viewMenu;
2754 viewPropertiesItem.parent = null;
2759 viewMethodsItem.parent = viewMenu;
2760 viewPropertiesItem.parent = viewMenu;
2761 if(sheetSelected == methods)
2763 viewMethodsItem.accelerator = f4;
2764 viewPropertiesItem.accelerator = 0;
2768 viewMethodsItem.accelerator = 0;
2769 viewPropertiesItem.accelerator = f4;
2774 void OnActivateClient(Window client, Window previous)
2776 //if(!client || client != previous)
2779 if(!client || client != previous)
2782 dataType = previous._class;
2783 if(previous && !strcmp(dataType.name, "CodeEditor"))
2785 ((CodeEditor)previous).UpdateFormCode();
2787 else if(previous && !strcmp(dataType.name, "Designer"))
2789 ((Designer)previous).codeEditor.UpdateFormCode();
2794 dataType = client._class;
2795 if(client && !strcmp(dataType.name, "CodeEditor"))
2797 CodeEditor codeEditor = (CodeEditor)client;
2798 SetPrivateModule(codeEditor.privateModule);
2799 SetCurrentContext(codeEditor.globalContext);
2800 SetTopContext(codeEditor.globalContext);
2801 SetGlobalContext(codeEditor.globalContext);
2803 SetDefines(&codeEditor.defines);
2804 SetImports(&codeEditor.imports);
2806 SetActiveDesigner(codeEditor.designer);
2808 sheet.codeEditor = codeEditor;
2809 toolBox.codeEditor = codeEditor;
2811 viewDesignerItem.parent = viewMenu;
2812 if(activeChild != codeEditor)
2814 viewCodeItem.parent = viewMenu;
2815 viewDesignerItem.accelerator = 0;
2816 viewCodeItem.accelerator = f8;
2820 viewCodeItem.parent = null;
2821 viewDesignerItem.accelerator = f8;
2824 else if(client && !strcmp(dataType.name, "Designer"))
2826 CodeEditor codeEditor = ((Designer)client).codeEditor;
2829 SetPrivateModule(codeEditor.privateModule);
2830 SetCurrentContext(codeEditor.globalContext);
2831 SetTopContext(codeEditor.globalContext);
2832 SetGlobalContext(codeEditor.globalContext);
2833 SetDefines(&codeEditor.defines);
2834 SetImports(&codeEditor.imports);
2838 SetPrivateModule(null);
2839 SetCurrentContext(null);
2840 SetTopContext(null);
2841 SetGlobalContext(null);
2846 SetActiveDesigner((Designer)client);
2848 sheet.codeEditor = codeEditor;
2849 toolBox.codeEditor = codeEditor;
2851 viewCodeItem.parent = viewMenu;
2852 if(activeChild != client)
2854 viewDesignerItem.parent = viewMenu;
2855 viewDesignerItem.accelerator = f8;
2856 viewCodeItem.accelerator = 0;
2860 viewDesignerItem.parent = null;
2861 viewCodeItem.accelerator = f8;
2867 sheet.codeEditor = null;
2868 toolBox.codeEditor = null;
2869 SetActiveDesigner(null);
2871 viewDesignerItem.parent = null;
2872 viewCodeItem.parent = null;
2875 SheetSelected(sheet.sheetSelected);
2878 projectCompileItem = null;
2883 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2885 CodeEditor codeEditor = (CodeEditor)client;
2886 EditBox editBox = codeEditor.editBox;
2888 statusBar.AddField(pos);
2890 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2891 statusBar.AddField(caps);
2893 ovr = { width = 30, text = $"OVR", color = (editBox && editBox.overwrite) ? black : Color { 128, 128, 128 } };
2894 statusBar.AddField(ovr);
2896 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2897 statusBar.AddField(num);
2899 //statusBar.text = "Ready";
2901 if(projectView && projectView.project)
2903 bool isCObject = false;
2904 ProjectNode node = projectView.GetNodeFromWindow(client, null, false);
2905 if(!node && (node = projectView.GetNodeFromWindow(client, null, true)))
2909 char nodeName[MAX_FILENAME];
2910 char name[MAX_FILENAME+96];
2912 ChangeExtension(node.name, "c", nodeName);
2913 sprintf(name, $"Compile %s", isCObject ? nodeName : node.name);
2914 projectCompileItem =
2916 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2918 bool NotifySelect(MenuItem selection, Modifiers mods)
2922 bool result = false;
2923 bool isCObject = false;
2924 ProjectNode node = null;
2925 for(p : ide.workspace.projects)
2927 node = projectView.GetNodeFromWindow(activeClient, p, false);
2930 if(!node && (node = projectView.GetNodeFromWindow(activeClient, null, true)))
2934 List<ProjectNode> nodes { };
2936 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, isCObject ? cObject : normal);
2941 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2946 projectMenu.AddDynamic(projectCompileItem, ide, false);
2952 caps = ovr = num = null;
2957 bool OnClose(bool parentClosing)
2959 //return !projectView.buildInProgress;
2960 if(projectView && projectView.buildInProgress)
2962 if(DontTerminateDebugSession($"Close IDE"))
2964 if(findInFilesDialog)
2965 findInFilesDialog.SearchStop();
2968 workspace.timer.Stop();
2971 ideMainFrame.Destroy(0);
2978 bool passThrough = false;
2979 bool debugStart = false;
2980 bool debugWorkDir = false;
2981 char * passDebugWorkDir = null;
2982 bool openAsText = false;
2983 DynamicString passArgs { };
2986 for(c = 1; c<app.argc; c++)
2990 char * arg = app.argv[c];
2991 char * buf = new char[strlen(arg)*2+1];
2993 passArgs.concat(" ");
2995 passArgs.concat(buf);
2998 else if(debugWorkDir)
3000 passDebugWorkDir = CopyString(app.argv[c]);
3001 StripQuotes(passDebugWorkDir, passDebugWorkDir);
3002 debugWorkDir = false;
3004 else if(!strcmp(app.argv[c], "-t"))
3006 else if(!strcmp(app.argv[c], "-no-parsing"))
3007 ide.noParsing = true;
3008 else if(!strcmp(app.argv[c], "-debug-start"))
3010 else if(!strcmp(app.argv[c], "-debug-work-dir"))
3011 debugWorkDir = true;
3012 else if(!strcmp(app.argv[c], "-@"))
3016 char fullPath[MAX_LOCATION];
3017 char parentPath[MAX_LOCATION];
3018 char ext[MAX_EXTENSION];
3020 FileAttribs dirAttribs;
3021 GetWorkingDir(fullPath, MAX_LOCATION);
3022 PathCat(fullPath, app.argv[c]);
3023 StripLastDirectory(fullPath, parentPath);
3024 GetExtension(app.argv[c], ext);
3025 isProject = !openAsText && !strcmpi(ext, "epj");
3027 if(isProject && c > (debugStart ? 2 : 1)) continue;
3029 // Create directory for projects (only)
3030 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
3032 if(isProject && !FileExists(fullPath))
3034 char name[MAX_LOCATION];
3035 NewProjectDialog newProjectDialog;
3039 projectView.visible = false;
3040 if(!projectView.Destroy(0))
3044 newProjectDialog = { master = this };
3046 strcpy(name, app.argv[c]);
3047 StripExtension(name);
3048 GetLastDirectory(name, name);
3049 newProjectDialog.projectName.contents = name;
3050 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
3051 newProjectDialog.locationEditBox.path = parentPath;
3052 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
3054 incref newProjectDialog;
3055 newProjectDialog.Modal();
3058 ideSettings.AddRecentProject(projectView.fileName);
3059 ide.UpdateRecentMenus();
3060 settingsContainer.Save();
3062 delete newProjectDialog;
3063 // Open only one project
3067 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false);
3069 else if(strstr(fullPath, "http://") == fullPath)
3070 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false);
3073 if(passThrough && projectView && projectView.project && workspace)
3074 workspace.commandLineArgs = passArgs;
3075 if(passDebugWorkDir && projectView && projectView.project && workspace)
3077 workspace.debugDir = passDebugWorkDir;
3078 delete passDebugWorkDir;
3081 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
3083 UpdateToolBarActiveConfigs(false);
3084 UpdateToolBarActiveCompilers();
3091 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
3094 projectView.visible = false;
3095 projectView.Destroy(0);
3098 #ifdef GDB_DEBUG_GUI
3099 gdbDialog.Destroy(0);
3104 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config, int bitDepth)
3108 char * oldPaths[128];
3109 String oldList = new char[maxPathLen];
3110 Array<String> newExePaths { };
3111 //Map<String, bool> exePathExists { };
3113 #if defined(__unix__) || defined(__APPLE__)
3114 Array<String> newLibPaths { };
3115 Map<String, bool> libPathExists { };
3120 for(prj : workspace.projects)
3122 DirExpression targetDirExp;
3124 // SKIP FIRST PROJECT...
3125 if(prj == workspace.projects.firstIterator.data) continue;
3127 // NOTE: Right now the additional project config dir will be
3128 // obtained when the debugger is started, so toggling it
3129 // while building will change which library gets used.
3130 // To go with the initial state, e.g. when F5 was pressed,
3131 // we nould need to keep a list of all project's active
3132 // config upon startup.
3133 targetDirExp = prj.GetTargetDir(compiler, prj.config, bitDepth);
3135 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
3139 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3140 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
3144 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3145 if(cfg.targetType == sharedLibrary && cfg.debug)
3149 if(targetDirExp.dir)
3151 char buffer[MAX_LOCATION];
3152 #if defined(__WIN32__)
3153 Array<String> paths = newExePaths;
3155 Array<String> paths = newLibPaths;
3157 GetSystemPathBuffer(buffer, prj.topNode.path);
3158 PathCat(buffer, targetDirExp.dir);
3161 if(!fstrcmp(p, buffer))
3168 paths.Add(CopyString(buffer));
3170 delete targetDirExp;
3174 for(item : compiler.executableDirs)
3177 for(p : newExePaths)
3179 if(!fstrcmp(p, item))
3186 newExePaths.Add(CopySystemPath(item));
3189 GetEnvironment("PATH", oldList, maxPathLen);
3191 printf("Old value of PATH: %s\n", oldList);
3193 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3194 for(c = 0; c < count; c++)
3197 for(p : newExePaths)
3199 if(!fstrcmp(p, oldPaths[c]))
3206 newExePaths.Add(CopySystemPath(oldPaths[c]));
3210 for(path : newExePaths)
3211 len += strlen(path) + 1;
3212 newList = new char[len + 1];
3214 for(path : newExePaths)
3216 strcat(newList, path);
3217 strcat(newList, pathListSep);
3219 newList[len - 1] = '\0';
3220 SetEnvironment("PATH", newList);
3222 printf("New value of PATH: %s\n", newList);
3229 #if defined(__unix__) || defined(__APPLE__)
3231 for(item : compiler.libraryDirs)
3233 if(!libPathExists[item]) // fstrcmp should be used
3235 String s = CopyString(item);
3237 libPathExists[s] = true;
3241 #if defined(__APPLE__)
3242 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
3244 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
3247 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
3249 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3250 for(c = 0; c < count; c++)
3252 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
3254 String s = CopyString(oldPaths[c]);
3256 libPathExists[s] = true;
3261 for(path : newLibPaths)
3262 len += strlen(path) + 1;
3263 newList = new char[len + 1];
3265 for(path : newLibPaths)
3267 strcat(newList, path);
3268 strcat(newList, pathListSep);
3270 newList[len - 1] = '\0';
3271 #if defined(__APPLE__)
3272 SetEnvironment("DYLD_LIBRARY_PATH", newList);
3274 SetEnvironment("LD_LIBRARY_PATH", newList);
3277 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
3283 delete libPathExists;
3286 if(compiler.distccEnabled && compiler.distccHosts)
3287 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
3292 void DestroyTemporaryProjectDir()
3294 if(tmpPrjDir && tmpPrjDir[0])
3296 if(FileExists(tmpPrjDir).isDirectory)
3297 DestroyDir(tmpPrjDir);
3298 property::tmpPrjDir = null;
3304 // Graphics Driver Menu
3308 app.currentSkin.selectionColor = selectionColor;
3309 app.currentSkin.selectionText = selectionText;
3313 driverItems = new MenuItem[app.numDrivers];
3314 for(c = 0; c < app.numDrivers; c++)
3316 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
3317 driverItems[c].id = c;
3318 driverItems[c].isRadio = true;
3321 driverItems = new MenuItem[2];
3322 #if defined(__unix__)
3323 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
3324 driverItems[0].id = 0;
3325 driverItems[0].isRadio = true;
3327 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
3328 driverItems[0].id = 0;
3329 driverItems[0].isRadio = true;
3331 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
3332 driverItems[1].id = 1;
3333 driverItems[1].isRadio = true;
3335 /* skinItems = new MenuItem[app.numSkins];
3336 for(c = 0; c < app.numSkins; c++)
3338 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
3339 skinItems[c].id = c;
3340 skinItems[c].isRadio = true;
3343 ideFileDialog.master = this;
3344 ideProjectFileDialog.master = this;
3346 //SetDriverAndSkin();
3350 void UpdateRecentMenus()
3353 Menu fileMenu = menu.FindMenu($"File");
3354 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
3355 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
3356 char * itemPath = new char[MAX_LOCATION];
3357 char * itemName = new char[MAX_LOCATION+4];
3360 recentFiles.Clear();
3363 for(recent : ideSettings.recentFiles)
3365 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3366 MakeSystemPath(itemPath);
3367 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3368 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
3372 recentProjects.Clear();
3374 for(recent : ideSettings.recentProjects)
3376 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3377 MakeSystemPath(itemPath);
3378 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3379 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
3394 documentor.Puts("Quit\n");
3401 void DestroyDir(char * path)
3403 RecursiveDeleteFolderFSI fsi { };
3408 #if defined(__WIN32__)
3409 define sdkDirName = "Ecere SDK";
3411 define sdkDirName = "ecere";
3414 void FindAndShellOpenInstalledFolder(char * name)
3416 char * p = new char[MAX_LOCATION];
3417 char * v = new char[maxPathLen];
3420 Array<String> paths { };
3422 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3423 StripLastDirectory(p, p);
3425 paths.Add(CopyString(p));
3426 #if defined(__WIN32__)
3427 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3430 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3431 PathCat(p, name); paths.Add(CopyString(p));
3433 GetEnvironment("AppData", v, maxPathLen);
3436 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3437 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3439 GetEnvironment("ProgramFiles", v, maxPathLen);
3442 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3443 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3445 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3448 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3449 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3451 GetEnvironment("SystemDrive", v, maxPathLen);
3454 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3455 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3458 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3459 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3460 for(c=0; c<numTokens; c++)
3462 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3463 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3468 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3469 if(FileExists(p).isDirectory)
3481 void FindAndShellOpenInstalledFile(char * subdir, char * name)
3483 char * p = new char[MAX_LOCATION];
3484 char * v = new char[maxPathLen];
3487 Array<String> paths { };
3489 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3490 paths.Add(CopyString(p));
3491 StripLastDirectory(p, p);
3493 paths.Add(CopyString(p));
3494 #if defined(__WIN32__)
3495 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3498 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3499 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3501 GetEnvironment("AppData", v, maxPathLen);
3504 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3505 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3507 GetEnvironment("ProgramFiles", v, maxPathLen);
3510 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3511 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3513 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3516 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3517 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3519 GetEnvironment("SystemDrive", v, maxPathLen);
3522 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3523 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3526 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3527 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3528 for(c=0; c<numTokens; c++)
3530 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3531 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3536 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3538 if(FileExists(p).isFile)
3550 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
3552 bool preserveRootFolder;
3554 void OutFolder(char * folderPath, bool isRoot)
3556 if(!(preserveRootFolder && isRoot))
3557 RemoveDir(folderPath);
3560 bool OnFile(char * filePath)
3562 DeleteFile(filePath);
3567 class IDEApp : GuiApplication
3569 //driver = "Win32Console";
3570 // driver = "OpenGL";
3574 TempFile includeFile { };
3578 char ext[MAX_EXTENSION];
3579 SetLoggingMode(stdOut, null);
3580 //SetLoggingMode(debug, null);
3582 settingsContainer.Load();
3583 if(argc > 1 && !strcmpi(GetExtension(argv[1], ext), "3ds"))
3585 app.driver = "OpenGL";
3586 ide.driverItems[1].checked = true;
3590 #if defined(__unix__) || defined(__APPLE__)
3591 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
3593 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
3595 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
3600 desktop.text = titleECEREIDE;
3603 for(c = 1; c<app.argc; c++)
3605 char fullPath[MAX_LOCATION];
3606 GetWorkingDir(fullPath, MAX_LOCATION);
3607 PathCat(fullPath, app.argv[c]);
3608 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal, false);
3612 if(!LoadIncludeFile())
3613 PrintLn("error: unable to load :crossplatform.mk file inside ide binary.");
3618 bool Cycle(bool idle)
3622 if(ide.documentor.Peek())
3625 ide.documentor.GetLine(line, sizeof(line));
3626 if(!strcmpi(line, "Exited"))
3627 delete ide.documentor;
3629 if(ide.documentor && ide.documentor.eof)
3630 delete ide.documentor;
3635 bool LoadIncludeFile()
3637 bool result = false;
3638 File include = FileOpen(":crossplatform.mk", read);
3641 File f = includeFile;
3644 for(; !include.Eof(); )
3647 int count = include.Read(buffer, 1, 4096);
3648 f.Write(buffer, 1, count);
3658 IDEMainFrame ideMainFrame { };
3660 define app = ((IDEApp)__thisModule);
3662 define titleECEREIDE = $"ECERE IDE (Debug)";
3664 define titleECEREIDE = $"ECERE IDE";