summaryrefslogtreecommitdiffstats
path: root/src/move.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/move.c')
-rw-r--r--src/move.c275
1 files changed, 86 insertions, 189 deletions
diff --git a/src/move.c b/src/move.c
index 772b173bc8..25f419e5aa 100644
--- a/src/move.c
+++ b/src/move.c
@@ -3026,13 +3026,74 @@ cursor_correct(void)
}
/*
+ * Decide how much overlap to use for page-up or page-down scrolling.
+ * This is symmetric, so that doing both keeps the same lines displayed.
+ * Three lines are examined:
+ *
+ * before CTRL-F after CTRL-F / before CTRL-B
+ * etc. l1
+ * l1 last but one line ------------
+ * l2 last text line l2 top text line
+ * ------------- l3 second text line
+ * l3 etc.
+ */
+static int get_scroll_overlap(int dir)
+{
+ lineoff_T loff;
+ int min_height = curwin->w_height - 2;
+
+ validate_botline();
+ if (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)
+ return min_height + 2; // no overlap, still handle 'smoothscroll'
+
+ loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1;
+#ifdef FEAT_DIFF
+ loff.fill = diff_check_fill(curwin, loff.lnum + dir == BACKWARD)
+ - (dir == FORWARD ? curwin->w_filler_rows : curwin->w_topfill);
+ loff.height = loff.fill > 0 ? 1 : plines_nofill(loff.lnum);
+#else
+ loff.height = plines(loff.lnum);
+#endif
+
+ int h1 = loff.height;
+ if (h1 > min_height)
+ return min_height + 2; // no overlap
+ if (dir == FORWARD)
+ topline_back(&loff);
+ else
+ botline_forw(&loff);
+
+ int h2 = loff.height;
+ if (h2 == MAXCOL || h2 + h1 > min_height)
+ return min_height + 2; // no overlap
+ if (dir == FORWARD)
+ topline_back(&loff);
+ else
+ botline_forw(&loff);
+
+ int h3 = loff.height;
+ if (h3 == MAXCOL || h3 + h2 > min_height)
+ return min_height + 2; // no overlap
+ if (dir == FORWARD)
+ topline_back(&loff);
+ else
+ botline_forw(&loff);
+
+ int h4 = loff.height;
+ if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height)
+ return min_height + 1; // 1 line overlap
+ else
+ return min_height; // 2 lines overlap
+}
+
+/*
* Move screen "count" pages up ("dir" is BACKWARD) or down ("dir" is FORWARD)
* and update the screen.
*
* Return FAIL for failure, OK otherwise.
*/
int
-onepage(int dir, long count)
+pagescroll(int dir, long count, int half)
{
#ifdef FEAT_DIFF
int prev_topfill = curwin->w_topfill;
@@ -3040,9 +3101,17 @@ onepage(int dir, long count)
linenr_T prev_topline = curwin->w_topline;
colnr_T prev_skipcol = curwin->w_skipcol;
- // Scroll 'window' or current window height lines.
- count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
- p_window : curwin->w_height) - 2;
+ if (half)
+ {
+ // Scroll [count], 'scroll' or current window height lines.
+ if (count)
+ curwin->w_p_scr = MIN(curwin->w_height, count);
+ count = MIN(curwin->w_height, curwin->w_p_scr);
+ }
+ else
+ // Scroll 'window' or current window height lines.
+ count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ?
+ p_window - 2 : get_scroll_overlap(dir));
if (curwin->w_p_sms)
scroll_redraw(dir == FORWARD, count);
@@ -3063,6 +3132,10 @@ onepage(int dir, long count)
scroll_redraw(dir == FORWARD, count);
curwin->w_p_sms = FALSE;
}
+#ifdef FEAT_FOLDING
+ // Move cursor to first line of closed fold.
+ foldAdjustCursor();
+#endif
int nochange = curwin->w_topline == prev_topline
#ifdef FEAT_DIFF
@@ -3070,198 +3143,22 @@ onepage(int dir, long count)
#endif
&& curwin->w_skipcol == prev_skipcol;
+ // Error if the viewport did not change and the cursor is already
+ // at the boundary.
if (nochange)
- beep_flush();
+ {
+ int prev_cursor = curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum += (count + 1) * (dir == FORWARD ? 1 : -1);
+ check_cursor();
+ if (curwin->w_cursor.lnum == prev_cursor)
+ beep_flush();
+ }
else if (!curwin->w_p_sms || curwin->w_skipcol == prev_skipcol)
beginline(BL_SOL | BL_FIX);
return nochange;
}
-/*
- * Scroll 'scroll' lines up or down.
- */
- void
-halfpage(int flag, linenr_T Prenum)
-{
- long scrolled = 0;
- int i;
- int n;
- int room;
-
- if (Prenum)
- curwin->w_p_scr = (Prenum > curwin->w_height) ?
- curwin->w_height : Prenum;
- n = (curwin->w_p_scr <= curwin->w_height) ?
- curwin->w_p_scr : curwin->w_height;
-
- update_topline();
- validate_botline();
- room = curwin->w_empty_rows;
-#ifdef FEAT_DIFF
- room += curwin->w_filler_rows;
-#endif
- if (flag)
- {
- /*
- * scroll the text up
- */
- while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count)
- {
-#ifdef FEAT_DIFF
- if (curwin->w_topfill > 0)
- {
- i = 1;
- --n;
- --curwin->w_topfill;
- }
- else
-#endif
- {
- i = PLINES_NOFILL(curwin->w_topline);
- n -= i;
- if (n < 0 && scrolled > 0)
- break;
-#ifdef FEAT_FOLDING
- (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
-#endif
- ++curwin->w_topline;
-#ifdef FEAT_DIFF
- curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
-#endif
-
- if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
- {
- ++curwin->w_cursor.lnum;
- curwin->w_valid &=
- ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
- }
- }
- curwin->w_valid &= ~(VALID_CROW|VALID_WROW);
- scrolled += i;
-
- /*
- * Correct w_botline for changed w_topline.
- * Won't work when there are filler lines.
- */
-#ifdef FEAT_DIFF
- if (curwin->w_p_diff)
- curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
- else
-#endif
- {
- room += i;
- do
- {
- i = plines(curwin->w_botline);
- if (i > room)
- break;
-#ifdef FEAT_FOLDING
- (void)hasFolding(curwin->w_botline, NULL,
- &curwin->w_botline);
-#endif
- ++curwin->w_botline;
- room -= i;
- } while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
- }
- }
-
- /*
- * When hit bottom of the file: move cursor down.
- */
- if (n > 0)
- {
-# ifdef FEAT_FOLDING
- if (hasAnyFolding(curwin))
- {
- while (--n >= 0
- && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
- {
- (void)hasFolding(curwin->w_cursor.lnum, NULL,
- &curwin->w_cursor.lnum);
- ++curwin->w_cursor.lnum;
- }
- }
- else
-# endif
- curwin->w_cursor.lnum += n;
- check_cursor_lnum();
- }
- }
- else
- {
- /*
- * scroll the text down
- */
- while (n > 0 && curwin->w_topline > 1)
- {
-#ifdef FEAT_DIFF
- if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline))
- {
- i = 1;
- --n;
- ++curwin->w_topfill;
- }
- else
-#endif
- {
- i = PLINES_NOFILL(curwin->w_topline - 1);
- n -= i;
- if (n < 0 && scrolled > 0)
- break;
- --curwin->w_topline;
-#ifdef FEAT_FOLDING
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
-#endif
-#ifdef FEAT_DIFF
- curwin->w_topfill = 0;
-#endif
- }
- curwin->w_valid &= ~(VALID_CROW|VALID_WROW|
- VALID_BOTLINE|VALID_BOTLINE_AP);
- scrolled += i;
- if (curwin->w_cursor.lnum > 1)
- {
- --curwin->w_cursor.lnum;
- curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL);
- }
- }
-
- /*
- * When hit top of the file: move cursor up.
- */
- if (n > 0)
- {
- if (curwin->w_cursor.lnum <= (linenr_T)n)
- curwin->w_cursor.lnum = 1;
- else
-# ifdef FEAT_FOLDING
- if (hasAnyFolding(curwin))
- {
- while (--n >= 0 && curwin->w_cursor.lnum > 1)
- {
- --curwin->w_cursor.lnum;
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
- }
- }
- else
-# endif
- curwin->w_cursor.lnum -= n;
- }
- }
-# ifdef FEAT_FOLDING
- // Move cursor to first line of closed fold.
- foldAdjustCursor();
-# endif
-#ifdef FEAT_DIFF
- check_topfill(curwin, !flag);
-#endif
- cursor_correct();
- beginline(BL_SOL | BL_FIX);
- redraw_later(UPD_VALID);
-}
-
void
do_check_cursorbind(void)
{