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 const 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, const 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(const char * path, const 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(const 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<const 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, const 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 const 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(const char * name, bool readOnly)
206 CompilerConfig defaultCompiler
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 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
401 data.ManagePortablePaths(moduleLocation, false);
402 data.ForcePathSeparatorStyle(true);
403 result = GlobalSettings::Save();
404 if(result != success)
405 PrintLn("Error saving IDE settings");
406 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
407 data.ManagePortablePaths(moduleLocation, true);
409 FileGetSize(settingsFilePath, &settingsFileSize);
414 class IDESettings : GlobalSettingsData
417 List<CompilerConfig> compilerConfigs { };
418 Array<String> recentFiles { };
419 Array<String> recentProjects { };
420 property const char * docDir
422 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
423 get { return docDir ? docDir : ""; }
424 isset { return docDir && docDir[0]; }
426 property const char * ideFileDialogLocation
428 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
429 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
430 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
432 property const char * ideProjectFileDialogLocation
434 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
435 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
436 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
439 bool showLineNumbers;
440 bool caretFollowsScrolling;
441 char * displayDriver;
443 // TODO: Classify settings
444 //EditorSettings editor { };
446 property const char * projectDefaultTargetDir
448 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
449 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
450 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
452 property const char * projectDefaultIntermediateObjDir
454 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
455 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
456 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
459 property const char * compilerConfigsDir
461 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
462 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
463 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
466 property const char * defaultCompiler
468 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
469 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
470 isset { return defaultCompiler && defaultCompiler[0]; }
473 property const String language
478 language = CopyString(value);
480 get { return language; }
481 isset { return language != null; }
486 char * ideFileDialogLocation;
487 char * ideProjectFileDialogLocation;
488 char * projectDefaultTargetDir;
489 char * projectDefaultIntermediateObjDir;
490 char * compilerConfigsDir;
491 char * defaultCompiler;
494 CompilerConfig GetCompilerConfig(const String compilerName)
496 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
497 CompilerConfig compilerConfig = null;
498 for(compiler : compilerConfigs)
500 if(!strcmp(compiler.name, name))
502 compilerConfig = compiler;
506 if(!compilerConfig && compilerConfigs.count)
507 compilerConfig = compilerConfigs.firstIterator.data;
509 incref compilerConfig;
510 return compilerConfig;
515 compilerConfigs.Free();
516 delete compilerConfigs;
519 recentProjects.Free();
520 delete recentProjects;
523 delete projectDefaultTargetDir;
524 delete projectDefaultIntermediateObjDir;
525 delete compilerConfigsDir;
526 delete defaultCompiler;
529 delete ideFileDialogLocation;
530 delete ideProjectFileDialogLocation;
531 delete displayDriver;
534 void ForcePathSeparatorStyle(bool unixStyle)
538 from = '\\', to = '/';
540 from = '/', to = '\\';
541 if(compilerConfigs && compilerConfigs.count)
544 for(config : compilerConfigs)
546 if(config.includeDirs && config.includeDirs.count)
548 for(i = 0; i < config.includeDirs.count; i++)
550 if(config.includeDirs[i] && config.includeDirs[i][0])
551 ChangeCh(config.includeDirs[i], from, to);
554 if(config.libraryDirs && config.libraryDirs.count)
556 for(i = 0; i < config.libraryDirs.count; i++)
558 if(config.libraryDirs[i] && config.libraryDirs[i][0])
559 ChangeCh(config.libraryDirs[i], from, to);
562 if(config.executableDirs && config.executableDirs.count)
564 for(i = 0; i < config.executableDirs.count; i++)
566 if(config.executableDirs[i] && config.executableDirs[i][0])
567 ChangeCh(config.executableDirs[i], from, to);
572 if(recentFiles && recentFiles.count)
575 for(c = 0; c < recentFiles.count; c++)
577 if(recentFiles[c] && recentFiles[c][0])
578 ChangeCh(recentFiles[c], from, to);
581 if(recentProjects && recentProjects.count)
584 for(c = 0; c < recentProjects.count; c++)
586 if(recentProjects[c] && recentProjects[c][0])
587 ChangeCh(recentProjects[c], from, to);
590 if(docDir && docDir[0])
591 ChangeCh(docDir, from, to);
592 if(ideFileDialogLocation && ideFileDialogLocation[0])
593 ChangeCh(ideFileDialogLocation, from, to);
594 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
595 ChangeCh(ideProjectFileDialogLocation, from, to);
597 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
598 ChangeCh(projectDefaultTargetDir, from, to);
599 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
600 ChangeCh(projectDefaultIntermediateObjDir, from, to);
602 if(compilerConfigsDir && compilerConfigsDir[0])
603 ChangeCh(compilerConfigsDir, from, to);
606 void ManagePortablePaths(char * location, bool makeAbsolute)
609 if(compilerConfigs && compilerConfigs.count)
611 for(config : compilerConfigs)
614 for(t = 0; t < DirTypes::enumSize; t++)
616 Array<String> dirs = null;
617 if(t == executables) dirs = config.executableDirs;
618 else if(t == includes) dirs = config.includeDirs;
619 else if(t == libraries) dirs = config.libraryDirs;
620 if(dirs && dirs.count)
622 for(c = 0; c < dirs.count; c++)
624 if(dirs[c] && dirs[c][0])
625 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
631 if(recentFiles && recentFiles.count)
633 for(c = 0; c < recentFiles.count; c++)
635 if(recentFiles[c] && recentFiles[c][0])
636 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
639 if(recentProjects && recentProjects.count)
641 for(c = 0; c < recentProjects.count; c++)
643 if(recentProjects[c] && recentProjects[c][0])
644 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
647 if(docDir && docDir[0])
648 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
649 if(ideFileDialogLocation && ideFileDialogLocation[0])
650 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
651 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
652 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
654 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
655 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
656 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
657 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
659 if(compilerConfigsDir && compilerConfigsDir[0])
660 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
663 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
668 char p[MAX_LOCATION];
670 PathCatSlash(p, path);
672 output = CopyString(p);
676 PathRelationship rel = eString_PathRelated(path, location, null);
677 if(rel == subPath || rel == identical)
679 char p[MAX_LOCATION];
680 MakePathRelative(path, location, p);
681 if(!*p) strcpy(p, "./");
682 else ChangeCh(p, '\\', '/');
684 output = CopyString(p);
692 void AddRecentFile(const char * fileName)
695 char * filePath = CopyString(fileName);
696 ChangeCh(filePath, '\\', '/');
697 for(c = 0; c<recentFiles.count; c++)
699 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
701 recentFiles.Delete((void *)&recentFiles[c]);
705 while(recentFiles.count >= MaxRecent)
706 recentFiles.Delete(recentFiles.GetLast());
707 recentFiles.Insert(null, filePath);
708 //UpdateRecentMenus(owner);
711 void AddRecentProject(const char * projectName)
714 char * filePath = CopyString(projectName);
715 ChangeCh(filePath, '\\', '/');
716 for(c = 0; c<recentProjects.count; c++)
718 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
720 recentProjects.Delete((void *)&recentProjects[c]);
724 while(recentProjects.count >= MaxRecent)
725 recentProjects.Delete(recentProjects.GetLast());
726 recentProjects.Insert(null, filePath);
727 //UpdateRecentMenus(owner);
731 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
732 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
733 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
734 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
735 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
736 // TODO: i18n with Array
737 static Array<const String> compilerTypeLongNames
739 $"GNU Compiler Collection (GCC) / GNU Make",
740 $"Tiny C Compiler / GNU Make",
741 $"Portable C Compiler / GNU Make",
742 $"Microsoft Visual Studio 2005 (8.0) Compiler",
743 $"Microsoft Visual Studio 2008 (9.0) Compiler",
744 $"Microsoft Visual Studio 2010 (10.0) Compiler"
746 const CompilerType firstCompilerType = gcc;
747 const CompilerType lastCompilerType = vs10;
748 public enum CompilerType
750 gcc, tcc, pcc, vs8, vs9, vs10;
754 get { return this == vs8 || this == vs9 || this == vs10; }
757 property const char *
759 get { return OnGetString(null, null, null); }
765 for(c = firstCompilerType; c <= lastCompilerType; c++)
766 if(!strcmpi(value, compilerTypeNames[c]))
773 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
774 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
775 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
776 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
777 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
779 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
781 if(this >= firstCompilerType && this <= lastCompilerType)
784 strcpy(tempString, compilerTypeNames[this]);
785 if(fieldData == null)
786 return compilerTypeNames[this];
787 else if(fieldData == (void*)1)
788 return compilerTypeLongNames[this];
789 else if(fieldData == (void*)2)
790 return compilerTypeVersionString[this];
791 else if(fieldData == (void*)3)
792 return compilerTypeYearString[this];
793 else if(fieldData == (void*)4)
794 return compilerTypeProjectFileExtension[this];
795 else if(fieldData == (void*)5)
796 return compilerTypeSolutionFileVersionString[this];
808 property const char * name
814 name = CopyString(value);
820 Platform targetPlatform;
822 property const char * makeCommand
824 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
825 get { return makeCommand; }
826 isset { return makeCommand && makeCommand[0]; }
828 property const char * ecpCommand
830 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
831 get { return ecpCommand; }
832 isset { return ecpCommand && ecpCommand[0]; }
834 property const char * eccCommand
836 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
837 get { return eccCommand; }
838 isset { return eccCommand && eccCommand[0]; }
840 property const char * ecsCommand
842 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
843 get { return ecsCommand; }
844 isset { return ecsCommand && ecsCommand[0]; }
846 property const char * earCommand
848 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
849 get { return earCommand; }
850 isset { return earCommand && earCommand[0]; }
852 property const char * cppCommand
854 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
855 get { return cppCommand; }
856 isset { return cppCommand && cppCommand[0]; }
858 property const char * ccCommand
860 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
861 get { return ccCommand; }
862 isset { return ccCommand && ccCommand[0]; }
864 property const char * cxxCommand
866 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
867 get { return cxxCommand; }
868 isset { return cxxCommand && cxxCommand[0]; }
870 property const char * execPrefixCommand // <-- old name for json ide settings file compatibility
872 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
873 get { return executableLauncher; }
874 isset { return executableLauncher && executableLauncher[0]; }
876 // TODO: implement CompilerConfig::windresCommand
880 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
882 property const char * distccHosts
884 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
885 get { return distccHosts; }
886 isset { return distccHosts && distccHosts[0]; }
888 property const char * gccPrefix // <-- old name for json ide settings file compatibility
890 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
891 get { return gnuToolchainPrefix; }
892 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
894 property const char * sysroot
896 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
897 get { return sysroot; }
898 isset { return sysroot && sysroot[0]; }
900 property Array<String> includeDirs
911 get { return includeDirs; }
912 isset { return includeDirs.count != 0; }
914 property Array<String> libraryDirs
925 get { return libraryDirs; }
926 isset { return libraryDirs.count != 0; }
928 property Array<String> executableDirs
932 executableDirs.Free();
935 delete executableDirs;
936 executableDirs = value;
939 get { return executableDirs; }
940 isset { return executableDirs.count != 0; }
942 property Array<NamedString> environmentVars
946 environmentVars.Free();
949 delete environmentVars;
950 environmentVars = value;
953 get { return environmentVars; }
954 isset { return environmentVars.count != 0; }
956 property Array<String> prepDirectives
960 prepDirectives.Free();
963 delete prepDirectives;
964 prepDirectives = value;
967 get { return prepDirectives; }
968 isset { return prepDirectives.count != 0; }
970 property Array<String> excludeLibs
981 get { return excludeLibs; }
982 isset { return excludeLibs.count != 0; }
984 property Array<String> eCcompilerFlags
988 eCcompilerFlags.Free();
991 delete eCcompilerFlags;
992 eCcompilerFlags = value;
995 get { return eCcompilerFlags; }
996 isset { return eCcompilerFlags.count != 0; }
998 property Array<String> compilerFlags
1002 compilerFlags.Free();
1005 delete compilerFlags;
1006 compilerFlags = value;
1009 get { return compilerFlags; }
1010 isset { return compilerFlags.count != 0; }
1012 property Array<String> linkerFlags
1020 linkerFlags = value;
1023 get { return linkerFlags; }
1024 isset { return linkerFlags.count != 0; }
1027 Array<String> includeDirs { };
1028 Array<String> libraryDirs { };
1029 Array<String> executableDirs { };
1030 // TODO: Can JSON parse and serialize maps?
1031 //EnvironmentVariables { };
1032 Array<NamedString> environmentVars { };
1033 Array<String> prepDirectives { };
1034 Array<String> excludeLibs { };
1035 Array<String> eCcompilerFlags { };
1036 Array<String> compilerFlags { };
1037 Array<String> linkerFlags { };
1047 char * executableLauncher;
1049 char * gnuToolchainPrefix;
1053 struct { Array<String> includes, libraries, executables; };
1054 Array<String> dirs[DirTypes];
1068 delete executableLauncher;
1070 delete gnuToolchainPrefix;
1072 if(environmentVars) environmentVars.Free();
1073 if(includeDirs) { includeDirs.Free(); }
1074 if(libraryDirs) { libraryDirs.Free(); }
1075 if(executableDirs) { executableDirs.Free(); }
1076 if(prepDirectives) { prepDirectives.Free(); }
1077 if(excludeLibs) { excludeLibs.Free(); }
1078 if(compilerFlags) { compilerFlags.Free(); }
1079 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1080 if(linkerFlags) { linkerFlags.Free(); }
1082 CompilerConfig Copy()
1107 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1108 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1109 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1110 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1111 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1112 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1113 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1114 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1115 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1122 struct LanguageOption
1125 const String bitmap;
1129 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1134 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1136 Bitmap icon = res ? res.bitmap : null;
1139 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1140 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1144 Array<LanguageOption> languages
1146 { "English", ":countryCode/gb.png", "" },
1147 { "汉语", ":countryCode/cn.png", "zh_CN" },
1148 { "Español", ":countryCode/es.png", "es" },
1149 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1150 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1151 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1152 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1153 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1154 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1155 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1158 const String GetLanguageString()
1160 char * dot, * colon;
1161 static char lang[256];
1162 const String language = getenv("ECERE_LANGUAGE");
1163 if(!language) language = getenv("LANGUAGE");
1164 if(!language) language = getenv("LC_ALL");
1165 if(!language) language = getenv("LC_MESSAGES");
1166 if(!language) language = getenv("LANG");
1167 if(!language) language = "";
1168 if(language && (colon = strchr(language, ':')))
1170 if(lang != language)
1171 strncpy(lang, language, sizeof(lang));
1172 lang[sizeof(lang)-1] = 0;
1173 lang[colon - language] = 0;
1176 if(language && (dot = strchr(language, '.')))
1178 if(lang != language)
1179 strncpy(lang, language, sizeof(lang));
1180 lang[sizeof(lang)-1] = 0;
1181 lang[dot - language] = 0;
1187 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1189 bool restart = true;
1190 String command = null;
1191 int arg0Len = (int)strlen(app.argv[0]);
1203 for(w = ide.firstChild; w; w = w.next)
1205 if(w.isActiveClient && w.isDocument)
1207 if(!w.CloseConfirmation(true))
1216 if(!projectView.CloseConfirmation(true))
1218 if(projectView.fileName)
1220 const char * name = projectView.fileName;
1223 for(j = 0; (ch = name[j]); j++)
1224 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1228 command = new char[len + 1];
1230 strcpy(command, app.argv[0]);
1232 if(projectView.fileName)
1234 strcat(command, " ");
1236 ReplaceSpaces(command + len, projectView.fileName);
1241 for(w = ide.firstChild; w; w = w.next)
1242 if(w.isActiveClient && w.isDocument)
1243 w.modifiedDocument = false;
1244 projectView.modifiedDocument = false;
1249 for(w = ide.firstChild; w; w = w.next)
1251 if(w.isActiveClient && w.isDocument)
1253 if(!w.CloseConfirmation(true))
1260 const char * name = w.fileName;
1262 for(j = 0; (ch = name[j]); j++)
1263 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1270 command = new char[len + 1];
1271 strcpy(command, app.argv[0]);
1274 for(w = ide.firstChild; w; w = w.next)
1276 if(w.isActiveClient && w.isDocument)
1278 const char * name = w.fileName;
1281 strcat(command, " ");
1283 ReplaceSpaces(command + len, name);
1284 len = (int)strlen(command);
1291 for(w = ide.firstChild; w; w = w.next)
1292 if(w.isActiveClient && w.isDocument)
1293 w.modifiedDocument = false;
1298 settings.language = code;
1299 settingsContainer.Save();
1301 #if defined(__WIN32__)
1302 // Set LANGUAGE environment variable
1305 uint16 wLanguage[256];
1309 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1312 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1313 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1319 if(eClass_IsDerived(app._class, class(GuiApplication)))
1321 GuiApplication guiApp = (GuiApplication)app;
1322 guiApp.desktop.Destroy(0);
1329 for(i = 1; i < app.argc; i++)
1331 const char * arg = app.argv[i];
1333 for(j = 0; (ch = arg[j]); j++)
1334 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1337 command = new char[len + 1];
1338 strcpy(command, app.argv[0]);
1340 for(i = 1; i < app.argc; i++)
1342 strcat(command, " ");
1344 ReplaceSpaces(command + len, app.argv[i]);
1345 len = (int)strlen(command);
1351 SetEnvironment("ECERE_LANGUAGE", code);
1353 ExecuteWait(command);