shithub: vdir

Download patch

ref: ff8478aa12d49a2bb177a84fb038a102b79d1830
parent: 9d6acbaea32ebff4ef4cbe69a5f2ba010b9b6ad6
author: phil9 <telephil9@gmail.com>
date: Thu May 9 12:40:07 EDT 2024

add a confirmation dialog for delete operation

	remove the -r flag and make it the default but add a confirmation
	step prior to actually deleting files/directories.

--- /dev/null
+++ b/confirm.c
@@ -1,0 +1,97 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+enum { Padding = 12, };
+
+int
+confirm(const char *message, Mousectl *mctl, Keyboardctl *kctl)
+{
+	Alt alts[3];
+	Rectangle r, sc;
+	Point o, p;
+	Image *b, *save, *bg, *fg, *hi;
+	int done, rc, h, w;
+	Mouse m;
+	Rune k;
+
+	alts[0].op = CHANRCV;
+	alts[0].c  = mctl->c;
+	alts[0].v  = &m;
+	alts[1].op = CHANRCV;
+	alts[1].c  = kctl->c;
+	alts[1].v  = &k;
+	alts[2].op = CHANEND;
+	alts[2].c  = nil;
+	alts[2].v  = nil;
+	while(nbrecv(kctl->c, nil)==1)
+		;
+	bg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xffffffff);
+	fg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000ff);
+	hi = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreygreen);
+	done = 0;
+	rc = 0;
+	save = nil;
+	h = Padding+font->height+Padding;
+	w = Padding+stringwidth(font, message)+stringwidth(font, " Yes / No")+Padding;
+	b = screen;
+	sc = b->clipr;
+	replclipr(b, 0, b->r);
+	while(!done){
+		o = addpt(screen->r.min, Pt((Dx(screen->r)-w)/2, (Dy(screen->r)-h)/2));
+		r = Rect(o.x, o.y, o.x+w, o.y+h);
+		if(save==nil){
+			save = allocimage(display, r, b->chan, 0, DNofill);
+			if(save==nil)
+				break;
+			draw(save, r, b, nil, r.min);
+		}
+		draw(b, r, bg, nil, ZP);
+		border(b, r, 2, hi, ZP);
+		p = addpt(o, Pt(Padding, Padding));
+		p = string(b, p, fg, ZP, font, message);
+		p = string(b, p, hi, ZP, font, " Y");
+		p = string(b, p, fg, ZP, font, "es /");
+		p = string(b, p, hi, ZP, font, " N");
+		string(b, p, fg, ZP, font, "o");
+		flushimage(display, 1);
+		if(b!=screen || !eqrect(screen->clipr, sc)){
+			freeimage(save);
+			save = nil;
+		}
+		b = screen;
+		sc = b->clipr;
+		replclipr(b, 0, b->r);
+		switch(alt(alts)){
+		default:
+			continue;
+			break;
+		case 1:
+			if(k=='\n' || k==Kesc || k=='n' || k=='N'){
+				done = 1;
+				rc = 0;
+			}else if(k=='y' || k=='Y'){
+				done = 1;
+				rc = 1;
+			}
+			break;
+		case 0:
+			done = m.buttons&1 && ptinrect(m.xy, r);
+			rc = 0;
+			break;
+		}
+		if(save){
+			draw(b, save->r, save, nil, save->r.min);
+			freeimage(save);
+			save = nil;
+		}
+			
+	}
+	replclipr(b, 0, sc);
+	freeimage(bg);
+	freeimage(fg);
+	return rc;
+}
--- a/mkfile
+++ b/mkfile
@@ -2,7 +2,7 @@
 
 BIN=/$objtype/bin
 TARG=vdir
-OFILES=vdir.$O alert.$O theme.$O
+OFILES=vdir.$O alert.$O confirm.$O theme.$O
 HFILES=icons.h
 
 </sys/src/cmd/mkone
--- a/vdir.c
+++ b/vdir.c
@@ -10,6 +10,7 @@
 #include "theme.h"
 
 extern void alert(const char *message, const char *err, Mousectl *mctl, Keyboardctl *kctl);
+extern int confirm(const char *message, Mousectl *mctl, Keyboardctl *kctl);
 void redraw(void);
 
 enum
@@ -78,7 +79,6 @@
 int scrolling;
 int oldbuttons;
 int lastn;
-int rmode;
 
 void
 showerrstr(char *msg)
@@ -258,14 +258,20 @@
 }
 
 void
-rm(char *name)
+rm(Dir d)
 {
-	char cmd[300];
+	char cmd[300], buf[1024] = {0};
 	char *p, *qp;
 
-	p = smprint("%s/%s", path, name);
+	if(d.qid.type&QTDIR)
+		snprint(buf, sizeof buf, "Delete directory '%s' and its subdirectories ?", d.name);
+	else
+		snprint(buf, sizeof buf, "Delete file '%s' ?", d.name);
+	if(!confirm(buf, mctl, kctl))
+		return;
+	p = smprint("%s/%s", path, d.name);
 	qp = quotestrdup(p);
-	snprint(cmd, sizeof cmd, "rm %s %s >/dev/null >[2=1]", rmode ? "-r" : "", qp);
+	snprint(cmd, sizeof cmd, "rm -r %s >/dev/null >[2=1]", qp);
 	if(doexec(cmd) < 0)
 		showerrstr("Cannot remove file/directory");
 	else
@@ -625,7 +631,7 @@
 			d = dirs[offset+n];
 			switch(menuhit(2, mctl, &menu2, nil)){
 			case Mdelete:
-				rm(d.name);
+				rm(d);
 				redraw();
 				break;
 			case Mrename:
@@ -760,11 +766,7 @@
 	scrolling = 0;
 	oldbuttons = 0;
 	lastn = -1;
-	rmode = 0;
 	ARGBEGIN{
-	case 'r':
-		++rmode;
-		break;
 	default:
 		usage();
 	}ARGEND;