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)
286 for(prj : ide.workspace.projects)
288 for(cfg : prj.configurations)
290 if(cfg.name && !strcmp(cfg.name, row.string))
297 ide.UpdateToolBarActiveConfigs(true);
298 ide.projectView.Update(null);
304 Window spacer6 { this, size = { 4 } };
306 DropBox activeCompiler
308 this, toolTip = $"Active Compiler", size = { 160 }, disabled = true;
309 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
311 if(ide.workspace && ide.projectView && row && strcmp(row.string, ide.workspace.compiler))
313 bool silent = ide.projectView.buildInProgress == none ? false : true;
314 CompilerConfig compiler = ideSettings.GetCompilerConfig(row.string);
315 ide.workspace.compiler = row.string;
316 ide.projectView.ShowOutputBuildLog(!silent);
318 ide.projectView.DisplayCompiler(compiler, false);
319 for(prj : ide.workspace.projects)
320 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
322 ide.workspace.Save();
328 DropBox activeBitDepth
330 this, toolTip = $"Active Bit Depth", size = { 60 }, disabled = true;
331 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
333 if(ide.workspace && ide.projectView && row)
335 bool silent = ide.projectView.buildInProgress == none ? false : true;
336 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
337 ide.workspace.bitDepth = (int)row.tag;
338 ide.projectView.ShowOutputBuildLog(!silent);
340 ide.projectView.DisplayCompiler(compiler, false);
341 for(prj : ide.workspace.projects)
342 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
344 ide.workspace.Save();
350 Window spacer7 { this, size = { 4 } };
355 row = activeBitDepth.AddString("Auto");
357 activeBitDepth.AddString("32 bit").tag = 32;
358 activeBitDepth.AddString("64 bit").tag = 64;
359 activeBitDepth.currentRow = row;
364 class IDEMainFrame : Window
366 background = formColor;
367 borderStyle = sizable;
371 minClientSize = { 600, 300 };
373 icon = { ":icon.png" };
374 text = titleECEREIDE;
378 anchor = { top = 0, right = 0, bottom = 0 };
381 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
388 isActiveClient = true;
390 direction = vertical;
391 background = formColor;
392 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
400 ((IDEWorkSpace)master).toolBar = null;
403 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
406 define ide = ideMainFrame.ideWorkSpace;
408 class IDEWorkSpace : Window
410 background = Color { 85, 85, 85 };
413 hasVertScroll = true;
414 hasHorzScroll = true;
416 isActiveClient = true;
417 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
421 MenuItem * driverItems, * skinItems;
422 StatusField pos { width = 150 };
423 StatusField ovr, caps, num;
425 BitmapResource back { ":ecereBack.jpg", window = this };
426 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
427 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
428 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
429 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
430 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
431 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
432 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
433 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
434 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
435 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
437 Debugger debugger { };
439 ProjectView projectView;
441 OutputView outputView
445 void OnGotoError(char * line, bool noParsing)
447 ide.GoToError(line, noParsing);
450 void OnCodeLocationParseAndGoTo(char * line)
452 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
455 bool OnKeyDown(Key key, unichar ch)
460 if(activeBox != findBox || !ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
461 ide.ShowCodeEditor();
465 OutputView::OnKeyDown(key, ch);
472 bool OnClose(bool parentClosing)
476 ide.RepositionWindows(false);
477 return parentClosing;
481 CallStackView callStackView
483 parent = this, font = { panelFont.faceName, panelFont.size };
485 void OnSelectFrame(int frameIndex)
487 ide.debugger.GoToStackFrameLine(frameIndex, true);
489 ide.debugger.SelectFrame(frameIndex);
492 void OnToggleBreakpoint()
494 Debugger debugger = ide.debugger;
495 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
497 int line = debugger.activeFrame.line;
498 char name[MAX_LOCATION];
500 // TOFIX: Improve on this, don't use only filename, make a function
501 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
502 if(ide && ide.workspace)
504 for(p : ide.workspace.projects)
506 if(p.topNode.Find(name, false))
514 for(p : ide.workspace.projects)
516 if(IsPathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
524 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
527 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
528 if(codeEditor) { codeEditor.Update(null); Activate(); }
533 bool OnKeyDown(Key key, unichar ch)
537 case escape: ide.ShowCodeEditor(); break;
542 bool OnClose(bool parentClosing)
546 ide.RepositionWindows(false);
547 return parentClosing;
550 void OnRedraw(Surface surface)
552 Debugger debugger = ide.debugger;
553 Frame activeFrame = debugger.activeFrame;
557 int lineCursor, lineTopFrame, activeThread, hitThread;
558 int lineH, scrollY, boxH;
560 Breakpoint bp = null;
563 scrollY = editBox.scroll.y;
564 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
565 activeThread = debugger.activeThread;
566 hitThread = debugger.hitThread;
567 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
569 // TODO: improve bp drawing... it should be visible even if it's not on the activeFrame
570 if(activeFrame.absoluteFile)
572 for(i : ide.workspace.breakpoints; i.type == user)
574 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
575 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
576 activeFrame.line == i.line)
584 DrawLineMarginIcon(surface,
585 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
586 lineCursor /*1*/, lineH, scrollY, boxH);
588 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
589 DrawLineMarginIcon(surface,
590 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
591 1, lineH, scrollY, boxH);
593 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
594 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
595 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
597 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
598 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
600 if(editBox.horzScroll && editBox.horzScroll.visible)
602 surface.SetBackground(control);
603 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
608 WatchesView watchesView { parent = this };
609 ThreadsView threadsView
611 parent = this, font = { panelFont.faceName, panelFont.size };
613 bool OnKeyDown(Key key, unichar ch)
617 case escape: ide.ShowCodeEditor(); break;
622 bool OnClose(bool parentClosing)
626 ide.RepositionWindows(false);
627 return parentClosing;
630 void OnSelectThread(int threadId)
633 ide.debugger.SelectThread(threadId);
636 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
639 Debugger debugger = ide.debugger;
640 *activeThread = debugger.activeThread;
641 *hitThread = debugger.hitThread;
642 *signalThread = debugger.signalThread;
647 BreakpointsView breakpointsView { parent = this };
649 ToolBox toolBox { parent = this };
650 Sheet sheet { parent = this };
653 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
655 Menu fileMenu { menu, $"File", f, hasMargin = true };
658 fileMenu, $"New", n, ctrlN;
659 bitmap = { ":actions/docNew.png" };
660 bool NotifySelect(MenuItem selection, Modifiers mods)
662 Window document = (Window)NewCodeEditor(this, normal, false);
663 document.NotifySaved = DocumentSaved;
667 MenuItem fileOpenItem
669 fileMenu, $"Open...", o, ctrlO;
670 bitmap = { ":actions/docOpen.png" };
671 bool NotifySelect(MenuItem selection, Modifiers mods)
673 if(!projectView && ideSettings.ideFileDialogLocation)
674 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
677 if(ideFileDialog.Modal() == ok)
679 bool gotWhatWeWant = false;
681 int numSelections = ideFileDialog.numSelections;
682 char ** multiFilePaths = ideFileDialog.multiFilePaths;
684 for(c = 0; c < numSelections; c++)
686 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift))
687 gotWhatWeWant = true;
690 MessageBox { type = yesNo, master = this, text = $"Error opening file",
691 contents = $"Open a different file?" }.Modal() == no)
693 if(!projectView && gotWhatWeWant)
694 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
695 ide.RepositionWindows(false);
705 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
706 MenuDivider { fileMenu };
707 MenuItem fileSaveItem
709 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
711 // For the toolbar button; clients can still override that for the menu item
712 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
714 Window w = activeClient;
716 w.MenuFileSave(null, 0);
720 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
721 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
722 MenuDivider { fileMenu };
725 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
726 bool NotifySelect(MenuItem selection, Modifiers mods)
728 findInFilesDialog.replaceMode = false;
729 findInFilesDialog.Show();
733 MenuItem replaceInFiles
735 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
736 bool NotifySelect(MenuItem selection, Modifiers mods)
738 findInFilesDialog.replaceMode = true;
739 findInFilesDialog.Show();
743 MenuDivider { fileMenu };
744 MenuItem globalSettingsItem
746 fileMenu, $"Global Settings...", g;
747 bool NotifySelect(MenuItem selection, Modifiers mods)
749 globalSettingsDialog.master = this;
750 if(ide.workspace && ide.workspace.compiler)
751 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
752 else if(ideSettings.defaultCompiler)
753 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
754 globalSettingsDialog.Modal();
758 MenuDivider { fileMenu };
759 Menu recentFiles { fileMenu, $"Recent Files", r };
760 Menu recentProjects { fileMenu, $"Recent Projects", p };
761 MenuDivider { fileMenu };
764 fileMenu, $"Exit", x, altF4;
766 bool NotifySelect(MenuItem selection, Modifiers mods)
768 ideMainFrame.Destroy(0);
773 bool FileRecentFile(MenuItem selection, Modifiers mods)
776 for(file : ideSettings.recentFiles)
778 if(id == selection.id)
781 char extension[MAX_EXTENSION] = "";
782 GetExtension(file, extension);
783 isProjectFile = (!strcmpi(extension, "epj") || !strcmpi(extension, "ews"));
786 char * command = PrintString("ide ", isProjectFile ? "-t " : "", file);
792 OpenFile(file, normal, true, isProjectFile ? "txt" : null, no, normal, mods.ctrl && mods.shift);
793 ide.RepositionWindows(false);
802 bool FileRecentProject(MenuItem selection, Modifiers mods)
805 for(file : ideSettings.recentProjects)
807 if(id == selection.id)
811 char * command = PrintString("ide ", file);
816 OpenFile(file, normal, true, null, no, normal, mods.ctrl && mods.shift);
824 MenuPlacement editMenu { menu, $"Edit", e };
826 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
827 MenuItem projectNewItem
829 projectMenu, $"New...", n, Key { n, true, true };
830 bitmap = { ":actions/projNew.png" };
831 bool NotifySelect(MenuItem selection, Modifiers mods)
833 if(!DontTerminateDebugSession($"New Project"))
836 NewProjectDialog newProjectDialog { master = this };
837 incref newProjectDialog;
838 result = newProjectDialog.Modal();
843 newProjectDialog.CreateNewProject();
846 ideSettings.AddRecentProject(projectView.fileName);
847 ide.UpdateRecentMenus();
848 settingsContainer.Save();
852 delete newProjectDialog;
857 MenuItem projectOpenItem
859 projectMenu, $"Open...", o, Key { o, true, true };
860 bitmap = { ":actions/projOpen.png" };
861 bool NotifySelect(MenuItem selection, Modifiers mods)
863 if(ideSettings.ideProjectFileDialogLocation)
864 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
866 ideProjectFileDialog.text = openProjectFileDialogTitle;
867 if(ideProjectFileDialog.Modal() == ok)
869 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift);
870 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
875 MenuItem projectQuickItem
877 projectMenu, $"Quick...", q, f7, disabled = true;
878 bool NotifySelect(MenuItem selection, Modifiers mods)
881 QuickProjectDialog { this }.Modal();
885 MenuItem projectAddItem
887 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
888 bitmap = { ":actions/projAdd.png" };
890 bool NotifySelect(MenuItem selection, Modifiers mods)
892 if(ideSettings.ideProjectFileDialogLocation)
893 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
895 ideProjectFileDialog.text = addProjectFileDialogTitle;
898 if(ideProjectFileDialog.Modal() == ok)
900 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add, mods.ctrl && mods.shift))
902 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
903 contents = $"Add a different project?" }.Modal() == no)
914 MenuItem projectCloseItem
916 projectMenu, $"Close", c, disabled = true;
917 bool NotifySelect(MenuItem selection, Modifiers mods)
921 if(!ide.DontTerminateDebugSession($"Project Close"))
927 MenuDivider { projectMenu };
928 MenuItem projectSettingsItem
930 projectMenu, $"Settings...", s, altF7, disabled = true;
931 bool NotifySelect(MenuItem selection, Modifiers mods)
933 projectView.MenuSettings(projectView.active ? selection : null, mods);
937 MenuDivider { projectMenu };
938 MenuItem projectBrowseFolderItem
940 projectMenu, $"Browse Project Folder", p, disabled = true;
941 bool NotifySelect(MenuItem selection, Modifiers mods)
944 projectView.MenuBrowseFolder(null, mods);
948 MenuDivider { projectMenu };
949 MenuItem projectRunItem
951 projectMenu, $"Run", r, ctrlF5, disabled = true;
952 bitmap = { ":actions/run.png" };
953 bool NotifySelect(MenuItem selection, Modifiers mods)
956 projectView.Run(null, mods);
960 MenuItem projectBuildItem
962 projectMenu, $"Build", b, f7, disabled = true;
963 bitmap = { ":actions/build.png" };
964 bool NotifySelect(MenuItem selection, Modifiers mods)
968 if(projectView.buildInProgress == none)
969 projectView.ProjectBuild(projectView.active ? selection : null, mods);
971 projectView.stopBuild = true;
976 MenuItem projectLinkItem
978 projectMenu, $"Relink", l, disabled = true;
979 bitmap = { ":actions/relink.png" };
980 bool NotifySelect(MenuItem selection, Modifiers mods)
983 projectView.ProjectLink(projectView.active ? selection : null, mods);
987 MenuItem projectRebuildItem
989 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
990 bitmap = { ":actions/rebuild.png" };
991 bool NotifySelect(MenuItem selection, Modifiers mods)
994 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
998 MenuItem projectCleanTargetItem
1000 projectMenu, $"Clean Target", g, disabled = true;
1001 bitmap = { ":actions/clean.png" };
1002 bool NotifySelect(MenuItem selection, Modifiers mods)
1007 projectView.ProjectCleanTarget(projectView.active ? selection : null, mods);
1012 MenuItem projectCleanItem
1014 projectMenu, $"Clean", e, disabled = true;
1015 bitmap = { ":actions/clean.png" };
1016 bool NotifySelect(MenuItem selection, Modifiers mods)
1021 projectView.ProjectClean(projectView.active ? selection : null, mods);
1026 MenuItem projectRealCleanItem
1028 projectMenu, $"Real Clean", disabled = true;
1029 bitmap = { ":actions/clean.png" };
1030 bool NotifySelect(MenuItem selection, Modifiers mods)
1035 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
1040 MenuItem projectRegenerateItem
1042 projectMenu, $"Regenerate Makefile", m, disabled = true;
1043 bitmap = { ":actions/regMakefile.png" };
1044 bool NotifySelect(MenuItem selection, Modifiers mods)
1047 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
1051 MenuItem projectInstallItem
1053 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
1054 projectMenu, $"Install", t, disabled = true;
1056 bitmap = { ":status/software-update-available.png" };
1057 bool NotifySelect(MenuItem selection, Modifiers mods)
1060 projectView.ProjectInstall(projectView.active ? selection : null, mods);
1064 MenuItem projectCompileItem;
1065 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1066 MenuItem debugStartResumeItem
1068 debugMenu, $"Start", s, f5, disabled = true;
1069 bitmap = { ":actions/debug.png" };
1070 NotifySelect = MenuDebugStart;
1072 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1076 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1077 if(!projectView.DebugStart())
1078 debugStartResumeItem.disabled = false; // same exception
1082 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1085 projectView.DebugResume();
1088 MenuItem debugRestartItem
1090 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1091 bitmap = { ":actions/restart.png" };
1092 bool NotifySelect(MenuItem selection, Modifiers mods)
1095 projectView.DebugRestart();
1099 MenuItem debugBreakItem
1101 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1102 bitmap = { ":actions/pause.png" };
1103 bool NotifySelect(MenuItem selection, Modifiers mods)
1105 if(projectView && projectView.buildInProgress != none)
1108 projectView.DebugBreak();
1112 MenuItem debugStopItem
1114 debugMenu, $"Stop", p, shiftF5, disabled = true;
1115 bitmap = { ":actions/stopDebug.png" };
1116 bool NotifySelect(MenuItem selection, Modifiers mods)
1119 projectView.DebugStop();
1123 MenuDivider { debugMenu };
1124 MenuItem debugUseValgrindItem
1126 debugMenu, $"Use Valgrind", d, disabled = true, checkable = true;
1127 bool NotifySelect(MenuItem selection, Modifiers mods)
1131 ide.workspace.useValgrind = selection.checked;
1132 ide.workspace.Save();
1134 ide.AdjustValgrindChecks();
1138 MenuItem debugValgrindFullLeakCheckItem
1140 debugMenu, $"Valgrind: Full Leak Check", d, disabled = true, checkable = true;
1141 bool NotifySelect(MenuItem selection, Modifiers mods)
1145 ide.workspace.vgFullLeakCheck = selection.checked;
1146 ide.workspace.Save();
1151 MenuDivider { debugMenu };
1152 MenuItem debugStepIntoItem
1154 debugMenu, $"Step Into", i, f11, disabled = true;
1155 bitmap = { ":actions/stepInto.png" };
1156 bool NotifySelect(MenuItem selection, Modifiers mods)
1159 projectView.DebugStepInto();
1163 MenuItem debugStepOverItem
1165 debugMenu, $"Step Over", v, f10, disabled = true;
1166 bitmap = { ":actions/stepOver.png" };
1167 bool NotifySelect(MenuItem selection, Modifiers mods)
1170 projectView.DebugStepOver(false);
1174 MenuItem debugStepOutItem
1176 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1177 bitmap = { ":actions/stepOut.png" };
1178 bool NotifySelect(MenuItem selection, Modifiers mods)
1181 projectView.DebugStepOut(false);
1185 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1186 MenuItem debugSkipStepOverItem
1188 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1189 bool NotifySelect(MenuItem selection, Modifiers mods)
1192 projectView.DebugStepOver(true);
1196 MenuItem debugSkipStepOutItem
1198 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1199 bitmap = { ":actions/skipBreaks.png" };
1200 bool NotifySelect(MenuItem selection, Modifiers mods)
1203 projectView.DebugStepOut(true);
1207 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1208 MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", l };
1209 //MenuDivider { debugMenu };
1210 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1211 MenuPlacement imageMenu { menu, $"Image", i };
1212 Menu viewMenu { menu, $"View", v };
1213 MenuItem viewProjectItem
1215 viewMenu, $"Project View", j, alt0, disabled = true;
1216 bool NotifySelect(MenuItem selection, Modifiers mods)
1220 projectView.visible = true;
1221 projectView.Activate();
1226 MenuPlacement { viewMenu, $"View Designer" };
1227 MenuPlacement { viewMenu, $"View Code" };
1228 MenuPlacement { viewMenu, $"View Properties" };
1229 MenuPlacement { viewMenu, $"View Methods" };
1230 MenuItem viewDesignerItem
1232 viewMenu, $"View Designer", d, f8;
1233 bool NotifySelect(MenuItem selection, Modifiers mods)
1235 Window client = activeClient;
1236 Class dataType = client._class;
1237 if(!strcmp(dataType.name, "Designer"))
1239 client.visible = true;
1243 ((CodeEditor)client).ViewDesigner();
1247 MenuItem viewCodeItem
1249 viewMenu, $"View Code", c, f8;
1250 bool NotifySelect(MenuItem selection, Modifiers mods)
1252 Window client = activeClient;
1253 Class dataType = client._class;
1254 if(!strcmp(dataType.name, "Designer"))
1255 client = ((Designer)client).codeEditor;
1258 // Do this after so the caret isn't moved yet...
1259 client.visible = true;
1263 MenuItem viewPropertiesItem
1265 viewMenu, $"View Properties", p, f4;
1266 bool NotifySelect(MenuItem selection, Modifiers mods)
1268 sheet.visible = true;
1269 sheet.sheetSelected = properties;
1274 MenuItem viewMethodsItem
1276 viewMenu, $"View Methods", m, f4;
1277 bool NotifySelect(MenuItem selection, Modifiers mods)
1279 sheet.visible = true;
1280 sheet.sheetSelected = methods;
1285 MenuItem viewToolBoxItem
1287 viewMenu, $"View Toolbox", x, f12;
1288 bool NotifySelect(MenuItem selection, Modifiers mods)
1290 toolBox.visible = true;
1295 MenuItem viewOutputItem
1297 viewMenu, $"Output", o, alt2;
1298 bool NotifySelect(MenuItem selection, Modifiers mods)
1304 MenuItem viewWatchesItem
1306 viewMenu, $"Watches", w, alt3;
1307 bool NotifySelect(MenuItem selection, Modifiers mods)
1313 MenuItem viewThreadsItem
1315 viewMenu, $"Threads", t, alt4;
1316 bool NotifySelect(MenuItem selection, Modifiers mods)
1322 MenuItem viewBreakpointsItem
1324 viewMenu, $"Breakpoints", b, alt5;
1325 bool NotifySelect(MenuItem selection, Modifiers mods)
1327 breakpointsView.Show();
1331 MenuItem viewCallStackItem
1333 viewMenu, $"Call Stack", s, alt7;
1334 bool NotifySelect(MenuItem selection, Modifiers mods)
1336 callStackView.Show();
1340 MenuItem viewAllDebugViews
1342 viewMenu, $"All Debug Views", a, alt9;
1343 bool NotifySelect(MenuItem selection, Modifiers mods)
1348 callStackView.Show();
1349 breakpointsView.Show();
1353 #ifdef GDB_DEBUG_GUI
1354 MenuDivider { viewMenu };
1355 MenuItem viewGDBItem
1357 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1358 bool NotifySelect(MenuItem selection, Modifiers mods)
1365 MenuDivider { viewMenu };
1366 MenuItem viewColorPicker
1368 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1369 bool NotifySelect(MenuItem selection, Modifiers mods)
1371 ColorPicker colorPicker { master = this };
1372 colorPicker.Modal();
1376 MenuDivider { viewMenu };
1380 viewMenu, "Full Screen", f, checkable = true;
1382 bool NotifySelect(MenuItem selection, Modifiers mods)
1384 app.fullScreen ^= true;
1386 anchor = { 0, 0, 0, 0 };
1391 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1392 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1393 Menu windowMenu { menu, $"Window", w };
1394 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1395 MenuDivider { windowMenu };
1396 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1397 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1398 MenuDivider { windowMenu };
1399 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1400 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1401 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1402 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1403 MenuDivider { windowMenu };
1404 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1405 Menu helpMenu { menu, $"Help", h };
1408 helpMenu, $"API Reference", r, f1;
1409 bool NotifySelect(MenuItem selection, Modifiers mods)
1411 char * p = new char[MAX_LOCATION];
1413 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
1414 PathCat(p, "documentor");
1415 #if defined(__WIN32__)
1416 ChangeExtension(p, "exe", p);
1418 if(FileExists(p).isFile)
1421 Execute("documentor");
1426 MenuDivider { helpMenu };
1429 helpMenu, $"Ecere Tao of Programming [work in progress]", t;
1430 bool NotifySelect(MenuItem selection, Modifiers mods)
1432 FindAndShellOpenInstalledFile("doc", "Ecere Tao of Programming [work in progress].pdf");
1436 MenuDivider { helpMenu };
1439 helpMenu, $"Documentation Folder", d;
1440 bool NotifySelect(MenuItem selection, Modifiers mods)
1442 FindAndShellOpenInstalledFolder("doc");
1448 helpMenu, $"Samples Folder", s;
1449 bool NotifySelect(MenuItem selection, Modifiers mods)
1451 FindAndShellOpenInstalledFolder("samples");
1457 helpMenu, $"Extras Folder", x;
1458 bool NotifySelect(MenuItem selection, Modifiers mods)
1460 FindAndShellOpenInstalledFolder("extras");
1464 MenuDivider { helpMenu };
1467 helpMenu, $"Community Forums", f;
1468 bool NotifySelect(MenuItem selection, Modifiers mods)
1470 ShellOpen("http://ecere.com/forums");
1474 MenuDivider { helpMenu };
1477 helpMenu, $"About...", a;
1478 bool NotifySelect(MenuItem selection, Modifiers mods)
1480 AboutIDE { master = this }.Modal();
1485 property ToolBox toolBox
1487 get { return toolBox; }
1490 property Sheet sheet
1492 get { return sheet; }
1495 property Project project
1497 get { return projectView ? projectView.project : null; }
1500 property Workspace workspace
1502 get { return projectView ? projectView.workspace : null; }
1505 FindInFilesDialog findInFilesDialog
1508 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1514 #ifdef GDB_DEBUG_GUI
1517 master = this, parent = this;
1518 //anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1520 void OnCommand(char * string)
1523 ide.debugger.SendGDBCommand(string);
1528 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1530 //app.driver = app.drivers[selection.id];
1531 #if defined(__unix__) || defined(__APPLE__)
1532 app.driver = selection.id ? "OpenGL" : "X";
1534 app.driver = selection.id ? "OpenGL" : "GDI";
1536 delete ideSettings.displayDriver;
1537 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1539 settingsContainer.Save();
1540 //SetDriverAndSkin();
1544 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1546 app.skin = app.skins[selection.id];
1551 void SetDriverAndSkin()
1554 for(c = 0; c < app.numSkins; c++)
1555 if(!strcmp(app.skins[c], app.skin))
1557 skinItems[c].checked = true;
1560 for(c = 0; c < app.numDrivers; c++)
1561 if(!strcmp(app.drivers[c], app.driver))
1563 driverItems[c].checked = true;
1568 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1570 Project project = workspace.projects.firstIterator.data;
1571 projectView = ProjectView
1574 fileName = fileName;
1576 void NotifyDestroyed(Window window, DialogResult result)
1579 text = titleECEREIDE;
1584 projectView.Create();
1585 RepositionWindows(false);
1587 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1588 projectView.workspace = workspace;
1589 projectView.project = project;
1590 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1594 ide.breakpointsView.LoadFromWorkspace();
1595 ide.watchesView.LoadFromWorkspace();
1597 findInFilesDialog.projectNodeField.userData = projectView;
1600 char fileName[MAX_LOCATION];
1601 strcpy(fileName, project.topNode.path);
1602 PathCat(fileName, project.topNode.name);
1609 projectView.visible = false;
1610 if((!projectView || projectView.created == false || projectView.Destroy(0)) && MenuWindowCloseAll(null, 0))
1612 if(findInFilesDialog)
1614 char workingDir[MAX_LOCATION];
1615 GetWorkingDir(workingDir, MAX_LOCATION);
1616 findInFilesDialog.SearchStop();
1617 findInFilesDialog.currentDirectory = workingDir;
1619 ideMainFrame.text = titleECEREIDE;
1626 void RepositionWindows(bool expand)
1631 bool inDebugMode = debugger.isActive;
1632 bool callStackVisible = expand ? false : callStackView.visible;
1633 bool threadsVisible = expand ? false : threadsView.visible;
1634 bool watchesVisible = expand ? false : watchesView.visible;
1635 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1636 bool toolBoxVisible = toolBox.visible;
1637 bool outputVisible = expand ? false : outputView.visible;
1638 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1639 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1641 for(child = firstChild; child; child = child.next)
1643 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1644 child._class == class(Sheet) || child._class == class(ProjectView))
1646 Anchor anchor = child.anchor;
1647 anchor.top = topDistance;
1648 anchor.bottom = bottomDistance;
1649 if(child._class == class(CodeEditor) || child._class == class(Designer))
1652 anchor.right = toolBoxVisible ? 150 : 0;
1654 child.anchor = anchor;
1658 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1659 child._class == class(BreakpointsView))
1660 child.visible = false;
1663 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1668 bool ShowCodeEditor()
1671 activeClient.Activate();
1672 else if(projectView)
1674 projectView.visible = true;
1675 projectView.Activate();
1679 sheet.visible = true;
1685 void DocumentSaved(Window document, char * fileName)
1687 ideSettings.AddRecentFile(fileName);
1688 ide.UpdateRecentMenus();
1689 ide.AdjustFileMenus();
1690 settingsContainer.Save();
1693 bool Window::OnFileModified(FileChange fileChange, char * param)
1696 sprintf(temp, $"The document %s was modified by another application.\n"
1697 "Would you like to reload it and lose your changes?", this.fileName);
1698 if(MessageBox { type = yesNo, master = this/*.parent*/,
1699 text = $"Document has been modified", contents = temp }.Modal() == yes)
1701 bool noParsing = (this._class == class(CodeEditor) && ((CodeEditor)this).noParsing) ? true : false;
1702 char * fileName = CopyString(this.fileName);
1703 WindowState state = this.state;
1704 Anchor anchor = this.anchor;
1705 Size size = this.size;
1707 this.modifiedDocument = false;
1709 this = ide.OpenFile(fileName, normal, true, null, no, normal, noParsing);
1712 this.anchor = anchor;
1714 this.SetState(state, true, 0);
1722 void UpdateMakefiles()
1726 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1727 for(prj : workspace.projects)
1728 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1733 void UpdateCompilerConfigs(bool mute)
1735 UpdateToolBarActiveCompilers();
1738 bool silent = mute || (ide.projectView.buildInProgress == none ? false : true);
1739 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1742 projectView.ShowOutputBuildLog(true);
1743 projectView.DisplayCompiler(compiler, false);
1745 for(prj : workspace.projects)
1746 projectView.ProjectPrepareCompiler(prj, compiler, silent);
1751 void UpdateToolBarActiveCompilers()
1753 toolBar.activeCompiler.Clear();
1754 for(compiler : ideSettings.compilerConfigs)
1756 DataRow row = toolBar.activeCompiler.AddString(compiler.name);
1757 if(workspace && workspace.compiler && !strcmp(compiler.name, workspace.compiler))
1758 toolBar.activeCompiler.currentRow = row;
1760 if(!toolBar.activeCompiler.currentRow && toolBar.activeCompiler.firstRow)
1761 toolBar.activeCompiler.SelectRow(toolBar.activeCompiler.firstRow);
1764 void UpdateToolBarActiveConfigs(bool selectionOnly)
1766 bool commonSelected = false;
1767 DataRow row = toolBar.activeConfig.currentRow;
1769 row = toolBar.activeConfig.FindRow(1);
1772 toolBar.activeConfig.Clear();
1773 row = toolBar.activeConfig.AddString($"(Mixed)");
1778 char * configName = null;
1781 Map<String, int> configs { }; // TOIMP: just need sort but using map until containers have sort
1782 for(prj : workspace.projects)
1784 for(cfg : prj.configurations)
1787 configs[cfg.name] = 1;
1792 toolBar.activeConfig.AddString(&name);
1796 if(projectView && projectView.project)
1798 for(prj : workspace.projects)
1800 if(prj.config && prj.config.name)
1802 configName = prj.config.name;
1808 commonSelected = true;
1809 for(prj : workspace.projects)
1811 if(prj.config && (!prj.config.name || strcmp(prj.config.name, configName)))
1813 commonSelected = false;
1821 commonSelected = false;
1822 for(row = toolBar.activeConfig.firstRow; row; row = row.next)
1824 if(!strcmp(row.string, configName))
1826 toolBar.activeConfig.currentRow = row;
1827 commonSelected = true;
1834 toolBar.activeConfig.Sort(null, 0);
1836 toolBar.activeConfig.currentRow = row;
1841 bool unavailable = !project;
1843 projectAddItem.disabled = unavailable;
1844 toolBar.buttonAddProject.disabled = unavailable;
1846 projectSettingsItem.disabled = unavailable;
1848 projectBrowseFolderItem.disabled = unavailable;
1850 viewProjectItem.disabled = unavailable;
1852 toolBar.activeConfig.disabled = unavailable;
1853 toolBar.activeCompiler.disabled = unavailable;
1854 toolBar.activeBitDepth.disabled = unavailable;
1855 debugUseValgrindItem.disabled = unavailable;
1857 AdjustValgrindChecks();
1863 void AdjustValgrindChecks()
1865 bool unavailable = !project || !debugUseValgrindItem.checked;
1866 debugValgrindFullLeakCheckItem.disabled = unavailable;
1869 property bool hasOpenedCodeEditors
1874 for(w = firstChild; w; w = w.next)
1875 if(w._class == class(CodeEditor) &&
1876 w.isDocument && !w.closing && w.visible && w.created &&
1877 w.fileName && w.fileName[0])
1883 void AdjustFileMenus()
1885 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1887 projectQuickItem.disabled = unavailable;
1890 void AdjustBuildMenus()
1892 bool unavailable = project && projectView.buildInProgress;
1893 bool naForRun = unavailable || !project || project.GetTargetType(project.config) != executable;
1895 projectNewItem.disabled = unavailable;
1896 toolBar.buttonNewProject.disabled = unavailable;
1897 projectOpenItem.disabled = unavailable;
1898 toolBar.buttonOpenProject.disabled = unavailable;
1900 unavailable = !project || projectView.buildInProgress;
1902 projectCloseItem.disabled = unavailable;
1903 // toolBar.buttonCloseProject.disabled = unavailable;
1905 projectRunItem.disabled = naForRun;
1906 toolBar.buttonRun.disabled = naForRun;
1908 projectBuildItem.disabled = false;
1909 projectBuildItem.text = unavailable ? $"Stop Build" : $"Build";
1910 projectBuildItem.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
1912 projectLinkItem.disabled = unavailable;
1913 toolBar.buttonReLink.disabled = unavailable;
1914 projectRebuildItem.disabled = unavailable;
1915 toolBar.buttonRebuild.disabled = unavailable;
1916 projectCleanItem.disabled = unavailable;
1917 toolBar.buttonClean.disabled = unavailable;
1918 projectCleanTargetItem.disabled = unavailable;
1919 projectRealCleanItem.disabled = unavailable;
1920 // toolBar.buttonRealClean.disabled = unavailable;
1921 projectRegenerateItem.disabled = unavailable;
1922 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1923 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
1924 projectInstallItem.disabled = unavailable;
1925 toolBar.buttonInstall.disabled = unavailable;
1927 projectCompileItem.disabled = unavailable;
1929 AdjustPopupBuildMenus();
1932 void AdjustPopupBuildMenus()
1934 bool unavailable = !project || projectView.buildInProgress;
1936 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1939 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0);
1942 menu.disabled = false;
1943 menu.text = unavailable ? $"Stop Build" : $"Build";
1944 menu.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
1947 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1948 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1949 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectCleanTarget, 0); if(menu) menu.disabled = unavailable;
1950 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1951 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1952 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1953 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, 0); if(menu) menu.disabled = unavailable;
1954 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
1955 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
1956 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
1957 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
1958 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
1959 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
1960 projectView.popupMenu.Update(null);
1964 property bool areDebugMenusUnavailable { get {
1966 project.GetTargetType(project.config) != executable ||
1967 projectView.buildInProgress == buildingMainProject;
1970 property bool isBreakpointTogglingUnavailable { get {
1974 property bool isDebuggerExecuting { get {
1978 return ide.debugger.state == running;
1981 void AdjustDebugMenus()
1983 bool unavailable = areDebugMenusUnavailable;
1984 bool active = debugger.isActive;
1985 bool bpNoToggle = isBreakpointTogglingUnavailable;
1986 bool executing = isDebuggerExecuting;
1987 //bool holding = debugger.state == stopped;
1989 debugStartResumeItem.disabled = unavailable || executing;
1990 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1991 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1994 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1995 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1998 debugBreakItem.disabled = unavailable || !executing;
1999 debugStopItem.disabled = unavailable || !active;
2000 debugRestartItem.disabled = unavailable || !active;
2003 toolBar.buttonDebugPause.disabled = unavailable || !executing;
2004 toolBar.buttonDebugStop.disabled = unavailable || !active;
2005 toolBar.buttonDebugRestart.disabled = unavailable || !active;
2008 debugStepIntoItem.disabled = unavailable || executing;
2009 debugStepOverItem.disabled = unavailable || executing;
2010 debugStepOutItem.disabled = unavailable || executing || !active;
2011 debugSkipStepOverItem.disabled = unavailable || executing;
2012 debugSkipStepOutItem.disabled = unavailable || executing || !active;
2015 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
2016 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
2017 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
2018 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
2019 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
2021 if((Designer)GetActiveDesigner())
2023 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
2025 codeEditor.AdjustDebugMenus(unavailable, bpNoToggle, executing);
2029 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
2031 char tempString[MAX_LOCATION];
2032 strcpy(tempString, directory);
2033 if(saveSettings && !projectView)
2035 ideSettings.ideFileDialogLocation = directory;
2036 settingsContainer.Save();
2039 ideFileDialog.currentDirectory = tempString;
2040 codeEditorFileDialog.currentDirectory = tempString;
2041 codeEditorFormFileDialog.currentDirectory = tempString;
2044 void ChangeProjectFileDialogDirectory(char * directory)
2046 ideSettings.ideProjectFileDialogLocation = directory;
2047 settingsContainer.Save();
2050 Window FindWindow(char * filePath)
2052 Window document = null;
2054 // TOCHECK: Do we need to change slashes here?
2055 for(document = firstChild; document; document = document.next)
2057 char * fileName = document.fileName;
2058 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
2060 document.visible = true;
2061 document.Activate();
2068 bool DontTerminateDebugSession(char * title)
2070 if(debugger.isActive)
2072 if(MessageBox { type = yesNo, master = ide,
2073 contents = $"Do you want to terminate the debugging session in progress?",
2074 text = title }.Modal() == no)
2077 MessageBox msg { type = yesNo, master = ide,
2078 contents = "Do you want to terminate the debugging session in progress?",
2080 if(msg.Modal() == no)
2092 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod, bool noParsing)
2094 char extension[MAX_EXTENSION] = "";
2095 Window document = null;
2096 bool isProject = false;
2097 bool needFileModified = true;
2098 char winFilePath[MAX_LOCATION];
2099 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
2103 GetExtension(filePath, extension);
2107 strcpy(extension, type);
2109 if(strcmp(extension, ProjectExtension))
2111 for(document = firstChild; document; document = document.next)
2113 char * fileName = document.fileName;
2114 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
2116 document.visible = true;
2118 document.Activate();
2124 if(createIfFails == whatever)
2126 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
2128 needFileModified = false;
2129 if(openMethod == normal)
2131 if(DontTerminateDebugSession($"Open Project"))
2141 Workspace workspace = null;
2143 if(FileExists(filePath))
2145 if(!strcmp(extension, ProjectExtension))
2147 char workspaceFile[MAX_LOCATION];
2148 strcpy(workspaceFile, filePath);
2149 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
2150 workspace = LoadWorkspace(workspaceFile, filePath);
2152 else if(!strcmp(extension, WorkspaceExtension))
2153 workspace = LoadWorkspace(filePath, null);
2156 //project = LoadProject(filePath, null);
2161 char absolutePath[MAX_LOCATION];
2162 CreateProjectView(workspace, filePath);
2163 document = projectView;
2165 workspace.DropInvalidBreakpoints();
2168 ide.projectView.ShowOutputBuildLog(true);
2170 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2171 ide.projectView.DisplayCompiler(compiler, false);
2174 UpdateCompilerConfigs(false);
2177 char newWorkingDir[MAX_LOCATION];
2178 StripLastDirectory(filePath, newWorkingDir);
2179 ChangeFileDialogsDirectory(newWorkingDir, false);
2182 document.fileName = filePath;
2184 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
2186 // this crashes on starting ide with epj file, solution please?
2187 // app.UpdateDisplay();
2189 workspace.holdTracking = true;
2190 for(ofi : workspace.openedFiles)
2192 if(ofi.state != closed)
2194 Window file = OpenFile(ofi.path, normal, true, null, no, normal, noParsing);
2197 char fileName[MAX_LOCATION];
2199 GetLastDirectory(ofi.path, fileName);
2200 node = projectView.project.topNode.Find(fileName, true);
2202 node.EnsureVisible();
2206 ide.RepositionWindows(false);
2207 workspace.holdTracking = false;
2209 workspace.timer.Start();
2211 findInFilesDialog.mode = FindInFilesMode::project;
2212 findInFilesDialog.currentDirectory = ide.project.topNode.path;
2215 char location[MAX_LOCATION];
2216 StripLastDirectory(ide.project.topNode.path, location);
2217 ChangeProjectFileDialogDirectory(location);
2221 if(projectView.debugger)
2222 projectView.debugger.EvaluateWatches();
2229 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
2231 ideProjectFileDialog.text = openProjectFileDialogTitle;
2232 if(ideProjectFileDialog.Modal() == cancel)
2234 filePath = ideProjectFileDialog.filePath;
2235 GetExtension(filePath, extension);
2246 else if(openMethod == add)
2251 char slashFilePath[MAX_LOCATION];
2252 GetSlashPathBuffer(slashFilePath, filePath);
2253 for(p : workspace.projects)
2255 if(!fstrcmp(p.filePath, slashFilePath))
2263 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
2264 contents = $"This project is already present in workspace." }.Modal();
2268 prj = LoadProject(filePath, null);
2271 char * activeConfigName = null;
2272 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
2273 prj.StartMonitoring();
2274 workspace.projects.Add(prj);
2275 if(toolBar.activeConfig.currentRow && toolBar.activeConfig.currentRow != toolBar.activeConfig.firstRow &&
2276 toolBar.activeConfig.currentRow.string && toolBar.activeConfig.currentRow.string[0])
2277 activeConfigName = toolBar.activeConfig.currentRow.string;
2278 if(activeConfigName)
2280 for(cfg : prj.configurations)
2282 if(cfg.name && !strcmp(cfg.name, activeConfigName))
2290 projectView.AddNode(prj.topNode, null);
2291 workspace.modified = true;
2293 findInFilesDialog.AddProjectItem(prj);
2294 projectView.ShowOutputBuildLog(true);
2295 projectView.DisplayCompiler(compiler, false);
2296 projectView.ProjectUpdateMakefileForAllConfigs(prj);
2300 char location[MAX_LOCATION];
2301 StripLastDirectory(prj.topNode.path, location);
2302 ChangeProjectFileDialogDirectory(location);
2305 // projectView is associated with the main project and not with the one just added but
2306 return projectView; // just to let the caller know something was opened
2314 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2315 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2316 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2318 if(FileExists(filePath))
2319 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2320 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2321 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2324 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2327 else if(!strcmp(extension, "3ds"))
2329 if(FileExists(filePath))
2330 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2331 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2332 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2336 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2339 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2340 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2341 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2342 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2343 !strcmp(extension, "js"))
2345 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2346 editor.updatingCode = true;
2347 if(editor.LoadFile(filePath))
2350 editor.visible = true;
2354 needFileModified = false;
2358 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2359 if(editor.LoadFile(filePath))
2362 editor.visible = true;
2366 needFileModified = false;
2369 if(document && (document._class == class(PictureEdit) ||
2370 document._class == class(ModelView)))
2375 document.fileName = filePath;
2376 if(workspace && !workspace.holdTracking)
2377 workspace.UpdateOpenedFileInfo(filePath, opened);
2381 if(!document && createIfFails != no)
2383 if(createIfFails != yes && !needFileModified &&
2384 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2385 createIfFails = yes;
2386 if(createIfFails == yes || createIfFails == whatever)
2388 document = (Window)NewCodeEditor(this, state, true);
2390 document.fileName = filePath;
2396 if(projectView && document._class == class(CodeEditor) && workspace)
2398 int lineNumber, position;
2400 CodeEditor editor = (CodeEditor)document;
2401 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2402 editor.openedFileInfo.holdTracking = true;
2403 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2404 position = Max(editor.openedFileInfo.position - 1, 0);
2405 editor.editBox.GoToLineNum(lineNumber);
2406 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2407 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2408 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2409 editor.editBox.scroll = scroll;
2410 editor.openedFileInfo.holdTracking = false;
2413 if(needFileModified)
2414 document.OnFileModified = OnFileModified;
2415 document.NotifySaved = DocumentSaved;
2418 ideSettings.AddRecentProject(document.fileName);
2420 ideSettings.AddRecentFile(document.fileName);
2421 ide.UpdateRecentMenus();
2422 ide.AdjustFileMenus();
2423 settingsContainer.Save();
2431 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2432 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2434 if(!parentClosing && ide.workspace)
2435 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2438 bool ModelView::ModelViewOnClose(bool parentClosing)
2440 if(!parentClosing && ide.workspace)
2441 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2444 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2446 if(!parentClosing && ide.workspace)
2447 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2452 void OnUnloadGraphics(Window window)
2454 display.ClearMaterials();
2455 display.ClearTextures();
2456 display.ClearMeshes();
2460 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2462 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2463 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2467 bool OnKeyDown(Key key, unichar ch)
2472 projectView.Update(null);
2475 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2478 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2484 void GoToError(const char * line, bool noParsing)
2487 projectView.GoToError(line, noParsing);
2490 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2494 char *colon = strchr(text, ':');
2495 char filePath[MAX_LOCATION] = "";
2496 char completePath[MAX_LOCATION];
2497 int line = 0, col = 0;
2498 int len = strlen(text);
2500 FileAttribs fileAttribs;
2502 // support for valgrind output
2503 if((s = strstr(text, "==")) && (s = strstr(s+2, "==")) && (s = strstr(s+2, ":")) && (s = strstr(s+1, ":")))
2514 /*for(s=colon; *s; s++)
2523 //line = atoi(colon+1);
2525 // support for "Found n match(es) in "file/path";
2526 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)
2532 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2534 path = (colon - 1 > path) ? colon - 1 : path;
2535 colon = strstr(colon + 1, ":");
2537 if(*path == '*' && (s = strchr(path+1, '*')))
2539 while(isspace(*path)) path++;
2543 char * close = strchr(path, ')');
2547 strncpy(name, path+1, close - path - 1);
2548 name[close - path - 1] = '\0';
2549 for(p : ide.workspace.projects)
2551 if(!strcmp(p.name, name))
2561 prj = project ? project : (dir ? null : ide.project);
2564 strncpy(filePath, path, colon - path);
2565 filePath[colon - path] = '\0';
2566 line = atoi(colon + 1);
2567 colon = strstr(colon + 1, ":");
2569 col = atoi(colon + 1);
2571 else if(path - 1 >= text && *(path - 1) == '\"')
2573 colon = strchr(path, '\"');
2576 strncpy(filePath, path, colon - path);
2577 filePath[colon - path] = '\0';
2580 else if(path && !colon)
2582 strcpy(filePath, path);
2588 strcpy(completePath, prj.topNode.path);
2589 else if(dir && dir[0])
2590 strcpy(completePath, dir);
2592 completePath[0] = '\0';
2593 PathCat(completePath, filePath);
2595 if((fileAttribs = FileExists(completePath)))
2596 CodeLocationGoTo(completePath, fileAttribs, line, col);
2597 else if(ide.workspace)
2600 for(p : ide.workspace.projects)
2602 strcpy(completePath, p.topNode.path);
2603 PathCat(completePath, filePath);
2604 if((fileAttribs = FileExists(completePath)).isFile)
2606 CodeLocationGoTo(completePath, fileAttribs, line, col);
2613 for(p : ide.workspace.projects)
2615 ProjectNode node = p.topNode.Find(filePath, false);
2618 node.GetFullFilePath(completePath);
2619 if((fileAttribs = FileExists(completePath)).isFile)
2621 CodeLocationGoTo(completePath, fileAttribs, line, col);
2631 void CodeLocationGoTo(const char * path, const FileAttribs fileAttribs, int line, int col)
2633 if(fileAttribs.isFile)
2635 char ext[MAX_EXTENSION];
2636 GetExtension(path, ext);
2637 if(!strcmp(ext, "mp3") || !strcmp(ext, "flac") || !strcmp(ext, "ogg") || !strcmp(ext, "avi") || !strcmp(ext, "mkv"))
2639 else if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") || !strcmp(ext, "dll") || !strcmp(ext, "exe"))
2641 char dirPath[MAX_LOCATION];
2642 StripLastDirectory(path, dirPath);
2647 CodeEditor codeEditor = (CodeEditor)OpenFile(path, normal, true, ext, no, normal, false);
2648 if(codeEditor && line)
2650 EditBox editBox = codeEditor.editBox;
2651 editBox.GoToLineNum(line - 1);
2652 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2656 else if(fileAttribs.isDirectory)
2660 void OnRedraw(Surface surface)
2662 Bitmap bitmap = back.bitmap;
2664 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2667 void SheetSelected(SheetType sheetSelected)
2669 if(activeChild == sheet)
2671 if(sheetSelected == methods)
2673 viewPropertiesItem.accelerator = f4;
2674 viewPropertiesItem.parent = viewMenu;
2675 viewMethodsItem.parent = null;
2679 viewMethodsItem.accelerator = f4;
2680 viewMethodsItem.parent = viewMenu;
2681 viewPropertiesItem.parent = null;
2686 viewMethodsItem.parent = viewMenu;
2687 viewPropertiesItem.parent = viewMenu;
2688 if(sheetSelected == methods)
2690 viewMethodsItem.accelerator = f4;
2691 viewPropertiesItem.accelerator = 0;
2695 viewMethodsItem.accelerator = 0;
2696 viewPropertiesItem.accelerator = f4;
2701 void OnActivateClient(Window client, Window previous)
2703 //if(!client || client != previous)
2706 if(!client || client != previous)
2709 dataType = previous._class;
2710 if(previous && !strcmp(dataType.name, "CodeEditor"))
2712 ((CodeEditor)previous).UpdateFormCode();
2714 else if(previous && !strcmp(dataType.name, "Designer"))
2716 ((Designer)previous).codeEditor.UpdateFormCode();
2721 dataType = client._class;
2722 if(client && !strcmp(dataType.name, "CodeEditor"))
2724 CodeEditor codeEditor = (CodeEditor)client;
2725 SetPrivateModule(codeEditor.privateModule);
2726 SetCurrentContext(codeEditor.globalContext);
2727 SetTopContext(codeEditor.globalContext);
2728 SetGlobalContext(codeEditor.globalContext);
2730 SetDefines(&codeEditor.defines);
2731 SetImports(&codeEditor.imports);
2733 SetActiveDesigner(codeEditor.designer);
2735 sheet.codeEditor = codeEditor;
2736 toolBox.codeEditor = codeEditor;
2738 viewDesignerItem.parent = viewMenu;
2739 if(activeChild != codeEditor)
2741 viewCodeItem.parent = viewMenu;
2742 viewDesignerItem.accelerator = 0;
2743 viewCodeItem.accelerator = f8;
2747 viewCodeItem.parent = null;
2748 viewDesignerItem.accelerator = f8;
2751 else if(client && !strcmp(dataType.name, "Designer"))
2753 CodeEditor codeEditor = ((Designer)client).codeEditor;
2756 SetPrivateModule(codeEditor.privateModule);
2757 SetCurrentContext(codeEditor.globalContext);
2758 SetTopContext(codeEditor.globalContext);
2759 SetGlobalContext(codeEditor.globalContext);
2760 SetDefines(&codeEditor.defines);
2761 SetImports(&codeEditor.imports);
2765 SetPrivateModule(null);
2766 SetCurrentContext(null);
2767 SetTopContext(null);
2768 SetGlobalContext(null);
2773 SetActiveDesigner((Designer)client);
2775 sheet.codeEditor = codeEditor;
2776 toolBox.codeEditor = codeEditor;
2778 viewCodeItem.parent = viewMenu;
2779 if(activeChild != client)
2781 viewDesignerItem.parent = viewMenu;
2782 viewDesignerItem.accelerator = f8;
2783 viewCodeItem.accelerator = 0;
2787 viewDesignerItem.parent = null;
2788 viewCodeItem.accelerator = f8;
2794 sheet.codeEditor = null;
2795 toolBox.codeEditor = null;
2796 SetActiveDesigner(null);
2798 viewDesignerItem.parent = null;
2799 viewCodeItem.parent = null;
2802 SheetSelected(sheet.sheetSelected);
2805 projectCompileItem = null;
2810 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2812 CodeEditor codeEditor = (CodeEditor)client;
2813 EditBox editBox = codeEditor.editBox;
2815 statusBar.AddField(pos);
2817 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2818 statusBar.AddField(caps);
2820 ovr = { width = 30, text = $"OVR", color = (editBox && editBox.overwrite) ? black : Color { 128, 128, 128 } };
2821 statusBar.AddField(ovr);
2823 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2824 statusBar.AddField(num);
2826 //statusBar.text = "Ready";
2828 if(projectView && projectView.project)
2830 bool isCObject = false;
2831 ProjectNode node = projectView.GetNodeFromWindow(client, null, false);
2832 if(!node && (node = projectView.GetNodeFromWindow(client, null, true)))
2836 char nodeName[MAX_FILENAME];
2837 char name[MAX_FILENAME+96];
2839 ChangeExtension(node.name, "c", nodeName);
2840 sprintf(name, $"Compile %s", isCObject ? nodeName : node.name);
2841 projectCompileItem =
2843 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2845 bool NotifySelect(MenuItem selection, Modifiers mods)
2849 bool result = false;
2850 bool isCObject = false;
2851 ProjectNode node = null;
2852 for(p : ide.workspace.projects)
2854 node = projectView.GetNodeFromWindow(activeClient, p, false);
2857 if(!node && (node = projectView.GetNodeFromWindow(activeClient, null, true)))
2861 List<ProjectNode> nodes { };
2863 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, isCObject ? cObject : normal);
2868 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2873 projectMenu.AddDynamic(projectCompileItem, ide, false);
2879 caps = ovr = num = null;
2884 bool OnClose(bool parentClosing)
2886 //return !projectView.buildInProgress;
2887 if(projectView && projectView.buildInProgress)
2889 if(DontTerminateDebugSession($"Close IDE"))
2891 if(findInFilesDialog)
2892 findInFilesDialog.SearchStop();
2895 workspace.timer.Stop();
2898 ideMainFrame.Destroy(0);
2905 bool passThrough = false;
2906 bool debugStart = false;
2907 bool debugWorkDir = false;
2908 char * passDebugWorkDir = null;
2909 bool openAsText = false;
2910 DynamicString passArgs { };
2913 for(c = 1; c<app.argc; c++)
2917 char * arg = app.argv[c];
2918 char * buf = new char[strlen(arg)*2+1];
2920 passArgs.concat(" ");
2922 passArgs.concat(buf);
2925 else if(debugWorkDir)
2927 passDebugWorkDir = CopyString(app.argv[c]);
2928 StripQuotes(passDebugWorkDir, passDebugWorkDir);
2929 debugWorkDir = false;
2931 else if(!strcmp(app.argv[c], "-t"))
2933 else if(!strcmp(app.argv[c], "-no-parsing"))
2934 ide.noParsing = true;
2935 else if(!strcmp(app.argv[c], "-debug-start"))
2937 else if(!strcmp(app.argv[c], "-debug-work-dir"))
2938 debugWorkDir = true;
2939 else if(!strcmp(app.argv[c], "-@"))
2943 char fullPath[MAX_LOCATION];
2944 char parentPath[MAX_LOCATION];
2945 char ext[MAX_EXTENSION];
2947 FileAttribs dirAttribs;
2948 GetWorkingDir(fullPath, MAX_LOCATION);
2949 PathCat(fullPath, app.argv[c]);
2950 StripLastDirectory(fullPath, parentPath);
2951 GetExtension(app.argv[c], ext);
2952 isProject = !openAsText && !strcmpi(ext, "epj");
2954 if(isProject && c > (debugStart ? 2 : 1)) continue;
2956 // Create directory for projects (only)
2957 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2959 if(isProject && !FileExists(fullPath))
2961 char name[MAX_LOCATION];
2962 NewProjectDialog newProjectDialog;
2966 projectView.visible = false;
2967 if(!projectView.Destroy(0))
2971 newProjectDialog = { master = this };
2973 strcpy(name, app.argv[c]);
2974 StripExtension(name);
2975 GetLastDirectory(name, name);
2976 newProjectDialog.projectName.contents = name;
2977 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2978 newProjectDialog.locationEditBox.path = parentPath;
2979 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2981 incref newProjectDialog;
2982 newProjectDialog.Modal();
2985 ideSettings.AddRecentProject(projectView.fileName);
2986 ide.UpdateRecentMenus();
2987 settingsContainer.Save();
2989 delete newProjectDialog;
2990 // Open only one project
2994 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false);
2996 else if(strstr(fullPath, "http://") == fullPath)
2997 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false);
3000 if(passThrough && projectView && projectView.project && workspace)
3001 workspace.commandLineArgs = passArgs;
3002 if(passDebugWorkDir && projectView && projectView.project && workspace)
3004 workspace.debugDir = passDebugWorkDir;
3005 delete passDebugWorkDir;
3008 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
3010 UpdateToolBarActiveConfigs(false);
3011 UpdateToolBarActiveCompilers();
3018 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
3021 projectView.visible = false;
3022 projectView.Destroy(0);
3025 #ifdef GDB_DEBUG_GUI
3026 gdbDialog.Destroy(0);
3031 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config, int bitDepth)
3035 char * oldPaths[128];
3036 String oldList = new char[maxPathLen];
3037 Array<String> newExePaths { };
3038 //Map<String, bool> exePathExists { };
3040 #if defined(__unix__) || defined(__APPLE__)
3041 Array<String> newLibPaths { };
3042 Map<String, bool> libPathExists { };
3047 for(prj : workspace.projects)
3049 DirExpression targetDirExp;
3051 // SKIP FIRST PROJECT...
3052 if(prj == workspace.projects.firstIterator.data) continue;
3054 // NOTE: Right now the additional project config dir will be
3055 // obtained when the debugger is started, so toggling it
3056 // while building will change which library gets used.
3057 // To go with the initial state, e.g. when F5 was pressed,
3058 // we nould need to keep a list of all project's active
3059 // config upon startup.
3060 targetDirExp = prj.GetTargetDir(compiler, prj.config, bitDepth);
3062 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
3066 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3067 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
3071 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3072 if(cfg.targetType == sharedLibrary && cfg.debug)
3076 if(targetDirExp.dir)
3078 char buffer[MAX_LOCATION];
3079 #if defined(__WIN32__)
3080 Array<String> paths = newExePaths;
3082 Array<String> paths = newLibPaths;
3084 GetSystemPathBuffer(buffer, prj.topNode.path);
3085 PathCat(buffer, targetDirExp.dir);
3088 if(!fstrcmp(p, buffer))
3095 paths.Add(CopyString(buffer));
3097 delete targetDirExp;
3101 for(item : compiler.executableDirs)
3104 for(p : newExePaths)
3106 if(!fstrcmp(p, item))
3113 newExePaths.Add(CopySystemPath(item));
3116 GetEnvironment("PATH", oldList, maxPathLen);
3118 printf("Old value of PATH: %s\n", oldList);
3120 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3121 for(c = 0; c < count; c++)
3124 for(p : newExePaths)
3126 if(!fstrcmp(p, oldPaths[c]))
3133 newExePaths.Add(CopySystemPath(oldPaths[c]));
3137 for(path : newExePaths)
3138 len += strlen(path) + 1;
3139 newList = new char[len + 1];
3141 for(path : newExePaths)
3143 strcat(newList, path);
3144 strcat(newList, pathListSep);
3146 newList[len - 1] = '\0';
3147 SetEnvironment("PATH", newList);
3149 printf("New value of PATH: %s\n", newList);
3156 #if defined(__unix__) || defined(__APPLE__)
3158 for(item : compiler.libraryDirs)
3160 if(!libPathExists[item]) // fstrcmp should be used
3162 String s = CopyString(item);
3164 libPathExists[s] = true;
3168 #if defined(__APPLE__)
3169 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
3171 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
3174 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
3176 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3177 for(c = 0; c < count; c++)
3179 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
3181 String s = CopyString(oldPaths[c]);
3183 libPathExists[s] = true;
3188 for(path : newLibPaths)
3189 len += strlen(path) + 1;
3190 newList = new char[len + 1];
3192 for(path : newLibPaths)
3194 strcat(newList, path);
3195 strcat(newList, pathListSep);
3197 newList[len - 1] = '\0';
3198 #if defined(__APPLE__)
3199 SetEnvironment("DYLD_LIBRARY_PATH", newList);
3201 SetEnvironment("LD_LIBRARY_PATH", newList);
3204 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
3210 delete libPathExists;
3213 if(compiler.distccEnabled && compiler.distccHosts)
3214 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
3219 void DestroyTemporaryProjectDir()
3221 if(tmpPrjDir && tmpPrjDir[0])
3223 if(FileExists(tmpPrjDir).isDirectory)
3224 DestroyDir(tmpPrjDir);
3225 property::tmpPrjDir = null;
3231 // Graphics Driver Menu
3235 app.currentSkin.selectionColor = selectionColor;
3236 app.currentSkin.selectionText = selectionText;
3240 driverItems = new MenuItem[app.numDrivers];
3241 for(c = 0; c < app.numDrivers; c++)
3243 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
3244 driverItems[c].id = c;
3245 driverItems[c].isRadio = true;
3248 driverItems = new MenuItem[2];
3249 #if defined(__unix__)
3250 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
3251 driverItems[0].id = 0;
3252 driverItems[0].isRadio = true;
3254 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
3255 driverItems[0].id = 0;
3256 driverItems[0].isRadio = true;
3258 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
3259 driverItems[1].id = 1;
3260 driverItems[1].isRadio = true;
3262 /* skinItems = new MenuItem[app.numSkins];
3263 for(c = 0; c < app.numSkins; c++)
3265 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
3266 skinItems[c].id = c;
3267 skinItems[c].isRadio = true;
3270 ideFileDialog.master = this;
3271 ideProjectFileDialog.master = this;
3273 //SetDriverAndSkin();
3277 void UpdateRecentMenus()
3280 Menu fileMenu = menu.FindMenu($"File");
3281 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
3282 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
3283 char * itemPath = new char[MAX_LOCATION];
3284 char * itemName = new char[MAX_LOCATION+4];
3287 recentFiles.Clear();
3290 for(recent : ideSettings.recentFiles)
3292 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3293 MakeSystemPath(itemPath);
3294 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3295 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
3299 recentProjects.Clear();
3301 for(recent : ideSettings.recentProjects)
3303 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3304 MakeSystemPath(itemPath);
3305 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3306 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
3322 void DestroyDir(char * path)
3324 RecursiveDeleteFolderFSI fsi { };
3329 #if defined(__WIN32__)
3330 define sdkDirName = "Ecere SDK";
3332 define sdkDirName = "ecere";
3335 void FindAndShellOpenInstalledFolder(char * name)
3337 char * p = new char[MAX_LOCATION];
3338 char * v = new char[maxPathLen];
3341 Array<String> paths { };
3343 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3344 StripLastDirectory(p, p);
3346 paths.Add(CopyString(p));
3347 #if defined(__WIN32__)
3348 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3351 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3352 PathCat(p, name); paths.Add(CopyString(p));
3354 GetEnvironment("AppData", v, maxPathLen);
3357 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3358 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3360 GetEnvironment("ProgramFiles", v, maxPathLen);
3363 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3364 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3366 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3369 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3370 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3372 GetEnvironment("SystemDrive", v, maxPathLen);
3375 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3376 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3379 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3380 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3381 for(c=0; c<numTokens; c++)
3383 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3384 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3389 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3390 if(FileExists(p).isDirectory)
3402 void FindAndShellOpenInstalledFile(char * subdir, char * name)
3404 char * p = new char[MAX_LOCATION];
3405 char * v = new char[maxPathLen];
3408 Array<String> paths { };
3410 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3411 paths.Add(CopyString(p));
3412 StripLastDirectory(p, p);
3414 paths.Add(CopyString(p));
3415 #if defined(__WIN32__)
3416 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3419 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3420 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3422 GetEnvironment("AppData", v, maxPathLen);
3425 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3426 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3428 GetEnvironment("ProgramFiles", v, maxPathLen);
3431 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3432 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3434 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3437 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3438 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3440 GetEnvironment("SystemDrive", v, maxPathLen);
3443 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3444 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3447 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3448 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3449 for(c=0; c<numTokens; c++)
3451 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3452 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3457 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3459 if(FileExists(p).isFile)
3471 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
3473 bool preserveRootFolder;
3475 void OutFolder(char * folderPath, bool isRoot)
3477 if(!(preserveRootFolder && isRoot))
3478 RemoveDir(folderPath);
3481 bool OnFile(char * filePath)
3483 DeleteFile(filePath);
3488 class IDEApp : GuiApplication
3490 //driver = "Win32Console";
3491 // driver = "OpenGL";
3495 TempFile includeFile { };
3499 char ext[MAX_EXTENSION];
3500 SetLoggingMode(stdOut, null);
3501 //SetLoggingMode(debug, null);
3503 settingsContainer.Load();
3504 if(argc > 1 && !strcmpi(GetExtension(argv[1], ext), "3ds"))
3506 app.driver = "OpenGL";
3507 ide.driverItems[1].checked = true;
3511 #if defined(__unix__) || defined(__APPLE__)
3512 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
3514 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
3516 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
3521 desktop.text = titleECEREIDE;
3524 for(c = 1; c<app.argc; c++)
3526 char fullPath[MAX_LOCATION];
3527 GetWorkingDir(fullPath, MAX_LOCATION);
3528 PathCat(fullPath, app.argv[c]);
3529 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal, false);
3533 if(!LoadIncludeFile())
3534 PrintLn("error: unable to load :crossplatform.mk file inside ide binary.");
3539 bool LoadIncludeFile()
3541 bool result = false;
3542 File include = FileOpen(":crossplatform.mk", read);
3545 File f = includeFile;
3548 for(; !include.Eof(); )
3551 int count = include.Read(buffer, 1, 4096);
3552 f.Write(buffer, 1, count);
3562 IDEMainFrame ideMainFrame { };
3564 define app = ((IDEApp)__thisModule);
3566 define titleECEREIDE = $"ECERE IDE (Debug)";
3568 define titleECEREIDE = $"ECERE IDE";