[PATCH 3/4] n_tty: support th, ae and ng runes

From: Adam Borowski
Date: Sat Apr 01 2017 - 05:44:17 EST


Especially 'th' is a prominent letter in Elder Futhark, far more widespread
than 't'. It has survived in English as 'Ã' until a combination of disdain
from Latin-educated scribes and printing presses imported from Germany that
lacked this letter wiped it out.

Alas, we need to maintain a 1:1 relationship to keep alignment, thus you
need to write 'Ã', 'Ã' or 'Å' (or uppercase). Unless you're Icelandic,
it's easiest to use the Compose key.

Signed-off-by: Adam Borowski <kilobyte@xxxxxxxxxx>
---
drivers/tty/n_tty.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index c36b9114f76b..3b8b745eb7cf 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -87,7 +87,7 @@
# define n_tty_trace(f, args...)
#endif

-enum { ESnormal, ESesc, EScsi, ESsetG };
+enum { ESnormal, ESesc, EScsi, ESsetG, ESxc3, ESxc5 };

struct n_tty_data {
/* producer-published */
@@ -404,7 +404,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
static int do_olcuc_char(unsigned char c, struct tty_struct *tty, int space)
{
/* 3 bytes per character */
- static const char *runes = "áááááááááááááááááááááááááá";
+ static const char *runes = "ááááááááááááááááááááááááááááá";
struct n_tty_data *ldata = tty->disc_data;

switch (ldata->vt_state) {
@@ -419,6 +419,31 @@ static int do_olcuc_char(unsigned char c, struct tty_struct *tty, int space)
case ESsetG:
ldata->vt_state = ESnormal;
break;
+ case ESxc3:
+ if (c == 0xbe || c == 0x9e) { /* th */
+ c = 'A' + 26;
+ goto print_rune;
+ } else if (c == 0xa6 || c == 0x86) { /* ae */
+ c = 'A' + 27;
+ goto print_rune;
+ }
+ if (space < 2)
+ return -1;
+ tty_put_char(tty, 0xc3); /* no match, print the stolen prefix */
+ ldata->vt_state = ESnormal;
+ ldata->column++;
+ break;
+ case ESxc5:
+ if (c == 0x8b || c == 0x8a) { /* ng */
+ c = 'A' + 28;
+ goto print_rune;
+ }
+ if (space < 2)
+ return -1;
+ tty_put_char(tty, 0xc5); /* no match, print the stolen prefix */
+ ldata->vt_state = ESnormal;
+ ldata->column++;
+ break;
default:
if (c == '\e') {
ldata->vt_state = ESesc;
@@ -428,8 +453,10 @@ static int do_olcuc_char(unsigned char c, struct tty_struct *tty, int space)
c -= 32;
if (I_IUTF8(tty)) {
if (c >= 'A' && c <= 'Z') {
+print_rune:
if (space < 3)
return -1;
+ ldata->vt_state = ESnormal;
ldata->column++;
c -= 'A';
tty_put_char(tty, runes[3 * c + 0]);
@@ -437,6 +464,10 @@ static int do_olcuc_char(unsigned char c, struct tty_struct *tty, int space)
tty_put_char(tty, runes[3 * c + 2]);
return 1;
}
+ if (c == 0xc3)
+ return ldata->vt_state = ESxc3, 1;
+ if (c == 0xc5)
+ return ldata->vt_state = ESxc5, 1;
}
}
if (!iscntrl(c) && !is_continuation(c, tty))
--
2.11.0