Skip to content

Commit db4d88c

Browse files
committed
patch 9.0.1121: cursor positioning and display problems with 'smoothscroll'
Problem: Cursor positioning and display problems with 'smoothscroll' and using "zt", "zb" or "zz". Solution: Adjust computations and conditions. (Yee Cheng Chin, closes #11764)
1 parent c55e8f2 commit db4d88c

12 files changed

+184
-29
lines changed

src/macros.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,10 @@
253253

254254
#ifdef FEAT_DIFF
255255
# define PLINES_NOFILL(x) plines_nofill(x)
256+
# define PLINES_WIN_NOFILL(w, l, h) plines_win_nofill((w), (l), (h))
256257
#else
257258
# define PLINES_NOFILL(x) plines(x)
259+
# define PLINES_WIN_NOFILL(w, l, h) plines_win((w), (l), (h))
258260
#endif
259261

260262
#if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER)

src/move.c

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,23 @@ smoothscroll_marker_overlap(int extra2)
221221
return extra2 > 3 ? 0 : 3 - extra2;
222222
}
223223

224+
/*
225+
* Calculates the skipcol offset for window "wp" given how many
226+
* physical lines we want to scroll down.
227+
*/
228+
static int
229+
skipcol_from_plines(win_T *wp, int plines_off)
230+
{
231+
int width1 = wp->w_width - win_col_off(wp);
232+
233+
int skipcol = 0;
234+
if (plines_off > 0)
235+
skipcol += width1;
236+
if (plines_off > 1)
237+
skipcol += (width1 + win_col_off2(wp)) * (plines_off - 1);
238+
return skipcol;
239+
}
240+
224241
/*
225242
* Set curwin->s_skipcol to zero and redraw later if needed.
226243
*/
@@ -2149,7 +2166,9 @@ scrollup_clamp(void)
21492166
* Lines above the first one are incredibly high: MAXCOL.
21502167
*/
21512168
static void
2152-
topline_back(lineoff_T *lp)
2169+
topline_back_winheight(
2170+
lineoff_T *lp,
2171+
int winheight) // when TRUE limit to window height
21532172
{
21542173
#ifdef FEAT_DIFF
21552174
if (lp->fill < diff_check_fill(curwin, lp->lnum))
@@ -2174,10 +2193,17 @@ topline_back(lineoff_T *lp)
21742193
lp->height = 1;
21752194
else
21762195
#endif
2177-
lp->height = PLINES_NOFILL(lp->lnum);
2196+
lp->height = PLINES_WIN_NOFILL(curwin, lp->lnum, winheight);
21782197
}
21792198
}
21802199

2200+
static void
2201+
topline_back(lineoff_T *lp)
2202+
{
2203+
topline_back_winheight(lp, TRUE);
2204+
}
2205+
2206+
21812207
/*
21822208
* Add one line below "lp->lnum". This can be a filler line, a closed fold or
21832209
* a (wrapped) text line. Uses and sets "lp->fill".
@@ -2317,6 +2343,14 @@ scroll_cursor_top(int min_scroll, int always)
23172343
else
23182344
#endif
23192345
i = PLINES_NOFILL(top);
2346+
if (top < curwin->w_topline)
2347+
scrolled += i;
2348+
2349+
// If scrolling is needed, scroll at least 'sj' lines.
2350+
if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
2351+
&& extra >= off)
2352+
break;
2353+
23202354
used += i;
23212355
if (extra + i <= off && bot < curbuf->b_ml.ml_line_count)
23222356
{
@@ -2330,15 +2364,6 @@ scroll_cursor_top(int min_scroll, int always)
23302364
}
23312365
if (used > curwin->w_height)
23322366
break;
2333-
if (top < curwin->w_topline)
2334-
scrolled += i;
2335-
2336-
/*
2337-
* If scrolling is needed, scroll at least 'sj' lines.
2338-
*/
2339-
if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
2340-
&& extra >= off)
2341-
break;
23422367

23432368
extra += i;
23442369
new_topline = top;
@@ -2436,6 +2461,7 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
24362461
int i;
24372462
linenr_T line_count;
24382463
linenr_T old_topline = curwin->w_topline;
2464+
int old_skipcol = curwin->w_skipcol;
24392465
lineoff_T loff;
24402466
lineoff_T boff;
24412467
#ifdef FEAT_DIFF
@@ -2451,6 +2477,8 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
24512477
cln = curwin->w_cursor.lnum;
24522478
if (set_topbot)
24532479
{
2480+
int set_skipcol = FALSE;
2481+
24542482
used = 0;
24552483
curwin->w_botline = cln + 1;
24562484
#ifdef FEAT_DIFF
@@ -2461,9 +2489,32 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
24612489
curwin->w_topline = loff.lnum)
24622490
{
24632491
loff.lnum = curwin->w_topline;
2464-
topline_back(&loff);
2465-
if (loff.height == MAXCOL || used + loff.height > curwin->w_height)
2492+
topline_back_winheight(&loff, FALSE);
2493+
if (loff.height == MAXCOL)
24662494
break;
2495+
if (used + loff.height > curwin->w_height)
2496+
{
2497+
if (curwin->w_p_sms && curwin->w_p_wrap)
2498+
{
2499+
// 'smoothscroll' and 'wrap' are set. The above line is
2500+
// too long to show in its entirety, so we show just a part
2501+
// of it.
2502+
if (used < curwin->w_height)
2503+
{
2504+
int plines_offset = used + loff.height
2505+
- curwin->w_height;
2506+
used = curwin->w_height;
2507+
#ifdef FEAT_DIFF
2508+
curwin->w_topfill = loff.fill;
2509+
#endif
2510+
curwin->w_topline = loff.lnum;
2511+
curwin->w_skipcol = skipcol_from_plines(
2512+
curwin, plines_offset);
2513+
set_skipcol = TRUE;
2514+
}
2515+
}
2516+
break;
2517+
}
24672518
used += loff.height;
24682519
#ifdef FEAT_DIFF
24692520
curwin->w_topfill = loff.fill;
@@ -2475,8 +2526,15 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
24752526
#ifdef FEAT_DIFF
24762527
|| curwin->w_topfill != old_topfill
24772528
#endif
2478-
)
2529+
|| set_skipcol
2530+
|| curwin->w_skipcol != 0)
2531+
{
24792532
curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
2533+
if (set_skipcol)
2534+
redraw_later(UPD_NOT_VALID);
2535+
else
2536+
reset_skipcol();
2537+
}
24802538
}
24812539
else
24822540
validate_botline();
@@ -2680,7 +2738,9 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
26802738
* (we changed them).
26812739
* If topline did change, update_screen() will set botline.
26822740
*/
2683-
if (curwin->w_topline == old_topline && set_topbot)
2741+
if (curwin->w_topline == old_topline
2742+
&& curwin->w_skipcol == old_skipcol
2743+
&& set_topbot)
26842744
{
26852745
curwin->w_botline = old_botline;
26862746
curwin->w_empty_rows = old_empty_rows;
@@ -2698,6 +2758,8 @@ scroll_cursor_halfway(int atend)
26982758
{
26992759
int above = 0;
27002760
linenr_T topline;
2761+
colnr_T skipcol = 0;
2762+
int set_skipcol = FALSE;
27012763
#ifdef FEAT_DIFF
27022764
int topfill = 0;
27032765
#endif
@@ -2725,8 +2787,57 @@ scroll_cursor_halfway(int atend)
27252787
used = plines(loff.lnum);
27262788
#endif
27272789
topline = loff.lnum;
2790+
2791+
int half_height = 0;
2792+
int smooth_scroll = FALSE;
2793+
if (curwin->w_p_sms && curwin->w_p_wrap)
2794+
{
2795+
// 'smoothscroll' and 'wrap' are set
2796+
smooth_scroll = TRUE;
2797+
half_height = (curwin->w_height - used) / 2;
2798+
used = 0;
2799+
}
2800+
27282801
while (topline > 1)
27292802
{
2803+
// If using smoothscroll, we can precisely scroll to the
2804+
// exact point where the cursor is halfway down the screen.
2805+
if (smooth_scroll)
2806+
{
2807+
topline_back_winheight(&loff, FALSE);
2808+
if (loff.height == MAXCOL)
2809+
break;
2810+
else
2811+
used += loff.height;
2812+
if (used > half_height)
2813+
{
2814+
if (used - loff.height < half_height)
2815+
{
2816+
int plines_offset = used - half_height;
2817+
loff.height -= plines_offset;
2818+
used = half_height;
2819+
2820+
topline = loff.lnum;
2821+
#ifdef FEAT_DIFF
2822+
topfill = loff.fill;
2823+
#endif
2824+
skipcol = skipcol_from_plines(curwin, plines_offset);
2825+
set_skipcol = TRUE;
2826+
}
2827+
break;
2828+
}
2829+
topline = loff.lnum;
2830+
#ifdef FEAT_DIFF
2831+
topfill = loff.fill;
2832+
#endif
2833+
continue;
2834+
}
2835+
2836+
// If not using smoothscroll, we have to iteratively find how many
2837+
// lines to scroll down to roughly fit the cursor.
2838+
// This may not be right in the middle if the lines' physical height >
2839+
// 1 (e.g. 'wrap' is on).
2840+
27302841
if (below <= above) // add a line below the cursor first
27312842
{
27322843
if (boff.lnum < curbuf->b_ml.ml_line_count)
@@ -2764,7 +2875,21 @@ scroll_cursor_halfway(int atend)
27642875
#ifdef FEAT_FOLDING
27652876
if (!hasFolding(topline, &curwin->w_topline, NULL))
27662877
#endif
2767-
curwin->w_topline = topline;
2878+
{
2879+
if (curwin->w_topline != topline
2880+
|| set_skipcol
2881+
|| curwin->w_skipcol != 0)
2882+
{
2883+
curwin->w_topline = topline;
2884+
if (set_skipcol)
2885+
{
2886+
curwin->w_skipcol = skipcol;
2887+
redraw_later(UPD_NOT_VALID);
2888+
}
2889+
else
2890+
reset_skipcol();
2891+
}
2892+
}
27682893
#ifdef FEAT_DIFF
27692894
curwin->w_topfill = topfill;
27702895
if (old_topline > curwin->w_topline + curwin->w_height)
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
>f+0&#ffffff0|o|u|r| @35
1+
|<+0#4040ff13#ffffff0@2|o+0#0000000&|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
2+
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
3+
>f|o|u|r| @35
24
|~+0#4040ff13&| @38
35
|~| @38
4-
|~| @38
5-
|~| @38
66
|:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t|

src/testdir/dumps/Test_smooth_long_11.dump

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
44
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
55
>f|o|u|r| @35
6-
@22|4|,|1| @10|B|o|t|
6+
|:|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t|
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
|<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
2-
|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
3-
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
1+
|<+0#4040ff13#ffffff0@2|o+0#0000000&|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
42
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
5-
|f|o|u>r| @35
6-
@22|4|,|4| @10|B|o|t|
3+
>f|o|u|r| @35
4+
|~+0#4040ff13&| @38
5+
|~| @38
6+
|:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t|
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
>f+0&#ffffff0|o|u|r| @35
2+
|~+0#4040ff13&| @38
3+
|~| @38
4+
|~| @38
5+
|~| @38
6+
| +0#0000000&@21|4|,|1| @10|B|o|t|
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
|<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
2+
|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
3+
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
4+
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
5+
>f|o|u|r| @35
6+
@22|4|,|1| @10|B|o|t|
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
|<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t
2+
|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o
3+
|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
4+
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
5+
|f|o|u>r| @35
6+
@22|4|,|4| @10|B|o|t|

src/testdir/dumps/Test_smooth_long_8.dump

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
|t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
44
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
55
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
6-
|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|6@1|%|
6+
| @21|3|,|1|3|0| @8|6@1|%|

src/testdir/dumps/Test_smooth_long_9.dump

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
|t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o
44
|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e
55
|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w
6-
|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|6@1|%|
6+
| @21|3|,|1|3|0| @8|6@1|%|

0 commit comments

Comments
 (0)