shithub: zuke

ref: 0b91a70d4d7e3fe993e66b882b3fb988026f806b
dir: zuke/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", 0xe2e2e2},
	[Dfhigh] = {"f_high",     0xffffff},
	[Dfmed]  = {"f_med",      0x343434},
	[Dflow]  = {"f_low",      0xa5a5a5},
	[Dfinv]  = {"f_inv",      0x323232},
	[Dbhigh] = {"b_high",     0xcacaca},
	[Dbmed]  = {"b_med",      0x72dec2},
	[Dblow]  = {"b_low",      0x404040},
	[Dbinv]  = {"b_inv",      0xffb545},
};

void themechanged(void);

static char *themeplumb;

static void
runpicker(void *x)
{
	int *p;
	char tmp[32];

	snprint(tmp, sizeof(tmp), "-pid %d -dx %d -dy %d", getpid(), 384, 320);
	if(newwindow(tmp) == 0){
		p = x;
		dup(*p, 0); dup(*p, 1); close(*p);
		close(p[1]);
		execl("/bin/picker", "picker", nil);
	}

	fprint(2, "runpicker: %r");
	threadexits("%r");
}

void
themeproc(void *)
{
	char *s, *v[3];
	int p[2], n, i;
	static int pid = -1;
	u32int rgb;
	Biobuf *b;
	Image *im;

	threadsetname("themeproc");
	pipe(p);
	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);
					rgb = strtoul(v[1], nil, 16);
					im = allocimage(display, Rect(0,0,1,1), RGB24, 1, rgb<<8 | 0xff);
					if(im == nil)
						fprint(2, "%r\n");
					else{
						freeimage(colors[i].im);
						colors[i].rgb = rgb;
						colors[i].im = im;
					}
					if(display->locking)
						unlockdisplay(display);
					themechanged();
					break;
				}
			}
		}
		free(s);
		if(n != 2)
			break;
	}
	Bterm(b);
	postnote(PNGROUP, pid, "interrupt");
	pid = -1;

	threadexits(nil);
}

static int
loadtheme(char *filename, int init)
{
	char *s, *v[3];
	Biobuf *in;
	u32int rgb;
	Image *im;
	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){
						rgb = strtoul(v[1], nil, 16);
						im = allocimage(display, Rect(0,0,1,1), RGB24, 1, rgb<<8 | 0xff);
						if(im == nil)
							fprint(2, "%r\n");
						else{
							freeimage(colors[i].im);
							colors[i].rgb = rgb;
							colors[i].im = im;
						}
						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);
}