To: vim_dev@googlegroups.com Subject: Patch 9.0.0537 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0537 Problem: The do_set() function is much too long. Solution: Move setting of a string option to a separate function. Files: src/option.c *** ../vim-9.0.0536/src/option.c 2022-09-12 13:35:06.514946763 +0100 --- src/option.c 2022-09-21 21:10:26.865408272 +0100 *************** *** 1205,1210 **** --- 1205,1635 ---- } } + typedef enum { + OP_NONE = 0, + OP_ADDING, // "opt+=arg" + OP_PREPENDING, // "opt^=arg" + OP_REMOVING, // "opt-=arg" + } set_op_T; + + /* + * Part of do_set() for string options. + * Returns FAIL on failure, do not process further options. + */ + static int + do_set_string( + int opt_idx, + int opt_flags, + char_u **arg, + int nextchar, + set_op_T op_arg, + int flags, + int cp_val, + char_u *varp_arg, + char *errbuf, + int *value_checked, + char **errmsg) + { + set_op_T op = op_arg; + char_u *varp = varp_arg; + char_u *save_arg = NULL; + char_u *s = NULL; + char_u *oldval = NULL; // previous value if *varp + char_u *newval; + char_u *origval = NULL; + char_u *origval_l = NULL; + char_u *origval_g = NULL; + #if defined(FEAT_EVAL) + char_u *saved_origval = NULL; + char_u *saved_origval_l = NULL; + char_u *saved_origval_g = NULL; + char_u *saved_newval = NULL; + #endif + unsigned newlen; + int comma; + char_u whichwrap[80]; + + // When using ":set opt=val" for a global option + // with a local value the local value will be + // reset, use the global value here. + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + && ((int)options[opt_idx].indir & PV_BOTH)) + varp = options[opt_idx].var; + + // The old value is kept until we are sure that the new value is valid. + oldval = *(char_u **)varp; + + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) + { + origval_l = *(char_u **)get_varp_scope( + &(options[opt_idx]), OPT_LOCAL); + origval_g = *(char_u **)get_varp_scope( + &(options[opt_idx]), OPT_GLOBAL); + + // A global-local string option might have an empty option as value to + // indicate that the global value should be used. + if (((int)options[opt_idx].indir & PV_BOTH) + && origval_l == empty_option) + origval_l = origval_g; + } + + // When setting the local value of a global option, the old value may be + // the global value. + if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) + origval = *(char_u **)get_varp(&options[opt_idx]); + else + origval = oldval; + + if (nextchar == '&') // set to default val + { + newval = options[opt_idx].def_val[((flags & P_VI_DEF) || cp_val) + ? VI_DEFAULT : VIM_DEFAULT]; + if ((char_u **)varp == &p_bg) + { + // guess the value of 'background' + #ifdef FEAT_GUI + if (gui.in_use) + newval = gui_bg_default(); + else + #endif + newval = term_bg_default(); + } + else if ((char_u **)varp == &p_fencs && enc_utf8) + newval = fencs_utf8_default; + + // expand environment variables and ~ since the default value was + // already expanded, only required when an environment variable was set + // later + if (newval == NULL) + newval = empty_option; + else + { + s = option_expand(opt_idx, newval); + if (s == NULL) + s = newval; + newval = vim_strsave(s); + } + } + else if (nextchar == '<') // set to global val + { + newval = vim_strsave(*(char_u **)get_varp_scope( + &(options[opt_idx]), OPT_GLOBAL)); + } + else + { + ++*arg; // jump to after the '=' or ':' + + /* + * Set 'keywordprg' to ":help" if an empty + * value was passed to :set by the user. + * Misuse errbuf[] for the resulting string. + */ + if (varp == (char_u *)&p_kp && (**arg == NUL || **arg == ' ')) + { + STRCPY(errbuf, ":help"); + save_arg = *arg; + *arg = (char_u *)errbuf; + } + /* + * Convert 'backspace' number to string, for + * adding, prepending and removing string. + */ + else if (varp == (char_u *)&p_bs && VIM_ISDIGIT(**(char_u **)varp)) + { + int i = getdigits((char_u **)varp); + + switch (i) + { + case 0: + *(char_u **)varp = empty_option; + break; + case 1: + *(char_u **)varp = vim_strsave((char_u *)"indent,eol"); + break; + case 2: + *(char_u **)varp = vim_strsave( + (char_u *)"indent,eol,start"); + break; + case 3: + *(char_u **)varp = vim_strsave( + (char_u *)"indent,eol,nostop"); + break; + } + vim_free(oldval); + if (origval == oldval) + origval = *(char_u **)varp; + if (origval_l == oldval) + origval_l = *(char_u **)varp; + if (origval_g == oldval) + origval_g = *(char_u **)varp; + oldval = *(char_u **)varp; + } + /* + * Convert 'whichwrap' number to string, for backwards compatibility + * with Vim 3.0. + */ + else if (varp == (char_u *)&p_ww && VIM_ISDIGIT(**arg)) + { + *whichwrap = NUL; + int i = getdigits(arg); + if (i & 1) + STRCAT(whichwrap, "b,"); + if (i & 2) + STRCAT(whichwrap, "s,"); + if (i & 4) + STRCAT(whichwrap, "h,l,"); + if (i & 8) + STRCAT(whichwrap, "<,>,"); + if (i & 16) + STRCAT(whichwrap, "[,],"); + if (*whichwrap != NUL) // remove trailing , + whichwrap[STRLEN(whichwrap) - 1] = NUL; + save_arg = *arg; + *arg = (char_u *)whichwrap; + } + /* + * Remove '>' before 'dir' and 'bdir', for backwards compatibility with + * version 3.0 + */ + else if ( **arg == '>' && (varp == (char_u *)&p_dir + || varp == (char_u *)&p_bdir)) + ++*arg; + + /* + * Copy the new string into allocated memory. + * Can't use set_string_option_direct(), because we need to remove the + * backslashes. + */ + // get a bit too much + newlen = (unsigned)STRLEN(*arg) + 1; + if (op != OP_NONE) + newlen += (unsigned)STRLEN(origval) + 1; + newval = alloc(newlen); + if (newval == NULL) // out of mem, don't change + return FAIL; + s = newval; + + /* + * Copy the string, skip over escaped chars. + * For MS-DOS and WIN32 backslashes before normal file name characters + * are not removed, and keep backslash at start, for "\\machine\path", + * but do remove it for "\\\\machine\\path". + * The reverse is found in ExpandOldSetting(). + */ + while (**arg && !VIM_ISWHITE(**arg)) + { + int i; + + if (**arg == '\\' && (*arg)[1] != NUL + #ifdef BACKSLASH_IN_FILENAME + && !((flags & P_EXPAND) + && vim_isfilec((*arg)[1]) + && !VIM_ISWHITE((*arg)[1]) + && ((*arg)[1] != '\\' + || (s == newval && (*arg)[2] != '\\'))) + #endif + ) + ++*arg; // remove backslash + if (has_mbyte && (i = (*mb_ptr2len)(*arg)) > 1) + { + // copy multibyte char + mch_memmove(s, *arg, (size_t)i); + *arg += i; + s += i; + } + else + *s++ = *(*arg)++; + } + *s = NUL; + + /* + * Expand environment variables and ~. + * Don't do it when adding without inserting a comma. + */ + if (op == OP_NONE || (flags & P_COMMA)) + { + s = option_expand(opt_idx, newval); + if (s != NULL) + { + vim_free(newval); + newlen = (unsigned)STRLEN(s) + 1; + if (op != OP_NONE) + newlen += (unsigned)STRLEN(origval) + 1; + newval = alloc(newlen); + if (newval == NULL) + return FAIL; + STRCPY(newval, s); + } + } + + // locate newval[] in origval[] when removing it + // and when adding to avoid duplicates + int len = 0; + if (op == OP_REMOVING || (flags & P_NODUP)) + { + len = (int)STRLEN(newval); + s = find_dup_item(origval, newval, flags); + + // do not add if already there + if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL) + { + op = OP_NONE; + STRCPY(newval, origval); + } + + // if no duplicate, move pointer to end of original value + if (s == NULL) + s = origval + (int)STRLEN(origval); + } + + // concatenate the two strings; add a ',' if needed + if (op == OP_ADDING || op == OP_PREPENDING) + { + comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL); + if (op == OP_ADDING) + { + len = (int)STRLEN(origval); + // strip a trailing comma, would get 2 + if (comma && len > 1 + && (flags & P_ONECOMMA) == P_ONECOMMA + && origval[len - 1] == ',' + && origval[len - 2] != '\\') + len--; + mch_memmove(newval + len + comma, newval, STRLEN(newval) + 1); + mch_memmove(newval, origval, (size_t)len); + } + else + { + len = (int)STRLEN(newval); + STRMOVE(newval + len + comma, origval); + } + if (comma) + newval[len] = ','; + } + + // Remove newval[] from origval[]. (Note: "len" has been set above and + // is used here). + if (op == OP_REMOVING) + { + STRCPY(newval, origval); + if (*s) + { + // may need to remove a comma + if (flags & P_COMMA) + { + if (s == origval) + { + // include comma after string + if (s[len] == ',') + ++len; + } + else + { + // include comma before string + --s; + ++len; + } + } + STRMOVE(newval + (s - origval), s + len); + } + } + + if (flags & P_FLAGLIST) + { + // Remove flags that appear twice. + for (s = newval; *s;) + { + // if options have P_FLAGLIST and P_ONECOMMA such as + // 'whichwrap' + if (flags & P_ONECOMMA) + { + if (*s != ',' && *(s + 1) == ',' + && vim_strchr(s + 2, *s) != NULL) + { + // Remove the duplicated value and the next comma. + STRMOVE(s, s + 2); + continue; + } + } + else + { + if ((!(flags & P_COMMA) || *s != ',') + && vim_strchr(s + 1, *s) != NULL) + { + STRMOVE(s, s + 1); + continue; + } + } + ++s; + } + } + + if (save_arg != NULL) // number for 'whichwrap' + *arg = save_arg; + } + + /* + * Set the new value. + */ + *(char_u **)(varp) = newval; + + #if defined(FEAT_EVAL) + if (!starting + # ifdef FEAT_CRYPT + && options[opt_idx].indir != PV_KEY + # endif + && origval != NULL && newval != NULL) + { + // origval may be freed by did_set_string_option(), make a copy. + saved_origval = vim_strsave(origval); + // newval (and varp) may become invalid if the buffer is closed by + // autocommands. + saved_newval = vim_strsave(newval); + if (origval_l != NULL) + saved_origval_l = vim_strsave(origval_l); + if (origval_g != NULL) + saved_origval_g = vim_strsave(origval_g); + } + #endif + + { + long_u *p = insecure_flag(opt_idx, opt_flags); + int secure_saved = secure; + + // When an option is set in the sandbox, from a modeline or in secure + // mode, then deal with side effects in secure mode. Also when the + // value was set with the P_INSECURE flag and is not completely + // replaced. + if ((opt_flags & OPT_MODELINE) + #ifdef HAVE_SANDBOX + || sandbox != 0 + #endif + || (op != OP_NONE && (*p & P_INSECURE))) + secure = 1; + + // Handle side effects, and set the global value for ":set" on local + // options. Note: when setting 'syntax' or 'filetype' autocommands may + // be triggered that can cause havoc. + *errmsg = did_set_string_option( + opt_idx, (char_u **)varp, oldval, errbuf, + opt_flags, value_checked); + + secure = secure_saved; + } + + #if defined(FEAT_EVAL) + if (*errmsg == NULL) + trigger_optionsset_string(opt_idx, opt_flags, saved_origval, + saved_origval_l, saved_origval_g, saved_newval); + vim_free(saved_origval); + vim_free(saved_origval_l); + vim_free(saved_origval_g); + vim_free(saved_newval); + #endif + + return *errmsg == NULL ? OK : FAIL; + } + /* * Parse 'arg' for option settings. * *************** *** 1241,1249 **** long_u flags; // flags for current option char_u *varp = NULL; // pointer to variable for current option int did_show = FALSE; // already showed one value ! int adding; // "opt+=arg" ! int prepending; // "opt^=arg" ! int removing; // "opt-=arg" int cp_val = 0; char_u key_name[2]; --- 1666,1672 ---- long_u flags; // flags for current option char_u *varp = NULL; // pointer to variable for current option int did_show = FALSE; // already showed one value ! set_op_T op = 0; int cp_val = 0; char_u key_name[2]; *************** *** 1371,1394 **** while (VIM_ISWHITE(arg[len])) ++len; ! adding = FALSE; ! prepending = FALSE; ! removing = FALSE; if (arg[len] != NUL && arg[len + 1] == '=') { if (arg[len] == '+') { ! adding = TRUE; // "+=" ++len; } else if (arg[len] == '^') { ! prepending = TRUE; // "^=" ++len; } else if (arg[len] == '-') { ! removing = TRUE; // "-=" ++len; } } --- 1794,1815 ---- while (VIM_ISWHITE(arg[len])) ++len; ! op = OP_NONE; if (arg[len] != NUL && arg[len + 1] == '=') { if (arg[len] == '+') { ! op = OP_ADDING; // "+=" ++len; } else if (arg[len] == '^') { ! op = OP_PREPENDING; // "^=" ++len; } else if (arg[len] == '-') { ! op = OP_REMOVING; // "-=" ++len; } } *************** *** 1564,1570 **** } else { - int value_is_replaced = !prepending && !adding && !removing; int value_checked = FALSE; if (flags & P_BOOL) // boolean --- 1985,1990 ---- *************** *** 1686,2125 **** goto skip; } ! if (adding) value = *(long *)varp + value; ! if (prepending) value = *(long *)varp * value; ! if (removing) value = *(long *)varp - value; errmsg = set_num_option(opt_idx, varp, value, errbuf, sizeof(errbuf), opt_flags); } else if (opt_idx >= 0) // string { ! char_u *save_arg = NULL; ! char_u *s = NULL; ! char_u *oldval = NULL; // previous value if *varp ! char_u *newval; ! char_u *origval = NULL; ! char_u *origval_l = NULL; ! char_u *origval_g = NULL; ! #if defined(FEAT_EVAL) ! char_u *saved_origval = NULL; ! char_u *saved_origval_l = NULL; ! char_u *saved_origval_g = NULL; ! char_u *saved_newval = NULL; ! #endif ! unsigned newlen; ! int comma; ! ! // When using ":set opt=val" for a global option ! // with a local value the local value will be ! // reset, use the global value here. ! if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ! && ((int)options[opt_idx].indir & PV_BOTH)) ! varp = options[opt_idx].var; ! ! // The old value is kept until we are sure that the ! // new value is valid. ! oldval = *(char_u **)varp; ! ! if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { ! origval_l = *(char_u **)get_varp_scope( ! &(options[opt_idx]), OPT_LOCAL); ! origval_g = *(char_u **)get_varp_scope( ! &(options[opt_idx]), OPT_GLOBAL); ! ! // A global-local string option might have an empty ! // option as value to indicate that the global ! // value should be used. ! if (((int)options[opt_idx].indir & PV_BOTH) ! && origval_l == empty_option) ! origval_l = origval_g; ! } ! ! // When setting the local value of a global ! // option, the old value may be the global value. ! if (((int)options[opt_idx].indir & PV_BOTH) ! && (opt_flags & OPT_LOCAL)) ! origval = *(char_u **)get_varp( ! &options[opt_idx]); ! else ! origval = oldval; ! ! if (nextchar == '&') // set to default val ! { ! newval = options[opt_idx].def_val[ ! ((flags & P_VI_DEF) || cp_val) ! ? VI_DEFAULT : VIM_DEFAULT]; ! if ((char_u **)varp == &p_bg) ! { ! // guess the value of 'background' ! #ifdef FEAT_GUI ! if (gui.in_use) ! newval = gui_bg_default(); ! else ! #endif ! newval = term_bg_default(); ! } ! else if ((char_u **)varp == &p_fencs && enc_utf8) ! newval = fencs_utf8_default; ! ! // expand environment variables and ~ since the ! // default value was already expanded, only ! // required when an environment variable was set ! // later ! if (newval == NULL) ! newval = empty_option; ! else ! { ! s = option_expand(opt_idx, newval); ! if (s == NULL) ! s = newval; ! newval = vim_strsave(s); ! } ! } ! else if (nextchar == '<') // set to global val ! { ! newval = vim_strsave(*(char_u **)get_varp_scope( ! &(options[opt_idx]), OPT_GLOBAL)); ! } ! else ! { ! ++arg; // jump to after the '=' or ':' ! ! /* ! * Set 'keywordprg' to ":help" if an empty ! * value was passed to :set by the user. ! * Misuse errbuf[] for the resulting string. ! */ ! if (varp == (char_u *)&p_kp ! && (*arg == NUL || *arg == ' ')) ! { ! STRCPY(errbuf, ":help"); ! save_arg = arg; ! arg = (char_u *)errbuf; ! } ! /* ! * Convert 'backspace' number to string, for ! * adding, prepending and removing string. ! */ ! else if (varp == (char_u *)&p_bs ! && VIM_ISDIGIT(**(char_u **)varp)) ! { ! i = getdigits((char_u **)varp); ! switch (i) ! { ! case 0: ! *(char_u **)varp = empty_option; ! break; ! case 1: ! *(char_u **)varp = vim_strsave( ! (char_u *)"indent,eol"); ! break; ! case 2: ! *(char_u **)varp = vim_strsave( ! (char_u *)"indent,eol,start"); ! break; ! case 3: ! *(char_u **)varp = vim_strsave( ! (char_u *)"indent,eol,nostop"); ! break; ! } ! vim_free(oldval); ! if (origval == oldval) ! origval = *(char_u **)varp; ! if (origval_l == oldval) ! origval_l = *(char_u **)varp; ! if (origval_g == oldval) ! origval_g = *(char_u **)varp; ! oldval = *(char_u **)varp; ! } ! /* ! * Convert 'whichwrap' number to string, for ! * backwards compatibility with Vim 3.0. ! * Misuse errbuf[] for the resulting string. ! */ ! else if (varp == (char_u *)&p_ww ! && VIM_ISDIGIT(*arg)) ! { ! *errbuf = NUL; ! i = getdigits(&arg); ! if (i & 1) ! STRCAT(errbuf, "b,"); ! if (i & 2) ! STRCAT(errbuf, "s,"); ! if (i & 4) ! STRCAT(errbuf, "h,l,"); ! if (i & 8) ! STRCAT(errbuf, "<,>,"); ! if (i & 16) ! STRCAT(errbuf, "[,],"); ! if (*errbuf != NUL) // remove trailing , ! errbuf[STRLEN(errbuf) - 1] = NUL; ! save_arg = arg; ! arg = (char_u *)errbuf; ! } ! /* ! * Remove '>' before 'dir' and 'bdir', for ! * backwards compatibility with version 3.0 ! */ ! else if ( *arg == '>' ! && (varp == (char_u *)&p_dir ! || varp == (char_u *)&p_bdir)) ! { ! ++arg; ! } ! ! /* ! * Copy the new string into allocated memory. ! * Can't use set_string_option_direct(), because ! * we need to remove the backslashes. ! */ ! // get a bit too much ! newlen = (unsigned)STRLEN(arg) + 1; ! if (adding || prepending || removing) ! newlen += (unsigned)STRLEN(origval) + 1; ! newval = alloc(newlen); ! if (newval == NULL) // out of mem, don't change ! break; ! s = newval; ! ! /* ! * Copy the string, skip over escaped chars. ! * For MS-DOS and WIN32 backslashes before normal ! * file name characters are not removed, and keep ! * backslash at start, for "\\machine\path", but ! * do remove it for "\\\\machine\\path". ! * The reverse is found in ExpandOldSetting(). ! */ ! while (*arg && !VIM_ISWHITE(*arg)) ! { ! if (*arg == '\\' && arg[1] != NUL ! #ifdef BACKSLASH_IN_FILENAME ! && !((flags & P_EXPAND) ! && vim_isfilec(arg[1]) ! && !VIM_ISWHITE(arg[1]) ! && (arg[1] != '\\' ! || (s == newval ! && arg[2] != '\\'))) ! #endif ! ) ! ++arg; // remove backslash ! if (has_mbyte ! && (i = (*mb_ptr2len)(arg)) > 1) ! { ! // copy multibyte char ! mch_memmove(s, arg, (size_t)i); ! arg += i; ! s += i; ! } ! else ! *s++ = *arg++; ! } ! *s = NUL; ! ! /* ! * Expand environment variables and ~. ! * Don't do it when adding without inserting a ! * comma. ! */ ! if (!(adding || prepending || removing) ! || (flags & P_COMMA)) ! { ! s = option_expand(opt_idx, newval); ! if (s != NULL) ! { ! vim_free(newval); ! newlen = (unsigned)STRLEN(s) + 1; ! if (adding || prepending || removing) ! newlen += (unsigned)STRLEN(origval) + 1; ! newval = alloc(newlen); ! if (newval == NULL) ! break; ! STRCPY(newval, s); ! } ! } ! ! // locate newval[] in origval[] when removing it ! // and when adding to avoid duplicates ! i = 0; // init for GCC ! if (removing || (flags & P_NODUP)) ! { ! i = (int)STRLEN(newval); ! s = find_dup_item(origval, newval, flags); ! ! // do not add if already there ! if ((adding || prepending) && s != NULL) ! { ! prepending = FALSE; ! adding = FALSE; ! STRCPY(newval, origval); ! } ! ! // if no duplicate, move pointer to end of ! // original value ! if (s == NULL) ! s = origval + (int)STRLEN(origval); ! } ! ! // concatenate the two strings; add a ',' if ! // needed ! if (adding || prepending) ! { ! comma = ((flags & P_COMMA) && *origval != NUL ! && *newval != NUL); ! if (adding) ! { ! i = (int)STRLEN(origval); ! // strip a trailing comma, would get 2 ! if (comma && i > 1 ! && (flags & P_ONECOMMA) == P_ONECOMMA ! && origval[i - 1] == ',' ! && origval[i - 2] != '\\') ! i--; ! mch_memmove(newval + i + comma, newval, ! STRLEN(newval) + 1); ! mch_memmove(newval, origval, (size_t)i); ! } ! else ! { ! i = (int)STRLEN(newval); ! STRMOVE(newval + i + comma, origval); ! } ! if (comma) ! newval[i] = ','; ! } ! ! // Remove newval[] from origval[]. (Note: "i" has ! // been set above and is used here). ! if (removing) ! { ! STRCPY(newval, origval); ! if (*s) ! { ! // may need to remove a comma ! if (flags & P_COMMA) ! { ! if (s == origval) ! { ! // include comma after string ! if (s[i] == ',') ! ++i; ! } ! else ! { ! // include comma before string ! --s; ! ++i; ! } ! } ! STRMOVE(newval + (s - origval), s + i); ! } ! } ! ! if (flags & P_FLAGLIST) ! { ! // Remove flags that appear twice. ! for (s = newval; *s;) ! { ! // if options have P_FLAGLIST and ! // P_ONECOMMA such as 'whichwrap' ! if (flags & P_ONECOMMA) ! { ! if (*s != ',' && *(s + 1) == ',' ! && vim_strchr(s + 2, *s) != NULL) ! { ! // Remove the duplicated value and ! // the next comma. ! STRMOVE(s, s + 2); ! continue; ! } ! } ! else ! { ! if ((!(flags & P_COMMA) || *s != ',') ! && vim_strchr(s + 1, *s) != NULL) ! { ! STRMOVE(s, s + 1); ! continue; ! } ! } ! ++s; ! } ! } ! ! if (save_arg != NULL) // number for 'whichwrap' ! arg = save_arg; ! } ! ! /* ! * Set the new value. ! */ ! *(char_u **)(varp) = newval; ! ! #if defined(FEAT_EVAL) ! if (!starting ! # ifdef FEAT_CRYPT ! && options[opt_idx].indir != PV_KEY ! # endif ! && origval != NULL && newval != NULL) ! { ! // origval may be freed by ! // did_set_string_option(), make a copy. ! saved_origval = vim_strsave(origval); ! // newval (and varp) may become invalid if the ! // buffer is closed by autocommands. ! saved_newval = vim_strsave(newval); ! if (origval_l != NULL) ! saved_origval_l = vim_strsave(origval_l); ! if (origval_g != NULL) ! saved_origval_g = vim_strsave(origval_g); ! } ! #endif ! ! { ! long_u *p = insecure_flag(opt_idx, opt_flags); ! int secure_saved = secure; ! ! // When an option is set in the sandbox, from a ! // modeline or in secure mode, then deal with side ! // effects in secure mode. Also when the value was ! // set with the P_INSECURE flag and is not ! // completely replaced. ! if ((opt_flags & OPT_MODELINE) ! #ifdef HAVE_SANDBOX ! || sandbox != 0 ! #endif ! || (!value_is_replaced && (*p & P_INSECURE))) ! secure = 1; ! ! // Handle side effects, and set the global value ! // for ":set" on local options. Note: when setting ! // 'syntax' or 'filetype' autocommands may be ! // triggered that can cause havoc. ! errmsg = did_set_string_option( ! opt_idx, (char_u **)varp, oldval, errbuf, ! opt_flags, &value_checked); ! ! secure = secure_saved; } - - #if defined(FEAT_EVAL) - if (errmsg == NULL) - trigger_optionsset_string( - opt_idx, opt_flags, saved_origval, - saved_origval_l, saved_origval_g, - saved_newval); - vim_free(saved_origval); - vim_free(saved_origval_l); - vim_free(saved_origval_g); - vim_free(saved_newval); - #endif - // If error detected, print the error message. - if (errmsg != NULL) - goto skip; } else // key code option { --- 2106,2130 ---- goto skip; } ! if (op == OP_ADDING) value = *(long *)varp + value; ! else if (op == OP_PREPENDING) value = *(long *)varp * value; ! else if (op == OP_REMOVING) value = *(long *)varp - value; errmsg = set_num_option(opt_idx, varp, value, errbuf, sizeof(errbuf), opt_flags); } else if (opt_idx >= 0) // string { ! if (do_set_string(opt_idx, opt_flags, &arg, nextchar, ! op, flags, cp_val, varp, errbuf, ! &value_checked, &errmsg) == FAIL) { ! if (errmsg != NULL) ! goto skip; ! break; } } else // key code option { *************** *** 2149,2155 **** if (opt_idx >= 0) did_set_option( ! opt_idx, opt_flags, value_is_replaced, value_checked); } skip: --- 2154,2160 ---- if (opt_idx >= 0) did_set_option( ! opt_idx, opt_flags, op == OP_NONE, value_checked); } skip: *** ../vim-9.0.0536/src/version.c 2022-09-21 19:41:52.172533866 +0100 --- src/version.c 2022-09-21 20:20:35.973014671 +0100 *************** *** 701,702 **** --- 701,704 ---- { /* Add new patch number below this line */ + /**/ + 537, /**/ -- I'm writing a book. I've got the page numbers done. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///