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