engine: trim the key dispatch
mapget and maplookup were one trie probe with two predicates; mapmatch returns the match kind and mapget is its exact case. movedelta is a switch. searchkey's modifier test was unreachable behind transition's, searchlang's Alt/Super test behind both callers' earlier returns, and picksearch's range check behind numberedkouho. Korean key folding runs once at the top of transition. commit() on an empty preedit is a no-op, so the Ctrl branch and startsearch lose their haspre guards and repeated commit/reset pairs. Ctrl+language inside a search now commits the shown query as it does elsewhere instead of dropping it. Language ids are documented as the Ctrl codes they are; Im parameters no longer shadow the file's Im.
This commit is contained in:
1
dat.h
1
dat.h
@@ -7,6 +7,7 @@
|
|||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define max(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
|
enum
|
||||||
{
|
{
|
||||||
LangEN = 0x14,
|
LangEN = 0x14,
|
||||||
|
|||||||
158
strans.c
158
strans.c
@@ -9,7 +9,6 @@ static int candidatechosen;
|
|||||||
static Drawcmd lastdraw;
|
static Drawcmd lastdraw;
|
||||||
static Emit transjp(Im*, Rune);
|
static Emit transjp(Im*, Rune);
|
||||||
static void backjp(Im*);
|
static void backjp(Im*);
|
||||||
static int maplookup(Trie*, Str*, Str*);
|
|
||||||
|
|
||||||
typedef struct Search Search;
|
typedef struct Search Search;
|
||||||
struct Search
|
struct Search
|
||||||
@@ -31,6 +30,28 @@ Lang langs[] = {
|
|||||||
};
|
};
|
||||||
int nlang = nelem(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
|
static void
|
||||||
clearkouho(void)
|
clearkouho(void)
|
||||||
{
|
{
|
||||||
@@ -56,18 +77,12 @@ pagefirst(void)
|
|||||||
static int
|
static int
|
||||||
movedelta(u32int ks)
|
movedelta(u32int ks)
|
||||||
{
|
{
|
||||||
static struct {
|
switch(ks){
|
||||||
u32int key;
|
case Kup: return -1;
|
||||||
int delta;
|
case Kdown: return 1;
|
||||||
} move[] = {
|
case Kpgup: return -Maxdisp;
|
||||||
{Kup, -1}, {Kdown, 1},
|
case Kpgdown: return Maxdisp;
|
||||||
{Kpgup, -Maxdisp}, {Kpgdown, Maxdisp},
|
}
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < nelem(move); i++)
|
|
||||||
if(move[i].key == ks)
|
|
||||||
return move[i].delta;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,12 +286,12 @@ commit(Str *com)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
backjp(Im *im)
|
backjp(Im *p)
|
||||||
{
|
{
|
||||||
if(im->raw.n != 0)
|
if(p->raw.n != 0)
|
||||||
spopr(&im->raw);
|
spopr(&p->raw);
|
||||||
else
|
else
|
||||||
spopr(&im->pre);
|
spopr(&p->pre);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -314,7 +329,7 @@ transjp(Im *p, Rune c)
|
|||||||
}
|
}
|
||||||
key = e.raw;
|
key = e.raw;
|
||||||
sputr(&key, c);
|
sputr(&key, c);
|
||||||
if(maplookup(p->l->map, &key, &mapped)){
|
if(mapmatch(p->l->map, &key, &mapped) != TrieMiss){
|
||||||
e.raw = key;
|
e.raw = key;
|
||||||
if(issmalltsu(&mapped)){
|
if(issmalltsu(&mapped)){
|
||||||
sappend(&e.next, &mapped);
|
sappend(&e.next, &mapped);
|
||||||
@@ -327,7 +342,7 @@ transjp(Im *p, Rune c)
|
|||||||
sclear(&e.raw);
|
sclear(&e.raw);
|
||||||
sclear(&key);
|
sclear(&key);
|
||||||
sputr(&key, c);
|
sputr(&key, c);
|
||||||
if(maplookup(p->l->map, &key, &mapped)){
|
if(mapmatch(p->l->map, &key, &mapped) != TrieMiss){
|
||||||
e.raw = key;
|
e.raw = key;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -367,43 +382,30 @@ getlang(int lang)
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/*
|
||||||
maplookup(Trie *t, Str *key, Str *out)
|
* 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.
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Emit
|
Emit
|
||||||
transmap(Im *im, Rune c)
|
transmap(Im *p, Rune c)
|
||||||
{
|
{
|
||||||
Emit e = {0};
|
Emit e = {0};
|
||||||
Str key, mapped;
|
Str key, mapped;
|
||||||
Trie *t;
|
Trie *t;
|
||||||
|
|
||||||
t = im->l->map;
|
t = p->l->map;
|
||||||
key = im->pre;
|
key = p->pre;
|
||||||
sputr(&key, c);
|
sputr(&key, c);
|
||||||
if(maplookup(t, &key, &mapped)){
|
if(mapmatch(t, &key, &mapped) != TrieMiss){
|
||||||
e.eat = 1;
|
e.eat = 1;
|
||||||
e.next = key;
|
e.next = key;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
if(!mapget(t, &im->pre, &e.s))
|
if(!mapget(t, &p->pre, &e.s))
|
||||||
e.s = im->pre;
|
e.s = p->pre;
|
||||||
sclear(&key);
|
sclear(&key);
|
||||||
sputr(&key, c);
|
sputr(&key, c);
|
||||||
if(!maplookup(t, &key, &mapped))
|
if(mapmatch(t, &key, &mapped) == TrieMiss)
|
||||||
return e;
|
return e;
|
||||||
e.eat = 1;
|
e.eat = 1;
|
||||||
sputr(&e.next, c);
|
sputr(&e.next, c);
|
||||||
@@ -533,13 +535,9 @@ searchquery(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
searchlang(Rune c, u32int mod)
|
searchlang(Rune c)
|
||||||
{
|
{
|
||||||
if(mod & (Malt|Msuper))
|
return c == LangEMOJI || c == LangHANJA ? c : 0;
|
||||||
return 0;
|
|
||||||
if(c == LangEMOJI || c == LangHANJA)
|
|
||||||
return c;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -551,17 +549,13 @@ endsearch(void)
|
|||||||
clearkouho();
|
clearkouho();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A search commits any pending composition and takes over the keys. */
|
||||||
static void
|
static void
|
||||||
startsearch(int lang, Str *com)
|
startsearch(int lang, Str *com)
|
||||||
{
|
{
|
||||||
if(haspre(&im))
|
|
||||||
commit(com);
|
commit(com);
|
||||||
sclear(&im.pre);
|
endsearch();
|
||||||
sclear(&im.raw);
|
|
||||||
clearkouho();
|
|
||||||
search.lang = lang;
|
search.lang = lang;
|
||||||
sclear(&search.raw);
|
|
||||||
sclear(&search.text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -571,14 +565,11 @@ commitsearch(Str *com)
|
|||||||
endsearch();
|
endsearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
picksearch(int n, Str *com)
|
picksearch(int n, Str *com)
|
||||||
{
|
{
|
||||||
if(n < 0 || n >= im.nkouho)
|
|
||||||
return 0;
|
|
||||||
sappend(com, &im.kouho[n]);
|
sappend(com, &im.kouho[n]);
|
||||||
endsearch();
|
endsearch();
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -587,8 +578,6 @@ searchkey(u32int ks, u32int mod, Str *com)
|
|||||||
int n;
|
int n;
|
||||||
Rune c;
|
Rune c;
|
||||||
|
|
||||||
if(ismodkey(ks))
|
|
||||||
return 0;
|
|
||||||
n = movedelta(ks);
|
n = movedelta(ks);
|
||||||
if(n != 0){
|
if(n != 0){
|
||||||
if(im.nkouho == 0)
|
if(im.nkouho == 0)
|
||||||
@@ -617,7 +606,8 @@ searchkey(u32int ks, u32int mod, Str *com)
|
|||||||
}
|
}
|
||||||
if(ks == Kret){
|
if(ks == Kret){
|
||||||
if(im.nkouho > 0)
|
if(im.nkouho > 0)
|
||||||
return picksearch(im.sel >= 0 ? im.sel : 0, com);
|
picksearch(max(im.sel, 0), com);
|
||||||
|
else
|
||||||
commitsearch(com);
|
commitsearch(com);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -641,25 +631,21 @@ searchkey(u32int ks, u32int mod, Str *com)
|
|||||||
}
|
}
|
||||||
if(mod & Mctrl){
|
if(mod & Mctrl){
|
||||||
c = ctrlkey(ks);
|
c = ctrlkey(ks);
|
||||||
n = searchlang(c, mod);
|
n = searchlang(c);
|
||||||
if(n != 0){
|
|
||||||
if(n == search.lang)
|
if(n == search.lang)
|
||||||
endsearch();
|
endsearch();
|
||||||
else
|
else if(n != 0)
|
||||||
startsearch(n, com);
|
startsearch(n, com);
|
||||||
return 1;
|
else{
|
||||||
|
commitsearch(com);
|
||||||
|
return setlang(c);
|
||||||
}
|
}
|
||||||
endsearch();
|
|
||||||
if(setlang(c))
|
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if(search.raw.n >= Maxrunes){
|
if(search.raw.n >= Maxrunes){
|
||||||
commitsearch(com);
|
commitsearch(com);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(im.l->lang == LangKO)
|
|
||||||
ks = kokey(ks, mod);
|
|
||||||
sputr(&search.raw, ks);
|
sputr(&search.raw, ks);
|
||||||
searchquery();
|
searchquery();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -673,6 +659,8 @@ transition(u32int ks, u32int mod, Str *com)
|
|||||||
|
|
||||||
if(ismodkey(ks))
|
if(ismodkey(ks))
|
||||||
return 0;
|
return 0;
|
||||||
|
if(im.l->lang == LangKO)
|
||||||
|
ks = kokey(ks, mod);
|
||||||
if(search.lang)
|
if(search.lang)
|
||||||
return searchkey(ks, mod, com);
|
return searchkey(ks, mod, com);
|
||||||
n = movedelta(ks);
|
n = movedelta(ks);
|
||||||
@@ -728,22 +716,14 @@ transition(u32int ks, u32int mod, Str *com)
|
|||||||
}
|
}
|
||||||
if(mod & Mctrl){
|
if(mod & Mctrl){
|
||||||
c = ctrlkey(ks);
|
c = ctrlkey(ks);
|
||||||
n = searchlang(c, mod);
|
n = searchlang(c);
|
||||||
if(n != 0){
|
if(n != 0){
|
||||||
startsearch(n, com);
|
startsearch(n, com);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(getlang(c) != nil){
|
|
||||||
if(haspre(&im))
|
|
||||||
commit(com);
|
commit(com);
|
||||||
reset();
|
reset();
|
||||||
setlang(c);
|
return setlang(c);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(haspre(&im))
|
|
||||||
commit(com);
|
|
||||||
reset();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if(ks == '0' && im.nkouho > 0){
|
if(ks == '0' && im.nkouho > 0){
|
||||||
commit(com);
|
commit(com);
|
||||||
@@ -768,10 +748,7 @@ transition(u32int ks, u32int mod, Str *com)
|
|||||||
reset();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(im.l->lang == LangKO)
|
return dotrans(ks, com);
|
||||||
ks = kokey(ks, mod);
|
|
||||||
n = dotrans(ks, com);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1570,6 +1570,17 @@ engine_emoji_start_and_unknown(struct ct *t)
|
|||||||
CT_EQ_INT(t, LangKO, im.l->lang);
|
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);
|
sclear(&com);
|
||||||
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
for(i = 0; i < Maxrunes; i++)
|
for(i = 0; i < Maxrunes; i++)
|
||||||
|
|||||||
Reference in New Issue
Block a user