ref: 13590f759547f4ef544b251f2966b4ed2d82038c
dir: /efilter.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <draw.h> #include <memdraw.h> #include <event.h> #include <plumb.h> #include "blie.h" #include "db.h" #define DEBUG static int consfd = -1; static void clog(char *fmt, ...) { #ifdef DEBUG va_list args; if (consfd < 0) { consfd = open("#c/cons", OWRITE|OCEXEC); if (consfd < 0) return; } fprint(consfd, "blie-efilter: "); va_start(args, fmt); vfprint(consfd, fmt, args); va_end(args); fprint(consfd, "\n"); #endif } /* TODO: add params as entries, use putenv(2) */ /* stored in database */ typedef struct Data Data; struct Data { char *script; ulong mtime; Db *db; }; static int lwinoffset = 10; static Point toolcell; static void finitialize() { if (headless) return; toolcell = Pt(15, vdata.fontheight); } static void finit(Layer *l) { Data *d; char *s; if (l->data) return; clog("init layer: %s", l->name); l->data = mallocz(sizeof(Data), 1); d = l->data; d->script = smprint("l/%s/script", l->name); s = smprint("l/%s/params", l->name); d->db = opendb(s); free(s); } static Rectangle ftoolrect(Layer*) { return Rect(0, 0, 1, 1); } static void fdrawtools(Layer*, Image*) { } static int fsavedata(Layer *l) { Data *d; int r = 0; d = (Data*)l->data; r |= writedb(d->db, nil); return r; } static Redrawwin ftoolinput(Layer*, int, Event) { return Rnil; } static void setenvs(Data *d) { Dpack *dv; Dtuple *dt; dv = getdpack(d->db, "params"); for (dt = dv->tuple; dt; dt = dt->next) { clog("$%s = %s", dt->key, dt->value); putenv(dt->key, dt->value); } } static Memimage* readfiltered(Memimage *i, Data *d) { Memimage *result; int in[2]; int out[2]; int errfd; Dir *dir; if (pipe(in) < 0) sysfatal("%r"); if (pipe(out) < 0) sysfatal("%r"); dir = dirfstat(in[0]); if (!dir) sysfatal("%r"); dir->length = i->width * Dy(i->r) * sizeof(ulong) + 12*5; if (!dirfwstat(in[0], dir)) sysfatal("%r"); free(dir); switch (rfork(RFFDG|RFREND|RFPROC|RFENVG|RFNAMEG)) { case -1: sysfatal("fork: %r"); case 0: /* child process */ setenvs(d); errfd = open("#c/cons", OWRITE|OCEXEC); if (errfd >= 0) { dup(errfd, 2); } dup(in[1], 0); dup(out[1], 1); close(in[0]); close(out[0]); execl(d->script, d->script, nil); sysfatal("%r"); default: close(in[1]); close(out[1]); } writememimage(in[0], i); result = readmemimage(out[0]); if (!result) sysfatal("%r"); close(in[0]); close(out[0]); return result; } static Memimage* fcomposite(Layer *l, Memimage *img) { Data *d; d = (Data*)l->data; if (!img || !d) return nil; return readfiltered(img, d); } static void drcells(Image *i, Point p, char *s, int hl) { Rectangle r; r.min = p; r.max = addpt(p, toolcell); draw(i, r, display->white, nil, ZP); border(i, r, 1, vdata.gray, ZP); if (hl) { r = insetrect(r, 2); draw(i, r, vdata.gray, nil, ZP); } string(i, addpt(p, Pt(2, 2)), display->black, ZP, font, s); } static void fdrawlwin(Layer*, Image *i, Rectangle r) { Point p; p = r.min; p.x += lwinoffset; drcells(i, p, "E", 0); p.x += toolcell.x; drcells(i, p, "P", 0); p.x += toolcell.x; drcells(i, p, "A", 0); p.x += toolcell.x; drcells(i, p, "D", 0); } static int editparams(Data *d, Mouse m) { Ask *asks; Dpack *dv; Dtuple *dt; int num, i, n; if (!d || !d->db) return 0; dv = getdpack(d->db, "params"); if (!dv) return 0; num = 0; for (dt = dv->tuple; dt; dt = dt->next) num++; asks = mallocz((num+1) * sizeof(Ask), 1); i = 0; for (dt = dv->tuple; dt; dt = dt->next) { n = strlen(dt->value); if (n < 511) n = 511; n++; asks[i].label = dt->key; asks[i].value = mallocz(n, 1); snprint(asks[i].value, n, "%s", dt->value); asks[i].nval = n; i++; } m.xy = vstate.mousepos; if (!ask(asks, m)) { for (i = 0; i < num; i++) free(asks[i].value); free(asks); return 0; } for (i = 0; i < num; i++) { setdval(dv, asks[i].label, asks[i].value); free(asks[i].value); } free(asks); return 1; } static int editscr(Data *d, Mouse m) { int fd; char wd[256]; if (m.buttons & 1) /* left click: dirty */ return 1; if (! (m.buttons & 4)) /* right click: edit */ return 0; if (!d || !d->script) return 0; fd = plumbopen("send", OWRITE); if (fd < 0) return 0; getwd(wd, sizeof wd); plumbsendtext(fd, "blie", "edit", wd, d->script); close(fd); return 1; } static int addparam(Data *d, Mouse m, int del) { Dpack *dv; char buf[512]; char *s; if (!d || !d->db) return 0; dv = getdpack(d->db, "params"); if (!dv) { clog("no params found"); return 0; } m.xy = vstate.mousepos; buf[0] = 0; if (!eenter("name", buf, sizeof buf, &m)) return 0; if (del) { deldtuple(dv, buf); return 1; } s = strdup(buf); buf[0] = 0; if (!eenter("value", buf, sizeof buf, &m)) { free(s); return 0; } setdval(dv, s, buf); free(s); return 1; } static Redrawwin flwininput(Layer *l, int, Event ev) { Data *d; d = (Data*)l->data; ev.mouse.xy.x -= lwinoffset; if (ev.mouse.xy.y / toolcell.y != 0) return Rnil; switch (ev.mouse.xy.x / toolcell.x) { case 0: /* edit script (plumb) */ if (editscr(d, ev.mouse)) goto Out; break; case 1: /* edit params */ if (editparams(d, ev.mouse)) goto Out; break; case 2: /* add param */ if (addparam(d, ev.mouse, 0)) goto Out; break; case 3: /* delete param */ if (addparam(d, ev.mouse, 1)) goto Out; break; } return Rnil; Out: dirtylayer(l); setdrawingdirty(Dcontent); return Rdrawing; } Editor efilter = { .name = "filter", .init = finitialize, .initlayer = finit, .raw = nil, .mask = nil, .composite = fcomposite, .overlay = nil, .toolrect = ftoolrect, .drawtools = fdrawtools, .drawlwin = fdrawlwin, .savedata = fsavedata, .savetools = nil, .drawinput = nil, .toolinput = ftoolinput, .lwininput = flwininput, };