Mercurial > vim
diff src/move.c @ 30610:6c6ac189a05f v9.0.0640
patch 9.0.0640: cannot scroll by screen line if a line wraps
Commit: https://github.com/vim/vim/commit/f6196f424474e2a9c160f2a995fc2691f82b58f9
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Oct 2 21:29:55 2022 +0100
patch 9.0.0640: cannot scroll by screen line if a line wraps
Problem: Cannot scroll by screen line if a line wraps.
Solution: Add the 'smoothscroll' option. Only works for CTRL-E and CTRL-Y
so far.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 02 Oct 2022 22:30:15 +0200 |
parents | 729e2305f4b2 |
children | 70d6345a2976 |
line wrap: on
line diff
--- a/src/move.c +++ b/src/move.c @@ -36,6 +36,32 @@ static void topline_back(lineoff_T *lp); static void botline_forw(lineoff_T *lp); /* + * Reduce "n" for the screen lines skipped with "wp->w_skipcol". + */ + static int +adjust_plines_for_skipcol(win_T *wp, int n) +{ + if (wp->w_skipcol == 0) + return n; + + int off = 0; + int width = wp->w_width - win_col_off(wp); + if (wp->w_skipcol >= width) + { + ++off; + int skip = wp->w_skipcol - width; + width -= win_col_off2(wp); + while (skip >= width) + { + ++off; + skip -= width; + } + } + wp->w_valid &= ~VALID_WROW; + return n - off; +} + +/* * Compute wp->w_botline for the current wp->w_topline. Can be called after * wp->w_topline changed. */ @@ -78,12 +104,16 @@ comp_botline(win_T *wp) } else #endif + { #ifdef FEAT_DIFF if (lnum == wp->w_topline) n = plines_win_nofill(wp, lnum, TRUE) + wp->w_topfill; else #endif n = plines_win(wp, lnum, TRUE); + if (lnum == wp->w_topline) + n = adjust_plines_for_skipcol(wp, n); + } if ( #ifdef FEAT_FOLDING lnum <= wp->w_cursor.lnum && last >= wp->w_cursor.lnum @@ -778,13 +808,18 @@ curs_rows(win_T *wp) } else #endif + { + int n; #ifdef FEAT_DIFF if (lnum == wp->w_topline) - wp->w_cline_row += plines_win_nofill(wp, lnum++, TRUE) - + wp->w_topfill; + n = plines_win_nofill(wp, lnum, TRUE) + wp->w_topfill; else #endif - wp->w_cline_row += plines_win(wp, lnum++, TRUE); + n = plines_win(wp, lnum, TRUE); + if (lnum++ == wp->w_topline) + n = adjust_plines_for_skipcol(wp, n); + wp->w_cline_row += n; + } } } @@ -1237,7 +1272,7 @@ curs_columns( else if (extra < 0) win_del_lines(curwin, 0, -extra, FALSE, FALSE, 0); } - else + else if (!curwin->w_p_sms) curwin->w_skipcol = 0; if (prev_skipcol != curwin->w_skipcol) redraw_later(UPD_NOT_VALID); @@ -1422,6 +1457,14 @@ scrolldown( long done = 0; // total # of physical lines done int wrow; int moved = FALSE; + int width1 = 0; + int width2 = 0; + + if (curwin->w_p_wrap && curwin->w_p_sms) + { + width1 = curwin->w_width - curwin_col_off(); + width2 = width1 - curwin_col_off2(); + } #ifdef FEAT_FOLDING linenr_T first; @@ -1442,25 +1485,57 @@ scrolldown( else #endif { - if (curwin->w_topline == 1) + if (curwin->w_topline == 1 && curwin->w_skipcol < width1) break; - --curwin->w_topline; + if (curwin->w_p_wrap && curwin->w_p_sms + && curwin->w_skipcol >= width1) + { + if (curwin->w_skipcol >= width1 + width2) + curwin->w_skipcol -= width2; + else + curwin->w_skipcol -= width1; + redraw_later(UPD_NOT_VALID); + ++done; + } + else + { + --curwin->w_topline; + curwin->w_skipcol = 0; #ifdef FEAT_DIFF - curwin->w_topfill = 0; + curwin->w_topfill = 0; #endif #ifdef FEAT_FOLDING - // A sequence of folded lines only counts for one logical line - if (hasFolding(curwin->w_topline, &first, NULL)) - { - ++done; - if (!byfold) - line_count -= curwin->w_topline - first - 1; - curwin->w_botline -= curwin->w_topline - first; - curwin->w_topline = first; + // A sequence of folded lines only counts for one logical line + if (hasFolding(curwin->w_topline, &first, NULL)) + { + ++done; + if (!byfold) + line_count -= curwin->w_topline - first - 1; + curwin->w_botline -= curwin->w_topline - first; + curwin->w_topline = first; + } + else +#endif + if (curwin->w_p_wrap && curwin->w_p_sms) + { + int size = win_linetabsize(curwin, curwin->w_topline, + ml_get(curwin->w_topline), (colnr_T)MAXCOL); + if (size > width1) + { + curwin->w_skipcol = width1; + size -= width1; + redraw_later(UPD_NOT_VALID); + } + while (size > width2) + { + curwin->w_skipcol += width2; + size -= width2; + } + ++done; + } + else + done += PLINES_NOFILL(curwin->w_topline); } - else -#endif - done += PLINES_NOFILL(curwin->w_topline); } --curwin->w_botline; // approximate w_botline invalidate_botline(); @@ -1565,6 +1640,41 @@ scrollup( } else #endif + if (curwin->w_p_wrap && curwin->w_p_sms) + { + int off1 = curwin_col_off(); + int off2 = off1 + curwin_col_off2(); + int add; + int size = win_linetabsize(curwin, curwin->w_topline, + ml_get(curwin->w_topline), (colnr_T)MAXCOL); + linenr_T prev_topline = curwin->w_topline; + + // 'smoothscroll': increase "w_skipcol" until it goes over the end of + // the line, then advance to the next line. + for (int todo = line_count; todo > 0; --todo) + { + add = curwin->w_width - (curwin->w_skipcol > 0 ? off2 : off1); + curwin->w_skipcol += add; + if (curwin->w_skipcol >= size) + { + if (curwin->w_topline == curbuf->b_ml.ml_line_count) + { + curwin->w_skipcol -= add; + break; + } + ++curwin->w_topline; + ++curwin->w_botline; // approximate w_botline + curwin->w_skipcol = 0; + if (todo > 1) + size = win_linetabsize(curwin, curwin->w_topline, + ml_get(curwin->w_topline), (colnr_T)MAXCOL); + } + } + if (curwin->w_topline == prev_topline) + // need to redraw even though w_topline didn't change + redraw_later(UPD_NOT_VALID); + } + else { curwin->w_topline += line_count; curwin->w_botline += line_count; // approximate w_botline