Skip to content

Commit b044cf0

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 3cc4453 + 030cddc commit b044cf0

20 files changed

Lines changed: 261 additions & 134 deletions

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2059,7 +2059,7 @@ test1 \
20592059
test_utf8 \
20602060
test_wordcount \
20612061
test2 test3 test4 test5 test6 test7 test8 test9 \
2062-
test11 test12 test13 test14 test15 test17 test18 test19 \
2062+
test11 test12 test14 test15 test17 test18 test19 \
20632063
test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 \
20642064
test30 test31 test32 test33 test34 test36 test37 test38 test39 \
20652065
test40 test41 test42 test43 test44 test45 test48 test49 \

src/buffer.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,11 @@ close_buffer(
450450
int is_curbuf;
451451
int nwindows;
452452
bufref_T bufref;
453+
# ifdef FEAT_WINDOWS
454+
int is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
455+
win_T *the_curwin = curwin;
456+
tabpage_T *the_curtab = curtab;
457+
# endif
453458
#endif
454459
int unload_buf = (action != 0);
455460
int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
@@ -476,6 +481,16 @@ close_buffer(
476481
unload_buf = TRUE;
477482
#endif
478483

484+
#ifdef FEAT_AUTOCMD
485+
/* Disallow deleting the buffer when it is locked (already being closed or
486+
* halfway a command that relies on it). Unloading is allowed. */
487+
if (buf->b_locked > 0 && (del_buf || wipe_buf))
488+
{
489+
EMSG(_("E937: Attempt to delete a buffer that is in use"));
490+
return;
491+
}
492+
#endif
493+
479494
if (win != NULL
480495
#ifdef FEAT_WINDOWS
481496
&& win_valid_any_tab(win) /* in case autocommands closed the window */
@@ -499,7 +514,7 @@ close_buffer(
499514
/* When the buffer is no longer in a window, trigger BufWinLeave */
500515
if (buf->b_nwindows == 1)
501516
{
502-
buf->b_closing = TRUE;
517+
++buf->b_locked;
503518
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
504519
FALSE, buf)
505520
&& !bufref_valid(&bufref))
@@ -509,7 +524,7 @@ close_buffer(
509524
EMSG(_(e_auabort));
510525
return;
511526
}
512-
buf->b_closing = FALSE;
527+
--buf->b_locked;
513528
if (abort_if_last && one_window())
514529
/* Autocommands made this the only window. */
515530
goto aucmd_abort;
@@ -518,13 +533,13 @@ close_buffer(
518533
* BufHidden */
519534
if (!unload_buf)
520535
{
521-
buf->b_closing = TRUE;
536+
++buf->b_locked;
522537
if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
523538
FALSE, buf)
524539
&& !bufref_valid(&bufref))
525540
/* Autocommands deleted the buffer. */
526541
goto aucmd_abort;
527-
buf->b_closing = FALSE;
542+
--buf->b_locked;
528543
if (abort_if_last && one_window())
529544
/* Autocommands made this the only window. */
530545
goto aucmd_abort;
@@ -534,6 +549,19 @@ close_buffer(
534549
return;
535550
# endif
536551
}
552+
553+
# ifdef FEAT_WINDOWS
554+
/* If the buffer was in curwin and the window has changed, go back to that
555+
* window, if it still exists. This avoids that ":edit x" triggering a
556+
* "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
557+
if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin))
558+
{
559+
block_autocmds();
560+
goto_tabpage_win(the_curtab, the_curwin);
561+
unblock_autocmds();
562+
}
563+
# endif
564+
537565
nwindows = buf->b_nwindows;
538566
#endif
539567

@@ -683,13 +711,13 @@ buf_freeall(buf_T *buf, int flags)
683711
int is_curbuf = (buf == curbuf);
684712
bufref_T bufref;
685713
# ifdef FEAT_WINDOWS
686-
int is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
714+
int is_curwin = (curwin != NULL && curwin->w_buffer == buf);
687715
win_T *the_curwin = curwin;
688716
tabpage_T *the_curtab = curtab;
689717
# endif
690718

691719
/* Make sure the buffer isn't closed by autocommands. */
692-
buf->b_closing = TRUE;
720+
++buf->b_locked;
693721
set_bufref(&bufref, buf);
694722
if (buf->b_ml.ml_mfp != NULL)
695723
{
@@ -715,7 +743,7 @@ buf_freeall(buf_T *buf, int flags)
715743
/* autocommands deleted the buffer */
716744
return;
717745
}
718-
buf->b_closing = FALSE;
746+
--buf->b_locked;
719747

720748
# ifdef FEAT_WINDOWS
721749
/* If the buffer was in curwin and the window has changed, go back to that
@@ -748,7 +776,7 @@ buf_freeall(buf_T *buf, int flags)
748776
#endif
749777
#ifdef FEAT_SYN_HL
750778
/* Remove any ownsyntax, unless exiting. */
751-
if (firstwin != NULL && curwin->w_buffer == buf)
779+
if (curwin != NULL && curwin->w_buffer == buf)
752780
reset_synblock(curwin);
753781
#endif
754782

@@ -764,7 +792,7 @@ buf_freeall(buf_T *buf, int flags)
764792
clearFolding(win);
765793
}
766794
# else
767-
if (curwin->w_buffer == buf)
795+
if (curwin != NULL && curwin->w_buffer == buf)
768796
clearFolding(curwin);
769797
# endif
770798
#endif
@@ -1373,7 +1401,7 @@ do_buffer(
13731401
*/
13741402
while (buf == curbuf
13751403
# ifdef FEAT_AUTOCMD
1376-
&& !(curwin->w_closing || curwin->w_buffer->b_closing)
1404+
&& !(curwin->w_closing || curwin->w_buffer->b_locked > 0)
13771405
# endif
13781406
&& (firstwin != lastwin || first_tabpage->tp_next != NULL))
13791407
{
@@ -5110,7 +5138,7 @@ ex_buffer_all(exarg_T *eap)
51105138
#endif
51115139
) && firstwin != lastwin
51125140
#ifdef FEAT_AUTOCMD
5113-
&& !(wp->w_closing || wp->w_buffer->b_closing)
5141+
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
51145142
#endif
51155143
)
51165144
{

src/channel.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
21632163
}
21642164
else
21652165
{
2166-
typval_T *tv;
2166+
typval_T *tv = NULL;
21672167
typval_T res_tv;
21682168
typval_T err_tv;
21692169
char_u *json = NULL;
@@ -2180,8 +2180,6 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
21802180
ch_logs(channel, "Calling '%s'", (char *)arg);
21812181
if (func_call(arg, &argv[2], NULL, NULL, &res_tv) == OK)
21822182
tv = &res_tv;
2183-
else
2184-
tv = NULL;
21852183
}
21862184

21872185
if (argv[id_idx].v_type == VAR_NUMBER)
@@ -2195,11 +2193,9 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
21952193
/* If evaluation failed or the result can't be encoded
21962194
* then return the string "ERROR". */
21972195
vim_free(json);
2198-
free_tv(tv);
21992196
err_tv.v_type = VAR_STRING;
22002197
err_tv.vval.v_string = (char_u *)"ERROR";
2201-
tv = &err_tv;
2202-
json = json_encode_nr_expr(id, tv, options | JSON_NL);
2198+
json = json_encode_nr_expr(id, &err_tv, options | JSON_NL);
22032199
}
22042200
if (json != NULL)
22052201
{
@@ -2212,7 +2208,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
22122208
--emsg_skip;
22132209
if (tv == &res_tv)
22142210
clear_tv(tv);
2215-
else if (tv != &err_tv)
2211+
else
22162212
free_tv(tv);
22172213
}
22182214
}

src/evalfunc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7648,7 +7648,7 @@ max_min(typval_T *argvars, typval_T *rettv, int domax)
76487648
}
76497649
}
76507650
else
7651-
EMSG(_(e_listdictarg));
7651+
EMSG2(_(e_listdictarg), domax ? "max()" : "min()");
76527652
rettv->vval.v_number = error ? 0 : n;
76537653
}
76547654

src/ex_cmds.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,8 +3872,8 @@ do_ecmd(
38723872
oldbuf = TRUE;
38733873
set_bufref(&bufref, buf);
38743874
(void)buf_check_timestamp(buf, FALSE);
3875-
/* Check if autocommands made buffer invalid or changed the current
3876-
* buffer. */
3875+
/* Check if autocommands made the buffer invalid or changed the
3876+
* current buffer. */
38773877
if (!bufref_valid(&bufref)
38783878
#ifdef FEAT_AUTOCMD
38793879
|| curbuf != old_curbuf.br_buf
@@ -3938,8 +3938,9 @@ do_ecmd(
39383938
win_T *the_curwin = curwin;
39393939

39403940
/* Set the w_closing flag to avoid that autocommands close the
3941-
* window. */
3941+
* window. And set b_locked for the same reason. */
39423942
the_curwin->w_closing = TRUE;
3943+
++buf->b_locked;
39433944

39443945
if (curbuf == old_curbuf.br_buf)
39453946
#endif
@@ -3953,6 +3954,7 @@ do_ecmd(
39533954

39543955
#ifdef FEAT_AUTOCMD
39553956
the_curwin->w_closing = FALSE;
3957+
--buf->b_locked;
39563958

39573959
# ifdef FEAT_EVAL
39583960
/* autocmds may abort script processing */
@@ -4139,11 +4141,6 @@ do_ecmd(
41394141
/* Assume success now */
41404142
retval = OK;
41414143

4142-
/*
4143-
* Reset cursor position, could be used by autocommands.
4144-
*/
4145-
check_cursor();
4146-
41474144
/*
41484145
* Check if we are editing the w_arg_idx file in the argument list.
41494146
*/

src/ex_docmd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7218,7 +7218,7 @@ ex_quit(exarg_T *eap)
72187218
/* Refuse to quit when locked or when the buffer in the last window is
72197219
* being closed (can only happen in autocommands). */
72207220
if (curbuf_locked() || (wp->w_buffer->b_nwindows == 1
7221-
&& wp->w_buffer->b_closing))
7221+
&& wp->w_buffer->b_locked > 0))
72227222
return;
72237223
#endif
72247224

@@ -7300,7 +7300,7 @@ ex_quit_all(exarg_T *eap)
73007300
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
73017301
/* Refuse to quit when locked or when the buffer in the last window is
73027302
* being closed (can only happen in autocommands). */
7303-
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
7303+
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
73047304
return;
73057305
#endif
73067306

@@ -7682,7 +7682,7 @@ ex_exit(exarg_T *eap)
76827682
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
76837683
/* Refuse to quit when locked or when the buffer in the last window is
76847684
* being closed (can only happen in autocommands). */
7685-
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
7685+
if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
76867686
return;
76877687
#endif
76887688

src/misc2.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,28 @@ get_cursor_rel_lnum(
504504
return retval;
505505
}
506506

507+
/*
508+
* Make sure "pos.lnum" and "pos.col" are valid in "buf".
509+
* This allows for the col to be on the NUL byte.
510+
*/
511+
void
512+
check_pos(buf_T *buf, pos_T *pos)
513+
{
514+
char_u *line;
515+
colnr_T len;
516+
517+
if (pos->lnum > buf->b_ml.ml_line_count)
518+
pos->lnum = buf->b_ml.ml_line_count;
519+
520+
if (pos->col > 0)
521+
{
522+
line = ml_get_buf(buf, pos->lnum, FALSE);
523+
len = (colnr_T)STRLEN(line);
524+
if (pos->col > len)
525+
pos->col = len;
526+
}
527+
}
528+
507529
/*
508530
* Make sure curwin->w_cursor.lnum is valid.
509531
*/

src/move.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,7 @@ onepage(int dir, long count)
25082508
foldAdjustCursor();
25092509
#endif
25102510
cursor_correct();
2511+
check_cursor_col();
25112512
if (retval == OK)
25122513
beginline(BL_SOL | BL_FIX);
25132514
curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL);

src/normal.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9485,7 +9485,10 @@ get_op_vcol(
94859485
#ifdef FEAT_MBYTE
94869486
/* prevent from moving onto a trail byte */
94879487
if (has_mbyte)
9488+
{
9489+
check_pos(curwin->w_buffer, &oap->end);
94889490
mb_adjustpos(curwin->w_buffer, &oap->end);
9491+
}
94899492
#endif
94909493

94919494
getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);

src/ops.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4741,6 +4741,7 @@ fex_format(
47414741
int use_sandbox = was_set_insecurely((char_u *)"formatexpr",
47424742
OPT_LOCAL);
47434743
int r;
4744+
char_u *fex;
47444745

47454746
/*
47464747
* Set v:lnum to the first line number and v:count to the number of lines.
@@ -4750,16 +4751,22 @@ fex_format(
47504751
set_vim_var_nr(VV_COUNT, count);
47514752
set_vim_var_char(c);
47524753

4754+
/* Make a copy, the option could be changed while calling it. */
4755+
fex = vim_strsave(curbuf->b_p_fex);
4756+
if (fex == NULL)
4757+
return 0;
4758+
47534759
/*
47544760
* Evaluate the function.
47554761
*/
47564762
if (use_sandbox)
47574763
++sandbox;
4758-
r = (int)eval_to_number(curbuf->b_p_fex);
4764+
r = (int)eval_to_number(fex);
47594765
if (use_sandbox)
47604766
--sandbox;
47614767

47624768
set_vim_var_string(VV_CHAR, NULL, -1);
4769+
vim_free(fex);
47634770

47644771
return r;
47654772
}

0 commit comments

Comments
 (0)