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(CopyString(s));
358 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(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 Array<String> recentFiles { };
456 Array<String> 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;
556 recentProjects.Free();
557 delete recentProjects;
560 delete projectDefaultTargetDir;
561 delete projectDefaultIntermediateObjDir;
562 delete compilerConfigsDir;
563 delete defaultCompiler;
566 delete ideFileDialogLocation;
567 delete ideProjectFileDialogLocation;
568 delete displayDriver;
571 void ForcePathSeparatorStyle(bool unixStyle)
575 from = '\\', to = '/';
577 from = '/', to = '\\';
578 if(compilerConfigs && compilerConfigs.count)
581 for(config : compilerConfigs)
583 if(config.includeDirs && config.includeDirs.count)
585 for(i = 0; i < config.includeDirs.count; i++)
587 if(config.includeDirs[i] && config.includeDirs[i][0])
588 ChangeCh(config.includeDirs[i], from, to);
591 if(config.libraryDirs && config.libraryDirs.count)
593 for(i = 0; i < config.libraryDirs.count; i++)
595 if(config.libraryDirs[i] && config.libraryDirs[i][0])
596 ChangeCh(config.libraryDirs[i], from, to);
599 if(config.executableDirs && config.executableDirs.count)
601 for(i = 0; i < config.executableDirs.count; i++)
603 if(config.executableDirs[i] && config.executableDirs[i][0])
604 ChangeCh(config.executableDirs[i], from, to);
609 if(recentFiles && recentFiles.count)
612 for(c = 0; c < recentFiles.count; c++)
614 if(recentFiles[c] && recentFiles[c][0])
615 ChangeCh(recentFiles[c], from, to);
618 if(recentProjects && recentProjects.count)
621 for(c = 0; c < recentProjects.count; c++)
623 if(recentProjects[c] && recentProjects[c][0])
624 ChangeCh(recentProjects[c], from, to);
627 if(docDir && docDir[0])
628 ChangeCh(docDir, from, to);
629 if(ideFileDialogLocation && ideFileDialogLocation[0])
630 ChangeCh(ideFileDialogLocation, from, to);
631 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
632 ChangeCh(ideProjectFileDialogLocation, from, to);
634 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
635 ChangeCh(projectDefaultTargetDir, from, to);
636 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
637 ChangeCh(projectDefaultIntermediateObjDir, from, to);
639 if(compilerConfigsDir && compilerConfigsDir[0])
640 ChangeCh(compilerConfigsDir, from, to);
643 void ManagePortablePaths(char * location, bool makeAbsolute)
646 if(compilerConfigs && compilerConfigs.count)
648 for(config : compilerConfigs)
651 for(t = 0; t < DirTypes::enumSize; t++)
653 Array<String> dirs = null;
654 if(t == executables) dirs = config.executableDirs;
655 else if(t == includes) dirs = config.includeDirs;
656 else if(t == libraries) dirs = config.libraryDirs;
657 if(dirs && dirs.count)
659 for(c = 0; c < dirs.count; c++)
661 if(dirs[c] && dirs[c][0])
662 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
668 if(recentFiles && recentFiles.count)
670 for(c = 0; c < recentFiles.count; c++)
672 if(recentFiles[c] && recentFiles[c][0])
673 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
676 if(recentProjects && recentProjects.count)
678 for(c = 0; c < recentProjects.count; c++)
680 if(recentProjects[c] && recentProjects[c][0])
681 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
684 if(docDir && docDir[0])
685 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
686 if(ideFileDialogLocation && ideFileDialogLocation[0])
687 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
688 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
689 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
691 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
692 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
693 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
694 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
696 if(compilerConfigsDir && compilerConfigsDir[0])
697 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
700 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
705 char p[MAX_LOCATION];
707 PathCatSlash(p, path);
709 output = CopyString(p);
713 PathRelationship rel = eString_PathRelated(path, location, null);
714 if(rel == subPath || rel == identical)
716 char p[MAX_LOCATION];
717 MakePathRelative(path, location, p);
718 if(!*p) strcpy(p, "./");
719 else ChangeCh(p, '\\', '/');
721 output = CopyString(p);
729 void AddRecentFile(const char * fileName)
732 char * filePath = CopyString(fileName);
733 ChangeCh(filePath, '\\', '/');
734 for(c = 0; c<recentFiles.count; c++)
736 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
738 recentFiles.Delete((void *)&recentFiles[c]);
742 while(recentFiles.count >= MaxRecent)
743 recentFiles.Delete(recentFiles.GetLast());
744 recentFiles.Insert(null, filePath);
745 //UpdateRecentMenus(owner);
748 void AddRecentProject(const char * projectName)
751 char * filePath = CopyString(projectName);
752 ChangeCh(filePath, '\\', '/');
753 for(c = 0; c<recentProjects.count; c++)
755 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
757 recentProjects.Delete((void *)&recentProjects[c]);
761 while(recentProjects.count >= MaxRecent)
762 recentProjects.Delete(recentProjects.GetLast());
763 recentProjects.Insert(null, filePath);
764 //UpdateRecentMenus(owner);
768 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
769 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
770 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
771 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
772 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
773 // TODO: i18n with Array
774 static Array<const String> compilerTypeLongNames
776 $"GNU Compiler Collection (GCC) / GNU Make",
777 $"Tiny C Compiler / GNU Make",
778 $"Portable C Compiler / GNU Make",
779 $"Microsoft Visual Studio 2005 (8.0) Compiler",
780 $"Microsoft Visual Studio 2008 (9.0) Compiler",
781 $"Microsoft Visual Studio 2010 (10.0) Compiler"
783 const CompilerType firstCompilerType = gcc;
784 const CompilerType lastCompilerType = vs10;
785 public enum CompilerType
787 gcc, tcc, pcc, vs8, vs9, vs10;
791 get { return this == vs8 || this == vs9 || this == vs10; }
794 property const char *
796 get { return OnGetString(null, null, null); }
802 for(c = firstCompilerType; c <= lastCompilerType; c++)
803 if(!strcmpi(value, compilerTypeNames[c]))
810 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
811 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
812 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
813 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
814 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
816 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
818 if(this >= firstCompilerType && this <= lastCompilerType)
821 strcpy(tempString, compilerTypeNames[this]);
822 if(fieldData == null)
823 return compilerTypeNames[this];
824 else if(fieldData == (void*)1)
825 return compilerTypeLongNames[this];
826 else if(fieldData == (void*)2)
827 return compilerTypeVersionString[this];
828 else if(fieldData == (void*)3)
829 return compilerTypeYearString[this];
830 else if(fieldData == (void*)4)
831 return compilerTypeProjectFileExtension[this];
832 else if(fieldData == (void*)5)
833 return compilerTypeSolutionFileVersionString[this];
845 property const char * name
851 name = CopyString(value);
857 Platform targetPlatform;
859 property const char * makeCommand
861 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
862 get { return makeCommand; }
863 isset { return makeCommand && makeCommand[0]; }
865 property const char * ecpCommand
867 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
868 get { return ecpCommand; }
869 isset { return ecpCommand && ecpCommand[0]; }
871 property const char * eccCommand
873 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
874 get { return eccCommand; }
875 isset { return eccCommand && eccCommand[0]; }
877 property const char * ecsCommand
879 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
880 get { return ecsCommand; }
881 isset { return ecsCommand && ecsCommand[0]; }
883 property const char * earCommand
885 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
886 get { return earCommand; }
887 isset { return earCommand && earCommand[0]; }
889 property const char * cppCommand
891 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
892 get { return cppCommand; }
893 isset { return cppCommand && cppCommand[0]; }
895 property const char * ccCommand
897 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
898 get { return ccCommand; }
899 isset { return ccCommand && ccCommand[0]; }
901 property const char * cxxCommand
903 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
904 get { return cxxCommand; }
905 isset { return cxxCommand && cxxCommand[0]; }
907 property const char * arCommand
909 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
910 get { return arCommand; }
911 isset { return arCommand && arCommand[0]; }
913 property const char * ldCommand
915 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
916 get { return ldCommand; }
917 isset { return ldCommand && ldCommand[0]; }
919 property const char * objectFileExt
921 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
922 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
923 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
925 property const char * outputFileExt
927 set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
928 get { return outputFileExt; }
929 isset { return outputFileExt && outputFileExt[0]; }
931 property const char * executableLauncher
933 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
934 get { return executableLauncher; }
935 isset { return executableLauncher && executableLauncher[0]; }
937 // TODO: implement CompilerConfig::windresCommand
941 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
943 property const char * distccHosts
945 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
946 get { return distccHosts; }
947 isset { return distccHosts && distccHosts[0]; }
949 property const char * gnuToolchainPrefix
951 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
952 get { return gnuToolchainPrefix; }
953 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
955 property const char * sysroot
957 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
958 get { return sysroot; }
959 isset { return sysroot && sysroot[0]; }
961 bool resourcesDotEar;
962 property Array<String> includeDirs
973 get { return includeDirs; }
974 isset { return includeDirs.count != 0; }
976 property Array<String> libraryDirs
987 get { return libraryDirs; }
988 isset { return libraryDirs.count != 0; }
990 property Array<String> executableDirs
994 executableDirs.Free();
997 delete executableDirs;
998 executableDirs = value;
1001 get { return executableDirs; }
1002 isset { return executableDirs.count != 0; }
1004 property Array<NamedString> environmentVars
1008 environmentVars.Free();
1011 delete environmentVars;
1012 environmentVars = value;
1015 get { return environmentVars; }
1016 isset { return environmentVars.count != 0; }
1018 property Array<String> prepDirectives
1022 prepDirectives.Free();
1025 delete prepDirectives;
1026 prepDirectives = value;
1029 get { return prepDirectives; }
1030 isset { return prepDirectives.count != 0; }
1032 property Array<String> excludeLibs
1040 excludeLibs = value;
1043 get { return excludeLibs; }
1044 isset { return excludeLibs.count != 0; }
1046 property Array<String> eCcompilerFlags
1050 eCcompilerFlags.Free();
1053 delete eCcompilerFlags;
1054 eCcompilerFlags = value;
1057 get { return eCcompilerFlags; }
1058 isset { return eCcompilerFlags.count != 0; }
1060 property Array<String> compilerFlags
1064 compilerFlags.Free();
1067 delete compilerFlags;
1068 compilerFlags = value;
1071 get { return compilerFlags; }
1072 isset { return compilerFlags.count != 0; }
1074 property Array<String> linkerFlags
1082 linkerFlags = value;
1085 get { return linkerFlags; }
1086 isset { return linkerFlags.count != 0; }
1088 // json backward compatibility
1089 property const char * gccPrefix
1091 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1092 get { return gnuToolchainPrefix; }
1093 isset { return false; }
1095 property const char * execPrefixCommand
1097 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1098 get { return executableLauncher; }
1099 isset { return false; }
1102 Array<String> includeDirs { };
1103 Array<String> libraryDirs { };
1104 Array<String> executableDirs { };
1105 // TODO: Can JSON parse and serialize maps?
1106 //EnvironmentVariables { };
1107 Array<NamedString> environmentVars { };
1108 Array<String> prepDirectives { };
1109 Array<String> excludeLibs { };
1110 Array<String> eCcompilerFlags { };
1111 Array<String> compilerFlags { };
1112 Array<String> linkerFlags { };
1124 char * objectFileExt;
1125 char * outputFileExt;
1126 char * executableLauncher;
1128 char * gnuToolchainPrefix;
1132 struct { Array<String> includes, libraries, executables; };
1133 Array<String> dirs[DirTypes];
1148 delete objectFileExt;
1149 delete outputFileExt;
1151 delete executableLauncher;
1153 delete gnuToolchainPrefix;
1155 if(environmentVars) environmentVars.Free();
1156 if(includeDirs) { includeDirs.Free(); }
1157 if(libraryDirs) { libraryDirs.Free(); }
1158 if(executableDirs) { executableDirs.Free(); }
1159 if(prepDirectives) { prepDirectives.Free(); }
1160 if(excludeLibs) { excludeLibs.Free(); }
1161 if(compilerFlags) { compilerFlags.Free(); }
1162 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1163 if(linkerFlags) { linkerFlags.Free(); }
1167 CompilerConfig Copy()
1197 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1198 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1199 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1200 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1201 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1202 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1203 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1204 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1205 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1212 struct LanguageOption
1215 const String bitmap;
1219 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1224 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1226 Bitmap icon = res ? res.bitmap : null;
1229 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1230 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1234 Array<LanguageOption> languages
1236 { "English", ":countryCode/gb.png", "" },
1237 { "汉语", ":countryCode/cn.png", "zh_CN" },
1238 { "Español", ":countryCode/es.png", "es" },
1239 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1240 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1241 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1242 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1243 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1244 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1245 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1248 const String GetLanguageString()
1250 char * dot, * colon;
1251 static char lang[256];
1252 const String language = getenv("ECERE_LANGUAGE");
1253 if(!language) language = getenv("LANGUAGE");
1254 if(!language) language = getenv("LC_ALL");
1255 if(!language) language = getenv("LC_MESSAGES");
1256 if(!language) language = getenv("LANG");
1257 if(!language) language = "";
1258 if(language && (colon = strchr(language, ':')))
1260 if(lang != language)
1261 strncpy(lang, language, sizeof(lang));
1262 lang[sizeof(lang)-1] = 0;
1263 lang[colon - language] = 0;
1266 if(language && (dot = strchr(language, '.')))
1268 if(lang != language)
1269 strncpy(lang, language, sizeof(lang));
1270 lang[sizeof(lang)-1] = 0;
1271 lang[dot - language] = 0;
1277 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1279 bool restart = true;
1280 String command = null;
1281 int arg0Len = (int)strlen(app.argv[0]);
1293 for(w = ide.firstChild; w; w = w.next)
1295 if(w.isActiveClient && w.isDocument)
1297 if(!w.CloseConfirmation(true))
1306 if(!projectView.CloseConfirmation(true))
1308 if(projectView.fileName)
1310 const char * name = projectView.fileName;
1313 for(j = 0; (ch = name[j]); j++)
1314 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1318 command = new char[len + 1];
1320 strcpy(command, app.argv[0]);
1322 if(projectView.fileName)
1324 strcat(command, " ");
1326 ReplaceSpaces(command + len, projectView.fileName);
1331 for(w = ide.firstChild; w; w = w.next)
1332 if(w.isActiveClient && w.isDocument)
1333 w.modifiedDocument = false;
1334 projectView.modifiedDocument = false;
1339 for(w = ide.firstChild; w; w = w.next)
1341 if(w.isActiveClient && w.isDocument)
1343 if(!w.CloseConfirmation(true))
1350 const char * name = w.fileName;
1352 for(j = 0; (ch = name[j]); j++)
1353 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1360 command = new char[len + 1];
1361 strcpy(command, app.argv[0]);
1364 for(w = ide.firstChild; w; w = w.next)
1366 if(w.isActiveClient && w.isDocument)
1368 const char * name = w.fileName;
1371 strcat(command, " ");
1373 ReplaceSpaces(command + len, name);
1374 len = (int)strlen(command);
1381 for(w = ide.firstChild; w; w = w.next)
1382 if(w.isActiveClient && w.isDocument)
1383 w.modifiedDocument = false;
1388 settings.language = code;
1389 settingsContainer.Save();
1391 #if defined(__WIN32__)
1392 // Set LANGUAGE environment variable
1395 uint16 wLanguage[256];
1399 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1402 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1403 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1409 if(eClass_IsDerived(app._class, class(GuiApplication)))
1411 GuiApplication guiApp = (GuiApplication)app;
1412 guiApp.desktop.Destroy(0);
1419 for(i = 1; i < app.argc; i++)
1421 const char * arg = app.argv[i];
1423 for(j = 0; (ch = arg[j]); j++)
1424 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1427 command = new char[len + 1];
1428 strcpy(command, app.argv[0]);
1430 for(i = 1; i < app.argc; i++)
1432 strcat(command, " ");
1434 ReplaceSpaces(command + len, app.argv[i]);
1435 len = (int)strlen(command);
1441 SetEnvironment("ECERE_LANGUAGE", code);
1443 ExecuteWait(command);