shithub: blie

ref: 0e8796746fad950ab61be075de5638fdcbd6fc32
dir: /layer.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <event.h>
#include <bio.h>
#include "blie.h"

char Ebadfmt[] = "bad file format: ";

typedef struct List List;
struct List {
	Layer *layer;
	List *next;
};

List *firstlayer = nil;

static Drawop
str2op(char *s)
{
#define OP(n) if (!strcmp(s, "n")) { return n; }
	OP(Clear);
	OP(SinD);
	OP(DinS);
	OP(SoutD);
	OP(DoutS);
	OP(S);
	OP(SoverD);
	OP(SatopD);
	OP(SxorD);
	OP(D);
	OP(DoverS);
	OP(DatopS);
	OP(DxorS);
#undef OP
	return SoverD;
}

static char*
op2str(Drawop op)
{
#define OP(n) if (op == n) { return "n"; }
	OP(Clear);
	OP(SinD);
	OP(DinS);
	OP(SoutD);
	OP(DoutS);
	OP(S);
	OP(SoverD);
	OP(SatopD);
	OP(SxorD);
	OP(D);
	OP(DoverS);
	OP(DatopS);
	OP(DxorS);
#undef OP
	return "SoverD";
}

static void
addlayerl(Layer *l)
{
	List *f;
	if (!firstlayer) {
		firstlayer = mallocz(sizeof(List), 1);
		firstlayer->layer = l;
		return;
	}
	for (f = firstlayer; f->next; f = f->next)
		continue;
	f->next = mallocz(sizeof(List), 1);
	f->next->layer = l;
}

void
addlayer(char *name)
{
	Biobuf *b;
	char *file;
	char *ed, *lbl, *op;
	Layer *l;
	
	if (!name || !name[0])
		return;
	
	file = smprint("%s/meta", name);
	b = Bopen(file, OREAD);
	free(file);
	if (!b)
		sysfatal("error opening file %s/meta: %r", name);
	
	ed = Brdstr(b, '\n', 1);
	if (!ed)
		sysfatal("%s%s/meta: missing editor", Ebadfmt, name);
	lbl = Brdstr(b, '\n', 1);
	if (!lbl)
		sysfatal("%s%s/meta: missing label", Ebadfmt, name);
	op = Brdstr(b, '\n', 1);
	if (!op)
		sysfatal("%s%s/meta: missing drawop", Ebadfmt, name);
	
	l = mallocz(sizeof(Layer), 1);
	l->name = strdup(name);
	l->label = strdup(lbl);
	l->editor = geteditor(ed);
	l->op = str2op(op);
	if (!l->editor)
		sysfatal("editor %s not found for %s", ed, name);
	addlayerl(l);
	free(lbl);
	free(ed);
	free(op);
	
	Bterm(b);
}

void
movelayer(Layer *layer, int dir)
{
	List *parent;
	List *l;
	
	if (firstlayer->layer == layer) {
		if (dir == DOWN) {
			l = firstlayer->next;
			firstlayer->next = l ? l->next : nil;
			l->next = firstlayer;
			firstlayer = l;
			return;
		}
		if (dir == UP)
			return; /* NOP */
	}
	
	/* find parent */
	for (l = firstlayer; l && l->next->layer != layer; l = l->next)
		continue;
	
	if (!l)
		return; /* not found */
	parent = l;
	
	if (dir == DOWN)
		goto Movedown;
	if (dir != UP)
		sysfatal("code error: direction != UP|DOWN");
	
	/* movelayer(layer, UP) == movelayer(parent, DOWN) */
	movelayer(parent->layer, DOWN);
	
	return;
Movedown:
	l = parent->next;
	if (!l)
		return; /* NOP: last element */
	parent->next = l->next;
	l->next = l->next ? l->next->next : nil;
	parent->next->next = l;
}

void
savelayermeta(Layer *layer)
{
	Biobuf *b;
	char *file;
	
	file = smprint("%s.meta", layer->name);
	b = Bopen(file, OWRITE|OTRUNC);
	free(file);
	if (!b)
		sysfatal("error opening file %s.meta for write: %r", layer->name);
	
	Bprint(b, "%s\n%s\n", layer->editor->name, layer->label);
	Bterm(b);
}

int
foreachlayer(void (*f)(Layer*, int, void*), void* aux)
{
	List *l;
	int i;
	
	i = 0;
	for (l = firstlayer; l; l = l->next, i++) {
		f(l->layer, i, aux);
	}
	
	return i;
}