blob: 99e046f3f14b669febf27f8c56157fbc19995b11 [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 Moolenaar916a8182018-11-25 02:18:29 +010041static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010042static char_u *option_expand(int opt_idx, char_u *val);
43static void didset_options(void);
44static void didset_options2(void);
45static void check_string_option(char_u **pp);
Bram Moolenaard1f56e62006-02-22 21:25:37 +000046#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010047static long_u *insecure_flag(int opt_idx, int opt_flags);
Bram Moolenaard1f56e62006-02-22 21:25:37 +000048#else
49# define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
50#endif
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010051static void set_string_option_global(int opt_idx, char_u **varp);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010052static char *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char *errbuf, int opt_flags, int *value_checked);
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020053#ifdef FEAT_STL_OPT
54static char *check_stl_option(char_u *s);
55#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000056#ifdef FEAT_CLIPBOARD
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010057static char *check_clipboard_option(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000058#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000059#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +020060static void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +000061#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +010062static char *set_bool_option(int opt_idx, char_u *varp, int value, int opt_flags);
63static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, size_t errbuflen, int opt_flags);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010064static void check_redraw(long_u flags);
65static int findoption(char_u *);
Bram Moolenaar9cf4b502018-07-23 04:12:03 +020066static int find_key_option(char_u *arg_arg, int has_lt);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010067static void showoptions(int all, int opt_flags);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +020068static int optval_default(struct vimoption *, char_u *varp, int compatible);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010069static void showoneopt(struct vimoption *, int opt_flags);
Bram Moolenaared18f2c2019-01-24 20:30:52 +010070static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, long_u flags);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010071static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep);
72static int put_setbool(FILE *fd, char *cmd, char *name, int value);
73static int istermoption(struct vimoption *);
74static char_u *get_varp_scope(struct vimoption *p, int opt_flags);
75static char_u *get_varp(struct vimoption *);
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020076static void check_win_options(win_T *win);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010077static void option_value2string(struct vimoption *, int opt_flags);
78static void check_winopt(winopt_T *wop);
79static int wc_use_keyname(char_u *varp, long *wcp);
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010080static void paste_option_changed(void);
81static void compatible_set(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000082#ifdef FEAT_LINEBREAK
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010083static void fill_breakat_flags(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000084#endif
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010085static int opt_strings_flags(char_u *val, char **values, unsigned *flagp, int list);
86static int check_opt_strings(char_u *val, char **values, int);
87static int check_opt_wim(void);
Bram Moolenaar285ed7e2014-08-24 21:39:49 +020088#ifdef FEAT_LINEBREAK
Bram Moolenaarbaaa7e92016-01-29 22:47:03 +010089static int briopt_check(win_T *wp);
Bram Moolenaar285ed7e2014-08-24 21:39:49 +020090#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +020091#ifdef FEAT_SYN_HL
92static int fill_culopt_flags(char_u *val, win_T *wp);
93#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000094
95/*
96 * Initialize the options, first part.
97 *
98 * Called only once from main(), just after creating the first buffer.
Bram Moolenaar07268702018-03-01 21:57:32 +010099 * If "clean_arg" is TRUE Vim was started with --clean.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100 */
101 void
Bram Moolenaar07268702018-03-01 21:57:32 +0100102set_init_1(int clean_arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103{
104 char_u *p;
105 int opt_idx;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000106 long_u n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107
108#ifdef FEAT_LANGMAP
109 langmap_init();
110#endif
111
112 /* Be Vi compatible by default */
113 p_cp = TRUE;
114
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000115 /* Use POSIX compatibility when $VIM_POSIX is set. */
116 if (mch_getenv((char_u *)"VIM_POSIX") != NULL)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000117 {
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000118 set_string_default("cpo", (char_u *)CPO_ALL);
Bram Moolenaar9dfa3132019-05-04 21:08:40 +0200119 set_string_default("shm", (char_u *)SHM_POSIX);
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000120 }
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000121
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122 /*
123 * Find default value for 'shell' option.
Bram Moolenaar7c626922005-02-07 22:01:03 +0000124 * Don't use it if it is empty.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000125 */
Bram Moolenaar7c626922005-02-07 22:01:03 +0000126 if (((p = mch_getenv((char_u *)"SHELL")) != NULL && *p != NUL)
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100127#if defined(MSWIN)
Bram Moolenaar7c626922005-02-07 22:01:03 +0000128 || ((p = mch_getenv((char_u *)"COMSPEC")) != NULL && *p != NUL)
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100129 || ((p = (char_u *)default_shell()) != NULL && *p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130#endif
Bram Moolenaar7c626922005-02-07 22:01:03 +0000131 )
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100132 set_string_default_esc("sh", p, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133
134#ifdef FEAT_WILDIGN
135 /*
136 * Set the default for 'backupskip' to include environment variables for
137 * temp files.
138 */
139 {
140# ifdef UNIX
141 static char *(names[4]) = {"", "TMPDIR", "TEMP", "TMP"};
142# else
143 static char *(names[3]) = {"TMPDIR", "TEMP", "TMP"};
144# endif
Bram Moolenaar05159a02005-02-26 23:04:13 +0000145 int len;
146 garray_T ga;
147 int mustfree;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148
149 ga_init2(&ga, 1, 100);
150 for (n = 0; n < (long)(sizeof(names) / sizeof(char *)); ++n)
151 {
Bram Moolenaar05159a02005-02-26 23:04:13 +0000152 mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153# ifdef UNIX
154 if (*names[n] == NUL)
Bram Moolenaarb8e22a02018-04-12 21:37:34 +0200155# ifdef MACOS_X
156 p = (char_u *)"/private/tmp";
157# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000158 p = (char_u *)"/tmp";
Bram Moolenaarb8e22a02018-04-12 21:37:34 +0200159# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160 else
161# endif
Bram Moolenaar05159a02005-02-26 23:04:13 +0000162 p = vim_getenv((char_u *)names[n], &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000163 if (p != NULL && *p != NUL)
164 {
165 /* First time count the NUL, otherwise count the ','. */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000166 len = (int)STRLEN(p) + 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000167 if (ga_grow(&ga, len) == OK)
168 {
169 if (ga.ga_len > 0)
170 STRCAT(ga.ga_data, ",");
171 STRCAT(ga.ga_data, p);
172 add_pathsep(ga.ga_data);
173 STRCAT(ga.ga_data, "*");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000174 ga.ga_len += len;
175 }
176 }
Bram Moolenaar05159a02005-02-26 23:04:13 +0000177 if (mustfree)
178 vim_free(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000179 }
180 if (ga.ga_data != NULL)
181 {
182 set_string_default("bsk", ga.ga_data);
183 vim_free(ga.ga_data);
184 }
185 }
186#endif
187
188 /*
189 * 'maxmemtot' and 'maxmem' may have to be adjusted for available memory
190 */
191 opt_idx = findoption((char_u *)"maxmemtot");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000192 if (opt_idx >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000194#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
195 if (options[opt_idx].def_val[VI_DEFAULT] == (char_u *)0L)
196#endif
197 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198#ifdef HAVE_AVAIL_MEM
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000199 /* Use amount of memory available at this moment. */
Bram Moolenaar11b73d62012-06-29 15:51:30 +0200200 n = (mch_avail_mem(FALSE) >> 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201#else
202# ifdef HAVE_TOTAL_MEM
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000203 /* Use amount of memory available to Vim. */
Bram Moolenaar914572a2007-05-01 11:37:47 +0000204 n = (mch_total_mem(FALSE) >> 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205# else
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000206 n = (0x7fffffff >> 11);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207# endif
208#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000210 opt_idx = findoption((char_u *)"maxmem");
211 if (opt_idx >= 0)
212 {
213#if !defined(HAVE_AVAIL_MEM) && !defined(HAVE_TOTAL_MEM)
Bram Moolenaar35be4532015-12-11 22:38:36 +0100214 if ((long)(long_i)options[opt_idx].def_val[VI_DEFAULT] > (long)n
215 || (long)(long_i)options[opt_idx].def_val[VI_DEFAULT] == 0L)
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000216#endif
217 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)n;
218 }
219 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000220 }
221
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222#ifdef FEAT_SEARCHPATH
223 {
224 char_u *cdpath;
225 char_u *buf;
226 int i;
227 int j;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000228 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229
230 /* Initialize the 'cdpath' option's default value. */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000231 cdpath = vim_getenv((char_u *)"CDPATH", &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232 if (cdpath != NULL)
233 {
Bram Moolenaar964b3742019-05-24 18:54:09 +0200234 buf = alloc((STRLEN(cdpath) << 1) + 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235 if (buf != NULL)
236 {
237 buf[0] = ','; /* start with ",", current dir first */
238 j = 1;
239 for (i = 0; cdpath[i] != NUL; ++i)
240 {
241 if (vim_ispathlistsep(cdpath[i]))
242 buf[j++] = ',';
243 else
244 {
245 if (cdpath[i] == ' ' || cdpath[i] == ',')
246 buf[j++] = '\\';
247 buf[j++] = cdpath[i];
248 }
249 }
250 buf[j] = NUL;
251 opt_idx = findoption((char_u *)"cdpath");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000252 if (opt_idx >= 0)
253 {
254 options[opt_idx].def_val[VI_DEFAULT] = buf;
255 options[opt_idx].flags |= P_DEF_ALLOCED;
256 }
Bram Moolenaara9d52e32010-07-31 16:44:19 +0200257 else
258 vim_free(buf); /* cannot happen */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259 }
Bram Moolenaar05159a02005-02-26 23:04:13 +0000260 if (mustfree)
261 vim_free(cdpath);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262 }
263 }
264#endif
265
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100266#if defined(FEAT_POSTSCRIPT) && (defined(MSWIN) || defined(VMS) || defined(EBCDIC) || defined(MAC) || defined(hpux))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000267 /* Set print encoding on platforms that don't default to latin1 */
268 set_string_default("penc",
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100269# if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000270 (char_u *)"cp1252"
271# else
272# ifdef VMS
273 (char_u *)"dec-mcs"
274# else
275# ifdef EBCDIC
276 (char_u *)"ebcdic-uk"
277# else
278# ifdef MAC
279 (char_u *)"mac-roman"
280# else /* HPUX */
281 (char_u *)"hp-roman8"
282# endif
283# endif
284# endif
285# endif
286 );
287#endif
288
289#ifdef FEAT_POSTSCRIPT
290 /* 'printexpr' must be allocated to be able to evaluate it. */
291 set_string_default("pexpr",
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100292# if defined(MSWIN)
Bram Moolenaared203462004-06-16 11:19:22 +0000293 (char_u *)"system('copy' . ' ' . v:fname_in . (&printdevice == '' ? ' LPT1:' : (' \"' . &printdevice . '\"'))) . delete(v:fname_in)"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294# else
295# ifdef VMS
296 (char_u *)"system('print/delete' . (&printdevice == '' ? '' : ' /queue=' . &printdevice) . ' ' . v:fname_in)"
297
298# else
299 (char_u *)"system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice) . ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error"
300# endif
301# endif
302 );
303#endif
304
305 /*
306 * Set all the options (except the terminal options) to their default
307 * value. Also set the global value for local options.
308 */
309 set_options_default(0);
310
Bram Moolenaar07268702018-03-01 21:57:32 +0100311#ifdef CLEAN_RUNTIMEPATH
312 if (clean_arg)
313 {
314 opt_idx = findoption((char_u *)"runtimepath");
315 if (opt_idx >= 0)
316 {
317 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
318 p_rtp = (char_u *)CLEAN_RUNTIMEPATH;
319 }
320 opt_idx = findoption((char_u *)"packpath");
321 if (opt_idx >= 0)
322 {
323 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)CLEAN_RUNTIMEPATH;
324 p_pp = (char_u *)CLEAN_RUNTIMEPATH;
325 }
326 }
327#endif
328
Bram Moolenaar071d4272004-06-13 20:20:40 +0000329#ifdef FEAT_GUI
330 if (found_reverse_arg)
331 set_option_value((char_u *)"bg", 0L, (char_u *)"dark", 0);
332#endif
333
334 curbuf->b_p_initialized = TRUE;
335 curbuf->b_p_ar = -1; /* no local 'autoread' value */
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +0100336 curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337 check_buf_options(curbuf);
338 check_win_options(curwin);
339 check_options();
340
341 /* Must be before option_expand(), because that one needs vim_isIDc() */
342 didset_options();
343
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +0000344#ifdef FEAT_SPELL
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200345 /* Use the current chartab for the generic chartab. This is not in
346 * didset_options() because it only depends on 'encoding'. */
Bram Moolenaar6bb68362005-03-22 23:03:44 +0000347 init_spell_chartab();
348#endif
349
Bram Moolenaar071d4272004-06-13 20:20:40 +0000350 /*
351 * Expand environment variables and things like "~" for the defaults.
352 * If option_expand() returns non-NULL the variable is expanded. This can
353 * only happen for non-indirect options.
354 * Also set the default to the expanded value, so ":set" does not list
355 * them.
356 * Don't set the P_ALLOCED flag, because we don't want to free the
357 * default.
358 */
359 for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
360 {
361 if ((options[opt_idx].flags & P_GETTEXT)
362 && options[opt_idx].var != NULL)
363 p = (char_u *)_(*(char **)options[opt_idx].var);
364 else
365 p = option_expand(opt_idx, NULL);
366 if (p != NULL && (p = vim_strsave(p)) != NULL)
367 {
368 *(char_u **)options[opt_idx].var = p;
369 /* VIMEXP
370 * Defaults for all expanded options are currently the same for Vi
371 * and Vim. When this changes, add some code here! Also need to
372 * split P_DEF_ALLOCED in two.
373 */
374 if (options[opt_idx].flags & P_DEF_ALLOCED)
375 vim_free(options[opt_idx].def_val[VI_DEFAULT]);
376 options[opt_idx].def_val[VI_DEFAULT] = p;
377 options[opt_idx].flags |= P_DEF_ALLOCED;
378 }
379 }
380
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 save_file_ff(curbuf); /* Buffer is unchanged */
382
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383#if defined(FEAT_ARABIC)
384 /* Detect use of mlterm.
385 * Mlterm is a terminal emulator akin to xterm that has some special
386 * abilities (bidi namely).
387 * NOTE: mlterm's author is being asked to 'set' a variable
388 * instead of an environment variable due to inheritance.
389 */
390 if (mch_getenv((char_u *)"MLTERM") != NULL)
391 set_option_value((char_u *)"tbidi", 1L, NULL, 0);
392#endif
393
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200394 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395
Bram Moolenaar4f974752019-02-17 17:44:42 +0100396# if defined(MSWIN) && defined(FEAT_GETTEXT)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000397 /*
398 * If $LANG isn't set, try to get a good value for it. This makes the
399 * right language be used automatically. Don't do this for English.
400 */
401 if (mch_getenv((char_u *)"LANG") == NULL)
402 {
403 char buf[20];
404
405 /* Could use LOCALE_SISO639LANGNAME, but it's not in Win95.
406 * LOCALE_SABBREVLANGNAME gives us three letters, like "enu", we use
407 * only the first two. */
408 n = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME,
409 (LPTSTR)buf, 20);
410 if (n >= 2 && STRNICMP(buf, "en", 2) != 0)
411 {
412 /* There are a few exceptions (probably more) */
413 if (STRNICMP(buf, "cht", 3) == 0 || STRNICMP(buf, "zht", 3) == 0)
414 STRCPY(buf, "zh_TW");
415 else if (STRNICMP(buf, "chs", 3) == 0
416 || STRNICMP(buf, "zhc", 3) == 0)
417 STRCPY(buf, "zh_CN");
418 else if (STRNICMP(buf, "jp", 2) == 0)
419 STRCPY(buf, "ja");
420 else
421 buf[2] = NUL; /* truncate to two-letter code */
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100422 vim_setenv((char_u *)"LANG", (char_u *)buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000423 }
424 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000425# else
Bram Moolenaar9d47f172006-03-15 23:03:01 +0000426# ifdef MACOS_CONVERT
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +0000427 /* Moved to os_mac_conv.c to avoid dependency problems. */
428 mac_lang_init();
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000429# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430# endif
431
432 /* enc_locale() will try to find the encoding of the current locale. */
433 p = enc_locale();
434 if (p != NULL)
435 {
436 char_u *save_enc;
437
438 /* Try setting 'encoding' and check if the value is valid.
439 * If not, go back to the default "latin1". */
440 save_enc = p_enc;
441 p_enc = p;
Bram Moolenaar733f0a22007-03-02 18:56:27 +0000442 if (STRCMP(p_enc, "gb18030") == 0)
443 {
444 /* We don't support "gb18030", but "cp936" is a good substitute
445 * for practical purposes, thus use that. It's not an alias to
446 * still support conversion between gb18030 and utf-8. */
447 p_enc = vim_strsave((char_u *)"cp936");
448 vim_free(p);
449 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 if (mb_init() == NULL)
451 {
452 opt_idx = findoption((char_u *)"encoding");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000453 if (opt_idx >= 0)
454 {
455 options[opt_idx].def_val[VI_DEFAULT] = p_enc;
456 options[opt_idx].flags |= P_DEF_ALLOCED;
457 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458
Bram Moolenaard0573012017-10-28 21:11:06 +0200459#if defined(MSWIN) || defined(MACOS_X) || defined(VMS)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100460 if (STRCMP(p_enc, "latin1") == 0 || enc_utf8)
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000461 {
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000462 /* Adjust the default for 'isprint' and 'iskeyword' to match
463 * latin1. Also set the defaults for when 'nocompatible' is
464 * set. */
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000465 set_string_option_direct((char_u *)"isp", -1,
Bram Moolenaar4ea8fe12006-03-09 22:32:39 +0000466 ISP_LATIN1, OPT_FREE, SID_NONE);
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000467 set_string_option_direct((char_u *)"isk", -1,
468 ISK_LATIN1, OPT_FREE, SID_NONE);
469 opt_idx = findoption((char_u *)"isp");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000470 if (opt_idx >= 0)
471 options[opt_idx].def_val[VIM_DEFAULT] = ISP_LATIN1;
Bram Moolenaar362e1a32006-03-06 23:29:24 +0000472 opt_idx = findoption((char_u *)"isk");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000473 if (opt_idx >= 0)
474 options[opt_idx].def_val[VIM_DEFAULT] = ISK_LATIN1;
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000475 (void)init_chartab();
476 }
477#endif
478
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200479#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 /* Win32 console: When GetACP() returns a different value from
481 * GetConsoleCP() set 'termencoding'. */
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200482 if (
483# ifdef VIMDLL
484 (!gui.in_use && !gui.starting) &&
485# endif
486 GetACP() != GetConsoleCP())
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487 {
488 char buf[50];
489
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +0100490 /* Win32 console: In ConPTY, GetConsoleCP() returns zero.
491 * Use an alternative value. */
492 if (GetConsoleCP() == 0)
493 sprintf(buf, "cp%ld", (long)GetACP());
494 else
495 sprintf(buf, "cp%ld", (long)GetConsoleCP());
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496 p_tenc = vim_strsave((char_u *)buf);
497 if (p_tenc != NULL)
498 {
499 opt_idx = findoption((char_u *)"termencoding");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000500 if (opt_idx >= 0)
501 {
502 options[opt_idx].def_val[VI_DEFAULT] = p_tenc;
503 options[opt_idx].flags |= P_DEF_ALLOCED;
504 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505 convert_setup(&input_conv, p_tenc, p_enc);
506 convert_setup(&output_conv, p_enc, p_tenc);
507 }
508 else
509 p_tenc = empty_option;
510 }
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100511#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +0100512#if defined(MSWIN)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000513 /* $HOME may have characters in active code page. */
514 init_homedir();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100515#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000516 }
517 else
518 {
519 vim_free(p_enc);
520 p_enc = save_enc;
521 }
522 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523
524#ifdef FEAT_MULTI_LANG
525 /* Set the default for 'helplang'. */
526 set_helplang_default(get_mess_lang());
527#endif
528}
529
530/*
531 * Set an option to its default value.
532 * This does not take care of side effects!
533 */
534 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100535set_option_default(
536 int opt_idx,
537 int opt_flags, /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
538 int compatible) /* use Vi default value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000539{
540 char_u *varp; /* pointer to variable for current option */
541 int dvi; /* index in def_val[] */
542 long_u flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000543 long_u *flagsp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000544 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
545
546 varp = get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
547 flags = options[opt_idx].flags;
Bram Moolenaar3638c682005-06-08 22:05:14 +0000548 if (varp != NULL) /* skip hidden option, nothing to do for it */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549 {
550 dvi = ((flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
551 if (flags & P_STRING)
552 {
Bram Moolenaarb833c1e2018-05-05 16:36:06 +0200553 /* Use set_string_option_direct() for local options to handle
554 * freeing and allocating the value. */
555 if (options[opt_idx].indir != PV_NONE)
556 set_string_option_direct(NULL, opt_idx,
557 options[opt_idx].def_val[dvi], opt_flags, 0);
558 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000559 {
Bram Moolenaarb833c1e2018-05-05 16:36:06 +0200560 if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED))
561 free_string_option(*(char_u **)(varp));
562 *(char_u **)varp = options[opt_idx].def_val[dvi];
563 options[opt_idx].flags &= ~P_ALLOCED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000564 }
565 }
566 else if (flags & P_NUM)
567 {
Bram Moolenaar5fc1a8b2006-10-17 16:34:24 +0000568 if (options[opt_idx].indir == PV_SCROLL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000569 win_comp_scroll(curwin);
570 else
571 {
Bram Moolenaar375e3392019-01-31 18:26:10 +0100572 long def_val = (long)(long_i)options[opt_idx].def_val[dvi];
573
574 if ((long *)varp == &curwin->w_p_so
575 || (long *)varp == &curwin->w_p_siso)
576 // 'scrolloff' and 'sidescrolloff' local values have a
577 // different default value than the global default.
578 *(long *)varp = -1;
579 else
580 *(long *)varp = def_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000581 /* May also set global value for local option. */
582 if (both)
583 *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
Bram Moolenaar375e3392019-01-31 18:26:10 +0100584 def_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000585 }
586 }
587 else /* P_BOOL */
588 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000589 /* the cast to long is required for Manx C, long_i is needed for
590 * MSVC */
591 *(int *)varp = (int)(long)(long_i)options[opt_idx].def_val[dvi];
Bram Moolenaar8243a792007-05-01 17:05:03 +0000592#ifdef UNIX
593 /* 'modeline' defaults to off for root */
594 if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID)
595 *(int *)varp = FALSE;
596#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597 /* May also set global value for local option. */
598 if (both)
599 *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
600 *(int *)varp;
601 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000602
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000603 /* The default value is not insecure. */
604 flagsp = insecure_flag(opt_idx, opt_flags);
605 *flagsp = *flagsp & ~P_INSECURE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606 }
607
608#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +0200609 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610#endif
611}
612
613/*
614 * Set all options (except terminal options) to their default value.
Bram Moolenaarb341dda2015-08-25 12:56:31 +0200615 * When "opt_flags" is non-zero skip 'encoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000616 */
617 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100618set_options_default(
619 int opt_flags) /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000620{
621 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622 win_T *wp;
Bram Moolenaarf740b292006-02-16 22:11:02 +0000623 tabpage_T *tp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624
625 for (i = 0; !istermoption(&options[i]); i++)
Bram Moolenaarb341dda2015-08-25 12:56:31 +0200626 if (!(options[i].flags & P_NODEFAULT)
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200627 && (opt_flags == 0
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100628 || (options[i].var != (char_u *)&p_enc
Bram Moolenaar5ea87a02015-08-26 23:24:09 +0200629# if defined(FEAT_CRYPT)
Bram Moolenaare68c25c2015-08-25 15:39:55 +0200630 && options[i].var != (char_u *)&p_cm
Bram Moolenaar80606872015-08-25 21:27:35 +0200631 && options[i].var != (char_u *)&p_key
Bram Moolenaar5ea87a02015-08-26 23:24:09 +0200632# endif
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100633 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 set_option_default(i, opt_flags, p_cp);
635
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 /* The 'scroll' option must be computed for all windows. */
Bram Moolenaarf740b292006-02-16 22:11:02 +0000637 FOR_ALL_TAB_WINDOWS(tp, wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000638 win_comp_scroll(wp);
Bram Moolenaar5a4eceb2014-09-09 17:33:07 +0200639#ifdef FEAT_CINDENT
640 parse_cino(curbuf);
641#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642}
643
644/*
645 * Set the Vi-default value of a string option.
646 * Used for 'sh', 'backupskip' and 'term'.
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100647 * When "escape" is TRUE escape spaces with a backslash.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000648 */
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100649 static void
650set_string_default_esc(char *name, char_u *val, int escape)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651{
652 char_u *p;
653 int opt_idx;
654
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100655 if (escape && vim_strchr(val, ' ') != NULL)
656 p = vim_strsave_escaped(val, (char_u *)" ");
657 else
658 p = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 if (p != NULL) /* we don't want a NULL */
660 {
661 opt_idx = findoption((char_u *)name);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000662 if (opt_idx >= 0)
663 {
664 if (options[opt_idx].flags & P_DEF_ALLOCED)
665 vim_free(options[opt_idx].def_val[VI_DEFAULT]);
666 options[opt_idx].def_val[VI_DEFAULT] = p;
667 options[opt_idx].flags |= P_DEF_ALLOCED;
668 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000669 }
670}
671
Bram Moolenaar4bfa8af2018-02-03 15:14:46 +0100672 void
673set_string_default(char *name, char_u *val)
674{
675 set_string_default_esc(name, val, FALSE);
676}
677
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678/*
679 * Set the Vi-default value of a number option.
680 * Used for 'lines' and 'columns'.
681 */
682 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100683set_number_default(char *name, long val)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684{
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000685 int opt_idx;
686
687 opt_idx = findoption((char_u *)name);
688 if (opt_idx >= 0)
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000689 options[opt_idx].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690}
691
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200692/*
693 * Set all window-local and buffer-local options to the Vim default.
694 * local-global options will use the global value.
Bram Moolenaar46451042019-08-24 15:50:46 +0200695 * When "do_buffer" is FALSE don't set buffer-local options.
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200696 */
697 void
Bram Moolenaar46451042019-08-24 15:50:46 +0200698set_local_options_default(win_T *wp, int do_buffer)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200699{
700 win_T *save_curwin = curwin;
701 int i;
702
703 curwin = wp;
704 curbuf = curwin->w_buffer;
705 block_autocmds();
706
707 for (i = 0; !istermoption(&options[i]); i++)
708 {
709 struct vimoption *p = &(options[i]);
710 char_u *varp = get_varp_scope(p, OPT_LOCAL);
711
712 if (p->indir != PV_NONE
Bram Moolenaar46451042019-08-24 15:50:46 +0200713 && (do_buffer || (p->indir & PV_BUF) == 0)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +0200714 && !(options[i].flags & P_NODEFAULT)
715 && !optval_default(p, varp, FALSE))
716 set_option_default(i, OPT_LOCAL, FALSE);
717 }
718
719 unblock_autocmds();
720 curwin = save_curwin;
721 curbuf = curwin->w_buffer;
722}
723
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000724#if defined(EXITFREE) || defined(PROTO)
725/*
726 * Free all options.
727 */
728 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100729free_all_options(void)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000730{
731 int i;
732
733 for (i = 0; !istermoption(&options[i]); i++)
734 {
735 if (options[i].indir == PV_NONE)
736 {
737 /* global option: free value and default value. */
Bram Moolenaar67391142017-02-19 21:07:04 +0100738 if ((options[i].flags & P_ALLOCED) && options[i].var != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +0000739 free_string_option(*(char_u **)options[i].var);
740 if (options[i].flags & P_DEF_ALLOCED)
741 free_string_option(options[i].def_val[VI_DEFAULT]);
742 }
743 else if (options[i].var != VAR_WIN
744 && (options[i].flags & P_STRING))
745 /* buffer-local option: free global value */
746 free_string_option(*(char_u **)options[i].var);
747 }
748}
749#endif
750
751
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752/*
753 * Initialize the options, part two: After getting Rows and Columns and
754 * setting 'term'.
755 */
756 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100757set_init_2(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758{
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000759 int idx;
760
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761 /*
Bram Moolenaaraf2d20c2017-10-29 15:26:57 +0100762 * 'scroll' defaults to half the window height. The stored default is zero,
763 * which results in the actual value computed from the window height.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000765 idx = findoption((char_u *)"scroll");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000766 if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000767 set_option_default(idx, OPT_LOCAL, p_cp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768 comp_col();
769
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000770 /*
771 * 'window' is only for backwards compatibility with Vi.
772 * Default is Rows - 1.
773 */
Bram Moolenaard68071d2006-05-02 22:08:30 +0000774 if (!option_was_set((char_u *)"window"))
Bram Moolenaar4399ef42005-02-12 14:29:27 +0000775 p_window = Rows - 1;
776 set_number_default("window", Rows - 1);
777
Bram Moolenaarf740b292006-02-16 22:11:02 +0000778 /* For DOS console the default is always black. */
Bram Moolenaar4f974752019-02-17 17:44:42 +0100779#if !((defined(MSWIN)) && !defined(FEAT_GUI))
Bram Moolenaarf740b292006-02-16 22:11:02 +0000780 /*
781 * If 'background' wasn't set by the user, try guessing the value,
782 * depending on the terminal name. Only need to check for terminals
783 * with a dark background, that can handle color.
784 */
785 idx = findoption((char_u *)"bg");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000786 if (idx >= 0 && !(options[idx].flags & P_WAS_SET)
787 && *term_bg_default() == 'd')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000789 set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE, 0);
Bram Moolenaarf740b292006-02-16 22:11:02 +0000790 /* don't mark it as set, when starting the GUI it may be
791 * changed again */
792 options[idx].flags &= ~P_WAS_SET;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 }
794#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +0000795
796#ifdef CURSOR_SHAPE
797 parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */
798#endif
799#ifdef FEAT_MOUSESHAPE
800 parse_shape_opt(SHAPE_MOUSE); /* set mouse shapes from 'mouseshape' */
801#endif
802#ifdef FEAT_PRINTER
803 (void)parse_printoptions(); /* parse 'printoptions' default value */
804#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805}
806
807/*
Bram Moolenaarf740b292006-02-16 22:11:02 +0000808 * Return "dark" or "light" depending on the kind of terminal.
809 * This is just guessing! Recognized are:
810 * "linux" Linux console
811 * "screen.linux" Linux console with screen
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200812 * "cygwin.*" Cygwin shell
813 * "putty.*" Putty program
Bram Moolenaarf740b292006-02-16 22:11:02 +0000814 * We also check the COLORFGBG environment variable, which is set by
815 * rxvt and derivatives. This variable contains either two or three
816 * values separated by semicolons; we want the last value in either
817 * case. If this value is 0-6 or 8, our background is dark.
818 */
819 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +0100820term_bg_default(void)
Bram Moolenaarf740b292006-02-16 22:11:02 +0000821{
Bram Moolenaar4f974752019-02-17 17:44:42 +0100822#if defined(MSWIN)
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200823 /* DOS console is nearly always black */
Bram Moolenaarf740b292006-02-16 22:11:02 +0000824 return (char_u *)"dark";
825#else
Bram Moolenaarfaa959a2006-02-20 21:37:40 +0000826 char_u *p;
827
Bram Moolenaarf740b292006-02-16 22:11:02 +0000828 if (STRCMP(T_NAME, "linux") == 0
829 || STRCMP(T_NAME, "screen.linux") == 0
Bram Moolenaarc6da01a2017-09-07 22:37:36 +0200830 || STRNCMP(T_NAME, "cygwin", 6) == 0
831 || STRNCMP(T_NAME, "putty", 5) == 0
Bram Moolenaarf740b292006-02-16 22:11:02 +0000832 || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
833 && (p = vim_strrchr(p, ';')) != NULL
834 && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
835 && p[2] == NUL))
836 return (char_u *)"dark";
837 return (char_u *)"light";
838#endif
839}
840
841/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 * Initialize the options, part three: After reading the .vimrc
843 */
844 void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100845set_init_3(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846{
Bram Moolenaar4f974752019-02-17 17:44:42 +0100847#if defined(UNIX) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000848/*
849 * Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
850 * This is done after other initializations, where 'shell' might have been
851 * set, but only if they have not been set before.
852 */
853 char_u *p;
854 int idx_srr;
855 int do_srr;
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100856# ifdef FEAT_QUICKFIX
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 int idx_sp;
858 int do_sp;
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100859# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860
861 idx_srr = findoption((char_u *)"srr");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000862 if (idx_srr < 0)
863 do_srr = FALSE;
864 else
865 do_srr = !(options[idx_srr].flags & P_WAS_SET);
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100866# ifdef FEAT_QUICKFIX
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 idx_sp = findoption((char_u *)"sp");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000868 if (idx_sp < 0)
869 do_sp = FALSE;
870 else
871 do_sp = !(options[idx_sp].flags & P_WAS_SET);
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100872# endif
Bram Moolenaar75a8d742014-05-07 15:10:21 +0200873 p = get_isolated_shell_name();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 if (p != NULL)
875 {
876 /*
877 * Default for p_sp is "| tee", for p_srr is ">".
878 * For known shells it is changed here to include stderr.
879 */
880 if ( fnamecmp(p, "csh") == 0
881 || fnamecmp(p, "tcsh") == 0
Bram Moolenaar4f974752019-02-17 17:44:42 +0100882# if defined(MSWIN) // also check with .exe extension
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 || fnamecmp(p, "csh.exe") == 0
884 || fnamecmp(p, "tcsh.exe") == 0
885# endif
886 )
887 {
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100888# if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 if (do_sp)
890 {
Bram Moolenaar4f974752019-02-17 17:44:42 +0100891# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892 p_sp = (char_u *)">&";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100893# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 p_sp = (char_u *)"|& tee";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100895# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896 options[idx_sp].def_val[VI_DEFAULT] = p_sp;
897 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100898# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899 if (do_srr)
900 {
901 p_srr = (char_u *)">&";
902 options[idx_srr].def_val[VI_DEFAULT] = p_srr;
903 }
904 }
905 else
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100906 /* Always use bourne shell style redirection if we reach this */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000907 if ( fnamecmp(p, "sh") == 0
908 || fnamecmp(p, "ksh") == 0
Bram Moolenaarf1fda2d2011-04-28 12:57:36 +0200909 || fnamecmp(p, "mksh") == 0
910 || fnamecmp(p, "pdksh") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911 || fnamecmp(p, "zsh") == 0
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000912 || fnamecmp(p, "zsh-beta") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 || fnamecmp(p, "bash") == 0
Bram Moolenaar75a8d742014-05-07 15:10:21 +0200914 || fnamecmp(p, "fish") == 0
Bram Moolenaar4f974752019-02-17 17:44:42 +0100915# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000916 || fnamecmp(p, "cmd") == 0
917 || fnamecmp(p, "sh.exe") == 0
918 || fnamecmp(p, "ksh.exe") == 0
Bram Moolenaarf1fda2d2011-04-28 12:57:36 +0200919 || fnamecmp(p, "mksh.exe") == 0
920 || fnamecmp(p, "pdksh.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 || fnamecmp(p, "zsh.exe") == 0
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000922 || fnamecmp(p, "zsh-beta.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000923 || fnamecmp(p, "bash.exe") == 0
924 || fnamecmp(p, "cmd.exe") == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925# endif
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100926 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 {
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100928# if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 if (do_sp)
930 {
Bram Moolenaar4f974752019-02-17 17:44:42 +0100931# ifdef MSWIN
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932 p_sp = (char_u *)">%s 2>&1";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100933# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000934 p_sp = (char_u *)"2>&1| tee";
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100935# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936 options[idx_sp].def_val[VI_DEFAULT] = p_sp;
937 }
Bram Moolenaare7fedb62015-12-31 19:07:19 +0100938# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 if (do_srr)
940 {
941 p_srr = (char_u *)">%s 2>&1";
942 options[idx_srr].def_val[VI_DEFAULT] = p_srr;
943 }
944 }
945 vim_free(p);
946 }
947#endif
948
Bram Moolenaar4f974752019-02-17 17:44:42 +0100949#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000950 /*
Bram Moolenaara64ba222012-02-12 23:23:31 +0100951 * Set 'shellcmdflag', 'shellxquote', and 'shellquote' depending on the
952 * 'shell' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000953 * This is done after other initializations, where 'shell' might have been
954 * set, but only if they have not been set before. Default for p_shcf is
955 * "/c", for p_shq is "". For "sh" like shells it is changed here to
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100956 * "-c" and "\"". And for Win32 we need to set p_sxq instead.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 */
Bram Moolenaarf4b8e572004-06-24 15:53:16 +0000958 if (strstr((char *)gettail(p_sh), "sh") != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 {
960 int idx3;
961
962 idx3 = findoption((char_u *)"shcf");
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_shcf = (char_u *)"-c";
966 options[idx3].def_val[VI_DEFAULT] = p_shcf;
967 }
968
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969 /* Somehow Win32 requires the quotes around the redirection too */
970 idx3 = findoption((char_u *)"sxq");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +0000971 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972 {
973 p_sxq = (char_u *)"\"";
974 options[idx3].def_val[VI_DEFAULT] = p_sxq;
975 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976 }
Bram Moolenaara64ba222012-02-12 23:23:31 +0100977 else if (strstr((char *)gettail(p_sh), "cmd.exe") != NULL)
978 {
979 int idx3;
980
981 /*
982 * cmd.exe on Windows will strip the first and last double quote given
983 * on the command line, e.g. most of the time things like:
984 * cmd /c "my path/to/echo" "my args to echo"
985 * become:
986 * my path/to/echo" "my args to echo
987 * when executed.
988 *
Bram Moolenaar034b1152012-02-19 18:19:30 +0100989 * To avoid this, set shellxquote to surround the command in
990 * parenthesis. This appears to make most commands work, without
991 * breaking commands that worked previously, such as
992 * '"path with spaces/cmd" "a&b"'.
Bram Moolenaara64ba222012-02-12 23:23:31 +0100993 */
Bram Moolenaara64ba222012-02-12 23:23:31 +0100994 idx3 = findoption((char_u *)"sxq");
995 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
996 {
Bram Moolenaar034b1152012-02-19 18:19:30 +0100997 p_sxq = (char_u *)"(";
Bram Moolenaara64ba222012-02-12 23:23:31 +0100998 options[idx3].def_val[VI_DEFAULT] = p_sxq;
999 }
1000
Bram Moolenaara64ba222012-02-12 23:23:31 +01001001 idx3 = findoption((char_u *)"shcf");
1002 if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET))
1003 {
Bram Moolenaar034b1152012-02-19 18:19:30 +01001004 p_shcf = (char_u *)"/c";
Bram Moolenaara64ba222012-02-12 23:23:31 +01001005 options[idx3].def_val[VI_DEFAULT] = p_shcf;
1006 }
1007 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008#endif
1009
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01001010 if (BUFEMPTY())
Bram Moolenaar364fa5c2016-03-20 17:53:25 +01001011 {
1012 int idx_ffs = findoption((char_u *)"ffs");
1013
1014 /* Apply the first entry of 'fileformats' to the initial buffer. */
1015 if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET))
1016 set_fileformat(default_fileformat(), OPT_LOCAL);
1017 }
1018
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019#ifdef FEAT_TITLE
1020 set_title_defaults();
1021#endif
1022}
1023
1024#if defined(FEAT_MULTI_LANG) || defined(PROTO)
1025/*
1026 * When 'helplang' is still at its default value, set it to "lang".
1027 * Only the first two characters of "lang" are used.
1028 */
1029 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001030set_helplang_default(char_u *lang)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031{
1032 int idx;
1033
1034 if (lang == NULL || STRLEN(lang) < 2) /* safety check */
1035 return;
1036 idx = findoption((char_u *)"hlg");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001037 if (idx >= 0 && !(options[idx].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001038 {
1039 if (options[idx].flags & P_ALLOCED)
1040 free_string_option(p_hlg);
1041 p_hlg = vim_strsave(lang);
1042 if (p_hlg == NULL)
1043 p_hlg = empty_option;
1044 else
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001045 {
Bram Moolenaardcd71cb2018-11-04 14:40:47 +01001046 // zh_CN becomes "cn", zh_TW becomes "tw"
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001047 if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5)
1048 {
1049 p_hlg[0] = TOLOWER_ASC(p_hlg[3]);
1050 p_hlg[1] = TOLOWER_ASC(p_hlg[4]);
1051 }
Bram Moolenaardcd71cb2018-11-04 14:40:47 +01001052 // any C like setting, such as C.UTF-8, becomes "en"
1053 else if (STRLEN(p_hlg) >= 1 && *p_hlg == 'C')
1054 {
1055 p_hlg[0] = 'e';
1056 p_hlg[1] = 'n';
1057 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 p_hlg[2] = NUL;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001059 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060 options[idx].flags |= P_ALLOCED;
1061 }
1062}
1063#endif
1064
1065#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01001067gui_bg_default(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001068{
1069 if (gui_get_lightness(gui.back_pixel) < 127)
1070 return (char_u *)"dark";
1071 return (char_u *)"light";
1072}
1073
1074/*
1075 * Option initializations that can only be done after opening the GUI window.
1076 */
1077 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001078init_gui_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079{
1080 /* Set the 'background' option according to the lightness of the
1081 * background color, unless the user has set it already. */
1082 if (!option_was_set((char_u *)"bg") && STRCMP(p_bg, gui_bg_default()) != 0)
1083 {
1084 set_option_value((char_u *)"bg", 0L, gui_bg_default(), 0);
1085 highlight_changed();
1086 }
1087}
1088#endif
1089
1090#ifdef FEAT_TITLE
1091/*
1092 * 'title' and 'icon' only default to true if they have not been set or reset
1093 * in .vimrc and we can read the old value.
1094 * When 'title' and 'icon' have been reset in .vimrc, we won't even check if
1095 * they can be reset. This reduces startup time when using X on a remote
1096 * machine.
1097 */
1098 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01001099set_title_defaults(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100{
1101 int idx1;
1102 long val;
1103
1104 /*
1105 * If GUI is (going to be) used, we can always set the window title and
1106 * icon name. Saves a bit of time, because the X11 display server does
1107 * not need to be contacted.
1108 */
1109 idx1 = findoption((char_u *)"title");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001110 if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111 {
1112#ifdef FEAT_GUI
1113 if (gui.starting || gui.in_use)
1114 val = TRUE;
1115 else
1116#endif
1117 val = mch_can_restore_title();
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001118 options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001119 p_title = val;
1120 }
1121 idx1 = findoption((char_u *)"icon");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00001122 if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001123 {
1124#ifdef FEAT_GUI
1125 if (gui.starting || gui.in_use)
1126 val = TRUE;
1127 else
1128#endif
1129 val = mch_can_restore_icon();
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001130 options[idx1].def_val[VI_DEFAULT] = (char_u *)(long_i)val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 p_icon = val;
1132 }
1133}
1134#endif
1135
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001136#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02001137/*
1138 * Trigger the OptionSet autocommand.
1139 * "opt_idx" is the index of the option being set.
1140 * "opt_flags" can be OPT_LOCAL etc.
1141 * "oldval" the old value
1142 * "oldval_l" the old local value (only non-NULL if global and local value
1143 * are set)
1144 * "oldval_g" the old global value (only non-NULL if global and local value
1145 * are set)
1146 * "newval" the new value
1147 */
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001148 static void
1149trigger_optionsset_string(
1150 int opt_idx,
1151 int opt_flags,
Bram Moolenaard7c96872019-06-15 17:12:48 +02001152 char_u *oldval,
1153 char_u *oldval_l,
1154 char_u *oldval_g,
1155 char_u *newval)
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001156{
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02001157 // Don't do this recursively.
1158 if (oldval != NULL && newval != NULL
1159 && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001160 {
1161 char_u buf_type[7];
1162
1163 sprintf((char *)buf_type, "%s",
1164 (opt_flags & OPT_LOCAL) ? "local" : "global");
1165 set_vim_var_string(VV_OPTION_OLD, oldval, -1);
1166 set_vim_var_string(VV_OPTION_NEW, newval, -1);
1167 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02001168 if (opt_flags & OPT_LOCAL)
1169 {
1170 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
1171 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
1172 }
1173 if (opt_flags & OPT_GLOBAL)
1174 {
1175 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
1176 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
1177 }
1178 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1179 {
1180 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
1181 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
1182 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
1183 }
1184 if (opt_flags & OPT_MODELINE)
1185 {
1186 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
1187 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
1188 }
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001189 apply_autocmds(EVENT_OPTIONSET,
1190 (char_u *)options[opt_idx].fullname, NULL, FALSE, NULL);
1191 reset_v_option_vars();
1192 }
Bram Moolenaar182a17b2017-06-25 20:57:18 +02001193}
1194#endif
1195
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196/*
1197 * Parse 'arg' for option settings.
1198 *
1199 * 'arg' may be IObuff, but only when no errors can be present and option
1200 * does not need to be expanded with option_expand().
1201 * "opt_flags":
1202 * 0 for ":set"
Bram Moolenaara3227e22006-03-08 21:32:40 +00001203 * OPT_GLOBAL for ":setglobal"
1204 * OPT_LOCAL for ":setlocal" and a modeline
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205 * OPT_MODELINE for a modeline
Bram Moolenaara3227e22006-03-08 21:32:40 +00001206 * OPT_WINONLY to only set window-local options
1207 * OPT_NOWIN to skip setting window-local options
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208 *
1209 * returns FAIL if an error is detected, OK otherwise
1210 */
1211 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01001212do_set(
1213 char_u *arg, /* option string (may be written to!) */
1214 int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001215{
1216 int opt_idx;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001217 char *errmsg;
1218 char errbuf[80];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219 char_u *startarg;
1220 int prefix; /* 1: nothing, 0: "no", 2: "inv" in front of name */
1221 int nextchar; /* next non-white char after option name */
1222 int afterchar; /* character just after option name */
1223 int len;
1224 int i;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001225 varnumber_T value;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001226 int key;
1227 long_u flags; /* flags for current option */
1228 char_u *varp = NULL; /* pointer to variable for current option */
1229 int did_show = FALSE; /* already showed one value */
1230 int adding; /* "opt+=arg" */
1231 int prepending; /* "opt^=arg" */
1232 int removing; /* "opt-=arg" */
1233 int cp_val = 0;
1234 char_u key_name[2];
1235
1236 if (*arg == NUL)
1237 {
1238 showoptions(0, opt_flags);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001239 did_show = TRUE;
1240 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241 }
1242
1243 while (*arg != NUL) /* loop to process all options */
1244 {
1245 errmsg = NULL;
1246 startarg = arg; /* remember for error message */
1247
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001248 if (STRNCMP(arg, "all", 3) == 0 && !isalpha(arg[3])
1249 && !(opt_flags & OPT_MODELINE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250 {
1251 /*
1252 * ":set all" show all options.
1253 * ":set all&" set all options to their default value.
1254 */
1255 arg += 3;
1256 if (*arg == '&')
1257 {
1258 ++arg;
1259 /* Only for :set command set global value of local options. */
1260 set_options_default(OPT_FREE | opt_flags);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02001261 didset_options();
1262 didset_options2();
Bram Moolenaarb341dda2015-08-25 12:56:31 +02001263 redraw_all_later(CLEAR);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264 }
1265 else
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001266 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267 showoptions(1, opt_flags);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001268 did_show = TRUE;
1269 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001270 }
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001271 else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272 {
1273 showoptions(2, opt_flags);
1274 show_termcodes();
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001275 did_show = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001276 arg += 7;
1277 }
1278 else
1279 {
1280 prefix = 1;
Bram Moolenaar2a7b9ee2009-06-16 15:50:33 +00001281 if (STRNCMP(arg, "no", 2) == 0 && STRNCMP(arg, "novice", 6) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001282 {
1283 prefix = 0;
1284 arg += 2;
1285 }
1286 else if (STRNCMP(arg, "inv", 3) == 0)
1287 {
1288 prefix = 2;
1289 arg += 3;
1290 }
1291
1292 /* find end of name */
1293 key = 0;
1294 if (*arg == '<')
1295 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001296 opt_idx = -1;
1297 /* look out for <t_>;> */
1298 if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4])
1299 len = 5;
1300 else
1301 {
1302 len = 1;
1303 while (arg[len] != NUL && arg[len] != '>')
1304 ++len;
1305 }
1306 if (arg[len] != '>')
1307 {
1308 errmsg = e_invarg;
1309 goto skip;
1310 }
1311 arg[len] = NUL; /* put NUL after name */
1312 if (arg[1] == 't' && arg[2] == '_') /* could be term code */
1313 opt_idx = findoption(arg + 1);
1314 arg[len++] = '>'; /* restore '>' */
1315 if (opt_idx == -1)
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02001316 key = find_key_option(arg + 1, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317 }
1318 else
1319 {
1320 len = 0;
1321 /*
1322 * The two characters after "t_" may not be alphanumeric.
1323 */
1324 if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
1325 len = 4;
1326 else
1327 while (ASCII_ISALNUM(arg[len]) || arg[len] == '_')
1328 ++len;
1329 nextchar = arg[len];
1330 arg[len] = NUL; /* put NUL after name */
1331 opt_idx = findoption(arg);
1332 arg[len] = nextchar; /* restore nextchar */
1333 if (opt_idx == -1)
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02001334 key = find_key_option(arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335 }
1336
1337 /* remember character after option name */
1338 afterchar = arg[len];
1339
1340 /* skip white space, allow ":set ai ?" */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001341 while (VIM_ISWHITE(arg[len]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001342 ++len;
1343
1344 adding = FALSE;
1345 prepending = FALSE;
1346 removing = FALSE;
1347 if (arg[len] != NUL && arg[len + 1] == '=')
1348 {
1349 if (arg[len] == '+')
1350 {
1351 adding = TRUE; /* "+=" */
1352 ++len;
1353 }
1354 else if (arg[len] == '^')
1355 {
1356 prepending = TRUE; /* "^=" */
1357 ++len;
1358 }
1359 else if (arg[len] == '-')
1360 {
1361 removing = TRUE; /* "-=" */
1362 ++len;
1363 }
1364 }
1365 nextchar = arg[len];
1366
1367 if (opt_idx == -1 && key == 0) /* found a mismatch: skip */
1368 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001369 errmsg = N_("E518: Unknown option");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001370 goto skip;
1371 }
1372
1373 if (opt_idx >= 0)
1374 {
1375 if (options[opt_idx].var == NULL) /* hidden option: skip */
1376 {
1377 /* Only give an error message when requesting the value of
1378 * a hidden option, ignore setting it. */
1379 if (vim_strchr((char_u *)"=:!&<", nextchar) == NULL
1380 && (!(options[opt_idx].flags & P_BOOL)
1381 || nextchar == '?'))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001382 errmsg = N_("E519: Option not supported");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001383 goto skip;
1384 }
1385
1386 flags = options[opt_idx].flags;
1387 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
1388 }
1389 else
1390 {
1391 flags = P_STRING;
1392 if (key < 0)
1393 {
1394 key_name[0] = KEY2TERMCAP0(key);
1395 key_name[1] = KEY2TERMCAP1(key);
1396 }
1397 else
1398 {
1399 key_name[0] = KS_KEY;
1400 key_name[1] = (key & 0xff);
1401 }
1402 }
1403
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001404 /* Skip all options that are not window-local (used when showing
1405 * an already loaded buffer in a window). */
1406 if ((opt_flags & OPT_WINONLY)
1407 && (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
1408 goto skip;
1409
Bram Moolenaara3227e22006-03-08 21:32:40 +00001410 /* Skip all options that are window-local (used for :vimgrep). */
1411 if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
1412 && options[opt_idx].var == VAR_WIN)
1413 goto skip;
1414
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001415 /* Disallow changing some options from modelines. */
1416 if (opt_flags & OPT_MODELINE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001417 {
Bram Moolenaar865242e2010-07-14 21:12:05 +02001418 if (flags & (P_SECURE | P_NO_ML))
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001419 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001420 errmsg = _("E520: Not allowed in a modeline");
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001421 goto skip;
1422 }
Bram Moolenaar110289e2019-05-23 15:38:06 +02001423 if ((flags & P_MLE) && !p_mle)
1424 {
1425 errmsg = _("E992: Not allowed in a modeline when 'modelineexpr' is off");
1426 goto skip;
1427 }
Bram Moolenaarf69d9a32009-02-11 21:48:40 +00001428#ifdef FEAT_DIFF
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001429 /* In diff mode some options are overruled. This avoids that
1430 * 'foldmethod' becomes "marker" instead of "diff" and that
1431 * "wrap" gets set. */
1432 if (curwin->w_p_diff
Bram Moolenaara9d52e32010-07-31 16:44:19 +02001433 && opt_idx >= 0 /* shut up coverity warning */
Bram Moolenaara6c07602017-03-05 21:18:27 +01001434 && (
1435#ifdef FEAT_FOLDING
1436 options[opt_idx].indir == PV_FDM ||
1437#endif
1438 options[opt_idx].indir == PV_WRAP))
Bram Moolenaar1bf0ddc2009-02-11 15:47:05 +00001439 goto skip;
Bram Moolenaarf69d9a32009-02-11 21:48:40 +00001440#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001441 }
1442
1443#ifdef HAVE_SANDBOX
1444 /* Disallow changing some options in the sandbox */
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001445 if (sandbox != 0 && (flags & P_SECURE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001446 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001447 errmsg = _(e_sandbox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001448 goto skip;
1449 }
1450#endif
1451
1452 if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL)
1453 {
1454 arg += len;
1455 cp_val = p_cp;
1456 if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i')
1457 {
1458 if (arg[3] == 'm') /* "opt&vim": set to Vim default */
1459 {
1460 cp_val = FALSE;
1461 arg += 3;
1462 }
1463 else /* "opt&vi": set to Vi default */
1464 {
1465 cp_val = TRUE;
1466 arg += 2;
1467 }
1468 }
1469 if (vim_strchr((char_u *)"?!&<", nextchar) != NULL
Bram Moolenaar1c465442017-03-12 20:10:05 +01001470 && arg[1] != NUL && !VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001471 {
1472 errmsg = e_trailing;
1473 goto skip;
1474 }
1475 }
1476
1477 /*
Bram Moolenaar48e330a2016-02-23 14:53:34 +01001478 * allow '=' and ':' for hystorical reasons (MSDOS command.com
1479 * allows only one '=' character per "set" command line. grrr. (jw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480 */
1481 if (nextchar == '?'
1482 || (prefix == 1
1483 && vim_strchr((char_u *)"=:&<", nextchar) == NULL
1484 && !(flags & P_BOOL)))
1485 {
1486 /*
1487 * print value
1488 */
1489 if (did_show)
1490 msg_putchar('\n'); /* cursor below last one */
1491 else
1492 {
1493 gotocmdline(TRUE); /* cursor at status line */
1494 did_show = TRUE; /* remember that we did a line */
1495 }
1496 if (opt_idx >= 0)
1497 {
1498 showoneopt(&options[opt_idx], opt_flags);
1499#ifdef FEAT_EVAL
1500 if (p_verbose > 0)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001501 {
1502 /* Mention where the option was last set. */
1503 if (varp == options[opt_idx].var)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001504 last_set_msg(options[opt_idx].script_ctx);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001505 else if ((int)options[opt_idx].indir & PV_WIN)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001506 last_set_msg(curwin->w_p_script_ctx[
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001507 (int)options[opt_idx].indir & PV_MASK]);
1508 else if ((int)options[opt_idx].indir & PV_BUF)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02001509 last_set_msg(curbuf->b_p_script_ctx[
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001510 (int)options[opt_idx].indir & PV_MASK]);
1511 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001512#endif
1513 }
1514 else
1515 {
1516 char_u *p;
1517
1518 p = find_termcode(key_name);
1519 if (p == NULL)
1520 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001521 errmsg = N_("E846: Key code not set");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001522 goto skip;
1523 }
1524 else
1525 (void)show_one_termcode(key_name, p, TRUE);
1526 }
1527 if (nextchar != '?'
Bram Moolenaar1c465442017-03-12 20:10:05 +01001528 && nextchar != NUL && !VIM_ISWHITE(afterchar))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001529 errmsg = e_trailing;
1530 }
1531 else
1532 {
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01001533 int value_is_replaced = !prepending && !adding && !removing;
Bram Moolenaar916a8182018-11-25 02:18:29 +01001534 int value_checked = FALSE;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01001535
Bram Moolenaar071d4272004-06-13 20:20:40 +00001536 if (flags & P_BOOL) /* boolean */
1537 {
1538 if (nextchar == '=' || nextchar == ':')
1539 {
1540 errmsg = e_invarg;
1541 goto skip;
1542 }
1543
1544 /*
1545 * ":set opt!": invert
1546 * ":set opt&": reset to default value
1547 * ":set opt<": reset to global value
1548 */
1549 if (nextchar == '!')
1550 value = *(int *)(varp) ^ 1;
1551 else if (nextchar == '&')
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001552 value = (int)(long)(long_i)options[opt_idx].def_val[
Bram Moolenaar071d4272004-06-13 20:20:40 +00001553 ((flags & P_VI_DEF) || cp_val)
1554 ? VI_DEFAULT : VIM_DEFAULT];
1555 else if (nextchar == '<')
1556 {
1557 /* For 'autoread' -1 means to use global value. */
1558 if ((int *)varp == &curbuf->b_p_ar
1559 && opt_flags == OPT_LOCAL)
1560 value = -1;
1561 else
1562 value = *(int *)get_varp_scope(&(options[opt_idx]),
1563 OPT_GLOBAL);
1564 }
1565 else
1566 {
1567 /*
1568 * ":set invopt": invert
1569 * ":set opt" or ":set noopt": set or reset
1570 */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001571 if (nextchar != NUL && !VIM_ISWHITE(afterchar))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001572 {
1573 errmsg = e_trailing;
1574 goto skip;
1575 }
1576 if (prefix == 2) /* inv */
1577 value = *(int *)(varp) ^ 1;
1578 else
1579 value = prefix;
1580 }
1581
1582 errmsg = set_bool_option(opt_idx, varp, (int)value,
1583 opt_flags);
1584 }
1585 else /* numeric or string */
1586 {
1587 if (vim_strchr((char_u *)"=:&<", nextchar) == NULL
1588 || prefix != 1)
1589 {
1590 errmsg = e_invarg;
1591 goto skip;
1592 }
1593
1594 if (flags & P_NUM) /* numeric */
1595 {
1596 /*
1597 * Different ways to set a number option:
1598 * & set to default value
1599 * < set to global value
1600 * <xx> accept special key codes for 'wildchar'
1601 * c accept any non-digit for 'wildchar'
1602 * [-]0-9 set number
1603 * other error
1604 */
1605 ++arg;
1606 if (nextchar == '&')
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001607 value = (long)(long_i)options[opt_idx].def_val[
Bram Moolenaar071d4272004-06-13 20:20:40 +00001608 ((flags & P_VI_DEF) || cp_val)
1609 ? VI_DEFAULT : VIM_DEFAULT];
1610 else if (nextchar == '<')
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01001611 {
1612 /* For 'undolevels' NO_LOCAL_UNDOLEVEL means to
1613 * use the global value. */
1614 if ((long *)varp == &curbuf->b_p_ul
1615 && opt_flags == OPT_LOCAL)
1616 value = NO_LOCAL_UNDOLEVEL;
1617 else
1618 value = *(long *)get_varp_scope(
1619 &(options[opt_idx]), OPT_GLOBAL);
1620 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001621 else if (((long *)varp == &p_wc
1622 || (long *)varp == &p_wcm)
1623 && (*arg == '<'
1624 || *arg == '^'
Bram Moolenaar1c465442017-03-12 20:10:05 +01001625 || (*arg != NUL
1626 && (!arg[1] || VIM_ISWHITE(arg[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001627 && !VIM_ISDIGIT(*arg))))
1628 {
Bram Moolenaardbe948d2017-07-23 22:50:51 +02001629 value = string_to_key(arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001630 if (value == 0 && (long *)varp != &p_wcm)
1631 {
1632 errmsg = e_invarg;
1633 goto skip;
1634 }
1635 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001636 else if (*arg == '-' || VIM_ISDIGIT(*arg))
1637 {
Bram Moolenaar18400e62015-01-27 15:58:40 +01001638 /* Allow negative (for 'undolevels'), octal and
1639 * hex numbers. */
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001640 vim_str2nr(arg, NULL, &i, STR2NR_ALL,
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001641 &value, NULL, 0, TRUE);
Bram Moolenaar06e2c812019-06-12 19:05:48 +02001642 if (i == 0 || (arg[i] != NUL
1643 && !VIM_ISWHITE(arg[i])))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001644 {
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001645 errmsg = N_("E521: Number required after =");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646 goto skip;
1647 }
1648 }
1649 else
1650 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001651 errmsg = N_("E521: Number required after =");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001652 goto skip;
1653 }
1654
1655 if (adding)
1656 value = *(long *)varp + value;
1657 if (prepending)
1658 value = *(long *)varp * value;
1659 if (removing)
1660 value = *(long *)varp - value;
1661 errmsg = set_num_option(opt_idx, varp, value,
Bram Moolenaar555b2802005-05-19 21:08:39 +00001662 errbuf, sizeof(errbuf), opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001663 }
1664 else if (opt_idx >= 0) /* string */
1665 {
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001666 char_u *save_arg = NULL;
1667 char_u *s = NULL;
1668 char_u *oldval = NULL; /* previous value if *varp */
1669 char_u *newval;
1670 char_u *origval = NULL;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001671 char_u *origval_l = NULL;
1672 char_u *origval_g = NULL;
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001673#if defined(FEAT_EVAL)
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001674 char_u *saved_origval = NULL;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001675 char_u *saved_origval_l = NULL;
1676 char_u *saved_origval_g = NULL;
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001677 char_u *saved_newval = NULL;
Bram Moolenaar53744302015-07-17 17:38:22 +02001678#endif
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001679 unsigned newlen;
1680 int comma;
1681 int bs;
1682 int new_value_alloced; /* new string option
Bram Moolenaar071d4272004-06-13 20:20:40 +00001683 was allocated */
1684
1685 /* When using ":set opt=val" for a global option
1686 * with a local value the local value will be
1687 * reset, use the global value here. */
1688 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001689 && ((int)options[opt_idx].indir & PV_BOTH))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001690 varp = options[opt_idx].var;
1691
1692 /* The old value is kept until we are sure that the
1693 * new value is valid. */
1694 oldval = *(char_u **)varp;
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001695
Bram Moolenaard7c96872019-06-15 17:12:48 +02001696 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
1697 {
1698 origval_l = *(char_u **)get_varp_scope(
1699 &(options[opt_idx]), OPT_LOCAL);
1700 origval_g = *(char_u **)get_varp_scope(
1701 &(options[opt_idx]), OPT_GLOBAL);
1702
1703 // A global-local string option might have an empty
1704 // option as value to indicate that the global
1705 // value should be used.
1706 if (((int)options[opt_idx].indir & PV_BOTH)
1707 && origval_l == empty_option)
1708 origval_l = origval_g;
1709 }
1710
1711 // When setting the local value of a global
1712 // option, the old value may be the global value.
Bram Moolenaar8efa0262017-08-20 15:47:20 +02001713 if (((int)options[opt_idx].indir & PV_BOTH)
1714 && (opt_flags & OPT_LOCAL))
1715 origval = *(char_u **)get_varp(
1716 &options[opt_idx]);
1717 else
1718 origval = oldval;
1719
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720 if (nextchar == '&') /* set to default val */
1721 {
1722 newval = options[opt_idx].def_val[
1723 ((flags & P_VI_DEF) || cp_val)
1724 ? VI_DEFAULT : VIM_DEFAULT];
1725 if ((char_u **)varp == &p_bg)
1726 {
1727 /* guess the value of 'background' */
1728#ifdef FEAT_GUI
1729 if (gui.in_use)
1730 newval = gui_bg_default();
1731 else
1732#endif
Bram Moolenaarf740b292006-02-16 22:11:02 +00001733 newval = term_bg_default();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001734 }
1735
1736 /* expand environment variables and ~ (since the
1737 * default value was already expanded, only
1738 * required when an environment variable was set
1739 * later */
1740 if (newval == NULL)
1741 newval = empty_option;
1742 else
1743 {
1744 s = option_expand(opt_idx, newval);
1745 if (s == NULL)
1746 s = newval;
1747 newval = vim_strsave(s);
1748 }
1749 new_value_alloced = TRUE;
1750 }
1751 else if (nextchar == '<') /* set to global val */
1752 {
1753 newval = vim_strsave(*(char_u **)get_varp_scope(
1754 &(options[opt_idx]), OPT_GLOBAL));
1755 new_value_alloced = TRUE;
1756 }
1757 else
1758 {
1759 ++arg; /* jump to after the '=' or ':' */
1760
1761 /*
1762 * Set 'keywordprg' to ":help" if an empty
1763 * value was passed to :set by the user.
1764 * Misuse errbuf[] for the resulting string.
1765 */
1766 if (varp == (char_u *)&p_kp
1767 && (*arg == NUL || *arg == ' '))
1768 {
1769 STRCPY(errbuf, ":help");
1770 save_arg = arg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001771 arg = (char_u *)errbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001772 }
1773 /*
Bram Moolenaar4e5ccfa2011-11-30 11:15:47 +01001774 * Convert 'backspace' number to string, for
1775 * adding, prepending and removing string.
1776 */
1777 else if (varp == (char_u *)&p_bs
1778 && VIM_ISDIGIT(**(char_u **)varp))
1779 {
1780 i = getdigits((char_u **)varp);
1781 switch (i)
1782 {
1783 case 0:
1784 *(char_u **)varp = empty_option;
1785 break;
1786 case 1:
1787 *(char_u **)varp = vim_strsave(
1788 (char_u *)"indent,eol");
1789 break;
1790 case 2:
1791 *(char_u **)varp = vim_strsave(
1792 (char_u *)"indent,eol,start");
1793 break;
1794 }
1795 vim_free(oldval);
Bram Moolenaaredbc0d42017-08-20 16:11:51 +02001796 if (origval == oldval)
1797 origval = *(char_u **)varp;
Bram Moolenaard7c96872019-06-15 17:12:48 +02001798 if (origval_l == oldval)
1799 origval_l = *(char_u **)varp;
1800 if (origval_g == oldval)
1801 origval_g = *(char_u **)varp;
Bram Moolenaar4e5ccfa2011-11-30 11:15:47 +01001802 oldval = *(char_u **)varp;
1803 }
1804 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001805 * Convert 'whichwrap' number to string, for
1806 * backwards compatibility with Vim 3.0.
1807 * Misuse errbuf[] for the resulting string.
1808 */
1809 else if (varp == (char_u *)&p_ww
1810 && VIM_ISDIGIT(*arg))
1811 {
1812 *errbuf = NUL;
1813 i = getdigits(&arg);
1814 if (i & 1)
1815 STRCAT(errbuf, "b,");
1816 if (i & 2)
1817 STRCAT(errbuf, "s,");
1818 if (i & 4)
1819 STRCAT(errbuf, "h,l,");
1820 if (i & 8)
1821 STRCAT(errbuf, "<,>,");
1822 if (i & 16)
1823 STRCAT(errbuf, "[,],");
1824 if (*errbuf != NUL) /* remove trailing , */
1825 errbuf[STRLEN(errbuf) - 1] = NUL;
1826 save_arg = arg;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01001827 arg = (char_u *)errbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001828 }
1829 /*
1830 * Remove '>' before 'dir' and 'bdir', for
1831 * backwards compatibility with version 3.0
1832 */
1833 else if ( *arg == '>'
1834 && (varp == (char_u *)&p_dir
1835 || varp == (char_u *)&p_bdir))
1836 {
1837 ++arg;
1838 }
1839
Bram Moolenaar071d4272004-06-13 20:20:40 +00001840 /*
1841 * Copy the new string into allocated memory.
1842 * Can't use set_string_option_direct(), because
1843 * we need to remove the backslashes.
1844 */
1845 /* get a bit too much */
1846 newlen = (unsigned)STRLEN(arg) + 1;
1847 if (adding || prepending || removing)
1848 newlen += (unsigned)STRLEN(origval) + 1;
1849 newval = alloc(newlen);
1850 if (newval == NULL) /* out of mem, don't change */
1851 break;
1852 s = newval;
1853
1854 /*
1855 * Copy the string, skip over escaped chars.
1856 * For MS-DOS and WIN32 backslashes before normal
1857 * file name characters are not removed, and keep
1858 * backslash at start, for "\\machine\path", but
1859 * do remove it for "\\\\machine\\path".
1860 * The reverse is found in ExpandOldSetting().
1861 */
Bram Moolenaar1c465442017-03-12 20:10:05 +01001862 while (*arg && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 {
1864 if (*arg == '\\' && arg[1] != NUL
1865#ifdef BACKSLASH_IN_FILENAME
1866 && !((flags & P_EXPAND)
1867 && vim_isfilec(arg[1])
1868 && (arg[1] != '\\'
1869 || (s == newval
1870 && arg[2] != '\\')))
1871#endif
1872 )
1873 ++arg; /* remove backslash */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874 if (has_mbyte
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00001875 && (i = (*mb_ptr2len)(arg)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 {
1877 /* copy multibyte char */
1878 mch_memmove(s, arg, (size_t)i);
1879 arg += i;
1880 s += i;
1881 }
1882 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001883 *s++ = *arg++;
1884 }
1885 *s = NUL;
1886
1887 /*
1888 * Expand environment variables and ~.
1889 * Don't do it when adding without inserting a
1890 * comma.
1891 */
1892 if (!(adding || prepending || removing)
1893 || (flags & P_COMMA))
1894 {
1895 s = option_expand(opt_idx, newval);
1896 if (s != NULL)
1897 {
1898 vim_free(newval);
1899 newlen = (unsigned)STRLEN(s) + 1;
1900 if (adding || prepending || removing)
1901 newlen += (unsigned)STRLEN(origval) + 1;
1902 newval = alloc(newlen);
1903 if (newval == NULL)
1904 break;
1905 STRCPY(newval, s);
1906 }
1907 }
1908
1909 /* locate newval[] in origval[] when removing it
1910 * and when adding to avoid duplicates */
1911 i = 0; /* init for GCC */
1912 if (removing || (flags & P_NODUP))
1913 {
1914 i = (int)STRLEN(newval);
1915 bs = 0;
1916 for (s = origval; *s; ++s)
1917 {
1918 if ((!(flags & P_COMMA)
1919 || s == origval
1920 || (s[-1] == ',' && !(bs & 1)))
1921 && STRNCMP(s, newval, i) == 0
1922 && (!(flags & P_COMMA)
1923 || s[i] == ','
1924 || s[i] == NUL))
1925 break;
Bram Moolenaar0b2f94d2011-03-22 14:35:05 +01001926 /* Count backslashes. Only a comma with an
Bram Moolenaar8f79acd2016-01-01 14:48:20 +01001927 * even number of backslashes or a single
1928 * backslash preceded by a comma before it
1929 * is recognized as a separator */
1930 if ((s > origval + 1
1931 && s[-1] == '\\'
1932 && s[-2] != ',')
1933 || (s == origval + 1
1934 && s[-1] == '\\'))
1935
Bram Moolenaar071d4272004-06-13 20:20:40 +00001936 ++bs;
1937 else
1938 bs = 0;
1939 }
1940
1941 /* do not add if already there */
1942 if ((adding || prepending) && *s)
1943 {
1944 prepending = FALSE;
1945 adding = FALSE;
1946 STRCPY(newval, origval);
1947 }
1948 }
1949
1950 /* concatenate the two strings; add a ',' if
1951 * needed */
1952 if (adding || prepending)
1953 {
1954 comma = ((flags & P_COMMA) && *origval != NUL
1955 && *newval != NUL);
1956 if (adding)
1957 {
1958 i = (int)STRLEN(origval);
Bram Moolenaara7b7b1c2015-06-19 14:06:43 +02001959 /* strip a trailing comma, would get 2 */
Bram Moolenaar17467472015-11-10 17:50:24 +01001960 if (comma && i > 1
1961 && (flags & P_ONECOMMA) == P_ONECOMMA
1962 && origval[i - 1] == ','
1963 && origval[i - 2] != '\\')
Bram Moolenaara7b7b1c2015-06-19 14:06:43 +02001964 i--;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001965 mch_memmove(newval + i + comma, newval,
1966 STRLEN(newval) + 1);
1967 mch_memmove(newval, origval, (size_t)i);
1968 }
1969 else
1970 {
1971 i = (int)STRLEN(newval);
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00001972 STRMOVE(newval + i + comma, origval);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001973 }
1974 if (comma)
1975 newval[i] = ',';
1976 }
1977
1978 /* Remove newval[] from origval[]. (Note: "i" has
1979 * been set above and is used here). */
1980 if (removing)
1981 {
1982 STRCPY(newval, origval);
1983 if (*s)
1984 {
1985 /* may need to remove a comma */
1986 if (flags & P_COMMA)
1987 {
1988 if (s == origval)
1989 {
1990 /* include comma after string */
1991 if (s[i] == ',')
1992 ++i;
1993 }
1994 else
1995 {
1996 /* include comma before string */
1997 --s;
1998 ++i;
1999 }
2000 }
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00002001 STRMOVE(newval + (s - origval), s + i);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002002 }
2003 }
2004
2005 if (flags & P_FLAGLIST)
2006 {
2007 /* Remove flags that appear twice. */
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01002008 for (s = newval; *s;)
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002009 {
2010 /* if options have P_FLAGLIST and
2011 * P_ONECOMMA such as 'whichwrap' */
2012 if (flags & P_ONECOMMA)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002013 {
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002014 if (*s != ',' && *(s + 1) == ','
2015 && vim_strchr(s + 2, *s) != NULL)
2016 {
2017 /* Remove the duplicated value and
2018 * the next comma. */
2019 STRMOVE(s, s + 2);
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01002020 continue;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002021 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002022 }
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002023 else
2024 {
2025 if ((!(flags & P_COMMA) || *s != ',')
2026 && vim_strchr(s + 1, *s) != NULL)
2027 {
2028 STRMOVE(s, s + 1);
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01002029 continue;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002030 }
2031 }
Bram Moolenaaraaaf57d2017-02-05 14:13:20 +01002032 ++s;
Bram Moolenaarc8ce6152016-08-07 13:48:20 +02002033 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002034 }
2035
2036 if (save_arg != NULL) /* number for 'whichwrap' */
2037 arg = save_arg;
2038 new_value_alloced = TRUE;
2039 }
2040
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002041 /*
2042 * Set the new value.
2043 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002044 *(char_u **)(varp) = newval;
2045
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01002046#if defined(FEAT_EVAL)
Bram Moolenaar5cbb8db2015-07-17 23:08:29 +02002047 if (!starting
2048# ifdef FEAT_CRYPT
2049 && options[opt_idx].indir != PV_KEY
2050# endif
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002051 && origval != NULL && newval != NULL)
2052 {
Bram Moolenaar53744302015-07-17 17:38:22 +02002053 /* origval may be freed by
2054 * did_set_string_option(), make a copy. */
2055 saved_origval = vim_strsave(origval);
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002056 /* newval (and varp) may become invalid if the
2057 * buffer is closed by autocommands. */
2058 saved_newval = vim_strsave(newval);
Bram Moolenaard7c96872019-06-15 17:12:48 +02002059 if (origval_l != NULL)
2060 saved_origval_l = vim_strsave(origval_l);
2061 if (origval_g != NULL)
2062 saved_origval_g = vim_strsave(origval_g);
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002063 }
Bram Moolenaar53744302015-07-17 17:38:22 +02002064#endif
2065
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002066 {
2067 long_u *p = insecure_flag(opt_idx, opt_flags);
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002068 int secure_saved = secure;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002069
2070 // When an option is set in the sandbox, from a
2071 // modeline or in secure mode, then deal with side
2072 // effects in secure mode. Also when the value was
2073 // set with the P_INSECURE flag and is not
2074 // completely replaced.
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002075 if ((opt_flags & OPT_MODELINE)
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002076#ifdef HAVE_SANDBOX
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002077 || sandbox != 0
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002078#endif
Bram Moolenaar82b033e2019-03-24 14:02:04 +01002079 || (!value_is_replaced && (*p & P_INSECURE)))
2080 secure = 1;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002081
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002082 // Handle side effects, and set the global value
2083 // for ":set" on local options. Note: when setting
2084 // 'syntax' or 'filetype' autocommands may be
2085 // triggered that can cause havoc.
2086 errmsg = did_set_string_option(
2087 opt_idx, (char_u **)varp,
Bram Moolenaar916a8182018-11-25 02:18:29 +01002088 new_value_alloced, oldval, errbuf,
2089 opt_flags, &value_checked);
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002090
Bram Moolenaar48f377a2018-12-21 13:03:28 +01002091 secure = secure_saved;
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01002092 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002093
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01002094#if defined(FEAT_EVAL)
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002095 if (errmsg == NULL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002096 trigger_optionsset_string(
2097 opt_idx, opt_flags, saved_origval,
2098 saved_origval_l, saved_origval_g,
2099 saved_newval);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002100 vim_free(saved_origval);
Bram Moolenaard7c96872019-06-15 17:12:48 +02002101 vim_free(saved_origval_l);
2102 vim_free(saved_origval_g);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002103 vim_free(saved_newval);
2104#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002105 /* If error detected, print the error message. */
2106 if (errmsg != NULL)
2107 goto skip;
2108 }
2109 else /* key code option */
2110 {
2111 char_u *p;
2112
2113 if (nextchar == '&')
2114 {
2115 if (add_termcap_entry(key_name, TRUE) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002116 errmsg = N_("E522: Not found in termcap");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002117 }
2118 else
2119 {
2120 ++arg; /* jump to after the '=' or ':' */
Bram Moolenaar1c465442017-03-12 20:10:05 +01002121 for (p = arg; *p && !VIM_ISWHITE(*p); ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002122 if (*p == '\\' && p[1] != NUL)
2123 ++p;
2124 nextchar = *p;
2125 *p = NUL;
2126 add_termcode(key_name, arg, FALSE);
2127 *p = nextchar;
2128 }
2129 if (full_screen)
2130 ttest(FALSE);
2131 redraw_all_later(CLEAR);
2132 }
2133 }
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002134
Bram Moolenaar071d4272004-06-13 20:20:40 +00002135 if (opt_idx >= 0)
Bram Moolenaar916a8182018-11-25 02:18:29 +01002136 did_set_option(
2137 opt_idx, opt_flags, value_is_replaced, value_checked);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002138 }
2139
2140skip:
2141 /*
2142 * Advance to next argument.
2143 * - skip until a blank found, taking care of backslashes
2144 * - skip blanks
2145 * - skip one "=val" argument (for hidden options ":set gfn =xx")
2146 */
2147 for (i = 0; i < 2 ; ++i)
2148 {
Bram Moolenaar1c465442017-03-12 20:10:05 +01002149 while (*arg != NUL && !VIM_ISWHITE(*arg))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002150 if (*arg++ == '\\' && *arg != NUL)
2151 ++arg;
2152 arg = skipwhite(arg);
2153 if (*arg != '=')
2154 break;
2155 }
2156 }
2157
2158 if (errmsg != NULL)
2159 {
Bram Moolenaarce0842a2005-07-18 21:58:11 +00002160 vim_strncpy(IObuff, (char_u *)_(errmsg), IOSIZE - 1);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002161 i = (int)STRLEN(IObuff) + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002162 if (i + (arg - startarg) < IOSIZE)
2163 {
2164 /* append the argument with the error */
2165 STRCAT(IObuff, ": ");
2166 mch_memmove(IObuff + i, startarg, (arg - startarg));
2167 IObuff[i + (arg - startarg)] = NUL;
2168 }
2169 /* make sure all characters are printable */
2170 trans_characters(IObuff, IOSIZE);
2171
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002172 ++no_wait_return; // wait_return done later
2173 emsg((char *)IObuff); // show error highlighted
Bram Moolenaar071d4272004-06-13 20:20:40 +00002174 --no_wait_return;
2175
2176 return FAIL;
2177 }
2178
2179 arg = skipwhite(arg);
2180 }
2181
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002182theend:
2183 if (silent_mode && did_show)
2184 {
2185 /* After displaying option values in silent mode. */
2186 silent_mode = FALSE;
2187 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
2188 msg_putchar('\n');
2189 cursor_on(); /* msg_start() switches it off */
2190 out_flush();
2191 silent_mode = TRUE;
2192 info_message = FALSE; /* use mch_msg(), not mch_errmsg() */
2193 }
2194
Bram Moolenaar071d4272004-06-13 20:20:40 +00002195 return OK;
2196}
2197
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002198/*
2199 * Call this when an option has been given a new value through a user command.
2200 * Sets the P_WAS_SET flag and takes care of the P_INSECURE flag.
2201 */
2202 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002203did_set_option(
2204 int opt_idx,
Bram Moolenaar916a8182018-11-25 02:18:29 +01002205 int opt_flags, // possibly with OPT_MODELINE
2206 int new_value, // value was replaced completely
2207 int value_checked) // value was checked to be safe, no need to set the
2208 // P_INSECURE flag.
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002209{
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002210 long_u *p;
2211
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002212 options[opt_idx].flags |= P_WAS_SET;
2213
2214 /* When an option is set in the sandbox, from a modeline or in secure mode
2215 * set the P_INSECURE flag. Otherwise, if a new value is stored reset the
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002216 * flag. */
2217 p = insecure_flag(opt_idx, opt_flags);
Bram Moolenaar916a8182018-11-25 02:18:29 +01002218 if (!value_checked && (secure
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002219#ifdef HAVE_SANDBOX
2220 || sandbox != 0
2221#endif
Bram Moolenaar916a8182018-11-25 02:18:29 +01002222 || (opt_flags & OPT_MODELINE)))
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002223 *p = *p | P_INSECURE;
2224 else if (new_value)
2225 *p = *p & ~P_INSECURE;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002226}
2227
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002228 static char *
2229illegal_char(char *errbuf, int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002230{
2231 if (errbuf == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002232 return "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00002233 sprintf((char *)errbuf, _("E539: Illegal character <%s>"),
Bram Moolenaar555b2802005-05-19 21:08:39 +00002234 (char *)transchar(c));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002235 return errbuf;
2236}
2237
2238/*
2239 * Convert a key name or string into a key value.
2240 * Used for 'wildchar' and 'cedit' options.
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002241 * When "multi_byte" is TRUE allow for multi-byte characters.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002242 */
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002243 int
2244string_to_key(char_u *arg, int multi_byte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002245{
2246 if (*arg == '<')
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02002247 return find_key_option(arg + 1, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002248 if (*arg == '^')
2249 return Ctrl_chr(arg[1]);
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002250 if (multi_byte)
2251 return PTR2CHAR(arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002252 return *arg;
2253}
2254
2255#ifdef FEAT_CMDWIN
2256/*
2257 * Check value of 'cedit' and set cedit_key.
2258 * Returns NULL if value is OK, error message otherwise.
2259 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002260 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002261check_cedit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002262{
2263 int n;
2264
2265 if (*p_cedit == NUL)
2266 cedit_key = -1;
2267 else
2268 {
Bram Moolenaardbe948d2017-07-23 22:50:51 +02002269 n = string_to_key(p_cedit, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002270 if (vim_isprintc(n))
2271 return e_invarg;
2272 cedit_key = n;
2273 }
2274 return NULL;
2275}
2276#endif
2277
2278#ifdef FEAT_TITLE
2279/*
2280 * When changing 'title', 'titlestring', 'icon' or 'iconstring', call
2281 * maketitle() to create and display it.
2282 * When switching the title or icon off, call mch_restore_title() to get
2283 * the old value back.
2284 */
2285 static void
Bram Moolenaar84a93082018-06-16 22:58:15 +02002286did_set_title(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002287{
2288 if (starting != NO_SCREEN
2289#ifdef FEAT_GUI
2290 && !gui.starting
2291#endif
2292 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00002293 maketitle();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002294}
2295#endif
2296
2297/*
2298 * set_options_bin - called when 'bin' changes value.
2299 */
2300 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002301set_options_bin(
2302 int oldval,
2303 int newval,
2304 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002305{
2306 /*
2307 * The option values that are changed when 'bin' changes are
2308 * copied when 'bin is set and restored when 'bin' is reset.
2309 */
2310 if (newval)
2311 {
2312 if (!oldval) /* switched on */
2313 {
2314 if (!(opt_flags & OPT_GLOBAL))
2315 {
2316 curbuf->b_p_tw_nobin = curbuf->b_p_tw;
2317 curbuf->b_p_wm_nobin = curbuf->b_p_wm;
2318 curbuf->b_p_ml_nobin = curbuf->b_p_ml;
2319 curbuf->b_p_et_nobin = curbuf->b_p_et;
2320 }
2321 if (!(opt_flags & OPT_LOCAL))
2322 {
2323 p_tw_nobin = p_tw;
2324 p_wm_nobin = p_wm;
2325 p_ml_nobin = p_ml;
2326 p_et_nobin = p_et;
2327 }
2328 }
2329
2330 if (!(opt_flags & OPT_GLOBAL))
2331 {
2332 curbuf->b_p_tw = 0; /* no automatic line wrap */
2333 curbuf->b_p_wm = 0; /* no automatic line wrap */
2334 curbuf->b_p_ml = 0; /* no modelines */
2335 curbuf->b_p_et = 0; /* no expandtab */
2336 }
2337 if (!(opt_flags & OPT_LOCAL))
2338 {
2339 p_tw = 0;
2340 p_wm = 0;
2341 p_ml = FALSE;
2342 p_et = FALSE;
2343 p_bin = TRUE; /* needed when called for the "-b" argument */
2344 }
2345 }
2346 else if (oldval) /* switched off */
2347 {
2348 if (!(opt_flags & OPT_GLOBAL))
2349 {
2350 curbuf->b_p_tw = curbuf->b_p_tw_nobin;
2351 curbuf->b_p_wm = curbuf->b_p_wm_nobin;
2352 curbuf->b_p_ml = curbuf->b_p_ml_nobin;
2353 curbuf->b_p_et = curbuf->b_p_et_nobin;
2354 }
2355 if (!(opt_flags & OPT_LOCAL))
2356 {
2357 p_tw = p_tw_nobin;
2358 p_wm = p_wm_nobin;
2359 p_ml = p_ml_nobin;
2360 p_et = p_et_nobin;
2361 }
2362 }
2363}
2364
Bram Moolenaar071d4272004-06-13 20:20:40 +00002365/*
2366 * Expand environment variables for some string options.
2367 * These string options cannot be indirect!
2368 * If "val" is NULL expand the current value of the option.
2369 * Return pointer to NameBuff, or NULL when not expanded.
2370 */
2371 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002372option_expand(int opt_idx, char_u *val)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002373{
2374 /* if option doesn't need expansion nothing to do */
2375 if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL)
2376 return NULL;
2377
2378 /* If val is longer than MAXPATHL no meaningful expansion can be done,
2379 * expand_env() would truncate the string. */
2380 if (val != NULL && STRLEN(val) > MAXPATHL)
2381 return NULL;
2382
2383 if (val == NULL)
2384 val = *(char_u **)options[opt_idx].var;
2385
2386 /*
2387 * Expanding this with NameBuff, expand_env() must not be passed IObuff.
2388 * Escape spaces when expanding 'tags', they are used to separate file
2389 * names.
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002390 * For 'spellsuggest' expand after "file:".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002391 */
2392 expand_env_esc(val, NameBuff, MAXPATHL,
Bram Moolenaar9f0545d2007-09-26 20:36:32 +00002393 (char_u **)options[opt_idx].var == &p_tags, FALSE,
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002394#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002395 (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" :
2396#endif
2397 NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 if (STRCMP(NameBuff, val) == 0) /* they are the same */
2399 return NULL;
2400
2401 return NameBuff;
2402}
2403
2404/*
2405 * After setting various option values: recompute variables that depend on
2406 * option values.
2407 */
2408 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002409didset_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410{
2411 /* initialize the table for 'iskeyword' et.al. */
2412 (void)init_chartab();
2413
2414 (void)opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE);
2415 (void)opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, TRUE);
Bram Moolenaar165bc692015-07-21 17:53:25 +02002416 (void)opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002417#ifdef FEAT_SESSION
2418 (void)opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE);
2419 (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE);
2420#endif
2421#ifdef FEAT_FOLDING
2422 (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE);
2423#endif
2424 (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE);
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01002425 (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002426 (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427#if defined(FEAT_MOUSE) && (defined(UNIX) || defined(VMS))
2428 (void)opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE);
2429#endif
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002430#ifdef FEAT_SPELL
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00002431 (void)spell_check_msm();
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00002432 (void)spell_check_sps();
Bram Moolenaar860cae12010-06-05 23:22:07 +02002433 (void)compile_cap_prog(curwin->w_s);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002434 (void)did_set_spell_option(TRUE);
Bram Moolenaard857f0e2005-06-21 22:37:39 +00002435#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01002436#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002437 (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE);
2438#endif
Bram Moolenaar182c5be2010-06-25 05:37:59 +02002439#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 (void)opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE);
2441#endif
2442#ifdef FEAT_CMDWIN
2443 /* set cedit_key */
2444 (void)check_cedit();
2445#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02002446#ifdef FEAT_LINEBREAK
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02002447 briopt_check(curwin);
Bram Moolenaar597a4222014-06-25 14:39:50 +02002448#endif
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002449#ifdef FEAT_LINEBREAK
2450 /* initialize the table for 'breakat'. */
2451 fill_breakat_flags();
2452#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +02002453#ifdef FEAT_SYN_HL
2454 fill_culopt_flags(NULL, curwin);
2455#endif
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002456}
2457
2458/*
2459 * More side effects of setting options.
2460 */
2461 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002462didset_options2(void)
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002463{
2464 /* Initialize the highlight_attr[] table. */
2465 (void)highlight_changed();
2466
2467 /* Parse default for 'wildmode' */
2468 check_opt_wim();
2469
2470 (void)set_chars_option(&p_lcs);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002471 /* Parse default for 'fillchars'. */
2472 (void)set_chars_option(&p_fcs);
Bram Moolenaare68c25c2015-08-25 15:39:55 +02002473
2474#ifdef FEAT_CLIPBOARD
2475 /* Parse default for 'clipboard' */
2476 (void)check_clipboard_option();
2477#endif
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002478#ifdef FEAT_VARTABS
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01002479 vim_free(curbuf->b_p_vsts_array);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002480 tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01002481 vim_free(curbuf->b_p_vts_array);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002482 tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
2483#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002484}
2485
2486/*
2487 * Check for string options that are NULL (normally only termcap options).
2488 */
2489 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002490check_options(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002491{
2492 int opt_idx;
2493
2494 for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++)
2495 if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL)
2496 check_string_option((char_u **)get_varp(&(options[opt_idx])));
2497}
2498
2499/*
2500 * Check string options in a buffer for NULL value.
2501 */
2502 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002503check_buf_options(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002504{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002505 check_string_option(&buf->b_p_bh);
2506 check_string_option(&buf->b_p_bt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002507 check_string_option(&buf->b_p_fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508 check_string_option(&buf->b_p_ff);
2509#ifdef FEAT_FIND_ID
2510 check_string_option(&buf->b_p_def);
2511 check_string_option(&buf->b_p_inc);
2512# ifdef FEAT_EVAL
2513 check_string_option(&buf->b_p_inex);
2514# endif
2515#endif
2516#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
2517 check_string_option(&buf->b_p_inde);
2518 check_string_option(&buf->b_p_indk);
2519#endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00002520#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
2521 check_string_option(&buf->b_p_bexpr);
2522#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02002523#if defined(FEAT_CRYPT)
2524 check_string_option(&buf->b_p_cm);
2525#endif
Bram Moolenaar9be7c042017-01-14 14:28:30 +01002526 check_string_option(&buf->b_p_fp);
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00002527#if defined(FEAT_EVAL)
2528 check_string_option(&buf->b_p_fex);
2529#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002530#ifdef FEAT_CRYPT
2531 check_string_option(&buf->b_p_key);
2532#endif
2533 check_string_option(&buf->b_p_kp);
2534 check_string_option(&buf->b_p_mps);
2535 check_string_option(&buf->b_p_fo);
Bram Moolenaar86b68352004-12-27 21:59:20 +00002536 check_string_option(&buf->b_p_flp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002537 check_string_option(&buf->b_p_isk);
2538#ifdef FEAT_COMMENTS
2539 check_string_option(&buf->b_p_com);
2540#endif
2541#ifdef FEAT_FOLDING
2542 check_string_option(&buf->b_p_cms);
2543#endif
2544 check_string_option(&buf->b_p_nf);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00002545#ifdef FEAT_TEXTOBJ
2546 check_string_option(&buf->b_p_qe);
2547#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002548#ifdef FEAT_SYN_HL
2549 check_string_option(&buf->b_p_syn);
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01002550 check_string_option(&buf->b_s.b_syn_isk);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00002551#endif
2552#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +02002553 check_string_option(&buf->b_s.b_p_spc);
2554 check_string_option(&buf->b_s.b_p_spf);
2555 check_string_option(&buf->b_s.b_p_spl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002556#endif
2557#ifdef FEAT_SEARCHPATH
2558 check_string_option(&buf->b_p_sua);
2559#endif
2560#ifdef FEAT_CINDENT
2561 check_string_option(&buf->b_p_cink);
2562 check_string_option(&buf->b_p_cino);
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01002563 parse_cino(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002564#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002565 check_string_option(&buf->b_p_ft);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002566#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
2567 check_string_option(&buf->b_p_cinw);
2568#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002569 check_string_option(&buf->b_p_cpt);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00002570#ifdef FEAT_COMPL_FUNC
2571 check_string_option(&buf->b_p_cfu);
Bram Moolenaare344bea2005-09-01 20:46:49 +00002572 check_string_option(&buf->b_p_ofu);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00002573#endif
Bram Moolenaar45e18cb2019-04-28 18:05:35 +02002574#ifdef FEAT_EVAL
2575 check_string_option(&buf->b_p_tfu);
2576#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002577#ifdef FEAT_KEYMAP
2578 check_string_option(&buf->b_p_keymap);
2579#endif
2580#ifdef FEAT_QUICKFIX
2581 check_string_option(&buf->b_p_gp);
2582 check_string_option(&buf->b_p_mp);
2583 check_string_option(&buf->b_p_efm);
2584#endif
2585 check_string_option(&buf->b_p_ep);
2586 check_string_option(&buf->b_p_path);
2587 check_string_option(&buf->b_p_tags);
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01002588 check_string_option(&buf->b_p_tc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002589 check_string_option(&buf->b_p_dict);
2590 check_string_option(&buf->b_p_tsr);
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01002591#ifdef FEAT_LISP
2592 check_string_option(&buf->b_p_lw);
2593#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02002594 check_string_option(&buf->b_p_bkc);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01002595 check_string_option(&buf->b_p_menc);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02002596#ifdef FEAT_VARTABS
2597 check_string_option(&buf->b_p_vsts);
2598 check_string_option(&buf->b_p_vts);
2599#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600}
2601
2602/*
2603 * Free the string allocated for an option.
2604 * Checks for the string being empty_option. This may happen if we're out of
2605 * memory, vim_strsave() returned NULL, which was replaced by empty_option by
2606 * check_options().
2607 * Does NOT check for P_ALLOCED flag!
2608 */
2609 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002610free_string_option(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611{
2612 if (p != empty_option)
2613 vim_free(p);
2614}
2615
2616 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002617clear_string_option(char_u **pp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002618{
2619 if (*pp != empty_option)
2620 vim_free(*pp);
2621 *pp = empty_option;
2622}
2623
2624 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002625check_string_option(char_u **pp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002626{
2627 if (*pp == NULL)
2628 *pp = empty_option;
2629}
2630
2631/*
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002632 * Return the option index found by a pointer into term_strings[].
2633 * Return -1 if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 */
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002635 int
2636get_term_opt_idx(char_u **p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002637{
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002638 int opt_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639
2640 for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++)
2641 if (options[opt_idx].var == (char_u *)p)
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02002642 return opt_idx;
2643 return -1; // cannot happen: didn't find it!
2644}
2645
2646/*
2647 * Mark a terminal option as allocated, found by a pointer into term_strings[].
2648 * Return the option index or -1 if not found.
2649 */
2650 int
2651set_term_option_alloced(char_u **p)
2652{
2653 int opt_idx = get_term_opt_idx(p);
2654
2655 if (opt_idx >= 0)
2656 options[opt_idx].flags |= P_ALLOCED;
2657 return opt_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002658}
2659
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002660#if defined(FEAT_EVAL) || defined(PROTO)
2661/*
2662 * Return TRUE when option "opt" was set from a modeline or in secure mode.
2663 * Return FALSE when it wasn't.
2664 * Return -1 for an unknown option.
2665 */
2666 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01002667was_set_insecurely(char_u *opt, int opt_flags)
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002668{
2669 int idx = findoption(opt);
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002670 long_u *flagp;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002671
2672 if (idx >= 0)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002673 {
2674 flagp = insecure_flag(idx, opt_flags);
2675 return (*flagp & P_INSECURE) != 0;
2676 }
Bram Moolenaar95f09602016-11-10 20:01:45 +01002677 internal_error("was_set_insecurely()");
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002678 return -1;
2679}
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002680
2681/*
2682 * Get a pointer to the flags used for the P_INSECURE flag of option
2683 * "opt_idx". For some local options a local flags field is used.
2684 */
2685 static long_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002686insecure_flag(int opt_idx, int opt_flags)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002687{
2688 if (opt_flags & OPT_LOCAL)
2689 switch ((int)options[opt_idx].indir)
2690 {
2691#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002692 case PV_STL: return &curwin->w_p_stl_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002693#endif
2694#ifdef FEAT_EVAL
Bram Moolenaar2e978902006-05-13 12:37:50 +00002695# ifdef FEAT_FOLDING
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002696 case PV_FDE: return &curwin->w_p_fde_flags;
2697 case PV_FDT: return &curwin->w_p_fdt_flags;
Bram Moolenaar2e978902006-05-13 12:37:50 +00002698# endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00002699# ifdef FEAT_BEVAL
2700 case PV_BEXPR: return &curbuf->b_p_bexpr_flags;
2701# endif
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002702# if defined(FEAT_CINDENT)
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002703 case PV_INDE: return &curbuf->b_p_inde_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002704# endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002705 case PV_FEX: return &curbuf->b_p_fex_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002706# ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002707 case PV_INEX: return &curbuf->b_p_inex_flags;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00002708# endif
2709#endif
2710 }
2711
2712 /* Nothing special, return global flags field. */
2713 return &options[opt_idx].flags;
2714}
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00002715#endif
2716
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002717#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002718/*
2719 * Redraw the window title and/or tab page text later.
2720 */
Bram Moolenaar9b578142016-01-30 19:39:49 +01002721static void redraw_titles(void)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002722{
2723 need_maketitle = TRUE;
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002724 redraw_tabline = TRUE;
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00002725}
2726#endif
2727
Bram Moolenaar071d4272004-06-13 20:20:40 +00002728/*
2729 * Set a string option to a new value (without checking the effect).
2730 * The string is copied into allocated memory.
2731 * if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used.
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002732 * When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When
2733 * "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to
2734 * "set_sid".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002735 */
2736 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002737set_string_option_direct(
2738 char_u *name,
2739 int opt_idx,
2740 char_u *val,
2741 int opt_flags, /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */
2742 int set_sid UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002743{
2744 char_u *s;
2745 char_u **varp;
2746 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
Bram Moolenaar89d40322006-08-29 15:30:07 +00002747 int idx = opt_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002748
Bram Moolenaar89d40322006-08-29 15:30:07 +00002749 if (idx == -1) /* use name */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002750 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002751 idx = findoption(name);
2752 if (idx < 0) /* not found (should not happen) */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002753 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002754 semsg(_(e_intern2), "set_string_option_direct()");
2755 siemsg(_("For option %s"), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002756 return;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002757 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758 }
2759
Bram Moolenaar89d40322006-08-29 15:30:07 +00002760 if (options[idx].var == NULL) /* can't set hidden option */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002761 return;
2762
2763 s = vim_strsave(val);
2764 if (s != NULL)
2765 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002766 varp = (char_u **)get_varp_scope(&(options[idx]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002767 both ? OPT_LOCAL : opt_flags);
Bram Moolenaar89d40322006-08-29 15:30:07 +00002768 if ((opt_flags & OPT_FREE) && (options[idx].flags & P_ALLOCED))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002769 free_string_option(*varp);
2770 *varp = s;
2771
2772 /* For buffer/window local option may also set the global value. */
2773 if (both)
Bram Moolenaar89d40322006-08-29 15:30:07 +00002774 set_string_option_global(idx, varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002775
Bram Moolenaar89d40322006-08-29 15:30:07 +00002776 options[idx].flags |= P_ALLOCED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002777
2778 /* When setting both values of a global option with a local value,
2779 * make the local value empty, so that the global value is used. */
Bram Moolenaar89d40322006-08-29 15:30:07 +00002780 if (((int)options[idx].indir & PV_BOTH) && both)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002781 {
2782 free_string_option(*varp);
2783 *varp = empty_option;
2784 }
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002785# ifdef FEAT_EVAL
2786 if (set_sid != SID_NONE)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002787 {
2788 sctx_T script_ctx;
2789
2790 if (set_sid == 0)
2791 script_ctx = current_sctx;
2792 else
2793 {
2794 script_ctx.sc_sid = set_sid;
Bram Moolenaarded5f1b2018-11-10 17:33:29 +01002795 script_ctx.sc_seq = 0;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002796 script_ctx.sc_lnum = 0;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02002797 script_ctx.sc_version = 1;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002798 }
2799 set_option_sctx_idx(idx, opt_flags, script_ctx);
2800 }
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00002801# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002802 }
2803}
2804
2805/*
Bram Moolenaar20c023a2019-05-26 21:03:24 +02002806 * Like set_string_option_direct(), but for a window-local option in "wp".
2807 * Blocks autocommands to avoid the old curwin becoming invalid.
2808 */
2809 void
2810set_string_option_direct_in_win(
2811 win_T *wp,
2812 char_u *name,
2813 int opt_idx,
2814 char_u *val,
2815 int opt_flags,
2816 int set_sid)
2817{
2818 win_T *save_curwin = curwin;
2819
2820 block_autocmds();
2821 curwin = wp;
2822 curbuf = curwin->w_buffer;
2823 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
2824 curwin = save_curwin;
2825 curbuf = curwin->w_buffer;
2826 unblock_autocmds();
2827}
2828
2829/*
2830 * Like set_string_option_direct(), but for a buffer-local option in "buf".
2831 * Blocks autocommands to avoid the old curbuf becoming invalid.
2832 */
2833 void
2834set_string_option_direct_in_buf(
2835 buf_T *buf,
2836 char_u *name,
2837 int opt_idx,
2838 char_u *val,
2839 int opt_flags,
2840 int set_sid)
2841{
2842 buf_T *save_curbuf = curbuf;
2843
2844 block_autocmds();
2845 curbuf = buf;
2846 curwin->w_buffer = curbuf;
2847 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
2848 curbuf = save_curbuf;
2849 curwin->w_buffer = curbuf;
2850 unblock_autocmds();
2851}
2852
2853/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854 * Set global value for string option when it's a local option.
2855 */
2856 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002857set_string_option_global(
2858 int opt_idx, /* option index */
2859 char_u **varp) /* pointer to option variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002860{
2861 char_u **p, *s;
2862
2863 /* the global value is always allocated */
2864 if (options[opt_idx].var == VAR_WIN)
2865 p = (char_u **)GLOBAL_WO(varp);
2866 else
2867 p = (char_u **)options[opt_idx].var;
2868 if (options[opt_idx].indir != PV_NONE
2869 && p != varp
2870 && (s = vim_strsave(*varp)) != NULL)
2871 {
2872 free_string_option(*p);
2873 *p = s;
2874 }
2875}
2876
2877/*
2878 * Set a string option to a new value, and handle the effects.
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002879 *
2880 * Returns NULL on success or error message on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002881 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002882 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002883set_string_option(
2884 int opt_idx,
2885 char_u *value,
2886 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002887{
2888 char_u *s;
2889 char_u **varp;
2890 char_u *oldval;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002891#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002892 char_u *oldval_l = NULL;
2893 char_u *oldval_g = NULL;
Bram Moolenaar53744302015-07-17 17:38:22 +02002894 char_u *saved_oldval = NULL;
Bram Moolenaard7c96872019-06-15 17:12:48 +02002895 char_u *saved_oldval_l = NULL;
2896 char_u *saved_oldval_g = NULL;
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002897 char_u *saved_newval = NULL;
Bram Moolenaar53744302015-07-17 17:38:22 +02002898#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002899 char *r = NULL;
Bram Moolenaar916a8182018-11-25 02:18:29 +01002900 int value_checked = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002901
2902 if (options[opt_idx].var == NULL) /* don't set hidden option */
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002903 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002904
2905 s = vim_strsave(value);
2906 if (s != NULL)
2907 {
2908 varp = (char_u **)get_varp_scope(&(options[opt_idx]),
2909 (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
Bram Moolenaara23ccb82006-02-27 00:08:02 +00002910 ? (((int)options[opt_idx].indir & PV_BOTH)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002911 ? OPT_GLOBAL : OPT_LOCAL)
2912 : opt_flags);
2913 oldval = *varp;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002914#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02002915 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
2916 {
2917 oldval_l = *(char_u **)get_varp_scope(&(options[opt_idx]),
2918 OPT_LOCAL);
2919 oldval_g = *(char_u **)get_varp_scope(&(options[opt_idx]),
2920 OPT_GLOBAL);
2921 }
Bram Moolenaar983f2f12019-06-16 16:41:41 +02002922#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 *varp = s;
Bram Moolenaar53744302015-07-17 17:38:22 +02002924
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01002925#if defined(FEAT_EVAL)
Bram Moolenaar5cbb8db2015-07-17 23:08:29 +02002926 if (!starting
2927# ifdef FEAT_CRYPT
2928 && options[opt_idx].indir != PV_KEY
2929# endif
2930 )
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002931 {
Bram Moolenaard7c96872019-06-15 17:12:48 +02002932 if (oldval_l != NULL)
2933 saved_oldval_l = vim_strsave(oldval_l);
2934 if (oldval_g != NULL)
2935 saved_oldval_g = vim_strsave(oldval_g);
Bram Moolenaar53744302015-07-17 17:38:22 +02002936 saved_oldval = vim_strsave(oldval);
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002937 saved_newval = vim_strsave(s);
2938 }
Bram Moolenaar53744302015-07-17 17:38:22 +02002939#endif
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002940 if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
Bram Moolenaar916a8182018-11-25 02:18:29 +01002941 opt_flags, &value_checked)) == NULL)
2942 did_set_option(opt_idx, opt_flags, TRUE, value_checked);
Bram Moolenaar53744302015-07-17 17:38:22 +02002943
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01002944#if defined(FEAT_EVAL)
Bram Moolenaar182a17b2017-06-25 20:57:18 +02002945 /* call autocommand after handling side effects */
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002946 if (r == NULL)
2947 trigger_optionsset_string(opt_idx, opt_flags,
Bram Moolenaard7c96872019-06-15 17:12:48 +02002948 saved_oldval, saved_oldval_l,
2949 saved_oldval_g, saved_newval);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002950 vim_free(saved_oldval);
Bram Moolenaard7c96872019-06-15 17:12:48 +02002951 vim_free(saved_oldval_l);
2952 vim_free(saved_oldval_g);
Bram Moolenaar8efa0262017-08-20 15:47:20 +02002953 vim_free(saved_newval);
Bram Moolenaar53744302015-07-17 17:38:22 +02002954#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002955 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002956 return r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002957}
2958
2959/*
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02002960 * Return TRUE if "val" is a valid name: only consists of alphanumeric ASCII
2961 * characters or characters in "allowed".
2962 */
Bram Moolenaare677df82019-09-02 22:31:11 +02002963 int
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02002964valid_name(char_u *val, char *allowed)
2965{
2966 char_u *s;
2967
2968 for (s = val; *s != NUL; ++s)
2969 if (!ASCII_ISALNUM(*s) && vim_strchr((char_u *)allowed, *s) == NULL)
2970 return FALSE;
2971 return TRUE;
2972}
2973
2974/*
Bram Moolenaard0b51382016-11-04 15:23:45 +01002975 * Return TRUE if "val" is a valid 'filetype' name.
2976 * Also used for 'syntax' and 'keymap'.
2977 */
2978 static int
2979valid_filetype(char_u *val)
2980{
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02002981 return valid_name(val, ".-_");
2982}
Bram Moolenaard0b51382016-11-04 15:23:45 +01002983
Bram Moolenaar862f1e12019-04-10 22:33:41 +02002984/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002985 * Handle string options that need some action to perform when changed.
2986 * Returns NULL for success, or an error message for an error.
2987 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002988 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01002989did_set_string_option(
Bram Moolenaar916a8182018-11-25 02:18:29 +01002990 int opt_idx, // index in options[] table
2991 char_u **varp, // pointer to the option variable
2992 int new_value_alloced, // new value was allocated
2993 char_u *oldval, // previous value of the option
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002994 char *errbuf, // buffer for errors, or NULL
Bram Moolenaar916a8182018-11-25 02:18:29 +01002995 int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL
2996 int *value_checked) // value was checked to be save, no
2997 // need to set P_INSECURE
Bram Moolenaar071d4272004-06-13 20:20:40 +00002998{
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01002999 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000 char_u *s, *p;
3001 int did_chartab = FALSE;
3002 char_u **gvarp;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00003003 long_u free_oldval = (options[opt_idx].flags & P_ALLOCED);
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003004#ifdef FEAT_GUI
3005 /* set when changing an option that only requires a redraw in the GUI */
3006 int redraw_gui_only = FALSE;
3007#endif
Bram Moolenaarc3ffc9b2018-06-17 17:32:58 +02003008 int value_changed = FALSE;
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02003009#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
3010 int did_swaptcap = FALSE;
3011#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003012
3013 /* Get the global option to compare with, otherwise we would have to check
3014 * two values for all local options. */
3015 gvarp = (char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
3016
3017 /* Disallow changing some options from secure mode */
3018 if ((secure
3019#ifdef HAVE_SANDBOX
3020 || sandbox != 0
3021#endif
3022 ) && (options[opt_idx].flags & P_SECURE))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003023 errmsg = e_secure;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003024
Bram Moolenaar916a8182018-11-25 02:18:29 +01003025 // Check for a "normal" directory or file name in some options. Disallow a
3026 // path separator (slash and/or backslash), wildcards and characters that
3027 // are often illegal in a file name. Be more permissive if "secure" is off.
Bram Moolenaar7554da42016-11-25 22:04:13 +01003028 else if (((options[opt_idx].flags & P_NFNAME)
Bram Moolenaar0945eaf2016-11-29 22:10:48 +01003029 && vim_strpbrk(*varp, (char_u *)(secure
3030 ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
Bram Moolenaar7554da42016-11-25 22:04:13 +01003031 || ((options[opt_idx].flags & P_NDNAME)
3032 && vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003033 errmsg = e_invarg;
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003034
Bram Moolenaar071d4272004-06-13 20:20:40 +00003035 /* 'term' */
3036 else if (varp == &T_NAME)
3037 {
3038 if (T_NAME[0] == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003039 errmsg = N_("E529: Cannot set 'term' to empty string");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040#ifdef FEAT_GUI
3041 if (gui.in_use)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003042 errmsg = N_("E530: Cannot change term in GUI");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003043 else if (term_is_gui(T_NAME))
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003044 errmsg = N_("E531: Use \":gui\" to start the GUI");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045#endif
3046 else if (set_termname(T_NAME) == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003047 errmsg = N_("E522: Not found in termcap");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003048 else
Bram Moolenaar67391142017-02-19 21:07:04 +01003049 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003050 /* Screen colors may have changed. */
3051 redraw_later_clear();
Bram Moolenaar67391142017-02-19 21:07:04 +01003052
3053 /* Both 'term' and 'ttytype' point to T_NAME, only set the
3054 * P_ALLOCED flag on 'term'. */
3055 opt_idx = findoption((char_u *)"term");
Bram Moolenaar354796c2017-02-23 17:18:37 +01003056 free_oldval = (options[opt_idx].flags & P_ALLOCED);
Bram Moolenaar67391142017-02-19 21:07:04 +01003057 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003058 }
3059
3060 /* 'backupcopy' */
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003061 else if (gvarp == &p_bkc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003062 {
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02003063 char_u *bkc = p_bkc;
3064 unsigned int *flags = &bkc_flags;
3065
3066 if (opt_flags & OPT_LOCAL)
3067 {
3068 bkc = curbuf->b_p_bkc;
3069 flags = &curbuf->b_bkc_flags;
3070 }
3071
Bram Moolenaar84d17a62014-09-29 17:15:18 +02003072 if ((opt_flags & OPT_LOCAL) && *bkc == NUL)
3073 /* make the local value empty: use the global value */
3074 *flags = 0;
3075 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076 {
Bram Moolenaar84d17a62014-09-29 17:15:18 +02003077 if (opt_strings_flags(bkc, p_bkc_values, flags, TRUE) != OK)
3078 errmsg = e_invarg;
3079 if ((((int)*flags & BKC_AUTO) != 0)
3080 + (((int)*flags & BKC_YES) != 0)
3081 + (((int)*flags & BKC_NO) != 0) != 1)
3082 {
3083 /* Must have exactly one of "auto", "yes" and "no". */
3084 (void)opt_strings_flags(oldval, p_bkc_values, flags, TRUE);
3085 errmsg = e_invarg;
3086 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087 }
3088 }
3089
3090 /* 'backupext' and 'patchmode' */
3091 else if (varp == &p_bex || varp == &p_pm)
3092 {
3093 if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex,
3094 *p_pm == '.' ? p_pm + 1 : p_pm) == 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003095 errmsg = N_("E589: 'backupext' and 'patchmode' are equal");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003096 }
Bram Moolenaar597a4222014-06-25 14:39:50 +02003097#ifdef FEAT_LINEBREAK
3098 /* 'breakindentopt' */
3099 else if (varp == &curwin->w_p_briopt)
3100 {
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02003101 if (briopt_check(curwin) == FAIL)
Bram Moolenaar597a4222014-06-25 14:39:50 +02003102 errmsg = e_invarg;
3103 }
3104#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003105
3106 /*
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +01003107 * 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
Bram Moolenaar071d4272004-06-13 20:20:40 +00003108 * If the new option is invalid, use old value. 'lisp' option: refill
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +01003109 * g_chartab[] for '-' char
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110 */
3111 else if ( varp == &p_isi
3112 || varp == &(curbuf->b_p_isk)
3113 || varp == &p_isp
3114 || varp == &p_isf)
3115 {
3116 if (init_chartab() == FAIL)
3117 {
3118 did_chartab = TRUE; /* need to restore it below */
3119 errmsg = e_invarg; /* error in value */
3120 }
3121 }
3122
3123 /* 'helpfile' */
3124 else if (varp == &p_hf)
3125 {
3126 /* May compute new values for $VIM and $VIMRUNTIME */
3127 if (didset_vim)
3128 {
3129 vim_setenv((char_u *)"VIM", (char_u *)"");
3130 didset_vim = FALSE;
3131 }
3132 if (didset_vimruntime)
3133 {
3134 vim_setenv((char_u *)"VIMRUNTIME", (char_u *)"");
3135 didset_vimruntime = FALSE;
3136 }
3137 }
3138
Bram Moolenaar1a384422010-07-14 19:53:30 +02003139#ifdef FEAT_SYN_HL
Bram Moolenaar410e98a2019-09-09 22:05:49 +02003140 /* 'cursorlineopt' */
3141 else if (varp == &curwin->w_p_culopt
3142 || gvarp == &curwin->w_allbuf_opt.wo_culopt)
3143 {
Bram Moolenaar017ba072019-09-14 21:01:23 +02003144 if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK)
Bram Moolenaar410e98a2019-09-09 22:05:49 +02003145 errmsg = e_invarg;
3146 }
3147
Bram Moolenaar1a384422010-07-14 19:53:30 +02003148 /* 'colorcolumn' */
3149 else if (varp == &curwin->w_p_cc)
3150 errmsg = check_colorcolumn(curwin);
3151#endif
3152
Bram Moolenaar071d4272004-06-13 20:20:40 +00003153#ifdef FEAT_MULTI_LANG
3154 /* 'helplang' */
3155 else if (varp == &p_hlg)
3156 {
3157 /* Check for "", "ab", "ab,cd", etc. */
3158 for (s = p_hlg; *s != NUL; s += 3)
3159 {
3160 if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL))
3161 {
3162 errmsg = e_invarg;
3163 break;
3164 }
3165 if (s[2] == NUL)
3166 break;
3167 }
3168 }
3169#endif
3170
3171 /* 'highlight' */
3172 else if (varp == &p_hl)
3173 {
3174 if (highlight_changed() == FAIL)
3175 errmsg = e_invarg; /* invalid flags */
3176 }
3177
3178 /* 'nrformats' */
3179 else if (gvarp == &p_nf)
3180 {
3181 if (check_opt_strings(*varp, p_nf_values, TRUE) != OK)
3182 errmsg = e_invarg;
3183 }
3184
3185#ifdef FEAT_SESSION
3186 /* 'sessionoptions' */
3187 else if (varp == &p_ssop)
3188 {
3189 if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK)
3190 errmsg = e_invarg;
3191 if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR))
3192 {
3193 /* Don't allow both "sesdir" and "curdir". */
3194 (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, TRUE);
3195 errmsg = e_invarg;
3196 }
3197 }
3198 /* 'viewoptions' */
3199 else if (varp == &p_vop)
3200 {
3201 if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE) != OK)
3202 errmsg = e_invarg;
3203 }
3204#endif
3205
3206 /* 'scrollopt' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003207 else if (varp == &p_sbo)
3208 {
3209 if (check_opt_strings(p_sbo, p_scbopt_values, TRUE) != OK)
3210 errmsg = e_invarg;
3211 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212
3213 /* 'ambiwidth' */
Bram Moolenaar3848e002016-03-19 18:42:29 +01003214 else if (varp == &p_ambw || varp == &p_emoji)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003215 {
3216 if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK)
3217 errmsg = e_invarg;
Bram Moolenaar5c3bd0a2010-08-04 20:55:44 +02003218 else if (set_chars_option(&p_lcs) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003219 errmsg = _("E834: Conflicts with value of 'listchars'");
Bram Moolenaar5c3bd0a2010-08-04 20:55:44 +02003220 else if (set_chars_option(&p_fcs) != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003221 errmsg = _("E835: Conflicts with value of 'fillchars'");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223
3224 /* 'background' */
3225 else if (varp == &p_bg)
3226 {
3227 if (check_opt_strings(p_bg, p_bg_values, FALSE) == OK)
3228 {
3229#ifdef FEAT_EVAL
3230 int dark = (*p_bg == 'd');
3231#endif
3232
3233 init_highlight(FALSE, FALSE);
3234
3235#ifdef FEAT_EVAL
3236 if (dark != (*p_bg == 'd')
3237 && get_var_value((char_u *)"g:colors_name") != NULL)
3238 {
3239 /* The color scheme must have set 'background' back to another
3240 * value, that's not what we want here. Disable the color
3241 * scheme and set the colors again. */
Bram Moolenaar2ce06f62005-01-31 19:19:04 +00003242 do_unlet((char_u *)"g:colors_name", TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003243 free_string_option(p_bg);
3244 p_bg = vim_strsave((char_u *)(dark ? "dark" : "light"));
3245 check_string_option(&p_bg);
3246 init_highlight(FALSE, FALSE);
3247 }
3248#endif
3249 }
3250 else
3251 errmsg = e_invarg;
3252 }
3253
3254 /* 'wildmode' */
3255 else if (varp == &p_wim)
3256 {
3257 if (check_opt_wim() == FAIL)
3258 errmsg = e_invarg;
3259 }
3260
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00003261 /* 'wildoptions' */
3262 else if (varp == &p_wop)
3263 {
3264 if (check_opt_strings(p_wop, p_wop_values, TRUE) != OK)
3265 errmsg = e_invarg;
3266 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00003267
Bram Moolenaar071d4272004-06-13 20:20:40 +00003268#ifdef FEAT_WAK
3269 /* 'winaltkeys' */
3270 else if (varp == &p_wak)
3271 {
3272 if (*p_wak == NUL
3273 || check_opt_strings(p_wak, p_wak_values, FALSE) != OK)
3274 errmsg = e_invarg;
3275# ifdef FEAT_MENU
3276# ifdef FEAT_GUI_MOTIF
3277 else if (gui.in_use)
3278 gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
3279# else
3280# ifdef FEAT_GUI_GTK
3281 else if (gui.in_use)
3282 gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm');
3283# endif
3284# endif
3285# endif
3286 }
3287#endif
3288
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 /* 'eventignore' */
3290 else if (varp == &p_ei)
3291 {
3292 if (check_ei() == FAIL)
3293 errmsg = e_invarg;
3294 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003295
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01003296 /* 'encoding', 'fileencoding', 'termencoding' and 'makeencoding' */
3297 else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
3298 || gvarp == &p_menc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003299 {
3300 if (gvarp == &p_fenc)
3301 {
Bram Moolenaarf2f70252008-02-13 17:36:06 +00003302 if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003303 errmsg = e_modifiable;
3304 else if (vim_strchr(*varp, ',') != NULL)
3305 /* No comma allowed in 'fileencoding'; catches confusing it
3306 * with 'fileencodings'. */
3307 errmsg = e_invarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308 else
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003309 {
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003310#ifdef FEAT_TITLE
Bram Moolenaar071d4272004-06-13 20:20:40 +00003311 /* May show a "+" in the title now. */
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00003312 redraw_titles();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003313#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003314 /* Add 'fileencoding' to the swap file. */
3315 ml_setflags(curbuf);
3316 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003317 }
3318 if (errmsg == NULL)
3319 {
3320 /* canonize the value, so that STRCMP() can be used on it */
3321 p = enc_canonize(*varp);
3322 if (p != NULL)
3323 {
3324 vim_free(*varp);
3325 *varp = p;
3326 }
3327 if (varp == &p_enc)
3328 {
3329 errmsg = mb_init();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003330#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00003331 redraw_titles();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003332#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003333 }
3334 }
3335
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003336#if defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337 if (errmsg == NULL && varp == &p_tenc && gui.in_use)
3338 {
3339 /* GTK+ 2 uses only a single encoding, and that is UTF-8. */
3340 if (STRCMP(p_tenc, "utf-8") != 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003341 errmsg = N_("E617: Cannot be changed in the GTK+ 2 GUI");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003342 }
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003343#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003344
3345 if (errmsg == NULL)
3346 {
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003347#ifdef FEAT_KEYMAP
Bram Moolenaar071d4272004-06-13 20:20:40 +00003348 /* When 'keymap' is used and 'encoding' changes, reload the keymap
3349 * (with another encoding). */
3350 if (varp == &p_enc && *curbuf->b_p_keymap != NUL)
3351 (void)keymap_init();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003352#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003353
3354 /* When 'termencoding' is not empty and 'encoding' changes or when
3355 * 'termencoding' changes, need to setup for keyboard input and
3356 * display output conversion. */
3357 if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc))
3358 {
Bram Moolenaar17471e82017-11-26 23:47:18 +01003359 if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL
3360 || convert_setup(&output_conv, p_enc, p_tenc) == FAIL)
3361 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003362 semsg(_("E950: Cannot convert between %s and %s"),
Bram Moolenaar17471e82017-11-26 23:47:18 +01003363 p_tenc, p_enc);
3364 errmsg = e_invarg;
3365 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003366 }
Bram Moolenaar05159a02005-02-26 23:04:13 +00003367
Bram Moolenaar4f974752019-02-17 17:44:42 +01003368#if defined(MSWIN)
Bram Moolenaar05159a02005-02-26 23:04:13 +00003369 /* $HOME may have characters in active code page. */
3370 if (varp == &p_enc)
3371 init_homedir();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003372#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003373 }
3374 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003375
3376#if defined(FEAT_POSTSCRIPT)
3377 else if (varp == &p_penc)
3378 {
3379 /* Canonize printencoding if VIM standard one */
3380 p = enc_canonize(p_penc);
3381 if (p != NULL)
3382 {
3383 vim_free(p_penc);
3384 p_penc = p;
3385 }
3386 else
3387 {
3388 /* Ensure lower case and '-' for '_' */
3389 for (s = p_penc; *s != NUL; s++)
3390 {
3391 if (*s == '_')
3392 *s = '-';
3393 else
3394 *s = TOLOWER_ASC(*s);
3395 }
3396 }
3397 }
3398#endif
3399
Bram Moolenaar9372a112005-12-06 19:59:18 +00003400#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003401 else if (varp == &p_imak)
3402 {
Bram Moolenaar86e57922017-04-23 18:44:26 +02003403 if (!im_xim_isvalid_imactivate())
Bram Moolenaar071d4272004-06-13 20:20:40 +00003404 errmsg = e_invarg;
3405 }
3406#endif
3407
3408#ifdef FEAT_KEYMAP
3409 else if (varp == &curbuf->b_p_keymap)
3410 {
Bram Moolenaard0b51382016-11-04 15:23:45 +01003411 if (!valid_filetype(*varp))
3412 errmsg = e_invarg;
3413 else
Bram Moolenaar916a8182018-11-25 02:18:29 +01003414 {
3415 int secure_save = secure;
3416
3417 // Reset the secure flag, since the value of 'keymap' has
3418 // been checked to be safe.
3419 secure = 0;
3420
3421 // load or unload key mapping tables
Bram Moolenaard0b51382016-11-04 15:23:45 +01003422 errmsg = keymap_init();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003423
Bram Moolenaar916a8182018-11-25 02:18:29 +01003424 secure = secure_save;
3425
3426 // Since we check the value, there is no need to set P_INSECURE,
3427 // even when the value comes from a modeline.
3428 *value_checked = TRUE;
3429 }
3430
Bram Moolenaarfab06232009-03-04 03:13:35 +00003431 if (errmsg == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003432 {
Bram Moolenaarfab06232009-03-04 03:13:35 +00003433 if (*curbuf->b_p_keymap != NUL)
3434 {
3435 /* Installed a new keymap, switch on using it. */
3436 curbuf->b_p_iminsert = B_IMODE_LMAP;
3437 if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT)
3438 curbuf->b_p_imsearch = B_IMODE_LMAP;
3439 }
3440 else
3441 {
3442 /* Cleared the keymap, may reset 'iminsert' and 'imsearch'. */
3443 if (curbuf->b_p_iminsert == B_IMODE_LMAP)
3444 curbuf->b_p_iminsert = B_IMODE_NONE;
3445 if (curbuf->b_p_imsearch == B_IMODE_LMAP)
3446 curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
3447 }
3448 if ((opt_flags & OPT_LOCAL) == 0)
3449 {
3450 set_iminsert_global();
3451 set_imsearch_global();
3452 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003453 status_redraw_curbuf();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003454 }
3455 }
3456#endif
3457
3458 /* 'fileformat' */
3459 else if (gvarp == &p_ff)
3460 {
3461 if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL))
3462 errmsg = e_modifiable;
3463 else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK)
3464 errmsg = e_invarg;
3465 else
3466 {
3467 /* may also change 'textmode' */
3468 if (get_fileformat(curbuf) == EOL_DOS)
3469 curbuf->b_p_tx = TRUE;
3470 else
3471 curbuf->b_p_tx = FALSE;
3472#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00003473 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003474#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003475 /* update flag in swap file */
3476 ml_setflags(curbuf);
Bram Moolenaar0413d482010-02-11 17:02:11 +01003477 /* Redraw needed when switching to/from "mac": a CR in the text
3478 * will be displayed differently. */
3479 if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm')
3480 redraw_curbuf_later(NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003481 }
3482 }
3483
3484 /* 'fileformats' */
3485 else if (varp == &p_ffs)
3486 {
3487 if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK)
3488 errmsg = e_invarg;
3489 else
3490 {
3491 /* also change 'textauto' */
3492 if (*p_ffs == NUL)
3493 p_ta = FALSE;
3494 else
3495 p_ta = TRUE;
3496 }
3497 }
3498
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003499#if defined(FEAT_CRYPT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003500 /* 'cryptkey' */
3501 else if (gvarp == &p_key)
3502 {
Bram Moolenaard7663c22019-08-06 21:59:57 +02003503 // Make sure the ":set" command doesn't show the new value in the
3504 // history.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003505 remove_key_from_history();
Bram Moolenaard7663c22019-08-06 21:59:57 +02003506
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02003507 if (STRCMP(curbuf->b_p_key, oldval) != 0)
3508 /* Need to update the swapfile. */
Bram Moolenaarbc563362015-06-09 18:35:25 +02003509 ml_set_crypt_key(curbuf, oldval,
3510 *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm);
Bram Moolenaar49771f42010-07-20 17:32:38 +02003511 }
3512
3513 else if (gvarp == &p_cm)
3514 {
3515 if (opt_flags & OPT_LOCAL)
3516 p = curbuf->b_p_cm;
3517 else
3518 p = p_cm;
3519 if (check_opt_strings(p, p_cm_values, TRUE) != OK)
3520 errmsg = e_invarg;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02003521 else if (crypt_self_test() == FAIL)
Bram Moolenaar49771f42010-07-20 17:32:38 +02003522 errmsg = e_invarg;
3523 else
3524 {
3525 /* When setting the global value to empty, make it "zip". */
3526 if (*p_cm == NUL)
3527 {
3528 if (new_value_alloced)
3529 free_string_option(p_cm);
3530 p_cm = vim_strsave((char_u *)"zip");
3531 new_value_alloced = TRUE;
3532 }
Bram Moolenaar2be79502014-08-13 21:58:28 +02003533 /* When using ":set cm=name" the local value is going to be empty.
3534 * Do that here, otherwise the crypt functions will still use the
3535 * local value. */
3536 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
3537 {
3538 free_string_option(curbuf->b_p_cm);
3539 curbuf->b_p_cm = empty_option;
3540 }
Bram Moolenaar49771f42010-07-20 17:32:38 +02003541
3542 /* Need to update the swapfile when the effective method changed.
3543 * Set "s" to the effective old value, "p" to the effective new
3544 * method and compare. */
3545 if ((opt_flags & OPT_LOCAL) && *oldval == NUL)
3546 s = p_cm; /* was previously using the global value */
3547 else
3548 s = oldval;
3549 if (*curbuf->b_p_cm == NUL)
3550 p = p_cm; /* is now using the global value */
3551 else
3552 p = curbuf->b_p_cm;
3553 if (STRCMP(s, p) != 0)
Bram Moolenaarbc563362015-06-09 18:35:25 +02003554 ml_set_crypt_key(curbuf, curbuf->b_p_key, s);
Bram Moolenaar49771f42010-07-20 17:32:38 +02003555
3556 /* If the global value changes need to update the swapfile for all
3557 * buffers using that value. */
3558 if ((opt_flags & OPT_GLOBAL) && STRCMP(p_cm, oldval) != 0)
3559 {
3560 buf_T *buf;
3561
Bram Moolenaar29323592016-07-24 22:04:11 +02003562 FOR_ALL_BUFFERS(buf)
Bram Moolenaar49771f42010-07-20 17:32:38 +02003563 if (buf != curbuf && *buf->b_p_cm == NUL)
Bram Moolenaarbc563362015-06-09 18:35:25 +02003564 ml_set_crypt_key(buf, buf->b_p_key, oldval);
Bram Moolenaar49771f42010-07-20 17:32:38 +02003565 }
3566 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003567 }
3568#endif
3569
3570 /* 'matchpairs' */
3571 else if (gvarp == &p_mps)
3572 {
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003573 if (has_mbyte)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003574 {
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003575 for (p = *varp; *p != NUL; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003576 {
Bram Moolenaar09365022013-01-17 17:37:35 +01003577 int x2 = -1;
3578 int x3 = -1;
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003579
3580 if (*p != NUL)
3581 p += mb_ptr2len(p);
3582 if (*p != NUL)
3583 x2 = *p++;
3584 if (*p != NUL)
3585 {
3586 x3 = mb_ptr2char(p);
3587 p += mb_ptr2len(p);
3588 }
Bram Moolenaar09365022013-01-17 17:37:35 +01003589 if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ','))
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003590 {
3591 errmsg = e_invarg;
3592 break;
3593 }
3594 if (*p == NUL)
3595 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003596 }
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003597 }
3598 else
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01003599 {
3600 /* Check for "x:y,x:y" */
3601 for (p = *varp; *p != NUL; p += 4)
3602 {
3603 if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ','))
3604 {
3605 errmsg = e_invarg;
3606 break;
3607 }
3608 if (p[3] == NUL)
3609 break;
3610 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003611 }
3612 }
3613
3614#ifdef FEAT_COMMENTS
3615 /* 'comments' */
3616 else if (gvarp == &p_com)
3617 {
3618 for (s = *varp; *s; )
3619 {
3620 while (*s && *s != ':')
3621 {
3622 if (vim_strchr((char_u *)COM_ALL, *s) == NULL
3623 && !VIM_ISDIGIT(*s) && *s != '-')
3624 {
3625 errmsg = illegal_char(errbuf, *s);
3626 break;
3627 }
3628 ++s;
3629 }
3630 if (*s++ == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003631 errmsg = N_("E524: Missing colon");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 else if (*s == ',' || *s == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003633 errmsg = N_("E525: Zero length string");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003634 if (errmsg != NULL)
3635 break;
3636 while (*s && *s != ',')
3637 {
3638 if (*s == '\\' && s[1] != NUL)
3639 ++s;
3640 ++s;
3641 }
3642 s = skip_to_option_part(s);
3643 }
3644 }
3645#endif
3646
3647 /* 'listchars' */
3648 else if (varp == &p_lcs)
3649 {
3650 errmsg = set_chars_option(varp);
3651 }
3652
Bram Moolenaar071d4272004-06-13 20:20:40 +00003653 /* 'fillchars' */
3654 else if (varp == &p_fcs)
3655 {
3656 errmsg = set_chars_option(varp);
3657 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003658
3659#ifdef FEAT_CMDWIN
3660 /* 'cedit' */
3661 else if (varp == &p_cedit)
3662 {
3663 errmsg = check_cedit();
3664 }
3665#endif
3666
Bram Moolenaar54ee7752005-05-31 22:22:17 +00003667 /* 'verbosefile' */
3668 else if (varp == &p_vfile)
3669 {
3670 verbose_stop();
3671 if (*p_vfile != NUL && verbose_open() == FAIL)
3672 errmsg = e_invarg;
3673 }
3674
Bram Moolenaar071d4272004-06-13 20:20:40 +00003675#ifdef FEAT_VIMINFO
3676 /* 'viminfo' */
3677 else if (varp == &p_viminfo)
3678 {
3679 for (s = p_viminfo; *s;)
3680 {
3681 /* Check it's a valid character */
3682 if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL)
3683 {
3684 errmsg = illegal_char(errbuf, *s);
3685 break;
3686 }
3687 if (*s == 'n') /* name is always last one */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003688 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003689 else if (*s == 'r') /* skip until next ',' */
3690 {
3691 while (*++s && *s != ',')
3692 ;
3693 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00003694 else if (*s == '%')
3695 {
3696 /* optional number */
3697 while (vim_isdigit(*++s))
3698 ;
3699 }
3700 else if (*s == '!' || *s == 'h' || *s == 'c')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003701 ++s; /* no extra chars */
3702 else /* must have a number */
3703 {
3704 while (vim_isdigit(*++s))
3705 ;
3706
3707 if (!VIM_ISDIGIT(*(s - 1)))
3708 {
3709 if (errbuf != NULL)
3710 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003711 sprintf(errbuf, _("E526: Missing number after <%s>"),
Bram Moolenaar071d4272004-06-13 20:20:40 +00003712 transchar_byte(*(s - 1)));
3713 errmsg = errbuf;
3714 }
3715 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003716 errmsg = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00003717 break;
3718 }
3719 }
3720 if (*s == ',')
3721 ++s;
3722 else if (*s)
3723 {
3724 if (errbuf != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003725 errmsg = N_("E527: Missing comma");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003727 errmsg = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 break;
3729 }
3730 }
3731 if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003732 errmsg = N_("E528: Must specify a ' value");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003733 }
3734#endif /* FEAT_VIMINFO */
3735
3736 /* terminal options */
3737 else if (istermoption(&options[opt_idx]) && full_screen)
3738 {
3739 /* ":set t_Co=0" and ":set t_Co=1" do ":set t_Co=" */
3740 if (varp == &T_CCO)
3741 {
Bram Moolenaarc84e8952009-03-18 13:21:18 +00003742 int colors = atoi((char *)T_CCO);
3743
3744 /* Only reinitialize colors if t_Co value has really changed to
3745 * avoid expensive reload of colorscheme if t_Co is set to the
3746 * same value multiple times. */
3747 if (colors != t_colors)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003748 {
Bram Moolenaarc84e8952009-03-18 13:21:18 +00003749 t_colors = colors;
3750 if (t_colors <= 1)
3751 {
3752 if (new_value_alloced)
3753 vim_free(T_CCO);
3754 T_CCO = empty_option;
3755 }
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02003756#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
3757 if (is_term_win32())
3758 {
3759 swap_tcap();
3760 did_swaptcap = TRUE;
3761 }
3762#endif
Bram Moolenaarc84e8952009-03-18 13:21:18 +00003763 /* We now have a different color setup, initialize it again. */
3764 init_highlight(TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003766 }
3767 ttest(FALSE);
3768 if (varp == &T_ME)
3769 {
3770 out_str(T_ME);
3771 redraw_later(CLEAR);
Bram Moolenaarafde13b2019-04-28 19:46:49 +02003772#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 /* Since t_me has been set, this probably means that the user
3774 * wants to use this as default colors. Need to reset default
3775 * background/foreground colors. */
Bram Moolenaarafde13b2019-04-28 19:46:49 +02003776# ifdef VIMDLL
3777 if (!gui.in_use && !gui.starting)
3778# endif
3779 mch_set_normal_colors();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003780#endif
3781 }
Bram Moolenaard9c60642017-01-27 20:03:18 +01003782 if (varp == &T_BE && termcap_active)
3783 {
3784 if (*T_BE == NUL)
3785 /* When clearing t_BE we assume the user no longer wants
3786 * bracketed paste, thus disable it by writing t_BD. */
3787 out_str(T_BD);
3788 else
3789 out_str(T_BE);
3790 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003791 }
3792
3793#ifdef FEAT_LINEBREAK
3794 /* 'showbreak' */
3795 else if (varp == &p_sbr)
3796 {
3797 for (s = p_sbr; *s; )
3798 {
3799 if (ptr2cells(s) != 1)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003800 errmsg = N_("E595: contains unprintable or wide character");
Bram Moolenaar91acfff2017-03-12 19:22:36 +01003801 MB_PTR_ADV(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003802 }
3803 }
3804#endif
3805
3806#ifdef FEAT_GUI
3807 /* 'guifont' */
3808 else if (varp == &p_guifont)
3809 {
3810 if (gui.in_use)
3811 {
3812 p = p_guifont;
Bram Moolenaar9372a112005-12-06 19:59:18 +00003813# if defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003814 /*
3815 * Put up a font dialog and let the user select a new value.
3816 * If this is cancelled go back to the old value but don't
3817 * give an error message.
3818 */
3819 if (STRCMP(p, "*") == 0)
3820 {
3821 p = gui_mch_font_dialog(oldval);
3822
3823 if (new_value_alloced)
3824 free_string_option(p_guifont);
3825
3826 p_guifont = (p != NULL) ? p : vim_strsave(oldval);
3827 new_value_alloced = TRUE;
3828 }
3829# endif
3830 if (p != NULL && gui_init_font(p_guifont, FALSE) != OK)
3831 {
3832# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON)
3833 if (STRCMP(p_guifont, "*") == 0)
3834 {
3835 /* Dialog was cancelled: Keep the old value without giving
3836 * an error message. */
3837 if (new_value_alloced)
3838 free_string_option(p_guifont);
3839 p_guifont = vim_strsave(oldval);
3840 new_value_alloced = TRUE;
3841 }
3842 else
3843# endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003844 errmsg = N_("E596: Invalid font(s)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003845 }
3846 }
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003847 redraw_gui_only = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003848 }
3849# ifdef FEAT_XFONTSET
3850 else if (varp == &p_guifontset)
3851 {
3852 if (STRCMP(p_guifontset, "*") == 0)
Bram Moolenaarb1443b42019-01-13 23:51:14 +01003853 errmsg = N_("E597: can't select fontset");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003854 else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK)
Bram Moolenaarb1443b42019-01-13 23:51:14 +01003855 errmsg = N_("E598: Invalid fontset");
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003856 redraw_gui_only = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003857 }
3858# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003859 else if (varp == &p_guifontwide)
3860 {
3861 if (STRCMP(p_guifontwide, "*") == 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003862 errmsg = N_("E533: can't select wide font");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003863 else if (gui_get_wide_font() == FAIL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003864 errmsg = N_("E534: Invalid wide font");
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003865 redraw_gui_only = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003866 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003867#endif
3868
3869#ifdef CURSOR_SHAPE
3870 /* 'guicursor' */
3871 else if (varp == &p_guicursor)
3872 errmsg = parse_shape_opt(SHAPE_CURSOR);
3873#endif
3874
3875#ifdef FEAT_MOUSESHAPE
3876 /* 'mouseshape' */
3877 else if (varp == &p_mouseshape)
3878 {
3879 errmsg = parse_shape_opt(SHAPE_MOUSE);
3880 update_mouseshape(-1);
3881 }
3882#endif
3883
3884#ifdef FEAT_PRINTER
3885 else if (varp == &p_popt)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003886 errmsg = parse_printoptions();
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01003887# if defined(FEAT_POSTSCRIPT)
Bram Moolenaar8299df92004-07-10 09:47:34 +00003888 else if (varp == &p_pmfn)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003889 errmsg = parse_printmbfont();
Bram Moolenaar8299df92004-07-10 09:47:34 +00003890# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003891#endif
3892
3893#ifdef FEAT_LANGMAP
3894 /* 'langmap' */
3895 else if (varp == &p_langmap)
3896 langmap_set();
3897#endif
3898
3899#ifdef FEAT_LINEBREAK
3900 /* 'breakat' */
3901 else if (varp == &p_breakat)
3902 fill_breakat_flags();
3903#endif
3904
3905#ifdef FEAT_TITLE
3906 /* 'titlestring' and 'iconstring' */
3907 else if (varp == &p_titlestring || varp == &p_iconstring)
3908 {
3909# ifdef FEAT_STL_OPT
3910 int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
3911
3912 /* NULL => statusline syntax */
3913 if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL)
3914 stl_syntax |= flagval;
3915 else
3916 stl_syntax &= ~flagval;
3917# endif
Bram Moolenaar84a93082018-06-16 22:58:15 +02003918 did_set_title();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003919 }
3920#endif
3921
3922#ifdef FEAT_GUI
3923 /* 'guioptions' */
3924 else if (varp == &p_go)
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003925 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003926 gui_init_which_components(oldval);
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003927 redraw_gui_only = TRUE;
3928 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929#endif
3930
Bram Moolenaar5c8837f2006-02-25 21:52:33 +00003931#if defined(FEAT_GUI_TABLINE)
3932 /* 'guitablabel' */
3933 else if (varp == &p_gtl)
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003934 {
Bram Moolenaar18144c82006-04-12 21:52:12 +00003935 redraw_tabline = TRUE;
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00003936 redraw_gui_only = TRUE;
3937 }
3938 /* 'guitabtooltip' */
3939 else if (varp == &p_gtt)
3940 {
3941 redraw_gui_only = TRUE;
3942 }
Bram Moolenaar5c8837f2006-02-25 21:52:33 +00003943#endif
3944
Bram Moolenaar071d4272004-06-13 20:20:40 +00003945#if defined(FEAT_MOUSE_TTY) && (defined(UNIX) || defined(VMS))
3946 /* 'ttymouse' */
3947 else if (varp == &p_ttym)
3948 {
Bram Moolenaarf1f8bc52005-03-07 23:20:08 +00003949 /* Switch the mouse off before changing the escape sequences used for
3950 * that. */
3951 mch_setmouse(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003952 if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK)
3953 errmsg = e_invarg;
3954 else
3955 check_mouse_termcode();
Bram Moolenaar6bb68362005-03-22 23:03:44 +00003956 if (termcap_active)
3957 setmouse(); /* may switch it on again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 }
3959#endif
3960
Bram Moolenaar071d4272004-06-13 20:20:40 +00003961 /* 'selection' */
3962 else if (varp == &p_sel)
3963 {
3964 if (*p_sel == NUL
3965 || check_opt_strings(p_sel, p_sel_values, FALSE) != OK)
3966 errmsg = e_invarg;
3967 }
3968
3969 /* 'selectmode' */
3970 else if (varp == &p_slm)
3971 {
3972 if (check_opt_strings(p_slm, p_slm_values, TRUE) != OK)
3973 errmsg = e_invarg;
3974 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003975
3976#ifdef FEAT_BROWSE
3977 /* 'browsedir' */
3978 else if (varp == &p_bsdir)
3979 {
3980 if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK
3981 && !mch_isdir(p_bsdir))
3982 errmsg = e_invarg;
3983 }
3984#endif
3985
Bram Moolenaar071d4272004-06-13 20:20:40 +00003986 /* 'keymodel' */
3987 else if (varp == &p_km)
3988 {
3989 if (check_opt_strings(p_km, p_km_values, TRUE) != OK)
3990 errmsg = e_invarg;
3991 else
3992 {
3993 km_stopsel = (vim_strchr(p_km, 'o') != NULL);
3994 km_startsel = (vim_strchr(p_km, 'a') != NULL);
3995 }
3996 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003997
3998 /* 'mousemodel' */
3999 else if (varp == &p_mousem)
4000 {
4001 if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK)
4002 errmsg = e_invarg;
4003#if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002)
4004 else if (*p_mousem != *oldval)
4005 /* Changed from "extend" to "popup" or "popup_setpos" or vv: need
4006 * to create or delete the popup menus. */
4007 gui_motif_update_mousemodel(root_menu);
4008#endif
4009 }
4010
4011 /* 'switchbuf' */
4012 else if (varp == &p_swb)
4013 {
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00004014 if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE) != OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015 errmsg = e_invarg;
4016 }
4017
4018 /* 'debug' */
4019 else if (varp == &p_debug)
4020 {
Bram Moolenaar57657d82006-04-21 22:12:41 +00004021 if (check_opt_strings(p_debug, p_debug_values, TRUE) != OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004022 errmsg = e_invarg;
4023 }
4024
4025 /* 'display' */
4026 else if (varp == &p_dy)
4027 {
4028 if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK)
4029 errmsg = e_invarg;
4030 else
4031 (void)init_chartab();
4032
4033 }
4034
Bram Moolenaar071d4272004-06-13 20:20:40 +00004035 /* 'eadirection' */
4036 else if (varp == &p_ead)
4037 {
4038 if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
4039 errmsg = e_invarg;
4040 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004041
4042#ifdef FEAT_CLIPBOARD
4043 /* 'clipboard' */
4044 else if (varp == &p_cb)
4045 errmsg = check_clipboard_option();
4046#endif
4047
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00004048#ifdef FEAT_SPELL
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004049 /* When 'spelllang' or 'spellfile' is set and there is a window for this
4050 * buffer in which 'spell' is set load the wordlists. */
Bram Moolenaar2683c8e2014-11-19 19:33:16 +01004051 else if (varp == &(curwin->w_s->b_p_spl)
4052 || varp == &(curwin->w_s->b_p_spf))
Bram Moolenaar217ad922005-03-20 22:37:15 +00004053 {
Bram Moolenaar862f1e12019-04-10 22:33:41 +02004054 int is_spellfile = varp == &(curwin->w_s->b_p_spf);
4055
4056 if ((is_spellfile && !valid_spellfile(*varp))
4057 || (!is_spellfile && !valid_spellang(*varp)))
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02004058 errmsg = e_invarg;
4059 else
Bram Moolenaar862f1e12019-04-10 22:33:41 +02004060 errmsg = did_set_spell_option(is_spellfile);
Bram Moolenaar217ad922005-03-20 22:37:15 +00004061 }
Bram Moolenaar0d9c26d2005-07-02 23:19:16 +00004062 /* When 'spellcapcheck' is set compile the regexp program. */
Bram Moolenaar860cae12010-06-05 23:22:07 +02004063 else if (varp == &(curwin->w_s->b_p_spc))
Bram Moolenaar0d9c26d2005-07-02 23:19:16 +00004064 {
Bram Moolenaar860cae12010-06-05 23:22:07 +02004065 errmsg = compile_cap_prog(curwin->w_s);
Bram Moolenaar0d9c26d2005-07-02 23:19:16 +00004066 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +00004067 /* 'spellsuggest' */
4068 else if (varp == &p_sps)
4069 {
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00004070 if (spell_check_sps() != OK)
Bram Moolenaard857f0e2005-06-21 22:37:39 +00004071 errmsg = e_invarg;
4072 }
Bram Moolenaar8aff23a2005-08-19 20:40:30 +00004073 /* 'mkspellmem' */
4074 else if (varp == &p_msm)
4075 {
4076 if (spell_check_msm() != OK)
4077 errmsg = e_invarg;
4078 }
Bram Moolenaar217ad922005-03-20 22:37:15 +00004079#endif
4080
Bram Moolenaar071d4272004-06-13 20:20:40 +00004081 /* When 'bufhidden' is set, check for valid value. */
4082 else if (gvarp == &p_bh)
4083 {
4084 if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE) != OK)
4085 errmsg = e_invarg;
4086 }
4087
4088 /* When 'buftype' is set, check for valid value. */
4089 else if (gvarp == &p_bt)
4090 {
4091 if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK)
4092 errmsg = e_invarg;
4093 else
4094 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095 if (curwin->w_status_height)
4096 {
4097 curwin->w_redr_status = TRUE;
4098 redraw_later(VALID);
4099 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004100 curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
Bram Moolenaar1f2903c2017-07-23 19:51:01 +02004101#ifdef FEAT_TITLE
Bram Moolenaar5075aad2010-01-27 15:58:13 +01004102 redraw_titles();
Bram Moolenaar1f2903c2017-07-23 19:51:01 +02004103#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004104 }
4105 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004106
4107#ifdef FEAT_STL_OPT
4108 /* 'statusline' or 'rulerformat' */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00004109 else if (gvarp == &p_stl || varp == &p_ruf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004110 {
4111 int wid;
4112
4113 if (varp == &p_ruf) /* reset ru_wid first */
4114 ru_wid = 0;
4115 s = *varp;
4116 if (varp == &p_ruf && *s == '%')
4117 {
4118 /* set ru_wid if 'ruf' starts with "%99(" */
4119 if (*++s == '-') /* ignore a '-' */
4120 s++;
4121 wid = getdigits(&s);
4122 if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL)
4123 ru_wid = wid;
4124 else
4125 errmsg = check_stl_option(p_ruf);
4126 }
Bram Moolenaar3709e7c2006-08-08 14:29:16 +00004127 /* check 'statusline' only if it doesn't start with "%!" */
Bram Moolenaar177d8c62007-09-06 11:33:37 +00004128 else if (varp == &p_ruf || s[0] != '%' || s[1] != '!')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004129 errmsg = check_stl_option(s);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00004130 if (varp == &p_ruf && errmsg == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004131 comp_col();
4132 }
4133#endif
4134
Bram Moolenaar071d4272004-06-13 20:20:40 +00004135 /* check if it is a valid value for 'complete' -- Acevedo */
4136 else if (gvarp == &p_cpt)
4137 {
4138 for (s = *varp; *s;)
4139 {
Bram Moolenaar11b73d62012-06-29 15:51:30 +02004140 while (*s == ',' || *s == ' ')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004141 s++;
4142 if (!*s)
4143 break;
4144 if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL)
4145 {
4146 errmsg = illegal_char(errbuf, *s);
4147 break;
4148 }
4149 if (*++s != NUL && *s != ',' && *s != ' ')
4150 {
4151 if (s[-1] == 'k' || s[-1] == 's')
4152 {
4153 /* skip optional filename after 'k' and 's' */
4154 while (*s && *s != ',' && *s != ' ')
4155 {
Bram Moolenaar226c5342017-02-17 14:53:15 +01004156 if (*s == '\\' && s[1] != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004157 ++s;
4158 ++s;
4159 }
4160 }
4161 else
4162 {
4163 if (errbuf != NULL)
4164 {
4165 sprintf((char *)errbuf,
4166 _("E535: Illegal character after <%c>"),
4167 *--s);
4168 errmsg = errbuf;
4169 }
4170 else
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004171 errmsg = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +00004172 break;
4173 }
4174 }
4175 }
4176 }
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004177
Bram Moolenaarac3150d2019-07-28 16:36:39 +02004178 // 'completeopt'
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004179 else if (varp == &p_cot)
4180 {
4181 if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK)
4182 errmsg = e_invarg;
Bram Moolenaarc0200422016-04-20 12:02:02 +02004183 else
4184 completeopt_was_set();
Bram Moolenaar1c7715d2005-10-03 22:02:18 +00004185 }
Bram Moolenaarac3150d2019-07-28 16:36:39 +02004186
Bram Moolenaare2c453d2019-08-21 14:37:09 +02004187#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarac3150d2019-07-28 16:36:39 +02004188 // 'completeslash'
Bram Moolenaarb78564d2019-07-28 19:24:36 +02004189 else if (gvarp == &p_csl)
Bram Moolenaarac3150d2019-07-28 16:36:39 +02004190 {
Bram Moolenaarb78564d2019-07-28 19:24:36 +02004191 if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK
4192 || check_opt_strings(curbuf->b_p_csl, p_csl_values, FALSE) != OK)
Bram Moolenaarac3150d2019-07-28 16:36:39 +02004193 errmsg = e_invarg;
4194 }
Bram Moolenaare2c453d2019-08-21 14:37:09 +02004195#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004196
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02004197#ifdef FEAT_SIGNS
Bram Moolenaare4b407f2019-07-04 11:59:28 +02004198 // 'signcolumn'
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02004199 else if (varp == &curwin->w_p_scl)
4200 {
4201 if (check_opt_strings(*varp, p_scl_values, FALSE) != OK)
4202 errmsg = e_invarg;
Bram Moolenaare4b407f2019-07-04 11:59:28 +02004203 // When changing the 'signcolumn' to or from 'number', recompute the
4204 // width of the number column if 'number' or 'relativenumber' is set.
4205 if (((*oldval == 'n' && *(oldval + 1) == 'u')
4206 || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u'))
4207 && (curwin->w_p_nu || curwin->w_p_rnu))
4208 curwin->w_nrwidth_line_count = 0;
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02004209 }
4210#endif
4211
Bram Moolenaar071d4272004-06-13 20:20:40 +00004212
Bram Moolenaar4f974752019-02-17 17:44:42 +01004213#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
Bram Moolenaar031cb742016-11-24 21:46:19 +01004214 /* 'toolbar' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215 else if (varp == &p_toolbar)
4216 {
4217 if (opt_strings_flags(p_toolbar, p_toolbar_values,
4218 &toolbar_flags, TRUE) != OK)
4219 errmsg = e_invarg;
4220 else
4221 {
4222 out_flush();
4223 gui_mch_show_toolbar((toolbar_flags &
4224 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
4225 }
4226 }
4227#endif
4228
Bram Moolenaar182c5be2010-06-25 05:37:59 +02004229#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004230 /* 'toolbariconsize': GTK+ 2 only */
4231 else if (varp == &p_tbis)
4232 {
4233 if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK)
4234 errmsg = e_invarg;
4235 else
4236 {
4237 out_flush();
4238 gui_mch_show_toolbar((toolbar_flags &
4239 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0);
4240 }
4241 }
4242#endif
4243
4244 /* 'pastetoggle': translate key codes like in a mapping */
4245 else if (varp == &p_pt)
4246 {
4247 if (*p_pt)
4248 {
Bram Moolenaar9c102382006-05-03 21:26:49 +00004249 (void)replace_termcodes(p_pt, &p, TRUE, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004250 if (p != NULL)
4251 {
4252 if (new_value_alloced)
4253 free_string_option(p_pt);
4254 p_pt = p;
4255 new_value_alloced = TRUE;
4256 }
4257 }
4258 }
4259
4260 /* 'backspace' */
4261 else if (varp == &p_bs)
4262 {
4263 if (VIM_ISDIGIT(*p_bs))
4264 {
Bram Moolenaare7fedb62015-12-31 19:07:19 +01004265 if (*p_bs > '2' || p_bs[1] != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004266 errmsg = e_invarg;
4267 }
4268 else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK)
4269 errmsg = e_invarg;
4270 }
Bram Moolenaar165bc692015-07-21 17:53:25 +02004271 else if (varp == &p_bo)
4272 {
4273 if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE) != OK)
4274 errmsg = e_invarg;
4275 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004276
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01004277 /* 'tagcase' */
4278 else if (gvarp == &p_tc)
4279 {
4280 unsigned int *flags;
4281
4282 if (opt_flags & OPT_LOCAL)
4283 {
4284 p = curbuf->b_p_tc;
4285 flags = &curbuf->b_tc_flags;
4286 }
4287 else
4288 {
4289 p = p_tc;
4290 flags = &tc_flags;
4291 }
4292
4293 if ((opt_flags & OPT_LOCAL) && *p == NUL)
4294 /* make the local value empty: use the global value */
4295 *flags = 0;
4296 else if (*p == NUL
4297 || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK)
4298 errmsg = e_invarg;
4299 }
4300
Bram Moolenaar071d4272004-06-13 20:20:40 +00004301 /* 'casemap' */
4302 else if (varp == &p_cmp)
4303 {
4304 if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE) != OK)
4305 errmsg = e_invarg;
4306 }
4307
4308#ifdef FEAT_DIFF
4309 /* 'diffopt' */
4310 else if (varp == &p_dip)
4311 {
4312 if (diffopt_changed() == FAIL)
4313 errmsg = e_invarg;
4314 }
4315#endif
4316
4317#ifdef FEAT_FOLDING
4318 /* 'foldmethod' */
4319 else if (gvarp == &curwin->w_allbuf_opt.wo_fdm)
4320 {
4321 if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK
4322 || *curwin->w_p_fdm == NUL)
4323 errmsg = e_invarg;
4324 else
Bram Moolenaarf4d7f942010-02-24 14:34:19 +01004325 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004326 foldUpdateAll(curwin);
Bram Moolenaarf4d7f942010-02-24 14:34:19 +01004327 if (foldmethodIsDiff(curwin))
4328 newFoldLevel();
4329 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004330 }
4331# ifdef FEAT_EVAL
4332 /* 'foldexpr' */
4333 else if (varp == &curwin->w_p_fde)
4334 {
4335 if (foldmethodIsExpr(curwin))
4336 foldUpdateAll(curwin);
4337 }
4338# endif
4339 /* 'foldmarker' */
4340 else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)
4341 {
4342 p = vim_strchr(*varp, ',');
4343 if (p == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004344 errmsg = N_("E536: comma required");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345 else if (p == *varp || p[1] == NUL)
4346 errmsg = e_invarg;
4347 else if (foldmethodIsMarker(curwin))
4348 foldUpdateAll(curwin);
4349 }
4350 /* 'commentstring' */
4351 else if (gvarp == &p_cms)
4352 {
4353 if (**varp != NUL && strstr((char *)*varp, "%s") == NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004354 errmsg = N_("E537: 'commentstring' must be empty or contain %s");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004355 }
4356 /* 'foldopen' */
4357 else if (varp == &p_fdo)
4358 {
4359 if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE) != OK)
4360 errmsg = e_invarg;
4361 }
4362 /* 'foldclose' */
4363 else if (varp == &p_fcl)
4364 {
4365 if (check_opt_strings(p_fcl, p_fcl_values, TRUE) != OK)
4366 errmsg = e_invarg;
4367 }
Bram Moolenaar7fc904b2006-04-13 20:37:35 +00004368 /* 'foldignore' */
4369 else if (gvarp == &curwin->w_allbuf_opt.wo_fdi)
4370 {
4371 if (foldmethodIsIndent(curwin))
4372 foldUpdateAll(curwin);
4373 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004374#endif
4375
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376 /* 'virtualedit' */
4377 else if (varp == &p_ve)
4378 {
4379 if (opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE) != OK)
4380 errmsg = e_invarg;
4381 else if (STRCMP(p_ve, oldval) != 0)
4382 {
4383 /* Recompute cursor position in case the new 've' setting
4384 * changes something. */
4385 validate_virtcol();
4386 coladvance(curwin->w_virtcol);
4387 }
4388 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004389
4390#if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX)
4391 else if (varp == &p_csqf)
4392 {
4393 if (p_csqf != NULL)
4394 {
4395 p = p_csqf;
4396 while (*p != NUL)
4397 {
4398 if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL
4399 || p[1] == NUL
4400 || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL
4401 || (p[2] != NUL && p[2] != ','))
4402 {
4403 errmsg = e_invarg;
4404 break;
4405 }
4406 else if (p[2] == NUL)
4407 break;
4408 else
4409 p += 3;
4410 }
4411 }
4412 }
4413#endif
4414
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01004415#ifdef FEAT_CINDENT
4416 /* 'cinoptions' */
4417 else if (gvarp == &p_cino)
4418 {
4419 /* TODO: recognize errors */
4420 parse_cino(curbuf);
4421 }
4422#endif
4423
Bram Moolenaarb5a7a8b2014-08-06 14:52:30 +02004424#if defined(FEAT_RENDER_OPTIONS)
Bram Moolenaar031cb742016-11-24 21:46:19 +01004425 /* 'renderoptions' */
Bram Moolenaar3767c6e2017-12-05 16:57:56 +01004426 else if (varp == &p_rop)
Bram Moolenaarb5a7a8b2014-08-06 14:52:30 +02004427 {
4428 if (!gui_mch_set_rendering_options(p_rop))
4429 errmsg = e_invarg;
4430 }
4431#endif
4432
Bram Moolenaard0b51382016-11-04 15:23:45 +01004433 else if (gvarp == &p_ft)
4434 {
4435 if (!valid_filetype(*varp))
4436 errmsg = e_invarg;
Bram Moolenaar90492982017-06-22 14:16:31 +02004437 else
Bram Moolenaar916a8182018-11-25 02:18:29 +01004438 {
Bram Moolenaarc3ffc9b2018-06-17 17:32:58 +02004439 value_changed = STRCMP(oldval, *varp) != 0;
Bram Moolenaar916a8182018-11-25 02:18:29 +01004440
4441 // Since we check the value, there is no need to set P_INSECURE,
4442 // even when the value comes from a modeline.
4443 *value_checked = TRUE;
4444 }
Bram Moolenaard0b51382016-11-04 15:23:45 +01004445 }
Bram Moolenaard0b51382016-11-04 15:23:45 +01004446
4447#ifdef FEAT_SYN_HL
4448 else if (gvarp == &p_syn)
4449 {
4450 if (!valid_filetype(*varp))
4451 errmsg = e_invarg;
Bram Moolenaarc3ffc9b2018-06-17 17:32:58 +02004452 else
Bram Moolenaar916a8182018-11-25 02:18:29 +01004453 {
Bram Moolenaarc3ffc9b2018-06-17 17:32:58 +02004454 value_changed = STRCMP(oldval, *varp) != 0;
Bram Moolenaar916a8182018-11-25 02:18:29 +01004455
4456 // Since we check the value, there is no need to set P_INSECURE,
4457 // even when the value comes from a modeline.
4458 *value_checked = TRUE;
4459 }
Bram Moolenaard0b51382016-11-04 15:23:45 +01004460 }
4461#endif
4462
Bram Moolenaar825680f2017-07-22 17:04:02 +02004463#ifdef FEAT_TERMINAL
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01004464 // 'termwinkey'
Bram Moolenaar6d150f72018-04-21 20:03:20 +02004465 else if (varp == &curwin->w_p_twk)
Bram Moolenaardbe948d2017-07-23 22:50:51 +02004466 {
Bram Moolenaar6d150f72018-04-21 20:03:20 +02004467 if (*curwin->w_p_twk != NUL
4468 && string_to_key(curwin->w_p_twk, TRUE) == 0)
Bram Moolenaardbe948d2017-07-23 22:50:51 +02004469 errmsg = e_invarg;
4470 }
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01004471 // 'termwinsize'
Bram Moolenaar6d150f72018-04-21 20:03:20 +02004472 else if (varp == &curwin->w_p_tws)
Bram Moolenaar825680f2017-07-22 17:04:02 +02004473 {
Bram Moolenaar6d150f72018-04-21 20:03:20 +02004474 if (*curwin->w_p_tws != NUL)
Bram Moolenaar825680f2017-07-22 17:04:02 +02004475 {
Bram Moolenaar6d150f72018-04-21 20:03:20 +02004476 p = skipdigits(curwin->w_p_tws);
4477 if (p == curwin->w_p_tws
Bram Moolenaar498c2562018-04-15 23:45:15 +02004478 || (*p != 'x' && *p != '*')
4479 || *skipdigits(p + 1) != NUL)
Bram Moolenaar825680f2017-07-22 17:04:02 +02004480 errmsg = e_invarg;
4481 }
4482 }
Bram Moolenaar4f974752019-02-17 17:44:42 +01004483# if defined(MSWIN)
Bram Moolenaarc6ddce32019-02-08 12:47:03 +01004484 // 'termwintype'
4485 else if (varp == &p_twt)
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01004486 {
Bram Moolenaarc6ddce32019-02-08 12:47:03 +01004487 if (check_opt_strings(*varp, p_twt_values, FALSE) != OK)
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01004488 errmsg = e_invarg;
4489 }
Bram Moolenaarc6ddce32019-02-08 12:47:03 +01004490# endif
Bram Moolenaar825680f2017-07-22 17:04:02 +02004491#endif
4492
Bram Moolenaar04958cb2018-06-23 19:23:02 +02004493#ifdef FEAT_VARTABS
4494 /* 'varsofttabstop' */
4495 else if (varp == &(curbuf->b_p_vsts))
4496 {
4497 char_u *cp;
4498
4499 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
4500 {
4501 if (curbuf->b_p_vsts_array)
4502 {
4503 vim_free(curbuf->b_p_vsts_array);
4504 curbuf->b_p_vsts_array = 0;
4505 }
4506 }
4507 else
4508 {
4509 for (cp = *varp; *cp; ++cp)
4510 {
4511 if (vim_isdigit(*cp))
4512 continue;
4513 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
4514 continue;
4515 errmsg = e_invarg;
4516 break;
4517 }
4518 if (errmsg == NULL)
4519 {
4520 int *oldarray = curbuf->b_p_vsts_array;
4521 if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)))
4522 {
4523 if (oldarray)
4524 vim_free(oldarray);
4525 }
4526 else
4527 errmsg = e_invarg;
4528 }
4529 }
4530 }
4531
4532 /* 'vartabstop' */
4533 else if (varp == &(curbuf->b_p_vts))
4534 {
4535 char_u *cp;
4536
4537 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1]))
4538 {
4539 if (curbuf->b_p_vts_array)
4540 {
4541 vim_free(curbuf->b_p_vts_array);
4542 curbuf->b_p_vts_array = NULL;
4543 }
4544 }
4545 else
4546 {
4547 for (cp = *varp; *cp; ++cp)
4548 {
4549 if (vim_isdigit(*cp))
4550 continue;
4551 if (*cp == ',' && cp > *varp && *(cp-1) != ',')
4552 continue;
4553 errmsg = e_invarg;
4554 break;
4555 }
4556 if (errmsg == NULL)
4557 {
4558 int *oldarray = curbuf->b_p_vts_array;
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01004559
Bram Moolenaar04958cb2018-06-23 19:23:02 +02004560 if (tabstop_set(*varp, &(curbuf->b_p_vts_array)))
4561 {
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01004562 vim_free(oldarray);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02004563#ifdef FEAT_FOLDING
4564 if (foldmethodIsIndent(curwin))
4565 foldUpdateAll(curwin);
Bram Moolenaar55c77cf2019-02-16 19:05:11 +01004566#endif
Bram Moolenaar04958cb2018-06-23 19:23:02 +02004567 }
4568 else
4569 errmsg = e_invarg;
4570 }
4571 }
4572 }
4573#endif
4574
Bram Moolenaar79648732019-07-18 21:43:07 +02004575#ifdef FEAT_TEXT_PROP
4576 // 'previewpopup'
4577 else if (varp == &p_pvp)
4578 {
4579 if (parse_previewpopup(NULL) == FAIL)
4580 errmsg = e_invarg;
4581 }
Bram Moolenaar36e4d982019-08-20 21:12:16 +02004582# ifdef FEAT_QUICKFIX
Bram Moolenaar62a0cb42019-08-18 16:35:23 +02004583 // 'completepopup'
4584 else if (varp == &p_cpp)
4585 {
4586 if (parse_completepopup(NULL) == FAIL)
4587 errmsg = e_invarg;
4588 }
Bram Moolenaar36e4d982019-08-20 21:12:16 +02004589# endif
Bram Moolenaar79648732019-07-18 21:43:07 +02004590#endif
4591
Bram Moolenaar071d4272004-06-13 20:20:40 +00004592 /* Options that are a list of flags. */
4593 else
4594 {
4595 p = NULL;
Bram Moolenaar031cb742016-11-24 21:46:19 +01004596 if (varp == &p_ww) /* 'whichwrap' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004597 p = (char_u *)WW_ALL;
Bram Moolenaar031cb742016-11-24 21:46:19 +01004598 if (varp == &p_shm) /* 'shortmess' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004599 p = (char_u *)SHM_ALL;
Bram Moolenaar031cb742016-11-24 21:46:19 +01004600 else if (varp == &(p_cpo)) /* 'cpoptions' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004601 p = (char_u *)CPO_ALL;
Bram Moolenaar031cb742016-11-24 21:46:19 +01004602 else if (varp == &(curbuf->b_p_fo)) /* 'formatoptions' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603 p = (char_u *)FO_ALL;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02004604#ifdef FEAT_CONCEAL
Bram Moolenaar031cb742016-11-24 21:46:19 +01004605 else if (varp == &curwin->w_p_cocu) /* 'concealcursor' */
Bram Moolenaarf5963f72010-07-23 22:10:27 +02004606 p = (char_u *)COCU_ALL;
4607#endif
Bram Moolenaar031cb742016-11-24 21:46:19 +01004608 else if (varp == &p_mouse) /* 'mouse' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609 {
4610#ifdef FEAT_MOUSE
4611 p = (char_u *)MOUSE_ALL;
4612#else
4613 if (*p_mouse != NUL)
Bram Moolenaarb1443b42019-01-13 23:51:14 +01004614 errmsg = N_("E538: No mouse support");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615#endif
4616 }
4617#if defined(FEAT_GUI)
Bram Moolenaar031cb742016-11-24 21:46:19 +01004618 else if (varp == &p_go) /* 'guioptions' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004619 p = (char_u *)GO_ALL;
4620#endif
4621 if (p != NULL)
4622 {
4623 for (s = *varp; *s; ++s)
4624 if (vim_strchr(p, *s) == NULL)
4625 {
4626 errmsg = illegal_char(errbuf, *s);
4627 break;
4628 }
4629 }
4630 }
4631
4632 /*
4633 * If error detected, restore the previous value.
4634 */
4635 if (errmsg != NULL)
4636 {
4637 if (new_value_alloced)
4638 free_string_option(*varp);
4639 *varp = oldval;
4640 /*
4641 * When resetting some values, need to act on it.
4642 */
4643 if (did_chartab)
4644 (void)init_chartab();
4645 if (varp == &p_hl)
4646 (void)highlight_changed();
4647 }
4648 else
4649 {
4650#ifdef FEAT_EVAL
4651 /* Remember where the option was set. */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004652 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004653#endif
4654 /*
4655 * Free string options that are in allocated memory.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004656 * Use "free_oldval", because recursiveness may change the flags under
4657 * our fingers (esp. init_highlight()).
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004659 if (free_oldval)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004660 free_string_option(oldval);
4661 if (new_value_alloced)
4662 options[opt_idx].flags |= P_ALLOCED;
4663 else
4664 options[opt_idx].flags &= ~P_ALLOCED;
4665
4666 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
Bram Moolenaara23ccb82006-02-27 00:08:02 +00004667 && ((int)options[opt_idx].indir & PV_BOTH))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004668 {
4669 /* global option with local value set to use global value; free
4670 * the local value and make it empty */
4671 p = get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
4672 free_string_option(*(char_u **)p);
4673 *(char_u **)p = empty_option;
4674 }
4675
4676 /* May set global value for local option. */
4677 else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL)
4678 set_string_option_global(opt_idx, varp);
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004679
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004680 /*
4681 * Trigger the autocommand only after setting the flags.
4682 */
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01004683#ifdef FEAT_SYN_HL
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004684 /* When 'syntax' is set, load the syntax of that name */
4685 if (varp == &(curbuf->b_p_syn))
4686 {
Bram Moolenaara5616b02018-06-17 19:08:30 +02004687 static int syn_recursive = 0;
4688
4689 ++syn_recursive;
4690 // Only pass TRUE for "force" when the value changed or not used
4691 // recursively, to avoid endless recurrence.
4692 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
4693 value_changed || syn_recursive == 1, curbuf);
Bram Moolenaarc7f1e402019-08-03 13:29:46 +02004694 curbuf->b_flags |= BF_SYN_SET;
Bram Moolenaara5616b02018-06-17 19:08:30 +02004695 --syn_recursive;
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004696 }
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01004697#endif
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004698 else if (varp == &(curbuf->b_p_ft))
4699 {
Bram Moolenaar90492982017-06-22 14:16:31 +02004700 /* 'filetype' is set, trigger the FileType autocommand.
4701 * Skip this when called from a modeline and the filetype was
Bram Moolenaara5616b02018-06-17 19:08:30 +02004702 * already set to this value. */
Bram Moolenaarc3ffc9b2018-06-17 17:32:58 +02004703 if (!(opt_flags & OPT_MODELINE) || value_changed)
Bram Moolenaar90492982017-06-22 14:16:31 +02004704 {
Bram Moolenaar916a8182018-11-25 02:18:29 +01004705 static int ft_recursive = 0;
4706 int secure_save = secure;
4707
4708 // Reset the secure flag, since the value of 'filetype' has
4709 // been checked to be safe.
4710 secure = 0;
Bram Moolenaara5616b02018-06-17 19:08:30 +02004711
4712 ++ft_recursive;
Bram Moolenaar90492982017-06-22 14:16:31 +02004713 did_filetype = TRUE;
Bram Moolenaara5616b02018-06-17 19:08:30 +02004714 // Only pass TRUE for "force" when the value changed or not
4715 // used recursively, to avoid endless recurrence.
4716 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
4717 value_changed || ft_recursive == 1, curbuf);
4718 --ft_recursive;
Bram Moolenaar163095f2017-07-09 15:41:53 +02004719 /* Just in case the old "curbuf" is now invalid. */
4720 if (varp != &(curbuf->b_p_ft))
4721 varp = NULL;
Bram Moolenaar916a8182018-11-25 02:18:29 +01004722
4723 secure = secure_save;
Bram Moolenaar90492982017-06-22 14:16:31 +02004724 }
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004725 }
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00004726#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +02004727 if (varp == &(curwin->w_s->b_p_spl))
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004728 {
4729 char_u fname[200];
Bram Moolenaarcc63c642013-11-12 04:44:01 +01004730 char_u *q = curwin->w_s->b_p_spl;
4731
4732 /* Skip the first name if it is "cjk". */
4733 if (STRNCMP(q, "cjk,", 4) == 0)
4734 q += 4;
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004735
4736 /*
4737 * Source the spell/LANG.vim in 'runtimepath'.
4738 * They could set 'spellcapcheck' depending on the language.
4739 * Use the first name in 'spelllang' up to '_region' or
4740 * '.encoding'.
4741 */
Bram Moolenaarcc63c642013-11-12 04:44:01 +01004742 for (p = q; *p != NUL; ++p)
Bram Moolenaar247bb7e2018-11-20 14:27:07 +01004743 if (!ASCII_ISALNUM(*p) && *p != '-')
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004744 break;
Bram Moolenaar82e8c922018-11-20 13:32:36 +01004745 if (p > q)
4746 {
Bram Moolenaar8f130ed2019-04-10 22:15:19 +02004747 vim_snprintf((char *)fname, 200, "spell/%.*s.vim",
4748 (int)(p - q), q);
Bram Moolenaar82e8c922018-11-20 13:32:36 +01004749 source_runtime(fname, DIP_ALL);
4750 }
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +00004751 }
4752#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004753 }
4754
4755#ifdef FEAT_MOUSE
4756 if (varp == &p_mouse)
4757 {
4758# ifdef FEAT_MOUSE_TTY
4759 if (*p_mouse == NUL)
4760 mch_setmouse(FALSE); /* switch mouse off */
4761 else
4762# endif
4763 setmouse(); /* in case 'mouse' changed */
4764 }
4765#endif
4766
Bram Moolenaar913077c2012-03-28 19:59:04 +02004767 if (curwin->w_curswant != MAXCOL
Bram Moolenaar488eb262015-03-13 11:23:50 +01004768 && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaar913077c2012-03-28 19:59:04 +02004769 curwin->w_set_curswant = TRUE;
4770
Bram Moolenaarfaff14a2009-02-04 16:29:07 +00004771#ifdef FEAT_GUI
4772 /* check redraw when it's not a GUI option or the GUI is active. */
4773 if (!redraw_gui_only || gui.in_use)
4774#endif
4775 check_redraw(options[opt_idx].flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02004777#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
4778 if (did_swaptcap)
4779 {
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02004780 set_termname((char_u *)"win32");
4781 init_highlight(TRUE, FALSE);
4782 }
4783#endif
4784
Bram Moolenaar071d4272004-06-13 20:20:40 +00004785 return errmsg;
4786}
4787
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788#ifdef FEAT_STL_OPT
4789/*
4790 * Check validity of options with the 'statusline' format.
4791 * Return error message or NULL.
4792 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02004793 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004794check_stl_option(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004795{
4796 int itemcnt = 0;
4797 int groupdepth = 0;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004798 static char errbuf[80];
Bram Moolenaar071d4272004-06-13 20:20:40 +00004799
4800 while (*s && itemcnt < STL_MAX_ITEM)
4801 {
4802 /* Check for valid keys after % sequences */
4803 while (*s && *s != '%')
4804 s++;
4805 if (!*s)
4806 break;
4807 s++;
4808 if (*s != '%' && *s != ')')
4809 ++itemcnt;
4810 if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK)
4811 {
4812 s++;
4813 continue;
4814 }
4815 if (*s == ')')
4816 {
4817 s++;
4818 if (--groupdepth < 0)
4819 break;
4820 continue;
4821 }
4822 if (*s == '-')
4823 s++;
4824 while (VIM_ISDIGIT(*s))
4825 s++;
Bram Moolenaar238a5642006-02-21 22:12:05 +00004826 if (*s == STL_USER_HL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004827 continue;
4828 if (*s == '.')
4829 {
4830 s++;
4831 while (*s && VIM_ISDIGIT(*s))
4832 s++;
4833 }
4834 if (*s == '(')
4835 {
4836 groupdepth++;
4837 continue;
4838 }
4839 if (vim_strchr(STL_ALL, *s) == NULL)
4840 {
4841 return illegal_char(errbuf, *s);
4842 }
4843 if (*s == '{')
4844 {
4845 s++;
4846 while (*s != '}' && *s)
4847 s++;
4848 if (*s != '}')
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004849 return N_("E540: Unclosed expression sequence");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004850 }
4851 }
4852 if (itemcnt >= STL_MAX_ITEM)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004853 return N_("E541: too many items");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004854 if (groupdepth != 0)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004855 return N_("E542: unbalanced groups");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856 return NULL;
4857}
4858#endif
4859
4860#ifdef FEAT_CLIPBOARD
4861/*
4862 * Extract the items in the 'clipboard' option and set global values.
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004863 * Return an error message or NULL for success.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004864 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004865 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01004866check_clipboard_option(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004867{
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01004868 int new_unnamed = 0;
Bram Moolenaar89af4392012-07-10 18:31:54 +02004869 int new_autoselect_star = FALSE;
4870 int new_autoselect_plus = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871 int new_autoselectml = FALSE;
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00004872 int new_html = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004873 regprog_T *new_exclude_prog = NULL;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01004874 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004875 char_u *p;
4876
4877 for (p = p_cb; *p != NUL; )
4878 {
4879 if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL))
4880 {
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01004881 new_unnamed |= CLIP_UNNAMED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004882 p += 7;
4883 }
Bram Moolenaar11b73d62012-06-29 15:51:30 +02004884 else if (STRNCMP(p, "unnamedplus", 11) == 0
Bram Moolenaarbf9680e2010-12-02 21:43:16 +01004885 && (p[11] == ',' || p[11] == NUL))
4886 {
4887 new_unnamed |= CLIP_UNNAMED_PLUS;
4888 p += 11;
4889 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004890 else if (STRNCMP(p, "autoselect", 10) == 0
Bram Moolenaar89af4392012-07-10 18:31:54 +02004891 && (p[10] == ',' || p[10] == NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892 {
Bram Moolenaar89af4392012-07-10 18:31:54 +02004893 new_autoselect_star = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004894 p += 10;
4895 }
Bram Moolenaar89af4392012-07-10 18:31:54 +02004896 else if (STRNCMP(p, "autoselectplus", 14) == 0
4897 && (p[14] == ',' || p[14] == NUL))
4898 {
4899 new_autoselect_plus = TRUE;
4900 p += 14;
4901 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004902 else if (STRNCMP(p, "autoselectml", 12) == 0
Bram Moolenaar89af4392012-07-10 18:31:54 +02004903 && (p[12] == ',' || p[12] == NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004904 {
4905 new_autoselectml = TRUE;
4906 p += 12;
4907 }
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00004908 else if (STRNCMP(p, "html", 4) == 0 && (p[4] == ',' || p[4] == NUL))
4909 {
4910 new_html = TRUE;
4911 p += 4;
4912 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004913 else if (STRNCMP(p, "exclude:", 8) == 0 && new_exclude_prog == NULL)
4914 {
4915 p += 8;
4916 new_exclude_prog = vim_regcomp(p, RE_MAGIC);
4917 if (new_exclude_prog == NULL)
4918 errmsg = e_invarg;
4919 break;
4920 }
4921 else
4922 {
4923 errmsg = e_invarg;
4924 break;
4925 }
4926 if (*p == ',')
4927 ++p;
4928 }
4929 if (errmsg == NULL)
4930 {
4931 clip_unnamed = new_unnamed;
Bram Moolenaar89af4392012-07-10 18:31:54 +02004932 clip_autoselect_star = new_autoselect_star;
4933 clip_autoselect_plus = new_autoselect_plus;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004934 clip_autoselectml = new_autoselectml;
Bram Moolenaar3a6eaa52009-06-16 13:23:06 +00004935 clip_html = new_html;
Bram Moolenaar473de612013-06-08 18:19:48 +02004936 vim_regfree(clip_exclude_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004937 clip_exclude_prog = new_exclude_prog;
Bram Moolenaara76638f2010-06-05 12:49:46 +02004938#ifdef FEAT_GUI_GTK
4939 if (gui.in_use)
4940 {
4941 gui_gtk_set_selection_targets();
4942 gui_gtk_set_dnd_targets();
4943 }
4944#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945 }
4946 else
Bram Moolenaar473de612013-06-08 18:19:48 +02004947 vim_regfree(new_exclude_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004948
4949 return errmsg;
4950}
4951#endif
4952
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004953#if defined(FEAT_EVAL) || defined(PROTO)
4954/*
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004955 * Set the script_ctx for an option, taking care of setting the buffer- or
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004956 * window-local value.
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004957 */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004958 static void
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004959set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004960{
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004961 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
4962 int indir = (int)options[opt_idx].indir;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004963 sctx_T new_script_ctx = script_ctx;
4964
4965 new_script_ctx.sc_lnum += sourcing_lnum;
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004966
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004967 /* Remember where the option was set. For local options need to do that
4968 * in the buffer or window structure. */
4969 if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004970 options[opt_idx].script_ctx = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004971 if (both || (opt_flags & OPT_LOCAL))
4972 {
4973 if (indir & PV_BUF)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004974 curbuf->b_p_script_ctx[indir & PV_MASK] = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004975 else if (indir & PV_WIN)
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02004976 curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00004977 }
Bram Moolenaard1f56e62006-02-22 21:25:37 +00004978}
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02004979
4980/*
4981 * Set the script_ctx for a termcap option.
4982 * "name" must be the two character code, e.g. "RV".
4983 * When "name" is NULL use "opt_idx".
4984 */
4985 void
4986set_term_option_sctx_idx(char *name, int opt_idx)
4987{
4988 char_u buf[5];
4989 int idx;
4990
4991 if (name == NULL)
4992 idx = opt_idx;
4993 else
4994 {
4995 buf[0] = 't';
4996 buf[1] = '_';
4997 buf[2] = name[0];
4998 buf[3] = name[1];
4999 buf[4] = 0;
5000 idx = findoption(buf);
5001 }
5002 if (idx >= 0)
5003 set_option_sctx_idx(idx, OPT_GLOBAL, current_sctx);
5004}
Bram Moolenaard1f56e62006-02-22 21:25:37 +00005005#endif
5006
Bram Moolenaar071d4272004-06-13 20:20:40 +00005007/*
5008 * Set the value of a boolean option, and take care of side effects.
5009 * Returns NULL for success, or an error message for an error.
5010 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005011 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01005012set_bool_option(
5013 int opt_idx, /* index in options[] table */
5014 char_u *varp, /* pointer to the option variable */
5015 int value, /* new value */
5016 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005017{
5018 int old_value = *(int *)varp;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005019#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02005020 int old_global_value = 0;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005021#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005022
Bram Moolenaar071d4272004-06-13 20:20:40 +00005023 /* Disallow changing some options from secure mode */
5024 if ((secure
5025#ifdef HAVE_SANDBOX
5026 || sandbox != 0
5027#endif
5028 ) && (options[opt_idx].flags & P_SECURE))
5029 return e_secure;
5030
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005031#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02005032 // Save the global value before changing anything. This is needed as for
5033 // a global-only option setting the "local value" in fact sets the global
5034 // value (since there is only one value).
5035 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
5036 old_global_value = *(int *)get_varp_scope(&(options[opt_idx]),
5037 OPT_GLOBAL);
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005038#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02005039
Bram Moolenaar071d4272004-06-13 20:20:40 +00005040 *(int *)varp = value; /* set the new value */
5041#ifdef FEAT_EVAL
5042 /* Remember where the option was set. */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02005043 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044#endif
5045
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005046#ifdef FEAT_GUI
5047 need_mouse_correct = TRUE;
5048#endif
5049
Bram Moolenaar071d4272004-06-13 20:20:40 +00005050 /* May set global value for local option. */
5051 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
5052 *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
5053
5054 /*
5055 * Handle side effects of changing a bool option.
5056 */
5057
5058 /* 'compatible' */
5059 if ((int *)varp == &p_cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005060 compatible_set();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005061
Bram Moolenaar920694c2016-08-21 17:45:02 +02005062#ifdef FEAT_LANGMAP
5063 if ((int *)varp == &p_lrm)
5064 /* 'langremap' -> !'langnoremap' */
5065 p_lnr = !p_lrm;
5066 else if ((int *)varp == &p_lnr)
5067 /* 'langnoremap' -> !'langremap' */
5068 p_lrm = !p_lnr;
5069#endif
5070
Bram Moolenaar8c63e0e2018-09-25 22:17:54 +02005071#ifdef FEAT_SYN_HL
5072 else if ((int *)varp == &curwin->w_p_cul && !value && old_value)
5073 reset_cursorline();
5074#endif
5075
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005076#ifdef FEAT_PERSISTENT_UNDO
5077 /* 'undofile' */
5078 else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf)
5079 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02005080 /* Only take action when the option was set. When reset we do not
5081 * delete the undo file, the option may be set again without making
5082 * any changes in between. */
5083 if (curbuf->b_p_udf || p_udf)
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005084 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02005085 char_u hash[UNDO_HASH_SIZE];
5086 buf_T *save_curbuf = curbuf;
5087
Bram Moolenaar29323592016-07-24 22:04:11 +02005088 FOR_ALL_BUFFERS(curbuf)
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005089 {
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02005090 /* When 'undofile' is set globally: for every buffer, otherwise
5091 * only for the current buffer: Try to read in the undofile,
5092 * if one exists, the buffer wasn't changed and the buffer was
5093 * loaded */
5094 if ((curbuf == save_curbuf
5095 || (opt_flags & OPT_GLOBAL) || opt_flags == 0)
5096 && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL)
5097 {
5098 u_compute_hash(hash);
5099 u_read_undo(NULL, hash, curbuf->b_fname);
5100 }
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005101 }
Bram Moolenaare8d8fd22012-10-21 03:46:05 +02005102 curbuf = save_curbuf;
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005103 }
Bram Moolenaar374d32d2012-01-04 19:34:37 +01005104 }
5105#endif
5106
Bram Moolenaar071d4272004-06-13 20:20:40 +00005107 else if ((int *)varp == &curbuf->b_p_ro)
5108 {
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +00005109 /* when 'readonly' is reset globally, also reset readonlymode */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005110 if (!curbuf->b_p_ro && (opt_flags & OPT_LOCAL) == 0)
5111 readonlymode = FALSE;
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +00005112
5113 /* when 'readonly' is set may give W10 again */
5114 if (curbuf->b_p_ro)
5115 curbuf->b_did_warn = FALSE;
5116
Bram Moolenaar071d4272004-06-13 20:20:40 +00005117#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005118 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005119#endif
5120 }
5121
Bram Moolenaar9c449722010-07-20 18:44:27 +02005122#ifdef FEAT_GUI
5123 else if ((int *)varp == &p_mh)
5124 {
5125 if (!p_mh)
5126 gui_mch_mousehide(FALSE);
5127 }
5128#endif
5129
Bram Moolenaara539df02010-08-01 14:35:05 +02005130 /* when 'modifiable' is changed, redraw the window title */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005131 else if ((int *)varp == &curbuf->b_p_ma)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005132 {
Bram Moolenaar423802d2017-07-30 16:52:24 +02005133# ifdef FEAT_TERMINAL
5134 /* Cannot set 'modifiable' when in Terminal mode. */
Bram Moolenaard7db27b2018-03-07 23:02:33 +01005135 if (curbuf->b_p_ma && (term_in_normal_mode() || (bt_terminal(curbuf)
5136 && curbuf->b_term != NULL && !term_is_finished(curbuf))))
Bram Moolenaar423802d2017-07-30 16:52:24 +02005137 {
5138 curbuf->b_p_ma = FALSE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005139 return N_("E946: Cannot make a terminal with running job modifiable");
Bram Moolenaar423802d2017-07-30 16:52:24 +02005140 }
5141# endif
5142# ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005143 redraw_titles();
Bram Moolenaar423802d2017-07-30 16:52:24 +02005144# endif
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005145 }
Bram Moolenaar423802d2017-07-30 16:52:24 +02005146#ifdef FEAT_TITLE
Bram Moolenaar071d4272004-06-13 20:20:40 +00005147 /* when 'endofline' is changed, redraw the window title */
5148 else if ((int *)varp == &curbuf->b_p_eol)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005149 {
5150 redraw_titles();
5151 }
Bram Moolenaar34d72d42015-07-17 14:18:08 +02005152 /* when 'fixeol' is changed, redraw the window title */
5153 else if ((int *)varp == &curbuf->b_p_fixeol)
5154 {
5155 redraw_titles();
5156 }
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005157 /* when 'bomb' is changed, redraw the window title and tab page text */
Bram Moolenaar83eb8852007-08-12 13:51:26 +00005158 else if ((int *)varp == &curbuf->b_p_bomb)
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005159 {
5160 redraw_titles();
5161 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005162#endif
5163
5164 /* when 'bin' is set also set some other options */
5165 else if ((int *)varp == &curbuf->b_p_bin)
5166 {
5167 set_options_bin(old_value, curbuf->b_p_bin, opt_flags);
5168#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005169 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005170#endif
5171 }
5172
Bram Moolenaar071d4272004-06-13 20:20:40 +00005173 /* when 'buflisted' changes, trigger autocommands */
5174 else if ((int *)varp == &curbuf->b_p_bl && old_value != curbuf->b_p_bl)
5175 {
5176 apply_autocmds(curbuf->b_p_bl ? EVENT_BUFADD : EVENT_BUFDELETE,
5177 NULL, NULL, TRUE, curbuf);
5178 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005179
5180 /* when 'swf' is set, create swapfile, when reset remove swapfile */
5181 else if ((int *)varp == &curbuf->b_p_swf)
5182 {
5183 if (curbuf->b_p_swf && p_uc)
5184 ml_open_file(curbuf); /* create the swap file */
5185 else
Bram Moolenaard55de222007-05-06 13:38:48 +00005186 /* no need to reset curbuf->b_may_swap, ml_open_file() will check
5187 * buf->b_p_swf */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005188 mf_close_file(curbuf, TRUE); /* remove the swap file */
5189 }
5190
5191 /* when 'terse' is set change 'shortmess' */
5192 else if ((int *)varp == &p_terse)
5193 {
5194 char_u *p;
5195
5196 p = vim_strchr(p_shm, SHM_SEARCH);
5197
5198 /* insert 's' in p_shm */
5199 if (p_terse && p == NULL)
5200 {
5201 STRCPY(IObuff, p_shm);
5202 STRCAT(IObuff, "s");
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005203 set_string_option_direct((char_u *)"shm", -1, IObuff, OPT_FREE, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005204 }
5205 /* remove 's' from p_shm */
5206 else if (!p_terse && p != NULL)
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00005207 STRMOVE(p, p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 }
5209
5210 /* when 'paste' is set or reset also change other options */
5211 else if ((int *)varp == &p_paste)
5212 {
5213 paste_option_changed();
5214 }
5215
5216 /* when 'insertmode' is set from an autocommand need to do work here */
5217 else if ((int *)varp == &p_im)
5218 {
5219 if (p_im)
5220 {
5221 if ((State & INSERT) == 0)
5222 need_start_insertmode = TRUE;
5223 stop_insert_mode = FALSE;
5224 }
Bram Moolenaar00672e12016-06-26 18:38:13 +02005225 /* only reset if it was set previously */
5226 else if (old_value)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005227 {
5228 need_start_insertmode = FALSE;
5229 stop_insert_mode = TRUE;
Bram Moolenaard12f5c12006-01-25 22:10:52 +00005230 if (restart_edit != 0 && mode_displayed)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231 clear_cmdline = TRUE; /* remove "(insert)" */
5232 restart_edit = 0;
5233 }
5234 }
5235
5236 /* when 'ignorecase' is set or reset and 'hlsearch' is set, redraw */
5237 else if ((int *)varp == &p_ic && p_hls)
5238 {
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005239 redraw_all_later(SOME_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005240 }
5241
5242#ifdef FEAT_SEARCH_EXTRA
5243 /* when 'hlsearch' is set or reset: reset no_hlsearch */
5244 else if ((int *)varp == &p_hls)
5245 {
Bram Moolenaar451fc7b2018-04-27 22:53:07 +02005246 set_no_hlsearch(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005247 }
5248#endif
5249
Bram Moolenaar071d4272004-06-13 20:20:40 +00005250 /* when 'scrollbind' is set: snapshot the current position to avoid a jump
5251 * at the end of normal_cmd() */
5252 else if ((int *)varp == &curwin->w_p_scb)
5253 {
5254 if (curwin->w_p_scb)
Bram Moolenaar04c5c9e2013-07-09 13:44:59 +02005255 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005256 do_check_scrollbind(FALSE);
Bram Moolenaar04c5c9e2013-07-09 13:44:59 +02005257 curwin->w_scbind_pos = curwin->w_topline;
5258 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005259 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005260
Bram Moolenaar4033c552017-09-16 20:54:51 +02005261#if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005262 /* There can be only one window with 'previewwindow' set. */
5263 else if ((int *)varp == &curwin->w_p_pvw)
5264 {
5265 if (curwin->w_p_pvw)
5266 {
5267 win_T *win;
5268
Bram Moolenaar29323592016-07-24 22:04:11 +02005269 FOR_ALL_WINDOWS(win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005270 if (win->w_p_pvw && win != curwin)
5271 {
5272 curwin->w_p_pvw = FALSE;
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005273 return N_("E590: A preview window already exists");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274 }
5275 }
5276 }
5277#endif
5278
5279 /* when 'textmode' is set or reset also change 'fileformat' */
5280 else if ((int *)varp == &curbuf->b_p_tx)
5281 {
5282 set_fileformat(curbuf->b_p_tx ? EOL_DOS : EOL_UNIX, opt_flags);
5283 }
5284
5285 /* when 'textauto' is set or reset also change 'fileformats' */
5286 else if ((int *)varp == &p_ta)
Bram Moolenaarabab0b02019-03-30 18:47:01 +01005287 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005288 set_string_option_direct((char_u *)"ffs", -1,
5289 p_ta ? (char_u *)DFLT_FFS_VIM : (char_u *)"",
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00005290 OPT_FREE | opt_flags, 0);
Bram Moolenaarabab0b02019-03-30 18:47:01 +01005291 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005292
5293 /*
5294 * When 'lisp' option changes include/exclude '-' in
5295 * keyword characters.
5296 */
5297#ifdef FEAT_LISP
5298 else if (varp == (char_u *)&(curbuf->b_p_lisp))
5299 {
5300 (void)buf_init_chartab(curbuf, FALSE); /* ignore errors */
5301 }
5302#endif
5303
5304#ifdef FEAT_TITLE
5305 /* when 'title' changed, may need to change the title; same for 'icon' */
Bram Moolenaar84a93082018-06-16 22:58:15 +02005306 else if ((int *)varp == &p_title || (int *)varp == &p_icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005307 {
Bram Moolenaar84a93082018-06-16 22:58:15 +02005308 did_set_title();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005309 }
5310#endif
5311
5312 else if ((int *)varp == &curbuf->b_changed)
5313 {
5314 if (!value)
5315 save_file_ff(curbuf); /* Buffer is unchanged */
5316#ifdef FEAT_TITLE
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005317 redraw_titles();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005318#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005319 modified_was_set = value;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 }
5321
5322#ifdef BACKSLASH_IN_FILENAME
5323 else if ((int *)varp == &p_ssl)
5324 {
5325 if (p_ssl)
5326 {
5327 psepc = '/';
5328 psepcN = '\\';
5329 pseps[0] = '/';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005330 }
5331 else
5332 {
5333 psepc = '\\';
5334 psepcN = '/';
5335 pseps[0] = '\\';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005336 }
5337
5338 /* need to adjust the file name arguments and buffer names. */
5339 buflist_slash_adjust();
5340 alist_slash_adjust();
5341# ifdef FEAT_EVAL
5342 scriptnames_slash_adjust();
5343# endif
5344 }
5345#endif
5346
5347 /* If 'wrap' is set, set w_leftcol to zero. */
5348 else if ((int *)varp == &curwin->w_p_wrap)
5349 {
5350 if (curwin->w_p_wrap)
5351 curwin->w_leftcol = 0;
5352 }
5353
Bram Moolenaar071d4272004-06-13 20:20:40 +00005354 else if ((int *)varp == &p_ea)
5355 {
5356 if (p_ea && !old_value)
5357 win_equal(curwin, FALSE, 0);
5358 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005359
5360 else if ((int *)varp == &p_wiv)
5361 {
5362 /*
5363 * When 'weirdinvert' changed, set/reset 't_xs'.
5364 * Then set 'weirdinvert' according to value of 't_xs'.
5365 */
5366 if (p_wiv && !old_value)
5367 T_XS = (char_u *)"y";
5368 else if (!p_wiv && old_value)
5369 T_XS = empty_option;
5370 p_wiv = (*T_XS != NUL);
5371 }
5372
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01005373#ifdef FEAT_BEVAL_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00005374 else if ((int *)varp == &p_beval)
5375 {
Bram Moolenaar51b0f372017-11-18 18:52:04 +01005376 if (!balloonEvalForTerm)
5377 {
5378 if (p_beval && !old_value)
5379 gui_mch_enable_beval_area(balloonEval);
5380 else if (!p_beval && old_value)
5381 gui_mch_disable_beval_area(balloonEval);
5382 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005383 }
Bram Moolenaar8dff8182006-04-06 20:18:50 +00005384#endif
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01005385#ifdef FEAT_BEVAL_TERM
Bram Moolenaar51b0f372017-11-18 18:52:04 +01005386 else if ((int *)varp == &p_bevalterm)
5387 {
5388 mch_bevalterm_changed();
5389 }
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01005390#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005391
Bram Moolenaar8dff8182006-04-06 20:18:50 +00005392#ifdef FEAT_AUTOCHDIR
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393 else if ((int *)varp == &p_acd)
5394 {
Bram Moolenaar498efdb2006-09-05 14:31:54 +00005395 /* Change directories when the 'acd' option is set now. */
Bram Moolenaar6f470022018-04-10 18:47:20 +02005396 DO_AUTOCHDIR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005397 }
5398#endif
5399
5400#ifdef FEAT_DIFF
5401 /* 'diff' */
5402 else if ((int *)varp == &curwin->w_p_diff)
5403 {
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00005404 /* May add or remove the buffer from the list of diff buffers. */
5405 diff_buf_adjust(curwin);
5406# ifdef FEAT_FOLDING
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 if (foldmethodIsDiff(curwin))
5408 foldUpdateAll(curwin);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00005409# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410 }
5411#endif
5412
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005413#ifdef HAVE_INPUT_METHOD
Bram Moolenaar071d4272004-06-13 20:20:40 +00005414 /* 'imdisable' */
5415 else if ((int *)varp == &p_imdisable)
5416 {
5417 /* Only de-activate it here, it will be enabled when changing mode. */
5418 if (p_imdisable)
5419 im_set_active(FALSE);
Bram Moolenaar725a9622011-10-12 16:57:13 +02005420 else if (State & INSERT)
5421 /* When the option is set from an autocommand, it may need to take
5422 * effect right away. */
5423 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424 }
5425#endif
5426
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00005427#ifdef FEAT_SPELL
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00005428 /* 'spell' */
5429 else if ((int *)varp == &curwin->w_p_spell)
5430 {
5431 if (curwin->w_p_spell)
5432 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005433 char *errmsg = did_set_spelllang(curwin);
5434
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00005435 if (errmsg != NULL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005436 emsg(_(errmsg));
Bram Moolenaar0cb032e2005-04-23 20:52:00 +00005437 }
5438 }
5439#endif
5440
Bram Moolenaar071d4272004-06-13 20:20:40 +00005441#ifdef FEAT_ARABIC
5442 if ((int *)varp == &curwin->w_p_arab)
5443 {
5444 if (curwin->w_p_arab)
5445 {
5446 /*
5447 * 'arabic' is set, handle various sub-settings.
5448 */
5449 if (!p_tbidi)
5450 {
5451 /* set rightleft mode */
5452 if (!curwin->w_p_rl)
5453 {
5454 curwin->w_p_rl = TRUE;
5455 changed_window_setting();
5456 }
5457
5458 /* Enable Arabic shaping (major part of what Arabic requires) */
5459 if (!p_arshape)
5460 {
5461 p_arshape = TRUE;
5462 redraw_later_clear();
5463 }
5464 }
5465
5466 /* Arabic requires a utf-8 encoding, inform the user if its not
5467 * set. */
5468 if (STRCMP(p_enc, "utf-8") != 0)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00005469 {
Bram Moolenaar496c5262009-03-18 14:42:00 +00005470 static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
5471
Bram Moolenaar8820b482017-03-16 17:23:31 +01005472 msg_source(HL_ATTR(HLF_W));
Bram Moolenaar32526b32019-01-19 17:43:09 +01005473 msg_attr(_(w_arabic), HL_ATTR(HLF_W));
Bram Moolenaar496c5262009-03-18 14:42:00 +00005474#ifdef FEAT_EVAL
5475 set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_arabic), -1);
5476#endif
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00005477 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005478
Bram Moolenaar071d4272004-06-13 20:20:40 +00005479 /* set 'delcombine' */
5480 p_deco = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005481
5482# ifdef FEAT_KEYMAP
5483 /* Force-set the necessary keymap for arabic */
5484 set_option_value((char_u *)"keymap", 0L, (char_u *)"arabic",
5485 OPT_LOCAL);
5486# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005487 }
5488 else
5489 {
5490 /*
5491 * 'arabic' is reset, handle various sub-settings.
5492 */
5493 if (!p_tbidi)
5494 {
5495 /* reset rightleft mode */
5496 if (curwin->w_p_rl)
5497 {
5498 curwin->w_p_rl = FALSE;
5499 changed_window_setting();
5500 }
5501
5502 /* 'arabicshape' isn't reset, it is a global option and
5503 * another window may still need it "on". */
5504 }
5505
5506 /* 'delcombine' isn't reset, it is a global option and another
5507 * window may still want it "on". */
5508
5509# ifdef FEAT_KEYMAP
5510 /* Revert to the default keymap */
5511 curbuf->b_p_iminsert = B_IMODE_NONE;
5512 curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
5513# endif
5514 }
Bram Moolenaar801f8b82009-07-29 13:42:05 +00005515 }
5516
Bram Moolenaar319bdbd2009-09-11 13:20:33 +00005517#endif
5518
Bram Moolenaar44826212019-08-22 21:23:20 +02005519#if defined(FEAT_SIGNS) && defined(FEAT_GUI)
5520 else if (((int *)varp == &curwin->w_p_nu
5521 || (int *)varp == &curwin->w_p_rnu)
5522 && gui.in_use
5523 && (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u')
5524 && curbuf->b_signlist != NULL)
5525 {
5526 // If the 'number' or 'relativenumber' options are modified and
5527 // 'signcolumn' is set to 'number', then clear the screen for a full
5528 // refresh. Otherwise the sign icons are not displayed properly in the
5529 // number column. If the 'number' option is set and only the
5530 // 'relativenumber' option is toggled, then don't refresh the screen
5531 // (optimization).
5532 if (!(curwin->w_p_nu && ((int *)varp == &curwin->w_p_rnu)))
5533 redraw_all_later(CLEAR);
5534 }
5535#endif
5536
Bram Moolenaar61be73b2016-04-29 22:59:22 +02005537#ifdef FEAT_TERMGUICOLORS
5538 /* 'termguicolors' */
5539 else if ((int *)varp == &p_tgc)
Bram Moolenaar8a633e32016-04-21 21:10:14 +02005540 {
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005541# ifdef FEAT_VTP
5542 /* Do not turn on 'tgc' when 24-bit colors are not supported. */
Bram Moolenaarafde13b2019-04-28 19:46:49 +02005543 if (
5544# ifdef VIMDLL
5545 !gui.in_use && !gui.starting &&
5546# endif
5547 !has_vtp_working())
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005548 {
5549 p_tgc = 0;
Bram Moolenaaraa5df7e2019-02-03 14:53:10 +01005550 return N_("E954: 24-bit colors are not supported on this environment");
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005551 }
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02005552 if (is_term_win32())
5553 swap_tcap();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005554# endif
Bram Moolenaar8a633e32016-04-21 21:10:14 +02005555# ifdef FEAT_GUI
5556 if (!gui.in_use && !gui.starting)
5557# endif
5558 highlight_gui_started();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005559# ifdef FEAT_VTP
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005560 /* reset t_Co */
Bram Moolenaarc5cd8852018-05-01 15:47:38 +02005561 if (is_term_win32())
Bram Moolenaarb0eb14f2018-06-28 15:29:52 +02005562 {
5563 control_console_color_rgb();
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005564 set_termname(T_NAME);
Bram Moolenaarb0eb14f2018-06-28 15:29:52 +02005565 init_highlight(TRUE, FALSE);
5566 }
Bram Moolenaarcafafb32018-02-22 21:07:09 +01005567# endif
Bram Moolenaar8a633e32016-04-21 21:10:14 +02005568 }
5569#endif
5570
Bram Moolenaar071d4272004-06-13 20:20:40 +00005571 /*
5572 * End of handling side effects for bool options.
5573 */
5574
Bram Moolenaar53744302015-07-17 17:38:22 +02005575 /* after handling side effects, call autocommand */
5576
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577 options[opt_idx].flags |= P_WAS_SET;
5578
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01005579#if defined(FEAT_EVAL)
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02005580 // Don't do this while starting up or recursively.
5581 if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
Bram Moolenaar53744302015-07-17 17:38:22 +02005582 {
Bram Moolenaard7c96872019-06-15 17:12:48 +02005583 char_u buf_old[2], buf_old_global[2], buf_new[2], buf_type[7];
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02005584
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02005585 vim_snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE);
Bram Moolenaard7c96872019-06-15 17:12:48 +02005586 vim_snprintf((char *)buf_old_global, 2, "%d",
5587 old_global_value ? TRUE: FALSE);
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02005588 vim_snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE);
Bram Moolenaard7c96872019-06-15 17:12:48 +02005589 vim_snprintf((char *)buf_type, 7, "%s",
5590 (opt_flags & OPT_LOCAL) ? "local" : "global");
Bram Moolenaar53744302015-07-17 17:38:22 +02005591 set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
5592 set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
5593 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02005594 if (opt_flags & OPT_LOCAL)
5595 {
5596 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
5597 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
5598 }
5599 if (opt_flags & OPT_GLOBAL)
5600 {
5601 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
5602 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
5603 }
5604 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
5605 {
5606 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
5607 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
5608 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
5609 }
5610 if (opt_flags & OPT_MODELINE)
5611 {
5612 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
5613 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
5614 }
5615 apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
5616 NULL, FALSE, NULL);
Bram Moolenaar53744302015-07-17 17:38:22 +02005617 reset_v_option_vars();
5618 }
5619#endif
5620
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621 comp_col(); /* in case 'ruler' or 'showcmd' changed */
Bram Moolenaar913077c2012-03-28 19:59:04 +02005622 if (curwin->w_curswant != MAXCOL
Bram Moolenaar488eb262015-03-13 11:23:50 +01005623 && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaar913077c2012-03-28 19:59:04 +02005624 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 check_redraw(options[opt_idx].flags);
5626
5627 return NULL;
5628}
5629
5630/*
5631 * Set the value of a number option, and take care of side effects.
5632 * Returns NULL for success, or an error message for an error.
5633 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005634 static char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01005635set_num_option(
5636 int opt_idx, /* index in options[] table */
5637 char_u *varp, /* pointer to the option variable */
5638 long value, /* new value */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005639 char *errbuf, /* buffer for error messages */
Bram Moolenaar9b578142016-01-30 19:39:49 +01005640 size_t errbuflen, /* length of "errbuf" */
5641 int opt_flags) /* OPT_LOCAL, OPT_GLOBAL and
Bram Moolenaar071d4272004-06-13 20:20:40 +00005642 OPT_MODELINE */
5643{
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005644 char *errmsg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005645 long old_value = *(long *)varp;
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005646#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02005647 long old_global_value = 0; // only used when setting a local and
5648 // global option
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005649#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02005650 long old_Rows = Rows; // remember old Rows
5651 long old_Columns = Columns; // remember old Columns
Bram Moolenaar071d4272004-06-13 20:20:40 +00005652 long *pp = (long *)varp;
5653
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005654 /* Disallow changing some options from secure mode. */
5655 if ((secure
5656#ifdef HAVE_SANDBOX
5657 || sandbox != 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00005658#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005659 ) && (options[opt_idx].flags & P_SECURE))
5660 return e_secure;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005661
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005662#if defined(FEAT_EVAL)
Bram Moolenaard7c96872019-06-15 17:12:48 +02005663 // Save the global value before changing anything. This is needed as for
5664 // a global-only option setting the "local value" infact sets the global
5665 // value (since there is only one value).
5666 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
Bram Moolenaar983f2f12019-06-16 16:41:41 +02005667 old_global_value = *(long *)get_varp_scope(&(options[opt_idx]),
5668 OPT_GLOBAL);
5669#endif
Bram Moolenaard7c96872019-06-15 17:12:48 +02005670
Bram Moolenaar071d4272004-06-13 20:20:40 +00005671 *pp = value;
5672#ifdef FEAT_EVAL
5673 /* Remember where the option was set. */
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02005674 set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005675#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00005676#ifdef FEAT_GUI
5677 need_mouse_correct = TRUE;
5678#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005679
Bram Moolenaar14f24742012-08-08 18:01:05 +02005680 if (curbuf->b_p_sw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005681 {
5682 errmsg = e_positive;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005683#ifdef FEAT_VARTABS
5684 // Use the first 'vartabstop' value, or 'tabstop' if vts isn't in use.
5685 curbuf->b_p_sw = tabstop_count(curbuf->b_p_vts_array) > 0
5686 ? tabstop_first(curbuf->b_p_vts_array)
5687 : curbuf->b_p_ts;
5688#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005689 curbuf->b_p_sw = curbuf->b_p_ts;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02005690#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005691 }
5692
5693 /*
5694 * Number options that need some action when changed
5695 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005696 if (pp == &p_wh || pp == &p_hh)
5697 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02005698 // 'winheight' and 'helpheight'
Bram Moolenaar071d4272004-06-13 20:20:40 +00005699 if (p_wh < 1)
5700 {
5701 errmsg = e_positive;
5702 p_wh = 1;
5703 }
5704 if (p_wmh > p_wh)
5705 {
5706 errmsg = e_winheight;
5707 p_wh = p_wmh;
5708 }
5709 if (p_hh < 0)
5710 {
5711 errmsg = e_positive;
5712 p_hh = 0;
5713 }
5714
5715 /* Change window height NOW */
Bram Moolenaar459ca562016-11-10 18:16:33 +01005716 if (!ONE_WINDOW)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005717 {
5718 if (pp == &p_wh && curwin->w_height < p_wh)
5719 win_setheight((int)p_wh);
5720 if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh)
5721 win_setheight((int)p_hh);
5722 }
5723 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005724 else if (pp == &p_wmh)
5725 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02005726 // 'winminheight'
Bram Moolenaar071d4272004-06-13 20:20:40 +00005727 if (p_wmh < 0)
5728 {
5729 errmsg = e_positive;
5730 p_wmh = 0;
5731 }
5732 if (p_wmh > p_wh)
5733 {
5734 errmsg = e_winheight;
5735 p_wmh = p_wh;
5736 }
5737 win_setminheight();
5738 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00005739 else if (pp == &p_wiw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005740 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02005741 // 'winwidth'
Bram Moolenaar071d4272004-06-13 20:20:40 +00005742 if (p_wiw < 1)
5743 {
5744 errmsg = e_positive;
5745 p_wiw = 1;
5746 }
5747 if (p_wmw > p_wiw)
5748 {
5749 errmsg = e_winwidth;
5750 p_wiw = p_wmw;
5751 }
5752
5753 /* Change window width NOW */
Bram Moolenaar459ca562016-11-10 18:16:33 +01005754 if (!ONE_WINDOW && curwin->w_width < p_wiw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005755 win_setwidth((int)p_wiw);
5756 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005757 else if (pp == &p_wmw)
5758 {
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02005759 // 'winminwidth'
Bram Moolenaar071d4272004-06-13 20:20:40 +00005760 if (p_wmw < 0)
5761 {
5762 errmsg = e_positive;
5763 p_wmw = 0;
5764 }
5765 if (p_wmw > p_wiw)
5766 {
5767 errmsg = e_winwidth;
5768 p_wmw = p_wiw;
5769 }
Bram Moolenaar1c3c1042018-06-12 16:49:30 +02005770 win_setminwidth();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005771 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005772
Bram Moolenaar071d4272004-06-13 20:20:40 +00005773 /* (re)set last window status line */
5774 else if (pp == &p_ls)
5775 {
5776 last_status(FALSE);
5777 }
Bram Moolenaar4c7ed462006-02-15 22:18:42 +00005778
5779 /* (re)set tab page line */
Bram Moolenaarfaa959a2006-02-20 21:37:40 +00005780 else if (pp == &p_stal)
Bram Moolenaar4c7ed462006-02-15 22:18:42 +00005781 {
5782 shell_new_rows(); /* recompute window positions and heights */
5783 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005784
5785#ifdef FEAT_GUI
5786 else if (pp == &p_linespace)
5787 {
Bram Moolenaar02743632005-07-25 20:42:36 +00005788 /* Recompute gui.char_height and resize the Vim window to keep the
5789 * same number of lines. */
5790 if (gui.in_use && gui_mch_adjust_charheight() == OK)
Bram Moolenaar3964b7e2006-03-27 20:59:33 +00005791 gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005792 }
5793#endif
5794
5795#ifdef FEAT_FOLDING
5796 /* 'foldlevel' */
5797 else if (pp == &curwin->w_p_fdl)
5798 {
5799 if (curwin->w_p_fdl < 0)
5800 curwin->w_p_fdl = 0;
5801 newFoldLevel();
5802 }
5803
Bram Moolenaar1f26d2f2009-02-11 10:35:36 +00005804 /* 'foldminlines' */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005805 else if (pp == &curwin->w_p_fml)
5806 {
5807 foldUpdateAll(curwin);
5808 }
5809
5810 /* 'foldnestmax' */
5811 else if (pp == &curwin->w_p_fdn)
5812 {
5813 if (foldmethodIsSyntax(curwin) || foldmethodIsIndent(curwin))
5814 foldUpdateAll(curwin);
5815 }
5816
5817 /* 'foldcolumn' */
5818 else if (pp == &curwin->w_p_fdc)
5819 {
5820 if (curwin->w_p_fdc < 0)
5821 {
5822 errmsg = e_positive;
5823 curwin->w_p_fdc = 0;
5824 }
5825 else if (curwin->w_p_fdc > 12)
5826 {
5827 errmsg = e_invarg;
5828 curwin->w_p_fdc = 12;
5829 }
5830 }
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01005831#endif /* FEAT_FOLDING */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005832
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01005833#if defined(FEAT_FOLDING) || defined(FEAT_CINDENT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834 /* 'shiftwidth' or 'tabstop' */
5835 else if (pp == &curbuf->b_p_sw || pp == &curbuf->b_p_ts)
5836 {
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01005837# ifdef FEAT_FOLDING
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838 if (foldmethodIsIndent(curwin))
5839 foldUpdateAll(curwin);
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01005840# endif
5841# ifdef FEAT_CINDENT
5842 /* When 'shiftwidth' changes, or it's zero and 'tabstop' changes:
5843 * parse 'cinoptions'. */
5844 if (pp == &curbuf->b_p_sw || curbuf->b_p_sw == 0)
5845 parse_cino(curbuf);
5846# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005847 }
Bram Moolenaar6bcbcc52013-11-05 07:13:41 +01005848#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005849
Bram Moolenaar362e1a32006-03-06 23:29:24 +00005850 /* 'maxcombine' */
5851 else if (pp == &p_mco)
5852 {
5853 if (p_mco > MAX_MCO)
5854 p_mco = MAX_MCO;
5855 else if (p_mco < 0)
5856 p_mco = 0;
5857 screenclear(); /* will re-allocate the screen */
5858 }
Bram Moolenaar362e1a32006-03-06 23:29:24 +00005859
Bram Moolenaar071d4272004-06-13 20:20:40 +00005860 else if (pp == &curbuf->b_p_iminsert)
5861 {
5862 if (curbuf->b_p_iminsert < 0 || curbuf->b_p_iminsert > B_IMODE_LAST)
5863 {
5864 errmsg = e_invarg;
5865 curbuf->b_p_iminsert = B_IMODE_NONE;
5866 }
5867 p_iminsert = curbuf->b_p_iminsert;
5868 if (termcap_active) /* don't do this in the alternate screen */
5869 showmode();
Bram Moolenaar4033c552017-09-16 20:54:51 +02005870#if defined(FEAT_KEYMAP)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005871 /* Show/unshow value of 'keymap' in status lines. */
5872 status_redraw_curbuf();
5873#endif
5874 }
5875
Bram Moolenaar5c6dbcb2017-08-30 22:00:20 +02005876#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
5877 /* 'imstyle' */
5878 else if (pp == &p_imst)
5879 {
5880 if (p_imst != IM_ON_THE_SPOT && p_imst != IM_OVER_THE_SPOT)
5881 errmsg = e_invarg;
5882 }
5883#endif
5884
Bram Moolenaar4399ef42005-02-12 14:29:27 +00005885 else if (pp == &p_window)
5886 {
5887 if (p_window < 1)
5888 p_window = 1;
5889 else if (p_window >= Rows)
5890 p_window = Rows - 1;
5891 }
5892
Bram Moolenaar071d4272004-06-13 20:20:40 +00005893 else if (pp == &curbuf->b_p_imsearch)
5894 {
5895 if (curbuf->b_p_imsearch < -1 || curbuf->b_p_imsearch > B_IMODE_LAST)
5896 {
5897 errmsg = e_invarg;
5898 curbuf->b_p_imsearch = B_IMODE_NONE;
5899 }
5900 p_imsearch = curbuf->b_p_imsearch;
5901 }
5902
5903#ifdef FEAT_TITLE
5904 /* if 'titlelen' has changed, redraw the title */
5905 else if (pp == &p_titlelen)
5906 {
5907 if (p_titlelen < 0)
5908 {
5909 errmsg = e_positive;
5910 p_titlelen = 85;
5911 }
5912 if (starting != NO_SCREEN && old_value != p_titlelen)
5913 need_maketitle = TRUE;
5914 }
5915#endif
5916
5917 /* if p_ch changed value, change the command line height */
5918 else if (pp == &p_ch)
5919 {
5920 if (p_ch < 1)
5921 {
5922 errmsg = e_positive;
5923 p_ch = 1;
5924 }
Bram Moolenaar719939c2007-09-25 12:51:28 +00005925 if (p_ch > Rows - min_rows() + 1)
5926 p_ch = Rows - min_rows() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005927
5928 /* Only compute the new window layout when startup has been
5929 * completed. Otherwise the frame sizes may be wrong. */
5930 if (p_ch != old_value && full_screen
5931#ifdef FEAT_GUI
5932 && !gui.starting
5933#endif
5934 )
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00005935 command_height();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005936 }
5937
5938 /* when 'updatecount' changes from zero to non-zero, open swap files */
5939 else if (pp == &p_uc)
5940 {
5941 if (p_uc < 0)
5942 {
5943 errmsg = e_positive;
5944 p_uc = 100;
5945 }
5946 if (p_uc && !old_value)
5947 ml_open_files();
5948 }
Bram Moolenaar860cae12010-06-05 23:22:07 +02005949#ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005950 else if (pp == &curwin->w_p_cole)
Bram Moolenaar860cae12010-06-05 23:22:07 +02005951 {
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005952 if (curwin->w_p_cole < 0)
Bram Moolenaar860cae12010-06-05 23:22:07 +02005953 {
5954 errmsg = e_positive;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005955 curwin->w_p_cole = 0;
Bram Moolenaar860cae12010-06-05 23:22:07 +02005956 }
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005957 else if (curwin->w_p_cole > 3)
Bram Moolenaar860cae12010-06-05 23:22:07 +02005958 {
5959 errmsg = e_invarg;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02005960 curwin->w_p_cole = 3;
Bram Moolenaar860cae12010-06-05 23:22:07 +02005961 }
5962 }
5963#endif
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00005964#ifdef MZSCHEME_GUI_THREADS
Bram Moolenaar325b7a22004-07-05 15:58:32 +00005965 else if (pp == &p_mzq)
5966 mzvim_reset_timer();
5967#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005968
Bram Moolenaarf42dd3c2017-01-28 16:06:38 +01005969#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
5970 /* 'pyxversion' */
5971 else if (pp == &p_pyx)
5972 {
5973 if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3)
5974 errmsg = e_invarg;
5975 }
5976#endif
5977
Bram Moolenaar071d4272004-06-13 20:20:40 +00005978 /* sync undo before 'undolevels' changes */
5979 else if (pp == &p_ul)
5980 {
5981 /* use the old value, otherwise u_sync() may not work properly */
5982 p_ul = old_value;
Bram Moolenaar779b74b2006-04-10 14:55:34 +00005983 u_sync(TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005984 p_ul = value;
5985 }
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01005986 else if (pp == &curbuf->b_p_ul)
5987 {
5988 /* use the old value, otherwise u_sync() may not work properly */
5989 curbuf->b_p_ul = old_value;
5990 u_sync(TRUE);
5991 curbuf->b_p_ul = value;
5992 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005993
Bram Moolenaar592e0a22004-07-03 16:05:59 +00005994#ifdef FEAT_LINEBREAK
5995 /* 'numberwidth' must be positive */
5996 else if (pp == &curwin->w_p_nuw)
5997 {
5998 if (curwin->w_p_nuw < 1)
5999 {
6000 errmsg = e_positive;
6001 curwin->w_p_nuw = 1;
6002 }
Bram Moolenaarf8a07122019-07-01 22:06:07 +02006003 if (curwin->w_p_nuw > 20)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00006004 {
6005 errmsg = e_invarg;
Bram Moolenaarf8a07122019-07-01 22:06:07 +02006006 curwin->w_p_nuw = 20;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00006007 }
Bram Moolenaar1e7813a2015-03-31 18:31:03 +02006008 curwin->w_nrwidth_line_count = 0; /* trigger a redraw */
Bram Moolenaar592e0a22004-07-03 16:05:59 +00006009 }
6010#endif
6011
Bram Moolenaar1a384422010-07-14 19:53:30 +02006012 else if (pp == &curbuf->b_p_tw)
6013 {
6014 if (curbuf->b_p_tw < 0)
6015 {
6016 errmsg = e_positive;
6017 curbuf->b_p_tw = 0;
6018 }
6019#ifdef FEAT_SYN_HL
Bram Moolenaar1a384422010-07-14 19:53:30 +02006020 {
6021 win_T *wp;
6022 tabpage_T *tp;
6023
6024 FOR_ALL_TAB_WINDOWS(tp, wp)
6025 check_colorcolumn(wp);
6026 }
Bram Moolenaar1a384422010-07-14 19:53:30 +02006027#endif
6028 }
6029
Bram Moolenaar071d4272004-06-13 20:20:40 +00006030 /*
6031 * Check the bounds for numeric options here
6032 */
6033 if (Rows < min_rows() && full_screen)
6034 {
6035 if (errbuf != NULL)
6036 {
Bram Moolenaar555b2802005-05-19 21:08:39 +00006037 vim_snprintf((char *)errbuf, errbuflen,
6038 _("E593: Need at least %d lines"), min_rows());
Bram Moolenaar071d4272004-06-13 20:20:40 +00006039 errmsg = errbuf;
6040 }
6041 Rows = min_rows();
6042 }
6043 if (Columns < MIN_COLUMNS && full_screen)
6044 {
6045 if (errbuf != NULL)
6046 {
Bram Moolenaar555b2802005-05-19 21:08:39 +00006047 vim_snprintf((char *)errbuf, errbuflen,
6048 _("E594: Need at least %d columns"), MIN_COLUMNS);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006049 errmsg = errbuf;
6050 }
6051 Columns = MIN_COLUMNS;
6052 }
Bram Moolenaare057d402013-06-30 17:51:51 +02006053 limit_screen_size();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054
Bram Moolenaar071d4272004-06-13 20:20:40 +00006055 /*
6056 * If the screen (shell) height has been changed, assume it is the
6057 * physical screenheight.
6058 */
6059 if (old_Rows != Rows || old_Columns != Columns)
6060 {
6061 /* Changing the screen size is not allowed while updating the screen. */
6062 if (updating_screen)
6063 *pp = old_value;
6064 else if (full_screen
6065#ifdef FEAT_GUI
6066 && !gui.starting
6067#endif
6068 )
6069 set_shellsize((int)Columns, (int)Rows, TRUE);
6070 else
6071 {
6072 /* Postpone the resizing; check the size and cmdline position for
6073 * messages. */
6074 check_shellsize();
6075 if (cmdline_row > Rows - p_ch && Rows > p_ch)
6076 cmdline_row = Rows - p_ch;
6077 }
Bram Moolenaard68071d2006-05-02 22:08:30 +00006078 if (p_window >= Rows || !option_was_set((char_u *)"window"))
Bram Moolenaar4399ef42005-02-12 14:29:27 +00006079 p_window = Rows - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006080 }
6081
Bram Moolenaar071d4272004-06-13 20:20:40 +00006082 if (curbuf->b_p_ts <= 0)
6083 {
6084 errmsg = e_positive;
6085 curbuf->b_p_ts = 8;
6086 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006087 if (p_tm < 0)
6088 {
6089 errmsg = e_positive;
6090 p_tm = 0;
6091 }
6092 if ((curwin->w_p_scr <= 0
6093 || (curwin->w_p_scr > curwin->w_height
6094 && curwin->w_height > 0))
6095 && full_screen)
6096 {
6097 if (pp == &(curwin->w_p_scr))
6098 {
6099 if (curwin->w_p_scr != 0)
6100 errmsg = e_scroll;
6101 win_comp_scroll(curwin);
6102 }
6103 /* If 'scroll' became invalid because of a side effect silently adjust
6104 * it. */
6105 else if (curwin->w_p_scr <= 0)
6106 curwin->w_p_scr = 1;
6107 else /* curwin->w_p_scr > curwin->w_height */
6108 curwin->w_p_scr = curwin->w_height;
6109 }
Bram Moolenaar991e10f2008-10-02 20:48:41 +00006110 if (p_hi < 0)
6111 {
6112 errmsg = e_positive;
6113 p_hi = 0;
6114 }
Bram Moolenaar78159bb2014-06-25 11:48:54 +02006115 else if (p_hi > 10000)
6116 {
6117 errmsg = e_invarg;
6118 p_hi = 10000;
6119 }
Bram Moolenaarfbc0d2e2013-05-19 19:40:29 +02006120 if (p_re < 0 || p_re > 2)
6121 {
6122 errmsg = e_invarg;
6123 p_re = 0;
6124 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006125 if (p_report < 0)
6126 {
6127 errmsg = e_positive;
6128 p_report = 1;
6129 }
Bram Moolenaar1e015462005-09-25 22:16:38 +00006130 if ((p_sj < -100 || p_sj >= Rows) && full_screen)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006131 {
6132 if (Rows != old_Rows) /* Rows changed, just adjust p_sj */
6133 p_sj = Rows / 2;
6134 else
6135 {
6136 errmsg = e_scroll;
6137 p_sj = 1;
6138 }
6139 }
6140 if (p_so < 0 && full_screen)
6141 {
Bram Moolenaar375e3392019-01-31 18:26:10 +01006142 errmsg = e_positive;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006143 p_so = 0;
6144 }
6145 if (p_siso < 0 && full_screen)
6146 {
6147 errmsg = e_positive;
6148 p_siso = 0;
6149 }
6150#ifdef FEAT_CMDWIN
6151 if (p_cwh < 1)
6152 {
6153 errmsg = e_positive;
6154 p_cwh = 1;
6155 }
6156#endif
6157 if (p_ut < 0)
6158 {
6159 errmsg = e_positive;
6160 p_ut = 2000;
6161 }
6162 if (p_ss < 0)
6163 {
6164 errmsg = e_positive;
6165 p_ss = 0;
6166 }
6167
6168 /* May set global value for local option. */
6169 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
6170 *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = *pp;
6171
6172 options[opt_idx].flags |= P_WAS_SET;
6173
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006174#if defined(FEAT_EVAL)
Bram Moolenaar3f3fb0b2018-09-21 11:59:32 +02006175 // Don't do this while starting up, failure or recursively.
6176 if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL)
Bram Moolenaar53744302015-07-17 17:38:22 +02006177 {
Bram Moolenaard7c96872019-06-15 17:12:48 +02006178 char_u buf_old[11], buf_old_global[11], buf_new[11], buf_type[7];
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02006179 vim_snprintf((char *)buf_old, 10, "%ld", old_value);
Bram Moolenaard7c96872019-06-15 17:12:48 +02006180 vim_snprintf((char *)buf_old_global, 10, "%ld", old_global_value);
Bram Moolenaarfb9bc482015-07-17 22:04:48 +02006181 vim_snprintf((char *)buf_new, 10, "%ld", value);
6182 vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
Bram Moolenaar53744302015-07-17 17:38:22 +02006183 set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
6184 set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
6185 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
Bram Moolenaard7c96872019-06-15 17:12:48 +02006186 if (opt_flags & OPT_LOCAL)
6187 {
6188 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
6189 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
6190 }
6191 if (opt_flags & OPT_GLOBAL)
6192 {
6193 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
6194 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
6195 }
6196 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
6197 {
6198 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
6199 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
6200 set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
6201 }
6202 if (opt_flags & OPT_MODELINE)
6203 {
6204 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
6205 set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
6206 }
6207 apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
6208 NULL, FALSE, NULL);
Bram Moolenaar53744302015-07-17 17:38:22 +02006209 reset_v_option_vars();
6210 }
6211#endif
6212
Bram Moolenaar071d4272004-06-13 20:20:40 +00006213 comp_col(); /* in case 'columns' or 'ls' changed */
Bram Moolenaar913077c2012-03-28 19:59:04 +02006214 if (curwin->w_curswant != MAXCOL
Bram Moolenaar488eb262015-03-13 11:23:50 +01006215 && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0)
Bram Moolenaar913077c2012-03-28 19:59:04 +02006216 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006217 check_redraw(options[opt_idx].flags);
6218
6219 return errmsg;
6220}
6221
6222/*
6223 * Called after an option changed: check if something needs to be redrawn.
6224 */
6225 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006226check_redraw(long_u flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006227{
6228 /* Careful: P_RCLR and P_RALL are a combination of other P_ flags */
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006229 int doclear = (flags & P_RCLR) == P_RCLR;
6230 int all = ((flags & P_RALL) == P_RALL || doclear);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006231
Bram Moolenaar071d4272004-06-13 20:20:40 +00006232 if ((flags & P_RSTAT) || all) /* mark all status lines dirty */
6233 status_redraw_all();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006234
6235 if ((flags & P_RBUF) || (flags & P_RWIN) || all)
6236 changed_window_setting();
6237 if (flags & P_RBUF)
6238 redraw_curbuf_later(NOT_VALID);
Bram Moolenaara2477fd2016-12-03 15:13:20 +01006239 if (flags & P_RWINONLY)
6240 redraw_later(NOT_VALID);
Bram Moolenaar70b2a562012-01-10 22:26:17 +01006241 if (doclear)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006242 redraw_all_later(CLEAR);
6243 else if (all)
6244 redraw_all_later(NOT_VALID);
6245}
6246
6247/*
6248 * Find index for option 'arg'.
6249 * Return -1 if not found.
6250 */
6251 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006252findoption(char_u *arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253{
6254 int opt_idx;
6255 char *s, *p;
6256 static short quick_tab[27] = {0, 0}; /* quick access table */
6257 int is_term_opt;
6258
6259 /*
6260 * For first call: Initialize the quick-access table.
6261 * It contains the index for the first option that starts with a certain
6262 * letter. There are 26 letters, plus the first "t_" option.
6263 */
6264 if (quick_tab[1] == 0)
6265 {
6266 p = options[0].fullname;
6267 for (opt_idx = 1; (s = options[opt_idx].fullname) != NULL; opt_idx++)
6268 {
6269 if (s[0] != p[0])
6270 {
6271 if (s[0] == 't' && s[1] == '_')
6272 quick_tab[26] = opt_idx;
6273 else
6274 quick_tab[CharOrdLow(s[0])] = opt_idx;
6275 }
6276 p = s;
6277 }
6278 }
6279
6280 /*
6281 * Check for name starting with an illegal character.
6282 */
6283#ifdef EBCDIC
6284 if (!islower(arg[0]))
6285#else
6286 if (arg[0] < 'a' || arg[0] > 'z')
6287#endif
6288 return -1;
6289
6290 is_term_opt = (arg[0] == 't' && arg[1] == '_');
6291 if (is_term_opt)
6292 opt_idx = quick_tab[26];
6293 else
6294 opt_idx = quick_tab[CharOrdLow(arg[0])];
6295 for ( ; (s = options[opt_idx].fullname) != NULL; opt_idx++)
6296 {
6297 if (STRCMP(arg, s) == 0) /* match full name */
6298 break;
6299 }
6300 if (s == NULL && !is_term_opt)
6301 {
6302 opt_idx = quick_tab[CharOrdLow(arg[0])];
6303 for ( ; options[opt_idx].fullname != NULL; opt_idx++)
6304 {
6305 s = options[opt_idx].shortname;
6306 if (s != NULL && STRCMP(arg, s) == 0) /* match short name */
6307 break;
6308 s = NULL;
6309 }
6310 }
6311 if (s == NULL)
6312 opt_idx = -1;
6313 return opt_idx;
6314}
6315
Bram Moolenaar325b7a22004-07-05 15:58:32 +00006316#if defined(FEAT_EVAL) || defined(FEAT_TCL) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006317/*
6318 * Get the value for an option.
6319 *
6320 * Returns:
6321 * Number or Toggle option: 1, *numval gets value.
6322 * String option: 0, *stringval gets allocated string.
6323 * Hidden Number or Toggle option: -1.
6324 * hidden String option: -2.
6325 * unknown option: -3.
6326 */
6327 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006328get_option_value(
6329 char_u *name,
6330 long *numval,
6331 char_u **stringval, /* NULL when only checking existence */
6332 int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006333{
6334 int opt_idx;
6335 char_u *varp;
6336
6337 opt_idx = findoption(name);
6338 if (opt_idx < 0) /* unknown option */
Bram Moolenaare353c402017-02-04 19:49:16 +01006339 {
6340 int key;
6341
6342 if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006343 && (key = find_key_option(name, FALSE)) != 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01006344 {
6345 char_u key_name[2];
6346 char_u *p;
6347
6348 if (key < 0)
6349 {
6350 key_name[0] = KEY2TERMCAP0(key);
6351 key_name[1] = KEY2TERMCAP1(key);
6352 }
6353 else
6354 {
6355 key_name[0] = KS_KEY;
6356 key_name[1] = (key & 0xff);
6357 }
6358 p = find_termcode(key_name);
6359 if (p != NULL)
6360 {
6361 if (stringval != NULL)
6362 *stringval = vim_strsave(p);
6363 return 0;
6364 }
6365 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006366 return -3;
Bram Moolenaare353c402017-02-04 19:49:16 +01006367 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006368
6369 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
6370
6371 if (options[opt_idx].flags & P_STRING)
6372 {
6373 if (varp == NULL) /* hidden option */
6374 return -2;
6375 if (stringval != NULL)
6376 {
6377#ifdef FEAT_CRYPT
6378 /* never return the value of the crypt key */
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00006379 if ((char_u **)varp == &curbuf->b_p_key
6380 && **(char_u **)(varp) != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006381 *stringval = vim_strsave((char_u *)"*****");
6382 else
6383#endif
6384 *stringval = vim_strsave(*(char_u **)(varp));
6385 }
6386 return 0;
6387 }
6388
6389 if (varp == NULL) /* hidden option */
6390 return -1;
6391 if (options[opt_idx].flags & P_NUM)
6392 *numval = *(long *)varp;
6393 else
6394 {
6395 /* Special case: 'modified' is b_changed, but we also want to consider
6396 * it set when 'ff' or 'fenc' changed. */
6397 if ((int *)varp == &curbuf->b_changed)
6398 *numval = curbufIsChanged();
6399 else
Bram Moolenaar2acfbed2016-07-01 23:14:02 +02006400 *numval = (long) *(int *)varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006401 }
6402 return 1;
6403}
6404#endif
6405
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006406#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006407/*
6408 * Returns the option attributes and its value. Unlike the above function it
6409 * will return either global value or local value of the option depending on
6410 * what was requested, but it will never return global value if it was
6411 * requested to return local one and vice versa. Neither it will return
6412 * buffer-local value if it was requested to return window-local one.
6413 *
6414 * Pretends that option is absent if it is not present in the requested scope
6415 * (i.e. has no global, window-local or buffer-local value depending on
6416 * opt_type). Uses
6417 *
6418 * Returned flags:
Bram Moolenaar75a8d742014-05-07 15:10:21 +02006419 * 0 hidden or unknown option, also option that does not have requested
6420 * type (see SREQ_* in vim.h)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006421 * see SOPT_* in vim.h for other flags
6422 *
6423 * Possible opt_type values: see SREQ_* in vim.h
6424 */
6425 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006426get_option_value_strict(
6427 char_u *name,
6428 long *numval,
6429 char_u **stringval, /* NULL when only obtaining attributes */
6430 int opt_type,
6431 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006432{
6433 int opt_idx;
Bram Moolenaar68001862013-05-11 13:45:05 +02006434 char_u *varp = NULL;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006435 struct vimoption *p;
6436 int r = 0;
6437
6438 opt_idx = findoption(name);
6439 if (opt_idx < 0)
6440 return 0;
6441
6442 p = &(options[opt_idx]);
6443
6444 /* Hidden option */
6445 if (p->var == NULL)
6446 return 0;
6447
6448 if (p->flags & P_BOOL)
6449 r |= SOPT_BOOL;
6450 else if (p->flags & P_NUM)
6451 r |= SOPT_NUM;
6452 else if (p->flags & P_STRING)
6453 r |= SOPT_STRING;
6454
6455 if (p->indir == PV_NONE)
6456 {
6457 if (opt_type == SREQ_GLOBAL)
6458 r |= SOPT_GLOBAL;
6459 else
6460 return 0; /* Did not request global-only option */
6461 }
6462 else
6463 {
6464 if (p->indir & PV_BOTH)
6465 r |= SOPT_GLOBAL;
6466 else if (opt_type == SREQ_GLOBAL)
6467 return 0; /* Requested global option */
6468
6469 if (p->indir & PV_WIN)
6470 {
6471 if (opt_type == SREQ_BUF)
6472 return 0; /* Did not request window-local option */
6473 else
6474 r |= SOPT_WIN;
6475 }
6476 else if (p->indir & PV_BUF)
6477 {
6478 if (opt_type == SREQ_WIN)
6479 return 0; /* Did not request buffer-local option */
6480 else
6481 r |= SOPT_BUF;
6482 }
6483 }
6484
6485 if (stringval == NULL)
6486 return r;
6487
6488 if (opt_type == SREQ_GLOBAL)
6489 varp = p->var;
6490 else
6491 {
6492 if (opt_type == SREQ_BUF)
6493 {
6494 /* Special case: 'modified' is b_changed, but we also want to
6495 * consider it set when 'ff' or 'fenc' changed. */
6496 if (p->indir == PV_MOD)
6497 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02006498 *numval = bufIsChanged((buf_T *)from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006499 varp = NULL;
6500 }
6501#ifdef FEAT_CRYPT
6502 else if (p->indir == PV_KEY)
6503 {
6504 /* never return the value of the crypt key */
6505 *stringval = NULL;
6506 varp = NULL;
6507 }
6508#endif
6509 else
6510 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02006511 buf_T *save_curbuf = curbuf;
6512
6513 // only getting a pointer, no need to use aucmd_prepbuf()
6514 curbuf = (buf_T *)from;
6515 curwin->w_buffer = curbuf;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006516 varp = get_varp(p);
Bram Moolenaardefe6422018-06-24 15:14:07 +02006517 curbuf = save_curbuf;
6518 curwin->w_buffer = curbuf;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006519 }
6520 }
6521 else if (opt_type == SREQ_WIN)
6522 {
Bram Moolenaardefe6422018-06-24 15:14:07 +02006523 win_T *save_curwin = curwin;
6524
6525 curwin = (win_T *)from;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006526 curbuf = curwin->w_buffer;
6527 varp = get_varp(p);
6528 curwin = save_curwin;
6529 curbuf = curwin->w_buffer;
6530 }
6531 if (varp == p->var)
6532 return (r | SOPT_UNSET);
6533 }
6534
6535 if (varp != NULL)
6536 {
6537 if (p->flags & P_STRING)
6538 *stringval = vim_strsave(*(char_u **)(varp));
6539 else if (p->flags & P_NUM)
6540 *numval = *(long *) varp;
6541 else
6542 *numval = *(int *)varp;
6543 }
6544
6545 return r;
6546}
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006547
6548/*
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02006549 * Iterate over options. First argument is a pointer to a pointer to a
6550 * structure inside options[] array, second is option type like in the above
6551 * function.
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006552 *
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02006553 * If first argument points to NULL it is assumed that iteration just started
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006554 * and caller needs the very first value.
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02006555 * If first argument points to the end marker function returns NULL and sets
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006556 * first argument to NULL.
6557 *
6558 * Returns full option name for current option on each call.
6559 */
6560 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01006561option_iter_next(void **option, int opt_type)
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006562{
6563 struct vimoption *ret = NULL;
6564 do
6565 {
6566 if (*option == NULL)
6567 *option = (void *) options;
6568 else if (((struct vimoption *) (*option))->fullname == NULL)
6569 {
6570 *option = NULL;
6571 return NULL;
6572 }
6573 else
6574 *option = (void *) (((struct vimoption *) (*option)) + 1);
6575
6576 ret = ((struct vimoption *) (*option));
6577
6578 /* Hidden option */
6579 if (ret->var == NULL)
6580 {
6581 ret = NULL;
6582 continue;
6583 }
6584
6585 switch (opt_type)
6586 {
6587 case SREQ_GLOBAL:
6588 if (!(ret->indir == PV_NONE || ret->indir & PV_BOTH))
6589 ret = NULL;
6590 break;
6591 case SREQ_BUF:
6592 if (!(ret->indir & PV_BUF))
6593 ret = NULL;
6594 break;
6595 case SREQ_WIN:
6596 if (!(ret->indir & PV_WIN))
6597 ret = NULL;
6598 break;
6599 default:
Bram Moolenaar95f09602016-11-10 20:01:45 +01006600 internal_error("option_iter_next()");
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006601 return NULL;
6602 }
6603 }
6604 while (ret == NULL);
6605
6606 return (char_u *)ret->fullname;
6607}
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006608#endif
6609
Bram Moolenaar071d4272004-06-13 20:20:40 +00006610/*
6611 * Set the value of option "name".
6612 * Use "string" for string options, use "number" for other options.
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006613 *
6614 * Returns NULL on success or error message on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006615 */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006616 char *
Bram Moolenaar9b578142016-01-30 19:39:49 +01006617set_option_value(
6618 char_u *name,
6619 long number,
6620 char_u *string,
6621 int opt_flags) /* OPT_LOCAL or 0 (both) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006622{
6623 int opt_idx;
6624 char_u *varp;
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00006625 long_u flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006626
6627 opt_idx = findoption(name);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00006628 if (opt_idx < 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01006629 {
6630 int key;
6631
6632 if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006633 && (key = find_key_option(name, FALSE)) != 0)
Bram Moolenaare353c402017-02-04 19:49:16 +01006634 {
6635 char_u key_name[2];
6636
6637 if (key < 0)
6638 {
6639 key_name[0] = KEY2TERMCAP0(key);
6640 key_name[1] = KEY2TERMCAP1(key);
6641 }
6642 else
6643 {
6644 key_name[0] = KS_KEY;
6645 key_name[1] = (key & 0xff);
6646 }
6647 add_termcode(key_name, string, FALSE);
6648 if (full_screen)
6649 ttest(FALSE);
6650 redraw_all_later(CLEAR);
6651 return NULL;
6652 }
6653
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006654 semsg(_("E355: Unknown option: %s"), name);
Bram Moolenaare353c402017-02-04 19:49:16 +01006655 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006656 else
6657 {
6658 flags = options[opt_idx].flags;
6659#ifdef HAVE_SANDBOX
6660 /* Disallow changing some options in the sandbox */
6661 if (sandbox > 0 && (flags & P_SECURE))
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006662 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006663 emsg(_(e_sandbox));
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006664 return NULL;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006665 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006666#endif
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006667 if (flags & P_STRING)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006668 return set_string_option(opt_idx, string, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006669 else
6670 {
Bram Moolenaarb3163762008-07-08 15:15:08 +00006671 varp = get_varp_scope(&(options[opt_idx]), opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006672 if (varp != NULL) /* hidden option is not changed */
6673 {
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006674 if (number == 0 && string != NULL)
6675 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006676 int idx;
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006677
6678 /* Either we are given a string or we are setting option
6679 * to zero. */
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006680 for (idx = 0; string[idx] == '0'; ++idx)
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006681 ;
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00006682 if (string[idx] != NUL || idx == 0)
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006683 {
6684 /* There's another character after zeros or the string
6685 * is empty. In both cases, we are trying to set a
6686 * num option using a string. */
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006687 semsg(_("E521: Number required: &%s = '%s'"),
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006688 name, string);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006689 return NULL; /* do nothing as we hit an error */
Bram Moolenaar96bb6212007-06-19 18:52:53 +00006690
6691 }
6692 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006693 if (flags & P_NUM)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006694 return set_num_option(opt_idx, varp, number,
Bram Moolenaar555b2802005-05-19 21:08:39 +00006695 NULL, 0, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696 else
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006697 return set_bool_option(opt_idx, varp, (int)number,
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006698 opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006699 }
6700 }
6701 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02006702 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006703}
6704
6705/*
6706 * Get the terminal code for a terminal option.
6707 * Returns NULL when not found.
6708 */
6709 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01006710get_term_code(char_u *tname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006711{
6712 int opt_idx;
6713 char_u *varp;
6714
6715 if (tname[0] != 't' || tname[1] != '_' ||
6716 tname[2] == NUL || tname[3] == NUL)
6717 return NULL;
6718 if ((opt_idx = findoption(tname)) >= 0)
6719 {
6720 varp = get_varp(&(options[opt_idx]));
6721 if (varp != NULL)
6722 varp = *(char_u **)(varp);
6723 return varp;
6724 }
6725 return find_termcode(tname + 2);
6726}
6727
6728 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01006729get_highlight_default(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006730{
6731 int i;
6732
6733 i = findoption((char_u *)"hl");
6734 if (i >= 0)
6735 return options[i].def_val[VI_DEFAULT];
6736 return (char_u *)NULL;
6737}
6738
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006739 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01006740get_encoding_default(void)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006741{
6742 int i;
6743
6744 i = findoption((char_u *)"enc");
6745 if (i >= 0)
6746 return options[i].def_val[VI_DEFAULT];
6747 return (char_u *)NULL;
6748}
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006749
Bram Moolenaar071d4272004-06-13 20:20:40 +00006750/*
6751 * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006752 * When "has_lt" is true there is a '<' before "*arg_arg".
6753 * Returns 0 when the key is not recognized.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006754 */
6755 static int
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006756find_key_option(char_u *arg_arg, int has_lt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006757{
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006758 int key = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006759 int modifiers;
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006760 char_u *arg = arg_arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006761
6762 /*
6763 * Don't use get_special_key_code() for t_xx, we don't want it to call
6764 * add_termcap_entry().
6765 */
6766 if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
6767 key = TERMCAP2KEY(arg[2], arg[3]);
Bram Moolenaar9cf4b502018-07-23 04:12:03 +02006768 else if (has_lt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006769 {
6770 --arg; /* put arg at the '<' */
6771 modifiers = 0;
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02006772 key = find_special_key(&arg, &modifiers, TRUE, TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006773 if (modifiers) /* can't handle modifiers here */
6774 key = 0;
6775 }
6776 return key;
6777}
6778
6779/*
6780 * if 'all' == 0: show changed options
6781 * if 'all' == 1: show all normal options
6782 * if 'all' == 2: show all terminal options
6783 */
6784 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006785showoptions(
6786 int all,
6787 int opt_flags) /* OPT_LOCAL and/or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788{
6789 struct vimoption *p;
6790 int col;
6791 int isterm;
6792 char_u *varp;
6793 struct vimoption **items;
6794 int item_count;
6795 int run;
6796 int row, rows;
6797 int cols;
6798 int i;
6799 int len;
6800
6801#define INC 20
6802#define GAP 3
6803
Bram Moolenaarc799fe22019-05-28 23:08:19 +02006804 items = ALLOC_MULT(struct vimoption *, PARAM_COUNT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006805 if (items == NULL)
6806 return;
6807
6808 /* Highlight title */
6809 if (all == 2)
Bram Moolenaar32526b32019-01-19 17:43:09 +01006810 msg_puts_title(_("\n--- Terminal codes ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006811 else if (opt_flags & OPT_GLOBAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01006812 msg_puts_title(_("\n--- Global option values ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006813 else if (opt_flags & OPT_LOCAL)
Bram Moolenaar32526b32019-01-19 17:43:09 +01006814 msg_puts_title(_("\n--- Local option values ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006815 else
Bram Moolenaar32526b32019-01-19 17:43:09 +01006816 msg_puts_title(_("\n--- Options ---"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006817
6818 /*
6819 * do the loop two times:
6820 * 1. display the short items
6821 * 2. display the long items (only strings and numbers)
6822 */
6823 for (run = 1; run <= 2 && !got_int; ++run)
6824 {
6825 /*
6826 * collect the items in items[]
6827 */
6828 item_count = 0;
6829 for (p = &options[0]; p->fullname != NULL; p++)
6830 {
Bram Moolenaarf86db782018-10-25 13:31:37 +02006831 // apply :filter /pat/
6832 if (message_filtered((char_u *) p->fullname))
6833 continue;
6834
Bram Moolenaar071d4272004-06-13 20:20:40 +00006835 varp = NULL;
6836 isterm = istermoption(p);
6837 if (opt_flags != 0)
6838 {
6839 if (p->indir != PV_NONE && !isterm)
6840 varp = get_varp_scope(p, opt_flags);
6841 }
6842 else
6843 varp = get_varp(p);
6844 if (varp != NULL
6845 && ((all == 2 && isterm)
6846 || (all == 1 && !isterm)
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02006847 || (all == 0 && !optval_default(p, varp, p_cp))))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006848 {
6849 if (p->flags & P_BOOL)
6850 len = 1; /* a toggle option fits always */
6851 else
6852 {
6853 option_value2string(p, opt_flags);
6854 len = (int)STRLEN(p->fullname) + vim_strsize(NameBuff) + 1;
6855 }
6856 if ((len <= INC - GAP && run == 1) ||
6857 (len > INC - GAP && run == 2))
6858 items[item_count++] = p;
6859 }
6860 }
6861
6862 /*
6863 * display the items
6864 */
6865 if (run == 1)
6866 {
6867 cols = (Columns + GAP - 3) / INC;
6868 if (cols == 0)
6869 cols = 1;
6870 rows = (item_count + cols - 1) / cols;
6871 }
6872 else /* run == 2 */
6873 rows = item_count;
6874 for (row = 0; row < rows && !got_int; ++row)
6875 {
6876 msg_putchar('\n'); /* go to next line */
6877 if (got_int) /* 'q' typed in more */
6878 break;
6879 col = 0;
6880 for (i = row; i < item_count; i += rows)
6881 {
6882 msg_col = col; /* make columns */
6883 showoneopt(items[i], opt_flags);
6884 col += INC;
6885 }
6886 out_flush();
6887 ui_breakcheck();
6888 }
6889 }
6890 vim_free(items);
6891}
6892
6893/*
6894 * Return TRUE if option "p" has its default value.
6895 */
6896 static int
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02006897optval_default(struct vimoption *p, char_u *varp, int compatible)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006898{
6899 int dvi;
6900
6901 if (varp == NULL)
6902 return TRUE; /* hidden option is always at default */
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02006903 dvi = ((p->flags & P_VI_DEF) || compatible) ? VI_DEFAULT : VIM_DEFAULT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006904 if (p->flags & P_NUM)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006905 return (*(long *)varp == (long)(long_i)p->def_val[dvi]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006906 if (p->flags & P_BOOL)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00006907 /* the cast to long is required for Manx C, long_i is
6908 * needed for MSVC */
6909 return (*(int *)varp == (int)(long)(long_i)p->def_val[dvi]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006910 /* P_STRING */
6911 return (STRCMP(*(char_u **)varp, p->def_val[dvi]) == 0);
6912}
6913
6914/*
6915 * showoneopt: show the value of one option
6916 * must not be called with a hidden option!
6917 */
6918 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01006919showoneopt(
6920 struct vimoption *p,
6921 int opt_flags) /* OPT_LOCAL or OPT_GLOBAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006922{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006923 char_u *varp;
6924 int save_silent = silent_mode;
6925
6926 silent_mode = FALSE;
6927 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006928
6929 varp = get_varp_scope(p, opt_flags);
6930
6931 /* for 'modified' we also need to check if 'ff' or 'fenc' changed. */
6932 if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
6933 ? !curbufIsChanged() : !*(int *)varp))
Bram Moolenaar32526b32019-01-19 17:43:09 +01006934 msg_puts("no");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006935 else if ((p->flags & P_BOOL) && *(int *)varp < 0)
Bram Moolenaar32526b32019-01-19 17:43:09 +01006936 msg_puts("--");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006937 else
Bram Moolenaar32526b32019-01-19 17:43:09 +01006938 msg_puts(" ");
6939 msg_puts(p->fullname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006940 if (!(p->flags & P_BOOL))
6941 {
6942 msg_putchar('=');
6943 /* put value string in NameBuff */
6944 option_value2string(p, opt_flags);
6945 msg_outtrans(NameBuff);
6946 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006947
6948 silent_mode = save_silent;
6949 info_message = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006950}
6951
6952/*
6953 * Write modified options as ":set" commands to a file.
6954 *
6955 * There are three values for "opt_flags":
6956 * OPT_GLOBAL: Write global option values and fresh values of
6957 * buffer-local options (used for start of a session
6958 * file).
6959 * OPT_GLOBAL + OPT_LOCAL: Idem, add fresh values of window-local options for
6960 * curwin (used for a vimrc file).
6961 * OPT_LOCAL: Write buffer-local option values for curbuf, fresh
6962 * and local values for window-local options of
6963 * curwin. Local values are also written when at the
6964 * default value, because a modeline or autocommand
6965 * may have set them when doing ":edit file" and the
6966 * user has set them back at the default or fresh
6967 * value.
6968 * When "local_only" is TRUE, don't write fresh
6969 * values, only local values (for ":mkview").
6970 * (fresh value = value used for a new buffer or window for a local option).
6971 *
6972 * Return FAIL on error, OK otherwise.
6973 */
6974 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01006975makeset(FILE *fd, int opt_flags, int local_only)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006976{
6977 struct vimoption *p;
6978 char_u *varp; /* currently used value */
6979 char_u *varp_fresh; /* local value */
6980 char_u *varp_local = NULL; /* fresh value */
6981 char *cmd;
6982 int round;
Bram Moolenaar7fd16022007-09-06 14:35:35 +00006983 int pri;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006984
6985 /*
6986 * The options that don't have a default (terminal name, columns, lines)
6987 * are never written. Terminal options are also not written.
Bram Moolenaar7fd16022007-09-06 14:35:35 +00006988 * Do the loop over "options[]" twice: once for options with the
6989 * P_PRI_MKRC flag and once without.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006990 */
Bram Moolenaar7fd16022007-09-06 14:35:35 +00006991 for (pri = 1; pri >= 0; --pri)
6992 {
6993 for (p = &options[0]; !istermoption(p); p++)
6994 if (!(p->flags & P_NO_MKRC)
6995 && !istermoption(p)
6996 && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006997 {
6998 /* skip global option when only doing locals */
6999 if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL))
7000 continue;
7001
7002 /* Do not store options like 'bufhidden' and 'syntax' in a vimrc
7003 * file, they are always buffer-specific. */
7004 if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB))
7005 continue;
7006
7007 /* Global values are only written when not at the default value. */
7008 varp = get_varp_scope(p, opt_flags);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02007009 if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp, p_cp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007010 continue;
7011
7012 round = 2;
7013 if (p->indir != PV_NONE)
7014 {
7015 if (p->var == VAR_WIN)
7016 {
7017 /* skip window-local option when only doing globals */
7018 if (!(opt_flags & OPT_LOCAL))
7019 continue;
7020 /* When fresh value of window-local option is not at the
7021 * default, need to write it too. */
7022 if (!(opt_flags & OPT_GLOBAL) && !local_only)
7023 {
7024 varp_fresh = get_varp_scope(p, OPT_GLOBAL);
Bram Moolenaarcacc6a52019-05-30 15:22:43 +02007025 if (!optval_default(p, varp_fresh, p_cp))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007026 {
7027 round = 1;
7028 varp_local = varp;
7029 varp = varp_fresh;
7030 }
7031 }
7032 }
7033 }
7034
7035 /* Round 1: fresh value for window-local options.
7036 * Round 2: other values */
7037 for ( ; round <= 2; varp = varp_local, ++round)
7038 {
7039 if (round == 1 || (opt_flags & OPT_GLOBAL))
7040 cmd = "set";
7041 else
7042 cmd = "setlocal";
7043
7044 if (p->flags & P_BOOL)
7045 {
7046 if (put_setbool(fd, cmd, p->fullname, *(int *)varp) == FAIL)
7047 return FAIL;
7048 }
7049 else if (p->flags & P_NUM)
7050 {
7051 if (put_setnum(fd, cmd, p->fullname, (long *)varp) == FAIL)
7052 return FAIL;
7053 }
7054 else /* P_STRING */
7055 {
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007056 int do_endif = FALSE;
7057
Bram Moolenaar071d4272004-06-13 20:20:40 +00007058 /* Don't set 'syntax' and 'filetype' again if the value is
7059 * already right, avoids reloading the syntax file. */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007060 if (
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01007061#if defined(FEAT_SYN_HL)
7062 p->indir == PV_SYN ||
7063#endif
7064 p->indir == PV_FT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007065 {
7066 if (fprintf(fd, "if &%s != '%s'", p->fullname,
7067 *(char_u **)(varp)) < 0
7068 || put_eol(fd) < 0)
7069 return FAIL;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007070 do_endif = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007071 }
7072 if (put_setstring(fd, cmd, p->fullname, (char_u **)varp,
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007073 p->flags) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007074 return FAIL;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007075 if (do_endif)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007076 {
7077 if (put_line(fd, "endif") == FAIL)
7078 return FAIL;
7079 }
7080 }
7081 }
7082 }
Bram Moolenaar7fd16022007-09-06 14:35:35 +00007083 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007084 return OK;
7085}
7086
7087#if defined(FEAT_FOLDING) || defined(PROTO)
7088/*
7089 * Generate set commands for the local fold options only. Used when
7090 * 'sessionoptions' or 'viewoptions' contains "folds" but not "options".
7091 */
7092 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007093makefoldset(FILE *fd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007094{
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007095 if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007096# ifdef FEAT_EVAL
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007097 || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007098 == FAIL
7099# endif
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007100 || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007101 == FAIL
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007102 || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007103 == FAIL
7104 || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL
7105 || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL
7106 || put_setnum(fd, "setlocal", "fdn", &curwin->w_p_fdn) == FAIL
7107 || put_setbool(fd, "setlocal", "fen", curwin->w_p_fen) == FAIL
7108 )
7109 return FAIL;
7110
7111 return OK;
7112}
7113#endif
7114
7115 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007116put_setstring(
7117 FILE *fd,
7118 char *cmd,
7119 char *name,
7120 char_u **valuep,
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007121 long_u flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007122{
7123 char_u *s;
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007124 char_u *buf = NULL;
7125 char_u *part = NULL;
7126 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007127
7128 if (fprintf(fd, "%s %s=", cmd, name) < 0)
7129 return FAIL;
7130 if (*valuep != NULL)
7131 {
7132 /* Output 'pastetoggle' as key names. For other
7133 * options some characters have to be escaped with
7134 * CTRL-V or backslash */
7135 if (valuep == &p_pt)
7136 {
7137 s = *valuep;
7138 while (*s != NUL)
Bram Moolenaar7d96acd2008-06-09 15:07:54 +00007139 if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007140 return FAIL;
7141 }
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007142 // expand the option value, replace $HOME by ~
7143 else if ((flags & P_EXPAND) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007144 {
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007145 int size = (int)STRLEN(*valuep) + 1;
7146
7147 // replace home directory in the whole option value into "buf"
7148 buf = alloc(size);
Bram Moolenaarf8441472011-04-28 17:24:58 +02007149 if (buf == NULL)
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007150 goto fail;
7151 home_replace(NULL, *valuep, buf, size, FALSE);
7152
7153 // If the option value is longer than MAXPATHL, we need to append
7154 // earch comma separated part of the option separately, so that it
7155 // can be expanded when read back.
7156 if (size >= MAXPATHL && (flags & P_COMMA) != 0
7157 && vim_strchr(*valuep, ',') != NULL)
7158 {
7159 part = alloc(size);
7160 if (part == NULL)
7161 goto fail;
7162
7163 // write line break to clear the option, e.g. ':set rtp='
7164 if (put_eol(fd) == FAIL)
7165 goto fail;
7166
7167 p = buf;
7168 while (*p != NUL)
7169 {
7170 // for each comma separated option part, append value to
7171 // the option, :set rtp+=value
7172 if (fprintf(fd, "%s %s+=", cmd, name) < 0)
7173 goto fail;
7174 (void)copy_option_part(&p, part, size, ",");
7175 if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL)
7176 goto fail;
7177 }
7178 vim_free(buf);
7179 vim_free(part);
7180 return OK;
7181 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007182 if (put_escstr(fd, buf, 2) == FAIL)
Bram Moolenaarf8441472011-04-28 17:24:58 +02007183 {
7184 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007185 return FAIL;
Bram Moolenaarf8441472011-04-28 17:24:58 +02007186 }
7187 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007188 }
7189 else if (put_escstr(fd, *valuep, 2) == FAIL)
7190 return FAIL;
7191 }
7192 if (put_eol(fd) < 0)
7193 return FAIL;
7194 return OK;
Bram Moolenaared18f2c2019-01-24 20:30:52 +01007195fail:
7196 vim_free(buf);
7197 vim_free(part);
7198 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007199}
7200
7201 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007202put_setnum(
7203 FILE *fd,
7204 char *cmd,
7205 char *name,
7206 long *valuep)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007207{
7208 long wc;
7209
7210 if (fprintf(fd, "%s %s=", cmd, name) < 0)
7211 return FAIL;
7212 if (wc_use_keyname((char_u *)valuep, &wc))
7213 {
7214 /* print 'wildchar' and 'wildcharm' as a key name */
7215 if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0)
7216 return FAIL;
7217 }
7218 else if (fprintf(fd, "%ld", *valuep) < 0)
7219 return FAIL;
7220 if (put_eol(fd) < 0)
7221 return FAIL;
7222 return OK;
7223}
7224
7225 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007226put_setbool(
7227 FILE *fd,
7228 char *cmd,
7229 char *name,
7230 int value)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007231{
Bram Moolenaar893de922007-10-02 18:40:57 +00007232 if (value < 0) /* global/local option using global value */
7233 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007234 if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
7235 || put_eol(fd) < 0)
7236 return FAIL;
7237 return OK;
7238}
7239
7240/*
7241 * Clear all the terminal options.
7242 * If the option has been allocated, free the memory.
7243 * Terminal options are never hidden or indirect.
7244 */
7245 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007246clear_termoptions(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007247{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007248 /*
7249 * Reset a few things before clearing the old options. This may cause
7250 * outputting a few things that the terminal doesn't understand, but the
7251 * screen will be cleared later, so this is OK.
7252 */
7253#ifdef FEAT_MOUSE_TTY
7254 mch_setmouse(FALSE); /* switch mouse off */
7255#endif
7256#ifdef FEAT_TITLE
Bram Moolenaar40385db2018-08-07 22:31:44 +02007257 mch_restore_title(SAVE_RESTORE_BOTH); /* restore window titles */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007258#endif
7259#if defined(FEAT_XCLIPBOARD) && defined(FEAT_GUI)
7260 /* When starting the GUI close the display opened for the clipboard.
7261 * After restoring the title, because that will need the display. */
7262 if (gui.starting)
7263 clear_xterm_clip();
7264#endif
Bram Moolenaarcea912a2016-10-12 14:20:24 +02007265 stoptermcap(); /* stop termcap mode */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007266
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00007267 free_termoptions();
7268}
7269
7270 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007271free_termoptions(void)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00007272{
7273 struct vimoption *p;
7274
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02007275 for (p = options; p->fullname != NULL; p++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007276 if (istermoption(p))
7277 {
7278 if (p->flags & P_ALLOCED)
7279 free_string_option(*(char_u **)(p->var));
7280 if (p->flags & P_DEF_ALLOCED)
7281 free_string_option(p->def_val[VI_DEFAULT]);
7282 *(char_u **)(p->var) = empty_option;
7283 p->def_val[VI_DEFAULT] = empty_option;
7284 p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED);
Bram Moolenaar35bc7d62018-10-02 14:45:10 +02007285#ifdef FEAT_EVAL
7286 // remember where the option was cleared
7287 set_option_sctx_idx((int)(p - options), OPT_GLOBAL, current_sctx);
7288#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007289 }
7290 clear_termcodes();
7291}
7292
7293/*
Bram Moolenaar363cb672009-07-22 12:28:17 +00007294 * Free the string for one term option, if it was allocated.
7295 * Set the string to empty_option and clear allocated flag.
7296 * "var" points to the option value.
7297 */
7298 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007299free_one_termoption(char_u *var)
Bram Moolenaar363cb672009-07-22 12:28:17 +00007300{
7301 struct vimoption *p;
7302
7303 for (p = &options[0]; p->fullname != NULL; p++)
7304 if (p->var == var)
7305 {
7306 if (p->flags & P_ALLOCED)
7307 free_string_option(*(char_u **)(p->var));
7308 *(char_u **)(p->var) = empty_option;
7309 p->flags &= ~P_ALLOCED;
7310 break;
7311 }
7312}
7313
7314/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007315 * Set the terminal option defaults to the current value.
7316 * Used after setting the terminal name.
7317 */
7318 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007319set_term_defaults(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007320{
7321 struct vimoption *p;
7322
7323 for (p = &options[0]; p->fullname != NULL; p++)
7324 {
7325 if (istermoption(p) && p->def_val[VI_DEFAULT] != *(char_u **)(p->var))
7326 {
7327 if (p->flags & P_DEF_ALLOCED)
7328 {
7329 free_string_option(p->def_val[VI_DEFAULT]);
7330 p->flags &= ~P_DEF_ALLOCED;
7331 }
7332 p->def_val[VI_DEFAULT] = *(char_u **)(p->var);
7333 if (p->flags & P_ALLOCED)
7334 {
7335 p->flags |= P_DEF_ALLOCED;
7336 p->flags &= ~P_ALLOCED; /* don't free the value now */
7337 }
7338 }
7339 }
7340}
7341
7342/*
7343 * return TRUE if 'p' starts with 't_'
7344 */
7345 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01007346istermoption(struct vimoption *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347{
7348 return (p->fullname[0] == 't' && p->fullname[1] == '_');
7349}
7350
Bram Moolenaar113e1072019-01-20 15:30:40 +01007351#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007352/*
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007353 * Unset local option value, similar to ":set opt<".
7354 */
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007355 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007356unset_global_local_option(char_u *name, void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007357{
7358 struct vimoption *p;
7359 int opt_idx;
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007360 buf_T *buf = (buf_T *)from;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007361
7362 opt_idx = findoption(name);
Bram Moolenaarbd8539a2015-08-11 18:53:03 +02007363 if (opt_idx < 0)
7364 return;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007365 p = &(options[opt_idx]);
7366
7367 switch ((int)p->indir)
7368 {
7369 /* global option with local value: use local value if it's been set */
7370 case PV_EP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007371 clear_string_option(&buf->b_p_ep);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007372 break;
7373 case PV_KP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007374 clear_string_option(&buf->b_p_kp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007375 break;
7376 case PV_PATH:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007377 clear_string_option(&buf->b_p_path);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007378 break;
7379 case PV_AR:
7380 buf->b_p_ar = -1;
7381 break;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02007382 case PV_BKC:
7383 clear_string_option(&buf->b_p_bkc);
7384 buf->b_bkc_flags = 0;
7385 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007386 case PV_TAGS:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007387 clear_string_option(&buf->b_p_tags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007388 break;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01007389 case PV_TC:
7390 clear_string_option(&buf->b_p_tc);
7391 buf->b_tc_flags = 0;
7392 break;
Bram Moolenaar375e3392019-01-31 18:26:10 +01007393 case PV_SISO:
7394 curwin->w_p_siso = -1;
7395 break;
7396 case PV_SO:
7397 curwin->w_p_so = -1;
7398 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007399#ifdef FEAT_FIND_ID
7400 case PV_DEF:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007401 clear_string_option(&buf->b_p_def);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007402 break;
7403 case PV_INC:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007404 clear_string_option(&buf->b_p_inc);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007405 break;
7406#endif
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007407 case PV_DICT:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007408 clear_string_option(&buf->b_p_dict);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007409 break;
7410 case PV_TSR:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007411 clear_string_option(&buf->b_p_tsr);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007412 break;
Bram Moolenaar9be7c042017-01-14 14:28:30 +01007413 case PV_FP:
7414 clear_string_option(&buf->b_p_fp);
7415 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007416#ifdef FEAT_QUICKFIX
7417 case PV_EFM:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007418 clear_string_option(&buf->b_p_efm);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007419 break;
7420 case PV_GP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007421 clear_string_option(&buf->b_p_gp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007422 break;
7423 case PV_MP:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007424 clear_string_option(&buf->b_p_mp);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007425 break;
7426#endif
7427#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
7428 case PV_BEXPR:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007429 clear_string_option(&buf->b_p_bexpr);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007430 break;
7431#endif
7432#if defined(FEAT_CRYPT)
7433 case PV_CM:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007434 clear_string_option(&buf->b_p_cm);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007435 break;
7436#endif
7437#ifdef FEAT_STL_OPT
7438 case PV_STL:
Bram Moolenaar51ac8a22013-05-06 06:45:47 +02007439 clear_string_option(&((win_T *)from)->w_p_stl);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007440 break;
7441#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01007442 case PV_UL:
7443 buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
7444 break;
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01007445#ifdef FEAT_LISP
7446 case PV_LW:
7447 clear_string_option(&buf->b_p_lw);
7448 break;
7449#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01007450 case PV_MENC:
7451 clear_string_option(&buf->b_p_menc);
7452 break;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007453 }
7454}
Bram Moolenaar113e1072019-01-20 15:30:40 +01007455#endif
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007456
7457/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007458 * Get pointer to option variable, depending on local or global scope.
7459 */
7460 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01007461get_varp_scope(struct vimoption *p, int opt_flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007462{
7463 if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE)
7464 {
7465 if (p->var == VAR_WIN)
7466 return (char_u *)GLOBAL_WO(get_varp(p));
7467 return p->var;
7468 }
Bram Moolenaara23ccb82006-02-27 00:08:02 +00007469 if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 {
7471 switch ((int)p->indir)
7472 {
Bram Moolenaar9be7c042017-01-14 14:28:30 +01007473 case PV_FP: return (char_u *)&(curbuf->b_p_fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007474#ifdef FEAT_QUICKFIX
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007475 case PV_EFM: return (char_u *)&(curbuf->b_p_efm);
7476 case PV_GP: return (char_u *)&(curbuf->b_p_gp);
7477 case PV_MP: return (char_u *)&(curbuf->b_p_mp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007479 case PV_EP: return (char_u *)&(curbuf->b_p_ep);
7480 case PV_KP: return (char_u *)&(curbuf->b_p_kp);
7481 case PV_PATH: return (char_u *)&(curbuf->b_p_path);
Bram Moolenaara23ccb82006-02-27 00:08:02 +00007482 case PV_AR: return (char_u *)&(curbuf->b_p_ar);
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007483 case PV_TAGS: return (char_u *)&(curbuf->b_p_tags);
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01007484 case PV_TC: return (char_u *)&(curbuf->b_p_tc);
Bram Moolenaar375e3392019-01-31 18:26:10 +01007485 case PV_SISO: return (char_u *)&(curwin->w_p_siso);
7486 case PV_SO: return (char_u *)&(curwin->w_p_so);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007487#ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007488 case PV_DEF: return (char_u *)&(curbuf->b_p_def);
7489 case PV_INC: return (char_u *)&(curbuf->b_p_inc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007490#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007491 case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
7492 case PV_TSR: return (char_u *)&(curbuf->b_p_tsr);
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00007493#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
7494 case PV_BEXPR: return (char_u *)&(curbuf->b_p_bexpr);
7495#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02007496#if defined(FEAT_CRYPT)
7497 case PV_CM: return (char_u *)&(curbuf->b_p_cm);
7498#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007499#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007500 case PV_STL: return (char_u *)&(curwin->w_p_stl);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007501#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01007502 case PV_UL: return (char_u *)&(curbuf->b_p_ul);
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01007503#ifdef FEAT_LISP
7504 case PV_LW: return (char_u *)&(curbuf->b_p_lw);
7505#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02007506 case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01007507 case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007508 }
7509 return NULL; /* "cannot happen" */
7510 }
7511 return get_varp(p);
7512}
7513
7514/*
7515 * Get pointer to option variable.
7516 */
7517 static char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01007518get_varp(struct vimoption *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007519{
7520 /* hidden option, always return NULL */
7521 if (p->var == NULL)
7522 return NULL;
7523
7524 switch ((int)p->indir)
7525 {
7526 case PV_NONE: return p->var;
7527
7528 /* global option with local value: use local value if it's been set */
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007529 case PV_EP: return *curbuf->b_p_ep != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007530 ? (char_u *)&curbuf->b_p_ep : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007531 case PV_KP: return *curbuf->b_p_kp != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007532 ? (char_u *)&curbuf->b_p_kp : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007533 case PV_PATH: return *curbuf->b_p_path != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007534 ? (char_u *)&(curbuf->b_p_path) : p->var;
Bram Moolenaara23ccb82006-02-27 00:08:02 +00007535 case PV_AR: return curbuf->b_p_ar >= 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00007536 ? (char_u *)&(curbuf->b_p_ar) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007537 case PV_TAGS: return *curbuf->b_p_tags != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007538 ? (char_u *)&(curbuf->b_p_tags) : p->var;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01007539 case PV_TC: return *curbuf->b_p_tc != NUL
7540 ? (char_u *)&(curbuf->b_p_tc) : p->var;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02007541 case PV_BKC: return *curbuf->b_p_bkc != NUL
7542 ? (char_u *)&(curbuf->b_p_bkc) : p->var;
Bram Moolenaar375e3392019-01-31 18:26:10 +01007543 case PV_SISO: return curwin->w_p_siso >= 0
7544 ? (char_u *)&(curwin->w_p_siso) : p->var;
7545 case PV_SO: return curwin->w_p_so >= 0
7546 ? (char_u *)&(curwin->w_p_so) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007547#ifdef FEAT_FIND_ID
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007548 case PV_DEF: return *curbuf->b_p_def != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007549 ? (char_u *)&(curbuf->b_p_def) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007550 case PV_INC: return *curbuf->b_p_inc != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007551 ? (char_u *)&(curbuf->b_p_inc) : p->var;
7552#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007553 case PV_DICT: return *curbuf->b_p_dict != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007554 ? (char_u *)&(curbuf->b_p_dict) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007555 case PV_TSR: return *curbuf->b_p_tsr != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007556 ? (char_u *)&(curbuf->b_p_tsr) : p->var;
Bram Moolenaar9be7c042017-01-14 14:28:30 +01007557 case PV_FP: return *curbuf->b_p_fp != NUL
7558 ? (char_u *)&(curbuf->b_p_fp) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007559#ifdef FEAT_QUICKFIX
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007560 case PV_EFM: return *curbuf->b_p_efm != NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007561 ? (char_u *)&(curbuf->b_p_efm) : p->var;
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007562 case PV_GP: return *curbuf->b_p_gp != NUL
7563 ? (char_u *)&(curbuf->b_p_gp) : p->var;
7564 case PV_MP: return *curbuf->b_p_mp != NUL
7565 ? (char_u *)&(curbuf->b_p_mp) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007566#endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00007567#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
7568 case PV_BEXPR: return *curbuf->b_p_bexpr != NUL
7569 ? (char_u *)&(curbuf->b_p_bexpr) : p->var;
7570#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02007571#if defined(FEAT_CRYPT)
7572 case PV_CM: return *curbuf->b_p_cm != NUL
7573 ? (char_u *)&(curbuf->b_p_cm) : p->var;
7574#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007575#ifdef FEAT_STL_OPT
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007576 case PV_STL: return *curwin->w_p_stl != NUL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007577 ? (char_u *)&(curwin->w_p_stl) : p->var;
7578#endif
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01007579 case PV_UL: return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
7580 ? (char_u *)&(curbuf->b_p_ul) : p->var;
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01007581#ifdef FEAT_LISP
7582 case PV_LW: return *curbuf->b_p_lw != NUL
7583 ? (char_u *)&(curbuf->b_p_lw) : p->var;
7584#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01007585 case PV_MENC: return *curbuf->b_p_menc != NUL
7586 ? (char_u *)&(curbuf->b_p_menc) : p->var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007587#ifdef FEAT_ARABIC
7588 case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
7589#endif
7590 case PV_LIST: return (char_u *)&(curwin->w_p_list);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007591#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00007592 case PV_SPELL: return (char_u *)&(curwin->w_p_spell);
7593#endif
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007594#ifdef FEAT_SYN_HL
7595 case PV_CUC: return (char_u *)&(curwin->w_p_cuc);
7596 case PV_CUL: return (char_u *)&(curwin->w_p_cul);
Bram Moolenaar410e98a2019-09-09 22:05:49 +02007597 case PV_CULOPT: return (char_u *)&(curwin->w_p_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02007598 case PV_CC: return (char_u *)&(curwin->w_p_cc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007599#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007600#ifdef FEAT_DIFF
7601 case PV_DIFF: return (char_u *)&(curwin->w_p_diff);
7602#endif
7603#ifdef FEAT_FOLDING
7604 case PV_FDC: return (char_u *)&(curwin->w_p_fdc);
7605 case PV_FEN: return (char_u *)&(curwin->w_p_fen);
7606 case PV_FDI: return (char_u *)&(curwin->w_p_fdi);
7607 case PV_FDL: return (char_u *)&(curwin->w_p_fdl);
7608 case PV_FDM: return (char_u *)&(curwin->w_p_fdm);
7609 case PV_FML: return (char_u *)&(curwin->w_p_fml);
7610 case PV_FDN: return (char_u *)&(curwin->w_p_fdn);
7611# ifdef FEAT_EVAL
7612 case PV_FDE: return (char_u *)&(curwin->w_p_fde);
7613 case PV_FDT: return (char_u *)&(curwin->w_p_fdt);
7614# endif
7615 case PV_FMR: return (char_u *)&(curwin->w_p_fmr);
7616#endif
7617 case PV_NU: return (char_u *)&(curwin->w_p_nu);
Bram Moolenaar64486672010-05-16 15:46:46 +02007618 case PV_RNU: return (char_u *)&(curwin->w_p_rnu);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00007619#ifdef FEAT_LINEBREAK
7620 case PV_NUW: return (char_u *)&(curwin->w_p_nuw);
7621#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007622 case PV_WFH: return (char_u *)&(curwin->w_p_wfh);
Bram Moolenaar97b2ad32006-03-18 21:40:56 +00007623 case PV_WFW: return (char_u *)&(curwin->w_p_wfw);
Bram Moolenaar4033c552017-09-16 20:54:51 +02007624#if defined(FEAT_QUICKFIX)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007625 case PV_PVW: return (char_u *)&(curwin->w_p_pvw);
7626#endif
7627#ifdef FEAT_RIGHTLEFT
7628 case PV_RL: return (char_u *)&(curwin->w_p_rl);
7629 case PV_RLC: return (char_u *)&(curwin->w_p_rlc);
7630#endif
7631 case PV_SCROLL: return (char_u *)&(curwin->w_p_scr);
7632 case PV_WRAP: return (char_u *)&(curwin->w_p_wrap);
7633#ifdef FEAT_LINEBREAK
7634 case PV_LBR: return (char_u *)&(curwin->w_p_lbr);
Bram Moolenaar597a4222014-06-25 14:39:50 +02007635 case PV_BRI: return (char_u *)&(curwin->w_p_bri);
7636 case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007637#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02007638 case PV_WCR: return (char_u *)&(curwin->w_p_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007639 case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
Bram Moolenaar860cae12010-06-05 23:22:07 +02007640 case PV_CRBIND: return (char_u *)&(curwin->w_p_crb);
Bram Moolenaar860cae12010-06-05 23:22:07 +02007641#ifdef FEAT_CONCEAL
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007642 case PV_COCU: return (char_u *)&(curwin->w_p_cocu);
7643 case PV_COLE: return (char_u *)&(curwin->w_p_cole);
7644#endif
7645#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02007646 case PV_TWK: return (char_u *)&(curwin->w_p_twk);
7647 case PV_TWS: return (char_u *)&(curwin->w_p_tws);
7648 case PV_TWSL: return (char_u *)&(curbuf->b_p_twsl);
Bram Moolenaar860cae12010-06-05 23:22:07 +02007649#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007650
7651 case PV_AI: return (char_u *)&(curbuf->b_p_ai);
7652 case PV_BIN: return (char_u *)&(curbuf->b_p_bin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007653 case PV_BOMB: return (char_u *)&(curbuf->b_p_bomb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007654 case PV_BH: return (char_u *)&(curbuf->b_p_bh);
7655 case PV_BT: return (char_u *)&(curbuf->b_p_bt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007656 case PV_BL: return (char_u *)&(curbuf->b_p_bl);
7657 case PV_CI: return (char_u *)&(curbuf->b_p_ci);
7658#ifdef FEAT_CINDENT
7659 case PV_CIN: return (char_u *)&(curbuf->b_p_cin);
7660 case PV_CINK: return (char_u *)&(curbuf->b_p_cink);
7661 case PV_CINO: return (char_u *)&(curbuf->b_p_cino);
7662#endif
7663#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
7664 case PV_CINW: return (char_u *)&(curbuf->b_p_cinw);
7665#endif
7666#ifdef FEAT_COMMENTS
7667 case PV_COM: return (char_u *)&(curbuf->b_p_com);
7668#endif
7669#ifdef FEAT_FOLDING
7670 case PV_CMS: return (char_u *)&(curbuf->b_p_cms);
7671#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007672 case PV_CPT: return (char_u *)&(curbuf->b_p_cpt);
Bram Moolenaare2c453d2019-08-21 14:37:09 +02007673#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarac3150d2019-07-28 16:36:39 +02007674 case PV_CSL: return (char_u *)&(curbuf->b_p_csl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007675#endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007676#ifdef FEAT_COMPL_FUNC
7677 case PV_CFU: return (char_u *)&(curbuf->b_p_cfu);
Bram Moolenaare344bea2005-09-01 20:46:49 +00007678 case PV_OFU: return (char_u *)&(curbuf->b_p_ofu);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007679#endif
Bram Moolenaar45e18cb2019-04-28 18:05:35 +02007680#ifdef FEAT_EVAL
7681 case PV_TFU: return (char_u *)&(curbuf->b_p_tfu);
7682#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007683 case PV_EOL: return (char_u *)&(curbuf->b_p_eol);
Bram Moolenaar34d72d42015-07-17 14:18:08 +02007684 case PV_FIXEOL: return (char_u *)&(curbuf->b_p_fixeol);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007685 case PV_ET: return (char_u *)&(curbuf->b_p_et);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007686 case PV_FENC: return (char_u *)&(curbuf->b_p_fenc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007687 case PV_FF: return (char_u *)&(curbuf->b_p_ff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007688 case PV_FT: return (char_u *)&(curbuf->b_p_ft);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007689 case PV_FO: return (char_u *)&(curbuf->b_p_fo);
Bram Moolenaar86b68352004-12-27 21:59:20 +00007690 case PV_FLP: return (char_u *)&(curbuf->b_p_flp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007691 case PV_IMI: return (char_u *)&(curbuf->b_p_iminsert);
7692 case PV_IMS: return (char_u *)&(curbuf->b_p_imsearch);
7693 case PV_INF: return (char_u *)&(curbuf->b_p_inf);
7694 case PV_ISK: return (char_u *)&(curbuf->b_p_isk);
7695#ifdef FEAT_FIND_ID
7696# ifdef FEAT_EVAL
7697 case PV_INEX: return (char_u *)&(curbuf->b_p_inex);
7698# endif
7699#endif
7700#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
7701 case PV_INDE: return (char_u *)&(curbuf->b_p_inde);
7702 case PV_INDK: return (char_u *)&(curbuf->b_p_indk);
7703#endif
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00007704#ifdef FEAT_EVAL
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00007705 case PV_FEX: return (char_u *)&(curbuf->b_p_fex);
7706#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007707#ifdef FEAT_CRYPT
7708 case PV_KEY: return (char_u *)&(curbuf->b_p_key);
7709#endif
7710#ifdef FEAT_LISP
7711 case PV_LISP: return (char_u *)&(curbuf->b_p_lisp);
7712#endif
7713 case PV_ML: return (char_u *)&(curbuf->b_p_ml);
7714 case PV_MPS: return (char_u *)&(curbuf->b_p_mps);
7715 case PV_MA: return (char_u *)&(curbuf->b_p_ma);
7716 case PV_MOD: return (char_u *)&(curbuf->b_changed);
7717 case PV_NF: return (char_u *)&(curbuf->b_p_nf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007718 case PV_PI: return (char_u *)&(curbuf->b_p_pi);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00007719#ifdef FEAT_TEXTOBJ
7720 case PV_QE: return (char_u *)&(curbuf->b_p_qe);
7721#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007722 case PV_RO: return (char_u *)&(curbuf->b_p_ro);
7723#ifdef FEAT_SMARTINDENT
7724 case PV_SI: return (char_u *)&(curbuf->b_p_si);
7725#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007726 case PV_SN: return (char_u *)&(curbuf->b_p_sn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007727 case PV_STS: return (char_u *)&(curbuf->b_p_sts);
7728#ifdef FEAT_SEARCHPATH
7729 case PV_SUA: return (char_u *)&(curbuf->b_p_sua);
7730#endif
7731 case PV_SWF: return (char_u *)&(curbuf->b_p_swf);
7732#ifdef FEAT_SYN_HL
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00007733 case PV_SMC: return (char_u *)&(curbuf->b_p_smc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007734 case PV_SYN: return (char_u *)&(curbuf->b_p_syn);
7735#endif
7736#ifdef FEAT_SPELL
Bram Moolenaar860cae12010-06-05 23:22:07 +02007737 case PV_SPC: return (char_u *)&(curwin->w_s->b_p_spc);
7738 case PV_SPF: return (char_u *)&(curwin->w_s->b_p_spf);
7739 case PV_SPL: return (char_u *)&(curwin->w_s->b_p_spl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007740#endif
7741 case PV_SW: return (char_u *)&(curbuf->b_p_sw);
7742 case PV_TS: return (char_u *)&(curbuf->b_p_ts);
7743 case PV_TW: return (char_u *)&(curbuf->b_p_tw);
7744 case PV_TX: return (char_u *)&(curbuf->b_p_tx);
Bram Moolenaar55debbe2010-05-23 23:34:36 +02007745#ifdef FEAT_PERSISTENT_UNDO
7746 case PV_UDF: return (char_u *)&(curbuf->b_p_udf);
7747#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007748 case PV_WM: return (char_u *)&(curbuf->b_p_wm);
7749#ifdef FEAT_KEYMAP
7750 case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
7751#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007752#ifdef FEAT_SIGNS
7753 case PV_SCL: return (char_u *)&(curwin->w_p_scl);
7754#endif
Bram Moolenaar04958cb2018-06-23 19:23:02 +02007755#ifdef FEAT_VARTABS
7756 case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts);
7757 case PV_VTS: return (char_u *)&(curbuf->b_p_vts);
7758#endif
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007759 default: iemsg(_("E356: get_varp ERROR"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007760 }
7761 /* always return a valid pointer to avoid a crash! */
7762 return (char_u *)&(curbuf->b_p_wm);
7763}
7764
7765/*
7766 * Get the value of 'equalprg', either the buffer-local one or the global one.
7767 */
7768 char_u *
Bram Moolenaar9b578142016-01-30 19:39:49 +01007769get_equalprg(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007770{
7771 if (*curbuf->b_p_ep == NUL)
7772 return p_ep;
7773 return curbuf->b_p_ep;
7774}
7775
Bram Moolenaar071d4272004-06-13 20:20:40 +00007776/*
7777 * Copy options from one window to another.
7778 * Used when splitting a window.
7779 */
7780 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007781win_copy_options(win_T *wp_from, win_T *wp_to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007782{
7783 copy_winopt(&wp_from->w_onebuf_opt, &wp_to->w_onebuf_opt);
7784 copy_winopt(&wp_from->w_allbuf_opt, &wp_to->w_allbuf_opt);
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02007785#if defined(FEAT_LINEBREAK)
7786 briopt_check(wp_to);
7787#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +02007788#ifdef FEAT_SYN_HL
7789 fill_culopt_flags(NULL, wp_to);
7790#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007791}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007792
7793/*
7794 * Copy the options from one winopt_T to another.
7795 * Doesn't free the old option values in "to", use clear_winopt() for that.
7796 * The 'scroll' option is not copied, because it depends on the window height.
7797 * The 'previewwindow' option is reset, there can be only one preview window.
7798 */
7799 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007800copy_winopt(winopt_T *from, winopt_T *to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007801{
7802#ifdef FEAT_ARABIC
7803 to->wo_arab = from->wo_arab;
7804#endif
7805 to->wo_list = from->wo_list;
7806 to->wo_nu = from->wo_nu;
Bram Moolenaar64486672010-05-16 15:46:46 +02007807 to->wo_rnu = from->wo_rnu;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00007808#ifdef FEAT_LINEBREAK
7809 to->wo_nuw = from->wo_nuw;
7810#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007811#ifdef FEAT_RIGHTLEFT
7812 to->wo_rl = from->wo_rl;
7813 to->wo_rlc = vim_strsave(from->wo_rlc);
7814#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007815#ifdef FEAT_STL_OPT
7816 to->wo_stl = vim_strsave(from->wo_stl);
7817#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007818 to->wo_wrap = from->wo_wrap;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007819#ifdef FEAT_DIFF
7820 to->wo_wrap_save = from->wo_wrap_save;
7821#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007822#ifdef FEAT_LINEBREAK
7823 to->wo_lbr = from->wo_lbr;
Bram Moolenaar597a4222014-06-25 14:39:50 +02007824 to->wo_bri = from->wo_bri;
7825 to->wo_briopt = vim_strsave(from->wo_briopt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007826#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02007827 to->wo_wcr = vim_strsave(from->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007828 to->wo_scb = from->wo_scb;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007829 to->wo_scb_save = from->wo_scb_save;
Bram Moolenaar4161dcc2010-12-02 15:33:21 +01007830 to->wo_crb = from->wo_crb;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007831 to->wo_crb_save = from->wo_crb_save;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007832#ifdef FEAT_SPELL
Bram Moolenaar217ad922005-03-20 22:37:15 +00007833 to->wo_spell = from->wo_spell;
7834#endif
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007835#ifdef FEAT_SYN_HL
7836 to->wo_cuc = from->wo_cuc;
7837 to->wo_cul = from->wo_cul;
Bram Moolenaar410e98a2019-09-09 22:05:49 +02007838 to->wo_culopt = vim_strsave(from->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02007839 to->wo_cc = vim_strsave(from->wo_cc);
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00007840#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007841#ifdef FEAT_DIFF
7842 to->wo_diff = from->wo_diff;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007843 to->wo_diff_saved = from->wo_diff_saved;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007844#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02007845#ifdef FEAT_CONCEAL
7846 to->wo_cocu = vim_strsave(from->wo_cocu);
Bram Moolenaard497a302010-07-23 22:27:03 +02007847 to->wo_cole = from->wo_cole;
Bram Moolenaarf5963f72010-07-23 22:10:27 +02007848#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007849#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02007850 to->wo_twk = vim_strsave(from->wo_twk);
7851 to->wo_tws = vim_strsave(from->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007852#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007853#ifdef FEAT_FOLDING
7854 to->wo_fdc = from->wo_fdc;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007855 to->wo_fdc_save = from->wo_fdc_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007856 to->wo_fen = from->wo_fen;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007857 to->wo_fen_save = from->wo_fen_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007858 to->wo_fdi = vim_strsave(from->wo_fdi);
7859 to->wo_fml = from->wo_fml;
7860 to->wo_fdl = from->wo_fdl;
Bram Moolenaara87aa802013-07-03 15:47:03 +02007861 to->wo_fdl_save = from->wo_fdl_save;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007862 to->wo_fdm = vim_strsave(from->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02007863 to->wo_fdm_save = from->wo_diff_saved
7864 ? vim_strsave(from->wo_fdm_save) : empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007865 to->wo_fdn = from->wo_fdn;
7866# ifdef FEAT_EVAL
7867 to->wo_fde = vim_strsave(from->wo_fde);
7868 to->wo_fdt = vim_strsave(from->wo_fdt);
7869# endif
7870 to->wo_fmr = vim_strsave(from->wo_fmr);
7871#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007872#ifdef FEAT_SIGNS
7873 to->wo_scl = vim_strsave(from->wo_scl);
7874#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007875 check_winopt(to); /* don't want NULL pointers */
7876}
7877
7878/*
7879 * Check string options in a window for a NULL value.
7880 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02007881 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007882check_win_options(win_T *win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007883{
7884 check_winopt(&win->w_onebuf_opt);
7885 check_winopt(&win->w_allbuf_opt);
7886}
7887
7888/*
7889 * Check for NULL pointers in a winopt_T and replace them with empty_option.
7890 */
Bram Moolenaar8dc907d2014-06-25 14:44:10 +02007891 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007892check_winopt(winopt_T *wop UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007893{
7894#ifdef FEAT_FOLDING
7895 check_string_option(&wop->wo_fdi);
7896 check_string_option(&wop->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02007897 check_string_option(&wop->wo_fdm_save);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007898# ifdef FEAT_EVAL
7899 check_string_option(&wop->wo_fde);
7900 check_string_option(&wop->wo_fdt);
7901# endif
7902 check_string_option(&wop->wo_fmr);
7903#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007904#ifdef FEAT_SIGNS
7905 check_string_option(&wop->wo_scl);
7906#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007907#ifdef FEAT_RIGHTLEFT
7908 check_string_option(&wop->wo_rlc);
7909#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007910#ifdef FEAT_STL_OPT
7911 check_string_option(&wop->wo_stl);
7912#endif
Bram Moolenaar1a384422010-07-14 19:53:30 +02007913#ifdef FEAT_SYN_HL
Bram Moolenaar410e98a2019-09-09 22:05:49 +02007914 check_string_option(&wop->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02007915 check_string_option(&wop->wo_cc);
7916#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02007917#ifdef FEAT_CONCEAL
7918 check_string_option(&wop->wo_cocu);
7919#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007920#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02007921 check_string_option(&wop->wo_twk);
7922 check_string_option(&wop->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007923#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02007924#ifdef FEAT_LINEBREAK
7925 check_string_option(&wop->wo_briopt);
7926#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02007927 check_string_option(&wop->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007928}
7929
7930/*
7931 * Free the allocated memory inside a winopt_T.
7932 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007933 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007934clear_winopt(winopt_T *wop UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007935{
7936#ifdef FEAT_FOLDING
7937 clear_string_option(&wop->wo_fdi);
7938 clear_string_option(&wop->wo_fdm);
Bram Moolenaara87aa802013-07-03 15:47:03 +02007939 clear_string_option(&wop->wo_fdm_save);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007940# ifdef FEAT_EVAL
7941 clear_string_option(&wop->wo_fde);
7942 clear_string_option(&wop->wo_fdt);
7943# endif
7944 clear_string_option(&wop->wo_fmr);
7945#endif
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02007946#ifdef FEAT_SIGNS
7947 clear_string_option(&wop->wo_scl);
7948#endif
Bram Moolenaar597a4222014-06-25 14:39:50 +02007949#ifdef FEAT_LINEBREAK
7950 clear_string_option(&wop->wo_briopt);
7951#endif
Bram Moolenaar4d784b22019-05-25 19:51:39 +02007952 clear_string_option(&wop->wo_wcr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007953#ifdef FEAT_RIGHTLEFT
7954 clear_string_option(&wop->wo_rlc);
7955#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007956#ifdef FEAT_STL_OPT
7957 clear_string_option(&wop->wo_stl);
7958#endif
Bram Moolenaar1a384422010-07-14 19:53:30 +02007959#ifdef FEAT_SYN_HL
Bram Moolenaar410e98a2019-09-09 22:05:49 +02007960 clear_string_option(&wop->wo_culopt);
Bram Moolenaar1a384422010-07-14 19:53:30 +02007961 clear_string_option(&wop->wo_cc);
7962#endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02007963#ifdef FEAT_CONCEAL
7964 clear_string_option(&wop->wo_cocu);
7965#endif
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007966#ifdef FEAT_TERMINAL
Bram Moolenaar6d150f72018-04-21 20:03:20 +02007967 clear_string_option(&wop->wo_twk);
7968 clear_string_option(&wop->wo_tws);
Bram Moolenaare4f25e42017-07-07 11:54:15 +02007969#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007970}
7971
7972/*
7973 * Copy global option values to local options for one buffer.
7974 * Used when creating a new buffer and sometimes when entering a buffer.
7975 * flags:
7976 * BCO_ENTER We will enter the buf buffer.
7977 * BCO_ALWAYS Always copy the options, but only set b_p_initialized when
7978 * appropriate.
7979 * BCO_NOHELP Don't copy the values to a help buffer.
7980 */
7981 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01007982buf_copy_options(buf_T *buf, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007983{
7984 int should_copy = TRUE;
7985 char_u *save_p_isk = NULL; /* init for GCC */
7986 int dont_do_help;
7987 int did_isk = FALSE;
7988
7989 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007990 * Skip this when the option defaults have not been set yet. Happens when
7991 * main() allocates the first buffer.
7992 */
7993 if (p_cpo != NULL)
7994 {
7995 /*
7996 * Always copy when entering and 'cpo' contains 'S'.
7997 * Don't copy when already initialized.
7998 * Don't copy when 'cpo' contains 's' and not entering.
7999 * 'S' BCO_ENTER initialized 's' should_copy
8000 * yes yes X X TRUE
8001 * yes no yes X FALSE
8002 * no X yes X FALSE
8003 * X no no yes FALSE
8004 * X no no no TRUE
8005 * no yes no X TRUE
8006 */
8007 if ((vim_strchr(p_cpo, CPO_BUFOPTGLOB) == NULL || !(flags & BCO_ENTER))
8008 && (buf->b_p_initialized
8009 || (!(flags & BCO_ENTER)
8010 && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
8011 should_copy = FALSE;
8012
8013 if (should_copy || (flags & BCO_ALWAYS))
8014 {
8015 /* Don't copy the options specific to a help buffer when
8016 * BCO_NOHELP is given or the options were initialized already
8017 * (jumping back to a help file with CTRL-T or CTRL-O) */
8018 dont_do_help = ((flags & BCO_NOHELP) && buf->b_help)
8019 || buf->b_p_initialized;
8020 if (dont_do_help) /* don't free b_p_isk */
8021 {
8022 save_p_isk = buf->b_p_isk;
8023 buf->b_p_isk = NULL;
8024 }
8025 /*
Bram Moolenaar40385db2018-08-07 22:31:44 +02008026 * Always free the allocated strings. If not already initialized,
8027 * reset 'readonly' and copy 'fileformat'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008028 */
8029 if (!buf->b_p_initialized)
8030 {
8031 free_buf_options(buf, TRUE);
8032 buf->b_p_ro = FALSE; /* don't copy readonly */
8033 buf->b_p_tx = p_tx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008034 buf->b_p_fenc = vim_strsave(p_fenc);
Bram Moolenaare8ef3a02016-10-12 17:45:29 +02008035 switch (*p_ffs)
8036 {
8037 case 'm':
8038 buf->b_p_ff = vim_strsave((char_u *)FF_MAC); break;
8039 case 'd':
8040 buf->b_p_ff = vim_strsave((char_u *)FF_DOS); break;
8041 case 'u':
8042 buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); break;
8043 default:
8044 buf->b_p_ff = vim_strsave(p_ff);
8045 }
8046 if (buf->b_p_ff != NULL)
8047 buf->b_start_ffc = *buf->b_p_ff;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008048 buf->b_p_bh = empty_option;
8049 buf->b_p_bt = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008050 }
8051 else
8052 free_buf_options(buf, FALSE);
8053
8054 buf->b_p_ai = p_ai;
8055 buf->b_p_ai_nopaste = p_ai_nopaste;
8056 buf->b_p_sw = p_sw;
8057 buf->b_p_tw = p_tw;
8058 buf->b_p_tw_nopaste = p_tw_nopaste;
8059 buf->b_p_tw_nobin = p_tw_nobin;
8060 buf->b_p_wm = p_wm;
8061 buf->b_p_wm_nopaste = p_wm_nopaste;
8062 buf->b_p_wm_nobin = p_wm_nobin;
8063 buf->b_p_bin = p_bin;
Bram Moolenaare8bb2552005-07-08 22:26:47 +00008064 buf->b_p_bomb = p_bomb;
Bram Moolenaarb388be02015-07-22 22:19:38 +02008065 buf->b_p_fixeol = p_fixeol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008066 buf->b_p_et = p_et;
8067 buf->b_p_et_nobin = p_et_nobin;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008068 buf->b_p_et_nopaste = p_et_nopaste;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008069 buf->b_p_ml = p_ml;
8070 buf->b_p_ml_nobin = p_ml_nobin;
8071 buf->b_p_inf = p_inf;
Bram Moolenaar3bab9392017-04-07 15:42:25 +02008072 buf->b_p_swf = cmdmod.noswapfile ? FALSE : p_swf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008073 buf->b_p_cpt = vim_strsave(p_cpt);
Bram Moolenaare2c453d2019-08-21 14:37:09 +02008074#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarac3150d2019-07-28 16:36:39 +02008075 buf->b_p_csl = vim_strsave(p_csl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008076#endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00008077#ifdef FEAT_COMPL_FUNC
8078 buf->b_p_cfu = vim_strsave(p_cfu);
Bram Moolenaare344bea2005-09-01 20:46:49 +00008079 buf->b_p_ofu = vim_strsave(p_ofu);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00008080#endif
Bram Moolenaar45e18cb2019-04-28 18:05:35 +02008081#ifdef FEAT_EVAL
8082 buf->b_p_tfu = vim_strsave(p_tfu);
8083#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008084 buf->b_p_sts = p_sts;
8085 buf->b_p_sts_nopaste = p_sts_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008086#ifdef FEAT_VARTABS
8087 buf->b_p_vsts = vim_strsave(p_vsts);
8088 if (p_vsts && p_vsts != empty_option)
8089 tabstop_set(p_vsts, &buf->b_p_vsts_array);
8090 else
8091 buf->b_p_vsts_array = 0;
8092 buf->b_p_vsts_nopaste = p_vsts_nopaste
8093 ? vim_strsave(p_vsts_nopaste) : NULL;
8094#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008095 buf->b_p_sn = p_sn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008096#ifdef FEAT_COMMENTS
8097 buf->b_p_com = vim_strsave(p_com);
8098#endif
8099#ifdef FEAT_FOLDING
8100 buf->b_p_cms = vim_strsave(p_cms);
8101#endif
8102 buf->b_p_fo = vim_strsave(p_fo);
Bram Moolenaar86b68352004-12-27 21:59:20 +00008103 buf->b_p_flp = vim_strsave(p_flp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008104 buf->b_p_nf = vim_strsave(p_nf);
8105 buf->b_p_mps = vim_strsave(p_mps);
8106#ifdef FEAT_SMARTINDENT
8107 buf->b_p_si = p_si;
8108#endif
8109 buf->b_p_ci = p_ci;
8110#ifdef FEAT_CINDENT
8111 buf->b_p_cin = p_cin;
8112 buf->b_p_cink = vim_strsave(p_cink);
8113 buf->b_p_cino = vim_strsave(p_cino);
8114#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008115 /* Don't copy 'filetype', it must be detected */
8116 buf->b_p_ft = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008117 buf->b_p_pi = p_pi;
8118#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
8119 buf->b_p_cinw = vim_strsave(p_cinw);
8120#endif
8121#ifdef FEAT_LISP
8122 buf->b_p_lisp = p_lisp;
8123#endif
8124#ifdef FEAT_SYN_HL
8125 /* Don't copy 'syntax', it must be set */
8126 buf->b_p_syn = empty_option;
Bram Moolenaar3b56eb32005-07-11 22:40:32 +00008127 buf->b_p_smc = p_smc;
Bram Moolenaarb8060fe2016-01-19 22:29:28 +01008128 buf->b_s.b_syn_isk = empty_option;
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00008129#endif
8130#ifdef FEAT_SPELL
Bram Moolenaard5784f92010-10-13 14:05:35 +02008131 buf->b_s.b_p_spc = vim_strsave(p_spc);
Bram Moolenaar860cae12010-06-05 23:22:07 +02008132 (void)compile_cap_prog(&buf->b_s);
8133 buf->b_s.b_p_spf = vim_strsave(p_spf);
8134 buf->b_s.b_p_spl = vim_strsave(p_spl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008135#endif
8136#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
8137 buf->b_p_inde = vim_strsave(p_inde);
8138 buf->b_p_indk = vim_strsave(p_indk);
8139#endif
Bram Moolenaar9be7c042017-01-14 14:28:30 +01008140 buf->b_p_fp = empty_option;
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00008141#if defined(FEAT_EVAL)
8142 buf->b_p_fex = vim_strsave(p_fex);
8143#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008144#ifdef FEAT_CRYPT
8145 buf->b_p_key = vim_strsave(p_key);
8146#endif
8147#ifdef FEAT_SEARCHPATH
8148 buf->b_p_sua = vim_strsave(p_sua);
8149#endif
8150#ifdef FEAT_KEYMAP
8151 buf->b_p_keymap = vim_strsave(p_keymap);
8152 buf->b_kmap_state |= KEYMAP_INIT;
8153#endif
Bram Moolenaar6d150f72018-04-21 20:03:20 +02008154#ifdef FEAT_TERMINAL
8155 buf->b_p_twsl = p_twsl;
8156#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008157 /* This isn't really an option, but copying the langmap and IME
8158 * state from the current buffer is better than resetting it. */
8159 buf->b_p_iminsert = p_iminsert;
8160 buf->b_p_imsearch = p_imsearch;
8161
8162 /* options that are normally global but also have a local value
8163 * are not copied, start using the global value */
8164 buf->b_p_ar = -1;
Bram Moolenaarf5a2fd82013-11-06 05:26:15 +01008165 buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02008166 buf->b_p_bkc = empty_option;
8167 buf->b_bkc_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008168#ifdef FEAT_QUICKFIX
8169 buf->b_p_gp = empty_option;
8170 buf->b_p_mp = empty_option;
8171 buf->b_p_efm = empty_option;
8172#endif
8173 buf->b_p_ep = empty_option;
8174 buf->b_p_kp = empty_option;
8175 buf->b_p_path = empty_option;
8176 buf->b_p_tags = empty_option;
Bram Moolenaar0f6562e2015-11-24 18:48:14 +01008177 buf->b_p_tc = empty_option;
8178 buf->b_tc_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008179#ifdef FEAT_FIND_ID
8180 buf->b_p_def = empty_option;
8181 buf->b_p_inc = empty_option;
8182# ifdef FEAT_EVAL
8183 buf->b_p_inex = vim_strsave(p_inex);
8184# endif
8185#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008186 buf->b_p_dict = empty_option;
8187 buf->b_p_tsr = empty_option;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00008188#ifdef FEAT_TEXTOBJ
8189 buf->b_p_qe = vim_strsave(p_qe);
8190#endif
Bram Moolenaar9b2200a2006-03-20 21:55:45 +00008191#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
8192 buf->b_p_bexpr = empty_option;
8193#endif
Bram Moolenaar49771f42010-07-20 17:32:38 +02008194#if defined(FEAT_CRYPT)
8195 buf->b_p_cm = empty_option;
8196#endif
Bram Moolenaar55debbe2010-05-23 23:34:36 +02008197#ifdef FEAT_PERSISTENT_UNDO
8198 buf->b_p_udf = p_udf;
8199#endif
Bram Moolenaaraf6c1312014-03-12 18:55:58 +01008200#ifdef FEAT_LISP
8201 buf->b_p_lw = empty_option;
8202#endif
Bram Moolenaar2c7292d2017-03-05 17:43:31 +01008203 buf->b_p_menc = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008204
8205 /*
8206 * Don't copy the options set by ex_help(), use the saved values,
8207 * when going from a help buffer to a non-help buffer.
8208 * Don't touch these at all when BCO_NOHELP is used and going from
8209 * or to a help buffer.
8210 */
8211 if (dont_do_help)
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008212 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008213 buf->b_p_isk = save_p_isk;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008214#ifdef FEAT_VARTABS
8215 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
8216 tabstop_set(p_vts, &buf->b_p_vts_array);
8217 else
8218 buf->b_p_vts_array = NULL;
8219#endif
8220 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008221 else
8222 {
8223 buf->b_p_isk = vim_strsave(p_isk);
8224 did_isk = TRUE;
8225 buf->b_p_ts = p_ts;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008226#ifdef FEAT_VARTABS
8227 buf->b_p_vts = vim_strsave(p_vts);
8228 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
8229 tabstop_set(p_vts, &buf->b_p_vts_array);
8230 else
8231 buf->b_p_vts_array = NULL;
8232#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008233 buf->b_help = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008234 if (buf->b_p_bt[0] == 'h')
8235 clear_string_option(&buf->b_p_bt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008236 buf->b_p_ma = p_ma;
8237 }
8238 }
8239
8240 /*
8241 * When the options should be copied (ignoring BCO_ALWAYS), set the
8242 * flag that indicates that the options have been initialized.
8243 */
8244 if (should_copy)
8245 buf->b_p_initialized = TRUE;
8246 }
8247
8248 check_buf_options(buf); /* make sure we don't have NULLs */
8249 if (did_isk)
8250 (void)buf_init_chartab(buf, FALSE);
8251}
8252
8253/*
8254 * Reset the 'modifiable' option and its default value.
8255 */
8256 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008257reset_modifiable(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008258{
8259 int opt_idx;
8260
8261 curbuf->b_p_ma = FALSE;
8262 p_ma = FALSE;
8263 opt_idx = findoption((char_u *)"ma");
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00008264 if (opt_idx >= 0)
8265 options[opt_idx].def_val[VI_DEFAULT] = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008266}
8267
8268/*
8269 * Set the global value for 'iminsert' to the local value.
8270 */
8271 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008272set_iminsert_global(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008273{
8274 p_iminsert = curbuf->b_p_iminsert;
8275}
8276
8277/*
8278 * Set the global value for 'imsearch' to the local value.
8279 */
8280 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008281set_imsearch_global(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008282{
8283 p_imsearch = curbuf->b_p_imsearch;
8284}
8285
Bram Moolenaar071d4272004-06-13 20:20:40 +00008286static int expand_option_idx = -1;
8287static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL};
8288static int expand_option_flags = 0;
8289
8290 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008291set_context_in_set_cmd(
8292 expand_T *xp,
8293 char_u *arg,
8294 int opt_flags) /* OPT_GLOBAL and/or OPT_LOCAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008295{
8296 int nextchar;
8297 long_u flags = 0; /* init for GCC */
8298 int opt_idx = 0; /* init for GCC */
8299 char_u *p;
8300 char_u *s;
8301 int is_term_option = FALSE;
8302 int key;
8303
8304 expand_option_flags = opt_flags;
8305
8306 xp->xp_context = EXPAND_SETTINGS;
8307 if (*arg == NUL)
8308 {
8309 xp->xp_pattern = arg;
8310 return;
8311 }
8312 p = arg + STRLEN(arg) - 1;
8313 if (*p == ' ' && *(p - 1) != '\\')
8314 {
8315 xp->xp_pattern = p + 1;
8316 return;
8317 }
8318 while (p > arg)
8319 {
8320 s = p;
8321 /* count number of backslashes before ' ' or ',' */
8322 if (*p == ' ' || *p == ',')
8323 {
8324 while (s > arg && *(s - 1) == '\\')
8325 --s;
8326 }
8327 /* break at a space with an even number of backslashes */
8328 if (*p == ' ' && ((p - s) & 1) == 0)
8329 {
8330 ++p;
8331 break;
8332 }
8333 --p;
8334 }
Bram Moolenaar2a7b9ee2009-06-16 15:50:33 +00008335 if (STRNCMP(p, "no", 2) == 0 && STRNCMP(p, "novice", 6) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008336 {
8337 xp->xp_context = EXPAND_BOOL_SETTINGS;
8338 p += 2;
8339 }
8340 if (STRNCMP(p, "inv", 3) == 0)
8341 {
8342 xp->xp_context = EXPAND_BOOL_SETTINGS;
8343 p += 3;
8344 }
8345 xp->xp_pattern = arg = p;
8346 if (*arg == '<')
8347 {
8348 while (*p != '>')
8349 if (*p++ == NUL) /* expand terminal option name */
8350 return;
8351 key = get_special_key_code(arg + 1);
8352 if (key == 0) /* unknown name */
8353 {
8354 xp->xp_context = EXPAND_NOTHING;
8355 return;
8356 }
8357 nextchar = *++p;
8358 is_term_option = TRUE;
8359 expand_option_name[2] = KEY2TERMCAP0(key);
8360 expand_option_name[3] = KEY2TERMCAP1(key);
8361 }
8362 else
8363 {
8364 if (p[0] == 't' && p[1] == '_')
8365 {
8366 p += 2;
8367 if (*p != NUL)
8368 ++p;
8369 if (*p == NUL)
8370 return; /* expand option name */
8371 nextchar = *++p;
8372 is_term_option = TRUE;
8373 expand_option_name[2] = p[-2];
8374 expand_option_name[3] = p[-1];
8375 }
8376 else
8377 {
8378 /* Allow * wildcard */
8379 while (ASCII_ISALNUM(*p) || *p == '_' || *p == '*')
8380 p++;
8381 if (*p == NUL)
8382 return;
8383 nextchar = *p;
8384 *p = NUL;
8385 opt_idx = findoption(arg);
8386 *p = nextchar;
8387 if (opt_idx == -1 || options[opt_idx].var == NULL)
8388 {
8389 xp->xp_context = EXPAND_NOTHING;
8390 return;
8391 }
8392 flags = options[opt_idx].flags;
8393 if (flags & P_BOOL)
8394 {
8395 xp->xp_context = EXPAND_NOTHING;
8396 return;
8397 }
8398 }
8399 }
8400 /* handle "-=" and "+=" */
8401 if ((nextchar == '-' || nextchar == '+' || nextchar == '^') && p[1] == '=')
8402 {
8403 ++p;
8404 nextchar = '=';
8405 }
8406 if ((nextchar != '=' && nextchar != ':')
8407 || xp->xp_context == EXPAND_BOOL_SETTINGS)
8408 {
8409 xp->xp_context = EXPAND_UNSUCCESSFUL;
8410 return;
8411 }
8412 if (xp->xp_context != EXPAND_BOOL_SETTINGS && p[1] == NUL)
8413 {
8414 xp->xp_context = EXPAND_OLD_SETTING;
8415 if (is_term_option)
8416 expand_option_idx = -1;
8417 else
8418 expand_option_idx = opt_idx;
8419 xp->xp_pattern = p + 1;
8420 return;
8421 }
8422 xp->xp_context = EXPAND_NOTHING;
8423 if (is_term_option || (flags & P_NUM))
8424 return;
8425
8426 xp->xp_pattern = p + 1;
8427
8428 if (flags & P_EXPAND)
8429 {
8430 p = options[opt_idx].var;
8431 if (p == (char_u *)&p_bdir
8432 || p == (char_u *)&p_dir
8433 || p == (char_u *)&p_path
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +01008434 || p == (char_u *)&p_pp
Bram Moolenaar071d4272004-06-13 20:20:40 +00008435 || p == (char_u *)&p_rtp
8436#ifdef FEAT_SEARCHPATH
8437 || p == (char_u *)&p_cdpath
8438#endif
8439#ifdef FEAT_SESSION
8440 || p == (char_u *)&p_vdir
8441#endif
8442 )
8443 {
8444 xp->xp_context = EXPAND_DIRECTORIES;
8445 if (p == (char_u *)&p_path
8446#ifdef FEAT_SEARCHPATH
8447 || p == (char_u *)&p_cdpath
8448#endif
8449 )
8450 xp->xp_backslash = XP_BS_THREE;
8451 else
8452 xp->xp_backslash = XP_BS_ONE;
8453 }
8454 else
8455 {
8456 xp->xp_context = EXPAND_FILES;
8457 /* for 'tags' need three backslashes for a space */
8458 if (p == (char_u *)&p_tags)
8459 xp->xp_backslash = XP_BS_THREE;
8460 else
8461 xp->xp_backslash = XP_BS_ONE;
8462 }
8463 }
8464
8465 /* For an option that is a list of file names, find the start of the
8466 * last file name. */
8467 for (p = arg + STRLEN(arg) - 1; p > xp->xp_pattern; --p)
8468 {
8469 /* count number of backslashes before ' ' or ',' */
8470 if (*p == ' ' || *p == ',')
8471 {
8472 s = p;
8473 while (s > xp->xp_pattern && *(s - 1) == '\\')
8474 --s;
8475 if ((*p == ' ' && (xp->xp_backslash == XP_BS_THREE && (p - s) < 3))
8476 || (*p == ',' && (flags & P_COMMA) && ((p - s) & 1) == 0))
8477 {
8478 xp->xp_pattern = p + 1;
8479 break;
8480 }
8481 }
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00008482
Bram Moolenaarb9a02fc2006-03-12 22:08:12 +00008483#ifdef FEAT_SPELL
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00008484 /* for 'spellsuggest' start at "file:" */
8485 if (options[opt_idx].var == (char_u *)&p_sps
8486 && STRNCMP(p, "file:", 5) == 0)
8487 {
8488 xp->xp_pattern = p + 5;
8489 break;
8490 }
8491#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008492 }
8493
8494 return;
8495}
8496
8497 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01008498ExpandSettings(
8499 expand_T *xp,
8500 regmatch_T *regmatch,
8501 int *num_file,
8502 char_u ***file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008503{
8504 int num_normal = 0; /* Nr of matching non-term-code settings */
8505 int num_term = 0; /* Nr of matching terminal code settings */
8506 int opt_idx;
8507 int match;
8508 int count = 0;
8509 char_u *str;
8510 int loop;
8511 int is_term_opt;
8512 char_u name_buf[MAX_KEY_NAME_LEN];
8513 static char *(names[]) = {"all", "termcap"};
8514 int ic = regmatch->rm_ic; /* remember the ignore-case flag */
8515
8516 /* do this loop twice:
8517 * loop == 0: count the number of matching options
8518 * loop == 1: copy the matching options into allocated memory
8519 */
8520 for (loop = 0; loop <= 1; ++loop)
8521 {
8522 regmatch->rm_ic = ic;
8523 if (xp->xp_context != EXPAND_BOOL_SETTINGS)
8524 {
Bram Moolenaar2c4278f2009-05-17 11:33:22 +00008525 for (match = 0; match < (int)(sizeof(names) / sizeof(char *));
8526 ++match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008527 if (vim_regexec(regmatch, (char_u *)names[match], (colnr_T)0))
8528 {
8529 if (loop == 0)
8530 num_normal++;
8531 else
8532 (*file)[count++] = vim_strsave((char_u *)names[match]);
8533 }
8534 }
8535 for (opt_idx = 0; (str = (char_u *)options[opt_idx].fullname) != NULL;
8536 opt_idx++)
8537 {
8538 if (options[opt_idx].var == NULL)
8539 continue;
8540 if (xp->xp_context == EXPAND_BOOL_SETTINGS
8541 && !(options[opt_idx].flags & P_BOOL))
8542 continue;
8543 is_term_opt = istermoption(&options[opt_idx]);
8544 if (is_term_opt && num_normal > 0)
8545 continue;
8546 match = FALSE;
8547 if (vim_regexec(regmatch, str, (colnr_T)0)
8548 || (options[opt_idx].shortname != NULL
8549 && vim_regexec(regmatch,
8550 (char_u *)options[opt_idx].shortname, (colnr_T)0)))
8551 match = TRUE;
8552 else if (is_term_opt)
8553 {
8554 name_buf[0] = '<';
8555 name_buf[1] = 't';
8556 name_buf[2] = '_';
8557 name_buf[3] = str[2];
8558 name_buf[4] = str[3];
8559 name_buf[5] = '>';
8560 name_buf[6] = NUL;
8561 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
8562 {
8563 match = TRUE;
8564 str = name_buf;
8565 }
8566 }
8567 if (match)
8568 {
8569 if (loop == 0)
8570 {
8571 if (is_term_opt)
8572 num_term++;
8573 else
8574 num_normal++;
8575 }
8576 else
8577 (*file)[count++] = vim_strsave(str);
8578 }
8579 }
8580 /*
8581 * Check terminal key codes, these are not in the option table
8582 */
8583 if (xp->xp_context != EXPAND_BOOL_SETTINGS && num_normal == 0)
8584 {
8585 for (opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++)
8586 {
8587 if (!isprint(str[0]) || !isprint(str[1]))
8588 continue;
8589
8590 name_buf[0] = 't';
8591 name_buf[1] = '_';
8592 name_buf[2] = str[0];
8593 name_buf[3] = str[1];
8594 name_buf[4] = NUL;
8595
8596 match = FALSE;
8597 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
8598 match = TRUE;
8599 else
8600 {
8601 name_buf[0] = '<';
8602 name_buf[1] = 't';
8603 name_buf[2] = '_';
8604 name_buf[3] = str[0];
8605 name_buf[4] = str[1];
8606 name_buf[5] = '>';
8607 name_buf[6] = NUL;
8608
8609 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
8610 match = TRUE;
8611 }
8612 if (match)
8613 {
8614 if (loop == 0)
8615 num_term++;
8616 else
8617 (*file)[count++] = vim_strsave(name_buf);
8618 }
8619 }
8620
8621 /*
8622 * Check special key names.
8623 */
8624 regmatch->rm_ic = TRUE; /* ignore case here */
8625 for (opt_idx = 0; (str = get_key_name(opt_idx)) != NULL; opt_idx++)
8626 {
8627 name_buf[0] = '<';
8628 STRCPY(name_buf + 1, str);
8629 STRCAT(name_buf, ">");
8630
8631 if (vim_regexec(regmatch, name_buf, (colnr_T)0))
8632 {
8633 if (loop == 0)
8634 num_term++;
8635 else
8636 (*file)[count++] = vim_strsave(name_buf);
8637 }
8638 }
8639 }
8640 if (loop == 0)
8641 {
8642 if (num_normal > 0)
8643 *num_file = num_normal;
8644 else if (num_term > 0)
8645 *num_file = num_term;
8646 else
8647 return OK;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008648 *file = ALLOC_MULT(char_u *, *num_file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008649 if (*file == NULL)
8650 {
8651 *file = (char_u **)"";
8652 return FAIL;
8653 }
8654 }
8655 }
8656 return OK;
8657}
8658
8659 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01008660ExpandOldSetting(int *num_file, char_u ***file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008661{
8662 char_u *var = NULL; /* init for GCC */
8663 char_u *buf;
8664
8665 *num_file = 0;
Bram Moolenaarc799fe22019-05-28 23:08:19 +02008666 *file = ALLOC_ONE(char_u *);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008667 if (*file == NULL)
8668 return FAIL;
8669
8670 /*
8671 * For a terminal key code expand_option_idx is < 0.
8672 */
8673 if (expand_option_idx < 0)
8674 {
8675 var = find_termcode(expand_option_name + 2);
8676 if (var == NULL)
8677 expand_option_idx = findoption(expand_option_name);
8678 }
8679
8680 if (expand_option_idx >= 0)
8681 {
8682 /* put string of option value in NameBuff */
8683 option_value2string(&options[expand_option_idx], expand_option_flags);
8684 var = NameBuff;
8685 }
8686 else if (var == NULL)
8687 var = (char_u *)"";
8688
8689 /* A backslash is required before some characters. This is the reverse of
8690 * what happens in do_set(). */
8691 buf = vim_strsave_escaped(var, escape_chars);
8692
8693 if (buf == NULL)
8694 {
Bram Moolenaard23a8232018-02-10 18:45:26 +01008695 VIM_CLEAR(*file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008696 return FAIL;
8697 }
8698
8699#ifdef BACKSLASH_IN_FILENAME
8700 /* For MS-Windows et al. we don't double backslashes at the start and
8701 * before a file name character. */
Bram Moolenaar91acfff2017-03-12 19:22:36 +01008702 for (var = buf; *var != NUL; MB_PTR_ADV(var))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008703 if (var[0] == '\\' && var[1] == '\\'
8704 && expand_option_idx >= 0
8705 && (options[expand_option_idx].flags & P_EXPAND)
8706 && vim_isfilec(var[2])
8707 && (var[2] != '\\' || (var == buf && var[4] != '\\')))
Bram Moolenaarc1a11ed2008-06-24 22:09:24 +00008708 STRMOVE(var, var + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008709#endif
8710
8711 *file[0] = buf;
8712 *num_file = 1;
8713 return OK;
8714}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008715
8716/*
8717 * Get the value for the numeric or string option *opp in a nice format into
8718 * NameBuff[]. Must not be called with a hidden option!
8719 */
8720 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008721option_value2string(
8722 struct vimoption *opp,
8723 int opt_flags) /* OPT_GLOBAL and/or OPT_LOCAL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008724{
8725 char_u *varp;
8726
8727 varp = get_varp_scope(opp, opt_flags);
8728
8729 if (opp->flags & P_NUM)
8730 {
8731 long wc = 0;
8732
8733 if (wc_use_keyname(varp, &wc))
8734 STRCPY(NameBuff, get_special_key_name((int)wc, 0));
8735 else if (wc != 0)
8736 STRCPY(NameBuff, transchar((int)wc));
8737 else
8738 sprintf((char *)NameBuff, "%ld", *(long *)varp);
8739 }
8740 else /* P_STRING */
8741 {
8742 varp = *(char_u **)(varp);
8743 if (varp == NULL) /* just in case */
8744 NameBuff[0] = NUL;
8745#ifdef FEAT_CRYPT
8746 /* don't show the actual value of 'key', only that it's set */
Bram Moolenaareb3593b2006-04-22 22:33:57 +00008747 else if (opp->var == (char_u *)&p_key && *varp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008748 STRCPY(NameBuff, "*****");
8749#endif
8750 else if (opp->flags & P_EXPAND)
8751 home_replace(NULL, varp, NameBuff, MAXPATHL, FALSE);
8752 /* Translate 'pastetoggle' into special key names */
8753 else if ((char_u **)opp->var == &p_pt)
8754 str2specialbuf(p_pt, NameBuff, MAXPATHL);
8755 else
Bram Moolenaarce0842a2005-07-18 21:58:11 +00008756 vim_strncpy(NameBuff, varp, MAXPATHL - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008757 }
8758}
8759
8760/*
8761 * Return TRUE if "varp" points to 'wildchar' or 'wildcharm' and it can be
8762 * printed as a keyname.
8763 * "*wcp" is set to the value of the option if it's 'wildchar' or 'wildcharm'.
8764 */
8765 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01008766wc_use_keyname(char_u *varp, long *wcp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008767{
8768 if (((long *)varp == &p_wc) || ((long *)varp == &p_wcm))
8769 {
8770 *wcp = *(long *)varp;
8771 if (IS_SPECIAL(*wcp) || find_special_key_in_table((int)*wcp) >= 0)
8772 return TRUE;
8773 }
8774 return FALSE;
8775}
8776
Bram Moolenaar071d4272004-06-13 20:20:40 +00008777/*
8778 * Return TRUE if format option 'x' is in effect.
8779 * Take care of no formatting when 'paste' is set.
8780 */
8781 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01008782has_format_option(int x)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008783{
8784 if (p_paste)
8785 return FALSE;
8786 return (vim_strchr(curbuf->b_p_fo, x) != NULL);
8787}
8788
8789/*
8790 * Return TRUE if "x" is present in 'shortmess' option, or
8791 * 'shortmess' contains 'a' and "x" is present in SHM_A.
8792 */
8793 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01008794shortmess(int x)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008795{
Bram Moolenaar7f29f7a2012-02-29 13:51:37 +01008796 return p_shm != NULL &&
8797 ( vim_strchr(p_shm, x) != NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00008798 || (vim_strchr(p_shm, 'a') != NULL
8799 && vim_strchr((char_u *)SHM_A, x) != NULL));
8800}
8801
8802/*
8803 * paste_option_changed() - Called after p_paste was set or reset.
8804 */
8805 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008806paste_option_changed(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008807{
8808 static int old_p_paste = FALSE;
8809 static int save_sm = 0;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008810 static int save_sta = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008811#ifdef FEAT_CMDL_INFO
8812 static int save_ru = 0;
8813#endif
8814#ifdef FEAT_RIGHTLEFT
8815 static int save_ri = 0;
8816 static int save_hkmap = 0;
8817#endif
8818 buf_T *buf;
8819
8820 if (p_paste)
8821 {
8822 /*
8823 * Paste switched from off to on.
8824 * Save the current values, so they can be restored later.
8825 */
8826 if (!old_p_paste)
8827 {
8828 /* save options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02008829 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008830 {
8831 buf->b_p_tw_nopaste = buf->b_p_tw;
8832 buf->b_p_wm_nopaste = buf->b_p_wm;
8833 buf->b_p_sts_nopaste = buf->b_p_sts;
8834 buf->b_p_ai_nopaste = buf->b_p_ai;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008835 buf->b_p_et_nopaste = buf->b_p_et;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008836#ifdef FEAT_VARTABS
8837 if (buf->b_p_vsts_nopaste)
8838 vim_free(buf->b_p_vsts_nopaste);
8839 buf->b_p_vsts_nopaste = buf->b_p_vsts && buf->b_p_vsts != empty_option
8840 ? vim_strsave(buf->b_p_vsts) : NULL;
8841#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008842 }
8843
8844 /* save global options */
8845 save_sm = p_sm;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008846 save_sta = p_sta;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008847#ifdef FEAT_CMDL_INFO
8848 save_ru = p_ru;
8849#endif
8850#ifdef FEAT_RIGHTLEFT
8851 save_ri = p_ri;
8852 save_hkmap = p_hkmap;
8853#endif
8854 /* save global values for local buffer options */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008855 p_ai_nopaste = p_ai;
8856 p_et_nopaste = p_et;
8857 p_sts_nopaste = p_sts;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008858 p_tw_nopaste = p_tw;
8859 p_wm_nopaste = p_wm;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008860#ifdef FEAT_VARTABS
8861 if (p_vsts_nopaste)
8862 vim_free(p_vsts_nopaste);
8863 p_vsts_nopaste = p_vsts && p_vsts != empty_option ? vim_strsave(p_vsts) : NULL;
8864#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008865 }
8866
8867 /*
8868 * Always set the option values, also when 'paste' is set when it is
8869 * already on.
8870 */
8871 /* set options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02008872 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008873 {
8874 buf->b_p_tw = 0; /* textwidth is 0 */
8875 buf->b_p_wm = 0; /* wrapmargin is 0 */
8876 buf->b_p_sts = 0; /* softtabstop is 0 */
8877 buf->b_p_ai = 0; /* no auto-indent */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008878 buf->b_p_et = 0; /* no expandtab */
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008879#ifdef FEAT_VARTABS
8880 if (buf->b_p_vsts)
8881 free_string_option(buf->b_p_vsts);
8882 buf->b_p_vsts = empty_option;
8883 if (buf->b_p_vsts_array)
8884 vim_free(buf->b_p_vsts_array);
8885 buf->b_p_vsts_array = 0;
8886#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008887 }
8888
8889 /* set global options */
8890 p_sm = 0; /* no showmatch */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008891 p_sta = 0; /* no smarttab */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008892#ifdef FEAT_CMDL_INFO
Bram Moolenaar071d4272004-06-13 20:20:40 +00008893 if (p_ru)
8894 status_redraw_all(); /* redraw to remove the ruler */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008895 p_ru = 0; /* no ruler */
8896#endif
8897#ifdef FEAT_RIGHTLEFT
8898 p_ri = 0; /* no reverse insert */
8899 p_hkmap = 0; /* no Hebrew keyboard */
8900#endif
8901 /* set global values for local buffer options */
8902 p_tw = 0;
8903 p_wm = 0;
8904 p_sts = 0;
8905 p_ai = 0;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008906#ifdef FEAT_VARTABS
8907 if (p_vsts)
8908 free_string_option(p_vsts);
8909 p_vsts = empty_option;
8910#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008911 }
8912
8913 /*
8914 * Paste switched from on to off: Restore saved values.
8915 */
8916 else if (old_p_paste)
8917 {
8918 /* restore options for each buffer */
Bram Moolenaar29323592016-07-24 22:04:11 +02008919 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008920 {
8921 buf->b_p_tw = buf->b_p_tw_nopaste;
8922 buf->b_p_wm = buf->b_p_wm_nopaste;
8923 buf->b_p_sts = buf->b_p_sts_nopaste;
8924 buf->b_p_ai = buf->b_p_ai_nopaste;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008925 buf->b_p_et = buf->b_p_et_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008926#ifdef FEAT_VARTABS
8927 if (buf->b_p_vsts)
8928 free_string_option(buf->b_p_vsts);
8929 buf->b_p_vsts = buf->b_p_vsts_nopaste
8930 ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option;
8931 if (buf->b_p_vsts_array)
8932 vim_free(buf->b_p_vsts_array);
8933 if (buf->b_p_vsts && buf->b_p_vsts != empty_option)
8934 tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
8935 else
8936 buf->b_p_vsts_array = 0;
8937#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008938 }
8939
8940 /* restore global options */
8941 p_sm = save_sm;
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008942 p_sta = save_sta;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008943#ifdef FEAT_CMDL_INFO
Bram Moolenaar071d4272004-06-13 20:20:40 +00008944 if (p_ru != save_ru)
8945 status_redraw_all(); /* redraw to draw the ruler */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008946 p_ru = save_ru;
8947#endif
8948#ifdef FEAT_RIGHTLEFT
8949 p_ri = save_ri;
8950 p_hkmap = save_hkmap;
8951#endif
8952 /* set global values for local buffer options */
Bram Moolenaar54f018c2015-09-15 17:30:40 +02008953 p_ai = p_ai_nopaste;
8954 p_et = p_et_nopaste;
8955 p_sts = p_sts_nopaste;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008956 p_tw = p_tw_nopaste;
8957 p_wm = p_wm_nopaste;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02008958#ifdef FEAT_VARTABS
8959 if (p_vsts)
8960 free_string_option(p_vsts);
8961 p_vsts = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : empty_option;
8962#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00008963 }
8964
8965 old_p_paste = p_paste;
8966}
8967
8968/*
8969 * vimrc_found() - Called when a ".vimrc" or "VIMINIT" has been found.
8970 *
8971 * Reset 'compatible' and set the values for options that didn't get set yet
8972 * to the Vim defaults.
8973 * Don't do this if the 'compatible' option has been set or reset before.
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008974 * When "fname" is not NULL, use it to set $"envname" when it wasn't set yet.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008975 */
8976 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01008977vimrc_found(char_u *fname, char_u *envname)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008978{
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008979 int opt_idx;
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00008980 int dofree = FALSE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008981 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008982
8983 if (!option_was_set((char_u *)"cp"))
8984 {
8985 p_cp = FALSE;
8986 for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
8987 if (!(options[opt_idx].flags & (P_WAS_SET|P_VI_DEF)))
8988 set_option_default(opt_idx, OPT_FREE, FALSE);
8989 didset_options();
Bram Moolenaare68c25c2015-08-25 15:39:55 +02008990 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008991 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +00008992
8993 if (fname != NULL)
8994 {
8995 p = vim_getenv(envname, &dofree);
8996 if (p == NULL)
8997 {
8998 /* Set $MYVIMRC to the first vimrc file found. */
8999 p = FullName_save(fname, FALSE);
9000 if (p != NULL)
9001 {
9002 vim_setenv(envname, p);
9003 vim_free(p);
9004 }
9005 }
9006 else if (dofree)
9007 vim_free(p);
9008 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009009}
9010
9011/*
9012 * Set 'compatible' on or off. Called for "-C" and "-N" command line arg.
9013 */
9014 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01009015change_compatible(int on)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009016{
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00009017 int opt_idx;
9018
Bram Moolenaar071d4272004-06-13 20:20:40 +00009019 if (p_cp != on)
9020 {
9021 p_cp = on;
9022 compatible_set();
9023 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00009024 opt_idx = findoption((char_u *)"cp");
9025 if (opt_idx >= 0)
9026 options[opt_idx].flags |= P_WAS_SET;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009027}
9028
9029/*
9030 * Return TRUE when option "name" has been set.
Bram Moolenaar1a4a75c2013-07-28 16:03:06 +02009031 * Only works correctly for global options.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009032 */
9033 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009034option_was_set(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009035{
9036 int idx;
9037
9038 idx = findoption(name);
9039 if (idx < 0) /* unknown option */
9040 return FALSE;
9041 if (options[idx].flags & P_WAS_SET)
9042 return TRUE;
9043 return FALSE;
9044}
9045
9046/*
Bram Moolenaar15d55de2012-12-05 14:43:02 +01009047 * Reset the flag indicating option "name" was set.
9048 */
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02009049 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009050reset_option_was_set(char_u *name)
Bram Moolenaar15d55de2012-12-05 14:43:02 +01009051{
9052 int idx = findoption(name);
9053
9054 if (idx >= 0)
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02009055 {
Bram Moolenaar15d55de2012-12-05 14:43:02 +01009056 options[idx].flags &= ~P_WAS_SET;
Bram Moolenaarfe8ef982018-09-13 20:31:54 +02009057 return OK;
9058 }
9059 return FAIL;
Bram Moolenaar15d55de2012-12-05 14:43:02 +01009060}
9061
9062/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009063 * compatible_set() - Called when 'compatible' has been set or unset.
9064 *
9065 * When 'compatible' set: Set all relevant options (those that have the P_VIM)
9066 * flag) to a Vi compatible value.
9067 * When 'compatible' is unset: Set all options that have a different default
9068 * for Vim (without the P_VI_DEF flag) to that default.
9069 */
9070 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01009071compatible_set(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009072{
9073 int opt_idx;
9074
9075 for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
9076 if ( ((options[opt_idx].flags & P_VIM) && p_cp)
9077 || (!(options[opt_idx].flags & P_VI_DEF) && !p_cp))
9078 set_option_default(opt_idx, OPT_FREE, p_cp);
9079 didset_options();
Bram Moolenaare68c25c2015-08-25 15:39:55 +02009080 didset_options2();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009081}
9082
9083#ifdef FEAT_LINEBREAK
9084
Bram Moolenaar071d4272004-06-13 20:20:40 +00009085/*
9086 * fill_breakat_flags() -- called when 'breakat' changes value.
9087 */
9088 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01009089fill_breakat_flags(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009090{
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00009091 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009092 int i;
9093
9094 for (i = 0; i < 256; i++)
9095 breakat_flags[i] = FALSE;
9096
9097 if (p_breakat != NULL)
Bram Moolenaarac6e65f2005-08-29 22:25:38 +00009098 for (p = p_breakat; *p; p++)
9099 breakat_flags[*p] = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009100}
Bram Moolenaar071d4272004-06-13 20:20:40 +00009101#endif
9102
9103/*
9104 * Check an option that can be a range of string values.
9105 *
9106 * Return OK for correct value, FAIL otherwise.
9107 * Empty is always OK.
9108 */
9109 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009110check_opt_strings(
9111 char_u *val,
9112 char **values,
9113 int list) /* when TRUE: accept a list of values */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009114{
9115 return opt_strings_flags(val, values, NULL, list);
9116}
9117
9118/*
9119 * Handle an option that can be a range of string values.
9120 * Set a flag in "*flagp" for each string present.
9121 *
9122 * Return OK for correct value, FAIL otherwise.
9123 * Empty is always OK.
9124 */
9125 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009126opt_strings_flags(
9127 char_u *val, /* new value */
9128 char **values, /* array of valid string values */
9129 unsigned *flagp,
9130 int list) /* when TRUE: accept a list of values */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009131{
9132 int i;
9133 int len;
9134 unsigned new_flags = 0;
9135
9136 while (*val)
9137 {
9138 for (i = 0; ; ++i)
9139 {
9140 if (values[i] == NULL) /* val not found in values[] */
9141 return FAIL;
9142
9143 len = (int)STRLEN(values[i]);
9144 if (STRNCMP(values[i], val, len) == 0
9145 && ((list && val[len] == ',') || val[len] == NUL))
9146 {
9147 val += len + (val[len] == ',');
9148 new_flags |= (1 << i);
9149 break; /* check next item in val list */
9150 }
9151 }
9152 }
9153 if (flagp != NULL)
9154 *flagp = new_flags;
9155
9156 return OK;
9157}
9158
9159/*
9160 * Read the 'wildmode' option, fill wim_flags[].
9161 */
9162 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009163check_opt_wim(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009164{
9165 char_u new_wim_flags[4];
9166 char_u *p;
9167 int i;
9168 int idx = 0;
9169
9170 for (i = 0; i < 4; ++i)
9171 new_wim_flags[i] = 0;
9172
9173 for (p = p_wim; *p; ++p)
9174 {
9175 for (i = 0; ASCII_ISALPHA(p[i]); ++i)
9176 ;
9177 if (p[i] != NUL && p[i] != ',' && p[i] != ':')
9178 return FAIL;
9179 if (i == 7 && STRNCMP(p, "longest", 7) == 0)
9180 new_wim_flags[idx] |= WIM_LONGEST;
9181 else if (i == 4 && STRNCMP(p, "full", 4) == 0)
9182 new_wim_flags[idx] |= WIM_FULL;
9183 else if (i == 4 && STRNCMP(p, "list", 4) == 0)
9184 new_wim_flags[idx] |= WIM_LIST;
9185 else
9186 return FAIL;
9187 p += i;
9188 if (*p == NUL)
9189 break;
9190 if (*p == ',')
9191 {
9192 if (idx == 3)
9193 return FAIL;
9194 ++idx;
9195 }
9196 }
9197
9198 /* fill remaining entries with last flag */
9199 while (idx < 3)
9200 {
9201 new_wim_flags[idx + 1] = new_wim_flags[idx];
9202 ++idx;
9203 }
9204
9205 /* only when there are no errors, wim_flags[] is changed */
9206 for (i = 0; i < 4; ++i)
9207 wim_flags[i] = new_wim_flags[i];
9208 return OK;
9209}
9210
9211/*
9212 * Check if backspacing over something is allowed.
9213 */
9214 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009215can_bs(
9216 int what) /* BS_INDENT, BS_EOL or BS_START */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009217{
Bram Moolenaar6b810d92018-06-04 17:28:44 +02009218#ifdef FEAT_JOB_CHANNEL
9219 if (what == BS_START && bt_prompt(curbuf))
9220 return FALSE;
9221#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009222 switch (*p_bs)
9223 {
9224 case '2': return TRUE;
9225 case '1': return (what != BS_START);
9226 case '0': return FALSE;
9227 }
9228 return vim_strchr(p_bs, what) != NULL;
9229}
9230
9231/*
9232 * Save the current values of 'fileformat' and 'fileencoding', so that we know
9233 * the file must be considered changed when the value is different.
9234 */
9235 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01009236save_file_ff(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009237{
9238 buf->b_start_ffc = *buf->b_p_ff;
9239 buf->b_start_eol = buf->b_p_eol;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00009240 buf->b_start_bomb = buf->b_p_bomb;
9241
Bram Moolenaar071d4272004-06-13 20:20:40 +00009242 /* Only use free/alloc when necessary, they take time. */
9243 if (buf->b_start_fenc == NULL
9244 || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0)
9245 {
9246 vim_free(buf->b_start_fenc);
9247 buf->b_start_fenc = vim_strsave(buf->b_p_fenc);
9248 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009249}
9250
9251/*
9252 * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value
9253 * from when editing started (save_file_ff() called).
Bram Moolenaar83eb8852007-08-12 13:51:26 +00009254 * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
9255 * changed and 'binary' is not set.
Bram Moolenaar34d72d42015-07-17 14:18:08 +02009256 * Also when 'endofline' was changed and 'fixeol' is not set.
Bram Moolenaar164c60f2011-01-22 00:11:50 +01009257 * When "ignore_empty" is true don't consider a new, empty buffer to be
9258 * changed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009259 */
9260 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009261file_ff_differs(buf_T *buf, int ignore_empty)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009262{
Bram Moolenaar9cffde92007-07-24 07:51:18 +00009263 /* In a buffer that was never loaded the options are not valid. */
9264 if (buf->b_flags & BF_NEVERLOADED)
9265 return FALSE;
Bram Moolenaar164c60f2011-01-22 00:11:50 +01009266 if (ignore_empty
9267 && (buf->b_flags & BF_NEW)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009268 && buf->b_ml.ml_line_count == 1
9269 && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL)
9270 return FALSE;
9271 if (buf->b_start_ffc != *buf->b_p_ff)
9272 return TRUE;
Bram Moolenaar34d72d42015-07-17 14:18:08 +02009273 if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009274 return TRUE;
Bram Moolenaar83eb8852007-08-12 13:51:26 +00009275 if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb)
9276 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009277 if (buf->b_start_fenc == NULL)
9278 return (*buf->b_p_fenc != NUL);
9279 return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009280}
9281
9282/*
9283 * return OK if "p" is a valid fileformat name, FAIL otherwise.
9284 */
9285 int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009286check_ff_value(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009287{
9288 return check_opt_strings(p, p_ff_values, FALSE);
9289}
Bram Moolenaar14f24742012-08-08 18:01:05 +02009290
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01009291/*
Bram Moolenaar375e3392019-01-31 18:26:10 +01009292 * Return the effective 'scrolloff' value for the current window, using the
9293 * global value when appropriate.
9294 */
9295 long
9296get_scrolloff_value(void)
9297{
9298 return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
9299}
9300
9301/*
9302 * Return the effective 'sidescrolloff' value for the current window, using the
9303 * global value when appropriate.
9304 */
9305 long
9306get_sidescrolloff_value(void)
9307{
9308 return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
9309}
9310
9311/*
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01009312 * Check matchpairs option for "*initc".
9313 * If there is a match set "*initc" to the matching character and "*findc" to
9314 * the opposite character. Set "*backwards" to the direction.
9315 * When "switchit" is TRUE swap the direction.
9316 */
9317 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01009318find_mps_values(
9319 int *initc,
9320 int *findc,
9321 int *backwards,
9322 int switchit)
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01009323{
9324 char_u *ptr;
9325
9326 ptr = curbuf->b_p_mps;
9327 while (*ptr != NUL)
9328 {
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01009329 if (has_mbyte)
9330 {
9331 char_u *prev;
9332
9333 if (mb_ptr2char(ptr) == *initc)
9334 {
9335 if (switchit)
9336 {
9337 *findc = *initc;
9338 *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
9339 *backwards = TRUE;
9340 }
9341 else
9342 {
9343 *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1);
9344 *backwards = FALSE;
9345 }
9346 return;
9347 }
9348 prev = ptr;
9349 ptr += mb_ptr2len(ptr) + 1;
9350 if (mb_ptr2char(ptr) == *initc)
9351 {
9352 if (switchit)
9353 {
9354 *findc = *initc;
9355 *initc = mb_ptr2char(prev);
9356 *backwards = FALSE;
9357 }
9358 else
9359 {
9360 *findc = mb_ptr2char(prev);
9361 *backwards = TRUE;
9362 }
9363 return;
9364 }
9365 ptr += mb_ptr2len(ptr);
9366 }
9367 else
Bram Moolenaar8c7694a2013-01-17 17:02:05 +01009368 {
9369 if (*ptr == *initc)
9370 {
9371 if (switchit)
9372 {
9373 *backwards = TRUE;
9374 *findc = *initc;
9375 *initc = ptr[2];
9376 }
9377 else
9378 {
9379 *backwards = FALSE;
9380 *findc = ptr[2];
9381 }
9382 return;
9383 }
9384 ptr += 2;
9385 if (*ptr == *initc)
9386 {
9387 if (switchit)
9388 {
9389 *backwards = FALSE;
9390 *findc = *initc;
9391 *initc = ptr[-2];
9392 }
9393 else
9394 {
9395 *backwards = TRUE;
9396 *findc = ptr[-2];
9397 }
9398 return;
9399 }
9400 ++ptr;
9401 }
9402 if (*ptr == ',')
9403 ++ptr;
9404 }
9405}
Bram Moolenaar597a4222014-06-25 14:39:50 +02009406
9407#if defined(FEAT_LINEBREAK) || defined(PROTO)
9408/*
9409 * This is called when 'breakindentopt' is changed and when a window is
9410 * initialized.
9411 */
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02009412 static int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009413briopt_check(win_T *wp)
Bram Moolenaar597a4222014-06-25 14:39:50 +02009414{
9415 char_u *p;
9416 int bri_shift = 0;
9417 long bri_min = 20;
9418 int bri_sbr = FALSE;
9419
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02009420 p = wp->w_p_briopt;
Bram Moolenaar597a4222014-06-25 14:39:50 +02009421 while (*p != NUL)
9422 {
9423 if (STRNCMP(p, "shift:", 6) == 0
9424 && ((p[6] == '-' && VIM_ISDIGIT(p[7])) || VIM_ISDIGIT(p[6])))
9425 {
9426 p += 6;
9427 bri_shift = getdigits(&p);
9428 }
9429 else if (STRNCMP(p, "min:", 4) == 0 && VIM_ISDIGIT(p[4]))
9430 {
9431 p += 4;
9432 bri_min = getdigits(&p);
9433 }
9434 else if (STRNCMP(p, "sbr", 3) == 0)
9435 {
9436 p += 3;
9437 bri_sbr = TRUE;
9438 }
9439 if (*p != ',' && *p != NUL)
9440 return FAIL;
9441 if (*p == ',')
9442 ++p;
9443 }
9444
Bram Moolenaar285ed7e2014-08-24 21:39:49 +02009445 wp->w_p_brishift = bri_shift;
9446 wp->w_p_brimin = bri_min;
9447 wp->w_p_brisbr = bri_sbr;
Bram Moolenaar597a4222014-06-25 14:39:50 +02009448
9449 return OK;
9450}
9451#endif
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02009452
9453/*
9454 * Get the local or global value of 'backupcopy'.
9455 */
9456 unsigned int
Bram Moolenaar9b578142016-01-30 19:39:49 +01009457get_bkc_value(buf_T *buf)
Bram Moolenaarb8ee25a2014-09-23 15:45:08 +02009458{
9459 return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
9460}
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02009461
9462#if defined(FEAT_SIGNS) || defined(PROTO)
9463/*
9464 * Return TRUE when window "wp" has a column to draw signs in.
9465 */
9466 int
9467signcolumn_on(win_T *wp)
9468{
Bram Moolenaar394c5d82019-06-17 21:48:05 +02009469 // If 'signcolumn' is set to 'number', signs are displayed in the 'number'
9470 // column (if present). Otherwise signs are to be displayed in the sign
9471 // column.
9472 if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')
9473 return wp->w_buffer->b_signlist != NULL && !wp->w_p_nu && !wp->w_p_rnu;
9474
Bram Moolenaar95ec9d62016-08-12 18:29:59 +02009475 if (*wp->w_p_scl == 'n')
9476 return FALSE;
9477 if (*wp->w_p_scl == 'y')
9478 return TRUE;
9479 return (wp->w_buffer->b_signlist != NULL
9480# ifdef FEAT_NETBEANS_INTG
9481 || wp->w_buffer->b_has_sign_column
9482# endif
9483 );
9484}
9485#endif
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02009486
9487#if defined(FEAT_EVAL) || defined(PROTO)
9488/*
9489 * Get window or buffer local options.
9490 */
9491 dict_T *
9492get_winbuf_options(int bufopt)
9493{
9494 dict_T *d;
9495 int opt_idx;
9496
9497 d = dict_alloc();
9498 if (d == NULL)
9499 return NULL;
9500
9501 for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++)
9502 {
9503 struct vimoption *opt = &options[opt_idx];
9504
9505 if ((bufopt && (opt->indir & PV_BUF))
9506 || (!bufopt && (opt->indir & PV_WIN)))
9507 {
9508 char_u *varp = get_varp(opt);
9509
9510 if (varp != NULL)
9511 {
9512 if (opt->flags & P_STRING)
Bram Moolenaare0be1672018-07-08 16:50:37 +02009513 dict_add_string(d, opt->fullname, *(char_u **)varp);
Bram Moolenaar789a5c02016-09-12 19:51:11 +02009514 else if (opt->flags & P_NUM)
Bram Moolenaare0be1672018-07-08 16:50:37 +02009515 dict_add_number(d, opt->fullname, *(long *)varp);
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02009516 else
Bram Moolenaare0be1672018-07-08 16:50:37 +02009517 dict_add_number(d, opt->fullname, *(int *)varp);
Bram Moolenaarb5ae48e2016-08-12 22:23:25 +02009518 }
9519 }
9520 }
9521
9522 return d;
9523}
9524#endif
Bram Moolenaar017ba072019-09-14 21:01:23 +02009525
9526#ifdef FEAT_SYN_HL
9527/*
9528 * This is called when 'culopt' is changed
9529 */
9530 static int
9531fill_culopt_flags(char_u *val, win_T *wp)
9532{
9533 char_u *p;
9534 char_u culopt_flags_new = 0;
9535
9536 if (val == NULL)
9537 p = wp->w_p_culopt;
9538 else
9539 p = val;
9540 while (*p != NUL)
9541 {
9542 if (STRNCMP(p, "line", 4) == 0)
9543 {
9544 p += 4;
9545 culopt_flags_new |= CULOPT_LINE;
9546 }
9547 else if (STRNCMP(p, "both", 4) == 0)
9548 {
9549 p += 4;
9550 culopt_flags_new |= CULOPT_LINE | CULOPT_NBR;
9551 }
9552 else if (STRNCMP(p, "number", 6) == 0)
9553 {
9554 p += 6;
9555 culopt_flags_new |= CULOPT_NBR;
9556 }
9557 else if (STRNCMP(p, "screenline", 10) == 0)
9558 {
9559 p += 10;
9560 culopt_flags_new |= CULOPT_SCRLINE;
9561 }
9562
9563 if (*p != ',' && *p != NUL)
9564 return FAIL;
9565 if (*p == ',')
9566 ++p;
9567 }
9568
9569 // Can't have both "line" and "screenline".
9570 if ((culopt_flags_new & CULOPT_LINE) && (culopt_flags_new & CULOPT_SCRLINE))
9571 return FAIL;
9572 wp->w_p_culopt_flags = culopt_flags_new;
9573
9574 return OK;
9575}
9576#endif