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);