shithub: nc

Download patch

ref: b355c72152380f66c87553ca51ef3d9020c5d40c
parent: d9121a953e12ee3c3699ddd533d69f57e2f3a74c
author: phil9 <[email protected]>
date: Tue Dec 27 14:49:34 EST 2022

new input dialog

--- a/a.h
+++ b/a.h
@@ -6,6 +6,7 @@
 #include <thread.h>
 #include <plumb.h>
 #include <bio.h>
+#include <ctype.h>
 
 typedef struct Dirview Dirview;
 typedef struct Dirpanel Dirpanel;
@@ -151,6 +152,7 @@
 
 int			message(int, const char*, Mousectl*, Keyboardctl*);
 void		errormessage(char*, Mousectl*, Keyboardctl*);
+int			input(char*, char*, int, Mousectl*, Keyboardctl*);
 
 int			mkdir(char*, char*);
 int			rm(char*, Dir);
@@ -184,6 +186,7 @@
 	Ncols
 };
 extern Image*		cols[Ncols];
+extern Image*		tick;
 extern Mousectl*	mc;
 extern Keyboardctl*	kc;
 extern int			mode;
--- /dev/null
+++ b/input.c
@@ -1,0 +1,173 @@
+#include "a.h"
+
+enum{ 
+	Border = 1, 
+	Padding = 8, 
+};
+
+static
+int
+max(int a, int b)
+{
+	return a>b ? a : b;
+}
+
+static void
+button(Image *b, Rectangle br, char *label, int focus)
+{
+	Point p;
+	int dx;
+
+	dx = (Dx(br) - stringwidth(font, label)) / 2;
+	border(b, br, 2, focus ? cols[Ctitle] : 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);
+}
+
+static void
+entry(Image *b, Rectangle r, char *text, int focus)
+{
+	Point p;
+
+	border(b, r, 2, focus ? cols[Ctitle] : cols[Csel], ZP);
+	p = addpt(r.min, Pt(Padding, Padding/2));
+	p = string(b, p, cols[Cfg], ZP, font, text);
+	if(focus)
+		draw(b, rectaddpt(tick->r, p), tick, nil, ZP);
+}
+
+int
+input(char *ask, char *buf, int nbuf, Mousectl *mctl, Keyboardctl *kctl)
+{
+	Alt alts[3];
+	Rectangle r, er, br, brn, sc;
+	Point o, p;
+	Image *b, *save, *bg, *fg, *hi;
+	int rc, done, len, h, w, ew, eh, bw, bh, mw, dy, focus;
+	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 = -1;
+	len = strlen(buf);
+	bg = cols[Cdialog];
+	fg = cols[Cfg];
+	hi = cols[Ctitle];
+	focus = 0;
+	done = 0;
+	save = nil;
+	bw = 2*stringwidth(font, "Cancel");
+	bh = 1.5*font->height;
+	mw = stringwidth(font, ask);
+	w = Border+Padding+3*mw+Padding+Border;
+	ew = w - 2*(Border+Padding);
+	eh = Padding+font->height;
+	h = Border+Padding+2*font->height+Padding+eh+Padding+bh+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, ask);
+		p.y += Padding+1.5*font->height;
+		dy = Border+Padding+1.5*font->height+Padding;
+		er = rectaddpt(Rect(0, 0, ew, eh), addpt(o, Pt(Border+Padding, dy)));
+		entry(b, er, buf, focus == 0);
+		dy += eh+0.5*font->height+Padding;
+		br = rectaddpt(Rect(0, 0, bw, bh), addpt(o, Pt(Border+Padding, dy)));
+		button(b, br, "Ok", focus == 1);
+		brn = rectaddpt(br, Pt(bw+Padding, 0));
+		button(b, brn, "Cancel", focus == 2);
+		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 == '\t'){
+				focus = (focus + 1) % 3;
+			}else if(focus != 0 && (k == 'o' || k == 'O')){
+				done = 1;
+				rc = len;
+			}else if(k == '\n'){
+				done = 1;
+				if(focus == 0 || focus == 1)
+					rc = len;
+				else
+					rc = -1;
+			}else if(focus != 0 && (k == 'c' || k == 'C')){
+				done = 1;
+				rc = -1;
+			}else if(k == Kesc){
+				done = 1;
+				rc = -1;
+			}else{
+				if(isprint(k)){
+					if(len >= nbuf){
+						done = 1;
+						rc = -1;
+					}else
+						buf[len++] = k;
+				}else if(k == Knack){
+					len = 0;
+				}else if(k == Kbs){
+					if(len > 0)
+						buf[--len] = '\0';
+				}
+				buf[len] = 0;
+			}
+			break;
+		case 0:
+			if(m.buttons&4){
+				if(ptinrect(m.xy, br)){
+					done = 1;
+					rc = len;
+				}else if(ptinrect(m.xy, brn)){
+					done = 1;
+					rc = -1;
+				}
+			}
+			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/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
 #include "a.h"
 
 Image		*cols[Ncols];
+Image		*tick;
 Mousectl	*mc;
 Keyboardctl	*kc;
 int			mode;
@@ -23,6 +24,20 @@
 }
 
 void
+tickinit(void)
+{
+	enum { Tickw = 3 };
+
+	tick = allocimage(display, Rect(0, 0, Tickw, font->height), screen->chan, 0, DWhite);
+	if(tick == nil)
+		sysfatal("allocimage: %r");
+	draw(tick, tick->r, cols[Cbg], nil, ZP);
+	draw(tick, Rect(Tickw/2, 0, Tickw/2+1, font->height), cols[Cfg], nil, ZP);
+	draw(tick, Rect(0, 0, Tickw, Tickw), cols[Cfg], nil, ZP);
+	draw(tick, Rect(0, font->height-Tickw, Tickw, font->height), cols[Cfg], nil, ZP);
+}
+
+void
 redraw(void)
 {
 	draw(screen, screen->r, cols[Cbg], nil, ZP);
@@ -144,6 +159,7 @@
 	text = mktext();
 	abar = mkactionbar();
 	colsinit();
+	tickinit();
 	resize();
 	setmode(Mdir);
 	alts[Emouse].c = mc->c;
--- a/mkfile
+++ b/mkfile
@@ -14,6 +14,7 @@
 	viewercmd.$O	\
 	text.$O			\
 	message.$O		\
+	input.$O		\
 	glob.$O			\
 	fops.$O			\
 	utils.$O