From fd2a0255b1d8c0f112b3e2a5e01ff2e510d05def Mon Sep 17 00:00:00 2001 From: Russell McClellan Date: Sun, 21 Aug 2022 18:30:08 -0400 Subject: Support `sb_clear` callback if present --- CMakeLists.txt | 7 +++++-- vterm-module.c | 55 ++++++++++++++++++++++++++++++++++++++++--------------- vterm-module.h | 1 + 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d909076..24c09ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,10 @@ if (USE_SYSTEM_LIBVTERM) # add_compile_definitions(VTermStringFragmentNotExists) add_definitions(-DVTermSelectionMaskNotExists) endif() - + execute_process(COMMAND grep -c "sb_clear" "${LIBVTERM_INCLUDE_DIR}/vterm.h" OUTPUT_VARIABLE VTermSBClearExists) + if (${VTermSBClearExists} EQUAL "0") + add_definitions(-VTermSBClearNotExists) + endif() else() message(STATUS "System libvterm not found: libvterm will be downloaded and compiled as part of the build process") endif() @@ -70,7 +73,7 @@ else() ExternalProject_add(libvterm GIT_REPOSITORY https://github.com/Sbozzolo/libvterm-mirror.git - GIT_TAG 15133bba2c0bce32baabbf91610a2450495fea02 + GIT_TAG 64f1775952dbe001e989f2ab679563b54f2fca55 CONFIGURE_COMMAND "" BUILD_COMMAND ${LIBVTERM_BUILD_COMMAND} "CFLAGS='-fPIC'" BUILD_IN_SOURCE ON diff --git a/vterm-module.c b/vterm-module.c index a41188a..93942e1 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -154,6 +154,32 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data) { return 1; } +static int term_sb_clear(void *data) { + Term *term = (Term *)data; + + if (term->sb_clear_pending) { + // Another scrollback clear is already pending, so skip this one. + return 0; + } + + for (int i = 0; i < term->sb_current; i++) { + if (term->sb_buffer[i]->info != NULL) { + free_lineinfo(term->sb_buffer[i]->info); + term->sb_buffer[i]->info = NULL; + } + free(term->sb_buffer[i]); + } + free(term->sb_buffer); + term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size); + term->sb_clear_pending = true; + term->sb_current = 0; + term->sb_pending = 0; + term->sb_pending_by_height_decr = 0; + invalidate_terminal(term, -1, -1); + + return 0; +} + static int row_to_linenr(Term *term, int row) { return row != INT_MAX ? row + (int)term->sb_current + 1 : INT_MAX; } @@ -436,6 +462,14 @@ static int term_resize(int rows, int cols, void *user_data) { static void refresh_scrollback(Term *term, emacs_env *env) { int max_line_count = (int)term->sb_current + term->height; int del_cnt = 0; + if (term->sb_clear_pending) { + del_cnt = term->linenum - term->height; + if (del_cnt > 0) { + delete_lines(env, 1, del_cnt, true); + term->linenum -= del_cnt; + } + term->sb_clear_pending = false; + } if (term->sb_pending > 0) { // This means that either the window height has decreased or the screen // became full and libvterm had to push all rows up. Convert the first @@ -628,6 +662,9 @@ static VTermScreenCallbacks vterm_screen_callbacks = { .resize = term_resize, .sb_pushline = term_sb_push, .sb_popline = term_sb_pop, +#if !defined(VTermSBClearNotExists) + .sb_clear = term_sb_clear, +#endif }; static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b) { @@ -846,24 +883,11 @@ static void term_flush_output(Term *term, emacs_env *env) { } static void term_clear_scrollback(Term *term, emacs_env *env) { + term_sb_clear(term); vterm_screen_flush_damage(term->vts); term_redraw(term, env); - if (term->sb_pending > 0) { // Pending rows must be processed first. - return; - } - for (int i = 0; i < term->sb_current; i++) { - if (term->sb_buffer[i]->info != NULL) { - free_lineinfo(term->sb_buffer[i]->info); - term->sb_buffer[i]->info = NULL; - } - free(term->sb_buffer[i]); - } - free(term->sb_buffer); - term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size); - delete_lines(env, 1, term->sb_current, true); - term->linenum -= term->sb_current; - term->sb_current = 0; } + static void term_process_key(Term *term, emacs_env *env, unsigned char *key, size_t len, VTermModifier modifier) { if (is_key(key, len, "")) { @@ -1221,6 +1245,7 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[], term->sb_size = MIN(SB_MAX, sb_size); term->sb_current = 0; term->sb_pending = 0; + term->sb_clear_pending = false; term->sb_pending_by_height_decr = 0; term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size); term->invalid_start = 0; diff --git a/vterm-module.h b/vterm-module.h index e8bb01b..1699cbc 100644 --- a/vterm-module.h +++ b/vterm-module.h @@ -79,6 +79,7 @@ typedef struct Term { // window height has increased) and must be deleted from the terminal buffer int sb_pending; int sb_pending_by_height_decr; + bool sb_clear_pending; long linenum; long linenum_added; -- cgit v1.0