To: vim_dev@googlegroups.com Subject: Patch 9.0.1308 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1308 Problem: The code for setting options is too complicated. Solution: Refactor the code for setting options. (Yegappan Lakshmanan, closes #11989) Files: src/option.c *** ../vim-9.0.1307/src/option.c 2023-02-13 16:10:00.375551633 +0000 --- src/option.c 2023-02-14 13:06:30.795414084 +0000 *************** *** 186,216 **** long_u n; opt_idx = findoption((char_u *)"maxmemtot"); ! if (opt_idx >= 0) ! { #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM) ! if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L) #endif ! { #if defined(HAVE_AVAIL_MEM) ! // Use amount of memory available at this moment. ! n = (mch_avail_mem(FALSE) >> 1); #elif defined(HAVE_TOTAL_MEM) ! // Use amount of memory available to Vim. ! n = (mch_total_mem(FALSE) >> 1); #else ! n = (0x7fffffff >> 11); #endif ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; ! opt_idx = findoption((char_u *)"maxmem"); ! if (opt_idx >= 0) ! { #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM) ! if ((long)(long_i)options[opt_idx].def_val[VI_DEFAULT] > (long)n ! || (long)(long_i)options[opt_idx].def_val[VI_DEFAULT] == 0L) #endif ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; ! } } } } --- 186,216 ---- long_u n; opt_idx = findoption((char_u *)"maxmemtot"); ! if (opt_idx < 0) ! return; ! #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM) ! if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L) #endif ! { #if defined(HAVE_AVAIL_MEM) ! // Use amount of memory available at this moment. ! n = (mch_avail_mem(FALSE) >> 1); #elif defined(HAVE_TOTAL_MEM) ! // Use amount of memory available to Vim. ! n = (mch_total_mem(FALSE) >> 1); #else ! n = (0x7fffffff >> 11); #endif ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; ! opt_idx = findoption((char_u *)"maxmem"); ! if (opt_idx >= 0) ! { #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM) ! if ((long)(long_i)options[opt_idx].def_val[VI_DEFAULT] > (long)n ! || (long)(long_i)options[opt_idx].def_val[VI_DEFAULT] == 0L) #endif ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n; } } } *************** *** 316,327 **** char_u *p; p = get_isolated_shell_name(); ! if (p != NULL) ! { ! if (fnamecmp(p, "nologin") == 0 || fnamecmp(p, "false") == 0) ! restricted = TRUE; ! vim_free(p); ! } } #endif --- 316,326 ---- char_u *p; p = get_isolated_shell_name(); ! if (p == NULL) ! return; ! if (fnamecmp(p, "nologin") == 0 || fnamecmp(p, "false") == 0) ! restricted = TRUE; ! vim_free(p); } #endif *************** *** 342,352 **** p_rtp = (char_u *)CLEAN_RUNTIMEPATH; } opt_idx = findoption((char_u *)"packpath"); ! if (opt_idx >= 0) ! { ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH; ! p_pp = (char_u *)CLEAN_RUNTIMEPATH; ! } } #endif --- 341,350 ---- p_rtp = (char_u *)CLEAN_RUNTIMEPATH; } opt_idx = findoption((char_u *)"packpath"); ! if (opt_idx < 0) ! return; ! options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH; ! p_pp = (char_u *)CLEAN_RUNTIMEPATH; } #endif *************** *** 532,538 **** vim_free(p_enc); p_enc = save_enc; } - } /* --- 530,535 ---- *************** *** 1493,1748 **** } /* ! * 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 **argp, ! int nextchar, ! set_op_T op_arg, ! int flags, ! int cp_val, ! char_u *varp_arg, ! char *errbuf, ! int *value_checked, ! char **errmsg) { - char_u *arg = *argp; - 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. ! */ if (varp == (char_u *)&p_kp && (*arg == NUL || *arg == ' ')) { save_arg = arg; arg = (char_u *)":help"; } ! /* ! * 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 != NUL && !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)) { --- 1490,1880 ---- } /* ! * Get the Vim/Vi default value for a string option. */ ! static char_u * ! stropt_get_default_val( ! int opt_idx, ! char_u *varp, ! int flags, ! int cp_val) { char_u *newval; ! ! 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 ! { ! char_u *s = option_expand(opt_idx, newval); ! if (s == NULL) ! s = newval; ! newval = vim_strsave(s); ! } ! return newval; ! } ! /* ! * Convert the 'backspace' option number value to a string: for adding, ! * prepending and removing string. ! */ ! static void ! opt_backspace_nr2str( ! char_u *varp, ! char_u **origval_p, ! char_u **origval_l_p, ! char_u **origval_g_p, ! char_u **oldval_p) ! { ! 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_p); ! if (*origval_p == *oldval_p) ! *origval_p = *(char_u **)varp; ! if (*origval_l_p == *oldval_p) ! *origval_l_p = *(char_u **)varp; ! if (*origval_g_p == *oldval_p) ! *origval_g_p = *(char_u **)varp; ! *oldval_p = *(char_u **)varp; ! } ! ! /* ! * Convert the 'whichwrap' option number value to a string, for backwards ! * compatibility with Vim 3.0. ! * Note: 'argp' is a pointer to a char_u pointer and is updated. ! */ ! static char_u * ! opt_whichwrap_nr2str(char_u **argp, char_u *whichwrap) ! { ! *whichwrap = NUL; ! int i = getdigits(argp); ! 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; ! ! return whichwrap; ! } ! ! /* ! * Copy the new string value into allocated memory for the option. ! * Can't use set_string_option_direct(), because we need to remove the ! * backslashes. ! */ ! static char_u * ! stropt_copy_value( ! char_u *origval, ! char_u **argp, ! set_op_T op, ! int flags UNUSED) ! { ! char_u *arg = *argp; ! unsigned newlen; ! char_u *newval; ! char_u *s = NULL; ! ! // 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 NULL; ! 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 != NUL && !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; ! *argp = arg; ! return newval; ! } ! ! /* ! * Expand environment variables and ~ in string option value 'newval'. ! */ ! static char_u * ! stropt_expand_envvar( ! int opt_idx, ! char_u *origval, ! char_u *newval, ! set_op_T op) ! { ! char_u *s = option_expand(opt_idx, newval); ! if (s == NULL) ! return newval; ! ! vim_free(newval); ! unsigned newlen = (unsigned)STRLEN(s) + 1; ! if (op != OP_NONE) ! newlen += (unsigned)STRLEN(origval) + 1; ! ! newval = alloc(newlen); ! if (newval == NULL) ! return NULL; ! ! STRCPY(newval, s); ! ! return newval; ! } ! ! /* ! * Concatenate the original and new values of a string option, adding a "," if ! * needed. ! */ ! static void ! stropt_concat_with_comma( ! char_u *origval, ! char_u *newval, ! set_op_T op, ! int flags) ! { ! int len = 0; ! ! int 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 a value from a string option. Copy string option value in "origval" ! * to "newval" and then remove the string "strval" of length "len". ! */ ! static void ! stropt_remove_val( ! char_u *origval, ! char_u *newval, ! int flags, ! char_u *strval, ! int len) ! { ! // Remove newval[] from origval[]. (Note: "len" has been set above ! // and is used here). ! STRCPY(newval, origval); ! if (*strval) { ! // may need to remove a comma ! if (flags & P_COMMA) { ! if (strval == origval) ! { ! // include comma after string ! if (strval[len] == ',') ! ++len; ! } else ! { ! // include comma before string ! --strval; ! ++len; ! } } ! STRMOVE(newval + (strval - origval), strval + len); ! } ! } ! /* ! * Remove flags that appear twice in the string option value 'newval'. ! */ ! static void ! stropt_remove_dupflags(char_u *newval, int flags) ! { ! char_u *s = newval; ! ! // Remove flags that appear twice. ! while (*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; } + } + + /* + * Get the string value specified for a ":set" command. The following set + * options are supported: + * set {opt}& + * set {opt}< + * set {opt}={val} + * set {opt}:{val} + */ + static char_u * + stropt_get_newval( + int nextchar, + int opt_idx, + char_u **argp, + char_u *varp, + char_u **origval_arg, + char_u **origval_l_arg, + char_u **origval_g_arg, + char_u **oldval_arg, + set_op_T *op_arg, + int flags, + int cp_val) + { + char_u *arg = *argp; + char_u *origval = *origval_arg; + char_u *origval_l = *origval_l_arg; + char_u *origval_g = *origval_g_arg; + char_u *oldval = *oldval_arg; + set_op_T op = *op_arg; + char_u *save_arg = NULL; + char_u *newval; + char_u *s = NULL; + char_u whichwrap[80]; + + if (nextchar == '&') // set to default val + newval = stropt_get_default_val(opt_idx, varp, flags, cp_val); 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. if (varp == (char_u *)&p_kp && (*arg == NUL || *arg == ' ')) { save_arg = arg; arg = (char_u *)":help"; } ! // Convert 'backspace' number to string else if (varp == (char_u *)&p_bs && VIM_ISDIGIT(**(char_u **)varp)) ! opt_backspace_nr2str(varp, &origval, &origval_l, &origval_g, ! &oldval); else if (varp == (char_u *)&p_ww && VIM_ISDIGIT(*arg)) { ! // Convert 'whichwrap' number to string, for backwards ! // compatibility with Vim 3.0. ! char_u *t = opt_whichwrap_nr2str(&arg, whichwrap); save_arg = arg; ! arg = t; } ! // 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. ! newval = stropt_copy_value(origval, &arg, op, flags); ! if (newval == NULL) ! goto done; ! // Expand environment variables and ~. ! // Don't do it when adding without inserting a comma. if (op == OP_NONE || (flags & P_COMMA)) { ! newval = stropt_expand_envvar(opt_idx, origval, newval, op); ! if (newval == NULL) ! goto done; } ! // locate newval[] in origval[] when removing it and when adding to ! // avoid duplicates int len = 0; if (op == OP_REMOVING || (flags & P_NODUP)) { *************** *** 1763,1855 **** // 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) ! arg = save_arg; // arg was temporarily changed, restore it } ! /* ! * Set the new value. ! */ *(char_u **)(varp) = newval; #if defined(FEAT_EVAL) --- 1895,1994 ---- // concatenate the two strings; add a ',' if needed if (op == OP_ADDING || op == OP_PREPENDING) ! stropt_concat_with_comma(origval, newval, op, flags); ! else if (op == OP_REMOVING) ! // Remove newval[] from origval[]. (Note: "len" has been set above ! // and is used here). ! stropt_remove_val(origval, newval, flags, s, len); if (flags & P_FLAGLIST) // Remove flags that appear twice. ! stropt_remove_dupflags(newval, flags); ! } ! ! done: ! if (save_arg != NULL) ! arg = save_arg; // arg was temporarily changed, restore it ! *argp = arg; ! *origval_arg = origval; ! *origval_l_arg = origval_l; ! *origval_g_arg = origval_g; ! *oldval_arg = oldval; ! *op_arg = op; ! return newval; ! } ! ! /* ! * Part of do_set() for string options. ! * Returns FAIL on failure, do not process further options. ! */ ! static int ! do_set_option_string( ! int opt_idx, ! int opt_flags, ! char_u **argp, ! int nextchar, ! set_op_T op_arg, ! int flags, ! int cp_val, ! char_u *varp_arg, ! char *errbuf, ! int *value_checked, ! char **errmsg) ! { ! char_u *arg = *argp; ! set_op_T op = op_arg; ! char_u *varp = varp_arg; ! 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 ! ! // 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; ! ! // Get the new value for the option ! newval = stropt_get_newval(nextchar, opt_idx, &arg, varp, &origval, ! &origval_l, &origval_g, &oldval, &op, flags, ! cp_val); ! ! // Set the new value. *(char_u **)(varp) = newval; #if defined(FEAT_EVAL) *************** *** 2147,2155 **** else if (opt_idx >= 0) { // string option ! 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; --- 2286,2294 ---- else if (opt_idx >= 0) { // string option ! if (do_set_option_string(opt_idx, opt_flags, &arg, nextchar, op, ! flags, cp_val, varp, errbuf, ! &value_checked, &errmsg) == FAIL) { if (errmsg != NULL) goto skip; *************** *** 3033,3067 **** static void did_set_undofile(int opt_flags) { ! // Only take action when the option was set. When reset we do not ! // delete the undo file, the option may be set again without making ! // any changes in between. ! if (curbuf->b_p_udf || p_udf) ! { ! char_u hash[UNDO_HASH_SIZE]; ! buf_T *save_curbuf = curbuf; ! ! FOR_ALL_BUFFERS(curbuf) ! { ! // When 'undofile' is set globally: for every buffer, otherwise ! // only for the current buffer: Try to read in the undofile, ! // if one exists, the buffer wasn't changed and the buffer was ! // loaded ! if ((curbuf == save_curbuf ! || (opt_flags & OPT_GLOBAL) || opt_flags == 0) ! && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL) ! { #ifdef FEAT_CRYPT ! if (crypt_get_method_nr(curbuf) == CRYPT_M_SOD) ! continue; #endif ! u_compute_hash(hash); ! u_read_undo(NULL, hash, curbuf->b_fname); ! } } - curbuf = save_curbuf; } ! } #endif --- 3172,3205 ---- static void did_set_undofile(int opt_flags) { ! // Only take action when the option was set. ! if (!curbuf->b_p_udf && !p_udf) ! return; ! ! // When reset we do not delete the undo file, the option may be set again ! // without making any changes in between. ! char_u hash[UNDO_HASH_SIZE]; ! buf_T *save_curbuf = curbuf; ! ! FOR_ALL_BUFFERS(curbuf) ! { ! // When 'undofile' is set globally: for every buffer, otherwise ! // only for the current buffer: Try to read in the undofile, ! // if one exists, the buffer wasn't changed and the buffer was ! // loaded ! if ((curbuf == save_curbuf ! || (opt_flags & OPT_GLOBAL) || opt_flags == 0) ! && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL) ! { #ifdef FEAT_CRYPT ! if (crypt_get_method_nr(curbuf) == CRYPT_M_SOD) ! continue; #endif ! u_compute_hash(hash); ! u_read_undo(NULL, hash, curbuf->b_fname); } } ! curbuf = save_curbuf; } #endif *************** *** 3254,3264 **** { // when 'scrollbind' is set: snapshot the current position to avoid a jump // at the end of normal_cmd() ! if (curwin->w_p_scb) ! { ! do_check_scrollbind(FALSE); ! curwin->w_scbind_pos = curwin->w_topline; ! } } #ifdef FEAT_QUICKFIX --- 3392,3401 ---- { // when 'scrollbind' is set: snapshot the current position to avoid a jump // at the end of normal_cmd() ! if (!curwin->w_p_scb) ! return; ! do_check_scrollbind(FALSE); ! curwin->w_scbind_pos = curwin->w_topline; } #ifdef FEAT_QUICKFIX *************** *** 3292,3302 **** static void did_set_smoothscroll(void) { ! if (!curwin->w_p_sms) ! { ! curwin->w_skipcol = 0; ! changed_line_abv_curs(); ! } } /* --- 3429,3438 ---- static void did_set_smoothscroll(void) { ! if (curwin->w_p_sms) ! return; ! curwin->w_skipcol = 0; ! changed_line_abv_curs(); } /* *************** *** 3425,3438 **** static void did_set_ballooneval(long old_value) { ! if (!balloonEvalForTerm) ! { ! if (p_beval && !old_value) ! gui_mch_enable_beval_area(balloonEval); ! else if (!p_beval && old_value) ! gui_mch_disable_beval_area(balloonEval); ! } ! } #endif --- 3561,3572 ---- static void did_set_ballooneval(long old_value) { ! if (balloonEvalForTerm) ! return; ! if (p_beval && !old_value) ! gui_mch_enable_beval_area(balloonEval); ! else if (!p_beval && old_value) ! gui_mch_disable_beval_area(balloonEval); } #endif *** ../vim-9.0.1307/src/version.c 2023-02-13 16:10:00.375551633 +0000 --- src/version.c 2023-02-14 13:03:52.859183536 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1308, /**/ -- Would you care for a drink? I mean, if it were, like, disabled and you had to look after it? /// 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 ///