X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ide%2Fsrc%2FIDESettings.ec;h=1fedfa45822f6c9301411f3c9218be148706f789;hb=fcc2160154caf03623d6fbe305af2cd955e7de04;hp=5a73376006efa55e13a67576b074b2196c810271;hpb=384ad752fcf52ee54f274730d71d29a8fb91e00e;p=sdk diff --git a/ide/src/IDESettings.ec b/ide/src/IDESettings.ec index 5a73376..1fedfa4 100644 --- a/ide/src/IDESettings.ec +++ b/ide/src/IDESettings.ec @@ -1,9 +1,28 @@ +#if defined(__WIN32__) +#define MessageBox _MessageBox +#define WIN32_LEAN_AND_MEAN +#include +#undef MessageBox +#endif + #ifdef ECERE_STATIC -import static "ecere" +public import static "ecere" #else -import "ecere" +public import "ecere" #endif +define ecpDefaultCommand = "ecp"; +define eccDefaultCommand = "ecc"; +define ecsDefaultCommand = "ecs"; +define earDefaultCommand = "ear"; +define cppDefaultCommand = "gcc"; // As per #624 we decided to default to "gcc"... +define ccDefaultCommand = "gcc"; +define cxxDefaultCommand = "g++"; +//define ldDefaultCommand = "gcc"; +define arDefaultCommand = "ar"; +define objectDefaultFileExt = "o"; +define outputDefaultFileExt = ""; + import "StringsBox" import "OldIDESettings" @@ -16,17 +35,42 @@ define defaultCompilerName = "Default"; define defaultObjDirExpression = "obj/$(CONFIG).$(PLATFORM)$(COMPILER_SUFFIX)$(DEBUG_SUFFIX)"; -char * settingsDirectoryNames[DirTypes] = +const char * settingsDirectoryNames[DirTypes] = { "Include Files", "Library Files", "Executable Files" }; +// This function cannot accept same pointer for source and output +// todo: rename ReplaceSpaces to EscapeSpaceAndSpecialChars or something +void ReplaceSpaces(char * output, const char * source) +{ + int c, dc; + char ch, pch = 0; + + for(c = 0, dc = 0; (ch = source[c]); c++, dc++) + { + if(ch == ' ') output[dc++] = '\\'; + if(ch == '\"') output[dc++] = '\\'; + if(ch == '&') output[dc++] = '\\'; + if(pch != '$') + { + if(ch == '(' || ch == ')') output[dc++] = '\\'; + pch = ch; + } + else if(ch == ')') + pch = 0; + output[dc] = ch; + } + output[dc] = '\0'; +} + + enum GlobalSettingsChange { none, editorSettings, projectOptions, compilerSettings }; enum PathRelationship { unrelated, identical, siblings, subPath, parentPath, insuficientInput, pathEmpty, toEmpty, pathNull, toNull, bothEmpty, bothNull }; -PathRelationship eString_PathRelated(char * path, char * to, char * pathDiff) +PathRelationship eString_PathRelated(const char * path, const char * to, char * pathDiff) { PathRelationship result; if(pathDiff) *pathDiff = '\0'; @@ -67,24 +111,24 @@ PathRelationship eString_PathRelated(char * path, char * to, char * pathDiff) return result; } -char * CopyValidateMakefilePath(char * path) +char * CopyValidateMakefilePath(const char * path) { - const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 7 }; - const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)",(char *)0 }; + const int map[] = { 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 7 }; + const char * vars[] = { "$(MODULE)", "$(CONFIG)", "$(PLATFORM)", "$(COMPILER)", "$(TARGET)", "$(COMPILER_SUFFIX)", "$(DEBUG_SUFFIX)", "$(PROJECT)", "$(CONFIGURATION)", "$(TARGET_PLATFORM)",(char *)0 }; char * copy = null; if(path) { int len; - len = strlen(path); + len = (int)strlen(path); copy = CopyString(path); if(len) { int c; char * tmp = copy; char * start = tmp; - Array parts { }; - + Array parts { }; + for(c=0; c?"; + char ch, * s = output, * o = output; + while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; } + *o = '\0'; + } +#ifdef __WIN32__ + if(volumePath && output[0]) + output[1] = ':'; +#endif +} + +void RemoveTrailingPathSeparator(char *path) +{ + int len; + len = (int)strlen(path); + if(len>1 && path[len-1] == DIR_SEP) + path[--len] = '\0'; +} + +void BasicValidatePathBoxPath(PathBox pathBox) +{ + char path[MAX_LOCATION]; + ValidPathBufCopy(path, pathBox.path); + RemoveTrailingPathSeparator(path); + pathBox.path = path; +} + +CompilerConfig MakeDefaultCompiler(const char * name, bool readOnly) { CompilerConfig defaultCompiler { name, readOnly, gcc, - GetRuntimePlatform(), + __runtimePlatform, 1, makeDefaultCommand, ecpDefaultCommand, @@ -141,25 +229,31 @@ CompilerConfig MakeDefaultCompiler(char * name, bool readOnly) earDefaultCommand, cppDefaultCommand, ccDefaultCommand, - cxxDefaultCommand + cxxDefaultCommand, + arDefaultCommand + //ldDefaultCommand }; incref defaultCompiler; return defaultCompiler; } -class IDESettingsContainer : GlobalSettings -{ #ifdef SETTINGS_TEST - settingsName = "ecereIDESettingsTest"; +define settingsName = "ecereIDE-SettingsTest"; #else - settingsName = "ecereIDE"; +define ideSettingsName = "ecereIDE"; #endif +class IDESettingsContainer : GlobalSettings +{ + settingsName = ideSettingsName; + virtual void OnLoad(GlobalSettingsData data); char moduleLocation[MAX_LOCATION]; private: + FileSize settingsFileSize; + IDESettingsContainer() { char path[MAX_LOCATION]; @@ -178,13 +272,15 @@ private: strcpy(configFilePath, path); PathCat(configFilePath, "Data"); - PathCat(configFilePath, "ecereIDE.ini"); + PathCat(configFilePath, ideSettingsName); + ChangeExtension(configFilePath, "ini", configFilePath); strcpy(defaultConfigFilePath, path); PathCat(defaultConfigFilePath, "App"); PathCat(defaultConfigFilePath, "DefaultData"); - PathCat(defaultConfigFilePath, "ecereIDE.ini"); - + PathCat(defaultConfigFilePath, ideSettingsName); + ChangeExtension(defaultConfigFilePath, "ini", defaultConfigFilePath); + if(FileExists(defaultConfigFilePath)) { if(!FileExists(configFilePath)) @@ -196,9 +292,9 @@ private: } PathCat(path, "Data"); // the forced settings location will only be - // used if the running ide's path matches + // used if the running ide's path matches // the PortableApps.com directory structure - // and the default ini file is found in + // and the default ini file is found in // the DefaultData directory settingsLocation = path; portable = true; @@ -208,16 +304,32 @@ private: void OnAskReloadSettings() { - /*if(MessageBox { type = YesNo, master = this, - text = "Global Settings Modified Externally", - contents = "The global settings were modified by another instance.\n" - "Would you like to reload them?" }.Modal() == Yes)*/ + FileSize newSettingsFileSize; + + if(OpenAndLock(&newSettingsFileSize)) { - Load(); + if((double)settingsFileSize - (double)newSettingsFileSize < 2048) + Load(); + else + { + GuiApplication app = ((GuiApplication)__thisModule.application); + Window w; + for(w = app.desktop.firstChild; w && (!w.created || !w.visible); w = w.next); + + CloseAndMonitor(); + + MessageBox { master = w, type = ok, isModal = true, + creationActivation = flash, + text = "Global Settings Modified Externally", + contents = "The global settings were modified by another process and a drastic shrinking of the settings file was detected.\n" + "The new settings will not be loaded to prevent loss of your ide settings.\n" + "Please check your settings file and make sure to save this IDE's global settings if your settings file has been compromised." + }.Create(); + } } } - void Load() + SettingsIOResult Load() { SettingsIOResult result = GlobalSettings::Load(); IDESettings data = (IDESettings)this.data; @@ -233,7 +345,7 @@ private: bool loaded; OldIDESettings oldSettings { }; Close(); - loaded = oldSettings.Load(); + loaded = oldSettings.Load() == success; oldSettings.Close(); if(loaded) { @@ -242,8 +354,8 @@ private: for(c : oldSettings.compilerConfigs) data.compilerConfigs.Add(c.Copy()); - for(s : oldSettings.recentFiles) data.recentFiles.Add(CopyString(s)); - for(s : oldSettings.recentProjects) data.recentProjects.Add(CopyString(s)); + for(s : oldSettings.recentFiles) data.recentFiles.Add(s); + for(s : oldSettings.recentProjects) data.recentProjects.Add(s); data.docDir = oldSettings.docDir; data.ideFileDialogLocation = oldSettings.ideFileDialogLocation; @@ -254,7 +366,7 @@ private: delete data.displayDriver; data.displayDriver = CopyString(oldSettings.displayDriver); data.projectDefaultTargetDir = oldSettings.projectDefaultTargetDir; data.projectDefaultIntermediateObjDir = oldSettings.projectDefaultIntermediateObjDir; - + Save(); result = success; } @@ -263,9 +375,9 @@ private: if(result == fileNotFound || !data) { data = (IDESettings)this.data; - data.useFreeCaret = true; + data.useFreeCaret = false; //true; data.showLineNumbers = true; - data.caretFollowsScrolling = true; + data.caretFollowsScrolling = false; //true; } } // Ensure we have a default compiler @@ -280,32 +392,59 @@ private: defaultCompiler._refCount = 0; CloseAndMonitor(); + FileGetSize(settingsFilePath, &settingsFileSize); if(data.compilerConfigs) { - for(c : data.compilerConfigs) + for(ccfg : data.compilerConfigs) { - CompilerConfig compiler = c; - incref compiler; + 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.outputFileExt || !ccfg.outputFileExt[0]) + ccfg.outputFileExt = outputDefaultFileExt;*/ + incref ccfg; } } if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory) data.ManagePortablePaths(moduleLocation, true); data.ForcePathSeparatorStyle(true); OnLoad(data); + return result; } - void Save() + SettingsIOResult Save() { + SettingsIOResult result; + IDESettings data = (IDESettings)this.data; - Platform runtimePlatform = GetRuntimePlatform(); if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory) data.ManagePortablePaths(moduleLocation, false); data.ForcePathSeparatorStyle(true); - if(!GlobalSettings::Save()) + result = GlobalSettings::Save(); + if(result != success) PrintLn("Error saving IDE settings"); if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory) data.ManagePortablePaths(moduleLocation, true); CloseAndMonitor(); + FileGetSize(settingsFilePath, &settingsFileSize); + return result; } } @@ -313,21 +452,21 @@ class IDESettings : GlobalSettingsData { public: List compilerConfigs { }; - Array recentFiles { }; - Array recentProjects { }; - property char * docDir + RecentPaths recentFiles { }; + RecentPaths recentProjects { }; + property const char * docDir { set { delete docDir; if(value && value[0]) docDir = CopyString(value); } get { return docDir ? docDir : ""; } isset { return docDir && docDir[0]; } } - property char * ideFileDialogLocation + property const char * ideFileDialogLocation { set { delete ideFileDialogLocation; if(value && value[0]) ideFileDialogLocation = CopyString(value); } get { return ideFileDialogLocation ? ideFileDialogLocation : ""; } isset { return ideFileDialogLocation && ideFileDialogLocation[0]; } } - property char * ideProjectFileDialogLocation + property const char * ideProjectFileDialogLocation { set { delete ideProjectFileDialogLocation; if(value && value[0]) ideProjectFileDialogLocation = CopyString(value); } get { return ideProjectFileDialogLocation ? ideProjectFileDialogLocation : ""; } @@ -337,37 +476,48 @@ public: bool showLineNumbers; bool caretFollowsScrolling; char * displayDriver; - + // TODO: Classify settings //EditorSettings editor { }; - property char * projectDefaultTargetDir + property const char * projectDefaultTargetDir { set { delete projectDefaultTargetDir; if(value && value[0]) projectDefaultTargetDir = CopyValidateMakefilePath(value); } get { return projectDefaultTargetDir ? projectDefaultTargetDir : ""; } isset { return projectDefaultTargetDir && projectDefaultTargetDir[0]; } } - property char * projectDefaultIntermediateObjDir + property const char * projectDefaultIntermediateObjDir { set { delete projectDefaultIntermediateObjDir; if(value && value[0]) projectDefaultIntermediateObjDir = CopyValidateMakefilePath(value); } get { return projectDefaultIntermediateObjDir ? projectDefaultIntermediateObjDir : ""; } isset { return projectDefaultIntermediateObjDir && projectDefaultIntermediateObjDir[0]; } } - property char * compilerConfigsDir + property const char * compilerConfigsDir { set { delete compilerConfigsDir; if(value && value[0]) compilerConfigsDir = CopyString(value); } get { return compilerConfigsDir ? compilerConfigsDir : ""; } isset { return compilerConfigsDir && compilerConfigsDir[0]; } } - property char * defaultCompiler + property const char * defaultCompiler { set { delete defaultCompiler; if(value && value[0]) defaultCompiler = CopyString(value); } get { return defaultCompiler && defaultCompiler[0] ? defaultCompiler : defaultCompilerName; } isset { return defaultCompiler && defaultCompiler[0]; } } + property const String language + { + set + { + delete language; + language = CopyString(value); + } + get { return language; } + isset { return language != null; } + } + private: char * docDir; char * ideFileDialogLocation; @@ -376,10 +526,11 @@ private: char * projectDefaultIntermediateObjDir; char * compilerConfigsDir; char * defaultCompiler; + String language; - CompilerConfig GetCompilerConfig(String compilerName) + CompilerConfig GetCompilerConfig(const String compilerName) { - char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName; + const char * name = compilerName && compilerName[0] ? compilerName : defaultCompilerName; CompilerConfig compilerConfig = null; for(compiler : compilerConfigs) { @@ -400,16 +551,15 @@ private: { compilerConfigs.Free(); delete compilerConfigs; - recentFiles.Free(); - delete recentFiles; - recentProjects.Free(); - delete recentProjects; + if(recentProjects) { recentFiles.Free(); delete recentFiles; } + if(recentProjects) { recentProjects.Free(); delete recentProjects; } delete docDir; - + delete projectDefaultTargetDir; delete projectDefaultIntermediateObjDir; delete compilerConfigsDir; delete defaultCompiler; + delete language; delete ideFileDialogLocation; delete ideProjectFileDialogLocation; @@ -454,24 +604,8 @@ private: } } } - if(recentFiles && recentFiles.count) - { - int c; - for(c = 0; c < recentFiles.count; c++) - { - if(recentFiles[c] && recentFiles[c][0]) - ChangeCh(recentFiles[c], from, to); - } - } - if(recentProjects && recentProjects.count) - { - int c; - for(c = 0; c < recentProjects.count; c++) - { - if(recentProjects[c] && recentProjects[c][0]) - ChangeCh(recentProjects[c], from, to); - } - } + recentFiles.changeChar(from, to); + recentProjects.changeChar(from, to); if(docDir && docDir[0]) ChangeCh(docDir, from, to); if(ideFileDialogLocation && ideFileDialogLocation[0]) @@ -545,7 +679,7 @@ private: compilerConfigsDir = UpdatePortablePath(compilerConfigsDir, location, makeAbsolute); } - char * UpdatePortablePath(char * path, char * location, bool makeAbsolute) + char * UpdatePortablePath(char * path, const char * location, bool makeAbsolute) { char * output; if(makeAbsolute) @@ -573,43 +707,55 @@ private: } return output; } +} - void AddRecentFile(char * fileName) +class RecentPaths : Array +{ + IteratorPointer Add(T value) { int c; - char * filePath = CopyString(fileName); + char * filePath = (char *)value; ChangeCh(filePath, '\\', '/'); - for(c = 0; c= MaxRecent) - recentFiles.Delete(recentFiles.GetLast()); - recentFiles.Insert(null, filePath); - //UpdateRecentMenus(owner); + return Array::Add((T)filePath); } - void AddRecentProject(char * projectName) + IteratorPointer addRecent(T value) { int c; - char * filePath = CopyString(projectName); + char * filePath = (char *)value; ChangeCh(filePath, '\\', '/'); - for(c = 0; c= MaxRecent) - recentProjects.Delete(recentProjects.GetLast()); - recentProjects.Insert(null, filePath); - //UpdateRecentMenus(owner); + while(count >= MaxRecent) + Delete(GetLast()); + return Insert(null, filePath); + } + + void changeChar(char from, char to) + { + if(this && count) + { + int c; + for(c = 0; c < count; c++) + { + if(this[c] && this[c][0]) + ChangeCh(this[c], from, to); + } + } } } @@ -619,7 +765,7 @@ static const char * compilerTypeSolutionFileVersionString[CompilerType] = { "", static const char * compilerTypeYearString[CompilerType] = { "", "", "", "2005", "2008", "2010" }; static const char * compilerTypeProjectFileExtension[CompilerType] = { "", "", "", "vcproj", "vcproj", "vcxproj" }; // TODO: i18n with Array -static Array compilerTypeLongNames +static Array compilerTypeLongNames { [ $"GNU Compiler Collection (GCC) / GNU Make", $"Tiny C Compiler / GNU Make", @@ -639,14 +785,14 @@ public enum CompilerType get { return this == vs8 || this == vs9 || this == vs10; } } - property char * + property const char * { get { return OnGetString(null, null, null); } set - { + { if(value) { - Platform c; + CompilerType c; for(c = firstCompilerType; c <= lastCompilerType; c++) if(!strcmpi(value, compilerTypeNames[c])) return c; @@ -655,13 +801,13 @@ public enum CompilerType } }; - property char * longName { get { return OnGetString(null, (void*)1, null); } }; - property char * versionString { get { return OnGetString(null, (void*)2, null); } }; - property char * yearString { get { return OnGetString(null, (void*)3, null); } }; - property char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } }; - property char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } }; + property const char * longName { get { return OnGetString(null, (void*)1, null); } }; + property const char * versionString { get { return OnGetString(null, (void*)2, null); } }; + property const char * yearString { get { return OnGetString(null, (void*)3, null); } }; + property const char * projectFileExtension { get { return OnGetString(null, (void*)4, null); } }; + property const char * solutionFileVersionString { get { return OnGetString(null, (void*)5, null); } }; - char * OnGetString(char * tempString, void * fieldData, bool * needClass) + const char * OnGetString(char * tempString, void * fieldData, bool * needClass) { if(this >= firstCompilerType && this <= lastCompilerType) { @@ -690,7 +836,7 @@ class CompilerConfig numJobs = 1; public: - property char * name + property const char * name { set { @@ -704,68 +850,109 @@ public: CompilerType type; Platform targetPlatform; int numJobs; - property char * makeCommand + property const char * makeCommand { set { delete makeCommand; if(value && value[0]) makeCommand = CopyString(value); } get { return makeCommand; } isset { return makeCommand && makeCommand[0]; } } - property char * ecpCommand + property const char * ecpCommand { set { delete ecpCommand; if(value && value[0]) ecpCommand = CopyString(value); } get { return ecpCommand; } isset { return ecpCommand && ecpCommand[0]; } } - property char * eccCommand + property const char * eccCommand { set { delete eccCommand; if(value && value[0]) eccCommand = CopyString(value); } get { return eccCommand; } isset { return eccCommand && eccCommand[0]; } } - property char * ecsCommand + property const char * ecsCommand { set { delete ecsCommand; if(value && value[0]) ecsCommand = CopyString(value); } get { return ecsCommand; } isset { return ecsCommand && ecsCommand[0]; } } - property char * earCommand + property const char * earCommand { set { delete earCommand; if(value && value[0]) earCommand = CopyString(value); } get { return earCommand; } isset { return earCommand && earCommand[0]; } } - property char * cppCommand + property const char * cppCommand { set { delete cppCommand; if(value && value[0]) cppCommand = CopyString(value); } get { return cppCommand; } isset { return cppCommand && cppCommand[0]; } } - property char * ccCommand + property const char * ccCommand { set { delete ccCommand; if(value && value[0]) ccCommand = CopyString(value); } get { return ccCommand; } isset { return ccCommand && ccCommand[0]; } } - property char * cxxCommand + property const char * cxxCommand { set { delete cxxCommand; if(value && value[0]) cxxCommand = CopyString(value); } get { return cxxCommand; } isset { return cxxCommand && cxxCommand[0]; } } - property char * execPrefixCommand + property const char * arCommand + { + set { delete arCommand; if(value && value[0]) arCommand = CopyString(value); } + get { return arCommand; } + isset { return arCommand && arCommand[0]; } + } + property const char * ldCommand + { + set { delete ldCommand; if(value && value[0]) ldCommand = CopyString(value); } + get { return ldCommand; } + isset { return ldCommand && ldCommand[0]; } + } + property const char * objectFileExt + { + set { delete objectFileExt; if(value && value[0]) objectFileExt = CopyString(value); } + get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; } + isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); } + } + property const char * outputFileExt + { + set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); } + get { return outputFileExt; } + isset { return outputFileExt && outputFileExt[0]; } + } + property const char * executableLauncher { - set { delete execPrefixCommand; if(value && value[0]) execPrefixCommand = CopyString(value); } - get { return execPrefixCommand; } - isset { return execPrefixCommand && execPrefixCommand[0]; } + set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); } + get { return executableLauncher; } + isset { return executableLauncher && executableLauncher[0]; } } + // TODO: implement CompilerConfig::windresCommand bool ccacheEnabled; bool distccEnabled; - property char * distccHosts + // deprecated + property bool supportsBitDepth { set { } get { return true; } isset { return false; } } + + property const char * distccHosts { set { delete distccHosts; if(value && value[0]) distccHosts = CopyString(value); } get { return distccHosts; } isset { return distccHosts && distccHosts[0]; } } + property const char * gnuToolchainPrefix + { + set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); } + get { return gnuToolchainPrefix; } + isset { return gnuToolchainPrefix && gnuToolchainPrefix[0]; } + } + property const char * sysroot + { + set { delete sysroot; if(value && value[0]) sysroot = CopyString(value); } + get { return sysroot; } + isset { return sysroot && sysroot[0]; } + } + bool resourcesDotEar; property Array includeDirs { set @@ -822,6 +1009,89 @@ public: get { return environmentVars; } isset { return environmentVars.count != 0; } } + property Array prepDirectives + { + set + { + prepDirectives.Free(); + if(value) + { + delete prepDirectives; + prepDirectives = value; + } + } + get { return prepDirectives; } + isset { return prepDirectives.count != 0; } + } + property Array excludeLibs + { + set + { + excludeLibs.Free(); + if(value) + { + delete excludeLibs; + excludeLibs = value; + } + } + get { return excludeLibs; } + isset { return excludeLibs.count != 0; } + } + property Array eCcompilerFlags + { + set + { + eCcompilerFlags.Free(); + if(value) + { + delete eCcompilerFlags; + eCcompilerFlags = value; + } + } + get { return eCcompilerFlags; } + isset { return eCcompilerFlags.count != 0; } + } + property Array compilerFlags + { + set + { + compilerFlags.Free(); + if(value) + { + delete compilerFlags; + compilerFlags = value; + } + } + get { return compilerFlags; } + isset { return compilerFlags.count != 0; } + } + property Array linkerFlags + { + set + { + linkerFlags.Free(); + if(value) + { + delete linkerFlags; + linkerFlags = value; + } + } + get { return linkerFlags; } + isset { return linkerFlags.count != 0; } + } + // json backward compatibility + property const char * gccPrefix + { + set { delete gnuToolchainPrefix; if(value && value[0]) gnuToolchainPrefix = CopyString(value); } + get { return gnuToolchainPrefix; } + isset { return false; } + } + property const char * execPrefixCommand + { + set { delete executableLauncher; if(value && value[0]) executableLauncher = CopyString(value); } + get { return executableLauncher; } + isset { return false; } + } private: Array includeDirs { }; Array libraryDirs { }; @@ -829,6 +1099,11 @@ private: // TODO: Can JSON parse and serialize maps? //EnvironmentVariables { }; Array environmentVars { }; + Array prepDirectives { }; + Array excludeLibs { }; + Array eCcompilerFlags { }; + Array compilerFlags { }; + Array linkerFlags { }; char * name; char * makeCommand; char * ecpCommand; @@ -838,8 +1113,14 @@ private: char * cppCommand; char * ccCommand; char * cxxCommand; - char * execPrefixCommand; + char * ldCommand; + char * arCommand; + char * objectFileExt; + char * outputFileExt; + char * executableLauncher; char * distccHosts; + char * gnuToolchainPrefix; + char * sysroot; /*union { struct { Array includes, libraries, executables; }; @@ -856,14 +1137,27 @@ private: delete cppCommand; delete ccCommand; delete cxxCommand; + delete ldCommand; + delete arCommand; + delete objectFileExt; + delete outputFileExt; delete makeCommand; - delete execPrefixCommand; + delete executableLauncher; delete distccHosts; + delete gnuToolchainPrefix; + delete sysroot; if(environmentVars) environmentVars.Free(); if(includeDirs) { includeDirs.Free(); } if(libraryDirs) { libraryDirs.Free(); } if(executableDirs) { executableDirs.Free(); } + if(prepDirectives) { prepDirectives.Free(); } + if(excludeLibs) { excludeLibs.Free(); } + if(compilerFlags) { compilerFlags.Free(); } + if(eCcompilerFlags) { eCcompilerFlags.Free(); } + if(linkerFlags) { linkerFlags.Free(); } } + +public: CompilerConfig Copy() { CompilerConfig copy @@ -881,17 +1175,269 @@ private: cppCommand, ccCommand, cxxCommand, - execPrefixCommand, + arCommand, + ldCommand, + objectFileExt, + outputFileExt, + executableLauncher, ccacheEnabled, distccEnabled, - distccHosts + false, + distccHosts, + gnuToolchainPrefix, + sysroot, + resourcesDotEar }; for(s : includeDirs) copy.includeDirs.Add(CopyString(s)); for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s)); for(s : executableDirs) copy.executableDirs.Add(CopyString(s)); for(ns : environmentVars) copy.environmentVars.Add(NamedString { name = ns.name, string = ns.string }); + for(s : prepDirectives) copy.prepDirectives.Add(CopyString(s)); + for(s : excludeLibs) copy.excludeLibs.Add(CopyString(s)); + for(s : compilerFlags) copy.compilerFlags.Add(CopyString(s)); + for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s)); + for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s)); incref copy; return copy; } } + +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 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(); + +#if defined(__WIN32__) + // Set LANGUAGE environment variable + { + HKEY key = null; + uint16 wLanguage[256]; + DWORD status; + wLanguage[0] = 0; + + RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + if(key) + { + UTF8toUTF16Buffer(code, wLanguage, sizeof(wLanguage) / sizeof(uint16)); + RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2); + RegCloseKey(key); + } + } +#endif + + 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; +}