ref: 8dcf65f21e079f471eef6d3b3d0360c7beac4cd6
parent: 119f35bc702aded0bd57488c275b54872d290bc3
author: Jacob Moody <moody@posixcafe.org>
date: Tue Aug 23 00:53:11 EDT 2022
ktrans: xin chào Add telex Vietnamese input.
--- /dev/null
+++ b/lib/ktrans/telex.map
@@ -1,0 +1,131 @@
+aw ă
+aa â
+dd đ
+ee ê
+oo ô
+ow ơ
+uw ư
+êe ee
+âa aa
+đd dd
+ôo oo
+Af À
+af à
+Ăf Ằ
+ăf ằ
+Âf Ầ
+âf ầ
+Ef È
+ef è
+Êf Ề
+êf ề
+If Ì
+if ì
+Of Ò
+of ò
+Ôf Ồ
+ôf ồ
+Ơf Ờ
+ơf ờ
+Uf Ù
+uf ù
+Ưf Ừ
+ưf ừ
+Yf Ỳ
+yf ỳ
+As Á
+as á
+Ăs Ắ
+ăs ắ
+Âs Ấ
+âs ấ
+Es É
+es é
+Ês Ế
+ês ế
+Is Í
+is í
+Os Ó
+os ó
+Ôs Ố
+ôs ố
+Ơs Ớ
+ơs ớ
+Us Ú
+us ú
+Ưs Ứ
+ưs ứ
+Ys Ý
+ys ý
+Ar Ả
+ar ả
+Ăr Ẳ
+ăr ẳ
+Âr Ẩ
+âr ẩ
+Er Ẻ
+er ẻ
+Êr Ể
+êr ể
+Ir Ỉ
+ir ỉ
+Or Ỏ
+or ỏ
+Ôr Ổ
+ôr ổ
+Ơr Ở
+ơr ở
+Ur Ủ
+ur ủ
+Ưr Ử
+ưr ử
+Yr Ỷ
+yr ỷ
+Ax Ã
+ax ã
+Ăx Ẵ
+ăx ẵ
+Âx Ẫ
+âx ẫ
+Ex Ẽ
+ex ẽ
+Êx Ễ
+êx ễ
+Ix Ĩ
+ix ĩ
+Ox Õ
+ox õ
+Ôx Ỗ
+ôx ỗ
+Ơx Ỡ
+ơx ỡ
+Ux Ũ
+ux ũ
+Ưx Ữ
+ưx ữ
+Yx Ỹ
+yx ỹ
+Aj Ạ
+aj ạ
+Ăj Ặ
+ăj ặ
+Âj Ậ
+âj ậ
+Ej Ẹ
+ej ẹ
+Êj Ệ
+êj ệ
+Ij Ị
+ij ị
+Oj Ọ
+oj ọ
+Ôj Ộ
+ôj ộ
+Ơj Ợ
+ơj ợ
+Uj Ụ
+uj ụ
+Ưj Ự
+ưj ự
+Yj Ỵ
+yj ỵ
--- a/sys/man/1/ktrans
+++ b/sys/man/1/ktrans
@@ -82,6 +82,9 @@
.TP
.B ctl-s
Korean mode. Implicit layer converts latin to Korean Hangul.
+.TP
+.B ctrl-v
+Vietnamese Telex input.
.SH SOURCE
.B /sys/src/cmd/ktrans
.SH SEE ALSO
--- a/sys/src/cmd/ktrans/main.c
+++ b/sys/src/cmd/ktrans/main.c
@@ -43,6 +43,14 @@
return d;
}
+char*
+peekstr(char *s, char *b)
+{
+ while(s > b && (*--s & 0xC0)==Runesync)
+ ;
+ return s;
+}
+
typedef struct Str Str;
struct Str {
char b[128];
@@ -67,9 +75,7 @@
void
popstr(Str *s)
{
- while(s->p > s->b && (*--s->p & 0xC0)==Runesync)
- ;
-
+ s->p = peekstr(s->p, s->b);
s->p[0] = '\0';
}
@@ -190,6 +196,7 @@
LangEL = '', // ^o
LangKO = '', // ^s
LangZH = '', // ^c
+ LangVN = '', // ^v
};
int deflang;
@@ -200,6 +207,7 @@
Hmap *greek;
Hmap *hangul;
Hmap *hanzi, *zidian;
+Hmap *telex;
Hmap **langtab[] = {
[LangEN] &natural,
@@ -209,6 +217,7 @@
[LangEL] &greek,
[LangKO] &hangul,
[LangZH] &hanzi,
+ [LangVN] &telex,
};
char *langcodetab[] = {
@@ -219,6 +228,7 @@
[LangEL] "el",
[LangKO] "ko",
[LangZH] "zh",
+ [LangVN] "vn",
};
int
@@ -433,6 +443,41 @@
}
}
+int
+telexlkup(Str *line, Str *out)
+{
+ Map lkup;
+ char buf[UTFmax*3], *p, *e;
+ int n;
+
+ p = pushutf(buf, buf+sizeof buf, line->b, 1);
+ n = p-buf;
+
+ if(hmapget(telex, buf, &lkup) < 0)
+ return -1;
+
+ assert(lkup.leadstomore == 1);
+ if(utflen(line->b) < 2)
+ return 2;
+
+ e = peekstr(line->p, line->b);
+ pushutf(p, buf+sizeof buf, e, 1);
+ if(hmapget(telex, buf, &lkup) < 0){
+ /* not correct; matches should be allowed to span vowels */
+ if(hmapget(telex, buf+n, &lkup) == 0)
+ line->p = pushutf(line->b, strend(line), buf+n, 0);
+ return 2;
+ }
+
+ out->p = pushutf(out->b, strend(out), lkup.kana, 0);
+ out->p = pushutf(out->p, strend(out), line->b+n, 0);
+ popstr(out);
+
+ if(utflen(lkup.kana) == 2)
+ return 1;
+ return 0;
+}
+
static void
keythread(void*)
{
@@ -440,10 +485,10 @@
Msg m;
Map lkup;
char *p;
- int n;
+ int n, ln, rn;
Rune r;
char peek[UTFmax+1];
- Str line;
+ Str line, tbuf;
int mode;
mode = 0;
@@ -473,6 +518,11 @@
resetstr(&line, nil);
continue;
}
+ if(lang == LangVN && utfrune(" ", r) != nil){
+ resetstr(&line, nil);
+ if(r != ' ')
+ continue;
+ }
if(lang == LangZH || lang == LangJP){
emitutf(dictch, p, 1);
if(utfrune("\n", r) != nil){
@@ -496,6 +546,26 @@
}
line.p = pushutf(line.p, strend(&line), p, 1);
+ if(lang == LangVN){
+ Again:
+ ln = utflen(line.b);
+ switch(rn = telexlkup(&line, &tbuf)){
+ default:
+ resetstr(&line, nil);
+ continue;
+ case 2:
+ continue;
+ case 1:
+ case 0:
+ if(ln > 0)
+ emitutf(output, backspace, ln);
+ emitutf(output, tbuf.b, 0);
+ line.p = pushutf(line.b, strend(&line), tbuf.b, 0);
+ if(rn == 0)
+ goto Again;
+ continue;
+ }
+ }
if(maplkup(lang, line.b, &lkup) < 0){
resetstr(&line, nil);
pushutf(peek, peek + sizeof peek, p, 1);
@@ -634,6 +704,7 @@
greek = openmap("/lib/ktrans/greek.map");
cyril = openmap("/lib/ktrans/cyril.map");
hangul = openmap("/lib/ktrans/hangul.map");
+ telex = openmap("/lib/ktrans/telex.map");
dictch = chancreate(sizeof(Msg), 0);
input = chancreate(sizeof(Msg), 0);