diff options
Diffstat (limited to 'src/move.c')
-rw-r--r-- | src/move.c | 377 |
1 files changed, 29 insertions, 348 deletions
diff --git a/src/move.c b/src/move.c index 9ea24c8ed2..772b173bc8 100644 --- a/src/move.c +++ b/src/move.c @@ -2047,26 +2047,6 @@ check_topfill( } } } - -/* - * Use as many filler lines as possible for w_topline. Make sure w_topline - * is still visible. - */ - static void -max_topfill(void) -{ - int n; - - n = plines_nofill(curwin->w_topline); - if (n >= curwin->w_height) - curwin->w_topfill = 0; - else - { - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); - if (curwin->w_topfill + n > curwin->w_height) - curwin->w_topfill = curwin->w_height - n; - } -} #endif /* @@ -2269,38 +2249,6 @@ botline_forw(lineoff_T *lp) } } -#ifdef FEAT_DIFF -/* - * Switch from including filler lines below lp->lnum to including filler - * lines above loff.lnum + 1. This keeps pointing to the same line. - * When there are no filler lines nothing changes. - */ - static void -botline_topline(lineoff_T *lp) -{ - if (lp->fill > 0) - { - ++lp->lnum; - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; - } -} - -/* - * Switch from including filler lines above lp->lnum to including filler - * lines below loff.lnum - 1. This keeps pointing to the same line. - * When there are no filler lines nothing changes. - */ - static void -topline_botline(lineoff_T *lp) -{ - if (lp->fill > 0) - { - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; - --lp->lnum; - } -} -#endif - /* * Recompute topline to put the cursor at the top of the window. * Scroll at least "min_scroll" lines. @@ -3077,8 +3025,6 @@ cursor_correct(void) curwin->w_valid |= VALID_TOPLINE; } -static void get_scroll_overlap(lineoff_T *lp, int dir); - /* * Move screen "count" pages up ("dir" is BACKWARD) or down ("dir" is FORWARD) * and update the screen. @@ -3088,313 +3034,48 @@ static void get_scroll_overlap(lineoff_T *lp, int dir); int onepage(int dir, long count) { - long n; - int retval = OK; - lineoff_T loff; - linenr_T old_topline = curwin->w_topline; - long so = get_scrolloff_value(); - - if (curbuf->b_ml.ml_line_count == 1) // nothing to do - { - beep_flush(); - return FAIL; - } - - for ( ; count > 0; --count) - { - validate_botline(); - /* - * It's an error to move a page up when the first line is already on - * the screen. It's an error to move a page down when the last line - * is on the screen and the topline is 'scrolloff' lines from the - * last line. - */ - if (dir == FORWARD - ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - so) - && curwin->w_botline > curbuf->b_ml.ml_line_count) - : (curwin->w_topline == 1 -#ifdef FEAT_DIFF - && curwin->w_topfill == - diff_check_fill(curwin, curwin->w_topline) -#endif - )) - { - beep_flush(); - retval = FAIL; - break; - } - -#ifdef FEAT_DIFF - loff.fill = 0; -#endif - if (dir == FORWARD) - { - if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) - { - // Vi compatible scrolling - if (p_window <= 2) - ++curwin->w_topline; - else - curwin->w_topline += p_window - 2; - if (curwin->w_topline > curbuf->b_ml.ml_line_count) - curwin->w_topline = curbuf->b_ml.ml_line_count; - curwin->w_cursor.lnum = curwin->w_topline; - } - else if (curwin->w_botline > curbuf->b_ml.ml_line_count) - { - // at end of file - curwin->w_topline = curbuf->b_ml.ml_line_count; -#ifdef FEAT_DIFF - curwin->w_topfill = 0; -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW); - } - else - { - // For the overlap, start with the line just below the window - // and go upwards. - loff.lnum = curwin->w_botline; -#ifdef FEAT_DIFF - loff.fill = diff_check_fill(curwin, loff.lnum) - - curwin->w_filler_rows; -#endif - get_scroll_overlap(&loff, -1); - curwin->w_topline = loff.lnum; -#ifdef FEAT_DIFF - curwin->w_topfill = loff.fill; - check_topfill(curwin, FALSE); -#endif - curwin->w_cursor.lnum = curwin->w_topline; - curwin->w_valid &= ~(VALID_WCOL|VALID_CHEIGHT|VALID_WROW| - VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); - } - } - else // dir == BACKWARDS - { -#ifdef FEAT_DIFF - if (curwin->w_topline == 1) - { - // Include max number of filler lines - max_topfill(); - continue; - } -#endif - if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) - { - // Vi compatible scrolling (sort of) - if (p_window <= 2) - --curwin->w_topline; - else - curwin->w_topline -= p_window - 2; - if (curwin->w_topline < 1) - curwin->w_topline = 1; - curwin->w_cursor.lnum = curwin->w_topline + p_window - 1; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - continue; - } - - // Find the line at the top of the window that is going to be the - // line at the bottom of the window. Make sure this results in - // the same line as before doing CTRL-F. - loff.lnum = curwin->w_topline - 1; -#ifdef FEAT_DIFF - loff.fill = diff_check_fill(curwin, loff.lnum + 1) - - curwin->w_topfill; -#endif - get_scroll_overlap(&loff, 1); - - if (loff.lnum >= curbuf->b_ml.ml_line_count) - { - loff.lnum = curbuf->b_ml.ml_line_count; #ifdef FEAT_DIFF - loff.fill = 0; - } - else - { - botline_topline(&loff); + int prev_topfill = curwin->w_topfill; #endif - } - curwin->w_cursor.lnum = loff.lnum; + linenr_T prev_topline = curwin->w_topline; + colnr_T prev_skipcol = curwin->w_skipcol; - // Find the line just above the new topline to get the right line - // at the bottom of the window. - n = 0; - while (n <= curwin->w_height && loff.lnum >= 1) - { - topline_back(&loff); - if (loff.height == MAXCOL) - n = MAXCOL; - else - n += loff.height; - } - if (loff.lnum < 1) // at begin of file - { - curwin->w_topline = 1; -#ifdef FEAT_DIFF - max_topfill(); -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE); - } - else - { - // Go two lines forward again. -#ifdef FEAT_DIFF - topline_botline(&loff); -#endif - botline_forw(&loff); - botline_forw(&loff); -#ifdef FEAT_DIFF - botline_topline(&loff); -#endif -#ifdef FEAT_FOLDING - // We're at the wrong end of a fold now. - (void)hasFolding(loff.lnum, &loff.lnum, NULL); -#endif + // Scroll 'window' or current window height lines. + count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ? + p_window : curwin->w_height) - 2; - // Always scroll at least one line. Avoid getting stuck on - // very long lines. - if (loff.lnum >= curwin->w_topline -#ifdef FEAT_DIFF - && (loff.lnum > curwin->w_topline - || loff.fill >= curwin->w_topfill) -#endif - ) - { -#ifdef FEAT_DIFF - // First try using the maximum number of filler lines. If - // that's not enough, backup one line. - loff.fill = curwin->w_topfill; - if (curwin->w_topfill < diff_check_fill(curwin, - curwin->w_topline)) - max_topfill(); - if (curwin->w_topfill == loff.fill) -#endif - { - --curwin->w_topline; -#ifdef FEAT_DIFF - curwin->w_topfill = 0; -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW); - } - comp_botline(curwin); - curwin->w_cursor.lnum = curwin->w_botline - 1; - curwin->w_valid &= - ~(VALID_WCOL|VALID_CHEIGHT|VALID_WROW|VALID_CROW); - } - else - { - curwin->w_topline = loff.lnum; + if (curwin->w_p_sms) + scroll_redraw(dir == FORWARD, count); + else + { + // Scroll at least one full line without 'smoothscroll'. #ifdef FEAT_DIFF - curwin->w_topfill = loff.fill; - check_topfill(curwin, FALSE); -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE); - } - } - } - } -#ifdef FEAT_FOLDING - foldAdjustCursor(); + count -= plines_nofill(curwin->w_topline); +#else + count -= plines(curwin->w_topline); #endif - cursor_correct(); - check_cursor_col(); - if (retval == OK) - beginline(BL_SOL | BL_FIX); - curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL); + scroll_redraw(dir == FORWARD, 1); - if (retval == OK && dir == FORWARD) - { - // Avoid the screen jumping up and down when 'scrolloff' is non-zero. - // But make sure we scroll at least one line (happens with mix of long - // wrapping lines and non-wrapping line). - if (check_top_offset()) - { - scroll_cursor_top(1, FALSE); - if (curwin->w_topline <= old_topline - && old_topline < curbuf->b_ml.ml_line_count) - { - curwin->w_topline = old_topline + 1; -#ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); -#endif - } - } -#ifdef FEAT_FOLDING - else if (curwin->w_botline > curbuf->b_ml.ml_line_count) - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); -#endif + // Temporarily set 'smoothscroll' so that scrolling count lines + // does not skip over parts of the buffer with wrapped lines. + curwin->w_p_sms = TRUE; + if (count > 0) + scroll_redraw(dir == FORWARD, count); + curwin->w_p_sms = FALSE; } - redraw_later(UPD_VALID); - return retval; -} - -/* - * 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 void -get_scroll_overlap(lineoff_T *lp, int dir) -{ - int h1, h2, h3, h4; - int min_height = curwin->w_height - 2; - lineoff_T loff0, loff1, loff2; - + int nochange = curwin->w_topline == prev_topline #ifdef FEAT_DIFF - if (lp->fill > 0) - lp->height = 1; - else - lp->height = plines_nofill(lp->lnum); -#else - lp->height = plines(lp->lnum); + && curwin->w_topfill == prev_topfill #endif - h1 = lp->height; - if (h1 > min_height) - return; // no overlap + && curwin->w_skipcol == prev_skipcol; - loff0 = *lp; - if (dir > 0) - botline_forw(lp); - else - topline_back(lp); - h2 = lp->height; - if (h2 == MAXCOL || h2 + h1 > min_height) - { - *lp = loff0; // no overlap - return; - } - - loff1 = *lp; - if (dir > 0) - botline_forw(lp); - else - topline_back(lp); - h3 = lp->height; - if (h3 == MAXCOL || h3 + h2 > min_height) - { - *lp = loff0; // no overlap - return; - } + if (nochange) + beep_flush(); + else if (!curwin->w_p_sms || curwin->w_skipcol == prev_skipcol) + beginline(BL_SOL | BL_FIX); - loff2 = *lp; - if (dir > 0) - botline_forw(lp); - else - topline_back(lp); - h4 = lp->height; - if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height) - *lp = loff1; // 1 line overlap - else - *lp = loff2; // 2 lines overlap + return nochange; } /* |