commit 8f78591f9ac086f01c90ad804f48bf4b0c4a3196
parent 8b171852a92595176308a36978baead585e878d3
Author: zeertzjq <zeertzjq@outlook.com>
Date: Wed, 27 Aug 2025 10:16:13 +0800
fix(column): wrong alignment and highlight with empty 'display' (#35495)
This fixes a regression from #26961.
Diffstat:
4 files changed, 72 insertions(+), 14 deletions(-)
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
@@ -3178,5 +3178,5 @@ static void wlv_put_linebuf(win_T *wp, const winlinevars_T *wlv, int endcol, boo
int row = wlv->row;
int coloff = 0;
ScreenGrid *g = grid_adjust(grid, &row, &coloff);
- grid_put_linebuf(g, row, coloff, startcol, endcol, clear_width, bg_attr, wlv->vcol - 1, flags);
+ grid_put_linebuf(g, row, coloff, startcol, endcol, clear_width, bg_attr, 0, wlv->vcol - 1, flags);
}
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
@@ -2577,7 +2577,8 @@ void win_draw_end(win_T *wp, schar_T c1, bool draw_margin, int startrow, int end
n = grid_line_fill(n, n + fdc, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
// draw the sign column
- n = grid_line_fill(n, n + wp->w_scwidth, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
+ n = grid_line_fill(n, n + wp->w_scwidth * SIGN_WIDTH, schar_from_ascii(' '),
+ win_hl_attr(wp, HLF_SC));
// draw the number column
if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) {
@@ -2586,14 +2587,14 @@ void win_draw_end(win_T *wp, schar_T c1, bool draw_margin, int startrow, int end
}
}
- int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl));
+ int attr = win_hl_attr(wp, (int)hl);
if (n < wp->w_view_width) {
- grid_line_put_schar(n, c1, 0); // base attr is inherited from clear
+ grid_line_put_schar(n, c1, attr);
n++;
}
- grid_line_clear_end(n, wp->w_view_width, attr);
+ grid_line_clear_end(n, wp->w_view_width, win_bg_attr(wp), attr);
if (wp->w_p_rl) {
grid_line_mirror(wp->w_view_width);
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
@@ -352,6 +352,7 @@ static int grid_line_maxcol = 0;
static int grid_line_first = INT_MAX;
static int grid_line_last = 0;
static int grid_line_clear_to = 0;
+static int grid_line_bg_attr = 0;
static int grid_line_clear_attr = 0;
static int grid_line_flags = 0;
@@ -377,6 +378,7 @@ void screengrid_line_start(ScreenGrid *grid, int row, int col)
grid_line_maxcol = MIN(grid_line_maxcol, grid->cols - grid_line_coloff);
grid_line_last = 0;
grid_line_clear_to = 0;
+ grid_line_bg_attr = 0;
grid_line_clear_attr = 0;
grid_line_flags = 0;
@@ -517,14 +519,17 @@ int grid_line_fill(int start_col, int end_col, schar_T sc, int attr)
return end_col;
}
-void grid_line_clear_end(int start_col, int end_col, int attr)
+/// @param bg_attr applies to both the buffered line and the columns to clear
+/// @param clear_attr applies only to the columns to clear
+void grid_line_clear_end(int start_col, int end_col, int bg_attr, int clear_attr)
{
if (grid_line_first > start_col) {
grid_line_first = start_col;
grid_line_last = start_col;
}
grid_line_clear_to = end_col;
- grid_line_clear_attr = attr;
+ grid_line_bg_attr = bg_attr;
+ grid_line_clear_attr = clear_attr;
}
/// move the cursor to a position in a currently rendered line.
@@ -593,7 +598,8 @@ void grid_line_flush(void)
}
grid_put_linebuf(grid, grid_line_row, grid_line_coloff, grid_line_first, grid_line_last,
- grid_line_clear_to, grid_line_clear_attr, -1, grid_line_flags);
+ grid_line_clear_to, grid_line_bg_attr, grid_line_clear_attr, -1,
+ grid_line_flags);
}
/// flush grid line but only if on a valid row
@@ -621,7 +627,7 @@ void grid_clear(GridView *grid, int start_row, int end_row, int start_col, int e
grid_line_grid = NULL; // TODO(bfredl): make callers behave instead
return;
}
- grid_line_clear_end(start_col, end_col, attr);
+ grid_line_clear_end(start_col, end_col, attr, 0);
grid_line_flush();
}
}
@@ -648,6 +654,7 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int col, size_t off_to, int
/// @param coloff gives the first column on the grid for this line.
/// @param endcol gives the columns where valid characters are.
/// @param clear_width see SLF_RIGHTLEFT.
+/// @param clear_attr combined with "bg_attr" for the columns to clear.
/// @param flags can have bits:
/// - SLF_RIGHTLEFT rightleft text, like a window with 'rightleft' option set:
/// - When false, clear columns "endcol" to "clear_width".
@@ -658,7 +665,7 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int col, size_t off_to, int
/// - When true, use an increasing sequence starting from "last_vcol + 1" for
/// grid->vcols[] of the columns to clear.
void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol, int clear_width,
- int bg_attr, colnr_T last_vcol, int flags)
+ int bg_attr, int clear_attr, colnr_T last_vcol, int flags)
{
bool redraw_next; // redraw_this for next character
bool clear_next = false;
@@ -778,15 +785,16 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
grid->vcols[off] = (flags & SLF_INC_VCOL) ? ++last_vcol : last_vcol;
}
}
+ clear_attr = hl_combine_attr(bg_attr, clear_attr);
// blank out the rest of the line
// TODO(bfredl): we could cache winline widths
for (col = clear_start; col < clear_width; col++) {
size_t off = off_to + (size_t)col;
if (grid->chars[off] != schar_from_ascii(' ')
- || grid->attrs[off] != bg_attr
+ || grid->attrs[off] != clear_attr
|| rdb_flags & kOptRdbFlagNodelta) {
grid->chars[off] = schar_from_ascii(' ');
- grid->attrs[off] = bg_attr;
+ grid->attrs[off] = clear_attr;
if (clear_dirty_start == -1) {
clear_dirty_start = col;
}
@@ -803,7 +811,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
start_dirty = clear_dirty_start;
} else {
ui_line(grid, row, invalid_row, coloff + clear_dirty_start, coloff + clear_dirty_start,
- coloff + clear_end, bg_attr, flags & SLF_WRAP);
+ coloff + clear_end, clear_attr, flags & SLF_WRAP);
}
clear_end = end_dirty;
} else {
@@ -820,7 +828,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
if (clear_end > start_dirty) {
if (!grid->throttled) {
ui_line(grid, row, invalid_row, coloff + start_dirty, coloff + end_dirty, coloff + clear_end,
- bg_attr, flags & SLF_WRAP);
+ clear_attr, flags & SLF_WRAP);
} else if (grid->dirty_col) {
// TODO(bfredl): really get rid of the extra pseudo terminal in message.c
// by using a linebuf_char copy for "throttled message line"
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
@@ -689,4 +689,53 @@ describe('Signs', function()
api.nvim_buf_set_lines(0, 0, -1, false, {})
n.assert_alive()
end)
+
+ it("with line that doesn't fit in window", function()
+ screen:try_resize(40, 9)
+ api.nvim_set_option_value('foldcolumn', '1', {})
+ api.nvim_set_option_value('number', true, {})
+ api.nvim_set_option_value('signcolumn', 'yes:2', {})
+ api.nvim_set_hl(0, 'FoldColumn', { link = 'StatusLine' })
+ api.nvim_buf_set_lines(
+ 0,
+ 0,
+ -1,
+ false,
+ { ('a'):rep(90), ('b'):rep(90), ('c'):rep(90), ('d'):rep(90), ('e'):rep(90) }
+ )
+ screen:expect([[
+ {3: }{7: }{8: 1 }^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {3: }{7: }{8: 2 }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbb |
+ {3: }{7: }{8: 3 }ccccccccccccccccccccccccccccccc|
+ {3: }{7: }{8: }cccccccccccccccccccccccccccc{1:@@@}|
+ |
+ ]])
+ api.nvim_set_option_value('display', 'truncate', {})
+ screen:expect([[
+ {3: }{7: }{8: 1 }^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {3: }{7: }{8: 2 }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbb |
+ {3: }{7: }{8: 3 }ccccccccccccccccccccccccccccccc|
+ {1:@@@ }|
+ |
+ ]])
+ api.nvim_set_option_value('display', '', {})
+ screen:expect([[
+ {3: }{7: }{8: 1 }^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {3: }{7: }{8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {3: }{7: }{8: 2 }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ {3: }{7: }{8: }bbbbbbbbbbbbbbbbbbbbbbbbbbbb |
+ {3: }{7: }{8: }{1:@ }|*2
+ |
+ ]])
+ end)
end)