From 1d9990daac37810ebfd20b49fa57e39e6806f4f6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 10 May 2025 10:36:33 +0800 Subject: [PATCH] fix(folds): avoid unnecessary loop with horizontal scrolling (#33932) Fix #33931 --- src/nvim/drawline.c | 11 +++- test/functional/ui/fold_spec.lua | 98 +++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e68265bcb6..b5baf6f646 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1475,7 +1475,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b ? (startrow == 0 ? wp->w_skipcol : 0) : wp->w_leftcol; - if (start_col > 0 && col_rows == 0) { + if (has_foldtext) { + wlv.vcol = start_col; + } else if (start_col > 0 && col_rows == 0) { char *prev_ptr = ptr; CharSize cs = { 0 }; @@ -1518,12 +1520,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b // - 'cuc' is set, or // - 'colorcolumn' is set, or // - 'virtualedit' is set, or - // - the visual mode is active, + // - the visual mode is active, or + // - drawing a fold // the end of the line may be before the start of the displayed part. if (wlv.vcol < start_col && (wp->w_p_cuc || wlv.color_cols || virtual_active(wp) - || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { + || (VIsual_active && wp->w_buffer == curwin->w_buffer) + || has_fold)) { wlv.vcol = start_col; } @@ -1935,6 +1939,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b wlv.n_extra = (int)strlen(wlv.p_extra); if (wlv.p_extra != buf_fold) { + assert(foldtext_free == NULL); foldtext_free = wlv.p_extra; } wlv.sc_extra = NUL; diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 13b1558b68..249ea86e3e 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -1593,6 +1593,45 @@ describe('folded lines', function() | ]]) end + + eq({ 0, 1, 2, 0, 2 }, fn.getcurpos()) + api.nvim_input_mouse('left', 'press', '', multigrid and 2 or 0, 2, 4) + eq({ 0, 3, 2, 0, 2 }, fn.getcurpos()) + feed('2k') + eq({ 0, 1, 2, 0, 2 }, fn.getcurpos()) + + api.nvim_set_option_value('foldtext', "'αβγ'", { win = 0 }) + -- No crash or memory leak when scrolling beyond end of folded line #33931 + fn.append('$', ('!'):rep(100)) + feed('G$') + if multigrid then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {8: 1 } | + {8: 2 } | + {8: 3 }{5:αβγ······································}| + {8: 5 } | + {8: 6 } | + {8: 7 }!!!!!!!!!!!!!!!!!!!!^! | + {1:~ }| + ## grid 3 + | + ]]) + else + screen:expect([[ + {8: 1 } | + {8: 2 } | + {8: 3 }{5:αβγ······································}| + {8: 5 } | + {8: 6 } | + {8: 7 }!!!!!!!!!!!!!!!!!!!!^! | + {1:~ }| + | + ]]) + end end) it('fold attached virtual lines are drawn and scrolled correctly #21837', function() @@ -2624,8 +2663,6 @@ describe('folded lines', function() screen:try_resize(30, 7) insert(content1) command('hi! CursorLine guibg=NONE guifg=Red gui=NONE') - command('hi F0 guibg=Red guifg=Black') - command('hi F1 guifg=White') command([[syn match Keyword /\/]]) command('hi! Keyword guibg=NONE guifg=Green') api.nvim_set_option_value('cursorline', true, {}) @@ -2734,6 +2771,63 @@ describe('folded lines', function() {11:-- VISUAL LINE --} | ]]) end + + api.nvim_set_option_value('rightleft', false, {}) + api.nvim_set_option_value('wrap', false, {}) + feed('zl') + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + {7: }his is a | + {7:- }{12:^alid English }| + {7:│+ }{21:entence}{5: composed by·······}| + {7:│+ }{5:n his cave.···············}| + {1:~ }|*2 + ## grid 3 + | + ]]) + else + screen:expect([[ + {7: }his is a | + {7:- }{12:^alid English }| + {7:│+ }{21:entence}{5: composed by·······}| + {7:│+ }{5:n his cave.···············}| + {1:~ }|*2 + | + ]]) + end + + fn.append(0, ('!'):rep(15)) + feed('gg$zs') + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + {7: }{12:^! }| + {7: } | + {7:- } | + {7:│+ }{5:sed by····················}| + {7:│+ }{5:··························}| + {1:~ }| + ## grid 3 + | + ]]) + else + screen:expect([[ + {7: }{12:^! }| + {7: } | + {7:- } | + {7:│+ }{5:sed by····················}| + {7:│+ }{5:··························}| + {1:~ }| + | + ]]) + end end) end