[PATCH 2/4] n_tty: use runes rather than uppercase in IUTF8 OLCUC mode

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


It is puzzling why OLCUC support has been added to Linux, despite it being
obsolete for a long long time before Linux was born. The only explanation
I see, as on all-caps displays those were often called "Great Runes" (see
the Jargon File), is that the intention was to support runes but that
wasn't possible before Unicode.

As the kernel's tty discipline knows about UTF-8, that's now possible.

Standards compliance:
Elder Futhark (2nd to 8th centuries), other than:
'y' 'c' are from Anglo-Saxon runes (5th to 11th centuries), 'c' should use
kauna rather than cen but as the former is shared with 'k', I sacrificed
period accuracy for usability.
'q' 'v' 'x' are from Medieval runes (12th to 15th centuries). 'x' could
use Anglo-Saxon eolhx but that's same glyph (and Unicode codepoint) as
Elder Futhark algiz 'z'.

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

diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index bbc9f07c19fa..c36b9114f76b 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -401,8 +401,10 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
* only some commands require lowercase.
*/

-static int do_olcuc_char(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 = "áááááááááááááááááááááááááá";
struct n_tty_data *ldata = tty->disc_data;

switch (ldata->vt_state) {
@@ -418,10 +420,24 @@ static int do_olcuc_char(unsigned char c, struct tty_struct *tty)
ldata->vt_state = ESnormal;
break;
default:
- if (c == '\e')
+ if (c == '\e') {
ldata->vt_state = ESesc;
- else if (c >= 'a' && c <= 'z')
+ break;
+ }
+ if (c >= 'a' && c <= 'z')
c -= 32;
+ if (I_IUTF8(tty)) {
+ if (c >= 'A' && c <= 'Z') {
+ if (space < 3)
+ return -1;
+ ldata->column++;
+ c -= 'A';
+ tty_put_char(tty, runes[3 * c + 0]);
+ tty_put_char(tty, runes[3 * c + 1]);
+ tty_put_char(tty, runes[3 * c + 2]);
+ return 1;
+ }
+ }
}
if (!iscntrl(c) && !is_continuation(c, tty))
ldata->column++;
@@ -500,7 +516,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
break;
default:
if (O_OLCUC(tty))
- return do_olcuc_char(c, tty);
+ return do_olcuc_char(c, tty, space);
if (!iscntrl(c) && !is_continuation(c, tty))
ldata->column++;
break;
--
2.11.0