ecere/sys/GlobalSettings: improve code.
authorRejean Loyer <redj@ecere.com>
Wed, 18 Jun 2014 20:07:19 +0000 (16:07 -0400)
committerJerome St-Louis <jerome@ecere.com>
Thu, 19 Jun 2014 05:27:35 +0000 (01:27 -0400)
 - add support for setting portable to true and according behavior.
 - remember successful read and write types.
 - add good commented out debugging PrintLn for read/write tries and successes.

ecere/src/sys/GlobalAppSettings.ec

index a4df515..bf9a9f5 100644 (file)
@@ -20,6 +20,9 @@ public enum GlobalSettingType
    stringList
 };
 
+// note: missing application data location support on windows
+enum SettingsLocationType { none, specified, portable, home, winUserProfile, winHomeDrive, winSystemPath, winAllUsers, nixEtc };
+
 public enum SettingsIOResult { error, success, fileNotFound, fileNotCompatibleWithDriver };
 
 public class GlobalSettingsDriver
@@ -110,6 +113,11 @@ public:
       set { allUsers = value; }
       get { return allUsers; }
    };
+   property bool portable
+   {
+      set { portable = value; }
+      get { return portable; }
+   };
 
    property const String driver
    {
@@ -124,7 +132,6 @@ public:
    GlobalSettingsData data;
    GlobalSettingsData * dataOwner;
    subclass(GlobalSettingsData) dataClass;
-   bool portable;
 
 private:
    char * settingsName;
@@ -133,8 +140,11 @@ private:
    char * settingsFilePath;
    bool allowDefaultLocations;
    bool allUsers;
+   bool portable;
    bool globalPath;
    char * settingsDirectory;
+   SettingsLocationType readType;
+   SettingsLocationType writeType;
 
    FileMonitor settingsMonitor
    {
@@ -163,103 +173,93 @@ private:
       delete settingsDirectory;
    }
 
-   char * PrepareSpecifiedLocationPath(const char * extension, bool create)
-   {
-      char * path = null;
-      char location[MAX_LOCATION] = "";
-      if(settingsLocation)
-         strcpy(location, settingsLocation);
-      path = GetFilePath(location, extension, create, false, false);
-      return path;
-   }
-
-   char * PreparePortablePath(const char * extension, bool create)
+   char * PreparePath(SettingsLocationType type, const char * extension, bool create, bool unixStyle)
    {
-      //
       char * path = null;
-      char location[MAX_LOCATION];
-      LocateModule(null, location);
-      StripLastDirectory(location, location);
-      path = GetFilePath(location, extension, create, false, false);
-      return path;
-   }
-
-   char * PrepareHomePath(const char * extension, bool create, bool unixStyle)
-   {
-      // ~/.apprc
-      char * path = null;
-      char * home = getenv("HOME");
-      if(home && home[0])
+      char * buffer = new char[MAX_LOCATION];
+      switch(type)
       {
-         char location[MAX_LOCATION];
-         strcpy(location, home);
-         path = GetFilePath(location, extension, create, true, unixStyle);
-      }
-      return path;
-   }
-
+         case specified:
+            if(settingsLocation)
+            {
+               buffer[0] = '\0';
+               strcpy(buffer, settingsLocation);
+               path = GetFilePath(buffer, extension, create, false, false);
+            }
+            break;
+         case portable:
+            buffer[0] = '\0';
+            LocateModule(null, buffer);
+            StripLastDirectory(buffer, buffer);
+            path = GetFilePath(buffer, extension, create, false, false);
+            break;
+         case home:
+         {
+            // ~/.apprc
+            char * home = getenv("HOME");
+            if(home && home[0])
+            {
+               strcpy(buffer, home);
+               path = GetFilePath(buffer, extension, create, true, unixStyle);
+            }
+            break;
+         }
 #if defined(__WIN32__)
-   char * PrepareUserProfilePath(const char * extension, bool create)
-   {
-      // Windows attempts: $USERPROFILE/app.ini
-      char * path = null;
-      char * profile = getenv("USERPROFILE");
-      if(profile && profile[0])
-      {
-         char location[MAX_LOCATION];
-         strcpy(location, profile);
-         path = GetFilePath(location, extension, create, false, false);
-      }
-      return path;
-   }
-
-   char * PrepareHomeDrivePath(const char * extension, bool create)
-   {
-      char * path = null;
-      const char * homedrive = getenv("HOMEDRIVE");
-      const char * homepath = getenv("HOMEPATH");
-      if(homedrive && homedrive[0] && homepath && homepath[0])
-      {
-         char location[MAX_LOCATION];
-         strcpy(location, homedrive);
-         PathCatSlash(location, homepath);
-         path = GetFilePath(location, extension, create, false, false);
-      }
-      return path;
-   }
-
-   char * PrepareSystemPath(const char * extension, bool create)
-   {
-      char * path = null;
-      uint16 _wfilePath[MAX_LOCATION];
-      char location[MAX_LOCATION];
-      GetSystemDirectory(_wfilePath, MAX_LOCATION);
-      UTF16toUTF8Buffer(_wfilePath, location, MAX_LOCATION);
-      path = GetFilePath(location, extension, create, false, false);
-      return path;
-   }
-
-   char * PrepareAllUsersPath(const char * extension, bool create)
-   {
-      char * path = null;
-      char * allUsers = getenv("ALLUSERSPROFILE");
-      if(allUsers && allUsers[0])
-      {
-         char location[MAX_LOCATION];
-         strcpy(location, allUsers);
-         path = GetFilePath(location, extension, create, false, false);
-      }
-      return path;
-   }
+         case winUserProfile:
+         {
+            // Windows attempts: $USERPROFILE/app.ini
+            char * profile = getenv("USERPROFILE");
+            if(profile && profile[0])
+            {
+               strcpy(buffer, profile);
+               path = GetFilePath(buffer, extension, create, false, false);
+            }
+            break;
+         }
+         case winHomeDrive:
+         {
+            const char * homedrive = getenv("HOMEDRIVE");
+            const char * homepath = getenv("HOMEPATH");
+            if(homedrive && homedrive[0] && homepath && homepath[0])
+            {
+               strcpy(buffer, homedrive);
+               PathCatSlash(buffer, homepath);
+               path = GetFilePath(buffer, extension, create, false, false);
+            }
+            break;
+         }
+         case winSystemPath:
+         {
+            uint16 _wfilePath[MAX_LOCATION];
+            buffer[0] = '\0';
+            GetSystemDirectory(_wfilePath, MAX_LOCATION);
+            UTF16toUTF8Buffer(_wfilePath, buffer, MAX_LOCATION);
+            path = GetFilePath(buffer, extension, create, false, false);
+            break;
+         }
+         case winAllUsers:
+         {
+            char * allUsers = getenv("ALLUSERSPROFILE");
+            if(allUsers && allUsers[0])
+            {
+               strcpy(buffer, allUsers);
+               path = GetFilePath(buffer, extension, create, false, false);
+            }
+            break;
+         }
 #else
-   char * PrepareEtcPath(const char * extension, bool create)
-   {
-      char * path = null;
-      char location[MAX_LOCATION] = "/etc/";
-      path = GetFilePath(location, extension, create, false, false);
+         case nixEtc:
+         {
+            strcpy(buffer, "/etc/");
+            path = GetFilePath(buffer, extension, create, false, false);
+            delete buffer;
+            break;
+         }
+#endif
+      }
+      if(!path) delete buffer;
       return path;
    }
-#endif
 
    char * GetFilePath(char * location, const char * extension, bool create, bool dotPrefix, bool runCommandsStyle)
    {
@@ -267,7 +267,7 @@ private:
       FileAttribs attribs;
       if(location[0])
          MakeSlashPath(location);
-      if(location[0] && (attribs = FileExists(location)).isDirectory)
+      if(location[0] && (attribs = FileExists(location)) && (attribs.isDirectory || attribs.isDrive))
       {
          if(settingsDirectory)
          {
@@ -282,7 +282,7 @@ private:
                MakeDir(location);
             attribs = FileExists(location);
          }
-         if(attribs.isDirectory)
+         if(attribs.isDirectory || attribs.isDrive)
          {
             char * name = new char[strlen(settingsName) + strlen(extension) + 2];
             if(dotPrefix && !settingsDirectory)
@@ -299,9 +299,8 @@ private:
                strcat(name, ".");
                strcat(name, extension);
             }
-            path = new char[strlen(location) + strlen(name) + 16];
-            strcpy(path, location);
-            PathCatSlash(path, name);
+            PathCatSlash(location, name);
+            path = location;
             delete name;
          }
       }
@@ -322,15 +321,20 @@ private:
       return extension;
    }
 
-   void FileOpenTryRead()
+   void FileOpenTryRead(SettingsLocationType type)
    {
       f = FileOpen(settingsFilePath, read);
-      //PrintLn("GlobalSettings::FileOpenTryRead -- ", settingsFilePath, " -- ", f != null);
-      if(!f)                       // This delete will cover both trying the next possible config location and
+      //PrintLn("GlobalSettings::FileOpenTryRead(", type, ") (", settingsFilePath, ") -- ", f ? "SUCCESS" : "FAIL");
+      if(f)
+         readType = type;
+      else
+      {
+                                   // This delete will cover both trying the next possible config location and
          delete settingsFilePath;  // the case when we're doing a load when the config file is no longer available
-   }                               // and we want to re-try all possible config locations.
+      }                            // and we want to re-try all possible config locations.
+   }
 
-   bool FileOpenTryWrite(bool shouldDelete, bool * locked)
+   bool FileOpenTryWrite(SettingsLocationType type, bool shouldDelete, bool * locked)
    {
       *locked = false;
       f = FileOpen(settingsFilePath, readWrite);
@@ -343,8 +347,10 @@ private:
             f = FileOpen(settingsFilePath, readWrite);
          }
       }
+      //PrintLn("GlobalSettings::FileOpenTryWrite(", type, ") (", settingsFilePath, ") -- ", f ? "SUCCESS" : "FAIL");
       if(f)
       {
+         writeType = type;
          // Don't wait for a lock, first one to lock gets to write, other will likely loose changes on a reload.
          if(f.Lock(exclusive, 0, 0, false))
          {
@@ -356,9 +362,10 @@ private:
             }
          }
       }
-      else if(shouldDelete)        // This delete will cover both trying the next possible config location and
-         delete settingsFilePath;  // allow trying to save to a location where user has permission.
-      //PrintLn("GlobalSettings::FileOpenTryWrite -- ", settingsFilePath, " -- ", f != null);
+      else if(shouldDelete)
+      {
+         delete settingsFilePath;  // This delete will cover both trying the next possible config location and
+      }                            // allow trying to save to a location where user has permission.
       return f != null;
    }
 
@@ -367,55 +374,56 @@ public:
 
    bool OpenAndLock(FileSize * fileSize)
    {
+      SettingsLocationType type = readType;
       if(!f)
       {
          settingsMonitor.StopMonitoring();
 
          if(settingsFilePath)
-            FileOpenTryRead();
+            FileOpenTryRead(type);
 
          if(!settingsFilePath && settingsName && settingsName[0])
          {
             const char * extension = GetExtension();
 
-            if(!f && (settingsFilePath = PrepareSpecifiedLocationPath(extension, false)))
-               FileOpenTryRead();
+            if(!f && (settingsFilePath = PreparePath((type = specified), extension, false, false)))
+               FileOpenTryRead(type);
             if(!f && (!settingsLocation || allowDefaultLocations))
             {
                globalPath = false;
-               if(!f && (settingsFilePath = PreparePortablePath(extension, false)))
-                  FileOpenTryRead();
+               if(!f && (settingsFilePath = PreparePath((type = portable), extension, false, false)))
+                  FileOpenTryRead(type);
                if(f)
                   portable = true;
                if(!allUsers)
                {
 #if defined(__WIN32__)
-                  if(!f && (settingsFilePath = PrepareHomePath(extension, false, false)))
-                     FileOpenTryRead();
+                  if(!f && (settingsFilePath = PreparePath((type = home), extension, false, false)))
+                     FileOpenTryRead(type);
 #endif
-                  if(!f && (settingsFilePath = PrepareHomePath(extension, false, true)))
-                     FileOpenTryRead();
+                  if(!f && (settingsFilePath = PreparePath((type = home), extension, false, true)))
+                     FileOpenTryRead(type);
                }
 #if defined(__WIN32__)
                if(!allUsers)
                {
-                  if(!f && (settingsFilePath = PrepareUserProfilePath(extension, false)))
-                     FileOpenTryRead();
-                  if(!f && (settingsFilePath = PrepareHomeDrivePath(extension, false)))
-                     FileOpenTryRead();
+                  if(!f && (settingsFilePath = PreparePath((type = winUserProfile), extension, false, false)))
+                     FileOpenTryRead(type);
+                  if(!f && (settingsFilePath = PreparePath((type = winHomeDrive), extension, false, false)))
+                     FileOpenTryRead(type);
                }
                if(!f)
                   globalPath = true;
-               if(!f && (settingsFilePath = PrepareAllUsersPath(extension, false)))
-                  FileOpenTryRead();
+               if(!f && (settingsFilePath = PreparePath((type = winAllUsers), extension, false, false)))
+                  FileOpenTryRead(type);
 
-               if(!f && (settingsFilePath = PrepareSystemPath(extension, false)))
-                  FileOpenTryRead();
+               if(!f && (settingsFilePath = PreparePath((type = winSystemPath), extension, false, false)))
+                  FileOpenTryRead(type);
 #else
                if(!f)
                   globalPath = true;
-               if(!f && (settingsFilePath = PrepareEtcPath(extension, false)))
-                  FileOpenTryRead();
+               if(!f && (settingsFilePath = PreparePath((type = nixEtc), extension, false, false)))
+                  FileOpenTryRead(type);
 #endif
             }
          }
@@ -459,6 +467,7 @@ public:
    virtual SettingsIOResult Save()
    {
       SettingsIOResult result = error;
+      SettingsLocationType type = writeType;
       if(!f)
       {
          locked = false;
@@ -467,54 +476,52 @@ public:
 
          if(settingsFilePath)
             // Don't auto delete settingsFilePath because only want to try another path if we were using a global path
-            FileOpenTryWrite(false, &locked);
+            FileOpenTryWrite(type, false, &locked);
 
          if((!settingsFilePath || (!f && globalPath)) && settingsName && settingsName[0])
          {
             const char * extension = GetExtension();
             delete settingsFilePath;
 
-            if(!f && (settingsFilePath = PrepareSpecifiedLocationPath(extension, true)))
-               FileOpenTryWrite(true, &locked);
+            if(!f && (settingsFilePath = PreparePath((type = specified), extension, true, false)))
+               FileOpenTryWrite(type, true, &locked);
             if(!f && (!settingsLocation || allowDefaultLocations))
             {
                globalPath = true;
-               // never try to write a new portable configuration file?
-               //       -- Probably always want to write back to the same file, the first FileOpenTryWrite(true) should succeed
-               //if(!f && (settingsFilePath = PreparePortablePath(extension, true)))
-               //   FileOpenTryWrite(true);
+               if(!f && portable && (settingsFilePath = PreparePath((type = portable), extension, true, false)))
+                  FileOpenTryWrite(type, true, &locked);
 #if defined(__WIN32__)
-               if(!f && allUSers && (settingsFilePath = PrepareAllUsersPath()))
-                  FileOpenTryWrite(true, &locked);
+               if(!f && allUsers && (settingsFilePath = PreparePath((type = winAllUsers), extension, true, false)))
+                  FileOpenTryWrite(type, true, &locked);
 #else
-               if(!f && allUSers && (settingsFilePath = PrepareEtcPath()))
-                  FileOpenTryWrite(true, &locked);
+               if(!f && allUsers && (settingsFilePath = PreparePath((type = nixEtc), extension, true, false)))
+                  FileOpenTryWrite(type, true, &locked);
 #endif
                if(!f && !allUsers)
                {
                   globalPath = false;
-                  if(!f && (settingsFilePath = PrepareHomePath(extension, true,
+                  if(!f && (settingsFilePath = PreparePath((type = home), extension, true,
 #if defined(__WIN32__)
                      false
 #else
                      true
 #endif
                      )))
-                     FileOpenTryWrite(true, &locked);
+                     FileOpenTryWrite(type, true, &locked);
                }
 #if defined(__WIN32__)
                if(!f && !allUsers)
                {
                   globalPath = false;
-                  if(!f && (settingsFilePath = PrepareUserProfilePath(extension, true)))
-                     FileOpenTryWrite(true, &locked);
-                  if(!f && (settingsFilePath = PrepareHomeDrivePath(extension, true)))
-                     FileOpenTryWrite(true, &locked);
+                  if(!f && (settingsFilePath = PreparePath((type = winUserProfile), extension, true, false)))
+                     FileOpenTryWrite(type, true, &locked);
+                  if(!f && (settingsFilePath = PreparePath((type = winHomeDrive), extension, true, false)))
+                     FileOpenTryWrite(type, true, &locked);
                }
-               if(!f && (settingsFilePath = PrepareSystemPath(extension, true)))
+               if(!f && (settingsFilePath = PreparePath((type = winSystemPath), extension, true, false)))
                {
                   globalPath = true;
-                  FileOpenTryWrite(true, &locked);
+                  FileOpenTryWrite(type, true, &locked);
                }
 #endif
             }