diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
commit | d5f194ce780c95821a855aca3c19426576d28ae0 (patch) | |
tree | d45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/optionstr.c | |
parent | c5d770d311841ea5230426cc4c868e8db27300a8 (diff) | |
parent | 44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff) | |
download | rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.gz rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.bz2 rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.zip |
Diffstat (limited to 'src/nvim/optionstr.c')
-rw-r--r-- | src/nvim/optionstr.c | 1021 |
1 files changed, 211 insertions, 810 deletions
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index bfb26a0be6..645bb23638 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -3,6 +3,7 @@ #include <stdint.h> #include <string.h> +#include "nvim/api/private/defs.h" #include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" @@ -15,7 +16,6 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/errors.h" -#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/ex_getln.h" @@ -45,6 +45,7 @@ #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" #include "nvim/strings.h" +#include "nvim/terminal.h" #include "nvim/types_defs.h" #include "nvim/vim_defs.h" #include "nvim/window.h" @@ -68,84 +69,6 @@ static const char e_wrong_number_of_characters_for_field_str[] static const char e_wrong_character_width_for_field_str[] = N_("E1512: Wrong character width for field \"%s\""); -static char *(p_ambw_values[]) = { "single", "double", NULL }; -static char *(p_bg_values[]) = { "light", "dark", NULL }; -static char *(p_bkc_values[]) = { "yes", "auto", "no", "breaksymlink", "breakhardlink", NULL }; -static char *(p_bo_values[]) = { "all", "backspace", "cursor", "complete", "copy", "ctrlg", "error", - "esc", "ex", "hangul", "insertmode", "lang", "mess", "showmatch", - "operator", "register", "shell", "spell", "term", "wildmode", - NULL }; -// Note: Keep this in sync with briopt_check() -static char *(p_briopt_values[]) = { "shift:", "min:", "sbr", "list:", "column:", NULL }; -// Note: Keep this in sync with diffopt_changed() -static char *(p_dip_values[]) = { "filler", "context:", "iblank", "icase", - "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", - "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", - "indent-heuristic", "linematch:", "algorithm:", NULL }; -static char *(p_dip_algorithm_values[]) = { "myers", "minimal", "patience", "histogram", NULL }; -static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", "unsigned", "blank", NULL }; -static char *(p_ff_values[]) = { "unix", "dos", "mac", NULL }; -static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL }; -static char *(p_cmp_values[]) = { "internal", "keepascii", NULL }; -// Note: Keep this in sync with fill_culopt_flags() -static char *(p_culopt_values[]) = { "line", "screenline", "number", "both", NULL }; -static char *(p_dy_values[]) = { "lastline", "truncate", "uhex", "msgsep", NULL }; -static char *(p_fdo_values[]) = { "all", "block", "hor", "mark", "percent", "quickfix", "search", - "tag", "insert", "undo", "jump", NULL }; -// Note: Keep this in sync with spell_check_sps() -static char *(p_sps_values[]) = { "best", "fast", "double", "expr:", "file:", "timeout:", NULL }; -/// Also used for 'viewoptions'! Keep in sync with SSOP_ flags. -static char *(p_ssop_values[]) = { "buffers", "winpos", "resize", "winsize", "localoptions", - "options", "help", "blank", "globals", "slash", "unix", "sesdir", - "curdir", "folds", "cursor", "tabpages", "terminal", "skiprtp", - NULL }; -// Keep in sync with SWB_ flags in option_vars.h -static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vsplit", "uselast", - NULL }; -static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL }; -static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL }; -// Keep in sync with TCL_ flags in option_vars.h -static char *(p_tcl_values[]) = { "left", "uselast", NULL }; -static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL }; -// Note: Keep this in sync with check_opt_wim() -static char *(p_wim_values[]) = { "full", "longest", "list", "lastused", NULL }; -static char *(p_wop_values[]) = { "fuzzy", "tagfile", "pum", NULL }; -static char *(p_wak_values[]) = { "yes", "menu", "no", NULL }; -static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", "mac", NULL }; -static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL }; -static char *(p_slm_values[]) = { "mouse", "key", "cmd", NULL }; -static char *(p_km_values[]) = { "startsel", "stopsel", NULL }; -static char *(p_scbopt_values[]) = { "ver", "hor", "jump", NULL }; -static char *(p_debug_values[]) = { "msg", "throw", "beep", NULL }; -static char *(p_ead_values[]) = { "both", "ver", "hor", NULL }; -static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix", "help", "acwrite", - "terminal", "prompt", NULL }; -static char *(p_bufhidden_values[]) = { "hide", "unload", "delete", "wipe", NULL }; -static char *(p_bs_values[]) = { "indent", "eol", "start", "nostop", NULL }; -static char *(p_fdm_values[]) = { "manual", "expr", "marker", "indent", - "syntax", "diff", NULL }; -static char *(p_fcl_values[]) = { "all", NULL }; -static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview", "popup", - "noinsert", "noselect", "fuzzy", NULL }; -#ifdef BACKSLASH_IN_FILENAME -static char *(p_csl_values[]) = { "slash", "backslash", NULL }; -#endif - -static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2", "auto:3", "auto:4", - "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", "yes:1", - "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8", - "yes:9", "number", NULL }; -static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", "auto:3", "auto:4", "auto:5", - "auto:6", "auto:7", "auto:8", "auto:9", "0", "1", "2", "3", "4", - "5", "6", "7", "8", "9", NULL }; -static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; -static char *(p_icm_values[]) = { "nosplit", "split", NULL }; -static char *(p_jop_values[]) = { "stack", "view", "clean", NULL }; -static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL }; -static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line", - "flush", NULL }; -static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; - /// All possible flags for 'shm'. /// the literal chars before 0 are removed flags. these are safely ignored static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_LINES, @@ -158,23 +81,23 @@ static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_LINES, /// option values. void didset_string_options(void) { - opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true); - opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, true); - opt_strings_flags(p_bo, p_bo_values, &bo_flags, true); - opt_strings_flags(p_cot, p_cot_values, &cot_flags, true); - opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true); - opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true); - opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true); - opt_strings_flags(p_dy, p_dy_values, &dy_flags, true); - opt_strings_flags(p_jop, p_jop_values, &jop_flags, true); - opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true); - opt_strings_flags(p_tc, p_tc_values, &tc_flags, false); - opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true); - opt_strings_flags(p_ve, p_ve_values, &ve_flags, true); - opt_strings_flags(p_swb, p_swb_values, &swb_flags, true); - opt_strings_flags(p_tcl, p_tcl_values, &tcl_flags, true); - opt_strings_flags(p_wop, p_wop_values, &wop_flags, true); - opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); + check_str_opt(kOptCasemap, NULL); + check_str_opt(kOptBackupcopy, NULL); + check_str_opt(kOptBelloff, NULL); + check_str_opt(kOptCompleteopt, NULL); + check_str_opt(kOptSessionoptions, NULL); + check_str_opt(kOptViewoptions, NULL); + check_str_opt(kOptFoldopen, NULL); + check_str_opt(kOptDisplay, NULL); + check_str_opt(kOptJumpoptions, NULL); + check_str_opt(kOptRedrawdebug, NULL); + check_str_opt(kOptTagcase, NULL); + check_str_opt(kOptTermpastefilter, NULL); + check_str_opt(kOptVirtualedit, NULL); + check_str_opt(kOptSwitchbuf, NULL); + check_str_opt(kOptTabclose, NULL); + check_str_opt(kOptWildoptions, NULL); + check_str_opt(kOptClipboard, NULL); } char *illegal_char(char *errbuf, size_t errbuflen, int c) @@ -300,7 +223,7 @@ int check_signcolumn(char *scl, win_T *wp) return FAIL; } - if (check_opt_strings(val, p_scl_values, false) == OK) { + if (opt_strings_flags(val, opt_scl_values, NULL, false) == OK) { if (wp == NULL) { return OK; } @@ -428,7 +351,7 @@ bool check_illegal_path_names(char *val, uint32_t flags) /// An option that accepts a list of flags is changed. /// e.g. 'viewoptions', 'switchbuf', 'casemap', etc. -static const char *did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list) +static const char *did_set_opt_flags(char *val, const char **values, unsigned *flagp, bool list) { if (opt_strings_flags(val, values, flagp, list) != OK) { return e_invarg; @@ -436,11 +359,40 @@ static const char *did_set_opt_flags(char *val, char **values, unsigned *flagp, return NULL; } -/// An option that accepts a list of string values is changed. -/// e.g. 'nrformats', 'scrollopt', 'wildoptions', etc. -static const char *did_set_opt_strings(char *val, char **values, bool list) +static const char **opt_values(OptIndex idx, size_t *values_len) +{ + OptIndex idx1 = idx == kOptViewoptions ? kOptSessionoptions + : idx == kOptFileformats ? kOptFileformat + : idx; + + vimoption_T *opt = get_option(idx1); + if (values_len != NULL) { + *values_len = opt->values_len; + } + return opt->values; +} + +static int check_str_opt(OptIndex idx, char **varp) { - return did_set_opt_flags(val, values, NULL, list); + vimoption_T *opt = get_option(idx); + if (varp == NULL) { + varp = opt->var; + } + bool list = opt->flags & (kOptFlagComma | kOptFlagOneComma); + const char **values = opt_values(idx, NULL); + return opt_strings_flags(*varp, values, opt->flags_var, list); +} + +int expand_set_str_generic(optexpand_T *args, int *numMatches, char ***matches) +{ + size_t values_len; + const char **values = opt_values(args->oe_idx, &values_len); + return expand_set_opt_string(args, values, values_len, numMatches, matches); +} + +const char *did_set_str_generic(optset_T *args) +{ + return check_str_opt(args->os_idx, args->os_varp) != OK ? e_invarg : NULL; } /// An option which is a list of flags is set. Valid values are in "flags". @@ -456,7 +408,7 @@ static const char *did_set_option_listflag(char *val, char *flags, char *errbuf, } /// Expand an option that accepts a list of string values. -static int expand_set_opt_string(optexpand_T *args, char **values, size_t numValues, +static int expand_set_opt_string(optexpand_T *args, const char **values, size_t numValues, int *numMatches, char ***matches) { regmatch_T *regmatch = args->oe_regmatch; @@ -473,8 +425,10 @@ static int expand_set_opt_string(optexpand_T *args, char **values, size_t numVal (*matches)[count++] = xstrdup(option_val); } - for (char **val = values; *val != NULL; val++) { - if (include_orig_val && *option_val != NUL) { + for (const char **val = values; *val != NULL; val++) { + if (**val == NUL) { + continue; // Ignore empty + } else if (include_orig_val && *option_val != NUL) { if (strcmp(*val, option_val) == 0) { continue; } @@ -566,28 +520,30 @@ static int expand_set_opt_listflag(optexpand_T *args, char *flags, int *numMatch } /// The 'ambiwidth' option is changed. -const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) +const char *did_set_ambiwidth(optset_T *args) { - if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } return check_chars_options(); } -int expand_set_ambiwidth(optexpand_T *args, int *numMatches, char ***matches) +/// The 'emoji' option is changed. +const char *did_set_emoji(optset_T *args) { - return expand_set_opt_string(args, - p_ambw_values, - ARRAY_SIZE(p_ambw_values) - 1, - numMatches, - matches); + if (check_str_opt(kOptAmbiwidth, NULL) != OK) { + return e_invarg; + } + return check_chars_options(); } /// The 'background' option is changed. const char *did_set_background(optset_T *args) { - if (check_opt_strings(p_bg, p_bg_values, false) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } if (args->os_oldval.string.data[0] == *p_bg) { @@ -609,16 +565,16 @@ const char *did_set_background(optset_T *args) check_string_option(&p_bg); init_highlight(false, false); } - return NULL; -} -int expand_set_background(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_bg_values, - ARRAY_SIZE(p_bg_values) - 1, - numMatches, - matches); + // Notify all terminal buffers that the background color changed so they can + // send a theme update notification + FOR_ALL_BUFFERS(buf) { + if (buf->terminal) { + terminal_notify_theme(buf->terminal, dark); + } + } + + return NULL; } /// The 'backspace' option is changed. @@ -628,19 +584,9 @@ const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) if (*p_bs != '2') { return e_invarg; } - } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { - return e_invarg; + return NULL; } - return NULL; -} - -int expand_set_backspace(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_bs_values, - ARRAY_SIZE(p_bs_values) - 1, - numMatches, - matches); + return did_set_str_generic(args); } /// The 'backupcopy' option is changed. @@ -664,15 +610,15 @@ const char *did_set_backupcopy(optset_T *args) // make the local value empty: use the global value *flags = 0; } else { - if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) { + if (opt_strings_flags(bkc, opt_bkc_values, flags, true) != OK) { return e_invarg; } - if (((*flags & BKC_AUTO) != 0) - + ((*flags & BKC_YES) != 0) - + ((*flags & BKC_NO) != 0) != 1) { + if (((*flags & kOptBkcFlagAuto) != 0) + + ((*flags & kOptBkcFlagYes) != 0) + + ((*flags & kOptBkcFlagNo) != 0) != 1) { // Must have exactly one of "auto", "yes" and "no". - opt_strings_flags(oldval, p_bkc_values, flags, true); + opt_strings_flags(oldval, opt_bkc_values, flags, true); return e_invarg; } } @@ -680,15 +626,6 @@ const char *did_set_backupcopy(optset_T *args) return NULL; } -int expand_set_backupcopy(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_bkc_values, - ARRAY_SIZE(p_bkc_values) - 1, - numMatches, - matches); -} - /// The 'backupext' or the 'patchmode' option is changed. const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) { @@ -700,21 +637,6 @@ const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) return NULL; } -/// The 'belloff' option is changed. -const char *did_set_belloff(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true); -} - -int expand_set_belloff(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_bo_values, - ARRAY_SIZE(p_bo_values) - 1, - numMatches, - matches); -} - /// The 'breakat' option is changed. const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED) { @@ -749,29 +671,11 @@ const char *did_set_breakindentopt(optset_T *args) return NULL; } -int expand_set_breakindentopt(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_briopt_values, - ARRAY_SIZE(p_briopt_values) - 1, - numMatches, - matches); -} - /// The 'bufhidden' option is changed. const char *did_set_bufhidden(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - return did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false); -} - -int expand_set_bufhidden(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_bufhidden_values, - ARRAY_SIZE(p_bufhidden_values) - 1, - numMatches, - matches); + return did_set_opt_flags(buf->b_p_bh, opt_bh_values, NULL, false); } /// The 'buftype' option is changed. @@ -782,7 +686,7 @@ const char *did_set_buftype(optset_T *args) // When 'buftype' is set, check for valid value. if ((buf->terminal && buf->b_p_bt[0] != 't') || (!buf->terminal && buf->b_p_bt[0] == 't') - || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) { + || opt_strings_flags(buf->b_p_bt, opt_bt_values, NULL, false) != OK) { return e_invarg; } if (win->w_status_height || global_stl_height()) { @@ -794,30 +698,6 @@ const char *did_set_buftype(optset_T *args) return NULL; } -int expand_set_buftype(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_buftype_values, - ARRAY_SIZE(p_buftype_values) - 1, - numMatches, - matches); -} - -/// The 'casemap' option is changed. -const char *did_set_casemap(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true); -} - -int expand_set_casemap(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_cmp_values, - ARRAY_SIZE(p_cmp_values) - 1, - numMatches, - matches); -} - /// The global 'listchars' or 'fillchars' option is changed. static const char *did_set_global_chars_option(win_T *win, char *val, CharsOption what, int opt_flags, char *errbuf, size_t errbuflen) @@ -901,21 +781,6 @@ const char *did_set_cinoptions(optset_T *args) return NULL; } -/// The 'clipboard' option is changed. -const char *did_set_clipboard(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true); -} - -int expand_set_clipboard(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_cb_values, - ARRAY_SIZE(p_cb_values) - 1, - numMatches, - matches); -} - /// The 'colorcolumn' option is changed. const char *did_set_colorcolumn(optset_T *args) { @@ -1007,18 +872,6 @@ const char *did_set_complete(optset_T *args) return NULL; } -int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches) -{ - static char *(p_cpt_values[]) = { - ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U", "f", NULL - }; - return expand_set_opt_string(args, - p_cpt_values, - ARRAY_SIZE(p_cpt_values) - 1, - numMatches, - matches); -} - /// The 'completeitemalign' option is changed. const char *did_set_completeitemalign(optset_T *args) { @@ -1079,46 +932,28 @@ const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) buf->b_cot_flags = 0; } - if (check_opt_strings(cot, p_cot_values, true) != OK) { + if (opt_strings_flags(cot, opt_cot_values, NULL, true) != OK) { return e_invarg; } - if (opt_strings_flags(cot, p_cot_values, flags, true) != OK) { + if (opt_strings_flags(cot, opt_cot_values, flags, true) != OK) { return e_invarg; } return NULL; } -int expand_set_completeopt(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_cot_values, - ARRAY_SIZE(p_cot_values) - 1, - numMatches, - matches); -} - #ifdef BACKSLASH_IN_FILENAME /// The 'completeslash' option is changed. const char *did_set_completeslash(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - if (check_opt_strings(p_csl, p_csl_values, false) != OK - || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { + if (opt_strings_flags(p_csl, opt_csl_values, NULL, false) != OK + || opt_strings_flags(buf->b_p_csl, opt_csl_values, NULL, false) != OK) { return e_invarg; } return NULL; } - -int expand_set_completeslash(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_csl_values, - ARRAY_SIZE(p_csl_values) - 1, - numMatches, - matches); -} #endif /// The 'concealcursor' option is changed. @@ -1161,37 +996,10 @@ const char *did_set_cursorlineopt(optset_T *args) return NULL; } -int expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_culopt_values, - ARRAY_SIZE(p_culopt_values) - 1, - numMatches, - matches); -} - -/// The 'debug' option is changed. -const char *did_set_debug(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_debug, p_debug_values, false); -} - -int expand_set_debug(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_debug_values, - ARRAY_SIZE(p_debug_values) - 1, - numMatches, - matches); -} - /// The 'diffopt' option is changed. const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { - if (diffopt_changed() == FAIL) { - return e_invarg; - } - return NULL; + return diffopt_changed() == FAIL ? e_invarg : NULL; } int expand_set_diffopt(optexpand_T *args, int *numMatches, char ***matches) @@ -1204,56 +1012,29 @@ int expand_set_diffopt(optexpand_T *args, int *numMatches, char ***matches) if (xp->xp_pattern - args->oe_set_arg >= (int)algo_len && strncmp(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0) { return expand_set_opt_string(args, - p_dip_algorithm_values, - ARRAY_SIZE(p_dip_algorithm_values) - 1, + opt_dip_algorithm_values, + ARRAY_SIZE(opt_dip_algorithm_values) - 1, numMatches, matches); } return FAIL; } - return expand_set_opt_string(args, - p_dip_values, - ARRAY_SIZE(p_dip_values) - 1, - numMatches, - matches); + return expand_set_str_generic(args, numMatches, matches); } /// The 'display' option is changed. -const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) +const char *did_set_display(optset_T *args) { - if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } init_chartab(); msg_grid_validate(); return NULL; } -int expand_set_display(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_dy_values, - ARRAY_SIZE(p_dy_values) - 1, - numMatches, - matches); -} - -/// The 'eadirection' option is changed. -const char *did_set_eadirection(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_ead, p_ead_values, false); -} - -int expand_set_eadirection(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_ead_values, - ARRAY_SIZE(p_ead_values) - 1, - numMatches, - matches); -} - /// One of the 'encoding', 'fileencoding' or 'makeencoding' /// options is changed. const char *did_set_encoding(optset_T *args) @@ -1329,14 +1110,17 @@ int expand_set_eventignore(optexpand_T *args, int *numMatches, char ***matches) const char *did_set_fileformat(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - char **varp = (char **)args->os_varp; const char *oldval = args->os_oldval.string.data; int opt_flags = args->os_flags; if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { return e_modifiable; - } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { - return e_invarg; } + + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; + } + redraw_titles(); // update flag in swap file ml_setflags(buf); @@ -1348,30 +1132,15 @@ const char *did_set_fileformat(optset_T *args) return NULL; } -int expand_set_fileformat(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_ff_values, - ARRAY_SIZE(p_ff_values) - 1, - numMatches, - matches); -} - /// Function given to ExpandGeneric() to obtain the possible arguments of the /// fileformat options. char *get_fileformat_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) { - if (idx >= (int)ARRAY_SIZE(p_ff_values)) { + if (idx >= (int)ARRAY_SIZE(opt_ff_values)) { return NULL; } - return p_ff_values[idx]; -} - -/// The 'fileformats' option is changed. -const char *did_set_fileformats(optset_T *args) -{ - return did_set_opt_strings(p_ffs, p_ff_values, true); + return (char *)opt_ff_values[idx]; } /// The 'filetype' or the 'syntax' option is changed. @@ -1392,40 +1161,6 @@ const char *did_set_filetype_or_syntax(optset_T *args) return NULL; } -/// The 'foldclose' option is changed. -const char *did_set_foldclose(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_fcl, p_fcl_values, true); -} - -int expand_set_foldclose(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_fcl_values, - ARRAY_SIZE(p_fcl_values) - 1, - numMatches, - matches); -} - -/// The 'foldcolumn' option is changed. -const char *did_set_foldcolumn(optset_T *args) -{ - char **varp = (char **)args->os_varp; - if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { - return e_invarg; - } - return NULL; -} - -int expand_set_foldcolumn(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_fdc_values, - ARRAY_SIZE(p_fdc_values) - 1, - numMatches, - matches); -} - /// The 'foldexpr' option is changed. const char *did_set_foldexpr(optset_T *args) { @@ -1472,11 +1207,11 @@ const char *did_set_foldmarker(optset_T *args) /// The 'foldmethod' option is changed. const char *did_set_foldmethod(optset_T *args) { - win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; - if (check_opt_strings(*varp, p_fdm_values, false) != OK || **varp == NUL) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } + win_T *win = (win_T *)args->os_win; foldUpdateAll(win); if (foldmethodIsDiff(win)) { newFoldLevel(); @@ -1484,30 +1219,6 @@ const char *did_set_foldmethod(optset_T *args) return NULL; } -int expand_set_foldmethod(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_fdm_values, - ARRAY_SIZE(p_fdm_values) - 1, - numMatches, - matches); -} - -/// The 'foldopen' option is changed. -const char *did_set_foldopen(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true); -} - -int expand_set_foldopen(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_fdo_values, - ARRAY_SIZE(p_fdo_values) - 1, - numMatches, - matches); -} - /// The 'formatoptions' option is changed. const char *did_set_formatoptions(optset_T *args) { @@ -1586,16 +1297,7 @@ const char *did_set_inccommand(optset_T *args FUNC_ATTR_UNUSED) if (cmdpreview) { return e_invarg; } - return did_set_opt_strings(p_icm, p_icm_values, false); -} - -int expand_set_inccommand(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_icm_values, - ARRAY_SIZE(p_icm_values) - 1, - numMatches, - matches); + return did_set_str_generic(args); } /// The 'iskeyword' option is changed. @@ -1629,21 +1331,6 @@ const char *did_set_isopt(optset_T *args) return NULL; } -/// The 'jumpoptions' option is changed. -const char *did_set_jumpoptions(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true); -} - -int expand_set_jumpoptions(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_jop_values, - ARRAY_SIZE(p_jop_values) - 1, - numMatches, - matches); -} - /// The 'keymap' option has changed. const char *did_set_keymap(optset_T *args) { @@ -1699,23 +1386,15 @@ const char *did_set_keymap(optset_T *args) /// The 'keymodel' option is changed. const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) { - if (check_opt_strings(p_km, p_km_values, true) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } km_stopsel = (vim_strchr(p_km, 'o') != NULL); km_startsel = (vim_strchr(p_km, 'a') != NULL); return NULL; } -int expand_set_keymodel(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_km_values, - ARRAY_SIZE(p_km_values) - 1, - numMatches, - matches); -} - /// The 'lispoptions' option is changed. const char *did_set_lispoptions(optset_T *args) { @@ -1727,16 +1406,6 @@ const char *did_set_lispoptions(optset_T *args) return NULL; } -int expand_set_lispoptions(optexpand_T *args, int *numMatches, char ***matches) -{ - static char *(p_lop_values[]) = { "expr:0", "expr:1", NULL }; - return expand_set_opt_string(args, - p_lop_values, - ARRAY_SIZE(p_lop_values) - 1, - numMatches, - matches); -} - /// The 'matchpairs' option is changed. const char *did_set_matchpairs(optset_T *args) { @@ -1764,6 +1433,15 @@ const char *did_set_matchpairs(optset_T *args) return NULL; } +/// Process the updated 'messagesopt' option value. +const char *did_set_messagesopt(optset_T *args FUNC_ATTR_UNUSED) +{ + if (messagesopt_changed() == FAIL) { + return e_invarg; + } + return NULL; +} + /// The 'mkspellmem' option is changed. const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) { @@ -1786,21 +1464,6 @@ int expand_set_mouse(optexpand_T *args, int *numMatches, char ***matches) return expand_set_opt_listflag(args, MOUSE_ALL, numMatches, matches); } -/// The 'mousemodel' option is changed. -const char *did_set_mousemodel(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_mousem, p_mousem_values, false); -} - -int expand_set_mousemodel(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_mousem_values, - ARRAY_SIZE(p_mousem_values) - 1, - numMatches, - matches); -} - /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) @@ -1866,33 +1529,6 @@ const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) return NULL; } -int expand_set_mousescroll(optexpand_T *args, int *numMatches, char ***matches) -{ - static char *(p_mousescroll_values[]) = { "hor:", "ver:", NULL }; - return expand_set_opt_string(args, - p_mousescroll_values, - ARRAY_SIZE(p_mousescroll_values) - 1, - numMatches, - matches); -} - -/// The 'nrformats' option is changed. -const char *did_set_nrformats(optset_T *args) -{ - char **varp = (char **)args->os_varp; - - return did_set_opt_strings(*varp, p_nf_values, true); -} - -int expand_set_nrformats(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_nf_values, - ARRAY_SIZE(p_nf_values) - 1, - numMatches, - matches); -} - /// One of the '*expr' options is changed:, 'diffexpr', 'foldexpr', 'foldtext', /// 'formatexpr', 'includeexpr', 'indentexpr', 'patchexpr' and 'charconvert'. const char *did_set_optexpr(optset_T *args) @@ -1909,61 +1545,18 @@ const char *did_set_optexpr(optset_T *args) return NULL; } -/// The 'redrawdebug' option is changed. -const char *did_set_redrawdebug(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true); -} - -/// The 'rightleftcmd' option is changed. -const char *did_set_rightleftcmd(optset_T *args) -{ - char **varp = (char **)args->os_varp; - - // Currently only "search" is a supported value. - if (**varp != NUL && strcmp(*varp, "search") != 0) { - return e_invarg; - } - - return NULL; -} - -int expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char ***matches) -{ - static char *(p_rlc_values[]) = { "search", NULL }; - return expand_set_opt_string(args, - p_rlc_values, - ARRAY_SIZE(p_rlc_values) - 1, - numMatches, - matches); -} - /// The 'rulerformat' option is changed. const char *did_set_rulerformat(optset_T *args) { return did_set_statustabline_rulerformat(args, true, false); } -/// The 'scrollopt' option is changed. -const char *did_set_scrollopt(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_sbo, p_scbopt_values, true); -} - -int expand_set_scrollopt(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_scbopt_values, - ARRAY_SIZE(p_scbopt_values) - 1, - numMatches, - matches); -} - /// The 'selection' option is changed. const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { - if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } if (VIsual_active) { // Visual selection may be drawn differently. @@ -1972,54 +1565,22 @@ const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) return NULL; } -int expand_set_selection(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_sel_values, - ARRAY_SIZE(p_sel_values) - 1, - numMatches, - matches); -} - -/// The 'selectmode' option is changed. -const char *did_set_selectmode(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_slm, p_slm_values, true); -} - -int expand_set_selectmode(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_slm_values, - ARRAY_SIZE(p_slm_values) - 1, - numMatches, - matches); -} - /// The 'sessionoptions' option is changed. const char *did_set_sessionoptions(optset_T *args) { - if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { - return e_invarg; + const char *errmsg = did_set_str_generic(args); + if (errmsg != NULL) { + return errmsg; } - if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { + if ((ssop_flags & kOptSsopFlagCurdir) && (ssop_flags & kOptSsopFlagSesdir)) { // Don't allow both "sesdir" and "curdir". const char *oldval = args->os_oldval.string.data; - opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); + opt_strings_flags(oldval, opt_ssop_values, &ssop_flags, true); return e_invarg; } return NULL; } -int expand_set_sessionoptions(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_ssop_values, - ARRAY_SIZE(p_ssop_values) - 1, - numMatches, - matches); -} - const char *did_set_shada(optset_T *args) { char *errbuf = args->os_errbuf; @@ -2099,7 +1660,7 @@ const char *did_set_showbreak(optset_T *args) /// The 'showcmdloc' option is changed. const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) { - const char *errmsg = did_set_opt_strings(p_sloc, p_sloc_values, false); + const char *errmsg = did_set_str_generic(args); if (errmsg == NULL) { comp_col(); @@ -2108,15 +1669,6 @@ const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED) return errmsg; } -int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_sloc_values, - ARRAY_SIZE(p_sloc_values) - 1, - numMatches, - matches); -} - /// The 'signcolumn' option is changed. const char *did_set_signcolumn(optset_T *args) { @@ -2134,15 +1686,6 @@ const char *did_set_signcolumn(optset_T *args) return NULL; } -int expand_set_signcolumn(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_scl_values, - ARRAY_SIZE(p_scl_values) - 1, - numMatches, - matches); -} - /// The 'spellcapcheck' option is changed. const char *did_set_spellcapcheck(optset_T *args) { @@ -2185,25 +1728,16 @@ const char *did_set_spelloptions(optset_T *args) const char *val = args->os_newval.string.data; if (!(opt_flags & OPT_LOCAL) - && opt_strings_flags(val, p_spo_values, &spo_flags, true) != OK) { + && opt_strings_flags(val, opt_spo_values, &spo_flags, true) != OK) { return e_invarg; } if (!(opt_flags & OPT_GLOBAL) - && opt_strings_flags(val, p_spo_values, &win->w_s->b_p_spo_flags, true) != OK) { + && opt_strings_flags(val, opt_spo_values, &win->w_s->b_p_spo_flags, true) != OK) { return e_invarg; } return NULL; } -int expand_set_spelloptions(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_spo_values, - ARRAY_SIZE(p_spo_values) - 1, - numMatches, - matches); -} - /// The 'spellsuggest' option is changed. const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { @@ -2213,30 +1747,6 @@ const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) return NULL; } -int expand_set_spellsuggest(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_sps_values, - ARRAY_SIZE(p_sps_values) - 1, - numMatches, - matches); -} - -/// The 'splitkeep' option is changed. -const char *did_set_splitkeep(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_strings(p_spk, p_spk_values, false); -} - -int expand_set_splitkeep(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_spk_values, - ARRAY_SIZE(p_spk_values) - 1, - numMatches, - matches); -} - /// The 'statuscolumn' option is changed. const char *did_set_statuscolumn(optset_T *args) { @@ -2275,7 +1785,11 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) { ru_wid = wid; } else { - errmsg = check_stl_option(p_ruf); + // Validate the flags in 'rulerformat' only if it doesn't point to + // a custom function ("%!" flag). + if ((*varp)[1] != '!') { + errmsg = check_stl_option(p_ruf); + } } } else if (rulerformat || s[0] != '%' || s[1] != '!') { // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' @@ -2288,36 +1802,6 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf return errmsg; } -/// The 'switchbuf' option is changed. -const char *did_set_switchbuf(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true); -} - -int expand_set_switchbuf(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_swb_values, - ARRAY_SIZE(p_swb_values) - 1, - numMatches, - matches); -} - -/// The 'tabclose' option is changed. -const char *did_set_tabclose(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_tcl, p_tcl_values, &tcl_flags, true); -} - -int expand_set_tabclose(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_tcl_values, - ARRAY_SIZE(p_tcl_values) - 1, - numMatches, - matches); -} - /// The 'tabline' option is changed. const char *did_set_tabline(optset_T *args) { @@ -2344,37 +1828,12 @@ const char *did_set_tagcase(optset_T *args) if ((opt_flags & OPT_LOCAL) && *p == NUL) { // make the local value empty: use the global value *flags = 0; - } else if (*p == NUL - || opt_strings_flags(p, p_tc_values, flags, false) != OK) { + } else if (opt_strings_flags(p, opt_tc_values, flags, false) != OK) { return e_invarg; } return NULL; } -int expand_set_tagcase(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_tc_values, - ARRAY_SIZE(p_tc_values) - 1, - numMatches, - matches); -} - -/// The 'termpastefilter' option is changed. -const char *did_set_termpastefilter(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true); -} - -int expand_set_termpastefilter(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_tpf_values, - ARRAY_SIZE(p_tpf_values) - 1, - numMatches, - matches); -} - /// The 'titlestring' or the 'iconstring' option is changed. static const char *did_set_titleiconstring(optset_T *args, int flagval) { @@ -2471,12 +1930,6 @@ const char *did_set_verbosefile(optset_T *args) return NULL; } -/// The 'viewoptions' option is changed. -const char *did_set_viewoptions(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true); -} - /// The 'virtualedit' option is changed. const char *did_set_virtualedit(optset_T *args) { @@ -2494,7 +1947,7 @@ const char *did_set_virtualedit(optset_T *args) // make the local value empty: use the global value *flags = 0; } else { - if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { + if (opt_strings_flags(ve, opt_ve_values, flags, true) != OK) { return e_invarg; } else if (strcmp(ve, args->os_oldval.string.data) != 0) { // Recompute cursor position in case the new 've' setting @@ -2506,15 +1959,6 @@ const char *did_set_virtualedit(optset_T *args) return NULL; } -int expand_set_virtualedit(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_ve_values, - ARRAY_SIZE(p_ve_values) - 1, - numMatches, - matches); -} - /// The 'whichwrap' option is changed. const char *did_set_whichwrap(optset_T *args) { @@ -2539,48 +1983,6 @@ const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) return NULL; } -int expand_set_wildmode(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_wim_values, - ARRAY_SIZE(p_wim_values) - 1, - numMatches, - matches); -} - -/// The 'wildoptions' option is changed. -const char *did_set_wildoptions(optset_T *args FUNC_ATTR_UNUSED) -{ - return did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true); -} - -int expand_set_wildoptions(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_wop_values, - ARRAY_SIZE(p_wop_values) - 1, - numMatches, - matches); -} - -/// The 'winaltkeys' option is changed. -const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) -{ - if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { - return e_invarg; - } - return NULL; -} - -int expand_set_winaltkeys(optexpand_T *args, int *numMatches, char ***matches) -{ - return expand_set_opt_string(args, - p_wak_values, - ARRAY_SIZE(p_wak_values) - 1, - numMatches, - matches); -} - /// The 'winbar' option is changed. const char *did_set_winbar(optset_T *args) { @@ -2603,16 +2005,6 @@ int expand_set_winhighlight(optexpand_T *args, int *numMatches, char ***matches) return expand_set_opt_generic(args, get_highlight_name, numMatches, matches); } -/// Check an option that can be a range of string values. -/// -/// @param list when true: accept a list of values -/// -/// @return OK for correct value, FAIL otherwise. Empty is always OK. -static int check_opt_strings(char *val, char **values, int list) -{ - return opt_strings_flags(val, values, NULL, list); -} - /// Handle an option that can be a range of string values. /// Set a flag in "*flagp" for each string present. /// @@ -2621,11 +2013,14 @@ static int check_opt_strings(char *val, char **values, int list) /// @param list when true: accept a list of values /// /// @return OK for correct value, FAIL otherwise. Empty is always OK. -static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bool list) +static int opt_strings_flags(const char *val, const char **values, unsigned *flagp, bool list) { unsigned new_flags = 0; - while (*val) { + // If not list and val is empty, then force one iteration of the while loop + bool iter_one = (*val == NUL) && !list; + + while (*val || iter_one) { for (unsigned i = 0;; i++) { if (values[i] == NULL) { // val not found in values[] return FAIL; @@ -2640,6 +2035,9 @@ static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bo break; // check next item in val list } } + if (iter_one) { + break; + } } if (flagp != NULL) { *flagp = new_flags; @@ -2651,7 +2049,7 @@ static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bo /// @return OK if "p" is a valid fileformat name, FAIL otherwise. int check_ff_value(char *p) { - return check_opt_strings(p, p_ff_values, false); + return opt_strings_flags(p, opt_ff_values, NULL, false); } static const char e_conflicts_with_value_of_listchars[] @@ -2689,49 +2087,54 @@ static schar_T get_encoded_char_adv(const char **p) } struct chars_tab { - schar_T *cp; ///< char value - const char *name; ///< char id - const char *def; ///< default value - const char *fallback; ///< default value when "def" isn't single-width + schar_T *cp; ///< char value + String name; ///< char id + const char *def; ///< default value + const char *fallback; ///< default value when "def" isn't single-width }; +#define CHARSTAB_ENTRY(cp, name, def, fallback) \ + { (cp), { name, STRLEN_LITERAL(name) }, def, fallback } + static fcs_chars_T fcs_chars; static const struct chars_tab fcs_tab[] = { - { &fcs_chars.stl, "stl", " ", NULL }, - { &fcs_chars.stlnc, "stlnc", " ", NULL }, - { &fcs_chars.wbr, "wbr", " ", NULL }, - { &fcs_chars.horiz, "horiz", "─", "-" }, - { &fcs_chars.horizup, "horizup", "┴", "-" }, - { &fcs_chars.horizdown, "horizdown", "┬", "-" }, - { &fcs_chars.vert, "vert", "│", "|" }, - { &fcs_chars.vertleft, "vertleft", "┤", "|" }, - { &fcs_chars.vertright, "vertright", "├", "|" }, - { &fcs_chars.verthoriz, "verthoriz", "┼", "+" }, - { &fcs_chars.fold, "fold", "·", "-" }, - { &fcs_chars.foldopen, "foldopen", "-", NULL }, - { &fcs_chars.foldclosed, "foldclose", "+", NULL }, - { &fcs_chars.foldsep, "foldsep", "│", "|" }, - { &fcs_chars.diff, "diff", "-", NULL }, - { &fcs_chars.msgsep, "msgsep", " ", NULL }, - { &fcs_chars.eob, "eob", "~", NULL }, - { &fcs_chars.lastline, "lastline", "@", NULL }, + CHARSTAB_ENTRY(&fcs_chars.stl, "stl", " ", NULL), + CHARSTAB_ENTRY(&fcs_chars.stlnc, "stlnc", " ", NULL), + CHARSTAB_ENTRY(&fcs_chars.wbr, "wbr", " ", NULL), + CHARSTAB_ENTRY(&fcs_chars.horiz, "horiz", "─", "-"), + CHARSTAB_ENTRY(&fcs_chars.horizup, "horizup", "┴", "-"), + CHARSTAB_ENTRY(&fcs_chars.horizdown, "horizdown", "┬", "-"), + CHARSTAB_ENTRY(&fcs_chars.vert, "vert", "│", "|"), + CHARSTAB_ENTRY(&fcs_chars.vertleft, "vertleft", "┤", "|"), + CHARSTAB_ENTRY(&fcs_chars.vertright, "vertright", "├", "|"), + CHARSTAB_ENTRY(&fcs_chars.verthoriz, "verthoriz", "┼", "+"), + CHARSTAB_ENTRY(&fcs_chars.fold, "fold", "·", "-"), + CHARSTAB_ENTRY(&fcs_chars.foldopen, "foldopen", "-", NULL), + CHARSTAB_ENTRY(&fcs_chars.foldclosed, "foldclose", "+", NULL), + CHARSTAB_ENTRY(&fcs_chars.foldsep, "foldsep", "│", "|"), + CHARSTAB_ENTRY(&fcs_chars.diff, "diff", "-", NULL), + CHARSTAB_ENTRY(&fcs_chars.msgsep, "msgsep", " ", NULL), + CHARSTAB_ENTRY(&fcs_chars.eob, "eob", "~", NULL), + CHARSTAB_ENTRY(&fcs_chars.lastline, "lastline", "@", NULL), }; static lcs_chars_T lcs_chars; static const struct chars_tab lcs_tab[] = { - { &lcs_chars.eol, "eol", NULL, NULL }, - { &lcs_chars.ext, "extends", NULL, NULL }, - { &lcs_chars.nbsp, "nbsp", NULL, NULL }, - { &lcs_chars.prec, "precedes", NULL, NULL }, - { &lcs_chars.space, "space", NULL, NULL }, - { &lcs_chars.tab2, "tab", NULL, NULL }, - { &lcs_chars.lead, "lead", NULL, NULL }, - { &lcs_chars.trail, "trail", NULL, NULL }, - { &lcs_chars.conceal, "conceal", NULL, NULL }, - { NULL, "multispace", NULL, NULL }, - { NULL, "leadmultispace", NULL, NULL }, + CHARSTAB_ENTRY(&lcs_chars.eol, "eol", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.ext, "extends", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.nbsp, "nbsp", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.prec, "precedes", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.space, "space", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.tab2, "tab", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.lead, "lead", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.trail, "trail", NULL, NULL), + CHARSTAB_ENTRY(&lcs_chars.conceal, "conceal", NULL, NULL), + CHARSTAB_ENTRY(NULL, "multispace", NULL, NULL), + CHARSTAB_ENTRY(NULL, "leadmultispace", NULL, NULL), }; +#undef CHARSTAB_ENTRY + static char *field_value_err(char *errbuf, size_t errbuflen, const char *fmt, const char *field) { if (errbuf == NULL) { @@ -2812,13 +2215,13 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo while (*p) { int i; for (i = 0; i < entries; i++) { - const size_t len = strlen(tab[i].name); - if (!(strncmp(p, tab[i].name, len) == 0 && p[len] == ':')) { + if (!(strncmp(p, tab[i].name.data, + tab[i].name.size) == 0 && p[tab[i].name.size] == ':')) { continue; } - if (what == kListchars && strcmp(tab[i].name, "multispace") == 0) { - const char *s = p + len + 1; + const char *s = p + tab[i].name.size + 1; + if (what == kListchars && strcmp(tab[i].name.data, "multispace") == 0) { if (round == 0) { // Get length of lcs-multispace string in the first round last_multispace = p; @@ -2828,7 +2231,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo if (c1 == 0) { return field_value_err(errbuf, errbuflen, e_wrong_character_width_for_field_str, - tab[i].name); + tab[i].name.data); } multispace_len++; } @@ -2836,7 +2239,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo // lcs-multispace cannot be an empty string return field_value_err(errbuf, errbuflen, e_wrong_number_of_characters_for_field_str, - tab[i].name); + tab[i].name.data); } p = s; } else { @@ -2852,8 +2255,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo break; } - if (what == kListchars && strcmp(tab[i].name, "leadmultispace") == 0) { - const char *s = p + len + 1; + if (what == kListchars && strcmp(tab[i].name.data, "leadmultispace") == 0) { if (round == 0) { // get length of lcs-leadmultispace string in first round last_lmultispace = p; @@ -2863,7 +2265,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo if (c1 == 0) { return field_value_err(errbuf, errbuflen, e_wrong_character_width_for_field_str, - tab[i].name); + tab[i].name.data); } lead_multispace_len++; } @@ -2871,7 +2273,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo // lcs-leadmultispace cannot be an empty string return field_value_err(errbuf, errbuflen, e_wrong_number_of_characters_for_field_str, - tab[i].name); + tab[i].name.data); } p = s; } else { @@ -2887,17 +2289,16 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo break; } - const char *s = p + len + 1; if (*s == NUL) { return field_value_err(errbuf, errbuflen, e_wrong_number_of_characters_for_field_str, - tab[i].name); + tab[i].name.data); } schar_T c1 = get_encoded_char_adv(&s); if (c1 == 0) { return field_value_err(errbuf, errbuflen, e_wrong_character_width_for_field_str, - tab[i].name); + tab[i].name.data); } schar_T c2 = 0; schar_T c3 = 0; @@ -2905,20 +2306,20 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo if (*s == NUL) { return field_value_err(errbuf, errbuflen, e_wrong_number_of_characters_for_field_str, - tab[i].name); + tab[i].name.data); } c2 = get_encoded_char_adv(&s); if (c2 == 0) { return field_value_err(errbuf, errbuflen, e_wrong_character_width_for_field_str, - tab[i].name); + tab[i].name.data); } if (!(*s == ',' || *s == NUL)) { c3 = get_encoded_char_adv(&s); if (c3 == 0) { return field_value_err(errbuf, errbuflen, e_wrong_character_width_for_field_str, - tab[i].name); + tab[i].name.data); } } } @@ -2938,7 +2339,7 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo } else { return field_value_err(errbuf, errbuflen, e_wrong_number_of_characters_for_field_str, - tab[i].name); + tab[i].name.data); } } @@ -2969,22 +2370,22 @@ const char *set_chars_option(win_T *wp, const char *value, CharsOption what, boo /// 'fillchars' option. char *get_fillchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) { - if (idx >= (int)ARRAY_SIZE(fcs_tab)) { + if (idx < 0 || idx >= (int)ARRAY_SIZE(fcs_tab)) { return NULL; } - return (char *)fcs_tab[idx].name; + return fcs_tab[idx].name.data; } /// Function given to ExpandGeneric() to obtain possible arguments of the /// 'listchars' option. char *get_listchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx) { - if (idx >= (int)ARRAY_SIZE(lcs_tab)) { + if (idx < 0 || idx >= (int)ARRAY_SIZE(lcs_tab)) { return NULL; } - return (char *)lcs_tab[idx].name; + return lcs_tab[idx].name.data; } /// Check all global and local values of 'listchars' and 'fillchars'. |