engine: look dictionaries up synchronously

The dictionary thread ran in imthread's own proc, so a lookup could
only start once the engine blocked, and it was a trie probe anyway; the
emoji and Hanja searches already called dictlookup directly. The
request/result channels, sequence numbers, staleness checks and the
second draw per Japanese key are gone; dictqjp fills the candidates
in place. Emit.dict and Lang.dictq only ever triggered lookups for
Vietnamese, which has no dictionary. dictlookup(Lang*, key, out, max)
returns the count. The Hanja lookup no longer pre-checks for a single
syllable; a reading either has an entry or it does not.
This commit is contained in:
2026-08-16 16:02:09 +09:00
parent ebcec3af6b
commit abaea77248
10 changed files with 123 additions and 473 deletions

157
strans.c
View File

@@ -6,10 +6,7 @@ static int visible = 0;
static void *activeowner;
static int activecap;
static Caret caret;
static u32int dictseq;
static int candidatechosen;
static void dictqmap(Im*);
static void dictqjp(Im*);
static void backjp(Im*);
static int maplookup(Trie*, Str*, Str*);
@@ -23,20 +20,19 @@ struct Search
static Search search;
Lang langs[] = {
{LangEN, nil, nil, nil, nil, nil, nil, nil},
{LangJP, "hira", "kanji", transmap, backjp, dictqjp, nil, nil},
{LangJPK, "kata", nil, transmap, backjp, dictqjp, nil, nil},
{LangKO, nil, nil, transko, backko, nil, nil, nil},
{LangHANJA, nil, "hanja", nil, nil, nil, nil, nil},
{LangEMOJI, nil, "emoji", nil, nil, nil, nil, nil},
{LangVI, "telex", nil, transvi, backvi, dictqmap, nil, nil},
{LangEN, nil, nil, nil, nil, nil, nil},
{LangJP, "hira", "kanji", transmap, backjp, nil, nil},
{LangJPK, "kata", nil, transmap, backjp, nil, nil},
{LangKO, nil, nil, transko, backko, nil, nil},
{LangHANJA, nil, "hanja", nil, nil, nil, nil},
{LangEMOJI, nil, "emoji", nil, nil, nil, nil},
{LangVI, "telex", nil, transvi, backvi, nil, nil},
};
int nlang = nelem(langs);
static void
clearkouho(void)
{
dictseq++;
im.nkouho = 0;
im.sel = -1;
candidatechosen = 0;
@@ -144,19 +140,6 @@ impre(Str *s)
*s = im.pre;
}
static void
setkouho(Dictres *res)
{
int i;
clearkouho();
for(i = 0; i < res->nkouho; i++){
im.kouho[i] = res->kouho[i];
im.nkouho++;
}
selectfirst();
}
static void
snapshot(Drawcmd *dc)
{
@@ -210,43 +193,17 @@ reset(void)
clearkouho();
}
/* Kanji candidates for a complete reading. */
static void
dictsend(Im *im, Str *key)
{
Dictreq old, req;
req.key = *key;
req.lang = im->l->lang;
req.seq = dictseq;
impre(&req.pre);
/* imthread is the sole producer; discard every obsolete queued lookup. */
while(channbrecv(dictreqc, &old) > 0)
;
channbsend(dictreqc, &req);
}
static void
dictqmap(Im *im)
{
Str dict;
clearkouho();
if(im->l->map == nil)
return;
if(!mapget(im->l->map, &im->pre, &dict))
return;
dictsend(im, &dict);
}
static void
dictqjp(Im *im)
dictqjp(void)
{
Str reading;
clearkouho();
if(im->l->dict == nil || !jpreading(im, &reading) || reading.n == 0)
if(!jpreading(&im, &reading) || reading.n == 0)
return;
dictsend(im, &reading);
im.nkouho = dictlookup(im.l, &reading, im.kouho, Maxkouho);
selectfirst();
}
static int
@@ -355,7 +312,7 @@ dotrans(Rune c, Str *com)
if(isjp(&im)){
e.eat = transjp(&im, c, com);
if(e.eat)
dictqjp(&im);
dictqjp();
else
clearkouho();
return e.eat;
@@ -380,9 +337,6 @@ dotrans(Rune c, Str *com)
sappend(com, &e.s);
sclear(&im.pre);
sappend(&im.pre, &e.next);
if(e.eat && e.dict.n > 0){
dictsend(&im, &e.dict);
}
return e.eat;
}
@@ -418,13 +372,13 @@ Emit
transmap(Im *im, Rune c)
{
Emit e = {0};
Str key;
Str key, mapped;
Trie *t;
t = im->l->map;
key = im->pre;
sputr(&key, c);
if(maplookup(t, &key, &e.dict)){
if(maplookup(t, &key, &mapped)){
e.eat = 1;
e.next = key;
return e;
@@ -433,7 +387,7 @@ transmap(Im *im, Rune c)
e.s = im->pre;
sclear(&key);
sputr(&key, c);
if(!maplookup(t, &key, &e.dict))
if(!maplookup(t, &key, &mapped))
return e;
e.eat = 1;
sputr(&e.next, c);
@@ -526,40 +480,28 @@ addkouho(Str *s)
im.kouho[im.nkouho++] = *s;
}
static void
searchlookup(int lang, Str *key, Dictres *res)
{
Dictreq req;
req.key = *key;
req.pre = req.key;
req.lang = lang;
req.seq = 0;
dictlookup(&req, res);
}
/* The typed keys and their transliteration are both emoji queries. */
static void
emojiquery(void)
{
static Dictres res;
Str raw, local;
int i, rawhit, localhit;
Str kouho[Maxkouho], raw, local;
int i, n, rawhit, localhit;
raw = search.raw;
foldascii(&raw);
transstr(im.l, &search.raw, &local);
foldascii(&local);
clearkouho();
searchlookup(LangEMOJI, &raw, &res);
rawhit = res.nkouho != 0;
for(i = 0; i < res.nkouho; i++)
addkouho(&res.kouho[i]);
n = dictlookup(getlang(LangEMOJI), &raw, kouho, Maxkouho);
rawhit = n != 0;
for(i = 0; i < n; i++)
addkouho(&kouho[i]);
localhit = 0;
if(scmp(&raw, &local) != 0){
searchlookup(LangEMOJI, &local, &res);
localhit = res.nkouho != 0;
for(i = 0; i < res.nkouho; i++)
addkouho(&res.kouho[i]);
n = dictlookup(getlang(LangEMOJI), &local, kouho, Maxkouho);
localhit = n != 0;
for(i = 0; i < n; i++)
addkouho(&kouho[i]);
}
search.text = rawhit || !localhit ? raw : local;
selectfirst();
@@ -568,16 +510,13 @@ emojiquery(void)
static void
hanjaquery(void)
{
static Dictres res;
Str key;
transstr(im.l, &search.raw, &key);
search.text = key;
if(key.n == 1 && key.r[0] >= 0xac00 && key.r[0] <= 0xd7a3){
searchlookup(LangHANJA, &key, &res);
setkouho(&res);
}else
clearkouho();
clearkouho();
im.nkouho = dictlookup(getlang(LangHANJA), &key, im.kouho, Maxkouho);
selectfirst();
}
static void
@@ -766,8 +705,10 @@ transition(u32int ks, u32int mod, Str *com)
reset();
return 1;
}
if(im.l->dictq != nil)
im.l->dictq(&im);
if(isjp(&im))
dictqjp();
else
clearkouho();
return 1;
}
if(ks == Kesc){
@@ -896,7 +837,6 @@ init(void)
memset(&caret, 0, sizeof caret);
activeowner = nil;
activecap = 0;
dictseq = 0;
candidatechosen = 0;
visible = 0;
}
@@ -1004,41 +944,16 @@ imhandlekey(Keyreq *kr)
chansend(kr->reply, &res);
}
static void
dictresult(Dictres *res)
{
Str pre;
impre(&pre);
if(search.lang || res->seq != dictseq || res->lang != im.l->lang ||
scmp(&res->key, &pre) != 0)
return;
setkouho(res);
redraw();
}
void
imthread(void*)
{
static Dictres res;
Keyreq kr;
Alt alts[] = {
{keyc, &kr, CHANRCV, nil},
{dictresc, &res, CHANRCV, nil},
{nil, nil, CHANEND, nil},
};
threadsetname("im");
init();
for(;;){
switch(alt(alts)){
case 0:
imhandlekey(&kr);
break;
case 1:
dictresult(&res);
break;
}
chanrecv(keyc, &kr);
imhandlekey(&kr);
}
}