shithub: dmenu

ref: fc299fdf45602f63cf16c939706abbfc276e69db
dir: /linesel.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <draw.h>
#include <thread.h>
#include <keyboard.h>
#include <mouse.h>

int bflag;
Image *fgcolor, *bgcolor;
Font *font;
char **lines, **matches, *buffer,  *selected;
usize nlines, nmatches;
Rune kbdin[512];
Keyboardctl *keyboard;
Mousectl *mouse;

enum
{
	Ckeyboard,
	Cmouse,
	Cresize,
	Cnum
};

static void
redraw(void)
{
	draw(screen, screen->r, bgcolor, nil, ZP);
	string(screen,
	  Pt(10, 10), fgcolor, ZP, font, "test");
	flushimage(display, 1);
}

static void
resetmatches(void)
{
	memmove(matches, lines, nlines * sizeof *lines);
	nmatches = nlines;
}

static void
initgraphics(Alt *a)
{
	if(initdraw(nil, nil, "linesel") == -1)
		sysfatal("initdraw: %r");
	if(bflag){
		fgcolor = display->white;
		bgcolor = display->black;
	}else{
		fgcolor = display->black;
		bgcolor = display->white;
	}
	font = display->defaultfont;

	if((keyboard = initkeyboard(nil)) == nil)
		sysfatal("initkeyboard: %r");
	if((mouse = initmouse(nil, screen)) == nil)
		sysfatal("initmouse: %r");	

	a[Ckeyboard].c = keyboard->c;
	a[Cmouse].c = mouse->c;
}

static void
readbuffer(void)
{
	Biobuf *bp;
	char *line, *s;

	if((bp = Bfdopen(0, OREAD)) == nil)
		sysfatal("setting buffering on fd0: %r");
	if ((buffer = Brdstr(bp, '\0', 1)) == nil)
		sysfatal("reading input lines: %r");

	for(line = s = buffer; s = strchr(s, '\n'); line = ++s){
		*s = '\0';
		if((lines = realloc(lines, ++nlines * sizeof *lines)) == nil)
			sysfatal("malloc: %r");
		lines[nlines-1] = line;
	}
	if((matches = malloc(nlines * sizeof *lines)) == nil)
		sysfatal("malloc: %r");
}

static void
linesel(void)
{
	Rune r;
	Mouse m;
	Alt a[] = {
		[Ckeyboard] = {nil, &r, CHANRCV},
		[Cmouse] = {nil, &m, CHANRCV},
		[Cnum] = {nil, nil, CHANEND},
	};

	initgraphics(a);
	redraw();

	for(;;){
		switch(alt(a)){
		case -1:
			sysfatal("watching channels: %r\n");

		case Ckeyboard:
			switch(r){
			case '\n':
				return;
			}
			break;

		case Cmouse:
			break;
		}
	}

}

static void
usage(void)
{
	print("usage: %s [-b] <choices\n", argv0);
	threadexitsall("usage");
}

void
threadmain(int argc, char **argv)
{
	ARGBEGIN{
	case 'b':
		bflag = 1;
		break;
	default:
		usage();
	}ARGEND;

	readbuffer();
	resetmatches();
	selected = matches[0];
	linesel();
	print("%s\n", selected);
	threadexitsall(nil);
}