Skip to content

Commit

Permalink
text is scrolled for 'nosplitscroll' when window has folds
Browse files Browse the repository at this point in the history
Problem:	Text is scrolled for 'nosplitscroll' when window has folds.
Solution:	Take into account fold length when calculating cursor
position to avoid scrolling.
  • Loading branch information
luukvbaal committed Sep 26, 2022
1 parent 838b746 commit b6aec37
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 19 deletions.
20 changes: 20 additions & 0 deletions src/testdir/dumps/Test_nosplitscroll_fold_1.dump
@@ -0,0 +1,20 @@
| +0#0000e05#a8a8a8255@1|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0@1|8| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255@1|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|1|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|1|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|2|4| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|2|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|3|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p
| +0#af5f00255&|4|0| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|4|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|4|8| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|4|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|5|6| >a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|5|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|6|4| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|6|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|7|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|5|6|,|1| @10|3|0|%
|:+0&&|w|i|n|c|m|d| |s| @65
20 changes: 20 additions & 0 deletions src/testdir/dumps/Test_nosplitscroll_fold_2.dump
@@ -0,0 +1,20 @@
| +0#0000e05#a8a8a8255@1|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0@1|8| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255@1|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|1|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|1|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p
| +0#0000e05#a8a8a8255|2|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|3|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|3@1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|4|0| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|4|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|3|9|,|1| @10|1|7|%
| +0#0000e05#a8a8a8255|4|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|5|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|5|7| >+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|6|4| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|6|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|7|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|6|3|,|1| @10|3|5|%
|:+0&&|w|i|n|c|m|d| |s| @65
20 changes: 20 additions & 0 deletions src/testdir/dumps/Test_nosplitscroll_fold_3.dump
@@ -0,0 +1,20 @@
| +0#0000e05#a8a8a8255@1|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0@1|8| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255@1|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|1|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|1|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p
| +0#0000e05#a8a8a8255|2|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|3|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|3@1| >+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|4|0| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|4|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+3#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|3|9|,|1| @10|1|7|%
| +0#0000e05#a8a8a8255|4|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|5|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|5|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|6|4| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|6|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|7|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|6|3|,|1| @10|3|5|%
|:+0&&|w|i|n|c|m|d| |k| @65
20 changes: 20 additions & 0 deletions src/testdir/dumps/Test_nosplitscroll_fold_4.dump
@@ -0,0 +1,20 @@
| +0#0000e05#a8a8a8255@1|1| >+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0@1|8| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255@1|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|1|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|1|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+3#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p
| +0#0000e05#a8a8a8255|2|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|3|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|3@1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|4|0| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|4|1| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
|[+1#0000000#ffffff0|N|o| |N|a|m|e|]| |[|+|]| @43|3|9|,|1| @10|1|7|%
| +0#0000e05#a8a8a8255|4|9| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|5|6| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|5|7| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|6|4| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
| +0#0000e05#a8a8a8255|6|5| |+|-@1| @1|7| |l|i|n|e|s|:| |i|n|t| |F|u|n|c|N|a|m|e|(|)| |{|-@40
| +0#af5f00255#ffffff0|7|2| |a+0#0000000&|f|t|e|r| |f|o|l|d| @60
|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|6|3|,|1| @10|3|5|%
|:+0&&|w|i|n|c|m|d| |k| @65
31 changes: 31 additions & 0 deletions src/testdir/test_window_cmd.vim
Expand Up @@ -1848,4 +1848,35 @@ function Test_nosplitscroll_callback()
call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_4', {})
endfunc

function Test_nosplitscroll_fold()
CheckScreendump

let lines =<< trim END
set nosplitscroll
set foldmethod=marker
set number
set splitbelow
let line = 1
for n in range(1, &lines)
call setline(line, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
\ 'after fold'])
let line += 8
endfor
END
call writefile(lines, 'XTestNosplitscrollFold', 'D')
let buf = RunVimInTerminal('-S XTestNosplitscrollFold', #{rows: 20})

call term_sendkeys(buf, ":wincmd s\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_1', {})

call term_sendkeys(buf, ":wincmd s\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_2', {})

call term_sendkeys(buf, ":wincmd k\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_3', {})

call term_sendkeys(buf, ":wincmd k\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_4', {})
endfunction

" vim: shiftwidth=2 sts=2 expandtab
91 changes: 72 additions & 19 deletions src/window.c
Expand Up @@ -27,6 +27,9 @@ static win_T *frame2win(frame_T *frp);
static int frame_has_win(frame_T *frp, win_T *wp);
static void win_fix_scroll(int resize);
static void win_fix_cursor(int normal);
#ifdef FEAT_FOLDING
static linenr_T win_walk_fold(win_T *wp, linenr_T start, int steps, int down);
#endif
static void frame_new_height(frame_T *topfrp, int height, int topfirst, int wfh);
static int frame_fixed_height(frame_T *frp);
static int frame_fixed_width(frame_T *frp);
Expand Down Expand Up @@ -6370,9 +6373,15 @@ win_fix_scroll(int resize)
if (wp->w_winrow != wp->w_prev_winrow)
{
lnum = wp->w_cursor.lnum;
wp->w_cursor.lnum = MIN(wp->w_buffer->b_ml.ml_line_count,
wp->w_botline - 1 + (wp->w_winrow - wp->w_prev_winrow)
+ (wp->w_height - wp->w_prev_height));
int diff = (wp->w_winrow - wp->w_prev_winrow)
+ (wp->w_height - wp->w_prev_height);
#ifdef FEAT_FOLDING
if (hasAnyFolding(wp))
win_walk_fold(wp, wp->w_botline - 1, abs(diff), diff > 0);
else
#endif
wp->w_cursor.lnum = MIN(wp->w_buffer->b_ml.ml_line_count,
wp->w_botline - 1 + diff);
// Bring the new cursor position to the bottom of the screen.
wp->w_fraction = FRACTION_MULT;
scroll_to_fraction(wp, wp->w_prev_height);
Expand Down Expand Up @@ -6404,8 +6413,14 @@ win_fix_scroll(int resize)
win_fix_cursor(int normal)
{
win_T *wp = curwin;
#ifdef FEAT_FOLDING
int fold = hasAnyFolding(wp);
#endif
long so = get_scrolloff_value();
linenr_T nlnum = 0;
linenr_T lnum = wp->w_cursor.lnum;
linenr_T top;
linenr_T bot;

if (wp->w_buffer->b_ml.ml_line_count < wp->w_height)
return;
Expand All @@ -6415,33 +6430,71 @@ win_fix_cursor(int normal)
#endif

so = MIN(wp->w_height / 2, so);
// Check if cursor position is above topline or below botline.
if (wp->w_cursor.lnum < (wp->w_topline + so) && wp->w_topline != 1)
nlnum = MIN(wp->w_topline + so, wp->w_buffer->b_ml.ml_line_count);
else if (wp->w_cursor.lnum > (wp->w_botline - so - 1)
&& (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
nlnum = MAX(wp->w_botline - so - 1, 1);
// If cursor was invalid scroll or change cursor.
top = wp->w_topline + so;
bot = wp->w_botline - 1 - so;
#ifdef FEAT_FOLDING
if (fold && so)
{
top = win_walk_fold(wp, wp->w_topline, so, TRUE);
bot = win_walk_fold(wp, wp->w_botline - 1, so, FALSE);
}
#endif

// Check if cursor position is above or below visible range.
if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
nlnum = bot;
else if (lnum < top && wp->w_topline != 1)
nlnum = (so == wp->w_height / 2) ? bot : top;

wp->w_cursor.lnum = lnum;
// Cursor is invalid for current scroll position.
if (nlnum)
{
if (normal)
{ // Make sure cursor is closer to topline than botline.
if (so == wp->w_height / 2
&& nlnum - wp->w_topline > wp->w_botline - 1 - nlnum)
nlnum--;
setmark('\''); // save cursor position
wp->w_cursor.lnum = nlnum; // change to avoid scrolling
if (normal) // Save to jumplist and set cursor to avoid scrolling.
{
setmark('\'');
wp->w_cursor.lnum = nlnum;
curs_columns(TRUE); // validate w_wrow
}
else
{ // Ensure cursor stays visible if we are not in normal mode.
else // Scroll instead when not in normal mode.
{
wp->w_fraction = 0.5 * FRACTION_MULT;
scroll_to_fraction(wp, wp->w_prev_height);
validate_botline_win(curwin);
}
}
}

/*
* Walk cursor "steps" up or down from "start". Return resulting cursor lnum.
*/
#ifdef FEAT_FOLDING
static linenr_T
win_walk_fold(win_T *wp, linenr_T start, int steps, int down)
{
long fold_len;
foldinfo_T foldinfo;

wp->w_cursor.lnum = start;

while (steps-- && wp->w_cursor.lnum > 1
&& wp->w_cursor.lnum < wp->w_buffer->b_ml.ml_line_count)
{
fold_len = foldedCount(wp, wp->w_cursor.lnum, &foldinfo);

if (down)
wp->w_cursor.lnum += fold_len ? fold_len : 1;
else
{
fold_len = fold_len ? foldedCount(wp, foldinfo.fi_lnum, NULL) : 1;
wp->w_cursor.lnum -= fold_len;
}
}

return wp->w_cursor.lnum;
}
#endif

/*
* Set the height of a window.
* "height" excludes any window toolbar.
Expand Down

0 comments on commit b6aec37

Please sign in to comment.