# HG changeset patch # User Christian Brabandt # Date 1691782203 -7200 # Node ID b13f723a7ec6e0f108a9416b78aaacaf0d65e244 # Parent 6beeb2e0105d9134bbe59a236d7cf0602e002282 patch 9.0.1684: Update libvterm to rev 839 Commit: https://github.com/vim/vim/commit/b00df7aa388994119346a21d77b0d0db2a0a5e9f Author: zeertzjq Date: Tue Aug 8 11:03:00 2023 +0800 patch 9.0.1684: Update libvterm to rev 839 Problem: libvterm slightly outdated Solution: Update libvterm from rev 818 to rev 839 Notable fix: libvterm now handles DECSM/DECRM with multiple arguents, so several ncurses programs (e.g. nnn) can enable mouse properly when run in Vim's terminal in XTerm. closes: #12746 Signed-off-by: Christian Brabandt Co-authored-by: zeertzjq diff --git a/src/libvterm/CODE-MAP b/src/libvterm/CODE-MAP new file mode 100644 --- /dev/null +++ b/src/libvterm/CODE-MAP @@ -0,0 +1,66 @@ +CODE-MAP + - high-level list and description of files in the repository + +CONTRIBUTING + - documentation explaining how developers can contribute fixes and features + +doc/ + - contains documentation + +doc/seqs.txt + - documents the sequences recognised by the library + +include/vterm.h + - main include file + +include/vterm_keycodes.h + - include file containing the keyboard input keycode enumerations + +LICENSE + - legalese + +Makefile + - main build file + +src/ + - contains the source code for the library + +src/encoding.c + - handles mapping ISO/IEC 2022 alternate character sets into Unicode + codepoints + +src/keyboard.c + - handles sending reported keyboard events to the output stream + +src/mouse.c + - handles sending reported mouse events to the output stream + +src/parser.c + - parses bytes from the input stream into parser-level events + +src/pen.c + - interprets SGR sequences and maintains current rendering attributes + +src/screen.c + - uses state-level events to maintain a buffer of current screen contents + +src/state.c + - follows parser-level events to keep track of the overall terminal state + +src/unicode.c + - utility functions for Unicode and UTF-8 handling + +src/vterm.c + - toplevel object state and miscellaneous functions + +src/vterm_internal.h + - include file for definitions private to the library's internals + +t/ + - contains unit tests + +t/harness.c + - standalone program to embed the library into for unit-test purposes + +t/run-test.pl + - invokes the test harness to run a single unit test script diff --git a/src/libvterm/Makefile b/src/libvterm/Makefile --- a/src/libvterm/Makefile +++ b/src/libvterm/Makefile @@ -36,14 +36,11 @@ INCFILES=$(TBLFILES:.tbl=.inc) HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES) -VERSION_MAJOR=0 -VERSION_MINOR=3 - VERSION_CURRENT=0 VERSION_REVISION=0 VERSION_AGE=0 -VERSION=$(VERSION_MAJOR).$(VERSION_MINOR) +VERSION=0.3.3 PREFIX=/usr/local BINDIR=$(PREFIX)/bin diff --git a/src/libvterm/include/vterm.h b/src/libvterm/include/vterm.h --- a/src/libvterm/include/vterm.h +++ b/src/libvterm/include/vterm.h @@ -23,6 +23,7 @@ typedef unsigned int uint32_t; #define VTERM_VERSION_MAJOR 0 #define VTERM_VERSION_MINOR 3 +#define VTERM_VERSION_PATCH 3 #define VTERM_CHECK_VERSION \ vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR) @@ -255,6 +256,7 @@ typedef enum { VTERM_PROP_REVERSE, // bool VTERM_PROP_CURSORSHAPE, // number VTERM_PROP_MOUSE, // number + VTERM_PROP_FOCUSREPORT, // bool VTERM_PROP_CURSORCOLOR, // VIM - string VTERM_N_PROPS @@ -422,6 +424,11 @@ typedef struct { void vterm_parser_set_callbacks(VTerm *vt, const VTermParserCallbacks *callbacks, void *user); void *vterm_parser_get_cbdata(VTerm *vt); +/* Normally NUL, CAN, SUB and DEL are ignored. Setting this true causes them + * to be emitted by the 'control' callback + */ +void vterm_parser_set_emit_nul(VTerm *vt, int emit); + // ----------- // State layer // ----------- @@ -645,6 +652,12 @@ int vterm_screen_is_eol(const VTermScree */ void vterm_screen_convert_color_to_rgb(const VTermScreen *screen, VTermColor *col); +/** + * Similar to vterm_state_set_default_colors(), but also resets colours in the + * screen buffer(s) + */ +void vterm_screen_set_default_colors(VTermScreen *screen, const VTermColor *default_fg, const VTermColor *default_bg); + // --------- // Utilities // --------- diff --git a/src/libvterm/src/parser.c b/src/libvterm/src/parser.c --- a/src/libvterm/src/parser.c +++ b/src/libvterm/src/parser.c @@ -148,11 +148,15 @@ size_t vterm_input_write(VTerm *vt, cons string_fragment(vt, string_start, bytes + pos - string_start, FALSE); string_start = bytes + pos + 1; } + if(vt->parser.emit_nul) + do_control(vt, c); continue; } if(c == 0x18 || c == 0x1a) { // CAN, SUB vt->parser.in_esc = FALSE; ENTER_NORMAL_STATE(); + if(vt->parser.emit_nul) + do_control(vt, c); continue; } else if(c == 0x1b) { // ESC @@ -402,3 +406,8 @@ void *vterm_parser_get_cbdata(VTerm *vt) { return vt->parser.cbdata; } + +void vterm_parser_set_emit_nul(VTerm *vt, int emit) +{ + vt->parser.emit_nul = emit; +} diff --git a/src/libvterm/src/pen.c b/src/libvterm/src/pen.c --- a/src/libvterm/src/pen.c +++ b/src/libvterm/src/pen.c @@ -259,15 +259,17 @@ void vterm_state_get_palette_color(const void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg) { - /* Copy the given colors */ - state->default_fg = *default_fg; - state->default_bg = *default_bg; + if(default_fg) { + state->default_fg = *default_fg; + state->default_fg.type = (state->default_fg.type & ~VTERM_COLOR_DEFAULT_MASK) + | VTERM_COLOR_DEFAULT_FG; + } - /* Make sure the correct type flags are set */ - state->default_fg.type = (state->default_fg.type & ~VTERM_COLOR_DEFAULT_MASK) - | VTERM_COLOR_DEFAULT_FG; - state->default_bg.type = (state->default_bg.type & ~VTERM_COLOR_DEFAULT_MASK) - | VTERM_COLOR_DEFAULT_BG; + if(default_bg) { + state->default_bg = *default_bg; + state->default_bg.type = (state->default_bg.type & ~VTERM_COLOR_DEFAULT_MASK) + | VTERM_COLOR_DEFAULT_BG; + } } void vterm_state_set_palette_color(VTermState *state, int index, const VTermColor *col) diff --git a/src/libvterm/src/screen.c b/src/libvterm/src/screen.c --- a/src/libvterm/src/screen.c +++ b/src/libvterm/src/screen.c @@ -292,7 +292,11 @@ static int erase_internal(VTermRect rect continue; cell->chars[0] = 0; - cell->pen = screen->pen; + cell->pen = (ScreenPen){ + /* Only copy .fg and .bg; leave things like rv in reset state */ + .fg = screen->pen.fg, + .bg = screen->pen.bg, + }; cell->pen.dwl = info->doublewidth; cell->pen.dhl = info->doubleheight; } @@ -603,8 +607,15 @@ static void resize_buffer(VTermScreen *s new_row_start, new_row_end, old_row_start, old_row_end, width); #endif - if(new_row_start < 0) + if(new_row_start < 0) { + if(old_row_start <= old_cursor.row && old_cursor.row < old_row_end) { + new_cursor.row = 0; + new_cursor.col = old_cursor.col; + if(new_cursor.col >= new_cols) + new_cursor.col = new_cols-1; + } break; + } for(new_row = new_row_start, old_row = old_row_start; new_row <= new_row_end; new_row++) { int count = width >= new_cols ? new_cols : width; @@ -674,8 +685,9 @@ static void resize_buffer(VTermScreen *s if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) { /* Push spare lines to scrollback buffer */ - for(int row = 0; row <= old_row; row++) - sb_pushline_from_row(screen, row); + if(screen->callbacks && screen->callbacks->sb_pushline) + for(int row = 0; row <= old_row; row++) + sb_pushline_from_row(screen, row); if(active) statefields->pos.row -= (old_row + 1); } @@ -1204,3 +1216,36 @@ void vterm_screen_convert_color_to_rgb(c { vterm_state_convert_color_to_rgb(screen->state, col); } + +static void reset_default_colours(VTermScreen *screen, ScreenCell *buffer) +{ + for(int row = 0; row <= screen->rows - 1; row++) + for(int col = 0; col <= screen->cols - 1; col++) { + ScreenCell *cell = &buffer[row * screen->cols + col]; + if(VTERM_COLOR_IS_DEFAULT_FG(&cell->pen.fg)) + cell->pen.fg = screen->pen.fg; + if(VTERM_COLOR_IS_DEFAULT_BG(&cell->pen.bg)) + cell->pen.bg = screen->pen.bg; + } +} + +void vterm_screen_set_default_colors(VTermScreen *screen, const VTermColor *default_fg, const VTermColor *default_bg) +{ + vterm_state_set_default_colors(screen->state, default_fg, default_bg); + + if(default_fg && VTERM_COLOR_IS_DEFAULT_FG(&screen->pen.fg)) { + screen->pen.fg = *default_fg; + screen->pen.fg.type = (screen->pen.fg.type & ~VTERM_COLOR_DEFAULT_MASK) + | VTERM_COLOR_DEFAULT_FG; + } + + if(default_bg && VTERM_COLOR_IS_DEFAULT_BG(&screen->pen.bg)) { + screen->pen.bg = *default_bg; + screen->pen.bg.type = (screen->pen.bg.type & ~VTERM_COLOR_DEFAULT_MASK) + | VTERM_COLOR_DEFAULT_BG; + } + + reset_default_colours(screen, screen->buffers[0]); + if(screen->buffers[1]) + reset_default_colours(screen, screen->buffers[1]); +} diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c --- a/src/libvterm/src/state.c +++ b/src/libvterm/src/state.c @@ -837,6 +837,7 @@ static void set_dec_mode(VTermState *sta break; case 1004: + settermprop_bool(state, VTERM_PROP_FOCUSREPORT, val); state->mode.report_focus = val; break; @@ -993,6 +994,7 @@ static int on_csi(const char *leader, co switch(intermed[0]) { case ' ': + case '!': case '"': case '$': case '\'': @@ -1370,8 +1372,10 @@ static int on_csi(const char *leader, co break; case LEADER('?', 0x68): // DEC private mode set - if(!CSI_ARG_IS_MISSING(args[0])) - set_dec_mode(state, CSI_ARG(args[0]), 1); + for(int i = 0; i < argcount; i++) { + if(!CSI_ARG_IS_MISSING(args[i])) + set_dec_mode(state, CSI_ARG(args[i]), 1); + } break; case 0x6a: // HPB - ECMA-48 8.3.58 @@ -1392,8 +1396,10 @@ static int on_csi(const char *leader, co break; case LEADER('?', 0x6c): // DEC private mode reset - if(!CSI_ARG_IS_MISSING(args[0])) - set_dec_mode(state, CSI_ARG(args[0]), 0); + for(int i = 0; i < argcount; i++) { + if(!CSI_ARG_IS_MISSING(args[i])) + set_dec_mode(state, CSI_ARG(args[i]), 0); + } break; case 0x6d: // SGR - ECMA-48 8.3.117 @@ -1486,7 +1492,7 @@ static int on_csi(const char *leader, co break; - case LEADER('!', 0x70): // DECSTR - DEC soft terminal reset + case INTERMED('!', 0x70): // DECSTR - DEC soft terminal reset vterm_state_reset(state, 0); break; @@ -1769,8 +1775,18 @@ static void osc_selection(VTermState *st frag.len--; } - if(!frag.len) + if(!frag.len) { + /* Clear selection if we're already finished but didn't do anything */ + if(frag.final && state->selection.callbacks->set) { + (*state->selection.callbacks->set)(state->tmp.selection.mask, (VTermStringFragment){ + .str = NULL, + .len = 0, + .initial = state->tmp.selection.state != SELECTION_SET, + .final = TRUE, + }, state->selection.user); + } return; + } if(state->tmp.selection.state == SELECTION_SELECTED) { if(frag.str[0] == '?') { @@ -1788,6 +1804,9 @@ static void osc_selection(VTermState *st return; } + if(state->tmp.selection.state == SELECTION_INVALID) + return; + if(state->selection.callbacks->set) { size_t bufcur = 0; char *buffer = state->selection.buffer; @@ -1823,11 +1842,21 @@ static void osc_selection(VTermState *st uint8_t b = unbase64one(frag.str[0]); if(b == 0xFF) { DEBUG_LOG1("base64decode bad input %02X\n", (uint8_t)frag.str[0]); + + state->tmp.selection.state = SELECTION_INVALID; + if(state->selection.callbacks->set) { + (*state->selection.callbacks->set)(state->tmp.selection.mask, (VTermStringFragment){ + .str = NULL, + .len = 0, + .initial = TRUE, + .final = TRUE, + }, state->selection.user); + } + break; } - else { - x = (x << 6) | b; - n++; - } + + x = (x << 6) | b; + n++; frag.str++, frag.len--; if(n == 4) { @@ -1847,7 +1876,7 @@ static void osc_selection(VTermState *st state->selection.buffer, // str bufcur, // len state->tmp.selection.state == SELECTION_SET_INITIAL, // initial - frag.final // final + frag.final && !frag.len // final }; (*state->selection.callbacks->set)(state->tmp.selection.mask, setfrag, state->selection.user); @@ -2004,7 +2033,7 @@ static void request_status_string(VTermS return; } - vterm_push_output_sprintf_str(state->vt, C1_DCS, TRUE, "0$r%s", tmp); + vterm_push_output_sprintf_str(state->vt, C1_DCS, TRUE, "0$r"); } static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user) @@ -2354,6 +2383,9 @@ int vterm_state_set_termprop(VTermState if(val->number == VTERM_PROP_MOUSE_MOVE) state->mouse_flags |= MOUSE_WANT_MOVE; return 1; + case VTERM_PROP_FOCUSREPORT: + state->mode.report_focus = val->boolean; + return 1; case VTERM_N_PROPS: return 0; diff --git a/src/libvterm/src/vterm.c b/src/libvterm/src/vterm.c --- a/src/libvterm/src/vterm.c +++ b/src/libvterm/src/vterm.c @@ -73,6 +73,8 @@ VTerm *vterm_build(const struct VTermBui vt->parser.callbacks = NULL; vt->parser.cbdata = NULL; + vt->parser.emit_nul = FALSE; + vt->outfunc = NULL; vt->outdata = NULL; @@ -314,6 +316,7 @@ VTermValueType vterm_get_prop_type(VTerm case VTERM_PROP_REVERSE: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORSHAPE: return VTERM_VALUETYPE_INT; case VTERM_PROP_MOUSE: return VTERM_VALUETYPE_INT; + case VTERM_PROP_FOCUSREPORT: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORCOLOR: return VTERM_VALUETYPE_STRING; case VTERM_N_PROPS: return 0; diff --git a/src/libvterm/src/vterm_internal.h b/src/libvterm/src/vterm_internal.h --- a/src/libvterm/src/vterm_internal.h +++ b/src/libvterm/src/vterm_internal.h @@ -169,6 +169,7 @@ struct VTermState SELECTION_QUERY, SELECTION_SET_INITIAL, SELECTION_SET, + SELECTION_INVALID, } state : 8; uint32_t recvpartial; uint32_t sendpartial; @@ -238,6 +239,8 @@ struct VTerm void *cbdata; int string_initial; + + int emit_nul; } parser; /* len == malloc()ed size; cur == number of valid bytes */ diff --git a/src/libvterm/t/17state_mouse.test b/src/libvterm/t/17state_mouse.test --- a/src/libvterm/t/17state_mouse.test +++ b/src/libvterm/t/17state_mouse.test @@ -55,6 +55,10 @@ MOUSEBTN d 4 0 output "\e[M\x60\x36\x2b" MOUSEBTN d 5 0 output "\e[M\x61\x36\x2b" +MOUSEBTN d 6 0 + output "\e[M\x62\x36\x2b" +MOUSEBTN d 7 0 + output "\e[M\x63\x36\x2b" !DECRQM on mouse button mode PUSH "\e[?1000\$p" @@ -179,3 +183,9 @@ RESET MOUSEMOVE 0,0 0 MOUSEBTN d 1 0 MOUSEBTN u 1 0 + +!DECSM can set multiple modes at once +PUSH "\e[?1002;1006h" + settermprop 8 2 +MOUSEBTN d 1 0 + output "\e[<0;1;1M" diff --git a/src/libvterm/t/25state_input.test b/src/libvterm/t/25state_input.test --- a/src/libvterm/t/25state_input.test +++ b/src/libvterm/t/25state_input.test @@ -148,7 +148,9 @@ FOCUS IN FOCUS OUT !Focus reporting enabled +WANTSTATE +p PUSH "\e[?1004h" + settermprop 9 true FOCUS IN output "\e[I" FOCUS OUT diff --git a/src/libvterm/t/30state_pen.test b/src/libvterm/t/30state_pen.test --- a/src/libvterm/t/30state_pen.test +++ b/src/libvterm/t/30state_pen.test @@ -123,3 +123,11 @@ PUSH "\e[74m" PUSH "\e[75m" ?pen small = off ?pen baseline = normal + +!DECSTR resets pen attributes +PUSH "\e[1;4m" + ?pen bold = on + ?pen underline = 1 +PUSH "\e[!p" + ?pen bold = off + ?pen underline = 0 diff --git a/src/libvterm/t/40state_selection.test b/src/libvterm/t/40state_selection.test --- a/src/libvterm/t/40state_selection.test +++ b/src/libvterm/t/40state_selection.test @@ -26,6 +26,30 @@ PUSH "\e]52;c;SGVsbG" PUSH "8s\e\\" selection-set mask=0001 "lo,"] +!Set clipboard; empty first chunk +PUSH "\e]52;c;" +PUSH "SGVsbG8s\e\\" + selection-set mask=0001 ["Hello,"] + +!Set clipboard; empty final chunk +PUSH "\e]52;c;SGVsbG8s" + selection-set mask=0001 ["Hello," +PUSH "\e\\" + selection-set mask=0001 ] + +!Set clipboard; longer than buffer +PUSH "\e]52;c;" . "LS0t"x10 . "\e\\" + selection-set mask=0001 ["-"x15 + selection-set mask=0001 "-"x15] + +!Clear clipboard +PUSH "\e]52;c;\e\\" + selection-set mask=0001 [] + +!Set invalid data clears and ignores +PUSH "\e]52;c;SGVs*SGVsbG8s\e\\" + selection-set mask=0001 [] + !Query clipboard PUSH "\e]52;c;?\e\\" selection-query mask=0001 diff --git a/src/libvterm/t/64screen_pen.test b/src/libvterm/t/64screen_pen.test --- a/src/libvterm/t/64screen_pen.test +++ b/src/libvterm/t/64screen_pen.test @@ -41,21 +41,31 @@ PUSH "x\e[74m0\e[73m2\e[m" ?screen_cell 0,9 = {0x30} width=1 attrs={S_} fg=rgb(240,240,240) bg=rgb(0,0,0) ?screen_cell 0,10 = {0x32} width=1 attrs={S^} fg=rgb(240,240,240) bg=rgb(0,0,0) -!EL sets reverse and colours to end of line +!EL sets only colours to end of line, not other attrs PUSH "\e[H\e[7;33;44m\e[K" - ?screen_cell 0,0 = {} width=1 attrs={R} fg=idx(3) bg=idx(4) - ?screen_cell 0,79 = {} width=1 attrs={R} fg=idx(3) bg=idx(4) + ?screen_cell 0,0 = {} width=1 attrs={} fg=idx(3) bg=idx(4) + ?screen_cell 0,79 = {} width=1 attrs={} fg=idx(3) bg=idx(4) !DECSCNM xors reverse for entire screen -PUSH "\e[?5h" - ?screen_cell 0,0 = {} width=1 attrs={} fg=idx(3) bg=idx(4) - ?screen_cell 0,79 = {} width=1 attrs={} fg=idx(3) bg=idx(4) +PUSH "R\e[?5h" + ?screen_cell 0,0 = {0x52} width=1 attrs={} fg=idx(3) bg=idx(4) ?screen_cell 1,0 = {} width=1 attrs={R} fg=rgb(240,240,240) bg=rgb(0,0,0) PUSH "\e[?5\$p" output "\e[?5;1\$y" PUSH "\e[?5l" - ?screen_cell 0,0 = {} width=1 attrs={R} fg=idx(3) bg=idx(4) - ?screen_cell 0,79 = {} width=1 attrs={R} fg=idx(3) bg=idx(4) + ?screen_cell 0,0 = {0x52} width=1 attrs={R} fg=idx(3) bg=idx(4) ?screen_cell 1,0 = {} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0) PUSH "\e[?5\$p" output "\e[?5;2\$y" + +!Set default colours +RESET +PUSH "ABC\e[31mDEF\e[m" + ?screen_cell 0,0 = {0x41} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0) + ?screen_cell 0,3 = {0x44} width=1 attrs={} fg=idx(1) bg=rgb(0,0,0) +SETDEFAULTCOL rgb(252,253,254) + ?screen_cell 0,0 = {0x41} width=1 attrs={} fg=rgb(252,253,254) bg=rgb(0,0,0) + ?screen_cell 0,3 = {0x44} width=1 attrs={} fg=idx(1) bg=rgb(0,0,0) +SETDEFAULTCOL rgb(250,250,250) rgb(10,20,30) + ?screen_cell 0,0 = {0x41} width=1 attrs={} fg=rgb(250,250,250) bg=rgb(10,20,30) + ?screen_cell 0,3 = {0x44} width=1 attrs={} fg=idx(1) bg=rgb(10,20,30) diff --git a/src/libvterm/t/69screen_reflow.test b/src/libvterm/t/69screen_reflow.test --- a/src/libvterm/t/69screen_reflow.test +++ b/src/libvterm/t/69screen_reflow.test @@ -77,3 +77,12 @@ RESIZE 5,16 ?lineinfo 3 = ?screen_row 3 = "> " ?cursor = 3,2 + +!Cursor goes missing +# For more context: https://github.com/neovim/neovim/pull/21124 +RESET +RESIZE 5,5 +RESIZE 3,1 +PUSH "\x1b[2;1Habc\r\n\x1b[H" +RESIZE 1,1 + ?cursor = 0,0 diff --git a/src/libvterm/t/harness.c b/src/libvterm/t/harness.c --- a/src/libvterm/t/harness.c +++ b/src/libvterm/t/harness.c @@ -82,6 +82,26 @@ static void print_color(const VTermColor printf(")"); } +static VTermColor strpe_color(char **strp) +{ + uint8_t r, g, b, idx; + int len = 0; + VTermColor col; + + if(sscanf(*strp, "rgb(%hhu,%hhu,%hhu)%n", &r, &g, &b, &len) == 3 && len > 0) { + *strp += len; + vterm_color_rgb(&col, r, g, b); + } + else if(sscanf(*strp, "idx(%hhu)%n", &idx, &len) == 1 && len > 0) { + *strp += len; + vterm_color_indexed(&col, idx); + } + else + vterm_color_rgb(&col, 127, 127, 127); + + return col; +} + static VTerm *vt; static VTermState *state; static VTermScreen *screen; @@ -669,7 +689,10 @@ int main(int argc UNUSED, char **argv UN if(!state) { state = vterm_obtain_state(vt); vterm_state_set_callbacks(state, &state_cbs, NULL); - vterm_state_set_selection_callbacks(state, &selection_cbs, NULL, NULL, 1024); + /* In some tests we want to check the behaviour of overflowing the + * buffer, so make it nicely small + */ + vterm_state_set_selection_callbacks(state, &selection_cbs, NULL, NULL, 16); vterm_state_set_bold_highbright(state, 1); vterm_state_reset(state, 1); } @@ -942,6 +965,23 @@ int main(int argc UNUSED, char **argv UN vterm_screen_flush_damage(screen); } + else if(strstartswith(line, "SETDEFAULTCOL ")) { + assert(screen); + char *linep = line + 14; + while(linep[0] == ' ') + linep++; + VTermColor fg = strpe_color(&linep); + if(linep[0]) { + while(linep[0] == ' ') + linep++; + VTermColor bg = strpe_color(&linep); + + vterm_screen_set_default_colors(screen, &fg, &bg); + } + else + vterm_screen_set_default_colors(screen, &fg, NULL); + } + else if(line[0] == '?') { if(streq(line, "?cursor")) { assert(state); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1684, +/**/ 1683, /**/ 1682,