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);
}