2 #define MessageBox _MessageBox
3 #define WIN32_LEAN_AND_MEAN
9 public import static "ecere"
16 import "OldIDESettings"
20 enum DirTypes { includes, libraries, executables };
22 define defaultCompilerName = "Default";
24 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
26 char * settingsDirectoryNames[DirTypes] =
33 // This function cannot accept same pointer for source and output
34 // todo: rename ReplaceSpaces to EscapeSpaceAndSpecialChars or something
35 void ReplaceSpaces(char * output, char * source)
40 for(c = 0, dc = 0; (ch = source[c]); c++, dc++)
42 if(ch == ' ') output[dc++] = '\\';
43 if(ch == '\"') output[dc++] = '\\';
44 if(ch == '&') output[dc++] = '\\';
47 if(ch == '(' || ch == ')') output[dc++] = '\\';
58 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
60 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
61 PathRelationship eString_PathRelated(char * path, char * to, char * pathDiff)
63 PathRelationship result;
64 if(pathDiff) *pathDiff = '\0';
65 if(path && *path && to && *to)
67 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
68 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
70 strcpy(pathRest, path);
71 for(; toRest[0] && pathRest[0];)
73 SplitDirectory(toRest, toPart, toRest);
74 SplitDirectory(pathRest, pathPart, pathRest);
75 if(!fstrcmp(pathPart, toPart)) result = siblings;
78 if(result == siblings)
80 if(!*toRest && !*pathRest) result = identical;
81 else if(!*pathRest) result = parentPath;
82 else result = subPath;
83 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
85 else result = unrelated;
91 if(!*path && !*to) result = bothEmpty;
92 else if(!*path) result = pathEmpty;
93 else result = toEmpty;
95 else if(!path && !to) result = bothNull;
96 else if(!path) result = pathNull;
102 char * CopyValidateMakefilePath(char * path)
104 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 };
105 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 };
111 len = (int)strlen(path);
112 copy = CopyString(path);
118 Array<char *> parts { };
125 for(v=0; vars[v]; v++)
127 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
131 parts.Add(vars[map[v]]);
132 c += strlen(vars[v]);
146 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
147 copy = new char[++len];
149 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
160 void ValidPathBufCopy(char *output, char *input)
163 bool volumePath = false;
165 strcpy(output, input);
166 TrimLSpaces(output, output);
167 TrimRSpaces(output, output);
168 MakeSystemPath(output);
170 if(output[0] && output[1] == ':')
177 char * chars = "*|:\",<>?";
178 char ch, * s = output, * o = output;
179 while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; }
183 if(volumePath && output[0])
188 void RemoveTrailingPathSeparator(char *path)
191 len = (int)strlen(path);
192 if(len>1 && path[len-1] == DIR_SEP)
196 void BasicValidatePathBoxPath(PathBox pathBox)
198 char path[MAX_LOCATION];
199 ValidPathBufCopy(path, pathBox.path);
200 RemoveTrailingPathSeparator(path);
204 CompilerConfig MakeDefaultCompiler(char * name, bool readOnly)
206 CompilerConfig defaultCompiler
211 GetRuntimePlatform(),
222 incref defaultCompiler;
223 return defaultCompiler;
226 class IDESettingsContainer : GlobalSettings
229 settingsName = "ecereIDESettingsTest";
231 settingsName = "ecereIDE";
234 virtual void OnLoad(GlobalSettingsData data);
236 char moduleLocation[MAX_LOCATION];
239 FileSize settingsFileSize;
241 IDESettingsContainer()
243 char path[MAX_LOCATION];
245 LocateModule(null, moduleLocation);
246 strcpy(path, moduleLocation);
247 StripLastDirectory(moduleLocation, moduleLocation);
248 ChangeCh(moduleLocation, '\\', '/');
249 // PortableApps.com directory structure
250 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
252 char configFilePath[MAX_LOCATION];
253 char defaultConfigFilePath[MAX_LOCATION];
257 strcpy(configFilePath, path);
258 PathCat(configFilePath, "Data");
259 PathCat(configFilePath, "ecereIDE.ini");
261 strcpy(defaultConfigFilePath, path);
262 PathCat(defaultConfigFilePath, "App");
263 PathCat(defaultConfigFilePath, "DefaultData");
264 PathCat(defaultConfigFilePath, "ecereIDE.ini");
266 if(FileExists(defaultConfigFilePath))
268 if(!FileExists(configFilePath))
270 File f = FileOpen(defaultConfigFilePath, read);
271 f.CopyTo(configFilePath);
275 PathCat(path, "Data");
276 // the forced settings location will only be
277 // used if the running ide's path matches
278 // the PortableApps.com directory structure
279 // and the default ini file is found in
280 // the DefaultData directory
281 settingsLocation = path;
287 void OnAskReloadSettings()
289 FileSize newSettingsFileSize;
291 if(OpenAndLock(&newSettingsFileSize))
293 if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
297 GuiApplication app = ((GuiApplication)__thisModule.application);
299 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
303 MessageBox { master = w, type = ok, isModal = true,
304 text = "Global Settings Modified Externally",
305 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
306 "The new settings will not be loaded to prevent loss of your ide settings.\n"
307 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
313 SettingsIOResult Load()
315 SettingsIOResult result = GlobalSettings::Load();
316 IDESettings data = (IDESettings)this.data;
317 CompilerConfig defaultCompiler = null;
320 this.data = IDESettings { };
322 *dataOwner = this.data;
324 if(result == fileNotCompatibleWithDriver)
327 OldIDESettings oldSettings { };
329 loaded = oldSettings.Load() == success;
333 data = (IDESettings)this.data;
335 for(c : oldSettings.compilerConfigs)
336 data.compilerConfigs.Add(c.Copy());
338 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
339 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
341 data.docDir = oldSettings.docDir;
342 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
343 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
344 data.useFreeCaret = oldSettings.useFreeCaret;
345 data.showLineNumbers = oldSettings.showLineNumbers;
346 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
347 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
348 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
349 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
356 if(result == fileNotFound || !data)
358 data = (IDESettings)this.data;
359 data.useFreeCaret = false; //true;
360 data.showLineNumbers = true;
361 data.caretFollowsScrolling = false; //true;
364 // Ensure we have a default compiler
365 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
368 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
369 data.compilerConfigs.Add(defaultCompiler);
372 // We incref the compilers below, so reset refCount to 0
373 defaultCompiler._refCount = 0;
376 FileGetSize(settingsFilePath, &settingsFileSize);
377 if(data.compilerConfigs)
379 for(c : data.compilerConfigs)
381 CompilerConfig compiler = c;
382 char * cxxCommand = compiler.cxxCommand;
383 if(!cxxCommand || !cxxCommand[0])
384 compiler.cxxCommand = cxxDefaultCommand;
388 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
389 data.ManagePortablePaths(moduleLocation, true);
390 data.ForcePathSeparatorStyle(true);
395 SettingsIOResult Save()
397 SettingsIOResult result;
399 IDESettings data = (IDESettings)this.data;
400 Platform runtimePlatform = GetRuntimePlatform();
401 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
402 data.ManagePortablePaths(moduleLocation, false);
403 data.ForcePathSeparatorStyle(true);
404 result = GlobalSettings::Save();
405 if(result != success)
406 PrintLn("Error saving IDE settings");
407 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
408 data.ManagePortablePaths(moduleLocation, true);
410 FileGetSize(settingsFilePath, &settingsFileSize);
415 class IDESettings : GlobalSettingsData
418 List<CompilerConfig> compilerConfigs { };
419 Array<String> recentFiles { };
420 Array<String> recentProjects { };
421 property char * docDir
423 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
424 get { return docDir ? docDir : ""; }
425 isset { return docDir && docDir[0]; }
427 property char * ideFileDialogLocation
429 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
430 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
431 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
433 property char * ideProjectFileDialogLocation
435 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
436 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
437 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
440 bool showLineNumbers;
441 bool caretFollowsScrolling;
442 char * displayDriver;
444 // TODO: Classify settings
445 //EditorSettings editor { };
447 property char * projectDefaultTargetDir
449 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
450 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
451 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
453 property char * projectDefaultIntermediateObjDir
455 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
456 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
457 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
460 property char * compilerConfigsDir
462 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
463 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
464 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
467 property char * defaultCompiler
469 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
470 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
471 isset { return defaultCompiler && defaultCompiler[0]; }
474 property String language
479 language = CopyString(value);
481 get { return language; }
482 isset { return language != null; }
487 char * ideFileDialogLocation;
488 char * ideProjectFileDialogLocation;
489 char * projectDefaultTargetDir;
490 char * projectDefaultIntermediateObjDir;
491 char * compilerConfigsDir;
492 char * defaultCompiler;
495 CompilerConfig GetCompilerConfig(String compilerName)
497 char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
498 CompilerConfig compilerConfig = null;
499 for(compiler : compilerConfigs)
501 if(!strcmp(compiler.name, name))
503 compilerConfig = compiler;
507 if(!compilerConfig && compilerConfigs.count)
508 compilerConfig = compilerConfigs.firstIterator.data;
510 incref compilerConfig;
511 return compilerConfig;
516 compilerConfigs.Free();
517 delete compilerConfigs;
520 recentProjects.Free();
521 delete recentProjects;
524 delete projectDefaultTargetDir;
525 delete projectDefaultIntermediateObjDir;
526 delete compilerConfigsDir;
527 delete defaultCompiler;
530 delete ideFileDialogLocation;
531 delete ideProjectFileDialogLocation;
532 delete displayDriver;
535 void ForcePathSeparatorStyle(bool unixStyle)
539 from = '\\', to = '/';
541 from = '/', to = '\\';
542 if(compilerConfigs && compilerConfigs.count)
545 for(config : compilerConfigs)
547 if(config.includeDirs && config.includeDirs.count)
549 for(i = 0; i < config.includeDirs.count; i++)
551 if(config.includeDirs[i] && config.includeDirs[i][0])
552 ChangeCh(config.includeDirs[i], from, to);
555 if(config.libraryDirs && config.libraryDirs.count)
557 for(i = 0; i < config.libraryDirs.count; i++)
559 if(config.libraryDirs[i] && config.libraryDirs[i][0])
560 ChangeCh(config.libraryDirs[i], from, to);
563 if(config.executableDirs && config.executableDirs.count)
565 for(i = 0; i < config.executableDirs.count; i++)
567 if(config.executableDirs[i] && config.executableDirs[i][0])
568 ChangeCh(config.executableDirs[i], from, to);
573 if(recentFiles && recentFiles.count)
576 for(c = 0; c < recentFiles.count; c++)
578 if(recentFiles[c] && recentFiles[c][0])
579 ChangeCh(recentFiles[c], from, to);
582 if(recentProjects && recentProjects.count)
585 for(c = 0; c < recentProjects.count; c++)
587 if(recentProjects[c] && recentProjects[c][0])
588 ChangeCh(recentProjects[c], from, to);
591 if(docDir && docDir[0])
592 ChangeCh(docDir, from, to);
593 if(ideFileDialogLocation && ideFileDialogLocation[0])
594 ChangeCh(ideFileDialogLocation, from, to);
595 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
596 ChangeCh(ideProjectFileDialogLocation, from, to);
598 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
599 ChangeCh(projectDefaultTargetDir, from, to);
600 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
601 ChangeCh(projectDefaultIntermediateObjDir, from, to);
603 if(compilerConfigsDir && compilerConfigsDir[0])
604 ChangeCh(compilerConfigsDir, from, to);
607 void ManagePortablePaths(char * location, bool makeAbsolute)
610 if(compilerConfigs && compilerConfigs.count)
612 for(config : compilerConfigs)
615 for(t = 0; t < DirTypes::enumSize; t++)
617 Array<String> dirs = null;
618 if(t == executables) dirs = config.executableDirs;
619 else if(t == includes) dirs = config.includeDirs;
620 else if(t == libraries) dirs = config.libraryDirs;
621 if(dirs && dirs.count)
623 for(c = 0; c < dirs.count; c++)
625 if(dirs[c] && dirs[c][0])
626 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
632 if(recentFiles && recentFiles.count)
634 for(c = 0; c < recentFiles.count; c++)
636 if(recentFiles[c] && recentFiles[c][0])
637 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
640 if(recentProjects && recentProjects.count)
642 for(c = 0; c < recentProjects.count; c++)
644 if(recentProjects[c] && recentProjects[c][0])
645 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
648 if(docDir && docDir[0])
649 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
650 if(ideFileDialogLocation && ideFileDialogLocation[0])
651 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
652 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
653 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
655 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
656 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
657 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
658 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
660 if(compilerConfigsDir && compilerConfigsDir[0])
661 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
664 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
669 char p[MAX_LOCATION];
671 PathCatSlash(p, path);
673 output = CopyString(p);
677 PathRelationship rel = eString_PathRelated(path, location, null);
678 if(rel == subPath || rel == identical)
680 char p[MAX_LOCATION];
681 MakePathRelative(path, location, p);
682 if(!*p) strcpy(p, "./");
683 else ChangeCh(p, '\\', '/');
685 output = CopyString(p);
693 void AddRecentFile(char * fileName)
696 char * filePath = CopyString(fileName);
697 ChangeCh(filePath, '\\', '/');
698 for(c = 0; c<recentFiles.count; c++)
700 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
702 recentFiles.Delete((void *)&recentFiles[c]);
706 while(recentFiles.count >= MaxRecent)
707 recentFiles.Delete(recentFiles.GetLast());
708 recentFiles.Insert(null, filePath);
709 //UpdateRecentMenus(owner);
712 void AddRecentProject(char * projectName)
715 char * filePath = CopyString(projectName);
716 ChangeCh(filePath, '\\', '/');
717 for(c = 0; c<recentProjects.count; c++)
719 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
721 recentProjects.Delete((void *)&recentProjects[c]);
725 while(recentProjects.count >= MaxRecent)
726 recentProjects.Delete(recentProjects.GetLast());
727 recentProjects.Insert(null, filePath);
728 //UpdateRecentMenus(owner);
732 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
733 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
734 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
735 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
736 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
737 // TODO: i18n with Array
738 static Array<String> compilerTypeLongNames
740 $"GNU Compiler Collection (GCC) / GNU Make",
741 $"Tiny C Compiler / GNU Make",
742 $"Portable C Compiler / GNU Make",
743 $"Microsoft Visual Studio 2005 (8.0) Compiler",
744 $"Microsoft Visual Studio 2008 (9.0) Compiler",
745 $"Microsoft Visual Studio 2010 (10.0) Compiler"
747 const CompilerType firstCompilerType = gcc;
748 const CompilerType lastCompilerType = vs10;
749 public enum CompilerType
751 gcc, tcc, pcc, vs8, vs9, vs10;
755 get { return this == vs8 || this == vs9 || this == vs10; }
760 get { return OnGetString(null, null, null); }
766 for(c = firstCompilerType; c <= lastCompilerType; c++)
767 if(!strcmpi(value, compilerTypeNames[c]))
774 property char * longName { get { return OnGetString(null, (void*)1, null); } };
775 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
776 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
777 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
778 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
780 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
782 if(this >= firstCompilerType && this <= lastCompilerType)
785 strcpy(tempString, compilerTypeNames[this]);
786 if(fieldData == null)
787 return compilerTypeNames[this];
788 else if(fieldData == (void*)1)
789 return compilerTypeLongNames[this];
790 else if(fieldData == (void*)2)
791 return compilerTypeVersionString[this];
792 else if(fieldData == (void*)3)
793 return compilerTypeYearString[this];
794 else if(fieldData == (void*)4)
795 return compilerTypeProjectFileExtension[this];
796 else if(fieldData == (void*)5)
797 return compilerTypeSolutionFileVersionString[this];
815 name = CopyString(value);
821 Platform targetPlatform;
823 property char * makeCommand
825 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
826 get { return makeCommand; }
827 isset { return makeCommand && makeCommand[0]; }
829 property char * ecpCommand
831 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
832 get { return ecpCommand; }
833 isset { return ecpCommand && ecpCommand[0]; }
835 property char * eccCommand
837 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
838 get { return eccCommand; }
839 isset { return eccCommand && eccCommand[0]; }
841 property char * ecsCommand
843 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
844 get { return ecsCommand; }
845 isset { return ecsCommand && ecsCommand[0]; }
847 property char * earCommand
849 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
850 get { return earCommand; }
851 isset { return earCommand && earCommand[0]; }
853 property char * cppCommand
855 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
856 get { return cppCommand; }
857 isset { return cppCommand && cppCommand[0]; }
859 property char * ccCommand
861 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
862 get { return ccCommand; }
863 isset { return ccCommand && ccCommand[0]; }
865 property char * cxxCommand
867 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
868 get { return cxxCommand; }
869 isset { return cxxCommand && cxxCommand[0]; }
871 property char * execPrefixCommand // <-- old name for json ide settings file compatibility
873 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
874 get { return executableLauncher; }
875 isset { return executableLauncher && executableLauncher[0]; }
877 // TODO: implement CompilerConfig::windresCommand
881 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
883 property char * distccHosts
885 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
886 get { return distccHosts; }
887 isset { return distccHosts && distccHosts[0]; }
889 property char * gccPrefix // <-- old name for json ide settings file compatibility
891 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
892 get { return gnuToolchainPrefix; }
893 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
895 property char * sysroot
897 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
898 get { return sysroot; }
899 isset { return sysroot && sysroot[0]; }
901 property Array<String> includeDirs
912 get { return includeDirs; }
913 isset { return includeDirs.count != 0; }
915 property Array<String> libraryDirs
926 get { return libraryDirs; }
927 isset { return libraryDirs.count != 0; }
929 property Array<String> executableDirs
933 executableDirs.Free();
936 delete executableDirs;
937 executableDirs = value;
940 get { return executableDirs; }
941 isset { return executableDirs.count != 0; }
943 property Array<NamedString> environmentVars
947 environmentVars.Free();
950 delete environmentVars;
951 environmentVars = value;
954 get { return environmentVars; }
955 isset { return environmentVars.count != 0; }
957 property Array<String> prepDirectives
961 prepDirectives.Free();
964 delete prepDirectives;
965 prepDirectives = value;
968 get { return prepDirectives; }
969 isset { return prepDirectives.count != 0; }
971 property Array<String> excludeLibs
982 get { return excludeLibs; }
983 isset { return excludeLibs.count != 0; }
985 property Array<String> eCcompilerFlags
989 eCcompilerFlags.Free();
992 delete eCcompilerFlags;
993 eCcompilerFlags = value;
996 get { return eCcompilerFlags; }
997 isset { return eCcompilerFlags.count != 0; }
999 property Array<String> compilerFlags
1003 compilerFlags.Free();
1006 delete compilerFlags;
1007 compilerFlags = value;
1010 get { return compilerFlags; }
1011 isset { return compilerFlags.count != 0; }
1013 property Array<String> linkerFlags
1021 linkerFlags = value;
1024 get { return linkerFlags; }
1025 isset { return linkerFlags.count != 0; }
1028 Array<String> includeDirs { };
1029 Array<String> libraryDirs { };
1030 Array<String> executableDirs { };
1031 // TODO: Can JSON parse and serialize maps?
1032 //EnvironmentVariables { };
1033 Array<NamedString> environmentVars { };
1034 Array<String> prepDirectives { };
1035 Array<String> excludeLibs { };
1036 Array<String> eCcompilerFlags { };
1037 Array<String> compilerFlags { };
1038 Array<String> linkerFlags { };
1048 char * executableLauncher;
1050 char * gnuToolchainPrefix;
1054 struct { Array<String> includes, libraries, executables; };
1055 Array<String> dirs[DirTypes];
1069 delete executableLauncher;
1071 delete gnuToolchainPrefix;
1073 if(environmentVars) environmentVars.Free();
1074 if(includeDirs) { includeDirs.Free(); }
1075 if(libraryDirs) { libraryDirs.Free(); }
1076 if(executableDirs) { executableDirs.Free(); }
1077 if(prepDirectives) { prepDirectives.Free(); }
1078 if(excludeLibs) { excludeLibs.Free(); }
1079 if(compilerFlags) { compilerFlags.Free(); }
1080 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1081 if(linkerFlags) { linkerFlags.Free(); }
1083 CompilerConfig Copy()
1108 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1109 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1110 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1111 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1112 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1113 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1114 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1115 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1116 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1123 struct LanguageOption
1130 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1135 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1137 Bitmap icon = res ? res.bitmap : null;
1140 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1141 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1145 Array<LanguageOption> languages
1147 { "English", ":countryCode/gb.png", "" },
1148 { "汉语", ":countryCode/cn.png", "zh_CN" },
1149 { "Español", ":countryCode/es.png", "es" },
1150 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1151 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1152 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1153 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1154 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1155 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1156 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1159 String GetLanguageString()
1161 char * dot, * colon;
1162 static char lang[256];
1163 String language = getenv("ECERE_LANGUAGE");
1164 if(!language) language = getenv("LANGUAGE");
1165 if(!language) language = getenv("LC_ALL");
1166 if(!language) language = getenv("LC_MESSAGES");
1167 if(!language) language = getenv("LANG");
1168 if(!language) language = "";
1169 if(language && (colon = strchr(language, ':')))
1171 if(lang != language)
1172 strncpy(lang, language, sizeof(lang));
1173 lang[sizeof(lang)-1] = 0;
1174 lang[colon - language] = 0;
1177 if(language && (dot = strchr(language, '.')))
1179 if(lang != language)
1180 strncpy(lang, language, sizeof(lang));
1181 lang[sizeof(lang)-1] = 0;
1182 lang[dot - language] = 0;
1188 bool LanguageRestart(char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1190 bool restart = true;
1191 String command = null;
1192 int arg0Len = (int)strlen(app.argv[0]);
1204 for(w = ide.firstChild; w; w = w.next)
1206 if(w.isActiveClient && w.isDocument)
1208 if(!w.CloseConfirmation(true))
1217 if(!projectView.CloseConfirmation(true))
1219 if(projectView.fileName)
1221 char * name = projectView.fileName;
1224 for(j = 0; (ch = name[j]); j++)
1225 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1229 command = new char[len + 1];
1231 strcpy(command, app.argv[0]);
1233 if(projectView.fileName)
1235 strcat(command, " ");
1237 ReplaceSpaces(command + len, projectView.fileName);
1242 for(w = ide.firstChild; w; w = w.next)
1243 if(w.isActiveClient && w.isDocument)
1244 w.modifiedDocument = false;
1245 projectView.modifiedDocument = false;
1250 for(w = ide.firstChild; w; w = w.next)
1252 if(w.isActiveClient && w.isDocument)
1254 if(!w.CloseConfirmation(true))
1261 char * name = w.fileName;
1263 for(j = 0; (ch = name[j]); j++)
1264 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1271 command = new char[len + 1];
1272 strcpy(command, app.argv[0]);
1275 for(w = ide.firstChild; w; w = w.next)
1277 if(w.isActiveClient && w.isDocument)
1279 char * name = w.fileName;
1282 strcat(command, " ");
1284 ReplaceSpaces(command + len, name);
1285 len = (int)strlen(command);
1292 for(w = ide.firstChild; w; w = w.next)
1293 if(w.isActiveClient && w.isDocument)
1294 w.modifiedDocument = false;
1299 settings.language = code;
1300 settingsContainer.Save();
1302 #if defined(__WIN32__)
1303 // Set LANGUAGE environment variable
1306 uint16 wLanguage[256];
1310 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1313 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1314 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1320 if(eClass_IsDerived(app._class, class(GuiApplication)))
1322 GuiApplication guiApp = (GuiApplication)app;
1323 guiApp.desktop.Destroy(0);
1330 for(i = 1; i < app.argc; i++)
1332 char * arg = app.argv[i];
1334 for(j = 0; (ch = arg[j]); j++)
1335 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1338 command = new char[len + 1];
1339 strcpy(command, app.argv[0]);
1341 for(i = 1; i < app.argc; i++)
1343 strcat(command, " ");
1345 ReplaceSpaces(command + len, app.argv[i]);
1346 len = (int)strlen(command);
1352 SetEnvironment("ECERE_LANGUAGE", code);
1354 ExecuteWait(command);