buildsystem, ide; added install feature. aka install library or executable from ide...
[sdk] / ide / src / ProjectSettings.ec
index d62095e..223f53f 100644 (file)
@@ -9,16 +9,32 @@ static Platform platform;
 static ProjectNode currentNode;
 static Project project;
 
-static String MakeString(char * s, int len)
+static String MakeString(char * s, int len, char * switchToKeep, int lenSwitchToKeep)
 {
    String string = new char[len+1];
-   memcpy(string, s, len);
-   string[len] = 0;
+   if(s[0] == '-' && switchToKeep && switchToKeep[0])
+   {
+      if(strstr(s+1, switchToKeep) == s+1)
+      {
+         memcpy(string, s+lenSwitchToKeep+1, len-lenSwitchToKeep-1);
+         string[len-lenSwitchToKeep-1] = '\0';
+      }
+      else
+         delete string;
+   }
+   else
+   {
+      memcpy(string, s, len);
+      string[len] = '\0';
+   }
    return string;
 }
 
 class StringListBox : EditBox
 {
+   char * switchToKeep;
+   int lenSwitchToKeep;
+
    textHorzScroll = true;
 
    property Array<String> strings
@@ -31,15 +47,13 @@ class StringListBox : EditBox
             bool first = true;
             for(item : value)
             {
-               bool quoted = strchr(item, ' ') != null;
-               if(!first)
-                  AddS(" ");
-               if(quoted)
-                  AddS("\"");
-               AddS(item);
-               if(quoted)
-                  AddS("\"");
-               first = false;
+               if(item)
+               {
+                  if(!first)
+                     AddS(" ");
+                  AddS(item);
+                  first = false;
+               }
             }
          }
       }
@@ -48,6 +62,7 @@ class StringListBox : EditBox
          Array<String> array { };
          int c, start = 0;
          char * contents = property::contents;
+         char * s;
          char ch;
          bool quoted = false;
 
@@ -56,27 +71,25 @@ class StringListBox : EditBox
             if(ch == ' ' && !quoted)
             {
                if(c - start)
-                  array.Add(MakeString(contents + start, c - start));
+               {
+                  if((s = MakeString(contents + start, c - start, switchToKeep, lenSwitchToKeep)))
+                     array.Add(s);
+               }
                start = c + 1;
             }
             else if(ch == '\"')
             {
                if(quoted)
-               {
-                  if(c - start)
-                     array.Add(MakeString(contents + start, c - start));
                   quoted = false;
-                  start = c + 1;
-               }
                else
-               {
                   quoted = true;
-                  start = c + 1;
-               }
             }
          }
          if(c - start)
-            array.Add(MakeString(contents + start, c - start));
+         {
+            if((s = MakeString(contents + start, c - start, switchToKeep, lenSwitchToKeep)))
+               array.Add(s);
+         }
          return array;
       }
    }
@@ -89,10 +102,10 @@ class ProjectSettings : Window
    text = dialogTitle;
    background = formColor;
    borderStyle = sizable;
-   minClientSize = { 650, 490 };
+   minClientSize = { 650, 520 };
    hasClose = true;
    tabCycle = true;
-   size = { 650, 490 };
+   size = { 650, 520 };
 
    property Project project
    {
@@ -219,7 +232,6 @@ class ProjectSettings : Window
             project.topNode.modified = true;
             project.MarkChanges(buildTab.backupNode);
             ide.projectView.modifiedDocument = true;
-            ide.UpdateToolBarActiveConfigs(false);
             ide.projectView.Update(null);
          }
          if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
@@ -241,6 +253,10 @@ class ProjectSettings : Window
    {
       UpdateDialogTitle();
       prjTabControl.curTab = buildTab;
+
+      ((DirectoriesBox)buildTab.compilerTab.includeDirs.editor).baseBrowsePath = project.topNode.path;
+      ((DirectoriesBox)buildTab.linkerTab.libraryDirs.editor).baseBrowsePath = project.topNode.path;
+
       return true;
    }
 }
@@ -276,7 +292,7 @@ class OptionBox<class Z> : CommonControl
    }
 
    property bool visible { set { editor.visible = value; } get { return editor.visible; } }
-   property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int)this; } }
+   property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int64)this; } }
    property Point position { set { editor.position = value; } }
    property Size size { set { editor.size = value; } }
    property Anchor anchor { set { editor.anchor = value; } }
@@ -765,6 +781,7 @@ class PathOptionBox : OptionBox<String>
 
       bool NotifyModified(PathBox pathBox)
       {
+         FixPathOnPathBoxNotifyModified(pathBox);
          ((OptionBox)pathBox.id).Retrieve();
          return true;
       }
@@ -827,7 +844,7 @@ class MultiStringOptionBox : OptionBox<Array<String>>
             {
                String s = it.data;
                bool found = false;
-               for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
+               for(i : tempStrings; i && s && !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
                if(found && (!configReplaces || platform))   // ADDED || platform here...
                {
                   delete s;
@@ -861,7 +878,7 @@ class MultiStringOptionBox : OptionBox<Array<String>>
             for(s : strings)
             {
                bool found = false;
-               for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
+               for(i : tempStrings; i && s && !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
                if(!found) tempStrings.Add(s);
             }
          }
@@ -919,6 +936,8 @@ class StringArrayOptionBox : MultiStringOptionBox
    // NO VIRTUAL PROPERTIES YET...
    Array<String> GetStrings() { return ((StringListBox)editor).strings; }
    void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
+
+   property char * switchToKeep { set { ((StringListBox)editor).switchToKeep = value; ((StringListBox)editor).lenSwitchToKeep = strlen(value); } };
 }
 
 class StringsArrayOptionBox : MultiStringOptionBox
@@ -942,68 +961,113 @@ class StringsArrayOptionBox : MultiStringOptionBox
    void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
 }
 
-class DirsArrayOptionBox : MultiStringOptionBox
+bool eString_IsPathRelatedTo(char * path, char * to)
 {
-   editor = DirectoriesBox
+   if(path[0] && to[0])
    {
-      bool NotifyModified(DirectoriesBox dirsBox)
-      {
-         ((OptionBox)dirsBox.id).Retrieve();
-         return true;
-      }
-
-      bool OnChangedDir(char * * directory)
+      char rest[MAX_FILENAME];
+      char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION] = "";
+      char toPart[MAX_FILENAME], toRest[MAX_LOCATION] = "";
+      SplitDirectory(path, pathPart, pathRest);
+      SplitDirectory(to, toPart, toRest);
+      if(!fstrcmp(pathPart, toPart))
       {
-         char fixedDirectory[MAX_LOCATION] = "";
-         if(PathCat(fixedDirectory, *directory))
+         if(pathRest[0] && toRest[0])
          {
-            char cwdBackup[MAX_LOCATION];
-            if(project)
-            {
-               GetWorkingDir(cwdBackup, sizeof(cwdBackup));
-               ChangeWorkingDir(project.topNode.path);
-            }
-            FileFixCase(fixedDirectory);
-            if(project)
-               ChangeWorkingDir(cwdBackup);
-            delete *directory;
-            *directory = CopyString(fixedDirectory);
-            return true;
+            SplitDirectory(pathRest, pathPart, pathRest);
+            SplitDirectory(toRest, toPart, toRest);
+            if(!fstrcmp(pathPart, toPart))
+               return true;
          }
-         return false;
       }
+   }
+   return false;
+}
+
+static void FixPathOnPathBoxNotifyModified(PathBox pathBox)
+{
+   int len;
+   char path[MAX_LOCATION];
+   ValidPathBufCopy(path, pathBox.path);
+   len = strlen(path);
+   if(len && !(path[0] == '.' && (len == 1 || (len == 2 && path[1] == DIR_SEP) || (len > 1 && path[1] == '.'))))
+   {
+      char cwdBackup[MAX_LOCATION];
+      if(project)
+      {
+         GetWorkingDir(cwdBackup, sizeof(cwdBackup));
+         ChangeWorkingDir(project.topNode.path);
+      }
+      FileFixCase(path);
+      if(project)
+         ChangeWorkingDir(cwdBackup);
+      if(eString_IsPathRelatedTo(path, project.topNode.path))
+         MakePathRelative(path, project.topNode.path, path);
+      if(!path[0])
+         strcpy(path, ".");
+      len = strlen(path);
+   }
+   if(len>1 && path[len-1] == DIR_SEP)
+      path[--len] = '\0';
+   pathBox.path = path;
+}
+
+class DirsArrayOptionBox : MultiStringOptionBox
+{
+public:
+   property char * switchToKeep { set { switchToKeep = value; lenSwitchToKeep = strlen(value); } };
+private:
+   char * switchToKeep;
+   int lenSwitchToKeep;
 
-      bool OnPrepareBrowseDir(char * * directory)
+   editor = DirectoriesBox
+   {
+      browseDialog = { };
+      bool NotifyModified(DirectoriesBox dirsBox)
       {
-         char dir[MAX_LOCATION];
-         if(project)
+         char * switchToKeep = ((DirsArrayOptionBox)dirsBox.id).switchToKeep;
+         if(switchToKeep && switchToKeep[0])
          {
-            GetSystemPathBuffer(dir, project.topNode.path);
-            if(*directory)
-               PathCat(dir, *directory);
+            bool change = false;
+            int lenSwitchToKeep = ((DirsArrayOptionBox)dirsBox.id).lenSwitchToKeep;
+            Array<String> dirs { };
+            Array<String> previousDirs = dirsBox.strings;
+            for(d : previousDirs)
+            {
+               int c;
+               char * buffer = new char[strlen(d)+64];
+               char * tokens[1024];
+               uint count;
+               strcpy(buffer, d);
+               count = Tokenize(buffer, sizeof(tokens)/sizeof(tokens[0]), tokens, (BackSlashEscaping)false);
+               for(c=0; c<count; c++)
+               {
+                  if(tokens[c][0] == '-')
+                  {
+                     if(strstr(tokens[c]+1, switchToKeep) == tokens[c]+1)
+                        tokens[c] += lenSwitchToKeep+1;
+                     else
+                        tokens[c][0] = '\0';
+                     change = true;
+                  }
+                  dirs.Add(CopyString(tokens[c]));
+               }
+               delete buffer;
+            }
+            if(change)
+               dirsBox.strings = dirs;
+            dirs.Free();
+            delete dirs;
+            previousDirs.Free();
+            delete previousDirs;
          }
-         else if(*directory)
-            strcpy(dir, *directory);
-         else
-            dir[0] = '\0';
-         
-         delete *directory;
-         *directory = CopyString(dir);
-
-            // GCC 4.4 bug:  -----  path becomes *directory
-            //strcpy(dir, path ? path : "");
+         ((OptionBox)dirsBox.id).Retrieve();
          return true;
       }
 
-      bool OnBrowsedDir(char * * directory)
+      bool NotifyPathBoxModified(DirectoriesBox dirsBox, PathBox pathBox)
       {
-         if(project)
-         {
-            char path[MAX_LOCATION];
-            MakePathRelative(*directory, project.topNode.path, path);
-            delete *directory;
-            *directory = CopyString(path);
-         }
+         FixPathOnPathBoxNotifyModified(pathBox);
          return true;
       }
    };
@@ -1098,7 +1162,7 @@ class DropOptionBox : OptionBox
    {
       DropBox dropBox = (DropBox)editor;
       Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
-      dropBox.currentRow = value ? dropBox.FindRow((int)value) : dropBox.firstRow;
+      dropBox.currentRow = value ? dropBox.FindRow((int64)value) : dropBox.firstRow;
    }
 
    void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
@@ -1325,7 +1389,7 @@ class BuildTab : Tab
 
          button =
          {
-            configSelector, renameable = true, master = this, text = config.name, id = (int)config;
+            configSelector, renameable = true, master = this, text = config.name, id = (int64)config;
             NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
          };
 
@@ -1377,7 +1441,7 @@ class BuildTab : Tab
                   }
                }
                */
-               SelectorButton button = configSelector.FindButtonByID((int)configToDelete);
+               SelectorButton button = configSelector.FindButtonByID((int64)configToDelete);
                if(button)
                   configSelector.RemoveButton(button);
 
@@ -1581,13 +1645,13 @@ class BuildTab : Tab
          }
          else
          {
-            compilerTab.rightPaneHeader.id = (int)node;
+            compilerTab.rightPaneHeader.id = (int64)node;
             compilerTab.rightPaneHeader.Update(null);
             compilerTab.rightPaneHeader.visible = true;
          }
 
          {
-            DataRow row = compilerTab.fileList.FindSubRow((int)currentNode);
+            DataRow row = compilerTab.fileList.FindSubRow((int64)currentNode);
             if(row)
             {
                compilerTab.fileList.currentRow = row;
@@ -1615,8 +1679,6 @@ class BuildTab : Tab
             compilerTab.labelOptimization.visible = !newNodeRes;
             compilerTab.optimization.visible = !newNodeRes;
             compilerTab.fastMath.visible = !newNodeRes;
-            compilerTab.m32.visible = !newNodeRes;
-            compilerTab.m64.visible = !newNodeRes;
             compilerTab.labelIncludeDirs.visible = !newNodeRes;
             compilerTab.includeDirs.visible = !newNodeRes;
          }
@@ -1662,7 +1724,7 @@ class BuildTab : Tab
       // Create Config Buttons
       commonButton = SelectorButton
       {
-         configSelector, master = this, text = $"Common", id = (int)null; font = { font.faceName, font.size, true };
+         configSelector, master = this, text = $"Common", id = (int64)null; font = { font.faceName, font.size, true };
          checked = true;
          NotifyClicked = ConfigClicked;
       };
@@ -1675,7 +1737,7 @@ class BuildTab : Tab
          {
             EditableSelectorButton button
             {
-               configSelector, master = this, renameable = true, text = c.name, id = (int)c;
+               configSelector, master = this, renameable = true, text = c.name, id = (int64)c;
                NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
             };
          }
@@ -1705,7 +1767,7 @@ class BuildTab : Tab
       {
          SelectorButton button
          {
-            platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int)p; 
+            platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int64)p; 
             NotifyClicked = PlatformClicked;
          };
       }
@@ -1767,6 +1829,14 @@ class BuildTab : Tab
             }
          }
       }
+      if(!project.config)
+      {
+         List<ProjectConfig> configs = project.topNode.configurations;
+         if(configs && configs.count)
+            project.config = configs[0];
+      }
+
+      ide.UpdateToolBarActiveConfigs(false);
    }
 
    void RevertChanges()
@@ -1904,8 +1974,8 @@ class CompilerTab : Tab
          if(id)
          {
             ide.projectView.drawingInProjectSettingsDialogHeader = true;
-            class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay](class(ProjectNode),
-               id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
+            ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay])(class(ProjectNode),
+               (void *)id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
             ide.projectView.drawingInProjectSettingsDialogHeader = false;
          }
       }
@@ -1974,12 +2044,6 @@ class CompilerTab : Tab
       text = $"Optimization", hotKey = altO, option = OPTION(optimization);
    };
 
-   BuildBitDepthOptionBox m32
-   {
-      rightPane, this, position = { 348, 154 };
-      text = $"32bit", hotKey = alt3, option = OPTION(buildBitDepth), enumValue = bits32;
-   };
-
    BoolOptionBox debug
    {
       rightPane, this, position = { 8, 188 };
@@ -1998,17 +2062,19 @@ class CompilerTab : Tab
       text = $"No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
    };
 
-   BuildBitDepthOptionBox m64
+   Label labelCompilerOptions { rightPane, this, position = { 8, 208 }, labeledWindow = compilerOptions };
+   StringArrayOptionBox compilerOptions
    {
-      rightPane, this, position = { 348, 188 };
-      text = $"64bit", hotKey = alt6, option = OPTION(buildBitDepth), enumValue = bits64;
+      rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 224, right = 8 };
+      text = $"Compiler Options", hotKey = altO, option = OPTION(compilerOptions);
+      configReplaces = true;
    };
 
    Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
    DirsArrayOptionBox includeDirs
    {
-      rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 208, right = 8, bottom = 8 };
-      text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs);
+      rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 250, right = 8, bottom = 8 };
+      text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs), switchToKeep = "I";
    };
 
    CompilerTab()
@@ -2028,7 +2094,7 @@ class CompilerTab : Tab
    {
       DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
 
-      row.tag = (int)node;
+      row.tag = (int64)node;
 
       row.SetData(null, node);
 
@@ -2099,7 +2165,7 @@ class LinkerTab : Tab
    StringArrayOptionBox libraries
    {
       this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
-      text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries);
+      text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries), switchToKeep = "l";
       configReplaces = true;
    };
 
@@ -2127,7 +2193,7 @@ class LinkerTab : Tab
    DirsArrayOptionBox libraryDirs
    {
       this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
-      text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs);
+      text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs), switchToKeep = "L";
    };
 
    bool OnCreate()
@@ -2161,17 +2227,24 @@ class BuilderTab : Tab
    Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
    StringsArrayOptionBox prebuildCommands
    {
-      this, size = { 290, 100 }, anchor = { left = 8, top = 8, right = 8, bottom = 0.5 };
+      this, size = { 290, 100 }, anchor = { left = 8, top = 8, right = 8, bottom = 0.66 };
       text = $"Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
    };
 
    Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
    StringsArrayOptionBox postbuildCommands
    {
-      this, size = { 290 }, anchor = { left = 8, top = 0.5, right = 8, bottom = 8 };
+      this, size = { 290 }, anchor = { left = 8, top = 0.33, right = 8, bottom = 0.33 };
       text = $"Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
    };
 
+   Label labelInstallCommands { installCommands.editor, labeledWindow = installCommands, position = { 0, 6 }; };
+   StringsArrayOptionBox installCommands
+   {
+      this, size = { 290 }, anchor = { left = 8, top = 0.66, right = 8, bottom = 8 };
+      text = $"Install Commands", hotKey = altT, option = OPTION(installCommands);
+   };
+
    void LoadSettings()
    {
       bool disabled = strlen(((BuildTab)master).selectedPlatformName) > 0;