From 59c547179d5009a1e6d0c0e7ac4c3be1acb78e3f Mon Sep 17 00:00:00 2001 From: Boris Faure Date: Mon, 31 Dec 2018 19:12:57 +0100 Subject: [PATCH] termptyesc: support DECCRA + tests --- src/bin/termptyesc.c | 131 +++++++++++++++++++++++++++++++++++++++++++ tests/deccra.sh | 78 ++++++++++++++++++++++++++ tests/tests.results | 1 + 3 files changed, 210 insertions(+) create mode 100755 tests/deccra.sh diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index 5b8444ea..e52fe422 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -1967,6 +1967,131 @@ _handle_esc_csi_decera(Termpty *ty, Eina_Unicode **b) } } +static void +_handle_esc_csi_deccra(Termpty *ty, Eina_Unicode **b) +{ + int top = _csi_arg_get(ty, b); + int left = _csi_arg_get(ty, b); + int bottom = _csi_arg_get(ty, b); + int right = _csi_arg_get(ty, b); + int p1 = _csi_arg_get(ty, b); + int to_top = _csi_arg_get(ty, b); + int to_left = _csi_arg_get(ty, b); + int p2 = _csi_arg_get(ty, b); + int to_bottom = ty->h - 1; + int to_right = ty->w; + int len; + + DBG("DECFRA (%d;%d;%d;%d -> %d;%d) Copy Rectangular Area", + top, left, bottom, right, to_top, to_left); + if ((top == -CSI_ARG_ERROR) || + (left == -CSI_ARG_ERROR) || + (bottom == -CSI_ARG_ERROR) || + (right == -CSI_ARG_ERROR) || + (p1 == -CSI_ARG_ERROR) || + (to_top == -CSI_ARG_ERROR) || + (to_left == -CSI_ARG_ERROR) || + (p2 == -CSI_ARG_ERROR)) + return; + + if (_clean_up_rect_coordinates(ty, &top, &left, &bottom, &right) < 0) + return; + + TERMPTY_RESTRICT_FIELD(to_top, 1, ty->h); + if (ty->termstate.restrict_cursor) + { + to_top += ty->termstate.top_margin; + if (ty->termstate.bottom_margin) + { + if (to_top >= ty->termstate.bottom_margin) + to_top = ty->termstate.bottom_margin; + to_bottom = ty->termstate.bottom_margin - 1; + } + } + to_top--; + if (to_bottom - to_top > bottom - top) + to_bottom = to_top + bottom - top; + TERMPTY_RESTRICT_FIELD(to_left, 1, ty->w); + if (ty->termstate.restrict_cursor) + { + to_left += ty->termstate.left_margin; + if (ty->termstate.right_margin) + { + if (to_left >= ty->termstate.right_margin) + to_left = ty->termstate.right_margin; + to_right = ty->termstate.right_margin; + } + } + to_left--; + + len = MIN(right - left, to_right - to_left); + + if (to_top < top) + { + /* Up -> Bottom */ + for (; top <= bottom && to_top <= to_bottom; top++, to_top++) + { + Termcell *cells_src = &(TERMPTY_SCREEN(ty, left, top)); + Termcell *cells_dst = &(TERMPTY_SCREEN(ty, to_left, to_top)); + int x; + if (to_left <= left) + { + /* -> */ + for (x = 0; x < len; x++) + { + if (&(cells_src[x]) != &(cells_dst[x])) + { + TERMPTY_CELL_COPY(ty, &(cells_src[x]), &(cells_dst[x]), 1); + } + } + } + else + { + /* <- */ + for (x = len - 1; x >= 0; x--) + { + if (&(cells_src[x]) != &(cells_dst[x])) + { + TERMPTY_CELL_COPY(ty, &(cells_src[x]), &(cells_dst[x]), 1); + } + } + } + } + } + else + { + /* Bottom -> Up */ + for (; bottom >= top && to_bottom >= to_top; bottom--, to_bottom--) + { + Termcell *cells_src = &(TERMPTY_SCREEN(ty, left, bottom)); + Termcell *cells_dst = &(TERMPTY_SCREEN(ty, to_left, to_bottom)); + int x; + if (to_left <= left) + { + /* -> */ + for (x = 0; x < len; x++) + { + if (&(cells_src[x]) != &(cells_dst[x])) + { + TERMPTY_CELL_COPY(ty, &(cells_src[x]), &(cells_dst[x]), 1); + } + } + } + else + { + /* <- */ + for (x = len - 1; x >= 0; x--) + { + if (&(cells_src[x]) != &(cells_dst[x])) + { + TERMPTY_CELL_COPY(ty, &(cells_src[x]), &(cells_dst[x]), 1); + } + } + } + } + } +} + static void _handle_esc_csi_cursor_pos_set(Termpty *ty, Eina_Unicode **b, const Eina_Unicode *cc) @@ -2704,6 +2829,12 @@ HVP: case 'u': // restore cursor pos termpty_cursor_copy(ty, EINA_FALSE); break; + case 'v': + if (*(cc-1) == '$') + _handle_esc_csi_deccra(ty, &b); + else + ty->decoding_error = EINA_TRUE; + break; case 'x': if (*(cc-1) == '$') _handle_esc_csi_decfra(ty, &b); diff --git a/tests/deccra.sh b/tests/deccra.sh new file mode 100755 index 00000000..c8e9079f --- /dev/null +++ b/tests/deccra.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +# move to 0; 0 +printf '\033[H' +# fill in left space +for _ in $(seq 0 23); do + for _ in $(seq 0 3); do + printf '\033[0;1m\' + printf '\033[0;1m-' + printf '\033[0;46;1;4m/' + printf '\033[0;46;1;4m|' + printf '\033[0;1;4;7m\\' + printf '\033[0m~' + printf '\033[0;1m_' + printf '\033[0;31;7m>' + printf '\033[0;31;4;7m^' + printf '\033[0;1;7m<' + done + for _ in $(seq 0 3); do + printf '\033[0m ' + done +done + +# move to 0; 0 +printf '\033[H' + +#set color +printf '\033[43;32;3m' + +# set top/bottom margins: +printf '\033[3;20r' +# allow left/right margins +printf '\033[?69h' +# set left/right margins: +printf '\033[5;75s' + +# copy one char +printf '\033[3;3;3;3;;2;48;\044v' + +# Copy rectangle +printf '\033[5;5;9;9;;8;45;\044v' + +# invalid rectangles +printf '\033[5;5;4;9;;8;45;\044v' +printf '\033[5;5;9;4;;8;45;\044v' + + +# Copy rectangle with invalid page values +printf '\033[5;5;9;9;1337;14;55;1337\044v' + +# Copy to part clipped +printf '\033[5;5;9;9;;22;78;\044v' + +# Copy upon itself (full overlap) +printf '\033[5;5;9;9;;5;5;\044v' + +# Copy upon itself (some overlap on the right) +printf '\033[5;5;9;9;;7;7;\044v' + +# Copy upon itself (some overlap on the left) +printf '\033[15;5;19;9;;17;3;\044v' + + +# WITH MARGINS ENFORCED + +# set top/bottom margins: +printf '\033[3;10r' +# allow left/right margins +printf '\033[?69h' +# set left/right margins: +printf '\033[5;60s' + +# restrict cursor +printf '\033[?6h' + +printf '\033[5;21;9;25;;1;50;\044v' +# Copy rectangle to on margins +printf '\033[5;21;9;25;;6;54;\044v' diff --git a/tests/tests.results b/tests/tests.results index 324b8ea2..0a5e0f78 100644 --- a/tests/tests.results +++ b/tests/tests.results @@ -51,3 +51,4 @@ decrara-no-rectangular-no-restrict-cursor.sh c375dd5d6538aff4c920b022f32f4ab0 decrara-no-rectangular-restrict-cursor.sh 815a848844cf7ea33d60e71948346a33 decic-decdc.sh 6d67999a7c5c771281ff2229cdbdda76 ich.sh fe1bfee25582f37a27665af1f66513df +deccra.sh 6a0846004c4effb9d5eb45b8044d5f7e