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;