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