diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index b70fe898..477826c3 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -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); diff --git a/src/bin/termptyops.c b/src/bin/termptyops.c index f0dfd046..6b7bc9e5 100644 --- a/src/bin/termptyops.c +++ b/src/bin/termptyops.c @@ -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); } } diff --git a/tests/tests.results b/tests/tests.results index e064dae3..781f5112 100644 --- a/tests/tests.results +++ b/tests/tests.results @@ -58,3 +58,4 @@ ed-2.sh 82e7919a46fdea3a003143b41562b148 ed-3.sh 005871b7e4d63017c08a73ab34f99b14 ed-4.sh 574f37ac24ead26ef86c03d7dfae3152 el.sh abca9d5e5990bed6bd72a7ab9f72b849 +il.sh 1788258650a94f2568d05f749b6cf578