forked from enlightenment/terminology
terminology: cleanup escape sequences parsing. Fix #1628
Charset length for example was not correctly handled and could even lead to segfaults. SVN revision: 80980
This commit is contained in:
parent
1434247df2
commit
d18cc90367
|
@ -16,12 +16,16 @@
|
||||||
#define ERR(...) EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
|
#define ERR(...) EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
|
||||||
#define WRN(...) EINA_LOG_DOM_WARN(_termpty_log_dom, __VA_ARGS__)
|
#define WRN(...) EINA_LOG_DOM_WARN(_termpty_log_dom, __VA_ARGS__)
|
||||||
#define INF(...) EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
|
#define INF(...) EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
|
||||||
#define DBG(...) EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
|
#define DBG(...) EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
|
||||||
|
|
||||||
#define ST 0x9c // String Terminator
|
#define ST 0x9c // String Terminator
|
||||||
#define BEL 0x07 // Bell
|
#define BEL 0x07 // Bell
|
||||||
#define ESC 033 // Escape
|
#define ESC 033 // Escape
|
||||||
|
|
||||||
|
/* XXX: all handle_ functions return the number of bytes successfully read, 0
|
||||||
|
* if not enought bytes could be read
|
||||||
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_csi_arg_get(Eina_Unicode **ptr)
|
_csi_arg_get(Eina_Unicode **ptr)
|
||||||
{
|
{
|
||||||
|
@ -62,10 +66,7 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
b++;
|
b++;
|
||||||
cc++;
|
cc++;
|
||||||
}
|
}
|
||||||
// if cc == ce then we got to the end of the string with no end marker
|
if (cc == ce) return 0;
|
||||||
// so return -2 to indicate to go back to the escape beginning when
|
|
||||||
// there is more bufer available
|
|
||||||
if (cc == ce) return -2;
|
|
||||||
*b = 0;
|
*b = 0;
|
||||||
b = buf;
|
b = buf;
|
||||||
// DBG(" CSI: '%c' args '%s'", *cc, buf);
|
// DBG(" CSI: '%c' args '%s'", *cc, buf);
|
||||||
|
@ -892,7 +893,7 @@ _handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
}
|
}
|
||||||
*b = 0;
|
*b = 0;
|
||||||
if ((*cc == ST) || (*cc == BEL) || (*cc == '\\')) cc++;
|
if ((*cc == ST) || (*cc == BEL) || (*cc == '\\')) cc++;
|
||||||
else return -2;
|
else return 0;
|
||||||
switch (buf[0])
|
switch (buf[0])
|
||||||
{
|
{
|
||||||
case '0':
|
case '0':
|
||||||
|
@ -946,6 +947,8 @@ _handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
break;
|
break;
|
||||||
case '4':
|
case '4':
|
||||||
// XXX: set palette entry. not supported.
|
// XXX: set palette entry. not supported.
|
||||||
|
DBG("set palette, not supported");
|
||||||
|
if ((cc - c) < 3) return 0;
|
||||||
b = &(buf[2]);
|
b = &(buf[2]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -974,7 +977,7 @@ _handle_esc_terminology(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
}
|
}
|
||||||
*b = 0;
|
*b = 0;
|
||||||
if (*cc == 0x0) cc++;
|
if (*cc == 0x0) cc++;
|
||||||
else return -2;
|
else return 0;
|
||||||
// commands are stored in the buffer, 0 bytes not allowd (end marker)
|
// commands are stored in the buffer, 0 bytes not allowd (end marker)
|
||||||
s = eina_unicode_unicode_to_utf8(buf, &slen);
|
s = eina_unicode_unicode_to_utf8(buf, &slen);
|
||||||
ty->cur_cmd = s;
|
ty->cur_cmd = s;
|
||||||
|
@ -1008,7 +1011,7 @@ _handle_esc_dcs(Termpty *ty __UNUSED__, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
}
|
}
|
||||||
*b = 0;
|
*b = 0;
|
||||||
if ((*cc == ST) || (*cc == '\\')) cc++;
|
if ((*cc == ST) || (*cc == '\\')) cc++;
|
||||||
else return -2;
|
else return 0;
|
||||||
switch (buf[0])
|
switch (buf[0])
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
|
@ -1025,73 +1028,89 @@ _handle_esc_dcs(Termpty *ty __UNUSED__, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
static int
|
static int
|
||||||
_handle_esc(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
_handle_esc(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
{
|
{
|
||||||
if ((ce - c) < 2) return 0;
|
int len = ce - c;
|
||||||
DBG("ESC: '%c'", c[1]);
|
|
||||||
switch (c[1])
|
if (len < 1) return 0;
|
||||||
|
DBG("ESC: '%c'", c[0]);
|
||||||
|
switch (c[0])
|
||||||
{
|
{
|
||||||
case '[':
|
case '[':
|
||||||
return 2 + _handle_esc_csi(ty, c + 2, ce);
|
len = _handle_esc_csi(ty, c + 1, ce);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
return 1 + len;
|
||||||
case ']':
|
case ']':
|
||||||
return 2 + _handle_esc_xterm(ty, c + 2, ce);
|
len = _handle_esc_xterm(ty, c + 1, ce);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
return 1 + len;
|
||||||
case '}':
|
case '}':
|
||||||
return 2 + _handle_esc_terminology(ty, c + 2, ce);
|
len = _handle_esc_terminology(ty, c + 1, ce);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
return 1 + len;
|
||||||
case 'P':
|
case 'P':
|
||||||
return 2 + _handle_esc_dcs(ty, c + 2, ce);
|
len = _handle_esc_dcs(ty, c + 1, ce);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
return 1 + len;
|
||||||
case '=': // set alternate keypad mode
|
case '=': // set alternate keypad mode
|
||||||
ty->state.alt_kp = 1;
|
ty->state.alt_kp = 1;
|
||||||
return 2;
|
return 1;
|
||||||
case '>': // set numeric keypad mode
|
case '>': // set numeric keypad mode
|
||||||
ty->state.alt_kp = 0;
|
ty->state.alt_kp = 0;
|
||||||
return 2;
|
return 1;
|
||||||
case 'M': // move to prev line
|
case 'M': // move to prev line
|
||||||
ty->state.wrapnext = 0;
|
ty->state.wrapnext = 0;
|
||||||
ty->state.cy--;
|
ty->state.cy--;
|
||||||
_termpty_text_scroll_rev_test(ty);
|
_termpty_text_scroll_rev_test(ty);
|
||||||
return 2;
|
return 1;
|
||||||
case 'D': // move to next line
|
case 'D': // move to next line
|
||||||
ty->state.wrapnext = 0;
|
ty->state.wrapnext = 0;
|
||||||
ty->state.cy++;
|
ty->state.cy++;
|
||||||
_termpty_text_scroll_test(ty);
|
_termpty_text_scroll_test(ty);
|
||||||
return 2;
|
return 1;
|
||||||
case 'E': // add \n\r
|
case 'E': // add \n\r
|
||||||
ty->state.wrapnext = 0;
|
ty->state.wrapnext = 0;
|
||||||
ty->state.cx = 0;
|
ty->state.cx = 0;
|
||||||
ty->state.cy++;
|
ty->state.cy++;
|
||||||
_termpty_text_scroll_test(ty);
|
_termpty_text_scroll_test(ty);
|
||||||
return 2;
|
return 1;
|
||||||
case 'Z': // same a 'ESC [ Pn c'
|
case 'Z': // same a 'ESC [ Pn c'
|
||||||
_term_txt_write(ty, "\033[?1;2C");
|
_term_txt_write(ty, "\033[?1;2C");
|
||||||
return 2;
|
return 1;
|
||||||
case 'c': // reset terminal to initial state
|
case 'c': // reset terminal to initial state
|
||||||
DBG("reset to init mode and clear");
|
DBG("reset to init mode and clear");
|
||||||
_termpty_reset_state(ty);
|
_termpty_reset_state(ty);
|
||||||
_termpty_clear_screen(ty, TERMPTY_CLR_ALL);
|
_termpty_clear_screen(ty, TERMPTY_CLR_ALL);
|
||||||
if (ty->cb.cancel_sel.func)
|
if (ty->cb.cancel_sel.func)
|
||||||
ty->cb.cancel_sel.func(ty->cb.cancel_sel.data);
|
ty->cb.cancel_sel.func(ty->cb.cancel_sel.data);
|
||||||
return 2;
|
return 1;
|
||||||
case '(': // charset 0
|
case '(': // charset 0
|
||||||
ty->state.chset[0] = c[2];
|
if (len < 2) return 0;
|
||||||
|
ty->state.chset[0] = c[1];
|
||||||
ty->state.multibyte = 0;
|
ty->state.multibyte = 0;
|
||||||
ty->state.charsetch = c[2];
|
ty->state.charsetch = c[1];
|
||||||
return 3;
|
return 2;
|
||||||
case ')': // charset 1
|
case ')': // charset 1
|
||||||
ty->state.chset[1] = c[2];
|
if (len < 2) return 0;
|
||||||
|
ty->state.chset[1] = c[1];
|
||||||
ty->state.multibyte = 0;
|
ty->state.multibyte = 0;
|
||||||
return 3;
|
return 2;
|
||||||
case '*': // charset 2
|
case '*': // charset 2
|
||||||
ty->state.chset[2] = c[2];
|
if (len < 2) return 0;
|
||||||
|
ty->state.chset[2] = c[1];
|
||||||
ty->state.multibyte = 0;
|
ty->state.multibyte = 0;
|
||||||
return 3;
|
return 2;
|
||||||
case '+': // charset 3
|
case '+': // charset 3
|
||||||
ty->state.chset[3] = c[2];
|
if (len < 2) return 0;
|
||||||
|
ty->state.chset[3] = c[1];
|
||||||
ty->state.multibyte = 0;
|
ty->state.multibyte = 0;
|
||||||
return 3;
|
return 2;
|
||||||
case '$': // charset -2
|
case '$': // charset -2
|
||||||
ty->state.chset[2] = c[2];
|
if (len < 2) return 0;
|
||||||
|
ty->state.chset[2] = c[1];
|
||||||
ty->state.multibyte = 1;
|
ty->state.multibyte = 1;
|
||||||
return 3;
|
return 2;
|
||||||
case '#': // #8 == test mode -> fill screen with "E";
|
case '#': // #8 == test mode -> fill screen with "E";
|
||||||
if (c[2] == '8')
|
if (len < 2) return 0;
|
||||||
|
if (c[1] == '8')
|
||||||
{
|
{
|
||||||
int i, size;
|
int i, size;
|
||||||
Termcell *cells;
|
Termcell *cells;
|
||||||
|
@ -1110,30 +1129,31 @@ _handle_esc(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
for (i = 0; i < size; i++) cells[i].codepoint = 'E';
|
for (i = 0; i < size; i++) cells[i].codepoint = 'E';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 3;
|
return 2;
|
||||||
case '@': // just consume this plus next char
|
case '@': // just consume this plus next char
|
||||||
return 3;
|
if (len < 2) return 0;
|
||||||
|
return 2;
|
||||||
case '7': // save cursor pos
|
case '7': // save cursor pos
|
||||||
_termpty_cursor_copy(&(ty->state), &(ty->save));
|
_termpty_cursor_copy(&(ty->state), &(ty->save));
|
||||||
return 2;
|
return 1;
|
||||||
case '8': // restore cursor pos
|
case '8': // restore cursor pos
|
||||||
_termpty_cursor_copy(&(ty->save), &(ty->state));
|
_termpty_cursor_copy(&(ty->save), &(ty->state));
|
||||||
return 2;
|
return 1;
|
||||||
/*
|
/*
|
||||||
case 'G': // query gfx mode
|
case 'G': // query gfx mode
|
||||||
return 3;
|
return 2;
|
||||||
case 'H': // set tab at current column
|
case 'H': // set tab at current column
|
||||||
return 2;
|
return 1;
|
||||||
case 'n': // single shift 2
|
case 'n': // single shift 2
|
||||||
return 2;
|
return 1;
|
||||||
case 'o': // single shift 3
|
case 'o': // single shift 3
|
||||||
return 2;
|
return 1;
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
ERR("eek - esc unhandled '%c' (0x%02x)", c[1], c[1]);
|
ERR("eek - esc unhandled '%c' (0x%02x)", c[0], c[0]);
|
||||||
break;
|
return 1;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1257,7 +1277,9 @@ _termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
*/
|
*/
|
||||||
case 0x1b: // ESC (escape)
|
case 0x1b: // ESC (escape)
|
||||||
ty->state.had_cr = 0;
|
ty->state.had_cr = 0;
|
||||||
return _handle_esc(ty, c, ce);
|
len = _handle_esc(ty, c + 1, ce);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
return 1 + len;
|
||||||
/*
|
/*
|
||||||
case 0x1c: // FS (file separator)
|
case 0x1c: // FS (file separator)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1282,13 +1304,11 @@ _termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce)
|
||||||
}
|
}
|
||||||
else if (c[0] == 0x9b) // ANSI ESC!!!
|
else if (c[0] == 0x9b) // ANSI ESC!!!
|
||||||
{
|
{
|
||||||
int v;
|
|
||||||
|
|
||||||
printf("ANSI CSI!!!!!\n");
|
printf("ANSI CSI!!!!!\n");
|
||||||
ty->state.had_cr = 0;
|
ty->state.had_cr = 0;
|
||||||
v = _handle_esc_csi(ty, c + 1, ce);
|
len = _handle_esc_csi(ty, c + 1, ce);
|
||||||
if (v == -2) return 0;
|
if (len == 0) return 0;
|
||||||
return v + 1;
|
return 1 + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc = (int *)c;
|
cc = (int *)c;
|
||||||
|
|
Loading…
Reference in New Issue