9 import "OldIDESettings"
13 enum DirTypes { includes, libraries, executables };
15 define defaultCompilerName = "Default";
17 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
19 char * settingsDirectoryNames[DirTypes] =
26 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
28 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
29 PathRelationship eString_PathRelated(char * path, char * to, char * pathDiff)
31 PathRelationship result;
32 if(pathDiff) *pathDiff = '\0';
33 if(path && *path && to && *to)
35 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
36 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
38 strcpy(pathRest, path);
39 for(; toRest[0] && pathRest[0];)
41 SplitDirectory(toRest, toPart, toRest);
42 SplitDirectory(pathRest, pathPart, pathRest);
43 if(!fstrcmp(pathPart, toPart)) result = siblings;
46 if(result == siblings)
48 if(!*toRest && !*pathRest) result = identical;
49 else if(!*pathRest) result = parentPath;
50 else result = subPath;
51 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
53 else result = unrelated;
59 if(!*path && !*to) result = bothEmpty;
60 else if(!*path) result = pathEmpty;
61 else result = toEmpty;
63 else if(!path && !to) result = bothNull;
64 else if(!path) result = pathNull;
70 char * CopyValidateMakefilePath(char * path)
72 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 7 };
73 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)",(char *)0 };
80 copy = CopyString(path);
86 Array<char *> parts { };
93 for(v=0; vars[v]; v++)
95 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
99 parts.Add(vars[map[v]]);
100 c += strlen(vars[v]);
114 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
115 copy = new char[++len];
117 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
128 CompilerConfig MakeDefaultCompiler(char * name, bool readOnly)
130 CompilerConfig defaultCompiler
135 GetRuntimePlatform(),
146 incref defaultCompiler;
147 return defaultCompiler;
150 class IDESettingsContainer : GlobalSettings
153 settingsName = "ecereIDESettingsTest";
155 settingsName = "ecereIDE";
158 virtual void OnLoad(GlobalSettingsData data);
160 char moduleLocation[MAX_LOCATION];
163 IDESettingsContainer()
165 char path[MAX_LOCATION];
167 LocateModule(null, moduleLocation);
168 strcpy(path, moduleLocation);
169 StripLastDirectory(moduleLocation, moduleLocation);
170 ChangeCh(moduleLocation, '\\', '/');
171 // PortableApps.com directory structure
172 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
174 char configFilePath[MAX_LOCATION];
175 char defaultConfigFilePath[MAX_LOCATION];
179 strcpy(configFilePath, path);
180 PathCat(configFilePath, "Data");
181 PathCat(configFilePath, "ecereIDE.ini");
183 strcpy(defaultConfigFilePath, path);
184 PathCat(defaultConfigFilePath, "App");
185 PathCat(defaultConfigFilePath, "DefaultData");
186 PathCat(defaultConfigFilePath, "ecereIDE.ini");
188 if(FileExists(defaultConfigFilePath))
190 if(!FileExists(configFilePath))
192 File f = FileOpen(defaultConfigFilePath, read);
193 f.CopyTo(configFilePath);
197 PathCat(path, "Data");
198 // the forced settings location will only be
199 // used if the running ide's path matches
200 // the PortableApps.com directory structure
201 // and the default ini file is found in
202 // the DefaultData directory
203 settingsLocation = path;
209 void OnAskReloadSettings()
211 /*if(MessageBox { type = YesNo, master = this,
212 text = "Global Settings Modified Externally",
213 contents = "The global settings were modified by another instance.\n"
214 "Would you like to reload them?" }.Modal() == Yes)*/
222 SettingsIOResult result = GlobalSettings::Load();
223 IDESettings data = (IDESettings)this.data;
224 CompilerConfig defaultCompiler = null;
227 this.data = IDESettings { };
229 *dataOwner = this.data;
231 if(result == fileNotCompatibleWithDriver)
234 OldIDESettings oldSettings { };
236 loaded = oldSettings.Load();
240 data = (IDESettings)this.data;
242 for(c : oldSettings.compilerConfigs)
243 data.compilerConfigs.Add(c.Copy());
245 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
246 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
248 data.docDir = oldSettings.docDir;
249 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
250 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
251 data.useFreeCaret = oldSettings.useFreeCaret;
252 data.showLineNumbers = oldSettings.showLineNumbers;
253 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
254 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
255 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
256 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
263 if(result == fileNotFound || !data)
265 data = (IDESettings)this.data;
266 data.useFreeCaret = true;
267 data.showLineNumbers = true;
268 data.caretFollowsScrolling = true;
271 // Ensure we have a default compiler
272 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
275 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
276 data.compilerConfigs.Add(defaultCompiler);
279 // We incref the compilers below, so reset refCount to 0
280 defaultCompiler._refCount = 0;
283 if(data.compilerConfigs)
285 for(c : data.compilerConfigs)
287 CompilerConfig compiler = c;
291 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
292 data.ManagePortablePaths(moduleLocation, true);
293 data.ForcePathSeparatorStyle(true);
299 IDESettings data = (IDESettings)this.data;
300 Platform runtimePlatform = GetRuntimePlatform();
301 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
302 data.ManagePortablePaths(moduleLocation, false);
303 data.ForcePathSeparatorStyle(true);
304 if(!GlobalSettings::Save())
305 PrintLn("Error saving IDE settings");
306 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
307 data.ManagePortablePaths(moduleLocation, true);
312 class IDESettings : GlobalSettingsData
315 List<CompilerConfig> compilerConfigs { };
316 Array<String> recentFiles { };
317 Array<String> recentProjects { };
318 property char * docDir
320 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
321 get { return docDir ? docDir : ""; }
322 isset { return docDir && docDir[0]; }
324 property char * ideFileDialogLocation
326 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
327 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
328 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
330 property char * ideProjectFileDialogLocation
332 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
333 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
334 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
337 bool showLineNumbers;
338 bool caretFollowsScrolling;
339 char * displayDriver;
341 // TODO: Classify settings
342 //EditorSettings editor { };
344 property char * projectDefaultTargetDir
346 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
347 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
348 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
350 property char * projectDefaultIntermediateObjDir
352 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
353 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
354 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
357 property char * compilerConfigsDir
359 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
360 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
361 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
364 property char * defaultCompiler
366 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
367 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
368 isset { return defaultCompiler && defaultCompiler[0]; }
373 char * ideFileDialogLocation;
374 char * ideProjectFileDialogLocation;
375 char * projectDefaultTargetDir;
376 char * projectDefaultIntermediateObjDir;
377 char * compilerConfigsDir;
378 char * defaultCompiler;
380 CompilerConfig GetCompilerConfig(String compilerName)
382 char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
383 CompilerConfig compilerConfig = null;
384 for(compiler : compilerConfigs)
386 if(!strcmp(compiler.name, name))
388 compilerConfig = compiler;
392 if(!compilerConfig && compilerConfigs.count)
393 compilerConfig = compilerConfigs.firstIterator.data;
395 incref compilerConfig;
396 return compilerConfig;
401 compilerConfigs.Free();
402 delete compilerConfigs;
405 recentProjects.Free();
406 delete recentProjects;
409 delete projectDefaultTargetDir;
410 delete projectDefaultIntermediateObjDir;
411 delete compilerConfigsDir;
412 delete defaultCompiler;
414 delete ideFileDialogLocation;
415 delete ideProjectFileDialogLocation;
416 delete displayDriver;
419 void ForcePathSeparatorStyle(bool unixStyle)
423 from = '\\', to = '/';
425 from = '/', to = '\\';
426 if(compilerConfigs && compilerConfigs.count)
429 for(config : compilerConfigs)
431 if(config.includeDirs && config.includeDirs.count)
433 for(i = 0; i < config.includeDirs.count; i++)
435 if(config.includeDirs[i] && config.includeDirs[i][0])
436 ChangeCh(config.includeDirs[i], from, to);
439 if(config.libraryDirs && config.libraryDirs.count)
441 for(i = 0; i < config.libraryDirs.count; i++)
443 if(config.libraryDirs[i] && config.libraryDirs[i][0])
444 ChangeCh(config.libraryDirs[i], from, to);
447 if(config.executableDirs && config.executableDirs.count)
449 for(i = 0; i < config.executableDirs.count; i++)
451 if(config.executableDirs[i] && config.executableDirs[i][0])
452 ChangeCh(config.executableDirs[i], from, to);
457 if(recentFiles && recentFiles.count)
460 for(c = 0; c < recentFiles.count; c++)
462 if(recentFiles[c] && recentFiles[c][0])
463 ChangeCh(recentFiles[c], from, to);
466 if(recentProjects && recentProjects.count)
469 for(c = 0; c < recentProjects.count; c++)
471 if(recentProjects[c] && recentProjects[c][0])
472 ChangeCh(recentProjects[c], from, to);
475 if(docDir && docDir[0])
476 ChangeCh(docDir, from, to);
477 if(ideFileDialogLocation && ideFileDialogLocation[0])
478 ChangeCh(ideFileDialogLocation, from, to);
479 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
480 ChangeCh(ideProjectFileDialogLocation, from, to);
482 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
483 ChangeCh(projectDefaultTargetDir, from, to);
484 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
485 ChangeCh(projectDefaultIntermediateObjDir, from, to);
487 if(compilerConfigsDir && compilerConfigsDir[0])
488 ChangeCh(compilerConfigsDir, from, to);
491 void ManagePortablePaths(char * location, bool makeAbsolute)
494 if(compilerConfigs && compilerConfigs.count)
496 for(config : compilerConfigs)
499 for(t = 0; t < DirTypes::enumSize; t++)
501 Array<String> dirs = null;
502 if(t == executables) dirs = config.executableDirs;
503 else if(t == includes) dirs = config.includeDirs;
504 else if(t == libraries) dirs = config.libraryDirs;
505 if(dirs && dirs.count)
507 for(c = 0; c < dirs.count; c++)
509 if(dirs[c] && dirs[c][0])
510 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
516 if(recentFiles && recentFiles.count)
518 for(c = 0; c < recentFiles.count; c++)
520 if(recentFiles[c] && recentFiles[c][0])
521 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
524 if(recentProjects && recentProjects.count)
526 for(c = 0; c < recentProjects.count; c++)
528 if(recentProjects[c] && recentProjects[c][0])
529 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
532 if(docDir && docDir[0])
533 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
534 if(ideFileDialogLocation && ideFileDialogLocation[0])
535 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
536 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
537 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
539 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
540 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
541 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
542 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
544 if(compilerConfigsDir && compilerConfigsDir[0])
545 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
548 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
553 char p[MAX_LOCATION];
555 PathCatSlash(p, path);
557 output = CopyString(p);
561 PathRelationship rel = eString_PathRelated(path, location, null);
562 if(rel == subPath || rel == identical)
564 char p[MAX_LOCATION];
565 MakePathRelative(path, location, p);
566 if(!*p) strcpy(p, "./");
567 else ChangeCh(p, '\\', '/');
569 output = CopyString(p);
577 void AddRecentFile(char * fileName)
580 char * filePath = CopyString(fileName);
581 ChangeCh(filePath, '\\', '/');
582 for(c = 0; c<recentFiles.count; c++)
584 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
586 recentFiles.Delete((void *)&recentFiles[c]);
590 while(recentFiles.count >= MaxRecent)
591 recentFiles.Delete(recentFiles.GetLast());
592 recentFiles.Insert(null, filePath);
593 //UpdateRecentMenus(owner);
596 void AddRecentProject(char * projectName)
599 char * filePath = CopyString(projectName);
600 ChangeCh(filePath, '\\', '/');
601 for(c = 0; c<recentProjects.count; c++)
603 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
605 recentProjects.Delete((void *)&recentProjects[c]);
609 while(recentProjects.count >= MaxRecent)
610 recentProjects.Delete(recentProjects.GetLast());
611 recentProjects.Insert(null, filePath);
612 //UpdateRecentMenus(owner);
616 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
617 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
618 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
619 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
620 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
621 // TODO: i18n with Array
622 static Array<String> compilerTypeLongNames
624 $"GNU Compiler Collection (GCC) / GNU Make",
625 $"Tiny C Compiler / GNU Make",
626 $"Portable C Compiler / GNU Make",
627 $"Microsoft Visual Studio 2005 (8.0) Compiler",
628 $"Microsoft Visual Studio 2008 (9.0) Compiler",
629 $"Microsoft Visual Studio 2010 (10.0) Compiler"
631 const CompilerType firstCompilerType = gcc;
632 const CompilerType lastCompilerType = vs10;
633 public enum CompilerType
635 gcc, tcc, pcc, vs8, vs9, vs10;
639 get { return this == vs8 || this == vs9 || this == vs10; }
644 get { return OnGetString(null, null, null); }
650 for(c = firstCompilerType; c <= lastCompilerType; c++)
651 if(!strcmpi(value, compilerTypeNames[c]))
658 property char * longName { get { return OnGetString(null, (void*)1, null); } };
659 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
660 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
661 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
662 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
664 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
666 if(this >= firstCompilerType && this <= lastCompilerType)
669 strcpy(tempString, compilerTypeNames[this]);
670 if(fieldData == null)
671 return compilerTypeNames[this];
672 else if(fieldData == (void*)1)
673 return compilerTypeLongNames[this];
674 else if(fieldData == (void*)2)
675 return compilerTypeVersionString[this];
676 else if(fieldData == (void*)3)
677 return compilerTypeYearString[this];
678 else if(fieldData == (void*)4)
679 return compilerTypeProjectFileExtension[this];
680 else if(fieldData == (void*)5)
681 return compilerTypeSolutionFileVersionString[this];
699 name = CopyString(value);
705 Platform targetPlatform;
707 property char * makeCommand
709 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
710 get { return makeCommand; }
711 isset { return makeCommand && makeCommand[0]; }
713 property char * ecpCommand
715 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
716 get { return ecpCommand; }
717 isset { return ecpCommand && ecpCommand[0]; }
719 property char * eccCommand
721 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
722 get { return eccCommand; }
723 isset { return eccCommand && eccCommand[0]; }
725 property char * ecsCommand
727 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
728 get { return ecsCommand; }
729 isset { return ecsCommand && ecsCommand[0]; }
731 property char * earCommand
733 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
734 get { return earCommand; }
735 isset { return earCommand && earCommand[0]; }
737 property char * cppCommand
739 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
740 get { return cppCommand; }
741 isset { return cppCommand && cppCommand[0]; }
743 property char * ccCommand
745 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
746 get { return ccCommand; }
747 isset { return ccCommand && ccCommand[0]; }
749 property char * cxxCommand
751 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
752 get { return cxxCommand; }
753 isset { return cxxCommand && cxxCommand[0]; }
755 property char * execPrefixCommand
757 set { delete execPrefixCommand; if(value && value[0]) execPrefixCommand = CopyString(value); }
758 get { return execPrefixCommand; }
759 isset { return execPrefixCommand && execPrefixCommand[0]; }
763 property char * distccHosts
765 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
766 get { return distccHosts; }
767 isset { return distccHosts && distccHosts[0]; }
769 property Array<String> includeDirs
780 get { return includeDirs; }
781 isset { return includeDirs.count != 0; }
783 property Array<String> libraryDirs
794 get { return libraryDirs; }
795 isset { return libraryDirs.count != 0; }
797 property Array<String> executableDirs
801 executableDirs.Free();
804 delete executableDirs;
805 executableDirs = value;
808 get { return executableDirs; }
809 isset { return executableDirs.count != 0; }
811 property Array<NamedString> environmentVars
815 environmentVars.Free();
818 delete environmentVars;
819 environmentVars = value;
822 get { return environmentVars; }
823 isset { return environmentVars.count != 0; }
825 property Array<String> prepDirectives
829 prepDirectives.Free();
832 delete prepDirectives;
833 prepDirectives = value;
836 get { return prepDirectives; }
837 isset { return prepDirectives.count != 0; }
839 property Array<String> excludeLibs
850 get { return excludeLibs; }
851 isset { return excludeLibs.count != 0; }
854 Array<String> includeDirs { };
855 Array<String> libraryDirs { };
856 Array<String> executableDirs { };
857 // TODO: Can JSON parse and serialize maps?
858 //EnvironmentVariables { };
859 Array<NamedString> environmentVars { };
860 Array<String> prepDirectives { };
861 Array<String> excludeLibs { };
871 char * execPrefixCommand;
875 struct { Array<String> includes, libraries, executables; };
876 Array<String> dirs[DirTypes];
890 delete execPrefixCommand;
892 if(environmentVars) environmentVars.Free();
893 if(includeDirs) { includeDirs.Free(); }
894 if(libraryDirs) { libraryDirs.Free(); }
895 if(executableDirs) { executableDirs.Free(); }
896 if(prepDirectives) { prepDirectives.Free(); }
897 if(excludeLibs) { excludeLibs.Free(); }
899 CompilerConfig Copy()
921 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
922 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
923 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
924 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
925 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
926 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));