From c6864b0d146f017990d6feb8c876784160a25241 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sun, 7 Jan 2024 09:59:10 +0100 Subject: [PATCH] fix(column): redraw 'statuscolumn' on wrapped lines with 'relativenumber' Problem: The 'statuscolumn' is not redrawn on the wrapped part of a line when moving the cursor with 'relativenumber' set. Solution: Redraw the 'statuscolumn' for the entire line height in the "col_rows" win_line() code path. --- src/nvim/drawline.c | 22 ++++++++++++++-------- src/nvim/drawscreen.c | 10 ++++------ test/functional/ui/statuscolumn_spec.lua | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 5ccfb24b8a..e8c41cb608 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -907,7 +907,7 @@ static void fix_for_boguscols(winlinevars_T *wlv) /// @param lnum line to display /// @param startrow first row relative to window grid /// @param endrow last grid row to be redrawn -/// @param number_only only update the number column +/// @param col_rows only update the columns for this amount of rows /// @param spv 'spell' related variables kept between calls for "wp" /// @param foldinfo fold info for this line /// @param[in, out] providers decoration providers active this line @@ -915,7 +915,7 @@ static void fix_for_boguscols(winlinevars_T *wlv) /// or explicitly return `false`. /// /// @return the number of last row the line occupies. -int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_only, spellvars_T *spv, +int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, spellvars_T *spv, foldinfo_T foldinfo) { winlinevars_T wlv; // variables passed between functions @@ -1019,7 +1019,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl buf_T *buf = wp->w_buffer; const bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); - if (!number_only) { + if (col_rows == 0) { // To speed up the loop below, set extra_check when there is linebreak, // trailing white space and/or syntax processing to be done. extra_check = wp->w_p_lbr; @@ -1229,7 +1229,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl line_attr_lowprio_save = wlv.line_attr_lowprio; } - if (spv->spv_has_spell && !number_only) { + if (spv->spv_has_spell && col_rows == 0) { // Prepare for spell checking. extra_check = true; @@ -1321,7 +1321,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } else { v = wp->w_leftcol; } - if (v > 0 && !number_only) { + if (v > 0 && col_rows == 0) { char *prev_ptr = ptr; chartabsize_T cts; int charsize = 0; @@ -1454,7 +1454,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl } } - if (!number_only && !has_fold && !end_fill) { + if (col_rows == 0 && !has_fold && !end_fill) { v = ptr - line; area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v, &line, &screen_search_hl, &search_attr, @@ -1566,13 +1566,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl && wp == curwin && lnum == wp->w_cursor.lnum && wlv.vcol >= wp->w_virtcol) - || number_only) + || col_rows > 0) && wlv.filler_todo <= 0) { - if (!number_only) { + if (col_rows == 0) { draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row); } // don't clear anything after wlv.col win_put_linebuf(wp, wlv.row, 0, wlv.col, wlv.col, bg_attr, false); + // update the 'statuscolumn' for the entire line size + if (col_rows > 0 && statuscol.draw && ++wlv.row - wlv.startrow < col_rows) { + draw_cols = true; + wlv.off = 0; + continue; + } // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. if (wp->w_p_cuc) { diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index b49de19349..8341989ab0 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -2285,9 +2285,8 @@ static void win_update(win_T *wp) // Display one line spellvars_T zero_spv = { 0 }; - row = win_line(wp, lnum, srow, wp->w_grid.rows, false, - foldinfo.fi_lines > 0 ? &zero_spv : &spv, - foldinfo); + row = win_line(wp, lnum, srow, wp->w_grid.rows, 0, + foldinfo.fi_lines > 0 ? &zero_spv : &spv, foldinfo); if (foldinfo.fi_lines == 0) { wp->w_lines[idx].wl_folded = false; @@ -2325,7 +2324,7 @@ static void win_update(win_T *wp) // text doesn't need to be drawn, but the number column does. 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, true, &spv, info); + win_line(wp, lnum, srow, wp->w_grid.rows, wp->w_lines[idx].wl_size, &spv, info); } // This line does not need to be drawn, advance to the next one. @@ -2422,8 +2421,7 @@ static void win_update(win_T *wp) // for ml_line_count+1 and only draw filler lines spellvars_T zero_spv = { 0 }; foldinfo_T zero_foldinfo = { 0 }; - row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, false, &zero_spv, - zero_foldinfo); + row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, 0, &zero_spv, zero_foldinfo); } } else if (dollar_vcol == -1) { wp->w_botline = lnum; diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index d5aeb2c51a..2058f9a59d 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -510,6 +510,28 @@ describe('statuscolumn', function() {0:~ }| | ]]) + -- Also test "col_rows" code path for 'relativenumber' cursor movement + command([[ + set cpoptions-=n nocursorline relativenumber + set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum.'\ '.v:relnum} + ]]) + feed('kk') + screen:expect([[ + {1:buffer 0 12 1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 12 1}aaaaaaaaaaa | + {1:buffer 0 13 0}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 13 0}aaaaaaaaaa^a | + {1:buffer 0 14 1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 14 1}aaaaaaaaaaa | + {1:buffer 0 15 2}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 15 2}aaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 2 15 2}aaaaaaaaaaaaaaaaaaaaaaa | + {1:virtual-3 15 2}virt_line1 | + {1:virtual-2 15 2}virt_line2 | + {1:virtual-1 15 2}END | + {0:~ }| + | + ]]) end) it('does not corrupt the screen with minwid sign item', function()