ide: Fixed zombie documentor processes
[sdk] / ide / src / ide.ec
index 2e9cc4b..30d3837 100644 (file)
@@ -246,6 +246,9 @@ class IDEToolbar : ToolBar
    // Compile actual file
    // Execute
    ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
+#ifdef IDE_SHOW_INSTALL_MENU_BUTTON
+   ToolButton buttonInstall { this, toolTip = $"Install", menuItemPtr = IDEItem(projectInstallItem), disabled = true; };
+#endif
 
    ToolSeparator separator4 { this };
 
@@ -279,21 +282,7 @@ class IDEToolbar : ToolBar
       bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
       {
          if(row)
-         {
-            for(prj : ide.workspace.projects)
-            {
-               for(cfg : prj.configurations)
-               {
-                  if(cfg.name && !strcmp(cfg.name, row.string))
-                  {
-                     prj.config = cfg;
-                     break;
-                  }
-               }
-            }
-            ide.UpdateToolBarActiveConfigs(true);
-            ide.projectView.Update(null);
-         }
+            ide.workspace.SelectActiveConfig(row.string);
          return true;
       }
    };
@@ -418,6 +407,7 @@ class IDEWorkSpace : Window
    MenuItem * driverItems, * skinItems;
    StatusField pos { width = 150 };
    StatusField ovr, caps, num;
+   DualPipe documentor;
 
    BitmapResource back                 { ":ecereBack.jpg", window = this };
    BitmapResource bmpBp                { ":codeMarks/breakpoint.png", window = this };
@@ -831,6 +821,7 @@ class IDEWorkSpace : Window
             {
                DialogResult result;
                NewProjectDialog newProjectDialog { master = this };
+               incref newProjectDialog;
                result = newProjectDialog.Modal();
                if(result == ok)
                {
@@ -845,6 +836,7 @@ class IDEWorkSpace : Window
                      }
                   }
                }
+               delete newProjectDialog;
             }
             return true;
          }
@@ -1043,6 +1035,19 @@ class IDEWorkSpace : Window
             return true;
          }
       }
+      MenuItem projectInstallItem
+      {
+#ifdef IDE_SHOW_INSTALL_MENU_BUTTON
+         projectMenu, $"Install", t, disabled = true;
+#endif
+         bitmap = { ":status/software-update-available.png" };
+         bool NotifySelect(MenuItem selection, Modifiers mods)
+         {
+            if(projectView)
+               projectView.ProjectInstall(projectView.active ? selection : null, mods);
+            return true;
+         }
+      }
       MenuItem projectCompileItem;
    Menu debugMenu { menu, $"Debug", d, hasMargin = true };
       MenuItem debugStartResumeItem
@@ -1102,6 +1107,94 @@ class IDEWorkSpace : Window
             return true;
          }
       }
+#ifndef __WIN32__
+      MenuDivider { debugMenu };
+      MenuItem debugUseValgrindItem
+      {
+         debugMenu, $"Use Valgrind", d, disabled = true, checkable = true;
+         bool NotifySelect(MenuItem selection, Modifiers mods)
+         {
+            if(ide.workspace)
+            {
+               ide.workspace.useValgrind = selection.checked;
+               ide.workspace.Save();
+            }
+            ide.AdjustValgrindMenus();
+            return true;
+         }
+      }
+      Menu debugValgrindLeakCheckItem { debugMenu, $"Valgrind Leak Check", h };
+         MenuItem debugValgrindNoLeakCheckItem      { debugValgrindLeakCheckItem, $"No"     , f, id = ValgrindLeakCheck::no     , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
+         MenuItem debugValgrindSummaryLeakCheckItem { debugValgrindLeakCheckItem, $"Summary", f, id = ValgrindLeakCheck::summary, checkable = true, disabled = true; NotifySelect = ValgrindLCSelect, checked = true; }
+         MenuItem debugValgrindYesLeakCheckItem     { debugValgrindLeakCheckItem, $"Yes"    , f, id = ValgrindLeakCheck::yes    , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
+         MenuItem debugValgrindFullLeakCheckItem    { debugValgrindLeakCheckItem, $"Full"   , f, id = ValgrindLeakCheck::full   , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
+         bool ValgrindLCSelect(MenuItem selection, Modifiers mods)
+         {
+            if(ide.workspace)
+            {
+               if(selection.checked)
+               {
+                  ValgrindLeakCheck vgLeakCheck = (ValgrindLeakCheck)selection.id;
+
+                  debugValgrindNoLeakCheckItem.checked      = debugValgrindNoLeakCheckItem.id      == vgLeakCheck;
+                  debugValgrindSummaryLeakCheckItem.checked = debugValgrindSummaryLeakCheckItem.id == vgLeakCheck;
+                  debugValgrindYesLeakCheckItem.checked     = debugValgrindYesLeakCheckItem.id     == vgLeakCheck;
+                  debugValgrindFullLeakCheckItem.checked    = debugValgrindFullLeakCheckItem.id    == vgLeakCheck;
+
+                  ide.workspace.vgLeakCheck = vgLeakCheck;
+                  ide.workspace.Save();
+               }
+               else
+                  selection.checked = true;
+            }
+            return true;
+         }
+      Menu debugValgrindRedzoneSizeItem { debugMenu, $"Valgrind Redzone Size", z };
+         MenuItem debugValgrindRS0Item   { debugValgrindRedzoneSizeItem, $"0"  , f, id =   0, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect, checked = true; }
+         MenuItem debugValgrindRS16Item  { debugValgrindRedzoneSizeItem, $"16" , f, id =  16, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         MenuItem debugValgrindRS32Item  { debugValgrindRedzoneSizeItem, $"32" , f, id =  32, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         MenuItem debugValgrindRS64Item  { debugValgrindRedzoneSizeItem, $"64" , f, id =  64, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         MenuItem debugValgrindRS128Item { debugValgrindRedzoneSizeItem, $"128", f, id = 128, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         MenuItem debugValgrindRS256Item { debugValgrindRedzoneSizeItem, $"256", f, id = 256, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         MenuItem debugValgrindRS512Item { debugValgrindRedzoneSizeItem, $"512", f, id = 512, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
+         bool ValgrindRSSelect(MenuItem selection, Modifiers mods)
+         {
+            if(ide.workspace)
+            {
+               if(selection.checked)
+               {
+                  int vgRedzoneSize = (int)selection.id;
+
+                  debugValgrindRS0Item.checked   = debugValgrindRS0Item.id   == vgRedzoneSize;
+                  debugValgrindRS16Item.checked  = debugValgrindRS16Item.id  == vgRedzoneSize;
+                  debugValgrindRS32Item.checked  = debugValgrindRS32Item.id  == vgRedzoneSize;
+                  debugValgrindRS64Item.checked  = debugValgrindRS64Item.id  == vgRedzoneSize;
+                  debugValgrindRS128Item.checked = debugValgrindRS128Item.id == vgRedzoneSize;
+                  debugValgrindRS256Item.checked = debugValgrindRS256Item.id == vgRedzoneSize;
+                  debugValgrindRS512Item.checked = debugValgrindRS512Item.id == vgRedzoneSize;
+
+                  ide.workspace.vgRedzoneSize = vgRedzoneSize;
+                  ide.workspace.Save();
+               }
+               else
+                  selection.checked = true;
+            }
+            return true;
+         }
+      MenuItem debugValgrindTrackOriginsItem
+      {
+         debugMenu, $"Valgrind Track Origins", k, checkable = true, disabled = true;
+         bool NotifySelect(MenuItem selection, Modifiers mods)
+         {
+            if(ide.workspace)
+            {
+               ide.workspace.vgTrackOrigins = selection.checked;
+               ide.workspace.Save();
+            }
+            return true;
+         }
+      };
+#endif
       MenuDivider { debugMenu };
       MenuItem debugStepIntoItem
       {
@@ -1159,7 +1252,7 @@ class IDEWorkSpace : Window
          }
       }
       MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
-      MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", s };
+      MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", l };
       //MenuDivider { debugMenu };
       //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
    MenuPlacement imageMenu { menu, $"Image", i };
@@ -1362,18 +1455,26 @@ class IDEWorkSpace : Window
          helpMenu, $"API Reference", r, f1;
          bool NotifySelect(MenuItem selection, Modifiers mods)
          {
-            char * p = new char[MAX_LOCATION];
-            p[0] = '\0';
-            strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
-            PathCat(p, "documentor");
-#if defined(__WIN32__)
-            ChangeExtension(p, "exe", p);
-#endif
-            if(FileExists(p).isFile)
-               Execute(p);
+            if(!documentor)
+            {
+               char * p = new char[MAX_LOCATION];
+               p[0] = '\0';
+               strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
+               PathCat(p, "documentor");
+   #if defined(__WIN32__)
+               ChangeExtension(p, "exe", p);
+   #endif
+               if(!FileExists(p).isFile)
+                  strcpy(p, "documentor");
+
+               documentor = DualPipeOpen({ input = true, output = true, showWindow = true }, p);
+               delete p;
+            }
             else
-               Execute("documentor");
-            delete p;
+            {
+               Process_ShowWindows(documentor.GetProcessID());
+               // documentor.Puts("Activate\n");
+            }
             return true;
          }
       }
@@ -1469,7 +1570,7 @@ class IDEWorkSpace : Window
    GDBDialog gdbDialog
    {
       master = this, parent = this;
-      anchor = { left = 100, top = 100, right = 100, bottom = 100 };
+      //anchor = { left = 100, top = 100, right = 100, bottom = 100 };
 
       void OnCommand(char * string)
       {
@@ -1807,11 +1908,37 @@ class IDEWorkSpace : Window
       toolBar.activeCompiler.disabled     = unavailable;
       toolBar.activeBitDepth.disabled     = unavailable;
 
+#ifndef __WIN32__
+      debugUseValgrindItem.disabled       = unavailable;
+      AdjustValgrindMenus();
+#endif
+
       AdjustFileMenus();
       AdjustBuildMenus();
       AdjustDebugMenus();
    }
 
+#ifndef __WIN32__
+   void AdjustValgrindMenus()
+   {
+      bool unavailable = !project || !debugUseValgrindItem.checked;
+      debugValgrindNoLeakCheckItem.disabled        = unavailable;
+      debugValgrindSummaryLeakCheckItem.disabled   = unavailable;
+      debugValgrindYesLeakCheckItem.disabled       = unavailable;
+      debugValgrindFullLeakCheckItem.disabled      = unavailable;
+
+      debugValgrindTrackOriginsItem.disabled       = unavailable;
+
+      debugValgrindRS0Item.disabled   = unavailable;
+      debugValgrindRS16Item.disabled  = unavailable;
+      debugValgrindRS32Item.disabled  = unavailable;
+      debugValgrindRS64Item.disabled  = unavailable;
+      debugValgrindRS128Item.disabled = unavailable;
+      debugValgrindRS256Item.disabled = unavailable;
+      debugValgrindRS512Item.disabled = unavailable;
+   }
+#endif
+
    property bool hasOpenedCodeEditors
    {
       get
@@ -1836,6 +1963,7 @@ class IDEWorkSpace : Window
    void AdjustBuildMenus()
    {
       bool unavailable = project && projectView.buildInProgress;
+      bool naForRun = unavailable || !project || project.GetTargetType(project.config) != executable;
 
       projectNewItem.disabled             = unavailable;
       toolBar.buttonNewProject.disabled   = unavailable;
@@ -1847,8 +1975,8 @@ class IDEWorkSpace : Window
       projectCloseItem.disabled           = unavailable;
       // toolBar.buttonCloseProject.disabled = unavailable;
 
-      projectRunItem.disabled    = unavailable || project.GetTargetType(project.config) != executable;
-      toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
+      projectRunItem.disabled    = naForRun;
+      toolBar.buttonRun.disabled = naForRun;
 
       projectBuildItem.disabled = false;
       projectBuildItem.text     = unavailable ? $"Stop Build" : $"Build";
@@ -1865,6 +1993,10 @@ class IDEWorkSpace : Window
       // toolBar.buttonRealClean.disabled          = unavailable;
       projectRegenerateItem.disabled            = unavailable;
       toolBar.buttonRegenerateMakefile.disabled = unavailable;
+#ifdef IDE_SHOW_INSTALL_MENU_BUTTON
+      projectInstallItem.disabled               = unavailable;
+      toolBar.buttonInstall.disabled            = unavailable;
+#endif
       projectCompileItem.disabled               = unavailable;
 
       AdjustPopupBuildMenus();
@@ -1891,6 +2023,7 @@ class IDEWorkSpace : Window
          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0);             if(menu) menu.disabled = unavailable;
          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0);         if(menu) menu.disabled = unavailable;
          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0);        if(menu) menu.disabled = unavailable;
+         menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, 0);           if(menu) menu.disabled = unavailable;
          menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0);            if(menu) menu.disabled = unavailable;
          menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0);                if(menu) menu.disabled = unavailable;
          menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0);              if(menu) menu.disabled = unavailable;
@@ -2095,7 +2228,7 @@ class IDEWorkSpace : Window
                            return null;
                         //project = LoadProject(filePath, null);
                      }
-                     
+
                      if(workspace)
                      {
                         char absolutePath[MAX_LOCATION];
@@ -3256,6 +3389,12 @@ class IDEWorkSpace : Window
       delete driverItems;
       delete skinItems;
       delete ideSettings;
+      if(documentor)
+      {
+         documentor.Puts("Quit\n");
+         documentor.Wait();
+         delete documentor;
+      }
    }
 }
 
@@ -3476,6 +3615,33 @@ class IDEApp : GuiApplication
       return true;
    }
 
+   bool Cycle(bool idle)
+   {
+      if(ide.documentor)
+      {
+         if(ide.documentor.Peek())
+         {
+            char line[1024];
+            ide.documentor.GetLine(line, sizeof(line));
+            if(!strcmpi(line, "Exited"))
+            {
+               ide.documentor.CloseInput();
+               ide.documentor.CloseOutput();
+               ide.documentor.Wait();
+               delete ide.documentor;
+            }
+         }
+         if(ide.documentor && ide.documentor.eof)
+         {
+            ide.documentor.CloseInput();
+            ide.documentor.CloseOutput();
+            ide.documentor.Wait();
+            delete ide.documentor;
+         }
+      }
+      return true;
+   }
+
    bool LoadIncludeFile()
    {
       bool result = false;