handle a lot more escape codes now and mouse tracking too.

SVN revision: 72712
This commit is contained in:
Carsten Haitzler 2012-06-23 06:43:02 +00:00
parent e672d4b895
commit 099de44801
4 changed files with 403 additions and 24 deletions

View File

@ -260,6 +260,12 @@ keyin_handle(Termpty *ty, Evas_Event_Key_Down *ev)
if (_key_try(ty, appcur_keyout, ev)) return;
}
if ((ty->state.send_bs) &&
(!strcmp(ev->keyname, "Bakcspace")))
{
termpty_write(ty, "\b", 1);
return;
}
if (_key_try(ty, keyout, ev)) return;
if (ev->string)
{

View File

@ -40,6 +40,7 @@ struct _Termio
Eina_Bool sel : 1;
} backup;
int scroll;
unsigned int last_keyup;
Evas_Object *event;
Termpty *pty;
Ecore_Animator *anim;
@ -60,11 +61,12 @@ _smart_apply(Evas_Object *obj)
{
Termio *sd = evas_object_smart_data_get(obj);
Evas_Coord ox, oy, ow, oh;
int j, x, y, w, ch1 = 0, ch2 = 0;
int j, x, y, w, ch1 = 0, ch2 = 0, inv = 0;
if (!sd) return;
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
inv = sd->pty->state.reverse;
for (y = 0; y < sd->grid.h; y++)
{
Termcell *cells;
@ -87,7 +89,8 @@ _smart_apply(Evas_Object *obj)
ch2 = x;
}
tc[x].codepoint = 0;
tc[x].bg = COL_INVIS;
if (inv) tc[x].bg = COL_INVERSEBG;
else tc[x].bg = COL_INVIS;
tc[x].bg_extended = 0;
}
else
@ -102,7 +105,8 @@ _smart_apply(Evas_Object *obj)
ch2 = x;
}
tc[x].codepoint = 0;
tc[x].bg = COL_INVIS;
if (inv) tc[x].bg = COL_INVERSEBG;
else tc[x].bg = COL_INVIS;
tc[x].bg_extended = 0;
}
else
@ -115,7 +119,7 @@ _smart_apply(Evas_Object *obj)
bgext = cells[j].att.bg256;
glyph = cells[j].glyph;
if (cells[j].att.inverse)
if (cells[j].att.inverse ^ inv)
{
int t;
@ -396,6 +400,7 @@ _smart_cb_key_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, vo
sd = evas_object_smart_data_get(data);
if (!sd) return;
sd->last_keyup = ev->timestamp;
if (sd->imf)
{
Ecore_IMF_Event_Key_Up imf_ev;
@ -451,6 +456,12 @@ _smart_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
}
}
}
// if term app asked fro kbd lock - dont handle here
if (sd->pty->state.kbd_lock) return;
// if app asked us to not do autorepeat - ignore pree is it is the same
// timestamp as last one
if ((sd->pty->state.no_autorepeat) &&
(ev->timestamp == sd->last_keyup)) return;
keyin_handle(sd->pty, ev);
end:
if (sd->config->flicker_on_key)
@ -625,6 +636,197 @@ _sel_word_to(Evas_Object *obj, int cx, int cy)
}
}
static void
_rep_mouse_down(Evas_Object *obj, Evas_Event_Mouse_Down *ev, int cx, int cy)
{
Termio *sd;
char buf[64];
sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (sd->pty->state.mouse_rep == MOUSE_OFF) return;
switch (sd->pty->state.mouse_rep)
{
case MOUSE_X10:
if ((cx < (0xff - ' ')) && (cy < (0xff - ' ')))
{
int btn = ev->button - 1;
if (btn <= 2)
{
buf[0] = 0x1b;
buf[1] = '[';
buf[2] = 'M';
buf[3] = btn + ' ';
buf[4] = cx + 1 + ' ';
buf[5] = cy + 1 + ' ';
buf[6] = 0;
termpty_write(sd->pty, buf, strlen(buf));
}
}
break;
case MOUSE_UTF8: // ESC.[.M.BTN/FLGS.UTF8.YUTF8
{
int btn = ev->button - 1;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
int dbl = (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) ? 32 : 0;
int v, i;
if (btn > 2) btn = 0;
buf[0] = 0x1b;
buf[1] = '[';
buf[2] = 'M';
buf[3] = (btn | shift | meta | ctrl | dbl) + ' ';
i = 4;
v = cx + 1 + ' ';
if (v <= 127) buf[i++] = v;
else
{ // 14 bits for cx/cy - enough i think
buf[i++] = 0xc0 + (v >> 6);
buf[i++] = 0x80 + (v & 0x3f);
}
v = cy + 1 + ' ';
if (v <= 127) buf[i++] = v;
else
{ // 14 bits for cx/cy - enough i think
buf[i++] = 0xc0 + (v >> 6);
buf[i++] = 0x80 + (v & 0x3f);
}
buf[i] = 0;
termpty_write(sd->pty, buf, strlen(buf));
}
break;
case MOUSE_SGR: // ESC.[.<.NUM.;.NUM.;.NUM.M
{
int btn = ev->button - 1;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
int dbl = (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) ? 32 : 0;
snprintf(buf, sizeof(buf), "%c[<%i;%i;%iM", 0x1b,
(btn | shift | meta | ctrl | dbl), cx + 1, cy + 1);
termpty_write(sd->pty, buf, strlen(buf));
}
break;
case MOUSE_NORMAL:
case MOUSE_URXVT: // ESC.[.M.BTN/FLGS.X.Y
if ((cx < (0xff - ' ')) && (cy < (0xff - ' ')))
{
int btn = ev->button - 1;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
int dbl = (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) ? 32 : 0;
if (btn > 2) btn = 0;
buf[0] = 0x1b;
buf[1] = '[';
buf[2] = 'M';
buf[3] = (btn | shift | meta | ctrl | dbl) + ' ';
buf[4] = cx + 1 + ' ';
buf[5] = cy + 1 + ' ';
buf[6] = 0;
termpty_write(sd->pty, buf, strlen(buf));
}
break;
default:
break;
}
}
static void
_rep_mouse_up(Evas_Object *obj, Evas_Event_Mouse_Up *ev, int cx, int cy)
{
Termio *sd;
char buf[64];
sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (sd->pty->state.mouse_rep == MOUSE_OFF) return;
switch (sd->pty->state.mouse_rep)
{
case MOUSE_UTF8: // ESC.[.M.BTN/FLGS.UTF8.YUTF8
{
int btn = 3;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
int v, i;
btn = 3;
buf[0] = 0x1b;
buf[1] = '[';
buf[2] = 'M';
buf[3] = (btn | shift | meta | ctrl) + ' ';
i = 4;
v = cx + 1 + ' ';
if (v <= 127) buf[i++] = v;
else
{ // 14 bits for cx/cy - enough i think
buf[i++] = 0xc0 + (v >> 6);
buf[i++] = 0x80 + (v & 0x3f);
}
v = cy + 1 + ' ';
if (v <= 127) buf[i++] = v;
else
{ // 14 bits for cx/cy - enough i think
buf[i++] = 0xc0 + (v >> 6);
buf[i++] = 0x80 + (v & 0x3f);
}
buf[i] = 0;
termpty_write(sd->pty, buf, strlen(buf));
}
break;
case MOUSE_SGR: // ESC.[.<.NUM.;.NUM.;.NUM.M
{
int btn = 3;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
snprintf(buf, sizeof(buf), "%c[<%i;%i;%im", 0x1b,
(btn | shift | meta | ctrl), cx + 1, cy + 1);
termpty_write(sd->pty, buf, strlen(buf));
}
break;
case MOUSE_NORMAL:
case MOUSE_URXVT: // ESC.[.M.BTN/FLGS.X.Y
if ((cx < (0xff - ' ')) && (cy < (0xff - ' ')))
{
int btn = 3;
int shift = evas_key_modifier_is_set(ev->modifiers, "Shift") ? 4 : 0;
int meta = evas_key_modifier_is_set(ev->modifiers, "Alt") ? 8 : 0;
int ctrl = evas_key_modifier_is_set(ev->modifiers, "Control") ? 16 : 0;
buf[0] = 0x1b;
buf[1] = '[';
buf[2] = 'M';
buf[3] = (btn | shift | meta | ctrl) + ' ';
buf[4] = cx + 1 + ' ';
buf[5] = cy + 1 + ' ';
buf[6] = 0;
termpty_write(sd->pty, buf, strlen(buf));
}
break;
default:
break;
}
}
static void
_rep_mouse_move(Evas_Object *obj, Evas_Event_Mouse_Move *ev, int cx, int cy)
{
Termio *sd;
sd = evas_object_smart_data_get(obj);
if (!sd) return;
if (sd->pty->state.mouse_rep == MOUSE_OFF) return;
// not sure what to d here right now so do nothing.
}
static void
_smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
{
@ -635,6 +837,7 @@ _smart_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__
sd = evas_object_smart_data_get(data);
if (!sd) return;
_smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy);
_rep_mouse_down(data, ev, cx, cy);
if (ev->button == 1)
{
if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK)
@ -692,6 +895,7 @@ _smart_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
sd = evas_object_smart_data_get(data);
if (!sd) return;
_smart_xy_to_cursor(data, ev->canvas.x, ev->canvas.y, &cx, &cy);
_rep_mouse_up(data, ev, cx, cy);
if (sd->cur.makesel)
{
sd->cur.makesel = 0;
@ -715,6 +919,7 @@ _smart_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__
sd = evas_object_smart_data_get(data);
if (!sd) return;
_smart_xy_to_cursor(data, ev->cur.canvas.x, ev->cur.canvas.y, &cx, &cy);
_rep_mouse_move(data, ev, cx, cy);
if (sd->cur.makesel)
{
if (!sd->cur.sel)

View File

@ -204,7 +204,6 @@ static const int vt100_to_unicode[62] =
0x2264, 0x2265, 0x03c0, 0x2260, 0x20a4, 0x00b7
};
static void
_text_append(Termpty *ty, const int *glyphs, int len)
{
@ -891,38 +890,156 @@ _handle_esc_csi(Termpty *ty, const int *c, int *ce)
{
int size;
// complete-ish list here:
// http://ttssh2.sourceforge.jp/manual/en/about/ctrlseq.html
switch (arg)
{
case 1:
handled = 1;
ty->state.appcursor = mode;
break;
case 2:
handled = 1;
ty->state.kbd_lock = mode;
break;
case 3: // should we handle this?
handled = 1;
ERR("XXX: 132 column mode %i", mode);
break;
case 4:
handled = 1;
ERR("XXX: set insert mode to %i", mode);
break;
case 5:
handled = 1;
ty->state.reverse = mode;
break;
case 6:
handled = 1;
ERR("XXX: origin mode: cursor is at 0,0/cursor limited to screen/start point for line #'s depends on top margin");
break;
case 7:
handled = 1;
DBG("DDD: set wrap mode to %i", mode);
ty->state.wrap = mode;
break;
case 20:
ty->state.crlf = mode;
break;
case 12:
case 8:
handled = 1;
// DBG("XXX: set blinking cursor to (stop?) %i", mode);
ty->state.no_autorepeat = !mode;
INF("XXX: auto repeat %i", mode);
break;
case 9:
handled = 1;
if (mode) ty->state.mouse_rep = MOUSE_X10;
else ty->state.mouse_rep = MOUSE_OFF;
break;
case 12: // ignore
handled = 1;
// DBG("XXX: set blinking cursor to (stop?) %i or local echo", mode);
break;
case 19: // never seen this - what to do?
handled = 1;
// INF("XXX: 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
handled = 1;
ty->state.crlf = mode;
break;
case 25:
handled = 1;
ty->state.hidecursor = !mode;
break;
case 30: // ignore
handled = 1;
// DBG("XXX: set scrollbar mapping %i", mode);
break;
case 33: // ignore
handled = 1;
// INF("XXX: Stop cursor blink %i", mode);
break;
case 34: // ignore
handled = 1;
// INF("XXX: Underline cursor mode %i", mode);
break;
case 35: // ignore
handled = 1;
// DBG("XXX: set shift keys %i", mode);
break;
case 38: // ignore
handled = 1;
// INF("XXX: switch to tek window %i", mode);
break;
case 59: // ignore
handled = 1;
// INF("XXX: kanji terminal mode %i", mode);
break;
case 66:
handled = 1;
ERR("XXX: app keypad mode %i", mode);
break;
case 67:
handled = 1;
ty->state.send_bs = mode;
INF("XXX: backspace send bs not del = %i", mode);
break;
case 1000:
handled = 1;
INF("XXX: set x11 mouse reporting to %i", mode);
if (mode) ty->state.mouse_rep = MOUSE_NORMAL;
else ty->state.mouse_rep = MOUSE_OFF;
INF("XXX: set mouse (press+release only) to %i", mode);
break;
case 1001:
handled = 1;
ERR("XXX: x11 mouse highlighting %i", mode);
break;
case 1002:
handled = 1;
ERR("XXX: set mouse (press+relese+motion while pressed) %i", mode);
break;
case 1003:
handled = 1;
ERR("XXX: set mouse (press+relese+all motion) %i", mode);
break;
case 1004: // i dont know what focus repporting is?
handled = 1;
ERR("XXX: enable focus reporting %i", mode);
break;
case 1005:
handled = 1;
if (mode) ty->state.mouse_rep = MOUSE_UTF8;
else ty->state.mouse_rep = MOUSE_OFF;
INF("XXX: set mouse (xterm utf8 style) %i", mode);
break;
case 1006:
handled = 1;
if (mode) ty->state.mouse_rep = MOUSE_SGR;
else ty->state.mouse_rep = MOUSE_OFF;
INF("XXX: set mouse (xterm sgr style) %i", mode);
break;
case 1010: // ignore
handled = 1;
// DBG("XXX: set home on tty output %i", mode);
break;
case 1012: // ignore
handled = 1;
// DBG("XXX: set home on tty input %i", mode);
break;
case 1015:
handled = 1;
if (mode) ty->state.mouse_rep = MOUSE_URXVT;
else ty->state.mouse_rep = MOUSE_OFF;
INF("XXX: set mouse (rxvt-unicdode 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
*/
handled = 1;
// DBG("Ignored screen mode %i", arg);
break;
case 1047:
case 1049:
case 47:
case 1047:
handled = 1;
DBG("DDD: switch buf");
if (ty->altbuf)
@ -960,14 +1077,18 @@ _handle_esc_csi(Termpty *ty, const int *c, int *ce)
else
_cursor_copy(&(ty->save), &(ty->state));
break;
case 1034:
/* libreadline6 emits it but it shouldn't.
See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577012
*/
handled = 1;
DBG("Ignored screen mode %i", arg);
break;
case 2004: // ignore
handled = 1;
// INF("XXX: enable bracketed paste mode %i", mode);
break;
case 7727: // ignore
handled = 1;
// INF("XXX: enable application escape mode %i", mode);
break;
case 7786: // ignore
handled = 1;
// INF("XXX: enable mouse wheel -> cursor key xlation %i", mode);
break;
default:
ERR("unhandled screen mode arg %i", arg);
break;
@ -1027,9 +1148,9 @@ _handle_esc_csi(Termpty *ty, const int *c, int *ce)
}
else
{
if (arg >= arg2)
if (arg > arg2)
{
ERR("scroll region beginning >= end [%i %i]", arg, arg2);
ERR("scroll region beginning > end [%i %i]", arg, arg2);
ty->state.scroll_y1 = 0;
ty->state.scroll_y2 = 0;
}
@ -1250,6 +1371,18 @@ _handle_seq(Termpty *ty, const int *c, int *ce)
{
int *cc, len = 0;
/*
printf(" B: ");
int j;
for (j = 0; c + j < ce && j < 100; j++)
{
if ((c[j] < ' ') || (c[j] >= 0x7f))
printf("\033[35m%02x\033[0m", c[j]);
else
printf("%c", c[j]);
}
printf("\n");
*/
if (c[0] < 0x20)
{
switch (c[0])
@ -1376,6 +1509,16 @@ _handle_seq(Termpty *ty, const int *c, int *ce)
ty->state.had_cr = 0;
return 1;
}
else if (c[0] == 0x9b) // ANSI ESC!!!
{
int v;
printf("ANSI CSI!!!!!\n");
ty->state.had_cr = 0;
v = _handle_esc_csi(ty, c + 1, ce);
if (v == -2) return 0;
return v + 1;
}
cc = (int *)c;
DBG("txt: [");
@ -1507,11 +1650,24 @@ _cb_fd_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
int glyph[4097];
int len, i, j, reads;
// read up to 64 * 4096 bytes OR until time expires;
// read up to 64 * 4096 bytes
for (reads = 0; reads < 64; reads++)
{
len = read(ty->fd, buf, sizeof(buf) - 1);
if (len <= 0) break;
/*
printf(" I: ");
int jj;
for (jj = 0; jj < len && jj < 100; jj++)
{
if ((buf[jj] < ' ') || (buf[jj] >= 0x7f))
printf("\033[33m%02x\033[0m", buf[jj]);
else
printf("%c", buf[jj]);
}
printf("\n");
*/
buf[len] = 0;
// convert UTF8 to glyph integers
j = 0;
@ -1527,7 +1683,6 @@ _cb_fd_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
}
else
{
ERR("ZERO GLYPH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
g = 0;
i++;
}
@ -1582,6 +1737,7 @@ termpty_new(const char *cmd, int w, int h, int backscroll)
if (ty->slavefd < 0) goto err;
fcntl(ty->fd, F_SETFL, O_NDELAY);
printf("@@@@@@@@@@@@ ty->fd = %i\n", ty->fd);
ty->hand_exe_exit = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_cb_exe_exit, ty);
ty->pid = fork();

View File

@ -18,6 +18,13 @@ typedef struct _Termsave Termsave;
#define COL_INVERSE 10
#define COL_INVERSEBG 11
#define MOUSE_OFF 0
#define MOUSE_X10 1
#define MOUSE_NORMAL 2
#define MOUSE_UTF8 3
#define MOUSE_SGR 4
#define MOUSE_URXVT 5
struct _Termatt
{
unsigned char fg, bg;
@ -58,6 +65,11 @@ struct _Termstate
unsigned int hidecursor : 1;
unsigned int crlf : 1;
unsigned int had_cr : 1;
unsigned int send_bs : 1;
unsigned int kbd_lock : 1;
unsigned int reverse : 1;
unsigned int no_autorepeat : 1;
unsigned int mouse_rep : 3;
};
struct _Termpty