blob: 88532ee5996b01fe5edb32653ee81ab928b426ef [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,
Yegappan Lakshmanana41e2212023-01-16 18:19:05 +0000582 opt_flags, &value_checked)) == NULL)
583 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
1581 if (STRCMP(curbuf->b_p_key, args->os_oldval.string) != 0)
1582 {
1583 // Need to update the swapfile.
1584 ml_set_crypt_key(curbuf, args->os_oldval.string,
1585 *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
1586 changed_internal();
1587 }
Christian Brabandt19e6c4f2023-06-27 18:57:10 +01001588# ifdef FEAT_SODIUM
1589 if (crypt_method_is_sodium(crypt_get_method_nr(curbuf)))
1590 crypt_sodium_lock_key(args->os_newval.string);
1591# endif
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001592
1593 return NULL;
1594}
1595
1596/*
1597 * The 'cryptmethod' option is changed.
1598 */
1599 char *
1600did_set_cryptmethod(optset_T *args)
1601{
1602 char_u *p;
1603 char_u *s;
1604
1605 if (args->os_flags & OPT_LOCAL)
1606 p = curbuf->b_p_cm;
1607 else
1608 p = p_cm;
1609 if (check_opt_strings(p, p_cm_values, TRUE) != OK)
1610 return e_invalid_argument;
1611 else if (crypt_self_test() == FAIL)
1612 return e_invalid_argument;
1613
1614 // When setting the global value to empty, make it "zip".
1615 if (*p_cm == NUL)
1616 {
1617 free_string_option(p_cm);
1618 p_cm = vim_strsave((char_u *)"zip");
1619 }
1620 // When using ":set cm=name" the local value is going to be empty.
1621 // Do that here, otherwise the crypt functions will still use the
1622 // local value.
1623 if ((args->os_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1624 {
1625 free_string_option(curbuf->b_p_cm);
1626 curbuf->b_p_cm = empty_option;
1627 }
1628
1629 // Need to update the swapfile when the effective method changed.
1630 // Set "s" to the effective old value, "p" to the effective new
1631 // method and compare.
1632 if ((args->os_flags & OPT_LOCAL) && *args->os_oldval.string == NUL)
1633 s = p_cm; // was previously using the global value
1634 else
1635 s = args->os_oldval.string;
1636 if (*curbuf->b_p_cm == NUL)
1637 p = p_cm; // is now using the global value
1638 else
1639 p = curbuf->b_p_cm;
1640 if (STRCMP(s, p) != 0)
1641 ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
1642
1643 // If the global value changes need to update the swapfile for all
1644 // buffers using that value.
1645 if ((args->os_flags & OPT_GLOBAL)
1646 && STRCMP(p_cm, args->os_oldval.string) != 0)
1647 {
1648 buf_T *buf;
1649
1650 FOR_ALL_BUFFERS(buf)
1651 if (buf != curbuf && *buf->b_p_cm == NUL)
1652 ml_set_crypt_key(buf, buf->b_p_key, args->os_oldval.string);
1653 }
1654 return NULL;
1655}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001656
1657 int
1658expand_set_cryptmethod(optexpand_T *args, int *numMatches, char_u ***matches)
1659{
1660 return expand_set_opt_string(
1661 args,
1662 p_cm_values,
1663 sizeof(p_cm_values) / sizeof(p_cm_values[0]) - 1,
1664 numMatches,
1665 matches);
1666}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001667#endif
1668
1669#if (defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)) || defined(PROTO)
1670/*
1671 * The 'cscopequickfix' option is changed.
1672 */
1673 char *
1674did_set_cscopequickfix(optset_T *args UNUSED)
1675{
1676 char_u *p;
1677
1678 if (p_csqf == NULL)
1679 return NULL;
1680
1681 p = p_csqf;
1682 while (*p != NUL)
1683 {
1684 if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
1685 || p[1] == NUL
1686 || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
1687 || (p[2] != NUL && p[2] != ','))
1688 return e_invalid_argument;
1689 else if (p[2] == NUL)
1690 break;
1691 else
1692 p += 3;
1693 }
1694
1695 return NULL;
1696}
1697#endif
1698
1699#if defined(FEAT_SYN_HL) || defined(PROTO)
1700/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001701 * The 'cursorlineopt' option is changed.
1702 */
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001703 char *
1704did_set_cursorlineopt(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001705{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001706 char_u **varp = (char_u **)args->os_varp;
1707
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001708 // This could be changed to use opt_strings_flags() instead.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001709 if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001710 return e_invalid_argument;
1711
1712 return NULL;
1713}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001714
1715 int
1716expand_set_cursorlineopt(optexpand_T *args, int *numMatches, char_u ***matches)
1717{
1718 return expand_set_opt_string(
1719 args,
1720 p_culopt_values,
1721 sizeof(p_culopt_values) / sizeof(p_culopt_values[0]) - 1,
1722 numMatches,
1723 matches);
1724}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001725#endif
1726
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001727/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001728 * The 'debug' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001729 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001730 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001731did_set_debug(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001732{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001733 return did_set_opt_strings(p_debug, p_debug_values, TRUE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001734}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001735
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001736 int
1737expand_set_debug(optexpand_T *args, int *numMatches, char_u ***matches)
1738{
1739 return expand_set_opt_string(
1740 args,
1741 p_debug_values,
1742 sizeof(p_debug_values) / sizeof(p_debug_values[0]) - 1,
1743 numMatches,
1744 matches);
1745}
1746
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001747#if defined(FEAT_DIFF) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001748/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001749 * The 'diffopt' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001750 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001751 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001752did_set_diffopt(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001753{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001754 if (diffopt_changed() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001755 return e_invalid_argument;
1756
1757 return NULL;
1758}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001759
1760 int
1761expand_set_diffopt(optexpand_T *args, int *numMatches, char_u ***matches)
1762{
1763 expand_T *xp = args->oe_xp;
1764
1765 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
1766 {
1767 // Within "algorithm:", we have a subgroup of possible options.
1768 int algo_len = STRLEN("algorithm:");
1769 if (xp->xp_pattern - args->oe_set_arg >= algo_len &&
1770 STRNCMP(xp->xp_pattern - algo_len, "algorithm:", algo_len) == 0)
1771 {
1772 return expand_set_opt_string(
1773 args,
1774 p_dip_algorithm_values,
1775 sizeof(p_dip_algorithm_values) / sizeof(p_dip_algorithm_values[0]) - 1,
1776 numMatches,
1777 matches);
1778 }
1779 return FAIL;
1780 }
1781
1782 return expand_set_opt_string(
1783 args,
1784 p_dip_values,
1785 sizeof(p_dip_values) / sizeof(p_dip_values[0]) - 1,
1786 numMatches,
1787 matches);
1788}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001789#endif
1790
1791/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001792 * The 'display' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001793 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001794 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001795did_set_display(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001796{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001797 if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001798 return e_invalid_argument;
1799
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001800 (void)init_chartab();
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001801 return NULL;
1802}
1803
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001804 int
1805expand_set_display(optexpand_T *args, int *numMatches, char_u ***matches)
1806{
1807 return expand_set_opt_string(
1808 args,
1809 p_dy_values,
1810 sizeof(p_dy_values) / sizeof(p_dy_values[0]) - 1,
1811 numMatches,
1812 matches);
1813}
1814
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001815/*
1816 * The 'eadirection' option is changed.
1817 */
1818 char *
1819did_set_eadirection(optset_T *args UNUSED)
1820{
1821 return did_set_opt_strings(p_ead, p_ead_values, FALSE);
1822}
1823
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001824 int
1825expand_set_eadirection(optexpand_T *args, int *numMatches, char_u ***matches)
1826{
1827 return expand_set_opt_string(
1828 args,
1829 p_ead_values,
1830 sizeof(p_ead_values) / sizeof(p_ead_values[0]) - 1,
1831 numMatches,
1832 matches);
1833}
1834
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00001835/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001836 * One of the 'encoding', 'fileencoding', 'termencoding' or 'makeencoding'
1837 * options is changed.
1838 */
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001839 char *
1840did_set_encoding(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001841{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001842 char_u **varp = (char_u **)args->os_varp;
1843 char_u **gvarp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001844 char *errmsg = NULL;
1845 char_u *p;
1846
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001847 // Get the global option to compare with, otherwise we would have to check
1848 // two values for all local options.
1849 gvarp = (char_u **)get_option_varp_scope(args->os_idx, OPT_GLOBAL);
1850
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001851 if (gvarp == &p_fenc)
1852 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001853 if (!curbuf->b_p_ma && args->os_flags != OPT_GLOBAL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001854 errmsg = e_cannot_make_changes_modifiable_is_off;
1855 else if (vim_strchr(*varp, ',') != NULL)
1856 // No comma allowed in 'fileencoding'; catches confusing it
1857 // with 'fileencodings'.
1858 errmsg = e_invalid_argument;
1859 else
1860 {
1861 // May show a "+" in the title now.
1862 redraw_titles();
1863 // Add 'fileencoding' to the swap file.
1864 ml_setflags(curbuf);
1865 }
1866 }
1867 if (errmsg == NULL)
1868 {
1869 // canonize the value, so that STRCMP() can be used on it
1870 p = enc_canonize(*varp);
1871 if (p != NULL)
1872 {
1873 vim_free(*varp);
1874 *varp = p;
1875 }
1876 if (varp == &p_enc)
1877 {
1878 errmsg = mb_init();
1879 redraw_titles();
1880 }
1881 }
1882
1883#if defined(FEAT_GUI_GTK)
1884 if (errmsg == NULL && varp == &p_tenc && gui.in_use)
1885 {
1886 // GTK uses only a single encoding, and that is UTF-8.
1887 if (STRCMP(p_tenc, "utf-8") != 0)
1888 errmsg = e_cannot_be_changed_in_gtk_GUI;
1889 }
1890#endif
1891
1892 if (errmsg == NULL)
1893 {
1894#ifdef FEAT_KEYMAP
1895 // When 'keymap' is used and 'encoding' changes, reload the keymap
1896 // (with another encoding).
1897 if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
1898 (void)keymap_init();
1899#endif
1900
1901 // When 'termencoding' is not empty and 'encoding' changes or when
1902 // 'termencoding' changes, need to setup for keyboard input and
1903 // display output conversion.
1904 if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
1905 {
1906 if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL
1907 || convert_setup(&output_conv, p_enc, p_tenc) == FAIL)
1908 {
1909 semsg(_(e_cannot_convert_between_str_and_str),
1910 p_tenc, p_enc);
1911 errmsg = e_invalid_argument;
1912 }
1913 }
1914
1915#if defined(MSWIN)
K.Takatace3189d2023-02-15 19:13:43 +00001916 // $HOME, $VIM and $VIMRUNTIME may have characters in active code page.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001917 if (varp == &p_enc)
K.Takatace3189d2023-02-15 19:13:43 +00001918 {
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001919 init_homedir();
K.Takatace3189d2023-02-15 19:13:43 +00001920 init_vimdir();
1921 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001922#endif
1923 }
1924
1925 return errmsg;
1926}
1927
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001928 int
1929expand_set_encoding(optexpand_T *args, int *numMatches, char_u ***matches)
1930{
1931 return expand_set_opt_generic(
1932 args,
1933 get_encoding_name,
1934 numMatches,
1935 matches);
1936}
1937
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001938/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001939 * The 'eventignore' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001940 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001941 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001942did_set_eventignore(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001943{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00001944 if (check_ei() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001945 return e_invalid_argument;
1946 return NULL;
1947}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001948
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001949 static char_u *
1950get_eventignore_name(expand_T *xp, int idx)
1951{
1952 // 'eventignore' allows special keyword "all" in addition to
1953 // all event names.
1954 if (idx == 0)
1955 return (char_u *)"all";
1956 return get_event_name_no_group(xp, idx - 1);
1957}
1958
1959 int
1960expand_set_eventignore(optexpand_T *args, int *numMatches, char_u ***matches)
1961{
1962 return expand_set_opt_generic(
1963 args,
1964 get_eventignore_name,
1965 numMatches,
1966 matches);
1967}
1968
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001969/*
1970 * The 'fileformat' option is changed.
1971 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001972 char *
1973did_set_fileformat(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001974{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001975 char_u **varp = (char_u **)args->os_varp;
1976
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001977 if (!curbuf->b_p_ma && !(args->os_flags & OPT_GLOBAL))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001978 return e_cannot_make_changes_modifiable_is_off;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00001979 else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001980 return e_invalid_argument;
1981
1982 // may also change 'textmode'
1983 if (get_fileformat(curbuf) == EOL_DOS)
1984 curbuf->b_p_tx = TRUE;
1985 else
1986 curbuf->b_p_tx = FALSE;
1987 redraw_titles();
1988 // update flag in swap file
1989 ml_setflags(curbuf);
1990 // Redraw needed when switching to/from "mac": a CR in the text
1991 // will be displayed differently.
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00001992 if (get_fileformat(curbuf) == EOL_MAC || *args->os_oldval.string == 'm')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00001993 redraw_curbuf_later(UPD_NOT_VALID);
1994
1995 return NULL;
1996}
1997
Yee Cheng Chin900894b2023-09-29 20:42:32 +02001998 int
1999expand_set_fileformat(optexpand_T *args, int *numMatches, char_u ***matches)
2000{
2001 return expand_set_opt_string(
2002 args,
2003 p_ff_values,
2004 sizeof(p_ff_values) / sizeof(p_ff_values[0]) - 1,
2005 numMatches,
2006 matches);
2007}
2008
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002009/*
2010 * The 'fileformats' option is changed.
2011 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002012 char *
2013did_set_fileformats(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002014{
2015 if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
2016 return e_invalid_argument;
2017
2018 // also change 'textauto'
2019 if (*p_ffs == NUL)
2020 p_ta = FALSE;
2021 else
2022 p_ta = TRUE;
2023
2024 return NULL;
2025}
2026
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002027/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002028 * The 'filetype' or the 'syntax' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002029 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002030 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002031did_set_filetype_or_syntax(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002032{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002033 char_u **varp = (char_u **)args->os_varp;
2034
2035 if (!valid_filetype(*varp))
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002036 return e_invalid_argument;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002037
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002038 args->os_value_changed = STRCMP(args->os_oldval.string, *varp) != 0;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002039
2040 // Since we check the value, there is no need to set P_INSECURE,
2041 // even when the value comes from a modeline.
2042 args->os_value_checked = TRUE;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002043
2044 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002045}
2046
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002047#if defined(FEAT_FOLDING) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002048/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002049 * The 'foldclose' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002050 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002051 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002052did_set_foldclose(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002053{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002054 return did_set_opt_strings(p_fcl, p_fcl_values, TRUE);
2055}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002056
2057 int
2058expand_set_foldclose(optexpand_T *args, int *numMatches, char_u ***matches)
2059{
2060 return expand_set_opt_string(
2061 args,
2062 p_fcl_values,
2063 sizeof(p_fcl_values) / sizeof(p_fcl_values[0]) - 1,
2064 numMatches,
2065 matches);
2066}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002067#endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002068
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002069#if (defined(FEAT_EVAL) && defined(FEAT_FOLDING)) || defined(PROTO)
2070/*
2071 * The 'foldexpr' option is changed.
2072 */
2073 char *
2074did_set_foldexpr(optset_T *args)
2075{
2076 (void)did_set_optexpr(args);
2077 if (foldmethodIsExpr(curwin))
2078 foldUpdateAll(curwin);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002079 return NULL;
2080}
2081#endif
2082
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002083#if defined(FEAT_FOLDING) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002084/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002085 * The 'foldignore' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002086 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002087 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002088did_set_foldignore(optset_T *args UNUSED)
2089{
2090 if (foldmethodIsIndent(curwin))
2091 foldUpdateAll(curwin);
2092 return NULL;
2093}
2094
2095/*
2096 * The 'foldmarker' option is changed.
2097 */
2098 char *
2099did_set_foldmarker(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002100{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002101 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002102 char_u *p;
2103
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002104 p = vim_strchr(*varp, ',');
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002105 if (p == NULL)
2106 return e_comma_required;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002107 else if (p == *varp || p[1] == NUL)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002108 return e_invalid_argument;
2109 else if (foldmethodIsMarker(curwin))
2110 foldUpdateAll(curwin);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002111
2112 return NULL;
2113}
2114
2115/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002116 * The 'foldmethod' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002117 */
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002118 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002119did_set_foldmethod(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002120{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002121 char_u **varp = (char_u **)args->os_varp;
2122
2123 if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002124 || *curwin->w_p_fdm == NUL)
2125 return e_invalid_argument;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002126
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002127 foldUpdateAll(curwin);
2128 if (foldmethodIsDiff(curwin))
2129 newFoldLevel();
2130 return NULL;
2131}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002132
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002133 int
2134expand_set_foldmethod(optexpand_T *args, int *numMatches, char_u ***matches)
2135{
2136 return expand_set_opt_string(
2137 args,
2138 p_fdm_values,
2139 sizeof(p_fdm_values) / sizeof(p_fdm_values[0]) - 1,
2140 numMatches,
2141 matches);
2142}
2143
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002144/*
2145 * The 'foldopen' option is changed.
2146 */
2147 char *
2148did_set_foldopen(optset_T *args UNUSED)
2149{
2150 return did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
2151}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002152
2153 int
2154expand_set_foldopen(optexpand_T *args, int *numMatches, char_u ***matches)
2155{
2156 return expand_set_opt_string(
2157 args,
2158 p_fdo_values,
2159 sizeof(p_fdo_values) / sizeof(p_fdo_values[0]) - 1,
2160 numMatches,
2161 matches);
2162}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002163#endif
2164
2165/*
2166 * The 'formatoptions' option is changed.
2167 */
2168 char *
2169did_set_formatoptions(optset_T *args)
2170{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002171 char_u **varp = (char_u **)args->os_varp;
2172
2173 return did_set_option_listflag(*varp, (char_u *)FO_ALL, args->os_errbuf);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002174}
2175
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002176 int
2177expand_set_formatoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2178{
2179 return expand_set_opt_listflag(args, (char_u*)FO_ALL, numMatches, matches);
2180}
2181
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002182#if defined(CURSOR_SHAPE) || defined(PROTO)
2183/*
2184 * The 'guicursor' option is changed.
2185 */
2186 char *
2187did_set_guicursor(optset_T *args UNUSED)
2188{
2189 return parse_shape_opt(SHAPE_CURSOR);
2190}
2191#endif
2192
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002193#if defined(FEAT_GUI) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002194/*
2195 * The 'guifont' option is changed.
2196 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002197 char *
2198did_set_guifont(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002199{
2200 char_u *p;
2201 char *errmsg = NULL;
2202
2203 if (gui.in_use)
2204 {
2205 p = p_guifont;
2206# if defined(FEAT_GUI_GTK)
2207 // Put up a font dialog and let the user select a new value.
2208 // If this is cancelled go back to the old value but don't
2209 // give an error message.
2210 if (STRCMP(p, "*") == 0)
2211 {
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002212 p = gui_mch_font_dialog(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002213 free_string_option(p_guifont);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002214 p_guifont = (p != NULL) ? p : vim_strsave(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002215 }
2216# endif
2217 if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
2218 {
2219# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
2220 if (STRCMP(p_guifont, "*") == 0)
2221 {
2222 // Dialog was cancelled: Keep the old value without giving
2223 // an error message.
2224 free_string_option(p_guifont);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002225 p_guifont = vim_strsave(args->os_oldval.string);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002226 }
2227 else
2228# endif
2229 errmsg = e_invalid_fonts;
2230 }
2231 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002232
2233 return errmsg;
2234}
2235
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002236# if defined(FEAT_XFONTSET) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002237/*
2238 * The 'guifontset' option is changed.
2239 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002240 char *
2241did_set_guifontset(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002242{
2243 char *errmsg = NULL;
2244
2245 if (STRCMP(p_guifontset, "*") == 0)
2246 errmsg = e_cant_select_fontset;
2247 else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
2248 errmsg = e_invalid_fontset;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002249
2250 return errmsg;
2251}
2252# endif
2253
2254/*
2255 * The 'guifontwide' option is changed.
2256 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002257 char *
2258did_set_guifontwide(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002259{
2260 char *errmsg = NULL;
2261
2262 if (STRCMP(p_guifontwide, "*") == 0)
2263 errmsg = e_cant_select_wide_font;
2264 else if (gui_get_wide_font() == FAIL)
2265 errmsg = e_invalid_wide_font;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002266
2267 return errmsg;
2268}
2269#endif
2270
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002271#if defined(FEAT_GUI_GTK) || defined(PROTO)
2272/*
2273 * The 'guiligatures' option is changed.
2274 */
2275 char *
2276did_set_guiligatures(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002277{
2278 gui_set_ligatures();
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002279 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002280}
2281#endif
2282
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002283#if defined(FEAT_GUI) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002284/*
2285 * The 'guioptions' option is changed.
2286 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002287 char *
2288did_set_guioptions(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002289{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002290 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002291 char *errmsg;
2292
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002293 errmsg = did_set_option_listflag(*varp, (char_u *)GO_ALL, args->os_errbuf);
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00002294 if (errmsg != NULL)
2295 return errmsg;
2296
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002297 gui_init_which_components(args->os_oldval.string);
2298 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002299}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002300
2301 int
2302expand_set_guioptions(optexpand_T *args, int *numMatches, char_u ***matches)
2303{
2304 return expand_set_opt_listflag(args, (char_u*)GO_ALL, numMatches, matches);
2305}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002306#endif
2307
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002308#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002309/*
2310 * The 'guitablabel' option is changed.
2311 */
2312 char *
2313did_set_guitablabel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002314{
2315 redraw_tabline = TRUE;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002316 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002317}
2318#endif
2319
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002320/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002321 * The 'helpfile' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002322 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002323 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002324did_set_helpfile(optset_T *args UNUSED)
2325{
2326 // May compute new values for $VIM and $VIMRUNTIME
2327 if (didset_vim)
2328 vim_unsetenv_ext((char_u *)"VIM");
2329 if (didset_vimruntime)
2330 vim_unsetenv_ext((char_u *)"VIMRUNTIME");
2331 return NULL;
2332}
2333
2334#if defined(FEAT_MULTI_LANG) || defined(PROTO)
2335/*
2336 * The 'helplang' option is changed.
2337 */
2338 char *
2339did_set_helplang(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002340{
2341 char *errmsg = NULL;
2342
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002343 // Check for "", "ab", "ab,cd", etc.
2344 for (char_u *s = p_hlg; *s != NUL; s += 3)
2345 {
2346 if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
2347 {
2348 errmsg = e_invalid_argument;
2349 break;
2350 }
2351 if (s[2] == NUL)
2352 break;
2353 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002354
2355 return errmsg;
2356}
2357#endif
2358
2359/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002360 * The 'highlight' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002361 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002362 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002363did_set_highlight(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002364{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002365 if (highlight_changed() == FAIL)
2366 return e_invalid_argument; // invalid flags
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002367
2368 return NULL;
2369}
2370
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002371/*
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002372 * Expand 'highlight' option.
2373 */
2374 int
2375expand_set_highlight(optexpand_T *args, int *numMatches, char_u ***matches)
2376{
2377 char_u *p;
2378 expand_T *xp = args->oe_xp;
2379 static char_u hl_flags[HLF_COUNT] = HL_FLAGS;
2380 int i;
2381 int count = 0;
2382
2383 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2384 {
2385 // Right after a ':', meaning we just return all highlight names.
2386 return expand_set_opt_generic(
2387 args,
2388 get_highlight_name,
2389 numMatches,
2390 matches);
2391 }
2392
2393 if (*xp->xp_pattern == NUL)
2394 {
2395 // At beginning of a comma-separated list. Return the specific list of
2396 // supported occasions.
2397 *matches = ALLOC_MULT(char_u *, HLF_COUNT + 1);
2398 if (*matches == NULL)
2399 return FAIL;
2400
2401 // We still want to return the full option if it's requested.
2402 if (args->oe_include_orig_val)
2403 {
2404 p = vim_strsave(args->oe_opt_value);
2405 if (p == NULL)
2406 {
2407 VIM_CLEAR(*matches);
2408 return FAIL;
2409 }
2410 (*matches)[count++] = p;
2411 }
2412
2413 for (i = 0; i < HLF_COUNT; i++)
2414 {
2415 p = vim_strnsave(&hl_flags[i], 1);
2416 if (p == NULL)
2417 {
2418 if (count == 0)
2419 {
2420 VIM_CLEAR(*matches);
2421 return FAIL;
2422 }
2423 else
2424 break;
2425 }
2426 (*matches)[count++] = p;
2427 }
2428
2429 if (count == 0)
2430 {
2431 VIM_CLEAR(*matches);
2432 return FAIL;
2433 }
2434 *numMatches = count;
2435 return OK;
2436 }
2437
2438 // We are after the initial character (which indicates the occasion). We
2439 // already made sure we are not matching after a ':' above, so now we want
2440 // to match against display mode modifiers.
2441 // Since the xp_pattern starts from the beginning, we need to include it in
2442 // the returned match.
2443
2444 // Note: Keep this in sync with highlight_changed()
2445 static char p_hl_mode_values[] =
2446 {':', 'b', 'i', '-', 'n', 'r', 's', 'u', 'c', '2', 'd', '=', 't'};
2447 int num_hl_modes = sizeof(p_hl_mode_values) / sizeof(p_hl_mode_values[0]);
2448
2449 *matches = ALLOC_MULT(char_u *, num_hl_modes);
2450 if (*matches == NULL)
2451 return FAIL;
2452
2453 int pattern_len = STRLEN(xp->xp_pattern);
2454
2455 for (i = 0; i < num_hl_modes; i++)
2456 {
2457 // Don't allow duplicates as these are unique flags
2458 if (vim_strchr(xp->xp_pattern + 1, p_hl_mode_values[i]) != NULL)
2459 continue;
2460
2461 // ':' only works by itself, not with other flags.
2462 if (pattern_len > 1 && p_hl_mode_values[i] == ':')
2463 continue;
2464
2465 p = vim_strnsave(xp->xp_pattern, pattern_len + 1);
2466 if (p == NULL)
2467 {
2468 if (i == 0)
2469 {
2470 VIM_CLEAR(*matches);
2471 return FAIL;
2472 }
2473 else
2474 break;
2475 }
2476 p[pattern_len] = p_hl_mode_values[i];
2477 p[pattern_len + 1] = NUL;
2478 (*matches)[count++] = p;
2479 }
2480 if (count == 0)
2481 {
2482 VIM_CLEAR(*matches);
2483 return FAIL;
2484 }
2485 *numMatches = count;
2486
2487 return OK;
2488}
2489
2490/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002491 * The 'titlestring' or the 'iconstring' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002492 */
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002493 static char *
2494parse_titleiconstring(optset_T *args UNUSED, int flagval UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002495{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002496#ifdef FEAT_STL_OPT
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002497 char_u **varp = (char_u **)args->os_varp;
2498
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002499 // NULL => statusline syntax
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002500 if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002501 stl_syntax |= flagval;
2502 else
2503 stl_syntax &= ~flagval;
2504#endif
2505 did_set_title();
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002506
2507 return NULL;
2508}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002509
2510/*
2511 * The 'iconstring' option is changed.
2512 */
2513 char *
2514did_set_iconstring(optset_T *args)
2515{
2516 int flagval = 0;
2517
2518#ifdef FEAT_STL_OPT
2519 flagval = STL_IN_ICON;
2520#endif
2521
2522 return parse_titleiconstring(args, flagval);
2523}
2524
2525#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) || defined(PROTO)
2526/*
2527 * The 'imactivatekey' option is changed.
2528 */
2529 char *
2530did_set_imactivatekey(optset_T *args UNUSED)
2531{
2532 if (!im_xim_isvalid_imactivate())
2533 return e_invalid_argument;
2534 return NULL;
2535}
2536#endif
2537
2538/*
2539 * The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is
2540 * changed.
2541 */
2542 char *
2543did_set_isopt(optset_T *args)
2544{
2545 // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
2546 // If the new option is invalid, use old value.
2547 // 'lisp' option: refill g_chartab[] for '-' char.
2548 if (init_chartab() == FAIL)
2549 {
2550 args->os_restore_chartab = TRUE;// need to restore the chartab.
2551 return e_invalid_argument; // error in value
2552 }
2553
2554 return NULL;
2555}
2556
Yegappan Lakshmanan87018252023-09-20 20:20:04 +02002557/*
2558 * The 'jumpoptions' option is changed.
2559 */
2560 char *
Yegappan Lakshmanan1926ae42023-09-21 16:36:28 +02002561did_set_jumpoptions(optset_T *args UNUSED)
Yegappan Lakshmanan87018252023-09-20 20:20:04 +02002562{
2563 if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, TRUE) != OK)
2564 return e_invalid_argument;
2565
2566 return NULL;
2567}
2568
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002569 int
2570expand_set_jumpoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2571{
2572 return expand_set_opt_string(
2573 args,
2574 p_jop_values,
2575 sizeof(p_jop_values) / sizeof(p_jop_values[0]) - 1,
2576 numMatches,
2577 matches);
2578}
2579
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002580#if defined(FEAT_KEYMAP) || defined(PROTO)
2581/*
2582 * The 'keymap' option is changed.
2583 */
2584 char *
2585did_set_keymap(optset_T *args)
2586{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002587 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002588 char *errmsg = NULL;
2589
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002590 if (!valid_filetype(*varp))
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002591 errmsg = e_invalid_argument;
2592 else
2593 {
2594 int secure_save = secure;
2595
2596 // Reset the secure flag, since the value of 'keymap' has
2597 // been checked to be safe.
2598 secure = 0;
2599
2600 // load or unload key mapping tables
2601 errmsg = keymap_init();
2602
2603 secure = secure_save;
2604
2605 // Since we check the value, there is no need to set P_INSECURE,
2606 // even when the value comes from a modeline.
2607 args->os_value_checked = TRUE;
2608 }
2609
2610 if (errmsg == NULL)
2611 {
2612 if (*curbuf->b_p_keymap != NUL)
2613 {
2614 // Installed a new keymap, switch on using it.
2615 curbuf->b_p_iminsert = B_IMODE_LMAP;
2616 if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
2617 curbuf->b_p_imsearch = B_IMODE_LMAP;
2618 }
2619 else
2620 {
2621 // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
2622 if (curbuf->b_p_iminsert == B_IMODE_LMAP)
2623 curbuf->b_p_iminsert = B_IMODE_NONE;
2624 if (curbuf->b_p_imsearch == B_IMODE_LMAP)
2625 curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
2626 }
2627 if ((args->os_flags & OPT_LOCAL) == 0)
2628 {
2629 set_iminsert_global();
2630 set_imsearch_global();
2631 }
2632 status_redraw_curbuf();
2633 }
2634
2635 return errmsg;
2636}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002637#endif
2638
2639/*
2640 * The 'keymodel' option is changed.
2641 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002642 char *
2643did_set_keymodel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002644{
2645 if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
2646 return e_invalid_argument;
2647
2648 km_stopsel = (vim_strchr(p_km, 'o') != NULL);
2649 km_startsel = (vim_strchr(p_km, 'a') != NULL);
2650 return NULL;
2651}
2652
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002653 int
2654expand_set_keymodel(optexpand_T *args, int *numMatches, char_u ***matches)
2655{
2656 return expand_set_opt_string(
2657 args,
2658 p_km_values,
2659 sizeof(p_km_values) / sizeof(p_km_values[0]) - 1,
2660 numMatches,
2661 matches);
2662}
2663
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002664/*
2665 * The 'keyprotocol' option is changed.
2666 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002667 char *
2668did_set_keyprotocol(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002669{
Gregory Anders3695d0e2023-09-29 20:17:20 +02002670 char_u *term = T_NAME;
2671 keyprot_T kpc = match_keyprotocol(term);
2672 if (kpc == KEYPROTOCOL_FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002673 return e_invalid_argument;
2674
Gregory Anders3695d0e2023-09-29 20:17:20 +02002675 apply_keyprotocol(term, kpc);
2676
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002677 return NULL;
2678}
2679
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002680 int
2681expand_set_keyprotocol(optexpand_T *args, int *numMatches, char_u ***matches)
2682{
2683 expand_T *xp = args->oe_xp;
2684 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2685 {
2686 // 'keyprotocol' only has well-defined terms for completion for the
2687 // protocol part after the colon.
2688 return expand_set_opt_string(
2689 args,
2690 p_kpc_protocol_values,
2691 sizeof(p_kpc_protocol_values) / sizeof(p_kpc_protocol_values[0]) - 1,
2692 numMatches,
2693 matches);
2694 }
2695 // Use expand_set_opt_string instead of returning FAIL so that we can
2696 // include the original value if args->oe_include_orig_val is set.
2697 static char *(empty[]) = {NULL};
2698 return expand_set_opt_string(args, empty, 0, numMatches, matches);
2699}
2700
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002701/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002702 * The 'lispoptions' option is changed.
2703 */
2704 char *
2705did_set_lispoptions(optset_T *args)
2706{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002707 char_u **varp = (char_u **)args->os_varp;
2708
2709 if (**varp != NUL
2710 && STRCMP(*varp, "expr:0") != 0
2711 && STRCMP(*varp, "expr:1") != 0)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002712 return e_invalid_argument;
2713
2714 return NULL;
2715}
2716
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002717 int
2718expand_set_lispoptions(optexpand_T *args, int *numMatches, char_u ***matches)
2719{
2720 static char *(p_lop_values[]) = {"expr:0", "expr:1", NULL};
2721 return expand_set_opt_string(
2722 args,
2723 p_lop_values,
2724 sizeof(p_lop_values) / sizeof(p_lop_values[0]) - 1,
2725 numMatches,
2726 matches);
2727}
2728
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002729/*
2730 * The 'matchpairs' option is changed.
2731 */
2732 char *
2733did_set_matchpairs(optset_T *args)
2734{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002735 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002736 char_u *p;
2737
2738 if (has_mbyte)
2739 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002740 for (p = *varp; *p != NUL; ++p)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002741 {
2742 int x2 = -1;
2743 int x3 = -1;
2744
2745 p += mb_ptr2len(p);
2746 if (*p != NUL)
2747 x2 = *p++;
2748 if (*p != NUL)
2749 {
2750 x3 = mb_ptr2char(p);
2751 p += mb_ptr2len(p);
2752 }
2753 if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ','))
2754 return e_invalid_argument;
2755 if (*p == NUL)
2756 break;
2757 }
2758 }
2759 else
2760 {
2761 // Check for "x:y,x:y"
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002762 for (p = *varp; *p != NUL; p += 4)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002763 {
2764 if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
2765 return e_invalid_argument;
2766 if (p[3] == NUL)
2767 break;
2768 }
2769 }
2770
2771 return NULL;
2772}
2773
2774#if defined(FEAT_SPELL) || defined(PROTO)
2775/*
2776 * The 'mkspellmem' option is changed.
2777 */
2778 char *
2779did_set_mkspellmem(optset_T *args UNUSED)
2780{
2781 if (spell_check_msm() != OK)
2782 return e_invalid_argument;
2783
2784 return NULL;
2785}
2786#endif
2787
2788/*
2789 * The 'mouse' option is changed.
2790 */
2791 char *
2792did_set_mouse(optset_T *args)
2793{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002794 char_u **varp = (char_u **)args->os_varp;
2795
2796 return did_set_option_listflag(*varp, (char_u *)MOUSE_ALL,
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002797 args->os_errbuf);
2798}
2799
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002800 int
2801expand_set_mouse(optexpand_T *args, int *numMatches, char_u ***matches)
2802{
2803 return expand_set_opt_listflag(args, (char_u*)MOUSE_ALL, numMatches, matches);
2804}
2805
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002806/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002807 * The 'mousemodel' option is changed.
2808 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002809 char *
2810did_set_mousemodel(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002811{
2812 if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
2813 return e_invalid_argument;
2814#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
2815 else if (*p_mousem != *oldval)
2816 // Changed from "extend" to "popup" or "popup_setpos" or vv: need
2817 // to create or delete the popup menus.
2818 gui_motif_update_mousemodel(root_menu);
2819#endif
2820
2821 return NULL;
2822}
2823
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002824 int
2825expand_set_mousemodel(optexpand_T *args, int *numMatches, char_u ***matches)
2826{
2827 return expand_set_opt_string(
2828 args,
2829 p_mousem_values,
2830 sizeof(p_mousem_values) / sizeof(p_mousem_values[0]) - 1,
2831 numMatches,
2832 matches);
2833}
2834
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002835#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
2836 char *
2837did_set_mouseshape(optset_T *args UNUSED)
2838{
2839 char *errmsg = NULL;
2840
2841 errmsg = parse_shape_opt(SHAPE_MOUSE);
2842 update_mouseshape(-1);
2843
2844 return errmsg;
2845}
2846#endif
2847
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002848/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002849 * The 'nrformats' option is changed.
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00002850 */
2851 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002852did_set_nrformats(optset_T *args)
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00002853{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002854 char_u **varp = (char_u **)args->os_varp;
2855
2856 return did_set_opt_strings(*varp, p_nf_values, TRUE);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002857}
2858
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002859 int
2860expand_set_nrformats(optexpand_T *args, int *numMatches, char_u ***matches)
2861{
2862 return expand_set_opt_string(
2863 args,
2864 p_nf_values,
2865 sizeof(p_nf_values) / sizeof(p_nf_values[0]) - 1,
2866 numMatches,
2867 matches);
2868}
2869
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002870#if defined(FEAT_EVAL) || defined(PROTO)
2871/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002872 * One of the '*expr' options is changed: 'balloonexpr', 'diffexpr',
2873 * 'foldexpr', 'foldtext', 'formatexpr', 'includeexpr', 'indentexpr',
2874 * 'patchexpr', 'printexpr' and 'charconvert'.
2875 *
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002876 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00002877 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002878did_set_optexpr(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002879{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002880 char_u **varp = (char_u **)args->os_varp;
2881
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002882 // If the option value starts with <SID> or s:, then replace that with
2883 // the script identifier.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002884 char_u *name = get_scriptlocal_funcname(*varp);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002885 if (name != NULL)
2886 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00002887 free_string_option(*varp);
2888 *varp = name;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002889 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002890
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002891 return NULL;
2892}
2893#endif
2894
2895/*
2896 * The 'pastetoggle' option is changed.
2897 */
2898 char *
2899did_set_pastetoggle(optset_T *args UNUSED)
2900{
2901 char_u *p;
2902
2903 // translate key codes like in a mapping
2904 if (*p_pt)
2905 {
zeertzjq7e0bae02023-08-11 23:15:38 +02002906 (void)replace_termcodes(p_pt, &p, 0,
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002907 REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
2908 if (p != NULL)
2909 {
2910 free_string_option(p_pt);
2911 p_pt = p;
2912 }
2913 }
2914
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00002915 return NULL;
2916}
2917
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002918#if defined(FEAT_PROP_POPUP) || defined(PROTO)
2919/*
2920 * The 'previewpopup' option is changed.
2921 */
2922 char *
2923did_set_previewpopup(optset_T *args UNUSED)
2924{
2925 if (parse_previewpopup(NULL) == FAIL)
2926 return e_invalid_argument;
2927
2928 return NULL;
2929}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02002930
2931 int
2932expand_set_popupoption(optexpand_T *args, int *numMatches, char_u ***matches)
2933{
2934 expand_T *xp = args->oe_xp;
2935
2936 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2937 {
2938 // Within "highlight:"/"border:"/"align:", we have a subgroup of possible options.
2939 int border_len = STRLEN("border:");
2940 if (xp->xp_pattern - args->oe_set_arg >= border_len &&
2941 STRNCMP(xp->xp_pattern - border_len, "border:", border_len) == 0)
2942 {
2943 return expand_set_opt_string(
2944 args,
2945 p_popup_option_border_values,
2946 sizeof(p_popup_option_border_values) / sizeof(p_popup_option_border_values[0]) - 1,
2947 numMatches,
2948 matches);
2949 }
2950 int align_len = STRLEN("align:");
2951 if (xp->xp_pattern - args->oe_set_arg >= align_len &&
2952 STRNCMP(xp->xp_pattern - align_len, "align:", align_len) == 0)
2953 {
2954 return expand_set_opt_string(
2955 args,
2956 p_popup_option_align_values,
2957 sizeof(p_popup_option_align_values) / sizeof(p_popup_option_align_values[0]) - 1,
2958 numMatches,
2959 matches);
2960 }
2961 int highlight_len = STRLEN("highlight:");
2962 if (xp->xp_pattern - args->oe_set_arg >= highlight_len &&
2963 STRNCMP(xp->xp_pattern - highlight_len, "highlight:", highlight_len) == 0)
2964 {
2965 // Return the list of all highlight names
2966 return expand_set_opt_generic(
2967 args,
2968 get_highlight_name,
2969 numMatches,
2970 matches);
2971 }
2972 return FAIL;
2973 }
2974
2975 return expand_set_opt_string(
2976 args,
2977 p_popup_option_values,
2978 sizeof(p_popup_option_values) / sizeof(p_popup_option_values[0]) - 1,
2979 numMatches,
2980 matches);
2981}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00002982#endif
2983
2984#if defined(FEAT_POSTSCRIPT) || defined(PROTO)
2985/*
2986 * The 'printencoding' option is changed.
2987 */
2988 char *
2989did_set_printencoding(optset_T *args UNUSED)
2990{
2991 char_u *s, *p;
2992
2993 // Canonize 'printencoding' if VIM standard one
2994 p = enc_canonize(p_penc);
2995 if (p != NULL)
2996 {
2997 vim_free(p_penc);
2998 p_penc = p;
2999 }
3000 else
3001 {
3002 // Ensure lower case and '-' for '_'
3003 for (s = p_penc; *s != NUL; s++)
3004 {
3005 if (*s == '_')
3006 *s = '-';
3007 else
3008 *s = TOLOWER_ASC(*s);
3009 }
3010 }
3011
3012 return NULL;
3013}
3014#endif
3015
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003016#if defined(FEAT_PRINTER) || defined(PROTO)
3017
3018 static char_u *
3019get_printoptions_names(expand_T *xp UNUSED, int idx)
3020{
3021 if (idx >= (int)(sizeof(printer_opts) / sizeof(printer_opts[0])))
3022 return NULL;
3023 return (char_u*)printer_opts[idx].name;
3024}
3025
3026/*
3027 * Expand 'printoptions' option
3028 */
3029 int
3030expand_set_printoptions(optexpand_T *args, int *numMatches, char_u ***matches)
3031{
3032 return expand_set_opt_generic(
3033 args,
3034 get_printoptions_names,
3035 numMatches,
3036 matches);
3037}
3038#endif
3039
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003040#if defined(FEAT_STL_OPT) || defined(PROTO)
3041/*
3042 * The 'statusline' or the 'tabline' or the 'rulerformat' option is changed.
3043 * "rulerformat" is TRUE if the 'rulerformat' option is changed.
3044 */
3045 static char *
3046parse_statustabline_rulerformat(optset_T *args, int rulerformat)
3047{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003048 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003049 char_u *s;
3050 char *errmsg = NULL;
3051 int wid;
3052
3053 if (rulerformat) // reset ru_wid first
3054 ru_wid = 0;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003055 s = *varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003056 if (rulerformat && *s == '%')
3057 {
3058 // set ru_wid if 'ruf' starts with "%99("
3059 if (*++s == '-') // ignore a '-'
3060 s++;
3061 wid = getdigits(&s);
3062 if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
3063 ru_wid = wid;
3064 else
3065 errmsg = check_stl_option(p_ruf);
3066 }
3067 // check 'statusline' or 'tabline' only if it doesn't start with "%!"
3068 else if (rulerformat || s[0] != '%' || s[1] != '!')
3069 errmsg = check_stl_option(s);
3070 if (rulerformat && errmsg == NULL)
3071 comp_col();
3072
3073 return errmsg;
3074}
3075#endif
3076
3077#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
3078/*
3079 * The 'renderoptions' option is changed.
3080 */
3081 char *
3082did_set_renderoptions(optset_T *args UNUSED)
3083{
3084 if (!gui_mch_set_rendering_options(p_rop))
3085 return e_invalid_argument;
3086
3087 return NULL;
3088}
3089#endif
3090
3091#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
3092/*
3093 * The 'rightleftcmd' option is changed.
3094 */
3095 char *
3096did_set_rightleftcmd(optset_T *args)
3097{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003098 char_u **varp = (char_u **)args->os_varp;
3099
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003100 // Currently only "search" is a supported value.
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003101 if (**varp != NUL && STRCMP(*varp, "search") != 0)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003102 return e_invalid_argument;
3103
3104 return NULL;
3105}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003106
3107 int
3108expand_set_rightleftcmd(optexpand_T *args, int *numMatches, char_u ***matches)
3109{
3110 static char *(p_rlc_values[]) = {"search", NULL};
3111 return expand_set_opt_string(
3112 args,
3113 p_rlc_values,
3114 sizeof(p_rlc_values) / sizeof(p_rlc_values[0]) - 1,
3115 numMatches,
3116 matches);
3117}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003118#endif
3119
3120#if defined(FEAT_STL_OPT) || defined(PROTO)
3121/*
3122 * The 'rulerformat' option is changed.
3123 */
3124 char *
3125did_set_rulerformat(optset_T *args)
3126{
3127 return parse_statustabline_rulerformat(args, TRUE);
3128}
3129#endif
3130
3131/*
3132 * The 'scrollopt' option is changed.
3133 */
3134 char *
3135did_set_scrollopt(optset_T *args UNUSED)
3136{
3137 return did_set_opt_strings(p_sbo, p_scbopt_values, TRUE);
3138}
3139
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003140 int
3141expand_set_scrollopt(optexpand_T *args, int *numMatches, char_u ***matches)
3142{
3143 return expand_set_opt_string(
3144 args,
3145 p_scbopt_values,
3146 sizeof(p_scbopt_values) / sizeof(p_scbopt_values[0]) - 1,
3147 numMatches,
3148 matches);
3149}
3150
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003151/*
3152 * The 'selection' option is changed.
3153 */
3154 char *
3155did_set_selection(optset_T *args UNUSED)
3156{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003157 if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003158 return e_invalid_argument;
3159
3160 return NULL;
3161}
3162
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003163 int
3164expand_set_selection(optexpand_T *args, int *numMatches, char_u ***matches)
3165{
3166 return expand_set_opt_string(
3167 args,
3168 p_sel_values,
3169 sizeof(p_sel_values) / sizeof(p_sel_values[0]) - 1,
3170 numMatches,
3171 matches);
3172}
3173
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003174/*
3175 * The 'selectmode' option is changed.
3176 */
3177 char *
3178did_set_selectmode(optset_T *args UNUSED)
3179{
3180 return did_set_opt_strings(p_slm, p_slm_values, TRUE);
3181}
3182
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003183 int
3184expand_set_selectmode(optexpand_T *args, int *numMatches, char_u ***matches)
3185{
3186 return expand_set_opt_string(
3187 args,
3188 p_slm_values,
3189 sizeof(p_slm_values) / sizeof(p_slm_values[0]) - 1,
3190 numMatches,
3191 matches);
3192}
3193
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003194#if defined(FEAT_SESSION) || defined(PROTO)
3195/*
3196 * The 'sessionoptions' option is changed.
3197 */
3198 char *
3199did_set_sessionoptions(optset_T *args)
3200{
3201 if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
3202 return e_invalid_argument;
3203 if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR))
3204 {
3205 // Don't allow both "sesdir" and "curdir".
3206 (void)opt_strings_flags(args->os_oldval.string, p_ssop_values,
3207 &ssop_flags, TRUE);
3208 return e_invalid_argument;
3209 }
3210
3211 return NULL;
3212}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003213
3214 int
3215expand_set_sessionoptions(optexpand_T *args, int *numMatches, char_u ***matches)
3216{
3217 return expand_set_opt_string(
3218 args,
3219 p_ssop_values,
3220 sizeof(p_ssop_values) / sizeof(p_ssop_values[0]) - 1,
3221 numMatches,
3222 matches);
3223}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003224#endif
3225
3226/*
3227 * The 'shortmess' option is changed.
3228 */
3229 char *
3230did_set_shortmess(optset_T *args)
3231{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003232 char_u **varp = (char_u **)args->os_varp;
3233
3234 return did_set_option_listflag(*varp, (char_u *)SHM_ALL, args->os_errbuf);
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003235}
3236
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003237 int
3238expand_set_shortmess(optexpand_T *args, int *numMatches, char_u ***matches)
3239{
3240 return expand_set_opt_listflag(args, (char_u*)SHM_ALL, numMatches, matches);
3241}
3242
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003243#if defined(FEAT_LINEBREAK) || defined(PROTO)
3244/*
3245 * The 'showbreak' option is changed.
3246 */
3247 char *
3248did_set_showbreak(optset_T *args)
3249{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003250 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003251 char_u *s;
3252
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003253 for (s = *varp; *s; )
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003254 {
3255 if (ptr2cells(s) != 1)
3256 return e_showbreak_contains_unprintable_or_wide_character;
3257 MB_PTR_ADV(s);
3258 }
3259
3260 return NULL;
3261}
3262#endif
3263
3264/*
3265 * The 'showcmdloc' option is changed.
3266 */
3267 char *
3268did_set_showcmdloc(optset_T *args UNUSED)
3269{
3270 return did_set_opt_strings(p_sloc, p_sloc_values, FALSE);
3271}
3272
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003273 int
3274expand_set_showcmdloc(optexpand_T *args, int *numMatches, char_u ***matches)
3275{
3276 return expand_set_opt_string(
3277 args,
3278 p_sloc_values,
3279 sizeof(p_sloc_values) / sizeof(p_sloc_values[0]) - 1,
3280 numMatches,
3281 matches);
3282}
3283
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003284#if defined(FEAT_SIGNS) || defined(PROTO)
3285/*
3286 * The 'signcolumn' option is changed.
3287 */
3288 char *
3289did_set_signcolumn(optset_T *args)
3290{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003291 char_u **varp = (char_u **)args->os_varp;
3292
3293 if (check_opt_strings(*varp, p_scl_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003294 return e_invalid_argument;
3295 // When changing the 'signcolumn' to or from 'number', recompute the
3296 // width of the number column if 'number' or 'relativenumber' is set.
3297 if (((*args->os_oldval.string == 'n' && args->os_oldval.string[1] == 'u')
3298 || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u'))
3299 && (curwin->w_p_nu || curwin->w_p_rnu))
3300 curwin->w_nrwidth_line_count = 0;
3301
3302 return NULL;
3303}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003304
3305 int
3306expand_set_signcolumn(optexpand_T *args, int *numMatches, char_u ***matches)
3307{
3308 return expand_set_opt_string(
3309 args,
3310 p_scl_values,
3311 sizeof(p_scl_values) / sizeof(p_scl_values[0]) - 1,
3312 numMatches,
3313 matches);
3314}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003315#endif
3316
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003317#if defined(FEAT_SPELL) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003318/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003319 * The 'spellcapcheck' option is changed.
3320 */
3321 char *
3322did_set_spellcapcheck(optset_T *args UNUSED)
3323{
3324 // compile the regexp program.
3325 return compile_cap_prog(curwin->w_s);
3326}
3327
3328/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003329 * The 'spellfile' option is changed.
3330 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003331 char *
3332did_set_spellfile(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003333{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003334 char_u **varp = (char_u **)args->os_varp;
3335
3336 if (!valid_spellfile(*varp))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003337 return e_invalid_argument;
3338
3339 // If there is a window for this buffer in which 'spell' is set load the
3340 // wordlists.
3341 return did_set_spell_option(TRUE);
3342}
3343
3344/*
3345 * The 'spell' option is changed.
3346 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003347 char *
3348did_set_spelllang(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003349{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003350 char_u **varp = (char_u **)args->os_varp;
3351
3352 if (!valid_spelllang(*varp))
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003353 return e_invalid_argument;
3354
3355 // If there is a window for this buffer in which 'spell' is set load the
3356 // wordlists.
3357 return did_set_spell_option(FALSE);
3358}
3359
3360/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003361 * The 'spelloptions' option is changed.
3362 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003363 char *
3364did_set_spelloptions(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003365{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003366 char_u **varp = (char_u **)args->os_varp;
3367
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003368 if (**varp != NUL && STRCMP(*varp, "camel") != 0)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003369 return e_invalid_argument;
3370
3371 return NULL;
3372}
3373
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003374 int
3375expand_set_spelloptions(optexpand_T *args, int *numMatches, char_u ***matches)
3376{
3377 static char *(p_spo_values[]) = {"camel", NULL};
3378 return expand_set_opt_string(
3379 args,
3380 p_spo_values,
3381 sizeof(p_spo_values) / sizeof(p_spo_values[0]) - 1,
3382 numMatches,
3383 matches);
3384}
3385
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003386/*
3387 * The 'spellsuggest' option is changed.
3388 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003389 char *
3390did_set_spellsuggest(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003391{
3392 if (spell_check_sps() != OK)
3393 return e_invalid_argument;
3394
3395 return NULL;
3396}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003397
3398 int
3399expand_set_spellsuggest(optexpand_T *args, int *numMatches, char_u ***matches)
3400{
3401 return expand_set_opt_string(
3402 args,
3403 p_sps_values,
3404 sizeof(p_sps_values) / sizeof(p_sps_values[0]) - 1,
3405 numMatches,
3406 matches);
3407}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003408#endif
3409
3410/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003411 * The 'splitkeep' option is changed.
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003412 */
3413 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003414did_set_splitkeep(optset_T *args UNUSED)
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003415{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003416 return did_set_opt_strings(p_spk, p_spk_values, FALSE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003417}
3418
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003419 int
3420expand_set_splitkeep(optexpand_T *args, int *numMatches, char_u ***matches)
3421{
3422 return expand_set_opt_string(
3423 args,
3424 p_spk_values,
3425 sizeof(p_spk_values) / sizeof(p_spk_values[0]) - 1,
3426 numMatches,
3427 matches);
3428}
3429
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003430#if defined(FEAT_STL_OPT) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003431/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003432 * The 'statusline' option is changed.
3433 */
3434 char *
3435did_set_statusline(optset_T *args)
3436{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003437 return parse_statustabline_rulerformat(args, FALSE);
3438}
3439#endif
3440
3441/*
3442 * The 'swapsync' option is changed.
3443 */
3444 char *
3445did_set_swapsync(optset_T *args UNUSED)
3446{
3447 return did_set_opt_strings(p_sws, p_sws_values, FALSE);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003448}
3449
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003450 int
3451expand_set_swapsync(optexpand_T *args, int *numMatches, char_u ***matches)
3452{
3453 return expand_set_opt_string(
3454 args,
3455 p_sws_values,
3456 sizeof(p_sws_values) / sizeof(p_sws_values[0]) - 1,
3457 numMatches,
3458 matches);
3459}
3460
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003461/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003462 * The 'switchbuf' option is changed.
3463 */
3464 char *
3465did_set_switchbuf(optset_T *args UNUSED)
3466{
3467 return did_set_opt_flags(p_swb, p_swb_values, &swb_flags, TRUE);
3468}
3469
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003470 int
3471expand_set_switchbuf(optexpand_T *args, int *numMatches, char_u ***matches)
3472{
3473 return expand_set_opt_string(
3474 args,
3475 p_swb_values,
3476 sizeof(p_swb_values) / sizeof(p_swb_values[0]) - 1,
3477 numMatches,
3478 matches);
3479}
3480
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003481#if defined(FEAT_STL_OPT) || defined(PROTO)
3482/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003483 * The 'tabline' option is changed.
3484 */
3485 char *
3486did_set_tabline(optset_T *args)
3487{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003488 return parse_statustabline_rulerformat(args, FALSE);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003489}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003490#endif
3491
3492/*
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003493 * The 'tagcase' option is changed.
3494 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003495 char *
3496did_set_tagcase(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003497{
3498 unsigned int *flags;
3499 char_u *p;
3500
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003501 if (args->os_flags & OPT_LOCAL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003502 {
3503 p = curbuf->b_p_tc;
3504 flags = &curbuf->b_tc_flags;
3505 }
3506 else
3507 {
3508 p = p_tc;
3509 flags = &tc_flags;
3510 }
3511
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003512 if ((args->os_flags & OPT_LOCAL) && *p == NUL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003513 // make the local value empty: use the global value
3514 *flags = 0;
3515 else if (*p == NUL
3516 || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
3517 return e_invalid_argument;
3518
3519 return NULL;
3520}
3521
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003522 int
3523expand_set_tagcase(optexpand_T *args, int *numMatches, char_u ***matches)
3524{
3525 return expand_set_opt_string(
3526 args,
3527 p_tc_values,
3528 sizeof(p_tc_values) / sizeof(p_tc_values[0]) - 1,
3529 numMatches,
3530 matches);
3531}
3532
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003533/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003534 * The 'term' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003535 */
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003536 char *
3537did_set_term(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003538{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003539 if (T_NAME[0] == NUL)
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003540 return e_cannot_set_term_to_empty_string;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003541#ifdef FEAT_GUI
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003542 if (gui.in_use)
3543 return e_cannot_change_term_in_GUI;
3544 if (term_is_gui(T_NAME))
3545 return e_use_gui_to_start_GUI;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003546#endif
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003547 if (set_termname(T_NAME) == FAIL)
3548 return e_not_found_in_termcap;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003549
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003550 // Screen colors may have changed.
3551 redraw_later_clear();
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003552
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003553 return NULL;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003554}
3555
3556/*
3557 * Some terminal option (t_xxx) is changed
3558 */
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003559 char *
3560did_set_term_option(optset_T *args)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003561{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003562 char_u **varp = (char_u **)args->os_varp;
3563
3564 if (!full_screen)
3565 return NULL;
3566
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003567 // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co="
3568 if (varp == &T_CCO)
3569 {
3570 int colors = atoi((char *)T_CCO);
3571
3572 // Only reinitialize colors if t_Co value has really changed to
3573 // avoid expensive reload of colorscheme if t_Co is set to the
3574 // same value multiple times.
3575 if (colors != t_colors)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003576 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003577 t_colors = colors;
3578 if (t_colors <= 1)
3579 {
3580 vim_free(T_CCO);
3581 T_CCO = empty_option;
3582 }
3583#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
3584 if (is_term_win32())
3585 {
3586 swap_tcap();
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003587 args->os_did_swaptcap = TRUE;
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003588 }
3589#endif
3590 // We now have a different color setup, initialize it again.
3591 init_highlight(TRUE, FALSE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003592 }
3593 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003594 ttest(FALSE);
3595 if (varp == &T_ME)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003596 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003597 out_str(T_ME);
3598 redraw_later(UPD_CLEAR);
3599#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
3600 // Since t_me has been set, this probably means that the user
3601 // wants to use this as default colors. Need to reset default
3602 // background/foreground colors.
3603# ifdef VIMDLL
3604 if (!gui.in_use && !gui.starting)
3605# endif
3606 mch_set_normal_colors();
3607#endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003608 }
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003609 if (varp == &T_BE && termcap_active)
3610 {
3611 MAY_WANT_TO_LOG_THIS;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003612
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003613 if (*T_BE == NUL)
3614 // When clearing t_BE we assume the user no longer wants
3615 // bracketed paste, thus disable it by writing t_BD.
3616 out_str(T_BD);
3617 else
3618 out_str(T_BE);
3619 }
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003620
3621 return NULL;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003622}
3623
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003624#if defined(FEAT_TERMINAL) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003625/*
3626 * The 'termwinkey' option is changed.
3627 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003628 char *
3629did_set_termwinkey(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003630{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003631 if (*curwin->w_p_twk != NUL && string_to_key(curwin->w_p_twk, TRUE) == 0)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003632 return e_invalid_argument;
3633
3634 return NULL;
3635}
3636
3637/*
3638 * The 'termwinsize' option is changed.
3639 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003640 char *
3641did_set_termwinsize(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003642{
3643 char_u *p;
3644
3645 if (*curwin->w_p_tws == NUL)
3646 return NULL;
3647
3648 p = skipdigits(curwin->w_p_tws);
3649 if (p == curwin->w_p_tws
3650 || (*p != 'x' && *p != '*')
3651 || *skipdigits(p + 1) != NUL)
3652 return e_invalid_argument;
3653
3654 return NULL;
3655}
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003656
3657# if defined(MSWIN) || defined(PROTO)
3658/*
3659 * The 'termwintype' option is changed.
3660 */
3661 char *
3662did_set_termwintype(optset_T *args UNUSED)
3663{
3664 return did_set_opt_strings(p_twt, p_twt_values, FALSE);
3665}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003666
3667 int
3668expand_set_termwintype(optexpand_T *args, int *numMatches, char_u ***matches)
3669{
3670 return expand_set_opt_string(
3671 args,
3672 p_twt_values,
3673 sizeof(p_twt_values) / sizeof(p_twt_values[0]) - 1,
3674 numMatches,
3675 matches);
3676}
Yegappan Lakshmanan8ad862a2023-02-23 15:05:22 +00003677# endif
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003678#endif
3679
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003680/*
3681 * The 'titlestring' option is changed.
3682 */
3683 char *
3684did_set_titlestring(optset_T *args)
3685{
3686 int flagval = 0;
3687
3688#ifdef FEAT_STL_OPT
3689 flagval = STL_IN_TITLE;
3690#endif
3691 return parse_titleiconstring(args, flagval);
3692}
3693
3694#if (defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)) || defined(PROTO)
3695/*
3696 * The 'toolbar' option is changed.
3697 */
3698 char *
3699did_set_toolbar(optset_T *args UNUSED)
3700{
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00003701 if (opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags,
3702 TRUE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003703 return e_invalid_argument;
3704
3705 out_flush();
3706 gui_mch_show_toolbar((toolbar_flags &
3707 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
3708 return NULL;
3709}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003710
3711 int
3712expand_set_toolbar(optexpand_T *args, int *numMatches, char_u ***matches)
3713{
3714 return expand_set_opt_string(
3715 args,
3716 p_toolbar_values,
3717 sizeof(p_toolbar_values) / sizeof(p_toolbar_values[0]) - 1,
3718 numMatches,
3719 matches);
3720}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003721#endif
3722
3723#if (defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)) || defined(PROTO)
3724/*
3725 * The 'toolbariconsize' option is changed. GTK+ 2 only.
3726 */
3727 char *
3728did_set_toolbariconsize(optset_T *args UNUSED)
3729{
3730 if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
3731 return e_invalid_argument;
3732
3733 out_flush();
3734 gui_mch_show_toolbar((toolbar_flags &
3735 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
3736 return NULL;
3737}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003738
3739 int
3740expand_set_toolbariconsize(optexpand_T *args, int *numMatches, char_u ***matches)
3741{
3742 return expand_set_opt_string(
3743 args,
3744 p_tbis_values,
3745 sizeof(p_tbis_values) / sizeof(p_tbis_values[0]) - 1,
3746 numMatches,
3747 matches);
3748}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003749#endif
3750
3751#if defined(UNIX) || defined(VMS) || defined(PROTO)
3752/*
3753 * The 'ttymouse' option is changed.
3754 */
3755 char *
3756did_set_ttymouse(optset_T *args UNUSED)
3757{
3758 char *errmsg = NULL;
3759
3760 // Switch the mouse off before changing the escape sequences used for
3761 // that.
3762 mch_setmouse(FALSE);
3763 if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
3764 errmsg = e_invalid_argument;
3765 else
3766 check_mouse_termcode();
3767 if (termcap_active)
3768 setmouse(); // may switch it on again
3769
3770 return errmsg;
3771}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003772
3773 int
3774expand_set_ttymouse(optexpand_T *args, int *numMatches, char_u ***matches)
3775{
3776 return expand_set_opt_string(
3777 args,
3778 p_ttym_values,
3779 sizeof(p_ttym_values) / sizeof(p_ttym_values[0]) - 1,
3780 numMatches,
3781 matches);
3782}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003783#endif
3784
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003785#if defined(FEAT_VARTABS) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003786/*
3787 * The 'varsofttabstop' option is changed.
3788 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003789 char *
3790did_set_varsofttabstop(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003791{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003792 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003793 char_u *cp;
3794
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003795 if (!((*varp)[0]) || ((*varp)[0] == '0' && !((*varp)[1])))
Yegappan Lakshmanan960dcbd2023-03-07 17:45:11 +00003796 VIM_CLEAR(curbuf->b_p_vsts_array);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003797 else
3798 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003799 for (cp = *varp; *cp; ++cp)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003800 {
3801 if (vim_isdigit(*cp))
3802 continue;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003803 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003804 continue;
3805 return e_invalid_argument;
3806 }
3807
3808 int *oldarray = curbuf->b_p_vsts_array;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003809 if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)) == OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003810 {
3811 if (oldarray)
3812 vim_free(oldarray);
3813 }
3814 else
3815 return e_invalid_argument;
3816 }
3817
3818 return NULL;
3819}
3820
3821/*
3822 * The 'vartabstop' option is changed.
3823 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003824 char *
3825did_set_vartabstop(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003826{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003827 char_u **varp = (char_u **)args->os_varp;
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003828 char_u *cp;
3829
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003830 if (!((*varp)[0]) || ((*varp)[0] == '0' && !((*varp)[1])))
Yegappan Lakshmanan960dcbd2023-03-07 17:45:11 +00003831 VIM_CLEAR(curbuf->b_p_vts_array);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003832 else
3833 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003834 for (cp = *varp; *cp; ++cp)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003835 {
3836 if (vim_isdigit(*cp))
3837 continue;
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003838 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003839 continue;
3840 return e_invalid_argument;
3841 }
3842
3843 int *oldarray = curbuf->b_p_vts_array;
3844
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00003845 if (tabstop_set(*varp, &(curbuf->b_p_vts_array)) == OK)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003846 {
3847 vim_free(oldarray);
3848# ifdef FEAT_FOLDING
3849 if (foldmethodIsIndent(curwin))
3850 foldUpdateAll(curwin);
3851# endif
3852 }
3853 else
3854 return e_invalid_argument;
3855 }
3856
3857 return NULL;
3858}
3859#endif
3860
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003861/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003862 * The 'verbosefile' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003863 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003864 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003865did_set_verbosefile(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003866{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003867 verbose_stop();
3868 if (*p_vfile != NUL && verbose_open() == FAIL)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003869 return e_invalid_argument;
3870
3871 return NULL;
3872}
3873
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003874#if defined(FEAT_SESSION) || defined(PROTO)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003875/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003876 * The 'viewoptions' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003877 */
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00003878 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003879did_set_viewoptions(optset_T *args UNUSED)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003880{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003881 return did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003882}
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003883#endif
3884
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003885#if defined(FEAT_VIMINFO) || defined(PROTO)
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003886/*
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003887 * The 'viminfo' option is changed.
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003888 */
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003889 char *
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003890did_set_viminfo(optset_T *args)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003891{
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003892 char_u *s;
3893 char *errmsg = NULL;
3894
3895 for (s = p_viminfo; *s;)
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003896 {
Yegappan Lakshmananad608982023-03-01 12:44:06 +00003897 // Check it's a valid character
3898 if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
3899 {
3900 errmsg = illegal_char(args->os_errbuf, *s);
3901 break;
3902 }
3903 if (*s == 'n') // name is always last one
3904 break;
3905 else if (*s == 'r') // skip until next ','
3906 {
3907 while (*++s && *s != ',')
3908 ;
3909 }
3910 else if (*s == '%')
3911 {
3912 // optional number
3913 while (vim_isdigit(*++s))
3914 ;
3915 }
3916 else if (*s == '!' || *s == 'h' || *s == 'c')
3917 ++s; // no extra chars
3918 else // must have a number
3919 {
3920 while (vim_isdigit(*++s))
3921 ;
3922
3923 if (!VIM_ISDIGIT(*(s - 1)))
3924 {
3925 if (args->os_errbuf != NULL)
3926 {
3927 sprintf(args->os_errbuf,
3928 _(e_missing_number_after_angle_str_angle),
3929 transchar_byte(*(s - 1)));
3930 errmsg = args->os_errbuf;
3931 }
3932 else
3933 errmsg = "";
3934 break;
3935 }
3936 }
3937 if (*s == ',')
3938 ++s;
3939 else if (*s)
3940 {
3941 if (args->os_errbuf != NULL)
3942 errmsg = e_missing_comma;
3943 else
3944 errmsg = "";
3945 break;
3946 }
3947 }
3948 if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
3949 errmsg = e_must_specify_a_value;
3950
3951 return errmsg;
3952}
3953#endif
3954
3955/*
3956 * The 'virtualedit' option is changed.
3957 */
3958 char *
3959did_set_virtualedit(optset_T *args)
3960{
3961 char_u *ve = p_ve;
3962 unsigned int *flags = &ve_flags;
3963
3964 if (args->os_flags & OPT_LOCAL)
3965 {
3966 ve = curwin->w_p_ve;
3967 flags = &curwin->w_ve_flags;
3968 }
3969
3970 if ((args->os_flags & OPT_LOCAL) && *ve == NUL)
3971 // make the local value empty: use the global value
3972 *flags = 0;
3973 else
3974 {
3975 if (opt_strings_flags(ve, p_ve_values, flags, TRUE) != OK)
3976 return e_invalid_argument;
3977 else if (STRCMP(ve, args->os_oldval.string) != 0)
3978 {
3979 // Recompute cursor position in case the new 've' setting
3980 // changes something.
3981 validate_virtcol();
3982 coladvance(curwin->w_virtcol);
3983 }
Yegappan Lakshmananf2e30d02023-01-30 13:04:42 +00003984 }
3985
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00003986 return NULL;
3987}
3988
Yee Cheng Chin900894b2023-09-29 20:42:32 +02003989 int
3990expand_set_virtualedit(optexpand_T *args, int *numMatches, char_u ***matches)
3991{
3992 return expand_set_opt_string(
3993 args,
3994 p_ve_values,
3995 sizeof(p_ve_values) / sizeof(p_ve_values[0]) - 1,
3996 numMatches,
3997 matches);
3998}
3999
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00004000/*
4001 * The 'whichwrap' option is changed.
4002 */
4003 char *
4004did_set_whichwrap(optset_T *args)
4005{
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00004006 char_u **varp = (char_u **)args->os_varp;
4007
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004008 // Add ',' to the list flags because 'whichwrap' is a flag
4009 // list that is comma-separated.
4010 return did_set_option_listflag(*varp, (char_u *)(WW_ALL ","), args->os_errbuf);
4011}
4012
4013 int
4014expand_set_whichwrap(optexpand_T *args, int *numMatches, char_u ***matches)
4015{
4016 return expand_set_opt_listflag(args, (char_u*)WW_ALL, numMatches, matches);
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004017}
4018
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004019/*
4020 * The 'wildmode' option is changed.
4021 */
4022 char *
4023did_set_wildmode(optset_T *args UNUSED)
4024{
4025 if (check_opt_wim() == FAIL)
4026 return e_invalid_argument;
4027 return NULL;
4028}
4029
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004030 int
4031expand_set_wildmode(optexpand_T *args, int *numMatches, char_u ***matches)
4032{
4033 return expand_set_opt_string(
4034 args,
4035 p_wim_values,
4036 sizeof(p_wim_values) / sizeof(p_wim_values[0]) - 1,
4037 numMatches,
4038 matches);
4039}
4040
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004041/*
4042 * The 'wildoptions' option is changed.
4043 */
4044 char *
4045did_set_wildoptions(optset_T *args UNUSED)
4046{
4047 return did_set_opt_strings(p_wop, p_wop_values, TRUE);
4048}
4049
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004050 int
4051expand_set_wildoptions(optexpand_T *args, int *numMatches, char_u ***matches)
4052{
4053 return expand_set_opt_string(
4054 args,
4055 p_wop_values,
4056 sizeof(p_wop_values) / sizeof(p_wop_values[0]) - 1,
4057 numMatches,
4058 matches);
4059}
4060
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004061#if defined(FEAT_WAK) || defined(PROTO)
4062/*
4063 * The 'winaltkeys' option is changed.
4064 */
4065 char *
4066did_set_winaltkeys(optset_T *args UNUSED)
4067{
4068 char *errmsg = NULL;
4069
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004070 if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004071 errmsg = e_invalid_argument;
4072# ifdef FEAT_MENU
4073# if defined(FEAT_GUI_MOTIF)
4074 else if (gui.in_use)
4075 gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
4076# elif defined(FEAT_GUI_GTK)
4077 else if (gui.in_use)
4078 gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
4079# endif
4080# endif
4081 return errmsg;
4082}
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004083
4084 int
4085expand_set_winaltkeys(optexpand_T *args, int *numMatches, char_u ***matches)
4086{
4087 return expand_set_opt_string(
4088 args,
4089 p_wak_values,
4090 sizeof(p_wak_values) / sizeof(p_wak_values[0]) - 1,
4091 numMatches,
4092 matches);
4093}
Yegappan Lakshmananad608982023-03-01 12:44:06 +00004094#endif
4095
4096/*
4097 * The 'wincolor' option is changed.
4098 */
4099 char *
4100did_set_wincolor(optset_T *args UNUSED)
4101{
4102#ifdef FEAT_TERMINAL
4103 term_update_wincolor(curwin);
4104#endif
4105 return NULL;
4106}
4107
Yee Cheng Chin900894b2023-09-29 20:42:32 +02004108 int
4109expand_set_wincolor(optexpand_T *args, int *numMatches, char_u ***matches)
4110{
4111 return expand_set_opt_generic(
4112 args,
4113 get_highlight_name,
4114 numMatches,
4115 matches);
4116}
4117
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004118#ifdef FEAT_SYN_HL
4119/*
4120 * When the 'syntax' option is set, load the syntax of that name.
4121 */
4122 static void
4123do_syntax_autocmd(int value_changed)
4124{
4125 static int syn_recursive = 0;
4126
4127 ++syn_recursive;
4128 // Only pass TRUE for "force" when the value changed or not used
4129 // recursively, to avoid endless recurrence.
4130 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
4131 value_changed || syn_recursive == 1, curbuf);
4132 curbuf->b_flags |= BF_SYN_SET;
4133 --syn_recursive;
4134}
4135#endif
4136
4137/*
4138 * When the 'filetype' option is set, trigger the FileType autocommand.
4139 */
4140 static void
4141do_filetype_autocmd(char_u **varp, int opt_flags, int value_changed)
4142{
4143 // Skip this when called from a modeline and the filetype was already set
4144 // to this value.
4145 if ((opt_flags & OPT_MODELINE) && !value_changed)
4146 return;
4147
4148 static int ft_recursive = 0;
4149 int secure_save = secure;
4150
4151 // Reset the secure flag, since the value of 'filetype' has
4152 // been checked to be safe.
4153 secure = 0;
4154
4155 ++ft_recursive;
4156 did_filetype = TRUE;
4157 // Only pass TRUE for "force" when the value changed or not
4158 // used recursively, to avoid endless recurrence.
4159 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
4160 value_changed || ft_recursive == 1, curbuf);
4161 --ft_recursive;
4162 // Just in case the old "curbuf" is now invalid.
4163 if (varp != &(curbuf->b_p_ft))
4164 varp = NULL;
4165
4166 secure = secure_save;
4167}
4168
4169#ifdef FEAT_SPELL
4170/*
4171 * When the 'spelllang' option is set, source the spell/LANG.vim file in
4172 * 'runtimepath'.
4173 */
4174 static void
4175do_spelllang_source(void)
4176{
4177 char_u fname[200];
4178 char_u *p;
4179 char_u *q = curwin->w_s->b_p_spl;
4180
4181 // Skip the first name if it is "cjk".
4182 if (STRNCMP(q, "cjk,", 4) == 0)
4183 q += 4;
4184
4185 // They could set 'spellcapcheck' depending on the language. Use the first
4186 // name in 'spelllang' up to '_region' or '.encoding'.
4187 for (p = q; *p != NUL; ++p)
4188 if (!ASCII_ISALNUM(*p) && *p != '-')
4189 break;
4190 if (p > q)
4191 {
4192 vim_snprintf((char *)fname, 200, "spell/%.*s.vim",
4193 (int)(p - q), q);
4194 source_runtime(fname, DIP_ALL);
4195 }
4196}
4197#endif
4198
4199/*
Bram Moolenaardac13472019-09-16 21:06:21 +02004200 * Handle string options that need some action to perform when changed.
zeertzjqf6782732022-07-27 18:26:03 +01004201 * The new value must be allocated.
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004202 * Returns NULL for success, or an untranslated error message for an error.
Bram Moolenaardac13472019-09-16 21:06:21 +02004203 */
4204 char *
4205did_set_string_option(
4206 int opt_idx, // index in options[] table
4207 char_u **varp, // pointer to the option variable
Bram Moolenaardac13472019-09-16 21:06:21 +02004208 char_u *oldval, // previous value of the option
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004209 char_u *value, // new value of the option
Bram Moolenaardac13472019-09-16 21:06:21 +02004210 char *errbuf, // buffer for errors, or NULL
4211 int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004212 int *value_checked) // value was checked to be safe, no
Bram Moolenaardac13472019-09-16 21:06:21 +02004213 // need to set P_INSECURE
4214{
4215 char *errmsg = NULL;
Bram Moolenaardac13472019-09-16 21:06:21 +02004216 long_u free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004217 opt_did_set_cb_T did_set_cb = get_option_did_set_cb(opt_idx);
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004218 optset_T args;
4219
4220 // 'ttytype' is an alias for 'term'. Both 'term' and 'ttytype' point to
4221 // T_NAME. If 'term' or 'ttytype' is modified, then use the index for the
4222 // 'term' option. Only set the P_ALLOCED flag on 'term'.
4223 if (varp == &T_NAME)
4224 {
4225 opt_idx = findoption((char_u *)"term");
4226 if (opt_idx >= 0)
4227 {
4228 free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
4229 did_set_cb = get_option_did_set_cb(opt_idx);
4230 }
4231 }
4232
4233 CLEAR_FIELD(args);
Bram Moolenaardac13472019-09-16 21:06:21 +02004234
Bram Moolenaardac13472019-09-16 21:06:21 +02004235 // Disallow changing some options from secure mode
4236 if ((secure
4237#ifdef HAVE_SANDBOX
4238 || sandbox != 0
4239#endif
4240 ) && (get_option_flags(opt_idx) & P_SECURE))
Bram Moolenaar74409f62022-01-01 15:58:22 +00004241 errmsg = e_not_allowed_here;
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004242 // Check for a "normal" directory or file name in some options.
4243 else if (check_illegal_path_names(opt_idx, varp))
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00004244 errmsg = e_invalid_argument;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004245 else if (did_set_cb != NULL)
4246 {
Yegappan Lakshmananc727b192023-03-03 12:26:15 +00004247 args.os_varp = (char_u *)varp;
4248 args.os_idx = opt_idx;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004249 args.os_flags = opt_flags;
4250 args.os_oldval.string = oldval;
4251 args.os_newval.string = value;
Yegappan Lakshmanan6d611de2023-02-25 11:59:33 +00004252 args.os_errbuf = errbuf;
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004253 // Invoke the option specific callback function to validate and apply
4254 // the new option value.
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004255 errmsg = did_set_cb(&args);
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004256
Yegappan Lakshmanan5da901b2023-02-27 12:47:47 +00004257 // The 'keymap', 'filetype' and 'syntax' option callback functions
4258 // may change the os_value_checked field.
4259 *value_checked = args.os_value_checked;
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004260 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004261
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004262 // If an error is detected, restore the previous value.
Bram Moolenaardac13472019-09-16 21:06:21 +02004263 if (errmsg != NULL)
4264 {
zeertzjqf6782732022-07-27 18:26:03 +01004265 free_string_option(*varp);
Bram Moolenaardac13472019-09-16 21:06:21 +02004266 *varp = oldval;
4267 // When resetting some values, need to act on it.
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004268 if (args.os_restore_chartab)
Bram Moolenaardac13472019-09-16 21:06:21 +02004269 (void)init_chartab();
4270 if (varp == &p_hl)
4271 (void)highlight_changed();
4272 }
4273 else
4274 {
4275#ifdef FEAT_EVAL
4276 // Remember where the option was set.
4277 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
4278#endif
4279 // Free string options that are in allocated memory.
4280 // Use "free_oldval", because recursiveness may change the flags under
4281 // our fingers (esp. init_highlight()).
4282 if (free_oldval)
4283 free_string_option(oldval);
zeertzjqf6782732022-07-27 18:26:03 +01004284 set_option_flag(opt_idx, P_ALLOCED);
Bram Moolenaardac13472019-09-16 21:06:21 +02004285
4286 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
4287 && is_global_local_option(opt_idx))
4288 {
4289 // global option with local value set to use global value; free
4290 // the local value and make it empty
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004291 char_u *p = get_option_varp_scope(opt_idx, OPT_LOCAL);
Bram Moolenaardac13472019-09-16 21:06:21 +02004292 free_string_option(*(char_u **)p);
4293 *(char_u **)p = empty_option;
4294 }
4295
4296 // May set global value for local option.
4297 else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL)
4298 set_string_option_global(opt_idx, varp);
4299
4300 // Trigger the autocommand only after setting the flags.
4301#ifdef FEAT_SYN_HL
Bram Moolenaardac13472019-09-16 21:06:21 +02004302 if (varp == &(curbuf->b_p_syn))
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004303 do_syntax_autocmd(args.os_value_changed);
Bram Moolenaardac13472019-09-16 21:06:21 +02004304#endif
4305 else if (varp == &(curbuf->b_p_ft))
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004306 do_filetype_autocmd(varp, opt_flags, args.os_value_changed);
Bram Moolenaardac13472019-09-16 21:06:21 +02004307#ifdef FEAT_SPELL
4308 if (varp == &(curwin->w_s->b_p_spl))
Yegappan Lakshmanand6e4c752023-01-31 13:25:58 +00004309 do_spelllang_source();
Bram Moolenaardac13472019-09-16 21:06:21 +02004310#endif
4311 }
4312
Bram Moolenaardac13472019-09-16 21:06:21 +02004313 if (varp == &p_mouse)
4314 {
Bram Moolenaardac13472019-09-16 21:06:21 +02004315 if (*p_mouse == NUL)
4316 mch_setmouse(FALSE); // switch mouse off
4317 else
Bram Moolenaardac13472019-09-16 21:06:21 +02004318 setmouse(); // in case 'mouse' changed
4319 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004320
Bram Moolenaar788fbb42020-05-31 14:08:12 +02004321#if defined(FEAT_LUA) || defined(PROTO)
4322 if (varp == &p_rtp)
4323 update_package_paths_in_lua();
4324#endif
4325
Bram Moolenaarb2d85e32022-01-07 16:55:32 +00004326#if defined(FEAT_LINEBREAK)
4327 // Changing Formatlistpattern when briopt includes the list setting:
4328 // redraw
4329 if ((varp == &p_flp || varp == &(curbuf->b_p_flp))
4330 && curwin->w_briopt_list)
Bram Moolenaara4d158b2022-08-14 14:17:45 +01004331 redraw_all_later(UPD_NOT_VALID);
Bram Moolenaarb2d85e32022-01-07 16:55:32 +00004332#endif
4333
Bram Moolenaardac13472019-09-16 21:06:21 +02004334 if (curwin->w_curswant != MAXCOL
Bram Moolenaara1cb1d12019-10-17 23:00:07 +02004335 && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaardac13472019-09-16 21:06:21 +02004336 curwin->w_set_curswant = TRUE;
4337
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004338 if ((opt_flags & OPT_NO_REDRAW) == 0)
4339 {
Bram Moolenaardac13472019-09-16 21:06:21 +02004340#ifdef FEAT_GUI
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004341 // set when changing an option that only requires a redraw in the GUI
4342 int redraw_gui_only = FALSE;
4343
4344 if (varp == &p_go // 'guioptions'
4345 || varp == &p_guifont // 'guifont'
4346# ifdef FEAT_GUI_TABLINE
4347 || varp == &p_gtl // 'guitablabel'
4348 || varp == &p_gtt // 'guitabtooltip'
4349# endif
4350# ifdef FEAT_XFONTSET
4351 || varp == &p_guifontset // 'guifontset'
4352# endif
4353 || varp == &p_guifontwide // 'guifontwide'
4354# ifdef FEAT_GUI_GTK
4355 || varp == &p_guiligatures // 'guiligatures'
4356# endif
4357 )
4358 redraw_gui_only = TRUE;
4359
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004360 // check redraw when it's not a GUI option or the GUI is active.
4361 if (!redraw_gui_only || gui.in_use)
Bram Moolenaardac13472019-09-16 21:06:21 +02004362#endif
Bram Moolenaar37294bd2021-03-10 13:40:08 +01004363 check_redraw(get_option_flags(opt_idx));
4364 }
Bram Moolenaardac13472019-09-16 21:06:21 +02004365
4366#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
Yegappan Lakshmanan5284b232023-03-04 19:57:32 +00004367 if (args.os_did_swaptcap)
Bram Moolenaardac13472019-09-16 21:06:21 +02004368 {
4369 set_termname((char_u *)"win32");
4370 init_highlight(TRUE, FALSE);
4371 }
4372#endif
4373
4374 return errmsg;
4375}
4376
4377/*
4378 * Check an option that can be a range of string values.
4379 *
4380 * Return OK for correct value, FAIL otherwise.
4381 * Empty is always OK.
4382 */
4383 static int
4384check_opt_strings(
4385 char_u *val,
4386 char **values,
4387 int list) // when TRUE: accept a list of values
4388{
4389 return opt_strings_flags(val, values, NULL, list);
4390}
4391
4392/*
4393 * Handle an option that can be a range of string values.
4394 * Set a flag in "*flagp" for each string present.
4395 *
4396 * Return OK for correct value, FAIL otherwise.
4397 * Empty is always OK.
4398 */
4399 static int
4400opt_strings_flags(
4401 char_u *val, // new value
4402 char **values, // array of valid string values
4403 unsigned *flagp,
4404 int list) // when TRUE: accept a list of values
4405{
4406 int i;
4407 int len;
4408 unsigned new_flags = 0;
4409
4410 while (*val)
4411 {
4412 for (i = 0; ; ++i)
4413 {
4414 if (values[i] == NULL) // val not found in values[]
4415 return FAIL;
4416
4417 len = (int)STRLEN(values[i]);
4418 if (STRNCMP(values[i], val, len) == 0
4419 && ((list && val[len] == ',') || val[len] == NUL))
4420 {
4421 val += len + (val[len] == ',');
4422 new_flags |= (1 << i);
4423 break; // check next item in val list
4424 }
4425 }
4426 }
4427 if (flagp != NULL)
4428 *flagp = new_flags;
4429
4430 return OK;
4431}
4432
4433/*
4434 * return OK if "p" is a valid fileformat name, FAIL otherwise.
4435 */
4436 int
4437check_ff_value(char_u *p)
4438{
4439 return check_opt_strings(p, p_ff_values, FALSE);
4440}
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004441
4442/*
Yegappan Lakshmananaf936912023-02-20 12:16:39 +00004443 * Save the actual shortmess Flags and clear them temporarily to avoid that
4444 * file messages overwrites any output from the following commands.
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004445 *
4446 * Caller must make sure to first call save_clear_shm_value() and then
4447 * restore_shm_value() exactly the same number of times.
4448 */
4449 void
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +00004450save_clear_shm_value(void)
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004451{
4452 if (STRLEN(p_shm) >= SHM_LEN)
4453 {
4454 iemsg(e_internal_error_shortmess_too_long);
4455 return;
4456 }
4457
4458 if (++set_shm_recursive == 1)
4459 {
4460 STRCPY(shm_buf, p_shm);
4461 set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
4462 }
4463}
4464
4465/*
4466 * Restore the shortmess Flags set from the save_clear_shm_value() function.
4467 */
4468 void
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +00004469restore_shm_value(void)
Christian Brabandt9aee8ec2022-12-16 16:41:23 +00004470{
4471 if (--set_shm_recursive == 0)
4472 {
4473 set_option_value_give_err((char_u *)"shm", 0L, shm_buf, 0);
4474 vim_memset(shm_buf, 0, SHM_LEN);
4475 }
4476}