2012-07-13 01:46:33 -07:00
|
|
|
#include "private.h"
|
|
|
|
#include <Elementary.h>
|
2014-08-17 13:20:40 -07:00
|
|
|
#include "termio.h"
|
2012-07-13 01:46:33 -07:00
|
|
|
#include "termpty.h"
|
|
|
|
#include "termptydbl.h"
|
|
|
|
#include "termptyesc.h"
|
|
|
|
#include "termptyops.h"
|
|
|
|
#include "termptyext.h"
|
2013-04-21 14:18:03 -07:00
|
|
|
#if defined(SUPPORT_80_132_COLUMNS)
|
|
|
|
#include "termio.h"
|
|
|
|
#endif
|
2012-07-13 01:46:33 -07:00
|
|
|
|
|
|
|
#undef CRITICAL
|
|
|
|
#undef ERR
|
|
|
|
#undef WRN
|
|
|
|
#undef INF
|
|
|
|
#undef DBG
|
|
|
|
|
|
|
|
#define CRITICAL(...) EINA_LOG_DOM_CRIT(_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 INF(...) EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
|
2012-12-14 23:48:17 -08:00
|
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
|
2012-07-13 01:46:33 -07:00
|
|
|
|
2012-10-04 16:18:46 -07:00
|
|
|
#define ST 0x9c // String Terminator
|
|
|
|
#define BEL 0x07 // Bell
|
2012-10-04 16:18:54 -07:00
|
|
|
#define ESC 033 // Escape
|
2012-10-04 16:18:46 -07:00
|
|
|
|
2012-12-14 10:52:19 -08:00
|
|
|
/* XXX: all handle_ functions return the number of bytes successfully read, 0
|
2014-08-14 12:48:26 -07:00
|
|
|
* if not enough bytes could be read
|
2012-12-14 10:52:19 -08:00
|
|
|
*/
|
|
|
|
|
2012-07-13 01:46:33 -07:00
|
|
|
static int
|
|
|
|
_csi_arg_get(Eina_Unicode **ptr)
|
|
|
|
{
|
|
|
|
Eina_Unicode *b = *ptr;
|
|
|
|
int sum = 0;
|
|
|
|
|
2014-09-15 14:10:55 -07:00
|
|
|
while ((*b) && (*b < '0' || *b > '9')) b++;
|
2012-07-13 01:46:33 -07:00
|
|
|
if (!*b)
|
|
|
|
{
|
|
|
|
*ptr = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
2014-09-15 14:10:55 -07:00
|
|
|
while ((*b >= '0') && (*b <= '9'))
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2013-04-28 08:35:48 -07:00
|
|
|
sum *= 10;
|
2012-07-13 01:46:33 -07:00
|
|
|
sum += *b - '0';
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
*ptr = b;
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
2013-04-27 12:17:14 -07:00
|
|
|
static void
|
2014-03-05 13:23:13 -08:00
|
|
|
_handle_cursor_control(Termpty *ty, const Eina_Unicode *cc)
|
2013-04-27 12:17:14 -07:00
|
|
|
{
|
|
|
|
switch (*cc)
|
|
|
|
{
|
|
|
|
case 0x07: // BEL '\a' (bell)
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
if (ty->cb.bell.func) ty->cb.bell.func(ty->cb.bell.data);
|
|
|
|
return;
|
|
|
|
case 0x08: // BS '\b' (backspace)
|
|
|
|
DBG("->BS");
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cx--;
|
|
|
|
if (ty->state.cx < 0) ty->state.cx = 0;
|
|
|
|
return;
|
|
|
|
case 0x09: // HT '\t' (horizontal tab)
|
|
|
|
DBG("->HT");
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
TERMPTY_SCREEN(ty, ty->state.cx, ty->state.cy).att.tab = 1;
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cx += 8;
|
|
|
|
ty->state.cx = (ty->state.cx / 8) * 8;
|
|
|
|
if (ty->state.cx >= ty->w)
|
|
|
|
ty->state.cx = ty->w - 1;
|
|
|
|
return;
|
|
|
|
case 0x0a: // LF '\n' (new line)
|
|
|
|
case 0x0b: // VT '\v' (vertical tab)
|
|
|
|
case 0x0c: // FF '\f' (form feed)
|
|
|
|
DBG("->LF");
|
|
|
|
if (ty->state.had_cr)
|
|
|
|
{
|
|
|
|
TERMPTY_SCREEN(ty, ty->state.had_cr_x,
|
|
|
|
ty->state.had_cr_y).att.newline = 1;
|
|
|
|
}
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
if (ty->state.crlf) ty->state.cx = 0;
|
|
|
|
ty->state.cy++;
|
|
|
|
_termpty_text_scroll_test(ty, EINA_TRUE);
|
|
|
|
return;
|
|
|
|
case 0x0d: // CR '\r' (carriage ret)
|
|
|
|
DBG("->CR");
|
|
|
|
if (ty->state.cx != 0)
|
|
|
|
{
|
|
|
|
ty->state.had_cr_x = ty->state.cx;
|
|
|
|
ty->state.had_cr_y = ty->state.cy;
|
2014-12-07 14:51:23 -08:00
|
|
|
ty->state.wrapnext = 0;
|
2013-04-27 12:17:14 -07:00
|
|
|
}
|
|
|
|
ty->state.cx = 0;
|
|
|
|
// ty->state.had_cr = 1;
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-11 13:02:56 -07:00
|
|
|
static void
|
|
|
|
_handle_esc_csi_reset_mode(Termpty *ty, Eina_Unicode cc, Eina_Unicode *b)
|
|
|
|
{
|
|
|
|
int mode = 0, priv = 0, arg;
|
|
|
|
|
|
|
|
if (cc == 'h') mode = 1;
|
|
|
|
if (*b == '?')
|
|
|
|
{
|
|
|
|
priv = 1;
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
if (priv) /* DEC Private Mode Reset (DECRST) */
|
|
|
|
{
|
|
|
|
while (b)
|
|
|
|
{
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
// complete-ish list here:
|
|
|
|
// http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html
|
|
|
|
switch (arg)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ty->state.appcursor = mode;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ty->state.kbd_lock = mode;
|
|
|
|
break;
|
|
|
|
case 3: // 132 column mode… should we handle this?
|
|
|
|
#if defined(SUPPORT_80_132_COLUMNS)
|
|
|
|
if (ty->state.att.is_80_132_mode_allowed)
|
|
|
|
{
|
|
|
|
/* ONLY FOR TESTING PURPOSE FTM */
|
|
|
|
Evas_Object *wn;
|
|
|
|
int w, h;
|
|
|
|
|
|
|
|
wn = termio_win_get(ty->obj);
|
|
|
|
elm_win_size_step_get(wn, &w, &h);
|
|
|
|
evas_object_resize(wn,
|
|
|
|
4 +
|
|
|
|
(mode ? 132 : 80) * w,
|
|
|
|
4 + ty->h * h);
|
|
|
|
termpty_resize(ty, mode ? 132 : 80,
|
|
|
|
ty->h);
|
|
|
|
_termpty_reset_state(ty);
|
|
|
|
_termpty_clear_screen(ty,
|
|
|
|
TERMPTY_CLR_ALL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
WRN("TODO: scrolling mode (DECSCLM): %i", mode);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
ty->state.reverse = mode;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
if (mode)
|
|
|
|
{
|
|
|
|
ty->state.margin_top = ty->state.cy;
|
|
|
|
ty->state.cx = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.cx = 0;
|
|
|
|
ty->state.margin_top = 0;
|
|
|
|
}
|
|
|
|
DBG("origin mode (%d): cursor is at 0,0"
|
|
|
|
" cursor limited to screen/start point"
|
|
|
|
" for line #'s depends on top margin",
|
|
|
|
mode);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
DBG("set wrap mode to %i", mode);
|
|
|
|
ty->state.wrap = mode;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
ty->state.no_autorepeat = !mode;
|
|
|
|
DBG("auto repeat %i", mode);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
DBG("set mouse (X10) %i", mode);
|
|
|
|
if (mode) ty->mouse_mode = MOUSE_X10;
|
|
|
|
else ty->mouse_mode = MOUSE_OFF;
|
|
|
|
break;
|
|
|
|
case 12: // ignore
|
|
|
|
WRN("TODO: set blinking cursor to (stop?) %i or local echo (ignored)", mode);
|
|
|
|
break;
|
|
|
|
case 19: // never seen this - what to do?
|
|
|
|
WRN("TODO: set print extent to full screen");
|
|
|
|
break;
|
|
|
|
case 20: // crfl==1 -> cur moves to col 0 on LF, FF or VT, ==0 -> mode is cr+lf
|
|
|
|
ty->state.crlf = mode;
|
|
|
|
break;
|
|
|
|
case 25:
|
|
|
|
ty->state.hidecursor = !mode;
|
|
|
|
DBG("hide cursor: %d", !mode);
|
|
|
|
break;
|
|
|
|
case 30: // ignore
|
|
|
|
WRN("TODO: set scrollbar mapping %i", mode);
|
|
|
|
break;
|
|
|
|
case 33: // ignore
|
|
|
|
WRN("TODO: Stop cursor blink %i", mode);
|
|
|
|
break;
|
|
|
|
case 34: // ignore
|
|
|
|
WRN("TODO: Underline cursor mode %i", mode);
|
|
|
|
break;
|
|
|
|
case 35: // ignore
|
|
|
|
WRN("TODO: set shift keys %i", mode);
|
|
|
|
break;
|
|
|
|
case 38: // ignore
|
|
|
|
WRN("TODO: switch to tek window %i", mode);
|
|
|
|
break;
|
|
|
|
case 40:
|
|
|
|
DBG("Allow 80 -> 132 Mode %i", mode);
|
|
|
|
#if defined(SUPPORT_80_132_COLUMNS)
|
|
|
|
ty->state.att.is_80_132_mode_allowed = mode;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 45: // ignore
|
|
|
|
WRN("TODO: Reverse-wraparound Mode");
|
|
|
|
break;
|
|
|
|
case 59: // ignore
|
|
|
|
WRN("TODO: kanji terminal mode %i", mode);
|
|
|
|
break;
|
|
|
|
case 66:
|
|
|
|
WRN("TODO: app keypad mode %i", mode);
|
|
|
|
break;
|
|
|
|
case 67:
|
|
|
|
ty->state.send_bs = mode;
|
|
|
|
DBG("backspace send bs not del = %i", mode);
|
|
|
|
break;
|
|
|
|
case 1000:
|
|
|
|
if (mode) ty->mouse_mode = MOUSE_NORMAL;
|
|
|
|
else ty->mouse_mode = MOUSE_OFF;
|
|
|
|
DBG("set mouse (press+release only) to %i", mode);
|
|
|
|
break;
|
|
|
|
case 1001:
|
|
|
|
WRN("TODO: x11 mouse highlighting %i", mode);
|
|
|
|
break;
|
|
|
|
case 1002:
|
|
|
|
if (mode) ty->mouse_mode = MOUSE_NORMAL_BTN_MOVE;
|
|
|
|
else ty->mouse_mode = MOUSE_OFF;
|
|
|
|
DBG("set mouse (press+release+motion while pressed) %i", mode);
|
|
|
|
break;
|
|
|
|
case 1003:
|
|
|
|
if (mode) ty->mouse_mode = MOUSE_NORMAL_ALL_MOVE;
|
|
|
|
else ty->mouse_mode = MOUSE_OFF;
|
|
|
|
DBG("set mouse (press+release+all motion) %i", mode);
|
|
|
|
break;
|
|
|
|
case 1004: // i dont know what focus repporting is?
|
|
|
|
WRN("TODO: enable focus reporting %i", mode);
|
|
|
|
break;
|
|
|
|
case 1005:
|
|
|
|
if (mode) ty->mouse_ext = MOUSE_EXT_UTF8;
|
|
|
|
else ty->mouse_ext = MOUSE_EXT_NONE;
|
|
|
|
DBG("set mouse (xterm utf8 style) %i", mode);
|
|
|
|
break;
|
|
|
|
case 1006:
|
|
|
|
if (mode) ty->mouse_ext = MOUSE_EXT_SGR;
|
|
|
|
else ty->mouse_ext = MOUSE_EXT_NONE;
|
|
|
|
DBG("set mouse (xterm sgr style) %i", mode);
|
|
|
|
break;
|
|
|
|
case 1010: // ignore
|
|
|
|
WRN("TODO: set home on tty output %i", mode);
|
|
|
|
break;
|
|
|
|
case 1012: // ignore
|
|
|
|
WRN("TODO: set home on tty input %i", mode);
|
|
|
|
break;
|
|
|
|
case 1015:
|
|
|
|
if (mode) ty->mouse_ext = MOUSE_EXT_URXVT;
|
|
|
|
else ty->mouse_ext = MOUSE_EXT_NONE;
|
|
|
|
DBG("set mouse (rxvt-unicode style) %i", mode);
|
|
|
|
break;
|
|
|
|
case 1034: // ignore
|
|
|
|
/* libreadline6 emits it but it shouldn't.
|
|
|
|
See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577012
|
|
|
|
*/
|
|
|
|
DBG("Ignored screen mode %i", arg);
|
|
|
|
break;
|
|
|
|
case 1047:
|
|
|
|
case 1049:
|
|
|
|
case 47:
|
|
|
|
DBG("DDD: switch buf");
|
|
|
|
if (ty->altbuf)
|
|
|
|
{
|
|
|
|
// if we are looking at alt buf now,
|
|
|
|
// clear main buf before we swap it back
|
|
|
|
// into the screen2 save (so save is
|
|
|
|
// clear)
|
|
|
|
_termpty_clear_all(ty);
|
|
|
|
}
|
|
|
|
// swap screen content now
|
|
|
|
if (mode != ty->altbuf)
|
|
|
|
termpty_screen_swap(ty);
|
|
|
|
break;
|
|
|
|
case 1048:
|
|
|
|
if (mode)
|
|
|
|
_termpty_cursor_copy(&(ty->state), &(ty->save));
|
|
|
|
else
|
|
|
|
_termpty_cursor_copy(&(ty->save), &(ty->state));
|
|
|
|
break;
|
|
|
|
case 2004:
|
|
|
|
ty->bracketed_paste = mode;
|
|
|
|
break;
|
|
|
|
case 7727: // ignore
|
|
|
|
WRN("TODO: enable application escape mode %i", mode);
|
|
|
|
break;
|
|
|
|
case 7786: // ignore
|
|
|
|
WRN("TODO: enable mouse wheel -> cursor key xlation %i", mode);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR("Unhandled DEC Private Reset Mode arg %i", arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* Reset Mode (RM) */
|
|
|
|
{
|
|
|
|
while (b)
|
|
|
|
{
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
switch (arg)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ty->state.appcursor = mode;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
DBG("set insert mode to %i", mode);
|
|
|
|
ty->state.insert = mode;
|
|
|
|
break;
|
|
|
|
case 34:
|
|
|
|
WRN("TODO: hebrew keyboard mapping: %i", mode);
|
|
|
|
break;
|
|
|
|
case 36:
|
|
|
|
WRN("TODO: hebrew encoding mode: %i", mode);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR("Unhandled ANSI Reset Mode arg %i", arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 09:10:48 -07:00
|
|
|
static void
|
|
|
|
_handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr)
|
|
|
|
{
|
|
|
|
Eina_Unicode *b = *ptr;
|
|
|
|
int first = 1;
|
|
|
|
|
|
|
|
if (b && (*b == '>'))
|
|
|
|
{ // key resources used by xterm
|
|
|
|
ERR("TODO: set/reset key resources used by xterm");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DBG("color set");
|
|
|
|
while (b)
|
|
|
|
{
|
|
|
|
int arg = _csi_arg_get(&b);
|
|
|
|
if ((first) && (!b))
|
|
|
|
_termpty_reset_att(&(ty->state.att));
|
|
|
|
else if (b)
|
|
|
|
{
|
|
|
|
first = 0;
|
|
|
|
switch (arg)
|
|
|
|
{
|
|
|
|
case 0: // reset to normal
|
|
|
|
_termpty_reset_att(&(ty->state.att));
|
|
|
|
break;
|
|
|
|
case 1: // bold/bright
|
|
|
|
ty->state.att.bold = 1;
|
|
|
|
break;
|
|
|
|
case 2: // faint
|
|
|
|
ty->state.att.faint = 1;
|
|
|
|
break;
|
|
|
|
case 3: // italic
|
|
|
|
#if defined(SUPPORT_ITALIC)
|
|
|
|
ty->state.att.italic = 1;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 4: // underline
|
|
|
|
ty->state.att.underline = 1;
|
|
|
|
break;
|
|
|
|
case 5: // blink
|
|
|
|
ty->state.att.blink = 1;
|
|
|
|
break;
|
|
|
|
case 6: // blink rapid
|
|
|
|
ty->state.att.blink2 = 1;
|
|
|
|
break;
|
|
|
|
case 7: // reverse
|
|
|
|
ty->state.att.inverse = 1;
|
|
|
|
break;
|
|
|
|
case 8: // invisible
|
|
|
|
ty->state.att.invisible = 1;
|
|
|
|
break;
|
|
|
|
case 9: // strikethrough
|
|
|
|
ty->state.att.strike = 1;
|
|
|
|
break;
|
2014-04-06 05:42:38 -07:00
|
|
|
case 20: // fraktur!
|
|
|
|
ty->state.att.fraktur = 1;
|
|
|
|
break;
|
2013-09-21 09:10:48 -07:00
|
|
|
case 21: // no bold/bright
|
|
|
|
ty->state.att.bold = 0;
|
|
|
|
break;
|
2014-03-03 14:02:17 -08:00
|
|
|
case 22: // no bold/bright, no faint
|
|
|
|
ty->state.att.bold = 0;
|
2013-09-21 09:10:48 -07:00
|
|
|
ty->state.att.faint = 0;
|
|
|
|
break;
|
2014-04-06 05:42:38 -07:00
|
|
|
case 23: // no italic, not fraktur
|
2013-09-21 09:10:48 -07:00
|
|
|
#if defined(SUPPORT_ITALIC)
|
|
|
|
ty->state.att.italic = 0;
|
|
|
|
#endif
|
2014-04-06 05:42:38 -07:00
|
|
|
ty->state.att.fraktur = 0;
|
2013-09-21 09:10:48 -07:00
|
|
|
break;
|
|
|
|
case 24: // no underline
|
|
|
|
ty->state.att.underline = 0;
|
|
|
|
break;
|
|
|
|
case 25: // no blink
|
|
|
|
ty->state.att.blink = 0;
|
|
|
|
ty->state.att.blink2 = 0;
|
|
|
|
break;
|
|
|
|
case 27: // no reverse
|
|
|
|
ty->state.att.inverse = 0;
|
|
|
|
break;
|
|
|
|
case 28: // no invisible
|
|
|
|
ty->state.att.invisible = 0;
|
|
|
|
break;
|
|
|
|
case 29: // no strikethrough
|
|
|
|
ty->state.att.strike = 0;
|
|
|
|
break;
|
|
|
|
case 30: // fg
|
|
|
|
case 31:
|
|
|
|
case 32:
|
|
|
|
case 33:
|
|
|
|
case 34:
|
|
|
|
case 35:
|
|
|
|
case 36:
|
|
|
|
case 37:
|
|
|
|
ty->state.att.fg256 = 0;
|
|
|
|
ty->state.att.fg = (arg - 30) + COL_BLACK;
|
|
|
|
ty->state.att.fgintense = 0;
|
|
|
|
break;
|
|
|
|
case 38: // 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);
|
|
|
|
if (!b) ERR("Failed xterm 256 color fg esc val");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.att.fg256 = 1;
|
|
|
|
ty->state.att.fg = arg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty->state.att.fgintense = 0;
|
|
|
|
break;
|
|
|
|
case 39: // default fg color
|
|
|
|
ty->state.att.fg256 = 0;
|
|
|
|
ty->state.att.fg = COL_DEF;
|
|
|
|
ty->state.att.fgintense = 0;
|
|
|
|
break;
|
|
|
|
case 40: // bg
|
|
|
|
case 41:
|
|
|
|
case 42:
|
|
|
|
case 43:
|
|
|
|
case 44:
|
|
|
|
case 45:
|
|
|
|
case 46:
|
|
|
|
case 47:
|
|
|
|
ty->state.att.bg256 = 0;
|
|
|
|
ty->state.att.bg = (arg - 40) + COL_BLACK;
|
|
|
|
ty->state.att.bgintense = 0;
|
|
|
|
break;
|
|
|
|
case 48: // 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);
|
|
|
|
if (!b) ERR("Failed xterm 256 color bg esc val");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.att.bg256 = 1;
|
|
|
|
ty->state.att.bg = arg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty->state.att.bgintense = 0;
|
|
|
|
break;
|
|
|
|
case 49: // default bg color
|
|
|
|
ty->state.att.bg256 = 0;
|
|
|
|
ty->state.att.bg = COL_DEF;
|
|
|
|
ty->state.att.bgintense = 0;
|
|
|
|
break;
|
|
|
|
case 90: // fg
|
|
|
|
case 91:
|
|
|
|
case 92:
|
|
|
|
case 93:
|
|
|
|
case 94:
|
|
|
|
case 95:
|
|
|
|
case 96:
|
|
|
|
case 97:
|
|
|
|
ty->state.att.fg256 = 0;
|
|
|
|
ty->state.att.fg = (arg - 90) + COL_BLACK;
|
|
|
|
ty->state.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);
|
|
|
|
if (!b) ERR("Failed xterm 256 color fg esc val");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.att.fg256 = 1;
|
|
|
|
ty->state.att.fg = arg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty->state.att.fgintense = 1;
|
|
|
|
break;
|
|
|
|
case 99: // default fg color
|
|
|
|
ty->state.att.fg256 = 0;
|
|
|
|
ty->state.att.fg = COL_DEF;
|
|
|
|
ty->state.att.fgintense = 1;
|
|
|
|
break;
|
|
|
|
case 100: // bg
|
|
|
|
case 101:
|
|
|
|
case 102:
|
|
|
|
case 103:
|
|
|
|
case 104:
|
|
|
|
case 105:
|
|
|
|
case 106:
|
|
|
|
case 107:
|
|
|
|
ty->state.att.bg256 = 0;
|
|
|
|
ty->state.att.bg = (arg - 100) + COL_BLACK;
|
|
|
|
ty->state.att.bgintense = 1;
|
|
|
|
break;
|
|
|
|
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);
|
|
|
|
if (!b) ERR("Failed xterm 256 color bg esc val");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.att.bg256 = 1;
|
|
|
|
ty->state.att.bg = arg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty->state.att.bgintense = 1;
|
|
|
|
break;
|
|
|
|
case 109: // default bg color
|
|
|
|
ty->state.att.bg256 = 0;
|
|
|
|
ty->state.att.bg = COL_DEF;
|
|
|
|
ty->state.att.bgintense = 1;
|
|
|
|
break;
|
|
|
|
default: // not handled???
|
2014-07-21 14:51:26 -07:00
|
|
|
ERR("Unhandled color cmd [%i]", arg);
|
2013-09-21 09:10:48 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-14 12:48:26 -07:00
|
|
|
static void
|
|
|
|
_handle_esc_csi_dsr(Termpty *ty, Eina_Unicode *b)
|
|
|
|
{
|
|
|
|
int arg, len;
|
|
|
|
char bf[32];
|
|
|
|
|
|
|
|
if (*b == '>')
|
|
|
|
{
|
|
|
|
ERR("TODO: disable key resources used by xterm");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (*b == '?')
|
|
|
|
{
|
|
|
|
b++;
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
switch (arg)
|
|
|
|
{
|
|
|
|
case 6:
|
|
|
|
len = snprintf(bf, sizeof(bf), "\033[?%d;%d;1R",
|
|
|
|
ty->state.cy + 1, ty->state.cx + 1);
|
|
|
|
termpty_write(ty, bf, len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRN("unhandled DSR (dec specific) %d", arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
switch (arg)
|
|
|
|
{
|
|
|
|
case 6:
|
|
|
|
len = snprintf(bf, sizeof(bf), "\033[%d;%dR",
|
|
|
|
ty->state.cy + 1, ty->state.cx + 1);
|
|
|
|
termpty_write(ty, bf, len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WRN("unhandled DSR %d", arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:46:33 -07:00
|
|
|
static int
|
|
|
|
_handle_esc_csi(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
|
|
|
{
|
2014-03-05 12:42:33 -08:00
|
|
|
int arg, i;
|
2014-03-05 13:23:13 -08:00
|
|
|
const Eina_Unicode *cc, *be;
|
2012-07-13 01:46:33 -07:00
|
|
|
Eina_Unicode buf[4096], *b;
|
|
|
|
|
|
|
|
cc = (Eina_Unicode *)c;
|
|
|
|
b = buf;
|
2014-03-05 13:23:13 -08:00
|
|
|
be = buf + sizeof(buf) / sizeof(buf[0]);
|
|
|
|
while ((cc < ce) && (*cc <= '?') && (b < be))
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2013-04-27 12:17:14 -07:00
|
|
|
_handle_cursor_control(ty, cc);
|
2012-07-13 01:46:33 -07:00
|
|
|
*b = *cc;
|
|
|
|
b++;
|
|
|
|
cc++;
|
|
|
|
}
|
2014-03-05 13:23:13 -08:00
|
|
|
if (b == be)
|
|
|
|
{
|
|
|
|
ERR("csi parsing overflowed, skipping the whole buffer (binary data?)");
|
|
|
|
return cc - c;
|
|
|
|
}
|
2012-12-14 10:52:19 -08:00
|
|
|
if (cc == ce) return 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
*b = 0;
|
|
|
|
b = buf;
|
2015-02-23 13:20:18 -08:00
|
|
|
DBG(" CSI: '%c' args '%s'", (int) *cc, (char *) buf);
|
2012-07-13 01:46:33 -07:00
|
|
|
switch (*cc)
|
|
|
|
{
|
|
|
|
case 'm': // color set
|
2013-09-21 09:10:48 -07:00
|
|
|
_handle_esc_csi_color_set(ty, &b);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case '@': // insert N blank chars
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("insert %d blank chars", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
int pi = ty->state.insert;
|
2015-02-23 13:20:18 -08:00
|
|
|
Eina_Unicode blank[1] = { ' ' };
|
2012-07-13 01:46:33 -07:00
|
|
|
int cx = ty->state.cx;
|
|
|
|
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.insert = 1;
|
|
|
|
for (i = 0; i < arg; i++)
|
|
|
|
_termpty_text_append(ty, blank, 1);
|
|
|
|
ty->state.insert = pi;
|
|
|
|
ty->state.cx = cx;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'A': // cursor up N
|
|
|
|
case 'e': // cursor up N
|
|
|
|
arg = _csi_arg_get(&b);
|
2013-12-25 18:36:51 -08:00
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("cursor up %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
2013-12-26 23:16:17 -08:00
|
|
|
ty->state.cy = MAX(0, ty->state.cy - arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'B': // cursor down N
|
|
|
|
arg = _csi_arg_get(&b);
|
2013-12-25 18:36:51 -08:00
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("cursor down %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
2013-12-26 23:16:17 -08:00
|
|
|
ty->state.cy = MIN(ty->h - 1, ty->state.cy + arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'D': // cursor left N
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("cursor left %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
for (i = 0; i < arg; i++)
|
|
|
|
{
|
|
|
|
ty->state.cx--;
|
|
|
|
if (ty->state.cx < 0) ty->state.cx = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'C': // cursor right N
|
|
|
|
case 'a': // cursor right N
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("cursor right %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
for (i = 0; i < arg; i++)
|
|
|
|
{
|
|
|
|
ty->state.cx++;
|
|
|
|
if (ty->state.cx >= ty->w) ty->state.cx = ty->w - 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'H': // cursor pos set
|
|
|
|
case 'f': // cursor pos set
|
2013-05-27 13:03:34 -07:00
|
|
|
DBG("cursor pos set");
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
if (!*b)
|
|
|
|
{
|
|
|
|
ty->state.cx = 0;
|
|
|
|
ty->state.cy = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
|
|
|
arg--;
|
2014-01-22 14:19:11 -08:00
|
|
|
if (arg >= ty->h) arg = ty->h - 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
if (b)
|
|
|
|
{
|
2013-04-22 13:27:52 -07:00
|
|
|
ty->state.cy = arg;
|
2012-07-13 01:46:33 -07:00
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
|
|
|
arg--;
|
|
|
|
}
|
|
|
|
else arg = 0;
|
2014-03-24 05:40:05 -07:00
|
|
|
|
|
|
|
if (arg >= ty->w) arg = ty->w - 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
if (b) ty->state.cx = arg;
|
|
|
|
}
|
2013-04-22 13:27:52 -07:00
|
|
|
ty->state.cy += ty->state.margin_top;
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'G': // to column N
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("to column %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cx = arg - 1;
|
|
|
|
if (ty->state.cx < 0) ty->state.cx = 0;
|
|
|
|
else if (ty->state.cx >= ty->w) ty->state.cx = ty->w - 1;
|
|
|
|
break;
|
|
|
|
case 'd': // to row N
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("to row %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cy = arg - 1;
|
|
|
|
if (ty->state.cy < 0) ty->state.cy = 0;
|
|
|
|
else if (ty->state.cy >= ty->h) ty->state.cy = ty->h - 1;
|
|
|
|
break;
|
|
|
|
case 'E': // down relative N rows, and to col 0
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("down relative %d rows, and to col 0", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cy += arg;
|
|
|
|
if (ty->state.cy < 0) ty->state.cy = 0;
|
|
|
|
else if (ty->state.cy >= ty->h) ty->state.cy = ty->h - 1;
|
|
|
|
ty->state.cx = 0;
|
|
|
|
break;
|
|
|
|
case 'F': // up relative N rows, and to col 0
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("up relative %d rows, and to col 0", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cy -= arg;
|
|
|
|
if (ty->state.cy < 0) ty->state.cy = 0;
|
|
|
|
else if (ty->state.cy >= ty->h) ty->state.cy = ty->h - 1;
|
|
|
|
ty->state.cx = 0;
|
|
|
|
break;
|
|
|
|
case 'X': // erase N chars
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("erase %d chars", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
_termpty_clear_line(ty, TERMPTY_CLR_END, arg);
|
|
|
|
break;
|
|
|
|
case 'S': // scroll up N lines
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("scroll up %d lines", arg);
|
2013-05-27 13:10:18 -07:00
|
|
|
for (i = 0; i < arg; i++) _termpty_text_scroll(ty, EINA_TRUE);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'T': // scroll down N lines
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
2013-09-14 09:52:48 -07:00
|
|
|
DBG("scroll down %d lines", arg);
|
2013-05-27 13:10:18 -07:00
|
|
|
for (i = 0; i < arg; i++) _termpty_text_scroll_rev(ty, EINA_TRUE);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'M': // delete N lines - cy
|
|
|
|
case 'L': // insert N lines - cy
|
|
|
|
arg = _csi_arg_get(&b);
|
2013-09-14 09:52:48 -07:00
|
|
|
if (arg < 1) arg = 1;
|
2013-11-16 10:26:10 -08:00
|
|
|
DBG("%s %d lines", (*cc == 'M') ? "delete" : "insert", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
int sy1, sy2;
|
|
|
|
|
|
|
|
sy1 = ty->state.scroll_y1;
|
|
|
|
sy2 = ty->state.scroll_y2;
|
|
|
|
if (ty->state.scroll_y2 == 0)
|
|
|
|
{
|
|
|
|
ty->state.scroll_y1 = ty->state.cy;
|
|
|
|
ty->state.scroll_y2 = ty->h;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.scroll_y1 = ty->state.cy;
|
|
|
|
if (ty->state.scroll_y2 <= ty->state.scroll_y1)
|
|
|
|
ty->state.scroll_y2 = ty->state.scroll_y1 + 1;
|
|
|
|
}
|
|
|
|
for (i = 0; i < arg; i++)
|
|
|
|
{
|
2013-04-18 14:12:15 -07:00
|
|
|
if (*cc == 'M') _termpty_text_scroll(ty, EINA_TRUE);
|
|
|
|
else _termpty_text_scroll_rev(ty, EINA_TRUE);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
ty->state.scroll_y1 = sy1;
|
|
|
|
ty->state.scroll_y2 = sy2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'P': // erase and scrollback N chars
|
|
|
|
arg = _csi_arg_get(&b);
|
2013-09-14 09:52:48 -07:00
|
|
|
if (arg < 1) arg = 1;
|
|
|
|
DBG("erase and scrollback %d chars", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
Termcell *cells;
|
|
|
|
int x, lim;
|
|
|
|
|
2013-01-21 06:02:32 -08:00
|
|
|
cells = &(TERMPTY_SCREEN(ty, 0, ty->state.cy));
|
2012-07-13 01:46:33 -07:00
|
|
|
lim = ty->w - arg;
|
|
|
|
for (x = ty->state.cx; x < (ty->w); x++)
|
|
|
|
{
|
|
|
|
if (x < lim)
|
2013-01-29 07:54:47 -08:00
|
|
|
termpty_cell_copy(ty, &(cells[x + arg]), &(cells[x]), 1);
|
2012-07-13 01:46:33 -07:00
|
|
|
else
|
2013-11-23 10:29:31 -08:00
|
|
|
{
|
|
|
|
cells[x].codepoint = ' ';
|
|
|
|
cells[x].att.underline = 0;
|
|
|
|
cells[x].att.blink = 0;
|
|
|
|
cells[x].att.blink2 = 0;
|
|
|
|
cells[x].att.inverse = 0;
|
|
|
|
cells[x].att.strike = 0;
|
|
|
|
#if defined(SUPPORT_DBLWIDTH)
|
|
|
|
cells[x].att.dblwidth = 0;
|
|
|
|
#endif
|
|
|
|
}
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-04-17 13:13:00 -07:00
|
|
|
case 'c': // query device attributes
|
2013-05-27 13:03:34 -07:00
|
|
|
DBG("query device attributes");
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
char bf[32];
|
2013-04-17 13:13:00 -07:00
|
|
|
if (b && *b == '>')
|
|
|
|
{
|
|
|
|
// Primary device attributes
|
|
|
|
// 0 → VT100
|
|
|
|
// 1 → VT220
|
|
|
|
// 2 → VT240
|
|
|
|
// 18 → VT330
|
|
|
|
// 19 → VT340
|
|
|
|
// 24 → VT320
|
|
|
|
// 41 → VT420
|
|
|
|
// 61 → VT510
|
|
|
|
// 64 → VT520
|
|
|
|
// 65 → VT525
|
|
|
|
snprintf(bf, sizeof(bf), "\033[>41;285;%ic", 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Secondary device attributes
|
|
|
|
snprintf(bf, sizeof(bf), "\033[?64;1;2;6;9;15;18;21;22c");
|
|
|
|
}
|
2012-07-13 01:46:33 -07:00
|
|
|
termpty_write(ty, bf, strlen(bf));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'J': // "2j" erases the screen, 1j erase from screen start to curs, 0j erase cursor to end of screen
|
2013-05-27 13:03:34 -07:00
|
|
|
DBG("2j erases the screen, 1j erase from screen start to curs, 0j erase cursor to end of screen");
|
2012-07-13 01:46:33 -07:00
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
if ((arg >= TERMPTY_CLR_END) && (arg <= TERMPTY_CLR_ALL))
|
|
|
|
_termpty_clear_screen(ty, arg);
|
|
|
|
else
|
|
|
|
ERR("invalid clr scr %i", arg);
|
|
|
|
}
|
|
|
|
else _termpty_clear_screen(ty, TERMPTY_CLR_END);
|
|
|
|
break;
|
|
|
|
case 'K': // 0K erase to end of line, 1K erase from screen start to cursor, 2K erase all of line
|
|
|
|
arg = _csi_arg_get(&b);
|
2014-03-15 10:35:59 -07:00
|
|
|
DBG("0K erase to end of line, 1K erase from screen start to cursor, 2K erase all of line: %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
if ((arg >= TERMPTY_CLR_END) && (arg <= TERMPTY_CLR_ALL))
|
|
|
|
_termpty_clear_line(ty, arg, ty->w);
|
|
|
|
else
|
|
|
|
ERR("invalid clr lin %i", arg);
|
|
|
|
}
|
|
|
|
else _termpty_clear_line(ty, TERMPTY_CLR_END, ty->w);
|
|
|
|
break;
|
2014-08-11 13:02:56 -07:00
|
|
|
case 'h':
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'l':
|
2014-08-11 13:02:56 -07:00
|
|
|
_handle_esc_csi_reset_mode(ty, *cc, b);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (!b)
|
|
|
|
{
|
2013-11-10 06:35:16 -08:00
|
|
|
WRN("no region args reset region");
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.scroll_y1 = 0;
|
|
|
|
ty->state.scroll_y2 = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int arg2;
|
|
|
|
|
|
|
|
arg2 = _csi_arg_get(&b);
|
|
|
|
if (!b)
|
|
|
|
{
|
2013-11-10 06:35:16 -08:00
|
|
|
WRN("failed to give 2 regions args reset region");
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.scroll_y1 = 0;
|
|
|
|
ty->state.scroll_y2 = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (arg > arg2)
|
|
|
|
{
|
2013-11-10 06:35:16 -08:00
|
|
|
DBG("scroll region beginning > end [%i %i]", arg, arg2);
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.scroll_y1 = 0;
|
|
|
|
ty->state.scroll_y2 = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-10 06:35:16 -08:00
|
|
|
DBG("2 regions args: %i %i", arg, arg2);
|
2012-07-13 01:46:33 -07:00
|
|
|
if (arg >= ty->h) arg = ty->h - 1;
|
2014-06-08 06:52:34 -07:00
|
|
|
if (arg == 0) arg = 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
if (arg2 > ty->h) arg2 = ty->h;
|
|
|
|
ty->state.scroll_y1 = arg - 1;
|
2013-11-16 10:27:09 -08:00
|
|
|
ty->state.scroll_y2 = arg2;
|
2013-11-17 08:25:09 -08:00
|
|
|
if ((arg == 1) && (arg2 == ty->h))
|
|
|
|
ty->state.scroll_y2 = 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's': // store cursor pos
|
|
|
|
_termpty_cursor_copy(&(ty->state), &(ty->save));
|
|
|
|
break;
|
|
|
|
case 'u': // restore cursor pos
|
|
|
|
_termpty_cursor_copy(&(ty->save), &(ty->state));
|
|
|
|
break;
|
2014-03-01 06:39:20 -08:00
|
|
|
case 'p': // define key assignments based on keycode
|
|
|
|
if (b && *b == '!')
|
|
|
|
{
|
|
|
|
DBG("soft reset (DECSTR)");
|
|
|
|
_termpty_reset_state(ty);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
goto unhandled;
|
|
|
|
}
|
|
|
|
break;
|
2014-08-14 12:48:26 -07:00
|
|
|
case 'n':
|
|
|
|
_handle_esc_csi_dsr(ty, b);
|
|
|
|
break;
|
2012-07-13 01:46:33 -07:00
|
|
|
/*
|
|
|
|
case 'R': // report cursor
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
break;
|
|
|
|
case 'q': // set/clear led's
|
|
|
|
break;
|
|
|
|
case 'x': // request terminal parameters
|
|
|
|
break;
|
|
|
|
case 'r': // set top and bottom margins
|
|
|
|
break;
|
|
|
|
case 'y': // invoke confidence test
|
|
|
|
break;
|
2015-01-10 08:02:54 -08:00
|
|
|
*/
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'g': // clear tabulation
|
2015-01-10 08:02:54 -08:00
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
DBG("Tabulation Clear (TBC): %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
2012-10-04 08:23:07 -07:00
|
|
|
case 'Z': // Cursor Back Tab
|
|
|
|
{
|
2012-10-23 07:47:51 -07:00
|
|
|
int idx, size, cx = ty->state.cx, cy = ty->state.cy;
|
2012-10-04 08:23:07 -07:00
|
|
|
|
|
|
|
arg = _csi_arg_get(&b);
|
|
|
|
if (arg < 1) arg = 1;
|
|
|
|
|
|
|
|
size = ty->w * cy + cx + 1;
|
2012-10-23 07:47:51 -07:00
|
|
|
for (idx = size - 1; idx >= 0; idx--)
|
2012-10-04 08:23:07 -07:00
|
|
|
{
|
2013-01-21 06:02:32 -08:00
|
|
|
if (TERMPTY_SCREEN(ty, cx, cy).att.tab) arg--;
|
2012-10-04 08:23:07 -07:00
|
|
|
cx--;
|
|
|
|
if (cx < 0)
|
|
|
|
{
|
|
|
|
cx = ty->w - 1;
|
|
|
|
cy--;
|
|
|
|
}
|
|
|
|
if (!arg) break;
|
|
|
|
}
|
|
|
|
if (!arg)
|
|
|
|
{
|
|
|
|
ty->state.cx = cx;
|
|
|
|
ty->state.cy = cy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-07-13 01:46:33 -07:00
|
|
|
default:
|
2014-03-01 06:29:32 -08:00
|
|
|
goto unhandled;
|
|
|
|
}
|
|
|
|
cc++;
|
|
|
|
return cc - c;
|
|
|
|
unhandled:
|
|
|
|
{
|
2014-03-05 12:42:33 -08:00
|
|
|
Eina_Strbuf *bf = eina_strbuf_new();
|
|
|
|
|
|
|
|
for (i = 0; c + i <= cc && i < 100; i++)
|
|
|
|
{
|
|
|
|
if ((c[i] < ' ') || (c[i] >= 0x7f))
|
2015-02-23 13:20:18 -08:00
|
|
|
eina_strbuf_append_printf(bf, "\033[35m%08x\033[0m",
|
|
|
|
(unsigned int) c[i]);
|
2014-03-05 12:42:33 -08:00
|
|
|
else
|
|
|
|
eina_strbuf_append_char(bf, c[i]);
|
|
|
|
}
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("unhandled CSI '%c': %s", (int) *cc, eina_strbuf_string_get(bf));
|
2014-03-05 12:42:33 -08:00
|
|
|
eina_strbuf_free(bf);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
cc++;
|
|
|
|
return cc - c;
|
|
|
|
}
|
|
|
|
|
2014-08-17 08:32:57 -07:00
|
|
|
static int
|
|
|
|
_xterm_arg_get(Eina_Unicode **ptr)
|
|
|
|
{
|
|
|
|
Eina_Unicode *b = *ptr;
|
|
|
|
int sum = 0;
|
|
|
|
|
2014-09-15 14:10:55 -07:00
|
|
|
while (*b >= '0' && *b <= '9')
|
2014-08-17 08:32:57 -07:00
|
|
|
{
|
|
|
|
sum *= 10;
|
|
|
|
sum += *b - '0';
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
if (*b != ';')
|
|
|
|
sum = -1;
|
|
|
|
else
|
|
|
|
b++;
|
|
|
|
*ptr = b;
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
2014-08-17 13:20:40 -07:00
|
|
|
static int
|
|
|
|
_eina_unicode_to_hex(Eina_Unicode u)
|
|
|
|
{
|
|
|
|
if (u >= '0' && u <= '9')
|
|
|
|
return u - '0';
|
|
|
|
if (u >= 'a' && u <= 'f')
|
|
|
|
return 10 + u - 'a';
|
|
|
|
if (u >= 'A' && u <= 'F')
|
|
|
|
return 10 + u - 'A';
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_xterm_parse_color(Eina_Unicode **ptr, unsigned char *r, unsigned char *g,
|
|
|
|
unsigned char *b, int len)
|
|
|
|
{
|
|
|
|
Eina_Unicode *p = *ptr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (*p != '#')
|
|
|
|
{
|
|
|
|
ERR("unsupported xterm color");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
len--;
|
|
|
|
if (len == 7)
|
|
|
|
{
|
|
|
|
i = _eina_unicode_to_hex(p[0]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*r = i;
|
|
|
|
i = _eina_unicode_to_hex(p[1]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*r = *r * 16 + i;
|
|
|
|
|
|
|
|
i = _eina_unicode_to_hex(p[2]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*g = i;
|
|
|
|
i = _eina_unicode_to_hex(p[3]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*g = *g * 16 + i;
|
|
|
|
|
|
|
|
i = _eina_unicode_to_hex(p[4]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*b = i;
|
|
|
|
i = _eina_unicode_to_hex(p[5]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*b = *b * 16 + i;
|
|
|
|
}
|
|
|
|
else if (len == 4)
|
|
|
|
{
|
|
|
|
i = _eina_unicode_to_hex(p[0]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*r = i;
|
|
|
|
i = _eina_unicode_to_hex(p[1]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*g = i;
|
|
|
|
i = _eina_unicode_to_hex(p[2]);
|
|
|
|
if (i < 0) goto err;
|
|
|
|
*b = i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
ERR("invalid xterm color");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-12 14:11:12 -08:00
|
|
|
static void
|
|
|
|
_handle_xterm_777_command(Termpty *ty EINA_UNUSED,
|
2015-02-14 03:08:50 -08:00
|
|
|
char *s
|
|
|
|
#if ((ELM_VERSION_MAJOR == 1) && (ELM_VERSION_MINOR < 8))
|
|
|
|
EINA_UNUSED
|
|
|
|
#endif
|
|
|
|
, int len EINA_UNUSED)
|
2015-01-12 14:11:12 -08:00
|
|
|
{
|
|
|
|
#if (ELM_VERSION_MAJOR > 1) || (ELM_VERSION_MINOR >= 8)
|
|
|
|
char *cmd_end = NULL,
|
|
|
|
*title = NULL,
|
|
|
|
*title_end = NULL,
|
|
|
|
*message = NULL;
|
|
|
|
|
|
|
|
if (strncmp(s, "notify;", strlen("notify;")))
|
|
|
|
{
|
|
|
|
ERR("unrecognized xterm 777 command %s", s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!elm_need_sys_notify())
|
|
|
|
{
|
|
|
|
ERR("no elementary system notification support");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cmd_end = s + strlen("notify");
|
|
|
|
if (*cmd_end != ';')
|
|
|
|
return;
|
|
|
|
*cmd_end = '\0';
|
|
|
|
title = cmd_end + 1;
|
|
|
|
title_end = strchr(title, ';');
|
|
|
|
if (!title_end)
|
|
|
|
{
|
|
|
|
*cmd_end = ';';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*title_end = '\0';
|
|
|
|
message = title_end + 1;
|
|
|
|
|
|
|
|
elm_sys_notify_send(0, "dialog-information", title, message,
|
|
|
|
ELM_SYS_NOTIFY_URGENCY_NORMAL, -1,
|
|
|
|
NULL, NULL);
|
|
|
|
*cmd_end = ';';
|
|
|
|
*title_end = ';';
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:46:33 -07:00
|
|
|
static int
|
|
|
|
_handle_esc_xterm(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
|
|
|
{
|
2014-03-05 13:23:13 -08:00
|
|
|
const Eina_Unicode *cc, *be;
|
2014-08-17 13:20:40 -07:00
|
|
|
Eina_Unicode buf[4096], *p;
|
2012-07-13 01:46:33 -07:00
|
|
|
char *s;
|
|
|
|
int len = 0;
|
2014-08-17 08:32:57 -07:00
|
|
|
int arg;
|
2014-03-05 13:23:13 -08:00
|
|
|
|
2012-09-28 04:12:15 -07:00
|
|
|
cc = c;
|
2014-08-17 13:20:40 -07:00
|
|
|
p = buf;
|
2014-03-05 13:23:13 -08:00
|
|
|
be = buf + sizeof(buf) / sizeof(buf[0]);
|
2014-08-17 13:20:40 -07:00
|
|
|
while ((cc < ce) && (*cc != ST) && (*cc != BEL) && (p < be))
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2012-10-04 16:18:54 -07:00
|
|
|
if ((cc < ce - 1) && (*cc == ESC) && (*(cc + 1) == '\\'))
|
|
|
|
{
|
|
|
|
cc++;
|
|
|
|
break;
|
|
|
|
}
|
2014-08-17 13:20:40 -07:00
|
|
|
*p = *cc;
|
|
|
|
p++;
|
2012-07-13 01:46:33 -07:00
|
|
|
cc++;
|
|
|
|
}
|
2014-08-17 13:20:40 -07:00
|
|
|
if (p == be)
|
2014-03-05 13:23:13 -08:00
|
|
|
{
|
|
|
|
ERR("xterm parsing overflowed, skipping the whole buffer (binary data?)");
|
|
|
|
return cc - c;
|
|
|
|
}
|
2014-08-17 13:20:40 -07:00
|
|
|
*p = 0;
|
|
|
|
p = buf;
|
2012-10-04 16:18:54 -07:00
|
|
|
if ((*cc == ST) || (*cc == BEL) || (*cc == '\\')) cc++;
|
2012-12-14 10:52:19 -08:00
|
|
|
else return 0;
|
2014-08-17 08:32:57 -07:00
|
|
|
|
2014-08-17 08:44:19 -07:00
|
|
|
#define TERMPTY_WRITE_STR(_S) \
|
|
|
|
termpty_write(ty, _S, strlen(_S))
|
|
|
|
|
2014-08-17 13:20:40 -07:00
|
|
|
arg = _xterm_arg_get(&p);
|
2014-08-17 08:32:57 -07:00
|
|
|
switch (arg)
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2014-08-17 08:32:57 -07:00
|
|
|
case -1:
|
|
|
|
goto err;
|
|
|
|
case 0:
|
2012-07-13 01:46:33 -07:00
|
|
|
// XXX: title + name - callback
|
2014-08-17 13:20:40 -07:00
|
|
|
if (!*p)
|
2014-08-17 08:32:57 -07:00
|
|
|
goto err;
|
2014-08-17 13:20:40 -07:00
|
|
|
if (*p == '?')
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2014-08-17 08:44:19 -07:00
|
|
|
TERMPTY_WRITE_STR("\033]0;");
|
|
|
|
if (ty->prop.title)
|
|
|
|
{
|
|
|
|
TERMPTY_WRITE_STR(ty->prop.title);
|
|
|
|
}
|
|
|
|
TERMPTY_WRITE_STR("\007");
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-17 13:20:40 -07:00
|
|
|
s = eina_unicode_unicode_to_utf8(p, &len);
|
2014-08-17 08:44:19 -07:00
|
|
|
if (ty->prop.title) eina_stringshare_del(ty->prop.title);
|
|
|
|
if (ty->prop.icon) eina_stringshare_del(ty->prop.icon);
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
ty->prop.title = eina_stringshare_add(s);
|
|
|
|
ty->prop.icon = eina_stringshare_add(s);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->prop.title = NULL;
|
|
|
|
ty->prop.icon = NULL;
|
|
|
|
}
|
|
|
|
if (ty->cb.set_title.func) ty->cb.set_title.func(ty->cb.set_title.data);
|
|
|
|
if (ty->cb.set_icon.func) ty->cb.set_icon.func(ty->cb.set_icon.data);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
break;
|
2014-08-17 08:32:57 -07:00
|
|
|
case 1:
|
2014-08-17 08:44:19 -07:00
|
|
|
// XXX: icon name - callback
|
2014-08-17 13:20:40 -07:00
|
|
|
if (!*p)
|
2014-08-17 08:32:57 -07:00
|
|
|
goto err;
|
2014-08-17 13:20:40 -07:00
|
|
|
if (*p == '?')
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2014-08-17 08:44:19 -07:00
|
|
|
TERMPTY_WRITE_STR("\033]0;");
|
|
|
|
if (ty->prop.icon)
|
|
|
|
{
|
|
|
|
TERMPTY_WRITE_STR(ty->prop.icon);
|
|
|
|
}
|
|
|
|
TERMPTY_WRITE_STR("\007");
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-17 13:20:40 -07:00
|
|
|
s = eina_unicode_unicode_to_utf8(p, &len);
|
2014-08-17 08:44:19 -07:00
|
|
|
if (ty->prop.icon) eina_stringshare_del(ty->prop.icon);
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
ty->prop.icon = eina_stringshare_add(s);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->prop.icon = NULL;
|
|
|
|
}
|
|
|
|
if (ty->cb.set_icon.func) ty->cb.set_icon.func(ty->cb.set_icon.data);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
break;
|
2014-08-17 08:32:57 -07:00
|
|
|
case 2:
|
2014-08-17 08:44:19 -07:00
|
|
|
// XXX: title - callback
|
2014-08-17 13:20:40 -07:00
|
|
|
if (!*p)
|
2014-08-17 08:32:57 -07:00
|
|
|
goto err;
|
2014-08-17 13:20:40 -07:00
|
|
|
if (*p == '?')
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2014-08-17 08:44:19 -07:00
|
|
|
TERMPTY_WRITE_STR("\033]0;");
|
|
|
|
if (ty->prop.title)
|
|
|
|
{
|
|
|
|
TERMPTY_WRITE_STR(ty->prop.title);
|
|
|
|
}
|
|
|
|
TERMPTY_WRITE_STR("\007");
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-17 13:20:40 -07:00
|
|
|
s = eina_unicode_unicode_to_utf8(p, &len);
|
2014-08-17 08:44:19 -07:00
|
|
|
if (ty->prop.title) eina_stringshare_del(ty->prop.title);
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
ty->prop.title = eina_stringshare_add(s);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->prop.title = NULL;
|
|
|
|
}
|
|
|
|
if (ty->cb.set_title.func) ty->cb.set_title.func(ty->cb.set_title.data);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
break;
|
2014-08-17 08:32:57 -07:00
|
|
|
case 4:
|
2014-08-17 13:20:40 -07:00
|
|
|
if (!*p)
|
2014-08-17 08:32:57 -07:00
|
|
|
goto err;
|
2012-07-13 01:46:33 -07:00
|
|
|
// XXX: set palette entry. not supported.
|
2014-08-17 08:32:57 -07:00
|
|
|
WRN("set palette, not supported");
|
2012-12-14 10:52:19 -08:00
|
|
|
if ((cc - c) < 3) return 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
2014-08-17 13:20:40 -07:00
|
|
|
case 10:
|
|
|
|
if (!*p)
|
|
|
|
goto err;
|
|
|
|
if (*p == '?')
|
|
|
|
{
|
|
|
|
char bf[6];
|
|
|
|
Config *config = termio_config_get(ty->obj);
|
|
|
|
TERMPTY_WRITE_STR("\033]10;#");
|
|
|
|
snprintf(bf, sizeof(bf), "%.2X%.2X%.2X",
|
|
|
|
config->colors[0].r,
|
|
|
|
config->colors[0].g,
|
|
|
|
config->colors[0].b);
|
|
|
|
termpty_write(ty, bf, 6);
|
|
|
|
TERMPTY_WRITE_STR("\007");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned char r, g, b;
|
|
|
|
len = cc - c - (p - buf);
|
|
|
|
if (_xterm_parse_color(&p, &r, &g, &b, len) < 0)
|
|
|
|
goto err;
|
|
|
|
evas_object_textgrid_palette_set(
|
|
|
|
termio_textgrid_get(ty->obj),
|
|
|
|
EVAS_TEXTGRID_PALETTE_STANDARD, 0,
|
|
|
|
r, g, b, 0xff);
|
|
|
|
}
|
|
|
|
break;
|
2015-01-12 14:11:12 -08:00
|
|
|
case 777:
|
|
|
|
DBG("xterm notification support");
|
|
|
|
s = eina_unicode_unicode_to_utf8(p, &len);
|
|
|
|
if (s)
|
|
|
|
{
|
|
|
|
_handle_xterm_777_command(ty, s, len);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
break;
|
2012-07-13 01:46:33 -07:00
|
|
|
default:
|
|
|
|
// many others
|
2014-08-17 08:32:57 -07:00
|
|
|
ERR("unhandled xterm esc %d", arg);
|
2012-07-13 01:46:33 -07:00
|
|
|
break;
|
|
|
|
}
|
2014-08-17 08:44:19 -07:00
|
|
|
|
|
|
|
#undef TERMPTY_WRITE_STR
|
|
|
|
|
2012-07-13 01:46:33 -07:00
|
|
|
return cc - c;
|
2014-08-17 08:32:57 -07:00
|
|
|
err:
|
|
|
|
ERR("invalid xterm sequence");
|
|
|
|
return cc - c;
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-03-13 18:58:43 -07:00
|
|
|
_handle_esc_terminology(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2013-03-17 07:52:13 -07:00
|
|
|
Eina_Unicode *cc;
|
2013-01-29 07:54:47 -08:00
|
|
|
Eina_Unicode *buf, bufsmall[1024], *b;
|
2012-07-13 01:46:33 -07:00
|
|
|
char *s;
|
2013-01-29 07:54:47 -08:00
|
|
|
int blen = 0, slen = 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
|
2013-01-29 07:54:47 -08:00
|
|
|
cc = (Eina_Unicode *)c;
|
|
|
|
while ((cc < ce) && (*cc != 0x0))
|
|
|
|
{
|
|
|
|
blen++;
|
|
|
|
cc++;
|
|
|
|
}
|
|
|
|
buf = bufsmall;
|
2013-03-14 04:27:36 -07:00
|
|
|
if (blen > (int)((sizeof(bufsmall) / sizeof(Eina_Unicode)) - 40))
|
|
|
|
buf = malloc((blen * sizeof(Eina_Unicode)) + 40);
|
2012-07-13 01:46:33 -07:00
|
|
|
cc = (Eina_Unicode *)c;
|
|
|
|
b = buf;
|
2013-03-14 04:27:36 -07:00
|
|
|
while ((cc < ce) && (*cc != 0x0))
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
*b = *cc;
|
|
|
|
b++;
|
|
|
|
cc++;
|
|
|
|
}
|
2013-03-14 04:27:36 -07:00
|
|
|
if ((cc < ce) && (*cc == 0x0)) cc++;
|
2013-01-29 07:54:47 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (buf != bufsmall) free(buf);
|
2013-03-14 04:27:36 -07:00
|
|
|
return 0;
|
2013-01-29 07:54:47 -08:00
|
|
|
}
|
2013-03-13 18:58:43 -07:00
|
|
|
*b = 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
// commands are stored in the buffer, 0 bytes not allowd (end marker)
|
|
|
|
s = eina_unicode_unicode_to_utf8(buf, &slen);
|
|
|
|
ty->cur_cmd = s;
|
2012-07-13 01:47:14 -07:00
|
|
|
if (!_termpty_ext_handle(ty, s, buf))
|
|
|
|
{
|
|
|
|
if (ty->cb.command.func) ty->cb.command.func(ty->cb.command.data);
|
|
|
|
}
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->cur_cmd = NULL;
|
2013-11-07 15:13:37 -08:00
|
|
|
free(s);
|
2013-01-29 07:54:47 -08:00
|
|
|
if (buf != bufsmall) free(buf);
|
2012-07-13 01:46:33 -07:00
|
|
|
return cc - c;
|
|
|
|
}
|
|
|
|
|
2012-10-04 16:18:59 -07:00
|
|
|
static int
|
2013-08-27 06:36:50 -07:00
|
|
|
_handle_esc_dcs(Termpty *ty EINA_UNUSED, const Eina_Unicode *c, const Eina_Unicode *ce)
|
2012-10-04 16:18:59 -07:00
|
|
|
{
|
2013-03-13 18:58:43 -07:00
|
|
|
const Eina_Unicode *cc, *be;
|
2012-10-04 16:18:59 -07:00
|
|
|
Eina_Unicode buf[4096], *b;
|
2013-06-19 01:18:42 -07:00
|
|
|
int len = 0;
|
2013-04-17 13:55:37 -07:00
|
|
|
|
2012-10-04 16:18:59 -07:00
|
|
|
cc = c;
|
|
|
|
b = buf;
|
2013-03-13 18:58:43 -07:00
|
|
|
be = buf + sizeof(buf) / sizeof(buf[0]);
|
2014-03-05 13:23:13 -08:00
|
|
|
while ((cc < ce) && (*cc != ST) && (b < be))
|
2012-10-04 16:18:59 -07:00
|
|
|
{
|
|
|
|
if ((cc < ce - 1) && (*cc == ESC) && (*(cc + 1) == '\\'))
|
|
|
|
{
|
|
|
|
cc++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*b = *cc;
|
|
|
|
b++;
|
|
|
|
cc++;
|
|
|
|
}
|
2013-03-13 18:58:43 -07:00
|
|
|
if (b == be)
|
2013-04-17 13:55:37 -07:00
|
|
|
{
|
2014-02-11 13:18:12 -08:00
|
|
|
ERR("dcs parsing overflowed, skipping the whole buffer (binary data?)");
|
|
|
|
len = cc - c;
|
2013-04-17 13:55:37 -07:00
|
|
|
goto end;
|
|
|
|
}
|
2012-10-04 16:18:59 -07:00
|
|
|
*b = 0;
|
|
|
|
if ((*cc == ST) || (*cc == '\\')) cc++;
|
2012-12-14 10:52:19 -08:00
|
|
|
else return 0;
|
2013-05-10 14:01:58 -07:00
|
|
|
len = cc - c;
|
2012-10-04 16:18:59 -07:00
|
|
|
switch (buf[0])
|
|
|
|
{
|
|
|
|
case '+':
|
2013-05-10 14:02:46 -07:00
|
|
|
if (len < 4)
|
|
|
|
goto end;
|
|
|
|
switch (buf[1])
|
|
|
|
{
|
|
|
|
case 'q':
|
|
|
|
ERR("unhandled dsc request to get termcap/terminfo");
|
|
|
|
/* TODO */
|
|
|
|
goto end;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
ERR("unhandled dsc request to set termcap/terminfo");
|
|
|
|
/* TODO */
|
|
|
|
goto end;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR("invalid dsc request about termcap/terminfo");
|
|
|
|
goto end;
|
|
|
|
}
|
2012-10-04 16:18:59 -07:00
|
|
|
break;
|
2013-04-17 13:55:37 -07:00
|
|
|
case '$':
|
|
|
|
/* Request status string */
|
|
|
|
if (len > 1 && buf[1] != 'q')
|
|
|
|
{
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("invalid/unhandled dsc esc '$%c' (expected '$q')",
|
|
|
|
(int) buf[1]);
|
2013-04-17 13:55:37 -07:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (len < 4)
|
|
|
|
goto end;
|
|
|
|
switch (buf[2])
|
|
|
|
{
|
|
|
|
case '"':
|
|
|
|
if (buf[3] == 'p') /* DECSCL */
|
|
|
|
{
|
|
|
|
char bf[32];
|
|
|
|
snprintf(bf, sizeof(bf), "\033P1$r64;1\"p\033\\");
|
|
|
|
termpty_write(ty, bf, strlen(bf));
|
|
|
|
}
|
|
|
|
else if (buf[3] == 'q') /* DECSCA */
|
|
|
|
{
|
2013-05-10 14:02:46 -07:00
|
|
|
ERR("unhandled DECSCA '$qq'");
|
|
|
|
goto end;
|
2013-04-17 13:55:37 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("invalid/unhandled dsc esc '$q\"%c'", (int) buf[3]);
|
2013-04-17 13:55:37 -07:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm': /* SGR */
|
|
|
|
/* TODO: */
|
|
|
|
case 'r': /* DECSTBM */
|
|
|
|
/* TODO: */
|
|
|
|
default:
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("unhandled dsc request status string '$q%c'",
|
|
|
|
(int) buf[2]);
|
2013-04-17 13:55:37 -07:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
/* TODO */
|
|
|
|
break;
|
2012-10-04 16:18:59 -07:00
|
|
|
default:
|
|
|
|
// many others
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("Unhandled DCS escape '%c'", (int) buf[0]);
|
2012-10-04 16:18:59 -07:00
|
|
|
break;
|
|
|
|
}
|
2013-04-17 13:55:37 -07:00
|
|
|
end:
|
|
|
|
return len;
|
2012-10-04 16:18:59 -07:00
|
|
|
}
|
|
|
|
|
2012-07-13 01:46:33 -07:00
|
|
|
static int
|
|
|
|
_handle_esc(Termpty *ty, const Eina_Unicode *c, Eina_Unicode *ce)
|
|
|
|
{
|
2012-12-14 10:52:19 -08:00
|
|
|
int len = ce - c;
|
|
|
|
|
|
|
|
if (len < 1) return 0;
|
2015-02-23 13:20:18 -08:00
|
|
|
DBG("ESC: '%c'", (int) c[0]);
|
2012-12-14 10:52:19 -08:00
|
|
|
switch (c[0])
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
case '[':
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc_csi(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-07-13 01:46:33 -07:00
|
|
|
case ']':
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc_xterm(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '}':
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc_terminology(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-10-04 16:18:59 -07:00
|
|
|
case 'P':
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc_dcs(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '=': // set alternate keypad mode
|
|
|
|
ty->state.alt_kp = 1;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '>': // set numeric keypad mode
|
|
|
|
ty->state.alt_kp = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'M': // move to prev line
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cy--;
|
2013-04-18 14:12:15 -07:00
|
|
|
_termpty_text_scroll_rev_test(ty, EINA_TRUE);
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'D': // move to next line
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cy++;
|
2013-04-18 14:12:15 -07:00
|
|
|
_termpty_text_scroll_test(ty, EINA_FALSE);
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'E': // add \n\r
|
|
|
|
ty->state.wrapnext = 0;
|
|
|
|
ty->state.cx = 0;
|
|
|
|
ty->state.cy++;
|
2013-04-18 14:12:15 -07:00
|
|
|
_termpty_text_scroll_test(ty, EINA_FALSE);
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'Z': // same a 'ESC [ Pn c'
|
|
|
|
_term_txt_write(ty, "\033[?1;2C");
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'c': // reset terminal to initial state
|
|
|
|
DBG("reset to init mode and clear");
|
|
|
|
_termpty_reset_state(ty);
|
|
|
|
_termpty_clear_screen(ty, TERMPTY_CLR_ALL);
|
|
|
|
if (ty->cb.cancel_sel.func)
|
|
|
|
ty->cb.cancel_sel.func(ty->cb.cancel_sel.data);
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '(': // charset 0
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
ty->state.chset[0] = c[1];
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.multibyte = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
ty->state.charsetch = c[1];
|
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case ')': // charset 1
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
ty->state.chset[1] = c[1];
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.multibyte = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '*': // charset 2
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
ty->state.chset[2] = c[1];
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.multibyte = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '+': // charset 3
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
ty->state.chset[3] = c[1];
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.multibyte = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '$': // charset -2
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
ty->state.chset[2] = c[1];
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.multibyte = 1;
|
2012-12-14 10:52:19 -08:00
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '#': // #8 == test mode -> fill screen with "E";
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
if (c[1] == '8')
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
2013-01-29 07:54:47 -08:00
|
|
|
int size;
|
2012-07-13 01:46:33 -07:00
|
|
|
Termcell *cells;
|
|
|
|
|
|
|
|
DBG("reset to init mode and clear then fill with E");
|
|
|
|
_termpty_reset_state(ty);
|
|
|
|
ty->save = ty->state;
|
|
|
|
ty->swap = ty->state;
|
|
|
|
_termpty_clear_screen(ty, TERMPTY_CLR_ALL);
|
|
|
|
if (ty->cb.cancel_sel.func)
|
|
|
|
ty->cb.cancel_sel.func(ty->cb.cancel_sel.data);
|
|
|
|
cells = ty->screen;
|
|
|
|
size = ty->w * ty->h;
|
|
|
|
if (cells)
|
|
|
|
{
|
2013-01-29 07:54:47 -08:00
|
|
|
Termatt att;
|
|
|
|
|
|
|
|
memset((&att), 0, sizeof(att));
|
|
|
|
termpty_cell_codepoint_att_fill(ty, 'E', att, cells, size);
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
}
|
2012-12-14 10:52:19 -08:00
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '@': // just consume this plus next char
|
2012-12-14 10:52:19 -08:00
|
|
|
if (len < 2) return 0;
|
|
|
|
return 2;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '7': // save cursor pos
|
|
|
|
_termpty_cursor_copy(&(ty->state), &(ty->save));
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case '8': // restore cursor pos
|
|
|
|
_termpty_cursor_copy(&(ty->save), &(ty->state));
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2015-01-10 09:48:48 -08:00
|
|
|
case 'H': // set tab at current column
|
|
|
|
DBG("Character Tabulation Set (HTS)");
|
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
/*
|
|
|
|
case 'G': // query gfx mode
|
|
|
|
return 2;
|
|
|
|
case 'n': // single shift 2
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
case 'o': // single shift 3
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
*/
|
|
|
|
default:
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("Unhandled escape '%c' (0x%02x)", (int) c[0], (unsigned int) c[0]);
|
2012-12-14 10:52:19 -08:00
|
|
|
return 1;
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
2012-12-14 10:52:19 -08:00
|
|
|
return 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
|
|
|
|
2014-09-15 14:10:55 -07:00
|
|
|
/* XXX: ce is excluded */
|
2012-07-13 01:46:33 -07:00
|
|
|
int
|
2014-09-15 14:10:55 -07:00
|
|
|
termpty_handle_seq(Termpty *ty, Eina_Unicode *c, Eina_Unicode *ce)
|
2012-07-13 01:46:33 -07:00
|
|
|
{
|
|
|
|
Eina_Unicode *cc;
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
printf(" B: ");
|
|
|
|
int j;
|
|
|
|
for (j = 0; c + j < ce && j < 100; j++)
|
|
|
|
{
|
|
|
|
if ((c[j] < ' ') || (c[j] >= 0x7f))
|
2012-09-28 04:12:04 -07:00
|
|
|
printf("\033[35m%08x\033[0m", c[j]);
|
2012-07-13 01:46:33 -07:00
|
|
|
else
|
|
|
|
printf("%c", c[j]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
*/
|
|
|
|
if (c[0] < 0x20)
|
|
|
|
{
|
|
|
|
switch (c[0])
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
case 0x00: // NUL
|
|
|
|
return 1;
|
|
|
|
case 0x01: // SOH (start of heading)
|
|
|
|
return 1;
|
|
|
|
case 0x02: // STX (start of text)
|
|
|
|
return 1;
|
|
|
|
case 0x03: // ETX (end of text)
|
|
|
|
return 1;
|
|
|
|
case 0x04: // EOT (end of transmission)
|
|
|
|
return 1;
|
|
|
|
*/
|
2013-03-13 18:58:43 -07:00
|
|
|
/*
|
2012-07-13 01:46:33 -07:00
|
|
|
case 0x05: // ENQ (enquiry)
|
|
|
|
_term_txt_write(ty, "ABC\r\n");
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
return 1;
|
2013-03-13 18:58:43 -07:00
|
|
|
*/
|
2012-07-13 01:46:33 -07:00
|
|
|
/*
|
|
|
|
case 0x06: // ACK (acknowledge)
|
|
|
|
return 1;
|
|
|
|
*/
|
|
|
|
case 0x07: // BEL '\a' (bell)
|
|
|
|
case 0x08: // BS '\b' (backspace)
|
|
|
|
case 0x09: // HT '\t' (horizontal tab)
|
|
|
|
case 0x0a: // LF '\n' (new line)
|
|
|
|
case 0x0b: // VT '\v' (vertical tab)
|
|
|
|
case 0x0c: // FF '\f' (form feed)
|
|
|
|
case 0x0d: // CR '\r' (carriage ret)
|
2013-04-27 12:17:14 -07:00
|
|
|
_handle_cursor_control(ty, c);
|
2012-07-13 01:46:33 -07:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
case 0x0e: // SO (shift out) // Maps G1 character set into GL.
|
2013-05-03 19:44:20 -07:00
|
|
|
ty->state.had_cr = 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.charset = 1;
|
|
|
|
ty->state.charsetch = ty->state.chset[1];
|
|
|
|
return 1;
|
|
|
|
case 0x0f: // SI (shift in) // Maps G0 character set into GL.
|
|
|
|
ty->state.charset = 0;
|
2013-05-03 19:44:20 -07:00
|
|
|
ty->state.had_cr = 0;
|
2012-07-13 01:46:33 -07:00
|
|
|
ty->state.charsetch = ty->state.chset[0];
|
|
|
|
return 1;
|
|
|
|
/*
|
|
|
|
case 0x10: // DLE (data link escape)
|
|
|
|
return 1;
|
|
|
|
case 0x11: // DC1 (device control 1)
|
|
|
|
return 1;
|
|
|
|
case 0x12: // DC2 (device control 2)
|
|
|
|
return 1;
|
|
|
|
case 0x13: // DC3 (device control 3)
|
|
|
|
return 1;
|
|
|
|
case 0x14: // DC4 (device control 4)
|
|
|
|
return 1;
|
|
|
|
case 0x15: // NAK (negative ack.)
|
|
|
|
return 1;
|
|
|
|
case 0x16: // SYN (synchronous idle)
|
|
|
|
return 1;
|
|
|
|
case 0x17: // ETB (end of trans. blk)
|
|
|
|
return 1;
|
|
|
|
case 0x18: // CAN (cancel)
|
|
|
|
return 1;
|
|
|
|
case 0x19: // EM (end of medium)
|
|
|
|
return 1;
|
|
|
|
case 0x1a: // SUB (substitute)
|
|
|
|
return 1;
|
|
|
|
*/
|
|
|
|
case 0x1b: // ESC (escape)
|
|
|
|
ty->state.had_cr = 0;
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-07-13 01:46:33 -07:00
|
|
|
/*
|
|
|
|
case 0x1c: // FS (file separator)
|
|
|
|
return 1;
|
|
|
|
case 0x1d: // GS (group separator)
|
|
|
|
return 1;
|
|
|
|
case 0x1e: // RS (record separator)
|
|
|
|
return 1;
|
|
|
|
case 0x1f: // US (unit separator)
|
|
|
|
return 1;
|
|
|
|
*/
|
|
|
|
default:
|
|
|
|
ty->state.had_cr = 0;
|
2013-05-03 19:44:20 -07:00
|
|
|
//ERR("unhandled char 0x%02x", c[0]);
|
2012-07-13 01:46:33 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (c[0] == 0x7f) // DEL
|
|
|
|
{
|
|
|
|
ty->state.had_cr = 0;
|
2015-02-23 13:20:18 -08:00
|
|
|
ERR("Unhandled char 0x%02x [DEL]", (unsigned int) c[0]);
|
2012-07-13 01:46:33 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (c[0] == 0x9b) // ANSI ESC!!!
|
|
|
|
{
|
|
|
|
ty->state.had_cr = 0;
|
2013-05-03 19:44:20 -07:00
|
|
|
DBG("ANSI CSI!!!!!");
|
2012-12-14 10:52:19 -08:00
|
|
|
len = _handle_esc_csi(ty, c + 1, ce);
|
|
|
|
if (len == 0) return 0;
|
|
|
|
return 1 + len;
|
2012-07-13 01:46:33 -07:00
|
|
|
}
|
2013-01-28 19:34:50 -08:00
|
|
|
else if ((ty->block.expecting) && (ty->block.on))
|
2013-01-28 08:06:26 -08:00
|
|
|
{
|
2013-01-28 16:43:13 -08:00
|
|
|
Termexp *ex;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2013-05-03 19:44:20 -07:00
|
|
|
ty->state.had_cr = 0;
|
2013-01-28 16:43:13 -08:00
|
|
|
EINA_LIST_FOREACH(ty->block.expecting, l, ex)
|
2013-01-28 08:06:26 -08:00
|
|
|
{
|
2013-01-28 16:43:13 -08:00
|
|
|
if (c[0] == ex->ch)
|
2013-01-28 08:06:26 -08:00
|
|
|
{
|
2013-01-28 16:43:13 -08:00
|
|
|
Eina_Unicode cp;
|
|
|
|
|
|
|
|
cp = (1 << 31) | ((ex->id & 0x1fff) << 18) |
|
|
|
|
((ex->x & 0x1ff) << 9) | (ex->y & 0x1ff);
|
|
|
|
ex->x++;
|
|
|
|
if (ex->x >= ex->w)
|
|
|
|
{
|
|
|
|
ex->x = 0;
|
|
|
|
ex->y++;
|
|
|
|
}
|
|
|
|
ex->left--;
|
|
|
|
_termpty_text_append(ty, &cp, 1);
|
|
|
|
if (ex->left <= 0)
|
|
|
|
{
|
|
|
|
ty->block.expecting =
|
|
|
|
eina_list_remove_list(ty->block.expecting, l);
|
|
|
|
free(ex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ty->block.expecting =
|
|
|
|
eina_list_promote_list(ty->block.expecting, l);
|
|
|
|
return 1;
|
2013-01-28 08:06:26 -08:00
|
|
|
}
|
|
|
|
}
|
2013-01-28 16:43:13 -08:00
|
|
|
_termpty_text_append(ty, c, 1);
|
|
|
|
return 1;
|
2013-01-28 08:06:26 -08:00
|
|
|
}
|
2013-05-03 19:44:20 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
}
|
2015-02-23 13:20:18 -08:00
|
|
|
cc = (Eina_Unicode *)c;
|
2012-07-13 01:46:33 -07:00
|
|
|
DBG("txt: [");
|
|
|
|
while ((cc < ce) && (*cc >= 0x20) && (*cc != 0x7f))
|
|
|
|
{
|
2015-02-23 13:20:18 -08:00
|
|
|
DBG("%c", (int) *cc);
|
2012-07-13 01:46:33 -07:00
|
|
|
cc++;
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
DBG("]");
|
|
|
|
_termpty_text_append(ty, c, len);
|
|
|
|
ty->state.had_cr = 0;
|
|
|
|
return len;
|
|
|
|
}
|