Commit be758139 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] tty utf8 mode

This sounds like a good moment to come with this patch.

This is essentially a five-year-old patch by Bruno Haible.  It
introduces utf8 mode, and the effect it has on erasing input characters.

(Side note - without stty support, this is not very useful, but now
the infrastructure is in place)
parent e5bf4651
......@@ -172,6 +172,16 @@ ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
return n;
}
static inline int is_utf8_continuation(unsigned char c)
{
return (c & 0xc0) == 0x80;
}
static inline int is_continuation(unsigned char c, struct tty_struct *tty)
{
return I_IUTF8(tty) && is_utf8_continuation(c);
}
/*
* Perform OPOST processing. Returns -1 when the output device is
* full and the character must be retried.
......@@ -226,7 +236,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
default:
if (O_OLCUC(tty))
c = toupper(c);
if (!iscntrl(c))
if (!iscntrl(c) && !is_continuation(c, tty))
tty->column++;
break;
}
......@@ -330,7 +340,7 @@ static inline void finish_erasing(struct tty_struct *tty)
static void eraser(unsigned char c, struct tty_struct *tty)
{
enum { ERASE, WERASE, KILL } kill_type;
int head, seen_alnums;
int head, seen_alnums, cnt;
unsigned long flags;
if (tty->read_head == tty->canon_head) {
......@@ -368,8 +378,18 @@ static void eraser(unsigned char c, struct tty_struct *tty)
seen_alnums = 0;
while (tty->read_head != tty->canon_head) {
head = (tty->read_head - 1) & (N_TTY_BUF_SIZE-1);
c = tty->read_buf[head];
head = tty->read_head;
/* erase a single possibly multibyte character */
do {
head = (head - 1) & (N_TTY_BUF_SIZE-1);
c = tty->read_buf[head];
} while (is_continuation(c, tty) && head != tty->canon_head);
/* do not partially erase */
if (is_continuation(c, tty))
break;
if (kill_type == WERASE) {
/* Equivalent to BSD's ALTWERASE. */
if (isalnum(c) || c == '_')
......@@ -377,9 +397,10 @@ static void eraser(unsigned char c, struct tty_struct *tty)
else if (seen_alnums)
break;
}
cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1);
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_head = head;
tty->read_cnt--;
tty->read_cnt -= cnt;
spin_unlock_irqrestore(&tty->read_lock, flags);
if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) {
......@@ -388,7 +409,12 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tty->column++;
tty->erasing = 1;
}
/* if cnt > 1, output a multi-byte character */
echo_char(c, tty);
while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1);
put_char(tty->read_buf[head], tty);
}
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
......@@ -403,7 +429,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
else if (iscntrl(c)) {
if (L_ECHOCTL(tty))
col += 2;
} else
} else if (!is_continuation(c, tty))
col++;
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
......
......@@ -56,12 +56,10 @@ struct termios {
#define ICRNL 0000400
#define IXON 0001000
#define IXOFF 0002000
#if !defined(KERNEL) || defined(__USE_BSD)
/* POSIX.1 doesn't want these... */
# define IXANY 0004000
# define IUCLC 0010000
# define IMAXBEL 0020000
#endif
#define IXANY 0004000
#define IUCLC 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -49,6 +49,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -49,6 +49,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -53,6 +53,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -52,6 +52,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -51,6 +51,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -60,6 +60,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -52,6 +52,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -77,6 +77,7 @@ struct termios {
#define IXANY 0004000 /* Any character will restart after stop. */
#define IXOFF 0010000 /* Enable start/stop input control. */
#define IMAXBEL 0020000 /* Ring bell when input queue is full. */
#define IUTF8 0040000 /* Input is UTF8 */
/* c_oflag bits */
#define OPOST 0000001 /* Perform output processing. */
......
......@@ -52,6 +52,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0040000
#define IUTF8 0100000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -58,6 +58,7 @@ struct termios {
#define IXANY 0004000
#define IUCLC 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -66,6 +66,7 @@ struct termios {
#define IXANY 0004000
#define IUCLC 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -59,6 +59,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -51,6 +51,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -78,6 +78,7 @@ struct termios {
#define IXANY 0x00000800
#define IXOFF 0x00001000
#define IMAXBEL 0x00002000
#define IUTF8 0x00004000
/* c_oflag bits */
#define OPOST 0x00000001
......
......@@ -80,6 +80,7 @@ struct termios {
#define IXANY 0x00000800
#define IXOFF 0x00001000
#define IMAXBEL 0x00002000
#define IUTF8 0x00004000
/* c_oflag bits */
#define OPOST 0x00000001
......
......@@ -52,6 +52,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -51,6 +51,7 @@ struct termios {
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
......
......@@ -184,6 +184,7 @@ struct tty_flip_buffer {
#define I_IXANY(tty) _I_FLAG((tty),IXANY)
#define I_IXOFF(tty) _I_FLAG((tty),IXOFF)
#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL)
#define I_IUTF8(tty) _I_FLAG((tty),IUTF8)
#define O_OPOST(tty) _O_FLAG((tty),OPOST)
#define O_OLCUC(tty) _O_FLAG((tty),OLCUC)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment