+
+ CompilerConfig ::read(const char * path)
+ {
+ CompilerConfig d = null;
+ readConfigFile(path, class(CompilerConfig), &d);
+ return d;
+ }
+
+ void write()
+ {
+ char dir[MAX_LOCATION];
+ char path[MAX_LOCATION];
+ const char * settingsFilePath = settingsContainer.settingsFilePath;
+ getConfigFilePath(path, _class, dir, name);
+ if(FileExists(settingsFilePath) && !FileExists(dir))
+ {
+ MakeDir(dir);
+ if(!FileExists(dir))
+ PrintLn($"Error creating compiler configs directory at ", dir, " location.");
+ }
+ writeConfigFile(path, _class, this);
+ }
+}
+
+class CompilerConfigs : List<CompilerConfig>
+{
+ void ::fix()
+ {
+ IDESettings s = (IDESettings)settingsContainer.data;
+ // Ensure we have a default compiler
+ CompilerConfig defaultCompiler = null;
+ defaultCompiler = s.GetCompilerConfig(defaultCompilerName);
+ if(!defaultCompiler)
+ {
+ defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
+ s.compilerConfigs.Insert(null, defaultCompiler);
+ defaultCompiler = null;
+ }
+ delete defaultCompiler;
+
+ if(s.compilerConfigs)
+ {
+ for(ccfg : s.compilerConfigs)
+ {
+ if(!ccfg.ecpCommand || !ccfg.ecpCommand[0])
+ ccfg.ecpCommand = ecpDefaultCommand;
+ if(!ccfg.eccCommand || !ccfg.eccCommand[0])
+ ccfg.eccCommand = eccDefaultCommand;
+ if(!ccfg.ecsCommand || !ccfg.ecsCommand[0])
+ ccfg.ecsCommand = ecsDefaultCommand;
+ if(!ccfg.earCommand || !ccfg.earCommand[0])
+ ccfg.earCommand = earDefaultCommand;
+ if(!ccfg.cppCommand || !ccfg.cppCommand[0])
+ ccfg.cppCommand = cppDefaultCommand;
+ if(!ccfg.ccCommand || !ccfg.ccCommand[0])
+ ccfg.ccCommand = ccDefaultCommand;
+ if(!ccfg.cxxCommand || !ccfg.cxxCommand[0])
+ ccfg.cxxCommand = cxxDefaultCommand;
+ /*if(!ccfg.ldCommand || !ccfg.ldCommand[0])
+ ccfg.ldCommand = ldDefaultCommand;*/
+ if(!ccfg.arCommand || !ccfg.arCommand[0])
+ ccfg.arCommand = arDefaultCommand;
+ if(!ccfg.objectFileExt || !ccfg.objectFileExt[0])
+ ccfg.objectFileExt = objectDefaultFileExt;
+ /*if(!ccfg.staticLibFileExt || !ccfg.staticLibFileExt[0])
+ ccfg.staticLibFileExt = staticLibDefaultFileExt;*/
+ /*if(!ccfg.sharedLibFileExt || !ccfg.sharedLibFileExt[0])
+ ccfg.sharedLibFileExt = sharedLibDefaultFileExt;*/
+ /*if(!ccfg.executableFileExt || !ccfg.executableFileExt[0])
+ ccfg.executableFileExt = outputDefaultFileExt;*/
+ if(!ccfg._refCount) incref ccfg;
+ }
+ }
+ }
+
+ AVLTree<String> getWriteRequiredList(CompilerConfigs oldConfigs)
+ {
+ AVLTree<String> list { };
+ for(ccfg : this)
+ {
+ for(occfg : oldConfigs)
+ {
+ if(!strcmp(ccfg.name, occfg.name))
+ {
+ if(ccfg.OnCompare(occfg))
+ list.Add(CopyString(ccfg.name));
+ break;
+ }
+ }
+ }
+ return list;
+ }
+
+ void ::read()
+ {
+ if(settingsContainer.settingsFilePath)
+ {
+ char dir[MAX_LOCATION];
+ char path[MAX_LOCATION];
+ Class _class = class(CompilerConfig);
+ getConfigFilePath(path, _class, dir, null);
+ if(dir[0])
+ {
+ CompilerConfigs ccfgs { };
+ AVLTree<const String> addedConfigs { };
+ IDESettings s = (IDESettings)settingsContainer.data;
+ Map<String, CompilerConfig> compilerConfigsByName = getCompilerConfigsByName(dir);
+ MapIterator<const String, CompilerConfig> it { map = compilerConfigsByName };
+ if(it.Index("Default", false))
+ {
+ CompilerConfig ccfg = it.data;
+ ccfgs.Add(ccfg.Copy());
+ addedConfigs.Add(ccfg.name);
+ }
+ for(ccfg : compilerConfigsByName)
+ {
+ if(!addedConfigs.Find(ccfg.name))
+ {
+ ccfgs.Add(ccfg.Copy());
+ addedConfigs.Add(ccfg.name);
+ }
+ }
+ for(ccfg : s.compilerConfigs)
+ {
+ if(!addedConfigs.Find(ccfg.name))
+ ccfgs.Add(ccfg.Copy());
+ }
+ delete addedConfigs;
+ s.property::compilerConfigs = ccfgs;
+ fix();
+ compilerConfigsByName.Free();
+ delete compilerConfigsByName;
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+ ide.UpdateCompilerConfigs(true);
+#endif
+ }
+ }
+ }
+
+ void ::write(AVLTree<String> cfgsToWrite)
+ {
+ char dir[MAX_LOCATION];
+ char path[MAX_LOCATION];
+ Map<String, String> paths;
+ IDESettings s = (IDESettings)settingsContainer.data;
+ getConfigFilePath(path, class(CompilerConfig), dir, null);
+ paths = getCompilerConfigFilePathsByName(dir);
+ {
+ MapIterator<String, String> it { map = paths };
+ for(c : s.compilerConfigs)
+ {
+ CompilerConfig ccfg = c;
+ if(!cfgsToWrite || cfgsToWrite.Find(ccfg.name))
+ ccfg.write();
+ if(it.Index(ccfg.name, false))
+ {
+ delete it.data;
+ it.Remove();
+ }
+ }
+ }
+ for(p : paths)
+ {
+ const char * path = p;
+ DeleteFile(path);
+ }
+ paths.Free();
+ delete paths;
+ }
+}
+
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+struct LanguageOption
+{
+ const String name;
+ const String bitmap;
+ const String code;
+ BitmapResource res;
+
+ const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
+ {
+ return name;
+ }
+
+ void OnDisplay(Surface surface, int x, int y, int width, void * data, Alignment alignment, DataDisplayFlags flags)
+ {
+ Bitmap icon = res ? res.bitmap : null;
+ int w = 8 + 16;
+ if(icon)
+ surface.Blit(icon, x + (16 - icon.width) / 2,y+2,0,0, icon.width, icon.height);
+ class::OnDisplay(surface, x + w, y, width - w, null, alignment, flags);
+ }
+};
+
+Array<LanguageOption> languages
+{ [
+ { "English", ":countryCode/gb.png", "" },
+ { "汉语", ":countryCode/cn.png", "zh_CN" },
+ { "Español", ":countryCode/es.png", "es" },
+ { "Português (Brazil)", ":countryCode/br.png", "pt_BR" },
+ { "Русский (43%)", ":countryCode/ru.png", "ru" },
+ { "Nederlandse (13%)", ":countryCode/nl.png", "nl" },
+ { "Tiếng Việt (12%)", ":countryCode/vn.png", "vi" },
+ { "मराठी (10%)", ":countryCode/in.png", "mr" },
+ { "Hebrew (8%)", ":countryCode/il.png", "he" },
+ { "Magyar (8%)", ":countryCode/hu.png", "hu" }
+] };
+
+const String GetLanguageString()
+{
+ char * dot, * colon;
+ static char lang[256];
+ const String language = getenv("ECERE_LANGUAGE");
+ if(!language) language = getenv("LANGUAGE");
+ if(!language) language = getenv("LC_ALL");
+ if(!language) language = getenv("LC_MESSAGES");
+ if(!language) language = getenv("LANG");
+ if(!language) language = "";
+ if(language && (colon = strchr(language, ':')))
+ {
+ if(lang != language)
+ strncpy(lang, language, sizeof(lang));
+ lang[sizeof(lang)-1] = 0;
+ lang[colon - language] = 0;
+ language = lang;
+ }
+ if(language && (dot = strchr(language, '.')))
+ {
+ if(lang != language)
+ strncpy(lang, language, sizeof(lang));
+ lang[sizeof(lang)-1] = 0;
+ lang[dot - language] = 0;
+ language = lang;
+ }
+ return language;
+}
+
+bool LanguageRestart(const char * code, Application app, IDESettings settings, IDESettingsContainer settingsContainer, Window ide, Window projectView, bool wait)
+{
+ bool restart = true;
+ String command = null;
+ int arg0Len = (int)strlen(app.argv[0]);
+ int len = arg0Len;
+ int j;
+ char ch;
+
+ if(ide)
+ {
+ Window w;
+
+ if(projectView)
+ {
+ Window w;
+ for(w = ide.firstChild; w; w = w.next)
+ {
+ if(w.isActiveClient && w.isDocument)
+ {
+ if(!w.CloseConfirmation(true))
+ {
+ restart = false;
+ break;
+ }
+ }
+ }
+ if(restart)
+ {
+ if(!projectView.CloseConfirmation(true))
+ restart = false;
+ if(projectView.fileName)
+ {
+ const char * name = projectView.fileName;
+ if(name)
+ {
+ for(j = 0; (ch = name[j]); j++)
+ len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
+ }
+ }
+
+ command = new char[len + 1];
+
+ strcpy(command, app.argv[0]);
+ len = arg0Len;
+ if(projectView.fileName)
+ {
+ strcat(command, " ");
+ len++;
+ ReplaceSpaces(command + len, projectView.fileName);
+ }
+ }
+ if(restart)
+ {
+ for(w = ide.firstChild; w; w = w.next)
+ if(w.isActiveClient && w.isDocument)
+ w.modifiedDocument = false;
+ projectView.modifiedDocument = false;
+ }
+ }
+ else
+ {
+ for(w = ide.firstChild; w; w = w.next)
+ {
+ if(w.isActiveClient && w.isDocument)
+ {
+ if(!w.CloseConfirmation(true))
+ {
+ restart = false;
+ break;
+ }
+ if(w.fileName)
+ {
+ const char * name = w.fileName;
+ len++;
+ for(j = 0; (ch = name[j]); j++)
+ len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
+ }
+ }
+ }
+
+ if(restart)
+ {
+ command = new char[len + 1];
+ strcpy(command, app.argv[0]);
+ len = arg0Len;
+
+ for(w = ide.firstChild; w; w = w.next)
+ {
+ if(w.isActiveClient && w.isDocument)
+ {
+ const char * name = w.fileName;
+ if(name)
+ {
+ strcat(command, " ");
+ len++;
+ ReplaceSpaces(command + len, name);
+ len = (int)strlen(command);
+ }
+ }
+ }
+ }
+ if(restart)
+ {
+ for(w = ide.firstChild; w; w = w.next)
+ if(w.isActiveClient && w.isDocument)
+ w.modifiedDocument = false;
+ }
+ }
+ if(restart)
+ {
+ settings.language = code;
+ settingsContainer.Save();
+
+ setEcereLanguageInWinRegEnvironment(code);
+
+ if(eClass_IsDerived(app._class, class(GuiApplication)))
+ {
+ GuiApplication guiApp = (GuiApplication)app;
+ guiApp.desktop.Destroy(0);
+ }
+ }
+ }
+ else
+ {
+ int i;
+ for(i = 1; i < app.argc; i++)
+ {
+ const char * arg = app.argv[i];
+ len++;
+ for(j = 0; (ch = arg[j]); j++)
+ len += (ch == ' ' || ch == '\"' || ch == '&' || ch == '$' || ch == '(' || ch == ')') ? 2 : 1;
+ }
+
+ command = new char[len + 1];
+ strcpy(command, app.argv[0]);
+ len = arg0Len;
+ for(i = 1; i < app.argc; i++)
+ {
+ strcat(command, " ");
+ len++;
+ ReplaceSpaces(command + len, app.argv[i]);
+ len = (int)strlen(command);
+ }
+ }
+
+ if(restart)
+ {
+ SetEnvironment("ECERE_LANGUAGE", code);
+ if(wait)
+ ExecuteWait(command);
+ else
+ Execute(command);
+ }
+ delete command;
+ return restart;