#include "ide.h" const char tempaux[] = ""; const char prjaux[] = ""; const char ideaux[] = ""; Image OverLtRed(const Image& m) { Image red = CreateImage(m.GetSize(), Blend(LtRed, SColorPaper)); Over(red, Point(0, 0), m, m.GetSize()); return red; } Image ImageOverRed(const Image& m) { return MakeImage(m, OverLtRed); } Font WorkspaceWork::ListFont() { return StdFont(); }; void WorkspaceWork::SetErrorFiles(const Vector& files) { errorfiles = clone(files); int i = filelist.GetCursor(); int s = filelist.GetSbPos(); SaveLoadPackage(false); filelist.SetSbPos(s); filelist.SetCursor(i); SyncErrorPackages(); } String WorkspaceWork::PackagePathA(const String& pn) { if(pn == prjaux) { String nm; String cfg = ConfigFile("cfg"); for(const char *s = main; *s; s++) nm.Cat(*s == '\\' || *s == '/' ? '$' : *s); RealizeDirectory(cfg); return AppendFileName(cfg, ForceExt(nm + '@' + GetVarsName(), ".aux")); } if(pn == ideaux) return ConfigFile("ide.aux"); if(pn == tempaux) return ConfigFile(Sprintf("aux%x.tmp", #ifdef PLATFORM_WIN32 GetCurrentProcessId() #endif #ifdef PLATFORM_POSIX getpid() #endif )); if(pn == METAPACKAGE) return Null; return PackagePath(pn); } void WorkspaceWork::SyncErrorPackages() { for(int i = 0; i < package.GetCount(); i++) { FileList::File f = package.Get(i); if(!IsAux(f.name)) { FileList::File ff = f; String path = GetFileFolder(PackagePath(f.name)); #ifdef PLATFORM_WIN32 path = ToLower(path); #endif ff.icon = i ? IdeImg::Package() : IdeImg::MainPackage(); ff.underline = Null; for(int q = 0; q < errorfiles.GetCount(); q++) { if(errorfiles[q].StartsWith(path)) { ff.icon = ImageOverRed(ff.icon); ff.underline = LtRed; break; } } package.Set(i, ff); } } } struct PackageOrder { String mainpath; int GetMatchLen(const String& x) const { if(*x == '<') return 0; String h = PackagePath(x); for(int i = 0; i < mainpath.GetCount(); i++) if(mainpath[i] != h[i]) return i; return mainpath.GetCount(); } bool operator()(const String& p1, const String& p2) const { int l1 = GetMatchLen(p1); int l2 = GetMatchLen(p2); return l1 != l2 ? l1 > l2 : p1 < p2; } }; void WorkspaceWork::ScanWorkspace() { Workspace wspc; if(main.GetCount()) wspc.Scan(main); actualpackage.Clear(); actualfileindex = -1; filelist.Clear(); package.Clear(); Vector pks; for(int i = 0; i < wspc.package.GetCount(); i++) pks.Add(wspc.package.GetKey(i)); if(sort && wspc.GetCount()) { PackageOrder po; po.mainpath = PackagePath(pks[0]); Sort(SubRange(pks, 1, pks.GetCount() - 1), po); } for(int i = 0; i < wspc.package.GetCount(); i++) { String pk = pks[i]; Font fnt = ListFont(); if(i == 0) fnt.Bold(); PackageInfo pi = GetPackageInfo(pk); if(pi.bold) fnt.Bold(); if(pi.italic) fnt.Italic(); package.Add(pk, Null, fnt, Nvl(AColor(pi.ink), SColorText()), false, 0, Null, SColorMark); } if(!organizer) { if(main.GetCount()) package.Add(prjaux, IdeImg::PrjAux(), ListFont(), AColor(Magenta())); package.Add(ideaux, IdeImg::IdeAux(), ListFont(), AColor(Magenta())); package.Add(tempaux, IdeImg::TempAux(), ListFont(), AColor(Magenta())); if(main.GetCount()) package.Add(METAPACKAGE, IdeImg::Meta(), ListFont(), AColor(Red())); } package.SetCursor(0); SyncErrorPackages(); } void WorkspaceWork::SavePackage() { if(IsNull(actualpackage) || actualpackage == METAPACKAGE) return; InvalidatePackageInfo(actualpackage); String pp = PackagePathA(actualpackage); if(organizer && backup.Find(pp) < 0) { Backup& b = backup.Add(pp); FindFile ff(pp); if(ff) { b.time = ff.GetLastWriteTime(); b.data = LoadFile(pp); } else b.data = String::GetVoid(); } if(FileExists(pp) || actual.GetCount()) actual.Save(pp); } void WorkspaceWork::RestoreBackup() { for(int i = 0; i < backup.GetCount(); i++) { Backup& b = backup[i]; String fn = backup.GetKey(i); if(b.data.IsVoid()) DeleteFile(fn); else { SaveFile(fn, b.data); SetFileTime(fn, b.time); } } } void WorkspaceWork::SaveLoadPackageNS(bool sel) { SavePackage(); String p = actualpackage; String f; if(IsActiveFile()) f = ActiveFile(); int psc = package.GetSbPos(); int fsc = filelist.GetSbPos(); ScanWorkspace(); package.SetSbPos(psc); package.FindSetCursor(p); if (sel) { filelist.SetSbPos(fsc); filelist.FindSetCursor(f); } } void WorkspaceWork::SaveLoadPackage(bool sel) { SaveLoadPackageNS(sel); SyncWorkspace(); } bool PathIsLocal(const String& path) { #ifdef PLATFORM_WIN32 char drive[4] = "?:\\"; *drive = *path; return GetDriveType(drive) == DRIVE_FIXED; #else return false; #endif } void WorkspaceWork::LoadActualPackage() { #ifdef PLATFORM_WIN32 static BOOL (WINAPI *PathIsNetworkPathA)(LPCSTR pszPath); ONCELOCK { DllFn(PathIsNetworkPathA, "Shlwapi.dll", "PathIsNetworkPathA"); } #endif Time utime = FileGetTime(ConfigFile("version")); filelist.Clear(); fileindex.Clear(); bool open = true; Time tm = GetSysTime(); for(int i = 0; i < actual.file.GetCount(); i++) { Package::File& f = actual.file[i]; if(f.separator) { open = closed.Find(Sepfo(actualpackage, f)) < 0; filelist.Add(f, open ? IdeImg::SeparatorClose() : IdeImg::SeparatorOpen(), ListFont().Bold(), open ? SColorMark : SColorText, true, 0, Null); fileindex.Add(i); } else if(open) { Color uln = Null; String p = SourcePath(GetActivePackage(), f); if(showtime && (findarg(actualpackage, "", "", "") < 0 || PathIsLocal(p)) #ifdef PLATFORM_WIN32 && !(PathIsNetworkPathA && PathIsNetworkPathA(p)) #endif ) { FindFile ff(p); if(ff) { Time ftm = Time(ff.GetLastWriteTime()); if(ftm > utime) { int64 t = tm - ftm; if(t < 24 * 3600) uln = SColorMark; else if(t < 32 * 24 * 3600) uln = SColorDisabled; } } } Image m = IdeFileImage(f, false, f.pch); if(GetFileExt(p) == ".tpp" && IsFolder(p)) { if(FileExists(AppendFileName(p, "all.i"))) m = TopicImg::IGroup(); else m = TopicImg::Group(); } #ifdef PLATFORM_WIN32 p = ToLower(p); #endif if(errorfiles.Find(p) >= 0) { m = ImageOverRed(m); uln = LtRed; } filelist.Add(f, m, ListFont(), SColorText, false, 0, Null, SColorMark, Null, Null, Null, uln); fileindex.Add(i); } } } void WorkspaceWork::TouchFile(const String& path) { if(!showtime) return; String n = GetFileName(path); for(int i = 0; i < filelist.GetCount(); i++) { FileList::File f = filelist[i]; if(f.name == n && path == SourcePath(GetActivePackage(), f.name)) filelist.Set(i, f.name, f.icon, f.font, f.ink, false, 0, Null, SColorMark, Null, Null, Null, SColorMark); } } void WorkspaceWork::Fetch(Package& p, const String& pkg) { if(pkg.IsEmpty()) return; if(pkg == METAPACKAGE) { p.file.Clear(); p.file.AddPick(Package::File(String(HELPNAME))); p.file.AddPick(Package::File(ConfigFile("global.defs"))); for(String d : GetUppDirs()) { Package::File sep(GetFileName(d)); sep.separator = true; p.file.AddPick(pick(sep)); p.file.AddPick(Package::File(AppendFileName(d, "_.tpp"))); for(String f : { "readme", "license", "copying" }) { for(int u = 0; u < 4; u++) { FindFile ff(AppendFileName(d, (u & 1 ? ToUpper(f) : f) + (u & 2 ? ".md" : ""))); if(ff) { p.file.AddPick(Package::File(ff.GetPath())); break; } } } } } else { String pp = PackagePathA(pkg); p.Load(pp); } } void WorkspaceWork::PackageCursor() { InvalidatePackageCache(); filelist.WhenBar.Clear(); actualpackage = GetActivePackage(); repo_dirs = false; Fetch(actual, actualpackage); LoadActualPackage(); filelist.Enable(); if(actualpackage != METAPACKAGE) filelist.WhenBar = THISBACK(FileMenu); repo_dirs = RepoDirs(true).GetCount(); } Vector WorkspaceWork::RepoDirs(bool actual) { Vector u = GetUppDirs(); for(String& s : u) s = NormalizePath(s); Index id; const Workspace& w = GetIdeWorkspace(); for(int i = 0; i < w.GetCount(); i++) { String pp = PackagePath(w[i]); for(String s : u) if(pp.StartsWith(s)) id.FindAdd(s); } Vector d = id.PickKeys(); if (actual && !IsAux()) d.Insert(0, GetFileFolder(PackagePath(actualpackage))); Vector r; for(int i = 0; i < d.GetCount(); i++) if(GetRepoKind(d[i])) r.Add(d[i]); return r; } void WorkspaceWork::FileCursor() { int i = filelist.GetCursor(); actualfileindex = -1; if(i >= 0 && i < fileindex.GetCount()) actualfileindex = fileindex[i]; } String WorkspaceWork::FileName(int i) const { return i >= 0 && i < fileindex.GetCount() ? (String)actual.file[fileindex[i]] : Null; } bool WorkspaceWork::IsSeparator(int i) const { return i >= 0 && i < fileindex.GetCount() ? actual.file[fileindex[i]].separator : true; } String WorkspaceWork::GetActiveFileName() const { return FileName(filelist.GetCursor()); } String WorkspaceWork::GetActiveFilePath() const { return SourcePath(GetActivePackage(), GetActiveFileName()); } bool WorkspaceWork::IsActiveFile() const { int i = filelist.GetCursor(); return i >= 0 && i < fileindex.GetCount() && fileindex[i] < actual.file.GetCount(); } bool WorkspaceWork::IsActiveSeparator() const { return IsSeparator(filelist.GetCursor()); } Package::File& WorkspaceWork::ActiveFile() { return actual.file[fileindex[filelist.GetCursor()]]; } void WorkspaceWork::AddFile(ADDFILE af) { String active = GetActivePackage(); if(active.IsEmpty()) return; FileSel *fs = &OutputFs(); RealizeDirectory(GetLocalDir()); switch(af) { case PACKAGE_FILE: fs = &BasedSourceFs(); fs->BaseDir(GetFileFolder(PackagePathA(active))); break; case ANY_FILE: fs = &AnySourceFs(); break; case OUTPUT_FILE: fs->ActiveDir(GetOutputDir()); break; case CONFIG_FILE: fs->ActiveDir(GetConfigDir()); break; case HOME_FILE: fs->ActiveDir(GetHomeDirectory()); break; case LOCAL_FILE: fs->ActiveDir(GetLocalDir()); break; default: ; // GCC warns otherwise } if(!fs->ExecuteOpen("Add files to package..")) return; int fci = filelist.GetCursor(); int cs = filelist.GetSbPos(); int ci = fci >= 0 && fci < fileindex.GetCount() ? fileindex[fci] : -1; for(int i = 0; i < fs->GetCount(); i++) { Package::File& f = ci >= 0 ? actual.file.Insert(ci++) : actual.file.Add(); f = (*fs)[i]; f.readonly = fs->GetReadOnly(); } SaveLoadPackage(false); filelist.SetSbPos(cs); filelist.SetCursor(fci >= 0 ? fci : filelist.GetCount() - 1); FileSelected(); } void WorkspaceWork::AddItem(const String& name, bool separator, bool readonly) { int fci = filelist.GetCursor(); int cs = filelist.GetSbPos(); int ci = fci >= 0 && fci < fileindex.GetCount() ? fileindex[fci] : -1; Package::File& f = ci >= 0 ? actual.file.Insert(ci) : actual.file.Add(); f = name; f.separator = separator; f.readonly = readonly; if(separator) SaveLoadPackageNS(false); else SaveLoadPackage(false); filelist.SetSbPos(cs); filelist.SetCursor(fci >= 0 ? fci : filelist.GetCount() - 1); FileSelected(); } void WorkspaceWork::AddSeparator() { String active = GetActivePackage(); if(active.IsEmpty()) return; String name; if(!EditText(name, "Add separator", "Name")) return; AddItem(~name, true, true); } class ImportDlg : public WithImportLayout { typedef ImportDlg CLASSNAME; FrameRight