Patch 9.0.1262
Problem:    The did_set_string_option function is too long.
Solution:   Split off functionality to individual functions.  (Yegappan
            Lakshmanan, Lewis Russell, closes #11904)
Files:      src/gui_xim.c, src/insexpand.c, src/ops.c, src/optionstr.c,
            src/proto/gui_xim.pro, src/proto/insexpand.pro, src/proto/ops.pro,
            src/proto/quickfix.pro, src/proto/tag.pro, src/quickfix.c,
            src/spell.c, src/tag.c


*** ../vim-9.0.1261/src/gui_xim.c       2023-01-08 13:44:21.073352325 +0000
--- src/gui_xim.c       2023-01-30 12:55:05.454365093 +0000
***************
*** 73,88 ****
  static callback_T imaf_cb;        // 'imactivatefunc' callback function
  static callback_T imsf_cb;        // 'imstatusfunc' callback function
  
!     int
  set_imactivatefunc_option(void)
  {
!     return option_set_callback_func(p_imaf, &imaf_cb);
  }
  
!     int
  set_imstatusfunc_option(void)
  {
!     return option_set_callback_func(p_imsf, &imsf_cb);
  }
  
      static void
--- 73,94 ----
  static callback_T imaf_cb;        // 'imactivatefunc' callback function
  static callback_T imsf_cb;        // 'imstatusfunc' callback function
  
!     char *
  set_imactivatefunc_option(void)
  {
!     if (option_set_callback_func(p_imaf, &imaf_cb) == FAIL)
!       return e_invalid_argument;
! 
!     return NULL;
  }
  
!     char *
  set_imstatusfunc_option(void)
  {
!     if (option_set_callback_func(p_imsf, &imsf_cb) == FAIL)
!       return e_invalid_argument;
! 
!     return NULL;
  }
  
      static void
*** ../vim-9.0.1261/src/insexpand.c     2023-01-22 21:14:32.617863616 +0000
--- src/insexpand.c     2023-01-30 12:55:05.454365093 +0000
***************
*** 2545,2560 ****
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     int
  set_completefunc_option(void)
  {
!     int       retval;
  
!     retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
!     if (retval == OK)
!       set_buflocal_cfu_callback(curbuf);
  
!     return retval;
  }
  
  /*
--- 2545,2559 ----
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     char *
  set_completefunc_option(void)
  {
!     if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL)
!       return e_invalid_argument;
  
!     set_buflocal_cfu_callback(curbuf);
  
!     return NULL;
  }
  
  /*
***************
*** 2575,2590 ****
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     int
  set_omnifunc_option(void)
  {
!     int       retval;
! 
!     retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
!     if (retval == OK)
!       set_buflocal_ofu_callback(curbuf);
  
!     return retval;
  }
  
  /*
--- 2574,2587 ----
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     char *
  set_omnifunc_option(void)
  {
!     if (option_set_callback_func(curbuf->b_p_ofu, &ofu_cb) == FAIL)
!       return e_invalid_argument;
  
!     set_buflocal_ofu_callback(curbuf);
!     return NULL;
  }
  
  /*
***************
*** 2605,2611 ****
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     int
  set_thesaurusfunc_option(void)
  {
      int       retval;
--- 2602,2608 ----
   * name of a function (string), or function(<name>) or funcref(<name>) or a
   * lambda expression.
   */
!     char *
  set_thesaurusfunc_option(void)
  {
      int       retval;
***************
*** 2622,2628 ****
        retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
      }
  
!     return retval;
  }
  
  /*
--- 2619,2625 ----
        retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
      }
  
!     return retval == FAIL ? e_invalid_argument : NULL;
  }
  
  /*
*** ../vim-9.0.1261/src/ops.c   2023-01-16 18:19:01.907301080 +0000
--- src/ops.c   2023-01-30 12:55:05.454365093 +0000
***************
*** 3405,3414 ****
   * Process the 'operatorfunc' option value.
   * Returns OK or FAIL.
   */
!     int
  set_operatorfunc_option(void)
  {
!     return option_set_callback_func(p_opfunc, &opfunc_cb);
  }
  
  #if defined(EXITFREE) || defined(PROTO)
--- 3405,3417 ----
   * Process the 'operatorfunc' option value.
   * Returns OK or FAIL.
   */
!     char *
  set_operatorfunc_option(void)
  {
!     if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL)
!       return e_invalid_argument;
! 
!     return NULL;
  }
  
  #if defined(EXITFREE) || defined(PROTO)
*** ../vim-9.0.1261/src/optionstr.c     2023-01-28 16:37:33.898559056 +0000
--- src/optionstr.c     2023-01-30 12:55:05.458365091 +0000
***************
*** 640,645 ****
--- 640,2497 ----
  #endif
  
  /*
+  * The 'term' option is changed.
+  */
+     static char *
+ did_set_term(int *opt_idx, long_u *free_oldval)
+ {
+     char *errmsg = NULL;
+ 
+     if (T_NAME[0] == NUL)
+       errmsg = e_cannot_set_term_to_empty_string;
+ #ifdef FEAT_GUI
+     else if (gui.in_use)
+       errmsg = e_cannot_change_term_in_GUI;
+     else if (term_is_gui(T_NAME))
+       errmsg = e_use_gui_to_start_GUI;
+ #endif
+     else if (set_termname(T_NAME) == FAIL)
+       errmsg = e_not_found_in_termcap;
+     else
+     {
+       // Screen colors may have changed.
+       redraw_later_clear();
+ 
+       // Both 'term' and 'ttytype' point to T_NAME, only set the
+       // P_ALLOCED flag on 'term'.
+       *opt_idx = findoption((char_u *)"term");
+       *free_oldval = (get_option_flags(*opt_idx) & P_ALLOCED);
+     }
+ 
+     return errmsg;
+ }
+ 
+ /*
+  * The 'backupcopy' option is changed.
+  */
+     static char *
+ did_set_backupcopy(
+     char_u    *oldval,
+     int               opt_flags)
+ {
+     char_u            *bkc = p_bkc;
+     unsigned int      *flags = &bkc_flags;
+     char              *errmsg = NULL;
+ 
+     if (opt_flags & OPT_LOCAL)
+     {
+       bkc = curbuf->b_p_bkc;
+       flags = &curbuf->b_bkc_flags;
+     }
+ 
+     if ((opt_flags & OPT_LOCAL) && *bkc == NUL)
+       // make the local value empty: use the global value
+       *flags = 0;
+     else
+     {
+       if (opt_strings_flags(bkc, p_bkc_values, flags, TRUE) != OK)
+           errmsg = e_invalid_argument;
+       if ((((int)*flags & BKC_AUTO) != 0)
+               + (((int)*flags & BKC_YES) != 0)
+               + (((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);
+           errmsg = e_invalid_argument;
+       }
+     }
+ 
+     return errmsg;
+ }
+ 
+ /*
+  * The 'backupext' or the 'patchmode' option is changed.
+  */
+     static char *
+ did_set_backupext_or_patchmode(void)
+ {
+     if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
+               *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
+       return e_backupext_and_patchmode_are_equal;
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_LINEBREAK
+ /*
+  * The 'breakindentopt' option is changed.
+  */
+     static char *
+ did_set_breakindentopt(void)
+ {
+     char *errmsg = NULL;
+ 
+     if (briopt_check(curwin) == FAIL)
+       errmsg = e_invalid_argument;
+     // list setting requires a redraw
+     if (curwin->w_briopt_list)
+       redraw_all_later(UPD_NOT_VALID);
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option 
is
+  * changed.
+  */
+     static char *
+ did_set_isopt(int *did_chartab)
+ {
+     if (init_chartab() == FAIL)
+     {
+       *did_chartab = TRUE;            // need to restore it below
+       return e_invalid_argument;      // error in value
+     }
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'helpfile' option is changed.
+  */
+     static void
+ did_set_helpfile(void)
+ {
+     // 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");
+ }
+ 
+ #ifdef FEAT_SYN_HL
+ /*
+  * The 'cursorlineopt' option is changed.
+  */
+     static char *
+ did_set_cursorlineopt(char_u **varp)
+ {
+     if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_MULTI_LANG
+ /*
+  * The 'helplang' option is changed.
+  */
+     static char *
+ did_set_helplang(void)
+ {
+     char *errmsg = NULL;
+ 
+     // Check for "", "ab", "ab,cd", etc.
+     for (char_u *s = p_hlg; *s != NUL; s += 3)
+     {
+       if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
+       {
+           errmsg = e_invalid_argument;
+           break;
+       }
+       if (s[2] == NUL)
+           break;
+     }
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'highlight' option is changed.
+  */
+     static char *
+ did_set_highlight(void)
+ {
+     if (highlight_changed() == FAIL)
+       return e_invalid_argument;      // invalid flags
+ 
+     return NULL;
+ }
+ 
+ /*
+  * An option that accepts a list of flags is changed.
+  * e.g. 'viewoptions', 'switchbuf', 'casemap', etc.
+  */
+     static char *
+ did_set_opt_flags(char_u *val, char **values, unsigned *flagp, int list)
+ {
+     if (opt_strings_flags(val, values, flagp, list) == FAIL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * An option that accepts a list of string values is changed.
+  * e.g. 'nrformats', 'scrollopt', 'wildoptions', etc.
+  */
+     static char *
+ did_set_opt_strings(char_u *val, char **values, int list)
+ {
+     return did_set_opt_flags(val, values, NULL, list);
+ }
+ 
+ #ifdef FEAT_SESSION
+ /*
+  * The 'sessionoptions' option is changed.
+  */
+     static char *
+ did_set_sessionoptions(char_u *oldval)
+ {
+     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);
+       return e_invalid_argument;
+     }
+ 
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'ambiwidth' option is changed.
+  */
+     static char *
+ did_set_ambiwidth(void)
+ {
+     if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     return check_chars_options();
+ }
+ 
+ /*
+  * The 'background' option is changed.
+  */
+     static char *
+ did_set_background(void)
+ {
+     if (check_opt_strings(p_bg, p_bg_values, FALSE) == FAIL)
+       return e_invalid_argument;
+ 
+ #ifdef FEAT_EVAL
+     int dark = (*p_bg == 'd');
+ #endif
+ 
+     init_highlight(FALSE, FALSE);
+ 
+ #ifdef FEAT_EVAL
+     if (dark != (*p_bg == 'd')
+           && get_var_value((char_u *)"g:colors_name") != NULL)
+     {
+       // The color scheme must have set 'background' back to another
+       // value, that's not what we want here.  Disable the color
+       // scheme and set the colors again.
+       do_unlet((char_u *)"g:colors_name", TRUE);
+       free_string_option(p_bg);
+       p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
+       check_string_option(&p_bg);
+       init_highlight(FALSE, FALSE);
+     }
+ #endif
+ #ifdef FEAT_TERMINAL
+     term_update_colors_all();
+ #endif
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'wildmode' option is changed.
+  */
+     static char *
+ did_set_wildmode(void)
+ {
+     if (check_opt_wim() == FAIL)
+       return e_invalid_argument;
+     return NULL;
+ }
+ 
+ #ifdef FEAT_WAK
+ /*
+  * The 'winaltkeys' option is changed.
+  */
+     static char *
+ did_set_winaltkeys(void)
+ {
+     char *errmsg = NULL;
+ 
+     if (*p_wak == NUL
+           || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
+       errmsg = e_invalid_argument;
+ # ifdef FEAT_MENU
+ #  if defined(FEAT_GUI_MOTIF)
+     else if (gui.in_use)
+       gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
+ #  elif defined(FEAT_GUI_GTK)
+     else if (gui.in_use)
+       gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
+ #  endif
+ # endif
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'eventignore' option is changed.
+  */
+     static char *
+ did_set_eventignore(void)
+ {
+     if (check_ei() == FAIL)
+       return e_invalid_argument;
+     return NULL;
+ }
+ 
+ /*
+  * One of the 'encoding', 'fileencoding', 'termencoding' or 'makeencoding'
+  * options is changed.
+  */
+     static char *
+ did_set_encoding(char_u **varp, char_u **gvarp, int opt_flags)
+ {
+     char      *errmsg = NULL;
+     char_u    *p;
+ 
+     if (gvarp == &p_fenc)
+     {
+       if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL)
+           errmsg = e_cannot_make_changes_modifiable_is_off;
+       else if (vim_strchr(*varp, ',') != NULL)
+           // No comma allowed in 'fileencoding'; catches confusing it
+           // with 'fileencodings'.
+           errmsg = e_invalid_argument;
+       else
+       {
+           // May show a "+" in the title now.
+           redraw_titles();
+           // Add 'fileencoding' to the swap file.
+           ml_setflags(curbuf);
+       }
+     }
+     if (errmsg == NULL)
+     {
+       // canonize the value, so that STRCMP() can be used on it
+       p = enc_canonize(*varp);
+       if (p != NULL)
+       {
+           vim_free(*varp);
+           *varp = p;
+       }
+       if (varp == &p_enc)
+       {
+           errmsg = mb_init();
+           redraw_titles();
+       }
+     }
+ 
+ #if defined(FEAT_GUI_GTK)
+     if (errmsg == NULL && varp == &p_tenc && gui.in_use)
+     {
+       // GTK uses only a single encoding, and that is UTF-8.
+       if (STRCMP(p_tenc, "utf-8") != 0)
+           errmsg = e_cannot_be_changed_in_gtk_GUI;
+     }
+ #endif
+ 
+     if (errmsg == NULL)
+     {
+ #ifdef FEAT_KEYMAP
+       // When 'keymap' is used and 'encoding' changes, reload the keymap
+       // (with another encoding).
+       if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
+           (void)keymap_init();
+ #endif
+ 
+       // When 'termencoding' is not empty and 'encoding' changes or when
+       // 'termencoding' changes, need to setup for keyboard input and
+       // display output conversion.
+       if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
+       {
+           if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL
+                   || convert_setup(&output_conv, p_enc, p_tenc) == FAIL)
+           {
+               semsg(_(e_cannot_convert_between_str_and_str),
+                       p_tenc, p_enc);
+               errmsg = e_invalid_argument;
+           }
+       }
+ 
+ #if defined(MSWIN)
+       // $HOME may have characters in active code page.
+       if (varp == &p_enc)
+           init_homedir();
+ #endif
+     }
+ 
+     return errmsg;
+ }
+ 
+ #if defined(FEAT_POSTSCRIPT)
+ /*
+  * The 'printencoding' option is changed.
+  */
+     static void
+ did_set_printencoding(void)
+ {
+     char_u    *s, *p;
+ 
+     // Canonize printencoding if VIM standard one
+     p = enc_canonize(p_penc);
+     if (p != NULL)
+     {
+       vim_free(p_penc);
+       p_penc = p;
+     }
+     else
+     {
+       // Ensure lower case and '-' for '_'
+       for (s = p_penc; *s != NUL; s++)
+       {
+           if (*s == '_')
+               *s = '-';
+           else
+               *s = TOLOWER_ASC(*s);
+       }
+     }
+ }
+ #endif
+ 
+ #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
+ /*
+  * The 'imactivatekey' option is changed.
+  */
+     static char *
+ did_set_imactivatekey(void)
+ {
+     if (!im_xim_isvalid_imactivate())
+       return e_invalid_argument;
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_KEYMAP
+ /*
+  * The 'keymap' option is changed.
+  */
+     static char *
+ did_set_keymap(char_u **varp, int opt_flags, int *value_checked)
+ {
+     char *errmsg = NULL;
+ 
+     if (!valid_filetype(*varp))
+       errmsg = e_invalid_argument;
+     else
+     {
+       int         secure_save = secure;
+ 
+       // Reset the secure flag, since the value of 'keymap' has
+       // been checked to be safe.
+       secure = 0;
+ 
+       // load or unload key mapping tables
+       errmsg = keymap_init();
+ 
+       secure = secure_save;
+ 
+       // Since we check the value, there is no need to set P_INSECURE,
+       // even when the value comes from a modeline.
+       *value_checked = TRUE;
+     }
+ 
+     if (errmsg == NULL)
+     {
+       if (*curbuf->b_p_keymap != NUL)
+       {
+           // Installed a new keymap, switch on using it.
+           curbuf->b_p_iminsert = B_IMODE_LMAP;
+           if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
+               curbuf->b_p_imsearch = B_IMODE_LMAP;
+       }
+       else
+       {
+           // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
+           if (curbuf->b_p_iminsert == B_IMODE_LMAP)
+               curbuf->b_p_iminsert = B_IMODE_NONE;
+           if (curbuf->b_p_imsearch == B_IMODE_LMAP)
+               curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
+       }
+       if ((opt_flags & OPT_LOCAL) == 0)
+       {
+           set_iminsert_global();
+           set_imsearch_global();
+       }
+       status_redraw_curbuf();
+     }
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'fileformat' option is changed.
+  */
+     static char *
+ did_set_fileformat(char_u **varp, char_u *oldval, int opt_flags)
+ {
+     if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL))
+       return e_cannot_make_changes_modifiable_is_off;
+     else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     // may also change 'textmode'
+     if (get_fileformat(curbuf) == EOL_DOS)
+       curbuf->b_p_tx = TRUE;
+     else
+       curbuf->b_p_tx = FALSE;
+     redraw_titles();
+     // update flag in swap file
+     ml_setflags(curbuf);
+     // Redraw needed when switching to/from "mac": a CR in the text
+     // will be displayed differently.
+     if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm')
+       redraw_curbuf_later(UPD_NOT_VALID);
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'fileformats' option is changed.
+  */
+     static char *
+ did_set_fileformats(void)
+ {
+     if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     // also change 'textauto'
+     if (*p_ffs == NUL)
+       p_ta = FALSE;
+     else
+       p_ta = TRUE;
+ 
+     return NULL;
+ }
+ 
+ #if defined(FEAT_CRYPT)
+ /*
+  * The 'cryptkey' option is changed.
+  */
+     static void
+ did_set_cryptkey(char_u *oldval)
+ {
+     // 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)
+       // Need to update the swapfile.
+     {
+       ml_set_crypt_key(curbuf, oldval,
+               *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
+       changed_internal();
+     }
+ }
+ 
+ /*
+  * The 'cryptmethod' option is changed.
+  */
+     static char *
+ did_set_cryptmethod(char_u *oldval, int opt_flags)
+ {
+     char_u  *p;
+     char_u  *s;
+ 
+     if (opt_flags & OPT_LOCAL)
+       p = curbuf->b_p_cm;
+     else
+       p = p_cm;
+     if (check_opt_strings(p, p_cm_values, TRUE) != OK)
+       return e_invalid_argument;
+     else if (crypt_self_test() == FAIL)
+       return e_invalid_argument;
+ 
+     // When setting the global value to empty, make it "zip".
+     if (*p_cm == NUL)
+     {
+       free_string_option(p_cm);
+       p_cm = vim_strsave((char_u *)"zip");
+     }
+     // 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)
+     {
+       free_string_option(curbuf->b_p_cm);
+       curbuf->b_p_cm = empty_option;
+     }
+ 
+     // 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)
+       s = p_cm;  // was previously using the global value
+     else
+       s = oldval;
+     if (*curbuf->b_p_cm == NUL)
+       p = p_cm;  // is now using the global value
+     else
+       p = curbuf->b_p_cm;
+     if (STRCMP(s, p) != 0)
+       ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
+ 
+     // 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)
+     {
+       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);
+     }
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'matchpairs' option is changed.
+  */
+     static char *
+ did_set_matchpairs(char_u **varp)
+ {
+     char_u    *p;
+ 
+     if (has_mbyte)
+     {
+       for (p = *varp; *p != NUL; ++p)
+       {
+           int x2 = -1;
+           int x3 = -1;
+ 
+           p += mb_ptr2len(p);
+           if (*p != NUL)
+               x2 = *p++;
+           if (*p != NUL)
+           {
+               x3 = mb_ptr2char(p);
+               p += mb_ptr2len(p);
+           }
+           if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ','))
+               return e_invalid_argument;
+           if (*p == NUL)
+               break;
+       }
+     }
+     else
+     {
+       // Check for "x:y,x:y"
+       for (p = *varp; *p != NUL; p += 4)
+       {
+           if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
+               return e_invalid_argument;
+           if (p[3] == NUL)
+               break;
+       }
+     }
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'comments' option is changed.
+  */
+     static char *
+ did_set_comments(char_u **varp, char *errbuf)
+ {
+     char_u    *s;
+     char      *errmsg = NULL;
+ 
+     for (s = *varp; *s; )
+     {
+       while (*s && *s != ':')
+       {
+           if (vim_strchr((char_u *)COM_ALL, *s) == NULL
+                   && !VIM_ISDIGIT(*s) && *s != '-')
+           {
+               errmsg = illegal_char(errbuf, *s);
+               break;
+           }
+           ++s;
+       }
+       if (*s++ == NUL)
+           errmsg = e_missing_colon;
+       else if (*s == ',' || *s == NUL)
+           errmsg = e_zero_length_string;
+       if (errmsg != NULL)
+           break;
+       while (*s && *s != ',')
+       {
+           if (*s == '\\' && s[1] != NUL)
+               ++s;
+           ++s;
+       }
+       s = skip_to_option_part(s);
+     }
+ 
+     return errmsg;
+ }
+ 
+ /*
+  * The global 'listchars' or 'fillchars' option is changed.
+  */
+     static char *
+ did_set_global_listfillchars(char_u **varp, int opt_flags)
+ {
+     char      *errmsg = NULL;
+     char_u    **local_ptr = varp == &p_lcs
+       ? &curwin->w_p_lcs : &curwin->w_p_fcs;
+ 
+     // only apply the global value to "curwin" when it does not have a
+     // local value
+     errmsg = set_chars_option(curwin, varp,
+           **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+     if (errmsg != NULL)
+       return errmsg;
+ 
+     tabpage_T *tp;
+     win_T     *wp;
+ 
+     // If the current window is set to use the global
+     // 'listchars'/'fillchars' value, clear the window-local value.
+     if (!(opt_flags & OPT_GLOBAL))
+       clear_string_option(local_ptr);
+     FOR_ALL_TAB_WINDOWS(tp, wp)
+     {
+       // If the current window has a local value need to apply it
+       // again, it was changed when setting the global value.
+       // If no error was returned above, we don't expect an error
+       // here, so ignore the return value.
+       local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
+       if (**local_ptr == NUL)
+           (void)set_chars_option(wp, local_ptr, TRUE);
+     }
+ 
+     redraw_all_later(UPD_NOT_VALID);
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'verbosefile' option is changed.
+  */
+     static char *
+ did_set_verbosefile(void)
+ {
+     verbose_stop();
+     if (*p_vfile != NUL && verbose_open() == FAIL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_VIMINFO
+ /*
+  * The 'viminfo' option is changed.
+  */
+     static char *
+ did_set_viminfo(char *errbuf)
+ {
+     char_u    *s;
+     char      *errmsg = NULL;
+ 
+     for (s = p_viminfo; *s;)
+     {
+       // Check it's a valid character
+       if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
+       {
+           errmsg = illegal_char(errbuf, *s);
+           break;
+       }
+       if (*s == 'n')  // name is always last one
+           break;
+       else if (*s == 'r') // skip until next ','
+       {
+           while (*++s && *s != ',')
+               ;
+       }
+       else if (*s == '%')
+       {
+           // optional number
+           while (vim_isdigit(*++s))
+               ;
+       }
+       else if (*s == '!' || *s == 'h' || *s == 'c')
+           ++s;                // no extra chars
+       else            // must have a number
+       {
+           while (vim_isdigit(*++s))
+               ;
+ 
+           if (!VIM_ISDIGIT(*(s - 1)))
+           {
+               if (errbuf != NULL)
+               {
+                   sprintf(errbuf,
+                           _(e_missing_number_after_angle_str_angle),
+                           transchar_byte(*(s - 1)));
+                   errmsg = errbuf;
+               }
+               else
+                   errmsg = "";
+               break;
+           }
+       }
+       if (*s == ',')
+           ++s;
+       else if (*s)
+       {
+           if (errbuf != NULL)
+               errmsg = e_missing_comma;
+           else
+               errmsg = "";
+           break;
+       }
+     }
+     if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
+       errmsg = e_must_specify_a_value;
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * Some terminal option (t_xxx) is changed
+  */
+     static void
+ did_set_term_option(char_u **varp, int *did_swaptcap UNUSED)
+ {
+     // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co="
+     if (varp == &T_CCO)
+     {
+       int colors = atoi((char *)T_CCO);
+ 
+       // Only reinitialize colors if t_Co value has really changed to
+       // avoid expensive reload of colorscheme if t_Co is set to the
+       // same value multiple times.
+       if (colors != t_colors)
+       {
+           t_colors = colors;
+           if (t_colors <= 1)
+           {
+               vim_free(T_CCO);
+               T_CCO = empty_option;
+           }
+ #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
+           if (is_term_win32())
+           {
+               swap_tcap();
+               *did_swaptcap = TRUE;
+           }
+ #endif
+           // We now have a different color setup, initialize it again.
+           init_highlight(TRUE, FALSE);
+       }
+     }
+     ttest(FALSE);
+     if (varp == &T_ME)
+     {
+       out_str(T_ME);
+       redraw_later(UPD_CLEAR);
+ #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+       // Since t_me has been set, this probably means that the user
+       // wants to use this as default colors.  Need to reset default
+       // background/foreground colors.
+ # ifdef VIMDLL
+       if (!gui.in_use && !gui.starting)
+ # endif
+           mch_set_normal_colors();
+ #endif
+     }
+     if (varp == &T_BE && termcap_active)
+     {
+       MAY_WANT_TO_LOG_THIS;
+ 
+       if (*T_BE == NUL)
+           // When clearing t_BE we assume the user no longer wants
+           // bracketed paste, thus disable it by writing t_BD.
+           out_str(T_BD);
+       else
+           out_str(T_BE);
+     }
+ }
+ 
+ #ifdef FEAT_LINEBREAK
+ /*
+  * The 'showbreak' option is changed.
+  */
+     static char *
+ did_set_showbreak(char_u **varp)
+ {
+     char_u    *s;
+ 
+     for (s = *varp; *s; )
+     {
+       if (ptr2cells(s) != 1)
+           return e_showbreak_contains_unprintable_or_wide_character;
+       MB_PTR_ADV(s);
+     }
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_GUI
+ /*
+  * The 'guifont' option is changed.
+  */
+     static char *
+ did_set_guifont(char_u *oldval, int *redraw_gui_only)
+ {
+     char_u    *p;
+     char      *errmsg = NULL;
+ 
+     if (gui.in_use)
+     {
+       p = p_guifont;
+ # if defined(FEAT_GUI_GTK)
+       // Put up a font dialog and let the user select a new value.
+       // If this is cancelled go back to the old value but don't
+       // give an error message.
+       if (STRCMP(p, "*") == 0)
+       {
+           p = gui_mch_font_dialog(oldval);
+           free_string_option(p_guifont);
+           p_guifont = (p != NULL) ? p : vim_strsave(oldval);
+       }
+ # endif
+       if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
+       {
+ # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
+           if (STRCMP(p_guifont, "*") == 0)
+           {
+               // Dialog was cancelled: Keep the old value without giving
+               // an error message.
+               free_string_option(p_guifont);
+               p_guifont = vim_strsave(oldval);
+           }
+           else
+ # endif
+               errmsg = e_invalid_fonts;
+       }
+     }
+     *redraw_gui_only = TRUE;
+ 
+     return errmsg;
+ }
+ 
+ # ifdef FEAT_XFONTSET
+ /*
+  * The 'guifontset' option is changed.
+  */
+     static char *
+ did_set_guifontset(int *redraw_gui_only)
+ {
+     char *errmsg = NULL;
+ 
+     if (STRCMP(p_guifontset, "*") == 0)
+       errmsg = e_cant_select_fontset;
+     else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
+       errmsg = e_invalid_fontset;
+     *redraw_gui_only = TRUE;
+ 
+     return errmsg;
+ }
+ # endif
+ 
+ /*
+  * The 'guifontwide' option is changed.
+  */
+     static char *
+ did_set_guifontwide(int *redraw_gui_only)
+ {
+     char *errmsg = NULL;
+ 
+     if (STRCMP(p_guifontwide, "*") == 0)
+       errmsg = e_cant_select_wide_font;
+     else if (gui_get_wide_font() == FAIL)
+       errmsg = e_invalid_wide_font;
+     *redraw_gui_only = TRUE;
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ #if defined(FEAT_GUI_GTK)
+     static void
+ did_set_guiligatures(int *redraw_gui_only)
+ {
+     gui_set_ligatures();
+     *redraw_gui_only = TRUE;
+ }
+ #endif
+ 
+ #ifdef FEAT_MOUSESHAPE
+     static char *
+ did_set_mouseshape(void)
+ {
+     char *errmsg = NULL;
+ 
+     errmsg = parse_shape_opt(SHAPE_MOUSE);
+     update_mouseshape(-1);
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'titlestring' or the 'iconstring' option is changed.
+  */
+     static void
+ did_set_titleiconstring(char_u **varp 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)
+       stl_syntax |= flagval;
+     else
+       stl_syntax &= ~flagval;
+ #endif
+     did_set_title();
+ }
+ 
+ #ifdef FEAT_GUI
+ /*
+  * The 'guioptions' option is changed.
+  */
+     static void
+ did_set_guioptions(char_u *oldval, int *redraw_gui_only)
+ {
+     gui_init_which_components(oldval);
+     *redraw_gui_only = TRUE;
+ }
+ #endif
+ 
+ #if defined(FEAT_GUI_TABLINE)
+     static void
+ did_set_guitablabel(int *redraw_gui_only)
+ {
+     redraw_tabline = TRUE;
+     *redraw_gui_only = TRUE;
+ }
+ #endif
+ 
+ #if defined(UNIX) || defined(VMS)
+ /*
+  * The 'ttymouse' option is changed.
+  */
+     static char *
+ did_set_ttymouse(void)
+ {
+     char *errmsg = NULL;
+ 
+     // Switch the mouse off before changing the escape sequences used for
+     // that.
+     mch_setmouse(FALSE);
+     if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
+       errmsg = e_invalid_argument;
+     else
+       check_mouse_termcode();
+     if (termcap_active)
+       setmouse();             // may switch it on again
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'selection' option is changed.
+  */
+     static char *
+ did_set_selection(void)
+ {
+     if (*p_sel == NUL
+           || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_BROWSE
+ /*
+  * The 'browsedir' option is changed.
+  */
+     static char *
+ did_set_browsedir(void)
+ {
+     if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
+           && !mch_isdir(p_bsdir))
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'keymodel' option is changed.
+  */
+     static char *
+ did_set_keymodel(void)
+ {
+     if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+     km_startsel = (vim_strchr(p_km, 'a') != NULL);
+     return NULL;
+ }
+ 
+ /*
+  * The 'keyprotocol' option is changed.
+  */
+     static char *
+ did_set_keyprotocol(void)
+ {
+     if (match_keyprotocol(NULL) == KEYPROTOCOL_FAIL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'mousemodel' option is changed.
+  */
+     static char *
+ did_set_mousemodel(void)
+ {
+     if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
+       return e_invalid_argument;
+ #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
+     else if (*p_mousem != *oldval)
+       // Changed from "extend" to "popup" or "popup_setpos" or vv: need
+       // to create or delete the popup menus.
+       gui_motif_update_mousemodel(root_menu);
+ #endif
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'display' option is changed.
+  */
+     static char *
+ did_set_display(void)
+ {
+     if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     (void)init_chartab();
+     return NULL;
+ }
+ 
+ #ifdef FEAT_SPELL
+ /*
+  * The 'spellfile' option is changed.
+  */
+     static char *
+ did_set_spellfile(char_u **varp)
+ {
+     if (!valid_spellfile(*varp))
+       return e_invalid_argument;
+ 
+     // If there is a window for this buffer in which 'spell' is set load the
+     // wordlists.
+     return did_set_spell_option(TRUE);
+ }
+ 
+ /*
+  * The 'spell' option is changed.
+  */
+     static char *
+ did_set_spell(char_u **varp)
+ {
+     if (!valid_spelllang(*varp))
+       return e_invalid_argument;
+ 
+     // If there is a window for this buffer in which 'spell' is set load the
+     // wordlists.
+     return did_set_spell_option(FALSE);
+ }
+ 
+ /*
+  * The 'spellcapcheck' option is changed.
+  */
+     static char *
+ did_set_spellcapcheck(void)
+ {
+     // compile the regexp program.
+     return compile_cap_prog(curwin->w_s);
+ }
+ 
+ /*
+  * The 'spelloptions' option is changed.
+  */
+     static char *
+ did_set_spelloptions(char_u **varp)
+ {
+     if (**varp != NUL && STRCMP("camel", *varp) != 0)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'spellsuggest' option is changed.
+  */
+     static char *
+ did_set_spellsuggest(void)
+ {
+     if (spell_check_sps() != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'mkspellmem' option is changed.
+  */
+     static char *
+ did_set_mkspellmem(void)
+ {
+     if (spell_check_msm() != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'buftype' option is changed.
+  */
+     static char *
+ did_set_buftype(void)
+ {
+     if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     if (curwin->w_status_height)
+     {
+       curwin->w_redr_status = TRUE;
+       redraw_later(UPD_VALID);
+     }
+     curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
+     redraw_titles();
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_STL_OPT
+ /*
+  * The 'statusline' or the 'tabline' or the 'rulerformat' option is changed.
+  */
+     static char *
+ did_set_statusline(char_u **varp)
+ {
+     char_u    *s;
+     char      *errmsg = NULL;
+     int               wid;
+ 
+     if (varp == &p_ruf)       // reset ru_wid first
+       ru_wid = 0;
+     s = *varp;
+     if (varp == &p_ruf && *s == '%')
+     {
+       // set ru_wid if 'ruf' starts with "%99("
+       if (*++s == '-')        // ignore a '-'
+           s++;
+       wid = getdigits(&s);
+       if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
+           ru_wid = wid;
+       else
+           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] != '!')
+       errmsg = check_stl_option(s);
+     if (varp == &p_ruf && errmsg == NULL)
+       comp_col();
+ 
+     return errmsg;
+ }
+ #endif
+ 
+ /*
+  * The 'complete' option is changed.
+  */
+     static char *
+ did_set_complete(char_u **varp, char *errbuf)
+ {
+     char_u    *s;
+ 
+     // check if it is a valid value for 'complete' -- Acevedo
+     for (s = *varp; *s;)
+     {
+       while (*s == ',' || *s == ' ')
+           s++;
+       if (!*s)
+           break;
+       if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
+           return illegal_char(errbuf, *s);
+       if (*++s != NUL && *s != ',' && *s != ' ')
+       {
+           if (s[-1] == 'k' || s[-1] == 's')
+           {
+               // skip optional filename after 'k' and 's'
+               while (*s && *s != ',' && *s != ' ')
+               {
+                   if (*s == '\\' && s[1] != NUL)
+                       ++s;
+                   ++s;
+               }
+           }
+           else
+           {
+               if (errbuf != NULL)
+               {
+                   sprintf((char *)errbuf,
+                           _(e_illegal_character_after_chr), *--s);
+                   return errbuf;
+               }
+               return "";
+           }
+       }
+     }
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'completeopt' option is changed.
+  */
+     static char *
+ did_set_completeopt(void)
+ {
+     if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     completeopt_was_set();
+     return NULL;
+ }
+ 
+ #ifdef FEAT_SIGNS
+ /*
+  * The 'signcolumn' option is changed.
+  */
+     static char *
+ did_set_signcolumn(char_u **varp, char_u *oldval)
+ {
+     if (check_opt_strings(*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')
+               || (*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;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
+ /*
+  * The 'toolbar' option is changed.
+  */
+     static char *
+ did_set_toolbar(void)
+ {
+     if (opt_strings_flags(p_toolbar, p_toolbar_values,
+               &toolbar_flags, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     out_flush();
+     gui_mch_show_toolbar((toolbar_flags &
+               (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
+     return NULL;
+ }
+ #endif
+ 
+ #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
+ /*
+  * The 'toolbariconsize' option is changed.  GTK+ 2 only.
+  */
+     static char *
+ did_set_toolbariconsize(void)
+ {
+     if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     out_flush();
+     gui_mch_show_toolbar((toolbar_flags &
+               (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'pastetoggle' option is changed.
+  */
+     static void
+ did_set_pastetoggle(void)
+ {
+     char_u    *p;
+ 
+     // translate key codes like in a mapping
+     if (*p_pt)
+     {
+       (void)replace_termcodes(p_pt, &p,
+               REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
+       if (p != NULL)
+       {
+           free_string_option(p_pt);
+           p_pt = p;
+       }
+     }
+ }
+ 
+ /*
+  * The 'backspace' option is changed.
+  */
+     static char *
+ did_set_backspace(void)
+ {
+     if (VIM_ISDIGIT(*p_bs))
+     {
+       if (*p_bs > '3' || p_bs[1] != NUL)
+           return e_invalid_argument;
+     }
+     else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'tagcase' option is changed.
+  */
+     static char *
+ did_set_tagcase(int opt_flags)
+ {
+     unsigned int      *flags;
+     char_u            *p;
+ 
+     if (opt_flags & OPT_LOCAL)
+     {
+       p = curbuf->b_p_tc;
+       flags = &curbuf->b_tc_flags;
+     }
+     else
+     {
+       p = p_tc;
+       flags = &tc_flags;
+     }
+ 
+     if ((opt_flags & OPT_LOCAL) && *p == NUL)
+       // make the local value empty: use the global value
+       *flags = 0;
+     else if (*p == NUL
+           || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_DIFF
+ /*
+  * The 'diffopt' option is changed.
+  */
+     static char *
+ did_set_diffopt(void)
+ {
+     if (diffopt_changed() == FAIL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_FOLDING
+ /*
+  * The 'foldmethod' option is changed.
+  */
+     static char *
+ did_set_foldmethod(char_u **varp)
+ {
+     if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
+           || *curwin->w_p_fdm == NUL)
+       return e_invalid_argument;
+ 
+     foldUpdateAll(curwin);
+     if (foldmethodIsDiff(curwin))
+       newFoldLevel();
+     return NULL;
+ }
+ 
+ /*
+  * The 'foldmarker' option is changed.
+  */
+     static char *
+ did_set_foldmarker(char_u **varp)
+ {
+     char_u    *p;
+ 
+     p = vim_strchr(*varp, ',');
+     if (p == NULL)
+       return e_comma_required;
+     else if (p == *varp || p[1] == NUL)
+       return e_invalid_argument;
+     else if (foldmethodIsMarker(curwin))
+       foldUpdateAll(curwin);
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'commentstring' option is changed.
+  */
+     static char *
+ did_set_commentstring(char_u **varp)
+ {
+     if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
+       return e_commentstring_must_be_empty_or_contain_str;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'foldignore' option is changed.
+  */
+     static void
+ did_set_foldignore(void)
+ {
+     if (foldmethodIsIndent(curwin))
+       foldUpdateAll(curwin);
+ }
+ #endif
+ 
+ /*
+  * The 'virtualedit' option is changed.
+  */
+     static char *
+ did_set_virtualedit(char_u *oldval, int opt_flags)
+ {
+     char_u            *ve = p_ve;
+     unsigned int      *flags = &ve_flags;
+ 
+     if (opt_flags & OPT_LOCAL)
+     {
+       ve = curwin->w_p_ve;
+       flags = &curwin->w_ve_flags;
+     }
+ 
+     if ((opt_flags & OPT_LOCAL) && *ve == NUL)
+       // make the local value empty: use the global value
+       *flags = 0;
+     else
+     {
+       if (opt_strings_flags(ve, p_ve_values, flags, TRUE) != OK)
+           return e_invalid_argument;
+       else if (STRCMP(ve, oldval) != 0)
+       {
+           // Recompute cursor position in case the new 've' setting
+           // changes something.
+           validate_virtcol();
+           coladvance(curwin->w_virtcol);
+       }
+     }
+ 
+     return NULL;
+ }
+ 
+ #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
+ /*
+  * The 'cscopequickfix' option is changed.
+  */
+     static char *
+ did_set_cscopequickfix(void)
+ {
+     char_u    *p;
+ 
+     if (p_csqf == NULL)
+       return NULL;
+ 
+     p = p_csqf;
+     while (*p != NUL)
+     {
+       if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
+               || p[1] == NUL
+               || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
+               || (p[2] != NUL && p[2] != ','))
+           return e_invalid_argument;
+       else if (p[2] == NUL)
+           break;
+       else
+           p += 3;
+     }
+ 
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'cinoptions' option is changed.
+  */
+     static void
+ did_set_cinoptions(void)
+ {
+     // TODO: recognize errors
+     parse_cino(curbuf);
+ }
+ 
+ /*
+  * The 'lispoptions' option is changed.
+  */
+     static char *
+ did_set_lispoptions(char_u **varp)
+ {
+     if (**varp != NUL && STRCMP(*varp, "expr:0") != 0
+           && STRCMP(*varp, "expr:1") != 0)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ #if defined(FEAT_RENDER_OPTIONS)
+ /*
+  * The 'renderoptions' option is changed.
+  */
+     static char *
+ did_set_renderoptions(void)
+ {
+     if (!gui_mch_set_rendering_options(p_rop))
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ /*
+  * The 'filetype' or the 'syntax' option is changed.
+  */
+     static char *
+ did_set_filetype_or_syntax(
+     char_u    **varp,
+     char_u    *oldval,
+     int               *value_checked,
+     int               *value_changed)
+ {
+     if (!valid_filetype(*varp))
+       return e_invalid_argument;
+ 
+     *value_changed = STRCMP(oldval, *varp) != 0;
+ 
+     // Since we check the value, there is no need to set P_INSECURE,
+     // even when the value comes from a modeline.
+     *value_checked = TRUE;
+ 
+     return NULL;
+ }
+ 
+ #ifdef FEAT_TERMINAL
+ /*
+  * The 'termwinkey' option is changed.
+  */
+     static char *
+ did_set_termwinkey(void)
+ {
+     if (*curwin->w_p_twk != NUL
+           && string_to_key(curwin->w_p_twk, TRUE) == 0)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'termwinsize' option is changed.
+  */
+     static char *
+ did_set_termwinsize(void)
+ {
+     char_u    *p;
+ 
+     if (*curwin->w_p_tws == NUL)
+       return NULL;
+ 
+     p = skipdigits(curwin->w_p_tws);
+     if (p == curwin->w_p_tws
+           || (*p != 'x' && *p != '*')
+           || *skipdigits(p + 1) != NUL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_VARTABS
+ /*
+  * The 'varsofttabstop' option is changed.
+  */
+     static char *
+ did_set_varsofttabstop(char_u **varp)
+ {
+     char_u *cp;
+ 
+     if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
+     {
+       if (curbuf->b_p_vsts_array)
+       {
+           vim_free(curbuf->b_p_vsts_array);
+           curbuf->b_p_vsts_array = 0;
+       }
+     }
+     else
+     {
+       for (cp = *varp; *cp; ++cp)
+       {
+           if (vim_isdigit(*cp))
+               continue;
+           if (*cp == ',' && cp > *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 (oldarray)
+               vim_free(oldarray);
+       }
+       else
+           return e_invalid_argument;
+     }
+ 
+     return NULL;
+ }
+ 
+ /*
+  * The 'vartabstop' option is changed.
+  */
+     static char *
+ did_set_vartabstop(char_u **varp)
+ {
+     char_u *cp;
+ 
+     if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
+     {
+       if (curbuf->b_p_vts_array)
+       {
+           vim_free(curbuf->b_p_vts_array);
+           curbuf->b_p_vts_array = NULL;
+       }
+     }
+     else
+     {
+       for (cp = *varp; *cp; ++cp)
+       {
+           if (vim_isdigit(*cp))
+               continue;
+           if (*cp == ',' && cp > *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)
+       {
+           vim_free(oldarray);
+ # ifdef FEAT_FOLDING
+           if (foldmethodIsIndent(curwin))
+               foldUpdateAll(curwin);
+ # endif
+       }
+       else
+           return e_invalid_argument;
+     }
+ 
+     return NULL;
+ }
+ #endif
+ 
+ #ifdef FEAT_PROP_POPUP
+ /*
+  * The 'previewpopup' option is changed.
+  */
+     static char *
+ did_set_previewpopup(void)
+ {
+     if (parse_previewpopup(NULL) == FAIL)
+       return e_invalid_argument;
+ 
+     return NULL;
+ }
+ 
+ # ifdef FEAT_QUICKFIX
+ /*
+  * The 'completepopup' option is changed.
+  */
+     static char *
+ did_set_completepopup(void)
+ {
+     if (parse_completepopup(NULL) == FAIL)
+       return e_invalid_argument;
+ 
+     popup_close_info();
+     return NULL;
+ }
+ # endif
+ #endif
+ 
+ #ifdef FEAT_EVAL
+ /*
+  * One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
+  * 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr',
+  * 'patchexpr', 'printexpr' and 'charconvert'.
+  *
+  */
+     static void
+ did_set_optexpr(char_u **varp)
+ {
+     // If the option value starts with <SID> or s:, then replace that with
+     // the script identifier.
+     char_u *name = get_scriptlocal_funcname(*varp);
+     if (name != NULL)
+     {
+       free_string_option(*varp);
+       *varp = name;
+     }
+ 
+ # ifdef FEAT_FOLDING
+     if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin))
+       foldUpdateAll(curwin);
+ # endif
+ }
+ #endif
+ 
+ /*
   * Handle string options that need some action to perform when changed.
   * The new value must be allocated.
   * Returns NULL for success, or an unstranslated error message for an error.
***************
*** 664,672 ****
      int               redraw_gui_only = FALSE;
  #endif
      int               value_changed = FALSE;
- #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
      int               did_swaptcap = FALSE;
- #endif
  
      // Get the global option to compare with, otherwise we would have to check
      // two values for all local options.
--- 2516,2522 ----
***************
*** 692,767 ****
  
      // 'term'
      else if (varp == &T_NAME)
!     {
!       if (T_NAME[0] == NUL)
!           errmsg = e_cannot_set_term_to_empty_string;
! #ifdef FEAT_GUI
!       else if (gui.in_use)
!           errmsg = e_cannot_change_term_in_GUI;
!       else if (term_is_gui(T_NAME))
!           errmsg = e_use_gui_to_start_GUI;
! #endif
!       else if (set_termname(T_NAME) == FAIL)
!           errmsg = e_not_found_in_termcap;
!       else
!       {
!           // Screen colors may have changed.
!           redraw_later_clear();
! 
!           // Both 'term' and 'ttytype' point to T_NAME, only set the
!           // P_ALLOCED flag on 'term'.
!           opt_idx = findoption((char_u *)"term");
!           free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
!       }
!     }
  
      // 'backupcopy'
      else if (gvarp == &p_bkc)
!     {
!       char_u          *bkc = p_bkc;
!       unsigned int    *flags = &bkc_flags;
! 
!       if (opt_flags & OPT_LOCAL)
!       {
!           bkc = curbuf->b_p_bkc;
!           flags = &curbuf->b_bkc_flags;
!       }
! 
!       if ((opt_flags & OPT_LOCAL) && *bkc == NUL)
!           // make the local value empty: use the global value
!           *flags = 0;
!       else
!       {
!           if (opt_strings_flags(bkc, p_bkc_values, flags, TRUE) != OK)
!               errmsg = e_invalid_argument;
!           if ((((int)*flags & BKC_AUTO) != 0)
!                   + (((int)*flags & BKC_YES) != 0)
!                   + (((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);
!               errmsg = e_invalid_argument;
!           }
!       }
!     }
  
      // 'backupext' and 'patchmode'
      else if (varp == &p_bex || varp == &p_pm)
!     {
!       if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
!                    *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
!           errmsg = e_backupext_and_patchmode_are_equal;
!     }
  #ifdef FEAT_LINEBREAK
      // 'breakindentopt'
      else if (varp == &curwin->w_p_briopt)
!     {
!       if (briopt_check(curwin) == FAIL)
!           errmsg = e_invalid_argument;
!       // list setting requires a redraw
!       if (curwin->w_briopt_list)
!           redraw_all_later(UPD_NOT_VALID);
!     }
  #endif
  
      // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill 
g_chartab[]
--- 2542,2561 ----
  
      // 'term'
      else if (varp == &T_NAME)
!       errmsg = did_set_term(&opt_idx, &free_oldval);
  
      // 'backupcopy'
      else if (gvarp == &p_bkc)
!       errmsg = did_set_backupcopy(oldval, opt_flags);
  
      // 'backupext' and 'patchmode'
      else if (varp == &p_bex || varp == &p_pm)
!       errmsg = did_set_backupext_or_patchmode();
! 
  #ifdef FEAT_LINEBREAK
      // 'breakindentopt'
      else if (varp == &curwin->w_p_briopt)
!       errmsg = did_set_breakindentopt();
  #endif
  
      // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill 
g_chartab[]
***************
*** 771,802 ****
            || varp == &(curbuf->b_p_isk)
            || varp == &p_isp
            || varp == &p_isf)
!     {
!       if (init_chartab() == FAIL)
!       {
!           did_chartab = TRUE;     // need to restore it below
!           errmsg = e_invalid_argument;            // error in value
!       }
!     }
  
      // 'helpfile'
      else if (varp == &p_hf)
!     {
!       // 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");
!     }
  
  #ifdef FEAT_SYN_HL
      // 'cursorlineopt'
      else if (varp == &curwin->w_p_culopt
                                  || gvarp == &curwin->w_allbuf_opt.wo_culopt)
!     {
!       if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'colorcolumn'
      else if (varp == &curwin->w_p_cc)
--- 2565,2581 ----
            || varp == &(curbuf->b_p_isk)
            || varp == &p_isp
            || varp == &p_isf)
!       errmsg = did_set_isopt(&did_chartab);
  
      // 'helpfile'
      else if (varp == &p_hf)
!       did_set_helpfile();
  
  #ifdef FEAT_SYN_HL
      // 'cursorlineopt'
      else if (varp == &curwin->w_p_culopt
                                  || gvarp == &curwin->w_allbuf_opt.wo_culopt)
!       errmsg = did_set_cursorlineopt(varp);
  
      // 'colorcolumn'
      else if (varp == &curwin->w_p_cc)
***************
*** 806,1544 ****
  #ifdef FEAT_MULTI_LANG
      // 'helplang'
      else if (varp == &p_hlg)
!     {
!       // Check for "", "ab", "ab,cd", etc.
!       for (s = p_hlg; *s != NUL; s += 3)
!       {
!           if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
!           {
!               errmsg = e_invalid_argument;
!               break;
!           }
!           if (s[2] == NUL)
!               break;
!       }
!     }
  #endif
  
      // 'highlight'
      else if (varp == &p_hl)
!     {
!       if (highlight_changed() == FAIL)
!           errmsg = e_invalid_argument;        // invalid flags
!     }
  
      // 'nrformats'
      else if (gvarp == &p_nf)
!     {
!       if (check_opt_strings(*varp, p_nf_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_SESSION
      // 'sessionoptions'
      else if (varp == &p_ssop)
!     {
!       if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
!           errmsg = 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);
!           errmsg = e_invalid_argument;
!       }
!     }
      // 'viewoptions'
      else if (varp == &p_vop)
!     {
!       if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      // 'scrollopt'
      else if (varp == &p_sbo)
!     {
!       if (check_opt_strings(p_sbo, p_scbopt_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'ambiwidth'
      else if (varp == &p_ambw || varp == &p_emoji)
!     {
!       if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!       else
!           errmsg = check_chars_options();
!     }
  
      // 'background'
      else if (varp == &p_bg)
!     {
!       if (check_opt_strings(p_bg, p_bg_values, FALSE) == OK)
!       {
! #ifdef FEAT_EVAL
!           int dark = (*p_bg == 'd');
! #endif
! 
!           init_highlight(FALSE, FALSE);
! 
! #ifdef FEAT_EVAL
!           if (dark != (*p_bg == 'd')
!                         && get_var_value((char_u *)"g:colors_name") != NULL)
!           {
!               // The color scheme must have set 'background' back to another
!               // value, that's not what we want here.  Disable the color
!               // scheme and set the colors again.
!               do_unlet((char_u *)"g:colors_name", TRUE);
!               free_string_option(p_bg);
!               p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
!               check_string_option(&p_bg);
!               init_highlight(FALSE, FALSE);
!           }
! #endif
! #ifdef FEAT_TERMINAL
!           term_update_colors_all();
! #endif
!       }
!       else
!           errmsg = e_invalid_argument;
!     }
  
      // 'wildmode'
      else if (varp == &p_wim)
!     {
!       if (check_opt_wim() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'wildoptions'
      else if (varp == &p_wop)
!     {
!       if (check_opt_strings(p_wop, p_wop_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_WAK
      // 'winaltkeys'
      else if (varp == &p_wak)
!     {
!       if (*p_wak == NUL
!               || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
! # ifdef FEAT_MENU
! #  if defined(FEAT_GUI_MOTIF)
!       else if (gui.in_use)
!           gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
! #  elif defined(FEAT_GUI_GTK)
!       else if (gui.in_use)
!           gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
! #  endif
! # endif
!     }
  #endif
  
      // 'eventignore'
      else if (varp == &p_ei)
!     {
!       if (check_ei() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'encoding', 'fileencoding', 'termencoding' and 'makeencoding'
      else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
                                                           || gvarp == &p_menc)
!     {
!       if (gvarp == &p_fenc)
!       {
!           if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL)
!               errmsg = e_cannot_make_changes_modifiable_is_off;
!           else if (vim_strchr(*varp, ',') != NULL)
!               // No comma allowed in 'fileencoding'; catches confusing it
!               // with 'fileencodings'.
!               errmsg = e_invalid_argument;
!           else
!           {
!               // May show a "+" in the title now.
!               redraw_titles();
!               // Add 'fileencoding' to the swap file.
!               ml_setflags(curbuf);
!           }
!       }
!       if (errmsg == NULL)
!       {
!           // canonize the value, so that STRCMP() can be used on it
!           p = enc_canonize(*varp);
!           if (p != NULL)
!           {
!               vim_free(*varp);
!               *varp = p;
!           }
!           if (varp == &p_enc)
!           {
!               errmsg = mb_init();
!               redraw_titles();
!           }
!       }
! 
! #if defined(FEAT_GUI_GTK)
!       if (errmsg == NULL && varp == &p_tenc && gui.in_use)
!       {
!           // GTK uses only a single encoding, and that is UTF-8.
!           if (STRCMP(p_tenc, "utf-8") != 0)
!               errmsg = e_cannot_be_changed_in_gtk_GUI;
!       }
! #endif
! 
!       if (errmsg == NULL)
!       {
! #ifdef FEAT_KEYMAP
!           // When 'keymap' is used and 'encoding' changes, reload the keymap
!           // (with another encoding).
!           if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
!               (void)keymap_init();
! #endif
! 
!           // When 'termencoding' is not empty and 'encoding' changes or when
!           // 'termencoding' changes, need to setup for keyboard input and
!           // display output conversion.
!           if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
!           {
!               if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL
!                       || convert_setup(&output_conv, p_enc, p_tenc) == FAIL)
!               {
!                   semsg(_(e_cannot_convert_between_str_and_str),
!                                                               p_tenc, p_enc);
!                   errmsg = e_invalid_argument;
!               }
!           }
! 
! #if defined(MSWIN)
!           // $HOME may have characters in active code page.
!           if (varp == &p_enc)
!               init_homedir();
! #endif
!       }
!     }
  
  #if defined(FEAT_POSTSCRIPT)
      else if (varp == &p_penc)
!     {
!       // Canonize printencoding if VIM standard one
!       p = enc_canonize(p_penc);
!       if (p != NULL)
!       {
!           vim_free(p_penc);
!           p_penc = p;
!       }
!       else
!       {
!           // Ensure lower case and '-' for '_'
!           for (s = p_penc; *s != NUL; s++)
!           {
!               if (*s == '_')
!                   *s = '-';
!               else
!                   *s = TOLOWER_ASC(*s);
!           }
!       }
!     }
  #endif
  
  #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
      else if (varp == &p_imak)
!     {
!       if (!im_xim_isvalid_imactivate())
!           errmsg = e_invalid_argument;
!     }
  #endif
  
  #ifdef FEAT_KEYMAP
      else if (varp == &curbuf->b_p_keymap)
!     {
!       if (!valid_filetype(*varp))
!           errmsg = e_invalid_argument;
!       else
!       {
!           int     secure_save = secure;
! 
!           // Reset the secure flag, since the value of 'keymap' has
!           // been checked to be safe.
!           secure = 0;
! 
!           // load or unload key mapping tables
!           errmsg = keymap_init();
! 
!           secure = secure_save;
! 
!           // Since we check the value, there is no need to set P_INSECURE,
!           // even when the value comes from a modeline.
!           *value_checked = TRUE;
!       }
! 
!       if (errmsg == NULL)
!       {
!           if (*curbuf->b_p_keymap != NUL)
!           {
!               // Installed a new keymap, switch on using it.
!               curbuf->b_p_iminsert = B_IMODE_LMAP;
!               if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
!                   curbuf->b_p_imsearch = B_IMODE_LMAP;
!           }
!           else
!           {
!               // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
!               if (curbuf->b_p_iminsert == B_IMODE_LMAP)
!                   curbuf->b_p_iminsert = B_IMODE_NONE;
!               if (curbuf->b_p_imsearch == B_IMODE_LMAP)
!                   curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
!           }
!           if ((opt_flags & OPT_LOCAL) == 0)
!           {
!               set_iminsert_global();
!               set_imsearch_global();
!           }
!           status_redraw_curbuf();
!       }
!     }
  #endif
  
      // 'fileformat'
      else if (gvarp == &p_ff)
!     {
!       if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL))
!           errmsg = e_cannot_make_changes_modifiable_is_off;
!       else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           // may also change 'textmode'
!           if (get_fileformat(curbuf) == EOL_DOS)
!               curbuf->b_p_tx = TRUE;
!           else
!               curbuf->b_p_tx = FALSE;
!           redraw_titles();
!           // update flag in swap file
!           ml_setflags(curbuf);
!           // Redraw needed when switching to/from "mac": a CR in the text
!           // will be displayed differently.
!           if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm')
!               redraw_curbuf_later(UPD_NOT_VALID);
!       }
!     }
  
      // 'fileformats'
      else if (varp == &p_ffs)
!     {
!       if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           // also change 'textauto'
!           if (*p_ffs == NUL)
!               p_ta = FALSE;
!           else
!               p_ta = TRUE;
!       }
!     }
  
  #if defined(FEAT_CRYPT)
      // 'cryptkey'
      else if (gvarp == &p_key)
!     {
!       // 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)
!           // Need to update the swapfile.
!       {
!           ml_set_crypt_key(curbuf, oldval,
!                             *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
!           changed_internal();
!       }
!     }
  
      else if (gvarp == &p_cm)
!     {
!       if (opt_flags & OPT_LOCAL)
!           p = curbuf->b_p_cm;
!       else
!           p = p_cm;
!       if (check_opt_strings(p, p_cm_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else if (crypt_self_test() == FAIL)
!           errmsg = e_invalid_argument;
!       else
!       {
!           // When setting the global value to empty, make it "zip".
!           if (*p_cm == NUL)
!           {
!               free_string_option(p_cm);
!               p_cm = vim_strsave((char_u *)"zip");
!           }
!           // 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)
!           {
!               free_string_option(curbuf->b_p_cm);
!               curbuf->b_p_cm = empty_option;
!           }
! 
!           // 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)
!               s = p_cm;  // was previously using the global value
!           else
!               s = oldval;
!           if (*curbuf->b_p_cm == NUL)
!               p = p_cm;  // is now using the global value
!           else
!               p = curbuf->b_p_cm;
!           if (STRCMP(s, p) != 0)
!               ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
! 
!           // 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)
!           {
!               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);
!           }
!       }
!     }
  #endif
  
      // 'matchpairs'
      else if (gvarp == &p_mps)
!     {
!       if (has_mbyte)
!       {
!           for (p = *varp; *p != NUL; ++p)
!           {
!               int x2 = -1;
!               int x3 = -1;
! 
!               p += mb_ptr2len(p);
!               if (*p != NUL)
!                   x2 = *p++;
!               if (*p != NUL)
!               {
!                   x3 = mb_ptr2char(p);
!                   p += mb_ptr2len(p);
!               }
!               if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ','))
!               {
!                   errmsg = e_invalid_argument;
!                   break;
!               }
!               if (*p == NUL)
!                   break;
!           }
!       }
!       else
!       {
!           // Check for "x:y,x:y"
!           for (p = *varp; *p != NUL; p += 4)
!           {
!               if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
!               {
!                   errmsg = e_invalid_argument;
!                   break;
!               }
!               if (p[3] == NUL)
!                   break;
!           }
!       }
!     }
  
      // 'comments'
      else if (gvarp == &p_com)
!     {
!       for (s = *varp; *s; )
!       {
!           while (*s && *s != ':')
!           {
!               if (vim_strchr((char_u *)COM_ALL, *s) == NULL
!                                            && !VIM_ISDIGIT(*s) && *s != '-')
!               {
!                   errmsg = illegal_char(errbuf, *s);
!                   break;
!               }
!               ++s;
!           }
!           if (*s++ == NUL)
!               errmsg = e_missing_colon;
!           else if (*s == ',' || *s == NUL)
!               errmsg = e_zero_length_string;
!           if (errmsg != NULL)
!               break;
!           while (*s && *s != ',')
!           {
!               if (*s == '\\' && s[1] != NUL)
!                   ++s;
!               ++s;
!           }
!           s = skip_to_option_part(s);
!       }
!     }
  
      // global 'listchars' or 'fillchars'
      else if (varp == &p_lcs || varp == &p_fcs)
!     {
!       char_u **local_ptr = varp == &p_lcs
!                                        ? &curwin->w_p_lcs : &curwin->w_p_fcs;
  
-       // only apply the global value to "curwin" when it does not have a
-       // local value
-       errmsg = set_chars_option(curwin, varp,
-                             **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
-       if (errmsg == NULL)
-       {
-           tabpage_T   *tp;
-           win_T       *wp;
- 
-           // If the current window is set to use the global
-           // 'listchars'/'fillchars' value, clear the window-local value.
-           if (!(opt_flags & OPT_GLOBAL))
-               clear_string_option(local_ptr);
-           FOR_ALL_TAB_WINDOWS(tp, wp)
-           {
-               // If the current window has a local value need to apply it
-               // again, it was changed when setting the global value.
-               // If no error was returned above, we don't expect an error
-               // here, so ignore the return value.
-               local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
-               if (**local_ptr == NUL)
-                   (void)set_chars_option(wp, local_ptr, TRUE);
-           }
- 
-           redraw_all_later(UPD_NOT_VALID);
-       }
-     }
      // local 'listchars'
      else if (varp == &curwin->w_p_lcs)
        errmsg = set_chars_option(curwin, varp, TRUE);
  
      // local 'fillchars'
      else if (varp == &curwin->w_p_fcs)
-     {
        errmsg = set_chars_option(curwin, varp, TRUE);
-     }
  
      // 'cedit'
      else if (varp == &p_cedit)
-     {
        errmsg = check_cedit();
-     }
  
      // 'verbosefile'
      else if (varp == &p_vfile)
!     {
!       verbose_stop();
!       if (*p_vfile != NUL && verbose_open() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_VIMINFO
      // 'viminfo'
      else if (varp == &p_viminfo)
!     {
!       for (s = p_viminfo; *s;)
!       {
!           // Check it's a valid character
!           if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
!           {
!               errmsg = illegal_char(errbuf, *s);
!               break;
!           }
!           if (*s == 'n')      // name is always last one
!               break;
!           else if (*s == 'r') // skip until next ','
!           {
!               while (*++s && *s != ',')
!                   ;
!           }
!           else if (*s == '%')
!           {
!               // optional number
!               while (vim_isdigit(*++s))
!                   ;
!           }
!           else if (*s == '!' || *s == 'h' || *s == 'c')
!               ++s;            // no extra chars
!           else                // must have a number
!           {
!               while (vim_isdigit(*++s))
!                   ;
! 
!               if (!VIM_ISDIGIT(*(s - 1)))
!               {
!                   if (errbuf != NULL)
!                   {
!                       sprintf(errbuf,
!                               _(e_missing_number_after_angle_str_angle),
!                                                   transchar_byte(*(s - 1)));
!                       errmsg = errbuf;
!                   }
!                   else
!                       errmsg = "";
!                   break;
!               }
!           }
!           if (*s == ',')
!               ++s;
!           else if (*s)
!           {
!               if (errbuf != NULL)
!                   errmsg = e_missing_comma;
!               else
!                   errmsg = "";
!               break;
!           }
!       }
!       if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
!           errmsg = e_must_specify_a_value;
!     }
  #endif // FEAT_VIMINFO
  
      // terminal options
      else if (istermoption_idx(opt_idx) && full_screen)
!     {
!       // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co="
!       if (varp == &T_CCO)
!       {
!           int colors = atoi((char *)T_CCO);
! 
!           // Only reinitialize colors if t_Co value has really changed to
!           // avoid expensive reload of colorscheme if t_Co is set to the
!           // same value multiple times.
!           if (colors != t_colors)
!           {
!               t_colors = colors;
!               if (t_colors <= 1)
!               {
!                   vim_free(T_CCO);
!                   T_CCO = empty_option;
!               }
! #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
!               if (is_term_win32())
!               {
!                   swap_tcap();
!                   did_swaptcap = TRUE;
!               }
! #endif
!               // We now have a different color setup, initialize it again.
!               init_highlight(TRUE, FALSE);
!           }
!       }
!       ttest(FALSE);
!       if (varp == &T_ME)
!       {
!           out_str(T_ME);
!           redraw_later(UPD_CLEAR);
! #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
!           // Since t_me has been set, this probably means that the user
!           // wants to use this as default colors.  Need to reset default
!           // background/foreground colors.
! # ifdef VIMDLL
!           if (!gui.in_use && !gui.starting)
! # endif
!               mch_set_normal_colors();
! #endif
!       }
!       if (varp == &T_BE && termcap_active)
!       {
!           MAY_WANT_TO_LOG_THIS;
! 
!           if (*T_BE == NUL)
!               // When clearing t_BE we assume the user no longer wants
!               // bracketed paste, thus disable it by writing t_BD.
!               out_str(T_BD);
!           else
!               out_str(T_BE);
!       }
!     }
  
  #ifdef FEAT_LINEBREAK
      // 'showbreak'
      else if (gvarp == &p_sbr)
!     {
!       for (s = *varp; *s; )
!       {
!           if (ptr2cells(s) != 1)
!               errmsg = e_showbreak_contains_unprintable_or_wide_character;
!           MB_PTR_ADV(s);
!       }
!     }
  #endif
  
  #ifdef FEAT_GUI
      // 'guifont'
      else if (varp == &p_guifont)
!     {
!       if (gui.in_use)
!       {
!           p = p_guifont;
! # if defined(FEAT_GUI_GTK)
!           // Put up a font dialog and let the user select a new value.
!           // If this is cancelled go back to the old value but don't
!           // give an error message.
!           if (STRCMP(p, "*") == 0)
!           {
!               p = gui_mch_font_dialog(oldval);
!               free_string_option(p_guifont);
!               p_guifont = (p != NULL) ? p : vim_strsave(oldval);
!           }
! # endif
!           if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
!           {
! # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
!               if (STRCMP(p_guifont, "*") == 0)
!               {
!                   // Dialog was cancelled: Keep the old value without giving
!                   // an error message.
!                   free_string_option(p_guifont);
!                   p_guifont = vim_strsave(oldval);
!               }
!               else
! # endif
!                   errmsg = e_invalid_fonts;
!           }
!       }
!       redraw_gui_only = TRUE;
!     }
  # ifdef FEAT_XFONTSET
      else if (varp == &p_guifontset)
!     {
!       if (STRCMP(p_guifontset, "*") == 0)
!           errmsg = e_cant_select_fontset;
!       else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
!           errmsg = e_invalid_fontset;
!       redraw_gui_only = TRUE;
!     }
  # endif
      else if (varp == &p_guifontwide)
!     {
!       if (STRCMP(p_guifontwide, "*") == 0)
!           errmsg = e_cant_select_wide_font;
!       else if (gui_get_wide_font() == FAIL)
!           errmsg = e_invalid_wide_font;
!       redraw_gui_only = TRUE;
!     }
  #endif
! # if defined(FEAT_GUI_GTK)
      else if (varp == &p_guiligatures)
!     {
!       gui_set_ligatures();
!       redraw_gui_only = TRUE;
!     }
! # endif
  
  #ifdef CURSOR_SHAPE
      // 'guicursor'
--- 2585,2742 ----
  #ifdef FEAT_MULTI_LANG
      // 'helplang'
      else if (varp == &p_hlg)
!       errmsg = did_set_helplang();
  #endif
  
      // 'highlight'
      else if (varp == &p_hl)
!       errmsg = did_set_highlight();
  
      // 'nrformats'
      else if (gvarp == &p_nf)
!       errmsg = did_set_opt_strings(*varp, p_nf_values, TRUE);
  
  #ifdef FEAT_SESSION
      // 'sessionoptions'
      else if (varp == &p_ssop)
!       errmsg = did_set_sessionoptions(oldval);
! 
      // 'viewoptions'
      else if (varp == &p_vop)
!       errmsg = did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
  #endif
  
      // 'scrollopt'
      else if (varp == &p_sbo)
!       errmsg = did_set_opt_strings(p_sbo, p_scbopt_values, TRUE);
  
      // 'ambiwidth'
      else if (varp == &p_ambw || varp == &p_emoji)
!       errmsg = did_set_ambiwidth();
  
      // 'background'
      else if (varp == &p_bg)
!       errmsg = did_set_background();
  
      // 'wildmode'
      else if (varp == &p_wim)
!       errmsg = did_set_wildmode();
  
      // 'wildoptions'
      else if (varp == &p_wop)
!       errmsg = did_set_opt_strings(p_wop, p_wop_values, TRUE);
  
  #ifdef FEAT_WAK
      // 'winaltkeys'
      else if (varp == &p_wak)
!       errmsg = did_set_winaltkeys();
  #endif
  
      // 'eventignore'
      else if (varp == &p_ei)
!       errmsg = did_set_eventignore();
  
      // 'encoding', 'fileencoding', 'termencoding' and 'makeencoding'
      else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
                                                           || gvarp == &p_menc)
!       errmsg = did_set_encoding(varp, gvarp, opt_flags);
  
  #if defined(FEAT_POSTSCRIPT)
      else if (varp == &p_penc)
!       did_set_printencoding();
  #endif
  
  #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
      else if (varp == &p_imak)
!       errmsg = did_set_imactivatekey();
  #endif
  
  #ifdef FEAT_KEYMAP
      else if (varp == &curbuf->b_p_keymap)
!       errmsg = did_set_keymap(varp, opt_flags, value_checked);
  #endif
  
      // 'fileformat'
      else if (gvarp == &p_ff)
!       errmsg = did_set_fileformat(varp, oldval, opt_flags);
  
      // 'fileformats'
      else if (varp == &p_ffs)
!       errmsg = did_set_fileformats();
  
  #if defined(FEAT_CRYPT)
      // 'cryptkey'
      else if (gvarp == &p_key)
!       did_set_cryptkey(oldval);
  
+     // 'cryptmethod'
      else if (gvarp == &p_cm)
!       errmsg = did_set_cryptmethod(oldval, opt_flags);
  #endif
  
      // 'matchpairs'
      else if (gvarp == &p_mps)
!       errmsg = did_set_matchpairs(varp);
  
      // 'comments'
      else if (gvarp == &p_com)
!       errmsg = did_set_comments(varp, errbuf);
  
      // global 'listchars' or 'fillchars'
      else if (varp == &p_lcs || varp == &p_fcs)
!       errmsg = did_set_global_listfillchars(varp, opt_flags);
  
      // local 'listchars'
      else if (varp == &curwin->w_p_lcs)
        errmsg = set_chars_option(curwin, varp, TRUE);
  
      // local 'fillchars'
      else if (varp == &curwin->w_p_fcs)
        errmsg = set_chars_option(curwin, varp, TRUE);
  
      // 'cedit'
      else if (varp == &p_cedit)
        errmsg = check_cedit();
  
      // 'verbosefile'
      else if (varp == &p_vfile)
!       errmsg = did_set_verbosefile();
  
  #ifdef FEAT_VIMINFO
      // 'viminfo'
      else if (varp == &p_viminfo)
!       errmsg = did_set_viminfo(errbuf);
  #endif // FEAT_VIMINFO
  
      // terminal options
      else if (istermoption_idx(opt_idx) && full_screen)
!       did_set_term_option(varp, &did_swaptcap);
  
  #ifdef FEAT_LINEBREAK
      // 'showbreak'
      else if (gvarp == &p_sbr)
!       errmsg = did_set_showbreak(varp);
  #endif
  
  #ifdef FEAT_GUI
      // 'guifont'
      else if (varp == &p_guifont)
!       errmsg = did_set_guifont(oldval, &redraw_gui_only);
! 
  # ifdef FEAT_XFONTSET
+     // 'guifontset'
      else if (varp == &p_guifontset)
!       errmsg = did_set_guifontset(&redraw_gui_only);
  # endif
+ 
+     // 'guifontwide'
      else if (varp == &p_guifontwide)
!       errmsg = did_set_guifontwide(&redraw_gui_only);
  #endif
! #if defined(FEAT_GUI_GTK)
      else if (varp == &p_guiligatures)
!       did_set_guiligatures(&redraw_gui_only);
! #endif
  
  #ifdef CURSOR_SHAPE
      // 'guicursor'
***************
*** 1549,1558 ****
  #ifdef FEAT_MOUSESHAPE
      // 'mouseshape'
      else if (varp == &p_mouseshape)
!     {
!       errmsg = parse_shape_opt(SHAPE_MOUSE);
!       update_mouseshape(-1);
!     }
  #endif
  
  #ifdef FEAT_PRINTER
--- 2747,2753 ----
  #ifdef FEAT_MOUSESHAPE
      // 'mouseshape'
      else if (varp == &p_mouseshape)
!       errmsg = did_set_mouseshape();
  #endif
  
  #ifdef FEAT_PRINTER
***************
*** 1578,1729 ****
  
      // 'titlestring' and 'iconstring'
      else if (varp == &p_titlestring || varp == &p_iconstring)
!     {
! #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)
!           stl_syntax |= flagval;
!       else
!           stl_syntax &= ~flagval;
! #endif
!       did_set_title();
!     }
  
  #ifdef FEAT_GUI
      // 'guioptions'
      else if (varp == &p_go)
!     {
!       gui_init_which_components(oldval);
!       redraw_gui_only = TRUE;
!     }
  #endif
  
  #if defined(FEAT_GUI_TABLINE)
      // 'guitablabel'
      else if (varp == &p_gtl)
!     {
!       redraw_tabline = TRUE;
!       redraw_gui_only = TRUE;
!     }
      // 'guitabtooltip'
      else if (varp == &p_gtt)
-     {
        redraw_gui_only = TRUE;
-     }
  #endif
  
  #if defined(UNIX) || defined(VMS)
      // 'ttymouse'
      else if (varp == &p_ttym)
!     {
!       // Switch the mouse off before changing the escape sequences used for
!       // that.
!       mch_setmouse(FALSE);
!       if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
!           errmsg = e_invalid_argument;
!       else
!           check_mouse_termcode();
!       if (termcap_active)
!           setmouse();         // may switch it on again
!     }
  #endif
  
      // 'selection'
      else if (varp == &p_sel)
!     {
!       if (*p_sel == NUL
!               || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'selectmode'
      else if (varp == &p_slm)
!     {
!       if (check_opt_strings(p_slm, p_slm_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_BROWSE
      // 'browsedir'
      else if (varp == &p_bsdir)
!     {
!       if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
!               && !mch_isdir(p_bsdir))
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      // 'keymodel'
      else if (varp == &p_km)
!     {
!       if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           km_stopsel = (vim_strchr(p_km, 'o') != NULL);
!           km_startsel = (vim_strchr(p_km, 'a') != NULL);
!       }
!     }
  
      // 'keyprotocol'
      else if (varp == &p_kpc)
!     {
!       if (match_keyprotocol(NULL) == KEYPROTOCOL_FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'mousemodel'
      else if (varp == &p_mousem)
!     {
!       if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
! #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
!       else if (*p_mousem != *oldval)
!           // Changed from "extend" to "popup" or "popup_setpos" or vv: need
!           // to create or delete the popup menus.
!           gui_motif_update_mousemodel(root_menu);
! #endif
!     }
  
      // 'switchbuf'
      else if (varp == &p_swb)
!     {
!       if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'splitkeep'
      else if (varp == &p_spk)
!     {
!       if (check_opt_strings(p_spk, p_spk_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'debug'
      else if (varp == &p_debug)
!     {
!       if (check_opt_strings(p_debug, p_debug_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'display'
      else if (varp == &p_dy)
!     {
!       if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else
!           (void)init_chartab();
! 
!     }
  
      // 'eadirection'
      else if (varp == &p_ead)
!     {
!       if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_CLIPBOARD
      // 'clipboard'
--- 2773,2846 ----
  
      // 'titlestring' and 'iconstring'
      else if (varp == &p_titlestring || varp == &p_iconstring)
!       did_set_titleiconstring(varp);
  
  #ifdef FEAT_GUI
      // 'guioptions'
      else if (varp == &p_go)
!       did_set_guioptions(oldval, &redraw_gui_only);
  #endif
  
  #if defined(FEAT_GUI_TABLINE)
      // 'guitablabel'
      else if (varp == &p_gtl)
!       did_set_guitablabel(&redraw_gui_only);
      // 'guitabtooltip'
      else if (varp == &p_gtt)
        redraw_gui_only = TRUE;
  #endif
  
  #if defined(UNIX) || defined(VMS)
      // 'ttymouse'
      else if (varp == &p_ttym)
!       errmsg = did_set_ttymouse();
  #endif
  
      // 'selection'
      else if (varp == &p_sel)
!       errmsg = did_set_selection();
  
      // 'selectmode'
      else if (varp == &p_slm)
!       errmsg = did_set_opt_strings(p_slm, p_slm_values, TRUE);
  
  #ifdef FEAT_BROWSE
      // 'browsedir'
      else if (varp == &p_bsdir)
!       errmsg = did_set_browsedir();
  #endif
  
      // 'keymodel'
      else if (varp == &p_km)
!       errmsg = did_set_keymodel();
  
      // 'keyprotocol'
      else if (varp == &p_kpc)
!       errmsg = did_set_keyprotocol();
  
      // 'mousemodel'
      else if (varp == &p_mousem)
!       errmsg = did_set_mousemodel();
  
      // 'switchbuf'
      else if (varp == &p_swb)
!       errmsg = did_set_opt_flags(p_swb, p_swb_values, &swb_flags, TRUE);
  
      // 'splitkeep'
      else if (varp == &p_spk)
!       errmsg = did_set_opt_strings(p_spk, p_spk_values, FALSE);
  
      // 'debug'
      else if (varp == &p_debug)
!       errmsg = did_set_opt_strings(p_debug, p_debug_values, TRUE);
  
      // 'display'
      else if (varp == &p_dy)
!       errmsg = did_set_display();
  
      // 'eadirection'
      else if (varp == &p_ead)
!       errmsg = did_set_opt_strings(p_ead, p_ead_values, FALSE);
  
  #ifdef FEAT_CLIPBOARD
      // 'clipboard'
***************
*** 1732,1877 ****
  #endif
  
  #ifdef FEAT_SPELL
!     // When 'spelllang' or 'spellfile' is set and there is a window for this
!     // buffer in which 'spell' is set load the wordlists.
!     else if (varp == &(curwin->w_s->b_p_spl)
!           || varp == &(curwin->w_s->b_p_spf))
!     {
!       int     is_spellfile = varp == &(curwin->w_s->b_p_spf);
  
!       if ((is_spellfile && !valid_spellfile(*varp))
!               || (!is_spellfile && !valid_spelllang(*varp)))
!           errmsg = e_invalid_argument;
!       else
!           errmsg = did_set_spell_option(is_spellfile);
!     }
!     // When 'spellcapcheck' is set compile the regexp program.
      else if (varp == &(curwin->w_s->b_p_spc))
!     {
!       errmsg = compile_cap_prog(curwin->w_s);
!     }
      // 'spelloptions'
      else if (varp == &(curwin->w_s->b_p_spo))
!     {
!       if (**varp != NUL && STRCMP("camel", *varp) != 0)
!           errmsg = e_invalid_argument;
!     }
      // 'spellsuggest'
      else if (varp == &p_sps)
!     {
!       if (spell_check_sps() != OK)
!           errmsg = e_invalid_argument;
!     }
      // 'mkspellmem'
      else if (varp == &p_msm)
!     {
!       if (spell_check_msm() != OK)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      // When 'bufhidden' is set, check for valid value.
      else if (gvarp == &p_bh)
!     {
!       if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // When 'buftype' is set, check for valid value.
      else if (gvarp == &p_bt)
!     {
!       if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           if (curwin->w_status_height)
!           {
!               curwin->w_redr_status = TRUE;
!               redraw_later(UPD_VALID);
!           }
!           curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
!           redraw_titles();
!       }
!     }
  
  #ifdef FEAT_STL_OPT
      // 'statusline', 'tabline' or 'rulerformat'
      else if (gvarp == &p_stl || varp == &p_tal || varp == &p_ruf)
!     {
!       int wid;
! 
!       if (varp == &p_ruf)     // reset ru_wid first
!           ru_wid = 0;
!       s = *varp;
!       if (varp == &p_ruf && *s == '%')
!       {
!           // set ru_wid if 'ruf' starts with "%99("
!           if (*++s == '-')    // ignore a '-'
!               s++;
!           wid = getdigits(&s);
!           if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
!               ru_wid = wid;
!           else
!               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] != '!')
!           errmsg = check_stl_option(s);
!       if (varp == &p_ruf && errmsg == NULL)
!           comp_col();
!     }
  #endif
  
!     // check if it is a valid value for 'complete' -- Acevedo
      else if (gvarp == &p_cpt)
!     {
!       for (s = *varp; *s;)
!       {
!           while (*s == ',' || *s == ' ')
!               s++;
!           if (!*s)
!               break;
!           if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
!           {
!               errmsg = illegal_char(errbuf, *s);
!               break;
!           }
!           if (*++s != NUL && *s != ',' && *s != ' ')
!           {
!               if (s[-1] == 'k' || s[-1] == 's')
!               {
!                   // skip optional filename after 'k' and 's'
!                   while (*s && *s != ',' && *s != ' ')
!                   {
!                       if (*s == '\\' && s[1] != NUL)
!                           ++s;
!                       ++s;
!                   }
!               }
!               else
!               {
!                   if (errbuf != NULL)
!                   {
!                       sprintf((char *)errbuf,
!                                      _(e_illegal_character_after_chr), *--s);
!                       errmsg = errbuf;
!                   }
!                   else
!                       errmsg = "";
!                   break;
!               }
!           }
!       }
!     }
  
      // 'completeopt'
      else if (varp == &p_cot)
!     {
!       if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else
!           completeopt_was_set();
!     }
  
  #ifdef BACKSLASH_IN_FILENAME
      // 'completeslash'
--- 2849,2901 ----
  #endif
  
  #ifdef FEAT_SPELL
!     // 'spellfile'
!     else if (varp == &(curwin->w_s->b_p_spf))
!       errmsg = did_set_spellfile(varp);
! 
!     // 'spell'
!     else if (varp == &(curwin->w_s->b_p_spl))
!       errmsg = did_set_spell(varp);
  
!     // 'spellcapcheck'
      else if (varp == &(curwin->w_s->b_p_spc))
!       errmsg = did_set_spellcapcheck();
! 
      // 'spelloptions'
      else if (varp == &(curwin->w_s->b_p_spo))
!       errmsg = did_set_spelloptions(varp);
! 
      // 'spellsuggest'
      else if (varp == &p_sps)
!       errmsg = did_set_spellsuggest();
! 
      // 'mkspellmem'
      else if (varp == &p_msm)
!       errmsg = did_set_mkspellmem();
  #endif
  
      // When 'bufhidden' is set, check for valid value.
      else if (gvarp == &p_bh)
!       errmsg = did_set_opt_strings(curbuf->b_p_bh, p_bufhidden_values,
!                                                               FALSE);
  
      // When 'buftype' is set, check for valid value.
      else if (gvarp == &p_bt)
!       errmsg = did_set_buftype();
  
  #ifdef FEAT_STL_OPT
      // 'statusline', 'tabline' or 'rulerformat'
      else if (gvarp == &p_stl || varp == &p_tal || varp == &p_ruf)
!       errmsg = did_set_statusline(varp);
  #endif
  
!     // 'complete'
      else if (gvarp == &p_cpt)
!       errmsg = did_set_complete(varp, errbuf);
  
      // 'completeopt'
      else if (varp == &p_cot)
!       errmsg = did_set_completeopt();
  
  #ifdef BACKSLASH_IN_FILENAME
      // 'completeslash'
***************
*** 1886,2303 ****
  #ifdef FEAT_SIGNS
      // 'signcolumn'
      else if (varp == &curwin->w_p_scl)
!     {
!       if (check_opt_strings(*varp, p_scl_values, FALSE) != OK)
!           errmsg = 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')
!               || (*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;
!     }
  #endif
  
      // 'showcmdloc'
      else if (varp == &p_sloc)
!     {
!       if (check_opt_strings(p_sloc, p_sloc_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
      // 'toolbar'
      else if (varp == &p_toolbar)
!     {
!       if (opt_strings_flags(p_toolbar, p_toolbar_values,
!                             &toolbar_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           out_flush();
!           gui_mch_show_toolbar((toolbar_flags &
!                                 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
!       }
!     }
  #endif
  
  #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
      // 'toolbariconsize': GTK+ 2 only
      else if (varp == &p_tbis)
!     {
!       if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
!           errmsg = e_invalid_argument;
!       else
!       {
!           out_flush();
!           gui_mch_show_toolbar((toolbar_flags &
!                                 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
!       }
!     }
  #endif
  
!     // 'pastetoggle': translate key codes like in a mapping
      else if (varp == &p_pt)
!     {
!       if (*p_pt)
!       {
!           (void)replace_termcodes(p_pt, &p,
!                                     REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
!           if (p != NULL)
!           {
!               free_string_option(p_pt);
!               p_pt = p;
!           }
!       }
!     }
  
      // 'backspace'
      else if (varp == &p_bs)
!     {
!       if (VIM_ISDIGIT(*p_bs))
!       {
!           if (*p_bs > '3' || p_bs[1] != NUL)
!               errmsg = e_invalid_argument;
!       }
!       else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
      else if (varp == &p_bo)
!     {
!       if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'tagcase'
      else if (gvarp == &p_tc)
!     {
!       unsigned int    *flags;
! 
!       if (opt_flags & OPT_LOCAL)
!       {
!           p = curbuf->b_p_tc;
!           flags = &curbuf->b_tc_flags;
!       }
!       else
!       {
!           p = p_tc;
!           flags = &tc_flags;
!       }
! 
!       if ((opt_flags & OPT_LOCAL) && *p == NUL)
!           // make the local value empty: use the global value
!           *flags = 0;
!       else if (*p == NUL
!               || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
      // 'casemap'
      else if (varp == &p_cmp)
!     {
!       if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_DIFF
      // 'diffopt'
      else if (varp == &p_dip)
!     {
!       if (diffopt_changed() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
  #ifdef FEAT_FOLDING
      // 'foldmethod'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fdm)
!     {
!       if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
!               || *curwin->w_p_fdm == NUL)
!           errmsg = e_invalid_argument;
!       else
!       {
!           foldUpdateAll(curwin);
!           if (foldmethodIsDiff(curwin))
!               newFoldLevel();
!       }
!     }
      // 'foldmarker'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)
!     {
!       p = vim_strchr(*varp, ',');
!       if (p == NULL)
!           errmsg = e_comma_required;
!       else if (p == *varp || p[1] == NUL)
!           errmsg = e_invalid_argument;
!       else if (foldmethodIsMarker(curwin))
!           foldUpdateAll(curwin);
!     }
      // 'commentstring'
      else if (gvarp == &p_cms)
!     {
!       if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
!           errmsg = e_commentstring_must_be_empty_or_contain_str;
!     }
      // 'foldopen'
      else if (varp == &p_fdo)
!     {
!       if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
      // 'foldclose'
      else if (varp == &p_fcl)
!     {
!       if (check_opt_strings(p_fcl, p_fcl_values, TRUE) != OK)
!           errmsg = e_invalid_argument;
!     }
      // 'foldignore'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fdi)
!     {
!       if (foldmethodIsIndent(curwin))
!           foldUpdateAll(curwin);
!     }
  #endif
  
      // 'virtualedit'
      else if (gvarp == &p_ve)
!     {
!       char_u          *ve = p_ve;
!       unsigned int    *flags = &ve_flags;
! 
!       if (opt_flags & OPT_LOCAL)
!       {
!           ve = curwin->w_p_ve;
!           flags = &curwin->w_ve_flags;
!       }
! 
!       if ((opt_flags & OPT_LOCAL) && *ve == NUL)
!           // make the local value empty: use the global value
!           *flags = 0;
!       else
!       {
!           if (opt_strings_flags(ve, p_ve_values, flags, TRUE) != OK)
!               errmsg = e_invalid_argument;
!           else if (STRCMP(ve, oldval) != 0)
!           {
!               // Recompute cursor position in case the new 've' setting
!               // changes something.
!               validate_virtcol();
!               coladvance(curwin->w_virtcol);
!           }
!       }
!     }
  
  #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
      else if (varp == &p_csqf)
!     {
!       if (p_csqf != NULL)
!       {
!           p = p_csqf;
!           while (*p != NUL)
!           {
!               if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
!                       || p[1] == NUL
!                       || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
!                       || (p[2] != NUL && p[2] != ','))
!               {
!                   errmsg = e_invalid_argument;
!                   break;
!               }
!               else if (p[2] == NUL)
!                   break;
!               else
!                   p += 3;
!           }
!       }
!     }
  #endif
  
      // 'cinoptions'
      else if (gvarp == &p_cino)
!     {
!       // TODO: recognize errors
!       parse_cino(curbuf);
!     }
  
      // 'lispoptions'
      else if (gvarp == &p_lop)
!     {
!       if (**varp != NUL && STRCMP(*varp, "expr:0") != 0
!                                              && STRCMP(*varp, "expr:1") != 0)
!           errmsg = e_invalid_argument;
!     }
  
  #if defined(FEAT_RENDER_OPTIONS)
      // 'renderoptions'
      else if (varp == &p_rop)
!     {
!       if (!gui_mch_set_rendering_options(p_rop))
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      else if (gvarp == &p_ft)
!     {
!       if (!valid_filetype(*varp))
!           errmsg = e_invalid_argument;
!       else
!       {
!           value_changed = STRCMP(oldval, *varp) != 0;
! 
!           // Since we check the value, there is no need to set P_INSECURE,
!           // even when the value comes from a modeline.
!           *value_checked = TRUE;
!       }
!     }
  
  #ifdef FEAT_SYN_HL
      else if (gvarp == &p_syn)
!     {
!       if (!valid_filetype(*varp))
!           errmsg = e_invalid_argument;
!       else
!       {
!           value_changed = STRCMP(oldval, *varp) != 0;
! 
!           // Since we check the value, there is no need to set P_INSECURE,
!           // even when the value comes from a modeline.
!           *value_checked = TRUE;
!       }
!     }
  #endif
  
  #ifdef FEAT_TERMINAL
      // 'termwinkey'
      else if (varp == &curwin->w_p_twk)
!     {
!       if (*curwin->w_p_twk != NUL
!                                 && string_to_key(curwin->w_p_twk, TRUE) == 0)
!           errmsg = e_invalid_argument;
!     }
      // 'termwinsize'
      else if (varp == &curwin->w_p_tws)
!     {
!       if (*curwin->w_p_tws != NUL)
!       {
!           p = skipdigits(curwin->w_p_tws);
!           if (p == curwin->w_p_tws
!                   || (*p != 'x' && *p != '*')
!                   || *skipdigits(p + 1) != NUL)
!               errmsg = e_invalid_argument;
!       }
!     }
      // 'wincolor'
      else if (varp == &curwin->w_p_wcr)
        term_update_wincolor(curwin);
  # if defined(MSWIN)
      // 'termwintype'
      else if (varp == &p_twt)
!     {
!       if (check_opt_strings(*varp, p_twt_values, FALSE) != OK)
!           errmsg = e_invalid_argument;
!     }
  # endif
  #endif
  
  #ifdef FEAT_VARTABS
      // 'varsofttabstop'
      else if (varp == &(curbuf->b_p_vsts))
!     {
!       char_u *cp;
! 
!       if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
!       {
!           if (curbuf->b_p_vsts_array)
!           {
!               vim_free(curbuf->b_p_vsts_array);
!               curbuf->b_p_vsts_array = 0;
!           }
!       }
!       else
!       {
!           for (cp = *varp; *cp; ++cp)
!           {
!               if (vim_isdigit(*cp))
!                   continue;
!               if (*cp == ',' && cp > *varp && *(cp-1) != ',')
!                   continue;
!               errmsg = e_invalid_argument;
!               break;
!           }
!           if (errmsg == NULL)
!           {
!               int *oldarray = curbuf->b_p_vsts_array;
!               if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)) == OK)
!               {
!                   if (oldarray)
!                       vim_free(oldarray);
!               }
!               else
!                   errmsg = e_invalid_argument;
!           }
!       }
!     }
  
      // 'vartabstop'
      else if (varp == &(curbuf->b_p_vts))
!     {
!       char_u *cp;
! 
!       if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
!       {
!           if (curbuf->b_p_vts_array)
!           {
!               vim_free(curbuf->b_p_vts_array);
!               curbuf->b_p_vts_array = NULL;
!           }
!       }
!       else
!       {
!           for (cp = *varp; *cp; ++cp)
!           {
!               if (vim_isdigit(*cp))
!                   continue;
!               if (*cp == ',' && cp > *varp && *(cp-1) != ',')
!                   continue;
!               errmsg = e_invalid_argument;
!               break;
!           }
!           if (errmsg == NULL)
!           {
!               int *oldarray = curbuf->b_p_vts_array;
! 
!               if (tabstop_set(*varp, &(curbuf->b_p_vts_array)) == OK)
!               {
!                   vim_free(oldarray);
! #ifdef FEAT_FOLDING
!                   if (foldmethodIsIndent(curwin))
!                       foldUpdateAll(curwin);
! #endif
!               }
!               else
!                   errmsg = e_invalid_argument;
!           }
!       }
!     }
  #endif
  
  #ifdef FEAT_PROP_POPUP
      // 'previewpopup'
      else if (varp == &p_pvp)
!     {
!       if (parse_previewpopup(NULL) == FAIL)
!           errmsg = e_invalid_argument;
!     }
  # ifdef FEAT_QUICKFIX
      // 'completepopup'
      else if (varp == &p_cpp)
!     {
!       if (parse_completepopup(NULL) == FAIL)
!           errmsg = e_invalid_argument;
!       else
!           popup_close_info();
!     }
  # endif
  #endif
  
--- 2910,3059 ----
  #ifdef FEAT_SIGNS
      // 'signcolumn'
      else if (varp == &curwin->w_p_scl)
!       errmsg = did_set_signcolumn(varp, oldval);
  #endif
  
      // 'showcmdloc'
      else if (varp == &p_sloc)
!       errmsg = did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
  
  #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
      // 'toolbar'
      else if (varp == &p_toolbar)
!       errmsg = did_set_toolbar();
  #endif
  
  #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
      // 'toolbariconsize': GTK+ 2 only
      else if (varp == &p_tbis)
!       errmsg = did_set_toolbariconsize();
  #endif
  
!     // 'pastetoggle'
      else if (varp == &p_pt)
!       did_set_pastetoggle();
  
      // 'backspace'
      else if (varp == &p_bs)
!       errmsg = did_set_backspace();
! 
!     // 'belloff'
      else if (varp == &p_bo)
!       errmsg = did_set_opt_flags(p_bo, p_bo_values, &bo_flags, TRUE);
  
      // 'tagcase'
      else if (gvarp == &p_tc)
!       errmsg = did_set_tagcase(opt_flags);
  
      // 'casemap'
      else if (varp == &p_cmp)
!       errmsg = did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
  
  #ifdef FEAT_DIFF
      // 'diffopt'
      else if (varp == &p_dip)
!       errmsg = did_set_diffopt();
  #endif
  
  #ifdef FEAT_FOLDING
      // 'foldmethod'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fdm)
!       errmsg = did_set_foldmethod(varp);
! 
      // 'foldmarker'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)
!       errmsg = did_set_foldmarker(varp);
! 
      // 'commentstring'
      else if (gvarp == &p_cms)
!       errmsg = did_set_commentstring(varp);
! 
      // 'foldopen'
      else if (varp == &p_fdo)
!       errmsg = did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
! 
      // 'foldclose'
      else if (varp == &p_fcl)
!       errmsg = did_set_opt_strings(p_fcl, p_fcl_values, TRUE);
! 
      // 'foldignore'
      else if (gvarp == &curwin->w_allbuf_opt.wo_fdi)
!       did_set_foldignore();
  #endif
  
      // 'virtualedit'
      else if (gvarp == &p_ve)
!       errmsg = did_set_virtualedit(oldval, opt_flags);
  
  #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
+     // 'cscopequickfix'
      else if (varp == &p_csqf)
!       errmsg = did_set_cscopequickfix();
  #endif
  
      // 'cinoptions'
      else if (gvarp == &p_cino)
!       did_set_cinoptions();
  
      // 'lispoptions'
      else if (gvarp == &p_lop)
!       errmsg = did_set_lispoptions(varp);
  
  #if defined(FEAT_RENDER_OPTIONS)
      // 'renderoptions'
      else if (varp == &p_rop)
!       errmsg = did_set_renderoptions();
  #endif
  
+     // 'filetype'
      else if (gvarp == &p_ft)
!       errmsg = did_set_filetype_or_syntax(varp, oldval, value_checked,
!                                                       &value_changed);
  
  #ifdef FEAT_SYN_HL
+     // 'syntax'
      else if (gvarp == &p_syn)
!       errmsg = did_set_filetype_or_syntax(varp, oldval, value_checked,
!                                                       &value_changed);
  #endif
  
  #ifdef FEAT_TERMINAL
      // 'termwinkey'
      else if (varp == &curwin->w_p_twk)
!       errmsg = did_set_termwinkey();
! 
      // 'termwinsize'
      else if (varp == &curwin->w_p_tws)
!       errmsg = did_set_termwinsize();
! 
      // 'wincolor'
      else if (varp == &curwin->w_p_wcr)
        term_update_wincolor(curwin);
  # if defined(MSWIN)
      // 'termwintype'
      else if (varp == &p_twt)
!       errmsg = did_set_opt_strings(p_twt, p_twt_values, FALSE);
  # endif
  #endif
  
  #ifdef FEAT_VARTABS
      // 'varsofttabstop'
      else if (varp == &(curbuf->b_p_vsts))
!       errmsg = did_set_varsofttabstop(varp);
  
      // 'vartabstop'
      else if (varp == &(curbuf->b_p_vts))
!       errmsg = did_set_vartabstop(varp);
  #endif
  
  #ifdef FEAT_PROP_POPUP
      // 'previewpopup'
      else if (varp == &p_pvp)
!       errmsg = did_set_previewpopup();
  # ifdef FEAT_QUICKFIX
      // 'completepopup'
      else if (varp == &p_cpp)
!       errmsg = did_set_completepopup();
  # endif
  #endif
  
***************
*** 2326,2411 ****
            varp == &p_pexpr ||
  # endif
            varp == &p_ccv)
!     {
!       // If the option value starts with <SID> or s:, then replace that with
!       // the script identifier.
!       char_u *name = get_scriptlocal_funcname(*varp);
!       if (name != NULL)
!       {
!           free_string_option(*varp);
!           *varp = name;
!       }
! 
! # ifdef FEAT_FOLDING
!       if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin))
!           foldUpdateAll(curwin);
! # endif
!     }
  #endif
  
  #ifdef FEAT_COMPL_FUNC
      // 'completefunc'
      else if (gvarp == &p_cfu)
!     {
!       if (set_completefunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'omnifunc'
      else if (gvarp == &p_ofu)
!     {
!       if (set_omnifunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'thesaurusfunc'
      else if (gvarp == &p_tsrfu)
!     {
!       if (set_thesaurusfunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
  #if defined(FEAT_EVAL) && \
       (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
      // 'imactivatefunc'
      else if (gvarp == &p_imaf)
!     {
!       if (set_imactivatefunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
      // 'imstatusfunc'
      else if (gvarp == &p_imsf)
!     {
!       if (set_imstatusfunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      // 'operatorfunc'
      else if (varp == &p_opfunc)
!     {
!       if (set_operatorfunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  
  #ifdef FEAT_QUICKFIX
      // 'quickfixtextfunc'
      else if (varp == &p_qftf)
!     {
!       if (qf_process_qftf_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
  #ifdef FEAT_EVAL
      // 'tagfunc'
      else if (gvarp == &p_tfu)
!     {
!       if (set_tagfunc_option() == FAIL)
!           errmsg = e_invalid_argument;
!     }
  #endif
  
      // Options that are a list of flags.
--- 3082,3129 ----
            varp == &p_pexpr ||
  # endif
            varp == &p_ccv)
!       did_set_optexpr(varp);
  #endif
  
  #ifdef FEAT_COMPL_FUNC
      // 'completefunc'
      else if (gvarp == &p_cfu)
!       errmsg = set_completefunc_option();
  
      // 'omnifunc'
      else if (gvarp == &p_ofu)
!       errmsg = set_omnifunc_option();
  
      // 'thesaurusfunc'
      else if (gvarp == &p_tsrfu)
!       errmsg = set_thesaurusfunc_option();
  #endif
  
  #if defined(FEAT_EVAL) && \
       (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
      // 'imactivatefunc'
      else if (gvarp == &p_imaf)
!       errmsg = set_imactivatefunc_option();
  
      // 'imstatusfunc'
      else if (gvarp == &p_imsf)
!       errmsg = set_imstatusfunc_option();
  #endif
  
      // 'operatorfunc'
      else if (varp == &p_opfunc)
!       errmsg = set_operatorfunc_option();
  
  #ifdef FEAT_QUICKFIX
      // 'quickfixtextfunc'
      else if (varp == &p_qftf)
!       errmsg = qf_process_qftf_option();
  #endif
  
  #ifdef FEAT_EVAL
      // 'tagfunc'
      else if (gvarp == &p_tfu)
!       errmsg = set_tagfunc_option();
  #endif
  
      // Options that are a list of flags.
*** ../vim-9.0.1261/src/proto/gui_xim.pro       2022-06-27 23:15:07.000000000 
+0100
--- src/proto/gui_xim.pro       2023-01-30 12:55:05.458365091 +0000
***************
*** 1,6 ****
  /* gui_xim.c */
! int set_imactivatefunc_option(void);
! int set_imstatusfunc_option(void);
  void free_xim_stuff(void);
  int set_ref_in_im_funcs(int copyID);
  void im_set_active(int active);
--- 1,6 ----
  /* gui_xim.c */
! char *set_imactivatefunc_option(void);
! char *set_imstatusfunc_option(void);
  void free_xim_stuff(void);
  int set_ref_in_im_funcs(int copyID);
  void im_set_active(int active);
*** ../vim-9.0.1261/src/proto/insexpand.pro     2022-06-27 23:15:11.000000000 
+0100
--- src/proto/insexpand.pro     2023-01-30 12:55:05.458365091 +0000
***************
*** 44,54 ****
  void ins_compl_addleader(int c);
  void ins_compl_addfrommatch(void);
  int ins_compl_prep(int c);
! int set_completefunc_option(void);
  void set_buflocal_cfu_callback(buf_T *buf);
! int set_omnifunc_option(void);
  void set_buflocal_ofu_callback(buf_T *buf);
! int set_thesaurusfunc_option(void);
  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);
--- 44,54 ----
  void ins_compl_addleader(int c);
  void ins_compl_addfrommatch(void);
  int ins_compl_prep(int c);
! char *set_completefunc_option(void);
  void set_buflocal_cfu_callback(buf_T *buf);
! char *set_omnifunc_option(void);
  void set_buflocal_ofu_callback(buf_T *buf);
! char *set_thesaurusfunc_option(void);
  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);
*** ../vim-9.0.1261/src/proto/ops.pro   2022-06-27 23:15:17.000000000 +0100
--- src/proto/ops.pro   2023-01-30 12:55:05.458365091 +0000
***************
*** 17,23 ****
  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);
! int set_operatorfunc_option(void);
  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);
--- 17,23 ----
  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);
  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);
*** ../vim-9.0.1261/src/proto/quickfix.pro      2022-10-14 13:11:10.128828896 
+0100
--- src/proto/quickfix.pro      2023-01-30 12:55:05.458365091 +0000
***************
*** 15,21 ****
  void ex_copen(exarg_T *eap);
  void ex_cbottom(exarg_T *eap);
  linenr_T qf_current_entry(win_T *wp);
! int qf_process_qftf_option(void);
  int grep_internal(cmdidx_T cmdidx);
  void ex_make(exarg_T *eap);
  int qf_get_size(exarg_T *eap);
--- 15,21 ----
  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);
  int grep_internal(cmdidx_T cmdidx);
  void ex_make(exarg_T *eap);
  int qf_get_size(exarg_T *eap);
*** ../vim-9.0.1261/src/proto/tag.pro   2022-06-27 23:15:24.000000000 +0100
--- src/proto/tag.pro   2023-01-30 12:55:05.458365091 +0000
***************
*** 1,5 ****
  /* tag.c */
! int set_tagfunc_option(void);
  void free_tagfunc_option(void);
  int set_ref_in_tagfunc(int copyID);
  void set_buflocal_tfu_callback(buf_T *buf);
--- 1,5 ----
  /* tag.c */
! char *set_tagfunc_option(void);
  void free_tagfunc_option(void);
  int set_ref_in_tagfunc(int copyID);
  void set_buflocal_tfu_callback(buf_T *buf);
*** ../vim-9.0.1261/src/quickfix.c      2023-01-22 21:14:32.617863616 +0000
--- src/quickfix.c      2023-01-30 12:55:05.458365091 +0000
***************
*** 4533,4542 ****
   * Process the 'quickfixtextfunc' option value.
   * Returns OK or FAIL.
   */
!     int
  qf_process_qftf_option(void)
  {
!     return option_set_callback_func(p_qftf, &qftf_cb);
  }
  
  /*
--- 4533,4545 ----
   * Process the 'quickfixtextfunc' option value.
   * Returns OK or FAIL.
   */
!     char *
  qf_process_qftf_option(void)
  {
!     if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL)
!       return e_invalid_argument;
! 
!     return NULL;
  }
  
  /*
*** ../vim-9.0.1261/src/spell.c 2023-01-23 20:46:16.166493150 +0000
--- src/spell.c 2023-01-30 12:55:05.458365091 +0000
***************
*** 4386,4392 ****
  }
  
  /*
!  * Handle side effects of setting 'spell'.
   * Return an error message or NULL for success.
   */
      char *
--- 4386,4392 ----
  }
  
  /*
!  * Handle side effects of setting 'spell' or 'spellfile'
   * Return an error message or NULL for success.
   */
      char *
*** ../vim-9.0.1261/src/tag.c   2023-01-27 21:03:08.899101847 +0000
--- src/tag.c   2023-01-30 12:55:05.458365091 +0000
***************
*** 170,176 ****
   * Invoked when the 'tagfunc' option is set. The option value can be a name of
   * a function (string), or function(<name>) or funcref(<name>) or a lambda.
   */
!     int
  set_tagfunc_option(void)
  {
  #ifdef FEAT_EVAL
--- 170,176 ----
   * Invoked when the 'tagfunc' option is set. The option value can be a name of
   * a function (string), or function(<name>) or funcref(<name>) or a lambda.
   */
!     char *
  set_tagfunc_option(void)
  {
  #ifdef FEAT_EVAL
***************
*** 178,192 ****
      free_callback(&curbuf->b_tfu_cb);
  
      if (*curbuf->b_p_tfu == NUL)
!       return OK;
  
      if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL)
!       return FAIL;
  
      copy_callback(&curbuf->b_tfu_cb, &tfu_cb);
  #endif
  
!     return OK;
  }
  #endif
  
--- 178,192 ----
      free_callback(&curbuf->b_tfu_cb);
  
      if (*curbuf->b_p_tfu == NUL)
!       return NULL;
  
      if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL)
!       return e_invalid_argument;
  
      copy_callback(&curbuf->b_tfu_cb, &tfu_cb);
  #endif
  
!     return NULL;
  }
  #endif
  
*** ../vim-9.0.1261/src/version.c       2023-01-29 17:50:10.917568887 +0000
--- src/version.c       2023-01-30 12:59:29.238081566 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1262,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
65. The last time you looked at the clock it was 11:30pm, and in what
    seems like only a few seconds later, your sister runs past you to
    catch her 7am school bus.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230130130519.9A9DC1C0723%40moolenaar.net.

Raspunde prin e-mail lui