shithub: orca

Download patch

ref: b390d010c5135d7bf86bb3a0657f8ed4bff2bfbc
parent: b70bc705d1a4ecfe686d01f11a2bdb60234f8ca5
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Aug 1 15:35:02 EDT 2020

plan9: update theming logic

--- a/mkfile
+++ b/mkfile
@@ -17,6 +17,7 @@
 	gbuffer.$O\
 	plan9.$O\
 	sim.$O\
+	theme.$O\
 	vmio.$O\
 
 default:V:	all
--- a/plan9.c
+++ b/plan9.c
@@ -10,6 +10,7 @@
 #include <plumb.h>
 #include <cursor.h>
 #include <tos.h>
+#include "theme.h"
 
 #define MIN(x,y) ((x)<=(y)?(x):(y))
 #define MAX(x,y) ((x)>=(y)?(x):(y))
@@ -45,17 +46,6 @@
 	Menu3exit,
 	Nummenu3,
 
-	Dback = 0,
-	Dfhigh,
-	Dfmed,
-	Dflow,
-	Dfinv,
-	Dbhigh,
-	Dbmed,
-	Dblow,
-	Dbinv,
-	Numcolors,
-
 	/* this might become a bad idea in the future */
 	Mark_flag_group_highlight = 1<<6,
 	Mark_flag_selected = 1<<7,
@@ -143,23 +133,6 @@
 	},
 };
 
-static struct {
-	char *id;
-	u32int color;
-}theme[Numcolors] = {
-	[Dback]  = {"background", 0x000000},
-	[Dfhigh] = {"f_high",     0xffffff},
-	[Dfmed]  = {"f_med",      0x777777},
-	[Dflow]  = {"f_low",      0x444444},
-	[Dfinv]  = {"f_inv",      0x000000},
-	[Dbhigh] = {"b_high",     0xdddddd},
-	[Dbmed]  = {"b_med",      0x72dec2},
-	[Dblow]  = {"b_low",      0x222222},
-	[Dbinv]  = {"b_inv",      0xffb545},
-};
-
-static Image *color[Numcolors];
-
 static char *modes[Nummodes] = {
 	[Minsert] = "insert",
 	[Mappend] = "append",
@@ -596,10 +569,10 @@
 	if (complete) {
 		r = screen->r;
 		r.max.y = r.min.y + txtoff.y;
-		draw(screen, r, color[Dback], nil, ZP);
+		draw(screen, r, colors[Dback].im, nil, ZP);
 		r = screen->r;
 		r.max.x = r.min.x + txtoff.x;
-		draw(screen, r, color[Dback], nil, ZP);
+		draw(screen, r, colors[Dback].im, nil, ZP);
 	}
 
 	off = field.width*cur.y + cur.x;
@@ -636,7 +609,7 @@
 
 			if (!grouphl && !complete && c == fscr.buffer[off] && attr == mscr.buffer[off]) {
 				if (i > 0) {
-					p = runestringnbg(screen, p, color[oldfg], ZP, font, linebuf, i, color[oldbg], ZP);
+					p = runestringnbg(screen, p, colors[oldfg].im, ZP, font, linebuf, i, colors[oldbg].im, ZP);
 					i = 0;
 				}
 				p.x += glyphsz.x;
@@ -687,32 +660,32 @@
 			}
 
 			if (bg != oldbg || fg != oldfg) {
-				p = runestringnbg(screen, p, color[oldfg], ZP, font, linebuf, i, color[oldbg], ZP);
+				p = runestringnbg(screen, p, colors[oldfg].im, ZP, font, linebuf, i, colors[oldbg].im, ZP);
 				i = 0;
 			}
 			linebuf[i++] = c;
 		}
-		runestringnbg(screen, p, color[fg], ZP, font, linebuf, i, color[bg], ZP);
+		runestringnbg(screen, p, colors[fg].im, ZP, font, linebuf, i, colors[bg].im, ZP);
 		p.y += glyphsz.y;
 	}
 
 	r = screen->r;
 	r.min.x += txtoff.x + max.x*glyphsz.x;
-	draw(screen, r, color[Dback], nil, ZP);
+	draw(screen, r, colors[Dback].im, nil, ZP);
 
 	r = screen->r;
 	r.min.y += txtoff.y + max.y*glyphsz.y;
-	draw(screen, r, color[Dback], nil, ZP);
+	draw(screen, r, colors[Dback].im, nil, ZP);
 
 	p = top;
 	p.y += glyphsz.y*(max.y-1)/2;
 	if (scroll.x > 0) {
 		p.x = top.x - txtoff.x;
-		string(screen, p, color[Dfmed], ZP, font, "←");
+		string(screen, p, colors[Dfmed].im, ZP, font, "←");
 	}
 	if (max.x+scroll.x < field.width) {
 		p.x = top.x + max.x*glyphsz.x + txtoff.x - glyphsz.x;
-		string(screen, p, color[Dfmed], ZP, font, "→");
+		string(screen, p, colors[Dfmed].im, ZP, font, "→");
 	}
 
 	p = top;
@@ -719,11 +692,11 @@
 	p.x += glyphsz.x*(max.x-1)/2;
 	if (scroll.y > 0) {
 		p.y = screen->r.min.y;
-		string(screen, p, color[Dfmed], ZP, font, "↑");
+		string(screen, p, colors[Dfmed].im, ZP, font, "↑");
 	}
 	if (max.y+scroll.y < field.height) {
 		p.y = top.y + max.y*glyphsz.y;
-		string(screen, p, color[Dfmed], ZP, font, "↓");
+		string(screen, p, colors[Dfmed].im, ZP, font, "↓");
 	}
 
 	i = 0;
@@ -741,7 +714,7 @@
 	i += runesprint(linebuf+i, "%-9s", s);
 	sprint(s, "%ldms", labs(framedev));
 	i += runesprint(linebuf+i, "%-8s", s);
-	runestringn(screen, bot, color[Dfhigh], ZP, font, linebuf, i);
+	runestringn(screen, bot, colors[Dfhigh].im, ZP, font, linebuf, i);
 	bot.y += glyphsz.y;
 
 	i = 0;
@@ -752,12 +725,18 @@
 	i += runesprint(linebuf+i, "%-9s", s);
 	i += runesprint(linebuf+i, "%-9s", modes[altdown ? Mslide : mode]);
 	i += runesprint(linebuf+i, "%s", filename[0] ? filename : "unnamed");
-	runestringn(screen, bot, color[Dfhigh], ZP, font, linebuf, i);
+	runestringn(screen, bot, colors[Dfhigh].im, ZP, font, linebuf, i);
 
 	flushimage(display, 1);
 	unlockdisplay(display);
 }
 
+void
+themechanged(void)
+{
+	redraw(1);
+}
+
 static void
 command(char *s, void (*snapshot)(void))
 {
@@ -815,7 +794,7 @@
 	} else if (s[0] == 'c' && s[1] == 'o') { /* color ffffff 111111 232323 ... */
 		if (argc < 2) {
 			for (i = 0; i < Numcolors; i++)
-				print("%06x ", theme[i].color);
+				print("%06x ", colors[i].rgb);
 			print("\n");
 			fflush(stdout);
 		} else {
@@ -825,9 +804,9 @@
 					continue;
 				if ((im = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, c<<8 | 0xff)) == nil)
 					continue;
-				freeimage(color[i-1]);
-				theme[i-1].color = c;
-				color[i-1] = im;
+				freeimage(colors[i-1].im);
+				colors[i-1].rgb = c;
+				colors[i-1].im = im;
 			}
 			unlockdisplay(display);
 			redraw(1);
@@ -1169,88 +1148,6 @@
 }
 
 static void
-runpicker(void *x)
-{
-	int *p, wfd;
-	char *wsys;
-	char tmp[64];
-
-	if ((wsys = getenv("wsys")) == nil) {
-		fprint(2, "wsys not set\n");
-		goto err;
-	}
-	if ((wfd = open(wsys, ORDWR)) < 0) {
-		fprint(2, "can't open wsys: %r\n");
-		goto err;
-	}
-
-	snprint(tmp, sizeof(tmp), "new -pid %d -dx %d -dy %d", getpid(), 384, 320);
-
-	if (mount(wfd, -1, "/mnt/wsys", MREPL, tmp) < 0) {
-		fprint(2, "couldn't mount wsys: %r\n");
-		goto err;
-	}
-	if (bind("/mnt/wsys", "/dev", MBEFORE) < 0) {
-		fprint(2, "couldn't bind wsys: %r\n");
-		goto err;
-	}
-
-	p = x;
-	dup(p[0], 0); close(p[0]); close(p[1]);
-	dup(p[3], 1); close(p[3]); close(p[2]);
-	dup(open("/dev/null", OWRITE), 2);
-	procexecl(nil, "/bin/picker", "picker", nil);
-
-err:
-	threadexits("exec: %r");
-}
-
-static void
-colorsproc(void *)
-{
-	Biobuf *in, *out;
-	char *s, *v[3];
-	int p[4], n, i;
-
-	threadsetname("colorsproc");
-	pipe(p);
-	pipe(p+2);
-	procrfork(runpicker, p, 4096, RFFDG|RFNAMEG);
-	close(p[0]);
-	close(p[3]);
-	out = Bfdopen(p[1], OWRITE);
-	in = Bfdopen(p[2], OREAD);
-
-	for (i = 0; i < nelem(theme); i++)
-		Bprint(out, "%s\t%06ux\n", theme[i].id, theme[i].color);
-	Bterm(out);
-
-	for (;;) {
-		if ((s = Brdstr(in, '\n', 1)) == nil)
-			break;
-		if ((n = tokenize(s, v, nelem(v))) == 2) {
-			for (i = 0; i < nelem(theme); i++) {
-				if (strcmp(theme[i].id, v[0]) == 0) {
-					lockdisplay(display);
-					freeimage(color[i]);
-					theme[i].color = strtoul(v[1], nil, 16);
-					color[i] = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, theme[i].color<<8 | 0xff);
-					unlockdisplay(display);
-					redraw(1);
-					break;
-				}
-			}
-		}
-		free(s);
-		if (n != 2)
-			break;
-	}
-	Bterm(in);
-
-	threadexits(nil);
-}
-
-static void
 kbdproc(void *cchan)
 {
 	char buf[128], buf2[128], *s;
@@ -1357,7 +1254,7 @@
 	Point p;
 	char tmp[256];
 	char cmd[256];
-	int oldw, oldh, w, h, n, oldbuttons;
+	int oldw, oldh, w, h, n, oldbuttons, themetid;
 	long seed;
 	bool complete;
 	Alt a[Numchan+1] = {
@@ -1464,8 +1361,8 @@
 
 	proccreate(stdinproc, nil, mainstacksize);
 
-	for (n = 0; n < Numcolors; n++)
-		color[n] = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, theme[n].color<<8 | 0xff);
+	themeinit();
+
 	glyphsz.x = stringwidth(font, "@");
 	glyphsz.y = font->height;
 
@@ -1496,6 +1393,7 @@
 	move.y = 1;
 	oldbuttons = 0;
 	cmd[0] = 0;
+	themetid = -1;
 
 	netdial(nil, nil);
 	midiopen(nil);
@@ -1570,7 +1468,7 @@
 				} else if (n == Menu3rulerstyle) {
 					rulerstyle = ++rulerstyle % Numstyles;
 				} else if (n == Menu3colors) {
-					proccreate(colorsproc, nil, mainstacksize);
+					themetid = proccreate(themeproc, nil, 4096);
 				} else if (n == Menu3exit) {
 					setcursor(mctl, &yousure);
 					for (;;) {
@@ -1840,6 +1738,7 @@
 	}
 
 end:
+	threadint(themetid);
 	chanclose(a[Ckey].c);
 	chanclose(a[Credraw].c);
 	mbuf_reusable_deinit(&mscr);
--- /dev/null
+++ b/theme.c
@@ -1,0 +1,164 @@
+#include <u.h>
+#include <libc.h>
+#include <plumb.h>
+#include <draw.h>
+#include <bio.h>
+#include <thread.h>
+#include "theme.h"
+
+ThemeColor colors[Numcolors] = {
+	[Dback]  = {"background", 0x000000},
+	[Dfhigh] = {"f_high",     0xffffff},
+	[Dfmed]  = {"f_med",      0x777777},
+	[Dflow]  = {"f_low",      0x444444},
+	[Dfinv]  = {"f_inv",      0x000000},
+	[Dbhigh] = {"b_high",     0xdddddd},
+	[Dbmed]  = {"b_med",      0x72dec2},
+	[Dblow]  = {"b_low",      0x222222},
+	[Dbinv]  = {"b_inv",      0xffb545},
+};
+
+void themechanged(void);
+
+static char *themeplumb;
+
+static void
+runpicker(void *x)
+{
+	int *p, f;
+	char tmp[32];
+
+	snprint(tmp, sizeof(tmp), "-pid %d -dx %d -dy %d", getpid(), 384, 320);
+	newwindow(tmp);
+
+	p = x;
+	dup(*p, 0); dup(*p, 1); close(*p);
+	close(p[1]);
+	close(p[2]);
+	dup(f = open("/dev/null", OWRITE), 2); close(f);
+	execl("/bin/picker", "picker", nil);
+
+	threadexits("exec: %r");
+}
+
+void
+themeproc(void *fd)
+{
+	Biobuf *b;
+	char *s, *v[3];
+	int p[3], n, i;
+	static int pid;
+
+	threadsetname("themeproc");
+	pipe(p);
+	p[2] = fd != nil ? *(int*)fd : -1;
+	postnote(PNGROUP, pid, "interrupt");
+	pid = threadpid(procrfork(runpicker, p, 4096, RFFDG|RFNAMEG|RFNOTEG));
+	close(p[0]);
+	b = Bfdopen(p[1], OREAD);
+
+	for(i = 0; i < nelem(colors); i++)
+		fprint(p[1], "%s\t%06ux\n", colors[i].id, colors[i].rgb);
+
+	for(;;){
+		if((s = Brdstr(b, '\n', 1)) == nil)
+			break;
+		if((n = tokenize(s, v, nelem(v))) >= 2){
+			for(i = 0; i < nelem(colors); i++){
+				if(strcmp(colors[i].id, v[0]) == 0){
+					if(display->locking)
+						lockdisplay(display);
+					freeimage(colors[i].im);
+					colors[i].rgb = strtoul(v[1], nil, 16);
+					colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff);
+					if(display->locking)
+						unlockdisplay(display);
+					themechanged();
+					break;
+				}
+			}
+		}
+		free(s);
+		if(n != 2)
+			break;
+	}
+	Bterm(b);
+	postnote(PNGROUP, pid, "interrupt");
+
+	threadexits(nil);
+}
+
+static int
+loadtheme(char *filename, int init)
+{
+	Biobuf *in;
+	char *s, *v[3];
+	int i, n;
+
+	if ((in = Bopen(filename, OREAD)) != nil) {
+		if(display->locking && !init)
+			lockdisplay(display);
+		for(;;){
+			if((s = Brdstr(in, '\n', 1)) == nil)
+				break;
+			if((n = tokenize(s, v, nelem(v))) == 2){
+				for(i = 0; i < nelem(colors); i++){
+					if(strcmp(colors[i].id, v[0]) == 0){
+						freeimage(colors[i].im);
+						colors[i].rgb = strtoul(v[1], nil, 16);
+						colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff);
+						break;
+					}
+				}
+			}
+			free(s);
+			if(n != 2)
+				break;
+		}
+		if(display->locking && !init)
+			unlockdisplay(display);
+		Bterm(in);
+		if(!init)
+			themechanged();
+		return 0;
+	}
+
+	return -1;
+}
+
+static void
+plumbproc(void *)
+{
+	int f;
+	Plumbmsg *m;
+
+	threadsetname("theme/plumb");
+	if ((f = plumbopen(themeplumb, OREAD)) >= 0) {
+		while ((m = plumbrecv(f)) != nil) {
+			loadtheme(m->data, 0);
+			themechanged();
+			plumbfree(m);
+		}
+	}
+
+	threadexits(nil);
+}
+
+void
+themeinit(void)
+{
+	char *s;
+	int i;
+
+	if((s = getenv("theme")) != nil){
+		if(loadtheme(s, 1) != 0)
+			sysfatal("theme load failed: %r");
+		free(s);
+	}
+	for(i = 0; i < Numcolors; i++){
+		if(colors[i].im == nil)
+			colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff);
+	}
+	if((themeplumb = getenv("themeplumb")) != nil)
+		proccreate(plumbproc, nil, 4096);
+}
--- /dev/null
+++ b/theme.h
@@ -1,0 +1,25 @@
+enum {
+	Dback = 0,
+	Dfhigh,
+	Dfmed,
+	Dflow,
+	Dfinv,
+	Dbhigh,
+	Dbmed,
+	Dblow,
+	Dbinv,
+	Numcolors,
+};
+
+typedef struct ThemeColor ThemeColor;
+
+struct ThemeColor {
+	char *id;
+	u32int rgb;
+	Image *im;
+};
+
+extern ThemeColor colors[Numcolors];
+
+void themeproc(void *fd);
+void themeinit(void);