# HG changeset patch # User Christian Brabandt # Date 1538485207 -7200 # Node ID cf4d6489c9ebf1fbeb09d0c3c8067721fdcafea3 # Parent 2cc6cfa2b80425bbc794e30f3dd0e7238b92d204 patch 8.1.0445: setting 'term' does not store location for termcap options commit https://github.com/vim/vim/commit/35bc7d6c52f516b60d683bf9f0f57266d86e25b9 Author: Bram Moolenaar Date: Tue Oct 2 14:45:10 2018 +0200 patch 8.1.0445: setting 'term' does not store location for termcap options Problem: Setting 'term' does not store location for termcap options. Solution: Set the script context for termcap options that are changed when 'term' is set. diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -1755,12 +1755,12 @@ static struct vimoption options[] = {"langmap", "lmap", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP|P_SECURE, #ifdef FEAT_LANGMAP (char_u *)&p_langmap, PV_NONE, - {(char_u *)"", /* unmatched } */ -#else - (char_u *)NULL, PV_NONE, - {(char_u *)NULL, -#endif - (char_u *)0L} SCTX_INIT}, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +#endif + SCTX_INIT}, {"langmenu", "lm", P_STRING|P_VI_DEF|P_NFNAME, #if defined(FEAT_MENU) && defined(FEAT_MULTI_LANG) (char_u *)&p_lm, PV_NONE, @@ -5790,20 +5790,32 @@ check_string_option(char_u **pp) } /* - * Mark a terminal option as allocated, found by a pointer into term_strings[]. - */ - void -set_term_option_alloced(char_u **p) -{ - int opt_idx; + * Return the option index found by a pointer into term_strings[]. + * Return -1 if not found. + */ + int +get_term_opt_idx(char_u **p) +{ + int opt_idx; for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++) if (options[opt_idx].var == (char_u *)p) - { - options[opt_idx].flags |= P_ALLOCED; - return; - } - return; /* cannot happen: didn't find it! */ + return opt_idx; + return -1; // cannot happen: didn't find it! +} + +/* + * Mark a terminal option as allocated, found by a pointer into term_strings[]. + * Return the option index or -1 if not found. + */ + int +set_term_option_alloced(char_u **p) +{ + int opt_idx = get_term_opt_idx(p); + + if (opt_idx >= 0) + options[opt_idx].flags |= P_ALLOCED; + return opt_idx; } #if defined(FEAT_EVAL) || defined(PROTO) @@ -8237,6 +8249,32 @@ set_option_sctx_idx(int opt_idx, int opt curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx; } } + +/* + * Set the script_ctx for a termcap option. + * "name" must be the two character code, e.g. "RV". + * When "name" is NULL use "opt_idx". + */ + void +set_term_option_sctx_idx(char *name, int opt_idx) +{ + char_u buf[5]; + int idx; + + if (name == NULL) + idx = opt_idx; + else + { + buf[0] = 't'; + buf[1] = '_'; + buf[2] = name[0]; + buf[3] = name[1]; + buf[4] = 0; + idx = findoption(buf); + } + if (idx >= 0) + set_option_sctx_idx(idx, OPT_GLOBAL, current_sctx); +} #endif /* @@ -10445,7 +10483,7 @@ free_termoptions(void) { struct vimoption *p; - for (p = &options[0]; p->fullname != NULL; p++) + for (p = options; p->fullname != NULL; p++) if (istermoption(p)) { if (p->flags & P_ALLOCED) @@ -10455,6 +10493,10 @@ free_termoptions(void) *(char_u **)(p->var) = empty_option; p->def_val[VI_DEFAULT] = empty_option; p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED); +#ifdef FEAT_EVAL + // remember where the option was cleared + set_option_sctx_idx((int)(p - options), OPT_GLOBAL, current_sctx); +#endif } clear_termcodes(); } diff --git a/src/proto/option.pro b/src/proto/option.pro --- a/src/proto/option.pro +++ b/src/proto/option.pro @@ -17,11 +17,13 @@ void check_options(void); void check_buf_options(buf_T *buf); void free_string_option(char_u *p); void clear_string_option(char_u **pp); -void set_term_option_alloced(char_u **p); +int get_term_opt_idx(char_u **p); +int set_term_option_alloced(char_u **p); int was_set_insecurely(char_u *opt, int opt_flags); void set_string_option_direct(char_u *name, int opt_idx, char_u *val, int opt_flags, int set_sid); char_u *check_colorcolumn(win_T *wp); char_u *check_stl_option(char_u *s); +void set_term_option_sctx_idx(char *name, int opt_idx); int get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags); int get_option_value_strict(char_u *name, long *numval, char_u **stringval, int opt_type, void *from); char_u *option_iter_next(void **option, int opt_type); diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -1471,6 +1471,9 @@ parse_builtin_tcap(char_u *term) if (term_strings[p->bt_entry] == NULL || term_strings[p->bt_entry] == empty_option) { +#ifdef FEAT_EVAL + int opt_idx = -1; +#endif /* 8bit terminal: use CSI instead of [ */ if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0) { @@ -1486,11 +1489,23 @@ parse_builtin_tcap(char_u *term) STRMOVE(t + 1, t + 2); } term_strings[p->bt_entry] = s; - set_term_option_alloced(&term_strings[p->bt_entry]); +#ifdef FEAT_EVAL + opt_idx = +#endif + set_term_option_alloced( + &term_strings[p->bt_entry]); } } else + { term_strings[p->bt_entry] = (char_u *)p->bt_string; +#ifdef FEAT_EVAL + opt_idx = get_term_opt_idx(&term_strings[p->bt_entry]); +#endif + } +#ifdef FEAT_EVAL + set_term_option_sctx_idx(NULL, opt_idx); +#endif } } else @@ -1616,7 +1631,12 @@ get_term_entries(int *height, int *width { if (TERM_STR(string_names[i].dest) == NULL || TERM_STR(string_names[i].dest) == empty_option) + { TERM_STR(string_names[i].dest) = TGETSTR(string_names[i].name, &tp); +#ifdef FEAT_EVAL + set_term_option_sctx_idx(string_names[i].name, -1); +#endif + } } /* tgetflag() returns 1 if the flag is present, 0 if not and @@ -1658,7 +1678,12 @@ get_term_entries(int *height, int *width * Get number of colors (if not done already). */ if (TERM_STR(KS_CCO) == NULL || TERM_STR(KS_CCO) == empty_option) + { set_color_count(tgetnum("Co")); +#ifdef FEAT_EVAL + set_term_option_sctx_idx("Co", -1); +#endif + } # ifndef hpux BC = (char *)TGETSTR("bc", &tp); diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -270,6 +270,18 @@ func Test_set_errors() call assert_fails('set t_foo=', 'E846:') endfunc +" Must be executed before other tests that set 'term'. +func Test_000_term_option_verbose() + let verb_cm = execute('verbose set t_cm') + call assert_notmatch('Last set from', verb_cm) + + let term_save = &term + set term=ansi + let verb_cm = execute('verbose set t_cm') + call assert_match('Last set from.*test_options.vim', verb_cm) + let &term = term_save +endfunc + func Test_set_ttytype() if !has('gui_running') && has('unix') " Setting 'ttytype' used to cause a double-free when exiting vim and diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -793,6 +793,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 445, +/**/ 444, /**/ 443,