summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2006-01-20 23:10:18 +0000
committerBram Moolenaar <Bram@vim.org>2006-01-20 23:10:18 +0000
commitb71eaaeaa8193b0cbb67496de6ad16ced80b8b09 (patch)
tree29e50b81ba2e1352e1f1940398e1b3507b8ea2c6
parent2d3f489e09a1cc50f5b7601eff568a4eb87fbd51 (diff)
updated for version 7.0183v7.0183
-rw-r--r--runtime/doc/eval.txt31
-rw-r--r--runtime/doc/options.txt48
-rw-r--r--runtime/doc/tags3
-rw-r--r--runtime/doc/todo.txt22
-rw-r--r--runtime/doc/version7.txt28
-rw-r--r--src/edit.c2
-rw-r--r--src/eval.c135
-rw-r--r--src/ex_cmds.c10
-rw-r--r--src/ex_getln.c27
-rw-r--r--src/fold.c3
-rw-r--r--src/globals.h14
-rw-r--r--src/gui_beval.c12
-rw-r--r--src/if_python.c112
-rw-r--r--src/misc1.c9
-rw-r--r--src/option.c103
-rw-r--r--src/proto/eval.pro3
-rw-r--r--src/quickfix.c2
-rw-r--r--src/undo.c2
-rw-r--r--src/version.h4
19 files changed, 447 insertions, 123 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index dfab7c9075..837ba3cb1f 100644
--- 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 @@ done, the features in this document are not available. See |+eval| and
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 it should block most attacks.
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:
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 16c36db2ca..2a812fe40b 100644
--- 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 short description can be found at |Q_op|.
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 short description can be found at |Q_op|.
{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 short description can be found at |Q_op|.
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 short description can be found at |Q_op|.
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 short description can be found at |Q_op|.
: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 short description can be found at |Q_op|.
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
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 2174f20c61..302907b1fc 100644
--- 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*
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index da95e60723..6785f76210 100644
--- 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 Vim development. See |sponsor|.
*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.
diff --git a/runtime/doc/version7.txt b/runtime/doc/version7.txt
index 5743a79710..604447bdab 100644
--- 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 way.
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-stack errors. State is stored in
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. (Yegappan Lakshmanan)
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 Insert mode.
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 command, as in "!cmd foo<Tab>" or ":r
!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:
diff --git a/src/edit.c b/src/edit.c
index ab3558a9f9..8dc07fdf97 100644
--- 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;
diff --git a/src/eval.c b/src/eval.c
index c18b42d0f3..737dfa64c6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -420,8 +420,8 @@ static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
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 *orig, int deep, int copyID));
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);
+ s = echo_string(&item->li_tv, &tofree, numbuf, copyID);
else
- s = tv2string(&item->li_tv, &tofree, numbuf);
+ 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;
+ 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;
+ 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, rettv, firstline, lastline, selfdict)
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, rettv, firstline, lastline, selfdict)
/* 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);
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index e192d100c5..c8912cae0e 100644
--- 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, lnum, forceit)
int retval;
char_u *free_me = NULL;
- if (editing_cmdline())
+ if (text_locked())
return 1;
if (fnum == 0)
diff --git a/src/ex_getln.c b/src/ex_getln.c
index b1142c472f..6828f671de 100644
--- 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, xp_context, xp_arg)
#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);
diff --git a/src/fold.c b/src/fold.c
index 6731e6386a..67d542c4a5 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -1938,7 +1938,8 @@ get_foldtext(wp, lnum, lnume, foldinfo, buf)
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;
diff --git a/src/globals.h b/src/globals.h
index 9c81e4efbf..6a46485fb5 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -86,7 +86,6 @@ EXTERN int clear_cmdline INIT(= FALSE); /* cmdline must be cleared */
#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_("E449: Invalid expression received"));
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"));
diff --git a/src/gui_beval.c b/src/gui_beval.c
index 290f388b84..755f943100 100644
--- 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)
diff --git a/src/if_python.c b/src/if_python.c
index d58f7cf1e2..c1b3bf8176 100644
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -1082,35 +1082,137 @@ VimCommand(PyObject *self, PyObject *args)
return r