ref: a04b62338356b4d2b39e13624afad0f204bd43f4
dir: /kdict.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <thread.h>
#include <draw.h>
#include <mouse.h>
#include <keyboard.h>
#include "hash.h"
Hmap *radk;
Rune rads[256];
int selected[256];
int nrads;
static void
load(void)
{
Biobuf *b;
char *s, *k;
Rune r;
int i;
b = Bopen("/lib/radk", OREAD);
if(b == nil)
sysfatal("Bopen: %r");
radk = hmapalloc(128, sizeof(char*));
i = 0;
while((s = Brdstr(b, '\n', 1)) != nil){
if(*s == '\0')
continue;
s += chartorune(&r, s);
k = smprint("%C", r);
if(*s++ != ' ')
goto Bad;
while(*s >= '0' && *s <= '9')
s++;
if(*s++ != ' ')
goto Bad;
hmapupd(&radk, k, &s);
rads[i++] = r;
assert(i < nelem(rads));
}
rads[i] = 0;
nrads = i;
Bterm(b);
return;
Bad:
sysfatal("invalid format");
}
char*
lkup(Rune *q)
{
Hmap *h;
char buf[4096];
char *dot, *e, *r;
Rune u;
int count;
uchar *p;
int *v;
Hnode *node;
int len;
h = hmapalloc(128, sizeof count);
for(len = 0; *q != 0; q++){
snprint(buf, sizeof buf, "%C", *q);
r = nil;
hmapget(radk, buf, &r);
assert(r != nil);
len++;
for(;;){
r += chartorune(&u, r);
if(u == ' ')
continue;
if(u == '\0')
break;
snprint(buf, sizeof buf, "%C", u);
count = 0;
hmapget(h, buf, &count);
count++;
hmapupd(&h, strdup(buf), &count);
}
}
e = buf + sizeof buf;
dot = buf;
for(p = h->nodes; p < h->nodes+(h->nsz*h->len); p += h->nsz){
node = (void*)p;
if(node->filled == 0)
continue;
v = (void*)(p+Tagsize);
if(*v == len)
dot = seprint(dot, e, "%s", node->key);
}
return strdup(buf);
}
void
threadmain(int, char**)
{
Rune buf[64], *bp, *be;
Mousectl *mctl;
Keyboardctl *kctl;
Mouse m;
Rune key;
Font *f;
Point p, p2;
int i, n;
char *res;
Image *blue, *green, *back;
enum { Aresize, Amouse, Akbd, Aend };
Alt a[] = {
[Aresize] { nil, nil, CHANRCV },
[Amouse] { nil, &m, CHANRCV },
[Akbd] { nil, &key, CHANRCV },
[Aend] { nil, nil, CHANEND },
};
if(initdraw(nil, nil, "kdict") < 0)
sysfatal("failed to initdraw: %r");
mctl = initmouse(nil, screen);
if(mctl == nil)
sysfatal("failed to get mouse: %r");
kctl = initkeyboard(nil);
if(kctl == nil)
sysfatal("failed to get keyboard: %r");
f = display->defaultfont;
load();
a[Aresize].c = mctl->resizec;
a[Amouse].c = mctl->c;
a[Akbd].c = kctl->c;
blue = allocimagemix(display, DPaleblue, DWhite);
green = allocimagemix(display, DGreen, DWhite);
res = nil;
goto Redraw;
for(;;)
switch(alt(a)){
case Amouse:
if(m.buttons == 0)
continue;
m.xy = subpt(m.xy, screen->r.min);
i = m.xy.y / font->height;
if(i > nelem(rads)/25)
continue;
for(n = 1; i*25 + n < nrads && m.xy.x > runestringnwidth(f, rads + i*25, n); n++)
;
selected[i*25 + n - 1] = !selected[i*25 + n - 1];
goto Redraw;
case Akbd:
if(key == 'q' || key == Kdel){
if(res != nil)
print("%s\n", res);
threadexitsall(nil);
}
break;
case Aresize:
getwindow(display, Refnone);
Redraw:
draw(screen, screen->r, display->white, nil, ZP);
p = screen->r.min;
bp = buf;
be = buf + nelem(buf);
*bp = 0;
for(i = 0; i < nelem(rads); i++){
if(selected[i]){
back = green;
bp = runeseprint(bp, be, "%C", rads[i]);
} else if(i/25 % 2 == 1)
back = blue;
else
back = display->white;
p = runestringnbg(screen, p, display->black, ZP, f, rads+i, 1, back, ZP);
if((i+1) % 25 == 0){
p.x = screen->r.min.x;
p.y += font->height;
}
}
free(res);
if(runestrlen(buf) != 0){
p.y += font->height*2;
p.x = screen->r.min.x;
res = lkup(buf);
string(screen, p, display->black, ZP, f, res);
} else
res = nil;
flushimage(display, 1);
break;
}
}