From ba4d06e09e9b08f1dfc11cee827e09e723fa21f0 Mon Sep 17 00:00:00 2001
From: Yorhel <git@yorhel.nl>
Date: Sun, 19 Apr 2009 11:35:24 +0200
Subject: [PATCH] (partly) rewrote delete.c for the new framework and re-added
 the deletion feature

---
 src/Makefile.am |   4 +-
 src/browser.c   |  17 +--
 src/delete.c    | 280 +++++++++++++++++++++++++++---------------------
 src/delete.h    |  39 +++++++
 src/main.c      |   7 +-
 5 files changed, 212 insertions(+), 135 deletions(-)
 create mode 100644 src/delete.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 1bf484e..e9d0b52 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
 bin_PROGRAMS = ncdu
 
-ncdu_SOURCES = browser.c calc.c exclude.c help.c main.c util.c
+ncdu_SOURCES = browser.c calc.c delete.c exclude.c help.c main.c util.c
 
-noinst_HEADERS = browser.h calc.h exclude.h help.h ncdu.h util.h
+noinst_HEADERS = browser.h calc.h delete.h exclude.h help.h ncdu.h util.h
diff --git a/src/browser.c b/src/browser.c
index ff99847..089ffcf 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -27,6 +27,7 @@
 #include "browser.h"
 #include "util.h"
 #include "calc.h"
+#include "delete.h"
 #include "help.h"
 
 #include <string.h>
@@ -443,17 +444,15 @@ int browse_key(int ch) {
       help_init();
       nonfo++;
       break;
-      /*
     case 'd':
-      drawBrowser(0);
-      n = selected();
-      if(n != bcur->parent)
-        bcur = showDelete(n);
-      if(bcur && bcur->parent)
-        bcur = bcur->parent->sub;
+      for(n=browse_dir; n!=NULL; n=n->next)
+        if(n->flags & FF_BSEL)
+          break;
+      if(n == NULL)
+        break;
+      delete_init(n);
       nonfo++;
       break;
-        */
   }
 
   if(sort)
@@ -470,6 +469,8 @@ void browse_init(struct dir *cur) {
     browse_dir = cur->sub;
   else
     browse_dir = cur;
+  if(browse_dir != NULL && browse_dir->parent->sub != browse_dir)
+    browse_dir = cur->parent->sub;
   browse_dir = browse_sort(browse_dir);
 }
 
diff --git a/src/delete.c b/src/delete.c
index 7109373..e19b7e2 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -1,5 +1,5 @@
-/* ncdu - NCurses Disk Usage 
-  
+/* ncdu - NCurses Disk Usage
+
   Copyright (c) 2007-2009 Yoran Heling
 
   Permission is hereby granted, free of charge, to any person obtaining
@@ -9,10 +9,10 @@
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:
-  
+
   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.
-  
+
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -23,195 +23,227 @@
 
 */
 
+
 #include "ncdu.h"
+#include "util.h"
+#include "browser.h"
+
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#define DS_CONFIRM  0
+#define DS_PROGRESS 1
+#define DS_FAILED   2
+
+
+int delete_delay = 100;
 
 suseconds_t lastupdate;
+struct dir *root;
+char noconfirm = 0,
+     ignoreerr = 0,
+     state, seloption, curfile[PATH_MAX];
+int lasterrno;
 
 
-void drawConfirm(struct dir *del, int sel) {
+void delete_draw_confirm() {
   nccreate(6, 60, "Confirm delete");
 
   ncprint(1, 2, "Are you sure you want to delete \"%s\"%c",
-    cropdir(del->name, 21), del->flags & FF_DIR ? ' ' : '?');
-  if(del->flags & FF_DIR) 
+    cropstr(root->name, 21), root->flags & FF_DIR ? ' ' : '?');
+  if(root->flags & FF_DIR)
     ncprint(2, 18, "and all of its contents?");
 
-  if(sel == 0)
+  if(seloption == 0)
     attron(A_REVERSE);
   ncaddstr(4, 15, "yes");
   attroff(A_REVERSE);
-  if(sel == 1)
+  if(seloption == 1)
     attron(A_REVERSE);
   ncaddstr(4, 24, "no");
   attroff(A_REVERSE);
-  if(sel == 2)
+  if(seloption == 2)
     attron(A_REVERSE);
   ncaddstr(4, 31, "don't ask me again");
   attroff(A_REVERSE);
 
-  ncmove(4, sel == 0 ? 15 : sel == 1 ? 24 : 31);
-  
-  refresh();
+  ncmove(4, seloption == 0 ? 15 : seloption == 1 ? 24 : 31);
 }
 
 
-/* show progress */
-static void drawProgress(char *file) {
+void delete_draw_progress() {
   nccreate(6, 60, "Deleting...");
 
-  ncaddstr(1, 2, cropdir(file, 47));
+  ncaddstr(1, 2, cropstr(curfile, 47));
   ncaddstr(4, 41, "Press q to abort");
-
-  refresh();
 }
 
 
-/* show error dialog */
-static void drawError(int sel, char *file) {
+void delete_draw_error() {
   nccreate(6, 60, "Error!");
 
-  ncprint(1, 2, "Can't delete %s:", cropdir(file, 42));
-  ncaddstr(2, 4, strerror(errno));
+  ncprint(1, 2, "Can't delete %s:", cropstr(curfile, 42));
+  ncaddstr(2, 4, strerror(lasterrno));
 
-  if(sel == 0)
+  if(seloption == 0)
     attron(A_REVERSE);
   ncaddstr(4, 14, "abort");
   attroff(A_REVERSE);
-  if(sel == 1)
+  if(seloption == 1)
     attron(A_REVERSE);
   ncaddstr(4, 23, "ignore");
   attroff(A_REVERSE);
-  if(sel == 2)
+  if(seloption == 2)
     attron(A_REVERSE);
   ncaddstr(4, 33, "ignore all");
   attroff(A_REVERSE);
+}
+
 
-  refresh();
+int delete_draw() {
+  struct timeval tv;
+
+  switch(state) {
+    case DS_CONFIRM:
+      browse_draw();
+      delete_draw_confirm();
+      return 0;
+    case DS_PROGRESS:
+      gettimeofday(&tv, (void *)NULL);
+      tv.tv_usec = (1000*(tv.tv_sec % 1000) + (tv.tv_usec / 1000)) / delete_delay;
+      if(lastupdate != tv.tv_usec) {
+        browse_draw();
+        delete_draw_progress();
+        lastupdate = tv.tv_usec;
+        return 0;
+      }
+      return 1;
+    case DS_FAILED:
+      browse_draw();
+      delete_draw_error();
+      return 0;
+  }
+  return 1;
 }
 
 
-struct dir *deleteDir(struct dir *dr) {
+int delete_key(int ch) {
+  /* confirm */
+  if(state == DS_CONFIRM)
+    switch(ch) {
+      case KEY_LEFT:
+        if(--seloption < 0)
+          seloption = 0;
+        break;
+      case KEY_RIGHT:
+        if(++seloption > 2)
+          seloption = 2;
+        break;
+      case '\n':
+        if(seloption == 1)
+          return 1;
+        if(seloption == 2)
+          noconfirm++;
+        state = DS_PROGRESS;
+        break;
+      case 'q':
+        return 1;
+    }
+  /* processing deletion */
+  else if(state == DS_PROGRESS)
+    switch(ch) {
+      case 'q':
+        return 1;
+    }
+  /* error */
+  else if(state == DS_FAILED)
+    switch(ch) {
+      case KEY_LEFT:
+        if(--seloption < 0)
+          seloption = 0;
+        break;
+      case KEY_RIGHT:
+        if(++seloption > 2)
+          seloption = 2;
+        break;
+      case 10:
+        if(seloption == 0)
+          return 1;
+        if(seloption == 2)
+          ignoreerr++;
+        state = DS_PROGRESS;
+        break;
+      case 'q':
+        return 1;
+    }
+
+  return 0;
+}
+
+
+struct dir *delete_dir(struct dir *dr) {
   struct dir *nxt, *cur;
-  int ch, sel = 0;
+  int r;
   char file[PATH_MAX];
-  struct timeval tv;
 
   getpath(dr, file);
   if(file[strlen(file)-1] != '/')
     strcat(file, "/");
   strcat(file, dr->name);
 
- /* check for input or screen resizes */
-  nodelay(stdscr, 1);
-  while((ch = getch()) != ERR) {
-    if(ch == 'q')
-      return(NULL);
-    if(ch == KEY_RESIZE) {
-      ncresize();
-      drawBrowser(0);
-      drawProgress(file);
-    }
-  }
-  nodelay(stdscr, 0);
-
- /* don't update the screen with shorter intervals than sdelay */
-  gettimeofday(&tv, (void *)NULL);
-  tv.tv_usec = (1000*(tv.tv_sec % 1000) + (tv.tv_usec / 1000)) / sdelay;
-  if(lastupdate != tv.tv_usec) {
-    drawProgress(file);
-    lastupdate = tv.tv_usec;
-  }
+  /* check for input or screen resizes */
+  strcpy(curfile, file);
+  if(input_handle(1))
+    return root;
 
- /* do the actual deleting */
+  /* do the actual deleting */
   if(dr->flags & FF_DIR) {
     if(dr->sub != NULL) {
       nxt = dr->sub;
       while(nxt != NULL) {
         cur = nxt;
         nxt = cur->next;
-        if(deleteDir(cur) == NULL)
-          return(NULL);
+        if(delete_dir(cur) == root)
+          return root;
       }
     }
-    ch = rmdir(file);
+    r = rmdir(file);
   } else
-    ch = unlink(file);
-
- /* error occured, ask user what to do */
-  if(ch == -1 && !(sflags & SF_IGNE)) {
-    drawError(sel, file);
-    while((ch = getch())) {
-      switch(ch) {
-        case KEY_LEFT:
-          if(--sel < 0)
-            sel = 0;
-          break;
-        case KEY_RIGHT:
-          if(++sel > 2)
-            sel = 2;
-          break;
-        case 10:
-          if(sel == 0)
-            return(NULL);
-          if(sel == 2)
-            sflags |= SF_IGNE;
-          goto ignore;
-        case 'q':
-          return(NULL);
-        case KEY_RESIZE:
-          ncresize();
-          drawBrowser(0);
-          break;
-      }
-      drawError(sel, file);
-    }
-  };
-  ignore: 
+    r = unlink(file);
+
+  /* error occured, ask user what to do */
+  if(r == -1 && !ignoreerr) {
+    state = DS_FAILED;
+    lasterrno = errno;
+    while(state == DS_FAILED)
+      if(input_handle(0))
+        return root;
+  }
 
-  return(freedir(dr));
+  return freedir(dr);
 }
 
 
-struct dir *showDelete(struct dir *dr) {
-  int ch, sel = 1;
-  struct dir *ret;
-
- /* confirm */
-  if(sflags & SF_NOCFM)
-    goto doit;
-  
-  drawConfirm(dr, sel);
-  while((ch = getch())) {
-    switch(ch) {
-      case KEY_LEFT:
-        if(--sel < 0)
-          sel = 0;
-        break;
-      case KEY_RIGHT:
-        if(++sel > 2)
-          sel = 2;
-        break;
-      case 10:
-        if(sel == 1)
-          return(dr);
-        if(sel == 2)
-          sflags |= SF_NOCFM;
-        goto doit;
-      case 'q':
-        return(dr);
-      case KEY_RESIZE:
-        ncresize();
-        drawBrowser(0);
-        break;
-    }
-    drawConfirm(dr, sel);
-  }
+void delete_process() {
+  /* confirm */
+  seloption = 1;
+  while(state == DS_CONFIRM && !noconfirm)
+    if(input_handle(0))
+      return browse_init(root);
 
-  doit:
-  lastupdate = 999; /* just some random high value as initialisation */
+  /* delete */
+  lastupdate = 999;
+  seloption = 0;
+  return browse_init(delete_dir(root));
+}
 
-  ret = deleteDir(dr);
 
-  return(ret == NULL ? dr : ret);
+void delete_init(struct dir *dr) {
+  state = DS_CONFIRM;
+  root = dr;
+  pstate = ST_DEL;
 }
 
diff --git a/src/delete.h b/src/delete.h
new file mode 100644
index 0000000..a994854
--- /dev/null
+++ b/src/delete.h
@@ -0,0 +1,39 @@
+/* ncdu - NCurses Disk Usage
+
+  Copyright (c) 2007-2009 Yoran Heling
+
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef _delete_h
+#define _delete_h
+
+#include "ncdu.h"
+
+extern int delete_delay;
+
+void delete_process(void);
+int  delete_key(int);
+int  delete_draw(void);
+void delete_init(struct dir *);
+
+
+#endif
diff --git a/src/main.c b/src/main.c
index 888aaad..a3ef949 100644
--- a/src/main.c
+++ b/src/main.c
@@ -27,6 +27,7 @@
 #include "exclude.h"
 #include "util.h"
 #include "calc.h"
+#include "delete.h"
 #include "browser.h"
 
 #include <stdlib.h>
@@ -46,6 +47,7 @@ void screen_draw() {
     case ST_CALC:   n = calc_draw();   break;
     case ST_BROWSE: n = browse_draw(); break;
     case ST_HELP:   n = help_draw();   break;
+    case ST_DEL:    n = delete_draw(); break;
   }
   if(!n)
     refresh();
@@ -68,6 +70,7 @@ int input_handle(int wait) {
       case ST_CALC:   return calc_key(ch);
       case ST_BROWSE: return browse_key(ch);
       case ST_HELP:   return help_key(ch);
+      case ST_DEL:    return delete_key(ch);
     }
     screen_draw();
   }
@@ -106,7 +109,7 @@ void argv_parse(int argc, char **argv, char *dir) {
       for(j=1; j<len; j++)
         switch(argv[i][j]) {
           case 'x': calc_smfs = 1; break;
-          case 'q': calc_delay = 2000;     break;
+          case 'q': calc_delay = delete_delay = 2000;     break;
           case '?':
           case 'h':
             printf("ncdu [-hqvx] [--exclude PATTERN] [-X FILE] directory\n\n");
@@ -154,6 +157,8 @@ int main(int argc, char **argv) {
   while(pstate != ST_QUIT) {
     if(pstate == ST_CALC)
       calc_process();
+    if(pstate == ST_DEL)
+      delete_process();
     else if(input_handle(0))
       break;
   }
-- 
GitLab