ref: 13590f759547f4ef544b251f2966b4ed2d82038c
parent: 7455a7027cde79e0304bade55b6616983e2e8e1a
author: sirjofri <sirjofri@sirjofri.de>
date: Fri Sep 6 14:10:57 EDT 2024
adds efilter which I forgot, adds buttons for efilter
--- a/db.c
+++ b/db.c
@@ -344,6 +344,8 @@
ptp = nil; /* shut up compiler */
for (tp = dv->tuple; tp; tp = tp->next) {
+ if (tp->key == key)
+ return tp;
if (strcmp(tp->key, key) == 0)
return tp;
ptp = tp;
@@ -380,8 +382,39 @@
void
deldtuple(Dpack *dv, char *key)
{
- USED(dv, key);
- sysfatal("deldtuple not implemented yet!");
+ Dtuple *tp, *ntp;
+
+ if (!(dv && dv->tuple))
+ return;
+
+ /* delete first tuple */
+ if (key == dv->tuple->key
+ || strcmp(key, dv->tuple->key) == 0) {
+ tp = dv->tuple;
+ dv->tuple = tp->next;
+ free(tp->key);
+ if (tp->value)
+ free(tp->value);
+ free(tp);
+ return;
+ }
+
+ for (tp = dv->tuple; tp->next; tp = tp->next) {
+ if (tp->next->key == key
+ || strcmp(tp->next->key, key) == 0)
+ break; /* tp is parent of found tuple */
+ continue;
+ }
+
+ if (!tp->next)
+ return;
+
+ ntp = tp->next;
+ tp->next = tp->next->next;
+ free(ntp->key);
+ if (ntp->value)
+ free(ntp->value);
+ free(ntp);
}
void
--- /dev/null
+++ b/efilter.c
@@ -1,0 +1,371 @@
+#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,
+};
--- a/p9image.c
+++ b/p9image.c
@@ -830,7 +830,6 @@
drcells(i, p, "S", tstate.mode == Img);
p.x += toolcell.x;
drcells(i, p, "M", tstate.mode == Mask);
- p.x += toolcell.x;
}
static Redrawwin
@@ -838,21 +837,22 @@
{
ev.mouse.xy.x -= lwinoffset;
- if (ev.mouse.xy.y / toolcell.y == 0) {
- switch (ev.mouse.xy.x / toolcell.x) {
- case 0:
- tstate.mode = Composite;
- tstate.drawtarget = DTimg;
- goto Out;
- case 1:
- tstate.mode = Img;
- tstate.drawtarget = DTimg;
- goto Out;
- case 2:
- tstate.mode = Mask;
- tstate.drawtarget = DTmask;
- goto Out;
- }
+ if (ev.mouse.xy.y / toolcell.y != 0)
+ return Rnil;
+
+ switch (ev.mouse.xy.x / toolcell.x) {
+ case 0:
+ tstate.mode = Composite;
+ tstate.drawtarget = DTimg;
+ goto Out;
+ case 1:
+ tstate.mode = Img;
+ tstate.drawtarget = DTimg;
+ goto Out;
+ case 2:
+ tstate.mode = Mask;
+ tstate.drawtarget = DTmask;
+ goto Out;
}
return Rnil;
Out:
--- a/test/img/l/filter/params
+++ b/test/img/l/filter/params
@@ -1,1 +1,1 @@
-params width=20
+params width=5 red=100
--- a/test/img/l/filter/script
+++ b/test/img/l/filter/script
@@ -1,3 +1,3 @@
#!/bin/rc
-crop -i $width | crop -i -$width -b 255 0 255
+crop -i $width | crop -i -$width -b $red 200 255