]> granicus.if.org Git - vim/commitdiff
patch 8.1.0864: cannot have a local value for 'scrolloff' and 'sidescrolloff' v8.1.0864
authorBram Moolenaar <Bram@vim.org>
Thu, 31 Jan 2019 17:26:10 +0000 (18:26 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 31 Jan 2019 17:26:10 +0000 (18:26 +0100)
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)

16 files changed:
runtime/doc/options.txt
src/edit.c
src/ex_cmds.c
src/ex_docmd.c
src/gui.c
src/misc2.c
src/move.c
src/normal.c
src/option.c
src/option.h
src/proto/option.pro
src/search.c
src/structs.h
src/testdir/test_options.vim
src/version.c
src/window.c

index 266749006f7b21f67984f3179d8000868518418e..04c38b204174200544265ac60a2f0fd270f77deb 100644 (file)
@@ -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
index de1666cc5eef4a3e59d66ab7a029bd14419694fd..eac480314761df8a389fb9dbff557fc20966f0d3 100644 (file)
@@ -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
index 6d03d88ca7419fa3e90a7ce2cd3e623355b3602a..a3974c1bad8f89062d6e913aed125f3d36438295 100644 (file)
@@ -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 */
     }
 
index 1646a22139bbd8b1986b62d44f95cc163c8afc49..b90ea7b17c3a3b8d4a69a3b387244cdc1ef0aac4 100644 (file)
@@ -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;
            }
index 39968954a8734abd3e98df33ba446afa25aea53a..d993bc6b0098169bfdefe87eef320fa4392474cd 100644 (file)
--- 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 */
index 657e164913139f59c7b194e34eae95ea1633035b..278cc330c0ecee7f7cc62ae3435b1d115c62fe31 100644 (file)
@@ -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));
     }
 
     /*
index 14b7a6e7dc5c66bf3ea0bb0f070cce6ef6a69ea6..da29b36f54542bd8adc70cbc9e2fee098d76ee99 100644 (file)
@@ -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
index b512b559ada3beb095f52ad493fa843bfcea63db..41af966288c511f4162fb79eab652600b8c7806b 100644 (file)
@@ -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;
index abbbaa5873433596f1cfb6f24074816016d2e86f..6d2bab1e02dec7b03cc8a84db5b5267c981e3046 100644 (file)
 #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;
@@ -13098,6 +13120,26 @@ get_sts_value(void)
     return curbuf->b_p_sts < 0 ? get_sw_value(curbuf) : curbuf->b_p_sts;
 }
 
+/*
+ * 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
index c282da32532569a936e9cbcf5f6a4507767e6ddb..90c05080bd18e026a5544ed9f90ca6d4dae444da 100644 (file)
@@ -1152,6 +1152,8 @@ enum
 #endif
     , WV_SCBIND
     , WV_SCROLL
+    , WV_SISO
+    , WV_SO
 #ifdef FEAT_SPELL
     , WV_SPELL
 #endif
index 3da51c6587a428c2778c350632f587ce9bafd974..1027edf68c76f219b6e78dbdb1bb04435956be1c 100644 (file)
@@ -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);
index a4b4c4177c7c018a93509b455cc63c22f162de75..4b3f8532a55818e137c885a031ea88d1a860c8a6 100644 (file)
@@ -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 */
index ddc56bca4d8bbc5c1b80df58cbabdc5b60bedbc9..e6cc8291f18ffd775e66dc9c88ca951771431c56 100644 (file)
@@ -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))
index 740863e3cc3b0d7aa525f74eb6b141badd05730f..83b315d00e3a430133ed91145261e5675bd51dc1 100644 (file)
@@ -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
index 05b18ed7e6c6197b7afb8f82c35c541d1fcf2d6d..7a02fbdca130e71778a9ffc16b68dc4b67a09b72 100644 (file)
@@ -783,6 +783,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    864,
 /**/
     863,
 /**/
index d89f3a8e6eb6b3aa3ef96c99ddb2ed9e71a65864..f78fccafe6d9dbd4c3414dd16215a08223e33f79 100644 (file)
@@ -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 */
     }