termptyesc: handle some utf8 control codes

This commit is contained in:
Boris Faure 2018-10-14 11:12:04 +02:00
parent a11c591cce
commit 4c54edaa52
1 changed files with 53 additions and 11 deletions

View File

@ -24,6 +24,7 @@
#define BEL 0x07 // Bell #define BEL 0x07 // Bell
#define ESC 033 // Escape #define ESC 033 // Escape
#define DEL 127 #define DEL 127
#define UTF8CC 0xc2
/* XXX: all handle_ functions return the number of bytes successfully read, 0 /* XXX: all handle_ functions return the number of bytes successfully read, 0
* if not enough bytes could be read * if not enough bytes could be read
@ -1709,7 +1710,7 @@ unhandled:
} }
static int static int
_xterm_arg_get(Eina_Unicode **ptr) _osc_arg_get(Eina_Unicode **ptr)
{ {
Eina_Unicode *b = *ptr; Eina_Unicode *b = *ptr;
int sum = 0; int sum = 0;
@ -1955,7 +1956,7 @@ _handle_xterm_777_command(Termpty *_ty EINA_UNUSED,
} }
static int static int
_handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce) _handle_esc_osc(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
{ {
const Eina_Unicode *cc, *be; const Eina_Unicode *cc, *be;
Eina_Unicode buf[4096], *p; Eina_Unicode buf[4096], *p;
@ -1968,7 +1969,9 @@ _handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
be = buf + sizeof(buf) / sizeof(buf[0]); be = buf + sizeof(buf) / sizeof(buf[0]);
while ((cc < ce) && (*cc != ST) && (*cc != BEL) && (p < be)) while ((cc < ce) && (*cc != ST) && (*cc != BEL) && (p < be))
{ {
if ((cc < ce - 1) && (*cc == ESC) && (*(cc + 1) == '\\')) if ((cc < ce - 1) &&
(((*cc == ESC) && (*(cc + 1) == '\\')) ||
((*cc == UTF8CC) && (*(cc + 1) == ST))))
{ {
cc++; cc++;
break; break;
@ -1979,18 +1982,20 @@ _handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
} }
if (p == be) if (p == be)
{ {
ERR("xterm parsing overflowed, skipping the whole buffer (binary data?)"); ERR("OSC parsing overflowed, skipping the whole buffer (binary data?)");
return cc - c; return cc - c;
} }
*p = 0; *p = '\0';
p = buf; p = buf;
if ((*cc == ST) || (*cc == BEL) || (*cc == '\\')) cc++; if ((*cc == ST) || (*cc == BEL) || (*cc == '\\'))
else return 0; cc++;
else
return 0;
#define TERMPTY_WRITE_STR(_S) \ #define TERMPTY_WRITE_STR(_S) \
termpty_write(ty, _S, strlen(_S)) termpty_write(ty, _S, strlen(_S))
arg = _xterm_arg_get(&p); arg = _osc_arg_get(&p);
switch (arg) switch (arg)
{ {
case -1: case -1:
@ -2202,7 +2207,9 @@ _handle_esc_dcs(Termpty *ty,
be = buf + sizeof(buf) / sizeof(buf[0]); be = buf + sizeof(buf) / sizeof(buf[0]);
while ((cc < ce) && (*cc != ST) && (b < be)) while ((cc < ce) && (*cc != ST) && (b < be))
{ {
if ((cc < ce - 1) && (*cc == ESC) && (*(cc + 1) == '\\')) if ((cc < ce - 1) &&
(((*cc == ESC) && (*(cc + 1) == '\\')) ||
((*cc == UTF8CC) && (*(cc + 1) == ST))))
{ {
cc++; cc++;
break; break;
@ -2305,7 +2312,7 @@ _handle_esc(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
if (len == 0) return 0; if (len == 0) return 0;
return 1 + len; return 1 + len;
case ']': case ']':
len = _handle_esc_xterm(ty, c + 1, ce); len = _handle_esc_osc(ty, c + 1, ce);
if (len == 0) return 0; if (len == 0) return 0;
return 1 + len; return 1 + len;
case '}': case '}':
@ -2428,6 +2435,32 @@ _handle_esc(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
return 0; return 0;
} }
static int
_handle_utf8_control_code(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
{
int len = ce - c;
if (len < 1)
return 0;
DBG("c0 utf8: '%s' (0x%02x)", _safechar(c[0]), c[0]);
switch (c[0])
{
case 0x9b:
len = _handle_esc_csi(ty, c + 1, ce);
if (len == 0) return 0;
return 1 + len;
case 0x9d:
len = _handle_esc_osc(ty, c + 1, ce);
if (len == 0) return 0;
return 1 + len;
default:
WRN("Unhandled utf8 control code '%s' (0x%02x)", _safechar(c[0]), (unsigned int) c[0]);
return 1;
}
return 0;
}
/* XXX: ce is excluded */ /* XXX: ce is excluded */
int int
termpty_handle_seq(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce) termpty_handle_seq(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
@ -2500,6 +2533,14 @@ termpty_handle_seq(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
len++; len++;
goto end; goto end;
} }
else if (c[0] == UTF8CC)
{
len = _handle_utf8_control_code(ty, c + 1, ce);
if (len == 0)
goto end;
len++;
goto end;
}
else if ((ty->block.expecting) && (ty->block.on)) else if ((ty->block.expecting) && (ty->block.on))
{ {
Termexp *ex; Termexp *ex;
@ -2540,7 +2581,8 @@ termpty_handle_seq(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
} }
cc = (Eina_Unicode *)c; cc = (Eina_Unicode *)c;
DBG("txt: ["); DBG("txt: [");
while ((cc < ce) && (*cc >= 0x20) && (*cc != 0x7f)) while ((cc < ce) && (*cc >= 0x20) && (*cc != 0x7f) && (*cc != 0x9b)
&& (*cc != UTF8CC))
{ {
DBG("%s", _safechar(*cc)); DBG("%s", _safechar(*cc));
cc++; cc++;