fix(display): adjust setting winline info for concealed lines (#33717)

Problem:  Wrong winline info after partial redraw. Setting
          `conceal_cursor_used` is unnecessarily spread out.
Solution: Rather than adjusting `wl_lastlnum` for the previous
          winline, adjust it when setting the current winline.
          Set `conceal_cursor_used` when the current window is redrawn.
(cherry picked from commit 97a6259442)
This commit is contained in:
luukvbaal
2025-05-01 09:51:51 +02:00
parent c4b9bdbdf4
commit 81233a41d7
4 changed files with 43 additions and 40 deletions

View File

@ -2789,7 +2789,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
curwin->w_cline_height = wlv.row - startrow;
curwin->w_cline_folded = has_fold;
curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
conceal_cursor_used = conceal_cursor_line(curwin);
}
break;

View File

@ -19,8 +19,6 @@ typedef struct {
} WinExtmark;
EXTERN kvec_t(WinExtmark) win_extmark_arr INIT( = KV_INITIAL_VALUE);
EXTERN bool conceal_cursor_used INIT( = false);
/// Spell checking variables passed from win_update() to win_line().
typedef struct {
bool spv_has_spell; ///< drawn window has spell checking

View File

@ -135,6 +135,7 @@ typedef enum {
static bool redraw_popupmenu = false;
static bool msg_grid_invalid = false;
static bool resizing_autocmd = false;
static bool conceal_cursor_used = false;
/// Check if the cursor line needs to be redrawn because of 'concealcursor'.
///
@ -2047,6 +2048,9 @@ static void win_update(win_T *wp)
foldinfo_T cursorline_fi = { 0 };
win_update_cursorline(wp, &cursorline_fi);
if (wp == curwin) {
conceal_cursor_used = conceal_cursor_line(curwin);
}
win_check_ns_hl(wp);
@ -2123,21 +2127,13 @@ static void win_update(win_T *wp)
// If the line is concealed and has no filler lines, go to the next line.
bool concealed = decor_conceal_line(wp, lnum - 1, false);
if (concealed) {
if (wp == curwin && lnum == curwin->w_cursor.lnum) {
conceal_cursor_used = conceal_cursor_line(curwin);
}
if (win_get_fill(wp, lnum) == 0) {
if (idx > 0) {
wp->w_lines[idx - 1].wl_lastlnum = lnum + foldinfo.fi_lines - (foldinfo.fi_lines != 0);
}
if (lnum == mod_top && lnum < mod_bot) {
mod_top += foldinfo.fi_lines ? foldinfo.fi_lines : 1;
}
lnum += foldinfo.fi_lines ? foldinfo.fi_lines : 1;
spv.spv_capcol_lnum = 0;
continue;
if (concealed && win_get_fill(wp, lnum) == 0) {
if (lnum == mod_top && lnum < mod_bot) {
mod_top += foldinfo.fi_lines ? foldinfo.fi_lines : 1;
}
lnum += foldinfo.fi_lines ? foldinfo.fi_lines : 1;
spv.spv_capcol_lnum = 0;
continue;
}
// When at start of changed lines: May scroll following lines
@ -2189,8 +2185,8 @@ static void win_update(win_T *wp)
// rows, and may insert/delete lines
int j = idx;
for (l = lnum; l < mod_bot; l++) {
int n = plines_win_full(wp, l, &l, NULL, true, false);
n -= (l == wp->w_topline ? adjust_plines_for_skipcol(wp) : 0);
int n = (l == wp->w_topline ? -adjust_plines_for_skipcol(wp) : 0);
n += plines_win_full(wp, l, &l, NULL, true, false);
new_rows += MIN(n, wp->w_height_inner);
j += n > 0; // don't count concealed lines
if (new_rows > wp->w_grid.rows - row - 2) {
@ -2306,23 +2302,19 @@ static void win_update(win_T *wp)
spv.spv_capcol_lnum = 0;
}
if (foldinfo.fi_lines == 0) {
wp->w_lines[idx].wl_folded = false;
wp->w_lines[idx].wl_foldend = lnum;
wp->w_lines[idx].wl_lastlnum = lnum;
did_update = DID_LINE;
} else {
foldinfo.fi_lines--;
wp->w_lines[idx].wl_folded = true;
wp->w_lines[idx].wl_foldend = lnum + foldinfo.fi_lines;
wp->w_lines[idx].wl_lastlnum = lnum + foldinfo.fi_lines;
did_update = DID_FOLD;
}
linenr_T lastlnum = lnum + foldinfo.fi_lines - (foldinfo.fi_lines > 0);
wp->w_lines[idx].wl_folded = foldinfo.fi_lines > 0;
wp->w_lines[idx].wl_foldend = lastlnum;
wp->w_lines[idx].wl_lastlnum = lastlnum;
did_update = foldinfo.fi_lines > 0 ? DID_FOLD : DID_LINE;
// Adjust "wl_lastlnum" for concealed lines below the last line in the window.
while (row == wp->w_grid.rows
&& wp->w_lines[idx].wl_lastlnum < buf->b_ml.ml_line_count
// Adjust "wl_lastlnum" for concealed lines below this line, unless it should
// still be drawn for below virt_lines attached to the current line. Below
// virt_lines attached to a second adjacent concealed line are concealed.
bool virt_below = decor_virt_lines(wp, lastlnum, lastlnum + 1, NULL, NULL, true) > 0;
while (!virt_below && wp->w_lines[idx].wl_lastlnum < buf->b_ml.ml_line_count
&& decor_conceal_line(wp, wp->w_lines[idx].wl_lastlnum, false)) {
virt_below = false;
wp->w_lines[idx].wl_lastlnum++;
hasFolding(wp, wp->w_lines[idx].wl_lastlnum, NULL, &wp->w_lines[idx].wl_lastlnum);
}
@ -2342,17 +2334,15 @@ static void win_update(win_T *wp)
if (dollar_vcol == -1) {
wp->w_lines[idx].wl_size = (uint16_t)(row - srow);
}
idx++;
lnum += foldinfo.fi_lines + 1;
lnum = wp->w_lines[idx++].wl_lastlnum + 1;
} else {
// If:
// - 'number' is set and below inserted/deleted lines, or
// - 'relativenumber' is set and cursor moved vertically,
// the text doesn't need to be redrawn, but the number column does.
if (((wp->w_p_nu && mod_top != 0 && lnum >= mod_bot
&& buf->b_mod_set && buf->b_mod_xlines != 0)
|| (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum))
&& !decor_conceal_line(wp, lnum - 1, true)) {
if ((wp->w_p_nu && mod_top != 0 && lnum >= mod_bot
&& buf->b_mod_set && buf->b_mod_xlines != 0)
|| (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum)) {
foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum
? cursorline_fi : fold_info(wp, lnum);
win_line(wp, lnum, srow, wp->w_grid.rows, wp->w_lines[idx].wl_size, false, &spv, info);

View File

@ -2950,6 +2950,22 @@ describe('extmark decorations', function()
{1:~ }|*4
|
]])
-- Correct relativenumber for line below concealed line #33694
feed('4Gk')
screen:expect([[
{2: 2 }for _,item in ipairs(items) do |
{2:3 } if h^l_id_cell ~= nil then |
{2: 1 } hl_id = hl_id_cell |
{2: 3 } for _ = 1, (count or 1) do |
{2: 4 } local cell = line[colpos] |
{2: 5 } cell.text = text |
{2: 6 } cell.hl_id = hl_id |
{2: 7 } colpos = colpos+1 |
{2: 8 } end |
{2: 9 }end |
{1:~ }|*4
|
]])
-- Also with above virtual line #32744
command('set nornu')
api.nvim_buf_set_extmark(0, ns, 3, 0, { virt_lines = { { { "virt_below 4" } } } })