diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index f4f50048..bfde79c4 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -1550,6 +1550,117 @@ _handle_esc_csi_decfra(Termpty *ty, Eina_Unicode **b) } } +static void +_handle_esc_csi_deccara(Termpty *ty, Eina_Unicode **ptr, + const Eina_Unicode * const end) +{ + Eina_Unicode *b = *ptr; + int top; + int left; + int bottom; + int right; + int i, len; + Eina_Bool set_bold = EINA_FALSE, reset_bold = EINA_FALSE; + Eina_Bool set_underline = EINA_FALSE, reset_underline = EINA_FALSE; + Eina_Bool set_blink = EINA_FALSE, reset_blink = EINA_FALSE; + Eina_Bool set_reverse = EINA_FALSE, reset_reverse = EINA_FALSE; + + top = _csi_arg_get(ty, &b); + left = _csi_arg_get(ty, &b); + bottom = _csi_arg_get(ty, &b); + right = _csi_arg_get(ty, &b); + + DBG("DECCARA (%d;%d;%d;%d) Change Attributes in Rectangular Area", + top, left, bottom, right); + if ((top == -CSI_ARG_ERROR) || + (left == -CSI_ARG_ERROR) || + (bottom == -CSI_ARG_ERROR) || + (right == -CSI_ARG_ERROR)) + return; + + while (b && b < end) + { + int arg = _csi_arg_get(ty, &b); + switch (arg) + { + case -CSI_ARG_ERROR: + return; + case -CSI_ARG_NO_VALUE: + EINA_FALLTHROUGH; + case 0: + set_bold = set_underline = set_blink = set_reverse = EINA_FALSE; + reset_bold = reset_underline = reset_blink = reset_reverse = EINA_TRUE; + break; + case 1: + set_bold = EINA_TRUE; + reset_bold = EINA_FALSE; + break; + case 4: + set_underline = EINA_TRUE; + reset_underline = EINA_FALSE; + break; + case 5: + set_blink = EINA_TRUE; + reset_blink = EINA_FALSE; + break; + case 7: + set_reverse = EINA_TRUE; + reset_reverse = EINA_FALSE; + break; + case 22: + set_bold = EINA_FALSE; + reset_bold = EINA_TRUE; + break; + case 24: + set_underline = EINA_FALSE; + reset_underline = EINA_TRUE; + break; + case 25: + set_blink = EINA_FALSE; + reset_blink = EINA_TRUE; + break; + case 27: + set_reverse = EINA_FALSE; + reset_reverse = EINA_TRUE; + break; + default: + WRN("Invalid change attribute [%i]", arg); + ty->decoding_error = EINA_TRUE; + return; + } + } + + if (_clean_up_rect_coordinates(ty, &top, &left, &bottom, &right) < 0) + return; + + len = right - left; + + for (; top <= bottom; top++) + { + Termcell *cells = &(TERMPTY_SCREEN(ty, left, top)); + for (i = 0; i < len; i++) + { + Termatt * att = &cells[i].att; + if (set_bold) + att->bold = 1; + if (set_underline) + att->underline = 1; + if (set_blink) + att->blink = 1; + if (set_reverse) + att->inverse = 1; + if (reset_bold) + att->bold = 0; + if (reset_underline) + att->underline = 0; + if (reset_blink) + att->blink = 0; + if (reset_reverse) + att->inverse = 0; + } + } +} + static void _handle_esc_csi_decera(Termpty *ty, Eina_Unicode **b) { @@ -2111,7 +2222,10 @@ HVP: } break; case 'r': - _handle_esc_csi_decstbm(ty, &b); + if (*(cc-1) == '$') + _handle_esc_csi_deccara(ty, &b, be-1); + else + _handle_esc_csi_decstbm(ty, &b); break; case 's': if (ty->termstate.lr_margins) diff --git a/tests/deccara-rectangular-no-restrict-cursor.sh b/tests/deccara-rectangular-no-restrict-cursor.sh new file mode 100755 index 00000000..7e7f99fa --- /dev/null +++ b/tests/deccara-rectangular-no-restrict-cursor.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# move to 0; 0 +printf '\033[H' +# fill space +PL=0 +for _ in $(seq 0 23); do + PL=$((PL+1)) + if [ $PL -ge 9 ] ; then + PL=0 + fi + for _ in $(seq 1 $PL); do + printf '#' + done + PR=$((10 - PL)) + for _ in $(seq 0 6); do + printf '\033[0;1m\-' + printf '\033[0;46;1;4m/' + printf '\033[0;46;1;4;5m|' + printf '\033[0;1;4;5;7m\\' + printf '\033[0m~' + printf '\033[0;1;5m_' + printf '\033[0;31;5;7m>' + printf '\033[0;31;4;7m^' + printf '\033[0;1;7m<' + done + printf '\033[0m' + for _ in $(seq 1 $PR); do + printf '#' + done +done + +# move to 0; 0 +printf '\033[H' + +# set top/bottom margins: +printf '\033[5;20r' + +# force rectangular modifications +printf '\033[2*x' + +# column reset +printf '\033[1;10;80;15;0\044r' + +# column reset +printf '\033[1;20;80;25;22;24;25;27\044r' + +# reset bold/blink +printf '\033[1;30;80;35;22;25\044r' + +# set bold/underline, remove blink/reverse +printf '\033[1;40;80;45;1;4;25;27\044r' + +# set blink/reverse, remove bold/underline +printf '\033[1;50;80;55;5;7;22;24\044r' + +# set all, remove all +printf '\033[1;60;80;65;1;4;5;7;0\044r' diff --git a/tests/deccara-rectangular-restrict-cursor.sh b/tests/deccara-rectangular-restrict-cursor.sh new file mode 100755 index 00000000..268962e8 --- /dev/null +++ b/tests/deccara-rectangular-restrict-cursor.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# move to 0; 0 +printf '\033[H' +# fill space +PL=0 +for _ in $(seq 0 23); do + PL=$((PL+1)) + if [ $PL -ge 9 ] ; then + PL=0 + fi + for _ in $(seq 1 $PL); do + printf '#' + done + PR=$((10 - PL)) + for _ in $(seq 0 6); do + printf '\033[0;1m\-' + printf '\033[0;46;1;4m/' + printf '\033[0;46;1;4;5m|' + printf '\033[0;1;4;5;7m\\' + printf '\033[0m~' + printf '\033[0;1;5m_' + printf '\033[0;31;5;7m>' + printf '\033[0;31;4;7m^' + printf '\033[0;1;7m<' + done + printf '\033[0m' + for _ in $(seq 1 $PR); do + printf '#' + done +done + +# move to 0; 0 +printf '\033[H' + +# set top/bottom margins: +printf '\033[5;20r' + +# restrict cursor +printf '\033[?6h' + +# force rectangular modifications +printf '\033[2*x' + +# column reset +printf '\033[1;10;80;15;0\044r' + +# column reset +printf '\033[1;20;80;25;22;24;25;27\044r' + +# reset bold/blink +printf '\033[1;30;80;35;22;25\044r' + +# set bold/underline, remove blink/reverse +printf '\033[1;40;80;45;1;4;25;27\044r' + +# set blink/reverse, remove bold/underline +printf '\033[1;50;80;55;5;7;22;24\044r' + +# set all, remove all +printf '\033[1;60;80;65;1;4;5;7;0\044r' diff --git a/tests/tests.results b/tests/tests.results index f71bdb5b..5b38bdcf 100644 --- a/tests/tests.results +++ b/tests/tests.results @@ -41,3 +41,5 @@ decaln.sh 9c0cf4de336193bcdaed6ba6c0d6f590 decawm.sh 84321e76f07b40cf9462238ec0919dc0 decbi.sh 8153bff12a0d529cb8ba0dbff036a1ee decfi.sh e93690447902b923d3d9d2ae72a31de4 +deccara-rectangular-no-restrict-cursor.sh 5f85e9992055397f951af7b5713fabde +deccara-rectangular-restrict-cursor.sh c1d571a6c60a4fb06fdd81fee7c85e1c