ref: 60929ada1a066c49396d48bf45cf347a50f8e363
dir: /src/optshow.c/
/* 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); }