2 public import static "ecere"
7 // *** Color Schemes ***
11 SyntaxColorScheme syntaxColors;
14 property const String name
16 set { delete name; name = CopyString(value); }
22 Color viewsBackground;
24 Color outputBackground;
26 Color projectViewBackground;
27 Color projectViewText;
31 Color selectedMarginColor;
32 Color lineNumbersColor;
33 Color sheetSelectionColor;
34 Color sheetSelectionText;
36 property SyntaxColorScheme syntaxColors
38 set { delete syntaxColors; syntaxColors = value; if(value) incref value; }
39 get { return syntaxColors; }
49 IDEColorScheme colorScheme;
51 // Default Color Schemes
52 IDEColorScheme darkColorScheme
54 name = "Classic Dark";
55 selectionColor = lightYellow;
56 selectionText = Color { 30, 40, 50 };
57 viewsBackground = Color { 30, 40, 50 };
58 viewsText = lightGray;
59 outputBackground = black;
61 sheetSelectionColor = Color { 170, 220, 255 };
62 sheetSelectionText = black;
63 projectViewBackground = Color { 30, 40, 50 };
64 projectViewText = lightGray;
67 marginColor = Color {24, 24, 24};
68 selectedMarginColor = Color {64, 64, 64};
69 lineNumbersColor = Color {160, 160, 160};
72 keywordColors = [ skyBlue, skyBlue ];
73 commentColor = Color { 125, 125, 125 };
74 charLiteralColor = Color { 245, 50, 245 };
75 stringLiteralColor = Color { 245, 50, 245 };
76 preprocessorColor = { 120, 220, 140 };
77 numberColor = Color { 0, 192, 192 };
81 IDEColorScheme lightColorScheme
83 name = "Classic Light";
84 selectionColor = Color { 10, 36, 106 };
85 selectionText = white;
86 viewsBackground = white;
88 outputBackground = white;
90 sheetSelectionColor = Color { 170, 220, 255 };
91 sheetSelectionText = black;
92 projectViewBackground = white;
93 projectViewText = black;
96 marginColor = Color {230, 230, 230};
97 selectedMarginColor = Color {200, 200, 200};
98 lineNumbersColor = Color {60, 60, 60};
101 keywordColors = [ blue, blue ];
102 commentColor = dimGray;
103 charLiteralColor = crimson;
104 stringLiteralColor = crimson;
105 preprocessorColor = green;
110 IDEColorScheme greenColorScheme
113 selectionColor = 0x00FFFFE0,
114 selectionText = 0x001E2832,
115 viewsBackground = 0x001E2832,
116 viewsText = 0x00D3D3D3,
117 outputBackground = 0x00000000,
118 outputText = 0x0000FF00,
119 projectViewBackground = 0x001E2832,
120 projectViewText = 0x00D3D3D3,
121 codeEditorBG = 0x00000000,
122 codeEditorFG = 0x00FFFFF0,
123 marginColor = 0x001100,
124 selectedMarginColor = 0x002200,
125 lineNumbersColor = 0x00FF00,
126 sheetSelectionColor = 0x00AADCFF,
127 sheetSelectionText = 0x00000000,
129 commentColor = 0x008c00,
130 charLiteralColor = 0x89de00,
131 stringLiteralColor = 0x89de00,
132 preprocessorColor = 0x0078DC8C,
133 numberColor = { 8, 237, 141 },
141 IDEColorScheme grayColorScheme
143 name = "Gray & Orange",
144 selectionColor = 0x00FFFFE0,
145 selectionText = 0x001E2832,
146 viewsBackground = 0x001E2832,
147 viewsText = 0x00D3D3D3,
148 outputBackground = 0x00000000,
149 outputText = 0x0000FF00,
150 projectViewBackground = 0x001E2832,
151 projectViewText = 0x00D3D3D3,
152 codeEditorBG = 0x00202020,
153 codeEditorFG = 0x00E2E2E5,
154 marginColor = 0x00303030,
155 selectedMarginColor = 0x00404040,
156 lineNumbersColor = 0x00939395,
157 sheetSelectionColor = 0x00AADCFF,
158 sheetSelectionText = 0x00000000,
160 commentColor = 0x005F5F5F,
161 charLiteralColor = 0x0089DE00,
162 stringLiteralColor = 0x00707070,
163 preprocessorColor = 0x00FAF4C6,
164 numberColor = 0x00FF9800,
172 define ecpDefaultCommand = "ecp";
173 define eccDefaultCommand = "ecc";
174 define ecsDefaultCommand = "ecs";
175 define earDefaultCommand = "ear";
176 define cppDefaultCommand = "gcc"; // As per #624 we decided to default to "gcc"...
177 define ccDefaultCommand = "gcc";
178 define cxxDefaultCommand = "g++";
179 //define ldDefaultCommand = "gcc";
180 define arDefaultCommand = "ar";
181 define objectDefaultFileExt = "o";
182 define outputDefaultFileExt = "";
186 import "OldIDESettings"
189 #define WIN32_LEAN_AND_MEAN
198 define MaxRecent = 9;
200 enum DirTypes { includes, libraries, executables };
202 define defaultCompilerName = "Default";
204 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
206 const char * settingsDirectoryNames[DirTypes] =
213 // This function cannot accept same pointer for source and output
214 // todo: rename ReplaceSpaces to EscapeSpaceAndSpecialChars or something
215 void ReplaceSpaces(char * output, const char * source)
220 for(c = 0, dc = 0; (ch = source[c]); c++, dc++)
222 if(ch == ' ') output[dc++] = '\\';
223 if(ch == '\"') output[dc++] = '\\';
224 if(ch == '&') output[dc++] = '\\';
227 if(ch == '(' || ch == ')') output[dc++] = '\\';
238 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
240 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
241 PathRelationship eString_PathRelated(const char * path, const char * to, char * pathDiff)
243 PathRelationship result;
244 if(pathDiff) *pathDiff = '\0';
245 if(path && *path && to && *to)
247 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
248 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
250 strcpy(pathRest, path);
251 for(; toRest[0] && pathRest[0];)
253 SplitDirectory(toRest, toPart, toRest);
254 SplitDirectory(pathRest, pathPart, pathRest);
255 if(!fstrcmp(pathPart, toPart)) result = siblings;
258 if(result == siblings)
260 if(!*toRest && !*pathRest) result = identical;
261 else if(!*pathRest) result = parentPath;
262 else result = subPath;
263 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
265 else result = unrelated;
271 if(!*path && !*to) result = bothEmpty;
272 else if(!*path) result = pathEmpty;
273 else result = toEmpty;
275 else if(!path && !to) result = bothNull;
276 else if(!path) result = pathNull;
277 else result = toNull;
282 char * CopyValidateMakefilePath(const char * path)
284 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 };
285 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 };
291 len = (int)strlen(path);
292 copy = CopyString(path);
298 Array<const char *> parts { };
305 for(v=0; vars[v]; v++)
307 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
311 parts.Add(vars[map[v]]);
312 c += strlen(vars[v]);
326 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
327 copy = new char[++len];
329 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
340 void ValidPathBufCopy(char *output, const char *input)
343 bool volumePath = false;
345 strcpy(output, input);
346 TrimLSpaces(output, output);
347 TrimRSpaces(output, output);
348 MakeSystemPath(output);
350 if(output[0] && output[1] == ':')
357 const char * chars = "*|:\",<>?";
358 char ch, * s = output, * o = output;
359 while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; }
363 if(volumePath && output[0])
368 void RemoveTrailingPathSeparator(char *path)
371 len = (int)strlen(path);
372 if(len>1 && path[len-1] == DIR_SEP)
376 void BasicValidatePathBoxPath(PathBox pathBox)
378 char path[MAX_LOCATION];
379 ValidPathBufCopy(path, pathBox.path);
380 RemoveTrailingPathSeparator(path);
384 CompilerConfig MakeDefaultCompiler(const char * name, bool readOnly)
386 CompilerConfig defaultCompiler
404 incref defaultCompiler;
405 return defaultCompiler;
408 //#define SETTINGS_TEST
410 define settingsDir = ".ecereIDE-SettingsTest";
411 define ideSettingsName = "ecereIDE-SettingsTest";
414 define settingsDir = "EcereIDE";
415 define ideSettingsName = "EcereIDE";
417 define settingsDir = ".ecereIDE";
418 define ideSettingsName = "ecereIDE";
422 class IDEConfigHolder
424 CompilerConfigs compilers { };
425 RecentFiles recentFiles { };
426 RecentWorkspaces recentWorkspaces { };
428 property CompilerConfigs compilers
430 set { compilers.Free(); delete compilers; compilers = value; }
431 get { return compilers; }
433 property RecentFiles recentFiles
435 set { recentFiles.Free(); delete recentFiles; recentFiles = value; }
436 get { return recentFiles; }
438 property RecentWorkspaces recentProjects
440 set { recentWorkspaces.Free(); delete recentWorkspaces; recentWorkspaces = value; }
441 get { return recentWorkspaces; }
448 recentWorkspaces.Free();
451 void forcePathSeparatorStyle(bool unixStyle)
455 from = '\\', to = '/';
457 from = '/', to = '\\';
458 recentFiles.changeChar(from, to);
459 recentWorkspaces.changeChar(from, to);
463 class IDESettingsContainer : GlobalSettings
465 virtual void onLoadCompilerConfigs();
466 virtual void onLoadRecentFiles();
467 virtual void onLoadRecentProjects();
468 virtual void onLoad();
470 CompilerConfigs compilerConfigs;
471 RecentFiles recentFiles;
472 RecentWorkspaces recentProjects;
474 property bool useNewConfigurationFiles
481 settingsName = "config";
482 settingsExtension = "econ";
483 settingsDirectory = settingsDir;
488 settingsName = ideSettingsName;
489 settingsExtension = null;
490 settingsDirectory = null;
495 char moduleLocation[MAX_LOCATION];
497 FileMonitor recentFilesMonitor
499 this, fileChange = { modified = true };
501 bool OnFileNotify(FileChange action, const char * param)
504 recentFilesMonitor.StopMonitoring();
505 f = FileOpen(recentFilesMonitor.fileName, read);
510 for(c = 0; c < 10 && !(locked = f.Lock(shared, 0, 0, false)); c++) ecere::sys::Sleep(0.01);
511 recentFiles.read(this);
519 FileMonitor recentProjectsMonitor
521 this, fileChange = { modified = true };
523 bool OnFileNotify(FileChange action, const char * param)
526 recentProjectsMonitor.StopMonitoring();
527 f = FileOpen(recentProjectsMonitor.fileName, read);
532 for(c = 0; c < 10 && !(locked = f.Lock(shared, 0, 0, false)); c++) ecere::sys::Sleep(0.01);
533 recentProjects.read(this);
541 static void getConfigFilePath(char * path, Class _class, char * dir, const char * configName)
544 strcpy(path, settingsFilePath);
545 StripLastDirectory(path, path);
547 PathCatSlash(path, settingsDir);
548 if(_class == class(CompilerConfig))
550 PathCatSlash(path, "compilerConfigs");
555 PathCatSlash(path, configName);
556 strcat(path, ".econ");
559 else if(_class == class(RecentFilesData))
560 PathCatSlash(path, "recentFiles.econ");
561 else if(_class == class(RecentWorkspacesData))
562 PathCatSlash(path, "recentWorkspaces.econ");
567 FileSize settingsFileSize;
569 IDESettingsContainer()
571 char path[MAX_LOCATION];
573 LocateModule(null, moduleLocation);
574 strcpy(path, moduleLocation);
575 StripLastDirectory(moduleLocation, moduleLocation);
576 ChangeCh(moduleLocation, '\\', '/');
577 // PortableApps.com directory structure
578 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ecere-ide.exe")))
580 char configFilePath[MAX_LOCATION];
581 char defaultConfigFilePath[MAX_LOCATION];
585 strcpy(configFilePath, path);
586 PathCat(configFilePath, "Data");
587 PathCat(configFilePath, ideSettingsName);
588 ChangeExtension(configFilePath, "ini", configFilePath);
590 strcpy(defaultConfigFilePath, path);
591 PathCat(defaultConfigFilePath, "App");
592 PathCat(defaultConfigFilePath, "DefaultData");
593 PathCat(defaultConfigFilePath, ideSettingsName);
594 ChangeExtension(defaultConfigFilePath, "ini", defaultConfigFilePath);
596 if(FileExists(defaultConfigFilePath))
598 if(!FileExists(configFilePath))
600 File f = FileOpen(defaultConfigFilePath, read);
601 f.CopyTo(configFilePath);
605 PathCat(path, "Data");
606 // the forced settings location will only be
607 // used if the running ide's path matches
608 // the PortableApps.com directory structure
609 // and the default ini file is found in
610 // the DefaultData directory
611 settingsLocation = path;
617 void OnAskReloadSettings()
619 FileSize newSettingsFileSize;
621 if(OpenAndLock(&newSettingsFileSize))
623 //if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
628 GuiApplication app = ((GuiApplication)__thisModule.application);
630 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
634 MessageBox { master = w, type = ok, isModal = true,
635 creationActivation = flash,
636 text = "Global Settings Modified Externally",
637 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
638 "The new settings will not be loaded to prevent loss of your ide settings.\n"
639 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
645 SettingsIOResult Load()
648 SettingsIOResult result;
649 useNewConfigurationFiles = true;
650 result = GlobalSettings::Load();
651 data = (IDESettings)this.data;
653 if(result == fileNotFound || (settingsFilePath && isGlobalPath))
655 bool retryNewConfig = settingsFilePath && isGlobalPath;
657 useNewConfigurationFiles = false;
660 settingsFilePath = null;
664 GlobalSettings::Load();
666 if(result == fileNotFound && retryNewConfig)
669 useNewConfigurationFiles = true;
670 result = GlobalSettings::Load();
673 data = (IDESettings)this.data;
676 this.data = IDESettings { };
678 *dataOwner = this.data;
680 if(result == fileNotCompatibleWithDriver)
683 OldIDESettings oldSettings { };
685 loaded = oldSettings.Load() == success;
689 data = (IDESettings)this.data;
691 for(c : oldSettings.compilerConfigs)
692 data.compilerConfigs.Add(c.Copy());
694 for(s : oldSettings.recentFiles) data.recentFiles.Add(s);
695 for(s : oldSettings.recentProjects) data.recentProjects.Add(s);
697 data.docDir = oldSettings.docDir;
698 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
699 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
700 data.useFreeCaret = oldSettings.useFreeCaret;
701 data.showLineNumbers = oldSettings.showLineNumbers;
702 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
703 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
704 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
705 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
712 if(result == fileNotFound || !data)
714 data = (IDESettings)this.data;
715 data.useFreeCaret = false; //true;
716 data.showLineNumbers = true;
717 data.caretFollowsScrolling = false; //true;
722 FileGetSize(settingsFilePath, &settingsFileSize);
723 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
724 data.ManagePortablePaths(moduleLocation, true);
725 data.ForcePathSeparatorStyle(true);
727 if(!data.colorSchemes || !data.colorSchemes.count)
729 if(!data.colorSchemes) data.colorSchemes = { };
731 data.colorSchemes.Add(darkColorScheme); incref darkColorScheme;
732 data.colorSchemes.Add(lightColorScheme); incref lightColorScheme;
733 data.colorSchemes.Add(greenColorScheme); incref greenColorScheme;
734 data.colorSchemes.Add(grayColorScheme); incref grayColorScheme;
737 if(data.activeColorScheme)
739 for(cs : data.colorSchemes; cs.name && !strcmp(cs.name, data.activeColorScheme))
747 colorScheme = data.colorSchemes[0];
748 data.activeColorScheme = colorScheme.name;
751 // Import from previous ecereIDE settings
754 // Save first so that settingsFilePath get set up
757 data.compilerConfigs.ensureDefaults();
758 data.compilerConfigs.write(this, null);
759 data.compilerConfigs.Free();
761 data.recentFiles.write(this);
762 data.recentFiles.Free();
764 data.recentProjects.write(this);
765 data.recentProjects.Free();
770 SettingsIOResult Save()
772 SettingsIOResult result;
774 useNewConfigurationFiles = true;
775 data = (IDESettings)this.data;
776 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
777 data.ManagePortablePaths(moduleLocation, false);
778 data.ForcePathSeparatorStyle(true);
780 settingsFilePath = null;
781 result = GlobalSettings::Save();
782 if(result != success)
783 PrintLn("Error saving IDE settings");
786 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
787 data.ManagePortablePaths(moduleLocation, true);
790 FileGetSize(settingsFilePath, &settingsFileSize);
796 static Map<String, String> getCompilerConfigFilePathsByName(const char * path)
798 Map<String, String> map { };
799 FileListing fl { path, extensions = "econ" };
802 if(fl.stats.attribs.isFile)
804 char name[MAX_FILENAME];
805 char * path = CopyString(fl.path);
807 GetLastDirectory(path, name);
808 StripExtension(name);
815 static Map<String, CompilerConfig> getCompilerConfigsByName(const char * path)
817 Map<String, CompilerConfig> map { };
818 FileListing fl { path, extensions = "econ" };
821 if(fl.stats.attribs.isFile)
823 char name[MAX_FILENAME];
824 char * path = CopyString(fl.path);
826 GetLastDirectory(path, name);
827 StripExtension(name);
829 CompilerConfig ccfg = CompilerConfig::read(path);
839 static SettingsIOResult writeConfigFile(const char * path, Class dataType, void * data)
841 SettingsIOResult result = error;
842 SafeFile sf = SafeFile::open(path, write);
845 WriteECONObject(sf.file, dataType, data, 0);
851 PrintLn($"error: could not safely open file for writing configuration: ", path);
855 static SettingsIOResult readConfigFile(const char * path, Class dataType, void ** data)
857 SettingsIOResult result = error;
859 if(!FileExists(path))
860 result = fileNotFound;
861 else if((sf = SafeFile::open(path, read)))
863 JSONResult jsonResult;
865 ECONParser parser { f = sf.file };
866 sf.file.Seek(0, start);
867 jsonResult = parser.GetObject(dataType, data);
868 if(jsonResult != success)
872 if(jsonResult == success)
876 result = fileNotCompatibleWithDriver;
877 PrintLn($"error: could not parse configuration file: ", path);
888 char path[MAX_LOCATION];
889 char tmp[MAX_LOCATION];
891 SafeFile ::open(const char * path, FileOpenMode mode)
893 SafeFile result = null;
894 if(mode == write || mode == read)
896 SafeFile sf { mode = mode };
899 FileLock lockType = mode == write ? exclusive : shared;
901 strcpy(sf.path, path);
902 strcpy(sf.tmp, path);
903 strcat(sf.tmp, ".tmp");
904 if(mode == write && FileExists(sf.tmp).isFile)
909 sf.file = FileOpen(sf.tmp, readWrite);
912 sf.file = FileOpen(sf.tmp, writeRead);
916 sf.file = FileOpen(sf.tmp, readWrite);
921 sf.file = FileOpen(path, mode);
924 for(c = 0; c < 10 && !(locked = sf.file.Lock(lockType, 0, 0, false)); c++) Sleep(0.01);
928 sf.file.Seek(0, start);
931 else if(mode == write)
932 PrintLn($"warning: SafeFile::open: unable to obtain exclusive lock on temporary file for writing: ", sf.tmp);
934 PrintLn($"warning: SafeFile::open: unable to obtain shared lock on file for reading: ", path);
936 else if(mode == write)
937 PrintLn($"warning: SafeFile::open: unable to open temporary file for writing: ", sf.tmp);
939 PrintLn($"warning: SafeFile::open: unable to open file for reading: ", path);
945 PrintLn($"warning: SafeFile::open: does not yet support FileOpenMode::", mode);
951 if(file && mode == write)
954 File f = FileOpen(path, readWrite);
957 f = FileOpen(path, writeRead);
961 f = FileOpen(path, readWrite);
967 for(c = 0; c < 10 && !(locked = f.Lock(exclusive, 0,0, false)); c++) Sleep(0.01);
971 f.Unlock(0,0, false);
973 file.Unlock(0,0, false);
976 for(c = 0; c < 10; c++)
978 if(MoveFileEx(tmp, path, { true, true }))
987 PrintLn($"warning: SafeFile::sync: failed to lock file for ", mode);
998 file.Unlock(0,0, false);
1004 class RecentFilesData
1007 RecentFiles recentFiles;
1011 if(recentFiles) recentFiles.Free();
1016 class RecentWorkspacesData
1019 RecentWorkspaces recentWorkspaces;
1021 ~RecentWorkspacesData()
1023 if(recentWorkspaces) recentWorkspaces.Free();
1024 delete recentWorkspaces;
1028 class IDESettings : GlobalSettingsData
1031 property CompilerConfigs compilerConfigs
1033 set { /*if(settingsContainer.oldConfig)*/ { if(compilerConfigs) compilerConfigs.Free(); delete compilerConfigs; if(value) compilerConfigs = value; } }
1034 get { return compilerConfigs; }
1035 isset { return false; }
1037 property RecentFiles recentFiles
1039 set { if(recentFiles) recentFiles.Free(); delete recentFiles; if(value) recentFiles = value; }
1040 get { return recentFiles; }
1041 isset { return false; }
1043 property RecentWorkspaces recentProjects
1045 set { if(recentProjects) recentProjects.Free(); delete recentProjects; if(value) recentProjects = value; }
1046 get { return recentProjects; }
1047 isset { return false; }
1049 property const char * docDir
1051 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
1052 get { return docDir ? docDir : ""; }
1053 isset { return docDir && docDir[0]; }
1055 property const char * ideFileDialogLocation
1057 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
1058 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
1059 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
1061 property const char * ideProjectFileDialogLocation
1063 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
1064 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
1065 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
1068 bool showLineNumbers;
1069 bool caretFollowsScrolling;
1070 char * displayDriver;
1072 // TODO: Classify settings
1073 //EditorSettings editor { };
1075 property const char * projectDefaultTargetDir
1077 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
1078 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
1079 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
1081 property const char * projectDefaultIntermediateObjDir
1083 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
1084 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
1085 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
1088 property const char * compilerConfigsDir
1090 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
1091 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
1092 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
1095 property const char * defaultCompiler
1097 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
1098 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
1099 isset { return defaultCompiler && defaultCompiler[0]; }
1102 property const String language
1107 language = CopyString(value);
1109 get { return language; }
1110 isset { return language != null; }
1113 property const String codeEditorFont
1117 delete codeEditorFont;
1118 codeEditorFont = CopyString(value);
1120 get { return codeEditorFont; }
1123 float codeEditorFontSize;
1124 bool showFixedPitchFontsOnly;
1126 property Array<IDEColorScheme> colorSchemes
1130 if(colorSchemes && colorSchemes._refCount < 2)
1131 colorSchemes.Free();
1132 delete colorSchemes;
1133 colorSchemes = value;
1135 incref colorSchemes;
1137 get { return colorSchemes; }
1140 property const String activeColorScheme
1144 delete activeColorScheme;
1145 activeColorScheme = CopyString(value);
1147 get { return activeColorScheme; }
1151 CompilerConfigs compilerConfigs { };
1153 char * ideFileDialogLocation;
1154 char * ideProjectFileDialogLocation;
1155 char * projectDefaultTargetDir;
1156 char * projectDefaultIntermediateObjDir;
1157 char * compilerConfigsDir;
1158 char * defaultCompiler;
1160 RecentFiles recentFiles { };
1161 RecentWorkspaces recentProjects { };
1163 Array<IDEColorScheme> colorSchemes;
1165 String codeEditorFont;
1167 String activeColorScheme;
1169 showFixedPitchFontsOnly = true;
1170 codeEditorFontSize = 12;
1171 codeEditorFont = CopyString("Courier New");
1175 compilerConfigs.Free();
1176 delete compilerConfigs;
1177 if(recentProjects) { recentFiles.Free(); delete recentFiles; }
1178 if(recentProjects) { recentProjects.Free(); delete recentProjects; }
1181 delete projectDefaultTargetDir;
1182 delete projectDefaultIntermediateObjDir;
1183 delete compilerConfigsDir;
1184 delete defaultCompiler;
1187 delete ideFileDialogLocation;
1188 delete ideProjectFileDialogLocation;
1189 delete displayDriver;
1191 delete codeEditorFont;
1193 colorSchemes.Free();
1194 delete activeColorScheme;
1197 void ForcePathSeparatorStyle(bool unixStyle)
1201 from = '\\', to = '/';
1203 from = '/', to = '\\';
1204 if(compilerConfigs && compilerConfigs.count)
1207 for(config : compilerConfigs)
1209 if(config.includeDirs && config.includeDirs.count)
1211 for(i = 0; i < config.includeDirs.count; i++)
1213 if(config.includeDirs[i] && config.includeDirs[i][0])
1214 ChangeCh(config.includeDirs[i], from, to);
1217 if(config.libraryDirs && config.libraryDirs.count)
1219 for(i = 0; i < config.libraryDirs.count; i++)
1221 if(config.libraryDirs[i] && config.libraryDirs[i][0])
1222 ChangeCh(config.libraryDirs[i], from, to);
1225 if(config.executableDirs && config.executableDirs.count)
1227 for(i = 0; i < config.executableDirs.count; i++)
1229 if(config.executableDirs[i] && config.executableDirs[i][0])
1230 ChangeCh(config.executableDirs[i], from, to);
1235 recentFiles.changeChar(from, to);
1236 recentProjects.changeChar(from, to);
1237 if(docDir && docDir[0])
1238 ChangeCh(docDir, from, to);
1239 if(ideFileDialogLocation && ideFileDialogLocation[0])
1240 ChangeCh(ideFileDialogLocation, from, to);
1241 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
1242 ChangeCh(ideProjectFileDialogLocation, from, to);
1244 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
1245 ChangeCh(projectDefaultTargetDir, from, to);
1246 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
1247 ChangeCh(projectDefaultIntermediateObjDir, from, to);
1249 if(compilerConfigsDir && compilerConfigsDir[0])
1250 ChangeCh(compilerConfigsDir, from, to);
1253 void ManagePortablePaths(char * location, bool makeAbsolute)
1256 if(compilerConfigs && compilerConfigs.count)
1258 for(config : compilerConfigs)
1261 for(t = 0; t < DirTypes::enumSize; t++)
1263 Array<String> dirs = null;
1264 if(t == executables) dirs = config.executableDirs;
1265 else if(t == includes) dirs = config.includeDirs;
1266 else if(t == libraries) dirs = config.libraryDirs;
1267 if(dirs && dirs.count)
1269 for(c = 0; c < dirs.count; c++)
1271 if(dirs[c] && dirs[c][0])
1272 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
1278 if(recentFiles && recentFiles.count)
1280 for(c = 0; c < recentFiles.count; c++)
1282 if(recentFiles[c] && recentFiles[c][0])
1283 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
1286 if(recentProjects && recentProjects.count)
1288 for(c = 0; c < recentProjects.count; c++)
1290 if(recentProjects[c] && recentProjects[c][0])
1291 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
1294 if(docDir && docDir[0])
1295 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
1296 if(ideFileDialogLocation && ideFileDialogLocation[0])
1297 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
1298 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
1299 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
1301 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
1302 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
1303 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
1304 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
1306 if(compilerConfigsDir && compilerConfigsDir[0])
1307 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
1310 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
1315 char p[MAX_LOCATION];
1316 strcpy(p, location);
1317 PathCatSlash(p, path);
1319 output = CopyString(p);
1323 PathRelationship rel = eString_PathRelated(path, location, null);
1324 if(rel == subPath || rel == identical)
1326 char p[MAX_LOCATION];
1327 MakePathRelative(path, location, p);
1328 if(!*p) strcpy(p, "./");
1329 else ChangeCh(p, '\\', '/');
1331 output = CopyString(p);
1340 class RecentFiles : RecentPaths
1342 void read(IDESettingsContainer settingsContainer)
1344 char path[MAX_LOCATION];
1345 RecentFilesData d = null;
1346 Class _class = class(RecentFilesData);
1347 settingsContainer.getConfigFilePath(path, _class, null, null);
1348 readConfigFile(path, _class, &d);
1349 if(d && d.recentFiles && d.recentFiles.count)
1352 Copy((void *)d.recentFiles);
1353 d.recentFiles.RemoveAll();
1354 settingsContainer.recentFiles = this; // Merge IDEConfigHolder / IDESettingsContainer?
1357 settingsContainer.recentFilesMonitor.fileName = path;
1358 settingsContainer.recentFilesMonitor.StartMonitoring();
1359 settingsContainer.onLoadRecentFiles();
1362 void write(IDESettingsContainer settingsContainer)
1364 char path[MAX_LOCATION];
1365 RecentFilesData d { };
1366 Class _class = class(RecentFilesData);
1367 settingsContainer.getConfigFilePath(path, _class, null, null);
1368 d.recentFiles = this;
1369 writeConfigFile(path, _class, d);
1370 d.recentFiles = null;
1375 class RecentWorkspaces : RecentPaths
1377 void read(IDESettingsContainer settingsContainer)
1379 char path[MAX_LOCATION];
1380 RecentWorkspacesData d = null;
1381 Class _class = class(RecentWorkspacesData);
1382 settingsContainer.getConfigFilePath(path, _class, null, null);
1383 readConfigFile(path, _class, &d);
1384 if(d && d.recentWorkspaces && d.recentWorkspaces.count)
1387 Copy((void *)d.recentWorkspaces);
1388 d.recentWorkspaces.RemoveAll();
1389 settingsContainer.recentProjects = this; // Merge IDEConfigHolder / IDESettingsContainer?
1392 settingsContainer.recentProjectsMonitor.fileName = path;
1393 settingsContainer.recentProjectsMonitor.StartMonitoring();
1394 settingsContainer.onLoadRecentProjects();
1397 void write(IDESettingsContainer settingsContainer)
1399 char path[MAX_LOCATION];
1400 RecentWorkspacesData d { };
1401 Class _class = class(RecentWorkspacesData);
1402 settingsContainer.getConfigFilePath(path, _class, null, null);
1403 d.recentWorkspaces = this;
1404 writeConfigFile(path, _class, d);
1405 d.recentWorkspaces = null;
1410 class RecentPaths : Array<String>
1412 IteratorPointer Add(T value)
1415 char * filePath = (char *)value;
1416 ChangeCh(filePath, '\\', '/');
1417 for(c = 0; c < count; c++)
1419 if(this[c] && !fstrcmp(this[c], filePath))
1421 Delete((void *)&this[c]);
1425 return Array::Add((T)filePath);
1428 IteratorPointer addRecent(const String value)
1431 char * filePath = CopyString((char *)value);
1433 ChangeCh(filePath, '\\', '/');
1434 for(c = 0; c < count; c++)
1436 if(this[c] && !fstrcmp(this[c], filePath))
1438 Delete((void *)&this[c]);
1442 while(count >= MaxRecent)
1444 ip = Insert(null, filePath);
1448 void changeChar(char from, char to)
1453 for(c = 0; c < count; c++)
1455 if(this[c] && this[c][0])
1456 ChangeCh(this[c], from, to);
1462 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
1463 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
1464 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
1465 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
1466 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
1467 // TODO: i18n with Array
1468 static Array<const String> compilerTypeLongNames
1470 $"GNU Compiler Collection (GCC) / GNU Make",
1471 $"Tiny C Compiler / GNU Make",
1472 $"Portable C Compiler / GNU Make",
1473 $"Microsoft Visual Studio 2005 (8.0) Compiler",
1474 $"Microsoft Visual Studio 2008 (9.0) Compiler",
1475 $"Microsoft Visual Studio 2010 (10.0) Compiler"
1477 const CompilerType firstCompilerType = gcc;
1478 const CompilerType lastCompilerType = vs10;
1479 public enum CompilerType
1481 gcc, tcc, pcc, vs8, vs9, vs10;
1485 get { return this == vs8 || this == vs9 || this == vs10; }
1488 property const char *
1490 get { return OnGetString(null, null, null); }
1496 for(c = firstCompilerType; c <= lastCompilerType; c++)
1497 if(!strcmpi(value, compilerTypeNames[c]))
1504 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
1505 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
1506 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
1507 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
1508 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
1510 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1512 if(this >= firstCompilerType && this <= lastCompilerType)
1515 strcpy(tempString, compilerTypeNames[this]);
1516 if(fieldData == null)
1517 return compilerTypeNames[this];
1518 else if(fieldData == (void*)1)
1519 return compilerTypeLongNames[this];
1520 else if(fieldData == (void*)2)
1521 return compilerTypeVersionString[this];
1522 else if(fieldData == (void*)3)
1523 return compilerTypeYearString[this];
1524 else if(fieldData == (void*)4)
1525 return compilerTypeProjectFileExtension[this];
1526 else if(fieldData == (void*)5)
1527 return compilerTypeSolutionFileVersionString[this];
1533 class CompilerConfig
1539 property const char * name
1541 set { delete name; if(value) name = CopyString(value); }
1542 get { return name; }
1546 Platform targetPlatform;
1548 property const char * makeCommand
1550 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
1551 get { return makeCommand; }
1552 isset { return makeCommand && makeCommand[0]; }
1554 property const char * ecpCommand
1556 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
1557 get { return ecpCommand; }
1558 isset { return ecpCommand && ecpCommand[0]; }
1560 property const char * eccCommand
1562 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
1563 get { return eccCommand; }
1564 isset { return eccCommand && eccCommand[0]; }
1566 property const char * ecsCommand
1568 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
1569 get { return ecsCommand; }
1570 isset { return ecsCommand && ecsCommand[0]; }
1572 property const char * earCommand
1574 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
1575 get { return earCommand; }
1576 isset { return earCommand && earCommand[0]; }
1578 property const char * cppCommand
1580 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
1581 get { return cppCommand; }
1582 isset { return cppCommand && cppCommand[0]; }
1584 property const char * ccCommand
1586 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
1587 get { return ccCommand; }
1588 isset { return ccCommand && ccCommand[0]; }
1590 property const char * cxxCommand
1592 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
1593 get { return cxxCommand; }
1594 isset { return cxxCommand && cxxCommand[0]; }
1596 property const char * arCommand
1598 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
1599 get { return arCommand; }
1600 isset { return arCommand && arCommand[0]; }
1602 property const char * ldCommand
1604 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
1605 get { return ldCommand; }
1606 isset { return ldCommand && ldCommand[0]; }
1608 property const char * objectFileExt
1610 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
1611 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
1612 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
1614 property const char * staticLibFileExt
1616 set { delete staticLibFileExt; if(value && value[0]) staticLibFileExt = CopyString(value); }
1617 get { return staticLibFileExt; }
1618 isset { return staticLibFileExt && staticLibFileExt[0]; }
1620 property const char * sharedLibFileExt
1622 set { delete sharedLibFileExt; if(value && value[0]) sharedLibFileExt = CopyString(value); }
1623 get { return sharedLibFileExt; }
1624 isset { return sharedLibFileExt && sharedLibFileExt[0]; }
1626 property const char * executableFileExt
1628 set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
1629 get { return executableFileExt; }
1630 isset { return executableFileExt && executableFileExt[0]; }
1632 property const char * executableLauncher
1634 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1635 get { return executableLauncher; }
1636 isset { return executableLauncher && executableLauncher[0]; }
1638 // TODO: implement CompilerConfig::windresCommand
1642 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
1644 property const char * distccHosts
1646 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
1647 get { return distccHosts; }
1648 isset { return distccHosts && distccHosts[0]; }
1650 property const char * gnuToolchainPrefix
1652 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1653 get { return gnuToolchainPrefix; }
1654 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
1656 property const char * sysroot
1658 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
1659 get { return sysroot; }
1660 isset { return sysroot && sysroot[0]; }
1662 bool resourcesDotEar;
1664 property Array<String> includeDirs
1672 includeDirs = value;
1675 get { return includeDirs; }
1676 isset { return includeDirs.count != 0; }
1678 property Array<String> libraryDirs
1686 libraryDirs = value;
1689 get { return libraryDirs; }
1690 isset { return libraryDirs.count != 0; }
1692 property Array<String> executableDirs
1696 executableDirs.Free();
1699 delete executableDirs;
1700 executableDirs = value;
1703 get { return executableDirs; }
1704 isset { return executableDirs.count != 0; }
1706 property Array<NamedString> environmentVars
1710 environmentVars.Free();
1713 delete environmentVars;
1714 environmentVars = value;
1717 get { return environmentVars; }
1718 isset { return environmentVars.count != 0; }
1720 property Array<String> prepDirectives
1724 prepDirectives.Free();
1727 delete prepDirectives;
1728 prepDirectives = value;
1731 get { return prepDirectives; }
1732 isset { return prepDirectives.count != 0; }
1734 property Array<String> excludeLibs
1742 excludeLibs = value;
1745 get { return excludeLibs; }
1746 isset { return excludeLibs.count != 0; }
1748 property Array<String> eCcompilerFlags
1752 eCcompilerFlags.Free();
1755 delete eCcompilerFlags;
1756 eCcompilerFlags = value;
1759 get { return eCcompilerFlags; }
1760 isset { return eCcompilerFlags.count != 0; }
1762 property Array<String> compilerFlags
1766 compilerFlags.Free();
1769 delete compilerFlags;
1770 compilerFlags = value;
1773 get { return compilerFlags; }
1774 isset { return compilerFlags.count != 0; }
1776 property Array<String> cxxFlags
1787 get { return cxxFlags; }
1788 isset { return cxxFlags.count != 0; }
1790 property Array<String> linkerFlags
1798 linkerFlags = value;
1801 get { return linkerFlags; }
1802 isset { return linkerFlags.count != 0; }
1804 // json backward compatibility
1805 property const char * gccPrefix
1807 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1808 get { return gnuToolchainPrefix; }
1809 isset { return false; }
1811 property const char * execPrefixCommand
1813 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1814 get { return executableLauncher; }
1815 isset { return false; }
1817 property const char * outputFileExt
1819 set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
1820 get { return executableFileExt; }
1821 isset { return false; }
1824 property bool hasDocumentOutput
1828 bool result = executableFileExt && executableFileExt[0] &&
1829 (!strcmpi(executableFileExt, "htm") || !strcmpi(executableFileExt, "html"));
1832 isset { return false; }
1835 Array<String> includeDirs { };
1836 Array<String> libraryDirs { };
1837 Array<String> executableDirs { };
1838 // TODO: Can JSON parse and serialize maps?
1839 //EnvironmentVariables { };
1840 Array<NamedString> environmentVars { };
1841 Array<String> prepDirectives { };
1842 Array<String> excludeLibs { };
1843 Array<String> eCcompilerFlags { };
1844 Array<String> compilerFlags { };
1845 Array<String> cxxFlags { };
1846 Array<String> linkerFlags { };
1858 char * objectFileExt;
1859 char * staticLibFileExt;
1860 char * sharedLibFileExt;
1861 char * executableFileExt;
1862 char * executableLauncher;
1864 char * gnuToolchainPrefix;
1868 struct { Array<String> includes, libraries, executables; };
1869 Array<String> dirs[DirTypes];
1884 delete objectFileExt;
1885 delete staticLibFileExt;
1886 delete sharedLibFileExt;
1887 delete executableFileExt;
1889 delete executableLauncher;
1891 delete gnuToolchainPrefix;
1893 if(environmentVars) environmentVars.Free();
1894 if(includeDirs) { includeDirs.Free(); }
1895 if(libraryDirs) { libraryDirs.Free(); }
1896 if(executableDirs) { executableDirs.Free(); }
1897 if(prepDirectives) { prepDirectives.Free(); }
1898 if(excludeLibs) { excludeLibs.Free(); }
1899 if(compilerFlags) { compilerFlags.Free(); }
1900 if(cxxFlags) { cxxFlags.Free(); }
1901 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1902 if(linkerFlags) { linkerFlags.Free(); }
1905 int OnCompare(CompilerConfig b)
1909 !(result = type.OnCompare(b.type)) &&
1910 !(result = targetPlatform.OnCompare(b.targetPlatform)) &&
1911 !(result = numJobs.OnCompare(b.numJobs)) &&
1912 !(result = ccacheEnabled.OnCompare(b.ccacheEnabled)) &&
1913 !(result = distccEnabled.OnCompare(b.distccEnabled)) &&
1914 !(result = resourcesDotEar.OnCompare(b.resourcesDotEar)) &&
1915 !(result = noStripTarget.OnCompare(b.noStripTarget))
1919 !(result = name.OnCompare(b.name)) &&
1920 !(result = ecpCommand.OnCompare(b.ecpCommand)) &&
1921 !(result = eccCommand.OnCompare(b.eccCommand)) &&
1922 !(result = ecsCommand.OnCompare(b.ecsCommand)) &&
1923 !(result = earCommand.OnCompare(b.earCommand)) &&
1924 !(result = cppCommand.OnCompare(b.cppCommand)) &&
1925 !(result = ccCommand.OnCompare(b.ccCommand)) &&
1926 !(result = cxxCommand.OnCompare(b.cxxCommand)) &&
1927 !(result = ldCommand.OnCompare(b.ldCommand)) &&
1928 !(result = arCommand.OnCompare(b.arCommand)) &&
1929 !(result = objectFileExt.OnCompare(b.objectFileExt)) &&
1930 !(result = outputFileExt.OnCompare(b.outputFileExt)) &&
1931 !(result = makeCommand.OnCompare(b.makeCommand)) &&
1932 !(result = executableLauncher.OnCompare(b.executableLauncher)) &&
1933 !(result = distccHosts.OnCompare(b.distccHosts)) &&
1934 !(result = gnuToolchainPrefix.OnCompare(b.gnuToolchainPrefix)) &&
1935 !(result = sysroot.OnCompare(b.sysroot)));
1938 !(result = includeDirs.OnCompare(b.includeDirs)) &&
1939 !(result = libraryDirs.OnCompare(b.libraryDirs)) &&
1940 !(result = executableDirs.OnCompare(b.executableDirs)) &&
1941 !(result = environmentVars.OnCompare(b.environmentVars)) &&
1942 !(result = prepDirectives.OnCompare(b.prepDirectives)) &&
1943 !(result = excludeLibs.OnCompare(b.excludeLibs)) &&
1944 !(result = cxxFlags.OnCompare(b.cxxFlags)) &&
1945 !(result = eCcompilerFlags.OnCompare(b.eCcompilerFlags)) &&
1946 !(result = compilerFlags.OnCompare(b.compilerFlags)) &&
1947 !(result = linkerFlags.OnCompare(b.linkerFlags)));
1952 CompilerConfig Copy()
1985 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1986 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1987 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1988 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1989 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1990 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1991 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1992 for(s : cxxFlags) copy.cxxFlags.Add(CopyString(s));
1993 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1994 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
2000 CompilerConfig ::read(const char * path)
2002 CompilerConfig d = null;
2003 readConfigFile(path, class(CompilerConfig), &d);
2007 void write(IDESettingsContainer settingsContainer)
2009 char dir[MAX_LOCATION];
2010 char path[MAX_LOCATION];
2011 const char * settingsFilePath = settingsContainer.settingsFilePath;
2012 settingsContainer.getConfigFilePath(path, _class, dir, name);
2013 if(FileExists(settingsFilePath) && !FileExists(dir))
2016 if(!FileExists(dir))
2017 PrintLn($"Error creating compiler configs directory at ", dir, " location.");
2019 writeConfigFile(path, _class, this);
2023 class CompilerConfigs : List<CompilerConfig>
2025 CompilerConfig GetCompilerConfig(const String compilerName)
2027 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
2028 CompilerConfig compilerConfig = null;
2029 for(compiler : this)
2031 if(!strcmp(compiler.name, name))
2033 compilerConfig = compiler;
2037 if(!compilerConfig && count)
2038 compilerConfig = this[0];
2041 incref compilerConfig;
2042 if(compilerConfig._refCount == 1)
2043 incref compilerConfig;
2045 return compilerConfig;
2048 void ensureDefaults()
2050 // Ensure we have a default compiler
2051 CompilerConfig defaultCompiler = GetCompilerConfig(defaultCompilerName);
2052 if(!defaultCompiler)
2054 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
2055 Insert(null, defaultCompiler);
2056 defaultCompiler = null;
2058 delete defaultCompiler;
2062 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
2063 ccfg.ecpCommand = ecpDefaultCommand;
2064 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
2065 ccfg.eccCommand = eccDefaultCommand;
2066 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
2067 ccfg.ecsCommand = ecsDefaultCommand;
2068 if(!ccfg.earCommand || !ccfg.earCommand[0])
2069 ccfg.earCommand = earDefaultCommand;
2070 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
2071 ccfg.cppCommand = cppDefaultCommand;
2072 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
2073 ccfg.ccCommand = ccDefaultCommand;
2074 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
2075 ccfg.cxxCommand = cxxDefaultCommand;
2076 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
2077 ccfg.ldCommand = ldDefaultCommand;*/
2078 if(!ccfg.arCommand || !ccfg.arCommand[0])
2079 ccfg.arCommand = arDefaultCommand;
2080 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
2081 ccfg.objectFileExt = objectDefaultFileExt;
2082 /*if(!ccfg.staticLibFileExt || !ccfg.staticLibFileExt[0])
2083 ccfg.staticLibFileExt = staticLibDefaultFileExt;*/
2084 /*if(!ccfg.sharedLibFileExt || !ccfg.sharedLibFileExt[0])
2085 ccfg.sharedLibFileExt = sharedLibDefaultFileExt;*/
2086 /*if(!ccfg.executableFileExt || !ccfg.executableFileExt[0])
2087 ccfg.executableFileExt = outputDefaultFileExt;*/
2088 if(!ccfg._refCount) incref ccfg;
2092 AVLTree<String> getWriteRequiredList(CompilerConfigs oldConfigs)
2094 AVLTree<String> list { };
2098 for(occfg : oldConfigs; !strcmp(ccfg.name, occfg.name))
2101 if(ccfg.OnCompare(occfg))
2102 list.Add(CopyString(ccfg.name));
2106 list.Add(CopyString(ccfg.name));
2111 bool read(IDESettingsContainer settingsContainer)
2113 if(settingsContainer.settingsFilePath)
2115 char dir[MAX_LOCATION];
2116 char path[MAX_LOCATION];
2117 Class _class = class(CompilerConfig);
2118 settingsContainer.getConfigFilePath(path, _class, dir, null);
2121 AVLTree<const String> addedConfigs { };
2122 Map<String, CompilerConfig> compilerConfigsByName = getCompilerConfigsByName(dir);
2123 MapIterator<const String, CompilerConfig> it { map = compilerConfigsByName };
2125 settingsContainer.compilerConfigs = this; // Merge IDEConfigHolder / IDESettingsContainer?
2126 if(it.Index("Default", false))
2128 CompilerConfig ccfg = it.data;
2130 addedConfigs.Add(ccfg.name);
2132 for(ccfg : compilerConfigsByName)
2134 if(!addedConfigs.Find(ccfg.name))
2137 addedConfigs.Add(ccfg.name);
2140 delete addedConfigs;
2142 compilerConfigsByName.Free();
2143 delete compilerConfigsByName;
2144 settingsContainer.onLoadCompilerConfigs();
2151 void write(IDESettingsContainer settingsContainer, AVLTree<String> cfgsToWrite)
2153 char dir[MAX_LOCATION];
2154 char path[MAX_LOCATION];
2155 Map<String, String> paths;
2156 settingsContainer.getConfigFilePath(path, class(CompilerConfig), dir, null);
2157 paths = getCompilerConfigFilePathsByName(dir);
2159 MapIterator<String, String> it { map = paths };
2162 CompilerConfig ccfg = c;
2163 if(!cfgsToWrite || cfgsToWrite.Find(ccfg.name))
2164 ccfg.write(settingsContainer);
2165 if(it.Index(ccfg.name, false))
2174 const char * path = p;
2182 #if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
2183 struct LanguageOption
2186 const String bitmap;
2190 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
2195 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
2197 Bitmap icon = res ? res.bitmap : null;
2200 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
2201 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
2205 Array<LanguageOption> languages
2207 { "English", ":countryCode/gb.png", "" },
2208 { "汉语", ":countryCode/cn.png", "zh_CN" },
2209 { "Español", ":countryCode/es.png", "es" },
2210 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
2211 { "Русский (43%)", ":countryCode/ru.png", "ru" },
2212 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
2213 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
2214 { "मराठी (10%)", ":countryCode/in.png", "mr" },
2215 { "Hebrew (8%)", ":countryCode/il.png", "he" },
2216 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
2219 const String GetLanguageString()
2221 char * dot, * colon;
2222 static char lang[256];
2223 const String language = getenv("ECERE_LANGUAGE");
2224 if(!language) language = getenv("LANGUAGE");
2225 if(!language) language = getenv("LC_ALL");
2226 if(!language) language = getenv("LC_MESSAGES");
2227 if(!language) language = getenv("LANG");
2228 if(!language) language = "";
2229 if(language && (colon = strchr(language, ':')))
2231 if(lang != language)
2232 strncpy(lang, language, sizeof(lang));
2233 lang[sizeof(lang)-1] = 0;
2234 lang[colon - language] = 0;
2237 if(language && (dot = strchr(language, '.')))
2239 if(lang != language)
2240 strncpy(lang, language, sizeof(lang));
2241 lang[sizeof(lang)-1] = 0;
2242 lang[dot - language] = 0;
2248 void setEcereLanguageInWinRegEnvironment(const char * languageCode)
2252 uint16 wLanguage[256];
2256 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
2259 UTF8toUTF16Buffer(languageCode, wLanguage, sizeof(wLanguage) / sizeof(uint16));
2260 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
2266 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
2268 bool restart = true;
2269 String command = null;
2270 int arg0Len = (int)strlen(app.argv[0]);
2282 for(w = ide.firstChild; w; w = w.next)
2284 if(w.isActiveClient && w.isDocument)
2286 if(!w.CloseConfirmation(true))
2295 if(!projectView.CloseConfirmation(true))
2297 if(projectView.fileName)
2299 const char * name = projectView.fileName;
2302 for(j = 0; (ch = name[j]); j++)
2303 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2307 command = new char[len + 1];
2309 strcpy(command, app.argv[0]);
2311 if(projectView.fileName)
2313 strcat(command, " ");
2315 ReplaceSpaces(command + len, projectView.fileName);
2320 for(w = ide.firstChild; w; w = w.next)
2321 if(w.isActiveClient && w.isDocument)
2322 w.modifiedDocument = false;
2323 projectView.modifiedDocument = false;
2328 for(w = ide.firstChild; w; w = w.next)
2330 if(w.isActiveClient && w.isDocument)
2332 if(!w.CloseConfirmation(true))
2339 const char * name = w.fileName;
2341 for(j = 0; (ch = name[j]); j++)
2342 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2349 command = new char[len + 1];
2350 strcpy(command, app.argv[0]);
2353 for(w = ide.firstChild; w; w = w.next)
2355 if(w.isActiveClient && w.isDocument)
2357 const char * name = w.fileName;
2360 strcat(command, " ");
2362 ReplaceSpaces(command + len, name);
2363 len = (int)strlen(command);
2370 for(w = ide.firstChild; w; w = w.next)
2371 if(w.isActiveClient && w.isDocument)
2372 w.modifiedDocument = false;
2377 settings.language = code;
2378 settingsContainer.Save();
2380 setEcereLanguageInWinRegEnvironment(code);
2382 if(eClass_IsDerived(app._class, class(GuiApplication)))
2384 GuiApplication guiApp = (GuiApplication)app;
2385 guiApp.desktop.Destroy(0);
2392 for(i = 1; i < app.argc; i++)
2394 const char * arg = app.argv[i];
2396 for(j = 0; (ch = arg[j]); j++)
2397 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2400 command = new char[len + 1];
2401 strcpy(command, app.argv[0]);
2403 for(i = 1; i < app.argc; i++)
2405 strcat(command, " ");
2407 ReplaceSpaces(command + len, app.argv[i]);
2408 len = (int)strlen(command);
2414 SetEnvironment("ECERE_LANGUAGE", code);
2416 ExecuteWait(command);