To: vim_dev@googlegroups.com Subject: Patch 9.0.0036 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0036 Problem: 'fillchars' cannot have window-local values. Solution: Make 'fillchars' global-local. (closes #5206) Files: runtime/doc/options.txt, src/structs.h, src/globals.h, src/screen.c, src/optionstr.c, src/option.c, src/drawscreen.c, src/drawline.c, src/mouse.c, src/optiondefs.h, src/option.h, src/mbyte.c, src/proto/screen.pro, src/testdir/test_display.vim, src/testdir/dumps/Test_display_fillchars_1.dump, src/testdir/dumps/Test_display_fillchars_2.dump, src/testdir/screendump.vim, src/testdir/runtest.vim *** ../vim-9.0.0035/runtime/doc/options.txt 2022-06-29 18:39:05.011841452 +0100 --- runtime/doc/options.txt 2022-07-04 16:06:53.011093858 +0100 *************** *** 3376,3397 **** *'fillchars'* *'fcs'* 'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~") ! global {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 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 '=' --- 3376,3399 ---- *'fillchars'* *'fcs'* 'fillchars' 'fcs' string (default "vert:|,fold:-,eob:~") ! global or local to window |global-local| {not available when compiled without the |+folding| feature} ! 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,3419 **** 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| *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* 'fixendofline' 'fixeol' boolean (default on) --- 3409,3421 ---- characters are not supported. The highlighting used for these items: ! 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) *** ../vim-9.0.0035/src/structs.h 2022-06-30 22:13:56.200846349 +0100 --- src/structs.h 2022-07-04 16:27:08.128891145 +0100 *************** *** 232,237 **** --- 232,239 ---- #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; *************** *** 3419,3424 **** --- 3421,3442 ---- } 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 * * All row numbers are relative to the start of the window, except w_winrow. *************** *** 3470,3475 **** --- 3488,3494 ---- // 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 *** ../vim-9.0.0035/src/globals.h 2022-06-30 22:13:56.200846349 +0100 --- src/globals.h 2022-07-04 16:12:33.914079085 +0100 *************** *** 1380,1396 **** // 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 --- 1380,1385 ---- *** ../vim-9.0.0035/src/screen.c 2022-06-29 18:39:05.015841419 +0100 --- src/screen.c 2022-07-04 17:08:33.595832044 +0100 *************** *** 285,293 **** { if (win_foldinfo.fi_lnum == lnum && first_level + i >= win_foldinfo.fi_low_level) ! symbol = fill_foldopen; else if (first_level == 1) ! symbol = fill_foldsep; else if (first_level + i <= 9) symbol = '0' + first_level + i; else --- 285,293 ---- { if (win_foldinfo.fi_lnum == lnum && first_level + i >= win_foldinfo.fi_low_level) ! symbol = wp->w_fill_chars.foldopen; else if (first_level == 1) ! symbol = wp->w_fill_chars.foldsep; else if (first_level + i <= 9) symbol = '0' + first_level + i; else *************** *** 312,318 **** // for a multibyte character, erase all the bytes vim_memset(p + byte_counter, ' ', len); } ! symbol = fill_foldclosed; len = utf_char2bytes(symbol, &p[byte_counter]); byte_counter += len; } --- 312,318 ---- // for a multibyte character, erase all the bytes vim_memset(p + byte_counter, ' ', len); } ! symbol = wp->w_fill_chars.foldclosed; len = utf_char2bytes(symbol, &p[byte_counter]); byte_counter += len; } *************** *** 430,440 **** */ void screen_line( ! int row, ! int coloff, ! int endcol, ! int clear_width, ! int flags UNUSED) { unsigned off_from; unsigned off_to; --- 430,441 ---- */ void screen_line( ! win_T *wp, ! int row, ! int coloff, ! int endcol, ! int clear_width, ! int flags UNUSED) { unsigned off_from; unsigned off_to; *************** *** 794,800 **** { int c; ! c = fillchar_vsep(&hl); if (ScreenLines[off_to] != (schar_T)c || (enc_utf8 && (int)ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0)) --- 795,801 ---- { int c; ! c = fillchar_vsep(&hl, wp); if (ScreenLines[off_to] != (schar_T)c || (enc_utf8 && (int)ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0)) *************** *** 853,859 **** if (wp->w_vsep_width) { // draw the vertical separator right of this window ! c = fillchar_vsep(&hl); screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height, W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl); --- 854,860 ---- if (wp->w_vsep_width) { // draw the vertical separator right of this window ! 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,4630 **** if (wp == curwin) { *attr = HL_ATTR(HLF_ST); ! fill = fill_stl; } else { *attr = HL_ATTR(HLF_STNC); ! fill = fill_stlnc; } } else --- 4620,4631 ---- if (wp == curwin) { *attr = HL_ATTR(HLF_ST); ! fill = wp->w_fill_chars.stl; } else { *attr = HL_ATTR(HLF_STNC); ! fill = wp->w_fill_chars.stlnc; } } else *************** *** 4632,4650 **** if (wp == curwin) { *attr = HL_ATTR(HLF_S); ! fill = fill_stl; } else { *attr = HL_ATTR(HLF_SNC); ! fill = fill_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))) return fill; if (wp == curwin) return '^'; --- 4633,4651 ---- if (wp == curwin) { *attr = HL_ATTR(HLF_S); ! fill = wp->w_fill_chars.stl; } else { *attr = HL_ATTR(HLF_SNC); ! 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) ! || (wp->w_fill_chars.stl != wp->w_fill_chars.stlnc))) return fill; if (wp == curwin) return '^'; *************** *** 4656,4668 **** * Get its attributes in "*attr". */ int ! fillchar_vsep(int *attr) { *attr = HL_ATTR(HLF_C); ! if (*attr == 0 && fill_vert == ' ') return '|'; else ! return fill_vert; } /* --- 4657,4669 ---- * Get its attributes in "*attr". */ int ! fillchar_vsep(int *attr, win_T *wp) { *attr = HL_ATTR(HLF_C); ! if (*attr == 0 && wp->w_fill_chars.vert == ' ') return '|'; else ! return wp->w_fill_chars.vert; } /* *************** *** 4848,4876 **** 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 struct charstab { int *cp; char *name; }; 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"}, }; static lcs_chars_T lcs_chars; struct charstab lcstab[] = --- 4849,4878 ---- 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 struct charstab { int *cp; char *name; }; + static fill_chars_T fill_chars; static struct charstab filltab[] = { ! {&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,4908 **** --- 4905,4912 ---- { 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,4924 **** { 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 : ' '); ! if (varp == &p_lcs || varp == &wp->w_p_lcs) { lcs_chars.tab1 = NUL; lcs_chars.tab3 = NUL; --- 4914,4925 ---- { if (round > 0) { ! // 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,4938 **** if (lead_multispace_len > 0) { ! lcs_chars.leadmultispace = ALLOC_MULT(int, lead_multispace_len + 1); lcs_chars.leadmultispace[lead_multispace_len] = NUL; } else --- 4933,4940 ---- if (lead_multispace_len > 0) { ! lcs_chars.leadmultispace = ! ALLOC_MULT(int, lead_multispace_len + 1); lcs_chars.leadmultispace[lead_multispace_len] = NUL; } else *************** *** 4940,4950 **** } else { ! fill_diff = '-'; ! fill_foldopen = '-'; ! fill_foldclosed = '+'; ! fill_foldsep = '|'; ! fill_eob = '~'; } } p = *varp; --- 4942,4956 ---- } else { ! 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,5094 **** --- 5089,5105 ---- ++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 } *** ../vim-9.0.0035/src/optionstr.c 2022-06-04 21:55:28.000000000 +0100 --- src/optionstr.c 2022-07-04 16:21:12.420717809 +0100 *************** *** 1311,1317 **** if (errmsg == NULL) { tabpage_T *tp; ! win_T *wp; // The current window is set to use the global 'listchars' value. // So clear the window-local value. --- 1311,1317 ---- if (errmsg == NULL) { tabpage_T *tp; ! win_T *wp; // The current window is set to use the global 'listchars' value. // So clear the window-local value. *************** *** 1320,1331 **** 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); redraw_all_later(NOT_VALID); } } - // local 'listchars' else if (varp == &curwin->w_p_lcs) errmsg = set_chars_option(curwin, varp); --- 1320,1331 ---- 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_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); *************** *** 1334,1339 **** --- 1334,1361 ---- 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); } #ifdef FEAT_CMDWIN *** ../vim-9.0.0035/src/option.c 2022-05-21 19:36:50.000000000 +0100 --- src/option.c 2022-07-04 16:51:59.944675852 +0100 *************** *** 2436,2442 **** (void)set_chars_option(curwin, &curwin->w_p_lcs); // Parse default for 'fillchars'. ! (void)set_chars_option(curwin, &p_fcs); #ifdef FEAT_CLIPBOARD // Parse default for 'clipboard' --- 2436,2442 ---- (void)set_chars_option(curwin, &curwin->w_p_lcs); // Parse default for 'fillchars'. ! (void)set_chars_option(curwin, &curwin->w_p_fcs); #ifdef FEAT_CLIPBOARD // Parse default for 'clipboard' *************** *** 5207,5212 **** --- 5207,5217 ---- 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,5277 **** --- 5277,5283 ---- 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,5380 **** --- 5381,5388 ---- 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,5605 **** --- 5608,5622 ---- 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,5637 **** to->wo_arab = from->wo_arab; #endif to->wo_list = from->wo_list; ! to->wo_lcs = vim_strsave(from->wo_lcs); to->wo_nu = from->wo_nu; to->wo_rnu = from->wo_rnu; ! to->wo_ve = vim_strsave(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); #endif #ifdef FEAT_LINEBREAK ! to->wo_sbr = vim_strsave(from->wo_sbr); #endif #ifdef FEAT_STL_OPT ! to->wo_stl = vim_strsave(from->wo_stl); #endif to->wo_wrap = from->wo_wrap; #ifdef FEAT_DIFF --- 5632,5655 ---- to->wo_arab = from->wo_arab; #endif to->wo_list = from->wo_list; ! 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 = 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 = copy_option_val(from->wo_rlc); #endif #ifdef FEAT_LINEBREAK ! to->wo_sbr = copy_option_val(from->wo_sbr); #endif #ifdef FEAT_STL_OPT ! to->wo_stl = copy_option_val(from->wo_stl); #endif to->wo_wrap = from->wo_wrap; #ifdef FEAT_DIFF *************** *** 5640,5648 **** #ifdef FEAT_LINEBREAK to->wo_lbr = from->wo_lbr; to->wo_bri = from->wo_bri; ! to->wo_briopt = vim_strsave(from->wo_briopt); #endif ! to->wo_wcr = vim_strsave(from->wo_wcr); to->wo_scb = from->wo_scb; to->wo_scb_save = from->wo_scb_save; to->wo_crb = from->wo_crb; --- 5658,5666 ---- #ifdef FEAT_LINEBREAK to->wo_lbr = from->wo_lbr; to->wo_bri = from->wo_bri; ! to->wo_briopt = copy_option_val(from->wo_briopt); #endif ! 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,5694 **** #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); #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_cole = from->wo_cole; #endif #ifdef FEAT_TERMINAL ! to->wo_twk = vim_strsave(from->wo_twk); ! to->wo_tws = vim_strsave(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_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_save = from->wo_diff_saved ! ? 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); # endif ! to->wo_fmr = vim_strsave(from->wo_fmr); #endif #ifdef FEAT_SIGNS ! to->wo_scl = vim_strsave(from->wo_scl); #endif #ifdef FEAT_EVAL --- 5671,5712 ---- #ifdef FEAT_SYN_HL to->wo_cuc = from->wo_cuc; to->wo_cul = from->wo_cul; ! 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 = copy_option_val(from->wo_cocu); to->wo_cole = from->wo_cole; #endif #ifdef FEAT_TERMINAL ! 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 = 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 = copy_option_val(from->wo_fdm); to->wo_fdm_save = from->wo_diff_saved ! ? vim_strsave(from->wo_fdm_save) : empty_option; to->wo_fdn = from->wo_fdn; # ifdef FEAT_EVAL ! to->wo_fde = copy_option_val(from->wo_fde); ! to->wo_fdt = copy_option_val(from->wo_fdt); # endif ! to->wo_fmr = copy_option_val(from->wo_fmr); #endif #ifdef FEAT_SIGNS ! to->wo_scl = copy_option_val(from->wo_scl); #endif #ifdef FEAT_EVAL *************** *** 5753,5758 **** --- 5771,5777 ---- #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,5805 **** --- 5819,5825 ---- 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); } *** ../vim-9.0.0035/src/drawscreen.c 2022-06-19 12:13:15.000000000 +0100 --- src/drawscreen.c 2022-07-04 17:14:24.567478674 +0100 *************** *** 555,561 **** if (stl_connected(wp)) fillchar = fillchar_status(&attr, wp); else ! fillchar = fillchar_vsep(&attr); screen_putchar(fillchar, row, W_ENDCOL(wp), attr); } busy = FALSE; --- 555,561 ---- if (stl_connected(wp)) fillchar = fillchar_status(&attr, wp); else ! fillchar = fillchar_vsep(&attr, wp); screen_putchar(fillchar, row, W_ENDCOL(wp), attr); } busy = FALSE; *************** *** 1038,1044 **** } 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); } #endif --- 1038,1044 ---- } wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker ! screen_line(wp, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, 0); } #endif *************** *** 1246,1252 **** txtcol = col; // remember where text starts ! // 5. move the text to current_ScreenLine. Fill up with "fill_fold". // 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); --- 1246,1253 ---- txtcol = col; // remember where text starts ! // 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,1284 **** #endif ) { if (enc_utf8) { ! if (fill_fold >= 0x80) { ! ScreenLinesUC[off + col] = fill_fold; ScreenLinesC[0][off + col] = 0; ScreenLines[off + col] = 0x80; // avoid storing zero } else { ScreenLinesUC[off + col] = 0; ! ScreenLines[off + col] = fill_fold; } col++; } else ! ScreenLines[off + col++] = fill_fold; } if (text != buf) --- 1263,1287 ---- #endif ) { + int c = wp->w_fill_chars.fold; + if (enc_utf8) { ! if (c >= 0x80) { ! ScreenLinesUC[off + col] = c; ScreenLinesC[0][off + col] = 0; ScreenLines[off + col] = 0x80; // avoid storing zero } else { ScreenLinesUC[off + col] = 0; ! ScreenLines[off + col] = c; } col++; } else ! ScreenLines[off + col++] = c; } if (text != buf) *************** *** 1371,1377 **** } #endif ! screen_line(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). --- 1374,1381 ---- } #endif ! 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,2678 **** if (j > 0 && !wp->w_botfill) { // Display filler lines at the end of the file. ! if (char2cells(fill_diff) > 1) i = '-'; else ! i = fill_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); --- 2673,2682 ---- if (j > 0 && !wp->w_botfill) { // Display filler lines at the end of the file. ! if (char2cells(wp->w_fill_chars.diff) > 1) i = '-'; else ! 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,2694 **** 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 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); } #ifdef SYN_TIME_LIMIT --- 2687,2700 ---- else if (dollar_vcol == -1) wp->w_botline = lnum; ! // 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, wp->w_fill_chars.eob, ' ', FALSE, ! row, wp->w_height, HLF_EOB); } #ifdef SYN_TIME_LIMIT *************** *** 3026,3032 **** mch_memmove(ScreenLines2 + off, screenline2 + r * cols, (size_t)cols * sizeof(schar_T)); ! screen_line(cmdline_row + r, 0, cols, cols, 0); } ret = 4; } --- 3032,3038 ---- mch_memmove(ScreenLines2 + off, screenline2 + r * cols, (size_t)cols * sizeof(schar_T)); ! screen_line(curwin, cmdline_row + r, 0, cols, cols, 0); } ret = 4; } *** ../vim-9.0.0035/src/drawline.c 2022-07-03 14:20:44.788010407 +0100 --- src/drawline.c 2022-07-04 17:09:19.247789215 +0100 *************** *** 1268,1281 **** if (filler_todo > 0) { // Draw "deleted" diff line(s). ! if (char2cells(fill_diff) > 1) { c_extra = '-'; c_final = NUL; } else { ! c_extra = fill_diff; c_final = NUL; } # ifdef FEAT_RIGHTLEFT --- 1268,1281 ---- if (filler_todo > 0) { // Draw "deleted" diff line(s). ! if (char2cells(wp->w_fill_chars.diff) > 1) { c_extra = '-'; c_final = NUL; } else { ! c_extra = wp->w_fill_chars.diff; c_final = NUL; } # ifdef FEAT_RIGHTLEFT *************** *** 1352,1358 **** #endif ) { ! screen_line(screen_row, wp->w_wincol, col, -wp->w_width, screen_line_flags); // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. --- 1352,1358 ---- #endif ) { ! 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,2865 **** } #endif ! screen_line(screen_row, wp->w_wincol, col, wp->w_width, screen_line_flags); row++; --- 2859,2865 ---- } #endif ! screen_line(wp, screen_row, wp->w_wincol, col, wp->w_width, screen_line_flags); row++; *************** *** 3160,3170 **** ) { #ifdef FEAT_CONCEAL ! screen_line(screen_row, wp->w_wincol, col - boguscols, wp->w_width, screen_line_flags); boguscols = 0; #else ! screen_line(screen_row, wp->w_wincol, col, wp->w_width, screen_line_flags); #endif ++row; --- 3160,3170 ---- ) { #ifdef FEAT_CONCEAL ! screen_line(wp, screen_row, wp->w_wincol, col - boguscols, wp->w_width, screen_line_flags); boguscols = 0; #else ! screen_line(wp, screen_row, wp->w_wincol, col, wp->w_width, screen_line_flags); #endif ++row; *** ../vim-9.0.0035/src/mouse.c 2022-06-16 11:37:51.000000000 +0100 --- src/mouse.c 2022-07-04 16:35:37.197400173 +0100 *************** *** 2018,2024 **** count |= CURSOR_MOVED; // Cursor has moved # ifdef FEAT_FOLDING ! if (mouse_char == fill_foldclosed) count |= MOUSE_FOLD_OPEN; else if (mouse_char != ' ') count |= MOUSE_FOLD_CLOSE; --- 2018,2024 ---- count |= CURSOR_MOVED; // Cursor has moved # ifdef FEAT_FOLDING ! if (mouse_char == curwin->w_fill_chars.foldclosed) count |= MOUSE_FOLD_OPEN; else if (mouse_char != ' ') count |= MOUSE_FOLD_CLOSE; *** ../vim-9.0.0035/src/optiondefs.h 2022-06-29 18:39:05.015841419 +0100 --- src/optiondefs.h 2022-07-04 17:02:06.948133305 +0100 *************** *** 182,187 **** --- 182,188 ---- # 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,953 **** {(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 *)"vert:|,fold:-,eob:~", (char_u *)0L} SCTX_INIT}, {"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT, --- 948,954 ---- {(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_FCS, {(char_u *)"vert:|,fold:-,eob:~", (char_u *)0L} SCTX_INIT}, {"fixendofline", "fixeol", P_BOOL|P_VI_DEF|P_RSTAT, *** ../vim-9.0.0035/src/option.h 2022-05-21 19:39:20.000000000 +0100 --- src/option.h 2022-07-04 16:40:49.405300034 +0100 *************** *** 1238,1243 **** --- 1238,1244 ---- { WV_LIST = 0 , WV_LCS + , WV_FCS #ifdef FEAT_ARABIC , WV_ARAB #endif *** ../vim-9.0.0035/src/mbyte.c 2022-06-09 20:49:49.000000000 +0100 --- src/mbyte.c 2022-07-04 16:58:34.740226987 +0100 *************** *** 4229,4236 **** #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. */ int utf_valid_string(char_u *s, char_u *end) --- 4229,4235 ---- #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. Otherwise stop at "end". */ int utf_valid_string(char_u *s, char_u *end) *************** *** 5529,5534 **** --- 5528,5534 ---- 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,5677 **** // 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; ! } else { ! 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; } } } vim_free(cw_table_save); } --- 5648,5683 ---- // Check that the new value does not conflict with 'fillchars' or // 'listchars'. if (set_chars_option(curwin, &p_fcs) != NULL) ! 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; FOR_ALL_TAB_WINDOWS(tp, wp) { if (set_chars_option(wp, &wp->w_p_lcs) != NULL) { ! 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); } *** ../vim-9.0.0035/src/proto/screen.pro 2022-06-27 23:15:21.000000000 +0100 --- src/proto/screen.pro 2022-07-04 17:14:32.551470103 +0100 *************** *** 7,13 **** 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 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); --- 7,13 ---- 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(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,54 **** 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 redrawing(void); int messaging(void); void comp_col(void); --- 48,54 ---- void draw_tabline(void); void get_trans_bufname(buf_T *buf); int fillchar_status(int *attr, win_T *wp); ! int fillchar_vsep(int *attr, win_T *wp); int redrawing(void); int messaging(void); void comp_col(void); *** ../vim-9.0.0035/src/testdir/test_display.vim 2022-04-09 12:33:17.000000000 +0100 --- src/testdir/test_display.vim 2022-07-04 17:29:16.118453795 +0100 *************** *** 356,361 **** --- 356,389 ---- 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 *** ../vim-9.0.0035/src/testdir/dumps/Test_display_fillchars_1.dump 2022-07-04 17:32:54.886261399 +0100 --- src/testdir/dumps/Test_display_fillchars_1.dump 2022-07-04 17:29:19.858449323 +0100 *************** *** 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 *** ../vim-9.0.0035/src/testdir/dumps/Test_display_fillchars_2.dump 2022-07-04 17:32:54.894261404 +0100 --- src/testdir/dumps/Test_display_fillchars_2.dump 2022-07-04 17:29:21.010447948 +0100 *************** *** 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 *** ../vim-9.0.0035/src/testdir/screendump.vim 2022-05-06 11:18:24.000000000 +0100 --- src/testdir/screendump.vim 2022-07-04 17:26:36.558643489 +0100 *************** *** 75,80 **** --- 75,82 ---- 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) *** ../vim-9.0.0035/src/testdir/runtest.vim 2022-06-30 22:13:56.200846349 +0100 --- src/testdir/runtest.vim 2022-07-04 17:27:07.162607215 +0100 *************** *** 481,487 **** call add(total_errors, 'Run ' . g:run_nr . ':') call extend(total_errors, v:errors) ! 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 --- 481,487 ---- call add(total_errors, 'Run ' . g:run_nr . ':') call extend(total_errors, v:errors) ! 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 *** ../vim-9.0.0035/src/version.c 2022-07-04 13:37:03.937167269 +0100 --- src/version.c 2022-07-04 17:32:42.142254364 +0100 *************** *** 737,738 **** --- 737,740 ---- { /* Add new patch number below this line */ + /**/ + 36, /**/ -- hundred-and-one symptoms of being an internet addict: 43. You tell the kids they can't use the computer because "Daddy's got work to do" and you don't even have a job. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///