shithub: blie

Download patch

ref: 13590f759547f4ef544b251f2966b4ed2d82038c
parent: 7455a7027cde79e0304bade55b6616983e2e8e1a
author: sirjofri <[email protected]>
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