termpty: better handle ';' in escape sequences. Closes T7475

This commit is contained in:
Boris Faure 2018-11-19 23:12:00 +01:00
parent 15ec4cb8d4
commit 3f432544df
1 changed files with 298 additions and 291 deletions

View File

@ -104,9 +104,11 @@ _csi_arg_get(Eina_Unicode **ptr)
*ptr = b; *ptr = b;
return -1; return -1;
} }
if (*b == '\0')
if (!*b) {
goto error; *ptr = NULL;
return -1;
}
while ((*b >= '0') && (*b <= '9')) while ((*b >= '0') && (*b <= '9'))
{ {
@ -119,15 +121,21 @@ _csi_arg_get(Eina_Unicode **ptr)
if (*b == ';') if (*b == ';')
{ {
b++; if (b[1])
b++;
*ptr = b;
} }
else if (*b == '\0')
*ptr = b; {
*ptr = NULL;
}
else
*ptr = b;
return sum; return sum;
error: error:
*ptr = NULL; *ptr = NULL;
return -1; return -2;
} }
static void static void
@ -645,10 +653,10 @@ _handle_esc_csi_truecolor_cmyk(Termpty *ty, Eina_Unicode **ptr)
} }
static void static void
_handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr) _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr,
const Eina_Unicode * const end)
{ {
Eina_Unicode *b = *ptr; Eina_Unicode *b = *ptr;
int first = 1;
if (b && (*b == '>')) if (b && (*b == '>'))
{ // key resources used by xterm { // key resources used by xterm
@ -656,296 +664,293 @@ _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr)
return; return;
} }
DBG("color set"); DBG("color set");
while (b) while (b && b <= end)
{ {
int arg = _csi_arg_get(&b); int arg = _csi_arg_get(&b);
if ((first) && (!b)) DBG("arg=%d b:%p", arg, b);
termpty_reset_att(&(ty->termstate.att)); switch (arg)
else if (b)
{ {
first = 0; case -1:
switch (arg) EINA_FALLTHROUGH;
{ case 0: // reset to normal
case 0: // reset to normal termpty_reset_att(&(ty->termstate.att));
termpty_reset_att(&(ty->termstate.att)); break;
break; case 1: // bold/bright
case 1: // bold/bright ty->termstate.att.bold = 1;
ty->termstate.att.bold = 1; break;
break; case 2: // faint
case 2: // faint ty->termstate.att.faint = 1;
ty->termstate.att.faint = 1; break;
break; case 3: // italic
case 3: // italic ty->termstate.att.italic = 1;
ty->termstate.att.italic = 1; break;
break; case 4: // underline
case 4: // underline ty->termstate.att.underline = 1;
ty->termstate.att.underline = 1; break;
break; case 5: // blink
case 5: // blink ty->termstate.att.blink = 1;
ty->termstate.att.blink = 1; break;
break; case 6: // blink rapid
case 6: // blink rapid ty->termstate.att.blink2 = 1;
ty->termstate.att.blink2 = 1; break;
break; case 7: // reverse
case 7: // reverse ty->termstate.att.inverse = 1;
ty->termstate.att.inverse = 1; break;
break; case 8: // invisible
case 8: // invisible ty->termstate.att.invisible = 1;
ty->termstate.att.invisible = 1; break;
break; case 9: // strikethrough
case 9: // strikethrough ty->termstate.att.strike = 1;
ty->termstate.att.strike = 1; break;
break; case 20: // fraktur!
case 20: // fraktur! ty->termstate.att.fraktur = 1;
ty->termstate.att.fraktur = 1; break;
break; case 21: // no bold/bright
case 21: // no bold/bright ty->termstate.att.bold = 0;
ty->termstate.att.bold = 0; break;
break; case 22: // no bold/bright, no faint
case 22: // no bold/bright, no faint ty->termstate.att.bold = 0;
ty->termstate.att.bold = 0; ty->termstate.att.faint = 0;
ty->termstate.att.faint = 0; break;
break; case 23: // no italic, not fraktur
case 23: // no italic, not fraktur ty->termstate.att.italic = 0;
ty->termstate.att.italic = 0; ty->termstate.att.fraktur = 0;
ty->termstate.att.fraktur = 0; break;
break; case 24: // no underline
case 24: // no underline ty->termstate.att.underline = 0;
ty->termstate.att.underline = 0; break;
break; case 25: // no blink
case 25: // no blink ty->termstate.att.blink = 0;
ty->termstate.att.blink = 0; ty->termstate.att.blink2 = 0;
ty->termstate.att.blink2 = 0; break;
break; case 27: // no reverse
case 27: // no reverse ty->termstate.att.inverse = 0;
ty->termstate.att.inverse = 0; break;
break; case 28: // no invisible
case 28: // no invisible ty->termstate.att.invisible = 0;
ty->termstate.att.invisible = 0; break;
break; case 29: // no strikethrough
case 29: // no strikethrough ty->termstate.att.strike = 0;
ty->termstate.att.strike = 0; break;
break; case 30: // fg
case 30: // fg case 31:
case 31: case 32:
case 32: case 33:
case 33: case 34:
case 34: case 35:
case 35: case 36:
case 36: case 37:
case 37: ty->termstate.att.fg256 = 0;
ty->termstate.att.fg256 = 0; ty->termstate.att.fg = (arg - 30) + COL_BLACK;
ty->termstate.att.fg = (arg - 30) + COL_BLACK; ty->termstate.att.fgintense = 0;
ty->termstate.att.fgintense = 0; break;
break; case 38: // xterm 256 fg color ???
case 38: // xterm 256 fg color ??? arg = _csi_arg_get(&b);
arg = _csi_arg_get(&b); switch (arg)
switch (arg) {
{ case 1:
case 1: ty->termstate.att.fg256 = 0;
ty->termstate.att.fg256 = 0; ty->termstate.att.fg = COL_INVIS;
ty->termstate.att.fg = COL_INVIS; break;
break; case 2:
case 2: ty->termstate.att.fg256 = 1;
ty->termstate.att.fg =
_handle_esc_csi_truecolor_rgb(ty, &b);
DBG("truecolor RGB fg: approximation got color %d",
ty->termstate.att.fg);
break;
case 3:
ty->termstate.att.fg256 = 1;
ty->termstate.att.fg =
_handle_esc_csi_truecolor_cmy(ty, &b);
DBG("truecolor CMY fg: approximation got color %d",
ty->termstate.att.fg);
break;
case 4:
ty->termstate.att.fg256 = 1;
ty->termstate.att.fg =
_handle_esc_csi_truecolor_cmyk(ty, &b);
DBG("truecolor CMYK fg: approximation got color %d",
ty->termstate.att.fg);
break;
case 5:
// then get next arg - should be color index 0-255
arg = _csi_arg_get(&b);
if (!b) ERR("Failed xterm 256 color fg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid fg color %d", arg);
else
{
ty->termstate.att.fg256 = 1; ty->termstate.att.fg256 = 1;
ty->termstate.att.fg = ty->termstate.att.fg = arg;
_handle_esc_csi_truecolor_rgb(ty, &b); }
DBG("truecolor RGB fg: approximation got color %d", break;
ty->termstate.att.fg); default:
break; ERR("Failed xterm 256 color fg (got %d)", arg);
case 3: }
ty->termstate.att.fg256 = 1; ty->termstate.att.fgintense = 0;
ty->termstate.att.fg = break;
_handle_esc_csi_truecolor_cmy(ty, &b); case 39: // default fg color
DBG("truecolor CMY fg: approximation got color %d", ty->termstate.att.fg256 = 0;
ty->termstate.att.fg); ty->termstate.att.fg = COL_DEF;
break; ty->termstate.att.fgintense = 0;
case 4: break;
ty->termstate.att.fg256 = 1; case 40: // bg
ty->termstate.att.fg = case 41:
_handle_esc_csi_truecolor_cmyk(ty, &b); case 42:
DBG("truecolor CMYK fg: approximation got color %d", case 43:
ty->termstate.att.fg); case 44:
break; case 45:
case 5: case 46:
// then get next arg - should be color index 0-255 case 47:
arg = _csi_arg_get(&b); ty->termstate.att.bg256 = 0;
if (!b) ERR("Failed xterm 256 color fg esc val"); ty->termstate.att.bg = (arg - 40) + COL_BLACK;
else if (arg < 0 || arg > 255) ty->termstate.att.bgintense = 0;
ERR("Invalid fg color %d", arg); break;
else case 48: // xterm 256 bg color ???
{ arg = _csi_arg_get(&b);
ty->termstate.att.fg256 = 1; switch (arg)
ty->termstate.att.fg = arg; {
} case 1:
break; ty->termstate.att.bg256 = 0;
default: ty->termstate.att.bg = COL_INVIS;
ERR("Failed xterm 256 color fg (got %d)", arg); break;
} case 2:
ty->termstate.att.fgintense = 0; ty->termstate.att.bg256 = 1;
break; ty->termstate.att.bg =
case 39: // default fg color _handle_esc_csi_truecolor_rgb(ty, &b);
ty->termstate.att.fg256 = 0; DBG("truecolor RGB bg: approximation got color %d",
ty->termstate.att.fg = COL_DEF; ty->termstate.att.bg);
ty->termstate.att.fgintense = 0; break;
break; case 3:
case 40: // bg ty->termstate.att.bg256 = 1;
case 41: ty->termstate.att.bg =
case 42: _handle_esc_csi_truecolor_cmy(ty, &b);
case 43: DBG("truecolor CMY bg: approximation got color %d",
case 44: ty->termstate.att.bg);
case 45: break;
case 46: case 4:
case 47: ty->termstate.att.bg256 = 1;
ty->termstate.att.bg256 = 0; ty->termstate.att.bg =
ty->termstate.att.bg = (arg - 40) + COL_BLACK; _handle_esc_csi_truecolor_cmyk(ty, &b);
ty->termstate.att.bgintense = 0; DBG("truecolor CMYK bg: approximation got color %d",
break; ty->termstate.att.bg);
case 48: // xterm 256 bg color ??? break;
case 5:
// then get next arg - should be color index 0-255
arg = _csi_arg_get(&b);
if (!b) ERR("Failed xterm 256 color bg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid bg color %d", arg);
else
{
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg = arg;
}
break;
default:
ERR("Failed xterm 256 color bg (got %d)", arg);
}
ty->termstate.att.bgintense = 0;
break;
case 49: // default bg color
ty->termstate.att.bg256 = 0;
ty->termstate.att.bg = COL_DEF;
ty->termstate.att.bgintense = 0;
break;
case 51:
WRN("TODO: support SGR 51 - framed attribute");
ty->termstate.att.framed = 1;
break;
case 52:
ty->termstate.att.encircled = 1;
break;
case 53:
WRN("TODO: support SGR 51 - overlined attribute");
ty->termstate.att.overlined = 1;
break;
case 54:
ty->termstate.att.framed = 0;
ty->termstate.att.encircled = 0;
break;
case 55:
ty->termstate.att.overlined = 0;
break;
case 90: // fg
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
ty->termstate.att.fg256 = 0;
ty->termstate.att.fg = (arg - 90) + COL_BLACK;
ty->termstate.att.fgintense = 1;
break;
case 98: // xterm 256 fg color ???
// now check if next arg is 5
arg = _csi_arg_get(&b);
if (arg != 5) ERR("Failed xterm 256 color fg esc 5 (got %d)", arg);
else
{
// then get next arg - should be color index 0-255
arg = _csi_arg_get(&b); arg = _csi_arg_get(&b);
switch (arg) if (!b) ERR("Failed xterm 256 color fg esc val");
{ else if (arg < 0 || arg > 255)
case 1: ERR("Invalid fg color %d", arg);
ty->termstate.att.bg256 = 0;
ty->termstate.att.bg = COL_INVIS;
break;
case 2:
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg =
_handle_esc_csi_truecolor_rgb(ty, &b);
DBG("truecolor RGB bg: approximation got color %d",
ty->termstate.att.bg);
break;
case 3:
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg =
_handle_esc_csi_truecolor_cmy(ty, &b);
DBG("truecolor CMY bg: approximation got color %d",
ty->termstate.att.bg);
break;
case 4:
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg =
_handle_esc_csi_truecolor_cmyk(ty, &b);
DBG("truecolor CMYK bg: approximation got color %d",
ty->termstate.att.bg);
break;
case 5:
// then get next arg - should be color index 0-255
arg = _csi_arg_get(&b);
if (!b) ERR("Failed xterm 256 color bg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid bg color %d", arg);
else
{
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg = arg;
}
break;
default:
ERR("Failed xterm 256 color bg (got %d)", arg);
}
ty->termstate.att.bgintense = 0;
break;
case 49: // default bg color
ty->termstate.att.bg256 = 0;
ty->termstate.att.bg = COL_DEF;
ty->termstate.att.bgintense = 0;
break;
case 51:
WRN("TODO: support SGR 51 - framed attribute");
ty->termstate.att.framed = 1;
break;
case 52:
ty->termstate.att.encircled = 1;
break;
case 53:
WRN("TODO: support SGR 51 - overlined attribute");
ty->termstate.att.overlined = 1;
break;
case 54:
ty->termstate.att.framed = 0;
ty->termstate.att.encircled = 0;
break;
case 55:
ty->termstate.att.overlined = 0;
break;
case 90: // fg
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
ty->termstate.att.fg256 = 0;
ty->termstate.att.fg = (arg - 90) + COL_BLACK;
ty->termstate.att.fgintense = 1;
break;
case 98: // xterm 256 fg color ???
// now check if next arg is 5
arg = _csi_arg_get(&b);
if (arg != 5) ERR("Failed xterm 256 color fg esc 5 (got %d)", arg);
else else
{ {
// then get next arg - should be color index 0-255 ty->termstate.att.fg256 = 1;
arg = _csi_arg_get(&b); ty->termstate.att.fg = arg;
if (!b) ERR("Failed xterm 256 color fg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid fg color %d", arg);
else
{
ty->termstate.att.fg256 = 1;
ty->termstate.att.fg = arg;
}
} }
ty->termstate.att.fgintense = 1; }
break; ty->termstate.att.fgintense = 1;
case 99: // default fg color break;
ty->termstate.att.fg256 = 0; case 99: // default fg color
ty->termstate.att.fg = COL_DEF; ty->termstate.att.fg256 = 0;
ty->termstate.att.fgintense = 1; ty->termstate.att.fg = COL_DEF;
break; ty->termstate.att.fgintense = 1;
case 100: // bg break;
case 101: case 100: // bg
case 102: case 101:
case 103: case 102:
case 104: case 103:
case 105: case 104:
case 106: case 105:
case 107: case 106:
ty->termstate.att.bg256 = 0; case 107:
ty->termstate.att.bg = (arg - 100) + COL_BLACK; ty->termstate.att.bg256 = 0;
ty->termstate.att.bgintense = 1; ty->termstate.att.bg = (arg - 100) + COL_BLACK;
break; ty->termstate.att.bgintense = 1;
case 108: // xterm 256 bg color ??? break;
// now check if next arg is 5 case 108: // xterm 256 bg color ???
// now check if next arg is 5
arg = _csi_arg_get(&b);
if (arg != 5) ERR("Failed xterm 256 color bg esc 5 (got %d)", arg);
else
{
// then get next arg - should be color index 0-255
arg = _csi_arg_get(&b); arg = _csi_arg_get(&b);
if (arg != 5) ERR("Failed xterm 256 color bg esc 5 (got %d)", arg); if (!b) ERR("Failed xterm 256 color bg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid bg color %d", arg);
else else
{ {
// then get next arg - should be color index 0-255 ty->termstate.att.bg256 = 1;
arg = _csi_arg_get(&b); ty->termstate.att.bg = arg;
if (!b) ERR("Failed xterm 256 color bg esc val");
else if (arg < 0 || arg > 255)
ERR("Invalid bg color %d", arg);
else
{
ty->termstate.att.bg256 = 1;
ty->termstate.att.bg = arg;
}
} }
ty->termstate.att.bgintense = 1; }
break; ty->termstate.att.bgintense = 1;
case 109: // default bg color break;
ty->termstate.att.bg256 = 0; case 109: // default bg color
ty->termstate.att.bg = COL_DEF; ty->termstate.att.bg256 = 0;
ty->termstate.att.bgintense = 1; ty->termstate.att.bg = COL_DEF;
break; ty->termstate.att.bgintense = 1;
default: // not handled??? break;
WRN("Unhandled color cmd [%i]", arg); default: // not handled???
break; WRN("Unhandled color cmd [%i]", arg);
} break;
} }
} }
} }
@ -1255,8 +1260,9 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
ERR("csi parsing overflowed, skipping the whole buffer (binary data?)"); ERR("csi parsing overflowed, skipping the whole buffer (binary data?)");
return cc - c; return cc - c;
} }
if (cc == ce) return 0; if (cc == ce)
*b = 0; return 0;
*b = '\0';
be = b; be = b;
b = buf; b = buf;
DBG(" CSI: '%s' args '%s'", _safechar(*cc), (char *) buf); DBG(" CSI: '%s' args '%s'", _safechar(*cc), (char *) buf);
@ -1284,7 +1290,8 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
case 'A': // cursor up N (CUU) case 'A': // cursor up N (CUU)
CUU: CUU:
arg = _csi_arg_get(&b); arg = _csi_arg_get(&b);
if (arg < 1) arg = 1; if (arg < 1)
arg = 1;
DBG("cursor up %d", arg); DBG("cursor up %d", arg);
ty->termstate.wrapnext = 0; ty->termstate.wrapnext = 0;
ty->cursor_state.cy = MAX(0, ty->cursor_state.cy - arg); ty->cursor_state.cy = MAX(0, ty->cursor_state.cy - arg);
@ -1625,7 +1632,7 @@ HVP:
_handle_esc_csi_reset_mode(ty, *cc, b); _handle_esc_csi_reset_mode(ty, *cc, b);
break; break;
case 'm': // color set case 'm': // color set
_handle_esc_csi_color_set(ty, &b); _handle_esc_csi_color_set(ty, &b, be);
break; break;
case 'n': case 'n':
_handle_esc_csi_dsr(ty, b); _handle_esc_csi_dsr(ty, b);