engine: no candidate is chosen until the user moves to one; Space converts
A complete Japanese reading showed its candidates with the first row highlighted, yet Enter committed the reading unless the user had moved to a candidate: the highlight lied. Now sel is -1 while nothing is chosen, and it alone says what Enter commits; candidatechosen goes. Every key that ends a composition — Enter, Tab, a language switch, a special key, a modifier chord, typing on — now commits the chosen candidate through one flush; before, only Enter and Tab did, and Ctrl+S after choosing 漢字 committed かんじ. Space in a Japanese mode is the conversion key, as in every other Japanese IME: it steps through the candidates (Shift+Space backwards, both wrapping) and commits a reading that has none, without typing a space. Backspace and Escape on a chosen candidate go back to the reading first. Tab in a search wraps through the same cyclekouho. reset() no longer forgets the caret: a chosen candidate confirmed by typing on would otherwise redraw the next reading at the pointer.
This commit is contained in:
138
strans.c
138
strans.c
@@ -5,7 +5,6 @@ static Im im;
|
||||
static void *activeowner;
|
||||
static int activecap;
|
||||
static Caret caret;
|
||||
static int candidatechosen;
|
||||
static Drawcmd lastdraw;
|
||||
static Emit transjp(Im*, Rune);
|
||||
static void backjp(Im*);
|
||||
@@ -54,12 +53,12 @@ mapget(Trie *t, Str *key, Str *out)
|
||||
return mapmatch(t, key, out) == TrieExact;
|
||||
}
|
||||
|
||||
/* sel is the chosen candidate; -1 while the user has not moved to one. */
|
||||
static void
|
||||
clearkouho(void)
|
||||
{
|
||||
im.nkouho = 0;
|
||||
im.sel = -1;
|
||||
candidatechosen = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -99,7 +98,16 @@ movekouho(int delta)
|
||||
im.sel = 0;
|
||||
if(im.sel >= im.nkouho)
|
||||
im.sel = im.nkouho - 1;
|
||||
candidatechosen = 1;
|
||||
}
|
||||
|
||||
/* Space and Tab step through the candidates and wrap around. */
|
||||
static void
|
||||
cyclekouho(int delta)
|
||||
{
|
||||
if(im.sel < 0)
|
||||
im.sel = delta > 0 ? 0 : im.nkouho - 1;
|
||||
else
|
||||
im.sel = (im.sel + delta + im.nkouho) % im.nkouho;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -230,7 +238,7 @@ redraw(void)
|
||||
channbsend(drawc, &dc);
|
||||
}
|
||||
|
||||
/* Kanji candidates for a complete reading. */
|
||||
/* Kanji candidates for a complete reading; none is chosen yet. */
|
||||
static void
|
||||
dictqjp(void)
|
||||
{
|
||||
@@ -240,7 +248,6 @@ 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);
|
||||
selectfirst();
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -269,12 +276,6 @@ commitim(Im *p, Str *com)
|
||||
sclear(&p->raw);
|
||||
}
|
||||
|
||||
static void
|
||||
commit(Str *com)
|
||||
{
|
||||
commitim(&im, com);
|
||||
}
|
||||
|
||||
static void
|
||||
backjp(Im *p)
|
||||
{
|
||||
@@ -542,10 +543,7 @@ searchlang(Rune c)
|
||||
static void
|
||||
endsearch(void)
|
||||
{
|
||||
search.lang = 0;
|
||||
sclear(&search.seed);
|
||||
sclear(&search.raw);
|
||||
sclear(&search.text);
|
||||
memset(&search, 0, sizeof search);
|
||||
clearkouho();
|
||||
}
|
||||
|
||||
@@ -555,14 +553,23 @@ reset(void)
|
||||
sclear(&im.pre);
|
||||
sclear(&im.raw);
|
||||
endsearch();
|
||||
memset(&caret, 0, sizeof caret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Whatever is pending becomes committed text: the search query, a chosen
|
||||
* candidate, else the reading. Enter does this, and so do a reset and a
|
||||
* lost focus.
|
||||
*/
|
||||
static void
|
||||
commitsearch(Str *com)
|
||||
flush(Str *com)
|
||||
{
|
||||
sappend(com, &search.text);
|
||||
endsearch();
|
||||
if(search.lang)
|
||||
sappend(com, &search.text);
|
||||
else if(im.sel >= 0)
|
||||
sappend(com, &im.kouho[im.sel]);
|
||||
else
|
||||
commitim(&im, com);
|
||||
reset();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -572,36 +579,18 @@ commitsearch(Str *com)
|
||||
static void
|
||||
startsearch(int lang, Str *com)
|
||||
{
|
||||
Str pending;
|
||||
Str seed;
|
||||
|
||||
impre(&im, &pending);
|
||||
if(lang == LangHANJA){
|
||||
sclear(&im.pre);
|
||||
sclear(&im.raw);
|
||||
}else
|
||||
commit(com);
|
||||
commitsearch(com);
|
||||
search.lang = lang;
|
||||
if(lang == LangHANJA){
|
||||
search.seed = pending;
|
||||
searchquery();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Whatever is pending becomes committed text, a moved-to candidate
|
||||
* first: Enter does this, and so do a reset and a lost focus.
|
||||
*/
|
||||
static void
|
||||
flush(Str *com)
|
||||
{
|
||||
if(search.lang)
|
||||
commitsearch(com);
|
||||
else if(candidatechosen && im.sel >= 0 && im.sel < im.nkouho)
|
||||
sappend(com, &im.kouho[im.sel]);
|
||||
sclear(&seed);
|
||||
if(lang == LangHANJA && !search.lang && im.sel < 0)
|
||||
impre(&im, &seed);
|
||||
else
|
||||
commit(com);
|
||||
flush(com);
|
||||
reset();
|
||||
search.lang = lang;
|
||||
search.seed = seed;
|
||||
if(lang == LangHANJA)
|
||||
searchquery();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -630,24 +619,15 @@ searchkey(u32int ks, u32int mod, Str *com)
|
||||
return 1;
|
||||
}
|
||||
if(ks == Ktab){
|
||||
if(im.nkouho == 0)
|
||||
return 1;
|
||||
if(mod & Mshift){
|
||||
if(im.sel <= 0)
|
||||
im.sel = im.nkouho - 1;
|
||||
else
|
||||
im.sel--;
|
||||
}else if(im.sel >= im.nkouho - 1)
|
||||
im.sel = 0;
|
||||
else
|
||||
im.sel++;
|
||||
if(im.nkouho != 0)
|
||||
cyclekouho(mod & Mshift ? -1 : 1);
|
||||
return 1;
|
||||
}
|
||||
if(ks == Kret){
|
||||
if(im.nkouho > 0)
|
||||
picksearch(max(im.sel, 0), com);
|
||||
else
|
||||
commitsearch(com);
|
||||
flush(com);
|
||||
return 1;
|
||||
}
|
||||
if(ks == Kback){
|
||||
@@ -668,7 +648,7 @@ searchkey(u32int ks, u32int mod, Str *com)
|
||||
}
|
||||
if(ks >= Kspec || (ks < ' ' && !(mod & Mctrl)) ||
|
||||
(mod & (Malt|Msuper))){
|
||||
commitsearch(com);
|
||||
flush(com);
|
||||
return 0;
|
||||
}
|
||||
if(mod & Mctrl){
|
||||
@@ -678,11 +658,11 @@ searchkey(u32int ks, u32int mod, Str *com)
|
||||
startsearch(n, com);
|
||||
return 1;
|
||||
}
|
||||
commitsearch(com);
|
||||
flush(com);
|
||||
return n != 0 || setlang(c);
|
||||
}
|
||||
if(search.raw.n >= Maxrunes){
|
||||
commitsearch(com);
|
||||
flush(com);
|
||||
return 0;
|
||||
}
|
||||
sputr(&search.raw, ks);
|
||||
@@ -715,6 +695,15 @@ transition(u32int ks, u32int mod, Str *com)
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(ks == ' ' && isjp(&im) && haspre(&im) && !(mod & ~Mshift)){
|
||||
/* Space converts: it steps through the candidates, or
|
||||
* commits a reading that has none. */
|
||||
if(im.nkouho != 0)
|
||||
cyclekouho(mod & Mshift ? -1 : 1);
|
||||
else
|
||||
flush(com);
|
||||
return 1;
|
||||
}
|
||||
if(ks == Ktab || ks == Kret){
|
||||
if(!haspre(&im))
|
||||
return 0;
|
||||
@@ -725,6 +714,10 @@ transition(u32int ks, u32int mod, Str *com)
|
||||
if(ks == Kback){
|
||||
if(!haspre(&im))
|
||||
return 0;
|
||||
if(im.sel >= 0){
|
||||
im.sel = -1; /* back from the candidate to the reading */
|
||||
return 1;
|
||||
}
|
||||
im.l->back(&im);
|
||||
if(!haspre(&im)){
|
||||
reset();
|
||||
@@ -739,12 +732,14 @@ transition(u32int ks, u32int mod, Str *com)
|
||||
if(ks == Kesc){
|
||||
if(!haspre(&im))
|
||||
return 0;
|
||||
reset();
|
||||
if(im.sel >= 0)
|
||||
im.sel = -1;
|
||||
else
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(ks >= Kspec || (mod & (Malt|Msuper))){
|
||||
commit(com);
|
||||
reset();
|
||||
flush(com);
|
||||
return 0;
|
||||
}
|
||||
if(mod & Mctrl){
|
||||
@@ -754,20 +749,18 @@ transition(u32int ks, u32int mod, Str *com)
|
||||
startsearch(n, com);
|
||||
return 1;
|
||||
}
|
||||
commit(com);
|
||||
reset();
|
||||
flush(com);
|
||||
return setlang(c);
|
||||
}
|
||||
if(ks == '0' && im.nkouho > 0){
|
||||
commit(com);
|
||||
reset();
|
||||
im.sel = -1;
|
||||
flush(com);
|
||||
return 1;
|
||||
}
|
||||
if(ks > 0x7f || ks == ' '){
|
||||
if(!haspre(&im))
|
||||
return 0;
|
||||
commit(com);
|
||||
reset();
|
||||
flush(com);
|
||||
if(com->n >= Maxrunes)
|
||||
return 0;
|
||||
sputr(com, ks);
|
||||
@@ -775,13 +768,15 @@ transition(u32int ks, u32int mod, Str *com)
|
||||
}
|
||||
if(im.l->trans == nil)
|
||||
return 0;
|
||||
if(im.sel >= 0)
|
||||
flush(com); /* typing on takes the chosen candidate */
|
||||
if(im.pre.n >= Maxrunes ||
|
||||
(isjp(&im) && im.pre.n + im.raw.n >= Maxrunes)){
|
||||
/* A full reading commits; a pending romaji syllable stays. */
|
||||
if(isjp(&im))
|
||||
sappend(com, &im.pre);
|
||||
else
|
||||
commit(com);
|
||||
commitim(&im, com);
|
||||
sclear(&im.pre);
|
||||
clearkouho();
|
||||
}
|
||||
@@ -798,7 +793,6 @@ init(void)
|
||||
memset(&caret, 0, sizeof caret);
|
||||
activeowner = nil;
|
||||
activecap = 0;
|
||||
candidatechosen = 0;
|
||||
memset(&lastdraw, 0, sizeof lastdraw);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user