vim-patch:8.1.0864 Make 'scrolloff' and 'sidescrolloff' options window local (#11854)

Problem: cannot have a local value for 'scrolloff' and 'sidescrolloff'

Author: Bram Moolenar

375e339007
This commit is contained in:
Will Eccles 2020-03-17 15:05:34 -04:00 committed by GitHub
parent 5a5c2f0290
commit 87d892afa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 245 additions and 126 deletions

View File

@ -4900,13 +4900,17 @@ A jump table for the options with a short description can be found at |Q_op|.
*'scrolloff'* *'so'*
'scrolloff' 'so' number (default 0)
global
global or local to window |global-local|
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'.
*'scrollopt'* *'sbo'*
'scrollopt' 'sbo' string (default "ver,jump")
@ -5515,7 +5519,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|
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
value greater than 0 while having |'sidescroll'| also at a non-zero
@ -5524,7 +5528,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.
After using the local value, go back the global value with one of
these two: >
setlocal sidescrolloff<
setlocal sidescrolloff=-1
<
Example: Try this together with 'sidescroll' and 'listchars' as
in the following example to never allow the cursor to move
onto the "extends" character: >

View File

@ -1278,16 +1278,18 @@ struct window_S {
winopt_T w_onebuf_opt;
winopt_T w_allbuf_opt;
/* A few options have local flags for P_INSECURE. */
uint32_t w_p_stl_flags; /* flags for 'statusline' */
uint32_t w_p_fde_flags; /* flags for 'foldexpr' */
uint32_t w_p_fdt_flags; /* flags for 'foldtext' */
int *w_p_cc_cols; /* array of columns to highlight or NULL */
int w_p_brimin; /* minimum width for breakindent */
int w_p_brishift; /* additional shift for breakindent */
bool w_p_brisbr; /* sbr in 'briopt' */
// A few options have local flags for P_INSECURE.
uint32_t w_p_stl_flags; // flags for 'statusline'
uint32_t w_p_fde_flags; // flags for 'foldexpr'
uint32_t w_p_fdt_flags; // flags for 'foldtext'
int *w_p_cc_cols; // array of columns to highlight or NULL
int w_p_brimin; // minimum width for breakindent
int w_p_brishift; // additional shift for breakindent
bool w_p_brisbr; // sbr in 'briopt'
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 */
// transform a pointer to a "onebuf" option into a "allbuf" option
#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T))
long w_scbind_pos;

View File

@ -593,7 +593,7 @@ static int insert_check(VimState *state)
if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
&& curwin->w_wrow == curwin->w_winrow
+ curwin->w_height_inner - 1 - p_so
+ curwin->w_height_inner - 1 - get_scrolloff_value()
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {

View File

@ -2177,6 +2177,7 @@ int do_ecmd(
int did_get_winopts = FALSE;
int readfile_flags = 0;
bool 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;
@ -2678,13 +2679,14 @@ int do_ecmd(
RedrawingDisabled--;
did_inc_redrawing_disabled = false;
if (!skip_redraw) {
n = p_so;
if (topline == 0 && command == NULL)
p_so = 999; // force cursor to be vertically centered in the window
n = *so_ptr;
if (topline == 0 && command == NULL) {
*so_ptr = 999; // force cursor to be vertically centered in the window
}
update_topline();
curwin->w_scbind_pos = curwin->w_topline;
p_so = n;
redraw_curbuf_later(NOT_VALID); /* redraw this buffer later */
*so_ptr = n;
redraw_curbuf_later(NOT_VALID); // redraw this buffer later
}
if (p_im)

View File

@ -7367,7 +7367,7 @@ static void ex_syncbind(exarg_T *eap)
topline = curwin->w_topline;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
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;
}

View File

@ -142,7 +142,8 @@ void update_topline(void)
int old_topfill;
bool check_topline = false;
bool check_botline = false;
long save_so = p_so;
long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
long save_so = *so_ptr;
// If there is no valid screen and when the window height is zero just use
// the cursor line.
@ -158,9 +159,10 @@ void update_topline(void)
if (curwin->w_valid & VALID_TOPLINE)
return;
/* When dragging with the mouse, don't scroll that quickly */
if (mouse_dragging > 0)
p_so = mouse_dragging - 1;
// When dragging with the mouse, don't scroll that quickly
if (mouse_dragging > 0) {
*so_ptr = mouse_dragging - 1;
}
old_topline = curwin->w_topline;
old_topfill = curwin->w_topfill;
@ -206,15 +208,17 @@ void update_topline(void)
* scrolled). */
n = 0;
for (linenr_T lnum = curwin->w_cursor.lnum;
lnum < curwin->w_topline + p_so; ++lnum) {
++n;
/* stop at end of file or when we know we are far off */
if (lnum >= curbuf->b_ml.ml_line_count || n >= halfheight)
lnum < curwin->w_topline + *so_ptr; lnum++) {
n++;
// stop at end of file or when we know we are far off
if (lnum >= curbuf->b_ml.ml_line_count || n >= halfheight) {
break;
}
(void)hasFolding(lnum, NULL, &lnum);
}
} else
n = curwin->w_topline + p_so - curwin->w_cursor.lnum;
} else {
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
@ -247,7 +251,7 @@ void update_topline(void)
if (curwin->w_botline <= curbuf->b_ml.ml_line_count) {
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
|| hasAnyFolding(curwin)
)) {
lineoff_T loff;
@ -266,13 +270,15 @@ void update_topline(void)
&& (loff.lnum + 1 < curwin->w_botline || loff.fill == 0)
) {
n += loff.height;
if (n >= p_so)
if (n >= *so_ptr) {
break;
}
botline_forw(&loff);
}
if (n >= p_so)
/* sufficient context, no need to scroll */
if (n >= *so_ptr) {
// sufficient context, no need to scroll
check_botline = false;
}
} else {
/* sufficient context, no need to scroll */
check_botline = false;
@ -285,7 +291,7 @@ void update_topline(void)
* botline - p_so (approximation of how much will be
* scrolled). */
for (linenr_T 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
if (lnum <= 0 || line_count > curwin->w_height_inner + 1) {
@ -295,7 +301,7 @@ void update_topline(void)
}
} else
line_count = curwin->w_cursor.lnum - curwin->w_botline
+ 1 + p_so;
+ 1 + *so_ptr;
if (line_count <= curwin->w_height_inner + 1) {
scroll_cursor_bot(scrolljump_value(), false);
} else {
@ -324,7 +330,7 @@ void update_topline(void)
validate_cursor();
}
p_so = save_so;
*so_ptr = save_so;
}
/*
@ -356,25 +362,28 @@ static int scrolljump_value(void)
*/
static bool check_top_offset(void)
{
if (curwin->w_cursor.lnum < curwin->w_topline + p_so
long so = get_scrolloff_value();
if (curwin->w_cursor.lnum < curwin->w_topline + so
|| hasAnyFolding(curwin)
) {
lineoff_T loff;
loff.lnum = curwin->w_cursor.lnum;
loff.fill = 0;
int n = curwin->w_topfill; /* always have this context */
/* Count the visible screen lines above the cursor line. */
while (n < p_so) {
int n = curwin->w_topfill; // always have this context
// Count the visible screen lines above the cursor line.
while (n < so) {
topline_back(&loff);
/* Stop when included a line above the window. */
// Stop when included a line above the window.
if (loff.lnum < curwin->w_topline
|| (loff.lnum == curwin->w_topline && loff.fill > 0)
)
) {
break;
}
n += loff.height;
}
if (n < p_so)
if (n < so) {
return true;
}
}
return false;
}
@ -714,6 +723,8 @@ void 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).
@ -785,10 +796,10 @@ void curs_columns(
* If we get closer to the edge than 'sidescrolloff', scroll a little
* extra
*/
assert(p_siso <= INT_MAX);
int off_left = startcol - curwin->w_leftcol - (int)p_siso;
assert(siso <= INT_MAX);
int off_left = startcol - curwin->w_leftcol - (int)siso;
int off_right =
endcol - curwin->w_leftcol - curwin->w_width_inner + (int)p_siso + 1;
endcol - curwin->w_leftcol - curwin->w_width_inner + (int)siso + 1;
if (off_left < 0 || off_right > 0) {
int diff = (off_left < 0) ? -off_left: off_right;
@ -834,7 +845,7 @@ void curs_columns(
int plines = 0;
if ((curwin->w_wrow >= curwin->w_height_inner
|| ((prev_skipcol > 0
|| curwin->w_wrow + p_so >= curwin->w_height_inner)
|| curwin->w_wrow + so >= curwin->w_height_inner)
&& (plines =
plines_win_nofill(curwin, curwin->w_cursor.lnum, false)) - 1
>= curwin->w_height_inner))
@ -850,17 +861,18 @@ void curs_columns(
* 2: Less than "p_so" 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. */
}
// Compute last display line of the buffer line that we want at the
// bottom of the window.
if (plines == 0) {
plines = plines_win(curwin, curwin->w_cursor.lnum, false);
}
plines--;
if (plines > curwin->w_wrow + p_so) {
assert(p_so <= INT_MAX);
n = curwin->w_wrow + (int)p_so;
if (plines > curwin->w_wrow + so) {
assert(so <= INT_MAX);
n = curwin->w_wrow + (int)so;
} else {
n = plines;
}
@ -868,7 +880,7 @@ void curs_columns(
extra += 2;
}
if (extra == 3 || plines < p_so * 2) {
if (extra == 3 || plines < so * 2) {
// not enough room for 'scrolloff', put cursor in the middle
n = curwin->w_virtcol / width;
if (n > curwin->w_height_inner / 2) {
@ -882,9 +894,9 @@ void curs_columns(
}
curwin->w_skipcol = n * width;
} else if (extra == 1) {
/* less then 'scrolloff' lines above, decrease skipcol */
assert(p_so <= INT_MAX);
extra = (curwin->w_skipcol + (int)p_so * width - curwin->w_virtcol
// less then 'scrolloff' lines above, decrease skipcol
assert(so <= INT_MAX);
extra = (curwin->w_skipcol + (int)so * width - curwin->w_virtcol
+ width - 1) / width;
if (extra > 0) {
if ((colnr_T)(extra * width) > curwin->w_skipcol)
@ -1206,7 +1218,7 @@ void scrolldown_clamp(void)
end_row += curwin->w_cline_height - 1 -
curwin->w_virtcol / curwin->w_width_inner;
}
if (end_row < curwin->w_height_inner - p_so) {
if (end_row < curwin->w_height_inner - get_scrolloff_value()) {
if (can_fill) {
++curwin->w_topfill;
check_topfill(curwin, true);
@ -1246,14 +1258,14 @@ void scrollup_clamp(void)
validate_virtcol();
start_row -= curwin->w_virtcol / curwin->w_width_inner;
}
if (start_row >= p_so) {
if (curwin->w_topfill > 0)
--curwin->w_topfill;
else {
if (start_row >= get_scrolloff_value()) {
if (curwin->w_topfill > 0) {
curwin->w_topfill--;
} else {
(void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
++curwin->w_topline;
curwin->w_topline++;
}
++curwin->w_botline; /* approximate w_botline */
curwin->w_botline++; // approximate w_botline
curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
}
}
@ -1349,8 +1361,7 @@ void scroll_cursor_top(int min_scroll, int always)
linenr_T old_topline = curwin->w_topline;
linenr_T old_topfill = curwin->w_topfill;
linenr_T new_topline;
assert(p_so <= INT_MAX);
int off = (int)p_so;
int off = (int)get_scrolloff_value();
if (mouse_dragging > 0)
off = mouse_dragging - 1;
@ -1492,7 +1503,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
linenr_T old_botline = curwin->w_botline;
int old_valid = curwin->w_valid;
int old_empty_rows = curwin->w_empty_rows;
linenr_T cln = curwin->w_cursor.lnum; /* Cursor Line Number */
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
long so = get_scrolloff_value();
if (set_topbot) {
used = 0;
@ -1551,7 +1563,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
/* Stop when scrolled nothing or at least "min_scroll", found "extra"
* context for 'scrolloff' and counted all lines below the window. */
if ((((scrolled <= 0 || scrolled >= min_scroll)
&& extra >= (mouse_dragging > 0 ? mouse_dragging - 1 : p_so))
&& extra >= (mouse_dragging > 0 ? mouse_dragging - 1 : so))
|| boff.lnum + 1 > curbuf->b_ml.ml_line_count)
&& loff.lnum <= curwin->w_botline
&& (loff.lnum < curwin->w_botline
@ -1589,7 +1601,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
if (used > curwin->w_height_inner) {
break;
}
if (extra < (mouse_dragging > 0 ? mouse_dragging - 1 : p_so)
if (extra < (mouse_dragging > 0 ? mouse_dragging - 1 : so)
|| scrolled < min_scroll) {
extra += boff.height;
if (boff.lnum >= curwin->w_botline
@ -1724,9 +1736,8 @@ void cursor_correct(void)
* 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.
*/
assert(p_so <= INT_MAX);
int above_wanted = (int)p_so;
int below_wanted = (int)p_so;
int above_wanted = (int)get_scrolloff_value();
int below_wanted = (int)get_scrolloff_value();
if (mouse_dragging > 0) {
above_wanted = mouse_dragging - 1;
below_wanted = mouse_dragging - 1;
@ -1821,6 +1832,7 @@ int onepage(Direction 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 */
beep_flush();
@ -1836,7 +1848,7 @@ int onepage(Direction 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
&& curwin->w_topfill ==

View File

@ -2584,12 +2584,13 @@ 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) {
/* In the very first line, allow scrolling one line */
if (mouse_row == 0)
if (VIsual_active && is_drag && get_scrolloff_value()) {
// In the very first line, allow scrolling one line
if (mouse_row == 0) {
mouse_dragging = 2;
else
} else {
mouse_dragging = 1;
}
}
/* When dragging the mouse above the window, scroll down. */
@ -4089,9 +4090,9 @@ void scroll_redraw(int up, long count)
scrollup(count, true);
else
scrolldown(count, true);
if (p_so) {
/* Adjust the cursor position for 'scrolloff'. Mark w_topline as
* valid, otherwise the screen jumps back at the end of the file. */
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.
cursor_correct();
check_cursor_moved(curwin);
curwin->w_valid |= VALID_TOPLINE;
@ -4135,8 +4136,8 @@ static void nv_zet(cmdarg_T *cap)
int old_fen = curwin->w_p_fen;
bool undo = false;
assert(p_siso <= INT_MAX);
int l_p_siso = (int)p_siso;
int l_p_siso = (int)get_sidescrolloff_value();
assert(l_p_siso <= INT_MAX);
if (ascii_isdigit(nchar)) {
/*

View File

@ -904,11 +904,19 @@ set_option_default(
if (options[opt_idx].indir == PV_SCROLL) {
win_comp_scroll(curwin);
} else {
*(long *)varp = (long)(intptr_t)options[opt_idx].def_val[dvi];
long def_val = (long)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
@ -4349,7 +4357,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
}
} else if (pp == &p_so) {
if (value < 0 && full_screen) {
errmsg = e_scroll;
errmsg = e_positive;
}
} else if (pp == &p_siso) {
if (value < 0 && full_screen) {
@ -5326,20 +5334,20 @@ showoneopt(
* Write modified options as ":set" commands to a file.
*
* There are three values for "opt_flags":
* OPT_GLOBAL: Write global option values and fresh values of
* buffer-local options (used for start of a session
* file).
* OPT_GLOBAL: Write global option values and fresh values of
* buffer-local options (used for start of a session
* file).
* OPT_GLOBAL + OPT_LOCAL: Idem, add fresh values of window-local options for
* curwin (used for a vimrc file).
* OPT_LOCAL: Write buffer-local option values for curbuf, fresh
* and local values for window-local options of
* curwin. Local values are also written when at the
* default value, because a modeline or autocommand
* may have set them when doing ":edit file" and the
* user has set them back at the default or fresh
* value.
* When "local_only" is true, don't write fresh
* values, only local values (for ":mkview").
* curwin (used for a vimrc file).
* OPT_LOCAL: Write buffer-local option values for curbuf, fresh
* and local values for window-local options of
* curwin. Local values are also written when at the
* default value, because a modeline or autocommand
* may have set them when doing ":edit file" and the
* user has set them back at the default or fresh
* value.
* When "local_only" is true, don't write fresh
* values, only local values (for ":mkview").
* (fresh value = value used for a new buffer or window for a local option).
*
* Return FAIL on error, OK otherwise.
@ -5634,6 +5642,12 @@ void unset_global_local_option(char *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;
case PV_DEF:
clear_string_option(&buf->b_p_def);
break;
@ -5706,6 +5720,8 @@ static char_u *get_varp_scope(vimoption_T *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);
case PV_DEF: return (char_u *)&(curbuf->b_p_def);
case PV_INC: return (char_u *)&(curbuf->b_p_inc);
case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
@ -5750,6 +5766,10 @@ static char_u *get_varp(vimoption_T *p)
? (char_u *)&(curbuf->b_p_tags) : p->var;
case PV_TC: return *curbuf->b_p_tc != NUL
? (char_u *)&(curbuf->b_p_tc) : 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;
case PV_BKC: return *curbuf->b_p_bkc != NUL
? (char_u *)&(curbuf->b_p_bkc) : p->var;
case PV_DEF: return *curbuf->b_p_def != NUL
@ -6034,10 +6054,10 @@ void didset_window_options(win_T *wp)
* Copy global option values to local options for one buffer.
* Used when creating a new buffer and sometimes when entering a buffer.
* flags:
* BCO_ENTER We will enter the buf buffer.
* BCO_ALWAYS Always copy the options, but only set b_p_initialized when
* appropriate.
* BCO_NOHELP Don't copy the values to a help buffer.
* BCO_ENTER We will enter the buf buffer.
* BCO_ALWAYS Always copy the options, but only set b_p_initialized when
* appropriate.
* BCO_NOHELP Don't copy the values to a help buffer.
*/
void buf_copy_options(buf_T *buf, int flags)
{
@ -7485,3 +7505,18 @@ dict_T *get_winbuf_options(const int bufopt)
return d;
}
/// 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;
}

View File

@ -835,6 +835,8 @@ enum {
, WV_RLC
, WV_SCBIND
, WV_SCROLL
, WV_SISO
, WV_SO
, WV_SPELL
, WV_CUC
, WV_CUL

View File

@ -1990,7 +1990,7 @@ return {
},
{
full_name='scrolloff', abbreviation='so',
type='number', scope={'global'},
type='number', scope={'global', 'window'},
vi_def=true,
vim=true,
redraw={'all_windows'},
@ -2229,10 +2229,10 @@ return {
},
{
full_name='sidescrolloff', abbreviation='siso',
type='number', scope={'global'},
type='number', scope={'global', 'window'},
vi_def=true,
vim=true,
redraw={'current_buffer'},
redraw={'all_windows'},
varname='p_siso',
defaults={if_true={vi=0}}
},

View File

@ -2227,6 +2227,8 @@ showmatch(
pos_T *lpos, save_cursor;
pos_T mpos;
colnr_T vcol;
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;
long save_so;
long save_siso;
int save_state;
@ -2262,23 +2264,24 @@ showmatch(
&& vcol < curwin->w_leftcol + curwin->w_width_inner)) {
mpos = *lpos; // save the pos, update_screen() may change it
save_cursor = curwin->w_cursor;
save_so = p_so;
save_siso = p_siso;
/* Handle "$" in 'cpo': If the ')' is typed on top of the "$",
* stop displaying the "$". */
if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol)
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) {
dollar_vcol = -1;
++curwin->w_virtcol; /* do display ')' just before "$" */
update_screen(VALID); /* show the new char first */
}
curwin->w_virtcol++; // do display ')' just before "$"
update_screen(VALID); // show the new char first
save_dollar_vcol = dollar_vcol;
save_state = State;
State = SHOWMATCH;
ui_cursor_shape(); /* may show different cursor shape */
curwin->w_cursor = mpos; /* move to matching char */
p_so = 0; /* don't use 'scrolloff' here */
p_siso = 0; /* don't use 'sidescrolloff' here */
showruler(FALSE);
ui_cursor_shape(); // may show different cursor shape
curwin->w_cursor = mpos; // move to matching char
*so = 0; // don't use 'scrolloff' here
*siso = 0; // don't use 'sidescrolloff' here
showruler(false);
setcursor();
ui_flush();
/* Restore dollar_vcol(), because setcursor() may call curs_rows()
@ -2294,11 +2297,11 @@ showmatch(
os_delay(p_mat * 100L, true);
else if (!char_avail())
os_delay(p_mat * 100L, false);
curwin->w_cursor = save_cursor; /* restore cursor position */
p_so = save_so;
p_siso = save_siso;
curwin->w_cursor = save_cursor; // restore cursor position
*so = save_so;
*siso = save_siso;
State = save_state;
ui_cursor_shape(); /* may show different cursor shape */
ui_cursor_shape(); // may show different cursor shape
}
}
}

View File

@ -512,6 +512,41 @@ func Test_shortmess_F2()
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
func Test_visualbell()
set belloff=
set visualbell

View File

@ -4689,6 +4689,10 @@ static win_T *win_alloc(win_T *after, int hidden)
new_wp->w_floating = 0;
new_wp->w_float_config = FLOAT_CONFIG_INIT;
// use global option 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;
@ -5799,9 +5803,10 @@ void 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 */
}
curs_columns(false); // validate w_wrow
}
if (prev_height > 0) {
wp->w_prev_fraction_row = wp->w_wrow;

View File

@ -65,8 +65,6 @@ describe(':set validation', function()
should_succeed('regexpengine', 2)
should_fail('report', -1, 'E487')
should_succeed('report', 0)
should_fail('scrolloff', -1, 'E49')
should_fail('sidescrolloff', -1, 'E487')
should_fail('sidescroll', -1, 'E487')
should_fail('cmdwinheight', 0, 'E487')
should_fail('updatetime', -1, 'E487')
@ -82,6 +80,22 @@ describe(':set validation', function()
meths.set_option('window', -10)
eq(23, meths.get_option('window'))
eq('', eval("v:errmsg"))
-- 'scrolloff' and 'sidescrolloff' can have a -1 value when
-- set for the current window, but not globally
feed_command('setglobal scrolloff=-1')
eq('E487', eval("v:errmsg"):match("E%d*"))
feed_command('setglobal sidescrolloff=-1')
eq('E487', eval("v:errmsg"):match("E%d*"))
feed_command('let v:errmsg=""')
feed_command('setlocal scrolloff=-1')
eq('', eval("v:errmsg"))
feed_command('setlocal sidescrolloff=-1')
eq('', eval("v:errmsg"))
end)
it('set wmh/wh wmw/wiw checks', function()