aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/normal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r--src/nvim/normal.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 88b8ccbb85..3931ae3ee9 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -2092,17 +2092,23 @@ static void display_showcmd(void)
grid_line_flush();
}
+int get_vtopline(win_T *wp)
+{
+ return plines_m_win_fill(wp, 1, wp->w_topline) - wp->w_topfill;
+}
+
/// When "check" is false, prepare for commands that scroll the window.
/// When "check" is true, take care of scroll-binding after the window has
/// scrolled. Called from normal_cmd() and edit().
void do_check_scrollbind(bool check)
{
static win_T *old_curwin = NULL;
- static linenr_T old_topline = 0;
- static int old_topfill = 0;
+ static linenr_T old_vtopline = 0;
static buf_T *old_buf = NULL;
static colnr_T old_leftcol = 0;
+ int vtopline = get_vtopline(curwin);
+
if (check && curwin->w_p_scb) {
// If a ":syncbind" command was just used, don't scroll, only reset
// the values.
@@ -2115,10 +2121,9 @@ void do_check_scrollbind(bool check)
if ((curwin->w_buffer == old_buf
|| curwin->w_p_diff
)
- && (curwin->w_topline != old_topline
- || curwin->w_topfill != old_topfill
+ && (vtopline != old_vtopline
|| curwin->w_leftcol != old_leftcol)) {
- check_scrollbind(curwin->w_topline - old_topline, curwin->w_leftcol - old_leftcol);
+ check_scrollbind(vtopline - old_vtopline, curwin->w_leftcol - old_leftcol);
}
} else if (vim_strchr(p_sbo, 'j')) { // jump flag set in 'scrollopt'
// When switching between windows, make sure that the relative
@@ -2129,14 +2134,13 @@ void do_check_scrollbind(bool check)
// resync is performed, some of the other 'scrollbind' windows may
// need to jump so that the current window's relative position is
// visible on-screen.
- check_scrollbind(curwin->w_topline - (linenr_T)curwin->w_scbind_pos, 0);
+ check_scrollbind(vtopline - curwin->w_scbind_pos, 0);
}
- curwin->w_scbind_pos = curwin->w_topline;
+ curwin->w_scbind_pos = vtopline;
}
old_curwin = curwin;
- old_topline = curwin->w_topline;
- old_topfill = curwin->w_topfill;
+ old_vtopline = vtopline;
old_buf = curwin->w_buffer;
old_leftcol = curwin->w_leftcol;
}
@@ -2144,20 +2148,18 @@ void do_check_scrollbind(bool check)
/// Synchronize any windows that have "scrollbind" set, based on the
/// number of rows by which the current window has changed
/// (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>)
-void check_scrollbind(linenr_T topline_diff, int leftcol_diff)
+void check_scrollbind(linenr_T vtopline_diff, int leftcol_diff)
{
win_T *old_curwin = curwin;
buf_T *old_curbuf = curbuf;
int old_VIsual_select = VIsual_select;
int old_VIsual_active = VIsual_active;
colnr_T tgt_leftcol = curwin->w_leftcol;
- linenr_T topline;
- linenr_T y;
// check 'scrollopt' string for vertical and horizontal scroll options
- bool want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0);
- want_ver |= old_curwin->w_p_diff;
- bool want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0));
+ bool want_ver = old_curwin->w_p_diff
+ || (vim_strchr(p_sbo, 'v') && vtopline_diff != 0);
+ bool want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || vtopline_diff != 0));
// loop through the scrollbound windows and scroll accordingly
VIsual_select = VIsual_active = 0;
@@ -2174,16 +2176,19 @@ void check_scrollbind(linenr_T topline_diff, int leftcol_diff)
if (old_curwin->w_p_diff && curwin->w_p_diff) {
diff_set_topline(old_curwin, curwin);
} else {
- curwin->w_scbind_pos += topline_diff;
- topline = (linenr_T)curwin->w_scbind_pos;
- if (topline > curbuf->b_ml.ml_line_count) {
- topline = curbuf->b_ml.ml_line_count;
- }
- if (topline < 1) {
- topline = 1;
- }
+ curwin->w_scbind_pos += vtopline_diff;
+ int curr_vtopline = get_vtopline(curwin);
+
+ // Perf: reuse curr_vtopline to reduce the time in plines_m_win_fill().
+ // Equivalent to:
+ // int max_vtopline = plines_m_win_fill(curwin, 1, curbuf->b_ml.ml_line_count);
+ int max_vtopline = curr_vtopline + curwin->w_topfill
+ + plines_m_win_fill(curwin, curwin->w_topline + 1,
+ curbuf->b_ml.ml_line_count);
+
+ int new_vtopline = MAX(MIN((linenr_T)curwin->w_scbind_pos, max_vtopline), 1);
- y = topline - curwin->w_topline;
+ int y = new_vtopline - curr_vtopline;
if (y > 0) {
scrollup(curwin, y, false);
} else {