import "ide"
-/*static void ParseListValue(List<String> list, char * equal)
-{
- char * start, * comma;
- char * string;
- string = CopyString(equal);
- start = string;
- while(start)
- {
- comma = strstr(start, ",");
- if(comma)
- comma[0] = '\0';
- list.Add(CopyString(start));
- if(comma)
- comma++;
- if(comma)
- comma++;
- start = comma;
- }
- delete string;
-}*/
-
enum OpenedFileState { unknown, opened, closed };
enum ValgrindLeakCheck
{
no, summary, yes, full;
- property char *
+ property const char *
{
get { return OnGetString(null, null, null); }
}
- char * OnGetString(char * tempString, void * fieldData, bool * needClass)
+ const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
{
if(this >= no && this <= full)
{
};
static const char * valgrindLeakCheckNames[ValgrindLeakCheck] = { "no", "summary", "yes", "full" };
-class OpenedFileInfo
+class OpenedFileInfo : struct
{
class_no_expansion;
-//public:
+public:
// class_fixed
char * path;
OpenedFileState state;
- int lineNumber, position;
+ int lineNumber;
+ int position;
Point scroll;
+ TimeStamp modified;
+
+private:
bool holdTracking;
property bool trackingAllowed
{
List<OpenedFileInfo> files = ide.workspace.openedFiles;
Iterator<OpenedFileInfo> it { files };
- if(it.Find(this) && it.pointer != files.GetLast())
+ IteratorPointer last;
+ if(it.Find(this) && it.pointer != (last = files.GetLast()))
{
- files.Move(it.pointer, files.GetPrev(files.GetLast()));
+ files.Move(it.pointer, last);
ide.workspace.modified = true;
}
+ modified = GetLocalTimeStamp();
}
}
+
+ void SetCodeEditorState(CodeEditor editor)
+ {
+ int num = Max(lineNumber - 1, 0);
+ Point scrl;
+ holdTracking = true;
+ if(editor.editBox.GoToLineNum(num))
+ {
+ int pos = Max(Min(editor.editBox.line.count, position - 1), 0);
+ editor.editBox.GoToPosition(editor.editBox.line, num, pos);
+ }
+ scrl.x = Max(scroll.x, 0);
+ scrl.y = Max(scroll.y, 0);
+ editor.editBox.scroll = scrl;
+ holdTracking = false;
+ }
+
~OpenedFileInfo()
{
delete path;
}
};
-class Workspace
+class WorkspaceFile : struct
+{
+ class_no_expansion;
+public:
+ property const char * format
+ {
+ set { }
+ get { return "Ecere IDE Workspace File"; }
+ isset { return true; }
+ }
+ property const char * version
+ {
+ set { }
+ get { return "0.1"; }
+ isset { return true; }
+ }
+ Workspace workspace;
+}
+
+class AddedProjectInfo : struct
+{
+ class_no_expansion;
+public:
+ property const char * path
+ {
+ set { delete path; if(value && value[0]) path = CopyString(value); }
+ get { return path && path[0] ? path : null; }
+ isset { return path != null; }
+ }
+ property const char * activeConfig
+ {
+ set { delete activeConfig; if(value && value[0]) activeConfig = CopyString(value); }
+ get
+ {
+ char * config;
+ if(project && project.config)
+ config = project.config.name;
+ else
+ config = activeConfig;
+ return config && config[0] ? config : null;
+ }
+ isset { return property::activeConfig != null; }
+ }
+private:
+ char * path;
+ char * activeConfig;
+ Project project;
+
+ void Free()
+ {
+ delete path;
+ delete activeConfig;
+ }
+
+ void OnFree()
+ {
+ Free();
+ class::OnFree();
+ }
+
+ ~AddedProjectInfo()
+ {
+ Free();
+ }
+}
+
+class Workspace : struct
{
+ class_no_expansion;
public:
+ property const char * name
+ {
+ set { delete name; if(value && value[0]) name = CopyString(value); }
+ get { return name && name[0] ? name : null; }
+ isset { return name != null; }
+ }
+ property const char * activeCompiler
+ {
+ set { delete activeCompiler; if(value && value[0]) activeCompiler = CopyString(value); }
+ get { return activeCompiler && activeCompiler[0] ? activeCompiler : null; }
+ isset { return activeCompiler != null; }
+ }
+ int bitDepth;
+ property const char * commandLineArgs
+ {
+ set { delete commandLineArgs; if(value && value[0]) commandLineArgs = CopyString(value); }
+ get { return commandLineArgs && commandLineArgs[0] ? commandLineArgs : null; }
+ isset { return commandLineArgs != null; }
+ }
+ property const char * debugDir
+ {
+ set { delete debugDir; if(value && value[0]) debugDir = CopyString(value); }
+ get { return debugDir && debugDir[0] ? debugDir : null; }
+ isset { return debugDir != null; }
+ }
+
+ List<AddedProjectInfo> addedProjects;
+ List<String> sourceDirs;
+ Array<NamedString> environmentVars;
+ List<Breakpoint> breakpoints;
+ List<Watch> watches;
+ List<OpenedFileInfo> openedFiles;
+
+ bool useValgrind;
+ ValgrindLeakCheck vgLeakCheck;
+ bool vgTrackOrigins;
+ int vgRedzoneSize;
+
+private:
char * name;
- char * workspaceFile;
- char * workspaceDir;
+ char * activeCompiler;
char * commandLineArgs;
- property char * commandLineArgs { set { delete commandLineArgs; if(value) commandLineArgs = CopyString(value); } }
char * debugDir;
- property char * debugDir { set { delete debugDir; if(value) debugDir = CopyString(value); } }
- int bpCount;
+ char * workspaceFile;
+ char * workspaceDir;
- property char * compiler
- {
- set { delete compiler; if(value && value[0]) compiler = CopyString(value); }
- get { return compiler && compiler[0] ? compiler : null; }
- }
+ int bpCount;
- List<String> sourceDirs { };
- Array<NamedString> environmentVars { };
- List<Breakpoint> breakpoints { };
- List<Watch> watches { };
- List<OpenedFileInfo> openedFiles { };
List<Project> projects { };
-
//Project project;
bool modified;
bool holdTracking;
+ vgRedzoneSize = -1;
+ vgLeakCheck = summary;
+
Timer timer
{
- userData = this, delay = 2.5;
+ userData = this, delay = 1.0;
bool DelayExpired()
{
- if(modified)
+ static bool skip = true;
+ if(skip)
+ skip = false;
+ else if(modified)
Save();
+
+ if(ide.debugStart)
+ {
+ ide.MenuDebugStart(ide.debugStartResumeItem, 0);
+ ide.debugStart = false;
+ }
+ else if(ide.debugHideIDE)
+ {
+ bool visible = ide.debugger.state != running;
+ if(ideMainFrame.visible != visible)
+ {
+ ideMainFrame.visible = visible;
+ if(visible)
+ ideMainFrame.Activate();
+ }
+ }
return true;
}
};
- property char * workspaceFile
+ void AddProject(Project project, AddedProjectInfo addedProject)
+ {
+ if(addedProject)
+ {
+ ProjectConfig activeConfig = project.GetConfig(addedProject.activeConfig);
+ if(activeConfig)
+ project.config = activeConfig;
+ addedProject.project = project;
+ }
+ else
+ {
+ char location[MAX_LOCATION];
+ GetRelativePathForProject(location, project);
+ if(!addedProjects)
+ addedProjects = { };
+ addedProjects.Add(AddedProjectInfo { path = location, project = project });
+ }
+ projects.Add(project);
+ }
+
+ property const char * workspaceFile
{
set
{
get { return workspaceFile; }
}
- property char * projectDir
+ property const char * projectDir
{
get
{
get { return project; }
}*/
-private:
- String compiler;
- int bitDepth;
- // TODO: save these new settings when json format is ready
- bool useValgrind;
- ValgrindLeakCheck vgLeakCheck;
- bool vgTrackOrigins;
- int vgRedzoneSize;
-
- vgRedzoneSize = -1;
- vgLeakCheck = summary;
-
public:
void Save()
{
- bool bkpts = false;
- File file;
-
- file = FileOpen(workspaceFile, write);
- if(file)
+ if(workspaceFile && workspaceFile[0])
{
- /*
- for(bp : breakpoints)
- {
- if(bp.type == user)
- {
- if(bp.enabled)
- file.Printf("Breakpoint=1,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
- else
- file.Printf("Breakpoint=0,%d,%s,%s\n", bp.line, bp.absoluteFilePath, bp.relativeFilePath);
- }
- }
-
- for(wh : watches)
- file.Printf("Watch=%s\n", wh.expression);
-
- for(dir : sourceDirs)
- file.Printf("SourceDir=%s\n", dir);
-
- if(debugDir && debugDir[0])
- file.Printf("DebugDir=%s\n", debugDir);
-
- if(commandLineArgs && commandLineArgs[0])
- file.Printf("CommandLineArgs=%s\n", commandLineArgs);
- */
-
- /*
- char indentation[128*3];
- char path[MAX_LOCATION];
- */
- file.Printf("\nECERE Workspace File\n");
- file.Printf("\nVersion 0.02\n");
- file.Printf("\nWorkspace\n");
- file.Printf("\n Active Compiler = %s\n", compiler ? compiler : defaultCompilerName);
- file.Printf("\n Active Bit Depth = %d\n", bitDepth);
-
- if(projects.first)
- {
- file.Printf("\n Projects\n\n");
- for(prj : projects)
- {
- char location[MAX_LOCATION];
- MakePathRelative(prj.topNode.path, workspaceDir, location);
- MakeSlashPath(location);
- PathCatSlash(location, prj.topNode.name);
- //strcat(location, ".epj");
-
- file.Printf(" %s %s\n", "-", location);
-
- if(prj.config)
- file.Printf(" Active Configuration = %s\n", prj.config.name);
- for(cfg : prj.configurations)
- {
- if(cfg.compilingModified)
- file.Printf(" Modified Compiler Config = %s\n", cfg.name);
- else if(cfg.linkingModified)
- file.Printf(" Modified Linker Config = %s\n", cfg.name);
- }
- }
- }
-
- file.Printf("\n Execution Data\n");
- if(commandLineArgs && commandLineArgs[0])
- {
- file.Printf("\n Command Line Arguments = ");
- file.Puts(commandLineArgs);
- file.Printf("\n");
- }
-
- if(environmentVars.count)
- {
- file.Printf("\n Environment Variables\n\n");
- for(v : environmentVars)
- {
- file.Printf(" ~ ");
- file.Puts(v.name);
- file.Printf(" = ");
- file.Puts(v.string);
- file.Printf("\n");
- }
- }
-
- file.Printf("\n Debugger Data\n");
- // This really belonged in Execution Data...
- if(debugDir && debugDir[0])
- file.Printf("\n Debug Working Directory = %s\n", debugDir);
- if(sourceDirs.count)
- {
- file.Printf("\n Source Directories\n");
- for(dir : sourceDirs)
- file.Printf(" = %s\n", dir);
- }
-
- for(bp : breakpoints)
- {
- if(bp.type == user)
- {
- if(!bkpts)
- {
- bkpts = true;
- file.Printf("\n Breakpoints\n\n");
- }
- bp.Save(file);
- }
- }
-
- if(watches.count)
+ File file = FileOpen(workspaceFile, write);
+ if(file)
{
- file.Printf("\n Watches\n\n");
- for(wh : watches)
- wh.Save(file);
+ WorkspaceFile wf { workspace = this };
+ WriteJSONObject(file, class(WorkspaceFile), wf, 0);
+ delete wf;
+ delete file;
+ modified = false;
}
-
- if(openedFiles.count)
- {
- file.Printf("\n Opened Files\n\n");
- for(ofi : openedFiles)
- {
- char * location;
- char chr[2];
- char relativePath[MAX_LOCATION];
- if(IsPathInsideOf(ofi.path, workspaceDir))
- {
- MakePathRelative(ofi.path, workspaceDir, relativePath);
- MakeSlashPath(relativePath);
- location = relativePath;
- }
- else
- location = ofi.path;
- strcpy(chr, "=");
-
- 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);
- }
- }
-
- modified = false;
- delete file;
}
}
- char * GetAbsolutePathFromRelative(char * relative)
+ char * CopyAbsolutePathFromRelative(const char * relative)
{
char name[MAX_LOCATION];
char absolute[MAX_LOCATION];
GetLastDirectory(relative, name);
for(p : projects)
{
- if(node = p.topNode.Find(name, false))
+ if((node = p.topNode.Find(name, false)))
{
prj = p;
break;
return null;
}
- char * GetPathWorkspaceRelativeOrAbsolute(char * path)
+ char * CopyUnixPathWorkspaceRelativeOrAbsolute(const char * path)
{
if(IsPathInsideOf(path, workspaceDir))
{
return CopyUnixPath(path);
}
- OpenedFileInfo UpdateOpenedFileInfo(char * fileName, OpenedFileState state)
+ char * MakeRelativePath(char * buffer, const char * path)
{
- char filePath[MAX_LOCATION];
- OpenedFileInfo ofi = null;
- GetSlashPathBuffer(filePath, fileName);
- for(item : openedFiles)
+ char * result = null;
+ if(buffer && path)
{
- if(!fstrcmp(item.path, filePath))
+ MakePathRelative(path, workspaceDir, buffer);
+ MakeSlashPath(buffer);
+ result = buffer;
+ }
+ return result;
+ }
+
+ char * GetRelativePathForProject(char * buffer, Project project)
+ {
+ char * result = null;
+ if(buffer && project && project.topNode.path)
+ {
+ MakePathRelative(project.topNode.path, workspaceDir, buffer);
+ MakeSlashPath(buffer);
+ PathCatSlash(buffer, project.topNode.name);
+ result = buffer;
+ }
+ return result;
+ }
+
+ Array<ProjectNode> GetAllProjectNodes(const char *fullPath, bool skipExcluded)
+ {
+ Array<ProjectNode> nodes = null;
+ for(project : projects)
+ {
+ ProjectNode node;
+ if((node = project.topNode.FindByFullPath(fullPath, false)))
{
- ofi = item;
+ if(!skipExcluded || !node.GetIsExcluded(project.config))
+ {
+ if(!nodes) nodes = { };
+ nodes.Add(node);
+ }
+ }
+ }
+ return nodes;
+ }
+
+ Project GetFileOwner(const char * absolutePath, const char * objectFileExt)
+ {
+ Project owner = null;
+ for(prj : projects)
+ {
+ if(prj.topNode.FindByFullPath(absolutePath, false))
+ {
+ owner = prj;
break;
}
}
+ if(!owner)
+ GetObjectFileNode(absolutePath, &owner, null, objectFileExt);
+ return owner;
+ }
+
+ void GetRelativePath(const char * absolutePath, char * relativePath, Project * owner, const char * objectFileExt)
+ {
+ Project prj = GetFileOwner(absolutePath, objectFileExt);
+ if(owner)
+ *owner = prj;
+ if(!prj)
+ prj = projects.firstIterator.data;
+ if(prj)
+ {
+ MakePathRelative(absolutePath, prj.topNode.path, relativePath);
+ MakeSlashPath(relativePath);
+ }
+ else
+ relativePath[0] = '\0';
+ }
+
+ ProjectNode GetObjectFileNode(const char * filePath, Project * project, char * fullPath, const char * objectFileExt)
+ {
+ ProjectNode node = null;
+ char ext[MAX_EXTENSION];
+ GetExtension(filePath, ext);
+ if(ext[0])
+ {
+ IntermediateFileType type = IntermediateFileType::FromExtension(ext);
+ if(type)
+ {
+ char fileName[MAX_FILENAME];
+ GetLastDirectory(filePath, fileName);
+ if(fileName[0])
+ {
+ DotMain dotMain = DotMain::FromFileName(fileName);
+ for(prj : ide.workspace.projects)
+ {
+ if((node = prj.FindNodeByObjectFileName(fileName, type, dotMain, null, objectFileExt)))
+ {
+ if(project)
+ *project = prj;
+ if(fullPath)
+ {
+ const char * cfgName = prj.config ? prj.config.name : "";
+ char name[MAX_FILENAME];
+ CompilerConfig compiler = ideSettings.GetCompilerConfig(prj.lastBuildCompilerName);
+ DirExpression objDir = prj.GetObjDir(compiler, prj.config, bitDepth);
+ strcpy(fullPath, prj.topNode.path);
+ PathCatSlash(fullPath, objDir.dir);
+ node.GetObjectFileName(name, prj.configsNameCollisions[cfgName], type, dotMain, objectFileExt);
+ PathCatSlash(fullPath, name);
+ delete objDir;
+ delete compiler;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ return node;
+ }
+
+ OpenedFileInfo UpdateOpenedFileInfo(const char * fileName, OpenedFileState state)
+ {
+ char absolutePath[MAX_LOCATION];
+ char relativePath[MAX_LOCATION];
+ OpenedFileInfo ofi;
+ GetSlashPathBuffer(absolutePath, fileName);
+ MakeRelativePath(relativePath, fileName);
+ ofi = FindOpenedFileInfo(relativePath, absolutePath);
if(state)
{
if(!ofi)
{
- ofi = OpenedFileInfo { path = CopyString(filePath) };
+ ofi = OpenedFileInfo { path = CopyString(relativePath) };
openedFiles.Add(ofi);
}
ofi.state = state;
+ ofi.modified = GetLocalTimeStamp();
if(!holdTracking)
modified = true;
}
return ofi;
}
- void UpdateSourceDirsArray(Array<String> dirs)
+ void LoadOpenedFileInfo(const char * path, OpenedFileState state, int lineNumber, int position, Point scroll, TimeStamp modified, Array<String> openedFilesNotFound)
+ {
+ char absolutePath[MAX_LOCATION];
+ char relativePath[MAX_LOCATION];
+ TimeStamp stamp = modified;
+ bool exists;
+ strcpy(absolutePath, workspaceDir);
+ PathCatSlash(absolutePath, path);
+ MakeRelativePath(relativePath, absolutePath);
+ if(!(exists = FileExists(absolutePath)))
+ stamp -= 60*60*24*20; // Days { 20 };
+ if(stamp > GetLocalTimeStamp() - 60*60*24*384) // Days { 384 });
+ {
+ if(state == closed || exists)
+ {
+ OpenedFileInfo ofi = FindOpenedFileInfo(relativePath, absolutePath);
+ if(!ofi)
+ openedFiles.Add(OpenedFileInfo { CopyString(relativePath), state, lineNumber, position, scroll, stamp });
+ // else silently drop duplicates if they should ever occur;
+ }
+ else
+ openedFilesNotFound.Add(CopyString(absolutePath));
+ }
+ // else silently discarding old or broken OpenedFileInfo entries;
+ }
+
+ void OpenPreviouslyOpenedFiles(bool noParsing)
{
- byte * tokens[256];
- int c, numTokens;
+ holdTracking = true;
+ for(ofi : openedFiles)
+ {
+ if(ofi.state != closed)
+ {
+ Window file;
+ char absolutePath[MAX_LOCATION];
+ strcpy(absolutePath, workspaceDir);
+ PathCatSlash(absolutePath, ofi.path);
+ file = ide.OpenFile(absolutePath, false, true, null, no, normal, noParsing);
+ if(file)
+ {
+ for(prj : projects)
+ {
+ ProjectNode node = prj.topNode.FindByFullPath(absolutePath, true);
+ if(node)
+ node.EnsureVisible();
+ }
+ }
+ }
+ }
+ holdTracking = false;
+ }
+ OpenedFileInfo FindOpenedFileInfo(const char * relativePath, const char * absolutePath)
+ {
+ OpenedFileInfo result = null;
+ for(e : openedFiles)
+ {
+ bool switchToRelative;
+ if((switchToRelative = !fstrcmp(absolutePath, e.path)) || !fstrcmp(relativePath, e.path))
+ {
+ result = e;
+ if(switchToRelative)
+ {
+ delete result.path;
+ result.path = CopyString(relativePath);
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
+ void RestorePreviouslyOpenedFileState(CodeEditor editor)
+ {
+ if((editor.openedFileInfo = UpdateOpenedFileInfo(editor.fileName, opened)))
+ editor.openedFileInfo.SetCodeEditorState(editor);
+ }
+
+ void UpdateSourceDirsArray(Array<String> dirs)
+ {
sourceDirs.Free();
for(s : dirs)
void RemoveProject(Project project)
{
- Iterator<Project> it { projects };
- if(it.Find(project))
- it.Remove();
+ Iterator<AddedProjectInfo> it { addedProjects };
+ while(it.Next())
+ {
+ if(it.data.project == project)
+ {
+ addedProjects.Remove(it.pointer);
+ break;
+ }
+ }
+ projects.TakeOut(project);
- for(bp : breakpoints)
DropInvalidBreakpoints(project);
modified = true;
ide.findInFilesDialog.RemoveProjectItem(project);
delete project;
}
- void SelectActiveConfig(char * configName)
+ void SelectActiveConfig(const char * configName)
{
bool change = false;
for(prj : ide.workspace.projects)
ide.projectView.Update(null);
Save();
}
+ ide.AdjustDebugMenus();
}
- bool FindPath(ProjectNode node, char * path)
+ bool FindPath(ProjectNode node, const char * path)
{
if(node.type == file)
{
return false;
}
- void ChangeBreakpoint(DataRow row, char * location)
+ void ChangeBreakpoint(DataRow row, const char * location)
{
- Breakpoint bp = (Breakpoint)row.tag;
+ Breakpoint bp = (Breakpoint)(intptr)row.tag;
if(bp)
{
char * currentLoc = bp.CopyUserLocationString();
void ChangeBreakpointIgnore(DataRow row, int ignore)
{
- Breakpoint bp = (Breakpoint)row.tag;
+ Breakpoint bp = (Breakpoint)(intptr)row.tag;
if(bp)
{
bp.ignore = ignore;
void ChangeBreakpointLevel(DataRow row, int level)
{
- Breakpoint bp = (Breakpoint)row.tag;
+ Breakpoint bp = (Breakpoint)(intptr)row.tag;
if(bp)
{
bp.level = level;
}
}
- void ChangeBreakpointCondition(DataRow row, char * condition)
+ void ChangeBreakpointCondition(DataRow row, const char * condition)
{
- Breakpoint bp = (Breakpoint)row.tag;
+ Breakpoint bp = (Breakpoint)(intptr)row.tag;
if(bp && !(!bp.condition && !(condition && condition[0])))
{
if(!bp.condition)
Window document;
for(document = ide.firstChild; document; document = document.next)
{
- char * fileName = document.fileName;
+ const char * fileName = document.fileName;
if(document.isDocument && fileName && document.created)
{
char winFilePath[MAX_LOCATION];
- char * slashPath = GetSlashPathBuffer(winFilePath, fileName);
+ const char * slashPath = GetSlashPathBuffer(winFilePath, fileName);
if(!fstrcmp(slashPath, bp.absoluteFilePath))
{
}
}
- void DropInvalidBreakpoints(Project removedProject)
- {
- Link bpLink, next;
- for(bpLink = breakpoints.first; bpLink; bpLink = next)
+ void DropInvalidBreakpoints(Project removedProject) // think about not dropping BPs that are past end of file but simply disable them
+ { // why? when using a scm/vcs you might be alternating between two version of a file
+ if(breakpoints) // and anoyingly keep loosing breakpoints in the version of the file you are working on
{
- Breakpoint bp = (Breakpoint)bpLink.data;
- next = bpLink.next;
-
- if(bp.type == user)
+ Link bpLink, next;
+ for(bpLink = breakpoints.first; bpLink; bpLink = next)
{
+ Breakpoint bp = (Breakpoint)(intptr)bpLink.data;
+ next = bpLink.next;
if(removedProject)
{
if(bp.project == removedProject)
}
}
}
+ ide.breakpointsView.Update(null);
}
- ide.breakpointsView.Update(null);
+ }
+
+ void Init()
+ {
+ if(!addedProjects) addedProjects = { };
+ if(!sourceDirs) sourceDirs = { };
+ if(!environmentVars) environmentVars = { };
+ if(!breakpoints) breakpoints = { };
+ if(!watches) watches = { };
+ if(!openedFiles) openedFiles = { };
}
void Free()
delete workspaceDir;
delete commandLineArgs;
delete debugDir;
+ delete activeCompiler;
//project = null;
+ if(addedProjects) { addedProjects.Free(); delete addedProjects; }
+ if(sourceDirs) { sourceDirs.Free(); delete sourceDirs; }
+ if(environmentVars) { environmentVars.Free(); delete environmentVars; }
+ if(breakpoints) { breakpoints.Free(); delete breakpoints; }
+ if(watches) { watches.Free(); delete watches; }
+ if(openedFiles) { openedFiles.Free(); delete openedFiles; }
+
projects.Free();
- breakpoints.Free();
- watches.Free();
}
Workspace()
Save();
timer.Stop();
- sourceDirs.Free();
- environmentVars.Free();
SetSourceDirs(null);
Free();
- openedFiles.Free();
- delete compiler;
}
}
-Workspace LoadWorkspace(char * filePath, char * fromProjectFile)
+Workspace LoadWorkspace(const char * filePath, const char * fromProjectFile)
+{
+ File f;
+ Workspace workspace = null;
+
+ f = FileOpen(filePath, read);
+ if(f)
+ {
+ Array<String> openedFilesNotFound { };
+ WorkspaceFile wf = null;
+ JSONParser parser { f = f };
+ /*JSONResult result = */parser.GetObject(class(WorkspaceFile), &wf);
+ if(!wf)
+ workspace = LoadLegacyWorkspace(filePath, openedFilesNotFound);
+ else
+ {
+ workspace = wf.workspace;
+ //incref workspace;
+ workspace.workspaceFile = filePath;
+ {
+ char absolutePath[MAX_LOCATION];
+ bool done = false;
+ bool ahead = false;
+ Iterator<AddedProjectInfo> it { workspace.addedProjects };
+ while(!done && (ahead || !(done = !it.Next())))
+ {
+ // TODO: implement some type of time based pruning of "dea" added projects instead of just dropping them on the spot
+ // TimeStamp modified; modified = GetLocalTimeStamp();
+ // TimeStamp stamp = modified; if(stamp > GetLocalTimeStamp() - 60*60*24*20) // Days { 20 });
+ AddedProjectInfo addedPrj = it.data;
+ strcpy(absolutePath, workspace.workspaceDir);
+ PathCatSlash(absolutePath, addedPrj.path);
+ if(FileExists(absolutePath))
+ {
+ Project loadedProject = LoadProject(absolutePath, null);
+ if(loadedProject)
+ {
+ workspace.AddProject(loadedProject, addedPrj);
+ loadedProject.StartMonitoring();
+ }
+ else if(workspace.projects.count == 0)
+ {
+ delete workspace;
+ break;
+ }
+ else
+ {
+ // TODO: (#524) show message or something when added project fails to load;
+ }
+ ahead = false;
+ }
+ else
+ {
+ IteratorPointer notFound = it.pointer;
+ done = !it.Next();
+ workspace.addedProjects.Delete(notFound);
+ ahead = true;
+ }
+ }
+ if(workspace)
+ {
+ for(bp : workspace.breakpoints)
+ {
+ char * path = workspace.CopyAbsolutePathFromRelative(bp.relativeFilePath);
+ bp.type = user;
+ if(path)
+ {
+ bp.absoluteFilePath = path;
+ delete path;
+ }
+ else
+ bp.absoluteFilePath = "";
+ }
+ if(workspace.openedFiles && workspace.openedFiles.count)
+ {
+ List<OpenedFileInfo> openedFiles = workspace.openedFiles;
+ workspace.openedFiles = { };
+ for(of : openedFiles)
+ {
+ workspace.LoadOpenedFileInfo(of.path, of.state, of.lineNumber, of.position, of.scroll, of.modified, openedFilesNotFound);
+ }
+ openedFiles.Free();
+ delete openedFiles;
+ }
+ }
+ }
+ }
+
+ if(workspace)
+ {
+ workspace.Init();
+ if(!workspace.projects.first)
+ {
+ Project project;
+ if(fromProjectFile)
+ project = LoadProject(fromProjectFile /*projectFilePath*/, null);
+ else
+ {
+ char projectFilePath[MAX_LOCATION];
+ strcpy(projectFilePath, workspace.workspaceFile);
+ ChangeExtension(projectFilePath, ProjectExtension, projectFilePath);
+ project = LoadProject(projectFilePath, null);
+ }
+ if(project)
+ {
+ project.StartMonitoring();
+ workspace.AddProject(project, null);
+ workspace.name = CopyString(project.name);
+ }
+ else
+ {
+ MessageBox { type = ok, master = ide, contents = $"Workspace load file failed", text = $"Workspace Load File Error" }.Modal();
+ delete workspace;
+ return null;
+ }
+ }
+
+ if(openedFilesNotFound.count)
+ {
+ int c = 0;
+ char s[2] = "";
+ String files = new char[MAX_LOCATION * 16];
+ char title[512];
+ String msg = new char[MAX_LOCATION * 16 + 2048];
+ strcpy(files,"\n");
+
+ if(openedFilesNotFound.count > 1)
+ strcpy(s, "s");
+
+ for(item : openedFilesNotFound)
+ {
+ c++;
+ if(c == 16)
+ {
+ strcat(files, "\n...");
+ break;
+ }
+ strcat(files, "\n");
+ strcat(files, item);
+ }
+
+ sprintf(title, $"File%s not found", s);
+ sprintf(msg, $"The following file%s could not be re-opened.%s", s, files);
+
+ MessageBox { type = ok, master = ide, contents = msg, text = title }.Modal();
+
+ delete files;
+ delete msg;
+ }
+ }
+ openedFilesNotFound.Free();
+ delete openedFilesNotFound;
+ delete parser;
+ delete wf;
+ delete f;
+ }
+ else if(fromProjectFile)
+ {
+ //MessageBox { type = Ok, master = ide, contents = "Worspace load file failed", text = "Worspace Load File Error" }.Modal();
+
+ //char projectFile[MAX_LOCATION];
+ Project newProject;
+
+ //strcpy(projectFile, filePath);
+ //ChangeExtension(projectFile, ProjectExtension, projectFile);
+ newProject = LoadProject(fromProjectFile /*projectFile*/, null);
+
+ if(newProject)
+ {
+ newProject.StartMonitoring();
+ workspace = Workspace { property::workspaceFile = filePath };
+
+ workspace.Init();
+ workspace.AddProject(newProject, null);
+ workspace.Save();
+ }
+ }
+
+ if(workspace)
+ {
+ ide.ChangeFileDialogsDirectory(workspace.workspaceDir, false);
+
+ if(!workspace.activeCompiler || !workspace.activeCompiler[0])
+ workspace.activeCompiler = defaultCompilerName;
+ }
+
+ return workspace;
+}
+
+Workspace LoadLegacyWorkspace(const char * filePath, Array<String> openedFilesNotFound)
{
File file;
Workspace workspace = null;
file = FileOpen(filePath, read);
if(file)
{
- OldList openedFilesNotFound { };
double version = 0;
char section[128];
char subSection[128];
- workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = filePath };
+ workspace = Workspace { activeCompiler = ideSettings.defaultCompiler, property::workspaceFile = filePath };
+ workspace.Init();
file.Seek(0, start);
while(!file.Eof())
{
char buffer[65536];
char * equal;
- int len;
Watch wh;
- Breakpoint bp;
+ Breakpoint bp = null;
file.GetLine(buffer, 65536 - 1);
TrimLSpaces(buffer, buffer);
if(!strcmpi(section, "Debugger Data") && !strcmpi(subSection, "Watches"))
{
wh = Watch { };
+ if(!workspace.watches) workspace.watches = { };
workspace.watches.Add(wh);
wh.expression = CopyString(equal);
}
line = atoi(strLine);
bp = { type = user, enabled = enabled, ignore = ignore, level = level, line = line };
+ if(!workspace.breakpoints)
+ workspace.breakpoints = { };
workspace.breakpoints.Add(bp);
bp.location = strFile;
}
int lineNumber = 0;
int position = 0;
Point scroll { };
- char absolutePath[MAX_LOCATION];
- strcpy(absolutePath, workspace.workspaceDir);
if(version == 0.01)
{
char * comma = strchr(equal, ',');
}
}
}
- PathCatSlash(absolutePath, equal);
-
- if(state == closed || FileExists(absolutePath))
- workspace.openedFiles.Add(OpenedFileInfo { path = CopyString(absolutePath), state = state, lineNumber = lineNumber, position = position, scroll = scroll });
- else
- openedFilesNotFound.Add(NamedItem { name = CopyString(equal) });
+ workspace.LoadOpenedFileInfo(equal, state, lineNumber, position, scroll, GetLocalTimeStamp(), openedFilesNotFound);
}
else if(!strcmpi(section, "Projects"))
{
newProject = LoadProject(projectFilePath, null);
if(newProject)
{
- workspace.projects.Add(newProject);
+ workspace.AddProject(newProject, null);
newProject.StartMonitoring();
}
else if(workspace.projects.count == 0)
}
else
{
- // TODO: show message or something when added project fails to load
- // http://ecere.com/mantis/view.php?id=524
+ // TODO: (#524) show message or something when added project fails to load;
}
}
}
else if(!strcmpi(buffer, "Environment Variables"))
strcpy(subSection, buffer);
else if(!strcmpi(buffer, "Opened Files"))
+ {
strcpy(section, buffer);
+ if(!workspace.openedFiles) workspace.openedFiles = { };
+ }
else if(!strcmpi(buffer, "")) // | These two lines were commented out
strcpy(subSection, buffer); // | Do they serve a purpose? They were there for copy paste when adding a new subsection
else
{
CompilerConfig compiler = ideSettings.GetCompilerConfig(equal);
if(!compiler)
- workspace.compiler = defaultCompilerName;
+ workspace.activeCompiler = defaultCompilerName;
else
- workspace.compiler = equal;
+ workspace.activeCompiler = equal;
delete compiler;
}
if(!strcmpi(buffer, "Active Bit Depth"))
}
}
}
-
delete file;
-
- if(workspace)
- {
- if(!workspace.projects.first)
- {
- Project project;
- if(fromProjectFile)
- project = LoadProject(fromProjectFile /*projectFilePath*/, null);
- else
- {
- char projectFilePath[MAX_LOCATION];
- strcpy(projectFilePath, workspace.workspaceFile);
- ChangeExtension(projectFilePath, ProjectExtension, projectFilePath);
- project = LoadProject(projectFilePath, null);
- }
- if(project)
- {
- project.StartMonitoring();
- workspace.projects.Add(project);
- workspace.name = CopyString(project.name);
- }
- else
- {
- MessageBox { type = ok, master = ide, contents = $"Workspace load file failed", text = $"Workspace Load File Error" }.Modal();
- delete workspace;
- return null;
- }
- }
-
- if(openedFilesNotFound.first)
- {
- int c = 0;
- char s[2] = "";
- String files = new char[MAX_LOCATION * 16];
- char title[512];
- String msg = new char[MAX_LOCATION * 16 + 2048];
- NamedItem item;
- strcpy(files,"\n");
-
- item = openedFilesNotFound.first;
- if(item.next)
- strcpy(s, "s");
-
- for(item = openedFilesNotFound.first; item; item = item.next)
- {
- c++;
- if(c == 16)
- {
- strcat(files, "\n...");
- break;
- }
- strcat(files, "\n");
- strcat(files, item.name);
- }
-
- sprintf(title, $"File%s not found", s);
- sprintf(msg, $"The following file%s could not be re-opened.%s", s, files);
-
- MessageBox { type = ok, master = ide, contents = msg, text = title }.Modal();
-
- delete files;
- delete msg;
- }
- openedFilesNotFound.Free(OldLink::Free);
- }
- else
- openedFilesNotFound.Free(OldLink::Free);
- }
- else if(fromProjectFile)
- {
- //MessageBox { type = Ok, master = ide, contents = "Worspace load file failed", text = "Worspace Load File Error" }.Modal();
-
- char projectFile[MAX_LOCATION];
- Project newProject;
-
- //strcpy(projectFile, filePath);
- //ChangeExtension(projectFile, ProjectExtension, projectFile);
- newProject = LoadProject(fromProjectFile /*projectFile*/, null);
-
- if(newProject)
- {
- newProject.StartMonitoring();
- workspace = Workspace { workspaceFile = filePath };
-
- workspace.projects.Add(newProject);
- workspace.Save();
- }
- }
-
- if(workspace)
- {
- ide.ChangeFileDialogsDirectory(workspace.workspaceDir, false);
-
- if(!workspace.compiler || !workspace.compiler[0])
- workspace.compiler = defaultCompilerName;
}
return workspace;
}
+
+TimeStamp GetLocalTimeStamp()
+{
+ TimeStamp now;
+ DateTime time { };
+ time.GetLocalTime();
+ now = time;
+ return now;
+}