shithub: plumbto

Download patch

ref: b8ce27374966893fe7ee3b587051161421ff0173
parent: 0edad9c09a294ca1151c692a106015e218a1e096
author: sirjofri <sirjofri@sirjofri.de>
date: Thu Jan 20 14:46:49 EST 2022

adds thanks and lots of adjustments (thanks phil9)

--- a/plumbto.c
+++ b/plumbto.c
@@ -7,151 +7,247 @@
 #include <keyboard.h>
 #include <control.h>
 
-Controlset *cs;
-int ctldeletequits = 1;
+enum
+{
+	Maxchans = 16,
+	Padding = 4,
+};
 
-Control *items[] = {
-	nil, /* pmhead */
-	nil,
-	nil, nil, nil, nil, nil,
-	nil, nil, nil,
+enum
+{
+	BACK,
+	TEXT,
+	SEL,
+	NCOLS,
 };
-int itemsize = 1;
-int maxitems = 10;
 
+int wfd;
+Mousectl *mc;
+Keyboardctl *kc;
+Image *cols[NCOLS];
+Point headerp;
+Rectangle listr;
+int sel = -1;
+int plumbfd;
+Channel *plumbc;
+Plumbmsg *pm;
+char *chans[Maxchans];
+usize nchans;
+
 void
-resizecontrolset(Controlset*)
+plumbto(char *chan)
 {
-	int i;
-	Rectangle r;
-	if (getwindow(display, Refnone) < 0)
-		sysfatal("resize failed: %r");
-	r = insetrect(screen->r, 10);
-	for (i = 0; items[i]; i++){
-		r = insetrect(screen->r, 10);
-		r.min.y = r.min.y +  i   *(1+font->height+1);
-		r.max.y = r.min.y +       (1+font->height+1);
-		chanprint(cs->ctl, "%s rect %R\n%s show", items[i]->name, r, items[i]->name);
-	}
+	pm->attr = plumbdelattr(pm->attr, "channels");
+	pm->dst = strdup(chan);
+	plumbsend(plumbfd, pm);
+	plumbfree(pm);
+	pm = nil;
+	nchans = 0;
 }
 
-int pfd, psfd;
-Plumbmsg *pm;
-char *channels;
+void
+drawwait(void)
+{
+	string(screen, headerp, cols[SEL], ZP, font, "waiting for plumb message...");
+}
 
 void
-plumblisten(void *arg)
+drawline(int index, int selected)
 {
-	while ((pm = plumbrecv(pfd)) != nil){
-		channels = plumblookup(pm->attr, "channels");
-		if (channels != nil && strcmp(channels, "") != 0)
-			send((Channel*)arg, 0);
-	}
+	Point p, q;
+	Image *c;
+
+	p = Pt(listr.min.x, listr.min.y + index*font->height);
+	q = addpt(p, Pt(Dx(listr), font->height));
+	c = selected ? cols[SEL] : cols[BACK];
+	draw(screen, Rpt(p, q), c, nil, ZP);
+	p = string(screen, p, cols[TEXT], ZP, font, "» ");
+	string(screen, p, cols[TEXT], ZP, font, chans[index]);
 }
 
 void
-cleanup(void)
+redraw(void)
 {
+	char *f, buf[1024] = {0};
 	int i;
-	for (i = 1; items[i]; i++){
-		closecontrol(items[i]);
-		items[i] = nil;
+
+	lockdisplay(display);
+	draw(screen, screen->r, cols[BACK], nil, ZP);
+	if(pm == nil){
+		drawwait();
+		flushimage(display, 1);
+		unlockdisplay(display);
+		return;
 	}
-	resizecontrolset(cs);
+	f = plumblookup(pm->attr, "filename");
+	if(f != nil)
+		snprint(buf, sizeof buf, "Plumb '%s' to:", f);
+	else
+		snprint(buf, sizeof buf, "Plumb data to:");
+	string(screen, headerp, cols[TEXT], ZP, font, buf);
+	for(i = 0; i < nchans; i++){
+		drawline(i, 0);
+	}
+	flushimage(display, 1);
+	unlockdisplay(display);
 }
 
 void
-handleplumb(Channel *c)
+evtresize(void)
 {
-	char *args[10]; // maxitems-1+1
-	int n, i;
+	headerp = addpt(screen->r.min, Pt(Padding, Padding));
+	listr = Rect(screen->r.min.x + Padding,
+				 screen->r.min.y + Padding + font->height + Padding,
+				 screen->r.max.x - Padding,
+				 screen->r.max.y - Padding);
+	redraw();
+}
 
-	cleanup();
+void
+evtmouse(Mouse *m)
+{
+	int n;
 
-	n = getfields(channels, args, 10, 1, ",");
-	for (i = 0; i < n; i++){
-		items[i+1] = createtextbutton(cs, args[i]);
-		activate(items[i+1]);
-		chanprint(cs->ctl, "%q text %q", args[i], args[i]);
-		controlwire(items[i+1], "event", c);
-		itemsize++;
+	if(!ptinrect(m->xy, listr)){
+		if(sel != -1){
+			sel = -1;
+			redraw();
+		}
+		return;
 	}
-	resizecontrolset(cs);
+	n = (m->xy.y - listr.min.y) / font->height;
+	if(m->buttons == 0){
+		if(n >= nchans){
+			sel = -1;
+			redraw();
+		}else if(n != sel){
+			if(sel != -1)
+				drawline(sel, 0);
+			drawline(n, 1);
+			flushimage(display, 1);
+			sel = n;
+		}
+	}else if(m->buttons == 1){
+		if(sel != -1){
+			sel = -1;
+			plumbto(chans[n]);
+			redraw();
+			fprint(wfd, "hide\n");
+		}
+	}
 }
 
 void
-handleevent(char *c)
+evtkeyboard(Rune k)
 {
-	char *args[10];
-	int n;
-	
-	gettokens(c, args, 10, " \t:");
-	
-	if (atoi(args[2]) == 1){
-		pm->attr = plumbdelattr(pm->attr, "channels");
-		pm->dst = args[0];
-		n = plumbsend(psfd, pm);
-		if (!n)
-			fprint(2, "plumbsend failed: %r\n");
+	if(k == Kdel)
+		threadexitsall(nil);
+}
+
+void
+evtplumb(Plumbmsg *p)
+{
+	fprint(wfd, "unhide\n");
+	pm = p;
+	redraw();
+}
+
+void
+initcols(void)
+{
+	cols[BACK] = display->white;
+	cols[TEXT] = display->black;
+	cols[SEL]  = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xccccccff);
+}
+
+void
+plumbproc(void *v)
+{
+	Channel *c;
+	Plumbmsg *p;
+	int fd;
+	char *s;
+
+	c = v;
+	fd = plumbopen("chanselect", OREAD);
+	if(fd < 0)
+		sysfatal("plumbopen: %r");
+	for(;;){
+		p = plumbrecv(fd);
+		if(p == nil)
+			break;
+		s = plumblookup(p->attr, "channels");
+		if(s == nil || s[0] == 0){
+			plumbfree(p);
+			continue;
+		}
+		nchans = getfields(s, chans, nelem(chans), 0, ",");
+		if(nchans != 0)
+			sendp(c, p);
+		else
+			plumbfree(p);
 	}
-	cleanup();
+	threadexits(nil);
 }
 
 void
-threadmain(int argc, char **argv)
+threadmain(int argc, char *argv[])
 {
-	USED(argc, argv);
-	int i;
-	int wctlfd;
-	char *chanval;
+	enum { Emouse, Eresize, Ekeyboard, Eplumb, };
+	Mouse m;
+	Rune k;
+	Plumbmsg *p;
 	Alt a[] = {
-		{nil, &i, CHANRCV},
-		{nil, &chanval, CHANRCV},
-		{nil, nil, CHANEND},
+		{ nil, &m,  CHANRCV },
+		{ nil, nil, CHANRCV },
+		{ nil, &k,  CHANRCV },
+		{ nil, &p, CHANRCV },
+		{ nil, nil, CHANEND },
 	};
-	
-	pfd = plumbopen("chanselect", OREAD);
-	if (!pfd)
-		sysfatal("cannot open plumb channel: %r");
-	psfd = plumbopen("send", OWRITE);
-	if (!psfd)
-		sysfatal("cannot open plumb send: %r");
-	
-	wctlfd = open("/dev/wctl", OWRITE);
-	if (wctlfd)
-		fprint(wctlfd, "hide\n");
-	
-	initdraw(0, 0, "plumbto!");
-	initcontrols();
-	
-	a[0].c = chancreate(sizeof(int), 0);
-	proccreate(plumblisten, a[0].c, 2048);
-	
-	cs = newcontrolset(screen, nil, nil, nil);
-	cs->clicktotype = 1;
-	
-	items[0] = createlabel(cs, "pmhead");
-	chanprint(cs->ctl, "pmhead value %q", "no message");
-	
-	a[1].c = chancreate(sizeof(char*), 0);
-	
-	resizecontrolset(cs);
-	for (;;){
-		switch (alt(a)){
-		case 0: /* plumb event */
-			chanprint(cs->ctl, "pmhead value %q", pm->wdir);
-			handleplumb(a[1].c);
-			if (wctlfd)
-				fprint(wctlfd, "unhide\n");
+
+	ARGBEGIN{
+	}ARGEND;
+
+	nchans = 0;
+	if(initdraw(nil, nil, argv0) < 0)
+		sysfatal("initdisplay: %r");
+	unlockdisplay(display);
+	if((wfd = open("/dev/wctl", OWRITE)) < 0)
+		sysfatal("open: %r");
+	fprint(wfd, "hide\n");
+	if((mc = initmouse(nil, screen)) == nil)
+		sysfatal("initmouse: %r");
+	if((kc = initkeyboard(nil)) == nil)
+		sysfatal("initkeyboard: %r");
+	plumbfd = plumbopen("send", OWRITE);
+	if(plumbfd < 0)
+		sysfatal("plumbopen: %r");
+	plumbc = chancreate(sizeof(Plumbmsg*), 0);
+	if(plumbc == nil)
+		sysfatal("initchan: %r");
+	proccreate(plumbproc, plumbc, 8192);
+	a[Emouse].c = mc->c;
+	a[Eresize].c = mc->resizec;
+	a[Ekeyboard].c = kc->c;
+	a[Eplumb].c = plumbc;
+	initcols();
+	evtresize();
+	for(;;){
+		switch(alt(a)){
+		case Emouse:
+			evtmouse(&m);
 			break;
-		case 1: /* control event */
-			handleevent(chanval);
-		//	plumbfree(pm);
-			if (wctlfd)
-				fprint(wctlfd, "hide\n");
+		case Eresize:
+			if(getwindow(display, Refnone) < 0)
+				sysfatal("getwindow: %r");
+			evtresize();
 			break;
-		default:
-			sysfatal("can't happen");
+		case Ekeyboard:
+			evtkeyboard(k);
+			break;
+		case Eplumb:
+			evtplumb(p);
+			break;
 		}
 	}
 }
--- /dev/null
+++ b/thanks
@@ -1,0 +1,3 @@
+Special thanks to:
+
+- phil9