diff options
Diffstat (limited to 'src/nvim/optionstr.c')
-rw-r--r-- | src/nvim/optionstr.c | 716 |
1 files changed, 386 insertions, 330 deletions
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index ece7a90b4a..d7cf948730 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -444,7 +444,7 @@ const char *set_string_option(const int opt_idx, const char *const value, const char *const saved_newval = xstrdup(s); int value_checked = false; - const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, errbuf, errbuflen, + const char *const errmsg = did_set_string_option(opt_idx, varp, oldval, s, errbuf, errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); @@ -479,11 +479,13 @@ static bool valid_filetype(const char *val) /// Handle setting 'mousescroll'. /// @return error message, NULL if it's OK. -static const char *check_mousescroll(char *string) +const char *did_set_mousescroll(optset_T *args FUNC_ATTR_UNUSED) { long vertical = -1; long horizontal = -1; + char *string = p_mousescroll; + while (true) { char *end = vim_strchr(string, ','); size_t length = end ? (size_t)(end - string) : strlen(string); @@ -651,8 +653,12 @@ static bool check_illegal_path_names(char *val, uint32_t flags) && strpbrk(val, "*?[|;&<>\r\n") != NULL)); } -static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const char **errmsg) +/// The 'backupcopy' option is changed. +const char *did_set_backupcopy(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + const char *oldval = args->os_oldval.string; + int opt_flags = args->os_flags; char *bkc = p_bkc; unsigned *flags = &bkc_flags; @@ -666,7 +672,7 @@ static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const ch *flags = 0; } else { if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } if (((*flags & BKC_AUTO) != 0) @@ -674,30 +680,41 @@ static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, const ch + ((*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_invarg; + return e_invarg; } } + + return NULL; } -static void did_set_backupext_or_patchmode(const char **errmsg) +/// The 'backupext' or the 'patchmode' option is changed. +const char *did_set_backupext_or_patchmode(optset_T *args FUNC_ATTR_UNUSED) { if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { - *errmsg = e_backupext_and_patchmode_are_equal; + return e_backupext_and_patchmode_are_equal; } + + return NULL; } -static void did_set_breakindentopt(win_T *win, const char **errmsg) +/// The 'breakindentopt' option is changed. +const char *did_set_breakindentopt(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (briopt_check(win) == FAIL) { - *errmsg = e_invarg; + return e_invarg; } // list setting requires a redraw if (win == curwin && win->w_briopt_list) { redraw_all_later(UPD_NOT_VALID); } + + return NULL; } +/// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is +/// changed. static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) { // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] @@ -709,7 +726,8 @@ static void did_set_isopt(buf_T *buf, bool *did_chartab, const char **errmsg) } } -static void did_set_helpfile(void) +/// The 'helpfile' option is changed. +const char *did_set_helpfile(optset_T *args FUNC_ATTR_UNUSED) { // May compute new values for $VIM and $VIMRUNTIME if (didset_vim) { @@ -718,8 +736,10 @@ static void did_set_helpfile(void) if (didset_vimruntime) { vim_unsetenv_ext("VIMRUNTIME"); } + return NULL; } +/// The 'cursorlineopt' option is changed. static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) { if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) { @@ -727,25 +747,28 @@ static void did_set_cursorlineopt(win_T *win, char **varp, const char **errmsg) } } -static void did_set_helplang(const char **errmsg) +/// The 'helplang' option is changed. +const char *did_set_helplang(optset_T *args FUNC_ATTR_UNUSED) { // Check for "", "ab", "ab,cd", etc. for (char *s = p_hlg; *s != NUL; s += 3) { if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) { - *errmsg = e_invarg; - break; + return e_invarg; } if (s[2] == NUL) { break; } } + return NULL; } -static void did_set_highlight(char **varp, const char **errmsg) +/// The 'highlight' option is changed. +const char *did_set_highlight(optset_T *args) { - if (strcmp(*varp, HIGHLIGHT_INIT) != 0) { - *errmsg = e_unsupportedoption; + if (strcmp(args->os_varp, HIGHLIGHT_INIT) != 0) { + return e_unsupportedoption; } + return NULL; } static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, @@ -761,32 +784,35 @@ static void did_set_opt_strings(char *val, char **values, bool list, const char did_set_opt_flags(val, values, NULL, list, errmsg); } -static void did_set_sessionoptions(char *oldval, const char **errmsg) +/// The 'sessionoptions' option is changed. +const char *did_set_sessionoptions(optset_T *args) { if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) { // Don't allow both "sesdir" and "curdir". + const char *oldval = args->os_oldval.string; (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true); - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_ambiwidth(const char **errmsg) +/// The 'ambiwidth' option is changed. +const char *did_set_ambiwidth(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { - *errmsg = e_invarg; - } else { - *errmsg = check_chars_options(); + return e_invarg; } + return check_chars_options(); } -static void did_set_background(const char **errmsg) +/// The 'background' option is changed. +const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_bg, p_bg_values, false) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } int dark = (*p_bg == 'd'); @@ -803,27 +829,34 @@ static void did_set_background(const char **errmsg) check_string_option(&p_bg); init_highlight(false, false); } + return NULL; } -static void did_set_wildmode(const char **errmsg) +/// The 'wildmode' option is changed. +const char *did_set_wildmode(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_wim() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_winaltkeys(const char **errmsg) +/// The 'winaltkeys' option is changed. +const char *did_set_winaltkeys(optset_T *args FUNC_ATTR_UNUSED) { if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_eventignore(const char **errmsg) +/// The 'eventignore' option is changed. +const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED) { if (check_ei() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } // 'encoding', 'fileencoding' and 'makeencoding' @@ -886,7 +919,7 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch // even when the value comes from a modeline. *value_checked = true; - if (*errmsg == NULL) { + if (errmsg == NULL) { if (*buf->b_p_keymap != NUL) { // Installed a new keymap, switch on using it. buf->b_p_iminsert = B_IMODE_LMAP; @@ -910,28 +943,32 @@ static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_ch } } -static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags, - const char **errmsg) +/// The 'fileformat' option is changed. +const char *did_set_fileformat(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + const char *oldval = args->os_oldval.string; + int opt_flags = args->os_flags; if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) { - *errmsg = e_modifiable; - } else if (check_opt_strings(*varp, p_ff_values, false) != OK) { - *errmsg = e_invarg; - } else { - redraw_titles(); - // update flag in swap file - ml_setflags(buf); - // Redraw needed when switching to/from "mac": a CR in the text - // will be displayed differently. - if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { - redraw_buf_later(buf, UPD_NOT_VALID); - } + return e_modifiable; + } else if (check_opt_strings(args->os_varp, p_ff_values, false) != OK) { + return e_invarg; + } + redraw_titles(); + // update flag in swap file + ml_setflags(buf); + // Redraw needed when switching to/from "mac": a CR in the text + // will be displayed differently. + if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') { + redraw_buf_later(buf, UPD_NOT_VALID); } + return NULL; } -static void did_set_matchpairs(char **varp, const char **errmsg) +/// The 'matchpairs' option is changed. +const char *did_set_matchpairs(optset_T *args) { - for (char *p = *varp; *p != NUL; p++) { + for (char *p = args->os_varp; *p != NUL; p++) { int x2 = -1; int x3 = -1; @@ -944,13 +981,22 @@ static void did_set_matchpairs(char **varp, const char **errmsg) p += utfc_ptr2len(p); } if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) { - *errmsg = e_invarg; - break; + return e_invarg; } if (*p == NUL) { break; } } + return NULL; +} + +/// The 'cinoptions' option is changed. +const char *did_set_cinoptions(optset_T *args FUNC_ATTR_UNUSED) +{ + // TODO(vim): recognize errors + parse_cino(curbuf); + + return NULL; } static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) @@ -1008,18 +1054,20 @@ static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, } } -static void did_set_verbosefile(const char **errmsg) +/// The 'verbosefile' option is changed. +const char *did_set_verbosefile(optset_T *args) { verbose_stop(); if (*p_vfile != NUL && verbose_open() == FAIL) { - *errmsg = e_invarg; + return (char *)e_invarg; } + return NULL; } static int shada_idx = -1; -static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, - size_t errbuflen, const char **errmsg) +static const char *did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, + size_t errbuflen) { // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo // option. @@ -1034,8 +1082,7 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch for (char *s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); - break; + return illegal_char(errbuf, errbuflen, (uint8_t)(*s)); } if (*s == 'n') { // name is always last one break; @@ -1054,181 +1101,241 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch vim_snprintf(errbuf, errbuflen, _("E526: Missing number after <%s>"), transchar_byte((uint8_t)(*(s - 1)))); - *errmsg = errbuf; + return errbuf; } else { - *errmsg = ""; + return ""; } - break; } } if (*s == ',') { s++; } else if (*s) { if (errbuf != NULL) { - *errmsg = N_("E527: Missing comma"); + return N_("E527: Missing comma"); } else { - *errmsg = ""; + return ""; } - break; } } - if (*p_shada && *errmsg == NULL && get_shada_parameter('\'') < 0) { - *errmsg = N_("E528: Must specify a ' value"); + if (*p_shada && get_shada_parameter('\'') < 0) { + return N_("E528: Must specify a ' value"); } + return NULL; } -static void did_set_showbreak(char **varp, const char **errmsg) +/// The 'showbreak' option is changed. +const char *did_set_showbreak(optset_T *args) { - for (char *s = *varp; *s;) { + for (char *s = args->os_varp; *s;) { if (ptr2cells(s) != 1) { - *errmsg = e_showbreak_contains_unprintable_or_wide_character; + return e_showbreak_contains_unprintable_or_wide_character; } MB_PTR_ADV(s); } + return NULL; } -static void did_set_titleiconstring(char **varp) +/// The 'titlestring' or the 'iconstring' option is changed. +static const char *did_set_titleiconstring(optset_T *args, int flagval) { - // 'titlestring' and 'iconstring' - int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON; - // NULL => statusline syntax - if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) { + if (vim_strchr(args->os_varp, '%') && check_stl_option(args->os_varp) == NULL) { stl_syntax |= flagval; } else { stl_syntax &= ~flagval; } did_set_title(); + + return NULL; +} + +/// The 'titlestring' option is changed. +const char *did_set_titlestring(optset_T *args) +{ + return did_set_titleiconstring(args, STL_IN_TITLE); +} + +/// The 'iconstring' option is changed. +const char *did_set_iconstring(optset_T *args) +{ + return did_set_titleiconstring(args, STL_IN_ICON); } -static void did_set_selection(const char **errmsg) +/// The 'selection' option is changed. +const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED) { if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_keymodel(const char **errmsg) +/// The 'keymodel' option is changed. +const char *did_set_keymodel(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_km, p_km_values, true) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } km_stopsel = (vim_strchr(p_km, 'o') != NULL); km_startsel = (vim_strchr(p_km, 'a') != NULL); + return NULL; } -static void did_set_display(const char **errmsg) +/// The 'display' option is changed. +const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED) { if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) { - *errmsg = e_invarg; - return; + return e_invarg; } (void)init_chartab(); msg_grid_validate(); + return NULL; } -static void did_set_spellfile(char **varp, const char **errmsg) +/// The 'spellfile' option is changed. +const char *did_set_spellfile(optset_T *args) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. - - if ((!valid_spellfile(*varp))) { - *errmsg = e_invarg; - } else { - *errmsg = did_set_spell_option(true); + if ((!valid_spellfile(args->os_varp))) { + return e_invarg; } + return did_set_spell_option(true); } -static void did_set_spell(char **varp, const char **errmsg) +const char *did_set_spelllang(optset_T *args) { // When there is a window for this buffer in which 'spell' // is set load the wordlists. - if (!valid_spelllang(*varp)) { - *errmsg = e_invarg; - } else { - *errmsg = did_set_spell_option(false); + if (!valid_spelllang(args->os_varp)) { + return e_invarg; } + return did_set_spell_option(false); } -static void did_set_spellcapcheck(win_T *win, const char **errmsg) +/// The 'spellcapcheck' option is changed. +const char *did_set_spellcapcheck(optset_T *args) { + win_T *win = (win_T *)args->os_win; // When 'spellcapcheck' is set compile the regexp program. - *errmsg = compile_cap_prog(win->w_s); + return compile_cap_prog(win->w_s); } -static void did_set_spelloptions(win_T *win, const char **errmsg) +/// The 'spelloptions' option is changed. +const char *did_set_spelloptions(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags), true) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_spellsuggest(const char **errmsg) +/// The 'spellsuggest' option is changed. +const char *did_set_spellsuggest(optset_T *args FUNC_ATTR_UNUSED) { if (spell_check_sps() != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_mkspellmem(const char **errmsg) + /// The 'mkspellmem' option is changed. +const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED) { if (spell_check_msm() != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_buftype(buf_T *buf, win_T *win, const char **errmsg) +/// The 'buftype' option is changed. +const char *did_set_buftype(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + win_T *win = (win_T *)args->os_win; // When 'buftype' is set, check for valid value. if ((buf->terminal && buf->b_p_bt[0] != 't') || (!buf->terminal && buf->b_p_bt[0] == 't') || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) { - *errmsg = e_invarg; - } else { - if (win->w_status_height || global_stl_height()) { - win->w_redr_status = true; - redraw_later(win, UPD_VALID); - } - buf->b_help = (buf->b_p_bt[0] == 'h'); - redraw_titles(); + return e_invarg; } + if (win->w_status_height || global_stl_height()) { + win->w_redr_status = true; + redraw_later(win, UPD_VALID); + } + buf->b_help = (buf->b_p_bt[0] == 'h'); + redraw_titles(); + return NULL; } -// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' -static void did_set_statusline(win_T *win, char **varp, char **gvarp, const char **errmsg) +/// The 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' option is changed. +/// +/// @param rulerformat true if the 'rulerformat' option is changed +/// @param statuscolumn true if the 'statuscolumn' option is changed +static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerformat, + bool statuscolumn) { - if (varp == &p_ruf) { // reset ru_wid first + win_T *win = (win_T *)args->os_win; + if (rulerformat) { // reset ru_wid first ru_wid = 0; - } else if (varp == &win->w_p_stc) { + } else if (statuscolumn) { // reset 'statuscolumn' width win->w_nrwidth_line_count = 0; } - char *s = *varp; - if (varp == &p_ruf && *s == '%') { + const char *errmsg = NULL; + char *s = args->os_varp; + if (rulerformat && *s == '%') { // set ru_wid if 'ruf' starts with "%99(" if (*++s == '-') { // ignore a '-' s++; } int wid = getdigits_int(&s, true, 0); - if (wid && *s == '(' && (*errmsg = check_stl_option(p_ruf)) == NULL) { + if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) { ru_wid = wid; } else { - *errmsg = check_stl_option(p_ruf); + errmsg = check_stl_option(p_ruf); } - } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') { + } else if (rulerformat || s[0] != '%' || s[1] != '!') { // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' // only if it doesn't start with "%!" - *errmsg = check_stl_option(s); + errmsg = check_stl_option(s); } - if (varp == &p_ruf && *errmsg == NULL) { + if (rulerformat && errmsg == NULL) { comp_col(); } - // add / remove window bars for 'winbar' - if (gvarp == &p_wbr) { - set_winbar(true); - } + return errmsg; +} + +/// The 'statusline' option is changed. +const char *did_set_statusline(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'tabline' option is changed. +const char *did_set_tabline(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'rulerformat' option is changed. +const char *did_set_rulerformat(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, true, false); +} + +/// The 'winbar' option is changed. +const char *did_set_winbar(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, false); +} + +/// The 'statuscolumn' option is changed. +const char *did_set_statuscolumn(optset_T *args) +{ + return did_set_statustabline_rulerformat(args, false, true); } static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const char **errmsg) @@ -1269,29 +1376,36 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, const } } -static void did_set_completeopt(const char **errmsg) +/// The 'completeopt' option is changed. +const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { if (check_opt_strings(p_cot, p_cot_values, true) != OK) { - *errmsg = e_invarg; - } else { - completeopt_was_set(); + return e_invarg; } + completeopt_was_set(); + return NULL; } #ifdef BACKSLASH_IN_FILENAME -static void did_set_completeslash(buf_T *buf, const char **errmsg) +/// The 'completeslash' option is changed. +const char *did_set_completeslash(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; if (check_opt_strings(p_csl, p_csl_values, false) != OK || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } #endif -static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, const char **errmsg) +/// The 'signcolumn' option is changed. +const char *did_set_signcolumn(optset_T *args) { - if (check_signcolumn(*varp) != OK) { - *errmsg = e_invarg; + win_T *win = (win_T *)args->os_win; + const char *oldval = args->os_oldval.string; + if (check_signcolumn(args->os_varp) != OK) { + return e_invarg; } // When changing the 'signcolumn' to or from 'number', recompute the // width of the number column if 'number' or 'relativenumber' is set. @@ -1300,28 +1414,37 @@ static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, cons && (win->w_p_nu || win->w_p_rnu)) { win->w_nrwidth_line_count = 0; } + return NULL; } -static void did_set_foldcolumn(char **varp, const char **errmsg) +/// The 'foldcolumn' option is changed. +const char *did_set_foldcolumn(optset_T *args) { - if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) { - *errmsg = e_invarg; + if (*args->os_varp == NUL || check_opt_strings(args->os_varp, p_fdc_values, false) != OK) { + return e_invarg; } + return NULL; } -static void did_set_backspace(const char **errmsg) +/// The 'backspace' option is changed. +const char *did_set_backspace(optset_T *args FUNC_ATTR_UNUSED) { if (ascii_isdigit(*p_bs)) { if (*p_bs > '3' || p_bs[1] != NUL) { - *errmsg = e_invarg; + return e_invarg; } } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) +/// The 'tagcase' option is changed. +const char *did_set_tagcase(optset_T *args) { + buf_T *buf = (buf_T *)args->os_buf; + int opt_flags = args->os_flags; + unsigned *flags; char *p; @@ -1338,73 +1461,95 @@ static void did_set_tagcase(buf_T *buf, int opt_flags, const char **errmsg) *flags = 0; } else if (*p == NUL || opt_strings_flags(p, p_tc_values, flags, false) != OK) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_diffopt(const char **errmsg) +/// The 'diffopt' option is changed. +const char *did_set_diffopt(optset_T *args FUNC_ATTR_UNUSED) { if (diffopt_changed() == FAIL) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_foldmethod(win_T *win, char **varp, const char **errmsg) +/// The 'foldmethod' option is changed. +const char *did_set_foldmethod(optset_T *args) { - if (check_opt_strings(*varp, p_fdm_values, false) != OK + win_T *win = (win_T *)args->os_win; + if (check_opt_strings(args->os_varp, p_fdm_values, false) != OK || *win->w_p_fdm == NUL) { - *errmsg = e_invarg; - } else { - foldUpdateAll(win); - if (foldmethodIsDiff(win)) { - newFoldLevel(); - } + return e_invarg; } + foldUpdateAll(win); + if (foldmethodIsDiff(win)) { + newFoldLevel(); + } + return NULL; } -static void did_set_foldmarker(win_T *win, char **varp, const char **errmsg) +/// The 'foldmarker' option is changed. +const char *did_set_foldmarker(optset_T *args) { - char *p = vim_strchr(*varp, ','); + win_T *win = (win_T *)args->os_win; + char *p = vim_strchr(args->os_varp, ','); + if (p == NULL) { - *errmsg = N_("E536: comma required"); - } else if (p == *varp || p[1] == NUL) { - *errmsg = e_invarg; - } else if (foldmethodIsMarker(win)) { + return N_("E536: comma required"); + } + + if (p == args->os_varp || p[1] == NUL) { + return e_invarg; + } + + if (foldmethodIsMarker(win)) { foldUpdateAll(win); } + + return NULL; } -static void did_set_commentstring(char **varp, const char **errmsg) +/// The 'commentstring' option is changed. +const char *did_set_commentstring(optset_T *args) { - if (**varp != NUL && strstr(*varp, "%s") == NULL) { - *errmsg = N_("E537: 'commentstring' must be empty or contain %s"); + if (*args->os_varp != NUL && strstr(args->os_varp, "%s") == NULL) { + return N_("E537: 'commentstring' must be empty or contain %s"); } + return NULL; } -static void did_set_foldignore(win_T *win) +/// The 'foldignore' option is changed. +const char *did_set_foldignore(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (foldmethodIsIndent(win)) { foldUpdateAll(win); } + return NULL; } -static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const char **errmsg) +/// The 'virtualedit' option is changed. +const char *did_set_virtualedit(optset_T *args) { + win_T *win = (win_T *)args->os_win; + char *ve = p_ve; unsigned *flags = &ve_flags; - if (opt_flags & OPT_LOCAL) { + if (args->os_flags & OPT_LOCAL) { ve = win->w_p_ve; flags = &win->w_ve_flags; } - if ((opt_flags & OPT_LOCAL) && *ve == NUL) { + if ((args->os_flags & OPT_LOCAL) && *ve == NUL) { // make the local value empty: use the global value *flags = 0; } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { - *errmsg = e_invarg; - } else if (strcmp(ve, oldval) != 0) { + return e_invarg; + } else if (strcmp(ve, args->os_oldval.string) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol_win(win); @@ -1412,15 +1557,20 @@ static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, const c coladvance(win->w_virtcol); } } + return NULL; } -static void did_set_lispoptions(char **varp, const char **errmsg) +/// The 'lispoptions' option is changed. +const char *did_set_lispoptions(optset_T *args) { - if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) { - *errmsg = e_invarg; + if (*args->os_varp != NUL + && strcmp(args->os_varp, "expr:0") != 0 && strcmp(args->os_varp, "expr:1") != 0) { + return e_invarg; } + return NULL; } +/// The 'filetype' or the 'syntax' option is changed. static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked, bool *value_changed, const char **errmsg) { @@ -1436,66 +1586,75 @@ static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_che *value_checked = true; } -static void did_set_winhl(win_T *win, const char **errmsg) +const char *did_set_winhl(optset_T *args) { + win_T *win = (win_T *)args->os_win; if (!parse_winhl_opt(win)) { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_varsoftabstop(buf_T *buf, char **varp, const char **errmsg) +/// The 'varsofttabstop' option is changed. +const char *did_set_varsofttabstop(optset_T *args) { - if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { + buf_T *buf = (buf_T *)args->os_buf; + + if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { XFREE_CLEAR(buf->b_p_vsts_array); - return; + return NULL; } - for (char *cp = *varp; *cp; cp++) { + for (char *cp = args->os_varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { continue; } - *errmsg = e_invarg; - return; + return e_invarg; } long *oldarray = buf->b_p_vsts_array; - if (tabstop_set(*varp, &(buf->b_p_vsts_array))) { + if (tabstop_set(args->os_varp, &(buf->b_p_vsts_array))) { xfree(oldarray); } else { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } -static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, const char **errmsg) +/// The 'varstabstop' option is changed. +const char *did_set_vartabstop(optset_T *args) { - if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) { + buf_T *buf = (buf_T *)args->os_buf; + win_T *win = (win_T *)args->os_win; + + if (!(args->os_varp[0]) || ((args->os_varp[0]) == '0' && !(args->os_varp[1]))) { XFREE_CLEAR(buf->b_p_vts_array); - return; + return NULL; } - for (char *cp = *varp; *cp; cp++) { + for (char *cp = args->os_varp; *cp; cp++) { if (ascii_isdigit(*cp)) { continue; } - if (*cp == ',' && cp > *varp && *(cp - 1) != ',') { + if (*cp == ',' && cp > args->os_varp && *(cp - 1) != ',') { continue; } - *errmsg = e_invarg; - return; + return e_invarg; } long *oldarray = buf->b_p_vts_array; - if (tabstop_set(*varp, &(buf->b_p_vts_array))) { + if (tabstop_set(args->os_varp, &(buf->b_p_vts_array))) { xfree(oldarray); if (foldmethodIsIndent(win)) { foldUpdateAll(win); } } else { - *errmsg = e_invarg; + return e_invarg; } + return NULL; } static void did_set_optexpr(char **varp) @@ -1519,6 +1678,11 @@ static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size } } +const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED) +{ + return parse_shape_opt(SHAPE_CURSOR); +} + // When 'syntax' is set, load the syntax of that name static void do_syntax_autocmd(buf_T *buf, bool value_changed) { @@ -1574,87 +1738,68 @@ static void do_spelllang_source(win_T *win) /// /// @return NULL for success, or an untranslated error message for an error static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp, - char *oldval, char *errbuf, size_t errbuflen, - int opt_flags, int *value_checked) + char *oldval, const char *value, char *errbuf, + size_t errbuflen, int opt_flags, int *value_checked) { const char *errmsg = NULL; bool did_chartab = false; vimoption_T *opt = get_option(opt_idx); bool free_oldval = (opt->flags & P_ALLOCED); + opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx); bool value_changed = false; // Get the global option to compare with, otherwise we would have to check // two values for all local options. char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); + optset_T args = { + .os_varp = *varp, + .os_flags = opt_flags, + .os_oldval.string = oldval, + .os_newval.string = value, + .os_win = curwin, + .os_buf = curbuf, + }; + // Disallow changing some options from secure mode if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) { errmsg = e_secure; // Check for a "normal" directory or file name in some options. } else if (check_illegal_path_names(*varp, opt->flags)) { errmsg = e_invarg; - } else if (gvarp == &p_bkc) { // 'backupcopy' - did_set_backupcopy(buf, oldval, opt_flags, &errmsg); - } else if (varp == &p_bex // 'backupext' - || varp == &p_pm) { // 'patchmode' - did_set_backupext_or_patchmode(&errmsg); - } else if (varp == &win->w_p_briopt) { // 'breakindentopt' - did_set_breakindentopt(win, &errmsg); + } else if (did_set_cb != NULL) { + // Invoke the option specific callback function to validate and apply + // the new option value. + errmsg = did_set_cb(&args); } else if (varp == &p_isi // 'isident' || varp == &buf->b_p_isk // 'iskeyword' || varp == &p_isp // 'isprint' || varp == &p_isf) { // 'isfname' did_set_isopt(buf, &did_chartab, &errmsg); - } else if (varp == &p_hf) { // 'helpfile' - did_set_helpfile(); - } else if (varp == &p_rtp // 'runtimepath' - || varp == &p_pp) { // 'packpath' - runtime_search_path_invalidate(); } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' did_set_cursorlineopt(win, varp, &errmsg); } else if (varp == &win->w_p_cc) { // 'colorcolumn' errmsg = check_colorcolumn(win); - } else if (varp == &p_hlg) { // 'helplang' - did_set_helplang(&errmsg); - } else if (varp == &p_hl) { // 'highlight' - did_set_highlight(varp, &errmsg); } else if (varp == &p_jop) { // 'jumpoptions' did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg); } else if (gvarp == &p_nf) { // 'nrformats' did_set_opt_strings(*varp, p_nf_values, true, &errmsg); - } else if (varp == &p_ssop) { // 'sessionoptions' - did_set_sessionoptions(oldval, &errmsg); } else if (varp == &p_vop) { // 'viewoptions' did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg); } else if (varp == &p_rdb) { // 'redrawdebug' did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg); } else if (varp == &p_sbo) { // 'scrollopt' did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg); - } else if (varp == &p_ambw // 'ambiwidth' - || (int *)varp == &p_emoji) { // 'emoji' - did_set_ambiwidth(&errmsg); - } else if (varp == &p_bg) { // 'background' - did_set_background(&errmsg); - } else if (varp == &p_wim) { // 'wildmode' - did_set_wildmode(&errmsg); } else if (varp == &p_wop) { // 'wildoptions' did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg); - } else if (varp == &p_wak) { // 'winaltkeys' - did_set_winaltkeys(&errmsg); - } else if (varp == &p_ei) { // 'eventignore' - did_set_eventignore(&errmsg); } else if (varp == &p_enc // 'encoding' || gvarp == &p_fenc // 'fileencoding' || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (gvarp == &p_ff) { // 'fileformat' - did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg); } else if (varp == &p_ffs) { // 'fileformats' did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg); - } else if (gvarp == &p_mps) { // 'matchpairs' - did_set_matchpairs(varp, &errmsg); } else if (gvarp == &p_com) { // 'comments' did_set_comments(varp, errbuf, errbuflen, &errmsg); } else if (varp == &p_lcs // global 'listchars' @@ -1664,123 +1809,43 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx errmsg = set_chars_option(win, varp, true); } else if (varp == &win->w_p_fcs) { // local 'fillchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &p_cedit) { // 'cedit' - errmsg = check_cedit(); - } else if (varp == &p_vfile) { // 'verbosefile' - did_set_verbosefile(&errmsg); } else if (varp == &p_shada) { // 'shada' - did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_sbr) { // 'showbreak' - did_set_showbreak(varp, &errmsg); - } else if (varp == &p_guicursor) { // 'guicursor' - errmsg = parse_shape_opt(SHAPE_CURSOR); - } else if (varp == &p_langmap) { // 'langmap' - langmap_set(); - } else if (varp == &p_breakat) { // 'breakat' - fill_breakat_flags(); - } else if (varp == &p_titlestring // 'titlestring' - || varp == &p_iconstring) { // 'iconstring' - did_set_titleiconstring(varp); - } else if (varp == &p_sel) { // 'selection' - did_set_selection(&errmsg); + errmsg = did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen); } else if (varp == &p_slm) { // 'selectmode' did_set_opt_strings(p_slm, p_slm_values, true, &errmsg); - } else if (varp == &p_km) { // 'keymodel' - did_set_keymodel(&errmsg); } else if (varp == &p_mousem) { // 'mousemodel' did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg); - } else if (varp == &p_mousescroll) { // 'mousescroll' - errmsg = check_mousescroll(p_mousescroll); } else if (varp == &p_swb) { // 'switchbuf' did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg); } else if (varp == &p_spk) { // 'splitkeep' did_set_opt_strings(p_spk, p_spk_values, false, &errmsg); } else if (varp == &p_debug) { // 'debug' did_set_opt_strings(p_debug, p_debug_values, true, &errmsg); - } else if (varp == &p_dy) { // 'display' - did_set_display(&errmsg); } else if (varp == &p_ead) { // 'eadirection' did_set_opt_strings(p_ead, p_ead_values, false, &errmsg); } else if (varp == &p_cb) { // 'clipboard' did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg); - } else if (varp == &win->w_s->b_p_spf) { // 'spellfile' - did_set_spellfile(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spl) { // 'spell' - did_set_spell(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck' - did_set_spellcapcheck(win, &errmsg); - } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' - did_set_spelloptions(win, &errmsg); - } else if (varp == &p_sps) { // 'spellsuggest' - did_set_spellsuggest(&errmsg); - } else if (varp == &p_msm) { // 'mkspellmem' - did_set_mkspellmem(&errmsg); } else if (gvarp == &p_bh) { // 'bufhidden' did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg); - } else if (gvarp == &p_bt) { // 'buftype' - did_set_buftype(buf, win, &errmsg); - } else if (gvarp == &p_stl // 'statusline' - || gvarp == &p_wbr // 'winbar' - || varp == &p_tal // 'tabline' - || varp == &p_ruf // 'rulerformat' - || varp == &win->w_p_stc) { // 'statuscolumn' - did_set_statusline(win, varp, gvarp, &errmsg); } else if (gvarp == &p_cpt) { // 'complete' did_set_complete(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cot) { // 'completeopt' - did_set_completeopt(&errmsg); -#ifdef BACKSLASH_IN_FILENAME - } else if (gvarp == &p_csl) { // 'completeslash' - did_set_completeslash(buf, &errmsg); -#endif - } else if (varp == &win->w_p_scl) { // 'signcolumn' - did_set_signcolumn(win, varp, oldval, &errmsg); } else if (varp == &p_sloc) { // 'showcmdloc' did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' - did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_bs) { // 'backspace' - did_set_backspace(&errmsg); } else if (varp == &p_bo) { did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg); - } else if (gvarp == &p_tc) { // 'tagcase' - did_set_tagcase(buf, opt_flags, &errmsg); } else if (varp == &p_cmp) { // 'casemap' did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg); - } else if (varp == &p_dip) { // 'diffopt' - did_set_diffopt(&errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' - did_set_foldmethod(win, varp, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' - did_set_foldmarker(win, varp, &errmsg); - } else if (gvarp == &p_cms) { // 'commentstring' - did_set_commentstring(varp, &errmsg); } else if (varp == &p_fdo) { // 'foldopen' did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg); } else if (varp == &p_fcl) { // 'foldclose' did_set_opt_strings(*varp, p_fcl_values, true, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' - did_set_foldignore(win); - } else if (gvarp == &p_ve) { // 'virtualedit' - did_set_virtualedit(win, opt_flags, oldval, &errmsg); - } else if (gvarp == &p_cino) { // 'cinoptions' - // TODO(vim): recognize errors - parse_cino(buf); - } else if (gvarp == &p_lop) { // 'lispoptions' - did_set_lispoptions(varp, &errmsg); } else if (varp == &p_icm) { // 'inccommand' did_set_opt_strings(*varp, p_icm_values, false, &errmsg); } else if (gvarp == &p_ft // 'filetype' || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &win->w_p_winhl) { // 'winhighlight' - did_set_winhl(win, &errmsg); } else if (varp == &p_tpf) { did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg); - } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' - did_set_varsoftabstop(buf, varp, &errmsg); - } else if (varp == &buf->b_p_vts) { // 'vartabstop' - did_set_vartabstop(buf, win, varp, &errmsg); } else if (varp == &p_dex // 'diffexpr' || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' @@ -1793,18 +1858,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (gvarp == &p_cfu) { // 'completefunc' - set_completefunc_option(&errmsg); - } else if (gvarp == &p_ofu) { // 'omnifunc' - set_omnifunc_option(buf, &errmsg); - } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' - set_thesaurusfunc_option(&errmsg); - } else if (varp == &p_opfunc) { // 'operatorfunc' - set_operatorfunc_option(&errmsg); - } else if (varp == &p_qftf) { // 'quickfixtextfunc' - qf_process_qftf_option(&errmsg); - } else if (gvarp == &p_tfu) { // 'tagfunc' - set_tagfunc_option(&errmsg); } else if (varp == &p_ww) { // 'whichwrap' did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg); } else if (varp == &p_shm) { // 'shortmess' @@ -1817,12 +1870,6 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg); } else if (varp == &p_mouse) { // 'mouse' did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_flp) { // 'formatlistpat' - if (win->w_briopt_list) { - // Changing Formatlistpattern when briopt includes the list setting: - // redraw - redraw_all_later(UPD_NOT_VALID); - } } // If an error is detected, restore the previous value. @@ -1875,6 +1922,16 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx setmouse(); // in case 'mouse' changed } + if ((varp == &p_flp || varp == &(buf->b_p_flp)) + && win->w_briopt_list) { + // Changing Formatlistpattern when briopt includes the list setting: + // redraw + redraw_all_later(UPD_NOT_VALID); + } else if (varp == &p_wbr || varp == &(win->w_p_wbr)) { + // add / remove window bars for 'winbar' + set_winbar(true); + } + if (win->w_curswant != MAXCOL && (opt->flags & (P_CURSWANT | P_RALL)) != 0) { win->w_set_curswant = true; @@ -1885,11 +1942,11 @@ static const char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx return errmsg; } -const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, +const char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *value, char *errbuf, size_t errbuflen, int opt_flags, int *value_checked) { - return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen, - opt_flags, value_checked); + return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, value, errbuf, + errbuflen, opt_flags, value_checked); } /// Check an option that can be a range of string values. @@ -1910,7 +1967,7 @@ static int check_opt_strings(char *val, char **values, int list) /// @param list when true: accept a list of values /// /// @return OK for correct value, FAIL otherwise. Empty is always OK. -static int opt_strings_flags(char *val, char **values, unsigned *flagp, bool list) +static int opt_strings_flags(const char *val, char **values, unsigned *flagp, bool list) { unsigned new_flags = 0; @@ -1946,9 +2003,8 @@ int check_ff_value(char *p) static char shm_buf[SHM_LEN]; static int set_shm_recursive = 0; -/// Save the acutal shortmess Flags and clear them -/// temporarily to avoid that file messages -/// overwrites any output from the following commands. +/// Save the actual shortmess Flags and clear them temporarily to avoid that +/// file messages overwrites any output from the following commands. /// /// Caller must make sure to first call save_clear_shm_value() and then /// restore_shm_value() exactly the same number of times. |