vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: c59760708c5c34d620221773c128f39e70d4ac85
Parent: 7b2a7bda201ec0b716f53108d9c2abff434c95bc
Author: Randy Palamar
Date:   Mon, 17 Feb 2025 15:16:02 -0700

terminal: fix currently supported delete character modes

Diffstat:
Mbuild.sh | 14++++++++------
Mterminal.c | 39++++++++++++++++++++++++++++++++++++---
2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/build.sh b/build.sh @@ -54,10 +54,12 @@ fuzz) ;; fuzz_llvm) clang ${testcflags} -O0 -fsanitize=fuzzer,address,undefined -o tests/test-fuzz tests/test-fuzz.c - mkdir -p tests/llvm_fuzz_corpus input=tests/llvm_fuzz_corpus if [ ! -d ${input} ]; then - ./tests/test-fuzz -merge=1 tests/llvm_fuzz_corpus tests/fuzz_in + mkdir -p tests/llvm_fuzz_corpus + # NOTE(rnp): libFuzzer can't handle arbitrary utf-8 inputs and seems + # to leak memory at startup (gg llvm devs) + ./tests/test-fuzz -detect_leaks=0 -merge=1 tests/llvm_fuzz_corpus tests/fuzz_in else ./tests/test-fuzz tests/llvm_fuzz_corpus fi @@ -70,10 +72,10 @@ fuzz_results) echo ${file} ./tests/test-fuzz-results "${file}" done - for file in tests/llvm_fuzz_corpus/*; do - echo ${file} - ./tests/test-fuzz-results "${file}" - done + #for file in tests/llvm_fuzz_corpus/*; do + # echo ${file} + # ./tests/test-fuzz-results "${file}" + #done exit 0 ;; *) diff --git a/terminal.c b/terminal.c @@ -562,8 +562,41 @@ erase_lines(Term *t, i32 count) fb_scroll_up(t, t->cursor.pos.y, count); } -/* DCH: Delete Characters (NOTE: DCH is technically different but we are ignoring that) */ -/* ECH: Erase Characters */ +/* DCH: Delete <count> Characters */ +static void +delete_characters(Term *t, i32 requested_count) +{ + iv2 cpos = t->cursor.pos; + /* TODO(rnp): if the cursor is outside the left/right margins do nothing */ + + TermView *tv = t->views + t->view_idx; + i32 count = MAX(0, MIN(requested_count, t->size.w - cpos.x)); + i32 total = t->size.w - count; + + Cell *dst = tv->fb.rows[cpos.y] + cpos.x; + if (dst->bg & ATTR_WDUMMY) dst--; + Cell *src = dst + count; + + i32 dst_off = 0, src_off = 0; + for (i32 i = 0; i < total; i++) { + b32 dst_wide = (dst[i].bg & ATTR_WIDE) != 0; + b32 src_wide = (src[i].bg & ATTR_WIDE) != 0; + + if (dst_wide && !src_wide) + dst[i + 1].bg &= ~ATTR_WDUMMY; + + dst[i + dst_off] = src[i + src_off]; + + if (src_wide && !dst_wide) { + dst[i + 1] = src[i + 1]; + i++; + } + } + + fb_clear_region(t, cpos.y, cpos.y, t->size.w - count, t->size.w); +} + +/* ECH: Erase <count> Characters */ static void erase_characters(Term *t, i32 count) { @@ -962,7 +995,7 @@ handle_csi(Term *t, CSI *csi) case 'K': erase_in_line(t, csi); break; case 'L': insert_blank_lines(t, ORONE(csi->argv[0])); break; case 'M': erase_lines(t, ORONE(csi->argv[0])); break; - case 'P': erase_characters(t, ORONE(csi->argv[0])); break; + case 'P': delete_characters(t, ORONE(csi->argv[0])); break; case 'X': erase_characters(t, ORONE(csi->argv[0])); break; case 'S': fb_scroll_up(t, t->top, ORONE(csi->argv[0])); break; case 'T': fb_scroll_down(t, t->top, ORONE(csi->argv[0])); break;