blob: 75ff3cdb2959aa397a68c48d949d91b9dfccddfd [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
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.
Bram Moolenaarcea912a2016-10-12 14:20:24 +020025 * - Add documentation! One line in doc/quickref.txt, full description in
Bram Moolenaar071d4272004-06-13 20:20:40 +000026 * 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"
Bram Moolenaar0eddca42019-09-12 22:26:43 +020036#include "optiondefs.h"
Bram Moolenaar071d4272004-06-13 20:20:40 +000037
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010038static void set_options_default(int opt_flags);
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +010039static void set_string_default_esc(char *name, char_u *val, int escape);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010040static char_u *term_bg_default(void);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010041static char_u *option_expand(int opt_idx, char_u *val);
42static void didset_options(void);
43static void didset_options2(void);
Bram Moolenaard1f56e62006-02-22 21:25:37 +000044#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010045static long_u *insecure_flag(int opt_idx, int opt_flags);
Bram Moolenaard1f56e62006-02-22 21:25:37 +000046#else
47# define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
48#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010049static char *set_bool_option(int opt_idx, char_u *varp, int value, int opt_flags);
50static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, size_t errbuflen, int opt_flags);
Bram Moolenaar9cf4b502018-07-23 04:12:03 +020051static int find_key_option(char_u *arg_arg, int has_lt);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010052static void showoptions(int all, int opt_flags);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +020053static int optval_default(struct vimoption *, char_u *varp, int compatible);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010054static void showoneopt(struct vimoption *, int opt_flags);
Bram Moolenaared18f2c2019-01-24 20:30:52 +010055static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, long_u flags);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010056static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep);
57static int put_setbool(FILE *fd, char *cmd, char *name, int value);
Bram Moolenaardac13472019-09-16 21:06:21 +020058static int istermoption(struct vimoption *p);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010059static char_u *get_varp_scope(struct vimoption *p, int opt_flags);
60static char_u *get_varp(struct vimoption *);
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020061static void check_win_options(win_T *win);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010062static void option_value2string(struct vimoption *, int opt_flags);
63static void check_winopt(winopt_T *wop);
64static int wc_use_keyname(char_u *varp, long *wcp);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010065static void paste_option_changed(void);
66static void compatible_set(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000067
68/*
69 * Initialize the options, first part.
70 *
71 * Called only once from main(), just after creating the first buffer.
Bram Moolenaar07268702018-03-01 21:57:32 +010072 * If "clean_arg" is TRUE Vim was started with --clean.
Bram Moolenaar071d4272004-06-13 20:20:40 +000073 */
74 void
Bram Moolenaar07268702018-03-01 21:57:32 +010075set_init_1(int clean_arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +000076{
77 char_u *p;
78 int opt_idx;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +000079 long_u n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000080
81#ifdef FEAT_LANGMAP
82 langmap_init();
83#endif
84
85 /* Be Vi compatible by default */
86 p_cp = TRUE;
87
Bram Moolenaar4399ef42005-02-12 14:29:27 +000088 /* Use POSIX compatibility when $VIM_POSIX is set. */
89 if (mch_getenv((char_u *)"VIM_POSIX") != NULL)
Bram Moolenaar26a60b42005-02-22 08:49:11 +000090 {
Bram Moolenaar4399ef42005-02-12 14:29:27 +000091 set_string_default("cpo", (char_u *)CPO_ALL);
Bram Moolenaar9dfa3132019-05-04 21:08:40 +020092 set_string_default("shm", (char_u *)SHM_POSIX);
Bram Moolenaar26a60b42005-02-22 08:49:11 +000093 }
Bram Moolenaar4399ef42005-02-12 14:29:27 +000094
Bram Moolenaar071d4272004-06-13 20:20:40 +000095 /*
96 * Find default value for 'shell' option.
Bram Moolenaar7c626922005-02-07 22:01:03 +000097 * Don't use it if it is empty.
Bram Moolenaar071d4272004-06-13 20:20:40 +000098 */
Bram Moolenaar7c626922005-02-07 22:01:03 +000099 if (((p = mch_getenv((char_u *)"SHELL")) != NULL && *p != NUL)
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100100#if defined(MSWIN)
Bram Moolenaar7c626922005-02-07 22:01:03 +0000101 || ((p = mch_getenv((char_u *)"COMSPEC")) != NULL && *p != NUL)
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100102 || ((p = (char_u *)default_shell()) != NULL && *p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103#endif
Bram Moolenaar7c626922005-02-07 22:01:03 +0000104 )
Bram Moolenaar2efc44b2019-10-05 12:09:32 +0200105#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 vim_snprintf((char *)cmd, len, "\"%s\"", p);
116 set_string_default("sh", cmd);
117 vim_free(cmd);
118 }
119 else
120 set_string_default("sh", p);
121 }
122#else
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100123 set_string_default_esc("sh", p, TRUE);
Bram Moolenaar2efc44b2019-10-05 12:09:32 +0200124#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000125
126#ifdef FEAT_WILDIGN
127 /*
128 * Set the default for 'backupskip' to include environment variables for
129 * temp files.
130 */
131 {
132# ifdef UNIX
133 static char *(names[4]) = {"", "TMPDIR", "TEMP", "TMP"};
134# else
135 static char *(names[3]) = {"TMPDIR", "TEMP", "TMP"};
136# endif
Bram Moolenaar05159a02005-02-26 23:04:13 +0000137 int len;
138 garray_T ga;
139 int mustfree;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140
141 ga_init2(&ga, 1, 100);
142 for (n = 0; n < (long)(sizeof(names) / sizeof(char *)); ++n)
143 {
Bram Moolenaar05159a02005-02-26 23:04:13 +0000144 mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145# ifdef UNIX
146 if (*names[n] == NUL)
Bram Moolenaarb8e22a02018-04-12 21:37:34 +0200147# ifdef MACOS_X
148 p = (char_u *)"/private/tmp";
149# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150 p = (char_u *)"/tmp";
Bram Moolenaarb8e22a02018-04-12 21:37:34 +0200151# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000152 else
153# endif
Bram Moolenaar05159a02005-02-26 23:04:13 +0000154 p = vim_getenv((char_u *)names[n], &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000155 if (p != NULL && *p != NUL)
156 {
157 /* First time count the NUL, otherwise count the ','. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000158 len = (int)STRLEN(p) + 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159 if (ga_grow(&ga, len) == OK)
160 {
161 if (ga.ga_len > 0)
162 STRCAT(ga.ga_data, ",");
163 STRCAT(ga.ga_data, p);
164 add_pathsep(ga.ga_data);
165 STRCAT(ga.ga_data, "*");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000166 ga.ga_len += len;
167 }
168 }
Bram Moolenaar05159a02005-02-26 23:04:13 +0000169 if (mustfree)
170 vim_free(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 }
172 if (ga.ga_data != NULL)
173 {
174 set_string_default("bsk", ga.ga_data);
175 vim_free(ga.ga_data);
176 }
177 }
178#endif
179
180 /*
181 * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
182 */
183 opt_idx = findoption((char_u *)"maxmemtot");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000184 if (opt_idx >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000186#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
187 if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L)
188#endif
189 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190#ifdef HAVE_AVAIL_MEM
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000191 /* Use amount of memory available at this moment. */
Bram Moolenaar11b73d62012-06-29 15:51:30 +0200192 n = (mch_avail_mem(FALSE) >> 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193#else
194# ifdef HAVE_TOTAL_MEM
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000195 /* Use amount of memory available to Vim. */
Bram Moolenaar914572a2007-05-01 11:37:47 +0000196 n = (mch_total_mem(FALSE) >> 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197# else
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000198 n = (0x7fffffff >> 11);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199# endif
200#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000202 opt_idx = findoption((char_u *)"maxmem");
203 if (opt_idx >= 0)
204 {
205#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
Bram Moolenaar35be4532015-12-11 22:38:36 +0100206 if ((long)(long_i)options[opt_idx].def_val[VI_DEFAULT] > (long)n
207 || (long)(long_i)options[opt_idx].def_val[VI_DEFAULT] == 0L)
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000208#endif
209 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
210 }
211 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000212 }
213
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214#ifdef FEAT_SEARCHPATH
215 {
216 char_u *cdpath;
217 char_u *buf;
218 int i;
219 int j;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000220 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221
222 /* Initialize the 'cdpath' option's default value. */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000223 cdpath = vim_getenv((char_u *)"CDPATH", &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224 if (cdpath != NULL)
225 {
Bram Moolenaar964b3742019-05-24 18:54:09 +0200226 buf = alloc((STRLEN(cdpath) << 1) + 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227 if (buf != NULL)
228 {
229 buf[0] = ','; /* start with ",", current dir first */
230 j = 1;
231 for (i = 0; cdpath[i] != NUL; ++i)
232 {
233 if (vim_ispathlistsep(cdpath[i]))
234 buf[j++] = ',';
235 else
236 {
237 if (cdpath[i] == ' ' || cdpath[i] == ',')
238 buf[j++] = '\\';
239 buf[j++] = cdpath[i];
240 }
241 }
242 buf[j] = NUL;
243 opt_idx = findoption((char_u *)"cdpath");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000244 if (opt_idx >= 0)
245 {
246 options[opt_idx].def_val[VI_DEFAULT] = buf;
247 options[opt_idx].flags |= P_DEF_ALLOCED;
248 }
Bram Moolenaara9d52e32010-07-31 16:44:19 +0200249 else
250 vim_free(buf); /* cannot happen */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 }
Bram Moolenaar05159a02005-02-26 23:04:13 +0000252 if (mustfree)
253 vim_free(cdpath);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000254 }
255 }
256#endif
257
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100258#if defined(FEAT_POSTSCRIPT) && (defined(MSWIN) || defined(VMS) || defined(EBCDIC) || defined(MAC) || defined(hpux))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259 /* Set print encoding on platforms that don't default to latin1 */
260 set_string_default("penc",
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100261# if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262 (char_u *)"cp1252"
263# else
264# ifdef VMS
265 (char_u *)"dec-mcs"
266# else
267# ifdef EBCDIC
268 (char_u *)"ebcdic-uk"
269# else
270# ifdef MAC
271 (char_u *)"mac-roman"
272# else /* HPUX */
273 (char_u *)"hp-roman8"
274# endif
275# endif
276# endif
277# endif
278 );
279#endif
280
281#ifdef FEAT_POSTSCRIPT
282 /* 'printexpr' must be allocated to be able to evaluate it. */
283 set_string_default("pexpr",
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100284# if defined(MSWIN)
Bram Moolenaared203462004-06-16 11:19:22 +0000285 (char_u *)"system('copy' . ' ' . v:fname_in . (&printdevice == '' ? ' LPT1:' : (' \"' . &printdevice . '\"'))) . delete(v:fname_in)"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000286# else
287# ifdef VMS
288 (char_u *)"system('print/delete' . (&printdevice == '' ? '' : ' /queue=' . &printdevice) . ' ' . v:fname_in)"
289
290# else
291 (char_u *)"system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
292# endif
293# endif
294 );
295#endif
296
297 /*
298 * Set all the options (except the terminal options) to their default
299 * value. Also set the global value for local options.
300 */
301 set_options_default(0);
302
Bram Moolenaar07268702018-03-01 21:57:32 +0100303#ifdef CLEAN_RUNTIMEPATH
304 if (clean_arg)
305 {
306 opt_idx = findoption((char_u *)"runtimepath");
307 if (opt_idx >= 0)
308 {
309 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
310 p_rtp = (char_u *)CLEAN_RUNTIMEPATH;
311 }
312 opt_idx = findoption((char_u *)"packpath");
313 if (opt_idx >= 0)
314 {
315 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
316 p_pp = (char_u *)CLEAN_RUNTIMEPATH;
317 }
318 }
319#endif
320
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321#ifdef FEAT_GUI
322 if (found_reverse_arg)
323 set_option_value((char_u *)"bg", 0L, (char_u *)"dark", 0);
324#endif
325
326 curbuf->b_p_initialized = TRUE;
327 curbuf->b_p_ar = -1; /* no local 'autoread' value */
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +0100328 curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000329 check_buf_options(curbuf);
330 check_win_options(curwin);
331 check_options();
332
333 /* Must be before option_expand(), because that one needs vim_isIDc() */
334 didset_options();
335
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +0000336#ifdef FEAT_SPELL
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200337 /* Use the current chartab for the generic chartab. This is not in
338 * didset_options() because it only depends on 'encoding'. */
Bram Moolenaar6bb68362005-03-22 23:03:44 +0000339 init_spell_chartab();
340#endif
341
Bram Moolenaar071d4272004-06-13 20:20:40 +0000342 /*
343 * Expand environment variables and things like "~" for the defaults.
344 * If option_expand() returns non-NULL the variable is expanded. This can
345 * only happen for non-indirect options.
346 * Also set the default to the expanded value, so ":set" does not list
347 * them.
348 * Don't set the P_ALLOCED flag, because we don't want to free the
349 * default.
350 */
Bram Moolenaardac13472019-09-16 21:06:21 +0200351 for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000352 {
353 if ((options[opt_idx].flags & P_GETTEXT)
354 && options[opt_idx].var != NULL)
355 p = (char_u *)_(*(char **)options[opt_idx].var);
356 else
357 p = option_expand(opt_idx, NULL);
358 if (p != NULL && (p = vim_strsave(p)) != NULL)
359 {
360 *(char_u **)options[opt_idx].var = p;
361 /* VIMEXP
362 * Defaults for all expanded options are currently the same for Vi
363 * and Vim. When this changes, add some code here! Also need to
364 * split P_DEF_ALLOCED in two.
365 */
366 if (options[opt_idx].flags & P_DEF_ALLOCED)
367 vim_free(options[opt_idx].def_val[VI_DEFAULT]);
368 options[opt_idx].def_val[VI_DEFAULT] = p;
369 options[opt_idx].flags |= P_DEF_ALLOCED;
370 }
371 }
372
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373 save_file_ff(curbuf); /* Buffer is unchanged */
374
Bram Moolenaar071d4272004-06-13 20:20:40 +0000375#if defined(FEAT_ARABIC)
376 /* Detect use of mlterm.
377 * Mlterm is a terminal emulator akin to xterm that has some special
378 * abilities (bidi namely).
379 * NOTE: mlterm's author is being asked to 'set' a variable
380 * instead of an environment variable due to inheritance.
381 */
382 if (mch_getenv((char_u *)"MLTERM") != NULL)
383 set_option_value((char_u *)"tbidi", 1L, NULL, 0);
384#endif
385
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200386 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000387
Bram Moolenaar4f974752019-02-17 17:44:42 +0100388# if defined(MSWIN) && defined(FEAT_GETTEXT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389 /*
390 * If $LANG isn't set, try to get a good value for it. This makes the
391 * right language be used automatically. Don't do this for English.
392 */
393 if (mch_getenv((char_u *)"LANG") == NULL)
394 {
395 char buf[20];
396
397 /* Could use LOCALE_SISO639LANGNAME, but it's not in Win95.
398 * LOCALE_SABBREVLANGNAME gives us three letters, like "enu", we use
399 * only the first two. */
400 n = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME,
401 (LPTSTR)buf, 20);
402 if (n >= 2 && STRNICMP(buf, "en", 2) != 0)
403 {
404 /* There are a few exceptions (probably more) */
405 if (STRNICMP(buf, "cht", 3) == 0 || STRNICMP(buf, "zht", 3) == 0)
406 STRCPY(buf, "zh_TW");
407 else if (STRNICMP(buf, "chs", 3) == 0
408 || STRNICMP(buf, "zhc", 3) == 0)
409 STRCPY(buf, "zh_CN");
410 else if (STRNICMP(buf, "jp", 2) == 0)
411 STRCPY(buf, "ja");
412 else
413 buf[2] = NUL; /* truncate to two-letter code */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100414 vim_setenv((char_u *)"LANG", (char_u *)buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000415 }
416 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000417# else
Bram Moolenaar9d47f172006-03-15 23:03:01 +0000418# ifdef MACOS_CONVERT
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +0000419 /* Moved to os_mac_conv.c to avoid dependency problems. */
420 mac_lang_init();
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000421# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000422# endif
423
424 /* enc_locale() will try to find the encoding of the current locale. */
425 p = enc_locale();
426 if (p != NULL)
427 {
428 char_u *save_enc;
429
430 /* Try setting 'encoding' and check if the value is valid.
431 * If not, go back to the default "latin1". */
432 save_enc = p_enc;
433 p_enc = p;
Bram Moolenaar733f0a22007-03-02 18:56:27 +0000434 if (STRCMP(p_enc, "gb18030") == 0)
435 {
436 /* We don't support "gb18030", but "cp936" is a good substitute
437 * for practical purposes, thus use that. It's not an alias to
438 * still support conversion between gb18030 and utf-8. */
439 p_enc = vim_strsave((char_u *)"cp936");
440 vim_free(p);
441 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000442 if (mb_init() == NULL)
443 {
444 opt_idx = findoption((char_u *)"encoding");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000445 if (opt_idx >= 0)
446 {
447 options[opt_idx].def_val[VI_DEFAULT] = p_enc;
448 options[opt_idx].flags |= P_DEF_ALLOCED;
449 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450
Bram Moolenaard0573012017-10-28 21:11:06 +0200451#if defined(MSWIN) || defined(MACOS_X) || defined(VMS)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100452 if (STRCMP(p_enc, "latin1") == 0 || enc_utf8)
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000453 {
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000454 /* Adjust the default for 'isprint' and 'iskeyword' to match
455 * latin1. Also set the defaults for when 'nocompatible' is
456 * set. */
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000457 set_string_option_direct((char_u *)"isp", -1,
Bram Moolenaar4ea8fe12006-03-09 22:32:39 +0000458 ISP_LATIN1, OPT_FREE, SID_NONE);
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000459 set_string_option_direct((char_u *)"isk", -1,
460 ISK_LATIN1, OPT_FREE, SID_NONE);
461 opt_idx = findoption((char_u *)"isp");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000462 if (opt_idx >= 0)
463 options[opt_idx].def_val[VIM_DEFAULT] = ISP_LATIN1;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000464 opt_idx = findoption((char_u *)"isk");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000465 if (opt_idx >= 0)
466 options[opt_idx].def_val[VIM_DEFAULT] = ISK_LATIN1;
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000467 (void)init_chartab();
468 }
469#endif
470
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200471#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000472 /* Win32 console: When GetACP() returns a different value from
473 * GetConsoleCP() set 'termencoding'. */
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200474 if (
475# ifdef VIMDLL
476 (!gui.in_use && !gui.starting) &&
477# endif
478 GetACP() != GetConsoleCP())
Bram Moolenaar071d4272004-06-13 20:20:40 +0000479 {
480 char buf[50];
481
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100482 /* Win32 console: In ConPTY, GetConsoleCP() returns zero.
483 * Use an alternative value. */
484 if (GetConsoleCP() == 0)
485 sprintf(buf, "cp%ld", (long)GetACP());
486 else
487 sprintf(buf, "cp%ld", (long)GetConsoleCP());
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488 p_tenc = vim_strsave((char_u *)buf);
489 if (p_tenc != NULL)
490 {
491 opt_idx = findoption((char_u *)"termencoding");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000492 if (opt_idx >= 0)
493 {
494 options[opt_idx].def_val[VI_DEFAULT] = p_tenc;
495 options[opt_idx].flags |= P_DEF_ALLOCED;
496 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000497 convert_setup(&input_conv, p_tenc, p_enc);
498 convert_setup(&output_conv, p_enc, p_tenc);
499 }
500 else
501 p_tenc = empty_option;
502 }
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100503#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +0100504#if defined(MSWIN)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000505 /* $HOME may have characters in active code page. */
506 init_homedir();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100507#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508 }
509 else
510 {
511 vim_free(p_enc);
512 p_enc = save_enc;
513 }
514 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000515
516#ifdef FEAT_MULTI_LANG
517 /* Set the default for 'helplang'. */
518 set_helplang_default(get_mess_lang());
519#endif
520}
521
522/*
523 * Set an option to its default value.
524 * This does not take care of side effects!
525 */
526 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100527set_option_default(
528 int opt_idx,
529 int opt_flags, /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
530 int compatible) /* use Vi default value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531{
532 char_u *varp; /* pointer to variable for current option */
533 int dvi; /* index in def_val[] */
534 long_u flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000535 long_u *flagsp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000536 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
537
538 varp = get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
539 flags = options[opt_idx].flags;
Bram Moolenaar3638c682005-06-08 22:05:14 +0000540 if (varp != NULL) /* skip hidden option, nothing to do for it */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000541 {
542 dvi = ((flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
543 if (flags & P_STRING)
544 {
Bram Moolenaarb833c1e2018-05-05 16:36:06 +0200545 /* Use set_string_option_direct() for local options to handle
546 * freeing and allocating the value. */
547 if (options[opt_idx].indir != PV_NONE)
548 set_string_option_direct(NULL, opt_idx,
549 options[opt_idx].def_val[dvi], opt_flags, 0);
550 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 {
Bram Moolenaarb833c1e2018-05-05 16:36:06 +0200552 if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED))
553 free_string_option(*(char_u **)(varp));
554 *(char_u **)varp = options[opt_idx].def_val[dvi];
555 options[opt_idx].flags &= ~P_ALLOCED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 }
557 }
558 else if (flags & P_NUM)
559 {
Bram Moolenaar5fc1a8b2006-10-17 16:34:24 +0000560 if (options[opt_idx].indir == PV_SCROLL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561 win_comp_scroll(curwin);
562 else
563 {
Bram Moolenaar375e3392019-01-31 18:26:10 +0100564 long def_val = (long)(long_i)options[opt_idx].def_val[dvi];
565
566 if ((long *)varp == &curwin->w_p_so
567 || (long *)varp == &curwin->w_p_siso)
568 // 'scrolloff' and 'sidescrolloff' local values have a
569 // different default value than the global default.
570 *(long *)varp = -1;
571 else
572 *(long *)varp = def_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000573 /* May also set global value for local option. */
574 if (both)
575 *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
Bram Moolenaar375e3392019-01-31 18:26:10 +0100576 def_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577 }
578 }
579 else /* P_BOOL */
580 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000581 /* the cast to long is required for Manx C, long_i is needed for
582 * MSVC */
583 *(int *)varp = (int)(long)(long_i)options[opt_idx].def_val[dvi];
Bram Moolenaar8243a792007-05-01 17:05:03 +0000584#ifdef UNIX
585 /* 'modeline' defaults to off for root */
586 if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID)
587 *(int *)varp = FALSE;
588#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000589 /* May also set global value for local option. */
590 if (both)
591 *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
592 *(int *)varp;
593 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000594
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000595 /* The default value is not insecure. */
596 flagsp = insecure_flag(opt_idx, opt_flags);
597 *flagsp = *flagsp & ~P_INSECURE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000598 }
599
600#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +0200601 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000602#endif
603}
604
605/*
606 * Set all options (except terminal options) to their default value.
Bram Moolenaarb341dda2015-08-25 12:56:31 +0200607 * When "opt_flags" is non-zero skip 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000608 */
609 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100610set_options_default(
611 int opt_flags) /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612{
613 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000614 win_T *wp;
Bram Moolenaarf740b292006-02-16 22:11:02 +0000615 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000616
Bram Moolenaardac13472019-09-16 21:06:21 +0200617 for (i = 0; !istermoption_idx(i); i++)
Bram Moolenaarb341dda2015-08-25 12:56:31 +0200618 if (!(options[i].flags & P_NODEFAULT)
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200619 && (opt_flags == 0
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100620 || (options[i].var != (char_u *)&p_enc
Bram Moolenaar5ea87a02015-08-26 23:24:09 +0200621# if defined(FEAT_CRYPT)
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200622 && options[i].var != (char_u *)&p_cm
Bram Moolenaar80606872015-08-25 21:27:35 +0200623 && options[i].var != (char_u *)&p_key
Bram Moolenaar5ea87a02015-08-26 23:24:09 +0200624# endif
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100625 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 set_option_default(i, opt_flags, p_cp);
627
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628 /* The 'scroll' option must be computed for all windows. */
Bram Moolenaarf740b292006-02-16 22:11:02 +0000629 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000630 win_comp_scroll(wp);
Bram Moolenaar5a4eceb2014-09-09 17:33:07 +0200631#ifdef FEAT_CINDENT
632 parse_cino(curbuf);
633#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634}
635
636/*
637 * Set the Vi-default value of a string option.
638 * Used for 'sh', 'backupskip' and 'term'.
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100639 * When "escape" is TRUE escape spaces with a backslash.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640 */
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100641 static void
642set_string_default_esc(char *name, char_u *val, int escape)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000643{
644 char_u *p;
645 int opt_idx;
646
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100647 if (escape && vim_strchr(val, ' ') != NULL)
648 p = vim_strsave_escaped(val, (char_u *)" ");
649 else
650 p = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651 if (p != NULL) /* we don't want a NULL */
652 {
653 opt_idx = findoption((char_u *)name);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000654 if (opt_idx >= 0)
655 {
656 if (options[opt_idx].flags & P_DEF_ALLOCED)
657 vim_free(options[opt_idx].def_val[VI_DEFAULT]);
658 options[opt_idx].def_val[VI_DEFAULT] = p;
659 options[opt_idx].flags |= P_DEF_ALLOCED;
660 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661 }
662}
663
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100664 void
665set_string_default(char *name, char_u *val)
666{
667 set_string_default_esc(name, val, FALSE);
668}
669
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670/*
671 * Set the Vi-default value of a number option.
672 * Used for 'lines' and 'columns'.
673 */
674 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100675set_number_default(char *name, long val)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676{
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000677 int opt_idx;
678
679 opt_idx = findoption((char_u *)name);
680 if (opt_idx >= 0)
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000681 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682}
683
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200684/*
685 * Set all window-local and buffer-local options to the Vim default.
686 * local-global options will use the global value.
Bram Moolenaar46451042019-08-24 15:50:46 +0200687 * When "do_buffer" is FALSE don't set buffer-local options.
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200688 */
689 void
Bram Moolenaar46451042019-08-24 15:50:46 +0200690set_local_options_default(win_T *wp, int do_buffer)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200691{
692 win_T *save_curwin = curwin;
693 int i;
694
695 curwin = wp;
696 curbuf = curwin->w_buffer;
697 block_autocmds();
698
Bram Moolenaardac13472019-09-16 21:06:21 +0200699 for (i = 0; !istermoption_idx(i); i++)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200700 {
701 struct vimoption *p = &(options[i]);
702 char_u *varp = get_varp_scope(p, OPT_LOCAL);
703
704 if (p->indir != PV_NONE
Bram Moolenaar46451042019-08-24 15:50:46 +0200705 && (do_buffer || (p->indir & PV_BUF) == 0)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200706 && !(options[i].flags & P_NODEFAULT)
707 && !optval_default(p, varp, FALSE))
Bram Moolenaar86173482019-10-01 17:02:16 +0200708 set_option_default(i, OPT_FREE|OPT_LOCAL, FALSE);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200709 }
710
711 unblock_autocmds();
712 curwin = save_curwin;
713 curbuf = curwin->w_buffer;
714}
715
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000716#if defined(EXITFREE) || defined(PROTO)
717/*
718 * Free all options.
719 */
720 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100721free_all_options(void)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000722{
723 int i;
724
Bram Moolenaardac13472019-09-16 21:06:21 +0200725 for (i = 0; !istermoption_idx(i); i++)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000726 {
727 if (options[i].indir == PV_NONE)
728 {
729 /* global option: free value and default value. */
Bram Moolenaar67391142017-02-19 21:07:04 +0100730 if ((options[i].flags & P_ALLOCED) && options[i].var != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000731 free_string_option(*(char_u **)options[i].var);
732 if (options[i].flags & P_DEF_ALLOCED)
733 free_string_option(options[i].def_val[VI_DEFAULT]);
734 }
735 else if (options[i].var != VAR_WIN
736 && (options[i].flags & P_STRING))
737 /* buffer-local option: free global value */
738 free_string_option(*(char_u **)options[i].var);
739 }
740}
741#endif
742
743
Bram Moolenaar071d4272004-06-13 20:20:40 +0000744/*
745 * Initialize the options, part two: After getting Rows and Columns and
746 * setting 'term'.
747 */
748 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100749set_init_2(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750{
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000751 int idx;
752
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753 /*
Bram Moolenaaraf2d20c2017-10-29 15:26:57 +0100754 * 'scroll' defaults to half the window height. The stored default is zero,
755 * which results in the actual value computed from the window height.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000756 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000757 idx = findoption((char_u *)"scroll");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000758 if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000759 set_option_default(idx, OPT_LOCAL, p_cp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 comp_col();
761
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000762 /*
763 * 'window' is only for backwards compatibility with Vi.
764 * Default is Rows - 1.
765 */
Bram Moolenaard68071d2006-05-02 22:08:30 +0000766 if (!option_was_set((char_u *)"window"))
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000767 p_window = Rows - 1;
768 set_number_default("window", Rows - 1);
769
Bram Moolenaarf740b292006-02-16 22:11:02 +0000770 /* For DOS console the default is always black. */
Bram Moolenaar4f974752019-02-17 17:44:42 +0100771#if !((defined(MSWIN)) && !defined(FEAT_GUI))
Bram Moolenaarf740b292006-02-16 22:11:02 +0000772 /*
773 * If 'background' wasn't set by the user, try guessing the value,
774 * depending on the terminal name. Only need to check for terminals
775 * with a dark background, that can handle color.
776 */
777 idx = findoption((char_u *)"bg");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000778 if (idx >= 0 && !(options[idx].flags & P_WAS_SET)
779 && *term_bg_default() == 'd')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000781 set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE, 0);
Bram Moolenaarf740b292006-02-16 22:11:02 +0000782 /* don't mark it as set, when starting the GUI it may be
783 * changed again */
784 options[idx].flags &= ~P_WAS_SET;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785 }
786#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +0000787
788#ifdef CURSOR_SHAPE
789 parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */
790#endif
791#ifdef FEAT_MOUSESHAPE
792 parse_shape_opt(SHAPE_MOUSE); /* set mouse shapes from 'mouseshape' */
793#endif
794#ifdef FEAT_PRINTER
795 (void)parse_printoptions(); /* parse 'printoptions' default value */
796#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797}
798
799/*
Bram Moolenaarf740b292006-02-16 22:11:02 +0000800 * Return "dark" or "light" depending on the kind of terminal.
801 * This is just guessing! Recognized are:
802 * "linux" Linux console
803 * "screen.linux" Linux console with screen
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200804 * "cygwin.*" Cygwin shell
805 * "putty.*" Putty program
Bram Moolenaarf740b292006-02-16 22:11:02 +0000806 * We also check the COLORFGBG environment variable, which is set by
807 * rxvt and derivatives. This variable contains either two or three
808 * values separated by semicolons; we want the last value in either
809 * case. If this value is 0-6 or 8, our background is dark.
810 */
811 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +0100812term_bg_default(void)
Bram Moolenaarf740b292006-02-16 22:11:02 +0000813{
Bram Moolenaar4f974752019-02-17 17:44:42 +0100814#if defined(MSWIN)
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200815 /* DOS console is nearly always black */
Bram Moolenaarf740b292006-02-16 22:11:02 +0000816 return (char_u *)"dark";
817#else
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000818 char_u *p;
819
Bram Moolenaarf740b292006-02-16 22:11:02 +0000820 if (STRCMP(T_NAME, "linux") == 0
821 || STRCMP(T_NAME, "screen.linux") == 0
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200822 || STRNCMP(T_NAME, "cygwin", 6) == 0
823 || STRNCMP(T_NAME, "putty", 5) == 0
Bram Moolenaarf740b292006-02-16 22:11:02 +0000824 || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
825 && (p = vim_strrchr(p, ';')) != NULL
826 && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
827 && p[2] == NUL))
828 return (char_u *)"dark";
829 return (char_u *)"light";
830#endif
831}
832
833/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 * Initialize the options, part three: After reading the .vimrc
835 */
836 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100837set_init_3(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838{
Bram Moolenaar4f974752019-02-17 17:44:42 +0100839#if defined(UNIX) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840/*
841 * Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
842 * This is done after other initializations, where 'shell' might have been
843 * set, but only if they have not been set before.
844 */
845 char_u *p;
846 int idx_srr;
847 int do_srr;
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100848# ifdef FEAT_QUICKFIX
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 int idx_sp;
850 int do_sp;
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100851# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852
853 idx_srr = findoption((char_u *)"srr");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000854 if (idx_srr < 0)
855 do_srr = FALSE;
856 else
857 do_srr = !(options[idx_srr].flags & P_WAS_SET);
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100858# ifdef FEAT_QUICKFIX
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 idx_sp = findoption((char_u *)"sp");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000860 if (idx_sp < 0)
861 do_sp = FALSE;
862 else
863 do_sp = !(options[idx_sp].flags & P_WAS_SET);
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100864# endif
Bram Moolenaar75a8d742014-05-07 15:10:21 +0200865 p = get_isolated_shell_name();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 if (p != NULL)
867 {
868 /*
869 * Default for p_sp is "| tee", for p_srr is ">".
870 * For known shells it is changed here to include stderr.
871 */
872 if ( fnamecmp(p, "csh") == 0
873 || fnamecmp(p, "tcsh") == 0
Bram Moolenaar4f974752019-02-17 17:44:42 +0100874# if defined(MSWIN) // also check with .exe extension
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875 || fnamecmp(p, "csh.exe") == 0
876 || fnamecmp(p, "tcsh.exe") == 0
877# endif
878 )
879 {
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100880# if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000881 if (do_sp)
882 {
Bram Moolenaar4f974752019-02-17 17:44:42 +0100883# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 p_sp = (char_u *)">&";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100885# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886 p_sp = (char_u *)"|& tee";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100887# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 options[idx_sp].def_val[VI_DEFAULT] = p_sp;
889 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100890# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891 if (do_srr)
892 {
893 p_srr = (char_u *)">&";
894 options[idx_srr].def_val[VI_DEFAULT] = p_srr;
895 }
896 }
897 else
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100898 /* Always use bourne shell style redirection if we reach this */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899 if ( fnamecmp(p, "sh") == 0
900 || fnamecmp(p, "ksh") == 0
Bram Moolenaarf1fda2d2011-04-28 12:57:36 +0200901 || fnamecmp(p, "mksh") == 0
902 || fnamecmp(p, "pdksh") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 || fnamecmp(p, "zsh") == 0
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000904 || fnamecmp(p, "zsh-beta") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905 || fnamecmp(p, "bash") == 0
Bram Moolenaar75a8d742014-05-07 15:10:21 +0200906 || fnamecmp(p, "fish") == 0
Bram Moolenaar4f974752019-02-17 17:44:42 +0100907# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908 || fnamecmp(p, "cmd") == 0
909 || fnamecmp(p, "sh.exe") == 0
910 || fnamecmp(p, "ksh.exe") == 0
Bram Moolenaarf1fda2d2011-04-28 12:57:36 +0200911 || fnamecmp(p, "mksh.exe") == 0
912 || fnamecmp(p, "pdksh.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 || fnamecmp(p, "zsh.exe") == 0
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000914 || fnamecmp(p, "zsh-beta.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 || fnamecmp(p, "bash.exe") == 0
916 || fnamecmp(p, "cmd.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917# endif
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100918 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 {
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100920# if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 if (do_sp)
922 {
Bram Moolenaar4f974752019-02-17 17:44:42 +0100923# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924 p_sp = (char_u *)">%s 2>&1";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100925# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926 p_sp = (char_u *)"2>&1| tee";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100927# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000928 options[idx_sp].def_val[VI_DEFAULT] = p_sp;
929 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100930# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931 if (do_srr)
932 {
933 p_srr = (char_u *)">%s 2>&1";
934 options[idx_srr].def_val[VI_DEFAULT] = p_srr;
935 }
936 }
937 vim_free(p);
938 }
939#endif
940
Bram Moolenaar4f974752019-02-17 17:44:42 +0100941#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 /*
Bram Moolenaara64ba222012-02-12 23:23:31 +0100943 * Set 'shellcmdflag', 'shellxquote', and 'shellquote' depending on the
944 * 'shell' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945 * This is done after other initializations, where 'shell' might have been
946 * set, but only if they have not been set before. Default for p_shcf is
947 * "/c", for p_shq is "". For "sh" like shells it is changed here to
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100948 * "-c" and "\"". And for Win32 we need to set p_sxq instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 */
Bram Moolenaarf4b8e572004-06-24 15:53:16 +0000950 if (strstr((char *)gettail(p_sh), "sh") != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 {
952 int idx3;
953
954 idx3 = findoption((char_u *)"shcf");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000955 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000956 {
957 p_shcf = (char_u *)"-c";
958 options[idx3].def_val[VI_DEFAULT] = p_shcf;
959 }
960
Bram Moolenaar071d4272004-06-13 20:20:40 +0000961 /* Somehow Win32 requires the quotes around the redirection too */
962 idx3 = findoption((char_u *)"sxq");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000963 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 {
965 p_sxq = (char_u *)"\"";
966 options[idx3].def_val[VI_DEFAULT] = p_sxq;
967 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 }
Bram Moolenaara64ba222012-02-12 23:23:31 +0100969 else if (strstr((char *)gettail(p_sh), "cmd.exe") != NULL)
970 {
971 int idx3;
972
973 /*
974 * cmd.exe on Windows will strip the first and last double quote given
975 * on the command line, e.g. most of the time things like:
976 * cmd /c "my path/to/echo" "my args to echo"
977 * become:
978 * my path/to/echo" "my args to echo
979 * when executed.
980 *
Bram Moolenaar034b1152012-02-19 18:19:30 +0100981 * To avoid this, set shellxquote to surround the command in
982 * parenthesis. This appears to make most commands work, without
983 * breaking commands that worked previously, such as
984 * '"path with spaces/cmd" "a&b"'.
Bram Moolenaara64ba222012-02-12 23:23:31 +0100985 */
Bram Moolenaara64ba222012-02-12 23:23:31 +0100986 idx3 = findoption((char_u *)"sxq");
987 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
988 {
Bram Moolenaar034b1152012-02-19 18:19:30 +0100989 p_sxq = (char_u *)"(";
Bram Moolenaara64ba222012-02-12 23:23:31 +0100990 options[idx3].def_val[VI_DEFAULT] = p_sxq;
991 }
992
Bram Moolenaara64ba222012-02-12 23:23:31 +0100993 idx3 = findoption((char_u *)"shcf");
994 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
995 {
Bram Moolenaar034b1152012-02-19 18:19:30 +0100996 p_shcf = (char_u *)"/c";
Bram Moolenaara64ba222012-02-12 23:23:31 +0100997 options[idx3].def_val[VI_DEFAULT] = p_shcf;
998 }
999 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000#endif
1001
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01001002 if (BUFEMPTY())
Bram Moolenaar364fa5c2016-03-20 17:53:25 +01001003 {
1004 int idx_ffs = findoption((char_u *)"ffs");
1005
1006 /* Apply the first entry of 'fileformats' to the initial buffer. */
1007 if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET))
1008 set_fileformat(default_fileformat(), OPT_LOCAL);
1009 }
1010
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011#ifdef FEAT_TITLE
1012 set_title_defaults();
1013#endif
1014}
1015
1016#if defined(FEAT_MULTI_LANG) || defined(PROTO)
1017/*
1018 * When 'helplang' is still at its default value, set it to "lang".
1019 * Only the first two characters of "lang" are used.
1020 */
1021 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001022set_helplang_default(char_u *lang)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001023{
1024 int idx;
1025
1026 if (lang == NULL || STRLEN(lang) < 2) /* safety check */
1027 return;
1028 idx = findoption((char_u *)"hlg");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001029 if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030 {
1031 if (options[idx].flags & P_ALLOCED)
1032 free_string_option(p_hlg);
1033 p_hlg = vim_strsave(lang);
1034 if (p_hlg == NULL)
1035 p_hlg = empty_option;
1036 else
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001037 {
Bram Moolenaardcd71cb2018-11-04 14:40:47 +01001038 // zh_CN becomes "cn", zh_TW becomes "tw"
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001039 if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5)
1040 {
1041 p_hlg[0] = TOLOWER_ASC(p_hlg[3]);
1042 p_hlg[1] = TOLOWER_ASC(p_hlg[4]);
1043 }
Bram Moolenaardcd71cb2018-11-04 14:40:47 +01001044 // any C like setting, such as C.UTF-8, becomes "en"
1045 else if (STRLEN(p_hlg) >= 1 && *p_hlg == 'C')
1046 {
1047 p_hlg[0] = 'e';
1048 p_hlg[1] = 'n';
1049 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001050 p_hlg[2] = NUL;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001051 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052 options[idx].flags |= P_ALLOCED;
1053 }
1054}
1055#endif
1056
1057#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01001059gui_bg_default(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060{
1061 if (gui_get_lightness(gui.back_pixel) < 127)
1062 return (char_u *)"dark";
1063 return (char_u *)"light";
1064}
1065
1066/*
1067 * Option initializations that can only be done after opening the GUI window.
1068 */
1069 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001070init_gui_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001071{
1072 /* Set the 'background' option according to the lightness of the
1073 * background color, unless the user has set it already. */
1074 if (!option_was_set((char_u *)"bg") && STRCMP(p_bg, gui_bg_default()) != 0)
1075 {
1076 set_option_value((char_u *)"bg", 0L, gui_bg_default(), 0);
1077 highlight_changed();
1078 }
1079}
1080#endif
1081
1082#ifdef FEAT_TITLE
1083/*
1084 * 'title' and 'icon' only default to true if they have not been set or reset
1085 * in .vimrc and we can read the old value.
1086 * When 'title' and 'icon' have been reset in .vimrc, we won't even check if
1087 * they can be reset. This reduces startup time when using X on a remote
1088 * machine.
1089 */
1090 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001091set_title_defaults(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001092{
1093 int idx1;
1094 long val;
1095
1096 /*
1097 * If GUI is (going to be) used, we can always set the window title and
1098 * icon name. Saves a bit of time, because the X11 display server does
1099 * not need to be contacted.
1100 */
1101 idx1 = findoption((char_u *)"title");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001102 if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001103 {
1104#ifdef FEAT_GUI
1105 if (gui.starting || gui.in_use)
1106 val = TRUE;
1107 else
1108#endif
1109 val = mch_can_restore_title();
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001110 options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111 p_title = val;
1112 }
1113 idx1 = findoption((char_u *)"icon");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001114 if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001115 {
1116#ifdef FEAT_GUI
1117 if (gui.starting || gui.in_use)
1118 val = TRUE;
1119 else
1120#endif
1121 val = mch_can_restore_icon();
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001122 options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001123 p_icon = val;
1124 }
1125}
1126#endif
1127
1128/*
1129 * Parse 'arg' for option settings.
1130 *
1131 * 'arg' may be IObuff, but only when no errors can be present and option
1132 * does not need to be expanded with option_expand().
1133 * "opt_flags":
1134 * 0 for ":set"
Bram Moolenaara3227e22006-03-08 21:32:40 +00001135 * OPT_GLOBAL for ":setglobal"
1136 * OPT_LOCAL for ":setlocal" and a modeline
Bram Moolenaar071d4272004-06-13 20:20:40 +00001137 * OPT_MODELINE for a modeline
Bram Moolenaara3227e22006-03-08 21:32:40 +00001138 * OPT_WINONLY to only set window-local options
1139 * OPT_NOWIN to skip setting window-local options
Bram Moolenaar071d4272004-06-13 20:20:40 +00001140 *
1141 * returns FAIL if an error is detected, OK otherwise
1142 */
1143 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01001144do_set(
1145 char_u *arg, /* option string (may be written to!) */
1146 int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147{
1148 int opt_idx;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001149 char *errmsg;
1150 char errbuf[80];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001151 char_u *startarg;
1152 int prefix; /* 1: nothing, 0: "no", 2: "inv" in front of name */
1153 int nextchar; /* next non-white char after option name */
1154 int afterchar; /* character just after option name */
1155 int len;
1156 int i;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001157 varnumber_T value;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 int key;
1159 long_u flags; /* flags for current option */
1160 char_u *varp = NULL; /* pointer to variable for current option */
1161 int did_show = FALSE; /* already showed one value */
1162 int adding; /* "opt+=arg" */
1163 int prepending; /* "opt^=arg" */
1164 int removing; /* "opt-=arg" */
1165 int cp_val = 0;
1166 char_u key_name[2];
1167
1168 if (*arg == NUL)
1169 {
1170 showoptions(0, opt_flags);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001171 did_show = TRUE;
1172 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173 }
1174
1175 while (*arg != NUL) /* loop to process all options */
1176 {
1177 errmsg = NULL;
1178 startarg = arg; /* remember for error message */
1179
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001180 if (STRNCMP(arg, "all", 3) == 0 && !isalpha(arg[3])
1181 && !(opt_flags & OPT_MODELINE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001182 {
1183 /*
1184 * ":set all" show all options.
1185 * ":set all&" set all options to their default value.
1186 */
1187 arg += 3;
1188 if (*arg == '&')
1189 {
1190 ++arg;
1191 /* Only for :set command set global value of local options. */
1192 set_options_default(OPT_FREE | opt_flags);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02001193 didset_options();
1194 didset_options2();
Bram Moolenaarb341dda2015-08-25 12:56:31 +02001195 redraw_all_later(CLEAR);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196 }
1197 else
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001198 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001199 showoptions(1, opt_flags);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001200 did_show = TRUE;
1201 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202 }
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001203 else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001204 {
1205 showoptions(2, opt_flags);
1206 show_termcodes();
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001207 did_show = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208 arg += 7;
1209 }
1210 else
1211 {
1212 prefix = 1;
Bram Moolenaar2a7b9ee2009-06-16 15:50:33 +00001213 if (STRNCMP(arg, "no", 2) == 0 && STRNCMP(arg, "novice", 6) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214 {
1215 prefix = 0;
1216 arg += 2;
1217 }
1218 else if (STRNCMP(arg, "inv", 3) == 0)
1219 {
1220 prefix = 2;
1221 arg += 3;
1222 }
1223
1224 /* find end of name */
1225 key = 0;
1226 if (*arg == '<')
1227 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001228 opt_idx = -1;
1229 /* look out for <t_>;> */
1230 if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
1231 len = 5;
1232 else
1233 {
1234 len = 1;
1235 while (arg[len] != NUL && arg[len] != '>')
1236 ++len;
1237 }
1238 if (arg[len] != '>')
1239 {
1240 errmsg = e_invarg;
1241 goto skip;
1242 }
1243 arg[len] = NUL; /* put NUL after name */
1244 if (arg[1] == 't' && arg[2] == '_') /* could be term code */
1245 opt_idx = findoption(arg + 1);
1246 arg[len++] = '>'; /* restore '>' */
1247 if (opt_idx == -1)
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02001248 key = find_key_option(arg + 1, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001249 }
1250 else
1251 {
1252 len = 0;
1253 /*
1254 * The two characters after "t_" may not be alphanumeric.
1255 */
1256 if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
1257 len = 4;
1258 else
1259 while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
1260 ++len;
1261 nextchar = arg[len];
1262 arg[len] = NUL; /* put NUL after name */
1263 opt_idx = findoption(arg);
1264 arg[len] = nextchar; /* restore nextchar */
1265 if (opt_idx == -1)
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02001266 key = find_key_option(arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267 }
1268
1269 /* remember character after option name */
1270 afterchar = arg[len];
1271
1272 /* skip white space, allow ":set ai ?" */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001273 while (VIM_ISWHITE(arg[len]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274 ++len;
1275
1276 adding = FALSE;
1277 prepending = FALSE;
1278 removing = FALSE;
1279 if (arg[len] != NUL && arg[len + 1] == '=')
1280 {
1281 if (arg[len] == '+')
1282 {
1283 adding = TRUE; /* "+=" */
1284 ++len;
1285 }
1286 else if (arg[len] == '^')
1287 {
1288 prepending = TRUE; /* "^=" */
1289 ++len;
1290 }
1291 else if (arg[len] == '-')
1292 {
1293 removing = TRUE; /* "-=" */
1294 ++len;
1295 }
1296 }
1297 nextchar = arg[len];
1298
1299 if (opt_idx == -1 && key == 0) /* found a mismatch: skip */
1300 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001301 errmsg = N_("E518: Unknown option");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302 goto skip;
1303 }
1304
1305 if (opt_idx >= 0)
1306 {
1307 if (options[opt_idx].var == NULL) /* hidden option: skip */
1308 {
1309 /* Only give an error message when requesting the value of
1310 * a hidden option, ignore setting it. */
1311 if (vim_strchr((char_u *)"=:!&<", nextchar) == NULL
1312 && (!(options[opt_idx].flags & P_BOOL)
1313 || nextchar == '?'))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001314 errmsg = N_("E519: Option not supported");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315 goto skip;
1316 }
1317
1318 flags = options[opt_idx].flags;
1319 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
1320 }
1321 else
1322 {
1323 flags = P_STRING;
1324 if (key < 0)
1325 {
1326 key_name[0] = KEY2TERMCAP0(key);
1327 key_name[1] = KEY2TERMCAP1(key);
1328 }
1329 else
1330 {
1331 key_name[0] = KS_KEY;
1332 key_name[1] = (key & 0xff);
1333 }
1334 }
1335
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001336 /* Skip all options that are not window-local (used when showing
1337 * an already loaded buffer in a window). */
1338 if ((opt_flags & OPT_WINONLY)
1339 && (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
1340 goto skip;
1341
Bram Moolenaara3227e22006-03-08 21:32:40 +00001342 /* Skip all options that are window-local (used for :vimgrep). */
1343 if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
1344 && options[opt_idx].var == VAR_WIN)
1345 goto skip;
1346
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001347 /* Disallow changing some options from modelines. */
1348 if (opt_flags & OPT_MODELINE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001349 {
Bram Moolenaar865242e2010-07-14 21:12:05 +02001350 if (flags & (P_SECURE | P_NO_ML))
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001351 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001352 errmsg = _("E520: Not allowed in a modeline");
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001353 goto skip;
1354 }
Bram Moolenaar110289e2019-05-23 15:38:06 +02001355 if ((flags & P_MLE) && !p_mle)
1356 {
1357 errmsg = _("E992: Not allowed in a modeline when 'modelineexpr' is off");
1358 goto skip;
1359 }
Bram Moolenaarf69d9a32009-02-11 21:48:40 +00001360#ifdef FEAT_DIFF
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001361 /* In diff mode some options are overruled. This avoids that
1362 * 'foldmethod' becomes "marker" instead of "diff" and that
1363 * "wrap" gets set. */
1364 if (curwin->w_p_diff
Bram Moolenaara9d52e32010-07-31 16:44:19 +02001365 && opt_idx >= 0 /* shut up coverity warning */
Bram Moolenaara6c07602017-03-05 21:18:27 +01001366 && (
1367#ifdef FEAT_FOLDING
1368 options[opt_idx].indir == PV_FDM ||
1369#endif
1370 options[opt_idx].indir == PV_WRAP))
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001371 goto skip;
Bram Moolenaarf69d9a32009-02-11 21:48:40 +00001372#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373 }
1374
1375#ifdef HAVE_SANDBOX
1376 /* Disallow changing some options in the sandbox */
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001377 if (sandbox != 0 && (flags & P_SECURE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001378 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001379 errmsg = _(e_sandbox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001380 goto skip;
1381 }
1382#endif
1383
1384 if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
1385 {
1386 arg += len;
1387 cp_val = p_cp;
1388 if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i')
1389 {
1390 if (arg[3] == 'm') /* "opt&vim": set to Vim default */
1391 {
1392 cp_val = FALSE;
1393 arg += 3;
1394 }
1395 else /* "opt&vi": set to Vi default */
1396 {
1397 cp_val = TRUE;
1398 arg += 2;
1399 }
1400 }
1401 if (vim_strchr((char_u *)"?!&<", nextchar) != NULL
Bram Moolenaar1c465442017-03-12 20:10:05 +01001402 && arg[1] != NUL && !VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001403 {
1404 errmsg = e_trailing;
1405 goto skip;
1406 }
1407 }
1408
1409 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +01001410 * allow '=' and ':' for hystorical reasons (MSDOS command.com
1411 * allows only one '=' character per "set" command line. grrr. (jw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001412 */
1413 if (nextchar == '?'
1414 || (prefix == 1
1415 && vim_strchr((char_u *)"=:&<", nextchar) == NULL
1416 && !(flags & P_BOOL)))
1417 {
1418 /*
1419 * print value
1420 */
1421 if (did_show)
1422 msg_putchar('\n'); /* cursor below last one */
1423 else
1424 {
1425 gotocmdline(TRUE); /* cursor at status line */
1426 did_show = TRUE; /* remember that we did a line */
1427 }
1428 if (opt_idx >= 0)
1429 {
1430 showoneopt(&options[opt_idx], opt_flags);
1431#ifdef FEAT_EVAL
1432 if (p_verbose > 0)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001433 {
1434 /* Mention where the option was last set. */
1435 if (varp == options[opt_idx].var)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001436 last_set_msg(options[opt_idx].script_ctx);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001437 else if ((int)options[opt_idx].indir & PV_WIN)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001438 last_set_msg(curwin->w_p_script_ctx[
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001439 (int)options[opt_idx].indir & PV_MASK]);
1440 else if ((int)options[opt_idx].indir & PV_BUF)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001441 last_set_msg(curbuf->b_p_script_ctx[
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001442 (int)options[opt_idx].indir & PV_MASK]);
1443 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001444#endif
1445 }
1446 else
1447 {
1448 char_u *p;
1449
1450 p = find_termcode(key_name);
1451 if (p == NULL)
1452 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001453 errmsg = N_("E846: Key code not set");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001454 goto skip;
1455 }
1456 else
1457 (void)show_one_termcode(key_name, p, TRUE);
1458 }
1459 if (nextchar != '?'
Bram Moolenaar1c465442017-03-12 20:10:05 +01001460 && nextchar != NUL && !VIM_ISWHITE(afterchar))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001461 errmsg = e_trailing;
1462 }
1463 else
1464 {
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01001465 int value_is_replaced = !prepending && !adding && !removing;
Bram Moolenaar916a8182018-11-25 02:18:29 +01001466 int value_checked = FALSE;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01001467
Bram Moolenaar071d4272004-06-13 20:20:40 +00001468 if (flags & P_BOOL) /* boolean */
1469 {
1470 if (nextchar == '=' || nextchar == ':')
1471 {
1472 errmsg = e_invarg;
1473 goto skip;
1474 }
1475
1476 /*
1477 * ":set opt!": invert
1478 * ":set opt&": reset to default value
1479 * ":set opt<": reset to global value
1480 */
1481 if (nextchar == '!')
1482 value = *(int *)(varp) ^ 1;
1483 else if (nextchar == '&')
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001484 value = (int)(long)(long_i)options[opt_idx].def_val[
Bram Moolenaar071d4272004-06-13 20:20:40 +00001485 ((flags & P_VI_DEF) || cp_val)
1486 ? VI_DEFAULT : VIM_DEFAULT];
1487 else if (nextchar == '<')
1488 {
1489 /* For 'autoread' -1 means to use global value. */
1490 if ((int *)varp == &curbuf->b_p_ar
1491 && opt_flags == OPT_LOCAL)
1492 value = -1;
1493 else
1494 value = *(int *)get_varp_scope(&(options[opt_idx]),
1495 OPT_GLOBAL);
1496 }
1497 else
1498 {
1499 /*
1500 * ":set invopt": invert
1501 * ":set opt" or ":set noopt": set or reset
1502 */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001503 if (nextchar != NUL && !VIM_ISWHITE(afterchar))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001504 {
1505 errmsg = e_trailing;
1506 goto skip;
1507 }
1508 if (prefix == 2) /* inv */
1509 value = *(int *)(varp) ^ 1;
1510 else
1511 value = prefix;
1512 }
1513
1514 errmsg = set_bool_option(opt_idx, varp, (int)value,
1515 opt_flags);
1516 }
1517 else /* numeric or string */
1518 {
1519 if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
1520 || prefix != 1)
1521 {
1522 errmsg = e_invarg;
1523 goto skip;
1524 }
1525
1526 if (flags & P_NUM) /* numeric */
1527 {
1528 /*
1529 * Different ways to set a number option:
1530 * & set to default value
1531 * < set to global value
1532 * <xx> accept special key codes for 'wildchar'
1533 * c accept any non-digit for 'wildchar'
1534 * [-]0-9 set number
1535 * other error
1536 */
1537 ++arg;
1538 if (nextchar == '&')
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001539 value = (long)(long_i)options[opt_idx].def_val[
Bram Moolenaar071d4272004-06-13 20:20:40 +00001540 ((flags & P_VI_DEF) || cp_val)
1541 ? VI_DEFAULT : VIM_DEFAULT];
1542 else if (nextchar == '<')
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01001543 {
1544 /* For 'undolevels' NO_LOCAL_UNDOLEVEL means to
1545 * use the global value. */
1546 if ((long *)varp == &curbuf->b_p_ul
1547 && opt_flags == OPT_LOCAL)
1548 value = NO_LOCAL_UNDOLEVEL;
1549 else
1550 value = *(long *)get_varp_scope(
1551 &(options[opt_idx]), OPT_GLOBAL);
1552 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001553 else if (((long *)varp == &p_wc
1554 || (long *)varp == &p_wcm)
1555 && (*arg == '<'
1556 || *arg == '^'
Bram Moolenaar1c465442017-03-12 20:10:05 +01001557 || (*arg != NUL
1558 && (!arg[1] || VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001559 && !VIM_ISDIGIT(*arg))))
1560 {
Bram Moolenaardbe948d2017-07-23 22:50:51 +02001561 value = string_to_key(arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001562 if (value == 0 && (long *)varp != &p_wcm)
1563 {
1564 errmsg = e_invarg;
1565 goto skip;
1566 }
1567 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001568 else if (*arg == '-' || VIM_ISDIGIT(*arg))
1569 {
Bram Moolenaar18400e62015-01-27 15:58:40 +01001570 /* Allow negative (for 'undolevels'), octal and
1571 * hex numbers. */
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001572 vim_str2nr(arg, NULL, &i, STR2NR_ALL,
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001573 &value, NULL, 0, TRUE);
Bram Moolenaar06e2c812019-06-12 19:05:48 +02001574 if (i == 0 || (arg[i] != NUL
1575 && !VIM_ISWHITE(arg[i])))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001576 {
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001577 errmsg = N_("E521: Number required after =");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001578 goto skip;
1579 }
1580 }
1581 else
1582 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001583 errmsg = N_("E521: Number required after =");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001584 goto skip;
1585 }
1586
1587 if (adding)
1588 value = *(long *)varp + value;
1589 if (prepending)
1590 value = *(long *)varp * value;
1591 if (removing)
1592 value = *(long *)varp - value;
1593 errmsg = set_num_option(opt_idx, varp, value,
Bram Moolenaar555b2802005-05-19 21:08:39 +00001594 errbuf, sizeof(errbuf), opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001595 }
1596 else if (opt_idx >= 0) /* string */
1597 {
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001598 char_u *save_arg = NULL;
1599 char_u *s = NULL;
1600 char_u *oldval = NULL; /* previous value if *varp */
1601 char_u *newval;
1602 char_u *origval = NULL;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001603 char_u *origval_l = NULL;
1604 char_u *origval_g = NULL;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001605#if defined(FEAT_EVAL)
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001606 char_u *saved_origval = NULL;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001607 char_u *saved_origval_l = NULL;
1608 char_u *saved_origval_g = NULL;
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001609 char_u *saved_newval = NULL;
Bram Moolenaar53744302015-07-17 17:38:22 +02001610#endif
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001611 unsigned newlen;
1612 int comma;
1613 int bs;
1614 int new_value_alloced; /* new string option
Bram Moolenaar071d4272004-06-13 20:20:40 +00001615 was allocated */
1616
1617 /* When using ":set opt=val" for a global option
1618 * with a local value the local value will be
1619 * reset, use the global value here. */
1620 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001621 && ((int)options[opt_idx].indir & PV_BOTH))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001622 varp = options[opt_idx].var;
1623
1624 /* The old value is kept until we are sure that the
1625 * new value is valid. */
1626 oldval = *(char_u **)varp;
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001627
Bram Moolenaard7c96872019-06-15 17:12:48 +02001628 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1629 {
1630 origval_l = *(char_u **)get_varp_scope(
1631 &(options[opt_idx]), OPT_LOCAL);
1632 origval_g = *(char_u **)get_varp_scope(
1633 &(options[opt_idx]), OPT_GLOBAL);
1634
1635 // A global-local string option might have an empty
1636 // option as value to indicate that the global
1637 // value should be used.
1638 if (((int)options[opt_idx].indir & PV_BOTH)
1639 && origval_l == empty_option)
1640 origval_l = origval_g;
1641 }
1642
1643 // When setting the local value of a global
1644 // option, the old value may be the global value.
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001645 if (((int)options[opt_idx].indir & PV_BOTH)
1646 && (opt_flags & OPT_LOCAL))
1647 origval = *(char_u **)get_varp(
1648 &options[opt_idx]);
1649 else
1650 origval = oldval;
1651
Bram Moolenaar071d4272004-06-13 20:20:40 +00001652 if (nextchar == '&') /* set to default val */
1653 {
1654 newval = options[opt_idx].def_val[
1655 ((flags & P_VI_DEF) || cp_val)
1656 ? VI_DEFAULT : VIM_DEFAULT];
1657 if ((char_u **)varp == &p_bg)
1658 {
1659 /* guess the value of 'background' */
1660#ifdef FEAT_GUI
1661 if (gui.in_use)
1662 newval = gui_bg_default();
1663 else
1664#endif
Bram Moolenaarf740b292006-02-16 22:11:02 +00001665 newval = term_bg_default();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001666 }
1667
1668 /* expand environment variables and ~ (since the
1669 * default value was already expanded, only
1670 * required when an environment variable was set
1671 * later */
1672 if (newval == NULL)
1673 newval = empty_option;
1674 else
1675 {
1676 s = option_expand(opt_idx, newval);
1677 if (s == NULL)
1678 s = newval;
1679 newval = vim_strsave(s);
1680 }
1681 new_value_alloced = TRUE;
1682 }
1683 else if (nextchar == '<') /* set to global val */
1684 {
1685 newval = vim_strsave(*(char_u **)get_varp_scope(
1686 &(options[opt_idx]), OPT_GLOBAL));
1687 new_value_alloced = TRUE;
1688 }
1689 else
1690 {
1691 ++arg; /* jump to after the '=' or ':' */
1692
1693 /*
1694 * Set 'keywordprg' to ":help" if an empty
1695 * value was passed to :set by the user.
1696 * Misuse errbuf[] for the resulting string.
1697 */
1698 if (varp == (char_u *)&p_kp
1699 && (*arg == NUL || *arg == ' '))
1700 {
1701 STRCPY(errbuf, ":help");
1702 save_arg = arg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001703 arg = (char_u *)errbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001704 }
1705 /*
Bram Moolenaar4e5ccfa2011-11-30 11:15:47 +01001706 * Convert 'backspace' number to string, for
1707 * adding, prepending and removing string.
1708 */
1709 else if (varp == (char_u *)&p_bs
1710 && VIM_ISDIGIT(**(char_u **)varp))
1711 {
1712 i = getdigits((char_u **)varp);
1713 switch (i)
1714 {
1715 case 0:
1716 *(char_u **)varp = empty_option;
1717 break;
1718 case 1:
1719 *(char_u **)varp = vim_strsave(
1720 (char_u *)"indent,eol");
1721 break;
1722 case 2:
1723 *(char_u **)varp = vim_strsave(
1724 (char_u *)"indent,eol,start");
1725 break;
1726 }
1727 vim_free(oldval);
Bram Moolenaaredbc0d42017-08-20 16:11:51 +02001728 if (origval == oldval)
1729 origval = *(char_u **)varp;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001730 if (origval_l == oldval)
1731 origval_l = *(char_u **)varp;
1732 if (origval_g == oldval)
1733 origval_g = *(char_u **)varp;
Bram Moolenaar4e5ccfa2011-11-30 11:15:47 +01001734 oldval = *(char_u **)varp;
1735 }
1736 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 * Convert 'whichwrap' number to string, for
1738 * backwards compatibility with Vim 3.0.
1739 * Misuse errbuf[] for the resulting string.
1740 */
1741 else if (varp == (char_u *)&p_ww
1742 && VIM_ISDIGIT(*arg))
1743 {
1744 *errbuf = NUL;
1745 i = getdigits(&arg);
1746 if (i & 1)
1747 STRCAT(errbuf, "b,");
1748 if (i & 2)
1749 STRCAT(errbuf, "s,");
1750 if (i & 4)
1751 STRCAT(errbuf, "h,l,");
1752 if (i & 8)
1753 STRCAT(errbuf, "<,>,");
1754 if (i & 16)
1755 STRCAT(errbuf, "[,],");
1756 if (*errbuf != NUL) /* remove trailing , */
1757 errbuf[STRLEN(errbuf) - 1] = NUL;
1758 save_arg = arg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001759 arg = (char_u *)errbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001760 }
1761 /*
1762 * Remove '>' before 'dir' and 'bdir', for
1763 * backwards compatibility with version 3.0
1764 */
1765 else if ( *arg == '>'
1766 && (varp == (char_u *)&p_dir
1767 || varp == (char_u *)&p_bdir))
1768 {
1769 ++arg;
1770 }
1771
Bram Moolenaar071d4272004-06-13 20:20:40 +00001772 /*
1773 * Copy the new string into allocated memory.
1774 * Can't use set_string_option_direct(), because
1775 * we need to remove the backslashes.
1776 */
1777 /* get a bit too much */
1778 newlen = (unsigned)STRLEN(arg) + 1;
1779 if (adding || prepending || removing)
1780 newlen += (unsigned)STRLEN(origval) + 1;
1781 newval = alloc(newlen);
1782 if (newval == NULL) /* out of mem, don't change */
1783 break;
1784 s = newval;
1785
1786 /*
1787 * Copy the string, skip over escaped chars.
1788 * For MS-DOS and WIN32 backslashes before normal
1789 * file name characters are not removed, and keep
1790 * backslash at start, for "\\machine\path", but
1791 * do remove it for "\\\\machine\\path".
1792 * The reverse is found in ExpandOldSetting().
1793 */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001794 while (*arg && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795 {
1796 if (*arg == '\\' && arg[1] != NUL
1797#ifdef BACKSLASH_IN_FILENAME
1798 && !((flags & P_EXPAND)
1799 && vim_isfilec(arg[1])
1800 && (arg[1] != '\\'
1801 || (s == newval
1802 && arg[2] != '\\')))
1803#endif
1804 )
1805 ++arg; /* remove backslash */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001806 if (has_mbyte
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00001807 && (i = (*mb_ptr2len)(arg)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001808 {
1809 /* copy multibyte char */
1810 mch_memmove(s, arg, (size_t)i);
1811 arg += i;
1812 s += i;
1813 }
1814 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001815 *s++ = *arg++;
1816 }
1817 *s = NUL;
1818
1819 /*
1820 * Expand environment variables and ~.
1821 * Don't do it when adding without inserting a
1822 * comma.
1823 */
1824 if (!(adding || prepending || removing)
1825 || (flags & P_COMMA))
1826 {
1827 s = option_expand(opt_idx, newval);
1828 if (s != NULL)
1829 {
1830 vim_free(newval);
1831 newlen = (unsigned)STRLEN(s) + 1;
1832 if (adding || prepending || removing)
1833 newlen += (unsigned)STRLEN(origval) + 1;
1834 newval = alloc(newlen);
1835 if (newval == NULL)
1836 break;
1837 STRCPY(newval, s);
1838 }
1839 }
1840
1841 /* locate newval[] in origval[] when removing it
1842 * and when adding to avoid duplicates */
1843 i = 0; /* init for GCC */
1844 if (removing || (flags & P_NODUP))
1845 {
1846 i = (int)STRLEN(newval);
1847 bs = 0;
1848 for (s = origval; *s; ++s)
1849 {
1850 if ((!(flags & P_COMMA)
1851 || s == origval
1852 || (s[-1] == ',' && !(bs & 1)))
1853 && STRNCMP(s, newval, i) == 0
1854 && (!(flags & P_COMMA)
1855 || s[i] == ','
1856 || s[i] == NUL))
1857 break;
Bram Moolenaar0b2f94d2011-03-22 14:35:05 +01001858 /* Count backslashes. Only a comma with an
Bram Moolenaar8f79acd2016-01-01 14:48:20 +01001859 * even number of backslashes or a single
1860 * backslash preceded by a comma before it
1861 * is recognized as a separator */
1862 if ((s > origval + 1
1863 && s[-1] == '\\'
1864 && s[-2] != ',')
1865 || (s == origval + 1
1866 && s[-1] == '\\'))
1867
Bram Moolenaar071d4272004-06-13 20:20:40 +00001868 ++bs;
1869 else
1870 bs = 0;
1871 }
1872
1873 /* do not add if already there */
1874 if ((adding || prepending) && *s)
1875 {
1876 prepending = FALSE;
1877 adding = FALSE;
1878 STRCPY(newval, origval);
1879 }
1880 }
1881
1882 /* concatenate the two strings; add a ',' if
1883 * needed */
1884 if (adding || prepending)
1885 {
1886 comma = ((flags & P_COMMA) && *origval != NUL
1887 && *newval != NUL);
1888 if (adding)
1889 {
1890 i = (int)STRLEN(origval);
Bram Moolenaara7b7b1c2015-06-19 14:06:43 +02001891 /* strip a trailing comma, would get 2 */
Bram Moolenaar17467472015-11-10 17:50:24 +01001892 if (comma && i > 1
1893 && (flags & P_ONECOMMA) == P_ONECOMMA
1894 && origval[i - 1] == ','
1895 && origval[i - 2] != '\\')
Bram Moolenaara7b7b1c2015-06-19 14:06:43 +02001896 i--;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001897 mch_memmove(newval + i + comma, newval,
1898 STRLEN(newval) + 1);
1899 mch_memmove(newval, origval, (size_t)i);
1900 }
1901 else
1902 {
1903 i = (int)STRLEN(newval);
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00001904 STRMOVE(newval + i + comma, origval);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001905 }
1906 if (comma)
1907 newval[i] = ',';
1908 }
1909
1910 /* Remove newval[] from origval[]. (Note: "i" has
1911 * been set above and is used here). */
1912 if (removing)
1913 {
1914 STRCPY(newval, origval);
1915 if (*s)
1916 {
1917 /* may need to remove a comma */
1918 if (flags & P_COMMA)
1919 {
1920 if (s == origval)
1921 {
1922 /* include comma after string */
1923 if (s[i] == ',')
1924 ++i;
1925 }
1926 else
1927 {
1928 /* include comma before string */
1929 --s;
1930 ++i;
1931 }
1932 }
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00001933 STRMOVE(newval + (s - origval), s + i);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001934 }
1935 }
1936
1937 if (flags & P_FLAGLIST)
1938 {
1939 /* Remove flags that appear twice. */
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01001940 for (s = newval; *s;)
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001941 {
1942 /* if options have P_FLAGLIST and
1943 * P_ONECOMMA such as 'whichwrap' */
1944 if (flags & P_ONECOMMA)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001945 {
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001946 if (*s != ',' && *(s + 1) == ','
1947 && vim_strchr(s + 2, *s) != NULL)
1948 {
1949 /* Remove the duplicated value and
1950 * the next comma. */
1951 STRMOVE(s, s + 2);
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01001952 continue;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001953 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001954 }
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001955 else
1956 {
1957 if ((!(flags & P_COMMA) || *s != ',')
1958 && vim_strchr(s + 1, *s) != NULL)
1959 {
1960 STRMOVE(s, s + 1);
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01001961 continue;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001962 }
1963 }
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01001964 ++s;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02001965 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001966 }
1967
1968 if (save_arg != NULL) /* number for 'whichwrap' */
1969 arg = save_arg;
1970 new_value_alloced = TRUE;
1971 }
1972
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001973 /*
1974 * Set the new value.
1975 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001976 *(char_u **)(varp) = newval;
1977
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001978#if defined(FEAT_EVAL)
Bram Moolenaar5cbb8db2015-07-17 23:08:29 +02001979 if (!starting
1980# ifdef FEAT_CRYPT
1981 && options[opt_idx].indir != PV_KEY
1982# endif
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001983 && origval != NULL && newval != NULL)
1984 {
Bram Moolenaar53744302015-07-17 17:38:22 +02001985 /* origval may be freed by
1986 * did_set_string_option(), make a copy. */
1987 saved_origval = vim_strsave(origval);
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001988 /* newval (and varp) may become invalid if the
1989 * buffer is closed by autocommands. */
1990 saved_newval = vim_strsave(newval);
Bram Moolenaard7c96872019-06-15 17:12:48 +02001991 if (origval_l != NULL)
1992 saved_origval_l = vim_strsave(origval_l);
1993 if (origval_g != NULL)
1994 saved_origval_g = vim_strsave(origval_g);
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001995 }
Bram Moolenaar53744302015-07-17 17:38:22 +02001996#endif
1997
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01001998 {
1999 long_u *p = insecure_flag(opt_idx, opt_flags);
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002000 int secure_saved = secure;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002001
2002 // When an option is set in the sandbox, from a
2003 // modeline or in secure mode, then deal with side
2004 // effects in secure mode. Also when the value was
2005 // set with the P_INSECURE flag and is not
2006 // completely replaced.
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002007 if ((opt_flags & OPT_MODELINE)
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002008#ifdef HAVE_SANDBOX
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002009 || sandbox != 0
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002010#endif
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002011 || (!value_is_replaced && (*p & P_INSECURE)))
2012 secure = 1;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002013
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002014 // Handle side effects, and set the global value
2015 // for ":set" on local options. Note: when setting
2016 // 'syntax' or 'filetype' autocommands may be
2017 // triggered that can cause havoc.
2018 errmsg = did_set_string_option(
2019 opt_idx, (char_u **)varp,
Bram Moolenaar916a8182018-11-25 02:18:29 +01002020 new_value_alloced, oldval, errbuf,
2021 opt_flags, &value_checked);
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002022
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002023 secure = secure_saved;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002024 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002025
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01002026#if defined(FEAT_EVAL)
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002027 if (errmsg == NULL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002028 trigger_optionsset_string(
2029 opt_idx, opt_flags, saved_origval,
2030 saved_origval_l, saved_origval_g,
2031 saved_newval);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002032 vim_free(saved_origval);
Bram Moolenaard7c96872019-06-15 17:12:48 +02002033 vim_free(saved_origval_l);
2034 vim_free(saved_origval_g);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002035 vim_free(saved_newval);
2036#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002037 /* If error detected, print the error message. */
2038 if (errmsg != NULL)
2039 goto skip;
2040 }
2041 else /* key code option */
2042 {
2043 char_u *p;
2044
2045 if (nextchar == '&')
2046 {
2047 if (add_termcap_entry(key_name, TRUE) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002048 errmsg = N_("E522: Not found in termcap");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002049 }
2050 else
2051 {
2052 ++arg; /* jump to after the '=' or ':' */
Bram Moolenaar1c465442017-03-12 20:10:05 +01002053 for (p = arg; *p && !VIM_ISWHITE(*p); ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002054 if (*p == '\\' && p[1] != NUL)
2055 ++p;
2056 nextchar = *p;
2057 *p = NUL;
2058 add_termcode(key_name, arg, FALSE);
2059 *p = nextchar;
2060 }
2061 if (full_screen)
2062 ttest(FALSE);
2063 redraw_all_later(CLEAR);
2064 }
2065 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002066
Bram Moolenaar071d4272004-06-13 20:20:40 +00002067 if (opt_idx >= 0)
Bram Moolenaar916a8182018-11-25 02:18:29 +01002068 did_set_option(
2069 opt_idx, opt_flags, value_is_replaced, value_checked);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002070 }
2071
2072skip:
2073 /*
2074 * Advance to next argument.
2075 * - skip until a blank found, taking care of backslashes
2076 * - skip blanks
2077 * - skip one "=val" argument (for hidden options ":set gfn =xx")
2078 */
2079 for (i = 0; i < 2 ; ++i)
2080 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01002081 while (*arg != NUL && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002082 if (*arg++ == '\\' && *arg != NUL)
2083 ++arg;
2084 arg = skipwhite(arg);
2085 if (*arg != '=')
2086 break;
2087 }
2088 }
2089
2090 if (errmsg != NULL)
2091 {
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002092 vim_strncpy(IObuff, (char_u *)_(errmsg), IOSIZE - 1);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002093 i = (int)STRLEN(IObuff) + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002094 if (i + (arg - startarg) < IOSIZE)
2095 {
2096 /* append the argument with the error */
2097 STRCAT(IObuff, ": ");
2098 mch_memmove(IObuff + i, startarg, (arg - startarg));
2099 IObuff[i + (arg - startarg)] = NUL;
2100 }
2101 /* make sure all characters are printable */
2102 trans_characters(IObuff, IOSIZE);
2103
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002104 ++no_wait_return; // wait_return done later
2105 emsg((char *)IObuff); // show error highlighted
Bram Moolenaar071d4272004-06-13 20:20:40 +00002106 --no_wait_return;
2107
2108 return FAIL;
2109 }
2110
2111 arg = skipwhite(arg);
2112 }
2113
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002114theend:
2115 if (silent_mode && did_show)
2116 {
2117 /* After displaying option values in silent mode. */
2118 silent_mode = FALSE;
2119 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
2120 msg_putchar('\n');
2121 cursor_on(); /* msg_start() switches it off */
2122 out_flush();
2123 silent_mode = TRUE;
2124 info_message = FALSE; /* use mch_msg(), not mch_errmsg() */
2125 }
2126
Bram Moolenaar071d4272004-06-13 20:20:40 +00002127 return OK;
2128}
2129
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002130/*
2131 * Call this when an option has been given a new value through a user command.
2132 * Sets the P_WAS_SET flag and takes care of the P_INSECURE flag.
2133 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002134 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002135did_set_option(
2136 int opt_idx,
Bram Moolenaar916a8182018-11-25 02:18:29 +01002137 int opt_flags, // possibly with OPT_MODELINE
2138 int new_value, // value was replaced completely
2139 int value_checked) // value was checked to be safe, no need to set the
2140 // P_INSECURE flag.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002141{
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002142 long_u *p;
2143
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002144 options[opt_idx].flags |= P_WAS_SET;
2145
2146 /* When an option is set in the sandbox, from a modeline or in secure mode
2147 * set the P_INSECURE flag. Otherwise, if a new value is stored reset the
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002148 * flag. */
2149 p = insecure_flag(opt_idx, opt_flags);
Bram Moolenaar916a8182018-11-25 02:18:29 +01002150 if (!value_checked && (secure
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002151#ifdef HAVE_SANDBOX
2152 || sandbox != 0
2153#endif
Bram Moolenaar916a8182018-11-25 02:18:29 +01002154 || (opt_flags & OPT_MODELINE)))
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002155 *p = *p | P_INSECURE;
2156 else if (new_value)
2157 *p = *p & ~P_INSECURE;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002158}
2159
Bram Moolenaar071d4272004-06-13 20:20:40 +00002160/*
2161 * Convert a key name or string into a key value.
2162 * Used for 'wildchar' and 'cedit' options.
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002163 * When "multi_byte" is TRUE allow for multi-byte characters.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002164 */
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002165 int
2166string_to_key(char_u *arg, int multi_byte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002167{
2168 if (*arg == '<')
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02002169 return find_key_option(arg + 1, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002170 if (*arg == '^')
2171 return Ctrl_chr(arg[1]);
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002172 if (multi_byte)
2173 return PTR2CHAR(arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002174 return *arg;
2175}
2176
Bram Moolenaardac13472019-09-16 21:06:21 +02002177#if defined(FEAT_CMDWIN) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002178/*
2179 * Check value of 'cedit' and set cedit_key.
2180 * Returns NULL if value is OK, error message otherwise.
2181 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002182 char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002183check_cedit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002184{
2185 int n;
2186
2187 if (*p_cedit == NUL)
2188 cedit_key = -1;
2189 else
2190 {
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002191 n = string_to_key(p_cedit, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002192 if (vim_isprintc(n))
2193 return e_invarg;
2194 cedit_key = n;
2195 }
2196 return NULL;
2197}
2198#endif
2199
2200#ifdef FEAT_TITLE
2201/*
2202 * When changing 'title', 'titlestring', 'icon' or 'iconstring', call
2203 * maketitle() to create and display it.
2204 * When switching the title or icon off, call mch_restore_title() to get
2205 * the old value back.
2206 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002207 void
Bram Moolenaar84a93082018-06-16 22:58:15 +02002208did_set_title(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002209{
2210 if (starting != NO_SCREEN
2211#ifdef FEAT_GUI
2212 && !gui.starting
2213#endif
2214 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002215 maketitle();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002216}
2217#endif
2218
2219/*
2220 * set_options_bin - called when 'bin' changes value.
2221 */
2222 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002223set_options_bin(
2224 int oldval,
2225 int newval,
2226 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227{
2228 /*
2229 * The option values that are changed when 'bin' changes are
2230 * copied when 'bin is set and restored when 'bin' is reset.
2231 */
2232 if (newval)
2233 {
2234 if (!oldval) /* switched on */
2235 {
2236 if (!(opt_flags & OPT_GLOBAL))
2237 {
2238 curbuf->b_p_tw_nobin = curbuf->b_p_tw;
2239 curbuf->b_p_wm_nobin = curbuf->b_p_wm;
2240 curbuf->b_p_ml_nobin = curbuf->b_p_ml;
2241 curbuf->b_p_et_nobin = curbuf->b_p_et;
2242 }
2243 if (!(opt_flags & OPT_LOCAL))
2244 {
2245 p_tw_nobin = p_tw;
2246 p_wm_nobin = p_wm;
2247 p_ml_nobin = p_ml;
2248 p_et_nobin = p_et;
2249 }
2250 }
2251
2252 if (!(opt_flags & OPT_GLOBAL))
2253 {
2254 curbuf->b_p_tw = 0; /* no automatic line wrap */
2255 curbuf->b_p_wm = 0; /* no automatic line wrap */
2256 curbuf->b_p_ml = 0; /* no modelines */
2257 curbuf->b_p_et = 0; /* no expandtab */
2258 }
2259 if (!(opt_flags & OPT_LOCAL))
2260 {
2261 p_tw = 0;
2262 p_wm = 0;
2263 p_ml = FALSE;
2264 p_et = FALSE;
2265 p_bin = TRUE; /* needed when called for the "-b" argument */
2266 }
2267 }
2268 else if (oldval) /* switched off */
2269 {
2270 if (!(opt_flags & OPT_GLOBAL))
2271 {
2272 curbuf->b_p_tw = curbuf->b_p_tw_nobin;
2273 curbuf->b_p_wm = curbuf->b_p_wm_nobin;
2274 curbuf->b_p_ml = curbuf->b_p_ml_nobin;
2275 curbuf->b_p_et = curbuf->b_p_et_nobin;
2276 }
2277 if (!(opt_flags & OPT_LOCAL))
2278 {
2279 p_tw = p_tw_nobin;
2280 p_wm = p_wm_nobin;
2281 p_ml = p_ml_nobin;
2282 p_et = p_et_nobin;
2283 }
2284 }
2285}
2286
Bram Moolenaar071d4272004-06-13 20:20:40 +00002287/*
2288 * Expand environment variables for some string options.
2289 * These string options cannot be indirect!
2290 * If "val" is NULL expand the current value of the option.
2291 * Return pointer to NameBuff, or NULL when not expanded.
2292 */
2293 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002294option_expand(int opt_idx, char_u *val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002295{
2296 /* if option doesn't need expansion nothing to do */
2297 if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL)
2298 return NULL;
2299
2300 /* If val is longer than MAXPATHL no meaningful expansion can be done,
2301 * expand_env() would truncate the string. */
2302 if (val != NULL && STRLEN(val) > MAXPATHL)
2303 return NULL;
2304
2305 if (val == NULL)
2306 val = *(char_u **)options[opt_idx].var;
2307
2308 /*
2309 * Expanding this with NameBuff, expand_env() must not be passed IObuff.
2310 * Escape spaces when expanding 'tags', they are used to separate file
2311 * names.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002312 * For 'spellsuggest' expand after "file:".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002313 */
2314 expand_env_esc(val, NameBuff, MAXPATHL,
Bram Moolenaar9f0545d2007-09-26 20:36:32 +00002315 (char_u **)options[opt_idx].var == &p_tags, FALSE,
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002316#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002317 (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" :
2318#endif
2319 NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002320 if (STRCMP(NameBuff, val) == 0) /* they are the same */
2321 return NULL;
2322
2323 return NameBuff;
2324}
2325
2326/*
2327 * After setting various option values: recompute variables that depend on
2328 * option values.
2329 */
2330 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002331didset_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002332{
2333 /* initialize the table for 'iskeyword' et.al. */
2334 (void)init_chartab();
2335
Bram Moolenaardac13472019-09-16 21:06:21 +02002336 didset_string_options();
2337
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002338#ifdef FEAT_SPELL
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00002339 (void)spell_check_msm();
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002340 (void)spell_check_sps();
Bram Moolenaar860cae12010-06-05 23:22:07 +02002341 (void)compile_cap_prog(curwin->w_s);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002342 (void)did_set_spell_option(TRUE);
Bram Moolenaard857f0e2005-06-21 22:37:39 +00002343#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002344#ifdef FEAT_CMDWIN
Bram Moolenaar010ee962019-09-25 20:37:36 +02002345 // set cedit_key
Bram Moolenaar071d4272004-06-13 20:20:40 +00002346 (void)check_cedit();
2347#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02002348#ifdef FEAT_LINEBREAK
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002349 /* initialize the table for 'breakat'. */
2350 fill_breakat_flags();
2351#endif
Bram Moolenaar010ee962019-09-25 20:37:36 +02002352 after_copy_winopt(curwin);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002353}
2354
2355/*
2356 * More side effects of setting options.
2357 */
2358 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002359didset_options2(void)
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002360{
2361 /* Initialize the highlight_attr[] table. */
2362 (void)highlight_changed();
2363
2364 /* Parse default for 'wildmode' */
2365 check_opt_wim();
2366
2367 (void)set_chars_option(&p_lcs);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002368 /* Parse default for 'fillchars'. */
2369 (void)set_chars_option(&p_fcs);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002370
2371#ifdef FEAT_CLIPBOARD
2372 /* Parse default for 'clipboard' */
2373 (void)check_clipboard_option();
2374#endif
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002375#ifdef FEAT_VARTABS
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01002376 vim_free(curbuf->b_p_vsts_array);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002377 tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01002378 vim_free(curbuf->b_p_vts_array);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002379 tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
2380#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002381}
2382
2383/*
2384 * Check for string options that are NULL (normally only termcap options).
2385 */
2386 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002387check_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002388{
2389 int opt_idx;
2390
2391 for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++)
2392 if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL)
2393 check_string_option((char_u **)get_varp(&(options[opt_idx])));
2394}
2395
2396/*
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002397 * Return the option index found by a pointer into term_strings[].
2398 * Return -1 if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002399 */
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002400 int
2401get_term_opt_idx(char_u **p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002402{
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002403 int opt_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002404
2405 for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++)
2406 if (options[opt_idx].var == (char_u *)p)
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002407 return opt_idx;
2408 return -1; // cannot happen: didn't find it!
2409}
2410
2411/*
2412 * Mark a terminal option as allocated, found by a pointer into term_strings[].
2413 * Return the option index or -1 if not found.
2414 */
2415 int
2416set_term_option_alloced(char_u **p)
2417{
2418 int opt_idx = get_term_opt_idx(p);
2419
2420 if (opt_idx >= 0)
2421 options[opt_idx].flags |= P_ALLOCED;
2422 return opt_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002423}
2424
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002425#if defined(FEAT_EVAL) || defined(PROTO)
2426/*
2427 * Return TRUE when option "opt" was set from a modeline or in secure mode.
2428 * Return FALSE when it wasn't.
2429 * Return -1 for an unknown option.
2430 */
2431 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01002432was_set_insecurely(char_u *opt, int opt_flags)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002433{
2434 int idx = findoption(opt);
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002435 long_u *flagp;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002436
2437 if (idx >= 0)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002438 {
2439 flagp = insecure_flag(idx, opt_flags);
2440 return (*flagp & P_INSECURE) != 0;
2441 }
Bram Moolenaar95f09602016-11-10 20:01:45 +01002442 internal_error("was_set_insecurely()");
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002443 return -1;
2444}
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002445
2446/*
2447 * Get a pointer to the flags used for the P_INSECURE flag of option
2448 * "opt_idx". For some local options a local flags field is used.
2449 */
2450 static long_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002451insecure_flag(int opt_idx, int opt_flags)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002452{
2453 if (opt_flags & OPT_LOCAL)
2454 switch ((int)options[opt_idx].indir)
2455 {
2456#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002457 case PV_STL: return &curwin->w_p_stl_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002458#endif
2459#ifdef FEAT_EVAL
Bram Moolenaar2e978902006-05-13 12:37:50 +00002460# ifdef FEAT_FOLDING
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002461 case PV_FDE: return &curwin->w_p_fde_flags;
2462 case PV_FDT: return &curwin->w_p_fdt_flags;
Bram Moolenaar2e978902006-05-13 12:37:50 +00002463# endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00002464# ifdef FEAT_BEVAL
2465 case PV_BEXPR: return &curbuf->b_p_bexpr_flags;
2466# endif
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002467# if defined(FEAT_CINDENT)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002468 case PV_INDE: return &curbuf->b_p_inde_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002469# endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002470 case PV_FEX: return &curbuf->b_p_fex_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002471# ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002472 case PV_INEX: return &curbuf->b_p_inex_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002473# endif
2474#endif
2475 }
2476
2477 /* Nothing special, return global flags field. */
2478 return &options[opt_idx].flags;
2479}
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002480#endif
2481
Bram Moolenaardac13472019-09-16 21:06:21 +02002482#if defined(FEAT_TITLE) || defined(PROTO)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002483/*
2484 * Redraw the window title and/or tab page text later.
2485 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002486void redraw_titles(void)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002487{
2488 need_maketitle = TRUE;
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002489 redraw_tabline = TRUE;
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002490}
2491#endif
2492
Bram Moolenaar071d4272004-06-13 20:20:40 +00002493/*
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02002494 * Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
2495 * characters or characters in "allowed".
2496 */
Bram Moolenaare677df82019-09-02 22:31:11 +02002497 int
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02002498valid_name(char_u *val, char *allowed)
2499{
2500 char_u *s;
2501
2502 for (s = val; *s != NUL; ++s)
2503 if (!ASCII_ISALNUM(*s) && vim_strchr((char_u *)allowed, *s) == NULL)
2504 return FALSE;
2505 return TRUE;
2506}
2507
Bram Moolenaardac13472019-09-16 21:06:21 +02002508#if defined(FEAT_CLIPBOARD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002509/*
2510 * Extract the items in the 'clipboard' option and set global values.
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002511 * Return an error message or NULL for success.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002512 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002513 char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002514check_clipboard_option(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002515{
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01002516 int new_unnamed = 0;
Bram Moolenaar89af4392012-07-10 18:31:54 +02002517 int new_autoselect_star = FALSE;
2518 int new_autoselect_plus = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 int new_autoselectml = FALSE;
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00002520 int new_html = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002521 regprog_T *new_exclude_prog = NULL;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002522 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002523 char_u *p;
2524
2525 for (p = p_cb; *p != NUL; )
2526 {
2527 if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL))
2528 {
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01002529 new_unnamed |= CLIP_UNNAMED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002530 p += 7;
2531 }
Bram Moolenaar11b73d62012-06-29 15:51:30 +02002532 else if (STRNCMP(p, "unnamedplus", 11) == 0
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01002533 && (p[11] == ',' || p[11] == NUL))
2534 {
2535 new_unnamed |= CLIP_UNNAMED_PLUS;
2536 p += 11;
2537 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002538 else if (STRNCMP(p, "autoselect", 10) == 0
Bram Moolenaar89af4392012-07-10 18:31:54 +02002539 && (p[10] == ',' || p[10] == NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002540 {
Bram Moolenaar89af4392012-07-10 18:31:54 +02002541 new_autoselect_star = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542 p += 10;
2543 }
Bram Moolenaar89af4392012-07-10 18:31:54 +02002544 else if (STRNCMP(p, "autoselectplus", 14) == 0
2545 && (p[14] == ',' || p[14] == NUL))
2546 {
2547 new_autoselect_plus = TRUE;
2548 p += 14;
2549 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002550 else if (STRNCMP(p, "autoselectml", 12) == 0
Bram Moolenaar89af4392012-07-10 18:31:54 +02002551 && (p[12] == ',' || p[12] == NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002552 {
2553 new_autoselectml = TRUE;
2554 p += 12;
2555 }
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00002556 else if (STRNCMP(p, "html", 4) == 0 && (p[4] == ',' || p[4] == NUL))
2557 {
2558 new_html = TRUE;
2559 p += 4;
2560 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002561 else if (STRNCMP(p, "exclude:", 8) == 0 && new_exclude_prog == NULL)
2562 {
2563 p += 8;
2564 new_exclude_prog = vim_regcomp(p, RE_MAGIC);
2565 if (new_exclude_prog == NULL)
2566 errmsg = e_invarg;
2567 break;
2568 }
2569 else
2570 {
2571 errmsg = e_invarg;
2572 break;
2573 }
2574 if (*p == ',')
2575 ++p;
2576 }
2577 if (errmsg == NULL)
2578 {
2579 clip_unnamed = new_unnamed;
Bram Moolenaar89af4392012-07-10 18:31:54 +02002580 clip_autoselect_star = new_autoselect_star;
2581 clip_autoselect_plus = new_autoselect_plus;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002582 clip_autoselectml = new_autoselectml;
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00002583 clip_html = new_html;
Bram Moolenaar473de612013-06-08 18:19:48 +02002584 vim_regfree(clip_exclude_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002585 clip_exclude_prog = new_exclude_prog;
Bram Moolenaara76638f2010-06-05 12:49:46 +02002586#ifdef FEAT_GUI_GTK
2587 if (gui.in_use)
2588 {
2589 gui_gtk_set_selection_targets();
2590 gui_gtk_set_dnd_targets();
2591 }
2592#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002593 }
2594 else
Bram Moolenaar473de612013-06-08 18:19:48 +02002595 vim_regfree(new_exclude_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002596
2597 return errmsg;
2598}
2599#endif
2600
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002601#if defined(FEAT_EVAL) || defined(PROTO)
2602/*
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002603 * Set the script_ctx for an option, taking care of setting the buffer- or
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002604 * window-local value.
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002605 */
Bram Moolenaardac13472019-09-16 21:06:21 +02002606 void
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002607set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002608{
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002609 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
2610 int indir = (int)options[opt_idx].indir;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002611 sctx_T new_script_ctx = script_ctx;
2612
2613 new_script_ctx.sc_lnum += sourcing_lnum;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002614
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002615 /* Remember where the option was set. For local options need to do that
2616 * in the buffer or window structure. */
2617 if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002618 options[opt_idx].script_ctx = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002619 if (both || (opt_flags & OPT_LOCAL))
2620 {
2621 if (indir & PV_BUF)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002622 curbuf->b_p_script_ctx[indir & PV_MASK] = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002623 else if (indir & PV_WIN)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002624 curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002625 }
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002626}
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002627
2628/*
2629 * Set the script_ctx for a termcap option.
2630 * "name" must be the two character code, e.g. "RV".
2631 * When "name" is NULL use "opt_idx".
2632 */
2633 void
2634set_term_option_sctx_idx(char *name, int opt_idx)
2635{
2636 char_u buf[5];
2637 int idx;
2638
2639 if (name == NULL)
2640 idx = opt_idx;
2641 else
2642 {
2643 buf[0] = 't';
2644 buf[1] = '_';
2645 buf[2] = name[0];
2646 buf[3] = name[1];
2647 buf[4] = 0;
2648 idx = findoption(buf);
2649 }
2650 if (idx >= 0)
2651 set_option_sctx_idx(idx, OPT_GLOBAL, current_sctx);
2652}
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002653#endif
2654
Bram Moolenaar071d4272004-06-13 20:20:40 +00002655/*
2656 * Set the value of a boolean option, and take care of side effects.
2657 * Returns NULL for success, or an error message for an error.
2658 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002659 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002660set_bool_option(
2661 int opt_idx, /* index in options[] table */
2662 char_u *varp, /* pointer to the option variable */
2663 int value, /* new value */
2664 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002665{
2666 int old_value = *(int *)varp;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002667#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002668 int old_global_value = 0;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002669#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002670
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671 /* Disallow changing some options from secure mode */
2672 if ((secure
2673#ifdef HAVE_SANDBOX
2674 || sandbox != 0
2675#endif
2676 ) && (options[opt_idx].flags & P_SECURE))
2677 return e_secure;
2678
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002679#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002680 // Save the global value before changing anything. This is needed as for
2681 // a global-only option setting the "local value" in fact sets the global
2682 // value (since there is only one value).
2683 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2684 old_global_value = *(int *)get_varp_scope(&(options[opt_idx]),
2685 OPT_GLOBAL);
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002686#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02002687
Bram Moolenaar071d4272004-06-13 20:20:40 +00002688 *(int *)varp = value; /* set the new value */
2689#ifdef FEAT_EVAL
2690 /* Remember where the option was set. */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002691 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002692#endif
2693
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002694#ifdef FEAT_GUI
2695 need_mouse_correct = TRUE;
2696#endif
2697
Bram Moolenaar071d4272004-06-13 20:20:40 +00002698 /* May set global value for local option. */
2699 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2700 *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
2701
2702 /*
2703 * Handle side effects of changing a bool option.
2704 */
2705
2706 /* 'compatible' */
2707 if ((int *)varp == &p_cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002708 compatible_set();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002709
Bram Moolenaar920694c2016-08-21 17:45:02 +02002710#ifdef FEAT_LANGMAP
2711 if ((int *)varp == &p_lrm)
2712 /* 'langremap' -> !'langnoremap' */
2713 p_lnr = !p_lrm;
2714 else if ((int *)varp == &p_lnr)
2715 /* 'langnoremap' -> !'langremap' */
2716 p_lrm = !p_lnr;
2717#endif
2718
Bram Moolenaar8c63e0e2018-09-25 22:17:54 +02002719#ifdef FEAT_SYN_HL
2720 else if ((int *)varp == &curwin->w_p_cul && !value && old_value)
2721 reset_cursorline();
2722#endif
2723
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002724#ifdef FEAT_PERSISTENT_UNDO
2725 /* 'undofile' */
2726 else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf)
2727 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02002728 /* Only take action when the option was set. When reset we do not
2729 * delete the undo file, the option may be set again without making
2730 * any changes in between. */
2731 if (curbuf->b_p_udf || p_udf)
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002732 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02002733 char_u hash[UNDO_HASH_SIZE];
2734 buf_T *save_curbuf = curbuf;
2735
Bram Moolenaar29323592016-07-24 22:04:11 +02002736 FOR_ALL_BUFFERS(curbuf)
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002737 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02002738 /* When 'undofile' is set globally: for every buffer, otherwise
2739 * only for the current buffer: Try to read in the undofile,
2740 * if one exists, the buffer wasn't changed and the buffer was
2741 * loaded */
2742 if ((curbuf == save_curbuf
2743 || (opt_flags & OPT_GLOBAL) || opt_flags == 0)
2744 && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL)
2745 {
2746 u_compute_hash(hash);
2747 u_read_undo(NULL, hash, curbuf->b_fname);
2748 }
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002749 }
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02002750 curbuf = save_curbuf;
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002751 }
Bram Moolenaar374d32d2012-01-04 19:34:37 +01002752 }
2753#endif
2754
Bram Moolenaar071d4272004-06-13 20:20:40 +00002755 else if ((int *)varp == &curbuf->b_p_ro)
2756 {
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +00002757 /* when 'readonly' is reset globally, also reset readonlymode */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758 if (!curbuf->b_p_ro && (opt_flags & OPT_LOCAL) == 0)
2759 readonlymode = FALSE;
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +00002760
2761 /* when 'readonly' is set may give W10 again */
2762 if (curbuf->b_p_ro)
2763 curbuf->b_did_warn = FALSE;
2764
Bram Moolenaar071d4272004-06-13 20:20:40 +00002765#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002766 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002767#endif
2768 }
2769
Bram Moolenaar9c449722010-07-20 18:44:27 +02002770#ifdef FEAT_GUI
2771 else if ((int *)varp == &p_mh)
2772 {
2773 if (!p_mh)
2774 gui_mch_mousehide(FALSE);
2775 }
2776#endif
2777
Bram Moolenaara539df02010-08-01 14:35:05 +02002778 /* when 'modifiable' is changed, redraw the window title */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002779 else if ((int *)varp == &curbuf->b_p_ma)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002780 {
Bram Moolenaar423802d2017-07-30 16:52:24 +02002781# ifdef FEAT_TERMINAL
2782 /* Cannot set 'modifiable' when in Terminal mode. */
Bram Moolenaard7db27b2018-03-07 23:02:33 +01002783 if (curbuf->b_p_ma && (term_in_normal_mode() || (bt_terminal(curbuf)
2784 && curbuf->b_term != NULL && !term_is_finished(curbuf))))
Bram Moolenaar423802d2017-07-30 16:52:24 +02002785 {
2786 curbuf->b_p_ma = FALSE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002787 return N_("E946: Cannot make a terminal with running job modifiable");
Bram Moolenaar423802d2017-07-30 16:52:24 +02002788 }
2789# endif
2790# ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002791 redraw_titles();
Bram Moolenaar423802d2017-07-30 16:52:24 +02002792# endif
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002793 }
Bram Moolenaar423802d2017-07-30 16:52:24 +02002794#ifdef FEAT_TITLE
Bram Moolenaar071d4272004-06-13 20:20:40 +00002795 /* when 'endofline' is changed, redraw the window title */
2796 else if ((int *)varp == &curbuf->b_p_eol)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002797 {
2798 redraw_titles();
2799 }
Bram Moolenaar34d72d42015-07-17 14:18:08 +02002800 /* when 'fixeol' is changed, redraw the window title */
2801 else if ((int *)varp == &curbuf->b_p_fixeol)
2802 {
2803 redraw_titles();
2804 }
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002805 /* when 'bomb' is changed, redraw the window title and tab page text */
Bram Moolenaar83eb8852007-08-12 13:51:26 +00002806 else if ((int *)varp == &curbuf->b_p_bomb)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002807 {
2808 redraw_titles();
2809 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002810#endif
2811
2812 /* when 'bin' is set also set some other options */
2813 else if ((int *)varp == &curbuf->b_p_bin)
2814 {
2815 set_options_bin(old_value, curbuf->b_p_bin, opt_flags);
2816#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002817 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818#endif
2819 }
2820
Bram Moolenaar071d4272004-06-13 20:20:40 +00002821 /* when 'buflisted' changes, trigger autocommands */
2822 else if ((int *)varp == &curbuf->b_p_bl && old_value != curbuf->b_p_bl)
2823 {
2824 apply_autocmds(curbuf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
2825 NULL, NULL, TRUE, curbuf);
2826 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827
2828 /* when 'swf' is set, create swapfile, when reset remove swapfile */
2829 else if ((int *)varp == &curbuf->b_p_swf)
2830 {
2831 if (curbuf->b_p_swf && p_uc)
2832 ml_open_file(curbuf); /* create the swap file */
2833 else
Bram Moolenaard55de222007-05-06 13:38:48 +00002834 /* no need to reset curbuf->b_may_swap, ml_open_file() will check
2835 * buf->b_p_swf */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836 mf_close_file(curbuf, TRUE); /* remove the swap file */
2837 }
2838
2839 /* when 'terse' is set change 'shortmess' */
2840 else if ((int *)varp == &p_terse)
2841 {
2842 char_u *p;
2843
2844 p = vim_strchr(p_shm, SHM_SEARCH);
2845
2846 /* insert 's' in p_shm */
2847 if (p_terse && p == NULL)
2848 {
2849 STRCPY(IObuff, p_shm);
2850 STRCAT(IObuff, "s");
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002851 set_string_option_direct((char_u *)"shm", -1, IObuff, OPT_FREE, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002852 }
2853 /* remove 's' from p_shm */
2854 else if (!p_terse && p != NULL)
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00002855 STRMOVE(p, p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002856 }
2857
2858 /* when 'paste' is set or reset also change other options */
2859 else if ((int *)varp == &p_paste)
2860 {
2861 paste_option_changed();
2862 }
2863
2864 /* when 'insertmode' is set from an autocommand need to do work here */
2865 else if ((int *)varp == &p_im)
2866 {
2867 if (p_im)
2868 {
2869 if ((State & INSERT) == 0)
2870 need_start_insertmode = TRUE;
2871 stop_insert_mode = FALSE;
2872 }
Bram Moolenaar00672e12016-06-26 18:38:13 +02002873 /* only reset if it was set previously */
2874 else if (old_value)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 {
2876 need_start_insertmode = FALSE;
2877 stop_insert_mode = TRUE;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002878 if (restart_edit != 0 && mode_displayed)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002879 clear_cmdline = TRUE; /* remove "(insert)" */
2880 restart_edit = 0;
2881 }
2882 }
2883
2884 /* when 'ignorecase' is set or reset and 'hlsearch' is set, redraw */
2885 else if ((int *)varp == &p_ic && p_hls)
2886 {
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002887 redraw_all_later(SOME_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888 }
2889
2890#ifdef FEAT_SEARCH_EXTRA
2891 /* when 'hlsearch' is set or reset: reset no_hlsearch */
2892 else if ((int *)varp == &p_hls)
2893 {
Bram Moolenaar451fc7b2018-04-27 22:53:07 +02002894 set_no_hlsearch(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002895 }
2896#endif
2897
Bram Moolenaar071d4272004-06-13 20:20:40 +00002898 /* when 'scrollbind' is set: snapshot the current position to avoid a jump
2899 * at the end of normal_cmd() */
2900 else if ((int *)varp == &curwin->w_p_scb)
2901 {
2902 if (curwin->w_p_scb)
Bram Moolenaar04c5c9e2013-07-09 13:44:59 +02002903 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002904 do_check_scrollbind(FALSE);
Bram Moolenaar04c5c9e2013-07-09 13:44:59 +02002905 curwin->w_scbind_pos = curwin->w_topline;
2906 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002907 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908
Bram Moolenaar4033c552017-09-16 20:54:51 +02002909#if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002910 /* There can be only one window with 'previewwindow' set. */
2911 else if ((int *)varp == &curwin->w_p_pvw)
2912 {
2913 if (curwin->w_p_pvw)
2914 {
2915 win_T *win;
2916
Bram Moolenaar29323592016-07-24 22:04:11 +02002917 FOR_ALL_WINDOWS(win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918 if (win->w_p_pvw && win != curwin)
2919 {
2920 curwin->w_p_pvw = FALSE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002921 return N_("E590: A preview window already exists");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002922 }
2923 }
2924 }
2925#endif
2926
2927 /* when 'textmode' is set or reset also change 'fileformat' */
2928 else if ((int *)varp == &curbuf->b_p_tx)
2929 {
2930 set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, opt_flags);
2931 }
2932
2933 /* when 'textauto' is set or reset also change 'fileformats' */
2934 else if ((int *)varp == &p_ta)
Bram Moolenaarabab0b02019-03-30 18:47:01 +01002935 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002936 set_string_option_direct((char_u *)"ffs", -1,
2937 p_ta ? (char_u *)DFLT_FFS_VIM : (char_u *)"",
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002938 OPT_FREE | opt_flags, 0);
Bram Moolenaarabab0b02019-03-30 18:47:01 +01002939 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940
2941 /*
2942 * When 'lisp' option changes include/exclude '-' in
2943 * keyword characters.
2944 */
2945#ifdef FEAT_LISP
2946 else if (varp == (char_u *)&(curbuf->b_p_lisp))
2947 {
2948 (void)buf_init_chartab(curbuf, FALSE); /* ignore errors */
2949 }
2950#endif
2951
2952#ifdef FEAT_TITLE
2953 /* when 'title' changed, may need to change the title; same for 'icon' */
Bram Moolenaar84a93082018-06-16 22:58:15 +02002954 else if ((int *)varp == &p_title || (int *)varp == &p_icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002955 {
Bram Moolenaar84a93082018-06-16 22:58:15 +02002956 did_set_title();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002957 }
2958#endif
2959
2960 else if ((int *)varp == &curbuf->b_changed)
2961 {
2962 if (!value)
2963 save_file_ff(curbuf); /* Buffer is unchanged */
2964#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002965 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002966#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002967 modified_was_set = value;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002968 }
2969
2970#ifdef BACKSLASH_IN_FILENAME
2971 else if ((int *)varp == &p_ssl)
2972 {
2973 if (p_ssl)
2974 {
2975 psepc = '/';
2976 psepcN = '\\';
2977 pseps[0] = '/';
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 }
2979 else
2980 {
2981 psepc = '\\';
2982 psepcN = '/';
2983 pseps[0] = '\\';
Bram Moolenaar071d4272004-06-13 20:20:40 +00002984 }
2985
2986 /* need to adjust the file name arguments and buffer names. */
2987 buflist_slash_adjust();
2988 alist_slash_adjust();
2989# ifdef FEAT_EVAL
2990 scriptnames_slash_adjust();
2991# endif
2992 }
2993#endif
2994
2995 /* If 'wrap' is set, set w_leftcol to zero. */
2996 else if ((int *)varp == &curwin->w_p_wrap)
2997 {
2998 if (curwin->w_p_wrap)
2999 curwin->w_leftcol = 0;
3000 }
3001
Bram Moolenaar071d4272004-06-13 20:20:40 +00003002 else if ((int *)varp == &p_ea)
3003 {
3004 if (p_ea && !old_value)
3005 win_equal(curwin, FALSE, 0);
3006 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003007
3008 else if ((int *)varp == &p_wiv)
3009 {
3010 /*
3011 * When 'weirdinvert' changed, set/reset 't_xs'.
3012 * Then set 'weirdinvert' according to value of 't_xs'.
3013 */
3014 if (p_wiv && !old_value)
3015 T_XS = (char_u *)"y";
3016 else if (!p_wiv && old_value)
3017 T_XS = empty_option;
3018 p_wiv = (*T_XS != NUL);
3019 }
3020
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01003021#ifdef FEAT_BEVAL_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00003022 else if ((int *)varp == &p_beval)
3023 {
Bram Moolenaar51b0f372017-11-18 18:52:04 +01003024 if (!balloonEvalForTerm)
3025 {
3026 if (p_beval && !old_value)
3027 gui_mch_enable_beval_area(balloonEval);
3028 else if (!p_beval && old_value)
3029 gui_mch_disable_beval_area(balloonEval);
3030 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003031 }
Bram Moolenaar8dff8182006-04-06 20:18:50 +00003032#endif
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01003033#ifdef FEAT_BEVAL_TERM
Bram Moolenaar51b0f372017-11-18 18:52:04 +01003034 else if ((int *)varp == &p_bevalterm)
3035 {
3036 mch_bevalterm_changed();
3037 }
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01003038#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003039
Bram Moolenaar8dff8182006-04-06 20:18:50 +00003040#ifdef FEAT_AUTOCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00003041 else if ((int *)varp == &p_acd)
3042 {
Bram Moolenaar498efdb2006-09-05 14:31:54 +00003043 /* Change directories when the 'acd' option is set now. */
Bram Moolenaar6f470022018-04-10 18:47:20 +02003044 DO_AUTOCHDIR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045 }
3046#endif
3047
3048#ifdef FEAT_DIFF
3049 /* 'diff' */
3050 else if ((int *)varp == &curwin->w_p_diff)
3051 {
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003052 /* May add or remove the buffer from the list of diff buffers. */
3053 diff_buf_adjust(curwin);
3054# ifdef FEAT_FOLDING
Bram Moolenaar071d4272004-06-13 20:20:40 +00003055 if (foldmethodIsDiff(curwin))
3056 foldUpdateAll(curwin);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003057# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003058 }
3059#endif
3060
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01003061#ifdef HAVE_INPUT_METHOD
Bram Moolenaar071d4272004-06-13 20:20:40 +00003062 /* 'imdisable' */
3063 else if ((int *)varp == &p_imdisable)
3064 {
3065 /* Only de-activate it here, it will be enabled when changing mode. */
3066 if (p_imdisable)
3067 im_set_active(FALSE);
Bram Moolenaar725a9622011-10-12 16:57:13 +02003068 else if (State & INSERT)
3069 /* When the option is set from an autocommand, it may need to take
3070 * effect right away. */
3071 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003072 }
3073#endif
3074
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00003075#ifdef FEAT_SPELL
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00003076 /* 'spell' */
3077 else if ((int *)varp == &curwin->w_p_spell)
3078 {
3079 if (curwin->w_p_spell)
3080 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003081 char *errmsg = did_set_spelllang(curwin);
3082
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00003083 if (errmsg != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003084 emsg(_(errmsg));
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00003085 }
3086 }
3087#endif
3088
Bram Moolenaar071d4272004-06-13 20:20:40 +00003089#ifdef FEAT_ARABIC
3090 if ((int *)varp == &curwin->w_p_arab)
3091 {
3092 if (curwin->w_p_arab)
3093 {
3094 /*
3095 * 'arabic' is set, handle various sub-settings.
3096 */
3097 if (!p_tbidi)
3098 {
3099 /* set rightleft mode */
3100 if (!curwin->w_p_rl)
3101 {
3102 curwin->w_p_rl = TRUE;
3103 changed_window_setting();
3104 }
3105
3106 /* Enable Arabic shaping (major part of what Arabic requires) */
3107 if (!p_arshape)
3108 {
3109 p_arshape = TRUE;
3110 redraw_later_clear();
3111 }
3112 }
3113
3114 /* Arabic requires a utf-8 encoding, inform the user if its not
3115 * set. */
3116 if (STRCMP(p_enc, "utf-8") != 0)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003117 {
Bram Moolenaar496c5262009-03-18 14:42:00 +00003118 static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
3119
Bram Moolenaar8820b482017-03-16 17:23:31 +01003120 msg_source(HL_ATTR(HLF_W));
Bram Moolenaar32526b32019-01-19 17:43:09 +01003121 msg_attr(_(w_arabic), HL_ATTR(HLF_W));
Bram Moolenaar496c5262009-03-18 14:42:00 +00003122#ifdef FEAT_EVAL
3123 set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_arabic), -1);
3124#endif
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003125 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003126
Bram Moolenaar071d4272004-06-13 20:20:40 +00003127 /* set 'delcombine' */
3128 p_deco = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003129
3130# ifdef FEAT_KEYMAP
3131 /* Force-set the necessary keymap for arabic */
3132 set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
3133 OPT_LOCAL);
3134# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003135 }
3136 else
3137 {
3138 /*
3139 * 'arabic' is reset, handle various sub-settings.
3140 */
3141 if (!p_tbidi)
3142 {
3143 /* reset rightleft mode */
3144 if (curwin->w_p_rl)
3145 {
3146 curwin->w_p_rl = FALSE;
3147 changed_window_setting();
3148 }
3149
3150 /* 'arabicshape' isn't reset, it is a global option and
3151 * another window may still need it "on". */
3152 }
3153
3154 /* 'delcombine' isn't reset, it is a global option and another
3155 * window may still want it "on". */
3156
3157# ifdef FEAT_KEYMAP
3158 /* Revert to the default keymap */
3159 curbuf->b_p_iminsert = B_IMODE_NONE;
3160 curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
3161# endif
3162 }
Bram Moolenaar801f8b82009-07-29 13:42:05 +00003163 }
3164
Bram Moolenaar319bdbd2009-09-11 13:20:33 +00003165#endif
3166
Bram Moolenaar44826212019-08-22 21:23:20 +02003167#if defined(FEAT_SIGNS) && defined(FEAT_GUI)
3168 else if (((int *)varp == &curwin->w_p_nu
3169 || (int *)varp == &curwin->w_p_rnu)
3170 && gui.in_use
3171 && (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u')
3172 && curbuf->b_signlist != NULL)
3173 {
3174 // If the 'number' or 'relativenumber' options are modified and
3175 // 'signcolumn' is set to 'number', then clear the screen for a full
3176 // refresh. Otherwise the sign icons are not displayed properly in the
3177 // number column. If the 'number' option is set and only the
3178 // 'relativenumber' option is toggled, then don't refresh the screen
3179 // (optimization).
3180 if (!(curwin->w_p_nu && ((int *)varp == &curwin->w_p_rnu)))
3181 redraw_all_later(CLEAR);
3182 }
3183#endif
3184
Bram Moolenaar61be73b2016-04-29 22:59:22 +02003185#ifdef FEAT_TERMGUICOLORS
3186 /* 'termguicolors' */
3187 else if ((int *)varp == &p_tgc)
Bram Moolenaar8a633e32016-04-21 21:10:14 +02003188 {
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003189# ifdef FEAT_VTP
3190 /* Do not turn on 'tgc' when 24-bit colors are not supported. */
Bram Moolenaarafde13b2019-04-28 19:46:49 +02003191 if (
3192# ifdef VIMDLL
3193 !gui.in_use && !gui.starting &&
3194# endif
3195 !has_vtp_working())
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003196 {
3197 p_tgc = 0;
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01003198 return N_("E954: 24-bit colors are not supported on this environment");
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003199 }
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02003200 if (is_term_win32())
3201 swap_tcap();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003202# endif
Bram Moolenaar8a633e32016-04-21 21:10:14 +02003203# ifdef FEAT_GUI
3204 if (!gui.in_use && !gui.starting)
3205# endif
3206 highlight_gui_started();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003207# ifdef FEAT_VTP
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003208 /* reset t_Co */
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02003209 if (is_term_win32())
Bram Moolenaarb0eb14f2018-06-28 15:29:52 +02003210 {
3211 control_console_color_rgb();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003212 set_termname(T_NAME);
Bram Moolenaarb0eb14f2018-06-28 15:29:52 +02003213 init_highlight(TRUE, FALSE);
3214 }
Bram Moolenaarcafafb32018-02-22 21:07:09 +01003215# endif
Bram Moolenaar8a633e32016-04-21 21:10:14 +02003216 }
3217#endif
3218
Bram Moolenaar071d4272004-06-13 20:20:40 +00003219 /*
3220 * End of handling side effects for bool options.
3221 */
3222
Bram Moolenaar53744302015-07-17 17:38:22 +02003223 /* after handling side effects, call autocommand */
3224
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225 options[opt_idx].flags |= P_WAS_SET;
3226
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01003227#if defined(FEAT_EVAL)
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02003228 // Don't do this while starting up or recursively.
3229 if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
Bram Moolenaar53744302015-07-17 17:38:22 +02003230 {
Bram Moolenaard7c96872019-06-15 17:12:48 +02003231 char_u buf_old[2], buf_old_global[2], buf_new[2], buf_type[7];
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02003232
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02003233 vim_snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE);
Bram Moolenaard7c96872019-06-15 17:12:48 +02003234 vim_snprintf((char *)buf_old_global, 2, "%d",
3235 old_global_value ? TRUE: FALSE);
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02003236 vim_snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE);
Bram Moolenaard7c96872019-06-15 17:12:48 +02003237 vim_snprintf((char *)buf_type, 7, "%s",
3238 (opt_flags & OPT_LOCAL) ? "local" : "global");
Bram Moolenaar53744302015-07-17 17:38:22 +02003239 set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
3240 set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
3241 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02003242 if (opt_flags & OPT_LOCAL)
3243 {
3244 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
3245 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3246 }
3247 if (opt_flags & OPT_GLOBAL)
3248 {
3249 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
3250 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
3251 }
3252 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3253 {
3254 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
3255 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3256 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
3257 }
3258 if (opt_flags & OPT_MODELINE)
3259 {
3260 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
3261 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3262 }
3263 apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
3264 NULL, FALSE, NULL);
Bram Moolenaar53744302015-07-17 17:38:22 +02003265 reset_v_option_vars();
3266 }
3267#endif
3268
Bram Moolenaar071d4272004-06-13 20:20:40 +00003269 comp_col(); /* in case 'ruler' or 'showcmd' changed */
Bram Moolenaar913077c2012-03-28 19:59:04 +02003270 if (curwin->w_curswant != MAXCOL
Bram Moolenaar488eb262015-03-13 11:23:50 +01003271 && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaar913077c2012-03-28 19:59:04 +02003272 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003273 check_redraw(options[opt_idx].flags);
3274
3275 return NULL;
3276}
3277
3278/*
3279 * Set the value of a number option, and take care of side effects.
3280 * Returns NULL for success, or an error message for an error.
3281 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003282 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01003283set_num_option(
3284 int opt_idx, /* index in options[] table */
3285 char_u *varp, /* pointer to the option variable */
3286 long value, /* new value */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003287 char *errbuf, /* buffer for error messages */
Bram Moolenaar9b578142016-01-30 19:39:49 +01003288 size_t errbuflen, /* length of "errbuf" */
3289 int opt_flags) /* OPT_LOCAL, OPT_GLOBAL and
Bram Moolenaar071d4272004-06-13 20:20:40 +00003290 OPT_MODELINE */
3291{
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003292 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003293 long old_value = *(long *)varp;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02003294#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02003295 long old_global_value = 0; // only used when setting a local and
3296 // global option
Bram Moolenaar983f2f12019-06-16 16:41:41 +02003297#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02003298 long old_Rows = Rows; // remember old Rows
3299 long old_Columns = Columns; // remember old Columns
Bram Moolenaar071d4272004-06-13 20:20:40 +00003300 long *pp = (long *)varp;
3301
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00003302 /* Disallow changing some options from secure mode. */
3303 if ((secure
3304#ifdef HAVE_SANDBOX
3305 || sandbox != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00003306#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00003307 ) && (options[opt_idx].flags & P_SECURE))
3308 return e_secure;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003309
Bram Moolenaar983f2f12019-06-16 16:41:41 +02003310#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02003311 // Save the global value before changing anything. This is needed as for
3312 // a global-only option setting the "local value" infact sets the global
3313 // value (since there is only one value).
3314 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
Bram Moolenaar983f2f12019-06-16 16:41:41 +02003315 old_global_value = *(long *)get_varp_scope(&(options[opt_idx]),
3316 OPT_GLOBAL);
3317#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02003318
Bram Moolenaar071d4272004-06-13 20:20:40 +00003319 *pp = value;
3320#ifdef FEAT_EVAL
3321 /* Remember where the option was set. */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003322 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003323#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00003324#ifdef FEAT_GUI
3325 need_mouse_correct = TRUE;
3326#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003327
Bram Moolenaar14f24742012-08-08 18:01:05 +02003328 if (curbuf->b_p_sw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003329 {
3330 errmsg = e_positive;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02003331#ifdef FEAT_VARTABS
3332 // Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use.
3333 curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0
3334 ? tabstop_first(curbuf->b_p_vts_array)
3335 : curbuf->b_p_ts;
3336#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337 curbuf->b_p_sw = curbuf->b_p_ts;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02003338#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 }
3340
3341 /*
3342 * Number options that need some action when changed
3343 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003344 if (pp == &p_wh || pp == &p_hh)
3345 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02003346 // 'winheight' and 'helpheight'
Bram Moolenaar071d4272004-06-13 20:20:40 +00003347 if (p_wh < 1)
3348 {
3349 errmsg = e_positive;
3350 p_wh = 1;
3351 }
3352 if (p_wmh > p_wh)
3353 {
3354 errmsg = e_winheight;
3355 p_wh = p_wmh;
3356 }
3357 if (p_hh < 0)
3358 {
3359 errmsg = e_positive;
3360 p_hh = 0;
3361 }
3362
3363 /* Change window height NOW */
Bram Moolenaar459ca562016-11-10 18:16:33 +01003364 if (!ONE_WINDOW)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003365 {
3366 if (pp == &p_wh && curwin->w_height < p_wh)
3367 win_setheight((int)p_wh);
3368 if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh)
3369 win_setheight((int)p_hh);
3370 }
3371 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372 else if (pp == &p_wmh)
3373 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02003374 // 'winminheight'
Bram Moolenaar071d4272004-06-13 20:20:40 +00003375 if (p_wmh < 0)
3376 {
3377 errmsg = e_positive;
3378 p_wmh = 0;
3379 }
3380 if (p_wmh > p_wh)
3381 {
3382 errmsg = e_winheight;
3383 p_wmh = p_wh;
3384 }
3385 win_setminheight();
3386 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003387 else if (pp == &p_wiw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003388 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02003389 // 'winwidth'
Bram Moolenaar071d4272004-06-13 20:20:40 +00003390 if (p_wiw < 1)
3391 {
3392 errmsg = e_positive;
3393 p_wiw = 1;
3394 }
3395 if (p_wmw > p_wiw)
3396 {
3397 errmsg = e_winwidth;
3398 p_wiw = p_wmw;
3399 }
3400
3401 /* Change window width NOW */
Bram Moolenaar459ca562016-11-10 18:16:33 +01003402 if (!ONE_WINDOW && curwin->w_width < p_wiw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003403 win_setwidth((int)p_wiw);
3404 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003405 else if (pp == &p_wmw)
3406 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02003407 // 'winminwidth'
Bram Moolenaar071d4272004-06-13 20:20:40 +00003408 if (p_wmw < 0)
3409 {
3410 errmsg = e_positive;
3411 p_wmw = 0;
3412 }
3413 if (p_wmw > p_wiw)
3414 {
3415 errmsg = e_winwidth;
3416 p_wmw = p_wiw;
3417 }
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02003418 win_setminwidth();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003419 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003420
Bram Moolenaar071d4272004-06-13 20:20:40 +00003421 /* (re)set last window status line */
3422 else if (pp == &p_ls)
3423 {
3424 last_status(FALSE);
3425 }
Bram Moolenaar4c7ed462006-02-15 22:18:42 +00003426
3427 /* (re)set tab page line */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00003428 else if (pp == &p_stal)
Bram Moolenaar4c7ed462006-02-15 22:18:42 +00003429 {
3430 shell_new_rows(); /* recompute window positions and heights */
3431 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003432
3433#ifdef FEAT_GUI
3434 else if (pp == &p_linespace)
3435 {
Bram Moolenaar02743632005-07-25 20:42:36 +00003436 /* Recompute gui.char_height and resize the Vim window to keep the
3437 * same number of lines. */
3438 if (gui.in_use && gui_mch_adjust_charheight() == OK)
Bram Moolenaar3964b7e2006-03-27 20:59:33 +00003439 gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003440 }
3441#endif
3442
3443#ifdef FEAT_FOLDING
3444 /* 'foldlevel' */
3445 else if (pp == &curwin->w_p_fdl)
3446 {
3447 if (curwin->w_p_fdl < 0)
3448 curwin->w_p_fdl = 0;
3449 newFoldLevel();
3450 }
3451
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00003452 /* 'foldminlines' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003453 else if (pp == &curwin->w_p_fml)
3454 {
3455 foldUpdateAll(curwin);
3456 }
3457
3458 /* 'foldnestmax' */
3459 else if (pp == &curwin->w_p_fdn)
3460 {
3461 if (foldmethodIsSyntax(curwin) || foldmethodIsIndent(curwin))
3462 foldUpdateAll(curwin);
3463 }
3464
3465 /* 'foldcolumn' */
3466 else if (pp == &curwin->w_p_fdc)
3467 {
3468 if (curwin->w_p_fdc < 0)
3469 {
3470 errmsg = e_positive;
3471 curwin->w_p_fdc = 0;
3472 }
3473 else if (curwin->w_p_fdc > 12)
3474 {
3475 errmsg = e_invarg;
3476 curwin->w_p_fdc = 12;
3477 }
3478 }
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01003479#endif /* FEAT_FOLDING */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003480
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01003481#if defined(FEAT_FOLDING) || defined(FEAT_CINDENT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003482 /* 'shiftwidth' or 'tabstop' */
3483 else if (pp == &curbuf->b_p_sw || pp == &curbuf->b_p_ts)
3484 {
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01003485# ifdef FEAT_FOLDING
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486 if (foldmethodIsIndent(curwin))
3487 foldUpdateAll(curwin);
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01003488# endif
3489# ifdef FEAT_CINDENT
3490 /* When 'shiftwidth' changes, or it's zero and 'tabstop' changes:
3491 * parse 'cinoptions'. */
3492 if (pp == &curbuf->b_p_sw || curbuf->b_p_sw == 0)
3493 parse_cino(curbuf);
3494# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003495 }
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01003496#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003497
Bram Moolenaar362e1a32006-03-06 23:29:24 +00003498 /* 'maxcombine' */
3499 else if (pp == &p_mco)
3500 {
3501 if (p_mco > MAX_MCO)
3502 p_mco = MAX_MCO;
3503 else if (p_mco < 0)
3504 p_mco = 0;
3505 screenclear(); /* will re-allocate the screen */
3506 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +00003507
Bram Moolenaar071d4272004-06-13 20:20:40 +00003508 else if (pp == &curbuf->b_p_iminsert)
3509 {
3510 if (curbuf->b_p_iminsert < 0 || curbuf->b_p_iminsert > B_IMODE_LAST)
3511 {
3512 errmsg = e_invarg;
3513 curbuf->b_p_iminsert = B_IMODE_NONE;
3514 }
3515 p_iminsert = curbuf->b_p_iminsert;
3516 if (termcap_active) /* don't do this in the alternate screen */
3517 showmode();
Bram Moolenaar4033c552017-09-16 20:54:51 +02003518#if defined(FEAT_KEYMAP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003519 /* Show/unshow value of 'keymap' in status lines. */
3520 status_redraw_curbuf();
3521#endif
3522 }
3523
Bram Moolenaar5c6dbcb2017-08-30 22:00:20 +02003524#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
3525 /* 'imstyle' */
3526 else if (pp == &p_imst)
3527 {
3528 if (p_imst != IM_ON_THE_SPOT && p_imst != IM_OVER_THE_SPOT)
3529 errmsg = e_invarg;
3530 }
3531#endif
3532
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003533 else if (pp == &p_window)
3534 {
3535 if (p_window < 1)
3536 p_window = 1;
3537 else if (p_window >= Rows)
3538 p_window = Rows - 1;
3539 }
3540
Bram Moolenaar071d4272004-06-13 20:20:40 +00003541 else if (pp == &curbuf->b_p_imsearch)
3542 {
3543 if (curbuf->b_p_imsearch < -1 || curbuf->b_p_imsearch > B_IMODE_LAST)
3544 {
3545 errmsg = e_invarg;
3546 curbuf->b_p_imsearch = B_IMODE_NONE;
3547 }
3548 p_imsearch = curbuf->b_p_imsearch;
3549 }
3550
3551#ifdef FEAT_TITLE
3552 /* if 'titlelen' has changed, redraw the title */
3553 else if (pp == &p_titlelen)
3554 {
3555 if (p_titlelen < 0)
3556 {
3557 errmsg = e_positive;
3558 p_titlelen = 85;
3559 }
3560 if (starting != NO_SCREEN && old_value != p_titlelen)
3561 need_maketitle = TRUE;
3562 }
3563#endif
3564
3565 /* if p_ch changed value, change the command line height */
3566 else if (pp == &p_ch)
3567 {
3568 if (p_ch < 1)
3569 {
3570 errmsg = e_positive;
3571 p_ch = 1;
3572 }
Bram Moolenaar719939c2007-09-25 12:51:28 +00003573 if (p_ch > Rows - min_rows() + 1)
3574 p_ch = Rows - min_rows() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003575
3576 /* Only compute the new window layout when startup has been
3577 * completed. Otherwise the frame sizes may be wrong. */
3578 if (p_ch != old_value && full_screen
3579#ifdef FEAT_GUI
3580 && !gui.starting
3581#endif
3582 )
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00003583 command_height();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003584 }
3585
3586 /* when 'updatecount' changes from zero to non-zero, open swap files */
3587 else if (pp == &p_uc)
3588 {
3589 if (p_uc < 0)
3590 {
3591 errmsg = e_positive;
3592 p_uc = 100;
3593 }
3594 if (p_uc && !old_value)
3595 ml_open_files();
3596 }
Bram Moolenaar860cae12010-06-05 23:22:07 +02003597#ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02003598 else if (pp == &curwin->w_p_cole)
Bram Moolenaar860cae12010-06-05 23:22:07 +02003599 {
Bram Moolenaarf5963f72010-07-23 22:10:27 +02003600 if (curwin->w_p_cole < 0)
Bram Moolenaar860cae12010-06-05 23:22:07 +02003601 {
3602 errmsg = e_positive;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02003603 curwin->w_p_cole = 0;
Bram Moolenaar860cae12010-06-05 23:22:07 +02003604 }
Bram Moolenaarf5963f72010-07-23 22:10:27 +02003605 else if (curwin->w_p_cole > 3)
Bram Moolenaar860cae12010-06-05 23:22:07 +02003606 {
3607 errmsg = e_invarg;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02003608 curwin->w_p_cole = 3;
Bram Moolenaar860cae12010-06-05 23:22:07 +02003609 }
3610 }
3611#endif
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003612#ifdef MZSCHEME_GUI_THREADS
Bram Moolenaar325b7a22004-07-05 15:58:32 +00003613 else if (pp == &p_mzq)
3614 mzvim_reset_timer();
3615#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003616
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01003617#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
3618 /* 'pyxversion' */
3619 else if (pp == &p_pyx)
3620 {
3621 if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3)
3622 errmsg = e_invarg;
3623 }
3624#endif
3625
Bram Moolenaar071d4272004-06-13 20:20:40 +00003626 /* sync undo before 'undolevels' changes */
3627 else if (pp == &p_ul)
3628 {
3629 /* use the old value, otherwise u_sync() may not work properly */
3630 p_ul = old_value;
Bram Moolenaar779b74b2006-04-10 14:55:34 +00003631 u_sync(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 p_ul = value;
3633 }
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01003634 else if (pp == &curbuf->b_p_ul)
3635 {
3636 /* use the old value, otherwise u_sync() may not work properly */
3637 curbuf->b_p_ul = old_value;
3638 u_sync(TRUE);
3639 curbuf->b_p_ul = value;
3640 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003641
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003642#ifdef FEAT_LINEBREAK
3643 /* 'numberwidth' must be positive */
3644 else if (pp == &curwin->w_p_nuw)
3645 {
3646 if (curwin->w_p_nuw < 1)
3647 {
3648 errmsg = e_positive;
3649 curwin->w_p_nuw = 1;
3650 }
Bram Moolenaarf8a07122019-07-01 22:06:07 +02003651 if (curwin->w_p_nuw > 20)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003652 {
3653 errmsg = e_invarg;
Bram Moolenaarf8a07122019-07-01 22:06:07 +02003654 curwin->w_p_nuw = 20;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003655 }
Bram Moolenaar1e7813a2015-03-31 18:31:03 +02003656 curwin->w_nrwidth_line_count = 0; /* trigger a redraw */
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003657 }
3658#endif
3659
Bram Moolenaar1a384422010-07-14 19:53:30 +02003660 else if (pp == &curbuf->b_p_tw)
3661 {
3662 if (curbuf->b_p_tw < 0)
3663 {
3664 errmsg = e_positive;
3665 curbuf->b_p_tw = 0;
3666 }
3667#ifdef FEAT_SYN_HL
Bram Moolenaar1a384422010-07-14 19:53:30 +02003668 {
3669 win_T *wp;
3670 tabpage_T *tp;
3671
3672 FOR_ALL_TAB_WINDOWS(tp, wp)
3673 check_colorcolumn(wp);
3674 }
Bram Moolenaar1a384422010-07-14 19:53:30 +02003675#endif
3676 }
3677
Bram Moolenaar071d4272004-06-13 20:20:40 +00003678 /*
3679 * Check the bounds for numeric options here
3680 */
3681 if (Rows < min_rows() && full_screen)
3682 {
3683 if (errbuf != NULL)
3684 {
Bram Moolenaar555b2802005-05-19 21:08:39 +00003685 vim_snprintf((char *)errbuf, errbuflen,
3686 _("E593: Need at least %d lines"), min_rows());
Bram Moolenaar071d4272004-06-13 20:20:40 +00003687 errmsg = errbuf;
3688 }
3689 Rows = min_rows();
3690 }
3691 if (Columns < MIN_COLUMNS && full_screen)
3692 {
3693 if (errbuf != NULL)
3694 {
Bram Moolenaar555b2802005-05-19 21:08:39 +00003695 vim_snprintf((char *)errbuf, errbuflen,
3696 _("E594: Need at least %d columns"), MIN_COLUMNS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003697 errmsg = errbuf;
3698 }
3699 Columns = MIN_COLUMNS;
3700 }
Bram Moolenaare057d402013-06-30 17:51:51 +02003701 limit_screen_size();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003702
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 /*
3704 * If the screen (shell) height has been changed, assume it is the
3705 * physical screenheight.
3706 */
3707 if (old_Rows != Rows || old_Columns != Columns)
3708 {
3709 /* Changing the screen size is not allowed while updating the screen. */
3710 if (updating_screen)
3711 *pp = old_value;
3712 else if (full_screen
3713#ifdef FEAT_GUI
3714 && !gui.starting
3715#endif
3716 )
3717 set_shellsize((int)Columns, (int)Rows, TRUE);
3718 else
3719 {
3720 /* Postpone the resizing; check the size and cmdline position for
3721 * messages. */
3722 check_shellsize();
3723 if (cmdline_row > Rows - p_ch && Rows > p_ch)
3724 cmdline_row = Rows - p_ch;
3725 }
Bram Moolenaard68071d2006-05-02 22:08:30 +00003726 if (p_window >= Rows || !option_was_set((char_u *)"window"))
Bram Moolenaar4399ef42005-02-12 14:29:27 +00003727 p_window = Rows - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 }
3729
Bram Moolenaar071d4272004-06-13 20:20:40 +00003730 if (curbuf->b_p_ts <= 0)
3731 {
3732 errmsg = e_positive;
3733 curbuf->b_p_ts = 8;
3734 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003735 if (p_tm < 0)
3736 {
3737 errmsg = e_positive;
3738 p_tm = 0;
3739 }
3740 if ((curwin->w_p_scr <= 0
3741 || (curwin->w_p_scr > curwin->w_height
3742 && curwin->w_height > 0))
3743 && full_screen)
3744 {
3745 if (pp == &(curwin->w_p_scr))
3746 {
3747 if (curwin->w_p_scr != 0)
3748 errmsg = e_scroll;
3749 win_comp_scroll(curwin);
3750 }
3751 /* If 'scroll' became invalid because of a side effect silently adjust
3752 * it. */
3753 else if (curwin->w_p_scr <= 0)
3754 curwin->w_p_scr = 1;
3755 else /* curwin->w_p_scr > curwin->w_height */
3756 curwin->w_p_scr = curwin->w_height;
3757 }
Bram Moolenaar991e10f2008-10-02 20:48:41 +00003758 if (p_hi < 0)
3759 {
3760 errmsg = e_positive;
3761 p_hi = 0;
3762 }
Bram Moolenaar78159bb2014-06-25 11:48:54 +02003763 else if (p_hi > 10000)
3764 {
3765 errmsg = e_invarg;
3766 p_hi = 10000;
3767 }
Bram Moolenaarfbc0d2e2013-05-19 19:40:29 +02003768 if (p_re < 0 || p_re > 2)
3769 {
3770 errmsg = e_invarg;
3771 p_re = 0;
3772 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 if (p_report < 0)
3774 {
3775 errmsg = e_positive;
3776 p_report = 1;
3777 }
Bram Moolenaar1e015462005-09-25 22:16:38 +00003778 if ((p_sj < -100 || p_sj >= Rows) && full_screen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003779 {
3780 if (Rows != old_Rows) /* Rows changed, just adjust p_sj */
3781 p_sj = Rows / 2;
3782 else
3783 {
3784 errmsg = e_scroll;
3785 p_sj = 1;
3786 }
3787 }
3788 if (p_so < 0 && full_screen)
3789 {
Bram Moolenaar375e3392019-01-31 18:26:10 +01003790 errmsg = e_positive;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003791 p_so = 0;
3792 }
3793 if (p_siso < 0 && full_screen)
3794 {
3795 errmsg = e_positive;
3796 p_siso = 0;
3797 }
3798#ifdef FEAT_CMDWIN
3799 if (p_cwh < 1)
3800 {
3801 errmsg = e_positive;
3802 p_cwh = 1;
3803 }
3804#endif
3805 if (p_ut < 0)
3806 {
3807 errmsg = e_positive;
3808 p_ut = 2000;
3809 }
3810 if (p_ss < 0)
3811 {
3812 errmsg = e_positive;
3813 p_ss = 0;
3814 }
3815
3816 /* May set global value for local option. */
3817 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3818 *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp;
3819
3820 options[opt_idx].flags |= P_WAS_SET;
3821
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01003822#if defined(FEAT_EVAL)
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02003823 // Don't do this while starting up, failure or recursively.
3824 if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
Bram Moolenaar53744302015-07-17 17:38:22 +02003825 {
Bram Moolenaard7c96872019-06-15 17:12:48 +02003826 char_u buf_old[11], buf_old_global[11], buf_new[11], buf_type[7];
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02003827 vim_snprintf((char *)buf_old, 10, "%ld", old_value);
Bram Moolenaard7c96872019-06-15 17:12:48 +02003828 vim_snprintf((char *)buf_old_global, 10, "%ld", old_global_value);
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02003829 vim_snprintf((char *)buf_new, 10, "%ld", value);
3830 vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
Bram Moolenaar53744302015-07-17 17:38:22 +02003831 set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
3832 set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
3833 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02003834 if (opt_flags & OPT_LOCAL)
3835 {
3836 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
3837 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3838 }
3839 if (opt_flags & OPT_GLOBAL)
3840 {
3841 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
3842 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
3843 }
3844 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3845 {
3846 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
3847 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3848 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
3849 }
3850 if (opt_flags & OPT_MODELINE)
3851 {
3852 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
3853 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
3854 }
3855 apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
3856 NULL, FALSE, NULL);
Bram Moolenaar53744302015-07-17 17:38:22 +02003857 reset_v_option_vars();
3858 }
3859#endif
3860
Bram Moolenaar071d4272004-06-13 20:20:40 +00003861 comp_col(); /* in case 'columns' or 'ls' changed */
Bram Moolenaar913077c2012-03-28 19:59:04 +02003862 if (curwin->w_curswant != MAXCOL
Bram Moolenaar488eb262015-03-13 11:23:50 +01003863 && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaar913077c2012-03-28 19:59:04 +02003864 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865 check_redraw(options[opt_idx].flags);
3866
3867 return errmsg;
3868}
3869
3870/*
3871 * Called after an option changed: check if something needs to be redrawn.
3872 */
Bram Moolenaardac13472019-09-16 21:06:21 +02003873 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01003874check_redraw(long_u flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003875{
3876 /* Careful: P_RCLR and P_RALL are a combination of other P_ flags */
Bram Moolenaar70b2a562012-01-10 22:26:17 +01003877 int doclear = (flags & P_RCLR) == P_RCLR;
3878 int all = ((flags & P_RALL) == P_RALL || doclear);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003879
Bram Moolenaar071d4272004-06-13 20:20:40 +00003880 if ((flags & P_RSTAT) || all) /* mark all status lines dirty */
3881 status_redraw_all();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003882
3883 if ((flags & P_RBUF) || (flags & P_RWIN) || all)
3884 changed_window_setting();
3885 if (flags & P_RBUF)
3886 redraw_curbuf_later(NOT_VALID);
Bram Moolenaara2477fd2016-12-03 15:13:20 +01003887 if (flags & P_RWINONLY)
3888 redraw_later(NOT_VALID);
Bram Moolenaar70b2a562012-01-10 22:26:17 +01003889 if (doclear)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003890 redraw_all_later(CLEAR);
3891 else if (all)
3892 redraw_all_later(NOT_VALID);
3893}
3894
3895/*
3896 * Find index for option 'arg'.
3897 * Return -1 if not found.
3898 */
Bram Moolenaardac13472019-09-16 21:06:21 +02003899 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01003900findoption(char_u *arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003901{
3902 int opt_idx;
3903 char *s, *p;
3904 static short quick_tab[27] = {0, 0}; /* quick access table */
3905 int is_term_opt;
3906
3907 /*
3908 * For first call: Initialize the quick-access table.
3909 * It contains the index for the first option that starts with a certain
3910 * letter. There are 26 letters, plus the first "t_" option.
3911 */
3912 if (quick_tab[1] == 0)
3913 {
3914 p = options[0].fullname;
3915 for (opt_idx = 1; (s = options[opt_idx].fullname) != NULL; opt_idx++)
3916 {
3917 if (s[0] != p[0])
3918 {
3919 if (s[0] == 't' && s[1] == '_')
3920 quick_tab[26] = opt_idx;
3921 else
3922 quick_tab[CharOrdLow(s[0])] = opt_idx;
3923 }
3924 p = s;
3925 }
3926 }
3927
3928 /*
3929 * Check for name starting with an illegal character.
3930 */
3931#ifdef EBCDIC
3932 if (!islower(arg[0]))
3933#else
3934 if (arg[0] < 'a' || arg[0] > 'z')
3935#endif
3936 return -1;
3937
3938 is_term_opt = (arg[0] == 't' && arg[1] == '_');
3939 if (is_term_opt)
3940 opt_idx = quick_tab[26];
3941 else
3942 opt_idx = quick_tab[CharOrdLow(arg[0])];
3943 for ( ; (s = options[opt_idx].fullname) != NULL; opt_idx++)
3944 {
3945 if (STRCMP(arg, s) == 0) /* match full name */
3946 break;
3947 }
3948 if (s == NULL && !is_term_opt)
3949 {
3950 opt_idx = quick_tab[CharOrdLow(arg[0])];
3951 for ( ; options[opt_idx].fullname != NULL; opt_idx++)
3952 {
3953 s = options[opt_idx].shortname;
3954 if (s != NULL && STRCMP(arg, s) == 0) /* match short name */
3955 break;
3956 s = NULL;
3957 }
3958 }
3959 if (s == NULL)
3960 opt_idx = -1;
3961 return opt_idx;
3962}
3963
Bram Moolenaar325b7a22004-07-05 15:58:32 +00003964#if defined(FEAT_EVAL) || defined(FEAT_TCL) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003965/*
3966 * Get the value for an option.
3967 *
3968 * Returns:
3969 * Number or Toggle option: 1, *numval gets value.
3970 * String option: 0, *stringval gets allocated string.
3971 * Hidden Number or Toggle option: -1.
3972 * hidden String option: -2.
3973 * unknown option: -3.
3974 */
3975 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01003976get_option_value(
3977 char_u *name,
3978 long *numval,
3979 char_u **stringval, /* NULL when only checking existence */
3980 int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003981{
3982 int opt_idx;
3983 char_u *varp;
3984
3985 opt_idx = findoption(name);
3986 if (opt_idx < 0) /* unknown option */
Bram Moolenaare353c402017-02-04 19:49:16 +01003987 {
3988 int key;
3989
3990 if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02003991 && (key = find_key_option(name, FALSE)) != 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01003992 {
3993 char_u key_name[2];
3994 char_u *p;
3995
3996 if (key < 0)
3997 {
3998 key_name[0] = KEY2TERMCAP0(key);
3999 key_name[1] = KEY2TERMCAP1(key);
4000 }
4001 else
4002 {
4003 key_name[0] = KS_KEY;
4004 key_name[1] = (key & 0xff);
4005 }
4006 p = find_termcode(key_name);
4007 if (p != NULL)
4008 {
4009 if (stringval != NULL)
4010 *stringval = vim_strsave(p);
4011 return 0;
4012 }
4013 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004014 return -3;
Bram Moolenaare353c402017-02-04 19:49:16 +01004015 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004016
4017 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
4018
4019 if (options[opt_idx].flags & P_STRING)
4020 {
4021 if (varp == NULL) /* hidden option */
4022 return -2;
4023 if (stringval != NULL)
4024 {
4025#ifdef FEAT_CRYPT
4026 /* never return the value of the crypt key */
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00004027 if ((char_u **)varp == &curbuf->b_p_key
4028 && **(char_u **)(varp) != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004029 *stringval = vim_strsave((char_u *)"*****");
4030 else
4031#endif
4032 *stringval = vim_strsave(*(char_u **)(varp));
4033 }
4034 return 0;
4035 }
4036
4037 if (varp == NULL) /* hidden option */
4038 return -1;
4039 if (options[opt_idx].flags & P_NUM)
4040 *numval = *(long *)varp;
4041 else
4042 {
4043 /* Special case: 'modified' is b_changed, but we also want to consider
4044 * it set when 'ff' or 'fenc' changed. */
4045 if ((int *)varp == &curbuf->b_changed)
4046 *numval = curbufIsChanged();
4047 else
Bram Moolenaar2acfbed2016-07-01 23:14:02 +02004048 *numval = (long) *(int *)varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004049 }
4050 return 1;
4051}
4052#endif
4053
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004054#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004055/*
4056 * Returns the option attributes and its value. Unlike the above function it
4057 * will return either global value or local value of the option depending on
4058 * what was requested, but it will never return global value if it was
4059 * requested to return local one and vice versa. Neither it will return
4060 * buffer-local value if it was requested to return window-local one.
4061 *
4062 * Pretends that option is absent if it is not present in the requested scope
4063 * (i.e. has no global, window-local or buffer-local value depending on
4064 * opt_type). Uses
4065 *
4066 * Returned flags:
Bram Moolenaar75a8d742014-05-07 15:10:21 +02004067 * 0 hidden or unknown option, also option that does not have requested
4068 * type (see SREQ_* in vim.h)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004069 * see SOPT_* in vim.h for other flags
4070 *
4071 * Possible opt_type values: see SREQ_* in vim.h
4072 */
4073 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004074get_option_value_strict(
4075 char_u *name,
4076 long *numval,
4077 char_u **stringval, /* NULL when only obtaining attributes */
4078 int opt_type,
4079 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004080{
4081 int opt_idx;
Bram Moolenaar68001862013-05-11 13:45:05 +02004082 char_u *varp = NULL;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004083 struct vimoption *p;
4084 int r = 0;
4085
4086 opt_idx = findoption(name);
4087 if (opt_idx < 0)
4088 return 0;
4089
4090 p = &(options[opt_idx]);
4091
4092 /* Hidden option */
4093 if (p->var == NULL)
4094 return 0;
4095
4096 if (p->flags & P_BOOL)
4097 r |= SOPT_BOOL;
4098 else if (p->flags & P_NUM)
4099 r |= SOPT_NUM;
4100 else if (p->flags & P_STRING)
4101 r |= SOPT_STRING;
4102
4103 if (p->indir == PV_NONE)
4104 {
4105 if (opt_type == SREQ_GLOBAL)
4106 r |= SOPT_GLOBAL;
4107 else
4108 return 0; /* Did not request global-only option */
4109 }
4110 else
4111 {
4112 if (p->indir & PV_BOTH)
4113 r |= SOPT_GLOBAL;
4114 else if (opt_type == SREQ_GLOBAL)
4115 return 0; /* Requested global option */
4116
4117 if (p->indir & PV_WIN)
4118 {
4119 if (opt_type == SREQ_BUF)
4120 return 0; /* Did not request window-local option */
4121 else
4122 r |= SOPT_WIN;
4123 }
4124 else if (p->indir & PV_BUF)
4125 {
4126 if (opt_type == SREQ_WIN)
4127 return 0; /* Did not request buffer-local option */
4128 else
4129 r |= SOPT_BUF;
4130 }
4131 }
4132
4133 if (stringval == NULL)
4134 return r;
4135
4136 if (opt_type == SREQ_GLOBAL)
4137 varp = p->var;
4138 else
4139 {
4140 if (opt_type == SREQ_BUF)
4141 {
4142 /* Special case: 'modified' is b_changed, but we also want to
4143 * consider it set when 'ff' or 'fenc' changed. */
4144 if (p->indir == PV_MOD)
4145 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02004146 *numval = bufIsChanged((buf_T *)from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004147 varp = NULL;
4148 }
4149#ifdef FEAT_CRYPT
4150 else if (p->indir == PV_KEY)
4151 {
4152 /* never return the value of the crypt key */
4153 *stringval = NULL;
4154 varp = NULL;
4155 }
4156#endif
4157 else
4158 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02004159 buf_T *save_curbuf = curbuf;
4160
4161 // only getting a pointer, no need to use aucmd_prepbuf()
4162 curbuf = (buf_T *)from;
4163 curwin->w_buffer = curbuf;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004164 varp = get_varp(p);
Bram Moolenaardefe6422018-06-24 15:14:07 +02004165 curbuf = save_curbuf;
4166 curwin->w_buffer = curbuf;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004167 }
4168 }
4169 else if (opt_type == SREQ_WIN)
4170 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02004171 win_T *save_curwin = curwin;
4172
4173 curwin = (win_T *)from;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004174 curbuf = curwin->w_buffer;
4175 varp = get_varp(p);
4176 curwin = save_curwin;
4177 curbuf = curwin->w_buffer;
4178 }
4179 if (varp == p->var)
4180 return (r | SOPT_UNSET);
4181 }
4182
4183 if (varp != NULL)
4184 {
4185 if (p->flags & P_STRING)
4186 *stringval = vim_strsave(*(char_u **)(varp));
4187 else if (p->flags & P_NUM)
4188 *numval = *(long *) varp;
4189 else
4190 *numval = *(int *)varp;
4191 }
4192
4193 return r;
4194}
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004195
4196/*
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02004197 * Iterate over options. First argument is a pointer to a pointer to a
4198 * structure inside options[] array, second is option type like in the above
4199 * function.
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004200 *
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02004201 * If first argument points to NULL it is assumed that iteration just started
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004202 * and caller needs the very first value.
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02004203 * If first argument points to the end marker function returns NULL and sets
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004204 * first argument to NULL.
4205 *
4206 * Returns full option name for current option on each call.
4207 */
4208 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004209option_iter_next(void **option, int opt_type)
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004210{
4211 struct vimoption *ret = NULL;
4212 do
4213 {
4214 if (*option == NULL)
4215 *option = (void *) options;
4216 else if (((struct vimoption *) (*option))->fullname == NULL)
4217 {
4218 *option = NULL;
4219 return NULL;
4220 }
4221 else
4222 *option = (void *) (((struct vimoption *) (*option)) + 1);
4223
4224 ret = ((struct vimoption *) (*option));
4225
4226 /* Hidden option */
4227 if (ret->var == NULL)
4228 {
4229 ret = NULL;
4230 continue;
4231 }
4232
4233 switch (opt_type)
4234 {
4235 case SREQ_GLOBAL:
4236 if (!(ret->indir == PV_NONE || ret->indir & PV_BOTH))
4237 ret = NULL;
4238 break;
4239 case SREQ_BUF:
4240 if (!(ret->indir & PV_BUF))
4241 ret = NULL;
4242 break;
4243 case SREQ_WIN:
4244 if (!(ret->indir & PV_WIN))
4245 ret = NULL;
4246 break;
4247 default:
Bram Moolenaar95f09602016-11-10 20:01:45 +01004248 internal_error("option_iter_next()");
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004249 return NULL;
4250 }
4251 }
4252 while (ret == NULL);
4253
4254 return (char_u *)ret->fullname;
4255}
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004256#endif
4257
Bram Moolenaar071d4272004-06-13 20:20:40 +00004258/*
Bram Moolenaardac13472019-09-16 21:06:21 +02004259 * Return the flags for the option at 'opt_idx'.
4260 */
4261 long_u
4262get_option_flags(int opt_idx)
4263{
4264 return options[opt_idx].flags;
4265}
4266
4267/*
4268 * Set a flag for the option at 'opt_idx'.
4269 */
4270 void
4271set_option_flag(int opt_idx, long_u flag)
4272{
4273 options[opt_idx].flags |= flag;
4274}
4275
4276/*
4277 * Clear a flag for the option at 'opt_idx'.
4278 */
4279 void
4280clear_option_flag(int opt_idx, long_u flag)
4281{
4282 options[opt_idx].flags &= ~flag;
4283}
4284
4285/*
4286 * Returns TRUE if the option at 'opt_idx' is a global option
4287 */
4288 int
4289is_global_option(int opt_idx)
4290{
4291 return options[opt_idx].indir == PV_NONE;
4292}
4293
4294/*
4295 * Returns TRUE if the option at 'opt_idx' is a global option which also has a
4296 * local value.
4297 */
4298 int
4299is_global_local_option(int opt_idx)
4300{
4301 return options[opt_idx].indir & PV_BOTH;
4302}
4303
4304/*
4305 * Returns TRUE if the option at 'opt_idx' is a window-local option
4306 */
4307 int
4308is_window_local_option(int opt_idx)
4309{
4310 return options[opt_idx].var == VAR_WIN;
4311}
4312
4313/*
4314 * Returns TRUE if the option at 'opt_idx' is a hidden option
4315 */
4316 int
4317is_hidden_option(int opt_idx)
4318{
4319 return options[opt_idx].var == NULL;
4320}
4321
4322#if defined(FEAT_CRYPT) || defined(PROTO)
4323/*
4324 * Returns TRUE if the option at 'opt_idx' is a crypt key option
4325 */
4326 int
4327is_crypt_key_option(int opt_idx)
4328{
4329 return options[opt_idx].indir == PV_KEY;
4330}
4331#endif
4332
4333/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 * Set the value of option "name".
4335 * Use "string" for string options, use "number" for other options.
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004336 *
4337 * Returns NULL on success or error message on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004339 char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004340set_option_value(
4341 char_u *name,
4342 long number,
4343 char_u *string,
4344 int opt_flags) /* OPT_LOCAL or 0 (both) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345{
4346 int opt_idx;
4347 char_u *varp;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00004348 long_u flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004349
4350 opt_idx = findoption(name);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004351 if (opt_idx < 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01004352 {
4353 int key;
4354
4355 if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004356 && (key = find_key_option(name, FALSE)) != 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01004357 {
4358 char_u key_name[2];
4359
4360 if (key < 0)
4361 {
4362 key_name[0] = KEY2TERMCAP0(key);
4363 key_name[1] = KEY2TERMCAP1(key);
4364 }
4365 else
4366 {
4367 key_name[0] = KS_KEY;
4368 key_name[1] = (key & 0xff);
4369 }
4370 add_termcode(key_name, string, FALSE);
4371 if (full_screen)
4372 ttest(FALSE);
4373 redraw_all_later(CLEAR);
4374 return NULL;
4375 }
4376
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004377 semsg(_("E355: Unknown option: %s"), name);
Bram Moolenaare353c402017-02-04 19:49:16 +01004378 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004379 else
4380 {
4381 flags = options[opt_idx].flags;
4382#ifdef HAVE_SANDBOX
4383 /* Disallow changing some options in the sandbox */
4384 if (sandbox > 0 && (flags & P_SECURE))
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00004385 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004386 emsg(_(e_sandbox));
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004387 return NULL;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00004388 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004389#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00004390 if (flags & P_STRING)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004391 return set_string_option(opt_idx, string, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004392 else
4393 {
Bram Moolenaarb3163762008-07-08 15:15:08 +00004394 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004395 if (varp != NULL) /* hidden option is not changed */
4396 {
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004397 if (number == 0 && string != NULL)
4398 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004399 int idx;
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004400
4401 /* Either we are given a string or we are setting option
4402 * to zero. */
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004403 for (idx = 0; string[idx] == '0'; ++idx)
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004404 ;
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00004405 if (string[idx] != NUL || idx == 0)
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004406 {
4407 /* There's another character after zeros or the string
4408 * is empty. In both cases, we are trying to set a
4409 * num option using a string. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004410 semsg(_("E521: Number required: &%s = '%s'"),
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004411 name, string);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004412 return NULL; /* do nothing as we hit an error */
Bram Moolenaar96bb6212007-06-19 18:52:53 +00004413
4414 }
4415 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004416 if (flags & P_NUM)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004417 return set_num_option(opt_idx, varp, number,
Bram Moolenaar555b2802005-05-19 21:08:39 +00004418 NULL, 0, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004419 else
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004420 return set_bool_option(opt_idx, varp, (int)number,
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00004421 opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422 }
4423 }
4424 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004425 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004426}
4427
4428/*
4429 * Get the terminal code for a terminal option.
4430 * Returns NULL when not found.
4431 */
4432 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004433get_term_code(char_u *tname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434{
4435 int opt_idx;
4436 char_u *varp;
4437
4438 if (tname[0] != 't' || tname[1] != '_' ||
4439 tname[2] == NUL || tname[3] == NUL)
4440 return NULL;
4441 if ((opt_idx = findoption(tname)) >= 0)
4442 {
4443 varp = get_varp(&(options[opt_idx]));
4444 if (varp != NULL)
4445 varp = *(char_u **)(varp);
4446 return varp;
4447 }
4448 return find_termcode(tname + 2);
4449}
4450
4451 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004452get_highlight_default(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453{
4454 int i;
4455
4456 i = findoption((char_u *)"hl");
4457 if (i >= 0)
4458 return options[i].def_val[VI_DEFAULT];
4459 return (char_u *)NULL;
4460}
4461
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004462 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004463get_encoding_default(void)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004464{
4465 int i;
4466
4467 i = findoption((char_u *)"enc");
4468 if (i >= 0)
4469 return options[i].def_val[VI_DEFAULT];
4470 return (char_u *)NULL;
4471}
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004472
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473/*
4474 * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004475 * When "has_lt" is true there is a '<' before "*arg_arg".
4476 * Returns 0 when the key is not recognized.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004477 */
4478 static int
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004479find_key_option(char_u *arg_arg, int has_lt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004480{
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004481 int key = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004482 int modifiers;
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004483 char_u *arg = arg_arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484
4485 /*
4486 * Don't use get_special_key_code() for t_xx, we don't want it to call
4487 * add_termcap_entry().
4488 */
4489 if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
4490 key = TERMCAP2KEY(arg[2], arg[3]);
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02004491 else if (has_lt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004492 {
4493 --arg; /* put arg at the '<' */
4494 modifiers = 0;
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02004495 key = find_special_key(&arg, &modifiers, TRUE, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004496 if (modifiers) /* can't handle modifiers here */
4497 key = 0;
4498 }
4499 return key;
4500}
4501
4502/*
4503 * if 'all' == 0: show changed options
4504 * if 'all' == 1: show all normal options
4505 * if 'all' == 2: show all terminal options
4506 */
4507 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01004508showoptions(
4509 int all,
4510 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004511{
4512 struct vimoption *p;
4513 int col;
4514 int isterm;
4515 char_u *varp;
4516 struct vimoption **items;
4517 int item_count;
4518 int run;
4519 int row, rows;
4520 int cols;
4521 int i;
4522 int len;
4523
4524#define INC 20
4525#define GAP 3
4526
Bram Moolenaarc799fe22019-05-28 23:08:19 +02004527 items = ALLOC_MULT(struct vimoption *, PARAM_COUNT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004528 if (items == NULL)
4529 return;
4530
4531 /* Highlight title */
4532 if (all == 2)
Bram Moolenaar32526b32019-01-19 17:43:09 +01004533 msg_puts_title(_("\n--- Terminal codes ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004534 else if (opt_flags & OPT_GLOBAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01004535 msg_puts_title(_("\n--- Global option values ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004536 else if (opt_flags & OPT_LOCAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01004537 msg_puts_title(_("\n--- Local option values ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004538 else
Bram Moolenaar32526b32019-01-19 17:43:09 +01004539 msg_puts_title(_("\n--- Options ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004540
4541 /*
4542 * do the loop two times:
4543 * 1. display the short items
4544 * 2. display the long items (only strings and numbers)
4545 */
4546 for (run = 1; run <= 2 && !got_int; ++run)
4547 {
4548 /*
4549 * collect the items in items[]
4550 */
4551 item_count = 0;
4552 for (p = &options[0]; p->fullname != NULL; p++)
4553 {
Bram Moolenaarf86db782018-10-25 13:31:37 +02004554 // apply :filter /pat/
4555 if (message_filtered((char_u *) p->fullname))
4556 continue;
4557
Bram Moolenaar071d4272004-06-13 20:20:40 +00004558 varp = NULL;
4559 isterm = istermoption(p);
4560 if (opt_flags != 0)
4561 {
4562 if (p->indir != PV_NONE && !isterm)
4563 varp = get_varp_scope(p, opt_flags);
4564 }
4565 else
4566 varp = get_varp(p);
4567 if (varp != NULL
4568 && ((all == 2 && isterm)
4569 || (all == 1 && !isterm)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02004570 || (all == 0 && !optval_default(p, varp, p_cp))))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571 {
4572 if (p->flags & P_BOOL)
4573 len = 1; /* a toggle option fits always */
4574 else
4575 {
4576 option_value2string(p, opt_flags);
4577 len = (int)STRLEN(p->fullname) + vim_strsize(NameBuff) + 1;
4578 }
4579 if ((len <= INC - GAP && run == 1) ||
4580 (len > INC - GAP && run == 2))
4581 items[item_count++] = p;
4582 }
4583 }
4584
4585 /*
4586 * display the items
4587 */
4588 if (run == 1)
4589 {
4590 cols = (Columns + GAP - 3) / INC;
4591 if (cols == 0)
4592 cols = 1;
4593 rows = (item_count + cols - 1) / cols;
4594 }
4595 else /* run == 2 */
4596 rows = item_count;
4597 for (row = 0; row < rows && !got_int; ++row)
4598 {
4599 msg_putchar('\n'); /* go to next line */
4600 if (got_int) /* 'q' typed in more */
4601 break;
4602 col = 0;
4603 for (i = row; i < item_count; i += rows)
4604 {
4605 msg_col = col; /* make columns */
4606 showoneopt(items[i], opt_flags);
4607 col += INC;
4608 }
4609 out_flush();
4610 ui_breakcheck();
4611 }
4612 }
4613 vim_free(items);
4614}
4615
4616/*
4617 * Return TRUE if option "p" has its default value.
4618 */
4619 static int
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02004620optval_default(struct vimoption *p, char_u *varp, int compatible)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004621{
4622 int dvi;
4623
4624 if (varp == NULL)
4625 return TRUE; /* hidden option is always at default */
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02004626 dvi = ((p->flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004627 if (p->flags & P_NUM)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00004628 return (*(long *)varp == (long)(long_i)p->def_val[dvi]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004629 if (p->flags & P_BOOL)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00004630 /* the cast to long is required for Manx C, long_i is
4631 * needed for MSVC */
4632 return (*(int *)varp == (int)(long)(long_i)p->def_val[dvi]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004633 /* P_STRING */
4634 return (STRCMP(*(char_u **)varp, p->def_val[dvi]) == 0);
4635}
4636
4637/*
4638 * showoneopt: show the value of one option
4639 * must not be called with a hidden option!
4640 */
4641 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01004642showoneopt(
4643 struct vimoption *p,
4644 int opt_flags) /* OPT_LOCAL or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004645{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004646 char_u *varp;
4647 int save_silent = silent_mode;
4648
4649 silent_mode = FALSE;
4650 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004651
4652 varp = get_varp_scope(p, opt_flags);
4653
4654 /* for 'modified' we also need to check if 'ff' or 'fenc' changed. */
4655 if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
4656 ? !curbufIsChanged() : !*(int *)varp))
Bram Moolenaar32526b32019-01-19 17:43:09 +01004657 msg_puts("no");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 else if ((p->flags & P_BOOL) && *(int *)varp < 0)
Bram Moolenaar32526b32019-01-19 17:43:09 +01004659 msg_puts("--");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004660 else
Bram Moolenaar32526b32019-01-19 17:43:09 +01004661 msg_puts(" ");
4662 msg_puts(p->fullname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004663 if (!(p->flags & P_BOOL))
4664 {
4665 msg_putchar('=');
4666 /* put value string in NameBuff */
4667 option_value2string(p, opt_flags);
4668 msg_outtrans(NameBuff);
4669 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004670
4671 silent_mode = save_silent;
4672 info_message = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004673}
4674
4675/*
4676 * Write modified options as ":set" commands to a file.
4677 *
4678 * There are three values for "opt_flags":
4679 * OPT_GLOBAL: Write global option values and fresh values of
4680 * buffer-local options (used for start of a session
4681 * file).
4682 * OPT_GLOBAL + OPT_LOCAL: Idem, add fresh values of window-local options for
4683 * curwin (used for a vimrc file).
4684 * OPT_LOCAL: Write buffer-local option values for curbuf, fresh
4685 * and local values for window-local options of
4686 * curwin. Local values are also written when at the
4687 * default value, because a modeline or autocommand
4688 * may have set them when doing ":edit file" and the
4689 * user has set them back at the default or fresh
4690 * value.
4691 * When "local_only" is TRUE, don't write fresh
4692 * values, only local values (for ":mkview").
4693 * (fresh value = value used for a new buffer or window for a local option).
4694 *
4695 * Return FAIL on error, OK otherwise.
4696 */
4697 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004698makeset(FILE *fd, int opt_flags, int local_only)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004699{
4700 struct vimoption *p;
4701 char_u *varp; /* currently used value */
4702 char_u *varp_fresh; /* local value */
4703 char_u *varp_local = NULL; /* fresh value */
4704 char *cmd;
4705 int round;
Bram Moolenaar7fd16022007-09-06 14:35:35 +00004706 int pri;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004707
4708 /*
4709 * The options that don't have a default (terminal name, columns, lines)
4710 * are never written. Terminal options are also not written.
Bram Moolenaar7fd16022007-09-06 14:35:35 +00004711 * Do the loop over "options[]" twice: once for options with the
4712 * P_PRI_MKRC flag and once without.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713 */
Bram Moolenaar7fd16022007-09-06 14:35:35 +00004714 for (pri = 1; pri >= 0; --pri)
4715 {
4716 for (p = &options[0]; !istermoption(p); p++)
4717 if (!(p->flags & P_NO_MKRC)
4718 && !istermoption(p)
4719 && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004720 {
4721 /* skip global option when only doing locals */
4722 if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL))
4723 continue;
4724
4725 /* Do not store options like 'bufhidden' and 'syntax' in a vimrc
4726 * file, they are always buffer-specific. */
4727 if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB))
4728 continue;
4729
4730 /* Global values are only written when not at the default value. */
4731 varp = get_varp_scope(p, opt_flags);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02004732 if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp, p_cp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004733 continue;
4734
4735 round = 2;
4736 if (p->indir != PV_NONE)
4737 {
4738 if (p->var == VAR_WIN)
4739 {
4740 /* skip window-local option when only doing globals */
4741 if (!(opt_flags & OPT_LOCAL))
4742 continue;
4743 /* When fresh value of window-local option is not at the
4744 * default, need to write it too. */
4745 if (!(opt_flags & OPT_GLOBAL) && !local_only)
4746 {
4747 varp_fresh = get_varp_scope(p, OPT_GLOBAL);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02004748 if (!optval_default(p, varp_fresh, p_cp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749 {
4750 round = 1;
4751 varp_local = varp;
4752 varp = varp_fresh;
4753 }
4754 }
4755 }
4756 }
4757
4758 /* Round 1: fresh value for window-local options.
4759 * Round 2: other values */
4760 for ( ; round <= 2; varp = varp_local, ++round)
4761 {
4762 if (round == 1 || (opt_flags & OPT_GLOBAL))
4763 cmd = "set";
4764 else
4765 cmd = "setlocal";
4766
4767 if (p->flags & P_BOOL)
4768 {
4769 if (put_setbool(fd, cmd, p->fullname, *(int *)varp) == FAIL)
4770 return FAIL;
4771 }
4772 else if (p->flags & P_NUM)
4773 {
4774 if (put_setnum(fd, cmd, p->fullname, (long *)varp) == FAIL)
4775 return FAIL;
4776 }
4777 else /* P_STRING */
4778 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004779 int do_endif = FALSE;
4780
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 /* Don't set 'syntax' and 'filetype' again if the value is
4782 * already right, avoids reloading the syntax file. */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004783 if (
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01004784#if defined(FEAT_SYN_HL)
4785 p->indir == PV_SYN ||
4786#endif
4787 p->indir == PV_FT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788 {
4789 if (fprintf(fd, "if &%s != '%s'", p->fullname,
4790 *(char_u **)(varp)) < 0
4791 || put_eol(fd) < 0)
4792 return FAIL;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004793 do_endif = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004794 }
4795 if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004796 p->flags) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004797 return FAIL;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004798 if (do_endif)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004799 {
4800 if (put_line(fd, "endif") == FAIL)
4801 return FAIL;
4802 }
4803 }
4804 }
4805 }
Bram Moolenaar7fd16022007-09-06 14:35:35 +00004806 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004807 return OK;
4808}
4809
4810#if defined(FEAT_FOLDING) || defined(PROTO)
4811/*
4812 * Generate set commands for the local fold options only. Used when
4813 * 'sessionoptions' or 'viewoptions' contains "folds" but not "options".
4814 */
4815 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004816makefoldset(FILE *fd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004817{
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004818 if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819# ifdef FEAT_EVAL
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004820 || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004821 == FAIL
4822# endif
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004823 || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004824 == FAIL
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004825 || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004826 == FAIL
4827 || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
4828 || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
4829 || put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
4830 || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL
4831 )
4832 return FAIL;
4833
4834 return OK;
4835}
4836#endif
4837
4838 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004839put_setstring(
4840 FILE *fd,
4841 char *cmd,
4842 char *name,
4843 char_u **valuep,
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004844 long_u flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004845{
4846 char_u *s;
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004847 char_u *buf = NULL;
4848 char_u *part = NULL;
4849 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004850
4851 if (fprintf(fd, "%s %s=", cmd, name) < 0)
4852 return FAIL;
4853 if (*valuep != NULL)
4854 {
4855 /* Output 'pastetoggle' as key names. For other
4856 * options some characters have to be escaped with
4857 * CTRL-V or backslash */
4858 if (valuep == &p_pt)
4859 {
4860 s = *valuep;
4861 while (*s != NUL)
Bram Moolenaar7d96acd2008-06-09 15:07:54 +00004862 if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004863 return FAIL;
4864 }
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004865 // expand the option value, replace $HOME by ~
4866 else if ((flags & P_EXPAND) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004867 {
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004868 int size = (int)STRLEN(*valuep) + 1;
4869
4870 // replace home directory in the whole option value into "buf"
4871 buf = alloc(size);
Bram Moolenaarf8441472011-04-28 17:24:58 +02004872 if (buf == NULL)
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004873 goto fail;
4874 home_replace(NULL, *valuep, buf, size, FALSE);
4875
4876 // If the option value is longer than MAXPATHL, we need to append
4877 // earch comma separated part of the option separately, so that it
4878 // can be expanded when read back.
4879 if (size >= MAXPATHL && (flags & P_COMMA) != 0
4880 && vim_strchr(*valuep, ',') != NULL)
4881 {
4882 part = alloc(size);
4883 if (part == NULL)
4884 goto fail;
4885
4886 // write line break to clear the option, e.g. ':set rtp='
4887 if (put_eol(fd) == FAIL)
4888 goto fail;
4889
4890 p = buf;
4891 while (*p != NUL)
4892 {
4893 // for each comma separated option part, append value to
4894 // the option, :set rtp+=value
4895 if (fprintf(fd, "%s %s+=", cmd, name) < 0)
4896 goto fail;
4897 (void)copy_option_part(&p, part, size, ",");
4898 if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL)
4899 goto fail;
4900 }
4901 vim_free(buf);
4902 vim_free(part);
4903 return OK;
4904 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004905 if (put_escstr(fd, buf, 2) == FAIL)
Bram Moolenaarf8441472011-04-28 17:24:58 +02004906 {
4907 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004908 return FAIL;
Bram Moolenaarf8441472011-04-28 17:24:58 +02004909 }
4910 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004911 }
4912 else if (put_escstr(fd, *valuep, 2) == FAIL)
4913 return FAIL;
4914 }
4915 if (put_eol(fd) < 0)
4916 return FAIL;
4917 return OK;
Bram Moolenaared18f2c2019-01-24 20:30:52 +01004918fail:
4919 vim_free(buf);
4920 vim_free(part);
4921 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004922}
4923
4924 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004925put_setnum(
4926 FILE *fd,
4927 char *cmd,
4928 char *name,
4929 long *valuep)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004930{
4931 long wc;
4932
4933 if (fprintf(fd, "%s %s=", cmd, name) < 0)
4934 return FAIL;
4935 if (wc_use_keyname((char_u *)valuep, &wc))
4936 {
4937 /* print 'wildchar' and 'wildcharm' as a key name */
4938 if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0)
4939 return FAIL;
4940 }
4941 else if (fprintf(fd, "%ld", *valuep) < 0)
4942 return FAIL;
4943 if (put_eol(fd) < 0)
4944 return FAIL;
4945 return OK;
4946}
4947
4948 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01004949put_setbool(
4950 FILE *fd,
4951 char *cmd,
4952 char *name,
4953 int value)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004954{
Bram Moolenaar893de922007-10-02 18:40:57 +00004955 if (value < 0) /* global/local option using global value */
4956 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004957 if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
4958 || put_eol(fd) < 0)
4959 return FAIL;
4960 return OK;
4961}
4962
4963/*
4964 * Clear all the terminal options.
4965 * If the option has been allocated, free the memory.
4966 * Terminal options are never hidden or indirect.
4967 */
4968 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01004969clear_termoptions(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004970{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004971 /*
4972 * Reset a few things before clearing the old options. This may cause
4973 * outputting a few things that the terminal doesn't understand, but the
4974 * screen will be cleared later, so this is OK.
4975 */
4976#ifdef FEAT_MOUSE_TTY
4977 mch_setmouse(FALSE); /* switch mouse off */
4978#endif
4979#ifdef FEAT_TITLE
Bram Moolenaar40385db2018-08-07 22:31:44 +02004980 mch_restore_title(SAVE_RESTORE_BOTH); /* restore window titles */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981#endif
4982#if defined(FEAT_XCLIPBOARD) && defined(FEAT_GUI)
4983 /* When starting the GUI close the display opened for the clipboard.
4984 * After restoring the title, because that will need the display. */
4985 if (gui.starting)
4986 clear_xterm_clip();
4987#endif
Bram Moolenaarcea912a2016-10-12 14:20:24 +02004988 stoptermcap(); /* stop termcap mode */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004989
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00004990 free_termoptions();
4991}
4992
4993 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01004994free_termoptions(void)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00004995{
4996 struct vimoption *p;
4997
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02004998 for (p = options; p->fullname != NULL; p++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004999 if (istermoption(p))
5000 {
5001 if (p->flags & P_ALLOCED)
5002 free_string_option(*(char_u **)(p->var));
5003 if (p->flags & P_DEF_ALLOCED)
5004 free_string_option(p->def_val[VI_DEFAULT]);
5005 *(char_u **)(p->var) = empty_option;
5006 p->def_val[VI_DEFAULT] = empty_option;
5007 p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED);
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02005008#ifdef FEAT_EVAL
5009 // remember where the option was cleared
5010 set_option_sctx_idx((int)(p - options), OPT_GLOBAL, current_sctx);
5011#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005012 }
5013 clear_termcodes();
5014}
5015
5016/*
Bram Moolenaar363cb672009-07-22 12:28:17 +00005017 * Free the string for one term option, if it was allocated.
5018 * Set the string to empty_option and clear allocated flag.
5019 * "var" points to the option value.
5020 */
5021 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005022free_one_termoption(char_u *var)
Bram Moolenaar363cb672009-07-22 12:28:17 +00005023{
5024 struct vimoption *p;
5025
5026 for (p = &options[0]; p->fullname != NULL; p++)
5027 if (p->var == var)
5028 {
5029 if (p->flags & P_ALLOCED)
5030 free_string_option(*(char_u **)(p->var));
5031 *(char_u **)(p->var) = empty_option;
5032 p->flags &= ~P_ALLOCED;
5033 break;
5034 }
5035}
5036
5037/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005038 * Set the terminal option defaults to the current value.
5039 * Used after setting the terminal name.
5040 */
5041 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005042set_term_defaults(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005043{
5044 struct vimoption *p;
5045
5046 for (p = &options[0]; p->fullname != NULL; p++)
5047 {
5048 if (istermoption(p) && p->def_val[VI_DEFAULT] != *(char_u **)(p->var))
5049 {
5050 if (p->flags & P_DEF_ALLOCED)
5051 {
5052 free_string_option(p->def_val[VI_DEFAULT]);
5053 p->flags &= ~P_DEF_ALLOCED;
5054 }
5055 p->def_val[VI_DEFAULT] = *(char_u **)(p->var);
5056 if (p->flags & P_ALLOCED)
5057 {
5058 p->flags |= P_DEF_ALLOCED;
5059 p->flags &= ~P_ALLOCED; /* don't free the value now */
5060 }
5061 }
5062 }
5063}
5064
5065/*
5066 * return TRUE if 'p' starts with 't_'
5067 */
5068 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01005069istermoption(struct vimoption *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005070{
5071 return (p->fullname[0] == 't' && p->fullname[1] == '_');
5072}
5073
Bram Moolenaardac13472019-09-16 21:06:21 +02005074/*
5075 * Returns TRUE if the option at 'opt_idx' starts with 't_'
5076 */
5077 int
5078istermoption_idx(int opt_idx)
5079{
5080 return istermoption(&options[opt_idx]);
5081}
5082
Bram Moolenaar113e1072019-01-20 15:30:40 +01005083#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005084/*
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005085 * Unset local option value, similar to ":set opt<".
5086 */
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005087 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005088unset_global_local_option(char_u *name, void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005089{
5090 struct vimoption *p;
5091 int opt_idx;
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005092 buf_T *buf = (buf_T *)from;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005093
5094 opt_idx = findoption(name);
Bram Moolenaarbd8539a2015-08-11 18:53:03 +02005095 if (opt_idx < 0)
5096 return;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005097 p = &(options[opt_idx]);
5098
5099 switch ((int)p->indir)
5100 {
5101 /* global option with local value: use local value if it's been set */
5102 case PV_EP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005103 clear_string_option(&buf->b_p_ep);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005104 break;
5105 case PV_KP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005106 clear_string_option(&buf->b_p_kp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005107 break;
5108 case PV_PATH:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005109 clear_string_option(&buf->b_p_path);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005110 break;
5111 case PV_AR:
5112 buf->b_p_ar = -1;
5113 break;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02005114 case PV_BKC:
5115 clear_string_option(&buf->b_p_bkc);
5116 buf->b_bkc_flags = 0;
5117 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005118 case PV_TAGS:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005119 clear_string_option(&buf->b_p_tags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005120 break;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01005121 case PV_TC:
5122 clear_string_option(&buf->b_p_tc);
5123 buf->b_tc_flags = 0;
5124 break;
Bram Moolenaar375e3392019-01-31 18:26:10 +01005125 case PV_SISO:
5126 curwin->w_p_siso = -1;
5127 break;
5128 case PV_SO:
5129 curwin->w_p_so = -1;
5130 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005131#ifdef FEAT_FIND_ID
5132 case PV_DEF:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005133 clear_string_option(&buf->b_p_def);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005134 break;
5135 case PV_INC:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005136 clear_string_option(&buf->b_p_inc);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005137 break;
5138#endif
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005139 case PV_DICT:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005140 clear_string_option(&buf->b_p_dict);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005141 break;
5142 case PV_TSR:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005143 clear_string_option(&buf->b_p_tsr);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005144 break;
Bram Moolenaar9be7c042017-01-14 14:28:30 +01005145 case PV_FP:
5146 clear_string_option(&buf->b_p_fp);
5147 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005148#ifdef FEAT_QUICKFIX
5149 case PV_EFM:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005150 clear_string_option(&buf->b_p_efm);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005151 break;
5152 case PV_GP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005153 clear_string_option(&buf->b_p_gp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005154 break;
5155 case PV_MP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005156 clear_string_option(&buf->b_p_mp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005157 break;
5158#endif
5159#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5160 case PV_BEXPR:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005161 clear_string_option(&buf->b_p_bexpr);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005162 break;
5163#endif
5164#if defined(FEAT_CRYPT)
5165 case PV_CM:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005166 clear_string_option(&buf->b_p_cm);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005167 break;
5168#endif
5169#ifdef FEAT_STL_OPT
5170 case PV_STL:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02005171 clear_string_option(&((win_T *)from)->w_p_stl);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005172 break;
5173#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01005174 case PV_UL:
5175 buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
5176 break;
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01005177#ifdef FEAT_LISP
5178 case PV_LW:
5179 clear_string_option(&buf->b_p_lw);
5180 break;
5181#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01005182 case PV_MENC:
5183 clear_string_option(&buf->b_p_menc);
5184 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005185 }
5186}
Bram Moolenaar113e1072019-01-20 15:30:40 +01005187#endif
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005188
5189/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005190 * Get pointer to option variable, depending on local or global scope.
5191 */
5192 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01005193get_varp_scope(struct vimoption *p, int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005194{
5195 if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE)
5196 {
5197 if (p->var == VAR_WIN)
5198 return (char_u *)GLOBAL_WO(get_varp(p));
5199 return p->var;
5200 }
Bram Moolenaara23ccb82006-02-27 00:08:02 +00005201 if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005202 {
5203 switch ((int)p->indir)
5204 {
Bram Moolenaar9be7c042017-01-14 14:28:30 +01005205 case PV_FP: return (char_u *)&(curbuf->b_p_fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206#ifdef FEAT_QUICKFIX
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005207 case PV_EFM: return (char_u *)&(curbuf->b_p_efm);
5208 case PV_GP: return (char_u *)&(curbuf->b_p_gp);
5209 case PV_MP: return (char_u *)&(curbuf->b_p_mp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005211 case PV_EP: return (char_u *)&(curbuf->b_p_ep);
5212 case PV_KP: return (char_u *)&(curbuf->b_p_kp);
5213 case PV_PATH: return (char_u *)&(curbuf->b_p_path);
Bram Moolenaara23ccb82006-02-27 00:08:02 +00005214 case PV_AR: return (char_u *)&(curbuf->b_p_ar);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005215 case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01005216 case PV_TC: return (char_u *)&(curbuf->b_p_tc);
Bram Moolenaar375e3392019-01-31 18:26:10 +01005217 case PV_SISO: return (char_u *)&(curwin->w_p_siso);
5218 case PV_SO: return (char_u *)&(curwin->w_p_so);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005219#ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005220 case PV_DEF: return (char_u *)&(curbuf->b_p_def);
5221 case PV_INC: return (char_u *)&(curbuf->b_p_inc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005222#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005223 case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
5224 case PV_TSR: return (char_u *)&(curbuf->b_p_tsr);
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00005225#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5226 case PV_BEXPR: return (char_u *)&(curbuf->b_p_bexpr);
5227#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02005228#if defined(FEAT_CRYPT)
5229 case PV_CM: return (char_u *)&(curbuf->b_p_cm);
5230#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005231#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005232 case PV_STL: return (char_u *)&(curwin->w_p_stl);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005233#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01005234 case PV_UL: return (char_u *)&(curbuf->b_p_ul);
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01005235#ifdef FEAT_LISP
5236 case PV_LW: return (char_u *)&(curbuf->b_p_lw);
5237#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02005238 case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01005239 case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005240 }
5241 return NULL; /* "cannot happen" */
5242 }
5243 return get_varp(p);
5244}
5245
5246/*
Bram Moolenaardac13472019-09-16 21:06:21 +02005247 * Get pointer to option variable at 'opt_idx', depending on local or global
5248 * scope.
5249 */
5250 char_u *
5251get_option_varp_scope(int opt_idx, int opt_flags)
5252{
5253 return get_varp_scope(&(options[opt_idx]), opt_flags);
5254}
5255
5256/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257 * Get pointer to option variable.
5258 */
5259 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01005260get_varp(struct vimoption *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005261{
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 */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005271 case PV_EP: return *curbuf->b_p_ep != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005272 ? (char_u *)&curbuf->b_p_ep : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005273 case PV_KP: return *curbuf->b_p_kp != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274 ? (char_u *)&curbuf->b_p_kp : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005275 case PV_PATH: return *curbuf->b_p_path != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005276 ? (char_u *)&(curbuf->b_p_path) : p->var;
Bram Moolenaara23ccb82006-02-27 00:08:02 +00005277 case PV_AR: return curbuf->b_p_ar >= 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00005278 ? (char_u *)&(curbuf->b_p_ar) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005279 case PV_TAGS: return *curbuf->b_p_tags != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005280 ? (char_u *)&(curbuf->b_p_tags) : p->var;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01005281 case PV_TC: return *curbuf->b_p_tc != NUL
5282 ? (char_u *)&(curbuf->b_p_tc) : p->var;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02005283 case PV_BKC: return *curbuf->b_p_bkc != NUL
5284 ? (char_u *)&(curbuf->b_p_bkc) : p->var;
Bram Moolenaar375e3392019-01-31 18:26:10 +01005285 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;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005289#ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005290 case PV_DEF: return *curbuf->b_p_def != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005291 ? (char_u *)&(curbuf->b_p_def) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005292 case PV_INC: return *curbuf->b_p_inc != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005293 ? (char_u *)&(curbuf->b_p_inc) : p->var;
5294#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005295 case PV_DICT: return *curbuf->b_p_dict != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005296 ? (char_u *)&(curbuf->b_p_dict) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005297 case PV_TSR: return *curbuf->b_p_tsr != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005298 ? (char_u *)&(curbuf->b_p_tsr) : p->var;
Bram Moolenaar9be7c042017-01-14 14:28:30 +01005299 case PV_FP: return *curbuf->b_p_fp != NUL
5300 ? (char_u *)&(curbuf->b_p_fp) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005301#ifdef FEAT_QUICKFIX
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005302 case PV_EFM: return *curbuf->b_p_efm != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303 ? (char_u *)&(curbuf->b_p_efm) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005304 case PV_GP: return *curbuf->b_p_gp != NUL
5305 ? (char_u *)&(curbuf->b_p_gp) : p->var;
5306 case PV_MP: return *curbuf->b_p_mp != NUL
5307 ? (char_u *)&(curbuf->b_p_mp) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005308#endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00005309#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5310 case PV_BEXPR: return *curbuf->b_p_bexpr != NUL
5311 ? (char_u *)&(curbuf->b_p_bexpr) : p->var;
5312#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02005313#if defined(FEAT_CRYPT)
5314 case PV_CM: return *curbuf->b_p_cm != NUL
5315 ? (char_u *)&(curbuf->b_p_cm) : p->var;
5316#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005317#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005318 case PV_STL: return *curwin->w_p_stl != NUL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005319 ? (char_u *)&(curwin->w_p_stl) : p->var;
5320#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01005321 case PV_UL: return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
5322 ? (char_u *)&(curbuf->b_p_ul) : p->var;
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01005323#ifdef FEAT_LISP
5324 case PV_LW: return *curbuf->b_p_lw != NUL
5325 ? (char_u *)&(curbuf->b_p_lw) : p->var;
5326#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01005327 case PV_MENC: return *curbuf->b_p_menc != NUL
5328 ? (char_u *)&(curbuf->b_p_menc) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005329#ifdef FEAT_ARABIC
5330 case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
5331#endif
5332 case PV_LIST: return (char_u *)&(curwin->w_p_list);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005333#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00005334 case PV_SPELL: return (char_u *)&(curwin->w_p_spell);
5335#endif
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005336#ifdef FEAT_SYN_HL
5337 case PV_CUC: return (char_u *)&(curwin->w_p_cuc);
5338 case PV_CUL: return (char_u *)&(curwin->w_p_cul);
Bram Moolenaar410e98a2019-09-09 22:05:49 +02005339 case PV_CULOPT: return (char_u *)&(curwin->w_p_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02005340 case PV_CC: return (char_u *)&(curwin->w_p_cc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005341#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005342#ifdef FEAT_DIFF
5343 case PV_DIFF: return (char_u *)&(curwin->w_p_diff);
5344#endif
5345#ifdef FEAT_FOLDING
5346 case PV_FDC: return (char_u *)&(curwin->w_p_fdc);
5347 case PV_FEN: return (char_u *)&(curwin->w_p_fen);
5348 case PV_FDI: return (char_u *)&(curwin->w_p_fdi);
5349 case PV_FDL: return (char_u *)&(curwin->w_p_fdl);
5350 case PV_FDM: return (char_u *)&(curwin->w_p_fdm);
5351 case PV_FML: return (char_u *)&(curwin->w_p_fml);
5352 case PV_FDN: return (char_u *)&(curwin->w_p_fdn);
5353# ifdef FEAT_EVAL
5354 case PV_FDE: return (char_u *)&(curwin->w_p_fde);
5355 case PV_FDT: return (char_u *)&(curwin->w_p_fdt);
5356# endif
5357 case PV_FMR: return (char_u *)&(curwin->w_p_fmr);
5358#endif
5359 case PV_NU: return (char_u *)&(curwin->w_p_nu);
Bram Moolenaar64486672010-05-16 15:46:46 +02005360 case PV_RNU: return (char_u *)&(curwin->w_p_rnu);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00005361#ifdef FEAT_LINEBREAK
5362 case PV_NUW: return (char_u *)&(curwin->w_p_nuw);
5363#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005364 case PV_WFH: return (char_u *)&(curwin->w_p_wfh);
Bram Moolenaar97b2ad32006-03-18 21:40:56 +00005365 case PV_WFW: return (char_u *)&(curwin->w_p_wfw);
Bram Moolenaar4033c552017-09-16 20:54:51 +02005366#if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005367 case PV_PVW: return (char_u *)&(curwin->w_p_pvw);
5368#endif
5369#ifdef FEAT_RIGHTLEFT
5370 case PV_RL: return (char_u *)&(curwin->w_p_rl);
5371 case PV_RLC: return (char_u *)&(curwin->w_p_rlc);
5372#endif
5373 case PV_SCROLL: return (char_u *)&(curwin->w_p_scr);
5374 case PV_WRAP: return (char_u *)&(curwin->w_p_wrap);
5375#ifdef FEAT_LINEBREAK
5376 case PV_LBR: return (char_u *)&(curwin->w_p_lbr);
Bram Moolenaar597a4222014-06-25 14:39:50 +02005377 case PV_BRI: return (char_u *)&(curwin->w_p_bri);
5378 case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005380 case PV_WCR: return (char_u *)&(curwin->w_p_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005381 case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
Bram Moolenaar860cae12010-06-05 23:22:07 +02005382 case PV_CRBIND: return (char_u *)&(curwin->w_p_crb);
Bram Moolenaar860cae12010-06-05 23:22:07 +02005383#ifdef FEAT_CONCEAL
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005384 case PV_COCU: return (char_u *)&(curwin->w_p_cocu);
5385 case PV_COLE: return (char_u *)&(curwin->w_p_cole);
5386#endif
5387#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02005388 case PV_TWK: return (char_u *)&(curwin->w_p_twk);
5389 case PV_TWS: return (char_u *)&(curwin->w_p_tws);
5390 case PV_TWSL: return (char_u *)&(curbuf->b_p_twsl);
Bram Moolenaar860cae12010-06-05 23:22:07 +02005391#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005392
5393 case PV_AI: return (char_u *)&(curbuf->b_p_ai);
5394 case PV_BIN: return (char_u *)&(curbuf->b_p_bin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005395 case PV_BOMB: return (char_u *)&(curbuf->b_p_bomb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005396 case PV_BH: return (char_u *)&(curbuf->b_p_bh);
5397 case PV_BT: return (char_u *)&(curbuf->b_p_bt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005398 case PV_BL: return (char_u *)&(curbuf->b_p_bl);
5399 case PV_CI: return (char_u *)&(curbuf->b_p_ci);
5400#ifdef FEAT_CINDENT
5401 case PV_CIN: return (char_u *)&(curbuf->b_p_cin);
5402 case PV_CINK: return (char_u *)&(curbuf->b_p_cink);
5403 case PV_CINO: return (char_u *)&(curbuf->b_p_cino);
5404#endif
5405#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
5406 case PV_CINW: return (char_u *)&(curbuf->b_p_cinw);
5407#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005408 case PV_COM: return (char_u *)&(curbuf->b_p_com);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005409#ifdef FEAT_FOLDING
5410 case PV_CMS: return (char_u *)&(curbuf->b_p_cms);
5411#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412 case PV_CPT: return (char_u *)&(curbuf->b_p_cpt);
Bram Moolenaare2c453d2019-08-21 14:37:09 +02005413#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarac3150d2019-07-28 16:36:39 +02005414 case PV_CSL: return (char_u *)&(curbuf->b_p_csl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005415#endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005416#ifdef FEAT_COMPL_FUNC
5417 case PV_CFU: return (char_u *)&(curbuf->b_p_cfu);
Bram Moolenaare344bea2005-09-01 20:46:49 +00005418 case PV_OFU: return (char_u *)&(curbuf->b_p_ofu);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005419#endif
Bram Moolenaar45e18cb2019-04-28 18:05:35 +02005420#ifdef FEAT_EVAL
5421 case PV_TFU: return (char_u *)&(curbuf->b_p_tfu);
5422#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005423 case PV_EOL: return (char_u *)&(curbuf->b_p_eol);
Bram Moolenaar34d72d42015-07-17 14:18:08 +02005424 case PV_FIXEOL: return (char_u *)&(curbuf->b_p_fixeol);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005425 case PV_ET: return (char_u *)&(curbuf->b_p_et);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005426 case PV_FENC: return (char_u *)&(curbuf->b_p_fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005427 case PV_FF: return (char_u *)&(curbuf->b_p_ff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 case PV_FT: return (char_u *)&(curbuf->b_p_ft);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005429 case PV_FO: return (char_u *)&(curbuf->b_p_fo);
Bram Moolenaar86b68352004-12-27 21:59:20 +00005430 case PV_FLP: return (char_u *)&(curbuf->b_p_flp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431 case PV_IMI: return (char_u *)&(curbuf->b_p_iminsert);
5432 case PV_IMS: return (char_u *)&(curbuf->b_p_imsearch);
5433 case PV_INF: return (char_u *)&(curbuf->b_p_inf);
5434 case PV_ISK: return (char_u *)&(curbuf->b_p_isk);
5435#ifdef FEAT_FIND_ID
5436# ifdef FEAT_EVAL
5437 case PV_INEX: return (char_u *)&(curbuf->b_p_inex);
5438# endif
5439#endif
5440#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
5441 case PV_INDE: return (char_u *)&(curbuf->b_p_inde);
5442 case PV_INDK: return (char_u *)&(curbuf->b_p_indk);
5443#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005444#ifdef FEAT_EVAL
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005445 case PV_FEX: return (char_u *)&(curbuf->b_p_fex);
5446#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005447#ifdef FEAT_CRYPT
5448 case PV_KEY: return (char_u *)&(curbuf->b_p_key);
5449#endif
5450#ifdef FEAT_LISP
5451 case PV_LISP: return (char_u *)&(curbuf->b_p_lisp);
5452#endif
5453 case PV_ML: return (char_u *)&(curbuf->b_p_ml);
5454 case PV_MPS: return (char_u *)&(curbuf->b_p_mps);
5455 case PV_MA: return (char_u *)&(curbuf->b_p_ma);
5456 case PV_MOD: return (char_u *)&(curbuf->b_changed);
5457 case PV_NF: return (char_u *)&(curbuf->b_p_nf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005458 case PV_PI: return (char_u *)&(curbuf->b_p_pi);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005459#ifdef FEAT_TEXTOBJ
5460 case PV_QE: return (char_u *)&(curbuf->b_p_qe);
5461#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005462 case PV_RO: return (char_u *)&(curbuf->b_p_ro);
5463#ifdef FEAT_SMARTINDENT
5464 case PV_SI: return (char_u *)&(curbuf->b_p_si);
5465#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005466 case PV_SN: return (char_u *)&(curbuf->b_p_sn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005467 case PV_STS: return (char_u *)&(curbuf->b_p_sts);
5468#ifdef FEAT_SEARCHPATH
5469 case PV_SUA: return (char_u *)&(curbuf->b_p_sua);
5470#endif
5471 case PV_SWF: return (char_u *)&(curbuf->b_p_swf);
5472#ifdef FEAT_SYN_HL
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00005473 case PV_SMC: return (char_u *)&(curbuf->b_p_smc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005474 case PV_SYN: return (char_u *)&(curbuf->b_p_syn);
5475#endif
5476#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +02005477 case PV_SPC: return (char_u *)&(curwin->w_s->b_p_spc);
5478 case PV_SPF: return (char_u *)&(curwin->w_s->b_p_spf);
5479 case PV_SPL: return (char_u *)&(curwin->w_s->b_p_spl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480#endif
5481 case PV_SW: return (char_u *)&(curbuf->b_p_sw);
5482 case PV_TS: return (char_u *)&(curbuf->b_p_ts);
5483 case PV_TW: return (char_u *)&(curbuf->b_p_tw);
5484 case PV_TX: return (char_u *)&(curbuf->b_p_tx);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02005485#ifdef FEAT_PERSISTENT_UNDO
5486 case PV_UDF: return (char_u *)&(curbuf->b_p_udf);
5487#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005488 case PV_WM: return (char_u *)&(curbuf->b_p_wm);
5489#ifdef FEAT_KEYMAP
5490 case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
5491#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02005492#ifdef FEAT_SIGNS
5493 case PV_SCL: return (char_u *)&(curwin->w_p_scl);
5494#endif
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005495#ifdef FEAT_VARTABS
5496 case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts);
5497 case PV_VTS: return (char_u *)&(curbuf->b_p_vts);
5498#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005499 default: iemsg(_("E356: get_varp ERROR"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005500 }
5501 /* always return a valid pointer to avoid a crash! */
5502 return (char_u *)&(curbuf->b_p_wm);
5503}
5504
5505/*
Bram Moolenaardac13472019-09-16 21:06:21 +02005506 * Return a pointer to the variable for option at 'opt_idx'
5507 */
5508 char_u *
5509get_option_var(int opt_idx)
5510{
5511 return options[opt_idx].var;
5512}
5513
5514/*
5515 * Return the full name of the option at 'opt_idx'
5516 */
5517 char_u *
5518get_option_fullname(int opt_idx)
5519{
5520 return (char_u *)options[opt_idx].fullname;
5521}
5522
5523/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005524 * Get the value of 'equalprg', either the buffer-local one or the global one.
5525 */
5526 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01005527get_equalprg(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005528{
5529 if (*curbuf->b_p_ep == NUL)
5530 return p_ep;
5531 return curbuf->b_p_ep;
5532}
5533
Bram Moolenaar071d4272004-06-13 20:20:40 +00005534/*
5535 * Copy options from one window to another.
5536 * Used when splitting a window.
5537 */
5538 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005539win_copy_options(win_T *wp_from, win_T *wp_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540{
5541 copy_winopt(&wp_from->w_onebuf_opt, &wp_to->w_onebuf_opt);
5542 copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
Bram Moolenaar010ee962019-09-25 20:37:36 +02005543 after_copy_winopt(wp_to);
5544}
5545
5546/*
5547 * After copying window options: update variables depending on options.
5548 */
5549 void
Bram Moolenaar473952e2019-09-28 16:30:04 +02005550after_copy_winopt(win_T *wp UNUSED)
Bram Moolenaar010ee962019-09-25 20:37:36 +02005551{
5552#ifdef FEAT_LINEBREAK
5553 briopt_check(wp);
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02005554#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +02005555#ifdef FEAT_SYN_HL
Bram Moolenaar010ee962019-09-25 20:37:36 +02005556 fill_culopt_flags(NULL, wp);
5557 check_colorcolumn(wp);
Bram Moolenaar017ba072019-09-14 21:01:23 +02005558#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005559}
Bram Moolenaar071d4272004-06-13 20:20:40 +00005560
5561/*
5562 * Copy the options from one winopt_T to another.
5563 * Doesn't free the old option values in "to", use clear_winopt() for that.
5564 * The 'scroll' option is not copied, because it depends on the window height.
5565 * The 'previewwindow' option is reset, there can be only one preview window.
5566 */
5567 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005568copy_winopt(winopt_T *from, winopt_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005569{
5570#ifdef FEAT_ARABIC
5571 to->wo_arab = from->wo_arab;
5572#endif
5573 to->wo_list = from->wo_list;
5574 to->wo_nu = from->wo_nu;
Bram Moolenaar64486672010-05-16 15:46:46 +02005575 to->wo_rnu = from->wo_rnu;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00005576#ifdef FEAT_LINEBREAK
5577 to->wo_nuw = from->wo_nuw;
5578#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579#ifdef FEAT_RIGHTLEFT
5580 to->wo_rl = from->wo_rl;
5581 to->wo_rlc = vim_strsave(from->wo_rlc);
5582#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005583#ifdef FEAT_STL_OPT
5584 to->wo_stl = vim_strsave(from->wo_stl);
5585#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005586 to->wo_wrap = from->wo_wrap;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005587#ifdef FEAT_DIFF
5588 to->wo_wrap_save = from->wo_wrap_save;
5589#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005590#ifdef FEAT_LINEBREAK
5591 to->wo_lbr = from->wo_lbr;
Bram Moolenaar597a4222014-06-25 14:39:50 +02005592 to->wo_bri = from->wo_bri;
5593 to->wo_briopt = vim_strsave(from->wo_briopt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005594#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005595 to->wo_wcr = vim_strsave(from->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005596 to->wo_scb = from->wo_scb;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005597 to->wo_scb_save = from->wo_scb_save;
Bram Moolenaar4161dcc2010-12-02 15:33:21 +01005598 to->wo_crb = from->wo_crb;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005599 to->wo_crb_save = from->wo_crb_save;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005600#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00005601 to->wo_spell = from->wo_spell;
5602#endif
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005603#ifdef FEAT_SYN_HL
5604 to->wo_cuc = from->wo_cuc;
5605 to->wo_cul = from->wo_cul;
Bram Moolenaar410e98a2019-09-09 22:05:49 +02005606 to->wo_culopt = vim_strsave(from->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02005607 to->wo_cc = vim_strsave(from->wo_cc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005608#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005609#ifdef FEAT_DIFF
5610 to->wo_diff = from->wo_diff;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005611 to->wo_diff_saved = from->wo_diff_saved;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005612#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005613#ifdef FEAT_CONCEAL
5614 to->wo_cocu = vim_strsave(from->wo_cocu);
Bram Moolenaard497a302010-07-23 22:27:03 +02005615 to->wo_cole = from->wo_cole;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005616#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005617#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02005618 to->wo_twk = vim_strsave(from->wo_twk);
5619 to->wo_tws = vim_strsave(from->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005620#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621#ifdef FEAT_FOLDING
5622 to->wo_fdc = from->wo_fdc;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005623 to->wo_fdc_save = from->wo_fdc_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005624 to->wo_fen = from->wo_fen;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005625 to->wo_fen_save = from->wo_fen_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005626 to->wo_fdi = vim_strsave(from->wo_fdi);
5627 to->wo_fml = from->wo_fml;
5628 to->wo_fdl = from->wo_fdl;
Bram Moolenaara87aa802013-07-03 15:47:03 +02005629 to->wo_fdl_save = from->wo_fdl_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005630 to->wo_fdm = vim_strsave(from->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02005631 to->wo_fdm_save = from->wo_diff_saved
5632 ? vim_strsave(from->wo_fdm_save) : empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005633 to->wo_fdn = from->wo_fdn;
5634# ifdef FEAT_EVAL
5635 to->wo_fde = vim_strsave(from->wo_fde);
5636 to->wo_fdt = vim_strsave(from->wo_fdt);
5637# endif
5638 to->wo_fmr = vim_strsave(from->wo_fmr);
5639#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02005640#ifdef FEAT_SIGNS
5641 to->wo_scl = vim_strsave(from->wo_scl);
5642#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005643 check_winopt(to); /* don't want NULL pointers */
5644}
5645
5646/*
5647 * Check string options in a window for a NULL value.
5648 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02005649 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005650check_win_options(win_T *win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005651{
5652 check_winopt(&win->w_onebuf_opt);
5653 check_winopt(&win->w_allbuf_opt);
5654}
5655
5656/*
5657 * Check for NULL pointers in a winopt_T and replace them with empty_option.
5658 */
Bram Moolenaar8dc907d2014-06-25 14:44:10 +02005659 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005660check_winopt(winopt_T *wop UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005661{
5662#ifdef FEAT_FOLDING
5663 check_string_option(&wop->wo_fdi);
5664 check_string_option(&wop->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02005665 check_string_option(&wop->wo_fdm_save);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005666# ifdef FEAT_EVAL
5667 check_string_option(&wop->wo_fde);
5668 check_string_option(&wop->wo_fdt);
5669# endif
5670 check_string_option(&wop->wo_fmr);
5671#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02005672#ifdef FEAT_SIGNS
5673 check_string_option(&wop->wo_scl);
5674#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005675#ifdef FEAT_RIGHTLEFT
5676 check_string_option(&wop->wo_rlc);
5677#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005678#ifdef FEAT_STL_OPT
5679 check_string_option(&wop->wo_stl);
5680#endif
Bram Moolenaar1a384422010-07-14 19:53:30 +02005681#ifdef FEAT_SYN_HL
Bram Moolenaar410e98a2019-09-09 22:05:49 +02005682 check_string_option(&wop->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02005683 check_string_option(&wop->wo_cc);
5684#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005685#ifdef FEAT_CONCEAL
5686 check_string_option(&wop->wo_cocu);
5687#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005688#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02005689 check_string_option(&wop->wo_twk);
5690 check_string_option(&wop->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005691#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02005692#ifdef FEAT_LINEBREAK
5693 check_string_option(&wop->wo_briopt);
5694#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005695 check_string_option(&wop->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005696}
5697
5698/*
5699 * Free the allocated memory inside a winopt_T.
5700 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005701 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005702clear_winopt(winopt_T *wop UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703{
5704#ifdef FEAT_FOLDING
5705 clear_string_option(&wop->wo_fdi);
5706 clear_string_option(&wop->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02005707 clear_string_option(&wop->wo_fdm_save);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005708# ifdef FEAT_EVAL
5709 clear_string_option(&wop->wo_fde);
5710 clear_string_option(&wop->wo_fdt);
5711# endif
5712 clear_string_option(&wop->wo_fmr);
5713#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02005714#ifdef FEAT_SIGNS
5715 clear_string_option(&wop->wo_scl);
5716#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02005717#ifdef FEAT_LINEBREAK
5718 clear_string_option(&wop->wo_briopt);
5719#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02005720 clear_string_option(&wop->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721#ifdef FEAT_RIGHTLEFT
5722 clear_string_option(&wop->wo_rlc);
5723#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00005724#ifdef FEAT_STL_OPT
5725 clear_string_option(&wop->wo_stl);
5726#endif
Bram Moolenaar1a384422010-07-14 19:53:30 +02005727#ifdef FEAT_SYN_HL
Bram Moolenaar410e98a2019-09-09 22:05:49 +02005728 clear_string_option(&wop->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02005729 clear_string_option(&wop->wo_cc);
5730#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005731#ifdef FEAT_CONCEAL
5732 clear_string_option(&wop->wo_cocu);
5733#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005734#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02005735 clear_string_option(&wop->wo_twk);
5736 clear_string_option(&wop->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02005737#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005738}
5739
5740/*
5741 * Copy global option values to local options for one buffer.
5742 * Used when creating a new buffer and sometimes when entering a buffer.
5743 * flags:
5744 * BCO_ENTER We will enter the buf buffer.
5745 * BCO_ALWAYS Always copy the options, but only set b_p_initialized when
5746 * appropriate.
5747 * BCO_NOHELP Don't copy the values to a help buffer.
5748 */
5749 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01005750buf_copy_options(buf_T *buf, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005751{
5752 int should_copy = TRUE;
5753 char_u *save_p_isk = NULL; /* init for GCC */
5754 int dont_do_help;
5755 int did_isk = FALSE;
5756
5757 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005758 * Skip this when the option defaults have not been set yet. Happens when
5759 * main() allocates the first buffer.
5760 */
5761 if (p_cpo != NULL)
5762 {
5763 /*
5764 * Always copy when entering and 'cpo' contains 'S'.
5765 * Don't copy when already initialized.
5766 * Don't copy when 'cpo' contains 's' and not entering.
5767 * 'S' BCO_ENTER initialized 's' should_copy
5768 * yes yes X X TRUE
5769 * yes no yes X FALSE
5770 * no X yes X FALSE
5771 * X no no yes FALSE
5772 * X no no no TRUE
5773 * no yes no X TRUE
5774 */
5775 if ((vim_strchr(p_cpo, CPO_BUFOPTGLOB) == NULL || !(flags & BCO_ENTER))
5776 && (buf->b_p_initialized
5777 || (!(flags & BCO_ENTER)
5778 && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
5779 should_copy = FALSE;
5780
5781 if (should_copy || (flags & BCO_ALWAYS))
5782 {
5783 /* Don't copy the options specific to a help buffer when
5784 * BCO_NOHELP is given or the options were initialized already
5785 * (jumping back to a help file with CTRL-T or CTRL-O) */
5786 dont_do_help = ((flags & BCO_NOHELP) && buf->b_help)
5787 || buf->b_p_initialized;
5788 if (dont_do_help) /* don't free b_p_isk */
5789 {
5790 save_p_isk = buf->b_p_isk;
5791 buf->b_p_isk = NULL;
5792 }
5793 /*
Bram Moolenaar40385db2018-08-07 22:31:44 +02005794 * Always free the allocated strings. If not already initialized,
5795 * reset 'readonly' and copy 'fileformat'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005796 */
5797 if (!buf->b_p_initialized)
5798 {
5799 free_buf_options(buf, TRUE);
5800 buf->b_p_ro = FALSE; /* don't copy readonly */
5801 buf->b_p_tx = p_tx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005802 buf->b_p_fenc = vim_strsave(p_fenc);
Bram Moolenaare8ef3a02016-10-12 17:45:29 +02005803 switch (*p_ffs)
5804 {
5805 case 'm':
5806 buf->b_p_ff = vim_strsave((char_u *)FF_MAC); break;
5807 case 'd':
5808 buf->b_p_ff = vim_strsave((char_u *)FF_DOS); break;
5809 case 'u':
5810 buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); break;
5811 default:
5812 buf->b_p_ff = vim_strsave(p_ff);
5813 }
5814 if (buf->b_p_ff != NULL)
5815 buf->b_start_ffc = *buf->b_p_ff;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005816 buf->b_p_bh = empty_option;
5817 buf->b_p_bt = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005818 }
5819 else
5820 free_buf_options(buf, FALSE);
5821
5822 buf->b_p_ai = p_ai;
5823 buf->b_p_ai_nopaste = p_ai_nopaste;
5824 buf->b_p_sw = p_sw;
5825 buf->b_p_tw = p_tw;
5826 buf->b_p_tw_nopaste = p_tw_nopaste;
5827 buf->b_p_tw_nobin = p_tw_nobin;
5828 buf->b_p_wm = p_wm;
5829 buf->b_p_wm_nopaste = p_wm_nopaste;
5830 buf->b_p_wm_nobin = p_wm_nobin;
5831 buf->b_p_bin = p_bin;
Bram Moolenaare8bb2552005-07-08 22:26:47 +00005832 buf->b_p_bomb = p_bomb;
Bram Moolenaarb388be02015-07-22 22:19:38 +02005833 buf->b_p_fixeol = p_fixeol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834 buf->b_p_et = p_et;
5835 buf->b_p_et_nobin = p_et_nobin;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02005836 buf->b_p_et_nopaste = p_et_nopaste;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005837 buf->b_p_ml = p_ml;
5838 buf->b_p_ml_nobin = p_ml_nobin;
5839 buf->b_p_inf = p_inf;
Bram Moolenaar3bab9392017-04-07 15:42:25 +02005840 buf->b_p_swf = cmdmod.noswapfile ? FALSE : p_swf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005841 buf->b_p_cpt = vim_strsave(p_cpt);
Bram Moolenaare2c453d2019-08-21 14:37:09 +02005842#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarac3150d2019-07-28 16:36:39 +02005843 buf->b_p_csl = vim_strsave(p_csl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005844#endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005845#ifdef FEAT_COMPL_FUNC
5846 buf->b_p_cfu = vim_strsave(p_cfu);
Bram Moolenaare344bea2005-09-01 20:46:49 +00005847 buf->b_p_ofu = vim_strsave(p_ofu);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005848#endif
Bram Moolenaar45e18cb2019-04-28 18:05:35 +02005849#ifdef FEAT_EVAL
5850 buf->b_p_tfu = vim_strsave(p_tfu);
5851#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852 buf->b_p_sts = p_sts;
5853 buf->b_p_sts_nopaste = p_sts_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005854#ifdef FEAT_VARTABS
5855 buf->b_p_vsts = vim_strsave(p_vsts);
5856 if (p_vsts && p_vsts != empty_option)
5857 tabstop_set(p_vsts, &buf->b_p_vsts_array);
5858 else
5859 buf->b_p_vsts_array = 0;
5860 buf->b_p_vsts_nopaste = p_vsts_nopaste
5861 ? vim_strsave(p_vsts_nopaste) : NULL;
5862#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005863 buf->b_p_sn = p_sn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005864 buf->b_p_com = vim_strsave(p_com);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005865#ifdef FEAT_FOLDING
5866 buf->b_p_cms = vim_strsave(p_cms);
5867#endif
5868 buf->b_p_fo = vim_strsave(p_fo);
Bram Moolenaar86b68352004-12-27 21:59:20 +00005869 buf->b_p_flp = vim_strsave(p_flp);
Bram Moolenaar473952e2019-09-28 16:30:04 +02005870 // NOTE: Valgrind may report a bogus memory leak for 'nrformats'
5871 // when it is set to 8 bytes in defaults.vim.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005872 buf->b_p_nf = vim_strsave(p_nf);
5873 buf->b_p_mps = vim_strsave(p_mps);
5874#ifdef FEAT_SMARTINDENT
5875 buf->b_p_si = p_si;
5876#endif
5877 buf->b_p_ci = p_ci;
5878#ifdef FEAT_CINDENT
5879 buf->b_p_cin = p_cin;
5880 buf->b_p_cink = vim_strsave(p_cink);
5881 buf->b_p_cino = vim_strsave(p_cino);
5882#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005883 /* Don't copy 'filetype', it must be detected */
5884 buf->b_p_ft = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885 buf->b_p_pi = p_pi;
5886#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
5887 buf->b_p_cinw = vim_strsave(p_cinw);
5888#endif
5889#ifdef FEAT_LISP
5890 buf->b_p_lisp = p_lisp;
5891#endif
5892#ifdef FEAT_SYN_HL
5893 /* Don't copy 'syntax', it must be set */
5894 buf->b_p_syn = empty_option;
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00005895 buf->b_p_smc = p_smc;
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01005896 buf->b_s.b_syn_isk = empty_option;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005897#endif
5898#ifdef FEAT_SPELL
Bram Moolenaard5784f92010-10-13 14:05:35 +02005899 buf->b_s.b_p_spc = vim_strsave(p_spc);
Bram Moolenaar860cae12010-06-05 23:22:07 +02005900 (void)compile_cap_prog(&buf->b_s);
5901 buf->b_s.b_p_spf = vim_strsave(p_spf);
5902 buf->b_s.b_p_spl = vim_strsave(p_spl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005903#endif
5904#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
5905 buf->b_p_inde = vim_strsave(p_inde);
5906 buf->b_p_indk = vim_strsave(p_indk);
5907#endif
Bram Moolenaar9be7c042017-01-14 14:28:30 +01005908 buf->b_p_fp = empty_option;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00005909#if defined(FEAT_EVAL)
5910 buf->b_p_fex = vim_strsave(p_fex);
5911#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005912#ifdef FEAT_CRYPT
5913 buf->b_p_key = vim_strsave(p_key);
5914#endif
5915#ifdef FEAT_SEARCHPATH
5916 buf->b_p_sua = vim_strsave(p_sua);
5917#endif
5918#ifdef FEAT_KEYMAP
5919 buf->b_p_keymap = vim_strsave(p_keymap);
5920 buf->b_kmap_state |= KEYMAP_INIT;
5921#endif
Bram Moolenaar6d150f72018-04-21 20:03:20 +02005922#ifdef FEAT_TERMINAL
5923 buf->b_p_twsl = p_twsl;
5924#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005925 /* This isn't really an option, but copying the langmap and IME
5926 * state from the current buffer is better than resetting it. */
5927 buf->b_p_iminsert = p_iminsert;
5928 buf->b_p_imsearch = p_imsearch;
5929
5930 /* options that are normally global but also have a local value
5931 * are not copied, start using the global value */
5932 buf->b_p_ar = -1;
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01005933 buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02005934 buf->b_p_bkc = empty_option;
5935 buf->b_bkc_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005936#ifdef FEAT_QUICKFIX
5937 buf->b_p_gp = empty_option;
5938 buf->b_p_mp = empty_option;
5939 buf->b_p_efm = empty_option;
5940#endif
5941 buf->b_p_ep = empty_option;
5942 buf->b_p_kp = empty_option;
5943 buf->b_p_path = empty_option;
5944 buf->b_p_tags = empty_option;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01005945 buf->b_p_tc = empty_option;
5946 buf->b_tc_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005947#ifdef FEAT_FIND_ID
5948 buf->b_p_def = empty_option;
5949 buf->b_p_inc = empty_option;
5950# ifdef FEAT_EVAL
5951 buf->b_p_inex = vim_strsave(p_inex);
5952# endif
5953#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005954 buf->b_p_dict = empty_option;
5955 buf->b_p_tsr = empty_option;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005956#ifdef FEAT_TEXTOBJ
5957 buf->b_p_qe = vim_strsave(p_qe);
5958#endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00005959#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
5960 buf->b_p_bexpr = empty_option;
5961#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02005962#if defined(FEAT_CRYPT)
5963 buf->b_p_cm = empty_option;
5964#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02005965#ifdef FEAT_PERSISTENT_UNDO
5966 buf->b_p_udf = p_udf;
5967#endif
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01005968#ifdef FEAT_LISP
5969 buf->b_p_lw = empty_option;
5970#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01005971 buf->b_p_menc = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005972
5973 /*
5974 * Don't copy the options set by ex_help(), use the saved values,
5975 * when going from a help buffer to a non-help buffer.
5976 * Don't touch these at all when BCO_NOHELP is used and going from
5977 * or to a help buffer.
5978 */
5979 if (dont_do_help)
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005980 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981 buf->b_p_isk = save_p_isk;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005982#ifdef FEAT_VARTABS
5983 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
5984 tabstop_set(p_vts, &buf->b_p_vts_array);
5985 else
5986 buf->b_p_vts_array = NULL;
5987#endif
5988 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005989 else
5990 {
5991 buf->b_p_isk = vim_strsave(p_isk);
5992 did_isk = TRUE;
5993 buf->b_p_ts = p_ts;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005994#ifdef FEAT_VARTABS
5995 buf->b_p_vts = vim_strsave(p_vts);
5996 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
5997 tabstop_set(p_vts, &buf->b_p_vts_array);
5998 else
5999 buf->b_p_vts_array = NULL;
6000#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006001 buf->b_help = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006002 if (buf->b_p_bt[0] == 'h')
6003 clear_string_option(&buf->b_p_bt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006004 buf->b_p_ma = p_ma;
6005 }
6006 }
6007
6008 /*
6009 * When the options should be copied (ignoring BCO_ALWAYS), set the
6010 * flag that indicates that the options have been initialized.
6011 */
6012 if (should_copy)
6013 buf->b_p_initialized = TRUE;
6014 }
6015
6016 check_buf_options(buf); /* make sure we don't have NULLs */
6017 if (did_isk)
6018 (void)buf_init_chartab(buf, FALSE);
6019}
6020
6021/*
6022 * Reset the 'modifiable' option and its default value.
6023 */
6024 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006025reset_modifiable(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006026{
6027 int opt_idx;
6028
6029 curbuf->b_p_ma = FALSE;
6030 p_ma = FALSE;
6031 opt_idx = findoption((char_u *)"ma");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00006032 if (opt_idx >= 0)
6033 options[opt_idx].def_val[VI_DEFAULT] = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034}
6035
6036/*
6037 * Set the global value for 'iminsert' to the local value.
6038 */
6039 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006040set_iminsert_global(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041{
6042 p_iminsert = curbuf->b_p_iminsert;
6043}
6044
6045/*
6046 * Set the global value for 'imsearch' to the local value.
6047 */
6048 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006049set_imsearch_global(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006050{
6051 p_imsearch = curbuf->b_p_imsearch;
6052}
6053
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054static int expand_option_idx = -1;
6055static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL};
6056static int expand_option_flags = 0;
6057
6058 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006059set_context_in_set_cmd(
6060 expand_T *xp,
6061 char_u *arg,
6062 int opt_flags) /* OPT_GLOBAL and/or OPT_LOCAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006063{
6064 int nextchar;
6065 long_u flags = 0; /* init for GCC */
6066 int opt_idx = 0; /* init for GCC */
6067 char_u *p;
6068 char_u *s;
6069 int is_term_option = FALSE;
6070 int key;
6071
6072 expand_option_flags = opt_flags;
6073
6074 xp->xp_context = EXPAND_SETTINGS;
6075 if (*arg == NUL)
6076 {
6077 xp->xp_pattern = arg;
6078 return;
6079 }
6080 p = arg + STRLEN(arg) - 1;
6081 if (*p == ' ' && *(p - 1) != '\\')
6082 {
6083 xp->xp_pattern = p + 1;
6084 return;
6085 }
6086 while (p > arg)
6087 {
6088 s = p;
6089 /* count number of backslashes before ' ' or ',' */
6090 if (*p == ' ' || *p == ',')
6091 {
6092 while (s > arg && *(s - 1) == '\\')
6093 --s;
6094 }
6095 /* break at a space with an even number of backslashes */
6096 if (*p == ' ' && ((p - s) & 1) == 0)
6097 {
6098 ++p;
6099 break;
6100 }
6101 --p;
6102 }
Bram Moolenaar2a7b9ee2009-06-16 15:50:33 +00006103 if (STRNCMP(p, "no", 2) == 0 && STRNCMP(p, "novice", 6) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006104 {
6105 xp->xp_context = EXPAND_BOOL_SETTINGS;
6106 p += 2;
6107 }
6108 if (STRNCMP(p, "inv", 3) == 0)
6109 {
6110 xp->xp_context = EXPAND_BOOL_SETTINGS;
6111 p += 3;
6112 }
6113 xp->xp_pattern = arg = p;
6114 if (*arg == '<')
6115 {
6116 while (*p != '>')
6117 if (*p++ == NUL) /* expand terminal option name */
6118 return;
6119 key = get_special_key_code(arg + 1);
6120 if (key == 0) /* unknown name */
6121 {
6122 xp->xp_context = EXPAND_NOTHING;
6123 return;
6124 }
6125 nextchar = *++p;
6126 is_term_option = TRUE;
6127 expand_option_name[2] = KEY2TERMCAP0(key);
6128 expand_option_name[3] = KEY2TERMCAP1(key);
6129 }
6130 else
6131 {
6132 if (p[0] == 't' && p[1] == '_')
6133 {
6134 p += 2;
6135 if (*p != NUL)
6136 ++p;
6137 if (*p == NUL)
6138 return; /* expand option name */
6139 nextchar = *++p;
6140 is_term_option = TRUE;
6141 expand_option_name[2] = p[-2];
6142 expand_option_name[3] = p[-1];
6143 }
6144 else
6145 {
6146 /* Allow * wildcard */
6147 while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
6148 p++;
6149 if (*p == NUL)
6150 return;
6151 nextchar = *p;
6152 *p = NUL;
6153 opt_idx = findoption(arg);
6154 *p = nextchar;
6155 if (opt_idx == -1 || options[opt_idx].var == NULL)
6156 {
6157 xp->xp_context = EXPAND_NOTHING;
6158 return;
6159 }
6160 flags = options[opt_idx].flags;
6161 if (flags & P_BOOL)
6162 {
6163 xp->xp_context = EXPAND_NOTHING;
6164 return;
6165 }
6166 }
6167 }
6168 /* handle "-=" and "+=" */
6169 if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=')
6170 {
6171 ++p;
6172 nextchar = '=';
6173 }
6174 if ((nextchar != '=' && nextchar != ':')
6175 || xp->xp_context == EXPAND_BOOL_SETTINGS)
6176 {
6177 xp->xp_context = EXPAND_UNSUCCESSFUL;
6178 return;
6179 }
6180 if (xp->xp_context != EXPAND_BOOL_SETTINGS && p[1] == NUL)
6181 {
6182 xp->xp_context = EXPAND_OLD_SETTING;
6183 if (is_term_option)
6184 expand_option_idx = -1;
6185 else
6186 expand_option_idx = opt_idx;
6187 xp->xp_pattern = p + 1;
6188 return;
6189 }
6190 xp->xp_context = EXPAND_NOTHING;
6191 if (is_term_option || (flags & P_NUM))
6192 return;
6193
6194 xp->xp_pattern = p + 1;
6195
6196 if (flags & P_EXPAND)
6197 {
6198 p = options[opt_idx].var;
6199 if (p == (char_u *)&p_bdir
6200 || p == (char_u *)&p_dir
6201 || p == (char_u *)&p_path
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +01006202 || p == (char_u *)&p_pp
Bram Moolenaar071d4272004-06-13 20:20:40 +00006203 || p == (char_u *)&p_rtp
6204#ifdef FEAT_SEARCHPATH
6205 || p == (char_u *)&p_cdpath
6206#endif
6207#ifdef FEAT_SESSION
6208 || p == (char_u *)&p_vdir
6209#endif
6210 )
6211 {
6212 xp->xp_context = EXPAND_DIRECTORIES;
6213 if (p == (char_u *)&p_path
6214#ifdef FEAT_SEARCHPATH
6215 || p == (char_u *)&p_cdpath
6216#endif
6217 )
6218 xp->xp_backslash = XP_BS_THREE;
6219 else
6220 xp->xp_backslash = XP_BS_ONE;
6221 }
6222 else
6223 {
6224 xp->xp_context = EXPAND_FILES;
6225 /* for 'tags' need three backslashes for a space */
6226 if (p == (char_u *)&p_tags)
6227 xp->xp_backslash = XP_BS_THREE;
6228 else
6229 xp->xp_backslash = XP_BS_ONE;
6230 }
6231 }
6232
6233 /* For an option that is a list of file names, find the start of the
6234 * last file name. */
6235 for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; --p)
6236 {
6237 /* count number of backslashes before ' ' or ',' */
6238 if (*p == ' ' || *p == ',')
6239 {
6240 s = p;
6241 while (s > xp->xp_pattern && *(s - 1) == '\\')
6242 --s;
6243 if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3))
6244 || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0))
6245 {
6246 xp->xp_pattern = p + 1;
6247 break;
6248 }
6249 }
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00006250
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00006251#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00006252 /* for 'spellsuggest' start at "file:" */
6253 if (options[opt_idx].var == (char_u *)&p_sps
6254 && STRNCMP(p, "file:", 5) == 0)
6255 {
6256 xp->xp_pattern = p + 5;
6257 break;
6258 }
6259#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006260 }
6261
6262 return;
6263}
6264
6265 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006266ExpandSettings(
6267 expand_T *xp,
6268 regmatch_T *regmatch,
6269 int *num_file,
6270 char_u ***file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006271{
6272 int num_normal = 0; /* Nr of matching non-term-code settings */
6273 int num_term = 0; /* Nr of matching terminal code settings */
6274 int opt_idx;
6275 int match;
6276 int count = 0;
6277 char_u *str;
6278 int loop;
6279 int is_term_opt;
6280 char_u name_buf[MAX_KEY_NAME_LEN];
6281 static char *(names[]) = {"all", "termcap"};
6282 int ic = regmatch->rm_ic; /* remember the ignore-case flag */
6283
6284 /* do this loop twice:
6285 * loop == 0: count the number of matching options
6286 * loop == 1: copy the matching options into allocated memory
6287 */
6288 for (loop = 0; loop <= 1; ++loop)
6289 {
6290 regmatch->rm_ic = ic;
6291 if (xp->xp_context != EXPAND_BOOL_SETTINGS)
6292 {
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00006293 for (match = 0; match < (int)(sizeof(names) / sizeof(char *));
6294 ++match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006295 if (vim_regexec(regmatch, (char_u *)names[match], (colnr_T)0))
6296 {
6297 if (loop == 0)
6298 num_normal++;
6299 else
6300 (*file)[count++] = vim_strsave((char_u *)names[match]);
6301 }
6302 }
6303 for (opt_idx = 0; (str = (char_u *)options[opt_idx].fullname) != NULL;
6304 opt_idx++)
6305 {
6306 if (options[opt_idx].var == NULL)
6307 continue;
6308 if (xp->xp_context == EXPAND_BOOL_SETTINGS
6309 && !(options[opt_idx].flags & P_BOOL))
6310 continue;
Bram Moolenaardac13472019-09-16 21:06:21 +02006311 is_term_opt = istermoption_idx(opt_idx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006312 if (is_term_opt && num_normal > 0)
6313 continue;
6314 match = FALSE;
6315 if (vim_regexec(regmatch, str, (colnr_T)0)
6316 || (options[opt_idx].shortname != NULL
6317 && vim_regexec(regmatch,
6318 (char_u *)options[opt_idx].shortname, (colnr_T)0)))
6319 match = TRUE;
6320 else if (is_term_opt)
6321 {
6322 name_buf[0] = '<';
6323 name_buf[1] = 't';
6324 name_buf[2] = '_';
6325 name_buf[3] = str[2];
6326 name_buf[4] = str[3];
6327 name_buf[5] = '>';
6328 name_buf[6] = NUL;
6329 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6330 {
6331 match = TRUE;
6332 str = name_buf;
6333 }
6334 }
6335 if (match)
6336 {
6337 if (loop == 0)
6338 {
6339 if (is_term_opt)
6340 num_term++;
6341 else
6342 num_normal++;
6343 }
6344 else
6345 (*file)[count++] = vim_strsave(str);
6346 }
6347 }
6348 /*
6349 * Check terminal key codes, these are not in the option table
6350 */
6351 if (xp->xp_context != EXPAND_BOOL_SETTINGS && num_normal == 0)
6352 {
6353 for (opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++)
6354 {
6355 if (!isprint(str[0]) || !isprint(str[1]))
6356 continue;
6357
6358 name_buf[0] = 't';
6359 name_buf[1] = '_';
6360 name_buf[2] = str[0];
6361 name_buf[3] = str[1];
6362 name_buf[4] = NUL;
6363
6364 match = FALSE;
6365 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6366 match = TRUE;
6367 else
6368 {
6369 name_buf[0] = '<';
6370 name_buf[1] = 't';
6371 name_buf[2] = '_';
6372 name_buf[3] = str[0];
6373 name_buf[4] = str[1];
6374 name_buf[5] = '>';
6375 name_buf[6] = NUL;
6376
6377 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6378 match = TRUE;
6379 }
6380 if (match)
6381 {
6382 if (loop == 0)
6383 num_term++;
6384 else
6385 (*file)[count++] = vim_strsave(name_buf);
6386 }
6387 }
6388
6389 /*
6390 * Check special key names.
6391 */
6392 regmatch->rm_ic = TRUE; /* ignore case here */
6393 for (opt_idx = 0; (str = get_key_name(opt_idx)) != NULL; opt_idx++)
6394 {
6395 name_buf[0] = '<';
6396 STRCPY(name_buf + 1, str);
6397 STRCAT(name_buf, ">");
6398
6399 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
6400 {
6401 if (loop == 0)
6402 num_term++;
6403 else
6404 (*file)[count++] = vim_strsave(name_buf);
6405 }
6406 }
6407 }
6408 if (loop == 0)
6409 {
6410 if (num_normal > 0)
6411 *num_file = num_normal;
6412 else if (num_term > 0)
6413 *num_file = num_term;
6414 else
6415 return OK;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02006416 *file = ALLOC_MULT(char_u *, *num_file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006417 if (*file == NULL)
6418 {
6419 *file = (char_u **)"";
6420 return FAIL;
6421 }
6422 }
6423 }
6424 return OK;
6425}
6426
6427 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006428ExpandOldSetting(int *num_file, char_u ***file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006429{
6430 char_u *var = NULL; /* init for GCC */
6431 char_u *buf;
6432
6433 *num_file = 0;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02006434 *file = ALLOC_ONE(char_u *);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006435 if (*file == NULL)
6436 return FAIL;
6437
6438 /*
6439 * For a terminal key code expand_option_idx is < 0.
6440 */
6441 if (expand_option_idx < 0)
6442 {
6443 var = find_termcode(expand_option_name + 2);
6444 if (var == NULL)
6445 expand_option_idx = findoption(expand_option_name);
6446 }
6447
6448 if (expand_option_idx >= 0)
6449 {
6450 /* put string of option value in NameBuff */
6451 option_value2string(&options[expand_option_idx], expand_option_flags);
6452 var = NameBuff;
6453 }
6454 else if (var == NULL)
6455 var = (char_u *)"";
6456
6457 /* A backslash is required before some characters. This is the reverse of
6458 * what happens in do_set(). */
6459 buf = vim_strsave_escaped(var, escape_chars);
6460
6461 if (buf == NULL)
6462 {
Bram Moolenaard23a8232018-02-10 18:45:26 +01006463 VIM_CLEAR(*file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006464 return FAIL;
6465 }
6466
6467#ifdef BACKSLASH_IN_FILENAME
6468 /* For MS-Windows et al. we don't double backslashes at the start and
6469 * before a file name character. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006470 for (var = buf; *var != NUL; MB_PTR_ADV(var))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006471 if (var[0] == '\\' && var[1] == '\\'
6472 && expand_option_idx >= 0
6473 && (options[expand_option_idx].flags & P_EXPAND)
6474 && vim_isfilec(var[2])
6475 && (var[2] != '\\' || (var == buf && var[4] != '\\')))
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00006476 STRMOVE(var, var + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006477#endif
6478
6479 *file[0] = buf;
6480 *num_file = 1;
6481 return OK;
6482}
Bram Moolenaar071d4272004-06-13 20:20:40 +00006483
6484/*
6485 * Get the value for the numeric or string option *opp in a nice format into
6486 * NameBuff[]. Must not be called with a hidden option!
6487 */
6488 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006489option_value2string(
6490 struct vimoption *opp,
6491 int opt_flags) /* OPT_GLOBAL and/or OPT_LOCAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006492{
6493 char_u *varp;
6494
6495 varp = get_varp_scope(opp, opt_flags);
6496
6497 if (opp->flags & P_NUM)
6498 {
6499 long wc = 0;
6500
6501 if (wc_use_keyname(varp, &wc))
6502 STRCPY(NameBuff, get_special_key_name((int)wc, 0));
6503 else if (wc != 0)
6504 STRCPY(NameBuff, transchar((int)wc));
6505 else
6506 sprintf((char *)NameBuff, "%ld", *(long *)varp);
6507 }
6508 else /* P_STRING */
6509 {
6510 varp = *(char_u **)(varp);
6511 if (varp == NULL) /* just in case */
6512 NameBuff[0] = NUL;
6513#ifdef FEAT_CRYPT
6514 /* don't show the actual value of 'key', only that it's set */
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006515 else if (opp->var == (char_u *)&p_key && *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006516 STRCPY(NameBuff, "*****");
6517#endif
6518 else if (opp->flags & P_EXPAND)
6519 home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE);
6520 /* Translate 'pastetoggle' into special key names */
6521 else if ((char_u **)opp->var == &p_pt)
6522 str2specialbuf(p_pt, NameBuff, MAXPATHL);
6523 else
Bram Moolenaarce0842a2005-07-18 21:58:11 +00006524 vim_strncpy(NameBuff, varp, MAXPATHL - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006525 }
6526}
6527
6528/*
6529 * Return TRUE if "varp" points to 'wildchar' or 'wildcharm' and it can be
6530 * printed as a keyname.
6531 * "*wcp" is set to the value of the option if it's 'wildchar' or 'wildcharm'.
6532 */
6533 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006534wc_use_keyname(char_u *varp, long *wcp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006535{
6536 if (((long *)varp == &p_wc) || ((long *)varp == &p_wcm))
6537 {
6538 *wcp = *(long *)varp;
6539 if (IS_SPECIAL(*wcp) || find_special_key_in_table((int)*wcp) >= 0)
6540 return TRUE;
6541 }
6542 return FALSE;
6543}
6544
Bram Moolenaar071d4272004-06-13 20:20:40 +00006545/*
6546 * Return TRUE if format option 'x' is in effect.
6547 * Take care of no formatting when 'paste' is set.
6548 */
6549 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006550has_format_option(int x)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006551{
6552 if (p_paste)
6553 return FALSE;
6554 return (vim_strchr(curbuf->b_p_fo, x) != NULL);
6555}
6556
6557/*
6558 * Return TRUE if "x" is present in 'shortmess' option, or
6559 * 'shortmess' contains 'a' and "x" is present in SHM_A.
6560 */
6561 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006562shortmess(int x)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006563{
Bram Moolenaar7f29f7a2012-02-29 13:51:37 +01006564 return p_shm != NULL &&
6565 ( vim_strchr(p_shm, x) != NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006566 || (vim_strchr(p_shm, 'a') != NULL
6567 && vim_strchr((char_u *)SHM_A, x) != NULL));
6568}
6569
6570/*
6571 * paste_option_changed() - Called after p_paste was set or reset.
6572 */
6573 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006574paste_option_changed(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006575{
6576 static int old_p_paste = FALSE;
6577 static int save_sm = 0;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006578 static int save_sta = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006579#ifdef FEAT_CMDL_INFO
6580 static int save_ru = 0;
6581#endif
6582#ifdef FEAT_RIGHTLEFT
6583 static int save_ri = 0;
6584 static int save_hkmap = 0;
6585#endif
6586 buf_T *buf;
6587
6588 if (p_paste)
6589 {
6590 /*
6591 * Paste switched from off to on.
6592 * Save the current values, so they can be restored later.
6593 */
6594 if (!old_p_paste)
6595 {
6596 /* save options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02006597 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006598 {
6599 buf->b_p_tw_nopaste = buf->b_p_tw;
6600 buf->b_p_wm_nopaste = buf->b_p_wm;
6601 buf->b_p_sts_nopaste = buf->b_p_sts;
6602 buf->b_p_ai_nopaste = buf->b_p_ai;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006603 buf->b_p_et_nopaste = buf->b_p_et;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006604#ifdef FEAT_VARTABS
6605 if (buf->b_p_vsts_nopaste)
6606 vim_free(buf->b_p_vsts_nopaste);
6607 buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
6608 ? vim_strsave(buf->b_p_vsts) : NULL;
6609#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006610 }
6611
6612 /* save global options */
6613 save_sm = p_sm;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006614 save_sta = p_sta;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006615#ifdef FEAT_CMDL_INFO
6616 save_ru = p_ru;
6617#endif
6618#ifdef FEAT_RIGHTLEFT
6619 save_ri = p_ri;
6620 save_hkmap = p_hkmap;
6621#endif
6622 /* save global values for local buffer options */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006623 p_ai_nopaste = p_ai;
6624 p_et_nopaste = p_et;
6625 p_sts_nopaste = p_sts;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006626 p_tw_nopaste = p_tw;
6627 p_wm_nopaste = p_wm;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006628#ifdef FEAT_VARTABS
6629 if (p_vsts_nopaste)
6630 vim_free(p_vsts_nopaste);
6631 p_vsts_nopaste = p_vsts && p_vsts != empty_option ? vim_strsave(p_vsts) : NULL;
6632#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006633 }
6634
6635 /*
6636 * Always set the option values, also when 'paste' is set when it is
6637 * already on.
6638 */
6639 /* set options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02006640 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006641 {
6642 buf->b_p_tw = 0; /* textwidth is 0 */
6643 buf->b_p_wm = 0; /* wrapmargin is 0 */
6644 buf->b_p_sts = 0; /* softtabstop is 0 */
6645 buf->b_p_ai = 0; /* no auto-indent */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006646 buf->b_p_et = 0; /* no expandtab */
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006647#ifdef FEAT_VARTABS
6648 if (buf->b_p_vsts)
6649 free_string_option(buf->b_p_vsts);
6650 buf->b_p_vsts = empty_option;
6651 if (buf->b_p_vsts_array)
6652 vim_free(buf->b_p_vsts_array);
6653 buf->b_p_vsts_array = 0;
6654#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006655 }
6656
6657 /* set global options */
6658 p_sm = 0; /* no showmatch */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006659 p_sta = 0; /* no smarttab */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006660#ifdef FEAT_CMDL_INFO
Bram Moolenaar071d4272004-06-13 20:20:40 +00006661 if (p_ru)
6662 status_redraw_all(); /* redraw to remove the ruler */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006663 p_ru = 0; /* no ruler */
6664#endif
6665#ifdef FEAT_RIGHTLEFT
6666 p_ri = 0; /* no reverse insert */
6667 p_hkmap = 0; /* no Hebrew keyboard */
6668#endif
6669 /* set global values for local buffer options */
6670 p_tw = 0;
6671 p_wm = 0;
6672 p_sts = 0;
6673 p_ai = 0;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006674#ifdef FEAT_VARTABS
6675 if (p_vsts)
6676 free_string_option(p_vsts);
6677 p_vsts = empty_option;
6678#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006679 }
6680
6681 /*
6682 * Paste switched from on to off: Restore saved values.
6683 */
6684 else if (old_p_paste)
6685 {
6686 /* restore options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02006687 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006688 {
6689 buf->b_p_tw = buf->b_p_tw_nopaste;
6690 buf->b_p_wm = buf->b_p_wm_nopaste;
6691 buf->b_p_sts = buf->b_p_sts_nopaste;
6692 buf->b_p_ai = buf->b_p_ai_nopaste;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006693 buf->b_p_et = buf->b_p_et_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006694#ifdef FEAT_VARTABS
6695 if (buf->b_p_vsts)
6696 free_string_option(buf->b_p_vsts);
6697 buf->b_p_vsts = buf->b_p_vsts_nopaste
6698 ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option;
6699 if (buf->b_p_vsts_array)
6700 vim_free(buf->b_p_vsts_array);
6701 if (buf->b_p_vsts && buf->b_p_vsts != empty_option)
6702 tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
6703 else
6704 buf->b_p_vsts_array = 0;
6705#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006706 }
6707
6708 /* restore global options */
6709 p_sm = save_sm;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006710 p_sta = save_sta;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006711#ifdef FEAT_CMDL_INFO
Bram Moolenaar071d4272004-06-13 20:20:40 +00006712 if (p_ru != save_ru)
6713 status_redraw_all(); /* redraw to draw the ruler */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006714 p_ru = save_ru;
6715#endif
6716#ifdef FEAT_RIGHTLEFT
6717 p_ri = save_ri;
6718 p_hkmap = save_hkmap;
6719#endif
6720 /* set global values for local buffer options */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02006721 p_ai = p_ai_nopaste;
6722 p_et = p_et_nopaste;
6723 p_sts = p_sts_nopaste;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006724 p_tw = p_tw_nopaste;
6725 p_wm = p_wm_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02006726#ifdef FEAT_VARTABS
6727 if (p_vsts)
6728 free_string_option(p_vsts);
6729 p_vsts = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : empty_option;
6730#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006731 }
6732
6733 old_p_paste = p_paste;
6734}
6735
6736/*
6737 * vimrc_found() - Called when a ".vimrc" or "VIMINIT" has been found.
6738 *
6739 * Reset 'compatible' and set the values for options that didn't get set yet
6740 * to the Vim defaults.
6741 * Don't do this if the 'compatible' option has been set or reset before.
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006742 * When "fname" is not NULL, use it to set $"envname" when it wasn't set yet.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006743 */
6744 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006745vimrc_found(char_u *fname, char_u *envname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006746{
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006747 int opt_idx;
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00006748 int dofree = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006749 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006750
6751 if (!option_was_set((char_u *)"cp"))
6752 {
6753 p_cp = FALSE;
Bram Moolenaardac13472019-09-16 21:06:21 +02006754 for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006755 if (!(options[opt_idx].flags & (P_WAS_SET|P_VI_DEF)))
6756 set_option_default(opt_idx, OPT_FREE, FALSE);
6757 didset_options();
Bram Moolenaare68c25c2015-08-25 15:39:55 +02006758 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006759 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +00006760
6761 if (fname != NULL)
6762 {
6763 p = vim_getenv(envname, &dofree);
6764 if (p == NULL)
6765 {
6766 /* Set $MYVIMRC to the first vimrc file found. */
6767 p = FullName_save(fname, FALSE);
6768 if (p != NULL)
6769 {
6770 vim_setenv(envname, p);
6771 vim_free(p);
6772 }
6773 }
6774 else if (dofree)
6775 vim_free(p);
6776 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006777}
6778
6779/*
6780 * Set 'compatible' on or off. Called for "-C" and "-N" command line arg.
6781 */
6782 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006783change_compatible(int on)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006784{
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00006785 int opt_idx;
6786
Bram Moolenaar071d4272004-06-13 20:20:40 +00006787 if (p_cp != on)
6788 {
6789 p_cp = on;
6790 compatible_set();
6791 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00006792 opt_idx = findoption((char_u *)"cp");
6793 if (opt_idx >= 0)
6794 options[opt_idx].flags |= P_WAS_SET;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006795}
6796
6797/*
6798 * Return TRUE when option "name" has been set.
Bram Moolenaar1a4a75c2013-07-28 16:03:06 +02006799 * Only works correctly for global options.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006800 */
6801 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006802option_was_set(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006803{
6804 int idx;
6805
6806 idx = findoption(name);
6807 if (idx < 0) /* unknown option */
6808 return FALSE;
6809 if (options[idx].flags & P_WAS_SET)
6810 return TRUE;
6811 return FALSE;
6812}
6813
6814/*
Bram Moolenaar15d55de2012-12-05 14:43:02 +01006815 * Reset the flag indicating option "name" was set.
6816 */
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02006817 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006818reset_option_was_set(char_u *name)
Bram Moolenaar15d55de2012-12-05 14:43:02 +01006819{
6820 int idx = findoption(name);
6821
6822 if (idx >= 0)
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02006823 {
Bram Moolenaar15d55de2012-12-05 14:43:02 +01006824 options[idx].flags &= ~P_WAS_SET;
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02006825 return OK;
6826 }
6827 return FAIL;
Bram Moolenaar15d55de2012-12-05 14:43:02 +01006828}
6829
6830/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006831 * compatible_set() - Called when 'compatible' has been set or unset.
6832 *
6833 * When 'compatible' set: Set all relevant options (those that have the P_VIM)
6834 * flag) to a Vi compatible value.
6835 * When 'compatible' is unset: Set all options that have a different default
6836 * for Vim (without the P_VI_DEF flag) to that default.
6837 */
6838 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006839compatible_set(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006840{
6841 int opt_idx;
6842
Bram Moolenaardac13472019-09-16 21:06:21 +02006843 for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006844 if ( ((options[opt_idx].flags & P_VIM) && p_cp)
6845 || (!(options[opt_idx].flags & P_VI_DEF) && !p_cp))
6846 set_option_default(opt_idx, OPT_FREE, p_cp);
6847 didset_options();
Bram Moolenaare68c25c2015-08-25 15:39:55 +02006848 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006849}
6850
Bram Moolenaardac13472019-09-16 21:06:21 +02006851#if defined(FEAT_LINEBREAK) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006852
Bram Moolenaar071d4272004-06-13 20:20:40 +00006853/*
6854 * fill_breakat_flags() -- called when 'breakat' changes value.
6855 */
Bram Moolenaardac13472019-09-16 21:06:21 +02006856 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006857fill_breakat_flags(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006858{
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00006859 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006860 int i;
6861
6862 for (i = 0; i < 256; i++)
6863 breakat_flags[i] = FALSE;
6864
6865 if (p_breakat != NULL)
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00006866 for (p = p_breakat; *p; p++)
6867 breakat_flags[*p] = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006868}
Bram Moolenaar071d4272004-06-13 20:20:40 +00006869#endif
6870
6871/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006872 * Read the 'wildmode' option, fill wim_flags[].
6873 */
Bram Moolenaardac13472019-09-16 21:06:21 +02006874 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006875check_opt_wim(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006876{
6877 char_u new_wim_flags[4];
6878 char_u *p;
6879 int i;
6880 int idx = 0;
6881
6882 for (i = 0; i < 4; ++i)
6883 new_wim_flags[i] = 0;
6884
6885 for (p = p_wim; *p; ++p)
6886 {
6887 for (i = 0; ASCII_ISALPHA(p[i]); ++i)
6888 ;
6889 if (p[i] != NUL && p[i] != ',' && p[i] != ':')
6890 return FAIL;
6891 if (i == 7 && STRNCMP(p, "longest", 7) == 0)
6892 new_wim_flags[idx] |= WIM_LONGEST;
6893 else if (i == 4 && STRNCMP(p, "full", 4) == 0)
6894 new_wim_flags[idx] |= WIM_FULL;
6895 else if (i == 4 && STRNCMP(p, "list", 4) == 0)
6896 new_wim_flags[idx] |= WIM_LIST;
6897 else
6898 return FAIL;
6899 p += i;
6900 if (*p == NUL)
6901 break;
6902 if (*p == ',')
6903 {
6904 if (idx == 3)
6905 return FAIL;
6906 ++idx;
6907 }
6908 }
6909
6910 /* fill remaining entries with last flag */
6911 while (idx < 3)
6912 {
6913 new_wim_flags[idx + 1] = new_wim_flags[idx];
6914 ++idx;
6915 }
6916
6917 /* only when there are no errors, wim_flags[] is changed */
6918 for (i = 0; i < 4; ++i)
6919 wim_flags[i] = new_wim_flags[i];
6920 return OK;
6921}
6922
6923/*
6924 * Check if backspacing over something is allowed.
6925 */
6926 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006927can_bs(
6928 int what) /* BS_INDENT, BS_EOL or BS_START */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006929{
Bram Moolenaar6b810d92018-06-04 17:28:44 +02006930#ifdef FEAT_JOB_CHANNEL
6931 if (what == BS_START && bt_prompt(curbuf))
6932 return FALSE;
6933#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934 switch (*p_bs)
6935 {
6936 case '2': return TRUE;
6937 case '1': return (what != BS_START);
6938 case '0': return FALSE;
6939 }
6940 return vim_strchr(p_bs, what) != NULL;
6941}
6942
6943/*
6944 * Save the current values of 'fileformat' and 'fileencoding', so that we know
6945 * the file must be considered changed when the value is different.
6946 */
6947 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006948save_file_ff(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006949{
6950 buf->b_start_ffc = *buf->b_p_ff;
6951 buf->b_start_eol = buf->b_p_eol;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00006952 buf->b_start_bomb = buf->b_p_bomb;
6953
Bram Moolenaar071d4272004-06-13 20:20:40 +00006954 /* Only use free/alloc when necessary, they take time. */
6955 if (buf->b_start_fenc == NULL
6956 || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0)
6957 {
6958 vim_free(buf->b_start_fenc);
6959 buf->b_start_fenc = vim_strsave(buf->b_p_fenc);
6960 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006961}
6962
6963/*
6964 * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value
6965 * from when editing started (save_file_ff() called).
Bram Moolenaar83eb8852007-08-12 13:51:26 +00006966 * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
6967 * changed and 'binary' is not set.
Bram Moolenaar34d72d42015-07-17 14:18:08 +02006968 * Also when 'endofline' was changed and 'fixeol' is not set.
Bram Moolenaar164c60f2011-01-22 00:11:50 +01006969 * When "ignore_empty" is true don't consider a new, empty buffer to be
6970 * changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006971 */
6972 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006973file_ff_differs(buf_T *buf, int ignore_empty)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006974{
Bram Moolenaar9cffde92007-07-24 07:51:18 +00006975 /* In a buffer that was never loaded the options are not valid. */
6976 if (buf->b_flags & BF_NEVERLOADED)
6977 return FALSE;
Bram Moolenaar164c60f2011-01-22 00:11:50 +01006978 if (ignore_empty
6979 && (buf->b_flags & BF_NEW)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006980 && buf->b_ml.ml_line_count == 1
6981 && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL)
6982 return FALSE;
6983 if (buf->b_start_ffc != *buf->b_p_ff)
6984 return TRUE;
Bram Moolenaar34d72d42015-07-17 14:18:08 +02006985 if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006986 return TRUE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00006987 if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb)
6988 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006989 if (buf->b_start_fenc == NULL)
6990 return (*buf->b_p_fenc != NUL);
6991 return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006992}
6993
6994/*
Bram Moolenaar375e3392019-01-31 18:26:10 +01006995 * Return the effective 'scrolloff' value for the current window, using the
6996 * global value when appropriate.
6997 */
6998 long
6999get_scrolloff_value(void)
7000{
7001 return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
7002}
7003
7004/*
7005 * Return the effective 'sidescrolloff' value for the current window, using the
7006 * global value when appropriate.
7007 */
7008 long
7009get_sidescrolloff_value(void)
7010{
7011 return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
7012}
7013
7014/*
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01007015 * Check matchpairs option for "*initc".
7016 * If there is a match set "*initc" to the matching character and "*findc" to
7017 * the opposite character. Set "*backwards" to the direction.
7018 * When "switchit" is TRUE swap the direction.
7019 */
7020 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007021find_mps_values(
7022 int *initc,
7023 int *findc,
7024 int *backwards,
7025 int switchit)
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01007026{
7027 char_u *ptr;
7028
7029 ptr = curbuf->b_p_mps;
7030 while (*ptr != NUL)
7031 {
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01007032 if (has_mbyte)
7033 {
7034 char_u *prev;
7035
7036 if (mb_ptr2char(ptr) == *initc)
7037 {
7038 if (switchit)
7039 {
7040 *findc = *initc;
7041 *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
7042 *backwards = TRUE;
7043 }
7044 else
7045 {
7046 *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
7047 *backwards = FALSE;
7048 }
7049 return;
7050 }
7051 prev = ptr;
7052 ptr += mb_ptr2len(ptr) + 1;
7053 if (mb_ptr2char(ptr) == *initc)
7054 {
7055 if (switchit)
7056 {
7057 *findc = *initc;
7058 *initc = mb_ptr2char(prev);
7059 *backwards = FALSE;
7060 }
7061 else
7062 {
7063 *findc = mb_ptr2char(prev);
7064 *backwards = TRUE;
7065 }
7066 return;
7067 }
7068 ptr += mb_ptr2len(ptr);
7069 }
7070 else
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01007071 {
7072 if (*ptr == *initc)
7073 {
7074 if (switchit)
7075 {
7076 *backwards = TRUE;
7077 *findc = *initc;
7078 *initc = ptr[2];
7079 }
7080 else
7081 {
7082 *backwards = FALSE;
7083 *findc = ptr[2];
7084 }
7085 return;
7086 }
7087 ptr += 2;
7088 if (*ptr == *initc)
7089 {
7090 if (switchit)
7091 {
7092 *backwards = FALSE;
7093 *findc = *initc;
7094 *initc = ptr[-2];
7095 }
7096 else
7097 {
7098 *backwards = TRUE;
7099 *findc = ptr[-2];
7100 }
7101 return;
7102 }
7103 ++ptr;
7104 }
7105 if (*ptr == ',')
7106 ++ptr;
7107 }
7108}
Bram Moolenaar597a4222014-06-25 14:39:50 +02007109
7110#if defined(FEAT_LINEBREAK) || defined(PROTO)
7111/*
7112 * This is called when 'breakindentopt' is changed and when a window is
7113 * initialized.
7114 */
Bram Moolenaardac13472019-09-16 21:06:21 +02007115 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007116briopt_check(win_T *wp)
Bram Moolenaar597a4222014-06-25 14:39:50 +02007117{
7118 char_u *p;
7119 int bri_shift = 0;
7120 long bri_min = 20;
7121 int bri_sbr = FALSE;
7122
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02007123 p = wp->w_p_briopt;
Bram Moolenaar597a4222014-06-25 14:39:50 +02007124 while (*p != NUL)
7125 {
7126 if (STRNCMP(p, "shift:", 6) == 0
7127 && ((p[6] == '-' && VIM_ISDIGIT(p[7])) || VIM_ISDIGIT(p[6])))
7128 {
7129 p += 6;
7130 bri_shift = getdigits(&p);
7131 }
7132 else if (STRNCMP(p, "min:", 4) == 0 && VIM_ISDIGIT(p[4]))
7133 {
7134 p += 4;
7135 bri_min = getdigits(&p);
7136 }
7137 else if (STRNCMP(p, "sbr", 3) == 0)
7138 {
7139 p += 3;
7140 bri_sbr = TRUE;
7141 }
7142 if (*p != ',' && *p != NUL)
7143 return FAIL;
7144 if (*p == ',')
7145 ++p;
7146 }
7147
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02007148 wp->w_p_brishift = bri_shift;
7149 wp->w_p_brimin = bri_min;
7150 wp->w_p_brisbr = bri_sbr;
Bram Moolenaar597a4222014-06-25 14:39:50 +02007151
7152 return OK;
7153}
7154#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02007155
7156/*
7157 * Get the local or global value of 'backupcopy'.
7158 */
7159 unsigned int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007160get_bkc_value(buf_T *buf)
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02007161{
7162 return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
7163}
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007164
7165#if defined(FEAT_SIGNS) || defined(PROTO)
7166/*
7167 * Return TRUE when window "wp" has a column to draw signs in.
7168 */
7169 int
7170signcolumn_on(win_T *wp)
7171{
Bram Moolenaar394c5d82019-06-17 21:48:05 +02007172 // If 'signcolumn' is set to 'number', signs are displayed in the 'number'
7173 // column (if present). Otherwise signs are to be displayed in the sign
7174 // column.
7175 if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
7176 return wp->w_buffer->b_signlist != NULL && !wp->w_p_nu && !wp->w_p_rnu;
7177
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007178 if (*wp->w_p_scl == 'n')
7179 return FALSE;
7180 if (*wp->w_p_scl == 'y')
7181 return TRUE;
7182 return (wp->w_buffer->b_signlist != NULL
7183# ifdef FEAT_NETBEANS_INTG
7184 || wp->w_buffer->b_has_sign_column
7185# endif
7186 );
7187}
7188#endif
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02007189
7190#if defined(FEAT_EVAL) || defined(PROTO)
7191/*
7192 * Get window or buffer local options.
7193 */
7194 dict_T *
7195get_winbuf_options(int bufopt)
7196{
7197 dict_T *d;
7198 int opt_idx;
7199
7200 d = dict_alloc();
7201 if (d == NULL)
7202 return NULL;
7203
Bram Moolenaardac13472019-09-16 21:06:21 +02007204 for (opt_idx = 0; !istermoption_idx(opt_idx); opt_idx++)
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02007205 {
7206 struct vimoption *opt = &options[opt_idx];
7207
7208 if ((bufopt && (opt->indir & PV_BUF))
7209 || (!bufopt && (opt->indir & PV_WIN)))
7210 {
7211 char_u *varp = get_varp(opt);
7212
7213 if (varp != NULL)
7214 {
7215 if (opt->flags & P_STRING)
Bram Moolenaare0be1672018-07-08 16:50:37 +02007216 dict_add_string(d, opt->fullname, *(char_u **)varp);
Bram Moolenaar789a5c02016-09-12 19:51:11 +02007217 else if (opt->flags & P_NUM)
Bram Moolenaare0be1672018-07-08 16:50:37 +02007218 dict_add_number(d, opt->fullname, *(long *)varp);
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02007219 else
Bram Moolenaare0be1672018-07-08 16:50:37 +02007220 dict_add_number(d, opt->fullname, *(int *)varp);
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02007221 }
7222 }
7223 }
7224
7225 return d;
7226}
7227#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +02007228
Bram Moolenaardac13472019-09-16 21:06:21 +02007229#if defined(FEAT_SYN_HL) || defined(PROTO)
Bram Moolenaar017ba072019-09-14 21:01:23 +02007230/*
7231 * This is called when 'culopt' is changed
7232 */
Bram Moolenaardac13472019-09-16 21:06:21 +02007233 int
Bram Moolenaar017ba072019-09-14 21:01:23 +02007234fill_culopt_flags(char_u *val, win_T *wp)
7235{
7236 char_u *p;
7237 char_u culopt_flags_new = 0;
7238
7239 if (val == NULL)
7240 p = wp->w_p_culopt;
7241 else
7242 p = val;
7243 while (*p != NUL)
7244 {
7245 if (STRNCMP(p, "line", 4) == 0)
7246 {
7247 p += 4;
7248 culopt_flags_new |= CULOPT_LINE;
7249 }
7250 else if (STRNCMP(p, "both", 4) == 0)
7251 {
7252 p += 4;
7253 culopt_flags_new |= CULOPT_LINE | CULOPT_NBR;
7254 }
7255 else if (STRNCMP(p, "number", 6) == 0)
7256 {
7257 p += 6;
7258 culopt_flags_new |= CULOPT_NBR;
7259 }
7260 else if (STRNCMP(p, "screenline", 10) == 0)
7261 {
7262 p += 10;
7263 culopt_flags_new |= CULOPT_SCRLINE;
7264 }
7265
7266 if (*p != ',' && *p != NUL)
7267 return FAIL;
7268 if (*p == ',')
7269 ++p;
7270 }
7271
7272 // Can't have both "line" and "screenline".
7273 if ((culopt_flags_new & CULOPT_LINE) && (culopt_flags_new & CULOPT_SCRLINE))
7274 return FAIL;
7275 wp->w_p_culopt_flags = culopt_flags_new;
7276
7277 return OK;
7278}
7279#endif