blob: 5a3dd6e758dfd7d151233481f3865a58bb0b49ce [file] [log] [blame]
Bram Moolenaardac13472019-09-16 21:06:21 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * optionstr.c: Functions related to string options
12 */
13
14#include "vim.h"
15
Christian Brabandt9aee8ec2022-12-16 16:41:23 +000016static char_u shm_buf[SHM_LEN];
17static int set_shm_recursive = 0;
18
Bram Moolenaardac13472019-09-16 21:06:21 +020019static char *(p_ambw_values[]) = {"single", "double", NULL};
20static char *(p_bg_values[]) = {"light", "dark", NULL};
21static char *(p_bkc_values[]) = {"yes", "auto", "no", "breaksymlink", "breakhardlink", NULL};
22static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete",
23 "copy", "ctrlg", "error", "esc", "ex",
24 "hangul", "insertmode", "lang", "mess",
25 "showmatch", "operator", "register", "shell",
LemonBoy77771d32022-04-13 11:47:25 +010026 "spell", "term", "wildmode", NULL};
Yee Cheng Chin900894b2023-09-29 20:42:32 +020027#if defined(FEAT_LINEBREAK)
28// Note: Keep this in sync with briopt_check()
29static char *(p_briopt_values[]) = {"shift:", "min:", "sbr", "list:", "column:", NULL};
30#endif
31#if defined(FEAT_DIFF)
32// Note: Keep this in sync with diffopt_changed()
33static char *(p_dip_values[]) = {"filler", "context:", "iblank", "icase", "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", "indent-heuristic", "algorithm:", NULL};
34static char *(p_dip_algorithm_values[]) = {"myers", "minimal", "patience", "histogram", NULL};
35#endif
Bram Moolenaaraaad9952020-05-31 15:08:59 +020036static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020037static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
Yee Cheng Chin900894b2023-09-29 20:42:32 +020038#ifdef FEAT_CLIPBOARD
39// Note: Keep this in sync with did_set_clipboard()
40static char *(p_cb_values[]) = {"unnamed", "unnamedplus", "autoselect", "autoselectplus", "autoselectml", "html", "exclude:", NULL};
41#endif
Bram Moolenaardac13472019-09-16 21:06:21 +020042#ifdef FEAT_CRYPT
Christian Brabandtf573c6e2021-06-20 14:02:16 +020043static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2",
44 # ifdef FEAT_SODIUM
Christian Brabandtaae58342023-04-23 17:50:22 +010045 "xchacha20", "xchacha20v2",
Christian Brabandtf573c6e2021-06-20 14:02:16 +020046 # endif
47 NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020048#endif
49static char *(p_cmp_values[]) = {"internal", "keepascii", NULL};
Yee Cheng Chin900894b2023-09-29 20:42:32 +020050#ifdef FEAT_SYN_HL
51// Note: Keep this in sync with fill_culopt_flags()
52static char *(p_culopt_values[]) = {"line", "screenline", "number", "both", NULL};
53#endif
Bram Moolenaardac13472019-09-16 21:06:21 +020054static char *(p_dy_values[]) = {"lastline", "truncate", "uhex", NULL};
Yegappan Lakshmanan87018252023-09-20 20:20:04 +020055static char *(p_jop_values[]) = {"stack", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020056#ifdef FEAT_FOLDING
57static char *(p_fdo_values[]) = {"all", "block", "hor", "mark", "percent",
58 "quickfix", "search", "tag", "insert",
59 "undo", "jump", NULL};
60#endif
Yee Cheng Chin900894b2023-09-29 20:42:32 +020061// Note: Keep this in sync with match_keyprotocol()
62static char *(p_kpc_protocol_values[]) = {"none", "mok2", "kitty", NULL};
63#ifdef FEAT_PROP_POPUP
64// Note: Keep this in sync with parse_popup_option()
65static char *(p_popup_option_values[]) = {"height:", "width:", "highlight:", "border:", "align:", NULL};
66static char *(p_popup_option_border_values[]) = {"on", "off", NULL};
67static char *(p_popup_option_align_values[]) = {"item", "menu", NULL};
68#endif
69#if defined(FEAT_SPELL)
70// Note: Keep this in sync with spell_check_sps()
71static char *(p_sps_values[]) = {"best", "fast", "double", "expr:", "file:", "timeout:", NULL};
72#endif
Bram Moolenaardac13472019-09-16 21:06:21 +020073#ifdef FEAT_SESSION
Bram Moolenaar635bd602021-04-16 19:58:22 +020074// Also used for 'viewoptions'! Keep in sync with SSOP_ flags.
Bram Moolenaardac13472019-09-16 21:06:21 +020075static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize",
76 "localoptions", "options", "help", "blank", "globals", "slash", "unix",
Bram Moolenaar635bd602021-04-16 19:58:22 +020077 "sesdir", "curdir", "folds", "cursor", "tabpages", "terminal", "skiprtp",
78 NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020079#endif
Bram Moolenaar539aa6b2019-11-17 18:09:38 +010080// Keep in sync with SWB_ flags in option.h
81static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL};
Luuk van Baal13ece2a2022-10-03 15:28:08 +010082static char *(p_spk_values[]) = {"cursor", "screen", "topline", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020083static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL};
84#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
85static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL};
86#endif
87#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
88static char *(p_tbis_values[]) = {"tiny", "small", "medium", "large", "huge", "giant", NULL};
89#endif
Bram Moolenaara1cb1d12019-10-17 23:00:07 +020090#if defined(UNIX) || defined(VMS)
Bram Moolenaardac13472019-09-16 21:06:21 +020091static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", "urxvt", "sgr", NULL};
92#endif
Gary Johnson53ba05b2021-07-26 22:19:10 +020093static char *(p_ve_values[]) = {"block", "insert", "all", "onemore", "none", "NONE", NULL};
Yee Cheng Chin900894b2023-09-29 20:42:32 +020094// Note: Keep this in sync with check_opt_wim()
95static char *(p_wim_values[]) = {"full", "longest", "list", "lastused", NULL};
Yegappan Lakshmanan38b85cb2022-02-24 13:28:41 +000096static char *(p_wop_values[]) = {"fuzzy", "tagfile", "pum", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +020097#ifdef FEAT_WAK
98static char *(p_wak_values[]) = {"yes", "menu", "no", NULL};
99#endif
100static char *(p_mousem_values[]) = {"extend", "popup", "popup_setpos", "mac", NULL};
101static char *(p_sel_values[]) = {"inclusive", "exclusive", "old", NULL};
102static char *(p_slm_values[]) = {"mouse", "key", "cmd", NULL};
103static char *(p_km_values[]) = {"startsel", "stopsel", NULL};
104#ifdef FEAT_BROWSE
105static char *(p_bsdir_values[]) = {"current", "last", "buffer", NULL};
106#endif
107static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL};
108static char *(p_debug_values[]) = {"msg", "throw", "beep", NULL};
109static char *(p_ead_values[]) = {"both", "ver", "hor", NULL};
110static char *(p_buftype_values[]) = {"nofile", "nowrite", "quickfix", "help", "terminal", "acwrite", "prompt", "popup", NULL};
111static char *(p_bufhidden_values[]) = {"hide", "unload", "delete", "wipe", NULL};
Bram Moolenaaraa0489e2020-04-17 19:41:21 +0200112static char *(p_bs_values[]) = {"indent", "eol", "start", "nostop", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +0200113#ifdef FEAT_FOLDING
114static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax",
115# ifdef FEAT_DIFF
116 "diff",
117# endif
118 NULL};
119static char *(p_fcl_values[]) = {"all", NULL};
120#endif
Bram Moolenaardca7abe2019-10-20 18:17:57 +0200121static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "popuphidden", "noinsert", "noselect", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +0200122#ifdef BACKSLASH_IN_FILENAME
123static char *(p_csl_values[]) = {"slash", "backslash", NULL};
124#endif
125#ifdef FEAT_SIGNS
126static char *(p_scl_values[]) = {"yes", "no", "auto", "number", NULL};
127#endif
128#if defined(MSWIN) && defined(FEAT_TERMINAL)
129static char *(p_twt_values[]) = {"winpty", "conpty", "", NULL};
130#endif
Luuk van Baalba936f62022-12-15 13:15:39 +0000131static char *(p_sloc_values[]) = {"last", "statusline", "tabline", NULL};
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +0000132static char *(p_sws_values[]) = {"fsync", "sync", NULL};
Bram Moolenaardac13472019-09-16 21:06:21 +0200133
134static int check_opt_strings(char_u *val, char **values, int list);
135static int opt_strings_flags(char_u *val, char **values, unsigned *flagp, int list);
136
137/*
138 * After setting various option values: recompute variables that depend on
139 * option values.
140 */
141 void
142didset_string_options(void)
143{
144 (void)opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
145 (void)opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, TRUE);
146 (void)opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE);
147#ifdef FEAT_SESSION
148 (void)opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE);
149 (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
150#endif
151#ifdef FEAT_FOLDING
152 (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
153#endif
154 (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE);
Yegappan Lakshmanan87018252023-09-20 20:20:04 +0200155 (void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, TRUE);
Bram Moolenaardac13472019-09-16 21:06:21 +0200156 (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, FALSE);
157 (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE);
Bram Moolenaara1cb1d12019-10-17 23:00:07 +0200158#if defined(UNIX) || defined(VMS)
Bram Moolenaardac13472019-09-16 21:06:21 +0200159 (void)opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE);
160#endif
161#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
162 (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE);
163#endif
164#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
165 (void)opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE);
166#endif
Sean Dewar39c46b42022-05-12 17:44:29 +0100167 (void)opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE);
Bram Moolenaardac13472019-09-16 21:06:21 +0200168}
169
Yegappan Lakshmananf9dc2782023-05-11 15:02:56 +0100170#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaardac13472019-09-16 21:06:21 +0200171/*
172 * Trigger the OptionSet autocommand.
173 * "opt_idx" is the index of the option being set.
174 * "opt_flags" can be OPT_LOCAL etc.
175 * "oldval" the old value
176 * "oldval_l" the old local value (only non-NULL if global and local value
177 * are set)
178 * "oldval_g" the old global value (only non-NULL if global and local value
179 * are set)
180 * "newval" the new value
181 */
182 void
zeertzjq269aa2b2022-11-28 11:36:50 +0000183trigger_optionset_string(
Bram Moolenaardac13472019-09-16 21:06:21 +0200184 int opt_idx,
185 int opt_flags,
186 char_u *oldval,
187 char_u *oldval_l,
188 char_u *oldval_g,
189 char_u *newval)
190{
191 // Don't do this recursively.
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000192 if (oldval == NULL || newval == NULL
193 || *get_vim_var_str(VV_OPTION_TYPE) != NUL)
194 return;
Bram Moolenaardac13472019-09-16 21:06:21 +0200195
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000196 char_u buf_type[7];
197
198 sprintf((char *)buf_type, "%s",
Bram Moolenaardac13472019-09-16 21:06:21 +0200199 (opt_flags & OPT_LOCAL) ? "local" : "global");
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000200 set_vim_var_string(VV_OPTION_OLD, oldval, -1);
201 set_vim_var_string(VV_OPTION_NEW, newval, -1);
202 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
203 if (opt_flags & OPT_LOCAL)
204 {
205 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
206 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
Bram Moolenaardac13472019-09-16 21:06:21 +0200207 }
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000208 if (opt_flags & OPT_GLOBAL)
209 {
210 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
211 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
212 }
213 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
214 {
215 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
216 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
217 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
218 }
219 if (opt_flags & OPT_MODELINE)
220 {
221 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
222 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
223 }
224 apply_autocmds(EVENT_OPTIONSET,
225 get_option_fullname(opt_idx), NULL, FALSE,
226 NULL);
227 reset_v_option_vars();
Bram Moolenaardac13472019-09-16 21:06:21 +0200228}
229#endif
230
231 static char *
232illegal_char(char *errbuf, int c)
233{
234 if (errbuf == NULL)
235 return "";
Bram Moolenaar1d423ef2022-01-02 21:26:16 +0000236 sprintf((char *)errbuf, _(e_illegal_character_str), (char *)transchar(c));
Bram Moolenaardac13472019-09-16 21:06:21 +0200237 return errbuf;
238}
239
240/*
241 * Check string options in a buffer for NULL value.
242 */
243 void
244check_buf_options(buf_T *buf)
245{
246 check_string_option(&buf->b_p_bh);
247 check_string_option(&buf->b_p_bt);
248 check_string_option(&buf->b_p_fenc);
249 check_string_option(&buf->b_p_ff);
250#ifdef FEAT_FIND_ID
251 check_string_option(&buf->b_p_def);
252 check_string_option(&buf->b_p_inc);
253# ifdef FEAT_EVAL
254 check_string_option(&buf->b_p_inex);
255# endif
256#endif
Bram Moolenaar8e145b82022-05-21 20:17:31 +0100257#if defined(FEAT_EVAL)
Bram Moolenaardac13472019-09-16 21:06:21 +0200258 check_string_option(&buf->b_p_inde);
259 check_string_option(&buf->b_p_indk);
260#endif
261#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
262 check_string_option(&buf->b_p_bexpr);
263#endif
264#if defined(FEAT_CRYPT)
265 check_string_option(&buf->b_p_cm);
266#endif
267 check_string_option(&buf->b_p_fp);
268#if defined(FEAT_EVAL)
269 check_string_option(&buf->b_p_fex);
270#endif
271#ifdef FEAT_CRYPT
272 check_string_option(&buf->b_p_key);
273#endif
274 check_string_option(&buf->b_p_kp);
275 check_string_option(&buf->b_p_mps);
276 check_string_option(&buf->b_p_fo);
277 check_string_option(&buf->b_p_flp);
278 check_string_option(&buf->b_p_isk);
Bram Moolenaardac13472019-09-16 21:06:21 +0200279 check_string_option(&buf->b_p_com);
Bram Moolenaardac13472019-09-16 21:06:21 +0200280#ifdef FEAT_FOLDING
281 check_string_option(&buf->b_p_cms);
282#endif
283 check_string_option(&buf->b_p_nf);
Bram Moolenaardac13472019-09-16 21:06:21 +0200284 check_string_option(&buf->b_p_qe);
Bram Moolenaardac13472019-09-16 21:06:21 +0200285#ifdef FEAT_SYN_HL
286 check_string_option(&buf->b_p_syn);
287 check_string_option(&buf->b_s.b_syn_isk);
288#endif
289#ifdef FEAT_SPELL
290 check_string_option(&buf->b_s.b_p_spc);
291 check_string_option(&buf->b_s.b_p_spf);
292 check_string_option(&buf->b_s.b_p_spl);
Bram Moolenaar362b44b2020-06-10 21:47:00 +0200293 check_string_option(&buf->b_s.b_p_spo);
Bram Moolenaardac13472019-09-16 21:06:21 +0200294#endif
Bram Moolenaardac13472019-09-16 21:06:21 +0200295 check_string_option(&buf->b_p_sua);
Bram Moolenaardac13472019-09-16 21:06:21 +0200296 check_string_option(&buf->b_p_cink);
297 check_string_option(&buf->b_p_cino);
Tom Praschan3506cf32022-04-07 12:39:08 +0100298 check_string_option(&buf->b_p_cinsd);
Bram Moolenaardac13472019-09-16 21:06:21 +0200299 parse_cino(buf);
Bram Moolenaar49846fb2022-10-15 16:05:33 +0100300 check_string_option(&buf->b_p_lop);
Bram Moolenaardac13472019-09-16 21:06:21 +0200301 check_string_option(&buf->b_p_ft);
Bram Moolenaardac13472019-09-16 21:06:21 +0200302 check_string_option(&buf->b_p_cinw);
Bram Moolenaardac13472019-09-16 21:06:21 +0200303 check_string_option(&buf->b_p_cpt);
304#ifdef FEAT_COMPL_FUNC
305 check_string_option(&buf->b_p_cfu);
306 check_string_option(&buf->b_p_ofu);
Bram Moolenaard4c4bfa2021-10-16 21:14:11 +0100307 check_string_option(&buf->b_p_tsrfu);
Bram Moolenaardac13472019-09-16 21:06:21 +0200308#endif
309#ifdef FEAT_EVAL
310 check_string_option(&buf->b_p_tfu);
311#endif
312#ifdef FEAT_KEYMAP
313 check_string_option(&buf->b_p_keymap);
314#endif
315#ifdef FEAT_QUICKFIX
316 check_string_option(&buf->b_p_gp);
317 check_string_option(&buf->b_p_mp);
318 check_string_option(&buf->b_p_efm);
319#endif
320 check_string_option(&buf->b_p_ep);
321 check_string_option(&buf->b_p_path);
322 check_string_option(&buf->b_p_tags);
323 check_string_option(&buf->b_p_tc);
324 check_string_option(&buf->b_p_dict);
325 check_string_option(&buf->b_p_tsr);
Bram Moolenaardac13472019-09-16 21:06:21 +0200326 check_string_option(&buf->b_p_lw);
Bram Moolenaardac13472019-09-16 21:06:21 +0200327 check_string_option(&buf->b_p_bkc);
328 check_string_option(&buf->b_p_menc);
329#ifdef FEAT_VARTABS
330 check_string_option(&buf->b_p_vsts);
331 check_string_option(&buf->b_p_vts);
332#endif
333}
334
335/*
336 * Free the string allocated for an option.
337 * Checks for the string being empty_option. This may happen if we're out of
338 * memory, vim_strsave() returned NULL, which was replaced by empty_option by
339 * check_options().
340 * Does NOT check for P_ALLOCED flag!
341 */
342 void
343free_string_option(char_u *p)
344{
345 if (p != empty_option)
346 vim_free(p);
347}
348
349 void
350clear_string_option(char_u **pp)
351{
352 if (*pp != empty_option)
353 vim_free(*pp);
354 *pp = empty_option;
355}
356
357 void
358check_string_option(char_u **pp)
359{
360 if (*pp == NULL)
361 *pp = empty_option;
362}
363
364/*
365 * Set global value for string option when it's a local option.
366 */
367 static void
368set_string_option_global(
369 int opt_idx, // option index
370 char_u **varp) // pointer to option variable
371{
372 char_u **p, *s;
373
374 // the global value is always allocated
375 if (is_window_local_option(opt_idx))
376 p = (char_u **)GLOBAL_WO(varp);
377 else
378 p = (char_u **)get_option_var(opt_idx);
379 if (!is_global_option(opt_idx)
380 && p != varp
381 && (s = vim_strsave(*varp)) != NULL)
382 {
383 free_string_option(*p);
384 *p = s;
385 }
386}
387
388/*
389 * Set a string option to a new value (without checking the effect).
390 * The string is copied into allocated memory.
391 * if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used.
392 * When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When
393 * "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to
394 * "set_sid".
395 */
396 void
397set_string_option_direct(
398 char_u *name,
399 int opt_idx,
400 char_u *val,
401 int opt_flags, // OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
402 int set_sid UNUSED)
403{
404 char_u *s;
405 char_u **varp;
406 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
407 int idx = opt_idx;
408
409 if (idx == -1) // use name
410 {
411 idx = findoption(name);
412 if (idx < 0) // not found (should not happen)
413 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000414 semsg(_(e_internal_error_str), "set_string_option_direct()");
RestorerZ68ebcee2023-05-31 17:12:14 +0100415 siemsg("For option %s", name);
Bram Moolenaardac13472019-09-16 21:06:21 +0200416 return;
417 }
418 }
419
420 if (is_hidden_option(idx)) // can't set hidden option
421 return;
422
423 s = vim_strsave(val);
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000424 if (s == NULL)
425 return;
426
427 varp = (char_u **)get_option_varp_scope(idx,
428 both ? OPT_LOCAL : opt_flags);
429 if ((opt_flags & OPT_FREE) && (get_option_flags(idx) & P_ALLOCED))
430 free_string_option(*varp);
431 *varp = s;
432
433 // For buffer/window local option may also set the global value.
434 if (both)
435 set_string_option_global(idx, varp);
436
437 set_option_flag(idx, P_ALLOCED);
438
439 // When setting both values of a global option with a local value,
440 // make the local value empty, so that the global value is used.
441 if (is_global_local_option(idx) && both)
Bram Moolenaardac13472019-09-16 21:06:21 +0200442 {
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000443 free_string_option(*varp);
444 *varp = empty_option;
Bram Moolenaardac13472019-09-16 21:06:21 +0200445 }
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000446# ifdef FEAT_EVAL
447 if (set_sid != SID_NONE)
448 {
449 sctx_T script_ctx;
450
451 if (set_sid == 0)
452 script_ctx = current_sctx;
453 else
454 {
455 script_ctx.sc_sid = set_sid;
456 script_ctx.sc_seq = 0;
457 script_ctx.sc_lnum = 0;
458 script_ctx.sc_version = 1;
459 }
460 set_option_sctx_idx(idx, opt_flags, script_ctx);
461 }
462# endif
Bram Moolenaardac13472019-09-16 21:06:21 +0200463}
464
Dominique Pellee764d1b2023-03-12 21:20:59 +0000465#if defined(FEAT_PROP_POPUP) || \
466 (defined(FEAT_DIFF) && defined(FEAT_FOLDING)) || defined(PROTO)
Bram Moolenaardac13472019-09-16 21:06:21 +0200467/*
468 * Like set_string_option_direct(), but for a window-local option in "wp".
469 * Blocks autocommands to avoid the old curwin becoming invalid.
470 */
471 void
472set_string_option_direct_in_win(
473 win_T *wp,
474 char_u *name,
475 int opt_idx,
476 char_u *val,
477 int opt_flags,
478 int set_sid)
479{
480 win_T *save_curwin = curwin;
481
482 block_autocmds();
483 curwin = wp;
484 curbuf = curwin->w_buffer;
485 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
486 curwin = save_curwin;
487 curbuf = curwin->w_buffer;
488 unblock_autocmds();
489}
Dominique Pellee764d1b2023-03-12 21:20:59 +0000490#endif
Bram Moolenaardac13472019-09-16 21:06:21 +0200491
Dominique Pelle748b3082022-01-08 12:41:16 +0000492#if defined(FEAT_PROP_POPUP) || defined(PROTO)
Bram Moolenaardac13472019-09-16 21:06:21 +0200493/*
494 * Like set_string_option_direct(), but for a buffer-local option in "buf".
495 * Blocks autocommands to avoid the old curbuf becoming invalid.
496 */
497 void
498set_string_option_direct_in_buf(
499 buf_T *buf,
500 char_u *name,
501 int opt_idx,
502 char_u *val,
503 int opt_flags,
504 int set_sid)
505{
506 buf_T *save_curbuf = curbuf;
507
508 block_autocmds();
509 curbuf = buf;
510 curwin->w_buffer = curbuf;
511 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
512 curbuf = save_curbuf;
513 curwin->w_buffer = curbuf;
514 unblock_autocmds();
515}
Dominique Pelle748b3082022-01-08 12:41:16 +0000516#endif
Bram Moolenaardac13472019-09-16 21:06:21 +0200517
518/*
519 * Set a string option to a new value, and handle the effects.
520 *
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100521 * Returns NULL on success or an untranslated error message on error.
Bram Moolenaardac13472019-09-16 21:06:21 +0200522 */
523 char *
524set_string_option(
525 int opt_idx,
526 char_u *value,
Yegappan Lakshmanan32ff96e2023-02-13 16:10:04 +0000527 int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL
528 char *errbuf)
Bram Moolenaardac13472019-09-16 21:06:21 +0200529{
530 char_u *s;
531 char_u **varp;
532 char_u *oldval;
533#if defined(FEAT_EVAL)
534 char_u *oldval_l = NULL;
535 char_u *oldval_g = NULL;
536 char_u *saved_oldval = NULL;
537 char_u *saved_oldval_l = NULL;
538 char_u *saved_oldval_g = NULL;
539 char_u *saved_newval = NULL;
540#endif
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100541 char *errmsg = NULL;
Bram Moolenaardac13472019-09-16 21:06:21 +0200542 int value_checked = FALSE;
543
544 if (is_hidden_option(opt_idx)) // don't set hidden option
545 return NULL;
546
Bram Moolenaar7f009df2020-03-16 20:27:38 +0100547 s = vim_strsave(value == NULL ? (char_u *)"" : value);
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000548 if (s == NULL)
549 return NULL;
550
551 varp = (char_u **)get_option_varp_scope(opt_idx,
552 (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
553 ? (is_global_local_option(opt_idx)
554 ? OPT_GLOBAL : OPT_LOCAL)
555 : opt_flags);
556 oldval = *varp;
557#if defined(FEAT_EVAL)
558 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
Bram Moolenaardac13472019-09-16 21:06:21 +0200559 {
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000560 oldval_l = *(char_u **)get_option_varp_scope(opt_idx, OPT_LOCAL);
561 oldval_g = *(char_u **)get_option_varp_scope(opt_idx, OPT_GLOBAL);
Bram Moolenaardac13472019-09-16 21:06:21 +0200562 }
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000563#endif
564 *varp = s;
565
566#if defined(FEAT_EVAL)
567 if (!starting
568# ifdef FEAT_CRYPT
569 && !is_crypt_key_option(opt_idx)
570# endif
571 )
572 {
573 if (oldval_l != NULL)
574 saved_oldval_l = vim_strsave(oldval_l);
575 if (oldval_g != NULL)
576 saved_oldval_g = vim_strsave(oldval_g);
577 saved_oldval = vim_strsave(oldval);
578 saved_newval = vim_strsave(s);
579 }
580#endif
Yegappan Lakshmananaf936912023-02-20 12:16:39 +0000581 if ((errmsg = did_set_string_option(opt_idx, varp, oldval, value, errbuf,
Yee Cheng Chin6ee7b522023-10-01 09:13:22 +0200582 opt_flags, OP_NONE, &value_checked)) == NULL)
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000583 did_set_option(opt_idx, opt_flags, TRUE, value_checked);
584
585#if defined(FEAT_EVAL)
586 // call autocommand after handling side effects
587 if (errmsg == NULL)
588 trigger_optionset_string(opt_idx, opt_flags,
589 saved_oldval, saved_oldval_l,
590 saved_oldval_g, saved_newval);
591 vim_free(saved_oldval);
592 vim_free(saved_oldval_l);
593 vim_free(saved_oldval_g);
594 vim_free(saved_newval);
595#endif
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100596 return errmsg;
Bram Moolenaardac13472019-09-16 21:06:21 +0200597}
598
599/*
600 * Return TRUE if "val" is a valid 'filetype' name.
601 * Also used for 'syntax' and 'keymap'.
602 */
603 static int
604valid_filetype(char_u *val)
605{
606 return valid_name(val, ".-_");
607}
608
609#ifdef FEAT_STL_OPT
610/*
611 * Check validity of options with the 'statusline' format.
zeertzjq5dc294a2022-04-15 13:17:57 +0100612 * Return an untranslated error message or NULL.
Bram Moolenaardac13472019-09-16 21:06:21 +0200613 */
614 static char *
615check_stl_option(char_u *s)
616{
Bram Moolenaardac13472019-09-16 21:06:21 +0200617 int groupdepth = 0;
618 static char errbuf[80];
619
Bram Moolenaar8133cc62020-10-26 21:05:27 +0100620 while (*s)
Bram Moolenaardac13472019-09-16 21:06:21 +0200621 {
622 // Check for valid keys after % sequences
623 while (*s && *s != '%')
624 s++;
625 if (!*s)
626 break;
627 s++;
Yegappan Lakshmanan3ec78f92023-02-11 11:15:25 +0000628 if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE)
Bram Moolenaardac13472019-09-16 21:06:21 +0200629 {
630 s++;
631 continue;
632 }
633 if (*s == ')')
634 {
635 s++;
636 if (--groupdepth < 0)
637 break;
638 continue;
639 }
640 if (*s == '-')
641 s++;
642 while (VIM_ISDIGIT(*s))
643 s++;
644 if (*s == STL_USER_HL)
645 continue;
646 if (*s == '.')
647 {
648 s++;
649 while (*s && VIM_ISDIGIT(*s))
650 s++;
651 }
652 if (*s == '(')
653 {
654 groupdepth++;
655 continue;
656 }
657 if (vim_strchr(STL_ALL, *s) == NULL)
658 {
659 return illegal_char(errbuf, *s);
660 }
661 if (*s == '{')
662 {
zeertzjq5dc294a2022-04-15 13:17:57 +0100663 int reevaluate = (*++s == '%');
shadmansaleh30e3de22021-05-15 17:23:28 +0200664
zeertzjq5dc294a2022-04-15 13:17:57 +0100665 if (reevaluate && *++s == '}')
666 // "}" is not allowed immediately after "%{%"
667 return illegal_char(errbuf, '}');
shadmansaleh30e3de22021-05-15 17:23:28 +0200668 while ((*s != '}' || (reevaluate && s[-1] != '%')) && *s)
Bram Moolenaardac13472019-09-16 21:06:21 +0200669 s++;
670 if (*s != '}')
zeertzjq5dc294a2022-04-15 13:17:57 +0100671 return e_unclosed_expression_sequence;
Bram Moolenaardac13472019-09-16 21:06:21 +0200672 }
673 }
Bram Moolenaardac13472019-09-16 21:06:21 +0200674 if (groupdepth != 0)
zeertzjq5dc294a2022-04-15 13:17:57 +0100675 return e_unbalanced_groups;
Bram Moolenaardac13472019-09-16 21:06:21 +0200676 return NULL;
677}
678#endif
679
680/*
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +0000681 * Check for a "normal" directory or file name in some options. Disallow a
682 * path separator (slash and/or backslash), wildcards and characters that are
683 * often illegal in a file name. Be more permissive if "secure" is off.
684 */
685 static int
686check_illegal_path_names(int opt_idx, char_u **varp)
687{
688 return (((get_option_flags(opt_idx) & P_NFNAME)
689 && vim_strpbrk(*varp, (char_u *)(secure
690 ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
691 || ((get_option_flags(opt_idx) & P_NDNAME)
692 && vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL));
693}
694
695/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000696 * An option that accepts a list of flags is changed.
697 * e.g. 'viewoptions', 'switchbuf', 'casemap', etc.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000698 */
699 static char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000700did_set_opt_flags(char_u *val, char **values, unsigned *flagp, int list)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000701{
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000702 if (opt_strings_flags(val, values, flagp, list) == FAIL)
703 return e_invalid_argument;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000704
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000705 return NULL;
706}
707
708/*
709 * An option that accepts a list of string values is changed.
710 * e.g. 'nrformats', 'scrollopt', 'wildoptions', etc.
711 */
712 static char *
713did_set_opt_strings(char_u *val, char **values, int list)
714{
715 return did_set_opt_flags(val, values, NULL, list);
716}
717
718/*
719 * An option which is a list of flags is set. Valid values are in 'flags'.
720 */
721 static char *
Yegappan Lakshmananc727b192023-03-03 12:26:15 +0000722did_set_option_listflag(char_u *val, char_u *flags, char *errbuf)
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000723{
724 char_u *s;
725
Yegappan Lakshmananc727b192023-03-03 12:26:15 +0000726 for (s = val; *s; ++s)
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000727 if (vim_strchr(flags, *s) == NULL)
728 return illegal_char(errbuf, *s);
729
730 return NULL;
731}
732
733/*
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200734 * Expand an option that accepts a list of string values.
735 */
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200736 static int
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200737expand_set_opt_string(
738 optexpand_T *args,
739 char **values,
740 int numValues,
741 int *numMatches,
742 char_u ***matches)
743{
744 char_u *p;
745 regmatch_T *regmatch = args->oe_regmatch;
746 int include_orig_val = args->oe_include_orig_val;
747 char_u *option_val = args->oe_opt_value;
748
749 // Assume numValues is small since they are fixed enums, so just allocate
750 // upfront instead of needing two passes to calculate output size.
751 *matches = ALLOC_MULT(char_u *, numValues + 1);
752 if (*matches == NULL)
753 return FAIL;
754
755 int count = 0;
756
757 if (include_orig_val && *option_val != NUL)
758 {
759 p = vim_strsave(option_val);
760 if (p == NULL)
761 {
762 VIM_CLEAR(*matches);
763 return FAIL;
764 }
765 (*matches)[count++] = p;
766 }
767
768 for (char **val = values; *val != NULL; val++)
769 {
770 if (include_orig_val && *option_val != NUL)
771 {
772 if (STRCMP((char_u*)*val, option_val) == 0)
773 continue;
774 }
775 if (vim_regexec(regmatch, (char_u*)(*val), (colnr_T)0))
776 {
777 p = vim_strsave((char_u*)*val);
778 if (p == NULL)
779 {
780 if (count == 0)
781 {
782 VIM_CLEAR(*matches);
783 return FAIL;
784 }
785 else
786 break;
787 }
788 (*matches)[count++] = p;
789 }
790 }
791 if (count == 0)
792 {
793 VIM_CLEAR(*matches);
794 return FAIL;
795 }
796 *numMatches = count;
797 return OK;
798}
799
800static char_u *set_opt_callback_orig_option = NULL;
801static char_u *((*set_opt_callback_func)(expand_T *, int));
802
803/*
804 * Callback used by expand_set_opt_generic to also include the original value.
805 */
806 static char_u *
807expand_set_opt_callback(expand_T *xp, int idx)
808{
809 if (idx == 0)
810 {
811 if (set_opt_callback_orig_option != NULL)
812 return set_opt_callback_orig_option;
813 else
814 return (char_u *)""; // empty strings are ignored
815 }
816 return set_opt_callback_func(xp, idx - 1);
817}
818
819/*
820 * Expand an option with a callback that iterates through a list of possible names.
821 */
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200822 static int
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200823expand_set_opt_generic(
824 optexpand_T *args,
825 char_u *((*func)(expand_T *, int)),
826 int *numMatches,
827 char_u ***matches)
828{
829 int ret;
830
831 set_opt_callback_orig_option = args->oe_include_orig_val ?
832 args->oe_opt_value : NULL;
833 set_opt_callback_func = func;
834
835 ret = ExpandGeneric(
836 (char_u*)"", // not using fuzzy as currently EXPAND_STRING_SETTING doesn't use it
837 args->oe_xp,
838 args->oe_regmatch,
839 matches,
840 numMatches,
841 expand_set_opt_callback,
842 FALSE);
843
844 set_opt_callback_orig_option = NULL;
845 set_opt_callback_func = NULL;
846 return ret;
847}
848
849
850/*
851 * Expand an option which is a list of flags.
852 */
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200853 static int
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200854expand_set_opt_listflag(
855 optexpand_T *args,
856 char_u *flags,
857 int *numMatches,
858 char_u ***matches)
859{
860 char_u *p;
861 char_u *option_val = args->oe_opt_value;
862 char_u *cmdline_val = args->oe_set_arg;
863 int append = args->oe_append;
864 int include_orig_val = args->oe_include_orig_val && (*option_val != NUL);
865
866 int num_flags = STRLEN(flags);
867
868 // Assume we only have small number of flags, so just allocate max size.
869 *matches = ALLOC_MULT(char_u *, num_flags + 1);
870 if (*matches == NULL)
871 return FAIL;
872
873 int count = 0;
874
875 if (include_orig_val)
876 {
877 p = vim_strsave(option_val);
878 if (p == NULL)
879 {
880 VIM_CLEAR(*matches);
881 return FAIL;
882 }
883 (*matches)[count++] = p;
884 }
885
886 for (char_u *flag = flags; *flag != NUL; flag++)
887 {
888 if (append && vim_strchr(option_val, *flag) != NULL)
889 continue;
890
891 if (vim_strchr(cmdline_val, *flag) == NULL)
892 {
893 if (include_orig_val
894 && option_val[1] == NUL
895 && *flag == option_val[0])
896 {
897 // This value is already used as the first choice as it's the
898 // existing flag. Just skip it to avoid duplicate.
899 continue;
900 }
901 p = vim_strnsave(flag, 1);
902 if (p == NULL)
903 {
904 if (count == 0)
905 {
906 VIM_CLEAR(*matches);
907 return FAIL;
908 }
909 else
910 break;
911 }
912 (*matches)[count++] = p;
913 }
914 }
915
916 if (count == 0)
917 {
918 VIM_CLEAR(*matches);
919 return FAIL;
920 }
921 *numMatches = count;
922 return OK;
923}
924
925/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000926 * The 'ambiwidth' option is changed.
927 */
928 char *
929did_set_ambiwidth(optset_T *args UNUSED)
930{
931 if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
932 return e_invalid_argument;
933
934 return check_chars_options();
935}
936
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200937 int
938expand_set_ambiwidth(optexpand_T *args, int *numMatches, char_u ***matches)
939{
940 return expand_set_opt_string(
941 args,
942 p_ambw_values,
943 sizeof(p_ambw_values) / sizeof(p_ambw_values[0]) - 1,
944 numMatches,
945 matches);
946}
947
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000948/*
949 * The 'background' option is changed.
950 */
951 char *
952did_set_background(optset_T *args UNUSED)
953{
954 if (check_opt_strings(p_bg, p_bg_values, FALSE) == FAIL)
955 return e_invalid_argument;
956
957#ifdef FEAT_EVAL
958 int dark = (*p_bg == 'd');
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000959#endif
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000960
961 init_highlight(FALSE, FALSE);
962
963#ifdef FEAT_EVAL
964 if (dark != (*p_bg == 'd')
965 && get_var_value((char_u *)"g:colors_name") != NULL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000966 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000967 // The color scheme must have set 'background' back to another
968 // value, that's not what we want here. Disable the color
969 // scheme and set the colors again.
970 do_unlet((char_u *)"g:colors_name", TRUE);
971 free_string_option(p_bg);
972 p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
973 check_string_option(&p_bg);
974 init_highlight(FALSE, FALSE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000975 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000976#endif
977#ifdef FEAT_TERMINAL
978 term_update_colors_all();
979#endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +0000980
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000981 return NULL;
982}
983
Yee Cheng Chin900894b2023-09-29 20:42:32 +0200984 int
985expand_set_background(optexpand_T *args, int *numMatches, char_u ***matches)
986{
987 return expand_set_opt_string(
988 args,
989 p_bg_values,
990 sizeof(p_bg_values) / sizeof(p_bg_values[0]) - 1,
991 numMatches,
992 matches);
993}
994
Yegappan Lakshmananad608982023-03-01 12:44:06 +0000995/*
996 * The 'backspace' option is changed.
997 */
998 char *
999did_set_backspace(optset_T *args UNUSED)
1000{
1001 if (VIM_ISDIGIT(*p_bs))
1002 {
1003 if (*p_bs > '3' || p_bs[1] != NUL)
1004 return e_invalid_argument;
1005 }
1006 else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK)
1007 return e_invalid_argument;
1008
1009 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001010}
1011
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001012 int
1013expand_set_backspace(optexpand_T *args, int *numMatches, char_u ***matches)
1014{
1015 return expand_set_opt_string(
1016 args,
1017 p_bs_values,
1018 sizeof(p_bs_values) / sizeof(p_bs_values[0]) - 1,
1019 numMatches,
1020 matches);
1021}
1022
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001023/*
1024 * The 'backupcopy' option is changed.
1025 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001026 char *
1027did_set_backupcopy(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001028{
1029 char_u *bkc = p_bkc;
1030 unsigned int *flags = &bkc_flags;
1031 char *errmsg = NULL;
1032
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001033 if (args->os_flags & OPT_LOCAL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001034 {
1035 bkc = curbuf->b_p_bkc;
1036 flags = &curbuf->b_bkc_flags;
1037 }
1038
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001039 if ((args->os_flags & OPT_LOCAL) && *bkc == NUL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001040 // make the local value empty: use the global value
1041 *flags = 0;
1042 else
1043 {
1044 if (opt_strings_flags(bkc, p_bkc_values, flags, TRUE) != OK)
1045 errmsg = e_invalid_argument;
1046 if ((((int)*flags & BKC_AUTO) != 0)
1047 + (((int)*flags & BKC_YES) != 0)
1048 + (((int)*flags & BKC_NO) != 0) != 1)
1049 {
1050 // Must have exactly one of "auto", "yes" and "no".
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001051 (void)opt_strings_flags(args->os_oldval.string, p_bkc_values,
1052 flags, TRUE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001053 errmsg = e_invalid_argument;
1054 }
1055 }
1056
1057 return errmsg;
1058}
1059
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001060 int
1061expand_set_backupcopy(optexpand_T *args, int *numMatches, char_u ***matches)
1062{
1063 return expand_set_opt_string(
1064 args,
1065 p_bkc_values,
1066 sizeof(p_bkc_values) / sizeof(p_bkc_values[0]) - 1,
1067 numMatches,
1068 matches);
1069}
1070
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001071/*
1072 * The 'backupext' or the 'patchmode' option is changed.
1073 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001074 char *
1075did_set_backupext_or_patchmode(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001076{
1077 if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
1078 *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
1079 return e_backupext_and_patchmode_are_equal;
1080
1081 return NULL;
1082}
1083
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001084/*
1085 * The 'belloff' option is changed.
1086 */
1087 char *
1088did_set_belloff(optset_T *args UNUSED)
1089{
1090 return did_set_opt_flags(p_bo, p_bo_values, &bo_flags, TRUE);
1091}
1092
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001093 int
1094expand_set_belloff(optexpand_T *args, int *numMatches, char_u ***matches)
1095{
1096 return expand_set_opt_string(
1097 args,
1098 p_bo_values,
1099 sizeof(p_bo_values) / sizeof(p_bo_values[0]) - 1,
1100 numMatches,
1101 matches);
1102}
1103
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001104#if defined(FEAT_LINEBREAK) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001105/*
1106 * The 'breakindentopt' option is changed.
1107 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001108 char *
1109did_set_breakindentopt(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001110{
1111 char *errmsg = NULL;
1112
1113 if (briopt_check(curwin) == FAIL)
1114 errmsg = e_invalid_argument;
1115 // list setting requires a redraw
1116 if (curwin->w_briopt_list)
1117 redraw_all_later(UPD_NOT_VALID);
1118
1119 return errmsg;
1120}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001121
1122 int
1123expand_set_breakindentopt(optexpand_T *args, int *numMatches, char_u ***matches)
1124{
1125 return expand_set_opt_string(
1126 args,
1127 p_briopt_values,
1128 sizeof(p_briopt_values) / sizeof(p_briopt_values[0]) - 1,
1129 numMatches,
1130 matches);
1131}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001132#endif
1133
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001134#if defined(FEAT_BROWSE) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001135/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001136 * The 'browsedir' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001137 */
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00001138 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001139did_set_browsedir(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001140{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001141 if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
1142 && !mch_isdir(p_bsdir))
1143 return e_invalid_argument;
1144
1145 return NULL;
1146}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001147
1148 int
1149expand_set_browsedir(optexpand_T *args, int *numMatches, char_u ***matches)
1150{
1151 return expand_set_opt_string(
1152 args,
1153 p_bsdir_values,
1154 sizeof(p_bsdir_values) / sizeof(p_bsdir_values[0]) - 1,
1155 numMatches,
1156 matches);
1157}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001158#endif
1159
1160/*
1161 * The 'bufhidden' option is changed.
1162 */
1163 char *
1164did_set_bufhidden(optset_T *args UNUSED)
1165{
1166 return did_set_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE);
1167}
1168
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001169 int
1170expand_set_bufhidden(optexpand_T *args, int *numMatches, char_u ***matches)
1171{
1172 return expand_set_opt_string(
1173 args,
1174 p_bufhidden_values,
1175 sizeof(p_bufhidden_values) / sizeof(p_bufhidden_values[0]) - 1,
1176 numMatches,
1177 matches);
1178}
1179
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001180/*
1181 * The 'buftype' option is changed.
1182 */
1183 char *
1184did_set_buftype(optset_T *args UNUSED)
1185{
1186 if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
1187 return e_invalid_argument;
1188
1189 if (curwin->w_status_height)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001190 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001191 curwin->w_redr_status = TRUE;
1192 redraw_later(UPD_VALID);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001193 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001194 curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
1195 redraw_titles();
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001196
1197 return NULL;
1198}
1199
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001200 int
1201expand_set_buftype(optexpand_T *args, int *numMatches, char_u ***matches)
1202{
1203 return expand_set_opt_string(
1204 args,
1205 p_buftype_values,
1206 sizeof(p_buftype_values) / sizeof(p_buftype_values[0]) - 1,
1207 numMatches,
1208 matches);
1209}
1210
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001211/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001212 * The 'casemap' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001213 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001214 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001215did_set_casemap(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001216{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001217 return did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
1218}
1219
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001220 int
1221expand_set_casemap(optexpand_T *args, int *numMatches, char_u ***matches)
1222{
1223 return expand_set_opt_string(
1224 args,
1225 p_cmp_values,
1226 sizeof(p_cmp_values) / sizeof(p_cmp_values[0]) - 1,
1227 numMatches,
1228 matches);
1229}
1230
1231#if defined(FEAT_CLIPBOARD) || defined(PROTO)
1232 int
1233expand_set_clipboard(optexpand_T *args, int *numMatches, char_u ***matches)
1234{
1235 return expand_set_opt_string(
1236 args,
1237 p_cb_values,
1238 sizeof(p_cb_values) / sizeof(p_cb_values[0]) - 1,
1239 numMatches,
1240 matches);
1241}
1242#endif
1243
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001244/*
Yegappan Lakshmananc6ff21e2023-03-02 14:46:48 +00001245 * The global 'listchars' or 'fillchars' option is changed.
1246 */
1247 static char *
1248did_set_global_listfillchars(char_u *val, int opt_lcs, int opt_flags)
1249{
1250 char *errmsg = NULL;
1251 char_u **local_ptr = opt_lcs ? &curwin->w_p_lcs : &curwin->w_p_fcs;
1252
1253 // only apply the global value to "curwin" when it does not have a
1254 // local value
1255 if (opt_lcs)
1256 errmsg = set_listchars_option(curwin, val,
1257 **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
1258 else
1259 errmsg = set_fillchars_option(curwin, val,
1260 **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
1261 if (errmsg != NULL)
1262 return errmsg;
1263
1264 tabpage_T *tp;
1265 win_T *wp;
1266
1267 // If the current window is set to use the global
1268 // 'listchars'/'fillchars' value, clear the window-local value.
1269 if (!(opt_flags & OPT_GLOBAL))
1270 clear_string_option(local_ptr);
1271 FOR_ALL_TAB_WINDOWS(tp, wp)
1272 {
1273 // If the current window has a local value need to apply it
1274 // again, it was changed when setting the global value.
1275 // If no error was returned above, we don't expect an error
1276 // here, so ignore the return value.
1277 if (opt_lcs)
1278 {
1279 if (*wp->w_p_lcs == NUL)
1280 (void)set_listchars_option(wp, wp->w_p_lcs, TRUE);
1281 }
1282 else
1283 {
1284 if (*wp->w_p_fcs == NUL)
1285 (void)set_fillchars_option(wp, wp->w_p_fcs, TRUE);
1286 }
1287 }
1288
1289 redraw_all_later(UPD_NOT_VALID);
1290
1291 return NULL;
1292}
1293
1294/*
1295 * The 'fillchars' option or the 'listchars' option is changed.
1296 */
1297 char *
1298did_set_chars_option(optset_T *args)
1299{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001300 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananc6ff21e2023-03-02 14:46:48 +00001301 char *errmsg = NULL;
1302
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001303 if ( varp == &p_lcs // global 'listchars'
1304 || varp == &p_fcs) // global 'fillchars'
1305 errmsg = did_set_global_listfillchars(*varp, varp == &p_lcs,
1306 args->os_flags);
1307 else if (varp == &curwin->w_p_lcs) // local 'listchars'
1308 errmsg = set_listchars_option(curwin, *varp, TRUE);
1309 else if (varp == &curwin->w_p_fcs) // local 'fillchars'
1310 errmsg = set_fillchars_option(curwin, *varp, TRUE);
Yegappan Lakshmananc6ff21e2023-03-02 14:46:48 +00001311
1312 return errmsg;
1313}
1314
1315/*
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001316 * Expand 'fillchars' or 'listchars' option value.
1317 */
1318 int
1319expand_set_chars_option(optexpand_T *args, int *numMatches, char_u ***matches)
1320{
1321 char_u **varp = (char_u **)args->oe_varp;
1322 int is_lcs = (varp == &p_lcs || varp == &curwin->w_p_lcs);
1323 return expand_set_opt_generic(
1324 args,
1325 is_lcs ? get_listchars_name : get_fillchars_name,
1326 numMatches,
1327 matches);
1328}
1329
1330/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001331 * The 'cinoptions' option is changed.
1332 */
1333 char *
1334did_set_cinoptions(optset_T *args UNUSED)
1335{
1336 // TODO: recognize errors
1337 parse_cino(curbuf);
1338
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001339 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001340}
1341
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00001342#if defined(FEAT_SYN_HL) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001343/*
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001344 * The 'colorcolumn' option is changed.
1345 */
1346 char *
1347did_set_colorcolumn(optset_T *args UNUSED)
1348{
1349 return check_colorcolumn(curwin);
1350}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001351#endif
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001352
1353/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001354 * The 'comments' option is changed.
1355 */
1356 char *
1357did_set_comments(optset_T *args)
1358{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001359 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001360 char_u *s;
1361 char *errmsg = NULL;
1362
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001363 for (s = *varp; *s; )
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001364 {
1365 while (*s && *s != ':')
1366 {
1367 if (vim_strchr((char_u *)COM_ALL, *s) == NULL
1368 && !VIM_ISDIGIT(*s) && *s != '-')
1369 {
1370 errmsg = illegal_char(args->os_errbuf, *s);
1371 break;
1372 }
1373 ++s;
1374 }
1375 if (*s++ == NUL)
1376 errmsg = e_missing_colon;
1377 else if (*s == ',' || *s == NUL)
1378 errmsg = e_zero_length_string;
1379 if (errmsg != NULL)
1380 break;
1381 while (*s && *s != ',')
1382 {
1383 if (*s == '\\' && s[1] != NUL)
1384 ++s;
1385 ++s;
1386 }
1387 s = skip_to_option_part(s);
1388 }
1389
1390 return errmsg;
1391}
1392
1393#if defined(FEAT_FOLDING) || defined(PROTO)
1394/*
1395 * The 'commentstring' option is changed.
1396 */
1397 char *
1398did_set_commentstring(optset_T *args)
1399{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001400 char_u **varp = (char_u **)args->os_varp;
1401
1402 if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001403 return e_commentstring_must_be_empty_or_contain_str;
1404
1405 return NULL;
1406}
1407#endif
1408
1409/*
1410 * The 'complete' option is changed.
1411 */
1412 char *
1413did_set_complete(optset_T *args)
1414{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001415 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001416 char_u *s;
1417
1418 // check if it is a valid value for 'complete' -- Acevedo
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001419 for (s = *varp; *s;)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001420 {
1421 while (*s == ',' || *s == ' ')
1422 s++;
1423 if (!*s)
1424 break;
1425 if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
1426 return illegal_char(args->os_errbuf, *s);
1427 if (*++s != NUL && *s != ',' && *s != ' ')
1428 {
1429 if (s[-1] == 'k' || s[-1] == 's')
1430 {
1431 // skip optional filename after 'k' and 's'
1432 while (*s && *s != ',' && *s != ' ')
1433 {
1434 if (*s == '\\' && s[1] != NUL)
1435 ++s;
1436 ++s;
1437 }
1438 }
1439 else
1440 {
1441 if (args->os_errbuf != NULL)
1442 {
1443 sprintf((char *)args->os_errbuf,
1444 _(e_illegal_character_after_chr), *--s);
1445 return args->os_errbuf;
1446 }
1447 return "";
1448 }
1449 }
1450 }
1451
1452 return NULL;
1453}
1454
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001455 int
1456expand_set_complete(optexpand_T *args, int *numMatches, char_u ***matches)
1457{
1458 static char *(p_cpt_values[]) = {
1459 ".", "w", "b", "u", "k", "kspell", "s", "i", "d", "]", "t", "U",
1460 NULL};
1461 return expand_set_opt_string(
1462 args,
1463 p_cpt_values,
1464 sizeof(p_cpt_values) / sizeof(p_cpt_values[0]) - 1,
1465 numMatches,
1466 matches);
1467}
1468
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001469/*
1470 * The 'completeopt' option is changed.
1471 */
1472 char *
1473did_set_completeopt(optset_T *args UNUSED)
1474{
1475 if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
1476 return e_invalid_argument;
1477
1478 completeopt_was_set();
1479 return NULL;
1480}
1481
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001482 int
1483expand_set_completeopt(optexpand_T *args, int *numMatches, char_u ***matches)
1484{
1485 return expand_set_opt_string(
1486 args,
1487 p_cot_values,
1488 sizeof(p_cot_values) / sizeof(p_cot_values[0]) - 1,
1489 numMatches,
1490 matches);
1491}
1492
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001493#if (defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX)) || defined(PROTO)
1494/*
1495 * The 'completepopup' option is changed.
1496 */
1497 char *
1498did_set_completepopup(optset_T *args UNUSED)
1499{
1500 if (parse_completepopup(NULL) == FAIL)
1501 return e_invalid_argument;
1502
1503 popup_close_info();
1504 return NULL;
1505}
1506#endif
1507
1508#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
1509/*
1510 * The 'completeslash' option is changed.
1511 */
1512 char *
1513did_set_completeslash(optset_T *args UNUSED)
1514{
1515 if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK
1516 || check_opt_strings(curbuf->b_p_csl, p_csl_values, FALSE) != OK)
1517 return e_invalid_argument;
1518
1519 return NULL;
1520}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001521
1522 int
1523expand_set_completeslash(optexpand_T *args, int *numMatches, char_u ***matches)
1524{
1525 return expand_set_opt_string(
1526 args,
1527 p_csl_values,
1528 sizeof(p_csl_values) / sizeof(p_csl_values[0]) - 1,
1529 numMatches,
1530 matches);
1531}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001532#endif
1533
1534#if defined(FEAT_CONCEAL) || defined(PROTO)
1535/*
1536 * The 'concealcursor' option is changed.
1537 */
1538 char *
1539did_set_concealcursor(optset_T *args)
1540{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001541 char_u **varp = (char_u **)args->os_varp;
1542
1543 return did_set_option_listflag(*varp, (char_u *)COCU_ALL, args->os_errbuf);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001544}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001545
1546 int
1547expand_set_concealcursor(optexpand_T *args, int *numMatches, char_u ***matches)
1548{
1549 return expand_set_opt_listflag(args, (char_u*)COCU_ALL, numMatches, matches);
1550}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001551#endif
1552
1553/*
1554 * The 'cpoptions' option is changed.
1555 */
1556 char *
1557did_set_cpoptions(optset_T *args)
1558{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001559 char_u **varp = (char_u **)args->os_varp;
1560
1561 return did_set_option_listflag(*varp, (char_u *)CPO_ALL, args->os_errbuf);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001562}
1563
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001564 int
1565expand_set_cpoptions(optexpand_T *args, int *numMatches, char_u ***matches)
1566{
1567 return expand_set_opt_listflag(args, (char_u*)CPO_ALL, numMatches, matches);
1568}
1569
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001570#if defined(FEAT_CRYPT) || defined(PROTO)
1571/*
1572 * The 'cryptkey' option is changed.
1573 */
1574 char *
1575did_set_cryptkey(optset_T *args)
1576{
1577 // Make sure the ":set" command doesn't show the new value in the
1578 // history.
1579 remove_key_from_history();
1580
Yee Cheng Chin6ee7b522023-10-01 09:13:22 +02001581 if (args->os_op != OP_NONE)
1582 // Don't allow set+=/-=/^= as they can allow for substring guessing
1583 return e_invalid_argument;
1584
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001585 if (STRCMP(curbuf->b_p_key, args->os_oldval.string) != 0)
1586 {
1587 // Need to update the swapfile.
1588 ml_set_crypt_key(curbuf, args->os_oldval.string,
1589 *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
1590 changed_internal();
1591 }
Christian Brabandt19e6c4f2023-06-27 18:57:10 +01001592# ifdef FEAT_SODIUM
1593 if (crypt_method_is_sodium(crypt_get_method_nr(curbuf)))
1594 crypt_sodium_lock_key(args->os_newval.string);
1595# endif
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001596
1597 return NULL;
1598}
1599
1600/*
1601 * The 'cryptmethod' option is changed.
1602 */
1603 char *
1604did_set_cryptmethod(optset_T *args)
1605{
1606 char_u *p;
1607 char_u *s;
1608
1609 if (args->os_flags & OPT_LOCAL)
1610 p = curbuf->b_p_cm;
1611 else
1612 p = p_cm;
1613 if (check_opt_strings(p, p_cm_values, TRUE) != OK)
1614 return e_invalid_argument;
1615 else if (crypt_self_test() == FAIL)
1616 return e_invalid_argument;
1617
1618 // When setting the global value to empty, make it "zip".
1619 if (*p_cm == NUL)
1620 {
1621 free_string_option(p_cm);
1622 p_cm = vim_strsave((char_u *)"zip");
1623 }
1624 // When using ":set cm=name" the local value is going to be empty.
1625 // Do that here, otherwise the crypt functions will still use the
1626 // local value.
1627 if ((args->os_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1628 {
1629 free_string_option(curbuf->b_p_cm);
1630 curbuf->b_p_cm = empty_option;
1631 }
1632
1633 // Need to update the swapfile when the effective method changed.
1634 // Set "s" to the effective old value, "p" to the effective new
1635 // method and compare.
1636 if ((args->os_flags & OPT_LOCAL) && *args->os_oldval.string == NUL)
1637 s = p_cm; // was previously using the global value
1638 else
1639 s = args->os_oldval.string;
1640 if (*curbuf->b_p_cm == NUL)
1641 p = p_cm; // is now using the global value
1642 else
1643 p = curbuf->b_p_cm;
1644 if (STRCMP(s, p) != 0)
1645 ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
1646
1647 // If the global value changes need to update the swapfile for all
1648 // buffers using that value.
1649 if ((args->os_flags & OPT_GLOBAL)
1650 && STRCMP(p_cm, args->os_oldval.string) != 0)
1651 {
1652 buf_T *buf;
1653
1654 FOR_ALL_BUFFERS(buf)
1655 if (buf != curbuf && *buf->b_p_cm == NUL)
1656 ml_set_crypt_key(buf, buf->b_p_key, args->os_oldval.string);
1657 }
1658 return NULL;
1659}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001660
1661 int
1662expand_set_cryptmethod(optexpand_T *args, int *numMatches, char_u ***matches)
1663{
1664 return expand_set_opt_string(
1665 args,
1666 p_cm_values,
1667 sizeof(p_cm_values) / sizeof(p_cm_values[0]) - 1,
1668 numMatches,
1669 matches);
1670}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001671#endif
1672
1673#if (defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)) || defined(PROTO)
1674/*
1675 * The 'cscopequickfix' option is changed.
1676 */
1677 char *
1678did_set_cscopequickfix(optset_T *args UNUSED)
1679{
1680 char_u *p;
1681
1682 if (p_csqf == NULL)
1683 return NULL;
1684
1685 p = p_csqf;
1686 while (*p != NUL)
1687 {
1688 if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
1689 || p[1] == NUL
1690 || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
1691 || (p[2] != NUL && p[2] != ','))
1692 return e_invalid_argument;
1693 else if (p[2] == NUL)
1694 break;
1695 else
1696 p += 3;
1697 }
1698
1699 return NULL;
1700}
1701#endif
1702
1703#if defined(FEAT_SYN_HL) || defined(PROTO)
1704/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001705 * The 'cursorlineopt' option is changed.
1706 */
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001707 char *
1708did_set_cursorlineopt(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001709{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001710 char_u **varp = (char_u **)args->os_varp;
1711
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001712 // This could be changed to use opt_strings_flags() instead.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001713 if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001714 return e_invalid_argument;
1715
1716 return NULL;
1717}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001718
1719 int
1720expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char_u ***matches)
1721{
1722 return expand_set_opt_string(
1723 args,
1724 p_culopt_values,
1725 sizeof(p_culopt_values) / sizeof(p_culopt_values[0]) - 1,
1726 numMatches,
1727 matches);
1728}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001729#endif
1730
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001731/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001732 * The 'debug' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001733 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001734 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001735did_set_debug(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001736{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001737 return did_set_opt_strings(p_debug, p_debug_values, TRUE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001738}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001739
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001740 int
1741expand_set_debug(optexpand_T *args, int *numMatches, char_u ***matches)
1742{
1743 return expand_set_opt_string(
1744 args,
1745 p_debug_values,
1746 sizeof(p_debug_values) / sizeof(p_debug_values[0]) - 1,
1747 numMatches,
1748 matches);
1749}
1750
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001751#if defined(FEAT_DIFF) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001752/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001753 * The 'diffopt' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001754 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001755 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001756did_set_diffopt(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001757{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001758 if (diffopt_changed() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001759 return e_invalid_argument;
1760
1761 return NULL;
1762}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001763
1764 int
1765expand_set_diffopt(optexpand_T *args, int *numMatches, char_u ***matches)
1766{
1767 expand_T *xp = args->oe_xp;
1768
1769 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
1770 {
1771 // Within "algorithm:", we have a subgroup of possible options.
1772 int algo_len = STRLEN("algorithm:");
1773 if (xp->xp_pattern - args->oe_set_arg >= algo_len &&
1774 STRNCMP(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0)
1775 {
1776 return expand_set_opt_string(
1777 args,
1778 p_dip_algorithm_values,
1779 sizeof(p_dip_algorithm_values) / sizeof(p_dip_algorithm_values[0]) - 1,
1780 numMatches,
1781 matches);
1782 }
1783 return FAIL;
1784 }
1785
1786 return expand_set_opt_string(
1787 args,
1788 p_dip_values,
1789 sizeof(p_dip_values) / sizeof(p_dip_values[0]) - 1,
1790 numMatches,
1791 matches);
1792}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001793#endif
1794
1795/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001796 * The 'display' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001797 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001798 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001799did_set_display(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001800{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001801 if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001802 return e_invalid_argument;
1803
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001804 (void)init_chartab();
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001805 return NULL;
1806}
1807
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001808 int
1809expand_set_display(optexpand_T *args, int *numMatches, char_u ***matches)
1810{
1811 return expand_set_opt_string(
1812 args,
1813 p_dy_values,
1814 sizeof(p_dy_values) / sizeof(p_dy_values[0]) - 1,
1815 numMatches,
1816 matches);
1817}
1818
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001819/*
1820 * The 'eadirection' option is changed.
1821 */
1822 char *
1823did_set_eadirection(optset_T *args UNUSED)
1824{
1825 return did_set_opt_strings(p_ead, p_ead_values, FALSE);
1826}
1827
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001828 int
1829expand_set_eadirection(optexpand_T *args, int *numMatches, char_u ***matches)
1830{
1831 return expand_set_opt_string(
1832 args,
1833 p_ead_values,
1834 sizeof(p_ead_values) / sizeof(p_ead_values[0]) - 1,
1835 numMatches,
1836 matches);
1837}
1838
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001839/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001840 * One of the 'encoding', 'fileencoding', 'termencoding' or 'makeencoding'
1841 * options is changed.
1842 */
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001843 char *
1844did_set_encoding(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001845{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001846 char_u **varp = (char_u **)args->os_varp;
1847 char_u **gvarp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001848 char *errmsg = NULL;
1849 char_u *p;
1850
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001851 // Get the global option to compare with, otherwise we would have to check
1852 // two values for all local options.
1853 gvarp = (char_u **)get_option_varp_scope(args->os_idx, OPT_GLOBAL);
1854
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001855 if (gvarp == &p_fenc)
1856 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001857 if (!curbuf->b_p_ma && args->os_flags != OPT_GLOBAL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001858 errmsg = e_cannot_make_changes_modifiable_is_off;
1859 else if (vim_strchr(*varp, ',') != NULL)
1860 // No comma allowed in 'fileencoding'; catches confusing it
1861 // with 'fileencodings'.
1862 errmsg = e_invalid_argument;
1863 else
1864 {
1865 // May show a "+" in the title now.
1866 redraw_titles();
1867 // Add 'fileencoding' to the swap file.
1868 ml_setflags(curbuf);
1869 }
1870 }
1871 if (errmsg == NULL)
1872 {
1873 // canonize the value, so that STRCMP() can be used on it
1874 p = enc_canonize(*varp);
1875 if (p != NULL)
1876 {
1877 vim_free(*varp);
1878 *varp = p;
1879 }
1880 if (varp == &p_enc)
1881 {
1882 errmsg = mb_init();
1883 redraw_titles();
1884 }
1885 }
1886
1887#if defined(FEAT_GUI_GTK)
1888 if (errmsg == NULL && varp == &p_tenc && gui.in_use)
1889 {
1890 // GTK uses only a single encoding, and that is UTF-8.
1891 if (STRCMP(p_tenc, "utf-8") != 0)
1892 errmsg = e_cannot_be_changed_in_gtk_GUI;
1893 }
1894#endif
1895
1896 if (errmsg == NULL)
1897 {
1898#ifdef FEAT_KEYMAP
1899 // When 'keymap' is used and 'encoding' changes, reload the keymap
1900 // (with another encoding).
1901 if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
1902 (void)keymap_init();
1903#endif
1904
1905 // When 'termencoding' is not empty and 'encoding' changes or when
1906 // 'termencoding' changes, need to setup for keyboard input and
1907 // display output conversion.
1908 if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
1909 {
1910 if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL
1911 || convert_setup(&output_conv, p_enc, p_tenc) == FAIL)
1912 {
1913 semsg(_(e_cannot_convert_between_str_and_str),
1914 p_tenc, p_enc);
1915 errmsg = e_invalid_argument;
1916 }
1917 }
1918
1919#if defined(MSWIN)
K.Takatace3189d2023-02-15 19:13:43 +00001920 // $HOME, $VIM and $VIMRUNTIME may have characters in active code page.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001921 if (varp == &p_enc)
K.Takatace3189d2023-02-15 19:13:43 +00001922 {
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001923 init_homedir();
K.Takatace3189d2023-02-15 19:13:43 +00001924 init_vimdir();
1925 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001926#endif
1927 }
1928
1929 return errmsg;
1930}
1931
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001932 int
1933expand_set_encoding(optexpand_T *args, int *numMatches, char_u ***matches)
1934{
1935 return expand_set_opt_generic(
1936 args,
1937 get_encoding_name,
1938 numMatches,
1939 matches);
1940}
1941
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001942/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001943 * The 'eventignore' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001944 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001945 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001946did_set_eventignore(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001947{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001948 if (check_ei() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001949 return e_invalid_argument;
1950 return NULL;
1951}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001952
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001953 static char_u *
1954get_eventignore_name(expand_T *xp, int idx)
1955{
1956 // 'eventignore' allows special keyword "all" in addition to
1957 // all event names.
1958 if (idx == 0)
1959 return (char_u *)"all";
1960 return get_event_name_no_group(xp, idx - 1);
1961}
1962
1963 int
1964expand_set_eventignore(optexpand_T *args, int *numMatches, char_u ***matches)
1965{
1966 return expand_set_opt_generic(
1967 args,
1968 get_eventignore_name,
1969 numMatches,
1970 matches);
1971}
1972
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001973/*
1974 * The 'fileformat' option is changed.
1975 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001976 char *
1977did_set_fileformat(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001978{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001979 char_u **varp = (char_u **)args->os_varp;
1980
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001981 if (!curbuf->b_p_ma && !(args->os_flags & OPT_GLOBAL))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001982 return e_cannot_make_changes_modifiable_is_off;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001983 else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001984 return e_invalid_argument;
1985
1986 // may also change 'textmode'
1987 if (get_fileformat(curbuf) == EOL_DOS)
1988 curbuf->b_p_tx = TRUE;
1989 else
1990 curbuf->b_p_tx = FALSE;
1991 redraw_titles();
1992 // update flag in swap file
1993 ml_setflags(curbuf);
1994 // Redraw needed when switching to/from "mac": a CR in the text
1995 // will be displayed differently.
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001996 if (get_fileformat(curbuf) == EOL_MAC || *args->os_oldval.string == 'm')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001997 redraw_curbuf_later(UPD_NOT_VALID);
1998
1999 return NULL;
2000}
2001
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002002 int
2003expand_set_fileformat(optexpand_T *args, int *numMatches, char_u ***matches)
2004{
2005 return expand_set_opt_string(
2006 args,
2007 p_ff_values,
2008 sizeof(p_ff_values) / sizeof(p_ff_values[0]) - 1,
2009 numMatches,
2010 matches);
2011}
2012
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002013/*
2014 * The 'fileformats' option is changed.
2015 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002016 char *
2017did_set_fileformats(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002018{
2019 if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
2020 return e_invalid_argument;
2021
2022 // also change 'textauto'
2023 if (*p_ffs == NUL)
2024 p_ta = FALSE;
2025 else
2026 p_ta = TRUE;
2027
2028 return NULL;
2029}
2030
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002031/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002032 * The 'filetype' or the 'syntax' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002033 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002034 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002035did_set_filetype_or_syntax(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002036{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002037 char_u **varp = (char_u **)args->os_varp;
2038
2039 if (!valid_filetype(*varp))
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002040 return e_invalid_argument;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002041
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002042 args->os_value_changed = STRCMP(args->os_oldval.string, *varp) != 0;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002043
2044 // Since we check the value, there is no need to set P_INSECURE,
2045 // even when the value comes from a modeline.
2046 args->os_value_checked = TRUE;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002047
2048 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002049}
2050
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002051#if defined(FEAT_FOLDING) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002052/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002053 * The 'foldclose' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002054 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002055 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002056did_set_foldclose(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002057{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002058 return did_set_opt_strings(p_fcl, p_fcl_values, TRUE);
2059}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002060
2061 int
2062expand_set_foldclose(optexpand_T *args, int *numMatches, char_u ***matches)
2063{
2064 return expand_set_opt_string(
2065 args,
2066 p_fcl_values,
2067 sizeof(p_fcl_values) / sizeof(p_fcl_values[0]) - 1,
2068 numMatches,
2069 matches);
2070}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002071#endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002072
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002073#if (defined(FEAT_EVAL) && defined(FEAT_FOLDING)) || defined(PROTO)
2074/*
2075 * The 'foldexpr' option is changed.
2076 */
2077 char *
2078did_set_foldexpr(optset_T *args)
2079{
2080 (void)did_set_optexpr(args);
2081 if (foldmethodIsExpr(curwin))
2082 foldUpdateAll(curwin);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002083 return NULL;
2084}
2085#endif
2086
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002087#if defined(FEAT_FOLDING) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002088/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002089 * The 'foldignore' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002090 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002091 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002092did_set_foldignore(optset_T *args UNUSED)
2093{
2094 if (foldmethodIsIndent(curwin))
2095 foldUpdateAll(curwin);
2096 return NULL;
2097}
2098
2099/*
2100 * The 'foldmarker' option is changed.
2101 */
2102 char *
2103did_set_foldmarker(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002104{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002105 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002106 char_u *p;
2107
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002108 p = vim_strchr(*varp, ',');
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002109 if (p == NULL)
2110 return e_comma_required;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002111 else if (p == *varp || p[1] == NUL)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002112 return e_invalid_argument;
2113 else if (foldmethodIsMarker(curwin))
2114 foldUpdateAll(curwin);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002115
2116 return NULL;
2117}
2118
2119/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002120 * The 'foldmethod' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002121 */
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002122 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002123did_set_foldmethod(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002124{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002125 char_u **varp = (char_u **)args->os_varp;
2126
2127 if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002128 || *curwin->w_p_fdm == NUL)
2129 return e_invalid_argument;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002130
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002131 foldUpdateAll(curwin);
2132 if (foldmethodIsDiff(curwin))
2133 newFoldLevel();
2134 return NULL;
2135}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002136
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002137 int
2138expand_set_foldmethod(optexpand_T *args, int *numMatches, char_u ***matches)
2139{
2140 return expand_set_opt_string(
2141 args,
2142 p_fdm_values,
2143 sizeof(p_fdm_values) / sizeof(p_fdm_values[0]) - 1,
2144 numMatches,
2145 matches);
2146}
2147
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002148/*
2149 * The 'foldopen' option is changed.
2150 */
2151 char *
2152did_set_foldopen(optset_T *args UNUSED)
2153{
2154 return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
2155}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002156
2157 int
2158expand_set_foldopen(optexpand_T *args, int *numMatches, char_u ***matches)
2159{
2160 return expand_set_opt_string(
2161 args,
2162 p_fdo_values,
2163 sizeof(p_fdo_values) / sizeof(p_fdo_values[0]) - 1,
2164 numMatches,
2165 matches);
2166}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002167#endif
2168
2169/*
2170 * The 'formatoptions' option is changed.
2171 */
2172 char *
2173did_set_formatoptions(optset_T *args)
2174{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002175 char_u **varp = (char_u **)args->os_varp;
2176
2177 return did_set_option_listflag(*varp, (char_u *)FO_ALL, args->os_errbuf);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002178}
2179
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002180 int
2181expand_set_formatoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2182{
2183 return expand_set_opt_listflag(args, (char_u*)FO_ALL, numMatches, matches);
2184}
2185
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002186#if defined(CURSOR_SHAPE) || defined(PROTO)
2187/*
2188 * The 'guicursor' option is changed.
2189 */
2190 char *
2191did_set_guicursor(optset_T *args UNUSED)
2192{
2193 return parse_shape_opt(SHAPE_CURSOR);
2194}
2195#endif
2196
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002197#if defined(FEAT_GUI) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002198/*
2199 * The 'guifont' option is changed.
2200 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002201 char *
2202did_set_guifont(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002203{
2204 char_u *p;
2205 char *errmsg = NULL;
2206
2207 if (gui.in_use)
2208 {
2209 p = p_guifont;
2210# if defined(FEAT_GUI_GTK)
2211 // Put up a font dialog and let the user select a new value.
2212 // If this is cancelled go back to the old value but don't
2213 // give an error message.
2214 if (STRCMP(p, "*") == 0)
2215 {
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002216 p = gui_mch_font_dialog(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002217 free_string_option(p_guifont);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002218 p_guifont = (p != NULL) ? p : vim_strsave(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002219 }
2220# endif
2221 if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
2222 {
2223# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
2224 if (STRCMP(p_guifont, "*") == 0)
2225 {
2226 // Dialog was cancelled: Keep the old value without giving
2227 // an error message.
2228 free_string_option(p_guifont);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002229 p_guifont = vim_strsave(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002230 }
2231 else
2232# endif
2233 errmsg = e_invalid_fonts;
2234 }
2235 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002236
2237 return errmsg;
2238}
2239
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002240# if defined(FEAT_XFONTSET) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002241/*
2242 * The 'guifontset' option is changed.
2243 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002244 char *
2245did_set_guifontset(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002246{
2247 char *errmsg = NULL;
2248
2249 if (STRCMP(p_guifontset, "*") == 0)
2250 errmsg = e_cant_select_fontset;
2251 else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
2252 errmsg = e_invalid_fontset;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002253
2254 return errmsg;
2255}
2256# endif
2257
2258/*
2259 * The 'guifontwide' option is changed.
2260 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002261 char *
2262did_set_guifontwide(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002263{
2264 char *errmsg = NULL;
2265
2266 if (STRCMP(p_guifontwide, "*") == 0)
2267 errmsg = e_cant_select_wide_font;
2268 else if (gui_get_wide_font() == FAIL)
2269 errmsg = e_invalid_wide_font;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002270
2271 return errmsg;
2272}
2273#endif
2274
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002275#if defined(FEAT_GUI_GTK) || defined(PROTO)
2276/*
2277 * The 'guiligatures' option is changed.
2278 */
2279 char *
2280did_set_guiligatures(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002281{
2282 gui_set_ligatures();
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002283 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002284}
2285#endif
2286
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002287#if defined(FEAT_GUI) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002288/*
2289 * The 'guioptions' option is changed.
2290 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002291 char *
2292did_set_guioptions(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002293{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002294 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002295 char *errmsg;
2296
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002297 errmsg = did_set_option_listflag(*varp, (char_u *)GO_ALL, args->os_errbuf);
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002298 if (errmsg != NULL)
2299 return errmsg;
2300
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002301 gui_init_which_components(args->os_oldval.string);
2302 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002303}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002304
2305 int
2306expand_set_guioptions(optexpand_T *args, int *numMatches, char_u ***matches)
2307{
2308 return expand_set_opt_listflag(args, (char_u*)GO_ALL, numMatches, matches);
2309}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002310#endif
2311
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002312#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002313/*
2314 * The 'guitablabel' option is changed.
2315 */
2316 char *
2317did_set_guitablabel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002318{
2319 redraw_tabline = TRUE;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002320 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002321}
2322#endif
2323
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002324/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002325 * The 'helpfile' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002326 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002327 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002328did_set_helpfile(optset_T *args UNUSED)
2329{
2330 // May compute new values for $VIM and $VIMRUNTIME
2331 if (didset_vim)
2332 vim_unsetenv_ext((char_u *)"VIM");
2333 if (didset_vimruntime)
2334 vim_unsetenv_ext((char_u *)"VIMRUNTIME");
2335 return NULL;
2336}
2337
2338#if defined(FEAT_MULTI_LANG) || defined(PROTO)
2339/*
2340 * The 'helplang' option is changed.
2341 */
2342 char *
2343did_set_helplang(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002344{
2345 char *errmsg = NULL;
2346
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002347 // Check for "", "ab", "ab,cd", etc.
2348 for (char_u *s = p_hlg; *s != NUL; s += 3)
2349 {
2350 if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
2351 {
2352 errmsg = e_invalid_argument;
2353 break;
2354 }
2355 if (s[2] == NUL)
2356 break;
2357 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002358
2359 return errmsg;
2360}
2361#endif
2362
2363/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002364 * The 'highlight' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002365 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002366 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002367did_set_highlight(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002368{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002369 if (highlight_changed() == FAIL)
2370 return e_invalid_argument; // invalid flags
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002371
2372 return NULL;
2373}
2374
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002375/*
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002376 * Expand 'highlight' option.
2377 */
2378 int
2379expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches)
2380{
2381 char_u *p;
2382 expand_T *xp = args->oe_xp;
2383 static char_u hl_flags[HLF_COUNT] = HL_FLAGS;
2384 int i;
2385 int count = 0;
2386
2387 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2388 {
2389 // Right after a ':', meaning we just return all highlight names.
2390 return expand_set_opt_generic(
2391 args,
2392 get_highlight_name,
2393 numMatches,
2394 matches);
2395 }
2396
2397 if (*xp->xp_pattern == NUL)
2398 {
2399 // At beginning of a comma-separated list. Return the specific list of
2400 // supported occasions.
2401 *matches = ALLOC_MULT(char_u *, HLF_COUNT + 1);
2402 if (*matches == NULL)
2403 return FAIL;
2404
2405 // We still want to return the full option if it's requested.
2406 if (args->oe_include_orig_val)
2407 {
2408 p = vim_strsave(args->oe_opt_value);
2409 if (p == NULL)
2410 {
2411 VIM_CLEAR(*matches);
2412 return FAIL;
2413 }
2414 (*matches)[count++] = p;
2415 }
2416
2417 for (i = 0; i < HLF_COUNT; i++)
2418 {
2419 p = vim_strnsave(&hl_flags[i], 1);
2420 if (p == NULL)
2421 {
2422 if (count == 0)
2423 {
2424 VIM_CLEAR(*matches);
2425 return FAIL;
2426 }
2427 else
2428 break;
2429 }
2430 (*matches)[count++] = p;
2431 }
2432
2433 if (count == 0)
2434 {
2435 VIM_CLEAR(*matches);
2436 return FAIL;
2437 }
2438 *numMatches = count;
2439 return OK;
2440 }
2441
2442 // We are after the initial character (which indicates the occasion). We
2443 // already made sure we are not matching after a ':' above, so now we want
2444 // to match against display mode modifiers.
2445 // Since the xp_pattern starts from the beginning, we need to include it in
2446 // the returned match.
2447
2448 // Note: Keep this in sync with highlight_changed()
2449 static char p_hl_mode_values[] =
2450 {':', 'b', 'i', '-', 'n', 'r', 's', 'u', 'c', '2', 'd', '=', 't'};
2451 int num_hl_modes = sizeof(p_hl_mode_values) / sizeof(p_hl_mode_values[0]);
2452
2453 *matches = ALLOC_MULT(char_u *, num_hl_modes);
2454 if (*matches == NULL)
2455 return FAIL;
2456
2457 int pattern_len = STRLEN(xp->xp_pattern);
2458
2459 for (i = 0; i < num_hl_modes; i++)
2460 {
2461 // Don't allow duplicates as these are unique flags
2462 if (vim_strchr(xp->xp_pattern + 1, p_hl_mode_values[i]) != NULL)
2463 continue;
2464
2465 // ':' only works by itself, not with other flags.
2466 if (pattern_len > 1 && p_hl_mode_values[i] == ':')
2467 continue;
2468
2469 p = vim_strnsave(xp->xp_pattern, pattern_len + 1);
2470 if (p == NULL)
2471 {
2472 if (i == 0)
2473 {
2474 VIM_CLEAR(*matches);
2475 return FAIL;
2476 }
2477 else
2478 break;
2479 }
2480 p[pattern_len] = p_hl_mode_values[i];
2481 p[pattern_len + 1] = NUL;
2482 (*matches)[count++] = p;
2483 }
2484 if (count == 0)
2485 {
2486 VIM_CLEAR(*matches);
2487 return FAIL;
2488 }
2489 *numMatches = count;
2490
2491 return OK;
2492}
2493
2494/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002495 * The 'titlestring' or the 'iconstring' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002496 */
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002497 static char *
2498parse_titleiconstring(optset_T *args UNUSED, int flagval UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002499{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002500#ifdef FEAT_STL_OPT
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002501 char_u **varp = (char_u **)args->os_varp;
2502
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002503 // NULL => statusline syntax
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002504 if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002505 stl_syntax |= flagval;
2506 else
2507 stl_syntax &= ~flagval;
2508#endif
2509 did_set_title();
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002510
2511 return NULL;
2512}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002513
2514/*
2515 * The 'iconstring' option is changed.
2516 */
2517 char *
2518did_set_iconstring(optset_T *args)
2519{
2520 int flagval = 0;
2521
2522#ifdef FEAT_STL_OPT
2523 flagval = STL_IN_ICON;
2524#endif
2525
2526 return parse_titleiconstring(args, flagval);
2527}
2528
2529#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) || defined(PROTO)
2530/*
2531 * The 'imactivatekey' option is changed.
2532 */
2533 char *
2534did_set_imactivatekey(optset_T *args UNUSED)
2535{
2536 if (!im_xim_isvalid_imactivate())
2537 return e_invalid_argument;
2538 return NULL;
2539}
2540#endif
2541
2542/*
2543 * The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is
2544 * changed.
2545 */
2546 char *
2547did_set_isopt(optset_T *args)
2548{
2549 // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
2550 // If the new option is invalid, use old value.
2551 // 'lisp' option: refill g_chartab[] for '-' char.
2552 if (init_chartab() == FAIL)
2553 {
2554 args->os_restore_chartab = TRUE;// need to restore the chartab.
2555 return e_invalid_argument; // error in value
2556 }
2557
2558 return NULL;
2559}
2560
Yegappan Lakshmanan87018252023-09-20 20:20:04 +02002561/*
2562 * The 'jumpoptions' option is changed.
2563 */
2564 char *
Yegappan Lakshmanan1926ae42023-09-21 16:36:28 +02002565did_set_jumpoptions(optset_T *args UNUSED)
Yegappan Lakshmanan87018252023-09-20 20:20:04 +02002566{
2567 if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, TRUE) != OK)
2568 return e_invalid_argument;
2569
2570 return NULL;
2571}
2572
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002573 int
2574expand_set_jumpoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2575{
2576 return expand_set_opt_string(
2577 args,
2578 p_jop_values,
2579 sizeof(p_jop_values) / sizeof(p_jop_values[0]) - 1,
2580 numMatches,
2581 matches);
2582}
2583
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002584#if defined(FEAT_KEYMAP) || defined(PROTO)
2585/*
2586 * The 'keymap' option is changed.
2587 */
2588 char *
2589did_set_keymap(optset_T *args)
2590{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002591 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002592 char *errmsg = NULL;
2593
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002594 if (!valid_filetype(*varp))
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002595 errmsg = e_invalid_argument;
2596 else
2597 {
2598 int secure_save = secure;
2599
2600 // Reset the secure flag, since the value of 'keymap' has
2601 // been checked to be safe.
2602 secure = 0;
2603
2604 // load or unload key mapping tables
2605 errmsg = keymap_init();
2606
2607 secure = secure_save;
2608
2609 // Since we check the value, there is no need to set P_INSECURE,
2610 // even when the value comes from a modeline.
2611 args->os_value_checked = TRUE;
2612 }
2613
2614 if (errmsg == NULL)
2615 {
2616 if (*curbuf->b_p_keymap != NUL)
2617 {
2618 // Installed a new keymap, switch on using it.
2619 curbuf->b_p_iminsert = B_IMODE_LMAP;
2620 if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
2621 curbuf->b_p_imsearch = B_IMODE_LMAP;
2622 }
2623 else
2624 {
2625 // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
2626 if (curbuf->b_p_iminsert == B_IMODE_LMAP)
2627 curbuf->b_p_iminsert = B_IMODE_NONE;
2628 if (curbuf->b_p_imsearch == B_IMODE_LMAP)
2629 curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
2630 }
2631 if ((args->os_flags & OPT_LOCAL) == 0)
2632 {
2633 set_iminsert_global();
2634 set_imsearch_global();
2635 }
2636 status_redraw_curbuf();
2637 }
2638
2639 return errmsg;
2640}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002641#endif
2642
2643/*
2644 * The 'keymodel' option is changed.
2645 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002646 char *
2647did_set_keymodel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002648{
2649 if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
2650 return e_invalid_argument;
2651
2652 km_stopsel = (vim_strchr(p_km, 'o') != NULL);
2653 km_startsel = (vim_strchr(p_km, 'a') != NULL);
2654 return NULL;
2655}
2656
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002657 int
2658expand_set_keymodel(optexpand_T *args, int *numMatches, char_u ***matches)
2659{
2660 return expand_set_opt_string(
2661 args,
2662 p_km_values,
2663 sizeof(p_km_values) / sizeof(p_km_values[0]) - 1,
2664 numMatches,
2665 matches);
2666}
2667
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002668/*
2669 * The 'keyprotocol' option is changed.
2670 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002671 char *
2672did_set_keyprotocol(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002673{
Gregory Anders3695d0e2023-09-29 20:17:20 +02002674 char_u *term = T_NAME;
2675 keyprot_T kpc = match_keyprotocol(term);
2676 if (kpc == KEYPROTOCOL_FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002677 return e_invalid_argument;
2678
Gregory Anders3695d0e2023-09-29 20:17:20 +02002679 apply_keyprotocol(term, kpc);
2680
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002681 return NULL;
2682}
2683
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002684 int
2685expand_set_keyprotocol(optexpand_T *args, int *numMatches, char_u ***matches)
2686{
2687 expand_T *xp = args->oe_xp;
2688 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2689 {
2690 // 'keyprotocol' only has well-defined terms for completion for the
2691 // protocol part after the colon.
2692 return expand_set_opt_string(
2693 args,
2694 p_kpc_protocol_values,
2695 sizeof(p_kpc_protocol_values) / sizeof(p_kpc_protocol_values[0]) - 1,
2696 numMatches,
2697 matches);
2698 }
2699 // Use expand_set_opt_string instead of returning FAIL so that we can
2700 // include the original value if args->oe_include_orig_val is set.
2701 static char *(empty[]) = {NULL};
2702 return expand_set_opt_string(args, empty, 0, numMatches, matches);
2703}
2704
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002705/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002706 * The 'lispoptions' option is changed.
2707 */
2708 char *
2709did_set_lispoptions(optset_T *args)
2710{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002711 char_u **varp = (char_u **)args->os_varp;
2712
2713 if (**varp != NUL
2714 && STRCMP(*varp, "expr:0") != 0
2715 && STRCMP(*varp, "expr:1") != 0)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002716 return e_invalid_argument;
2717
2718 return NULL;
2719}
2720
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002721 int
2722expand_set_lispoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2723{
2724 static char *(p_lop_values[]) = {"expr:0", "expr:1", NULL};
2725 return expand_set_opt_string(
2726 args,
2727 p_lop_values,
2728 sizeof(p_lop_values) / sizeof(p_lop_values[0]) - 1,
2729 numMatches,
2730 matches);
2731}
2732
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002733/*
2734 * The 'matchpairs' option is changed.
2735 */
2736 char *
2737did_set_matchpairs(optset_T *args)
2738{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002739 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002740 char_u *p;
2741
2742 if (has_mbyte)
2743 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002744 for (p = *varp; *p != NUL; ++p)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002745 {
2746 int x2 = -1;
2747 int x3 = -1;
2748
2749 p += mb_ptr2len(p);
2750 if (*p != NUL)
2751 x2 = *p++;
2752 if (*p != NUL)
2753 {
2754 x3 = mb_ptr2char(p);
2755 p += mb_ptr2len(p);
2756 }
2757 if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ','))
2758 return e_invalid_argument;
2759 if (*p == NUL)
2760 break;
2761 }
2762 }
2763 else
2764 {
2765 // Check for "x:y,x:y"
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002766 for (p = *varp; *p != NUL; p += 4)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002767 {
2768 if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
2769 return e_invalid_argument;
2770 if (p[3] == NUL)
2771 break;
2772 }
2773 }
2774
2775 return NULL;
2776}
2777
2778#if defined(FEAT_SPELL) || defined(PROTO)
2779/*
2780 * The 'mkspellmem' option is changed.
2781 */
2782 char *
2783did_set_mkspellmem(optset_T *args UNUSED)
2784{
2785 if (spell_check_msm() != OK)
2786 return e_invalid_argument;
2787
2788 return NULL;
2789}
2790#endif
2791
2792/*
2793 * The 'mouse' option is changed.
2794 */
2795 char *
2796did_set_mouse(optset_T *args)
2797{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002798 char_u **varp = (char_u **)args->os_varp;
2799
2800 return did_set_option_listflag(*varp, (char_u *)MOUSE_ALL,
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002801 args->os_errbuf);
2802}
2803
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002804 int
2805expand_set_mouse(optexpand_T *args, int *numMatches, char_u ***matches)
2806{
2807 return expand_set_opt_listflag(args, (char_u*)MOUSE_ALL, numMatches, matches);
2808}
2809
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002810/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002811 * The 'mousemodel' option is changed.
2812 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002813 char *
2814did_set_mousemodel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002815{
2816 if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
2817 return e_invalid_argument;
2818#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
2819 else if (*p_mousem != *oldval)
2820 // Changed from "extend" to "popup" or "popup_setpos" or vv: need
2821 // to create or delete the popup menus.
2822 gui_motif_update_mousemodel(root_menu);
2823#endif
2824
2825 return NULL;
2826}
2827
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002828 int
2829expand_set_mousemodel(optexpand_T *args, int *numMatches, char_u ***matches)
2830{
2831 return expand_set_opt_string(
2832 args,
2833 p_mousem_values,
2834 sizeof(p_mousem_values) / sizeof(p_mousem_values[0]) - 1,
2835 numMatches,
2836 matches);
2837}
2838
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002839#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
2840 char *
2841did_set_mouseshape(optset_T *args UNUSED)
2842{
2843 char *errmsg = NULL;
2844
2845 errmsg = parse_shape_opt(SHAPE_MOUSE);
2846 update_mouseshape(-1);
2847
2848 return errmsg;
2849}
2850#endif
2851
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002852/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002853 * The 'nrformats' option is changed.
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00002854 */
2855 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002856did_set_nrformats(optset_T *args)
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00002857{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002858 char_u **varp = (char_u **)args->os_varp;
2859
2860 return did_set_opt_strings(*varp, p_nf_values, TRUE);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002861}
2862
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002863 int
2864expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches)
2865{
2866 return expand_set_opt_string(
2867 args,
2868 p_nf_values,
2869 sizeof(p_nf_values) / sizeof(p_nf_values[0]) - 1,
2870 numMatches,
2871 matches);
2872}
2873
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002874#if defined(FEAT_EVAL) || defined(PROTO)
2875/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002876 * One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
2877 * 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr',
2878 * 'patchexpr', 'printexpr' and 'charconvert'.
2879 *
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002880 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002881 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002882did_set_optexpr(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002883{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002884 char_u **varp = (char_u **)args->os_varp;
2885
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002886 // If the option value starts with <SID> or s:, then replace that with
2887 // the script identifier.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002888 char_u *name = get_scriptlocal_funcname(*varp);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002889 if (name != NULL)
2890 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002891 free_string_option(*varp);
2892 *varp = name;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002893 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002894
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002895 return NULL;
2896}
2897#endif
2898
2899/*
2900 * The 'pastetoggle' option is changed.
2901 */
2902 char *
2903did_set_pastetoggle(optset_T *args UNUSED)
2904{
2905 char_u *p;
2906
2907 // translate key codes like in a mapping
2908 if (*p_pt)
2909 {
zeertzjq7e0bae02023-08-11 23:15:38 +02002910 (void)replace_termcodes(p_pt, &p, 0,
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002911 REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
2912 if (p != NULL)
2913 {
2914 free_string_option(p_pt);
2915 p_pt = p;
2916 }
2917 }
2918
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002919 return NULL;
2920}
2921
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002922#if defined(FEAT_PROP_POPUP) || defined(PROTO)
2923/*
2924 * The 'previewpopup' option is changed.
2925 */
2926 char *
2927did_set_previewpopup(optset_T *args UNUSED)
2928{
2929 if (parse_previewpopup(NULL) == FAIL)
2930 return e_invalid_argument;
2931
2932 return NULL;
2933}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002934
2935 int
2936expand_set_popupoption(optexpand_T *args, int *numMatches, char_u ***matches)
2937{
2938 expand_T *xp = args->oe_xp;
2939
2940 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2941 {
2942 // Within "highlight:"/"border:"/"align:", we have a subgroup of possible options.
2943 int border_len = STRLEN("border:");
2944 if (xp->xp_pattern - args->oe_set_arg >= border_len &&
2945 STRNCMP(xp->xp_pattern - border_len, "border:", border_len) == 0)
2946 {
2947 return expand_set_opt_string(
2948 args,
2949 p_popup_option_border_values,
2950 sizeof(p_popup_option_border_values) / sizeof(p_popup_option_border_values[0]) - 1,
2951 numMatches,
2952 matches);
2953 }
2954 int align_len = STRLEN("align:");
2955 if (xp->xp_pattern - args->oe_set_arg >= align_len &&
2956 STRNCMP(xp->xp_pattern - align_len, "align:", align_len) == 0)
2957 {
2958 return expand_set_opt_string(
2959 args,
2960 p_popup_option_align_values,
2961 sizeof(p_popup_option_align_values) / sizeof(p_popup_option_align_values[0]) - 1,
2962 numMatches,
2963 matches);
2964 }
2965 int highlight_len = STRLEN("highlight:");
2966 if (xp->xp_pattern - args->oe_set_arg >= highlight_len &&
2967 STRNCMP(xp->xp_pattern - highlight_len, "highlight:", highlight_len) == 0)
2968 {
2969 // Return the list of all highlight names
2970 return expand_set_opt_generic(
2971 args,
2972 get_highlight_name,
2973 numMatches,
2974 matches);
2975 }
2976 return FAIL;
2977 }
2978
2979 return expand_set_opt_string(
2980 args,
2981 p_popup_option_values,
2982 sizeof(p_popup_option_values) / sizeof(p_popup_option_values[0]) - 1,
2983 numMatches,
2984 matches);
2985}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002986#endif
2987
2988#if defined(FEAT_POSTSCRIPT) || defined(PROTO)
2989/*
2990 * The 'printencoding' option is changed.
2991 */
2992 char *
2993did_set_printencoding(optset_T *args UNUSED)
2994{
2995 char_u *s, *p;
2996
2997 // Canonize 'printencoding' if VIM standard one
2998 p = enc_canonize(p_penc);
2999 if (p != NULL)
3000 {
3001 vim_free(p_penc);
3002 p_penc = p;
3003 }
3004 else
3005 {
3006 // Ensure lower case and '-' for '_'
3007 for (s = p_penc; *s != NUL; s++)
3008 {
3009 if (*s == '_')
3010 *s = '-';
3011 else
3012 *s = TOLOWER_ASC(*s);
3013 }
3014 }
3015
3016 return NULL;
3017}
3018#endif
3019
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003020#if defined(FEAT_PRINTER) || defined(PROTO)
3021
3022 static char_u *
3023get_printoptions_names(expand_T *xp UNUSED, int idx)
3024{
3025 if (idx >= (int)(sizeof(printer_opts) / sizeof(printer_opts[0])))
3026 return NULL;
3027 return (char_u*)printer_opts[idx].name;
3028}
3029
3030/*
3031 * Expand 'printoptions' option
3032 */
3033 int
3034expand_set_printoptions(optexpand_T *args, int *numMatches, char_u ***matches)
3035{
3036 return expand_set_opt_generic(
3037 args,
3038 get_printoptions_names,
3039 numMatches,
3040 matches);
3041}
3042#endif
3043
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003044#if defined(FEAT_STL_OPT) || defined(PROTO)
3045/*
3046 * The 'statusline' or the 'tabline' or the 'rulerformat' option is changed.
3047 * "rulerformat" is TRUE if the 'rulerformat' option is changed.
3048 */
3049 static char *
3050parse_statustabline_rulerformat(optset_T *args, int rulerformat)
3051{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003052 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003053 char_u *s;
3054 char *errmsg = NULL;
3055 int wid;
3056
3057 if (rulerformat) // reset ru_wid first
3058 ru_wid = 0;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003059 s = *varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003060 if (rulerformat && *s == '%')
3061 {
3062 // set ru_wid if 'ruf' starts with "%99("
3063 if (*++s == '-') // ignore a '-'
3064 s++;
3065 wid = getdigits(&s);
3066 if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
3067 ru_wid = wid;
3068 else
3069 errmsg = check_stl_option(p_ruf);
3070 }
3071 // check 'statusline' or 'tabline' only if it doesn't start with "%!"
3072 else if (rulerformat || s[0] != '%' || s[1] != '!')
3073 errmsg = check_stl_option(s);
3074 if (rulerformat && errmsg == NULL)
3075 comp_col();
3076
3077 return errmsg;
3078}
3079#endif
3080
3081#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
3082/*
3083 * The 'renderoptions' option is changed.
3084 */
3085 char *
3086did_set_renderoptions(optset_T *args UNUSED)
3087{
3088 if (!gui_mch_set_rendering_options(p_rop))
3089 return e_invalid_argument;
3090
3091 return NULL;
3092}
3093#endif
3094
3095#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
3096/*
3097 * The 'rightleftcmd' option is changed.
3098 */
3099 char *
3100did_set_rightleftcmd(optset_T *args)
3101{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003102 char_u **varp = (char_u **)args->os_varp;
3103
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003104 // Currently only "search" is a supported value.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003105 if (**varp != NUL && STRCMP(*varp, "search") != 0)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003106 return e_invalid_argument;
3107
3108 return NULL;
3109}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003110
3111 int
3112expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char_u ***matches)
3113{
3114 static char *(p_rlc_values[]) = {"search", NULL};
3115 return expand_set_opt_string(
3116 args,
3117 p_rlc_values,
3118 sizeof(p_rlc_values) / sizeof(p_rlc_values[0]) - 1,
3119 numMatches,
3120 matches);
3121}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003122#endif
3123
3124#if defined(FEAT_STL_OPT) || defined(PROTO)
3125/*
3126 * The 'rulerformat' option is changed.
3127 */
3128 char *
3129did_set_rulerformat(optset_T *args)
3130{
3131 return parse_statustabline_rulerformat(args, TRUE);
3132}
3133#endif
3134
3135/*
3136 * The 'scrollopt' option is changed.
3137 */
3138 char *
3139did_set_scrollopt(optset_T *args UNUSED)
3140{
3141 return did_set_opt_strings(p_sbo, p_scbopt_values, TRUE);
3142}
3143
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003144 int
3145expand_set_scrollopt(optexpand_T *args, int *numMatches, char_u ***matches)
3146{
3147 return expand_set_opt_string(
3148 args,
3149 p_scbopt_values,
3150 sizeof(p_scbopt_values) / sizeof(p_scbopt_values[0]) - 1,
3151 numMatches,
3152 matches);
3153}
3154
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003155/*
3156 * The 'selection' option is changed.
3157 */
3158 char *
3159did_set_selection(optset_T *args UNUSED)
3160{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003161 if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003162 return e_invalid_argument;
3163
3164 return NULL;
3165}
3166
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003167 int
3168expand_set_selection(optexpand_T *args, int *numMatches, char_u ***matches)
3169{
3170 return expand_set_opt_string(
3171 args,
3172 p_sel_values,
3173 sizeof(p_sel_values) / sizeof(p_sel_values[0]) - 1,
3174 numMatches,
3175 matches);
3176}
3177
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003178/*
3179 * The 'selectmode' option is changed.
3180 */
3181 char *
3182did_set_selectmode(optset_T *args UNUSED)
3183{
3184 return did_set_opt_strings(p_slm, p_slm_values, TRUE);
3185}
3186
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003187 int
3188expand_set_selectmode(optexpand_T *args, int *numMatches, char_u ***matches)
3189{
3190 return expand_set_opt_string(
3191 args,
3192 p_slm_values,
3193 sizeof(p_slm_values) / sizeof(p_slm_values[0]) - 1,
3194 numMatches,
3195 matches);
3196}
3197
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003198#if defined(FEAT_SESSION) || defined(PROTO)
3199/*
3200 * The 'sessionoptions' option is changed.
3201 */
3202 char *
3203did_set_sessionoptions(optset_T *args)
3204{
3205 if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
3206 return e_invalid_argument;
3207 if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR))
3208 {
3209 // Don't allow both "sesdir" and "curdir".
3210 (void)opt_strings_flags(args->os_oldval.string, p_ssop_values,
3211 &ssop_flags, TRUE);
3212 return e_invalid_argument;
3213 }
3214
3215 return NULL;
3216}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003217
3218 int
3219expand_set_sessionoptions(optexpand_T *args, int *numMatches, char_u ***matches)
3220{
3221 return expand_set_opt_string(
3222 args,
3223 p_ssop_values,
3224 sizeof(p_ssop_values) / sizeof(p_ssop_values[0]) - 1,
3225 numMatches,
3226 matches);
3227}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003228#endif
3229
3230/*
3231 * The 'shortmess' option is changed.
3232 */
3233 char *
3234did_set_shortmess(optset_T *args)
3235{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003236 char_u **varp = (char_u **)args->os_varp;
3237
3238 return did_set_option_listflag(*varp, (char_u *)SHM_ALL, args->os_errbuf);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003239}
3240
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003241 int
3242expand_set_shortmess(optexpand_T *args, int *numMatches, char_u ***matches)
3243{
3244 return expand_set_opt_listflag(args, (char_u*)SHM_ALL, numMatches, matches);
3245}
3246
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003247#if defined(FEAT_LINEBREAK) || defined(PROTO)
3248/*
3249 * The 'showbreak' option is changed.
3250 */
3251 char *
3252did_set_showbreak(optset_T *args)
3253{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003254 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003255 char_u *s;
3256
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003257 for (s = *varp; *s; )
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003258 {
3259 if (ptr2cells(s) != 1)
3260 return e_showbreak_contains_unprintable_or_wide_character;
3261 MB_PTR_ADV(s);
3262 }
3263
3264 return NULL;
3265}
3266#endif
3267
3268/*
3269 * The 'showcmdloc' option is changed.
3270 */
3271 char *
3272did_set_showcmdloc(optset_T *args UNUSED)
3273{
3274 return did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
3275}
3276
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003277 int
3278expand_set_showcmdloc(optexpand_T *args, int *numMatches, char_u ***matches)
3279{
3280 return expand_set_opt_string(
3281 args,
3282 p_sloc_values,
3283 sizeof(p_sloc_values) / sizeof(p_sloc_values[0]) - 1,
3284 numMatches,
3285 matches);
3286}
3287
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003288#if defined(FEAT_SIGNS) || defined(PROTO)
3289/*
3290 * The 'signcolumn' option is changed.
3291 */
3292 char *
3293did_set_signcolumn(optset_T *args)
3294{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003295 char_u **varp = (char_u **)args->os_varp;
3296
3297 if (check_opt_strings(*varp, p_scl_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003298 return e_invalid_argument;
3299 // When changing the 'signcolumn' to or from 'number', recompute the
3300 // width of the number column if 'number' or 'relativenumber' is set.
3301 if (((*args->os_oldval.string == 'n' && args->os_oldval.string[1] == 'u')
3302 || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u'))
3303 && (curwin->w_p_nu || curwin->w_p_rnu))
3304 curwin->w_nrwidth_line_count = 0;
3305
3306 return NULL;
3307}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003308
3309 int
3310expand_set_signcolumn(optexpand_T *args, int *numMatches, char_u ***matches)
3311{
3312 return expand_set_opt_string(
3313 args,
3314 p_scl_values,
3315 sizeof(p_scl_values) / sizeof(p_scl_values[0]) - 1,
3316 numMatches,
3317 matches);
3318}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003319#endif
3320
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003321#if defined(FEAT_SPELL) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003322/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003323 * The 'spellcapcheck' option is changed.
3324 */
3325 char *
3326did_set_spellcapcheck(optset_T *args UNUSED)
3327{
3328 // compile the regexp program.
3329 return compile_cap_prog(curwin->w_s);
3330}
3331
3332/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003333 * The 'spellfile' option is changed.
3334 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003335 char *
3336did_set_spellfile(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003337{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003338 char_u **varp = (char_u **)args->os_varp;
3339
3340 if (!valid_spellfile(*varp))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003341 return e_invalid_argument;
3342
3343 // If there is a window for this buffer in which 'spell' is set load the
3344 // wordlists.
3345 return did_set_spell_option(TRUE);
3346}
3347
3348/*
3349 * The 'spell' option is changed.
3350 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003351 char *
3352did_set_spelllang(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003353{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003354 char_u **varp = (char_u **)args->os_varp;
3355
3356 if (!valid_spelllang(*varp))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003357 return e_invalid_argument;
3358
3359 // If there is a window for this buffer in which 'spell' is set load the
3360 // wordlists.
3361 return did_set_spell_option(FALSE);
3362}
3363
3364/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003365 * The 'spelloptions' option is changed.
3366 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003367 char *
3368did_set_spelloptions(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003369{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003370 char_u **varp = (char_u **)args->os_varp;
3371
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003372 if (**varp != NUL && STRCMP(*varp, "camel") != 0)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003373 return e_invalid_argument;
3374
3375 return NULL;
3376}
3377
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003378 int
3379expand_set_spelloptions(optexpand_T *args, int *numMatches, char_u ***matches)
3380{
3381 static char *(p_spo_values[]) = {"camel", NULL};
3382 return expand_set_opt_string(
3383 args,
3384 p_spo_values,
3385 sizeof(p_spo_values) / sizeof(p_spo_values[0]) - 1,
3386 numMatches,
3387 matches);
3388}
3389
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003390/*
3391 * The 'spellsuggest' option is changed.
3392 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003393 char *
3394did_set_spellsuggest(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003395{
3396 if (spell_check_sps() != OK)
3397 return e_invalid_argument;
3398
3399 return NULL;
3400}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003401
3402 int
3403expand_set_spellsuggest(optexpand_T *args, int *numMatches, char_u ***matches)
3404{
3405 return expand_set_opt_string(
3406 args,
3407 p_sps_values,
3408 sizeof(p_sps_values) / sizeof(p_sps_values[0]) - 1,
3409 numMatches,
3410 matches);
3411}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003412#endif
3413
3414/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003415 * The 'splitkeep' option is changed.
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003416 */
3417 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003418did_set_splitkeep(optset_T *args UNUSED)
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003419{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003420 return did_set_opt_strings(p_spk, p_spk_values, FALSE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003421}
3422
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003423 int
3424expand_set_splitkeep(optexpand_T *args, int *numMatches, char_u ***matches)
3425{
3426 return expand_set_opt_string(
3427 args,
3428 p_spk_values,
3429 sizeof(p_spk_values) / sizeof(p_spk_values[0]) - 1,
3430 numMatches,
3431 matches);
3432}
3433
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003434#if defined(FEAT_STL_OPT) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003435/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003436 * The 'statusline' option is changed.
3437 */
3438 char *
3439did_set_statusline(optset_T *args)
3440{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003441 return parse_statustabline_rulerformat(args, FALSE);
3442}
3443#endif
3444
3445/*
3446 * The 'swapsync' option is changed.
3447 */
3448 char *
3449did_set_swapsync(optset_T *args UNUSED)
3450{
3451 return did_set_opt_strings(p_sws, p_sws_values, FALSE);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003452}
3453
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003454 int
3455expand_set_swapsync(optexpand_T *args, int *numMatches, char_u ***matches)
3456{
3457 return expand_set_opt_string(
3458 args,
3459 p_sws_values,
3460 sizeof(p_sws_values) / sizeof(p_sws_values[0]) - 1,
3461 numMatches,
3462 matches);
3463}
3464
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003465/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003466 * The 'switchbuf' option is changed.
3467 */
3468 char *
3469did_set_switchbuf(optset_T *args UNUSED)
3470{
3471 return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, TRUE);
3472}
3473
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003474 int
3475expand_set_switchbuf(optexpand_T *args, int *numMatches, char_u ***matches)
3476{
3477 return expand_set_opt_string(
3478 args,
3479 p_swb_values,
3480 sizeof(p_swb_values) / sizeof(p_swb_values[0]) - 1,
3481 numMatches,
3482 matches);
3483}
3484
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003485#if defined(FEAT_STL_OPT) || defined(PROTO)
3486/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003487 * The 'tabline' option is changed.
3488 */
3489 char *
3490did_set_tabline(optset_T *args)
3491{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003492 return parse_statustabline_rulerformat(args, FALSE);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003493}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003494#endif
3495
3496/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003497 * The 'tagcase' option is changed.
3498 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003499 char *
3500did_set_tagcase(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003501{
3502 unsigned int *flags;
3503 char_u *p;
3504
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003505 if (args->os_flags & OPT_LOCAL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003506 {
3507 p = curbuf->b_p_tc;
3508 flags = &curbuf->b_tc_flags;
3509 }
3510 else
3511 {
3512 p = p_tc;
3513 flags = &tc_flags;
3514 }
3515
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003516 if ((args->os_flags & OPT_LOCAL) && *p == NUL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003517 // make the local value empty: use the global value
3518 *flags = 0;
3519 else if (*p == NUL
3520 || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
3521 return e_invalid_argument;
3522
3523 return NULL;
3524}
3525
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003526 int
3527expand_set_tagcase(optexpand_T *args, int *numMatches, char_u ***matches)
3528{
3529 return expand_set_opt_string(
3530 args,
3531 p_tc_values,
3532 sizeof(p_tc_values) / sizeof(p_tc_values[0]) - 1,
3533 numMatches,
3534 matches);
3535}
3536
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003537/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003538 * The 'term' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003539 */
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003540 char *
3541did_set_term(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003542{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003543 if (T_NAME[0] == NUL)
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003544 return e_cannot_set_term_to_empty_string;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003545#ifdef FEAT_GUI
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003546 if (gui.in_use)
3547 return e_cannot_change_term_in_GUI;
3548 if (term_is_gui(T_NAME))
3549 return e_use_gui_to_start_GUI;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003550#endif
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003551 if (set_termname(T_NAME) == FAIL)
3552 return e_not_found_in_termcap;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003553
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003554 // Screen colors may have changed.
3555 redraw_later_clear();
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003556
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003557 return NULL;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003558}
3559
3560/*
3561 * Some terminal option (t_xxx) is changed
3562 */
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003563 char *
3564did_set_term_option(optset_T *args)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003565{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003566 char_u **varp = (char_u **)args->os_varp;
3567
3568 if (!full_screen)
3569 return NULL;
3570
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003571 // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co="
3572 if (varp == &T_CCO)
3573 {
3574 int colors = atoi((char *)T_CCO);
3575
3576 // Only reinitialize colors if t_Co value has really changed to
3577 // avoid expensive reload of colorscheme if t_Co is set to the
3578 // same value multiple times.
3579 if (colors != t_colors)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003580 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003581 t_colors = colors;
3582 if (t_colors <= 1)
3583 {
3584 vim_free(T_CCO);
3585 T_CCO = empty_option;
3586 }
3587#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
3588 if (is_term_win32())
3589 {
3590 swap_tcap();
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003591 args->os_did_swaptcap = TRUE;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003592 }
3593#endif
3594 // We now have a different color setup, initialize it again.
3595 init_highlight(TRUE, FALSE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003596 }
3597 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003598 ttest(FALSE);
3599 if (varp == &T_ME)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003600 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003601 out_str(T_ME);
3602 redraw_later(UPD_CLEAR);
3603#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3604 // Since t_me has been set, this probably means that the user
3605 // wants to use this as default colors. Need to reset default
3606 // background/foreground colors.
3607# ifdef VIMDLL
3608 if (!gui.in_use && !gui.starting)
3609# endif
3610 mch_set_normal_colors();
3611#endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003612 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003613 if (varp == &T_BE && termcap_active)
3614 {
3615 MAY_WANT_TO_LOG_THIS;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003616
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003617 if (*T_BE == NUL)
3618 // When clearing t_BE we assume the user no longer wants
3619 // bracketed paste, thus disable it by writing t_BD.
3620 out_str(T_BD);
3621 else
3622 out_str(T_BE);
3623 }
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003624
3625 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003626}
3627
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003628#if defined(FEAT_TERMINAL) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003629/*
3630 * The 'termwinkey' option is changed.
3631 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003632 char *
3633did_set_termwinkey(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003634{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003635 if (*curwin->w_p_twk != NUL && string_to_key(curwin->w_p_twk, TRUE) == 0)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003636 return e_invalid_argument;
3637
3638 return NULL;
3639}
3640
3641/*
3642 * The 'termwinsize' option is changed.
3643 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003644 char *
3645did_set_termwinsize(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003646{
3647 char_u *p;
3648
3649 if (*curwin->w_p_tws == NUL)
3650 return NULL;
3651
3652 p = skipdigits(curwin->w_p_tws);
3653 if (p == curwin->w_p_tws
3654 || (*p != 'x' && *p != '*')
3655 || *skipdigits(p + 1) != NUL)
3656 return e_invalid_argument;
3657
3658 return NULL;
3659}
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003660
3661# if defined(MSWIN) || defined(PROTO)
3662/*
3663 * The 'termwintype' option is changed.
3664 */
3665 char *
3666did_set_termwintype(optset_T *args UNUSED)
3667{
3668 return did_set_opt_strings(p_twt, p_twt_values, FALSE);
3669}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003670
3671 int
3672expand_set_termwintype(optexpand_T *args, int *numMatches, char_u ***matches)
3673{
3674 return expand_set_opt_string(
3675 args,
3676 p_twt_values,
3677 sizeof(p_twt_values) / sizeof(p_twt_values[0]) - 1,
3678 numMatches,
3679 matches);
3680}
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003681# endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003682#endif
3683
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003684/*
3685 * The 'titlestring' option is changed.
3686 */
3687 char *
3688did_set_titlestring(optset_T *args)
3689{
3690 int flagval = 0;
3691
3692#ifdef FEAT_STL_OPT
3693 flagval = STL_IN_TITLE;
3694#endif
3695 return parse_titleiconstring(args, flagval);
3696}
3697
3698#if (defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)) || defined(PROTO)
3699/*
3700 * The 'toolbar' option is changed.
3701 */
3702 char *
3703did_set_toolbar(optset_T *args UNUSED)
3704{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003705 if (opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags,
3706 TRUE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003707 return e_invalid_argument;
3708
3709 out_flush();
3710 gui_mch_show_toolbar((toolbar_flags &
3711 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
3712 return NULL;
3713}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003714
3715 int
3716expand_set_toolbar(optexpand_T *args, int *numMatches, char_u ***matches)
3717{
3718 return expand_set_opt_string(
3719 args,
3720 p_toolbar_values,
3721 sizeof(p_toolbar_values) / sizeof(p_toolbar_values[0]) - 1,
3722 numMatches,
3723 matches);
3724}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003725#endif
3726
3727#if (defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)) || defined(PROTO)
3728/*
3729 * The 'toolbariconsize' option is changed. GTK+ 2 only.
3730 */
3731 char *
3732did_set_toolbariconsize(optset_T *args UNUSED)
3733{
3734 if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
3735 return e_invalid_argument;
3736
3737 out_flush();
3738 gui_mch_show_toolbar((toolbar_flags &
3739 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
3740 return NULL;
3741}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003742
3743 int
3744expand_set_toolbariconsize(optexpand_T *args, int *numMatches, char_u ***matches)
3745{
3746 return expand_set_opt_string(
3747 args,
3748 p_tbis_values,
3749 sizeof(p_tbis_values) / sizeof(p_tbis_values[0]) - 1,
3750 numMatches,
3751 matches);
3752}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003753#endif
3754
3755#if defined(UNIX) || defined(VMS) || defined(PROTO)
3756/*
3757 * The 'ttymouse' option is changed.
3758 */
3759 char *
3760did_set_ttymouse(optset_T *args UNUSED)
3761{
3762 char *errmsg = NULL;
3763
3764 // Switch the mouse off before changing the escape sequences used for
3765 // that.
3766 mch_setmouse(FALSE);
3767 if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
3768 errmsg = e_invalid_argument;
3769 else
3770 check_mouse_termcode();
3771 if (termcap_active)
3772 setmouse(); // may switch it on again
3773
3774 return errmsg;
3775}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003776
3777 int
3778expand_set_ttymouse(optexpand_T *args, int *numMatches, char_u ***matches)
3779{
3780 return expand_set_opt_string(
3781 args,
3782 p_ttym_values,
3783 sizeof(p_ttym_values) / sizeof(p_ttym_values[0]) - 1,
3784 numMatches,
3785 matches);
3786}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003787#endif
3788
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003789#if defined(FEAT_VARTABS) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003790/*
3791 * The 'varsofttabstop' option is changed.
3792 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003793 char *
3794did_set_varsofttabstop(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003795{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003796 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003797 char_u *cp;
3798
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003799 if (!((*varp)[0]) || ((*varp)[0] == '0' && !((*varp)[1])))
Yegappan Lakshmanan960dcbd2023-03-07 17:45:11 +00003800 VIM_CLEAR(curbuf->b_p_vsts_array);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003801 else
3802 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003803 for (cp = *varp; *cp; ++cp)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003804 {
3805 if (vim_isdigit(*cp))
3806 continue;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003807 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003808 continue;
3809 return e_invalid_argument;
3810 }
3811
3812 int *oldarray = curbuf->b_p_vsts_array;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003813 if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)) == OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003814 {
3815 if (oldarray)
3816 vim_free(oldarray);
3817 }
3818 else
3819 return e_invalid_argument;
3820 }
3821
3822 return NULL;
3823}
3824
3825/*
3826 * The 'vartabstop' option is changed.
3827 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003828 char *
3829did_set_vartabstop(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003830{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003831 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003832 char_u *cp;
3833
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003834 if (!((*varp)[0]) || ((*varp)[0] == '0' && !((*varp)[1])))
Yegappan Lakshmanan960dcbd2023-03-07 17:45:11 +00003835 VIM_CLEAR(curbuf->b_p_vts_array);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003836 else
3837 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003838 for (cp = *varp; *cp; ++cp)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003839 {
3840 if (vim_isdigit(*cp))
3841 continue;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003842 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003843 continue;
3844 return e_invalid_argument;
3845 }
3846
3847 int *oldarray = curbuf->b_p_vts_array;
3848
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003849 if (tabstop_set(*varp, &(curbuf->b_p_vts_array)) == OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003850 {
3851 vim_free(oldarray);
3852# ifdef FEAT_FOLDING
3853 if (foldmethodIsIndent(curwin))
3854 foldUpdateAll(curwin);
3855# endif
3856 }
3857 else
3858 return e_invalid_argument;
3859 }
3860
3861 return NULL;
3862}
3863#endif
3864
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003865/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003866 * The 'verbosefile' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003867 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003868 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003869did_set_verbosefile(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003870{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003871 verbose_stop();
3872 if (*p_vfile != NUL && verbose_open() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003873 return e_invalid_argument;
3874
3875 return NULL;
3876}
3877
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003878#if defined(FEAT_SESSION) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003879/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003880 * The 'viewoptions' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003881 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003882 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003883did_set_viewoptions(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003884{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003885 return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003886}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003887#endif
3888
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003889#if defined(FEAT_VIMINFO) || defined(PROTO)
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003890/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003891 * The 'viminfo' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003892 */
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003893 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003894did_set_viminfo(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003895{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003896 char_u *s;
3897 char *errmsg = NULL;
3898
3899 for (s = p_viminfo; *s;)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003900 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003901 // Check it's a valid character
3902 if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
3903 {
3904 errmsg = illegal_char(args->os_errbuf, *s);
3905 break;
3906 }
3907 if (*s == 'n') // name is always last one
3908 break;
3909 else if (*s == 'r') // skip until next ','
3910 {
3911 while (*++s && *s != ',')
3912 ;
3913 }
3914 else if (*s == '%')
3915 {
3916 // optional number
3917 while (vim_isdigit(*++s))
3918 ;
3919 }
3920 else if (*s == '!' || *s == 'h' || *s == 'c')
3921 ++s; // no extra chars
3922 else // must have a number
3923 {
3924 while (vim_isdigit(*++s))
3925 ;
3926
3927 if (!VIM_ISDIGIT(*(s - 1)))
3928 {
3929 if (args->os_errbuf != NULL)
3930 {
3931 sprintf(args->os_errbuf,
3932 _(e_missing_number_after_angle_str_angle),
3933 transchar_byte(*(s - 1)));
3934 errmsg = args->os_errbuf;
3935 }
3936 else
3937 errmsg = "";
3938 break;
3939 }
3940 }
3941 if (*s == ',')
3942 ++s;
3943 else if (*s)
3944 {
3945 if (args->os_errbuf != NULL)
3946 errmsg = e_missing_comma;
3947 else
3948 errmsg = "";
3949 break;
3950 }
3951 }
3952 if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
3953 errmsg = e_must_specify_a_value;
3954
3955 return errmsg;
3956}
3957#endif
3958
3959/*
3960 * The 'virtualedit' option is changed.
3961 */
3962 char *
3963did_set_virtualedit(optset_T *args)
3964{
3965 char_u *ve = p_ve;
3966 unsigned int *flags = &ve_flags;
3967
3968 if (args->os_flags & OPT_LOCAL)
3969 {
3970 ve = curwin->w_p_ve;
3971 flags = &curwin->w_ve_flags;
3972 }
3973
3974 if ((args->os_flags & OPT_LOCAL) && *ve == NUL)
3975 // make the local value empty: use the global value
3976 *flags = 0;
3977 else
3978 {
3979 if (opt_strings_flags(ve, p_ve_values, flags, TRUE) != OK)
3980 return e_invalid_argument;
3981 else if (STRCMP(ve, args->os_oldval.string) != 0)
3982 {
3983 // Recompute cursor position in case the new 've' setting
3984 // changes something.
3985 validate_virtcol();
3986 coladvance(curwin->w_virtcol);
3987 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003988 }
3989
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003990 return NULL;
3991}
3992
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003993 int
3994expand_set_virtualedit(optexpand_T *args, int *numMatches, char_u ***matches)
3995{
3996 return expand_set_opt_string(
3997 args,
3998 p_ve_values,
3999 sizeof(p_ve_values) / sizeof(p_ve_values[0]) - 1,
4000 numMatches,
4001 matches);
4002}
4003
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00004004/*
4005 * The 'whichwrap' option is changed.
4006 */
4007 char *
4008did_set_whichwrap(optset_T *args)
4009{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00004010 char_u **varp = (char_u **)args->os_varp;
4011
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004012 // Add ',' to the list flags because 'whichwrap' is a flag
4013 // list that is comma-separated.
4014 return did_set_option_listflag(*varp, (char_u *)(WW_ALL ","), args->os_errbuf);
4015}
4016
4017 int
4018expand_set_whichwrap(optexpand_T *args, int *numMatches, char_u ***matches)
4019{
4020 return expand_set_opt_listflag(args, (char_u*)WW_ALL, numMatches, matches);
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004021}
4022
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004023/*
4024 * The 'wildmode' option is changed.
4025 */
4026 char *
4027did_set_wildmode(optset_T *args UNUSED)
4028{
4029 if (check_opt_wim() == FAIL)
4030 return e_invalid_argument;
4031 return NULL;
4032}
4033
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004034 int
4035expand_set_wildmode(optexpand_T *args, int *numMatches, char_u ***matches)
4036{
4037 return expand_set_opt_string(
4038 args,
4039 p_wim_values,
4040 sizeof(p_wim_values) / sizeof(p_wim_values[0]) - 1,
4041 numMatches,
4042 matches);
4043}
4044
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004045/*
4046 * The 'wildoptions' option is changed.
4047 */
4048 char *
4049did_set_wildoptions(optset_T *args UNUSED)
4050{
4051 return did_set_opt_strings(p_wop, p_wop_values, TRUE);
4052}
4053
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004054 int
4055expand_set_wildoptions(optexpand_T *args, int *numMatches, char_u ***matches)
4056{
4057 return expand_set_opt_string(
4058 args,
4059 p_wop_values,
4060 sizeof(p_wop_values) / sizeof(p_wop_values[0]) - 1,
4061 numMatches,
4062 matches);
4063}
4064
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004065#if defined(FEAT_WAK) || defined(PROTO)
4066/*
4067 * The 'winaltkeys' option is changed.
4068 */
4069 char *
4070did_set_winaltkeys(optset_T *args UNUSED)
4071{
4072 char *errmsg = NULL;
4073
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004074 if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004075 errmsg = e_invalid_argument;
4076# ifdef FEAT_MENU
4077# if defined(FEAT_GUI_MOTIF)
4078 else if (gui.in_use)
4079 gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
4080# elif defined(FEAT_GUI_GTK)
4081 else if (gui.in_use)
4082 gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
4083# endif
4084# endif
4085 return errmsg;
4086}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004087
4088 int
4089expand_set_winaltkeys(optexpand_T *args, int *numMatches, char_u ***matches)
4090{
4091 return expand_set_opt_string(
4092 args,
4093 p_wak_values,
4094 sizeof(p_wak_values) / sizeof(p_wak_values[0]) - 1,
4095 numMatches,
4096 matches);
4097}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004098#endif
4099
4100/*
4101 * The 'wincolor' option is changed.
4102 */
4103 char *
4104did_set_wincolor(optset_T *args UNUSED)
4105{
4106#ifdef FEAT_TERMINAL
4107 term_update_wincolor(curwin);
4108#endif
4109 return NULL;
4110}
4111
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004112 int
4113expand_set_wincolor(optexpand_T *args, int *numMatches, char_u ***matches)
4114{
4115 return expand_set_opt_generic(
4116 args,
4117 get_highlight_name,
4118 numMatches,
4119 matches);
4120}
4121
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004122#ifdef FEAT_SYN_HL
4123/*
4124 * When the 'syntax' option is set, load the syntax of that name.
4125 */
4126 static void
4127do_syntax_autocmd(int value_changed)
4128{
4129 static int syn_recursive = 0;
4130
4131 ++syn_recursive;
4132 // Only pass TRUE for "force" when the value changed or not used
4133 // recursively, to avoid endless recurrence.
4134 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
4135 value_changed || syn_recursive == 1, curbuf);
4136 curbuf->b_flags |= BF_SYN_SET;
4137 --syn_recursive;
4138}
4139#endif
4140
4141/*
4142 * When the 'filetype' option is set, trigger the FileType autocommand.
4143 */
4144 static void
4145do_filetype_autocmd(char_u **varp, int opt_flags, int value_changed)
4146{
4147 // Skip this when called from a modeline and the filetype was already set
4148 // to this value.
4149 if ((opt_flags & OPT_MODELINE) && !value_changed)
4150 return;
4151
4152 static int ft_recursive = 0;
4153 int secure_save = secure;
4154
4155 // Reset the secure flag, since the value of 'filetype' has
4156 // been checked to be safe.
4157 secure = 0;
4158
4159 ++ft_recursive;
4160 did_filetype = TRUE;
4161 // Only pass TRUE for "force" when the value changed or not
4162 // used recursively, to avoid endless recurrence.
4163 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
4164 value_changed || ft_recursive == 1, curbuf);
4165 --ft_recursive;
4166 // Just in case the old "curbuf" is now invalid.
4167 if (varp != &(curbuf->b_p_ft))
4168 varp = NULL;
4169
4170 secure = secure_save;
4171}
4172
4173#ifdef FEAT_SPELL
4174/*
4175 * When the 'spelllang' option is set, source the spell/LANG.vim file in
4176 * 'runtimepath'.
4177 */
4178 static void
4179do_spelllang_source(void)
4180{
4181 char_u fname[200];
4182 char_u *p;
4183 char_u *q = curwin->w_s->b_p_spl;
4184
4185 // Skip the first name if it is "cjk".
4186 if (STRNCMP(q, "cjk,", 4) == 0)
4187 q += 4;
4188
4189 // They could set 'spellcapcheck' depending on the language. Use the first
4190 // name in 'spelllang' up to '_region' or '.encoding'.
4191 for (p = q; *p != NUL; ++p)
4192 if (!ASCII_ISALNUM(*p) && *p != '-')
4193 break;
4194 if (p > q)
4195 {
4196 vim_snprintf((char *)fname, 200, "spell/%.*s.vim",
4197 (int)(p - q), q);
4198 source_runtime(fname, DIP_ALL);
4199 }
4200}
4201#endif
4202
4203/*
Bram Moolenaardac13472019-09-16 21:06:21 +02004204 * Handle string options that need some action to perform when changed.
zeertzjqf6782732022-07-27 18:26:03 +01004205 * The new value must be allocated.
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004206 * Returns NULL for success, or an untranslated error message for an error.
Bram Moolenaardac13472019-09-16 21:06:21 +02004207 */
4208 char *
4209did_set_string_option(
4210 int opt_idx, // index in options[] table
4211 char_u **varp, // pointer to the option variable
Bram Moolenaardac13472019-09-16 21:06:21 +02004212 char_u *oldval, // previous value of the option
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004213 char_u *value, // new value of the option
Bram Moolenaardac13472019-09-16 21:06:21 +02004214 char *errbuf, // buffer for errors, or NULL
4215 int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL
Yee Cheng Chin6ee7b522023-10-01 09:13:22 +02004216 set_op_T op, // OP_ADDING/OP_PREPENDING/OP_REMOVING
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004217 int *value_checked) // value was checked to be safe, no
Bram Moolenaardac13472019-09-16 21:06:21 +02004218 // need to set P_INSECURE
4219{
4220 char *errmsg = NULL;
Bram Moolenaardac13472019-09-16 21:06:21 +02004221 long_u free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004222 opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx);
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004223 optset_T args;
4224
4225 // 'ttytype' is an alias for 'term'. Both 'term' and 'ttytype' point to
4226 // T_NAME. If 'term' or 'ttytype' is modified, then use the index for the
4227 // 'term' option. Only set the P_ALLOCED flag on 'term'.
4228 if (varp == &T_NAME)
4229 {
4230 opt_idx = findoption((char_u *)"term");
4231 if (opt_idx >= 0)
4232 {
4233 free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
4234 did_set_cb = get_option_did_set_cb(opt_idx);
4235 }
4236 }
4237
4238 CLEAR_FIELD(args);
Bram Moolenaardac13472019-09-16 21:06:21 +02004239
Bram Moolenaardac13472019-09-16 21:06:21 +02004240 // Disallow changing some options from secure mode
4241 if ((secure
4242#ifdef HAVE_SANDBOX
4243 || sandbox != 0
4244#endif
4245 ) && (get_option_flags(opt_idx) & P_SECURE))
Bram Moolenaar74409f62022-01-01 15:58:22 +00004246 errmsg = e_not_allowed_here;
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004247 // Check for a "normal" directory or file name in some options.
4248 else if (check_illegal_path_names(opt_idx, varp))
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00004249 errmsg = e_invalid_argument;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004250 else if (did_set_cb != NULL)
4251 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00004252 args.os_varp = (char_u *)varp;
4253 args.os_idx = opt_idx;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004254 args.os_flags = opt_flags;
Yee Cheng Chin6ee7b522023-10-01 09:13:22 +02004255 args.os_op = op;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004256 args.os_oldval.string = oldval;
4257 args.os_newval.string = value;
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00004258 args.os_errbuf = errbuf;
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004259 // Invoke the option specific callback function to validate and apply
4260 // the new option value.
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004261 errmsg = did_set_cb(&args);
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004262
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004263 // The 'keymap', 'filetype' and 'syntax' option callback functions
4264 // may change the os_value_checked field.
4265 *value_checked = args.os_value_checked;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004266 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004267
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004268 // If an error is detected, restore the previous value.
Bram Moolenaardac13472019-09-16 21:06:21 +02004269 if (errmsg != NULL)
4270 {
zeertzjqf6782732022-07-27 18:26:03 +01004271 free_string_option(*varp);
Bram Moolenaardac13472019-09-16 21:06:21 +02004272 *varp = oldval;
4273 // When resetting some values, need to act on it.
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004274 if (args.os_restore_chartab)
Bram Moolenaardac13472019-09-16 21:06:21 +02004275 (void)init_chartab();
4276 if (varp == &p_hl)
4277 (void)highlight_changed();
4278 }
4279 else
4280 {
4281#ifdef FEAT_EVAL
4282 // Remember where the option was set.
4283 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
4284#endif
4285 // Free string options that are in allocated memory.
4286 // Use "free_oldval", because recursiveness may change the flags under
4287 // our fingers (esp. init_highlight()).
4288 if (free_oldval)
4289 free_string_option(oldval);
zeertzjqf6782732022-07-27 18:26:03 +01004290 set_option_flag(opt_idx, P_ALLOCED);
Bram Moolenaardac13472019-09-16 21:06:21 +02004291
4292 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
4293 && is_global_local_option(opt_idx))
4294 {
4295 // global option with local value set to use global value; free
4296 // the local value and make it empty
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004297 char_u *p = get_option_varp_scope(opt_idx, OPT_LOCAL);
Bram Moolenaardac13472019-09-16 21:06:21 +02004298 free_string_option(*(char_u **)p);
4299 *(char_u **)p = empty_option;
4300 }
4301
4302 // May set global value for local option.
4303 else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL)
4304 set_string_option_global(opt_idx, varp);
4305
4306 // Trigger the autocommand only after setting the flags.
4307#ifdef FEAT_SYN_HL
Bram Moolenaardac13472019-09-16 21:06:21 +02004308 if (varp == &(curbuf->b_p_syn))
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004309 do_syntax_autocmd(args.os_value_changed);
Bram Moolenaardac13472019-09-16 21:06:21 +02004310#endif
4311 else if (varp == &(curbuf->b_p_ft))
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004312 do_filetype_autocmd(varp, opt_flags, args.os_value_changed);
Bram Moolenaardac13472019-09-16 21:06:21 +02004313#ifdef FEAT_SPELL
4314 if (varp == &(curwin->w_s->b_p_spl))
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004315 do_spelllang_source();
Bram Moolenaardac13472019-09-16 21:06:21 +02004316#endif
4317 }
4318
Bram Moolenaardac13472019-09-16 21:06:21 +02004319 if (varp == &p_mouse)
4320 {
Bram Moolenaardac13472019-09-16 21:06:21 +02004321 if (*p_mouse == NUL)
4322 mch_setmouse(FALSE); // switch mouse off
4323 else
Bram Moolenaardac13472019-09-16 21:06:21 +02004324 setmouse(); // in case 'mouse' changed
4325 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004326
Bram Moolenaar788fbb42020-05-31 14:08:12 +02004327#if defined(FEAT_LUA) || defined(PROTO)
4328 if (varp == &p_rtp)
4329 update_package_paths_in_lua();
4330#endif
4331
Bram Moolenaarb2d85e32022-01-07 16:55:32 +00004332#if defined(FEAT_LINEBREAK)
4333 // Changing Formatlistpattern when briopt includes the list setting:
4334 // redraw
4335 if ((varp == &p_flp || varp == &(curbuf->b_p_flp))
4336 && curwin->w_briopt_list)
Bram Moolenaara4d158b2022-08-14 14:17:45 +01004337 redraw_all_later(UPD_NOT_VALID);
Bram Moolenaarb2d85e32022-01-07 16:55:32 +00004338#endif
4339
Bram Moolenaardac13472019-09-16 21:06:21 +02004340 if (curwin->w_curswant != MAXCOL
Bram Moolenaara1cb1d12019-10-17 23:00:07 +02004341 && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaardac13472019-09-16 21:06:21 +02004342 curwin->w_set_curswant = TRUE;
4343
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004344 if ((opt_flags & OPT_NO_REDRAW) == 0)
4345 {
Bram Moolenaardac13472019-09-16 21:06:21 +02004346#ifdef FEAT_GUI
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004347 // set when changing an option that only requires a redraw in the GUI
4348 int redraw_gui_only = FALSE;
4349
4350 if (varp == &p_go // 'guioptions'
4351 || varp == &p_guifont // 'guifont'
4352# ifdef FEAT_GUI_TABLINE
4353 || varp == &p_gtl // 'guitablabel'
4354 || varp == &p_gtt // 'guitabtooltip'
4355# endif
4356# ifdef FEAT_XFONTSET
4357 || varp == &p_guifontset // 'guifontset'
4358# endif
4359 || varp == &p_guifontwide // 'guifontwide'
4360# ifdef FEAT_GUI_GTK
4361 || varp == &p_guiligatures // 'guiligatures'
4362# endif
4363 )
4364 redraw_gui_only = TRUE;
4365
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004366 // check redraw when it's not a GUI option or the GUI is active.
4367 if (!redraw_gui_only || gui.in_use)
Bram Moolenaardac13472019-09-16 21:06:21 +02004368#endif
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004369 check_redraw(get_option_flags(opt_idx));
4370 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004371
4372#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004373 if (args.os_did_swaptcap)
Bram Moolenaardac13472019-09-16 21:06:21 +02004374 {
4375 set_termname((char_u *)"win32");
4376 init_highlight(TRUE, FALSE);
4377 }
4378#endif
4379
4380 return errmsg;
4381}
4382
4383/*
4384 * Check an option that can be a range of string values.
4385 *
4386 * Return OK for correct value, FAIL otherwise.
4387 * Empty is always OK.
4388 */
4389 static int
4390check_opt_strings(
4391 char_u *val,
4392 char **values,
4393 int list) // when TRUE: accept a list of values
4394{
4395 return opt_strings_flags(val, values, NULL, list);
4396}
4397
4398/*
4399 * Handle an option that can be a range of string values.
4400 * Set a flag in "*flagp" for each string present.
4401 *
4402 * Return OK for correct value, FAIL otherwise.
4403 * Empty is always OK.
4404 */
4405 static int
4406opt_strings_flags(
4407 char_u *val, // new value
4408 char **values, // array of valid string values
4409 unsigned *flagp,
4410 int list) // when TRUE: accept a list of values
4411{
4412 int i;
4413 int len;
4414 unsigned new_flags = 0;
4415
4416 while (*val)
4417 {
4418 for (i = 0; ; ++i)
4419 {
4420 if (values[i] == NULL) // val not found in values[]
4421 return FAIL;
4422
4423 len = (int)STRLEN(values[i]);
4424 if (STRNCMP(values[i], val, len) == 0
4425 && ((list && val[len] == ',') || val[len] == NUL))
4426 {
4427 val += len + (val[len] == ',');
4428 new_flags |= (1 << i);
4429 break; // check next item in val list
4430 }
4431 }
4432 }
4433 if (flagp != NULL)
4434 *flagp = new_flags;
4435
4436 return OK;
4437}
4438
4439/*
4440 * return OK if "p" is a valid fileformat name, FAIL otherwise.
4441 */
4442 int
4443check_ff_value(char_u *p)
4444{
4445 return check_opt_strings(p, p_ff_values, FALSE);
4446}
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004447
4448/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004449 * Save the actual shortmess Flags and clear them temporarily to avoid that
4450 * file messages overwrites any output from the following commands.
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004451 *
4452 * Caller must make sure to first call save_clear_shm_value() and then
4453 * restore_shm_value() exactly the same number of times.
4454 */
4455 void
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +00004456save_clear_shm_value(void)
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004457{
4458 if (STRLEN(p_shm) >= SHM_LEN)
4459 {
4460 iemsg(e_internal_error_shortmess_too_long);
4461 return;
4462 }
4463
4464 if (++set_shm_recursive == 1)
4465 {
4466 STRCPY(shm_buf, p_shm);
4467 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
4468 }
4469}
4470
4471/*
4472 * Restore the shortmess Flags set from the save_clear_shm_value() function.
4473 */
4474 void
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +00004475restore_shm_value(void)
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004476{
4477 if (--set_shm_recursive == 0)
4478 {
4479 set_option_value_give_err((char_u *)"shm", 0L, shm_buf, 0);
4480 vim_memset(shm_buf, 0, SHM_LEN);
4481 }
4482}