vim-patch:8.2.3545: setcellwidths() may make 'listchars' or 'fillchars' invalid

Problem:    setcellwidths() may make 'listchars' or 'fillchars' invalid.
Solution:   Check the value and give an error. (closes vim/vim#9024)
94358a1e6e

Cherry-pick f_setcellwidths() change from patch 9.0.0036.
Cherry-pick 'ambiwidth' docs update from runtime update 079ba76ae7a7.
This commit is contained in:
zeertzjq
2022-08-08 12:08:28 +08:00
parent 01a7009af9
commit 9fedb6fd78
6 changed files with 55 additions and 4 deletions

View File

@@ -6837,6 +6837,9 @@ setcellwidths({list}) *setcellwidths()*
range overlaps with another.
Only characters with value 0x100 and higher can be used.
If the new value causes 'fillchars' or 'listchars' to become
invalid it is rejected and an error is given.
To clear the overrides pass an empty list: >
setcellwidths([]);

View File

@@ -591,6 +591,8 @@ A jump table for the options with a short description can be found at |Q_op|.
"double": Use twice the width of ASCII characters.
*E834* *E835*
The value "double" cannot be used if 'listchars' or 'fillchars'
contains a character that would be double width. These errors may
also be given when calling setcellwidths().
The values are overruled for characters specified with
|setcellwidths()|.

View File

@@ -1000,6 +1000,11 @@ EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String"));
EXTERN char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now"));
EXTERN char e_conflicts_with_value_of_listchars[]
INIT(= N_("E834: Conflicts with value of 'listchars'"));
EXTERN char e_conflicts_with_value_of_fillchars[]
INIT(= N_("E835: Conflicts with value of 'fillchars'"));
EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s"));
EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
EXTERN char e_cmdmap_repeated[]

View File

@@ -2838,7 +2838,38 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
xfree(ptrs);
xfree(cw_table);
cw_interval_T *const cw_table_save = cw_table;
const size_t cw_table_size_save = cw_table_size;
cw_table = table;
cw_table_size = (size_t)tv_list_len(l);
// Check that the new value does not conflict with 'fillchars' or
// 'listchars'.
char *error = 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, false) != NULL) {
error = e_conflicts_with_value_of_listchars;
} else {
FOR_ALL_TAB_WINDOWS(tp, wp) {
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, false) != 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;
xfree(table);
return;
}
xfree(cw_table_save);
}

View File

@@ -2580,11 +2580,11 @@ static char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, c
} else {
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (set_chars_option(wp, &wp->w_p_lcs, true) != NULL) {
errmsg = _("E834: Conflicts with value of 'listchars'");
errmsg = _(e_conflicts_with_value_of_listchars);
goto ambw_end;
}
if (set_chars_option(wp, &wp->w_p_fcs, true) != NULL) {
errmsg = _("E835: Conflicts with value of 'fillchars'");
errmsg = _(e_conflicts_with_value_of_fillchars);
goto ambw_end;
}
}
@@ -3605,7 +3605,7 @@ static int get_encoded_char_adv(char_u **p)
///
/// @param varp either &curwin->w_p_lcs or &curwin->w_p_fcs
/// @return error message, NULL if it's OK.
static char *set_chars_option(win_T *wp, char_u **varp, bool set)
char *set_chars_option(win_T *wp, char_u **varp, bool set)
{
int round, i, len, len2, entries;
char_u *p, *s;

View File

@@ -173,6 +173,16 @@ func Test_setcellwidths()
call assert_fails('call setcellwidths([[0x111, 0x122, 1], [0x122, 0x123, 2]])', 'E1113:')
call assert_fails('call setcellwidths([[0x33, 0x44, 2]])', 'E1114:')
set listchars=tab:--\\u2192
call assert_fails('call setcellwidths([[0x2192, 0x2192, 2]])', 'E834:')
set fillchars=stl:\\u2501
call assert_fails('call setcellwidths([[0x2501, 0x2501, 2]])', 'E835:')
set listchars&
set fillchars&
call setcellwidths([])
endfunc
func Test_print_overlong()