summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-31 18:26:10 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-31 18:26:10 +0100
commit375e3390078e740d3c83b0c118c50d9a920036c7 (patch)
tree34f565d4a9351b58d48d8d06e4a84b07effdb3fd /src
parentb3051ce82f2e8af95ce3b6a41867f70aee5ecc82 (diff)
patch 8.1.0864: cannot have a local value for 'scrolloff' and 'sidescrolloff'v8.1.0864
Problem: Cannot have a local value for 'scrolloff' and 'sidescrolloff'. (Gary Holloway) Solution: Make 'scrolloff' and 'sidescrolloff' global-local. (mostly by Aron Widforss, closes #3539)
Diffstat (limited to 'src')
-rw-r--r--src/edit.c2
-rw-r--r--src/ex_cmds.c7
-rw-r--r--src/ex_docmd.c2
-rw-r--r--src/gui.c2
-rw-r--r--src/misc2.c9
-rw-r--r--src/move.c78
-rw-r--r--src/normal.c13
-rw-r--r--src/option.c52
-rw-r--r--src/option.h2
-rw-r--r--src/proto/option.pro2
-rw-r--r--src/search.c14
-rw-r--r--src/structs.h2
-rw-r--r--src/testdir/test_options.vim35
-rw-r--r--src/version.c2
-rw-r--r--src/window.c6
15 files changed, 165 insertions, 63 deletions
diff --git a/src/edit.c b/src/edit.c
index de1666cc5e..eac4803147 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -728,7 +728,7 @@ edit(
(int)curwin->w_wcol < mincol - curbuf->b_p_ts
#endif
&& curwin->w_wrow == W_WINROW(curwin)
- + curwin->w_height - 1 - p_so
+ + curwin->w_height - 1 - get_scrolloff_value()
&& (curwin->w_cursor.lnum != curwin->w_topline
#ifdef FEAT_DIFF
|| curwin->w_topfill > 0
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 6d03d88ca7..a3974c1bad 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3784,6 +3784,7 @@ do_ecmd(
#endif
int readfile_flags = 0;
int did_inc_redrawing_disabled = FALSE;
+ long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
if (eap != NULL)
command = eap->do_ecmd_cmd;
@@ -4389,12 +4390,12 @@ do_ecmd(
did_inc_redrawing_disabled = FALSE;
if (!skip_redraw)
{
- n = p_so;
+ n = *so_ptr;
if (topline == 0 && command == NULL)
- p_so = 999; /* force cursor halfway the window */
+ *so_ptr = 9999; // force cursor halfway the window
update_topline();
curwin->w_scbind_pos = curwin->w_topline;
- p_so = n;
+ *so_ptr = n;
redraw_curbuf_later(NOT_VALID); /* redraw this buffer later */
}
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 1646a22139..b90ea7b17c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8923,7 +8923,7 @@ ex_syncbind(exarg_T *eap UNUSED)
{
if (wp->w_p_scb && wp->w_buffer)
{
- y = wp->w_buffer->b_ml.ml_line_count - p_so;
+ y = wp->w_buffer->b_ml.ml_line_count - get_scrolloff_value();
if (topline > y)
topline = y;
}
diff --git a/src/gui.c b/src/gui.c
index 39968954a8..d993bc6b00 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4405,7 +4405,7 @@ gui_do_scroll(void)
#endif
)
{
- if (p_so != 0)
+ if (get_scrolloff_value() != 0)
{
cursor_correct(); /* fix window for 'so' */
update_topline(); /* avoid up/down jump */
diff --git a/src/misc2.c b/src/misc2.c
index 657e164913..278cc330c0 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -643,6 +643,7 @@ leftcol_changed(void)
long lastcol;
colnr_T s, e;
int retval = FALSE;
+ long siso = get_sidescrolloff_value();
changed_cline_bef_curs();
lastcol = curwin->w_leftcol + curwin->w_width - curwin_col_off() - 1;
@@ -652,15 +653,15 @@ leftcol_changed(void)
* If the cursor is right or left of the screen, move it to last or first
* character.
*/
- if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso))
+ if (curwin->w_virtcol > (colnr_T)(lastcol - siso))
{
retval = TRUE;
- coladvance((colnr_T)(lastcol - p_siso));
+ coladvance((colnr_T)(lastcol - siso));
}
- else if (curwin->w_virtcol < curwin->w_leftcol + p_siso)
+ else if (curwin->w_virtcol < curwin->w_leftcol + siso)
{
retval = TRUE;
- (void)coladvance((colnr_T)(curwin->w_leftcol + p_siso));
+ (void)coladvance((colnr_T)(curwin->w_leftcol + siso));
}
/*
diff --git a/src/move.c b/src/move.c
index 14b7a6e7dc..da29b36f54 100644
--- a/src/move.c
+++ b/src/move.c
@@ -192,8 +192,9 @@ update_topline(void)
#endif
int check_topline = FALSE;
int check_botline = FALSE;
+ long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
#ifdef FEAT_MOUSE
- int save_so = p_so;
+ int save_so = *so_ptr;
#endif
/* If there is no valid screen and when the window height is zero just use
@@ -214,7 +215,7 @@ update_topline(void)
#ifdef FEAT_MOUSE
/* When dragging with the mouse, don't scroll that quickly */
if (mouse_dragging > 0)
- p_so = mouse_dragging - 1;
+ *so_ptr = mouse_dragging - 1;
#endif
old_topline = curwin->w_topline;
@@ -268,11 +269,11 @@ update_topline(void)
if (hasAnyFolding(curwin))
{
/* Count the number of logical lines between the cursor and
- * topline + p_so (approximation of how much will be
+ * topline + scrolloff (approximation of how much will be
* scrolled). */
n = 0;
for (lnum = curwin->w_cursor.lnum;
- lnum < curwin->w_topline + p_so; ++lnum)
+ lnum < curwin->w_topline + *so_ptr; ++lnum)
{
++n;
/* stop at end of file or when we know we are far off */
@@ -283,7 +284,7 @@ update_topline(void)
}
else
#endif
- n = curwin->w_topline + p_so - curwin->w_cursor.lnum;
+ n = curwin->w_topline + *so_ptr - curwin->w_cursor.lnum;
/* If we weren't very close to begin with, we scroll to put the
* cursor in the middle of the window. Otherwise put the cursor
@@ -325,7 +326,7 @@ update_topline(void)
if (curwin->w_cursor.lnum < curwin->w_botline)
{
if (((long)curwin->w_cursor.lnum
- >= (long)curwin->w_botline - p_so
+ >= (long)curwin->w_botline - *so_ptr
#ifdef FEAT_FOLDING
|| hasAnyFolding(curwin)
#endif
@@ -354,11 +355,11 @@ update_topline(void)
)
{
n += loff.height;
- if (n >= p_so)
+ if (n >= *so_ptr)
break;
botline_forw(&loff);
}
- if (n >= p_so)
+ if (n >= *so_ptr)
/* sufficient context, no need to scroll */
check_botline = FALSE;
}
@@ -372,11 +373,11 @@ update_topline(void)
if (hasAnyFolding(curwin))
{
/* Count the number of logical lines between the cursor and
- * botline - p_so (approximation of how much will be
+ * botline - scrolloff (approximation of how much will be
* scrolled). */
line_count = 0;
for (lnum = curwin->w_cursor.lnum;
- lnum >= curwin->w_botline - p_so; --lnum)
+ lnum >= curwin->w_botline - *so_ptr; --lnum)
{
++line_count;
/* stop at end of file or when we know we are far off */
@@ -388,7 +389,7 @@ update_topline(void)
else
#endif
line_count = curwin->w_cursor.lnum - curwin->w_botline
- + 1 + p_so;
+ + 1 + *so_ptr;
if (line_count <= curwin->w_height + 1)
scroll_cursor_bot(scrolljump_value(), FALSE);
else
@@ -421,7 +422,7 @@ update_topline(void)
}
#ifdef FEAT_MOUSE
- p_so = save_so;
+ *so_ptr = save_so;
#endif
}
@@ -447,8 +448,9 @@ check_top_offset(void)
{
lineoff_T loff;
int n;
+ long so = get_scrolloff_value();
- if (curwin->w_cursor.lnum < curwin->w_topline + p_so
+ if (curwin->w_cursor.lnum < curwin->w_topline + so
#ifdef FEAT_FOLDING
|| hasAnyFolding(curwin)
#endif
@@ -462,7 +464,7 @@ check_top_offset(void)
n = 0;
#endif
/* Count the visible screen lines above the cursor line. */
- while (n < p_so)
+ while (n < so)
{
topline_back(&loff);
/* Stop when included a line above the window. */
@@ -474,7 +476,7 @@ check_top_offset(void)
break;
n += loff.height;
}
- if (n < p_so)
+ if (n < so)
return TRUE;
}
return FALSE;
@@ -946,6 +948,8 @@ curs_columns(
colnr_T startcol;
colnr_T endcol;
colnr_T prev_skipcol;
+ long so = get_scrolloff_value();
+ long siso = get_sidescrolloff_value();
/*
* First make sure that w_topline is valid (after moving the cursor).
@@ -1028,9 +1032,9 @@ curs_columns(
* If we get closer to the edge than 'sidescrolloff', scroll a little
* extra
*/
- off_left = (int)startcol - (int)curwin->w_leftcol - p_siso;
+ off_left = (int)startcol - (int)curwin->w_leftcol - siso;
off_right = (int)endcol - (int)(curwin->w_leftcol + curwin->w_width
- - p_siso) + 1;
+ - siso) + 1;
if (off_left < 0 || off_right > 0)
{
if (off_left < 0)
@@ -1079,9 +1083,10 @@ curs_columns(
prev_skipcol = curwin->w_skipcol;
p_lines = 0;
+
if ((curwin->w_wrow >= curwin->w_height
|| ((prev_skipcol > 0
- || curwin->w_wrow + p_so >= curwin->w_height)
+ || curwin->w_wrow + so >= curwin->w_height)
&& (p_lines =
#ifdef FEAT_DIFF
plines_win_nofill
@@ -1098,25 +1103,25 @@ curs_columns(
/* Cursor past end of screen. Happens with a single line that does
* not fit on screen. Find a skipcol to show the text around the
* cursor. Avoid scrolling all the time. compute value of "extra":
- * 1: Less than "p_so" lines above
- * 2: Less than "p_so" lines below
+ * 1: Less than 'scrolloff' lines above
+ * 2: Less than 'scrolloff' lines below
* 3: both of them */
extra = 0;
- if (curwin->w_skipcol + p_so * width > curwin->w_virtcol)
+ if (curwin->w_skipcol + so * width > curwin->w_virtcol)
extra = 1;
/* Compute last display line of the buffer line that we want at the
* bottom of the window. */
if (p_lines == 0)
p_lines = plines_win(curwin, curwin->w_cursor.lnum, FALSE);
--p_lines;
- if (p_lines > curwin->w_wrow + p_so)
- n = curwin->w_wrow + p_so;
+ if (p_lines > curwin->w_wrow + so)
+ n = curwin->w_wrow + so;
else
n = p_lines;
if ((colnr_T)n >= curwin->w_height + curwin->w_skipcol / width)
extra += 2;
- if (extra == 3 || p_lines < p_so * 2)
+ if (extra == 3 || p_lines < so * 2)
{
/* not enough room for 'scrolloff', put cursor in the middle */
n = curwin->w_virtcol / width;
@@ -1132,7 +1137,7 @@ curs_columns(
else if (extra == 1)
{
/* less then 'scrolloff' lines above, decrease skipcol */
- extra = (curwin->w_skipcol + p_so * width - curwin->w_virtcol
+ extra = (curwin->w_skipcol + so * width - curwin->w_virtcol
+ width - 1) / width;
if (extra > 0)
{
@@ -1464,7 +1469,7 @@ scrolldown_clamp(void)
end_row += curwin->w_cline_height - 1 -
curwin->w_virtcol / curwin->w_width;
}
- if (end_row < curwin->w_height - p_so)
+ if (end_row < curwin->w_height - get_scrolloff_value())
{
#ifdef FEAT_DIFF
if (can_fill)
@@ -1522,7 +1527,7 @@ scrollup_clamp(void)
validate_virtcol();
start_row -= curwin->w_virtcol / curwin->w_width;
}
- if (start_row >= p_so)
+ if (start_row >= get_scrolloff_value())
{
#ifdef FEAT_DIFF
if (curwin->w_topfill > 0)
@@ -1666,7 +1671,7 @@ scroll_cursor_top(int min_scroll, int always)
linenr_T old_topfill = curwin->w_topfill;
#endif
linenr_T new_topline;
- int off = p_so;
+ int off = get_scrolloff_value();
#ifdef FEAT_MOUSE
if (mouse_dragging > 0)
@@ -1842,6 +1847,7 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
linenr_T old_valid = curwin->w_valid;
int old_empty_rows = curwin->w_empty_rows;
linenr_T cln; /* Cursor Line Number */
+ long so = get_scrolloff_value();
cln = curwin->w_cursor.lnum;
if (set_topbot)
@@ -1898,7 +1904,7 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
* Stop counting lines to scroll when
* - hitting start of the file
* - scrolled nothing or at least 'sj' lines
- * - at least 'so' lines below the cursor
+ * - at least 'scrolloff' lines below the cursor
* - lines between botline and cursor have been counted
*/
#ifdef FEAT_FOLDING
@@ -1924,7 +1930,7 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
#ifdef FEAT_MOUSE
mouse_dragging > 0 ? mouse_dragging - 1 :
#endif
- p_so))
+ so))
|| boff.lnum + 1 > curbuf->b_ml.ml_line_count)
&& loff.lnum <= curwin->w_botline
#ifdef FEAT_DIFF
@@ -1970,7 +1976,7 @@ scroll_cursor_bot(int min_scroll, int set_topbot)
#ifdef FEAT_MOUSE
mouse_dragging > 0 ? mouse_dragging - 1 :
#endif
- p_so) || scrolled < min_scroll)
+ so) || scrolled < min_scroll)
{
extra += boff.height;
if (boff.lnum >= curwin->w_botline
@@ -2124,7 +2130,7 @@ scroll_cursor_halfway(int atend)
/*
* Correct the cursor position so that it is in a part of the screen at least
- * 'so' lines from the top and bottom, if possible.
+ * 'scrolloff' lines from the top and bottom, if possible.
* If not possible, put it at the same position as scroll_cursor_halfway().
* When called topline must be valid!
*/
@@ -2138,13 +2144,14 @@ cursor_correct(void)
int above_wanted, below_wanted;
linenr_T cln; /* Cursor Line Number */
int max_off;
+ long so = get_scrolloff_value();
/*
* How many lines we would like to have above/below the cursor depends on
* whether the first/last line of the file is on screen.
*/
- above_wanted = p_so;
- below_wanted = p_so;
+ above_wanted = so;
+ below_wanted = so;
#ifdef FEAT_MOUSE
if (mouse_dragging > 0)
{
@@ -2262,6 +2269,7 @@ onepage(int dir, long count)
int retval = OK;
lineoff_T loff;
linenr_T old_topline = curwin->w_topline;
+ long so = get_scrolloff_value();
if (curbuf->b_ml.ml_line_count == 1) /* nothing to do */
{
@@ -2279,7 +2287,7 @@ onepage(int dir, long count)
* last line.
*/
if (dir == FORWARD
- ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - p_so)
+ ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - so)
&& curwin->w_botline > curbuf->b_ml.ml_line_count)
: (curwin->w_topline == 1
#ifdef FEAT_DIFF
diff --git a/src/normal.c b/src/normal.c
index b512b559ad..41af966288 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2814,7 +2814,7 @@ do_mouse(
/* Set global flag that we are extending the Visual area with mouse
* dragging; temporarily minimize 'scrolloff'. */
- if (VIsual_active && is_drag && p_so)
+ if (VIsual_active && is_drag && get_scrolloff_value())
{
/* In the very first line, allow scrolling one line */
if (mouse_row == 0)
@@ -4635,7 +4635,7 @@ scroll_redraw(int up, long count)
scrollup(count, TRUE);
else
scrolldown(count, TRUE);
- if (p_so)
+ if (get_scrolloff_value())
{
/* Adjust the cursor position for 'scrolloff'. Mark w_topline as
* valid, otherwise the screen jumps back at the end of the file. */
@@ -4692,6 +4692,7 @@ nv_zet(cmdarg_T *cap)
#ifdef FEAT_SPELL
int undo = FALSE;
#endif
+ long siso = get_sidescrolloff_value();
if (VIM_ISDIGIT(nchar))
{
@@ -4874,8 +4875,8 @@ dozet:
else
#endif
getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
- if ((long)col > p_siso)
- col -= p_siso;
+ if ((long)col > siso)
+ col -= siso;
else
col = 0;
if (curwin->w_leftcol != col)
@@ -4896,10 +4897,10 @@ dozet:
#endif
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
n = curwin->w_width - curwin_col_off();
- if ((long)col + p_siso < n)
+ if ((long)col + siso < n)
col = 0;
else
- col = col + p_siso - n + 1;
+ col = col + siso - n + 1;
if (curwin->w_leftcol != col)
{
curwin->w_leftcol = col;
diff --git a/src/option.c b/src/option.c
index abbbaa5873..6d2bab1e02 100644
--- a/src/option.c
+++ b/src/option.c
@@ -227,6 +227,8 @@
#endif
#define PV_SCBIND OPT_WIN(WV_SCBIND)
#define PV_SCROLL OPT_WIN(WV_SCROLL)
+#define PV_SISO OPT_BOTH(OPT_WIN(WV_SISO))
+#define PV_SO OPT_BOTH(OPT_WIN(WV_SO))
#ifdef FEAT_SPELL
# define PV_SPELL OPT_WIN(WV_SPELL)
#endif
@@ -2333,7 +2335,7 @@ static struct vimoption options[] =
(char_u *)&p_sj, PV_NONE,
{(char_u *)1L, (char_u *)0L} SCTX_INIT},
{"scrolloff", "so", P_NUM|P_VI_DEF|P_VIM|P_RALL,
- (char_u *)&p_so, PV_NONE,
+ (char_u *)&p_so, PV_SO,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"scrollopt", "sbo", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
(char_u *)&p_sbo, PV_NONE,
@@ -2490,7 +2492,7 @@ static struct vimoption options[] =
(char_u *)&p_ss, PV_NONE,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"sidescrolloff", "siso", P_NUM|P_VI_DEF|P_VIM|P_RBUF,
- (char_u *)&p_siso, PV_NONE,
+ (char_u *)&p_siso, PV_SISO,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"signcolumn", "scl", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN,
#ifdef FEAT_SIGNS
@@ -3736,11 +3738,19 @@ set_option_default(
win_comp_scroll(curwin);
else
{
- *(long *)varp = (long)(long_i)options[opt_idx].def_val[dvi];
+ long def_val = (long)(long_i)options[opt_idx].def_val[dvi];
+
+ if ((long *)varp == &curwin->w_p_so
+ || (long *)varp == &curwin->w_p_siso)
+ // 'scrolloff' and 'sidescrolloff' local values have a
+ // different default value than the global default.
+ *(long *)varp = -1;
+ else
+ *(long *)varp = def_val;
/* May also set global value for local option. */
if (both)
*(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
- *(long *)varp;
+ def_val;
}
}
else /* P_BOOL */
@@ -9382,7 +9392,7 @@ set_num_option(
}
if (p_so < 0 && full_screen)
{
- errmsg = e_scroll;
+ errmsg = e_positive;
p_so = 0;
}
if (p_siso < 0 && full_screen)
@@ -10657,6 +10667,12 @@ unset_global_local_option(char_u *name, void *from)
clear_string_option(&buf->b_p_tc);
buf->b_tc_flags = 0;
break;
+ case PV_SISO:
+ curwin->w_p_siso = -1;
+ break;
+ case PV_SO:
+ curwin->w_p_so = -1;
+ break;
#ifdef FEAT_FIND_ID
case PV_DEF:
clear_string_option(&buf->b_p_def);
@@ -10745,6 +10761,8 @@ get_varp_scope(struct vimoption *p, int opt_flags)
case PV_AR: return (char_u *)&(curbuf->b_p_ar);
case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
case PV_TC: return (char_u *)&(curbuf->b_p_tc);
+ case PV_SISO: return (char_u *)&(curwin->w_p_siso);
+ case PV_SO: return (char_u *)&(curwin->w_p_so);
#ifdef FEAT_FIND_ID
case PV_DEF: return (char_u *)&(curbuf->b_p_def);
case PV_INC: return (char_u *)&(curbuf->b_p_inc);
@@ -10803,6 +10821,10 @@ get_varp(struct vimoption *p)
? (char_u *)&(curbuf->b_p_tc) : p->var;
case PV_BKC: return *curbuf->b_p_bkc != NUL
? (char_u *)&(curbuf->b_p_bkc) : p->var;
+ case PV_SISO: return curwin->w_p_siso >= 0
+ ? (char_u *)&(curwin->w_p_siso) : p->var;
+ case PV_SO: return curwin->w_p_so >= 0
+ ? (char_u *)&(curwin->w_p_so) : p->var;
#ifdef FEAT_FIND_ID
case PV_DEF: return *curbuf->b_p_def != NUL
? (char_u *)&(curbuf->b_p_def) : p->var;
@@ -13099,6 +13121,26 @@ get_sts_value(void)
}
/*
+ * Return the effective 'scrolloff' value for the current window, using the
+ * global value when appropriate.
+ */
+ long
+get_scrolloff_value(void)
+{
+ return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
+}
+
+/*
+ * Return the effective 'sidescrolloff' value for the current window, using the
+ * global value when appropriate.
+ */
+ long
+get_sidescrolloff_value(void)
+{
+ return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
+}
+
+/*
* Check matchpairs option for "*initc".
* If there is a match set "*initc" to the matching character and "*findc" to
* the opposite character. Set "*backwards" to the direction.
diff --git a/src/option.h b/src/option.h
index c282da3253..90c05080bd 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1152,6 +1152,8 @@ enum
#endif
, WV_SCBIND
, WV_SCROLL
+ , WV_SISO
+ , WV_SO
#ifdef FEAT_SPELL
, WV_SPELL
#endif
diff --git a/src/proto/option.pro b/src/proto/option.pro
index 3da51c6587..1027edf68c 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -76,6 +76,8 @@ long get_sw_value_indent(buf_T *buf);
long get_sw_value_pos(buf_T *buf, pos_T *pos);
long get_sw_value_col(buf_T *buf, colnr_T col);
long get_sts_value(void);
+long get_scrolloff_value(void);
+long get_sidescrolloff_value(void);
void find_mps_values(int *initc, int *findc, int *backwards, int switchit);
unsigned int get_bkc_value(buf_T *buf);
int signcolumn_on(win_T *wp);
diff --git a/src/search.c b/src/search.c
index a4b4c4177c..4b3f8532a5 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2601,6 +2601,8 @@ showmatch(
#endif
colnr_T save_dollar_vcol;
char_u *p;
+ long *so = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
+ long *siso = curwin->w_p_siso >= 0 ? &curwin->w_p_siso : &p_siso;
/*
* Only show match for chars in the 'matchpairs' option.
@@ -2635,8 +2637,8 @@ showmatch(
{
mpos = *lpos; /* save the pos, update_screen() may change it */
save_cursor = curwin->w_cursor;
- save_so = p_so;
- save_siso = p_siso;
+ save_so = *so;
+ save_siso = *siso;
/* Handle "$" in 'cpo': If the ')' is typed on top of the "$",
* stop displaying the "$". */
if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol)
@@ -2651,8 +2653,8 @@ showmatch(
ui_cursor_shape(); /* may show different cursor shape */
#endif
curwin->w_cursor = mpos; /* move to matching char */
- p_so = 0; /* don't use 'scrolloff' here */
- p_siso = 0; /* don't use 'sidescrolloff' here */
+ *so = 0; /* don't use 'scrolloff' here */
+ *siso = 0; /* don't use 'sidescrolloff' here */
showruler(FALSE);
setcursor();
cursor_on(); /* make sure that the cursor is shown */
@@ -2672,8 +2674,8 @@ showmatch(
else if (!char_avail())
ui_delay(p_mat * 100L, FALSE);
curwin->w_cursor = save_cursor; /* restore cursor position */
- p_so = save_so;
- p_siso = save_siso;
+ *so = save_so;
+ *siso = save_siso;
#ifdef CURSOR_SHAPE
State = save_state;
ui_cursor_shape(); /* may show different cursor shape */
diff --git a/src/structs.h b/src/structs.h
index ddc56bca4d..e6cc8291f1 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2932,6 +2932,8 @@ struct window_S
int w_p_brishift; /* additional shift for breakindent */
int w_p_brisbr; /* sbr in 'briopt' */
#endif
+ long w_p_siso; /* 'sidescrolloff' local value */
+ long w_p_so; /* 'scrolloff' local value */
/* transform a pointer to a "onebuf" option into a "allbuf" option */
#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T))
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index 740863e3cc..83b315d00e 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -483,3 +483,38 @@ func Test_shortmess_F2()
bwipe
bwipe
endfunc
+
+func Test_local_scrolloff()
+ set so=5
+ set siso=7
+ split
+ call assert_equal(5, &so)
+ setlocal so=3
+ call assert_equal(3, &so)
+ wincmd w
+ call assert_equal(5, &so)
+ wincmd w
+ setlocal so<
+ call assert_equal(5, &so)
+ setlocal so=0
+ call assert_equal(0, &so)
+ setlocal so=-1
+ call assert_equal(5, &so)
+
+ call assert_equal(7, &siso)
+ setlocal siso=3
+ call assert_equal(3, &siso)
+ wincmd w
+ call assert_equal(7, &siso)
+ wincmd w
+ setlocal siso<
+ call assert_equal(7, &siso)
+ setlocal siso=0
+ call assert_equal(0, &siso)
+ setlocal siso=-1
+ call assert_equal(7, &siso)
+
+ close
+ set so&
+ set siso&
+endfunc
diff --git a/src/version.c b/src/version.c
index 05b18ed7e6..7a02fbdca1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -784,6 +784,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 864,
+/**/
863,
/**/
862,
diff --git a/src/window.c b/src/window.c
index d89f3a8e6e..f78fccafe6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4594,6 +4594,10 @@ win_alloc(win_T *after UNUSED, int hidden UNUSED)
new_wp->w_cursor.lnum = 1;
new_wp->w_scbind_pos = 1;
+ // use global option value for global-local options
+ new_wp->w_p_so = -1;
+ new_wp->w_p_siso = -1;
+
/* We won't calculate w_fraction until resizing the window */
new_wp->w_fraction = 0;
new_wp->w_prev_fraction_row = -1;
@@ -5871,7 +5875,7 @@ scroll_to_fraction(win_T *wp, int prev_height)
if (wp == curwin)
{
- if (p_so)
+ if (get_scrolloff_value())
update_topline();
curs_columns(FALSE); /* validate w_wrow */
}