Commit: patch 9.2.0666: Terminal-Normal mode does not color empty lines with a background color

1 view
Skip to first unread message

Christian Brabandt

unread,
Jun 17, 2026, 3:45:14 PM (11 hours ago) Jun 17
to vim...@googlegroups.com
patch 9.2.0666: Terminal-Normal mode does not color empty lines with a background color

Commit: https://github.com/vim/vim/commit/d4f531c90eec67d51261c9fd8ecca625a2dd20c3
Author: Hirohito Higashi <h.eas...@gmail.com>
Date: Wed Jun 17 19:37:28 2026 +0000

patch 9.2.0666: Terminal-Normal mode does not color empty lines with a background color

Problem: In Terminal-Normal mode an empty line that was erased with a
background color (CSI K after e.g. CSI 100m) is shown without
that color, although it is colored while the job is running.
Solution: Reset the empty line's background attribute only when the fill
is the terminal's default color, so that a Visual selection
still shows on a plain empty line, while an explicitly set
background color is kept.

closes: #20547

Co-Authored-By: Claude Opus 4.8 (1M context) <nor...@anthropic.com>
Signed-off-by: Hirohito Higashi <h.eas...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/drawline.c b/src/drawline.c
index 0b912e1ea..1747f67f4 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -2875,8 +2875,11 @@ win_line(
#ifdef FEAT_TERMINAL
if (term_show_buffer(wp->w_buffer)
&& wlv.vcol == 0
- && wlv.win_attr == term_get_attr(wp, lnum, -1))
- // reset highlighting attribute
+ && wlv.win_attr == term_get_attr(wp, lnum, -1)
+ && wlv.win_attr == term_get_default_attr(wp))
+ // Reset the attribute for an empty line with the
+ // default background, so a Visual selection shows;
+ // keep an explicitly set background color.
wlv.win_attr = 0;
#endif
}
diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro
index 6429ffadd..cc859dd6c 100644
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -36,6 +36,7 @@ int term_is_finished(buf_T *buf);
int term_show_buffer(buf_T *buf);
void term_change_in_curbuf(void);
int term_get_attr(win_T *wp, linenr_T lnum, int col);
+int term_get_default_attr(win_T *wp);
void term_reset_hlfwin(win_T *wp);
void term_update_hlfwin(win_T *wp);
void term_update_hlfwin_all(void);
diff --git a/src/terminal.c b/src/terminal.c
index a22047506..3a8f6cc67 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -4444,6 +4444,19 @@ term_get_attr(win_T *wp, linenr_T lnum, int col)
return cell2attr(term, wp, &cellattr->attrs, &cellattr->fg, &cellattr->bg);
}

+/*
+ * Return the screen attribute for the terminal's default color. Used to tell
+ * whether a line's fill (background) is the default or was set explicitly.
+ */
+ int
+term_get_default_attr(win_T *wp)
+{
+ term_T *term = wp->w_buffer->b_term;
+ cellattr_T *cellattr = &term->tl_default_color;
+
+ return cell2attr(term, wp, &cellattr->attrs, &cellattr->fg, &cellattr->bg);
+}
+
/*
* Convert a cterm color number 0 - 255 to RGB.
* This is compatible with xterm.
diff --git a/src/testdir/dumps/Test_terminal_colored_empty_1.dump b/src/testdir/dumps/Test_terminal_colored_empty_1.dump
new file mode 100644
index 000000000..96ac812a0
--- /dev/null
+++ b/src/testdir/dumps/Test_terminal_colored_empty_1.dump
@@ -0,0 +1,10 @@
+| +0&#8080809@74
+|o|l|d| @71
+@75
+> +0&#ffffff0@74
+|!+2#ffffff16#00e0003|s|h| |.|/|X|t|e|r|m|_|c|o|l|o|r|e|d|.|s|h| |[|f|i|n|i|s|h|e|d|]| @23|4|,|0|-|1| @9|A|l@1
+| +0#0000000#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|[+1#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1
+| +0&&@74
diff --git a/src/testdir/dumps/Test_terminal_colored_empty_2.dump b/src/testdir/dumps/Test_terminal_colored_empty_2.dump
new file mode 100644
index 000000000..96ac812a0
--- /dev/null
+++ b/src/testdir/dumps/Test_terminal_colored_empty_2.dump
@@ -0,0 +1,10 @@
+| +0&#8080809@74
+|o|l|d| @71
+@75
+> +0&#ffffff0@74
+|!+2#ffffff16#00e0003|s|h| |.|/|X|t|e|r|m|_|c|o|l|o|r|e|d|.|s|h| |[|f|i|n|i|s|h|e|d|]| @23|4|,|0|-|1| @9|A|l@1
+| +0#0000000#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|[+1#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1
+| +0&&@74
diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim
index 2e80f6fe4..8bbef4fd6 100644
--- a/src/testdir/test_terminal3.vim
+++ b/src/testdir/test_terminal3.vim
@@ -1039,6 +1039,29 @@ func Test_terminal_visual_empty_listchars()
call StopVimInTerminal(buf)
endfunc

+func Test_terminal_normal_mode_colored_empty_line()
+ CheckScreendump
+ CheckRunVimInTerminal
+ CheckUnix
+
+ " Erase lines with a gray background (CSI 100m) using CSI K. The empty lines
+ " around "old" must stay gray in Terminal-Normal mode too, not only while the
+ " job is running.
+ call writefile(["printf '\033[100m\033[K\nold\033[K\n\033[K\033[0m\n'"],
+ \ 'Xterm_colored.sh', 'D')
+ call writefile([':term sh ./Xterm_colored.sh'], 'XtermColored', 'D')
+ let buf = RunVimInTerminal('-S XtermColored', #{rows: 10})
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_terminal_colored_empty_1', {})
+
+ " Enter Terminal-Normal mode: the empty lines must still be gray.
+ call term_sendkeys(buf, "\<C-W>N")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_terminal_colored_empty_2', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_terminal_ansi_color_windows_cui()
if !has('win32') || has('gui_running')
throw 'Skipped: only for the Windows CUI'
diff --git a/src/version.c b/src/version.c
index 81bbaac75..fc9e9efae 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 666,
/**/
665,
/**/
Reply all
Reply to author
Forward
0 new messages