diff --git a/dat.h b/dat.h index 1bd5039..25816bf 100644 --- a/dat.h +++ b/dat.h @@ -7,6 +7,7 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) +/* A language id is the control code of the Ctrl key that selects it. */ enum { LangEN = 0x14, diff --git a/strans.c b/strans.c index 93aace9..50beb6b 100644 --- a/strans.c +++ b/strans.c @@ -9,7 +9,6 @@ static int candidatechosen; static Drawcmd lastdraw; static Emit transjp(Im*, Rune); static void backjp(Im*); -static int maplookup(Trie*, Str*, Str*); typedef struct Search Search; struct Search @@ -31,6 +30,28 @@ Lang langs[] = { }; int nlang = nelem(langs); +/* Trie match kind for key; on an exact match out holds the value. */ +static int +mapmatch(Trie *t, Str *key, Str *out) +{ + char *v; + int match, vlen; + + sclear(out); + if(key->n == 0) + return TrieMiss; + match = trielookup(t, key, &v, &vlen); + if(match == TrieExact && !sinit(out, v, vlen)) + return TrieMiss; + return match; +} + +int +mapget(Trie *t, Str *key, Str *out) +{ + return mapmatch(t, key, out) == TrieExact; +} + static void clearkouho(void) { @@ -56,18 +77,12 @@ pagefirst(void) static int movedelta(u32int ks) { - static struct { - u32int key; - int delta; - } move[] = { - {Kup, -1}, {Kdown, 1}, - {Kpgup, -Maxdisp}, {Kpgdown, Maxdisp}, - }; - int i; - - for(i = 0; i < nelem(move); i++) - if(move[i].key == ks) - return move[i].delta; + switch(ks){ + case Kup: return -1; + case Kdown: return 1; + case Kpgup: return -Maxdisp; + case Kpgdown: return Maxdisp; + } return 0; } @@ -271,12 +286,12 @@ commit(Str *com) } static void -backjp(Im *im) +backjp(Im *p) { - if(im->raw.n != 0) - spopr(&im->raw); + if(p->raw.n != 0) + spopr(&p->raw); else - spopr(&im->pre); + spopr(&p->pre); } static int @@ -314,7 +329,7 @@ transjp(Im *p, Rune c) } key = e.raw; sputr(&key, c); - if(maplookup(p->l->map, &key, &mapped)){ + if(mapmatch(p->l->map, &key, &mapped) != TrieMiss){ e.raw = key; if(issmalltsu(&mapped)){ sappend(&e.next, &mapped); @@ -327,7 +342,7 @@ transjp(Im *p, Rune c) sclear(&e.raw); sclear(&key); sputr(&key, c); - if(maplookup(p->l->map, &key, &mapped)){ + if(mapmatch(p->l->map, &key, &mapped) != TrieMiss){ e.raw = key; return e; } @@ -367,43 +382,30 @@ getlang(int lang) return nil; } -static int -maplookup(Trie *t, Str *key, Str *out) -{ - char *v; - int match, vlen; - - sclear(out); - if(key->n == 0) - return 0; - match = trielookup(t, key, &v, &vlen); - if(match == TrieMiss) - return 0; - if(match == TrieExact && !sinit(out, v, vlen)) - return 0; - return 1; -} - +/* + * The pending text is the key sequence itself while it is a prefix of some + * map entry; the map value is what gets shown and committed. + */ Emit -transmap(Im *im, Rune c) +transmap(Im *p, Rune c) { Emit e = {0}; Str key, mapped; Trie *t; - t = im->l->map; - key = im->pre; + t = p->l->map; + key = p->pre; sputr(&key, c); - if(maplookup(t, &key, &mapped)){ + if(mapmatch(t, &key, &mapped) != TrieMiss){ e.eat = 1; e.next = key; return e; } - if(!mapget(t, &im->pre, &e.s)) - e.s = im->pre; + if(!mapget(t, &p->pre, &e.s)) + e.s = p->pre; sclear(&key); sputr(&key, c); - if(!maplookup(t, &key, &mapped)) + if(mapmatch(t, &key, &mapped) == TrieMiss) return e; e.eat = 1; sputr(&e.next, c); @@ -533,13 +535,9 @@ searchquery(void) } static int -searchlang(Rune c, u32int mod) +searchlang(Rune c) { - if(mod & (Malt|Msuper)) - return 0; - if(c == LangEMOJI || c == LangHANJA) - return c; - return 0; + return c == LangEMOJI || c == LangHANJA ? c : 0; } static void @@ -551,17 +549,13 @@ endsearch(void) clearkouho(); } +/* A search commits any pending composition and takes over the keys. */ static void startsearch(int lang, Str *com) { - if(haspre(&im)) - commit(com); - sclear(&im.pre); - sclear(&im.raw); - clearkouho(); + commit(com); + endsearch(); search.lang = lang; - sclear(&search.raw); - sclear(&search.text); } static void @@ -571,14 +565,11 @@ commitsearch(Str *com) endsearch(); } -static int +static void picksearch(int n, Str *com) { - if(n < 0 || n >= im.nkouho) - return 0; sappend(com, &im.kouho[n]); endsearch(); - return 1; } static int @@ -587,8 +578,6 @@ searchkey(u32int ks, u32int mod, Str *com) int n; Rune c; - if(ismodkey(ks)) - return 0; n = movedelta(ks); if(n != 0){ if(im.nkouho == 0) @@ -617,8 +606,9 @@ searchkey(u32int ks, u32int mod, Str *com) } if(ks == Kret){ if(im.nkouho > 0) - return picksearch(im.sel >= 0 ? im.sel : 0, com); - commitsearch(com); + picksearch(max(im.sel, 0), com); + else + commitsearch(com); return 1; } if(ks == Kback){ @@ -641,25 +631,21 @@ searchkey(u32int ks, u32int mod, Str *com) } if(mod & Mctrl){ c = ctrlkey(ks); - n = searchlang(c, mod); - if(n != 0){ - if(n == search.lang) - endsearch(); - else - startsearch(n, com); - return 1; + n = searchlang(c); + if(n == search.lang) + endsearch(); + else if(n != 0) + startsearch(n, com); + else{ + commitsearch(com); + return setlang(c); } - endsearch(); - if(setlang(c)) - return 1; - return 0; + return 1; } if(search.raw.n >= Maxrunes){ commitsearch(com); return 0; } - if(im.l->lang == LangKO) - ks = kokey(ks, mod); sputr(&search.raw, ks); searchquery(); return 1; @@ -673,6 +659,8 @@ transition(u32int ks, u32int mod, Str *com) if(ismodkey(ks)) return 0; + if(im.l->lang == LangKO) + ks = kokey(ks, mod); if(search.lang) return searchkey(ks, mod, com); n = movedelta(ks); @@ -728,22 +716,14 @@ transition(u32int ks, u32int mod, Str *com) } if(mod & Mctrl){ c = ctrlkey(ks); - n = searchlang(c, mod); + n = searchlang(c); if(n != 0){ startsearch(n, com); return 1; } - if(getlang(c) != nil){ - if(haspre(&im)) - commit(com); - reset(); - setlang(c); - return 1; - } - if(haspre(&im)) - commit(com); + commit(com); reset(); - return 0; + return setlang(c); } if(ks == '0' && im.nkouho > 0){ commit(com); @@ -768,10 +748,7 @@ transition(u32int ks, u32int mod, Str *com) reset(); return 0; } - if(im.l->lang == LangKO) - ks = kokey(ks, mod); - n = dotrans(ks, com); - return n; + return dotrans(ks, com); } static void @@ -871,14 +848,3 @@ imthread(void*) } } -int -mapget(Trie *t, Str *key, Str *out) -{ - char *v; - int vlen; - - sclear(out); - if(key->n == 0 || trielookup(t, key, &v, &vlen) != TrieExact) - return 0; - return sinit(out, v, vlen); -} diff --git a/tests/engine_test.c b/tests/engine_test.c index 25ac438..02dc66f 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -1570,6 +1570,17 @@ engine_emoji_start_and_unknown(struct ct *t) CT_EQ_INT(t, LangKO, im.l->lang); } + /* A language switch commits the query like any other pending text. */ + sclear(&com); + CT_CHECK(t, keystroke('e', Mctrl, &com)); + if(typekeys(t, "xy", &com)){ + CT_CHECK(t, keystroke('t', Mctrl, &com)); + checkstr(t, "language switch commits query", "xy", &com); + CT_CHECK(t, !search.lang); + CT_EQ_INT(t, LangEN, im.l->lang); + im.l = getlang(LangKO); + } + sclear(&com); CT_CHECK(t, keystroke('e', Mctrl, &com)); for(i = 0; i < Maxrunes; i++)