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