~amavect/pal

33ccd568b59d6a3eb8d6049962e73cf00bc3ad6c — amavect 4 years ago
init commit, as presented in video
3 files changed, 387 insertions(+), 0 deletions(-)

A mkfile
A pal.c
A palette
A  => mkfile +20 -0
@@ 1,20 @@
</$objtype/mkfile

TARG=pal
OFILES=pal.$O

all:V: $O.$TARG

%.$O: %.c
	$CC $CFLAGS $prereq

$O.$TARG: $OFILES
	$LD -o $target $prereq

/$objtype/bin/$TARG: $O.$TARG
	cp $prereq $target

install:V: /$objtype/bin/$TARG

clean:V:
	rm -f [$OS].* *.[$OS]

A  => pal.c +354 -0
@@ 1,354 @@
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>

#define DX 64
#define DY 64

int cflag;
int pflag;
int iflag;
ulong ncolors;
ulong *colors;
ulong selcol;
Image *cim;
Image *tile;
Image *grey;

int pfd;

char *entries2[] = {"Add", "Delete", nil};
Menu menu2 = {entries2};
char *entries3[] = {"Send", "Exit", nil};
Menu menu3 = {entries3};

void
error(char *s)
{
	fprint(2, "%s: %s: %r\n", argv0, s);
	threadexitsall(s);
}

Image *
eallocimage(Rectangle r, ulong chan, int repl, ulong col)
{
	Image *i;
	i = allocimage(display, r, chan, repl, col);
	if(i == nil)
		error("cannot allocimage");
	return i;
}

void
dogetwindow(void)
{
	if(getwindow(display, Refnone) < 0)
		error("cannot get window");
}

void
sendcolor(void)
{
	print("0x%08ulX\n", colors[selcol]);
	if(!pflag)
		threadexitsall(nil);
}

void
redraw(void)
{
	int i;
	int mx;
	Rectangle r, sr, br;
	Point sp;
	uchar b[4];
	
	r = screen->r;
	sr = Rect(0,0,DX,DY);
	mx = Dx(r) / Dx(sr);
	
	draw(screen, screen->r, grey, nil, ZP);
	
	for(i = 0; i < ncolors; i++){
		sp.x = DX * (i % mx);
		sp.y = DY * (i / mx);
		b[0] = (char)(colors[i]>>0 & 0xFF);
		b[1] = (char)(colors[i]>>8 & 0xFF);
		b[2] = (char)(colors[i]>>16 & 0xFF);
		b[3] = (char)(colors[i]>>24 & 0xFF);
		loadimage(cim, cim->r, b, sizeof(b));
		br = rectaddpt(sr, addpt(r.min, sp));
		draw(screen, br, tile, nil, ZP);
		draw(screen, br, cim, nil, ZP);
		border(screen, br, 4, display->white, ZP);
	}
	if(ncolors > 0){
		sp.x = DX * (selcol % mx);
		sp.y = DY * (selcol / mx);
		br = rectaddpt(sr, addpt(r.min, sp));
		br = insetrect(br, 1);
		border(screen, br, 2, display->black, ZP);
	}
	flushimage(display, 1);
}

void
addcolor(ulong c, ulong i)
{
	int j;
	
	j = ncolors;
	ncolors++;
	if(ncolors == 1)
		colors = malloc(sizeof(*colors));
	else
		colors = realloc(colors, sizeof(*colors) * ncolors);
	if(colors == nil)
		error("null pointer");
	
	for(; j > i; j--){
		colors[j] = colors[j-1];
	}
	colors[i] = c;
}

void
delcolor(ulong i)
{
	if(ncolors == 0)
		return;
	ncolors--;
	for(; i < ncolors; i++){
		colors[i] = colors[i+1];
	}
	if(selcol >= ncolors)
		selcol--;
	if(ncolors == 0)
		free(colors);
	else
		colors = realloc(colors, sizeof(*colors) * ncolors);
	if(colors == nil)
		error("null pointer");
}

void
readpalfile(char *s)
{
	int fd;
	long n;
	char a[11];
	ulong c;
	
	fd = open(s, OREAD);
	if(fd < 0)
		error("cannot open file");
	while((n = read(fd, a, sizeof(a))) != 0){
		if(n != 11)
			error("invalid palette");
		if(a[10] != '\n')
			error("invalid palette");
		a[10] = 0;
		c = strtoul(a, nil, 0);
		addcolor(c, ncolors);
	}
}

void
pickerproc(void *aux)
{
	Channel *c;
	char s[11];
	long n;
	ulong col;
	
	c = aux;
	
	for(;;){
		n = read(pfd, s, sizeof(s));
		if(n <= 0){
			yield();
			threadexitsall(nil);
		}
		s[10] = 0;
		col = strtoul(s, nil, 0);
		send(c, &col);
	}
}

Channel *
initpicker(void)
{
	int pid;
	int fd[2];
	int wfd;
	char *srvwsys;
	Channel *c;
	
	if(pipe(fd) < 0)
		error("cannot pipe");
	pid = rfork(RFPROC|RFNOWAIT|RFNAMEG|RFFDG|RFREND);
	if(pid < 0)
		error("cannot fork");
	if(pid == 0){
		close(0);
		close(1);
		close(fd[0]);
		dup(fd[1], 0);
		dup(fd[1], 1);
		
		srvwsys = getenv("wsys");
		if(srvwsys == nil)
			error("can't find $wsys");
		wfd = open(srvwsys, ORDWR);
		if(wfd < 0)
			error("can't open $wsys");
		if(mount(wfd, -1, "/dev", MBEFORE, "new -dx 600 -dy 400") < 0)
			error("can't mount new window");
		if(execl("/bin/makeu", "/bin/makeu", "-pi", nil) < 0)
			error("can't exec");
	}
	close(fd[1]);
	pfd = fd[0];
	
	c = chancreate(sizeof(ulong), 16);
	proccreate(pickerproc, c, 0x2000);
	
	return c;
}

void
usage(void)
{
	fprint(2, "usage: %s [-c] [file]\n", argv0);
	threadexitsall("usage");
}

void
threadmain(int argc, char **argv)
{
	Keyboardctl *kctl;
	Mousectl *mctl;
	Mouse m;
	Rune r;
	ulong col;
	ulong tcol;
	Channel *pc;
	
	ARGBEGIN{
	case 'c':
		cflag++;
		break;
	case 'p':
		pflag++;
		break;
	case 'i':
		iflag++;
		break;
	default:
		usage();
	}ARGEND
	
	if(argc == 1){
		readpalfile(argv[0]);
	}else if(argc > 1){
		usage();
	}
	
	if(initdraw(nil, nil, argv0) < 0)
		error("cannot initdraw");
	cim = eallocimage(Rect(0,0,1,1), RGBA32, 1, DNofill);
	grey = eallocimage(Rect(0,0,1,1), RGB24, 1, 0x777777FF);
	tile = eallocimage(Rect(0,0,DX/2,DY/2), GREY1, 1, DWhite);
	draw(tile, Rect(0,0,DX/4,DY/4), display->black, nil, ZP);
	draw(tile, Rect(DX/4,DY/4,DX/2,DY/2), display->black, nil, ZP);
	
	kctl = initkeyboard(nil);
	if(kctl == nil)
		error("no keyboard");
	mctl = initmouse(nil, screen);
	if(mctl == nil)
		error("no mouse");
	
	
	enum{MOUSE, RESIZE, KEYS, PICKER};
	Alt alts[] = {
		{mctl->c, &m, CHANRCV},
		{mctl->resizec, nil, CHANRCV},
		{kctl->c, &r, CHANRCV},
		{nil, nil, CHANEND},
		{nil, nil, CHANEND}
	};
	
	if(cflag){
		pc = initpicker();
		alts[PICKER].c = pc;
		alts[PICKER].v = &col;
		alts[PICKER].op = CHANRCV;
	}
	
	
	redraw();
	
	for(;;){
		switch(alt(alts)){
		case MOUSE:
			if(m.buttons == 1 || m.buttons == 2){
				m.xy = subpt(m.xy, screen->r.min);
				tcol = (m.xy.x / DX) +
					(Dx(screen->r) / DX) * (m.xy.y / DY);
				if(tcol < ncolors && tcol != selcol){
					selcol = tcol;
					if(iflag)
						sendcolor();
					if(cflag)
						fprint(pfd, "0x%08ulX\n", colors[selcol]);
					redraw();
				}
				if(tcol >= ncolors)
					tcol = ncolors-1;
				if(m.buttons == 2){
					switch(menuhit(2, mctl, &menu2, nil)){
					case 0:
						addcolor(0xFFFFFFFF, tcol+1);
						break;
					case 1:
						delcolor(tcol);
						break;
					}
					redraw();
				}
			}
			if(m.buttons == 4){
				switch(menuhit(3, mctl, &menu3, nil)){
				case 0:
					sendcolor();
					break;
				case 1:
					threadexitsall(nil);
					break;
				}
			}
			break;
		case RESIZE:
			dogetwindow();
			redraw();
			break;
		case KEYS:
			if(r == Kdel)
				threadexitsall(nil);
			break;
		case PICKER:
			if(ncolors > 0){
				colors[selcol] = col;
				redraw();
			}
			break;
		default:
			error("invalid alt");
		}
	}
}

A  => palette +13 -0
@@ 1,13 @@
0xFF00FFFF
0xFFFF00FF
0x12345677
0xDEADBEEF
0x7F7F7F7F
0xFF0000FF
0x00FF00FF
0x0000FFFF
0x00FFFFFF
0x777777FF
0x770000FF
0x007700FF
0x000077FF