engine: keys outside a map pass on like any other; one candidate query; the caret rides on every key

Space and non-ASCII keys with a Korean or Telex syllable pending were
committed as text along with the syllable, while '.', ',' and digits
committed the syllable and passed on: one path for both now, through the
language's own trans, which commits and passes on.  Japanese Space is
its own key already.

dictqjp() knows which languages have candidates; its two callers no
longer choose between it and clearkouho().  Every request carries its
owner's caret as the frontend knows it, so a Keypress copies it whether
valid or not, and the XIM frontend need not send a Keycaret to say that
its spot went away.
This commit is contained in:
2026-08-17 01:30:56 +09:00
parent 97a838eda1
commit 3d862bdc0d
3 changed files with 20 additions and 41 deletions

View File

@@ -300,14 +300,15 @@ dictqokuri(Str *reading)
} }
} }
/* Kanji candidates for a complete reading; none is chosen yet. */ /* Kanji candidates for a complete Japanese reading; none is chosen yet. */
static void static void
dictqjp(void) dictqjp(void)
{ {
Str reading; Str reading;
clearkouho(); clearkouho();
if(!jpreading(im.l->map, &im.pre, &im.raw, &reading) || reading.n == 0) if(!isjp(&im) || !jpreading(im.l->map, &im.pre, &im.raw, &reading) ||
reading.n == 0)
return; return;
im.nkouho = dictlookup(im.l, &reading, im.kouho, Maxkouho); im.nkouho = dictlookup(im.l, &reading, im.kouho, Maxkouho);
dictqokuri(&reading); dictqokuri(&reading);
@@ -432,10 +433,7 @@ dotrans(Rune c, Str *com)
sappend(com, &e.s); sappend(com, &e.s);
im.pre = e.next; im.pre = e.next;
im.raw = e.raw; im.raw = e.raw;
if(e.eat && isjp(&im)) dictqjp();
dictqjp();
else
clearkouho();
return e.eat; return e.eat;
} }
@@ -821,14 +819,10 @@ transition(u32int ks, u32int mod, Str *com)
return 1; return 1;
} }
im.l->back(&im); im.l->back(&im);
if(!haspre(&im)){ if(haspre(&im))
reset();
return 1;
}
if(isjp(&im))
dictqjp(); dictqjp();
else else
clearkouho(); reset();
return 1; return 1;
} }
if(ks == Kesc){ if(ks == Kesc){
@@ -859,15 +853,6 @@ transition(u32int ks, u32int mod, Str *com)
flush(com); flush(com);
return 1; return 1;
} }
if(ks > 0x7f || ks == ' '){
if(!haspre(&im))
return 0;
flush(com);
if(com->n >= Maxrunes)
return 0;
sputr(com, ks);
return 1;
}
if(im.l->trans == nil) if(im.l->trans == nil)
return 0; return 0;
if(im.sel >= 0) if(im.sel >= 0)
@@ -930,22 +915,21 @@ imhandlekey(Keyreq *kr)
caret = kr->caret; caret = kr->caret;
break; break;
case Keycap: case Keycap:
res.eaten = activeowner != nil && kr->owner == activeowner; res.eaten = kr->owner == activeowner;
if(res.eaten) if(res.eaten)
activecap = kr->cap & Cclientpreedit; activecap = kr->cap & Cclientpreedit;
break; break;
case Keypress: case Keypress:
res.eaten = 0; res.eaten = 0;
if(activeowner != nil && kr->owner == activeowner) if(kr->owner == activeowner)
activecap = kr->cap & Cclientpreedit; activecap = kr->cap & Cclientpreedit;
if(keymeaningful(kr->ks)){ if(keymeaningful(kr->ks)){
if(kr->owner != activeowner){ if(kr->owner != activeowner){
reset(); reset();
activeowner = kr->owner; activeowner = kr->owner;
activecap = kr->cap & Cclientpreedit; activecap = kr->cap & Cclientpreedit;
caret = kr->caret; }
}else if(kr->caret.valid) caret = kr->caret;
caret = kr->caret;
res.eaten = transition(kr->ks, kr->mod, &res.commit); res.eaten = transition(kr->ks, kr->mod, &res.commit);
} }
break; break;

View File

@@ -473,10 +473,9 @@ engine_commit_contract(struct ct *t)
sclear(&com); sclear(&com);
if(!typekeys(t, "ka", &com)) if(!typekeys(t, "ka", &com))
return; return;
CT_CHECK(t, keystroke(0xf008, 0, &com)); /* A key outside the map commits the reading and passes on. */
CT_EQ_INT(t, 2, com.n); CT_CHECK(t, !keystroke(0xf008, 0, &com));
CT_EQ_UINT(t, 0x304b, com.r[0]); checkstr(t, "non-ASCII key commit", "", &com);
CT_EQ_UINT(t, 0xf008, com.r[1]);
CT_EQ_INT(t, 0, im.pre.n); CT_EQ_INT(t, 0, im.pre.n);
} }
@@ -1301,8 +1300,8 @@ engine_japanese_backspace_and_boundaries(struct ct *t)
im.l = getlang(LangJP); im.l = getlang(LangJP);
sclear(&com); sclear(&com);
if(typekeys(t, "kanji", &com)){ if(typekeys(t, "kanji", &com)){
CT_CHECK(t, keystroke(L'', 0, &com)); CT_CHECK(t, !keystroke(L'', 0, &com));
checkstr(t, "real input boundary", "かんじ", &com); checkstr(t, "real input boundary", "かんじ", &com);
} }
init(); init();
@@ -2153,9 +2152,9 @@ engine_full_boundary_passthrough(struct ct *t)
im.pre.r[i] = L''; im.pre.r[i] = L'';
im.pre.n = Maxrunes-1; im.pre.n = Maxrunes-1;
sclear(&com); sclear(&com);
CT_CHECK(t, keystroke(L'', 0, &com)); CT_CHECK(t, !keystroke(L'', 0, &com));
CT_EQ_INT(t, Maxrunes, com.n); CT_EQ_INT(t, Maxrunes-1, com.n);
CT_EQ_UINT(t, L'', com.r[Maxrunes-1]); CT_EQ_INT(t, 0, im.pre.n);
/* Typing on at the limit commits the kana and keeps the syllable. */ /* Typing on at the limit commits the kana and keeps the syllable. */
init(); init();

View File

@@ -385,7 +385,7 @@ kpress(Ic *state, xcb_key_press_event_t *ev)
Keyres res; Keyres res;
char buf[Maxutf]; char buf[Maxutf];
u32int key, sym; u32int key, sym;
int composed, n, wasvalid; int composed, n;
sym = keymaplookup(kstate, ev->detail, ev->state); sym = keymaplookup(kstate, ev->detail, ev->state);
composed = 0; composed = 0;
@@ -403,12 +403,8 @@ kpress(Ic *state, xcb_key_press_event_t *ev)
break; break;
} }
key = ipckeysym(sym, xkb_keysym_to_utf32(sym)); key = ipckeysym(sym, xkb_keysym_to_utf32(sym));
if(keymeaningful(key)){ if(keymeaningful(key))
wasvalid = state->caret.valid;
place(state); place(state);
if(state->engaged && wasvalid && !state->caret.valid)
sendrequest(state, Keycaret, 0, 0, &res);
}
keypress(state, key, ev->state, &res); keypress(state, key, ev->state, &res);
n = stoutf(&res.commit, buf, sizeof buf); n = stoutf(&res.commit, buf, sizeof buf);
commit(state, buf, n); commit(state, buf, n);