first commit
This commit is contained in:
372
strans.c
Normal file
372
strans.c
Normal file
@@ -0,0 +1,372 @@
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
static Im im;
|
||||
|
||||
Lang langs[] = {
|
||||
{LangJP, "hira", "kanji", nil, nil, jptrans},
|
||||
{LangJPK, "kata", "kanji", nil, nil, jptrans},
|
||||
{LangKO, "hangul", "hangul", nil, nil, trans},
|
||||
};
|
||||
int nlang = nelem(langs);
|
||||
|
||||
static void
|
||||
clearkouho(void)
|
||||
{
|
||||
im.nkouho = 0;
|
||||
im.sel = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setkouho(Dictres *res)
|
||||
{
|
||||
int i;
|
||||
|
||||
clearkouho();
|
||||
for(i = 0; i < res->nkouho; i++){
|
||||
im.kouho[i] = res->kouho[i];
|
||||
im.nkouho++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show(void)
|
||||
{
|
||||
Drawcmd dc;
|
||||
int i;
|
||||
|
||||
dc.nkouho = im.nkouho;
|
||||
dc.sel = im.sel;
|
||||
for(i = 0; i < dc.nkouho; i++)
|
||||
dc.kouho[i] = im.kouho[i];
|
||||
chansend(drawc, &dc);
|
||||
}
|
||||
|
||||
static void
|
||||
dictq(void)
|
||||
{
|
||||
Str dict;
|
||||
Dictreq req;
|
||||
|
||||
if(!mapget(im.l->map, &im.line, &dict)){
|
||||
clearkouho();
|
||||
show();
|
||||
return;
|
||||
}
|
||||
req.key = dict;
|
||||
req.lang = im.l->lang;
|
||||
req.line = im.line;
|
||||
channbsend(dictreqc, &req);
|
||||
}
|
||||
|
||||
static int
|
||||
checklang(int c)
|
||||
{
|
||||
Lang *l;
|
||||
|
||||
l = getlang(c);
|
||||
if(l == nil && c != LangEN)
|
||||
return 0;
|
||||
im.l = l;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
commit(Str *com)
|
||||
{
|
||||
Str kana;
|
||||
|
||||
if(mapget(im.l->map, &im.line, &kana))
|
||||
sappend(com, &kana);
|
||||
sclear(&im.line);
|
||||
}
|
||||
|
||||
static int
|
||||
dotrans(Rune c, Str *com)
|
||||
{
|
||||
Emit e;
|
||||
Dictreq req;
|
||||
|
||||
e = im.l->trans(&im, c);
|
||||
|
||||
if(e.s.n > 0)
|
||||
sappend(com, &e.s);
|
||||
sclear(&im.line);
|
||||
sappend(&im.line, &e.next);
|
||||
if(e.eat && e.dict.n > 0){
|
||||
req.key = e.dict;
|
||||
req.lang = im.l->lang;
|
||||
req.line = im.line;
|
||||
channbsend(dictreqc, &req);
|
||||
}
|
||||
|
||||
return e.eat;
|
||||
}
|
||||
|
||||
Lang*
|
||||
getlang(int lang)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(langs); i++)
|
||||
if(langs[i].lang == lang)
|
||||
return &langs[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
Emit
|
||||
trans(Im *im, Rune c)
|
||||
{
|
||||
Emit e = {0};
|
||||
Str key, kana;
|
||||
Hmap *h;
|
||||
Rune last;
|
||||
|
||||
h = im->l->map;
|
||||
key = im->line;
|
||||
sputr(&key, c);
|
||||
if(hmapget(h, &key)){
|
||||
e.eat = 1;
|
||||
e.next = key;
|
||||
mapget(h, &key, &e.dict);
|
||||
return e;
|
||||
}
|
||||
|
||||
last = slastr(&im->line);
|
||||
if(last == 0)
|
||||
goto flush;
|
||||
|
||||
key = im->line;
|
||||
key.n--;
|
||||
if(mapget(h, &key, &kana)){
|
||||
sclear(&key);
|
||||
sputr(&key, last);
|
||||
sputr(&key, c);
|
||||
if(hmapget(h, &key)){
|
||||
e.eat = 1;
|
||||
e.s = kana;
|
||||
sputr(&e.next, last);
|
||||
sputr(&e.next, c);
|
||||
mapget(h, &e.next, &e.dict);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
flush:
|
||||
mapget(h, &im->line, &e.s);
|
||||
|
||||
sclear(&key);
|
||||
sputr(&key, c);
|
||||
if(hmapget(h, &key) == nil){
|
||||
e.flush = 1;
|
||||
sputr(&e.s, c);
|
||||
return e;
|
||||
}
|
||||
|
||||
e.eat = 1;
|
||||
sputr(&e.next, c);
|
||||
mapget(h, &e.next, &e.dict);
|
||||
return e;
|
||||
}
|
||||
|
||||
static void
|
||||
reset(void)
|
||||
{
|
||||
sclear(&im.line);
|
||||
clearkouho();
|
||||
show();
|
||||
}
|
||||
|
||||
static int
|
||||
keystroke(u32int ks, u32int mod, Str *com)
|
||||
{
|
||||
int n, off;
|
||||
|
||||
if(ks == Ksuper || ks == Kshift)
|
||||
return 1;
|
||||
if(ks == Kdown || ks == Kup){
|
||||
if(im.nkouho == 0)
|
||||
return 0;
|
||||
if(ks == Kdown && im.sel < im.nkouho - 1)
|
||||
im.sel++;
|
||||
if(ks == Kup && im.sel > 0)
|
||||
im.sel--;
|
||||
show();
|
||||
return 1;
|
||||
}
|
||||
n = ks - '1';
|
||||
off = 0;
|
||||
if(im.sel >= Maxdisp)
|
||||
off = im.sel - Maxdisp + 1;
|
||||
if(n >= 0 && n < Maxdisp && off + n < im.nkouho){
|
||||
sappend(com, &im.kouho[off + n]);
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(ks == Ktab || ks == Kret){
|
||||
if(im.sel >= 0 && im.sel < im.nkouho){
|
||||
sappend(com, &im.kouho[im.sel]);
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(im.line.n > 0){
|
||||
commit(com);
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(ks == Kback){
|
||||
if(im.line.n == 0)
|
||||
return 0;
|
||||
spopr(&im.line);
|
||||
if(im.line.n == 0){
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
dictq();
|
||||
return 1;
|
||||
}
|
||||
if(ks == Kesc){
|
||||
if(im.line.n == 0)
|
||||
return 0;
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(ks >= Kspec || (mod & (Malt|Msuper))){
|
||||
commit(com);
|
||||
reset();
|
||||
return 0;
|
||||
}
|
||||
if(mod & Mctrl){
|
||||
reset();
|
||||
if(ks >= 'a' && ks <= 'z')
|
||||
ks -= 'a' - 1;
|
||||
if(checklang(ks))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(im.l == nil)
|
||||
return 0;
|
||||
if(ks > 0x7f || !isalpha(ks)){
|
||||
commit(com);
|
||||
sputr(com, ks);
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
return dotrans(ks, com);
|
||||
}
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
memset(&im, 0, sizeof(im));
|
||||
}
|
||||
|
||||
void
|
||||
imthread(void*)
|
||||
{
|
||||
Keyreq kr;
|
||||
Dictres res;
|
||||
Str com;
|
||||
uchar out[256];
|
||||
int n, len, r;
|
||||
Alt alts[] = {
|
||||
{keyc, &kr, CHANRCV, nil},
|
||||
{dictresc, &res, CHANRCV, nil},
|
||||
{nil, nil, CHANEND, nil},
|
||||
};
|
||||
|
||||
threadsetname("im");
|
||||
init();
|
||||
for(;;){
|
||||
switch(alt(alts)){
|
||||
case 0:
|
||||
sclear(&com);
|
||||
r = keystroke(kr.ks, kr.mod, &com);
|
||||
out[0] = r;
|
||||
out[1] = 0;
|
||||
n = 2;
|
||||
if(com.n > 0){
|
||||
len = stoutf(&com, (char*)(out+2), sizeof(out)-2);
|
||||
out[1] = len;
|
||||
n += len;
|
||||
}
|
||||
write(kr.fd, out, n);
|
||||
break;
|
||||
case 1:
|
||||
if(scmp(&res.key, &im.line) == 0){
|
||||
setkouho(&res);
|
||||
show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mapget(Hmap *h, Str *key, Str *out)
|
||||
{
|
||||
Hnode *n;
|
||||
|
||||
if(key->n == 0)
|
||||
return 0;
|
||||
n = hmapget(h, key);
|
||||
if(n == nil || n->kanalen == 0)
|
||||
return 0;
|
||||
sinit(out, n->kana, n->kanalen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Hmap*
|
||||
openmap(char *path)
|
||||
{
|
||||
Hmap *h;
|
||||
Biobuf *b;
|
||||
Str key, val, empty;
|
||||
char *line, *tab;
|
||||
int i, klen;
|
||||
|
||||
b = Bopen(path, OREAD);
|
||||
if(b == nil)
|
||||
die("can't open: %s", path);
|
||||
h = hmapalloc(1024, 0);
|
||||
sclear(&empty);
|
||||
while((line = Brdstr(b, '\n', 1)) != nil){
|
||||
if(line[0] == '\0'){
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
tab = strchr(line, '\t');
|
||||
if(tab == nil || tab[1] == '\0')
|
||||
die("malformed map: %s", path);
|
||||
*tab = '\0';
|
||||
klen = strlen(line);
|
||||
sinit(&key, line, klen);
|
||||
sinit(&val, tab+1, strlen(tab+1));
|
||||
hmapset(&h, &key, &val);
|
||||
for(i = 1; i < klen; i++){
|
||||
sinit(&key, line, i);
|
||||
if(hmapget(h, &key) == nil)
|
||||
hmapset(&h, &key, &empty);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
Bterm(b);
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
mapinit(char *dir)
|
||||
{
|
||||
char path[1024];
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(langs); i++){
|
||||
if(langs[i].mapname == nil)
|
||||
continue;
|
||||
snprint(path, sizeof(path), "%s/%s.map", dir, langs[i].mapname);
|
||||
langs[i].map = openmap(path);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user