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
--
⑨