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;
240 class IDESettingsContainer : GlobalSettings
243 settingsName = "ecereIDESettingsTest";
245 settingsName = "ecereIDE";
248 virtual void OnLoad(GlobalSettingsData data);
250 char moduleLocation[MAX_LOCATION];
253 FileSize settingsFileSize;
255 IDESettingsContainer()
257 char path[MAX_LOCATION];
259 LocateModule(null, moduleLocation);
260 strcpy(path, moduleLocation);
261 StripLastDirectory(moduleLocation, moduleLocation);
262 ChangeCh(moduleLocation, '\\', '/');
263 // PortableApps.com directory structure
264 if((start = strstr(path, "\\App\\EcereSDK\\bin\\ide.exe")))
266 char configFilePath[MAX_LOCATION];
267 char defaultConfigFilePath[MAX_LOCATION];
271 strcpy(configFilePath, path);
272 PathCat(configFilePath, "Data");
273 PathCat(configFilePath, "ecereIDE.ini");
275 strcpy(defaultConfigFilePath, path);
276 PathCat(defaultConfigFilePath, "App");
277 PathCat(defaultConfigFilePath, "DefaultData");
278 PathCat(defaultConfigFilePath, "ecereIDE.ini");
280 if(FileExists(defaultConfigFilePath))
282 if(!FileExists(configFilePath))
284 File f = FileOpen(defaultConfigFilePath, read);
285 f.CopyTo(configFilePath);
289 PathCat(path, "Data");
290 // the forced settings location will only be
291 // used if the running ide's path matches
292 // the PortableApps.com directory structure
293 // and the default ini file is found in
294 // the DefaultData directory
295 settingsLocation = path;
301 void OnAskReloadSettings()
303 FileSize newSettingsFileSize;
305 if(OpenAndLock(&newSettingsFileSize))
307 if((double)settingsFileSize - (double)newSettingsFileSize < 2048)
311 GuiApplication app = ((GuiApplication)__thisModule.application);
313 for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next);
317 MessageBox { master = w, type = ok, isModal = true,
318 text = "Global Settings Modified Externally",
319 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
320 "The new settings will not be loaded to prevent loss of your ide settings.\n"
321 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
327 SettingsIOResult Load()
329 SettingsIOResult result = GlobalSettings::Load();
330 IDESettings data = (IDESettings)this.data;
331 CompilerConfig defaultCompiler = null;
334 this.data = IDESettings { };
336 *dataOwner = this.data;
338 if(result == fileNotCompatibleWithDriver)
341 OldIDESettings oldSettings { };
343 loaded = oldSettings.Load() == success;
347 data = (IDESettings)this.data;
349 for(c : oldSettings.compilerConfigs)
350 data.compilerConfigs.Add(c.Copy());
352 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
353 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
355 data.docDir = oldSettings.docDir;
356 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
357 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
358 data.useFreeCaret = oldSettings.useFreeCaret;
359 data.showLineNumbers = oldSettings.showLineNumbers;
360 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
361 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
362 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
363 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
370 if(result == fileNotFound || !data)
372 data = (IDESettings)this.data;
373 data.useFreeCaret = false; //true;
374 data.showLineNumbers = true;
375 data.caretFollowsScrolling = false; //true;
378 // Ensure we have a default compiler
379 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
382 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
383 data.compilerConfigs.Add(defaultCompiler);
386 // We incref the compilers below, so reset refCount to 0
387 defaultCompiler._refCount = 0;
390 FileGetSize(settingsFilePath, &settingsFileSize);
391 if(data.compilerConfigs)
393 for(ccfg : data.compilerConfigs)
395 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
396 ccfg.ecpCommand = ecpDefaultCommand;
397 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
398 ccfg.eccCommand = eccDefaultCommand;
399 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
400 ccfg.ecsCommand = ecsDefaultCommand;
401 if(!ccfg.earCommand || !ccfg.earCommand[0])
402 ccfg.earCommand = earDefaultCommand;
403 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
404 ccfg.cppCommand = cppDefaultCommand;
405 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
406 ccfg.ccCommand = ccDefaultCommand;
407 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
408 ccfg.cxxCommand = cxxDefaultCommand;
409 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
410 ccfg.ldCommand = ldDefaultCommand;*/
411 if(!ccfg.arCommand || !ccfg.arCommand[0])
412 ccfg.arCommand = arDefaultCommand;
413 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
414 ccfg.objectFileExt = objectDefaultFileExt;
415 /*if(!ccfg.outputFileExt || !ccfg.outputFileExt[0])
416 ccfg.outputFileExt = outputDefaultFileExt;*/
420 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
421 data.ManagePortablePaths(moduleLocation, true);
422 data.ForcePathSeparatorStyle(true);
427 SettingsIOResult Save()
429 SettingsIOResult result;
431 IDESettings data = (IDESettings)this.data;
432 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
433 data.ManagePortablePaths(moduleLocation, false);
434 data.ForcePathSeparatorStyle(true);
435 result = GlobalSettings::Save();
436 if(result != success)
437 PrintLn("Error saving IDE settings");
438 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
439 data.ManagePortablePaths(moduleLocation, true);
441 FileGetSize(settingsFilePath, &settingsFileSize);
446 class IDESettings : GlobalSettingsData
449 List<CompilerConfig> compilerConfigs { };
450 Array<String> recentFiles { };
451 Array<String> recentProjects { };
452 property const char * docDir
454 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
455 get { return docDir ? docDir : ""; }
456 isset { return docDir && docDir[0]; }
458 property const char * ideFileDialogLocation
460 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
461 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
462 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
464 property const char * ideProjectFileDialogLocation
466 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
467 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
468 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
471 bool showLineNumbers;
472 bool caretFollowsScrolling;
473 char * displayDriver;
475 // TODO: Classify settings
476 //EditorSettings editor { };
478 property const char * projectDefaultTargetDir
480 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
481 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
482 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
484 property const char * projectDefaultIntermediateObjDir
486 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
487 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
488 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
491 property const char * compilerConfigsDir
493 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
494 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
495 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
498 property const char * defaultCompiler
500 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
501 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
502 isset { return defaultCompiler && defaultCompiler[0]; }
505 property const String language
510 language = CopyString(value);
512 get { return language; }
513 isset { return language != null; }
518 char * ideFileDialogLocation;
519 char * ideProjectFileDialogLocation;
520 char * projectDefaultTargetDir;
521 char * projectDefaultIntermediateObjDir;
522 char * compilerConfigsDir;
523 char * defaultCompiler;
526 CompilerConfig GetCompilerConfig(const String compilerName)
528 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
529 CompilerConfig compilerConfig = null;
530 for(compiler : compilerConfigs)
532 if(!strcmp(compiler.name, name))
534 compilerConfig = compiler;
538 if(!compilerConfig && compilerConfigs.count)
539 compilerConfig = compilerConfigs.firstIterator.data;
541 incref compilerConfig;
542 return compilerConfig;
547 compilerConfigs.Free();
548 delete compilerConfigs;
551 recentProjects.Free();
552 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 if(recentFiles && recentFiles.count)
607 for(c = 0; c < recentFiles.count; c++)
609 if(recentFiles[c] && recentFiles[c][0])
610 ChangeCh(recentFiles[c], from, to);
613 if(recentProjects && recentProjects.count)
616 for(c = 0; c < recentProjects.count; c++)
618 if(recentProjects[c] && recentProjects[c][0])
619 ChangeCh(recentProjects[c], from, to);
622 if(docDir && docDir[0])
623 ChangeCh(docDir, from, to);
624 if(ideFileDialogLocation && ideFileDialogLocation[0])
625 ChangeCh(ideFileDialogLocation, from, to);
626 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
627 ChangeCh(ideProjectFileDialogLocation, from, to);
629 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
630 ChangeCh(projectDefaultTargetDir, from, to);
631 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
632 ChangeCh(projectDefaultIntermediateObjDir, from, to);
634 if(compilerConfigsDir && compilerConfigsDir[0])
635 ChangeCh(compilerConfigsDir, from, to);
638 void ManagePortablePaths(char * location, bool makeAbsolute)
641 if(compilerConfigs && compilerConfigs.count)
643 for(config : compilerConfigs)
646 for(t = 0; t < DirTypes::enumSize; t++)
648 Array<String> dirs = null;
649 if(t == executables) dirs = config.executableDirs;
650 else if(t == includes) dirs = config.includeDirs;
651 else if(t == libraries) dirs = config.libraryDirs;
652 if(dirs && dirs.count)
654 for(c = 0; c < dirs.count; c++)
656 if(dirs[c] && dirs[c][0])
657 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
663 if(recentFiles && recentFiles.count)
665 for(c = 0; c < recentFiles.count; c++)
667 if(recentFiles[c] && recentFiles[c][0])
668 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
671 if(recentProjects && recentProjects.count)
673 for(c = 0; c < recentProjects.count; c++)
675 if(recentProjects[c] && recentProjects[c][0])
676 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
679 if(docDir && docDir[0])
680 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
681 if(ideFileDialogLocation && ideFileDialogLocation[0])
682 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
683 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
684 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
686 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
687 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
688 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
689 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
691 if(compilerConfigsDir && compilerConfigsDir[0])
692 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
695 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
700 char p[MAX_LOCATION];
702 PathCatSlash(p, path);
704 output = CopyString(p);
708 PathRelationship rel = eString_PathRelated(path, location, null);
709 if(rel == subPath || rel == identical)
711 char p[MAX_LOCATION];
712 MakePathRelative(path, location, p);
713 if(!*p) strcpy(p, "./");
714 else ChangeCh(p, '\\', '/');
716 output = CopyString(p);
724 void AddRecentFile(const char * fileName)
727 char * filePath = CopyString(fileName);
728 ChangeCh(filePath, '\\', '/');
729 for(c = 0; c<recentFiles.count; c++)
731 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
733 recentFiles.Delete((void *)&recentFiles[c]);
737 while(recentFiles.count >= MaxRecent)
738 recentFiles.Delete(recentFiles.GetLast());
739 recentFiles.Insert(null, filePath);
740 //UpdateRecentMenus(owner);
743 void AddRecentProject(const char * projectName)
746 char * filePath = CopyString(projectName);
747 ChangeCh(filePath, '\\', '/');
748 for(c = 0; c<recentProjects.count; c++)
750 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
752 recentProjects.Delete((void *)&recentProjects[c]);
756 while(recentProjects.count >= MaxRecent)
757 recentProjects.Delete(recentProjects.GetLast());
758 recentProjects.Insert(null, filePath);
759 //UpdateRecentMenus(owner);
763 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
764 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
765 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
766 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
767 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
768 // TODO: i18n with Array
769 static Array<const String> compilerTypeLongNames
771 $"GNU Compiler Collection (GCC) / GNU Make",
772 $"Tiny C Compiler / GNU Make",
773 $"Portable C Compiler / GNU Make",
774 $"Microsoft Visual Studio 2005 (8.0) Compiler",
775 $"Microsoft Visual Studio 2008 (9.0) Compiler",
776 $"Microsoft Visual Studio 2010 (10.0) Compiler"
778 const CompilerType firstCompilerType = gcc;
779 const CompilerType lastCompilerType = vs10;
780 public enum CompilerType
782 gcc, tcc, pcc, vs8, vs9, vs10;
786 get { return this == vs8 || this == vs9 || this == vs10; }
789 property const char *
791 get { return OnGetString(null, null, null); }
797 for(c = firstCompilerType; c <= lastCompilerType; c++)
798 if(!strcmpi(value, compilerTypeNames[c]))
805 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
806 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
807 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
808 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
809 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
811 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
813 if(this >= firstCompilerType && this <= lastCompilerType)
816 strcpy(tempString, compilerTypeNames[this]);
817 if(fieldData == null)
818 return compilerTypeNames[this];
819 else if(fieldData == (void*)1)
820 return compilerTypeLongNames[this];
821 else if(fieldData == (void*)2)
822 return compilerTypeVersionString[this];
823 else if(fieldData == (void*)3)
824 return compilerTypeYearString[this];
825 else if(fieldData == (void*)4)
826 return compilerTypeProjectFileExtension[this];
827 else if(fieldData == (void*)5)
828 return compilerTypeSolutionFileVersionString[this];
840 property const char * name
846 name = CopyString(value);
852 Platform targetPlatform;
854 property const char * makeCommand
856 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
857 get { return makeCommand; }
858 isset { return makeCommand && makeCommand[0]; }
860 property const char * ecpCommand
862 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
863 get { return ecpCommand; }
864 isset { return ecpCommand && ecpCommand[0]; }
866 property const char * eccCommand
868 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
869 get { return eccCommand; }
870 isset { return eccCommand && eccCommand[0]; }
872 property const char * ecsCommand
874 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
875 get { return ecsCommand; }
876 isset { return ecsCommand && ecsCommand[0]; }
878 property const char * earCommand
880 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
881 get { return earCommand; }
882 isset { return earCommand && earCommand[0]; }
884 property const char * cppCommand
886 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
887 get { return cppCommand; }
888 isset { return cppCommand && cppCommand[0]; }
890 property const char * ccCommand
892 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
893 get { return ccCommand; }
894 isset { return ccCommand && ccCommand[0]; }
896 property const char * cxxCommand
898 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
899 get { return cxxCommand; }
900 isset { return cxxCommand && cxxCommand[0]; }
902 property const char * arCommand
904 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
905 get { return arCommand; }
906 isset { return arCommand && arCommand[0]; }
908 property const char * ldCommand
910 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
911 get { return ldCommand; }
912 isset { return ldCommand && ldCommand[0]; }
914 property const char * objectFileExt
916 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
917 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
918 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
920 property const char * outputFileExt
922 set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
923 get { return outputFileExt; }
924 isset { return outputFileExt && outputFileExt[0]; }
926 property const char * executableLauncher
928 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
929 get { return executableLauncher; }
930 isset { return executableLauncher && executableLauncher[0]; }
932 // TODO: implement CompilerConfig::windresCommand
936 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
938 property const char * distccHosts
940 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
941 get { return distccHosts; }
942 isset { return distccHosts && distccHosts[0]; }
944 property const char * gnuToolchainPrefix
946 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
947 get { return gnuToolchainPrefix; }
948 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
950 property const char * sysroot
952 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
953 get { return sysroot; }
954 isset { return sysroot && sysroot[0]; }
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()
1190 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1191 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1192 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1193 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1194 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1195 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1196 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1197 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1198 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1205 struct LanguageOption
1208 const String bitmap;
1212 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1217 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1219 Bitmap icon = res ? res.bitmap : null;
1222 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1223 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1227 Array<LanguageOption> languages
1229 { "English", ":countryCode/gb.png", "" },
1230 { "汉语", ":countryCode/cn.png", "zh_CN" },
1231 { "Español", ":countryCode/es.png", "es" },
1232 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1233 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1234 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1235 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1236 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1237 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1238 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1241 const String GetLanguageString()
1243 char * dot, * colon;
1244 static char lang[256];
1245 const String language = getenv("ECERE_LANGUAGE");
1246 if(!language) language = getenv("LANGUAGE");
1247 if(!language) language = getenv("LC_ALL");
1248 if(!language) language = getenv("LC_MESSAGES");
1249 if(!language) language = getenv("LANG");
1250 if(!language) language = "";
1251 if(language && (colon = strchr(language, ':')))
1253 if(lang != language)
1254 strncpy(lang, language, sizeof(lang));
1255 lang[sizeof(lang)-1] = 0;
1256 lang[colon - language] = 0;
1259 if(language && (dot = strchr(language, '.')))
1261 if(lang != language)
1262 strncpy(lang, language, sizeof(lang));
1263 lang[sizeof(lang)-1] = 0;
1264 lang[dot - language] = 0;
1270 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1272 bool restart = true;
1273 String command = null;
1274 int arg0Len = (int)strlen(app.argv[0]);
1286 for(w = ide.firstChild; w; w = w.next)
1288 if(w.isActiveClient && w.isDocument)
1290 if(!w.CloseConfirmation(true))
1299 if(!projectView.CloseConfirmation(true))
1301 if(projectView.fileName)
1303 const char * name = projectView.fileName;
1306 for(j = 0; (ch = name[j]); j++)
1307 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1311 command = new char[len + 1];
1313 strcpy(command, app.argv[0]);
1315 if(projectView.fileName)
1317 strcat(command, " ");
1319 ReplaceSpaces(command + len, projectView.fileName);
1324 for(w = ide.firstChild; w; w = w.next)
1325 if(w.isActiveClient && w.isDocument)
1326 w.modifiedDocument = false;
1327 projectView.modifiedDocument = false;
1332 for(w = ide.firstChild; w; w = w.next)
1334 if(w.isActiveClient && w.isDocument)
1336 if(!w.CloseConfirmation(true))
1343 const char * name = w.fileName;
1345 for(j = 0; (ch = name[j]); j++)
1346 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1353 command = new char[len + 1];
1354 strcpy(command, app.argv[0]);
1357 for(w = ide.firstChild; w; w = w.next)
1359 if(w.isActiveClient && w.isDocument)
1361 const char * name = w.fileName;
1364 strcat(command, " ");
1366 ReplaceSpaces(command + len, name);
1367 len = (int)strlen(command);
1374 for(w = ide.firstChild; w; w = w.next)
1375 if(w.isActiveClient && w.isDocument)
1376 w.modifiedDocument = false;
1381 settings.language = code;
1382 settingsContainer.Save();
1384 #if defined(__WIN32__)
1385 // Set LANGUAGE environment variable
1388 uint16 wLanguage[256];
1392 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1395 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1396 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1402 if(eClass_IsDerived(app._class, class(GuiApplication)))
1404 GuiApplication guiApp = (GuiApplication)app;
1405 guiApp.desktop.Destroy(0);
1412 for(i = 1; i < app.argc; i++)
1414 const char * arg = app.argv[i];
1416 for(j = 0; (ch = arg[j]); j++)
1417 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1420 command = new char[len + 1];
1421 strcpy(command, app.argv[0]);
1423 for(i = 1; i < app.argc; i++)
1425 strcat(command, " ");
1427 ReplaceSpaces(command + len, app.argv[i]);
1428 len = (int)strlen(command);
1434 SetEnvironment("ECERE_LANGUAGE", code);
1436 ExecuteWait(command);