neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 1c96140b1a608020bfcee5f5ad73b2179e31b057
parent 0f9aae20ec60262822ffd6a2a565628e20f4bcea
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Thu,  1 Jan 2026 15:19:12 +0800

Merge pull request #37164 from janlazo/vim-8.2.2198

vim-patch:8.2.{2198,3159}
Diffstat:
Msrc/nvim/api/buffer.c | 4++--
Msrc/nvim/change.c | 10+++++++---
Msrc/nvim/decoration_provider.c | 2+-
Msrc/nvim/diff.c | 2+-
Msrc/nvim/drawscreen.c | 2+-
Msrc/nvim/eval.c | 4++--
Msrc/nvim/eval/window.c | 2+-
Msrc/nvim/ex_cmds.c | 2+-
Msrc/nvim/ex_getln.c | 2+-
Msrc/nvim/move.c | 25+++++++++++++++----------
Msrc/nvim/normal.c | 6+++---
Msrc/nvim/register.c | 2+-
Msrc/nvim/window.c | 10+++++-----
13 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c @@ -1269,7 +1269,7 @@ static void fix_cursor(win_T *win, linenr_T lo, linenr_T hi, linenr_T extra) win->w_valid &= ~(VALID_BOTLINE_AP); update_topline(win); } else { - invalidate_botline(win); + invalidate_botline_win(win); } } @@ -1343,7 +1343,7 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l check_cursor_col(win); changed_cline_bef_curs(win); - invalidate_botline(win); + invalidate_botline_win(win); } /// Initialise a string array either: diff --git a/src/nvim/change.c b/src/nvim/change.c @@ -177,9 +177,13 @@ static void changed_lines_invalidate_win(win_T *wp, linenr_T lnum, colnr_T col, changed_cline_bef_curs(wp); } if (wp->w_botline >= lnum) { - // Assume that botline doesn't change (inserted lines make - // other lines scroll down below botline). - approximate_botline_win(wp); + if (xtra < 0) { + invalidate_botline_win(wp); + } else { + // Assume that botline doesn't change (inserted lines make + // other lines scroll down below botline). + approximate_botline_win(wp); + } } // If lines have been inserted/deleted and the buffer has virt_lines, or diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c @@ -139,7 +139,7 @@ void decor_providers_invoke_win(win_T *wp) && decor_state.future_begin == (int)kv_size(decor_state.ranges_i)); if (kv_size(decor_providers) > 0) { - validate_botline(wp); + validate_botline_win(wp); } linenr_T botline = MIN(wp->w_botline, wp->w_buffer->b_ml.ml_line_count); diff --git a/src/nvim/diff.c b/src/nvim/diff.c @@ -2535,7 +2535,7 @@ void diff_set_topline(win_T *fromwin, win_T *towin) } // When w_topline changes need to recompute w_botline and cursor position - invalidate_botline(towin); + invalidate_botline_win(towin); changed_line_abv_curs_win(towin); check_topfill(towin, false); diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c @@ -363,7 +363,7 @@ void screen_resize(int width, int height) maketitle(); changed_line_abv_curs(); - invalidate_botline(curwin); + invalidate_botline_win(curwin); // We only redraw when it's needed: // - While at the more prompt or executing an external command, don't diff --git a/src/nvim/eval.c b/src/nvim/eval.c @@ -5361,7 +5361,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret if (name[0] == 'w' && dollar_lnum) { // the "w_valid" flags are not reset when moving the cursor, but they - // do matter for update_topline() and validate_botline(). + // do matter for update_topline() and validate_botline_win(). check_cursor_moved(wp); pos.col = 0; @@ -5372,7 +5372,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret pos.lnum = wp->w_topline > 0 ? wp->w_topline : 1; return &pos; } else if (name[1] == '$') { // "w$": last visible line - validate_botline(wp); + validate_botline_win(wp); // In silent Ex mode botline is zero, return zero then. pos.lnum = wp->w_botline > 0 ? wp->w_botline - 1 : 0; return &pos; diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c @@ -328,7 +328,7 @@ static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) dict_T *const dict = tv_dict_alloc(); // make sure w_botline is valid - validate_botline(wp); + validate_botline_win(wp); tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr); tv_dict_add_nr(dict, S_LEN("winnr"), winnr); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c @@ -1279,7 +1279,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b curwin->w_cursor.lnum = line1; curwin->w_cursor.col = 0; changed_line_abv_curs(); - invalidate_botline(curwin); + invalidate_botline_win(curwin); // When using temp files: // 1. * Form temp file names diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c @@ -4652,7 +4652,7 @@ static int open_cmdwin(void) curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; curwin->w_cursor.col = ccline.cmdpos; changed_line_abv_curs(); - invalidate_botline(curwin); + invalidate_botline_win(curwin); ui_ext_cmdline_hide(false); redraw_later(curwin, UPD_SOME_VALID); diff --git a/src/nvim/move.c b/src/nvim/move.c @@ -368,7 +368,7 @@ void update_topline(win_T *wp) // for every small change. if (check_botline) { if (!(wp->w_valid & VALID_BOTLINE_AP)) { - validate_botline(wp); + validate_botline_win(wp); } assert(wp->w_buffer != 0); @@ -571,6 +571,9 @@ void set_topline(win_T *wp, linenr_T lnum) hasFolding(wp, lnum, &lnum, NULL); // Approximate the value of w_botline wp->w_botline += lnum - wp->w_topline; + if (wp->w_botline > wp->w_buffer->b_ml.ml_line_count + 1) { + wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1; + } wp->w_topline = lnum; wp->w_topline_was_set = true; if (lnum != prev_topline) { @@ -608,16 +611,18 @@ void changed_line_abv_curs_win(win_T *wp) |VALID_CHEIGHT|VALID_TOPLINE); } -// Make sure the value of wp->w_botline is valid. -void validate_botline(win_T *wp) +/// Make sure the value of wp->w_botline is valid. +void validate_botline_win(win_T *wp) + FUNC_ATTR_NONNULL_ALL { if (!(wp->w_valid & VALID_BOTLINE)) { comp_botline(wp); } } -// Mark wp->w_botline as invalid (because of some change in the buffer). -void invalidate_botline(win_T *wp) +/// Mark wp->w_botline as invalid (because of some change in the buffer). +void invalidate_botline_win(win_T *wp) + FUNC_ATTR_NONNULL_ALL { wp->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP); } @@ -1397,7 +1402,7 @@ bool scrolldown(win_T *wp, linenr_T line_count, int byfold) } } wp->w_botline--; // approximate w_botline - invalidate_botline(wp); + invalidate_botline_win(wp); } // Adjust for concealed lines above w_topline @@ -1960,7 +1965,7 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot) } } } else { - validate_botline(wp); + validate_botline_win(wp); } // The lines of the cursor line itself are always used. @@ -2276,7 +2281,7 @@ void cursor_correct(win_T *wp) int max_off = wp->w_view_height / 2; below_wanted = MIN(below_wanted, max_off); } - validate_botline(wp); + validate_botline_win(wp); if (wp->w_botline == wp->w_buffer->b_ml.ml_line_count + 1 && mouse_dragging == 0) { below_wanted = 0; @@ -2365,7 +2370,7 @@ static int get_scroll_overlap(Direction dir) lineoff_T loff; int min_height = curwin->w_view_height - 2; - validate_botline(curwin); + validate_botline_win(curwin); if ((dir == BACKWARD && curwin->w_topline == 1) || (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)) { return min_height + 2; // no overlap, still handle 'smoothscroll' @@ -2516,7 +2521,7 @@ int pagescroll(Direction dir, int count, bool half) if (!nochange) { // Place cursor at top or bottom of window. - validate_botline(curwin); + validate_botline_win(curwin); linenr_T lnum = (dir == FORWARD ? curwin->w_topline : curwin->w_botline - 1); // In silent Ex mode the value of w_botline - 1 may be 0, // but cursor lnum needs to be at least 1. diff --git a/src/nvim/normal.c b/src/nvim/normal.c @@ -2800,7 +2800,7 @@ static void nv_zet(cmdarg_T *cap) case '+': if (cap->count0 == 0) { // No count given: put cursor at the line below screen - validate_botline(curwin); // make sure w_botline is valid + validate_botline_win(curwin); // make sure w_botline is valid curwin->w_cursor.lnum = MIN(curwin->w_botline, curbuf->b_ml.ml_line_count); } FALLTHROUGH; @@ -3622,7 +3622,7 @@ static void nv_scroll(cmdarg_T *cap) setpcmark(); if (cap->cmdchar == 'L') { - validate_botline(curwin); // make sure curwin->w_botline is valid + validate_botline_win(curwin); // make sure curwin->w_botline is valid curwin->w_cursor.lnum = curwin->w_botline - 1; if (cap->count1 - 1 >= curwin->w_cursor.lnum) { curwin->w_cursor.lnum = 1; @@ -3645,7 +3645,7 @@ static void nv_scroll(cmdarg_T *cap) int used = 0; // Don't count filler lines above the window. used -= win_get_fill(curwin, curwin->w_topline) - curwin->w_topfill; - validate_botline(curwin); // make sure w_empty_rows is valid + validate_botline_win(curwin); // make sure w_empty_rows is valid int half = (curwin->w_view_height - curwin->w_empty_rows + 1) / 2; for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) { // Count half the number of filler lines to be "below this diff --git a/src/nvim/register.c b/src/nvim/register.c @@ -1841,7 +1841,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags) if (lnum == curwin->w_cursor.lnum) { // make sure curwin->w_virtcol is updated changed_cline_bef_curs(curwin); - invalidate_botline(curwin); + invalidate_botline_win(curwin); curwin->w_cursor.col += (colnr_T)(totlen - 1); } changed_bytes(lnum, col); diff --git a/src/nvim/window.c b/src/nvim/window.c @@ -6576,8 +6576,8 @@ void win_fix_scroll(bool resize) wp->w_valid &= ~VALID_CROW; } - invalidate_botline(wp); - validate_botline(wp); + invalidate_botline_win(wp); + validate_botline_win(wp); } wp->w_prev_height = wp->w_height; wp->w_prev_winrow = wp->w_winrow; @@ -6634,7 +6634,7 @@ static void win_fix_cursor(bool normal) } else { // Scroll instead when not in normal mode. wp->w_fraction = (nlnum == bot) ? FRACTION_MULT : 0; scroll_to_fraction(wp, wp->w_prev_height); - validate_botline(curwin); + validate_botline_win(curwin); } } } @@ -6746,7 +6746,7 @@ void scroll_to_fraction(win_T *wp, int prev_height) } redraw_later(wp, UPD_SOME_VALID); - invalidate_botline(wp); + invalidate_botline_win(wp); } void win_set_inner_size(win_T *wp, bool valid_cursor) @@ -6793,7 +6793,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor) wp->w_lines_valid = 0; if (valid_cursor) { changed_line_abv_curs_win(wp); - invalidate_botline(wp); + invalidate_botline_win(wp); if (wp == curwin && (*p_spk == 'c' || wp->w_floating)) { curs_columns(wp, true); // validate w_wrow }