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";
413 define settingsDir = ".ecereIDE";
414 define ideSettingsName = "ecereIDE";
417 class IDEConfigHolder
419 CompilerConfigs compilers { };
420 RecentFiles recentFiles { };
421 RecentWorkspaces recentWorkspaces { };
423 property CompilerConfigs compilers
425 set { compilers.Free(); delete compilers; compilers = value; }
426 get { return compilers; }
428 property RecentFiles recentFiles
430 set { recentFiles.Free(); delete recentFiles; recentFiles = value; }
431 get { return recentFiles; }
433 property RecentWorkspaces recentProjects
435 set { recentWorkspaces.Free(); delete recentWorkspaces; recentWorkspaces = value; }
436 get { return recentWorkspaces; }
443 recentWorkspaces.Free();
446 void forcePathSeparatorStyle(bool unixStyle)
450 from = '\\', to = '/';
452 from = '/', to = '\\';
453 recentFiles.changeChar(from, to);
454 recentWorkspaces.changeChar(from, to);
458 class IDESettingsContainer : GlobalSettings
460 virtual void onLoadCompilerConfigs();
461 virtual void onLoadRecentFiles();
462 virtual void onLoadRecentProjects();
463 virtual void onLoad();
465 CompilerConfigs compilerConfigs;
466 RecentFiles recentFiles;
467 RecentWorkspaces recentProjects;
469 property bool useNewConfigurationFiles
476 settingsName = "config";
477 settingsExtension = "econ";
478 settingsDirectory = settingsDir;
483 settingsName = ideSettingsName;
484 settingsExtension = null;
485 settingsDirectory = null;
490 char moduleLocation[MAX_LOCATION];
492 FileMonitor recentFilesMonitor
494 this, fileChange = { modified = true };
496 bool OnFileNotify(FileChange action, const char * param)
499 recentFilesMonitor.StopMonitoring();
500 f = FileOpen(recentFilesMonitor.fileName, read);
505 for(c = 0; c < 10 && !(locked = f.Lock(shared, 0, 0, false)); c++) ecere::sys::Sleep(0.01);
506 recentFiles.read(this);
514 FileMonitor recentProjectsMonitor
516 this, fileChange = { modified = true };
518 bool OnFileNotify(FileChange action, const char * param)
521 recentProjectsMonitor.StopMonitoring();
522 f = FileOpen(recentProjectsMonitor.fileName, read);
527 for(c = 0; c < 10 && !(locked = f.Lock(shared, 0, 0, false)); c++) ecere::sys::Sleep(0.01);
528 recentProjects.read(this);
536 static void getConfigFilePath(char * path, Class _class, char * dir, const char * configName)
539 strcpy(path, settingsFilePath);
540 StripLastDirectory(path, path);
542 PathCatSlash(path, settingsDir);
543 if(_class == class(CompilerConfig))
545 PathCatSlash(path, "compilerConfigs");
550 PathCatSlash(path, configName);
551 strcat(path, ".econ");
554 else if(_class == class(RecentFilesData))
555 PathCatSlash(path, "recentFiles.econ");
556 else if(_class == class(RecentWorkspacesData))
557 PathCatSlash(path, "recentWorkspaces.econ");
562 FileSize settingsFileSize;
564 IDESettingsContainer()
566 char path[MAX_LOCATION];
568 LocateModule(null, moduleLocation);
569 strcpy(path, moduleLocation);
570 StripLastDirectory(moduleLocation, moduleLocation);
571 ChangeCh(moduleLocation, '\\', '/');
572 // PortableApps.com directory structure
573 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ecere-ide.exe")))
575 char configFilePath[MAX_LOCATION];
576 char defaultConfigFilePath[MAX_LOCATION];
580 strcpy(configFilePath, path);
581 PathCat(configFilePath, "Data");
582 PathCat(configFilePath, ideSettingsName);
583 ChangeExtension(configFilePath, "ini", configFilePath);
585 strcpy(defaultConfigFilePath, path);
586 PathCat(defaultConfigFilePath, "App");
587 PathCat(defaultConfigFilePath, "DefaultData");
588 PathCat(defaultConfigFilePath, ideSettingsName);
589 ChangeExtension(defaultConfigFilePath, "ini", defaultConfigFilePath);
591 if(FileExists(defaultConfigFilePath))
593 if(!FileExists(configFilePath))
595 File f = FileOpen(defaultConfigFilePath, read);
596 f.CopyTo(configFilePath);
600 PathCat(path, "Data");
601 // the forced settings location will only be
602 // used if the running ide's path matches
603 // the PortableApps.com directory structure
604 // and the default ini file is found in
605 // the DefaultData directory
606 settingsLocation = path;
612 void OnAskReloadSettings()
614 FileSize newSettingsFileSize;
616 if(OpenAndLock(&newSettingsFileSize))
618 //if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
623 GuiApplication app = ((GuiApplication)__thisModule.application);
625 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
629 MessageBox { master = w, type = ok, isModal = true,
630 creationActivation = flash,
631 text = "Global Settings Modified Externally",
632 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
633 "The new settings will not be loaded to prevent loss of your ide settings.\n"
634 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
640 SettingsIOResult Load()
643 SettingsIOResult result;
644 useNewConfigurationFiles = true;
645 result = GlobalSettings::Load();
646 data = (IDESettings)this.data;
648 if(result == fileNotFound)
651 useNewConfigurationFiles = false;
652 result = GlobalSettings::Load();
654 data = (IDESettings)this.data;
657 this.data = IDESettings { };
659 *dataOwner = this.data;
661 if(result == fileNotCompatibleWithDriver)
664 OldIDESettings oldSettings { };
666 loaded = oldSettings.Load() == success;
670 data = (IDESettings)this.data;
672 for(c : oldSettings.compilerConfigs)
673 data.compilerConfigs.Add(c.Copy());
675 for(s : oldSettings.recentFiles) data.recentFiles.Add(s);
676 for(s : oldSettings.recentProjects) data.recentProjects.Add(s);
678 data.docDir = oldSettings.docDir;
679 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
680 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
681 data.useFreeCaret = oldSettings.useFreeCaret;
682 data.showLineNumbers = oldSettings.showLineNumbers;
683 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
684 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
685 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
686 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
693 if(result == fileNotFound || !data)
695 data = (IDESettings)this.data;
696 data.useFreeCaret = false; //true;
697 data.showLineNumbers = true;
698 data.caretFollowsScrolling = false; //true;
703 FileGetSize(settingsFilePath, &settingsFileSize);
704 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
705 data.ManagePortablePaths(moduleLocation, true);
706 data.ForcePathSeparatorStyle(true);
708 if(!data.colorSchemes || !data.colorSchemes.count)
710 if(!data.colorSchemes) data.colorSchemes = { };
712 data.colorSchemes.Add(darkColorScheme); incref darkColorScheme;
713 data.colorSchemes.Add(lightColorScheme); incref lightColorScheme;
714 data.colorSchemes.Add(greenColorScheme); incref greenColorScheme;
715 data.colorSchemes.Add(grayColorScheme); incref grayColorScheme;
718 if(data.activeColorScheme)
720 for(cs : data.colorSchemes; cs.name && !strcmp(cs.name, data.activeColorScheme))
728 colorScheme = data.colorSchemes[0];
729 data.activeColorScheme = colorScheme.name;
732 // Import from previous ecereIDE settings
735 // Save first so that settingsFilePath get set up
738 data.compilerConfigs.ensureDefaults();
739 data.compilerConfigs.write(this, null);
740 data.compilerConfigs.Free();
742 data.recentFiles.write(this);
743 data.recentFiles.Free();
745 data.recentProjects.write(this);
746 data.recentProjects.Free();
751 SettingsIOResult Save()
753 SettingsIOResult result;
755 useNewConfigurationFiles = true;
756 data = (IDESettings)this.data;
757 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
758 data.ManagePortablePaths(moduleLocation, false);
759 data.ForcePathSeparatorStyle(true);
761 settingsFilePath = null;
762 result = GlobalSettings::Save();
763 if(result != success)
764 PrintLn("Error saving IDE settings");
767 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
768 data.ManagePortablePaths(moduleLocation, true);
771 FileGetSize(settingsFilePath, &settingsFileSize);
777 static Map<String, String> getCompilerConfigFilePathsByName(const char * path)
779 Map<String, String> map { };
780 FileListing fl { path, extensions = "econ" };
783 if(fl.stats.attribs.isFile)
785 char name[MAX_FILENAME];
786 char * path = CopyString(fl.path);
788 GetLastDirectory(path, name);
789 StripExtension(name);
796 static Map<String, CompilerConfig> getCompilerConfigsByName(const char * path)
798 Map<String, CompilerConfig> 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);
810 CompilerConfig ccfg = CompilerConfig::read(path);
820 static SettingsIOResult writeConfigFile(const char * path, Class dataType, void * data)
822 SettingsIOResult result = error;
823 SafeFile sf = SafeFile::open(path, write);
826 WriteECONObject(sf.file, dataType, data, 0);
832 PrintLn($"error: could not safely open file for writing configuration: ", path);
836 static SettingsIOResult readConfigFile(const char * path, Class dataType, void ** data)
838 SettingsIOResult result = error;
840 if(!FileExists(path))
841 result = fileNotFound;
842 else if((sf = SafeFile::open(path, read)))
844 JSONResult jsonResult;
846 ECONParser parser { f = sf.file };
847 sf.file.Seek(0, start);
848 jsonResult = parser.GetObject(dataType, data);
849 if(jsonResult != success)
853 if(jsonResult == success)
857 result = fileNotCompatibleWithDriver;
858 PrintLn($"error: could not parse configuration file: ", path);
869 char path[MAX_LOCATION];
870 char tmp[MAX_LOCATION];
872 SafeFile ::open(const char * path, FileOpenMode mode)
874 SafeFile result = null;
875 if(mode == write || mode == read)
877 SafeFile sf { mode = mode };
880 FileLock lockType = mode == write ? exclusive : shared;
882 strcpy(sf.path, path);
883 strcpy(sf.tmp, path);
884 strcat(sf.tmp, ".tmp");
885 if(mode == write && FileExists(sf.tmp).isFile)
890 sf.file = FileOpen(sf.tmp, readWrite);
893 sf.file = FileOpen(sf.tmp, writeRead);
897 sf.file = FileOpen(sf.tmp, readWrite);
902 sf.file = FileOpen(path, mode);
905 for(c = 0; c < 10 && !(locked = sf.file.Lock(lockType, 0, 0, false)); c++) Sleep(0.01);
909 sf.file.Seek(0, start);
912 else if(mode == write)
913 PrintLn($"warning: SafeFile::open: unable to obtain exclusive lock on temporary file for writing: ", sf.tmp);
915 PrintLn($"warning: SafeFile::open: unable to obtain shared lock on file for reading: ", path);
917 else if(mode == write)
918 PrintLn($"warning: SafeFile::open: unable to open temporary file for writing: ", sf.tmp);
920 PrintLn($"warning: SafeFile::open: unable to open file for reading: ", path);
926 PrintLn($"warning: SafeFile::open: does not yet support FileOpenMode::", mode);
932 if(file && mode == write)
935 File f = FileOpen(path, readWrite);
938 f = FileOpen(path, writeRead);
942 f = FileOpen(path, readWrite);
948 for(c = 0; c < 10 && !(locked = f.Lock(exclusive, 0,0, false)); c++) Sleep(0.01);
952 f.Unlock(0,0, false);
954 file.Unlock(0,0, false);
957 for(c = 0; c < 10; c++)
959 if(MoveFileEx(tmp, path, { true, true }))
968 PrintLn($"warning: SafeFile::sync: failed to lock file for ", mode);
979 file.Unlock(0,0, false);
985 class RecentFilesData
988 RecentFiles recentFiles;
992 if(recentFiles) recentFiles.Free();
997 class RecentWorkspacesData
1000 RecentWorkspaces recentWorkspaces;
1002 ~RecentWorkspacesData()
1004 if(recentWorkspaces) recentWorkspaces.Free();
1005 delete recentWorkspaces;
1009 class IDESettings : GlobalSettingsData
1012 property CompilerConfigs compilerConfigs
1014 set { /*if(settingsContainer.oldConfig)*/ { if(compilerConfigs) compilerConfigs.Free(); delete compilerConfigs; if(value) compilerConfigs = value; } }
1015 get { return compilerConfigs; }
1016 isset { return false; }
1018 property RecentFiles recentFiles
1020 set { if(recentFiles) recentFiles.Free(); delete recentFiles; if(value) recentFiles = value; }
1021 get { return recentFiles; }
1022 isset { return false; }
1024 property RecentWorkspaces recentProjects
1026 set { if(recentProjects) recentProjects.Free(); delete recentProjects; if(value) recentProjects = value; }
1027 get { return recentProjects; }
1028 isset { return false; }
1030 property const char * docDir
1032 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
1033 get { return docDir ? docDir : ""; }
1034 isset { return docDir && docDir[0]; }
1036 property const char * ideFileDialogLocation
1038 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
1039 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
1040 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
1042 property const char * ideProjectFileDialogLocation
1044 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
1045 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
1046 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
1049 bool showLineNumbers;
1050 bool caretFollowsScrolling;
1051 char * displayDriver;
1053 // TODO: Classify settings
1054 //EditorSettings editor { };
1056 property const char * projectDefaultTargetDir
1058 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
1059 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
1060 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
1062 property const char * projectDefaultIntermediateObjDir
1064 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
1065 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
1066 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
1069 property const char * compilerConfigsDir
1071 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
1072 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
1073 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
1076 property const char * defaultCompiler
1078 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
1079 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
1080 isset { return defaultCompiler && defaultCompiler[0]; }
1083 property const String language
1088 language = CopyString(value);
1090 get { return language; }
1091 isset { return language != null; }
1094 property const String codeEditorFont
1098 delete codeEditorFont;
1099 codeEditorFont = CopyString(value);
1101 get { return codeEditorFont; }
1104 float codeEditorFontSize;
1105 bool showFixedPitchFontsOnly;
1107 property Array<IDEColorScheme> colorSchemes
1111 if(colorSchemes && colorSchemes._refCount < 2)
1112 colorSchemes.Free();
1113 delete colorSchemes;
1114 colorSchemes = value;
1116 incref colorSchemes;
1118 get { return colorSchemes; }
1121 property const String activeColorScheme
1125 delete activeColorScheme;
1126 activeColorScheme = CopyString(value);
1128 get { return activeColorScheme; }
1132 CompilerConfigs compilerConfigs { };
1134 char * ideFileDialogLocation;
1135 char * ideProjectFileDialogLocation;
1136 char * projectDefaultTargetDir;
1137 char * projectDefaultIntermediateObjDir;
1138 char * compilerConfigsDir;
1139 char * defaultCompiler;
1141 RecentFiles recentFiles { };
1142 RecentWorkspaces recentProjects { };
1144 Array<IDEColorScheme> colorSchemes;
1146 String codeEditorFont;
1148 String activeColorScheme;
1150 showFixedPitchFontsOnly = true;
1151 codeEditorFontSize = 12;
1152 codeEditorFont = CopyString("Courier New");
1156 compilerConfigs.Free();
1157 delete compilerConfigs;
1158 if(recentProjects) { recentFiles.Free(); delete recentFiles; }
1159 if(recentProjects) { recentProjects.Free(); delete recentProjects; }
1162 delete projectDefaultTargetDir;
1163 delete projectDefaultIntermediateObjDir;
1164 delete compilerConfigsDir;
1165 delete defaultCompiler;
1168 delete ideFileDialogLocation;
1169 delete ideProjectFileDialogLocation;
1170 delete displayDriver;
1172 delete codeEditorFont;
1174 colorSchemes.Free();
1175 delete activeColorScheme;
1178 void ForcePathSeparatorStyle(bool unixStyle)
1182 from = '\\', to = '/';
1184 from = '/', to = '\\';
1185 if(compilerConfigs && compilerConfigs.count)
1188 for(config : compilerConfigs)
1190 if(config.includeDirs && config.includeDirs.count)
1192 for(i = 0; i < config.includeDirs.count; i++)
1194 if(config.includeDirs[i] && config.includeDirs[i][0])
1195 ChangeCh(config.includeDirs[i], from, to);
1198 if(config.libraryDirs && config.libraryDirs.count)
1200 for(i = 0; i < config.libraryDirs.count; i++)
1202 if(config.libraryDirs[i] && config.libraryDirs[i][0])
1203 ChangeCh(config.libraryDirs[i], from, to);
1206 if(config.executableDirs && config.executableDirs.count)
1208 for(i = 0; i < config.executableDirs.count; i++)
1210 if(config.executableDirs[i] && config.executableDirs[i][0])
1211 ChangeCh(config.executableDirs[i], from, to);
1216 recentFiles.changeChar(from, to);
1217 recentProjects.changeChar(from, to);
1218 if(docDir && docDir[0])
1219 ChangeCh(docDir, from, to);
1220 if(ideFileDialogLocation && ideFileDialogLocation[0])
1221 ChangeCh(ideFileDialogLocation, from, to);
1222 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
1223 ChangeCh(ideProjectFileDialogLocation, from, to);
1225 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
1226 ChangeCh(projectDefaultTargetDir, from, to);
1227 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
1228 ChangeCh(projectDefaultIntermediateObjDir, from, to);
1230 if(compilerConfigsDir && compilerConfigsDir[0])
1231 ChangeCh(compilerConfigsDir, from, to);
1234 void ManagePortablePaths(char * location, bool makeAbsolute)
1237 if(compilerConfigs && compilerConfigs.count)
1239 for(config : compilerConfigs)
1242 for(t = 0; t < DirTypes::enumSize; t++)
1244 Array<String> dirs = null;
1245 if(t == executables) dirs = config.executableDirs;
1246 else if(t == includes) dirs = config.includeDirs;
1247 else if(t == libraries) dirs = config.libraryDirs;
1248 if(dirs && dirs.count)
1250 for(c = 0; c < dirs.count; c++)
1252 if(dirs[c] && dirs[c][0])
1253 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
1259 if(recentFiles && recentFiles.count)
1261 for(c = 0; c < recentFiles.count; c++)
1263 if(recentFiles[c] && recentFiles[c][0])
1264 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
1267 if(recentProjects && recentProjects.count)
1269 for(c = 0; c < recentProjects.count; c++)
1271 if(recentProjects[c] && recentProjects[c][0])
1272 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
1275 if(docDir && docDir[0])
1276 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
1277 if(ideFileDialogLocation && ideFileDialogLocation[0])
1278 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
1279 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
1280 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
1282 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
1283 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
1284 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
1285 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
1287 if(compilerConfigsDir && compilerConfigsDir[0])
1288 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
1291 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
1296 char p[MAX_LOCATION];
1297 strcpy(p, location);
1298 PathCatSlash(p, path);
1300 output = CopyString(p);
1304 PathRelationship rel = eString_PathRelated(path, location, null);
1305 if(rel == subPath || rel == identical)
1307 char p[MAX_LOCATION];
1308 MakePathRelative(path, location, p);
1309 if(!*p) strcpy(p, "./");
1310 else ChangeCh(p, '\\', '/');
1312 output = CopyString(p);
1321 class RecentFiles : RecentPaths
1323 void read(IDESettingsContainer settingsContainer)
1325 char path[MAX_LOCATION];
1326 RecentFilesData d = null;
1327 Class _class = class(RecentFilesData);
1328 settingsContainer.getConfigFilePath(path, _class, null, null);
1329 readConfigFile(path, _class, &d);
1330 if(d && d.recentFiles && d.recentFiles.count)
1333 Copy((void *)d.recentFiles);
1334 d.recentFiles.RemoveAll();
1335 settingsContainer.recentFiles = this; // Merge IDEConfigHolder / IDESettingsContainer?
1338 settingsContainer.recentFilesMonitor.fileName = path;
1339 settingsContainer.recentFilesMonitor.StartMonitoring();
1340 settingsContainer.onLoadRecentFiles();
1343 void write(IDESettingsContainer settingsContainer)
1345 char path[MAX_LOCATION];
1346 RecentFilesData d { };
1347 Class _class = class(RecentFilesData);
1348 settingsContainer.getConfigFilePath(path, _class, null, null);
1349 d.recentFiles = this;
1350 writeConfigFile(path, _class, d);
1351 d.recentFiles = null;
1356 class RecentWorkspaces : RecentPaths
1358 void read(IDESettingsContainer settingsContainer)
1360 char path[MAX_LOCATION];
1361 RecentWorkspacesData d = null;
1362 Class _class = class(RecentWorkspacesData);
1363 settingsContainer.getConfigFilePath(path, _class, null, null);
1364 readConfigFile(path, _class, &d);
1365 if(d && d.recentWorkspaces && d.recentWorkspaces.count)
1368 Copy((void *)d.recentWorkspaces);
1369 d.recentWorkspaces.RemoveAll();
1370 settingsContainer.recentProjects = this; // Merge IDEConfigHolder / IDESettingsContainer?
1373 settingsContainer.recentProjectsMonitor.fileName = path;
1374 settingsContainer.recentProjectsMonitor.StartMonitoring();
1375 settingsContainer.onLoadRecentProjects();
1378 void write(IDESettingsContainer settingsContainer)
1380 char path[MAX_LOCATION];
1381 RecentWorkspacesData d { };
1382 Class _class = class(RecentWorkspacesData);
1383 settingsContainer.getConfigFilePath(path, _class, null, null);
1384 d.recentWorkspaces = this;
1385 writeConfigFile(path, _class, d);
1386 d.recentWorkspaces = null;
1391 class RecentPaths : Array<String>
1393 IteratorPointer Add(T value)
1396 char * filePath = (char *)value;
1397 ChangeCh(filePath, '\\', '/');
1398 for(c = 0; c < count; c++)
1400 if(this[c] && !fstrcmp(this[c], filePath))
1402 Delete((void *)&this[c]);
1406 return Array::Add((T)filePath);
1409 IteratorPointer addRecent(const String value)
1412 char * filePath = CopyString((char *)value);
1414 ChangeCh(filePath, '\\', '/');
1415 for(c = 0; c < count; c++)
1417 if(this[c] && !fstrcmp(this[c], filePath))
1419 Delete((void *)&this[c]);
1423 while(count >= MaxRecent)
1425 ip = Insert(null, filePath);
1429 void changeChar(char from, char to)
1434 for(c = 0; c < count; c++)
1436 if(this[c] && this[c][0])
1437 ChangeCh(this[c], from, to);
1443 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
1444 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
1445 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
1446 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
1447 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
1448 // TODO: i18n with Array
1449 static Array<const String> compilerTypeLongNames
1451 $"GNU Compiler Collection (GCC) / GNU Make",
1452 $"Tiny C Compiler / GNU Make",
1453 $"Portable C Compiler / GNU Make",
1454 $"Microsoft Visual Studio 2005 (8.0) Compiler",
1455 $"Microsoft Visual Studio 2008 (9.0) Compiler",
1456 $"Microsoft Visual Studio 2010 (10.0) Compiler"
1458 const CompilerType firstCompilerType = gcc;
1459 const CompilerType lastCompilerType = vs10;
1460 public enum CompilerType
1462 gcc, tcc, pcc, vs8, vs9, vs10;
1466 get { return this == vs8 || this == vs9 || this == vs10; }
1469 property const char *
1471 get { return OnGetString(null, null, null); }
1477 for(c = firstCompilerType; c <= lastCompilerType; c++)
1478 if(!strcmpi(value, compilerTypeNames[c]))
1485 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
1486 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
1487 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
1488 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
1489 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
1491 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1493 if(this >= firstCompilerType && this <= lastCompilerType)
1496 strcpy(tempString, compilerTypeNames[this]);
1497 if(fieldData == null)
1498 return compilerTypeNames[this];
1499 else if(fieldData == (void*)1)
1500 return compilerTypeLongNames[this];
1501 else if(fieldData == (void*)2)
1502 return compilerTypeVersionString[this];
1503 else if(fieldData == (void*)3)
1504 return compilerTypeYearString[this];
1505 else if(fieldData == (void*)4)
1506 return compilerTypeProjectFileExtension[this];
1507 else if(fieldData == (void*)5)
1508 return compilerTypeSolutionFileVersionString[this];
1514 class CompilerConfig
1520 property const char * name
1522 set { delete name; if(value) name = CopyString(value); }
1523 get { return name; }
1527 Platform targetPlatform;
1529 property const char * makeCommand
1531 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
1532 get { return makeCommand; }
1533 isset { return makeCommand && makeCommand[0]; }
1535 property const char * ecpCommand
1537 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
1538 get { return ecpCommand; }
1539 isset { return ecpCommand && ecpCommand[0]; }
1541 property const char * eccCommand
1543 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
1544 get { return eccCommand; }
1545 isset { return eccCommand && eccCommand[0]; }
1547 property const char * ecsCommand
1549 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
1550 get { return ecsCommand; }
1551 isset { return ecsCommand && ecsCommand[0]; }
1553 property const char * earCommand
1555 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
1556 get { return earCommand; }
1557 isset { return earCommand && earCommand[0]; }
1559 property const char * cppCommand
1561 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
1562 get { return cppCommand; }
1563 isset { return cppCommand && cppCommand[0]; }
1565 property const char * ccCommand
1567 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
1568 get { return ccCommand; }
1569 isset { return ccCommand && ccCommand[0]; }
1571 property const char * cxxCommand
1573 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
1574 get { return cxxCommand; }
1575 isset { return cxxCommand && cxxCommand[0]; }
1577 property const char * arCommand
1579 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
1580 get { return arCommand; }
1581 isset { return arCommand && arCommand[0]; }
1583 property const char * ldCommand
1585 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
1586 get { return ldCommand; }
1587 isset { return ldCommand && ldCommand[0]; }
1589 property const char * objectFileExt
1591 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
1592 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
1593 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
1595 property const char * staticLibFileExt
1597 set { delete staticLibFileExt; if(value && value[0]) staticLibFileExt = CopyString(value); }
1598 get { return staticLibFileExt; }
1599 isset { return staticLibFileExt && staticLibFileExt[0]; }
1601 property const char * sharedLibFileExt
1603 set { delete sharedLibFileExt; if(value && value[0]) sharedLibFileExt = CopyString(value); }
1604 get { return sharedLibFileExt; }
1605 isset { return sharedLibFileExt && sharedLibFileExt[0]; }
1607 property const char * executableFileExt
1609 set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
1610 get { return executableFileExt; }
1611 isset { return executableFileExt && executableFileExt[0]; }
1613 property const char * executableLauncher
1615 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1616 get { return executableLauncher; }
1617 isset { return executableLauncher && executableLauncher[0]; }
1619 // TODO: implement CompilerConfig::windresCommand
1623 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
1625 property const char * distccHosts
1627 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
1628 get { return distccHosts; }
1629 isset { return distccHosts && distccHosts[0]; }
1631 property const char * gnuToolchainPrefix
1633 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1634 get { return gnuToolchainPrefix; }
1635 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
1637 property const char * sysroot
1639 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
1640 get { return sysroot; }
1641 isset { return sysroot && sysroot[0]; }
1643 bool resourcesDotEar;
1645 property Array<String> includeDirs
1653 includeDirs = value;
1656 get { return includeDirs; }
1657 isset { return includeDirs.count != 0; }
1659 property Array<String> libraryDirs
1667 libraryDirs = value;
1670 get { return libraryDirs; }
1671 isset { return libraryDirs.count != 0; }
1673 property Array<String> executableDirs
1677 executableDirs.Free();
1680 delete executableDirs;
1681 executableDirs = value;
1684 get { return executableDirs; }
1685 isset { return executableDirs.count != 0; }
1687 property Array<NamedString> environmentVars
1691 environmentVars.Free();
1694 delete environmentVars;
1695 environmentVars = value;
1698 get { return environmentVars; }
1699 isset { return environmentVars.count != 0; }
1701 property Array<String> prepDirectives
1705 prepDirectives.Free();
1708 delete prepDirectives;
1709 prepDirectives = value;
1712 get { return prepDirectives; }
1713 isset { return prepDirectives.count != 0; }
1715 property Array<String> excludeLibs
1723 excludeLibs = value;
1726 get { return excludeLibs; }
1727 isset { return excludeLibs.count != 0; }
1729 property Array<String> eCcompilerFlags
1733 eCcompilerFlags.Free();
1736 delete eCcompilerFlags;
1737 eCcompilerFlags = value;
1740 get { return eCcompilerFlags; }
1741 isset { return eCcompilerFlags.count != 0; }
1743 property Array<String> compilerFlags
1747 compilerFlags.Free();
1750 delete compilerFlags;
1751 compilerFlags = value;
1754 get { return compilerFlags; }
1755 isset { return compilerFlags.count != 0; }
1757 property Array<String> cxxFlags
1768 get { return cxxFlags; }
1769 isset { return cxxFlags.count != 0; }
1771 property Array<String> linkerFlags
1779 linkerFlags = value;
1782 get { return linkerFlags; }
1783 isset { return linkerFlags.count != 0; }
1785 // json backward compatibility
1786 property const char * gccPrefix
1788 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1789 get { return gnuToolchainPrefix; }
1790 isset { return false; }
1792 property const char * execPrefixCommand
1794 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1795 get { return executableLauncher; }
1796 isset { return false; }
1798 property const char * outputFileExt
1800 set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
1801 get { return executableFileExt; }
1802 isset { return false; }
1805 property bool hasDocumentOutput
1809 bool result = executableFileExt && executableFileExt[0] &&
1810 (!strcmpi(executableFileExt, "htm") || !strcmpi(executableFileExt, "html"));
1813 isset { return false; }
1816 Array<String> includeDirs { };
1817 Array<String> libraryDirs { };
1818 Array<String> executableDirs { };
1819 // TODO: Can JSON parse and serialize maps?
1820 //EnvironmentVariables { };
1821 Array<NamedString> environmentVars { };
1822 Array<String> prepDirectives { };
1823 Array<String> excludeLibs { };
1824 Array<String> eCcompilerFlags { };
1825 Array<String> compilerFlags { };
1826 Array<String> cxxFlags { };
1827 Array<String> linkerFlags { };
1839 char * objectFileExt;
1840 char * staticLibFileExt;
1841 char * sharedLibFileExt;
1842 char * executableFileExt;
1843 char * executableLauncher;
1845 char * gnuToolchainPrefix;
1849 struct { Array<String> includes, libraries, executables; };
1850 Array<String> dirs[DirTypes];
1865 delete objectFileExt;
1866 delete staticLibFileExt;
1867 delete sharedLibFileExt;
1868 delete executableFileExt;
1870 delete executableLauncher;
1872 delete gnuToolchainPrefix;
1874 if(environmentVars) environmentVars.Free();
1875 if(includeDirs) { includeDirs.Free(); }
1876 if(libraryDirs) { libraryDirs.Free(); }
1877 if(executableDirs) { executableDirs.Free(); }
1878 if(prepDirectives) { prepDirectives.Free(); }
1879 if(excludeLibs) { excludeLibs.Free(); }
1880 if(compilerFlags) { compilerFlags.Free(); }
1881 if(cxxFlags) { cxxFlags.Free(); }
1882 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1883 if(linkerFlags) { linkerFlags.Free(); }
1886 int OnCompare(CompilerConfig b)
1890 !(result = type.OnCompare(b.type)) &&
1891 !(result = targetPlatform.OnCompare(b.targetPlatform)) &&
1892 !(result = numJobs.OnCompare(b.numJobs)) &&
1893 !(result = ccacheEnabled.OnCompare(b.ccacheEnabled)) &&
1894 !(result = distccEnabled.OnCompare(b.distccEnabled)) &&
1895 !(result = resourcesDotEar.OnCompare(b.resourcesDotEar)) &&
1896 !(result = noStripTarget.OnCompare(b.noStripTarget))
1900 !(result = name.OnCompare(b.name)) &&
1901 !(result = ecpCommand.OnCompare(b.ecpCommand)) &&
1902 !(result = eccCommand.OnCompare(b.eccCommand)) &&
1903 !(result = ecsCommand.OnCompare(b.ecsCommand)) &&
1904 !(result = earCommand.OnCompare(b.earCommand)) &&
1905 !(result = cppCommand.OnCompare(b.cppCommand)) &&
1906 !(result = ccCommand.OnCompare(b.ccCommand)) &&
1907 !(result = cxxCommand.OnCompare(b.cxxCommand)) &&
1908 !(result = ldCommand.OnCompare(b.ldCommand)) &&
1909 !(result = arCommand.OnCompare(b.arCommand)) &&
1910 !(result = objectFileExt.OnCompare(b.objectFileExt)) &&
1911 !(result = outputFileExt.OnCompare(b.outputFileExt)) &&
1912 !(result = makeCommand.OnCompare(b.makeCommand)) &&
1913 !(result = executableLauncher.OnCompare(b.executableLauncher)) &&
1914 !(result = distccHosts.OnCompare(b.distccHosts)) &&
1915 !(result = gnuToolchainPrefix.OnCompare(b.gnuToolchainPrefix)) &&
1916 !(result = sysroot.OnCompare(b.sysroot)));
1919 !(result = includeDirs.OnCompare(b.includeDirs)) &&
1920 !(result = libraryDirs.OnCompare(b.libraryDirs)) &&
1921 !(result = executableDirs.OnCompare(b.executableDirs)) &&
1922 !(result = environmentVars.OnCompare(b.environmentVars)) &&
1923 !(result = prepDirectives.OnCompare(b.prepDirectives)) &&
1924 !(result = excludeLibs.OnCompare(b.excludeLibs)) &&
1925 !(result = cxxFlags.OnCompare(b.cxxFlags)) &&
1926 !(result = eCcompilerFlags.OnCompare(b.eCcompilerFlags)) &&
1927 !(result = compilerFlags.OnCompare(b.compilerFlags)) &&
1928 !(result = linkerFlags.OnCompare(b.linkerFlags)));
1933 CompilerConfig Copy()
1966 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1967 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1968 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1969 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1970 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1971 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1972 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1973 for(s : cxxFlags) copy.cxxFlags.Add(CopyString(s));
1974 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1975 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1981 CompilerConfig ::read(const char * path)
1983 CompilerConfig d = null;
1984 readConfigFile(path, class(CompilerConfig), &d);
1988 void write(IDESettingsContainer settingsContainer)
1990 char dir[MAX_LOCATION];
1991 char path[MAX_LOCATION];
1992 const char * settingsFilePath = settingsContainer.settingsFilePath;
1993 settingsContainer.getConfigFilePath(path, _class, dir, name);
1994 if(FileExists(settingsFilePath) && !FileExists(dir))
1997 if(!FileExists(dir))
1998 PrintLn($"Error creating compiler configs directory at ", dir, " location.");
2000 writeConfigFile(path, _class, this);
2004 class CompilerConfigs : List<CompilerConfig>
2006 CompilerConfig GetCompilerConfig(const String compilerName)
2008 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
2009 CompilerConfig compilerConfig = null;
2010 for(compiler : this)
2012 if(!strcmp(compiler.name, name))
2014 compilerConfig = compiler;
2018 if(!compilerConfig && count)
2019 compilerConfig = this[0];
2022 incref compilerConfig;
2023 if(compilerConfig._refCount == 1)
2024 incref compilerConfig;
2026 return compilerConfig;
2029 void ensureDefaults()
2031 // Ensure we have a default compiler
2032 CompilerConfig defaultCompiler = GetCompilerConfig(defaultCompilerName);
2033 if(!defaultCompiler)
2035 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
2036 Insert(null, defaultCompiler);
2037 defaultCompiler = null;
2039 delete defaultCompiler;
2043 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
2044 ccfg.ecpCommand = ecpDefaultCommand;
2045 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
2046 ccfg.eccCommand = eccDefaultCommand;
2047 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
2048 ccfg.ecsCommand = ecsDefaultCommand;
2049 if(!ccfg.earCommand || !ccfg.earCommand[0])
2050 ccfg.earCommand = earDefaultCommand;
2051 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
2052 ccfg.cppCommand = cppDefaultCommand;
2053 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
2054 ccfg.ccCommand = ccDefaultCommand;
2055 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
2056 ccfg.cxxCommand = cxxDefaultCommand;
2057 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
2058 ccfg.ldCommand = ldDefaultCommand;*/
2059 if(!ccfg.arCommand || !ccfg.arCommand[0])
2060 ccfg.arCommand = arDefaultCommand;
2061 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
2062 ccfg.objectFileExt = objectDefaultFileExt;
2063 /*if(!ccfg.staticLibFileExt || !ccfg.staticLibFileExt[0])
2064 ccfg.staticLibFileExt = staticLibDefaultFileExt;*/
2065 /*if(!ccfg.sharedLibFileExt || !ccfg.sharedLibFileExt[0])
2066 ccfg.sharedLibFileExt = sharedLibDefaultFileExt;*/
2067 /*if(!ccfg.executableFileExt || !ccfg.executableFileExt[0])
2068 ccfg.executableFileExt = outputDefaultFileExt;*/
2069 if(!ccfg._refCount) incref ccfg;
2073 AVLTree<String> getWriteRequiredList(CompilerConfigs oldConfigs)
2075 AVLTree<String> list { };
2079 for(occfg : oldConfigs; !strcmp(ccfg.name, occfg.name))
2082 if(ccfg.OnCompare(occfg))
2083 list.Add(CopyString(ccfg.name));
2087 list.Add(CopyString(ccfg.name));
2092 bool read(IDESettingsContainer settingsContainer)
2094 if(settingsContainer.settingsFilePath)
2096 char dir[MAX_LOCATION];
2097 char path[MAX_LOCATION];
2098 Class _class = class(CompilerConfig);
2099 settingsContainer.getConfigFilePath(path, _class, dir, null);
2102 AVLTree<const String> addedConfigs { };
2103 Map<String, CompilerConfig> compilerConfigsByName = getCompilerConfigsByName(dir);
2104 MapIterator<const String, CompilerConfig> it { map = compilerConfigsByName };
2106 settingsContainer.compilerConfigs = this; // Merge IDEConfigHolder / IDESettingsContainer?
2107 if(it.Index("Default", false))
2109 CompilerConfig ccfg = it.data;
2111 addedConfigs.Add(ccfg.name);
2113 for(ccfg : compilerConfigsByName)
2115 if(!addedConfigs.Find(ccfg.name))
2118 addedConfigs.Add(ccfg.name);
2121 delete addedConfigs;
2123 compilerConfigsByName.Free();
2124 delete compilerConfigsByName;
2125 settingsContainer.onLoadCompilerConfigs();
2132 void write(IDESettingsContainer settingsContainer, AVLTree<String> cfgsToWrite)
2134 char dir[MAX_LOCATION];
2135 char path[MAX_LOCATION];
2136 Map<String, String> paths;
2137 settingsContainer.getConfigFilePath(path, class(CompilerConfig), dir, null);
2138 paths = getCompilerConfigFilePathsByName(dir);
2140 MapIterator<String, String> it { map = paths };
2143 CompilerConfig ccfg = c;
2144 if(!cfgsToWrite || cfgsToWrite.Find(ccfg.name))
2145 ccfg.write(settingsContainer);
2146 if(it.Index(ccfg.name, false))
2155 const char * path = p;
2163 #if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
2164 struct LanguageOption
2167 const String bitmap;
2171 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
2176 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
2178 Bitmap icon = res ? res.bitmap : null;
2181 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
2182 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
2186 Array<LanguageOption> languages
2188 { "English", ":countryCode/gb.png", "" },
2189 { "汉语", ":countryCode/cn.png", "zh_CN" },
2190 { "Español", ":countryCode/es.png", "es" },
2191 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
2192 { "Русский (43%)", ":countryCode/ru.png", "ru" },
2193 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
2194 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
2195 { "मराठी (10%)", ":countryCode/in.png", "mr" },
2196 { "Hebrew (8%)", ":countryCode/il.png", "he" },
2197 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
2200 const String GetLanguageString()
2202 char * dot, * colon;
2203 static char lang[256];
2204 const String language = getenv("ECERE_LANGUAGE");
2205 if(!language) language = getenv("LANGUAGE");
2206 if(!language) language = getenv("LC_ALL");
2207 if(!language) language = getenv("LC_MESSAGES");
2208 if(!language) language = getenv("LANG");
2209 if(!language) language = "";
2210 if(language && (colon = strchr(language, ':')))
2212 if(lang != language)
2213 strncpy(lang, language, sizeof(lang));
2214 lang[sizeof(lang)-1] = 0;
2215 lang[colon - language] = 0;
2218 if(language && (dot = strchr(language, '.')))
2220 if(lang != language)
2221 strncpy(lang, language, sizeof(lang));
2222 lang[sizeof(lang)-1] = 0;
2223 lang[dot - language] = 0;
2229 void setEcereLanguageInWinRegEnvironment(const char * languageCode)
2233 uint16 wLanguage[256];
2237 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
2240 UTF8toUTF16Buffer(languageCode, wLanguage, sizeof(wLanguage) / sizeof(uint16));
2241 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
2247 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
2249 bool restart = true;
2250 String command = null;
2251 int arg0Len = (int)strlen(app.argv[0]);
2263 for(w = ide.firstChild; w; w = w.next)
2265 if(w.isActiveClient && w.isDocument)
2267 if(!w.CloseConfirmation(true))
2276 if(!projectView.CloseConfirmation(true))
2278 if(projectView.fileName)
2280 const char * name = projectView.fileName;
2283 for(j = 0; (ch = name[j]); j++)
2284 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2288 command = new char[len + 1];
2290 strcpy(command, app.argv[0]);
2292 if(projectView.fileName)
2294 strcat(command, " ");
2296 ReplaceSpaces(command + len, projectView.fileName);
2301 for(w = ide.firstChild; w; w = w.next)
2302 if(w.isActiveClient && w.isDocument)
2303 w.modifiedDocument = false;
2304 projectView.modifiedDocument = false;
2309 for(w = ide.firstChild; w; w = w.next)
2311 if(w.isActiveClient && w.isDocument)
2313 if(!w.CloseConfirmation(true))
2320 const char * name = w.fileName;
2322 for(j = 0; (ch = name[j]); j++)
2323 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2330 command = new char[len + 1];
2331 strcpy(command, app.argv[0]);
2334 for(w = ide.firstChild; w; w = w.next)
2336 if(w.isActiveClient && w.isDocument)
2338 const char * name = w.fileName;
2341 strcat(command, " ");
2343 ReplaceSpaces(command + len, name);
2344 len = (int)strlen(command);
2351 for(w = ide.firstChild; w; w = w.next)
2352 if(w.isActiveClient && w.isDocument)
2353 w.modifiedDocument = false;
2358 settings.language = code;
2359 settingsContainer.Save();
2361 setEcereLanguageInWinRegEnvironment(code);
2363 if(eClass_IsDerived(app._class, class(GuiApplication)))
2365 GuiApplication guiApp = (GuiApplication)app;
2366 guiApp.desktop.Destroy(0);
2373 for(i = 1; i < app.argc; i++)
2375 const char * arg = app.argv[i];
2377 for(j = 0; (ch = arg[j]); j++)
2378 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
2381 command = new char[len + 1];
2382 strcpy(command, app.argv[0]);
2384 for(i = 1; i < app.argc; i++)
2386 strcat(command, " ");
2388 ReplaceSpaces(command + len, app.argv[i]);
2389 len = (int)strlen(command);
2395 SetEnvironment("ECERE_LANGUAGE", code);
2397 ExecuteWait(command);