3 enum OpenedFileState { unknown, opened, closed };
6 no, summary, yes, full;
10 get { return OnGetString(null, null, null); }
13 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
15 if(this >= no && this <= full)
18 strcpy(tempString, valgrindLeakCheckNames[this]);
19 return valgrindLeakCheckNames[this];
21 if(tempString && tempString[0])
26 static const char * valgrindLeakCheckNames[ValgrindLeakCheck] = { "no", "summary", "yes", "full" };
28 class OpenedFileInfo : struct
34 OpenedFileState state;
43 property bool trackingAllowed
45 get { return !holdTracking && ide && ide.workspace && !ide.workspace.holdTracking; }
48 void CaretMove(int line, int charPos)
50 if(trackingAllowed && (line != lineNumber || position != charPos))
54 ide.workspace.modified = true;
58 void ScrollChange(Point scroll)
62 this.scroll.x = scroll.x;
63 this.scroll.y = scroll.y;
64 ide.workspace.modified = true;
72 List<OpenedFileInfo> files = ide.workspace.openedFiles;
73 Iterator<OpenedFileInfo> it { files };
75 if(it.Find(this) && it.pointer != (last = files.GetLast()))
77 files.Move(it.pointer, last);
78 ide.workspace.modified = true;
80 modified = GetLocalTimeStamp();
84 void SetCodeEditorState(CodeEditor editor)
86 int num = Max(lineNumber - 1, 0);
89 if(editor.editBox.GoToLineNum(num))
91 int pos = Max(Min(editor.editBox.line.count, position - 1), 0);
92 editor.editBox.GoToPosition(editor.editBox.line, num, pos);
94 scrl.x = Max(scroll.x, 0);
95 scrl.y = Max(scroll.y, 0);
96 editor.editBox.scroll = scrl;
106 class WorkspaceFile : struct
110 property const char * format
113 get { return "Ecere IDE Workspace File"; }
114 isset { return true; }
116 property const char * version
119 get { return "0.1"; }
120 isset { return true; }
125 class AddedProjectInfo : struct
129 property const char * path
131 set { delete path; if(value && value[0]) path = CopyString(value); }
132 get { return path && path[0] ? path : null; }
133 isset { return path != null; }
135 property const char * activeConfig
137 set { delete activeConfig; if(value && value[0]) activeConfig = CopyString(value); }
141 if(project && project.config)
142 config = project.config.name;
144 config = activeConfig;
145 return config && config[0] ? config : null;
147 isset { return property::activeConfig != null; }
172 class Workspace : struct
176 property const char * name
178 set { delete name; if(value && value[0]) name = CopyString(value); }
179 get { return name && name[0] ? name : null; }
180 isset { return name != null; }
182 property const char * activeCompiler
184 set { delete activeCompiler; if(value && value[0]) activeCompiler = CopyString(value); }
185 get { return activeCompiler && activeCompiler[0] ? activeCompiler : null; }
186 isset { return activeCompiler != null; }
189 property const char * commandLineArgs
191 set { delete commandLineArgs; if(value && value[0]) commandLineArgs = CopyString(value); }
192 get { return commandLineArgs && commandLineArgs[0] ? commandLineArgs : null; }
193 isset { return commandLineArgs != null; }
195 property const char * debugDir
197 set { delete debugDir; if(value && value[0]) debugDir = CopyString(value); }
198 get { return debugDir && debugDir[0] ? debugDir : null; }
199 isset { return debugDir != null; }
202 property List<AddedProjectInfo> addedProjects { set { addedProjects = value; } get { return addedProjects; } isset { return addedProjects && addedProjects.count; } }
203 property List<String> sourceDirs { set { sourceDirs = value; } get { return sourceDirs; } isset { return sourceDirs && sourceDirs.count; } }
204 property Array<NamedString> environmentVars { set { environmentVars = value; } get { return environmentVars; } isset { return environmentVars && environmentVars.count; } }
205 property List<Breakpoint> breakpoints { set { breakpoints = value; } get { return breakpoints; } isset { return breakpoints && breakpoints.count; } }
206 property List<Watch> watches { set { watches = value; } get { return watches; } isset { return watches && watches.count; } }
207 property List<OpenedFileInfo> openedFiles { set { openedFiles = value; } get { return openedFiles; } isset { return openedFiles && openedFiles.count; } }
210 ValgrindLeakCheck vgLeakCheck;
216 char * activeCompiler;
217 char * commandLineArgs;
220 List<AddedProjectInfo> addedProjects;
221 List<String> sourceDirs;
222 Array<NamedString> environmentVars;
223 List<Breakpoint> breakpoints;
225 List<OpenedFileInfo> openedFiles;
227 char * workspaceFile;
232 List<Project> projects { };
239 vgLeakCheck = summary;
243 userData = this, delay = 1.0;
246 static bool skip = true;
254 ide.MenuDebugStart(ide.debugStartResumeItem, 0);
255 ide.debugStart = false;
261 void AddProject(Project project, AddedProjectInfo addedProject)
265 ProjectConfig activeConfig = project.GetConfig(addedProject.activeConfig);
267 project.config = activeConfig;
268 addedProject.project = project;
272 char location[MAX_LOCATION];
273 GetRelativePathForProject(location, project);
276 addedProjects.Add(AddedProjectInfo { path = location, project = project });
278 projects.Add(project);
281 property const char * workspaceFile
285 char dir[MAX_DIRECTORY];
286 if(workspaceFile) delete workspaceFile;
287 if(workspaceDir) delete workspaceDir;
288 workspaceFile = CopyString(value);
289 StripLastDirectory(workspaceFile, dir);
290 workspaceDir = CopyUnixPath(dir);
292 get { return workspaceFile; }
295 property const char * projectDir
301 Project prj = projects.firstIterator.data;
302 return prj.topNode ? prj.topNode.path : null;
309 /*property Project project
319 projectDir = CopyString(project.topNode.path);
321 if(!project.config && activeConfig && activeConfig[0])
324 for(cfg = project.configurations.first; cfg; cfg = cfg.next)
325 if(!strcmp(cfg.name, activeConfig))
327 project.config = cfg;
330 project.config = project.configurations.first;
333 get { return project; }
339 if(workspaceFile && workspaceFile[0])
341 File file = FileOpen(workspaceFile, write);
344 WorkspaceFile wf { workspace = this };
345 WriteECONObject(file, class(WorkspaceFile), wf, 0);
353 char * CopyAbsolutePathFromRelative(const char * relative)
355 char name[MAX_LOCATION];
356 char absolute[MAX_LOCATION];
358 ProjectNode node = null;
360 GetLastDirectory(relative, name);
363 if((node = p.topNode.Find(name, false)))
371 node.GetFullFilePath(absolute, true);
372 return CopyString(absolute);
378 strcpy(absolute, p.topNode.path);
379 PathCatSlash(absolute, relative);
380 if(FileExists(absolute))
387 return CopyString(absolute);
389 strcpy(absolute, workspaceDir); //projectDir // CHECK?
390 PathCatSlash(absolute, relative);
391 if(FileExists(absolute))
392 return CopyString(absolute);
395 for(dir : sourceDirs)
397 strcpy(absolute, dir);
398 PathCatSlash(absolute, relative);
399 if(FileExists(absolute))
400 return CopyString(absolute);
407 char * CopyUnixPathWorkspaceRelativeOrAbsolute(const char * path)
409 if(IsPathInsideOf(path, workspaceDir))
411 char relativePath[MAX_LOCATION];
412 MakePathRelative(path, workspaceDir, relativePath);
413 return CopyUnixPath(relativePath);
416 return CopyUnixPath(path);
419 char * MakeRelativePath(char * buffer, const char * path)
421 char * result = null;
424 MakePathRelative(path, workspaceDir, buffer);
425 MakeSlashPath(buffer);
431 char * GetRelativePathForProject(char * buffer, Project project)
433 char * result = null;
434 if(buffer && project && project.topNode.path)
436 MakePathRelative(project.topNode.path, workspaceDir, buffer);
437 MakeSlashPath(buffer);
438 PathCatSlash(buffer, project.topNode.name);
444 Array<ProjectNode> GetAllProjectNodes(const char *fullPath, bool skipExcluded)
446 Array<ProjectNode> nodes = null;
447 for(project : projects)
450 if((node = project.topNode.FindByFullPath(fullPath, false)))
452 if(!skipExcluded || !node.GetIsExcluded(project.config))
454 if(!nodes) nodes = { };
462 Project GetFileOwner(const char * absolutePath, const char * objectFileExt)
464 Project owner = null;
467 if(prj.topNode.FindByFullPath(absolutePath, false))
474 GetObjectFileNode(absolutePath, &owner, null, objectFileExt);
478 void GetRelativePath(const char * absolutePath, char * relativePath, Project * owner, const char * objectFileExt)
480 Project prj = GetFileOwner(absolutePath, objectFileExt);
484 prj = projects.firstIterator.data;
487 MakePathRelative(absolutePath, prj.topNode.path, relativePath);
488 MakeSlashPath(relativePath);
491 relativePath[0] = '\0';
494 ProjectNode GetObjectFileNode(const char * filePath, Project * project, char * fullPath, const char * objectFileExt)
496 ProjectNode node = null;
497 char ext[MAX_EXTENSION];
498 GetExtension(filePath, ext);
501 IntermediateFileType type = IntermediateFileType::FromExtension(ext);
504 char fileName[MAX_FILENAME];
505 GetLastDirectory(filePath, fileName);
508 DotMain dotMain = DotMain::FromFileName(fileName);
509 for(prj : ide.workspace.projects)
511 if((node = prj.FindNodeByObjectFileName(fileName, type, dotMain, null, objectFileExt)))
517 const char * cfgName = prj.config ? prj.config.name : "";
518 char name[MAX_FILENAME];
519 CompilerConfig compiler = ideSettings.GetCompilerConfig(prj.lastBuildCompilerName);
520 DirExpression objDir = prj.GetObjDir(compiler, prj.config, bitDepth);
521 strcpy(fullPath, prj.topNode.path);
522 PathCatSlash(fullPath, objDir.dir);
523 node.GetObjectFileName(name, prj.configsNameCollisions[cfgName], type, dotMain, objectFileExt);
524 PathCatSlash(fullPath, name);
537 OpenedFileInfo UpdateOpenedFileInfo(const char * fileName, OpenedFileState state)
539 char absolutePath[MAX_LOCATION];
540 char relativePath[MAX_LOCATION];
542 GetSlashPathBuffer(absolutePath, fileName);
543 MakeRelativePath(relativePath, fileName);
544 ofi = FindOpenedFileInfo(relativePath, absolutePath);
549 ofi = OpenedFileInfo { path = CopyString(relativePath) };
550 openedFiles.Add(ofi);
553 ofi.modified = GetLocalTimeStamp();
559 Iterator<OpenedFileInfo> it { openedFiles };
561 openedFiles.Delete(it.pointer);
568 void LoadOpenedFileInfo(const char * path, OpenedFileState state, int lineNumber, int position, Point scroll, TimeStamp modified, Array<String> openedFilesNotFound)
570 char absolutePath[MAX_LOCATION];
571 char relativePath[MAX_LOCATION];
572 TimeStamp stamp = modified;
574 strcpy(absolutePath, workspaceDir);
575 PathCatSlash(absolutePath, path);
576 MakeRelativePath(relativePath, absolutePath);
577 if(!(exists = FileExists(absolutePath)))
578 stamp -= 60*60*24*20; // Days { 20 };
579 if(stamp > GetLocalTimeStamp() - 60*60*24*384) // Days { 384 });
581 if(state == closed || exists)
583 OpenedFileInfo ofi = FindOpenedFileInfo(relativePath, absolutePath);
585 openedFiles.Add(OpenedFileInfo { CopyString(relativePath), state, lineNumber, position, scroll, stamp });
586 // else silently drop duplicates if they should ever occur;
589 openedFilesNotFound.Add(CopyString(absolutePath));
591 // else silently discarding old or broken OpenedFileInfo entries;
594 void OpenPreviouslyOpenedFiles(bool noParsing)
596 Array<String> filePaths {};
598 for(ofi : openedFiles; ofi.state != closed)
599 filePaths.Add(CopyString(ofi.path));
600 for(path : filePaths)
603 char absolutePath[MAX_LOCATION];
604 strcpy(absolutePath, workspaceDir);
605 PathCatSlash(absolutePath, path);
606 file = ide.OpenFile(absolutePath, false, true, null, no, normal, noParsing);
611 ProjectNode node = prj.topNode.FindByFullPath(absolutePath, true);
613 node.EnsureVisible();
617 holdTracking = false;
622 OpenedFileInfo FindOpenedFileInfo(const char * relativePath, const char * absolutePath)
624 OpenedFileInfo result = null;
627 bool switchToRelative;
628 if((switchToRelative = !fstrcmp(absolutePath, e.path)) || !fstrcmp(relativePath, e.path))
634 result.path = CopyString(relativePath);
642 void RestorePreviouslyOpenedFileState(CodeEditor editor)
644 if((editor.openedFileInfo = UpdateOpenedFileInfo(editor.fileName, opened)))
645 editor.openedFileInfo.SetCodeEditorState(editor);
648 void UpdateSourceDirsArray(Array<String> dirs)
653 sourceDirs.Add(CopyString(s));
655 DropInvalidBreakpoints(null);
660 void RemoveProject(Project project)
662 Iterator<AddedProjectInfo> it { addedProjects };
665 if(it.data.project == project)
667 addedProjects.Remove(it.pointer);
671 projects.TakeOut(project);
673 DropInvalidBreakpoints(project);
675 ide.findInFilesDialog.RemoveProjectItem(project);
676 ide.UpdateToolBarActiveConfigs(false);
682 void SelectActiveConfig(const char * configName)
685 for(prj : ide.workspace.projects)
687 for(cfg : prj.configurations)
689 if(cfg.name && !strcmp(cfg.name, configName))
700 ide.UpdateToolBarActiveConfigs(true);
701 ide.projectView.Update(null);
704 ide.AdjustDebugMenus();
707 bool FindPath(ProjectNode node, const char * path)
709 if(node.type == file)
711 // TODO: Should this code be moved into a ProjectNode::absolutePath property? Taken from NodeProperties.ec
712 char filePath[MAX_LOCATION];
713 GetSlashPathBuffer(filePath, node.project.topNode.path);
714 PathCatSlash(filePath, node.path);
715 PathCatSlash(filePath, node.name);
717 if(!fstrcmp(filePath, path))
724 if(FindPath(n, path))
731 void ChangeBreakpoint(DataRow row, const char * location)
733 Breakpoint bp = (Breakpoint)(intptr)row.tag;
736 char * currentLoc = bp.CopyUserLocationString();
737 if(strcmp(location, currentLoc))
740 bp.location = CopyString(location);
743 newLoc = bp.CopyUserLocationString();
744 if(strcmp(newLoc, currentLoc))
746 ide.breakpointsView.UpdateBreakpoint(row);
754 // adding a breakpoint by typing it in the breakpoints view
755 // todo, parse location
756 // if good, make add breakpoint, make sure possibly previously entered ignore and level are reflected in breakpoint
759 //bp = Breakpoint { };
760 //row.tag = (int64)bp;
761 //breakpoints.Add(bp);
767 void ChangeBreakpointIgnore(DataRow row, int ignore)
769 Breakpoint bp = (Breakpoint)(intptr)row.tag;
777 void ChangeBreakpointLevel(DataRow row, int level)
779 Breakpoint bp = (Breakpoint)(intptr)row.tag;
787 void ChangeBreakpointCondition(DataRow row, const char * condition)
789 Breakpoint bp = (Breakpoint)(intptr)row.tag;
790 if(bp && !(!bp.condition && !(condition && condition[0])))
794 bp.condition = Watch { };
795 bp.condition.expression = CopyString(condition);
798 else if(!(condition && condition[0]))
804 else if(strcmp(condition, bp.condition.expression))
807 bp.condition = Watch { };
808 bp.condition.expression = CopyString(condition);
814 void RemoveBreakpoint(Breakpoint bp)
817 ide.breakpointsView.RemoveBreakpoint(bp);
818 ide.debugger.UpdateRemovedBreakpoint(bp);
820 Iterator<Breakpoint> it { breakpoints };
822 breakpoints.Remove(it.pointer);
826 for(document = ide.firstChild; document; document = document.next)
828 const char * fileName = document.fileName;
829 if(document.isDocument && fileName && document.created)
831 char winFilePath[MAX_LOCATION];
832 const char * slashPath = GetSlashPathBuffer(winFilePath, fileName);
834 if(!fstrcmp(slashPath, bp.absoluteFilePath))
836 CodeEditor codeEditor = (CodeEditor)document;
837 int boxH = codeEditor.editBox.clientSize.h;
838 Box box { 0, 0, 19, boxH - 1 };
839 document.Update(box);
849 void ParseLoadedBreakpoints()
851 for(bp : breakpoints; bp.location)
855 ide.breakpointsView.UpdateBreakpoint(bp.row);
859 void DropInvalidBreakpoints(Project removedProject) // think about not dropping BPs that are past end of file but simply disable them
860 { // why? when using a scm/vcs you might be alternating between two version of a file
861 if(breakpoints) // and anoyingly keep loosing breakpoints in the version of the file you are working on
864 for(bpLink = breakpoints.first; bpLink; bpLink = next)
866 Breakpoint bp = (Breakpoint)(intptr)bpLink.data;
870 if(bp.project == removedProject)
872 ide.breakpointsView.RemoveBreakpoint(bp);
873 RemoveBreakpoint(bp);
878 Project project = bp.project;
883 if(FindPath(p.topNode, bp.absoluteFilePath))
888 // Handle symbol loader modules:
890 char moduleName[MAX_FILENAME];
892 GetLastDirectory(bp.absoluteFilePath, moduleName);
893 // Tweak for automatically resolving symbol loader modules
894 sl = strstr(moduleName, ".main.ec");
895 if(sl && (*sl = 0, !strcmpi(moduleName, p.name)))
906 for(dir : sourceDirs)
908 if(IsPathInsideOf(bp.absoluteFilePath, dir))
916 ide.breakpointsView.RemoveBreakpoint(bp);
917 RemoveBreakpoint(bp);
922 ide.breakpointsView.Update(null);
928 if(!addedProjects) addedProjects = { };
929 if(!sourceDirs) sourceDirs = { };
930 if(!environmentVars) environmentVars = { };
931 if(!breakpoints) breakpoints = { };
932 if(!watches) watches = { };
933 if(!openedFiles) openedFiles = { };
939 delete workspaceFile;
941 delete commandLineArgs;
943 delete activeCompiler;
947 if(addedProjects) { addedProjects.Free(); delete addedProjects; }
948 if(sourceDirs) { sourceDirs.Free(); delete sourceDirs; }
949 if(environmentVars) { environmentVars.Free(); delete environmentVars; }
950 if(breakpoints) { breakpoints.Free(); delete breakpoints; }
951 if(watches) { watches.Free(); delete watches; }
952 if(openedFiles) { openedFiles.Free(); delete openedFiles; }
959 ide.outputView.buildBox.Clear();
960 ide.outputView.debugBox.Clear();
961 ide.callStackView.Clear();
962 ide.watchesView.Clear();
963 ide.threadsView.Clear();
964 ide.breakpointsView.Clear();
966 property::debugDir = "";
968 SetSourceDirs(sourceDirs);
982 Workspace LoadWorkspace(const char * filePath, const char * fromProjectFile)
985 Workspace workspace = null;
987 f = FileOpen(filePath, read);
990 Array<String> openedFilesNotFound { };
992 WorkspaceFile wf = null;
994 ECONParser parser { f = f };
996 result = parser.GetObject(class(WorkspaceFile), &wf);
997 if(result != success)
1002 workspace = LoadLegacyWorkspace(filePath, openedFilesNotFound);
1003 else if(wf.workspace)
1005 workspace = wf.workspace;
1007 workspace.workspaceFile = filePath;
1009 char absolutePath[MAX_LOCATION];
1012 Iterator<AddedProjectInfo> it { workspace.addedProjects };
1013 while(!done && (ahead || !(done = !it.Next())))
1015 // TODO: implement some type of time based pruning of "dea" added projects instead of just dropping them on the spot
1016 // TimeStamp modified; modified = GetLocalTimeStamp();
1017 // TimeStamp stamp = modified; if(stamp > GetLocalTimeStamp() - 60*60*24*20) // Days { 20 });
1018 AddedProjectInfo addedPrj = it.data;
1019 strcpy(absolutePath, workspace.workspaceDir);
1020 PathCatSlash(absolutePath, addedPrj.path);
1021 if(FileExists(absolutePath))
1023 Project loadedProject = LoadProject(absolutePath, null);
1026 workspace.AddProject(loadedProject, addedPrj);
1027 loadedProject.StartMonitoring();
1029 else if(workspace.projects.count == 0)
1036 // TODO: (#524) show message or something when added project fails to load;
1042 IteratorPointer notFound = it.pointer;
1044 workspace.addedProjects.Delete(notFound);
1050 for(bp : workspace.breakpoints)
1052 char * path = workspace.CopyAbsolutePathFromRelative(bp.relativeFilePath);
1056 bp.absoluteFilePath = path;
1060 bp.absoluteFilePath = "";
1062 if(workspace.openedFiles && workspace.openedFiles.count)
1064 List<OpenedFileInfo> openedFiles = workspace.openedFiles;
1065 workspace.openedFiles = { };
1066 for(of : openedFiles)
1068 workspace.LoadOpenedFileInfo(of.path, of.state, of.lineNumber, of.position, of.scroll, of.modified, openedFilesNotFound);
1080 if(!workspace.projects.first)
1084 project = LoadProject(fromProjectFile /*projectFilePath*/, null);
1087 char projectFilePath[MAX_LOCATION];
1088 strcpy(projectFilePath, workspace.workspaceFile);
1089 ChangeExtension(projectFilePath, ProjectExtension, projectFilePath);
1090 project = LoadProject(projectFilePath, null);
1094 project.StartMonitoring();
1095 workspace.AddProject(project, null);
1096 workspace.name = CopyString(project.name);
1100 MessageBox { type = ok, master = ide, contents = $"Workspace load file failed", text = $"Workspace Load File Error" }.Modal();
1106 if(openedFilesNotFound.count)
1110 String files = new char[MAX_LOCATION * 16];
1112 String msg = new char[MAX_LOCATION * 16 + 2048];
1115 if(openedFilesNotFound.count > 1)
1118 for(item : openedFilesNotFound)
1123 strcat(files, "\n...");
1126 strcat(files, "\n");
1127 strcat(files, item);
1130 sprintf(title, $"File%s not found", s);
1131 sprintf(msg, $"The following file%s could not be re-opened.%s", s, files);
1133 MessageBox { type = ok, master = ide, contents = msg, text = title }.Modal();
1139 openedFilesNotFound.Free();
1140 delete openedFilesNotFound;
1144 else if(fromProjectFile)
1146 //MessageBox { type = Ok, master = ide, contents = "Worspace load file failed", text = "Worspace Load File Error" }.Modal();
1148 //char projectFile[MAX_LOCATION];
1151 //strcpy(projectFile, filePath);
1152 //ChangeExtension(projectFile, ProjectExtension, projectFile);
1153 newProject = LoadProject(fromProjectFile /*projectFile*/, null);
1157 newProject.StartMonitoring();
1158 workspace = Workspace { property::workspaceFile = filePath };
1161 workspace.AddProject(newProject, null);
1168 ide.ChangeFileDialogsDirectory(workspace.workspaceDir, false);
1170 if(!workspace.activeCompiler || !workspace.activeCompiler[0])
1171 workspace.activeCompiler = defaultCompilerName;
1177 Workspace LoadLegacyWorkspace(const char * filePath, Array<String> openedFilesNotFound)
1180 Workspace workspace = null;
1182 file = FileOpen(filePath, read);
1187 char subSection[128];
1189 workspace = Workspace { activeCompiler = ideSettings.defaultCompiler, property::workspaceFile = filePath };
1192 file.Seek(0, start);
1199 Breakpoint bp = null;
1201 file.GetLine(buffer, 65536 - 1);
1202 TrimLSpaces(buffer, buffer);
1203 TrimRSpaces(buffer, buffer);
1206 if(buffer[0] == '~')
1210 TrimLSpaces(equal, equal);
1211 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Watches"))
1214 if(!workspace.watches) workspace.watches = { };
1215 workspace.watches.Add(wh);
1216 wh.expression = CopyString(equal);
1218 else if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
1223 wh.expression = CopyString(equal);
1227 else if(!strcmpi(section, "Execution Data") && !strcmpi(subSection, "Environment Variables"))
1229 String value = strchr(equal, '=');
1234 TrimRSpaces(equal, equal);
1235 TrimLSpaces(value, value);
1236 workspace.environmentVars.Add({ equal, value });
1240 else if(buffer[0] == '*')
1244 TrimLSpaces(equal, equal);
1245 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
1247 char * strEnabled = null;
1248 char * strIgnore = null;
1249 char * strLevel = null;
1250 char * strLine = null;
1251 char * strFile = null;
1254 if(strEnabled && strEnabled[0])
1256 strIgnore = strstr(strEnabled, ",");
1257 strIgnore[0] = '\0';
1260 if(strIgnore && strIgnore[0])
1262 strLevel = strstr(strIgnore, ",");
1266 if(strLevel && strLevel[0])
1268 strLine = strstr(strLevel, ",");
1272 if(strLine && strLine[0])
1274 strFile = strstr(strLine, ",");
1278 if(strEnabled && strEnabled[0] && strIgnore && strIgnore[0] &&
1279 strLevel && strLevel[0] && strLine && strLine[0] && strFile && strFile[0])
1286 TrimLSpaces(strEnabled, strEnabled);
1287 TrimRSpaces(strEnabled, strEnabled);
1288 TrimLSpaces(strIgnore, strIgnore);
1289 TrimRSpaces(strIgnore, strIgnore);
1290 TrimLSpaces(strLevel, strLevel);
1291 TrimRSpaces(strLevel, strLevel);
1292 TrimLSpaces(strLevel, strLevel);
1293 TrimRSpaces(strLevel, strLevel);
1294 TrimLSpaces(strFile, strFile);
1295 TrimRSpaces(strFile, strFile);
1297 enabled = (strEnabled[0] == '1');
1298 ignore = atoi(strIgnore);
1299 level = atoi(strLevel);
1300 line = atoi(strLine);
1302 bp = { type = user, enabled = enabled, ignore = ignore, level = level, line = line };
1303 if(!workspace.breakpoints)
1304 workspace.breakpoints = { };
1305 workspace.breakpoints.Add(bp);
1306 bp.location = CopyString(strFile);
1310 else if(buffer[0] == '=' || buffer[0] == '-')
1314 TrimLSpaces(equal, equal);
1315 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Source Directories"))
1316 workspace.sourceDirs.Add(CopyString(equal));
1317 else if(!strcmpi(section, "Opened Files"))
1319 OpenedFileState state = opened;
1325 char * comma = strchr(equal, ',');
1329 lineNumber = atoi(equal);
1333 else if(version >= 0.02)
1335 char * column = strchr(equal, ':');
1339 if(strcmpi(equal, "O"))
1343 column = strchr(equal, ':');
1347 lineNumber = atoi(equal);
1350 column = strchr(equal, ':');
1354 position = atoi(equal);
1357 column = strchr(equal, ':');
1361 scroll.x = atoi(equal);
1364 column = strchr(equal, ':');
1368 scroll.y = atoi(equal);
1377 workspace.LoadOpenedFileInfo(equal, state, lineNumber, position, scroll, GetLocalTimeStamp(), openedFilesNotFound);
1379 else if(!strcmpi(section, "Projects"))
1381 char projectFilePath[MAX_LOCATION];
1383 strcpy(projectFilePath, workspace.workspaceDir);
1384 PathCatSlash(projectFilePath, equal);
1385 newProject = LoadProject(projectFilePath, null);
1388 workspace.AddProject(newProject, null);
1389 newProject.StartMonitoring();
1391 else if(workspace.projects.count == 0)
1398 // TODO: (#524) show message or something when added project fails to load;
1402 else if(!strcmpi(buffer, "ECERE Workspace File"));
1403 else if(!strcmpi(buffer, "Version 0a"))
1405 else if(!strncmp(buffer, "Version ", 8))
1406 version = atof(&buffer[8]);
1407 else if(!strcmpi(buffer, "Workspace"))
1408 strcpy(section, buffer);
1409 else if(!strcmpi(buffer, "Projects"))
1410 strcpy(section, buffer);
1411 else if(!strcmpi(buffer, "Execution Data"))
1412 strcpy(section, buffer);
1413 else if(!strcmpi(buffer, "Debugger Data"))
1414 strcpy(section, buffer);
1415 else if(!strcmpi(buffer, "Source Directories"))
1416 strcpy(subSection, buffer);
1417 else if(!strcmpi(buffer, "Breakpoints"))
1418 strcpy(subSection, buffer);
1419 else if(!strcmpi(buffer, "Watches"))
1420 strcpy(subSection, buffer);
1421 else if(!strcmpi(buffer, "Environment Variables"))
1422 strcpy(subSection, buffer);
1423 else if(!strcmpi(buffer, "Opened Files"))
1425 strcpy(section, buffer);
1426 if(!workspace.openedFiles) workspace.openedFiles = { };
1428 else if(!strcmpi(buffer, "")) // | These two lines were commented out
1429 strcpy(subSection, buffer); // | Do they serve a purpose? They were there for copy paste when adding a new subsection
1432 equal = strstr(buffer, "=");
1435 if(!strcmpi(section, "Workspace"))
1438 TrimRSpaces(buffer, buffer);
1440 TrimLSpaces(equal, equal);
1441 if(!strcmpi(buffer, "Active Compiler"))
1443 CompilerConfig compiler = ideSettings.GetCompilerConfig(equal);
1445 workspace.activeCompiler = defaultCompilerName;
1447 workspace.activeCompiler = equal;
1450 if(!strcmpi(buffer, "Active Bit Depth"))
1452 int bitDepth = atoi(equal);
1453 if(!(bitDepth == 32 || bitDepth == 64))
1455 workspace.bitDepth = bitDepth;
1456 ide.toolBar.activeBitDepth.SelectRow(ide.toolBar.activeBitDepth.FindRow(bitDepth));
1459 else if(!strcmpi(section, "Execution Data"))
1462 TrimRSpaces(buffer, buffer);
1464 TrimLSpaces(equal, equal);
1465 if(!strcmpi(buffer, "Command Line Arguments"))
1466 workspace.commandLineArgs = equal;
1468 if(!strcmpi(buffer, "Environment Variables"))
1470 workspace.environmentVars.Free();
1471 delete workspace.environmentVars;
1472 workspace.environmentVars = { };
1476 else if(!strcmpi(section, "Debugger Data"))
1479 TrimRSpaces(buffer, buffer);
1481 TrimLSpaces(equal, equal);
1482 if(!strcmpi(buffer, "Debug Working Directory"))
1483 workspace.debugDir = equal;
1488 TrimRSpaces(buffer, buffer);
1490 TrimLSpaces(equal, equal);
1491 if(!strcmpi(buffer, "Active Configuration"))
1494 if(workspace.projects.last)
1496 prj = workspace.projects.lastIterator.data;
1497 for(cfg : prj.configurations)
1499 if(!strcmp(cfg.name, equal))
1507 else if(!strcmpi(buffer, "Modified Compiler Config") || !strcmpi(buffer, "Modified Linker Config"))
1510 if(workspace.projects.last)
1512 prj = workspace.projects.lastIterator.data;
1513 for(cfg : prj.configurations)
1515 if(!strcmp(cfg.name, equal))
1517 if(strstr(buffer, "Compiler"))
1518 cfg.compilingModified = true;
1520 cfg.linkingModified = true;
1526 else if(!strcmpi(buffer, "CommandLineArgs"))
1527 workspace.commandLineArgs = equal;
1528 else if(!strcmpi(buffer, "Breakpoint"))
1531 char * lineNum = strstr(equal, ",");
1542 char * absPath = strstr(lineNum, ",");
1549 char * relPath = strstr(absPath, ",");
1556 bp = { type = user, enabled = enabled, level = -1 };
1557 workspace.breakpoints.Add(bp);
1558 bp.line = atoi(lineNum);
1559 bp.location = relPath;
1567 else if(!strcmpi(buffer, "Watch"))
1570 workspace.watches.Add(wh);
1571 wh.expression = CopyString(equal);
1573 else if(!strcmpi(buffer, "SourceDir"))
1575 workspace.sourceDirs.Add(CopyString(equal));
1577 else if(!strcmpi(buffer, "DebugDir"))
1579 workspace.debugDir = equal;
1591 TimeStamp GetLocalTimeStamp()
1595 time.GetLocalTime();