]> granicus.if.org Git - vim/commitdiff
patch 9.0.0036: 'fillchars' cannot have window-local values v9.0.0036
authorBram Moolenaar <Bram@vim.org>
Mon, 4 Jul 2022 16:34:33 +0000 (17:34 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 4 Jul 2022 16:34:33 +0000 (17:34 +0100)
Problem:    'fillchars' cannot have window-local values.
Solution:   Make 'fillchars' global-local. (closes #5206)

19 files changed:
runtime/doc/options.txt
src/drawline.c
src/drawscreen.c
src/globals.h
src/mbyte.c
src/mouse.c
src/option.c
src/option.h
src/optiondefs.h
src/optionstr.c
src/proto/screen.pro
src/screen.c
src/structs.h
src/testdir/dumps/Test_display_fillchars_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_display_fillchars_2.dump [new file with mode: 0644]
src/testdir/runtest.vim
src/testdir/screendump.vim
src/testdir/test_display.vim
src/version.c

index 1d14c44333746b4a11b30027a05383fb98cc6334..cef9bd5503a4b747eeb2b620d45daa4589bbb85b 100644 (file)
@@ -3376,22 +3376,24 @@ A jump table for the options with a short description can be found at |Q_op|.
 
                                                *'fillchars'* *'fcs'*
 'fillchars' 'fcs'      string  (default "vert:|,fold:-,eob:~")
-                       global
+                       global or local to window |global-local|
                        {not available when compiled without the |+folding|
                        feature}
-       Characters to fill the statuslines and vertical separators.
-       It is a comma-separated list of items:
-
-         item          default         Used for ~
-         stl:c         ' ' or '^'      statusline of the current window
-         stlnc:c       ' ' or '='      statusline of the non-current windows
-         vert:c        '|'             vertical separators |:vsplit|
-         fold:c        '-'             filling 'foldtext'
-         foldopen:c    '-'             mark the beginning of a fold
-         foldclose:c   '+'             show a closed fold
-         foldsep:c     '|'             open fold middle character
-         diff:c        '-'             deleted lines of the 'diff' option
-         eob:c         '~'             empty lines below the end of a buffer
+       Characters to fill the statuslines, vertical separators and special
+       lines in the window.
+       It is a comma-separated list of items.  Each item has a name, a colon
+       and the value of that item:
+
+         item name     default         Used for ~
+         stl           ' ' or '^'      statusline of the current window
+         stlnc         ' ' or '='      statusline of the non-current windows
+         vert          '|'             vertical separators |:vsplit|
+         fold          '-'             filling 'foldtext'
+         foldopen      '-'             mark the beginning of a fold
+         foldclose     '+'             show a closed fold
+         foldsep       '|'             open fold middle character
+         diff          '-'             deleted lines of the 'diff' option
+         eob           '~'             empty lines below the end of a buffer
 
        Any one that is omitted will fall back to the default.  For "stl" and
        "stlnc" the space will be used when there is highlighting, '^' or '='
@@ -3407,13 +3409,13 @@ A jump table for the options with a short description can be found at |Q_op|.
        characters are not supported.
 
        The highlighting used for these items:
-         item          highlight group ~
-         stl:c         StatusLine              |hl-StatusLine|
-         stlnc:c       StatusLineNC            |hl-StatusLineNC|
-         vert:c        VertSplit               |hl-VertSplit|
-         fold:c        Folded                  |hl-Folded|
-         diff:c        DiffDelete              |hl-DiffDelete|
-         eob:c         EndOfBuffer             |hl-EndOfBuffer|
+         item name     highlight group ~
+         stl           StatusLine              |hl-StatusLine|
+         stlnc         StatusLineNC            |hl-StatusLineNC|
+         vert          VertSplit               |hl-VertSplit|
+         fold          Folded                  |hl-Folded|
+         diff          DiffDelete              |hl-DiffDelete|
+         eob           EndOfBuffer             |hl-EndOfBuffer|
 
                *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
 'fixendofline' 'fixeol'        boolean (default on)
index d87d800eff9919fe63f8f1f2dda326c7634d900d..789893b0b2bba3372c0eea7473444f9b57523657 100644 (file)
@@ -1268,14 +1268,14 @@ win_line(
                if (filler_todo > 0)
                {
                    // Draw "deleted" diff line(s).
-                   if (char2cells(fill_diff) > 1)
+                   if (char2cells(wp->w_fill_chars.diff) > 1)
                    {
                        c_extra = '-';
                        c_final = NUL;
                    }
                    else
                    {
-                       c_extra = fill_diff;
+                       c_extra = wp->w_fill_chars.diff;
                        c_final = NUL;
                    }
 #  ifdef FEAT_RIGHTLEFT
@@ -1352,7 +1352,7 @@ win_line(
 #endif
                )
        {
-           screen_line(screen_row, wp->w_wincol, col, -wp->w_width,
+           screen_line(wp, screen_row, wp->w_wincol, col, -wp->w_width,
                                                            screen_line_flags);
            // Pretend we have finished updating the window.  Except when
            // 'cursorcolumn' is set.
@@ -2859,7 +2859,7 @@ win_line(
            }
 #endif
 
-           screen_line(screen_row, wp->w_wincol, col,
+           screen_line(wp, screen_row, wp->w_wincol, col,
                                          wp->w_width, screen_line_flags);
            row++;
 
@@ -3160,11 +3160,11 @@ win_line(
                )
        {
 #ifdef FEAT_CONCEAL
-           screen_line(screen_row, wp->w_wincol, col - boguscols,
+           screen_line(wp, screen_row, wp->w_wincol, col - boguscols,
                                          wp->w_width, screen_line_flags);
            boguscols = 0;
 #else
-           screen_line(screen_row, wp->w_wincol, col,
+           screen_line(wp, screen_row, wp->w_wincol, col,
                                          wp->w_width, screen_line_flags);
 #endif
            ++row;
index 4fea562fcf368eb03499f6a5acce2387fe0a8dd8..d1157043ea88b045f197afd90e9d9fc1444de91c 100644 (file)
@@ -555,7 +555,7 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
        if (stl_connected(wp))
            fillchar = fillchar_status(&attr, wp);
        else
-           fillchar = fillchar_vsep(&attr);
+           fillchar = fillchar_vsep(&attr, wp);
        screen_putchar(fillchar, row, W_ENDCOL(wp), attr);
     }
     busy = FALSE;
@@ -1038,7 +1038,7 @@ redraw_win_toolbar(win_T *wp)
     }
     wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker
 
-    screen_line(wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, 0);
+    screen_line(wp, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, 0);
 }
 #endif
 
@@ -1246,7 +1246,8 @@ fold_line(
 
     txtcol = col;      // remember where text starts
 
-    // 5. move the text to current_ScreenLine.  Fill up with "fill_fold".
+    // 5. move the text to current_ScreenLine.  Fill up with "fold" from
+    //    'fillchars'.
     //    Right-left text is put in columns 0 - number-col, normal text is put
     //    in columns number-col - window-width.
     col = text_to_screenline(wp, text, col);
@@ -1262,23 +1263,25 @@ fold_line(
 #endif
            )
     {
+       int c = wp->w_fill_chars.fold;
+
        if (enc_utf8)
        {
-           if (fill_fold >= 0x80)
+           if (c >= 0x80)
            {
-               ScreenLinesUC[off + col] = fill_fold;
+               ScreenLinesUC[off + col] = c;
                ScreenLinesC[0][off + col] = 0;
                ScreenLines[off + col] = 0x80; // avoid storing zero
            }
            else
            {
                ScreenLinesUC[off + col] = 0;
-               ScreenLines[off + col] = fill_fold;
+               ScreenLines[off + col] = c;
            }
            col++;
        }
        else
-           ScreenLines[off + col++] = fill_fold;
+           ScreenLines[off + col++] = c;
     }
 
     if (text != buf)
@@ -1371,7 +1374,8 @@ fold_line(
     }
 #endif
 
-    screen_line(row + W_WINROW(wp), wp->w_wincol, wp->w_width, wp->w_width, 0);
+    screen_line(wp, row + W_WINROW(wp), wp->w_wincol,
+                                                 wp->w_width, wp->w_width, 0);
 
     // Update w_cline_height and w_cline_folded if the cursor line was
     // updated (saves a call to plines() later).
@@ -2669,10 +2673,10 @@ win_update(win_T *wp)
            if (j > 0 && !wp->w_botfill)
            {
                // Display filler lines at the end of the file.
-               if (char2cells(fill_diff) > 1)
+               if (char2cells(wp->w_fill_chars.diff) > 1)
                    i = '-';
                else
-                   i = fill_diff;
+                   i = wp->w_fill_chars.diff;
                if (row + j > wp->w_height)
                    j = wp->w_height - row;
                win_draw_end(wp, i, i, TRUE, row, row + (int)j, HLF_DED);
@@ -2683,12 +2687,14 @@ win_update(win_T *wp)
        else if (dollar_vcol == -1)
            wp->w_botline = lnum;
 
-       // Make sure the rest of the screen is blank
-       // write the 'fill_eob' character to rows that aren't part of the file
+       // Make sure the rest of the screen is blank.
+       // write the "eob" character from 'fillchars' to rows that aren't part
+       // of the file.
        if (WIN_IS_POPUP(wp))
            win_draw_end(wp, ' ', ' ', FALSE, row, wp->w_height, HLF_AT);
        else
-           win_draw_end(wp, fill_eob, ' ', FALSE, row, wp->w_height, HLF_EOB);
+           win_draw_end(wp, wp->w_fill_chars.eob, ' ', FALSE,
+                                                  row, wp->w_height, HLF_EOB);
     }
 
 #ifdef SYN_TIME_LIMIT
@@ -3026,7 +3032,7 @@ redraw_asap(int type)
                    mch_memmove(ScreenLines2 + off,
                                screenline2 + r * cols,
                                (size_t)cols * sizeof(schar_T));
-               screen_line(cmdline_row + r, 0, cols, cols, 0);
+               screen_line(curwin, cmdline_row + r, 0, cols, cols, 0);
            }
            ret = 4;
        }
index ad563e4e9625e535c15e9ffbec9c2ff75dac4cfd..6f2a1a5cd5ea5080817220f4f9794bbfa2b3a07e 100644 (file)
@@ -1380,17 +1380,6 @@ EXTERN char_u    *homedir INIT(= NULL);
 // directory is not a local directory, globaldir is NULL.
 EXTERN char_u  *globaldir INIT(= NULL);
 
-// Characters from 'fillchars' option
-EXTERN int     fill_stl INIT(= ' ');
-EXTERN int     fill_stlnc INIT(= ' ');
-EXTERN int     fill_vert INIT(= ' ');
-EXTERN int     fill_fold INIT(= '-');
-EXTERN int     fill_foldopen INIT(= '-');
-EXTERN int     fill_foldclosed INIT(= '+');
-EXTERN int     fill_foldsep INIT(= '|');
-EXTERN int     fill_diff INIT(= '-');
-EXTERN int     fill_eob INIT(= '~');
-
 #ifdef FEAT_FOLDING
 EXTERN int     disable_fold_update INIT(= 0);
 #endif
index 3656880e23f815d7a2c79c3eba6549bb939be995..1e3ef72a3633af8996633540eaa032b5642bd078 100644 (file)
@@ -4229,8 +4229,7 @@ theend:
 #if defined(FEAT_GUI_GTK) || defined(FEAT_SPELL) || defined(PROTO)
 /*
  * Return TRUE if string "s" is a valid utf-8 string.
- * When "end" is NULL stop at the first NUL.
- * When "end" is positive stop there.
+ * When "end" is NULL stop at the first NUL.  Otherwise stop at "end".
  */
     int
 utf_valid_string(char_u *s, char_u *end)
@@ -5529,6 +5528,7 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
     cw_interval_T   *table;
     cw_interval_T   *cw_table_save;
     size_t         cw_table_size_save;
+    char           *error = NULL;
 
     if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
        return;
@@ -5648,30 +5648,36 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED)
     // Check that the new value does not conflict with 'fillchars' or
     // 'listchars'.
     if (set_chars_option(curwin, &p_fcs) != NULL)
-    {
-       emsg(_(e_conflicts_with_value_of_fillchars));
-       cw_table = cw_table_save;
-       cw_table_size = cw_table_size_save;
-       vim_free(table);
-       return;
-    }
+       error = e_conflicts_with_value_of_fillchars;
+    else if (set_chars_option(curwin, &p_lcs) != NULL)
+       error = e_conflicts_with_value_of_listchars;
     else
     {
-       tabpage_T       *tp;
-       win_T   *wp;
+       tabpage_T   *tp;
+       win_T       *wp;
 
        FOR_ALL_TAB_WINDOWS(tp, wp)
        {
            if (set_chars_option(wp, &wp->w_p_lcs) != NULL)
            {
-               emsg((e_conflicts_with_value_of_listchars));
-               cw_table = cw_table_save;
-               cw_table_size = cw_table_size_save;
-               vim_free(table);
-               return;
+               error = e_conflicts_with_value_of_listchars;
+               break;
+           }
+           if (set_chars_option(wp, &wp->w_p_fcs) != NULL)
+           {
+               error = e_conflicts_with_value_of_fillchars;
+               break;
            }
        }
     }
+    if (error != NULL)
+    {
+       emsg(_(error));
+       cw_table = cw_table_save;
+       cw_table_size = cw_table_size_save;
+       vim_free(table);
+       return;
+    }
 
     vim_free(cw_table_save);
 }
index 2297f81826d2b52f6953a56dae2fb9054ec87cf4..b01160952eeab90ceffae1122588ef8d5720c96e 100644 (file)
@@ -2018,7 +2018,7 @@ retnomove:
        count |= CURSOR_MOVED;          // Cursor has moved
 
 # ifdef FEAT_FOLDING
-    if (mouse_char == fill_foldclosed)
+    if (mouse_char == curwin->w_fill_chars.foldclosed)
        count |= MOUSE_FOLD_OPEN;
     else if (mouse_char != ' ')
        count |= MOUSE_FOLD_CLOSE;
index 4a15c51b9897a33b1122e9b154657dd3889f0385..dd4ed1b4f52b8cf87595361ffa51f671c8f70c42 100644 (file)
@@ -2436,7 +2436,7 @@ didset_options2(void)
     (void)set_chars_option(curwin, &curwin->w_p_lcs);
 
     // Parse default for 'fillchars'.
-    (void)set_chars_option(curwin, &p_fcs);
+    (void)set_chars_option(curwin, &curwin->w_p_fcs);
 
 #ifdef FEAT_CLIPBOARD
     // Parse default for 'clipboard'
@@ -5207,6 +5207,11 @@ unset_global_local_option(char_u *name, void *from)
            set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs);
            redraw_later(NOT_VALID);
            break;
+       case PV_FCS:
+           clear_string_option(&((win_T *)from)->w_p_fcs);
+           set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs);
+           redraw_later(NOT_VALID);
+           break;
        case PV_VE:
            clear_string_option(&((win_T *)from)->w_p_ve);
            ((win_T *)from)->w_ve_flags = 0;
@@ -5272,6 +5277,7 @@ get_varp_scope(struct vimoption *p, int scope)
            case PV_BKC:  return (char_u *)&(curbuf->b_p_bkc);
            case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
            case PV_LCS:  return (char_u *)&(curwin->w_p_lcs);
+           case PV_FCS:  return (char_u *)&(curwin->w_p_fcs);
            case PV_VE:   return (char_u *)&(curwin->w_p_ve);
 
        }
@@ -5375,6 +5381,8 @@ get_varp(struct vimoption *p)
        case PV_LIST:   return (char_u *)&(curwin->w_p_list);
        case PV_LCS:    return *curwin->w_p_lcs != NUL
                                    ? (char_u *)&(curwin->w_p_lcs) : p->var;
+       case PV_FCS:    return *curwin->w_p_fcs != NUL
+                                   ? (char_u *)&(curwin->w_p_fcs) : p->var;
        case PV_VE:     return *curwin->w_p_ve != NUL
                                    ? (char_u *)&(curwin->w_p_ve) : p->var;
 #ifdef FEAT_SPELL
@@ -5600,6 +5608,15 @@ after_copy_winopt(win_T *wp)
     check_colorcolumn(wp);
 #endif
     set_chars_option(wp, &wp->w_p_lcs);
+    set_chars_option(wp, &wp->w_p_fcs);
+}
+
+    static char_u *
+copy_option_val(char_u *val)
+{
+    if (val == empty_option)
+       return empty_option;  // no need to allocate memory
+    return vim_strsave(val);
 }
 
 /*
@@ -5615,23 +5632,24 @@ copy_winopt(winopt_T *from, winopt_T *to)
     to->wo_arab = from->wo_arab;
 #endif
     to->wo_list = from->wo_list;
-    to->wo_lcs = vim_strsave(from->wo_lcs);
+    to->wo_lcs = copy_option_val(from->wo_lcs);
+    to->wo_fcs = copy_option_val(from->wo_fcs);
     to->wo_nu = from->wo_nu;
     to->wo_rnu = from->wo_rnu;
-    to->wo_ve = vim_strsave(from->wo_ve);
+    to->wo_ve = copy_option_val(from->wo_ve);
     to->wo_ve_flags = from->wo_ve_flags;
 #ifdef FEAT_LINEBREAK
     to->wo_nuw = from->wo_nuw;
 #endif
 #ifdef FEAT_RIGHTLEFT
     to->wo_rl  = from->wo_rl;
-    to->wo_rlc = vim_strsave(from->wo_rlc);
+    to->wo_rlc = copy_option_val(from->wo_rlc);
 #endif
 #ifdef FEAT_LINEBREAK
-    to->wo_sbr = vim_strsave(from->wo_sbr);
+    to->wo_sbr = copy_option_val(from->wo_sbr);
 #endif
 #ifdef FEAT_STL_OPT
-    to->wo_stl = vim_strsave(from->wo_stl);
+    to->wo_stl = copy_option_val(from->wo_stl);
 #endif
     to->wo_wrap = from->wo_wrap;
 #ifdef FEAT_DIFF
@@ -5640,9 +5658,9 @@ copy_winopt(winopt_T *from, winopt_T *to)
 #ifdef FEAT_LINEBREAK
     to->wo_lbr = from->wo_lbr;
     to->wo_bri = from->wo_bri;
-    to->wo_briopt = vim_strsave(from->wo_briopt);
+    to->wo_briopt = copy_option_val(from->wo_briopt);
 #endif
-    to->wo_wcr = vim_strsave(from->wo_wcr);
+    to->wo_wcr = copy_option_val(from->wo_wcr);
     to->wo_scb = from->wo_scb;
     to->wo_scb_save = from->wo_scb_save;
     to->wo_crb = from->wo_crb;
@@ -5653,42 +5671,42 @@ copy_winopt(winopt_T *from, winopt_T *to)
 #ifdef FEAT_SYN_HL
     to->wo_cuc = from->wo_cuc;
     to->wo_cul = from->wo_cul;
-    to->wo_culopt = vim_strsave(from->wo_culopt);
-    to->wo_cc = vim_strsave(from->wo_cc);
+    to->wo_culopt = copy_option_val(from->wo_culopt);
+    to->wo_cc = copy_option_val(from->wo_cc);
 #endif
 #ifdef FEAT_DIFF
     to->wo_diff = from->wo_diff;
     to->wo_diff_saved = from->wo_diff_saved;
 #endif
 #ifdef FEAT_CONCEAL
-    to->wo_cocu = vim_strsave(from->wo_cocu);
+    to->wo_cocu = copy_option_val(from->wo_cocu);
     to->wo_cole = from->wo_cole;
 #endif
 #ifdef FEAT_TERMINAL
-    to->wo_twk = vim_strsave(from->wo_twk);
-    to->wo_tws = vim_strsave(from->wo_tws);
+    to->wo_twk = copy_option_val(from->wo_twk);
+    to->wo_tws = copy_option_val(from->wo_tws);
 #endif
 #ifdef FEAT_FOLDING
     to->wo_fdc = from->wo_fdc;
     to->wo_fdc_save = from->wo_fdc_save;
     to->wo_fen = from->wo_fen;
     to->wo_fen_save = from->wo_fen_save;
-    to->wo_fdi = vim_strsave(from->wo_fdi);
+    to->wo_fdi = copy_option_val(from->wo_fdi);
     to->wo_fml = from->wo_fml;
     to->wo_fdl = from->wo_fdl;
     to->wo_fdl_save = from->wo_fdl_save;
-    to->wo_fdm = vim_strsave(from->wo_fdm);
+    to->wo_fdm = copy_option_val(from->wo_fdm);
     to->wo_fdm_save = from->wo_diff_saved
-                             ? vim_strsave(from->wo_fdm_save) : empty_option;
+                              ? vim_strsave(from->wo_fdm_save) : empty_option;
     to->wo_fdn = from->wo_fdn;
 # ifdef FEAT_EVAL
-    to->wo_fde = vim_strsave(from->wo_fde);
-    to->wo_fdt = vim_strsave(from->wo_fdt);
+    to->wo_fde = copy_option_val(from->wo_fde);
+    to->wo_fdt = copy_option_val(from->wo_fdt);
 # endif
-    to->wo_fmr = vim_strsave(from->wo_fmr);
+    to->wo_fmr = copy_option_val(from->wo_fmr);
 #endif
 #ifdef FEAT_SIGNS
-    to->wo_scl = vim_strsave(from->wo_scl);
+    to->wo_scl = copy_option_val(from->wo_scl);
 #endif
 
 #ifdef FEAT_EVAL
@@ -5753,6 +5771,7 @@ check_winopt(winopt_T *wop UNUSED)
 #endif
     check_string_option(&wop->wo_wcr);
     check_string_option(&wop->wo_lcs);
+    check_string_option(&wop->wo_fcs);
     check_string_option(&wop->wo_ve);
 }
 
@@ -5800,6 +5819,7 @@ clear_winopt(winopt_T *wop UNUSED)
     clear_string_option(&wop->wo_tws);
 #endif
     clear_string_option(&wop->wo_lcs);
+    clear_string_option(&wop->wo_fcs);
     clear_string_option(&wop->wo_ve);
 }
 
index 815a1156e2a157f09ad121a889a9226598285291..5ac54efc6d4a41163cf85d031514c3c8c50e17bc 100644 (file)
@@ -1238,6 +1238,7 @@ enum
 {
     WV_LIST = 0
     , WV_LCS
+    , WV_FCS
 #ifdef FEAT_ARABIC
     , WV_ARAB
 #endif
index 03e472ff9e312d011bca1649b19d41ac19efb9e3..912209c025c94adb35cf93774e10bed5dade371c 100644 (file)
 # define PV_LBR                OPT_WIN(WV_LBR)
 #endif
 #define PV_LCS         OPT_BOTH(OPT_WIN(WV_LCS))
+#define PV_FCS         OPT_BOTH(OPT_WIN(WV_FCS))
 #define PV_NU          OPT_WIN(WV_NU)
 #define PV_RNU         OPT_WIN(WV_RNU)
 #define PV_VE          OPT_BOTH(OPT_WIN(WV_VE))
@@ -947,7 +948,7 @@ static struct vimoption options[] =
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"fillchars",   "fcs",  P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_fcs, PV_NONE,
+                           (char_u *)&p_fcs, PV_FCS,
                            {(char_u *)"vert:|,fold:-,eob:~", (char_u *)0L}
                            SCTX_INIT},
     {"fixendofline",  "fixeol", P_BOOL|P_VI_DEF|P_RSTAT,
index c26667a2bc5b8db059dca755dcc752748e5e9893..43b7e5097348a3b3150a1a6792a8950d1fb73919 100644 (file)
@@ -1311,7 +1311,7 @@ ambw_end:
        if (errmsg == NULL)
        {
            tabpage_T   *tp;
-           win_T               *wp;
+           win_T       *wp;
 
            // The current window is set to use the global 'listchars' value.
            // So clear the window-local value.
@@ -1320,18 +1320,40 @@ ambw_end:
            FOR_ALL_TAB_WINDOWS(tp, wp)
                // If no error was returned above, we don't expect an error
                // here, so ignore the return value.
-               (void)set_chars_option(wp, &wp->w_p_lcs);
+               if (*wp->w_p_lcs == NUL)
+                   (void)set_chars_option(wp, &wp->w_p_lcs);
 
            redraw_all_later(NOT_VALID);
        }
     }
-
     // local 'listchars'
     else if (varp == &curwin->w_p_lcs)
        errmsg = set_chars_option(curwin, varp);
 
     // 'fillchars'
     else if (varp == &p_fcs)
+    {
+       errmsg = set_chars_option(curwin, varp);
+       if (errmsg == NULL)
+       {
+           tabpage_T   *tp;
+           win_T       *wp;
+
+           // The current window is set to use the global 'fillchars' value.
+           // So clear the window-local value.
+           if (!(opt_flags & OPT_GLOBAL))
+               clear_string_option(&curwin->w_p_fcs);
+           FOR_ALL_TAB_WINDOWS(tp, wp)
+               // If no error was returned above, we don't expect an error
+               // here, so ignore the return value.
+               if (*wp->w_p_fcs == NUL)
+                   (void)set_chars_option(wp, &wp->w_p_fcs);
+
+           redraw_all_later(NOT_VALID);
+       }
+    }
+    // local 'fillchars'
+    else if (varp == &curwin->w_p_fcs)
     {
        errmsg = set_chars_option(curwin, varp);
     }
index 0ee1b5efb028db48d1359040f2e30923a178e807..de42c43de47be44d55c32443d2444261c606cb52 100644 (file)
@@ -7,7 +7,7 @@ int compute_foldcolumn(win_T *wp, int col);
 size_t fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum);
 int screen_get_current_line_off(void);
 void reset_screen_attr(void);
-void screen_line(int row, int coloff, int endcol, int clear_width, int flags);
+void screen_line(win_T *wp, int row, int coloff, int endcol, int clear_width, int flags);
 void rl_mirror(char_u *str);
 void draw_vsep_win(win_T *wp, int row);
 void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, int match, int showtail);
@@ -48,7 +48,7 @@ void clearmode(void);
 void draw_tabline(void);
 void get_trans_bufname(buf_T *buf);
 int fillchar_status(int *attr, win_T *wp);
-int fillchar_vsep(int *attr);
+int fillchar_vsep(int *attr, win_T *wp);
 int redrawing(void);
 int messaging(void);
 void comp_col(void);
index 01518882f29b45b62b3589d4b28289e11b84a55f..1ddafb3b37e486b89bfc10f1f2a9b3547c7eec51 100644 (file)
@@ -285,9 +285,9 @@ fill_foldcolumn(
     {
        if (win_foldinfo.fi_lnum == lnum
                && first_level + i >= win_foldinfo.fi_low_level)
-           symbol = fill_foldopen;
+           symbol = wp->w_fill_chars.foldopen;
        else if (first_level == 1)
-           symbol = fill_foldsep;
+           symbol = wp->w_fill_chars.foldsep;
        else if (first_level + i <= 9)
            symbol = '0' + first_level + i;
        else
@@ -312,7 +312,7 @@ fill_foldcolumn(
                // for a multibyte character, erase all the bytes
                vim_memset(p + byte_counter, ' ', len);
        }
-       symbol = fill_foldclosed;
+       symbol = wp->w_fill_chars.foldclosed;
        len = utf_char2bytes(symbol, &p[byte_counter]);
        byte_counter += len;
     }
@@ -430,11 +430,12 @@ reset_screen_attr(void)
  */
     void
 screen_line(
-    int            row,
-    int            coloff,
-    int            endcol,
-    int            clear_width,
-    int            flags UNUSED)
+       win_T   *wp,
+       int     row,
+       int     coloff,
+       int     endcol,
+       int     clear_width,
+       int     flags UNUSED)
 {
     unsigned       off_from;
     unsigned       off_to;
@@ -794,7 +795,7 @@ screen_line(
            {
                int c;
 
-               c = fillchar_vsep(&hl);
+               c = fillchar_vsep(&hl, wp);
                if (ScreenLines[off_to] != (schar_T)c
                        || (enc_utf8 && (int)ScreenLinesUC[off_to]
                                                        != (c >= 0x80 ? c : 0))
@@ -853,7 +854,7 @@ draw_vsep_win(win_T *wp, int row)
     if (wp->w_vsep_width)
     {
        // draw the vertical separator right of this window
-       c = fillchar_vsep(&hl);
+       c = fillchar_vsep(&hl, wp);
        screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
                W_ENDCOL(wp), W_ENDCOL(wp) + 1,
                c, ' ', hl);
@@ -4619,12 +4620,12 @@ fillchar_status(int *attr, win_T *wp)
        if (wp == curwin)
        {
            *attr = HL_ATTR(HLF_ST);
-           fill = fill_stl;
+           fill = wp->w_fill_chars.stl;
        }
        else
        {
            *attr = HL_ATTR(HLF_STNC);
-           fill = fill_stlnc;
+           fill = wp->w_fill_chars.stlnc;
        }
     }
     else
@@ -4632,19 +4633,19 @@ fillchar_status(int *attr, win_T *wp)
     if (wp == curwin)
     {
        *attr = HL_ATTR(HLF_S);
-       fill = fill_stl;
+       fill = wp->w_fill_chars.stl;
     }
     else
     {
        *attr = HL_ATTR(HLF_SNC);
-       fill = fill_stlnc;
+       fill = wp->w_fill_chars.stlnc;
     }
     // Use fill when there is highlighting, and highlighting of current
     // window differs, or the fillchars differ, or this is not the
     // current window
     if (*attr != 0 && ((HL_ATTR(HLF_S) != HL_ATTR(HLF_SNC)
                        || wp != curwin || ONE_WINDOW)
-                   || (fill_stl != fill_stlnc)))
+                   || (wp->w_fill_chars.stl != wp->w_fill_chars.stlnc)))
        return fill;
     if (wp == curwin)
        return '^';
@@ -4656,13 +4657,13 @@ fillchar_status(int *attr, win_T *wp)
  * Get its attributes in "*attr".
  */
     int
-fillchar_vsep(int *attr)
+fillchar_vsep(int *attr, win_T *wp)
 {
     *attr = HL_ATTR(HLF_C);
-    if (*attr == 0 && fill_vert == ' ')
+    if (*attr == 0 && wp->w_fill_chars.vert == ' ')
        return '|';
     else
-       return fill_vert;
+       return wp->w_fill_chars.vert;
 }
 
 /*
@@ -4848,29 +4849,30 @@ get_encoded_char_adv(char_u **p)
     char *
 set_chars_option(win_T *wp, char_u **varp)
 {
-    int                round, i, len, len2, entries;
-    char_u     *p, *s;
-    int                c1 = 0, c2 = 0, c3 = 0;
-    char_u     *last_multispace = NULL; // Last occurrence of "multispace:"
-    char_u     *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
-    int                multispace_len = 0;      // Length of lcs-multispace string
-    int                lead_multispace_len = 0; // Length of lcs-leadmultispace string
+    int            round, i, len, len2, entries;
+    char_u  *p, *s;
+    int            c1 = 0, c2 = 0, c3 = 0;
+    char_u  *last_multispace = NULL;  // Last occurrence of "multispace:"
+    char_u  *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
+    int            multispace_len = 0;       // Length of lcs-multispace string
+    int            lead_multispace_len = 0;  // Length of lcs-leadmultispace string
     struct charstab
     {
        int     *cp;
        char    *name;
     };
+    static fill_chars_T fill_chars;
     static struct charstab filltab[] =
     {
-       {&fill_stl,             "stl"},
-       {&fill_stlnc,           "stlnc"},
-       {&fill_vert,            "vert"},
-       {&fill_fold,            "fold"},
-       {&fill_foldopen,        "foldopen"},
-       {&fill_foldclosed,      "foldclose"},
-       {&fill_foldsep,         "foldsep"},
-       {&fill_diff,            "diff"},
-       {&fill_eob,             "eob"},
+       {&fill_chars.stl,       "stl"},
+       {&fill_chars.stlnc,     "stlnc"},
+       {&fill_chars.vert,      "vert"},
+       {&fill_chars.fold,      "fold"},
+       {&fill_chars.foldopen,  "foldopen"},
+       {&fill_chars.foldclosed, "foldclose"},
+       {&fill_chars.foldsep,   "foldsep"},
+       {&fill_chars.diff,      "diff"},
+       {&fill_chars.eob,       "eob"},
     };
     static lcs_chars_T lcs_chars;
     struct charstab lcstab[] =
@@ -4903,6 +4905,8 @@ set_chars_option(win_T *wp, char_u **varp)
     {
        tab = filltab;
        entries = ARRAY_LENGTH(filltab);
+       if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL)
+           varp = &p_fcs;
     }
 
     // first round: check for valid value, second round: assign values
@@ -4910,15 +4914,12 @@ set_chars_option(win_T *wp, char_u **varp)
     {
        if (round > 0)
        {
-           // After checking that the value is valid: set defaults: space for
-           // 'fillchars', NUL for 'listchars'
-           for (i = 0; i < entries; ++i)
-               if (tab[i].cp != NULL)
-                   *(tab[i].cp) =
-                       ((varp == &p_lcs || varp == &wp->w_p_lcs) ? NUL : ' ');
-
+           // After checking that the value is valid: set defaults.
            if (varp == &p_lcs || varp == &wp->w_p_lcs)
            {
+               for (i = 0; i < entries; ++i)
+                   if (tab[i].cp != NULL)
+                       *(tab[i].cp) = NUL;
                lcs_chars.tab1 = NUL;
                lcs_chars.tab3 = NUL;
 
@@ -4932,7 +4933,8 @@ set_chars_option(win_T *wp, char_u **varp)
 
                if (lead_multispace_len > 0)
                {
-                   lcs_chars.leadmultispace = ALLOC_MULT(int, lead_multispace_len + 1);
+                   lcs_chars.leadmultispace =
+                                     ALLOC_MULT(int, lead_multispace_len + 1);
                    lcs_chars.leadmultispace[lead_multispace_len] = NUL;
                }
                else
@@ -4940,11 +4942,15 @@ set_chars_option(win_T *wp, char_u **varp)
            }
            else
            {
-               fill_diff = '-';
-               fill_foldopen = '-';
-               fill_foldclosed = '+';
-               fill_foldsep = '|';
-               fill_eob = '~';
+               fill_chars.stl = ' ';
+               fill_chars.stlnc = ' ';
+               fill_chars.vert = ' ';
+               fill_chars.fold = '-';
+               fill_chars.foldopen = '-';
+               fill_chars.foldclosed = '+';
+               fill_chars.foldsep = '|';
+               fill_chars.diff = '-';
+               fill_chars.eob = '~';
            }
        }
        p = *varp;
@@ -5083,12 +5089,17 @@ set_chars_option(win_T *wp, char_u **varp)
                ++p;
        }
     }
+
     if (tab == lcstab)
     {
        vim_free(wp->w_lcs_chars.multispace);
        vim_free(wp->w_lcs_chars.leadmultispace);
        wp->w_lcs_chars = lcs_chars;
     }
+    else
+    {
+       wp->w_fill_chars = fill_chars;
+    }
 
     return NULL;       // no error
 }
index a537ccb8fdc0c2215b1818bd83edda8ddc065a46..11c3726f0432dbda5039af83395eefaa6c82c609 100644 (file)
@@ -232,6 +232,8 @@ typedef struct
 #define w_p_list w_onebuf_opt.wo_list  // 'list'
     char_u     *wo_lcs;
 #define w_p_lcs w_onebuf_opt.wo_lcs    // 'listchars'
+    char_u     *wo_fcs;
+#define w_p_fcs w_onebuf_opt.wo_fcs    // 'fillchars'
     int                wo_nu;
 #define w_p_nu w_onebuf_opt.wo_nu      // 'number'
     int                wo_rnu;
@@ -3418,6 +3420,22 @@ typedef struct
 #endif
 } lcs_chars_T;
 
+/*
+ * Characters from the 'fillchars' option
+ */
+typedef struct
+{
+    int        stl;
+    int        stlnc;
+    int        vert;
+    int        fold;
+    int        foldopen;
+    int        foldclosed;
+    int        foldsep;
+    int        diff;
+    int        eob;
+} fill_chars_T;
+
 /*
  * Structure which contains all information that belongs to a window
  *
@@ -3470,6 +3488,7 @@ struct window_S
                                         // redrawn
 
     lcs_chars_T        w_lcs_chars;        // 'listchars' characters
+    fill_chars_T w_fill_chars;     // 'fillchars' characters
 
     /*
      * "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
diff --git a/src/testdir/dumps/Test_display_fillchars_1.dump b/src/testdir/dumps/Test_display_fillchars_1.dump
new file mode 100644 (file)
index 0000000..b0b1642
--- /dev/null
@@ -0,0 +1,12 @@
+|w+0&#ffffff0|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|w|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|w|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|y+0#4040ff13&| @35|++1#0000000&|x+0#4040ff13&| @35
+|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]|b@5|1|,|1|b@11|A|l@1|b|[|N|o| |N|a|m|e|]| |[|+|]|a@5|1|,|1|a@11|A|l@1
+>w+0&&|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|w|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|w|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|o+0#4040ff13&| @35|>+1#0000000&|z+0#4040ff13&| @35
+|o| @35|>+1#0000000&|z+0#4040ff13&| @35
+|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]|4@5|1|,|1|4@11|A|l@1|4|[+1&&|N|o| |N|a|m|e|]| |[|+|]|c@5|1|,|1|c@11|A|l@1
+| +0&&@74
diff --git a/src/testdir/dumps/Test_display_fillchars_2.dump b/src/testdir/dumps/Test_display_fillchars_2.dump
new file mode 100644 (file)
index 0000000..b983fac
--- /dev/null
@@ -0,0 +1,12 @@
+>w+0&#ffffff0|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|w|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|w|i|n|d|o|w| |2| @28|++1&&|w+0&&|i|n|d|o|w| |1| @28
+|y+0#4040ff13&| @35|++1#0000000&|x+0#4040ff13&| @35
+|[+3#0000000&|N|o| |N|a|m|e|]| |[|+|]|2@5|1|,|1|2@11|A|l@1|2|[+1&&|N|o| |N|a|m|e|]| |[|+|]|a@5|1|,|1|a@11|A|l@1
+|w+0&&|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|w|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|w|i|n|d|o|w| |4| @28|>+1&&|w+0&&|i|n|d|o|w| |3| @28
+|o+0#4040ff13&| @35|>+1#0000000&|z+0#4040ff13&| @35
+|o| @35|>+1#0000000&|z+0#4040ff13&| @35
+|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]|d@5|1|,|1|d@11|A|l@1|d|[|N|o| |N|a|m|e|]| |[|+|]|c@5|1|,|1|c@11|A|l@1
+|:+0&&|w|i|n|c|m|d| |k| @65
index ce60c728e6015f35c9a448c6ba55be730e97f592..69443c5f9d9223926bc337e056ac5e645b36f52c 100644 (file)
@@ -481,7 +481,7 @@ for g:testfunc in sort(s:tests)
       call add(total_errors, 'Run ' . g:run_nr . ':')
       call extend(total_errors, v:errors)
 
-      if g:run_nr == 5 || prev_error == v:errors[0]
+      if g:run_nr >= 5 || prev_error == v:errors[0]
         call add(total_errors, 'Flaky test failed too often, giving up')
         let v:errors = total_errors
         break
index d872a809db04c968120e23250377321bbf2b4c26..e19d4f5e5b172d8e7e13dfbbe50688a35bbd8739 100644 (file)
@@ -75,6 +75,8 @@ func VerifyScreenDump(buf, filename, options, ...)
        endif
       else
        let msg = 'See new dump file: call term_dumpload("testdir/' .. testfile .. '")'
+       " no point in retrying
+       let g:run_nr = 10
       endif
       for i in range(len(refdump))
        if i >= len(testdump)
index f5c8dc51e544f281f3bbbe30d54e9369489561bd..9fd0126d61fac432e58378b3a2d0a52b24c66c15 100644 (file)
@@ -356,6 +356,34 @@ func Test_fold_fillchars()
   set fillchars& fdc& foldmethod& foldenable&
 endfunc
 
+func Test_local_fillchars()
+  CheckScreendump
+
+  let lines =<< trim END
+      call setline(1, ['window 1']->repeat(3))
+      setlocal fillchars=stl:1,stlnc:a,vert:=,eob:x
+      vnew
+      call setline(1, ['window 2']->repeat(3))
+      setlocal fillchars=stl:2,stlnc:b,vert:+,eob:y
+      new
+      wincmd J
+      call setline(1, ['window 3']->repeat(3))
+      setlocal fillchars=stl:3,stlnc:c,vert:<,eob:z
+      vnew
+      call setline(1, ['window 4']->repeat(3))
+      setlocal fillchars=stl:4,stlnc:d,vert:>,eob:o
+  END
+  call writefile(lines, 'Xdisplayfillchars')
+  let buf = RunVimInTerminal('-S Xdisplayfillchars', #{rows: 12})
+  call VerifyScreenDump(buf, 'Test_display_fillchars_1', {})
+
+  call term_sendkeys(buf, ":wincmd k\r")
+  call VerifyScreenDump(buf, 'Test_display_fillchars_2', {})
+
+  call StopVimInTerminal(buf)
+  call delete('Xdisplayfillchars')
+endfunc
+
 func Test_display_linebreak_breakat()
   new
   vert resize 25
index e22fb5673cec7847b3f3a336d3ad126862d287e2..95367ed9344170b7d73518aaab10e76ec8b273db 100644 (file)
@@ -735,6 +735,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    36,
 /**/
     35,
 /**/