changeset 634:1c586ee8dd45 v7.0183

updated for version 7.0183
author vimboss
date Fri, 20 Jan 2006 23:10:18 +0000
parents 7437be625546
children 23a639c430c5
files runtime/doc/eval.txt runtime/doc/options.txt runtime/doc/tags runtime/doc/todo.txt runtime/doc/version7.txt src/edit.c src/eval.c src/ex_cmds.c src/ex_getln.c src/fold.c src/globals.h src/gui_beval.c src/if_python.c src/misc1.c src/option.c src/proto/eval.pro src/quickfix.c src/undo.c src/version.h
diffstat 19 files changed, 452 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Jan 13
+*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Jan 20
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -28,6 +28,7 @@ 8.  Exception handling		|exception-handl
 9.  Examples			|eval-examples|
 10. No +eval feature		|no-eval-feature|
 11. The sandbox			|eval-sandbox|
+12. Textlock			|textlock|
 
 {Vi does not have any of these commands}
 
@@ -6830,5 +6831,33 @@ This is not guaranteed 100% secure, but 
 			option that may have been set from a modeline, e.g.
 			'foldexpr'.
 
+							*sandbox-option*
+A few options contain an expression.  When this expression is evaluated it may
+have to be done in the sandbox to avoid trouble.  But the sandbox is
+restrictive, thus this only happens when the option was set from an insecure
+location.  Insecure in this context are:
+- sourcing a .vimrc or .exrc in the current directlry
+- while executing in the sandbox
+- value coming from a modeline
+
+Note that when in the sandbox and saving an option value and restoring it, the
+option will still be marked as it was set in the sandbox.
+
+==============================================================================
+12. Textlock							*textlock*
+
+In a few situations it is not allowed to change the text in the buffer, jump
+to another window and some other things that might confuse or break what Vim
+is currently doing.  This mostly applies to things that happen when Vim is
+actually doing something else.  For example, evaluating the 'balloonexpr' may
+happen any moment the mouse cursor is resting at some position.
+
+This is not allowed when the textlock is active:
+	- changing the buffer text
+	- jumping to another buffer or window
+	- editing another file
+	- closing a window or quitting Vim
+	- etc.
+
 
  vim:tw=78:ts=8:ft=help:norl:
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.0aa.  Last change: 2006 Jan 19
+*options.txt*	For Vim version 7.0aa.  Last change: 2006 Jan 20
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1037,6 +1037,12 @@ A jump table for the options with a shor
 	Vim does not try to send a message to an external debugger (Netbeans
 	or Sun Workshop).
 
+	The expression may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'balloonexpr' |textlock|.
+
 	To check whether line breaks in the balloon text work use this check: >
 		if has("balloon_multiline")
 <
@@ -2771,8 +2777,13 @@ A jump table for the options with a shor
 			{not available when compiled without the |+folding|
 			or |+eval| feature}
 	The expression used for when 'foldmethod' is "expr".  It is evaluated
-	for each line to obtain its fold level.  See |fold-expr|.  Also see
-	|eval-sandbox|.
+	for each line to obtain its fold level.  See |fold-expr|.
+	
+	The expression may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'foldexpr' |textlock|.
 
 						*'foldignore'* *'fdi'*
 'foldignore' 'fdi'	string (default: "#")
@@ -2904,6 +2915,12 @@ A jump table for the options with a shor
 	An expression which is used to specify the text displayed for a closed
 	fold.  See |fold-foldtext|.
 
+	The expression may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'foldtext' |textlock|.
+
 					*'formatoptions'* *'fo'*
 'formatoptions' 'fo'	string (Vim default: "tcq", Vi default: "vt")
 			local to buffer
@@ -3696,11 +3713,17 @@ A jump table for the options with a shor
 	option to a file name.  Mostly useful to change "." to "/" for Java: >
 		:set includeexpr=substitute(v:fname,'\\.','/','g')
 <	The "v:fname" variable will be set to the file name that was detected.
-	Evaluated in the |sandbox|.
+
 	Also used for the |gf| command if an unmodified file name can't be
 	found.  Allows doing "gf" on the name after an 'include' statement.
 	Also used for |<cfile>|.
 
+	The expression may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'includeexpr' |textlock|.
+
 				 *'incsearch'* *'is'* *'noincsearch'* *'nois'*
 'incsearch' 'is'	boolean	(default off)
 			global
@@ -3746,9 +3769,16 @@ A jump table for the options with a shor
 		:set indentexpr=GetMyIndent()
 <	Error messages will be suppressed, unless the 'debug' option contains
 	"msg".
-	See |indent-expression|.  Also see |eval-sandbox|.
+	See |indent-expression|.
 	NOTE: This option is made empty when 'compatible' is set.
 
+	The expression may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'indentexpr' |textlock|.
+
+
 						*'indentkeys'* *'indk'*
 'indentkeys' 'indk'	string	(default "0{,0},:,0#,!^F,o,O,e")
 			local to buffer
@@ -6084,7 +6114,13 @@ A jump table for the options with a shor
 	temporarily to that of the window (and buffer) whose statusline is
 	currently being drawn.  The expression will evaluate in this context.
 	The variable "actual_curbuf" is set to the 'bufnr()' number of the
-	real current buffer.  The expression is evaluated in the |sandbox|.
+	real current buffer.
+
+	The 'statusline' option may be evaluated in the |sandbox|, see
+	|sandbox-option|.
+
+	It is not allowed to change text or jump to another window while
+	evaluating 'statusline' |textlock|.
 
 	If the statusline is not updated when you want it (e.g., after setting
 	a variable that's used in an expression), you can force an update by
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -5349,6 +5349,7 @@ hebrew	hebrew.txt	/*hebrew*
 hebrew.txt	hebrew.txt	/*hebrew.txt*
 help	various.txt	/*help*
 help-context	help.txt	/*help-context*
+help-tags	tags	1
 help-translated	various.txt	/*help-translated*
 help-xterm-window	various.txt	/*help-xterm-window*
 help.txt	help.txt	/*help.txt*
@@ -6404,6 +6405,7 @@ s:netrw_line	pi_netrw.txt	/*s:netrw_line
 s:var	eval.txt	/*s:var*
 s<CR>	change.txt	/*s<CR>*
 sandbox	eval.txt	/*sandbox*
+sandbox-option	eval.txt	/*sandbox-option*
 save-file	editing.txt	/*save-file*
 save-settings	starting.txt	/*save-settings*
 scheme.vim	syntax.txt	/*scheme.vim*
@@ -6929,6 +6931,7 @@ tex-style	syntax.txt	/*tex-style*
 tex.vim	syntax.txt	/*tex.vim*
 text-objects	motion.txt	/*text-objects*
 text-objects-changed	version5.txt	/*text-objects-changed*
+textlock	eval.txt	/*textlock*
 tf.vim	syntax.txt	/*tf.vim*
 this_session-variable	eval.txt	/*this_session-variable*
 throw-catch	eval.txt	/*throw-catch*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Jan 19
+*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Jan 20
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,20 +30,6 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-Evaluate 'balloonexpr' in the sandbox only when it was set from an unsafe
-place (e.g., modeline)?  Patch from Sumner Hayes, Jan 12.  Also use for other
-options?
-
-":saveas asdf.c" should set 'filetype' to c when it's empty.  Also for ":w
-asdf.c" when it sets the buffer filename.
-
-When ":cclose" is used the buffer is not wiped out and is no longer recognized
-as a quickfix buffer, thus it's not reused either.
-
-Patch to support lists and dicts for the Python interface. (G. Sumner Hayes,
-Jan 12).  Docs in a previous patch.
-Use free_tv() instead of clear_tv() and vim_free().
-
 ccomplete:
 - When using page-up/page-down in menu it sometimes jumps more than a page.
 - When an option is set: In completion mode and the user types (identifier)
@@ -71,9 +57,9 @@ ccomplete:
     Can't reproduce it right now...
 
 spelling:
-- Include script to cleanup a .add file. (Antonio Colombo, Jan 9)
-- suggestions for "macARONI" doesn't include "macaroni", they are all allcap.
-  suggestion for "KG" to "kg" when it's keepcase.
+- Use runtime/cleanadd script to cleanup .add files.  When to invoke it?
+  After deleting a word and some timestamp difference perhaps?
+- suggestion for "KG" to "kg" when it's keepcase.
 - Autocommand event for when a spell file is missing.  Allows making a plugin
   that fetches the file over internet.  Pattern == language.
 - Using KEEPCASE flag still allows all-upper word, docs say it doesn't.
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Jan 19
+*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Jan 20
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -154,6 +154,9 @@ expr".  "-=" and ".=" works in a similar
 With the |:profile| command you can find out where your function or script
 wastes its time.
 
+In the Python interface vim.eval() also handles Dictionaries and Lists.
+|python-eval| (G. Sumner Hayes)
+
 
 Spell checking						*new-spell*
 --------------
@@ -667,6 +670,15 @@ iterative mechanism.  This avoids out-of
 allocated memory, running out of memory can always be detected.  Allows
 matching more complex things, but Vim may seem to hang while doing that.
 
+Previously some options were always evaluated in the |sandbox|.  Now that only
+happens when the option was set from a modeline or in secure mode.  Applies to
+'balloonexpr', 'foldexpr', 'foldtext' and 'includeexpr'. (Sumner Hayes)
+
+Some commands and expressions could have nasty side effects, such as using
+CTRL-R = while editing a search pattern and the expression invokes a function
+that jumps to another window.  The |textlock| has been added to prevent this
+from happening.
+
 ":breakadd here" and ":breakdel here" can be used to set or delete a
 breakpoint at the cursor.
 
@@ -925,6 +937,10 @@ and for supported autocommand events. (Y
 Allow using ":global" in the sandbox, it doesn't do anything harmful by
 itself.
 
+":saveas asdf.c" will set 'filetype' to c when it's empty.  Also for ":w
+asdf.c" when it sets the filename for the buffer.
+
+
 ==============================================================================
 COMPILE TIME CHANGES					*compile-changes-7*
 
@@ -1528,8 +1544,8 @@ string, because it may cause trouble in 
 
 When evaluating an expression for CTRL-R = on the command line it was possible
 to call a function that opens a new window, resulting in errors for
-incremental search, and many other nasty things were possible.  Now set
-"cmdline_busy" and disallow changing the buffer or jumpting to another window
+incremental search, and many other nasty things were possible.  Now use the
+|textlock| to disallow changing the buffer or jumping to another window
 to protect from unexpected behavior.  Same for CTRL-\ e.
 
 "d(" deleted the character under the cursor, while the documentation specified
@@ -1574,4 +1590,10 @@ When expanding a file name for a shell c
 !cmd foo<Tab>" also escape characters that are special for the shell:
 "!;&()<>".
 
+When the name of the buffer was set by a ":r fname" command |cpo-f| no
+autocommands were triggered to notify about the change in the buffer list.
+
+In the quickfix buffer 'bufhidden' was set to "delete", which caused closing
+the quickfix window to leave an unlisted "No Name" buffer behind every time.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/src/edit.c
+++ b/src/edit.c
@@ -291,7 +291,7 @@ edit(cmdchar, startln, count)
 #endif
     /* Don't allow changes in the buffer while editing the cmdline.  The
      * caller of getcmdline() may get confused. */
-    if (cmdline_busy)
+    if (textlock != 0)
     {
 	EMSG(_(e_secure));
 	return FALSE;
--- a/src/eval.c
+++ b/src/eval.c
@@ -420,8 +420,8 @@ static int list_extend __ARGS((list_T	*l
 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
 static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
-static char_u *list2string __ARGS((typval_T *tv));
-static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
+static char_u *list2string __ARGS((typval_T *tv, int copyID));
+static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
 static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
 static void set_ref_in_list __ARGS((list_T *l, int copyID));
 static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
@@ -435,10 +435,10 @@ static dict_T *dict_copy __ARGS((dict_T 
 static int dict_add __ARGS((dict_T *d, dictitem_T *item));
 static long dict_len __ARGS((dict_T *d));
 static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
-static char_u *dict2string __ARGS((typval_T *tv));
+static char_u *dict2string __ARGS((typval_T *tv, int copyID));
 static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
-static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
-static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
+static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
+static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf, int copyID));
 static char_u *string_quote __ARGS((char_u *str, int function));
 static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
 static int find_internal_func __ARGS((char_u *name));
@@ -1175,20 +1175,26 @@ eval_to_string(arg, nextcmd)
 }
 
 /*
- * Call eval_to_string() with "sandbox" set and not using local variables.
+ * Call eval_to_string() without using current local variables and using
+ * textlock.  When "use_sandbox" is TRUE use the sandbox.
  */
     char_u *
-eval_to_string_safe(arg, nextcmd)
+eval_to_string_safe(arg, nextcmd, use_sandbox)
     char_u	*arg;
     char_u	**nextcmd;
+    int		use_sandbox;
 {
     char_u	*retval;
     void	*save_funccalp;
 
     save_funccalp = save_funccal();
-    ++sandbox;
+    if (use_sandbox)
+	++sandbox;
+    ++textlock;
     retval = eval_to_string(arg, nextcmd);
-    --sandbox;
+    if (use_sandbox)
+	--sandbox;
+    --textlock;
     restore_funccal(save_funccalp);
     return retval;
 }
@@ -1566,9 +1572,12 @@ eval_foldexpr(arg, cp)
     typval_T	tv;
     int		retval;
     char_u	*s;
+    int		use_sandbox = was_set_insecurely((char_u *)"foldexpr");
 
     ++emsg_off;
-    ++sandbox;
+    if (use_sandbox)
+	++sandbox;
+    ++textlock;
     *cp = NUL;
     if (eval0(arg, &tv, NULL, TRUE) == FAIL)
 	retval = 0;
@@ -1591,7 +1600,9 @@ eval_foldexpr(arg, cp)
 	clear_tv(&tv);
     }
     --emsg_off;
-    --sandbox;
+    if (use_sandbox)
+	--sandbox;
+    --textlock;
 
     return retval;
 }
@@ -1985,7 +1996,7 @@ list_arg_vars(eap, arg)
 			    int		c;
 			    char_u	*s;
 
-			    s = echo_string(&tv, &tf, numbuf);
+			    s = echo_string(&tv, &tf, numbuf, 0);
 			    c = *arg;
 			    *arg = NUL;
 			    list_one_var_a((char_u *)"",
@@ -5310,6 +5321,18 @@ list_equal(l1, l2, ic)
     return item1 == NULL && item2 == NULL;
 }
 
+#if defined(FEAT_PYTHON) || defined(PROTO)
+/*
+ * Return the dictitem that an entry in a hashtable points to.
+ */
+    dictitem_T *
+dict_lookup(hi)
+    hashitem_T *hi;
+{
+    return HI2DI(hi);
+}
+#endif
+
 /*
  * Return TRUE when two dictionaries have exactly the same key/values.
  */
@@ -5777,8 +5800,9 @@ list_remove(l, item, item2)
  * May return NULL.
  */
     static char_u *
-list2string(tv)
+list2string(tv, copyID)
     typval_T	*tv;
+    int		copyID;
 {
     garray_T	ga;
 
@@ -5786,7 +5810,7 @@ list2string(tv)
 	return NULL;
     ga_init2(&ga, (int)sizeof(char), 80);
     ga_append(&ga, '[');
-    if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
+    if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE, copyID) == FAIL)
     {
 	vim_free(ga.ga_data);
 	return NULL;
@@ -5802,11 +5826,12 @@ list2string(tv)
  * Return FAIL or OK.
  */
     static int
-list_join(gap, l, sep, echo)
+list_join(gap, l, sep, echo, copyID)
     garray_T	*gap;
     list_T	*l;
     char_u	*sep;
     int		echo;
+    int		copyID;
 {
     int		first = TRUE;
     char_u	*tofree;
@@ -5822,9 +5847,9 @@ list_join(gap, l, sep, echo)
 	    ga_concat(gap, sep);
 
 	if (echo)
-	    s = echo_string(&item->li_tv, &tofree, numbuf);
-	else
-	    s = tv2string(&item->li_tv, &tofree, numbuf);
+	    s = echo_string(&item->li_tv, &tofree, numbuf, copyID);
+	else
+	    s = tv2string(&item->li_tv, &tofree, numbuf, copyID);
 	if (s != NULL)
 	    ga_concat(gap, s);
 	vim_free(tofree);
@@ -6355,8 +6380,9 @@ get_dict_number(d, key)
  * May return NULL.
  */
     static char_u *
-dict2string(tv)
+dict2string(tv, copyID)
     typval_T	*tv;
+    int		copyID;
 {
     garray_T	ga;
     int		first = TRUE;
@@ -6391,7 +6417,7 @@ dict2string(tv)
 		vim_free(tofree);
 	    }
 	    ga_concat(&ga, (char_u *)": ");
-	    s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
+	    s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID);
 	    if (s != NULL)
 		ga_concat(&ga, s);
 	    vim_free(tofree);
@@ -6535,13 +6561,15 @@ failret:
  * If the memory is allocated "tofree" is set to it, otherwise NULL.
  * "numbuf" is used for a number.
  * Does not put quotes around strings, as ":echo" displays values.
+ * When "copyID" is not NULL replace recursive lists and dicts with "...".
  * May return NULL;
  */
     static char_u *
-echo_string(tv, tofree, numbuf)
+echo_string(tv, tofree, numbuf, copyID)
     typval_T	*tv;
     char_u	**tofree;
     char_u	*numbuf;
+    int		copyID;
 {
     static int	recurse = 0;
     char_u	*r = NULL;
@@ -6560,19 +6588,51 @@ echo_string(tv, tofree, numbuf)
 	    *tofree = NULL;
 	    r = tv->vval.v_string;
 	    break;
+
 	case VAR_LIST:
-	    *tofree = list2string(tv);
-	    r = *tofree;
-	    break;
+	    if (tv->vval.v_list == NULL)
+	    {
+		*tofree = NULL;
+		r = NULL;
+	    }
+	    else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID)
+	    {
+		*tofree = NULL;
+		r = (char_u *)"[...]";
+	    }
+	    else
+	    {
+		tv->vval.v_list->lv_copyID = copyID;
+		*tofree = list2string(tv, copyID);
+		r = *tofree;
+	    }
+	    break;
+
 	case VAR_DICT:
-	    *tofree = dict2string(tv);
-	    r = *tofree;
-	    break;
+	    if (tv->vval.v_dict == NULL)
+	    {
+		*tofree = NULL;
+		r = NULL;
+	    }
+	    else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID)
+	    {
+		*tofree = NULL;
+		r = (char_u *)"{...}";
+	    }
+	    else
+	    {
+		tv->vval.v_dict->dv_copyID = copyID;
+		*tofree = dict2string(tv, copyID);
+		r = *tofree;
+	    }
+	    break;
+
 	case VAR_STRING:
 	case VAR_NUMBER:
 	    *tofree = NULL;
 	    r = get_tv_string_buf(tv, numbuf);
 	    break;
+
 	default:
 	    EMSG2(_(e_intern2), "echo_string()");
 	    *tofree = NULL;
@@ -6590,10 +6650,11 @@ echo_string(tv, tofree, numbuf)
  * May return NULL;
  */
     static char_u *
-tv2string(tv, tofree, numbuf)
+tv2string(tv, tofree, numbuf, copyID)
     typval_T	*tv;
     char_u	**tofree;
     char_u	*numbuf;
+    int		copyID;
 {
     switch (tv->v_type)
     {
@@ -6610,7 +6671,7 @@ tv2string(tv, tofree, numbuf)
 	default:
 	    EMSG2(_(e_intern2), "tv2string()");
     }
-    return echo_string(tv, tofree, numbuf);
+    return echo_string(tv, tofree, numbuf, copyID);
 }
 
 /*
@@ -11302,7 +11363,7 @@ f_join(argvars, rettv)
     if (sep != NULL)
     {
 	ga_init2(&ga, (int)sizeof(char), 80);
-	list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
+	list_join(&ga, argvars[0].vval.v_list, sep, TRUE, 0);
 	ga_append(&ga, NUL);
 	rettv->vval.v_string = (char_u *)ga.ga_data;
     }
@@ -11695,7 +11756,7 @@ find_some_match(argvars, rettv, type)
 		    break;
 		}
 		vim_free(tofree);
-		str = echo_string(&li->li_tv, &tofree, strbuf);
+		str = echo_string(&li->li_tv, &tofree, strbuf,0);
 		if (str == NULL)
 		    break;
 	    }
@@ -13734,8 +13795,8 @@ item_compare(s1, s2)
     char_u	numbuf1[NUMBUFLEN];
     char_u	numbuf2[NUMBUFLEN];
 
-    p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
-    p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
+    p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
+    p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
     if (item_compare_ic)
 	res = STRICMP(p1, p2);
     else
@@ -14212,7 +14273,7 @@ f_string(argvars, rettv)
     char_u	numbuf[NUMBUFLEN];
 
     rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
+    rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
     if (tofree == NULL)
 	rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
 }
@@ -16407,7 +16468,7 @@ list_one_var(v, prefix)
     char_u	*s;
     char_u	numbuf[NUMBUFLEN];
 
-    s = echo_string(&v->di_tv, &tofree, numbuf);
+    s = echo_string(&v->di_tv, &tofree, numbuf, ++current_copyID);
     list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
 						s == NULL ? (char_u *)"" : s);
     vim_free(tofree);
@@ -16782,7 +16843,7 @@ ex_echo(eap)
 	    }
 	    else if (eap->cmdidx == CMD_echo)
 		msg_puts_attr((char_u *)" ", echo_attr);
-	    p = echo_string(&rettv, &tofree, numbuf);
+	    p = echo_string(&rettv, &tofree, numbuf, ++current_copyID);
 	    if (p != NULL)
 		for ( ; *p != NUL && !got_int; ++p)
 		{
@@ -18499,7 +18560,7 @@ call_user_func(fp, argcount, argvars, re
 			msg_outnum((long)argvars[i].vval.v_number);
 		    else
 		    {
-			trunc_string(tv2string(&argvars[i], &tofree, numbuf),
+			trunc_string(tv2string(&argvars[i], &tofree, numbuf, 0),
 							    buf, MSG_BUF_CLEN);
 			msg_puts(buf);
 			vim_free(tofree);
@@ -18584,7 +18645,7 @@ call_user_func(fp, argcount, argvars, re
 	    /* The value may be very long.  Skip the middle part, so that we
 	     * have some idea how it starts and ends. smsg() would always
 	     * truncate it at the end. */
-	    trunc_string(tv2string(fc.rettv, &tofree, numbuf),
+	    trunc_string(tv2string(fc.rettv, &tofree, numbuf, 0),
 							   buf, MSG_BUF_CLEN);
 	    smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
 	    vim_free(tofree);
@@ -18806,7 +18867,7 @@ get_return_cmd(rettv)
     char_u	numbuf[NUMBUFLEN];
 
     if (rettv != NULL)
-	s = echo_string((typval_T *)rettv, &tofree, numbuf);
+	s = echo_string((typval_T *)rettv, &tofree, numbuf, 0);
     if (s == NULL)
 	s = (char_u *)"";
 
@@ -19076,7 +19137,7 @@ write_viminfo_varlist(fp)
 		    default: continue;
 		}
 		fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
-		p = echo_string(&this_var->di_tv, &tofree, numbuf);
+		p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
 		if (p != NULL)
 		    viminfo_writestring(fp, p);
 		vim_free(tofree);
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -2583,11 +2583,19 @@ do_write(eap)
 		retval = FAIL;
 		goto theend;
 	    }
+
+	    /* If 'filetype' was empty try detecting it now. */
+	    if (*curbuf->b_p_ft == NUL)
+	    {
+		(void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE);
+		do_modelines(FALSE);
+	    }
 #endif
 	}
 
 	retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
 				 eap, eap->append, eap->forceit, TRUE, FALSE);
+
     }
 
 theend:
@@ -2861,7 +2869,7 @@ getfile(fnum, ffname, sfname, setpm, lnu
     int		retval;
     char_u	*free_me = NULL;
 
-    if (editing_cmdline())
+    if (text_locked())
 	return 1;
 
     if (fnum == 0)
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -661,13 +661,13 @@ getcmdline(firstc, count, indent)
 		restore_cmdline(&save_ccline);
 		if (c == '=')
 		{
-		    /* Need to save and restore ccline.  And set cmdline_busy
+		    /* Need to save and restore ccline.  And set "textlock"
 		     * to avoid nasty things like going to another buffer when
 		     * evaluating an expression. */
 		    save_cmdline(&save_ccline);
-		    ++cmdline_busy;
+		    ++textlock;
 		    p = get_expr_line();
-		    --cmdline_busy;
+		    --textlock;
 		    restore_cmdline(&save_ccline);
 
 		    if (p != NULL && realloc_cmdbuff((int)STRLEN(p) + 1) == OK)
@@ -1875,17 +1875,18 @@ getcmdline_prompt(firstc, prompt, attr, 
 #endif
 
 /*
- * Return TRUE when the command line is being edited.  That means the current
- * buffer and window can't be changed.
+ * Return TRUE when the text must not be changed and we can't switch to
+ * another window or buffer.  Used when editing the command line, evaluating
+ * 'balloonexpr', etc.
  */
     int
-editing_cmdline()
+text_locked()
 {
 #ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
 	return TRUE;
 #endif
-    return cmdline_busy;
+    return textlock != 0;
 }
 
 /*
@@ -1893,7 +1894,7 @@ editing_cmdline()
  * window is open or editing the cmdline in another way.
  */
     void
-editing_cmdline_msg()
+text_locked_msg()
 {
 #ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
@@ -2814,12 +2815,12 @@ cmdline_paste(regname, literally)
     regname = may_get_selection(regname);
 #endif
 
-    /* Need to save and restore ccline.  And set cmdline_busy to avoid nasty
+    /* Need to save and restore ccline.  And set "textlock" to avoid nasty
      * things like going to another buffer when evaluating an expression. */
     save_cmdline(&save_ccline);
-    ++cmdline_busy;
+    ++textlock;
     i = get_spec_reg(regname, &arg, &allocated, TRUE);
-    --cmdline_busy;
+    --textlock;
     restore_cmdline(&save_ccline);
 
     if (i)
@@ -3837,8 +3838,8 @@ addstar(fname, len, context)
 
 		/* Custom expansion takes care of special things, match
 		 * backslashes literally (perhaps also for other types?) */
-		if ((context == EXPAND_USER_DEFINED ||
-		     context == EXPAND_USER_LIST) && fname[i] == '\\')
+		if ((context == EXPAND_USER_DEFINED
+			  || context == EXPAND_USER_LIST) && fname[i] == '\\')
 		    new_len++;		/* '\' becomes "\\" */
 	    }
 	    retval = alloc(new_len);
--- a/src/fold.c
+++ b/src/fold.c
@@ -1938,7 +1938,8 @@ get_foldtext(wp, lnum, lnume, foldinfo, 
 	curbuf = wp->w_buffer;
 
 	++emsg_off;
-	text = eval_to_string_safe(wp->w_p_fdt, NULL);
+	text = eval_to_string_safe(wp->w_p_fdt, NULL,
+				    was_set_insecurely((char_u *)"foldtext"));
 	--emsg_off;
 
 	curwin = save_curwin;
--- a/src/globals.h
+++ b/src/globals.h
@@ -86,7 +86,6 @@ EXTERN int	clear_cmdline INIT(= FALSE);	
 #if defined(FEAT_CRYPT) || defined(FEAT_EVAL)
 EXTERN int	cmdline_star INIT(= FALSE);	/* cmdline is crypted */
 #endif
-EXTERN int	cmdline_busy INIT(= FALSE);	/* editing the cmdline */
 
 EXTERN int	exec_from_reg INIT(= FALSE);	/* executing register */
 
@@ -547,12 +546,16 @@ EXTERN int	secure INIT(= FALSE);
 				 * allowed, e.g. when sourcing .exrc or .vimrc
 				 * in current directory */
 
+EXTERN int	textlock INIT(= 0);
+				/* non-zero when changing text and jumping to
+				 * another window or buffer is not allowed */
+
 #ifdef FEAT_EVAL
 # define HAVE_SANDBOX
 EXTERN int	sandbox INIT(= 0);
-				/* non-zero when evaluating an expression in a
-				 * "sandbox".  Not allowed to change the
-				 * buffer. */
+				/* Non-zero when evaluating an expression in a
+				 * "sandbox".  Several things are not allowed
+				 * then. */
 #endif
 
 EXTERN int	silent_mode INIT(= FALSE);
@@ -1413,10 +1416,7 @@ EXTERN char_u e_invexprmsg[]	INIT(= N_("
 EXTERN char_u e_guarded[]	INIT(= N_("E463: Region is guarded, cannot modify"));
 EXTERN char_u e_nbreadonly[]	INIT(= N_("E744: NetBeans does not allow changes in read-only files"));
 #endif
-#if defined(FEAT_INS_EXPAND) || defined(FEAT_EVAL) || defined(FEAT_SYN_HL) \
-	    || defined(PROTO)
 EXTERN char_u e_intern2[]	INIT(= N_("E685: Internal error: %s"));
-#endif
 EXTERN char_u e_maxmempat[]	INIT(= N_("E363: pattern uses more memory than 'maxmempattern'"));
 EXTERN char_u e_emptybuf[]	INIT(= N_("E749: empty buffer"));
 
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -23,6 +23,7 @@ general_beval_cb(beval, state)
 {
     win_T	*wp;
     int		col;
+    int		use_sandbox;
     linenr_T	lnum;
     char_u	*text;
     static char_u  *result = NULL;
@@ -50,10 +51,17 @@ general_beval_cb(beval, state)
 	set_vim_var_string(VV_BEVAL_TEXT, text, -1);
 	vim_free(text);
 
-	++sandbox;
+	use_sandbox = was_set_insecurely((char_u *)"balloonexpr");
+	if (use_sandbox)
+	    ++sandbox;
+	++textlock;
+
 	vim_free(result);
 	result = eval_to_string(p_bexpr, NULL);
-	--sandbox;
+
+	if (use_sandbox)
+	    --sandbox;
+	--textlock;
 
 	set_vim_var_string(VV_BEVAL_TEXT, NULL, -1);
 	if (result != NULL && result[0] != NUL)
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -1082,35 +1082,137 @@ VimCommand(PyObject *self, PyObject *arg
     return result;
 }
 
+/*
+ * Function to translate a typval_T into a PyObject; this will recursively
+ * translate lists/dictionaries into their Python equivalents.
+ *
+ * The depth parameter is too avoid infinite recursion, set it to 1 when
+ * you call VimToPython.
+ */
+    static PyObject *
+VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
+{
+    PyObject	*result;
+    PyObject	*newObj;
+    char	ptrBuf[NUMBUFLEN];
+
+    /* Avoid infinite recursion */
+    if (depth > 100)
+    {
+        Py_INCREF(Py_None);
+        result = Py_None;
+        return result;
+    }
+
+    /* Check if we run into a recursive loop.  The item must be in lookupDict
+     * then and we can use it again. */
+    sprintf(ptrBuf, "%ld", (long)our_tv);
+    result = PyDict_GetItemString(lookupDict, ptrBuf);
+    if (result != NULL)
+        Py_INCREF(result);
+    else if (our_tv->v_type == VAR_STRING)
+    {
+        result = Py_BuildValue("s", our_tv->vval.v_string);
+        PyDict_SetItemString(lookupDict, ptrBuf, result);
+    }
+    else if (our_tv->v_type == VAR_NUMBER)
+    {
+        char buf[NUMBUFLEN];
+
+	/* For backwards compatibility numbers are stored as strings. */
+        sprintf(buf, "%ld", (long)our_tv->vval.v_number);
+        result = Py_BuildValue("s", buf);
+        PyDict_SetItemString(lookupDict, ptrBuf, result);
+    }
+    else if (our_tv->v_type == VAR_LIST)
+    {
+        list_T		*list = our_tv->vval.v_list;
+        listitem_T	*curr;
+
+        result = PyList_New(0);
+        PyDict_SetItemString(lookupDict, ptrBuf, result);
+
+	if (list != NULL)
+	{
+	    for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
+	    {
+		newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict);
+		PyList_Append(result, newObj);
+		Py_DECREF(newObj);
+	    }
+	}
+    }
+    else if (our_tv->v_type == VAR_DICT)
+    {
+        result = PyDict_New();
+        PyDict_SetItemString(lookupDict, ptrBuf, result);
+
+	if (our_tv->vval.v_dict != NULL)
+	{
+	    hashtab_T	*ht = &our_tv->vval.v_dict->dv_hashtab;
+	    int		todo = ht->ht_used;
+	    hashitem_T	*hi;
+	    dictitem_T	*di;
+
+	    for (hi = ht->ht_array; todo > 0; ++hi)
+	    {
+		if (!HASHITEM_EMPTY(hi))
+		{
+		    --todo;
+
+		    di = dict_lookup(hi);
+		    newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
+		    PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
+		    Py_DECREF(newObj);
+		}
+	    }
+	}
+    }
+    else
+    {
+        Py_INCREF(Py_None);
+        result = Py_None;
+    }
+
+    return result;
+}
+
 /*ARGSUSED*/
     static PyObject *
 VimEval(PyObject *self, PyObject *args)
 {
 #ifdef FEAT_EVAL
     char	*expr;
-    char	*str;
+    typval_T	*our_tv;
     PyObject	*result;
+    PyObject    *lookup_dict;
 
     if (!PyArg_ParseTuple(args, "s", &expr))
 	return NULL;
 
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
-    str = (char *)eval_to_string((char_u *)expr, NULL);
+    our_tv = eval_expr((char_u *)expr, NULL);
+
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
-    if (str == NULL)
+    if (our_tv == NULL)
     {
 	PyErr_SetVim(_("invalid expression"));
 	return NULL;
     }
 
-    result = Py_BuildValue("s", str);
+    /* Convert the Vim type into a Python type.  Create a dictionary that's
+     * used to check for recursive loops. */
+    lookup_dict = PyDict_New();
+    result = VimToPython(our_tv, 1, lookup_dict);
+    Py_DECREF(lookup_dict);
+
 
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
-    vim_free(str);
+    free_tv(our_tv);
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -7673,12 +7673,17 @@ get_expr_indent()
     int		indent;
     pos_T	pos;
     int		save_State;
+    int		use_sandbox = was_set_insecurely((char_u *)"indentexpr");
 
     pos = curwin->w_cursor;
     set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
-    ++sandbox;
+    if (use_sandbox)
+	++sandbox;
+    ++textlock;
     indent = eval_to_number(curbuf->b_p_inde);
-    --sandbox;
+    if (use_sandbox)
+	--sandbox;
+    --textlock;
 
     /* Restore the cursor position so that 'indentexpr' doesn't need to.
      * Pretend to be in Insert mode, allow cursor past end of line for "o"
--- a/src/option.c
+++ b/src/option.c
@@ -317,6 +317,7 @@ struct vimoption
 #define P_GETTEXT	0x80000L/* expand default value with _() */
 #define P_NOGLOB       0x100000L/* do not use local value for global vimrc */
 #define P_NFNAME       0x200000L/* only normal file name chars allowed */
+#define P_INSECURE     0x400000L/* option was set from a modeline */
 
 /*
  * options[] is initialized here.
@@ -1460,7 +1461,7 @@ static struct vimoption
     {"magic",	    NULL,   P_BOOL|P_VI_DEF,
 			    (char_u *)&p_magic, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)0L}},
-    {"makeef",	    "mef",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
+    {"makeef",	    "mef",  P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
 			    (char_u *)&p_mef, PV_NONE,
 			    {(char_u *)"", (char_u *)0L}
@@ -2632,6 +2633,7 @@ static char *(p_cot_values[]) = {"menu",
 
 static void set_option_default __ARGS((int, int opt_flags, int compatible));
 static void set_options_default __ARGS((int opt_flags));
+static void did_set_option __ARGS((int opt_idx, int opt_flags, int new_value));
 static char_u *illegal_char __ARGS((char_u *, int));
 static int string_to_key __ARGS((char_u *arg));
 #ifdef FEAT_CMDWIN
@@ -3157,6 +3159,9 @@ set_option_default(opt_idx, opt_flags, c
 		*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
 								*(int *)varp;
 	}
+
+	/* the default value is not insecure */
+	options[opt_idx].flags &= ~P_INSECURE;
     }
 
 #ifdef FEAT_EVAL
@@ -3790,6 +3795,12 @@ do_set(arg, opt_flags)
 		}
 	    }
 
+	    /* Skip all options that are not window-local (used when showing
+	     * an already loaded buffer in a window). */
+	    if ((opt_flags & OPT_WINONLY)
+			  && (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
+		goto skip;
+
 	    /* Disallow changing some options from modelines */
 	    if ((opt_flags & OPT_MODELINE) && (flags & P_SECURE))
 	    {
@@ -3797,15 +3808,9 @@ do_set(arg, opt_flags)
 		goto skip;
 	    }
 
-	    /* Skip all options that are not window-local (used when showing
-	     * an already loaded buffer in a window). */
-	    if ((opt_flags & OPT_WINONLY)
-		    && (opt_idx < 0 || options[opt_idx].var != VAR_WIN))
-		goto skip;
-
 #ifdef HAVE_SANDBOX
 	    /* Disallow changing some options in the sandbox */
-	    if (sandbox > 0 && (flags & P_SECURE))
+	    if (sandbox != 0 && (flags & P_SECURE))
 	    {
 		errmsg = (char_u *)_(e_sandbox);
 		goto skip;
@@ -4343,8 +4348,10 @@ do_set(arg, opt_flags)
 			redraw_all_later(CLEAR);
 		    }
 		}
+
 		if (opt_idx >= 0)
-		    options[opt_idx].flags |= P_WAS_SET;
+		    did_set_option(opt_idx, opt_flags,
+					 !prepending && !adding && !removing);
 	    }
 
 skip:
@@ -4405,6 +4412,31 @@ theend:
     return OK;
 }
 
+/*
+ * Call this when an option has been given a new value through a user command.
+ * Sets the P_WAS_SET flag and takes care of the P_INSECURE flag.
+ */
+    static void
+did_set_option(opt_idx, opt_flags, new_value)
+    int	    opt_idx;
+    int	    opt_flags;	    /* possibly with OPT_MODELINE */
+    int	    new_value;	    /* value was replaced completely */
+{
+    options[opt_idx].flags |= P_WAS_SET;
+
+    /* When an option is set in the sandbox, from a modeline or in secure mode
+     * set the P_INSECURE flag.  Otherwise, if a new value is stored reset the
+     * flag. */
+    if (secure
+#ifdef HAVE_SANDBOX
+	    || sandbox != 0
+#endif
+	    || (opt_flags & OPT_MODELINE))
+	options[opt_idx].flags |= P_INSECURE;
+    else if (new_value)
+	options[opt_idx].flags &= ~P_INSECURE;
+}
+
     static char_u *
 illegal_char(errbuf, c)
     char_u	*errbuf;
@@ -4837,6 +4869,25 @@ set_term_option_alloced(p)
     return; /* cannot happen: didn't find it! */
 }
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return TRUE when option "opt" was set from a modeline or in secure mode.
+ * Return FALSE when it wasn't.
+ * Return -1 for an unknown option.
+ */
+    int
+was_set_insecurely(opt)
+    char_u *opt;
+{
+    int	    idx = findoption(opt);
+
+    if (idx >= 0)
+	return (options[idx].flags & P_INSECURE) != 0;
+    EMSG2(_(e_intern2), "was_set_insecurely()");
+    return -1;
+}
+#endif
+
 /*
  * Set a string option to a new value (without checking the effect).
  * The string is copied into allocated memory.
@@ -4938,9 +4989,9 @@ set_string_option(opt_idx, value, opt_fl
 		    : opt_flags);
 	oldval = *varp;
 	*varp = s;
-	options[opt_idx].flags |= P_WAS_SET;
-	(void)did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
-								   opt_flags);
+	if (did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
+							   opt_flags) == NULL)
+	    did_set_option(opt_idx, opt_flags, TRUE);
     }
 }
 
@@ -6571,10 +6622,6 @@ set_bool_option(opt_idx, varp, value, op
 {
     int		old_value = *(int *)varp;
 
-#ifdef FEAT_GUI
-    need_mouse_correct = TRUE;
-#endif
-
     /* Disallow changing some options from secure mode */
     if ((secure
 #ifdef HAVE_SANDBOX
@@ -6589,6 +6636,10 @@ set_bool_option(opt_idx, varp, value, op
     options[opt_idx].scriptID = current_SID;
 #endif
 
+#ifdef FEAT_GUI
+    need_mouse_correct = TRUE;
+#endif
+
     /* May set global value for local option. */
     if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
 	*(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) = value;
@@ -7077,15 +7128,22 @@ set_num_option(opt_idx, varp, value, err
     long	old_Columns = Columns;	/* remember old Columns */
     long	*pp = (long *)varp;
 
-#ifdef FEAT_GUI
-    need_mouse_correct = TRUE;
-#endif
+    /* Disallow changing some options from secure mode. */
+    if ((secure
+#ifdef HAVE_SANDBOX
+		|| sandbox != 0
+#endif
+		) && (options[opt_idx].flags & P_SECURE))
+	return e_secure;
 
     *pp = value;
 #ifdef FEAT_EVAL
     /* Remember where the option was set. */
     options[opt_idx].scriptID = current_SID;
 #endif
+#ifdef FEAT_GUI
+    need_mouse_correct = TRUE;
+#endif
 
     if (curbuf->b_p_sw <= 0)
     {
@@ -7690,10 +7748,12 @@ set_option_value(name, number, string, o
 #ifdef HAVE_SANDBOX
 	/* Disallow changing some options in the sandbox */
 	if (sandbox > 0 && (flags & P_SECURE))
+	{
 	    EMSG(_(e_sandbox));
-	else
-#endif
-	  if (flags & P_STRING)
+	    return;
+	}
+#endif
+	if (flags & P_STRING)
 	    set_string_option(opt_idx, string, opt_flags);
 	else
 	{
@@ -7704,7 +7764,8 @@ set_option_value(name, number, string, o
 		    (void)set_num_option(opt_idx, varp, number,
 							  NULL, 0, opt_flags);
 		else
-		    (void)set_bool_option(opt_idx, varp, (int)number, opt_flags);
+		    (void)set_bool_option(opt_idx, varp, (int)number,
+								   opt_flags);
 	    }
 	}
     }
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -18,7 +18,7 @@ int eval_to_bool __ARGS((char_u *arg, in
 char_u *eval_to_string_skip __ARGS((char_u *arg, char_u **nextcmd, int skip));
 int skip_expr __ARGS((char_u **pp));
 char_u *eval_to_string __ARGS((char_u *arg, char_u **nextcmd));
-char_u *eval_to_string_safe __ARGS((char_u *arg, char_u **nextcmd));
+char_u *eval_to_string_safe __ARGS((char_u *arg, char_u **nextcmd, int use_sandbox));
 int eval_to_number __ARGS((char_u *expr));
 list_T *eval_spell_expr __ARGS((char_u *badword, char_u *expr));
 int get_spellword __ARGS((list_T *list, char_u **pp));
@@ -43,6 +43,7 @@ int do_unlet __ARGS((char_u *name, int f
 void del_menutrans_vars __ARGS((void));
 char_u *get_user_var_name __ARGS((expand_T *xp, int idx));
 void list_unref __ARGS((list_T *l));
+dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
 int list_append_dict __ARGS((list_T *list, dict_T *dict));
 int garbage_collect __ARGS((void));
 dict_T *dict_alloc __ARGS((void));
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1880,7 +1880,7 @@ ex_copen(eap)
 	    set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
 	    set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
 								   OPT_LOCAL);
-	    set_option_value((char_u *)"bh", 0L, (char_u *)"delete", OPT_LOCAL);
+	    set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
 	    set_option_value((char_u *)"diff", 0L, (char_u *)"", OPT_LOCAL);
 	}
 	else if (buf != curbuf)
--- a/src/undo.c
+++ b/src/undo.c
@@ -182,7 +182,7 @@ undo_allowed()
 
     /* Don't allow changes in the buffer while editing the cmdline.  The
      * caller of getcmdline() may get confused. */
-    if (cmdline_busy)
+    if (textlock != 0)
     {
 	EMSG(_(e_secure));
 	return FALSE;
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Jan 19)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Jan 19, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Jan 20)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Jan 20, compiled "