-#if defined(__WIN32__)
-#define MessageBox _MessageBox
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef MessageBox
-#endif
-
#ifdef ECERE_STATIC
public import static "ecere"
#else
import "OldIDESettings"
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+import "ide"
+import "process"
+#endif
+
+IDEConfigHolder ideConfig { };
+
+IDESettings ideSettings;
+
+IDESettingsContainer settingsContainer
+{
+ dataOwner = &ideSettings;
+ dataClass = class(IDESettings);
+};
+
define MaxRecent = 9;
enum DirTypes { includes, libraries, executables };
return defaultCompiler;
}
+//#define SETTINGS_TEST
#ifdef SETTINGS_TEST
-define settingsName = "ecereIDE-SettingsTest";
+define settingsDir = ".ecereIDE-SettingsTest";
+define ideSettingsName = "ecereIDE-SettingsTest";
#else
+define settingsDir = ".ecereIDE";
define ideSettingsName = "ecereIDE";
#endif
-class IDESettingsContainer : GlobalSettings
+class IDEConfigHolder
{
- settingsName = ideSettingsName;
+ CompilerConfigs compilers { };
+ RecentFiles recentFiles { };
+ RecentWorkspaces recentWorkspaces { };
- virtual void OnLoad(GlobalSettingsData data);
+ void forcePathSeparatorStyle(bool unixStyle)
+ {
+ char from, to;
+ if(unixStyle)
+ from = '\\', to = '/';
+ else
+ from = '/', to = '\\';
+ recentFiles.changeChar(from, to);
+ recentWorkspaces.changeChar(from, to);
+ }
+}
+
+class IDESettingsContainer : GlobalSettings
+{
+ property bool useNewConfigurationFiles
+ {
+ set
+ {
+ if(value)
+ {
+ settingsContainer.driver = "ECON";
+ settingsName = "config";
+ settingsExtension = "econ";
+ settingsDirectory = settingsDir;
+ }
+ else
+ {
+ settingsContainer.driver = "JSON";
+ settingsName = ideSettingsName;
+ settingsExtension = null;
+ settingsDirectory = null;
+ }
+ }
+ }
char moduleLocation[MAX_LOCATION];
private:
+ bool oldConfig;
FileSize settingsFileSize;
IDESettingsContainer()
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"
SettingsIOResult Load()
{
- SettingsIOResult result = GlobalSettings::Load();
- IDESettings data = (IDESettings)this.data;
- CompilerConfig defaultCompiler = null;
+ IDESettings data;
+ SettingsIOResult result;
+ useNewConfigurationFiles = true;
+ result = GlobalSettings::Load();
+ data = (IDESettings)this.data;
+ oldConfig = false;
+ if(result == fileNotFound)
+ {
+ oldConfig = true;
+ useNewConfigurationFiles = false;
+ result = GlobalSettings::Load();
+ }
+ data = (IDESettings)this.data;
if(!data)
{
this.data = IDESettings { };
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;
data.caretFollowsScrolling = false; //true;
}
}
- // Ensure we have a default compiler
- defaultCompiler = data.GetCompilerConfig(defaultCompilerName);
- if(!defaultCompiler)
- {
- defaultCompiler = MakeDefaultCompiler(defaultCompilerName, true);
- data.compilerConfigs.Add(defaultCompiler);
- }
-
- // We incref the compilers below, so reset refCount to 0
- defaultCompiler._refCount = 0;
- CloseAndMonitor();
- FileGetSize(settingsFilePath, &settingsFileSize);
- if(data.compilerConfigs)
+ if(oldConfig)
{
- for(ccfg : data.compilerConfigs)
+ if(data.compilerConfigs && data.compilerConfigs.count)
{
- 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;
+ for(c : data.compilerConfigs)
+ ideConfig.compilers.Add(c);
+ data.compilerConfigs.RemoveAll();
+ }
+ if(data.recentFiles && data.recentFiles.count)
+ {
+ for(s : data.recentFiles)
+ ideConfig.recentFiles.Add(s);
+ data.recentFiles.RemoveAll();
+ }
+ if(data.recentProjects && data.recentProjects.count)
+ {
+ for(s : data.recentProjects)
+ ideConfig.recentWorkspaces.Add(s);
+ data.recentProjects.RemoveAll();
}
+ ideConfig.forcePathSeparatorStyle(true);
}
+
+ CloseAndMonitor();
+ FileGetSize(settingsFilePath, &settingsFileSize);
+ if(oldConfig)
+ CompilerConfigs::fix();
if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
data.ManagePortablePaths(moduleLocation, true);
data.ForcePathSeparatorStyle(true);
- OnLoad(data);
+
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+ globalSettingsDialog.ideSettings = data;
+ if(oldConfig)
+ {
+ ide.updateRecentMenus();
+ ide.UpdateCompilerConfigs(true);
+ }
+#endif
+
+ if(oldConfig)
+ {
+ useNewConfigurationFiles = true;
+ Save();
+ CompilerConfigs::write(null);
+ }
return result;
}
SettingsIOResult Save()
{
SettingsIOResult result;
-
- IDESettings data = (IDESettings)this.data;
+ IDESettings data;
+ useNewConfigurationFiles = true;
+ data = (IDESettings)this.data;
if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
data.ManagePortablePaths(moduleLocation, false);
data.ForcePathSeparatorStyle(true);
+ if(oldConfig)
+ settingsFilePath = null;
result = GlobalSettings::Save();
if(result != success)
PrintLn("Error saving IDE settings");
+ else
+ oldConfig = false;
if(portable && moduleLocation[0] && FileExists(moduleLocation).isDirectory)
data.ManagePortablePaths(moduleLocation, true);
+
CloseAndMonitor();
FileGetSize(settingsFilePath, &settingsFileSize);
+
return result;
}
}
+static Map<String, String> getCompilerConfigFilePathsByName(const char * path)
+{
+ Map<String, String> map { };
+ FileListing fl { path, extensions = "econ" };
+ while(fl.Find())
+ {
+ if(fl.stats.attribs.isFile)
+ {
+ char name[MAX_FILENAME];
+ char * path = CopyString(fl.path);
+ MakeSlashPath(path);
+ GetLastDirectory(path, name);
+ {
+ char * s = strstr(name, ".");
+ if(s) *s = 0;
+ }
+ map[name] = path;
+ }
+ }
+ return map;
+}
+
+static Map<String, CompilerConfig> getCompilerConfigsByName(const char * path)
+{
+ Map<String, CompilerConfig> map { };
+ FileListing fl { path, extensions = "econ" };
+ while(fl.Find())
+ {
+ if(fl.stats.attribs.isFile)
+ {
+ char name[MAX_FILENAME];
+ char * path = CopyString(fl.path);
+ MakeSlashPath(path);
+ GetLastDirectory(path, name);
+ {
+ char * s = strstr(name, ".");
+ if(s) *s = 0;
+ }
+ {
+ CompilerConfig ccfg = CompilerConfig::read(path);
+ if(ccfg)
+ map[name] = ccfg;
+ }
+ delete path;
+ }
+ }
+ return map;
+}
+
+static void getConfigFilePath(char * path, Class _class, char * dir, const char * configName)
+{
+ if(dir) *dir = 0;
+ strcpy(path, settingsContainer.settingsFilePath);
+ StripLastDirectory(path, path);
+ if(settingsContainer.oldConfig)
+ PathCatSlash(path, settingsDir);
+ if(_class == class(CompilerConfig))
+ {
+ PathCatSlash(path, "compilerConfigs");
+ if(dir)
+ strcpy(dir, path);
+ if(configName)
+ {
+ PathCatSlash(path, configName);
+ ChangeExtension(path, "econ", path);
+ }
+ }
+ else if(_class == class(RecentFilesData))
+ PathCatSlash(path, "recentFiles.econ");
+ else if(_class == class(RecentWorkspacesData))
+ PathCatSlash(path, "recentWorkspaces.econ");
+}
+
+static SettingsIOResult writeConfigFile(const char * path, Class dataType, void * data)
+{
+ SettingsIOResult result = error;
+ SafeFile sf;
+ sf = safeWriteFileOpen(path, write);
+ if(sf.file)
+ {
+ WriteECONObject(sf.file, dataType, data, 0);
+ delete sf;
+ result = success;
+ }
+ else
+ PrintLn($"error: could not safely open file for writing configuration: ", path);
+ return result;
+}
+
+static SettingsIOResult readConfigFile(const char * path, Class dataType, void ** data)
+{
+ SettingsIOResult result = error;
+ SafeFile sf;
+ if(!FileExists(path))
+ result = fileNotFound;
+ else if((sf = safeWriteFileOpen(path, read)))
+ {
+ JSONResult jsonResult;
+ {
+ ECONParser parser { f = sf.file };
+ sf.file.Seek(0, start);
+ jsonResult = parser.GetObject(dataType, data);
+ if(jsonResult != success)
+ delete *data;
+ delete parser;
+ }
+ if(jsonResult == success)
+ result = success;
+ else
+ {
+ result = fileNotCompatibleWithDriver;
+ PrintLn($"error: could not parse configuration file: ", path);
+ }
+ delete sf;
+ }
+ return result;
+}
+
+class SafeFile
+{
+ File file;
+ FileOpenMode mode;
+ char path[MAX_LOCATION];
+ char tmp[MAX_LOCATION];
+
+ ~SafeFile()
+ {
+ delete file;
+ // how to make this atomic ?
+ if(mode == write)
+ {
+ int c;
+ for(c = 0; c < 10; c++)
+ {
+ if(FileExists(path).isFile)
+ DeleteFile(path);
+ else
+ {
+ MoveFile(tmp, path);
+ if(FileExists(path).isFile)
+ break;
+ }
+ }
+ }
+ }
+}
+
+SafeFile safeWriteFileOpen(const char * path, FileOpenMode mode)
+{
+ SafeFile sf { mode = mode };
+ int c;
+ bool locked = false;
+ strcpy(sf.path, path);
+ strcpy(sf.tmp, path);
+ strcat(sf.tmp, ".tmp");
+ if(mode == write)
+ {
+ if(FileExists(sf.tmp).isFile)
+ DeleteFile(sf.tmp);
+ sf.file = FileOpen(sf.tmp, write);
+ if(sf.file)
+ {
+ for(c = 0; c < 10 && !(locked = sf.file.Lock(exclusive, 0, 0, false)); c++);
+ if(!locked)
+ {
+ delete sf.file;
+ PrintLn($"warning: safeWriteFileOpen: unable to obtain exclusive lock on temporary file for writing: ", sf.tmp);
+ }
+ }
+ else
+ PrintLn($"warning: safeWriteFileOpen: unable to open temporary file for writing: ", sf.tmp);
+ }
+ else if(mode == read)
+ {
+ sf.file = FileOpen(path, read);
+ if(sf.file)
+ {
+ for(c = 0; c < 10 && !(locked = sf.file.Lock(shared, 0, 0, false)); c++) Sleep(0.01);
+ if(!locked)
+ {
+ delete sf.file;
+ PrintLn($"warning: safeWriteFileOpen: unable to obtain shared lock on file for reading: ", path);
+ }
+ }
+ }
+ else
+ PrintLn($"warning: safeWriteFileOpen: does not yet support FileOpenMode::", mode);
+ return sf;
+}
+
+class RecentFilesData
+{
+public:
+ RecentFiles recentFiles;
+}
+
+class RecentWorkspacesData
+{
+public:
+ RecentWorkspaces recentWorkspaces;
+}
+
class IDESettings : GlobalSettingsData
{
public:
- List<CompilerConfig> compilerConfigs { };
- Array<String> recentFiles { };
- Array<String> recentProjects { };
+ property CompilerConfigs compilerConfigs
+ {
+ set { if(settingsContainer.oldConfig) { if(compilerConfigs) compilerConfigs.Free(); delete compilerConfigs; if(value) compilerConfigs = value; } }
+ get { return compilerConfigs; }
+ isset { return false; }
+ }
+ property RecentFiles recentFiles
+ {
+ set { if(recentFiles) recentFiles.Free(); delete recentFiles; if(value) recentFiles = value; }
+ get { return recentFiles; }
+ isset { return false; }
+ }
+ property RecentWorkspaces recentProjects
+ {
+ set { if(recentProjects) recentProjects.Free(); delete recentProjects; if(value) recentProjects = value; }
+ get { return recentProjects; }
+ isset { return false; }
+ }
property const char * docDir
{
set { delete docDir; if(value && value[0]) docDir = CopyString(value); }
}
private:
+ CompilerConfigs compilerConfigs { };
char * docDir;
char * ideFileDialogLocation;
char * ideProjectFileDialogLocation;
char * compilerConfigsDir;
char * defaultCompiler;
String language;
+ RecentFiles recentFiles { };
+ RecentWorkspaces recentProjects { };
CompilerConfig GetCompilerConfig(const String compilerName)
{
{
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;
}
}
}
- 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])
}
return output;
}
+}
+
+class RecentFiles : RecentPaths
+{
+ void onAdd()
+ {
+ write();
+ }
- void AddRecentFile(const char * fileName)
+ void ::read()
+ {
+ char path[MAX_LOCATION];
+ RecentFilesData d = null;
+ Class _class = class(RecentFilesData);
+ getConfigFilePath(path, _class, null, null);
+ readConfigFile(path, _class, &d);
+ if(d && d.recentFiles && d.recentFiles.count)
+ {
+ IDESettings s = (IDESettings)settingsContainer.data;
+ s.property::recentFiles = d.recentFiles;
+ d.recentFiles = null;
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+ ide.updateRecentFilesMenu();
+#endif
+ }
+ delete d;
+ }
+
+ void ::write()
+ {
+ char path[MAX_LOCATION];
+ IDESettings s = (IDESettings)settingsContainer.data;
+ RecentFilesData d { };
+ Class _class = class(RecentFilesData);
+ getConfigFilePath(path, _class, null, null);
+ d.recentFiles = s.recentFiles;
+ writeConfigFile(path, _class, d);
+ d.recentFiles = null;
+ delete d;
+ }
+}
+
+class RecentWorkspaces : RecentPaths
+{
+ void onAdd()
+ {
+ write();
+ }
+
+ void ::read()
+ {
+ char path[MAX_LOCATION];
+ RecentWorkspacesData d = null;
+ Class _class = class(RecentWorkspacesData);
+ getConfigFilePath(path, _class, null, null);
+ readConfigFile(path, _class, &d);
+ if(d && d.recentWorkspaces && d.recentWorkspaces.count)
+ {
+ IDESettings s = (IDESettings)settingsContainer.data;
+ s.property::recentProjects = d.recentWorkspaces;
+ d.recentWorkspaces = null;
+#if !defined(ECERE_DOCUMENTOR) && !defined(ECERE_EPJ2MAKE)
+ ide.updateRecentProjectsMenu();
+#endif
+ }
+ delete d;
+ }
+
+ void ::write()
+ {
+ char path[MAX_LOCATION];
+ IDESettings s = (IDESettings)settingsContainer.data;
+ RecentWorkspacesData d { };
+ Class _class = class(RecentWorkspacesData);
+ getConfigFilePath(path, _class, null, null);
+ d.recentWorkspaces = s.recentProjects;
+ writeConfigFile(path, _class, d);
+ d.recentWorkspaces = null;
+ delete d;
+ }
+}
+
+class RecentPaths : Array<String>
+{
+ virtual void onAdd();
+
+ IteratorPointer Add(T value)
{
int c;
- char * filePath = CopyString(fileName);
+ char * filePath = (char *)value;
ChangeCh(filePath, '\\', '/');
- for(c = 0; c<recentFiles.count; c++)
+ for(c = 0; c < count; c++)
{
- if(recentFiles[c] && !fstrcmp(recentFiles[c], filePath))
+ if(this[c] && !fstrcmp(this[c], filePath))
{
- recentFiles.Delete((void *)&recentFiles[c]);
+ Delete((void *)&this[c]);
c--;
}
}
- while(recentFiles.count >= MaxRecent)
- recentFiles.Delete(recentFiles.GetLast());
- recentFiles.Insert(null, filePath);
- //UpdateRecentMenus(owner);
+ return Array::Add((T)filePath);
}
- void AddRecentProject(const char * projectName)
+ IteratorPointer addRecent(T value)
{
int c;
- char * filePath = CopyString(projectName);
+ char * filePath = (char *)value;
+ IteratorPointer ip;
ChangeCh(filePath, '\\', '/');
- for(c = 0; c<recentProjects.count; c++)
+ for(c = 0; c < count; c++)
{
- if(recentProjects[c] && !fstrcmp(recentProjects[c], filePath))
+ if(this[c] && !fstrcmp(this[c], filePath))
{
- recentProjects.Delete((void *)&recentProjects[c]);
+ Delete((void *)&this[c]);
c--;
}
}
- while(recentProjects.count >= MaxRecent)
- recentProjects.Delete(recentProjects.GetLast());
- recentProjects.Insert(null, filePath);
- //UpdateRecentMenus(owner);
+ while(count >= MaxRecent)
+ Delete(GetLast());
+ ip = Insert(null, filePath);
+ onAdd();
+ return ip;
+ }
+
+ 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);
+ }
+ }
}
}
public:
property const char * name
{
- set
- {
- delete name;
- if(value)
- name = CopyString(value);
- }
+ set { delete name; if(value) name = CopyString(value); }
get { return name; }
}
bool readOnly;
get { return objectFileExt && objectFileExt[0] ? objectFileExt : objectDefaultFileExt ; }
isset { return objectFileExt && objectFileExt[0] && strcmp(objectFileExt, objectDefaultFileExt); }
}
- property const char * outputFileExt
+ property const char * staticLibFileExt
{
- set { delete outputFileExt; if(value && value[0]) outputFileExt = CopyString(value); }
- get { return outputFileExt; }
- isset { return outputFileExt && outputFileExt[0]; }
+ set { delete staticLibFileExt; if(value && value[0]) staticLibFileExt = CopyString(value); }
+ get { return staticLibFileExt; }
+ isset { return staticLibFileExt && staticLibFileExt[0]; }
+ }
+ property const char * sharedLibFileExt
+ {
+ set { delete sharedLibFileExt; if(value && value[0]) sharedLibFileExt = CopyString(value); }
+ get { return sharedLibFileExt; }
+ isset { return sharedLibFileExt && sharedLibFileExt[0]; }
+ }
+ property const char * executableFileExt
+ {
+ set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
+ get { return executableFileExt; }
+ isset { return executableFileExt && executableFileExt[0]; }
}
property const char * executableLauncher
{
get { return sysroot; }
isset { return sysroot && sysroot[0]; }
}
+ bool resourcesDotEar;
+ bool noStripTarget;
property Array<String> includeDirs
{
set
get { return compilerFlags; }
isset { return compilerFlags.count != 0; }
}
+ property Array<String> cxxFlags
+ {
+ set
+ {
+ cxxFlags.Free();
+ if(value)
+ {
+ delete cxxFlags;
+ cxxFlags = value;
+ }
+ }
+ get { return cxxFlags; }
+ isset { return cxxFlags.count != 0; }
+ }
property Array<String> linkerFlags
{
set
get { return executableLauncher; }
isset { return false; }
}
- bool resourcesDotEar;
+ property const char * outputFileExt
+ {
+ set { delete executableFileExt; if(value && value[0]) executableFileExt = CopyString(value); }
+ get { return executableFileExt; }
+ isset { return false; }
+ }
+ // utility
+ property bool hasDocumentOutput
+ {
+ get
+ {
+ bool result = executableFileExt && executableFileExt[0] &&
+ (!strcmpi(executableFileExt, "htm") || !strcmpi(executableFileExt, "html"));
+ return result;
+ }
+ isset { return false; }
+ }
private:
Array<String> includeDirs { };
Array<String> libraryDirs { };
Array<String> excludeLibs { };
Array<String> eCcompilerFlags { };
Array<String> compilerFlags { };
+ Array<String> cxxFlags { };
Array<String> linkerFlags { };
char * name;
char * makeCommand;
char * ldCommand;
char * arCommand;
char * objectFileExt;
- char * outputFileExt;
+ char * staticLibFileExt;
+ char * sharedLibFileExt;
+ char * executableFileExt;
char * executableLauncher;
char * distccHosts;
char * gnuToolchainPrefix;
delete ldCommand;
delete arCommand;
delete objectFileExt;
- delete outputFileExt;
+ delete staticLibFileExt;
+ delete sharedLibFileExt;
+ delete executableFileExt;
delete makeCommand;
delete executableLauncher;
delete distccHosts;
if(prepDirectives) { prepDirectives.Free(); }
if(excludeLibs) { excludeLibs.Free(); }
if(compilerFlags) { compilerFlags.Free(); }
+ if(cxxFlags) { cxxFlags.Free(); }
if(eCcompilerFlags) { eCcompilerFlags.Free(); }
if(linkerFlags) { linkerFlags.Free(); }
}
+ int OnCompare(CompilerConfig b)
+ {
+ int result;
+ if(!(result = name.OnCompare(b.name)) &&
+ !(result = ecpCommand.OnCompare(b.ecpCommand)) &&
+ !(result = eccCommand.OnCompare(b.eccCommand)) &&
+ !(result = ecsCommand.OnCompare(b.ecsCommand)) &&
+ !(result = earCommand.OnCompare(b.earCommand)) &&
+ !(result = cppCommand.OnCompare(b.cppCommand)) &&
+ !(result = ccCommand.OnCompare(b.ccCommand)) &&
+ !(result = cxxCommand.OnCompare(b.cxxCommand)) &&
+ !(result = ldCommand.OnCompare(b.ldCommand)) &&
+ !(result = arCommand.OnCompare(b.arCommand)) &&
+ !(result = objectFileExt.OnCompare(b.objectFileExt)) &&
+ !(result = outputFileExt.OnCompare(b.outputFileExt)) &&
+ !(result = makeCommand.OnCompare(b.makeCommand)) &&
+ !(result = executableLauncher.OnCompare(b.executableLauncher)) &&
+ !(result = distccHosts.OnCompare(b.distccHosts)) &&
+ !(result = gnuToolchainPrefix.OnCompare(b.gnuToolchainPrefix)) &&
+ !(result = sysroot.OnCompare(b.sysroot)))
+ ;
+
+ if(!result &&
+ !(result = includeDirs.OnCompare(b.includeDirs)) &&
+ !(result = libraryDirs.OnCompare(b.libraryDirs)) &&
+ !(result = executableDirs.OnCompare(b.executableDirs)) &&
+ !(result = environmentVars.OnCompare(b.environmentVars)) &&
+ !(result = prepDirectives.OnCompare(b.prepDirectives)) &&
+ !(result = excludeLibs.OnCompare(b.excludeLibs)) &&
+ !(result = cxxFlags.OnCompare(b.cxxFlags)) &&
+ !(result = eCcompilerFlags.OnCompare(b.eCcompilerFlags)) &&
+ !(result = compilerFlags.OnCompare(b.compilerFlags)) &&
+ !(result = linkerFlags.OnCompare(b.linkerFlags)))
+ ;
+
+ return result;
+ }
+
public:
CompilerConfig Copy()
{
arCommand,
ldCommand,
objectFileExt,
- outputFileExt,
+ staticLibFileExt,
+ sharedLibFileExt,
+ executableFileExt,
executableLauncher,
ccacheEnabled,
distccEnabled,
false,
distccHosts,
gnuToolchainPrefix,
- sysroot
+ sysroot,
+ resourcesDotEar,
+ noStripTarget
};
for(s : includeDirs) copy.includeDirs.Add(CopyString(s));
for(s : libraryDirs) copy.libraryDirs.Add(CopyString(s));
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 : cxxFlags) copy.cxxFlags.Add(CopyString(s));
for(s : eCcompilerFlags) copy.eCcompilerFlags.Add(CopyString(s));
for(s : linkerFlags) copy.linkerFlags.Add(CopyString(s));
incref copy;
return copy;
}
+
+ 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;
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
+ setEcereLanguageInWinRegEnvironment(code);
if(eClass_IsDerived(app._class, class(GuiApplication)))
{
delete command;
return restart;
}
+#endif