aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r--src/nvim/window.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index f5533db385..187115a4d6 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1030,15 +1030,13 @@ void ui_ext_win_position(win_T *wp, bool validate)
void ui_ext_win_viewport(win_T *wp)
{
if ((wp == curwin || ui_has(kUIMultigrid)) && wp->w_viewport_invalid) {
- int botline = wp->w_botline;
- int line_count = wp->w_buffer->b_ml.ml_line_count;
- if (botline == line_count + 1 && wp->w_empty_rows == 0) {
- // TODO(bfredl): The might be more cases to consider, like how does this
- // interact with incomplete final line? Diff filler lines?
- botline = wp->w_buffer->b_ml.ml_line_count;
- }
+ const linenr_T line_count = wp->w_buffer->b_ml.ml_line_count;
+ // Avoid ml_get errors when producing "scroll_delta".
+ const linenr_T cur_topline = MIN(wp->w_topline, line_count);
+ const linenr_T cur_botline = MIN(wp->w_botline, line_count);
int64_t delta = 0;
linenr_T last_topline = wp->w_viewport_last_topline;
+ linenr_T last_botline = wp->w_viewport_last_botline;
int last_topfill = wp->w_viewport_last_topfill;
int64_t last_skipcol = wp->w_viewport_last_skipcol;
if (last_topline > line_count) {
@@ -1047,19 +1045,39 @@ void ui_ext_win_viewport(win_T *wp)
last_topfill = 0;
last_skipcol = MAXCOL;
}
- if (wp->w_topline < last_topline
- || (wp->w_topline == last_topline && wp->w_skipcol < last_skipcol)) {
- delta -= win_get_text_height(wp, wp->w_topline, last_topline, wp->w_skipcol, last_skipcol);
- } else if ((wp->w_topline > last_topline && wp->w_topline <= line_count)
- || (wp->w_topline == last_topline && wp->w_skipcol > last_skipcol)) {
- delta += win_get_text_height(wp, last_topline, wp->w_topline, last_skipcol, wp->w_skipcol);
+ last_botline = MIN(last_botline, line_count);
+ if (cur_topline < last_topline
+ || (cur_topline == last_topline && wp->w_skipcol < last_skipcol)) {
+ if (last_topline > 0 && cur_botline < last_topline) {
+ // Scrolling too many lines: only give an approximate "scroll_delta".
+ delta -= win_get_text_height(wp, cur_topline, cur_botline, wp->w_skipcol, 0);
+ delta -= last_topline - cur_botline;
+ } else {
+ delta -= win_get_text_height(wp, cur_topline, last_topline, wp->w_skipcol, last_skipcol);
+ }
+ } else if (cur_topline > last_topline
+ || (cur_topline == last_topline && wp->w_skipcol > last_skipcol)) {
+ if (last_botline > 0 && cur_topline > last_botline) {
+ // Scrolling too many lines: only give an approximate "scroll_delta".
+ delta += win_get_text_height(wp, last_topline, last_botline, last_skipcol, 0);
+ delta += cur_topline - last_botline;
+ } else {
+ delta += win_get_text_height(wp, last_topline, cur_topline, last_skipcol, wp->w_skipcol);
+ }
}
delta += last_topfill;
delta -= wp->w_topfill;
- ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, botline,
+ linenr_T ev_botline = wp->w_botline;
+ if (ev_botline == line_count + 1 && wp->w_empty_rows == 0) {
+ // TODO(bfredl): The might be more cases to consider, like how does this
+ // interact with incomplete final line? Diff filler lines?
+ ev_botline = line_count;
+ }
+ ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, ev_botline,
wp->w_cursor.lnum - 1, wp->w_cursor.col, line_count, delta);
wp->w_viewport_invalid = false;
wp->w_viewport_last_topline = wp->w_topline;
+ wp->w_viewport_last_botline = wp->w_botline;
wp->w_viewport_last_topfill = wp->w_topfill;
wp->w_viewport_last_skipcol = wp->w_skipcol;
}