shithub: nime

ref: 60929ada1a066c49396d48bf45cf347a50f8e363
dir: /src/optshow.c/

View raw version
/* optshow
 *******************************************************************************
 * Author: Ethan Long
 * Licence: Public Domain
 * Email: ethandavidlong@gmail.com, u7281759@anu.edu.au
 * Description: optshow is a program for overlaying the convertion options for a
 *              IME over the input, it should work with existing IMEs like
 *              ktrans, but also for nIME's core.
 */

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include <frame.h>
#include <bio.h>

void clockproc(void*);
void optdraw(Image*, Image*, Point, Rune*);
void readinproc(void*);
void relocate(Rune*);
void usage(void);

enum
{
	STACK = 2048,
};

Channel *timer;
int top = 0;
Biobuf bin, bout;


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

void
threadmain(int argc, char *argv[])
{
	ulong bgco, textco;
	Image *bg, *text;
	Mousectl *mctl;
	Mouse mouse;
	Point textpos;
	int disp;
	Rune *buf;
	Rune input[64];
	int clock;
	
	bgco = 0xFFFFFFFF;
	textco = 0x000000FF;
	
	ARGBEGIN{
	case 't':
		top = 1;
		break;
	case 'b':
		top = 0;
		break;
	case 's':
		Binit(&bin, 0, OREAD);
		Binit(&bout, 1, OWRITE);
		break;
	default:
		usage();
		exits("usage");
	}ARGEND;
	
	if(initdraw(nil, nil, argv0) < 0)
		sysfatal("%s: %r", argv0);
	bg = allocimage(display, Rect(0,0,1,1), RGB24, 1, bgco);
	text = allocimage(display, Rect(0,0,screen->r.max.x,font->height), RGB24, 0, textco);
	if(bg == nil || text == nil)
		sysfatal("%s: We need more memory\n%r", argv0);
	
	textpos.x = screen->r.min.x;
	textpos.y = screen->r.min.y;
	
	buf = L"No input recieved";
	optdraw(bg, text, textpos, buf);
	
	if((mctl = initmouse(nil, screen)) == nil)
		sysfatal("%s: %r", argv0);
	
	enum{INPUT, MOUSE, CLOCK, NONE};
	Alt alts[4] = {
	/*   c        v       op      */
		{nil,     input,  CHANRCV},
		{mctl->c, &mouse, CHANRCV},
		{timer,   &clock, CHANRCV},
		{nil,     nil,    CHANEND},
	};
	
	alts[2].c = chancreate(sizeof(ulong), 0);
	timer = alts[2].c;
	proccreate(clockproc, alts[2].c, STACK);
	
	alts[0].c = chancreate(sizeof input, 0);
	proccreate(readinproc, alts[0].c, STACK);
	
	disp = 1;
	while(disp){
		switch(alt(alts)){
		case CLOCK:
			relocate(buf);
			optdraw(bg, text, textpos, buf);
			break;
		case INPUT:
			relocate(buf);
			if(!(recv(alts[0].c, input))){
				sysfatal("%s: Unsuccessful retrieval of input\n%r", argv0);
			}
			buf = input;
			optdraw(bg, text, textpos, buf);
			break;
		case MOUSE:
			relocate(buf);
			if(getwindow(display, Refnone) < 0)
				sysfatal("%s: %r", argv0);
			textpos.x = screen->r.min.x;
			textpos.y = screen->r.min.y;
			freeimage(text);
			text = allocimage(display, Rect(0,0,screen->r.max.x,font->height), RGB24, 0, textco);
			optdraw(bg, text, textpos, buf);
			break;
		case NONE:
			break;
		}
	}
}

void
clockproc(void *arg)
{
	int o;
	Channel *c;
	
	c = arg;
	
	o = 1;
	
	while(o){
		if(!(send(c, &o))){
			o = 0;
			sysfatal("%s: Clock broke can't fix\n%r", argv0);
		}
		sleep(1000);
	}
}

void
optdraw(Image *bg, Image *text, Point textpos, Rune *opt)
{
	draw(screen, screen->r, bg, nil, ZP);
	runestring(screen, textpos, text, ZP, font, opt);
	flushimage(display, Refnone);
}

void
readinproc(void *arg)
{
	Rune input[64];
	Rune r;
	Channel *mc;
	
	mc = arg;
	
	for(int i=0; (r=Bgetrune(&bin)) != Beof; i++){
		input[i] = r;
		input[i+1] = 0;
	}
	
	
	while(recv(timer, nil)){
		send(mc, nil);
		send(mc, input);
	}
}

void
relocate(Rune *buf)
{
	Point min, max;
	int wp, wid, ht, strlen;
	
	wid = 0;
	
	for(strlen=0; buf[strlen] != 0; strlen++)
	if((wid = strlen * (font->width + 4)) < 100)
		wid = 100;
	
	ht = font->height * 2;
	
	if((wp = open("/dev/wctl", ORDWR)) < 0)
		sysfatal("%s: Couldn't open wctl\n %r", argv0);
	
	if(top){
		min = Pt(0,0);
		max = Pt(wid, ht);
	}else{
		min = Pt(0, display->image->r.max.y - ht);
		max = Pt(wid, display->image->r.max.y);
	}
	
	fprint(wp, "resize -r %d %d %d %d", min.x, min.y, max.x, max.y);
	close(wp);
}