9 import "OldIDESettings"
13 enum DirTypes { includes, libraries, executables };
15 define defaultCompilerName = "Default";
17 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)";
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, 0, 1, 7 };
73 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(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(),
145 incref defaultCompiler;
146 return defaultCompiler;
149 class IDESettingsContainer : GlobalSettings
152 settingsName = "ecereIDESettingsTest";
154 settingsName = "ecereIDE";
157 virtual void OnLoad(GlobalSettingsData data);
159 char moduleLocation[MAX_LOCATION];
162 IDESettingsContainer()
164 char path[MAX_LOCATION];
166 LocateModule(null, moduleLocation);
167 strcpy(path, moduleLocation);
168 StripLastDirectory(moduleLocation, moduleLocation);
169 ChangeCh(moduleLocation, '\\', '/');
170 // PortableApps.com directory structure
171 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
173 char configFilePath[MAX_LOCATION];
174 char defaultConfigFilePath[MAX_LOCATION];
178 strcpy(configFilePath, path);
179 PathCat(configFilePath, "Data");
180 PathCat(configFilePath, "ecereIDE.ini");
182 strcpy(defaultConfigFilePath, path);
183 PathCat(defaultConfigFilePath, "App");
184 PathCat(defaultConfigFilePath, "DefaultData");
185 PathCat(defaultConfigFilePath, "ecereIDE.ini");
187 if(FileExists(defaultConfigFilePath))
189 if(!FileExists(configFilePath))
191 File f = FileOpen(defaultConfigFilePath, read);
192 f.CopyTo(configFilePath);
196 PathCat(path, "Data");
197 // the forced settings location will only be
198 // used if the running ide's path matches
199 // the PortableApps.com directory structure
200 // and the default ini file is found in
201 // the DefaultData directory
202 settingsLocation = path;
208 void OnAskReloadSettings()
210 /*if(MessageBox { type = YesNo, master = this,
211 text = "Global Settings Modified Externally",
212 contents = "The global settings were modified by another instance.\n"
213 "Would you like to reload them?" }.Modal() == Yes)*/
221 SettingsIOResult result = GlobalSettings::Load();
222 IDESettings data = (IDESettings)this.data;
223 CompilerConfig defaultCompiler = null;
226 this.data = IDESettings { };
228 *dataOwner = this.data;
230 if(result == fileNotCompatibleWithDriver)
233 OldIDESettings oldSettings { };
235 loaded = oldSettings.Load();
239 data = (IDESettings)this.data;
241 for(c : oldSettings.compilerConfigs)
242 data.compilerConfigs.Add(c.Copy());
244 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
245 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
247 data.docDir = oldSettings.docDir;
248 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
249 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
250 data.useFreeCaret = oldSettings.useFreeCaret;
251 data.showLineNumbers = oldSettings.showLineNumbers;
252 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
253 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
254 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
255 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
262 if(result == fileNotFound || !data)
264 data = (IDESettings)this.data;
265 data.useFreeCaret = true;
266 data.showLineNumbers = true;
267 data.caretFollowsScrolling = true;
270 // Ensure we have a default compiler
271 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
274 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
275 data.compilerConfigs.Add(defaultCompiler);
277 if(!data.compilerConfigsDir || !data.compilerConfigsDir[0])
278 data.property::compilerConfigsDir = "configs";
280 // We incref the compilers below, so reset refCount to 0
281 defaultCompiler._refCount = 0;
284 if(data.compilerConfigs)
286 for(c : data.compilerConfigs)
288 CompilerConfig compiler = c;
292 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
293 data.ManagePortablePaths(moduleLocation, true);
294 data.ForcePathSeparatorStyle(true);
300 IDESettings data = (IDESettings)this.data;
301 Platform runtimePlatform = GetRuntimePlatform();
302 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
303 data.ManagePortablePaths(moduleLocation, false);
304 data.ForcePathSeparatorStyle(true);
305 if(!GlobalSettings::Save())
306 PrintLn("Error saving IDE settings");
307 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
308 data.ManagePortablePaths(moduleLocation, true);
313 class IDESettings : GlobalSettingsData
316 List<CompilerConfig> compilerConfigs { };
317 Array<String> recentFiles { };
318 Array<String> recentProjects { };
319 property char * docDir
321 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
322 get { return docDir ? docDir : ""; }
323 isset { return docDir && docDir[0]; }
325 property char * ideFileDialogLocation
327 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
328 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
329 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
331 property char * ideProjectFileDialogLocation
333 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
334 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
335 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
338 bool showLineNumbers;
339 bool caretFollowsScrolling;
340 char * displayDriver;
342 // TODO: Classify settings
343 //EditorSettings editor { };
345 property char * projectDefaultTargetDir
347 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
348 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
349 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
351 property char * projectDefaultIntermediateObjDir
353 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
354 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
355 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
358 property char * compilerConfigsDir
360 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
361 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
362 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
365 property char * defaultCompiler
367 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
368 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
369 isset { return defaultCompiler && defaultCompiler[0]; }
374 char * ideFileDialogLocation;
375 char * ideProjectFileDialogLocation;
376 char * projectDefaultTargetDir;
377 char * projectDefaultIntermediateObjDir;
378 char * compilerConfigsDir;
379 char * defaultCompiler;
381 CompilerConfig GetCompilerConfig(String compilerName)
383 char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
384 CompilerConfig compilerConfig = null;
385 for(compiler : compilerConfigs)
387 if(!strcmp(compiler.name, name))
389 compilerConfig = compiler;
393 if(!compilerConfig && compilerConfigs.count)
394 compilerConfig = compilerConfigs.firstIterator.data;
396 incref compilerConfig;
397 return compilerConfig;
402 compilerConfigs.Free();
403 delete compilerConfigs;
406 recentProjects.Free();
407 delete recentProjects;
410 delete projectDefaultTargetDir;
411 delete projectDefaultIntermediateObjDir;
412 delete compilerConfigsDir;
413 delete defaultCompiler;
415 delete ideFileDialogLocation;
416 delete ideProjectFileDialogLocation;
417 delete displayDriver;
420 void ForcePathSeparatorStyle(bool unixStyle)
424 from = '\\', to = '/';
426 from = '/', to = '\\';
427 if(compilerConfigs && compilerConfigs.count)
430 for(config : compilerConfigs)
432 if(config.includeDirs && config.includeDirs.count)
434 for(i = 0; i < config.includeDirs.count; i++)
436 if(config.includeDirs[i] && config.includeDirs[i][0])
437 ChangeCh(config.includeDirs[i], from, to);
440 if(config.libraryDirs && config.libraryDirs.count)
442 for(i = 0; i < config.libraryDirs.count; i++)
444 if(config.libraryDirs[i] && config.libraryDirs[i][0])
445 ChangeCh(config.libraryDirs[i], from, to);
448 if(config.executableDirs && config.executableDirs.count)
450 for(i = 0; i < config.executableDirs.count; i++)
452 if(config.executableDirs[i] && config.executableDirs[i][0])
453 ChangeCh(config.executableDirs[i], from, to);
458 if(recentFiles && recentFiles.count)
461 for(c = 0; c < recentFiles.count; c++)
463 if(recentFiles[c] && recentFiles[c][0])
464 ChangeCh(recentFiles[c], from, to);
467 if(recentProjects && recentProjects.count)
470 for(c = 0; c < recentProjects.count; c++)
472 if(recentProjects[c] && recentProjects[c][0])
473 ChangeCh(recentProjects[c], from, to);
476 if(docDir && docDir[0])
477 ChangeCh(docDir, from, to);
478 if(ideFileDialogLocation && ideFileDialogLocation[0])
479 ChangeCh(ideFileDialogLocation, from, to);
480 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
481 ChangeCh(ideProjectFileDialogLocation, from, to);
483 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
484 ChangeCh(projectDefaultTargetDir, from, to);
485 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
486 ChangeCh(projectDefaultIntermediateObjDir, from, to);
488 if(compilerConfigsDir && compilerConfigsDir[0])
489 ChangeCh(compilerConfigsDir, from, to);
492 void ManagePortablePaths(char * location, bool makeAbsolute)
495 if(compilerConfigs && compilerConfigs.count)
497 for(config : compilerConfigs)
500 for(t = 0; t < DirTypes::enumSize; t++)
502 Array<String> dirs = null;
503 if(t == executables) dirs = config.executableDirs;
504 else if(t == includes) dirs = config.includeDirs;
505 else if(t == libraries) dirs = config.libraryDirs;
506 if(dirs && dirs.count)
508 for(c = 0; c < dirs.count; c++)
510 if(dirs[c] && dirs[c][0])
511 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
517 if(recentFiles && recentFiles.count)
519 for(c = 0; c < recentFiles.count; c++)
521 if(recentFiles[c] && recentFiles[c][0])
522 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
525 if(recentProjects && recentProjects.count)
527 for(c = 0; c < recentProjects.count; c++)
529 if(recentProjects[c] && recentProjects[c][0])
530 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
533 if(docDir && docDir[0])
534 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
535 if(ideFileDialogLocation && ideFileDialogLocation[0])
536 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
537 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
538 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
540 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
541 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
542 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
543 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
545 if(compilerConfigsDir && compilerConfigsDir[0])
546 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
549 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
554 char p[MAX_LOCATION];
556 PathCatSlash(p, path);
558 output = CopyString(p);
562 PathRelationship rel = eString_PathRelated(path, location, null);
563 if(rel == subPath || rel == identical)
565 char p[MAX_LOCATION];
566 MakePathRelative(path, location, p);
567 if(!*p) strcpy(p, "./");
568 else ChangeCh(p, '\\', '/');
570 output = CopyString(p);
578 void AddRecentFile(char * fileName)
581 char * filePath = CopyString(fileName);
582 ChangeCh(filePath, '\\', '/');
583 for(c = 0; c<recentFiles.count; c++)
585 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
587 recentFiles.Delete((void *)&recentFiles[c]);
591 while(recentFiles.count >= MaxRecent)
592 recentFiles.Delete(recentFiles.GetLast());
593 recentFiles.Insert(null, filePath);
594 //UpdateRecentMenus(owner);
597 void AddRecentProject(char * projectName)
600 char * filePath = CopyString(projectName);
601 ChangeCh(filePath, '\\', '/');
602 for(c = 0; c<recentProjects.count; c++)
604 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
606 recentProjects.Delete((void *)&recentProjects[c]);
610 while(recentProjects.count >= MaxRecent)
611 recentProjects.Delete(recentProjects.GetLast());
612 recentProjects.Insert(null, filePath);
613 //UpdateRecentMenus(owner);
617 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
618 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
619 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
620 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
621 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
622 // TODO: i18n with Array
623 static Array<String> compilerTypeLongNames
625 $"GNU Compiler Collection (GCC) / GNU Make",
626 $"Tiny C Compiler / GNU Make",
627 $"Portable C Compiler / GNU Make",
628 $"Microsoft Visual Studio 2005 (8.0) Compiler",
629 $"Microsoft Visual Studio 2008 (9.0) Compiler",
630 $"Microsoft Visual Studio 2010 (10.0) Compiler"
632 const CompilerType firstCompilerType = gcc;
633 const CompilerType lastCompilerType = vs10;
634 public enum CompilerType
636 gcc, tcc, pcc, vs8, vs9, vs10;
640 get { return this == vs8 || this == vs9 || this == vs10; }
645 get { return OnGetString(null, null, null); }
651 for(c = firstCompilerType; c <= lastCompilerType; c++)
652 if(!strcmpi(value, compilerTypeNames[c]))
659 property char * longName { get { return OnGetString(null, (void*)1, null); } };
660 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
661 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
662 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
663 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
665 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
667 if(this >= firstCompilerType && this <= lastCompilerType)
670 strcpy(tempString, compilerTypeNames[this]);
671 if(fieldData == null)
672 return compilerTypeNames[this];
673 else if(fieldData == (void*)1)
674 return compilerTypeLongNames[this];
675 else if(fieldData == (void*)2)
676 return compilerTypeVersionString[this];
677 else if(fieldData == (void*)3)
678 return compilerTypeYearString[this];
679 else if(fieldData == (void*)4)
680 return compilerTypeProjectFileExtension[this];
681 else if(fieldData == (void*)5)
682 return compilerTypeSolutionFileVersionString[this];
700 name = CopyString(value);
706 Platform targetPlatform;
708 property char * makeCommand
710 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
711 get { return makeCommand; }
712 isset { return makeCommand && makeCommand[0]; }
714 property char * ecpCommand
716 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
717 get { return ecpCommand; }
718 isset { return ecpCommand && ecpCommand[0]; }
720 property char * eccCommand
722 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
723 get { return eccCommand; }
724 isset { return eccCommand && eccCommand[0]; }
726 property char * ecsCommand
728 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
729 get { return ecsCommand; }
730 isset { return ecsCommand && ecsCommand[0]; }
732 property char * earCommand
734 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
735 get { return earCommand; }
736 isset { return earCommand && earCommand[0]; }
738 property char * cppCommand
740 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
741 get { return cppCommand; }
742 isset { return cppCommand && cppCommand[0]; }
744 property char * ccCommand
746 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
747 get { return ccCommand; }
748 isset { return ccCommand && ccCommand[0]; }
750 property char * execPrefixCommand
752 set { delete execPrefixCommand; if(value && value[0]) execPrefixCommand = CopyString(value); }
753 get { return execPrefixCommand; }
754 isset { return execPrefixCommand && execPrefixCommand[0]; }
758 property char * distccHosts
760 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
761 get { return distccHosts; }
762 isset { return distccHosts && distccHosts[0]; }
764 property Array<String> includeDirs
775 get { return includeDirs; }
776 isset { return includeDirs.count != 0; }
778 property Array<String> libraryDirs
789 get { return libraryDirs; }
790 isset { return libraryDirs.count != 0; }
792 property Array<String> executableDirs
796 executableDirs.Free();
799 delete executableDirs;
800 executableDirs = value;
803 get { return executableDirs; }
804 isset { return executableDirs.count != 0; }
806 property Array<NamedString> environmentVars
810 environmentVars.Free();
813 delete environmentVars;
814 environmentVars = value;
817 get { return environmentVars; }
818 isset { return environmentVars.count != 0; }
821 Array<String> includeDirs { };
822 Array<String> libraryDirs { };
823 Array<String> executableDirs { };
824 // TODO: Can JSON parse and serialize maps?
825 //EnvironmentVariables { };
826 Array<NamedString> environmentVars { };
835 char * execPrefixCommand;
839 struct { Array<String> includes, libraries, executables; };
840 Array<String> dirs[DirTypes];
853 delete execPrefixCommand;
855 if(environmentVars) environmentVars.Free();
856 if(includeDirs) { includeDirs.Free(); }
857 if(libraryDirs) { libraryDirs.Free(); }
858 if(executableDirs) { executableDirs.Free(); }
860 CompilerConfig Copy()
881 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
882 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
883 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
884 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });