engine: verbs and adjectives through SKK's okuri-ari entries

A sixth of kanji.dict is SKK's okuri-ari entries, keyed by a stem and
the letter of the okurigana that follows it — かk: 書 描 掛 —, and no
reading ever ends in a letter, so かく offered 確 and 各 but never 書く,
and no verb or adjective could be converted at all.  Now every split of a
complete reading is tried, longest stem first, with the okurigana put
back: かく adds 書く and 描く after the exact candidates, よむ gives
読む, あかい 赤い, おおきい 大きい, いった 言った, かいた 書いた.  A stem
that ends in っ writes it in kana too, so いt and いっt agree.
This commit is contained in:
2026-08-17 01:18:09 +09:00
parent f61f7ab5f8
commit ab0366b7f7
2 changed files with 89 additions and 12 deletions

View File

@@ -110,6 +110,18 @@ cyclekouho(int delta)
im.sel = (im.sel + delta + im.nkouho) % im.nkouho;
}
static void
addkouho(Str *s)
{
int i;
for(i = 0; i < im.nkouho; i++)
if(scmp(&im.kouho[i], s) == 0)
return;
if(im.nkouho < Maxkouho)
im.kouho[im.nkouho++] = *s;
}
static int
numberedkouho(u32int ks, u32int mod)
{
@@ -238,6 +250,56 @@ redraw(void)
channbsend(drawc, &dc);
}
/* SKK's letter for the okurigana a kana begins: its row, or its vowel. */
static Rune
okuriletter(Rune r)
{
static char *rows[] = {
"aあ", "iい", "uう", "eえ", "oお",
"kかきくけこ", "gがぎぐげご", "sさしすせそ", "zざじずぜぞ",
"tたちつてとっ", "dだぢづでど", "nなにぬねのん", "hはひふへほ",
"bばびぶべぼ", "pぱぴぷぺぽ", "mまみむめも", "yやゆよ",
"rらりるれろ", "wわ",
};
int i;
for(i = 0; i < nelem(rows); i++)
if(utfrune(rows[i]+1, r) != nil)
return rows[i][0];
return 0;
}
/*
* SKK keys a verb or adjective by its stem and the letter of the
* okurigana that follows (かk: 書, 描, ...). Every split of the reading
* is tried, longest stem first, and the okurigana is put back; a っ
* ending the stem (いっt: 言, 行) is written in kana too.
*/
static void
dictqokuri(Str *reading)
{
Str key, okuri, kouho[Maxkouho];
Rune c;
int i, j, n;
for(i = reading->n - 1; i > 0; i--){
c = okuriletter(reading->r[i]);
if(c == 0)
continue;
key = *reading;
key.n = i;
sputr(&key, c);
n = dictlookup(im.l, &key, kouho, Maxkouho);
sclear(&okuri);
for(j = i - (reading->r[i-1] == L''); j < reading->n; j++)
sputr(&okuri, reading->r[j]);
for(j = 0; j < n; j++){
sappend(&kouho[j], &okuri);
addkouho(&kouho[j]);
}
}
}
/* Kanji candidates for a complete reading; none is chosen yet. */
static void
dictqjp(void)
@@ -248,6 +310,7 @@ dictqjp(void)
if(!jpreading(im.l->map, &im.pre, &im.raw, &reading) || reading.n == 0)
return;
im.nkouho = dictlookup(im.l, &reading, im.kouho, Maxkouho);
dictqokuri(&reading);
}
static int
@@ -472,18 +535,6 @@ transstr(Lang *l, Str *raw, Str *out)
commitim(&q, out);
}
static void
addkouho(Str *s)
{
int i;
for(i = 0; i < im.nkouho; i++)
if(scmp(&im.kouho[i], s) == 0)
return;
if(im.nkouho < Maxkouho)
im.kouho[im.nkouho++] = *s;
}
/* The typed keys and their transliteration are both emoji queries. */
static void
emojiquery(void)