summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libvterm/CODE-MAP66
-rw-r--r--src/libvterm/Makefile5
-rw-r--r--src/libvterm/include/vterm.h13
-rw-r--r--src/libvterm/src/parser.c9
-rw-r--r--src/libvterm/src/pen.c20
-rw-r--r--src/libvterm/src/screen.c53
-rw-r--r--src/libvterm/src/state.c56
-rw-r--r--src/libvterm/src/vterm.c3
-rw-r--r--src/libvterm/src/vterm_internal.h3
-rw-r--r--src/libvterm/t/17state_mouse.test10
-rw-r--r--src/libvterm/t/25state_input.test2
-rw-r--r--src/libvterm/t/30state_pen.test8
-rw-r--r--src/libvterm/t/40state_selection.test24
-rw-r--r--src/libvterm/t/64screen_pen.test26
-rw-r--r--src/libvterm/t/69screen_reflow.test9
-rw-r--r--src/libvterm/t/harness.c42
-rw-r--r--src/version.c2
17 files changed, 313 insertions, 38 deletions
diff --git a/src/libvterm/CODE-MAP b/src/libvterm/CODE-MAP
new file mode 100644
index 0000000000..c7a0344fc8
--- /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
index ba4a3157ed..94ca40998a 100644
--- 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
index 6a967dbdb4..a3aa17a8f6 100644
--- 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 VTermScreen *screen, VTermPos pos);
*/
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
index 0d1e12b0a2..6d225166e3 100644
--- a/src/libvterm/src/parser.c
+++ b/src/libvterm/src/parser.c
@@ -148,11 +148,15 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
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
index 1c6cd4e488..ddc8e40a79 100644
--- a/src/libvterm/src/pen.c
+++ b/src/libvterm/src/pen.c
@@ -259,15 +259,17 @@ void vterm_state_get_palette_color(const VTermState *state, int index, VTermColo
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;
-
- /* 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_fg) {
+ state->default_fg = *default_fg;
+ state->default_fg.type = (state->default_fg.type & ~VTERM_COLOR_DEFAULT_MASK)
+ | VTERM_COLOR_DEFAULT_FG;
+ }
+
+ 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
index fb1d26e432..53564be16b 100644
--- a/src/libvterm/src/screen.c
+++ b/src/libvterm/src/screen.c
@@ -292,7 +292,11 @@ static int erase_internal(VTermRect rect, int selective, void *user)
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 *screen, int bufidx, int new_rows, int new
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 *screen, int bufidx, int new_rows, int new
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(const VTermScreen *screen, VTermColor *co
{
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
index ee44824696..ee36ad4c2d 100644
--- a/src/libvterm/src/state.c
+++ b/src/libvterm/src/state.c
@@ -837,6 +837,7 @@ static void set_dec_mode(VTermState *state, int num, int val)
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, const long args[], int argcount, const cha
switch(intermed[0]) {
case ' ':
+ case '!':
case '"':
case '$':
case '\'':
@@ -1370,8 +1372,10 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
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, const long args[], int argcount, const cha
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, const long args[], int argcount, const cha
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 *state, VTermStringFragment frag)
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 *state, VTermStringFragment frag)
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 *state, VTermStringFragment frag)
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 *state, VTermStringFragment frag)
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(VTermState *state, VTermStringFragment frag)
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 *state, VTermProp prop, VTermValue *val)
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
index ed6d21b778..dba6377186 100644
--- a/src/libvterm/src/vterm.c
+++ b/src/libvterm/src/vterm.c
@@ -73,6 +73,8 @@ VTerm *vterm_build(const struct VTermBuilder *builder)
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(VTermProp prop)
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
index 3e95611b42..0f80fa4315 100644
--- 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
index e5ba29b4e7..33b7dc2c74 100644
--- 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
index 4eb4c6abdf..11013ed9ba 100644
--- 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
index 92cf01d855..1a6cd01dd1 100644
--- 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
index 6ed8972fc0..a6a32319f0 100644
--- 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
index 1cb6324bda..fa15bce959 100644
--- 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)
-
-!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)
+
+!DECSCNM xors reverse for entire screen
+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
index 278cc5bdd1..eb7e4e4d95 100644
--- 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
index d12c1205ad..5285d94ec0 100644
--- a/src/libvterm/t/harness.c
+++ b/src/libvterm/t/harness.c
@@ -82,6 +82,26 @@ static void print_color(const VTermColor *col)
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 UNUSED)
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 UNUSED)
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
index 34f1203cdf..96c1817819 100644
--- 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,