3 /*static void ParseListValue(List<String> list, char * equal)
7 string = CopyString(equal);
11 comma = strstr(start, ",");
14 list.Add(CopyString(start));
24 enum OpenedFileState { unknown, opened, closed };
25 enum ValgrindLeakCheck
27 no, summary, yes, full;
31 get { return OnGetString(null, null, null); }
34 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
36 if(this >= no && this <= full)
39 strcpy(tempString, valgrindLeakCheckNames[this]);
40 return valgrindLeakCheckNames[this];
42 if(tempString && tempString[0])
47 static const char * valgrindLeakCheckNames[ValgrindLeakCheck] = { "no", "summary", "yes", "full" };
55 OpenedFileState state;
56 int lineNumber, position;
60 property bool trackingAllowed
62 get { return !holdTracking && ide && ide.workspace && !ide.workspace.holdTracking; }
65 void CaretMove(int line, int charPos)
67 if(trackingAllowed && (line != lineNumber || position != charPos))
71 ide.workspace.modified = true;
75 void ScrollChange(Point scroll)
79 this.scroll.x = scroll.x;
80 this.scroll.y = scroll.y;
81 ide.workspace.modified = true;
89 List<OpenedFileInfo> files = ide.workspace.openedFiles;
90 Iterator<OpenedFileInfo> it { files };
91 if(it.Find(this) && it.pointer != files.GetLast())
93 files.Move(it.pointer, files.GetPrev(files.GetLast()));
94 ide.workspace.modified = true;
108 char * workspaceFile;
110 char * commandLineArgs;
111 property const char * commandLineArgs { set { delete commandLineArgs; if(value) commandLineArgs = CopyString(value); } }
113 property const char * debugDir { set { delete debugDir; if(value) debugDir = CopyString(value); } }
117 property const char * compiler
119 set { delete compiler; if(value && value[0]) compiler = CopyString(value); }
120 get { return compiler && compiler[0] ? compiler : null; }
123 List<String> sourceDirs { };
124 Array<NamedString> environmentVars { };
125 List<Breakpoint> breakpoints { };
126 List<Watch> watches { };
127 List<OpenedFileInfo> openedFiles { };
128 List<Project> projects { };
137 userData = this, delay = 1.0;
140 static bool skip = true;
148 ide.MenuDebugStart(ide.debugStartResumeItem, 0);
149 ide.debugStart = false;
155 property const char * workspaceFile
159 char dir[MAX_DIRECTORY];
160 if(workspaceFile) delete workspaceFile;
161 if(workspaceDir) delete workspaceDir;
162 workspaceFile = CopyString(value);
163 StripLastDirectory(workspaceFile, dir);
164 workspaceDir = CopyUnixPath(dir);
166 get { return workspaceFile; }
169 property const char * projectDir
175 Project prj = projects.firstIterator.data;
176 return prj.topNode ? prj.topNode.path : null;
183 /*property Project project
193 projectDir = CopyString(project.topNode.path);
195 if(!project.config && activeConfig && activeConfig[0])
198 for(cfg = project.configurations.first; cfg; cfg = cfg.next)
199 if(!strcmp(cfg.name, activeConfig))
201 project.config = cfg;
204 project.config = project.configurations.first;
207 get { return project; }
213 // TODO: save these new settings when json format is ready
215 ValgrindLeakCheck vgLeakCheck;
220 vgLeakCheck = summary;
228 file = FileOpen(workspaceFile, write);
232 for(bp : breakpoints)
237 file.Printf("Breakpoint=1,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
239 file.Printf("Breakpoint=0,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
244 file.Printf("Watch=%s\n", wh.expression);
246 for(dir : sourceDirs)
247 file.Printf("SourceDir=%s\n", dir);
249 if(debugDir && debugDir[0])
250 file.Printf("DebugDir=%s\n", debugDir);
252 if(commandLineArgs && commandLineArgs[0])
253 file.Printf("CommandLineArgs=%s\n", commandLineArgs);
257 char indentation[128*3];
258 char path[MAX_LOCATION];
260 file.Printf("\nECERE Workspace File\n");
261 file.Printf("\nVersion 0.02\n");
262 file.Printf("\nWorkspace\n");
263 file.Printf("\n Active Compiler = %s\n", compiler ? compiler : defaultCompilerName);
264 file.Printf("\n Active Bit Depth = %d\n", bitDepth);
268 file.Printf("\n Projects\n\n");
271 char location[MAX_LOCATION];
272 MakePathRelative(prj.topNode.path, workspaceDir, location);
273 MakeSlashPath(location);
274 PathCatSlash(location, prj.topNode.name);
275 //strcat(location, ".epj");
277 file.Printf(" %s %s\n", "-", location);
280 file.Printf(" Active Configuration = %s\n", prj.config.name);
281 for(cfg : prj.configurations)
283 if(cfg.compilingModified)
284 file.Printf(" Modified Compiler Config = %s\n", cfg.name);
285 else if(cfg.linkingModified)
286 file.Printf(" Modified Linker Config = %s\n", cfg.name);
291 file.Printf("\n Execution Data\n");
292 if(commandLineArgs && commandLineArgs[0])
294 file.Printf("\n Command Line Arguments = ");
295 file.Puts(commandLineArgs);
299 if(environmentVars.count)
301 file.Printf("\n Environment Variables\n\n");
302 for(v : environmentVars)
312 file.Printf("\n Debugger Data\n");
313 // This really belonged in Execution Data...
314 if(debugDir && debugDir[0])
315 file.Printf("\n Debug Working Directory = %s\n", debugDir);
318 file.Printf("\n Source Directories\n");
319 for(dir : sourceDirs)
320 file.Printf(" = %s\n", dir);
323 for(bp : breakpoints)
330 file.Printf("\n Breakpoints\n\n");
338 file.Printf("\n Watches\n\n");
343 if(openedFiles.count)
345 file.Printf("\n Opened Files\n\n");
346 for(ofi : openedFiles)
350 char relativePath[MAX_LOCATION];
351 if(IsPathInsideOf(ofi.path, workspaceDir))
353 MakePathRelative(ofi.path, workspaceDir, relativePath);
354 MakeSlashPath(relativePath);
355 location = relativePath;
361 file.Printf(" %s %s:%d:%d:%d:%d:%s\n", chr, ofi.state == closed ? "C" : "O", ofi.lineNumber, ofi.position, ofi.scroll.x, ofi.scroll.y, location);
370 char * CopyAbsolutePathFromRelative(const char * relative)
372 char name[MAX_LOCATION];
373 char absolute[MAX_LOCATION];
375 ProjectNode node = null;
377 GetLastDirectory(relative, name);
380 if((node = p.topNode.Find(name, false)))
388 node.GetFullFilePath(absolute);
389 return CopyString(absolute);
395 strcpy(absolute, p.topNode.path);
396 PathCatSlash(absolute, relative);
397 if(FileExists(absolute))
404 return CopyString(absolute);
406 strcpy(absolute, workspaceDir); //projectDir // CHECK?
407 PathCatSlash(absolute, relative);
408 if(FileExists(absolute))
409 return CopyString(absolute);
412 for(dir : sourceDirs)
414 strcpy(absolute, dir);
415 PathCatSlash(absolute, relative);
416 if(FileExists(absolute))
417 return CopyString(absolute);
424 char * CopyUnixPathWorkspaceRelativeOrAbsolute(const char * path)
426 if(IsPathInsideOf(path, workspaceDir))
428 char relativePath[MAX_LOCATION];
429 MakePathRelative(path, workspaceDir, relativePath);
430 return CopyUnixPath(relativePath);
433 return CopyUnixPath(path);
436 char * MakeRelativePath(char * buffer, const char * path)
438 char * result = null;
441 MakePathRelative(path, workspaceDir, buffer);
442 MakeSlashPath(buffer);
448 char * GetRelativePathForProject(char * buffer, Project project)
450 char * result = null;
451 if(buffer && project && project.topNode.path)
453 MakePathRelative(project.topNode.path, workspaceDir, buffer);
454 MakeSlashPath(buffer);
455 PathCatSlash(buffer, project.topNode.name);
461 Array<ProjectNode> GetAllProjectNodes(const char *fullPath, bool skipExcluded)
463 Array<ProjectNode> nodes = null;
464 for(project : projects)
467 if((node = project.topNode.FindByFullPath(fullPath, false)))
469 if(!skipExcluded || !node.GetIsExcluded(project.config))
471 if(!nodes) nodes = { };
479 Project GetFileOwner(const char * absolutePath, const char * objectFileExt)
481 Project owner = null;
484 if(prj.topNode.FindByFullPath(absolutePath, false))
491 GetObjectFileNode(absolutePath, &owner, null, objectFileExt);
495 void GetRelativePath(const char * absolutePath, char * relativePath, Project * owner, const char * objectFileExt)
497 Project prj = GetFileOwner(absolutePath, objectFileExt);
501 prj = projects.firstIterator.data;
504 MakePathRelative(absolutePath, prj.topNode.path, relativePath);
505 MakeSlashPath(relativePath);
508 relativePath[0] = '\0';
511 ProjectNode GetObjectFileNode(const char * filePath, Project * project, char * fullPath, const char * objectFileExt)
513 ProjectNode node = null;
514 char ext[MAX_EXTENSION];
515 GetExtension(filePath, ext);
518 IntermediateFileType type = IntermediateFileType::FromExtension(ext);
521 char fileName[MAX_FILENAME];
522 GetLastDirectory(filePath, fileName);
525 DotMain dotMain = DotMain::FromFileName(fileName);
526 for(prj : ide.workspace.projects)
528 if((node = prj.FindNodeByObjectFileName(fileName, type, dotMain, null, objectFileExt)))
534 const char * cfgName = prj.config ? prj.config.name : "";
535 char name[MAX_FILENAME];
536 CompilerConfig compiler = ideSettings.GetCompilerConfig(prj.lastBuildCompilerName);
537 DirExpression objDir = prj.GetObjDir(compiler, prj.config, bitDepth);
538 strcpy(fullPath, prj.topNode.path);
539 PathCatSlash(fullPath, objDir.dir);
540 node.GetObjectFileName(name, prj.configsNameCollisions[cfgName], type, dotMain, objectFileExt);
541 PathCatSlash(fullPath, name);
554 OpenedFileInfo UpdateOpenedFileInfo(const char * fileName, OpenedFileState state)
556 char filePath[MAX_LOCATION];
557 OpenedFileInfo ofi = null;
558 GetSlashPathBuffer(filePath, fileName);
559 for(item : openedFiles)
561 if(!fstrcmp(item.path, filePath))
571 ofi = OpenedFileInfo { path = CopyString(filePath) };
572 openedFiles.Add(ofi);
580 Iterator<OpenedFileInfo> it { openedFiles };
582 openedFiles.Delete(it.pointer);
589 void UpdateSourceDirsArray(Array<String> dirs)
594 sourceDirs.Add(CopyString(s));
596 DropInvalidBreakpoints(null);
601 void RemoveProject(Project project)
603 Iterator<Project> it { projects };
607 for(bp : breakpoints)
608 DropInvalidBreakpoints(project);
610 ide.findInFilesDialog.RemoveProjectItem(project);
611 ide.UpdateToolBarActiveConfigs(false);
617 void SelectActiveConfig(const char * configName)
620 for(prj : ide.workspace.projects)
622 for(cfg : prj.configurations)
624 if(cfg.name && !strcmp(cfg.name, configName))
635 ide.UpdateToolBarActiveConfigs(true);
636 ide.projectView.Update(null);
639 ide.AdjustDebugMenus();
642 bool FindPath(ProjectNode node, const char * path)
644 if(node.type == file)
646 // TODO: Should this code be moved into a ProjectNode::absolutePath property? Taken from NodeProperties.ec
647 char filePath[MAX_LOCATION];
648 GetSlashPathBuffer(filePath, node.project.topNode.path);
649 PathCatSlash(filePath, node.path);
650 PathCatSlash(filePath, node.name);
652 if(!fstrcmp(filePath, path))
659 if(FindPath(n, path))
666 void ChangeBreakpoint(DataRow row, const char * location)
668 Breakpoint bp = (Breakpoint)(intptr)row.tag;
671 char * currentLoc = bp.CopyUserLocationString();
672 if(strcmp(location, currentLoc))
675 bp.location = location;
677 newLoc = bp.CopyUserLocationString();
678 if(strcmp(newLoc, currentLoc))
680 ide.breakpointsView.UpdateBreakpoint(row);
688 // adding a breakpoint by typing it in the breakpoints view
689 // todo, parse location
690 // if good, make add breakpoint, make sure possibly previously entered ignore and level are reflected in breakpoint
693 //bp = Breakpoint { };
694 //row.tag = (int64)bp;
695 //breakpoints.Add(bp);
701 void ChangeBreakpointIgnore(DataRow row, int ignore)
703 Breakpoint bp = (Breakpoint)(intptr)row.tag;
711 void ChangeBreakpointLevel(DataRow row, int level)
713 Breakpoint bp = (Breakpoint)(intptr)row.tag;
721 void ChangeBreakpointCondition(DataRow row, const char * condition)
723 Breakpoint bp = (Breakpoint)(intptr)row.tag;
724 if(bp && !(!bp.condition && !(condition && condition[0])))
728 bp.condition = Watch { };
729 bp.condition.expression = CopyString(condition);
732 else if(!(condition && condition[0]))
738 else if(strcmp(condition, bp.condition.expression))
741 bp.condition = Watch { };
742 bp.condition.expression = CopyString(condition);
748 void RemoveBreakpoint(Breakpoint bp)
751 ide.breakpointsView.RemoveBreakpoint(bp);
752 ide.debugger.UpdateRemovedBreakpoint(bp);
754 Iterator<Breakpoint> it { breakpoints };
756 breakpoints.Remove(it.pointer);
760 for(document = ide.firstChild; document; document = document.next)
762 const char * fileName = document.fileName;
763 if(document.isDocument && fileName && document.created)
765 char winFilePath[MAX_LOCATION];
766 const char * slashPath = GetSlashPathBuffer(winFilePath, fileName);
768 if(!fstrcmp(slashPath, bp.absoluteFilePath))
770 CodeEditor codeEditor = (CodeEditor)document;
771 int boxH = codeEditor.editBox.clientSize.h;
772 Box box { 0, 0, 19, boxH - 1 };
773 document.Update(box);
783 void ParseLoadedBreakpoints()
785 for(bp : breakpoints; bp.location)
788 ide.breakpointsView.UpdateBreakpoint(bp.row);
792 void DropInvalidBreakpoints(Project removedProject)
795 for(bpLink = breakpoints.first; bpLink; bpLink = next)
797 Breakpoint bp = (Breakpoint)(intptr)bpLink.data;
804 if(bp.project == removedProject)
806 ide.breakpointsView.RemoveBreakpoint(bp);
807 RemoveBreakpoint(bp);
812 Project project = bp.project;
817 if(FindPath(p.topNode, bp.absoluteFilePath))
822 // Handle symbol loader modules:
824 char moduleName[MAX_FILENAME];
826 GetLastDirectory(bp.absoluteFilePath, moduleName);
827 // Tweak for automatically resolving symbol loader modules
828 sl = strstr(moduleName, ".main.ec");
829 if(sl && (*sl = 0, !strcmpi(moduleName, p.name)))
840 for(dir : sourceDirs)
842 if(IsPathInsideOf(bp.absoluteFilePath, dir))
850 ide.breakpointsView.RemoveBreakpoint(bp);
851 RemoveBreakpoint(bp);
857 ide.breakpointsView.Update(null);
862 delete workspaceFile;
864 delete commandLineArgs;
876 ide.outputView.buildBox.Clear();
877 ide.outputView.debugBox.Clear();
878 ide.callStackView.Clear();
879 ide.watchesView.Clear();
880 ide.threadsView.Clear();
881 ide.breakpointsView.Clear();
883 property::debugDir = "";
885 SetSourceDirs(sourceDirs);
894 environmentVars.Free();
903 Workspace LoadWorkspace(const char * filePath, const char * fromProjectFile)
906 Workspace workspace = null;
908 file = FileOpen(filePath, read);
911 OldList openedFilesNotFound { };
914 char subSection[128];
916 workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = filePath };
925 Breakpoint bp = null;
927 file.GetLine(buffer, 65536 - 1);
928 TrimLSpaces(buffer, buffer);
929 TrimRSpaces(buffer, buffer);
936 TrimLSpaces(equal, equal);
937 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Watches"))
940 workspace.watches.Add(wh);
941 wh.expression = CopyString(equal);
943 else if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
948 wh.expression = CopyString(equal);
952 else if(!strcmpi(section, "Execution Data") && !strcmpi(subSection, "Environment Variables"))
954 String value = strchr(equal, '=');
959 TrimRSpaces(equal, equal);
960 TrimLSpaces(value, value);
961 workspace.environmentVars.Add({ equal, value });
965 else if(buffer[0] == '*')
969 TrimLSpaces(equal, equal);
970 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
972 char * strEnabled = null;
973 char * strIgnore = null;
974 char * strLevel = null;
975 char * strLine = null;
976 char * strFile = null;
979 if(strEnabled && strEnabled[0])
981 strIgnore = strstr(strEnabled, ",");
985 if(strIgnore && strIgnore[0])
987 strLevel = strstr(strIgnore, ",");
991 if(strLevel && strLevel[0])
993 strLine = strstr(strLevel, ",");
997 if(strLine && strLine[0])
999 strFile = strstr(strLine, ",");
1003 if(strEnabled && strEnabled[0] && strIgnore && strIgnore[0] &&
1004 strLevel && strLevel[0] && strLine && strLine[0] && strFile && strFile[0])
1011 TrimLSpaces(strEnabled, strEnabled);
1012 TrimRSpaces(strEnabled, strEnabled);
1013 TrimLSpaces(strIgnore, strIgnore);
1014 TrimRSpaces(strIgnore, strIgnore);
1015 TrimLSpaces(strLevel, strLevel);
1016 TrimRSpaces(strLevel, strLevel);
1017 TrimLSpaces(strLevel, strLevel);
1018 TrimRSpaces(strLevel, strLevel);
1019 TrimLSpaces(strFile, strFile);
1020 TrimRSpaces(strFile, strFile);
1022 enabled = (strEnabled[0] == '1');
1023 ignore = atoi(strIgnore);
1024 level = atoi(strLevel);
1025 line = atoi(strLine);
1027 bp = { type = user, enabled = enabled, ignore = ignore, level = level, line = line };
1028 workspace.breakpoints.Add(bp);
1029 bp.location = strFile;
1033 else if(buffer[0] == '=' || buffer[0] == '-')
1037 TrimLSpaces(equal, equal);
1038 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Source Directories"))
1039 workspace.sourceDirs.Add(CopyString(equal));
1040 else if(!strcmpi(section, "Opened Files"))
1042 OpenedFileState state = opened;
1046 char absolutePath[MAX_LOCATION];
1047 strcpy(absolutePath, workspace.workspaceDir);
1050 char * comma = strchr(equal, ',');
1054 lineNumber = atoi(equal);
1058 else if(version >= 0.02)
1060 char * column = strchr(equal, ':');
1064 if(strcmpi(equal, "O"))
1068 column = strchr(equal, ':');
1072 lineNumber = atoi(equal);
1075 column = strchr(equal, ':');
1079 position = atoi(equal);
1082 column = strchr(equal, ':');
1086 scroll.x = atoi(equal);
1089 column = strchr(equal, ':');
1093 scroll.y = atoi(equal);
1102 PathCatSlash(absolutePath, equal);
1104 if(state == closed || FileExists(absolutePath))
1105 workspace.openedFiles.Add(OpenedFileInfo { path = CopyString(absolutePath), state = state, lineNumber = lineNumber, position = position, scroll = scroll });
1107 openedFilesNotFound.Add(NamedItem { name = CopyString(equal) });
1109 else if(!strcmpi(section, "Projects"))
1111 char projectFilePath[MAX_LOCATION];
1113 strcpy(projectFilePath, workspace.workspaceDir);
1114 PathCatSlash(projectFilePath, equal);
1115 newProject = LoadProject(projectFilePath, null);
1118 workspace.projects.Add(newProject);
1119 newProject.StartMonitoring();
1121 else if(workspace.projects.count == 0)
1128 // TODO: show message or something when added project fails to load
1129 // http://ecere.com/mantis/view.php?id=524
1133 else if(!strcmpi(buffer, "ECERE Workspace File"));
1134 else if(!strcmpi(buffer, "Version 0a"))
1136 else if(!strncmp(buffer, "Version ", 8))
1137 version = atof(&buffer[8]);
1138 else if(!strcmpi(buffer, "Workspace"))
1139 strcpy(section, buffer);
1140 else if(!strcmpi(buffer, "Projects"))
1141 strcpy(section, buffer);
1142 else if(!strcmpi(buffer, "Execution Data"))
1143 strcpy(section, buffer);
1144 else if(!strcmpi(buffer, "Debugger Data"))
1145 strcpy(section, buffer);
1146 else if(!strcmpi(buffer, "Source Directories"))
1147 strcpy(subSection, buffer);
1148 else if(!strcmpi(buffer, "Breakpoints"))
1149 strcpy(subSection, buffer);
1150 else if(!strcmpi(buffer, "Watches"))
1151 strcpy(subSection, buffer);
1152 else if(!strcmpi(buffer, "Environment Variables"))
1153 strcpy(subSection, buffer);
1154 else if(!strcmpi(buffer, "Opened Files"))
1155 strcpy(section, buffer);
1156 else if(!strcmpi(buffer, "")) // | These two lines were commented out
1157 strcpy(subSection, buffer); // | Do they serve a purpose? They were there for copy paste when adding a new subsection
1160 equal = strstr(buffer, "=");
1163 if(!strcmpi(section, "Workspace"))
1166 TrimRSpaces(buffer, buffer);
1168 TrimLSpaces(equal, equal);
1169 if(!strcmpi(buffer, "Active Compiler"))
1171 CompilerConfig compiler = ideSettings.GetCompilerConfig(equal);
1173 workspace.compiler = defaultCompilerName;
1175 workspace.compiler = equal;
1178 if(!strcmpi(buffer, "Active Bit Depth"))
1180 int bitDepth = atoi(equal);
1181 if(!(bitDepth == 32 || bitDepth == 64))
1183 workspace.bitDepth = bitDepth;
1184 ide.toolBar.activeBitDepth.SelectRow(ide.toolBar.activeBitDepth.FindRow(bitDepth));
1187 else if(!strcmpi(section, "Execution Data"))
1190 TrimRSpaces(buffer, buffer);
1192 TrimLSpaces(equal, equal);
1193 if(!strcmpi(buffer, "Command Line Arguments"))
1194 workspace.commandLineArgs = equal;
1196 if(!strcmpi(buffer, "Environment Variables"))
1198 workspace.environmentVars.Free();
1199 delete workspace.environmentVars;
1200 workspace.environmentVars = { };
1204 else if(!strcmpi(section, "Debugger Data"))
1207 TrimRSpaces(buffer, buffer);
1209 TrimLSpaces(equal, equal);
1210 if(!strcmpi(buffer, "Debug Working Directory"))
1211 workspace.debugDir = equal;
1216 TrimRSpaces(buffer, buffer);
1218 TrimLSpaces(equal, equal);
1219 if(!strcmpi(buffer, "Active Configuration"))
1222 if(workspace.projects.last)
1224 prj = workspace.projects.lastIterator.data;
1225 for(cfg : prj.configurations)
1227 if(!strcmp(cfg.name, equal))
1235 else if(!strcmpi(buffer, "Modified Compiler Config") || !strcmpi(buffer, "Modified Linker Config"))
1238 if(workspace.projects.last)
1240 prj = workspace.projects.lastIterator.data;
1241 for(cfg : prj.configurations)
1243 if(!strcmp(cfg.name, equal))
1245 if(strstr(buffer, "Compiler"))
1246 cfg.compilingModified = true;
1248 cfg.linkingModified = true;
1254 else if(!strcmpi(buffer, "CommandLineArgs"))
1255 workspace.commandLineArgs = equal;
1256 else if(!strcmpi(buffer, "Breakpoint"))
1259 char * lineNum = strstr(equal, ",");
1270 char * absPath = strstr(lineNum, ",");
1277 char * relPath = strstr(absPath, ",");
1284 bp = { type = user, enabled = enabled, level = -1 };
1285 workspace.breakpoints.Add(bp);
1286 bp.line = atoi(lineNum);
1287 bp.location = relPath;
1295 else if(!strcmpi(buffer, "Watch"))
1298 workspace.watches.Add(wh);
1299 wh.expression = CopyString(equal);
1301 else if(!strcmpi(buffer, "SourceDir"))
1303 workspace.sourceDirs.Add(CopyString(equal));
1305 else if(!strcmpi(buffer, "DebugDir"))
1307 workspace.debugDir = equal;
1319 if(!workspace.projects.first)
1323 project = LoadProject(fromProjectFile /*projectFilePath*/, null);
1326 char projectFilePath[MAX_LOCATION];
1327 strcpy(projectFilePath, workspace.workspaceFile);
1328 ChangeExtension(projectFilePath, ProjectExtension, projectFilePath);
1329 project = LoadProject(projectFilePath, null);
1333 project.StartMonitoring();
1334 workspace.projects.Add(project);
1335 workspace.name = CopyString(project.name);
1339 MessageBox { type = ok, master = ide, contents = $"Workspace load file failed", text = $"Workspace Load File Error" }.Modal();
1345 if(openedFilesNotFound.first)
1349 String files = new char[MAX_LOCATION * 16];
1351 String msg = new char[MAX_LOCATION * 16 + 2048];
1355 item = openedFilesNotFound.first;
1359 for(item = openedFilesNotFound.first; item; item = item.next)
1364 strcat(files, "\n...");
1367 strcat(files, "\n");
1368 strcat(files, item.name);
1371 sprintf(title, $"File%s not found", s);
1372 sprintf(msg, $"The following file%s could not be re-opened.%s", s, files);
1374 MessageBox { type = ok, master = ide, contents = msg, text = title }.Modal();
1379 openedFilesNotFound.Free(OldLink::Free);
1382 openedFilesNotFound.Free(OldLink::Free);
1384 else if(fromProjectFile)
1386 //MessageBox { type = Ok, master = ide, contents = "Worspace load file failed", text = "Worspace Load File Error" }.Modal();
1387 //char projectFile[MAX_LOCATION];
1390 //strcpy(projectFile, filePath);
1391 //ChangeExtension(projectFile, ProjectExtension, projectFile);
1392 newProject = LoadProject(fromProjectFile /*projectFile*/, null);
1396 newProject.StartMonitoring();
1397 workspace = Workspace { workspaceFile = filePath };
1399 workspace.projects.Add(newProject);
1406 ide.ChangeFileDialogsDirectory(workspace.workspaceDir, false);
1408 if(!workspace.compiler || !workspace.compiler[0])
1409 workspace.compiler = defaultCompilerName;