]> granicus.if.org Git - vim/commitdiff
patch 9.0.1330: handling new value of an option has a long "else if" chain v9.0.1330
authorYegappan Lakshmanan <yegappan@yahoo.com>
Mon, 20 Feb 2023 12:16:39 +0000 (12:16 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 20 Feb 2023 12:16:39 +0000 (12:16 +0000)
Problem:    Handling new value of an option has a long "else if" chain.
Solution:   Use a function pointer. (Yegappan Lakshmanan, closes #12015)

37 files changed:
src/buffer.c
src/clipboard.c
src/evalfunc.c
src/ex_cmds.c
src/ex_docmd.c
src/ex_getln.c
src/gui_xim.c
src/hardcopy.c
src/if_mzsch.c
src/insexpand.c
src/map.c
src/ops.c
src/option.c
src/option.h
src/optiondefs.h
src/optionstr.c
src/proto/clipboard.pro
src/proto/ex_getln.pro
src/proto/gui_xim.pro
src/proto/hardcopy.pro
src/proto/if_mzsch.pro
src/proto/insexpand.pro
src/proto/map.pro
src/proto/ops.pro
src/proto/option.pro
src/proto/optionstr.pro
src/proto/quickfix.pro
src/proto/spell.pro
src/proto/tag.pro
src/quickfix.c
src/spell.c
src/spellfile.c
src/spellsuggest.c
src/structs.h
src/tag.c
src/version.c
src/vim.h

index 8fd81be869a417840292f1c115f1d3201acd24e7..cb7bdf445dee1cded42ef0b59153686b495d6877 100644 (file)
@@ -1971,7 +1971,7 @@ enter_buffer(buf_T *buf)
     // May need to set the spell language.  Can only do this after the buffer
     // has been properly setup.
     if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
-       (void)did_set_spelllang(curwin);
+       (void)parse_spelllang(curwin);
 #endif
 #ifdef FEAT_VIMINFO
     curbuf->b_last_used = vim_time();
index e140113ff7cfd5861c6eb9d55d0bc00f4d1ffd07..b09c678c22e12b60e40108a428ff588d23676f20 100644 (file)
@@ -1253,7 +1253,7 @@ clip_gen_owner_exists(Clipboard_T *cbd UNUSED)
  * Return an error message or NULL for success.
  */
     char *
-check_clipboard_option(void)
+did_set_clipboard(optset_T *args UNUSED)
 {
     int                new_unnamed = 0;
     int                new_autoselect_star = FALSE;
index 7f6cbac0411d04a8aee3622cf44d77c7cbf12542..cf30ed7623e5b784d21be6baaa301e809df9de3b 100644 (file)
@@ -9940,7 +9940,7 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
 
     if (!curwin->w_p_spell)
     {
-       did_set_spelllang(curwin);
+       parse_spelllang(curwin);
        curwin->w_p_spell = TRUE;
     }
 
@@ -10030,7 +10030,7 @@ f_spellsuggest(typval_T *argvars UNUSED, typval_T *rettv)
 
     if (!curwin->w_p_spell)
     {
-       did_set_spelllang(curwin);
+       parse_spelllang(curwin);
        curwin->w_p_spell = TRUE;
     }
 
index 7fd095268a4b55a02185cf8d5aa32ca247c88a90..0d8398062db7a0cb0481dec573a7c7ddd3880868 100644 (file)
@@ -3142,7 +3142,7 @@ do_ecmd(
     // If the window options were changed may need to set the spell language.
     // Can only do this after the buffer has been properly setup.
     if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
-       (void)did_set_spelllang(curwin);
+       (void)parse_spelllang(curwin);
 #endif
 
     if (command == NULL)
index e51f84997de27f9182b59b9dd093279f07fd8538..be0e3465d1b83bb268a188ee528d5feaa0e3093f 100644 (file)
@@ -1570,7 +1570,7 @@ getline_cookie(
 #endif
 }
 
-#if defined(FEAT_EVAL) || defined(PROT)
+#if defined(FEAT_EVAL) || defined(PROTO)
 /*
  * Get the next line source line without advancing.
  */
index b2bf4ed3296bea75bccc87b9a671b88556f11092..a938bd6b601e06a5cc6a407de796c91a6e4eb15f 100644 (file)
@@ -4366,7 +4366,7 @@ get_list_range(char_u **str, int *num1, int *num2)
  * Returns NULL if value is OK, error message otherwise.
  */
     char *
-check_cedit(void)
+did_set_cedit(optset_T *args UNUSED)
 {
     int n;
 
index 86273b5c3d4765a1cfbf914add48ac06386aa0d0..0d7b56e56bc0301e9b7d53622ce5d8cde4e7b58a 100644 (file)
 
 #include "vim.h"
 
+#if !defined(GTK_CHECK_VERSION)
+# define GTK_CHECK_VERSION(a, b, c) 0
+#endif
+#if !defined(FEAT_GUI_GTK) && defined(PROTO)
+typedef int GtkWidget;
+typedef int GtkIMContext;
+typedef int gchar;
+typedef int gpointer;
+typedef int PangoAttrIterator;
+typedef int GdkEventKey;
+#endif
+
 #if defined(FEAT_GUI_GTK) && defined(FEAT_XIM)
 # if GTK_CHECK_VERSION(3,0,0)
 #  include <gdk/gdkkeysyms-compat.h>
@@ -74,7 +86,7 @@ static callback_T imaf_cb;        // 'imactivatefunc' callback function
 static callback_T imsf_cb;         // 'imstatusfunc' callback function
 
     char *
-set_imactivatefunc_option(void)
+did_set_imactivatefunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(p_imaf, &imaf_cb) == FAIL)
        return e_invalid_argument;
@@ -83,7 +95,7 @@ set_imactivatefunc_option(void)
 }
 
     char *
-set_imstatusfunc_option(void)
+did_set_imstatusfunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(p_imsf, &imsf_cb) == FAIL)
        return e_invalid_argument;
index da3879b8c4ec694fb20e65440eb78c74880a0727..f6be017c33417f765b4e951bac3eb1a4debf4780 100644 (file)
@@ -144,7 +144,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
  * Returns an error message or NULL;
  */
     char *
-parse_printoptions(void)
+parse_printoptions(optset_T *args UNUSED)
 {
     return parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS);
 }
@@ -155,7 +155,7 @@ parse_printoptions(void)
  * Returns an error message or NULL;
  */
     char *
-parse_printmbfont(void)
+parse_printmbfont(optset_T *args UNUSED)
 {
     return parse_list_options(p_pmfn, mbfont_opts, OPT_MBFONT_NUM_OPTIONS);
 }
index 749223766631556a3c41cdbee85402c04aeea8a1..39d1530fe5539ad0e53864e2fbf7cd1b44a58874 100644 (file)
@@ -886,13 +886,15 @@ remove_timer(void)
     timer_id = 0;
 }
 
-    void
-mzvim_reset_timer(void)
+    char *
+did_set_mzquantum(void)
 {
+    // reset timer
     if (timer_id != 0)
        remove_timer();
     if (mz_threads_allow && p_mzq > 0 && gui.in_use)
        setup_timer();
+    return NULL;
 }
 
 #endif // MZSCHEME_GUI_THREADS
index a8d986a2cd0aa0b4efabd8ee74786b63f312acb3..779bf5eeb807430ea9305919d77ff1bb49ba6844 100644 (file)
@@ -2546,7 +2546,7 @@ copy_global_to_buflocal_cb(callback_T *globcb, callback_T *bufcb)
  * lambda expression.
  */
     char *
-set_completefunc_option(void)
+did_set_completefunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL)
        return e_invalid_argument;
@@ -2575,7 +2575,7 @@ set_buflocal_cfu_callback(buf_T *buf UNUSED)
  * lambda expression.
  */
     char *
-set_omnifunc_option(void)
+did_set_omnifunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(curbuf->b_p_ofu, &ofu_cb) == FAIL)
        return e_invalid_argument;
@@ -2603,7 +2603,7 @@ set_buflocal_ofu_callback(buf_T *buf UNUSED)
  * lambda expression.
  */
     char *
-set_thesaurusfunc_option(void)
+did_set_thesaurusfunc(optset_T *args UNUSED)
 {
     int        retval;
 
index 9a6cdb143cc2f96db8f6855b290e1a0918ec8aa9..92f76512abdd009c59a107bd90077ff98511addd 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -3034,8 +3034,8 @@ langmap_init(void)
  * Called when langmap option is set; the language map can be
  * changed at any time!
  */
-    void
-langmap_set(void)
+    char *
+did_set_langmap(optset_T *args UNUSED)
 {
     char_u  *p;
     char_u  *p2;
@@ -3088,9 +3088,11 @@ langmap_set(void)
            }
            if (to == NUL)
            {
+               // TODO: Need to use errbuf argument for this error message
+               // and return it.
                semsg(_(e_langmap_matching_character_missing_for_str),
                                                             transchar(from));
-               return;
+               return NULL;
            }
 
            if (from >= 256)
@@ -3110,8 +3112,10 @@ langmap_set(void)
                    {
                        if (p[0] != ',')
                        {
+                           // TODO: Need to use errbuf argument for this error
+                           // message and return it.
                            semsg(_(e_langmap_extra_characters_after_semicolon_str), p);
-                           return;
+                           return NULL;
                        }
                        ++p;
                    }
@@ -3120,6 +3124,8 @@ langmap_set(void)
            }
        }
     }
+
+    return NULL;
 }
 #endif
 
index 138edc73f5b9a657d6fcd899c61b2a9bb56e599f..01d2e95f85d250730f6e3d3697a1b4db24e6ce37 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -3406,7 +3406,7 @@ static callback_T opfunc_cb;
  * Returns OK or FAIL.
  */
     char *
-set_operatorfunc_option(void)
+did_set_operatorfunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL)
        return e_invalid_argument;
index 2332f2a38822c4db85d7c4601c8be9ce48654c21..d93d3859fb87239d05a7347f8b928771f1ce015f 100644 (file)
@@ -952,13 +952,13 @@ set_init_2(void)
 #endif
 
 #ifdef CURSOR_SHAPE
-    parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor'
+    parse_shape_opt(SHAPE_CURSOR);     // set cursor shapes from 'guicursor'
 #endif
 #ifdef FEAT_MOUSESHAPE
-    parse_shape_opt(SHAPE_MOUSE);  // set mouse shapes from 'mouseshape'
+    parse_shape_opt(SHAPE_MOUSE);      // set mouse shapes from 'mouseshape'
 #endif
 #ifdef FEAT_PRINTER
-    (void)parse_printoptions();            // parse 'printoptions' default value
+    (void)parse_printoptions(NULL);    // parse 'printoptions' default value
 #endif
 }
 
@@ -2032,7 +2032,7 @@ do_set_option_string(
        // options. Note: when setting 'syntax' or 'filetype' autocommands may
        // be triggered that can cause havoc.
        *errmsg = did_set_string_option(
-                       opt_idx, (char_u **)varp, oldval, errbuf,
+                       opt_idx, (char_u **)varp, oldval, newval, errbuf,
                        opt_flags, value_checked);
 
        secure = secure_saved;
@@ -2844,10 +2844,10 @@ didset_options(void)
     (void)did_set_spell_option(TRUE);
 #endif
     // set cedit_key
-    (void)check_cedit();
+    (void)did_set_cedit(NULL);
 #ifdef FEAT_LINEBREAK
     // initialize the table for 'breakat'.
-    fill_breakat_flags();
+    did_set_breakat(NULL);
 #endif
     after_copy_winopt(curwin);
 }
@@ -2872,7 +2872,7 @@ didset_options2(void)
 
 #ifdef FEAT_CLIPBOARD
     // Parse default for 'clipboard'
-    (void)check_clipboard_option();
+    (void)did_set_clipboard(NULL);
 #endif
 #ifdef FEAT_VARTABS
     vim_free(curbuf->b_p_vsts_array);
@@ -3140,44 +3140,47 @@ apply_optionset_autocmd(
 /*
  * Process the updated 'compatible' option value.
  */
-    static void
-did_set_compatible(void)
+    char *
+did_set_compatible(optset_T *args UNUSED)
 {
     compatible_set();
+    return NULL;
 }
 
-#ifdef FEAT_LANGMAP
+#if defined(FEAT_LANGMAP) || defined(PROTO)
 /*
  * Process the updated 'langremap' option value.
  */
-    static void
-did_set_langremap(void)
+    char *
+did_set_langremap(optset_T *args UNUSED)
 {
     // 'langremap' -> !'langnoremap'
     p_lnr = !p_lrm;
+    return NULL;
 }
 
 /*
  * Process the updated 'langnoremap' option value.
  */
-    static void
-did_set_langnoremap(void)
+    char *
+did_set_langnoremap(optset_T *args UNUSED)
 {
     // 'langnoremap' -> !'langremap'
     p_lrm = !p_lnr;
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_PERSISTENT_UNDO
+#if defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
 /*
  * Process the updated 'undofile' option value.
  */
-    static void
-did_set_undofile(int opt_flags)
+    char *
+did_set_undofile(optset_T *args)
 {
     // Only take action when the option was set.
     if (!curbuf->b_p_udf && !p_udf)
-       return;
+       return NULL;
 
     // When reset we do not delete the undo file, the option may be set again
     // without making any changes in between.
@@ -3191,7 +3194,8 @@ did_set_undofile(int opt_flags)
        // if one exists, the buffer wasn't changed and the buffer was
        // loaded
        if ((curbuf == save_curbuf
-                   || (opt_flags & OPT_GLOBAL) || opt_flags == 0)
+                   || (args->os_flags & OPT_GLOBAL)
+                   || args->os_flags == 0)
                && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL)
        {
 #ifdef FEAT_CRYPT
@@ -3203,17 +3207,19 @@ did_set_undofile(int opt_flags)
        }
     }
     curbuf = save_curbuf;
+
+    return NULL;
 }
 #endif
 
 /*
  * Process the updated 'readonly' option value.
  */
-    static void
-did_set_readonly(int opt_flags)
+    char *
+did_set_readonly(optset_T *args)
 {
     // when 'readonly' is reset globally, also reset readonlymode
-    if (!curbuf->b_p_ro && (opt_flags & OPT_LOCAL) == 0)
+    if (!curbuf->b_p_ro && (args->os_flags & OPT_LOCAL) == 0)
        readonlymode = FALSE;
 
     // when 'readonly' is set may give W10 again
@@ -3221,25 +3227,28 @@ did_set_readonly(int opt_flags)
        curbuf->b_did_warn = FALSE;
 
     redraw_titles();
+
+    return NULL;
 }
 
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI) || defined(PROTO)
 /*
  * Process the updated 'mousehide' option value.
  */
-    static void
-did_set_mousehide(void)
+    char *
+did_set_mousehide(optset_T *args UNUSED)
 {
     if (!p_mh)
        gui_mch_mousehide(FALSE);
+    return NULL;
 }
 #endif
 
 /*
  * Process the updated 'modifiable' option value.
  */
-    static char *
-did_set_modifiable(int *doskip UNUSED)
+    char *
+did_set_modifiable(optset_T *args UNUSED)
 {
     // when 'modifiable' is changed, redraw the window title
 
@@ -3249,7 +3258,7 @@ did_set_modifiable(int *doskip UNUSED)
                    && curbuf->b_term != NULL && !term_is_finished(curbuf))))
     {
        curbuf->b_p_ma = FALSE;
-       *doskip = TRUE;
+       args->os_doskip = TRUE;
        return e_cannot_make_terminal_with_running_job_modifiable;
     }
 # endif
@@ -3262,41 +3271,45 @@ did_set_modifiable(int *doskip UNUSED)
  * Process the updated 'endoffile' or 'endofline' or 'fixendofline' or 'bomb'
  * option value.
  */
-    static void
-did_set_eof_eol_fixeol_bomb(void)
+    char *
+did_set_eof_eol_fixeol_bomb(optset_T *args UNUSED)
 {
     // redraw the window title and tab page text
     redraw_titles();
+    return NULL;
 }
 
 /*
  * Process the updated 'binary' option value.
  */
-    static void
-did_set_binary(int opt_flags, long old_value)
+    char *
+did_set_binary(optset_T *args)
 {
     // when 'bin' is set also set some other options
-    set_options_bin(old_value, curbuf->b_p_bin, opt_flags);
+    set_options_bin(args->os_oldval.boolean, curbuf->b_p_bin, args->os_flags);
     redraw_titles();
+
+    return NULL;
 }
 
 /*
  * Process the updated 'buflisted' option value.
  */
-    static void
-did_set_buflisted(long old_value)
+    char *
+did_set_buflisted(optset_T *args)
 {
     // when 'buflisted' changes, trigger autocommands
-    if (old_value != curbuf->b_p_bl)
+    if (args->os_oldval.boolean != curbuf->b_p_bl)
        apply_autocmds(curbuf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
                                                NULL, NULL, TRUE, curbuf);
+    return NULL;
 }
 
 /*
  * Process the updated 'swapfile' option value.
  */
-    static void
-did_set_swapfile(void)
+    char *
+did_set_swapfile(optset_T *args UNUSED)
 {
     // when 'swf' is set, create swapfile, when reset remove swapfile
     if (curbuf->b_p_swf && p_uc)
@@ -3305,13 +3318,14 @@ did_set_swapfile(void)
        // no need to reset curbuf->b_may_swap, ml_open_file() will check
        // buf->b_p_swf
        mf_close_file(curbuf, TRUE);    // remove the swap file
+    return NULL;
 }
 
 /*
  * Process the updated 'terse' option value.
  */
-    static void
-did_set_terse(void)
+    char *
+did_set_terse(optset_T *args UNUSED)
 {
     char_u     *p;
 
@@ -3328,23 +3342,25 @@ did_set_terse(void)
     // remove 's' from p_shm
     else if (!p_terse && p != NULL)
        STRMOVE(p, p + 1);
+    return NULL;
 }
 
 /*
  * Process the updated 'paste' option value.
  */
-    static void
-did_set_paste(void)
+    char *
+did_set_paste(optset_T *args UNUSED)
 {
     // when 'paste' is set or reset also change other options
     paste_option_changed();
+    return NULL;
 }
 
 /*
  * Process the updated 'insertmode' option value.
  */
-    static void
-did_set_insertmode(long old_value)
+    char *
+did_set_insertmode(optset_T *args)
 {
     // when 'insertmode' is set from an autocommand need to do work here
     if (p_im)
@@ -3354,7 +3370,7 @@ did_set_insertmode(long old_value)
        stop_insert_mode = FALSE;
     }
     // only reset if it was set previously
-    else if (old_value)
+    else if (args->os_oldval.boolean)
     {
        need_start_insertmode = FALSE;
        stop_insert_mode = TRUE;
@@ -3362,51 +3378,57 @@ did_set_insertmode(long old_value)
            clear_cmdline = TRUE;       // remove "(insert)"
        restart_edit = 0;
     }
+
+    return NULL;
 }
 
 /*
  * Process the updated 'ignorecase' option value.
  */
-    static void
-did_set_ignorecase(void)
+    char *
+did_set_ignorecase(optset_T *args UNUSED)
 {
     // when 'ignorecase' is set or reset and 'hlsearch' is set, redraw
     if (p_hls)
        redraw_all_later(UPD_SOME_VALID);
+    return NULL;
 }
 
-#ifdef FEAT_SEARCH_EXTRA
+#if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
 /*
  * Process the updated 'hlsearch' option value.
  */
-    static void
-did_set_hlsearch(void)
+    char *
+did_set_hlsearch(optset_T *args UNUSED)
 {
     // when 'hlsearch' is set or reset: reset no_hlsearch
     set_no_hlsearch(FALSE);
+    return NULL;
 }
 #endif
 
 /*
  * Process the updated 'scrollbind' option value.
  */
-    static void
-did_set_scrollbind(void)
+    char *
+did_set_scrollbind(optset_T *args UNUSED)
 {
     // when 'scrollbind' is set: snapshot the current position to avoid a jump
     // at the end of normal_cmd()
     if (!curwin->w_p_scb)
-       return;
+       return NULL;
+
     do_check_scrollbind(FALSE);
     curwin->w_scbind_pos = curwin->w_topline;
+    return NULL;
 }
 
 #ifdef FEAT_QUICKFIX
 /*
  * Process the updated 'previewwindow' option value.
  */
-    static char *
-did_set_previewwindow(int *doskip)
+    char *
+did_set_previewwindow(optset_T *args)
 {
     if (!curwin->w_p_pvw)
        return NULL;
@@ -3418,7 +3440,7 @@ did_set_previewwindow(int *doskip)
        if (win->w_p_pvw && win != curwin)
        {
            curwin->w_p_pvw = FALSE;
-           *doskip = TRUE;
+           args->os_doskip = TRUE;
            return e_preview_window_already_exists;
        }
 
@@ -3429,75 +3451,84 @@ did_set_previewwindow(int *doskip)
 /*
  * Process the updated 'smoothscroll' option value.
  */
-    static void
-did_set_smoothscroll(void)
+    char *
+did_set_smoothscroll(optset_T *args UNUSED)
 {
     if (curwin->w_p_sms)
-       return;
+       return NULL;
+
     curwin->w_skipcol = 0;
     changed_line_abv_curs();
+    return NULL;
 }
 
 /*
  * Process the updated 'textmode' option value.
  */
-    static void
-did_set_textmode(int opt_flags)
+    char *
+did_set_textmode(optset_T *args)
 {
     // when 'textmode' is set or reset also change 'fileformat'
-    set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, opt_flags);
+    set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, args->os_flags);
+
+    return NULL;
 }
 
 /*
  * Process the updated 'textauto' option value.
  */
-    static void
-did_set_textauto(int opt_flags)
+    char *
+did_set_textauto(optset_T *args)
 {
     // when 'textauto' is set or reset also change 'fileformats'
     set_string_option_direct((char_u *)"ffs", -1,
                                p_ta ? (char_u *)DFLT_FFS_VIM : (char_u *)"",
-                               OPT_FREE | opt_flags, 0);
+                               OPT_FREE | args->os_flags, 0);
+
+    return NULL;
 }
 
 /*
  * Process the updated 'lisp' option value.
  */
-    static void
-did_set_lisp(void)
+    char *
+did_set_lisp(optset_T *args UNUSED)
 {
     // When 'lisp' option changes include/exclude '-' in keyword characters.
     (void)buf_init_chartab(curbuf, FALSE);         // ignore errors
+    return NULL;
 }
 
 /*
  * Process the updated 'title' or the 'icon' option value.
  */
-    static void
-did_set_title_icon(void)
+    char *
+did_set_title_icon(optset_T *args UNUSED)
 {
     // when 'title' changed, may need to change the title; same for 'icon'
     did_set_title();
+    return NULL;
 }
 
 /*
  * Process the updated 'modified' option value.
  */
-    static void
-did_set_modified(long value)
+    char *
+did_set_modified(optset_T *args)
 {
-    if (!value)
+    if (!args->os_newval.boolean)
        save_file_ff(curbuf);   // Buffer is unchanged
     redraw_titles();
-    modified_was_set = value;
+    modified_was_set = args->os_newval.boolean;
+    return NULL;
 }
 
-#ifdef BACKSLASH_IN_FILENAME
+#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
 /*
  * Process the updated 'shellslash' option value.
  */
-    static void
-did_set_shellslash(void)
+    char *
+did_set_shellslash(optset_T *args UNUSED)
 {
     if (p_ssl)
     {
@@ -3518,90 +3549,101 @@ did_set_shellslash(void)
 # ifdef FEAT_EVAL
     scriptnames_slash_adjust();
 # endif
+    return NULL;
 }
 #endif
 
 /*
  * Process the updated 'wrap' option value.
  */
-    static void
-did_set_wrap(void)
+    char *
+did_set_wrap(optset_T *args UNUSED)
 {
     // If 'wrap' is set, set w_leftcol to zero.
     if (curwin->w_p_wrap)
        curwin->w_leftcol = 0;
+    return NULL;
 }
 
 /*
  * Process the updated 'equalalways' option value.
  */
-    static void
-did_set_equalalways(long old_value)
+    char *
+did_set_equalalways(optset_T *args)
 {
-    if (p_ea && !old_value)
+    if (p_ea && !args->os_oldval.boolean)
        win_equal(curwin, FALSE, 0);
+
+    return NULL;
 }
 
 /*
  * Process the updated 'weirdinvert' option value.
  */
-    static void
-did_set_weirdinvert(long old_value)
+    char *
+did_set_weirdinvert(optset_T *args)
 {
     // When 'weirdinvert' changed, set/reset 't_xs'.
     // Then set 'weirdinvert' according to value of 't_xs'.
-    if (p_wiv && !old_value)
+    if (p_wiv && !args->os_oldval.boolean)
        T_XS = (char_u *)"y";
-    else if (!p_wiv && old_value)
+    else if (!p_wiv && args->os_oldval.boolean)
        T_XS = empty_option;
     p_wiv = (*T_XS != NUL);
+
+    return NULL;
 }
 
-#ifdef FEAT_BEVAL_GUI
+#if defined(FEAT_BEVAL_GUI) || defined(PROTO)
 /*
  * Process the updated 'ballooneval' option value.
  */
-    static void
-did_set_ballooneval(long old_value)
+    char *
+did_set_ballooneval(optset_T *args)
 {
     if (balloonEvalForTerm)
-       return;
-    if (p_beval && !old_value)
+       return NULL;
+
+    if (p_beval && !args->os_oldval.boolean)
        gui_mch_enable_beval_area(balloonEval);
-    else if (!p_beval && old_value)
+    else if (!p_beval && args->os_oldval.boolean)
        gui_mch_disable_beval_area(balloonEval);
+
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_BEVAL_TERM
+#if defined(FEAT_BEVAL_TERM) || defined(PROTO)
 /*
  * Process the updated 'balloonevalterm' option value.
  */
-    static void
-did_set_balloonevalterm(void)
+    char *
+did_set_balloonevalterm(optset_T *args UNUSED)
 {
     mch_bevalterm_changed();
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_AUTOCHDIR
+#if defined(FEAT_AUTOCHDIR) || defined(PROTO)
 /*
  * Process the updated 'autochdir' option value.
  */
-    static void
-did_set_autochdir(void)
+    char *
+did_set_autochdir(optset_T *args UNUSED)
 {
     // Change directories when the 'acd' option is set now.
     DO_AUTOCHDIR;
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_DIFF
+#if defined(FEAT_DIFF) || defined(PROTO)
 /*
  * Process the updated 'diff' option value.
  */
-    static void
-did_set_diff(void)
+    char *
+did_set_diff(optset_T *args UNUSED)
 {
     // May add or remove the buffer from the list of diff buffers.
     diff_buf_adjust(curwin);
@@ -3609,15 +3651,16 @@ did_set_diff(void)
     if (foldmethodIsDiff(curwin))
        foldUpdateAll(curwin);
 # endif
+    return NULL;
 }
 #endif
 
-#ifdef HAVE_INPUT_METHOD
+#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
 /*
  * Process the updated 'imdisable' option value.
  */
-    static void
-did_set_imdisable(void)
+    char *
+did_set_imdisable(optset_T *args UNUSED)
 {
     // Only de-activate it here, it will be enabled when changing mode.
     if (p_imdisable)
@@ -3626,29 +3669,30 @@ did_set_imdisable(void)
        // When the option is set from an autocommand, it may need to take
        // effect right away.
        im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_SPELL
+#if defined(FEAT_SPELL) || defined(PROTO)
 /*
  * Process the updated 'spell' option value.
  */
-    static char *
-did_set_spell(void)
+    char *
+did_set_spell(optset_T *args UNUSED)
 {
     if (curwin->w_p_spell)
-       return did_set_spelllang(curwin);
+       return parse_spelllang(curwin);
 
     return NULL;
 }
 #endif
 
-#ifdef FEAT_ARABIC
+#if defined(FEAT_ARABIC) || defined(PROTO)
 /*
  * Process the updated 'arabic' option value.
  */
-    static char *
-did_set_arabic(void)
+    char *
+did_set_arabic(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -3728,13 +3772,13 @@ did_set_arabic(void)
 }
 #endif
 
-#if defined(FEAT_SIGNS) && defined(FEAT_GUI)
 /*
  * Process the updated 'number' or 'relativenumber' option value.
  */
-    static void
-did_set_number_relativenumber(char_u *varp)
+    char *
+did_set_number_relativenumber(optset_T *args UNUSED)
 {
+#if (defined(FEAT_SIGNS) && defined(FEAT_GUI)) || defined(PROTO)
     if (gui.in_use
            && (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u')
            && curbuf->b_signlist != NULL)
@@ -3745,15 +3789,16 @@ did_set_number_relativenumber(char_u *varp)
        // number column.  If the 'number' option is set and only the
        // 'relativenumber' option is toggled, then don't refresh the screen
        // (optimization).
-       if (!(curwin->w_p_nu && ((int *)varp == &curwin->w_p_rnu)))
+       if (!(curwin->w_p_nu && ((int *)args->os_varp == &curwin->w_p_rnu)))
            redraw_all_later(UPD_CLEAR);
     }
-}
 #endif
+    return NULL;
+}
 
 #ifdef FEAT_TERMGUICOLORS
-    static char *
-did_set_termguicolors(int *doskip UNUSED)
+    char *
+did_set_termguicolors(optset_T *args UNUSED)
 {
 # ifdef FEAT_VTP
     // Do not turn on 'tgc' when 24-bit colors are not supported.
@@ -3764,7 +3809,7 @@ did_set_termguicolors(int *doskip UNUSED)
            !has_vtp_working())
     {
        p_tgc = 0;
-       *doskip = TRUE;
+       args->os_doskip = TRUE;
        return e_24_bit_colors_are_not_supported_on_this_environment;
     }
     if (is_term_win32())
@@ -3793,133 +3838,6 @@ did_set_termguicolors(int *doskip UNUSED)
 }
 #endif
 
-/*
- * When some boolean options are changed, need to take some action.
- */
-    static char *
-did_set_bool_option(
-    char_u     *varp,
-    int                opt_flags,
-    long       value,
-    long       old_value,
-    int                *doskip)
-{
-    char *errmsg = NULL;
-
-    if ((int *)varp == &p_cp)                  // 'compatible'
-       did_set_compatible();
-#ifdef FEAT_LANGMAP
-    else if ((int *)varp == &p_lrm)            // 'langremap'
-       did_set_langremap();
-    else if ((int *)varp == &p_lnr)            // 'langnoremap'
-       did_set_langnoremap();
-#endif
-#ifdef FEAT_PERSISTENT_UNDO
-    else if ((int *)varp == &curbuf->b_p_udf   // buffer local 'undofile'
-           || (int *)varp == &p_udf)           // 'undofile'
-       did_set_undofile(opt_flags);
-#endif
-    else if ((int *)varp == &curbuf->b_p_ro)   // 'readonly'
-       did_set_readonly(opt_flags);
-#ifdef FEAT_GUI
-    else if ((int *)varp == &p_mh)             // 'mousehide'
-       did_set_mousehide();
-#endif
-    else if ((int *)varp == &curbuf->b_p_ma)
-       errmsg = did_set_modifiable(doskip);    // 'modifiable'
-    else if ((int *)varp == &curbuf->b_p_eof   // 'endoffile'
-           || (int *)varp == &curbuf->b_p_eol  // 'endofline'
-           || (int *)varp == &curbuf->b_p_fixeol       // 'fixendofline'
-           || (int *)varp == &curbuf->b_p_bomb)        // 'bomb'
-       did_set_eof_eol_fixeol_bomb();
-    else if ((int *)varp == &curbuf->b_p_bin)  // 'binary'
-       did_set_binary(opt_flags, old_value);
-    else if ((int *)varp == &curbuf->b_p_bl)   // 'buflisted'
-       did_set_buflisted(old_value);
-    else if ((int *)varp == &curbuf->b_p_swf)  // 'swapfile'
-       did_set_swapfile();
-    else if ((int *)varp == &p_terse)          // 'terse'
-       did_set_terse();
-    else if ((int *)varp == &p_paste)          // 'paste'
-       did_set_paste();
-    else if ((int *)varp == &p_im)             // 'insertmode'
-       did_set_insertmode(old_value);
-    else if ((int *)varp == &p_ic)             // 'ignorecase'
-       did_set_ignorecase();
-#ifdef FEAT_SEARCH_EXTRA
-    else if ((int *)varp == &p_hls)            // 'hlsearch'
-       did_set_hlsearch();
-#endif
-    else if ((int *)varp == &curwin->w_p_scb)  // 'scrollbind'
-       did_set_scrollbind();
-#ifdef FEAT_QUICKFIX
-    else if ((int *)varp == &curwin->w_p_pvw)  // 'previewwindow'
-       errmsg = did_set_previewwindow(doskip);
-#endif
-    else if ((int *)varp == &curwin->w_p_sms)  // 'smoothscroll'
-       did_set_smoothscroll();
-    else if ((int *)varp == &curbuf->b_p_tx)   // 'textmode'
-       did_set_textmode(opt_flags);
-    else if ((int *)varp == &p_ta)             // 'textauto'
-       did_set_textauto(opt_flags);
-    else if (varp == (char_u *)&(curbuf->b_p_lisp))    // 'lisp'
-       did_set_lisp();
-    else if (  (int *)varp == &p_title         // 'title'
-           || (int *)varp == &p_icon)          // 'icon'
-       did_set_title_icon();
-    else if ((int *)varp == &curbuf->b_changed)        // 'modified'
-       did_set_modified(value);
-#ifdef BACKSLASH_IN_FILENAME
-    else if ((int *)varp == &p_ssl)            // 'shellslash'
-       did_set_shellslash();
-#endif
-    else if ((int *)varp == &curwin->w_p_wrap) // 'wrap'
-       did_set_wrap();
-    else if ((int *)varp == &p_ea)             // 'equalalways'
-       did_set_equalalways(old_value);
-    else if ((int *)varp == &p_wiv)            // weirdinvert'
-       did_set_weirdinvert(old_value);
-#ifdef FEAT_BEVAL_GUI
-    else if ((int *)varp == &p_beval)          // 'ballooneval'
-       did_set_ballooneval(old_value);
-#endif
-#ifdef FEAT_BEVAL_TERM
-    else if ((int *)varp == &p_bevalterm)      // 'balloonevalterm'
-       did_set_balloonevalterm();
-#endif
-#ifdef FEAT_AUTOCHDIR
-    else if ((int *)varp == &p_acd)            // 'autochdir'
-       did_set_autochdir();
-#endif
-#ifdef FEAT_DIFF
-    else if ((int *)varp == &curwin->w_p_diff) // 'diff'
-       did_set_diff();
-#endif
-#ifdef HAVE_INPUT_METHOD
-    else if ((int *)varp == &p_imdisable)      // 'imdisable'
-       did_set_imdisable();
-#endif
-#ifdef FEAT_SPELL
-    else if ((int *)varp == &curwin->w_p_spell)        // 'spell'
-       errmsg = did_set_spell();
-#endif
-#ifdef FEAT_ARABIC
-    else if ((int *)varp == &curwin->w_p_arab) // 'arabic'
-       errmsg = did_set_arabic();
-#endif
-#if defined(FEAT_SIGNS) && defined(FEAT_GUI)
-    else if (  (int *)varp == &curwin->w_p_nu  // 'number'
-           || (int *)varp == &curwin->w_p_rnu) // 'relativenumber'
-       did_set_number_relativenumber(varp);
-#endif
-#ifdef FEAT_TERMGUICOLORS
-    else if ((int *)varp == &p_tgc)            // 'termguicolors'
-       errmsg = did_set_termguicolors(doskip);
-#endif
-
-    return errmsg;
-}
-
 /*
  * Set the value of a boolean option, and take care of side effects.
  * Returns NULL for success, or an error message for an error.
@@ -3971,10 +3889,19 @@ set_bool_option(
     /*
      * Handle side effects of changing a bool option.
      */
-    int doskip = FALSE;
-    errmsg = did_set_bool_option(varp, opt_flags, value, old_value, &doskip);
-    if (doskip)
-       return errmsg;
+    if (options[opt_idx].opt_did_set_cb != NULL)
+    {
+       optset_T args;
+
+       args.os_varp = varp;
+       args.os_flags = opt_flags;
+       args.os_oldval.boolean = old_value;
+       args.os_newval.boolean = value;
+       args.os_doskip = FALSE;
+       errmsg = options[opt_idx].opt_did_set_cb(&args);
+       if (args.os_doskip)
+           return errmsg;
+    }
 
     // after handling side effects, call autocommand
 
@@ -4001,9 +3928,12 @@ set_bool_option(
 /*
  * Process the new 'winheight' or the 'helpheight' option value.
  */
-    static char *
-did_set_winheight_helpheight(long *pp, char *errmsg)
+    char *
+did_set_winheight_helpheight(optset_T *args)
 {
+    long       *pp = (long *)args->os_varp;
+    char       *errmsg = NULL;
+
     if (p_wh < 1)
     {
        errmsg = e_argument_must_be_positive;
@@ -4035,9 +3965,11 @@ did_set_winheight_helpheight(long *pp, char *errmsg)
 /*
  * Process the new 'winminheight' option value.
  */
-    static char *
-did_set_winminheight(char *errmsg)
+    char *
+did_set_winminheight(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (p_wmh < 0)
     {
        errmsg = e_argument_must_be_positive;
@@ -4056,9 +3988,11 @@ did_set_winminheight(char *errmsg)
 /*
  * Process the new 'winwidth' option value.
  */
-    static char *
-did_set_winwidth(char *errmsg)
+    char *
+did_set_winwidth(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (p_wiw < 1)
     {
        errmsg = e_argument_must_be_positive;
@@ -4080,9 +4014,11 @@ did_set_winwidth(char *errmsg)
 /*
  * Process the new 'winminwidth' option value.
  */
-    static char *
-did_set_winminwidth(char *errmsg)
+    char *
+did_set_winminwidth(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (p_wmw < 0)
     {
        errmsg = e_argument_must_be_positive;
@@ -4101,72 +4037,80 @@ did_set_winminwidth(char *errmsg)
 /*
  * Process the new 'laststatus' option value.
  */
-    static void
-did_set_laststatus(void)
+    char *
+did_set_laststatus(optset_T *args UNUSED)
 {
     last_status(FALSE);        // (re)set last window status line
+    return NULL;
 }
 
 /*
  * Process the new 'showtabline' option value.
  */
-    static void
-did_set_showtabline(void)
+    char *
+did_set_showtabline(optset_T *args UNUSED)
 {
     shell_new_rows();  // recompute window positions and heights
+    return NULL;
 }
 
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI) || defined(PROTO)
 /*
  * Process the new 'linespace' option value.
  */
-    static void
-did_set_linespace(void)
+    char *
+did_set_linespace(optset_T *args UNUSED)
 {
     // Recompute gui.char_height and resize the Vim window to keep the
     // same number of lines.
     if (gui.in_use && gui_mch_adjust_charheight() == OK)
        gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_FOLDING
+#if defined(FEAT_FOLDING) || defined(PROTO)
 /*
  * Process the new 'foldlevel' option value.
  */
-    static void
-did_set_foldlevel(void)
+    char *
+did_set_foldlevel(optset_T *args UNUSED)
 {
     if (curwin->w_p_fdl < 0)
        curwin->w_p_fdl = 0;
     newFoldLevel();
+    return NULL;
 }
 
 /*
  * Process the new 'foldminlines' option value.
  */
-    static void
-did_set_foldminlines(void)
+    char *
+did_set_foldminlines(optset_T *args UNUSED)
 {
     foldUpdateAll(curwin);
+    return NULL;
 }
 
 /*
  * Process the new 'foldnestmax' option value.
  */
-    static void
-did_set_foldnestmax(void)
+    char *
+did_set_foldnestmax(optset_T *args UNUSED)
 {
     if (foldmethodIsSyntax(curwin) || foldmethodIsIndent(curwin))
        foldUpdateAll(curwin);
+    return NULL;
 }
 
 /*
  * Process the new 'foldcolumn' option value.
  */
-    static char *
-did_set_foldcolumn(char *errmsg)
+    char *
+did_set_foldcolumn(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (curwin->w_p_fdc < 0)
     {
        errmsg = e_argument_must_be_positive;
@@ -4185,9 +4129,25 @@ did_set_foldcolumn(char *errmsg)
 /*
  * Process the new 'shiftwidth' or the 'tabstop' option value.
  */
-    static void
-did_set_shiftwidth_tabstop(long *pp)
+    char *
+did_set_shiftwidth_tabstop(optset_T *args)
 {
+    long       *pp = (long *)args->os_varp;
+    char       *errmsg = NULL;
+
+    if (curbuf->b_p_sw < 0)
+    {
+       errmsg = e_argument_must_be_positive;
+#ifdef FEAT_VARTABS
+       // Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use.
+       curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0
+                      ? tabstop_first(curbuf->b_p_vts_array)
+                      : curbuf->b_p_ts;
+#else
+       curbuf->b_p_sw = curbuf->b_p_ts;
+#endif
+    }
+
 #ifdef FEAT_FOLDING
     if (foldmethodIsIndent(curwin))
        foldUpdateAll(curwin);
@@ -4196,27 +4156,32 @@ did_set_shiftwidth_tabstop(long *pp)
     // parse 'cinoptions'.
     if (pp == &curbuf->b_p_sw || curbuf->b_p_sw == 0)
        parse_cino(curbuf);
+
+    return errmsg;
 }
 
 /*
  * Process the new 'maxcombine' option value.
  */
-    static void
-did_set_maxcombine(void)
+    char *
+did_set_maxcombine(optset_T *args UNUSED)
 {
     if (p_mco > MAX_MCO)
        p_mco = MAX_MCO;
     else if (p_mco < 0)
        p_mco = 0;
     screenclear();         // will re-allocate the screen
+    return NULL;
 }
 
 /*
  * Process the new 'iminsert' option value.
  */
-    static char *
-did_set_iminsert(char *errmsg)
+    char *
+did_set_iminsert(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (curbuf->b_p_iminsert < 0 || curbuf->b_p_iminsert > B_IMODE_LAST)
     {
        errmsg = e_invalid_argument;
@@ -4233,13 +4198,15 @@ did_set_iminsert(char *errmsg)
     return errmsg;
 }
 
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) || defined(PROTO)
 /*
  * Process the new 'imstyle' option value.
  */
-    static char *
-did_set_imstyle(char *errmsg)
+    char *
+did_set_imstyle(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (p_imst != IM_ON_THE_SPOT && p_imst != IM_OVER_THE_SPOT)
        errmsg = e_invalid_argument;
 
@@ -4250,21 +4217,24 @@ did_set_imstyle(char *errmsg)
 /*
  * Process the new 'window' option value.
  */
-    static void
-did_set_window(void)
+    char *
+did_set_window(optset_T *args UNUSED)
 {
     if (p_window < 1)
        p_window = 1;
     else if (p_window >= Rows)
        p_window = Rows - 1;
+    return NULL;
 }
 
 /*
  * Process the new 'imsearch' option value.
  */
-    static char *
-did_set_imsearch(char *errmsg)
+    char *
+did_set_imsearch(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (curbuf->b_p_imsearch < -1 || curbuf->b_p_imsearch > B_IMODE_LAST)
     {
        errmsg = e_invalid_argument;
@@ -4278,9 +4248,12 @@ did_set_imsearch(char *errmsg)
 /*
  * Process the new 'titlelen' option value.
  */
-    static char *
-did_set_titlelen(long old_value, char *errmsg)
+    char *
+did_set_titlelen(optset_T *args)
 {
+    long old_value = args->os_oldval.number;
+    char *errmsg = NULL;
+
     // if 'titlelen' has changed, redraw the title
     if (p_titlelen < 0)
     {
@@ -4296,9 +4269,12 @@ did_set_titlelen(long old_value, char *errmsg)
 /*
  * Process the new 'cmdheight' option value.
  */
-    static char *
-did_set_cmdheight(long old_value, char *errmsg)
+    char *
+did_set_cmdheight(optset_T *args)
 {
+    long old_value = args->os_oldval.number;
+    char *errmsg = NULL;
+
     // if p_ch changed value, change the command line height
     if (p_ch < 1)
     {
@@ -4325,9 +4301,12 @@ did_set_cmdheight(long old_value, char *errmsg)
 /*
  * Process the new 'updatecount' option value.
  */
-    static char *
-did_set_updatecount(long old_value, char *errmsg)
+    char *
+did_set_updatecount(optset_T *args)
 {
+    long old_value = args->os_oldval.number;
+    char *errmsg = NULL;
+
     // when 'updatecount' changes from zero to non-zero, open swap files
     if (p_uc < 0)
     {
@@ -4340,13 +4319,15 @@ did_set_updatecount(long old_value, char *errmsg)
     return errmsg;
 }
 
-#ifdef FEAT_CONCEAL
+#if defined(FEAT_CONCEAL) || defined(PROTO)
 /*
  * Process the new 'conceallevel' option value.
  */
-    static char *
-did_set_conceallevel(char *errmsg)
+    char *
+did_set_conceallevel(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (curwin->w_p_cole < 0)
     {
        errmsg = e_argument_must_be_positive;
@@ -4362,13 +4343,15 @@ did_set_conceallevel(char *errmsg)
 }
 #endif
 
-#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
+#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
 /*
  * Process the new 'pyxversion' option value.
  */
-    static char *
-did_set_pyxversion(char *errmsg)
+    char *
+did_set_pyxversion(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3)
        errmsg = e_invalid_argument;
 
@@ -4402,13 +4385,15 @@ did_set_buflocal_undolevels(long value, long old_value)
     curbuf->b_p_ul = value;
 }
 
-#ifdef FEAT_LINEBREAK
+#if defined(FEAT_LINEBREAK) || defined(PROTO)
 /*
  * Process the new 'numberwidth' option value.
  */
-    static char *
-did_set_numberwidth(char *errmsg)
+    char *
+did_set_numberwidth(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     // 'numberwidth' must be positive
     if (curwin->w_p_nuw < 1)
     {
@@ -4429,9 +4414,11 @@ did_set_numberwidth(char *errmsg)
 /*
  * Process the new 'textwidth' option value.
  */
-    static char *
-did_set_textwidth(char *errmsg)
+    char *
+did_set_textwidth(optset_T *args UNUSED)
 {
+    char *errmsg = NULL;
+
     if (curbuf->b_p_tw < 0)
     {
        errmsg = e_argument_must_be_positive;
@@ -4451,83 +4438,21 @@ did_set_textwidth(char *errmsg)
 }
 
 /*
- * When some number options are changed, need to take some action.
+ * Process the new 'undolevels' option value.
  */
-    static char *
-did_set_num_option(long *pp, long value, long old_value, char *errmsg)
-{
-    if (pp == &p_wh                            // 'winheight'
-           || pp == &p_hh)                     // 'helpheight'
-       errmsg = did_set_winheight_helpheight(pp, errmsg);
-    else if (pp == &p_wmh)                     // 'winminheight'
-       errmsg = did_set_winminheight(errmsg);
-    else if (pp == &p_wiw)                     // 'winwidth'
-       errmsg = did_set_winwidth(errmsg);
-    else if (pp == &p_wmw)                     // 'winminwidth'
-       errmsg = did_set_winminwidth(errmsg);
-    else if (pp == &p_ls)
-       did_set_laststatus();                   // 'laststatus'
-    else if (pp == &p_stal)
-       did_set_showtabline();                  // 'showtabline'
-#ifdef FEAT_GUI
-    else if (pp == &p_linespace)               // 'linespace'
-       did_set_linespace();
-#endif
-#ifdef FEAT_FOLDING
-    else if (pp == &curwin->w_p_fdl)           // 'foldlevel'
-       did_set_foldlevel();
-    else if (pp == &curwin->w_p_fml)           // 'foldminlines'
-       did_set_foldminlines();
-    else if (pp == &curwin->w_p_fdn)           // 'foldnestmax'
-       did_set_foldnestmax();
-    else if (pp == &curwin->w_p_fdc)           // 'foldcolumn'
-       errmsg = did_set_foldcolumn(errmsg);
-#endif // FEAT_FOLDING
-    else if (  pp == &curbuf->b_p_sw           // 'shiftwidth'
-           || pp == &curbuf->b_p_ts)           // 'tabstop'
-       did_set_shiftwidth_tabstop(pp);
-    else if (pp == &p_mco)                     // 'maxcombine'
-       did_set_maxcombine();
-    else if (pp == &curbuf->b_p_iminsert)      // 'iminsert'
-       errmsg = did_set_iminsert(errmsg);
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-    else if (pp == &p_imst)                    // 'imstyle'
-       errmsg = did_set_imstyle(errmsg);
-#endif
-    else if (pp == &p_window)                  // 'window'
-       did_set_window();
-    else if (pp == &curbuf->b_p_imsearch)      // 'imsearch'
-       errmsg = did_set_imsearch(errmsg);
-    else if (pp == &p_titlelen)                        // 'titlelen'
-       errmsg = did_set_titlelen(old_value, errmsg);
-    else if (pp == &p_ch)                      // 'cmdheight'
-       errmsg = did_set_cmdheight(old_value, errmsg);
-    else if (pp == &p_uc)                      // 'updatecount'
-       errmsg = did_set_updatecount(old_value, errmsg);
-#ifdef FEAT_CONCEAL
-    else if (pp == &curwin->w_p_cole)          // 'conceallevel'
-       errmsg = did_set_conceallevel(errmsg);
-#endif
-#ifdef MZSCHEME_GUI_THREADS
-    else if (pp == &p_mzq)                     // 'mzquantum'
-       mzvim_reset_timer();
-#endif
-#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
-    else if (pp == &p_pyx)                     // 'pyxversion'
-       errmsg = did_set_pyxversion(errmsg);
-#endif
-    else if (pp == &p_ul)                      // global 'undolevels'
-       did_set_global_undolevels(value, old_value);
-    else if (pp == &curbuf->b_p_ul)            // buffer local 'undolevels'
-       did_set_buflocal_undolevels(value, old_value);
-#ifdef FEAT_LINEBREAK
-    else if (pp == &curwin->w_p_nuw)           // 'numberwidth'
-       errmsg = did_set_numberwidth(errmsg);
-#endif
-    else if (pp == &curbuf->b_p_tw)            // 'textwidth'
-       errmsg = did_set_textwidth(errmsg);
+    char *
+did_set_undolevels(optset_T *args)
+{
+    long *pp = (long *)args->os_varp;
 
-    return errmsg;
+    if (pp == &p_ul)                   // global 'undolevels'
+       did_set_global_undolevels(args->os_newval.number,
+                                                      args->os_oldval.number);
+    else if (pp == &curbuf->b_p_ul)    // buffer local 'undolevels'
+       did_set_buflocal_undolevels(args->os_newval.number,
+                                                      args->os_oldval.number);
+
+    return NULL;
 }
 
 /*
@@ -4734,27 +4659,20 @@ set_num_option(
     need_mouse_correct = TRUE;
 #endif
 
-    if (curbuf->b_p_sw < 0)
+    // Invoke the option specific callback function to validate and apply the
+    // new value.
+    if (options[opt_idx].opt_did_set_cb != NULL)
     {
-       errmsg = e_argument_must_be_positive;
-#ifdef FEAT_VARTABS
-       // Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use.
-       curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0
-                      ? tabstop_first(curbuf->b_p_vts_array)
-                      : curbuf->b_p_ts;
-#else
-       curbuf->b_p_sw = curbuf->b_p_ts;
-#endif
-    }
+       optset_T args;
 
-    /*
-     * Number options that need some action when changed
-     */
-    errmsg = did_set_num_option(pp, value, old_value, errmsg);
+       args.os_varp = varp;
+       args.os_flags = opt_flags;
+       args.os_oldval.number = old_value;
+       args.os_newval.number = value;
+       errmsg = options[opt_idx].opt_did_set_cb(&args);
+    }
 
-    /*
-     * Check the bounds for numeric options here
-     */
+    // Check the bounds for numeric options here
     errmsg = check_num_option_bounds(pp, old_value, old_Rows, old_Columns,
                                                errbuf, errbuflen, errmsg);
 
@@ -6529,6 +6447,15 @@ get_option_fullname(int opt_idx)
 }
 #endif
 
+/*
+ * Return the did_set callback function for the option at 'opt_idx'
+ */
+    opt_did_set_cb_T
+get_option_did_set_cb(int opt_idx)
+{
+    return options[opt_idx].opt_did_set_cb;
+}
+
 /*
  * Get the value of 'equalprg', either the buffer-local one or the global one.
  */
@@ -8062,10 +7989,10 @@ compatible_set(void)
 #if defined(FEAT_LINEBREAK) || defined(PROTO)
 
 /*
- * fill_breakat_flags() -- called when 'breakat' changes value.
+ * Called when the 'breakat' option changes value.
  */
-    void
-fill_breakat_flags(void)
+    char *
+did_set_breakat(optset_T *args UNUSED)
 {
     char_u     *p;
     int                i;
@@ -8076,6 +8003,8 @@ fill_breakat_flags(void)
     if (p_breakat != NULL)
        for (p = p_breakat; *p; p++)
            breakat_flags[*p] = TRUE;
+
+    return NULL;
 }
 #endif
 
index 56b489b1979e96ebee474f773ec9db4cda3205ef..9cc540a24fd8aea05bdd251a61ffa2e13777fe9f 100644 (file)
@@ -14,7 +14,7 @@
 #define _OPTION_H_
 
 //
-// Flags
+// Option Flags
 //
 #define P_BOOL         0x01    // the option is boolean
 #define P_NUM          0x02    // the option is numeric
index 7ec4847d0140e2f7fb01e5cfa09f374bc462d6fb..c76cede2d84132c4eb50ebc08130783125724c45 100644 (file)
@@ -263,12 +263,15 @@ struct vimoption
 {
     char       *fullname;      // full option name
     char       *shortname;     // permissible abbreviation
-    long_u     flags;          // see below
+    long_u     flags;          // see in option.h
     char_u     *var;           // global option: pointer to variable;
                                // window-local option: VAR_WIN;
                                // buffer-local option: global value
     idopt_T    indir;          // global option: PV_NONE;
                                // local option: indirect option index
+    // callback function to invoke after an option is modified to validate and
+    // apply the new value.
+    opt_did_set_cb_T   opt_did_set_cb;
     char_u     *def_val[2];    // default values for variable (vi and vim)
 #ifdef FEAT_EVAL
     sctx_T     script_ctx;     // script context where the option was last set
@@ -321,6 +324,7 @@ static struct vimoption options[] =
 #else
                            (char_u *)NULL, PV_NONE,
 #endif
+                           NULL,
                            {
 #if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
                            (char_u *)128L,
@@ -329,72 +333,72 @@ static struct vimoption options[] =
 #endif
                                            (char_u *)0L} SCTX_INIT},
     {"antialias",   "anti", P_BOOL|P_VI_DEF|P_VIM|P_RCLR,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)FALSE}
                            SCTX_INIT},
     {"arabic",     "arab", P_BOOL|P_VI_DEF|P_VIM|P_CURSWANT,
 #ifdef FEAT_ARABIC
-                           (char_u *)VAR_WIN, PV_ARAB,
+                           (char_u *)VAR_WIN, PV_ARAB, did_set_arabic,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"arabicshape", "arshape", P_BOOL|P_VI_DEF|P_VIM|P_RCLR,
 #ifdef FEAT_ARABIC
-                           (char_u *)&p_arshape, PV_NONE,
+                           (char_u *)&p_arshape, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"allowrevins", "ari",  P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)&p_ari, PV_NONE,
+                           (char_u *)&p_ari, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"altkeymap",   "akm",  P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"ambiwidth",  "ambw",  P_STRING|P_VI_DEF|P_RCLR,
-                           (char_u *)&p_ambw, PV_NONE,
+                           (char_u *)&p_ambw, PV_NONE, did_set_ambiwidth,
                            {(char_u *)"single", (char_u *)0L}
                            SCTX_INIT},
     {"autochdir",  "acd",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_AUTOCHDIR
-                           (char_u *)&p_acd, PV_NONE,
+                           (char_u *)&p_acd, PV_NONE, did_set_autochdir,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"autoshelldir",  "asd",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_AUTOSHELLDIR
-                           (char_u *)&p_asd, PV_NONE,
+                           (char_u *)&p_asd, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"autoindent",  "ai",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_ai, PV_AI,
+                           (char_u *)&p_ai, PV_AI, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"autoprint",   "ap",   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"autoread",    "ar",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_ar, PV_AR,
+                           (char_u *)&p_ar, PV_AR, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"autowrite",   "aw",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_aw, PV_NONE,
+                           (char_u *)&p_aw, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"autowriteall","awa",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_awa, PV_NONE,
+                           (char_u *)&p_awa, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"background",  "bg",   P_STRING|P_VI_DEF|P_RCLR,
-                           (char_u *)&p_bg, PV_NONE,
+                           (char_u *)&p_bg, PV_NONE, did_set_background,
                            {
 #if (defined(MSWIN)) && !defined(FEAT_GUI)
                            (char_u *)"dark",
@@ -403,13 +407,13 @@ static struct vimoption options[] =
 #endif
                                            (char_u *)0L} SCTX_INIT},
     {"backspace",   "bs",   P_STRING|P_VI_DEF|P_VIM|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_bs, PV_NONE,
+                           (char_u *)&p_bs, PV_NONE, did_set_backspace,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"backup",     "bk",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_bk, PV_NONE,
+                           (char_u *)&p_bk, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"backupcopy",  "bkc",  P_STRING|P_VIM|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_bkc, PV_BKC,
+                           (char_u *)&p_bkc, PV_BKC, did_set_backupcopy,
 #ifdef UNIX
                            {(char_u *)"yes", (char_u *)"auto"}
 #else
@@ -418,10 +422,11 @@ static struct vimoption options[] =
                            SCTX_INIT},
     {"backupdir",   "bdir", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA
                                                            |P_NODUP|P_SECURE,
-                           (char_u *)&p_bdir, PV_NONE,
+                           (char_u *)&p_bdir, PV_NONE, NULL,
                            {(char_u *)DFLT_BDIR, (char_u *)0L} SCTX_INIT},
     {"backupext",   "bex",  P_STRING|P_VI_DEF|P_NFNAME,
                            (char_u *)&p_bex, PV_NONE,
+                           did_set_backupext_or_patchmode,
                            {
 #ifdef VMS
                            (char_u *)"_",
@@ -430,75 +435,77 @@ static struct vimoption options[] =
 #endif
                                            (char_u *)0L} SCTX_INIT},
     {"backupskip",  "bsk",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_bsk, PV_NONE,
+                           (char_u *)&p_bsk, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"balloondelay","bdlay",P_NUM|P_VI_DEF,
 #ifdef FEAT_BEVAL
-                           (char_u *)&p_bdlay, PV_NONE,
+                           (char_u *)&p_bdlay, PV_NONE, NULL,
                            {(char_u *)600L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"ballooneval", "beval",P_BOOL|P_VI_DEF|P_NO_MKRC,
 #ifdef FEAT_BEVAL_GUI
-                           (char_u *)&p_beval, PV_NONE,
+                           (char_u *)&p_beval, PV_NONE, did_set_ballooneval,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"balloonevalterm", "bevalterm",P_BOOL|P_VI_DEF|P_NO_MKRC,
 #ifdef FEAT_BEVAL_TERM
                            (char_u *)&p_bevalterm, PV_NONE,
+                           did_set_balloonevalterm,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"balloonexpr", "bexpr", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_MLE,
 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
-                           (char_u *)&p_bexpr, PV_BEXPR,
+                           (char_u *)&p_bexpr, PV_BEXPR, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"beautify",    "bf",   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"belloff",      "bo",  P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
-                           (char_u *)&p_bo, PV_NONE,
+                           (char_u *)&p_bo, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"binary",     "bin",  P_BOOL|P_VI_DEF|P_RSTAT,
-                           (char_u *)&p_bin, PV_BIN,
+                           (char_u *)&p_bin, PV_BIN, did_set_binary,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"bioskey",            "biosk",P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"bomb",       NULL,   P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
                            (char_u *)&p_bomb, PV_BOMB,
+                           did_set_eof_eol_fixeol_bomb,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"breakat",            "brk",  P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST,
 #ifdef FEAT_LINEBREAK
-                           (char_u *)&p_breakat, PV_NONE,
+                           (char_u *)&p_breakat, PV_NONE, did_set_breakat,
                            {(char_u *)" \t!@*-+;:,./?", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"breakindent",   "bri",  P_BOOL|P_VI_DEF|P_VIM|P_RWIN,
 #ifdef FEAT_LINEBREAK
-                           (char_u *)VAR_WIN, PV_BRI,
+                           (char_u *)VAR_WIN, PV_BRI, NULL,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
@@ -506,79 +513,80 @@ static struct vimoption options[] =
                                                  |P_ONECOMMA|P_NODUP,
 #ifdef FEAT_LINEBREAK
                            (char_u *)VAR_WIN, PV_BRIOPT,
+                           did_set_breakindentopt,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #endif
                            SCTX_INIT},
     {"browsedir",   "bsdir",P_STRING|P_VI_DEF,
 #ifdef FEAT_BROWSE
-                           (char_u *)&p_bsdir, PV_NONE,
+                           (char_u *)&p_bsdir, PV_NONE, did_set_browsedir,
                            {(char_u *)"last", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"bufhidden",   "bh",   P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
-                           (char_u *)&p_bh, PV_BH,
+                           (char_u *)&p_bh, PV_BH, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"buflisted",   "bl",   P_BOOL|P_VI_DEF|P_NOGLOB,
-                           (char_u *)&p_bl, PV_BL,
+                           (char_u *)&p_bl, PV_BL, did_set_buflisted,
                            {(char_u *)1L, (char_u *)0L}
                            SCTX_INIT},
     {"buftype",            "bt",   P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB,
-                           (char_u *)&p_bt, PV_BT,
+                           (char_u *)&p_bt, PV_BT, did_set_buftype,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"casemap",            "cmp",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cmp, PV_NONE,
+                           (char_u *)&p_cmp, PV_NONE, NULL,
                            {(char_u *)"internal,keepascii", (char_u *)0L}
                            SCTX_INIT},
     {"cdhome",     "cdh",  P_BOOL|P_VI_DEF|P_VIM|P_SECURE,
-                           (char_u *)&p_cdh, PV_NONE,
+                           (char_u *)&p_cdh, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L}
                            SCTX_INIT},
     {"cdpath",     "cd",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE|P_COMMA|P_NODUP,
-                           (char_u *)&p_cdpath, PV_NONE,
+                           (char_u *)&p_cdpath, PV_NONE, NULL,
                            {(char_u *)",,", (char_u *)0L}
                            SCTX_INIT},
     {"cedit",      NULL,   P_STRING,
-                           (char_u *)&p_cedit, PV_NONE,
+                           (char_u *)&p_cedit, PV_NONE, did_set_cedit,
                            {(char_u *)"", (char_u *)CTRL_F_STR}
                            SCTX_INIT},
     {"charconvert",  "ccv", P_STRING|P_VI_DEF|P_SECURE,
 #if defined(FEAT_EVAL)
-                           (char_u *)&p_ccv, PV_NONE,
+                           (char_u *)&p_ccv, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"cindent",            "cin",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_cin, PV_CIN,
+                           (char_u *)&p_cin, PV_CIN, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"cinkeys",            "cink", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cink, PV_CINK,
+                           (char_u *)&p_cink, PV_CINK, NULL,
                            {INDENTKEYS_DEFAULT, (char_u *)0L} SCTX_INIT},
     {"cinoptions",  "cino", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cino, PV_CINO,
+                           (char_u *)&p_cino, PV_CINO, did_set_cinoptions,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"cinscopedecls", "cinsd", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cinsd, PV_CINSD,
+                           (char_u *)&p_cinsd, PV_CINSD, NULL,
                            {(char_u *)"public,protected,private", (char_u *)0L}
                            SCTX_INIT},
     {"cinwords",    "cinw", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cinw, PV_CINW,
+                           (char_u *)&p_cinw, PV_CINW, NULL,
                            {(char_u *)"if,else,while,do,for,switch",
                                (char_u *)0L}
                            SCTX_INIT},
     {"clipboard",   "cb",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_CLIPBOARD
-                           (char_u *)&p_cb, PV_NONE,
+                           (char_u *)&p_cb, PV_NONE, did_set_clipboard,
 # ifdef FEAT_XCLIPBOARD
                            {(char_u *)"autoselect,exclude:cons\\|linux",
                                                               (char_u *)0L}
@@ -586,339 +594,342 @@ static struct vimoption options[] =
                            {(char_u *)"", (char_u *)0L}
 # endif
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"cmdheight",   "ch",   P_NUM|P_VI_DEF|P_RALL,
-                           (char_u *)&p_ch, PV_NONE,
+                           (char_u *)&p_ch, PV_NONE, did_set_cmdheight,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"cmdwinheight", "cwh", P_NUM|P_VI_DEF,
-                           (char_u *)&p_cwh, PV_NONE,
+                           (char_u *)&p_cwh, PV_NONE, NULL,
                            {(char_u *)7L, (char_u *)0L} SCTX_INIT},
     {"colorcolumn", "cc",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN,
 #ifdef FEAT_SYN_HL
-                           (char_u *)VAR_WIN, PV_CC,
+                           (char_u *)VAR_WIN, PV_CC, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"columns",            "co",   P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR,
-                           (char_u *)&Columns, PV_NONE,
+                           (char_u *)&Columns, PV_NONE, NULL,
                            {(char_u *)80L, (char_u *)0L} SCTX_INIT},
     {"comments",    "com",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA
                                                          |P_NODUP|P_CURSWANT,
-                           (char_u *)&p_com, PV_COM,
+                           (char_u *)&p_com, PV_COM, NULL,
                            {(char_u *)"s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-",
                                (char_u *)0L}
                            SCTX_INIT},
     {"commentstring", "cms", P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT,
 #ifdef FEAT_FOLDING
-                           (char_u *)&p_cms, PV_CMS,
+                           (char_u *)&p_cms, PV_CMS, did_set_commentstring,
                            {(char_u *)"/*%s*/", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
                            // P_PRI_MKRC isn't needed here, optval_default()
                            // always returns TRUE for 'compatible'
     {"compatible",  "cp",   P_BOOL|P_RALL,
-                           (char_u *)&p_cp, PV_NONE,
+                           (char_u *)&p_cp, PV_NONE, did_set_compatible,
                            {(char_u *)TRUE, (char_u *)FALSE} SCTX_INIT},
     {"complete",    "cpt",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cpt, PV_CPT,
+                           (char_u *)&p_cpt, PV_CPT, NULL,
                            {(char_u *)".,w,b,u,t,i", (char_u *)0L}
                            SCTX_INIT},
     {"concealcursor","cocu", P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
 #ifdef FEAT_CONCEAL
-                           (char_u *)VAR_WIN, PV_COCU,
+                           (char_u *)VAR_WIN, PV_COCU, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"conceallevel","cole", P_NUM|P_RWIN|P_VI_DEF,
 #ifdef FEAT_CONCEAL
-                           (char_u *)VAR_WIN, PV_COLE,
+                           (char_u *)VAR_WIN, PV_COLE, did_set_conceallevel,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L}
                            SCTX_INIT},
     {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
 #ifdef FEAT_COMPL_FUNC
-                           (char_u *)&p_cfu, PV_CFU,
+                           (char_u *)&p_cfu, PV_CFU, did_set_completefunc,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"completeopt",   "cot",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_cot, PV_NONE,
+                           (char_u *)&p_cot, PV_NONE, did_set_completeopt,
                            {(char_u *)"menu,preview", (char_u *)0L}
                            SCTX_INIT},
     {"completepopup", "cpp", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
 #if defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX)
-                           (char_u *)&p_cpp, PV_NONE,
+                           (char_u *)&p_cpp, PV_NONE, did_set_completepopup,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"completeslash",   "csl",  P_STRING|P_VI_DEF|P_VIM,
 #if defined(BACKSLASH_IN_FILENAME)
-                           (char_u *)&p_csl, PV_CSL,
+                           (char_u *)&p_csl, PV_CSL, did_set_completeslash,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"confirm",     "cf",   P_BOOL|P_VI_DEF,
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-                           (char_u *)&p_confirm, PV_NONE,
+                           (char_u *)&p_confirm, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"conskey",            "consk",P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"copyindent",  "ci",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_ci, PV_CI,
+                           (char_u *)&p_ci, PV_CI, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"cpoptions",   "cpo",  P_STRING|P_VIM|P_RALL|P_FLAGLIST,
-                           (char_u *)&p_cpo, PV_NONE,
+                           (char_u *)&p_cpo, PV_NONE, NULL,
                            {(char_u *)CPO_VI, (char_u *)CPO_VIM}
                            SCTX_INIT},
     {"cryptmethod", "cm",   P_STRING|P_ALLOCED|P_VI_DEF,
 #ifdef FEAT_CRYPT
-                           (char_u *)&p_cm, PV_CM,
+                           (char_u *)&p_cm, PV_CM, did_set_cryptmethod,
                            {(char_u *)"blowfish2", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"cscopepathcomp", "cspc", P_NUM|P_VI_DEF|P_VIM,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_cspc, PV_NONE,
+                           (char_u *)&p_cspc, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"cscopeprg",   "csprg", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_csprg, PV_NONE,
+                           (char_u *)&p_csprg, PV_NONE, NULL,
                            {(char_u *)"cscope", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"cscopequickfix", "csqf", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
                            (char_u *)&p_csqf, PV_NONE,
+                           did_set_cscopequickfix,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"cscoperelative", "csre", P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_csre, PV_NONE,
+                           (char_u *)&p_csre, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"cscopetag",   "cst",  P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_cst, PV_NONE,
+                           (char_u *)&p_cst, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"cscopetagorder", "csto", P_NUM|P_VI_DEF|P_VIM,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_csto, PV_NONE,
+                           (char_u *)&p_csto, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"cscopeverbose", "csverb", P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_CSCOPE
-                           (char_u *)&p_csverbose, PV_NONE,
+                           (char_u *)&p_csverbose, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"cursorbind",  "crb",  P_BOOL|P_VI_DEF,
-                           (char_u *)VAR_WIN, PV_CRBIND,
+                           (char_u *)VAR_WIN, PV_CRBIND, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWINONLY,
 #ifdef FEAT_SYN_HL
-                           (char_u *)VAR_WIN, PV_CUC,
+                           (char_u *)VAR_WIN, PV_CUC, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"cursorline",   "cul", P_BOOL|P_VI_DEF|P_RWINONLY,
 #ifdef FEAT_SYN_HL
-                           (char_u *)VAR_WIN, PV_CUL,
+                           (char_u *)VAR_WIN, PV_CUL, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"cursorlineopt", "culopt", P_STRING|P_VI_DEF|P_RWIN|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_SYN_HL
-                           (char_u *)VAR_WIN, PV_CULOPT,
+                           (char_u *)VAR_WIN, PV_CULOPT, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"both", (char_u *)0L} SCTX_INIT},
     {"debug",      NULL,   P_STRING|P_VI_DEF,
-                           (char_u *)&p_debug, PV_NONE,
+                           (char_u *)&p_debug, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"define",     "def",  P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT,
 #ifdef FEAT_FIND_ID
-                           (char_u *)&p_def, PV_DEF,
+                           (char_u *)&p_def, PV_DEF, NULL,
                            {(char_u *)"^\\s*#\\s*define", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"delcombine", "deco",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_deco, PV_NONE,
+                           (char_u *)&p_deco, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"dictionary",  "dict", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME,
-                           (char_u *)&p_dict, PV_DICT,
+                           (char_u *)&p_dict, PV_DICT, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"diff",       NULL,   P_BOOL|P_VI_DEF|P_RWIN|P_NOGLOB,
 #ifdef FEAT_DIFF
-                           (char_u *)VAR_WIN, PV_DIFF,
+                           (char_u *)VAR_WIN, PV_DIFF, did_set_diff,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"diffexpr",    "dex",  P_STRING|P_VI_DEF|P_SECURE|P_CURSWANT,
 #if defined(FEAT_DIFF) && defined(FEAT_EVAL)
-                           (char_u *)&p_dex, PV_NONE,
+                           (char_u *)&p_dex, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"diffopt",            "dip",  P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN|P_ONECOMMA
                                                                     |P_NODUP,
 #ifdef FEAT_DIFF
-                           (char_u *)&p_dip, PV_NONE,
+                           (char_u *)&p_dip, PV_NONE, did_set_diffopt,
                            {(char_u *)"internal,filler,closeoff",
                                                                (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #endif
                            SCTX_INIT},
     {"digraph",            "dg",   P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_DIGRAPHS
-                           (char_u *)&p_dg, PV_NONE,
+                           (char_u *)&p_dg, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"directory",   "dir",  P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA
                                                            |P_NODUP|P_SECURE,
-                           (char_u *)&p_dir, PV_NONE,
+                           (char_u *)&p_dir, PV_NONE, NULL,
                            {(char_u *)DFLT_DIR, (char_u *)0L} SCTX_INIT},
     {"display",            "dy",   P_STRING|P_VI_DEF|P_ONECOMMA|P_RALL|P_NODUP,
-                           (char_u *)&p_dy, PV_NONE,
+                           (char_u *)&p_dy, PV_NONE, did_set_display,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"eadirection", "ead",  P_STRING|P_VI_DEF,
-                           (char_u *)&p_ead, PV_NONE,
+                           (char_u *)&p_ead, PV_NONE, NULL,
                            {(char_u *)"both", (char_u *)0L}
                            SCTX_INIT},
     {"edcompatible","ed",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_ed, PV_NONE,
+                           (char_u *)&p_ed, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"emoji",      "emo",   P_BOOL|P_VI_DEF|P_RCLR,
-                           (char_u *)&p_emoji, PV_NONE,
+                           (char_u *)&p_emoji, PV_NONE, did_set_ambiwidth,
                            {(char_u *)TRUE, (char_u *)0L}
                            SCTX_INIT},
     {"encoding",    "enc",  P_STRING|P_VI_DEF|P_RCLR|P_NO_ML,
-                           (char_u *)&p_enc, PV_NONE,
+                           (char_u *)&p_enc, PV_NONE, NULL,
                            {(char_u *)ENC_DFLT, (char_u *)0L}
                            SCTX_INIT},
     {"endoffile",   "eof",  P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
                            (char_u *)&p_eof, PV_EOF,
+                           did_set_eof_eol_fixeol_bomb,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"endofline",   "eol",  P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
                            (char_u *)&p_eol, PV_EOL,
+                           did_set_eof_eol_fixeol_bomb,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"equalalways", "ea",   P_BOOL|P_VI_DEF|P_RALL,
-                           (char_u *)&p_ea, PV_NONE,
+                           (char_u *)&p_ea, PV_NONE, did_set_equalalways,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"equalprg",    "ep",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_ep, PV_EP,
+                           (char_u *)&p_ep, PV_EP, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"errorbells",  "eb",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_eb, PV_NONE,
+                           (char_u *)&p_eb, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"errorfile",   "ef",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_ef, PV_NONE,
+                           (char_u *)&p_ef, PV_NONE, NULL,
                            {(char_u *)DFLT_ERRORFILE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"errorformat", "efm",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_efm, PV_EFM,
+                           (char_u *)&p_efm, PV_EFM, NULL,
                            {(char_u *)DFLT_EFM, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"esckeys",            "ek",   P_BOOL|P_VIM,
-                           (char_u *)&p_ek, PV_NONE,
+                           (char_u *)&p_ek, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"eventignore", "ei",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_ei, PV_NONE,
+                           (char_u *)&p_ei, PV_NONE, did_set_eventignore,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"expandtab",   "et",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_et, PV_ET,
+                           (char_u *)&p_et, PV_ET, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"exrc",       "ex",   P_BOOL|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_exrc, PV_NONE,
+                           (char_u *)&p_exrc, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"fileencoding","fenc", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_RBUF
                                                                   |P_NO_MKRC,
-                           (char_u *)&p_fenc, PV_FENC,
+                           (char_u *)&p_fenc, PV_FENC, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"fileencodings","fencs", P_STRING|P_VI_DEF|P_ONECOMMA,
-                           (char_u *)&p_fencs, PV_NONE,
+                           (char_u *)&p_fencs, PV_NONE, NULL,
                            {(char_u *)"ucs-bom", (char_u *)0L}
                            SCTX_INIT},
     {"fileformat",  "ff",   P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_NO_MKRC
                                                                  |P_CURSWANT,
-                           (char_u *)&p_ff, PV_FF,
+                           (char_u *)&p_ff, PV_FF, did_set_fileformat,
                            {(char_u *)DFLT_FF, (char_u *)0L} SCTX_INIT},
     {"fileformats", "ffs",  P_STRING|P_VIM|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_ffs, PV_NONE,
+                           (char_u *)&p_ffs, PV_NONE, did_set_fileformats,
                            {(char_u *)DFLT_FFS_VI, (char_u *)DFLT_FFS_VIM}
                            SCTX_INIT},
     {"fileignorecase", "fic", P_BOOL|P_VI_DEF,
-                           (char_u *)&p_fic, PV_NONE,
+                           (char_u *)&p_fic, PV_NONE, NULL,
                            {
 #ifdef CASE_INSENSITIVE_FILENAME
                                    (char_u *)TRUE,
@@ -927,189 +938,190 @@ static struct vimoption options[] =
 #endif
                                        (char_u *)0L} SCTX_INIT},
     {"filetype",    "ft",   P_STRING|P_EXPAND|P_ALLOCED|P_VI_DEF|P_NOGLOB|P_NFNAME,
-                           (char_u *)&p_ft, PV_FT,
+                           (char_u *)&p_ft, PV_FT, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"fillchars",   "fcs",  P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_fcs, PV_FCS,
+                           (char_u *)&p_fcs, PV_FCS, NULL,
                            {(char_u *)"vert:|,fold:-,eob:~,lastline:@",
                                                                  (char_u *)0L}
                            SCTX_INIT},
     {"fixendofline",  "fixeol", P_BOOL|P_VI_DEF|P_RSTAT,
                            (char_u *)&p_fixeol, PV_FIXEOL,
+                           did_set_eof_eol_fixeol_bomb,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"fkmap",      "fk",   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"flash",      "fl",   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"foldclose",   "fcl",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)&p_fcl, PV_NONE,
+                           (char_u *)&p_fcl, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldcolumn",  "fdc",  P_NUM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FDC,
+                           (char_u *)VAR_WIN, PV_FDC, did_set_foldcolumn,
                            {(char_u *)FALSE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldenable",  "fen",  P_BOOL|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FEN,
+                           (char_u *)VAR_WIN, PV_FEN, NULL,
                            {(char_u *)TRUE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldexpr",    "fde",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN|P_MLE,
 #if defined(FEAT_FOLDING) && defined(FEAT_EVAL)
-                           (char_u *)VAR_WIN, PV_FDE,
+                           (char_u *)VAR_WIN, PV_FDE, NULL,
                            {(char_u *)"0", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldignore",  "fdi",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FDI,
+                           (char_u *)VAR_WIN, PV_FDI, did_set_foldignore,
                            {(char_u *)"#", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldlevel",   "fdl",  P_NUM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FDL,
+                           (char_u *)VAR_WIN, PV_FDL, did_set_foldlevel,
                            {(char_u *)0L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldlevelstart","fdls", P_NUM|P_VI_DEF|P_CURSWANT,
 #ifdef FEAT_FOLDING
-                           (char_u *)&p_fdls, PV_NONE,
+                           (char_u *)&p_fdls, PV_NONE, NULL,
                            {(char_u *)-1L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldmarker",  "fmr",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|
                                                    P_RWIN|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FMR,
+                           (char_u *)VAR_WIN, PV_FMR, did_set_foldmarker,
                            {(char_u *)"{{{,}}}", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldmethod",  "fdm",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FDM,
+                           (char_u *)VAR_WIN, PV_FDM, did_set_foldmethod,
                            {(char_u *)"manual", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldminlines","fml",  P_NUM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FML,
+                           (char_u *)VAR_WIN, PV_FML, did_set_foldminlines,
                            {(char_u *)1L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldnestmax", "fdn",  P_NUM|P_VI_DEF|P_RWIN,
 #ifdef FEAT_FOLDING
-                           (char_u *)VAR_WIN, PV_FDN,
+                           (char_u *)VAR_WIN, PV_FDN, did_set_foldnestmax,
                            {(char_u *)20L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldopen",    "fdo",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_CURSWANT,
 #ifdef FEAT_FOLDING
-                           (char_u *)&p_fdo, PV_NONE,
+                           (char_u *)&p_fdo, PV_NONE, NULL,
                 {(char_u *)"block,hor,mark,percent,quickfix,search,tag,undo",
                                                 (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"foldtext",    "fdt",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN|P_MLE,
 #if defined(FEAT_FOLDING) && defined(FEAT_EVAL)
-                           (char_u *)VAR_WIN, PV_FDT,
+                           (char_u *)VAR_WIN, PV_FDT, NULL,
                            {(char_u *)"foldtext()", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"formatexpr", "fex",   P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_MLE,
 #ifdef FEAT_EVAL
-                           (char_u *)&p_fex, PV_FEX,
+                           (char_u *)&p_fex, PV_FEX, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"formatoptions","fo",  P_STRING|P_ALLOCED|P_VIM|P_FLAGLIST,
-                           (char_u *)&p_fo, PV_FO,
+                           (char_u *)&p_fo, PV_FO, NULL,
                            {(char_u *)DFLT_FO_VI, (char_u *)DFLT_FO_VIM}
                            SCTX_INIT},
     {"formatlistpat","flp", P_STRING|P_ALLOCED|P_VI_DEF,
-                           (char_u *)&p_flp, PV_FLP,
+                           (char_u *)&p_flp, PV_FLP, NULL,
                            {(char_u *)"^\\s*\\d\\+[\\]:.)}\\t ]\\s*",
                                                 (char_u *)0L} SCTX_INIT},
     {"formatprg",   "fp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_fp, PV_FP,
+                           (char_u *)&p_fp, PV_FP, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"fsync",       "fs",   P_BOOL|P_SECURE|P_VI_DEF,
 #ifdef HAVE_FSYNC
-                           (char_u *)&p_fs, PV_NONE,
+                           (char_u *)&p_fs, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"gdefault",    "gd",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_gd, PV_NONE,
+                           (char_u *)&p_gd, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"graphic",            "gr",   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"grepformat",  "gfm",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_gefm, PV_NONE,
+                           (char_u *)&p_gefm, PV_NONE, NULL,
                            {(char_u *)DFLT_GREPFORMAT, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"grepprg",            "gp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_gp, PV_GP,
+                           (char_u *)&p_gp, PV_GP, NULL,
                            {
 # if defined(MSWIN)
                            // may be changed to "grep -n" in os_win32.c
@@ -1125,13 +1137,13 @@ static struct vimoption options[] =
 # endif
                            (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guicursor",    "gcr", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef CURSOR_SHAPE
-                           (char_u *)&p_guicursor, PV_NONE,
+                           (char_u *)&p_guicursor, PV_NONE, NULL,
                            {
 # ifdef FEAT_GUI
                                (char_u *)"n-v-c:block-Cursor/lCursor,ve:ver35-Cursor,o:hor50-Cursor,i-ci:ver25-Cursor/lCursor,r-cr:hor20-Cursor/lCursor,sm:block-Cursor-blinkwait175-blinkoff150-blinkon175",
@@ -1140,34 +1152,36 @@ static struct vimoption options[] =
 # endif
                                    (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guifont",            "gfn",  P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_GUI
-                           (char_u *)&p_guifont, PV_NONE,
+                           (char_u *)&p_guifont, PV_NONE, did_set_guifont,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guifontset",  "gfs",  P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA,
 #if defined(FEAT_GUI) && defined(FEAT_XFONTSET)
                            (char_u *)&p_guifontset, PV_NONE,
+                           did_set_guifontset,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guifontwide", "gfw",  P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
 #if defined(FEAT_GUI)
                            (char_u *)&p_guifontwide, PV_NONE,
+                           did_set_guifontwide,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
@@ -1176,9 +1190,10 @@ static struct vimoption options[] =
     {"guiligatures", "gli", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
 #if defined(FEAT_GUI_GTK)
                            (char_u *)&p_guiligatures, PV_NONE,
+                           did_set_guiligatures,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
@@ -1186,200 +1201,215 @@ static struct vimoption options[] =
 
     {"guiheadroom", "ghr",  P_NUM|P_VI_DEF,
 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11)
-                           (char_u *)&p_ghr, PV_NONE,
+                           (char_u *)&p_ghr, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)50L, (char_u *)0L} SCTX_INIT},
     {"guioptions",  "go",   P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST,
 #if defined(FEAT_GUI)
-                           (char_u *)&p_go, PV_NONE,
+                           (char_u *)&p_go, PV_NONE, did_set_guioptions,
 # if defined(UNIX)
                            {(char_u *)"aegimrLtT", (char_u *)0L}
 # else
                            {(char_u *)"egmrLtT", (char_u *)0L}
 # endif
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guipty",     NULL,   P_BOOL|P_VI_DEF,
 #if defined(FEAT_GUI)
-                           (char_u *)&p_guipty, PV_NONE,
+                           (char_u *)&p_guipty, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"guitablabel",  "gtl", P_STRING|P_VI_DEF|P_RWIN|P_MLE,
 #if defined(FEAT_GUI_TABLINE)
-                           (char_u *)&p_gtl, PV_NONE,
+                           (char_u *)&p_gtl, PV_NONE, did_set_guitablabel,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"guitabtooltip",  "gtt", P_STRING|P_VI_DEF|P_RWIN,
 #if defined(FEAT_GUI_TABLINE)
-                           (char_u *)&p_gtt, PV_NONE,
+                           (char_u *)&p_gtt, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"hardtabs",    "ht",   P_NUM|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"helpfile",    "hf",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_hf, PV_NONE,
+                           (char_u *)&p_hf, PV_NONE, did_set_helpfile,
                            {(char_u *)DFLT_HELPFILE, (char_u *)0L}
                            SCTX_INIT},
     {"helpheight",  "hh",   P_NUM|P_VI_DEF,
                            (char_u *)&p_hh, PV_NONE,
+                           did_set_winheight_helpheight,
                            {(char_u *)20L, (char_u *)0L} SCTX_INIT},
     {"helplang",    "hlg",  P_STRING|P_VI_DEF|P_ONECOMMA,
 #ifdef FEAT_MULTI_LANG
-                           (char_u *)&p_hlg, PV_NONE,
+                           (char_u *)&p_hlg, PV_NONE, did_set_helplang,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"hidden",     "hid",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_hid, PV_NONE,
+                           (char_u *)&p_hid, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"highlight",   "hl",   P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_hl, PV_NONE,
+                           (char_u *)&p_hl, PV_NONE, did_set_highlight,
                            {(char_u *)HIGHLIGHT_INIT, (char_u *)0L}
                            SCTX_INIT},
     {"history",            "hi",   P_NUM|P_VIM,
-                           (char_u *)&p_hi, PV_NONE,
+                           (char_u *)&p_hi, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)50L} SCTX_INIT},
     {"hkmap",      "hk",   P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)&p_hkmap, PV_NONE,
+                           (char_u *)&p_hkmap, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"hkmapp",     "hkp",  P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)&p_hkmapp, PV_NONE,
+                           (char_u *)&p_hkmapp, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"hlsearch",    "hls",  P_BOOL|P_VI_DEF|P_VIM|P_RALL,
-                           (char_u *)&p_hls, PV_NONE,
+#if defined(FEAT_SEARCH_EXTRA)
+                           (char_u *)&p_hls, PV_NONE, did_set_hlsearch,
+#else
+                           (char_u *)NULL, PV_NONE, NULL,
+#endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"icon",       NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_icon, PV_NONE,
+                           (char_u *)&p_icon, PV_NONE, did_set_title_icon,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"iconstring",  NULL,   P_STRING|P_VI_DEF|P_MLE,
                            (char_u *)&p_iconstring, PV_NONE,
+                           did_set_iconstring,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"ignorecase",  "ic",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_ic, PV_NONE,
+                           (char_u *)&p_ic, PV_NONE, did_set_ignorecase,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"imactivatefunc","imaf",P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
-#if defined(FEAT_EVAL)
+#if defined(FEAT_EVAL) && \
+       (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
                            (char_u *)&p_imaf, PV_NONE,
+                           did_set_imactivatefunc,
                            {(char_u *)"", (char_u *)NULL}
 # else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 # endif
                            SCTX_INIT},
     {"imactivatekey","imak",P_STRING|P_VI_DEF,
 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
                            (char_u *)&p_imak, PV_NONE,
+                           did_set_imactivatekey,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"imcmdline",   "imc",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_imcmdline, PV_NONE,
+                           (char_u *)&p_imcmdline, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"imdisable",   "imd",  P_BOOL|P_VI_DEF,
+#if defined(HAVE_INPUT_METHOD)
                            (char_u *)&p_imdisable, PV_NONE,
+                           did_set_imdisable,
+#else
+                           (char_u *)NULL, PV_NONE, NULL,
+#endif
                            {(char_u *)FALSE, (char_u *)0L}
                            SCTX_INIT},
     {"iminsert",    "imi",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_iminsert, PV_IMI,
+                           (char_u *)&p_iminsert, PV_IMI, did_set_iminsert,
                            {(char_u *)B_IMODE_NONE, (char_u *)0L}
                            SCTX_INIT},
     {"imsearch",    "ims",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_imsearch, PV_IMS,
+                           (char_u *)&p_imsearch, PV_IMS, did_set_imsearch,
                            {(char_u *)B_IMODE_USE_INSERT, (char_u *)0L}
                            SCTX_INIT},
     {"imstatusfunc","imsf",P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
-#if defined(FEAT_EVAL)
-                           (char_u *)&p_imsf, PV_NONE,
+#if defined(FEAT_EVAL) && \
+       (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
+                           (char_u *)&p_imsf, PV_NONE, did_set_imstatusfunc,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"imstyle",            "imst", P_NUM|P_VI_DEF|P_SECURE,
 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-                           (char_u *)&p_imst, PV_NONE,
+                           (char_u *)&p_imst, PV_NONE, did_set_imstyle,
                            {(char_u *)IM_OVER_THE_SPOT, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"include",            "inc",  P_STRING|P_ALLOCED|P_VI_DEF,
 #ifdef FEAT_FIND_ID
-                           (char_u *)&p_inc, PV_INC,
+                           (char_u *)&p_inc, PV_INC, NULL,
                            {(char_u *)"^\\s*#\\s*include", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"includeexpr", "inex", P_STRING|P_ALLOCED|P_VI_DEF|P_MLE,
 #if defined(FEAT_FIND_ID) && defined(FEAT_EVAL)
-                           (char_u *)&p_inex, PV_INEX,
+                           (char_u *)&p_inex, PV_INEX, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"incsearch",   "is",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_is, PV_NONE,
+                           (char_u *)&p_is, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"indentexpr", "inde",  P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_MLE,
 #if defined(FEAT_EVAL)
-                           (char_u *)&p_inde, PV_INDE,
+                           (char_u *)&p_inde, PV_INDE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"indentkeys", "indk",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #if defined(FEAT_EVAL)
-                           (char_u *)&p_indk, PV_INDK,
+                           (char_u *)&p_indk, PV_INDK, NULL,
                            {INDENTKEYS_DEFAULT, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"infercase",   "inf",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_inf, PV_INF,
+                           (char_u *)&p_inf, PV_INF, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"insertmode",  "im",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_im, PV_NONE,
+                           (char_u *)&p_im, PV_NONE, did_set_insertmode,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"isfname",            "isf",  P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
-                           (char_u *)&p_isf, PV_NONE,
+                           (char_u *)&p_isf, PV_NONE, NULL,
                            {
 #ifdef BACKSLASH_IN_FILENAME
                                // Excluded are: & and ^ are special in cmd.exe
@@ -1396,7 +1426,7 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"isident",            "isi",  P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
-                           (char_u *)&p_isi, PV_NONE,
+                           (char_u *)&p_isi, PV_NONE, NULL,
                            {
 #if defined(MSWIN)
                            (char_u *)"@,48-57,_,128-167,224-235",
@@ -1405,7 +1435,7 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"iskeyword",   "isk",  P_STRING|P_ALLOCED|P_VIM|P_COMMA|P_NODUP,
-                           (char_u *)&p_isk, PV_ISK,
+                           (char_u *)&p_isk, PV_ISK, NULL,
                            {
                                (char_u *)"@,48-57,_",
 #if defined(MSWIN)
@@ -1415,7 +1445,7 @@ static struct vimoption options[] =
 #endif
                            } SCTX_INIT},
     {"isprint",            "isp",  P_STRING|P_VI_DEF|P_RALL|P_COMMA|P_NODUP,
-                           (char_u *)&p_isp, PV_NONE,
+                           (char_u *)&p_isp, PV_NONE, NULL,
                            {
 #if defined(MSWIN) || defined(VMS)
                            (char_u *)"@,~-255",
@@ -1424,35 +1454,35 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"joinspaces",  "js",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_js, PV_NONE,
+                           (char_u *)&p_js, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"key",        NULL,   P_STRING|P_ALLOCED|P_VI_DEF|P_NO_MKRC,
 #ifdef FEAT_CRYPT
-                           (char_u *)&p_key, PV_KEY,
+                           (char_u *)&p_key, PV_KEY, did_set_cryptkey,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"keymap",     "kmp",  P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC,
 #ifdef FEAT_KEYMAP
-                           (char_u *)&p_keymap, PV_KMAP,
+                           (char_u *)&p_keymap, PV_KMAP, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"keymodel",    "km",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_km, PV_NONE,
+                           (char_u *)&p_km, PV_NONE, did_set_keymodel,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"keyprotocol", "kpc",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_kpc, PV_NONE,
+                           (char_u *)&p_kpc, PV_NONE, did_set_keyprotocol,
                            {(char_u *)"kitty:kitty,foot:kitty,wezterm:kitty,xterm:mok2", (char_u *)0L}
                            SCTX_INIT},
     {"keywordprg",  "kp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_kp, PV_KP,
+                           (char_u *)&p_kp, PV_KP, NULL,
                            {
 #if defined(MSWIN)
                            (char_u *)":help",
@@ -1466,49 +1496,49 @@ static struct vimoption options[] =
                                (char_u *)0L} SCTX_INIT},
     {"langmap",     "lmap", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_SECURE,
 #ifdef FEAT_LANGMAP
-                           (char_u *)&p_langmap, PV_NONE,
+                           (char_u *)&p_langmap, PV_NONE, did_set_langmap,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"langmenu",    "lm",   P_STRING|P_VI_DEF|P_NFNAME,
 #if defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)
-                           (char_u *)&p_lm, PV_NONE,
+                           (char_u *)&p_lm, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"langnoremap",  "lnr",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_LANGMAP
-                           (char_u *)&p_lnr, PV_NONE,
+                           (char_u *)&p_lnr, PV_NONE, did_set_langnoremap,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"langremap",  "lrm",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_LANGMAP
-                           (char_u *)&p_lrm, PV_NONE,
+                           (char_u *)&p_lrm, PV_NONE, did_set_langremap,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"laststatus",  "ls",   P_NUM|P_VI_DEF|P_RALL,
-                           (char_u *)&p_ls, PV_NONE,
+                           (char_u *)&p_ls, PV_NONE, did_set_laststatus,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"lazyredraw",  "lz",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_lz, PV_NONE,
+                           (char_u *)&p_lz, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"linebreak",   "lbr",  P_BOOL|P_VI_DEF|P_RWIN,
 #ifdef FEAT_LINEBREAK
-                           (char_u *)VAR_WIN, PV_LBR,
+                           (char_u *)VAR_WIN, PV_LBR, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"lines",      NULL,   P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR,
-                           (char_u *)&Rows, PV_NONE,
+                           (char_u *)&Rows, PV_NONE, NULL,
                            {
 #if defined(MSWIN)
                            (char_u *)25L,
@@ -1519,8 +1549,9 @@ static struct vimoption options[] =
     {"linespace",   "lsp",  P_NUM|P_VI_DEF|P_RCLR,
 #ifdef FEAT_GUI
                            (char_u *)&p_linespace, PV_NONE,
+                           did_set_linespace,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
 #ifdef FEAT_GUI_MSWIN
                            {(char_u *)1L, (char_u *)0L}
@@ -1529,135 +1560,135 @@ static struct vimoption options[] =
 #endif
                            SCTX_INIT},
     {"lisp",       NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_lisp, PV_LISP,
+                           (char_u *)&p_lisp, PV_LISP, did_set_lisp,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"lispoptions", "lop",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_lop, PV_LOP,
+                           (char_u *)&p_lop, PV_LOP, did_set_lispoptions,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"lispwords",   "lw",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_lispwords, PV_LW,
+                           (char_u *)&p_lispwords, PV_LW, NULL,
                            {(char_u *)LISPWORD_VALUE, (char_u *)0L} SCTX_INIT},
     {"list",       NULL,   P_BOOL|P_VI_DEF|P_RWIN,
-                           (char_u *)VAR_WIN, PV_LIST,
+                           (char_u *)VAR_WIN, PV_LIST, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"listchars",   "lcs",  P_STRING|P_VI_DEF|P_RALL|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_lcs, PV_LCS,
+                           (char_u *)&p_lcs, PV_LCS, NULL,
                            {(char_u *)"eol:$", (char_u *)0L} SCTX_INIT},
     {"loadplugins", "lpl",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_lpl, PV_NONE,
+                           (char_u *)&p_lpl, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"luadll",      NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_LUA)
-                           (char_u *)&p_luadll, PV_NONE,
+                           (char_u *)&p_luadll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_LUA_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"macatsui",    NULL,   P_BOOL|P_VI_DEF|P_RCLR,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"magic",      NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_magic, PV_NONE,
+                           (char_u *)&p_magic, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"makeef",     "mef",  P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_mef, PV_NONE,
+                           (char_u *)&p_mef, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"makeencoding","menc", P_STRING|P_VI_DEF,
-                           (char_u *)&p_menc, PV_MENC,
+                           (char_u *)&p_menc, PV_MENC, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"makeprg",            "mp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_mp, PV_MP,
+                           (char_u *)&p_mp, PV_MP, NULL,
 # ifdef VMS
                            {(char_u *)"MMS", (char_u *)0L}
 # else
                            {(char_u *)"make", (char_u *)0L}
 # endif
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"matchpairs",  "mps",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_mps, PV_MPS,
+                           (char_u *)&p_mps, PV_MPS, did_set_matchpairs,
                            {(char_u *)"(:),{:},[:]", (char_u *)0L}
                            SCTX_INIT},
     {"matchtime",   "mat",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_mat, PV_NONE,
+                           (char_u *)&p_mat, PV_NONE, NULL,
                            {(char_u *)5L, (char_u *)0L} SCTX_INIT},
     {"maxcombine",  "mco",  P_NUM|P_VI_DEF|P_CURSWANT,
-                           (char_u *)&p_mco, PV_NONE,
+                           (char_u *)&p_mco, PV_NONE, did_set_maxcombine,
                            {(char_u *)2, (char_u *)0L} SCTX_INIT},
     {"maxfuncdepth", "mfd", P_NUM|P_VI_DEF,
 #ifdef FEAT_EVAL
-                           (char_u *)&p_mfd, PV_NONE,
+                           (char_u *)&p_mfd, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)100L, (char_u *)0L} SCTX_INIT},
     {"maxmapdepth", "mmd",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_mmd, PV_NONE,
+                           (char_u *)&p_mmd, PV_NONE, NULL,
                            {(char_u *)1000L, (char_u *)0L} SCTX_INIT},
     {"maxmem",     "mm",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_mm, PV_NONE,
+                           (char_u *)&p_mm, PV_NONE, NULL,
                            {(char_u *)DFLT_MAXMEM, (char_u *)0L}
                            SCTX_INIT},
     {"maxmempattern","mmp", P_NUM|P_VI_DEF,
-                           (char_u *)&p_mmp, PV_NONE,
+                           (char_u *)&p_mmp, PV_NONE, NULL,
                            {(char_u *)1000L, (char_u *)0L} SCTX_INIT},
     {"maxmemtot",   "mmt",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_mmt, PV_NONE,
+                           (char_u *)&p_mmt, PV_NONE, NULL,
                            {(char_u *)DFLT_MAXMEMTOT, (char_u *)0L}
                            SCTX_INIT},
     {"menuitems",   "mis",  P_NUM|P_VI_DEF,
 #ifdef FEAT_MENU
-                           (char_u *)&p_mis, PV_NONE,
+                           (char_u *)&p_mis, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)25L, (char_u *)0L} SCTX_INIT},
     {"mesg",       NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"mkspellmem",  "msm",  P_STRING|P_VI_DEF|P_EXPAND|P_SECURE,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_msm, PV_NONE,
+                           (char_u *)&p_msm, PV_NONE, did_set_mkspellmem,
                            {(char_u *)"460000,2000,500", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"modeline",    "ml",   P_BOOL|P_VIM,
-                           (char_u *)&p_ml, PV_ML,
+                           (char_u *)&p_ml, PV_ML, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"modelineexpr", "mle",  P_BOOL|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_mle, PV_NONE,
+                           (char_u *)&p_mle, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"modelines",   "mls",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_mls, PV_NONE,
+                           (char_u *)&p_mls, PV_NONE, NULL,
                            {(char_u *)5L, (char_u *)0L} SCTX_INIT},
     {"modifiable",  "ma",   P_BOOL|P_VI_DEF|P_NOGLOB,
-                           (char_u *)&p_ma, PV_MA,
+                           (char_u *)&p_ma, PV_MA, did_set_modifiable,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"modified",    "mod",  P_BOOL|P_NO_MKRC|P_VI_DEF|P_RSTAT,
-                           (char_u *)&p_mod, PV_MOD,
+                           (char_u *)&p_mod, PV_MOD, did_set_modified,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"more",       NULL,   P_BOOL|P_VIM,
-                           (char_u *)&p_more, PV_NONE,
+                           (char_u *)&p_more, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"mouse",      NULL,   P_STRING|P_VI_DEF|P_FLAGLIST,
-                           (char_u *)&p_mouse, PV_NONE,
+                           (char_u *)&p_mouse, PV_NONE, NULL,
                            {
 #if defined(MSWIN)
                                (char_u *)"a",
@@ -1667,20 +1698,20 @@ static struct vimoption options[] =
                                (char_u *)0L} SCTX_INIT},
     {"mousefocus",   "mousef", P_BOOL|P_VI_DEF,
 #ifdef FEAT_GUI
-                           (char_u *)&p_mousef, PV_NONE,
+                           (char_u *)&p_mousef, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"mousehide",   "mh",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_GUI
-                           (char_u *)&p_mh, PV_NONE,
+                           (char_u *)&p_mh, PV_NONE, did_set_mousehide,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"mousemodel",  "mousem", P_STRING|P_VI_DEF,
-                           (char_u *)&p_mousem, PV_NONE,
+                           (char_u *)&p_mousem, PV_NONE, did_set_mousemodel,
                            {
 #if defined(MSWIN)
                                (char_u *)"popup",
@@ -1694,123 +1725,127 @@ static struct vimoption options[] =
                                (char_u *)0L} SCTX_INIT},
     {"mousemoveevent",   "mousemev",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_GUI
-                           (char_u *)&p_mousemev, PV_NONE,
+                           (char_u *)&p_mousemev, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"mouseshape",  "mouses",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_MOUSESHAPE
                            (char_u *)&p_mouseshape, PV_NONE,
+                           did_set_mouseshape,
                            {(char_u *)"i-r:beam,s:updown,sd:udsizing,vs:leftright,vd:lrsizing,m:no,ml:up-arrow,v:rightup-arrow", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"mousetime",   "mouset",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_mouset, PV_NONE,
+                           (char_u *)&p_mouset, PV_NONE, NULL,
                            {(char_u *)500L, (char_u *)0L} SCTX_INIT},
     {"mzschemedll", NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_MZSCHEME)
-                           (char_u *)&p_mzschemedll, PV_NONE,
+                           (char_u *)&p_mzschemedll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_MZSCH_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"mzschemegcdll", NULL, P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_MZSCHEME)
-                           (char_u *)&p_mzschemegcdll, PV_NONE,
+                           (char_u *)&p_mzschemegcdll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_MZGC_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"mzquantum",  "mzq",   P_NUM,
 #ifdef FEAT_MZSCHEME
-                           (char_u *)&p_mzq, PV_NONE,
+                           (char_u *)&p_mzq, PV_NONE, did_set_mzquantum,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)100L, (char_u *)100L} SCTX_INIT},
     {"novice",     NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"nrformats",   "nf",   P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_nf, PV_NF,
+                           (char_u *)&p_nf, PV_NF, NULL,
                            {(char_u *)"bin,octal,hex", (char_u *)0L}
                            SCTX_INIT},
     {"number",     "nu",   P_BOOL|P_VI_DEF|P_RWIN,
                            (char_u *)VAR_WIN, PV_NU,
+                           did_set_number_relativenumber,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"numberwidth", "nuw",  P_NUM|P_RWIN|P_VIM,
 #ifdef FEAT_LINEBREAK
-                           (char_u *)VAR_WIN, PV_NUW,
+                           (char_u *)VAR_WIN, PV_NUW, did_set_numberwidth,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)8L, (char_u *)4L} SCTX_INIT},
     {"omnifunc",    "ofu",  P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
 #ifdef FEAT_COMPL_FUNC
-                           (char_u *)&p_ofu, PV_OFU,
+                           (char_u *)&p_ofu, PV_OFU, did_set_omnifunc,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"open",       NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"opendevice",  "odev", P_BOOL|P_VI_DEF,
 #if defined(MSWIN)
-                           (char_u *)&p_odev, PV_NONE,
+                           (char_u *)&p_odev, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)FALSE}
                            SCTX_INIT},
     {"operatorfunc", "opfunc", P_STRING|P_VI_DEF|P_SECURE|P_FUNC,
                            (char_u *)&p_opfunc, PV_NONE,
+                           did_set_operatorfunc,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"optimize",    "opt",  P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"osfiletype",  "oft",  P_STRING|P_ALLOCED|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"packpath",    "pp",   P_STRING|P_VI_DEF|P_EXPAND|P_ONECOMMA|P_NODUP
                                                                    |P_SECURE,
-                           (char_u *)&p_pp, PV_NONE,
+                           (char_u *)&p_pp, PV_NONE, NULL,
                            {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L}
                            SCTX_INIT},
     {"paragraphs",  "para", P_STRING|P_VI_DEF,
-                           (char_u *)&p_para, PV_NONE,
+                           (char_u *)&p_para, PV_NONE, NULL,
                            {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp",
                                (char_u *)0L} SCTX_INIT},
     {"paste",      NULL,   P_BOOL|P_VI_DEF|P_PRI_MKRC,
-                           (char_u *)&p_paste, PV_NONE,
+                           (char_u *)&p_paste, PV_NONE, did_set_paste,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"pastetoggle", "pt",   P_STRING|P_VI_DEF,
-                           (char_u *)&p_pt, PV_NONE,
+                           (char_u *)&p_pt, PV_NONE, did_set_pastetoggle,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"patchexpr",   "pex",  P_STRING|P_VI_DEF|P_SECURE,
 #if defined(FEAT_DIFF) && defined(FEAT_EVAL)
-                           (char_u *)&p_pex, PV_NONE,
+                           (char_u *)&p_pex, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"patchmode",   "pm",   P_STRING|P_VI_DEF|P_NFNAME,
                            (char_u *)&p_pm, PV_NONE,
+                           did_set_backupext_or_patchmode,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"path",       "pa",   P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
-                           (char_u *)&p_path, PV_PATH,
+                           (char_u *)&p_path, PV_PATH, NULL,
                            {
 #if defined(AMIGA) || defined(MSWIN)
                            (char_u *)".,,",
@@ -1820,69 +1855,70 @@ static struct vimoption options[] =
                                (char_u *)0L} SCTX_INIT},
     {"perldll",     NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_PERL)
-                           (char_u *)&p_perldll, PV_NONE,
+                           (char_u *)&p_perldll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_PERL_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"preserveindent", "pi", P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_pi, PV_PI,
+                           (char_u *)&p_pi, PV_PI, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"previewheight", "pvh", P_NUM|P_VI_DEF,
 #if defined(FEAT_QUICKFIX)
-                           (char_u *)&p_pvh, PV_NONE,
+                           (char_u *)&p_pvh, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)12L, (char_u *)0L} SCTX_INIT},
     {"previewpopup", "pvp", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
 #ifdef FEAT_PROP_POPUP
-                           (char_u *)&p_pvp, PV_NONE,
+                           (char_u *)&p_pvp, PV_NONE, did_set_previewpopup,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"previewwindow", "pvw", P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB,
 #if defined(FEAT_QUICKFIX)
-                           (char_u *)VAR_WIN, PV_PVW,
+                           (char_u *)VAR_WIN, PV_PVW, did_set_previewwindow,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"printdevice", "pdev", P_STRING|P_VI_DEF|P_SECURE,
 #ifdef FEAT_PRINTER
-                           (char_u *)&p_pdev, PV_NONE,
+                           (char_u *)&p_pdev, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printencoding", "penc", P_STRING|P_VI_DEF,
 #ifdef FEAT_POSTSCRIPT
                            (char_u *)&p_penc, PV_NONE,
+                           did_set_printencoding,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printexpr", "pexpr",  P_STRING|P_VI_DEF|P_SECURE,
 #ifdef FEAT_POSTSCRIPT
-                           (char_u *)&p_pexpr, PV_NONE,
+                           (char_u *)&p_pexpr, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printfont", "pfn",    P_STRING|P_VI_DEF,
 #ifdef FEAT_PRINTER
-                           (char_u *)&p_pfn, PV_NONE,
+                           (char_u *)&p_pfn, PV_NONE, NULL,
                            {
 # ifdef MSWIN
                                (char_u *)"Courier_New:h10",
@@ -1891,250 +1927,253 @@ static struct vimoption options[] =
 # endif
                                (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printheader", "pheader",  P_STRING|P_VI_DEF|P_GETTEXT,
 #ifdef FEAT_PRINTER
-                           (char_u *)&p_header, PV_NONE,
+                           (char_u *)&p_header, PV_NONE, NULL,
                            // untranslated to avoid problems when 'encoding'
                            // is changed
                            {(char_u *)"%<%f%h%m%=Page %N", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
    {"printmbcharset", "pmbcs",  P_STRING|P_VI_DEF,
 #if defined(FEAT_POSTSCRIPT)
-                           (char_u *)&p_pmcs, PV_NONE,
+                           (char_u *)&p_pmcs, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printmbfont", "pmbfn",  P_STRING|P_VI_DEF,
 #if defined(FEAT_POSTSCRIPT)
-                           (char_u *)&p_pmfn, PV_NONE,
+                           (char_u *)&p_pmfn, PV_NONE, parse_printmbfont,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"printoptions", "popt", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_PRINTER
-                           (char_u *)&p_popt, PV_NONE,
+                           (char_u *)&p_popt, PV_NONE, parse_printoptions,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"prompt",     NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_prompt, PV_NONE,
+                           (char_u *)&p_prompt, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"pumheight",   "ph",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_ph, PV_NONE,
+                           (char_u *)&p_ph, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"pumwidth",    "pw",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_pw, PV_NONE,
+                           (char_u *)&p_pw, PV_NONE, NULL,
                            {(char_u *)15L, (char_u *)15L} SCTX_INIT},
     {"pythonthreedll",  NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_PYTHON3)
-                           (char_u *)&p_py3dll, PV_NONE,
+                           (char_u *)&p_py3dll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_PYTHON3_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"pythonthreehome", NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(FEAT_PYTHON3)
-                           (char_u *)&p_py3home, PV_NONE,
+                           (char_u *)&p_py3home, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"pythondll",   NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_PYTHON)
-                           (char_u *)&p_pydll, PV_NONE,
+                           (char_u *)&p_pydll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_PYTHON_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"pythonhome",  NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(FEAT_PYTHON)
-                           (char_u *)&p_pyhome, PV_NONE,
+                           (char_u *)&p_pyhome, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"pyxversion", "pyx",   P_NUM|P_VI_DEF|P_SECURE,
 #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
-                           (char_u *)&p_pyx, PV_NONE,
+                           (char_u *)&p_pyx, PV_NONE, did_set_pyxversion,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)DEFAULT_PYTHON_VER, (char_u *)0L}
                            SCTX_INIT},
     {"quickfixtextfunc", "qftf", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE|P_FUNC,
 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
                            (char_u *)&p_qftf, PV_NONE,
+                           did_set_quickfixtextfunc,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)NULL}
 #endif
                            SCTX_INIT},
     {"quoteescape", "qe",   P_STRING|P_ALLOCED|P_VI_DEF,
-                           (char_u *)&p_qe, PV_QE,
+                           (char_u *)&p_qe, PV_QE, NULL,
                            {(char_u *)"\\", (char_u *)0L} SCTX_INIT},
     {"readonly",    "ro",   P_BOOL|P_VI_DEF|P_RSTAT|P_NOGLOB,
-                           (char_u *)&p_ro, PV_RO,
+                           (char_u *)&p_ro, PV_RO, did_set_readonly,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"redraw",     NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"redrawtime",  "rdt",  P_NUM|P_VI_DEF,
 #ifdef FEAT_RELTIME
-                           (char_u *)&p_rdt, PV_NONE,
+                           (char_u *)&p_rdt, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)2000L, (char_u *)0L} SCTX_INIT},
     {"regexpengine", "re",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_re, PV_NONE,
+                           (char_u *)&p_re, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN,
                            (char_u *)VAR_WIN, PV_RNU,
+                           did_set_number_relativenumber,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"remap",      NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_remap, PV_NONE,
+                           (char_u *)&p_remap, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"renderoptions", "rop", P_STRING|P_ONECOMMA|P_RCLR|P_VI_DEF,
 #ifdef FEAT_RENDER_OPTIONS
-                           (char_u *)&p_rop, PV_NONE,
+                           (char_u *)&p_rop, PV_NONE, did_set_renderoptions,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"report",     NULL,   P_NUM|P_VI_DEF,
-                           (char_u *)&p_report, PV_NONE,
+                           (char_u *)&p_report, PV_NONE, NULL,
                            {(char_u *)2L, (char_u *)0L} SCTX_INIT},
     {"restorescreen", "rs", P_BOOL|P_VI_DEF,
 #ifdef MSWIN
-                           (char_u *)&p_rs, PV_NONE,
+                           (char_u *)&p_rs, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"revins",     "ri",   P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)&p_ri, PV_NONE,
+                           (char_u *)&p_ri, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"rightleft",   "rl",   P_BOOL|P_VI_DEF|P_RWIN,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)VAR_WIN, PV_RL,
+                           (char_u *)VAR_WIN, PV_RL, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"rightleftcmd", "rlc", P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN,
 #ifdef FEAT_RIGHTLEFT
-                           (char_u *)VAR_WIN, PV_RLC,
+                           (char_u *)VAR_WIN, PV_RLC, NULL,
                            {(char_u *)"search", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"rubydll",     NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_RUBY)
-                           (char_u *)&p_rubydll, PV_NONE,
+                           (char_u *)&p_rubydll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_RUBY_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"ruler",      "ru",   P_BOOL|P_VI_DEF|P_VIM|P_RSTAT,
-                           (char_u *)&p_ru, PV_NONE,
+                           (char_u *)&p_ru, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"rulerformat", "ruf",  P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT|P_MLE,
 #ifdef FEAT_STL_OPT
-                           (char_u *)&p_ruf, PV_NONE,
+                           (char_u *)&p_ruf, PV_NONE, did_set_rulerformat,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"runtimepath", "rtp",  P_STRING|P_VI_DEF|P_EXPAND|P_ONECOMMA|P_NODUP
                                                                    |P_SECURE,
-                           (char_u *)&p_rtp, PV_NONE,
+                           (char_u *)&p_rtp, PV_NONE, NULL,
                            {(char_u *)DFLT_RUNTIMEPATH, (char_u *)0L}
                            SCTX_INIT},
     {"scroll",     "scr",  P_NUM|P_NO_MKRC|P_VI_DEF,
-                           (char_u *)VAR_WIN, PV_SCROLL,
+                           (char_u *)VAR_WIN, PV_SCROLL, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"scrollbind",  "scb",  P_BOOL|P_VI_DEF,
-                           (char_u *)VAR_WIN, PV_SCBIND,
+                           (char_u *)VAR_WIN, PV_SCBIND, did_set_scrollbind,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"scrollfocus", "scf",  P_BOOL|P_VI_DEF,
 #if defined(MSWIN) && defined(FEAT_GUI)
-                           (char_u *)&p_scf, PV_NONE,
+                           (char_u *)&p_scf, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"scrolljump",  "sj",   P_NUM|P_VI_DEF|P_VIM,
-                           (char_u *)&p_sj, PV_NONE,
+                           (char_u *)&p_sj, PV_NONE, NULL,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"scrolloff",   "so",   P_NUM|P_VI_DEF|P_VIM|P_RALL,
-                           (char_u *)&p_so, PV_SO,
+                           (char_u *)&p_so, PV_SO, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"scrollopt",   "sbo",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_sbo, PV_NONE,
+                           (char_u *)&p_sbo, PV_NONE, NULL,
                            {(char_u *)"ver,jump", (char_u *)0L}
                            SCTX_INIT},
     {"sections",    "sect", P_STRING|P_VI_DEF,
-                           (char_u *)&p_sections, PV_NONE,
+                           (char_u *)&p_sections, PV_NONE, NULL,
                            {(char_u *)"SHNHH HUnhsh", (char_u *)0L}
                            SCTX_INIT},
     {"secure",     NULL,   P_BOOL|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_secure, PV_NONE,
+                           (char_u *)&p_secure, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"selection",   "sel",  P_STRING|P_VI_DEF,
-                           (char_u *)&p_sel, PV_NONE,
+                           (char_u *)&p_sel, PV_NONE, did_set_selection,
                            {(char_u *)"inclusive", (char_u *)0L}
                            SCTX_INIT},
     {"selectmode",  "slm",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_slm, PV_NONE,
+                           (char_u *)&p_slm, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"sessionoptions", "ssop", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_SESSION
                            (char_u *)&p_ssop, PV_NONE,
+                           did_set_sessionoptions,
         {(char_u *)"blank,buffers,curdir,folds,help,options,tabpages,winsize,terminal",
                                                               (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"shell",      "sh",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_sh, PV_NONE,
+                           (char_u *)&p_sh, PV_NONE, NULL,
                            {
 #ifdef VMS
                            (char_u *)"-",
@@ -2147,7 +2186,7 @@ static struct vimoption options[] =
 #endif // VMS
                                (char_u *)0L} SCTX_INIT},
     {"shellcmdflag","shcf", P_STRING|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_shcf, PV_NONE,
+                           (char_u *)&p_shcf, PV_NONE, NULL,
                            {
 #if defined(MSWIN)
                            (char_u *)"/c",
@@ -2157,7 +2196,7 @@ static struct vimoption options[] =
                                (char_u *)0L} SCTX_INIT},
     {"shellpipe",   "sp",   P_STRING|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
-                           (char_u *)&p_sp, PV_NONE,
+                           (char_u *)&p_sp, PV_NONE, NULL,
                            {
 #if defined(UNIX)
                            (char_u *)"| tee",
@@ -2166,35 +2205,35 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"shellquote",  "shq",  P_STRING|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_shq, PV_NONE,
+                           (char_u *)&p_shq, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"shellredir",  "srr",  P_STRING|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_srr, PV_NONE,
+                           (char_u *)&p_srr, PV_NONE, NULL,
                            {(char_u *)">", (char_u *)0L} SCTX_INIT},
     {"shellslash",  "ssl",   P_BOOL|P_VI_DEF,
 #ifdef BACKSLASH_IN_FILENAME
-                           (char_u *)&p_ssl, PV_NONE,
+                           (char_u *)&p_ssl, PV_NONE, did_set_shellslash,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"shelltemp",   "stmp", P_BOOL,
-                           (char_u *)&p_stmp, PV_NONE,
+                           (char_u *)&p_stmp, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"shelltype",   "st",   P_NUM|P_VI_DEF,
 #ifdef AMIGA
-                           (char_u *)&p_st, PV_NONE,
+                           (char_u *)&p_st, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"shellxquote", "sxq",  P_STRING|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_sxq, PV_NONE,
+                           (char_u *)&p_sxq, PV_NONE, NULL,
                            {
 #if defined(UNIX) && defined(USE_SYSTEM)
                            (char_u *)"\"",
@@ -2203,7 +2242,7 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_sxe, PV_NONE,
+                           (char_u *)&p_sxe, PV_NONE, NULL,
                            {
 #if defined(MSWIN)
                            (char_u *)"\"&|<>()@^",
@@ -2212,27 +2251,28 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"shiftround",  "sr",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_sr, PV_NONE,
+                           (char_u *)&p_sr, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"shiftwidth",  "sw",   P_NUM|P_VI_DEF,
                            (char_u *)&p_sw, PV_SW,
+                           did_set_shiftwidth_tabstop,
                            {(char_u *)8L, (char_u *)0L} SCTX_INIT},
     {"shortmess",   "shm",  P_STRING|P_VIM|P_FLAGLIST,
-                           (char_u *)&p_shm, PV_NONE,
+                           (char_u *)&p_shm, PV_NONE, NULL,
                            {(char_u *)"S", (char_u *)"filnxtToOS"}
                            SCTX_INIT},
     {"shortname",   "sn",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_sn, PV_SN,
+                           (char_u *)&p_sn, PV_SN, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"showbreak",   "sbr",  P_STRING|P_VI_DEF|P_RALL,
 #ifdef FEAT_LINEBREAK
-                           (char_u *)&p_sbr, PV_SBR,
+                           (char_u *)&p_sbr, PV_SBR, did_set_showbreak,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"showcmd",            "sc",   P_BOOL|P_VIM,
-                           (char_u *)&p_sc, PV_NONE,
+                           (char_u *)&p_sc, PV_NONE, NULL,
                            {(char_u *)FALSE,
 #ifdef UNIX
                                (char_u *)FALSE
@@ -2241,180 +2281,181 @@ static struct vimoption options[] =
 #endif
                                } SCTX_INIT},
     {"showcmdloc",  "sloc", P_STRING|P_RSTAT,
-                           (char_u *)&p_sloc, PV_NONE,
+                           (char_u *)&p_sloc, PV_NONE, NULL,
                            {(char_u *)"last", (char_u *)"last"} SCTX_INIT},
     {"showfulltag", "sft",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_sft, PV_NONE,
+                           (char_u *)&p_sft, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"showmatch",   "sm",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_sm, PV_NONE,
+                           (char_u *)&p_sm, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"showmode",    "smd",  P_BOOL|P_VIM,
-                           (char_u *)&p_smd, PV_NONE,
+                           (char_u *)&p_smd, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"showtabline", "stal", P_NUM|P_VI_DEF|P_RALL,
-                           (char_u *)&p_stal, PV_NONE,
+                           (char_u *)&p_stal, PV_NONE, did_set_showtabline,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"sidescroll",  "ss",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_ss, PV_NONE,
+                           (char_u *)&p_ss, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"sidescrolloff", "siso", P_NUM|P_VI_DEF|P_VIM|P_RBUF,
-                           (char_u *)&p_siso, PV_SISO,
+                           (char_u *)&p_siso, PV_SISO, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"signcolumn",   "scl",  P_STRING|P_ALLOCED|P_VI_DEF|P_RCLR,
 #ifdef FEAT_SIGNS
-                           (char_u *)VAR_WIN, PV_SCL,
+                           (char_u *)VAR_WIN, PV_SCL, did_set_signcolumn,
                            {(char_u *)"auto", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"slowopen",    "slow", P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"smartcase",   "scs",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_scs, PV_NONE,
+                           (char_u *)&p_scs, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"smartindent", "si",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_si, PV_SI,
+                           (char_u *)&p_si, PV_SI, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"smarttab",    "sta",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_sta, PV_NONE,
+                           (char_u *)&p_sta, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"smoothscroll", "sms", P_BOOL|P_VI_DEF|P_RWIN,
-                           (char_u *)VAR_WIN, PV_SMS,
+                           (char_u *)VAR_WIN, PV_SMS, did_set_smoothscroll,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"softtabstop", "sts",  P_NUM|P_VI_DEF|P_VIM,
-                           (char_u *)&p_sts, PV_STS,
+                           (char_u *)&p_sts, PV_STS, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"sourceany",   NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"spell",      NULL,   P_BOOL|P_VI_DEF|P_RWIN,
 #ifdef FEAT_SPELL
-                           (char_u *)VAR_WIN, PV_SPELL,
+                           (char_u *)VAR_WIN, PV_SPELL, did_set_spell,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"spellcapcheck", "spc", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_spc, PV_SPC,
+                           (char_u *)&p_spc, PV_SPC, did_set_spellcapcheck,
                            {(char_u *)"[.?!]\\_[\\])'\"         ]\\+", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"spellfile",   "spf",  P_STRING|P_EXPAND|P_ALLOCED|P_VI_DEF|P_SECURE
                                                                  |P_ONECOMMA,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_spf, PV_SPF,
+                           (char_u *)&p_spf, PV_SPF, did_set_spellfile,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"spelllang",   "spl",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA
                                                             |P_RBUF|P_EXPAND,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_spl, PV_SPL,
+                           (char_u *)&p_spl, PV_SPL, did_set_spelllang,
                            {(char_u *)"en", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"spelloptions", "spo",  P_STRING|P_ALLOCED|P_VI_DEF
                                                    |P_ONECOMMA|P_NODUP|P_RBUF,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_spo, PV_SPO,
+                           (char_u *)&p_spo, PV_SPO, did_set_spelloptions,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"spellsuggest", "sps", P_STRING|P_VI_DEF|P_EXPAND|P_SECURE|P_ONECOMMA,
 #ifdef FEAT_SPELL
-                           (char_u *)&p_sps, PV_NONE,
+                           (char_u *)&p_sps, PV_NONE, did_set_spellsuggest,
                            {(char_u *)"best", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"splitbelow",  "sb",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_sb, PV_NONE,
+                           (char_u *)&p_sb, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"splitkeep",   "spk",  P_STRING,
-                           (char_u *)&p_spk, PV_NONE,
+                           (char_u *)&p_spk, PV_NONE, NULL,
                            {(char_u *)"cursor", (char_u *)"cursor"} SCTX_INIT},
     {"splitright",  "spr",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_spr, PV_NONE,
+                           (char_u *)&p_spr, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"startofline", "sol",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_sol, PV_NONE,
+                           (char_u *)&p_sol, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"statusline"  ,"stl",  P_STRING|P_VI_DEF|P_ALLOCED|P_RSTAT|P_MLE,
 #ifdef FEAT_STL_OPT
-                           (char_u *)&p_stl, PV_STL,
+                           (char_u *)&p_stl, PV_STL, did_set_statusline,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"suffixes",    "su",   P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_su, PV_NONE,
+                           (char_u *)&p_su, PV_NONE, NULL,
                            {(char_u *)".bak,~,.o,.h,.info,.swp,.obj",
                                (char_u *)0L} SCTX_INIT},
     {"suffixesadd", "sua",  P_STRING|P_VI_DEF|P_ALLOCED|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_sua, PV_SUA,
+                           (char_u *)&p_sua, PV_SUA, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"swapfile",    "swf",  P_BOOL|P_VI_DEF|P_RSTAT,
-                           (char_u *)&p_swf, PV_SWF,
+                           (char_u *)&p_swf, PV_SWF, did_set_swapfile,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"swapsync",    "sws",  P_STRING|P_VI_DEF,
-                           (char_u *)&p_sws, PV_NONE,
+                           (char_u *)&p_sws, PV_NONE, NULL,
                            {(char_u *)"fsync", (char_u *)0L} SCTX_INIT},
     {"switchbuf",   "swb",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_swb, PV_NONE,
+                           (char_u *)&p_swb, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"synmaxcol",   "smc",  P_NUM|P_VI_DEF|P_RBUF,
 #ifdef FEAT_SYN_HL
-                           (char_u *)&p_smc, PV_SMC,
+                           (char_u *)&p_smc, PV_SMC, NULL,
                            {(char_u *)3000L, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"syntax",     "syn",  P_STRING|P_ALLOCED|P_VI_DEF|P_NOGLOB|P_NFNAME,
 #ifdef FEAT_SYN_HL
-                           (char_u *)&p_syn, PV_SYN,
+                           (char_u *)&p_syn, PV_SYN, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"tabline",            "tal",  P_STRING|P_VI_DEF|P_RALL|P_MLE,
 #ifdef FEAT_STL_OPT
-                           (char_u *)&p_tal, PV_NONE,
+                           (char_u *)&p_tal, PV_NONE, did_set_tabline,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"tabpagemax",  "tpm",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_tpm, PV_NONE,
+                           (char_u *)&p_tpm, PV_NONE, NULL,
                            {(char_u *)10L, (char_u *)0L} SCTX_INIT},
     {"tabstop",            "ts",   P_NUM|P_VI_DEF|P_RBUF,
                            (char_u *)&p_ts, PV_TS,
+                           did_set_shiftwidth_tabstop,
                            {(char_u *)8L, (char_u *)0L} SCTX_INIT},
     {"tagbsearch",  "tbs",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_tbs, PV_NONE,
+                           (char_u *)&p_tbs, PV_NONE, NULL,
 #ifdef VMS     // binary searching doesn't appear to work on VMS
                            {(char_u *)0L, (char_u *)0L}
 #else
@@ -2422,25 +2463,25 @@ static struct vimoption options[] =
 #endif
                            SCTX_INIT},
     {"tagcase",            "tc",   P_STRING|P_VIM,
-                           (char_u *)&p_tc, PV_TC,
+                           (char_u *)&p_tc, PV_TC, did_set_tagcase,
                            {(char_u *)"followic", (char_u *)"followic"} SCTX_INIT},
     {"tagfunc",    "tfu",   P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
 #ifdef FEAT_EVAL
-                           (char_u *)&p_tfu, PV_TFU,
+                           (char_u *)&p_tfu, PV_TFU, did_set_tagfunc,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"taglength",   "tl",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_tl, PV_NONE,
+                           (char_u *)&p_tl, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"tagrelative", "tr",   P_BOOL|P_VIM,
-                           (char_u *)&p_tr, PV_NONE,
+                           (char_u *)&p_tr, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)TRUE} SCTX_INIT},
     {"tags",       "tag",  P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_tags, PV_TAGS,
+                           (char_u *)&p_tags, PV_TAGS, NULL,
                            {
 #if defined(FEAT_EMACS_TAGS) && !defined(CASE_INSENSITIVE_FILENAME)
                            (char_u *)"./tags,./TAGS,tags,TAGS",
@@ -2449,85 +2490,85 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"tagstack",    "tgst", P_BOOL|P_VI_DEF,
-                           (char_u *)&p_tgst, PV_NONE,
+                           (char_u *)&p_tgst, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"tcldll",      NULL,   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(DYNAMIC_TCL)
-                           (char_u *)&p_tcldll, PV_NONE,
+                           (char_u *)&p_tcldll, PV_NONE, NULL,
                            {(char_u *)DYNAMIC_TCL_DLL, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"term",       NULL,   P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL,
-                           (char_u *)&T_NAME, PV_NONE,
+                           (char_u *)&T_NAME, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"termbidi", "tbidi",   P_BOOL|P_VI_DEF,
 #ifdef FEAT_ARABIC
-                           (char_u *)&p_tbidi, PV_NONE,
+                           (char_u *)&p_tbidi, PV_NONE, NULL,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"termencoding", "tenc", P_STRING|P_VI_DEF|P_RCLR,
-                           (char_u *)&p_tenc, PV_NONE,
+                           (char_u *)&p_tenc, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"termguicolors", "tgc", P_BOOL|P_VI_DEF|P_VIM|P_RCLR,
 #ifdef FEAT_TERMGUICOLORS
-                           (char_u *)&p_tgc, PV_NONE,
+                           (char_u *)&p_tgc, PV_NONE, did_set_termguicolors,
                            {(char_u *)FALSE, (char_u *)FALSE}
 #else
-                           (char_u*)NULL, PV_NONE,
+                           (char_u*)NULL, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)FALSE}
 #endif
                            SCTX_INIT},
     {"termwinkey", "twk",   P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
 #ifdef FEAT_TERMINAL
-                           (char_u *)VAR_WIN, PV_TWK,
+                           (char_u *)VAR_WIN, PV_TWK, did_set_termwinkey,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"termwinscroll", "twsl", P_NUM|P_VI_DEF|P_VIM|P_RBUF,
 #ifdef FEAT_TERMINAL
-                           (char_u *)&p_twsl, PV_TWSL,
+                           (char_u *)&p_twsl, PV_TWSL, NULL,
                            {(char_u *)10000L, (char_u *)10000L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"termwinsize", "tws",  P_STRING|P_ALLOCED|P_RWIN|P_VI_DEF,
 #ifdef FEAT_TERMINAL
-                           (char_u *)VAR_WIN, PV_TWS,
+                           (char_u *)VAR_WIN, PV_TWS, did_set_termwinsize,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"termwintype", "twt",  P_STRING|P_ALLOCED|P_VI_DEF,
 #if defined(MSWIN) && defined(FEAT_TERMINAL)
-                           (char_u *)&p_twt, PV_NONE,
+                           (char_u *)&p_twt, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"terse",      NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_terse, PV_NONE,
+                           (char_u *)&p_terse, PV_NONE, did_set_terse,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"textauto",    "ta",   P_BOOL|P_VIM,
-                           (char_u *)&p_ta, PV_NONE,
+                           (char_u *)&p_ta, PV_NONE, did_set_textauto,
                            {(char_u *)DFLT_TEXTAUTO, (char_u *)TRUE}
                            SCTX_INIT},
     {"textmode",    "tx",   P_BOOL|P_VI_DEF|P_NO_MKRC,
-                           (char_u *)&p_tx, PV_TX,
+                           (char_u *)&p_tx, PV_TX, did_set_textmode,
                            {
 #ifdef USE_CRNL
                            (char_u *)TRUE,
@@ -2536,105 +2577,108 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"textwidth",   "tw",   P_NUM|P_VI_DEF|P_VIM|P_RBUF,
-                           (char_u *)&p_tw, PV_TW,
+                           (char_u *)&p_tw, PV_TW, did_set_textwidth,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"thesaurus",   "tsr",  P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME,
-                           (char_u *)&p_tsr, PV_TSR,
+                           (char_u *)&p_tsr, PV_TSR, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"thesaurusfunc", "tsrfu",  P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE|P_FUNC,
 #ifdef FEAT_COMPL_FUNC
                            (char_u *)&p_tsrfu, PV_TSRFU,
+                           did_set_thesaurusfunc,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"tildeop",            "top",  P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_to, PV_NONE,
+                           (char_u *)&p_to, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"timeout",            "to",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_timeout, PV_NONE,
+                           (char_u *)&p_timeout, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"timeoutlen",  "tm",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_tm, PV_NONE,
+                           (char_u *)&p_tm, PV_NONE, NULL,
                            {(char_u *)1000L, (char_u *)0L} SCTX_INIT},
     {"title",      NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_title, PV_NONE,
+                           (char_u *)&p_title, PV_NONE, did_set_title_icon,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"titlelen",    NULL,   P_NUM|P_VI_DEF,
-                           (char_u *)&p_titlelen, PV_NONE,
+                           (char_u *)&p_titlelen, PV_NONE, did_set_titlelen,
                            {(char_u *)85L, (char_u *)0L} SCTX_INIT},
     {"titleold",    NULL,   P_STRING|P_VI_DEF|P_GETTEXT|P_SECURE|P_NO_MKRC,
-                           (char_u *)&p_titleold, PV_NONE,
+                           (char_u *)&p_titleold, PV_NONE, NULL,
                            {(char_u *)N_("Thanks for flying Vim"),
                                                               (char_u *)0L}
                            SCTX_INIT},
     {"titlestring", NULL,   P_STRING|P_VI_DEF|P_MLE,
                            (char_u *)&p_titlestring, PV_NONE,
+                           did_set_titlestring,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"toolbar",     "tb",   P_STRING|P_ONECOMMA|P_VI_DEF|P_NODUP,
 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
-                           (char_u *)&p_toolbar, PV_NONE,
+                           (char_u *)&p_toolbar, PV_NONE, did_set_toolbar,
                            {(char_u *)"icons,tooltips", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"toolbariconsize",        "tbis", P_STRING|P_VI_DEF,
 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
                            (char_u *)&p_tbis, PV_NONE,
+                           did_set_toolbariconsize,
                            {(char_u *)"small", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"ttimeout",    NULL,   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_ttimeout, PV_NONE,
+                           (char_u *)&p_ttimeout, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"ttimeoutlen", "ttm",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_ttm, PV_NONE,
+                           (char_u *)&p_ttm, PV_NONE, NULL,
                            {(char_u *)-1L, (char_u *)0L} SCTX_INIT},
     {"ttybuiltin",  "tbi",  P_BOOL|P_VI_DEF,
-                           (char_u *)&p_tbi, PV_NONE,
+                           (char_u *)&p_tbi, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"ttyfast",            "tf",   P_BOOL|P_NO_MKRC|P_VI_DEF,
-                           (char_u *)&p_tf, PV_NONE,
+                           (char_u *)&p_tf, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"ttymouse",    "ttym", P_STRING|P_NODEFAULT|P_NO_MKRC|P_VI_DEF,
 #if defined(UNIX) || defined(VMS)
-                           (char_u *)&p_ttym, PV_NONE,
+                           (char_u *)&p_ttym, PV_NONE, did_set_ttymouse,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"ttyscroll",   "tsl",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_ttyscroll, PV_NONE,
+                           (char_u *)&p_ttyscroll, PV_NONE, NULL,
                            {(char_u *)999L, (char_u *)0L} SCTX_INIT},
     {"ttytype",            "tty",  P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RALL,
-                           (char_u *)&T_NAME, PV_NONE,
+                           (char_u *)&T_NAME, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"undodir",     "udir", P_STRING|P_EXPAND|P_ONECOMMA|P_NODUP|P_SECURE
                                                                    |P_VI_DEF,
 #ifdef FEAT_PERSISTENT_UNDO
-                           (char_u *)&p_udir, PV_NONE,
+                           (char_u *)&p_udir, PV_NONE, NULL,
                            {(char_u *)".", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"undofile",    "udf",  P_BOOL|P_VI_DEF|P_VIM,
 #ifdef FEAT_PERSISTENT_UNDO
-                           (char_u *)&p_udf, PV_UDF,
+                           (char_u *)&p_udf, PV_UDF, did_set_undofile,
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
 #endif
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"undolevels",  "ul",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_ul, PV_UL,
+                           (char_u *)&p_ul, PV_UL, did_set_undolevels,
                            {
 #if defined(UNIX) || defined(MSWIN) || defined(VMS)
                            (char_u *)1000L,
@@ -2643,60 +2687,61 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"undoreload",  "ur",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_ur, PV_NONE,
+                           (char_u *)&p_ur, PV_NONE, NULL,
                            { (char_u *)10000L, (char_u *)0L} SCTX_INIT},
     {"updatecount", "uc",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_uc, PV_NONE,
+                           (char_u *)&p_uc, PV_NONE, did_set_updatecount,
                            {(char_u *)200L, (char_u *)0L} SCTX_INIT},
     {"updatetime",  "ut",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_ut, PV_NONE,
+                           (char_u *)&p_ut, PV_NONE, NULL,
                            {(char_u *)4000L, (char_u *)0L} SCTX_INIT},
     {"varsofttabstop", "vsts",  P_STRING|P_VI_DEF|P_VIM|P_COMMA,
 #ifdef FEAT_VARTABS
                            (char_u *)&p_vsts, PV_VSTS,
+                           did_set_varsofttabstop,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #endif
                            SCTX_INIT},
     {"vartabstop",  "vts",  P_STRING|P_VI_DEF|P_VIM|P_RBUF|P_COMMA,
 #ifdef FEAT_VARTABS
-                           (char_u *)&p_vts, PV_VTS,
+                           (char_u *)&p_vts, PV_VTS, did_set_vartabstop,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)NULL}
 #endif
                            SCTX_INIT},
     {"verbose",            "vbs",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_verbose, PV_NONE,
+                           (char_u *)&p_verbose, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"verbosefile", "vfile", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
-                           (char_u *)&p_vfile, PV_NONE,
+                           (char_u *)&p_vfile, PV_NONE, did_set_verbosefile,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"viewdir",     "vdir", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_SESSION
-                           (char_u *)&p_vdir, PV_NONE,
+                           (char_u *)&p_vdir, PV_NONE, NULL,
                            {(char_u *)DFLT_VDIR, (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"viewoptions", "vop",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #ifdef FEAT_SESSION
-                           (char_u *)&p_vop, PV_NONE,
+                           (char_u *)&p_vop, PV_NONE, NULL,
                            {(char_u *)"folds,options,cursor,curdir",
                                                                  (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"viminfo",            "vi",   P_STRING|P_ONECOMMA|P_NODUP|P_SECURE,
 #ifdef FEAT_VIMINFO
-                           (char_u *)&p_viminfo, PV_NONE,
+                           (char_u *)&p_viminfo, PV_NONE, NULL,
 #if defined(MSWIN)
                            {(char_u *)"", (char_u *)"'100,<50,s10,h,rA:,rB:"}
 #elif defined(AMIGA)
@@ -2706,103 +2751,104 @@ static struct vimoption options[] =
                            {(char_u *)"", (char_u *)"'100,<50,s10,h"}
 #endif
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"viminfofile", "vif",  P_STRING|P_EXPAND|P_ONECOMMA|P_NODUP
                                                            |P_SECURE|P_VI_DEF,
 #ifdef FEAT_VIMINFO
-                           (char_u *)&p_viminfofile, PV_NONE,
+                           (char_u *)&p_viminfofile, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"virtualedit", "ve",   P_STRING|P_ONECOMMA|P_NODUP|P_VI_DEF
                                                            |P_VIM|P_CURSWANT,
-                           (char_u *)&p_ve, PV_VE,
+                           (char_u *)&p_ve, PV_VE, did_set_virtualedit,
                            {(char_u *)"", (char_u *)""}
                            SCTX_INIT},
     {"visualbell",  "vb",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_vb, PV_NONE,
+                           (char_u *)&p_vb, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"w300",       NULL,   P_NUM|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"w1200",      NULL,   P_NUM|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"w9600",      NULL,   P_NUM|P_VI_DEF,
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"warn",       NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_warn, PV_NONE,
+                           (char_u *)&p_warn, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"weirdinvert", "wiv",  P_BOOL|P_VI_DEF|P_RCLR,
-                           (char_u *)&p_wiv, PV_NONE,
+                           (char_u *)&p_wiv, PV_NONE, did_set_weirdinvert,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"whichwrap",   "ww",   P_STRING|P_VIM|P_ONECOMMA|P_FLAGLIST,
-                           (char_u *)&p_ww, PV_NONE,
+                           (char_u *)&p_ww, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)"b,s"} SCTX_INIT},
     {"wildchar",    "wc",   P_NUM|P_VIM,
-                           (char_u *)&p_wc, PV_NONE,
+                           (char_u *)&p_wc, PV_NONE, NULL,
                            {(char_u *)(long)Ctrl_E, (char_u *)(long)TAB}
                            SCTX_INIT},
     {"wildcharm",   "wcm",  P_NUM|P_VI_DEF,
-                           (char_u *)&p_wcm, PV_NONE,
+                           (char_u *)&p_wcm, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"wildignore",  "wig",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_wig, PV_NONE,
+                           (char_u *)&p_wig, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
     {"wildignorecase", "wic", P_BOOL|P_VI_DEF,
-                           (char_u *)&p_wic, PV_NONE,
+                           (char_u *)&p_wic, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"wildmenu",    "wmnu", P_BOOL|P_VI_DEF,
-                           (char_u *)&p_wmnu, PV_NONE,
+                           (char_u *)&p_wmnu, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"wildmode",    "wim",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_wim, PV_NONE,
+                           (char_u *)&p_wim, PV_NONE, did_set_wildmode,
                            {(char_u *)"full", (char_u *)0L} SCTX_INIT},
     {"wildoptions", "wop",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-                           (char_u *)&p_wop, PV_NONE,
+                           (char_u *)&p_wop, PV_NONE, NULL,
                            {(char_u *)"", (char_u *)0L}
                            SCTX_INIT},
     {"winaltkeys",  "wak",  P_STRING|P_VI_DEF,
 #ifdef FEAT_WAK
-                           (char_u *)&p_wak, PV_NONE,
+                           (char_u *)&p_wak, PV_NONE, did_set_winaltkeys,
                            {(char_u *)"menu", (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"wincolor", "wcr",            P_STRING|P_ALLOCED|P_VI_DEF|P_RWIN,
-                           (char_u *)VAR_WIN, PV_WCR,
+                           (char_u *)VAR_WIN, PV_WCR, NULL,
                            {(char_u *)"", (char_u *)NULL}
                            SCTX_INIT},
     {"window",     "wi",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_window, PV_NONE,
+                           (char_u *)&p_window, PV_NONE, did_set_window,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"winheight",   "wh",   P_NUM|P_VI_DEF,
                            (char_u *)&p_wh, PV_NONE,
+                           did_set_winheight_helpheight,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT,
-                           (char_u *)VAR_WIN, PV_WFH,
+                           (char_u *)VAR_WIN, PV_WFH, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"winfixwidth", "wfw", P_BOOL|P_VI_DEF|P_RSTAT,
-                           (char_u *)VAR_WIN, PV_WFW,
+                           (char_u *)VAR_WIN, PV_WFW, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"winminheight", "wmh", P_NUM|P_VI_DEF,
-                           (char_u *)&p_wmh, PV_NONE,
+                           (char_u *)&p_wmh, PV_NONE, did_set_winminheight,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"winminwidth", "wmw", P_NUM|P_VI_DEF,
-                           (char_u *)&p_wmw, PV_NONE,
+                           (char_u *)&p_wmw, PV_NONE, did_set_winminwidth,
                            {(char_u *)1L, (char_u *)0L} SCTX_INIT},
     {"winptydll", NULL,            P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #if defined(MSWIN) && defined(FEAT_TERMINAL)
-                           (char_u *)&p_winptydll, PV_NONE, {
+                           (char_u *)&p_winptydll, PV_NONE, NULL, {
 # ifdef _WIN64
                            (char_u *)"winpty64.dll",
 # else
@@ -2810,30 +2856,30 @@ static struct vimoption options[] =
 # endif
                                (char_u *)0L}
 #else
-                           (char_u *)NULL, PV_NONE,
+                           (char_u *)NULL, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
     {"winwidth",   "wiw",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_wiw, PV_NONE,
+                           (char_u *)&p_wiw, PV_NONE, did_set_winwidth,
                            {(char_u *)20L, (char_u *)0L} SCTX_INIT},
     {"wrap",       NULL,   P_BOOL|P_VI_DEF|P_RWIN,
-                           (char_u *)VAR_WIN, PV_WRAP,
+                           (char_u *)VAR_WIN, PV_WRAP, did_set_wrap,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"wrapmargin",  "wm",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_wm, PV_WM,
+                           (char_u *)&p_wm, PV_WM, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"wrapscan",    "ws",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_ws, PV_NONE,
+                           (char_u *)&p_ws, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"write",      NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_write, PV_NONE,
+                           (char_u *)&p_write, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
     {"writeany",    "wa",   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_wa, PV_NONE,
+                           (char_u *)&p_wa, PV_NONE, NULL,
                            {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
     {"writebackup", "wb",   P_BOOL|P_VI_DEF|P_VIM,
-                           (char_u *)&p_wb, PV_NONE,
+                           (char_u *)&p_wb, PV_NONE, NULL,
                            {
 #ifdef FEAT_WRITEBACKUP
                            (char_u *)TRUE,
@@ -2842,16 +2888,16 @@ static struct vimoption options[] =
 #endif
                                (char_u *)0L} SCTX_INIT},
     {"writedelay",  "wd",   P_NUM|P_VI_DEF,
-                           (char_u *)&p_wd, PV_NONE,
+                           (char_u *)&p_wd, PV_NONE, NULL,
                            {(char_u *)0L, (char_u *)0L} SCTX_INIT},
     {"xtermcodes",  NULL,   P_BOOL|P_VI_DEF,
-                           (char_u *)&p_xtermcodes, PV_NONE,
+                           (char_u *)&p_xtermcodes, PV_NONE, NULL,
                            {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
 
 // terminal output codes
 #define p_term(sss, vvv) \
                            {sss, NULL, P_STRING|P_VI_DEF|P_RALL|P_SECURE, \
-                           (char_u *)&vvv, PV_NONE, \
+                           (char_u *)&vvv, PV_NONE, NULL, \
                            {(char_u *)"", (char_u *)0L} SCTX_INIT},
 
     p_term("t_AB", T_CAB)
@@ -2947,7 +2993,7 @@ static struct vimoption options[] =
 // terminal key codes are not in here
 
     // end marker
-    {NULL, NULL, 0, NULL, PV_NONE, {NULL, NULL} SCTX_INIT}
+    {NULL, NULL, 0, NULL, PV_NONE, NULL, {NULL, NULL} SCTX_INIT}
 };
 
 #define OPTION_COUNT ARRAY_LENGTH(options)
index 8acbbf7c98f098c9499a2c020f62fbb6ba8988d3..71ad1e4b282423d6c413083041f6f0e105fc775e 100644 (file)
@@ -541,7 +541,7 @@ set_string_option(
        saved_newval = vim_strsave(s);
     }
 #endif
-    if ((errmsg = did_set_string_option(opt_idx, varp, oldval, errbuf,
+    if ((errmsg = did_set_string_option(opt_idx, varp, oldval, value, errbuf,
                    opt_flags, &value_checked)) == NULL)
        did_set_option(opt_idx, opt_flags, TRUE, value_checked);
 
@@ -691,22 +691,20 @@ did_set_term(int *opt_idx, long_u *free_oldval)
 /*
  * The 'backupcopy' option is changed.
  */
-    static char *
-did_set_backupcopy(
-    char_u     *oldval,
-    int                opt_flags)
+    char *
+did_set_backupcopy(optset_T *args)
 {
     char_u             *bkc = p_bkc;
     unsigned int       *flags = &bkc_flags;
     char               *errmsg = NULL;
 
-    if (opt_flags & OPT_LOCAL)
+    if (args->os_flags & OPT_LOCAL)
     {
        bkc = curbuf->b_p_bkc;
        flags = &curbuf->b_bkc_flags;
     }
 
-    if ((opt_flags & OPT_LOCAL) && *bkc == NUL)
+    if ((args->os_flags & OPT_LOCAL) && *bkc == NUL)
        // make the local value empty: use the global value
        *flags = 0;
     else
@@ -718,7 +716,8 @@ did_set_backupcopy(
                + (((int)*flags & BKC_NO) != 0) != 1)
        {
            // Must have exactly one of "auto", "yes"  and "no".
-           (void)opt_strings_flags(oldval, p_bkc_values, flags, TRUE);
+           (void)opt_strings_flags(args->os_oldval.string, p_bkc_values,
+                                                                 flags, TRUE);
            errmsg = e_invalid_argument;
        }
     }
@@ -729,8 +728,8 @@ did_set_backupcopy(
 /*
  * The 'backupext' or the 'patchmode' option is changed.
  */
-    static char *
-did_set_backupext_or_patchmode(void)
+    char *
+did_set_backupext_or_patchmode(optset_T *args UNUSED)
 {
     if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
                *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
@@ -739,12 +738,12 @@ did_set_backupext_or_patchmode(void)
     return NULL;
 }
 
-#ifdef FEAT_LINEBREAK
+#if defined(FEAT_LINEBREAK) || defined(PROTO)
 /*
  * The 'breakindentopt' option is changed.
  */
-    static char *
-did_set_breakindentopt(void)
+    char *
+did_set_breakindentopt(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -780,14 +779,15 @@ did_set_isopt(int *did_chartab)
 /*
  * The 'helpfile' option is changed.
  */
-    static void
-did_set_helpfile(void)
+    char *
+did_set_helpfile(optset_T *args UNUSED)
 {
     // May compute new values for $VIM and $VIMRUNTIME
     if (didset_vim)
        vim_unsetenv_ext((char_u *)"VIM");
     if (didset_vimruntime)
        vim_unsetenv_ext((char_u *)"VIMRUNTIME");
+    return NULL;
 }
 
 #ifdef FEAT_SYN_HL
@@ -804,12 +804,12 @@ did_set_cursorlineopt(char_u **varp)
 }
 #endif
 
-#ifdef FEAT_MULTI_LANG
+#if defined(FEAT_MULTI_LANG) || defined(PROTO)
 /*
  * The 'helplang' option is changed.
  */
-    static char *
-did_set_helplang(void)
+    char *
+did_set_helplang(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -832,8 +832,8 @@ did_set_helplang(void)
 /*
  * The 'highlight' option is changed.
  */
-    static char *
-did_set_highlight(void)
+    char *
+did_set_highlight(optset_T *args UNUSED)
 {
     if (highlight_changed() == FAIL)
        return e_invalid_argument;      // invalid flags
@@ -868,15 +868,16 @@ did_set_opt_strings(char_u *val, char **values, int list)
 /*
  * The 'sessionoptions' option is changed.
  */
-    static char *
-did_set_sessionoptions(char_u *oldval)
+    char *
+did_set_sessionoptions(optset_T *args)
 {
     if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
        return e_invalid_argument;
     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);
+       (void)opt_strings_flags(args->os_oldval.string, p_ssop_values,
+                                                       &ssop_flags, TRUE);
        return e_invalid_argument;
     }
 
@@ -887,8 +888,8 @@ did_set_sessionoptions(char_u *oldval)
 /*
  * The 'ambiwidth' option is changed.
  */
-    static char *
-did_set_ambiwidth(void)
+    char *
+did_set_ambiwidth(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
        return e_invalid_argument;
@@ -899,8 +900,8 @@ did_set_ambiwidth(void)
 /*
  * The 'background' option is changed.
  */
-    static char *
-did_set_background(void)
+    char *
+did_set_background(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_bg, p_bg_values, FALSE) == FAIL)
        return e_invalid_argument;
@@ -935,20 +936,20 @@ did_set_background(void)
 /*
  * The 'wildmode' option is changed.
  */
-    static char *
-did_set_wildmode(void)
+    char *
+did_set_wildmode(optset_T *args UNUSED)
 {
     if (check_opt_wim() == FAIL)
        return e_invalid_argument;
     return NULL;
 }
 
-#ifdef FEAT_WAK
+#if defined(FEAT_WAK) || defined(PROTO)
 /*
  * The 'winaltkeys' option is changed.
  */
-    static char *
-did_set_winaltkeys(void)
+    char *
+did_set_winaltkeys(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -971,8 +972,8 @@ did_set_winaltkeys(void)
 /*
  * The 'eventignore' option is changed.
  */
-    static char *
-did_set_eventignore(void)
+    char *
+did_set_eventignore(optset_T *args UNUSED)
 {
     if (check_ei() == FAIL)
        return e_invalid_argument;
@@ -1066,12 +1067,12 @@ did_set_encoding(char_u **varp, char_u **gvarp, int opt_flags)
     return errmsg;
 }
 
-#if defined(FEAT_POSTSCRIPT)
+#if defined(FEAT_POSTSCRIPT) || defined(PROTO)
 /*
  * The 'printencoding' option is changed.
  */
-    static void
-did_set_printencoding(void)
+    char *
+did_set_printencoding(optset_T *args UNUSED)
 {
     char_u     *s, *p;
 
@@ -1093,15 +1094,17 @@ did_set_printencoding(void)
                *s = TOLOWER_ASC(*s);
        }
     }
+
+    return NULL;
 }
 #endif
 
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) || defined(PROTO)
 /*
  * The 'imactivatekey' option is changed.
  */
-    static char *
-did_set_imactivatekey(void)
+    char *
+did_set_imactivatekey(optset_T *args UNUSED)
 {
     if (!im_xim_isvalid_imactivate())
        return e_invalid_argument;
@@ -1170,12 +1173,12 @@ did_set_keymap(char_u **varp, int opt_flags, int *value_checked)
 /*
  * The 'fileformat' option is changed.
  */
-    static char *
-did_set_fileformat(char_u **varp, char_u *oldval, int opt_flags)
+    char *
+did_set_fileformat(optset_T *args)
 {
-    if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL))
+    if (!curbuf->b_p_ma && !(args->os_flags & OPT_GLOBAL))
        return e_cannot_make_changes_modifiable_is_off;
-    else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
+    else if (check_opt_strings(args->os_varp, p_ff_values, FALSE) != OK)
        return e_invalid_argument;
 
     // may also change 'textmode'
@@ -1188,7 +1191,7 @@ did_set_fileformat(char_u **varp, char_u *oldval, int opt_flags)
     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')
+    if (get_fileformat(curbuf) == EOL_MAC || *args->os_oldval.string == 'm')
        redraw_curbuf_later(UPD_NOT_VALID);
 
     return NULL;
@@ -1197,8 +1200,8 @@ did_set_fileformat(char_u **varp, char_u *oldval, int opt_flags)
 /*
  * The 'fileformats' option is changed.
  */
-    static char *
-did_set_fileformats(void)
+    char *
+did_set_fileformats(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
        return e_invalid_argument;
@@ -1212,36 +1215,38 @@ did_set_fileformats(void)
     return NULL;
 }
 
-#if defined(FEAT_CRYPT)
+#if defined(FEAT_CRYPT) || defined(PROTO)
 /*
  * The 'cryptkey' option is changed.
  */
-    static void
-did_set_cryptkey(char_u *oldval)
+    char *
+did_set_cryptkey(optset_T *args)
 {
     // Make sure the ":set" command doesn't show the new value in the
     // history.
     remove_key_from_history();
 
-    if (STRCMP(curbuf->b_p_key, oldval) != 0)
+    if (STRCMP(curbuf->b_p_key, args->os_oldval.string) != 0)
     {
        // Need to update the swapfile.
-       ml_set_crypt_key(curbuf, oldval,
+       ml_set_crypt_key(curbuf, args->os_oldval.string,
                *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
        changed_internal();
     }
+
+    return NULL;
 }
 
 /*
  * The 'cryptmethod' option is changed.
  */
-    static char *
-did_set_cryptmethod(char_u *oldval, int opt_flags)
+    char *
+did_set_cryptmethod(optset_T *args)
 {
     char_u  *p;
     char_u  *s;
 
-    if (opt_flags & OPT_LOCAL)
+    if (args->os_flags & OPT_LOCAL)
        p = curbuf->b_p_cm;
     else
        p = p_cm;
@@ -1259,7 +1264,7 @@ did_set_cryptmethod(char_u *oldval, int opt_flags)
     // When using ":set cm=name" the local value is going to be empty.
     // Do that here, otherwise the crypt functions will still use the
     // local value.
-    if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+    if ((args->os_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
     {
        free_string_option(curbuf->b_p_cm);
        curbuf->b_p_cm = empty_option;
@@ -1268,10 +1273,10 @@ did_set_cryptmethod(char_u *oldval, int opt_flags)
     // Need to update the swapfile when the effective method changed.
     // Set "s" to the effective old value, "p" to the effective new
     // method and compare.
-    if ((opt_flags & OPT_LOCAL) && *oldval == NUL)
+    if ((args->os_flags & OPT_LOCAL) && *args->os_oldval.string == NUL)
        s = p_cm;  // was previously using the global value
     else
-       s = oldval;
+       s = args->os_oldval.string;
     if (*curbuf->b_p_cm == NUL)
        p = p_cm;  // is now using the global value
     else
@@ -1281,13 +1286,14 @@ did_set_cryptmethod(char_u *oldval, int opt_flags)
 
     // If the global value changes need to update the swapfile for all
     // buffers using that value.
-    if ((opt_flags & OPT_GLOBAL) && STRCMP(p_cm, oldval) != 0)
+    if ((args->os_flags & OPT_GLOBAL)
+           && STRCMP(p_cm, args->os_oldval.string) != 0)
     {
        buf_T   *buf;
 
        FOR_ALL_BUFFERS(buf)
            if (buf != curbuf && *buf->b_p_cm == NUL)
-               ml_set_crypt_key(buf, buf->b_p_key, oldval);
+               ml_set_crypt_key(buf, buf->b_p_key, args->os_oldval.string);
     }
     return NULL;
 }
@@ -1296,14 +1302,14 @@ did_set_cryptmethod(char_u *oldval, int opt_flags)
 /*
  * The 'matchpairs' option is changed.
  */
-    static char *
-did_set_matchpairs(char_u **varp)
+    char *
+did_set_matchpairs(optset_T *args)
 {
     char_u     *p;
 
     if (has_mbyte)
     {
-       for (p = *varp; *p != NUL; ++p)
+       for (p = args->os_varp; *p != NUL; ++p)
        {
            int x2 = -1;
            int x3 = -1;
@@ -1325,7 +1331,7 @@ did_set_matchpairs(char_u **varp)
     else
     {
        // Check for "x:y,x:y"
-       for (p = *varp; *p != NUL; p += 4)
+       for (p = args->os_varp; *p != NUL; p += 4)
        {
            if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
                return e_invalid_argument;
@@ -1419,8 +1425,8 @@ did_set_global_listfillchars(char_u **varp, int opt_flags)
 /*
  * The 'verbosefile' option is changed.
  */
-    static char *
-did_set_verbosefile(void)
+    char *
+did_set_verbosefile(optset_T *args UNUSED)
 {
     verbose_stop();
     if (*p_vfile != NUL && verbose_open() == FAIL)
@@ -1560,16 +1566,16 @@ did_set_term_option(char_u **varp, int *did_swaptcap UNUSED)
     }
 }
 
-#ifdef FEAT_LINEBREAK
+#if defined(FEAT_LINEBREAK) || defined(PROTO)
 /*
  * The 'showbreak' option is changed.
  */
-    static char *
-did_set_showbreak(char_u **varp)
+    char *
+did_set_showbreak(optset_T *args)
 {
     char_u     *s;
 
-    for (s = *varp; *s; )
+    for (s = args->os_varp; *s; )
     {
        if (ptr2cells(s) != 1)
            return e_showbreak_contains_unprintable_or_wide_character;
@@ -1580,12 +1586,12 @@ did_set_showbreak(char_u **varp)
 }
 #endif
 
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI) || defined(PROTO)
 /*
  * The 'guifont' option is changed.
  */
-    static char *
-did_set_guifont(char_u *oldval UNUSED)
+    char *
+did_set_guifont(optset_T *args UNUSED)
 {
     char_u     *p;
     char       *errmsg = NULL;
@@ -1599,9 +1605,9 @@ did_set_guifont(char_u *oldval UNUSED)
        // give an error message.
        if (STRCMP(p, "*") == 0)
        {
-           p = gui_mch_font_dialog(oldval);
+           p = gui_mch_font_dialog(args->os_oldval.string);
            free_string_option(p_guifont);
-           p_guifont = (p != NULL) ? p : vim_strsave(oldval);
+           p_guifont = (p != NULL) ? p : vim_strsave(args->os_oldval.string);
        }
 # endif
        if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
@@ -1612,7 +1618,7 @@ did_set_guifont(char_u *oldval UNUSED)
                // Dialog was cancelled: Keep the old value without giving
                // an error message.
                free_string_option(p_guifont);
-               p_guifont = vim_strsave(oldval);
+               p_guifont = vim_strsave(args->os_oldval.string);
            }
            else
 # endif
@@ -1623,12 +1629,12 @@ did_set_guifont(char_u *oldval UNUSED)
     return errmsg;
 }
 
-# ifdef FEAT_XFONTSET
+# if defined(FEAT_XFONTSET) || defined(PROTO)
 /*
  * The 'guifontset' option is changed.
  */
-    static char *
-did_set_guifontset()
+    char *
+did_set_guifontset(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -1644,8 +1650,8 @@ did_set_guifontset()
 /*
  * The 'guifontwide' option is changed.
  */
-    static char *
-did_set_guifontwide(void)
+    char *
+did_set_guifontwide(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -1658,17 +1664,21 @@ did_set_guifontwide(void)
 }
 #endif
 
-#if defined(FEAT_GUI_GTK)
-    static void
-did_set_guiligatures(void)
+#if defined(FEAT_GUI_GTK) || defined(PROTO)
+/*
+ * The 'guiligatures' option is changed.
+ */
+    char *
+did_set_guiligatures(optset_T *args UNUSED)
 {
     gui_set_ligatures();
+    return NULL;
 }
 #endif
 
-#ifdef FEAT_MOUSESHAPE
-    static char *
-did_set_mouseshape(void)
+#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
+    char *
+did_set_mouseshape(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -1682,46 +1692,81 @@ did_set_mouseshape(void)
 /*
  * The 'titlestring' or the 'iconstring' option is changed.
  */
-    static void
-did_set_titleiconstring(char_u **varp UNUSED)
+    static char *
+did_set_titleiconstring(optset_T *args UNUSED, int flagval UNUSED)
 {
 #ifdef FEAT_STL_OPT
-    int        flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
-
     // NULL => statusline syntax
-    if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL)
+    if (vim_strchr(args->os_varp, '%')
+                                   && check_stl_option(args->os_varp) == NULL)
        stl_syntax |= flagval;
     else
        stl_syntax &= ~flagval;
 #endif
     did_set_title();
+
+    return NULL;
+}
+
+/*
+ * The 'titlestring' option is changed.
+ */
+    char *
+did_set_titlestring(optset_T *args)
+{
+    int flagval = 0;
+
+#ifdef FEAT_STL_OPT
+    flagval = STL_IN_TITLE;
+#endif
+    return did_set_titleiconstring(args, flagval);
+}
+
+/*
+ * The 'iconstring' option is changed.
+ */
+    char *
+did_set_iconstring(optset_T *args)
+{
+    int flagval = 0;
+
+#ifdef FEAT_STL_OPT
+    flagval = STL_IN_ICON;
+#endif
+
+    return did_set_titleiconstring(args, flagval);
 }
 
 #ifdef FEAT_GUI
 /*
  * The 'guioptions' option is changed.
  */
-    static void
-did_set_guioptions(char_u *oldval)
+    char *
+did_set_guioptions(optset_T *args)
 {
-    gui_init_which_components(oldval);
+    gui_init_which_components(args->os_oldval.string);
+    return NULL;
 }
 #endif
 
 #if defined(FEAT_GUI_TABLINE)
-    static void
-did_set_guitablabel()
+/*
+ * The 'guitablabel' option is changed.
+ */
+    char *
+did_set_guitablabel(optset_T *args UNUSED)
 {
     redraw_tabline = TRUE;
+    return NULL;
 }
 #endif
 
-#if defined(UNIX) || defined(VMS)
+#if defined(UNIX) || defined(VMS) || defined(PROTO)
 /*
  * The 'ttymouse' option is changed.
  */
-    static char *
-did_set_ttymouse(void)
+    char *
+did_set_ttymouse(optset_T *args UNUSED)
 {
     char *errmsg = NULL;
 
@@ -1742,8 +1787,8 @@ did_set_ttymouse(void)
 /*
  * The 'selection' option is changed.
  */
-    static char *
-did_set_selection(void)
+    char *
+did_set_selection(optset_T *args UNUSED)
 {
     if (*p_sel == NUL
            || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
@@ -1752,12 +1797,12 @@ did_set_selection(void)
     return NULL;
 }
 
-#ifdef FEAT_BROWSE
+#if defined(FEAT_BROWSE) || defined(PROTO)
 /*
  * The 'browsedir' option is changed.
  */
-    static char *
-did_set_browsedir(void)
+    char *
+did_set_browsedir(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
            && !mch_isdir(p_bsdir))
@@ -1770,8 +1815,8 @@ did_set_browsedir(void)
 /*
  * The 'keymodel' option is changed.
  */
-    static char *
-did_set_keymodel(void)
+    char *
+did_set_keymodel(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
        return e_invalid_argument;
@@ -1784,8 +1829,8 @@ did_set_keymodel(void)
 /*
  * The 'keyprotocol' option is changed.
  */
-    static char *
-did_set_keyprotocol(void)
+    char *
+did_set_keyprotocol(optset_T *args UNUSED)
 {
     if (match_keyprotocol(NULL) == KEYPROTOCOL_FAIL)
        return e_invalid_argument;
@@ -1796,8 +1841,8 @@ did_set_keyprotocol(void)
 /*
  * The 'mousemodel' option is changed.
  */
-    static char *
-did_set_mousemodel(void)
+    char *
+did_set_mousemodel(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
        return e_invalid_argument;
@@ -1814,8 +1859,8 @@ did_set_mousemodel(void)
 /*
  * The 'display' option is changed.
  */
-    static char *
-did_set_display(void)
+    char *
+did_set_display(optset_T *args UNUSED)
 {
     if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
        return e_invalid_argument;
@@ -1824,14 +1869,14 @@ did_set_display(void)
     return NULL;
 }
 
-#ifdef FEAT_SPELL
+#if defined(FEAT_SPELL) || defined(PROTO)
 /*
  * The 'spellfile' option is changed.
  */
-    static char *
-did_set_spellfile(char_u **varp)
+    char *
+did_set_spellfile(optset_T *args)
 {
-    if (!valid_spellfile(*varp))
+    if (!valid_spellfile(args->os_varp))
        return e_invalid_argument;
 
     // If there is a window for this buffer in which 'spell' is set load the
@@ -1842,10 +1887,10 @@ did_set_spellfile(char_u **varp)
 /*
  * The 'spell' option is changed.
  */
-    static char *
-did_set_spell(char_u **varp)
+    char *
+did_set_spelllang(optset_T *args)
 {
-    if (!valid_spelllang(*varp))
+    if (!valid_spelllang(args->os_varp))
        return e_invalid_argument;
 
     // If there is a window for this buffer in which 'spell' is set load the
@@ -1856,8 +1901,8 @@ did_set_spell(char_u **varp)
 /*
  * The 'spellcapcheck' option is changed.
  */
-    static char *
-did_set_spellcapcheck(void)
+    char *
+did_set_spellcapcheck(optset_T *args UNUSED)
 {
     // compile the regexp program.
     return compile_cap_prog(curwin->w_s);
@@ -1866,10 +1911,10 @@ did_set_spellcapcheck(void)
 /*
  * The 'spelloptions' option is changed.
  */
-    static char *
-did_set_spelloptions(char_u **varp)
+    char *
+did_set_spelloptions(optset_T *args)
 {
-    if (**varp != NUL && STRCMP("camel", *varp) != 0)
+    if (*args->os_varp != NUL && STRCMP("camel", args->os_varp) != 0)
        return e_invalid_argument;
 
     return NULL;
@@ -1878,8 +1923,8 @@ did_set_spelloptions(char_u **varp)
 /*
  * The 'spellsuggest' option is changed.
  */
-    static char *
-did_set_spellsuggest(void)
+    char *
+did_set_spellsuggest(optset_T *args UNUSED)
 {
     if (spell_check_sps() != OK)
        return e_invalid_argument;
@@ -1890,8 +1935,8 @@ did_set_spellsuggest(void)
 /*
  * The 'mkspellmem' option is changed.
  */
-    static char *
-did_set_mkspellmem(void)
+    char *
+did_set_mkspellmem(optset_T *args UNUSED)
 {
     if (spell_check_msm() != OK)
        return e_invalid_argument;
@@ -1903,8 +1948,8 @@ did_set_mkspellmem(void)
 /*
  * The 'buftype' option is changed.
  */
-    static char *
-did_set_buftype(void)
+    char *
+did_set_buftype(optset_T *args UNUSED)
 {
     if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
        return e_invalid_argument;
@@ -1923,18 +1968,19 @@ did_set_buftype(void)
 #ifdef FEAT_STL_OPT
 /*
  * The 'statusline' or the 'tabline' or the 'rulerformat' option is changed.
+ * "rulerformat" is TRUE if the 'rulerformat' option is changed.
  */
     static char *
-did_set_statusline(char_u **varp)
+did_set_statustabline_rulerformat(optset_T *args, int rulerformat)
 {
     char_u     *s;
     char       *errmsg = NULL;
     int                wid;
 
-    if (varp == &p_ruf)        // reset ru_wid first
+    if (rulerformat)   // reset ru_wid first
        ru_wid = 0;
-    s = *varp;
-    if (varp == &p_ruf && *s == '%')
+    s = args->os_varp;
+    if (rulerformat && *s == '%')
     {
        // set ru_wid if 'ruf' starts with "%99("
        if (*++s == '-')        // ignore a '-'
@@ -1946,13 +1992,41 @@ did_set_statusline(char_u **varp)
            errmsg = check_stl_option(p_ruf);
     }
     // check 'statusline' or 'tabline' only if it doesn't start with "%!"
-    else if (varp == &p_ruf || s[0] != '%' || s[1] != '!')
+    else if (rulerformat || s[0] != '%' || s[1] != '!')
        errmsg = check_stl_option(s);
-    if (varp == &p_ruf && errmsg == NULL)
+    if (rulerformat && errmsg == NULL)
        comp_col();
 
     return errmsg;
 }
+
+/*
+ * The 'statusline' option is changed.
+ */
+    char *
+did_set_statusline(optset_T *args)
+{
+    return did_set_statustabline_rulerformat(args, FALSE);
+}
+
+/*
+ * The 'tabline' option is changed.
+ */
+    char *
+did_set_tabline(optset_T *args)
+{
+    return did_set_statustabline_rulerformat(args, FALSE);
+}
+
+
+/*
+ * The 'rulerformat' option is changed.
+ */
+    char *
+did_set_rulerformat(optset_T *args)
+{
+    return did_set_statustabline_rulerformat(args, TRUE);
+}
 #endif
 
 /*
@@ -2003,8 +2077,8 @@ did_set_complete(char_u **varp, char *errbuf)
 /*
  * The 'completeopt' option is changed.
  */
-    static char *
-did_set_completeopt(void)
+    char *
+did_set_completeopt(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
        return e_invalid_argument;
@@ -2013,12 +2087,12 @@ did_set_completeopt(void)
     return NULL;
 }
 
-#ifdef BACKSLASH_IN_FILENAME
+#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
 /*
  * The 'completeslash' option is changed.
  */
-    static char *
-did_set_completeslash(void)
+    char *
+did_set_completeslash(optset_T *args UNUSED)
 {
     if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK
            || check_opt_strings(curbuf->b_p_csl, p_csl_values, FALSE) != OK)
@@ -2028,18 +2102,18 @@ did_set_completeslash(void)
 }
 #endif
 
-#ifdef FEAT_SIGNS
+#if defined(FEAT_SIGNS) || defined(PROTO)
 /*
  * The 'signcolumn' option is changed.
  */
-    static char *
-did_set_signcolumn(char_u **varp, char_u *oldval)
+    char *
+did_set_signcolumn(optset_T *args)
 {
-    if (check_opt_strings(*varp, p_scl_values, FALSE) != OK)
+    if (check_opt_strings(args->os_varp, p_scl_values, FALSE) != OK)
        return e_invalid_argument;
     // 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')
+    if (((*args->os_oldval.string == 'n' && args->os_oldval.string[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;
@@ -2048,12 +2122,12 @@ did_set_signcolumn(char_u **varp, char_u *oldval)
 }
 #endif
 
-#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
+#if (defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)) || defined(PROTO)
 /*
  * The 'toolbar' option is changed.
  */
-    static char *
-did_set_toolbar(void)
+    char *
+did_set_toolbar(optset_T *args UNUSED)
 {
     if (opt_strings_flags(p_toolbar, p_toolbar_values,
                &toolbar_flags, TRUE) != OK)
@@ -2066,12 +2140,12 @@ did_set_toolbar(void)
 }
 #endif
 
-#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
+#if (defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)) || defined(PROTO)
 /*
  * The 'toolbariconsize' option is changed.  GTK+ 2 only.
  */
-    static char *
-did_set_toolbariconsize(void)
+    char *
+did_set_toolbariconsize(optset_T *args UNUSED)
 {
     if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
        return e_invalid_argument;
@@ -2086,8 +2160,8 @@ did_set_toolbariconsize(void)
 /*
  * The 'pastetoggle' option is changed.
  */
-    static void
-did_set_pastetoggle(void)
+    char *
+did_set_pastetoggle(optset_T *args UNUSED)
 {
     char_u     *p;
 
@@ -2102,13 +2176,15 @@ did_set_pastetoggle(void)
            p_pt = p;
        }
     }
+
+    return NULL;
 }
 
 /*
  * The 'backspace' option is changed.
  */
-    static char *
-did_set_backspace(void)
+    char *
+did_set_backspace(optset_T *args UNUSED)
 {
     if (VIM_ISDIGIT(*p_bs))
     {
@@ -2124,13 +2200,13 @@ did_set_backspace(void)
 /*
  * The 'tagcase' option is changed.
  */
-    static char *
-did_set_tagcase(int opt_flags)
+    char *
+did_set_tagcase(optset_T *args)
 {
     unsigned int       *flags;
     char_u             *p;
 
-    if (opt_flags & OPT_LOCAL)
+    if (args->os_flags & OPT_LOCAL)
     {
        p = curbuf->b_p_tc;
        flags = &curbuf->b_tc_flags;
@@ -2141,7 +2217,7 @@ did_set_tagcase(int opt_flags)
        flags = &tc_flags;
     }
 
-    if ((opt_flags & OPT_LOCAL) && *p == NUL)
+    if ((args->os_flags & OPT_LOCAL) && *p == NUL)
        // make the local value empty: use the global value
        *flags = 0;
     else if (*p == NUL
@@ -2151,12 +2227,12 @@ did_set_tagcase(int opt_flags)
     return NULL;
 }
 
-#ifdef FEAT_DIFF
+#if defined(FEAT_DIFF) || defined(PROTO)
 /*
  * The 'diffopt' option is changed.
  */
-    static char *
-did_set_diffopt(void)
+    char *
+did_set_diffopt(optset_T *args UNUSED)
 {
     if (diffopt_changed() == FAIL)
        return e_invalid_argument;
@@ -2165,14 +2241,14 @@ did_set_diffopt(void)
 }
 #endif
 
-#ifdef FEAT_FOLDING
+#if defined(FEAT_FOLDING) || defined(PROTO)
 /*
  * The 'foldmethod' option is changed.
  */
-    static char *
-did_set_foldmethod(char_u **varp)
+    char *
+did_set_foldmethod(optset_T *args)
 {
-    if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
+    if (check_opt_strings(args->os_varp, p_fdm_values, FALSE) != OK
            || *curwin->w_p_fdm == NUL)
        return e_invalid_argument;
 
@@ -2185,15 +2261,15 @@ did_set_foldmethod(char_u **varp)
 /*
  * The 'foldmarker' option is changed.
  */
-    static char *
-did_set_foldmarker(char_u **varp)
+    char *
+did_set_foldmarker(optset_T *args)
 {
     char_u     *p;
 
-    p = vim_strchr(*varp, ',');
+    p = vim_strchr(args->os_varp, ',');
     if (p == NULL)
        return e_comma_required;
-    else if (p == *varp || p[1] == NUL)
+    else if (p == args->os_varp || p[1] == NUL)
        return e_invalid_argument;
     else if (foldmethodIsMarker(curwin))
        foldUpdateAll(curwin);
@@ -2204,10 +2280,10 @@ did_set_foldmarker(char_u **varp)
 /*
  * The 'commentstring' option is changed.
  */
-    static char *
-did_set_commentstring(char_u **varp)
+    char *
+did_set_commentstring(optset_T *args)
 {
-    if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
+    if (*args->os_varp != NUL && strstr((char *)args->os_varp, "%s") == NULL)
        return e_commentstring_must_be_empty_or_contain_str;
 
     return NULL;
@@ -2216,37 +2292,38 @@ did_set_commentstring(char_u **varp)
 /*
  * The 'foldignore' option is changed.
  */
-    static void
-did_set_foldignore(void)
+    char *
+did_set_foldignore(optset_T *args UNUSED)
 {
     if (foldmethodIsIndent(curwin))
        foldUpdateAll(curwin);
+    return NULL;
 }
 #endif
 
 /*
  * The 'virtualedit' option is changed.
  */
-    static char *
-did_set_virtualedit(char_u *oldval, int opt_flags)
+    char *
+did_set_virtualedit(optset_T *args)
 {
     char_u             *ve = p_ve;
     unsigned int       *flags = &ve_flags;
 
-    if (opt_flags & OPT_LOCAL)
+    if (args->os_flags & OPT_LOCAL)
     {
        ve = curwin->w_p_ve;
        flags = &curwin->w_ve_flags;
     }
 
-    if ((opt_flags & OPT_LOCAL) && *ve == NUL)
+    if ((args->os_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)
            return e_invalid_argument;
-       else if (STRCMP(ve, oldval) != 0)
+       else if (STRCMP(ve, args->os_oldval.string) != 0)
        {
            // Recompute cursor position in case the new 've' setting
            // changes something.
@@ -2258,12 +2335,12 @@ did_set_virtualedit(char_u *oldval, int opt_flags)
     return NULL;
 }
 
-#if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
+#if (defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)) || defined(PROTO)
 /*
  * The 'cscopequickfix' option is changed.
  */
-    static char *
-did_set_cscopequickfix(void)
+    char *
+did_set_cscopequickfix(optset_T *args UNUSED)
 {
     char_u     *p;
 
@@ -2291,32 +2368,34 @@ did_set_cscopequickfix(void)
 /*
  * The 'cinoptions' option is changed.
  */
-    static void
-did_set_cinoptions(void)
+    char *
+did_set_cinoptions(optset_T *args UNUSED)
 {
     // TODO: recognize errors
     parse_cino(curbuf);
+
+    return NULL;
 }
 
 /*
  * The 'lispoptions' option is changed.
  */
-    static char *
-did_set_lispoptions(char_u **varp)
+    char *
+did_set_lispoptions(optset_T *args)
 {
-    if (**varp != NUL && STRCMP(*varp, "expr:0") != 0
-           && STRCMP(*varp, "expr:1") != 0)
+    if (*args->os_varp != NUL && STRCMP(args->os_varp, "expr:0") != 0
+           && STRCMP(args->os_varp, "expr:1") != 0)
        return e_invalid_argument;
 
     return NULL;
 }
 
-#if defined(FEAT_RENDER_OPTIONS)
+#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
 /*
  * The 'renderoptions' option is changed.
  */
-    static char *
-did_set_renderoptions(void)
+    char *
+did_set_renderoptions(optset_T *args UNUSED)
 {
     if (!gui_mch_set_rendering_options(p_rop))
        return e_invalid_argument;
@@ -2347,12 +2426,12 @@ did_set_filetype_or_syntax(
     return NULL;
 }
 
-#ifdef FEAT_TERMINAL
+#if defined(FEAT_TERMINAL) || defined(PROTO)
 /*
  * The 'termwinkey' option is changed.
  */
-    static char *
-did_set_termwinkey(void)
+    char *
+did_set_termwinkey(optset_T *args UNUSED)
 {
     if (*curwin->w_p_twk != NUL
            && string_to_key(curwin->w_p_twk, TRUE) == 0)
@@ -2364,8 +2443,8 @@ did_set_termwinkey(void)
 /*
  * The 'termwinsize' option is changed.
  */
-    static char *
-did_set_termwinsize(void)
+    char *
+did_set_termwinsize(optset_T *args UNUSED)
 {
     char_u     *p;
 
@@ -2382,16 +2461,16 @@ did_set_termwinsize(void)
 }
 #endif
 
-#ifdef FEAT_VARTABS
+#if defined(FEAT_VARTABS) || defined(PROTO)
 /*
  * The 'varsofttabstop' option is changed.
  */
-    static char *
-did_set_varsofttabstop(char_u **varp)
+    char *
+did_set_varsofttabstop(optset_T *args)
 {
     char_u *cp;
 
-    if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
+    if (!(args->os_varp[0]) || (args->os_varp[0] == '0' && !(args->os_varp[1])))
     {
        if (curbuf->b_p_vsts_array)
        {
@@ -2401,17 +2480,17 @@ did_set_varsofttabstop(char_u **varp)
     }
     else
     {
-       for (cp = *varp; *cp; ++cp)
+       for (cp = args->os_varp; *cp; ++cp)
        {
            if (vim_isdigit(*cp))
                continue;
-           if (*cp == ',' && cp > *varp && *(cp-1) != ',')
+           if (*cp == ',' && cp > args->os_varp && *(cp-1) != ',')
                continue;
            return e_invalid_argument;
        }
 
        int *oldarray = curbuf->b_p_vsts_array;
-       if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)) == OK)
+       if (tabstop_set(args->os_varp, &(curbuf->b_p_vsts_array)) == OK)
        {
            if (oldarray)
                vim_free(oldarray);
@@ -2426,12 +2505,12 @@ did_set_varsofttabstop(char_u **varp)
 /*
  * The 'vartabstop' option is changed.
  */
-    static char *
-did_set_vartabstop(char_u **varp)
+    char *
+did_set_vartabstop(optset_T *args)
 {
     char_u *cp;
 
-    if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
+    if (!(args->os_varp[0]) || (args->os_varp[0] == '0' && !(args->os_varp[1])))
     {
        if (curbuf->b_p_vts_array)
        {
@@ -2441,18 +2520,18 @@ did_set_vartabstop(char_u **varp)
     }
     else
     {
-       for (cp = *varp; *cp; ++cp)
+       for (cp = args->os_varp; *cp; ++cp)
        {
            if (vim_isdigit(*cp))
                continue;
-           if (*cp == ',' && cp > *varp && *(cp-1) != ',')
+           if (*cp == ',' && cp > args->os_varp && *(cp-1) != ',')
                continue;
            return e_invalid_argument;
        }
 
        int *oldarray = curbuf->b_p_vts_array;
 
-       if (tabstop_set(*varp, &(curbuf->b_p_vts_array)) == OK)
+       if (tabstop_set(args->os_varp, &(curbuf->b_p_vts_array)) == OK)
        {
            vim_free(oldarray);
 # ifdef FEAT_FOLDING
@@ -2468,12 +2547,12 @@ did_set_vartabstop(char_u **varp)
 }
 #endif
 
-#ifdef FEAT_PROP_POPUP
+#if defined(FEAT_PROP_POPUP) || defined(PROTO)
 /*
  * The 'previewpopup' option is changed.
  */
-    static char *
-did_set_previewpopup(void)
+    char *
+did_set_previewpopup(optset_T *args UNUSED)
 {
     if (parse_previewpopup(NULL) == FAIL)
        return e_invalid_argument;
@@ -2481,12 +2560,12 @@ did_set_previewpopup(void)
     return NULL;
 }
 
-# ifdef FEAT_QUICKFIX
+# if defined(FEAT_QUICKFIX) || defined(PROTO)
 /*
  * The 'completepopup' option is changed.
  */
-    static char *
-did_set_completepopup(void)
+    char *
+did_set_completepopup(optset_T *args UNUSED)
 {
     if (parse_completepopup(NULL) == FAIL)
        return e_invalid_argument;
@@ -2629,6 +2708,7 @@ did_set_string_option(
     int                opt_idx,                // index in options[] table
     char_u     **varp,                 // pointer to the option variable
     char_u     *oldval,                // previous value of the option
+    char_u     *value,                 // new value of the option
     char       *errbuf,                // buffer for errors, or NULL
     int                opt_flags,              // OPT_LOCAL and/or OPT_GLOBAL
     int                *value_checked)         // value was checked to be safe, no
@@ -2638,12 +2718,9 @@ did_set_string_option(
     int                did_chartab = FALSE;
     char_u     **gvarp;
     long_u     free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
-#ifdef FEAT_GUI
-    // set when changing an option that only requires a redraw in the GUI
-    int                redraw_gui_only = FALSE;
-#endif
     int                value_changed = FALSE;
     int                did_swaptcap = FALSE;
+    opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx);
 
     // Get the global option to compare with, otherwise we would have to check
     // two values for all local options.
@@ -2659,25 +2736,23 @@ did_set_string_option(
     // Check for a "normal" directory or file name in some options.
     else if (check_illegal_path_names(opt_idx, varp))
        errmsg = e_invalid_argument;
+    else if (did_set_cb != NULL)
+    {
+       optset_T   args;
+
+       args.os_varp = *varp;
+       args.os_flags = opt_flags;
+       args.os_oldval.string = oldval;
+       args.os_newval.string = value;
+       errmsg = did_set_cb(&args);
+    }
     else if (varp == &T_NAME)                  // 'term'
        errmsg = did_set_term(&opt_idx, &free_oldval);
-    else if (gvarp == &p_bkc)                  // 'backupcopy'
-       errmsg = did_set_backupcopy(oldval, opt_flags);
-    else if (  varp == &p_bex                  // 'backupext'
-           || varp == &p_pm)                   // 'patchmode'
-       errmsg = did_set_backupext_or_patchmode();
-#ifdef FEAT_LINEBREAK
-    else if (varp == &curwin->w_p_briopt)      // 'breakindentopt'
-       errmsg = did_set_breakindentopt();
-#endif
-
     else if (  varp == &p_isi                  // 'isident'
            || varp == &(curbuf->b_p_isk)       // 'iskeyword'
            || varp == &p_isp                   // 'isprint'
            || varp == &p_isf)                  // 'isfname'
        errmsg = did_set_isopt(&did_chartab);
-    else if (varp == &p_hf)                    // 'helpfile'
-       did_set_helpfile();
 #ifdef FEAT_SYN_HL
     else if (  varp == &curwin->w_p_culopt     // 'cursorlineopt'
            || gvarp == &curwin->w_allbuf_opt.wo_culopt)
@@ -2685,67 +2760,25 @@ did_set_string_option(
     else if (varp == &curwin->w_p_cc)          // 'colorcolumn'
        errmsg = check_colorcolumn(curwin);
 #endif
-#ifdef FEAT_MULTI_LANG
-    else if (varp == &p_hlg)                   // 'helplang'
-       errmsg = did_set_helplang();
-#endif
-    else if (varp == &p_hl)                    // 'highlight'
-       errmsg = did_set_highlight();
     else if (gvarp == &p_nf)                   // 'nrformats'
        errmsg = did_set_opt_strings(*varp, p_nf_values, TRUE);
 #ifdef FEAT_SESSION
-    else if (varp == &p_ssop)                  // 'sessionoptions'
-       errmsg = did_set_sessionoptions(oldval);
     else if (varp == &p_vop)                   // 'viewoptions'
        errmsg = did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
 #endif
     else if (varp == &p_sbo)                   // 'scrollopt'
        errmsg = did_set_opt_strings(p_sbo, p_scbopt_values, TRUE);
-    else if (  varp == &p_ambw                 // 'ambiwidth'
-           || varp == &p_emoji)                // 'emoji'
-       errmsg = did_set_ambiwidth();
-    else if (varp == &p_bg)                    // 'background'
-       errmsg = did_set_background();
-    else if (varp == &p_wim)                   // 'wildmode'
-       errmsg = did_set_wildmode();
     else if (varp == &p_wop)                   // 'wildoptions'
        errmsg = did_set_opt_strings(p_wop, p_wop_values, TRUE);
-#ifdef FEAT_WAK
-    else if (varp == &p_wak)                   // 'winaltkeys'
-       errmsg = did_set_winaltkeys();
-#endif
-    else if (varp == &p_ei)                    // 'eventignore'
-       errmsg = did_set_eventignore();
-
     else if (  varp == &p_enc                  // 'encoding'
            || gvarp == &p_fenc                 // 'fileencoding'
            || varp == &p_tenc                  // 'termencoding'
            || gvarp == &p_menc)                // 'makeencoding'
        errmsg = did_set_encoding(varp, gvarp, opt_flags);
-#if defined(FEAT_POSTSCRIPT)
-    else if (varp == &p_penc)                  // 'printencoding'
-       did_set_printencoding();
-#endif
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-    else if (varp == &p_imak)                  // 'imactivatekey'
-       errmsg = did_set_imactivatekey();
-#endif
 #ifdef FEAT_KEYMAP
     else if (varp == &curbuf->b_p_keymap)      // 'keymap'
        errmsg = did_set_keymap(varp, opt_flags, value_checked);
 #endif
-    else if (gvarp == &p_ff)                   // 'fileformat'
-       errmsg = did_set_fileformat(varp, oldval, opt_flags);
-    else if (varp == &p_ffs)                   // 'fileformats'
-       errmsg = did_set_fileformats();
-#if defined(FEAT_CRYPT)
-    else if (gvarp == &p_key)                  // 'cryptkey'
-       did_set_cryptkey(oldval);
-    else if (gvarp == &p_cm)                   // 'cryptmethod'
-       errmsg = did_set_cryptmethod(oldval, opt_flags);
-#endif
-    else if (gvarp == &p_mps)                  // 'matchpairs'
-       errmsg = did_set_matchpairs(varp);
     else if (gvarp == &p_com)                  // 'comments'
        errmsg = did_set_comments(varp, errbuf);
     else if (  varp == &p_lcs                  // global 'listchars'
@@ -2755,10 +2788,6 @@ did_set_string_option(
        errmsg = set_chars_option(curwin, varp, TRUE);
     else if (varp == &curwin->w_p_fcs)         // local 'fillchars'
        errmsg = set_chars_option(curwin, varp, TRUE);
-    else if (varp == &p_cedit)                 // 'cedit'
-       errmsg = check_cedit();
-    else if (varp == &p_vfile)                 // 'verbosefile'
-       errmsg = did_set_verbosefile();
 #ifdef FEAT_VIMINFO
     else if (varp == &p_viminfo)               // 'viminfo'
        errmsg = did_set_viminfo(errbuf);
@@ -2766,199 +2795,36 @@ did_set_string_option(
     // terminal options
     else if (istermoption_idx(opt_idx) && full_screen)
        did_set_term_option(varp, &did_swaptcap);
-#ifdef FEAT_LINEBREAK
-    else if (gvarp == &p_sbr)                  // 'showbreak'
-       errmsg = did_set_showbreak(varp);
-#endif
-#ifdef FEAT_GUI
-    else if (varp == &p_guifont)               // 'guifont'
-    {
-       errmsg = did_set_guifont(oldval);
-       redraw_gui_only = TRUE;
-    }
-# ifdef FEAT_XFONTSET
-    else if (varp == &p_guifontset)            // 'guifontset'
-    {
-       errmsg = did_set_guifontset();
-       redraw_gui_only = TRUE;
-    }
-# endif
-    else if (varp == &p_guifontwide)           // 'guifontwide'
-    {
-       errmsg = did_set_guifontwide();
-       redraw_gui_only = TRUE;
-    }
-#endif
-#if defined(FEAT_GUI_GTK)
-    else if (varp == &p_guiligatures)          // 'guiligatures'
-    {
-       did_set_guiligatures();
-       redraw_gui_only = TRUE;
-    }
-#endif
 #ifdef CURSOR_SHAPE
     else if (varp == &p_guicursor)             // 'guicursor'
        errmsg = parse_shape_opt(SHAPE_CURSOR);
 #endif
-#ifdef FEAT_MOUSESHAPE
-    else if (varp == &p_mouseshape)            // 'mouseshape'
-       errmsg = did_set_mouseshape();
-#endif
-#ifdef FEAT_PRINTER
-    else if (varp == &p_popt)                  // 'printoptions'
-       errmsg = parse_printoptions();
-# if defined(FEAT_POSTSCRIPT)
-    else if (varp == &p_pmfn)                  // 'printmbfont'
-       errmsg = parse_printmbfont();
-# endif
-#endif
-#ifdef FEAT_LANGMAP
-    else if (varp == &p_langmap)               // 'langmap'
-       langmap_set();
-#endif
-#ifdef FEAT_LINEBREAK
-    else if (varp == &p_breakat)               // 'breakat'
-       fill_breakat_flags();
-#endif
-    else if (  varp == &p_titlestring          // 'titlestring'
-           || varp == &p_iconstring)           // 'iconstring'
-       did_set_titleiconstring(varp);
-#ifdef FEAT_GUI
-    else if (varp == &p_go)                    // 'guioptions'
-    {
-       did_set_guioptions(oldval);
-       redraw_gui_only = TRUE;
-    }
-#endif
-#if defined(FEAT_GUI_TABLINE)
-    else if (varp == &p_gtl)                   // 'guitablabel'
-    {
-       did_set_guitablabel();
-       redraw_gui_only = TRUE;
-    }
-    else if (varp == &p_gtt)                   // 'guitabtooltip'
-       redraw_gui_only = TRUE;
-#endif
-#if defined(UNIX) || defined(VMS)
-    else if (varp == &p_ttym)                  // 'ttymouse'
-       errmsg = did_set_ttymouse();
-#endif
-    else if (varp == &p_sel)                   // 'selection'
-       errmsg = did_set_selection();
     else if (varp == &p_slm)                   // 'selectmode'
        errmsg = did_set_opt_strings(p_slm, p_slm_values, TRUE);
-#ifdef FEAT_BROWSE
-    else if (varp == &p_bsdir)                 // 'browsedir'
-       errmsg = did_set_browsedir();
-#endif
-    else if (varp == &p_km)                    // 'keymodel'
-       errmsg = did_set_keymodel();
-    else if (varp == &p_kpc)                   // 'keyprotocol'
-       errmsg = did_set_keyprotocol();
-    else if (varp == &p_mousem)                        // 'mousemodel'
-       errmsg = did_set_mousemodel();
     else if (varp == &p_swb)                   // 'switchbuf'
        errmsg = did_set_opt_flags(p_swb, p_swb_values, &swb_flags, TRUE);
     else if (varp == &p_spk)                   // 'splitkeep'
        errmsg = did_set_opt_strings(p_spk, p_spk_values, FALSE);
     else if (varp == &p_debug)                 // 'debug'
        errmsg = did_set_opt_strings(p_debug, p_debug_values, TRUE);
-    else if (varp == &p_dy)                    // 'display'
-       errmsg = did_set_display();
     else if (varp == &p_ead)                   // 'eadirection'
        errmsg = did_set_opt_strings(p_ead, p_ead_values, FALSE);
-#ifdef FEAT_CLIPBOARD
-    else if (varp == &p_cb)                    // 'clipboard'
-       errmsg = check_clipboard_option();
-#endif
-#ifdef FEAT_SPELL
-    else if (varp == &(curwin->w_s->b_p_spf))  // 'spellfile'
-       errmsg = did_set_spellfile(varp);
-    else if (varp == &(curwin->w_s->b_p_spl))  // 'spell'
-       errmsg = did_set_spell(varp);
-    else if (varp == &(curwin->w_s->b_p_spc))  // 'spellcapcheck'
-       errmsg = did_set_spellcapcheck();
-    else if (varp == &(curwin->w_s->b_p_spo))  // 'spelloptions'
-       errmsg = did_set_spelloptions(varp);
-    else if (varp == &p_sps)                   // 'spellsuggest'
-       errmsg = did_set_spellsuggest();
-    else if (varp == &p_msm)                   // 'mkspellmem'
-       errmsg = did_set_mkspellmem();
-#endif
     else if (gvarp == &p_bh)                   // 'bufhidden'
        errmsg = did_set_opt_strings(curbuf->b_p_bh, p_bufhidden_values,
                                                                FALSE);
-    else if (gvarp == &p_bt)                   // 'buftype'
-       errmsg = did_set_buftype();
-#ifdef FEAT_STL_OPT
-    else if (  gvarp == &p_stl                 // 'statusline'
-           || varp == &p_tal                   // 'tabline'
-           || varp == &p_ruf)                  // 'rulerformat'
-       errmsg = did_set_statusline(varp);
-#endif
     else if (gvarp == &p_cpt)                  // 'complete'
        errmsg = did_set_complete(varp, errbuf);
-    else if (varp == &p_cot)                   // 'completeopt'
-       errmsg = did_set_completeopt();
-#ifdef BACKSLASH_IN_FILENAME
-    else if (gvarp == &p_csl)                  // 'completeslash'
-       errmsg = did_set_completeslash();
-#endif
-#ifdef FEAT_SIGNS
-    else if (varp == &curwin->w_p_scl)         // 'signcolumn'
-       errmsg = did_set_signcolumn(varp, oldval);
-#endif
     else if (varp == &p_sloc)                  // 'showcmdloc'
        errmsg = did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
-#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
-    else if (varp == &p_toolbar)               // 'toolbar'
-       errmsg = did_set_toolbar();
-#endif
-#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
-    else if (varp == &p_tbis)                  // 'toolbariconsize'
-       errmsg = did_set_toolbariconsize();
-#endif
-    else if (varp == &p_pt)                    // 'pastetoggle'
-       did_set_pastetoggle();
-    else if (varp == &p_bs)                    // 'backspace'
-       errmsg = did_set_backspace();
     else if (varp == &p_bo)                    // 'belloff'
        errmsg = did_set_opt_flags(p_bo, p_bo_values, &bo_flags, TRUE);
-    else if (gvarp == &p_tc)                   // 'tagcase'
-       errmsg = did_set_tagcase(opt_flags);
     else if (varp == &p_cmp)                   // 'casemap'
        errmsg = did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
-#ifdef FEAT_DIFF
-    else if (varp == &p_dip)                   // 'diffopt'
-       errmsg = did_set_diffopt();
-#endif
 #ifdef FEAT_FOLDING
-    else if (gvarp == &curwin->w_allbuf_opt.wo_fdm)    // 'foldmethod'
-       errmsg = did_set_foldmethod(varp);
-    else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)    // 'foldmarker'
-       errmsg = did_set_foldmarker(varp);
-    else if (gvarp == &p_cms)                  // 'commentstring'
-       errmsg = did_set_commentstring(varp);
     else if (varp == &p_fdo)                   // 'foldopen'
        errmsg = did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
     else if (varp == &p_fcl)                   // 'foldclose'
        errmsg = did_set_opt_strings(p_fcl, p_fcl_values, TRUE);
-    else if (gvarp == &curwin->w_allbuf_opt.wo_fdi)    // 'foldignore'
-       did_set_foldignore();
-#endif
-    else if (gvarp == &p_ve)                   // 'virtualedit'
-       errmsg = did_set_virtualedit(oldval, opt_flags);
-#if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
-    else if (varp == &p_csqf)                  // 'cscopequickfix'
-       errmsg = did_set_cscopequickfix();
-#endif
-    else if (gvarp == &p_cino)                 // 'cinoptions'
-       did_set_cinoptions();
-    else if (gvarp == &p_lop)                  // 'lispoptions'
-       errmsg = did_set_lispoptions(varp);
-#if defined(FEAT_RENDER_OPTIONS)
-    else if (varp == &p_rop)                   // 'renderoptions'
-       errmsg = did_set_renderoptions();
 #endif
     else if (gvarp == &p_ft)                   // 'filetype'
        errmsg = did_set_filetype_or_syntax(varp, oldval, value_checked,
@@ -2969,10 +2835,6 @@ did_set_string_option(
                                                        &value_changed);
 #endif
 #ifdef FEAT_TERMINAL
-    else if (varp == &curwin->w_p_twk)         // 'termwinkey'
-       errmsg = did_set_termwinkey();
-    else if (varp == &curwin->w_p_tws)         // 'termwinsize'
-       errmsg = did_set_termwinsize();
     else if (varp == &curwin->w_p_wcr)         // 'wincolor'
        term_update_wincolor(curwin);
 # if defined(MSWIN)
@@ -2980,20 +2842,6 @@ did_set_string_option(
        errmsg = did_set_opt_strings(p_twt, p_twt_values, FALSE);
 # endif
 #endif
-#ifdef FEAT_VARTABS
-    else if (varp == &(curbuf->b_p_vsts))      // 'varsofttabstop'
-       errmsg = did_set_varsofttabstop(varp);
-    else if (varp == &(curbuf->b_p_vts))       // 'vartabstop'
-       errmsg = did_set_vartabstop(varp);
-#endif
-#ifdef FEAT_PROP_POPUP
-    else if (varp == &p_pvp)                   // 'previewpopup'
-       errmsg = did_set_previewpopup();
-# ifdef FEAT_QUICKFIX
-    else if (varp == &p_cpp)                   // 'completepopup'
-       errmsg = did_set_completepopup();
-# endif
-#endif
 #ifdef FEAT_EVAL
     else if (
 # ifdef FEAT_BEVAL
@@ -3019,31 +2867,6 @@ did_set_string_option(
 # endif
            varp == &p_ccv)                     // 'charconvert'
        did_set_optexpr(varp);
-#endif
-#ifdef FEAT_COMPL_FUNC
-    else if (gvarp == &p_cfu)                  // 'completefunc'
-       errmsg = set_completefunc_option();
-    else if (gvarp == &p_ofu)                  // 'omnifunc'
-       errmsg = set_omnifunc_option();
-    else if (gvarp == &p_tsrfu)                        // 'thesaurusfunc'
-       errmsg = set_thesaurusfunc_option();
-#endif
-#if defined(FEAT_EVAL) && \
-     (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
-    else if (gvarp == &p_imaf)                 // 'imactivatefunc'
-       errmsg = set_imactivatefunc_option();
-    else if (gvarp == &p_imsf)                 // 'imstatusfunc'
-       errmsg = set_imstatusfunc_option();
-#endif
-    else if (varp == &p_opfunc)                        // 'operatorfunc'
-       errmsg = set_operatorfunc_option();
-#ifdef FEAT_QUICKFIX
-    else if (varp == &p_qftf)                  // 'quickfixtextfunc'
-       errmsg = qf_process_qftf_option();
-#endif
-#ifdef FEAT_EVAL
-    else if (gvarp == &p_tfu)                  // 'tagfunc'
-       errmsg = set_tagfunc_option();
 #endif
     else if (varp == &p_ww)                    // 'whichwrap'
        errmsg = did_set_option_listflag(varp, (char_u *)WW_ALL, errbuf);
@@ -3143,6 +2966,25 @@ did_set_string_option(
     if ((opt_flags & OPT_NO_REDRAW) == 0)
     {
 #ifdef FEAT_GUI
+       // set when changing an option that only requires a redraw in the GUI
+       int     redraw_gui_only = FALSE;
+
+       if (varp == &p_go                       // 'guioptions'
+               || varp == &p_guifont           // 'guifont'
+# ifdef FEAT_GUI_TABLINE
+               || varp == &p_gtl               // 'guitablabel'
+               || varp == &p_gtt               // 'guitabtooltip'
+# endif
+# ifdef FEAT_XFONTSET
+               || varp == &p_guifontset        // 'guifontset'
+# endif
+               || varp == &p_guifontwide       // 'guifontwide'
+# ifdef FEAT_GUI_GTK
+               || varp == &p_guiligatures      // 'guiligatures'
+# endif
+           )
+           redraw_gui_only = TRUE;
+
        // check redraw when it's not a GUI option or the GUI is active.
        if (!redraw_gui_only || gui.in_use)
 #endif
@@ -3226,9 +3068,8 @@ check_ff_value(char_u *p)
 }
 
 /*
- * Save the acutal shortmess Flags and clear them
- * temporarily to avoid that file messages
- * overwrites any output from the following commands.
+ * Save the actual shortmess Flags and clear them temporarily to avoid that
+ * file messages overwrites any output from the following commands.
  *
  * Caller must make sure to first call save_clear_shm_value() and then
  * restore_shm_value() exactly the same number of times.
index 3dca35b9adec0a28316ec5e0666b4fd8d9d2da51..f3e8cab979128135d5db614d322c328ec98881d3 100644 (file)
@@ -18,7 +18,7 @@ void clip_scroll_selection(int rows);
 void clip_copy_modeless_selection(int both);
 void clip_gen_set_selection(Clipboard_T *cbd);
 int clip_gen_owner_exists(Clipboard_T *cbd);
-char *check_clipboard_option(void);
+char *did_set_clipboard(optset_T *args);
 void open_app_context(void);
 void x11_setup_atoms(Display *dpy);
 void x11_setup_selection(Widget w);
index 88f0175ae48ad2ff3c9e2cf9e7d21b96e43c0783..956916dc54e1d9530c59790f6ecbd105ba1f83a4 100644 (file)
@@ -39,7 +39,7 @@ void f_setcmdline(typval_T *argvars, typval_T *rettv);
 void f_setcmdpos(typval_T *argvars, typval_T *rettv);
 int get_cmdline_firstc(void);
 int get_list_range(char_u **str, int *num1, int *num2);
-char *check_cedit(void);
+char *did_set_cedit(optset_T *args);
 int is_in_cmdwin(void);
 char_u *script_get(exarg_T *eap, char_u *cmd);
 void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog, int secret);
index 2e944aef668878abf598e94cce3403c101a88ba3..bac7321de94dcfaeb6439c0bdf1c5c6d57fe18e5 100644 (file)
@@ -1,6 +1,6 @@
 /* gui_xim.c */
-char *set_imactivatefunc_option(void);
-char *set_imstatusfunc_option(void);
+char *did_set_imactivatefunc(optset_T *args);
+char *did_set_imstatusfunc(optset_T *args);
 void free_xim_stuff(void);
 int set_ref_in_im_funcs(int copyID);
 void im_set_active(int active);
index 615f088565b904964bf658c9d20956501ab44c62..8a8c73e56f1eb57ce97a7d7c23f34fe3736e2f9d 100644 (file)
@@ -1,6 +1,6 @@
 /* hardcopy.c */
-char *parse_printoptions(void);
-char *parse_printmbfont(void);
+char *parse_printoptions(optset_T *args);
+char *parse_printmbfont(optset_T *args);
 int prt_header_height(void);
 int prt_use_number(void);
 int prt_get_unit(int idx);
index bab82cef3f1074338610d7cfe297f52e0b2cca7f..00bbf3c0580b32c26fbe0fa249e96a35c67f4d54 100644 (file)
@@ -1,7 +1,7 @@
 /* if_mzsch.c */
 int mzscheme_enabled(int verbose);
 void mzvim_check_threads(void);
-void mzvim_reset_timer(void);
+char *did_set_mzquantum(void);
 void mzscheme_end(void);
 int mzscheme_main(void);
 void mzscheme_buffer_free(buf_T *buf);
index b10d2a8c692f177060ba252effaf436eb230e294..51f5db0f8f2739320c8b88ec33b33a1740af07d4 100644 (file)
@@ -44,11 +44,11 @@ int ins_compl_bs(void);
 void ins_compl_addleader(int c);
 void ins_compl_addfrommatch(void);
 int ins_compl_prep(int c);
-char *set_completefunc_option(void);
+char *did_set_completefunc(optset_T *args);
 void set_buflocal_cfu_callback(buf_T *buf);
-char *set_omnifunc_option(void);
+char *did_set_omnifunc(optset_T *args);
 void set_buflocal_ofu_callback(buf_T *buf);
-char *set_thesaurusfunc_option(void);
+char *did_set_thesaurusfunc(optset_T *args);
 int set_ref_in_insexpand_funcs(int copyID);
 void f_complete(typval_T *argvars, typval_T *rettv);
 void f_complete_add(typval_T *argvars, typval_T *rettv);
index 1ed088dc64284efb7b8dbd11c9489e0600603c54..d696aabcd7bc095bc8439f5bc9acbe446f01d91e 100644 (file)
@@ -26,7 +26,7 @@ void init_mappings(void);
 void add_map(char_u *map, int mode, int nore);
 int langmap_adjust_mb(int c);
 void langmap_init(void);
-void langmap_set(void);
+char *did_set_langmap(optset_T *args);
 void ex_abbreviate(exarg_T *eap);
 void ex_map(exarg_T *eap);
 void ex_unmap(exarg_T *eap);
index 8a25bf62619031987b037135d1ae546bf9df1305..193e89430e739c133f059169ccaec8a99a141914 100644 (file)
@@ -17,7 +17,7 @@ void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int is_del);
 void op_addsub(oparg_T *oap, linenr_T Prenum1, int g_cmd);
 void clear_oparg(oparg_T *oap);
 void cursor_pos_info(dict_T *dict);
-char *set_operatorfunc_option(void);
+char *did_set_operatorfunc(optset_T *args);
 void free_operatorfunc_option(void);
 int set_ref_in_opfunc(int copyID);
 void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank);
index b32b95ed341b0dcc4572805882f3a7ee172d9c4e..a4a2b9f8150212252efc562d079a9aae14398161 100644 (file)
@@ -24,6 +24,68 @@ int valid_name(char_u *val, char *allowed);
 void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx);
 sctx_T *get_option_sctx(char *name);
 void set_term_option_sctx_idx(char *name, int opt_idx);
+char *did_set_compatible(optset_T *args);
+char *did_set_langremap(optset_T *args);
+char *did_set_langnoremap(optset_T *args);
+char *did_set_undofile(optset_T *args);
+char *did_set_readonly(optset_T *args);
+char *did_set_mousehide(optset_T *args);
+char *did_set_modifiable(optset_T *args);
+char *did_set_eof_eol_fixeol_bomb(optset_T *args);
+char *did_set_binary(optset_T *args);
+char *did_set_buflisted(optset_T *args);
+char *did_set_swapfile(optset_T *args);
+char *did_set_terse(optset_T *args);
+char *did_set_paste(optset_T *args);
+char *did_set_insertmode(optset_T *args);
+char *did_set_ignorecase(optset_T *args);
+char *did_set_hlsearch(optset_T *args);
+char *did_set_scrollbind(optset_T *args);
+char *did_set_previewwindow(optset_T *args);
+char *did_set_smoothscroll(optset_T *args);
+char *did_set_textmode(optset_T *args);
+char *did_set_textauto(optset_T *args);
+char *did_set_lisp(optset_T *args);
+char *did_set_title_icon(optset_T *args);
+char *did_set_modified(optset_T *args);
+char *did_set_shellslash(optset_T *args);
+char *did_set_wrap(optset_T *args);
+char *did_set_equalalways(optset_T *args);
+char *did_set_weirdinvert(optset_T *args);
+char *did_set_ballooneval(optset_T *args);
+char *did_set_balloonevalterm(optset_T *args);
+char *did_set_autochdir(optset_T *args);
+char *did_set_diff(optset_T *args);
+char *did_set_imdisable(optset_T *args);
+char *did_set_spell(optset_T *args);
+char *did_set_arabic(optset_T *args);
+char *did_set_number_relativenumber(optset_T *args);
+char *did_set_termguicolors(optset_T *args);
+char *did_set_winheight_helpheight(optset_T *args);
+char *did_set_winminheight(optset_T *args);
+char *did_set_winwidth(optset_T *args);
+char *did_set_winminwidth(optset_T *args);
+char *did_set_laststatus(optset_T *args);
+char *did_set_showtabline(optset_T *args);
+char *did_set_linespace(optset_T *args);
+char *did_set_foldlevel(optset_T *args);
+char *did_set_foldminlines(optset_T *args);
+char *did_set_foldnestmax(optset_T *args);
+char *did_set_foldcolumn(optset_T *args);
+char *did_set_shiftwidth_tabstop(optset_T *args);
+char *did_set_maxcombine(optset_T *args);
+char *did_set_iminsert(optset_T *args);
+char *did_set_imstyle(optset_T *args);
+char *did_set_window(optset_T *args);
+char *did_set_imsearch(optset_T *args);
+char *did_set_titlelen(optset_T *args);
+char *did_set_cmdheight(optset_T *args);
+char *did_set_updatecount(optset_T *args);
+char *did_set_conceallevel(optset_T *args);
+char *did_set_pyxversion(optset_T *args);
+char *did_set_numberwidth(optset_T *args);
+char *did_set_textwidth(optset_T *args);
+char *did_set_undolevels(optset_T *args);
 void check_redraw(long_u flags);
 int findoption(char_u *arg);
 getoption_T get_option_value(char_u *name, long *numval, char_u **stringval, int *flagsp, int scope);
@@ -55,6 +117,7 @@ void unset_global_local_option(char_u *name, void *from);
 char_u *get_option_varp_scope(int opt_idx, int scope);
 char_u *get_option_var(int opt_idx);
 char_u *get_option_fullname(int opt_idx);
+opt_did_set_cb_T get_option_did_set_cb(int opt_idx);
 char_u *get_equalprg(void);
 void win_copy_options(win_T *wp_from, win_T *wp_to);
 void after_copy_winopt(win_T *wp);
@@ -72,7 +135,7 @@ void vimrc_found(char_u *fname, char_u *envname);
 void change_compatible(int on);
 int option_was_set(char_u *name);
 int reset_option_was_set(char_u *name);
-void fill_breakat_flags(void);
+char *did_set_breakat(optset_T *args);
 int can_bs(int what);
 long get_scrolloff_value(void);
 long get_sidescrolloff_value(void);
index d4f96be40caabeb651766a121baaa82e7841ad7c..d92a7f0067933b979d062ef7153261e4002f2c23 100644 (file)
@@ -9,7 +9,78 @@ void set_string_option_direct(char_u *name, int opt_idx, char_u *val, int opt_fl
 void set_string_option_direct_in_win(win_T *wp, char_u *name, int opt_idx, char_u *val, int opt_flags, int set_sid);
 void set_string_option_direct_in_buf(buf_T *buf, char_u *name, int opt_idx, char_u *val, int opt_flags, int set_sid);
 char *set_string_option(int opt_idx, char_u *value, int opt_flags, char *errbuf);
-char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *errbuf, int opt_flags, int *value_checked);
+char *did_set_backupcopy(optset_T *args);
+char *did_set_backupext_or_patchmode(optset_T *args);
+char *did_set_breakindentopt(optset_T *args);
+char *did_set_helpfile(optset_T *args);
+char *did_set_helplang(optset_T *args);
+char *did_set_highlight(optset_T *args);
+char *did_set_sessionoptions(optset_T *args);
+char *did_set_ambiwidth(optset_T *args);
+char *did_set_background(optset_T *args);
+char *did_set_wildmode(optset_T *args);
+char *did_set_winaltkeys(optset_T *args);
+char *did_set_eventignore(optset_T *args);
+char *did_set_printencoding(optset_T *args);
+char *did_set_imactivatekey(optset_T *args);
+char *did_set_fileformat(optset_T *args);
+char *did_set_fileformats(optset_T *args);
+char *did_set_cryptkey(optset_T *args);
+char *did_set_cryptmethod(optset_T *args);
+char *did_set_matchpairs(optset_T *args);
+char *did_set_verbosefile(optset_T *args);
+char *did_set_showbreak(optset_T *args);
+char *did_set_guifont(optset_T *args);
+char *did_set_guifontset(optset_T *args);
+char *did_set_guifontwide(optset_T *args);
+char *did_set_guiligatures(optset_T *args);
+char *did_set_mouseshape(optset_T *args);
+char *did_set_titlestring(optset_T *args);
+char *did_set_iconstring(optset_T *args);
+char *did_set_guioptions(optset_T *args);
+char *did_set_guitablabel(optset_T *args);
+char *did_set_ttymouse(optset_T *args);
+char *did_set_selection(optset_T *args);
+char *did_set_browsedir(optset_T *args);
+char *did_set_keymodel(optset_T *args);
+char *did_set_keyprotocol(optset_T *args);
+char *did_set_mousemodel(optset_T *args);
+char *did_set_display(optset_T *args);
+char *did_set_spellfile(optset_T *args);
+char *did_set_spelllang(optset_T *args);
+char *did_set_spellcapcheck(optset_T *args);
+char *did_set_spelloptions(optset_T *args);
+char *did_set_spellsuggest(optset_T *args);
+char *did_set_mkspellmem(optset_T *args);
+char *did_set_buftype(optset_T *args);
+char *did_set_statusline(optset_T *args);
+char *did_set_tabline(optset_T *args);
+char *did_set_rulerformat(optset_T *args);
+char *did_set_completeopt(optset_T *args);
+char *did_set_completeslash(optset_T *args);
+char *did_set_signcolumn(optset_T *args);
+char *did_set_toolbar(optset_T *args);
+char *did_set_toolbariconsize(optset_T *args);
+char *did_set_pastetoggle(optset_T *args);
+char *did_set_backspace(optset_T *args);
+char *did_set_tagcase(optset_T *args);
+char *did_set_diffopt(optset_T *args);
+char *did_set_foldmethod(optset_T *args);
+char *did_set_foldmarker(optset_T *args);
+char *did_set_commentstring(optset_T *args);
+char *did_set_foldignore(optset_T *args);
+char *did_set_virtualedit(optset_T *args);
+char *did_set_cscopequickfix(optset_T *args);
+char *did_set_cinoptions(optset_T *args);
+char *did_set_lispoptions(optset_T *args);
+char *did_set_renderoptions(optset_T *args);
+char *did_set_termwinkey(optset_T *args);
+char *did_set_termwinsize(optset_T *args);
+char *did_set_varsofttabstop(optset_T *args);
+char *did_set_vartabstop(optset_T *args);
+char *did_set_previewpopup(optset_T *args);
+char *did_set_completepopup(optset_T *args);
+char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char_u *value, char *errbuf, int opt_flags, int *value_checked);
 int check_ff_value(char_u *p);
 void save_clear_shm_value(void);
 void restore_shm_value(void);
index 3a210b06656a168fedc1c7ea74af5157c79c5133..b708d6bd4dc544911f1dfd2755b98faf7259ee9a 100644 (file)
@@ -15,7 +15,7 @@ void ex_cclose(exarg_T *eap);
 void ex_copen(exarg_T *eap);
 void ex_cbottom(exarg_T *eap);
 linenr_T qf_current_entry(win_T *wp);
-char *qf_process_qftf_option(void);
+char *did_set_quickfixtextfunc(optset_T *args);
 int grep_internal(cmdidx_T cmdidx);
 void ex_make(exarg_T *eap);
 int qf_get_size(exarg_T *eap);
index 55c8482cd971289850d811bf1247241e701c7b4e..f6bad568ba86457983f4fbebeb2bebccd056b12c 100644 (file)
@@ -16,7 +16,7 @@ void slang_clear_sug(slang_T *lp);
 void count_common_word(slang_T *lp, char_u *word, int len, int count);
 int byte_in_str(char_u *str, int n);
 int init_syl_tab(slang_T *slang);
-char *did_set_spelllang(win_T *wp);
+char *parse_spelllang(win_T *wp);
 int captype(char_u *word, char_u *end);
 void spell_delete_wordlist(void);
 void spell_free_all(void);
index f42e3f8ee132b960dd4ab1b8c66e0c6ea7084ebc..6de463e92c55296d83fb79513f93ac091b63e235 100644 (file)
@@ -1,5 +1,5 @@
 /* tag.c */
-char *set_tagfunc_option(void);
+char *did_set_tagfunc(optset_T *args);
 void free_tagfunc_option(void);
 int set_ref_in_tagfunc(int copyID);
 void set_buflocal_tfu_callback(buf_T *buf);
index bc82ee027e01856262497a2162ac5f0ad4261ace..245e20bb8d5e1be8cfcd2029adb28d0d4a063934 100644 (file)
@@ -4534,7 +4534,7 @@ qf_find_buf(qf_info_T *qi)
  * Returns OK or FAIL.
  */
     char *
-qf_process_qftf_option(void)
+did_set_quickfixtextfunc(optset_T *args UNUSED)
 {
     if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL)
        return e_invalid_argument;
index 072740cbaaef3ba0bd4e1763b28031b226b7a7b1..071ac9c95bb77078d00c618a536a0b604d356501 100644 (file)
@@ -1987,7 +1987,7 @@ count_syllables(slang_T *slang, char_u *word)
  * Returns NULL if it's OK, an untranslated error message otherwise.
  */
     char *
-did_set_spelllang(win_T *wp)
+parse_spelllang(win_T *wp)
 {
     garray_T   ga;
     char_u     *splp;
@@ -2503,7 +2503,7 @@ spell_reload(void)
        {
                if (wp->w_p_spell)
                {
-                   (void)did_set_spelllang(wp);
+                   (void)parse_spelllang(wp);
                    break;
                }
        }
@@ -4410,7 +4410,7 @@ did_set_spell_option(int is_spellfile)
     FOR_ALL_WINDOWS(wp)
        if (wp->w_buffer == curbuf && wp->w_p_spell)
        {
-           errmsg = did_set_spelllang(wp);
+           errmsg = parse_spelllang(wp);
            break;
        }
     return errmsg;
index bf51f5fd6936cb0b12431415d41d9d3941d9fa0f..a9fa70cfa4537e9986300606aad7e4d364c8fc5a 100644 (file)
@@ -1771,7 +1771,7 @@ spell_reload_one(
     // When "zg" was used and the file wasn't loaded yet, should redo
     // 'spelllang' to load it now.
     if (added_word && !didit)
-       did_set_spelllang(curwin);
+       parse_spelllang(curwin);
 }
 
 
index 6b34ec8165d8b3b8fc20cb99afead91e0569b816..a60055728be436e55f4dbfb98c0b478776c4289c 100644 (file)
@@ -480,7 +480,7 @@ spell_suggest(int count)
 
     if (!curwin->w_p_spell)
     {
-       did_set_spelllang(curwin);
+       parse_spelllang(curwin);
        curwin->w_p_spell = TRUE;
     }
 
index a320d7069d427d2679e51d38b5c42462274acf15..584d472558e01b5f0f1764e420ffc2299a011e31 100644 (file)
@@ -4789,3 +4789,33 @@ typedef struct {
 #endif
     int                cts_vcol;           // virtual column at current position
 } chartabsize_T;
+
+/*
+ * Argument for the callback function (opt_did_set_cb_T) invoked after an
+ * option value is modified.
+ */
+typedef struct
+{
+    int                os_flags;
+    char_u     *os_varp;               // pointer to the option variable
+
+    // old value of the option (can be a string, number or a boolean)
+    union
+    {
+       long    number;
+       int     boolean;
+       char_u  *string;
+    } os_oldval;
+
+    // new value of the option (can be a string, number or a boolean)
+    union
+    {
+       long    number;
+       int     boolean;
+       char_u  *string;
+    } os_newval;
+
+    // When set by the called function: Stop processing the option further.
+    // Currently only used for boolean options.
+    int                os_doskip;
+} optset_T;
index de9473ca733da44f8e3eb2eea6c41449d95af217..86f8ac4bcfaf1be7b0ddb3c5064c3effe096dafd 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -171,7 +171,7 @@ static callback_T tfu_cb;       // 'tagfunc' callback function
  * a function (string), or function(<name>) or funcref(<name>) or a lambda.
  */
     char *
-set_tagfunc_option(void)
+did_set_tagfunc(optset_T *args UNUSED)
 {
 #ifdef FEAT_EVAL
     free_callback(&tfu_cb);
index d219f0fae589be8b32b59212d2869f5ff03dc85e..63fd787923260566e1ca79d66f8493557bbe0379 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1330,
 /**/
     1329,
 /**/
index 45b5fa925c7beb0beddb227d9c6784369f769e1a..db38da2e84f351ec03f0400aa99162d435ea390e 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2284,6 +2284,12 @@ typedef enum {
     FCERR_FAILED,      // error while executing the function
 } funcerror_T;
 
+/*
+ * Type for the callback function that is invoked after an option value is
+ * changed to validate and apply the new value.
+ */
+typedef char *(*opt_did_set_cb_T)(optset_T *args);
+
 // Flags for assignment functions.
 #define ASSIGN_VAR     0     // ":var" (nothing special)
 #define ASSIGN_FINAL   0x01  // ":final"