shithub: zuke

ref: 8952c92c316b6d97f2306f7f35583631cfca74d2
dir: /theme.c/

View raw version
#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]);
	dup(f = open("/dev/null", OWRITE), 2); close(f);
	procexecl(nil, "/bin/picker", "picker", nil);

	threadexits("exec: %r");
}

static void
themeproc(void *)
{
	Biobuf *b;
	char *s, *v[3];
	int p[2], n, i;

	threadsetname("themeproc");
	pipe(p);
	procrfork(runpicker, p, 4096, RFFDG|RFNAMEG);
	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);

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