2 public import static "ecere"
7 define ecpDefaultCommand = "ecp";
8 define eccDefaultCommand = "ecc";
9 define ecsDefaultCommand = "ecs";
10 define earDefaultCommand = "ear";
11 define cppDefaultCommand = "gcc"; // As per #624 we decided to default to "gcc"...
12 define ccDefaultCommand = "gcc";
13 define cxxDefaultCommand = "g++";
14 //define ldDefaultCommand = "gcc";
15 define arDefaultCommand = "ar";
16 define objectDefaultFileExt = "o";
17 define outputDefaultFileExt = "";
21 import "OldIDESettings"
23 #if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
29 enum DirTypes { includes, libraries, executables };
31 define defaultCompilerName = "Default";
33 define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)";
35 const char * settingsDirectoryNames[DirTypes] =
42 // This function cannot accept same pointer for source and output
43 // todo: rename ReplaceSpaces to EscapeSpaceAndSpecialChars or something
44 void ReplaceSpaces(char * output, const char * source)
49 for(c = 0, dc = 0; (ch = source[c]); c++, dc++)
51 if(ch == ' ') output[dc++] = '\\';
52 if(ch == '\"') output[dc++] = '\\';
53 if(ch == '&') output[dc++] = '\\';
56 if(ch == '(' || ch == ')') output[dc++] = '\\';
67 enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings };
69 enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull };
70 PathRelationship eString_PathRelated(const char * path, const char * to, char * pathDiff)
72 PathRelationship result;
73 if(pathDiff) *pathDiff = '\0';
74 if(path && *path && to && *to)
76 char toPart[MAX_FILENAME], toRest[MAX_LOCATION];
77 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
79 strcpy(pathRest, path);
80 for(; toRest[0] && pathRest[0];)
82 SplitDirectory(toRest, toPart, toRest);
83 SplitDirectory(pathRest, pathPart, pathRest);
84 if(!fstrcmp(pathPart, toPart)) result = siblings;
87 if(result == siblings)
89 if(!*toRest && !*pathRest) result = identical;
90 else if(!*pathRest) result = parentPath;
91 else result = subPath;
92 if(pathDiff && result != identical) strcpy(pathDiff, *pathRest == '\0' ? toRest : pathRest);
94 else result = unrelated;
100 if(!*path && !*to) result = bothEmpty;
101 else if(!*path) result = pathEmpty;
102 else result = toEmpty;
104 else if(!path && !to) result = bothNull;
105 else if(!path) result = pathNull;
106 else result = toNull;
111 char * CopyValidateMakefilePath(const char * path)
113 const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 };
114 const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 };
120 len = (int)strlen(path);
121 copy = CopyString(path);
127 Array<const char *> parts { };
134 for(v=0; vars[v]; v++)
136 if(SearchString(&tmp[c], 0, vars[v], false, false) == &tmp[c])
140 parts.Add(vars[map[v]]);
141 c += strlen(vars[v]);
155 for(c=0; c<parts.count; c++) len += strlen(parts[c]);
156 copy = new char[++len];
158 for(c=0; c<parts.count; c++) strcat(copy, parts[c]);
169 void ValidPathBufCopy(char *output, const char *input)
172 bool volumePath = false;
174 strcpy(output, input);
175 TrimLSpaces(output, output);
176 TrimRSpaces(output, output);
177 MakeSystemPath(output);
179 if(output[0] && output[1] == ':')
186 const char * chars = "*|:\",<>?";
187 char ch, * s = output, * o = output;
188 while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; }
192 if(volumePath && output[0])
197 void RemoveTrailingPathSeparator(char *path)
200 len = (int)strlen(path);
201 if(len>1 && path[len-1] == DIR_SEP)
205 void BasicValidatePathBoxPath(PathBox pathBox)
207 char path[MAX_LOCATION];
208 ValidPathBufCopy(path, pathBox.path);
209 RemoveTrailingPathSeparator(path);
213 CompilerConfig MakeDefaultCompiler(const char * name, bool readOnly)
215 CompilerConfig defaultCompiler
233 incref defaultCompiler;
234 return defaultCompiler;
238 define settingsName = "ecereIDE-SettingsTest";
240 define ideSettingsName = "ecereIDE";
243 class IDESettingsContainer : GlobalSettings
245 settingsName = ideSettingsName;
247 virtual void OnLoad(GlobalSettingsData data);
249 char moduleLocation[MAX_LOCATION];
252 FileSize settingsFileSize;
254 IDESettingsContainer()
256 char path[MAX_LOCATION];
258 LocateModule(null, moduleLocation);
259 strcpy(path, moduleLocation);
260 StripLastDirectory(moduleLocation, moduleLocation);
261 ChangeCh(moduleLocation, '\\', '/');
262 // PortableApps.com directory structure
263 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
265 char configFilePath[MAX_LOCATION];
266 char defaultConfigFilePath[MAX_LOCATION];
270 strcpy(configFilePath, path);
271 PathCat(configFilePath, "Data");
272 PathCat(configFilePath, ideSettingsName);
273 ChangeExtension(configFilePath, "ini", configFilePath);
275 strcpy(defaultConfigFilePath, path);
276 PathCat(defaultConfigFilePath, "App");
277 PathCat(defaultConfigFilePath, "DefaultData");
278 PathCat(defaultConfigFilePath, ideSettingsName);
279 ChangeExtension(defaultConfigFilePath, "ini", defaultConfigFilePath);
281 if(FileExists(defaultConfigFilePath))
283 if(!FileExists(configFilePath))
285 File f = FileOpen(defaultConfigFilePath, read);
286 f.CopyTo(configFilePath);
290 PathCat(path, "Data");
291 // the forced settings location will only be
292 // used if the running ide's path matches
293 // the PortableApps.com directory structure
294 // and the default ini file is found in
295 // the DefaultData directory
296 settingsLocation = path;
302 void OnAskReloadSettings()
304 FileSize newSettingsFileSize;
306 if(OpenAndLock(&newSettingsFileSize))
308 if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
312 GuiApplication app = ((GuiApplication)__thisModule.application);
314 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
318 MessageBox { master = w, type = ok, isModal = true,
319 creationActivation = flash,
320 text = "Global Settings Modified Externally",
321 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
322 "The new settings will not be loaded to prevent loss of your ide settings.\n"
323 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
329 SettingsIOResult Load()
331 SettingsIOResult result = GlobalSettings::Load();
332 IDESettings data = (IDESettings)this.data;
333 CompilerConfig defaultCompiler = null;
336 this.data = IDESettings { };
338 *dataOwner = this.data;
340 if(result == fileNotCompatibleWithDriver)
343 OldIDESettings oldSettings { };
345 loaded = oldSettings.Load() == success;
349 data = (IDESettings)this.data;
351 for(c : oldSettings.compilerConfigs)
352 data.compilerConfigs.Add(c.Copy());
354 for(s : oldSettings.recentFiles) data.recentFiles.Add(s);
355 for(s : oldSettings.recentProjects) data.recentProjects.Add(s);
357 data.docDir = oldSettings.docDir;
358 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
359 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
360 data.useFreeCaret = oldSettings.useFreeCaret;
361 data.showLineNumbers = oldSettings.showLineNumbers;
362 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
363 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
364 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
365 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
372 if(result == fileNotFound || !data)
374 data = (IDESettings)this.data;
375 data.useFreeCaret = false; //true;
376 data.showLineNumbers = true;
377 data.caretFollowsScrolling = false; //true;
380 // Ensure we have a default compiler
381 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
384 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
385 data.compilerConfigs.Add(defaultCompiler);
388 // We incref the compilers below, so reset refCount to 0
389 defaultCompiler._refCount = 0;
392 FileGetSize(settingsFilePath, &settingsFileSize);
393 if(data.compilerConfigs)
395 for(ccfg : data.compilerConfigs)
397 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
398 ccfg.ecpCommand = ecpDefaultCommand;
399 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
400 ccfg.eccCommand = eccDefaultCommand;
401 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
402 ccfg.ecsCommand = ecsDefaultCommand;
403 if(!ccfg.earCommand || !ccfg.earCommand[0])
404 ccfg.earCommand = earDefaultCommand;
405 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
406 ccfg.cppCommand = cppDefaultCommand;
407 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
408 ccfg.ccCommand = ccDefaultCommand;
409 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
410 ccfg.cxxCommand = cxxDefaultCommand;
411 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
412 ccfg.ldCommand = ldDefaultCommand;*/
413 if(!ccfg.arCommand || !ccfg.arCommand[0])
414 ccfg.arCommand = arDefaultCommand;
415 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
416 ccfg.objectFileExt = objectDefaultFileExt;
417 /*if(!ccfg.outputFileExt || !ccfg.outputFileExt[0])
418 ccfg.outputFileExt = outputDefaultFileExt;*/
422 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
423 data.ManagePortablePaths(moduleLocation, true);
424 data.ForcePathSeparatorStyle(true);
429 SettingsIOResult Save()
431 SettingsIOResult result;
433 IDESettings data = (IDESettings)this.data;
434 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
435 data.ManagePortablePaths(moduleLocation, false);
436 data.ForcePathSeparatorStyle(true);
437 result = GlobalSettings::Save();
438 if(result != success)
439 PrintLn("Error saving IDE settings");
440 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
441 data.ManagePortablePaths(moduleLocation, true);
443 FileGetSize(settingsFilePath, &settingsFileSize);
448 class IDESettings : GlobalSettingsData
451 List<CompilerConfig> compilerConfigs { };
452 RecentPaths recentFiles { };
453 RecentPaths recentProjects { };
454 property const char * docDir
456 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
457 get { return docDir ? docDir : ""; }
458 isset { return docDir && docDir[0]; }
460 property const char * ideFileDialogLocation
462 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
463 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
464 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
466 property const char * ideProjectFileDialogLocation
468 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
469 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
470 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
473 bool showLineNumbers;
474 bool caretFollowsScrolling;
475 char * displayDriver;
477 // TODO: Classify settings
478 //EditorSettings editor { };
480 property const char * projectDefaultTargetDir
482 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
483 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
484 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
486 property const char * projectDefaultIntermediateObjDir
488 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
489 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
490 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
493 property const char * compilerConfigsDir
495 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
496 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
497 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
500 property const char * defaultCompiler
502 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
503 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
504 isset { return defaultCompiler && defaultCompiler[0]; }
507 property const String language
512 language = CopyString(value);
514 get { return language; }
515 isset { return language != null; }
520 char * ideFileDialogLocation;
521 char * ideProjectFileDialogLocation;
522 char * projectDefaultTargetDir;
523 char * projectDefaultIntermediateObjDir;
524 char * compilerConfigsDir;
525 char * defaultCompiler;
528 CompilerConfig GetCompilerConfig(const String compilerName)
530 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
531 CompilerConfig compilerConfig = null;
532 for(compiler : compilerConfigs)
534 if(!strcmp(compiler.name, name))
536 compilerConfig = compiler;
540 if(!compilerConfig && compilerConfigs.count)
541 compilerConfig = compilerConfigs.firstIterator.data;
543 incref compilerConfig;
544 return compilerConfig;
549 compilerConfigs.Free();
550 delete compilerConfigs;
551 if(recentProjects) { recentFiles.Free(); delete recentFiles; }
552 if(recentProjects) { recentProjects.Free(); delete recentProjects; }
555 delete projectDefaultTargetDir;
556 delete projectDefaultIntermediateObjDir;
557 delete compilerConfigsDir;
558 delete defaultCompiler;
561 delete ideFileDialogLocation;
562 delete ideProjectFileDialogLocation;
563 delete displayDriver;
566 void ForcePathSeparatorStyle(bool unixStyle)
570 from = '\\', to = '/';
572 from = '/', to = '\\';
573 if(compilerConfigs && compilerConfigs.count)
576 for(config : compilerConfigs)
578 if(config.includeDirs && config.includeDirs.count)
580 for(i = 0; i < config.includeDirs.count; i++)
582 if(config.includeDirs[i] && config.includeDirs[i][0])
583 ChangeCh(config.includeDirs[i], from, to);
586 if(config.libraryDirs && config.libraryDirs.count)
588 for(i = 0; i < config.libraryDirs.count; i++)
590 if(config.libraryDirs[i] && config.libraryDirs[i][0])
591 ChangeCh(config.libraryDirs[i], from, to);
594 if(config.executableDirs && config.executableDirs.count)
596 for(i = 0; i < config.executableDirs.count; i++)
598 if(config.executableDirs[i] && config.executableDirs[i][0])
599 ChangeCh(config.executableDirs[i], from, to);
604 recentFiles.changeChar(from, to);
605 recentProjects.changeChar(from, to);
606 if(docDir && docDir[0])
607 ChangeCh(docDir, from, to);
608 if(ideFileDialogLocation && ideFileDialogLocation[0])
609 ChangeCh(ideFileDialogLocation, from, to);
610 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
611 ChangeCh(ideProjectFileDialogLocation, from, to);
613 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
614 ChangeCh(projectDefaultTargetDir, from, to);
615 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
616 ChangeCh(projectDefaultIntermediateObjDir, from, to);
618 if(compilerConfigsDir && compilerConfigsDir[0])
619 ChangeCh(compilerConfigsDir, from, to);
622 void ManagePortablePaths(char * location, bool makeAbsolute)
625 if(compilerConfigs && compilerConfigs.count)
627 for(config : compilerConfigs)
630 for(t = 0; t < DirTypes::enumSize; t++)
632 Array<String> dirs = null;
633 if(t == executables) dirs = config.executableDirs;
634 else if(t == includes) dirs = config.includeDirs;
635 else if(t == libraries) dirs = config.libraryDirs;
636 if(dirs && dirs.count)
638 for(c = 0; c < dirs.count; c++)
640 if(dirs[c] && dirs[c][0])
641 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
647 if(recentFiles && recentFiles.count)
649 for(c = 0; c < recentFiles.count; c++)
651 if(recentFiles[c] && recentFiles[c][0])
652 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
655 if(recentProjects && recentProjects.count)
657 for(c = 0; c < recentProjects.count; c++)
659 if(recentProjects[c] && recentProjects[c][0])
660 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
663 if(docDir && docDir[0])
664 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
665 if(ideFileDialogLocation && ideFileDialogLocation[0])
666 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
667 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
668 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
670 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
671 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
672 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
673 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
675 if(compilerConfigsDir && compilerConfigsDir[0])
676 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
679 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
684 char p[MAX_LOCATION];
686 PathCatSlash(p, path);
688 output = CopyString(p);
692 PathRelationship rel = eString_PathRelated(path, location, null);
693 if(rel == subPath || rel == identical)
695 char p[MAX_LOCATION];
696 MakePathRelative(path, location, p);
697 if(!*p) strcpy(p, "./");
698 else ChangeCh(p, '\\', '/');
700 output = CopyString(p);
709 class RecentPaths : Array<String>
711 IteratorPointer Add(T value)
714 char * filePath = (char *)value;
715 ChangeCh(filePath, '\\', '/');
716 for(c = 0; c < count; c++)
718 if(this[c] && !fstrcmp(this[c], filePath))
720 Delete((void *)&this[c]);
724 return Array::Add((T)filePath);
727 IteratorPointer addRecent(T value)
730 char * filePath = (char *)value;
731 ChangeCh(filePath, '\\', '/');
732 for(c = 0; c < count; c++)
734 if(this[c] && !fstrcmp(this[c], filePath))
736 Delete((void *)&this[c]);
740 while(count >= MaxRecent)
742 return Insert(null, filePath);
745 void changeChar(char from, char to)
750 for(c = 0; c < count; c++)
752 if(this[c] && this[c][0])
753 ChangeCh(this[c], from, to);
759 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
760 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
761 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
762 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
763 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
764 // TODO: i18n with Array
765 static Array<const String> compilerTypeLongNames
767 $"GNU Compiler Collection (GCC) / GNU Make",
768 $"Tiny C Compiler / GNU Make",
769 $"Portable C Compiler / GNU Make",
770 $"Microsoft Visual Studio 2005 (8.0) Compiler",
771 $"Microsoft Visual Studio 2008 (9.0) Compiler",
772 $"Microsoft Visual Studio 2010 (10.0) Compiler"
774 const CompilerType firstCompilerType = gcc;
775 const CompilerType lastCompilerType = vs10;
776 public enum CompilerType
778 gcc, tcc, pcc, vs8, vs9, vs10;
782 get { return this == vs8 || this == vs9 || this == vs10; }
785 property const char *
787 get { return OnGetString(null, null, null); }
793 for(c = firstCompilerType; c <= lastCompilerType; c++)
794 if(!strcmpi(value, compilerTypeNames[c]))
801 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
802 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
803 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
804 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
805 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
807 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
809 if(this >= firstCompilerType && this <= lastCompilerType)
812 strcpy(tempString, compilerTypeNames[this]);
813 if(fieldData == null)
814 return compilerTypeNames[this];
815 else if(fieldData == (void*)1)
816 return compilerTypeLongNames[this];
817 else if(fieldData == (void*)2)
818 return compilerTypeVersionString[this];
819 else if(fieldData == (void*)3)
820 return compilerTypeYearString[this];
821 else if(fieldData == (void*)4)
822 return compilerTypeProjectFileExtension[this];
823 else if(fieldData == (void*)5)
824 return compilerTypeSolutionFileVersionString[this];
836 property const char * name
842 name = CopyString(value);
848 Platform targetPlatform;
850 property const char * makeCommand
852 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
853 get { return makeCommand; }
854 isset { return makeCommand && makeCommand[0]; }
856 property const char * ecpCommand
858 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
859 get { return ecpCommand; }
860 isset { return ecpCommand && ecpCommand[0]; }
862 property const char * eccCommand
864 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
865 get { return eccCommand; }
866 isset { return eccCommand && eccCommand[0]; }
868 property const char * ecsCommand
870 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
871 get { return ecsCommand; }
872 isset { return ecsCommand && ecsCommand[0]; }
874 property const char * earCommand
876 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
877 get { return earCommand; }
878 isset { return earCommand && earCommand[0]; }
880 property const char * cppCommand
882 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
883 get { return cppCommand; }
884 isset { return cppCommand && cppCommand[0]; }
886 property const char * ccCommand
888 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
889 get { return ccCommand; }
890 isset { return ccCommand && ccCommand[0]; }
892 property const char * cxxCommand
894 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
895 get { return cxxCommand; }
896 isset { return cxxCommand && cxxCommand[0]; }
898 property const char * arCommand
900 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
901 get { return arCommand; }
902 isset { return arCommand && arCommand[0]; }
904 property const char * ldCommand
906 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
907 get { return ldCommand; }
908 isset { return ldCommand && ldCommand[0]; }
910 property const char * objectFileExt
912 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
913 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
914 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
916 property const char * outputFileExt
918 set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
919 get { return outputFileExt; }
920 isset { return outputFileExt && outputFileExt[0]; }
922 property const char * executableLauncher
924 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
925 get { return executableLauncher; }
926 isset { return executableLauncher && executableLauncher[0]; }
928 // TODO: implement CompilerConfig::windresCommand
932 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
934 property const char * distccHosts
936 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
937 get { return distccHosts; }
938 isset { return distccHosts && distccHosts[0]; }
940 property const char * gnuToolchainPrefix
942 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
943 get { return gnuToolchainPrefix; }
944 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
946 property const char * sysroot
948 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
949 get { return sysroot; }
950 isset { return sysroot && sysroot[0]; }
952 bool resourcesDotEar;
953 property Array<String> includeDirs
964 get { return includeDirs; }
965 isset { return includeDirs.count != 0; }
967 property Array<String> libraryDirs
978 get { return libraryDirs; }
979 isset { return libraryDirs.count != 0; }
981 property Array<String> executableDirs
985 executableDirs.Free();
988 delete executableDirs;
989 executableDirs = value;
992 get { return executableDirs; }
993 isset { return executableDirs.count != 0; }
995 property Array<NamedString> environmentVars
999 environmentVars.Free();
1002 delete environmentVars;
1003 environmentVars = value;
1006 get { return environmentVars; }
1007 isset { return environmentVars.count != 0; }
1009 property Array<String> prepDirectives
1013 prepDirectives.Free();
1016 delete prepDirectives;
1017 prepDirectives = value;
1020 get { return prepDirectives; }
1021 isset { return prepDirectives.count != 0; }
1023 property Array<String> excludeLibs
1031 excludeLibs = value;
1034 get { return excludeLibs; }
1035 isset { return excludeLibs.count != 0; }
1037 property Array<String> eCcompilerFlags
1041 eCcompilerFlags.Free();
1044 delete eCcompilerFlags;
1045 eCcompilerFlags = value;
1048 get { return eCcompilerFlags; }
1049 isset { return eCcompilerFlags.count != 0; }
1051 property Array<String> compilerFlags
1055 compilerFlags.Free();
1058 delete compilerFlags;
1059 compilerFlags = value;
1062 get { return compilerFlags; }
1063 isset { return compilerFlags.count != 0; }
1065 property Array<String> linkerFlags
1073 linkerFlags = value;
1076 get { return linkerFlags; }
1077 isset { return linkerFlags.count != 0; }
1079 // json backward compatibility
1080 property const char * gccPrefix
1082 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1083 get { return gnuToolchainPrefix; }
1084 isset { return false; }
1086 property const char * execPrefixCommand
1088 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1089 get { return executableLauncher; }
1090 isset { return false; }
1093 Array<String> includeDirs { };
1094 Array<String> libraryDirs { };
1095 Array<String> executableDirs { };
1096 // TODO: Can JSON parse and serialize maps?
1097 //EnvironmentVariables { };
1098 Array<NamedString> environmentVars { };
1099 Array<String> prepDirectives { };
1100 Array<String> excludeLibs { };
1101 Array<String> eCcompilerFlags { };
1102 Array<String> compilerFlags { };
1103 Array<String> linkerFlags { };
1115 char * objectFileExt;
1116 char * outputFileExt;
1117 char * executableLauncher;
1119 char * gnuToolchainPrefix;
1123 struct { Array<String> includes, libraries, executables; };
1124 Array<String> dirs[DirTypes];
1139 delete objectFileExt;
1140 delete outputFileExt;
1142 delete executableLauncher;
1144 delete gnuToolchainPrefix;
1146 if(environmentVars) environmentVars.Free();
1147 if(includeDirs) { includeDirs.Free(); }
1148 if(libraryDirs) { libraryDirs.Free(); }
1149 if(executableDirs) { executableDirs.Free(); }
1150 if(prepDirectives) { prepDirectives.Free(); }
1151 if(excludeLibs) { excludeLibs.Free(); }
1152 if(compilerFlags) { compilerFlags.Free(); }
1153 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1154 if(linkerFlags) { linkerFlags.Free(); }
1158 CompilerConfig Copy()
1188 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1189 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1190 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1191 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1192 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1193 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1194 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1195 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1196 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1203 #if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
1204 struct LanguageOption
1207 const String bitmap;
1211 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1216 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1218 Bitmap icon = res ? res.bitmap : null;
1221 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1222 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1226 Array<LanguageOption> languages
1228 { "English", ":countryCode/gb.png", "" },
1229 { "汉语", ":countryCode/cn.png", "zh_CN" },
1230 { "Español", ":countryCode/es.png", "es" },
1231 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1232 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1233 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1234 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1235 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1236 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1237 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1240 const String GetLanguageString()
1242 char * dot, * colon;
1243 static char lang[256];
1244 const String language = getenv("ECERE_LANGUAGE");
1245 if(!language) language = getenv("LANGUAGE");
1246 if(!language) language = getenv("LC_ALL");
1247 if(!language) language = getenv("LC_MESSAGES");
1248 if(!language) language = getenv("LANG");
1249 if(!language) language = "";
1250 if(language && (colon = strchr(language, ':')))
1252 if(lang != language)
1253 strncpy(lang, language, sizeof(lang));
1254 lang[sizeof(lang)-1] = 0;
1255 lang[colon - language] = 0;
1258 if(language && (dot = strchr(language, '.')))
1260 if(lang != language)
1261 strncpy(lang, language, sizeof(lang));
1262 lang[sizeof(lang)-1] = 0;
1263 lang[dot - language] = 0;
1269 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1271 bool restart = true;
1272 String command = null;
1273 int arg0Len = (int)strlen(app.argv[0]);
1285 for(w = ide.firstChild; w; w = w.next)
1287 if(w.isActiveClient && w.isDocument)
1289 if(!w.CloseConfirmation(true))
1298 if(!projectView.CloseConfirmation(true))
1300 if(projectView.fileName)
1302 const char * name = projectView.fileName;
1305 for(j = 0; (ch = name[j]); j++)
1306 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1310 command = new char[len + 1];
1312 strcpy(command, app.argv[0]);
1314 if(projectView.fileName)
1316 strcat(command, " ");
1318 ReplaceSpaces(command + len, projectView.fileName);
1323 for(w = ide.firstChild; w; w = w.next)
1324 if(w.isActiveClient && w.isDocument)
1325 w.modifiedDocument = false;
1326 projectView.modifiedDocument = false;
1331 for(w = ide.firstChild; w; w = w.next)
1333 if(w.isActiveClient && w.isDocument)
1335 if(!w.CloseConfirmation(true))
1342 const char * name = w.fileName;
1344 for(j = 0; (ch = name[j]); j++)
1345 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1352 command = new char[len + 1];
1353 strcpy(command, app.argv[0]);
1356 for(w = ide.firstChild; w; w = w.next)
1358 if(w.isActiveClient && w.isDocument)
1360 const char * name = w.fileName;
1363 strcat(command, " ");
1365 ReplaceSpaces(command + len, name);
1366 len = (int)strlen(command);
1373 for(w = ide.firstChild; w; w = w.next)
1374 if(w.isActiveClient && w.isDocument)
1375 w.modifiedDocument = false;
1380 settings.language = code;
1381 settingsContainer.Save();
1383 setEcereLanguageInWinRegEnvironment(code);
1385 if(eClass_IsDerived(app._class, class(GuiApplication)))
1387 GuiApplication guiApp = (GuiApplication)app;
1388 guiApp.desktop.Destroy(0);
1395 for(i = 1; i < app.argc; i++)
1397 const char * arg = app.argv[i];
1399 for(j = 0; (ch = arg[j]); j++)
1400 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1403 command = new char[len + 1];
1404 strcpy(command, app.argv[0]);
1406 for(i = 1; i < app.argc; i++)
1408 strcat(command, " ");
1410 ReplaceSpaces(command + len, app.argv[i]);
1411 len = (int)strlen(command);
1417 SetEnvironment("ECERE_LANGUAGE", code);
1419 ExecuteWait(command);