summaryrefslogtreecommitdiff
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
parentb3051ce82f2e8af95ce3b6a41867f70aee5ecc82 (diff)
downloadvim-git-375e3390078e740d3c83b0c118c50d9a920036c7.tar.gz
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)
-rw-r--r--runtime/doc/options.txt16
-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
16 files changed, 177 insertions, 67 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 266749006..04c38b204 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -6590,14 +6590,18 @@ A jump table for the options with a short description can be found at |Q_op|.
*'scrolloff'* *'so'*
'scrolloff' 'so' number (default 0, set to 5 in |defaults.vim|)
- global
+ global or local to window |global-local|
{not in Vi}
Minimal number of screen lines to keep above and below the cursor.
This will make some context visible around where you are working. If
you set it to a very large value (999) the cursor line will always be
in the middle of the window (except at the start or end of the file or
when long lines wrap).
- For scrolling horizontally see 'sidescrolloff'.
+ After using the local value, go back the global value with one of
+ these two: >
+ setlocal scrolloff<
+ setlocal scrolloff=-1
+< For scrolling horizontally see 'sidescrolloff'.
NOTE: This option is set to 0 when 'compatible' is set.
*'scrollopt'* *'sbo'*
@@ -7152,7 +7156,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'sidescrolloff'* *'siso'*
'sidescrolloff' 'siso' number (default 0)
- global
+ global or local to window |global-local|
{not in Vi}
The minimal number of screen columns to keep to the left and to the
right of the cursor if 'nowrap' is set. Setting this option to a
@@ -7162,7 +7166,11 @@ A jump table for the options with a short description can be found at |Q_op|.
to a large value (like 999) has the effect of keeping the cursor
horizontally centered in the window, as long as one does not come too
close to the beginning of the line.
- NOTE: This option is set to 0 when 'compatible' is set.
+ After using the local value, go back the global value with one of
+ these two: >
+ setlocal sidescrolloff<
+ setlocal sidescrolloff=-1
+< NOTE: This option is set to 0 when 'compatible' is set.
Example: Try this together with 'sidescroll' and 'listchars' as
in the following example to never allow the cursor to move
diff --git a/src/edit.c b/src/edit.c
index de1666cc5..eac480314 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 6d03d88ca..a3974c1ba 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 1646a2213..b90ea7b17 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 39968954a..d993bc6b0 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 657e16491..278cc330c 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 14b7a6e7d..da29b36f5 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 b512b559a..41af96628 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 abbbaa587..6d2bab1e0 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 c282da325..90c05080b 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 3da51c658..1027edf68 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 a4b4c4177..4b3f8532a 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 ddc56bca4..e6cc8291f 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 740863e3c..83b315d00 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 05b18ed7e..7a02fbdca 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 d89f3a8e6..f78fccafe 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 */
}