shithub: nc

Download patch

ref: 13040fa8c6785f422384989cd1591990a9c558bb
parent: dd71216e74f1e618a8a2e63c54a9edb382951525
author: phil9 <telephil9@gmail.com>
date: Mon Dec 26 15:58:38 EST 2022

revamped message dialog

	new message dialog that can show info or error messages but also ask for confirmation.
	style is also better if you ask me :]

--- a/a.h
+++ b/a.h
@@ -7,7 +7,6 @@
 #include <plumb.h>
 #include <bio.h>
 
-
 typedef struct Dirview Dirview;
 typedef struct Dirpanel Dirpanel;
 typedef struct Dirmodel Dirmodel;
@@ -95,6 +94,17 @@
 	Action	f;
 };
 
+enum{
+	Dinfo,
+	Derror,
+	Dconfirm,
+};
+
+enum{
+	Bno,
+	Byes,
+};
+
 Dirview*	mkdirview(char*);
 void		dirviewsetrect(Dirview*, Rectangle);
 void		dirviewredraw(Dirview*);
@@ -137,7 +147,7 @@
 
 int			match(char*, char*);
 
-void		alert(const char*, const char*, const char*, Mousectl*, Keyboardctl*);
+int			message(int, const char*, Mousectl*, Keyboardctl*);
 
 Rectangle	boundsrect(Rectangle);
 Image*		ealloccolor(ulong);
@@ -163,6 +173,7 @@
 	Ctitle,
 	Cborder,
 	Csel,
+	Cerror,
 	Cdialog,
 	Ncols
 };
--- a/dirviewcmd.c
+++ b/dirviewcmd.c
@@ -58,7 +58,7 @@
 {
 	Dirpanel *p;
 	Dir d, null;
-	char errbuf[ERRMAX], opath[1024] = {0}, buf[255] = {0};
+	char errbuf[64+ERRMAX], opath[1024] = {0}, buf[255] = {0};
 	int n;
 
 	p = dirviewcurrentpanel(dview);
@@ -65,7 +65,7 @@
 	if(strcmp(p->model->path, dirviewotherpanel(dview)->model->path) == 0){
 		d = dirmodelgetdir(p->model, dirpanelselectedindex(p));
 		if(d.qid.type&QTDIR){
-			alert("Error", "Cannot rename directories.", nil, mc, kc);
+			message(Derror, "cannot rename directories.", mc, kc);
 			return;
 		}
 		snprint(buf, sizeof buf, d.name);
@@ -77,8 +77,8 @@
 		nulldir(&null);
 		null.name = buf;
 		if(dirwstat(opath, &null) < 0){
-			errstr(errbuf, ERRMAX-1);
-			alert("Error", "Rename failed", errbuf, mc, kc);
+			snprint(errbuf, sizeof errbuf, "rename failed: %r");
+			message(Derror, errbuf, mc, kc);
 		}else{
 			dirmodelreload(p->model);
 			dirmodelreload(dirviewotherpanel(dview)->model);
--- a/main.c
+++ b/main.c
@@ -18,7 +18,8 @@
 	cols[Ctitle] = ealloccolor(DGreygreen);
 	cols[Cborder] = ealloccolor(0xAAAAAAFF);
 	cols[Csel] = ealloccolor(0xCCCCCCFF);
-	cols[Cdialog] = ealloccolor(0xF4F4F4FF);
+	cols[Cerror] = ealloccolor(0x721c24ff);
+	cols[Cdialog] = ealloccolor(0xFAFAFAFF);
 }
 
 void
--- /dev/null
+++ b/message.c
@@ -1,0 +1,138 @@
+#include "a.h"
+
+enum{ 
+	Border = 1, 
+	Padding = 8, 
+};
+
+static
+int
+max(int a, int b)
+{
+	return a>b ? a : b;
+}
+
+void
+button(Image *b, Rectangle br, char *label)
+{
+	Point p;
+	int dx;
+
+	dx = (Dx(br) - stringwidth(font, label)) / 2;
+	border(b, br, 2, cols[Csel], ZP);
+	p = addpt(br.min, Pt(dx, 0.25*font->height));
+	p = stringn(b, p, cols[Ctitle], ZP, font, label, 1);
+	string(b, p, cols[Cfg], ZP, font, label+1);
+}
+
+int
+message(int type, const char *message, Mousectl *mctl, Keyboardctl *kctl)
+{
+	Alt alts[3];
+	Rectangle r, br, brn, sc;
+	Point o, p;
+	Image *b, *save, *bg, *fg, *hi;
+	int rc, done, h, w, bw, bh, mw;
+	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)
+		;
+	rc = Bno;
+	bg = cols[Cdialog];
+	fg = cols[Cfg];
+	hi = type == Derror ? cols[Cerror] : cols[Ctitle];
+	done = 0;
+	save = nil;
+	bw = 3*stringwidth(font, "Yes");
+	bh = 1.5*font->height;
+	h = Border+Padding+2*font->height+Padding+bh+Padding+Border;
+	mw = stringwidth(font, message);
+	w = Border+Padding+1.5*mw+Padding+Border;
+	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, Border, cols[Csel], ZP);
+		p = addpt(o, Pt(0, 2));
+		line(b, p, Pt(r.max.x, p.y), 0, 0, 2, hi, ZP);
+		p = addpt(o, Pt(Border+Padding, Border+Padding+0.5*font->height));
+		string(b, p, fg, ZP, font, message);
+		p.y += Padding+1.5*font->height;
+		br = rectaddpt(Rect(0, 0, bw, bh), addpt(o, Pt(Border+Padding, Border+Padding+2*font->height+Padding)));
+		button(b, br, type == Dconfirm ? "Yes" : "Ok");
+		if(type == Dconfirm){
+			brn = rectaddpt(br, Pt(bw+Padding, 0));
+			button(b, brn, "No");
+		}
+		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((type == Dinfo || type == Derror) && (k == 'o' || k == 'O')){
+				done = 1;
+				rc = Byes;
+			}else if(type == Dconfirm && (k == 'y' || k == 'Y')){
+				done = 1;
+				rc = Byes;
+			}else if(k == '\n'){
+				done = 1;
+				rc = Byes;
+			}else if(type == Dconfirm && (k == 'n' || k == 'N')){
+				done = 1;
+				rc = Bno;
+			}else if(k == Kesc){
+				done = 1;
+				rc = Bno;
+			}
+			break;
+		case 0:
+			if(m.buttons&4){
+				if(ptinrect(m.xy, br)){
+					done = 1;
+					rc = Byes;
+				}else if(type == Dconfirm && ptinrect(m.xy, brn)){
+					done = 1;
+					rc = Bno;
+				}
+			}
+			break;
+		}
+		if(save){
+			draw(b, save->r, save, nil, save->r.min);
+			freeimage(save);
+			save = nil;
+		}
+			
+	}
+	replclipr(b, 0, sc);
+	flushimage(display, 1);
+	return rc;
+}
--- a/mkfile
+++ b/mkfile
@@ -13,7 +13,7 @@
 	dirpanel.$O		\
 	viewercmd.$O	\
 	text.$O			\
-	alert.$O		\
+	message.$O		\
 	glob.$O			\
 	utils.$O