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;
533 delete ideFileDialogLocation;
534 delete ideProjectFileDialogLocation;
535 delete displayDriver;
538 void ForcePathSeparatorStyle(bool unixStyle)
542 from = '\\', to = '/';
544 from = '/', to = '\\';
545 if(compilerConfigs && compilerConfigs.count)
548 for(config : compilerConfigs)
550 if(config.includeDirs && config.includeDirs.count)
552 for(i = 0; i < config.includeDirs.count; i++)
554 if(config.includeDirs[i] && config.includeDirs[i][0])
555 ChangeCh(config.includeDirs[i], from, to);
558 if(config.libraryDirs && config.libraryDirs.count)
560 for(i = 0; i < config.libraryDirs.count; i++)
562 if(config.libraryDirs[i] && config.libraryDirs[i][0])
563 ChangeCh(config.libraryDirs[i], from, to);
566 if(config.executableDirs && config.executableDirs.count)
568 for(i = 0; i < config.executableDirs.count; i++)
570 if(config.executableDirs[i] && config.executableDirs[i][0])
571 ChangeCh(config.executableDirs[i], from, to);
576 if(recentFiles && recentFiles.count)
579 for(c = 0; c < recentFiles.count; c++)
581 if(recentFiles[c] && recentFiles[c][0])
582 ChangeCh(recentFiles[c], from, to);
585 if(recentProjects && recentProjects.count)
588 for(c = 0; c < recentProjects.count; c++)
590 if(recentProjects[c] && recentProjects[c][0])
591 ChangeCh(recentProjects[c], from, to);
594 if(docDir && docDir[0])
595 ChangeCh(docDir, from, to);
596 if(ideFileDialogLocation && ideFileDialogLocation[0])
597 ChangeCh(ideFileDialogLocation, from, to);
598 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
599 ChangeCh(ideProjectFileDialogLocation, from, to);
601 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
602 ChangeCh(projectDefaultTargetDir, from, to);
603 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
604 ChangeCh(projectDefaultIntermediateObjDir, from, to);
606 if(compilerConfigsDir && compilerConfigsDir[0])
607 ChangeCh(compilerConfigsDir, from, to);
610 void ManagePortablePaths(char * location, bool makeAbsolute)
613 if(compilerConfigs && compilerConfigs.count)
615 for(config : compilerConfigs)
618 for(t = 0; t < DirTypes::enumSize; t++)
620 Array<String> dirs = null;
621 if(t == executables) dirs = config.executableDirs;
622 else if(t == includes) dirs = config.includeDirs;
623 else if(t == libraries) dirs = config.libraryDirs;
624 if(dirs && dirs.count)
626 for(c = 0; c < dirs.count; c++)
628 if(dirs[c] && dirs[c][0])
629 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
635 if(recentFiles && recentFiles.count)
637 for(c = 0; c < recentFiles.count; c++)
639 if(recentFiles[c] && recentFiles[c][0])
640 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
643 if(recentProjects && recentProjects.count)
645 for(c = 0; c < recentProjects.count; c++)
647 if(recentProjects[c] && recentProjects[c][0])
648 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
651 if(docDir && docDir[0])
652 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
653 if(ideFileDialogLocation && ideFileDialogLocation[0])
654 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
655 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
656 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
658 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
659 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
660 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
661 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
663 if(compilerConfigsDir && compilerConfigsDir[0])
664 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
667 char * UpdatePortablePath(char * path, char * location, bool makeAbsolute)
672 char p[MAX_LOCATION];
674 PathCatSlash(p, path);
676 output = CopyString(p);
680 PathRelationship rel = eString_PathRelated(path, location, null);
681 if(rel == subPath || rel == identical)
683 char p[MAX_LOCATION];
684 MakePathRelative(path, location, p);
685 if(!*p) strcpy(p, "./");
686 else ChangeCh(p, '\\', '/');
688 output = CopyString(p);
696 void AddRecentFile(char * fileName)
699 char * filePath = CopyString(fileName);
700 ChangeCh(filePath, '\\', '/');
701 for(c = 0; c<recentFiles.count; c++)
703 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
705 recentFiles.Delete((void *)&recentFiles[c]);
709 while(recentFiles.count >= MaxRecent)
710 recentFiles.Delete(recentFiles.GetLast());
711 recentFiles.Insert(null, filePath);
712 //UpdateRecentMenus(owner);
715 void AddRecentProject(char * projectName)
718 char * filePath = CopyString(projectName);
719 ChangeCh(filePath, '\\', '/');
720 for(c = 0; c<recentProjects.count; c++)
722 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
724 recentProjects.Delete((void *)&recentProjects[c]);
728 while(recentProjects.count >= MaxRecent)
729 recentProjects.Delete(recentProjects.GetLast());
730 recentProjects.Insert(null, filePath);
731 //UpdateRecentMenus(owner);
735 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
736 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
737 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
738 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
739 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
740 // TODO: i18n with Array
741 static Array<String> compilerTypeLongNames
743 $"GNU Compiler Collection (GCC) / GNU Make",
744 $"Tiny C Compiler / GNU Make",
745 $"Portable C Compiler / GNU Make",
746 $"Microsoft Visual Studio 2005 (8.0) Compiler",
747 $"Microsoft Visual Studio 2008 (9.0) Compiler",
748 $"Microsoft Visual Studio 2010 (10.0) Compiler"
750 const CompilerType firstCompilerType = gcc;
751 const CompilerType lastCompilerType = vs10;
752 public enum CompilerType
754 gcc, tcc, pcc, vs8, vs9, vs10;
758 get { return this == vs8 || this == vs9 || this == vs10; }
763 get { return OnGetString(null, null, null); }
769 for(c = firstCompilerType; c <= lastCompilerType; c++)
770 if(!strcmpi(value, compilerTypeNames[c]))
777 property char * longName { get { return OnGetString(null, (void*)1, null); } };
778 property char * versionString { get { return OnGetString(null, (void*)2, null); } };
779 property char * yearString { get { return OnGetString(null, (void*)3, null); } };
780 property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
781 property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
783 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
785 if(this >= firstCompilerType && this <= lastCompilerType)
788 strcpy(tempString, compilerTypeNames[this]);
789 if(fieldData == null)
790 return compilerTypeNames[this];
791 else if(fieldData == (void*)1)
792 return compilerTypeLongNames[this];
793 else if(fieldData == (void*)2)
794 return compilerTypeVersionString[this];
795 else if(fieldData == (void*)3)
796 return compilerTypeYearString[this];
797 else if(fieldData == (void*)4)
798 return compilerTypeProjectFileExtension[this];
799 else if(fieldData == (void*)5)
800 return compilerTypeSolutionFileVersionString[this];
818 name = CopyString(value);
824 Platform targetPlatform;
826 property char * makeCommand
828 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
829 get { return makeCommand; }
830 isset { return makeCommand && makeCommand[0]; }
832 property char * ecpCommand
834 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
835 get { return ecpCommand; }
836 isset { return ecpCommand && ecpCommand[0]; }
838 property char * eccCommand
840 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
841 get { return eccCommand; }
842 isset { return eccCommand && eccCommand[0]; }
844 property char * ecsCommand
846 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
847 get { return ecsCommand; }
848 isset { return ecsCommand && ecsCommand[0]; }
850 property char * earCommand
852 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
853 get { return earCommand; }
854 isset { return earCommand && earCommand[0]; }
856 property char * cppCommand
858 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
859 get { return cppCommand; }
860 isset { return cppCommand && cppCommand[0]; }
862 property char * ccCommand
864 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
865 get { return ccCommand; }
866 isset { return ccCommand && ccCommand[0]; }
868 property char * cxxCommand
870 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
871 get { return cxxCommand; }
872 isset { return cxxCommand && cxxCommand[0]; }
874 property char * execPrefixCommand // <-- old name for json ide settings file compatibility
876 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
877 get { return executableLauncher; }
878 isset { return executableLauncher && executableLauncher[0]; }
880 // TODO: implement CompilerConfig::windresCommand
884 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
886 property char * distccHosts
888 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
889 get { return distccHosts; }
890 isset { return distccHosts && distccHosts[0]; }
892 property char * gccPrefix // <-- old name for json ide settings file compatibility
894 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
895 get { return gnuToolchainPrefix; }
896 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
898 property char * sysroot
900 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
901 get { return sysroot; }
902 isset { return sysroot && sysroot[0]; }
904 property Array<String> includeDirs
915 get { return includeDirs; }
916 isset { return includeDirs.count != 0; }
918 property Array<String> libraryDirs
929 get { return libraryDirs; }
930 isset { return libraryDirs.count != 0; }
932 property Array<String> executableDirs
936 executableDirs.Free();
939 delete executableDirs;
940 executableDirs = value;
943 get { return executableDirs; }
944 isset { return executableDirs.count != 0; }
946 property Array<NamedString> environmentVars
950 environmentVars.Free();
953 delete environmentVars;
954 environmentVars = value;
957 get { return environmentVars; }
958 isset { return environmentVars.count != 0; }
960 property Array<String> prepDirectives
964 prepDirectives.Free();
967 delete prepDirectives;
968 prepDirectives = value;
971 get { return prepDirectives; }
972 isset { return prepDirectives.count != 0; }
974 property Array<String> excludeLibs
985 get { return excludeLibs; }
986 isset { return excludeLibs.count != 0; }
988 property Array<String> eCcompilerFlags
992 eCcompilerFlags.Free();
995 delete eCcompilerFlags;
996 eCcompilerFlags = value;
999 get { return eCcompilerFlags; }
1000 isset { return eCcompilerFlags.count != 0; }
1002 property Array<String> compilerFlags
1006 compilerFlags.Free();
1009 delete compilerFlags;
1010 compilerFlags = value;
1013 get { return compilerFlags; }
1014 isset { return compilerFlags.count != 0; }
1016 property Array<String> linkerFlags
1024 linkerFlags = value;
1027 get { return linkerFlags; }
1028 isset { return linkerFlags.count != 0; }
1031 Array<String> includeDirs { };
1032 Array<String> libraryDirs { };
1033 Array<String> executableDirs { };
1034 // TODO: Can JSON parse and serialize maps?
1035 //EnvironmentVariables { };
1036 Array<NamedString> environmentVars { };
1037 Array<String> prepDirectives { };
1038 Array<String> excludeLibs { };
1039 Array<String> eCcompilerFlags { };
1040 Array<String> compilerFlags { };
1041 Array<String> linkerFlags { };
1051 char * executableLauncher;
1053 char * gnuToolchainPrefix;
1057 struct { Array<String> includes, libraries, executables; };
1058 Array<String> dirs[DirTypes];
1072 delete executableLauncher;
1074 delete gnuToolchainPrefix;
1076 if(environmentVars) environmentVars.Free();
1077 if(includeDirs) { includeDirs.Free(); }
1078 if(libraryDirs) { libraryDirs.Free(); }
1079 if(executableDirs) { executableDirs.Free(); }
1080 if(prepDirectives) { prepDirectives.Free(); }
1081 if(excludeLibs) { excludeLibs.Free(); }
1082 if(compilerFlags) { compilerFlags.Free(); }
1083 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1084 if(linkerFlags) { linkerFlags.Free(); }
1086 CompilerConfig Copy()
1111 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1112 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1113 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1114 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1115 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1116 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1117 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1118 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1119 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1126 struct LanguageOption
1133 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1138 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1140 Bitmap icon = res ? res.bitmap : null;
1143 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1144 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1148 Array<LanguageOption> languages
1150 { "English", ":countryCode/gb.png", "" },
1151 { "汉语", ":countryCode/cn.png", "zh_CN" },
1152 { "Español", ":countryCode/es.png", "es" },
1153 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1154 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1155 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1156 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1157 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1158 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1159 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1162 String GetLanguageString()
1164 String language = getenv("ECERE_LANGUAGE");
1165 if(!language) language = getenv("LANGUAGE");
1166 if(!language) language = getenv("LC_ALL");
1167 if(!language) language = getenv("LC_MESSAGES");
1168 if(!language) language = getenv("LANG");
1169 if(!language) language = "";
1173 bool LanguageRestart(char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1175 bool restart = true;
1176 String command = null;
1177 int arg0Len = (int)strlen(app.argv[0]);
1189 for(w = ide.firstChild; w; w = w.next)
1191 if(w.isActiveClient && w.isDocument)
1193 if(!w.CloseConfirmation(true))
1202 if(!projectView.CloseConfirmation(true))
1204 if(projectView.fileName)
1206 char * name = projectView.fileName;
1209 for(j = 0; (ch = name[j]); j++)
1210 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1214 command = new char[len + 1];
1216 strcpy(command, app.argv[0]);
1218 if(projectView.fileName)
1220 strcat(command, " ");
1222 ReplaceSpaces(command + len, projectView.fileName);
1227 for(w = ide.firstChild; w; w = w.next)
1228 if(w.isActiveClient && w.isDocument)
1229 w.modifiedDocument = false;
1230 projectView.modifiedDocument = false;
1235 for(w = ide.firstChild; w; w = w.next)
1237 if(w.isActiveClient && w.isDocument)
1239 if(!w.CloseConfirmation(true))
1246 char * name = w.fileName;
1248 for(j = 0; (ch = name[j]); j++)
1249 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1256 command = new char[len + 1];
1257 strcpy(command, app.argv[0]);
1260 for(w = ide.firstChild; w; w = w.next)
1262 if(w.isActiveClient && w.isDocument)
1264 char * name = w.fileName;
1267 strcat(command, " ");
1269 ReplaceSpaces(command + len, name);
1270 len = (int)strlen(command);
1277 for(w = ide.firstChild; w; w = w.next)
1278 if(w.isActiveClient && w.isDocument)
1279 w.modifiedDocument = false;
1284 settings.language = code;
1285 settingsContainer.Save();
1287 #if defined(__WIN32__)
1288 // Set LANGUAGE environment variable
1291 uint16 wLanguage[256];
1295 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1298 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1299 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1305 if(eClass_IsDerived(app._class, class(GuiApplication)))
1307 GuiApplication guiApp = (GuiApplication)app;
1308 guiApp.desktop.Destroy(0);
1315 for(i = 1; i < app.argc; i++)
1317 char * arg = app.argv[i];
1319 for(j = 0; (ch = arg[j]); j++)
1320 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1323 command = new char[len + 1];
1324 strcpy(command, app.argv[0]);
1326 for(i = 1; i < app.argc; i++)
1328 strcat(command, " ");
1330 ReplaceSpaces(command + len, app.argv[i]);
1331 len = (int)strlen(command);
1337 SetEnvironment("ECERE_LANGUAGE", code);
1339 ExecuteWait(command);