code: plan9front

Download patch

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);