Add support for enabling/disabling utf

There are some ocasions where we want to disable the enconding/decoding of utf8, mainly
because it adds an important overhead. This is partial patch for ESC % G and ESC % @,
where they modified the way that st reads and write from/to the serial line, but it does
not modifies how it interacts with the X window part.
master
Roberto E. Vargas Caballero 2016-09-13 14:01:18 +02:00
parent 078337d745
commit f0e2d28732
1 changed files with 62 additions and 17 deletions

79
st.c
View File

@ -137,6 +137,7 @@ enum term_mode {
MODE_MOUSEMANY = 1 << 18, MODE_MOUSEMANY = 1 << 18,
MODE_BRCKTPASTE = 1 << 19, MODE_BRCKTPASTE = 1 << 19,
MODE_PRINT = 1 << 20, MODE_PRINT = 1 << 20,
MODE_UTF8 = 1 << 21,
MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
|MODE_MOUSEMANY, |MODE_MOUSEMANY,
}; };
@ -158,6 +159,7 @@ enum escape_state {
ESC_ALTCHARSET = 8, ESC_ALTCHARSET = 8,
ESC_STR_END = 16, /* a final string was encountered */ ESC_STR_END = 16, /* a final string was encountered */
ESC_TEST = 32, /* Enter in test mode */ ESC_TEST = 32, /* Enter in test mode */
ESC_UTF8 = 64,
}; };
enum window_state { enum window_state {
@ -412,6 +414,7 @@ static void tfulldirt(void);
static void techo(Rune); static void techo(Rune);
static void tcontrolcode(uchar ); static void tcontrolcode(uchar );
static void tdectest(char ); static void tdectest(char );
static void tdefutf8(char);
static int32_t tdefcolor(int *, int *, int); static int32_t tdefcolor(int *, int *, int);
static void tdeftran(char); static void tdeftran(char);
static inline int match(uint, uint); static inline int match(uint, uint);
@ -1478,17 +1481,29 @@ ttyread(void)
if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
die("Couldn't read from shell: %s\n", strerror(errno)); die("Couldn't read from shell: %s\n", strerror(errno));
/* process every complete utf8 char */
buflen += ret; buflen += ret;
ptr = buf; ptr = buf;
while ((charsize = utf8decode(ptr, &unicodep, buflen))) {
tputc(unicodep);
ptr += charsize;
buflen -= charsize;
}
for (;;) {
if (IS_SET(MODE_UTF8)) {
/* process a complete utf8 char */
charsize = utf8decode(ptr, &unicodep, buflen);
if (charsize == 0)
break;
tputc(unicodep);
ptr += charsize;
buflen -= charsize;
} else {
if (buflen <= 0)
break;
tputc(*ptr++ & 0xFF);
buflen--;
}
}
/* keep any uncomplete utf8 char for the next call */ /* keep any uncomplete utf8 char for the next call */
memmove(buf, ptr, buflen); if (buflen > 0)
memmove(buf, ptr, buflen);
return ret; return ret;
} }
@ -1554,15 +1569,26 @@ void
ttysend(char *s, size_t n) ttysend(char *s, size_t n)
{ {
int len; int len;
char *t, *lim;
Rune u; Rune u;
ttywrite(s, n); ttywrite(s, n);
if (IS_SET(MODE_ECHO)) if (!IS_SET(MODE_ECHO))
while ((len = utf8decode(s, &u, n)) > 0) { return;
techo(u);
n -= len; lim = &s[n];
s += len; for (t = s; t < lim; t += len) {
if (IS_SET(MODE_UTF8)) {
len = utf8decode(t, &u, n);
} else {
u = *t & 0xFF;
len = 1;
} }
if (len <= 0)
break;
techo(u);
n -= len;
}
} }
void void
@ -1656,7 +1682,7 @@ treset(void)
term.tabs[i] = 1; term.tabs[i] = 1;
term.top = 0; term.top = 0;
term.bot = term.row - 1; term.bot = term.row - 1;
term.mode = MODE_WRAP; term.mode = MODE_WRAP|MODE_UTF8;
memset(term.trantbl, CS_USA, sizeof(term.trantbl)); memset(term.trantbl, CS_USA, sizeof(term.trantbl));
term.charset = 0; term.charset = 0;
@ -2689,6 +2715,15 @@ techo(Rune u)
tputc(u); tputc(u);
} }
void
tdefutf8(char ascii)
{
if (ascii == 'G')
term.mode |= MODE_UTF8;
else if (ascii == '@')
term.mode &= ~MODE_UTF8;
}
void void
tdeftran(char ascii) tdeftran(char ascii)
{ {
@ -2851,6 +2886,9 @@ eschandle(uchar ascii)
case '#': case '#':
term.esc |= ESC_TEST; term.esc |= ESC_TEST;
return 0; return 0;
case '%':
term.esc |= ESC_UTF8;
return 0;
case 'P': /* DCS -- Device Control String */ case 'P': /* DCS -- Device Control String */
case '_': /* APC -- Application Program Command */ case '_': /* APC -- Application Program Command */
case '^': /* PM -- Privacy Message */ case '^': /* PM -- Privacy Message */
@ -2930,10 +2968,15 @@ tputc(Rune u)
Glyph *gp; Glyph *gp;
control = ISCONTROL(u); control = ISCONTROL(u);
len = utf8encode(u, c); if (!IS_SET(MODE_UTF8)) {
if (!control && (width = wcwidth(u)) == -1) { c[0] = u;
memcpy(c, "\357\277\275", 4); /* UTF_INVALID */ width = len = 1;
width = 1; } else {
len = utf8encode(u, c);
if (!control && (width = wcwidth(u)) == -1) {
memcpy(c, "\357\277\275", 4); /* UTF_INVALID */
width = 1;
}
} }
if (IS_SET(MODE_PRINT)) if (IS_SET(MODE_PRINT))
@ -2994,6 +3037,8 @@ tputc(Rune u)
csihandle(); csihandle();
} }
return; return;
} else if (term.esc & ESC_UTF8) {
tdefutf8(u);
} else if (term.esc & ESC_ALTCHARSET) { } else if (term.esc & ESC_ALTCHARSET) {
tdeftran(u); tdeftran(u);
} else if (term.esc & ESC_TEST) { } else if (term.esc & ESC_TEST) {