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", "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 #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 == NULL ? (char_u *)"" : 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 { 1161 ml_set_crypt_key(curbuf, oldval, 1162 *curbuf->b_p_cm == NUL ? p_cm : curbuf->b_p_cm); 1163 changed_internal(); 1164 } 1165 } 1166 1167 else if (gvarp == &p_cm) 1168 { 1169 if (opt_flags & OPT_LOCAL) 1170 p = curbuf->b_p_cm; 1171 else 1172 p = p_cm; 1173 if (check_opt_strings(p, p_cm_values, TRUE) != OK) 1174 errmsg = e_invarg; 1175 else if (crypt_self_test() == FAIL) 1176 errmsg = e_invarg; 1177 else 1178 { 1179 // When setting the global value to empty, make it "zip". 1180 if (*p_cm == NUL) 1181 { 1182 if (new_value_alloced) 1183 free_string_option(p_cm); 1184 p_cm = vim_strsave((char_u *)"zip"); 1185 new_value_alloced = TRUE; 1186 } 1187 // When using ":set cm=name" the local value is going to be empty. 1188 // Do that here, otherwise the crypt functions will still use the 1189 // local value. 1190 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) 1191 { 1192 free_string_option(curbuf->b_p_cm); 1193 curbuf->b_p_cm = empty_option; 1194 } 1195 1196 // Need to update the swapfile when the effective method changed. 1197 // Set "s" to the effective old value, "p" to the effective new 1198 // method and compare. 1199 if ((opt_flags & OPT_LOCAL) && *oldval == NUL) 1200 s = p_cm; // was previously using the global value 1201 else 1202 s = oldval; 1203 if (*curbuf->b_p_cm == NUL) 1204 p = p_cm; // is now using the global value 1205 else 1206 p = curbuf->b_p_cm; 1207 if (STRCMP(s, p) != 0) 1208 ml_set_crypt_key(curbuf, curbuf->b_p_key, s); 1209 1210 // If the global value changes need to update the swapfile for all 1211 // buffers using that value. 1212 if ((opt_flags & OPT_GLOBAL) && STRCMP(p_cm, oldval) != 0) 1213 { 1214 buf_T *buf; 1215 1216 FOR_ALL_BUFFERS(buf) 1217 if (buf != curbuf && *buf->b_p_cm == NUL) 1218 ml_set_crypt_key(buf, buf->b_p_key, oldval); 1219 } 1220 } 1221 } 1222 #endif 1223 1224 // 'matchpairs' 1225 else if (gvarp == &p_mps) 1226 { 1227 if (has_mbyte) 1228 { 1229 for (p = *varp; *p != NUL; ++p) 1230 { 1231 int x2 = -1; 1232 int x3 = -1; 1233 1234 if (*p != NUL) 1235 p += mb_ptr2len(p); 1236 if (*p != NUL) 1237 x2 = *p++; 1238 if (*p != NUL) 1239 { 1240 x3 = mb_ptr2char(p); 1241 p += mb_ptr2len(p); 1242 } 1243 if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) 1244 { 1245 errmsg = e_invarg; 1246 break; 1247 } 1248 if (*p == NUL) 1249 break; 1250 } 1251 } 1252 else 1253 { 1254 // Check for "x:y,x:y" 1255 for (p = *varp; *p != NUL; p += 4) 1256 { 1257 if (p[1] != ':' || p[2] == NUL || (p[3] != NUL && p[3] != ',')) 1258 { 1259 errmsg = e_invarg; 1260 break; 1261 } 1262 if (p[3] == NUL) 1263 break; 1264 } 1265 } 1266 } 1267 1268 // 'comments' 1269 else if (gvarp == &p_com) 1270 { 1271 for (s = *varp; *s; ) 1272 { 1273 while (*s && *s != ':') 1274 { 1275 if (vim_strchr((char_u *)COM_ALL, *s) == NULL 1276 && !VIM_ISDIGIT(*s) && *s != '-') 1277 { 1278 errmsg = illegal_char(errbuf, *s); 1279 break; 1280 } 1281 ++s; 1282 } 1283 if (*s++ == NUL) 1284 errmsg = N_("E524: Missing colon"); 1285 else if (*s == ',' || *s == NUL) 1286 errmsg = N_("E525: Zero length string"); 1287 if (errmsg != NULL) 1288 break; 1289 while (*s && *s != ',') 1290 { 1291 if (*s == '\\' && s[1] != NUL) 1292 ++s; 1293 ++s; 1294 } 1295 s = skip_to_option_part(s); 1296 } 1297 } 1298 1299 // 'listchars' 1300 else if (varp == &p_lcs) 1301 { 1302 errmsg = set_chars_option(varp); 1303 } 1304 1305 // 'fillchars' 1306 else if (varp == &p_fcs) 1307 { 1308 errmsg = set_chars_option(varp); 1309 } 1310 1311 #ifdef FEAT_CMDWIN 1312 // 'cedit' 1313 else if (varp == &p_cedit) 1314 { 1315 errmsg = check_cedit(); 1316 } 1317 #endif 1318 1319 // 'verbosefile' 1320 else if (varp == &p_vfile) 1321 { 1322 verbose_stop(); 1323 if (*p_vfile != NUL && verbose_open() == FAIL) 1324 errmsg = e_invarg; 1325 } 1326 1327 #ifdef FEAT_VIMINFO 1328 // 'viminfo' 1329 else if (varp == &p_viminfo) 1330 { 1331 for (s = p_viminfo; *s;) 1332 { 1333 // Check it's a valid character 1334 if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) 1335 { 1336 errmsg = illegal_char(errbuf, *s); 1337 break; 1338 } 1339 if (*s == 'n') // name is always last one 1340 break; 1341 else if (*s == 'r') // skip until next ',' 1342 { 1343 while (*++s && *s != ',') 1344 ; 1345 } 1346 else if (*s == '%') 1347 { 1348 // optional number 1349 while (vim_isdigit(*++s)) 1350 ; 1351 } 1352 else if (*s == '!' || *s == 'h' || *s == 'c') 1353 ++s; // no extra chars 1354 else // must have a number 1355 { 1356 while (vim_isdigit(*++s)) 1357 ; 1358 1359 if (!VIM_ISDIGIT(*(s - 1))) 1360 { 1361 if (errbuf != NULL) 1362 { 1363 sprintf(errbuf, _("E526: Missing number after <%s>"), 1364 transchar_byte(*(s - 1))); 1365 errmsg = errbuf; 1366 } 1367 else 1368 errmsg = ""; 1369 break; 1370 } 1371 } 1372 if (*s == ',') 1373 ++s; 1374 else if (*s) 1375 { 1376 if (errbuf != NULL) 1377 errmsg = N_("E527: Missing comma"); 1378 else 1379 errmsg = ""; 1380 break; 1381 } 1382 } 1383 if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0) 1384 errmsg = N_("E528: Must specify a ' value"); 1385 } 1386 #endif // FEAT_VIMINFO 1387 1388 // terminal options 1389 else if (istermoption_idx(opt_idx) && full_screen) 1390 { 1391 // ":set t_Co=0" and ":set t_Co=1" do ":set t_Co=" 1392 if (varp == &T_CCO) 1393 { 1394 int colors = atoi((char *)T_CCO); 1395 1396 // Only reinitialize colors if t_Co value has really changed to 1397 // avoid expensive reload of colorscheme if t_Co is set to the 1398 // same value multiple times. 1399 if (colors != t_colors) 1400 { 1401 t_colors = colors; 1402 if (t_colors <= 1) 1403 { 1404 if (new_value_alloced) 1405 vim_free(T_CCO); 1406 T_CCO = empty_option; 1407 } 1408 #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) 1409 if (is_term_win32()) 1410 { 1411 swap_tcap(); 1412 did_swaptcap = TRUE; 1413 } 1414 #endif 1415 // We now have a different color setup, initialize it again. 1416 init_highlight(TRUE, FALSE); 1417 } 1418 } 1419 ttest(FALSE); 1420 if (varp == &T_ME) 1421 { 1422 out_str(T_ME); 1423 redraw_later(CLEAR); 1424 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 1425 // Since t_me has been set, this probably means that the user 1426 // wants to use this as default colors. Need to reset default 1427 // background/foreground colors. 1428 # ifdef VIMDLL 1429 if (!gui.in_use && !gui.starting) 1430 # endif 1431 mch_set_normal_colors(); 1432 #endif 1433 } 1434 if (varp == &T_BE && termcap_active) 1435 { 1436 if (*T_BE == NUL) 1437 // When clearing t_BE we assume the user no longer wants 1438 // bracketed paste, thus disable it by writing t_BD. 1439 out_str(T_BD); 1440 else 1441 out_str(T_BE); 1442 } 1443 } 1444 1445 #ifdef FEAT_LINEBREAK 1446 // 'showbreak' 1447 else if (gvarp == &p_sbr) 1448 { 1449 for (s = *varp; *s; ) 1450 { 1451 if (ptr2cells(s) != 1) 1452 errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); 1453 MB_PTR_ADV(s); 1454 } 1455 } 1456 #endif 1457 1458 #ifdef FEAT_GUI 1459 // 'guifont' 1460 else if (varp == &p_guifont) 1461 { 1462 if (gui.in_use) 1463 { 1464 p = p_guifont; 1465 # if defined(FEAT_GUI_GTK) 1466 // Put up a font dialog and let the user select a new value. 1467 // If this is cancelled go back to the old value but don't 1468 // give an error message. 1469 if (STRCMP(p, "*") == 0) 1470 { 1471 p = gui_mch_font_dialog(oldval); 1472 1473 if (new_value_alloced) 1474 free_string_option(p_guifont); 1475 1476 p_guifont = (p != NULL) ? p : vim_strsave(oldval); 1477 new_value_alloced = TRUE; 1478 } 1479 # endif 1480 if (p != NULL && gui_init_font(p_guifont, FALSE) != OK) 1481 { 1482 # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON) 1483 if (STRCMP(p_guifont, "*") == 0) 1484 { 1485 // Dialog was cancelled: Keep the old value without giving 1486 // an error message. 1487 if (new_value_alloced) 1488 free_string_option(p_guifont); 1489 p_guifont = vim_strsave(oldval); 1490 new_value_alloced = TRUE; 1491 } 1492 else 1493 # endif 1494 errmsg = N_("E596: Invalid font(s)"); 1495 } 1496 } 1497 redraw_gui_only = TRUE; 1498 } 1499 # ifdef FEAT_XFONTSET 1500 else if (varp == &p_guifontset) 1501 { 1502 if (STRCMP(p_guifontset, "*") == 0) 1503 errmsg = N_("E597: can't select fontset"); 1504 else if (gui.in_use && gui_init_font(p_guifontset, TRUE) != OK) 1505 errmsg = N_("E598: Invalid fontset"); 1506 redraw_gui_only = TRUE; 1507 } 1508 # endif 1509 else if (varp == &p_guifontwide) 1510 { 1511 if (STRCMP(p_guifontwide, "*") == 0) 1512 errmsg = N_("E533: can't select wide font"); 1513 else if (gui_get_wide_font() == FAIL) 1514 errmsg = N_("E534: Invalid wide font"); 1515 redraw_gui_only = TRUE; 1516 } 1517 #endif 1518 1519 #ifdef CURSOR_SHAPE 1520 // 'guicursor' 1521 else if (varp == &p_guicursor) 1522 errmsg = parse_shape_opt(SHAPE_CURSOR); 1523 #endif 1524 1525 #ifdef FEAT_MOUSESHAPE 1526 // 'mouseshape' 1527 else if (varp == &p_mouseshape) 1528 { 1529 errmsg = parse_shape_opt(SHAPE_MOUSE); 1530 update_mouseshape(-1); 1531 } 1532 #endif 1533 1534 #ifdef FEAT_PRINTER 1535 else if (varp == &p_popt) 1536 errmsg = parse_printoptions(); 1537 # if defined(FEAT_POSTSCRIPT) 1538 else if (varp == &p_pmfn) 1539 errmsg = parse_printmbfont(); 1540 # endif 1541 #endif 1542 1543 #ifdef FEAT_LANGMAP 1544 // 'langmap' 1545 else if (varp == &p_langmap) 1546 langmap_set(); 1547 #endif 1548 1549 #ifdef FEAT_LINEBREAK 1550 // 'breakat' 1551 else if (varp == &p_breakat) 1552 fill_breakat_flags(); 1553 #endif 1554 1555 #ifdef FEAT_TITLE 1556 // 'titlestring' and 'iconstring' 1557 else if (varp == &p_titlestring || varp == &p_iconstring) 1558 { 1559 # ifdef FEAT_STL_OPT 1560 int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON; 1561 1562 // NULL => statusline syntax 1563 if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) 1564 stl_syntax |= flagval; 1565 else 1566 stl_syntax &= ~flagval; 1567 # endif 1568 did_set_title(); 1569 } 1570 #endif 1571 1572 #ifdef FEAT_GUI 1573 // 'guioptions' 1574 else if (varp == &p_go) 1575 { 1576 gui_init_which_components(oldval); 1577 redraw_gui_only = TRUE; 1578 } 1579 #endif 1580 1581 #if defined(FEAT_GUI_TABLINE) 1582 // 'guitablabel' 1583 else if (varp == &p_gtl) 1584 { 1585 redraw_tabline = TRUE; 1586 redraw_gui_only = TRUE; 1587 } 1588 // 'guitabtooltip' 1589 else if (varp == &p_gtt) 1590 { 1591 redraw_gui_only = TRUE; 1592 } 1593 #endif 1594 1595 #if defined(UNIX) || defined(VMS) 1596 // 'ttymouse' 1597 else if (varp == &p_ttym) 1598 { 1599 // Switch the mouse off before changing the escape sequences used for 1600 // that. 1601 mch_setmouse(FALSE); 1602 if (opt_strings_flags(p_ttym, p_ttym_values, &ttym_flags, FALSE) != OK) 1603 errmsg = e_invarg; 1604 else 1605 check_mouse_termcode(); 1606 if (termcap_active) 1607 setmouse(); // may switch it on again 1608 } 1609 #endif 1610 1611 // 'selection' 1612 else if (varp == &p_sel) 1613 { 1614 if (*p_sel == NUL 1615 || check_opt_strings(p_sel, p_sel_values, FALSE) != OK) 1616 errmsg = e_invarg; 1617 } 1618 1619 // 'selectmode' 1620 else if (varp == &p_slm) 1621 { 1622 if (check_opt_strings(p_slm, p_slm_values, TRUE) != OK) 1623 errmsg = e_invarg; 1624 } 1625 1626 #ifdef FEAT_BROWSE 1627 // 'browsedir' 1628 else if (varp == &p_bsdir) 1629 { 1630 if (check_opt_strings(p_bsdir, p_bsdir_values, FALSE) != OK 1631 && !mch_isdir(p_bsdir)) 1632 errmsg = e_invarg; 1633 } 1634 #endif 1635 1636 // 'keymodel' 1637 else if (varp == &p_km) 1638 { 1639 if (check_opt_strings(p_km, p_km_values, TRUE) != OK) 1640 errmsg = e_invarg; 1641 else 1642 { 1643 km_stopsel = (vim_strchr(p_km, 'o') != NULL); 1644 km_startsel = (vim_strchr(p_km, 'a') != NULL); 1645 } 1646 } 1647 1648 // 'mousemodel' 1649 else if (varp == &p_mousem) 1650 { 1651 if (check_opt_strings(p_mousem, p_mousem_values, FALSE) != OK) 1652 errmsg = e_invarg; 1653 #if defined(FEAT_GUI_MOTIF) && defined(FEAT_MENU) && (XmVersion <= 1002) 1654 else if (*p_mousem != *oldval) 1655 // Changed from "extend" to "popup" or "popup_setpos" or vv: need 1656 // to create or delete the popup menus. 1657 gui_motif_update_mousemodel(root_menu); 1658 #endif 1659 } 1660 1661 // 'switchbuf' 1662 else if (varp == &p_swb) 1663 { 1664 if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE) != OK) 1665 errmsg = e_invarg; 1666 } 1667 1668 // 'debug' 1669 else if (varp == &p_debug) 1670 { 1671 if (check_opt_strings(p_debug, p_debug_values, TRUE) != OK) 1672 errmsg = e_invarg; 1673 } 1674 1675 // 'display' 1676 else if (varp == &p_dy) 1677 { 1678 if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, TRUE) != OK) 1679 errmsg = e_invarg; 1680 else 1681 (void)init_chartab(); 1682 1683 } 1684 1685 // 'eadirection' 1686 else if (varp == &p_ead) 1687 { 1688 if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK) 1689 errmsg = e_invarg; 1690 } 1691 1692 #ifdef FEAT_CLIPBOARD 1693 // 'clipboard' 1694 else if (varp == &p_cb) 1695 errmsg = check_clipboard_option(); 1696 #endif 1697 1698 #ifdef FEAT_SPELL 1699 // When 'spelllang' or 'spellfile' is set and there is a window for this 1700 // buffer in which 'spell' is set load the wordlists. 1701 else if (varp == &(curwin->w_s->b_p_spl) 1702 || varp == &(curwin->w_s->b_p_spf)) 1703 { 1704 int is_spellfile = varp == &(curwin->w_s->b_p_spf); 1705 1706 if ((is_spellfile && !valid_spellfile(*varp)) 1707 || (!is_spellfile && !valid_spellang(*varp))) 1708 errmsg = e_invarg; 1709 else 1710 errmsg = did_set_spell_option(is_spellfile); 1711 } 1712 // When 'spellcapcheck' is set compile the regexp program. 1713 else if (varp == &(curwin->w_s->b_p_spc)) 1714 { 1715 errmsg = compile_cap_prog(curwin->w_s); 1716 } 1717 // 'spellsuggest' 1718 else if (varp == &p_sps) 1719 { 1720 if (spell_check_sps() != OK) 1721 errmsg = e_invarg; 1722 } 1723 // 'mkspellmem' 1724 else if (varp == &p_msm) 1725 { 1726 if (spell_check_msm() != OK) 1727 errmsg = e_invarg; 1728 } 1729 #endif 1730 1731 // When 'bufhidden' is set, check for valid value. 1732 else if (gvarp == &p_bh) 1733 { 1734 if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, FALSE) != OK) 1735 errmsg = e_invarg; 1736 } 1737 1738 // When 'buftype' is set, check for valid value. 1739 else if (gvarp == &p_bt) 1740 { 1741 if (check_opt_strings(curbuf->b_p_bt, p_buftype_values, FALSE) != OK) 1742 errmsg = e_invarg; 1743 else 1744 { 1745 if (curwin->w_status_height) 1746 { 1747 curwin->w_redr_status = TRUE; 1748 redraw_later(VALID); 1749 } 1750 curbuf->b_help = (curbuf->b_p_bt[0] == 'h'); 1751 #ifdef FEAT_TITLE 1752 redraw_titles(); 1753 #endif 1754 } 1755 } 1756 1757 #ifdef FEAT_STL_OPT 1758 // 'statusline' or 'rulerformat' 1759 else if (gvarp == &p_stl || varp == &p_ruf) 1760 { 1761 int wid; 1762 1763 if (varp == &p_ruf) // reset ru_wid first 1764 ru_wid = 0; 1765 s = *varp; 1766 if (varp == &p_ruf && *s == '%') 1767 { 1768 // set ru_wid if 'ruf' starts with "%99(" 1769 if (*++s == '-') // ignore a '-' 1770 s++; 1771 wid = getdigits(&s); 1772 if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) 1773 ru_wid = wid; 1774 else 1775 errmsg = check_stl_option(p_ruf); 1776 } 1777 // check 'statusline' only if it doesn't start with "%!" 1778 else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') 1779 errmsg = check_stl_option(s); 1780 if (varp == &p_ruf && errmsg == NULL) 1781 comp_col(); 1782 } 1783 #endif 1784 1785 // check if it is a valid value for 'complete' -- Acevedo 1786 else if (gvarp == &p_cpt) 1787 { 1788 for (s = *varp; *s;) 1789 { 1790 while (*s == ',' || *s == ' ') 1791 s++; 1792 if (!*s) 1793 break; 1794 if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL) 1795 { 1796 errmsg = illegal_char(errbuf, *s); 1797 break; 1798 } 1799 if (*++s != NUL && *s != ',' && *s != ' ') 1800 { 1801 if (s[-1] == 'k' || s[-1] == 's') 1802 { 1803 // skip optional filename after 'k' and 's' 1804 while (*s && *s != ',' && *s != ' ') 1805 { 1806 if (*s == '\\' && s[1] != NUL) 1807 ++s; 1808 ++s; 1809 } 1810 } 1811 else 1812 { 1813 if (errbuf != NULL) 1814 { 1815 sprintf((char *)errbuf, 1816 _("E535: Illegal character after <%c>"), 1817 *--s); 1818 errmsg = errbuf; 1819 } 1820 else 1821 errmsg = ""; 1822 break; 1823 } 1824 } 1825 } 1826 } 1827 1828 // 'completeopt' 1829 else if (varp == &p_cot) 1830 { 1831 if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK) 1832 errmsg = e_invarg; 1833 else 1834 completeopt_was_set(); 1835 } 1836 1837 #ifdef BACKSLASH_IN_FILENAME 1838 // 'completeslash' 1839 else if (gvarp == &p_csl) 1840 { 1841 if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK 1842 || check_opt_strings(curbuf->b_p_csl, p_csl_values, FALSE) != OK) 1843 errmsg = e_invarg; 1844 } 1845 #endif 1846 1847 #ifdef FEAT_SIGNS 1848 // 'signcolumn' 1849 else if (varp == &curwin->w_p_scl) 1850 { 1851 if (check_opt_strings(*varp, p_scl_values, FALSE) != OK) 1852 errmsg = e_invarg; 1853 // When changing the 'signcolumn' to or from 'number', recompute the 1854 // width of the number column if 'number' or 'relativenumber' is set. 1855 if (((*oldval == 'n' && *(oldval + 1) == 'u') 1856 || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) =='u')) 1857 && (curwin->w_p_nu || curwin->w_p_rnu)) 1858 curwin->w_nrwidth_line_count = 0; 1859 } 1860 #endif 1861 1862 1863 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) 1864 // 'toolbar' 1865 else if (varp == &p_toolbar) 1866 { 1867 if (opt_strings_flags(p_toolbar, p_toolbar_values, 1868 &toolbar_flags, TRUE) != OK) 1869 errmsg = e_invarg; 1870 else 1871 { 1872 out_flush(); 1873 gui_mch_show_toolbar((toolbar_flags & 1874 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0); 1875 } 1876 } 1877 #endif 1878 1879 #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_GTK) 1880 // 'toolbariconsize': GTK+ 2 only 1881 else if (varp == &p_tbis) 1882 { 1883 if (opt_strings_flags(p_tbis, p_tbis_values, &tbis_flags, FALSE) != OK) 1884 errmsg = e_invarg; 1885 else 1886 { 1887 out_flush(); 1888 gui_mch_show_toolbar((toolbar_flags & 1889 (TOOLBAR_TEXT | TOOLBAR_ICONS)) != 0); 1890 } 1891 } 1892 #endif 1893 1894 // 'pastetoggle': translate key codes like in a mapping 1895 else if (varp == &p_pt) 1896 { 1897 if (*p_pt) 1898 { 1899 (void)replace_termcodes(p_pt, &p, 1900 REPTERM_FROM_PART | REPTERM_DO_LT, NULL); 1901 if (p != NULL) 1902 { 1903 if (new_value_alloced) 1904 free_string_option(p_pt); 1905 p_pt = p; 1906 new_value_alloced = TRUE; 1907 } 1908 } 1909 } 1910 1911 // 'backspace' 1912 else if (varp == &p_bs) 1913 { 1914 if (VIM_ISDIGIT(*p_bs)) 1915 { 1916 if (*p_bs > '3' || p_bs[1] != NUL) 1917 errmsg = e_invarg; 1918 } 1919 else if (check_opt_strings(p_bs, p_bs_values, TRUE) != OK) 1920 errmsg = e_invarg; 1921 } 1922 else if (varp == &p_bo) 1923 { 1924 if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, TRUE) != OK) 1925 errmsg = e_invarg; 1926 } 1927 1928 // 'tagcase' 1929 else if (gvarp == &p_tc) 1930 { 1931 unsigned int *flags; 1932 1933 if (opt_flags & OPT_LOCAL) 1934 { 1935 p = curbuf->b_p_tc; 1936 flags = &curbuf->b_tc_flags; 1937 } 1938 else 1939 { 1940 p = p_tc; 1941 flags = &tc_flags; 1942 } 1943 1944 if ((opt_flags & OPT_LOCAL) && *p == NUL) 1945 // make the local value empty: use the global value 1946 *flags = 0; 1947 else if (*p == NUL 1948 || opt_strings_flags(p, p_tc_values, flags, FALSE) != OK) 1949 errmsg = e_invarg; 1950 } 1951 1952 // 'casemap' 1953 else if (varp == &p_cmp) 1954 { 1955 if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, TRUE) != OK) 1956 errmsg = e_invarg; 1957 } 1958 1959 #ifdef FEAT_DIFF 1960 // 'diffopt' 1961 else if (varp == &p_dip) 1962 { 1963 if (diffopt_changed() == FAIL) 1964 errmsg = e_invarg; 1965 } 1966 #endif 1967 1968 #ifdef FEAT_FOLDING 1969 // 'foldmethod' 1970 else if (gvarp == &curwin->w_allbuf_opt.wo_fdm) 1971 { 1972 if (check_opt_strings(*varp, p_fdm_values, FALSE) != OK 1973 || *curwin->w_p_fdm == NUL) 1974 errmsg = e_invarg; 1975 else 1976 { 1977 foldUpdateAll(curwin); 1978 if (foldmethodIsDiff(curwin)) 1979 newFoldLevel(); 1980 } 1981 } 1982 # ifdef FEAT_EVAL 1983 // 'foldexpr' 1984 else if (varp == &curwin->w_p_fde) 1985 { 1986 if (foldmethodIsExpr(curwin)) 1987 foldUpdateAll(curwin); 1988 } 1989 # endif 1990 // 'foldmarker' 1991 else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) 1992 { 1993 p = vim_strchr(*varp, ','); 1994 if (p == NULL) 1995 errmsg = N_("E536: comma required"); 1996 else if (p == *varp || p[1] == NUL) 1997 errmsg = e_invarg; 1998 else if (foldmethodIsMarker(curwin)) 1999 foldUpdateAll(curwin); 2000 } 2001 // 'commentstring' 2002 else if (gvarp == &p_cms) 2003 { 2004 if (**varp != NUL && strstr((char *)*varp, "%s") == NULL) 2005 errmsg = N_("E537: 'commentstring' must be empty or contain %s"); 2006 } 2007 // 'foldopen' 2008 else if (varp == &p_fdo) 2009 { 2010 if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, TRUE) != OK) 2011 errmsg = e_invarg; 2012 } 2013 // 'foldclose' 2014 else if (varp == &p_fcl) 2015 { 2016 if (check_opt_strings(p_fcl, p_fcl_values, TRUE) != OK) 2017 errmsg = e_invarg; 2018 } 2019 // 'foldignore' 2020 else if (gvarp == &curwin->w_allbuf_opt.wo_fdi) 2021 { 2022 if (foldmethodIsIndent(curwin)) 2023 foldUpdateAll(curwin); 2024 } 2025 #endif 2026 2027 // 'virtualedit' 2028 else if (varp == &p_ve) 2029 { 2030 if (opt_strings_flags(p_ve, p_ve_values, &ve_flags, TRUE) != OK) 2031 errmsg = e_invarg; 2032 else if (STRCMP(p_ve, oldval) != 0) 2033 { 2034 // Recompute cursor position in case the new 've' setting 2035 // changes something. 2036 validate_virtcol(); 2037 coladvance(curwin->w_virtcol); 2038 } 2039 } 2040 2041 #if defined(FEAT_CSCOPE) && defined(FEAT_QUICKFIX) 2042 else if (varp == &p_csqf) 2043 { 2044 if (p_csqf != NULL) 2045 { 2046 p = p_csqf; 2047 while (*p != NUL) 2048 { 2049 if (vim_strchr((char_u *)CSQF_CMDS, *p) == NULL 2050 || p[1] == NUL 2051 || vim_strchr((char_u *)CSQF_FLAGS, p[1]) == NULL 2052 || (p[2] != NUL && p[2] != ',')) 2053 { 2054 errmsg = e_invarg; 2055 break; 2056 } 2057 else if (p[2] == NUL) 2058 break; 2059 else 2060 p += 3; 2061 } 2062 } 2063 } 2064 #endif 2065 2066 #ifdef FEAT_CINDENT 2067 // 'cinoptions' 2068 else if (gvarp == &p_cino) 2069 { 2070 // TODO: recognize errors 2071 parse_cino(curbuf); 2072 } 2073 #endif 2074 2075 #if defined(FEAT_RENDER_OPTIONS) 2076 // 'renderoptions' 2077 else if (varp == &p_rop) 2078 { 2079 if (!gui_mch_set_rendering_options(p_rop)) 2080 errmsg = e_invarg; 2081 } 2082 #endif 2083 2084 else if (gvarp == &p_ft) 2085 { 2086 if (!valid_filetype(*varp)) 2087 errmsg = e_invarg; 2088 else 2089 { 2090 value_changed = STRCMP(oldval, *varp) != 0; 2091 2092 // Since we check the value, there is no need to set P_INSECURE, 2093 // even when the value comes from a modeline. 2094 *value_checked = TRUE; 2095 } 2096 } 2097 2098 #ifdef FEAT_SYN_HL 2099 else if (gvarp == &p_syn) 2100 { 2101 if (!valid_filetype(*varp)) 2102 errmsg = e_invarg; 2103 else 2104 { 2105 value_changed = STRCMP(oldval, *varp) != 0; 2106 2107 // Since we check the value, there is no need to set P_INSECURE, 2108 // even when the value comes from a modeline. 2109 *value_checked = TRUE; 2110 } 2111 } 2112 #endif 2113 2114 #ifdef FEAT_TERMINAL 2115 // 'termwinkey' 2116 else if (varp == &curwin->w_p_twk) 2117 { 2118 if (*curwin->w_p_twk != NUL 2119 && string_to_key(curwin->w_p_twk, TRUE) == 0) 2120 errmsg = e_invarg; 2121 } 2122 // 'termwinsize' 2123 else if (varp == &curwin->w_p_tws) 2124 { 2125 if (*curwin->w_p_tws != NUL) 2126 { 2127 p = skipdigits(curwin->w_p_tws); 2128 if (p == curwin->w_p_tws 2129 || (*p != 'x' && *p != '*') 2130 || *skipdigits(p + 1) != NUL) 2131 errmsg = e_invarg; 2132 } 2133 } 2134 // 'wincolor' 2135 else if (varp == &curwin->w_p_wcr) 2136 { 2137 if (curwin->w_buffer->b_term != NULL) 2138 term_update_colors(); 2139 } 2140 # if defined(MSWIN) 2141 // 'termwintype' 2142 else if (varp == &p_twt) 2143 { 2144 if (check_opt_strings(*varp, p_twt_values, FALSE) != OK) 2145 errmsg = e_invarg; 2146 } 2147 # endif 2148 #endif 2149 2150 #ifdef FEAT_VARTABS 2151 // 'varsofttabstop' 2152 else if (varp == &(curbuf->b_p_vsts)) 2153 { 2154 char_u *cp; 2155 2156 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) 2157 { 2158 if (curbuf->b_p_vsts_array) 2159 { 2160 vim_free(curbuf->b_p_vsts_array); 2161 curbuf->b_p_vsts_array = 0; 2162 } 2163 } 2164 else 2165 { 2166 for (cp = *varp; *cp; ++cp) 2167 { 2168 if (vim_isdigit(*cp)) 2169 continue; 2170 if (*cp == ',' && cp > *varp && *(cp-1) != ',') 2171 continue; 2172 errmsg = e_invarg; 2173 break; 2174 } 2175 if (errmsg == NULL) 2176 { 2177 int *oldarray = curbuf->b_p_vsts_array; 2178 if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) 2179 { 2180 if (oldarray) 2181 vim_free(oldarray); 2182 } 2183 else 2184 errmsg = e_invarg; 2185 } 2186 } 2187 } 2188 2189 // 'vartabstop' 2190 else if (varp == &(curbuf->b_p_vts)) 2191 { 2192 char_u *cp; 2193 2194 if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) 2195 { 2196 if (curbuf->b_p_vts_array) 2197 { 2198 vim_free(curbuf->b_p_vts_array); 2199 curbuf->b_p_vts_array = NULL; 2200 } 2201 } 2202 else 2203 { 2204 for (cp = *varp; *cp; ++cp) 2205 { 2206 if (vim_isdigit(*cp)) 2207 continue; 2208 if (*cp == ',' && cp > *varp && *(cp-1) != ',') 2209 continue; 2210 errmsg = e_invarg; 2211 break; 2212 } 2213 if (errmsg == NULL) 2214 { 2215 int *oldarray = curbuf->b_p_vts_array; 2216 2217 if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) 2218 { 2219 vim_free(oldarray); 2220 #ifdef FEAT_FOLDING 2221 if (foldmethodIsIndent(curwin)) 2222 foldUpdateAll(curwin); 2223 #endif 2224 } 2225 else 2226 errmsg = e_invarg; 2227 } 2228 } 2229 } 2230 #endif 2231 2232 #ifdef FEAT_PROP_POPUP 2233 // 'previewpopup' 2234 else if (varp == &p_pvp) 2235 { 2236 if (parse_previewpopup(NULL) == FAIL) 2237 errmsg = e_invarg; 2238 } 2239 # ifdef FEAT_QUICKFIX 2240 // 'completepopup' 2241 else if (varp == &p_cpp) 2242 { 2243 if (parse_completepopup(NULL) == FAIL) 2244 errmsg = e_invarg; 2245 } 2246 # endif 2247 #endif 2248 2249 // Options that are a list of flags. 2250 else 2251 { 2252 p = NULL; 2253 if (varp == &p_ww) // 'whichwrap' 2254 p = (char_u *)WW_ALL; 2255 if (varp == &p_shm) // 'shortmess' 2256 p = (char_u *)SHM_ALL; 2257 else if (varp == &(p_cpo)) // 'cpoptions' 2258 p = (char_u *)CPO_ALL; 2259 else if (varp == &(curbuf->b_p_fo)) // 'formatoptions' 2260 p = (char_u *)FO_ALL; 2261 #ifdef FEAT_CONCEAL 2262 else if (varp == &curwin->w_p_cocu) // 'concealcursor' 2263 p = (char_u *)COCU_ALL; 2264 #endif 2265 else if (varp == &p_mouse) // 'mouse' 2266 { 2267 p = (char_u *)MOUSE_ALL; 2268 } 2269 #if defined(FEAT_GUI) 2270 else if (varp == &p_go) // 'guioptions' 2271 p = (char_u *)GO_ALL; 2272 #endif 2273 if (p != NULL) 2274 { 2275 for (s = *varp; *s; ++s) 2276 if (vim_strchr(p, *s) == NULL) 2277 { 2278 errmsg = illegal_char(errbuf, *s); 2279 break; 2280 } 2281 } 2282 } 2283 2284 // If error detected, restore the previous value. 2285 if (errmsg != NULL) 2286 { 2287 if (new_value_alloced) 2288 free_string_option(*varp); 2289 *varp = oldval; 2290 // When resetting some values, need to act on it. 2291 if (did_chartab) 2292 (void)init_chartab(); 2293 if (varp == &p_hl) 2294 (void)highlight_changed(); 2295 } 2296 else 2297 { 2298 #ifdef FEAT_EVAL 2299 // Remember where the option was set. 2300 set_option_sctx_idx(opt_idx, opt_flags, current_sctx); 2301 #endif 2302 // Free string options that are in allocated memory. 2303 // Use "free_oldval", because recursiveness may change the flags under 2304 // our fingers (esp. init_highlight()). 2305 if (free_oldval) 2306 free_string_option(oldval); 2307 if (new_value_alloced) 2308 set_option_flag(opt_idx, P_ALLOCED); 2309 else 2310 clear_option_flag(opt_idx, P_ALLOCED); 2311 2312 if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 2313 && is_global_local_option(opt_idx)) 2314 { 2315 // global option with local value set to use global value; free 2316 // the local value and make it empty 2317 p = get_option_varp_scope(opt_idx, OPT_LOCAL); 2318 free_string_option(*(char_u **)p); 2319 *(char_u **)p = empty_option; 2320 } 2321 2322 // May set global value for local option. 2323 else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) 2324 set_string_option_global(opt_idx, varp); 2325 2326 // Trigger the autocommand only after setting the flags. 2327 #ifdef FEAT_SYN_HL 2328 // When 'syntax' is set, load the syntax of that name 2329 if (varp == &(curbuf->b_p_syn)) 2330 { 2331 static int syn_recursive = 0; 2332 2333 ++syn_recursive; 2334 // Only pass TRUE for "force" when the value changed or not used 2335 // recursively, to avoid endless recurrence. 2336 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, 2337 value_changed || syn_recursive == 1, curbuf); 2338 curbuf->b_flags |= BF_SYN_SET; 2339 --syn_recursive; 2340 } 2341 #endif 2342 else if (varp == &(curbuf->b_p_ft)) 2343 { 2344 // 'filetype' is set, trigger the FileType autocommand. 2345 // Skip this when called from a modeline and the filetype was 2346 // already set to this value. 2347 if (!(opt_flags & OPT_MODELINE) || value_changed) 2348 { 2349 static int ft_recursive = 0; 2350 int secure_save = secure; 2351 2352 // Reset the secure flag, since the value of 'filetype' has 2353 // been checked to be safe. 2354 secure = 0; 2355 2356 ++ft_recursive; 2357 did_filetype = TRUE; 2358 // Only pass TRUE for "force" when the value changed or not 2359 // used recursively, to avoid endless recurrence. 2360 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, 2361 value_changed || ft_recursive == 1, curbuf); 2362 --ft_recursive; 2363 // Just in case the old "curbuf" is now invalid. 2364 if (varp != &(curbuf->b_p_ft)) 2365 varp = NULL; 2366 2367 secure = secure_save; 2368 } 2369 } 2370 #ifdef FEAT_SPELL 2371 if (varp == &(curwin->w_s->b_p_spl)) 2372 { 2373 char_u fname[200]; 2374 char_u *q = curwin->w_s->b_p_spl; 2375 2376 // Skip the first name if it is "cjk". 2377 if (STRNCMP(q, "cjk,", 4) == 0) 2378 q += 4; 2379 2380 // Source the spell/LANG.vim in 'runtimepath'. 2381 // They could set 'spellcapcheck' depending on the language. 2382 // Use the first name in 'spelllang' up to '_region' or 2383 // '.encoding'. 2384 for (p = q; *p != NUL; ++p) 2385 if (!ASCII_ISALNUM(*p) && *p != '-') 2386 break; 2387 if (p > q) 2388 { 2389 vim_snprintf((char *)fname, 200, "spell/%.*s.vim", 2390 (int)(p - q), q); 2391 source_runtime(fname, DIP_ALL); 2392 } 2393 } 2394 #endif 2395 } 2396 2397 if (varp == &p_mouse) 2398 { 2399 if (*p_mouse == NUL) 2400 mch_setmouse(FALSE); // switch mouse off 2401 else 2402 setmouse(); // in case 'mouse' changed 2403 } 2404 2405 if (curwin->w_curswant != MAXCOL 2406 && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) 2407 curwin->w_set_curswant = TRUE; 2408 2409 #ifdef FEAT_GUI 2410 // check redraw when it's not a GUI option or the GUI is active. 2411 if (!redraw_gui_only || gui.in_use) 2412 #endif 2413 check_redraw(get_option_flags(opt_idx)); 2414 2415 #if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS) 2416 if (did_swaptcap) 2417 { 2418 set_termname((char_u *)"win32"); 2419 init_highlight(TRUE, FALSE); 2420 } 2421 #endif 2422 2423 return errmsg; 2424 } 2425 2426 /* 2427 * Check an option that can be a range of string values. 2428 * 2429 * Return OK for correct value, FAIL otherwise. 2430 * Empty is always OK. 2431 */ 2432 static int 2433 check_opt_strings( 2434 char_u *val, 2435 char **values, 2436 int list) // when TRUE: accept a list of values 2437 { 2438 return opt_strings_flags(val, values, NULL, list); 2439 } 2440 2441 /* 2442 * Handle an option that can be a range of string values. 2443 * Set a flag in "*flagp" for each string present. 2444 * 2445 * Return OK for correct value, FAIL otherwise. 2446 * Empty is always OK. 2447 */ 2448 static int 2449 opt_strings_flags( 2450 char_u *val, // new value 2451 char **values, // array of valid string values 2452 unsigned *flagp, 2453 int list) // when TRUE: accept a list of values 2454 { 2455 int i; 2456 int len; 2457 unsigned new_flags = 0; 2458 2459 while (*val) 2460 { 2461 for (i = 0; ; ++i) 2462 { 2463 if (values[i] == NULL) // val not found in values[] 2464 return FAIL; 2465 2466 len = (int)STRLEN(values[i]); 2467 if (STRNCMP(values[i], val, len) == 0 2468 && ((list && val[len] == ',') || val[len] == NUL)) 2469 { 2470 val += len + (val[len] == ','); 2471 new_flags |= (1 << i); 2472 break; // check next item in val list 2473 } 2474 } 2475 } 2476 if (flagp != NULL) 2477 *flagp = new_flags; 2478 2479 return OK; 2480 } 2481 2482 /* 2483 * return OK if "p" is a valid fileformat name, FAIL otherwise. 2484 */ 2485 int 2486 check_ff_value(char_u *p) 2487 { 2488 return check_opt_strings(p, p_ff_values, FALSE); 2489 } 2490