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