wip II
[sdk] / ide / src / dialogs / FindInFilesDialog.ec
index ab3d771..c0f8e0f 100644 (file)
@@ -6,7 +6,7 @@ enum FindInFilesMode { directory, workspace, project };
 class FindInFilesDialog : Window
 {
    text = $"Find In Files";
-   background = activeBorder;
+   background = formColor;
    borderStyle = sizable;
    minClientSize = { 440, 208 };
    maxClientSize = { 640, 208 };
@@ -14,14 +14,13 @@ class FindInFilesDialog : Window
    tabCycle = true;
    size = { 440, 208 };
    autoCreate = false;
-   stayOnTop = true;
    
 public:
    property char * searchString { set { findContent.contents = value; } get { return findContent.contents; } };
    property bool contentWholeWord { set { contentWholeWord.checked = value; } get { return contentWholeWord.checked; } };
    property bool contentMatchCase { set { contentMatchCase.checked = value; } get { return contentMatchCase.checked; } };
    property char * currentDirectory
-   { 
+   {
       set
       {
          GetWorkingDir(currentDirectory, MAX_DIRECTORY);
@@ -143,7 +142,7 @@ public:
          DataRow row;
          sprintf(label, $"%s Project", project.name);
          row = findIn.AddString(label);
-         row.tag = (uint)project;
+         row.tag = (int64)project;
       }
    }
 
@@ -162,11 +161,11 @@ public:
          }
       }
    }
-   
+
    void Show()
    {
       if(!created)
-         Create();
+         Modal();
       else
          Activate();
    }
@@ -180,9 +179,10 @@ private:
    DataRow inDirectoryRow;
    DataRow inWorkspaceRow;
    FindInFilesMode lastSelectionMode;
-   Project lastSelectionProject;
-   ProjectNode lastSelectionProjectNode;
+   String lastSelectionProject;
+   String lastSelectionProjectNode;
    bool replaceMode;
+   SelectorButton starDir;
 
    FindInFilesDialog()
    {
@@ -250,16 +250,23 @@ private:
          {
             Project prj;
             lastSelectionMode = mode;
-            lastSelectionProject = prj = lastSelectionMode == project ? (Project)row.tag : null;
+            prj = lastSelectionMode == project ? (Project)row.tag : null;
+            delete lastSelectionProject;
             if(prj)
             {
                DataRow r = null;
                ProjectNode node = prj.topNode;
+               char filePath[MAX_LOCATION];
+               prj.topNode.GetFullFilePath(filePath);
+               lastSelectionProject = CopyString(filePath);
                findWherePrjNode.Clear();
                ListProjectNodeFolders(node, null);
 
-               if(lastSelectionProjectNode && lastSelectionProjectNode.project == prj)
-                  node = lastSelectionProjectNode;
+               if(lastSelectionProjectNode && !(node = prj.topNode.FindByFullPath(lastSelectionProjectNode, false)))
+               {
+                  node = prj.topNode;
+                  delete lastSelectionProjectNode;
+               }
 
                for(r = findWherePrjNode.firstRow; r; r = r.next)
                   if((ProjectNode)r.tag == node)
@@ -279,7 +286,7 @@ private:
          row = findWherePrjNode/*parentRow*/.AddRow();
       else
          row = findWherePrjNode.AddRow();
-      row.tag = (int)node;
+      row.tag = (int64)node;
       row.SetData(null, node);
       if(node.files)
       {
@@ -287,7 +294,7 @@ private:
             ListProjectNodeFolders(child, row);
       }
    }
-   
+
    Label lfindWhere { llfindWhere, this, size.w = 72, labeledWindow = findWhere };
    PathBox findWhere
    {
@@ -303,18 +310,27 @@ private:
       bool NotifySelect(DropBox control, DataRow row, Modifiers mods)
       {
          if(row)
-            lastSelectionProjectNode = (ProjectNode)row.tag;
+         {
+            ProjectNode node = (ProjectNode)row.tag;
+            delete lastSelectionProjectNode;
+            if(node)
+            {
+               char filePath[MAX_LOCATION];
+               node.GetFullFilePath(filePath);
+               lastSelectionProjectNode = CopyString(filePath);
+            }
+         }
          return true;
       }
    };
    DataField projectNodeField { dataType = "ProjectNode", freeData = false };
-   
-   Window spacerA { llsubDirs, this, size = { 72, 10 }, clickThrough = true, background = activeBorder, inactive = true };
+
+   Window spacerA { llsubDirs, this, size = { 72, 10 }, clickThrough = true, background = formColor, inactive = true };
    Button subDirs
    {
       llsubDirs, this, $"Include Subdirectories", altU, isCheckbox = true, checked = true;
    };
-   
+
    Label lfilter { llfilter, this, size.w = 72, labeledWindow = filterDrop };
    DropBox filterDrop
    {
@@ -322,42 +338,42 @@ private:
 
       bool NotifySelect(DropBox control, DataRow row, Modifiers mods)
       {
-         fileFilter = row ? row.tag : 0;
+         fileFilter = (int)(row ? row.tag : 0);
          //ListFiles();
          return true;
       }
    };
-   
+
    Label lfileName { llfileName, this, size.w = 72, labeledWindow = fileName };
    EditBox fileName
    {
       llfileName, this, $"File name:", altN, size.h = 24, anchor.right = 0;
    };
-   
-   //Window spacerX { ll, this, size = { 72, 10 }, clickThrough = true, background = activeBorder, inactive = true };
+
+   //Window spacerX { ll, this, size = { 72, 10 }, clickThrough = true, background = formColor, inactive = true };
    //Button nameWholeWord { ll, this, "Whole word only", AltO, isCheckbox = true };
-   //Window spacerX { llwholeWord, this, size = { 72, 10 }, clickThrough = true, background = activeBorder, inactive = true };
+   //Window spacerX { llwholeWord, this, size = { 72, 10 }, clickThrough = true, background = formColor, inactive = true };
    //Button nameMatchCase { ll, this, "Match case", altA, isCheckbox = true };
-   
+
    Label lfindContent { llfindWhat, this, size.w = 72, labeledWindow = findContent };
    EditBox findContent
    {
       llfindWhat, this, $"Find what:", altT, size.h = 24, anchor.right = 0;
    };
-   
+
    Label lreplaceWith { llreplaceWith, this, size.w = 72, labeledWindow = replaceWith };
    EditBox replaceWith
    {
       llreplaceWith, this, $"Replace with:", altE;
       size.h = 24, anchor.right = 0;
    };
-   
-   Window spacerB { llwholeWord, this, size = { 72, 10 }, clickThrough = true, background = activeBorder, inactive = true };
+
+   Window spacerB { llwholeWord, this, size = { 72, 10 }, clickThrough = true, background = formColor, inactive = true };
    Button contentWholeWord { llwholeWord, this, $"Whole word only", altW, isCheckbox = true };
-   
-   Window spacerC { llmatchCase, this, size = { 72, 10 }, clickThrough = true, background = activeBorder, inactive = true };
+
+   Window spacerC { llmatchCase, this, size = { 72, 10 }, clickThrough = true, background = formColor, inactive = true };
    Button contentMatchCase { llmatchCase, this, $"Match case", altC, isCheckbox = true };
-   
+
    LayoutPage lpbuttons
    {
       layout, this;
@@ -381,19 +397,19 @@ private:
          if(findIn.currentRow == inDirectoryRow && !findPath[0])
          {
             findWhere.Activate();
-            MessageBox { type = ok, master = parent, 
+            MessageBox { type = ok, master = parent,
                   text = text, contents = $"You must specify a search location." }.Modal();
          }
-         else if(!FileExists(findPath))
+         else if(findIn.currentRow == inDirectoryRow && !FileExists(findPath))
          {
             findWhere.Activate();
-            MessageBox { type = ok, master = parent, 
+            MessageBox { type = ok, master = parent,
                   text = text, contents = $"Search location does not exist. Please provide a valid location." }.Modal();
          }
          else if(!fileName.contents[0] && !findContent.contents[0])
          {
             findContent.Activate();
-            MessageBox { type = ok, master = parent, 
+            MessageBox { type = ok, master = parent,
                   text = text, contents = $"Nothing to be found. Please specify at least one criteria." }.Modal();
          }
          else
@@ -405,7 +421,7 @@ private:
          return true;
       }
    };
-   
+
    Button cancel
    {
       llcancel, this, $"Cancel", hotKey = { escape }, size = { 80, 24 }, anchor.horz = 0, anchor.vert = 0;
@@ -444,12 +460,20 @@ private:
          if(lastSelectionProject)
          {
             for(row = findIn.firstRow; row; row = row.next)
-               if((Project)row.tag == lastSelectionProject)
-                  break;
+            {
+               char filePath[MAX_LOCATION];
+               Project p = (Project)row.tag;
+               if(p)
+               {
+                  p.topNode.GetFullFilePath(filePath);
+                  if(!fstrcmp(filePath, lastSelectionProject))
+                     break;
+               }
+            }
             if(row)
                findIn.SelectRow(row);
             else
-               lastSelectionProject = null;
+               delete lastSelectionProject;
          }
          if(!lastSelectionProject)
          {
@@ -570,7 +594,7 @@ private:
 
    bool OnKeyHit(Key key, unichar ch)
    {
-      if(ch)
+      if(ch && !key.alt && !key.ctrl && !key.shift && (contentMatchCase.active || contentWholeWord.active))
       {
          findContent.Activate();
          return findContent.OnKeyHit(key, ch);
@@ -623,10 +647,11 @@ private:
 
    unsigned int Main()
    {
+      const int stackSize = 1024;
       int frame, treeTop = 0;
-      int globalFindCount = 0, filesSearchedCount = 0, filesMatchedCount = 0;
+      int globalFindCount = 0, filesSearchedCount = 0, filesMatchedCount = 0, dirsMatchedCount = 0;
       //double lastTime = GetTime();
-      SearchStackFrame stack[1024];
+      SearchStackFrame stack[stackSize];
       FindInFilesMode mode = this.mode;
       
       EditBox replaceEdit = null;
@@ -637,36 +662,51 @@ private:
       app.Lock();
          {
             char substring[512];
+            char containing[512];
+            char * and;
+            char * filterName;
+            if(!strcmp(filter.name, "All files"))
+               filterName = "files";
+            else
+               filterName = filter.name;
             if(nameCriteria[0])
                sprintf(substring, $" with file name matching \"%s\"", nameCriteria);
             else
                substring[0] = '\0';
+            if(contentCriteria && contentCriteria[0])
+               sprintf(containing, $" containing \"%s\"", contentCriteria);
+            else
+               containing[0] = '\0';
+            if(substring[0] && containing[0])
+               and = " and";
+            else
+               and = "";
             if(mode == directory)
             {
                char * s;
                ide.outputView.findBox.Logf(
-                     $"Searching \"%s\"%s for %s%s%s containing \"%s\"\n\n",
+                     $"Searching \"%s\"%s for %s%s%s%s\n\n",
                      (s = CopySystemPath(dir)), subDirs ? $" and its sub directories" : "",
-                     filter.name, substring, substring[0] ? $" and" : "", contentCriteria);
+                     filterName, substring, and, containing);
                delete s;
             }
             else if(mode == workspace)
                ide.outputView.findBox.Logf(
-                     $"Searching workspace files for files%s%s containing \"%s\"\n\n",
-                     substring, substring[0] ? $" and" : "", contentCriteria);
+                     $"Searching workspace files for %s%s%s%s\n\n",
+                     filterName, substring, and, containing);
             else if(mode == project)
                ide.outputView.findBox.Logf(
-                     $"Searching project %s files for files%s%s containing \"%s\"\n\n",
-                     project.name, substring, substring[0] ? $" and" : "", contentCriteria);
+                     $"Searching project %s files for %s%s%s%s\n\n",
+                     project.name, filterName, substring, and, containing);
          }
       app.Unlock();
       
-      if(replaceMode && contentReplace[0])
+      if(replaceMode)
       {
          replaceEdit = EditBox
          {
             multiLine = true,textHorzScroll = true,textVertScroll = true, 
-            text = $"Replacing Editbox", size = Size { 640,480 },maxLineSize = 65536
+            text = $"Replacing Editbox", size = Size { 640,480 }/*,maxLineSize = 65536*/
          };
       }
 
@@ -675,14 +715,21 @@ private:
          strcpy(stack[0].path, dir);
          stack[0].fileList = FileListing { dir, extensions = filter.extensions };  // there should be a sorted = true/false 
 
-         for(frame = 0; frame >= 0 && !abort; )
+         for(frame = 0; frame >= 0 && frame < stackSize && !abort; )
          {
             if(stack[frame].fileList.Find())
             {
+               bool match = true;
+               if(nameCriteria[0])
+               {
+                  char name[MAX_LOCATION];
+                  GetLastDirectory(stack[frame].fileList.path, name);
+                  if(!(bool)SearchString(name, 0, nameCriteria, false, false))
+                     match = false;
+               }
                if(!stack[frame].fileList.stats.attribs.isDirectory)
                {
                   bool relative = false;
-                  bool match = true;
                   char fileRelative[MAX_LOCATION];
                   if(filter.ValidateFileName(stack[frame].fileList.name))
                   {
@@ -690,13 +737,6 @@ private:
                      relative = true;
                      
                      filesSearchedCount++;
-                     if(nameCriteria[0])
-                     {
-                        char name[MAX_LOCATION];
-                        GetLastDirectory(stack[frame].fileList.path, name);
-                        if(!(bool)SearchString(name, 0, nameCriteria, false, false))
-                           match = false;
-                     }
                      if(match && contentCriteria[0])
                      {
                         int ret;
@@ -706,7 +746,7 @@ private:
                                  $"Searching %s for %s", relative ? fileRelative : stack[frame].fileList.path, contentCriteria);
                         app.Unlock();
 
-                        if(replaceMode && contentReplace[0])
+                        if(replaceMode)
                            ret = SearchFileContentAndReplace(stack[frame].fileList.path, relative, fileRelative, replaceEdit);
                         else
                            ret = SearchFileContent(stack[frame].fileList.path, relative, fileRelative);
@@ -721,7 +761,7 @@ private:
                         filesMatchedCount++;
                         app.Lock();
                            ide.outputView.findBox.Logf(
-                                 $"%s matches the file name criteria\n",
+                                 "%s\n",
                                  relative ? fileRelative : stack[frame].fileList.path);
                         app.Unlock();
                      }
@@ -734,12 +774,19 @@ private:
                   MakePathRelative(stack[frame].fileList.path, dir, fileRelative);
                   relative = true;
                   app.Lock();
+                     if(match && nameCriteria[0])
+                     {
+                        dirsMatchedCount++;
+                        ide.outputView.findBox.Logf(
+                              "%s\n",
+                              relative ? fileRelative : stack[frame].fileList.path);
+                     }
                      ide.outputView.findBox.Tellf(
                            $"Searching %s", relative ? fileRelative : stack[frame].fileList.path);
                   app.Unlock();
                }
 
-               if(subDirs && stack[frame].fileList.stats.attribs.isDirectory)
+               if(subDirs && stack[frame].fileList.stats.attribs.isDirectory && strcmp(stack[frame].fileList.name, ".git"))
                {
                   int lastFrame = frame;
                   /*double thisTime = GetTime();
@@ -800,10 +847,12 @@ private:
                      bool relative = true;
                      char fileRelative[MAX_LOCATION];
                      char filePath[MAX_LOCATION];
-                     strcpy(filePath, prj.topNode.path);
+                     filePath[0] = '\0';
+                     PathCat(filePath, prj.topNode.path);
                      PathCat(filePath, stack[frame].path);
                      PathCat(filePath, stack[frame].name);
-                     strcpy(fileRelative, stack[frame].path);
+                     fileRelative[0] = '\0';
+                     PathCat(fileRelative, stack[frame].path);
                      PathCat(fileRelative, stack[frame].name);
                      if(relative && mode == workspace && prj != ide.project)
                      {
@@ -826,7 +875,7 @@ private:
                                        contentCriteria);
                               app.Unlock();
 
-                              if(replaceMode && contentReplace[0])
+                              if(replaceMode)
                                  ret = SearchFileContentAndReplace(filePath, relative, fileRelative, replaceEdit);
                               else
                                  ret = SearchFileContent(filePath, relative, fileRelative);
@@ -842,7 +891,6 @@ private:
                               app.Lock();
                                  ide.outputView.findBox.Logf(
                                        "%s\n", relative ? fileRelative : filePath);
-                                       /*" matches the file name criteria"*/
                               app.Unlock();
                            }
                         }
@@ -851,6 +899,29 @@ private:
                      break;
                   }
                   case folder:
+                  {
+                     bool relative = true;
+                     char fileRelative[MAX_LOCATION];
+                     char filePath[MAX_LOCATION];
+                     filePath[0] = '\0';
+                     PathCat(filePath, prj.topNode.path);
+                     PathCat(filePath, stack[frame].path);
+                     fileRelative[0] = '\0';
+                     PathCat(fileRelative, stack[frame].path);
+                     if(relative && mode == workspace && prj != ide.project)
+                     {
+                        char special[MAX_LOCATION];
+                        sprintf(special, "(%s)%s", prj.name, fileRelative);
+                        strcpy(fileRelative, special);
+                     }
+                     if(nameCriteria[0] && (bool)SearchString(stack[frame].name, 0, nameCriteria, false, false))
+                     {
+                        dirsMatchedCount++;
+                        app.Lock();
+                           ide.outputView.findBox.Logf(
+                                 "%s\n", relative ? fileRelative : filePath);
+                        app.Unlock();
+                     }
                      if((subDirs || firtIteration) && stack[frame].files && stack[frame].files.count)
                      {
                         int lastFrame = frame;
@@ -861,6 +932,7 @@ private:
                      else
                         stack[frame] = stack[frame].next;
                      break;
+                  }
                   case resources:
                      stack[frame] = stack[frame].next;
                      break;
@@ -889,6 +961,8 @@ private:
       app.Lock();
          if(filesSearchedCount)
          {
+            if(!contentCriteria[0] && (filesMatchedCount || dirsMatchedCount))
+               ide.outputView.findBox.Logf("\n");
             if(globalFindCount)
                ide.outputView.findBox.Logf(
                      $"%s search %s a total of %d match%s in %d out of the %d file%s searched\n",
@@ -962,6 +1036,14 @@ private:
                f.Seek(-strlen(contentCriteria), current);*/
          }
          delete f;
+         if(findCount)
+         {
+            app.Lock();
+               ide.outputView.findBox.Logf(
+                     $"Found %d match%s in \"%s\"%s\n\n", findCount, (findCount > 1) ? "es" : "",
+                     relative ? fileRelative : filePath, abortNow ? $" before search was aborted" : "");
+            app.Unlock();
+         }
       }
       else
       {
@@ -969,14 +1051,6 @@ private:
             ide.outputView.findBox.Logf($"Unable to open file %s\n\n", filePath);
          app.Unlock();
       }
-      if(findCount)
-      {
-         app.Lock();
-            ide.outputView.findBox.Logf(
-                  $"Found %d match%s in \"%s\"%s\n\n", findCount, (findCount > 1) ? "es" : "",
-                  relative ? fileRelative : filePath, abortNow ? $" before search was aborted" : "");
-         app.Unlock();
-      }
       return findCount;
    }
 
@@ -1048,6 +1122,14 @@ private:
                
          }
          delete f;
+         if(replaceCount)
+         {
+            app.Lock();
+               ide.outputView.findBox.Logf(
+                     $"Replaced %d match%s in \"%s\"%s\n\n", replaceCount, (replaceCount > 1) ? $"es" : "",
+                     relative ? fileRelative : filePath, abortNow ? $" before search was aborted" : "");
+            app.Unlock();
+         }
       }
       else
       {
@@ -1055,14 +1137,6 @@ private:
             ide.outputView.findBox.Logf($"Unable to open file %s\n\n", filePath);
          app.Unlock();
       }
-      if(replaceCount)
-      {
-         app.Lock();
-            ide.outputView.findBox.Logf(
-                  $"Replaced %d match%s in \"%s\"%s\n\n", replaceCount, (replaceCount > 1) ? $"es" : "",
-                  relative ? fileRelative : filePath, abortNow ? $" before search was aborted" : "");
-         app.Unlock();
-      }
       return replaceCount;
    }
 }