1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * optionstr.c: Functions related to string options 12 */ 13 14 #include "vim.h" 15 16 static char *(p_ambw_values[]) = {"single", "double", NULL}; 17 static char *(p_bg_values[]) = {"light", "dark", NULL}; 18 static char *(p_bkc_values[]) = {"yes", "auto", "no", "breaksymlink", "breakhardlink", NULL}; 19 static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete", 20 "copy", "ctrlg", "error", "esc", "ex", 21 "hangul", "insertmode", "lang", "mess", 22 "showmatch", "operator", "register", "shell", 23 "spell", "wildmode", NULL}; 24 static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", NULL}; 25 static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; 26 #ifdef FEAT_CRYPT 27 static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL}; 28 #endif 29 static char *(p_cmp_values[]) = {"internal", "keepascii", NULL}; 30 static char *(p_dy_values[]) = {"lastline", "truncate", "uhex", NULL}; 31 #ifdef FEAT_FOLDING 32 static char *(p_fdo_values[]) = {"all", "block", "hor", "mark", "percent", 33 "quickfix", "search", "tag", "insert", 34 "undo", "jump", NULL}; 35 #endif 36 #ifdef FEAT_SESSION 37 // Also used for 'viewoptions'! 38 static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize", 39 "localoptions", "options", "help", "blank", "globals", "slash", "unix", 40 "sesdir", "curdir", "folds", "cursor", "tabpages", "terminal", NULL}; 41 #endif 42 // Keep in sync with SWB_ flags in option.h 43 static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL}; 44 static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL}; 45 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) 46 static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL}; 47 #endif 48 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) 49 static char *(p_tbis_values[]) = {"tiny", "small", "medium", "large", "huge", "giant", NULL}; 50 #endif 51 #if defined(UNIX) || defined(VMS) 52 static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", "urxvt", "sgr", NULL}; 53 #endif 54 static char *(p_ve_values[]) = {"block", "insert", "all", "onemore", NULL}; 55 static char *(p_wop_values[]) = {"tagfile", NULL}; 56 #ifdef FEAT_WAK 57 static char *(p_wak_values[]) = {"yes", "menu", "no", NULL}; 58 #endif 59 static char *(p_mousem_values[]) = {"extend", "popup", "popup_setpos", "mac", NULL}; 60 static char *(p_sel_values[]) = {"inclusive", "exclusive", "old", NULL}; 61 static char *(p_slm_values[]) = {"mouse", "key", "cmd", NULL}; 62 static char *(p_km_values[]) = {"startsel", "stopsel", NULL}; 63 #ifdef FEAT_BROWSE 64 static char *(p_bsdir_values[]) = {"current", "last", "buffer", NULL}; 65 #endif 66 static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL}; 67 static char *(p_debug_values[]) = {"msg", "throw", "beep", NULL}; 68 static char *(p_ead_values[]) = {"both", "ver", "hor", NULL}; 69 static char *(p_buftype_values[]) = {"nofile", "nowrite", "quickfix", "help", "terminal", "acwrite", "prompt", "popup", NULL}; 70 static char *(p_bufhidden_values[]) = {"hide", "unload", "delete", "wipe", NULL}; 71 static char *(p_bs_values[]) = {"indent", "eol", "start", "nostop", NULL}; 72 #ifdef FEAT_FOLDING 73 static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax", 74 # ifdef FEAT_DIFF 75 "diff", 76 # endif 77 NULL}; 78 static char *(p_fcl_values[]) = {"all", NULL}; 79 #endif 80 static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "popuphidden", "noinsert", "noselect", NULL}; 81 #ifdef BACKSLASH_IN_FILENAME 82 static char *(p_csl_values[]) = {"slash", "backslash", NULL}; 83 #endif 84 #ifdef FEAT_SIGNS 85 static char *(p_scl_values[]) = {"yes", "no", "auto", "number", NULL}; 86 #endif 87 #if defined(MSWIN) && defined(FEAT_TERMINAL) 88 static char *(p_twt_values[]) = {"winpty", "conpty", "", NULL}; 89 #endif 90 91 static int check_opt_strings(char_u *val, char **values, int list); 92 static int opt_strings_flags(char_u *val, char **values, unsigned *flagp, int list); 93 94 /* 95 * After setting various option values: recompute variables that depend on 96 * option values. 97 */ 98 void 99 didset_string_options(void) 100 { 101 (void)opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE); 102 (void)opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, TRUE); 103 (void)opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE); 104 #ifdef FEAT_SESSION 105 (void)opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE); 106 (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE); 107 #endif 108 #ifdef FEAT_FOLDING 109 (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE); 110 #endif 111 (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE); 112 (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, FALSE); 113 (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE); 114 #if defined(UNIX) || defined(VMS) 115 (void)opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE); 116 #endif 117 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) 118 (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE); 119 #endif 120 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) 121 (void)opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE); 122 #endif 123 } 124 125 #if defined(FEAT_EVAL) 126 /* 127 * Trigger the OptionSet autocommand. 128 * "opt_idx" is the index of the option being set. 129 * "opt_flags" can be OPT_LOCAL etc. 130 * "oldval" the old value 131 * "oldval_l" the old local value (only non-NULL if global and local value 132 * are set) 133 * "oldval_g" the old global value (only non-NULL if global and local value 134 * are set) 135 * "newval" the new value 136 */ 137 void 138 trigger_optionsset_string( 139 int opt_idx, 140 int opt_flags, 141 char_u *oldval, 142 char_u *oldval_l, 143 char_u *oldval_g, 144 char_u *newval) 145 { 146 // Don't do this recursively. 147 if (oldval != NULL && newval != NULL 148 && *get_vim_var_str(VV_OPTION_TYPE) == NUL) 149 { 150 char_u buf_type[7]; 151 152 sprintf((char *)buf_type, "%s", 153 (opt_flags & OPT_LOCAL) ? "local" : "global"); 154 set_vim_var_string(VV_OPTION_OLD, oldval, -1); 155 set_vim_var_string(VV_OPTION_NEW, newval, -1); 156 set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); 157 if (opt_flags & OPT_LOCAL) 158 { 159 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1); 160 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1); 161 } 162 if (opt_flags & OPT_GLOBAL) 163 { 164 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1); 165 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1); 166 } 167 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) 168 { 169 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1); 170 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1); 171 set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1); 172 } 173 if (opt_flags & OPT_MODELINE) 174 { 175 set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1); 176 set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1); 177 } 178 apply_autocmds(EVENT_OPTIONSET, 179 (char_u *)get_option_fullname(opt_idx), NULL, FALSE, 180 NULL); 181 reset_v_option_vars(); 182 } 183 } 184 #endif 185 186 static char * 187 illegal_char(char *errbuf, int c) 188 { 189 if (errbuf == NULL) 190 return ""; 191 sprintf((char *)errbuf, _("E539: Illegal character <%s>"), 192 (char *)transchar(c)); 193 return errbuf; 194 } 195 196 /* 197 * Check string options in a buffer for NULL value. 198 */ 199 void 200 check_buf_options(buf_T *buf) 201 { 202 check_string_option(&buf->b_p_bh); 203 check_string_option(&buf->b_p_bt); 204 check_string_option(&buf->b_p_fenc); 205 check_string_option(&buf->b_p_ff); 206 #ifdef FEAT_FIND_ID 207 check_string_option(&buf->b_p_def); 208 check_string_option(&buf->b_p_inc); 209 # ifdef FEAT_EVAL 210 check_string_option(&buf->b_p_inex); 211 # endif 212 #endif 213 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL) 214 check_string_option(&buf->b_p_inde); 215 check_string_option(&buf->b_p_indk); 216 #endif 217 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) 218 check_string_option(&buf->b_p_bexpr); 219 #endif 220 #if defined(FEAT_CRYPT) 221 check_string_option(&buf->b_p_cm); 222 #endif 223 check_string_option(&buf->b_p_fp); 224 #if defined(FEAT_EVAL) 225 check_string_option(&buf->b_p_fex); 226 #endif 227 #ifdef FEAT_CRYPT 228 check_string_option(&buf->b_p_key); 229 #endif 230 check_string_option(&buf->b_p_kp); 231 check_string_option(&buf->b_p_mps); 232 check_string_option(&buf->b_p_fo); 233 check_string_option(&buf->b_p_flp); 234 check_string_option(&buf->b_p_isk); 235 check_string_option(&buf->b_p_com); 236 #ifdef FEAT_FOLDING 237 check_string_option(&buf->b_p_cms); 238 #endif 239 check_string_option(&buf->b_p_nf); 240 #ifdef FEAT_TEXTOBJ 241 check_string_option(&buf->b_p_qe); 242 #endif 243 #ifdef FEAT_SYN_HL 244 check_string_option(&buf->b_p_syn); 245 check_string_option(&buf->b_s.b_syn_isk); 246 #endif 247 #ifdef FEAT_SPELL 248 check_string_option(&buf->b_s.b_p_spc); 249 check_string_option(&buf->b_s.b_p_spf); 250 check_string_option(&buf->b_s.b_p_spl); 251 check_string_option(&buf->b_s.b_p_spo); 252 #endif 253 #ifdef FEAT_SEARCHPATH 254 check_string_option(&buf->b_p_sua); 255 #endif 256 #ifdef FEAT_CINDENT 257 check_string_option(&buf->b_p_cink); 258 check_string_option(&buf->b_p_cino); 259 parse_cino(buf); 260 #endif 261 check_string_option(&buf->b_p_ft); 262 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) 263 check_string_option(&buf->b_p_cinw); 264 #endif 265 check_string_option(&buf->b_p_cpt); 266 #ifdef FEAT_COMPL_FUNC 267 check_string_option(&buf->b_p_cfu); 268 check_string_option(&buf->b_p_ofu); 269 #endif 270 #ifdef FEAT_EVAL 271 check_string_option(&buf->b_p_tfu); 272 #endif 273 #ifdef FEAT_KEYMAP 274 check_string_option(&buf->b_p_keymap); 275 #endif 276 #ifdef FEAT_QUICKFIX 277 check_string_option(&buf->b_p_gp); 278 check_string_option(&buf->b_p_mp); 279 check_string_option(&buf->b_p_efm); 280 #endif 281 check_string_option(&buf->b_p_ep); 282 check_string_option(&buf->b_p_path); 283 check_string_option(&buf->b_p_tags); 284 check_string_option(&buf->b_p_tc); 285 check_string_option(&buf->b_p_dict); 286 check_string_option(&buf->b_p_tsr); 287 #ifdef FEAT_LISP 288 check_string_option(&buf->b_p_lw); 289 #endif 290 check_string_option(&buf->b_p_bkc); 291 check_string_option(&buf->b_p_menc); 292 #ifdef FEAT_VARTABS 293 check_string_option(&buf->b_p_vsts); 294 check_string_option(&buf->b_p_vts); 295 #endif 296 } 297 298 /* 299 * Free the string allocated for an option. 300 * Checks for the string being empty_option. This may happen if we're out of 301 * memory, vim_strsave() returned NULL, which was replaced by empty_option by 302 * check_options(). 303 * Does NOT check for P_ALLOCED flag! 304 */ 305 void 306 free_string_option(char_u *p) 307 { 308 if (p != empty_option) 309 vim_free(p); 310 } 311 312 void 313 clear_string_option(char_u **pp) 314 { 315 if (*pp != empty_option) 316 vim_free(*pp); 317 *pp = empty_option; 318 } 319 320 void 321 check_string_option(char_u **pp) 322 { 323 if (*pp == NULL) 324 *pp = empty_option; 325 } 326 327 /* 328 * Set global value for string option when it's a local option. 329 */ 330 static void 331 set_string_option_global( 332 int opt_idx, // option index 333 char_u **varp) // pointer to option variable 334 { 335 char_u **p, *s; 336 337 // the global value is always allocated 338 if (is_window_local_option(opt_idx)) 339 p = (char_u **)GLOBAL_WO(varp); 340 else 341 p = (char_u **)get_option_var(opt_idx); 342 if (!is_global_option(opt_idx) 343 && p != varp 344 && (s = vim_strsave(*varp)) != NULL) 345 { 346 free_string_option(*p); 347 *p = s; 348 } 349 } 350 351 /* 352 * Set a string option to a new value (without checking the effect). 353 * The string is copied into allocated memory. 354 * if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used. 355 * When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When 356 * "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to 357 * "set_sid". 358 */ 359 void 360 set_string_option_direct( 361 char_u *name, 362 int opt_idx, 363 char_u *val, 364 int opt_flags, // OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL 365 int set_sid UNUSED) 366 { 367 char_u *s; 368 char_u **varp; 369 int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; 370 int idx = opt_idx; 371 372 if (idx == -1) // use name 373 { 374 idx = findoption(name); 375 if (idx < 0) // not found (should not happen) 376 { 377 semsg(_(e_intern2), "set_string_option_direct()"); 378 siemsg(_("For option %s"), name); 379 return; 380 } 381 } 382 383 if (is_hidden_option(idx)) // can't set hidden option 384 return; 385 386 s = vim_strsave(val); 387 if (s != NULL) 388 { 389 varp = (char_u **)get_option_varp_scope(idx, 390 both ? OPT_LOCAL : opt_flags); 391 if ((opt_flags & OPT_FREE) && (get_option_flags(idx) & P_ALLOCED)) 392 free_string_option(*varp); 393 *varp = s; 394 395 // For buffer/window local option may also set the global value. 396 if (both) 397 set_string_option_global(idx, varp); 398 399 set_option_flag(idx, P_ALLOCED); 400 401 // When setting both values of a global option with a local value, 402 // make the local value empty, so that the global value is used. 403 if (is_global_local_option(idx) && both) 404 { 405 free_string_option(*varp); 406 *varp = empty_option; 407 } 408 # ifdef FEAT_EVAL 409 if (set_sid != SID_NONE) 410 { 411 sctx_T script_ctx; 412 413 if (set_sid == 0) 414 script_ctx = current_sctx; 415 else 416 { 417 script_ctx.sc_sid = set_sid; 418 script_ctx.sc_seq = 0; 419 script_ctx.sc_lnum = 0; 420 script_ctx.sc_version = 1; 421 } 422 set_option_sctx_idx(idx, opt_flags, script_ctx); 423 } 424 # endif 425 } 426 } 427 428 /* 429 * Like set_string_option_direct(), but for a window-local option in "wp". 430 * Blocks autocommands to avoid the old curwin becoming invalid. 431 */ 432 void 433 set_string_option_direct_in_win( 434 win_T *wp, 435 char_u *name, 436 int opt_idx, 437 char_u *val, 438 int opt_flags, 439 int set_sid) 440 { 441 win_T *save_curwin = curwin; 442 443 block_autocmds(); 444 curwin = wp; 445 curbuf = curwin->w_buffer; 446 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid); 447 curwin = save_curwin; 448 curbuf = curwin->w_buffer; 449 unblock_autocmds(); 450 } 451 452 /* 453 * Like set_string_option_direct(), but for a buffer-local option in "buf". 454 * Blocks autocommands to avoid the old curbuf becoming invalid. 455 */ 456 void 457 set_string_option_direct_in_buf( 458 buf_T *buf, 459 char_u *name, 460 int opt_idx, 461 char_u *val, 462 int opt_flags, 463 int set_sid) 464 { 465 buf_T *save_curbuf = curbuf; 466 467 block_autocmds(); 468 curbuf = buf; 469 curwin->w_buffer = curbuf; 470 set_string_option_direct(name, opt_idx, val, opt_flags, set_sid); 471 curbuf = save_curbuf; 472 curwin->w_buffer = curbuf; 473 unblock_autocmds(); 474 } 475 476 /* 477 * Set a string option to a new value, and handle the effects. 478 * 479 * Returns NULL on success or error message on error. 480 */ 481 char * 482 set_string_option( 483 int opt_idx, 484 char_u *value, 485 int opt_flags) // OPT_LOCAL and/or OPT_GLOBAL 486 { 487 char_u *s; 488 char_u **varp; 489 char_u *oldval; 490 #if defined(FEAT_EVAL) 491 char_u *oldval_l = NULL; 492 char_u *oldval_g = NULL; 493 char_u *saved_oldval = NULL; 494 char_u *saved_oldval_l = NULL; 495 char_u *saved_oldval_g = NULL; 496 char_u *saved_newval = NULL; 497 #endif 498 char *r = NULL; 499 int value_checked = FALSE; 500 501 if (is_hidden_option(opt_idx)) // don't set hidden option 502 return NULL; 503 504 s = vim_strsave(value == NULL ? (char_u *)"" : value); 505 if (s != NULL) 506 { 507 varp = (char_u **)get_option_varp_scope(opt_idx, 508 (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 509 ? (is_global_local_option(opt_idx) 510 ? OPT_GLOBAL : OPT_LOCAL) 511 : opt_flags); 512 oldval = *varp; 513 #if defined(FEAT_EVAL) 514 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) 515 { 516 oldval_l = *(char_u **)get_option_varp_scope(opt_idx, OPT_LOCAL); 517 oldval_g = *(char_u **)get_option_varp_scope(opt_idx, OPT_GLOBAL); 518 } 519 #endif 520 *varp = s; 521 522 #if defined(FEAT_EVAL) 523 if (!starting 524 # ifdef FEAT_CRYPT 525 && !is_crypt_key_option(opt_idx) 526 # endif 527 ) 528 { 529 if (oldval_l != NULL) 530 saved_oldval_l = vim_strsave(oldval_l); 531 if (oldval_g != NULL) 532 saved_oldval_g = vim_strsave(oldval_g); 533 saved_oldval = vim_strsave(oldval); 534 saved_newval = vim_strsave(s); 535 } 536 #endif 537 if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL, 538 opt_flags, &value_checked)) == NULL) 539 did_set_option(opt_idx, opt_flags, TRUE, value_checked); 540 541 #if defined(FEAT_EVAL) 542 // call autocommand after handling side effects 543 if (r == NULL) 544 trigger_optionsset_string(opt_idx, opt_flags, 545 saved_oldval, saved_oldval_l, 546 saved_oldval_g, saved_newval); 547 vim_free(saved_oldval); 548 vim_free(saved_oldval_l); 549 vim_free(saved_oldval_g); 550 vim_free(saved_newval); 551 #endif 552 } 553 return r; 554 } 555 556 /* 557 * Return TRUE if "val" is a valid 'filetype' name. 558 * Also used for 'syntax' and 'keymap'. 559 */ 560 static int 561 valid_filetype(char_u *val) 562 { 563 return valid_name(val, ".-_"); 564 } 565 566 #ifdef FEAT_STL_OPT 567 /* 568 * Check validity of options with the 'statusline' format. 569 * Return error message or NULL. 570 */ 571 static char * 572 check_stl_option(char_u *s) 573 { 574 int itemcnt = 0; 575 int groupdepth = 0; 576 static char errbuf[80]; 577 578 while (*s && itemcnt < STL_MAX_ITEM) 579 { 580 // Check for valid keys after % sequences 581 while (*s && *s != '%') 582 s++; 583 if (!*s) 584 break; 585 s++; 586 if (*s != '%' && *s != ')') 587 ++itemcnt; 588 if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_MIDDLEMARK) 589 { 590 s++; 591 continue; 592 } 593 if (*s == ')') 594 { 595 s++; 596 if (--groupdepth < 0) 597 break; 598 continue; 599 } 600 if (*s == '-') 601 s++; 602 while (VIM_ISDIGIT(*s)) 603 s++; 604 if (*s == STL_USER_HL) 605 continue; 606 if (*s == '.') 607 { 608 s++; 609 while (*s && VIM_ISDIGIT(*s)) 610 s++; 611 } 612 if (*s == '(') 613 { 614 groupdepth++; 615 continue; 616 } 617 if (vim_strchr(STL_ALL, *s) == NULL) 618 { 619 return illegal_char(errbuf, *s); 620 } 621 if (*s == '{') 622 { 623 s++; 624 while (*s != '}' && *s) 625 s++; 626 if (*s != '}') 627 return N_("E540: Unclosed expression sequence"); 628 } 629 } 630 if (itemcnt >= STL_MAX_ITEM) 631 return N_("E541: too many items"); 632 if (groupdepth != 0) 633 return N_("E542: unbalanced groups"); 634 return NULL; 635 } 636 #endif 637 638 /* 639 * Handle string options that need some action to perform when changed. 640 * Returns NULL for success, or an error message for an error. 641 */ 642 char * 643 did_set_string_option( 644 int opt_idx, // index in options[] table 645 char_u **varp, // pointer to the option variable 646 int new_value_alloced, // new value was allocated 647 char_u *oldval, // previous value of the option 648 char *errbuf, // buffer for errors, or NULL 649 int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL 650 int *value_checked) // value was checked to be save, no 651 // need to set P_INSECURE 652 { 653 char *errmsg = NULL; 654 char_u *s, *p; 655 int did_chartab = FALSE; 656 char_u **gvarp; 657 long_u free_oldval = (get_option_flags(opt_idx) & P_ALLOCED); 658 #ifdef FEAT_GUI 659 // set when changing an option that only requires a redraw in the GUI 660 int redraw_gui_only = FALSE; 661 #endif 662 int value_changed = FALSE; 663 #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) 664 int did_swaptcap = FALSE; 665 #endif 666 667 // Get the global option to compare with, otherwise we would have to check 668 // two values for all local options. 669 gvarp = (char_u **)get_option_varp_scope(opt_idx, OPT_GLOBAL); 670 671 // Disallow changing some options from secure mode 672 if ((secure 673 #ifdef HAVE_SANDBOX 674 || sandbox != 0 675 #endif 676 ) && (get_option_flags(opt_idx) & P_SECURE)) 677 errmsg = e_secure; 678 679 // Check for a "normal" directory or file name in some options. Disallow a 680 // path separator (slash and/or backslash), wildcards and characters that 681 // are often illegal in a file name. Be more permissive if "secure" is off. 682 else if (((get_option_flags(opt_idx) & P_NFNAME) 683 && vim_strpbrk(*varp, (char_u *)(secure 684 ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL) 685 || ((get_option_flags(opt_idx) & P_NDNAME) 686 && vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL)) 687 errmsg = e_invarg; 688 689 // 'term' 690 else if (varp == &T_NAME) 691 { 692 if (T_NAME[0] == NUL) 693 errmsg = N_("E529: Cannot set 'term' to empty string"); 694 #ifdef FEAT_GUI 695 if (gui.in_use) 696 errmsg = N_("E530: Cannot change term in GUI"); 697 else if (term_is_gui(T_NAME)) 698 errmsg = N_("E531: Use \":gui\" to start the GUI"); 699 #endif 700 else if (set_termname(T_NAME) == FAIL) 701 errmsg = N_("E522: Not found in termcap"); 702 else 703 { 704 // Screen colors may have changed. 705 redraw_later_clear(); 706 707 // Both 'term' and 'ttytype' point to T_NAME, only set the 708 // P_ALLOCED flag on 'term'. 709 opt_idx = findoption((char_u *)"term"); 710 free_oldval = (get_option_flags(opt_idx) & P_ALLOCED); 711 } 712 } 713 714 // 'backupcopy' 715 else if (gvarp == &p_bkc) 716 { 717 char_u *bkc = p_bkc; 718 unsigned int *flags = &bkc_flags; 719 720 if (opt_flags & OPT_LOCAL) 721 { 722 bkc = curbuf->b_p_bkc; 723 flags = &curbuf->b_bkc_flags; 724 } 725 726 if ((opt_flags & OPT_LOCAL) && *bkc == NUL) 727 // make the local value empty: use the global value 728 *flags = 0; 729 else 730 { 731 if (opt_strings_flags(bkc, p_bkc_values, flags, TRUE) != OK) 732 errmsg = e_invarg; 733 if ((((int)*flags & BKC_AUTO) != 0) 734 + (((int)*flags & BKC_YES) != 0) 735 + (((int)*flags & BKC_NO) != 0) != 1) 736 { 737 // Must have exactly one of "auto", "yes" and "no". 738 (void)opt_strings_flags(oldval, p_bkc_values, flags, TRUE); 739 errmsg = e_invarg; 740 } 741 } 742 } 743 744 // 'backupext' and 'patchmode' 745 else if (varp == &p_bex || varp == &p_pm) 746 { 747 if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex, 748 *p_pm == '.' ? p_pm + 1 : p_pm) == 0) 749 errmsg = N_("E589: 'backupext' and 'patchmode' are equal"); 750 } 751 #ifdef FEAT_LINEBREAK 752 // 'breakindentopt' 753 else if (varp == &curwin->w_p_briopt) 754 { 755 if (briopt_check(curwin) == FAIL) 756 errmsg = e_invarg; 757 } 758 #endif 759 760 // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] 761 // If the new option is invalid, use old value. 'lisp' option: refill 762 // g_chartab[] for '-' char 763 else if ( varp == &p_isi 764 || varp == &(curbuf->b_p_isk) 765 || varp == &p_isp 766 || varp == &p_isf) 767 { 768 if (init_chartab() == FAIL) 769 { 770 did_chartab = TRUE; // need to restore it below 771 errmsg = e_invarg; // error in value 772 } 773 } 774 775 // 'helpfile' 776 else if (varp == &p_hf) 777 { 778 // May compute new values for $VIM and $VIMRUNTIME 779 if (didset_vim) 780 { 781 vim_setenv((char_u *)"VIM", (char_u *)""); 782 didset_vim = FALSE; 783 } 784 if (didset_vimruntime) 785 { 786 vim_setenv((char_u *)"VIMRUNTIME", (char_u *)""); 787 didset_vimruntime = FALSE; 788 } 789 } 790 791 #ifdef FEAT_SYN_HL 792 // 'cursorlineopt' 793 else if (varp == &curwin->w_p_culopt 794 || gvarp == &curwin->w_allbuf_opt.wo_culopt) 795 { 796 if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) 797 errmsg = e_invarg; 798 } 799 800 // 'colorcolumn' 801 else if (varp == &curwin->w_p_cc) 802 errmsg = check_colorcolumn(curwin); 803 #endif 804 805 #ifdef FEAT_MULTI_LANG 806 // 'helplang' 807 else if (varp == &p_hlg) 808 { 809 // Check for "", "ab", "ab,cd", etc. 810 for (s = p_hlg; *s != NUL; s += 3) 811 { 812 if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) 813 { 814 errmsg = e_invarg; 815 break; 816 } 817 if (s[2] == NUL) 818 break; 819 } 820 } 821 #endif 822 823 // 'highlight' 824 else if (varp == &p_hl) 825 { 826 if (highlight_changed() == FAIL) 827 errmsg = e_invarg; // invalid flags 828 } 829 830 // 'nrformats' 831 else if (gvarp == &p_nf) 832 { 833 if (check_opt_strings(*varp, p_nf_values, TRUE) != OK) 834 errmsg = e_invarg; 835 } 836 837 #ifdef FEAT_SESSION 838 // 'sessionoptions' 839 else if (varp == &p_ssop) 840 { 841 if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, TRUE) != OK) 842 errmsg = e_invarg; 843 if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) 844 { 845 // Don't allow both "sesdir" and "curdir". 846 (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, TRUE); 847 errmsg = e_invarg; 848 } 849 } 850 // 'viewoptions' 851 else if (varp == &p_vop) 852 { 853 if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, TRUE) != OK) 854 errmsg = e_invarg; 855 } 856 #endif 857 858 // 'scrollopt' 859 else if (varp == &p_sbo) 860 { 861 if (check_opt_strings(p_sbo, p_scbopt_values, TRUE) != OK) 862 errmsg = e_invarg; 863 } 864 865 // 'ambiwidth' 866 else if (varp == &p_ambw || varp == &p_emoji) 867 { 868 if (check_opt_strings(p_ambw, p_ambw_values, FALSE) != OK) 869 errmsg = e_invarg; 870 else if (set_chars_option(&p_lcs) != NULL) 871 errmsg = _("E834: Conflicts with value of 'listchars'"); 872 else if (set_chars_option(&p_fcs) != NULL) 873 errmsg = _("E835: Conflicts with value of 'fillchars'"); 874 } 875 876 // 'background' 877 else if (varp == &p_bg) 878 { 879 if (check_opt_strings(p_bg, p_bg_values, FALSE) == OK) 880 { 881 #ifdef FEAT_EVAL 882 int dark = (*p_bg == 'd'); 883 #endif 884 885 init_highlight(FALSE, FALSE); 886 887 #ifdef FEAT_EVAL 888 if (dark != (*p_bg == 'd') 889 && get_var_value((char_u *)"g:colors_name") != NULL) 890 { 891 // The color scheme must have set 'background' back to another 892 // value, that's not what we want here. Disable the color 893 // scheme and set the colors again. 894 do_unlet((char_u *)"g:colors_name", TRUE); 895 free_string_option(p_bg); 896 p_bg = vim_strsave((char_u *)(dark ? "dark" : "light")); 897 check_string_option(&p_bg); 898 init_highlight(FALSE, FALSE); 899 } 900 #endif 901 } 902 else 903 errmsg = e_invarg; 904 } 905 906 // 'wildmode' 907 else if (varp == &p_wim) 908 { 909 if (check_opt_wim() == FAIL) 910 errmsg = e_invarg; 911 } 912 913 // 'wildoptions' 914 else if (varp == &p_wop) 915 { 916 if (check_opt_strings(p_wop, p_wop_values, TRUE) != OK) 917 errmsg = e_invarg; 918 } 919 920 #ifdef FEAT_WAK 921 // 'winaltkeys' 922 else if (varp == &p_wak) 923 { 924 if (*p_wak == NUL 925 || check_opt_strings(p_wak, p_wak_values, FALSE) != OK) 926 errmsg = e_invarg; 927 # ifdef FEAT_MENU 928 # ifdef FEAT_GUI_MOTIF 929 else if (gui.in_use) 930 gui_motif_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm'); 931 # else 932 # ifdef FEAT_GUI_GTK 933 else if (gui.in_use) 934 gui_gtk_set_mnemonics(p_wak[0] == 'y' || p_wak[0] == 'm'); 935 # endif 936 # endif 937 # endif 938 } 939 #endif 940 941 // 'eventignore' 942 else if (varp == &p_ei) 943 { 944 if (check_ei() == FAIL) 945 errmsg = e_invarg; 946 } 947 948 // 'encoding', 'fileencoding', 'termencoding' and 'makeencoding' 949 else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc 950 || gvarp == &p_menc) 951 { 952 if (gvarp == &p_fenc) 953 { 954 if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL) 955 errmsg = e_modifiable; 956 else if (vim_strchr(*varp, ',') != NULL) 957 // No comma allowed in 'fileencoding'; catches confusing it 958 // with 'fileencodings'. 959 errmsg = e_invarg; 960 else 961 { 962 #ifdef FEAT_TITLE 963 // May show a "+" in the title now. 964 redraw_titles(); 965 #endif 966 // Add 'fileencoding' to the swap file. 967 ml_setflags(curbuf); 968 } 969 } 970 if (errmsg == NULL) 971 { 972 // canonize the value, so that STRCMP() can be used on it 973 p = enc_canonize(*varp); 974 if (p != NULL) 975 { 976 vim_free(*varp); 977 *varp = p; 978 } 979 if (varp == &p_enc) 980 { 981 errmsg = mb_init(); 982 #ifdef FEAT_TITLE 983 redraw_titles(); 984 #endif 985 } 986 } 987 988 #if defined(FEAT_GUI_GTK) 989 if (errmsg == NULL && varp == &p_tenc && gui.in_use) 990 { 991 // GTK+ 2 uses only a single encoding, and that is UTF-8. 992 if (STRCMP(p_tenc, "utf-8") != 0) 993 errmsg = N_("E617: Cannot be changed in the GTK+ 2 GUI"); 994 } 995 #endif 996 997 if (errmsg == NULL) 998 { 999 #ifdef FEAT_KEYMAP 1000 // When 'keymap' is used and 'encoding' changes, reload the keymap 1001 // (with another encoding). 1002 if (varp == &p_enc && *curbuf->b_p_keymap != NUL) 1003 (void)keymap_init(); 1004 #endif 1005 1006 // When 'termencoding' is not empty and 'encoding' changes or when 1007 // 'termencoding' changes, need to setup for keyboard input and 1008 // display output conversion. 1009 if (((varp == &p_enc && *p_tenc != NUL) || varp == &p_tenc)) 1010 { 1011 if (convert_setup(&input_conv, p_tenc, p_enc) == FAIL 1012 || convert_setup(&output_conv, p_enc, p_tenc) == FAIL) 1013 { 1014 semsg(_("E950: Cannot convert between %s and %s"), 1015 p_tenc, p_enc); 1016 errmsg = e_invarg; 1017 } 1018 } 1019 1020 #if defined(MSWIN) 1021 // $HOME may have characters in active code page. 1022 if (varp == &p_enc) 1023 init_homedir(); 1024 #endif 1025 } 1026 } 1027 1028 #if defined(FEAT_POSTSCRIPT) 1029 else if (varp == &p_penc) 1030 { 1031 // Canonize printencoding if VIM standard one 1032 p = enc_canonize(p_penc); 1033 if (p != NULL) 1034 { 1035 vim_free(p_penc); 1036 p_penc = p; 1037 } 1038 else 1039 { 1040 // Ensure lower case and '-' for '_' 1041 for (s = p_penc; *s != NUL; s++) 1042 { 1043 if (*s == '_') 1044 *s = '-'; 1045 else 1046 *s = TOLOWER_ASC(*s); 1047 } 1048 } 1049 } 1050 #endif 1051 1052 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 1053 else if (varp == &p_imak) 1054 { 1055 if (!im_xim_isvalid_imactivate()) 1056 errmsg = e_invarg; 1057 } 1058 #endif 1059 1060 #ifdef FEAT_KEYMAP 1061 else if (varp == &curbuf->b_p_keymap) 1062 { 1063 if (!valid_filetype(*varp)) 1064 errmsg = e_invarg; 1065 else 1066 { 1067 int secure_save = secure; 1068 1069 // Reset the secure flag, since the value of 'keymap' has 1070 // been checked to be safe. 1071 secure = 0; 1072 1073 // load or unload key mapping tables 1074 errmsg = keymap_init(); 1075 1076 secure = secure_save; 1077 1078 // Since we check the value, there is no need to set P_INSECURE, 1079 // even when the value comes from a modeline. 1080 *value_checked = TRUE; 1081 } 1082 1083 if (errmsg == NULL) 1084 { 1085 if (*curbuf->b_p_keymap != NUL) 1086 { 1087 // Installed a new keymap, switch on using it. 1088 curbuf->b_p_iminsert = B_IMODE_LMAP; 1089 if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT) 1090 curbuf->b_p_imsearch = B_IMODE_LMAP; 1091 } 1092 else 1093 { 1094 // Cleared the keymap, may reset 'iminsert' and 'imsearch'. 1095 if (curbuf->b_p_iminsert == B_IMODE_LMAP) 1096 curbuf->b_p_iminsert = B_IMODE_NONE; 1097 if (curbuf->b_p_imsearch == B_IMODE_LMAP) 1098 curbuf->b_p_imsearch = B_IMODE_USE_INSERT; 1099 } 1100 if ((opt_flags & OPT_LOCAL) == 0) 1101 { 1102 set_iminsert_global(); 1103 set_imsearch_global(); 1104 } 1105 status_redraw_curbuf(); 1106 } 1107 } 1108 #endif 1109 1110 // 'fileformat' 1111 else if (gvarp == &p_ff) 1112 { 1113 if (!curbuf->b_p_ma && !(opt_flags & OPT_GLOBAL)) 1114 errmsg = e_modifiable; 1115 else if (check_opt_strings(*varp, p_ff_values, FALSE) != OK) 1116 errmsg = e_invarg; 1117 else 1118 { 1119 // may also change 'textmode' 1120 if (get_fileformat(curbuf) == EOL_DOS) 1121 curbuf->b_p_tx = TRUE; 1122 else 1123 curbuf->b_p_tx = FALSE; 1124 #ifdef FEAT_TITLE 1125 redraw_titles(); 1126 #endif 1127 // update flag in swap file 1128 ml_setflags(curbuf); 1129 // Redraw needed when switching to/from "mac": a CR in the text 1130 // will be displayed differently. 1131 if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm') 1132 redraw_curbuf_later(NOT_VALID); 1133 } 1134 } 1135 1136 // 'fileformats' 1137 else if (varp == &p_ffs) 1138 { 1139 if (check_opt_strings(p_ffs, p_ff_values, TRUE) != OK) 1140 errmsg = e_invarg; 1141 else 1142 { 1143 // also change 'textauto' 1144 if (*p_ffs == NUL) 1145 p_ta = FALSE; 1146 else 1147 p_ta = TRUE; 1148 } 1149 } 1150 1151 #if defined(FEAT_CRYPT) 1152 // 'cryptkey' 1153 else if (gvarp == &p_key) 1154 { 1155 // Make sure the ":set" command doesn't show the new value in the 1156 // history. 1157 remove_key_from_history(); 1158 1159 if (STRCMP(curbuf->b_p_key, oldval) != 0) 1160 // Need to update the swapfile. 1161 { 1162 ml_set_crypt_key(curbuf, oldval, 1163 *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm); 1164 changed_internal(); 1165 } 1166 } 1167 1168 else if (gvarp == &p_cm) 1169 { 1170 if (opt_flags & OPT_LOCAL) 1171 p = curbuf->b_p_cm; 1172 else 1173 p = p_cm; 1174 if (check_opt_strings(p, p_cm_values, TRUE) != OK) 1175 errmsg = e_invarg; 1176 else if (crypt_self_test() == FAIL) 1177 errmsg = e_invarg; 1178 else 1179 { 1180 // When setting the global value to empty, make it "zip". 1181 if (*p_cm == NUL) 1182 { 1183 if (new_value_alloced) 1184 free_string_option(p_cm); 1185 p_cm = vim_strsave((char_u *)"zip"); 1186 new_value_alloced = TRUE; 1187 } 1188 // When using ":set cm=name" the local value is going to be empty. 1189 // Do that here, otherwise the crypt functions will still use the 1190 // local value. 1191 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) 1192 { 1193 free_string_option(curbuf->b_p_cm); 1194 curbuf->b_p_cm = empty_option; 1195 } 1196 1197 // Need to update the swapfile when the effective method changed. 1198 // Set "s" to the effective old value, "p" to the effective new 1199 // method and compare. 1200 if ((opt_flags & OPT_LOCAL) && *oldval == NUL) 1201 s = p_cm; // was previously using the global value 1202 else 1203 s = oldval; 1204 if (*curbuf->b_p_cm == NUL) 1205 p = p_cm; // is now using the global value 1206 else 1207 p = curbuf->b_p_cm; 1208 if (STRCMP(s, p) != 0) 1209 ml_set_crypt_key(curbuf, curbuf->b_p_key, s); 1210 1211 // If the global value changes need to update the swapfile for all 1212 // buffers using that value. 1213 if ((opt_flags & OPT_GLOBAL) && STRCMP(p_cm, oldval) != 0) 1214 { 1215 buf_T *buf; 1216 1217 FOR_ALL_BUFFERS(buf) 1218 if (buf != curbuf && *buf->b_p_cm == NUL) 1219 ml_set_crypt_key(buf, buf->b_p_key, oldval); 1220 } 1221 } 1222 } 1223 #endif 1224 1225 // 'matchpairs' 1226 else if (gvarp == &p_mps) 1227 { 1228 if (has_mbyte) 1229 { 1230 for (p = *varp; *p != NUL; ++p) 1231 { 1232 int x2 = -1; 1233 int x3 = -1; 1234 1235 if (*p != NUL) 1236 p += mb_ptr2len(p); 1237 if (*p != NUL) 1238 x2 = *p++; 1239 if (*p != NUL) 1240 { 1241 x3 = mb_ptr2char(p); 1242 p += mb_ptr2len(p); 1243 } 1244 if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) 1245 { 1246 errmsg = e_invarg; 1247 break; 1248 } 1249 if (*p == NUL) 1250 break; 1251 } 1252 } 1253 else 1254 { 1255 // Check for "x:y,x:y" 1256 for (p = *varp; *p != NUL; p += 4) 1257 { 1258 if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ',')) 1259 { 1260 errmsg = e_invarg; 1261 break; 1262 } 1263 if (p[3] == NUL) 1264 break; 1265 } 1266 } 1267 } 1268 1269 // 'comments' 1270 else if (gvarp == &p_com) 1271 { 1272 for (s = *varp; *s; ) 1273 { 1274 while (*s && *s != ':') 1275 { 1276 if (vim_strchr((char_u *)COM_ALL, *s) == NULL 1277 && !VIM_ISDIGIT(*s) && *s != '-') 1278 { 1279 errmsg = illegal_char(errbuf, *s); 1280 break; 1281 } 1282 ++s; 1283 } 1284 if (*s++ == NUL) 1285 errmsg = N_("E524: Missing colon"); 1286 else if (*s == ',' || *s == NUL) 1287 errmsg = N_("E525: Zero length string"); 1288 if (errmsg != NULL) 1289 break; 1290 while (*s && *s != ',') 1291 { 1292 if (*s == '\\' && s[1] != NUL) 1293 ++s; 1294 ++s; 1295 } 1296 s = skip_to_option_part(s); 1297 } 1298 } 1299 1300 // 'listchars' 1301 else if (varp == &p_lcs) 1302 { 1303 errmsg = set_chars_option(varp); 1304 } 1305 1306 // 'fillchars' 1307 else if (varp == &p_fcs) 1308 { 1309 errmsg = set_chars_option(varp); 1310 } 1311 1312 #ifdef FEAT_CMDWIN 1313 // 'cedit' 1314 else if (varp == &p_cedit) 1315 { 1316 errmsg = check_cedit(); 1317 } 1318 #endif 1319 1320 // 'verbosefile' 1321 else if (varp == &p_vfile) 1322 { 1323 verbose_stop(); 1324 if (*p_vfile != NUL && verbose_open() == FAIL) 1325 errmsg = e_invarg; 1326 } 1327 1328 #ifdef FEAT_VIMINFO 1329 // 'viminfo' 1330 else if (varp == &p_viminfo) 1331 { 1332 for (s = p_viminfo; *s;) 1333 { 1334 // Check it's a valid character 1335 if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) 1336 { 1337 errmsg = illegal_char(errbuf, *s); 1338 break; 1339 } 1340 if (*s == 'n') // name is always last one 1341 break; 1342 else if (*s == 'r') // skip until next ',' 1343 { 1344 while (*++s && *s != ',') 1345 ; 1346 } 1347 else if (*s == '%') 1348 { 1349 // optional number 1350 while (vim_isdigit(*++s)) 1351 ; 1352 } 1353 else if (*s == '!' || *s == 'h' || *s == 'c') 1354 ++s; // no extra chars 1355 else // must have a number 1356 { 1357 while (vim_isdigit(*++s)) 1358 ; 1359 1360 if (!VIM_ISDIGIT(*(s - 1))) 1361 { 1362 if (errbuf != NULL) 1363 { 1364 sprintf(errbuf, _("E526: Missing number after <%s>"), 1365 transchar_byte(*(s - 1))); 1366 errmsg = errbuf; 1367 } 1368 else 1369 errmsg = ""; 1370 break; 1371 } 1372 } 1373 if (*s == ',') 1374 ++s; 1375 else if (*s) 1376 { 1377 if (errbuf != NULL) 1378 errmsg = N_("E527: Missing comma"); 1379 else 1380 errmsg = ""; 1381 break; 1382 } 1383 } 1384 if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0) 1385 errmsg = N_("E528: Must specify a ' value"); 1386 } 1387 #endif // FEAT_VIMINFO 1388 1389 // terminal options 1390 else if (istermoption_idx(opt_idx) && full_screen) 1391 { 1392 // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co=" 1393 if (varp == &T_CCO) 1394 { 1395 int colors = atoi((char *)T_CCO); 1396 1397 // Only reinitialize colors if t_Co value has really changed to 1398 // avoid expensive reload of colorscheme if t_Co is set to the 1399 // same value multiple times. 1400 if (colors != t_colors) 1401 { 1402 t_colors = colors; 1403 if (t_colors <= 1) 1404 { 1405 if (new_value_alloced) 1406 vim_free(T_CCO); 1407 T_CCO = empty_option; 1408 } 1409 #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) 1410 if (is_term_win32()) 1411 { 1412 swap_tcap(); 1413 did_swaptcap = TRUE; 1414 } 1415 #endif 1416 // We now have a different color setup, initialize it again. 1417 init_highlight(TRUE, FALSE); 1418 } 1419 } 1420 ttest(FALSE); 1421 if (varp == &T_ME) 1422 { 1423 out_str(T_ME); 1424 redraw_later(CLEAR); 1425 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 1426 // Since t_me has been set, this probably means that the user 1427 // wants to use this as default colors. Need to reset default 1428 // background/foreground colors. 1429 # ifdef VIMDLL 1430 if (!gui.in_use && !gui.starting) 1431 # endif 1432 mch_set_normal_colors(); 1433 #endif 1434 } 1435 if (varp == &T_BE && termcap_active) 1436 { 1437 if (*T_BE == NUL) 1438 // When clearing t_BE we assume the user no longer wants 1439 // bracketed paste, thus disable it by writing t_BD. 1440 out_str(T_BD); 1441 else 1442 out_str(T_BE); 1443 } 1444 } 1445 1446 #ifdef FEAT_LINEBREAK 1447 // 'showbreak' 1448 else if (gvarp == &p_sbr) 1449 { 1450 for (s = *varp; *s; ) 1451 { 1452 if (ptr2cells(s) != 1) 1453 errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); 1454 MB_PTR_ADV(s); 1455 } 1456 } 1457 #endif 1458 1459 #ifdef FEAT_GUI 1460 // 'guifont' 1461 else if (varp == &p_guifont) 1462 { 1463 if (gui.in_use) 1464 { 1465 p = p_guifont; 1466 # if defined(FEAT_GUI_GTK) 1467 // Put up a font dialog and let the user select a new value. 1468 // If this is cancelled go back to the old value but don't 1469 // give an error message. 1470 if (STRCMP(p, "*") == 0) 1471 { 1472 p = gui_mch_font_dialog(oldval); 1473 1474 if (new_value_alloced) 1475 free_string_option(p_guifont); 1476 1477 p_guifont = (p != NULL) ? p : vim_strsave(oldval); 1478 new_value_alloced = TRUE; 1479 } 1480 # endif 1481 if (p != NULL && gui_init_font(p_guifont, FALSE) != OK) 1482 { 1483 # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON) 1484 if (STRCMP(p_guifont, "*") == 0) 1485 { 1486 // Dialog was cancelled: Keep the old value without giving 1487 // an error message. 1488 if (new_value_alloced) 1489 free_string_option(p_guifont); 1490 p_guifont = vim_strsave(oldval); 1491 new_value_alloced = TRUE; 1492 } 1493 else 1494 # endif 1495 errmsg = N_("E596: Invalid font(s)"); 1496 } 1497 } 1498 redraw_gui_only = TRUE; 1499 } 1500 # ifdef FEAT_XFONTSET 1501 else if (varp == &p_guifontset) 1502 { 1503 if (STRCMP(p_guifontset, "*") == 0) 1504 errmsg = N_("E597: can't select fontset"); 1505 else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK) 1506 errmsg = N_("E598: Invalid fontset"); 1507 redraw_gui_only = TRUE; 1508 } 1509 # endif 1510 else if (varp == &p_guifontwide) 1511 { 1512 if (STRCMP(p_guifontwide, "*") == 0) 1513 errmsg = N_("E533: can't select wide font"); 1514 else if (gui_get_wide_font() == FAIL) 1515 errmsg = N_("E534: Invalid wide font"); 1516 redraw_gui_only = TRUE; 1517 } 1518 #endif 1519 1520 #ifdef CURSOR_SHAPE 1521 // 'guicursor' 1522 else if (varp == &p_guicursor) 1523 errmsg = parse_shape_opt(SHAPE_CURSOR); 1524 #endif 1525 1526 #ifdef FEAT_MOUSESHAPE 1527 // 'mouseshape' 1528 else if (varp == &p_mouseshape) 1529 { 1530 errmsg = parse_shape_opt(SHAPE_MOUSE); 1531 update_mouseshape(-1); 1532 } 1533 #endif 1534 1535 #ifdef FEAT_PRINTER 1536 else if (varp == &p_popt) 1537 errmsg = parse_printoptions(); 1538 # if defined(FEAT_POSTSCRIPT) 1539 else if (varp == &p_pmfn) 1540 errmsg = parse_printmbfont(); 1541 # endif 1542 #endif 1543 1544 #ifdef FEAT_LANGMAP 1545 // 'langmap' 1546 else if (varp == &p_langmap) 1547 langmap_set(); 1548 #endif 1549 1550 #ifdef FEAT_LINEBREAK 1551 // 'breakat' 1552 else if (varp == &p_breakat) 1553 fill_breakat_flags(); 1554 #endif 1555 1556 #ifdef FEAT_TITLE 1557 // 'titlestring' and 'iconstring' 1558 else if (varp == &p_titlestring || varp == &p_iconstring) 1559 { 1560 # ifdef FEAT_STL_OPT 1561 int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON; 1562 1563 // NULL => statusline syntax 1564 if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) 1565 stl_syntax |= flagval; 1566 else 1567 stl_syntax &= ~flagval; 1568 # endif 1569 did_set_title(); 1570 } 1571 #endif 1572 1573 #ifdef FEAT_GUI 1574 // 'guioptions' 1575 else if (varp == &p_go) 1576 { 1577 gui_init_which_components(oldval); 1578 redraw_gui_only = TRUE; 1579 } 1580 #endif 1581 1582 #if defined(FEAT_GUI_TABLINE) 1583 // 'guitablabel' 1584 else if (varp == &p_gtl) 1585 { 1586 redraw_tabline = TRUE; 1587 redraw_gui_only = TRUE; 1588 } 1589 // 'guitabtooltip' 1590 else if (varp == &p_gtt) 1591 { 1592 redraw_gui_only = TRUE; 1593 } 1594 #endif 1595 1596 #if defined(UNIX) || defined(VMS) 1597 // 'ttymouse' 1598 else if (varp == &p_ttym) 1599 { 1600 // Switch the mouse off before changing the escape sequences used for 1601 // that. 1602 mch_setmouse(FALSE); 1603 if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK) 1604 errmsg = e_invarg; 1605 else 1606 check_mouse_termcode(); 1607 if (termcap_active) 1608 setmouse(); // may switch it on again 1609 } 1610 #endif 1611 1612 // 'selection' 1613 else if (varp == &p_sel) 1614 { 1615 if (*p_sel == NUL 1616 || check_opt_strings(p_sel, p_sel_values, FALSE) != OK) 1617 errmsg = e_invarg; 1618 } 1619 1620 // 'selectmode' 1621 else if (varp == &p_slm) 1622 { 1623 if (check_opt_strings(p_slm, p_slm_values, TRUE) != OK) 1624 errmsg = e_invarg; 1625 } 1626 1627 #ifdef FEAT_BROWSE 1628 // 'browsedir' 1629 else if (varp == &p_bsdir) 1630 { 1631 if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK 1632 && !mch_isdir(p_bsdir)) 1633 errmsg = e_invarg; 1634 } 1635 #endif 1636 1637 // 'keymodel' 1638 else if (varp == &p_km) 1639 { 1640 if (check_opt_strings(p_km, p_km_values, TRUE) != OK) 1641 errmsg = e_invarg; 1642 else 1643 { 1644 km_stopsel = (vim_strchr(p_km, 'o') != NULL); 1645 km_startsel = (vim_strchr(p_km, 'a') != NULL); 1646 } 1647 } 1648 1649 // 'mousemodel' 1650 else if (varp == &p_mousem) 1651 { 1652 if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK) 1653 errmsg = e_invarg; 1654 #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002) 1655 else if (*p_mousem != *oldval) 1656 // Changed from "extend" to "popup" or "popup_setpos" or vv: need 1657 // to create or delete the popup menus. 1658 gui_motif_update_mousemodel(root_menu); 1659 #endif 1660 } 1661 1662 // 'switchbuf' 1663 else if (varp == &p_swb) 1664 { 1665 if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE) != OK) 1666 errmsg = e_invarg; 1667 } 1668 1669 // 'debug' 1670 else if (varp == &p_debug) 1671 { 1672 if (check_opt_strings(p_debug, p_debug_values, TRUE) != OK) 1673 errmsg = e_invarg; 1674 } 1675 1676 // 'display' 1677 else if (varp == &p_dy) 1678 { 1679 if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK) 1680 errmsg = e_invarg; 1681 else 1682 (void)init_chartab(); 1683 1684 } 1685 1686 // 'eadirection' 1687 else if (varp == &p_ead) 1688 { 1689 if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK) 1690 errmsg = e_invarg; 1691 } 1692 1693 #ifdef FEAT_CLIPBOARD 1694 // 'clipboard' 1695 else if (varp == &p_cb) 1696 errmsg = check_clipboard_option(); 1697 #endif 1698 1699 #ifdef FEAT_SPELL 1700 // When 'spelllang' or 'spellfile' is set and there is a window for this 1701 // buffer in which 'spell' is set load the wordlists. 1702 else if (varp == &(curwin->w_s->b_p_spl) 1703 || varp == &(curwin->w_s->b_p_spf)) 1704 { 1705 int is_spellfile = varp == &(curwin->w_s->b_p_spf); 1706 1707 if ((is_spellfile && !valid_spellfile(*varp)) 1708 || (!is_spellfile && !valid_spelllang(*varp))) 1709 errmsg = e_invarg; 1710 else 1711 errmsg = did_set_spell_option(is_spellfile); 1712 } 1713 // When 'spellcapcheck' is set compile the regexp program. 1714 else if (varp == &(curwin->w_s->b_p_spc)) 1715 { 1716 errmsg = compile_cap_prog(curwin->w_s); 1717 } 1718 // 'spelloptions' 1719 else if (varp == &(curwin->w_s->b_p_spo)) 1720 { 1721 if (**varp != NUL && STRCMP("camel", *varp) != 0) 1722 errmsg = e_invarg; 1723 } 1724 // 'spellsuggest' 1725 else if (varp == &p_sps) 1726 { 1727 if (spell_check_sps() != OK) 1728 errmsg = e_invarg; 1729 } 1730 // 'mkspellmem' 1731 else if (varp == &p_msm) 1732 { 1733 if (spell_check_msm() != OK) 1734 errmsg = e_invarg; 1735 } 1736 #endif 1737 1738 // When 'bufhidden' is set, check for valid value. 1739 else if (gvarp == &p_bh) 1740 { 1741 if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE) != OK) 1742 errmsg = e_invarg; 1743 } 1744 1745 // When 'buftype' is set, check for valid value. 1746 else if (gvarp == &p_bt) 1747 { 1748 if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK) 1749 errmsg = e_invarg; 1750 else 1751 { 1752 if (curwin->w_status_height) 1753 { 1754 curwin->w_redr_status = TRUE; 1755 redraw_later(VALID); 1756 } 1757 curbuf->b_help = (curbuf->b_p_bt[0] == 'h'); 1758 #ifdef FEAT_TITLE 1759 redraw_titles(); 1760 #endif 1761 } 1762 } 1763 1764 #ifdef FEAT_STL_OPT 1765 // 'statusline' or 'rulerformat' 1766 else if (gvarp == &p_stl || varp == &p_ruf) 1767 { 1768 int wid; 1769 1770 if (varp == &p_ruf) // reset ru_wid first 1771 ru_wid = 0; 1772 s = *varp; 1773 if (varp == &p_ruf && *s == '%') 1774 { 1775 // set ru_wid if 'ruf' starts with "%99(" 1776 if (*++s == '-') // ignore a '-' 1777 s++; 1778 wid = getdigits(&s); 1779 if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) 1780 ru_wid = wid; 1781 else 1782 errmsg = check_stl_option(p_ruf); 1783 } 1784 // check 'statusline' only if it doesn't start with "%!" 1785 else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') 1786 errmsg = check_stl_option(s); 1787 if (varp == &p_ruf && errmsg == NULL) 1788 comp_col(); 1789 } 1790 #endif 1791 1792 // check if it is a valid value for 'complete' -- Acevedo 1793 else if (gvarp == &p_cpt) 1794 { 1795 for (s = *varp; *s;) 1796 { 1797 while (*s == ',' || *s == ' ') 1798 s++; 1799 if (!*s) 1800 break; 1801 if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL) 1802 { 1803 errmsg = illegal_char(errbuf, *s); 1804 break; 1805 } 1806 if (*++s != NUL && *s != ',' && *s != ' ') 1807 { 1808 if (s[-1] == 'k' || s[-1] == 's') 1809 { 1810 // skip optional filename after 'k' and 's' 1811 while (*s && *s != ',' && *s != ' ') 1812 { 1813 if (*s == '\\' && s[1] != NUL) 1814 ++s; 1815 ++s; 1816 } 1817 } 1818 else 1819 { 1820 if (errbuf != NULL) 1821 { 1822 sprintf((char *)errbuf, 1823 _("E535: Illegal character after <%c>"), 1824 *--s); 1825 errmsg = errbuf; 1826 } 1827 else 1828 errmsg = ""; 1829 break; 1830 } 1831 } 1832 } 1833 } 1834 1835 // 'completeopt' 1836 else if (varp == &p_cot) 1837 { 1838 if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK) 1839 errmsg = e_invarg; 1840 else 1841 completeopt_was_set(); 1842 } 1843 1844 #ifdef BACKSLASH_IN_FILENAME 1845 // 'completeslash' 1846 else if (gvarp == &p_csl) 1847 { 1848 if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK 1849 || check_opt_strings(curbuf->b_p_csl, p_csl_values, FALSE) != OK) 1850 errmsg = e_invarg; 1851 } 1852 #endif 1853 1854 #ifdef FEAT_SIGNS 1855 // 'signcolumn' 1856 else if (varp == &curwin->w_p_scl) 1857 { 1858 if (check_opt_strings(*varp, p_scl_values, FALSE) != OK) 1859 errmsg = e_invarg; 1860 // When changing the 'signcolumn' to or from 'number', recompute the 1861 // width of the number column if 'number' or 'relativenumber' is set. 1862 if (((*oldval == 'n' && *(oldval + 1) == 'u') 1863 || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u')) 1864 && (curwin->w_p_nu || curwin->w_p_rnu)) 1865 curwin->w_nrwidth_line_count = 0; 1866 } 1867 #endif 1868 1869 1870 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) 1871 // 'toolbar' 1872 else if (varp == &p_toolbar) 1873 { 1874 if (opt_strings_flags(p_toolbar, p_toolbar_values, 1875 &toolbar_flags, TRUE) != OK) 1876 errmsg = e_invarg; 1877 else 1878 { 1879 out_flush(); 1880 gui_mch_show_toolbar((toolbar_flags & 1881 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0); 1882 } 1883 } 1884 #endif 1885 1886 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) 1887 // 'toolbariconsize': GTK+ 2 only 1888 else if (varp == &p_tbis) 1889 { 1890 if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK) 1891 errmsg = e_invarg; 1892 else 1893 { 1894 out_flush(); 1895 gui_mch_show_toolbar((toolbar_flags & 1896 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0); 1897 } 1898 } 1899 #endif 1900 1901 // 'pastetoggle': translate key codes like in a mapping 1902 else if (varp == &p_pt) 1903 { 1904 if (*p_pt) 1905 { 1906 (void)replace_termcodes(p_pt, &p, 1907 REPTERM_FROM_PART | REPTERM_DO_LT, NULL); 1908 if (p != NULL) 1909 { 1910 if (new_value_alloced) 1911 free_string_option(p_pt); 1912 p_pt = p; 1913 new_value_alloced = TRUE; 1914 } 1915 } 1916 } 1917 1918 // 'backspace' 1919 else if (varp == &p_bs) 1920 { 1921 if (VIM_ISDIGIT(*p_bs)) 1922 { 1923 if (*p_bs > '3' || p_bs[1] != NUL) 1924 errmsg = e_invarg; 1925 } 1926 else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK) 1927 errmsg = e_invarg; 1928 } 1929 else if (varp == &p_bo) 1930 { 1931 if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE) != OK) 1932 errmsg = e_invarg; 1933 } 1934 1935 // 'tagcase' 1936 else if (gvarp == &p_tc) 1937 { 1938 unsigned int *flags; 1939 1940 if (opt_flags & OPT_LOCAL) 1941 { 1942 p = curbuf->b_p_tc; 1943 flags = &curbuf->b_tc_flags; 1944 } 1945 else 1946 { 1947 p = p_tc; 1948 flags = &tc_flags; 1949 } 1950 1951 if ((opt_flags & OPT_LOCAL) && *p == NUL) 1952 // make the local value empty: use the global value 1953 *flags = 0; 1954 else if (*p == NUL 1955 || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK) 1956 errmsg = e_invarg; 1957 } 1958 1959 // 'casemap' 1960 else if (varp == &p_cmp) 1961 { 1962 if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE) != OK) 1963 errmsg = e_invarg; 1964 } 1965 1966 #ifdef FEAT_DIFF 1967 // 'diffopt' 1968 else if (varp == &p_dip) 1969 { 1970 if (diffopt_changed() == FAIL) 1971 errmsg = e_invarg; 1972 } 1973 #endif 1974 1975 #ifdef FEAT_FOLDING 1976 // 'foldmethod' 1977 else if (gvarp == &curwin->w_allbuf_opt.wo_fdm) 1978 { 1979 if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK 1980 || *curwin->w_p_fdm == NUL) 1981 errmsg = e_invarg; 1982 else 1983 { 1984 foldUpdateAll(curwin); 1985 if (foldmethodIsDiff(curwin)) 1986 newFoldLevel(); 1987 } 1988 } 1989 # ifdef FEAT_EVAL 1990 // 'foldexpr' 1991 else if (varp == &curwin->w_p_fde) 1992 { 1993 if (foldmethodIsExpr(curwin)) 1994 foldUpdateAll(curwin); 1995 } 1996 # endif 1997 // 'foldmarker' 1998 else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) 1999 { 2000 p = vim_strchr(*varp, ','); 2001 if (p == NULL) 2002 errmsg = N_("E536: comma required"); 2003 else if (p == *varp || p[1] == NUL) 2004 errmsg = e_invarg; 2005 else if (foldmethodIsMarker(curwin)) 2006 foldUpdateAll(curwin); 2007 } 2008 // 'commentstring' 2009 else if (gvarp == &p_cms) 2010 { 2011 if (**varp != NUL && strstr((char *)*varp, "%s") == NULL) 2012 errmsg = N_("E537: 'commentstring' must be empty or contain %s"); 2013 } 2014 // 'foldopen' 2015 else if (varp == &p_fdo) 2016 { 2017 if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE) != OK) 2018 errmsg = e_invarg; 2019 } 2020 // 'foldclose' 2021 else if (varp == &p_fcl) 2022 { 2023 if (check_opt_strings(p_fcl, p_fcl_values, TRUE) != OK) 2024 errmsg = e_invarg; 2025 } 2026 // 'foldignore' 2027 else if (gvarp == &curwin->w_allbuf_opt.wo_fdi) 2028 { 2029 if (foldmethodIsIndent(curwin)) 2030 foldUpdateAll(curwin); 2031 } 2032 #endif 2033 2034 // 'virtualedit' 2035 else if (varp == &p_ve) 2036 { 2037 if (opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE) != OK) 2038 errmsg = e_invarg; 2039 else if (STRCMP(p_ve, oldval) != 0) 2040 { 2041 // Recompute cursor position in case the new 've' setting 2042 // changes something. 2043 validate_virtcol(); 2044 coladvance(curwin->w_virtcol); 2045 } 2046 } 2047 2048 #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX) 2049 else if (varp == &p_csqf) 2050 { 2051 if (p_csqf != NULL) 2052 { 2053 p = p_csqf; 2054 while (*p != NUL) 2055 { 2056 if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL 2057 || p[1] == NUL 2058 || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL 2059 || (p[2] != NUL && p[2] != ',')) 2060 { 2061 errmsg = e_invarg; 2062 break; 2063 } 2064 else if (p[2] == NUL) 2065 break; 2066 else 2067 p += 3; 2068 } 2069 } 2070 } 2071 #endif 2072 2073 #ifdef FEAT_CINDENT 2074 // 'cinoptions' 2075 else if (gvarp == &p_cino) 2076 { 2077 // TODO: recognize errors 2078 parse_cino(curbuf); 2079 } 2080 #endif 2081 2082 #if defined(FEAT_RENDER_OPTIONS) 2083 // 'renderoptions' 2084 else if (varp == &p_rop) 2085 { 2086 if (!gui_mch_set_rendering_options(p_rop)) 2087 errmsg = e_invarg; 2088 } 2089 #endif 2090 2091 else if (gvarp == &p_ft) 2092 { 2093 if (!valid_filetype(*varp)) 2094 errmsg = e_invarg; 2095 else 2096 { 2097 value_changed = STRCMP(oldval, *varp) != 0; 2098 2099 // Since we check the value, there is no need to set P_INSECURE, 2100 // even when the value comes from a modeline. 2101 *value_checked = TRUE; 2102 } 2103 } 2104 2105 #ifdef FEAT_SYN_HL 2106 else if (gvarp == &p_syn) 2107 { 2108 if (!valid_filetype(*varp)) 2109 errmsg = e_invarg; 2110 else 2111 { 2112 value_changed = STRCMP(oldval, *varp) != 0; 2113 2114 // Since we check the value, there is no need to set P_INSECURE, 2115 // even when the value comes from a modeline. 2116 *value_checked = TRUE; 2117 } 2118 } 2119 #endif 2120 2121 #ifdef FEAT_TERMINAL 2122 // 'termwinkey' 2123 else if (varp == &curwin->w_p_twk) 2124 { 2125 if (*curwin->w_p_twk != NUL 2126 && string_to_key(curwin->w_p_twk, TRUE) == 0) 2127 errmsg = e_invarg; 2128 } 2129 // 'termwinsize' 2130 else if (varp == &curwin->w_p_tws) 2131 { 2132 if (*curwin->w_p_tws != NUL) 2133 { 2134 p = skipdigits(curwin->w_p_tws); 2135 if (p == curwin->w_p_tws 2136 || (*p != 'x' && *p != '*') 2137 || *skipdigits(p + 1) != NUL) 2138 errmsg = e_invarg; 2139 } 2140 } 2141 // 'wincolor' 2142 else if (varp == &curwin->w_p_wcr) 2143 { 2144 if (curwin->w_buffer->b_term != NULL) 2145 term_update_colors(); 2146 } 2147 # if defined(MSWIN) 2148 // 'termwintype' 2149 else if (varp == &p_twt) 2150 { 2151 if (check_opt_strings(*varp, p_twt_values, FALSE) != OK) 2152 errmsg = e_invarg; 2153 } 2154 # endif 2155 #endif 2156 2157 #ifdef FEAT_VARTABS 2158 // 'varsofttabstop' 2159 else if (varp == &(curbuf->b_p_vsts)) 2160 { 2161 char_u *cp; 2162 2163 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) 2164 { 2165 if (curbuf->b_p_vsts_array) 2166 { 2167 vim_free(curbuf->b_p_vsts_array); 2168 curbuf->b_p_vsts_array = 0; 2169 } 2170 } 2171 else 2172 { 2173 for (cp = *varp; *cp; ++cp) 2174 { 2175 if (vim_isdigit(*cp)) 2176 continue; 2177 if (*cp == ',' && cp > *varp && *(cp-1) != ',') 2178 continue; 2179 errmsg = e_invarg; 2180 break; 2181 } 2182 if (errmsg == NULL) 2183 { 2184 int *oldarray = curbuf->b_p_vsts_array; 2185 if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) 2186 { 2187 if (oldarray) 2188 vim_free(oldarray); 2189 } 2190 else 2191 errmsg = e_invarg; 2192 } 2193 } 2194 } 2195 2196 // 'vartabstop' 2197 else if (varp == &(curbuf->b_p_vts)) 2198 { 2199 char_u *cp; 2200 2201 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) 2202 { 2203 if (curbuf->b_p_vts_array) 2204 { 2205 vim_free(curbuf->b_p_vts_array); 2206 curbuf->b_p_vts_array = NULL; 2207 } 2208 } 2209 else 2210 { 2211 for (cp = *varp; *cp; ++cp) 2212 { 2213 if (vim_isdigit(*cp)) 2214 continue; 2215 if (*cp == ',' && cp > *varp && *(cp-1) != ',') 2216 continue; 2217 errmsg = e_invarg; 2218 break; 2219 } 2220 if (errmsg == NULL) 2221 { 2222 int *oldarray = curbuf->b_p_vts_array; 2223 2224 if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) 2225 { 2226 vim_free(oldarray); 2227 #ifdef FEAT_FOLDING 2228 if (foldmethodIsIndent(curwin)) 2229 foldUpdateAll(curwin); 2230 #endif 2231 } 2232 else 2233 errmsg = e_invarg; 2234 } 2235 } 2236 } 2237 #endif 2238 2239 #ifdef FEAT_PROP_POPUP 2240 // 'previewpopup' 2241 else if (varp == &p_pvp) 2242 { 2243 if (parse_previewpopup(NULL) == FAIL) 2244 errmsg = e_invarg; 2245 } 2246 # ifdef FEAT_QUICKFIX 2247 // 'completepopup' 2248 else if (varp == &p_cpp) 2249 { 2250 if (parse_completepopup(NULL) == FAIL) 2251 errmsg = e_invarg; 2252 else 2253 popup_close_info(); 2254 } 2255 # endif 2256 #endif 2257 2258 #ifdef FEAT_QUICKFIX 2259 else if (varp == &p_qftf) 2260 { 2261 if (qf_process_qftf_option() == FALSE) 2262 errmsg = e_invarg; 2263 } 2264 #endif 2265 2266 // Options that are a list of flags. 2267 else 2268 { 2269 p = NULL; 2270 if (varp == &p_ww) // 'whichwrap' 2271 p = (char_u *)WW_ALL; 2272 if (varp == &p_shm) // 'shortmess' 2273 p = (char_u *)SHM_ALL; 2274 else if (varp == &(p_cpo)) // 'cpoptions' 2275 p = (char_u *)CPO_ALL; 2276 else if (varp == &(curbuf->b_p_fo)) // 'formatoptions' 2277 p = (char_u *)FO_ALL; 2278 #ifdef FEAT_CONCEAL 2279 else if (varp == &curwin->w_p_cocu) // 'concealcursor' 2280 p = (char_u *)COCU_ALL; 2281 #endif 2282 else if (varp == &p_mouse) // 'mouse' 2283 { 2284 p = (char_u *)MOUSE_ALL; 2285 } 2286 #if defined(FEAT_GUI) 2287 else if (varp == &p_go) // 'guioptions' 2288 p = (char_u *)GO_ALL; 2289 #endif 2290 if (p != NULL) 2291 { 2292 for (s = *varp; *s; ++s) 2293 if (vim_strchr(p, *s) == NULL) 2294 { 2295 errmsg = illegal_char(errbuf, *s); 2296 break; 2297 } 2298 } 2299 } 2300 2301 // If error detected, restore the previous value. 2302 if (errmsg != NULL) 2303 { 2304 if (new_value_alloced) 2305 free_string_option(*varp); 2306 *varp = oldval; 2307 // When resetting some values, need to act on it. 2308 if (did_chartab) 2309 (void)init_chartab(); 2310 if (varp == &p_hl) 2311 (void)highlight_changed(); 2312 } 2313 else 2314 { 2315 #ifdef FEAT_EVAL 2316 // Remember where the option was set. 2317 set_option_sctx_idx(opt_idx, opt_flags, current_sctx); 2318 #endif 2319 // Free string options that are in allocated memory. 2320 // Use "free_oldval", because recursiveness may change the flags under 2321 // our fingers (esp. init_highlight()). 2322 if (free_oldval) 2323 free_string_option(oldval); 2324 if (new_value_alloced) 2325 set_option_flag(opt_idx, P_ALLOCED); 2326 else 2327 clear_option_flag(opt_idx, P_ALLOCED); 2328 2329 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 2330 && is_global_local_option(opt_idx)) 2331 { 2332 // global option with local value set to use global value; free 2333 // the local value and make it empty 2334 p = get_option_varp_scope(opt_idx, OPT_LOCAL); 2335 free_string_option(*(char_u **)p); 2336 *(char_u **)p = empty_option; 2337 } 2338 2339 // May set global value for local option. 2340 else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) 2341 set_string_option_global(opt_idx, varp); 2342 2343 // Trigger the autocommand only after setting the flags. 2344 #ifdef FEAT_SYN_HL 2345 // When 'syntax' is set, load the syntax of that name 2346 if (varp == &(curbuf->b_p_syn)) 2347 { 2348 static int syn_recursive = 0; 2349 2350 ++syn_recursive; 2351 // Only pass TRUE for "force" when the value changed or not used 2352 // recursively, to avoid endless recurrence. 2353 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, 2354 value_changed || syn_recursive == 1, curbuf); 2355 curbuf->b_flags |= BF_SYN_SET; 2356 --syn_recursive; 2357 } 2358 #endif 2359 else if (varp == &(curbuf->b_p_ft)) 2360 { 2361 // 'filetype' is set, trigger the FileType autocommand. 2362 // Skip this when called from a modeline and the filetype was 2363 // already set to this value. 2364 if (!(opt_flags & OPT_MODELINE) || value_changed) 2365 { 2366 static int ft_recursive = 0; 2367 int secure_save = secure; 2368 2369 // Reset the secure flag, since the value of 'filetype' has 2370 // been checked to be safe. 2371 secure = 0; 2372 2373 ++ft_recursive; 2374 did_filetype = TRUE; 2375 // Only pass TRUE for "force" when the value changed or not 2376 // used recursively, to avoid endless recurrence. 2377 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, 2378 value_changed || ft_recursive == 1, curbuf); 2379 --ft_recursive; 2380 // Just in case the old "curbuf" is now invalid. 2381 if (varp != &(curbuf->b_p_ft)) 2382 varp = NULL; 2383 2384 secure = secure_save; 2385 } 2386 } 2387 #ifdef FEAT_SPELL 2388 if (varp == &(curwin->w_s->b_p_spl)) 2389 { 2390 char_u fname[200]; 2391 char_u *q = curwin->w_s->b_p_spl; 2392 2393 // Skip the first name if it is "cjk". 2394 if (STRNCMP(q, "cjk,", 4) == 0) 2395 q += 4; 2396 2397 // Source the spell/LANG.vim in 'runtimepath'. 2398 // They could set 'spellcapcheck' depending on the language. 2399 // Use the first name in 'spelllang' up to '_region' or 2400 // '.encoding'. 2401 for (p = q; *p != NUL; ++p) 2402 if (!ASCII_ISALNUM(*p) && *p != '-') 2403 break; 2404 if (p > q) 2405 { 2406 vim_snprintf((char *)fname, 200, "spell/%.*s.vim", 2407 (int)(p - q), q); 2408 source_runtime(fname, DIP_ALL); 2409 } 2410 } 2411 #endif 2412 } 2413 2414 if (varp == &p_mouse) 2415 { 2416 if (*p_mouse == NUL) 2417 mch_setmouse(FALSE); // switch mouse off 2418 else 2419 setmouse(); // in case 'mouse' changed 2420 } 2421 2422 #if defined(FEAT_LUA) || defined(PROTO) 2423 if (varp == &p_rtp) 2424 update_package_paths_in_lua(); 2425 #endif 2426 2427 if (curwin->w_curswant != MAXCOL 2428 && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) 2429 curwin->w_set_curswant = TRUE; 2430 2431 #ifdef FEAT_GUI 2432 // check redraw when it's not a GUI option or the GUI is active. 2433 if (!redraw_gui_only || gui.in_use) 2434 #endif 2435 check_redraw(get_option_flags(opt_idx)); 2436 2437 #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) 2438 if (did_swaptcap) 2439 { 2440 set_termname((char_u *)"win32"); 2441 init_highlight(TRUE, FALSE); 2442 } 2443 #endif 2444 2445 return errmsg; 2446 } 2447 2448 /* 2449 * Check an option that can be a range of string values. 2450 * 2451 * Return OK for correct value, FAIL otherwise. 2452 * Empty is always OK. 2453 */ 2454 static int 2455 check_opt_strings( 2456 char_u *val, 2457 char **values, 2458 int list) // when TRUE: accept a list of values 2459 { 2460 return opt_strings_flags(val, values, NULL, list); 2461 } 2462 2463 /* 2464 * Handle an option that can be a range of string values. 2465 * Set a flag in "*flagp" for each string present. 2466 * 2467 * Return OK for correct value, FAIL otherwise. 2468 * Empty is always OK. 2469 */ 2470 static int 2471 opt_strings_flags( 2472 char_u *val, // new value 2473 char **values, // array of valid string values 2474 unsigned *flagp, 2475 int list) // when TRUE: accept a list of values 2476 { 2477 int i; 2478 int len; 2479 unsigned new_flags = 0; 2480 2481 while (*val) 2482 { 2483 for (i = 0; ; ++i) 2484 { 2485 if (values[i] == NULL) // val not found in values[] 2486 return FAIL; 2487 2488 len = (int)STRLEN(values[i]); 2489 if (STRNCMP(values[i], val, len) == 0 2490 && ((list && val[len] == ',') || val[len] == NUL)) 2491 { 2492 val += len + (val[len] == ','); 2493 new_flags |= (1 << i); 2494 break; // check next item in val list 2495 } 2496 } 2497 } 2498 if (flagp != NULL) 2499 *flagp = new_flags; 2500 2501 return OK; 2502 } 2503 2504 /* 2505 * return OK if "p" is a valid fileformat name, FAIL otherwise. 2506 */ 2507 int 2508 check_ff_value(char_u *p) 2509 { 2510 return check_opt_strings(p, p_ff_values, FALSE); 2511 } 2512