2 #define MessageBox _MessageBox
3 #define WIN32_LEAN_AND_MEAN
9 public import static "ecere"
14 define ecpDefaultCommand = "ecp";
15 define eccDefaultCommand = "ecc";
16 define ecsDefaultCommand = "ecs";
17 define earDefaultCommand = "ear";
18 define cppDefaultCommand = "gcc"; // As per #624 we decided to default to "gcc"...
19 define ccDefaultCommand = "gcc";
20 define cxxDefaultCommand = "g++";
21 //define ldDefaultCommand = "gcc";
22 define arDefaultCommand = "ar";
23 define objectDefaultFileExt = "o";
24 define outputDefaultFileExt = "";
28 import "OldIDESettings"
32 enum DirTypes { includes, libraries, executables };
34 define defaultCompilerName = "Default";
36 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
38 const char * settingsDirectoryNames[DirTypes] =
45 // This function cannot accept same pointer for source and output
46 // todo: rename ReplaceSpaces to EscapeSpaceAndSpecialChars or something
47 void ReplaceSpaces(char * output, const char * source)
52 for(c = 0, dc = 0; (ch = source[c]); c++, dc++)
54 if(ch == ' ') output[dc++] = '\\';
55 if(ch == '\"') output[dc++] = '\\';
56 if(ch == '&') output[dc++] = '\\';
59 if(ch == '(' || ch == ')') output[dc++] = '\\';
70 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
72 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
73 PathRelationship eString_PathRelated(const char * path, const char * to, char * pathDiff)
75 PathRelationship result;
76 if(pathDiff) *pathDiff = '\0';
77 if(path && *path && to && *to)
79 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
80 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
82 strcpy(pathRest, path);
83 for(; toRest[0] && pathRest[0];)
85 SplitDirectory(toRest, toPart, toRest);
86 SplitDirectory(pathRest, pathPart, pathRest);
87 if(!fstrcmp(pathPart, toPart)) result = siblings;
90 if(result == siblings)
92 if(!*toRest && !*pathRest) result = identical;
93 else if(!*pathRest) result = parentPath;
94 else result = subPath;
95 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
97 else result = unrelated;
103 if(!*path && !*to) result = bothEmpty;
104 else if(!*path) result = pathEmpty;
105 else result = toEmpty;
107 else if(!path && !to) result = bothNull;
108 else if(!path) result = pathNull;
109 else result = toNull;
114 char * CopyValidateMakefilePath(const char * path)
116 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 };
117 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 };
123 len = (int)strlen(path);
124 copy = CopyString(path);
130 Array<const char *> parts { };
137 for(v=0; vars[v]; v++)
139 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
143 parts.Add(vars[map[v]]);
144 c += strlen(vars[v]);
158 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
159 copy = new char[++len];
161 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
172 void ValidPathBufCopy(char *output, const char *input)
175 bool volumePath = false;
177 strcpy(output, input);
178 TrimLSpaces(output, output);
179 TrimRSpaces(output, output);
180 MakeSystemPath(output);
182 if(output[0] && output[1] == ':')
189 const char * chars = "*|:\",<>?";
190 char ch, * s = output, * o = output;
191 while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; }
195 if(volumePath && output[0])
200 void RemoveTrailingPathSeparator(char *path)
203 len = (int)strlen(path);
204 if(len>1 && path[len-1] == DIR_SEP)
208 void BasicValidatePathBoxPath(PathBox pathBox)
210 char path[MAX_LOCATION];
211 ValidPathBufCopy(path, pathBox.path);
212 RemoveTrailingPathSeparator(path);
216 CompilerConfig MakeDefaultCompiler(const char * name, bool readOnly)
218 CompilerConfig defaultCompiler
236 incref defaultCompiler;
237 return defaultCompiler;
241 define settingsName = "ecereIDE-SettingsTest";
243 define ideSettingsName = "ecereIDE";
246 class IDESettingsContainer : GlobalSettings
248 settingsName = ideSettingsName;
250 virtual void OnLoad(GlobalSettingsData data);
252 char moduleLocation[MAX_LOCATION];
255 FileSize settingsFileSize;
257 IDESettingsContainer()
259 char path[MAX_LOCATION];
261 LocateModule(null, moduleLocation);
262 strcpy(path, moduleLocation);
263 StripLastDirectory(moduleLocation, moduleLocation);
264 ChangeCh(moduleLocation, '\\', '/');
265 // PortableApps.com directory structure
266 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
268 char configFilePath[MAX_LOCATION];
269 char defaultConfigFilePath[MAX_LOCATION];
273 strcpy(configFilePath, path);
274 PathCat(configFilePath, "Data");
275 PathCat(configFilePath, ideSettingsName);
276 ChangeExtension(configFilePath, "ini", configFilePath);
278 strcpy(defaultConfigFilePath, path);
279 PathCat(defaultConfigFilePath, "App");
280 PathCat(defaultConfigFilePath, "DefaultData");
281 PathCat(defaultConfigFilePath, ideSettingsName);
282 ChangeExtension(defaultConfigFilePath, "ini", defaultConfigFilePath);
284 if(FileExists(defaultConfigFilePath))
286 if(!FileExists(configFilePath))
288 File f = FileOpen(defaultConfigFilePath, read);
289 f.CopyTo(configFilePath);
293 PathCat(path, "Data");
294 // the forced settings location will only be
295 // used if the running ide's path matches
296 // the PortableApps.com directory structure
297 // and the default ini file is found in
298 // the DefaultData directory
299 settingsLocation = path;
305 void OnAskReloadSettings()
307 FileSize newSettingsFileSize;
309 if(OpenAndLock(&newSettingsFileSize))
311 if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
315 GuiApplication app = ((GuiApplication)__thisModule.application);
317 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
321 MessageBox { master = w, type = ok, isModal = true,
322 creationActivation = flash,
323 text = "Global Settings Modified Externally",
324 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
325 "The new settings will not be loaded to prevent loss of your ide settings.\n"
326 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
332 SettingsIOResult Load()
334 SettingsIOResult result = GlobalSettings::Load();
335 IDESettings data = (IDESettings)this.data;
336 CompilerConfig defaultCompiler = null;
339 this.data = IDESettings { };
341 *dataOwner = this.data;
343 if(result == fileNotCompatibleWithDriver)
346 OldIDESettings oldSettings { };
348 loaded = oldSettings.Load() == success;
352 data = (IDESettings)this.data;
354 for(c : oldSettings.compilerConfigs)
355 data.compilerConfigs.Add(c.Copy());
357 for(s : oldSettings.recentFiles) data.recentFiles.Add(s);
358 for(s : oldSettings.recentProjects) data.recentProjects.Add(s);
360 data.docDir = oldSettings.docDir;
361 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
362 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
363 data.useFreeCaret = oldSettings.useFreeCaret;
364 data.showLineNumbers = oldSettings.showLineNumbers;
365 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
366 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
367 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
368 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
375 if(result == fileNotFound || !data)
377 data = (IDESettings)this.data;
378 data.useFreeCaret = false; //true;
379 data.showLineNumbers = true;
380 data.caretFollowsScrolling = false; //true;
383 // Ensure we have a default compiler
384 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
387 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
388 data.compilerConfigs.Add(defaultCompiler);
391 // We incref the compilers below, so reset refCount to 0
392 defaultCompiler._refCount = 0;
395 FileGetSize(settingsFilePath, &settingsFileSize);
396 if(data.compilerConfigs)
398 for(ccfg : data.compilerConfigs)
400 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
401 ccfg.ecpCommand = ecpDefaultCommand;
402 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
403 ccfg.eccCommand = eccDefaultCommand;
404 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
405 ccfg.ecsCommand = ecsDefaultCommand;
406 if(!ccfg.earCommand || !ccfg.earCommand[0])
407 ccfg.earCommand = earDefaultCommand;
408 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
409 ccfg.cppCommand = cppDefaultCommand;
410 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
411 ccfg.ccCommand = ccDefaultCommand;
412 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
413 ccfg.cxxCommand = cxxDefaultCommand;
414 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
415 ccfg.ldCommand = ldDefaultCommand;*/
416 if(!ccfg.arCommand || !ccfg.arCommand[0])
417 ccfg.arCommand = arDefaultCommand;
418 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
419 ccfg.objectFileExt = objectDefaultFileExt;
420 /*if(!ccfg.outputFileExt || !ccfg.outputFileExt[0])
421 ccfg.outputFileExt = outputDefaultFileExt;*/
425 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
426 data.ManagePortablePaths(moduleLocation, true);
427 data.ForcePathSeparatorStyle(true);
432 SettingsIOResult Save()
434 SettingsIOResult result;
436 IDESettings data = (IDESettings)this.data;
437 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
438 data.ManagePortablePaths(moduleLocation, false);
439 data.ForcePathSeparatorStyle(true);
440 result = GlobalSettings::Save();
441 if(result != success)
442 PrintLn("Error saving IDE settings");
443 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
444 data.ManagePortablePaths(moduleLocation, true);
446 FileGetSize(settingsFilePath, &settingsFileSize);
451 class IDESettings : GlobalSettingsData
454 List<CompilerConfig> compilerConfigs { };
455 RecentPaths recentFiles { };
456 RecentPaths recentProjects { };
457 property const char * docDir
459 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
460 get { return docDir ? docDir : ""; }
461 isset { return docDir && docDir[0]; }
463 property const char * ideFileDialogLocation
465 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
466 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
467 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
469 property const char * ideProjectFileDialogLocation
471 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
472 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
473 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
476 bool showLineNumbers;
477 bool caretFollowsScrolling;
478 char * displayDriver;
480 // TODO: Classify settings
481 //EditorSettings editor { };
483 property const char * projectDefaultTargetDir
485 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
486 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
487 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
489 property const char * projectDefaultIntermediateObjDir
491 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
492 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
493 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
496 property const char * compilerConfigsDir
498 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
499 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
500 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
503 property const char * defaultCompiler
505 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
506 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
507 isset { return defaultCompiler && defaultCompiler[0]; }
510 property const String language
515 language = CopyString(value);
517 get { return language; }
518 isset { return language != null; }
523 char * ideFileDialogLocation;
524 char * ideProjectFileDialogLocation;
525 char * projectDefaultTargetDir;
526 char * projectDefaultIntermediateObjDir;
527 char * compilerConfigsDir;
528 char * defaultCompiler;
531 CompilerConfig GetCompilerConfig(const String compilerName)
533 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
534 CompilerConfig compilerConfig = null;
535 for(compiler : compilerConfigs)
537 if(!strcmp(compiler.name, name))
539 compilerConfig = compiler;
543 if(!compilerConfig && compilerConfigs.count)
544 compilerConfig = compilerConfigs.firstIterator.data;
546 incref compilerConfig;
547 return compilerConfig;
552 compilerConfigs.Free();
553 delete compilerConfigs;
554 if(recentProjects) { recentFiles.Free(); delete recentFiles; }
555 if(recentProjects) { recentProjects.Free(); delete recentProjects; }
558 delete projectDefaultTargetDir;
559 delete projectDefaultIntermediateObjDir;
560 delete compilerConfigsDir;
561 delete defaultCompiler;
564 delete ideFileDialogLocation;
565 delete ideProjectFileDialogLocation;
566 delete displayDriver;
569 void ForcePathSeparatorStyle(bool unixStyle)
573 from = '\\', to = '/';
575 from = '/', to = '\\';
576 if(compilerConfigs && compilerConfigs.count)
579 for(config : compilerConfigs)
581 if(config.includeDirs && config.includeDirs.count)
583 for(i = 0; i < config.includeDirs.count; i++)
585 if(config.includeDirs[i] && config.includeDirs[i][0])
586 ChangeCh(config.includeDirs[i], from, to);
589 if(config.libraryDirs && config.libraryDirs.count)
591 for(i = 0; i < config.libraryDirs.count; i++)
593 if(config.libraryDirs[i] && config.libraryDirs[i][0])
594 ChangeCh(config.libraryDirs[i], from, to);
597 if(config.executableDirs && config.executableDirs.count)
599 for(i = 0; i < config.executableDirs.count; i++)
601 if(config.executableDirs[i] && config.executableDirs[i][0])
602 ChangeCh(config.executableDirs[i], from, to);
607 recentFiles.changeChar(from, to);
608 recentProjects.changeChar(from, to);
609 if(docDir && docDir[0])
610 ChangeCh(docDir, from, to);
611 if(ideFileDialogLocation && ideFileDialogLocation[0])
612 ChangeCh(ideFileDialogLocation, from, to);
613 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
614 ChangeCh(ideProjectFileDialogLocation, from, to);
616 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
617 ChangeCh(projectDefaultTargetDir, from, to);
618 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
619 ChangeCh(projectDefaultIntermediateObjDir, from, to);
621 if(compilerConfigsDir && compilerConfigsDir[0])
622 ChangeCh(compilerConfigsDir, from, to);
625 void ManagePortablePaths(char * location, bool makeAbsolute)
628 if(compilerConfigs && compilerConfigs.count)
630 for(config : compilerConfigs)
633 for(t = 0; t < DirTypes::enumSize; t++)
635 Array<String> dirs = null;
636 if(t == executables) dirs = config.executableDirs;
637 else if(t == includes) dirs = config.includeDirs;
638 else if(t == libraries) dirs = config.libraryDirs;
639 if(dirs && dirs.count)
641 for(c = 0; c < dirs.count; c++)
643 if(dirs[c] && dirs[c][0])
644 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
650 if(recentFiles && recentFiles.count)
652 for(c = 0; c < recentFiles.count; c++)
654 if(recentFiles[c] && recentFiles[c][0])
655 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
658 if(recentProjects && recentProjects.count)
660 for(c = 0; c < recentProjects.count; c++)
662 if(recentProjects[c] && recentProjects[c][0])
663 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
666 if(docDir && docDir[0])
667 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
668 if(ideFileDialogLocation && ideFileDialogLocation[0])
669 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
670 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
671 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
673 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
674 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
675 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
676 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
678 if(compilerConfigsDir && compilerConfigsDir[0])
679 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
682 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
687 char p[MAX_LOCATION];
689 PathCatSlash(p, path);
691 output = CopyString(p);
695 PathRelationship rel = eString_PathRelated(path, location, null);
696 if(rel == subPath || rel == identical)
698 char p[MAX_LOCATION];
699 MakePathRelative(path, location, p);
700 if(!*p) strcpy(p, "./");
701 else ChangeCh(p, '\\', '/');
703 output = CopyString(p);
712 class RecentPaths : Array<String>
714 IteratorPointer Add(T value)
717 char * filePath = (char *)value;
718 ChangeCh(filePath, '\\', '/');
719 for(c = 0; c < count; c++)
721 if(this[c] && !fstrcmp(this[c], filePath))
723 Delete((void *)&this[c]);
727 return Array::Add((T)filePath);
730 IteratorPointer addRecent(T value)
733 char * filePath = (char *)value;
734 ChangeCh(filePath, '\\', '/');
735 for(c = 0; c < count; c++)
737 if(this[c] && !fstrcmp(this[c], filePath))
739 Delete((void *)&this[c]);
743 while(count >= MaxRecent)
745 return Insert(null, filePath);
748 void changeChar(char from, char to)
753 for(c = 0; c < count; c++)
755 if(this[c] && this[c][0])
756 ChangeCh(this[c], from, to);
762 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
763 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
764 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
765 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
766 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
767 // TODO: i18n with Array
768 static Array<const String> compilerTypeLongNames
770 $"GNU Compiler Collection (GCC) / GNU Make",
771 $"Tiny C Compiler / GNU Make",
772 $"Portable C Compiler / GNU Make",
773 $"Microsoft Visual Studio 2005 (8.0) Compiler",
774 $"Microsoft Visual Studio 2008 (9.0) Compiler",
775 $"Microsoft Visual Studio 2010 (10.0) Compiler"
777 const CompilerType firstCompilerType = gcc;
778 const CompilerType lastCompilerType = vs10;
779 public enum CompilerType
781 gcc, tcc, pcc, vs8, vs9, vs10;
785 get { return this == vs8 || this == vs9 || this == vs10; }
788 property const char *
790 get { return OnGetString(null, null, null); }
796 for(c = firstCompilerType; c <= lastCompilerType; c++)
797 if(!strcmpi(value, compilerTypeNames[c]))
804 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
805 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
806 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
807 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
808 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
810 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
812 if(this >= firstCompilerType && this <= lastCompilerType)
815 strcpy(tempString, compilerTypeNames[this]);
816 if(fieldData == null)
817 return compilerTypeNames[this];
818 else if(fieldData == (void*)1)
819 return compilerTypeLongNames[this];
820 else if(fieldData == (void*)2)
821 return compilerTypeVersionString[this];
822 else if(fieldData == (void*)3)
823 return compilerTypeYearString[this];
824 else if(fieldData == (void*)4)
825 return compilerTypeProjectFileExtension[this];
826 else if(fieldData == (void*)5)
827 return compilerTypeSolutionFileVersionString[this];
839 property const char * name
845 name = CopyString(value);
851 Platform targetPlatform;
853 property const char * makeCommand
855 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
856 get { return makeCommand; }
857 isset { return makeCommand && makeCommand[0]; }
859 property const char * ecpCommand
861 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
862 get { return ecpCommand; }
863 isset { return ecpCommand && ecpCommand[0]; }
865 property const char * eccCommand
867 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
868 get { return eccCommand; }
869 isset { return eccCommand && eccCommand[0]; }
871 property const char * ecsCommand
873 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
874 get { return ecsCommand; }
875 isset { return ecsCommand && ecsCommand[0]; }
877 property const char * earCommand
879 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
880 get { return earCommand; }
881 isset { return earCommand && earCommand[0]; }
883 property const char * cppCommand
885 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
886 get { return cppCommand; }
887 isset { return cppCommand && cppCommand[0]; }
889 property const char * ccCommand
891 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
892 get { return ccCommand; }
893 isset { return ccCommand && ccCommand[0]; }
895 property const char * cxxCommand
897 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
898 get { return cxxCommand; }
899 isset { return cxxCommand && cxxCommand[0]; }
901 property const char * arCommand
903 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
904 get { return arCommand; }
905 isset { return arCommand && arCommand[0]; }
907 property const char * ldCommand
909 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
910 get { return ldCommand; }
911 isset { return ldCommand && ldCommand[0]; }
913 property const char * objectFileExt
915 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
916 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
917 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
919 property const char * outputFileExt
921 set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
922 get { return outputFileExt; }
923 isset { return outputFileExt && outputFileExt[0]; }
925 property const char * executableLauncher
927 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
928 get { return executableLauncher; }
929 isset { return executableLauncher && executableLauncher[0]; }
931 // TODO: implement CompilerConfig::windresCommand
935 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
937 property const char * distccHosts
939 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
940 get { return distccHosts; }
941 isset { return distccHosts && distccHosts[0]; }
943 property const char * gnuToolchainPrefix
945 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
946 get { return gnuToolchainPrefix; }
947 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
949 property const char * sysroot
951 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
952 get { return sysroot; }
953 isset { return sysroot && sysroot[0]; }
955 bool resourcesDotEar;
956 property Array<String> includeDirs
967 get { return includeDirs; }
968 isset { return includeDirs.count != 0; }
970 property Array<String> libraryDirs
981 get { return libraryDirs; }
982 isset { return libraryDirs.count != 0; }
984 property Array<String> executableDirs
988 executableDirs.Free();
991 delete executableDirs;
992 executableDirs = value;
995 get { return executableDirs; }
996 isset { return executableDirs.count != 0; }
998 property Array<NamedString> environmentVars
1002 environmentVars.Free();
1005 delete environmentVars;
1006 environmentVars = value;
1009 get { return environmentVars; }
1010 isset { return environmentVars.count != 0; }
1012 property Array<String> prepDirectives
1016 prepDirectives.Free();
1019 delete prepDirectives;
1020 prepDirectives = value;
1023 get { return prepDirectives; }
1024 isset { return prepDirectives.count != 0; }
1026 property Array<String> excludeLibs
1034 excludeLibs = value;
1037 get { return excludeLibs; }
1038 isset { return excludeLibs.count != 0; }
1040 property Array<String> eCcompilerFlags
1044 eCcompilerFlags.Free();
1047 delete eCcompilerFlags;
1048 eCcompilerFlags = value;
1051 get { return eCcompilerFlags; }
1052 isset { return eCcompilerFlags.count != 0; }
1054 property Array<String> compilerFlags
1058 compilerFlags.Free();
1061 delete compilerFlags;
1062 compilerFlags = value;
1065 get { return compilerFlags; }
1066 isset { return compilerFlags.count != 0; }
1068 property Array<String> linkerFlags
1076 linkerFlags = value;
1079 get { return linkerFlags; }
1080 isset { return linkerFlags.count != 0; }
1082 // json backward compatibility
1083 property const char * gccPrefix
1085 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1086 get { return gnuToolchainPrefix; }
1087 isset { return false; }
1089 property const char * execPrefixCommand
1091 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1092 get { return executableLauncher; }
1093 isset { return false; }
1096 Array<String> includeDirs { };
1097 Array<String> libraryDirs { };
1098 Array<String> executableDirs { };
1099 // TODO: Can JSON parse and serialize maps?
1100 //EnvironmentVariables { };
1101 Array<NamedString> environmentVars { };
1102 Array<String> prepDirectives { };
1103 Array<String> excludeLibs { };
1104 Array<String> eCcompilerFlags { };
1105 Array<String> compilerFlags { };
1106 Array<String> linkerFlags { };
1118 char * objectFileExt;
1119 char * outputFileExt;
1120 char * executableLauncher;
1122 char * gnuToolchainPrefix;
1126 struct { Array<String> includes, libraries, executables; };
1127 Array<String> dirs[DirTypes];
1142 delete objectFileExt;
1143 delete outputFileExt;
1145 delete executableLauncher;
1147 delete gnuToolchainPrefix;
1149 if(environmentVars) environmentVars.Free();
1150 if(includeDirs) { includeDirs.Free(); }
1151 if(libraryDirs) { libraryDirs.Free(); }
1152 if(executableDirs) { executableDirs.Free(); }
1153 if(prepDirectives) { prepDirectives.Free(); }
1154 if(excludeLibs) { excludeLibs.Free(); }
1155 if(compilerFlags) { compilerFlags.Free(); }
1156 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1157 if(linkerFlags) { linkerFlags.Free(); }
1161 CompilerConfig Copy()
1191 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1192 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1193 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1194 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1195 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1196 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1197 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1198 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1199 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1206 struct LanguageOption
1209 const String bitmap;
1213 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1218 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1220 Bitmap icon = res ? res.bitmap : null;
1223 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1224 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1228 Array<LanguageOption> languages
1230 { "English", ":countryCode/gb.png", "" },
1231 { "汉语", ":countryCode/cn.png", "zh_CN" },
1232 { "Español", ":countryCode/es.png", "es" },
1233 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1234 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1235 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1236 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1237 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1238 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1239 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1242 const String GetLanguageString()
1244 char * dot, * colon;
1245 static char lang[256];
1246 const String language = getenv("ECERE_LANGUAGE");
1247 if(!language) language = getenv("LANGUAGE");
1248 if(!language) language = getenv("LC_ALL");
1249 if(!language) language = getenv("LC_MESSAGES");
1250 if(!language) language = getenv("LANG");
1251 if(!language) language = "";
1252 if(language && (colon = strchr(language, ':')))
1254 if(lang != language)
1255 strncpy(lang, language, sizeof(lang));
1256 lang[sizeof(lang)-1] = 0;
1257 lang[colon - language] = 0;
1260 if(language && (dot = strchr(language, '.')))
1262 if(lang != language)
1263 strncpy(lang, language, sizeof(lang));
1264 lang[sizeof(lang)-1] = 0;
1265 lang[dot - language] = 0;
1271 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1273 bool restart = true;
1274 String command = null;
1275 int arg0Len = (int)strlen(app.argv[0]);
1287 for(w = ide.firstChild; w; w = w.next)
1289 if(w.isActiveClient && w.isDocument)
1291 if(!w.CloseConfirmation(true))
1300 if(!projectView.CloseConfirmation(true))
1302 if(projectView.fileName)
1304 const char * name = projectView.fileName;
1307 for(j = 0; (ch = name[j]); j++)
1308 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1312 command = new char[len + 1];
1314 strcpy(command, app.argv[0]);
1316 if(projectView.fileName)
1318 strcat(command, " ");
1320 ReplaceSpaces(command + len, projectView.fileName);
1325 for(w = ide.firstChild; w; w = w.next)
1326 if(w.isActiveClient && w.isDocument)
1327 w.modifiedDocument = false;
1328 projectView.modifiedDocument = false;
1333 for(w = ide.firstChild; w; w = w.next)
1335 if(w.isActiveClient && w.isDocument)
1337 if(!w.CloseConfirmation(true))
1344 const char * name = w.fileName;
1346 for(j = 0; (ch = name[j]); j++)
1347 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1354 command = new char[len + 1];
1355 strcpy(command, app.argv[0]);
1358 for(w = ide.firstChild; w; w = w.next)
1360 if(w.isActiveClient && w.isDocument)
1362 const char * name = w.fileName;
1365 strcat(command, " ");
1367 ReplaceSpaces(command + len, name);
1368 len = (int)strlen(command);
1375 for(w = ide.firstChild; w; w = w.next)
1376 if(w.isActiveClient && w.isDocument)
1377 w.modifiedDocument = false;
1382 settings.language = code;
1383 settingsContainer.Save();
1385 #if defined(__WIN32__)
1386 // Set LANGUAGE environment variable
1389 uint16 wLanguage[256];
1393 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1396 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1397 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1403 if(eClass_IsDerived(app._class, class(GuiApplication)))
1405 GuiApplication guiApp = (GuiApplication)app;
1406 guiApp.desktop.Destroy(0);
1413 for(i = 1; i < app.argc; i++)
1415 const char * arg = app.argv[i];
1417 for(j = 0; (ch = arg[j]); j++)
1418 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1421 command = new char[len + 1];
1422 strcpy(command, app.argv[0]);
1424 for(i = 1; i < app.argc; i++)
1426 strcat(command, " ");
1428 ReplaceSpaces(command + len, app.argv[i]);
1429 len = (int)strlen(command);
1435 SetEnvironment("ECERE_LANGUAGE", code);
1437 ExecuteWait(command);