From 4dd9252d6f0e93c9118c808bd47f407d581947a8 Mon Sep 17 00:00:00 2001 From: Anton Sharonov Date: Mon, 4 Jul 2022 10:47:31 +0100 Subject: [PATCH 1/8] patch 9.0.0033: on a Belgian keyboard CTRL-[ does not work Problem: On a Belgian keyboard CTRL-[ does not work. Solution: Handle GDK_KEY_dead_circumflex. (Anton Sharonov, closes #10658) --- src/gui_gtk_x11.c | 26 ++++++++++++++++++++++++++ src/version.c | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 0cd6613032..fd582dd799 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1160,6 +1160,7 @@ key_press_event(GtkWidget *widget UNUSED, int key; guint state; char_u *s, *d; + int ctrl_prefix_added = 0; gui.event_time = event->time; key_sym = event->keyval; @@ -1245,6 +1246,20 @@ key_press_event(GtkWidget *widget UNUSED, } } + // Belgian Ctrl+[ workaround + if (len == 0 && key_sym == GDK_KEY_dead_circumflex) + { + string[0] = CSI; + string[1] = KS_MODIFIER; + string[2] = MOD_MASK_CTRL; + string[3] = '['; + len = 4; + add_to_input_buf(string, len); + // workaround has to return here, otherwise our fake string[] entries + // are confusing code downstream + return TRUE; + } + if (len == 0) // Unrecognized key return TRUE; @@ -1288,6 +1303,8 @@ key_press_event(GtkWidget *widget UNUSED, string2[1] = KS_MODIFIER; string2[2] = modifiers; add_to_input_buf(string2, 3); + if (modifiers == 0x4) + ctrl_prefix_added = 1; } // Check if the key interrupts. @@ -1302,6 +1319,15 @@ key_press_event(GtkWidget *widget UNUSED, } } + // workaround for German keyboard, where instead of '[' char we have code + // sequence of bytes 195, 188 (UTF-8 for "u-umlaut") + if (ctrl_prefix_added && len == 2 + && ((int)string[0]) == 195 + && ((int)string[1]) == 188) + { + string[0] = 91; // ASCII('[') + len = 1; + } add_to_input_buf(string, len); // blank out the pointer if necessary diff --git a/src/version.c b/src/version.c index 1232f4e02f..419e25f6d3 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 33, /**/ 32, /**/ From 288ed23e3929ff55a8ae30db0ba3f57b6f119dc8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 4 Jul 2022 11:03:07 +0100 Subject: [PATCH 2/8] patch 9.0.0034: spell tests do not always clear the word list Problem: Spell tests do not always clear the word list. Solution: Clear the word list in TearDown(). (closes #10659) --- src/testdir/test_spell.vim | 9 ++++++--- src/testdir/test_spell_utf8.vim | 7 +++---- src/version.c | 2 ++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim index 0187a175a8..d3f56d8d14 100644 --- a/src/testdir/test_spell.vim +++ b/src/testdir/test_spell.vim @@ -14,6 +14,8 @@ func TearDown() call delete('Xtest.latin1.add.spl') call delete('Xtest.latin1.spl') call delete('Xtest.latin1.sug') + " set 'encoding' to clear the word list + set encoding=utf-8 endfunc func Test_wrap_search() @@ -781,6 +783,10 @@ func Test_zz_sal_and_addition() set spl=Xtest_ca.latin1.spl call assert_equal("elequint", FirstSpellWord()) call assert_equal("elekwint", SecondSpellWord()) + + bwipe! + set spellfile= + set spl& endfunc func Test_spellfile_value() @@ -864,9 +870,6 @@ func Test_spell_good_word_invalid() sil! norm z= bwipe! - " clear the internal word list - set enc=latin1 - set enc=utf-8 endfunc func LoadAffAndDic(aff_contents, dic_contents) diff --git a/src/testdir/test_spell_utf8.vim b/src/testdir/test_spell_utf8.vim index c71308be56..07cb87af6c 100644 --- a/src/testdir/test_spell_utf8.vim +++ b/src/testdir/test_spell_utf8.vim @@ -13,6 +13,8 @@ func TearDown() call delete('Xtest.utf-8.add.spl') call delete('Xtest.utf-8.spl') call delete('Xtest.utf-8.sug') + " set 'encoding' to clear the word list + set encoding=utf-8 endfunc let g:test_data_aff1 = [ @@ -484,7 +486,6 @@ let g:test_data_aff_sal = [ \ ] func LoadAffAndDic(aff_contents, dic_contents) - set enc=utf-8 set spellfile= call writefile(a:aff_contents, "Xtest.aff") call writefile(a:dic_contents, "Xtest.dic") @@ -759,6 +760,7 @@ func Test_spell_sal_and_addition() call assert_equal("elequint", FirstSpellWord()) call assert_equal("elekwint", SecondSpellWord()) + bwipe! set spellfile= set spl& endfunc @@ -802,8 +804,6 @@ func Test_word_index() sil norm z= bwipe! - " clear the word list - set enc=utf-8 call delete('Xtmpfile') endfunc @@ -816,7 +816,6 @@ func Test_check_empty_line() sil! norm P]svc norm P]s - " TODO: should we clear the word list? bwipe! endfunc diff --git a/src/version.c b/src/version.c index 419e25f6d3..180a4cf8c9 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 34, /**/ 33, /**/ From 54e5fed6d27b747ff152cdb6edfb72ff60e70939 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 13:37:07 +0100 Subject: [PATCH 3/8] patch 9.0.0035: spell dump may go beyond end of an array Problem: Spell dump may go beyond end of an array. Solution: Limit the word length. --- src/spell.c | 5 +++-- src/testdir/test_spell.vim | 12 ++++++++++++ src/version.c | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/spell.c b/src/spell.c index d866a2df72..24abce4625 100644 --- a/src/spell.c +++ b/src/spell.c @@ -3996,9 +3996,10 @@ spell_dump_compl( n = arridx[depth] + curi[depth]; ++curi[depth]; c = byts[n]; - if (c == 0) + if (c == 0 || depth >= MAXWLEN - 1) { - // End of word, deal with the word. + // End of word or reached maximum length, deal with the + // word. // Don't use keep-case words in the fold-case tree, // they will appear in the keep-case tree. // Only use the word when the region matches. diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim index d3f56d8d14..a291eb5c7a 100644 --- a/src/testdir/test_spell.vim +++ b/src/testdir/test_spell.vim @@ -285,6 +285,18 @@ func Test_spellreall() bwipe! endfunc +func Test_spell_dump_word_length() + " this was running over MAXWLEN + new + noremap 0 0a0zW0000000 + sil! norm 0z=0 + sil norm 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + sil! norm 0z=0 + + bwipe! + nunmap 0 +endfunc + " Test spellsuggest({word} [, {max} [, {capital}]]) func Test_spellsuggest() " Verify suggestions are given even when spell checking is not enabled. diff --git a/src/version.c b/src/version.c index 180a4cf8c9..e22fb5673c 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 35, /**/ 34, /**/ From 96ba25ac01279f73c0ecb5d4aa4ff37aa359e5eb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 17:34:33 +0100 Subject: [PATCH 4/8] patch 9.0.0036: 'fillchars' cannot have window-local values Problem: 'fillchars' cannot have window-local values. Solution: Make 'fillchars' global-local. (closes #5206) --- runtime/doc/options.txt | 42 +++---- src/drawline.c | 12 +- src/drawscreen.c | 34 +++--- src/globals.h | 11 -- src/mbyte.c | 38 ++++--- src/mouse.c | 2 +- src/option.c | 60 ++++++---- src/option.h | 1 + src/optiondefs.h | 3 +- src/optionstr.c | 28 ++++- src/proto/screen.pro | 4 +- src/screen.c | 105 ++++++++++-------- src/structs.h | 19 ++++ .../dumps/Test_display_fillchars_1.dump | 12 ++ .../dumps/Test_display_fillchars_2.dump | 12 ++ src/testdir/runtest.vim | 2 +- src/testdir/screendump.vim | 2 + src/testdir/test_display.vim | 28 +++++ src/version.c | 2 + 19 files changed, 275 insertions(+), 142 deletions(-) create mode 100644 src/testdir/dumps/Test_display_fillchars_1.dump create mode 100644 src/testdir/dumps/Test_display_fillchars_2.dump diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 1d14c44333..cef9bd5503 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -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: + 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 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 + 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) diff --git a/src/drawline.c b/src/drawline.c index d87d800eff..789893b0b2 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -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; diff --git a/src/drawscreen.c b/src/drawscreen.c index 4fea562fcf..d1157043ea 100644 --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -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; } diff --git a/src/globals.h b/src/globals.h index ad563e4e96..6f2a1a5cd5 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 diff --git a/src/mbyte.c b/src/mbyte.c index 3656880e23..1e3ef72a36 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -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); } diff --git a/src/mouse.c b/src/mouse.c index 2297f81826..b01160952e 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -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; diff --git a/src/option.c b/src/option.c index 4a15c51b98..dd4ed1b4f5 100644 --- a/src/option.c +++ b/src/option.c @@ -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); } diff --git a/src/option.h b/src/option.h index 815a1156e2..5ac54efc6d 100644 --- a/src/option.h +++ b/src/option.h @@ -1238,6 +1238,7 @@ enum { WV_LIST = 0 , WV_LCS + , WV_FCS #ifdef FEAT_ARABIC , WV_ARAB #endif diff --git a/src/optiondefs.h b/src/optiondefs.h index 03e472ff9e..912209c025 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -182,6 +182,7 @@ # 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, diff --git a/src/optionstr.c b/src/optionstr.c index c26667a2bc..43b7e50973 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -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); } diff --git a/src/proto/screen.pro b/src/proto/screen.pro index 0ee1b5efb0..de42c43de4 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -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); diff --git a/src/screen.c b/src/screen.c index 01518882f2..1ddafb3b37 100644 --- a/src/screen.c +++ b/src/screen.c @@ -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 } diff --git a/src/structs.h b/src/structs.h index a537ccb8fd..11c3726f04 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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 index 0000000000..b0b1642bff --- /dev/null +++ b/src/testdir/dumps/Test_display_fillchars_1.dump @@ -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 index 0000000000..b983face03 --- /dev/null +++ b/src/testdir/dumps/Test_display_fillchars_2.dump @@ -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 diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index ce60c728e6..69443c5f9d 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -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 diff --git a/src/testdir/screendump.vim b/src/testdir/screendump.vim index d872a809db..e19d4f5e5b 100644 --- a/src/testdir/screendump.vim +++ b/src/testdir/screendump.vim @@ -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) diff --git a/src/testdir/test_display.vim b/src/testdir/test_display.vim index f5c8dc51e5..9fd0126d61 100644 --- a/src/testdir/test_display.vim +++ b/src/testdir/test_display.vim @@ -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 diff --git a/src/version.c b/src/version.c index e22fb5673c..95367ed934 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 36, /**/ 35, /**/ From 510f03738dfcadfe2099c5b6a58cb75f64dbaa82 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 17:46:22 +0100 Subject: [PATCH 5/8] patch 9.0.0037: build error Problem: Build error. Solution: Add missing change. --- src/terminal.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/terminal.c b/src/terminal.c index 451d59c4d0..f1536e2bdc 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -3775,7 +3775,7 @@ update_system_term(term_T *term) else pos.col = 0; - screen_line(term->tl_toprow + pos.row, 0, pos.col, Columns, 0); + screen_line(curwin, term->tl_toprow + pos.row, 0, pos.col, Columns, 0); } term->tl_dirty_row_start = MAX_ROW; @@ -3894,7 +3894,7 @@ term_update_window(win_T *wp) else pos.col = 0; - screen_line(wp->w_winrow + pos.row + screen_line(wp, wp->w_winrow + pos.row #ifdef FEAT_MENU + winbar_height(wp) #endif diff --git a/src/version.c b/src/version.c index 95367ed934..81305060b9 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 37, /**/ 36, /**/ From 5ed26faace574f6b36744f9e17075d7e806aa877 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 18:05:51 +0100 Subject: [PATCH 6/8] patch 9.0.0038: 'listchars' test fails Problem: 'listchars' test fails. Solution: Use window-local value after setting the global value --- src/optionstr.c | 18 ++++++++++-------- src/version.c | 2 ++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/optionstr.c b/src/optionstr.c index 43b7e50973..1f9a0e5d52 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -1313,15 +1313,16 @@ ambw_end: tabpage_T *tp; win_T *wp; - // The current window is set to use the global 'listchars' value. - // So clear the window-local value. + // If the current window is set to use the global 'listchars' + // value, clear the window-local value. if (!(opt_flags & OPT_GLOBAL)) clear_string_option(&curwin->w_p_lcs); FOR_ALL_TAB_WINDOWS(tp, wp) + // If the current window has a local value need to apply it + // again, it was changed when setting the global value. // 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); + (void)set_chars_option(wp, &wp->w_p_lcs); redraw_all_later(NOT_VALID); } @@ -1339,15 +1340,16 @@ ambw_end: tabpage_T *tp; win_T *wp; - // The current window is set to use the global 'fillchars' value. - // So clear the window-local value. + // If the current window is set to use the global 'fillchars' + // value clear the window-local value. if (!(opt_flags & OPT_GLOBAL)) clear_string_option(&curwin->w_p_fcs); FOR_ALL_TAB_WINDOWS(tp, wp) + // If the current window has a local value need to apply it + // again, it was changed when setting the global value. // 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); + (void)set_chars_option(wp, &wp->w_p_fcs); redraw_all_later(NOT_VALID); } diff --git a/src/version.c b/src/version.c index 81305060b9..8ddbddaf82 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 38, /**/ 37, /**/ From 4c99e622ddd1cc0527262fda3b93e8e70f017371 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 19:58:17 +0100 Subject: [PATCH 7/8] patch 9.0.0039: not all systems have GDK_KEY_dead_circumflex Problem: Not all systems have GDK_KEY_dead_circumflex. (Hisashi T Fujinaka) Solution: Add an #ifdef. --- src/gui_gtk_x11.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index fd582dd799..d0d946cc0e 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1246,6 +1246,7 @@ key_press_event(GtkWidget *widget UNUSED, } } +#ifdef GDK_KEY_dead_circumflex // Belgian Ctrl+[ workaround if (len == 0 && key_sym == GDK_KEY_dead_circumflex) { @@ -1259,6 +1260,7 @@ key_press_event(GtkWidget *widget UNUSED, // are confusing code downstream return TRUE; } +#endif if (len == 0) // Unrecognized key return TRUE; diff --git a/src/version.c b/src/version.c index 8ddbddaf82..b2c63c4441 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 39, /**/ 38, /**/ From b67f0c8e495cfbfc09d6c7ff670b8162faf07b01 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 4 Jul 2022 21:03:36 +0100 Subject: [PATCH 8/8] patch 9.0.0040: use of set_chars_option() is confusing Problem: Use of set_chars_option() is confusing. Solution: Add "apply" argument to store the result or not. Merge similar code. --- src/mbyte.c | 8 +++---- src/option.c | 12 +++++----- src/optionstr.c | 55 +++++++++++++++++--------------------------- src/proto/screen.pro | 2 +- src/screen.c | 48 +++++++++++++++++++++++++------------- src/version.c | 2 ++ 6 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/mbyte.c b/src/mbyte.c index 1e3ef72a36..691c1608e3 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -5647,9 +5647,9 @@ 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) + if (set_chars_option(curwin, &p_fcs, FALSE) != NULL) error = e_conflicts_with_value_of_fillchars; - else if (set_chars_option(curwin, &p_lcs) != NULL) + else if (set_chars_option(curwin, &p_lcs, FALSE) != NULL) error = e_conflicts_with_value_of_listchars; else { @@ -5658,12 +5658,12 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED) 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, FALSE) != NULL) { error = e_conflicts_with_value_of_listchars; break; } - if (set_chars_option(wp, &wp->w_p_fcs) != NULL) + if (set_chars_option(wp, &wp->w_p_fcs, FALSE) != NULL) { error = e_conflicts_with_value_of_fillchars; break; diff --git a/src/option.c b/src/option.c index dd4ed1b4f5..1b4b9da0d3 100644 --- a/src/option.c +++ b/src/option.c @@ -2433,10 +2433,10 @@ didset_options2(void) check_opt_wim(); // Parse default for 'listchars'. - (void)set_chars_option(curwin, &curwin->w_p_lcs); + (void)set_chars_option(curwin, &curwin->w_p_lcs, TRUE); // Parse default for 'fillchars'. - (void)set_chars_option(curwin, &curwin->w_p_fcs); + (void)set_chars_option(curwin, &curwin->w_p_fcs, TRUE); #ifdef FEAT_CLIPBOARD // Parse default for 'clipboard' @@ -5204,12 +5204,12 @@ unset_global_local_option(char_u *name, void *from) break; case PV_LCS: clear_string_option(&((win_T *)from)->w_p_lcs); - set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs); + set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs, TRUE); 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); + set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs, TRUE); redraw_later(NOT_VALID); break; case PV_VE: @@ -5607,8 +5607,8 @@ after_copy_winopt(win_T *wp) fill_culopt_flags(NULL, wp); check_colorcolumn(wp); #endif - set_chars_option(wp, &wp->w_p_lcs); - set_chars_option(wp, &wp->w_p_fcs); + set_chars_option(wp, &wp->w_p_lcs, TRUE); + set_chars_option(wp, &wp->w_p_fcs, TRUE); } static char_u * diff --git a/src/optionstr.c b/src/optionstr.c index 1f9a0e5d52..5147a2120c 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -866,7 +866,7 @@ did_set_string_option( { if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK) errmsg = e_invalid_argument; - else if (set_chars_option(curwin, &p_fcs) != NULL) + else if (set_chars_option(curwin, &p_fcs, FALSE) != NULL) errmsg = e_conflicts_with_value_of_fillchars; else { @@ -875,7 +875,7 @@ did_set_string_option( 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, FALSE) != NULL) { errmsg = e_conflicts_with_value_of_listchars; goto ambw_end; @@ -1304,60 +1304,47 @@ ambw_end: } } - // global 'listchars' - else if (varp == &p_lcs) + // global 'listchars' or 'fillchars' + else if (varp == &p_lcs || varp == &p_fcs) { - errmsg = set_chars_option(curwin, varp); + char_u **local_ptr = varp == &p_lcs + ? &curwin->w_p_lcs : &curwin->w_p_fcs; + + // only apply the global value to "curwin" when it does not have a + // local value + errmsg = set_chars_option(curwin, varp, + **local_ptr == NUL || !(opt_flags & OPT_GLOBAL)); if (errmsg == NULL) { tabpage_T *tp; win_T *wp; - // If the current window is set to use the global 'listchars' - // value, clear the window-local value. + // If the current window is set to use the global + // 'listchars'/'fillchars' value, clear the window-local value. if (!(opt_flags & OPT_GLOBAL)) - clear_string_option(&curwin->w_p_lcs); + clear_string_option(local_ptr); FOR_ALL_TAB_WINDOWS(tp, wp) + { // If the current window has a local value need to apply it // again, it was changed when setting the global value. // 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); + local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs; + if (**local_ptr == NUL) + (void)set_chars_option(wp, local_ptr, TRUE); + } redraw_all_later(NOT_VALID); } } // local 'listchars' else if (varp == &curwin->w_p_lcs) - errmsg = set_chars_option(curwin, varp); + errmsg = set_chars_option(curwin, varp, TRUE); - // 'fillchars' - else if (varp == &p_fcs) - { - errmsg = set_chars_option(curwin, varp); - if (errmsg == NULL) - { - tabpage_T *tp; - win_T *wp; - - // If the current window is set to use the global 'fillchars' - // value clear the window-local value. - if (!(opt_flags & OPT_GLOBAL)) - clear_string_option(&curwin->w_p_fcs); - FOR_ALL_TAB_WINDOWS(tp, wp) - // If the current window has a local value need to apply it - // again, it was changed when setting the global value. - // 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_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, TRUE); } #ifdef FEAT_CMDWIN diff --git a/src/proto/screen.pro b/src/proto/screen.pro index de42c43de4..66fc0f3da2 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -55,5 +55,5 @@ void comp_col(void); int number_width(win_T *wp); int screen_screencol(void); int screen_screenrow(void); -char *set_chars_option(win_T *wp, char_u **varp); +char *set_chars_option(win_T *wp, char_u **varp, int apply); /* vim: set ft=c : */ diff --git a/src/screen.c b/src/screen.c index 1ddafb3b37..db251c0c49 100644 --- a/src/screen.c +++ b/src/screen.c @@ -4843,11 +4843,13 @@ get_encoded_char_adv(char_u **p) /* * Handle setting 'listchars' or 'fillchars'. + * "varp" points to either the global or the window-local value. + * When "apply" is FALSE do not store the flags, only check for errors. * Assume monocell characters. * Returns error message, NULL if it's OK. */ char * -set_chars_option(win_T *wp, char_u **varp) +set_chars_option(win_T *wp, char_u **varp, int apply) { int round, i, len, len2, entries; char_u *p, *s; @@ -4856,11 +4858,16 @@ set_chars_option(win_T *wp, char_u **varp) 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 is_listchars = (varp == &p_lcs || varp == &wp->w_p_lcs); + char_u *value = *varp; + struct charstab { int *cp; char *name; }; + struct charstab *tab; + static fill_chars_T fill_chars; static struct charstab filltab[] = { @@ -4874,6 +4881,7 @@ set_chars_option(win_T *wp, char_u **varp) {&fill_chars.diff, "diff"}, {&fill_chars.eob, "eob"}, }; + static lcs_chars_T lcs_chars; struct charstab lcstab[] = { @@ -4891,22 +4899,21 @@ set_chars_option(win_T *wp, char_u **varp) {NULL, "conceal"}, #endif }; - struct charstab *tab; - if (varp == &p_lcs || varp == &wp->w_p_lcs) + if (is_listchars) { tab = lcstab; CLEAR_FIELD(lcs_chars); entries = ARRAY_LENGTH(lcstab); if (varp == &wp->w_p_lcs && wp->w_p_lcs[0] == NUL) - varp = &p_lcs; + value = p_lcs; // local value is empty, us the global value } else { tab = filltab; entries = ARRAY_LENGTH(filltab); if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL) - varp = &p_fcs; + value = p_fcs; // local value is empty, us the global value } // first round: check for valid value, second round: assign values @@ -4915,7 +4922,7 @@ set_chars_option(win_T *wp, char_u **varp) if (round > 0) { // After checking that the value is valid: set defaults. - if (varp == &p_lcs || varp == &wp->w_p_lcs) + if (is_listchars) { for (i = 0; i < entries; ++i) if (tab[i].cp != NULL) @@ -4926,7 +4933,8 @@ set_chars_option(win_T *wp, char_u **varp) if (multispace_len > 0) { lcs_chars.multispace = ALLOC_MULT(int, multispace_len + 1); - lcs_chars.multispace[multispace_len] = NUL; + if (lcs_chars.multispace != NULL) + lcs_chars.multispace[multispace_len] = NUL; } else lcs_chars.multispace = NULL; @@ -4953,7 +4961,7 @@ set_chars_option(win_T *wp, char_u **varp) fill_chars.eob = '~'; } } - p = *varp; + p = value; while (*p) { for (i = 0; i < entries; ++i) @@ -5007,7 +5015,7 @@ set_chars_option(win_T *wp, char_u **varp) { len = (int)STRLEN("multispace"); len2 = (int)STRLEN("leadmultispace"); - if ((varp == &p_lcs || varp == &wp->w_p_lcs) + if (is_listchars && STRNCMP(p, "multispace", len) == 0 && p[len] == ':' && p[len + 1] != NUL) @@ -5044,7 +5052,7 @@ set_chars_option(win_T *wp, char_u **varp) } } - else if ((varp == &p_lcs || varp == &wp->w_p_lcs) + else if (is_listchars && STRNCMP(p, "leadmultispace", len2) == 0 && p[len2] == ':' && p[len2 + 1] != NUL) @@ -5090,15 +5098,23 @@ set_chars_option(win_T *wp, char_u **varp) } } - if (tab == lcstab) + if (apply) { - vim_free(wp->w_lcs_chars.multispace); - vim_free(wp->w_lcs_chars.leadmultispace); - wp->w_lcs_chars = lcs_chars; + if (is_listchars) + { + 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; + } } - else + else if (is_listchars) { - wp->w_fill_chars = fill_chars; + vim_free(lcs_chars.multispace); + vim_free(lcs_chars.leadmultispace); } return NULL; // no error diff --git a/src/version.c b/src/version.c index b2c63c4441..ed2caddd6f 100644 --- a/src/version.c +++ b/src/version.c @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 40, /**/ 39, /**/