fix: normalize Korean shifted input
This commit is contained in:
14
strans.c
14
strans.c
@@ -159,6 +159,8 @@ dictqmap(Im *im)
|
||||
|
||||
clearkouho();
|
||||
show();
|
||||
if(im->l->map == nil)
|
||||
return;
|
||||
if(!mapget(im->l->map, &im->pre, &dict))
|
||||
return;
|
||||
dictsend(im, &dict);
|
||||
@@ -374,6 +376,16 @@ ctrlkey(Rune c)
|
||||
return c;
|
||||
}
|
||||
|
||||
static Rune
|
||||
kokey(Rune c, u32int mod)
|
||||
{
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
if((mod & Mshift) && c >= 'a' && c <= 'z')
|
||||
c -= 'a' - 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
ismodkey(u32int ks)
|
||||
{
|
||||
@@ -694,6 +706,8 @@ keystroke(u32int ks, u32int mod, Str *com)
|
||||
reset();
|
||||
return 1;
|
||||
}
|
||||
if(im.l->lang == LangKO)
|
||||
ks = kokey(ks, mod);
|
||||
n = dotrans(ks, com);
|
||||
show();
|
||||
return n;
|
||||
|
||||
@@ -189,6 +189,63 @@ engine_telex_history_bound(struct ct *t)
|
||||
CT_EQ_INT(t, 0, im.raw.n);
|
||||
}
|
||||
|
||||
void
|
||||
engine_korean_modifiers_and_backspace(struct ct *t)
|
||||
{
|
||||
static const struct {
|
||||
Rune key;
|
||||
char *plain;
|
||||
char *shifted;
|
||||
} cases[] = {
|
||||
{ 'r', "ㄱ", "ㄲ" }, { 'e', "ㄷ", "ㄸ" },
|
||||
{ 'q', "ㅂ", "ㅃ" }, { 't', "ㅅ", "ㅆ" },
|
||||
{ 'w', "ㅈ", "ㅉ" }, { 'o', "ㅐ", "ㅒ" },
|
||||
{ 'p', "ㅔ", "ㅖ" },
|
||||
};
|
||||
Str com;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
init();
|
||||
im.l = getlang(LangKO);
|
||||
sclear(&com);
|
||||
CT_CHECK(t, keystroke(cases[i].key, 0, &com));
|
||||
checkstr(t, "plain Korean key", cases[i].plain, &im.pre);
|
||||
|
||||
init();
|
||||
im.l = getlang(LangKO);
|
||||
sclear(&com);
|
||||
CT_CHECK(t, keystroke(cases[i].key, Mshift, &com));
|
||||
checkstr(t, "shifted Korean key", cases[i].shifted, &im.pre);
|
||||
|
||||
init();
|
||||
im.l = getlang(LangKO);
|
||||
sclear(&com);
|
||||
CT_CHECK(t, keystroke(cases[i].key - 'a' + 'A', 0, &com));
|
||||
checkstr(t, "Caps Lock Korean key", cases[i].plain, &im.pre);
|
||||
|
||||
init();
|
||||
im.l = getlang(LangKO);
|
||||
sclear(&com);
|
||||
CT_CHECK(t, keystroke(cases[i].key, Mshift, &com));
|
||||
checkstr(t, "Shift+Caps Korean key", cases[i].shifted, &im.pre);
|
||||
}
|
||||
|
||||
init();
|
||||
im.l = getlang(LangKO);
|
||||
sclear(&com);
|
||||
if(typekeys(t, "rkr", &com)){
|
||||
checkstr(t, "Korean engine preedit", "각", &im.pre);
|
||||
CT_CHECK(t, keystroke(Kback, 0, &com));
|
||||
checkstr(t, "Korean final backspace", "가", &im.pre);
|
||||
CT_CHECK(t, keystroke(Kback, 0, &com));
|
||||
checkstr(t, "Korean vowel backspace", "ㄱ", &im.pre);
|
||||
CT_CHECK(t, keystroke(Kback, 0, &com));
|
||||
CT_EQ_INT(t, 0, im.pre.n);
|
||||
CT_CHECK(t, !keystroke(Kback, 0, &com));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
engine_language_switch_state(struct ct *t)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
#include "test.h"
|
||||
|
||||
static Str
|
||||
kotrans(char *keys)
|
||||
{
|
||||
Emit e;
|
||||
Im state;
|
||||
Str out;
|
||||
char *p;
|
||||
|
||||
memset(&state, 0, sizeof state);
|
||||
state.l = getlang(LangKO);
|
||||
sclear(&out);
|
||||
for(p = keys; *p != '\0'; p++){
|
||||
e = transko(&state, (uchar)*p);
|
||||
sappend(&out, &e.s);
|
||||
state.pre = e.next;
|
||||
if(!e.eat)
|
||||
sputr(&out, (uchar)*p);
|
||||
}
|
||||
sappend(&out, &state.pre);
|
||||
return out;
|
||||
}
|
||||
|
||||
void
|
||||
korean_sequences(struct ct *t)
|
||||
{
|
||||
@@ -14,39 +36,70 @@ korean_sequences(struct ct *t)
|
||||
{ "Rk", "까" },
|
||||
{ "rk1", "가1" },
|
||||
};
|
||||
Emit e;
|
||||
Im state;
|
||||
Str out;
|
||||
Rune key;
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
memset(&state, 0, sizeof state);
|
||||
state.l = getlang(LangKO);
|
||||
sclear(&out);
|
||||
for(p = cases[i].keys; *p != '\0'; p++){
|
||||
key = (uchar)*p;
|
||||
e = transko(&state, key);
|
||||
sappend(&out, &e.s);
|
||||
state.pre = e.next;
|
||||
if(!e.eat)
|
||||
sputr(&out, key);
|
||||
}
|
||||
sappend(&out, &state.pre);
|
||||
out = kotrans(cases[i].keys);
|
||||
checkstr(t, cases[i].keys, cases[i].want, &out);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
korean_compound_vowels(struct ct *t)
|
||||
{
|
||||
static const struct { char *keys, *want; } cases[] = {
|
||||
{ "hk", "ㅘ" }, { "ho", "ㅙ" }, { "hl", "ㅚ" },
|
||||
{ "nj", "ㅝ" }, { "np", "ㅞ" }, { "nl", "ㅟ" },
|
||||
{ "ml", "ㅢ" },
|
||||
};
|
||||
Str out;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
out = kotrans(cases[i].keys);
|
||||
checkstr(t, cases[i].keys, cases[i].want, &out);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
korean_compound_finals(struct ct *t)
|
||||
{
|
||||
static const struct { char *keys, *want, *split; } cases[] = {
|
||||
{ "rkrt", "갃", "각사" }, { "rksw", "갅", "간자" },
|
||||
{ "rksg", "갆", "간하" }, { "rkfr", "갉", "갈가" },
|
||||
{ "rkfa", "갊", "갈마" }, { "rkfq", "갋", "갈바" },
|
||||
{ "rkft", "갌", "갈사" }, { "rkfx", "갍", "갈타" },
|
||||
{ "rkfv", "갎", "갈파" }, { "rkfg", "갏", "갈하" },
|
||||
{ "rkqt", "값", "갑사" },
|
||||
};
|
||||
char keys[16];
|
||||
Str out;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
out = kotrans(cases[i].keys);
|
||||
checkstr(t, cases[i].keys, cases[i].want, &out);
|
||||
snprint(keys, sizeof keys, "%sk", cases[i].keys);
|
||||
out = kotrans(keys);
|
||||
checkstr(t, keys, cases[i].split, &out);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
korean_backspace(struct ct *t)
|
||||
{
|
||||
static const struct { char *before, *after; } cases[] = {
|
||||
{ "ㄱ", "" },
|
||||
{ "가", "ㄱ" },
|
||||
{ "과", "고" },
|
||||
{ "과", "고" }, { "괘", "고" }, { "괴", "고" },
|
||||
{ "궈", "구" }, { "궤", "구" }, { "귀", "구" },
|
||||
{ "긔", "그" },
|
||||
{ "각", "가" },
|
||||
{ "갃", "각" },
|
||||
{ "갃", "각" }, { "갅", "간" }, { "갆", "간" },
|
||||
{ "갉", "갈" }, { "갊", "갈" }, { "갋", "갈" },
|
||||
{ "갌", "갈" }, { "갍", "갈" }, { "갎", "갈" },
|
||||
{ "갏", "갈" }, { "값", "갑" },
|
||||
};
|
||||
Im state;
|
||||
int i;
|
||||
|
||||
@@ -23,6 +23,8 @@ void trie_exact_prefix_and_duplicate(struct ct*);
|
||||
void production_maps_load(struct ct*);
|
||||
void transmap_states(struct ct*);
|
||||
void korean_sequences(struct ct*);
|
||||
void korean_compound_vowels(struct ct*);
|
||||
void korean_compound_finals(struct ct*);
|
||||
void korean_backspace(struct ct*);
|
||||
void vietnamese_transitions(struct ct*);
|
||||
void vietnamese_backspace(struct ct*);
|
||||
@@ -33,6 +35,7 @@ void engine_selects_visible_candidate(struct ct*);
|
||||
void engine_commit_contract(struct ct*);
|
||||
void engine_language_switch_state(struct ct*);
|
||||
void engine_telex_history_bound(struct ct*);
|
||||
void engine_korean_modifiers_and_backspace(struct ct*);
|
||||
void engine_japanese_readings(struct ct*);
|
||||
void engine_japanese_candidates(struct ct*);
|
||||
void engine_japanese_backspace_and_boundaries(struct ct*);
|
||||
|
||||
@@ -72,6 +72,8 @@ static const struct ct_test tests[] = {
|
||||
{ "map/production-lifecycle", production_maps_load },
|
||||
{ "transmap/states", transmap_states },
|
||||
{ "hangul/sequences", korean_sequences },
|
||||
{ "hangul/compound-vowels", korean_compound_vowels },
|
||||
{ "hangul/compound-finals", korean_compound_finals },
|
||||
{ "hangul/backspace", korean_backspace },
|
||||
{ "telex/transitions", vietnamese_transitions },
|
||||
{ "telex/backspace", vietnamese_backspace },
|
||||
@@ -82,6 +84,7 @@ static const struct ct_test tests[] = {
|
||||
{ "engine/commit-contract", engine_commit_contract },
|
||||
{ "engine/language-switch-state", engine_language_switch_state },
|
||||
{ "engine/telex-history-bound", engine_telex_history_bound },
|
||||
{ "engine/korean-modifiers-backspace", engine_korean_modifiers_and_backspace },
|
||||
{ "engine/japanese-readings", engine_japanese_readings },
|
||||
{ "engine/japanese-candidates", engine_japanese_candidates },
|
||||
{ "engine/japanese-backspace-boundaries", engine_japanese_backspace_and_boundaries },
|
||||
|
||||
Reference in New Issue
Block a user