xref: /vim-8.2.3635/src/option.c (revision 87fd0924)
1 /* 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  * Code to handle user-settable options. This is all pretty much table-
12  * driven. Checklist for adding a new option:
13  * - Put it in the options array below (copy an existing entry).
14  * - For a global option: Add a variable for it in option.h.
15  * - For a buffer or window local option:
16  *   - Add a PV_XX entry to the enum below.
17  *   - Add a variable to the window or buffer struct in structs.h.
18  *   - For a window option, add some code to copy_winopt().
19  *   - For a buffer option, add some code to buf_copy_options().
20  *   - For a buffer string option, add code to check_buf_options().
21  * - If it's a numeric option, add any necessary bounds checks to do_set().
22  * - If it's a list of flags, add some code in do_set(), search for WW_ALL.
23  * - When adding an option with expansion (P_EXPAND), but with a different
24  *   default for Vi and Vim (no P_VI_DEF), add some code at VIMEXP.
25  * - Add documentation!  One line in doc/quickref.txt, full description in
26  *   options.txt, and any other related places.
27  * - Add an entry in runtime/optwin.vim.
28  * When making changes:
29  * - Adjust the help for the option in doc/option.txt.
30  * - When an entry has the P_VIM flag, or is lacking the P_VI_DEF flag, add a
31  *   comment at the help for the 'compatible' option.
32  */
33 
34 #define IN_OPTION_C
35 #include "vim.h"
36 #include "optiondefs.h"
37 
38 static void set_options_default(int opt_flags);
39 static void set_string_default_esc(char *name, char_u *val, int escape);
40 static char_u *find_dup_item(char_u *origval, char_u *newval, long_u flags);
41 static char_u *option_expand(int opt_idx, char_u *val);
42 static void didset_options(void);
43 static void didset_options2(void);
44 #if defined(FEAT_EVAL) || defined(PROTO)
45 static long_u *insecure_flag(int opt_idx, int opt_flags);
46 #else
47 # define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
48 #endif
49 static char *set_bool_option(int opt_idx, char_u *varp, int value, int opt_flags);
50 static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, size_t errbuflen, int opt_flags);
51 static int find_key_option(char_u *arg_arg, int has_lt);
52 static void showoptions(int all, int opt_flags);
53 static int optval_default(struct vimoption *, char_u *varp, int compatible);
54 static void showoneopt(struct vimoption *, int opt_flags);
55 static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, long_u flags);
56 static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep);
57 static int put_setbool(FILE *fd, char *cmd, char *name, int value);
58 static int istermoption(struct vimoption *p);
59 static char_u *get_varp_scope(struct vimoption *p, int opt_flags);
60 static char_u *get_varp(struct vimoption *);
61 static void check_win_options(win_T *win);
62 static void option_value2string(struct vimoption *, int opt_flags);
63 static void check_winopt(winopt_T *wop);
64 static int wc_use_keyname(char_u *varp, long *wcp);
65 static void paste_option_changed(void);
66 static void compatible_set(void);
67 
68 /*
69  * Initialize the options, first part.
70  *
71  * Called only once from main(), just after creating the first buffer.
72  * If "clean_arg" is TRUE Vim was started with --clean.
73  */
74     void
set_init_1(int clean_arg)75 set_init_1(int clean_arg)
76 {
77     char_u	*p;
78     int		opt_idx;
79     long_u	n;
80 
81 #ifdef FEAT_LANGMAP
82     langmap_init();
83 #endif
84 
85     // Be Vi compatible by default
86     p_cp = TRUE;
87 
88     // Use POSIX compatibility when $VIM_POSIX is set.
89     if (mch_getenv((char_u *)"VIM_POSIX") != NULL)
90     {
91 	set_string_default("cpo", (char_u *)CPO_ALL);
92 	set_string_default("shm", (char_u *)SHM_POSIX);
93     }
94 
95     /*
96      * Find default value for 'shell' option.
97      * Don't use it if it is empty.
98      */
99     if (((p = mch_getenv((char_u *)"SHELL")) != NULL && *p != NUL)
100 #if defined(MSWIN)
101 	    || ((p = mch_getenv((char_u *)"COMSPEC")) != NULL && *p != NUL)
102 	    || ((p = (char_u *)default_shell()) != NULL && *p != NUL)
103 #endif
104 	    )
105 #if defined(MSWIN)
106     {
107 	// For MS-Windows put the path in quotes instead of escaping spaces.
108 	char_u	    *cmd;
109 	size_t	    len;
110 
111 	if (vim_strchr(p, ' ') != NULL)
112 	{
113 	    len = STRLEN(p) + 3;  // two quotes and a trailing NUL
114 	    cmd = alloc(len);
115 	    if (cmd != NULL)
116 	    {
117 		vim_snprintf((char *)cmd, len, "\"%s\"", p);
118 		set_string_default("sh", cmd);
119 		vim_free(cmd);
120 	    }
121 	}
122 	else
123 	    set_string_default("sh", p);
124     }
125 #else
126 	set_string_default_esc("sh", p, TRUE);
127 #endif
128 
129 #ifdef FEAT_WILDIGN
130     /*
131      * Set the default for 'backupskip' to include environment variables for
132      * temp files.
133      */
134     {
135 # ifdef UNIX
136 	static char	*(names[4]) = {"", "TMPDIR", "TEMP", "TMP"};
137 # else
138 	static char	*(names[3]) = {"TMPDIR", "TEMP", "TMP"};
139 # endif
140 	int		len;
141 	garray_T	ga;
142 	int		mustfree;
143 	char_u		*item;
144 
145 	opt_idx = findoption((char_u *)"backupskip");
146 
147 	ga_init2(&ga, 1, 100);
148 	for (n = 0; n < (long)ARRAY_LENGTH(names); ++n)
149 	{
150 	    mustfree = FALSE;
151 # ifdef UNIX
152 	    if (*names[n] == NUL)
153 #  ifdef MACOS_X
154 		p = (char_u *)"/private/tmp";
155 #  else
156 		p = (char_u *)"/tmp";
157 #  endif
158 	    else
159 # endif
160 		p = vim_getenv((char_u *)names[n], &mustfree);
161 	    if (p != NULL && *p != NUL)
162 	    {
163 		// First time count the NUL, otherwise count the ','.
164 		len = (int)STRLEN(p) + 3;
165 		item = alloc(len);
166 		STRCPY(item, p);
167 		add_pathsep(item);
168 		STRCAT(item, "*");
169 		if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
170 									== NULL
171 			&& ga_grow(&ga, len) == OK)
172 		{
173 		    if (ga.ga_len > 0)
174 			STRCAT(ga.ga_data, ",");
175 		    STRCAT(ga.ga_data, item);
176 		    ga.ga_len += len;
177 		}
178 		vim_free(item);
179 	    }
180 	    if (mustfree)
181 		vim_free(p);
182 	}
183 	if (ga.ga_data != NULL)
184 	{
185 	    set_string_default("bsk", ga.ga_data);
186 	    vim_free(ga.ga_data);
187 	}
188     }
189 #endif
190 
191     /*
192      * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
193      */
194     opt_idx = findoption((char_u *)"maxmemtot");
195     if (opt_idx >= 0)
196     {
197 #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
198 	if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L)
199 #endif
200 	{
201 #ifdef HAVE_AVAIL_MEM
202 	    // Use amount of memory available at this moment.
203 	    n = (mch_avail_mem(FALSE) >> 1);
204 #else
205 # ifdef HAVE_TOTAL_MEM
206 	    // Use amount of memory available to Vim.
207 	    n = (mch_total_mem(FALSE) >> 1);
208 # else
209 	    n = (0x7fffffff >> 11);
210 # endif
211 #endif
212 	    options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
213 	    opt_idx = findoption((char_u *)"maxmem");
214 	    if (opt_idx >= 0)
215 	    {
216 #if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
217 		if ((long)(long_i)options[opt_idx].def_val[VI_DEFAULT] > (long)n
218 		  || (long)(long_i)options[opt_idx].def_val[VI_DEFAULT] == 0L)
219 #endif
220 		    options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
221 	    }
222 	}
223     }
224 
225 #ifdef FEAT_SEARCHPATH
226     {
227 	char_u	*cdpath;
228 	char_u	*buf;
229 	int	i;
230 	int	j;
231 	int	mustfree = FALSE;
232 
233 	// Initialize the 'cdpath' option's default value.
234 	cdpath = vim_getenv((char_u *)"CDPATH", &mustfree);
235 	if (cdpath != NULL)
236 	{
237 	    buf = alloc((STRLEN(cdpath) << 1) + 2);
238 	    if (buf != NULL)
239 	    {
240 		buf[0] = ',';	    // start with ",", current dir first
241 		j = 1;
242 		for (i = 0; cdpath[i] != NUL; ++i)
243 		{
244 		    if (vim_ispathlistsep(cdpath[i]))
245 			buf[j++] = ',';
246 		    else
247 		    {
248 			if (cdpath[i] == ' ' || cdpath[i] == ',')
249 			    buf[j++] = '\\';
250 			buf[j++] = cdpath[i];
251 		    }
252 		}
253 		buf[j] = NUL;
254 		opt_idx = findoption((char_u *)"cdpath");
255 		if (opt_idx >= 0)
256 		{
257 		    options[opt_idx].def_val[VI_DEFAULT] = buf;
258 		    options[opt_idx].flags |= P_DEF_ALLOCED;
259 		}
260 		else
261 		    vim_free(buf); // cannot happen
262 	    }
263 	    if (mustfree)
264 		vim_free(cdpath);
265 	}
266     }
267 #endif
268 
269 #if defined(FEAT_POSTSCRIPT) && (defined(MSWIN) || defined(VMS) || defined(EBCDIC) || defined(MAC) || defined(hpux))
270     // Set print encoding on platforms that don't default to latin1
271     set_string_default("penc",
272 # if defined(MSWIN)
273 		       (char_u *)"cp1252"
274 # else
275 #  ifdef VMS
276 		       (char_u *)"dec-mcs"
277 #  else
278 #   ifdef EBCDIC
279 		       (char_u *)"ebcdic-uk"
280 #   else
281 #    ifdef MAC
282 		       (char_u *)"mac-roman"
283 #    else // HPUX
284 		       (char_u *)"hp-roman8"
285 #    endif
286 #   endif
287 #  endif
288 # endif
289 		       );
290 #endif
291 
292 #ifdef FEAT_POSTSCRIPT
293     // 'printexpr' must be allocated to be able to evaluate it.
294     set_string_default("pexpr",
295 # if defined(MSWIN)
296 	    (char_u *)"system('copy' . ' ' . v:fname_in . (&printdevice == '' ? ' LPT1:' : (' \"' . &printdevice . '\"'))) . delete(v:fname_in)"
297 # else
298 #  ifdef VMS
299 	    (char_u *)"system('print/delete' . (&printdevice == '' ? '' : ' /queue=' . &printdevice) . ' ' . v:fname_in)"
300 
301 #  else
302 	    (char_u *)"system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
303 #  endif
304 # endif
305 	    );
306 #endif
307 
308     /*
309      * Set all the options (except the terminal options) to their default
310      * value.  Also set the global value for local options.
311      */
312     set_options_default(0);
313 
314 #ifdef CLEAN_RUNTIMEPATH
315     if (clean_arg)
316     {
317 	opt_idx = findoption((char_u *)"runtimepath");
318 	if (opt_idx >= 0)
319 	{
320 	    options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
321 	    p_rtp = (char_u *)CLEAN_RUNTIMEPATH;
322 	}
323 	opt_idx = findoption((char_u *)"packpath");
324 	if (opt_idx >= 0)
325 	{
326 	    options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
327 	    p_pp = (char_u *)CLEAN_RUNTIMEPATH;
328 	}
329     }
330 #endif
331 
332 #ifdef FEAT_GUI
333     if (found_reverse_arg)
334 	set_option_value((char_u *)"bg", 0L, (char_u *)"dark", 0);
335 #endif
336 
337     curbuf->b_p_initialized = TRUE;
338     curbuf->b_p_ar = -1;	// no local 'autoread' value
339     curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
340     check_buf_options(curbuf);
341     check_win_options(curwin);
342     check_options();
343 
344     // Must be before option_expand(), because that one needs vim_isIDc()
345     didset_options();
346 
347 #ifdef FEAT_SPELL
348     // Use the current chartab for the generic chartab. This is not in
349     // didset_options() because it only depends on 'encoding'.
350     init_spell_chartab();
351 #endif
352 
353     /*
354      * Expand environment variables and things like "~" for the defaults.
355      * If option_expand() returns non-NULL the variable is expanded.  This can
356      * only happen for non-indirect options.
357      * Also set the default to the expanded value, so ":set" does not list
358      * them.
359      * Don't set the P_ALLOCED flag, because we don't want to free the
360      * default.
361      */
362     for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
363     {
364 	if ((options[opt_idx].flags & P_GETTEXT)
365 					      && options[opt_idx].var != NULL)
366 	    p = (char_u *)_(*(char **)options[opt_idx].var);
367 	else
368 	    p = option_expand(opt_idx, NULL);
369 	if (p != NULL && (p = vim_strsave(p)) != NULL)
370 	{
371 	    *(char_u **)options[opt_idx].var = p;
372 	    // VIMEXP
373 	    // Defaults for all expanded options are currently the same for Vi
374 	    // and Vim.  When this changes, add some code here!  Also need to
375 	    // split P_DEF_ALLOCED in two.
376 	    if (options[opt_idx].flags & P_DEF_ALLOCED)
377 		vim_free(options[opt_idx].def_val[VI_DEFAULT]);
378 	    options[opt_idx].def_val[VI_DEFAULT] = p;
379 	    options[opt_idx].flags |= P_DEF_ALLOCED;
380 	}
381     }
382 
383     save_file_ff(curbuf);	// Buffer is unchanged
384 
385 #if defined(FEAT_ARABIC)
386     // Detect use of mlterm.
387     // Mlterm is a terminal emulator akin to xterm that has some special
388     // abilities (bidi namely).
389     // NOTE: mlterm's author is being asked to 'set' a variable
390     //       instead of an environment variable due to inheritance.
391     if (mch_getenv((char_u *)"MLTERM") != NULL)
392 	set_option_value((char_u *)"tbidi", 1L, NULL, 0);
393 #endif
394 
395     didset_options2();
396 
397 # if defined(MSWIN) && defined(FEAT_GETTEXT)
398     /*
399      * If $LANG isn't set, try to get a good value for it.  This makes the
400      * right language be used automatically.  Don't do this for English.
401      */
402     if (mch_getenv((char_u *)"LANG") == NULL)
403     {
404 	char	buf[20];
405 
406 	// Could use LOCALE_SISO639LANGNAME, but it's not in Win95.
407 	// LOCALE_SABBREVLANGNAME gives us three letters, like "enu", we use
408 	// only the first two.
409 	n = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME,
410 							     (LPTSTR)buf, 20);
411 	if (n >= 2 && STRNICMP(buf, "en", 2) != 0)
412 	{
413 	    // There are a few exceptions (probably more)
414 	    if (STRNICMP(buf, "cht", 3) == 0 || STRNICMP(buf, "zht", 3) == 0)
415 		STRCPY(buf, "zh_TW");
416 	    else if (STRNICMP(buf, "chs", 3) == 0
417 					      || STRNICMP(buf, "zhc", 3) == 0)
418 		STRCPY(buf, "zh_CN");
419 	    else if (STRNICMP(buf, "jp", 2) == 0)
420 		STRCPY(buf, "ja");
421 	    else
422 		buf[2] = NUL;		// truncate to two-letter code
423 	    vim_setenv((char_u *)"LANG", (char_u *)buf);
424 	}
425     }
426 # else
427 #  ifdef MACOS_CONVERT
428     // Moved to os_mac_conv.c to avoid dependency problems.
429     mac_lang_init();
430 #  endif
431 # endif
432 
433 # ifdef MSWIN
434     // MS-Windows has builtin support for conversion to and from Unicode, using
435     // "utf-8" for 'encoding' should work best for most users.
436     p = vim_strsave((char_u *)ENC_DFLT);
437 # else
438     // enc_locale() will try to find the encoding of the current locale.
439     // This works best for properly configured systems, old and new.
440     p = enc_locale();
441 # endif
442     if (p != NULL)
443     {
444 	char_u *save_enc;
445 
446 	// Try setting 'encoding' and check if the value is valid.
447 	// If not, go back to the default encoding.
448 	save_enc = p_enc;
449 	p_enc = p;
450 	if (STRCMP(p_enc, "gb18030") == 0)
451 	{
452 	    // We don't support "gb18030", but "cp936" is a good substitute
453 	    // for practical purposes, thus use that.  It's not an alias to
454 	    // still support conversion between gb18030 and utf-8.
455 	    p_enc = vim_strsave((char_u *)"cp936");
456 	    vim_free(p);
457 	}
458 	if (mb_init() == NULL)
459 	{
460 	    opt_idx = findoption((char_u *)"encoding");
461 	    if (opt_idx >= 0)
462 	    {
463 		options[opt_idx].def_val[VI_DEFAULT] = p_enc;
464 		options[opt_idx].flags |= P_DEF_ALLOCED;
465 	    }
466 
467 #if defined(MSWIN) || defined(MACOS_X) || defined(VMS)
468 	    if (STRCMP(p_enc, "latin1") == 0 || enc_utf8)
469 	    {
470 		// Adjust the default for 'isprint' and 'iskeyword' to match
471 		// latin1.  Also set the defaults for when 'nocompatible' is
472 		// set.
473 		set_string_option_direct((char_u *)"isp", -1,
474 					      ISP_LATIN1, OPT_FREE, SID_NONE);
475 		set_string_option_direct((char_u *)"isk", -1,
476 					      ISK_LATIN1, OPT_FREE, SID_NONE);
477 		opt_idx = findoption((char_u *)"isp");
478 		if (opt_idx >= 0)
479 		    options[opt_idx].def_val[VIM_DEFAULT] = ISP_LATIN1;
480 		opt_idx = findoption((char_u *)"isk");
481 		if (opt_idx >= 0)
482 		    options[opt_idx].def_val[VIM_DEFAULT] = ISK_LATIN1;
483 		(void)init_chartab();
484 	    }
485 #endif
486 
487 #if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
488 	    // Win32 console: When GetACP() returns a different value from
489 	    // GetConsoleCP() set 'termencoding'.
490 	    if (
491 # ifdef VIMDLL
492 	       (!gui.in_use && !gui.starting) &&
493 # endif
494 	        GetACP() != GetConsoleCP())
495 	    {
496 		char	buf[50];
497 
498 		// Win32 console: In ConPTY, GetConsoleCP() returns zero.
499 		// Use an alternative value.
500 		if (GetConsoleCP() == 0)
501 		    sprintf(buf, "cp%ld", (long)GetACP());
502 		else
503 		    sprintf(buf, "cp%ld", (long)GetConsoleCP());
504 		p_tenc = vim_strsave((char_u *)buf);
505 		if (p_tenc != NULL)
506 		{
507 		    opt_idx = findoption((char_u *)"termencoding");
508 		    if (opt_idx >= 0)
509 		    {
510 			options[opt_idx].def_val[VI_DEFAULT] = p_tenc;
511 			options[opt_idx].flags |= P_DEF_ALLOCED;
512 		    }
513 		    convert_setup(&input_conv, p_tenc, p_enc);
514 		    convert_setup(&output_conv, p_enc, p_tenc);
515 		}
516 		else
517 		    p_tenc = empty_option;
518 	    }
519 #endif
520 #if defined(MSWIN)
521 	    // $HOME may have characters in active code page.
522 	    init_homedir();
523 #endif
524 	}
525 	else
526 	{
527 	    vim_free(p_enc);
528 	    p_enc = save_enc;
529 	}
530     }
531 
532 #ifdef FEAT_MULTI_LANG
533     // Set the default for 'helplang'.
534     set_helplang_default(get_mess_lang());
535 #endif
536 }
537 
538 static char_u *fencs_utf8_default = (char_u *)"ucs-bom,utf-8,default,latin1";
539 
540 /*
541  * Set the "fileencodings" option to the default value for when 'encoding' is
542  * utf-8.
543  */
544     void
set_fencs_unicode()545 set_fencs_unicode()
546 {
547     set_string_option_direct((char_u *)"fencs", -1, fencs_utf8_default,
548 								  OPT_FREE, 0);
549 }
550 
551 /*
552  * Set an option to its default value.
553  * This does not take care of side effects!
554  */
555     static void
set_option_default(int opt_idx,int opt_flags,int compatible)556 set_option_default(
557     int		opt_idx,
558     int		opt_flags,	// OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
559     int		compatible)	// use Vi default value
560 {
561     char_u	*varp;		// pointer to variable for current option
562     int		dvi;		// index in def_val[]
563     long_u	flags;
564     long_u	*flagsp;
565     int		both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
566 
567     varp = get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
568     flags = options[opt_idx].flags;
569     if (varp != NULL)	    // skip hidden option, nothing to do for it
570     {
571 	dvi = ((flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
572 	if (flags & P_STRING)
573 	{
574 	    // 'fencs' default value depends on 'encoding'
575 	    if (options[opt_idx].var == (char_u *)&p_fencs && enc_utf8)
576 		set_fencs_unicode();
577 	    // Use set_string_option_direct() for local options to handle
578 	    // freeing and allocating the value.
579 	    else if (options[opt_idx].indir != PV_NONE)
580 		set_string_option_direct(NULL, opt_idx,
581 				 options[opt_idx].def_val[dvi], opt_flags, 0);
582 	    else
583 	    {
584 		if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED))
585 		    free_string_option(*(char_u **)(varp));
586 		*(char_u **)varp = options[opt_idx].def_val[dvi];
587 		options[opt_idx].flags &= ~P_ALLOCED;
588 	    }
589 	}
590 	else if (flags & P_NUM)
591 	{
592 	    if (options[opt_idx].indir == PV_SCROLL)
593 		win_comp_scroll(curwin);
594 	    else
595 	    {
596 		long def_val = (long)(long_i)options[opt_idx].def_val[dvi];
597 
598 		if ((long *)varp == &curwin->w_p_so
599 			|| (long *)varp == &curwin->w_p_siso)
600 		    // 'scrolloff' and 'sidescrolloff' local values have a
601 		    // different default value than the global default.
602 		    *(long *)varp = -1;
603 		else
604 		    *(long *)varp = def_val;
605 		// May also set global value for local option.
606 		if (both)
607 		    *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
608 								def_val;
609 	    }
610 	}
611 	else	// P_BOOL
612 	{
613 	    // the cast to long is required for Manx C, long_i is needed for
614 	    // MSVC
615 	    *(int *)varp = (int)(long)(long_i)options[opt_idx].def_val[dvi];
616 #ifdef UNIX
617 	    // 'modeline' defaults to off for root
618 	    if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID)
619 		*(int *)varp = FALSE;
620 #endif
621 	    // May also set global value for local option.
622 	    if (both)
623 		*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
624 								*(int *)varp;
625 	}
626 
627 	// The default value is not insecure.
628 	flagsp = insecure_flag(opt_idx, opt_flags);
629 	*flagsp = *flagsp & ~P_INSECURE;
630     }
631 
632 #ifdef FEAT_EVAL
633     set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
634 #endif
635 }
636 
637 /*
638  * Set all options (except terminal options) to their default value.
639  * When "opt_flags" is non-zero skip 'encoding'.
640  */
641     static void
set_options_default(int opt_flags)642 set_options_default(
643     int		opt_flags)	// OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
644 {
645     int		i;
646     win_T	*wp;
647     tabpage_T	*tp;
648 
649     for (i = 0; !istermoption_idx(i); i++)
650 	if (!(options[i].flags & P_NODEFAULT)
651 		&& (opt_flags == 0
652 		    || (options[i].var != (char_u *)&p_enc
653 # if defined(FEAT_CRYPT)
654 			&& options[i].var != (char_u *)&p_cm
655 			&& options[i].var != (char_u *)&p_key
656 # endif
657 			)))
658 	    set_option_default(i, opt_flags, p_cp);
659 
660     // The 'scroll' option must be computed for all windows.
661     FOR_ALL_TAB_WINDOWS(tp, wp)
662 	win_comp_scroll(wp);
663 #ifdef FEAT_CINDENT
664     parse_cino(curbuf);
665 #endif
666 }
667 
668 /*
669  * Set the Vi-default value of a string option.
670  * Used for 'sh', 'backupskip' and 'term'.
671  * When "escape" is TRUE escape spaces with a backslash.
672  */
673     static void
set_string_default_esc(char * name,char_u * val,int escape)674 set_string_default_esc(char *name, char_u *val, int escape)
675 {
676     char_u	*p;
677     int		opt_idx;
678 
679     if (escape && vim_strchr(val, ' ') != NULL)
680 	p = vim_strsave_escaped(val, (char_u *)" ");
681     else
682 	p = vim_strsave(val);
683     if (p != NULL)		// we don't want a NULL
684     {
685 	opt_idx = findoption((char_u *)name);
686 	if (opt_idx >= 0)
687 	{
688 	    if (options[opt_idx].flags & P_DEF_ALLOCED)
689 		vim_free(options[opt_idx].def_val[VI_DEFAULT]);
690 	    options[opt_idx].def_val[VI_DEFAULT] = p;
691 	    options[opt_idx].flags |= P_DEF_ALLOCED;
692 	}
693     }
694 }
695 
696     void
set_string_default(char * name,char_u * val)697 set_string_default(char *name, char_u *val)
698 {
699     set_string_default_esc(name, val, FALSE);
700 }
701 
702 /*
703  * For an option value that contains comma separated items, find "newval" in
704  * "origval".  Return NULL if not found.
705  */
706     static char_u *
find_dup_item(char_u * origval,char_u * newval,long_u flags)707 find_dup_item(char_u *origval, char_u *newval, long_u flags)
708 {
709     int	    bs = 0;
710     size_t  newlen;
711     char_u  *s;
712 
713     if (origval == NULL)
714 	return NULL;
715 
716     newlen = STRLEN(newval);
717     for (s = origval; *s != NUL; ++s)
718     {
719 	if ((!(flags & P_COMMA)
720 		    || s == origval
721 		    || (s[-1] == ',' && !(bs & 1)))
722 		&& STRNCMP(s, newval, newlen) == 0
723 		&& (!(flags & P_COMMA)
724 		    || s[newlen] == ','
725 		    || s[newlen] == NUL))
726 	    return s;
727 	// Count backslashes.  Only a comma with an even number of backslashes
728 	// or a single backslash preceded by a comma before it is recognized as
729 	// a separator.
730 	if ((s > origval + 1
731 		    && s[-1] == '\\'
732 		    && s[-2] != ',')
733 		|| (s == origval + 1
734 		    && s[-1] == '\\'))
735 	    ++bs;
736 	else
737 	    bs = 0;
738     }
739     return NULL;
740 }
741 
742 /*
743  * Set the Vi-default value of a number option.
744  * Used for 'lines' and 'columns'.
745  */
746     void
set_number_default(char * name,long val)747 set_number_default(char *name, long val)
748 {
749     int		opt_idx;
750 
751     opt_idx = findoption((char_u *)name);
752     if (opt_idx >= 0)
753 	options[opt_idx].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
754 }
755 
756 /*
757  * Set all window-local and buffer-local options to the Vim default.
758  * local-global options will use the global value.
759  * When "do_buffer" is FALSE don't set buffer-local options.
760  */
761     void
set_local_options_default(win_T * wp,int do_buffer)762 set_local_options_default(win_T *wp, int do_buffer)
763 {
764     win_T	*save_curwin = curwin;
765     int		i;
766 
767     curwin = wp;
768     curbuf = curwin->w_buffer;
769     block_autocmds();
770 
771     for (i = 0; !istermoption_idx(i); i++)
772     {
773 	struct vimoption    *p = &(options[i]);
774 	char_u		    *varp = get_varp_scope(p, OPT_LOCAL);
775 
776 	if (p->indir != PV_NONE
777 		&& (do_buffer || (p->indir & PV_BUF) == 0)
778 		&& !(options[i].flags & P_NODEFAULT)
779 		&& !optval_default(p, varp, FALSE))
780 	    set_option_default(i, OPT_FREE|OPT_LOCAL, FALSE);
781     }
782 
783     unblock_autocmds();
784     curwin = save_curwin;
785     curbuf = curwin->w_buffer;
786 }
787 
788 #if defined(EXITFREE) || defined(PROTO)
789 /*
790  * Free all options.
791  */
792     void
free_all_options(void)793 free_all_options(void)
794 {
795     int		i;
796 
797     for (i = 0; !istermoption_idx(i); i++)
798     {
799 	if (options[i].indir == PV_NONE)
800 	{
801 	    // global option: free value and default value.
802 	    if ((options[i].flags & P_ALLOCED) && options[i].var != NULL)
803 		free_string_option(*(char_u **)options[i].var);
804 	    if (options[i].flags & P_DEF_ALLOCED)
805 		free_string_option(options[i].def_val[VI_DEFAULT]);
806 	}
807 	else if (options[i].var != VAR_WIN
808 		&& (options[i].flags & P_STRING))
809 	    // buffer-local option: free global value
810 	    clear_string_option((char_u **)options[i].var);
811     }
812     free_operatorfunc_option();
813 }
814 #endif
815 
816 
817 /*
818  * Initialize the options, part two: After getting Rows and Columns and
819  * setting 'term'.
820  */
821     void
set_init_2(void)822 set_init_2(void)
823 {
824     int		idx;
825 
826     /*
827      * 'scroll' defaults to half the window height. The stored default is zero,
828      * which results in the actual value computed from the window height.
829      */
830     idx = findoption((char_u *)"scroll");
831     if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
832 	set_option_default(idx, OPT_LOCAL, p_cp);
833     comp_col();
834 
835     /*
836      * 'window' is only for backwards compatibility with Vi.
837      * Default is Rows - 1.
838      */
839     if (!option_was_set((char_u *)"window"))
840 	p_window = Rows - 1;
841     set_number_default("window", Rows - 1);
842 
843     // For DOS console the default is always black.
844 #if !((defined(MSWIN)) && !defined(FEAT_GUI))
845     /*
846      * If 'background' wasn't set by the user, try guessing the value,
847      * depending on the terminal name.  Only need to check for terminals
848      * with a dark background, that can handle color.
849      */
850     idx = findoption((char_u *)"bg");
851     if (idx >= 0 && !(options[idx].flags & P_WAS_SET)
852 						 && *term_bg_default() == 'd')
853     {
854 	set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE, 0);
855 	// don't mark it as set, when starting the GUI it may be
856 	// changed again
857 	options[idx].flags &= ~P_WAS_SET;
858     }
859 #endif
860 
861 #ifdef CURSOR_SHAPE
862     parse_shape_opt(SHAPE_CURSOR); // set cursor shapes from 'guicursor'
863 #endif
864 #ifdef FEAT_MOUSESHAPE
865     parse_shape_opt(SHAPE_MOUSE);  // set mouse shapes from 'mouseshape'
866 #endif
867 #ifdef FEAT_PRINTER
868     (void)parse_printoptions();	    // parse 'printoptions' default value
869 #endif
870 }
871 
872 /*
873  * Initialize the options, part three: After reading the .vimrc
874  */
875     void
set_init_3(void)876 set_init_3(void)
877 {
878 #if defined(UNIX) || defined(MSWIN)
879 /*
880  * Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
881  * This is done after other initializations, where 'shell' might have been
882  * set, but only if they have not been set before.
883  */
884     char_u  *p;
885     int	    idx_srr;
886     int	    do_srr;
887 # ifdef FEAT_QUICKFIX
888     int	    idx_sp;
889     int	    do_sp;
890 # endif
891 
892     idx_srr = findoption((char_u *)"srr");
893     if (idx_srr < 0)
894 	do_srr = FALSE;
895     else
896 	do_srr = !(options[idx_srr].flags & P_WAS_SET);
897 # ifdef FEAT_QUICKFIX
898     idx_sp = findoption((char_u *)"sp");
899     if (idx_sp < 0)
900 	do_sp = FALSE;
901     else
902 	do_sp = !(options[idx_sp].flags & P_WAS_SET);
903 # endif
904     p = get_isolated_shell_name();
905     if (p != NULL)
906     {
907 	/*
908 	 * Default for p_sp is "| tee", for p_srr is ">".
909 	 * For known shells it is changed here to include stderr.
910 	 */
911 	if (	   fnamecmp(p, "csh") == 0
912 		|| fnamecmp(p, "tcsh") == 0
913 # if defined(MSWIN)	// also check with .exe extension
914 		|| fnamecmp(p, "csh.exe") == 0
915 		|| fnamecmp(p, "tcsh.exe") == 0
916 # endif
917 	   )
918 	{
919 # if defined(FEAT_QUICKFIX)
920 	    if (do_sp)
921 	    {
922 #  ifdef MSWIN
923 		p_sp = (char_u *)">&";
924 #  else
925 		p_sp = (char_u *)"|& tee";
926 #  endif
927 		options[idx_sp].def_val[VI_DEFAULT] = p_sp;
928 	    }
929 # endif
930 	    if (do_srr)
931 	    {
932 		p_srr = (char_u *)">&";
933 		options[idx_srr].def_val[VI_DEFAULT] = p_srr;
934 	    }
935 	}
936 # ifdef MSWIN
937 	// Windows PowerShell output is UTF-16 with BOM so re-encode to the
938 	// current codepage.
939 	else if (   fnamecmp(p, "powershell") == 0
940 		    || fnamecmp(p, "powershell.exe") == 0
941 		)
942 	{
943 # if defined(FEAT_QUICKFIX)
944 		if (do_sp)
945 		{
946 		    p_sp = (char_u *)"2>&1 | Out-File -Encoding default";
947 		    options[idx_sp].def_val[VI_DEFAULT] = p_sp;
948 		}
949 # endif
950 		if (do_srr)
951 		{
952 		    p_srr = (char_u *)"2>&1 | Out-File -Encoding default";
953 		    options[idx_srr].def_val[VI_DEFAULT] = p_srr;
954 		}
955 	}
956 #endif
957 	else
958 	    // Always use POSIX shell style redirection if we reach this
959 	    if (       fnamecmp(p, "sh") == 0
960 		    || fnamecmp(p, "ksh") == 0
961 		    || fnamecmp(p, "mksh") == 0
962 		    || fnamecmp(p, "pdksh") == 0
963 		    || fnamecmp(p, "zsh") == 0
964 		    || fnamecmp(p, "zsh-beta") == 0
965 		    || fnamecmp(p, "bash") == 0
966 		    || fnamecmp(p, "fish") == 0
967 		    || fnamecmp(p, "ash") == 0
968 		    || fnamecmp(p, "dash") == 0
969 		    || fnamecmp(p, "pwsh") == 0
970 # ifdef MSWIN
971 		    || fnamecmp(p, "cmd") == 0
972 		    || fnamecmp(p, "sh.exe") == 0
973 		    || fnamecmp(p, "ksh.exe") == 0
974 		    || fnamecmp(p, "mksh.exe") == 0
975 		    || fnamecmp(p, "pdksh.exe") == 0
976 		    || fnamecmp(p, "zsh.exe") == 0
977 		    || fnamecmp(p, "zsh-beta.exe") == 0
978 		    || fnamecmp(p, "bash.exe") == 0
979 		    || fnamecmp(p, "cmd.exe") == 0
980 		    || fnamecmp(p, "dash.exe") == 0
981 		    || fnamecmp(p, "pwsh.exe") == 0
982 # endif
983 		    )
984 	    {
985 # if defined(FEAT_QUICKFIX)
986 		if (do_sp)
987 		{
988 #  ifdef MSWIN
989 		    p_sp = (char_u *)">%s 2>&1";
990 #  else
991 		    if (fnamecmp(p, "pwsh") == 0)
992 			p_sp = (char_u *)">%s 2>&1";
993 		    else
994 			p_sp = (char_u *)"2>&1| tee";
995 #  endif
996 		    options[idx_sp].def_val[VI_DEFAULT] = p_sp;
997 		}
998 # endif
999 		if (do_srr)
1000 		{
1001 		    p_srr = (char_u *)">%s 2>&1";
1002 		    options[idx_srr].def_val[VI_DEFAULT] = p_srr;
1003 		}
1004 	    }
1005 	vim_free(p);
1006     }
1007 #endif
1008 
1009 #if defined(MSWIN)
1010     /*
1011      * Set 'shellcmdflag', 'shellxquote', and 'shellquote' depending on the
1012      * 'shell' option.
1013      * This is done after other initializations, where 'shell' might have been
1014      * set, but only if they have not been set before.
1015      * Default values depend on shell (cmd.exe is default shell):
1016      *
1017      *			    p_shcf	p_sxq
1018      * cmd.exe          -   "/c"	"("
1019      * powershell.exe   -   "-Command"	"\""
1020      * pwsh.exe		-   "-c"	"\""
1021      * "sh" like shells -   "-c"	"\""
1022      *
1023      * For Win32 p_sxq is set instead of p_shq to include shell redirection.
1024      */
1025     if (strstr((char *)gettail(p_sh), "powershell") != NULL)
1026     {
1027 	int	idx_opt;
1028 
1029 	idx_opt = findoption((char_u *)"shcf");
1030 	if (idx_opt >= 0 && !(options[idx_opt].flags & P_WAS_SET))
1031 	{
1032 	    p_shcf = (char_u*)"-Command";
1033 	    options[idx_opt].def_val[VI_DEFAULT] = p_shcf;
1034 	}
1035 
1036 	idx_opt = findoption((char_u *)"sxq");
1037 	if (idx_opt >= 0 && !(options[idx_opt].flags & P_WAS_SET))
1038 	{
1039 	    p_sxq = (char_u*)"\"";
1040 	    options[idx_opt].def_val[VI_DEFAULT] = p_sxq;
1041 	}
1042     }
1043     else if (strstr((char *)gettail(p_sh), "sh") != NULL)
1044     {
1045 	int	idx3;
1046 
1047 	idx3 = findoption((char_u *)"shcf");
1048 	if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
1049 	{
1050 	    p_shcf = (char_u *)"-c";
1051 	    options[idx3].def_val[VI_DEFAULT] = p_shcf;
1052 	}
1053 
1054 	// Somehow Win32 requires the quotes around the redirection too
1055 	idx3 = findoption((char_u *)"sxq");
1056 	if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
1057 	{
1058 	    p_sxq = (char_u *)"\"";
1059 	    options[idx3].def_val[VI_DEFAULT] = p_sxq;
1060 	}
1061     }
1062     else if (strstr((char *)gettail(p_sh), "cmd.exe") != NULL)
1063     {
1064 	int	idx3;
1065 
1066 	/*
1067 	 * cmd.exe on Windows will strip the first and last double quote given
1068 	 * on the command line, e.g. most of the time things like:
1069 	 *   cmd /c "my path/to/echo" "my args to echo"
1070 	 * become:
1071 	 *   my path/to/echo" "my args to echo
1072 	 * when executed.
1073 	 *
1074 	 * To avoid this, set shellxquote to surround the command in
1075 	 * parenthesis.  This appears to make most commands work, without
1076 	 * breaking commands that worked previously, such as
1077 	 * '"path with spaces/cmd" "a&b"'.
1078 	 */
1079 	idx3 = findoption((char_u *)"sxq");
1080 	if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
1081 	{
1082 	    p_sxq = (char_u *)"(";
1083 	    options[idx3].def_val[VI_DEFAULT] = p_sxq;
1084 	}
1085 
1086 	idx3 = findoption((char_u *)"shcf");
1087 	if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
1088 	{
1089 	    p_shcf = (char_u *)"/c";
1090 	    options[idx3].def_val[VI_DEFAULT] = p_shcf;
1091 	}
1092     }
1093 #endif
1094 
1095     if (BUFEMPTY())
1096     {
1097 	int idx_ffs = findoption((char_u *)"ffs");
1098 
1099 	// Apply the first entry of 'fileformats' to the initial buffer.
1100 	if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET))
1101 	    set_fileformat(default_fileformat(), OPT_LOCAL);
1102     }
1103 
1104 #ifdef FEAT_TITLE
1105     set_title_defaults();
1106 #endif
1107 }
1108 
1109 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
1110 /*
1111  * When 'helplang' is still at its default value, set it to "lang".
1112  * Only the first two characters of "lang" are used.
1113  */
1114     void
set_helplang_default(char_u * lang)1115 set_helplang_default(char_u *lang)
1116 {
1117     int		idx;
1118 
1119     if (lang == NULL || STRLEN(lang) < 2)	// safety check
1120 	return;
1121     idx = findoption((char_u *)"hlg");
1122     if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
1123     {
1124 	if (options[idx].flags & P_ALLOCED)
1125 	    free_string_option(p_hlg);
1126 	p_hlg = vim_strsave(lang);
1127 	if (p_hlg == NULL)
1128 	    p_hlg = empty_option;
1129 	else
1130 	{
1131 	    // zh_CN becomes "cn", zh_TW becomes "tw"
1132 	    if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5)
1133 	    {
1134 		p_hlg[0] = TOLOWER_ASC(p_hlg[3]);
1135 		p_hlg[1] = TOLOWER_ASC(p_hlg[4]);
1136 	    }
1137 	    // any C like setting, such as C.UTF-8, becomes "en"
1138 	    else if (STRLEN(p_hlg) >= 1 && *p_hlg == 'C')
1139 	    {
1140 		p_hlg[0] = 'e';
1141 		p_hlg[1] = 'n';
1142 	    }
1143 	    p_hlg[2] = NUL;
1144 	}
1145 	options[idx].flags |= P_ALLOCED;
1146     }
1147 }
1148 #endif
1149 
1150 #ifdef FEAT_TITLE
1151 /*
1152  * 'title' and 'icon' only default to true if they have not been set or reset
1153  * in .vimrc and we can read the old value.
1154  * When 'title' and 'icon' have been reset in .vimrc, we won't even check if
1155  * they can be reset.  This reduces startup time when using X on a remote
1156  * machine.
1157  */
1158     void
set_title_defaults(void)1159 set_title_defaults(void)
1160 {
1161     int	    idx1;
1162     long    val;
1163 
1164     /*
1165      * If GUI is (going to be) used, we can always set the window title and
1166      * icon name.  Saves a bit of time, because the X11 display server does
1167      * not need to be contacted.
1168      */
1169     idx1 = findoption((char_u *)"title");
1170     if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
1171     {
1172 #ifdef FEAT_GUI
1173 	if (gui.starting || gui.in_use)
1174 	    val = TRUE;
1175 	else
1176 #endif
1177 	    val = mch_can_restore_title();
1178 	options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
1179 	p_title = val;
1180     }
1181     idx1 = findoption((char_u *)"icon");
1182     if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
1183     {
1184 #ifdef FEAT_GUI
1185 	if (gui.starting || gui.in_use)
1186 	    val = TRUE;
1187 	else
1188 #endif
1189 	    val = mch_can_restore_icon();
1190 	options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
1191 	p_icon = val;
1192     }
1193 }
1194 #endif
1195 
1196     void
ex_set(exarg_T * eap)1197 ex_set(exarg_T *eap)
1198 {
1199     int		flags = 0;
1200 
1201     if (eap->cmdidx == CMD_setlocal)
1202 	flags = OPT_LOCAL;
1203     else if (eap->cmdidx == CMD_setglobal)
1204 	flags = OPT_GLOBAL;
1205 #if defined(FEAT_EVAL) && defined(FEAT_BROWSE)
1206     if ((cmdmod.cmod_flags & CMOD_BROWSE) && flags == 0)
1207 	ex_options(eap);
1208     else
1209 #endif
1210     {
1211 	if (eap->forceit)
1212 	    flags |= OPT_ONECOLUMN;
1213 	(void)do_set(eap->arg, flags);
1214     }
1215 }
1216 
1217 /*
1218  * Parse 'arg' for option settings.
1219  *
1220  * 'arg' may be IObuff, but only when no errors can be present and option
1221  * does not need to be expanded with option_expand().
1222  * "opt_flags":
1223  * 0 for ":set"
1224  * OPT_GLOBAL   for ":setglobal"
1225  * OPT_LOCAL    for ":setlocal" and a modeline
1226  * OPT_MODELINE for a modeline
1227  * OPT_WINONLY  to only set window-local options
1228  * OPT_NOWIN	to skip setting window-local options
1229  *
1230  * returns FAIL if an error is detected, OK otherwise
1231  */
1232     int
do_set(char_u * arg_start,int opt_flags)1233 do_set(
1234     char_u	*arg_start,	// option string (may be written to!)
1235     int		opt_flags)
1236 {
1237     char_u	*arg = arg_start;
1238     int		opt_idx;
1239     char	*errmsg;
1240     char	errbuf[80];
1241     char_u	*startarg;
1242     int		prefix;	// 1: nothing, 0: "no", 2: "inv" in front of name
1243     int		nextchar;	    // next non-white char after option name
1244     int		afterchar;	    // character just after option name
1245     int		len;
1246     int		i;
1247     varnumber_T	value;
1248     int		key;
1249     long_u	flags;		    // flags for current option
1250     char_u	*varp = NULL;	    // pointer to variable for current option
1251     int		did_show = FALSE;   // already showed one value
1252     int		adding;		    // "opt+=arg"
1253     int		prepending;	    // "opt^=arg"
1254     int		removing;	    // "opt-=arg"
1255     int		cp_val = 0;
1256     char_u	key_name[2];
1257 
1258     if (*arg == NUL)
1259     {
1260 	showoptions(0, opt_flags);
1261 	did_show = TRUE;
1262 	goto theend;
1263     }
1264 
1265     while (*arg != NUL)		// loop to process all options
1266     {
1267 	errmsg = NULL;
1268 	startarg = arg;		// remember for error message
1269 
1270 	if (STRNCMP(arg, "all", 3) == 0 && !isalpha(arg[3])
1271 						&& !(opt_flags & OPT_MODELINE))
1272 	{
1273 	    /*
1274 	     * ":set all"  show all options.
1275 	     * ":set all&" set all options to their default value.
1276 	     */
1277 	    arg += 3;
1278 	    if (*arg == '&')
1279 	    {
1280 		++arg;
1281 		// Only for :set command set global value of local options.
1282 		set_options_default(OPT_FREE | opt_flags);
1283 		didset_options();
1284 		didset_options2();
1285 		redraw_all_later(CLEAR);
1286 	    }
1287 	    else
1288 	    {
1289 		showoptions(1, opt_flags);
1290 		did_show = TRUE;
1291 	    }
1292 	}
1293 	else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE))
1294 	{
1295 	    showoptions(2, opt_flags);
1296 	    show_termcodes();
1297 	    did_show = TRUE;
1298 	    arg += 7;
1299 	}
1300 	else
1301 	{
1302 	    prefix = 1;
1303 	    if (STRNCMP(arg, "no", 2) == 0 && STRNCMP(arg, "novice", 6) != 0)
1304 	    {
1305 		prefix = 0;
1306 		arg += 2;
1307 	    }
1308 	    else if (STRNCMP(arg, "inv", 3) == 0)
1309 	    {
1310 		prefix = 2;
1311 		arg += 3;
1312 	    }
1313 
1314 	    // find end of name
1315 	    key = 0;
1316 	    if (*arg == '<')
1317 	    {
1318 		opt_idx = -1;
1319 		// look out for <t_>;>
1320 		if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
1321 		    len = 5;
1322 		else
1323 		{
1324 		    len = 1;
1325 		    while (arg[len] != NUL && arg[len] != '>')
1326 			++len;
1327 		}
1328 		if (arg[len] != '>')
1329 		{
1330 		    errmsg = e_invarg;
1331 		    goto skip;
1332 		}
1333 		arg[len] = NUL;			    // put NUL after name
1334 		if (arg[1] == 't' && arg[2] == '_') // could be term code
1335 		    opt_idx = findoption(arg + 1);
1336 		arg[len++] = '>';		    // restore '>'
1337 		if (opt_idx == -1)
1338 		    key = find_key_option(arg + 1, TRUE);
1339 	    }
1340 	    else
1341 	    {
1342 		len = 0;
1343 		/*
1344 		 * The two characters after "t_" may not be alphanumeric.
1345 		 */
1346 		if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
1347 		    len = 4;
1348 		else
1349 		    while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
1350 			++len;
1351 		nextchar = arg[len];
1352 		arg[len] = NUL;			    // put NUL after name
1353 		opt_idx = findoption(arg);
1354 		arg[len] = nextchar;		    // restore nextchar
1355 		if (opt_idx == -1)
1356 		    key = find_key_option(arg, FALSE);
1357 	    }
1358 
1359 	    // remember character after option name
1360 	    afterchar = arg[len];
1361 
1362 	    if (in_vim9script())
1363 	    {
1364 		char_u *p = skipwhite(arg + len);
1365 
1366 		// disallow white space before =val, +=val, -=val, ^=val
1367 		if (p > arg + len && (p[0] == '='
1368 			|| (vim_strchr((char_u *)"+-^", p[0]) != NULL
1369 							      && p[1] == '=')))
1370 		{
1371 		    errmsg = e_no_white_space_allowed_between_option_and;
1372 		    arg = p;
1373 		    startarg = p;
1374 		    goto skip;
1375 		}
1376 	    }
1377 	    else
1378 		// skip white space, allow ":set ai  ?", ":set hlsearch  !"
1379 		while (VIM_ISWHITE(arg[len]))
1380 		    ++len;
1381 
1382 	    adding = FALSE;
1383 	    prepending = FALSE;
1384 	    removing = FALSE;
1385 	    if (arg[len] != NUL && arg[len + 1] == '=')
1386 	    {
1387 		if (arg[len] == '+')
1388 		{
1389 		    adding = TRUE;		// "+="
1390 		    ++len;
1391 		}
1392 		else if (arg[len] == '^')
1393 		{
1394 		    prepending = TRUE;		// "^="
1395 		    ++len;
1396 		}
1397 		else if (arg[len] == '-')
1398 		{
1399 		    removing = TRUE;		// "-="
1400 		    ++len;
1401 		}
1402 	    }
1403 	    nextchar = arg[len];
1404 
1405 	    if (opt_idx == -1 && key == 0)	// found a mismatch: skip
1406 	    {
1407 		if (in_vim9script() && arg > arg_start
1408 				  && vim_strchr((char_u *)"!&<", *arg) != NULL)
1409 		    errmsg = e_no_white_space_allowed_between_option_and;
1410 		else
1411 		    errmsg = N_("E518: Unknown option");
1412 		goto skip;
1413 	    }
1414 
1415 	    if (opt_idx >= 0)
1416 	    {
1417 		if (options[opt_idx].var == NULL)   // hidden option: skip
1418 		{
1419 		    // Only give an error message when requesting the value of
1420 		    // a hidden option, ignore setting it.
1421 		    if (vim_strchr((char_u *)"=:!&<", nextchar) == NULL
1422 			    && (!(options[opt_idx].flags & P_BOOL)
1423 				|| nextchar == '?'))
1424 			errmsg = N_("E519: Option not supported");
1425 		    goto skip;
1426 		}
1427 
1428 		flags = options[opt_idx].flags;
1429 		varp = get_varp_scope(&(options[opt_idx]), opt_flags);
1430 	    }
1431 	    else
1432 	    {
1433 		flags = P_STRING;
1434 		if (key < 0)
1435 		{
1436 		    key_name[0] = KEY2TERMCAP0(key);
1437 		    key_name[1] = KEY2TERMCAP1(key);
1438 		}
1439 		else
1440 		{
1441 		    key_name[0] = KS_KEY;
1442 		    key_name[1] = (key & 0xff);
1443 		}
1444 	    }
1445 
1446 	    // Skip all options that are not window-local (used when showing
1447 	    // an already loaded buffer in a window).
1448 	    if ((opt_flags & OPT_WINONLY)
1449 			  && (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
1450 		goto skip;
1451 
1452 	    // Skip all options that are window-local (used for :vimgrep).
1453 	    if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
1454 					   && options[opt_idx].var == VAR_WIN)
1455 		goto skip;
1456 
1457 	    // Disallow changing some options from modelines.
1458 	    if (opt_flags & OPT_MODELINE)
1459 	    {
1460 		if (flags & (P_SECURE | P_NO_ML))
1461 		{
1462 		    errmsg = N_("E520: Not allowed in a modeline");
1463 		    goto skip;
1464 		}
1465 		if ((flags & P_MLE) && !p_mle)
1466 		{
1467 		    errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off");
1468 		    goto skip;
1469 		}
1470 #ifdef FEAT_DIFF
1471 		// In diff mode some options are overruled.  This avoids that
1472 		// 'foldmethod' becomes "marker" instead of "diff" and that
1473 		// "wrap" gets set.
1474 		if (curwin->w_p_diff
1475 			&& opt_idx >= 0  // shut up coverity warning
1476 			&& (
1477 #ifdef FEAT_FOLDING
1478 			    options[opt_idx].indir == PV_FDM ||
1479 #endif
1480 			    options[opt_idx].indir == PV_WRAP))
1481 		    goto skip;
1482 #endif
1483 	    }
1484 
1485 #ifdef HAVE_SANDBOX
1486 	    // Disallow changing some options in the sandbox
1487 	    if (sandbox != 0 && (flags & P_SECURE))
1488 	    {
1489 		errmsg = e_not_allowed_in_sandbox;
1490 		goto skip;
1491 	    }
1492 #endif
1493 
1494 	    if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
1495 	    {
1496 		arg += len;
1497 		cp_val = p_cp;
1498 		if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i')
1499 		{
1500 		    if (arg[3] == 'm')	// "opt&vim": set to Vim default
1501 		    {
1502 			cp_val = FALSE;
1503 			arg += 3;
1504 		    }
1505 		    else		// "opt&vi": set to Vi default
1506 		    {
1507 			cp_val = TRUE;
1508 			arg += 2;
1509 		    }
1510 		}
1511 		if (vim_strchr((char_u *)"?!&<", nextchar) != NULL
1512 			&& arg[1] != NUL && !VIM_ISWHITE(arg[1]))
1513 		{
1514 		    errmsg = e_trailing;
1515 		    goto skip;
1516 		}
1517 	    }
1518 
1519 	    /*
1520 	     * allow '=' and ':' for historical reasons (MSDOS command.com
1521 	     * allows only one '=' character per "set" command line. grrr. (jw)
1522 	     */
1523 	    if (nextchar == '?'
1524 		    || (prefix == 1
1525 			&& vim_strchr((char_u *)"=:&<", nextchar) == NULL
1526 			&& !(flags & P_BOOL)))
1527 	    {
1528 		/*
1529 		 * print value
1530 		 */
1531 		if (did_show)
1532 		    msg_putchar('\n');	    // cursor below last one
1533 		else
1534 		{
1535 		    gotocmdline(TRUE);	    // cursor at status line
1536 		    did_show = TRUE;	    // remember that we did a line
1537 		}
1538 		if (opt_idx >= 0)
1539 		{
1540 		    showoneopt(&options[opt_idx], opt_flags);
1541 #ifdef FEAT_EVAL
1542 		    if (p_verbose > 0)
1543 		    {
1544 			// Mention where the option was last set.
1545 			if (varp == options[opt_idx].var)
1546 			    last_set_msg(options[opt_idx].script_ctx);
1547 			else if ((int)options[opt_idx].indir & PV_WIN)
1548 			    last_set_msg(curwin->w_p_script_ctx[
1549 				      (int)options[opt_idx].indir & PV_MASK]);
1550 			else if ((int)options[opt_idx].indir & PV_BUF)
1551 			    last_set_msg(curbuf->b_p_script_ctx[
1552 				      (int)options[opt_idx].indir & PV_MASK]);
1553 		    }
1554 #endif
1555 		}
1556 		else
1557 		{
1558 		    char_u	    *p;
1559 
1560 		    p = find_termcode(key_name);
1561 		    if (p == NULL)
1562 		    {
1563 			errmsg = N_("E846: Key code not set");
1564 			goto skip;
1565 		    }
1566 		    else
1567 			(void)show_one_termcode(key_name, p, TRUE);
1568 		}
1569 		if (nextchar != '?'
1570 			&& nextchar != NUL && !VIM_ISWHITE(afterchar))
1571 		    errmsg = e_trailing;
1572 	    }
1573 	    else
1574 	    {
1575 		int value_is_replaced = !prepending && !adding && !removing;
1576 		int value_checked = FALSE;
1577 
1578 		if (flags & P_BOOL)		    // boolean
1579 		{
1580 		    if (nextchar == '=' || nextchar == ':')
1581 		    {
1582 			errmsg = e_invarg;
1583 			goto skip;
1584 		    }
1585 
1586 		    /*
1587 		     * ":set opt!": invert
1588 		     * ":set opt&": reset to default value
1589 		     * ":set opt<": reset to global value
1590 		     */
1591 		    if (nextchar == '!')
1592 			value = *(int *)(varp) ^ 1;
1593 		    else if (nextchar == '&')
1594 			value = (int)(long)(long_i)options[opt_idx].def_val[
1595 						((flags & P_VI_DEF) || cp_val)
1596 						 ?  VI_DEFAULT : VIM_DEFAULT];
1597 		    else if (nextchar == '<')
1598 		    {
1599 			// For 'autoread' -1 means to use global value.
1600 			if ((int *)varp == &curbuf->b_p_ar
1601 						    && opt_flags == OPT_LOCAL)
1602 			    value = -1;
1603 			else
1604 			    value = *(int *)get_varp_scope(&(options[opt_idx]),
1605 								  OPT_GLOBAL);
1606 		    }
1607 		    else
1608 		    {
1609 			/*
1610 			 * ":set invopt": invert
1611 			 * ":set opt" or ":set noopt": set or reset
1612 			 */
1613 			if (nextchar != NUL && !VIM_ISWHITE(afterchar))
1614 			{
1615 			    errmsg = e_trailing;
1616 			    goto skip;
1617 			}
1618 			if (prefix == 2)	// inv
1619 			    value = *(int *)(varp) ^ 1;
1620 			else
1621 			    value = prefix;
1622 		    }
1623 
1624 		    errmsg = set_bool_option(opt_idx, varp, (int)value,
1625 								   opt_flags);
1626 		}
1627 		else				    // numeric or string
1628 		{
1629 		    if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
1630 							       || prefix != 1)
1631 		    {
1632 			errmsg = e_invarg;
1633 			goto skip;
1634 		    }
1635 
1636 		    if (flags & P_NUM)		    // numeric
1637 		    {
1638 			/*
1639 			 * Different ways to set a number option:
1640 			 * &	    set to default value
1641 			 * <	    set to global value
1642 			 * <xx>	    accept special key codes for 'wildchar'
1643 			 * c	    accept any non-digit for 'wildchar'
1644 			 * [-]0-9   set number
1645 			 * other    error
1646 			 */
1647 			++arg;
1648 			if (nextchar == '&')
1649 			    value = (long)(long_i)options[opt_idx].def_val[
1650 						((flags & P_VI_DEF) || cp_val)
1651 						 ?  VI_DEFAULT : VIM_DEFAULT];
1652 			else if (nextchar == '<')
1653 			{
1654 			    // For 'undolevels' NO_LOCAL_UNDOLEVEL means to
1655 			    // use the global value.
1656 			    if ((long *)varp == &curbuf->b_p_ul
1657 						    && opt_flags == OPT_LOCAL)
1658 				value = NO_LOCAL_UNDOLEVEL;
1659 			    else
1660 				value = *(long *)get_varp_scope(
1661 					     &(options[opt_idx]), OPT_GLOBAL);
1662 			}
1663 			else if (((long *)varp == &p_wc
1664 				    || (long *)varp == &p_wcm)
1665 				&& (*arg == '<'
1666 				    || *arg == '^'
1667 				    || (*arg != NUL
1668 					&& (!arg[1] || VIM_ISWHITE(arg[1]))
1669 					&& !VIM_ISDIGIT(*arg))))
1670 			{
1671 			    value = string_to_key(arg, FALSE);
1672 			    if (value == 0 && (long *)varp != &p_wcm)
1673 			    {
1674 				errmsg = e_invarg;
1675 				goto skip;
1676 			    }
1677 			}
1678 			else if (*arg == '-' || VIM_ISDIGIT(*arg))
1679 			{
1680 			    // Allow negative (for 'undolevels'), octal and
1681 			    // hex numbers.
1682 			    vim_str2nr(arg, NULL, &i, STR2NR_ALL,
1683 						     &value, NULL, 0, TRUE);
1684 			    if (i == 0 || (arg[i] != NUL
1685 						      && !VIM_ISWHITE(arg[i])))
1686 			    {
1687 				errmsg = N_("E521: Number required after =");
1688 				goto skip;
1689 			    }
1690 			}
1691 			else
1692 			{
1693 			    errmsg = N_("E521: Number required after =");
1694 			    goto skip;
1695 			}
1696 
1697 			if (adding)
1698 			    value = *(long *)varp + value;
1699 			if (prepending)
1700 			    value = *(long *)varp * value;
1701 			if (removing)
1702 			    value = *(long *)varp - value;
1703 			errmsg = set_num_option(opt_idx, varp, value,
1704 					   errbuf, sizeof(errbuf), opt_flags);
1705 		    }
1706 		    else if (opt_idx >= 0)		    // string
1707 		    {
1708 			char_u	  *save_arg = NULL;
1709 			char_u	  *s = NULL;
1710 			char_u	  *oldval = NULL; // previous value if *varp
1711 			char_u	  *newval;
1712 			char_u	  *origval = NULL;
1713 			char_u	  *origval_l = NULL;
1714 			char_u	  *origval_g = NULL;
1715 #if defined(FEAT_EVAL)
1716 			char_u	  *saved_origval = NULL;
1717 			char_u	  *saved_origval_l = NULL;
1718 			char_u	  *saved_origval_g = NULL;
1719 			char_u	  *saved_newval = NULL;
1720 #endif
1721 			unsigned  newlen;
1722 			int	  comma;
1723 			int	  new_value_alloced;	// new string option
1724 							// was allocated
1725 
1726 			// When using ":set opt=val" for a global option
1727 			// with a local value the local value will be
1728 			// reset, use the global value here.
1729 			if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
1730 				&& ((int)options[opt_idx].indir & PV_BOTH))
1731 			    varp = options[opt_idx].var;
1732 
1733 			// The old value is kept until we are sure that the
1734 			// new value is valid.
1735 			oldval = *(char_u **)varp;
1736 
1737 			if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1738 			{
1739 			    origval_l = *(char_u **)get_varp_scope(
1740 					       &(options[opt_idx]), OPT_LOCAL);
1741 			    origval_g = *(char_u **)get_varp_scope(
1742 					      &(options[opt_idx]), OPT_GLOBAL);
1743 
1744 			    // A global-local string option might have an empty
1745 			    // option as value to indicate that the global
1746 			    // value should be used.
1747 			    if (((int)options[opt_idx].indir & PV_BOTH)
1748 						  && origval_l == empty_option)
1749 				origval_l = origval_g;
1750 			}
1751 
1752 			// When setting the local value of a global
1753 			// option, the old value may be the global value.
1754 			if (((int)options[opt_idx].indir & PV_BOTH)
1755 					       && (opt_flags & OPT_LOCAL))
1756 			    origval = *(char_u **)get_varp(
1757 						       &options[opt_idx]);
1758 			else
1759 			    origval = oldval;
1760 
1761 			if (nextchar == '&')	// set to default val
1762 			{
1763 			    newval = options[opt_idx].def_val[
1764 						((flags & P_VI_DEF) || cp_val)
1765 						 ?  VI_DEFAULT : VIM_DEFAULT];
1766 			    if ((char_u **)varp == &p_bg)
1767 			    {
1768 				// guess the value of 'background'
1769 #ifdef FEAT_GUI
1770 				if (gui.in_use)
1771 				    newval = gui_bg_default();
1772 				else
1773 #endif
1774 				    newval = term_bg_default();
1775 			    }
1776 			    else if ((char_u **)varp == &p_fencs && enc_utf8)
1777 				newval = fencs_utf8_default;
1778 
1779 			    // expand environment variables and ~ (since the
1780 			    // default value was already expanded, only
1781 			    // required when an environment variable was set
1782 			    // later
1783 			    if (newval == NULL)
1784 				newval = empty_option;
1785 			    else
1786 			    {
1787 				s = option_expand(opt_idx, newval);
1788 				if (s == NULL)
1789 				    s = newval;
1790 				newval = vim_strsave(s);
1791 			    }
1792 			    new_value_alloced = TRUE;
1793 			}
1794 			else if (nextchar == '<')	// set to global val
1795 			{
1796 			    newval = vim_strsave(*(char_u **)get_varp_scope(
1797 					     &(options[opt_idx]), OPT_GLOBAL));
1798 			    new_value_alloced = TRUE;
1799 			}
1800 			else
1801 			{
1802 			    ++arg;	// jump to after the '=' or ':'
1803 
1804 			    /*
1805 			     * Set 'keywordprg' to ":help" if an empty
1806 			     * value was passed to :set by the user.
1807 			     * Misuse errbuf[] for the resulting string.
1808 			     */
1809 			    if (varp == (char_u *)&p_kp
1810 					      && (*arg == NUL || *arg == ' '))
1811 			    {
1812 				STRCPY(errbuf, ":help");
1813 				save_arg = arg;
1814 				arg = (char_u *)errbuf;
1815 			    }
1816 			    /*
1817 			     * Convert 'backspace' number to string, for
1818 			     * adding, prepending and removing string.
1819 			     */
1820 			    else if (varp == (char_u *)&p_bs
1821 					 && VIM_ISDIGIT(**(char_u **)varp))
1822 			    {
1823 				i = getdigits((char_u **)varp);
1824 				switch (i)
1825 				{
1826 				    case 0:
1827 					*(char_u **)varp = empty_option;
1828 					break;
1829 				    case 1:
1830 					*(char_u **)varp = vim_strsave(
1831 						      (char_u *)"indent,eol");
1832 					break;
1833 				    case 2:
1834 					*(char_u **)varp = vim_strsave(
1835 						(char_u *)"indent,eol,start");
1836 					break;
1837 				    case 3:
1838 					*(char_u **)varp = vim_strsave(
1839 						(char_u *)"indent,eol,nostop");
1840 					break;
1841 				}
1842 				vim_free(oldval);
1843 				if (origval == oldval)
1844 				    origval = *(char_u **)varp;
1845 				if (origval_l == oldval)
1846 				    origval_l = *(char_u **)varp;
1847 				if (origval_g == oldval)
1848 				    origval_g = *(char_u **)varp;
1849 				oldval = *(char_u **)varp;
1850 			    }
1851 			    /*
1852 			     * Convert 'whichwrap' number to string, for
1853 			     * backwards compatibility with Vim 3.0.
1854 			     * Misuse errbuf[] for the resulting string.
1855 			     */
1856 			    else if (varp == (char_u *)&p_ww
1857 							 && VIM_ISDIGIT(*arg))
1858 			    {
1859 				*errbuf = NUL;
1860 				i = getdigits(&arg);
1861 				if (i & 1)
1862 				    STRCAT(errbuf, "b,");
1863 				if (i & 2)
1864 				    STRCAT(errbuf, "s,");
1865 				if (i & 4)
1866 				    STRCAT(errbuf, "h,l,");
1867 				if (i & 8)
1868 				    STRCAT(errbuf, "<,>,");
1869 				if (i & 16)
1870 				    STRCAT(errbuf, "[,],");
1871 				if (*errbuf != NUL)	// remove trailing ,
1872 				    errbuf[STRLEN(errbuf) - 1] = NUL;
1873 				save_arg = arg;
1874 				arg = (char_u *)errbuf;
1875 			    }
1876 			    /*
1877 			     * Remove '>' before 'dir' and 'bdir', for
1878 			     * backwards compatibility with version 3.0
1879 			     */
1880 			    else if (  *arg == '>'
1881 				    && (varp == (char_u *)&p_dir
1882 					    || varp == (char_u *)&p_bdir))
1883 			    {
1884 				++arg;
1885 			    }
1886 
1887 			    /*
1888 			     * Copy the new string into allocated memory.
1889 			     * Can't use set_string_option_direct(), because
1890 			     * we need to remove the backslashes.
1891 			     */
1892 			    // get a bit too much
1893 			    newlen = (unsigned)STRLEN(arg) + 1;
1894 			    if (adding || prepending || removing)
1895 				newlen += (unsigned)STRLEN(origval) + 1;
1896 			    newval = alloc(newlen);
1897 			    if (newval == NULL)  // out of mem, don't change
1898 				break;
1899 			    s = newval;
1900 
1901 			    /*
1902 			     * Copy the string, skip over escaped chars.
1903 			     * For MS-DOS and WIN32 backslashes before normal
1904 			     * file name characters are not removed, and keep
1905 			     * backslash at start, for "\\machine\path", but
1906 			     * do remove it for "\\\\machine\\path".
1907 			     * The reverse is found in ExpandOldSetting().
1908 			     */
1909 			    while (*arg && !VIM_ISWHITE(*arg))
1910 			    {
1911 				if (*arg == '\\' && arg[1] != NUL
1912 #ifdef BACKSLASH_IN_FILENAME
1913 					&& !((flags & P_EXPAND)
1914 						&& vim_isfilec(arg[1])
1915 						&& !VIM_ISWHITE(arg[1])
1916 						&& (arg[1] != '\\'
1917 						    || (s == newval
1918 							&& arg[2] != '\\')))
1919 #endif
1920 								    )
1921 				    ++arg;	// remove backslash
1922 				if (has_mbyte
1923 					&& (i = (*mb_ptr2len)(arg)) > 1)
1924 				{
1925 				    // copy multibyte char
1926 				    mch_memmove(s, arg, (size_t)i);
1927 				    arg += i;
1928 				    s += i;
1929 				}
1930 				else
1931 				    *s++ = *arg++;
1932 			    }
1933 			    *s = NUL;
1934 
1935 			    /*
1936 			     * Expand environment variables and ~.
1937 			     * Don't do it when adding without inserting a
1938 			     * comma.
1939 			     */
1940 			    if (!(adding || prepending || removing)
1941 							 || (flags & P_COMMA))
1942 			    {
1943 				s = option_expand(opt_idx, newval);
1944 				if (s != NULL)
1945 				{
1946 				    vim_free(newval);
1947 				    newlen = (unsigned)STRLEN(s) + 1;
1948 				    if (adding || prepending || removing)
1949 					newlen += (unsigned)STRLEN(origval) + 1;
1950 				    newval = alloc(newlen);
1951 				    if (newval == NULL)
1952 					break;
1953 				    STRCPY(newval, s);
1954 				}
1955 			    }
1956 
1957 			    // locate newval[] in origval[] when removing it
1958 			    // and when adding to avoid duplicates
1959 			    i = 0;	// init for GCC
1960 			    if (removing || (flags & P_NODUP))
1961 			    {
1962 				i = (int)STRLEN(newval);
1963 				s = find_dup_item(origval, newval, flags);
1964 
1965 				// do not add if already there
1966 				if ((adding || prepending) && s != NULL)
1967 				{
1968 				    prepending = FALSE;
1969 				    adding = FALSE;
1970 				    STRCPY(newval, origval);
1971 				}
1972 
1973 				// if no duplicate, move pointer to end of
1974 				// original value
1975 				if (s == NULL)
1976 				    s = origval + (int)STRLEN(origval);
1977 			    }
1978 
1979 			    // concatenate the two strings; add a ',' if
1980 			    // needed
1981 			    if (adding || prepending)
1982 			    {
1983 				comma = ((flags & P_COMMA) && *origval != NUL
1984 							   && *newval != NUL);
1985 				if (adding)
1986 				{
1987 				    i = (int)STRLEN(origval);
1988 				    // strip a trailing comma, would get 2
1989 				    if (comma && i > 1
1990 					  && (flags & P_ONECOMMA) == P_ONECOMMA
1991 					  && origval[i - 1] == ','
1992 					  && origval[i - 2] != '\\')
1993 					i--;
1994 				    mch_memmove(newval + i + comma, newval,
1995 							  STRLEN(newval) + 1);
1996 				    mch_memmove(newval, origval, (size_t)i);
1997 				}
1998 				else
1999 				{
2000 				    i = (int)STRLEN(newval);
2001 				    STRMOVE(newval + i + comma, origval);
2002 				}
2003 				if (comma)
2004 				    newval[i] = ',';
2005 			    }
2006 
2007 			    // Remove newval[] from origval[]. (Note: "i" has
2008 			    // been set above and is used here).
2009 			    if (removing)
2010 			    {
2011 				STRCPY(newval, origval);
2012 				if (*s)
2013 				{
2014 				    // may need to remove a comma
2015 				    if (flags & P_COMMA)
2016 				    {
2017 					if (s == origval)
2018 					{
2019 					    // include comma after string
2020 					    if (s[i] == ',')
2021 						++i;
2022 					}
2023 					else
2024 					{
2025 					    // include comma before string
2026 					    --s;
2027 					    ++i;
2028 					}
2029 				    }
2030 				    STRMOVE(newval + (s - origval), s + i);
2031 				}
2032 			    }
2033 
2034 			    if (flags & P_FLAGLIST)
2035 			    {
2036 				// Remove flags that appear twice.
2037 				for (s = newval; *s;)
2038 				{
2039 				    // if options have P_FLAGLIST and
2040 				    // P_ONECOMMA such as 'whichwrap'
2041 				    if (flags & P_ONECOMMA)
2042 				    {
2043 					if (*s != ',' && *(s + 1) == ','
2044 					      && vim_strchr(s + 2, *s) != NULL)
2045 					{
2046 					    // Remove the duplicated value and
2047 					    // the next comma.
2048 					    STRMOVE(s, s + 2);
2049 					    continue;
2050 					}
2051 				    }
2052 				    else
2053 				    {
2054 					if ((!(flags & P_COMMA) || *s != ',')
2055 					      && vim_strchr(s + 1, *s) != NULL)
2056 					{
2057 					    STRMOVE(s, s + 1);
2058 					    continue;
2059 					}
2060 				    }
2061 				    ++s;
2062 				}
2063 			    }
2064 
2065 			    if (save_arg != NULL)   // number for 'whichwrap'
2066 				arg = save_arg;
2067 			    new_value_alloced = TRUE;
2068 			}
2069 
2070 			/*
2071 			 * Set the new value.
2072 			 */
2073 			*(char_u **)(varp) = newval;
2074 
2075 #if defined(FEAT_EVAL)
2076 			if (!starting
2077 # ifdef FEAT_CRYPT
2078 				&& options[opt_idx].indir != PV_KEY
2079 # endif
2080 					  && origval != NULL && newval != NULL)
2081 			{
2082 			    // origval may be freed by
2083 			    // did_set_string_option(), make a copy.
2084 			    saved_origval = vim_strsave(origval);
2085 			    // newval (and varp) may become invalid if the
2086 			    // buffer is closed by autocommands.
2087 			    saved_newval = vim_strsave(newval);
2088 			    if (origval_l != NULL)
2089 				saved_origval_l = vim_strsave(origval_l);
2090 			    if (origval_g != NULL)
2091 				saved_origval_g = vim_strsave(origval_g);
2092 			}
2093 #endif
2094 
2095 			{
2096 			    long_u *p = insecure_flag(opt_idx, opt_flags);
2097 			    int	    secure_saved = secure;
2098 
2099 			    // When an option is set in the sandbox, from a
2100 			    // modeline or in secure mode, then deal with side
2101 			    // effects in secure mode.  Also when the value was
2102 			    // set with the P_INSECURE flag and is not
2103 			    // completely replaced.
2104 			    if ((opt_flags & OPT_MODELINE)
2105 #ifdef HAVE_SANDBOX
2106 				  || sandbox != 0
2107 #endif
2108 				  || (!value_is_replaced && (*p & P_INSECURE)))
2109 				secure = 1;
2110 
2111 			    // Handle side effects, and set the global value
2112 			    // for ":set" on local options. Note: when setting
2113 			    // 'syntax' or 'filetype' autocommands may be
2114 			    // triggered that can cause havoc.
2115 			    errmsg = did_set_string_option(
2116 				    opt_idx, (char_u **)varp,
2117 				    new_value_alloced, oldval, errbuf,
2118 				    opt_flags, &value_checked);
2119 
2120 			    secure = secure_saved;
2121 			}
2122 
2123 #if defined(FEAT_EVAL)
2124 			if (errmsg == NULL)
2125 			    trigger_optionsset_string(
2126 				    opt_idx, opt_flags, saved_origval,
2127 				    saved_origval_l, saved_origval_g,
2128 				    saved_newval);
2129 			vim_free(saved_origval);
2130 			vim_free(saved_origval_l);
2131 			vim_free(saved_origval_g);
2132 			vim_free(saved_newval);
2133 #endif
2134 			// If error detected, print the error message.
2135 			if (errmsg != NULL)
2136 			    goto skip;
2137 		    }
2138 		    else	    // key code option
2139 		    {
2140 			char_u	    *p;
2141 
2142 			if (nextchar == '&')
2143 			{
2144 			    if (add_termcap_entry(key_name, TRUE) == FAIL)
2145 				errmsg = N_("E522: Not found in termcap");
2146 			}
2147 			else
2148 			{
2149 			    ++arg; // jump to after the '=' or ':'
2150 			    for (p = arg; *p && !VIM_ISWHITE(*p); ++p)
2151 				if (*p == '\\' && p[1] != NUL)
2152 				    ++p;
2153 			    nextchar = *p;
2154 			    *p = NUL;
2155 			    add_termcode(key_name, arg, FALSE);
2156 			    *p = nextchar;
2157 			}
2158 			if (full_screen)
2159 			    ttest(FALSE);
2160 			redraw_all_later(CLEAR);
2161 		    }
2162 		}
2163 
2164 		if (opt_idx >= 0)
2165 		    did_set_option(
2166 			 opt_idx, opt_flags, value_is_replaced, value_checked);
2167 	    }
2168 
2169 skip:
2170 	    /*
2171 	     * Advance to next argument.
2172 	     * - skip until a blank found, taking care of backslashes
2173 	     * - skip blanks
2174 	     * - skip one "=val" argument (for hidden options ":set gfn =xx")
2175 	     */
2176 	    for (i = 0; i < 2 ; ++i)
2177 	    {
2178 		while (*arg != NUL && !VIM_ISWHITE(*arg))
2179 		    if (*arg++ == '\\' && *arg != NUL)
2180 			++arg;
2181 		arg = skipwhite(arg);
2182 		if (*arg != '=')
2183 		    break;
2184 	    }
2185 	}
2186 
2187 	if (errmsg != NULL)
2188 	{
2189 	    vim_strncpy(IObuff, (char_u *)_(errmsg), IOSIZE - 1);
2190 	    i = (int)STRLEN(IObuff) + 2;
2191 	    if (i + (arg - startarg) < IOSIZE)
2192 	    {
2193 		// append the argument with the error
2194 		STRCAT(IObuff, ": ");
2195 		mch_memmove(IObuff + i, startarg, (arg - startarg));
2196 		IObuff[i + (arg - startarg)] = NUL;
2197 	    }
2198 	    // make sure all characters are printable
2199 	    trans_characters(IObuff, IOSIZE);
2200 
2201 	    ++no_wait_return;		// wait_return done later
2202 	    emsg((char *)IObuff);	// show error highlighted
2203 	    --no_wait_return;
2204 
2205 	    return FAIL;
2206 	}
2207 
2208 	arg = skipwhite(arg);
2209     }
2210 
2211 theend:
2212     if (silent_mode && did_show)
2213     {
2214 	// After displaying option values in silent mode.
2215 	silent_mode = FALSE;
2216 	info_message = TRUE;	// use mch_msg(), not mch_errmsg()
2217 	msg_putchar('\n');
2218 	cursor_on();		// msg_start() switches it off
2219 	out_flush();
2220 	silent_mode = TRUE;
2221 	info_message = FALSE;	// use mch_msg(), not mch_errmsg()
2222     }
2223 
2224     return OK;
2225 }
2226 
2227 /*
2228  * Call this when an option has been given a new value through a user command.
2229  * Sets the P_WAS_SET flag and takes care of the P_INSECURE flag.
2230  */
2231     void
did_set_option(int opt_idx,int opt_flags,int new_value,int value_checked)2232 did_set_option(
2233     int	    opt_idx,
2234     int	    opt_flags,	    // possibly with OPT_MODELINE
2235     int	    new_value,	    // value was replaced completely
2236     int	    value_checked)  // value was checked to be safe, no need to set the
2237 			    // P_INSECURE flag.
2238 {
2239     long_u	*p;
2240 
2241     options[opt_idx].flags |= P_WAS_SET;
2242 
2243     // When an option is set in the sandbox, from a modeline or in secure mode
2244     // set the P_INSECURE flag.  Otherwise, if a new value is stored reset the
2245     // flag.
2246     p = insecure_flag(opt_idx, opt_flags);
2247     if (!value_checked && (secure
2248 #ifdef HAVE_SANDBOX
2249 	    || sandbox != 0
2250 #endif
2251 	    || (opt_flags & OPT_MODELINE)))
2252 	*p = *p | P_INSECURE;
2253     else if (new_value)
2254 	*p = *p & ~P_INSECURE;
2255 }
2256 
2257 /*
2258  * Convert a key name or string into a key value.
2259  * Used for 'wildchar' and 'cedit' options.
2260  * When "multi_byte" is TRUE allow for multi-byte characters.
2261  */
2262     int
string_to_key(char_u * arg,int multi_byte)2263 string_to_key(char_u *arg, int multi_byte)
2264 {
2265     if (*arg == '<')
2266 	return find_key_option(arg + 1, TRUE);
2267     if (*arg == '^')
2268 	return Ctrl_chr(arg[1]);
2269     if (multi_byte)
2270 	return PTR2CHAR(arg);
2271     return *arg;
2272 }
2273 
2274 #ifdef FEAT_TITLE
2275 /*
2276  * When changing 'title', 'titlestring', 'icon' or 'iconstring', call
2277  * maketitle() to create and display it.
2278  * When switching the title or icon off, call mch_restore_title() to get
2279  * the old value back.
2280  */
2281     void
did_set_title(void)2282 did_set_title(void)
2283 {
2284     if (starting != NO_SCREEN
2285 #ifdef FEAT_GUI
2286 	    && !gui.starting
2287 #endif
2288 				)
2289 	maketitle();
2290 }
2291 #endif
2292 
2293 /*
2294  * set_options_bin -  called when 'bin' changes value.
2295  */
2296     void
set_options_bin(int oldval,int newval,int opt_flags)2297 set_options_bin(
2298     int		oldval,
2299     int		newval,
2300     int		opt_flags)	// OPT_LOCAL and/or OPT_GLOBAL
2301 {
2302     /*
2303      * The option values that are changed when 'bin' changes are
2304      * copied when 'bin is set and restored when 'bin' is reset.
2305      */
2306     if (newval)
2307     {
2308 	if (!oldval)		// switched on
2309 	{
2310 	    if (!(opt_flags & OPT_GLOBAL))
2311 	    {
2312 		curbuf->b_p_tw_nobin = curbuf->b_p_tw;
2313 		curbuf->b_p_wm_nobin = curbuf->b_p_wm;
2314 		curbuf->b_p_ml_nobin = curbuf->b_p_ml;
2315 		curbuf->b_p_et_nobin = curbuf->b_p_et;
2316 	    }
2317 	    if (!(opt_flags & OPT_LOCAL))
2318 	    {
2319 		p_tw_nobin = p_tw;
2320 		p_wm_nobin = p_wm;
2321 		p_ml_nobin = p_ml;
2322 		p_et_nobin = p_et;
2323 	    }
2324 	}
2325 
2326 	if (!(opt_flags & OPT_GLOBAL))
2327 	{
2328 	    curbuf->b_p_tw = 0;	// no automatic line wrap
2329 	    curbuf->b_p_wm = 0;	// no automatic line wrap
2330 	    curbuf->b_p_ml = 0;	// no modelines
2331 	    curbuf->b_p_et = 0;	// no expandtab
2332 	}
2333 	if (!(opt_flags & OPT_LOCAL))
2334 	{
2335 	    p_tw = 0;
2336 	    p_wm = 0;
2337 	    p_ml = FALSE;
2338 	    p_et = FALSE;
2339 	    p_bin = TRUE;	// needed when called for the "-b" argument
2340 	}
2341     }
2342     else if (oldval)		// switched off
2343     {
2344 	if (!(opt_flags & OPT_GLOBAL))
2345 	{
2346 	    curbuf->b_p_tw = curbuf->b_p_tw_nobin;
2347 	    curbuf->b_p_wm = curbuf->b_p_wm_nobin;
2348 	    curbuf->b_p_ml = curbuf->b_p_ml_nobin;
2349 	    curbuf->b_p_et = curbuf->b_p_et_nobin;
2350 	}
2351 	if (!(opt_flags & OPT_LOCAL))
2352 	{
2353 	    p_tw = p_tw_nobin;
2354 	    p_wm = p_wm_nobin;
2355 	    p_ml = p_ml_nobin;
2356 	    p_et = p_et_nobin;
2357 	}
2358     }
2359 }
2360 
2361 /*
2362  * Expand environment variables for some string options.
2363  * These string options cannot be indirect!
2364  * If "val" is NULL expand the current value of the option.
2365  * Return pointer to NameBuff, or NULL when not expanded.
2366  */
2367     static char_u *
option_expand(int opt_idx,char_u * val)2368 option_expand(int opt_idx, char_u *val)
2369 {
2370     // if option doesn't need expansion nothing to do
2371     if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL)
2372 	return NULL;
2373 
2374     // If val is longer than MAXPATHL no meaningful expansion can be done,
2375     // expand_env() would truncate the string.
2376     if (val != NULL && STRLEN(val) > MAXPATHL)
2377 	return NULL;
2378 
2379     if (val == NULL)
2380 	val = *(char_u **)options[opt_idx].var;
2381 
2382     /*
2383      * Expanding this with NameBuff, expand_env() must not be passed IObuff.
2384      * Escape spaces when expanding 'tags', they are used to separate file
2385      * names.
2386      * For 'spellsuggest' expand after "file:".
2387      */
2388     expand_env_esc(val, NameBuff, MAXPATHL,
2389 	    (char_u **)options[opt_idx].var == &p_tags, FALSE,
2390 #ifdef FEAT_SPELL
2391 	    (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" :
2392 #endif
2393 				  NULL);
2394     if (STRCMP(NameBuff, val) == 0)   // they are the same
2395 	return NULL;
2396 
2397     return NameBuff;
2398 }
2399 
2400 /*
2401  * After setting various option values: recompute variables that depend on
2402  * option values.
2403  */
2404     static void
didset_options(void)2405 didset_options(void)
2406 {
2407     // initialize the table for 'iskeyword' et.al.
2408     (void)init_chartab();
2409 
2410     didset_string_options();
2411 
2412 #ifdef FEAT_SPELL
2413     (void)spell_check_msm();
2414     (void)spell_check_sps();
2415     (void)compile_cap_prog(curwin->w_s);
2416     (void)did_set_spell_option(TRUE);
2417 #endif
2418 #ifdef FEAT_CMDWIN
2419     // set cedit_key
2420     (void)check_cedit();
2421 #endif
2422 #ifdef FEAT_LINEBREAK
2423     // initialize the table for 'breakat'.
2424     fill_breakat_flags();
2425 #endif
2426     after_copy_winopt(curwin);
2427 }
2428 
2429 /*
2430  * More side effects of setting options.
2431  */
2432     static void
didset_options2(void)2433 didset_options2(void)
2434 {
2435     // Initialize the highlight_attr[] table.
2436     (void)highlight_changed();
2437 
2438     // Parse default for 'wildmode'
2439     check_opt_wim();
2440 
2441     // Parse default for 'listchars'.
2442     (void)set_chars_option(curwin, &curwin->w_p_lcs);
2443 
2444     // Parse default for 'fillchars'.
2445     (void)set_chars_option(curwin, &p_fcs);
2446 
2447 #ifdef FEAT_CLIPBOARD
2448     // Parse default for 'clipboard'
2449     (void)check_clipboard_option();
2450 #endif
2451 #ifdef FEAT_VARTABS
2452     vim_free(curbuf->b_p_vsts_array);
2453     (void)tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
2454     vim_free(curbuf->b_p_vts_array);
2455     (void)tabstop_set(curbuf->b_p_vts,  &curbuf->b_p_vts_array);
2456 #endif
2457 }
2458 
2459 /*
2460  * Check for string options that are NULL (normally only termcap options).
2461  */
2462     void
check_options(void)2463 check_options(void)
2464 {
2465     int		opt_idx;
2466 
2467     for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++)
2468 	if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL)
2469 	    check_string_option((char_u **)get_varp(&(options[opt_idx])));
2470 }
2471 
2472 /*
2473  * Return the option index found by a pointer into term_strings[].
2474  * Return -1 if not found.
2475  */
2476     int
get_term_opt_idx(char_u ** p)2477 get_term_opt_idx(char_u **p)
2478 {
2479     int opt_idx;
2480 
2481     for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++)
2482 	if (options[opt_idx].var == (char_u *)p)
2483 	    return opt_idx;
2484     return -1; // cannot happen: didn't find it!
2485 }
2486 
2487 /*
2488  * Mark a terminal option as allocated, found by a pointer into term_strings[].
2489  * Return the option index or -1 if not found.
2490  */
2491     int
set_term_option_alloced(char_u ** p)2492 set_term_option_alloced(char_u **p)
2493 {
2494     int		opt_idx = get_term_opt_idx(p);
2495 
2496     if (opt_idx >= 0)
2497 	options[opt_idx].flags |= P_ALLOCED;
2498     return opt_idx;
2499 }
2500 
2501 #if defined(FEAT_EVAL) || defined(PROTO)
2502 /*
2503  * Return TRUE when option "opt" was set from a modeline or in secure mode.
2504  * Return FALSE when it wasn't.
2505  * Return -1 for an unknown option.
2506  */
2507     int
was_set_insecurely(char_u * opt,int opt_flags)2508 was_set_insecurely(char_u *opt, int opt_flags)
2509 {
2510     int	    idx = findoption(opt);
2511     long_u  *flagp;
2512 
2513     if (idx >= 0)
2514     {
2515 	flagp = insecure_flag(idx, opt_flags);
2516 	return (*flagp & P_INSECURE) != 0;
2517     }
2518     internal_error("was_set_insecurely()");
2519     return -1;
2520 }
2521 
2522 /*
2523  * Get a pointer to the flags used for the P_INSECURE flag of option
2524  * "opt_idx".  For some local options a local flags field is used.
2525  * NOTE: Caller must make sure that "curwin" is set to the window from which
2526  * the option is used.
2527  */
2528     static long_u *
insecure_flag(int opt_idx,int opt_flags)2529 insecure_flag(int opt_idx, int opt_flags)
2530 {
2531     if (opt_flags & OPT_LOCAL)
2532 	switch ((int)options[opt_idx].indir)
2533 	{
2534 #ifdef FEAT_STL_OPT
2535 	    case PV_STL:	return &curwin->w_p_stl_flags;
2536 #endif
2537 #ifdef FEAT_EVAL
2538 # ifdef FEAT_FOLDING
2539 	    case PV_FDE:	return &curwin->w_p_fde_flags;
2540 	    case PV_FDT:	return &curwin->w_p_fdt_flags;
2541 # endif
2542 # ifdef FEAT_BEVAL
2543 	    case PV_BEXPR:	return &curbuf->b_p_bexpr_flags;
2544 # endif
2545 # if defined(FEAT_CINDENT)
2546 	    case PV_INDE:	return &curbuf->b_p_inde_flags;
2547 # endif
2548 	    case PV_FEX:	return &curbuf->b_p_fex_flags;
2549 # ifdef FEAT_FIND_ID
2550 	    case PV_INEX:	return &curbuf->b_p_inex_flags;
2551 # endif
2552 #endif
2553 	}
2554 
2555     // Nothing special, return global flags field.
2556     return &options[opt_idx].flags;
2557 }
2558 #endif
2559 
2560 #if defined(FEAT_TITLE) || defined(PROTO)
2561 /*
2562  * Redraw the window title and/or tab page text later.
2563  */
redraw_titles(void)2564 void redraw_titles(void)
2565 {
2566     need_maketitle = TRUE;
2567     redraw_tabline = TRUE;
2568 }
2569 #endif
2570 
2571 /*
2572  * Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
2573  * characters or characters in "allowed".
2574  */
2575     int
valid_name(char_u * val,char * allowed)2576 valid_name(char_u *val, char *allowed)
2577 {
2578     char_u *s;
2579 
2580     for (s = val; *s != NUL; ++s)
2581 	if (!ASCII_ISALNUM(*s) && vim_strchr((char_u *)allowed, *s) == NULL)
2582 	    return FALSE;
2583     return TRUE;
2584 }
2585 
2586 #if defined(FEAT_EVAL) || defined(PROTO)
2587 /*
2588  * Set the script_ctx for an option, taking care of setting the buffer- or
2589  * window-local value.
2590  */
2591     void
set_option_sctx_idx(int opt_idx,int opt_flags,sctx_T script_ctx)2592 set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
2593 {
2594     int		both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
2595     int		indir = (int)options[opt_idx].indir;
2596     sctx_T	new_script_ctx = script_ctx;
2597 
2598     // Modeline already has the line number set.
2599     if (!(opt_flags & OPT_MODELINE))
2600 	new_script_ctx.sc_lnum += SOURCING_LNUM;
2601 
2602     // Remember where the option was set.  For local options need to do that
2603     // in the buffer or window structure.
2604     if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0)
2605 	options[opt_idx].script_ctx = new_script_ctx;
2606     if (both || (opt_flags & OPT_LOCAL))
2607     {
2608 	if (indir & PV_BUF)
2609 	    curbuf->b_p_script_ctx[indir & PV_MASK] = new_script_ctx;
2610 	else if (indir & PV_WIN)
2611 	    curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx;
2612     }
2613 }
2614 
2615 /*
2616  * Set the script_ctx for a termcap option.
2617  * "name" must be the two character code, e.g. "RV".
2618  * When "name" is NULL use "opt_idx".
2619  */
2620     void
set_term_option_sctx_idx(char * name,int opt_idx)2621 set_term_option_sctx_idx(char *name, int opt_idx)
2622 {
2623     char_u  buf[5];
2624     int	    idx;
2625 
2626     if (name == NULL)
2627 	idx = opt_idx;
2628     else
2629     {
2630 	buf[0] = 't';
2631 	buf[1] = '_';
2632 	buf[2] = name[0];
2633 	buf[3] = name[1];
2634 	buf[4] = 0;
2635 	idx = findoption(buf);
2636     }
2637     if (idx >= 0)
2638 	set_option_sctx_idx(idx, OPT_GLOBAL, current_sctx);
2639 }
2640 #endif
2641 
2642 #if defined(FEAT_EVAL)
2643 /*
2644  * Apply the OptionSet autocommand.
2645  */
2646     static void
apply_optionset_autocmd(int opt_idx,long opt_flags,long oldval,long oldval_g,long newval,char * errmsg)2647 apply_optionset_autocmd(
2648 	int	opt_idx,
2649 	long	opt_flags,
2650 	long	oldval,
2651 	long	oldval_g,
2652 	long	newval,
2653 	char	*errmsg)
2654 {
2655     char_u buf_old[12], buf_old_global[12], buf_new[12], buf_type[12];
2656 
2657     // Don't do this while starting up, failure or recursively.
2658     if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL)
2659 	return;
2660 
2661     vim_snprintf((char *)buf_old, sizeof(buf_old), "%ld", oldval);
2662     vim_snprintf((char *)buf_old_global, sizeof(buf_old_global), "%ld",
2663 							oldval_g);
2664     vim_snprintf((char *)buf_new, sizeof(buf_new), "%ld", newval);
2665     vim_snprintf((char *)buf_type, sizeof(buf_type), "%s",
2666 				(opt_flags & OPT_LOCAL) ? "local" : "global");
2667     set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
2668     set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
2669     set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
2670     if (opt_flags & OPT_LOCAL)
2671     {
2672 	set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
2673 	set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
2674     }
2675     if (opt_flags & OPT_GLOBAL)
2676     {
2677 	set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
2678 	set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
2679     }
2680     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2681     {
2682 	set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
2683 	set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
2684 	set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
2685     }
2686     if (opt_flags & OPT_MODELINE)
2687     {
2688 	set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
2689 	set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
2690     }
2691     apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
2692 	    NULL, FALSE, NULL);
2693     reset_v_option_vars();
2694 }
2695 #endif
2696 
2697 /*
2698  * Set the value of a boolean option, and take care of side effects.
2699  * Returns NULL for success, or an error message for an error.
2700  */
2701     static char *
set_bool_option(int opt_idx,char_u * varp,int value,int opt_flags)2702 set_bool_option(
2703     int		opt_idx,		// index in options[] table
2704     char_u	*varp,			// pointer to the option variable
2705     int		value,			// new value
2706     int		opt_flags)		// OPT_LOCAL and/or OPT_GLOBAL
2707 {
2708     int		old_value = *(int *)varp;
2709 #if defined(FEAT_EVAL)
2710     int		old_global_value = 0;
2711 #endif
2712 
2713     // Disallow changing some options from secure mode
2714     if ((secure
2715 #ifdef HAVE_SANDBOX
2716 		|| sandbox != 0
2717 #endif
2718 		) && (options[opt_idx].flags & P_SECURE))
2719 	return e_secure;
2720 
2721 #if defined(FEAT_EVAL)
2722     // Save the global value before changing anything. This is needed as for
2723     // a global-only option setting the "local value" in fact sets the global
2724     // value (since there is only one value).
2725     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2726 	old_global_value = *(int *)get_varp_scope(&(options[opt_idx]),
2727 								   OPT_GLOBAL);
2728 #endif
2729 
2730     *(int *)varp = value;	    // set the new value
2731 #ifdef FEAT_EVAL
2732     // Remember where the option was set.
2733     set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
2734 #endif
2735 
2736 #ifdef FEAT_GUI
2737     need_mouse_correct = TRUE;
2738 #endif
2739 
2740     // May set global value for local option.
2741     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2742 	*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
2743 
2744     /*
2745      * Handle side effects of changing a bool option.
2746      */
2747 
2748     // 'compatible'
2749     if ((int *)varp == &p_cp)
2750 	compatible_set();
2751 
2752 #ifdef FEAT_LANGMAP
2753     if ((int *)varp == &p_lrm)
2754 	// 'langremap' -> !'langnoremap'
2755 	p_lnr = !p_lrm;
2756     else if ((int *)varp == &p_lnr)
2757 	// 'langnoremap' -> !'langremap'
2758 	p_lrm = !p_lnr;
2759 #endif
2760 
2761 #ifdef FEAT_SYN_HL
2762     else if ((int *)varp == &curwin->w_p_cul && !value && old_value)
2763 	reset_cursorline();
2764 #endif
2765 
2766 #ifdef FEAT_PERSISTENT_UNDO
2767     // 'undofile'
2768     else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf)
2769     {
2770 	// Only take action when the option was set. When reset we do not
2771 	// delete the undo file, the option may be set again without making
2772 	// any changes in between.
2773 	if (curbuf->b_p_udf || p_udf)
2774 	{
2775 	    char_u	hash[UNDO_HASH_SIZE];
2776 	    buf_T	*save_curbuf = curbuf;
2777 
2778 	    FOR_ALL_BUFFERS(curbuf)
2779 	    {
2780 		// When 'undofile' is set globally: for every buffer, otherwise
2781 		// only for the current buffer: Try to read in the undofile,
2782 		// if one exists, the buffer wasn't changed and the buffer was
2783 		// loaded
2784 		if ((curbuf == save_curbuf
2785 				|| (opt_flags & OPT_GLOBAL) || opt_flags == 0)
2786 			&& !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL)
2787 		{
2788 #ifdef FEAT_CRYPT
2789 		    if (crypt_get_method_nr(curbuf) == CRYPT_M_SOD)
2790 			continue;
2791 #endif
2792 		    u_compute_hash(hash);
2793 		    u_read_undo(NULL, hash, curbuf->b_fname);
2794 		}
2795 	    }
2796 	    curbuf = save_curbuf;
2797 	}
2798     }
2799 #endif
2800 
2801     else if ((int *)varp == &curbuf->b_p_ro)
2802     {
2803 	// when 'readonly' is reset globally, also reset readonlymode
2804 	if (!curbuf->b_p_ro && (opt_flags & OPT_LOCAL) == 0)
2805 	    readonlymode = FALSE;
2806 
2807 	// when 'readonly' is set may give W10 again
2808 	if (curbuf->b_p_ro)
2809 	    curbuf->b_did_warn = FALSE;
2810 
2811 #ifdef FEAT_TITLE
2812 	redraw_titles();
2813 #endif
2814     }
2815 
2816 #ifdef FEAT_GUI
2817     else if ((int *)varp == &p_mh)
2818     {
2819 	if (!p_mh)
2820 	    gui_mch_mousehide(FALSE);
2821     }
2822 #endif
2823 
2824     // when 'modifiable' is changed, redraw the window title
2825     else if ((int *)varp == &curbuf->b_p_ma)
2826     {
2827 # ifdef FEAT_TERMINAL
2828 	// Cannot set 'modifiable' when in Terminal mode.
2829 	if (curbuf->b_p_ma && (term_in_normal_mode() || (bt_terminal(curbuf)
2830 		      && curbuf->b_term != NULL && !term_is_finished(curbuf))))
2831 	{
2832 	    curbuf->b_p_ma = FALSE;
2833 	    return N_("E946: Cannot make a terminal with running job modifiable");
2834 	}
2835 # endif
2836 # ifdef FEAT_TITLE
2837 	redraw_titles();
2838 # endif
2839     }
2840 #ifdef FEAT_TITLE
2841     // when 'endofline' is changed, redraw the window title
2842     else if ((int *)varp == &curbuf->b_p_eol)
2843     {
2844 	redraw_titles();
2845     }
2846     // when 'fixeol' is changed, redraw the window title
2847     else if ((int *)varp == &curbuf->b_p_fixeol)
2848     {
2849 	redraw_titles();
2850     }
2851     // when 'bomb' is changed, redraw the window title and tab page text
2852     else if ((int *)varp == &curbuf->b_p_bomb)
2853     {
2854 	redraw_titles();
2855     }
2856 #endif
2857 
2858     // when 'bin' is set also set some other options
2859     else if ((int *)varp == &curbuf->b_p_bin)
2860     {
2861 	set_options_bin(old_value, curbuf->b_p_bin, opt_flags);
2862 #ifdef FEAT_TITLE
2863 	redraw_titles();
2864 #endif
2865     }
2866 
2867     // when 'buflisted' changes, trigger autocommands
2868     else if ((int *)varp == &curbuf->b_p_bl && old_value != curbuf->b_p_bl)
2869     {
2870 	apply_autocmds(curbuf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
2871 						    NULL, NULL, TRUE, curbuf);
2872     }
2873 
2874     // when 'swf' is set, create swapfile, when reset remove swapfile
2875     else if ((int *)varp == &curbuf->b_p_swf)
2876     {
2877 	if (curbuf->b_p_swf && p_uc)
2878 	    ml_open_file(curbuf);		// create the swap file
2879 	else
2880 	    // no need to reset curbuf->b_may_swap, ml_open_file() will check
2881 	    // buf->b_p_swf
2882 	    mf_close_file(curbuf, TRUE);	// remove the swap file
2883     }
2884 
2885     // when 'terse' is set change 'shortmess'
2886     else if ((int *)varp == &p_terse)
2887     {
2888 	char_u	*p;
2889 
2890 	p = vim_strchr(p_shm, SHM_SEARCH);
2891 
2892 	// insert 's' in p_shm
2893 	if (p_terse && p == NULL)
2894 	{
2895 	    STRCPY(IObuff, p_shm);
2896 	    STRCAT(IObuff, "s");
2897 	    set_string_option_direct((char_u *)"shm", -1, IObuff, OPT_FREE, 0);
2898 	}
2899 	// remove 's' from p_shm
2900 	else if (!p_terse && p != NULL)
2901 	    STRMOVE(p, p + 1);
2902     }
2903 
2904     // when 'paste' is set or reset also change other options
2905     else if ((int *)varp == &p_paste)
2906     {
2907 	paste_option_changed();
2908     }
2909 
2910     // when 'insertmode' is set from an autocommand need to do work here
2911     else if ((int *)varp == &p_im)
2912     {
2913 	if (p_im)
2914 	{
2915 	    if ((State & INSERT) == 0)
2916 		need_start_insertmode = TRUE;
2917 	    stop_insert_mode = FALSE;
2918 	}
2919 	// only reset if it was set previously
2920 	else if (old_value)
2921 	{
2922 	    need_start_insertmode = FALSE;
2923 	    stop_insert_mode = TRUE;
2924 	    if (restart_edit != 0 && mode_displayed)
2925 		clear_cmdline = TRUE;	// remove "(insert)"
2926 	    restart_edit = 0;
2927 	}
2928     }
2929 
2930     // when 'ignorecase' is set or reset and 'hlsearch' is set, redraw
2931     else if ((int *)varp == &p_ic && p_hls)
2932     {
2933 	redraw_all_later(SOME_VALID);
2934     }
2935 
2936 #ifdef FEAT_SEARCH_EXTRA
2937     // when 'hlsearch' is set or reset: reset no_hlsearch
2938     else if ((int *)varp == &p_hls)
2939     {
2940 	set_no_hlsearch(FALSE);
2941     }
2942 #endif
2943 
2944     // when 'scrollbind' is set: snapshot the current position to avoid a jump
2945     // at the end of normal_cmd()
2946     else if ((int *)varp == &curwin->w_p_scb)
2947     {
2948 	if (curwin->w_p_scb)
2949 	{
2950 	    do_check_scrollbind(FALSE);
2951 	    curwin->w_scbind_pos = curwin->w_topline;
2952 	}
2953     }
2954 
2955 #if defined(FEAT_QUICKFIX)
2956     // There can be only one window with 'previewwindow' set.
2957     else if ((int *)varp == &curwin->w_p_pvw)
2958     {
2959 	if (curwin->w_p_pvw)
2960 	{
2961 	    win_T	*win;
2962 
2963 	    FOR_ALL_WINDOWS(win)
2964 		if (win->w_p_pvw && win != curwin)
2965 		{
2966 		    curwin->w_p_pvw = FALSE;
2967 		    return N_("E590: A preview window already exists");
2968 		}
2969 	}
2970     }
2971 #endif
2972 
2973     // when 'textmode' is set or reset also change 'fileformat'
2974     else if ((int *)varp == &curbuf->b_p_tx)
2975     {
2976 	set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, opt_flags);
2977     }
2978 
2979     // when 'textauto' is set or reset also change 'fileformats'
2980     else if ((int *)varp == &p_ta)
2981     {
2982 	set_string_option_direct((char_u *)"ffs", -1,
2983 				 p_ta ? (char_u *)DFLT_FFS_VIM : (char_u *)"",
2984 						     OPT_FREE | opt_flags, 0);
2985     }
2986 
2987     /*
2988      * When 'lisp' option changes include/exclude '-' in
2989      * keyword characters.
2990      */
2991 #ifdef FEAT_LISP
2992     else if (varp == (char_u *)&(curbuf->b_p_lisp))
2993     {
2994 	(void)buf_init_chartab(curbuf, FALSE);	    // ignore errors
2995     }
2996 #endif
2997 
2998 #ifdef FEAT_TITLE
2999     // when 'title' changed, may need to change the title; same for 'icon'
3000     else if ((int *)varp == &p_title || (int *)varp == &p_icon)
3001     {
3002 	did_set_title();
3003     }
3004 #endif
3005 
3006     else if ((int *)varp == &curbuf->b_changed)
3007     {
3008 	if (!value)
3009 	    save_file_ff(curbuf);	// Buffer is unchanged
3010 #ifdef FEAT_TITLE
3011 	redraw_titles();
3012 #endif
3013 	modified_was_set = value;
3014     }
3015 
3016 #ifdef BACKSLASH_IN_FILENAME
3017     else if ((int *)varp == &p_ssl)
3018     {
3019 	if (p_ssl)
3020 	{
3021 	    psepc = '/';
3022 	    psepcN = '\\';
3023 	    pseps[0] = '/';
3024 	}
3025 	else
3026 	{
3027 	    psepc = '\\';
3028 	    psepcN = '/';
3029 	    pseps[0] = '\\';
3030 	}
3031 
3032 	// need to adjust the file name arguments and buffer names.
3033 	buflist_slash_adjust();
3034 	alist_slash_adjust();
3035 # ifdef FEAT_EVAL
3036 	scriptnames_slash_adjust();
3037 # endif
3038     }
3039 #endif
3040 
3041     // If 'wrap' is set, set w_leftcol to zero.
3042     else if ((int *)varp == &curwin->w_p_wrap)
3043     {
3044 	if (curwin->w_p_wrap)
3045 	    curwin->w_leftcol = 0;
3046     }
3047 
3048     else if ((int *)varp == &p_ea)
3049     {
3050 	if (p_ea && !old_value)
3051 	    win_equal(curwin, FALSE, 0);
3052     }
3053 
3054     else if ((int *)varp == &p_wiv)
3055     {
3056 	/*
3057 	 * When 'weirdinvert' changed, set/reset 't_xs'.
3058 	 * Then set 'weirdinvert' according to value of 't_xs'.
3059 	 */
3060 	if (p_wiv && !old_value)
3061 	    T_XS = (char_u *)"y";
3062 	else if (!p_wiv && old_value)
3063 	    T_XS = empty_option;
3064 	p_wiv = (*T_XS != NUL);
3065     }
3066 
3067 #ifdef FEAT_BEVAL_GUI
3068     else if ((int *)varp == &p_beval)
3069     {
3070 	if (!balloonEvalForTerm)
3071 	{
3072 	    if (p_beval && !old_value)
3073 		gui_mch_enable_beval_area(balloonEval);
3074 	    else if (!p_beval && old_value)
3075 		gui_mch_disable_beval_area(balloonEval);
3076 	}
3077     }
3078 #endif
3079 #ifdef FEAT_BEVAL_TERM
3080     else if ((int *)varp == &p_bevalterm)
3081     {
3082 	mch_bevalterm_changed();
3083     }
3084 #endif
3085 
3086 #ifdef FEAT_AUTOCHDIR
3087     else if ((int *)varp == &p_acd)
3088     {
3089 	// Change directories when the 'acd' option is set now.
3090 	DO_AUTOCHDIR;
3091     }
3092 #endif
3093 
3094 #ifdef FEAT_DIFF
3095     // 'diff'
3096     else if ((int *)varp == &curwin->w_p_diff)
3097     {
3098 	// May add or remove the buffer from the list of diff buffers.
3099 	diff_buf_adjust(curwin);
3100 # ifdef FEAT_FOLDING
3101 	if (foldmethodIsDiff(curwin))
3102 	    foldUpdateAll(curwin);
3103 # endif
3104     }
3105 #endif
3106 
3107 #ifdef HAVE_INPUT_METHOD
3108     // 'imdisable'
3109     else if ((int *)varp == &p_imdisable)
3110     {
3111 	// Only de-activate it here, it will be enabled when changing mode.
3112 	if (p_imdisable)
3113 	    im_set_active(FALSE);
3114 	else if (State & INSERT)
3115 	    // When the option is set from an autocommand, it may need to take
3116 	    // effect right away.
3117 	    im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
3118     }
3119 #endif
3120 
3121 #ifdef FEAT_SPELL
3122     // 'spell'
3123     else if ((int *)varp == &curwin->w_p_spell)
3124     {
3125 	if (curwin->w_p_spell)
3126 	{
3127 	    char	*errmsg = did_set_spelllang(curwin);
3128 
3129 	    if (errmsg != NULL)
3130 		emsg(_(errmsg));
3131 	}
3132     }
3133 #endif
3134 
3135 #ifdef FEAT_ARABIC
3136     if ((int *)varp == &curwin->w_p_arab)
3137     {
3138 	if (curwin->w_p_arab)
3139 	{
3140 	    /*
3141 	     * 'arabic' is set, handle various sub-settings.
3142 	     */
3143 	    if (!p_tbidi)
3144 	    {
3145 		// set rightleft mode
3146 		if (!curwin->w_p_rl)
3147 		{
3148 		    curwin->w_p_rl = TRUE;
3149 		    changed_window_setting();
3150 		}
3151 
3152 		// Enable Arabic shaping (major part of what Arabic requires)
3153 		if (!p_arshape)
3154 		{
3155 		    p_arshape = TRUE;
3156 		    redraw_later_clear();
3157 		}
3158 	    }
3159 
3160 	    // Arabic requires a utf-8 encoding, inform the user if its not
3161 	    // set.
3162 	    if (STRCMP(p_enc, "utf-8") != 0)
3163 	    {
3164 		static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
3165 
3166 		msg_source(HL_ATTR(HLF_W));
3167 		msg_attr(_(w_arabic), HL_ATTR(HLF_W));
3168 #ifdef FEAT_EVAL
3169 		set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_arabic), -1);
3170 #endif
3171 	    }
3172 
3173 	    // set 'delcombine'
3174 	    p_deco = TRUE;
3175 
3176 # ifdef FEAT_KEYMAP
3177 	    // Force-set the necessary keymap for arabic
3178 	    set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
3179 								   OPT_LOCAL);
3180 # endif
3181 	}
3182 	else
3183 	{
3184 	    /*
3185 	     * 'arabic' is reset, handle various sub-settings.
3186 	     */
3187 	    if (!p_tbidi)
3188 	    {
3189 		// reset rightleft mode
3190 		if (curwin->w_p_rl)
3191 		{
3192 		    curwin->w_p_rl = FALSE;
3193 		    changed_window_setting();
3194 		}
3195 
3196 		// 'arabicshape' isn't reset, it is a global option and
3197 		// another window may still need it "on".
3198 	    }
3199 
3200 	    // 'delcombine' isn't reset, it is a global option and another
3201 	    // window may still want it "on".
3202 
3203 # ifdef FEAT_KEYMAP
3204 	    // Revert to the default keymap
3205 	    curbuf->b_p_iminsert = B_IMODE_NONE;
3206 	    curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
3207 # endif
3208 	}
3209     }
3210 
3211 #endif
3212 
3213 #if defined(FEAT_SIGNS) && defined(FEAT_GUI)
3214     else if (((int *)varp == &curwin->w_p_nu
3215 		|| (int *)varp == &curwin->w_p_rnu)
3216 	    && gui.in_use
3217 	    && (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u')
3218 	    && curbuf->b_signlist != NULL)
3219     {
3220 	// If the 'number' or 'relativenumber' options are modified and
3221 	// 'signcolumn' is set to 'number', then clear the screen for a full
3222 	// refresh. Otherwise the sign icons are not displayed properly in the
3223 	// number column.  If the 'number' option is set and only the
3224 	// 'relativenumber' option is toggled, then don't refresh the screen
3225 	// (optimization).
3226 	if (!(curwin->w_p_nu && ((int *)varp == &curwin->w_p_rnu)))
3227 	    redraw_all_later(CLEAR);
3228     }
3229 #endif
3230 
3231 #ifdef FEAT_TERMGUICOLORS
3232     // 'termguicolors'
3233     else if ((int *)varp == &p_tgc)
3234     {
3235 # ifdef FEAT_VTP
3236 	// Do not turn on 'tgc' when 24-bit colors are not supported.
3237 	if (
3238 #  ifdef VIMDLL
3239 	    !gui.in_use && !gui.starting &&
3240 #  endif
3241 	    !has_vtp_working())
3242 	{
3243 	    p_tgc = 0;
3244 	    return N_("E954: 24-bit colors are not supported on this environment");
3245 	}
3246 	if (is_term_win32())
3247 	    swap_tcap();
3248 # endif
3249 # ifdef FEAT_GUI
3250 	if (!gui.in_use && !gui.starting)
3251 # endif
3252 	    highlight_gui_started();
3253 # ifdef FEAT_VTP
3254 	// reset t_Co
3255 	if (is_term_win32())
3256 	{
3257 	    control_console_color_rgb();
3258 	    set_termname(T_NAME);
3259 	    init_highlight(TRUE, FALSE);
3260 	}
3261 # endif
3262 # ifdef FEAT_TERMINAL
3263 	term_update_colors_all();
3264 	term_update_wincolor_all();
3265 # endif
3266     }
3267 #endif
3268 
3269     /*
3270      * End of handling side effects for bool options.
3271      */
3272 
3273     // after handling side effects, call autocommand
3274 
3275     options[opt_idx].flags |= P_WAS_SET;
3276 
3277 #if defined(FEAT_EVAL)
3278     apply_optionset_autocmd(opt_idx, opt_flags,
3279 				(long)(old_value ? TRUE : FALSE),
3280 				(long)(old_global_value ? TRUE : FALSE),
3281 				(long)(value ? TRUE : FALSE), NULL);
3282 #endif
3283 
3284     comp_col();			    // in case 'ruler' or 'showcmd' changed
3285     if (curwin->w_curswant != MAXCOL
3286 		     && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
3287 	curwin->w_set_curswant = TRUE;
3288 
3289     if ((opt_flags & OPT_NO_REDRAW) == 0)
3290 	check_redraw(options[opt_idx].flags);
3291 
3292     return NULL;
3293 }
3294 
3295 /*
3296  * Set the value of a number option, and take care of side effects.
3297  * Returns NULL for success, or an error message for an error.
3298  */
3299     static char *
set_num_option(int opt_idx,char_u * varp,long value,char * errbuf,size_t errbuflen,int opt_flags)3300 set_num_option(
3301     int		opt_idx,		// index in options[] table
3302     char_u	*varp,			// pointer to the option variable
3303     long	value,			// new value
3304     char	*errbuf,		// buffer for error messages
3305     size_t	errbuflen,		// length of "errbuf"
3306     int		opt_flags)		// OPT_LOCAL, OPT_GLOBAL,
3307 					// OPT_MODELINE, etc.
3308 {
3309     char	*errmsg = NULL;
3310     long	old_value = *(long *)varp;
3311 #if defined(FEAT_EVAL)
3312     long	old_global_value = 0;	// only used when setting a local and
3313 					// global option
3314 #endif
3315     long	old_Rows = Rows;	// remember old Rows
3316     long	old_Columns = Columns;	// remember old Columns
3317     long	*pp = (long *)varp;
3318 
3319     // Disallow changing some options from secure mode.
3320     if ((secure
3321 #ifdef HAVE_SANDBOX
3322 		|| sandbox != 0
3323 #endif
3324 		) && (options[opt_idx].flags & P_SECURE))
3325 	return e_secure;
3326 
3327 #if defined(FEAT_EVAL)
3328     // Save the global value before changing anything. This is needed as for
3329     // a global-only option setting the "local value" in fact sets the global
3330     // value (since there is only one value).
3331     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3332 	old_global_value = *(long *)get_varp_scope(&(options[opt_idx]),
3333 								   OPT_GLOBAL);
3334 #endif
3335 
3336     *pp = value;
3337 #ifdef FEAT_EVAL
3338     // Remember where the option was set.
3339     set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
3340 #endif
3341 #ifdef FEAT_GUI
3342     need_mouse_correct = TRUE;
3343 #endif
3344 
3345     if (curbuf->b_p_sw < 0)
3346     {
3347 	errmsg = e_positive;
3348 #ifdef FEAT_VARTABS
3349 	// Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use.
3350 	curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0
3351 	               ? tabstop_first(curbuf->b_p_vts_array)
3352 		       : curbuf->b_p_ts;
3353 #else
3354 	curbuf->b_p_sw = curbuf->b_p_ts;
3355 #endif
3356     }
3357 
3358     /*
3359      * Number options that need some action when changed
3360      */
3361     if (pp == &p_wh || pp == &p_hh)
3362     {
3363 	// 'winheight' and 'helpheight'
3364 	if (p_wh < 1)
3365 	{
3366 	    errmsg = e_positive;
3367 	    p_wh = 1;
3368 	}
3369 	if (p_wmh > p_wh)
3370 	{
3371 	    errmsg = e_winheight;
3372 	    p_wh = p_wmh;
3373 	}
3374 	if (p_hh < 0)
3375 	{
3376 	    errmsg = e_positive;
3377 	    p_hh = 0;
3378 	}
3379 
3380 	// Change window height NOW
3381 	if (!ONE_WINDOW)
3382 	{
3383 	    if (pp == &p_wh && curwin->w_height < p_wh)
3384 		win_setheight((int)p_wh);
3385 	    if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh)
3386 		win_setheight((int)p_hh);
3387 	}
3388     }
3389     else if (pp == &p_wmh)
3390     {
3391 	// 'winminheight'
3392 	if (p_wmh < 0)
3393 	{
3394 	    errmsg = e_positive;
3395 	    p_wmh = 0;
3396 	}
3397 	if (p_wmh > p_wh)
3398 	{
3399 	    errmsg = e_winheight;
3400 	    p_wmh = p_wh;
3401 	}
3402 	win_setminheight();
3403     }
3404     else if (pp == &p_wiw)
3405     {
3406 	// 'winwidth'
3407 	if (p_wiw < 1)
3408 	{
3409 	    errmsg = e_positive;
3410 	    p_wiw = 1;
3411 	}
3412 	if (p_wmw > p_wiw)
3413 	{
3414 	    errmsg = e_winwidth;
3415 	    p_wiw = p_wmw;
3416 	}
3417 
3418 	// Change window width NOW
3419 	if (!ONE_WINDOW && curwin->w_width < p_wiw)
3420 	    win_setwidth((int)p_wiw);
3421     }
3422     else if (pp == &p_wmw)
3423     {
3424 	// 'winminwidth'
3425 	if (p_wmw < 0)
3426 	{
3427 	    errmsg = e_positive;
3428 	    p_wmw = 0;
3429 	}
3430 	if (p_wmw > p_wiw)
3431 	{
3432 	    errmsg = e_winwidth;
3433 	    p_wmw = p_wiw;
3434 	}
3435 	win_setminwidth();
3436     }
3437 
3438     // (re)set last window status line
3439     else if (pp == &p_ls)
3440     {
3441 	last_status(FALSE);
3442     }
3443 
3444     // (re)set tab page line
3445     else if (pp == &p_stal)
3446     {
3447 	shell_new_rows();	// recompute window positions and heights
3448     }
3449 
3450 #ifdef FEAT_GUI
3451     else if (pp == &p_linespace)
3452     {
3453 	// Recompute gui.char_height and resize the Vim window to keep the
3454 	// same number of lines.
3455 	if (gui.in_use && gui_mch_adjust_charheight() == OK)
3456 	    gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
3457     }
3458 #endif
3459 
3460 #ifdef FEAT_FOLDING
3461     // 'foldlevel'
3462     else if (pp == &curwin->w_p_fdl)
3463     {
3464 	if (curwin->w_p_fdl < 0)
3465 	    curwin->w_p_fdl = 0;
3466 	newFoldLevel();
3467     }
3468 
3469     // 'foldminlines'
3470     else if (pp == &curwin->w_p_fml)
3471     {
3472 	foldUpdateAll(curwin);
3473     }
3474 
3475     // 'foldnestmax'
3476     else if (pp == &curwin->w_p_fdn)
3477     {
3478 	if (foldmethodIsSyntax(curwin) || foldmethodIsIndent(curwin))
3479 	    foldUpdateAll(curwin);
3480     }
3481 
3482     // 'foldcolumn'
3483     else if (pp == &curwin->w_p_fdc)
3484     {
3485 	if (curwin->w_p_fdc < 0)
3486 	{
3487 	    errmsg = e_positive;
3488 	    curwin->w_p_fdc = 0;
3489 	}
3490 	else if (curwin->w_p_fdc > 12)
3491 	{
3492 	    errmsg = e_invarg;
3493 	    curwin->w_p_fdc = 12;
3494 	}
3495     }
3496 #endif // FEAT_FOLDING
3497 
3498 #if defined(FEAT_FOLDING) || defined(FEAT_CINDENT)
3499     // 'shiftwidth' or 'tabstop'
3500     else if (pp == &curbuf->b_p_sw || pp == &curbuf->b_p_ts)
3501     {
3502 # ifdef FEAT_FOLDING
3503 	if (foldmethodIsIndent(curwin))
3504 	    foldUpdateAll(curwin);
3505 # endif
3506 # ifdef FEAT_CINDENT
3507 	// When 'shiftwidth' changes, or it's zero and 'tabstop' changes:
3508 	// parse 'cinoptions'.
3509 	if (pp == &curbuf->b_p_sw || curbuf->b_p_sw == 0)
3510 	    parse_cino(curbuf);
3511 # endif
3512     }
3513 #endif
3514 
3515     // 'maxcombine'
3516     else if (pp == &p_mco)
3517     {
3518 	if (p_mco > MAX_MCO)
3519 	    p_mco = MAX_MCO;
3520 	else if (p_mco < 0)
3521 	    p_mco = 0;
3522 	screenclear();	    // will re-allocate the screen
3523     }
3524 
3525     else if (pp == &curbuf->b_p_iminsert)
3526     {
3527 	if (curbuf->b_p_iminsert < 0 || curbuf->b_p_iminsert > B_IMODE_LAST)
3528 	{
3529 	    errmsg = e_invarg;
3530 	    curbuf->b_p_iminsert = B_IMODE_NONE;
3531 	}
3532 	p_iminsert = curbuf->b_p_iminsert;
3533 	if (termcap_active)	// don't do this in the alternate screen
3534 	    showmode();
3535 #if defined(FEAT_KEYMAP)
3536 	// Show/unshow value of 'keymap' in status lines.
3537 	status_redraw_curbuf();
3538 #endif
3539     }
3540 
3541 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
3542     // 'imstyle'
3543     else if (pp == &p_imst)
3544     {
3545 	if (p_imst != IM_ON_THE_SPOT && p_imst != IM_OVER_THE_SPOT)
3546 	    errmsg = e_invarg;
3547     }
3548 #endif
3549 
3550     else if (pp == &p_window)
3551     {
3552 	if (p_window < 1)
3553 	    p_window = 1;
3554 	else if (p_window >= Rows)
3555 	    p_window = Rows - 1;
3556     }
3557 
3558     else if (pp == &curbuf->b_p_imsearch)
3559     {
3560 	if (curbuf->b_p_imsearch < -1 || curbuf->b_p_imsearch > B_IMODE_LAST)
3561 	{
3562 	    errmsg = e_invarg;
3563 	    curbuf->b_p_imsearch = B_IMODE_NONE;
3564 	}
3565 	p_imsearch = curbuf->b_p_imsearch;
3566     }
3567 
3568 #ifdef FEAT_TITLE
3569     // if 'titlelen' has changed, redraw the title
3570     else if (pp == &p_titlelen)
3571     {
3572 	if (p_titlelen < 0)
3573 	{
3574 	    errmsg = e_positive;
3575 	    p_titlelen = 85;
3576 	}
3577 	if (starting != NO_SCREEN && old_value != p_titlelen)
3578 	    need_maketitle = TRUE;
3579     }
3580 #endif
3581 
3582     // if p_ch changed value, change the command line height
3583     else if (pp == &p_ch)
3584     {
3585 	if (p_ch < 1)
3586 	{
3587 	    errmsg = e_positive;
3588 	    p_ch = 1;
3589 	}
3590 	if (p_ch > Rows - min_rows() + 1)
3591 	    p_ch = Rows - min_rows() + 1;
3592 
3593 	// Only compute the new window layout when startup has been
3594 	// completed. Otherwise the frame sizes may be wrong.
3595 	if (p_ch != old_value && full_screen
3596 #ifdef FEAT_GUI
3597 		&& !gui.starting
3598 #endif
3599 	   )
3600 	    command_height();
3601     }
3602 
3603     // when 'updatecount' changes from zero to non-zero, open swap files
3604     else if (pp == &p_uc)
3605     {
3606 	if (p_uc < 0)
3607 	{
3608 	    errmsg = e_positive;
3609 	    p_uc = 100;
3610 	}
3611 	if (p_uc && !old_value)
3612 	    ml_open_files();
3613     }
3614 #ifdef FEAT_CONCEAL
3615     else if (pp == &curwin->w_p_cole)
3616     {
3617 	if (curwin->w_p_cole < 0)
3618 	{
3619 	    errmsg = e_positive;
3620 	    curwin->w_p_cole = 0;
3621 	}
3622 	else if (curwin->w_p_cole > 3)
3623 	{
3624 	    errmsg = e_invarg;
3625 	    curwin->w_p_cole = 3;
3626 	}
3627     }
3628 #endif
3629 #ifdef MZSCHEME_GUI_THREADS
3630     else if (pp == &p_mzq)
3631 	mzvim_reset_timer();
3632 #endif
3633 
3634 #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
3635     // 'pyxversion'
3636     else if (pp == &p_pyx)
3637     {
3638 	if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3)
3639 	    errmsg = e_invarg;
3640     }
3641 #endif
3642 
3643     // sync undo before 'undolevels' changes
3644     else if (pp == &p_ul)
3645     {
3646 	// use the old value, otherwise u_sync() may not work properly
3647 	p_ul = old_value;
3648 	u_sync(TRUE);
3649 	p_ul = value;
3650     }
3651     else if (pp == &curbuf->b_p_ul)
3652     {
3653 	// use the old value, otherwise u_sync() may not work properly
3654 	curbuf->b_p_ul = old_value;
3655 	u_sync(TRUE);
3656 	curbuf->b_p_ul = value;
3657     }
3658 
3659 #ifdef FEAT_LINEBREAK
3660     // 'numberwidth' must be positive
3661     else if (pp == &curwin->w_p_nuw)
3662     {
3663 	if (curwin->w_p_nuw < 1)
3664 	{
3665 	    errmsg = e_positive;
3666 	    curwin->w_p_nuw = 1;
3667 	}
3668 	if (curwin->w_p_nuw > 20)
3669 	{
3670 	    errmsg = e_invarg;
3671 	    curwin->w_p_nuw = 20;
3672 	}
3673 	curwin->w_nrwidth_line_count = 0; // trigger a redraw
3674     }
3675 #endif
3676 
3677     else if (pp == &curbuf->b_p_tw)
3678     {
3679 	if (curbuf->b_p_tw < 0)
3680 	{
3681 	    errmsg = e_positive;
3682 	    curbuf->b_p_tw = 0;
3683 	}
3684 #ifdef FEAT_SYN_HL
3685 	{
3686 	    win_T	*wp;
3687 	    tabpage_T	*tp;
3688 
3689 	    FOR_ALL_TAB_WINDOWS(tp, wp)
3690 		check_colorcolumn(wp);
3691 	}
3692 #endif
3693     }
3694 
3695     /*
3696      * Check the bounds for numeric options here
3697      */
3698     if (Rows < min_rows() && full_screen)
3699     {
3700 	if (errbuf != NULL)
3701 	{
3702 	    vim_snprintf((char *)errbuf, errbuflen,
3703 			       _("E593: Need at least %d lines"), min_rows());
3704 	    errmsg = errbuf;
3705 	}
3706 	Rows = min_rows();
3707     }
3708     if (Columns < MIN_COLUMNS && full_screen)
3709     {
3710 	if (errbuf != NULL)
3711 	{
3712 	    vim_snprintf((char *)errbuf, errbuflen,
3713 			    _("E594: Need at least %d columns"), MIN_COLUMNS);
3714 	    errmsg = errbuf;
3715 	}
3716 	Columns = MIN_COLUMNS;
3717     }
3718     limit_screen_size();
3719 
3720     /*
3721      * If the screen (shell) height has been changed, assume it is the
3722      * physical screenheight.
3723      */
3724     if (old_Rows != Rows || old_Columns != Columns)
3725     {
3726 	// Changing the screen size is not allowed while updating the screen.
3727 	if (updating_screen)
3728 	    *pp = old_value;
3729 	else if (full_screen
3730 #ifdef FEAT_GUI
3731 		&& !gui.starting
3732 #endif
3733 	    )
3734 	    set_shellsize((int)Columns, (int)Rows, TRUE);
3735 	else
3736 	{
3737 	    // Postpone the resizing; check the size and cmdline position for
3738 	    // messages.
3739 	    check_shellsize();
3740 	    if (cmdline_row > Rows - p_ch && Rows > p_ch)
3741 		cmdline_row = Rows - p_ch;
3742 	}
3743 	if (p_window >= Rows || !option_was_set((char_u *)"window"))
3744 	    p_window = Rows - 1;
3745     }
3746 
3747     if (curbuf->b_p_ts <= 0)
3748     {
3749 	errmsg = e_positive;
3750 	curbuf->b_p_ts = 8;
3751     }
3752     if (p_tm < 0)
3753     {
3754 	errmsg = e_positive;
3755 	p_tm = 0;
3756     }
3757     if ((curwin->w_p_scr <= 0
3758 		|| (curwin->w_p_scr > curwin->w_height
3759 		    && curwin->w_height > 0))
3760 	    && full_screen)
3761     {
3762 	if (pp == &(curwin->w_p_scr))
3763 	{
3764 	    if (curwin->w_p_scr != 0)
3765 		errmsg = e_invalid_scroll_size;
3766 	    win_comp_scroll(curwin);
3767 	}
3768 	// If 'scroll' became invalid because of a side effect silently adjust
3769 	// it.
3770 	else if (curwin->w_p_scr <= 0)
3771 	    curwin->w_p_scr = 1;
3772 	else // curwin->w_p_scr > curwin->w_height
3773 	    curwin->w_p_scr = curwin->w_height;
3774     }
3775     if (p_hi < 0)
3776     {
3777 	errmsg = e_positive;
3778 	p_hi = 0;
3779     }
3780     else if (p_hi > 10000)
3781     {
3782 	errmsg = e_invarg;
3783 	p_hi = 10000;
3784     }
3785     if (p_re < 0 || p_re > 2)
3786     {
3787 	errmsg = e_invarg;
3788 	p_re = 0;
3789     }
3790     if (p_report < 0)
3791     {
3792 	errmsg = e_positive;
3793 	p_report = 1;
3794     }
3795     if ((p_sj < -100 || p_sj >= Rows) && full_screen)
3796     {
3797 	if (Rows != old_Rows)	// Rows changed, just adjust p_sj
3798 	    p_sj = Rows / 2;
3799 	else
3800 	{
3801 	    errmsg = e_invalid_scroll_size;
3802 	    p_sj = 1;
3803 	}
3804     }
3805     if (p_so < 0 && full_screen)
3806     {
3807 	errmsg = e_positive;
3808 	p_so = 0;
3809     }
3810     if (p_siso < 0 && full_screen)
3811     {
3812 	errmsg = e_positive;
3813 	p_siso = 0;
3814     }
3815 #ifdef FEAT_CMDWIN
3816     if (p_cwh < 1)
3817     {
3818 	errmsg = e_positive;
3819 	p_cwh = 1;
3820     }
3821 #endif
3822     if (p_ut < 0)
3823     {
3824 	errmsg = e_positive;
3825 	p_ut = 2000;
3826     }
3827     if (p_ss < 0)
3828     {
3829 	errmsg = e_positive;
3830 	p_ss = 0;
3831     }
3832 
3833     // May set global value for local option.
3834     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3835 	*(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp;
3836 
3837     options[opt_idx].flags |= P_WAS_SET;
3838 
3839 #if defined(FEAT_EVAL)
3840     apply_optionset_autocmd(opt_idx, opt_flags, old_value, old_global_value,
3841 								value, errmsg);
3842 #endif
3843 
3844     comp_col();			    // in case 'columns' or 'ls' changed
3845     if (curwin->w_curswant != MAXCOL
3846 		     && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
3847 	curwin->w_set_curswant = TRUE;
3848     if ((opt_flags & OPT_NO_REDRAW) == 0)
3849 	check_redraw(options[opt_idx].flags);
3850 
3851     return errmsg;
3852 }
3853 
3854 /*
3855  * Called after an option changed: check if something needs to be redrawn.
3856  */
3857     void
check_redraw(long_u flags)3858 check_redraw(long_u flags)
3859 {
3860     // Careful: P_RCLR and P_RALL are a combination of other P_ flags
3861     int		doclear = (flags & P_RCLR) == P_RCLR;
3862     int		all = ((flags & P_RALL) == P_RALL || doclear);
3863 
3864     if ((flags & P_RSTAT) || all)	// mark all status lines dirty
3865 	status_redraw_all();
3866 
3867     if ((flags & P_RBUF) || (flags & P_RWIN) || all)
3868 	changed_window_setting();
3869     if (flags & P_RBUF)
3870 	redraw_curbuf_later(NOT_VALID);
3871     if (flags & P_RWINONLY)
3872 	redraw_later(NOT_VALID);
3873     if (doclear)
3874 	redraw_all_later(CLEAR);
3875     else if (all)
3876 	redraw_all_later(NOT_VALID);
3877 }
3878 
3879 /*
3880  * Find index for option 'arg'.
3881  * Return -1 if not found.
3882  */
3883     int
findoption(char_u * arg)3884 findoption(char_u *arg)
3885 {
3886     int		    opt_idx;
3887     char	    *s, *p;
3888     static short    quick_tab[27] = {0, 0};	// quick access table
3889     int		    is_term_opt;
3890 
3891     /*
3892      * For first call: Initialize the quick-access table.
3893      * It contains the index for the first option that starts with a certain
3894      * letter.  There are 26 letters, plus the first "t_" option.
3895      */
3896     if (quick_tab[1] == 0)
3897     {
3898 	p = options[0].fullname;
3899 	for (opt_idx = 1; (s = options[opt_idx].fullname) != NULL; opt_idx++)
3900 	{
3901 	    if (s[0] != p[0])
3902 	    {
3903 		if (s[0] == 't' && s[1] == '_')
3904 		    quick_tab[26] = opt_idx;
3905 		else
3906 		    quick_tab[CharOrdLow(s[0])] = opt_idx;
3907 	    }
3908 	    p = s;
3909 	}
3910     }
3911 
3912     /*
3913      * Check for name starting with an illegal character.
3914      */
3915 #ifdef EBCDIC
3916     if (!islower(arg[0]))
3917 #else
3918     if (arg[0] < 'a' || arg[0] > 'z')
3919 #endif
3920 	return -1;
3921 
3922     is_term_opt = (arg[0] == 't' && arg[1] == '_');
3923     if (is_term_opt)
3924 	opt_idx = quick_tab[26];
3925     else
3926 	opt_idx = quick_tab[CharOrdLow(arg[0])];
3927     for ( ; (s = options[opt_idx].fullname) != NULL; opt_idx++)
3928     {
3929 	if (STRCMP(arg, s) == 0)		    // match full name
3930 	    break;
3931     }
3932     if (s == NULL && !is_term_opt)
3933     {
3934 	opt_idx = quick_tab[CharOrdLow(arg[0])];
3935 	for ( ; options[opt_idx].fullname != NULL; opt_idx++)
3936 	{
3937 	    s = options[opt_idx].shortname;
3938 	    if (s != NULL && STRCMP(arg, s) == 0)   // match short name
3939 		break;
3940 	    s = NULL;
3941 	}
3942     }
3943     if (s == NULL)
3944 	opt_idx = -1;
3945     return opt_idx;
3946 }
3947 
3948 #if defined(FEAT_EVAL) || defined(FEAT_TCL) || defined(FEAT_MZSCHEME)
3949 /*
3950  * Get the value for an option.
3951  *
3952  * Returns:
3953  * Number option: gov_number, *numval gets value.
3954  * Toggle option: gov_bool,   *numval gets value.
3955  * String option: gov_string, *stringval gets allocated string.
3956  * Hidden Number option: gov_hidden_number.
3957  * Hidden Toggle option: gov_hidden_bool.
3958  * Hidden String option: gov_hidden_string.
3959  * Unknown option: gov_unknown.
3960  */
3961     getoption_T
get_option_value(char_u * name,long * numval,char_u ** stringval,int opt_flags)3962 get_option_value(
3963     char_u	*name,
3964     long	*numval,
3965     char_u	**stringval,	    // NULL when only checking existence
3966     int		opt_flags)
3967 {
3968     int		opt_idx;
3969     char_u	*varp;
3970 
3971     opt_idx = findoption(name);
3972     if (opt_idx < 0)		    // option not in the table
3973     {
3974 	int key;
3975 
3976 	if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
3977 				  && (key = find_key_option(name, FALSE)) != 0)
3978 	{
3979 	    char_u key_name[2];
3980 	    char_u *p;
3981 
3982 	    // check for a terminal option
3983 	    if (key < 0)
3984 	    {
3985 		key_name[0] = KEY2TERMCAP0(key);
3986 		key_name[1] = KEY2TERMCAP1(key);
3987 	    }
3988 	    else
3989 	    {
3990 		key_name[0] = KS_KEY;
3991 		key_name[1] = (key & 0xff);
3992 	    }
3993 	    p = find_termcode(key_name);
3994 	    if (p != NULL)
3995 	    {
3996 		if (stringval != NULL)
3997 		    *stringval = vim_strsave(p);
3998 		return gov_string;
3999 	    }
4000 	}
4001 	return gov_unknown;
4002     }
4003 
4004     varp = get_varp_scope(&(options[opt_idx]), opt_flags);
4005 
4006     if (options[opt_idx].flags & P_STRING)
4007     {
4008 	if (varp == NULL)		    // hidden option
4009 	    return gov_hidden_string;
4010 	if (stringval != NULL)
4011 	{
4012 #ifdef FEAT_CRYPT
4013 	    // never return the value of the crypt key
4014 	    if ((char_u **)varp == &curbuf->b_p_key
4015 						&& **(char_u **)(varp) != NUL)
4016 		*stringval = vim_strsave((char_u *)"*****");
4017 	    else
4018 #endif
4019 		*stringval = vim_strsave(*(char_u **)(varp));
4020 	}
4021 	return gov_string;
4022     }
4023 
4024     if (varp == NULL)		    // hidden option
4025 	return (options[opt_idx].flags & P_NUM)
4026 					 ? gov_hidden_number : gov_hidden_bool;
4027     if (options[opt_idx].flags & P_NUM)
4028 	*numval = *(long *)varp;
4029     else
4030     {
4031 	// Special case: 'modified' is b_changed, but we also want to consider
4032 	// it set when 'ff' or 'fenc' changed.
4033 	if ((int *)varp == &curbuf->b_changed)
4034 	    *numval = curbufIsChanged();
4035 	else
4036 	    *numval = (long) *(int *)varp;
4037     }
4038     return (options[opt_idx].flags & P_NUM) ? gov_number : gov_bool;
4039 }
4040 #endif
4041 
4042 #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
4043 /*
4044  * Returns the option attributes and its value. Unlike the above function it
4045  * will return either global value or local value of the option depending on
4046  * what was requested, but it will never return global value if it was
4047  * requested to return local one and vice versa. Neither it will return
4048  * buffer-local value if it was requested to return window-local one.
4049  *
4050  * Pretends that option is absent if it is not present in the requested scope
4051  * (i.e. has no global, window-local or buffer-local value depending on
4052  * opt_type). Uses
4053  *
4054  * Returned flags:
4055  *       0 hidden or unknown option, also option that does not have requested
4056  *	   type (see SREQ_* in vim.h)
4057  *  see SOPT_* in vim.h for other flags
4058  *
4059  * Possible opt_type values: see SREQ_* in vim.h
4060  */
4061     int
get_option_value_strict(char_u * name,long * numval,char_u ** stringval,int opt_type,void * from)4062 get_option_value_strict(
4063     char_u	*name,
4064     long	*numval,
4065     char_u	**stringval,	    // NULL when only obtaining attributes
4066     int		opt_type,
4067     void	*from)
4068 {
4069     int		opt_idx;
4070     char_u	*varp = NULL;
4071     struct vimoption *p;
4072     int		r = 0;
4073 
4074     opt_idx = findoption(name);
4075     if (opt_idx < 0)
4076 	return 0;
4077 
4078     p = &(options[opt_idx]);
4079 
4080     // Hidden option
4081     if (p->var == NULL)
4082 	return 0;
4083 
4084     if (p->flags & P_BOOL)
4085 	r |= SOPT_BOOL;
4086     else if (p->flags & P_NUM)
4087 	r |= SOPT_NUM;
4088     else if (p->flags & P_STRING)
4089 	r |= SOPT_STRING;
4090 
4091     if (p->indir == PV_NONE)
4092     {
4093 	if (opt_type == SREQ_GLOBAL)
4094 	    r |= SOPT_GLOBAL;
4095 	else
4096 	    return 0; // Did not request global-only option
4097     }
4098     else
4099     {
4100 	if (p->indir & PV_BOTH)
4101 	    r |= SOPT_GLOBAL;
4102 	else if (opt_type == SREQ_GLOBAL)
4103 	    return 0; // Requested global option
4104 
4105 	if (p->indir & PV_WIN)
4106 	{
4107 	    if (opt_type == SREQ_BUF)
4108 		return 0; // Did not request window-local option
4109 	    else
4110 		r |= SOPT_WIN;
4111 	}
4112 	else if (p->indir & PV_BUF)
4113 	{
4114 	    if (opt_type == SREQ_WIN)
4115 		return 0; // Did not request buffer-local option
4116 	    else
4117 		r |= SOPT_BUF;
4118 	}
4119     }
4120 
4121     if (stringval == NULL)
4122 	return r;
4123 
4124     if (opt_type == SREQ_GLOBAL)
4125 	varp = p->var;
4126     else
4127     {
4128 	if (opt_type == SREQ_BUF)
4129 	{
4130 	    // Special case: 'modified' is b_changed, but we also want to
4131 	    // consider it set when 'ff' or 'fenc' changed.
4132 	    if (p->indir == PV_MOD)
4133 	    {
4134 		*numval = bufIsChanged((buf_T *)from);
4135 		varp = NULL;
4136 	    }
4137 #ifdef FEAT_CRYPT
4138 	    else if (p->indir == PV_KEY)
4139 	    {
4140 		// never return the value of the crypt key
4141 		*stringval = NULL;
4142 		varp = NULL;
4143 	    }
4144 #endif
4145 	    else
4146 	    {
4147 		buf_T *save_curbuf = curbuf;
4148 
4149 		// only getting a pointer, no need to use aucmd_prepbuf()
4150 		curbuf = (buf_T *)from;
4151 		curwin->w_buffer = curbuf;
4152 		varp = get_varp(p);
4153 		curbuf = save_curbuf;
4154 		curwin->w_buffer = curbuf;
4155 	    }
4156 	}
4157 	else if (opt_type == SREQ_WIN)
4158 	{
4159 	    win_T	*save_curwin = curwin;
4160 
4161 	    curwin = (win_T *)from;
4162 	    curbuf = curwin->w_buffer;
4163 	    varp = get_varp(p);
4164 	    curwin = save_curwin;
4165 	    curbuf = curwin->w_buffer;
4166 	}
4167 	if (varp == p->var)
4168 	    return (r | SOPT_UNSET);
4169     }
4170 
4171     if (varp != NULL)
4172     {
4173 	if (p->flags & P_STRING)
4174 	    *stringval = vim_strsave(*(char_u **)(varp));
4175 	else if (p->flags & P_NUM)
4176 	    *numval = *(long *) varp;
4177 	else
4178 	    *numval = *(int *)varp;
4179     }
4180 
4181     return r;
4182 }
4183 
4184 /*
4185  * Iterate over options. First argument is a pointer to a pointer to a
4186  * structure inside options[] array, second is option type like in the above
4187  * function.
4188  *
4189  * If first argument points to NULL it is assumed that iteration just started
4190  * and caller needs the very first value.
4191  * If first argument points to the end marker function returns NULL and sets
4192  * first argument to NULL.
4193  *
4194  * Returns full option name for current option on each call.
4195  */
4196     char_u *
option_iter_next(void ** option,int opt_type)4197 option_iter_next(void **option, int opt_type)
4198 {
4199     struct vimoption	*ret = NULL;
4200     do
4201     {
4202 	if (*option == NULL)
4203 	    *option = (void *) options;
4204 	else if (((struct vimoption *) (*option))->fullname == NULL)
4205 	{
4206 	    *option = NULL;
4207 	    return NULL;
4208 	}
4209 	else
4210 	    *option = (void *) (((struct vimoption *) (*option)) + 1);
4211 
4212 	ret = ((struct vimoption *) (*option));
4213 
4214 	// Hidden option
4215 	if (ret->var == NULL)
4216 	{
4217 	    ret = NULL;
4218 	    continue;
4219 	}
4220 
4221 	switch (opt_type)
4222 	{
4223 	    case SREQ_GLOBAL:
4224 		if (!(ret->indir == PV_NONE || ret->indir & PV_BOTH))
4225 		    ret = NULL;
4226 		break;
4227 	    case SREQ_BUF:
4228 		if (!(ret->indir & PV_BUF))
4229 		    ret = NULL;
4230 		break;
4231 	    case SREQ_WIN:
4232 		if (!(ret->indir & PV_WIN))
4233 		    ret = NULL;
4234 		break;
4235 	    default:
4236 		internal_error("option_iter_next()");
4237 		return NULL;
4238 	}
4239     }
4240     while (ret == NULL);
4241 
4242     return (char_u *)ret->fullname;
4243 }
4244 #endif
4245 
4246 /*
4247  * Return the flags for the option at 'opt_idx'.
4248  */
4249     long_u
get_option_flags(int opt_idx)4250 get_option_flags(int opt_idx)
4251 {
4252     return options[opt_idx].flags;
4253 }
4254 
4255 /*
4256  * Set a flag for the option at 'opt_idx'.
4257  */
4258     void
set_option_flag(int opt_idx,long_u flag)4259 set_option_flag(int opt_idx, long_u flag)
4260 {
4261     options[opt_idx].flags |= flag;
4262 }
4263 
4264 /*
4265  * Clear a flag for the option at 'opt_idx'.
4266  */
4267     void
clear_option_flag(int opt_idx,long_u flag)4268 clear_option_flag(int opt_idx, long_u flag)
4269 {
4270     options[opt_idx].flags &= ~flag;
4271 }
4272 
4273 /*
4274  * Returns TRUE if the option at 'opt_idx' is a global option
4275  */
4276     int
is_global_option(int opt_idx)4277 is_global_option(int opt_idx)
4278 {
4279     return options[opt_idx].indir == PV_NONE;
4280 }
4281 
4282 /*
4283  * Returns TRUE if the option at 'opt_idx' is a global option which also has a
4284  * local value.
4285  */
4286     int
is_global_local_option(int opt_idx)4287 is_global_local_option(int opt_idx)
4288 {
4289     return options[opt_idx].indir & PV_BOTH;
4290 }
4291 
4292 /*
4293  * Returns TRUE if the option at 'opt_idx' is a window-local option
4294  */
4295     int
is_window_local_option(int opt_idx)4296 is_window_local_option(int opt_idx)
4297 {
4298     return options[opt_idx].var == VAR_WIN;
4299 }
4300 
4301 /*
4302  * Returns TRUE if the option at 'opt_idx' is a hidden option
4303  */
4304     int
is_hidden_option(int opt_idx)4305 is_hidden_option(int opt_idx)
4306 {
4307     return options[opt_idx].var == NULL;
4308 }
4309 
4310 #if defined(FEAT_CRYPT) || defined(PROTO)
4311 /*
4312  * Returns TRUE if the option at 'opt_idx' is a crypt key option
4313  */
4314     int
is_crypt_key_option(int opt_idx)4315 is_crypt_key_option(int opt_idx)
4316 {
4317     return options[opt_idx].indir == PV_KEY;
4318 }
4319 #endif
4320 
4321 /*
4322  * Set the value of option "name".
4323  * Use "string" for string options, use "number" for other options.
4324  *
4325  * Returns NULL on success or error message on error.
4326  */
4327     char *
set_option_value(char_u * name,long number,char_u * string,int opt_flags)4328 set_option_value(
4329     char_u	*name,
4330     long	number,
4331     char_u	*string,
4332     int		opt_flags)	// OPT_LOCAL or 0 (both)
4333 {
4334     int		opt_idx;
4335     char_u	*varp;
4336     long_u	flags;
4337 
4338     opt_idx = findoption(name);
4339     if (opt_idx < 0)
4340     {
4341 	int key;
4342 
4343 	if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
4344 		&& (key = find_key_option(name, FALSE)) != 0)
4345 	{
4346 	    char_u key_name[2];
4347 
4348 	    if (key < 0)
4349 	    {
4350 		key_name[0] = KEY2TERMCAP0(key);
4351 		key_name[1] = KEY2TERMCAP1(key);
4352 	    }
4353 	    else
4354 	    {
4355 		key_name[0] = KS_KEY;
4356 		key_name[1] = (key & 0xff);
4357 	    }
4358 	    add_termcode(key_name, string, FALSE);
4359 	    if (full_screen)
4360 		ttest(FALSE);
4361 	    redraw_all_later(CLEAR);
4362 	    return NULL;
4363 	}
4364 
4365 	semsg(_("E355: Unknown option: %s"), name);
4366     }
4367     else
4368     {
4369 	flags = options[opt_idx].flags;
4370 #ifdef HAVE_SANDBOX
4371 	// Disallow changing some options in the sandbox
4372 	if (sandbox > 0 && (flags & P_SECURE))
4373 	{
4374 	    emsg(_(e_not_allowed_in_sandbox));
4375 	    return NULL;
4376 	}
4377 #endif
4378 	if (flags & P_STRING)
4379 	    return set_string_option(opt_idx, string, opt_flags);
4380 	else
4381 	{
4382 	    varp = get_varp_scope(&(options[opt_idx]), opt_flags);
4383 	    if (varp != NULL)	// hidden option is not changed
4384 	    {
4385 		if (number == 0 && string != NULL)
4386 		{
4387 		    int idx;
4388 
4389 		    // Either we are given a string or we are setting option
4390 		    // to zero.
4391 		    for (idx = 0; string[idx] == '0'; ++idx)
4392 			;
4393 		    if (string[idx] != NUL || idx == 0)
4394 		    {
4395 			// There's another character after zeros or the string
4396 			// is empty.  In both cases, we are trying to set a
4397 			// num option using a string.
4398 			semsg(_("E521: Number required: &%s = '%s'"),
4399 								name, string);
4400 			return NULL;     // do nothing as we hit an error
4401 
4402 		    }
4403 		}
4404 		if (flags & P_NUM)
4405 		    return set_num_option(opt_idx, varp, number,
4406 							  NULL, 0, opt_flags);
4407 		else
4408 		    return set_bool_option(opt_idx, varp, (int)number,
4409 								   opt_flags);
4410 	    }
4411 	}
4412     }
4413     return NULL;
4414 }
4415 
4416 /*
4417  * Get the terminal code for a terminal option.
4418  * Returns NULL when not found.
4419  */
4420     char_u *
get_term_code(char_u * tname)4421 get_term_code(char_u *tname)
4422 {
4423     int	    opt_idx;
4424     char_u  *varp;
4425 
4426     if (tname[0] != 't' || tname[1] != '_' ||
4427 	    tname[2] == NUL || tname[3] == NUL)
4428 	return NULL;
4429     if ((opt_idx = findoption(tname)) >= 0)
4430     {
4431 	varp = get_varp(&(options[opt_idx]));
4432 	if (varp != NULL)
4433 	    varp = *(char_u **)(varp);
4434 	return varp;
4435     }
4436     return find_termcode(tname + 2);
4437 }
4438 
4439     char_u *
get_highlight_default(void)4440 get_highlight_default(void)
4441 {
4442     int i;
4443 
4444     i = findoption((char_u *)"hl");
4445     if (i >= 0)
4446 	return options[i].def_val[VI_DEFAULT];
4447     return (char_u *)NULL;
4448 }
4449 
4450     char_u *
get_encoding_default(void)4451 get_encoding_default(void)
4452 {
4453     int i;
4454 
4455     i = findoption((char_u *)"enc");
4456     if (i >= 0)
4457 	return options[i].def_val[VI_DEFAULT];
4458     return (char_u *)NULL;
4459 }
4460 
4461 /*
4462  * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
4463  * When "has_lt" is true there is a '<' before "*arg_arg".
4464  * Returns 0 when the key is not recognized.
4465  */
4466     static int
find_key_option(char_u * arg_arg,int has_lt)4467 find_key_option(char_u *arg_arg, int has_lt)
4468 {
4469     int		key = 0;
4470     int		modifiers;
4471     char_u	*arg = arg_arg;
4472 
4473     /*
4474      * Don't use get_special_key_code() for t_xx, we don't want it to call
4475      * add_termcap_entry().
4476      */
4477     if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
4478 	key = TERMCAP2KEY(arg[2], arg[3]);
4479     else if (has_lt)
4480     {
4481 	--arg;			    // put arg at the '<'
4482 	modifiers = 0;
4483 	key = find_special_key(&arg, &modifiers,
4484 			    FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL);
4485 	if (modifiers)		    // can't handle modifiers here
4486 	    key = 0;
4487     }
4488     return key;
4489 }
4490 
4491 /*
4492  * if 'all' == 0: show changed options
4493  * if 'all' == 1: show all normal options
4494  * if 'all' == 2: show all terminal options
4495  */
4496     static void
showoptions(int all,int opt_flags)4497 showoptions(
4498     int		all,
4499     int		opt_flags)	// OPT_LOCAL and/or OPT_GLOBAL
4500 {
4501     struct vimoption	*p;
4502     int			col;
4503     int			isterm;
4504     char_u		*varp;
4505     struct vimoption	**items;
4506     int			item_count;
4507     int			run;
4508     int			row, rows;
4509     int			cols;
4510     int			i;
4511     int			len;
4512 
4513 #define INC 20
4514 #define GAP 3
4515 
4516     items = ALLOC_MULT(struct vimoption *, OPTION_COUNT);
4517     if (items == NULL)
4518 	return;
4519 
4520     // Highlight title
4521     if (all == 2)
4522 	msg_puts_title(_("\n--- Terminal codes ---"));
4523     else if (opt_flags & OPT_GLOBAL)
4524 	msg_puts_title(_("\n--- Global option values ---"));
4525     else if (opt_flags & OPT_LOCAL)
4526 	msg_puts_title(_("\n--- Local option values ---"));
4527     else
4528 	msg_puts_title(_("\n--- Options ---"));
4529 
4530     /*
4531      * Do the loop two times:
4532      * 1. display the short items
4533      * 2. display the long items (only strings and numbers)
4534      * When "opt_flags" has OPT_ONECOLUMN do everything in run 2.
4535      */
4536     for (run = 1; run <= 2 && !got_int; ++run)
4537     {
4538 	/*
4539 	 * collect the items in items[]
4540 	 */
4541 	item_count = 0;
4542 	for (p = &options[0]; p->fullname != NULL; p++)
4543 	{
4544 	    // apply :filter /pat/
4545 	    if (message_filtered((char_u *)p->fullname))
4546 		continue;
4547 
4548 	    varp = NULL;
4549 	    isterm = istermoption(p);
4550 	    if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0)
4551 	    {
4552 		if (p->indir != PV_NONE && !isterm)
4553 		    varp = get_varp_scope(p, opt_flags);
4554 	    }
4555 	    else
4556 		varp = get_varp(p);
4557 	    if (varp != NULL
4558 		    && ((all == 2 && isterm)
4559 			|| (all == 1 && !isterm)
4560 			|| (all == 0 && !optval_default(p, varp, p_cp))))
4561 	    {
4562 		if (opt_flags & OPT_ONECOLUMN)
4563 		    len = Columns;
4564 		else if (p->flags & P_BOOL)
4565 		    len = 1;		// a toggle option fits always
4566 		else
4567 		{
4568 		    option_value2string(p, opt_flags);
4569 		    len = (int)STRLEN(p->fullname) + vim_strsize(NameBuff) + 1;
4570 		}
4571 		if ((len <= INC - GAP && run == 1) ||
4572 						(len > INC - GAP && run == 2))
4573 		    items[item_count++] = p;
4574 	    }
4575 	}
4576 
4577 	/*
4578 	 * display the items
4579 	 */
4580 	if (run == 1)
4581 	{
4582 	    cols = (Columns + GAP - 3) / INC;
4583 	    if (cols == 0)
4584 		cols = 1;
4585 	    rows = (item_count + cols - 1) / cols;
4586 	}
4587 	else	// run == 2
4588 	    rows = item_count;
4589 	for (row = 0; row < rows && !got_int; ++row)
4590 	{
4591 	    msg_putchar('\n');			// go to next line
4592 	    if (got_int)			// 'q' typed in more
4593 		break;
4594 	    col = 0;
4595 	    for (i = row; i < item_count; i += rows)
4596 	    {
4597 		msg_col = col;			// make columns
4598 		showoneopt(items[i], opt_flags);
4599 		col += INC;
4600 	    }
4601 	    out_flush();
4602 	    ui_breakcheck();
4603 	}
4604     }
4605     vim_free(items);
4606 }
4607 
4608 /*
4609  * Return TRUE if option "p" has its default value.
4610  */
4611     static int
optval_default(struct vimoption * p,char_u * varp,int compatible)4612 optval_default(struct vimoption *p, char_u *varp, int compatible)
4613 {
4614     int		dvi;
4615 
4616     if (varp == NULL)
4617 	return TRUE;	    // hidden option is always at default
4618     dvi = ((p->flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
4619     if (p->flags & P_NUM)
4620 	return (*(long *)varp == (long)(long_i)p->def_val[dvi]);
4621     if (p->flags & P_BOOL)
4622 			// the cast to long is required for Manx C, long_i is
4623 			// needed for MSVC
4624 	return (*(int *)varp == (int)(long)(long_i)p->def_val[dvi]);
4625     // P_STRING
4626     return (STRCMP(*(char_u **)varp, p->def_val[dvi]) == 0);
4627 }
4628 
4629 /*
4630  * showoneopt: show the value of one option
4631  * must not be called with a hidden option!
4632  */
4633     static void
showoneopt(struct vimoption * p,int opt_flags)4634 showoneopt(
4635     struct vimoption	*p,
4636     int			opt_flags)	// OPT_LOCAL or OPT_GLOBAL
4637 {
4638     char_u	*varp;
4639     int		save_silent = silent_mode;
4640 
4641     silent_mode = FALSE;
4642     info_message = TRUE;	// use mch_msg(), not mch_errmsg()
4643 
4644     varp = get_varp_scope(p, opt_flags);
4645 
4646     // for 'modified' we also need to check if 'ff' or 'fenc' changed.
4647     if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
4648 					? !curbufIsChanged() : !*(int *)varp))
4649 	msg_puts("no");
4650     else if ((p->flags & P_BOOL) && *(int *)varp < 0)
4651 	msg_puts("--");
4652     else
4653 	msg_puts("  ");
4654     msg_puts(p->fullname);
4655     if (!(p->flags & P_BOOL))
4656     {
4657 	msg_putchar('=');
4658 	// put value string in NameBuff
4659 	option_value2string(p, opt_flags);
4660 	msg_outtrans(NameBuff);
4661     }
4662 
4663     silent_mode = save_silent;
4664     info_message = FALSE;
4665 }
4666 
4667 /*
4668  * Write modified options as ":set" commands to a file.
4669  *
4670  * There are three values for "opt_flags":
4671  * OPT_GLOBAL:		   Write global option values and fresh values of
4672  *			   buffer-local options (used for start of a session
4673  *			   file).
4674  * OPT_GLOBAL + OPT_LOCAL: Idem, add fresh values of window-local options for
4675  *			   curwin (used for a vimrc file).
4676  * OPT_LOCAL:		   Write buffer-local option values for curbuf, fresh
4677  *			   and local values for window-local options of
4678  *			   curwin.  Local values are also written when at the
4679  *			   default value, because a modeline or autocommand
4680  *			   may have set them when doing ":edit file" and the
4681  *			   user has set them back at the default or fresh
4682  *			   value.
4683  *			   When "local_only" is TRUE, don't write fresh
4684  *			   values, only local values (for ":mkview").
4685  * (fresh value = value used for a new buffer or window for a local option).
4686  *
4687  * Return FAIL on error, OK otherwise.
4688  */
4689     int
makeset(FILE * fd,int opt_flags,int local_only)4690 makeset(FILE *fd, int opt_flags, int local_only)
4691 {
4692     struct vimoption	*p;
4693     char_u		*varp;			// currently used value
4694     char_u		*varp_fresh;		// local value
4695     char_u		*varp_local = NULL;	// fresh value
4696     char		*cmd;
4697     int			round;
4698     int			pri;
4699 
4700     /*
4701      * The options that don't have a default (terminal name, columns, lines)
4702      * are never written.  Terminal options are also not written.
4703      * Do the loop over "options[]" twice: once for options with the
4704      * P_PRI_MKRC flag and once without.
4705      */
4706     for (pri = 1; pri >= 0; --pri)
4707     {
4708       for (p = &options[0]; !istermoption(p); p++)
4709 	if (!(p->flags & P_NO_MKRC)
4710 		&& !istermoption(p)
4711 		&& ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0)))
4712 	{
4713 	    // skip global option when only doing locals
4714 	    if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL))
4715 		continue;
4716 
4717 	    // Do not store options like 'bufhidden' and 'syntax' in a vimrc
4718 	    // file, they are always buffer-specific.
4719 	    if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB))
4720 		continue;
4721 
4722 	    // Global values are only written when not at the default value.
4723 	    varp = get_varp_scope(p, opt_flags);
4724 	    if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp, p_cp))
4725 		continue;
4726 
4727 	    if ((opt_flags & OPT_SKIPRTP) && (p->var == (char_u *)&p_rtp
4728 						 || p->var == (char_u *)&p_pp))
4729 		continue;
4730 
4731 	    round = 2;
4732 	    if (p->indir != PV_NONE)
4733 	    {
4734 		if (p->var == VAR_WIN)
4735 		{
4736 		    // skip window-local option when only doing globals
4737 		    if (!(opt_flags & OPT_LOCAL))
4738 			continue;
4739 		    // When fresh value of window-local option is not at the
4740 		    // default, need to write it too.
4741 		    if (!(opt_flags & OPT_GLOBAL) && !local_only)
4742 		    {
4743 			varp_fresh = get_varp_scope(p, OPT_GLOBAL);
4744 			if (!optval_default(p, varp_fresh, p_cp))
4745 			{
4746 			    round = 1;
4747 			    varp_local = varp;
4748 			    varp = varp_fresh;
4749 			}
4750 		    }
4751 		}
4752 	    }
4753 
4754 	    // Round 1: fresh value for window-local options.
4755 	    // Round 2: other values
4756 	    for ( ; round <= 2; varp = varp_local, ++round)
4757 	    {
4758 		if (round == 1 || (opt_flags & OPT_GLOBAL))
4759 		    cmd = "set";
4760 		else
4761 		    cmd = "setlocal";
4762 
4763 		if (p->flags & P_BOOL)
4764 		{
4765 		    if (put_setbool(fd, cmd, p->fullname, *(int *)varp) == FAIL)
4766 			return FAIL;
4767 		}
4768 		else if (p->flags & P_NUM)
4769 		{
4770 		    if (put_setnum(fd, cmd, p->fullname, (long *)varp) == FAIL)
4771 			return FAIL;
4772 		}
4773 		else    // P_STRING
4774 		{
4775 		    int		do_endif = FALSE;
4776 
4777 		    // Don't set 'syntax' and 'filetype' again if the value is
4778 		    // already right, avoids reloading the syntax file.
4779 		    if (
4780 #if defined(FEAT_SYN_HL)
4781 			    p->indir == PV_SYN ||
4782 #endif
4783 			    p->indir == PV_FT)
4784 		    {
4785 			if (fprintf(fd, "if &%s != '%s'", p->fullname,
4786 						       *(char_u **)(varp)) < 0
4787 				|| put_eol(fd) < 0)
4788 			    return FAIL;
4789 			do_endif = TRUE;
4790 		    }
4791 		    if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
4792 							     p->flags) == FAIL)
4793 			return FAIL;
4794 		    if (do_endif)
4795 		    {
4796 			if (put_line(fd, "endif") == FAIL)
4797 			    return FAIL;
4798 		    }
4799 		}
4800 	    }
4801 	}
4802     }
4803     return OK;
4804 }
4805 
4806 #if defined(FEAT_FOLDING) || defined(PROTO)
4807 /*
4808  * Generate set commands for the local fold options only.  Used when
4809  * 'sessionoptions' or 'viewoptions' contains "folds" but not "options".
4810  */
4811     int
makefoldset(FILE * fd)4812 makefoldset(FILE *fd)
4813 {
4814     if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
4815 # ifdef FEAT_EVAL
4816 	    || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0)
4817 								       == FAIL
4818 # endif
4819 	    || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0)
4820 								       == FAIL
4821 	    || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0)
4822 								       == FAIL
4823 	    || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
4824 	    || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
4825 	    || put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
4826 	    || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL
4827 	    )
4828 	return FAIL;
4829 
4830     return OK;
4831 }
4832 #endif
4833 
4834     static int
put_setstring(FILE * fd,char * cmd,char * name,char_u ** valuep,long_u flags)4835 put_setstring(
4836     FILE	*fd,
4837     char	*cmd,
4838     char	*name,
4839     char_u	**valuep,
4840     long_u	flags)
4841 {
4842     char_u	*s;
4843     char_u	*buf = NULL;
4844     char_u	*part = NULL;
4845     char_u	*p;
4846 
4847     if (fprintf(fd, "%s %s=", cmd, name) < 0)
4848 	return FAIL;
4849     if (*valuep != NULL)
4850     {
4851 	// Output 'pastetoggle' as key names.  For other
4852 	// options some characters have to be escaped with
4853 	// CTRL-V or backslash
4854 	if (valuep == &p_pt)
4855 	{
4856 	    s = *valuep;
4857 	    while (*s != NUL)
4858 		if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
4859 		    return FAIL;
4860 	}
4861 	// expand the option value, replace $HOME by ~
4862 	else if ((flags & P_EXPAND) != 0)
4863 	{
4864 	    int  size = (int)STRLEN(*valuep) + 1;
4865 
4866 	    // replace home directory in the whole option value into "buf"
4867 	    buf = alloc(size);
4868 	    if (buf == NULL)
4869 		goto fail;
4870 	    home_replace(NULL, *valuep, buf, size, FALSE);
4871 
4872 	    // If the option value is longer than MAXPATHL, we need to append
4873 	    // each comma separated part of the option separately, so that it
4874 	    // can be expanded when read back.
4875 	    if (size >= MAXPATHL && (flags & P_COMMA) != 0
4876 					   && vim_strchr(*valuep, ',') != NULL)
4877 	    {
4878 		part = alloc(size);
4879 		if (part == NULL)
4880 		    goto fail;
4881 
4882 		// write line break to clear the option, e.g. ':set rtp='
4883 		if (put_eol(fd) == FAIL)
4884 		    goto fail;
4885 
4886 		p = buf;
4887 		while (*p != NUL)
4888 		{
4889 		    // for each comma separated option part, append value to
4890 		    // the option, :set rtp+=value
4891 		    if (fprintf(fd, "%s %s+=", cmd, name) < 0)
4892 			goto fail;
4893 		    (void)copy_option_part(&p, part, size,  ",");
4894 		    if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL)
4895 			goto fail;
4896 		}
4897 		vim_free(buf);
4898 		vim_free(part);
4899 		return OK;
4900 	    }
4901 	    if (put_escstr(fd, buf, 2) == FAIL)
4902 	    {
4903 		vim_free(buf);
4904 		return FAIL;
4905 	    }
4906 	    vim_free(buf);
4907 	}
4908 	else if (put_escstr(fd, *valuep, 2) == FAIL)
4909 	    return FAIL;
4910     }
4911     if (put_eol(fd) < 0)
4912 	return FAIL;
4913     return OK;
4914 fail:
4915     vim_free(buf);
4916     vim_free(part);
4917     return FAIL;
4918 }
4919 
4920     static int
put_setnum(FILE * fd,char * cmd,char * name,long * valuep)4921 put_setnum(
4922     FILE	*fd,
4923     char	*cmd,
4924     char	*name,
4925     long	*valuep)
4926 {
4927     long	wc;
4928 
4929     if (fprintf(fd, "%s %s=", cmd, name) < 0)
4930 	return FAIL;
4931     if (wc_use_keyname((char_u *)valuep, &wc))
4932     {
4933 	// print 'wildchar' and 'wildcharm' as a key name
4934 	if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0)
4935 	    return FAIL;
4936     }
4937     else if (fprintf(fd, "%ld", *valuep) < 0)
4938 	return FAIL;
4939     if (put_eol(fd) < 0)
4940 	return FAIL;
4941     return OK;
4942 }
4943 
4944     static int
put_setbool(FILE * fd,char * cmd,char * name,int value)4945 put_setbool(
4946     FILE	*fd,
4947     char	*cmd,
4948     char	*name,
4949     int		value)
4950 {
4951     if (value < 0)	// global/local option using global value
4952 	return OK;
4953     if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
4954 	    || put_eol(fd) < 0)
4955 	return FAIL;
4956     return OK;
4957 }
4958 
4959 /*
4960  * Clear all the terminal options.
4961  * If the option has been allocated, free the memory.
4962  * Terminal options are never hidden or indirect.
4963  */
4964     void
clear_termoptions(void)4965 clear_termoptions(void)
4966 {
4967     /*
4968      * Reset a few things before clearing the old options. This may cause
4969      * outputting a few things that the terminal doesn't understand, but the
4970      * screen will be cleared later, so this is OK.
4971      */
4972     mch_setmouse(FALSE);	    // switch mouse off
4973 #ifdef FEAT_TITLE
4974     mch_restore_title(SAVE_RESTORE_BOTH);    // restore window titles
4975 #endif
4976 #if defined(FEAT_XCLIPBOARD) && defined(FEAT_GUI)
4977     // When starting the GUI close the display opened for the clipboard.
4978     // After restoring the title, because that will need the display.
4979     if (gui.starting)
4980 	clear_xterm_clip();
4981 #endif
4982     stoptermcap();			// stop termcap mode
4983 
4984     free_termoptions();
4985 }
4986 
4987     void
free_termoptions(void)4988 free_termoptions(void)
4989 {
4990     struct vimoption   *p;
4991 
4992     for (p = options; p->fullname != NULL; p++)
4993 	if (istermoption(p))
4994 	{
4995 	    if (p->flags & P_ALLOCED)
4996 		free_string_option(*(char_u **)(p->var));
4997 	    if (p->flags & P_DEF_ALLOCED)
4998 		free_string_option(p->def_val[VI_DEFAULT]);
4999 	    *(char_u **)(p->var) = empty_option;
5000 	    p->def_val[VI_DEFAULT] = empty_option;
5001 	    p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED);
5002 #ifdef FEAT_EVAL
5003 	    // remember where the option was cleared
5004 	    set_option_sctx_idx((int)(p - options), OPT_GLOBAL, current_sctx);
5005 #endif
5006 	}
5007     clear_termcodes();
5008 }
5009 
5010 /*
5011  * Free the string for one term option, if it was allocated.
5012  * Set the string to empty_option and clear allocated flag.
5013  * "var" points to the option value.
5014  */
5015     void
free_one_termoption(char_u * var)5016 free_one_termoption(char_u *var)
5017 {
5018     struct vimoption   *p;
5019 
5020     for (p = &options[0]; p->fullname != NULL; p++)
5021 	if (p->var == var)
5022 	{
5023 	    if (p->flags & P_ALLOCED)
5024 		free_string_option(*(char_u **)(p->var));
5025 	    *(char_u **)(p->var) = empty_option;
5026 	    p->flags &= ~P_ALLOCED;
5027 	    break;
5028 	}
5029 }
5030 
5031 /*
5032  * Set the terminal option defaults to the current value.
5033  * Used after setting the terminal name.
5034  */
5035     void
set_term_defaults(void)5036 set_term_defaults(void)
5037 {
5038     struct vimoption   *p;
5039 
5040     for (p = &options[0]; p->fullname != NULL; p++)
5041     {
5042 	if (istermoption(p) && p->def_val[VI_DEFAULT] != *(char_u **)(p->var))
5043 	{
5044 	    if (p->flags & P_DEF_ALLOCED)
5045 	    {
5046 		free_string_option(p->def_val[VI_DEFAULT]);
5047 		p->flags &= ~P_DEF_ALLOCED;
5048 	    }
5049 	    p->def_val[VI_DEFAULT] = *(char_u **)(p->var);
5050 	    if (p->flags & P_ALLOCED)
5051 	    {
5052 		p->flags |= P_DEF_ALLOCED;
5053 		p->flags &= ~P_ALLOCED;	 // don't free the value now
5054 	    }
5055 	}
5056     }
5057 }
5058 
5059 /*
5060  * return TRUE if 'p' starts with 't_'
5061  */
5062     static int
istermoption(struct vimoption * p)5063 istermoption(struct vimoption *p)
5064 {
5065     return (p->fullname[0] == 't' && p->fullname[1] == '_');
5066 }
5067 
5068 /*
5069  * Returns TRUE if the option at 'opt_idx' starts with 't_'
5070  */
5071     int
istermoption_idx(int opt_idx)5072 istermoption_idx(int opt_idx)
5073 {
5074     return istermoption(&options[opt_idx]);
5075 }
5076 
5077 #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
5078 /*
5079  * Unset local option value, similar to ":set opt<".
5080  */
5081     void
unset_global_local_option(char_u * name,void * from)5082 unset_global_local_option(char_u *name, void *from)
5083 {
5084     struct vimoption *p;
5085     int		opt_idx;
5086     buf_T	*buf = (buf_T *)from;
5087 
5088     opt_idx = findoption(name);
5089     if (opt_idx < 0)
5090 	return;
5091     p = &(options[opt_idx]);
5092 
5093     switch ((int)p->indir)
5094     {
5095 	// global option with local value: use local value if it's been set
5096 	case PV_EP:
5097 	    clear_string_option(&buf->b_p_ep);
5098 	    break;
5099 	case PV_KP:
5100 	    clear_string_option(&buf->b_p_kp);
5101 	    break;
5102 	case PV_PATH:
5103 	    clear_string_option(&buf->b_p_path);
5104 	    break;
5105 	case PV_AR:
5106 	    buf->b_p_ar = -1;
5107 	    break;
5108 	case PV_BKC:
5109 	    clear_string_option(&buf->b_p_bkc);
5110 	    buf->b_bkc_flags = 0;
5111 	    break;
5112 	case PV_TAGS:
5113 	    clear_string_option(&buf->b_p_tags);
5114 	    break;
5115 	case PV_TC:
5116 	    clear_string_option(&buf->b_p_tc);
5117 	    buf->b_tc_flags = 0;
5118 	    break;
5119         case PV_SISO:
5120             curwin->w_p_siso = -1;
5121             break;
5122         case PV_SO:
5123             curwin->w_p_so = -1;
5124             break;
5125 #ifdef FEAT_FIND_ID
5126 	case PV_DEF:
5127 	    clear_string_option(&buf->b_p_def);
5128 	    break;
5129 	case PV_INC:
5130 	    clear_string_option(&buf->b_p_inc);
5131 	    break;
5132 #endif
5133 	case PV_DICT:
5134 	    clear_string_option(&buf->b_p_dict);
5135 	    break;
5136 	case PV_TSR:
5137 	    clear_string_option(&buf->b_p_tsr);
5138 	    break;
5139 #ifdef FEAT_COMPL_FUNC
5140 	case PV_TSRFU:
5141 	    clear_string_option(&buf->b_p_tsrfu);
5142 	    break;
5143 #endif
5144 	case PV_FP:
5145 	    clear_string_option(&buf->b_p_fp);
5146 	    break;
5147 #ifdef FEAT_QUICKFIX
5148 	case PV_EFM:
5149 	    clear_string_option(&buf->b_p_efm);
5150 	    break;
5151 	case PV_GP:
5152 	    clear_string_option(&buf->b_p_gp);
5153 	    break;
5154 	case PV_MP:
5155 	    clear_string_option(&buf->b_p_mp);
5156 	    break;
5157 #endif
5158 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5159 	case PV_BEXPR:
5160 	    clear_string_option(&buf->b_p_bexpr);
5161 	    break;
5162 #endif
5163 #if defined(FEAT_CRYPT)
5164 	case PV_CM:
5165 	    clear_string_option(&buf->b_p_cm);
5166 	    break;
5167 #endif
5168 #ifdef FEAT_LINEBREAK
5169 	case PV_SBR:
5170 	    clear_string_option(&((win_T *)from)->w_p_sbr);
5171 	    break;
5172 #endif
5173 #ifdef FEAT_STL_OPT
5174 	case PV_STL:
5175 	    clear_string_option(&((win_T *)from)->w_p_stl);
5176 	    break;
5177 #endif
5178 	case PV_UL:
5179 	    buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
5180 	    break;
5181 #ifdef FEAT_LISP
5182 	case PV_LW:
5183 	    clear_string_option(&buf->b_p_lw);
5184 	    break;
5185 #endif
5186 	case PV_MENC:
5187 	    clear_string_option(&buf->b_p_menc);
5188 	    break;
5189 	case PV_LCS:
5190 	    clear_string_option(&((win_T *)from)->w_p_lcs);
5191 	    set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs);
5192 	    redraw_later(NOT_VALID);
5193 	    break;
5194 	case PV_VE:
5195 	    clear_string_option(&((win_T *)from)->w_p_ve);
5196 	    ((win_T *)from)->w_ve_flags = 0;
5197 	    break;
5198     }
5199 }
5200 #endif
5201 
5202 /*
5203  * Get pointer to option variable, depending on local or global scope.
5204  */
5205     static char_u *
get_varp_scope(struct vimoption * p,int opt_flags)5206 get_varp_scope(struct vimoption *p, int opt_flags)
5207 {
5208     if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE)
5209     {
5210 	if (p->var == VAR_WIN)
5211 	    return (char_u *)GLOBAL_WO(get_varp(p));
5212 	return p->var;
5213     }
5214     if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH))
5215     {
5216 	switch ((int)p->indir)
5217 	{
5218 	    case PV_FP:   return (char_u *)&(curbuf->b_p_fp);
5219 #ifdef FEAT_QUICKFIX
5220 	    case PV_EFM:  return (char_u *)&(curbuf->b_p_efm);
5221 	    case PV_GP:   return (char_u *)&(curbuf->b_p_gp);
5222 	    case PV_MP:   return (char_u *)&(curbuf->b_p_mp);
5223 #endif
5224 	    case PV_EP:   return (char_u *)&(curbuf->b_p_ep);
5225 	    case PV_KP:   return (char_u *)&(curbuf->b_p_kp);
5226 	    case PV_PATH: return (char_u *)&(curbuf->b_p_path);
5227 	    case PV_AR:   return (char_u *)&(curbuf->b_p_ar);
5228 	    case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
5229 	    case PV_TC:   return (char_u *)&(curbuf->b_p_tc);
5230             case PV_SISO: return (char_u *)&(curwin->w_p_siso);
5231             case PV_SO:   return (char_u *)&(curwin->w_p_so);
5232 #ifdef FEAT_FIND_ID
5233 	    case PV_DEF:  return (char_u *)&(curbuf->b_p_def);
5234 	    case PV_INC:  return (char_u *)&(curbuf->b_p_inc);
5235 #endif
5236 	    case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
5237 	    case PV_TSR:  return (char_u *)&(curbuf->b_p_tsr);
5238 #ifdef FEAT_COMPL_FUNC
5239 	    case PV_TSRFU: return (char_u *)&(curbuf->b_p_tsrfu);
5240 #endif
5241 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5242 	    case PV_BEXPR: return (char_u *)&(curbuf->b_p_bexpr);
5243 #endif
5244 #if defined(FEAT_CRYPT)
5245 	    case PV_CM:	  return (char_u *)&(curbuf->b_p_cm);
5246 #endif
5247 #ifdef FEAT_LINEBREAK
5248 	    case PV_SBR:  return (char_u *)&(curwin->w_p_sbr);
5249 #endif
5250 #ifdef FEAT_STL_OPT
5251 	    case PV_STL:  return (char_u *)&(curwin->w_p_stl);
5252 #endif
5253 	    case PV_UL:   return (char_u *)&(curbuf->b_p_ul);
5254 #ifdef FEAT_LISP
5255 	    case PV_LW:   return (char_u *)&(curbuf->b_p_lw);
5256 #endif
5257 	    case PV_BKC:  return (char_u *)&(curbuf->b_p_bkc);
5258 	    case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
5259 	    case PV_LCS:  return (char_u *)&(curwin->w_p_lcs);
5260 	    case PV_VE:	  return (char_u *)&(curwin->w_p_ve);
5261 
5262 	}
5263 	return NULL; // "cannot happen"
5264     }
5265     return get_varp(p);
5266 }
5267 
5268 /*
5269  * Get pointer to option variable at 'opt_idx', depending on local or global
5270  * scope.
5271  */
5272     char_u *
get_option_varp_scope(int opt_idx,int opt_flags)5273 get_option_varp_scope(int opt_idx, int opt_flags)
5274 {
5275     return get_varp_scope(&(options[opt_idx]), opt_flags);
5276 }
5277 
5278 /*
5279  * Get pointer to option variable.
5280  */
5281     static char_u *
get_varp(struct vimoption * p)5282 get_varp(struct vimoption *p)
5283 {
5284     // hidden option, always return NULL
5285     if (p->var == NULL)
5286 	return NULL;
5287 
5288     switch ((int)p->indir)
5289     {
5290 	case PV_NONE:	return p->var;
5291 
5292 	// global option with local value: use local value if it's been set
5293 	case PV_EP:	return *curbuf->b_p_ep != NUL
5294 				    ? (char_u *)&curbuf->b_p_ep : p->var;
5295 	case PV_KP:	return *curbuf->b_p_kp != NUL
5296 				    ? (char_u *)&curbuf->b_p_kp : p->var;
5297 	case PV_PATH:	return *curbuf->b_p_path != NUL
5298 				    ? (char_u *)&(curbuf->b_p_path) : p->var;
5299 	case PV_AR:	return curbuf->b_p_ar >= 0
5300 				    ? (char_u *)&(curbuf->b_p_ar) : p->var;
5301 	case PV_TAGS:	return *curbuf->b_p_tags != NUL
5302 				    ? (char_u *)&(curbuf->b_p_tags) : p->var;
5303 	case PV_TC:	return *curbuf->b_p_tc != NUL
5304 				    ? (char_u *)&(curbuf->b_p_tc) : p->var;
5305 	case PV_BKC:	return *curbuf->b_p_bkc != NUL
5306 				    ? (char_u *)&(curbuf->b_p_bkc) : p->var;
5307 	case PV_SISO:	return curwin->w_p_siso >= 0
5308 				    ? (char_u *)&(curwin->w_p_siso) : p->var;
5309 	case PV_SO:	return curwin->w_p_so >= 0
5310 				    ? (char_u *)&(curwin->w_p_so) : p->var;
5311 #ifdef FEAT_FIND_ID
5312 	case PV_DEF:	return *curbuf->b_p_def != NUL
5313 				    ? (char_u *)&(curbuf->b_p_def) : p->var;
5314 	case PV_INC:	return *curbuf->b_p_inc != NUL
5315 				    ? (char_u *)&(curbuf->b_p_inc) : p->var;
5316 #endif
5317 	case PV_DICT:	return *curbuf->b_p_dict != NUL
5318 				    ? (char_u *)&(curbuf->b_p_dict) : p->var;
5319 	case PV_TSR:	return *curbuf->b_p_tsr != NUL
5320 				    ? (char_u *)&(curbuf->b_p_tsr) : p->var;
5321 #ifdef FEAT_COMPL_FUNC
5322 	case PV_TSRFU:	return *curbuf->b_p_tsrfu != NUL
5323 				    ? (char_u *)&(curbuf->b_p_tsrfu) : p->var;
5324 #endif
5325 	case PV_FP:	return *curbuf->b_p_fp != NUL
5326 				    ? (char_u *)&(curbuf->b_p_fp) : p->var;
5327 #ifdef FEAT_QUICKFIX
5328 	case PV_EFM:	return *curbuf->b_p_efm != NUL
5329 				    ? (char_u *)&(curbuf->b_p_efm) : p->var;
5330 	case PV_GP:	return *curbuf->b_p_gp != NUL
5331 				    ? (char_u *)&(curbuf->b_p_gp) : p->var;
5332 	case PV_MP:	return *curbuf->b_p_mp != NUL
5333 				    ? (char_u *)&(curbuf->b_p_mp) : p->var;
5334 #endif
5335 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5336 	case PV_BEXPR:	return *curbuf->b_p_bexpr != NUL
5337 				    ? (char_u *)&(curbuf->b_p_bexpr) : p->var;
5338 #endif
5339 #if defined(FEAT_CRYPT)
5340 	case PV_CM:	return *curbuf->b_p_cm != NUL
5341 				    ? (char_u *)&(curbuf->b_p_cm) : p->var;
5342 #endif
5343 #ifdef FEAT_LINEBREAK
5344 	case PV_SBR:	return *curwin->w_p_sbr != NUL
5345 				    ? (char_u *)&(curwin->w_p_sbr) : p->var;
5346 #endif
5347 #ifdef FEAT_STL_OPT
5348 	case PV_STL:	return *curwin->w_p_stl != NUL
5349 				    ? (char_u *)&(curwin->w_p_stl) : p->var;
5350 #endif
5351 	case PV_UL:	return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
5352 				    ? (char_u *)&(curbuf->b_p_ul) : p->var;
5353 #ifdef FEAT_LISP
5354 	case PV_LW:	return *curbuf->b_p_lw != NUL
5355 				    ? (char_u *)&(curbuf->b_p_lw) : p->var;
5356 #endif
5357 	case PV_MENC:	return *curbuf->b_p_menc != NUL
5358 				    ? (char_u *)&(curbuf->b_p_menc) : p->var;
5359 #ifdef FEAT_ARABIC
5360 	case PV_ARAB:	return (char_u *)&(curwin->w_p_arab);
5361 #endif
5362 	case PV_LIST:	return (char_u *)&(curwin->w_p_list);
5363 	case PV_LCS:	return *curwin->w_p_lcs != NUL
5364 				    ? (char_u *)&(curwin->w_p_lcs) : p->var;
5365 	case PV_VE:	return *curwin->w_p_ve != NUL
5366 				    ? (char_u *)&(curwin->w_p_ve) : p->var;
5367 #ifdef FEAT_SPELL
5368 	case PV_SPELL:	return (char_u *)&(curwin->w_p_spell);
5369 #endif
5370 #ifdef FEAT_SYN_HL
5371 	case PV_CUC:	return (char_u *)&(curwin->w_p_cuc);
5372 	case PV_CUL:	return (char_u *)&(curwin->w_p_cul);
5373 	case PV_CULOPT:	return (char_u *)&(curwin->w_p_culopt);
5374 	case PV_CC:	return (char_u *)&(curwin->w_p_cc);
5375 #endif
5376 #ifdef FEAT_DIFF
5377 	case PV_DIFF:	return (char_u *)&(curwin->w_p_diff);
5378 #endif
5379 #ifdef FEAT_FOLDING
5380 	case PV_FDC:	return (char_u *)&(curwin->w_p_fdc);
5381 	case PV_FEN:	return (char_u *)&(curwin->w_p_fen);
5382 	case PV_FDI:	return (char_u *)&(curwin->w_p_fdi);
5383 	case PV_FDL:	return (char_u *)&(curwin->w_p_fdl);
5384 	case PV_FDM:	return (char_u *)&(curwin->w_p_fdm);
5385 	case PV_FML:	return (char_u *)&(curwin->w_p_fml);
5386 	case PV_FDN:	return (char_u *)&(curwin->w_p_fdn);
5387 # ifdef FEAT_EVAL
5388 	case PV_FDE:	return (char_u *)&(curwin->w_p_fde);
5389 	case PV_FDT:	return (char_u *)&(curwin->w_p_fdt);
5390 # endif
5391 	case PV_FMR:	return (char_u *)&(curwin->w_p_fmr);
5392 #endif
5393 	case PV_NU:	return (char_u *)&(curwin->w_p_nu);
5394 	case PV_RNU:	return (char_u *)&(curwin->w_p_rnu);
5395 #ifdef FEAT_LINEBREAK
5396 	case PV_NUW:	return (char_u *)&(curwin->w_p_nuw);
5397 #endif
5398 	case PV_WFH:	return (char_u *)&(curwin->w_p_wfh);
5399 	case PV_WFW:	return (char_u *)&(curwin->w_p_wfw);
5400 #if defined(FEAT_QUICKFIX)
5401 	case PV_PVW:	return (char_u *)&(curwin->w_p_pvw);
5402 #endif
5403 #ifdef FEAT_RIGHTLEFT
5404 	case PV_RL:	return (char_u *)&(curwin->w_p_rl);
5405 	case PV_RLC:	return (char_u *)&(curwin->w_p_rlc);
5406 #endif
5407 	case PV_SCROLL:	return (char_u *)&(curwin->w_p_scr);
5408 	case PV_WRAP:	return (char_u *)&(curwin->w_p_wrap);
5409 #ifdef FEAT_LINEBREAK
5410 	case PV_LBR:	return (char_u *)&(curwin->w_p_lbr);
5411 	case PV_BRI:	return (char_u *)&(curwin->w_p_bri);
5412 	case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt);
5413 #endif
5414 	case PV_WCR:	return (char_u *)&(curwin->w_p_wcr);
5415 	case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
5416 	case PV_CRBIND: return (char_u *)&(curwin->w_p_crb);
5417 #ifdef FEAT_CONCEAL
5418 	case PV_COCU:   return (char_u *)&(curwin->w_p_cocu);
5419 	case PV_COLE:   return (char_u *)&(curwin->w_p_cole);
5420 #endif
5421 #ifdef FEAT_TERMINAL
5422 	case PV_TWK:    return (char_u *)&(curwin->w_p_twk);
5423 	case PV_TWS:    return (char_u *)&(curwin->w_p_tws);
5424 	case PV_TWSL:	return (char_u *)&(curbuf->b_p_twsl);
5425 #endif
5426 
5427 	case PV_AI:	return (char_u *)&(curbuf->b_p_ai);
5428 	case PV_BIN:	return (char_u *)&(curbuf->b_p_bin);
5429 	case PV_BOMB:	return (char_u *)&(curbuf->b_p_bomb);
5430 	case PV_BH:	return (char_u *)&(curbuf->b_p_bh);
5431 	case PV_BT:	return (char_u *)&(curbuf->b_p_bt);
5432 	case PV_BL:	return (char_u *)&(curbuf->b_p_bl);
5433 	case PV_CI:	return (char_u *)&(curbuf->b_p_ci);
5434 #ifdef FEAT_CINDENT
5435 	case PV_CIN:	return (char_u *)&(curbuf->b_p_cin);
5436 	case PV_CINK:	return (char_u *)&(curbuf->b_p_cink);
5437 	case PV_CINO:	return (char_u *)&(curbuf->b_p_cino);
5438 #endif
5439 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
5440 	case PV_CINW:	return (char_u *)&(curbuf->b_p_cinw);
5441 #endif
5442 	case PV_COM:	return (char_u *)&(curbuf->b_p_com);
5443 #ifdef FEAT_FOLDING
5444 	case PV_CMS:	return (char_u *)&(curbuf->b_p_cms);
5445 #endif
5446 	case PV_CPT:	return (char_u *)&(curbuf->b_p_cpt);
5447 #ifdef BACKSLASH_IN_FILENAME
5448 	case PV_CSL:	return (char_u *)&(curbuf->b_p_csl);
5449 #endif
5450 #ifdef FEAT_COMPL_FUNC
5451 	case PV_CFU:	return (char_u *)&(curbuf->b_p_cfu);
5452 	case PV_OFU:	return (char_u *)&(curbuf->b_p_ofu);
5453 #endif
5454 #ifdef FEAT_EVAL
5455 	case PV_TFU:	return (char_u *)&(curbuf->b_p_tfu);
5456 #endif
5457 	case PV_EOL:	return (char_u *)&(curbuf->b_p_eol);
5458 	case PV_FIXEOL:	return (char_u *)&(curbuf->b_p_fixeol);
5459 	case PV_ET:	return (char_u *)&(curbuf->b_p_et);
5460 	case PV_FENC:	return (char_u *)&(curbuf->b_p_fenc);
5461 	case PV_FF:	return (char_u *)&(curbuf->b_p_ff);
5462 	case PV_FT:	return (char_u *)&(curbuf->b_p_ft);
5463 	case PV_FO:	return (char_u *)&(curbuf->b_p_fo);
5464 	case PV_FLP:	return (char_u *)&(curbuf->b_p_flp);
5465 	case PV_IMI:	return (char_u *)&(curbuf->b_p_iminsert);
5466 	case PV_IMS:	return (char_u *)&(curbuf->b_p_imsearch);
5467 	case PV_INF:	return (char_u *)&(curbuf->b_p_inf);
5468 	case PV_ISK:	return (char_u *)&(curbuf->b_p_isk);
5469 #ifdef FEAT_FIND_ID
5470 # ifdef FEAT_EVAL
5471 	case PV_INEX:	return (char_u *)&(curbuf->b_p_inex);
5472 # endif
5473 #endif
5474 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
5475 	case PV_INDE:	return (char_u *)&(curbuf->b_p_inde);
5476 	case PV_INDK:	return (char_u *)&(curbuf->b_p_indk);
5477 #endif
5478 #ifdef FEAT_EVAL
5479 	case PV_FEX:	return (char_u *)&(curbuf->b_p_fex);
5480 #endif
5481 #ifdef FEAT_CRYPT
5482 	case PV_KEY:	return (char_u *)&(curbuf->b_p_key);
5483 #endif
5484 #ifdef FEAT_LISP
5485 	case PV_LISP:	return (char_u *)&(curbuf->b_p_lisp);
5486 #endif
5487 	case PV_ML:	return (char_u *)&(curbuf->b_p_ml);
5488 	case PV_MPS:	return (char_u *)&(curbuf->b_p_mps);
5489 	case PV_MA:	return (char_u *)&(curbuf->b_p_ma);
5490 	case PV_MOD:	return (char_u *)&(curbuf->b_changed);
5491 	case PV_NF:	return (char_u *)&(curbuf->b_p_nf);
5492 	case PV_PI:	return (char_u *)&(curbuf->b_p_pi);
5493 #ifdef FEAT_TEXTOBJ
5494 	case PV_QE:	return (char_u *)&(curbuf->b_p_qe);
5495 #endif
5496 	case PV_RO:	return (char_u *)&(curbuf->b_p_ro);
5497 #ifdef FEAT_SMARTINDENT
5498 	case PV_SI:	return (char_u *)&(curbuf->b_p_si);
5499 #endif
5500 	case PV_SN:	return (char_u *)&(curbuf->b_p_sn);
5501 	case PV_STS:	return (char_u *)&(curbuf->b_p_sts);
5502 #ifdef FEAT_SEARCHPATH
5503 	case PV_SUA:	return (char_u *)&(curbuf->b_p_sua);
5504 #endif
5505 	case PV_SWF:	return (char_u *)&(curbuf->b_p_swf);
5506 #ifdef FEAT_SYN_HL
5507 	case PV_SMC:	return (char_u *)&(curbuf->b_p_smc);
5508 	case PV_SYN:	return (char_u *)&(curbuf->b_p_syn);
5509 #endif
5510 #ifdef FEAT_SPELL
5511 	case PV_SPC:	return (char_u *)&(curwin->w_s->b_p_spc);
5512 	case PV_SPF:	return (char_u *)&(curwin->w_s->b_p_spf);
5513 	case PV_SPL:	return (char_u *)&(curwin->w_s->b_p_spl);
5514 	case PV_SPO:	return (char_u *)&(curwin->w_s->b_p_spo);
5515 #endif
5516 	case PV_SW:	return (char_u *)&(curbuf->b_p_sw);
5517 	case PV_TS:	return (char_u *)&(curbuf->b_p_ts);
5518 	case PV_TW:	return (char_u *)&(curbuf->b_p_tw);
5519 	case PV_TX:	return (char_u *)&(curbuf->b_p_tx);
5520 #ifdef FEAT_PERSISTENT_UNDO
5521 	case PV_UDF:	return (char_u *)&(curbuf->b_p_udf);
5522 #endif
5523 	case PV_WM:	return (char_u *)&(curbuf->b_p_wm);
5524 #ifdef FEAT_KEYMAP
5525 	case PV_KMAP:	return (char_u *)&(curbuf->b_p_keymap);
5526 #endif
5527 #ifdef FEAT_SIGNS
5528 	case PV_SCL:	return (char_u *)&(curwin->w_p_scl);
5529 #endif
5530 #ifdef FEAT_VARTABS
5531 	case PV_VSTS:	return (char_u *)&(curbuf->b_p_vsts);
5532 	case PV_VTS:	return (char_u *)&(curbuf->b_p_vts);
5533 #endif
5534 	default:	iemsg(_("E356: get_varp ERROR"));
5535     }
5536     // always return a valid pointer to avoid a crash!
5537     return (char_u *)&(curbuf->b_p_wm);
5538 }
5539 
5540 /*
5541  * Return a pointer to the variable for option at 'opt_idx'
5542  */
5543     char_u *
get_option_var(int opt_idx)5544 get_option_var(int opt_idx)
5545 {
5546     return options[opt_idx].var;
5547 }
5548 
5549 /*
5550  * Return the full name of the option at 'opt_idx'
5551  */
5552     char_u *
get_option_fullname(int opt_idx)5553 get_option_fullname(int opt_idx)
5554 {
5555     return (char_u *)options[opt_idx].fullname;
5556 }
5557 
5558 /*
5559  * Get the value of 'equalprg', either the buffer-local one or the global one.
5560  */
5561     char_u *
get_equalprg(void)5562 get_equalprg(void)
5563 {
5564     if (*curbuf->b_p_ep == NUL)
5565 	return p_ep;
5566     return curbuf->b_p_ep;
5567 }
5568 
5569 /*
5570  * Copy options from one window to another.
5571  * Used when splitting a window.
5572  */
5573     void
win_copy_options(win_T * wp_from,win_T * wp_to)5574 win_copy_options(win_T *wp_from, win_T *wp_to)
5575 {
5576     copy_winopt(&wp_from->w_onebuf_opt, &wp_to->w_onebuf_opt);
5577     copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
5578     after_copy_winopt(wp_to);
5579 }
5580 
5581 /*
5582  * After copying window options: update variables depending on options.
5583  */
5584     void
after_copy_winopt(win_T * wp UNUSED)5585 after_copy_winopt(win_T *wp UNUSED)
5586 {
5587 #ifdef FEAT_LINEBREAK
5588     briopt_check(wp);
5589 #endif
5590 #ifdef FEAT_SYN_HL
5591     fill_culopt_flags(NULL, wp);
5592     check_colorcolumn(wp);
5593 #endif
5594     set_chars_option(wp, &wp->w_p_lcs);
5595 }
5596 
5597 /*
5598  * Copy the options from one winopt_T to another.
5599  * Doesn't free the old option values in "to", use clear_winopt() for that.
5600  * The 'scroll' option is not copied, because it depends on the window height.
5601  * The 'previewwindow' option is reset, there can be only one preview window.
5602  */
5603     void
copy_winopt(winopt_T * from,winopt_T * to)5604 copy_winopt(winopt_T *from, winopt_T *to)
5605 {
5606 #ifdef FEAT_ARABIC
5607     to->wo_arab = from->wo_arab;
5608 #endif
5609     to->wo_list = from->wo_list;
5610     to->wo_lcs = vim_strsave(from->wo_lcs);
5611     to->wo_nu = from->wo_nu;
5612     to->wo_rnu = from->wo_rnu;
5613     to->wo_ve = vim_strsave(from->wo_ve);
5614     to->wo_ve_flags = from->wo_ve_flags;
5615 #ifdef FEAT_LINEBREAK
5616     to->wo_nuw = from->wo_nuw;
5617 #endif
5618 #ifdef FEAT_RIGHTLEFT
5619     to->wo_rl  = from->wo_rl;
5620     to->wo_rlc = vim_strsave(from->wo_rlc);
5621 #endif
5622 #ifdef FEAT_LINEBREAK
5623     to->wo_sbr = vim_strsave(from->wo_sbr);
5624 #endif
5625 #ifdef FEAT_STL_OPT
5626     to->wo_stl = vim_strsave(from->wo_stl);
5627 #endif
5628     to->wo_wrap = from->wo_wrap;
5629 #ifdef FEAT_DIFF
5630     to->wo_wrap_save = from->wo_wrap_save;
5631 #endif
5632 #ifdef FEAT_LINEBREAK
5633     to->wo_lbr = from->wo_lbr;
5634     to->wo_bri = from->wo_bri;
5635     to->wo_briopt = vim_strsave(from->wo_briopt);
5636 #endif
5637     to->wo_wcr = vim_strsave(from->wo_wcr);
5638     to->wo_scb = from->wo_scb;
5639     to->wo_scb_save = from->wo_scb_save;
5640     to->wo_crb = from->wo_crb;
5641     to->wo_crb_save = from->wo_crb_save;
5642 #ifdef FEAT_SPELL
5643     to->wo_spell = from->wo_spell;
5644 #endif
5645 #ifdef FEAT_SYN_HL
5646     to->wo_cuc = from->wo_cuc;
5647     to->wo_cul = from->wo_cul;
5648     to->wo_culopt = vim_strsave(from->wo_culopt);
5649     to->wo_cc = vim_strsave(from->wo_cc);
5650 #endif
5651 #ifdef FEAT_DIFF
5652     to->wo_diff = from->wo_diff;
5653     to->wo_diff_saved = from->wo_diff_saved;
5654 #endif
5655 #ifdef FEAT_CONCEAL
5656     to->wo_cocu = vim_strsave(from->wo_cocu);
5657     to->wo_cole = from->wo_cole;
5658 #endif
5659 #ifdef FEAT_TERMINAL
5660     to->wo_twk = vim_strsave(from->wo_twk);
5661     to->wo_tws = vim_strsave(from->wo_tws);
5662 #endif
5663 #ifdef FEAT_FOLDING
5664     to->wo_fdc = from->wo_fdc;
5665     to->wo_fdc_save = from->wo_fdc_save;
5666     to->wo_fen = from->wo_fen;
5667     to->wo_fen_save = from->wo_fen_save;
5668     to->wo_fdi = vim_strsave(from->wo_fdi);
5669     to->wo_fml = from->wo_fml;
5670     to->wo_fdl = from->wo_fdl;
5671     to->wo_fdl_save = from->wo_fdl_save;
5672     to->wo_fdm = vim_strsave(from->wo_fdm);
5673     to->wo_fdm_save = from->wo_diff_saved
5674 			      ? vim_strsave(from->wo_fdm_save) : empty_option;
5675     to->wo_fdn = from->wo_fdn;
5676 # ifdef FEAT_EVAL
5677     to->wo_fde = vim_strsave(from->wo_fde);
5678     to->wo_fdt = vim_strsave(from->wo_fdt);
5679 # endif
5680     to->wo_fmr = vim_strsave(from->wo_fmr);
5681 #endif
5682 #ifdef FEAT_SIGNS
5683     to->wo_scl = vim_strsave(from->wo_scl);
5684 #endif
5685 
5686 #ifdef FEAT_EVAL
5687     // Copy the script context so that we know where the value was last set.
5688     mch_memmove(to->wo_script_ctx, from->wo_script_ctx,
5689 						    sizeof(to->wo_script_ctx));
5690 #endif
5691     check_winopt(to);		// don't want NULL pointers
5692 }
5693 
5694 /*
5695  * Check string options in a window for a NULL value.
5696  */
5697     static void
check_win_options(win_T * win)5698 check_win_options(win_T *win)
5699 {
5700     check_winopt(&win->w_onebuf_opt);
5701     check_winopt(&win->w_allbuf_opt);
5702 }
5703 
5704 /*
5705  * Check for NULL pointers in a winopt_T and replace them with empty_option.
5706  */
5707     static void
check_winopt(winopt_T * wop UNUSED)5708 check_winopt(winopt_T *wop UNUSED)
5709 {
5710 #ifdef FEAT_FOLDING
5711     check_string_option(&wop->wo_fdi);
5712     check_string_option(&wop->wo_fdm);
5713     check_string_option(&wop->wo_fdm_save);
5714 # ifdef FEAT_EVAL
5715     check_string_option(&wop->wo_fde);
5716     check_string_option(&wop->wo_fdt);
5717 # endif
5718     check_string_option(&wop->wo_fmr);
5719 #endif
5720 #ifdef FEAT_SIGNS
5721     check_string_option(&wop->wo_scl);
5722 #endif
5723 #ifdef FEAT_RIGHTLEFT
5724     check_string_option(&wop->wo_rlc);
5725 #endif
5726 #ifdef FEAT_LINEBREAK
5727     check_string_option(&wop->wo_sbr);
5728 #endif
5729 #ifdef FEAT_STL_OPT
5730     check_string_option(&wop->wo_stl);
5731 #endif
5732 #ifdef FEAT_SYN_HL
5733     check_string_option(&wop->wo_culopt);
5734     check_string_option(&wop->wo_cc);
5735 #endif
5736 #ifdef FEAT_CONCEAL
5737     check_string_option(&wop->wo_cocu);
5738 #endif
5739 #ifdef FEAT_TERMINAL
5740     check_string_option(&wop->wo_twk);
5741     check_string_option(&wop->wo_tws);
5742 #endif
5743 #ifdef FEAT_LINEBREAK
5744     check_string_option(&wop->wo_briopt);
5745 #endif
5746     check_string_option(&wop->wo_wcr);
5747     check_string_option(&wop->wo_lcs);
5748     check_string_option(&wop->wo_ve);
5749 }
5750 
5751 /*
5752  * Free the allocated memory inside a winopt_T.
5753  */
5754     void
clear_winopt(winopt_T * wop UNUSED)5755 clear_winopt(winopt_T *wop UNUSED)
5756 {
5757 #ifdef FEAT_FOLDING
5758     clear_string_option(&wop->wo_fdi);
5759     clear_string_option(&wop->wo_fdm);
5760     clear_string_option(&wop->wo_fdm_save);
5761 # ifdef FEAT_EVAL
5762     clear_string_option(&wop->wo_fde);
5763     clear_string_option(&wop->wo_fdt);
5764 # endif
5765     clear_string_option(&wop->wo_fmr);
5766 #endif
5767 #ifdef FEAT_SIGNS
5768     clear_string_option(&wop->wo_scl);
5769 #endif
5770 #ifdef FEAT_LINEBREAK
5771     clear_string_option(&wop->wo_briopt);
5772 #endif
5773     clear_string_option(&wop->wo_wcr);
5774 #ifdef FEAT_RIGHTLEFT
5775     clear_string_option(&wop->wo_rlc);
5776 #endif
5777 #ifdef FEAT_LINEBREAK
5778     clear_string_option(&wop->wo_sbr);
5779 #endif
5780 #ifdef FEAT_STL_OPT
5781     clear_string_option(&wop->wo_stl);
5782 #endif
5783 #ifdef FEAT_SYN_HL
5784     clear_string_option(&wop->wo_culopt);
5785     clear_string_option(&wop->wo_cc);
5786 #endif
5787 #ifdef FEAT_CONCEAL
5788     clear_string_option(&wop->wo_cocu);
5789 #endif
5790 #ifdef FEAT_TERMINAL
5791     clear_string_option(&wop->wo_twk);
5792     clear_string_option(&wop->wo_tws);
5793 #endif
5794     clear_string_option(&wop->wo_lcs);
5795     clear_string_option(&wop->wo_ve);
5796 }
5797 
5798 #ifdef FEAT_EVAL
5799 // Index into the options table for a buffer-local option enum.
5800 static int buf_opt_idx[BV_COUNT];
5801 # define COPY_OPT_SCTX(buf, bv) buf->b_p_script_ctx[bv] = options[buf_opt_idx[bv]].script_ctx
5802 
5803 /*
5804  * Initialize buf_opt_idx[] if not done already.
5805  */
5806     static void
init_buf_opt_idx(void)5807 init_buf_opt_idx(void)
5808 {
5809     static int did_init_buf_opt_idx = FALSE;
5810     int i;
5811 
5812     if (did_init_buf_opt_idx)
5813 	return;
5814     did_init_buf_opt_idx = TRUE;
5815     for (i = 0; !istermoption_idx(i); i++)
5816 	if (options[i].indir & PV_BUF)
5817 	    buf_opt_idx[options[i].indir & PV_MASK] = i;
5818 }
5819 #else
5820 # define COPY_OPT_SCTX(buf, bv)
5821 #endif
5822 
5823 /*
5824  * Copy global option values to local options for one buffer.
5825  * Used when creating a new buffer and sometimes when entering a buffer.
5826  * flags:
5827  * BCO_ENTER	We will enter the buffer "buf".
5828  * BCO_ALWAYS	Always copy the options, but only set b_p_initialized when
5829  *		appropriate.
5830  * BCO_NOHELP	Don't copy the values to a help buffer.
5831  */
5832     void
buf_copy_options(buf_T * buf,int flags)5833 buf_copy_options(buf_T *buf, int flags)
5834 {
5835     int		should_copy = TRUE;
5836     char_u	*save_p_isk = NULL;	    // init for GCC
5837     int		dont_do_help;
5838     int		did_isk = FALSE;
5839 
5840     /*
5841      * Skip this when the option defaults have not been set yet.  Happens when
5842      * main() allocates the first buffer.
5843      */
5844     if (p_cpo != NULL)
5845     {
5846 	/*
5847 	 * Always copy when entering and 'cpo' contains 'S'.
5848 	 * Don't copy when already initialized.
5849 	 * Don't copy when 'cpo' contains 's' and not entering.
5850 	 * 'S'	BCO_ENTER  initialized	's'  should_copy
5851 	 * yes	  yes	       X	 X	TRUE
5852 	 * yes	  no	      yes	 X	FALSE
5853 	 * no	   X	      yes	 X	FALSE
5854 	 *  X	  no	      no	yes	FALSE
5855 	 *  X	  no	      no	no	TRUE
5856 	 * no	  yes	      no	 X	TRUE
5857 	 */
5858 	if ((vim_strchr(p_cpo, CPO_BUFOPTGLOB) == NULL || !(flags & BCO_ENTER))
5859 		&& (buf->b_p_initialized
5860 		    || (!(flags & BCO_ENTER)
5861 			&& vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
5862 	    should_copy = FALSE;
5863 
5864 	if (should_copy || (flags & BCO_ALWAYS))
5865 	{
5866 #ifdef FEAT_EVAL
5867 	    CLEAR_FIELD(buf->b_p_script_ctx);
5868 	    init_buf_opt_idx();
5869 #endif
5870 	    // Don't copy the options specific to a help buffer when
5871 	    // BCO_NOHELP is given or the options were initialized already
5872 	    // (jumping back to a help file with CTRL-T or CTRL-O)
5873 	    dont_do_help = ((flags & BCO_NOHELP) && buf->b_help)
5874 						       || buf->b_p_initialized;
5875 	    if (dont_do_help)		// don't free b_p_isk
5876 	    {
5877 		save_p_isk = buf->b_p_isk;
5878 		buf->b_p_isk = NULL;
5879 	    }
5880 	    /*
5881 	     * Always free the allocated strings.  If not already initialized,
5882 	     * reset 'readonly' and copy 'fileformat'.
5883 	     */
5884 	    if (!buf->b_p_initialized)
5885 	    {
5886 		free_buf_options(buf, TRUE);
5887 		buf->b_p_ro = FALSE;		// don't copy readonly
5888 		buf->b_p_tx = p_tx;
5889 		buf->b_p_fenc = vim_strsave(p_fenc);
5890 		switch (*p_ffs)
5891 		{
5892 		    case 'm':
5893 			buf->b_p_ff = vim_strsave((char_u *)FF_MAC); break;
5894 		    case 'd':
5895 			buf->b_p_ff = vim_strsave((char_u *)FF_DOS); break;
5896 		    case 'u':
5897 			buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); break;
5898 		    default:
5899 			buf->b_p_ff = vim_strsave(p_ff);
5900 		}
5901 		if (buf->b_p_ff != NULL)
5902 		    buf->b_start_ffc = *buf->b_p_ff;
5903 		buf->b_p_bh = empty_option;
5904 		buf->b_p_bt = empty_option;
5905 	    }
5906 	    else
5907 		free_buf_options(buf, FALSE);
5908 
5909 	    buf->b_p_ai = p_ai;
5910 	    COPY_OPT_SCTX(buf, BV_AI);
5911 	    buf->b_p_ai_nopaste = p_ai_nopaste;
5912 	    buf->b_p_sw = p_sw;
5913 	    COPY_OPT_SCTX(buf, BV_SW);
5914 	    buf->b_p_tw = p_tw;
5915 	    COPY_OPT_SCTX(buf, BV_TW);
5916 	    buf->b_p_tw_nopaste = p_tw_nopaste;
5917 	    buf->b_p_tw_nobin = p_tw_nobin;
5918 	    buf->b_p_wm = p_wm;
5919 	    COPY_OPT_SCTX(buf, BV_WM);
5920 	    buf->b_p_wm_nopaste = p_wm_nopaste;
5921 	    buf->b_p_wm_nobin = p_wm_nobin;
5922 	    buf->b_p_bin = p_bin;
5923 	    COPY_OPT_SCTX(buf, BV_BIN);
5924 	    buf->b_p_bomb = p_bomb;
5925 	    COPY_OPT_SCTX(buf, BV_BOMB);
5926 	    buf->b_p_fixeol = p_fixeol;
5927 	    COPY_OPT_SCTX(buf, BV_FIXEOL);
5928 	    buf->b_p_et = p_et;
5929 	    COPY_OPT_SCTX(buf, BV_ET);
5930 	    buf->b_p_et_nobin = p_et_nobin;
5931 	    buf->b_p_et_nopaste = p_et_nopaste;
5932 	    buf->b_p_ml = p_ml;
5933 	    COPY_OPT_SCTX(buf, BV_ML);
5934 	    buf->b_p_ml_nobin = p_ml_nobin;
5935 	    buf->b_p_inf = p_inf;
5936 	    COPY_OPT_SCTX(buf, BV_INF);
5937 	    if (cmdmod.cmod_flags & CMOD_NOSWAPFILE)
5938 		buf->b_p_swf = FALSE;
5939 	    else
5940 	    {
5941 		buf->b_p_swf = p_swf;
5942 		COPY_OPT_SCTX(buf, BV_INF);
5943 	    }
5944 	    buf->b_p_cpt = vim_strsave(p_cpt);
5945 	    COPY_OPT_SCTX(buf, BV_CPT);
5946 #ifdef BACKSLASH_IN_FILENAME
5947 	    buf->b_p_csl = vim_strsave(p_csl);
5948 	    COPY_OPT_SCTX(buf, BV_CSL);
5949 #endif
5950 #ifdef FEAT_COMPL_FUNC
5951 	    buf->b_p_cfu = vim_strsave(p_cfu);
5952 	    COPY_OPT_SCTX(buf, BV_CFU);
5953 	    buf->b_p_ofu = vim_strsave(p_ofu);
5954 	    COPY_OPT_SCTX(buf, BV_OFU);
5955 #endif
5956 #ifdef FEAT_EVAL
5957 	    buf->b_p_tfu = vim_strsave(p_tfu);
5958 	    COPY_OPT_SCTX(buf, BV_TFU);
5959 #endif
5960 	    buf->b_p_sts = p_sts;
5961 	    COPY_OPT_SCTX(buf, BV_STS);
5962 	    buf->b_p_sts_nopaste = p_sts_nopaste;
5963 #ifdef FEAT_VARTABS
5964 	    buf->b_p_vsts = vim_strsave(p_vsts);
5965 	    COPY_OPT_SCTX(buf, BV_VSTS);
5966 	    if (p_vsts && p_vsts != empty_option)
5967 		(void)tabstop_set(p_vsts, &buf->b_p_vsts_array);
5968 	    else
5969 		buf->b_p_vsts_array = 0;
5970 	    buf->b_p_vsts_nopaste = p_vsts_nopaste
5971 				 ? vim_strsave(p_vsts_nopaste) : NULL;
5972 #endif
5973 	    buf->b_p_sn = p_sn;
5974 	    COPY_OPT_SCTX(buf, BV_SN);
5975 	    buf->b_p_com = vim_strsave(p_com);
5976 	    COPY_OPT_SCTX(buf, BV_COM);
5977 #ifdef FEAT_FOLDING
5978 	    buf->b_p_cms = vim_strsave(p_cms);
5979 	    COPY_OPT_SCTX(buf, BV_CMS);
5980 #endif
5981 	    buf->b_p_fo = vim_strsave(p_fo);
5982 	    COPY_OPT_SCTX(buf, BV_FO);
5983 	    buf->b_p_flp = vim_strsave(p_flp);
5984 	    COPY_OPT_SCTX(buf, BV_FLP);
5985 	    // NOTE: Valgrind may report a bogus memory leak for 'nrformats'
5986 	    // when it is set to 8 bytes in defaults.vim.
5987 	    buf->b_p_nf = vim_strsave(p_nf);
5988 	    COPY_OPT_SCTX(buf, BV_NF);
5989 	    buf->b_p_mps = vim_strsave(p_mps);
5990 	    COPY_OPT_SCTX(buf, BV_MPS);
5991 #ifdef FEAT_SMARTINDENT
5992 	    buf->b_p_si = p_si;
5993 	    COPY_OPT_SCTX(buf, BV_SI);
5994 #endif
5995 	    buf->b_p_ci = p_ci;
5996 	    COPY_OPT_SCTX(buf, BV_CI);
5997 #ifdef FEAT_CINDENT
5998 	    buf->b_p_cin = p_cin;
5999 	    COPY_OPT_SCTX(buf, BV_CIN);
6000 	    buf->b_p_cink = vim_strsave(p_cink);
6001 	    COPY_OPT_SCTX(buf, BV_CINK);
6002 	    buf->b_p_cino = vim_strsave(p_cino);
6003 	    COPY_OPT_SCTX(buf, BV_CINO);
6004 #endif
6005 	    // Don't copy 'filetype', it must be detected
6006 	    buf->b_p_ft = empty_option;
6007 	    buf->b_p_pi = p_pi;
6008 	    COPY_OPT_SCTX(buf, BV_PI);
6009 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
6010 	    buf->b_p_cinw = vim_strsave(p_cinw);
6011 	    COPY_OPT_SCTX(buf, BV_CINW);
6012 #endif
6013 #ifdef FEAT_LISP
6014 	    buf->b_p_lisp = p_lisp;
6015 	    COPY_OPT_SCTX(buf, BV_LISP);
6016 #endif
6017 #ifdef FEAT_SYN_HL
6018 	    // Don't copy 'syntax', it must be set
6019 	    buf->b_p_syn = empty_option;
6020 	    buf->b_p_smc = p_smc;
6021 	    COPY_OPT_SCTX(buf, BV_SMC);
6022 	    buf->b_s.b_syn_isk = empty_option;
6023 #endif
6024 #ifdef FEAT_SPELL
6025 	    buf->b_s.b_p_spc = vim_strsave(p_spc);
6026 	    COPY_OPT_SCTX(buf, BV_SPC);
6027 	    (void)compile_cap_prog(&buf->b_s);
6028 	    buf->b_s.b_p_spf = vim_strsave(p_spf);
6029 	    COPY_OPT_SCTX(buf, BV_SPF);
6030 	    buf->b_s.b_p_spl = vim_strsave(p_spl);
6031 	    COPY_OPT_SCTX(buf, BV_SPL);
6032 	    buf->b_s.b_p_spo = vim_strsave(p_spo);
6033 	    COPY_OPT_SCTX(buf, BV_SPO);
6034 #endif
6035 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
6036 	    buf->b_p_inde = vim_strsave(p_inde);
6037 	    COPY_OPT_SCTX(buf, BV_INDE);
6038 	    buf->b_p_indk = vim_strsave(p_indk);
6039 	    COPY_OPT_SCTX(buf, BV_INDK);
6040 #endif
6041 	    buf->b_p_fp = empty_option;
6042 #if defined(FEAT_EVAL)
6043 	    buf->b_p_fex = vim_strsave(p_fex);
6044 	    COPY_OPT_SCTX(buf, BV_FEX);
6045 #endif
6046 #ifdef FEAT_CRYPT
6047 	    buf->b_p_key = vim_strsave(p_key);
6048 	    COPY_OPT_SCTX(buf, BV_KEY);
6049 #endif
6050 #ifdef FEAT_SEARCHPATH
6051 	    buf->b_p_sua = vim_strsave(p_sua);
6052 	    COPY_OPT_SCTX(buf, BV_SUA);
6053 #endif
6054 #ifdef FEAT_KEYMAP
6055 	    buf->b_p_keymap = vim_strsave(p_keymap);
6056 	    COPY_OPT_SCTX(buf, BV_KMAP);
6057 	    buf->b_kmap_state |= KEYMAP_INIT;
6058 #endif
6059 #ifdef FEAT_TERMINAL
6060 	    buf->b_p_twsl = p_twsl;
6061 	    COPY_OPT_SCTX(buf, BV_TWSL);
6062 #endif
6063 	    // This isn't really an option, but copying the langmap and IME
6064 	    // state from the current buffer is better than resetting it.
6065 	    buf->b_p_iminsert = p_iminsert;
6066 	    COPY_OPT_SCTX(buf, BV_IMI);
6067 	    buf->b_p_imsearch = p_imsearch;
6068 	    COPY_OPT_SCTX(buf, BV_IMS);
6069 
6070 	    // options that are normally global but also have a local value
6071 	    // are not copied, start using the global value
6072 	    buf->b_p_ar = -1;
6073 	    buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
6074 	    buf->b_p_bkc = empty_option;
6075 	    buf->b_bkc_flags = 0;
6076 #ifdef FEAT_QUICKFIX
6077 	    buf->b_p_gp = empty_option;
6078 	    buf->b_p_mp = empty_option;
6079 	    buf->b_p_efm = empty_option;
6080 #endif
6081 	    buf->b_p_ep = empty_option;
6082 	    buf->b_p_kp = empty_option;
6083 	    buf->b_p_path = empty_option;
6084 	    buf->b_p_tags = empty_option;
6085 	    buf->b_p_tc = empty_option;
6086 	    buf->b_tc_flags = 0;
6087 #ifdef FEAT_FIND_ID
6088 	    buf->b_p_def = empty_option;
6089 	    buf->b_p_inc = empty_option;
6090 # ifdef FEAT_EVAL
6091 	    buf->b_p_inex = vim_strsave(p_inex);
6092 	    COPY_OPT_SCTX(buf, BV_INEX);
6093 # endif
6094 #endif
6095 	    buf->b_p_dict = empty_option;
6096 	    buf->b_p_tsr = empty_option;
6097 #ifdef FEAT_COMPL_FUNC
6098 	    buf->b_p_tsrfu = empty_option;
6099 #endif
6100 #ifdef FEAT_TEXTOBJ
6101 	    buf->b_p_qe = vim_strsave(p_qe);
6102 	    COPY_OPT_SCTX(buf, BV_QE);
6103 #endif
6104 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
6105 	    buf->b_p_bexpr = empty_option;
6106 #endif
6107 #if defined(FEAT_CRYPT)
6108 	    buf->b_p_cm = empty_option;
6109 #endif
6110 #ifdef FEAT_PERSISTENT_UNDO
6111 	    buf->b_p_udf = p_udf;
6112 	    COPY_OPT_SCTX(buf, BV_UDF);
6113 #endif
6114 #ifdef FEAT_LISP
6115 	    buf->b_p_lw = empty_option;
6116 #endif
6117 	    buf->b_p_menc = empty_option;
6118 
6119 	    /*
6120 	     * Don't copy the options set by ex_help(), use the saved values,
6121 	     * when going from a help buffer to a non-help buffer.
6122 	     * Don't touch these at all when BCO_NOHELP is used and going from
6123 	     * or to a help buffer.
6124 	     */
6125 	    if (dont_do_help)
6126 	    {
6127 		buf->b_p_isk = save_p_isk;
6128 #ifdef FEAT_VARTABS
6129 		if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
6130 		    (void)tabstop_set(p_vts, &buf->b_p_vts_array);
6131 		else
6132 		    buf->b_p_vts_array = NULL;
6133 #endif
6134 	    }
6135 	    else
6136 	    {
6137 		buf->b_p_isk = vim_strsave(p_isk);
6138 		COPY_OPT_SCTX(buf, BV_ISK);
6139 		did_isk = TRUE;
6140 		buf->b_p_ts = p_ts;
6141 #ifdef FEAT_VARTABS
6142 		buf->b_p_vts = vim_strsave(p_vts);
6143 		COPY_OPT_SCTX(buf, BV_VTS);
6144 		if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
6145 		    (void)tabstop_set(p_vts, &buf->b_p_vts_array);
6146 		else
6147 		    buf->b_p_vts_array = NULL;
6148 #endif
6149 		buf->b_help = FALSE;
6150 		if (buf->b_p_bt[0] == 'h')
6151 		    clear_string_option(&buf->b_p_bt);
6152 		buf->b_p_ma = p_ma;
6153 		COPY_OPT_SCTX(buf, BV_MA);
6154 	    }
6155 	}
6156 
6157 	/*
6158 	 * When the options should be copied (ignoring BCO_ALWAYS), set the
6159 	 * flag that indicates that the options have been initialized.
6160 	 */
6161 	if (should_copy)
6162 	    buf->b_p_initialized = TRUE;
6163     }
6164 
6165     check_buf_options(buf);	    // make sure we don't have NULLs
6166     if (did_isk)
6167 	(void)buf_init_chartab(buf, FALSE);
6168 }
6169 
6170 /*
6171  * Reset the 'modifiable' option and its default value.
6172  */
6173     void
reset_modifiable(void)6174 reset_modifiable(void)
6175 {
6176     int		opt_idx;
6177 
6178     curbuf->b_p_ma = FALSE;
6179     p_ma = FALSE;
6180     opt_idx = findoption((char_u *)"ma");
6181     if (opt_idx >= 0)
6182 	options[opt_idx].def_val[VI_DEFAULT] = FALSE;
6183 }
6184 
6185 /*
6186  * Set the global value for 'iminsert' to the local value.
6187  */
6188     void
set_iminsert_global(void)6189 set_iminsert_global(void)
6190 {
6191     p_iminsert = curbuf->b_p_iminsert;
6192 }
6193 
6194 /*
6195  * Set the global value for 'imsearch' to the local value.
6196  */
6197     void
set_imsearch_global(void)6198 set_imsearch_global(void)
6199 {
6200     p_imsearch = curbuf->b_p_imsearch;
6201 }
6202 
6203 static int expand_option_idx = -1;
6204 static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL};
6205 static int expand_option_flags = 0;
6206 
6207     void
set_context_in_set_cmd(expand_T * xp,char_u * arg,int opt_flags)6208 set_context_in_set_cmd(
6209     expand_T	*xp,
6210     char_u	*arg,
6211     int		opt_flags)	// OPT_GLOBAL and/or OPT_LOCAL
6212 {
6213     int		nextchar;
6214     long_u	flags = 0;	// init for GCC
6215     int		opt_idx = 0;	// init for GCC
6216     char_u	*p;
6217     char_u	*s;
6218     int		is_term_option = FALSE;
6219     int		key;
6220 
6221     expand_option_flags = opt_flags;
6222 
6223     xp->xp_context = EXPAND_SETTINGS;
6224     if (*arg == NUL)
6225     {
6226 	xp->xp_pattern = arg;
6227 	return;
6228     }
6229     p = arg + STRLEN(arg) - 1;
6230     if (*p == ' ' && *(p - 1) != '\\')
6231     {
6232 	xp->xp_pattern = p + 1;
6233 	return;
6234     }
6235     while (p > arg)
6236     {
6237 	s = p;
6238 	// count number of backslashes before ' ' or ','
6239 	if (*p == ' ' || *p == ',')
6240 	{
6241 	    while (s > arg && *(s - 1) == '\\')
6242 		--s;
6243 	}
6244 	// break at a space with an even number of backslashes
6245 	if (*p == ' ' && ((p - s) & 1) == 0)
6246 	{
6247 	    ++p;
6248 	    break;
6249 	}
6250 	--p;
6251     }
6252     if (STRNCMP(p, "no", 2) == 0 && STRNCMP(p, "novice", 6) != 0)
6253     {
6254 	xp->xp_context = EXPAND_BOOL_SETTINGS;
6255 	p += 2;
6256     }
6257     if (STRNCMP(p, "inv", 3) == 0)
6258     {
6259 	xp->xp_context = EXPAND_BOOL_SETTINGS;
6260 	p += 3;
6261     }
6262     xp->xp_pattern = arg = p;
6263     if (*arg == '<')
6264     {
6265 	while (*p != '>')
6266 	    if (*p++ == NUL)	    // expand terminal option name
6267 		return;
6268 	key = get_special_key_code(arg + 1);
6269 	if (key == 0)		    // unknown name
6270 	{
6271 	    xp->xp_context = EXPAND_NOTHING;
6272 	    return;
6273 	}
6274 	nextchar = *++p;
6275 	is_term_option = TRUE;
6276 	expand_option_name[2] = KEY2TERMCAP0(key);
6277 	expand_option_name[3] = KEY2TERMCAP1(key);
6278     }
6279     else
6280     {
6281 	if (p[0] == 't' && p[1] == '_')
6282 	{
6283 	    p += 2;
6284 	    if (*p != NUL)
6285 		++p;
6286 	    if (*p == NUL)
6287 		return;		// expand option name
6288 	    nextchar = *++p;
6289 	    is_term_option = TRUE;
6290 	    expand_option_name[2] = p[-2];
6291 	    expand_option_name[3] = p[-1];
6292 	}
6293 	else
6294 	{
6295 	    // Allow * wildcard
6296 	    while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
6297 		p++;
6298 	    if (*p == NUL)
6299 		return;
6300 	    nextchar = *p;
6301 	    *p = NUL;
6302 	    opt_idx = findoption(arg);
6303 	    *p = nextchar;
6304 	    if (opt_idx == -1 || options[opt_idx].var == NULL)
6305 	    {
6306 		xp->xp_context = EXPAND_NOTHING;
6307 		return;
6308 	    }
6309 	    flags = options[opt_idx].flags;
6310 	    if (flags & P_BOOL)
6311 	    {
6312 		xp->xp_context = EXPAND_NOTHING;
6313 		return;
6314 	    }
6315 	}
6316     }
6317     // handle "-=" and "+="
6318     if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=')
6319     {
6320 	++p;
6321 	nextchar = '=';
6322     }
6323     if ((nextchar != '=' && nextchar != ':')
6324 				    || xp->xp_context == EXPAND_BOOL_SETTINGS)
6325     {
6326 	xp->xp_context = EXPAND_UNSUCCESSFUL;
6327 	return;
6328     }
6329     if (xp->xp_context != EXPAND_BOOL_SETTINGS && p[1] == NUL)
6330     {
6331 	xp->xp_context = EXPAND_OLD_SETTING;
6332 	if (is_term_option)
6333 	    expand_option_idx = -1;
6334 	else
6335 	    expand_option_idx = opt_idx;
6336 	xp->xp_pattern = p + 1;
6337 	return;
6338     }
6339     xp->xp_context = EXPAND_NOTHING;
6340     if (is_term_option || (flags & P_NUM))
6341 	return;
6342 
6343     xp->xp_pattern = p + 1;
6344 
6345     if (flags & P_EXPAND)
6346     {
6347 	p = options[opt_idx].var;
6348 	if (p == (char_u *)&p_bdir
6349 		|| p == (char_u *)&p_dir
6350 		|| p == (char_u *)&p_path
6351 		|| p == (char_u *)&p_pp
6352 		|| p == (char_u *)&p_rtp
6353 #ifdef FEAT_SEARCHPATH
6354 		|| p == (char_u *)&p_cdpath
6355 #endif
6356 #ifdef FEAT_SESSION
6357 		|| p == (char_u *)&p_vdir
6358 #endif
6359 		)
6360 	{
6361 	    xp->xp_context = EXPAND_DIRECTORIES;
6362 	    if (p == (char_u *)&p_path
6363 #ifdef FEAT_SEARCHPATH
6364 		    || p == (char_u *)&p_cdpath
6365 #endif
6366 		   )
6367 		xp->xp_backslash = XP_BS_THREE;
6368 	    else
6369 		xp->xp_backslash = XP_BS_ONE;
6370 	}
6371 	else if (p == (char_u *)&p_ft)
6372 	{
6373 	    xp->xp_context = EXPAND_FILETYPE;
6374 	}
6375 	else
6376 	{
6377 	    xp->xp_context = EXPAND_FILES;
6378 	    // for 'tags' need three backslashes for a space
6379 	    if (p == (char_u *)&p_tags)
6380 		xp->xp_backslash = XP_BS_THREE;
6381 	    else
6382 		xp->xp_backslash = XP_BS_ONE;
6383 	}
6384     }
6385 
6386     // For an option that is a list of file names, find the start of the
6387     // last file name.
6388     for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; --p)
6389     {
6390 	// count number of backslashes before ' ' or ','
6391 	if (*p == ' ' || *p == ',')
6392 	{
6393 	    s = p;
6394 	    while (s > xp->xp_pattern && *(s - 1) == '\\')
6395 		--s;
6396 	    if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3))
6397 		    || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0))
6398 	    {
6399 		xp->xp_pattern = p + 1;
6400 		break;
6401 	    }
6402 	}
6403 
6404 #ifdef FEAT_SPELL
6405 	// for 'spellsuggest' start at "file:"
6406 	if (options[opt_idx].var == (char_u *)&p_sps
6407 					       && STRNCMP(p, "file:", 5) == 0)
6408 	{
6409 	    xp->xp_pattern = p + 5;
6410 	    break;
6411 	}
6412 #endif
6413     }
6414 }
6415 
6416     int
ExpandSettings(expand_T * xp,regmatch_T * regmatch,int * num_file,char_u *** file)6417 ExpandSettings(
6418     expand_T	*xp,
6419     regmatch_T	*regmatch,
6420     int		*num_file,
6421     char_u	***file)
6422 {
6423     int		num_normal = 0;	    // Nr of matching non-term-code settings
6424     int		num_term = 0;	    // Nr of matching terminal code settings
6425     int		opt_idx;
6426     int		match;
6427     int		count = 0;
6428     char_u	*str;
6429     int		loop;
6430     int		is_term_opt;
6431     char_u	name_buf[MAX_KEY_NAME_LEN];
6432     static char *(names[]) = {"all", "termcap"};
6433     int		ic = regmatch->rm_ic;	// remember the ignore-case flag
6434 
6435     // do this loop twice:
6436     // loop == 0: count the number of matching options
6437     // loop == 1: copy the matching options into allocated memory
6438     for (loop = 0; loop <= 1; ++loop)
6439     {
6440 	regmatch->rm_ic = ic;
6441 	if (xp->xp_context != EXPAND_BOOL_SETTINGS)
6442 	{
6443 	    for (match = 0; match < (int)ARRAY_LENGTH(names); ++match)
6444 		if (vim_regexec(regmatch, (char_u *)names[match], (colnr_T)0))
6445 		{
6446 		    if (loop == 0)
6447 			num_normal++;
6448 		    else
6449 			(*file)[count++] = vim_strsave((char_u *)names[match]);
6450 		}
6451 	}
6452 	for (opt_idx = 0; (str = (char_u *)options[opt_idx].fullname) != NULL;
6453 								    opt_idx++)
6454 	{
6455 	    if (options[opt_idx].var == NULL)
6456 		continue;
6457 	    if (xp->xp_context == EXPAND_BOOL_SETTINGS
6458 	      && !(options[opt_idx].flags & P_BOOL))
6459 		continue;
6460 	    is_term_opt = istermoption_idx(opt_idx);
6461 	    if (is_term_opt && num_normal > 0)
6462 		continue;
6463 	    match = FALSE;
6464 	    if (vim_regexec(regmatch, str, (colnr_T)0)
6465 		    || (options[opt_idx].shortname != NULL
6466 			&& vim_regexec(regmatch,
6467 			   (char_u *)options[opt_idx].shortname, (colnr_T)0)))
6468 		match = TRUE;
6469 	    else if (is_term_opt)
6470 	    {
6471 		name_buf[0] = '<';
6472 		name_buf[1] = 't';
6473 		name_buf[2] = '_';
6474 		name_buf[3] = str[2];
6475 		name_buf[4] = str[3];
6476 		name_buf[5] = '>';
6477 		name_buf[6] = NUL;
6478 		if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6479 		{
6480 		    match = TRUE;
6481 		    str = name_buf;
6482 		}
6483 	    }
6484 	    if (match)
6485 	    {
6486 		if (loop == 0)
6487 		{
6488 		    if (is_term_opt)
6489 			num_term++;
6490 		    else
6491 			num_normal++;
6492 		}
6493 		else
6494 		    (*file)[count++] = vim_strsave(str);
6495 	    }
6496 	}
6497 	/*
6498 	 * Check terminal key codes, these are not in the option table
6499 	 */
6500 	if (xp->xp_context != EXPAND_BOOL_SETTINGS  && num_normal == 0)
6501 	{
6502 	    for (opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++)
6503 	    {
6504 		if (!isprint(str[0]) || !isprint(str[1]))
6505 		    continue;
6506 
6507 		name_buf[0] = 't';
6508 		name_buf[1] = '_';
6509 		name_buf[2] = str[0];
6510 		name_buf[3] = str[1];
6511 		name_buf[4] = NUL;
6512 
6513 		match = FALSE;
6514 		if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6515 		    match = TRUE;
6516 		else
6517 		{
6518 		    name_buf[0] = '<';
6519 		    name_buf[1] = 't';
6520 		    name_buf[2] = '_';
6521 		    name_buf[3] = str[0];
6522 		    name_buf[4] = str[1];
6523 		    name_buf[5] = '>';
6524 		    name_buf[6] = NUL;
6525 
6526 		    if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6527 			match = TRUE;
6528 		}
6529 		if (match)
6530 		{
6531 		    if (loop == 0)
6532 			num_term++;
6533 		    else
6534 			(*file)[count++] = vim_strsave(name_buf);
6535 		}
6536 	    }
6537 
6538 	    /*
6539 	     * Check special key names.
6540 	     */
6541 	    regmatch->rm_ic = TRUE;		// ignore case here
6542 	    for (opt_idx = 0; (str = get_key_name(opt_idx)) != NULL; opt_idx++)
6543 	    {
6544 		name_buf[0] = '<';
6545 		STRCPY(name_buf + 1, str);
6546 		STRCAT(name_buf, ">");
6547 
6548 		if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6549 		{
6550 		    if (loop == 0)
6551 			num_term++;
6552 		    else
6553 			(*file)[count++] = vim_strsave(name_buf);
6554 		}
6555 	    }
6556 	}
6557 	if (loop == 0)
6558 	{
6559 	    if (num_normal > 0)
6560 		*num_file = num_normal;
6561 	    else if (num_term > 0)
6562 		*num_file = num_term;
6563 	    else
6564 		return OK;
6565 	    *file = ALLOC_MULT(char_u *, *num_file);
6566 	    if (*file == NULL)
6567 	    {
6568 		*file = (char_u **)"";
6569 		return FAIL;
6570 	    }
6571 	}
6572     }
6573     return OK;
6574 }
6575 
6576     int
ExpandOldSetting(int * num_file,char_u *** file)6577 ExpandOldSetting(int *num_file, char_u ***file)
6578 {
6579     char_u  *var = NULL;	// init for GCC
6580     char_u  *buf;
6581 
6582     *num_file = 0;
6583     *file = ALLOC_ONE(char_u *);
6584     if (*file == NULL)
6585 	return FAIL;
6586 
6587     /*
6588      * For a terminal key code expand_option_idx is < 0.
6589      */
6590     if (expand_option_idx < 0)
6591     {
6592 	var = find_termcode(expand_option_name + 2);
6593 	if (var == NULL)
6594 	    expand_option_idx = findoption(expand_option_name);
6595     }
6596 
6597     if (expand_option_idx >= 0)
6598     {
6599 	// put string of option value in NameBuff
6600 	option_value2string(&options[expand_option_idx], expand_option_flags);
6601 	var = NameBuff;
6602     }
6603     else if (var == NULL)
6604 	var = (char_u *)"";
6605 
6606     // A backslash is required before some characters.  This is the reverse of
6607     // what happens in do_set().
6608     buf = vim_strsave_escaped(var, escape_chars);
6609 
6610     if (buf == NULL)
6611     {
6612 	VIM_CLEAR(*file);
6613 	return FAIL;
6614     }
6615 
6616 #ifdef BACKSLASH_IN_FILENAME
6617     // For MS-Windows et al. we don't double backslashes at the start and
6618     // before a file name character.
6619     for (var = buf; *var != NUL; MB_PTR_ADV(var))
6620 	if (var[0] == '\\' && var[1] == '\\'
6621 		&& expand_option_idx >= 0
6622 		&& (options[expand_option_idx].flags & P_EXPAND)
6623 		&& vim_isfilec(var[2])
6624 		&& (var[2] != '\\' || (var == buf && var[4] != '\\')))
6625 	    STRMOVE(var, var + 1);
6626 #endif
6627 
6628     *file[0] = buf;
6629     *num_file = 1;
6630     return OK;
6631 }
6632 
6633 /*
6634  * Get the value for the numeric or string option *opp in a nice format into
6635  * NameBuff[].  Must not be called with a hidden option!
6636  */
6637     static void
option_value2string(struct vimoption * opp,int opt_flags)6638 option_value2string(
6639     struct vimoption	*opp,
6640     int			opt_flags)	// OPT_GLOBAL and/or OPT_LOCAL
6641 {
6642     char_u	*varp;
6643 
6644     varp = get_varp_scope(opp, opt_flags);
6645 
6646     if (opp->flags & P_NUM)
6647     {
6648 	long wc = 0;
6649 
6650 	if (wc_use_keyname(varp, &wc))
6651 	    STRCPY(NameBuff, get_special_key_name((int)wc, 0));
6652 	else if (wc != 0)
6653 	    STRCPY(NameBuff, transchar((int)wc));
6654 	else
6655 	    sprintf((char *)NameBuff, "%ld", *(long *)varp);
6656     }
6657     else    // P_STRING
6658     {
6659 	varp = *(char_u **)(varp);
6660 	if (varp == NULL)		    // just in case
6661 	    NameBuff[0] = NUL;
6662 #ifdef FEAT_CRYPT
6663 	// don't show the actual value of 'key', only that it's set
6664 	else if (opp->var == (char_u *)&p_key && *varp)
6665 	    STRCPY(NameBuff, "*****");
6666 #endif
6667 	else if (opp->flags & P_EXPAND)
6668 	    home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE);
6669 	// Translate 'pastetoggle' into special key names
6670 	else if ((char_u **)opp->var == &p_pt)
6671 	    str2specialbuf(p_pt, NameBuff, MAXPATHL);
6672 	else
6673 	    vim_strncpy(NameBuff, varp, MAXPATHL - 1);
6674     }
6675 }
6676 
6677 /*
6678  * Return TRUE if "varp" points to 'wildchar' or 'wildcharm' and it can be
6679  * printed as a keyname.
6680  * "*wcp" is set to the value of the option if it's 'wildchar' or 'wildcharm'.
6681  */
6682     static int
wc_use_keyname(char_u * varp,long * wcp)6683 wc_use_keyname(char_u *varp, long *wcp)
6684 {
6685     if (((long *)varp == &p_wc) || ((long *)varp == &p_wcm))
6686     {
6687 	*wcp = *(long *)varp;
6688 	if (IS_SPECIAL(*wcp) || find_special_key_in_table((int)*wcp) >= 0)
6689 	    return TRUE;
6690     }
6691     return FALSE;
6692 }
6693 
6694 /*
6695  * Return TRUE if "x" is present in 'shortmess' option, or
6696  * 'shortmess' contains 'a' and "x" is present in SHM_A.
6697  */
6698     int
shortmess(int x)6699 shortmess(int x)
6700 {
6701     return p_shm != NULL &&
6702 	    (   vim_strchr(p_shm, x) != NULL
6703 	    || (vim_strchr(p_shm, 'a') != NULL
6704 		&& vim_strchr((char_u *)SHM_A, x) != NULL));
6705 }
6706 
6707 /*
6708  * paste_option_changed() - Called after p_paste was set or reset.
6709  */
6710     static void
paste_option_changed(void)6711 paste_option_changed(void)
6712 {
6713     static int	old_p_paste = FALSE;
6714     static int	save_sm = 0;
6715     static int	save_sta = 0;
6716 #ifdef FEAT_CMDL_INFO
6717     static int	save_ru = 0;
6718 #endif
6719 #ifdef FEAT_RIGHTLEFT
6720     static int	save_ri = 0;
6721     static int	save_hkmap = 0;
6722 #endif
6723     buf_T	*buf;
6724 
6725     if (p_paste)
6726     {
6727 	/*
6728 	 * Paste switched from off to on.
6729 	 * Save the current values, so they can be restored later.
6730 	 */
6731 	if (!old_p_paste)
6732 	{
6733 	    // save options for each buffer
6734 	    FOR_ALL_BUFFERS(buf)
6735 	    {
6736 		buf->b_p_tw_nopaste = buf->b_p_tw;
6737 		buf->b_p_wm_nopaste = buf->b_p_wm;
6738 		buf->b_p_sts_nopaste = buf->b_p_sts;
6739 		buf->b_p_ai_nopaste = buf->b_p_ai;
6740 		buf->b_p_et_nopaste = buf->b_p_et;
6741 #ifdef FEAT_VARTABS
6742 		if (buf->b_p_vsts_nopaste)
6743 		    vim_free(buf->b_p_vsts_nopaste);
6744 		buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
6745 				     ? vim_strsave(buf->b_p_vsts) : NULL;
6746 #endif
6747 	    }
6748 
6749 	    // save global options
6750 	    save_sm = p_sm;
6751 	    save_sta = p_sta;
6752 #ifdef FEAT_CMDL_INFO
6753 	    save_ru = p_ru;
6754 #endif
6755 #ifdef FEAT_RIGHTLEFT
6756 	    save_ri = p_ri;
6757 	    save_hkmap = p_hkmap;
6758 #endif
6759 	    // save global values for local buffer options
6760 	    p_ai_nopaste = p_ai;
6761 	    p_et_nopaste = p_et;
6762 	    p_sts_nopaste = p_sts;
6763 	    p_tw_nopaste = p_tw;
6764 	    p_wm_nopaste = p_wm;
6765 #ifdef FEAT_VARTABS
6766 	    if (p_vsts_nopaste)
6767 		vim_free(p_vsts_nopaste);
6768 	    p_vsts_nopaste = p_vsts && p_vsts != empty_option ? vim_strsave(p_vsts) : NULL;
6769 #endif
6770 	}
6771 
6772 	/*
6773 	 * Always set the option values, also when 'paste' is set when it is
6774 	 * already on.
6775 	 */
6776 	// set options for each buffer
6777 	FOR_ALL_BUFFERS(buf)
6778 	{
6779 	    buf->b_p_tw = 0;	    // textwidth is 0
6780 	    buf->b_p_wm = 0;	    // wrapmargin is 0
6781 	    buf->b_p_sts = 0;	    // softtabstop is 0
6782 	    buf->b_p_ai = 0;	    // no auto-indent
6783 	    buf->b_p_et = 0;	    // no expandtab
6784 #ifdef FEAT_VARTABS
6785 	    if (buf->b_p_vsts)
6786 		free_string_option(buf->b_p_vsts);
6787 	    buf->b_p_vsts = empty_option;
6788 	    if (buf->b_p_vsts_array)
6789 		vim_free(buf->b_p_vsts_array);
6790 	    buf->b_p_vsts_array = 0;
6791 #endif
6792 	}
6793 
6794 	// set global options
6795 	p_sm = 0;		    // no showmatch
6796 	p_sta = 0;		    // no smarttab
6797 #ifdef FEAT_CMDL_INFO
6798 	if (p_ru)
6799 	    status_redraw_all();    // redraw to remove the ruler
6800 	p_ru = 0;		    // no ruler
6801 #endif
6802 #ifdef FEAT_RIGHTLEFT
6803 	p_ri = 0;		    // no reverse insert
6804 	p_hkmap = 0;		    // no Hebrew keyboard
6805 #endif
6806 	// set global values for local buffer options
6807 	p_tw = 0;
6808 	p_wm = 0;
6809 	p_sts = 0;
6810 	p_ai = 0;
6811 #ifdef FEAT_VARTABS
6812 	if (p_vsts)
6813 	    free_string_option(p_vsts);
6814 	p_vsts = empty_option;
6815 #endif
6816     }
6817 
6818     /*
6819      * Paste switched from on to off: Restore saved values.
6820      */
6821     else if (old_p_paste)
6822     {
6823 	// restore options for each buffer
6824 	FOR_ALL_BUFFERS(buf)
6825 	{
6826 	    buf->b_p_tw = buf->b_p_tw_nopaste;
6827 	    buf->b_p_wm = buf->b_p_wm_nopaste;
6828 	    buf->b_p_sts = buf->b_p_sts_nopaste;
6829 	    buf->b_p_ai = buf->b_p_ai_nopaste;
6830 	    buf->b_p_et = buf->b_p_et_nopaste;
6831 #ifdef FEAT_VARTABS
6832 	    if (buf->b_p_vsts)
6833 		free_string_option(buf->b_p_vsts);
6834 	    buf->b_p_vsts = buf->b_p_vsts_nopaste
6835 			 ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option;
6836 	    if (buf->b_p_vsts_array)
6837 		vim_free(buf->b_p_vsts_array);
6838 	    if (buf->b_p_vsts && buf->b_p_vsts != empty_option)
6839 		(void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
6840 	    else
6841 		buf->b_p_vsts_array = 0;
6842 #endif
6843 	}
6844 
6845 	// restore global options
6846 	p_sm = save_sm;
6847 	p_sta = save_sta;
6848 #ifdef FEAT_CMDL_INFO
6849 	if (p_ru != save_ru)
6850 	    status_redraw_all();    // redraw to draw the ruler
6851 	p_ru = save_ru;
6852 #endif
6853 #ifdef FEAT_RIGHTLEFT
6854 	p_ri = save_ri;
6855 	p_hkmap = save_hkmap;
6856 #endif
6857 	// set global values for local buffer options
6858 	p_ai = p_ai_nopaste;
6859 	p_et = p_et_nopaste;
6860 	p_sts = p_sts_nopaste;
6861 	p_tw = p_tw_nopaste;
6862 	p_wm = p_wm_nopaste;
6863 #ifdef FEAT_VARTABS
6864 	if (p_vsts)
6865 	    free_string_option(p_vsts);
6866 	p_vsts = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : empty_option;
6867 #endif
6868     }
6869 
6870     old_p_paste = p_paste;
6871 }
6872 
6873 /*
6874  * vimrc_found() - Called when a ".vimrc" or "VIMINIT" has been found.
6875  *
6876  * Reset 'compatible' and set the values for options that didn't get set yet
6877  * to the Vim defaults.
6878  * Don't do this if the 'compatible' option has been set or reset before.
6879  * When "fname" is not NULL, use it to set $"envname" when it wasn't set yet.
6880  */
6881     void
vimrc_found(char_u * fname,char_u * envname)6882 vimrc_found(char_u *fname, char_u *envname)
6883 {
6884     int		opt_idx;
6885     int		dofree = FALSE;
6886     char_u	*p;
6887 
6888     if (!option_was_set((char_u *)"cp"))
6889     {
6890 	p_cp = FALSE;
6891 	for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
6892 	    if (!(options[opt_idx].flags & (P_WAS_SET|P_VI_DEF)))
6893 		set_option_default(opt_idx, OPT_FREE, FALSE);
6894 	didset_options();
6895 	didset_options2();
6896     }
6897 
6898     if (fname != NULL)
6899     {
6900 	p = vim_getenv(envname, &dofree);
6901 	if (p == NULL)
6902 	{
6903 	    // Set $MYVIMRC to the first vimrc file found.
6904 	    p = FullName_save(fname, FALSE);
6905 	    if (p != NULL)
6906 	    {
6907 		vim_setenv(envname, p);
6908 		vim_free(p);
6909 	    }
6910 	}
6911 	else if (dofree)
6912 	    vim_free(p);
6913     }
6914 }
6915 
6916 /*
6917  * Set 'compatible' on or off.  Called for "-C" and "-N" command line arg.
6918  */
6919     void
change_compatible(int on)6920 change_compatible(int on)
6921 {
6922     int	    opt_idx;
6923 
6924     if (p_cp != on)
6925     {
6926 	p_cp = on;
6927 	compatible_set();
6928     }
6929     opt_idx = findoption((char_u *)"cp");
6930     if (opt_idx >= 0)
6931 	options[opt_idx].flags |= P_WAS_SET;
6932 }
6933 
6934 /*
6935  * Return TRUE when option "name" has been set.
6936  * Only works correctly for global options.
6937  */
6938     int
option_was_set(char_u * name)6939 option_was_set(char_u *name)
6940 {
6941     int idx;
6942 
6943     idx = findoption(name);
6944     if (idx < 0)	// unknown option
6945 	return FALSE;
6946     if (options[idx].flags & P_WAS_SET)
6947 	return TRUE;
6948     return FALSE;
6949 }
6950 
6951 /*
6952  * Reset the flag indicating option "name" was set.
6953  */
6954     int
reset_option_was_set(char_u * name)6955 reset_option_was_set(char_u *name)
6956 {
6957     int idx = findoption(name);
6958 
6959     if (idx >= 0)
6960     {
6961 	options[idx].flags &= ~P_WAS_SET;
6962 	return OK;
6963     }
6964     return FAIL;
6965 }
6966 
6967 /*
6968  * compatible_set() - Called when 'compatible' has been set or unset.
6969  *
6970  * When 'compatible' set: Set all relevant options (those that have the P_VIM)
6971  * flag) to a Vi compatible value.
6972  * When 'compatible' is unset: Set all options that have a different default
6973  * for Vim (without the P_VI_DEF flag) to that default.
6974  */
6975     static void
compatible_set(void)6976 compatible_set(void)
6977 {
6978     int	    opt_idx;
6979 
6980     for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
6981 	if (	   ((options[opt_idx].flags & P_VIM) && p_cp)
6982 		|| (!(options[opt_idx].flags & P_VI_DEF) && !p_cp))
6983 	    set_option_default(opt_idx, OPT_FREE, p_cp);
6984     didset_options();
6985     didset_options2();
6986 }
6987 
6988 #if defined(FEAT_LINEBREAK) || defined(PROTO)
6989 
6990 /*
6991  * fill_breakat_flags() -- called when 'breakat' changes value.
6992  */
6993     void
fill_breakat_flags(void)6994 fill_breakat_flags(void)
6995 {
6996     char_u	*p;
6997     int		i;
6998 
6999     for (i = 0; i < 256; i++)
7000 	breakat_flags[i] = FALSE;
7001 
7002     if (p_breakat != NULL)
7003 	for (p = p_breakat; *p; p++)
7004 	    breakat_flags[*p] = TRUE;
7005 }
7006 #endif
7007 
7008 /*
7009  * Check if backspacing over something is allowed.
7010  */
7011     int
can_bs(int what)7012 can_bs(
7013     int		what)	    // BS_INDENT, BS_EOL, BS_START or BS_NOSTOP
7014 {
7015 #ifdef FEAT_JOB_CHANNEL
7016     if (what == BS_START && bt_prompt(curbuf))
7017 	return FALSE;
7018 #endif
7019     switch (*p_bs)
7020     {
7021 	case '3':       return TRUE;
7022 	case '2':	return (what != BS_NOSTOP);
7023 	case '1':	return (what != BS_START);
7024 	case '0':	return FALSE;
7025     }
7026     return vim_strchr(p_bs, what) != NULL;
7027 }
7028 
7029 /*
7030  * Return the effective 'scrolloff' value for the current window, using the
7031  * global value when appropriate.
7032  */
7033     long
get_scrolloff_value(void)7034 get_scrolloff_value(void)
7035 {
7036     return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
7037 }
7038 
7039 /*
7040  * Return the effective 'sidescrolloff' value for the current window, using the
7041  * global value when appropriate.
7042  */
7043     long
get_sidescrolloff_value(void)7044 get_sidescrolloff_value(void)
7045 {
7046     return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
7047 }
7048 
7049 /*
7050  * Get the local or global value of 'backupcopy'.
7051  */
7052     unsigned int
get_bkc_value(buf_T * buf)7053 get_bkc_value(buf_T *buf)
7054 {
7055     return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
7056 }
7057 
7058 /*
7059  * Get the local or global value of the 'virtualedit' flags.
7060  */
7061     unsigned int
get_ve_flags(void)7062 get_ve_flags(void)
7063 {
7064     return (curwin->w_ve_flags ? curwin->w_ve_flags : ve_flags)
7065 	    & ~(VE_NONE | VE_NONEU);
7066 }
7067 
7068 #if defined(FEAT_LINEBREAK) || defined(PROTO)
7069 /*
7070  * Get the local or global value of 'showbreak'.
7071  */
7072     char_u *
get_showbreak_value(win_T * win)7073 get_showbreak_value(win_T *win)
7074 {
7075     if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL)
7076 	return p_sbr;
7077     if (STRCMP(win->w_p_sbr, "NONE") == 0)
7078 	return empty_option;
7079     return win->w_p_sbr;
7080 }
7081 #endif
7082 
7083 #if defined(FEAT_EVAL) || defined(PROTO)
7084 /*
7085  * Get window or buffer local options.
7086  */
7087     dict_T *
get_winbuf_options(int bufopt)7088 get_winbuf_options(int bufopt)
7089 {
7090     dict_T	*d;
7091     int		opt_idx;
7092 
7093     d = dict_alloc();
7094     if (d == NULL)
7095 	return NULL;
7096 
7097     for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
7098     {
7099 	struct vimoption *opt = &options[opt_idx];
7100 
7101 	if ((bufopt && (opt->indir & PV_BUF))
7102 					 || (!bufopt && (opt->indir & PV_WIN)))
7103 	{
7104 	    char_u *varp = get_varp(opt);
7105 
7106 	    if (varp != NULL)
7107 	    {
7108 		if (opt->flags & P_STRING)
7109 		    dict_add_string(d, opt->fullname, *(char_u **)varp);
7110 		else if (opt->flags & P_NUM)
7111 		    dict_add_number(d, opt->fullname, *(long *)varp);
7112 		else
7113 		    dict_add_number(d, opt->fullname, *(int *)varp);
7114 	    }
7115 	}
7116     }
7117 
7118     return d;
7119 }
7120 #endif
7121 
7122 #if defined(FEAT_SYN_HL) || defined(PROTO)
7123 /*
7124  * This is called when 'culopt' is changed
7125  */
7126     int
fill_culopt_flags(char_u * val,win_T * wp)7127 fill_culopt_flags(char_u *val, win_T *wp)
7128 {
7129     char_u	*p;
7130     char_u	culopt_flags_new = 0;
7131 
7132     if (val == NULL)
7133 	p = wp->w_p_culopt;
7134     else
7135 	p = val;
7136     while (*p != NUL)
7137     {
7138 	if (STRNCMP(p, "line", 4) == 0)
7139 	{
7140 	    p += 4;
7141 	    culopt_flags_new |= CULOPT_LINE;
7142 	}
7143 	else if (STRNCMP(p, "both", 4) == 0)
7144 	{
7145 	    p += 4;
7146 	    culopt_flags_new |= CULOPT_LINE | CULOPT_NBR;
7147 	}
7148 	else if (STRNCMP(p, "number", 6) == 0)
7149 	{
7150 	    p += 6;
7151 	    culopt_flags_new |= CULOPT_NBR;
7152 	}
7153 	else if (STRNCMP(p, "screenline", 10) == 0)
7154 	{
7155 	    p += 10;
7156 	    culopt_flags_new |= CULOPT_SCRLINE;
7157 	}
7158 
7159 	if (*p != ',' && *p != NUL)
7160 	    return FAIL;
7161 	if (*p == ',')
7162 	    ++p;
7163     }
7164 
7165     // Can't have both "line" and "screenline".
7166     if ((culopt_flags_new & CULOPT_LINE) && (culopt_flags_new & CULOPT_SCRLINE))
7167 	return FAIL;
7168     wp->w_p_culopt_flags = culopt_flags_new;
7169 
7170     return OK;
7171 }
7172 #endif
7173 
7174 /*
7175  * Get the value of 'magic' adjusted for Vim9 script.
7176  */
7177     int
magic_isset(void)7178 magic_isset(void)
7179 {
7180     switch (magic_overruled)
7181     {
7182 	case OPTION_MAGIC_ON:      return TRUE;
7183 	case OPTION_MAGIC_OFF:     return FALSE;
7184 	case OPTION_MAGIC_NOT_SET: break;
7185     }
7186 #ifdef FEAT_EVAL
7187     if (in_vim9script())
7188 	return TRUE;
7189 #endif
7190     return p_magic;
7191 }
7192 
7193 /*
7194  * Set the callback function value for an option that accepts a function name,
7195  * lambda, et al. (e.g. 'operatorfunc', 'tagfunc', etc.)
7196  * Returns OK if the option is successfully set to a function, otherwise
7197  * returns FAIL.
7198  */
7199     int
option_set_callback_func(char_u * optval UNUSED,callback_T * optcb UNUSED)7200 option_set_callback_func(char_u *optval UNUSED, callback_T *optcb UNUSED)
7201 {
7202 #ifdef FEAT_EVAL
7203     typval_T	*tv;
7204     callback_T	cb;
7205 
7206     if (optval == NULL || *optval == NUL)
7207     {
7208 	free_callback(optcb);
7209 	return OK;
7210     }
7211 
7212     if (*optval == '{'
7213 	    || (STRNCMP(optval, "function(", 9) == 0)
7214 	    || (STRNCMP(optval, "funcref(", 8) == 0))
7215 	// Lambda expression or a funcref
7216 	tv = eval_expr(optval, NULL);
7217     else
7218 	// treat everything else as a function name string
7219 	tv = alloc_string_tv(vim_strsave(optval));
7220     if (tv == NULL)
7221 	return FAIL;
7222 
7223     cb = get_callback(tv);
7224     if (cb.cb_name == NULL)
7225     {
7226 	free_tv(tv);
7227 	return FAIL;
7228     }
7229 
7230     free_callback(optcb);
7231     set_callback(optcb, &cb);
7232     free_tv(tv);
7233     return OK;
7234 #else
7235     return FAIL;
7236 #endif
7237 }
7238