shithub: dmenu

Download patch

ref: 342d92a22a97b02235abe83f4ec420c8aa6622ef
parent: fc299fdf45602f63cf16c939706abbfc276e69db
author: glenda <glenda@9front.local>
date: Sun Sep 5 09:23:30 EDT 2021

implement rendering the buffer

--- a/linesel.c
+++ b/linesel.c
@@ -2,67 +2,17 @@
 #include <libc.h>
 #include <bio.h>
 #include <draw.h>
-#include <thread.h>
+#include <event.h>
 #include <keyboard.h>
-#include <mouse.h>
 
-int bflag;
+#define Ctl(c) ((c) - 64)
+
 Image *fgcolor, *bgcolor;
-Font *font;
 char **lines, **matches, *buffer,  *selected;
 usize nlines, nmatches;
-Rune kbdin[512];
-Keyboardctl *keyboard;
-Mousectl *mouse;
+Rune kbinput[512];
 
-enum
-{
-	Ckeyboard,
-	Cmouse,
-	Cresize,
-	Cnum
-};
-
 static void
-redraw(void)
-{
-	draw(screen, screen->r, bgcolor, nil, ZP);
-	string(screen,
-	  Pt(10, 10), fgcolor, ZP, font, "test");
-	flushimage(display, 1);
-}
-
-static void
-resetmatches(void)
-{
-	memmove(matches, lines, nlines * sizeof *lines);
-	nmatches = nlines;
-}
-
-static void
-initgraphics(Alt *a)
-{
-	if(initdraw(nil, nil, "linesel") == -1)
-		sysfatal("initdraw: %r");
-	if(bflag){
-		fgcolor = display->white;
-		bgcolor = display->black;
-	}else{
-		fgcolor = display->black;
-		bgcolor = display->white;
-	}
-	font = display->defaultfont;
-
-	if((keyboard = initkeyboard(nil)) == nil)
-		sysfatal("initkeyboard: %r");
-	if((mouse = initmouse(nil, screen)) == nil)
-		sysfatal("initmouse: %r");	
-
-	a[Ckeyboard].c = keyboard->c;
-	a[Cmouse].c = mouse->c;
-}
-
-static void
 readbuffer(void)
 {
 	Biobuf *bp;
@@ -83,49 +33,100 @@
 		sysfatal("malloc: %r");
 }
 
+#define PROMPT "  > "
+
 static void
-linesel(void)
+redraw(Image *screen)
 {
-	Rune r;
-	Mouse m;
-	Alt a[] = {
-		[Ckeyboard] = {nil, &r, CHANRCV},
-		[Cmouse] = {nil, &m, CHANRCV},
-		[Cnum] = {nil, nil, CHANEND},
-	};
+	short fh = font->height;
+	Point pt = screen->r.min;
+	usize i;
+	char buf[512];
 
-	initgraphics(a);
-	redraw();
+	draw(screen, screen->r, bgcolor, nil, ZP);
 
-	for(;;){
-		switch(alt(a)){
-		case -1:
-			sysfatal("watching channels: %r\n");
+	pt = addpt(pt, Pt(0, fh));
+	snprint(buf, sizeof buf, PROMPT"%S▏", kbinput);
+	string(screen, pt, fgcolor, ZP, font, buf);	
+	pt = addpt(pt, Pt(stringwidth(font, PROMPT), fh));
 
-		case Ckeyboard:
-			switch(r){
-			case '\n':
-				return;
-			}
+	for(i = 0; i < nmatches; i++){
+		if (pt.y > screen->r.max.y)
 			break;
-
-		case Cmouse:
-			break;
-		}
+		string(screen, pt, fgcolor, ZP, font, matches[i]);
+		pt = addpt(pt, Pt(0, fh));
 	}
+}
 
+static void
+resetmatches(void)
+{
+	memmove(matches, lines, nlines * sizeof *lines);
+	nmatches = nlines;
 }
 
 static void
+kbadd(Rune r)
+{
+	usize len = runestrlen(kbinput);
+
+	if (len == sizeof kbinput / sizeof *kbinput)
+		return;
+	kbinput[len++] = r;
+	kbinput[len] = L'\0';
+}
+
+static void
+kbbackspace(void)
+{
+	usize len = runestrlen(kbinput);
+
+	if (len == 0)
+		return;
+	kbinput[len - 1] = L'\0';
+}
+
+static void
+kbdelword(void)
+{
+	usize len = runestrlen(kbinput);
+
+	if(len == 0)
+		return;
+	while(len > 0 && isspacerune(kbinput[len-1]))
+		len--;
+	while(len > 0 && !isspacerune(kbinput[len-1]))
+		len--;
+	kbinput[len] = L'\0';
+}
+
+static void
+kbclear(void)
+{
+	kbinput[0] = L'\0';
+}
+
+void
+eresized(int new)
+{
+	if(new && getwindow(display, Refnone) < 0)
+		sysfatal("resize failed: %r");
+	redraw(screen);
+}
+
+static void
 usage(void)
 {
 	print("usage: %s [-b] <choices\n", argv0);
-	threadexitsall("usage");
+	exits("usage");
 }
 
 void
-threadmain(int argc, char **argv)
+main(int argc, char **argv)
 {
+	Event e;
+	int bflag = 0;
+
 	ARGBEGIN{
 	case 'b':
 		bflag = 1;
@@ -137,7 +138,51 @@
 	readbuffer();
 	resetmatches();
 	selected = matches[0];
-	linesel();
+
+	if(initdraw(nil, nil, "linesel") < 0)
+		sysfatal("initdraw: %r");
+	if(bflag){
+		fgcolor = display->white;
+		bgcolor = display->black;
+	}else{
+		fgcolor = display->black;
+		bgcolor = display->white;
+	}
+	einit(Emouse|Ekeyboard);
+	redraw(screen);
+
+	for(;;){
+		switch(event(&e)){
+		case -1:
+			sysfatal("watching channels: %r\n");
+
+		case Ekeyboard:
+			switch(e.kbdc){
+			case Kdel:
+				exits("interrupted with Del");
+			case '\n':
+				goto End;
+			case Kbs:
+				kbbackspace();
+				break;
+			case Ctl('W'):
+				kbdelword();
+				break;
+			case Ctl('U'):
+				kbclear();
+				break;
+			default:
+				kbadd(e.kbdc);
+				break;
+			}
+			redraw(screen);
+			break;
+
+		case Emouse:
+			break;
+		}
+	}
+End:
 	print("%s\n", selected);
-	threadexitsall(nil);
+	exits(nil);
 }