From 08d0e0fec8f8ec180aa15b70fdca0363aa546b90 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Tue, 18 Aug 2026 16:03:15 +0900 Subject: [PATCH] engine: an okurigana mark does not outlive its kana MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shift on a romaji letter marks where the okurigana begins, and Backspace shortened the reading through im.l->back without clearing the mark. dictqjp only applies a mark that still falls inside the reading, so the stale index lay dormant while the reading was short and fired again the moment it grew back past it: kaKu, Backspace, then nzi offered 噛んじ 兼んじ 漢字 幹事 感じ, where kanzi typed plainly offers 漢字 first. A Backspace edits the reading, so the split marked in it is gone. Co-Authored-By: Claude Opus 5 (1M context) --- strans.c | 1 + tests/engine_test.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/strans.c b/strans.c index 94b6f9f..21d199d 100644 --- a/strans.c +++ b/strans.c @@ -970,6 +970,7 @@ transition(u32int ks, u32int mod, Str *com) else if(ks == Kesc) reset(); else{ + okuriat = -1; /* the mark goes with the kana it marked */ im.l->back(&im); if(haspre(&im)) dictqjp(); diff --git a/tests/engine_test.c b/tests/engine_test.c index 3691c7f..c3b2dd9 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -1277,6 +1277,13 @@ engine_japanese_candidates(struct ct *t) checkstr(t, "then the second", "描く", &im.kouho[1]); checkstr(t, "then the reading's own", "確", &im.kouho[2]); } + /* Backspace edits the reading, so the split it marked is gone. */ + CT_CHECK(t, keystroke(Kback, 0, &com)); + CT_CHECK(t, keystroke('k', 0, &com)); + CT_CHECK(t, keystroke('u', 0, &com)); + if(CT_EQ_INT(t, 3, im.nkouho)) + checkstr(t, "the mark did not outlive its kana", "確", + &im.kouho[0]); CT_CHECK(t, keystroke(Kesc, 0, &com)); setdict(jp->dict, "いt", "言 行"); setdict(jp->dict, "いっt", "言 行");