mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.1.1108: 'smoothscroll' gets stuck with 'listchars' "eol"
Problem: 'smoothscroll' gets stuck with 'listchars' "eol". Solution: Count size of 'listchars' "eol" in line size when scrolling. (zeertzjq) related: neovim/neovim#32405 closes: #16627 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
c0b7ca406b
commit
2c47ab8fcd
@@ -572,8 +572,7 @@ changed_common(
|
|||||||
&& (last < wp->w_topline
|
&& (last < wp->w_topline
|
||||||
|| (wp->w_topline >= lnum
|
|| (wp->w_topline >= lnum
|
||||||
&& wp->w_topline < lnume
|
&& wp->w_topline < lnume
|
||||||
&& win_linetabsize(wp, wp->w_topline,
|
&& linetabsize_eol(wp, wp->w_topline)
|
||||||
ml_get(wp->w_topline), (colnr_T)MAXCOL)
|
|
||||||
<= wp->w_skipcol + sms_marker_overlap(wp, -1))))
|
<= wp->w_skipcol + sms_marker_overlap(wp, -1))))
|
||||||
wp->w_skipcol = 0;
|
wp->w_skipcol = 0;
|
||||||
|
|
||||||
|
@@ -821,6 +821,7 @@ linetabsize_col(int startcol, char_u *s)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Like linetabsize_str(), but for a given window instead of the current one.
|
* Like linetabsize_str(), but for a given window instead of the current one.
|
||||||
|
* Doesn't count the size of 'listchars' "eol".
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
|
win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
|
||||||
@@ -836,14 +837,25 @@ win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len)
|
|||||||
/*
|
/*
|
||||||
* Return the number of cells line "lnum" of window "wp" will take on the
|
* Return the number of cells line "lnum" of window "wp" will take on the
|
||||||
* screen, taking into account the size of a tab and text properties.
|
* screen, taking into account the size of a tab and text properties.
|
||||||
|
* Doesn't count the size of 'listchars' "eol".
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
linetabsize(win_T *wp, linenr_T lnum)
|
linetabsize(win_T *wp, linenr_T lnum)
|
||||||
{
|
{
|
||||||
return win_linetabsize(wp, lnum,
|
return win_linetabsize(wp, lnum,
|
||||||
ml_get_buf(wp->w_buffer, lnum, FALSE), (colnr_T)MAXCOL);
|
ml_get_buf(wp->w_buffer, lnum, FALSE), (colnr_T)MAXCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like linetabsize(), but counts the size of 'listchars' "eol".
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
linetabsize_eol(win_T *wp, linenr_T lnum)
|
||||||
|
{
|
||||||
|
return linetabsize(wp, lnum)
|
||||||
|
+ ((wp->w_p_list && wp->w_lcs_chars.eol != NUL) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like linetabsize(), but excludes 'above'/'after'/'right'/'below' aligned
|
* Like linetabsize(), but excludes 'above'/'after'/'right'/'below' aligned
|
||||||
* virtual text, while keeping inline virtual text.
|
* virtual text, while keeping inline virtual text.
|
||||||
|
@@ -168,7 +168,7 @@ coladvance2(
|
|||||||
&& wcol >= (colnr_T)width
|
&& wcol >= (colnr_T)width
|
||||||
&& width > 0)
|
&& width > 0)
|
||||||
{
|
{
|
||||||
csize = linetabsize(curwin, pos->lnum);
|
csize = linetabsize_eol(curwin, pos->lnum);
|
||||||
if (csize > 0)
|
if (csize > 0)
|
||||||
csize--;
|
csize--;
|
||||||
|
|
||||||
|
43
src/move.c
43
src/move.c
@@ -1621,7 +1621,7 @@ f_virtcol2col(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
*/
|
*/
|
||||||
static void cursor_correct_sms(void)
|
static void cursor_correct_sms(void)
|
||||||
{
|
{
|
||||||
if (!curwin->w_p_sms ||!curwin->w_p_wrap
|
if (!curwin->w_p_sms || !curwin->w_p_wrap
|
||||||
|| curwin->w_cursor.lnum != curwin->w_topline)
|
|| curwin->w_cursor.lnum != curwin->w_topline)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1631,8 +1631,7 @@ static void cursor_correct_sms(void)
|
|||||||
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||||
int space_cols = (curwin->w_height - 1) * width2;
|
int space_cols = (curwin->w_height - 1) * width2;
|
||||||
int overlap, top, bot;
|
int overlap, top, bot;
|
||||||
int size = so == 0 ? 0 : win_linetabsize(curwin, curwin->w_topline,
|
int size = so == 0 ? 0 : linetabsize_eol(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
|
|
||||||
if (curwin->w_topline == 1 && curwin->w_skipcol == 0)
|
if (curwin->w_topline == 1 && curwin->w_skipcol == 0)
|
||||||
so_cols = 0; // Ignore 'scrolloff' at top of buffer.
|
so_cols = 0; // Ignore 'scrolloff' at top of buffer.
|
||||||
@@ -1645,10 +1644,10 @@ static void cursor_correct_sms(void)
|
|||||||
if (so_cols >= width1 && so_cols > size)
|
if (so_cols >= width1 && so_cols > size)
|
||||||
so_cols -= width1;
|
so_cols -= width1;
|
||||||
|
|
||||||
// If there is no marker or we have non-zero scrolloff, just ignore it.
|
overlap = curwin->w_skipcol == 0 ? 0
|
||||||
overlap = (curwin->w_skipcol == 0 || so_cols != 0) ? 0
|
: sms_marker_overlap(curwin, curwin->w_width - width2);
|
||||||
: sms_marker_overlap(curwin, -1);
|
// If we have non-zero scrolloff, ignore marker overlap.
|
||||||
top = curwin->w_skipcol + overlap + so_cols;
|
top = curwin->w_skipcol + (so_cols != 0 ? so_cols : overlap);
|
||||||
bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2
|
bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2
|
||||||
- so_cols;
|
- so_cols;
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
@@ -1667,12 +1666,28 @@ static void cursor_correct_sms(void)
|
|||||||
|
|
||||||
if (col != curwin->w_virtcol)
|
if (col != curwin->w_virtcol)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
curwin->w_curswant = col;
|
curwin->w_curswant = col;
|
||||||
coladvance(curwin->w_curswant);
|
rc = coladvance(curwin->w_curswant);
|
||||||
// validate_virtcol() marked various things as valid, but after
|
// validate_virtcol() marked various things as valid, but after
|
||||||
// moving the cursor they need to be recomputed
|
// moving the cursor they need to be recomputed
|
||||||
curwin->w_valid &=
|
curwin->w_valid &=
|
||||||
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL);
|
||||||
|
if (rc == FAIL && curwin->w_skipcol > 0
|
||||||
|
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
|
||||||
|
{
|
||||||
|
validate_virtcol();
|
||||||
|
if (curwin->w_virtcol < curwin->w_skipcol + overlap)
|
||||||
|
{
|
||||||
|
// Cursor still not visible: move it to the next line instead.
|
||||||
|
curwin->w_cursor.lnum++;
|
||||||
|
curwin->w_cursor.col = 0;
|
||||||
|
curwin->w_cursor.coladd = 0;
|
||||||
|
curwin->w_curswant = 0;
|
||||||
|
curwin->w_valid &= ~VALID_VIRTCOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1813,8 +1828,7 @@ scrolldown(
|
|||||||
#endif
|
#endif
|
||||||
if (do_sms)
|
if (do_sms)
|
||||||
{
|
{
|
||||||
int size = win_linetabsize(curwin, curwin->w_topline,
|
int size = linetabsize_eol(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
if (size > width1)
|
if (size > width1)
|
||||||
{
|
{
|
||||||
curwin->w_skipcol = width1;
|
curwin->w_skipcol = width1;
|
||||||
@@ -1911,7 +1925,7 @@ scrollup(
|
|||||||
colnr_T prev_skipcol = curwin->w_skipcol;
|
colnr_T prev_skipcol = curwin->w_skipcol;
|
||||||
|
|
||||||
if (do_sms)
|
if (do_sms)
|
||||||
size = linetabsize(curwin, curwin->w_topline);
|
size = linetabsize_eol(curwin, curwin->w_topline);
|
||||||
|
|
||||||
// diff mode: first consume "topfill"
|
// diff mode: first consume "topfill"
|
||||||
// 'smoothscroll': increase "w_skipcol" until it goes over the end of
|
// 'smoothscroll': increase "w_skipcol" until it goes over the end of
|
||||||
@@ -1966,7 +1980,7 @@ scrollup(
|
|||||||
# endif
|
# endif
|
||||||
curwin->w_skipcol = 0;
|
curwin->w_skipcol = 0;
|
||||||
if (todo > 1 && do_sms)
|
if (todo > 1 && do_sms)
|
||||||
size = linetabsize(curwin, curwin->w_topline);
|
size = linetabsize_eol(curwin, curwin->w_topline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2043,7 +2057,7 @@ adjust_skipcol(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
validate_virtcol();
|
validate_virtcol();
|
||||||
overlap = sms_marker_overlap(curwin, -1);
|
overlap = sms_marker_overlap(curwin, curwin->w_width - width2);
|
||||||
while (curwin->w_skipcol > 0
|
while (curwin->w_skipcol > 0
|
||||||
&& curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols)
|
&& curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols)
|
||||||
{
|
{
|
||||||
@@ -2066,8 +2080,7 @@ adjust_skipcol(void)
|
|||||||
// Avoid adjusting for 'scrolloff' beyond the text line height.
|
// Avoid adjusting for 'scrolloff' beyond the text line height.
|
||||||
if (scrolloff_cols > 0)
|
if (scrolloff_cols > 0)
|
||||||
{
|
{
|
||||||
int size = win_linetabsize(curwin, curwin->w_topline,
|
int size = linetabsize_eol(curwin, curwin->w_topline);
|
||||||
ml_get(curwin->w_topline), (colnr_T)MAXCOL);
|
|
||||||
size = width1 + width2 * ((size - width1 + width2 - 1) / width2);
|
size = width1 + width2 * ((size - width1 + width2 - 1) / width2);
|
||||||
while (col > size)
|
while (col > size)
|
||||||
col -= width2;
|
col -= width2;
|
||||||
|
@@ -5764,7 +5764,7 @@ nv_g_home_m_cmd(cmdarg_T *cap)
|
|||||||
// that skipcol is not adjusted later.
|
// that skipcol is not adjusted later.
|
||||||
if (curwin->w_skipcol > 0 && curwin->w_cursor.lnum == curwin->w_topline)
|
if (curwin->w_skipcol > 0 && curwin->w_cursor.lnum == curwin->w_topline)
|
||||||
{
|
{
|
||||||
int overlap = sms_marker_overlap(curwin, -1);
|
int overlap = sms_marker_overlap(curwin, curwin->w_width - width2);
|
||||||
if (overlap > 0 && i == curwin->w_skipcol)
|
if (overlap > 0 && i == curwin->w_skipcol)
|
||||||
i += overlap;
|
i += overlap;
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ int linetabsize_str(char_u *s);
|
|||||||
int linetabsize_col(int startcol, char_u *s);
|
int linetabsize_col(int startcol, char_u *s);
|
||||||
int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len);
|
int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len);
|
||||||
int linetabsize(win_T *wp, linenr_T lnum);
|
int linetabsize(win_T *wp, linenr_T lnum);
|
||||||
|
int linetabsize_eol(win_T *wp, linenr_T lnum);
|
||||||
int linetabsize_no_outer(win_T *wp, linenr_T lnum);
|
int linetabsize_no_outer(win_T *wp, linenr_T lnum);
|
||||||
void win_linetabsize_cts(chartabsize_T *cts, colnr_T len);
|
void win_linetabsize_cts(chartabsize_T *cts, colnr_T len);
|
||||||
int vim_isIDc(int c);
|
int vim_isIDc(int c);
|
||||||
|
@@ -1216,4 +1216,59 @@ func Test_smooth_long_scrolloff()
|
|||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_smoothscroll_listchars_eol()
|
||||||
|
call NewWindow(10, 40)
|
||||||
|
setlocal list listchars=eol:$ scrolloff=0 smoothscroll
|
||||||
|
call setline(1, repeat('-', 40))
|
||||||
|
call append(1, repeat(['foobar'], 10))
|
||||||
|
|
||||||
|
normal! G
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-Y>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
for ve in ['', 'all', 'onemore']
|
||||||
|
let &virtualedit = ve
|
||||||
|
normal! gg
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
redraw " redrawing should not cause another scroll
|
||||||
|
call assert_equal(1, line('w0'))
|
||||||
|
call assert_equal(40, winsaveview().skipcol)
|
||||||
|
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
redraw
|
||||||
|
call assert_equal(2, line('w0'))
|
||||||
|
call assert_equal(0, winsaveview().skipcol)
|
||||||
|
|
||||||
|
if ve != 'all'
|
||||||
|
call assert_equal([0, 2, 1, 0], getpos('.'))
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
set virtualedit&
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1108,
|
||||||
/**/
|
/**/
|
||||||
1107,
|
1107,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user