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:
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
}