0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

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.
This commit is contained in:
Bram Moolenaar
2022-10-02 21:29:55 +01:00
parent ff85d4a107
commit f6196f4244
18 changed files with 312 additions and 29 deletions

View File

@@ -35,6 +35,32 @@ typedef struct
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;
#ifdef FEAT_DIFF
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))
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;
if (!byfold)
line_count -= curwin->w_topline - first - 1;
curwin->w_botline -= curwin->w_topline - first;
curwin->w_topline = first;
}
else
{
--curwin->w_topline;
curwin->w_skipcol = 0;
#ifdef FEAT_DIFF
curwin->w_topfill = 0;
#endif
done += PLINES_NOFILL(curwin->w_topline);
#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;
}
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);
}
}
--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