diff options
-rw-r--r-- | src/nvim/option.c | 146 |
1 files changed, 77 insertions, 69 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index 716fd3775a..ffceeb6a5a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2981,181 +2981,189 @@ static const char *check_num_option_bounds(long *pp, long old_value, long old_Ro return errmsg; } -/// Set the value of a number option, taking care of side effects -/// -/// @param[in] opt_idx Option index in options[] table. -/// @param[out] varp Pointer to the option variable. -/// @param[in] value New value. -/// @param errbuf Buffer for error messages. -/// @param[in] errbuflen Length of `errbuf`. -/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. -/// -/// @return NULL on success, error message on error. -static const char *set_num_option(int opt_idx, void *varp, long value, char *errbuf, - size_t errbuflen, int opt_flags) +/// Options that need some validation. +static const char *validate_num_option(const long *pp, long *valuep) { - const char *errmsg = NULL; - long old_value = *(long *)varp; - long old_global_value = 0; // only used when setting a local and global option - long old_Rows = Rows; // remember old Rows - long *pp = (long *)varp; - - // Disallow changing some options from secure mode. - if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { - return e_secure; - } - - // Save the global value before changing anything. This is needed as for - // a global-only option setting the "local value" in fact sets the global - // value (since there is only one value). - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); - } + long value = *valuep; // Many number options assume their value is in the signed int range. if (value < INT_MIN || value > INT_MAX) { return e_invarg; } - // Options that need some validation. if (pp == &p_wh) { if (value < 1) { - errmsg = e_positive; + return e_positive; } else if (p_wmh > value) { - errmsg = e_winheight; + return e_winheight; } } else if (pp == &p_hh) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_wmh) { if (value < 0) { - errmsg = e_positive; + return e_positive; } else if (value > p_wh) { - errmsg = e_winheight; + return e_winheight; } } else if (pp == &p_wiw) { if (value < 1) { - errmsg = e_positive; + return e_positive; } else if (p_wmw > value) { - errmsg = e_winwidth; + return e_winwidth; } } else if (pp == &p_wmw) { if (value < 0) { - errmsg = e_positive; + return e_positive; } else if (value > p_wiw) { - errmsg = e_winwidth; + return e_winwidth; } } else if (pp == &p_mco) { - value = MAX_MCO; + *valuep = MAX_MCO; } else if (pp == &p_titlelen) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_uc) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_ch) { if (value < 0) { - errmsg = e_positive; + return e_positive; } else { p_ch_was_zero = value == 0; } } else if (pp == &p_tm) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_hi) { if (value < 0) { - errmsg = e_positive; + return e_positive; } else if (value > 10000) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &p_pyx) { if (value == 0) { - value = 3; + *valuep = 3; } else if (value != 3) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &p_re) { if (value < 0 || value > 2) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &p_report) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_so) { if (value < 0 && full_screen) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_siso) { if (value < 0 && full_screen) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_cwh) { if (value < 1) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_ut) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_ss) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &curwin->w_p_fdl || pp == &curwin->w_allbuf_opt.wo_fdl) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &curwin->w_p_cole || pp == &curwin->w_allbuf_opt.wo_cole) { if (value < 0) { - errmsg = e_positive; + return e_positive; } else if (value > 3) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curwin->w_p_nuw || pp == &curwin->w_allbuf_opt.wo_nuw) { if (value < 1) { - errmsg = e_positive; + return e_positive; } else if (value > MAX_NUMBERWIDTH) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curbuf->b_p_iminsert || pp == &p_iminsert) { if (value < 0 || value > B_IMODE_LAST) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curbuf->b_p_imsearch || pp == &p_imsearch) { if (value < -1 || value > B_IMODE_LAST) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curbuf->b_p_channel || pp == &p_channel) { - errmsg = e_invarg; + return e_invarg; } else if (pp == &curbuf->b_p_scbk || pp == &p_scbk) { if (value < -1 || value > SB_MAX) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curbuf->b_p_sw || pp == &p_sw) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &curbuf->b_p_ts || pp == &p_ts) { if (value < 1) { - errmsg = e_positive; + return e_positive; } else if (value > TABSTOP_MAX) { - errmsg = e_invarg; + return e_invarg; } } else if (pp == &curbuf->b_p_tw || pp == &p_tw) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } else if (pp == &p_wd) { if (value < 0) { - errmsg = e_positive; + return e_positive; } } + return NULL; +} + +/// Set the value of a number option, taking care of side effects +/// +/// @param[in] opt_idx Option index in options[] table. +/// @param[out] varp Pointer to the option variable. +/// @param[in] value New value. +/// @param errbuf Buffer for error messages. +/// @param[in] errbuflen Length of `errbuf`. +/// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. +/// +/// @return NULL on success, error message on error. +static const char *set_num_option(int opt_idx, void *varp, long value, char *errbuf, + size_t errbuflen, int opt_flags) +{ + long old_value = *(long *)varp; + long old_global_value = 0; // only used when setting a local and global option + long old_Rows = Rows; // remember old Rows + long *pp = (long *)varp; + + // Disallow changing some options from secure mode. + if ((secure || sandbox != 0) && (options[opt_idx].flags & P_SECURE)) { + return e_secure; + } + + // Save the global value before changing anything. This is needed as for + // a global-only option setting the "local value" in fact sets the global + // value (since there is only one value). + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { + old_global_value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); + } + + const char *errmsg = validate_num_option(pp, &value); + // Don't change the value and return early if validation failed. if (errmsg != NULL) { return errmsg; |