Compare commits

..

9 Commits

Author SHA1 Message Date
Bram Moolenaar
30445cb6e9 patch 7.4.2006
Problem:    Crash when using tabnext in BufUnload autocmd. (Norio Takagi)
Solution:   First check that the current buffer is the right one. (Hirohito
            Higashi)
2016-07-09 15:21:02 +02:00
Bram Moolenaar
ee1deb4a00 patch 7.4.2005
Problem:    After using evalcmd() message output is in the wrong position.
            (Christian Brabandt)
Solution:   Reset msg_col.
2016-07-08 23:06:21 +02:00
Bram Moolenaar
65549bdef5 patch 7.4.2004
Problem:    GUI: cursor displayed in the wrong position.
Solution:   Correct screen_cur_col and screen_cur_row.
2016-07-08 22:52:37 +02:00
Bram Moolenaar
144445d15f patch 7.4.2003
Problem:    Still cursor flickering when a callback updates the screen. (David
            Samvelyan)
Solution:   Put the cursor in the right position after updating the screen.
2016-07-08 21:41:54 +02:00
Bram Moolenaar
a06ec8f345 patch 7.4.2002
Problem:    Crash when passing number to filter() or map().
Solution:   Convert to a string. (Ozaki Kiichi)
2016-07-08 20:11:07 +02:00
Bram Moolenaar
ba768495c2 patch 7.4.2001
Problem:    Tiny build fails. (Tony Mechelynck)
Solution:   Add #ifdef.
2016-07-08 15:32:54 +02:00
Bram Moolenaar
245a7cb6d3 patch 7.4.2000
Problem:    Evalcmd test fails.
Solution:   Add missing piece.
2016-07-08 10:53:12 +02:00
Bram Moolenaar
bc5d6dd1dd patch 7.4.1999
Problem:    evalcmd() doesn't work recursively.
Solution:   Use redir_evalcmd instead of redir_vname.
2016-07-07 23:04:18 +02:00
Bram Moolenaar
bf2cc5f36d patch 7.4.1998
Problem:    When writing buffer lines to a job there is no NL to NUL
            conversion.
Solution:   Make it work symmetrical with writing lines from a job into a
            buffer.
2016-07-07 20:45:06 +02:00
14 changed files with 174 additions and 41 deletions

View File

@@ -459,14 +459,6 @@ aucmd_abort:
#endif
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
if (
#ifdef FEAT_WINDOWS
win_valid(win) &&
#else
win != NULL &&
#endif
win->w_buffer == buf)
win->w_buffer = NULL; /* make sure we don't use the buffer now */
#ifdef FEAT_AUTOCMD
/* Autocommands may have deleted the buffer. */
@@ -477,11 +469,6 @@ aucmd_abort:
return;
# endif
/* Autocommands may have opened or closed windows for this buffer.
* Decrement the count for the close we do here. */
if (buf->b_nwindows > 0)
--buf->b_nwindows;
/*
* It's possible that autocommands change curbuf to the one being deleted.
* This might cause the previous curbuf to be deleted unexpectedly. But
@@ -491,6 +478,20 @@ aucmd_abort:
*/
if (buf == curbuf && !is_curbuf)
return;
if (
#ifdef FEAT_WINDOWS
win_valid(win) &&
#else
win != NULL &&
#endif
win->w_buffer == buf)
win->w_buffer = NULL; /* make sure we don't use the buffer now */
/* Autocommands may have opened or closed windows for this buffer.
* Decrement the count for the close we do here. */
if (buf->b_nwindows > 0)
--buf->b_nwindows;
#endif
/* Change directories when the 'acd' option is set. */

View File

@@ -1313,14 +1313,20 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel)
char_u *line = ml_get_buf(buf, lnum, FALSE);
int len = (int)STRLEN(line);
char_u *p;
int i;
/* Need to make a copy to be able to append a NL. */
if ((p = alloc(len + 2)) == NULL)
return;
memcpy((char *)p, (char *)line, len);
for (i = 0; i < len; ++i)
if (p[i] == NL)
p[i] = NUL;
p[len] = NL;
p[len + 1] = NUL;
channel_send(channel, PART_IN, p, "write_buf_line()");
channel_send(channel, PART_IN, p, len + 1, "write_buf_line()");
vim_free(p);
}
@@ -2185,7 +2191,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
{
channel_send(channel,
part == PART_SOCK ? PART_SOCK : PART_IN,
json, (char *)cmd);
json, (int)STRLEN(json), (char *)cmd);
vim_free(json);
}
}
@@ -3380,9 +3386,8 @@ channel_handle_events(void)
* Return FAIL or OK.
*/
int
channel_send(channel_T *channel, int part, char_u *buf, char *fun)
channel_send(channel_T *channel, int part, char_u *buf, int len, char *fun)
{
int len = (int)STRLEN(buf);
int res;
sock_T fd;
@@ -3470,7 +3475,7 @@ send_common(
opt->jo_callback, opt->jo_partial, id);
}
if (channel_send(channel, part_send, text, fun) == OK
if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK
&& opt->jo_callback == NULL)
return channel;
return NULL;

View File

@@ -11345,6 +11345,28 @@ f_eval(typval_T *argvars, typval_T *rettv)
EMSG(_(e_trailing));
}
static garray_T redir_evalcmd_ga;
/*
* Append "value[value_len]" to the evalcmd() output.
*/
void
evalcmd_redir_str(char_u *value, int value_len)
{
int len;
if (value_len == -1)
len = (int)STRLEN(value); /* Append the entire string */
else
len = value_len; /* Append only "value_len" characters */
if (ga_grow(&redir_evalcmd_ga, len) == OK)
{
mch_memmove((char *)redir_evalcmd_ga.ga_data
+ redir_evalcmd_ga.ga_len, value, len);
redir_evalcmd_ga.ga_len += len;
}
}
/*
* "evalcmd()" function
*/
@@ -11352,6 +11374,9 @@ f_eval(typval_T *argvars, typval_T *rettv)
f_evalcmd(typval_T *argvars, typval_T *rettv)
{
char_u *s;
int save_msg_silent = msg_silent;
int save_redir_evalcmd = redir_evalcmd;
garray_T save_ga;
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
@@ -11359,20 +11384,24 @@ f_evalcmd(typval_T *argvars, typval_T *rettv)
s = get_tv_string_chk(&argvars[0]);
if (s != NULL)
{
redir_vname = TRUE;
redir_lval = (lval_T *)&redir_lval;
ga_init2(&redir_ga, (int)sizeof(char), 500);
if (redir_evalcmd)
save_ga = redir_evalcmd_ga;
ga_init2(&redir_evalcmd_ga, (int)sizeof(char), 500);
redir_evalcmd = TRUE;
if (do_cmdline_cmd(s) == OK)
rettv->vval.v_string = redir_ga.ga_data;
else
vim_free(redir_ga.ga_data);
++msg_silent;
do_cmdline_cmd(s);
rettv->vval.v_string = redir_evalcmd_ga.ga_data;
msg_silent = save_msg_silent;
redir_ga.ga_data = NULL;
redir_vname = FALSE;
redir_lval = NULL;
redir_evalcmd = save_redir_evalcmd;
if (redir_evalcmd)
redir_evalcmd_ga = save_ga;
/* "silent reg" or "silent echo x" leaves msg_col somewhere in the
* line. Put it back in the first column. */
msg_col = 0;
}
}
/*
@@ -12019,6 +12048,7 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
{
typval_T rettv;
typval_T argv[3];
char_u buf[NUMBUFLEN];
char_u *s;
int retval = FAIL;
int dummy;
@@ -12026,9 +12056,9 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
copy_tv(tv, &vimvars[VV_VAL].vv_tv);
argv[0] = vimvars[VV_KEY].vv_tv;
argv[1] = vimvars[VV_VAL].vv_tv;
s = expr->vval.v_string;
if (expr->v_type == VAR_FUNC)
{
s = expr->vval.v_string;
if (call_func(s, (int)STRLEN(s),
&rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
goto theend;
@@ -12045,6 +12075,9 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
}
else
{
s = get_tv_string_buf_chk(expr, buf);
if (s == NULL)
goto theend;
s = skipwhite(s);
if (eval1(&s, &rettv, TRUE) == FAIL)
goto theend;

View File

@@ -9455,6 +9455,14 @@ ex_redir(exarg_T *eap)
char_u *fname;
char_u *arg = eap->arg;
#ifdef FEAT_EVAL
if (redir_evalcmd)
{
EMSG(_("E930: Cannot use :redir inside evalcmd()"));
return;
}
#endif
if (STRICMP(eap->arg, "END") == 0)
close_redir();
else

View File

@@ -1106,6 +1106,7 @@ EXTERN FILE *redir_fd INIT(= NULL); /* message redirection file */
#ifdef FEAT_EVAL
EXTERN int redir_reg INIT(= 0); /* message redirection register */
EXTERN int redir_vname INIT(= 0); /* message redirection variable */
EXTERN int redir_evalcmd INIT(= 0); /* evalcmd() redirection */
#endif
#ifdef FEAT_LANGMAP

View File

@@ -3063,7 +3063,9 @@ redir_write(char_u *str, int maxlen)
while (cur_col < msg_col)
{
#ifdef FEAT_EVAL
if (redir_reg)
if (redir_evalcmd)
evalcmd_redir_str((char_u *)" ", -1);
else if (redir_reg)
write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
else if (redir_vname)
var_redir_str((char_u *)" ", -1);
@@ -3078,9 +3080,11 @@ redir_write(char_u *str, int maxlen)
}
#ifdef FEAT_EVAL
if (redir_reg)
if (redir_evalcmd)
evalcmd_redir_str(s, maxlen);
else if (redir_reg)
write_reg_contents(redir_reg, s, maxlen, TRUE);
if (redir_vname)
else if (redir_vname)
var_redir_str(s, maxlen);
#endif
@@ -3088,7 +3092,7 @@ redir_write(char_u *str, int maxlen)
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
{
#ifdef FEAT_EVAL
if (!redir_reg && !redir_vname)
if (!redir_reg && !redir_vname && !redir_evalcmd)
#endif
if (redir_fd != NULL)
putc(*s, redir_fd);
@@ -3113,7 +3117,7 @@ redirecting(void)
{
return redir_fd != NULL || *p_vfile != NUL
#ifdef FEAT_EVAL
|| redir_reg || redir_vname
|| redir_reg || redir_vname || redir_evalcmd
#endif
;
}

View File

@@ -765,7 +765,8 @@ netbeans_end(void)
nb_send(char *buf, char *fun)
{
if (nb_channel != NULL)
channel_send(nb_channel, PART_SOCK, (char_u *)buf, fun);
channel_send(nb_channel, PART_SOCK, (char_u *)buf,
(int)STRLEN(buf), fun);
}
/*

View File

@@ -34,7 +34,7 @@ int channel_read_json_block(channel_T *channel, int part, int timeout_arg, int i
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
channel_T *channel_fd2channel(sock_T fd, int *partp);
void channel_handle_events(void);
int channel_send(channel_T *channel, int part, char_u *buf, char *fun);
int channel_send(channel_T *channel, int part, char_u *buf, int len, char *fun);
channel_T *send_common(typval_T *argvars, char_u *text, int id, int eval, jobopt_T *opt, char *fun, int *part_read);
void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval);
void ch_raw_common(typval_T *argvars, typval_T *rettv, int eval);

View File

@@ -81,12 +81,14 @@ int dict_add_list(dict_T *d, char *key, list_T *list);
dictitem_T *dict_find(dict_T *d, char_u *key, int len);
char_u *get_dict_string(dict_T *d, char_u *key, int save);
varnumber_T get_dict_number(dict_T *d, char_u *key);
char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
int string2float(char_u *text, float_T *value);
char_u *get_function_name(expand_T *xp, int idx);
char_u *get_expr_name(expand_T *xp, int idx);
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
buf_T *buflist_find_by_name(char_u *name, int curtab_only);
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
void evalcmd_redir_str(char_u *value, int value_len);
void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
float_T vim_round(float_T f);
@@ -150,5 +152,4 @@ void ex_oldfiles(exarg_T *eap);
void reset_v_option_vars(void);
int modify_fname(char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen);
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags);
char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
/* vim: set ft=c : */

View File

@@ -422,7 +422,7 @@ redraw_after_callback(void)
; /* do nothing */
else if (State & CMDLINE)
redrawcmdline();
else if ((State & NORMAL) || (State & INSERT))
else if (State & (NORMAL | INSERT))
{
update_screen(0);
setcursor();
@@ -486,8 +486,6 @@ update_curbuf(int type)
}
/*
* update_screen()
*
* Based on the current value of curwin->w_topline, transfer a screenfull
* of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
*/
@@ -499,6 +497,10 @@ update_screen(int type)
#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_CLIPBOARD)
int did_one;
#endif
#ifdef FEAT_GUI
int gui_cursor_col;
int gui_cursor_row;
#endif
/* Don't do anything if the screen structures are (not yet) valid. */
if (!screen_valid(TRUE))
@@ -696,7 +698,11 @@ update_screen(int type)
* scrolling may make it difficult to redraw the text under
* it. */
if (gui.in_use)
{
gui_cursor_col = gui.cursor_col;
gui_cursor_row = gui.cursor_row;
gui_undraw_cursor();
}
#endif
}
#endif
@@ -752,7 +758,15 @@ update_screen(int type)
{
out_flush(); /* required before updating the cursor */
if (did_one)
{
/* Put the GUI position where the cursor was, gui_update_cursor()
* uses that. */
gui.col = gui_cursor_col;
gui.row = gui_cursor_row;
gui_update_cursor(FALSE, FALSE);
screen_cur_col = gui.col;
screen_cur_row = gui.row;
}
gui_update_scrollbars(FALSE);
}
#endif

View File

@@ -60,3 +60,21 @@ function Test_bufunload()
augroup! test_bufunload_group
endfunc
" SEGV occurs in older versions. (At least 7.4.2005 or older)
function Test_autocmd_bufunload_with_tabnext()
tabedit
tabfirst
augroup test_autocmd_bufunload_with_tabnext_group
autocmd!
autocmd BufUnload <buffer> tabnext
augroup END
quit
call assert_equal(2, tabpagenr('$'))
augroup! test_autocmd_bufunload_with_tabnext_group
tablast
quit
endfunc

View File

@@ -1,8 +1,33 @@
" test evalcmd()
func NestedEval()
let nested = evalcmd('echo "nested\nlines"')
echo 'got: "' . nested . '"'
endfunc
func NestedRedir()
redir => var
echo 'broken'
redir END
endfunc
func Test_evalcmd()
call assert_equal("\nnocompatible", evalcmd('set compatible?'))
call assert_equal("\nsomething\nnice", evalcmd('echo "something\nnice"'))
call assert_equal("noendofline", evalcmd('echon "noendofline"'))
call assert_equal("", evalcmd(123))
call assert_equal("\ngot: \"\nnested\nlines\"", evalcmd('call NestedEval()'))
redir => redired
echo 'this'
let evaled = evalcmd('echo "that"')
echo 'theend'
redir END
call assert_equal("\nthis\ntheend", redired)
call assert_equal("\nthat", evaled)
call assert_fails('call evalcmd("doesnotexist")', 'E492:')
call assert_fails('call evalcmd(3.4)', 'E806:')
call assert_fails('call evalcmd("call NestedRedir()")', 'E930:')
endfunc

View File

@@ -5,10 +5,12 @@ func Test_filter_map_list_expr_string()
" filter()
call assert_equal([2, 3, 4], filter([1, 2, 3, 4], 'v:val > 1'))
call assert_equal([3, 4], filter([1, 2, 3, 4], 'v:key > 1'))
call assert_equal([], filter([1, 2, 3, 4], 0))
" map()
call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2'))
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2'))
call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9))
endfunc
" dict with expression string
@@ -18,10 +20,12 @@ func Test_filter_map_dict_expr_string()
" filter()
call assert_equal({"bar": 2, "baz": 3}, filter(copy(dict), 'v:val > 1'))
call assert_equal({"foo": 1, "baz": 3}, filter(copy(dict), 'v:key > "bar"'))
call assert_equal({}, filter(copy(dict), 0))
" map()
call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2'))
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]'))
call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9))
endfunc
" list with funcref

View File

@@ -758,6 +758,24 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2006,
/**/
2005,
/**/
2004,
/**/
2003,
/**/
2002,
/**/
2001,
/**/
2000,
/**/
1999,
/**/
1998,
/**/
1997,
/**/