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 /*if(MessageBox { type = YesNo, master = this,
290 text = "Global Settings Modified Externally",
291 contents = "The global settings were modified by another instance.\n"
292 "Would you like to reload them?" }.Modal() == Yes)*/
295 FileSize newSettingsFileSize;
296 FileGetSize(settingsFilePath, &newSettingsFileSize);
297 o = settingsFileSize;
298 n = newSettingsFileSize;
303 GuiApplication app = ((GuiApplication)__thisModule.application);
305 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
306 MessageBox { master = w, type = ok,
307 text = "Global Settings Modified Externally",
308 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
309 "The new settings will not be loaded to prevent loss of your ide settings.\n"
310 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
317 SettingsIOResult Load()
319 SettingsIOResult result = GlobalSettings::Load();
320 IDESettings data = (IDESettings)this.data;
321 CompilerConfig defaultCompiler = null;
324 this.data = IDESettings { };
326 *dataOwner = this.data;
328 if(result == fileNotCompatibleWithDriver)
331 OldIDESettings oldSettings { };
333 loaded = oldSettings.Load() == success;
337 data = (IDESettings)this.data;
339 for(c : oldSettings.compilerConfigs)
340 data.compilerConfigs.Add(c.Copy());
342 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
343 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
345 data.docDir = oldSettings.docDir;
346 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
347 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
348 data.useFreeCaret = oldSettings.useFreeCaret;
349 data.showLineNumbers = oldSettings.showLineNumbers;
350 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
351 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
352 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
353 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
360 if(result == fileNotFound || !data)
362 data = (IDESettings)this.data;
363 data.useFreeCaret = false; //true;
364 data.showLineNumbers = true;
365 data.caretFollowsScrolling = false; //true;
368 // Ensure we have a default compiler
369 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
372 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
373 data.compilerConfigs.Add(defaultCompiler);
376 // We incref the compilers below, so reset refCount to 0
377 defaultCompiler._refCount = 0;
380 FileGetSize(settingsFilePath, &settingsFileSize);
381 if(data.compilerConfigs)
383 for(c : data.compilerConfigs)
385 CompilerConfig compiler = c;
386 char * cxxCommand = compiler.cxxCommand;
387 if(!cxxCommand || !cxxCommand[0])
388 compiler.cxxCommand = cxxDefaultCommand;
392 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
393 data.ManagePortablePaths(moduleLocation, true);
394 data.ForcePathSeparatorStyle(true);
399 SettingsIOResult Save()
401 SettingsIOResult result;
403 IDESettings data = (IDESettings)this.data;
404 Platform runtimePlatform = GetRuntimePlatform();
405 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
406 data.ManagePortablePaths(moduleLocation, false);
407 data.ForcePathSeparatorStyle(true);
408 result = GlobalSettings::Save();
409 if(result != success)
410 PrintLn("Error saving IDE settings");
411 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
412 data.ManagePortablePaths(moduleLocation, true);
414 FileGetSize(settingsFilePath, &settingsFileSize);
419 class IDESettings : GlobalSettingsData
422 List<CompilerConfig> compilerConfigs { };
423 Array<String> recentFiles { };
424 Array<String> recentProjects { };
425 property char * docDir
427 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
428 get { return docDir ? docDir : ""; }
429 isset { return docDir && docDir[0]; }
431 property char * ideFileDialogLocation
433 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
434 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
435 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
437 property char * ideProjectFileDialogLocation
439 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
440 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
441 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
444 bool showLineNumbers;
445 bool caretFollowsScrolling;
446 char * displayDriver;
448 // TODO: Classify settings
449 //EditorSettings editor { };
451 property char * projectDefaultTargetDir
453 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
454 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
455 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
457 property char * projectDefaultIntermediateObjDir
459 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
460 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
461 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
464 property char * compilerConfigsDir
466 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
467 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
468 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
471 property char * defaultCompiler
473 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
474 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
475 isset { return defaultCompiler && defaultCompiler[0]; }
478 property String language
483 language = CopyString(value);
485 get { return language; }
486 isset { return language != null; }
491 char * ideFileDialogLocation;
492 char * ideProjectFileDialogLocation;
493 char * projectDefaultTargetDir;
494 char * projectDefaultIntermediateObjDir;
495 char * compilerConfigsDir;
496 char * defaultCompiler;
499 CompilerConfig GetCompilerConfig(String compilerName)
501 char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
502 CompilerConfig compilerConfig = null;
503 for(compiler : compilerConfigs)
505 if(!strcmp(compiler.name, name))
507 compilerConfig = compiler;
511 if(!compilerConfig && compilerConfigs.count)
512 compilerConfig = compilerConfigs.firstIterator.data;
514 incref compilerConfig;
515 return compilerConfig;
520 compilerConfigs.Free();
521 delete compilerConfigs;
524 recentProjects.Free();
525 delete recentProjects;
528 delete projectDefaultTargetDir;
529 delete projectDefaultIntermediateObjDir;
530 delete compilerConfigsDir;
531 delete defaultCompiler;
534 delete ideFileDialogLocation;
535 delete ideProjectFileDialogLocation;
536 delete displayDriver;
539 void ForcePathSeparatorStyle(bool unixStyle)
543 from = '\\', to = '/';
545 from = '/', to = '\\';
546 if(compilerConfigs && compilerConfigs.count)
549 for(config : compilerConfigs)
551 if(config.includeDirs && config.includeDirs.count)
553 for(i = 0; i < config.includeDirs.count; i++)
555 if(config.includeDirs[i] && config.includeDirs[i][0])
556 ChangeCh(config.includeDirs[i], from, to);
559 if(config.libraryDirs && config.libraryDirs.count)
561 for(i = 0; i < config.libraryDirs.count; i++)
563 if(config.libraryDirs[i] && config.libraryDirs[i][0])
564 ChangeCh(config.libraryDirs[i], from, to);
567 if(config.executableDirs && config.executableDirs.count)
569 for(i = 0; i < config.executableDirs.count; i++)
571 if(config.executableDirs[i] && config.executableDirs[i][0])
572 ChangeCh(config.executableDirs[i], from, to);
577 if(recentFiles && recentFiles.count)
580 for(c = 0; c < recentFiles.count; c++)
582 if(recentFiles[c] && recentFiles[c][0])
583 ChangeCh(recentFiles[c], from, to);
586 if(recentProjects && recentProjects.count)
589 for(c = 0; c < recentProjects.count; c++)
591 if(recentProjects[c] && recentProjects[c][0])
592 ChangeCh(recentProjects[c], from, to);
595 if(docDir && docDir[0])
596 ChangeCh(docDir, from, to);
597 if(ideFileDialogLocation && ideFileDialogLocation[0])
598 ChangeCh(ideFileDialogLocation, from, to);
599 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
600 ChangeCh(ideProjectFileDialogLocation, from, to);
602 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
603 ChangeCh(projectDefaultTargetDir, from, to);
604 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
605 ChangeCh(projectDefaultIntermediateObjDir, from, to);
607 if(compilerConfigsDir && compilerConfigsDir[0])
608 ChangeCh(compilerConfigsDir, from, to);
611 void ManagePortablePaths(char * location, bool makeAbsolute)
614 if(compilerConfigs && compilerConfigs.count)
616 for(config : compilerConfigs)
619 for(t = 0; t < DirTypes::enumSize; t++)
621 Array<String> dirs = null;
622 if(t == executables) dirs = config.executableDirs;
623 else if(t == includes) dirs = config.includeDirs;
624 else if(t == libraries) dirs = config.libraryDirs;
625 if(dirs && dirs.count)
627 for(c = 0; c < dirs.count; c++)
629 if(dirs[c] && dirs[c][0])
630 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
636 if(recentFiles && recentFiles.count)
638 for(c = 0; c < recentFiles.count; c++)
640 if(recentFiles[c] && recentFiles[c][0])
641 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
644 if(recentProjects && recentProjects.count)
646 for(c = 0; c < recentProjects.count; c++)
648 if(recentProjects[c] && recentProjects[c][0])
649 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
652 if(docDir && docDir[0])
653 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
654 if(ideFileDialogLocation && ideFileDialogLocation[0])
655 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
656 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
657 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
659 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
660 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
661 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
662 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
664 if(compilerConfigsDir && compilerConfigsDir[0])
665 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
668 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
673 char p[MAX_LOCATION];
675 PathCatSlash(p, path);
677 output = CopyString(p);
681 PathRelationship rel = eString_PathRelated(path, location, null);
682 if(rel == subPath || rel == identical)
684 char p[MAX_LOCATION];
685 MakePathRelative(path, location, p);
686 if(!*p) strcpy(p, "./");
687 else ChangeCh(p, '\\', '/');
689 output = CopyString(p);
697 void AddRecentFile(char * fileName)
700 char * filePath = CopyString(fileName);
701 ChangeCh(filePath, '\\', '/');
702 for(c = 0; c<recentFiles.count; c++)
704 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
706 recentFiles.Delete((void *)&recentFiles[c]);
710 while(recentFiles.count >= MaxRecent)
711 recentFiles.Delete(recentFiles.GetLast());
712 recentFiles.Insert(null, filePath);
713 //UpdateRecentMenus(owner);
716 void AddRecentProject(char * projectName)
719 char * filePath = CopyString(projectName);
720 ChangeCh(filePath, '\\', '/');
721 for(c = 0; c<recentProjects.count; c++)
723 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
725 recentProjects.Delete((void *)&recentProjects[c]);
729 while(recentProjects.count >= MaxRecent)
730 recentProjects.Delete(recentProjects.GetLast());
731 recentProjects.Insert(null, filePath);
732 //UpdateRecentMenus(owner);
736 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
737 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
738 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
739 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
740 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
741 // TODO: i18n with Array
742 static Array<String> compilerTypeLongNames
744 $"GNU Compiler Collection (GCC) / GNU Make",
745 $"Tiny C Compiler / GNU Make",
746 $"Portable C Compiler / GNU Make",
747 $"Microsoft Visual Studio 2005 (8.0) Compiler",
748 $"Microsoft Visual Studio 2008 (9.0) Compiler",
749 $"Microsoft Visual Studio 2010 (10.0) Compiler"
751 const CompilerType firstCompilerType = gcc;
752 const CompilerType lastCompilerType = vs10;
753 public enum CompilerType
755 gcc, tcc, pcc, vs8, vs9, vs10;
759 get { return this == vs8 || this == vs9 || this == vs10; }
764 get { return OnGetString(null, null, null); }
770 for(c = firstCompilerType; c <= lastCompilerType; c++)
771 if(!strcmpi(value, compilerTypeNames[c]))
778 property char * longName { get { return OnGetString(null, (void*)1, null); } };
779 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
780 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
781 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
782 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
784 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
786 if(this >= firstCompilerType && this <= lastCompilerType)
789 strcpy(tempString, compilerTypeNames[this]);
790 if(fieldData == null)
791 return compilerTypeNames[this];
792 else if(fieldData == (void*)1)
793 return compilerTypeLongNames[this];
794 else if(fieldData == (void*)2)
795 return compilerTypeVersionString[this];
796 else if(fieldData == (void*)3)
797 return compilerTypeYearString[this];
798 else if(fieldData == (void*)4)
799 return compilerTypeProjectFileExtension[this];
800 else if(fieldData == (void*)5)
801 return compilerTypeSolutionFileVersionString[this];
819 name = CopyString(value);
825 Platform targetPlatform;
827 property char * makeCommand
829 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
830 get { return makeCommand; }
831 isset { return makeCommand && makeCommand[0]; }
833 property char * ecpCommand
835 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
836 get { return ecpCommand; }
837 isset { return ecpCommand && ecpCommand[0]; }
839 property char * eccCommand
841 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
842 get { return eccCommand; }
843 isset { return eccCommand && eccCommand[0]; }
845 property char * ecsCommand
847 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
848 get { return ecsCommand; }
849 isset { return ecsCommand && ecsCommand[0]; }
851 property char * earCommand
853 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
854 get { return earCommand; }
855 isset { return earCommand && earCommand[0]; }
857 property char * cppCommand
859 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
860 get { return cppCommand; }
861 isset { return cppCommand && cppCommand[0]; }
863 property char * ccCommand
865 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
866 get { return ccCommand; }
867 isset { return ccCommand && ccCommand[0]; }
869 property char * cxxCommand
871 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
872 get { return cxxCommand; }
873 isset { return cxxCommand && cxxCommand[0]; }
875 property char * execPrefixCommand // <-- old name for json ide settings file compatibility
877 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
878 get { return executableLauncher; }
879 isset { return executableLauncher && executableLauncher[0]; }
881 // TODO: implement CompilerConfig::windresCommand
885 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
887 property char * distccHosts
889 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
890 get { return distccHosts; }
891 isset { return distccHosts && distccHosts[0]; }
893 property char * gccPrefix // <-- old name for json ide settings file compatibility
895 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
896 get { return gnuToolchainPrefix; }
897 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
899 property char * sysroot
901 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
902 get { return sysroot; }
903 isset { return sysroot && sysroot[0]; }
905 property Array<String> includeDirs
916 get { return includeDirs; }
917 isset { return includeDirs.count != 0; }
919 property Array<String> libraryDirs
930 get { return libraryDirs; }
931 isset { return libraryDirs.count != 0; }
933 property Array<String> executableDirs
937 executableDirs.Free();
940 delete executableDirs;
941 executableDirs = value;
944 get { return executableDirs; }
945 isset { return executableDirs.count != 0; }
947 property Array<NamedString> environmentVars
951 environmentVars.Free();
954 delete environmentVars;
955 environmentVars = value;
958 get { return environmentVars; }
959 isset { return environmentVars.count != 0; }
961 property Array<String> prepDirectives
965 prepDirectives.Free();
968 delete prepDirectives;
969 prepDirectives = value;
972 get { return prepDirectives; }
973 isset { return prepDirectives.count != 0; }
975 property Array<String> excludeLibs
986 get { return excludeLibs; }
987 isset { return excludeLibs.count != 0; }
989 property Array<String> eCcompilerFlags
993 eCcompilerFlags.Free();
996 delete eCcompilerFlags;
997 eCcompilerFlags = value;
1000 get { return eCcompilerFlags; }
1001 isset { return eCcompilerFlags.count != 0; }
1003 property Array<String> compilerFlags
1007 compilerFlags.Free();
1010 delete compilerFlags;
1011 compilerFlags = value;
1014 get { return compilerFlags; }
1015 isset { return compilerFlags.count != 0; }
1017 property Array<String> linkerFlags
1025 linkerFlags = value;
1028 get { return linkerFlags; }
1029 isset { return linkerFlags.count != 0; }
1032 Array<String> includeDirs { };
1033 Array<String> libraryDirs { };
1034 Array<String> executableDirs { };
1035 // TODO: Can JSON parse and serialize maps?
1036 //EnvironmentVariables { };
1037 Array<NamedString> environmentVars { };
1038 Array<String> prepDirectives { };
1039 Array<String> excludeLibs { };
1040 Array<String> eCcompilerFlags { };
1041 Array<String> compilerFlags { };
1042 Array<String> linkerFlags { };
1052 char * executableLauncher;
1054 char * gnuToolchainPrefix;
1058 struct { Array<String> includes, libraries, executables; };
1059 Array<String> dirs[DirTypes];
1073 delete executableLauncher;
1075 delete gnuToolchainPrefix;
1077 if(environmentVars) environmentVars.Free();
1078 if(includeDirs) { includeDirs.Free(); }
1079 if(libraryDirs) { libraryDirs.Free(); }
1080 if(executableDirs) { executableDirs.Free(); }
1081 if(prepDirectives) { prepDirectives.Free(); }
1082 if(excludeLibs) { excludeLibs.Free(); }
1083 if(compilerFlags) { compilerFlags.Free(); }
1084 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1085 if(linkerFlags) { linkerFlags.Free(); }
1087 CompilerConfig Copy()
1112 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1113 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1114 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1115 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1116 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1117 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1118 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1119 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1120 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1127 struct LanguageOption
1134 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1139 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1141 Bitmap icon = res ? res.bitmap : null;
1144 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1145 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1149 Array<LanguageOption> languages
1151 { "English", ":countryCode/gb.png", "" },
1152 { "汉语", ":countryCode/cn.png", "zh_CN" },
1153 { "Español", ":countryCode/es.png", "es" },
1154 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1155 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1156 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1157 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1158 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1159 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1160 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1163 String GetLanguageString()
1165 String language = getenv("ECERE_LANGUAGE");
1166 if(!language) language = getenv("LANGUAGE");
1167 if(!language) language = getenv("LC_ALL");
1168 if(!language) language = getenv("LC_MESSAGES");
1169 if(!language) language = getenv("LANG");
1170 if(!language) language = "";
1174 bool LanguageRestart(char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1176 bool restart = true;
1177 String command = null;
1178 int arg0Len = (int)strlen(app.argv[0]);
1190 for(w = ide.firstChild; w; w = w.next)
1192 if(w.isActiveClient && w.isDocument)
1194 if(!w.CloseConfirmation(true))
1203 if(!projectView.CloseConfirmation(true))
1205 if(projectView.fileName)
1207 char * name = projectView.fileName;
1210 for(j = 0; (ch = name[j]); j++)
1211 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1215 command = new char[len + 1];
1217 strcpy(command, app.argv[0]);
1219 if(projectView.fileName)
1221 strcat(command, " ");
1223 ReplaceSpaces(command + len, projectView.fileName);
1228 for(w = ide.firstChild; w; w = w.next)
1229 if(w.isActiveClient && w.isDocument)
1230 w.modifiedDocument = false;
1231 projectView.modifiedDocument = false;
1236 for(w = ide.firstChild; w; w = w.next)
1238 if(w.isActiveClient && w.isDocument)
1240 if(!w.CloseConfirmation(true))
1247 char * name = w.fileName;
1249 for(j = 0; (ch = name[j]); j++)
1250 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1257 command = new char[len + 1];
1258 strcpy(command, app.argv[0]);
1261 for(w = ide.firstChild; w; w = w.next)
1263 if(w.isActiveClient && w.isDocument)
1265 char * name = w.fileName;
1268 strcat(command, " ");
1270 ReplaceSpaces(command + len, name);
1271 len = (int)strlen(command);
1278 for(w = ide.firstChild; w; w = w.next)
1279 if(w.isActiveClient && w.isDocument)
1280 w.modifiedDocument = false;
1285 settings.language = code;
1286 settingsContainer.Save();
1288 #if defined(__WIN32__)
1289 // Set LANGUAGE environment variable
1292 uint16 wLanguage[256];
1296 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1299 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1300 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1306 if(eClass_IsDerived(app._class, class(GuiApplication)))
1308 GuiApplication guiApp = (GuiApplication)app;
1309 guiApp.desktop.Destroy(0);
1316 for(i = 1; i < app.argc; i++)
1318 char * arg = app.argv[i];
1320 for(j = 0; (ch = arg[j]); j++)
1321 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1324 command = new char[len + 1];
1325 strcpy(command, app.argv[0]);
1327 for(i = 1; i < app.argc; i++)
1329 strcat(command, " ");
1331 ReplaceSpaces(command + len, app.argv[i]);
1332 len = (int)strlen(command);
1338 SetEnvironment("ECERE_LANGUAGE", code);
1340 ExecuteWait(command);