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