3 //bool eString_PathInsideOf(char * path, char * of);
5 /*static void ParseListValue(List<String> list, char * equal)
9 string = CopyString(equal);
13 comma = strstr(start, ",");
16 list.Add(CopyString(start));
26 enum OpenedFileState { unknown, opened, closed };
34 OpenedFileState state;
35 int lineNumber, position;
39 property bool trackingAllowed
41 get { return !holdTracking && ide && ide.workspace && !ide.workspace.holdTracking; }
44 void CaretMove(int line, int charPos)
46 if(trackingAllowed && (line != lineNumber || position != charPos))
50 ide.workspace.modified = true;
54 void ScrollChange(Point scroll)
58 this.scroll.x = scroll.x;
59 this.scroll.y = scroll.y;
60 ide.workspace.modified = true;
68 List<OpenedFileInfo> files = ide.workspace.openedFiles;
69 Iterator<OpenedFileInfo> it { files };
70 if(it.Find(this) && it.pointer != files.GetLast())
72 files.Move(it.pointer, files.GetPrev(files.GetLast()));
73 ide.workspace.modified = true;
89 char * commandLineArgs;
90 property char * commandLineArgs { set { delete commandLineArgs; if(value) commandLineArgs = CopyString(value); } }
92 property char * debugDir { set { delete debugDir; if(value) debugDir = CopyString(value); } }
96 property char * compiler
98 set { delete compiler; if(value && value[0]) compiler = CopyString(value); }
99 get { return compiler && compiler[0] ? compiler : null; }
102 List<String> sourceDirs { };
103 Array<NamedString> environmentVars { };
104 List<Breakpoint> breakpoints { };
105 List<Watch> watches { };
106 List<OpenedFileInfo> openedFiles { };
107 List<Project> projects { };
116 userData = this, delay = 2.5;
125 property char * workspaceFile
129 char dir[MAX_DIRECTORY];
130 if(workspaceFile) delete workspaceFile;
131 if(workspaceDir) delete workspaceDir;
132 workspaceFile = CopyString(value);
133 StripLastDirectory(workspaceFile, dir);
134 workspaceDir = CopyUnixPath(dir);
136 get { return workspaceFile; }
139 property char * projectDir
145 Project prj = projects.firstIterator.data;
146 return prj.topNode ? prj.topNode.path : null;
153 /*property Project project
163 projectDir = CopyString(project.topNode.path);
165 if(!project.config && activeConfig && activeConfig[0])
168 for(cfg = project.configurations.first; cfg; cfg = cfg.next)
169 if(!strcmp(cfg.name, activeConfig))
171 project.config = cfg;
174 project.config = project.configurations.first;
177 get { return project; }
189 file = FileOpen(workspaceFile, write);
193 for(bp : breakpoints)
198 file.Printf("Breakpoint=1,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
200 file.Printf("Breakpoint=0,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
205 file.Printf("Watch=%s\n", wh.expression);
207 for(dir : sourceDirs)
208 file.Printf("SourceDir=%s\n", dir);
210 if(debugDir && debugDir[0])
211 file.Printf("DebugDir=%s\n", debugDir);
213 if(commandLineArgs && commandLineArgs[0])
214 file.Printf("CommandLineArgs=%s\n", commandLineArgs);
218 char indentation[128*3];
219 char path[MAX_LOCATION];
221 file.Printf("\nECERE Workspace File\n");
222 file.Printf("\nVersion 0.02\n");
223 file.Printf("\nWorkspace\n");
224 file.Printf("\n Active Compiler = %s\n", compiler ? compiler : defaultCompilerName);
228 file.Printf("\n Projects\n\n");
231 char location[MAX_LOCATION];
232 MakePathRelative(prj.topNode.path, workspaceDir, location);
233 MakeSlashPath(location);
234 PathCatSlash(location, prj.topNode.name);
235 //strcat(location, ".epj");
237 file.Printf(" %s %s\n", "-", location);
240 file.Printf(" Active Configuration = %s\n", prj.config.name);
241 for(cfg : prj.configurations)
243 if(cfg.compilingModified)
244 file.Printf(" Modified Compiler Config = %s\n", cfg.name);
245 else if(cfg.linkingModified)
246 file.Printf(" Modified Linker Config = %s\n", cfg.name);
251 file.Printf("\n Execution Data\n");
252 if(commandLineArgs && commandLineArgs[0])
253 file.Printf("\n Command Line Arguments = %s\n", commandLineArgs);
255 if(environmentVars.count)
257 file.Printf("\n Environment Variables\n\n");
258 for(v : environmentVars)
259 file.Printf(" ~ %s = %s\n", v.name, v.string);
262 file.Printf("\n Debugger Data\n");
263 // This really belonged in Execution Data...
264 if(debugDir && debugDir[0])
265 file.Printf("\n Debug Working Directory = %s\n", debugDir);
268 file.Printf("\n Source Directories\n");
269 for(dir : sourceDirs)
270 file.Printf(" = %s\n", dir);
273 for(bp : breakpoints)
280 file.Printf("\n Breakpoints\n\n");
288 file.Printf("\n Watches\n\n");
293 if(openedFiles.count)
295 file.Printf("\n Opened Files\n\n");
296 for(ofi : openedFiles)
300 char relativePath[MAX_LOCATION];
301 if(eString_PathInsideOf(ofi.path, workspaceDir))
303 MakePathRelative(ofi.path, workspaceDir, relativePath);
304 MakeSlashPath(relativePath);
305 location = relativePath;
311 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);
320 char * GetAbsolutePathFromRelative(char * relative)
322 char name[MAX_LOCATION];
323 char absolute[MAX_LOCATION];
326 GetLastDirectory(relative, name);
329 if(p.topNode.Find(name, false))
337 strcpy(absolute, prj.topNode.path);
338 PathCatSlash(absolute, relative);
339 return CopyString(absolute);
345 strcpy(absolute, p.topNode.path);
346 PathCatSlash(absolute, relative);
347 if(FileExists(absolute))
354 return CopyString(absolute);
356 strcpy(absolute, workspaceDir); //projectDir // CHECK?
357 PathCatSlash(absolute, relative);
358 if(FileExists(absolute))
359 return CopyString(absolute);
362 for(dir : sourceDirs)
364 strcpy(absolute, dir);
365 PathCatSlash(absolute, relative);
366 if(FileExists(absolute))
367 return CopyString(absolute);
374 char * GetPathWorkspaceRelativeOrAbsolute(char * path)
376 if(eString_PathInsideOf(path, workspaceDir))
378 char relativePath[MAX_LOCATION];
379 MakePathRelative(path, workspaceDir, relativePath);
380 return CopyUnixPath(relativePath);
383 return CopyUnixPath(path);
386 OpenedFileInfo UpdateOpenedFileInfo(char * fileName, OpenedFileState state)
388 char filePath[MAX_LOCATION];
389 OpenedFileInfo ofi = null;
390 GetSlashPathBuffer(filePath, fileName);
391 for(item : openedFiles)
393 if(!fstrcmp(item.path, filePath))
403 ofi = OpenedFileInfo { path = CopyString(filePath) };
404 openedFiles.Add(ofi);
412 Iterator<OpenedFileInfo> it { openedFiles };
414 openedFiles.Delete(it.pointer);
421 void UpdateSourceDirsArray(Array<String> dirs)
429 sourceDirs.Add(CopyString(s));
431 DropInvalidBreakpoints();
436 void RemoveProject(Project project)
438 Iterator<Project> it { projects };
442 DropInvalidBreakpoints();
444 ide.findInFilesDialog.RemoveProjectItem(project);
450 bool FindPath(ProjectNode node, char * path)
452 if(node.type == file)
454 // TODO: Should this code be moved into a ProjectNode::absolutePath property? Taken from NodeProperties.ec
455 char filePath[MAX_LOCATION];
456 GetSlashPathBuffer(filePath, node.project.topNode.path);
457 PathCatSlash(filePath, node.path);
458 PathCatSlash(filePath, node.name);
460 if(!fstrcmp(filePath, path))
467 if(FindPath(n, path))
474 void ChangeBreakpoint(DataRow row, char * location)
476 Breakpoint bp = (Breakpoint)row.tag;
479 char * currentLoc = bp.LocationToString();
480 if(strcmp(location, currentLoc))
482 // todo, parse location
483 // if good, make changes to breakpoint, according to execution state delete and place breakpoint
484 ide.breakpointsView.UpdateBreakpoint(row); // this is the else
491 // adding a breakpoint by typing it in the breakpoints view
492 // todo, parse location
493 // if good, make add breakpoint, make sure possibly previously entered ignore and level are reflected in breakpoint
496 //bp = Breakpoint { };
498 //breakpoints.Add(bp);
504 void ChangeBreakpointIgnore(DataRow row, int ignore)
506 Breakpoint bp = (Breakpoint)row.tag;
514 void ChangeBreakpointLevel(DataRow row, int level)
516 Breakpoint bp = (Breakpoint)row.tag;
524 void ChangeBreakpointCondition(DataRow row, char * condition)
526 Breakpoint bp = (Breakpoint)row.tag;
527 if(bp && !(!bp.condition && !(condition && condition[0])))
531 bp.condition = Watch { };
532 bp.condition.expression = CopyString(condition);
535 else if(!(condition && condition[0]))
541 else if(strcmp(condition, bp.condition.expression))
544 bp.condition = Watch { };
545 bp.condition.expression = CopyString(condition);
551 void RemoveBreakpoint(Breakpoint bp)
554 ide.breakpointsView.RemoveBreakpoint(bp);
555 ide.debugger.UpdateRemovedBreakpoint(bp);
557 Iterator<Breakpoint> it { breakpoints };
559 breakpoints.Remove(it.pointer);
563 for(document = ide.firstChild; document; document = document.next)
565 char * fileName = document.fileName;
566 if(document.isDocument && fileName && document.created)
568 char winFilePath[MAX_LOCATION];
569 char * slashPath = GetSlashPathBuffer(winFilePath, fileName);
571 if(!fstrcmp(slashPath, bp.absoluteFilePath))
573 CodeEditor codeEditor = (CodeEditor)document;
574 int boxH = codeEditor.editBox.clientSize.h;
575 Box box { 0, 0, 19, boxH - 1 };
576 document.Update(box);
586 void DropInvalidBreakpoints()
589 for(bpLink = breakpoints.first; bpLink; bpLink = next)
591 Breakpoint bp = (Breakpoint)bpLink.data;
596 Project project = null;
599 if(FindPath(p.topNode, bp.absoluteFilePath))
608 for(dir : sourceDirs)
610 if(eString_PathInsideOf(bp.absoluteFilePath, dir))
618 ide.breakpointsView.RemoveBreakpoint(bp);
619 RemoveBreakpoint(bp);
624 ide.breakpointsView.Update(null);
629 delete workspaceFile;
631 delete commandLineArgs;
643 ide.outputView.buildBox.Clear();
644 ide.outputView.debugBox.Clear();
645 ide.callStackView.Clear();
646 ide.watchesView.Clear();
647 ide.threadsView.Clear();
648 ide.breakpointsView.Clear();
650 property::debugDir = "";
652 SetSourceDirs(sourceDirs);
661 environmentVars.Free();
670 Workspace LoadWorkspace(char * filePath, char * fromProjectFile)
673 Workspace workspace = null;
675 file = FileOpen(filePath, read);
678 OldList openedFilesNotFound { };
680 workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = filePath };
687 char subSection[128];
696 file.GetLine(buffer, 65536 - 1);
697 TrimLSpaces(buffer, buffer);
698 TrimRSpaces(buffer, buffer);
705 TrimLSpaces(equal, equal);
706 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Watches"))
709 workspace.watches.Add(wh);
710 wh.expression = CopyString(equal);
712 else if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
717 wh.expression = CopyString(equal);
721 else if(!strcmpi(section, "Execution Data") && !strcmpi(subSection, "Environment Variables"))
723 String value = strchr(equal, '=');
728 TrimRSpaces(equal, equal);
729 TrimLSpaces(value, value);
730 workspace.environmentVars.Add({ equal, value });
734 else if(buffer[0] == '*')
738 TrimLSpaces(equal, equal);
739 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Breakpoints"))
741 char * strEnabled = null;
742 char * strIgnore = null;
743 char * strLevel = null;
744 char * strLine = null;
745 char * strFile = null;
748 if(strEnabled && strEnabled[0])
750 strIgnore = strstr(strEnabled, ",");
754 if(strIgnore && strIgnore[0])
756 strLevel = strstr(strIgnore, ",");
760 if(strLevel && strLevel[0])
762 strLine = strstr(strLevel, ",");
766 if(strLine && strLine[0])
768 strFile = strstr(strLine, ",");
772 if(strEnabled && strEnabled[0] && strIgnore && strIgnore[0] &&
773 strLevel && strLevel[0] && strLine && strLine[0] && strFile && strFile[0])
780 TrimLSpaces(strEnabled, strEnabled);
781 TrimRSpaces(strEnabled, strEnabled);
782 TrimLSpaces(strIgnore, strIgnore);
783 TrimRSpaces(strIgnore, strIgnore);
784 TrimLSpaces(strLevel, strLevel);
785 TrimRSpaces(strLevel, strLevel);
786 TrimLSpaces(strLevel, strLevel);
787 TrimRSpaces(strLevel, strLevel);
788 TrimLSpaces(strFile, strFile);
789 TrimRSpaces(strFile, strFile);
791 enabled = (strEnabled[0] == '1');
792 ignore = atoi(strIgnore);
793 level = atoi(strLevel);
794 line = atoi(strLine);
796 bp = { type = user, enabled = enabled, ignore = ignore, level = level, line = line };
797 workspace.breakpoints.Add(bp);
798 bp.relativeFilePath = CopyString(strFile);
799 bp.absoluteFilePath = workspace.GetAbsolutePathFromRelative(strFile);
800 if(!bp.absoluteFilePath)
801 bp.absoluteFilePath = CopyString("");
805 else if(buffer[0] == '=' || buffer[0] == '-')
809 TrimLSpaces(equal, equal);
810 if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Source Directories"))
811 workspace.sourceDirs.Add(CopyString(equal));
812 else if(!strcmpi(section, "Opened Files"))
814 OpenedFileState state = opened;
818 char absolutePath[MAX_LOCATION];
819 strcpy(absolutePath, workspace.workspaceDir);
822 char * comma = strchr(equal, ',');
826 lineNumber = atoi(equal);
830 else if(version >= 0.02f)
832 char * column = strchr(equal, ':');
836 if(strcmpi(equal, "O"))
840 column = strchr(equal, ':');
844 lineNumber = atoi(equal);
847 column = strchr(equal, ':');
851 position = atoi(equal);
854 column = strchr(equal, ':');
858 scroll.x = atoi(equal);
861 column = strchr(equal, ':');
865 scroll.y = atoi(equal);
874 PathCatSlash(absolutePath, equal);
876 if(state == closed || FileExists(absolutePath))
877 workspace.openedFiles.Add(OpenedFileInfo { path = CopyString(absolutePath), state = state, lineNumber = lineNumber, position = position, scroll = scroll });
879 openedFilesNotFound.Add(NamedItem { name = CopyString(equal) });
881 else if(!strcmpi(section, "Projects"))
883 char projectFilePath[MAX_LOCATION];
885 strcpy(projectFilePath, workspace.workspaceDir);
886 PathCatSlash(projectFilePath, equal);
887 newProject = LoadProject(projectFilePath);
889 workspace.projects.Add(newProject);
890 else if(workspace.projects.count == 0)
897 // TODO: show message or something when added project fails to load
898 // http://ecere.com/mantis/view.php?id=524
902 else if(!strcmpi(buffer, "ECERE Workspace File"));
903 else if(!strcmpi(buffer, "Version 0a"))
905 else if(!strncmp(buffer, "Version ", 8))
906 version = atof(&buffer[8]);
907 else if(!strcmpi(buffer, "Workspace"))
908 strcpy(section, buffer);
909 else if(!strcmpi(buffer, "Projects"))
910 strcpy(section, buffer);
911 else if(!strcmpi(buffer, "Execution Data"))
912 strcpy(section, buffer);
913 else if(!strcmpi(buffer, "Debugger Data"))
914 strcpy(section, buffer);
915 else if(!strcmpi(buffer, "Source Directories"))
916 strcpy(subSection, buffer);
917 else if(!strcmpi(buffer, "Breakpoints"))
918 strcpy(subSection, buffer);
919 else if(!strcmpi(buffer, "Watches"))
920 strcpy(subSection, buffer);
921 else if(!strcmpi(buffer, "Environment Variables"))
922 strcpy(subSection, buffer);
923 else if(!strcmpi(buffer, "Opened Files"))
924 strcpy(section, buffer);
925 else if(!strcmpi(buffer, "")) // | These two lines were commented out
926 strcpy(subSection, buffer); // | Do they serve a purpose? They were there for copy paste when adding a new subsection
929 equal = strstr(buffer, "=");
932 if(!strcmpi(section, "Workspace"))
935 TrimRSpaces(buffer, buffer);
937 TrimLSpaces(equal, equal);
938 if(!strcmpi(buffer, "Active Compiler"))
940 CompilerConfig compiler = ideSettings.GetCompilerConfig(equal);
942 workspace.compiler = defaultCompilerName;
944 workspace.compiler = equal;
948 else if(!strcmpi(section, "Execution Data"))
951 TrimRSpaces(buffer, buffer);
953 TrimLSpaces(equal, equal);
954 if(!strcmpi(buffer, "Command Line Arguments"))
955 workspace.commandLineArgs = equal;
957 if(!strcmpi(buffer, "Environment Variables"))
959 delete workspace.environmentVars;
960 workspace.environmentVars = { };
964 else if(!strcmpi(section, "Debugger Data"))
967 TrimRSpaces(buffer, buffer);
969 TrimLSpaces(equal, equal);
970 if(!strcmpi(buffer, "Debug Working Directory"))
971 workspace.debugDir = equal;
976 TrimRSpaces(buffer, buffer);
978 TrimLSpaces(equal, equal);
979 if(!strcmpi(buffer, "Active Configuration"))
982 if(workspace.projects.last)
984 prj = workspace.projects.lastIterator.data;
985 for(cfg : prj.configurations)
987 if(!strcmp(cfg.name, equal))
995 else if(!strcmpi(buffer, "Modified Compiler Config") || !strcmpi(buffer, "Modified Linker Config"))
998 if(workspace.projects.last)
1000 prj = workspace.projects.lastIterator.data;
1001 for(cfg : prj.configurations)
1003 if(!strcmp(cfg.name, equal))
1005 if(strstr(buffer, "Compiler"))
1006 cfg.compilingModified = true;
1008 cfg.linkingModified = true;
1014 else if(!strcmpi(buffer, "CommandLineArgs"))
1015 workspace.commandLineArgs = equal;
1016 else if(!strcmpi(buffer, "Breakpoint"))
1019 char * lineNum = strstr(equal, ",");
1030 char * absPath = strstr(lineNum, ",");
1037 char * relPath = strstr(absPath, ",");
1044 bp = { type = user, enabled = enabled, level = -1 };
1045 workspace.breakpoints.Add(bp);
1046 bp.line = atoi(lineNum);
1047 bp.relativeFilePath = CopyString(relPath);
1048 bp.absoluteFilePath = workspace.GetAbsolutePathFromRelative(relPath);
1049 if(!bp.absoluteFilePath)
1050 bp.absoluteFilePath = CopyString("");
1058 else if(!strcmpi(buffer, "Watch"))
1061 workspace.watches.Add(wh);
1062 wh.expression = CopyString(equal);
1064 else if(!strcmpi(buffer, "SourceDir"))
1066 workspace.sourceDirs.Add(CopyString(equal));
1068 else if(!strcmpi(buffer, "DebugDir"))
1070 workspace.debugDir = equal;
1082 if(!workspace.projects.first)
1086 project = LoadProject(fromProjectFile /*projectFilePath*/);
1089 char projectFilePath[MAX_LOCATION];
1090 strcpy(projectFilePath, workspace.workspaceFile);
1091 ChangeExtension(projectFilePath, ProjectExtension, projectFilePath);
1092 project = LoadProject(projectFilePath);
1096 workspace.projects.Add(project);
1097 workspace.name = CopyString(project.name);
1101 MessageBox { type = ok, master = ide, contents = "Workspace load file failed", text = "Workspace Load File Error" }.Modal();
1107 if(openedFilesNotFound.first)
1111 String files = new char[MAX_LOCATION * 16];
1113 String msg = new char[MAX_LOCATION * 16 + 2048];
1117 item = openedFilesNotFound.first;
1121 for(item = openedFilesNotFound.first; item; item = item.next)
1126 strcat(files, "\n...");
1129 strcat(files, "\n");
1130 strcat(files, item.name);
1133 sprintf(title, "File%s not found", s);
1134 sprintf(msg, "The following file%s could not be re-opened.%s", s, files);
1136 MessageBox { type = ok, master = ide, contents = msg, text = title }.Modal();
1141 openedFilesNotFound.Free(OldLink::Free);
1144 openedFilesNotFound.Free(OldLink::Free);
1146 else if(fromProjectFile)
1148 //MessageBox { type = Ok, master = ide, contents = "Worspace load file failed", text = "Worspace Load File Error" }.Modal();
1150 char projectFile[MAX_LOCATION];
1153 //strcpy(projectFile, filePath);
1154 //ChangeExtension(projectFile, ProjectExtension, projectFile);
1155 newProject = LoadProject(fromProjectFile /*projectFile*/);
1159 workspace = Workspace { workspaceFile = filePath };
1161 workspace.projects.Add(newProject);
1168 ide.ChangeFileDialogsDirectory(workspace.workspaceDir, false);
1170 if(!workspace.compiler || !workspace.compiler[0])
1171 workspace.compiler = defaultCompilerName;