buildsystem, epj2make, ide: support Emscripten compiler.
[sdk] / ide / src / project / ProjectView.ec
old mode 100755 (executable)
new mode 100644 (file)
index 2f7ada3..626654d
@@ -7,7 +7,7 @@ class ImportFolderFSI : NormalFileSystemIterator
    ProjectView projectView;
    Array<ProjectNode> stack { };
 
-   bool OnFolder(char * folderPath)
+   bool OnFolder(const char * folderPath)
    {
       char name[MAX_LOCATION];
       ProjectNode parentNode = stack.lastIterator.data;
@@ -20,15 +20,21 @@ class ImportFolderFSI : NormalFileSystemIterator
       return true;
    }
 
-   void OutFolder(char * folderPath, bool isRoot)
+   void OutFolder(const char * folderPath, bool isRoot)
    {
       stack.lastIterator.Remove(); //stack.Remove();
    }
 
-   bool OnFile(char * filePath)
+   bool OnFile(const char * filePath)
    {
       ProjectNode parentNode = stack.lastIterator.data;
-      projectView.AddFile(parentNode, filePath, parentNode.isInResources, false);
+      if(!projectView.AddFile(parentNode, filePath, parentNode.isInResources, false))
+      {
+         char * msg = PrintString($"This file can't be imported due to a conflict.\n\n", filePath,
+               "\n\nThis occurs with identical file paths and with conflicting file names.\n");
+         MessageBox { master = ide, type = ok, text = "Import File Conflict", contents = msg }.Modal();
+         delete msg;
+      }
       return true;
    }
 }
@@ -43,7 +49,7 @@ static Array<FileFilter> fileFilters
 
 static Array<FileFilter> resourceFilters
 { [
-   { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png,*.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
+   { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
    { $"3D Studio Model Files (*.3ds)", "3ds" },
    { $"Translations (*.mo)", "mo" },
    { $"All files", null }
@@ -61,7 +67,7 @@ static Array<FileType> projectTypes
    { $"Ecere IDE Workspace", WorkspaceExtension }
 ] };
 
-static char * iconNames[] = 
+static const char * iconNames[] =
 {
    "<:ecere>mimeTypes/file.png",                   /*genFile*/
    "<:ecere>mimeTypes/textEcereWorkspace.png",     /*ewsFile*/
@@ -82,13 +88,14 @@ static char * iconNames[] =
    "<:ecere>mimeTypes/package.png",                /*archiveFile*/
    "<:ecere>mimeTypes/packageSoftware.png",        /*packageFile*/
    "<:ecere>mimeTypes/packageOpticalDisc.png",     /*opticalMediaImageFile*/
-   "<:ecere>mimeTypes/file.png"                    /*mFile*/ //TODO: create icon for mfile
+   "<:ecere>mimeTypes/file.png",                   /*mFile*/ //TODO: create icon for .m file
+   "<:ecere>mimeTypes/file.png"                    /*mmFile*/ //TODO: create icon for .mm file
 };
 
 enum PrepareMakefileMethod { normal, force, forceExists };
 
 enum CleanType { clean, realClean, cleanTarget };
-enum BuildType { build, rebuild, relink, run, start, restart, clean };
+enum BuildType { build, rebuild, relink, run, start, restart, clean, install };
 enum BuildState
 {
    none, buildingMainProject, buildingSecondaryProject, compilingFile;
@@ -109,10 +116,10 @@ class ProjectView : Window
    size = { 300 };
    anchor = Anchor { left = 0, top = 0, bottom = 0 };
    menu = Menu { };
-   
+
    //hasMinimize = true;
    saveDialog = projectFileDialog;
-   
+
    DataRow resourceRow;
    BuildState buildInProgress;
    BitmapResource icons[NodeIcons];
@@ -149,7 +156,7 @@ class ProjectView : Window
       }
       get { return workspace; }
    }
-   
+
    bool drawingInProjectSettingsDialog;
    bool drawingInProjectSettingsDialogHeader;
    ProjectSettings projectSettingsDialog;
@@ -195,11 +202,11 @@ class ProjectView : Window
          if(!active) Update(null);
          return ListBox::OnActivate(active, previous, goOnWithActivation, direct);
       }
-      
+
       bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
       {
          // Prevent the double click from reactivating the project view (returns false if we opened something)
-         return !OpenSelectedNodes();
+         return !OpenSelectedNodes(mods.ctrl && mods.shift);
       }
 
       bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
@@ -208,27 +215,38 @@ class ProjectView : Window
          if(row)
          {
             bool showDebuggingMenuItems = mods.ctrl && mods.shift;
-            ProjectNode node = (ProjectNode)row.tag;
+            bool showInstallMenuItem = mods.ctrl && mods.shift;
+            ProjectNode node = (ProjectNode)(intptr)row.tag;
+#ifdef IDE_SHOW_INSTALL_MENU_BUTTON
+            showInstallMenuItem = true;
+#endif
             if(node.type == NodeTypes::project || node.type == resources || node.type == file || node.type == folder)
             {
                bool na = buildInProgress; // N/A - buildMenuUnavailable
                Menu pop { };
-               
+
                if(node.type == NodeTypes::project)
                {
                   MenuItem mi;
-                                                                                                                                            mi = ide.projectBuildItem;
-                  MenuItem { pop, $"Build"              , b, f7     , NotifySelect = ProjectBuild     , bitmap = mi.bitmap }.disabled = na; mi = ide.projectLinkItem;
-                  MenuItem { pop, $"Relink"             , l         , NotifySelect = ProjectLink      , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRebuildItem;
-                  MenuItem { pop, $"Rebuild"            , r, shiftF7, NotifySelect = ProjectRebuild   , bitmap = mi.bitmap }.disabled = na; mi = ide.projectCleanItem;
-                  MenuItem { pop, $"Clean"              , c         , NotifySelect = ProjectClean     , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRealCleanItem;
-                  MenuItem { pop, $"Real Clean"         , d         , NotifySelect = ProjectRealClean , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRegenerateItem;
-                  MenuItem { pop, $"Regenerate Makefile", m         , NotifySelect = ProjectRegenerate, bitmap = mi.bitmap }.disabled = na;
-
-                  if(showDebuggingMenuItems && node.ContainsFilesWithExtension("ec"))
+                                                                                                                                             mi = ide.projectBuildItem;
+                  MenuItem { pop, $"Build"              , b, f7     , NotifySelect = ProjectBuild      , bitmap = mi.bitmap }.disabled = na; mi = ide.projectLinkItem;
+                  MenuItem { pop, $"Relink"             , l         , NotifySelect = ProjectLink       , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRebuildItem;
+                  MenuItem { pop, $"Rebuild"            , r, shiftF7, NotifySelect = ProjectRebuild    , bitmap = mi.bitmap }.disabled = na; mi = ide.projectCleanTargetItem;
+                  MenuItem { pop, $"Clean Target"       , g         , NotifySelect = ProjectCleanTarget, bitmap = mi.bitmap }.disabled = na; mi = ide.projectCleanItem;
+                  MenuItem { pop, $"Clean"              , c         , NotifySelect = ProjectClean      , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRealCleanItem;
+                  MenuItem { pop, $"Real Clean"                     , NotifySelect = ProjectRealClean  , bitmap = mi.bitmap }.disabled = na; mi = ide.projectRegenerateItem;
+                  MenuItem { pop, $"Regenerate Makefile", m         , NotifySelect = ProjectRegenerate , bitmap = mi.bitmap }.disabled = na;
+                  if(showInstallMenuItem)
+                  {
+                     mi = ide.projectInstallItem;
+                     MenuItem { pop, $"Install"            , t         , NotifySelect = ProjectInstall    , bitmap = mi.bitmap }.disabled = na;
+                  }
+                  if(showDebuggingMenuItems && node.ContainsFilesWithExtension("ec", node.project.config))
                   {
                      MenuDivider { pop };
                      MenuItem { pop, $"Debug Generate Symbols", l, NotifySelect = FileDebugGenerateSymbols }.disabled = na;
+                     MenuItem { pop, $"Debug Precompile", l, NotifySelect = FileDebugPrecompile }.disabled = na;
+                     MenuItem { pop, $"Debug Compile", l, NotifySelect = FileDebugCompile }.disabled = na;
                   }
                   MenuDivider { pop };
                   MenuItem { pop, $"New File...", l, Key { l, ctrl = true }, NotifySelect = ProjectNewFile };
@@ -321,11 +339,11 @@ class ProjectView : Window
                   MenuItem { pop, $"Properties...", p, Key { enter, alt = true }, NotifySelect = FileProperties };
                }
 
-               popupMenu = 
+               popupMenu =
                {
                   master = this, menu = pop;
                   position = {
-                     x + clientStart.x + absPosition.x - app.desktop.position.x, 
+                     x + clientStart.x + absPosition.x - app.desktop.position.x,
                      y + clientStart.y + absPosition.y - app.desktop.position.y };
 
                   void NotifyDestroyed(Window window, DialogResult result)
@@ -354,12 +372,12 @@ class ProjectView : Window
       {
          if(row)
          {
-            ProjectNode node = (ProjectNode)row.tag;
+            ProjectNode node = (ProjectNode)(intptr)row.tag;
             switch(key)
             {
                case altEnter: case Key { keyPadEnter, alt = true }:
                {
-                  NodeProperties { parent = parent, master = this, 
+                  NodeProperties { parent = parent, master = this,
                      position = { position.x + 100, position.y + 100 }, node = node }.Create();
                   return false;
                }
@@ -408,7 +426,9 @@ class ProjectView : Window
                   }
                   break;
                }
-               case Key { space, shift = true }:
+               case Key { space, false, true }:
+               case Key { space, true, true }:
+               case Key { space, true }:
                case space:
                {
                   if(node.type == NodeTypes::project)
@@ -422,7 +442,7 @@ class ProjectView : Window
                            break;
                         }
                      }
-                     prj.RotateActiveConfig(!key.shift);
+                     prj.RotateActiveConfig(!key.shift, key.ctrl);
                      if(prj == project)
                         ide.AdjustMenus();
                      return false;
@@ -433,9 +453,11 @@ class ProjectView : Window
          }
          switch(key)
          {
-            case enter: case keyPadEnter:  OpenSelectedNodes();   break;
-            case del:                      RemoveSelectedNodes(); break;
-            case escape:                      
+            case Key { enter, true, true }:        OpenSelectedNodes(true);   break;
+            case Key { keyPadEnter, true, true }:  OpenSelectedNodes(true);   break;
+            case enter: case keyPadEnter:          OpenSelectedNodes(false);  break;
+            case del:                              RemoveSelectedNodes();     break;
+            case escape:
             {
                Window activeClient = ide.activeClient;
                if(activeClient)
@@ -450,7 +472,7 @@ class ProjectView : Window
 
       bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
       {
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          if(node.type == folder)
             node.icon = collapsed ? folder : openFolder;
          return true;
@@ -529,10 +551,10 @@ class ProjectView : Window
       ide.watchesView.Clear();
       ide.threadsView.Clear();
       ide.breakpointsView.Clear();
-      ide.outputView.ShowClearSelectTab(find); // why this? 
+      ide.outputView.ShowClearSelectTab(find); // why this?
    }
 
-   bool OnSaveFile(char * fileName)
+   bool OnSaveFile(const char * fileName)
    {
       for(prj : ide.workspace.projects)
       {
@@ -549,26 +571,43 @@ class ProjectView : Window
       return true;
    }
 
-   bool IsModuleInProject(char * filePath)
+   bool IsModuleInProject(const char * filePath)
    {
       char moduleName[MAX_FILENAME]; //, modulePath[MAX_LOCATION];
       GetLastDirectory(filePath, moduleName);
       return project.topNode.Find(moduleName, false) != null;
    }
 
-   bool GetRelativePath(char * filePath, char * relativePath)
+   ProjectNode GetNodeForCompilationFromWindow(Window document, bool nonExcludedFirst, bool * isExcluded, bool * isCObject)
    {
-      return project.GetRelativePath(filePath, relativePath);
+      ProjectNode node = null;
+      if(nonExcludedFirst)
+         node = GetNodeFromWindow(document, null, false, false, isExcluded);
+      if(!node)
+         node = GetNodeFromWindow(document, null, true, false, isExcluded);
+      if(!node && nonExcludedFirst)
+      {
+         node = GetNodeFromWindow(document, null, false, true, isExcluded);
+         if(isCObject && node) *isCObject = true;
+      }
+      if(!node)
+      {
+         node = GetNodeFromWindow(document, null, true, true, isExcluded);
+         if(isCObject && node) *isCObject = true;
+      }
+      return node;
    }
 
-   ProjectNode GetNodeFromWindow(Window document, Project project, bool isCObject)
+   ProjectNode GetNodeFromWindow(Window document, Project project, bool allNodes, bool isCObject, bool * isNodeExcluded)
    {
+      ProjectNode node = null;
       if(document.fileName)
       {
+         bool excluded = false;
          char winFileName[MAX_LOCATION];
          char * documentFileName = GetSlashPathBuffer(winFileName, document.fileName);
-         ProjectNode node;
          Project prj;
+         ProjectNode n;
          if(isCObject)
          {
             char name[MAX_FILENAME];
@@ -577,8 +616,14 @@ class ProjectView : Window
             for(p : ide.workspace.projects)
             {
                prj = project ? project : p;
-               if((node = prj.topNode.Find(name, false)))
-                  return node;
+               if((n = prj.topNode.Find(name, false)))
+               {
+                  if(allNodes || !(excluded = n.GetIsExcluded(prj.config)))
+                  {
+                     node = n;
+                     break;
+                  }
+               }
                if(project) break;
             }
          }
@@ -587,13 +632,21 @@ class ProjectView : Window
             for(p : ide.workspace.projects)
             {
                prj = project ? project : p;
-               if((node = prj.topNode.FindByFullPath(documentFileName, false)))
-                  return node;
+               if((n = prj.topNode.FindByFullPath(documentFileName, false)))
+               {
+                  if(allNodes || !(excluded = n.GetIsExcluded(prj.config)))
+                  {
+                     node = n;
+                     break;
+                  }
+               }
                if(project) break;
             }
          }
+         if(node && isNodeExcluded)
+            *isNodeExcluded = excluded;
       }
-      return null;
+      return node;
    }
 
    //                          ((( UTILITY FUNCTIONS )))
@@ -611,10 +664,6 @@ class ProjectView : Window
    bool ProjectPrepareForToolchain(Project project, PrepareMakefileMethod method, bool cleanLog, bool displayCompiler,
       CompilerConfig compiler, ProjectConfig config)
    {
-      bool isReady = true;
-      char message[MAX_F_STRING];
-      LogBox logBox = ide.outputView.buildBox;
-
       ShowOutputBuildLog(cleanLog);
 
       if(displayCompiler)
@@ -627,7 +676,8 @@ class ProjectView : Window
 
    bool ProjectPrepareCompiler(Project project, CompilerConfig compiler, bool silent)
    {
-      if((!project.GenerateCrossPlatformMk(app.includeFile) || !project.GenerateCompilerCf(compiler)) && !silent)
+      if((!project.GenerateCrossPlatformMk(app.includeFile) ||
+            !project.GenerateCompilerCf(compiler, project.topNode.ContainsFilesWithExtension("ec", project.config))) && !silent)
          ide.outputView.buildBox.Logf($"Error generating compiler configuration (Is the project/config directory writable?)\n");
       return true;
    }
@@ -654,7 +704,7 @@ class ProjectView : Window
          char makefileName[MAX_LOCATION];
          bool exists;
          LogBox logBox = ide.outputView.buildBox;
-         
+
          strcpy(makefilePath, project.topNode.path);
          project.CatMakeFileName(makefileName, config);
          PathCatSlash(makefilePath, makefileName);
@@ -664,8 +714,8 @@ class ProjectView : Window
            (method == forceExists && exists) ||
            (method == normal && (!exists || (config && config.makingModified))))
          {
-            char * reason;
-            char * action;
+            const char * reason;
+            const char * action;
             ide.statusBar.text = $"Generating Makefile & Dependencies..."; // Dependencies?
             app.UpdateDisplay();
 
@@ -687,7 +737,7 @@ class ProjectView : Window
             //logBox.Logf("%s\n", makefileName);
             logBox.Logf($"%s - %s%smakefile for %s config...\n", makefileName, reason, action, GetConfigName(config));
 
-            if(!project.GenerateMakefile(null, false, null, config))
+            if(!project.GenerateMakefile(null, false, null, config, compiler.ldCommand))
                ide.outputView.buildBox.Logf($"Error generating makefile (Is the project directory writable?)\n");
 
             ide.statusBar.text = null;
@@ -697,7 +747,7 @@ class ProjectView : Window
       }
       return false;
    }
-   
+
    bool BuildInterrim(Project prj, BuildType buildType, CompilerConfig compiler, ProjectConfig config, int bitDepth, bool justPrint)
    {
       if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
@@ -730,6 +780,8 @@ class ProjectView : Window
                result = DebugStop();
          }
       }
+      app.ProcessInput(true);
+      ShowOutputBuildLog(false);
       return result;
    }
 
@@ -743,7 +795,7 @@ class ProjectView : Window
       {
          if(document.modifiedDocument)
          {
-            ProjectNode node = GetNodeFromWindow(document, prj, false);
+            ProjectNode node = GetNodeFromWindow(document, prj, true, false, null);
             if(node && !document.MenuFileSave(null, 0))
             {
                result = false;
@@ -771,7 +823,7 @@ class ProjectView : Window
                char moduleName[MAX_FILENAME];
                strcpy(fileName, prj.topNode.path);
                PathCatSlash(fileName, objDir.dir);
-               strcpy(moduleName, prj.moduleName);
+               ReplaceSpaces(moduleName, prj.moduleName);
                strcat(moduleName, ".main.ec");
                PathCatSlash(fileName, moduleName);
                if(FileExists(fileName))
@@ -790,12 +842,12 @@ class ProjectView : Window
          ide.AdjustBuildMenus();
          ide.AdjustDebugMenus();
 
-         result = prj.Build(buildType == run, null, compiler, config, bitDepth, justPrint, normal);
+         result = prj.Build(buildType, null, compiler, config, bitDepth, justPrint, normal);
 
          if(config)
          {
             config.compilingModified = false;
-            if(!ide.ShouldStopBuild())
+            if(!stopBuild)
                config.linkingModified = false;
 
             config.symbolGenModified = false;
@@ -830,12 +882,12 @@ class ProjectView : Window
          if(selection || !ide.activeClient)
          {
             DataRow row = fileList.currentRow;
-            ProjectNode node = row ? (ProjectNode)row.tag : null;
+            ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
             if(node) prj = node.project;
          }
          else
          {
-            ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
+            ProjectNode node = GetNodeForCompilationFromWindow(ide.activeClient, true, null, null);
             if(node)
                prj = node.project;
          }
@@ -851,7 +903,7 @@ class ProjectView : Window
       return true;
    }
 
-   bool ProjectLink(MenuItem selection, Modifiers mods)
+   bool ProjectInstall(MenuItem selection, Modifiers mods)
    {
       Project prj = project;
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
@@ -860,187 +912,178 @@ class ProjectView : Window
       if(selection || !ide.activeClient)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node) prj = node.project;
       }
       else
       {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
+         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, true, false, null);
          if(node)
             prj = node.project;
       }
       config = prj.config;
       if(!prj.GetConfigIsInDebugSession(config) ||
-            (!ide.DontTerminateDebugSession($"Project Link") && DebugStopForMake(prj, relink, compiler, config)))
+            (!ide.DontTerminateDebugSession($"Project Install") && DebugStopForMake(prj, relink, compiler, config)))
       {
-         if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
+         BuildInterrim(prj, build, compiler, config, bitDepth, mods.ctrl && mods.shift);
+         if(ProjectPrepareForToolchain(prj, normal, false, false, compiler, config))
          {
-            ide.outputView.buildBox.Logf($"Relinking project %s using the %s configuration...\n", prj.name, GetConfigName(config));
-            if(config)
-               config.linkingModified = true;
-            Build(prj, relink, compiler, config, bitDepth, mods.ctrl && mods.shift);
+            ide.outputView.buildBox.Logf($"\nInstalling project %s using the %s configuration...\n", prj.name, GetConfigName(config));
+            Build(prj, install, compiler, config, bitDepth, mods.ctrl && mods.shift);
          }
       }
       delete compiler;
       return true;
    }
 
-   bool ProjectRebuild(MenuItem selection, Modifiers mods)
+   bool ProjectLink(MenuItem selection, Modifiers mods)
    {
+      Project prj = project;
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
       int bitDepth = ide.workspace.bitDepth;
-      Project prj = project;
       ProjectConfig config;
       if(selection || !ide.activeClient)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node) prj = node.project;
       }
       else
       {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
+         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, true, false, null);
          if(node)
             prj = node.project;
       }
       config = prj.config;
       if(!prj.GetConfigIsInDebugSession(config) ||
-            (!ide.DontTerminateDebugSession($"Project Rebuild") && DebugStopForMake(prj, rebuild, compiler, config)))
+            (!ide.DontTerminateDebugSession($"Project Link") && DebugStopForMake(prj, relink, compiler, config)))
       {
          if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
          {
-            ide.outputView.buildBox.Logf($"Rebuilding project %s using the %s configuration...\n", prj.name, GetConfigName(config));
-            /*if(config)
-            {
-               config.compilingModified = true;
-               config.makingModified = true;
-            }*/ // -- should this still be used depite the new solution of BuildType?
-            Build(prj, rebuild, compiler, config, bitDepth, mods.ctrl && mods.shift);
+            ide.outputView.buildBox.Logf($"Relinking project %s using the %s configuration...\n", prj.name, GetConfigName(config));
+            if(config)
+               config.linkingModified = true;
+            Build(prj, relink, compiler, config, bitDepth, mods.ctrl && mods.shift);
          }
       }
       delete compiler;
       return true;
    }
 
-#if 0
-   bool ProjectCleanTarget(MenuItem selection, Modifiers mods)
+   bool ProjectRebuild(MenuItem selection, Modifiers mods)
    {
-      Project prj = project;
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
+      int bitDepth = ide.workspace.bitDepth;
+      Project prj = project;
       ProjectConfig config;
       if(selection || !ide.activeClient)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node) prj = node.project;
       }
       else
       {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
+         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, true, false, null);
          if(node)
             prj = node.project;
       }
       config = prj.config;
       if(!prj.GetConfigIsInDebugSession(config) ||
-            (!ide.DontTerminateDebugSession($"Project Clean Target") && DebugStopForMake(prj, clean, compiler, config)))
+            (!ide.DontTerminateDebugSession($"Project Rebuild") && DebugStopForMake(prj, rebuild, compiler, config)))
       {
          if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
          {
-            ide.outputView.buildBox.Logf($"Cleaning target for project %s using the %s configuration...\n", prj.name, GetConfigName(config));
-
-            buildInProgress = prj == project ? buildingMainProject : buildingSecondaryProject;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
-
-            prj.Clean(compiler, config, cleanTarget, mods.ctrl && mods.shift);
-            buildInProgress = none;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
+            ide.outputView.buildBox.Logf($"Rebuilding project %s using the %s configuration...\n", prj.name, GetConfigName(config));
+            /*if(config)
+            {
+               config.compilingModified = true;
+               config.makingModified = true;
+            }*/ // -- should this still be used depite the new solution of BuildType?
+            Build(prj, rebuild, compiler, config, bitDepth, mods.ctrl && mods.shift);
          }
       }
       delete compiler;
       return true;
    }
-#endif
 
-   bool ProjectClean(MenuItem selection, Modifiers mods)
+   bool ProjectCleanTarget(MenuItem selection, Modifiers mods)
    {
-      Project prj = project;
-      CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
-      ProjectConfig config;
-      int bitDepth = ide.workspace.bitDepth;
-      if(selection || !ide.activeClient)
-      {
-         DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
-         if(node) prj = node.project;
-      }
-      else
-      {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
-         if(node)
-            prj = node.project;
-      }
-      config = prj.config;
-      if(!prj.GetConfigIsInDebugSession(config) ||
-            (!ide.DontTerminateDebugSession($"Project Clean") && DebugStopForMake(prj, clean, compiler, config)))
-      {
-         if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
-         {
-            ide.outputView.buildBox.Logf($"Cleaning project %s using the %s configuration...\n", prj.name, GetConfigName(config));
-
-            buildInProgress = prj == project ? buildingMainProject : buildingSecondaryProject;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
+      CleanProject($"Project Clean Target", $"Cleaning project %s target using the %s configuration...\n", selection, cleanTarget, mods.ctrl && mods.shift);
+      return true;
+   }
 
-            prj.Clean(compiler, config, bitDepth, clean, mods.ctrl && mods.shift);
-            buildInProgress = none;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
-         }
-      }
-      delete compiler;
+   bool ProjectClean(MenuItem selection, Modifiers mods)
+   {
+      CleanProject($"Project Clean", $"Cleaning project %s using the %s configuration...\n", selection, clean, mods.ctrl && mods.shift);
       return true;
    }
 
    bool ProjectRealClean(MenuItem selection, Modifiers mods)
    {
+      CleanProject($"Project Real Clean", $"Removing intermediate objects directory for project %s using the %s configuration...\n", selection, realClean, mods.ctrl && mods.shift);
+      return true;
+   }
+
+   void CleanProject(const char * terminateDebugSessionMessage, const char * cleaningMessageLogFormat, MenuItem selection, CleanType cleanType, bool justPrint)
+   {
       Project prj = project;
+      Array<Project> projects { };
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
-      ProjectConfig config;
       int bitDepth = ide.workspace.bitDepth;
+      if(selection)
+      {
+         OldLink item;
+         OldList selectedRows;
+         fileList.GetMultiSelection(selectedRows);
+         for(item = selectedRows.first; item; item = item.next)
+         {
+            DataRow row = item.data;
+            ProjectNode node = (ProjectNode)(intptr)row.tag;
+            if(node.type == project)
+               projects.Add(node.project);
+         }
+         selectedRows.Free(null);
+      }
       if(selection || !ide.activeClient)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node) prj = node.project;
+         if(projects.count == 0)
+            projects.Add(prj);
       }
       else
       {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
-         if(node)
-            prj = node.project;
+         // TODO: a file can belong to more than one project, ask which one to clean
+         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, true, false, null);
+         if(node) prj = node.project;
+         if(projects.count == 0)
+            projects.Add(prj);
       }
-      config = prj.config;
-      if(!prj.GetConfigIsInDebugSession(config) ||
-            (!ide.DontTerminateDebugSession($"Project Real Clean") && DebugStopForMake(prj, clean, compiler, config)))
+      for(prj : projects)
       {
-         if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
+         ProjectConfig config = prj.config;
+         if(!prj.GetConfigIsInDebugSession(config) ||
+               (!ide.DontTerminateDebugSession(terminateDebugSessionMessage) && DebugStopForMake(prj, clean, compiler, config)))
          {
-            ide.outputView.buildBox.Logf($"Removing intermediate objects directory for project %s using the %s configuration...\n", prj.name, GetConfigName(config));
+            if(ProjectPrepareForToolchain(prj, normal, true, true, compiler, config))
+            {
+               ide.outputView.buildBox.Logf(cleaningMessageLogFormat, prj.name, GetConfigName(config));
 
-            buildInProgress = prj == project ? buildingMainProject : buildingSecondaryProject;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
+               buildInProgress = prj == project ? buildingMainProject : buildingSecondaryProject;
+               ide.AdjustBuildMenus();
+               ide.AdjustDebugMenus();
 
-            prj.Clean(compiler, config, bitDepth, realClean, mods.ctrl && mods.shift);
-            buildInProgress = none;
-            ide.AdjustBuildMenus();
-            ide.AdjustDebugMenus();
+               prj.Clean(compiler, config, bitDepth, cleanType, justPrint);
+               buildInProgress = none;
+               ide.AdjustBuildMenus();
+               ide.AdjustDebugMenus();
+            }
          }
       }
       delete compiler;
-      return true;
+      delete projects;
    }
 
    bool ProjectRegenerate(MenuItem selection, Modifiers mods)
@@ -1051,13 +1094,13 @@ class ProjectView : Window
       if(selection || !ide.activeClient)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node)
             prj = node.project;
       }
       else
       {
-         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, false);
+         ProjectNode node = GetNodeFromWindow(ide.activeClient, null, true, false, null);
          if(node)
             prj = node.project;
       }
@@ -1072,7 +1115,6 @@ class ProjectView : Window
    bool Compile(Project project, List<ProjectNode> nodes, bool justPrint, SingleFileCompileMode mode)
    {
       bool result = true;
-      char fileName[MAX_LOCATION];
       Window document;
       ProjectConfig config = project.config;
 
@@ -1082,7 +1124,7 @@ class ProjectView : Window
       {
          if(document.modifiedDocument)
          {
-            ProjectNode n = GetNodeFromWindow(document, project, mode == cObject ? true : false);
+            ProjectNode n = GetNodeFromWindow(document, project, true, mode == cObject ? true : false, null);
             for(node : nodes)
             {
                if(n && n.IsInNode(node) && !document.MenuFileSave(null, 0))
@@ -1111,11 +1153,9 @@ class ProjectView : Window
 
             buildInProgress = compilingFile;
             ide.AdjustBuildMenus();
-            project.Compile(nodes, compiler, config, bitDepth, justPrint, mode);
+            result = project.Compile(nodes, compiler, config, bitDepth, justPrint, mode);
             buildInProgress = none;
             ide.AdjustBuildMenus();
-
-            result = true;
          }
          delete compiler;
       }
@@ -1125,7 +1165,6 @@ class ProjectView : Window
    bool Clean(Project project, List<ProjectNode> nodes, bool justPrint)
    {
       bool result = true;
-      char fileName[MAX_LOCATION];
       Window document;
       ProjectConfig config = project.config;
 
@@ -1135,7 +1174,7 @@ class ProjectView : Window
       {
          if(document.modifiedDocument)
          {
-            ProjectNode n = GetNodeFromWindow(document, project, false);
+            ProjectNode n = GetNodeFromWindow(document, project, true, false, null);
             for(node : nodes)
             {
                if(n && n.IsInNode(node) && !document.MenuFileSave(null, 0))
@@ -1164,10 +1203,10 @@ class ProjectView : Window
                else
                {
                   if(config)
-                     ide.outputView.buildBox.Logf($"Deleteing intermediate objects for %s %s in project %s using the %s configuration...\n",
+                     ide.outputView.buildBox.Logf($"Deleting intermediate objects for %s %s in project %s using the %s configuration...\n",
                            node.type == file ? $"single file" : $"folder", node.name, project.name, config.name);
                   else
-                     ide.outputView.buildBox.Logf($"Deleteing intermediate objects for %s %s in project %s...\n",
+                     ide.outputView.buildBox.Logf($"Deleting intermediate objects for %s %s in project %s...\n",
                            node.type == file ? $"single file" : $"folder", node.name, project.name);
 
                   node.DeleteIntermediateFiles(compiler, config, bitDepth, namesInfo, false);
@@ -1189,13 +1228,13 @@ class ProjectView : Window
       {
          char fileName[1024];
          char filePath[MAX_LOCATION];
-         ProjectNode parentNode = (ProjectNode)row.tag;
+         ProjectNode parentNode = (ProjectNode)(intptr)row.tag;
          ProjectNode n, fileNode;
          parentNode.GetFileSysMatchingPath(filePath);
          MakePathRelative(filePath, parentNode.project.topNode.path, filePath);
          for(n = parentNode; n && n != parentNode.project.resNode; n = n.parent);
          sprintf(fileName, $"Untitled %d", documentID);
-         fileNode = AddFile(parentNode, fileName, (bool)n, true);
+         fileNode = AddFile(parentNode, fileName, n != null, true);
          fileNode.path = CopyUnixPath(filePath);
          if(fileNode)
          {
@@ -1217,7 +1256,7 @@ class ProjectView : Window
       DataRow row = fileList.currentRow;
       if(row)
       {
-         ProjectNode parentNode = (ProjectNode)row.tag;
+         ProjectNode parentNode = (ProjectNode)(intptr)row.tag;
          NewFolder(parentNode, null, true);
       }
       return true;
@@ -1240,7 +1279,7 @@ class ProjectView : Window
       DataRow row = fileList.currentRow;
       if(row)
       {
-         ProjectNode toNode = (ProjectNode)row.tag;
+         ProjectNode toNode = (ProjectNode)(intptr)row.tag;
          ImportFolder(toNode);
       }
       return true;
@@ -1250,6 +1289,7 @@ class ProjectView : Window
    {
       CodeEditor codeEditor = CreateNew("Form", "form", "Window", null);
       codeEditor.EnsureUpToDate();
+      ide.RepositionWindows(false);
       return true;
    }
 
@@ -1266,7 +1306,7 @@ class ProjectView : Window
       DataRow row = fileList.currentRow;
       if(row)
       {
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          if(node.type == project)
             RemoveSelectedNodes();
       }
@@ -1306,8 +1346,8 @@ class ProjectView : Window
       DataRow row = fileList.currentRow;
       if(row)
       {
-         ProjectNode node = (ProjectNode)row.tag;
-         NodeProperties { parent = parent, master = this, node = node, 
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
+         NodeProperties { parent = parent, master = this, node = node,
                position = { position.x + 100, position.y + 100 } }.Create();
       }
       return true;
@@ -1315,7 +1355,7 @@ class ProjectView : Window
 
    bool FileOpenFile(MenuItem selection, Modifiers mods)
    {
-      OpenSelectedNodes();
+      OpenSelectedNodes(mods.ctrl && mods.shift);
       return true;
    }
 
@@ -1334,9 +1374,8 @@ class ProjectView : Window
       fileList.GetMultiSelection(selectedRows);
       for(item = selectedRows.first; item; item = item.next)
       {
-         OldLink i;
          DataRow row = item.data;
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          if(!project)
             project = node.project;
          else if(node.project != project)
@@ -1364,9 +1403,8 @@ class ProjectView : Window
       fileList.GetMultiSelection(selectedRows);
       for(item = selectedRows.first; item; item = item.next)
       {
-         OldLink i;
          DataRow row = item.data;
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          if(!project)
             project = node.project;
          else if(node.project != project)
@@ -1388,12 +1426,16 @@ class ProjectView : Window
    bool FileDebugPrecompile(MenuItem selection, Modifiers mods)
    {
       DataRow row = fileList.currentRow;
-      ProjectNode node = row ? (ProjectNode)row.tag : null;
+      ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
       if(node)
       {
          List<ProjectNode> nodes { };
          nodes.Add(node);
-         Compile(node.project, nodes, mods.ctrl && mods.shift, debugPrecompile);
+         if(node.type == project)
+            ProjectBuild(selection, mods);
+         ide.Update(null);
+         if(!stopBuild)
+            Compile(node.project, nodes, mods.ctrl && mods.shift, debugPrecompile);
          delete nodes;
       }
       return true;
@@ -1402,12 +1444,17 @@ class ProjectView : Window
    bool FileDebugCompile(MenuItem selection, Modifiers mods)
    {
       DataRow row = fileList.currentRow;
-      ProjectNode node = row ? (ProjectNode)row.tag : null;
+      ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
       if(node)
       {
          List<ProjectNode> nodes { };
          nodes.Add(node);
-         Compile(node.project, nodes, mods.ctrl && mods.shift, debugCompile);
+         if(node.type == project)
+            ProjectBuild(selection, mods);
+         else
+            Compile(node.project, nodes, mods.ctrl && mods.shift, normal);
+         if(!stopBuild)
+            Compile(node.project, nodes, mods.ctrl && mods.shift, debugCompile);
          delete nodes;
       }
       return true;
@@ -1416,12 +1463,17 @@ class ProjectView : Window
    bool FileDebugGenerateSymbols(MenuItem selection, Modifiers mods)
    {
       DataRow row = fileList.currentRow;
-      ProjectNode node = row ? (ProjectNode)row.tag : null;
+      ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
       if(node)
       {
          List<ProjectNode> nodes { };
          nodes.Add(node);
-         Compile(node.project, nodes, mods.ctrl && mods.shift, debugGenerateSymbols);
+         if(node.type == project)
+            ProjectBuild(selection, mods);
+         else
+            Compile(node.project, nodes, mods.ctrl && mods.shift, normal);
+         if(!stopBuild)
+            Compile(node.project, nodes, mods.ctrl && mods.shift, debugGenerateSymbols);
          delete nodes;
       }
       return true;
@@ -1433,28 +1485,34 @@ class ProjectView : Window
       if(useSelection)
       {
          DataRow row = fileList.currentRow;
-         ProjectNode node = row ? (ProjectNode)row.tag : null;
+         ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
          if(node)
             prj = node.project;
       }
       return prj;
    }
-   
+
    void SelectNextProject(bool backwards)
    {
       DataRow row = fileList.currentRow;
-      DataRow currentRow = row;
-      ProjectNode node = (ProjectNode)row.tag;
-      if(node.type != project)
-         row = node.project.topNode.row;
-      else if(backwards)
-         row = row.previous ? row.previous : fileList.lastRow;
-      if(!backwards)
-         row = row.next ? row.next : fileList.firstRow;
-      if(row && row != currentRow)
+      if(!row)
+         row = backwards ? fileList.lastRow : fileList.firstRow;
+
+      if(row)
       {
-         fileList.SelectRow(row);
-         fileList.currentRow = row;
+         DataRow currentRow = row;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
+         if(node.type != project)
+            row = node.project.topNode.row;
+         else if(backwards)
+            row = row.previous ? row.previous : fileList.lastRow;
+         if(!backwards)
+            row = row.next ? row.next : fileList.firstRow;
+         if(row && row != currentRow)
+         {
+            fileList.SelectRow(row);
+            fileList.currentRow = row;
+         }
       }
    }
 
@@ -1465,7 +1523,7 @@ class ProjectView : Window
       {
          DataRow row = fileList.currentRow;
          if(row)
-            node = (ProjectNode)row.tag;
+            node = (ProjectNode)(intptr)row.tag;
       }
       return node;
    }
@@ -1513,6 +1571,7 @@ class ProjectView : Window
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
       ProjectConfig config = project.config;
       int bitDepth = ide.workspace.bitDepth;
+      bool useValgrind = ide.workspace.useValgrind;
       TargetTypes targetType = project.GetTargetType(config);
       if(targetType == sharedLibrary || targetType == staticLibrary)
          MessageBox { master = ide, type = ok, text = $"Run", contents = $"Shared and static libraries cannot be run like executables." }.Modal();
@@ -1531,7 +1590,7 @@ class ProjectView : Window
                char command[MAX_LOCATION];
 
                ide.SetPath(false, compiler, config, bitDepth);
-               
+
                GetWorkingDir(oldwd, sizeof(oldwd));
                ChangeWorkingDir(project.topNode.path);
 
@@ -1543,19 +1602,19 @@ class ProjectView : Window
             }
             else
             {
-               ide.debugger.Start(compiler, config, bitDepth);
+               ide.debugger.Start(compiler, config, bitDepth, useValgrind);
                result = true;
             }
          }
       }
       delete compiler;
-      return result;      
+      return result;
    }
 
-   void GoToError(const char * line)
+   void GoToError(const char * line, const bool noParsing, const char * objectFileExt)
    {
       char * colon;
-      
+
       while(isspace(*line)) line++;
       colon = strstr(line, ":");
 
@@ -1585,7 +1644,7 @@ class ProjectView : Window
          if(colon && lookForLineNumber)
          {
             char * comma;
-            // MSVS Errors
+#if 0 // MSVS Errors -- todo fix this later
             char * par = RSearchString(line, "(", colon - line, true, false);
             if(par && strstr(par, ")"))
                colon = par;
@@ -1596,6 +1655,7 @@ class ProjectView : Window
                   /*if(*colon == '(')
                      break*/;
             }
+#endif
             lineNumber = atoi(colon + 1);
             /*
             comma = strchr(colon, ',');
@@ -1606,18 +1666,20 @@ class ProjectView : Window
             if(comma)
                col = atoi(comma+1);
          }
-         
+
          {
-            char moduleName[MAX_LOCATION], filePath[MAX_LOCATION];
-            char ext[MAX_EXTENSION];
-            char * bracket;
+            char moduleName[MAX_LOCATION], filePath[MAX_LOCATION] = "";
+            char ext[MAX_EXTENSION] = "";
+            ProjectNode node = null;
             if(colon)
             {
-               char * inFileIncludedFrom = strstr(line, stringInFileIncludedFrom);
-               char * from = strstr(line, "from ");
-               char * start = inFileIncludedFrom ? inFileIncludedFrom + strlen(stringInFileIncludedFrom) : from ? from + strlen("from ") : line;
-               int len = (int)(colon - start);
-               len = Min(len, MAX_LOCATION-1);
+               const char * inFileIncludedFrom = strstr(line, stringInFileIncludedFrom);
+               const char * from = strstr(line, "from ");
+               const char * start = inFileIncludedFrom ? inFileIncludedFrom + strlen(stringInFileIncludedFrom) : from ? from + strlen("from ") : line;
+               int len;
+               if(colon < start)
+                  start = line;
+               len = Min((int)(colon - start), MAX_LOCATION-1);
                // Cut module name
                strncpy(moduleName, start, len);
                moduleName[len] = '\0';
@@ -1625,103 +1687,226 @@ class ProjectView : Window
             else
                strcpy(moduleName, line);
 
+            if(!colon)
+            {
+               char * msg;
+               if((msg = strstr(moduleName, " - ")))
+               {
+                  bool found = false;
+                  msg[0] = '\0';
+                  for(prj : ide.workspace.projects)
+                  {
+                     strcpy(filePath, prj.topNode.path);
+                     PathCatSlash(filePath, moduleName);
+                     if(FileExists(filePath).isFile)
+                     {
+                        found = true;
+                        break;
+                     }
+                  }
+                  if(!found)
+                  {
+                     msg[0] = ' ';
+                     filePath[0] = '\0';
+                  }
+               }
+               else if((msg = strstr(moduleName, "...")) && (colon = strchr(moduleName, ' ')) && (++colon)[0])
+               {
+                  bool found = false;
+                  msg[0] = '\0';
+                  for(prj : ide.workspace.projects)
+                  {
+                     if((node = prj.resNode.Find(colon, true)))
+                     {
+                        strcpy(filePath, prj.topNode.path);
+                        PathCatSlash(filePath, node.path);
+                        PathCatSlash(filePath, node.name);
+
+                        found = true;
+                        break;
+                     }
+                  }
+                  if(!found)
+                  {
+                     msg[0] = '.';
+                     filePath[0] = '\0';
+                  }
+               }
+               colon = null;
+            }
             // Remove stuff in brackets
             /*
             bracket = strstr(moduleName, "(");
             if(bracket) *bracket = '\0';
             */
             MakeSlashPath(moduleName);
+            GetExtension(moduleName, ext);
 
-            if(!colon)
+            if(!colon && !filePath[0])
             {
                // Check if it's one of our modules
-               ProjectNode node = project.topNode.Find(moduleName, false);
+               node = project.topNode.Find(moduleName, false);
                if(node)
                {
-                  strcpy(moduleName, node.path);
-                  PathCatSlash(moduleName, node.name);
+                  strcpy(filePath, node.path);
+                  PathCatSlash(filePath, node.name);
                }
                else
-                  moduleName[0] = '\0';
+               {
+                  char ext[MAX_EXTENSION];
+                  GetExtension(moduleName, ext);
+                  {
+                     DotMain dotMain = DotMain::FromFileName(moduleName);
+                     IntermediateFileType type = IntermediateFileType::FromExtension(ext);
+                     ProjectConfig config = null;
+                     if(type)
+                     {
+                        for(prj : ide.workspace.projects; prj.lastBuildConfigName)
+                        {
+                           if((config = prj.GetConfig(prj.lastBuildConfigName)))
+                              node = prj.FindNodeByObjectFileName(moduleName, type, dotMain, config, objectFileExt);
+                           if(node)
+                              break;
+                        }
+                     }
+                     if(node)
+                     {
+                        char name[MAX_FILENAME];
+                        Project project = node.project;
+                        CompilerConfig compiler = ideSettings.GetCompilerConfig(project.lastBuildCompilerName);
+                        if(compiler)
+                        {
+                           int bitDepth = ide.workspace.bitDepth;
+                           const char * objectFileExt = compiler ? compiler.objectFileExt : objectDefaultFileExt;
+                           DirExpression objDir = project.GetObjDir(compiler, config, bitDepth);
+                           strcpy(filePath, project.topNode.path);
+                           PathCatSlash(filePath, objDir.dir);
+                           node.GetObjectFileName(name, project.configsNameCollisions[config ? config.name : ""], type, dotMain, objectFileExt);
+                           PathCatSlash(filePath, name);
+                           delete objDir;
+                        }
+                        delete compiler;
+                     }
+                  }
+               }
+               if(!node)
+                  filePath[0] = '\0';
             }
-            GetExtension(moduleName, ext);
-            if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") || !strcmp(ext, "dll"))
+            if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") ||
+                  !strcmp(ext, "dll") || !strcmp(ext, "exe") || !strcmp(ext, "mo"))
                moduleName[0] = 0;    // Avoid opening binary files
             if(moduleName[0])
             {
-               CodeEditor codeEditor;
-               strcpy(filePath, project.topNode.path);
-               PathCatSlash(filePath, moduleName);
-      
-               codeEditor = (CodeEditor)ide.OpenFile(filePath, normal, true, null, no, normal);
-               if(!codeEditor && !strcmp(ext, "c"))
+               CodeEditor codeEditor = null;
+
+               if(ide.GoToCodeSelectFile(moduleName, null, project, null, filePath, objectFileExt))
                {
-                  char ecName[MAX_LOCATION];
-                  ChangeExtension(filePath, "ec", ecName);
-                  codeEditor = (CodeEditor)ide.OpenFile(ecName, normal, true, null, no, normal);
+                  codeEditor = (CodeEditor)ide.OpenFile(filePath, false, true, null, no, normal, noParsing);
                }
+
                if(!codeEditor)
                {
-                  char path[MAX_LOCATION];
-                  // TOFIX: Improve on this, don't use only filename, make a function
-                  if(ide && ide.workspace)
+                  if(!filePath[0])
                   {
-                     for(prj : ide.workspace.projects)
-                     {
-                        ProjectNode node;
-                        MakePathRelative(filePath, prj.topNode.path, path);
+                     strcpy(filePath, project.topNode.path);
+                     PathCatSlash(filePath, moduleName);
+                  }
 
-                        if((node = prj.topNode.FindWithPath(path, false)))
-                        {
-                           strcpy(filePath, prj.topNode.path);
-                           PathCatSlash(filePath, node.path);
-                           PathCatSlash(filePath, node.name);
-                           codeEditor = (CodeEditor)ide.OpenFile(filePath, normal, true, null, no, normal);
-                           if(codeEditor)
-                              break;
-                        }
-                     }
-                     if(!codeEditor && !strchr(moduleName, '/') && !strchr(moduleName, '\\'))
+                  codeEditor = (CodeEditor)ide.OpenFile(filePath, false, true, null, no, normal, noParsing);
+                  if(!codeEditor && !strcmp(ext, "c"))
+                  {
+                     char ecName[MAX_LOCATION];
+                     ChangeExtension(filePath, "ec", ecName);
+                     codeEditor = (CodeEditor)ide.OpenFile(ecName, false, true, null, no, normal, noParsing);
+                  }
+                  if(!codeEditor)
+                  {
+                     char path[MAX_LOCATION];
+                     // TOFIX: Improve on this, don't use only filename, make a function
+                     if(ide && ide.workspace)
                      {
                         for(prj : ide.workspace.projects)
                         {
                            ProjectNode node;
-                           if((node = prj.topNode.Find(moduleName, false)))
+                           MakePathRelative(filePath, prj.topNode.path, path);
+
+                           if((node = prj.topNode.FindWithPath(path, false)))
                            {
                               strcpy(filePath, prj.topNode.path);
                               PathCatSlash(filePath, node.path);
                               PathCatSlash(filePath, node.name);
-                              codeEditor = (CodeEditor)ide.OpenFile(filePath, normal, true, null, no, normal);
+                              codeEditor = (CodeEditor)ide.OpenFile(filePath, false, true, null, no, normal, noParsing);
                               if(codeEditor)
                                  break;
                            }
                         }
+                        if(!codeEditor && (strchr(moduleName, '/') || strchr(moduleName, '\\')))
+                        {
+                           for(prj : ide.workspace.projects)
+                           {
+                              ProjectNode node;
+                              if((node = prj.topNode.FindWithPath(moduleName, false)))
+                              {
+                                 strcpy(filePath, prj.topNode.path);
+                                 PathCatSlash(filePath, node.path);
+                                 PathCatSlash(filePath, node.name);
+                                 codeEditor = (CodeEditor)ide.OpenFile(filePath, false, true, null, no, normal, noParsing);
+                                 if(codeEditor)
+                                    break;
+                              }
+                           }
+                        }
+                        if(!codeEditor)
+                        {
+                           GetLastDirectory(moduleName, moduleName);
+                           for(prj : ide.workspace.projects)
+                           {
+                              ProjectNode node;
+                              if((node = prj.topNode.Find(moduleName, false)))
+                              {
+                                 strcpy(filePath, prj.topNode.path);
+                                 PathCatSlash(filePath, node.path);
+                                 PathCatSlash(filePath, node.name);
+                                 codeEditor = (CodeEditor)ide.OpenFile(filePath, false, true, null, no, normal, noParsing);
+                                 if(codeEditor)
+                                    break;
+                              }
+                           }
+                        }
                      }
                   }
                }
                if(codeEditor && lineNumber)
                {
                   EditBox editBox = codeEditor.editBox;
-                  editBox.GoToLineNum(lineNumber - 1);
-                  editBox.GoToPosition(editBox.line, lineNumber - 1, col ? (col - 1) : 0);
+                  if(editBox.GoToLineNum(lineNumber - 1))
+                     editBox.GoToPosition(editBox.line, lineNumber - 1, col ? (col - 1) : 0);
                }
             }
          }
       }
    }
 
-   bool OpenNode(ProjectNode node)
+   bool OpenNode(ProjectNode node, bool noParsing)
    {
       char filePath[MAX_LOCATION];
+      char ext[MAX_EXTENSION];
       node.GetFullFilePath(filePath);
-      return ide.OpenFile(filePath, normal, true/*false Why was it opening hidden?*/, null, something, normal) ? true : false;
+      GetExtension(filePath, ext);
+      if(binaryDocExt.Find(ext))
+      {
+         ShellOpen(filePath);
+         return true;
+      }
+      else
+         return ide.OpenFile(filePath, false, true/*false Why was it opening hidden?*/, null, something, normal, noParsing) ? true : false;
    }
 
    void AddNode(ProjectNode node, DataRow addTo)
    {
       DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
 
-      row.tag = (int64)node;
+      row.tag = (int64)(intptr)node;
       node.row = row;
 
       if(node.type == resources)
@@ -1729,9 +1914,9 @@ class ProjectView : Window
 
       row.SetData(null, node);
 
-      if(node.files && node.files.first && node.parent && 
-            !(!node.parent.parent && 
-               (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") || 
+      if(node.files && node.files.first && node.parent &&
+            !(!node.parent.parent &&
+               (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
                   !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
          row.collapsed = true;
       else if(node.type == folder)
@@ -1749,7 +1934,7 @@ class ProjectView : Window
       if(projectNode.files)
       {
          ProjectNode child;
-         while(child = projectNode.files.first)
+         while((child = projectNode.files.first))
             DeleteNode(child);
       }
       fileList.DeleteRow(projectNode.row);
@@ -1759,7 +1944,7 @@ class ProjectView : Window
    bool ProjectSave(MenuItem selection, Modifiers mods)
    {
       DataRow row = fileList.currentRow;
-      ProjectNode node = row ? (ProjectNode)row.tag : null;
+      ProjectNode node = row ? (ProjectNode)(intptr)row.tag : null;
       Project prj = node ? node.project : null;
       if(prj)
       {
@@ -1771,7 +1956,7 @@ class ProjectView : Window
             for(p : ide.workspace.projects)
             {
                if(p.topNode.modified)
-               { 
+               {
                   modPrj = p;
                   break;
                }
@@ -1803,6 +1988,7 @@ class ProjectView : Window
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
       ProjectConfig config = project.config;
       int bitDepth = ide.workspace.bitDepth;
+      bool useValgrind = ide.workspace.useValgrind;
 
       bool result = false;
       if(/*!IsProjectModified() ||*/ BuildInterrim(project, restart, compiler, config, bitDepth, false))
@@ -1810,7 +1996,7 @@ class ProjectView : Window
          // For Restart, compiler and config will only be used if for
          // whatever reason (if at all possible) the Debugger is in a
          // 'terminated' or 'none' state
-         ide.debugger.Restart(compiler, config, bitDepth);
+         ide.debugger.Restart(compiler, config, bitDepth, useValgrind);
          result = true;
       }
 
@@ -1841,9 +2027,10 @@ class ProjectView : Window
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
       ProjectConfig config = project.config;
       int bitDepth = ide.workspace.bitDepth;
+      bool useValgrind = ide.workspace.useValgrind;
 
       if((ide.debugger.isActive) || (!buildInProgress && BuildInterrim(project, start, compiler, config, bitDepth, false)))
-         ide.debugger.StepInto(compiler, config, bitDepth);
+         ide.debugger.StepInto(compiler, config, bitDepth, useValgrind);
       delete compiler;
       return true;
    }
@@ -1853,9 +2040,24 @@ class ProjectView : Window
       CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
       ProjectConfig config = project.config;
       int bitDepth = ide.workspace.bitDepth;
+      bool useValgrind = ide.workspace.useValgrind;
 
       if((ide.debugger.isActive) || (!buildInProgress && BuildInterrim(project, start, compiler, config, bitDepth, false)))
-         ide.debugger.StepOver(compiler, config, bitDepth, skip);
+         ide.debugger.StepOver(compiler, config, bitDepth, useValgrind, skip);
+
+      delete compiler;
+      return true;
+   }
+
+   bool DebugStepUntil(bool skip)
+   {
+      CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
+      ProjectConfig config = project.config;
+      int bitDepth = ide.workspace.bitDepth;
+      bool useValgrind = ide.workspace.useValgrind;
+
+      if((ide.debugger.isActive) || (!buildInProgress && BuildInterrim(project, start, compiler, config, bitDepth, false)))
+         ide.debugger.StepUntil(compiler, config, bitDepth, useValgrind, skip);
 
       delete compiler;
       return true;
@@ -1871,11 +2073,28 @@ class ProjectView : Window
    {
       if(toNode)
       {
-         //bool isFolder = toNode.type == folder;
-         //bool isRes = toNode.isInResources;
-         
+         char path[MAX_LOCATION];
+         char currentDir[MAX_LOCATION];
+         ProjectNode node = toNode;
          FileDialog fileDialog = importFileDialog;
          fileDialog.master = parent;
+         while(node)
+         {
+            node.GetFullFilePath(path);
+            while(path[0])
+            {
+               StripLastDirectory(path, path);
+               if(FileExists(path).isDirectory) break;
+            }
+            if(path[0] || node == toNode.project.topNode)
+               node = null;
+            else
+               node = toNode.project.topNode;
+         }
+         MakeSystemPath(path);
+         StripLastDirectory(path, currentDir);
+         fileDialog.currentDirectory = currentDir[0] ? currentDir : path;
+         fileDialog.filePath = path;
          if(fileDialog.Modal() == ok)
          {
             ImportFolderFSI fsi { projectView = this };
@@ -1900,7 +2119,7 @@ class ProjectView : Window
                break;
             after = node;
          }
-         
+
          if(name && name[0])
             folderNode = parentNode.Add(prj, name, after, folder, folder, true);
          else
@@ -1924,11 +2143,11 @@ class ProjectView : Window
             }
             Update(null);
             folderNode.row = parentNode.row.AddRowAfter(after ? after.row : null);
-            folderNode.row.tag = (int64)folderNode;
-               
+            folderNode.row.tag = (int64)(intptr)folderNode;
+
             folderNode.row.SetData(null, folderNode);
             fileList.currentRow = folderNode.row;
-            
+
             if(showProperties)
             {
                nodeProperties = NodeProperties
@@ -1955,16 +2174,16 @@ class ProjectView : Window
       {
          int c;
          DataRow row = fileList.currentRow;
-         ProjectNode parentNode = (ProjectNode)row.tag;
+         ProjectNode parentNode = (ProjectNode)(intptr)row.tag;
          bool addFailed = false;
          int numSelections = fileDialog.numSelections;
-         char ** multiFilePaths = fileDialog.multiFilePaths;
+         const char * const * multiFilePaths = fileDialog.multiFilePaths;
 
          Array<String> nameConflictFiles { };
 
          for(c = 0; c < numSelections; c++)
          {
-            char * filePath = multiFilePaths[c];
+            const char * filePath = multiFilePaths[c];
             FileAttribs exists = FileExists(filePath);
             bool addThisFile = true;
 
@@ -1972,7 +2191,7 @@ class ProjectView : Window
                addThisFile = false;
             else if(!exists)
             {
-               if(MessageBox { master = ide, type = yesNo, text = filePath, 
+               if(MessageBox { master = ide, type = yesNo, text = filePath,
                      contents = $"File doesn't exist. Create?" }.Modal() == yes)
                {
                   File f = FileOpen(filePath, write);
@@ -1983,7 +2202,7 @@ class ProjectView : Window
                   }
                   else
                   {
-                     MessageBox { master = ide, type = ok, text = filePath, 
+                     MessageBox { master = ide, type = ok, text = filePath,
                            contents = $"Couldn't create file."}.Modal();
                      addThisFile = false;
                   }
@@ -2002,10 +2221,10 @@ class ProjectView : Window
          if(addFailed)
          {
             int len = 0;
-            char * part1 = $"The following file";
-            char * opt1 = $" was ";
-            char * opt2 = $"s were ";
-            char * part2 = $"not added because of identical file name conflict within the project.\n\n";
+            const char * part1 = $"The following file";
+            const char * opt1 = $" was ";
+            const char * opt2 = $"s were ";
+            const char * part2 = $"not added because of identical file name conflict within the project.\n\n";
             char * message;
             len += strlen(part1);
             len += strlen(part2);
@@ -2021,7 +2240,7 @@ class ProjectView : Window
                strcat(message, s);
                strcat(message, "\n");
             }
-            MessageBox { master = ide, type = ok, text = $"Name Conflict", 
+            MessageBox { master = ide, type = ok, text = $"Name Conflict",
                   contents = message }.Modal();
             delete message;
          }
@@ -2030,7 +2249,7 @@ class ProjectView : Window
       }
    }
 
-   ProjectNode AddFile(ProjectNode parentNode, char * filePath, bool resources, bool isTemporary)
+   ProjectNode AddFile(ProjectNode parentNode, const char * filePath, bool resources, bool isTemporary)
    {
       ProjectNode result = null;
       ProjectNode after = null;
@@ -2053,13 +2272,13 @@ class ProjectView : Window
          }
          Update(null);
          result.row = parentNode.row.AddRowAfter(after ? after.row : null);
-         result.row.tag = (int64)result;
+         result.row.tag = (int64)(intptr)result;
          result.row.SetData(null, result);
       }
       return result;
    }
 
-   CodeEditor CreateNew(char * upper, char * lower, char * base, char * className)
+   CodeEditor CreateNew(const char * upper, const char * lower, const char * base, char * className)
    {
       CodeEditor codeEditor = null;
       ProjectNode projectNode;
@@ -2070,7 +2289,7 @@ class ProjectView : Window
 
       if(!row) row = project.topNode.row;
 
-      parentNode = (ProjectNode)row.tag;
+      parentNode = (ProjectNode)(intptr)row.tag;
 
       for(node : parentNode.files)
       {
@@ -2081,7 +2300,7 @@ class ProjectView : Window
       for(c = 1; c < 100; c++)
       {
          char string[16];
-         sprintf(string, c ? "%s%d.ec" : "%s.ec", lower, c);
+         sprintf(string, "%s%d.ec", lower, c);
          if((projectNode = parentNode.Add(project, string, after, file, genFile, true)))
             break;
       }
@@ -2095,8 +2314,8 @@ class ProjectView : Window
          Update(null);
          project.ModifiedAllConfigs(true, false, false, true);
          projectNode.row = parentNode.row.AddRowAfter(after ? after.row : null);
-         projectNode.row.tag =(int64)projectNode;
-            
+         projectNode.row.tag = (int64)(intptr)projectNode;
+
          projectNode.row.SetData(null, projectNode);
          fileList.currentRow = projectNode.row;
 
@@ -2111,7 +2330,7 @@ class ProjectView : Window
             subclass(ClassDesignerBase) designerClass = eClass_GetDesigner(baseClass);
             if(designerClass)
             {
-               codeEditor = (CodeEditor)ide.OpenFile(filePath, normal, false, null, whatever, normal);
+               codeEditor = (CodeEditor)ide.OpenFile(filePath, false, false, null, whatever, normal, false);
                strcpy(name, projectNode.name);
                sprintf(name, "%s%d", upper, c);
                if(className)
@@ -2127,20 +2346,22 @@ class ProjectView : Window
          }
          else // TODO: fix no symbols generated when ommiting {} for following else
          {
-            codeEditor = (CodeEditor)ide.OpenFile(filePath, normal, false, null, whatever, normal);
+            codeEditor = (CodeEditor)ide.OpenFile(filePath, false, false, null, whatever, normal, false);
          }
+         ide.sheet.visible = true;
+         ide.sheet.Activate();
          if(codeEditor)
          {
             codeEditor.ViewDesigner();
             codeEditor.codeModified = true;
          }
       }
-      visible = false;
-      return codeEditor;   
+      //visible = false;
+      return codeEditor;
    }
 
    // Returns true if we opened something
-   bool OpenSelectedNodes()
+   bool OpenSelectedNodes(bool noParsing)
    {
       bool result = false;
       OldList selection;
@@ -2150,15 +2371,15 @@ class ProjectView : Window
       for(item = selection.first; item; item = item.next)
       {
          DataRow row = item.data;
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          if(node.type == file)
          {
-            OpenNode(node);
+            OpenNode(node, noParsing);
             result = true;
-            break;
          }
       }
       selection.Free(null);
+      ide.RepositionWindows(false);
       return result;
    }
 
@@ -2166,7 +2387,7 @@ class ProjectView : Window
    {
       OldList selection;
       OldLink item, next;
-      
+
       fileList.GetMultiSelection(selection);
 
       // Remove children of parents we're deleting
@@ -2174,13 +2395,13 @@ class ProjectView : Window
       {
          OldLink i;
          DataRow row = item.data;
-         ProjectNode n, node = (ProjectNode)row.tag;
+         ProjectNode n, node = (ProjectNode)(intptr)row.tag;
          bool remove = false;
 
          next = item.next;
          for(i = selection.first; i && !remove; i = i.next)
          {
-            ProjectNode iNode = (ProjectNode)((DataRow)i.data).tag;
+            ProjectNode iNode = (ProjectNode)(intptr)((DataRow)i.data).tag;
             for(n = node.parent; n; n = n.parent)
             {
                if(iNode == n)
@@ -2197,7 +2418,7 @@ class ProjectView : Window
       for(item = selection.first; item; item = item.next)
       {
          DataRow row = item.data;
-         ProjectNode node = (ProjectNode)row.tag;
+         ProjectNode node = (ProjectNode)(intptr)row.tag;
          ProjectNode resNode;
          for(resNode = node.parent; resNode; resNode = resNode.parent)
             if(resNode.type == resources)