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 text = "Global Settings Modified Externally",
323 contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n"
324 "The new settings will not be loaded to prevent loss of your ide settings.\n"
325 "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised."
331 SettingsIOResult Load()
333 SettingsIOResult result = GlobalSettings::Load();
334 IDESettings data = (IDESettings)this.data;
335 CompilerConfig defaultCompiler = null;
338 this.data = IDESettings { };
340 *dataOwner = this.data;
342 if(result == fileNotCompatibleWithDriver)
345 OldIDESettings oldSettings { };
347 loaded = oldSettings.Load() == success;
351 data = (IDESettings)this.data;
353 for(c : oldSettings.compilerConfigs)
354 data.compilerConfigs.Add(c.Copy());
356 for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s));
357 for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s));
359 data.docDir = oldSettings.docDir;
360 data.ideFileDialogLocation = oldSettings.ideFileDialogLocation;
361 data.ideProjectFileDialogLocation = oldSettings.ideProjectFileDialogLocation;
362 data.useFreeCaret = oldSettings.useFreeCaret;
363 data.showLineNumbers = oldSettings.showLineNumbers;
364 data.caretFollowsScrolling = oldSettings.caretFollowsScrolling;
365 delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver);
366 data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir;
367 data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir;
374 if(result == fileNotFound || !data)
376 data = (IDESettings)this.data;
377 data.useFreeCaret = false; //true;
378 data.showLineNumbers = true;
379 data.caretFollowsScrolling = false; //true;
382 // Ensure we have a default compiler
383 defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
386 defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
387 data.compilerConfigs.Add(defaultCompiler);
390 // We incref the compilers below, so reset refCount to 0
391 defaultCompiler._refCount = 0;
394 FileGetSize(settingsFilePath, &settingsFileSize);
395 if(data.compilerConfigs)
397 for(ccfg : data.compilerConfigs)
399 if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
400 ccfg.ecpCommand = ecpDefaultCommand;
401 if(!ccfg.eccCommand || !ccfg.eccCommand[0])
402 ccfg.eccCommand = eccDefaultCommand;
403 if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
404 ccfg.ecsCommand = ecsDefaultCommand;
405 if(!ccfg.earCommand || !ccfg.earCommand[0])
406 ccfg.earCommand = earDefaultCommand;
407 if(!ccfg.cppCommand || !ccfg.cppCommand[0])
408 ccfg.cppCommand = cppDefaultCommand;
409 if(!ccfg.ccCommand || !ccfg.ccCommand[0])
410 ccfg.ccCommand = ccDefaultCommand;
411 if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
412 ccfg.cxxCommand = cxxDefaultCommand;
413 /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
414 ccfg.ldCommand = ldDefaultCommand;*/
415 if(!ccfg.arCommand || !ccfg.arCommand[0])
416 ccfg.arCommand = arDefaultCommand;
417 if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
418 ccfg.objectFileExt = objectDefaultFileExt;
419 /*if(!ccfg.outputFileExt || !ccfg.outputFileExt[0])
420 ccfg.outputFileExt = outputDefaultFileExt;*/
424 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
425 data.ManagePortablePaths(moduleLocation, true);
426 data.ForcePathSeparatorStyle(true);
431 SettingsIOResult Save()
433 SettingsIOResult result;
435 IDESettings data = (IDESettings)this.data;
436 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
437 data.ManagePortablePaths(moduleLocation, false);
438 data.ForcePathSeparatorStyle(true);
439 result = GlobalSettings::Save();
440 if(result != success)
441 PrintLn("Error saving IDE settings");
442 if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
443 data.ManagePortablePaths(moduleLocation, true);
445 FileGetSize(settingsFilePath, &settingsFileSize);
450 class IDESettings : GlobalSettingsData
453 List<CompilerConfig> compilerConfigs { };
454 Array<String> recentFiles { };
455 Array<String> recentProjects { };
456 property const char * docDir
458 set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
459 get { return docDir ? docDir : ""; }
460 isset { return docDir && docDir[0]; }
462 property const char * ideFileDialogLocation
464 set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); }
465 get { return ideFileDialogLocation ? ideFileDialogLocation : ""; }
466 isset { return ideFileDialogLocation && ideFileDialogLocation[0]; }
468 property const char * ideProjectFileDialogLocation
470 set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); }
471 get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; }
472 isset { return ideProjectFileDialogLocation && ideProjectFileDialogLocation[0]; }
475 bool showLineNumbers;
476 bool caretFollowsScrolling;
477 char * displayDriver;
479 // TODO: Classify settings
480 //EditorSettings editor { };
482 property const char * projectDefaultTargetDir
484 set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); }
485 get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; }
486 isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; }
488 property const char * projectDefaultIntermediateObjDir
490 set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); }
491 get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; }
492 isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; }
495 property const char * compilerConfigsDir
497 set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); }
498 get { return compilerConfigsDir ? compilerConfigsDir : ""; }
499 isset { return compilerConfigsDir && compilerConfigsDir[0]; }
502 property const char * defaultCompiler
504 set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); }
505 get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; }
506 isset { return defaultCompiler && defaultCompiler[0]; }
509 property const String language
514 language = CopyString(value);
516 get { return language; }
517 isset { return language != null; }
522 char * ideFileDialogLocation;
523 char * ideProjectFileDialogLocation;
524 char * projectDefaultTargetDir;
525 char * projectDefaultIntermediateObjDir;
526 char * compilerConfigsDir;
527 char * defaultCompiler;
530 CompilerConfig GetCompilerConfig(const String compilerName)
532 const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName;
533 CompilerConfig compilerConfig = null;
534 for(compiler : compilerConfigs)
536 if(!strcmp(compiler.name, name))
538 compilerConfig = compiler;
542 if(!compilerConfig && compilerConfigs.count)
543 compilerConfig = compilerConfigs.firstIterator.data;
545 incref compilerConfig;
546 return compilerConfig;
551 compilerConfigs.Free();
552 delete compilerConfigs;
555 recentProjects.Free();
556 delete recentProjects;
559 delete projectDefaultTargetDir;
560 delete projectDefaultIntermediateObjDir;
561 delete compilerConfigsDir;
562 delete defaultCompiler;
565 delete ideFileDialogLocation;
566 delete ideProjectFileDialogLocation;
567 delete displayDriver;
570 void ForcePathSeparatorStyle(bool unixStyle)
574 from = '\\', to = '/';
576 from = '/', to = '\\';
577 if(compilerConfigs && compilerConfigs.count)
580 for(config : compilerConfigs)
582 if(config.includeDirs && config.includeDirs.count)
584 for(i = 0; i < config.includeDirs.count; i++)
586 if(config.includeDirs[i] && config.includeDirs[i][0])
587 ChangeCh(config.includeDirs[i], from, to);
590 if(config.libraryDirs && config.libraryDirs.count)
592 for(i = 0; i < config.libraryDirs.count; i++)
594 if(config.libraryDirs[i] && config.libraryDirs[i][0])
595 ChangeCh(config.libraryDirs[i], from, to);
598 if(config.executableDirs && config.executableDirs.count)
600 for(i = 0; i < config.executableDirs.count; i++)
602 if(config.executableDirs[i] && config.executableDirs[i][0])
603 ChangeCh(config.executableDirs[i], from, to);
608 if(recentFiles && recentFiles.count)
611 for(c = 0; c < recentFiles.count; c++)
613 if(recentFiles[c] && recentFiles[c][0])
614 ChangeCh(recentFiles[c], from, to);
617 if(recentProjects && recentProjects.count)
620 for(c = 0; c < recentProjects.count; c++)
622 if(recentProjects[c] && recentProjects[c][0])
623 ChangeCh(recentProjects[c], from, to);
626 if(docDir && docDir[0])
627 ChangeCh(docDir, from, to);
628 if(ideFileDialogLocation && ideFileDialogLocation[0])
629 ChangeCh(ideFileDialogLocation, from, to);
630 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
631 ChangeCh(ideProjectFileDialogLocation, from, to);
633 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
634 ChangeCh(projectDefaultTargetDir, from, to);
635 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
636 ChangeCh(projectDefaultIntermediateObjDir, from, to);
638 if(compilerConfigsDir && compilerConfigsDir[0])
639 ChangeCh(compilerConfigsDir, from, to);
642 void ManagePortablePaths(char * location, bool makeAbsolute)
645 if(compilerConfigs && compilerConfigs.count)
647 for(config : compilerConfigs)
650 for(t = 0; t < DirTypes::enumSize; t++)
652 Array<String> dirs = null;
653 if(t == executables) dirs = config.executableDirs;
654 else if(t == includes) dirs = config.includeDirs;
655 else if(t == libraries) dirs = config.libraryDirs;
656 if(dirs && dirs.count)
658 for(c = 0; c < dirs.count; c++)
660 if(dirs[c] && dirs[c][0])
661 dirs[c] = UpdatePortablePath(dirs[c], location, makeAbsolute);
667 if(recentFiles && recentFiles.count)
669 for(c = 0; c < recentFiles.count; c++)
671 if(recentFiles[c] && recentFiles[c][0])
672 recentFiles[c] = UpdatePortablePath(recentFiles[c], location, makeAbsolute);
675 if(recentProjects && recentProjects.count)
677 for(c = 0; c < recentProjects.count; c++)
679 if(recentProjects[c] && recentProjects[c][0])
680 recentProjects[c] = UpdatePortablePath(recentProjects[c], location, makeAbsolute);
683 if(docDir && docDir[0])
684 docDir = UpdatePortablePath(docDir, location, makeAbsolute);
685 if(ideFileDialogLocation && ideFileDialogLocation[0])
686 ideFileDialogLocation = UpdatePortablePath(ideFileDialogLocation, location, makeAbsolute);
687 if(ideProjectFileDialogLocation && ideProjectFileDialogLocation[0])
688 ideProjectFileDialogLocation = UpdatePortablePath(ideProjectFileDialogLocation, location, makeAbsolute);
690 if(projectDefaultTargetDir && projectDefaultTargetDir[0])
691 projectDefaultTargetDir = UpdatePortablePath(projectDefaultTargetDir, location, makeAbsolute);
692 if(projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0])
693 projectDefaultIntermediateObjDir = UpdatePortablePath(projectDefaultIntermediateObjDir, location, makeAbsolute);
695 if(compilerConfigsDir && compilerConfigsDir[0])
696 compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute);
699 char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute)
704 char p[MAX_LOCATION];
706 PathCatSlash(p, path);
708 output = CopyString(p);
712 PathRelationship rel = eString_PathRelated(path, location, null);
713 if(rel == subPath || rel == identical)
715 char p[MAX_LOCATION];
716 MakePathRelative(path, location, p);
717 if(!*p) strcpy(p, "./");
718 else ChangeCh(p, '\\', '/');
720 output = CopyString(p);
728 void AddRecentFile(const char * fileName)
731 char * filePath = CopyString(fileName);
732 ChangeCh(filePath, '\\', '/');
733 for(c = 0; c<recentFiles.count; c++)
735 if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
737 recentFiles.Delete((void *)&recentFiles[c]);
741 while(recentFiles.count >= MaxRecent)
742 recentFiles.Delete(recentFiles.GetLast());
743 recentFiles.Insert(null, filePath);
744 //UpdateRecentMenus(owner);
747 void AddRecentProject(const char * projectName)
750 char * filePath = CopyString(projectName);
751 ChangeCh(filePath, '\\', '/');
752 for(c = 0; c<recentProjects.count; c++)
754 if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
756 recentProjects.Delete((void *)&recentProjects[c]);
760 while(recentProjects.count >= MaxRecent)
761 recentProjects.Delete(recentProjects.GetLast());
762 recentProjects.Insert(null, filePath);
763 //UpdateRecentMenus(owner);
767 static const char * compilerTypeNames[CompilerType] = { "GCC", "TCC", "PCC", "VS8", "VS9", "VS10" };
768 static const char * compilerTypeVersionString[CompilerType] = { "", "", "", "8.00", "9.00", "10.00" };
769 static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", "", "", "9.00", "10.00", "11.00" };
770 static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" };
771 static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" };
772 // TODO: i18n with Array
773 static Array<const String> compilerTypeLongNames
775 $"GNU Compiler Collection (GCC) / GNU Make",
776 $"Tiny C Compiler / GNU Make",
777 $"Portable C Compiler / GNU Make",
778 $"Microsoft Visual Studio 2005 (8.0) Compiler",
779 $"Microsoft Visual Studio 2008 (9.0) Compiler",
780 $"Microsoft Visual Studio 2010 (10.0) Compiler"
782 const CompilerType firstCompilerType = gcc;
783 const CompilerType lastCompilerType = vs10;
784 public enum CompilerType
786 gcc, tcc, pcc, vs8, vs9, vs10;
790 get { return this == vs8 || this == vs9 || this == vs10; }
793 property const char *
795 get { return OnGetString(null, null, null); }
801 for(c = firstCompilerType; c <= lastCompilerType; c++)
802 if(!strcmpi(value, compilerTypeNames[c]))
809 property const char * longName { get { return OnGetString(null, (void*)1, null); } };
810 property const char * versionString { get { return OnGetString(null, (void*)2, null); } };
811 property const char * yearString { get { return OnGetString(null, (void*)3, null); } };
812 property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } };
813 property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } };
815 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
817 if(this >= firstCompilerType && this <= lastCompilerType)
820 strcpy(tempString, compilerTypeNames[this]);
821 if(fieldData == null)
822 return compilerTypeNames[this];
823 else if(fieldData == (void*)1)
824 return compilerTypeLongNames[this];
825 else if(fieldData == (void*)2)
826 return compilerTypeVersionString[this];
827 else if(fieldData == (void*)3)
828 return compilerTypeYearString[this];
829 else if(fieldData == (void*)4)
830 return compilerTypeProjectFileExtension[this];
831 else if(fieldData == (void*)5)
832 return compilerTypeSolutionFileVersionString[this];
844 property const char * name
850 name = CopyString(value);
856 Platform targetPlatform;
858 property const char * makeCommand
860 set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); }
861 get { return makeCommand; }
862 isset { return makeCommand && makeCommand[0]; }
864 property const char * ecpCommand
866 set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); }
867 get { return ecpCommand; }
868 isset { return ecpCommand && ecpCommand[0]; }
870 property const char * eccCommand
872 set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); }
873 get { return eccCommand; }
874 isset { return eccCommand && eccCommand[0]; }
876 property const char * ecsCommand
878 set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); }
879 get { return ecsCommand; }
880 isset { return ecsCommand && ecsCommand[0]; }
882 property const char * earCommand
884 set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); }
885 get { return earCommand; }
886 isset { return earCommand && earCommand[0]; }
888 property const char * cppCommand
890 set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); }
891 get { return cppCommand; }
892 isset { return cppCommand && cppCommand[0]; }
894 property const char * ccCommand
896 set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); }
897 get { return ccCommand; }
898 isset { return ccCommand && ccCommand[0]; }
900 property const char * cxxCommand
902 set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); }
903 get { return cxxCommand; }
904 isset { return cxxCommand && cxxCommand[0]; }
906 property const char * arCommand
908 set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); }
909 get { return arCommand; }
910 isset { return arCommand && arCommand[0]; }
912 property const char * ldCommand
914 set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); }
915 get { return ldCommand; }
916 isset { return ldCommand && ldCommand[0]; }
918 property const char * objectFileExt
920 set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); }
921 get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
922 isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
924 property const char * outputFileExt
926 set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
927 get { return outputFileExt; }
928 isset { return outputFileExt && outputFileExt[0]; }
930 property const char * executableLauncher
932 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
933 get { return executableLauncher; }
934 isset { return executableLauncher && executableLauncher[0]; }
936 // TODO: implement CompilerConfig::windresCommand
940 property bool supportsBitDepth { set { } get { return true; } isset { return false; } }
942 property const char * distccHosts
944 set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); }
945 get { return distccHosts; }
946 isset { return distccHosts && distccHosts[0]; }
948 property const char * gnuToolchainPrefix
950 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
951 get { return gnuToolchainPrefix; }
952 isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; }
954 property const char * sysroot
956 set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); }
957 get { return sysroot; }
958 isset { return sysroot && sysroot[0]; }
960 bool resourcesDotEar;
961 property Array<String> includeDirs
972 get { return includeDirs; }
973 isset { return includeDirs.count != 0; }
975 property Array<String> libraryDirs
986 get { return libraryDirs; }
987 isset { return libraryDirs.count != 0; }
989 property Array<String> executableDirs
993 executableDirs.Free();
996 delete executableDirs;
997 executableDirs = value;
1000 get { return executableDirs; }
1001 isset { return executableDirs.count != 0; }
1003 property Array<NamedString> environmentVars
1007 environmentVars.Free();
1010 delete environmentVars;
1011 environmentVars = value;
1014 get { return environmentVars; }
1015 isset { return environmentVars.count != 0; }
1017 property Array<String> prepDirectives
1021 prepDirectives.Free();
1024 delete prepDirectives;
1025 prepDirectives = value;
1028 get { return prepDirectives; }
1029 isset { return prepDirectives.count != 0; }
1031 property Array<String> excludeLibs
1039 excludeLibs = value;
1042 get { return excludeLibs; }
1043 isset { return excludeLibs.count != 0; }
1045 property Array<String> eCcompilerFlags
1049 eCcompilerFlags.Free();
1052 delete eCcompilerFlags;
1053 eCcompilerFlags = value;
1056 get { return eCcompilerFlags; }
1057 isset { return eCcompilerFlags.count != 0; }
1059 property Array<String> compilerFlags
1063 compilerFlags.Free();
1066 delete compilerFlags;
1067 compilerFlags = value;
1070 get { return compilerFlags; }
1071 isset { return compilerFlags.count != 0; }
1073 property Array<String> linkerFlags
1081 linkerFlags = value;
1084 get { return linkerFlags; }
1085 isset { return linkerFlags.count != 0; }
1087 // json backward compatibility
1088 property const char * gccPrefix
1090 set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); }
1091 get { return gnuToolchainPrefix; }
1092 isset { return false; }
1094 property const char * execPrefixCommand
1096 set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); }
1097 get { return executableLauncher; }
1098 isset { return false; }
1101 Array<String> includeDirs { };
1102 Array<String> libraryDirs { };
1103 Array<String> executableDirs { };
1104 // TODO: Can JSON parse and serialize maps?
1105 //EnvironmentVariables { };
1106 Array<NamedString> environmentVars { };
1107 Array<String> prepDirectives { };
1108 Array<String> excludeLibs { };
1109 Array<String> eCcompilerFlags { };
1110 Array<String> compilerFlags { };
1111 Array<String> linkerFlags { };
1123 char * objectFileExt;
1124 char * outputFileExt;
1125 char * executableLauncher;
1127 char * gnuToolchainPrefix;
1131 struct { Array<String> includes, libraries, executables; };
1132 Array<String> dirs[DirTypes];
1147 delete objectFileExt;
1148 delete outputFileExt;
1150 delete executableLauncher;
1152 delete gnuToolchainPrefix;
1154 if(environmentVars) environmentVars.Free();
1155 if(includeDirs) { includeDirs.Free(); }
1156 if(libraryDirs) { libraryDirs.Free(); }
1157 if(executableDirs) { executableDirs.Free(); }
1158 if(prepDirectives) { prepDirectives.Free(); }
1159 if(excludeLibs) { excludeLibs.Free(); }
1160 if(compilerFlags) { compilerFlags.Free(); }
1161 if(eCcompilerFlags) { eCcompilerFlags.Free(); }
1162 if(linkerFlags) { linkerFlags.Free(); }
1166 CompilerConfig Copy()
1196 for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
1197 for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
1198 for(s : executableDirs) copy.executableDirs.Add(CopyString(s));
1199 for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string });
1200 for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s));
1201 for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s));
1202 for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s));
1203 for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
1204 for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
1211 struct LanguageOption
1214 const String bitmap;
1218 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1223 void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
1225 Bitmap icon = res ? res.bitmap : null;
1228 surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
1229 class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
1233 Array<LanguageOption> languages
1235 { "English", ":countryCode/gb.png", "" },
1236 { "汉语", ":countryCode/cn.png", "zh_CN" },
1237 { "Español", ":countryCode/es.png", "es" },
1238 { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
1239 { "Русский (43%)", ":countryCode/ru.png", "ru" },
1240 { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
1241 { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
1242 { "मराठी (10%)", ":countryCode/in.png", "mr" },
1243 { "Hebrew (8%)", ":countryCode/il.png", "he" },
1244 { "Magyar (8%)", ":countryCode/hu.png", "hu" }
1247 const String GetLanguageString()
1249 char * dot, * colon;
1250 static char lang[256];
1251 const String language = getenv("ECERE_LANGUAGE");
1252 if(!language) language = getenv("LANGUAGE");
1253 if(!language) language = getenv("LC_ALL");
1254 if(!language) language = getenv("LC_MESSAGES");
1255 if(!language) language = getenv("LANG");
1256 if(!language) language = "";
1257 if(language && (colon = strchr(language, ':')))
1259 if(lang != language)
1260 strncpy(lang, language, sizeof(lang));
1261 lang[sizeof(lang)-1] = 0;
1262 lang[colon - language] = 0;
1265 if(language && (dot = strchr(language, '.')))
1267 if(lang != language)
1268 strncpy(lang, language, sizeof(lang));
1269 lang[sizeof(lang)-1] = 0;
1270 lang[dot - language] = 0;
1276 bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
1278 bool restart = true;
1279 String command = null;
1280 int arg0Len = (int)strlen(app.argv[0]);
1292 for(w = ide.firstChild; w; w = w.next)
1294 if(w.isActiveClient && w.isDocument)
1296 if(!w.CloseConfirmation(true))
1305 if(!projectView.CloseConfirmation(true))
1307 if(projectView.fileName)
1309 const char * name = projectView.fileName;
1312 for(j = 0; (ch = name[j]); j++)
1313 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1317 command = new char[len + 1];
1319 strcpy(command, app.argv[0]);
1321 if(projectView.fileName)
1323 strcat(command, " ");
1325 ReplaceSpaces(command + len, projectView.fileName);
1330 for(w = ide.firstChild; w; w = w.next)
1331 if(w.isActiveClient && w.isDocument)
1332 w.modifiedDocument = false;
1333 projectView.modifiedDocument = false;
1338 for(w = ide.firstChild; w; w = w.next)
1340 if(w.isActiveClient && w.isDocument)
1342 if(!w.CloseConfirmation(true))
1349 const char * name = w.fileName;
1351 for(j = 0; (ch = name[j]); j++)
1352 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1359 command = new char[len + 1];
1360 strcpy(command, app.argv[0]);
1363 for(w = ide.firstChild; w; w = w.next)
1365 if(w.isActiveClient && w.isDocument)
1367 const char * name = w.fileName;
1370 strcat(command, " ");
1372 ReplaceSpaces(command + len, name);
1373 len = (int)strlen(command);
1380 for(w = ide.firstChild; w; w = w.next)
1381 if(w.isActiveClient && w.isDocument)
1382 w.modifiedDocument = false;
1387 settings.language = code;
1388 settingsContainer.Save();
1390 #if defined(__WIN32__)
1391 // Set LANGUAGE environment variable
1394 uint16 wLanguage[256];
1398 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1401 UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16));
1402 RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2);
1408 if(eClass_IsDerived(app._class, class(GuiApplication)))
1410 GuiApplication guiApp = (GuiApplication)app;
1411 guiApp.desktop.Destroy(0);
1418 for(i = 1; i < app.argc; i++)
1420 const char * arg = app.argv[i];
1422 for(j = 0; (ch = arg[j]); j++)
1423 len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
1426 command = new char[len + 1];
1427 strcpy(command, app.argv[0]);
1429 for(i = 1; i < app.argc; i++)
1431 strcat(command, " ");
1433 ReplaceSpaces(command + len, app.argv[i]);
1434 len = (int)strlen(command);
1440 SetEnvironment("ECERE_LANGUAGE", code);
1442 ExecuteWait(command);