aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2023-01-25 13:46:23 +0000
committerGitHub <noreply@github.com>2023-01-25 13:46:23 +0000
commite2a9d71521a1acdc5a554e3d9f54dfe543914db5 (patch)
tree07b5ac97f4770df35d8cf412b0a9c24f8c3a576d
parentb8288df99be8df701308167e4b0b497f003f25e9 (diff)
parent7bee622fdc72d7461ed43ea170cca20056891d2c (diff)
downloadrneovim-e2a9d71521a1acdc5a554e3d9f54dfe543914db5.tar.gz
rneovim-e2a9d71521a1acdc5a554e3d9f54dfe543914db5.tar.bz2
rneovim-e2a9d71521a1acdc5a554e3d9f54dfe543914db5.zip
Merge pull request #21885 from lewis6991/refactor/options
Problems: - Scope of local variables in options code is too large. - did_set_string_option() is too large (>1000LOC). - Setting options for a particular window or buffer requires a changing context (assigning curwin/curbuf). Solutions: - Reduce the scope of local variables. - Break up did_set_string_option so it doesn't contain specific logic about each individual option (1038 LOC -> 310 LOC). - Begin work on making functions not depend on curbuf or curwin and pass window or buffer handles explicitly.
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/insexpand.c27
-rw-r--r--src/nvim/ops.c7
-rw-r--r--src/nvim/option.c655
-rw-r--r--src/nvim/optionstr.c2006
-rw-r--r--src/nvim/quickfix.c7
-rw-r--r--src/nvim/tag.c8
8 files changed, 1474 insertions, 1242 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 32c035b028..095d73f53f 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3474,7 +3474,7 @@ static void ins_ctrl_hat(void)
State |= MODE_LANGMAP;
}
}
- set_iminsert_global();
+ set_iminsert_global(curbuf);
showmode();
// Show/unshow value of 'keymap' in status lines.
status_redraw_curbuf();
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index c62142310d..76c3680742 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1557,9 +1557,9 @@ static void command_line_toggle_langmap(CommandLineState *s)
if (s->b_im_ptr != NULL) {
if (s->b_im_ptr == &curbuf->b_p_iminsert) {
- set_iminsert_global();
+ set_iminsert_global(curbuf);
} else {
- set_imsearch_global();
+ set_imsearch_global(curbuf);
}
}
ui_cursor_shape(); // may show different cursor shape
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 7f81731b26..6de3b0a9d0 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -2258,14 +2258,14 @@ static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
/// Invoked when the 'completefunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_completefunc_option(void)
+void set_completefunc_option(char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
- if (retval == OK) {
- set_buflocal_cfu_callback(curbuf);
+ if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
- return retval;
+ set_buflocal_cfu_callback(curbuf);
}
/// Copy the global 'completefunc' callback function to the buffer-local
@@ -2279,14 +2279,13 @@ void set_buflocal_cfu_callback(buf_T *buf)
/// Invoked when the 'omnifunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_omnifunc_option(void)
+void set_omnifunc_option(buf_T *buf, char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
- if (retval == OK) {
- set_buflocal_ofu_callback(curbuf);
+ if (option_set_callback_func(buf->b_p_ofu, &ofu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
-
- return retval;
+ set_buflocal_ofu_callback(buf);
}
/// Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
@@ -2300,7 +2299,7 @@ void set_buflocal_ofu_callback(buf_T *buf)
/// Invoked when the 'thesaurusfunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_thesaurusfunc_option(void)
+void set_thesaurusfunc_option(char **errmsg)
{
int retval;
@@ -2312,7 +2311,9 @@ int set_thesaurusfunc_option(void)
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
}
- return retval;
+ if (retval == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index ac4116095f..435ca106ab 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5626,10 +5626,11 @@ static void op_colon(oparg_T *oap)
static Callback opfunc_cb;
/// Process the 'operatorfunc' option value.
-/// @return OK or FAIL
-int set_operatorfunc_option(void)
+void set_operatorfunc_option(char **errmsg)
{
- return option_set_callback_func(p_opfunc, &opfunc_cb);
+ if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
#if defined(EXITFREE)
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 268a1514c8..01a5c7677f 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -175,8 +175,6 @@ void set_init_tablocal(void)
/// editor state initialized here. Do logging in set_init_2 or later.
void set_init_1(bool clean_arg)
{
- int opt_idx;
-
langmap_init();
// Find default value for 'shell' option.
@@ -204,7 +202,7 @@ void set_init_1(bool clean_arg)
static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" };
#endif
garray_T ga;
- opt_idx = findoption("backupskip");
+ int opt_idx = findoption("backupskip");
ga_init(&ga, 1, 100);
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
@@ -253,19 +251,14 @@ void set_init_1(bool clean_arg)
}
{
- char *cdpath;
- char *buf;
- int i;
- int j;
-
// Initialize the 'cdpath' option's default value.
- cdpath = vim_getenv("CDPATH");
+ char *cdpath = vim_getenv("CDPATH");
if (cdpath != NULL) {
- buf = xmalloc(2 * strlen(cdpath) + 2);
+ char *buf = xmalloc(2 * strlen(cdpath) + 2);
{
buf[0] = ','; // start with ",", current dir first
- j = 1;
- for (i = 0; cdpath[i] != NUL; i++) {
+ int j = 1;
+ for (int i = 0; cdpath[i] != NUL; i++) {
if (vim_ispathlistsep(cdpath[i])) {
buf[j++] = ',';
} else {
@@ -276,7 +269,7 @@ void set_init_1(bool clean_arg)
}
}
buf[j] = NUL;
- opt_idx = findoption("cdpath");
+ int opt_idx = findoption("cdpath");
if (opt_idx >= 0) {
options[opt_idx].def_val = buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
@@ -341,25 +334,25 @@ void set_init_1(bool clean_arg)
// them.
// Don't set the P_ALLOCED flag, because we don't want to free the
// default.
- for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
- if (options[opt_idx].flags & P_NO_DEF_EXP) {
+ for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_NO_DEF_EXP) {
continue;
}
char *p;
- if ((options[opt_idx].flags & P_GETTEXT)
- && options[opt_idx].var != NULL) {
- p = _(*(char **)options[opt_idx].var);
+ if ((opt->flags & P_GETTEXT) && opt->var != NULL) {
+ p = _(*(char **)opt->var);
} else {
p = option_expand(opt_idx, NULL);
}
if (p != NULL) {
p = xstrdup(p);
- *(char **)options[opt_idx].var = p;
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ *(char **)opt->var = p;
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = p;
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = p;
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -402,32 +395,32 @@ void set_init_1(bool clean_arg)
/// This does not take care of side effects!
///
/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
-static void set_option_default(int opt_idx, int opt_flags)
+static void set_option_default(const int opt_idx, int opt_flags)
{
- char_u *varp; // pointer to variable for current option
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- varp = (char_u *)get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
- uint32_t flags = options[opt_idx].flags;
+ // pointer to variable for current option
+ vimoption_T *opt = &options[opt_idx];
+ char_u *varp = (char_u *)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
+ uint32_t flags = opt->flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
// Use set_string_option_direct() for local options to handle
// freeing and allocating the value.
- if (options[opt_idx].indir != PV_NONE) {
- set_string_option_direct(NULL, opt_idx,
- options[opt_idx].def_val, opt_flags, 0);
+ if (opt->indir != PV_NONE) {
+ set_string_option_direct(NULL, opt_idx, opt->def_val, opt_flags, 0);
} else {
if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) {
free_string_option(*(char **)(varp));
}
- *(char **)varp = options[opt_idx].def_val;
- options[opt_idx].flags &= ~P_ALLOCED;
+ *(char **)varp = opt->def_val;
+ opt->flags &= ~P_ALLOCED;
}
} else if (flags & P_NUM) {
- if (options[opt_idx].indir == PV_SCROLL) {
+ if (opt->indir == PV_SCROLL) {
win_comp_scroll(curwin);
} else {
- long def_val = (long)options[opt_idx].def_val;
+ long def_val = (long)opt->def_val;
if ((long *)varp == &curwin->w_p_so
|| (long *)varp == &curwin->w_p_siso) {
// 'scrolloff' and 'sidescrolloff' local values have a
@@ -438,21 +431,21 @@ static void set_option_default(int opt_idx, int opt_flags)
}
// May also set global value for local option.
if (both) {
- *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(long *)get_varp_scope(opt, OPT_GLOBAL) =
def_val;
}
}
} else { // P_BOOL
- *(int *)varp = (int)(intptr_t)options[opt_idx].def_val;
+ *(int *)varp = (int)(intptr_t)opt->def_val;
#ifdef UNIX
// 'modeline' defaults to off for root
- if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID) {
+ if (opt->indir == PV_ML && getuid() == ROOT_UID) {
*(int *)varp = false;
}
#endif
// May also set global value for local option.
if (both) {
- *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(int *)get_varp_scope(opt, OPT_GLOBAL) =
*(int *)varp;
}
}
@@ -495,12 +488,13 @@ static void set_string_default(const char *name, char *val, bool allocated)
{
int opt_idx = findoption(name);
if (opt_idx >= 0) {
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = allocated ? val : xstrdup(val);
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = allocated ? val : xstrdup(val);
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -509,12 +503,12 @@ static void set_string_default(const char *name, char *val, bool allocated)
static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
FUNC_ATTR_NONNULL_ARG(2)
{
- int bs = 0;
-
if (origval == NULL) {
return NULL;
}
+ int bs = 0;
+
const size_t newlen = strlen(newval);
for (char *s = origval; *s != NUL; s++) {
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
@@ -574,11 +568,9 @@ void set_init_2(bool headless)
// set in set_init_1 but logging is not allowed there
ILOG("startup runtimepath/packpath value: %s", p_rtp);
- int idx;
-
// 'scroll' defaults to half the window height. The stored default is zero,
// which results in the actual value computed from the window height.
- idx = findoption("scroll");
+ int idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
set_option_default(idx, OPT_LOCAL);
}
@@ -745,14 +737,8 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
char *varp = varp_arg;
char *save_arg = NULL;
char *s = NULL;
- char *oldval = NULL; // previous value if *varp
- char *origval = NULL;
char_u *origval_l = NULL;
char_u *origval_g = NULL;
- char *saved_origval = NULL;
- char *saved_origval_l = NULL;
- char *saved_origval_g = NULL;
- char *saved_newval = NULL;
char whichwrap[80];
// When using ":set opt=val" for a global option
@@ -764,7 +750,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
// The old value is kept until we are sure that the new value is valid.
- oldval = *(char **)varp;
+ char *oldval = *(char **)varp;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
@@ -777,6 +763,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
}
+ char *origval;
// When setting the local value of a global option, the old value may be
// the global value.
if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) {
@@ -1024,13 +1011,13 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
*(char_u **)(varp) = (char_u *)newval;
// origval may be freed by did_set_string_option(), make a copy.
- saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
- saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
- saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
+ char *saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
+ char *saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
+ char *saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
// newval (and varp) may become invalid if the buffer is closed by
// autocommands.
- saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
+ char *saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
{
uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags);
@@ -1707,9 +1694,7 @@ static void didset_options2(void)
/// Check for string options that are NULL (normally only termcap options).
void check_options(void)
{
- int opt_idx;
-
- for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
+ for (int opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL) {
check_string_option((char **)get_varp(&(options[opt_idx])));
}
@@ -2597,7 +2582,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
/// Called after an option changed: check if something needs to be redrawn.
-void check_redraw(uint32_t flags)
+void check_redraw_for(buf_T *buf, win_T *win, uint32_t flags)
{
// Careful: P_RALL is a combination of other P_ flags
bool all = (flags & P_RALL) == P_RALL;
@@ -2611,19 +2596,24 @@ void check_redraw(uint32_t flags)
}
if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
- changed_window_setting();
+ changed_window_setting_win(win);
}
if (flags & P_RBUF) {
- redraw_curbuf_later(UPD_NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
if (flags & P_RWINONLY) {
- redraw_later(curwin, UPD_NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
}
if (all) {
redraw_all_later(UPD_NOT_VALID);
}
}
+void check_redraw(uint32_t flags)
+{
+ check_redraw_for(curbuf, curwin, flags);
+}
+
/// Find index for named option
///
/// @param[in] arg Option to find index for.
@@ -2880,7 +2870,6 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return SOPT_STRING | SOPT_GLOBAL;
}
- char_u *varp = NULL;
int rv = 0;
int opt_idx = findoption(name);
if (opt_idx < 0) {
@@ -2930,6 +2919,8 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return rv;
}
+ char_u *varp = NULL;
+
if (opt_type == SREQ_GLOBAL) {
if (p->var == VAR_WIN) {
return 0;
@@ -3007,58 +2998,62 @@ char *set_option_value(const char *const name, const long number, const char *co
int opt_idx = findoption(name);
if (opt_idx < 0) {
semsg(_("E355: Unknown option: %s"), name);
- } else {
- uint32_t flags = options[opt_idx].flags;
- // Disallow changing some options in the sandbox
- if (sandbox > 0 && (flags & P_SECURE)) {
- emsg(_(e_sandbox));
- return NULL;
+ return NULL;
+ }
+
+ uint32_t flags = options[opt_idx].flags;
+ // Disallow changing some options in the sandbox
+ if (sandbox > 0 && (flags & P_SECURE)) {
+ emsg(_(e_sandbox));
+ return NULL;
+ }
+
+ if (flags & P_STRING) {
+ const char *s = string;
+ if (s == NULL || opt_flags & OPT_CLEAR) {
+ s = "";
}
- if (flags & P_STRING) {
- const char *s = string;
- if (s == NULL || opt_flags & OPT_CLEAR) {
- s = "";
- }
- return set_string_option(opt_idx, s, opt_flags);
- }
-
- char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
- if (varp != NULL) { // hidden option is not changed
- if (number == 0 && string != NULL) {
- int idx;
-
- // Either we are given a string or we are setting option
- // to zero.
- for (idx = 0; string[idx] == '0'; idx++) {}
- if (string[idx] != NUL || idx == 0) {
- // There's another character after zeros or the string
- // is empty. In both cases, we are trying to set a
- // num option using a string.
- semsg(_("E521: Number required: &%s = '%s'"),
- name, string);
- return NULL; // do nothing as we hit an error
- }
- }
- long numval = number;
- if (opt_flags & OPT_CLEAR) {
- if ((int *)varp == &curbuf->b_p_ar) {
- numval = -1;
- } else if ((long *)varp == &curbuf->b_p_ul) {
- numval = NO_LOCAL_UNDOLEVEL;
- } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
- numval = -1;
- } else {
- char *s = NULL;
- (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
- }
- }
- if (flags & P_NUM) {
- return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
- }
- return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
+ return set_string_option(opt_idx, s, opt_flags);
+ }
+
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ if (varp == NULL) {
+ // hidden option is not changed
+ return NULL;
+ }
+
+ if (number == 0 && string != NULL) {
+ int idx;
+
+ // Either we are given a string or we are setting option
+ // to zero.
+ for (idx = 0; string[idx] == '0'; idx++) {}
+ if (string[idx] != NUL || idx == 0) {
+ // There's another character after zeros or the string
+ // is empty. In both cases, we are trying to set a
+ // num option using a string.
+ semsg(_("E521: Number required: &%s = '%s'"),
+ name, string);
+ return NULL; // do nothing as we hit an error
+ }
+ }
+ long numval = number;
+ if (opt_flags & OPT_CLEAR) {
+ if ((int *)varp == &curbuf->b_p_ar) {
+ numval = -1;
+ } else if ((long *)varp == &curbuf->b_p_ul) {
+ numval = NO_LOCAL_UNDOLEVEL;
+ } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
+ numval = -1;
+ } else {
+ char *s = NULL;
+ (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
}
}
- return NULL;
+ if (flags & P_NUM) {
+ return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
+ }
+ return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
}
/// Call set_option_value() and when an error is returned report it.
@@ -3431,12 +3426,13 @@ int makefoldset(FILE *fd)
static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags)
{
- char *buf = NULL;
- char_u *part = NULL;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+
+ char *buf = NULL;
+ char_u *part = NULL;
+
if (*valuep != NULL) {
// Output 'pastetoggle' as key names. For other
// options some characters have to be escaped with
@@ -3503,11 +3499,10 @@ fail:
static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep)
{
- long wc;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+ long wc;
if (wc_use_keyname((char_u *)valuep, &wc)) {
// print 'wildchar' and 'wildcharm' as a key name
if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0) {
@@ -3643,83 +3638,87 @@ void unset_global_local_option(char *name, void *from)
}
}
-/// Get pointer to option variable, depending on local or global scope.
-///
-/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
-char *get_varp_scope(vimoption_T *p, int scope)
+char *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
{
if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
- return GLOBAL_WO(get_varp(p));
+ return GLOBAL_WO(get_varp_from(p, buf, win));
}
return (char *)p->var;
}
if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
- return (char *)&(curbuf->b_p_fp);
+ return (char *)&(buf->b_p_fp);
case PV_EFM:
- return (char *)&(curbuf->b_p_efm);
+ return (char *)&(buf->b_p_efm);
case PV_GP:
- return (char *)&(curbuf->b_p_gp);
+ return (char *)&(buf->b_p_gp);
case PV_MP:
- return (char *)&(curbuf->b_p_mp);
+ return (char *)&(buf->b_p_mp);
case PV_EP:
- return (char *)&(curbuf->b_p_ep);
+ return (char *)&(buf->b_p_ep);
case PV_KP:
- return (char *)&(curbuf->b_p_kp);
+ return (char *)&(buf->b_p_kp);
case PV_PATH:
- return (char *)&(curbuf->b_p_path);
+ return (char *)&(buf->b_p_path);
case PV_AR:
- return (char *)&(curbuf->b_p_ar);
+ return (char *)&(buf->b_p_ar);
case PV_TAGS:
- return (char *)&(curbuf->b_p_tags);
+ return (char *)&(buf->b_p_tags);
case PV_TC:
- return (char *)&(curbuf->b_p_tc);
+ return (char *)&(buf->b_p_tc);
case PV_SISO:
- return (char *)&(curwin->w_p_siso);
+ return (char *)&(win->w_p_siso);
case PV_SO:
- return (char *)&(curwin->w_p_so);
+ return (char *)&(win->w_p_so);
case PV_DEF:
- return (char *)&(curbuf->b_p_def);
+ return (char *)&(buf->b_p_def);
case PV_INC:
- return (char *)&(curbuf->b_p_inc);
+ return (char *)&(buf->b_p_inc);
case PV_DICT:
- return (char *)&(curbuf->b_p_dict);
+ return (char *)&(buf->b_p_dict);
case PV_TSR:
- return (char *)&(curbuf->b_p_tsr);
+ return (char *)&(buf->b_p_tsr);
case PV_TSRFU:
- return (char *)&(curbuf->b_p_tsrfu);
+ return (char *)&(buf->b_p_tsrfu);
case PV_TFU:
- return (char *)&(curbuf->b_p_tfu);
+ return (char *)&(buf->b_p_tfu);
case PV_SBR:
- return (char *)&(curwin->w_p_sbr);
+ return (char *)&(win->w_p_sbr);
case PV_STL:
- return (char *)&(curwin->w_p_stl);
+ return (char *)&(win->w_p_stl);
case PV_WBR:
- return (char *)&(curwin->w_p_wbr);
+ return (char *)&(win->w_p_wbr);
case PV_UL:
- return (char *)&(curbuf->b_p_ul);
+ return (char *)&(buf->b_p_ul);
case PV_LW:
- return (char *)&(curbuf->b_p_lw);
+ return (char *)&(buf->b_p_lw);
case PV_BKC:
- return (char *)&(curbuf->b_p_bkc);
+ return (char *)&(buf->b_p_bkc);
case PV_MENC:
- return (char *)&(curbuf->b_p_menc);
+ return (char *)&(buf->b_p_menc);
case PV_FCS:
- return (char *)&(curwin->w_p_fcs);
+ return (char *)&(win->w_p_fcs);
case PV_LCS:
- return (char *)&(curwin->w_p_lcs);
+ return (char *)&(win->w_p_lcs);
case PV_VE:
- return (char *)&(curwin->w_p_ve);
+ return (char *)&(win->w_p_ve);
}
return NULL; // "cannot happen"
}
- return (char *)get_varp(p);
+ return (char *)get_varp_from(p, buf, win);
}
-/// Get pointer to option variable.
-static char_u *get_varp(vimoption_T *p)
+/// Get pointer to option variable, depending on local or global scope.
+///
+/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
+char *get_varp_scope(vimoption_T *p, int scope)
+{
+ return get_varp_scope_from(p, scope, curbuf, curwin);
+}
+
+static char_u *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
{
// hidden option, always return NULL
if (p->var == NULL) {
@@ -3732,305 +3731,311 @@ static char_u *get_varp(vimoption_T *p)
// global option with local value: use local value if it's been set
case PV_EP:
- return *curbuf->b_p_ep != NUL
- ? (char_u *)&curbuf->b_p_ep : p->var;
+ return *buf->b_p_ep != NUL
+ ? (char_u *)&buf->b_p_ep : p->var;
case PV_KP:
- return *curbuf->b_p_kp != NUL
- ? (char_u *)&curbuf->b_p_kp : p->var;
+ return *buf->b_p_kp != NUL
+ ? (char_u *)&buf->b_p_kp : p->var;
case PV_PATH:
- return *curbuf->b_p_path != NUL
- ? (char_u *)&(curbuf->b_p_path) : p->var;
+ return *buf->b_p_path != NUL
+ ? (char_u *)&(buf->b_p_path) : p->var;
case PV_AR:
- return curbuf->b_p_ar >= 0
- ? (char_u *)&(curbuf->b_p_ar) : p->var;
+ return buf->b_p_ar >= 0
+ ? (char_u *)&(buf->b_p_ar) : p->var;
case PV_TAGS:
- return *curbuf->b_p_tags != NUL
- ? (char_u *)&(curbuf->b_p_tags) : p->var;
+ return *buf->b_p_tags != NUL
+ ? (char_u *)&(buf->b_p_tags) : p->var;
case PV_TC:
- return *curbuf->b_p_tc != NUL
- ? (char_u *)&(curbuf->b_p_tc) : p->var;
+ return *buf->b_p_tc != NUL
+ ? (char_u *)&(buf->b_p_tc) : p->var;
case PV_SISO:
- return curwin->w_p_siso >= 0
- ? (char_u *)&(curwin->w_p_siso) : p->var;
+ return win->w_p_siso >= 0
+ ? (char_u *)&(win->w_p_siso) : p->var;
case PV_SO:
- return curwin->w_p_so >= 0
- ? (char_u *)&(curwin->w_p_so) : p->var;
+ return win->w_p_so >= 0
+ ? (char_u *)&(win->w_p_so) : p->var;
case PV_BKC:
- return *curbuf->b_p_bkc != NUL
- ? (char_u *)&(curbuf->b_p_bkc) : p->var;
+ return *buf->b_p_bkc != NUL
+ ? (char_u *)&(buf->b_p_bkc) : p->var;
case PV_DEF:
- return *curbuf->b_p_def != NUL
- ? (char_u *)&(curbuf->b_p_def) : p->var;
+ return *buf->b_p_def != NUL
+ ? (char_u *)&(buf->b_p_def) : p->var;
case PV_INC:
- return *curbuf->b_p_inc != NUL
- ? (char_u *)&(curbuf->b_p_inc) : p->var;
+ return *buf->b_p_inc != NUL
+ ? (char_u *)&(buf->b_p_inc) : p->var;
case PV_DICT:
- return *curbuf->b_p_dict != NUL
- ? (char_u *)&(curbuf->b_p_dict) : p->var;
+ return *buf->b_p_dict != NUL
+ ? (char_u *)&(buf->b_p_dict) : p->var;
case PV_TSR:
- return *curbuf->b_p_tsr != NUL
- ? (char_u *)&(curbuf->b_p_tsr) : p->var;
+ return *buf->b_p_tsr != NUL
+ ? (char_u *)&(buf->b_p_tsr) : p->var;
case PV_TSRFU:
- return *curbuf->b_p_tsrfu != NUL
- ? (char_u *)&(curbuf->b_p_tsrfu) : p->var;
+ return *buf->b_p_tsrfu != NUL
+ ? (char_u *)&(buf->b_p_tsrfu) : p->var;
case PV_FP:
- return *curbuf->b_p_fp != NUL
- ? (char_u *)&(curbuf->b_p_fp) : p->var;
+ return *buf->b_p_fp != NUL
+ ? (char_u *)&(buf->b_p_fp) : p->var;
case PV_EFM:
- return *curbuf->b_p_efm != NUL
- ? (char_u *)&(curbuf->b_p_efm) : p->var;
+ return *buf->b_p_efm != NUL
+ ? (char_u *)&(buf->b_p_efm) : p->var;
case PV_GP:
- return *curbuf->b_p_gp != NUL
- ? (char_u *)&(curbuf->b_p_gp) : p->var;
+ return *buf->b_p_gp != NUL
+ ? (char_u *)&(buf->b_p_gp) : p->var;
case PV_MP:
- return *curbuf->b_p_mp != NUL
- ? (char_u *)&(curbuf->b_p_mp) : p->var;
+ return *buf->b_p_mp != NUL
+ ? (char_u *)&(buf->b_p_mp) : p->var;
case PV_SBR:
- return *curwin->w_p_sbr != NUL
- ? (char_u *)&(curwin->w_p_sbr) : p->var;
+ return *win->w_p_sbr != NUL
+ ? (char_u *)&(win->w_p_sbr) : p->var;
case PV_STL:
- return *curwin->w_p_stl != NUL
- ? (char_u *)&(curwin->w_p_stl) : p->var;
+ return *win->w_p_stl != NUL
+ ? (char_u *)&(win->w_p_stl) : p->var;
case PV_WBR:
- return *curwin->w_p_wbr != NUL
- ? (char_u *)&(curwin->w_p_wbr) : p->var;
+ return *win->w_p_wbr != NUL
+ ? (char_u *)&(win->w_p_wbr) : p->var;
case PV_UL:
- return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
- ? (char_u *)&(curbuf->b_p_ul) : p->var;
+ return buf->b_p_ul != NO_LOCAL_UNDOLEVEL
+ ? (char_u *)&(buf->b_p_ul) : p->var;
case PV_LW:
- return *curbuf->b_p_lw != NUL
- ? (char_u *)&(curbuf->b_p_lw) : p->var;
+ return *buf->b_p_lw != NUL
+ ? (char_u *)&(buf->b_p_lw) : p->var;
case PV_MENC:
- return *curbuf->b_p_menc != NUL
- ? (char_u *)&(curbuf->b_p_menc) : p->var;
+ return *buf->b_p_menc != NUL
+ ? (char_u *)&(buf->b_p_menc) : p->var;
case PV_FCS:
- return *curwin->w_p_fcs != NUL
- ? (char_u *)&(curwin->w_p_fcs) : p->var;
+ return *win->w_p_fcs != NUL
+ ? (char_u *)&(win->w_p_fcs) : p->var;
case PV_LCS:
- return *curwin->w_p_lcs != NUL
- ? (char_u *)&(curwin->w_p_lcs) : p->var;
+ return *win->w_p_lcs != NUL
+ ? (char_u *)&(win->w_p_lcs) : p->var;
case PV_VE:
- return *curwin->w_p_ve != NUL
- ? (char_u *)&curwin->w_p_ve : p->var;
+ return *win->w_p_ve != NUL
+ ? (char_u *)&win->w_p_ve : p->var;
case PV_ARAB:
- return (char_u *)&(curwin->w_p_arab);
+ return (char_u *)&(win->w_p_arab);
case PV_LIST:
- return (char_u *)&(curwin->w_p_list);
+ return (char_u *)&(win->w_p_list);
case PV_SPELL:
- return (char_u *)&(curwin->w_p_spell);
+ return (char_u *)&(win->w_p_spell);
case PV_CUC:
- return (char_u *)&(curwin->w_p_cuc);
+ return (char_u *)&(win->w_p_cuc);
case PV_CUL:
- return (char_u *)&(curwin->w_p_cul);
+ return (char_u *)&(win->w_p_cul);
case PV_CULOPT:
- return (char_u *)&(curwin->w_p_culopt);
+ return (char_u *)&(win->w_p_culopt);
case PV_CC:
- return (char_u *)&(curwin->w_p_cc);
+ return (char_u *)&(win->w_p_cc);
case PV_DIFF:
- return (char_u *)&(curwin->w_p_diff);
+ return (char_u *)&(win->w_p_diff);
case PV_FDC:
- return (char_u *)&(curwin->w_p_fdc);
+ return (char_u *)&(win->w_p_fdc);
case PV_FEN:
- return (char_u *)&(curwin->w_p_fen);
+ return (char_u *)&(win->w_p_fen);
case PV_FDI:
- return (char_u *)&(curwin->w_p_fdi);
+ return (char_u *)&(win->w_p_fdi);
case PV_FDL:
- return (char_u *)&(curwin->w_p_fdl);
+ return (char_u *)&(win->w_p_fdl);
case PV_FDM:
- return (char_u *)&(curwin->w_p_fdm);
+ return (char_u *)&(win->w_p_fdm);
case PV_FML:
- return (char_u *)&(curwin->w_p_fml);
+ return (char_u *)&(win->w_p_fml);
case PV_FDN:
- return (char_u *)&(curwin->w_p_fdn);
+ return (char_u *)&(win->w_p_fdn);
case PV_FDE:
- return (char_u *)&(curwin->w_p_fde);
+ return (char_u *)&(win->w_p_fde);
case PV_FDT:
- return (char_u *)&(curwin->w_p_fdt);
+ return (char_u *)&(win->w_p_fdt);
case PV_FMR:
- return (char_u *)&(curwin->w_p_fmr);
+ return (char_u *)&(win->w_p_fmr);
case PV_NU:
- return (char_u *)&(curwin->w_p_nu);
+ return (char_u *)&(win->w_p_nu);
case PV_RNU:
- return (char_u *)&(curwin->w_p_rnu);
+ return (char_u *)&(win->w_p_rnu);
case PV_NUW:
- return (char_u *)&(curwin->w_p_nuw);
+ return (char_u *)&(win->w_p_nuw);
case PV_WFH:
- return (char_u *)&(curwin->w_p_wfh);
+ return (char_u *)&(win->w_p_wfh);
case PV_WFW:
- return (char_u *)&(curwin->w_p_wfw);
+ return (char_u *)&(win->w_p_wfw);
case PV_PVW:
- return (char_u *)&(curwin->w_p_pvw);
+ return (char_u *)&(win->w_p_pvw);
case PV_RL:
- return (char_u *)&(curwin->w_p_rl);
+ return (char_u *)&(win->w_p_rl);
case PV_RLC:
- return (char_u *)&(curwin->w_p_rlc);
+ return (char_u *)&(win->w_p_rlc);
case PV_SCROLL:
- return (char_u *)&(curwin->w_p_scr);
+ return (char_u *)&(win->w_p_scr);
case PV_WRAP:
- return (char_u *)&(curwin->w_p_wrap);
+ return (char_u *)&(win->w_p_wrap);
case PV_LBR:
- return (char_u *)&(curwin->w_p_lbr);
+ return (char_u *)&(win->w_p_lbr);
case PV_BRI:
- return (char_u *)&(curwin->w_p_bri);
+ return (char_u *)&(win->w_p_bri);
case PV_BRIOPT:
- return (char_u *)&(curwin->w_p_briopt);
+ return (char_u *)&(win->w_p_briopt);
case PV_SCBIND:
- return (char_u *)&(curwin->w_p_scb);
+ return (char_u *)&(win->w_p_scb);
case PV_CRBIND:
- return (char_u *)&(curwin->w_p_crb);
+ return (char_u *)&(win->w_p_crb);
case PV_COCU:
- return (char_u *)&(curwin->w_p_cocu);
+ return (char_u *)&(win->w_p_cocu);
case PV_COLE:
- return (char_u *)&(curwin->w_p_cole);
+ return (char_u *)&(win->w_p_cole);
case PV_AI:
- return (char_u *)&(curbuf->b_p_ai);
+ return (char_u *)&(buf->b_p_ai);
case PV_BIN:
- return (char_u *)&(curbuf->b_p_bin);
+ return (char_u *)&(buf->b_p_bin);
case PV_BOMB:
- return (char_u *)&(curbuf->b_p_bomb);
+ return (char_u *)&(buf->b_p_bomb);
case PV_BH:
- return (char_u *)&(curbuf->b_p_bh);
+ return (char_u *)&(buf->b_p_bh);
case PV_BT:
- return (char_u *)&(curbuf->b_p_bt);
+ return (char_u *)&(buf->b_p_bt);
case PV_BL:
- return (char_u *)&(curbuf->b_p_bl);
+ return (char_u *)&(buf->b_p_bl);
case PV_CHANNEL:
- return (char_u *)&(curbuf->b_p_channel);
+ return (char_u *)&(buf->b_p_channel);
case PV_CI:
- return (char_u *)&(curbuf->b_p_ci);
+ return (char_u *)&(buf->b_p_ci);
case PV_CIN:
- return (char_u *)&(curbuf->b_p_cin);
+ return (char_u *)&(buf->b_p_cin);
case PV_CINK:
- return (char_u *)&(curbuf->b_p_cink);
+ return (char_u *)&(buf->b_p_cink);
case PV_CINO:
- return (char_u *)&(curbuf->b_p_cino);
+ return (char_u *)&(buf->b_p_cino);
case PV_CINSD:
- return (char_u *)&(curbuf->b_p_cinsd);
+ return (char_u *)&(buf->b_p_cinsd);
case PV_CINW:
- return (char_u *)&(curbuf->b_p_cinw);
+ return (char_u *)&(buf->b_p_cinw);
case PV_COM:
- return (char_u *)&(curbuf->b_p_com);
+ return (char_u *)&(buf->b_p_com);
case PV_CMS:
- return (char_u *)&(curbuf->b_p_cms);
+ return (char_u *)&(buf->b_p_cms);
case PV_CPT:
- return (char_u *)&(curbuf->b_p_cpt);
+ return (char_u *)&(buf->b_p_cpt);
#ifdef BACKSLASH_IN_FILENAME
case PV_CSL:
- return (char_u *)&(curbuf->b_p_csl);
+ return (char_u *)&(buf->b_p_csl);
#endif
case PV_CFU:
- return (char_u *)&(curbuf->b_p_cfu);
+ return (char_u *)&(buf->b_p_cfu);
case PV_OFU:
- return (char_u *)&(curbuf->b_p_ofu);
+ return (char_u *)&(buf->b_p_ofu);
case PV_EOF:
- return (char_u *)&(curbuf->b_p_eof);
+ return (char_u *)&(buf->b_p_eof);
case PV_EOL:
- return (char_u *)&(curbuf->b_p_eol);
+ return (char_u *)&(buf->b_p_eol);
case PV_FIXEOL:
- return (char_u *)&(curbuf->b_p_fixeol);
+ return (char_u *)&(buf->b_p_fixeol);
case PV_ET:
- return (char_u *)&(curbuf->b_p_et);
+ return (char_u *)&(buf->b_p_et);
case PV_FENC:
- return (char_u *)&(curbuf->b_p_fenc);
+ return (char_u *)&(buf->b_p_fenc);
case PV_FF:
- return (char_u *)&(curbuf->b_p_ff);
+ return (char_u *)&(buf->b_p_ff);
case PV_FT:
- return (char_u *)&(curbuf->b_p_ft);
+ return (char_u *)&(buf->b_p_ft);
case PV_FO:
- return (char_u *)&(curbuf->b_p_fo);
+ return (char_u *)&(buf->b_p_fo);
case PV_FLP:
- return (char_u *)&(curbuf->b_p_flp);
+ return (char_u *)&(buf->b_p_flp);
case PV_IMI:
- return (char_u *)&(curbuf->b_p_iminsert);
+ return (char_u *)&(buf->b_p_iminsert);
case PV_IMS:
- return (char_u *)&(curbuf->b_p_imsearch);
+ return (char_u *)&(buf->b_p_imsearch);
case PV_INF:
- return (char_u *)&(curbuf->b_p_inf);
+ return (char_u *)&(buf->b_p_inf);
case PV_ISK:
- return (char_u *)&(curbuf->b_p_isk);
+ return (char_u *)&(buf->b_p_isk);
case PV_INEX:
- return (char_u *)&(curbuf->b_p_inex);
+ return (char_u *)&(buf->b_p_inex);
case PV_INDE:
- return (char_u *)&(curbuf->b_p_inde);
+ return (char_u *)&(buf->b_p_inde);
case PV_INDK:
- return (char_u *)&(curbuf->b_p_indk);
+ return (char_u *)&(buf->b_p_indk);
case PV_FEX:
- return (char_u *)&(curbuf->b_p_fex);
+ return (char_u *)&(buf->b_p_fex);
case PV_LISP:
- return (char_u *)&(curbuf->b_p_lisp);
+ return (char_u *)&(buf->b_p_lisp);
case PV_LOP:
- return (char_u *)&(curbuf->b_p_lop);
+ return (char_u *)&(buf->b_p_lop);
case PV_ML:
- return (char_u *)&(curbuf->b_p_ml);
+ return (char_u *)&(buf->b_p_ml);
case PV_MPS:
- return (char_u *)&(curbuf->b_p_mps);
+ return (char_u *)&(buf->b_p_mps);
case PV_MA:
- return (char_u *)&(curbuf->b_p_ma);
+ return (char_u *)&(buf->b_p_ma);
case PV_MOD:
- return (char_u *)&(curbuf->b_changed);
+ return (char_u *)&(buf->b_changed);
case PV_NF:
- return (char_u *)&(curbuf->b_p_nf);
+ return (char_u *)&(buf->b_p_nf);
case PV_PI:
- return (char_u *)&(curbuf->b_p_pi);
+ return (char_u *)&(buf->b_p_pi);
case PV_QE:
- return (char_u *)&(curbuf->b_p_qe);
+ return (char_u *)&(buf->b_p_qe);
case PV_RO:
- return (char_u *)&(curbuf->b_p_ro);
+ return (char_u *)&(buf->b_p_ro);
case PV_SCBK:
- return (char_u *)&(curbuf->b_p_scbk);
+ return (char_u *)&(buf->b_p_scbk);
case PV_SI:
- return (char_u *)&(curbuf->b_p_si);
+ return (char_u *)&(buf->b_p_si);
case PV_STS:
- return (char_u *)&(curbuf->b_p_sts);
+ return (char_u *)&(buf->b_p_sts);
case PV_SUA:
- return (char_u *)&(curbuf->b_p_sua);
+ return (char_u *)&(buf->b_p_sua);
case PV_SWF:
- return (char_u *)&(curbuf->b_p_swf);
+ return (char_u *)&(buf->b_p_swf);
case PV_SMC:
- return (char_u *)&(curbuf->b_p_smc);
+ return (char_u *)&(buf->b_p_smc);
case PV_SYN:
- return (char_u *)&(curbuf->b_p_syn);
+ return (char_u *)&(buf->b_p_syn);
case PV_SPC:
- return (char_u *)&(curwin->w_s->b_p_spc);
+ return (char_u *)&(win->w_s->b_p_spc);
case PV_SPF:
- return (char_u *)&(curwin->w_s->b_p_spf);
+ return (char_u *)&(win->w_s->b_p_spf);
case PV_SPL:
- return (char_u *)&(curwin->w_s->b_p_spl);
+ return (char_u *)&(win->w_s->b_p_spl);
case PV_SPO:
- return (char_u *)&(curwin->w_s->b_p_spo);
+ return (char_u *)&(win->w_s->b_p_spo);
case PV_SW:
- return (char_u *)&(curbuf->b_p_sw);
+ return (char_u *)&(buf->b_p_sw);
case PV_TFU:
- return (char_u *)&(curbuf->b_p_tfu);
+ return (char_u *)&(buf->b_p_tfu);
case PV_TS:
- return (char_u *)&(curbuf->b_p_ts);
+ return (char_u *)&(buf->b_p_ts);
case PV_TW:
- return (char_u *)&(curbuf->b_p_tw);
+ return (char_u *)&(buf->b_p_tw);
case PV_UDF:
- return (char_u *)&(curbuf->b_p_udf);
+ return (char_u *)&(buf->b_p_udf);
case PV_WM:
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
case PV_VSTS:
- return (char_u *)&(curbuf->b_p_vsts);
+ return (char_u *)&(buf->b_p_vsts);
case PV_VTS:
- return (char_u *)&(curbuf->b_p_vts);
+ return (char_u *)&(buf->b_p_vts);
case PV_KMAP:
- return (char_u *)&(curbuf->b_p_keymap);
+ return (char_u *)&(buf->b_p_keymap);
case PV_SCL:
- return (char_u *)&(curwin->w_p_scl);
+ return (char_u *)&(win->w_p_scl);
case PV_WINHL:
- return (char_u *)&(curwin->w_p_winhl);
+ return (char_u *)&(win->w_p_winhl);
case PV_WINBL:
- return (char_u *)&(curwin->w_p_winbl);
+ return (char_u *)&(win->w_p_winbl);
case PV_STC:
- return (char_u *)&(curwin->w_p_stc);
+ return (char_u *)&(win->w_p_stc);
default:
iemsg(_("E356: get_varp ERROR"));
}
// always return a valid pointer to avoid a crash!
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
+}
+
+/// Get pointer to option variable.
+static inline char_u *get_varp(vimoption_T *p)
+{
+ return get_varp_from(p, curbuf, curwin);
}
/// Get the value of 'equalprg', either the buffer-local one or the global one.
@@ -4508,15 +4513,15 @@ void reset_modifiable(void)
}
/// Set the global value for 'iminsert' to the local value.
-void set_iminsert_global(void)
+void set_iminsert_global(buf_T *buf)
{
- p_iminsert = curbuf->b_p_iminsert;
+ p_iminsert = buf->b_p_iminsert;
}
/// Set the global value for 'imsearch' to the local value.
-void set_imsearch_global(void)
+void set_imsearch_global(buf_T *buf)
{
- p_imsearch = curbuf->b_p_imsearch;
+ p_imsearch = buf->b_p_imsearch;
}
static int expand_option_idx = -1;
@@ -4526,11 +4531,6 @@ static int expand_option_flags = 0;
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
{
- uint32_t flags = 0; // init for GCC
- int opt_idx = 0; // init for GCC
- char *p;
- int is_term_option = false;
-
expand_option_flags = opt_flags;
xp->xp_context = EXPAND_SETTINGS;
@@ -4538,7 +4538,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_pattern = arg;
return;
}
- p = arg + strlen(arg) - 1;
+ char *p = arg + strlen(arg) - 1;
if (*p == ' ' && *(p - 1) != '\\') {
xp->xp_pattern = p + 1;
return;
@@ -4570,6 +4570,9 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
arg = p;
char nextchar;
+ uint32_t flags = 0;
+ int opt_idx = 0;
+ int is_term_option = false;
if (*arg == '<') {
while (*p != '>') {
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index efb1ff2ab6..a5a708600f 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -640,6 +640,952 @@ char *check_stl_option(char *s)
static int shada_idx = -1;
+static bool check_illegal_path_names(char *val, uint32_t flags)
+{
+ // Disallow a path separator (slash and/or backslash), wildcards and
+ // characters that are often illegal in a file name. Be more permissive
+ // if "secure" is off.
+ return (((flags & P_NFNAME)
+ && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
+ || ((flags & P_NDNAME)
+ && strpbrk(val, "*?[|;&<>\r\n") != NULL));
+}
+
+static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, char **errmsg)
+{
+ char *bkc = p_bkc;
+ unsigned int *flags = &bkc_flags;
+
+ if (opt_flags & OPT_LOCAL) {
+ bkc = buf->b_p_bkc;
+ flags = &buf->b_bkc_flags;
+ }
+
+ if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
+
+ if (((*flags & BKC_AUTO) != 0)
+ + ((*flags & BKC_YES) != 0)
+ + ((*flags & BKC_NO) != 0) != 1) {
+ // Must have exactly one of "auto", "yes" and "no".
+ (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
+ *errmsg = e_invarg;
+ }
+ }
+}
+
+static void did_set_backupext_or_patchmode(char **errmsg)
+{
+ if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
+ *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
+ *errmsg = e_backupext_and_patchmode_are_equal;
+ }
+}
+
+static void did_set_breakindentopt(win_T *win, char **errmsg)
+{
+ if (briopt_check(win) == FAIL) {
+ *errmsg = e_invarg;
+ }
+ // list setting requires a redraw
+ if (win == curwin && win->w_briopt_list) {
+ redraw_all_later(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg)
+{
+ // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
+ // If the new option is invalid, use old value. 'lisp' option: refill
+ // g_chartab[] for '-' char
+ if (buf_init_chartab(buf, true) == FAIL) {
+ *did_chartab = true; // need to restore it below
+ *errmsg = e_invarg; // error in value
+ }
+}
+
+static void did_set_helpfile(void)
+{
+ // May compute new values for $VIM and $VIMRUNTIME
+ if (didset_vim) {
+ vim_unsetenv_ext("VIM");
+ }
+ if (didset_vimruntime) {
+ vim_unsetenv_ext("VIMRUNTIME");
+ }
+}
+
+static void did_set_cursorlineopt(win_T *win, char **varp, char **errmsg)
+{
+ if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_helplang(char **errmsg)
+{
+ // Check for "", "ab", "ab,cd", etc.
+ for (char *s = p_hlg; *s != NUL; s += 3) {
+ if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
+ *errmsg = e_invarg;
+ break;
+ }
+ if (s[2] == NUL) {
+ break;
+ }
+ }
+}
+
+static void did_set_highlight(char **varp, char **errmsg)
+{
+ if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
+ *errmsg = e_unsupportedoption;
+ }
+}
+
+static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, char **errmsg)
+{
+ if (opt_strings_flags(val, values, flagp, list) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_opt_strings(char *val, char **values, bool list, char **errmsg)
+{
+ did_set_opt_flags(val, values, NULL, list, errmsg);
+}
+
+static void did_set_sessionoptions(char *oldval, char **errmsg)
+{
+ if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
+ if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
+ // Don't allow both "sesdir" and "curdir".
+ (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_ambiwidth(char **errmsg)
+{
+ if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = check_chars_options();
+ }
+}
+
+static void did_set_background(char **errmsg)
+{
+ if (check_opt_strings(p_bg, p_bg_values, false) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ int dark = (*p_bg == 'd');
+
+ init_highlight(false, false);
+
+ if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
+ // The color scheme must have set 'background' back to another
+ // value, that's not what we want here. Disable the color
+ // scheme and set the colors again.
+ do_unlet(S_LEN("g:colors_name"), true);
+ free_string_option(p_bg);
+ p_bg = xstrdup((dark ? "dark" : "light"));
+ check_string_option(&p_bg);
+ init_highlight(false, false);
+ }
+}
+
+static void did_set_wildmode(char **errmsg)
+{
+ if (check_opt_wim() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_winaltkeys(char **errmsg)
+{
+ if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_eventignore(char **errmsg)
+{
+ if (check_ei() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+// 'encoding', 'fileencoding' and 'makeencoding'
+static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, char **errmsg)
+{
+ if (gvarp == &p_fenc) {
+ if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) {
+ *errmsg = e_modifiable;
+ return;
+ }
+
+ if (vim_strchr(*varp, ',') != NULL) {
+ // No comma allowed in 'fileencoding'; catches confusing it
+ // with 'fileencodings'.
+ *errmsg = e_invarg;
+ return;
+ }
+
+ // May show a "+" in the title now.
+ redraw_titles();
+ // Add 'fileencoding' to the swap file.
+ ml_setflags(buf);
+ }
+
+ // canonize the value, so that strcmp() can be used on it
+ char *p = enc_canonize(*varp);
+ xfree(*varp);
+ *varp = p;
+ if (varp == &p_enc) {
+ // only encoding=utf-8 allowed
+ if (strcmp(p_enc, "utf-8") != 0) {
+ *errmsg = e_unsupportedoption;
+ return;
+ }
+ spell_reload();
+ }
+}
+
+static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_checked,
+ char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ int secure_save = secure;
+
+ // Reset the secure flag, since the value of 'keymap' has
+ // been checked to be safe.
+ secure = 0;
+
+ // load or unload key mapping tables
+ *errmsg = keymap_init();
+
+ secure = secure_save;
+
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+
+ if (*errmsg == NULL) {
+ if (*buf->b_p_keymap != NUL) {
+ // Installed a new keymap, switch on using it.
+ buf->b_p_iminsert = B_IMODE_LMAP;
+ if (buf->b_p_imsearch != B_IMODE_USE_INSERT) {
+ buf->b_p_imsearch = B_IMODE_LMAP;
+ }
+ } else {
+ // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
+ if (buf->b_p_iminsert == B_IMODE_LMAP) {
+ buf->b_p_iminsert = B_IMODE_NONE;
+ }
+ if (buf->b_p_imsearch == B_IMODE_LMAP) {
+ buf->b_p_imsearch = B_IMODE_USE_INSERT;
+ }
+ }
+ if ((opt_flags & OPT_LOCAL) == 0) {
+ set_iminsert_global(buf);
+ set_imsearch_global(buf);
+ }
+ status_redraw_buf(buf);
+ }
+}
+
+static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags,
+ char **errmsg)
+{
+ if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) {
+ *errmsg = e_modifiable;
+ } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ redraw_titles();
+ // update flag in swap file
+ ml_setflags(buf);
+ // Redraw needed when switching to/from "mac": a CR in the text
+ // will be displayed differently.
+ if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') {
+ redraw_buf_later(buf, UPD_NOT_VALID);
+ }
+ }
+}
+
+static void did_set_matchpairs(char **varp, char **errmsg)
+{
+ for (char *p = *varp; *p != NUL; p++) {
+ int x2 = -1;
+ int x3 = -1;
+
+ p += utfc_ptr2len(p);
+ if (*p != NUL) {
+ x2 = (unsigned char)(*p++);
+ }
+ if (*p != NUL) {
+ x3 = utf_ptr2char(p);
+ p += utfc_ptr2len(p);
+ }
+ if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
+ *errmsg = e_invarg;
+ break;
+ }
+ if (*p == NUL) {
+ break;
+ }
+ }
+}
+
+static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ while (*s && *s != ':') {
+ if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL
+ && !ascii_isdigit(*s) && *s != '-') {
+ *errmsg = illegal_char(errbuf, errbuflen, *s);
+ break;
+ }
+ s++;
+ }
+ if (*s++ == NUL) {
+ *errmsg = N_("E524: Missing colon");
+ } else if (*s == ',' || *s == NUL) {
+ *errmsg = N_("E525: Zero length string");
+ }
+ if (*errmsg != NULL) {
+ break;
+ }
+ while (*s && *s != ',') {
+ if (*s == '\\' && s[1] != NUL) {
+ s++;
+ }
+ s++;
+ }
+ s = skip_to_option_part(s);
+ }
+}
+
+static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, char **errmsg)
+{
+ char **local_ptr = varp == &p_lcs ? &win->w_p_lcs : &win->w_p_fcs;
+ // only apply the global value to "win" when it does not have a local value
+ *errmsg = set_chars_option(win, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+ if (*errmsg == NULL) {
+ // 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(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.
+ 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(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_verbosefile(char **errmsg)
+{
+ verbose_stop();
+ if (*p_vfile != NUL && verbose_open() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
+ // option.
+ *opt_idx = (((*opt)->fullname[0] == 'v')
+ ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
+ : *opt_idx);
+ *opt = get_option(*opt_idx);
+ // Update free_oldval now that we have the opt_idx for 'shada', otherwise
+ // there would be a disconnect between the check for P_ALLOCED at the start
+ // of the function and the set of P_ALLOCED at the end of the function.
+ *free_oldval = ((*opt)->flags & P_ALLOCED);
+ for (char *s = p_shada; *s;) {
+ // Check it's a valid character
+ if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, *s);
+ break;
+ }
+ if (*s == 'n') { // name is always last one
+ break;
+ } else if (*s == 'r') { // skip until next ','
+ while (*++s && *s != ',') {}
+ } else if (*s == '%') {
+ // optional number
+ while (ascii_isdigit(*++s)) {}
+ } else if (*s == '!' || *s == 'h' || *s == 'c') {
+ s++; // no extra chars
+ } else { // must have a number
+ while (ascii_isdigit(*++s)) {}
+
+ if (!ascii_isdigit(*(s - 1))) {
+ if (errbuf != NULL) {
+ vim_snprintf(errbuf, errbuflen,
+ _("E526: Missing number after <%s>"),
+ transchar_byte((uint8_t)(*(s - 1))));
+ *errmsg = errbuf;
+ } else {
+ *errmsg = "";
+ }
+ break;
+ }
+ }
+ if (*s == ',') {
+ s++;
+ } else if (*s) {
+ if (errbuf != NULL) {
+ *errmsg = N_("E527: Missing comma");
+ } else {
+ *errmsg = "";
+ }
+ break;
+ }
+ }
+ if (*p_shada && *errmsg == NULL && get_shada_parameter('\'') < 0) {
+ *errmsg = N_("E528: Must specify a ' value");
+ }
+}
+
+static void did_set_showbreak(char **varp, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ if (ptr2cells(s) != 1) {
+ *errmsg = e_showbreak_contains_unprintable_or_wide_character;
+ }
+ MB_PTR_ADV(s);
+ }
+}
+
+static void did_set_titleiconstring(char **varp)
+{
+ // 'titlestring' and 'iconstring'
+ int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+
+ // NULL => statusline syntax
+ if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
+ stl_syntax |= flagval;
+ } else {
+ stl_syntax &= ~flagval;
+ }
+ did_set_title();
+}
+
+static void did_set_selection(char **errmsg)
+{
+ if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_keymodel(char **errmsg)
+{
+ if (check_opt_strings(p_km, p_km_values, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+ km_startsel = (vim_strchr(p_km, 'a') != NULL);
+}
+
+static void did_set_display(char **errmsg)
+{
+ if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ (void)init_chartab();
+ msg_grid_validate();
+}
+
+static void did_set_spellfile(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+
+ if ((!valid_spellfile(*varp))) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(true);
+ }
+}
+
+static void did_set_spell(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+ if (!valid_spelllang(*varp)) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(false);
+ }
+}
+
+static void did_set_spellcapcheck(win_T *win, char **errmsg)
+{
+ // When 'spellcapcheck' is set compile the regexp program.
+ *errmsg = compile_cap_prog(win->w_s);
+}
+
+static void did_set_spelloptions(win_T *win, char **errmsg)
+{
+ if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags),
+ true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_spellsuggest(char **errmsg)
+{
+ if (spell_check_sps() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_mkspellmem(char **errmsg)
+{
+ if (spell_check_msm() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_buftype(buf_T *buf, win_T *win, char **errmsg)
+{
+ // 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) {
+ *errmsg = e_invarg;
+ } else {
+ if (win->w_status_height || global_stl_height()) {
+ win->w_redr_status = true;
+ redraw_later(win, UPD_VALID);
+ }
+ buf->b_help = (buf->b_p_bt[0] == 'h');
+ redraw_titles();
+ }
+}
+
+// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
+static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **errmsg)
+{
+ if (varp == &p_ruf) { // reset ru_wid first
+ ru_wid = 0;
+ } else if (varp == &win->w_p_stc) {
+ win->w_nrwidth_line_count = 0;
+ }
+ char *s = *varp;
+ if (varp == &p_ruf && *s == '%') {
+ // set ru_wid if 'ruf' starts with "%99("
+ if (*++s == '-') { // ignore a '-'
+ s++;
+ }
+ int wid = getdigits_int(&s, true, 0);
+ if (wid && *s == '(' && (*errmsg = check_stl_option(p_ruf)) == NULL) {
+ ru_wid = wid;
+ } else {
+ *errmsg = check_stl_option(p_ruf);
+ }
+ } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
+ // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
+ // only if it doesn't start with "%!"
+ *errmsg = check_stl_option(s);
+ }
+ if (varp == &p_ruf && *errmsg == NULL) {
+ comp_col();
+ }
+ // add / remove window bars for 'winbar'
+ if (gvarp == &p_wbr) {
+ set_winbar(true);
+ }
+}
+
+static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ // check if it is a valid value for 'complete' -- Acevedo
+ for (char *s = *varp; *s;) {
+ while (*s == ',' || *s == ' ') {
+ s++;
+ }
+ if (!*s) {
+ break;
+ }
+ if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, *s);
+ break;
+ }
+ if (*++s != NUL && *s != ',' && *s != ' ') {
+ if (s[-1] == 'k' || s[-1] == 's') {
+ // skip optional filename after 'k' and 's'
+ while (*s && *s != ',' && *s != ' ') {
+ if (*s == '\\' && s[1] != NUL) {
+ s++;
+ }
+ s++;
+ }
+ } else {
+ if (errbuf != NULL) {
+ vim_snprintf(errbuf, errbuflen,
+ _("E535: Illegal character after <%c>"),
+ *--s);
+ *errmsg = errbuf;
+ } else {
+ *errmsg = "";
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void did_set_completeopt(char **errmsg)
+{
+ if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ completeopt_was_set();
+ }
+}
+
+static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg)
+{
+ if (check_signcolumn(*varp) != OK) {
+ *errmsg = e_invarg;
+ }
+ // When changing the 'signcolumn' to or from 'number', recompute the
+ // width of the number column if 'number' or 'relativenumber' is set.
+ if (((*oldval == 'n' && *(oldval + 1) == 'u')
+ || (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u'))
+ && (win->w_p_nu || win->w_p_rnu)) {
+ win->w_nrwidth_line_count = 0;
+ }
+}
+
+static void did_set_foldcolumn(char **varp, char **errmsg)
+{
+ if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_pastetoggle(void)
+{
+ // 'pastetoggle': translate key codes like in a mapping
+ if (*p_pt) {
+ char *p = NULL;
+ (void)replace_termcodes(p_pt,
+ strlen(p_pt),
+ &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
+ CPO_TO_CPO_FLAGS);
+ if (p != NULL) {
+ free_string_option(p_pt);
+ p_pt = p;
+ }
+ }
+}
+
+static void did_set_backspace(char **errmsg)
+{
+ if (ascii_isdigit(*p_bs)) {
+ if (*p_bs > '3' || p_bs[1] != NUL) {
+ *errmsg = e_invarg;
+ }
+ } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_tagcase(buf_T *buf, int opt_flags, char **errmsg)
+{
+ unsigned int *flags;
+ char *p;
+
+ if (opt_flags & OPT_LOCAL) {
+ p = buf->b_p_tc;
+ flags = &buf->b_tc_flags;
+ } else {
+ p = p_tc;
+ flags = &tc_flags;
+ }
+
+ 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) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_diffopt(char **errmsg)
+{
+ if (diffopt_changed() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_foldmethod(win_T *win, char **varp, char **errmsg)
+{
+ if (check_opt_strings(*varp, p_fdm_values, false) != OK
+ || *win->w_p_fdm == NUL) {
+ *errmsg = e_invarg;
+ } else {
+ foldUpdateAll(win);
+ if (foldmethodIsDiff(win)) {
+ newFoldLevel();
+ }
+ }
+}
+
+static void did_set_foldmarker(win_T *win, char **varp, char **errmsg)
+{
+ char *p = vim_strchr(*varp, ',');
+ if (p == NULL) {
+ *errmsg = N_("E536: comma required");
+ } else if (p == *varp || p[1] == NUL) {
+ *errmsg = e_invarg;
+ } else if (foldmethodIsMarker(win)) {
+ foldUpdateAll(win);
+ }
+}
+
+static void did_set_commentstring(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strstr(*varp, "%s") == NULL) {
+ *errmsg = N_("E537: 'commentstring' must be empty or contain %s");
+ }
+}
+
+static void did_set_foldignore(win_T *win)
+{
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
+ }
+}
+
+static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char **errmsg)
+{
+ char *ve = p_ve;
+ unsigned int *flags = &ve_flags;
+
+ if (opt_flags & OPT_LOCAL) {
+ ve = win->w_p_ve;
+ flags = &win->w_ve_flags;
+ }
+
+ if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ } else if (strcmp(p_ve, oldval) != 0) {
+ // Recompute cursor position in case the new 've' setting
+ // changes something.
+ validate_virtcol_win(win);
+ coladvance(win->w_virtcol);
+ }
+ }
+}
+
+static void did_set_lispoptions(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked,
+ bool *value_changed, char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ *value_changed = strcmp(oldval, *varp) != 0;
+
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+}
+
+static void did_set_winhl(win_T *win, char **errmsg)
+{
+ if (!parse_winhl_opt(win)) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_varsoftabstop(buf_T *buf, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vsts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
+ }
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
+ }
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vsts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vsts_array))) {
+ xfree(oldarray);
+ } else {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
+ }
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
+ }
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vts_array))) {
+ xfree(oldarray);
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
+ }
+ } else {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_optexpr(win_T *win, char **p_opt, char **varp, char **gvarp)
+{
+ char *name = get_scriptlocal_funcname(*p_opt);
+ if (name != NULL) {
+ free_string_option(*p_opt);
+ *p_opt = name;
+ }
+}
+
+// handle option that is a list of flags.
+static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen,
+ char **errmsg)
+{
+ for (char *s = *varp; *s; s++) {
+ if (vim_strchr(flags, *s) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, *s);
+ break;
+ }
+ }
+}
+
+// When 'syntax' is set, load the syntax of that name
+static void do_syntax_autocmd(buf_T *buf, bool value_changed)
+{
+ static int syn_recursive = 0;
+
+ syn_recursive++;
+ // Only pass true for "force" when the value changed or not used
+ // recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname,
+ value_changed || syn_recursive == 1, buf);
+ buf->b_flags |= BF_SYN_SET;
+ syn_recursive--;
+}
+
+static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool value_changed)
+{
+ // 'filetype' is set, trigger the FileType autocommand
+ // Skip this when called from a modeline and the filetype was
+ // already set to this value.
+ if (!(opt_flags & OPT_MODELINE) || value_changed) {
+ static int ft_recursive = 0;
+ int secure_save = secure;
+
+ // Reset the secure flag, since the value of 'filetype' has
+ // been checked to be safe.
+ secure = 0;
+
+ ft_recursive++;
+ did_filetype = true;
+ // Only pass true for "force" when the value changed or not
+ // used recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname,
+ value_changed || ft_recursive == 1, buf);
+ ft_recursive--;
+ // Just in case the old "buf" is now invalid
+ if (varp != &(buf->b_p_ft)) {
+ varp = NULL;
+ }
+ secure = secure_save;
+ }
+}
+
+static void did_set_spelllang_source(win_T *win)
+{
+ char fname[200];
+ char *q = win->w_s->b_p_spl;
+
+ // Skip the first name if it is "cjk".
+ if (strncmp(q, "cjk,", 4) == 0) {
+ q += 4;
+ }
+
+ // Source the spell/LANG.vim in 'runtimepath'.
+ // They could set 'spellcapcheck' depending on the language.
+ // Use the first name in 'spelllang' up to '_region' or
+ // '.encoding'.
+ char *p;
+ for (p = q; *p != NUL; p++) {
+ if (!ASCII_ISALNUM(*p) && *p != '-') {
+ break;
+ }
+ }
+ if (p > q) {
+ vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
+ source_runtime(fname, DIP_ALL);
+ }
+}
+
/// Handle string options that need some action to perform when changed.
/// The new value must be allocated.
///
@@ -652,12 +1598,12 @@ static int shada_idx = -1;
/// @param value_checked value was checked to be safe, no need to set P_INSECURE
///
/// @return NULL for success, or an untranslated error message for an error
-char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
- int opt_flags, int *value_checked)
+static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp,
+ char *oldval, char *errbuf, size_t errbuflen, int opt_flags,
+ int *value_checked)
{
char *errmsg = NULL;
- char *s, *p;
- int did_chartab = false;
+ bool did_chartab = false;
vimoption_T *opt = get_option(opt_idx);
bool free_oldval = (opt->flags & P_ALLOCED);
bool value_changed = false;
@@ -670,401 +1616,85 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
if ((secure || sandbox != 0)
&& (opt->flags & P_SECURE)) {
errmsg = e_secure;
- } else if (((opt->flags & P_NFNAME)
- && strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
- || ((opt->flags & P_NDNAME)
- && strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) {
- // Check for a "normal" directory or file name in some options. Disallow a
- // path separator (slash and/or backslash), wildcards and characters that
- // are often illegal in a file name. Be more permissive if "secure" is off.
+ } else if (check_illegal_path_names(*varp, opt->flags)) {
+ // Check for a "normal" directory or file name in some options.
errmsg = e_invarg;
} else if (gvarp == &p_bkc) { // 'backupcopy'
- char *bkc = p_bkc;
- unsigned int *flags = &bkc_flags;
-
- if (opt_flags & OPT_LOCAL) {
- bkc = curbuf->b_p_bkc;
- flags = &curbuf->b_bkc_flags;
- }
-
- if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
- errmsg = e_invarg;
- }
-
- if (((*flags & BKC_AUTO) != 0)
- + ((*flags & BKC_YES) != 0)
- + ((*flags & BKC_NO) != 0) != 1) {
- // Must have exactly one of "auto", "yes" and "no".
- (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
- errmsg = e_invarg;
- }
- }
+ did_set_backupcopy(buf, oldval, opt_flags, &errmsg);
} else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode'
- if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
- *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
- errmsg = e_backupext_and_patchmode_are_equal;
- }
- } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt'
- if (briopt_check(curwin) == FAIL) {
- errmsg = e_invarg;
- }
- // list setting requires a redraw
- if (curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
+ did_set_backupext_or_patchmode(&errmsg);
+ } else if (varp == &win->w_p_briopt) { // 'breakindentopt'
+ did_set_breakindentopt(win, &errmsg);
} else if (varp == &p_isi
- || varp == &(curbuf->b_p_isk)
+ || varp == &buf->b_p_isk
|| varp == &p_isp
|| varp == &p_isf) {
- // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
- // If the new option is invalid, use old value. 'lisp' option: refill
- // g_chartab[] for '-' char
- if (init_chartab() == FAIL) {
- did_chartab = true; // need to restore it below
- errmsg = e_invarg; // error in value
- }
+ // 'isident', 'iskeyword', 'isprint or 'isfname' option
+ did_set_isopt(buf, &did_chartab, &errmsg);
} else if (varp == &p_hf) { // 'helpfile'
- // May compute new values for $VIM and $VIMRUNTIME
- if (didset_vim) {
- vim_unsetenv_ext("VIM");
- }
- if (didset_vimruntime) {
- vim_unsetenv_ext("VIMRUNTIME");
- }
+ did_set_helpfile();
} else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath'
runtime_search_path_invalidate();
- } else if (varp == &curwin->w_p_culopt
- || gvarp == &curwin->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
- if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_cc) { // 'colorcolumn'
- errmsg = check_colorcolumn(curwin);
+ } else if (varp == &win->w_p_culopt
+ || gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
+ did_set_cursorlineopt(win, varp, &errmsg);
+ } else if (varp == &win->w_p_cc) { // 'colorcolumn'
+ errmsg = check_colorcolumn(win);
} else if (varp == &p_hlg) { // 'helplang'
- // Check for "", "ab", "ab,cd", etc.
- for (s = p_hlg; *s != NUL; s += 3) {
- if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
- errmsg = e_invarg;
- break;
- }
- if (s[2] == NUL) {
- break;
- }
- }
+ did_set_helplang(&errmsg);
} else if (varp == &p_hl) { // 'highlight'
- if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
- errmsg = e_unsupportedoption;
- }
+ did_set_highlight(varp, &errmsg);
} else if (varp == &p_jop) { // 'jumpoptions'
- if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg);
} else if (gvarp == &p_nf) { // 'nrformats'
- if (check_opt_strings(*varp, p_nf_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(*varp, p_nf_values, true, &errmsg);
} else if (varp == &p_ssop) { // 'sessionoptions'
- if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
- // Don't allow both "sesdir" and "curdir".
- (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
- errmsg = e_invarg;
- }
+ did_set_sessionoptions(oldval, &errmsg);
} else if (varp == &p_vop) { // 'viewoptions'
- if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg);
} else if (varp == &p_rdb) { // 'redrawdebug'
- if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg);
} else if (varp == &p_sbo) { // 'scrollopt'
- if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg);
} else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth'
- if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- errmsg = check_chars_options();
- }
+ did_set_ambiwidth(&errmsg);
} else if (varp == &p_bg) { // 'background'
- if (check_opt_strings(p_bg, p_bg_values, false) == OK) {
- int dark = (*p_bg == 'd');
-
- init_highlight(false, false);
-
- if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
- // The color scheme must have set 'background' back to another
- // value, that's not what we want here. Disable the color
- // scheme and set the colors again.
- do_unlet(S_LEN("g:colors_name"), true);
- free_string_option(p_bg);
- p_bg = xstrdup((dark ? "dark" : "light"));
- check_string_option(&p_bg);
- init_highlight(false, false);
- }
- } else {
- errmsg = e_invarg;
- }
+ did_set_background(&errmsg);
} else if (varp == &p_wim) { // 'wildmode'
- if (check_opt_wim() == FAIL) {
- errmsg = e_invarg;
- }
+ did_set_wildmode(&errmsg);
} else if (varp == &p_wop) { // 'wildoptions'
- if (opt_strings_flags(p_wop, p_wop_values, &wop_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg);
} else if (varp == &p_wak) { // 'winaltkeys'
- if (*p_wak == NUL
- || check_opt_strings(p_wak, p_wak_values, false) != OK) {
- errmsg = e_invarg;
- }
+ did_set_winaltkeys(&errmsg);
} else if (varp == &p_ei) { // 'eventignore'
- if (check_ei() == FAIL) {
- errmsg = e_invarg;
- }
+ did_set_eventignore(&errmsg);
} else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) {
// 'encoding', 'fileencoding' and 'makeencoding'
- if (gvarp == &p_fenc) {
- if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
- errmsg = e_modifiable;
- } else if (vim_strchr(*varp, ',') != NULL) {
- // No comma allowed in 'fileencoding'; catches confusing it
- // with 'fileencodings'.
- errmsg = e_invarg;
- } else {
- // May show a "+" in the title now.
- redraw_titles();
- // Add 'fileencoding' to the swap file.
- ml_setflags(curbuf);
- }
- }
-
- if (errmsg == NULL) {
- // canonize the value, so that strcmp() can be used on it
- p = enc_canonize(*varp);
- xfree(*varp);
- *varp = p;
- if (varp == &p_enc) {
- // only encoding=utf-8 allowed
- if (strcmp(p_enc, "utf-8") != 0) {
- errmsg = e_unsupportedoption;
- } else {
- spell_reload();
- }
- }
- }
- } else if (varp == &curbuf->b_p_keymap) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- int secure_save = secure;
-
- // Reset the secure flag, since the value of 'keymap' has
- // been checked to be safe.
- secure = 0;
-
- // load or unload key mapping tables
- errmsg = keymap_init();
-
- secure = secure_save;
-
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
-
- if (errmsg == NULL) {
- if (*curbuf->b_p_keymap != NUL) {
- // Installed a new keymap, switch on using it.
- curbuf->b_p_iminsert = B_IMODE_LMAP;
- if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT) {
- curbuf->b_p_imsearch = B_IMODE_LMAP;
- }
- } else {
- // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
- if (curbuf->b_p_iminsert == B_IMODE_LMAP) {
- curbuf->b_p_iminsert = B_IMODE_NONE;
- }
- if (curbuf->b_p_imsearch == B_IMODE_LMAP) {
- curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
- }
- }
- if ((opt_flags & OPT_LOCAL) == 0) {
- set_iminsert_global();
- set_imsearch_global();
- }
- status_redraw_curbuf();
- }
+ did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg);
+ } else if (varp == &buf->b_p_keymap) {
+ did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg);
} else if (gvarp == &p_ff) { // 'fileformat'
- if (!MODIFIABLE(curbuf) && !(opt_flags & OPT_GLOBAL)) {
- errmsg = e_modifiable;
- } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- redraw_titles();
- // update flag in swap file
- ml_setflags(curbuf);
- // Redraw needed when switching to/from "mac": a CR in the text
- // will be displayed differently.
- if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm') {
- redraw_curbuf_later(UPD_NOT_VALID);
- }
- }
+ did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg);
} else if (varp == &p_ffs) { // 'fileformats'
- if (check_opt_strings(p_ffs, p_ff_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg);
} else if (gvarp == &p_mps) { // 'matchpairs'
- for (p = *varp; *p != NUL; p++) {
- int x2 = -1;
- int x3 = -1;
-
- p += utfc_ptr2len(p);
- if (*p != NUL) {
- x2 = (unsigned char)(*p++);
- }
- if (*p != NUL) {
- x3 = utf_ptr2char(p);
- p += utfc_ptr2len(p);
- }
- if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
- errmsg = e_invarg;
- break;
- }
- if (*p == NUL) {
- break;
- }
- }
+ did_set_matchpairs(varp, &errmsg);
} else if (gvarp == &p_com) { // 'comments'
- for (s = *varp; *s;) {
- while (*s && *s != ':') {
- if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL
- && !ascii_isdigit(*s) && *s != '-') {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- s++;
- }
- if (*s++ == NUL) {
- errmsg = N_("E524: Missing colon");
- } else if (*s == ',' || *s == NUL) {
- errmsg = N_("E525: Zero length string");
- }
- if (errmsg != NULL) {
- break;
- }
- while (*s && *s != ',') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
- s++;
- }
- s = skip_to_option_part(s);
- }
+ did_set_comments(varp, errbuf, errbuflen, &errmsg);
} else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars'
- char **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) {
- // 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(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.
- 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(UPD_NOT_VALID);
- }
- } else if (varp == &curwin->w_p_lcs) { // local 'listchars'
- errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
- errmsg = set_chars_option(curwin, varp, true);
+ did_set_global_listfillchars(win, varp, opt_flags, &errmsg);
+ } else if (varp == &win->w_p_lcs) { // local 'listchars'
+ errmsg = set_chars_option(win, varp, true);
+ } else if (varp == &win->w_p_fcs) { // local 'fillchars'
+ errmsg = set_chars_option(win, varp, true);
} else if (varp == &p_cedit) { // 'cedit'
errmsg = check_cedit();
} else if (varp == &p_vfile) { // 'verbosefile'
- verbose_stop();
- if (*p_vfile != NUL && verbose_open() == FAIL) {
- errmsg = e_invarg;
- }
+ did_set_verbosefile(&errmsg);
} else if (varp == &p_shada) { // 'shada'
- // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
- // option.
- opt_idx = ((opt->fullname[0] == 'v')
- ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
- : opt_idx);
- opt = get_option(opt_idx);
- // Update free_oldval now that we have the opt_idx for 'shada', otherwise
- // there would be a disconnect between the check for P_ALLOCED at the start
- // of the function and the set of P_ALLOCED at the end of the function.
- free_oldval = (opt->flags & P_ALLOCED);
- for (s = p_shada; *s;) {
- // Check it's a valid character
- if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*s == 'n') { // name is always last one
- break;
- } else if (*s == 'r') { // skip until next ','
- while (*++s && *s != ',') {}
- } else if (*s == '%') {
- // optional number
- while (ascii_isdigit(*++s)) {}
- } else if (*s == '!' || *s == 'h' || *s == 'c') {
- s++; // no extra chars
- } else { // must have a number
- while (ascii_isdigit(*++s)) {}
-
- if (!ascii_isdigit(*(s - 1))) {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E526: Missing number after <%s>"),
- transchar_byte((uint8_t)(*(s - 1))));
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
- }
- }
- if (*s == ',') {
- s++;
- } else if (*s) {
- if (errbuf != NULL) {
- errmsg = N_("E527: Missing comma");
- } else {
- errmsg = "";
- }
- break;
- }
- }
- if (*p_shada && errmsg == NULL && get_shada_parameter('\'') < 0) {
- errmsg = N_("E528: Must specify a ' value");
- }
+ did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg);
} else if (gvarp == &p_sbr) { // 'showbreak'
- for (s = *varp; *s;) {
- if (ptr2cells(s) != 1) {
- errmsg = e_showbreak_contains_unprintable_or_wide_character;
- }
- MB_PTR_ADV(s);
- }
+ did_set_showbreak(varp, &errmsg);
} else if (varp == &p_guicursor) { // 'guicursor'
errmsg = parse_shape_opt(SHAPE_CURSOR);
} else if (varp == &p_langmap) { // 'langmap'
@@ -1073,507 +1703,157 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
fill_breakat_flags();
} else if (varp == &p_titlestring || varp == &p_iconstring) {
// 'titlestring' and 'iconstring'
- int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
-
- // NULL => statusline syntax
- if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
- stl_syntax |= flagval;
- } else {
- stl_syntax &= ~flagval;
- }
- did_set_title();
+ did_set_titleiconstring(varp);
} else if (varp == &p_sel) { // 'selection'
- if (*p_sel == NUL
- || check_opt_strings(p_sel, p_sel_values, false) != OK) {
- errmsg = e_invarg;
- }
+ did_set_selection(&errmsg);
} else if (varp == &p_slm) { // 'selectmode'
- if (check_opt_strings(p_slm, p_slm_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_slm, p_slm_values, true, &errmsg);
} else if (varp == &p_km) { // 'keymodel'
- if (check_opt_strings(p_km, p_km_values, true) != OK) {
- errmsg = e_invarg;
- } else {
- km_stopsel = (vim_strchr(p_km, 'o') != NULL);
- km_startsel = (vim_strchr(p_km, 'a') != NULL);
- }
+ did_set_keymodel(&errmsg);
} else if (varp == &p_mousem) { // 'mousemodel'
- if (check_opt_strings(p_mousem, p_mousem_values, false) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg);
} else if (varp == &p_mousescroll) { // 'mousescroll'
errmsg = check_mousescroll(p_mousescroll);
} else if (varp == &p_swb) { // 'switchbuf'
- if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg);
} else if (varp == &p_spk) { // 'splitkeep'
- if (check_opt_strings(p_spk, p_spk_values, false) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_spk, p_spk_values, false, &errmsg);
} else if (varp == &p_debug) { // 'debug'
- if (check_opt_strings(p_debug, p_debug_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_debug, p_debug_values, true, &errmsg);
} else if (varp == &p_dy) { // 'display'
- if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
- errmsg = e_invarg;
- } else {
- (void)init_chartab();
- msg_grid_validate();
- }
+ did_set_display(&errmsg);
} else if (varp == &p_ead) { // 'eadirection'
- if (check_opt_strings(p_ead, p_ead_values, false) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(p_ead, p_ead_values, false, &errmsg);
} else if (varp == &p_cb) { // 'clipboard'
- if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curwin->w_s->b_p_spl) // 'spell'
- || varp == &(curwin->w_s->b_p_spf)) {
- // When 'spelllang' or 'spellfile' is set and there is a window for this
- // buffer in which 'spell' is set load the wordlists.
- const bool is_spellfile = varp == &(curwin->w_s->b_p_spf);
-
- if ((is_spellfile && !valid_spellfile(*varp))
- || (!is_spellfile && !valid_spelllang(*varp))) {
- errmsg = e_invarg;
- } else {
- errmsg = did_set_spell_option(is_spellfile);
- }
- } else if (varp == &(curwin->w_s->b_p_spc)) {
- // When 'spellcapcheck' is set compile the regexp program.
- errmsg = compile_cap_prog(curwin->w_s);
- } else if (varp == &(curwin->w_s->b_p_spo)) { // 'spelloptions'
- if (opt_strings_flags(curwin->w_s->b_p_spo, p_spo_values, &(curwin->w_s->b_p_spo_flags),
- true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg);
+ } else if (varp == &win->w_s->b_p_spf) {
+ did_set_spellfile(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spl) { // 'spell'
+ did_set_spell(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spc) {
+ did_set_spellcapcheck(win, &errmsg);
+ } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions'
+ did_set_spelloptions(win, &errmsg);
} else if (varp == &p_sps) { // 'spellsuggest'
- if (spell_check_sps() != OK) {
- errmsg = e_invarg;
- }
+ did_set_spellsuggest(&errmsg);
} else if (varp == &p_msm) { // 'mkspellmem'
- if (spell_check_msm() != OK) {
- errmsg = e_invarg;
- }
+ did_set_mkspellmem(&errmsg);
} else if (gvarp == &p_bh) {
- // When 'bufhidden' is set, check for valid value.
- if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_bt) {
- // When 'buftype' is set, check for valid value.
- if ((curbuf->terminal && curbuf->b_p_bt[0] != 't')
- || (!curbuf->terminal && curbuf->b_p_bt[0] == 't')
- || check_opt_strings(curbuf->b_p_bt, p_buftype_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- if (curwin->w_status_height || global_stl_height()) {
- curwin->w_redr_status = true;
- redraw_later(curwin, UPD_VALID);
- }
- curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
- redraw_titles();
- }
+ did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg);
+ } else if (gvarp == &p_bt) { // 'buftype'
+ did_set_buftype(buf, win, &errmsg);
} else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
- || varp == &p_ruf || varp == &curwin->w_p_stc) {
+ || varp == &p_ruf || varp == &win->w_p_stc) {
// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
- int wid;
-
- if (varp == &p_ruf) { // reset ru_wid first
- ru_wid = 0;
- } else if (varp == &curwin->w_p_stc) {
- curwin->w_nrwidth_line_count = 0;
- }
- s = *varp;
- if (varp == &p_ruf && *s == '%') {
- // set ru_wid if 'ruf' starts with "%99("
- if (*++s == '-') { // ignore a '-'
- s++;
- }
- wid = getdigits_int(&s, true, 0);
- if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) {
- ru_wid = wid;
- } else {
- errmsg = check_stl_option(p_ruf);
- }
- } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
- // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
- // only if it doesn't start with "%!"
- errmsg = check_stl_option(s);
- }
- if (varp == &p_ruf && errmsg == NULL) {
- comp_col();
- }
- // add / remove window bars for 'winbar'
- if (gvarp == &p_wbr) {
- set_winbar(true);
- }
- } else if (gvarp == &p_cpt) {
- // check if it is a valid value for 'complete' -- Acevedo
- for (s = *varp; *s;) {
- while (*s == ',' || *s == ' ') {
- s++;
- }
- if (!*s) {
- break;
- }
- if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*++s != NUL && *s != ',' && *s != ' ') {
- if (s[-1] == 'k' || s[-1] == 's') {
- // skip optional filename after 'k' and 's'
- while (*s && *s != ',' && *s != ' ') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
- s++;
- }
- } else {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E535: Illegal character after <%c>"),
- *--s);
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
- }
- }
- }
+ did_set_statusline(win, varp, gvarp, &errmsg);
+ } else if (gvarp == &p_cpt) { // 'complete'
+ did_set_complete(varp, errbuf, errbuflen, &errmsg);
} else if (varp == &p_cot) { // 'completeopt'
- if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
- errmsg = e_invarg;
- } else {
- completeopt_was_set();
- }
+ did_set_completeopt(&errmsg);
#ifdef BACKSLASH_IN_FILENAME
} else if (gvarp == &p_csl) { // 'completeslash'
if (check_opt_strings(p_csl, p_csl_values, false) != OK
- || check_opt_strings(curbuf->b_p_csl, p_csl_values, false) != OK) {
+ || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) {
errmsg = e_invarg;
}
#endif
- } else if (varp == &curwin->w_p_scl) { // 'signcolumn'
- if (check_signcolumn(*varp) != OK) {
- errmsg = e_invarg;
- }
- // When changing the 'signcolumn' to or from 'number', recompute the
- // width of the number column if 'number' or 'relativenumber' is set.
- if (((*oldval == 'n' && *(oldval + 1) == 'u')
- || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u'))
- && (curwin->w_p_nu || curwin->w_p_rnu)) {
- curwin->w_nrwidth_line_count = 0;
- }
+ } else if (varp == &win->w_p_scl) { // 'signcolumn'
+ did_set_signcolumn(win, varp, oldval, &errmsg);
} else if (varp == &p_sloc) { // 'showcmdloc'
- if (check_opt_strings(p_sloc, p_sloc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_fdc
- || varp == &curwin->w_allbuf_opt.wo_fdc) {
+ did_set_opt_strings(*varp, p_sloc_values, false, &errmsg);
+ } else if (varp == &win->w_p_fdc
+ || varp == &win->w_allbuf_opt.wo_fdc) {
// 'foldcolumn'
- if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_pt) {
- // 'pastetoggle': translate key codes like in a mapping
- if (*p_pt) {
- p = NULL;
- (void)replace_termcodes(p_pt,
- strlen(p_pt),
- &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
- CPO_TO_CPO_FLAGS);
- if (p != NULL) {
- free_string_option(p_pt);
- p_pt = p;
- }
- }
+ did_set_foldcolumn(varp, &errmsg);
+ } else if (varp == &p_pt) { // 'pastetoggle'
+ did_set_pastetoggle();
} else if (varp == &p_bs) { // 'backspace'
- if (ascii_isdigit(*p_bs)) {
- if (*p_bs > '3' || p_bs[1] != NUL) {
- errmsg = e_invarg;
- }
- } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_backspace(&errmsg);
} else if (varp == &p_bo) {
- if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg);
} else if (gvarp == &p_tc) { // 'tagcase'
- unsigned int *flags;
-
- if (opt_flags & OPT_LOCAL) {
- p = curbuf->b_p_tc;
- flags = &curbuf->b_tc_flags;
- } else {
- p = p_tc;
- flags = &tc_flags;
- }
-
- 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) {
- errmsg = e_invarg;
- }
+ did_set_tagcase(buf, opt_flags, &errmsg);
} else if (varp == &p_cmp) { // 'casemap'
- if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg);
} else if (varp == &p_dip) { // 'diffopt'
- if (diffopt_changed() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdm) { // 'foldmethod'
- if (check_opt_strings(*varp, p_fdm_values, false) != OK
- || *curwin->w_p_fdm == NUL) {
- errmsg = e_invarg;
- } else {
- foldUpdateAll(curwin);
- if (foldmethodIsDiff(curwin)) {
- newFoldLevel();
- }
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) { // 'foldmarker'
- p = vim_strchr(*varp, ',');
- if (p == NULL) {
- errmsg = N_("E536: comma required");
- } else if (p == *varp || p[1] == NUL) {
- errmsg = e_invarg;
- } else if (foldmethodIsMarker(curwin)) {
- foldUpdateAll(curwin);
- }
+ did_set_diffopt(&errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod'
+ did_set_foldmethod(win, varp, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker'
+ did_set_foldmarker(win, varp, &errmsg);
} else if (gvarp == &p_cms) { // 'commentstring'
- if (**varp != NUL && strstr(*varp, "%s") == NULL) {
- errmsg = N_("E537: 'commentstring' must be empty or contain %s");
- }
+ did_set_commentstring(varp, &errmsg);
} else if (varp == &p_fdo) { // 'foldopen'
- if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true) != OK) {
- errmsg = e_invarg;
- }
+ did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg);
} else if (varp == &p_fcl) { // 'foldclose'
- if (check_opt_strings(p_fcl, p_fcl_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdi) { // 'foldignore'
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
+ did_set_opt_strings(*varp, p_fcl_values, true, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore'
+ did_set_foldignore(win);
} else if (gvarp == &p_ve) { // 'virtualedit'
- char *ve = p_ve;
- unsigned int *flags = &ve_flags;
-
- if (opt_flags & OPT_LOCAL) {
- ve = curwin->w_p_ve;
- flags = &curwin->w_ve_flags;
- }
-
- if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
- errmsg = e_invarg;
- } else if (strcmp(p_ve, oldval) != 0) {
- // Recompute cursor position in case the new 've' setting
- // changes something.
- validate_virtcol();
- coladvance(curwin->w_virtcol);
- }
- }
+ did_set_virtualedit(win, opt_flags, oldval, &errmsg);
} else if (gvarp == &p_cino) { // 'cinoptions'
// TODO(vim): recognize errors
- parse_cino(curbuf);
+ parse_cino(buf);
} else if (gvarp == &p_lop) { // 'lispoptions'
- if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
- errmsg = e_invarg;
- }
+ did_set_lispoptions(varp, &errmsg);
} else if (varp == &p_icm) { // 'inccommand'
- if (check_opt_strings(p_icm, p_icm_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_ft) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
-
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (gvarp == &p_syn) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
-
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (varp == &curwin->w_p_winhl) {
- if (!parse_winhl_opt(curwin)) {
- errmsg = e_invarg;
- }
+ did_set_opt_strings(*varp, p_icm_values, false, &errmsg);
+ } else if (gvarp == &p_ft || gvarp == &p_syn) {
+ did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg);
+ } else if (varp == &win->w_p_winhl) {
+ did_set_winhl(win, &errmsg);
} else if (varp == &p_tpf) {
- if (opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curbuf->b_p_vsts)) { // 'varsofttabstop'
- char *cp;
-
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vsts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vsts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) {
- xfree(oldarray);
- } else {
- errmsg = e_invarg;
- }
- }
- }
- } else if (varp == &(curbuf->b_p_vts)) { // 'vartabstop'
- char *cp;
-
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) {
- xfree(oldarray);
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
- } else {
- errmsg = e_invarg;
- }
- }
- }
- } else if (varp == &p_dex
- || varp == &curwin->w_p_fde
- || varp == &curwin->w_p_fdt
- || gvarp == &p_fex
- || gvarp == &p_inex
- || gvarp == &p_inde
- || varp == &p_pex) { // '*expr' options
- char **p_opt = NULL;
-
- // If the option value starts with <SID> or s:, then replace that with
- // the script identifier.
-
- if (varp == &p_dex) { // 'diffexpr'
- p_opt = &p_dex;
- }
- if (varp == &curwin->w_p_fde) { // 'foldexpr'
- p_opt = &curwin->w_p_fde;
- }
- if (varp == &curwin->w_p_fdt) { // 'foldtext'
- p_opt = &curwin->w_p_fdt;
- }
- if (gvarp == &p_fex) { // 'formatexpr'
- p_opt = &curbuf->b_p_fex;
- }
- if (gvarp == &p_inex) { // 'includeexpr'
- p_opt = &curbuf->b_p_inex;
- }
- if (gvarp == &p_inde) { // 'indentexpr'
- p_opt = &curbuf->b_p_inde;
- }
- if (varp == &p_pex) { // 'patchexpr'
- p_opt = &p_pex;
- }
-
- if (p_opt != NULL) {
- char *name = get_scriptlocal_funcname(*p_opt);
- if (name != NULL) {
- free_string_option(*p_opt);
- *p_opt = name;
- }
- }
-
- if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin)) {
- foldUpdateAll(curwin);
- }
+ did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg);
+ } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop'
+ did_set_varsoftabstop(buf, varp, &errmsg);
+ } else if (varp == &buf->b_p_vts) { // 'vartabstop'
+ did_set_vartabstop(buf, win, varp, &errmsg);
+ } else if (varp == &p_dex) { // 'diffexpr'
+ did_set_optexpr(win, &p_dex, varp, gvarp);
+ } else if (varp == &win->w_p_fde) { // 'foldexpr'
+ did_set_optexpr(win, &win->w_p_fde, varp, gvarp);
+ if (foldmethodIsExpr(win)) {
+ foldUpdateAll(win);
+ }
+ } else if (varp == &win->w_p_fdt) { // 'foldtext'
+ did_set_optexpr(win, &win->w_p_fdt, varp, gvarp);
+ } else if (varp == &p_pex) { // 'patchexpr'
+ did_set_optexpr(win, &p_pex, varp, gvarp);
+ } else if (gvarp == &p_fex) { // 'formatexpr'
+ did_set_optexpr(win, &buf->b_p_fex, varp, gvarp);
+ } else if (gvarp == &p_inex) { // 'includeexpr'
+ did_set_optexpr(win, &buf->b_p_inex, varp, gvarp);
+ } else if (gvarp == &p_inde) { // 'indentexpr'
+ did_set_optexpr(win, &buf->b_p_inde, varp, gvarp);
} else if (gvarp == &p_cfu) { // 'completefunc'
- if (set_completefunc_option() == FAIL) {
- errmsg = e_invarg;
- }
+ set_completefunc_option(&errmsg);
} else if (gvarp == &p_ofu) { // 'omnifunc'
- if (set_omnifunc_option() == FAIL) {
- errmsg = e_invarg;
- }
+ set_omnifunc_option(buf, &errmsg);
} else if (gvarp == &p_tsrfu) { // 'thesaurusfunc'
- if (set_thesaurusfunc_option() == FAIL) {
- errmsg = e_invarg;
- }
+ set_thesaurusfunc_option(&errmsg);
} else if (varp == &p_opfunc) { // 'operatorfunc'
- if (set_operatorfunc_option() == FAIL) {
- errmsg = e_invarg;
- }
+ set_operatorfunc_option(&errmsg);
} else if (varp == &p_qftf) { // 'quickfixtextfunc'
- if (qf_process_qftf_option() == FAIL) {
- errmsg = e_invarg;
- }
+ qf_process_qftf_option(&errmsg);
} else if (gvarp == &p_tfu) { // 'tagfunc'
- if (set_tagfunc_option() == FAIL) {
- errmsg = e_invarg;
- }
- } else {
- // Options that are a list of flags.
- p = NULL;
- if (varp == &p_ww) { // 'whichwrap'
- p = WW_ALL;
- }
- if (varp == &p_shm) { // 'shortmess'
- p = SHM_ALL;
- } else if (varp == &(p_cpo)) { // 'cpoptions'
- p = CPO_VI;
- } else if (varp == &(curbuf->b_p_fo)) { // 'formatoptions'
- p = FO_ALL;
- } else if (varp == &curwin->w_p_cocu) { // 'concealcursor'
- p = COCU_ALL;
- } else if (varp == &p_mouse) { // 'mouse'
- p = MOUSE_ALL;
- }
- if (p != NULL) {
- for (s = *varp; *s; s++) {
- if (vim_strchr(p, (uint8_t)(*s)) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- }
+ set_tagfunc_option(&errmsg);
+ } else if (varp == &p_ww) { // 'whichwrap'
+ did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_shm) { // 'shortmess'
+ did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_cpo) { // 'cpoptions'
+ did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg);
+ } else if (varp == &buf->b_p_fo) { // 'formatoptions'
+ did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &win->w_p_cocu) { // 'concealcursor'
+ did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_mouse) { // 'mouse'
+ did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg);
+ } else if (gvarp == &p_flp) {
+ if (win->w_briopt_list) {
+ // Changing Formatlistpattern when briopt includes the list setting:
+ // redraw
+ redraw_all_later(UPD_NOT_VALID);
}
}
@@ -1583,7 +1863,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
*varp = oldval;
// When resetting some values, need to act on it.
if (did_chartab) {
- (void)init_chartab();
+ (void)buf_init_chartab(buf, true);
}
} else {
// Remember where the option was set.
@@ -1600,7 +1880,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
&& (opt->indir & PV_BOTH)) {
// global option with local value set to use global value; free
// the local value and make it empty
- p = get_varp_scope(opt, OPT_LOCAL);
+ char *p = get_varp_scope(opt, OPT_LOCAL);
free_string_option(*(char **)p);
*(char **)p = empty_option;
} else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) {
@@ -1609,65 +1889,12 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
}
// Trigger the autocommand only after setting the flags.
- // When 'syntax' is set, load the syntax of that name
- if (varp == &(curbuf->b_p_syn)) {
- static int syn_recursive = 0;
-
- syn_recursive++;
- // Only pass true for "force" when the value changed or not used
- // recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
- value_changed || syn_recursive == 1, curbuf);
- curbuf->b_flags |= BF_SYN_SET;
- syn_recursive--;
- } else if (varp == &(curbuf->b_p_ft)) {
- // 'filetype' is set, trigger the FileType autocommand
- // Skip this when called from a modeline and the filetype was
- // already set to this value.
- if (!(opt_flags & OPT_MODELINE) || value_changed) {
- static int ft_recursive = 0;
- int secure_save = secure;
-
- // Reset the secure flag, since the value of 'filetype' has
- // been checked to be safe.
- secure = 0;
-
- ft_recursive++;
- did_filetype = true;
- // Only pass true for "force" when the value changed or not
- // used recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
- value_changed || ft_recursive == 1, curbuf);
- ft_recursive--;
- // Just in case the old "curbuf" is now invalid
- if (varp != &(curbuf->b_p_ft)) {
- varp = NULL;
- }
- secure = secure_save;
- }
- }
- if (varp == &(curwin->w_s->b_p_spl)) {
- char fname[200];
- char *q = curwin->w_s->b_p_spl;
-
- // Skip the first name if it is "cjk".
- if (strncmp(q, "cjk,", 4) == 0) {
- q += 4;
- }
-
- // Source the spell/LANG.vim in 'runtimepath'.
- // They could set 'spellcapcheck' depending on the language.
- // Use the first name in 'spelllang' up to '_region' or
- // '.encoding'.
- for (p = q; *p != NUL; p++) {
- if (!ASCII_ISALNUM(*p) && *p != '-') {
- break;
- }
- }
- if (p > q) {
- vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
- source_runtime(fname, DIP_ALL);
- }
+ if (varp == &buf->b_p_syn) {
+ do_syntax_autocmd(buf, value_changed);
+ } else if (varp == &buf->b_p_ft) {
+ do_filetype_autocmd(buf, varp, opt_flags, value_changed);
+ } else if (varp == &win->w_s->b_p_spl) {
+ did_set_spelllang_source(win);
}
}
@@ -1675,22 +1902,23 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
setmouse(); // in case 'mouse' changed
}
- // Changing Formatlistpattern when briopt includes the list setting:
- // redraw
- if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) && curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
-
- if (curwin->w_curswant != MAXCOL
+ if (win->w_curswant != MAXCOL
&& (opt->flags & (P_CURSWANT | P_RALL)) != 0) {
- curwin->w_set_curswant = true;
+ win->w_set_curswant = true;
}
- check_redraw(opt->flags);
+ check_redraw_for(buf, win, opt->flags);
return errmsg;
}
+char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
+ int opt_flags, int *value_checked)
+{
+ return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen,
+ opt_flags, value_checked);
+}
+
/// Check an option that can be a range of string values.
///
/// @param list when true: accept a list of values
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 44daefddc7..5518fdfa51 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -3854,10 +3854,11 @@ static buf_T *qf_find_buf(qf_info_T *qi)
}
/// Process the 'quickfixtextfunc' option value.
-/// @return OK or FAIL
-int qf_process_qftf_option(void)
+void qf_process_qftf_option(char **errmsg)
{
- return option_set_callback_func(p_qftf, &qftf_cb);
+ if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Update the w:quickfix_title variable in the quickfix/location list window in
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 18c7684584..197184c181 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -210,22 +210,20 @@ static Callback tfu_cb; // 'tagfunc' callback function
/// Reads the 'tagfunc' option value and convert that to a callback value.
/// Invoked when the 'tagfunc' option is set. The option value can be a name of
/// a function (string), or function(<name>) or funcref(<name>) or a lambda.
-int set_tagfunc_option(void)
+void set_tagfunc_option(char **errmsg)
{
callback_free(&tfu_cb);
callback_free(&curbuf->b_tfu_cb);
if (*curbuf->b_p_tfu == NUL) {
- return OK;
+ return;
}
if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL) {
- return FAIL;
+ *errmsg = e_invarg;
}
callback_copy(&curbuf->b_tfu_cb, &tfu_cb);
-
- return OK;
}
#if defined(EXITFREE)