X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ide%2Fsrc%2Fide.ec;h=815c3b0e7a711d34549eab07d512dfbf3f3acc5f;hb=84e623c3cb902d941ac9967bcf91767bae8f128b;hp=e1dbe7099d15630e0e92b34467bd7b240cdbaf48;hpb=5093862d259863f03127b6d21a54279c9f7cbeaf;p=sdk diff --git a/ide/src/ide.ec b/ide/src/ide.ec index e1dbe70..815c3b0 100644 --- a/ide/src/ide.ec +++ b/ide/src/ide.ec @@ -44,12 +44,39 @@ import "about" import "FileSystemIterator" +AVLTree binaryDocExt +{ [ + "wav", "mp3", "flac", "ogg", + "mid", + "avi", "mkv", "mpg", "mpeg", + "7z", "zip", "gz", "bz2", "xz", "rar", "z", "tar", "ear", + "pdf", "odp", "ods", "odt", "ppt", "doc", "xls", "pptx", "docx", "xlsx" +] }; + #if defined(__WIN32__) define pathListSep = ";"; #else define pathListSep = ":"; #endif +IDEConfigHolder ideConfig { }; + +FontResource panelFont { $"Courier New", 10 }; +FontResource codeFont { $"Courier New", 10 }; + +IDESettings ideSettings; + +IDESettingsContainer settingsContainer +{ + dataOwner = &ideSettings; + dataClass = class(IDESettings); + + void onLoadCompilerConfigs() { ide.UpdateCompilerConfigs(true); } + void onLoadRecentFiles() { ide.updateRecentFilesMenu(); } + void onLoadRecentProjects() { ide.updateRecentProjectsMenu(); } + void onLoad() { ide.ApplyColorScheme(colorScheme); ide.ApplyFont(ideSettings.codeEditorFont, ideSettings.codeEditorFontSize); } +}; + define maxPathLen = 65 * MAX_LOCATION; class PathBackup : struct @@ -142,9 +169,6 @@ FileDialog ideProjectFileDialog GlobalSettingsDialog globalSettingsDialog { - ideSettings = ideSettings; - settingsContainer = settingsContainer; - void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange) { switch(globalSettingsChange) @@ -195,7 +219,7 @@ void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int class IDEToolbar : ToolBar { - /* File options */ + // File options // New ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) }; // Open @@ -209,16 +233,16 @@ class IDEToolbar : ToolBar ToolSeparator separator1 { this }; - /* Edit options */ + // Edit options // Cut - // Copy + // Copy // Paste // Undo // Redo // ToolSeparator separator2 { this }; - /* Project options */ + // Project options // New project ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) }; // Open project @@ -230,7 +254,7 @@ class IDEToolbar : ToolBar ToolSeparator separator3 { this }; - /* Build/Execution options */ + // Build/Execution options // Build ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; }; // Re-link @@ -252,7 +276,7 @@ class IDEToolbar : ToolBar ToolSeparator separator4 { this }; - /* Debug options */ + // Debug options // Start/Resume ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; }; // Restart @@ -294,11 +318,11 @@ class IDEToolbar : ToolBar this, toolTip = $"Active Compiler", size = { 160 }, disabled = true; bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods) { - if(ide.workspace && ide.projectView && row && strcmp(row.string, ide.workspace.compiler)) + if(ide.workspace && ide.projectView && row && strcmp(row.string, ide.workspace.activeCompiler)) { bool silent = ide.projectView.buildInProgress == none ? false : true; - CompilerConfig compiler = ideSettings.GetCompilerConfig(row.string); - ide.workspace.compiler = row.string; + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(row.string); + ide.workspace.activeCompiler = row.string; ide.projectView.ShowOutputBuildLog(!silent); if(!silent) ide.projectView.DisplayCompiler(compiler, false); @@ -313,13 +337,13 @@ class IDEToolbar : ToolBar DropBox activeBitDepth { - this, toolTip = $"Active Bit Depth", size = { 60 }, disabled = true; + this, toolTip = $"Active Bit Length", size = { 60 }, disabled = true; bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods) { if(ide.workspace && ide.projectView && row) { bool silent = ide.projectView.buildInProgress == none ? false : true; - CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler); + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(ide.workspace.activeCompiler); ide.workspace.bitDepth = (int)row.tag; ide.projectView.ShowOutputBuildLog(!silent); if(!silent) @@ -344,7 +368,6 @@ class IDEToolbar : ToolBar activeBitDepth.AddString("64 bit").tag = 64; activeBitDepth.currentRow = row; } - } class IDEMainFrame : Window @@ -404,7 +427,7 @@ class IDEWorkSpace : Window menu = Menu { }; IDEToolbar toolBar; - MenuItem * driverItems, * skinItems; + MenuItem * driverItems, * skinItems, * languageItems; StatusField pos { width = 150 }; StatusField ovr, caps, num; DualPipe documentor; @@ -420,32 +443,145 @@ class IDEWorkSpace : Window BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this }; BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this }; BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this }; - + + BuildOutputMode rightClickMenuBuildOutputMode; + Debugger debugger { }; + void ApplyFont(const String faceName, float size) + { + panelFont.faceName = faceName; + panelFont.size = size; + + codeFont.faceName = faceName; + codeFont.size = size; + + { + CodeEditor ce; + for(ce = (CodeEditor)firstChild; ce; ce = (CodeEditor)ce.next) + if(ce._class == class(CodeEditor)) + { + ce.font = { codeFont.faceName, codeFont.size, codeFont.bold, codeFont.italic }; + ce.editBox.font = ce.font; + ce.OnPostCreate(); + } + } + + threadsView.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + callStackView.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.buildBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.debugBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.findBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + #ifdef GDB_DEBUG_OUTPUT + outputView.gdbBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + #endif +#ifdef GDB_DEBUG_GUI + if(gdbDialog) + { + gdbDialog.tree.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + gdbDialog.output.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + } +#endif + } + + void ApplyColorScheme(IDEColorScheme cs) + { + CodeEditor ce; + + colorScheme = cs; + + for(ce = (CodeEditor)firstChild; ce; ce = (CodeEditor)ce.next) + if(ce._class == class(CodeEditor)) + { + EditBox eb = ce.editBox; + ce.background = cs.marginColor; + eb.selectionColor = cs.selectionColor; + eb.selectionText = cs.selectionText; + eb.background = cs.codeEditorBG; + eb.foreground = cs.codeEditorFG; + eb.syntaxColorScheme = cs.syntaxColors; + } + + if(projectView) + { + projectView.fileList.background = cs.projectViewBackground; + projectView.fileList.foreground = cs.projectViewText; + projectView.fileList.selectionColor = cs.selectionColor; + projectView.fileList.selectionText = cs.selectionText; + } + + sheet.properties.background = cs.viewsBackground; + sheet.properties.foreground = cs.viewsText; + sheet.properties.selectionText = cs.sheetSelectionText; + sheet.properties.selectionColor = cs.sheetSelectionColor; + sheet.methods.background = cs.viewsBackground; + sheet.methods.foreground = cs.viewsText; + + threadsView.editBox.background = cs.viewsBackground; + threadsView.editBox.foreground = cs.viewsText; + threadsView.editBox.selectionColor = cs.selectionColor; + threadsView.editBox.selectionText = cs.selectionText; + + callStackView.editBox.background = cs.viewsBackground; + callStackView.editBox.foreground = cs.viewsText; + callStackView.editBox.selectionColor = cs.selectionColor; + callStackView.editBox.selectionText = cs.selectionText; + + watchesView.listBox.background = cs.viewsBackground; + watchesView.listBox.foreground = cs.viewsText; + watchesView.listBox.selectionColor = cs.selectionColor; + watchesView.listBox.selectionText = cs.selectionText; + + breakpointsView.listBox.background = cs.viewsBackground; + breakpointsView.listBox.foreground = cs.viewsText; + breakpointsView.listBox.selectionColor = cs.selectionColor; + breakpointsView.listBox.selectionText = cs.selectionText; + + outputView.buildBox.background = cs.outputBackground; + outputView.buildBox.foreground = cs.outputText; + outputView.buildBox.selectionColor = cs.selectionColor; + outputView.buildBox.selectionText = cs.selectionText; + + outputView.debugBox.background = cs.outputBackground; + outputView.debugBox.foreground = cs.outputText; + outputView.debugBox.selectionColor = cs.selectionColor; + outputView.debugBox.selectionText = cs.selectionText; + + outputView.findBox.background = cs.outputBackground; + outputView.findBox.foreground = cs.outputText; + outputView.findBox.selectionColor = cs.selectionColor; + outputView.findBox.selectionText = cs.selectionText; + } + ProjectView projectView; OutputView outputView { parent = this; - void OnGotoError(char * line, bool noParsing) + void OnGotoError(const char * line, bool noParsing) { - ide.GoToError(line, noParsing); + CompilerConfig compiler = ide.workspace ? ideConfig.compilers.GetCompilerConfig(ide.workspace.activeCompiler) : null; + const char * objectFileExt = compiler ? compiler.objectFileExt : objectDefaultFileExt; + ide.GoToError(line, noParsing, objectFileExt); + delete compiler; } - void OnCodeLocationParseAndGoTo(char * line) + void OnCodeLocationParseAndGoTo(const char * line) { - ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir); + CompilerConfig compiler = ide.workspace ? ideConfig.compilers.GetCompilerConfig(ide.workspace.activeCompiler) : null; + const char * objectFileExt = compiler ? compiler.objectFileExt : objectDefaultFileExt; + ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir, objectFileExt); + delete compiler; } bool OnKeyDown(Key key, unichar ch) { switch(key) { - case escape: + case escape: if(activeBox != findBox || !ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort()) - ide.ShowCodeEditor(); + ide.ShowCodeEditor(); break; default: { @@ -467,11 +603,11 @@ class IDEWorkSpace : Window CallStackView callStackView { - parent = this, font = { panelFont.faceName, panelFont.size }; + parent = this, font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; void OnSelectFrame(int frameIndex) { - ide.debugger.GoToStackFrameLine(frameIndex, true); + ide.debugger.GoToStackFrameLine(frameIndex, true, true); if(frameIndex >= 0) ide.debugger.SelectFrame(frameIndex); } @@ -482,33 +618,7 @@ class IDEWorkSpace : Window if(debugger.activeFrame && debugger.activeFrame.absoluteFile) { int line = debugger.activeFrame.line; - char name[MAX_LOCATION]; - Project prj = null; - // TOFIX: Improve on this, don't use only filename, make a function - GetLastDirectory(debugger.activeFrame.absoluteFile, name); - if(ide && ide.workspace) - { - for(p : ide.workspace.projects) - { - if(p.topNode.Find(name, false)) - { - prj = p; - break; - } - } - if(!prj) - { - for(p : ide.workspace.projects) - { - if(IsPathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path)) - { - prj = p; - break; - } - } - } - } - debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj); + debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line); Update(null); { CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile); @@ -541,7 +651,7 @@ class IDEWorkSpace : Window if(activeFrame) { bool error; - int lineCursor, lineTopFrame, activeThread, hitThread; + int lineCursor, lineTopFrame; int lineH, scrollY, boxH; BitmapResource bmp; Breakpoint bp = null; @@ -549,8 +659,8 @@ class IDEWorkSpace : Window boxH = clientSize.h; scrollY = editBox.scroll.y; displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH); - activeThread = debugger.activeThread; - hitThread = debugger.hitThread; + //activeThread = debugger.activeThread; + //hitThread = debugger.hitThread; debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame); // TODO: improve bp drawing... it should be visible even if it's not on the activeFrame @@ -591,11 +701,11 @@ class IDEWorkSpace : Window } } }; - + WatchesView watchesView { parent = this }; ThreadsView threadsView { - parent = this, font = { panelFont.faceName, panelFont.size }; + parent = this, font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; bool OnKeyDown(Key key, unichar ch) { @@ -633,8 +743,8 @@ class IDEWorkSpace : Window }; BreakpointsView breakpointsView { parent = this }; - ToolBox toolBox { parent = this }; - Sheet sheet { parent = this }; + ToolBox toolBox { parent = this, visible = false }; + Sheet sheet { parent = this, visible = false }; char * tmpPrjDir; property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } }; @@ -646,11 +756,14 @@ class IDEWorkSpace : Window bitmap = { ":actions/docNew.png" }; bool NotifySelect(MenuItem selection, Modifiers mods) { - Window document = (Window)NewCodeEditor(this, normal, false); + Window currentDoc = activeClient; + bool maximizeDoc = ((currentDoc && currentDoc.state == maximized) || (!currentDoc && !projectView)); + Window document = (Window)NewCodeEditor(this, maximizeDoc ? maximized : normal, false); + RepositionWindows(false); document.NotifySaved = DocumentSaved; return true; } - } + }; MenuItem fileOpenItem { fileMenu, $"Open...", o, ctrlO; @@ -666,15 +779,15 @@ class IDEWorkSpace : Window bool gotWhatWeWant = false; int c; int numSelections = ideFileDialog.numSelections; - char ** multiFilePaths = ideFileDialog.multiFilePaths; + const char * const * multiFilePaths = ideFileDialog.multiFilePaths; for(c = 0; c < numSelections; c++) { - if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift)) + if(OpenFile(multiFilePaths[c], false, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift)) gotWhatWeWant = true; } if(gotWhatWeWant || - MessageBox { type = yesNo, master = this, text = $"Error opening file", + MessageBox { type = yesNo, master = this, text = $"Error opening file", contents = $"Open a different file?" }.Modal() == no) { if(!projectView && gotWhatWeWant) @@ -688,7 +801,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose }; MenuDivider { fileMenu }; MenuItem fileSaveItem @@ -716,7 +829,7 @@ class IDEWorkSpace : Window findInFilesDialog.Show(); return true; } - } + }; MenuItem replaceInFiles { fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true }; @@ -726,25 +839,28 @@ class IDEWorkSpace : Window findInFilesDialog.Show(); return true; } - } + }; MenuDivider { fileMenu }; MenuItem globalSettingsItem { fileMenu, $"Global Settings...", g; bool NotifySelect(MenuItem selection, Modifiers mods) { + // Reload configs here until we setup a configs directory monitor + ideConfig.compilers.read(settingsContainer); + globalSettingsDialog.master = this; - if(ide.workspace && ide.workspace.compiler) - globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler; + if(ide.workspace && ide.workspace.activeCompiler) + globalSettingsDialog.workspaceActiveCompiler = ide.workspace.activeCompiler; else if(ideSettings.defaultCompiler) globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler; globalSettingsDialog.Modal(); return true; } - } + }; MenuDivider { fileMenu }; - Menu recentFiles { fileMenu, $"Recent Files", r }; - Menu recentProjects { fileMenu, $"Recent Projects", p }; + Menu recentFilesMenu { fileMenu, $"Recent Files", r }; + Menu recentProjectsMenu { fileMenu, $"Recent Projects", p }; MenuDivider { fileMenu }; MenuItem exitItem { @@ -760,7 +876,8 @@ class IDEWorkSpace : Window bool FileRecentFile(MenuItem selection, Modifiers mods) { int id = 0; - for(file : ideSettings.recentFiles) + RecentPaths recentFiles = workspace ? workspace.recentFiles : ideConfig.recentFiles; + for(file : recentFiles) { if(id == selection.id) { @@ -768,15 +885,15 @@ class IDEWorkSpace : Window char extension[MAX_EXTENSION] = ""; GetExtension(file, extension); isProjectFile = (!strcmpi(extension, "epj") || !strcmpi(extension, "ews")); - if(mods.ctrl) + if(mods.ctrl && !mods.shift) { - char * command = PrintString("ide ", isProjectFile ? "-t " : "", file); + char * command = PrintString("ecere-ide ", isProjectFile ? "-t " : "", file); Execute(command); delete command; } else { - OpenFile(file, normal, true, isProjectFile ? "txt" : null, no, normal, mods.ctrl && mods.shift); + OpenFile(file, false, true, isProjectFile ? "txt" : null, no, normal, mods.ctrl && mods.shift); ide.RepositionWindows(false); } break; @@ -789,18 +906,18 @@ class IDEWorkSpace : Window bool FileRecentProject(MenuItem selection, Modifiers mods) { int id = 0; - for(file : ideSettings.recentProjects) + for(file : ideConfig.recentWorkspaces) { if(id == selection.id) { - if(mods.ctrl) + if(mods.ctrl && !mods.shift) { - char * command = PrintString("ide ", file); + char * command = PrintString("ecere-ide ", file); Execute(command); delete command; } else - OpenFile(file, normal, true, null, no, normal, mods.ctrl && mods.shift); + OpenFile(file, false, true, (mods.ctrl && mods.shift) ? "txt" : null, no, normal, mods.ctrl && mods.shift); break; } id++; @@ -809,7 +926,7 @@ class IDEWorkSpace : Window } MenuPlacement editMenu { menu, $"Edit", e }; - + Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true }; MenuItem projectNewItem { @@ -830,9 +947,9 @@ class IDEWorkSpace : Window newProjectDialog.CreateNewProject(); if(projectView) { - ideSettings.AddRecentProject(projectView.fileName); - ide.UpdateRecentMenus(); - settingsContainer.Save(); + ideConfig.recentWorkspaces.addRecent(projectView.fileName); + ideConfig.recentWorkspaces.write(settingsContainer); + ide.updateRecentProjectsMenu(); } } } @@ -840,7 +957,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectOpenItem { projectMenu, $"Open...", o, Key { o, true, true }; @@ -853,12 +970,12 @@ class IDEWorkSpace : Window ideProjectFileDialog.text = openProjectFileDialogTitle; if(ideProjectFileDialog.Modal() == ok) { - OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift); + OpenFile(ideProjectFileDialog.filePath, false, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift); //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory); } return true; } - } + }; MenuItem projectQuickItem { projectMenu, $"Quick...", q, f7, disabled = true; @@ -868,7 +985,7 @@ class IDEWorkSpace : Window QuickProjectDialog { this }.Modal(); return true; } - } + }; MenuItem projectAddItem { projectMenu, $"Add project to workspace...", a, Key { a, true, true }; @@ -884,9 +1001,9 @@ class IDEWorkSpace : Window { if(ideProjectFileDialog.Modal() == ok) { - if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add, mods.ctrl && mods.shift)) + if(OpenFile(ideProjectFileDialog.filePath, false, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add, mods.ctrl && mods.shift)) break; - if(MessageBox { type = yesNo, master = this, text = $"Error opening project file", + if(MessageBox { type = yesNo, master = this, text = $"Error opening project file", contents = $"Add a different project?" }.Modal() == no) { break; @@ -897,7 +1014,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectCloseItem { projectMenu, $"Close", c, disabled = true; @@ -910,7 +1027,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuDivider { projectMenu }; MenuItem projectSettingsItem { @@ -920,7 +1037,7 @@ class IDEWorkSpace : Window projectView.MenuSettings(projectView.active ? selection : null, mods); return true; } - } + }; MenuDivider { projectMenu }; MenuItem projectBrowseFolderItem { @@ -931,7 +1048,7 @@ class IDEWorkSpace : Window projectView.MenuBrowseFolder(null, mods); return true; } - } + }; MenuDivider { projectMenu }; MenuItem projectRunItem { @@ -943,7 +1060,7 @@ class IDEWorkSpace : Window projectView.Run(null, mods); return true; } - } + }; MenuItem projectBuildItem { projectMenu, $"Build", b, f7, disabled = true; @@ -959,7 +1076,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectLinkItem { projectMenu, $"Relink", l, disabled = true; @@ -970,7 +1087,7 @@ class IDEWorkSpace : Window projectView.ProjectLink(projectView.active ? selection : null, mods); return true; } - } + }; MenuItem projectRebuildItem { projectMenu, $"Rebuild", d, shiftF7, disabled = true; @@ -981,7 +1098,7 @@ class IDEWorkSpace : Window projectView.ProjectRebuild(projectView.active ? selection : null, mods); return true; } - } + }; MenuItem projectCleanTargetItem { projectMenu, $"Clean Target", g, disabled = true; @@ -995,7 +1112,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectCleanItem { projectMenu, $"Clean", e, disabled = true; @@ -1009,7 +1126,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectRealCleanItem { projectMenu, $"Real Clean", disabled = true; @@ -1023,7 +1140,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuItem projectRegenerateItem { projectMenu, $"Regenerate Makefile", m, disabled = true; @@ -1034,7 +1151,7 @@ class IDEWorkSpace : Window projectView.ProjectRegenerate(projectView.active ? selection : null, mods); return true; } - } + }; MenuItem projectInstallItem { #ifdef IDE_SHOW_INSTALL_MENU_BUTTON @@ -1047,7 +1164,7 @@ class IDEWorkSpace : Window projectView.ProjectInstall(projectView.active ? selection : null, mods); return true; } - } + }; MenuItem projectCompileItem; Menu debugMenu { menu, $"Debug", d, hasMargin = true }; MenuItem debugStartResumeItem @@ -1055,7 +1172,7 @@ class IDEWorkSpace : Window debugMenu, $"Start", s, f5, disabled = true; bitmap = { ":actions/debug.png" }; NotifySelect = MenuDebugStart; - } + }; bool MenuDebugStart(MenuItem selection, Modifiers mods) { if(projectView) @@ -1082,7 +1199,7 @@ class IDEWorkSpace : Window projectView.DebugRestart(); return true; } - } + }; MenuItem debugBreakItem { debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true; @@ -1095,7 +1212,7 @@ class IDEWorkSpace : Window projectView.DebugBreak(); return true; } - } + }; MenuItem debugStopItem { debugMenu, $"Stop", p, shiftF5, disabled = true; @@ -1106,7 +1223,61 @@ class IDEWorkSpace : Window projectView.DebugStop(); return true; } - } + }; + MenuDivider { debugMenu }; + ModelView duck + { + this, + // nonClient = true, + autoCreate = false, + alphaBlend = true, + opacity = 0, + isRemote = true, + borderStyle = 0, + moveable = true, + anchor = { right = 0, bottom = 0 }, + inactive = true, + isActiveClient = false, + stayOnTop = true, + clickThrough = true, + size = { 500, 500 }; + + bool OnLoadGraphics() + { + ModelView::OnLoadGraphics(); + camera.position.z /= 1.3; + camera.orientation = Euler { yaw = 280, pitch = 20 }; + camera.Update(); + Update(null); + return true; + } + + bool OnRightButtonDown(int x, int y, Modifiers mods) + { + if(!displaySystem.flags.flipping) return true; + MenuWindowMove(null, 0); + return false; + } + + bool OnRightButtonUp(int x, int y, Modifiers mods) + { + position = position; + state = normal; + return true; + } + }; + MenuItem debugRubberDuck + { + debugMenu, $"Rubber Duck", checkable = true, disabled = true; + bool NotifySelect(MenuItem selection, Modifiers mods) + { + if(selection.checked) + duck.Create(); + else + duck.Destroy(0); + return true; + } + }; #ifndef __WIN32__ MenuDivider { debugMenu }; MenuItem debugUseValgrindItem @@ -1122,12 +1293,12 @@ class IDEWorkSpace : Window ide.AdjustValgrindMenus(); return true; } - } + }; Menu debugValgrindLeakCheckItem { debugMenu, $"Valgrind Leak Check", h }; - MenuItem debugValgrindNoLeakCheckItem { debugValgrindLeakCheckItem, $"No" , f, id = ValgrindLeakCheck::no , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; } - MenuItem debugValgrindSummaryLeakCheckItem { debugValgrindLeakCheckItem, $"Summary", f, id = ValgrindLeakCheck::summary, checkable = true, disabled = true; NotifySelect = ValgrindLCSelect, checked = true; } - MenuItem debugValgrindYesLeakCheckItem { debugValgrindLeakCheckItem, $"Yes" , f, id = ValgrindLeakCheck::yes , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; } - MenuItem debugValgrindFullLeakCheckItem { debugValgrindLeakCheckItem, $"Full" , f, id = ValgrindLeakCheck::full , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; } + MenuItem debugValgrindNoLeakCheckItem { debugValgrindLeakCheckItem, $"No" , f, id = ValgrindLeakCheck::no , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }; + MenuItem debugValgrindSummaryLeakCheckItem { debugValgrindLeakCheckItem, $"Summary", f, id = ValgrindLeakCheck::summary, checkable = true, disabled = true; NotifySelect = ValgrindLCSelect, checked = true; }; + MenuItem debugValgrindYesLeakCheckItem { debugValgrindLeakCheckItem, $"Yes" , f, id = ValgrindLeakCheck::yes , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }; + MenuItem debugValgrindFullLeakCheckItem { debugValgrindLeakCheckItem, $"Full" , f, id = ValgrindLeakCheck::full , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }; bool ValgrindLCSelect(MenuItem selection, Modifiers mods) { if(ide.workspace) @@ -1150,14 +1321,14 @@ class IDEWorkSpace : Window return true; } Menu debugValgrindRedzoneSizeItem { debugMenu, $"Valgrind Redzone Size", z }; - MenuItem debugValgrindRSDefaultItem { debugValgrindRedzoneSizeItem, $"Default", f, id = -1, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect, checked = true; } - MenuItem debugValgrindRS0Item { debugValgrindRedzoneSizeItem, $"0" , f, id = 0, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS16Item { debugValgrindRedzoneSizeItem, $"16" , f, id = 16, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS32Item { debugValgrindRedzoneSizeItem, $"32" , f, id = 32, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS64Item { debugValgrindRedzoneSizeItem, $"64" , f, id = 64, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS128Item { debugValgrindRedzoneSizeItem, $"128" , f, id = 128, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS256Item { debugValgrindRedzoneSizeItem, $"256" , f, id = 256, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } - MenuItem debugValgrindRS512Item { debugValgrindRedzoneSizeItem, $"512" , f, id = 512, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; } + MenuItem debugValgrindRSDefaultItem { debugValgrindRedzoneSizeItem, $"Default", f, id = -1, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect, checked = true; }; + MenuItem debugValgrindRS0Item { debugValgrindRedzoneSizeItem, "0" , f, id = 0, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS16Item { debugValgrindRedzoneSizeItem, "16" , f, id = 16, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS32Item { debugValgrindRedzoneSizeItem, "32" , f, id = 32, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS64Item { debugValgrindRedzoneSizeItem, "64" , f, id = 64, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS128Item { debugValgrindRedzoneSizeItem, "128" , f, id = 128, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS256Item { debugValgrindRedzoneSizeItem, "256" , f, id = 256, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; + MenuItem debugValgrindRS512Item { debugValgrindRedzoneSizeItem, "512" , f, id = 512, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }; bool ValgrindRSSelect(MenuItem selection, Modifiers mods) { if(ide.workspace) @@ -1204,57 +1375,80 @@ class IDEWorkSpace : Window bitmap = { ":actions/stepInto.png" }; bool NotifySelect(MenuItem selection, Modifiers mods) { - if(projectView) - projectView.DebugStepInto(); + if(projectView) projectView.DebugStepInto(); return true; } - } + }; MenuItem debugStepOverItem { debugMenu, $"Step Over", v, f10, disabled = true; bitmap = { ":actions/stepOver.png" }; bool NotifySelect(MenuItem selection, Modifiers mods) { - if(projectView) - projectView.DebugStepOver(false); + if(projectView) projectView.DebugStepOver(false); return true; } - } + }; + MenuItem debugSkipStepOverItem + { + debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true; + bitmap = { ":actions/stepOverSkipBreak.png" }; + bool NotifySelect(MenuItem selection, Modifiers mods) + { + if(projectView) projectView.DebugStepOver(true); + return true; + } + }; MenuItem debugStepOutItem { debugMenu, $"Step Out", o, shiftF11, disabled = true; bitmap = { ":actions/stepOut.png" }; bool NotifySelect(MenuItem selection, Modifiers mods) { - if(projectView) - projectView.DebugStepOut(false); + if(projectView) projectView.DebugStepOut(false); return true; } - } - MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c }; - MenuItem debugSkipStepOverItem + }; + MenuItem debugSkipStepOutItem { - debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true; + debugMenu, $"Step Out Skipping Breakpoints", n, Key { f11, ctrl = true, shift = true }, disabled = true; + bitmap = { ":actions/skipBreaks.png" }; bool NotifySelect(MenuItem selection, Modifiers mods) { - if(projectView) - projectView.DebugStepOver(true); + if(projectView) projectView.DebugStepOut(true); return true; } - } - MenuItem debugSkipStepOutItem + }; +#if 0 + MenuItem debugStepUntilItem { - debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true; - bitmap = { ":actions/skipBreaks.png" }; + debugMenu, $"Step Over Until Next Line", x, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { - if(projectView) - projectView.DebugStepOut(true); + if(projectView) projectView.DebugStepUntil(false); return true; } - } + }; + MenuItem debugSkipStepUntilItem + { + debugMenu, $"Step Over Until Next Line Skipping Breakpoints", e, Key { f10, shift = true, alt = true }, disabled = true; + bool NotifySelect(MenuItem selection, Modifiers mods) + { + if(projectView) projectView.DebugStepUntil(true); + return true; + } + }; +#endif + MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c }; MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u }; - MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", l }; + MenuPlacement debugRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level", l }; + MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", g }; +#if 0 + MenuPlacement debugBpRunToCursorItem { debugMenu, $"BP Run To Cursor" }; + MenuPlacement debugBpSkipRunToCursorItem { debugMenu, $"BP Run To Cursor Skipping Breakpoints" }; + MenuPlacement debugBpRunToCursorAtSameLevelItem { debugMenu, $"BP Run To Cursor At Same Level" }; + MenuPlacement debugBpSkipRunToCursorAtSameLevelItem { debugMenu, $"BP Run To Cursor At Same Level Skipping Breakpoints" }; +#endif //MenuDivider { debugMenu }; //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t }; MenuPlacement imageMenu { menu, $"Image", i }; @@ -1271,7 +1465,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuPlacement { viewMenu, $"View Designer" }; MenuPlacement { viewMenu, $"View Code" }; MenuPlacement { viewMenu, $"View Properties" }; @@ -1292,7 +1486,7 @@ class IDEWorkSpace : Window ((CodeEditor)client).ViewDesigner(); return true; } - } + }; MenuItem viewCodeItem { viewMenu, $"View Code", c, f8; @@ -1308,7 +1502,7 @@ class IDEWorkSpace : Window client.visible = true; return true; } - } + }; MenuItem viewPropertiesItem { viewMenu, $"View Properties", p, f4; @@ -1319,7 +1513,7 @@ class IDEWorkSpace : Window sheet.Activate(); return true; } - } + }; MenuItem viewMethodsItem { viewMenu, $"View Methods", m, f4; @@ -1330,7 +1524,7 @@ class IDEWorkSpace : Window sheet.Activate(); return true; } - } + }; MenuItem viewToolBoxItem { viewMenu, $"View Toolbox", x, f12; @@ -1340,7 +1534,7 @@ class IDEWorkSpace : Window toolBox.Activate(); return true; } - } + }; MenuItem viewOutputItem { viewMenu, $"Output", o, alt2; @@ -1349,7 +1543,7 @@ class IDEWorkSpace : Window outputView.Show(); return true; } - } + }; MenuItem viewWatchesItem { viewMenu, $"Watches", w, alt3; @@ -1358,7 +1552,7 @@ class IDEWorkSpace : Window watchesView.Show(); return true; } - } + }; MenuItem viewThreadsItem { viewMenu, $"Threads", t, alt4; @@ -1367,7 +1561,7 @@ class IDEWorkSpace : Window threadsView.Show(); return true; } - } + }; MenuItem viewBreakpointsItem { viewMenu, $"Breakpoints", b, alt5; @@ -1376,7 +1570,7 @@ class IDEWorkSpace : Window breakpointsView.Show(); return true; } - } + }; MenuItem viewCallStackItem { viewMenu, $"Call Stack", s, alt7; @@ -1385,7 +1579,7 @@ class IDEWorkSpace : Window callStackView.Show(); return true; } - } + }; MenuItem viewAllDebugViews { viewMenu, $"All Debug Views", a, alt9; @@ -1398,7 +1592,7 @@ class IDEWorkSpace : Window breakpointsView.Show(); return true; } - } + }; #ifdef GDB_DEBUG_GUI MenuDivider { viewMenu }; MenuItem viewGDBItem @@ -1409,7 +1603,7 @@ class IDEWorkSpace : Window gdbDialog.Show(); return true; } - } + }; #endif MenuDivider { viewMenu }; MenuItem viewColorPicker @@ -1421,7 +1615,7 @@ class IDEWorkSpace : Window colorPicker.Modal(); return true; } - } + }; MenuDivider { viewMenu }; /* MenuItem @@ -1438,6 +1632,11 @@ class IDEWorkSpace : Window }; */ Menu driversMenu { viewMenu, $"Graphics Driver", v }; + + MenuDivider { viewMenu }; + + Menu languageMenu { viewMenu, "Language", l }; + //Menu skinsMenu { viewMenu, "GUI Skins", k }; Menu windowMenu { menu, $"Window", w }; MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll }; @@ -1479,7 +1678,7 @@ class IDEWorkSpace : Window } return true; } - } + }; MenuDivider { helpMenu }; MenuItem { @@ -1489,7 +1688,7 @@ class IDEWorkSpace : Window FindAndShellOpenInstalledFile("doc", "Ecere Tao of Programming [work in progress].pdf"); return true; } - } + }; MenuDivider { helpMenu }; MenuItem { @@ -1499,7 +1698,7 @@ class IDEWorkSpace : Window FindAndShellOpenInstalledFolder("doc"); return true; } - } + }; MenuItem { helpMenu, $"Samples Folder", s; @@ -1508,7 +1707,7 @@ class IDEWorkSpace : Window FindAndShellOpenInstalledFolder("samples"); return true; } - } + }; MenuItem { helpMenu, $"Extras Folder", x; @@ -1517,7 +1716,7 @@ class IDEWorkSpace : Window FindAndShellOpenInstalledFolder("extras"); return true; } - } + }; MenuDivider { helpMenu }; MenuItem { @@ -1527,7 +1726,7 @@ class IDEWorkSpace : Window ShellOpen("http://ecere.com/forums"); return true; } - } + }; MenuDivider { helpMenu }; MenuItem { @@ -1537,7 +1736,7 @@ class IDEWorkSpace : Window AboutIDE { master = this }.Modal(); return true; } - } + }; property ToolBox toolBox { @@ -1567,6 +1766,7 @@ class IDEWorkSpace : Window }; bool noParsing; + bool debugStart; #ifdef GDB_DEBUG_GUI GDBDialog gdbDialog @@ -1574,14 +1774,14 @@ class IDEWorkSpace : Window master = this, parent = this; //anchor = { left = 100, top = 100, right = 100, bottom = 100 }; - void OnCommand(char * string) + void OnCommand(const char * string) { if(ide) ide.debugger.SendGDBCommand(string); } }; #endif - + bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods) { //app.driver = app.drivers[selection.id]; @@ -1593,6 +1793,8 @@ class IDEWorkSpace : Window delete ideSettings.displayDriver; ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default"); + ide.debugRubberDuck.disabled = !ide.duck.modelFile || strcmpi(app.driver, "OpenGL"); + settingsContainer.Save(); //SetDriverAndSkin(); return true; @@ -1622,19 +1824,19 @@ class IDEWorkSpace : Window } } - ProjectView CreateProjectView(Workspace workspace, char * fileName) + ProjectView CreateProjectView(Workspace workspace, const char * fileName) { Project project = workspace.projects.firstIterator.data; projectView = ProjectView { this; fileName = fileName; - + void NotifyDestroyed(Window window, DialogResult result) { projectView = null; text = titleECEREIDE; - + AdjustMenus(); } }; @@ -1647,6 +1849,7 @@ class IDEWorkSpace : Window ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE); AdjustMenus(); + updateRecentMenus(); ide.breakpointsView.LoadFromWorkspace(); ide.watchesView.LoadFromWorkspace(); @@ -1673,8 +1876,12 @@ class IDEWorkSpace : Window findInFilesDialog.SearchStop(); findInFilesDialog.currentDirectory = workingDir; } + sheet.visible = false; + toolBox.visible = false; + outputView.visible = false; ideMainFrame.text = titleECEREIDE; ide.AdjustMenus(); + ide.updateRecentMenus(); return true; } return false; @@ -1685,7 +1892,6 @@ class IDEWorkSpace : Window if(this) { Window child; - bool inDebugMode = debugger.isActive; bool callStackVisible = expand ? false : callStackView.visible; bool threadsVisible = expand ? false : threadsView.visible; bool watchesVisible = expand ? false : watchesView.visible; @@ -1694,10 +1900,10 @@ class IDEWorkSpace : Window bool outputVisible = expand ? false : outputView.visible; int topDistance = (callStackVisible || threadsVisible) ? 200 : 0; int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0; - + for(child = firstChild; child; child = child.next) { - if(child._class == class(CodeEditor) || child._class == class(Designer) || + if(child._class == class(CodeEditor) || child._class == class(Designer) || child._class == class(Sheet) || child._class == class(ProjectView)) { Anchor anchor = child.anchor; @@ -1705,20 +1911,22 @@ class IDEWorkSpace : Window anchor.bottom = bottomDistance; if(child._class == class(CodeEditor) || child._class == class(Designer)) { - anchor.left = 300; + anchor.left = (sheet.visible || (projectView && projectView.visible)) ? 300 : 0; anchor.right = toolBoxVisible ? 150 : 0; } - child.anchor = anchor; + if(ide.projectView) + child.anchor = anchor; } else if(expand) { - if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) || + if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) || child._class == class(BreakpointsView)) child.visible = false; } } // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated) Update(null); + if(duck.visible) duck.Update(null); // TOFIX: If this is not here, the duck disappears -- Why? } } @@ -1727,32 +1935,31 @@ class IDEWorkSpace : Window if(activeClient) activeClient.Activate(); else if(projectView) - { + { projectView.visible = true; projectView.Activate(); } - else - { - sheet.visible = true; + else if(sheet.visible) sheet.Activate(); - } + else + outputView.visible = false; return false; } - void DocumentSaved(Window document, char * fileName) + void DocumentSaved(Window document, const char * fileName) { - ideSettings.AddRecentFile(fileName); - ide.UpdateRecentMenus(); + ideConfig.recentFiles.addRecent(fileName); + ideConfig.recentFiles.write(settingsContainer); + ide.updateRecentFilesMenu(); ide.AdjustFileMenus(); - settingsContainer.Save(); } - bool Window::OnFileModified(FileChange fileChange, char * param) + bool Window::OnFileModified(FileChange fileChange, const char * param) { char temp[4096]; sprintf(temp, $"The document %s was modified by another application.\n" "Would you like to reload it and lose your changes?", this.fileName); - if(MessageBox { type = yesNo, master = this/*.parent*/, + if(MessageBox { creationActivation = flash, type = yesNo, master = this/*.parent*/, text = $"Document has been modified", contents = temp }.Modal() == yes) { bool noParsing = (this._class == class(CodeEditor) && ((CodeEditor)this).noParsing) ? true : false; @@ -1763,7 +1970,7 @@ class IDEWorkSpace : Window this.modifiedDocument = false; this.Destroy(0); - this = ide.OpenFile(fileName, normal, true, null, no, normal, noParsing); + this = ide.OpenFile(fileName, false, true, null, no, normal, noParsing); if(this) { this.anchor = anchor; @@ -1780,7 +1987,7 @@ class IDEWorkSpace : Window { if(workspace) { - CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler); + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(workspace.activeCompiler); for(prj : workspace.projects) projectView.ProjectUpdateMakefileForAllConfigs(prj); delete compiler; @@ -1793,7 +2000,7 @@ class IDEWorkSpace : Window if(workspace) { bool silent = mute || (ide.projectView.buildInProgress == none ? false : true); - CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler); + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(workspace.activeCompiler); if(!silent) { projectView.ShowOutputBuildLog(true); @@ -1808,14 +2015,15 @@ class IDEWorkSpace : Window void UpdateToolBarActiveCompilers() { toolBar.activeCompiler.Clear(); - for(compiler : ideSettings.compilerConfigs) + for(compiler : ideConfig.compilers) { DataRow row = toolBar.activeCompiler.AddString(compiler.name); - if(workspace && workspace.compiler && !strcmp(compiler.name, workspace.compiler)) + if(workspace && workspace.activeCompiler && !strcmp(compiler.name, workspace.activeCompiler)) toolBar.activeCompiler.currentRow = row; } if(!toolBar.activeCompiler.currentRow && toolBar.activeCompiler.firstRow) toolBar.activeCompiler.SelectRow(toolBar.activeCompiler.firstRow); + toolBar.activeBitDepth.SelectRow(toolBar.activeBitDepth.FindRow(workspace ? workspace.bitDepth : 0)); } void UpdateToolBarActiveConfigs(bool selectionOnly) @@ -1967,6 +2175,7 @@ class IDEWorkSpace : Window { bool unavailable = project && projectView.buildInProgress; bool naForRun = unavailable || !project || project.GetTargetType(project.config) != executable; + BuildOutputMode mode = ide.rightClickMenuBuildOutputMode; projectNewItem.disabled = unavailable; toolBar.buttonNewProject.disabled = unavailable; @@ -1982,7 +2191,7 @@ class IDEWorkSpace : Window toolBar.buttonRun.disabled = naForRun; projectBuildItem.disabled = false; - projectBuildItem.text = unavailable ? $"Stop Build" : $"Build"; + projectBuildItem.text = unavailable ? $"Stop Build" : bldMnuStrBuild[mode]; projectBuildItem.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7; projectLinkItem.disabled = unavailable; @@ -2012,27 +2221,28 @@ class IDEWorkSpace : Window if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created) { MenuItem menu; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); + BuildOutputMode mode = ide.rightClickMenuBuildOutputMode; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, mode); if(menu) { menu.disabled = false; - menu.text = unavailable ? $"Stop Build" : $"Build"; + menu.text = unavailable ? $"Stop Build" : bldMnuStrBuild[mode]; menu.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7; } - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectCleanTarget, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable; - menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectCleanTarget, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, mode); if(menu) menu.disabled = unavailable; + menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, mode); if(menu) menu.disabled = unavailable; projectView.popupMenu.Update(null); } } @@ -2043,66 +2253,67 @@ class IDEWorkSpace : Window projectView.buildInProgress == buildingMainProject; } } - property bool isBreakpointTogglingUnavailable { get { - return !project; - } } - - property bool isDebuggerExecuting { get { - if(!ide.debugger) - return false; - else - return ide.debugger.state == running; - } } + property bool isBreakpointTogglingUnavailable { get { return !project; } } + property bool isDebuggerRunning { get { if(ide.debugger) return ide.debugger.state == running; return false; } } + property bool isDebuggerStopped { get { if(ide.debugger) return ide.debugger.state == stopped; return false; } } void AdjustDebugMenus() { bool unavailable = areDebugMenusUnavailable; + bool running = isDebuggerRunning; + bool stopped = isDebuggerStopped; bool active = debugger.isActive; - bool bpNoToggle = isBreakpointTogglingUnavailable; - bool executing = isDebuggerExecuting; - //bool holding = debugger.state == stopped; - debugStartResumeItem.disabled = unavailable || executing; + bool isNotRunning = unavailable || !running; + bool isNotNotRunning = unavailable || running; + bool isNotStopped = unavailable || !stopped; + bool isNotActive = unavailable || !active; + + debugStartResumeItem.disabled = isNotNotRunning; debugStartResumeItem.text = active ? $"Resume" : $"Start"; debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart; if(toolBar) { - toolBar.buttonDebugStartResume.disabled = unavailable || executing; + toolBar.buttonDebugStartResume.disabled = isNotNotRunning; toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start"; } - debugBreakItem.disabled = unavailable || !executing; - debugStopItem.disabled = unavailable || !active; - debugRestartItem.disabled = unavailable || !active; + debugBreakItem.disabled = isNotRunning; + debugStopItem.disabled = isNotActive; + debugRestartItem.disabled = isNotActive; if(toolBar) { - toolBar.buttonDebugPause.disabled = unavailable || !executing; - toolBar.buttonDebugStop.disabled = unavailable || !active; - toolBar.buttonDebugRestart.disabled = unavailable || !active; + toolBar.buttonDebugPause.disabled = isNotRunning; + toolBar.buttonDebugStop.disabled = isNotActive; + toolBar.buttonDebugRestart.disabled = isNotActive; } - debugStepIntoItem.disabled = unavailable || executing; - debugStepOverItem.disabled = unavailable || executing; - debugStepOutItem.disabled = unavailable || executing || !active; - debugSkipStepOverItem.disabled = unavailable || executing; - debugSkipStepOutItem.disabled = unavailable || executing || !active; + debugStepIntoItem.disabled = isNotNotRunning; + debugStepOverItem.disabled = isNotNotRunning; + debugSkipStepOverItem.disabled = isNotNotRunning; + debugStepOutItem.disabled = isNotStopped; + debugSkipStepOutItem.disabled = isNotStopped; +#if 0 + debugStepUntilItem.disabled = isNotStopped; + debugSkipStepUntilItem.disabled = isNotStopped; +#endif if(toolBar) { - toolBar.buttonDebugStepInto.disabled = unavailable || executing; - toolBar.buttonDebugStepOver.disabled = unavailable || executing; - toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active; - toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing; - // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing; + toolBar.buttonDebugStepInto.disabled = isNotNotRunning; + toolBar.buttonDebugStepOver.disabled = isNotNotRunning; + toolBar.buttonDebugSkipStepOver.disabled = isNotNotRunning; + toolBar.buttonDebugStepOut.disabled = isNotStopped; + //toolBar.buttonDebugSkipStepOutItem.disabled = isNotNotRunning; } if((Designer)GetActiveDesigner()) { CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor; if(codeEditor) - codeEditor.AdjustDebugMenus(unavailable, bpNoToggle, executing); + codeEditor.AdjustDebugMenus(); } } - void ChangeFileDialogsDirectory(char * directory, bool saveSettings) + void ChangeFileDialogsDirectory(const char * directory, bool saveSettings) { char tempString[MAX_LOCATION]; strcpy(tempString, directory); @@ -2123,14 +2334,14 @@ class IDEWorkSpace : Window settingsContainer.Save(); } - Window FindWindow(char * filePath) + Window FindWindow(const char * filePath) { Window document = null; // TOCHECK: Do we need to change slashes here? for(document = firstChild; document; document = document.next) { - char * fileName = document.fileName; + const char * fileName = document.fileName; if(document.isDocument && fileName && !fstrcmp(fileName, filePath)) { document.visible = true; @@ -2141,17 +2352,17 @@ class IDEWorkSpace : Window return null; } - bool DontTerminateDebugSession(char * title) + bool DontTerminateDebugSession(const char * title) { if(debugger.isActive) { - if(MessageBox { type = yesNo, master = ide, - contents = $"Do you want to terminate the debugging session in progress?", + if(MessageBox { type = yesNo, master = ide, + contents = $"Do you want to terminate the debugging session in progress?", text = title }.Modal() == no) return true; /* - MessageBox msg { type = yesNo, master = ide, - contents = "Do you want to terminate the debugging session in progress?", + MessageBox msg { type = yesNo, master = ide, + contents = "Do you want to terminate the debugging session in progress?", text = title }; if(msg.Modal() == no) { @@ -2165,15 +2376,16 @@ class IDEWorkSpace : Window return false; } - Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod, bool noParsing) + Window OpenFile(const char * origFilePath, bool dontMaximize, bool visible, const char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod, bool noParsing) { char extension[MAX_EXTENSION] = ""; Window document = null; bool isProject = false; bool needFileModified = true; char winFilePath[MAX_LOCATION]; - char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath); - + const char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath); + Window currentDoc = activeClient; + bool maximizeDoc = !dontMaximize && ((currentDoc && currentDoc.state == maximized) || (!currentDoc && !projectView)); if(!type) { GetExtension(filePath, extension); @@ -2186,7 +2398,7 @@ class IDEWorkSpace : Window { for(document = firstChild; document; document = document.next) { - char * fileName = document.fileName; + const char * fileName = document.fileName; if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created) { document.visible = true; @@ -2213,9 +2425,8 @@ class IDEWorkSpace : Window { for(;;) { - Project project; Workspace workspace = null; - + if(FileExists(filePath)) { if(!strcmp(extension, ProjectExtension)) @@ -2229,21 +2440,24 @@ class IDEWorkSpace : Window workspace = LoadWorkspace(filePath, null); else return null; - //project = LoadProject(filePath, null); } if(workspace) { - char absolutePath[MAX_LOCATION]; CreateProjectView(workspace, filePath); document = projectView; - workspace.DropInvalidBreakpoints(); + toolBox.visible = true; + sheet.visible = true; + projectView.MakeActive(); + + workspace.ParseLoadedBreakpoints(); + workspace.DropInvalidBreakpoints(null); workspace.Save(); ide.projectView.ShowOutputBuildLog(true); { - CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler); + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(ide.workspace.activeCompiler); ide.projectView.DisplayCompiler(compiler, false); delete compiler; } @@ -2262,45 +2476,46 @@ class IDEWorkSpace : Window // this crashes on starting ide with epj file, solution please? // app.UpdateDisplay(); + workspace.OpenPreviouslyOpenedFiles(noParsing); workspace.holdTracking = true; - for(ofi : workspace.openedFiles) - { - if(ofi.state != closed) - { - Window file = OpenFile(ofi.path, normal, true, null, no, normal, noParsing); - if(file) - { - char fileName[MAX_LOCATION]; - ProjectNode node; - GetLastDirectory(ofi.path, fileName); - node = projectView.project.topNode.Find(fileName, true); - if(node) - node.EnsureVisible(); - } - } - } ide.RepositionWindows(false); workspace.holdTracking = false; workspace.timer.Start(); +#if !defined(__WIN32__) + // Valgrind Debug menu updates + debugUseValgrindItem.checked = workspace.useValgrind; + + debugValgrindNoLeakCheckItem.checked = workspace.vgLeakCheck == no; + debugValgrindSummaryLeakCheckItem.checked = workspace.vgLeakCheck == summary; + debugValgrindYesLeakCheckItem.checked = workspace.vgLeakCheck == yes; + debugValgrindFullLeakCheckItem.checked = workspace.vgLeakCheck == full; + + debugValgrindRSDefaultItem.checked = workspace.vgRedzoneSize == -1; + debugValgrindRS0Item.checked = workspace.vgRedzoneSize == 0; + debugValgrindRS16Item.checked = workspace.vgRedzoneSize == 16; + debugValgrindRS32Item.checked = workspace.vgRedzoneSize == 32; + debugValgrindRS64Item.checked = workspace.vgRedzoneSize == 64; + debugValgrindRS128Item.checked = workspace.vgRedzoneSize == 128; + debugValgrindRS256Item.checked = workspace.vgRedzoneSize == 256; + debugValgrindRS512Item.checked = workspace.vgRedzoneSize == 512; + + debugValgrindTrackOriginsItem.checked = workspace.vgTrackOrigins; +#endif + findInFilesDialog.mode = FindInFilesMode::project; findInFilesDialog.currentDirectory = ide.project.topNode.path; - + { char location[MAX_LOCATION]; StripLastDirectory(ide.project.topNode.path, location); ChangeProjectFileDialogDirectory(location); } - - /* - if(projectView.debugger) - projectView.debugger.EvaluateWatches(); - */ - + break; } - else + else { if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes) { @@ -2336,7 +2551,7 @@ class IDEWorkSpace : Window } if(prj) { - MessageBox { type = ok, parent = parent, master = this, text = $"Same Project", + MessageBox { type = ok, parent = parent, master = this, text = $"Same Project", contents = $"This project is already present in workspace." }.Modal(); } else @@ -2344,10 +2559,10 @@ class IDEWorkSpace : Window prj = LoadProject(filePath, null); if(prj) { - char * activeConfigName = null; - CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler); + const char * activeConfigName = null; + CompilerConfig compiler = ideConfig.compilers.GetCompilerConfig(workspace.activeCompiler); prj.StartMonitoring(); - workspace.projects.Add(prj); + workspace.AddProject(prj, null); if(toolBar.activeConfig.currentRow && toolBar.activeConfig.currentRow != toolBar.activeConfig.firstRow && toolBar.activeConfig.currentRow.string && toolBar.activeConfig.currentRow.string[0]) activeConfigName = toolBar.activeConfig.currentRow.string; @@ -2392,8 +2607,8 @@ class IDEWorkSpace : Window !strcmp(extension, "jpeg") || !strcmp(extension, "png")) { if(FileExists(filePath)) - document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, - hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, + document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, + hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/; }; if(!document) @@ -2403,8 +2618,8 @@ class IDEWorkSpace : Window else if(!strcmp(extension, "3ds")) { if(FileExists(filePath)) - document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, - hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, + document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable, + hasVertScroll = true, hasHorzScroll = true, parent = this, state = state, visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/ }; @@ -2450,18 +2665,18 @@ class IDEWorkSpace : Window { document.fileName = filePath; if(workspace && !workspace.holdTracking) - workspace.UpdateOpenedFileInfo(filePath, opened); + workspace.UpdateOpenedFileInfo(filePath, opened, true); } } - + if(!document && createIfFails != no) { - if(createIfFails != yes && !needFileModified && + if(createIfFails != yes && !needFileModified && MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes) createIfFails = yes; if(createIfFails == yes || createIfFails == whatever) { - document = (Window)NewCodeEditor(this, state, true); + document = (Window)NewCodeEditor(this, maximizeDoc ? maximized : normal, true); if(document) document.fileName = filePath; } @@ -2470,34 +2685,29 @@ class IDEWorkSpace : Window if(document) { if(projectView && document._class == class(CodeEditor) && workspace) - { - int lineNumber, position; - Point scroll; - CodeEditor editor = (CodeEditor)document; - editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened); - editor.openedFileInfo.holdTracking = true; - lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0); - position = Max(editor.openedFileInfo.position - 1, 0); - editor.editBox.GoToLineNum(lineNumber); - editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position); - scroll.x = Max(editor.openedFileInfo.scroll.x, 0); - scroll.y = Max(editor.openedFileInfo.scroll.y, 0); - editor.editBox.scroll = scroll; - editor.openedFileInfo.holdTracking = false; - } - + workspace.RestorePreviouslyOpenedFileState((CodeEditor)document); + if(needFileModified) document.OnFileModified = OnFileModified; document.NotifySaved = DocumentSaved; - + if(maximizeDoc && document.hasMaximize) + document.state = maximized; + if(isProject) - ideSettings.AddRecentProject(document.fileName); + { + ideConfig.recentWorkspaces.addRecent(document.fileName); + ideConfig.recentWorkspaces.write(settingsContainer); + ide.updateRecentProjectsMenu(); + } + else if(workspace) + workspace.recentFiles.addRecent(document.fileName); else - ideSettings.AddRecentFile(document.fileName); - ide.UpdateRecentMenus(); + { + ideConfig.recentFiles.addRecent(document.fileName); + ideConfig.recentFiles.write(settingsContainer); + } + ide.updateRecentFilesMenu(); ide.AdjustFileMenus(); - settingsContainer.Save(); - return document; } else @@ -2508,19 +2718,19 @@ class IDEWorkSpace : Window /*bool Window::GenericDocumentOnClose(bool parentClosing) { if(!parentClosing && ide.workspace) - ide.workspace.UpdateOpenedFileInfo(fileName, unknown); + ide.workspace.UpdateOpenedFileInfo(fileName, unknown, false); return true; }*/ bool ModelView::ModelViewOnClose(bool parentClosing) { if(!parentClosing && ide.workspace) - ide.workspace.UpdateOpenedFileInfo(fileName, unknown); + ide.workspace.UpdateOpenedFileInfo(fileName, unknown, false); return true; } bool PictureEdit::PictureEditOnClose(bool parentClosing) { if(!parentClosing && ide.workspace) - ide.workspace.UpdateOpenedFileInfo(fileName, unknown); + ide.workspace.UpdateOpenedFileInfo(fileName, unknown, false); return true; } @@ -2533,10 +2743,17 @@ class IDEWorkSpace : Window } */ + void UpdateStateLight(StatusField fld, bool on) + { + fld.color = on ? lime : Color { 128,128,128 }; + fld.backColor = on ? dimGray : 0; + fld.bold = on; + } + bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct) { - caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 }; - num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 }; + UpdateStateLight(caps, app.GetKeyState(capsState)); + UpdateStateLight(num, app.GetKeyState(numState)); return true; } @@ -2544,29 +2761,92 @@ class IDEWorkSpace : Window { switch(key) { - case b: - projectView.Update(null); - break; - case capsLock: - caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 }; - break; - case numLock: - num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 }; - break; + case b: projectView.Update(null); break; + case capsLock: UpdateStateLight(caps, app.GetKeyState(capsState)); break; + case numLock: UpdateStateLight(num, app.GetKeyState(numState)); break; + } + return true; + } + + bool OnKeyUp(Key key, unichar ch) + { + switch(key) + { + case capsLock: UpdateStateLight(caps, app.GetKeyState(capsState)); break; + case numLock: UpdateStateLight(num, app.GetKeyState(numState)); break; } return true; } - void GoToError(const char * line, bool noParsing) + void GoToError(const char * line, bool noParsing, const char * objectFileExt) { if(projectView) - projectView.GoToError(line, noParsing); + projectView.GoToError(line, noParsing, objectFileExt); } - void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir) + FileAttribs GoToCodeSelectFile(const char * filePath, const char * dir, Project prj, ProjectNode * node, char * selectedPath, const char * objectFileExt) + { + FileAttribs result { }; + FileAttribs fileAttribs; + if(filePath[0]) + { + if(prj) + strcpy(selectedPath, prj.topNode.path); + else if(dir && dir[0]) + strcpy(selectedPath, dir); + else + selectedPath[0] = '\0'; + PathCat(selectedPath, filePath); + + if((fileAttribs = FileExists(selectedPath)).isFile) + result = fileAttribs; + else if(workspace) + { + bool done = false; + for(p : workspace.projects) + { + strcpy(selectedPath, p.topNode.path); + PathCat(selectedPath, filePath); + if((fileAttribs = FileExists(selectedPath)).isFile) + { + done = true; + result = fileAttribs; + break; + } + } + if(!done) + { + Project project; + ProjectNode n = null; + for(p : workspace.projects) + { + if((n = p.topNode.Find(filePath, false))) + { + n.GetFullFilePath(selectedPath, true); + if((fileAttribs = FileExists(selectedPath)).isFile) + { + if(node) *node = n; + result = fileAttribs; + break; + } + } + } + if(!n && (n = workspace.GetObjectFileNode(filePath, &project, selectedPath, objectFileExt)) && project && + (fileAttribs = FileExists(selectedPath)).isFile) + { + if(node) *node = n; + result = fileAttribs; + } + } + } + } + return result; + } + + void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir, const char * objectFileExt) { char *s = null; - char *path = text; + const char *path = text; char *colon = strchr(text, ':'); char filePath[MAX_LOCATION] = ""; char completePath[MAX_LOCATION]; @@ -2576,7 +2856,7 @@ class IDEWorkSpace : Window FileAttribs fileAttribs; // support for valgrind output - if((s = strstr(text, "==")) && (s = strstr(s+2, "==")) && (s = strstr(s+2, ":")) && (s = strstr(s+1, ":"))) + if((s = strstr(text, "==")) && s == text && (s = strstr(s+2, "==")) && (s = strstr(s+2, ":")) && (s = strstr(s+1, ":"))) { colon = s; for(; s>text; s--) @@ -2599,7 +2879,7 @@ class IDEWorkSpace : Window //line = atoi(colon+1); } // support for "Found n match(es) in "file/path"; - 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) + else if(len > 0 && 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) { path = s+1; } @@ -2658,50 +2938,8 @@ class IDEWorkSpace : Window strcpy(filePath, path); } - if(filePath[0]) - { - if(prj) - strcpy(completePath, prj.topNode.path); - else if(dir && dir[0]) - strcpy(completePath, dir); - else - completePath[0] = '\0'; - PathCat(completePath, filePath); - - if((fileAttribs = FileExists(completePath))) - CodeLocationGoTo(completePath, fileAttribs, line, col); - else if(ide.workspace) - { - bool done = false; - for(p : ide.workspace.projects) - { - strcpy(completePath, p.topNode.path); - PathCat(completePath, filePath); - if((fileAttribs = FileExists(completePath)).isFile) - { - CodeLocationGoTo(completePath, fileAttribs, line, col); - done = true; - break; - } - } - if(!done) - { - for(p : ide.workspace.projects) - { - ProjectNode node = p.topNode.Find(filePath, false); - if(node) - { - node.GetFullFilePath(completePath); - if((fileAttribs = FileExists(completePath)).isFile) - { - CodeLocationGoTo(completePath, fileAttribs, line, col); - break; - } - } - } - } - } - } + if((fileAttribs = GoToCodeSelectFile(filePath, dir, prj, null, completePath, objectFileExt))) + CodeLocationGoTo(completePath, fileAttribs, line, col); } void CodeLocationGoTo(const char * path, const FileAttribs fileAttribs, int line, int col) @@ -2710,9 +2948,11 @@ class IDEWorkSpace : Window { char ext[MAX_EXTENSION]; GetExtension(path, ext); - if(!strcmp(ext, "mp3") || !strcmp(ext, "flac") || !strcmp(ext, "ogg") || !strcmp(ext, "avi") || !strcmp(ext, "mkv")) + strlwr(ext); + if(binaryDocExt.Find(ext)) ShellOpen(path); - else if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") || !strcmp(ext, "dll") || !strcmp(ext, "exe")) + else if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "bc") || + !strcmp(ext, "lib") || !strcmp(ext, "dll") || !strcmp(ext, "exe")) { char dirPath[MAX_LOCATION]; StripLastDirectory(path, dirPath); @@ -2720,8 +2960,8 @@ class IDEWorkSpace : Window } else { - CodeEditor codeEditor = (CodeEditor)OpenFile(path, normal, true, ext, no, normal, false); - if(codeEditor && line) + CodeEditor codeEditor = (CodeEditor)OpenFile(path, false, true, !strcmpi(ext, "epj") ? "txt" : ext, no, normal, false); + if(codeEditor && codeEditor._class == class(CodeEditor) && line) { EditBox editBox = codeEditor.editBox; editBox.GoToLineNum(line - 1); @@ -2802,12 +3042,12 @@ class IDEWorkSpace : Window SetCurrentContext(codeEditor.globalContext); SetTopContext(codeEditor.globalContext); SetGlobalContext(codeEditor.globalContext); - + SetDefines(&codeEditor.defines); SetImports(&codeEditor.imports); SetActiveDesigner(codeEditor.designer); - + sheet.codeEditor = codeEditor; toolBox.codeEditor = codeEditor; @@ -2866,6 +3106,12 @@ class IDEWorkSpace : Window } else { + if(!client && !projectView && sheet.visible) + { + if(sheet) + sheet.visible = false; + toolBox.visible = false; + } if(sheet) sheet.codeEditor = null; toolBox.codeEditor = null; @@ -2890,22 +3136,25 @@ class IDEWorkSpace : Window statusBar.AddField(pos); - caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } }; + caps = { width = 40, text = $"CAPS" }; statusBar.AddField(caps); + UpdateStateLight(caps, app.GetKeyState(capsState)); - ovr = { width = 30, text = $"OVR", color = (editBox && editBox.overwrite) ? black : Color { 128, 128, 128 } }; + ovr = { width = 36, text = $"OVR" }; statusBar.AddField(ovr); + UpdateStateLight(ovr, (editBox && editBox.overwrite)); - num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } }; + num = { width = 36, text = $"NUM" }; statusBar.AddField(num); + UpdateStateLight(num, app.GetKeyState(numState)); //statusBar.text = "Ready"; if(projectView && projectView.project) { bool isCObject = false; - ProjectNode node = projectView.GetNodeFromWindow(client, null, false); - if(!node && (node = projectView.GetNodeFromWindow(client, null, true))) + ProjectNode node = projectView.GetNodeFromWindow(client, null, true, false, null); + if(!node && (node = projectView.GetNodeFromWindow(client, null, true, true, null))) isCObject = true; if(node) { @@ -2914,7 +3163,7 @@ class IDEWorkSpace : Window if(isCObject) ChangeExtension(node.name, "c", nodeName); sprintf(name, $"Compile %s", isCObject ? nodeName : node.name); - projectCompileItem = + projectCompileItem = { copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress; @@ -2922,26 +3171,21 @@ class IDEWorkSpace : Window { if(projectView) { - bool result = false; bool isCObject = false; - ProjectNode node = null; - for(p : ide.workspace.projects) - { - node = projectView.GetNodeFromWindow(activeClient, p, false); - if(node) break; - } - if(!node && (node = projectView.GetNodeFromWindow(activeClient, null, true))) - isCObject = true; + bool isExcluded = false; + ProjectNode node = projectView.GetNodeForCompilationFromWindow(activeClient, true, &isExcluded, &isCObject); if(node) { - List nodes { }; - nodes.Add(node); - projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, isCObject ? cObject : normal); - delete nodes; - result = true; + if(isExcluded) + ide.outputView.buildBox.Logf($"%s %s is excluded from current build configuration.\n", isCObject ? "Object file" : "File", node.name); + else + { + List nodes { }; + nodes.Add(node); + projectView.Compile(node.project, nodes, normal, isCObject ? cObject : normal); + delete nodes; + } } - if(!result && node) - ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name); } return true; } @@ -2979,7 +3223,6 @@ class IDEWorkSpace : Window { int c; bool passThrough = false; - bool debugStart = false; bool debugWorkDir = false; char * passDebugWorkDir = null; bool openAsText = false; @@ -2990,7 +3233,7 @@ class IDEWorkSpace : Window { if(passThrough) { - char * arg = app.argv[c]; + const char * arg = app.argv[c]; char * buf = new char[strlen(arg)*2+1]; if(ptArg++ > 0) passArgs.concat(" "); @@ -3009,7 +3252,7 @@ class IDEWorkSpace : Window else if(!strcmp(app.argv[c], "-no-parsing")) ide.noParsing = true; else if(!strcmp(app.argv[c], "-debug-start")) - debugStart = true; + ide.debugStart = true; else if(!strcmp(app.argv[c], "-debug-work-dir")) debugWorkDir = true; else if(!strcmp(app.argv[c], "-@")) @@ -3027,7 +3270,7 @@ class IDEWorkSpace : Window GetExtension(app.argv[c], ext); isProject = !openAsText && !strcmpi(ext, "epj"); - if(isProject && c > (debugStart ? 2 : 1)) continue; + if(isProject && c > 1 + (ide.debugStart ? 1 : 0)) continue; // Create directory for projects (only) if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject) @@ -3058,19 +3301,19 @@ class IDEWorkSpace : Window newProjectDialog.Modal(); if(projectView) { - ideSettings.AddRecentProject(projectView.fileName); - ide.UpdateRecentMenus(); - settingsContainer.Save(); + ideConfig.recentWorkspaces.addRecent(projectView.fileName); + ideConfig.recentWorkspaces.write(settingsContainer); + ide.updateRecentMenus(); } delete newProjectDialog; // Open only one project break; } else - ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false); + ide.OpenFile(fullPath, app.argFilesCount > 1, true, openAsText ? "txt" : null, yes, normal, false); } else if(strstr(fullPath, "http://") == fullPath) - ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, openAsText ? "txt" : null, yes, normal, false); + ide.OpenFile(fullPath, app.argFilesCount > 1, true, openAsText ? "txt" : null, yes, normal, false); } } if(passThrough && projectView && projectView.project && workspace) @@ -3080,8 +3323,6 @@ class IDEWorkSpace : Window workspace.debugDir = passDebugWorkDir; delete passDebugWorkDir; } - if(debugStart) - ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock UpdateToolBarActiveConfigs(false); UpdateToolBarActiveCompilers(); @@ -3176,17 +3417,21 @@ class IDEWorkSpace : Window for(item : compiler.executableDirs) { + DirExpression dirExpr { }; + dirExpr.Evaluate(item, null, compiler, null, 0); found = false; + for(p : newExePaths) { - if(!fstrcmp(p, item)) + if(!fstrcmp(p, dirExpr.dir)) { found = true; break; } } if(!found) - newExePaths.Add(CopySystemPath(item)); + newExePaths.Add(CopySystemPath(dirExpr.dir)); + delete dirExpr; } GetEnvironment("PATH", oldList, maxPathLen); @@ -3305,7 +3550,6 @@ class IDEWorkSpace : Window IDEWorkSpace() { // Graphics Driver Menu - int c; /* app.currentSkin.selectionColor = selectionColor; @@ -3318,29 +3562,29 @@ class IDEWorkSpace : Window { driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver }; driverItems[c].id = c; - driverItems[c].isRadio = true; + driverItems[c].isRadio = true; } */ driverItems = new MenuItem[2]; #if defined(__unix__) driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver }; driverItems[0].id = 0; - driverItems[0].isRadio = true; + driverItems[0].isRadio = true; #else driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver }; driverItems[0].id = 0; - driverItems[0].isRadio = true; + driverItems[0].isRadio = true; #endif driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver }; driverItems[1].id = 1; - driverItems[1].isRadio = true; + driverItems[1].isRadio = true; /* skinItems = new MenuItem[app.numSkins]; for(c = 0; c < app.numSkins; c++) { skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin }; skinItems[c].id = c; - skinItems[c].isRadio = true; + skinItems[c].isRadio = true; } */ ideFileDialog.master = this; @@ -3350,39 +3594,46 @@ class IDEWorkSpace : Window return true; } - void UpdateRecentMenus() + void updateRecentMenus() { - int c; - Menu fileMenu = menu.FindMenu($"File"); - Menu recentFiles = fileMenu.FindMenu($"Recent Files"); - Menu recentProjects = fileMenu.FindMenu($"Recent Projects"); + updateRecentFilesMenu(); + updateRecentProjectsMenu(); + } + + void updateRecentFilesMenu() + { + int c = 0; char * itemPath = new char[MAX_LOCATION]; char * itemName = new char[MAX_LOCATION+4]; - MenuItem item; - - recentFiles.Clear(); - c = 0; - - for(recent : ideSettings.recentFiles) + Workspace ws = workspace; + RecentPaths recentFiles = ws ? ws.recentFiles : ideConfig.recentFiles; + recentFilesMenu.Clear(); + for(recent : recentFiles) { strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0'; MakeSystemPath(itemPath); snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0'; - recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true); + recentFilesMenu.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true); c++; } + delete itemPath; + delete itemName; + } - recentProjects.Clear(); - c = 0; - for(recent : ideSettings.recentProjects) + void updateRecentProjectsMenu() + { + int c = 0; + char * itemPath = new char[MAX_LOCATION]; + char * itemName = new char[MAX_LOCATION+4]; + recentProjectsMenu.Clear(); + for(recent : ideConfig.recentWorkspaces) { strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0'; MakeSystemPath(itemPath); snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0'; - recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true); + recentProjectsMenu.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true); c++; } - delete itemPath; delete itemName; } @@ -3391,6 +3642,7 @@ class IDEWorkSpace : Window { delete driverItems; delete skinItems; + delete languageItems; delete ideSettings; if(documentor) { @@ -3414,153 +3666,104 @@ define sdkDirName = "Ecere SDK"; define sdkDirName = "ecere"; #endif -void FindAndShellOpenInstalledFolder(char * name) +bool GetInstalledFileOrFolder(const char * subDir, const char * name, char * path, FileAttribs attribs) { - char * p = new char[MAX_LOCATION]; + bool found = false; char * v = new char[maxPathLen]; - byte * tokens[256]; - int c, numTokens; - Array paths { }; - p[0] = v[0] = '\0'; - strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - StripLastDirectory(p, p); - PathCat(p, name); - paths.Add(CopyString(p)); -#if defined(__WIN32__) - GetEnvironment("ECERE_SDK_SRC", v, maxPathLen); - if(v[0]) + v[0] = '\0'; + if(!found) { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, name); paths.Add(CopyString(p)); + strncpy(path, settingsContainer.moduleLocation, MAX_LOCATION); path[MAX_LOCATION-1] = '\0'; + StripLastDirectory(path, path); + PathCat(path, subDir); + if(name) PathCat(path, name); + if(FileExists(path) & attribs) found = true; } - GetEnvironment("AppData", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p)); - } - GetEnvironment("ProgramFiles", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p)); - } - GetEnvironment("ProgramFiles(x86)", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p)); - } - GetEnvironment("SystemDrive", v, maxPathLen); - if(v[0]) +#if defined(__WIN32__) + if(!found) { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p)); + for(s : [ "ECERE_SDK_SRC", "AppData", "ALLUSERSPROFILE", "USERPROFILE", "HOMEPATH", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "SystemDrive" ]) + { + GetEnvironment(s, v, maxPathLen); + if(v[0]) + { + strncpy(path, v, MAX_LOCATION); path[MAX_LOCATION-1] = '\0'; + if(!strcmp(s, "SystemDrive")) + PathCat(path, "Program Files"); + if(strcmp(s, "ECERE_SDK_SRC")) + PathCat(path, sdkDirName); + PathCat(path, subDir); + if(name) PathCat(path, name); + if(FileExists(path) & attribs) + { + found = true; + break; + } + } + } } #else - GetEnvironment("XDG_DATA_DIRS", v, maxPathLen); - numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false); - for(c=0; c paths { }; - p[0] = v[0] = '\0'; - strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - paths.Add(CopyString(p)); - StripLastDirectory(p, p); - PathCat(p, subdir); - paths.Add(CopyString(p)); -#if defined(__WIN32__) - GetEnvironment("ECERE_SDK_SRC", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p)); - } - GetEnvironment("AppData", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p)); - } - GetEnvironment("ProgramFiles", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p)); - } - GetEnvironment("ProgramFiles(x86)", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p)); - } - GetEnvironment("SystemDrive", v, maxPathLen); - if(v[0]) - { - strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0'; - PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p)); - } -#else - GetEnvironment("XDG_DATA_DIRS", v, maxPathLen); - numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false); - for(c=0; c 1 && !strcmpi(GetExtension(argv[1], ext), "3ds")) + + if(ideSettings.language) + { + const String language = GetLanguageString(); + if(ideSettings.language.OnCompare(language)) + { + LanguageRestart(ideSettings.language, app, null, null, null, null, true); + return false; + } + } + + ide.ApplyFont(ideSettings.codeEditorFont, ideSettings.codeEditorFontSize); + ide.ApplyColorScheme(colorScheme); + + ideConfig.compilers.read(settingsContainer); + ideConfig.recentFiles.read(settingsContainer); + ideConfig.recentWorkspaces.read(settingsContainer); + + // First count files arg to decide whether to maximize + { + bool passThrough = false, debugWorkDir = false; + int c; + argFilesCount = 0; + for(c = 1; c 0 && !strcmpi(GetExtension(argv[1], ext), "3ds")) { app.driver = "OpenGL"; ide.driverItems[1].checked = true; @@ -3598,9 +3842,20 @@ class IDEApp : GuiApplication ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true; } + { + char model[MAX_LOCATION]; + if(GetInstalledFileOrFolder("samples", "3D/ModelViewer/models/duck/duck.3DS", model, { isFile = true })) + { + ide.duck.modelFile = model; + ide.duck.parent = ideMainFrame; + } + } + if(ide.duck.modelFile && !strcmpi(app.driver, "OpenGL")) + ide.debugRubberDuck.disabled = false; + SetInIDE(true); - desktop.text = titleECEREIDE; + desktop.caption = titleECEREIDE; /* int c; for(c = 1; c 1, true, null, yes, normal, false); } */ + // Default to language specified by environment if no language selected + if(!ideSettings.language) + { + ideSettings.language = GetLanguageString(); + settingsContainer.Save(); + } + + // Default to home directory if no directory yet set up + if(!ideSettings.ideProjectFileDialogLocation[0]) + { + bool found = false; + char location[MAX_LOCATION]; + char * home = getenv("HOME"); + char * homeDrive = getenv("HOMEDRIVE"); + char * homePath = getenv("HOMEPATH"); + char * userProfile = getenv("USERPROFILE"); + char * systemDrive = getenv("SystemDrive"); + if(home && FileExists(home).isDirectory) + { + strcpy(location, home); + found = true; + } + if(!found && homeDrive && homePath) + { + strcpy(location, homeDrive); + PathCat(location, homePath); + if(FileExists(location).isDirectory) + found = true; + } + if(!found && FileExists(userProfile).isDirectory) + { + strcpy(location, userProfile); + found = true; + } + if(!found && FileExists(systemDrive).isDirectory) + { + strcpy(location, systemDrive); + found = true; + } + if(found) + { + ideSettings.ideProjectFileDialogLocation = location; + if(!ideSettings.ideFileDialogLocation[0]) + ideSettings.ideFileDialogLocation = location; + } + } + if(!LoadIncludeFile()) - PrintLn("error: unable to load :crossplatform.mk file inside ide binary."); + PrintLn($"error: unable to load :crossplatform.mk file inside ide binary."); + + // Create language menu + { + String language = ideSettings.language; + int i = 0; + bool found = false; + + ide.languageItems = new MenuItem[languages.count]; + for(l : languages) + { + ide.languageItems[i] = + { + ide.languageMenu, l.name; + bitmap = { l.bitmap }; + id = i; + isRadio = true; + + bool Window::NotifySelect(MenuItem selection, Modifiers mods) + { + if(!LanguageRestart(languages[(int)selection.id].code, app, ideSettings, settingsContainer, ide, ide.projectView, false)) + { + // Re-select previous selected language if aborted + String language = ideSettings.language; + int i = 0; + for(l : languages) + { + if(((!language || !language[0]) && i == 0) || + (language && !strcmpi(l.code, language))) + { + ide.languageItems[i].checked = true; + break; + } + i++; + } + } + return true; + } + }; + i++; + } + + // Try to find country-specific language first + if(language) + { + i = 0; + for(l : languages) + { + if(!strcmpi(l.code, language) || (i == 0 && !strcmpi("en", language))) + { + ide.languageItems[i].checked = true; + found = true; + break; + } + i++; + } + } + + // Try generalizing locale + if(!found && language) + { + char * under; + char genericLocale[256]; + i = 0; + strncpy(genericLocale, language, sizeof(genericLocale)); + genericLocale[sizeof(genericLocale)-1] = 0; + + under = strchr(genericLocale, '_'); + if(under) + *under = 0; + if(!strcmpi(genericLocale, "zh")) + strcpy(genericLocale, "zh_CN"); + if(strcmp(genericLocale, language)) + { + for(l : languages) + { + if(!strcmpi(l.code, genericLocale) || (i == 0 && !strcmpi("en", genericLocale))) + { + ide.languageItems[i].checked = true; + found = true; + break; + } + i++; + } + } + } + + if(!found) + ide.languageItems[0].checked = true; + + MenuDivider { ide.languageMenu }; + MenuItem + { + ide.languageMenu, "Help Translate"; + + bool Window::NotifySelect(MenuItem selection, Modifiers mods) + { + ShellOpen("http://translations.launchpad.net/ecere"); + return true; + } + }; + } + ideMainFrame.Create(); + if(app.argFilesCount > 1) + ide.MenuWindowTileVert(null, 0); return true; } @@ -3672,7 +4078,7 @@ IDEMainFrame ideMainFrame { }; define app = ((IDEApp)__thisModule); #ifdef _DEBUG -define titleECEREIDE = $"ECERE IDE (Debug)"; +define titleECEREIDE = $"Ecere IDE (Debug)"; #else -define titleECEREIDE = $"ECERE IDE"; +define titleECEREIDE = $"Ecere IDE"; #endif