engine: use stable candidate pages
This commit is contained in:
@@ -16,9 +16,12 @@ Vietnamese Telex is also available as a compatibility mode.
|
|||||||
| `Ctrl+E` | Emoji and symbol search |
|
| `Ctrl+E` | Emoji and symbol search |
|
||||||
| `Ctrl+H` | One-shot Hanja search |
|
| `Ctrl+H` | One-shot Hanja search |
|
||||||
|
|
||||||
Use `Up`/`Down` to move through candidates, `Enter` or `1`-`9` to select,
|
Use `Up`/`Down` to move through candidates and `PageUp`/`PageDown` to move by
|
||||||
`Tab` to cycle temporary search results, and `Esc` to cancel. `0` commits the
|
nine without wrapping. An unmodified `1`-`9` selects that row on the current
|
||||||
current reading without conversion.
|
page. `Enter` confirms the selection, and `0` commits the current reading
|
||||||
|
without conversion. `Tab` confirms an ordinary candidate; in a temporary
|
||||||
|
Emoji or Hanja search, `Tab` and `Shift-Tab` wrap through the results. `Esc`
|
||||||
|
cancels composition.
|
||||||
|
|
||||||
Hiragana mode composes a complete reading before offering Kanji candidates.
|
Hiragana mode composes a complete reading before offering Kanji candidates.
|
||||||
Katakana mode does not perform Kanji conversion. Emoji and Hanja searches
|
Katakana mode does not perform Kanji conversion. Emoji and Hanja searches
|
||||||
|
|||||||
2
ipc.h
2
ipc.h
@@ -33,6 +33,8 @@ enum
|
|||||||
Kesc = Kspec|0x1b,
|
Kesc = Kspec|0x1b,
|
||||||
Kup = Kspec|0x52,
|
Kup = Kspec|0x52,
|
||||||
Kdown = Kspec|0x54,
|
Kdown = Kspec|0x54,
|
||||||
|
Kpgup = Kspec|0x55,
|
||||||
|
Kpgdown = Kspec|0x56,
|
||||||
Kmodfirst = Kspec|0xe1,
|
Kmodfirst = Kspec|0xe1,
|
||||||
Kmodlast = Kspec|0xee,
|
Kmodlast = Kspec|0xee,
|
||||||
|
|
||||||
|
|||||||
99
strans.c
99
strans.c
@@ -40,6 +40,64 @@ clearkouho(void)
|
|||||||
im.sel = -1;
|
im.sel = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selectfirst(void)
|
||||||
|
{
|
||||||
|
im.sel = im.nkouho > 0 ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pagefirst(void)
|
||||||
|
{
|
||||||
|
if(im.sel < 0)
|
||||||
|
return 0;
|
||||||
|
return im.sel / Maxdisp * Maxdisp;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
movekouho(int delta)
|
||||||
|
{
|
||||||
|
if(im.sel < 0)
|
||||||
|
im.sel = 0;
|
||||||
|
else
|
||||||
|
im.sel += delta;
|
||||||
|
if(im.sel < 0)
|
||||||
|
im.sel = 0;
|
||||||
|
if(im.sel >= im.nkouho)
|
||||||
|
im.sel = im.nkouho - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
numberedkouho(u32int ks, u32int mod)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if(mod != 0 || ks < '1' || ks > '9')
|
||||||
|
return -1;
|
||||||
|
n = pagefirst() + ks - '1';
|
||||||
|
if(n >= im.nkouho)
|
||||||
|
return -1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isjp(Im *p)
|
isjp(Im *p)
|
||||||
{
|
{
|
||||||
@@ -92,6 +150,7 @@ setkouho(Dictres *res)
|
|||||||
im.kouho[i] = res->kouho[i];
|
im.kouho[i] = res->kouho[i];
|
||||||
im.nkouho++;
|
im.nkouho++;
|
||||||
}
|
}
|
||||||
|
selectfirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -112,7 +171,7 @@ show(void)
|
|||||||
!mapget(im.l->map, &pre, &dc.pre))
|
!mapget(im.l->map, &pre, &dc.pre))
|
||||||
dc.pre = pre;
|
dc.pre = pre;
|
||||||
}
|
}
|
||||||
first = im.sel >= Maxdisp ? im.sel - Maxdisp + 1 : 0;
|
first = pagefirst();
|
||||||
n = im.nkouho - first;
|
n = im.nkouho - first;
|
||||||
if(n > Maxdisp) n = Maxdisp;
|
if(n > Maxdisp) n = Maxdisp;
|
||||||
dc.nkouho = n;
|
dc.nkouho = n;
|
||||||
@@ -484,6 +543,7 @@ emojiquery(void)
|
|||||||
addkouho(&res.kouho[i]);
|
addkouho(&res.kouho[i]);
|
||||||
}
|
}
|
||||||
search.text = rawhit || !localhit ? raw : local;
|
search.text = rawhit || !localhit ? raw : local;
|
||||||
|
selectfirst();
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,25 +626,22 @@ picksearch(int n, Str *com)
|
|||||||
static int
|
static int
|
||||||
searchkey(u32int ks, u32int mod, Str *com)
|
searchkey(u32int ks, u32int mod, Str *com)
|
||||||
{
|
{
|
||||||
int n, off;
|
int n;
|
||||||
Rune c;
|
Rune c;
|
||||||
|
|
||||||
if(ismodkey(ks))
|
if(ismodkey(ks))
|
||||||
return 0;
|
return 0;
|
||||||
if(ks == Kdown || ks == Kup){
|
n = movedelta(ks);
|
||||||
|
if(n != 0){
|
||||||
if(im.nkouho == 0)
|
if(im.nkouho == 0)
|
||||||
return 1;
|
return 1;
|
||||||
if(ks == Kdown && im.sel < im.nkouho - 1)
|
movekouho(n);
|
||||||
im.sel++;
|
|
||||||
if(ks == Kup && im.sel > 0)
|
|
||||||
im.sel--;
|
|
||||||
show();
|
show();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
n = ks - '1';
|
n = numberedkouho(ks, mod);
|
||||||
off = im.sel >= Maxdisp ? im.sel - Maxdisp + 1 : 0;
|
if(n >= 0){
|
||||||
if(n >= 0 && n < Maxdisp && off + n < im.nkouho && mod == 0){
|
picksearch(n, com);
|
||||||
picksearch(off + n, com);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(ks == Ktab){
|
if(ks == Ktab){
|
||||||
@@ -655,29 +712,24 @@ searchkey(u32int ks, u32int mod, Str *com)
|
|||||||
static int
|
static int
|
||||||
keystroke(u32int ks, u32int mod, Str *com)
|
keystroke(u32int ks, u32int mod, Str *com)
|
||||||
{
|
{
|
||||||
int n, off;
|
int n;
|
||||||
Rune c;
|
Rune c;
|
||||||
|
|
||||||
if(ismodkey(ks))
|
if(ismodkey(ks))
|
||||||
return 0;
|
return 0;
|
||||||
if(search.lang)
|
if(search.lang)
|
||||||
return searchkey(ks, mod, com);
|
return searchkey(ks, mod, com);
|
||||||
if(ks == Kdown || ks == Kup){
|
n = movedelta(ks);
|
||||||
|
if(n != 0){
|
||||||
if(im.nkouho == 0)
|
if(im.nkouho == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if(ks == Kdown && im.sel < im.nkouho - 1)
|
movekouho(n);
|
||||||
im.sel++;
|
|
||||||
if(ks == Kup && im.sel >= 0)
|
|
||||||
im.sel--;
|
|
||||||
show();
|
show();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
n = ks - '1';
|
n = numberedkouho(ks, mod);
|
||||||
off = 0;
|
if(n >= 0){
|
||||||
if(im.sel >= Maxdisp)
|
sappend(com, &im.kouho[n]);
|
||||||
off = im.sel - Maxdisp + 1;
|
|
||||||
if(n >= 0 && n < Maxdisp && off + n < im.nkouho && mod == 0){
|
|
||||||
sappend(com, &im.kouho[off + n]);
|
|
||||||
reset();
|
reset();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -769,6 +821,7 @@ init(void)
|
|||||||
{
|
{
|
||||||
memset(&im, 0, sizeof(im));
|
memset(&im, 0, sizeof(im));
|
||||||
im.l = getlang(LangEN);
|
im.l = getlang(LangEN);
|
||||||
|
im.sel = -1;
|
||||||
memset(&search, 0, sizeof search);
|
memset(&search, 0, sizeof search);
|
||||||
memset(&caret, 0, sizeof caret);
|
memset(&caret, 0, sizeof caret);
|
||||||
activeowner = nil;
|
activeowner = nil;
|
||||||
|
|||||||
@@ -122,8 +122,9 @@ void
|
|||||||
engine_selects_visible_candidate(struct ct *t)
|
engine_selects_visible_candidate(struct ct *t)
|
||||||
{
|
{
|
||||||
static const struct { int n, sel; Rune key; char *want; } cases[] = {
|
static const struct { int n, sel; Rune key; char *want; } cases[] = {
|
||||||
{ Maxdisp, -1, '9', "c9" },
|
{ Maxdisp, 0, '9', "c9" },
|
||||||
{ Maxdisp+3, Maxdisp+1, '1', "c3" },
|
{ Maxkouho, Maxdisp, '1', "c10" },
|
||||||
|
{ Maxkouho, 2*Maxdisp, '9', "c27" },
|
||||||
};
|
};
|
||||||
char name[8];
|
char name[8];
|
||||||
Str com;
|
Str com;
|
||||||
@@ -147,18 +148,19 @@ engine_selects_visible_candidate(struct ct *t)
|
|||||||
void
|
void
|
||||||
engine_candidate_shortcut_modifiers(struct ct *t)
|
engine_candidate_shortcut_modifiers(struct ct *t)
|
||||||
{
|
{
|
||||||
static u32int mods[] = { Mctrl, Malt, Msuper };
|
static u32int mods[] = { Mshift, Mctrl, Malt, Msuper };
|
||||||
Str com;
|
Str com, selected;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < nelem(mods); i++){
|
for(i = 0; i < nelem(mods); i++){
|
||||||
init();
|
init();
|
||||||
im.kouho[0] = mkstr("must-not-select");
|
im.kouho[9] = mkstr("must-not-select");
|
||||||
im.nkouho = 1;
|
im.nkouho = 10;
|
||||||
im.sel = -1;
|
im.sel = 9;
|
||||||
|
selected = im.kouho[9];
|
||||||
sclear(&com);
|
sclear(&com);
|
||||||
CT_CHECK(t, !keystroke('1', mods[i], &com));
|
CT_CHECK(t, !keystroke('1', mods[i], &com));
|
||||||
CT_CHECK(t, scmp(&com, &im.kouho[0]) != 0);
|
CT_CHECK(t, scmp(&com, &selected) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,8 +399,6 @@ engine_commit_contract(struct ct *t)
|
|||||||
|
|
||||||
init();
|
init();
|
||||||
im.l = getlang(LangJP);
|
im.l = getlang(LangJP);
|
||||||
im.nkouho = 1;
|
|
||||||
im.sel = -1;
|
|
||||||
sclear(&com);
|
sclear(&com);
|
||||||
if(!typekeys(t, "ka", &com))
|
if(!typekeys(t, "ka", &com))
|
||||||
return;
|
return;
|
||||||
@@ -661,6 +661,147 @@ draindraw(Drawcmd *last)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setcandidates(int n)
|
||||||
|
{
|
||||||
|
Dictres res;
|
||||||
|
char name[8];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(&res, 0, sizeof res);
|
||||||
|
for(i = 0; i < n; i++){
|
||||||
|
snprint(name, sizeof name, "c%d", i+1);
|
||||||
|
res.kouho[i] = mkstr(name);
|
||||||
|
}
|
||||||
|
res.nkouho = n;
|
||||||
|
setkouho(&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
candidatebegin(int n)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
draindraw(nil);
|
||||||
|
setcandidates(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
checkcandidatepage(struct ct *t, char *where, int first, int n, int sel)
|
||||||
|
{
|
||||||
|
Drawcmd dc;
|
||||||
|
char want[8];
|
||||||
|
|
||||||
|
show();
|
||||||
|
if(!CT_CHECK(t, draindraw(&dc) > 0))
|
||||||
|
return 0;
|
||||||
|
if(!CT_EQ_INT(t, n, dc.nkouho) || !CT_EQ_INT(t, sel, dc.sel))
|
||||||
|
return 0;
|
||||||
|
if(n == 0)
|
||||||
|
return 1;
|
||||||
|
snprint(want, sizeof want, "c%d", first+1);
|
||||||
|
if(!checkstr(t, where, want, &dc.kouho[0]))
|
||||||
|
return 0;
|
||||||
|
snprint(want, sizeof want, "c%d", first+n);
|
||||||
|
return checkstr(t, where, want, &dc.kouho[n-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
engine_candidate_page_snapshots(struct ct *t)
|
||||||
|
{
|
||||||
|
static int totals[] = { 0, 1, 9, 10, 18, 19, 32 };
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
for(i = 0; i < nelem(totals); i++){
|
||||||
|
candidatebegin(totals[i]);
|
||||||
|
CT_EQ_INT(t, totals[i] == 0 ? -1 : 0, im.sel);
|
||||||
|
if(totals[i] == 0){
|
||||||
|
show();
|
||||||
|
CT_EQ_INT(t, 0, draindraw(nil));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = totals[i] < Maxdisp ? totals[i] : Maxdisp;
|
||||||
|
checkcandidatepage(t, "default candidate page", 0, n, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
engine_candidate_page_movement(struct ct *t)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
int n;
|
||||||
|
int sel;
|
||||||
|
Rune key;
|
||||||
|
int want;
|
||||||
|
} cases[] = {
|
||||||
|
{ 1, 0, Kup, 0 },
|
||||||
|
{ 9, 8, Kdown, 8 },
|
||||||
|
{ 10, 8, Kdown, 9 },
|
||||||
|
{ 10, 9, Kup, 8 },
|
||||||
|
{ 18, 8, Kpgdown, 17 },
|
||||||
|
{ 19, 17, Kdown, 18 },
|
||||||
|
{ 19, 18, Kup, 17 },
|
||||||
|
{ 32, 26, Kdown, 27 },
|
||||||
|
{ 32, 27, Kup, 26 },
|
||||||
|
{ 32, 0, Kpgup, 0 },
|
||||||
|
{ 32, 9, Kpgup, 0 },
|
||||||
|
{ 32, 22, Kpgdown, 31 },
|
||||||
|
{ 32, 31, Kpgup, 22 },
|
||||||
|
{ 32, 31, Kpgdown, 31 },
|
||||||
|
};
|
||||||
|
int first, i, n;
|
||||||
|
Str com;
|
||||||
|
|
||||||
|
for(i = 0; i < nelem(cases); i++){
|
||||||
|
candidatebegin(cases[i].n);
|
||||||
|
im.sel = cases[i].sel;
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke(cases[i].key, 0, &com));
|
||||||
|
CT_EQ_INT(t, cases[i].want, im.sel);
|
||||||
|
first = cases[i].want / Maxdisp * Maxdisp;
|
||||||
|
n = cases[i].n - first;
|
||||||
|
if(n > Maxdisp)
|
||||||
|
n = Maxdisp;
|
||||||
|
checkcandidatepage(t, "moved candidate page", first, n,
|
||||||
|
cases[i].want-first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
engine_candidate_completion(struct ct *t)
|
||||||
|
{
|
||||||
|
Str com;
|
||||||
|
|
||||||
|
candidatebegin(2);
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
|
checkstr(t, "default candidate", "c1", &com);
|
||||||
|
|
||||||
|
candidatebegin(2);
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke(Ktab, 0, &com));
|
||||||
|
checkstr(t, "ordinary Tab candidate", "c1", &com);
|
||||||
|
|
||||||
|
candidatebegin(2);
|
||||||
|
im.pre = mkstr("reading");
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke('0', 0, &com));
|
||||||
|
checkstr(t, "ordinary zero reading", "reading", &com);
|
||||||
|
|
||||||
|
candidatebegin(0);
|
||||||
|
im.pre = mkstr("reading");
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
|
checkstr(t, "Enter without candidates", "reading", &com);
|
||||||
|
|
||||||
|
candidatebegin(32);
|
||||||
|
im.sel = 27;
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, !keystroke('9', 0, &com));
|
||||||
|
checkstr(t, "unavailable short-page digit", "", &com);
|
||||||
|
CT_EQ_INT(t, 32, im.nkouho);
|
||||||
|
CT_EQ_INT(t, 27, im.sel);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setdict(Hmap **dict, char *key, char *val)
|
setdict(Hmap **dict, char *key, char *val)
|
||||||
{
|
{
|
||||||
@@ -888,11 +1029,10 @@ engine_japanese_candidates(struct ct *t)
|
|||||||
dictresult(&res);
|
dictresult(&res);
|
||||||
if(!CT_EQ_INT(t, 2, im.nkouho))
|
if(!CT_EQ_INT(t, 2, im.nkouho))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
checkstr(t, "candidate one", "漢字", &im.kouho[0]);
|
checkstr(t, "candidate one", "漢字", &im.kouho[0]);
|
||||||
checkstr(t, "candidate two", "幹事", &im.kouho[1]);
|
checkstr(t, "candidate two", "幹事", &im.kouho[1]);
|
||||||
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
||||||
CT_EQ_INT(t, 0, im.sel);
|
|
||||||
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
|
||||||
CT_EQ_INT(t, 1, im.sel);
|
CT_EQ_INT(t, 1, im.sel);
|
||||||
CT_CHECK(t, keystroke(Kret, 0, &com));
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
checkstr(t, "selected Kanji", "幹事", &com);
|
checkstr(t, "selected Kanji", "幹事", &com);
|
||||||
@@ -1187,40 +1327,89 @@ engine_emoji_navigation(struct ct *t)
|
|||||||
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
if(typekeys(t, "many", &com)){
|
if(typekeys(t, "many", &com)){
|
||||||
CT_EQ_INT(t, 12, im.nkouho);
|
CT_EQ_INT(t, 12, im.nkouho);
|
||||||
for(i = 0; i < Maxdisp+1; i++)
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
|
for(i = 0; i < Maxdisp; i++)
|
||||||
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
||||||
CT_EQ_INT(t, Maxdisp, im.sel);
|
CT_EQ_INT(t, Maxdisp, im.sel);
|
||||||
CT_CHECK(t, draindraw(&dc) > 0);
|
CT_CHECK(t, draindraw(&dc) > 0);
|
||||||
checkstr(t, "scrolled first row", "c2", &dc.kouho[0]);
|
checkstr(t, "second-page first row", "c10", &dc.kouho[0]);
|
||||||
checkstr(t, "scrolled ninth row", "c10", &dc.kouho[8]);
|
checkstr(t, "second-page last row", "c12", &dc.kouho[2]);
|
||||||
CT_EQ_INT(t, 8, dc.sel);
|
CT_EQ_INT(t, 3, dc.nkouho);
|
||||||
|
CT_EQ_INT(t, 0, dc.sel);
|
||||||
CT_CHECK(t, keystroke('1', 0, &com));
|
CT_CHECK(t, keystroke('1', 0, &com));
|
||||||
checkstr(t, "scrolled row one", "c2", &com);
|
checkstr(t, "second-page row one", "c10", &com);
|
||||||
}
|
}
|
||||||
|
|
||||||
sclear(&com);
|
sclear(&com);
|
||||||
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
if(typekeys(t, "many", &com)){
|
if(typekeys(t, "many", &com)){
|
||||||
for(i = 0; i < 12; i++)
|
for(i = 0; i < 11; i++)
|
||||||
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
||||||
CT_EQ_INT(t, 11, im.sel);
|
CT_EQ_INT(t, 11, im.sel);
|
||||||
CT_CHECK(t, keystroke('9', 0, &com));
|
CT_CHECK(t, keystroke('3', 0, &com));
|
||||||
checkstr(t, "scrolled row nine", "c12", &com);
|
checkstr(t, "short-page row three", "c12", &com);
|
||||||
}
|
}
|
||||||
|
|
||||||
sclear(&com);
|
sclear(&com);
|
||||||
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
if(typekeys(t, "smile", &com)){
|
if(typekeys(t, "smile", &com)){
|
||||||
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
|
CT_CHECK(t, keystroke(Ktab, Mshift, &com));
|
||||||
|
CT_EQ_INT(t, 1, im.sel);
|
||||||
CT_CHECK(t, keystroke(Ktab, 0, &com));
|
CT_CHECK(t, keystroke(Ktab, 0, &com));
|
||||||
CT_EQ_INT(t, 0, im.sel);
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
CT_CHECK(t, keystroke(Kdown, 0, &com));
|
||||||
CT_EQ_INT(t, 1, im.sel);
|
CT_EQ_INT(t, 1, im.sel);
|
||||||
CT_CHECK(t, keystroke(Kup, 0, &com));
|
CT_CHECK(t, keystroke(Kup, 0, &com));
|
||||||
CT_EQ_INT(t, 0, im.sel);
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
CT_CHECK(t, keystroke(Ktab, Mshift, &com));
|
|
||||||
CT_EQ_INT(t, 1, im.sel);
|
|
||||||
CT_CHECK(t, keystroke(Kret, 0, &com));
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
checkstr(t, "navigated candidate", "😄", &com);
|
checkstr(t, "navigated candidate", "😀", &com);
|
||||||
|
}
|
||||||
|
searchend(&f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
engine_search_candidate_keys(struct ct *t)
|
||||||
|
{
|
||||||
|
Searchfix f;
|
||||||
|
Str com;
|
||||||
|
|
||||||
|
emojibegin(&f, 0);
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
|
if(typekeys(t, "smile", &com)){
|
||||||
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
|
checkstr(t, "search default Enter", "😀", &com);
|
||||||
|
}
|
||||||
|
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
|
if(typekeys(t, "missing", &com)){
|
||||||
|
CT_EQ_INT(t, 0, im.nkouho);
|
||||||
|
CT_EQ_INT(t, -1, im.sel);
|
||||||
|
CT_CHECK(t, keystroke(Kret, 0, &com));
|
||||||
|
checkstr(t, "search query Enter", "missing", &com);
|
||||||
|
}
|
||||||
|
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
|
CT_CHECK(t, keystroke('^', Mshift, &com));
|
||||||
|
CT_CHECK(t, keystroke('0', 0, &com));
|
||||||
|
checkstr(t, "search zero query", "^0", &search.text);
|
||||||
|
checkstr(t, "search zero commit", "", &com);
|
||||||
|
CT_CHECK(t, search.lang);
|
||||||
|
CT_CHECK(t, keystroke(Kesc, 0, &com));
|
||||||
|
|
||||||
|
sclear(&com);
|
||||||
|
CT_CHECK(t, keystroke('e', Mctrl, &com));
|
||||||
|
if(typekeys(t, "many", &com)){
|
||||||
|
im.sel = Maxdisp;
|
||||||
|
CT_CHECK(t, keystroke('1', Mshift, &com));
|
||||||
|
checkstr(t, "modified search digit commit", "", &com);
|
||||||
|
checkstr(t, "modified search digit query", "many1", &search.text);
|
||||||
|
CT_CHECK(t, search.lang);
|
||||||
|
CT_CHECK(t, keystroke(Kesc, 0, &com));
|
||||||
}
|
}
|
||||||
searchend(&f);
|
searchend(&f);
|
||||||
}
|
}
|
||||||
@@ -1382,7 +1571,7 @@ engine_emoji_dictionary_identity(struct ct *t)
|
|||||||
res.kouho[0] = mkstr("right");
|
res.kouho[0] = mkstr("right");
|
||||||
dictresult(&res);
|
dictresult(&res);
|
||||||
CT_EQ_INT(t, 1, im.nkouho);
|
CT_EQ_INT(t, 1, im.nkouho);
|
||||||
CT_EQ_INT(t, -1, im.sel);
|
CT_EQ_INT(t, 0, im.sel);
|
||||||
checkstr(t, "matching response accepted", "right", &im.kouho[0]);
|
checkstr(t, "matching response accepted", "right", &im.kouho[0]);
|
||||||
searchend(&f);
|
searchend(&f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ void engine_clears_candidates(struct ct*);
|
|||||||
void engine_backspace_clears_candidates(struct ct*);
|
void engine_backspace_clears_candidates(struct ct*);
|
||||||
void engine_selects_visible_candidate(struct ct*);
|
void engine_selects_visible_candidate(struct ct*);
|
||||||
void engine_candidate_shortcut_modifiers(struct ct*);
|
void engine_candidate_shortcut_modifiers(struct ct*);
|
||||||
|
void engine_candidate_page_snapshots(struct ct*);
|
||||||
|
void engine_candidate_page_movement(struct ct*);
|
||||||
|
void engine_candidate_completion(struct ct*);
|
||||||
void engine_dictionary_queue_latest_wins(struct ct*);
|
void engine_dictionary_queue_latest_wins(struct ct*);
|
||||||
void engine_active_owner_lifecycle(struct ct*);
|
void engine_active_owner_lifecycle(struct ct*);
|
||||||
void engine_active_owner_reset(struct ct*);
|
void engine_active_owner_reset(struct ct*);
|
||||||
@@ -52,6 +55,7 @@ void engine_emoji_queries(struct ct*);
|
|||||||
void engine_emoji_japanese_and_multirune(struct ct*);
|
void engine_emoji_japanese_and_multirune(struct ct*);
|
||||||
void engine_emoji_digit_aliases(struct ct*);
|
void engine_emoji_digit_aliases(struct ct*);
|
||||||
void engine_emoji_navigation(struct ct*);
|
void engine_emoji_navigation(struct ct*);
|
||||||
|
void engine_search_candidate_keys(struct ct*);
|
||||||
void engine_emoji_preedit_languages(struct ct*);
|
void engine_emoji_preedit_languages(struct ct*);
|
||||||
void engine_emoji_start_and_unknown(struct ct*);
|
void engine_emoji_start_and_unknown(struct ct*);
|
||||||
void engine_emoji_dictionary_identity(struct ct*);
|
void engine_emoji_dictionary_identity(struct ct*);
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ static const struct ct_test tests[] = {
|
|||||||
{ "engine/backspace-clears-candidates", engine_backspace_clears_candidates },
|
{ "engine/backspace-clears-candidates", engine_backspace_clears_candidates },
|
||||||
{ "engine/selects-visible-candidate", engine_selects_visible_candidate },
|
{ "engine/selects-visible-candidate", engine_selects_visible_candidate },
|
||||||
{ "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers },
|
{ "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers },
|
||||||
|
{ "engine/candidate-page-snapshots", engine_candidate_page_snapshots },
|
||||||
|
{ "engine/candidate-page-movement", engine_candidate_page_movement },
|
||||||
|
{ "engine/candidate-completion", engine_candidate_completion },
|
||||||
{ "engine/dictionary-queue-latest", engine_dictionary_queue_latest_wins },
|
{ "engine/dictionary-queue-latest", engine_dictionary_queue_latest_wins },
|
||||||
{ "engine/active-owner-lifecycle", engine_active_owner_lifecycle },
|
{ "engine/active-owner-lifecycle", engine_active_owner_lifecycle },
|
||||||
{ "engine/active-owner-reset", engine_active_owner_reset },
|
{ "engine/active-owner-reset", engine_active_owner_reset },
|
||||||
@@ -106,6 +109,7 @@ static const struct ct_test tests[] = {
|
|||||||
{ "engine/emoji-japanese-multirune", engine_emoji_japanese_and_multirune },
|
{ "engine/emoji-japanese-multirune", engine_emoji_japanese_and_multirune },
|
||||||
{ "engine/emoji-digit-aliases", engine_emoji_digit_aliases },
|
{ "engine/emoji-digit-aliases", engine_emoji_digit_aliases },
|
||||||
{ "engine/emoji-navigation", engine_emoji_navigation },
|
{ "engine/emoji-navigation", engine_emoji_navigation },
|
||||||
|
{ "engine/search-candidate-keys", engine_search_candidate_keys },
|
||||||
{ "engine/emoji-preedit-languages", engine_emoji_preedit_languages },
|
{ "engine/emoji-preedit-languages", engine_emoji_preedit_languages },
|
||||||
{ "engine/emoji-start-and-unknown", engine_emoji_start_and_unknown },
|
{ "engine/emoji-start-and-unknown", engine_emoji_start_and_unknown },
|
||||||
{ "engine/emoji-dictionary-identity", engine_emoji_dictionary_identity },
|
{ "engine/emoji-dictionary-identity", engine_emoji_dictionary_identity },
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ xim_adapter_key_contract(struct ct *t)
|
|||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
checkstr(t, "か", &res.preedit);
|
checkstr(t, "か", &res.preedit);
|
||||||
|
|
||||||
keypress(&state, Kspec|0x55, 0, &res);
|
keypress(&state, Kspec|0x57, 0, &res);
|
||||||
nexttrace(t, &f, Keypress, &state);
|
nexttrace(t, &f, Keypress, &state);
|
||||||
CT_CHECK(t, !res.eaten);
|
CT_CHECK(t, !res.eaten);
|
||||||
checkstr(t, "か", &res.commit);
|
checkstr(t, "か", &res.commit);
|
||||||
|
|||||||
Reference in New Issue
Block a user