summaryrefslogtreecommitdiff
path: root/src/option.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-06-15 17:12:48 +0200
committerBram Moolenaar <Bram@vim.org>2019-06-15 17:12:48 +0200
commitd7c968794710f338d491072171df48f96612cf72 (patch)
treed5edca7e09283ff5c345d8e113a10829a70412a2 /src/option.c
parentbffc50494d52a3690cbbc5c7b34a835f9153184e (diff)
downloadvim-git-d7c968794710f338d491072171df48f96612cf72.tar.gz
patch 8.1.1542: an OptionSet autocommand does not get enough infov8.1.1542
Problem: An OptionSet autocommand does not get enough info. Solution: Add v:option_command, v:option_oldlocal and v:option_oldglobal. (Latrice Wilgus, closes #4118)
Diffstat (limited to 'src/option.c')
-rw-r--r--src/option.c176
1 files changed, 161 insertions, 15 deletions
diff --git a/src/option.c b/src/option.c
index 2d22c4c97..12a0816f3 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4336,12 +4336,25 @@ set_title_defaults(void)
#endif
#if defined(FEAT_EVAL)
+/*
+ * Trigger the OptionSet autocommand.
+ * "opt_idx" is the index of the option being set.
+ * "opt_flags" can be OPT_LOCAL etc.
+ * "oldval" the old value
+ * "oldval_l" the old local value (only non-NULL if global and local value
+ * are set)
+ * "oldval_g" the old global value (only non-NULL if global and local value
+ * are set)
+ * "newval" the new value
+ */
static void
trigger_optionsset_string(
int opt_idx,
int opt_flags,
- char_u *oldval,
- char_u *newval)
+ char_u *oldval,
+ char_u *oldval_l,
+ char_u *oldval_g,
+ char_u *newval)
{
// Don't do this recursively.
if (oldval != NULL && newval != NULL
@@ -4354,6 +4367,27 @@ trigger_optionsset_string(
set_vim_var_string(VV_OPTION_OLD, oldval, -1);
set_vim_var_string(VV_OPTION_NEW, newval, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+ if (opt_flags & OPT_LOCAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
+ if (opt_flags & OPT_GLOBAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
+ }
+ if (opt_flags & OPT_MODELINE)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
apply_autocmds(EVENT_OPTIONSET,
(char_u *)options[opt_idx].fullname, NULL, FALSE, NULL);
reset_v_option_vars();
@@ -4836,8 +4870,12 @@ do_set(
char_u *oldval = NULL; /* previous value if *varp */
char_u *newval;
char_u *origval = NULL;
+ char_u *origval_l = NULL;
+ char_u *origval_g = NULL;
#if defined(FEAT_EVAL)
char_u *saved_origval = NULL;
+ char_u *saved_origval_l = NULL;
+ char_u *saved_origval_g = NULL;
char_u *saved_newval = NULL;
#endif
unsigned newlen;
@@ -4857,8 +4895,23 @@ do_set(
* new value is valid. */
oldval = *(char_u **)varp;
- /* When setting the local value of a global
- * option, the old value may be the global value. */
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ origval_l = *(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_LOCAL);
+ origval_g = *(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_GLOBAL);
+
+ // A global-local string option might have an empty
+ // option as value to indicate that the global
+ // value should be used.
+ if (((int)options[opt_idx].indir & PV_BOTH)
+ && origval_l == empty_option)
+ origval_l = origval_g;
+ }
+
+ // 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))
origval = *(char_u **)get_varp(
@@ -4944,6 +4997,10 @@ do_set(
vim_free(oldval);
if (origval == oldval)
origval = *(char_u **)varp;
+ if (origval_l == oldval)
+ origval_l = *(char_u **)varp;
+ if (origval_g == oldval)
+ origval_g = *(char_u **)varp;
oldval = *(char_u **)varp;
}
/*
@@ -5201,6 +5258,10 @@ do_set(
/* newval (and varp) may become invalid if the
* buffer is closed by autocommands. */
saved_newval = vim_strsave(newval);
+ if (origval_l != NULL)
+ saved_origval_l = vim_strsave(origval_l);
+ if (origval_g != NULL)
+ saved_origval_g = vim_strsave(origval_g);
}
#endif
@@ -5234,9 +5295,13 @@ do_set(
#if defined(FEAT_EVAL)
if (errmsg == NULL)
- trigger_optionsset_string(opt_idx, opt_flags,
- saved_origval, saved_newval);
+ trigger_optionsset_string(
+ opt_idx, opt_flags, saved_origval,
+ saved_origval_l, saved_origval_g,
+ saved_newval);
vim_free(saved_origval);
+ vim_free(saved_origval_l);
+ vim_free(saved_origval_g);
vim_free(saved_newval);
#endif
/* If error detected, print the error message. */
@@ -6070,8 +6135,12 @@ set_string_option(
char_u *s;
char_u **varp;
char_u *oldval;
+ char_u *oldval_l = NULL;
+ char_u *oldval_g = NULL;
#if defined(FEAT_EVAL)
char_u *saved_oldval = NULL;
+ char_u *saved_oldval_l = NULL;
+ char_u *saved_oldval_g = NULL;
char_u *saved_newval = NULL;
#endif
char *r = NULL;
@@ -6089,6 +6158,13 @@ set_string_option(
? OPT_GLOBAL : OPT_LOCAL)
: opt_flags);
oldval = *varp;
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ oldval_l = *(char_u **)get_varp_scope(&(options[opt_idx]),
+ OPT_LOCAL);
+ oldval_g = *(char_u **)get_varp_scope(&(options[opt_idx]),
+ OPT_GLOBAL);
+ }
*varp = s;
#if defined(FEAT_EVAL)
@@ -6098,6 +6174,10 @@ set_string_option(
# endif
)
{
+ if (oldval_l != NULL)
+ saved_oldval_l = vim_strsave(oldval_l);
+ if (oldval_g != NULL)
+ saved_oldval_g = vim_strsave(oldval_g);
saved_oldval = vim_strsave(oldval);
saved_newval = vim_strsave(s);
}
@@ -6110,8 +6190,11 @@ set_string_option(
/* call autocommand after handling side effects */
if (r == NULL)
trigger_optionsset_string(opt_idx, opt_flags,
- saved_oldval, saved_newval);
+ saved_oldval, saved_oldval_l,
+ saved_oldval_g, saved_newval);
vim_free(saved_oldval);
+ vim_free(saved_oldval_l);
+ vim_free(saved_oldval_g);
vim_free(saved_newval);
#endif
}
@@ -8442,6 +8525,7 @@ set_bool_option(
int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
{
int old_value = *(int *)varp;
+ int old_global_value = 0;
/* Disallow changing some options from secure mode */
if ((secure
@@ -8451,6 +8535,13 @@ set_bool_option(
) && (options[opt_idx].flags & P_SECURE))
return e_secure;
+ // Save the global value before changing anything. This is needed as for
+ // a global-only option setting the "local value" in fact sets the global
+ // value (since there is only one value).
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ old_global_value = *(int *)get_varp_scope(&(options[opt_idx]),
+ OPT_GLOBAL);
+
*(int *)varp = value; /* set the new value */
#ifdef FEAT_EVAL
/* Remember where the option was set. */
@@ -8976,15 +9067,40 @@ set_bool_option(
// Don't do this while starting up or recursively.
if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
{
- char_u buf_old[2], buf_new[2], buf_type[7];
+ char_u buf_old[2], buf_old_global[2], buf_new[2], buf_type[7];
vim_snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE);
+ vim_snprintf((char *)buf_old_global, 2, "%d",
+ old_global_value ? TRUE: FALSE);
vim_snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE);
- vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
+ vim_snprintf((char *)buf_type, 7, "%s",
+ (opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- apply_autocmds(EVENT_OPTIONSET, (char_u *) options[opt_idx].fullname, NULL, FALSE, NULL);
+ if (opt_flags & OPT_LOCAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ if (opt_flags & OPT_GLOBAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+ }
+ if (opt_flags & OPT_MODELINE)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
+ NULL, FALSE, NULL);
reset_v_option_vars();
}
#endif
@@ -9014,8 +9130,10 @@ set_num_option(
{
char *errmsg = NULL;
long old_value = *(long *)varp;
- long old_Rows = Rows; /* remember old Rows */
- long old_Columns = Columns; /* remember old Columns */
+ long old_global_value = 0; // only used when setting a local and
+ // global option
+ long old_Rows = Rows; // remember old Rows
+ long old_Columns = Columns; // remember old Columns
long *pp = (long *)varp;
/* Disallow changing some options from secure mode. */
@@ -9026,6 +9144,12 @@ set_num_option(
) && (options[opt_idx].flags & P_SECURE))
return e_secure;
+ // Save the global value before changing anything. This is needed as for
+ // a global-only option setting the "local value" infact sets the global
+ // value (since there is only one value).
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+
*pp = value;
#ifdef FEAT_EVAL
/* Remember where the option was set. */
@@ -9533,15 +9657,37 @@ set_num_option(
// Don't do this while starting up, failure or recursively.
if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
{
- char_u buf_old[11], buf_new[11], buf_type[7];
-
+ char_u buf_old[11], buf_old_global[11], buf_new[11], buf_type[7];
vim_snprintf((char *)buf_old, 10, "%ld", old_value);
+ vim_snprintf((char *)buf_old_global, 10, "%ld", old_global_value);
vim_snprintf((char *)buf_new, 10, "%ld", value);
vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- apply_autocmds(EVENT_OPTIONSET, (char_u *) options[opt_idx].fullname, NULL, FALSE, NULL);
+ if (opt_flags & OPT_LOCAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ if (opt_flags & OPT_GLOBAL)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+ }
+ if (opt_flags & OPT_MODELINE)
+ {
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ }
+ apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
+ NULL, FALSE, NULL);
reset_v_option_vars();
}
#endif