termpty: handle IL with left/right margins + tests

terminology-1.4
Boris Faure 4 years ago
parent 571d2d03f1
commit 822f959163
  1. 133
      src/bin/termptyesc.c
  2. 40
      src/bin/termptyops.c
  3. 1
      tests/tests.results

@ -89,6 +89,21 @@ _safechar(unsigned int c)
return _str;
}
static Eina_Bool
_cursor_is_within_margins(const Termpty *ty)
{
return !(
((ty->termstate.top_margin > 0)
&& (ty->cursor_state.cy < ty->termstate.top_margin))
|| ((ty->termstate.bottom_margin > 0)
&& (ty->cursor_state.cy >= ty->termstate.bottom_margin))
|| ((ty->termstate.left_margin > 0)
&& (ty->cursor_state.cx < ty->termstate.left_margin))
|| ((ty->termstate.right_margin > 0)
&& (ty->cursor_state.cx >= ty->termstate.right_margin))
);
}
enum csi_arg_error {
CSI_ARG_NO_VALUE = 1,
CSI_ARG_ERROR = 2
@ -2564,6 +2579,82 @@ _handle_esc_csi_decsel(Termpty *ty, Eina_Unicode **ptr)
_handle_esc_csi_el(ty, ptr);
}
static void
_handle_esc_csi_il(Termpty *ty, Eina_Unicode **ptr)
{
Eina_Unicode *b = *ptr;
int arg = _csi_arg_get(ty, &b);
int sy1, sy2, i;
if (arg == -CSI_ARG_ERROR)
return;
TERMPTY_RESTRICT_FIELD(arg, 1, ty->h);
DBG("IL - Insert Lines: %d", arg);
if (!_cursor_is_within_margins(ty))
return;
sy1 = ty->termstate.top_margin;
sy2 = ty->termstate.bottom_margin;
if (ty->termstate.bottom_margin == 0)
{
ty->termstate.top_margin = ty->cursor_state.cy;
ty->termstate.bottom_margin = ty->h;
}
else
{
ty->termstate.top_margin = ty->cursor_state.cy;
if (ty->termstate.bottom_margin <= ty->termstate.top_margin)
ty->termstate.bottom_margin = ty->termstate.top_margin + 1;
}
ERR("arg:%d", arg);
for (i = 0; i < arg; i++)
{
termpty_text_scroll_rev(ty, EINA_TRUE);
}
ty->termstate.top_margin = sy1;
ty->termstate.bottom_margin = sy2;
ty->cursor_state.cx = ty->termstate.left_margin;
}
static void
_handle_esc_csi_dl(Termpty *ty, Eina_Unicode **ptr)
{
Eina_Unicode *b = *ptr;
int arg = _csi_arg_get(ty, &b);
int sy1, sy2, i;
if (arg == -CSI_ARG_ERROR)
return;
TERMPTY_RESTRICT_FIELD(arg, 1, ty->h);
DBG("DL - Delete Lines: %d", arg);
if (!_cursor_is_within_margins(ty))
return;
sy1 = ty->termstate.top_margin;
sy2 = ty->termstate.bottom_margin;
if (ty->termstate.bottom_margin == 0)
{
ty->termstate.top_margin = ty->cursor_state.cy;
ty->termstate.bottom_margin = ty->h;
}
else
{
ty->termstate.top_margin = ty->cursor_state.cy;
if (ty->termstate.bottom_margin <= ty->termstate.top_margin)
ty->termstate.bottom_margin = ty->termstate.top_margin + 1;
}
for (i = 0; i < arg; i++)
{
termpty_text_scroll(ty, EINA_TRUE);
}
ty->termstate.top_margin = sy1;
ty->termstate.bottom_margin = sy2;
}
static int
_handle_esc_csi(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
{
@ -2638,43 +2729,11 @@ _handle_esc_csi(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
else
_handle_esc_csi_el(ty, &b);
break;
case 'L': // insert N lines - cy
EINA_FALLTHROUGH;
case 'M': // delete N lines - cy
arg = _csi_arg_get(ty, &b);
if (arg == -CSI_ARG_ERROR)
goto error;
TERMPTY_RESTRICT_FIELD(arg, 1, ty->h);
DBG("%s %d lines", (*cc == 'M') ? "delete" : "insert", arg);
if ((ty->cursor_state.cy >= ty->termstate.top_margin) &&
((ty->termstate.bottom_margin == 0) ||
(ty->cursor_state.cy < ty->termstate.bottom_margin)))
{
int sy1, sy2;
sy1 = ty->termstate.top_margin;
sy2 = ty->termstate.bottom_margin;
if (ty->termstate.bottom_margin == 0)
{
ty->termstate.top_margin = ty->cursor_state.cy;
ty->termstate.bottom_margin = ty->h;
}
else
{
ty->termstate.top_margin = ty->cursor_state.cy;
if (ty->termstate.bottom_margin <= ty->termstate.top_margin)
ty->termstate.bottom_margin = ty->termstate.top_margin + 1;
}
for (i = 0; i < arg; i++)
{
if (*cc == 'M')
termpty_text_scroll(ty, EINA_TRUE);
else
termpty_text_scroll_rev(ty, EINA_TRUE);
}
ty->termstate.top_margin = sy1;
ty->termstate.bottom_margin = sy2;
}
case 'L':
_handle_esc_csi_il(ty, &b);
break;
case 'M':
_handle_esc_csi_dl(ty, &b);
break;
case 'P': // erase and scrollback N chars
_handle_esc_csi_dch(ty, &b);

@ -99,28 +99,36 @@ termpty_text_scroll_rev(Termpty *ty, Eina_Bool clear)
DBG("... scroll rev!!!!! [%i->%i]", start_y, end_y);
termio_scroll(ty->obj, 1, start_y, end_y);
if (start_y == 0 && end_y == ty->h - 1)
if ((start_y == 0 && end_y == (ty->h - 1)) &&
(ty->termstate.left_margin == 0) &&
(ty->termstate.right_margin == 0))
{
// screen is a circular buffer now
ty->circular_offset--;
if (ty->circular_offset < 0)
ty->circular_offset = ty->h - 1;
// screen is a circular buffer now
ty->circular_offset--;
if (ty->circular_offset < 0)
ty->circular_offset = ty->h - 1;
cells = &(ty->screen[ty->circular_offset * ty->w]);
if (clear)
cells = &(ty->screen[ty->circular_offset * ty->w]);
if (clear)
termpty_cells_clear(ty, cells, ty->w);
}
else
{
cells = &(TERMPTY_SCREEN(ty, 0, end_y));
for (y = end_y; y > start_y; y--)
{
cells = &(TERMPTY_SCREEN(ty, 0, (y - 1)));
cells2 = &(TERMPTY_SCREEN(ty, 0, y));
TERMPTY_CELL_COPY(ty, cells, cells2, ty->w);
}
if (clear)
termpty_cells_clear(ty, cells, ty->w);
int x = ty->termstate.left_margin;
int w = ty->w - x;
if (ty->termstate.right_margin)
w = ty->termstate.right_margin - x;
cells = &(TERMPTY_SCREEN(ty, x, end_y));
for (y = end_y; y > start_y; y--)
{
cells = &(TERMPTY_SCREEN(ty, x, (y - 1)));
cells2 = &(TERMPTY_SCREEN(ty, x, y));
TERMPTY_CELL_COPY(ty, cells, cells2, w);
}
if (clear)
termpty_cells_clear(ty, cells, w);
}
}

@ -58,3 +58,4 @@ ed-2.sh 82e7919a46fdea3a003143b41562b148
ed-3.sh 005871b7e4d63017c08a73ab34f99b14
ed-4.sh 574f37ac24ead26ef86c03d7dfae3152
el.sh abca9d5e5990bed6bd72a7ab9f72b849
il.sh 1788258650a94f2568d05f749b6cf578

Loading…
Cancel
Save