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