0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 9.0.0036: 'fillchars' cannot have window-local values

Problem:    'fillchars' cannot have window-local values.
Solution:   Make 'fillchars' global-local. (closes #5206)
This commit is contained in:
Bram Moolenaar 2022-07-04 17:34:33 +01:00
parent 54e5fed6d2
commit 96ba25ac01
19 changed files with 275 additions and 142 deletions

View 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'*
'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~") 'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~")
global global or local to window |global-local|
{not available when compiled without the |+folding| {not available when compiled without the |+folding|
feature} feature}
Characters to fill the statuslines and vertical separators. Characters to fill the statuslines, vertical separators and special
It is a comma-separated list of items: 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 default Used for ~ item name default Used for ~
stl:c ' ' or '^' statusline of the current window stl ' ' or '^' statusline of the current window
stlnc:c ' ' or '=' statusline of the non-current windows stlnc ' ' or '=' statusline of the non-current windows
vert:c '|' vertical separators |:vsplit| vert '|' vertical separators |:vsplit|
fold:c '-' filling 'foldtext' fold '-' filling 'foldtext'
foldopen:c '-' mark the beginning of a fold foldopen '-' mark the beginning of a fold
foldclose:c '+' show a closed fold foldclose '+' show a closed fold
foldsep:c '|' open fold middle character foldsep '|' open fold middle character
diff:c '-' deleted lines of the 'diff' option diff '-' deleted lines of the 'diff' option
eob:c '~' empty lines below the end of a buffer eob '~' empty lines below the end of a buffer
Any one that is omitted will fall back to the default. For "stl" and 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 '=' "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. characters are not supported.
The highlighting used for these items: The highlighting used for these items:
item highlight group ~ item name highlight group ~
stl:c StatusLine |hl-StatusLine| stl StatusLine |hl-StatusLine|
stlnc:c StatusLineNC |hl-StatusLineNC| stlnc StatusLineNC |hl-StatusLineNC|
vert:c VertSplit |hl-VertSplit| vert VertSplit |hl-VertSplit|
fold:c Folded |hl-Folded| fold Folded |hl-Folded|
diff:c DiffDelete |hl-DiffDelete| diff DiffDelete |hl-DiffDelete|
eob:c EndOfBuffer |hl-EndOfBuffer| eob EndOfBuffer |hl-EndOfBuffer|
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
'fixendofline' 'fixeol' boolean (default on) 'fixendofline' 'fixeol' boolean (default on)

View File

@ -1268,14 +1268,14 @@ win_line(
if (filler_todo > 0) if (filler_todo > 0)
{ {
// Draw "deleted" diff line(s). // Draw "deleted" diff line(s).
if (char2cells(fill_diff) > 1) if (char2cells(wp->w_fill_chars.diff) > 1)
{ {
c_extra = '-'; c_extra = '-';
c_final = NUL; c_final = NUL;
} }
else else
{ {
c_extra = fill_diff; c_extra = wp->w_fill_chars.diff;
c_final = NUL; c_final = NUL;
} }
# ifdef FEAT_RIGHTLEFT # ifdef FEAT_RIGHTLEFT
@ -1352,7 +1352,7 @@ win_line(
#endif #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); screen_line_flags);
// Pretend we have finished updating the window. Except when // Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set. // 'cursorcolumn' is set.
@ -2859,7 +2859,7 @@ win_line(
} }
#endif #endif
screen_line(screen_row, wp->w_wincol, col, screen_line(wp, screen_row, wp->w_wincol, col,
wp->w_width, screen_line_flags); wp->w_width, screen_line_flags);
row++; row++;
@ -3160,11 +3160,11 @@ win_line(
) )
{ {
#ifdef FEAT_CONCEAL #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); wp->w_width, screen_line_flags);
boguscols = 0; boguscols = 0;
#else #else
screen_line(screen_row, wp->w_wincol, col, screen_line(wp, screen_row, wp->w_wincol, col,
wp->w_width, screen_line_flags); wp->w_width, screen_line_flags);
#endif #endif
++row; ++row;

View File

@ -555,7 +555,7 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
if (stl_connected(wp)) if (stl_connected(wp))
fillchar = fillchar_status(&attr, wp); fillchar = fillchar_status(&attr, wp);
else else
fillchar = fillchar_vsep(&attr); fillchar = fillchar_vsep(&attr, wp);
screen_putchar(fillchar, row, W_ENDCOL(wp), attr); screen_putchar(fillchar, row, W_ENDCOL(wp), attr);
} }
busy = FALSE; busy = FALSE;
@ -1038,7 +1038,7 @@ redraw_win_toolbar(win_T *wp)
} }
wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker 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 #endif
@ -1246,7 +1246,8 @@ fold_line(
txtcol = col; // remember where text starts 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 // Right-left text is put in columns 0 - number-col, normal text is put
// in columns number-col - window-width. // in columns number-col - window-width.
col = text_to_screenline(wp, text, col); col = text_to_screenline(wp, text, col);
@ -1262,23 +1263,25 @@ fold_line(
#endif #endif
) )
{ {
int c = wp->w_fill_chars.fold;
if (enc_utf8) if (enc_utf8)
{ {
if (fill_fold >= 0x80) if (c >= 0x80)
{ {
ScreenLinesUC[off + col] = fill_fold; ScreenLinesUC[off + col] = c;
ScreenLinesC[0][off + col] = 0; ScreenLinesC[0][off + col] = 0;
ScreenLines[off + col] = 0x80; // avoid storing zero ScreenLines[off + col] = 0x80; // avoid storing zero
} }
else else
{ {
ScreenLinesUC[off + col] = 0; ScreenLinesUC[off + col] = 0;
ScreenLines[off + col] = fill_fold; ScreenLines[off + col] = c;
} }
col++; col++;
} }
else else
ScreenLines[off + col++] = fill_fold; ScreenLines[off + col++] = c;
} }
if (text != buf) if (text != buf)
@ -1371,7 +1374,8 @@ fold_line(
} }
#endif #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 // Update w_cline_height and w_cline_folded if the cursor line was
// updated (saves a call to plines() later). // updated (saves a call to plines() later).
@ -2669,10 +2673,10 @@ win_update(win_T *wp)
if (j > 0 && !wp->w_botfill) if (j > 0 && !wp->w_botfill)
{ {
// Display filler lines at the end of the file. // Display filler lines at the end of the file.
if (char2cells(fill_diff) > 1) if (char2cells(wp->w_fill_chars.diff) > 1)
i = '-'; i = '-';
else else
i = fill_diff; i = wp->w_fill_chars.diff;
if (row + j > wp->w_height) if (row + j > wp->w_height)
j = wp->w_height - row; j = wp->w_height - row;
win_draw_end(wp, i, i, TRUE, row, row + (int)j, HLF_DED); 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) else if (dollar_vcol == -1)
wp->w_botline = lnum; wp->w_botline = lnum;
// Make sure the rest of the screen is blank // Make sure the rest of the screen is blank.
// write the 'fill_eob' character to rows that aren't part of the file // write the "eob" character from 'fillchars' to rows that aren't part
// of the file.
if (WIN_IS_POPUP(wp)) if (WIN_IS_POPUP(wp))
win_draw_end(wp, ' ', ' ', FALSE, row, wp->w_height, HLF_AT); win_draw_end(wp, ' ', ' ', FALSE, row, wp->w_height, HLF_AT);
else 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 #ifdef SYN_TIME_LIMIT
@ -3026,7 +3032,7 @@ redraw_asap(int type)
mch_memmove(ScreenLines2 + off, mch_memmove(ScreenLines2 + off,
screenline2 + r * cols, screenline2 + r * cols,
(size_t)cols * sizeof(schar_T)); (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; ret = 4;
} }

View File

@ -1380,17 +1380,6 @@ EXTERN char_u *homedir INIT(= NULL);
// directory is not a local directory, globaldir is NULL. // directory is not a local directory, globaldir is NULL.
EXTERN char_u *globaldir INIT(= 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 #ifdef FEAT_FOLDING
EXTERN int disable_fold_update INIT(= 0); EXTERN int disable_fold_update INIT(= 0);
#endif #endif

View File

@ -4229,8 +4229,7 @@ theend:
#if defined(FEAT_GUI_GTK) || defined(FEAT_SPELL) || defined(PROTO) #if defined(FEAT_GUI_GTK) || defined(FEAT_SPELL) || defined(PROTO)
/* /*
* Return TRUE if string "s" is a valid utf-8 string. * Return TRUE if string "s" is a valid utf-8 string.
* When "end" is NULL stop at the first NUL. * When "end" is NULL stop at the first NUL. Otherwise stop at "end".
* When "end" is positive stop there.
*/ */
int int
utf_valid_string(char_u *s, char_u *end) 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 *table;
cw_interval_T *cw_table_save; cw_interval_T *cw_table_save;
size_t cw_table_size_save; size_t cw_table_size_save;
char *error = NULL;
if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL) if (in_vim9script() && check_for_list_arg(argvars, 0) == FAIL)
return; 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 // Check that the new value does not conflict with 'fillchars' or
// 'listchars'. // 'listchars'.
if (set_chars_option(curwin, &p_fcs) != NULL) if (set_chars_option(curwin, &p_fcs) != NULL)
{ error = e_conflicts_with_value_of_fillchars;
emsg(_(e_conflicts_with_value_of_fillchars)); else if (set_chars_option(curwin, &p_lcs) != NULL)
cw_table = cw_table_save; error = e_conflicts_with_value_of_listchars;
cw_table_size = cw_table_size_save;
vim_free(table);
return;
}
else else
{ {
tabpage_T *tp; tabpage_T *tp;
win_T *wp; win_T *wp;
FOR_ALL_TAB_WINDOWS(tp, wp) FOR_ALL_TAB_WINDOWS(tp, wp)
{ {
if (set_chars_option(wp, &wp->w_p_lcs) != NULL) if (set_chars_option(wp, &wp->w_p_lcs) != NULL)
{ {
emsg((e_conflicts_with_value_of_listchars)); error = e_conflicts_with_value_of_listchars;
cw_table = cw_table_save; break;
cw_table_size = cw_table_size_save; }
vim_free(table); if (set_chars_option(wp, &wp->w_p_fcs) != NULL)
return; {
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); vim_free(cw_table_save);
} }

View File

@ -2018,7 +2018,7 @@ retnomove:
count |= CURSOR_MOVED; // Cursor has moved count |= CURSOR_MOVED; // Cursor has moved
# ifdef FEAT_FOLDING # ifdef FEAT_FOLDING
if (mouse_char == fill_foldclosed) if (mouse_char == curwin->w_fill_chars.foldclosed)
count |= MOUSE_FOLD_OPEN; count |= MOUSE_FOLD_OPEN;
else if (mouse_char != ' ') else if (mouse_char != ' ')
count |= MOUSE_FOLD_CLOSE; count |= MOUSE_FOLD_CLOSE;

View File

@ -2436,7 +2436,7 @@ didset_options2(void)
(void)set_chars_option(curwin, &curwin->w_p_lcs); (void)set_chars_option(curwin, &curwin->w_p_lcs);
// Parse default for 'fillchars'. // Parse default for 'fillchars'.
(void)set_chars_option(curwin, &p_fcs); (void)set_chars_option(curwin, &curwin->w_p_fcs);
#ifdef FEAT_CLIPBOARD #ifdef FEAT_CLIPBOARD
// Parse default for '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); set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs);
redraw_later(NOT_VALID); redraw_later(NOT_VALID);
break; 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: case PV_VE:
clear_string_option(&((win_T *)from)->w_p_ve); clear_string_option(&((win_T *)from)->w_p_ve);
((win_T *)from)->w_ve_flags = 0; ((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_BKC: return (char_u *)&(curbuf->b_p_bkc);
case PV_MENC: return (char_u *)&(curbuf->b_p_menc); case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
case PV_LCS: return (char_u *)&(curwin->w_p_lcs); 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); 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_LIST: return (char_u *)&(curwin->w_p_list);
case PV_LCS: return *curwin->w_p_lcs != NUL case PV_LCS: return *curwin->w_p_lcs != NUL
? (char_u *)&(curwin->w_p_lcs) : p->var; ? (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 case PV_VE: return *curwin->w_p_ve != NUL
? (char_u *)&(curwin->w_p_ve) : p->var; ? (char_u *)&(curwin->w_p_ve) : p->var;
#ifdef FEAT_SPELL #ifdef FEAT_SPELL
@ -5600,6 +5608,15 @@ after_copy_winopt(win_T *wp)
check_colorcolumn(wp); check_colorcolumn(wp);
#endif #endif
set_chars_option(wp, &wp->w_p_lcs); 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; to->wo_arab = from->wo_arab;
#endif #endif
to->wo_list = from->wo_list; 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_nu = from->wo_nu;
to->wo_rnu = from->wo_rnu; 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; to->wo_ve_flags = from->wo_ve_flags;
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
to->wo_nuw = from->wo_nuw; to->wo_nuw = from->wo_nuw;
#endif #endif
#ifdef FEAT_RIGHTLEFT #ifdef FEAT_RIGHTLEFT
to->wo_rl = from->wo_rl; to->wo_rl = from->wo_rl;
to->wo_rlc = vim_strsave(from->wo_rlc); to->wo_rlc = copy_option_val(from->wo_rlc);
#endif #endif
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
to->wo_sbr = vim_strsave(from->wo_sbr); to->wo_sbr = copy_option_val(from->wo_sbr);
#endif #endif
#ifdef FEAT_STL_OPT #ifdef FEAT_STL_OPT
to->wo_stl = vim_strsave(from->wo_stl); to->wo_stl = copy_option_val(from->wo_stl);
#endif #endif
to->wo_wrap = from->wo_wrap; to->wo_wrap = from->wo_wrap;
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
@ -5640,9 +5658,9 @@ copy_winopt(winopt_T *from, winopt_T *to)
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
to->wo_lbr = from->wo_lbr; to->wo_lbr = from->wo_lbr;
to->wo_bri = from->wo_bri; to->wo_bri = from->wo_bri;
to->wo_briopt = vim_strsave(from->wo_briopt); to->wo_briopt = copy_option_val(from->wo_briopt);
#endif #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 = from->wo_scb;
to->wo_scb_save = from->wo_scb_save; to->wo_scb_save = from->wo_scb_save;
to->wo_crb = from->wo_crb; to->wo_crb = from->wo_crb;
@ -5653,42 +5671,42 @@ copy_winopt(winopt_T *from, winopt_T *to)
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
to->wo_cuc = from->wo_cuc; to->wo_cuc = from->wo_cuc;
to->wo_cul = from->wo_cul; to->wo_cul = from->wo_cul;
to->wo_culopt = vim_strsave(from->wo_culopt); to->wo_culopt = copy_option_val(from->wo_culopt);
to->wo_cc = vim_strsave(from->wo_cc); to->wo_cc = copy_option_val(from->wo_cc);
#endif #endif
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
to->wo_diff = from->wo_diff; to->wo_diff = from->wo_diff;
to->wo_diff_saved = from->wo_diff_saved; to->wo_diff_saved = from->wo_diff_saved;
#endif #endif
#ifdef FEAT_CONCEAL #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; to->wo_cole = from->wo_cole;
#endif #endif
#ifdef FEAT_TERMINAL #ifdef FEAT_TERMINAL
to->wo_twk = vim_strsave(from->wo_twk); to->wo_twk = copy_option_val(from->wo_twk);
to->wo_tws = vim_strsave(from->wo_tws); to->wo_tws = copy_option_val(from->wo_tws);
#endif #endif
#ifdef FEAT_FOLDING #ifdef FEAT_FOLDING
to->wo_fdc = from->wo_fdc; to->wo_fdc = from->wo_fdc;
to->wo_fdc_save = from->wo_fdc_save; to->wo_fdc_save = from->wo_fdc_save;
to->wo_fen = from->wo_fen; to->wo_fen = from->wo_fen;
to->wo_fen_save = from->wo_fen_save; 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_fml = from->wo_fml;
to->wo_fdl = from->wo_fdl; to->wo_fdl = from->wo_fdl;
to->wo_fdl_save = from->wo_fdl_save; 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 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; to->wo_fdn = from->wo_fdn;
# ifdef FEAT_EVAL # ifdef FEAT_EVAL
to->wo_fde = vim_strsave(from->wo_fde); to->wo_fde = copy_option_val(from->wo_fde);
to->wo_fdt = vim_strsave(from->wo_fdt); to->wo_fdt = copy_option_val(from->wo_fdt);
# endif # endif
to->wo_fmr = vim_strsave(from->wo_fmr); to->wo_fmr = copy_option_val(from->wo_fmr);
#endif #endif
#ifdef FEAT_SIGNS #ifdef FEAT_SIGNS
to->wo_scl = vim_strsave(from->wo_scl); to->wo_scl = copy_option_val(from->wo_scl);
#endif #endif
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
@ -5753,6 +5771,7 @@ check_winopt(winopt_T *wop UNUSED)
#endif #endif
check_string_option(&wop->wo_wcr); check_string_option(&wop->wo_wcr);
check_string_option(&wop->wo_lcs); check_string_option(&wop->wo_lcs);
check_string_option(&wop->wo_fcs);
check_string_option(&wop->wo_ve); check_string_option(&wop->wo_ve);
} }
@ -5800,6 +5819,7 @@ clear_winopt(winopt_T *wop UNUSED)
clear_string_option(&wop->wo_tws); clear_string_option(&wop->wo_tws);
#endif #endif
clear_string_option(&wop->wo_lcs); clear_string_option(&wop->wo_lcs);
clear_string_option(&wop->wo_fcs);
clear_string_option(&wop->wo_ve); clear_string_option(&wop->wo_ve);
} }

View File

@ -1238,6 +1238,7 @@ enum
{ {
WV_LIST = 0 WV_LIST = 0
, WV_LCS , WV_LCS
, WV_FCS
#ifdef FEAT_ARABIC #ifdef FEAT_ARABIC
, WV_ARAB , WV_ARAB
#endif #endif

View File

@ -182,6 +182,7 @@
# define PV_LBR OPT_WIN(WV_LBR) # define PV_LBR OPT_WIN(WV_LBR)
#endif #endif
#define PV_LCS OPT_BOTH(OPT_WIN(WV_LCS)) #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_NU OPT_WIN(WV_NU)
#define PV_RNU OPT_WIN(WV_RNU) #define PV_RNU OPT_WIN(WV_RNU)
#define PV_VE OPT_BOTH(OPT_WIN(WV_VE)) #define PV_VE OPT_BOTH(OPT_WIN(WV_VE))
@ -947,7 +948,7 @@ static struct vimoption options[] =
{(char_u *)"", (char_u *)0L} {(char_u *)"", (char_u *)0L}
SCTX_INIT}, SCTX_INIT},
{"fillchars", "fcs", P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP, {"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} {(char_u *)"vert:|,fold:-,eob:~", (char_u *)0L}
SCTX_INIT}, SCTX_INIT},
{"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT, {"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT,

View File

@ -1311,7 +1311,7 @@ ambw_end:
if (errmsg == NULL) if (errmsg == NULL)
{ {
tabpage_T *tp; tabpage_T *tp;
win_T *wp; win_T *wp;
// The current window is set to use the global 'listchars' value. // The current window is set to use the global 'listchars' value.
// So clear the window-local value. // So clear the window-local value.
@ -1320,18 +1320,40 @@ ambw_end:
FOR_ALL_TAB_WINDOWS(tp, wp) FOR_ALL_TAB_WINDOWS(tp, wp)
// If no error was returned above, we don't expect an error // If no error was returned above, we don't expect an error
// here, so ignore the return value. // 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); redraw_all_later(NOT_VALID);
} }
} }
// local 'listchars' // local 'listchars'
else if (varp == &curwin->w_p_lcs) else if (varp == &curwin->w_p_lcs)
errmsg = set_chars_option(curwin, varp); errmsg = set_chars_option(curwin, varp);
// 'fillchars' // 'fillchars'
else if (varp == &p_fcs) 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); errmsg = set_chars_option(curwin, varp);
} }

View 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); size_t fill_foldcolumn(char_u *p, win_T *wp, int closed, linenr_T lnum);
int screen_get_current_line_off(void); int screen_get_current_line_off(void);
void reset_screen_attr(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 rl_mirror(char_u *str);
void draw_vsep_win(win_T *wp, int row); 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); 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 draw_tabline(void);
void get_trans_bufname(buf_T *buf); void get_trans_bufname(buf_T *buf);
int fillchar_status(int *attr, win_T *wp); 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 redrawing(void);
int messaging(void); int messaging(void);
void comp_col(void); void comp_col(void);

View File

@ -285,9 +285,9 @@ fill_foldcolumn(
{ {
if (win_foldinfo.fi_lnum == lnum if (win_foldinfo.fi_lnum == lnum
&& first_level + i >= win_foldinfo.fi_low_level) && first_level + i >= win_foldinfo.fi_low_level)
symbol = fill_foldopen; symbol = wp->w_fill_chars.foldopen;
else if (first_level == 1) else if (first_level == 1)
symbol = fill_foldsep; symbol = wp->w_fill_chars.foldsep;
else if (first_level + i <= 9) else if (first_level + i <= 9)
symbol = '0' + first_level + i; symbol = '0' + first_level + i;
else else
@ -312,7 +312,7 @@ fill_foldcolumn(
// for a multibyte character, erase all the bytes // for a multibyte character, erase all the bytes
vim_memset(p + byte_counter, ' ', len); vim_memset(p + byte_counter, ' ', len);
} }
symbol = fill_foldclosed; symbol = wp->w_fill_chars.foldclosed;
len = utf_char2bytes(symbol, &p[byte_counter]); len = utf_char2bytes(symbol, &p[byte_counter]);
byte_counter += len; byte_counter += len;
} }
@ -430,11 +430,12 @@ reset_screen_attr(void)
*/ */
void void
screen_line( screen_line(
int row, win_T *wp,
int coloff, int row,
int endcol, int coloff,
int clear_width, int endcol,
int flags UNUSED) int clear_width,
int flags UNUSED)
{ {
unsigned off_from; unsigned off_from;
unsigned off_to; unsigned off_to;
@ -794,7 +795,7 @@ screen_line(
{ {
int c; int c;
c = fillchar_vsep(&hl); c = fillchar_vsep(&hl, wp);
if (ScreenLines[off_to] != (schar_T)c if (ScreenLines[off_to] != (schar_T)c
|| (enc_utf8 && (int)ScreenLinesUC[off_to] || (enc_utf8 && (int)ScreenLinesUC[off_to]
!= (c >= 0x80 ? c : 0)) != (c >= 0x80 ? c : 0))
@ -853,7 +854,7 @@ draw_vsep_win(win_T *wp, int row)
if (wp->w_vsep_width) if (wp->w_vsep_width)
{ {
// draw the vertical separator right of this window // 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, screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
W_ENDCOL(wp), W_ENDCOL(wp) + 1, W_ENDCOL(wp), W_ENDCOL(wp) + 1,
c, ' ', hl); c, ' ', hl);
@ -4619,12 +4620,12 @@ fillchar_status(int *attr, win_T *wp)
if (wp == curwin) if (wp == curwin)
{ {
*attr = HL_ATTR(HLF_ST); *attr = HL_ATTR(HLF_ST);
fill = fill_stl; fill = wp->w_fill_chars.stl;
} }
else else
{ {
*attr = HL_ATTR(HLF_STNC); *attr = HL_ATTR(HLF_STNC);
fill = fill_stlnc; fill = wp->w_fill_chars.stlnc;
} }
} }
else else
@ -4632,19 +4633,19 @@ fillchar_status(int *attr, win_T *wp)
if (wp == curwin) if (wp == curwin)
{ {
*attr = HL_ATTR(HLF_S); *attr = HL_ATTR(HLF_S);
fill = fill_stl; fill = wp->w_fill_chars.stl;
} }
else else
{ {
*attr = HL_ATTR(HLF_SNC); *attr = HL_ATTR(HLF_SNC);
fill = fill_stlnc; fill = wp->w_fill_chars.stlnc;
} }
// Use fill when there is highlighting, and highlighting of current // Use fill when there is highlighting, and highlighting of current
// window differs, or the fillchars differ, or this is not the // window differs, or the fillchars differ, or this is not the
// current window // current window
if (*attr != 0 && ((HL_ATTR(HLF_S) != HL_ATTR(HLF_SNC) if (*attr != 0 && ((HL_ATTR(HLF_S) != HL_ATTR(HLF_SNC)
|| wp != curwin || ONE_WINDOW) || wp != curwin || ONE_WINDOW)
|| (fill_stl != fill_stlnc))) || (wp->w_fill_chars.stl != wp->w_fill_chars.stlnc)))
return fill; return fill;
if (wp == curwin) if (wp == curwin)
return '^'; return '^';
@ -4656,13 +4657,13 @@ fillchar_status(int *attr, win_T *wp)
* Get its attributes in "*attr". * Get its attributes in "*attr".
*/ */
int int
fillchar_vsep(int *attr) fillchar_vsep(int *attr, win_T *wp)
{ {
*attr = HL_ATTR(HLF_C); *attr = HL_ATTR(HLF_C);
if (*attr == 0 && fill_vert == ' ') if (*attr == 0 && wp->w_fill_chars.vert == ' ')
return '|'; return '|';
else else
return fill_vert; return wp->w_fill_chars.vert;
} }
/* /*
@ -4848,29 +4849,30 @@ get_encoded_char_adv(char_u **p)
char * char *
set_chars_option(win_T *wp, char_u **varp) set_chars_option(win_T *wp, char_u **varp)
{ {
int round, i, len, len2, entries; int round, i, len, len2, entries;
char_u *p, *s; char_u *p, *s;
int c1 = 0, c2 = 0, c3 = 0; int c1 = 0, c2 = 0, c3 = 0;
char_u *last_multispace = NULL; // Last occurrence of "multispace:" char_u *last_multispace = NULL; // Last occurrence of "multispace:"
char_u *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" char_u *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
int multispace_len = 0; // Length of lcs-multispace string int multispace_len = 0; // Length of lcs-multispace string
int lead_multispace_len = 0; // Length of lcs-leadmultispace string int lead_multispace_len = 0; // Length of lcs-leadmultispace string
struct charstab struct charstab
{ {
int *cp; int *cp;
char *name; char *name;
}; };
static fill_chars_T fill_chars;
static struct charstab filltab[] = static struct charstab filltab[] =
{ {
{&fill_stl, "stl"}, {&fill_chars.stl, "stl"},
{&fill_stlnc, "stlnc"}, {&fill_chars.stlnc, "stlnc"},
{&fill_vert, "vert"}, {&fill_chars.vert, "vert"},
{&fill_fold, "fold"}, {&fill_chars.fold, "fold"},
{&fill_foldopen, "foldopen"}, {&fill_chars.foldopen, "foldopen"},
{&fill_foldclosed, "foldclose"}, {&fill_chars.foldclosed, "foldclose"},
{&fill_foldsep, "foldsep"}, {&fill_chars.foldsep, "foldsep"},
{&fill_diff, "diff"}, {&fill_chars.diff, "diff"},
{&fill_eob, "eob"}, {&fill_chars.eob, "eob"},
}; };
static lcs_chars_T lcs_chars; static lcs_chars_T lcs_chars;
struct charstab lcstab[] = struct charstab lcstab[] =
@ -4903,6 +4905,8 @@ set_chars_option(win_T *wp, char_u **varp)
{ {
tab = filltab; tab = filltab;
entries = ARRAY_LENGTH(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 // 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) if (round > 0)
{ {
// After checking that the value is valid: set defaults: space for // After checking that the value is valid: set defaults.
// '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 : ' ');
if (varp == &p_lcs || varp == &wp->w_p_lcs) 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.tab1 = NUL;
lcs_chars.tab3 = NUL; lcs_chars.tab3 = NUL;
@ -4932,7 +4933,8 @@ set_chars_option(win_T *wp, char_u **varp)
if (lead_multispace_len > 0) 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; lcs_chars.leadmultispace[lead_multispace_len] = NUL;
} }
else else
@ -4940,11 +4942,15 @@ set_chars_option(win_T *wp, char_u **varp)
} }
else else
{ {
fill_diff = '-'; fill_chars.stl = ' ';
fill_foldopen = '-'; fill_chars.stlnc = ' ';
fill_foldclosed = '+'; fill_chars.vert = ' ';
fill_foldsep = '|'; fill_chars.fold = '-';
fill_eob = '~'; fill_chars.foldopen = '-';
fill_chars.foldclosed = '+';
fill_chars.foldsep = '|';
fill_chars.diff = '-';
fill_chars.eob = '~';
} }
} }
p = *varp; p = *varp;
@ -5083,12 +5089,17 @@ set_chars_option(win_T *wp, char_u **varp)
++p; ++p;
} }
} }
if (tab == lcstab) if (tab == lcstab)
{ {
vim_free(wp->w_lcs_chars.multispace); vim_free(wp->w_lcs_chars.multispace);
vim_free(wp->w_lcs_chars.leadmultispace); vim_free(wp->w_lcs_chars.leadmultispace);
wp->w_lcs_chars = lcs_chars; wp->w_lcs_chars = lcs_chars;
} }
else
{
wp->w_fill_chars = fill_chars;
}
return NULL; // no error return NULL; // no error
} }

View File

@ -232,6 +232,8 @@ typedef struct
#define w_p_list w_onebuf_opt.wo_list // 'list' #define w_p_list w_onebuf_opt.wo_list // 'list'
char_u *wo_lcs; char_u *wo_lcs;
#define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars' #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; int wo_nu;
#define w_p_nu w_onebuf_opt.wo_nu // 'number' #define w_p_nu w_onebuf_opt.wo_nu // 'number'
int wo_rnu; int wo_rnu;
@ -3418,6 +3420,22 @@ typedef struct
#endif #endif
} lcs_chars_T; } 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 * Structure which contains all information that belongs to a window
* *
@ -3470,6 +3488,7 @@ struct window_S
// redrawn // redrawn
lcs_chars_T w_lcs_chars; // 'listchars' characters 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 * "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for

View File

@ -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

View File

@ -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

View File

@ -481,7 +481,7 @@ for g:testfunc in sort(s:tests)
call add(total_errors, 'Run ' . g:run_nr . ':') call add(total_errors, 'Run ' . g:run_nr . ':')
call extend(total_errors, v:errors) 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') call add(total_errors, 'Flaky test failed too often, giving up')
let v:errors = total_errors let v:errors = total_errors
break break

View File

@ -75,6 +75,8 @@ func VerifyScreenDump(buf, filename, options, ...)
endif endif
else else
let msg = 'See new dump file: call term_dumpload("testdir/' .. testfile .. '")' let msg = 'See new dump file: call term_dumpload("testdir/' .. testfile .. '")'
" no point in retrying
let g:run_nr = 10
endif endif
for i in range(len(refdump)) for i in range(len(refdump))
if i >= len(testdump) if i >= len(testdump)

View File

@ -356,6 +356,34 @@ func Test_fold_fillchars()
set fillchars& fdc& foldmethod& foldenable& set fillchars& fdc& foldmethod& foldenable&
endfunc 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() func Test_display_linebreak_breakat()
new new
vert resize 25 vert resize 25

View File

@ -735,6 +735,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
36,
/**/ /**/
35, 35,
/**/ /**/