changeset 14867:cf4d6489c9eb v8.1.0445

patch 8.1.0445: setting 'term' does not store location for termcap options commit https://github.com/vim/vim/commit/35bc7d6c52f516b60d683bf9f0f57266d86e25b9 Author: Bram Moolenaar <Bram@vim.org> 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.
author Christian Brabandt <cb@256bit.org>
date Tue, 02 Oct 2018 15:00:07 +0200
parents 2cc6cfa2b804
children 55aa5975227a
files src/option.c src/proto/option.pro src/term.c src/testdir/test_options.vim src/version.c
diffstat 5 files changed, 103 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- 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();
 }
--- 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);
--- 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 <Esc>[ */
 		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);
--- 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
--- 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,