mirror of
https://github.com/vim/vim.git
synced 2025-09-17 02:48:10 -04:00
patch 9.0.0965: using one window for executing autocommands is insufficient
Problem: Using one window for executing autocommands is insufficient. Solution: Use up to five windows for executing autocommands.
This commit is contained in:
parent
74a694dbe2
commit
e76062c078
115
src/autocmd.c
115
src/autocmd.c
@ -629,27 +629,51 @@ do_augroup(char_u *arg, int del_group)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
autocmd_init(void)
|
||||
{
|
||||
CLEAR_FIELD(aucmd_win);
|
||||
}
|
||||
|
||||
#if defined(EXITFREE) || defined(PROTO)
|
||||
void
|
||||
free_all_autocmds(void)
|
||||
{
|
||||
int i;
|
||||
char_u *s;
|
||||
|
||||
for (current_augroup = -1; current_augroup < augroups.ga_len;
|
||||
++current_augroup)
|
||||
do_autocmd(NULL, (char_u *)"", TRUE);
|
||||
|
||||
for (i = 0; i < augroups.ga_len; ++i)
|
||||
for (int i = 0; i < augroups.ga_len; ++i)
|
||||
{
|
||||
s = ((char_u **)(augroups.ga_data))[i];
|
||||
if (s != get_deleted_augroup())
|
||||
vim_free(s);
|
||||
}
|
||||
ga_clear(&augroups);
|
||||
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used)
|
||||
{
|
||||
aucmd_win[i].auc_win_used = FALSE;
|
||||
win_remove(aucmd_win[i].auc_win, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return TRUE if "win" is an active entry in aucmd_win[].
|
||||
*/
|
||||
int
|
||||
is_aucmd_win(win_T *win)
|
||||
{
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used && aucmd_win[i].auc_win == win)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the event number for event name "start".
|
||||
* Return NUM_EVENTS if the event name was not found.
|
||||
@ -1438,8 +1462,16 @@ ex_doautoall(exarg_T *eap)
|
||||
if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
|
||||
continue;
|
||||
|
||||
// find a window for this buffer and save some values
|
||||
// Find a window for this buffer and save some values.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf != buf)
|
||||
{
|
||||
// Failed to find a window for this buffer. Better not execute
|
||||
// autocommands then.
|
||||
retval = FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
set_bufref(&bufref, buf);
|
||||
|
||||
// execute the autocommands for this buffer
|
||||
@ -1449,7 +1481,7 @@ ex_doautoall(exarg_T *eap)
|
||||
// Execute the modeline settings, but don't set window-local
|
||||
// options if we are using the current window for another
|
||||
// buffer.
|
||||
do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
|
||||
do_modelines(is_aucmd_win(curwin) ? OPT_NOWIN : 0);
|
||||
|
||||
// restore the current window
|
||||
aucmd_restbuf(&aco);
|
||||
@ -1490,8 +1522,9 @@ check_nomodeline(char_u **argp)
|
||||
/*
|
||||
* Prepare for executing autocommands for (hidden) buffer "buf".
|
||||
* Search for a visible window containing the current buffer. If there isn't
|
||||
* one then use "aucmd_win".
|
||||
* one then use an entry in "aucmd_win[]".
|
||||
* Set "curbuf" and "curwin" to match "buf".
|
||||
* When this fails "curbuf" is not equal "buf".
|
||||
*/
|
||||
void
|
||||
aucmd_prepbuf(
|
||||
@ -1512,18 +1545,29 @@ aucmd_prepbuf(
|
||||
if (win->w_buffer == buf)
|
||||
break;
|
||||
|
||||
// Allocate "aucmd_win" when needed. If this fails (out of memory) fall
|
||||
// back to using the current window.
|
||||
if (win == NULL && aucmd_win == NULL)
|
||||
// Allocate a window when needed.
|
||||
win_T *auc_win = NULL;
|
||||
int auc_idx = AUCMD_WIN_COUNT;
|
||||
if (win == NULL)
|
||||
{
|
||||
aucmd_win = win_alloc_popup_win();
|
||||
if (aucmd_win == NULL)
|
||||
win = curwin;
|
||||
for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; ++auc_idx)
|
||||
if (!aucmd_win[auc_idx].auc_win_used)
|
||||
{
|
||||
auc_win = win_alloc_popup_win();
|
||||
if (auc_win != NULL)
|
||||
{
|
||||
aucmd_win[auc_idx].auc_win = auc_win;
|
||||
aucmd_win[auc_idx].auc_win_used = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// If this fails (out of memory or using all AUCMD_WIN_COUNT
|
||||
// entries) then we can't reliable execute the autocmd, return with
|
||||
// "curbuf" unequal "buf".
|
||||
if (auc_win == NULL)
|
||||
return;
|
||||
}
|
||||
if (win == NULL && aucmd_win_used)
|
||||
// Strange recursive autocommand, fall back to using the current
|
||||
// window. Expect a few side effects...
|
||||
win = curwin;
|
||||
|
||||
aco->save_curwin_id = curwin->w_id;
|
||||
aco->save_curbuf = curbuf;
|
||||
@ -1533,24 +1577,23 @@ aucmd_prepbuf(
|
||||
// There is a window for "buf" in the current tab page, make it the
|
||||
// curwin. This is preferred, it has the least side effects (esp. if
|
||||
// "buf" is curbuf).
|
||||
aco->use_aucmd_win = FALSE;
|
||||
aco->use_aucmd_win_idx = -1;
|
||||
curwin = win;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is no window for "buf", use "aucmd_win". To minimize the side
|
||||
// There is no window for "buf", use "auc_win". To minimize the side
|
||||
// effects, insert it in the current tab page.
|
||||
// Anything related to a window (e.g., setting folds) may have
|
||||
// unexpected results.
|
||||
aco->use_aucmd_win = TRUE;
|
||||
aucmd_win_used = TRUE;
|
||||
aco->use_aucmd_win_idx = auc_idx;
|
||||
|
||||
win_init_popup_win(aucmd_win, buf);
|
||||
win_init_popup_win(auc_win, buf);
|
||||
|
||||
aco->globaldir = globaldir;
|
||||
globaldir = NULL;
|
||||
|
||||
// Split the current window, put the aucmd_win in the upper half.
|
||||
// Split the current window, put the auc_win in the upper half.
|
||||
// We don't want the BufEnter or WinEnter autocommands.
|
||||
block_autocmds();
|
||||
make_snapshot(SNAP_AUCMD_IDX);
|
||||
@ -1565,7 +1608,7 @@ aucmd_prepbuf(
|
||||
|
||||
// no redrawing and don't set the window title
|
||||
++RedrawingDisabled;
|
||||
(void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
|
||||
(void)win_split_ins(0, WSP_TOP, auc_win, 0);
|
||||
--RedrawingDisabled;
|
||||
(void)win_comp_pos(); // recompute window positions
|
||||
p_ea = save_ea;
|
||||
@ -1573,7 +1616,7 @@ aucmd_prepbuf(
|
||||
p_acd = save_acd;
|
||||
#endif
|
||||
unblock_autocmds();
|
||||
curwin = aucmd_win;
|
||||
curwin = auc_win;
|
||||
}
|
||||
curbuf = buf;
|
||||
aco->new_curwin_id = curwin->w_id;
|
||||
@ -1595,24 +1638,26 @@ aucmd_restbuf(
|
||||
int dummy;
|
||||
win_T *save_curwin;
|
||||
|
||||
if (aco->use_aucmd_win)
|
||||
if (aco->use_aucmd_win_idx >= 0)
|
||||
{
|
||||
win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win;
|
||||
|
||||
--curbuf->b_nwindows;
|
||||
// Find "aucmd_win", it can't be closed, but it may be in another tab
|
||||
// Find "awp", it can't be closed, but it may be in another tab
|
||||
// page. Do not trigger autocommands here.
|
||||
block_autocmds();
|
||||
if (curwin != aucmd_win)
|
||||
if (curwin != awp)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
win_T *wp;
|
||||
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||
{
|
||||
if (wp == aucmd_win)
|
||||
if (wp == awp)
|
||||
{
|
||||
if (tp != curtab)
|
||||
goto_tabpage_tp(tp, TRUE, TRUE);
|
||||
win_goto(aucmd_win);
|
||||
win_goto(awp);
|
||||
goto win_found;
|
||||
}
|
||||
}
|
||||
@ -1622,7 +1667,7 @@ win_found:
|
||||
// Remove the window and frame from the tree of frames.
|
||||
(void)winframe_remove(curwin, &dummy, NULL);
|
||||
win_remove(curwin, NULL);
|
||||
aucmd_win_used = FALSE;
|
||||
aucmd_win[aco->use_aucmd_win_idx].auc_win_used = FALSE;
|
||||
last_status(FALSE); // may need to remove last status line
|
||||
|
||||
if (!valid_tabpage_win(curtab))
|
||||
@ -1646,8 +1691,8 @@ win_found:
|
||||
#endif
|
||||
prevwin = win_find_by_id(aco->save_prevwin_id);
|
||||
#ifdef FEAT_EVAL
|
||||
vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
|
||||
hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
|
||||
vars_clear(&awp->w_vars->dv_hashtab); // free all w: variables
|
||||
hash_init(&awp->w_vars->dv_hashtab); // re-use the hashtab
|
||||
#endif
|
||||
vim_free(globaldir);
|
||||
globaldir = aco->globaldir;
|
||||
@ -1664,11 +1709,9 @@ win_found:
|
||||
#if defined(FEAT_GUI)
|
||||
if (gui.in_use)
|
||||
{
|
||||
// Hide the scrollbars from the aucmd_win and update.
|
||||
gui_mch_enable_scrollbar(
|
||||
&aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
|
||||
gui_mch_enable_scrollbar(
|
||||
&aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
|
||||
// Hide the scrollbars from the "awp" and update.
|
||||
gui_mch_enable_scrollbar(&awp->w_scrollbars[SBAR_LEFT], FALSE);
|
||||
gui_mch_enable_scrollbar(&awp->w_scrollbars[SBAR_RIGHT], FALSE);
|
||||
gui_may_update_scrollbars();
|
||||
}
|
||||
#endif
|
||||
|
43
src/buffer.c
43
src/buffer.c
@ -150,11 +150,15 @@ buffer_ensure_loaded(buf_T *buf)
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
// Make sure the buffer is in a window. If not then skip it.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (swap_exists_action != SEA_READONLY)
|
||||
swap_exists_action = SEA_NONE;
|
||||
open_buffer(FALSE, NULL, 0);
|
||||
aucmd_restbuf(&aco);
|
||||
if (curbuf == buf)
|
||||
{
|
||||
if (swap_exists_action != SEA_READONLY)
|
||||
swap_exists_action = SEA_NONE;
|
||||
open_buffer(FALSE, NULL, 0);
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -361,21 +365,26 @@ open_buffer(
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
// Go to the buffer that was opened.
|
||||
// Go to the buffer that was opened, make sure it is in a window.
|
||||
// If not then skip it.
|
||||
aucmd_prepbuf(&aco, old_curbuf.br_buf);
|
||||
do_modelines(0);
|
||||
curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
|
||||
if (curbuf == old_curbuf.br_buf)
|
||||
{
|
||||
do_modelines(0);
|
||||
curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
|
||||
|
||||
if ((flags & READ_NOWINENTER) == 0)
|
||||
if ((flags & READ_NOWINENTER) == 0)
|
||||
#ifdef FEAT_EVAL
|
||||
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
|
||||
curbuf, &retval);
|
||||
apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL,
|
||||
FALSE, curbuf, &retval);
|
||||
#else
|
||||
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
|
||||
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL,
|
||||
FALSE, curbuf);
|
||||
#endif
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5942,8 +5951,14 @@ buf_contents_changed(buf_T *buf)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
// Set curwin/curbuf to buf and save a few things.
|
||||
aucmd_prepbuf(&aco, newbuf);
|
||||
if (curbuf != newbuf)
|
||||
{
|
||||
// Failed to find a window for "newbuf".
|
||||
wipe_buffer(newbuf, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ml_open(curbuf) == OK
|
||||
&& readfile(buf->b_ffname, buf->b_fname,
|
||||
|
@ -802,8 +802,15 @@ buf_write(
|
||||
if (fname == buf->b_sfname)
|
||||
buf_fname_s = TRUE;
|
||||
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
// Set curwin/curbuf to buf and save a few things.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf != buf)
|
||||
{
|
||||
// Could not find a window for "buf". Doing more might cause
|
||||
// problems, better bail out.
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
set_bufref(&bufref, buf);
|
||||
|
||||
if (append)
|
||||
@ -2592,23 +2599,26 @@ nofail:
|
||||
|
||||
// Apply POST autocommands.
|
||||
// Careful: The autocommands may call buf_write() recursively!
|
||||
// Only do this when a window was found for "buf".
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf == buf)
|
||||
{
|
||||
if (append)
|
||||
apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else if (filtering)
|
||||
apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else if (reset_changed && whole)
|
||||
apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else
|
||||
apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
|
||||
if (append)
|
||||
apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else if (filtering)
|
||||
apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else if (reset_changed && whole)
|
||||
apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
else
|
||||
apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
|
||||
FALSE, curbuf, eap);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
if (aborting()) // autocmds may abort script processing
|
||||
|
@ -2872,8 +2872,14 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
|
||||
|
||||
buffer->b_p_ma = TRUE;
|
||||
|
||||
// set curbuf to be our buf, temporarily
|
||||
// Set curbuf to "buffer", temporarily.
|
||||
aucmd_prepbuf(&aco, buffer);
|
||||
if (curbuf != buffer)
|
||||
{
|
||||
// Could not find a window for this buffer, the following might cause
|
||||
// trouble, better bail out.
|
||||
return;
|
||||
}
|
||||
|
||||
u_sync(TRUE);
|
||||
// ignore undo failure, undo is not very useful here
|
||||
|
@ -2786,8 +2786,12 @@ ex_diffgetput(exarg_T *eap)
|
||||
idx_to = idx_other;
|
||||
// Need to make the other buffer the current buffer to be able to make
|
||||
// changes in it.
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
// Set curwin/curbuf to buf and save a few things.
|
||||
aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
|
||||
if (curbuf != curtab->tp_diffbuf[idx_other])
|
||||
// Could not find a window for this buffer, the rest is likely to
|
||||
// fail.
|
||||
goto theend;
|
||||
}
|
||||
|
||||
// May give the warning for a changed buffer here, which can trigger the
|
||||
|
@ -5084,9 +5084,10 @@ garbage_collect(int testing)
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
if (aucmd_win != NULL)
|
||||
abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
|
||||
NULL, NULL);
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used)
|
||||
abort = abort || set_ref_in_item(
|
||||
&aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
FOR_ALL_POPUPWINS(wp)
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
|
||||
|
@ -136,6 +136,8 @@ typedef struct {
|
||||
*
|
||||
* Information is saved in "cob" and MUST be restored by calling
|
||||
* change_other_buffer_restore().
|
||||
*
|
||||
* If this fails then "curbuf" will not be equal to "buf".
|
||||
*/
|
||||
static void
|
||||
change_other_buffer_prepare(cob_T *cob, buf_T *buf)
|
||||
@ -156,7 +158,8 @@ change_other_buffer_prepare(cob_T *cob, buf_T *buf)
|
||||
// curwin->w_buffer differ from "curbuf", use the autocmd window.
|
||||
curbuf = curwin->w_buffer;
|
||||
aucmd_prepbuf(&cob->cob_aco, buf);
|
||||
cob->cob_using_aco = TRUE;
|
||||
if (curbuf == buf)
|
||||
cob->cob_using_aco = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4761,13 +4761,16 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
// set curbuf to be our buf, temporarily
|
||||
// Set curbuf to be our buf, temporarily.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf == buf)
|
||||
{
|
||||
// Only when it worked to set "curbuf".
|
||||
set_option_from_tv(varname + 1, varp);
|
||||
|
||||
set_option_from_tv(varname + 1, varp);
|
||||
|
||||
// reset notion of buffer
|
||||
aucmd_restbuf(&aco);
|
||||
// reset notion of buffer
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1064,7 +1064,7 @@ f_win_gettype(typval_T *argvars, typval_T *rettv)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (wp == aucmd_win)
|
||||
if (is_aucmd_win(wp))
|
||||
rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
|
||||
#if defined(FEAT_QUICKFIX)
|
||||
else if (wp->w_p_pvw)
|
||||
|
@ -705,9 +705,12 @@ ex_listdo(exarg_T *eap)
|
||||
else
|
||||
{
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
|
||||
if (curbuf == buf)
|
||||
{
|
||||
apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
|
||||
buf->b_fname, TRUE, buf);
|
||||
aucmd_restbuf(&aco);
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
|
||||
// start over, in case autocommands messed things up.
|
||||
|
@ -6050,7 +6050,7 @@ ex_win_close(
|
||||
buf_T *buf = win->w_buffer;
|
||||
|
||||
// Never close the autocommand window.
|
||||
if (win == aucmd_win)
|
||||
if (is_aucmd_win(win))
|
||||
{
|
||||
emsg(_(e_cannot_close_autocmd_or_popup_window));
|
||||
return;
|
||||
|
@ -4369,8 +4369,14 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
|
||||
int flags = READ_NEW;
|
||||
int prepped = OK;
|
||||
|
||||
// set curwin/curbuf for "buf" and save some things
|
||||
// Set curwin/curbuf for "buf" and save some things.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf != buf)
|
||||
{
|
||||
// Failed to find a window for "buf", it is dangerous to continue,
|
||||
// better bail out.
|
||||
return;
|
||||
}
|
||||
|
||||
// Unless reload_options is set, we only want to read the text from the
|
||||
// file, not reset the syntax highlighting, clear marks, diff status, etc.
|
||||
|
@ -977,8 +977,18 @@ EXTERN win_T *prevwin INIT(= NULL); // previous window
|
||||
|
||||
EXTERN win_T *curwin; // currently active window
|
||||
|
||||
EXTERN win_T *aucmd_win; // window used in aucmd_prepbuf()
|
||||
EXTERN int aucmd_win_used INIT(= FALSE); // aucmd_win is being used
|
||||
// When executing autocommands for a buffer that is not in any window, a
|
||||
// special window is created to handle the side effects. When autocommands
|
||||
// nest we may need more than one. Allow for up to five, if more are needed
|
||||
// something crazy is happening.
|
||||
#define AUCMD_WIN_COUNT 5
|
||||
|
||||
typedef struct {
|
||||
win_T *auc_win; // window used in aucmd_prepbuf()
|
||||
int auc_win_used; // this auc_win is being used
|
||||
} aucmdwin_T;
|
||||
|
||||
EXTERN aucmdwin_T aucmd_win[AUCMD_WIN_COUNT];
|
||||
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
EXTERN win_T *first_popupwin; // first global popup window
|
||||
|
@ -1869,18 +1869,21 @@ Set(vimbuf, ...)
|
||||
{
|
||||
aco_save_T aco;
|
||||
|
||||
/* set curwin/curbuf for "vimbuf" and save some things */
|
||||
/* Set curwin/curbuf for "vimbuf" and save some things. */
|
||||
aucmd_prepbuf(&aco, vimbuf);
|
||||
|
||||
if (u_savesub(lnum) == OK)
|
||||
if (curbuf == vimbuf)
|
||||
{
|
||||
ml_replace(lnum, (char_u *)line, TRUE);
|
||||
changed_bytes(lnum, 0);
|
||||
}
|
||||
/* Only when a window was found. */
|
||||
if (u_savesub(lnum) == OK)
|
||||
{
|
||||
ml_replace(lnum, (char_u *)line, TRUE);
|
||||
changed_bytes(lnum, 0);
|
||||
}
|
||||
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf" invalid! */
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf" invalid! */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1921,17 +1924,21 @@ Delete(vimbuf, ...)
|
||||
|
||||
/* set curwin/curbuf for "vimbuf" and save some things */
|
||||
aucmd_prepbuf(&aco, vimbuf);
|
||||
|
||||
if (u_savedel(lnum, 1) == OK)
|
||||
if (curbuf == vimbuf)
|
||||
{
|
||||
ml_delete(lnum);
|
||||
check_cursor();
|
||||
deleted_lines_mark(lnum, 1L);
|
||||
}
|
||||
/* Only when a window was found. */
|
||||
if (u_savedel(lnum, 1) == OK)
|
||||
{
|
||||
ml_delete(lnum);
|
||||
check_cursor();
|
||||
deleted_lines_mark(lnum, 1L);
|
||||
}
|
||||
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf" invalid! */
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf"
|
||||
* invalid! */
|
||||
}
|
||||
|
||||
update_curbuf(UPD_VALID);
|
||||
}
|
||||
@ -1963,16 +1970,19 @@ Append(vimbuf, ...)
|
||||
|
||||
/* set curwin/curbuf for "vimbuf" and save some things */
|
||||
aucmd_prepbuf(&aco, vimbuf);
|
||||
|
||||
if (u_inssub(lnum + 1) == OK)
|
||||
if (curbuf == vimbuf)
|
||||
{
|
||||
ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
|
||||
appended_lines_mark(lnum, 1L);
|
||||
}
|
||||
/* Only when a window for "vimbuf" was found. */
|
||||
if (u_inssub(lnum + 1) == OK)
|
||||
{
|
||||
ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
|
||||
appended_lines_mark(lnum, 1L);
|
||||
}
|
||||
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf" invalid! */
|
||||
/* restore curwin/curbuf and a few other things */
|
||||
aucmd_restbuf(&aco);
|
||||
/* Careful: autocommands may have made "vimbuf" invalid! */
|
||||
}
|
||||
|
||||
update_curbuf(UPD_VALID);
|
||||
}
|
||||
|
@ -5283,8 +5283,11 @@ BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
|
||||
VimTryStart();
|
||||
// Using aucmd_*: autocommands will be executed by rename_buffer
|
||||
aucmd_prepbuf(&aco, self->buf);
|
||||
ren_ret = rename_buffer(val);
|
||||
aucmd_restbuf(&aco);
|
||||
if (curbuf == self->buf)
|
||||
{
|
||||
ren_ret = rename_buffer(val);
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
Py_XDECREF(todecref);
|
||||
if (VimTryEnd())
|
||||
return -1;
|
||||
|
@ -1371,21 +1371,24 @@ set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
|
||||
|
||||
if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
|
||||
{
|
||||
// set curwin/curbuf for "buf" and save some things
|
||||
// Set curwin/curbuf for "buf" and save some things.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
if (u_savesub(n) == OK)
|
||||
if (curbuf == buf)
|
||||
{
|
||||
ml_replace(n, (char_u *)line, TRUE);
|
||||
changed();
|
||||
// Only when it worked to set "curbuf".
|
||||
if (u_savesub(n) == OK)
|
||||
{
|
||||
ml_replace(n, (char_u *)line, TRUE);
|
||||
changed();
|
||||
#ifdef SYNTAX_HL
|
||||
syn_changed(n); // recompute syntax hl. for this line
|
||||
syn_changed(n); // recompute syntax hl. for this line
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
}
|
||||
|
||||
update_curbuf(UPD_NOT_VALID);
|
||||
}
|
||||
@ -1415,24 +1418,27 @@ buffer_delete(VALUE self, VALUE num)
|
||||
|
||||
if (n > 0 && n <= buf->b_ml.ml_line_count)
|
||||
{
|
||||
// set curwin/curbuf for "buf" and save some things
|
||||
// Set curwin/curbuf for "buf" and save some things.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
if (u_savedel(n, 1) == OK)
|
||||
if (curbuf == buf)
|
||||
{
|
||||
ml_delete(n);
|
||||
// Only when it worked to set "curbuf".
|
||||
if (u_savedel(n, 1) == OK)
|
||||
{
|
||||
ml_delete(n);
|
||||
|
||||
// Changes to non-active buffers should properly refresh
|
||||
// SegPhault - 01/09/05
|
||||
deleted_lines_mark(n, 1L);
|
||||
// Changes to non-active buffers should properly refresh
|
||||
// SegPhault - 01/09/05
|
||||
deleted_lines_mark(n, 1L);
|
||||
|
||||
changed();
|
||||
changed();
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
|
||||
update_curbuf(UPD_NOT_VALID);
|
||||
}
|
||||
else
|
||||
@ -1458,22 +1464,25 @@ buffer_append(VALUE self, VALUE num, VALUE str)
|
||||
{
|
||||
// set curwin/curbuf for "buf" and save some things
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
if (u_inssub(n + 1) == OK)
|
||||
if (curbuf == buf)
|
||||
{
|
||||
ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
|
||||
// Only when it worked to set "curbuf".
|
||||
if (u_inssub(n + 1) == OK)
|
||||
{
|
||||
ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
|
||||
|
||||
// Changes to non-active buffers should properly refresh screen
|
||||
// SegPhault - 12/20/04
|
||||
appended_lines_mark(n, 1L);
|
||||
// Changes to non-active buffers should properly refresh screen
|
||||
// SegPhault - 12/20/04
|
||||
appended_lines_mark(n, 1L);
|
||||
|
||||
changed();
|
||||
changed();
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// Careful: autocommands may have made "buf" invalid!
|
||||
|
||||
update_curbuf(UPD_NOT_VALID);
|
||||
}
|
||||
else
|
||||
|
@ -123,6 +123,8 @@ main
|
||||
#endif
|
||||
params.window_count = -1;
|
||||
|
||||
autocmd_init();
|
||||
|
||||
#ifdef FEAT_RUBY
|
||||
{
|
||||
int ruby_stack_start;
|
||||
|
@ -4490,27 +4490,30 @@ mch_call_shell_terminal(
|
||||
|
||||
// Find a window to make "buf" curbuf.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
clear_oparg(&oa);
|
||||
while (term_use_loop())
|
||||
if (curbuf == buf)
|
||||
{
|
||||
if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
|
||||
// Only when managed to find a window for "buf",
|
||||
clear_oparg(&oa);
|
||||
while (term_use_loop())
|
||||
{
|
||||
// If terminal_loop() returns OK we got a key that is handled
|
||||
// in Normal model. We don't do redrawing anyway.
|
||||
if (terminal_loop(TRUE) == OK)
|
||||
if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
|
||||
{
|
||||
// If terminal_loop() returns OK we got a key that is handled
|
||||
// in Normal model. We don't do redrawing anyway.
|
||||
if (terminal_loop(TRUE) == OK)
|
||||
normal_cmd(&oa, TRUE);
|
||||
}
|
||||
else
|
||||
normal_cmd(&oa, TRUE);
|
||||
}
|
||||
else
|
||||
normal_cmd(&oa, TRUE);
|
||||
retval = job->jv_exitval;
|
||||
ch_log(NULL, "system command finished");
|
||||
|
||||
job_unref(job);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
retval = job->jv_exitval;
|
||||
ch_log(NULL, "system command finished");
|
||||
|
||||
job_unref(job);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
|
||||
// Only require pressing Enter when redrawing, to avoid that system() gets
|
||||
// the hit-enter prompt even though it didn't output anything.
|
||||
|
@ -4878,27 +4878,30 @@ mch_call_shell_terminal(
|
||||
|
||||
// Find a window to make "buf" curbuf.
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
clear_oparg(&oa);
|
||||
while (term_use_loop())
|
||||
if (curbuf == buf)
|
||||
{
|
||||
if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
|
||||
// Only do this when a window was found for "buf".
|
||||
clear_oparg(&oa);
|
||||
while (term_use_loop())
|
||||
{
|
||||
// If terminal_loop() returns OK we got a key that is handled
|
||||
// in Normal model. We don't do redrawing anyway.
|
||||
if (terminal_loop(TRUE) == OK)
|
||||
if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
|
||||
{
|
||||
// If terminal_loop() returns OK we got a key that is handled
|
||||
// in Normal model. We don't do redrawing anyway.
|
||||
if (terminal_loop(TRUE) == OK)
|
||||
normal_cmd(&oa, TRUE);
|
||||
}
|
||||
else
|
||||
normal_cmd(&oa, TRUE);
|
||||
}
|
||||
else
|
||||
normal_cmd(&oa, TRUE);
|
||||
retval = job->jv_exitval;
|
||||
ch_log(NULL, "system command finished");
|
||||
|
||||
job_unref(job);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
retval = job->jv_exitval;
|
||||
ch_log(NULL, "system command finished");
|
||||
|
||||
job_unref(job);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
|
||||
wait_return(TRUE);
|
||||
do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
|
||||
|
@ -2,7 +2,9 @@
|
||||
void aubuflocal_remove(buf_T *buf);
|
||||
int au_has_group(char_u *name);
|
||||
void do_augroup(char_u *arg, int del_group);
|
||||
void autocmd_init(void);
|
||||
void free_all_autocmds(void);
|
||||
int is_aucmd_win(win_T *win);
|
||||
int check_ei(void);
|
||||
char_u *au_event_disable(char *what);
|
||||
void au_event_restore(char_u *old_ei);
|
||||
|
102
src/quickfix.c
102
src/quickfix.c
@ -4598,21 +4598,29 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
|
||||
// autocommands may cause trouble
|
||||
incr_quickfix_busy();
|
||||
|
||||
if (old_last == NULL)
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
qf_update_win_titlevar(qi);
|
||||
|
||||
qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
|
||||
++CHANGEDTICK(buf);
|
||||
|
||||
int do_fill = TRUE;
|
||||
if (old_last == NULL)
|
||||
{
|
||||
(void)qf_win_pos_update(qi, 0);
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf != buf)
|
||||
do_fill = FALSE; // failed to find a window for "buf"
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
if (do_fill)
|
||||
{
|
||||
qf_update_win_titlevar(qi);
|
||||
|
||||
qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
|
||||
++CHANGEDTICK(buf);
|
||||
|
||||
if (old_last == NULL)
|
||||
{
|
||||
(void)qf_win_pos_update(qi, 0);
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
|
||||
// Only redraw when added lines are visible. This avoids flickering
|
||||
@ -6395,12 +6403,15 @@ vgr_process_files(
|
||||
// need to be done (again). But not the window-local
|
||||
// options!
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (curbuf == buf)
|
||||
{
|
||||
#if defined(FEAT_SYN_HL)
|
||||
apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
|
||||
apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
|
||||
buf->b_fname, TRUE, buf);
|
||||
#endif
|
||||
do_modelines(OPT_NOWIN);
|
||||
aucmd_restbuf(&aco);
|
||||
do_modelines(OPT_NOWIN);
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6593,40 +6604,43 @@ load_dummy_buffer(
|
||||
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
aucmd_prepbuf(&aco, newbuf);
|
||||
|
||||
// Need to set the filename for autocommands.
|
||||
(void)setfname(curbuf, fname, NULL, FALSE);
|
||||
|
||||
// Create swap file now to avoid the ATTENTION message.
|
||||
check_need_swap(TRUE);
|
||||
|
||||
// Remove the "dummy" flag, otherwise autocommands may not
|
||||
// work.
|
||||
curbuf->b_flags &= ~BF_DUMMY;
|
||||
|
||||
newbuf_to_wipe.br_buf = NULL;
|
||||
readfile_result = readfile(fname, NULL,
|
||||
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
|
||||
NULL, READ_NEW | READ_DUMMY);
|
||||
--newbuf->b_locked;
|
||||
if (readfile_result == OK
|
||||
&& !got_int
|
||||
&& !(curbuf->b_flags & BF_NEW))
|
||||
if (curbuf == newbuf)
|
||||
{
|
||||
failed = FALSE;
|
||||
if (curbuf != newbuf)
|
||||
// Need to set the filename for autocommands.
|
||||
(void)setfname(curbuf, fname, NULL, FALSE);
|
||||
|
||||
// Create swap file now to avoid the ATTENTION message.
|
||||
check_need_swap(TRUE);
|
||||
|
||||
// Remove the "dummy" flag, otherwise autocommands may not
|
||||
// work.
|
||||
curbuf->b_flags &= ~BF_DUMMY;
|
||||
|
||||
newbuf_to_wipe.br_buf = NULL;
|
||||
readfile_result = readfile(fname, NULL,
|
||||
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
|
||||
NULL, READ_NEW | READ_DUMMY);
|
||||
--newbuf->b_locked;
|
||||
if (readfile_result == OK
|
||||
&& !got_int
|
||||
&& !(curbuf->b_flags & BF_NEW))
|
||||
{
|
||||
// Bloody autocommands changed the buffer! Can happen when
|
||||
// using netrw and editing a remote file. Use the current
|
||||
// buffer instead, delete the dummy one after restoring the
|
||||
// window stuff.
|
||||
set_bufref(&newbuf_to_wipe, newbuf);
|
||||
newbuf = curbuf;
|
||||
failed = FALSE;
|
||||
if (curbuf != newbuf)
|
||||
{
|
||||
// Bloody autocommands changed the buffer! Can happen when
|
||||
// using netrw and editing a remote file. Use the current
|
||||
// buffer instead, delete the dummy one after restoring the
|
||||
// window stuff.
|
||||
set_bufref(&newbuf_to_wipe, newbuf);
|
||||
newbuf = curbuf;
|
||||
}
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
|
||||
wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
|
||||
|
||||
|
35
src/screen.c
35
src/screen.c
@ -2369,7 +2369,6 @@ screenalloc(int doclear)
|
||||
u8char_T *new_ScreenLinesUC = NULL;
|
||||
u8char_T *new_ScreenLinesC[MAX_MCO];
|
||||
schar_T *new_ScreenLines2 = NULL;
|
||||
int i;
|
||||
sattr_T *new_ScreenAttrs;
|
||||
colnr_T *new_ScreenCols;
|
||||
unsigned *new_LineOffset;
|
||||
@ -2438,8 +2437,9 @@ retry:
|
||||
*/
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||
win_free_lsize(wp);
|
||||
if (aucmd_win != NULL)
|
||||
win_free_lsize(aucmd_win);
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used)
|
||||
win_free_lsize(aucmd_win[i].auc_win);
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
// global popup windows
|
||||
FOR_ALL_POPUPWINS(wp)
|
||||
@ -2455,7 +2455,7 @@ retry:
|
||||
if (enc_utf8)
|
||||
{
|
||||
new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
|
||||
(Rows + 1) * Columns);
|
||||
}
|
||||
@ -2482,9 +2482,14 @@ retry:
|
||||
goto give_up;
|
||||
}
|
||||
}
|
||||
if (aucmd_win != NULL && aucmd_win->w_lines == NULL
|
||||
&& win_alloc_lines(aucmd_win) == FAIL)
|
||||
outofmem = TRUE;
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used
|
||||
&& aucmd_win[i].auc_win->w_lines == NULL
|
||||
&& win_alloc_lines(aucmd_win[i].auc_win) == FAIL)
|
||||
{
|
||||
outofmem = TRUE;
|
||||
break;
|
||||
}
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
// global popup windows
|
||||
FOR_ALL_POPUPWINS(wp)
|
||||
@ -2505,11 +2510,15 @@ retry:
|
||||
|
||||
give_up:
|
||||
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
int found_null = FALSE;
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
if (new_ScreenLinesC[i] == NULL)
|
||||
{
|
||||
found_null = TRUE;
|
||||
break;
|
||||
}
|
||||
if (new_ScreenLines == NULL
|
||||
|| (enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
|
||||
|| (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
|
||||
|| (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
|
||||
|| new_ScreenAttrs == NULL
|
||||
|| new_ScreenCols == NULL
|
||||
@ -2534,7 +2543,7 @@ give_up:
|
||||
}
|
||||
VIM_CLEAR(new_ScreenLines);
|
||||
VIM_CLEAR(new_ScreenLinesUC);
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
VIM_CLEAR(new_ScreenLinesC[i]);
|
||||
VIM_CLEAR(new_ScreenLines2);
|
||||
VIM_CLEAR(new_ScreenAttrs);
|
||||
@ -2571,7 +2580,7 @@ give_up:
|
||||
{
|
||||
(void)vim_memset(new_ScreenLinesUC + new_row * Columns,
|
||||
0, (size_t)Columns * sizeof(u8char_T));
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
(void)vim_memset(new_ScreenLinesC[i]
|
||||
+ new_row * Columns,
|
||||
0, (size_t)Columns * sizeof(u8char_T));
|
||||
@ -2603,7 +2612,7 @@ give_up:
|
||||
mch_memmove(new_ScreenLinesUC + new_LineOffset[new_row],
|
||||
ScreenLinesUC + LineOffset[old_row],
|
||||
(size_t)len * sizeof(u8char_T));
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
mch_memmove(new_ScreenLinesC[i]
|
||||
+ new_LineOffset[new_row],
|
||||
ScreenLinesC[i] + LineOffset[old_row],
|
||||
@ -2636,7 +2645,7 @@ give_up:
|
||||
// NOTE: this may result in all pointers to become NULL.
|
||||
ScreenLines = new_ScreenLines;
|
||||
ScreenLinesUC = new_ScreenLinesUC;
|
||||
for (i = 0; i < p_mco; ++i)
|
||||
for (int i = 0; i < p_mco; ++i)
|
||||
ScreenLinesC[i] = new_ScreenLinesC[i];
|
||||
Screen_mco = p_mco;
|
||||
ScreenLines2 = new_ScreenLines2;
|
||||
|
@ -4160,7 +4160,7 @@ typedef int vimmenu_T;
|
||||
typedef struct
|
||||
{
|
||||
buf_T *save_curbuf; // saved curbuf
|
||||
int use_aucmd_win; // using aucmd_win
|
||||
int use_aucmd_win_idx; // index in aucmd_win[] if >= 0
|
||||
int save_curwin_id; // ID of saved curwin
|
||||
int new_curwin_id; // ID of new curwin
|
||||
int save_prevwin_id; // ID of saved prevwin
|
||||
|
@ -2232,10 +2232,13 @@ set_termname(char_u *term)
|
||||
if (curbuf->b_ml.ml_mfp != NULL)
|
||||
{
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
|
||||
if (curbuf == buf)
|
||||
{
|
||||
apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
|
||||
curbuf);
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
// restore curwin/curbuf and a few other things
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3560,15 +3560,18 @@ term_after_channel_closed(term_T *term)
|
||||
// ++close or term_finish == "close"
|
||||
ch_log(NULL, "terminal job finished, closing window");
|
||||
aucmd_prepbuf(&aco, term->tl_buffer);
|
||||
// Avoid closing the window if we temporarily use it.
|
||||
if (curwin == aucmd_win)
|
||||
do_set_w_closing = TRUE;
|
||||
if (do_set_w_closing)
|
||||
curwin->w_closing = TRUE;
|
||||
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
|
||||
if (do_set_w_closing)
|
||||
curwin->w_closing = FALSE;
|
||||
aucmd_restbuf(&aco);
|
||||
if (curbuf == term->tl_buffer)
|
||||
{
|
||||
// Avoid closing the window if we temporarily use it.
|
||||
if (is_aucmd_win(curwin))
|
||||
do_set_w_closing = TRUE;
|
||||
if (do_set_w_closing)
|
||||
curwin->w_closing = TRUE;
|
||||
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
|
||||
if (do_set_w_closing)
|
||||
curwin->w_closing = FALSE;
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
if (pwin != NULL)
|
||||
popup_close_with_retval(pwin, 0);
|
||||
|
@ -4068,4 +4068,27 @@ func Test_autocmd_split_dummy()
|
||||
call delete('Xerr')
|
||||
endfunc
|
||||
|
||||
" This was crashing because there was only one window to execute autocommands
|
||||
" in.
|
||||
func Test_autocmd_nested_setbufvar()
|
||||
CheckFeature python3
|
||||
|
||||
set hidden
|
||||
edit Xaaa
|
||||
edit Xbbb
|
||||
call setline(1, 'bar')
|
||||
enew
|
||||
au BufWriteCmd Xbbb ++nested call setbufvar('Xaaa', '&ft', 'foo') | bw! Xaaa
|
||||
au FileType foo call py3eval('vim.current.buffer.options["cindent"]')
|
||||
wall
|
||||
|
||||
au! BufWriteCmd
|
||||
au! FileType foo
|
||||
set nohidden
|
||||
call delete('Xaaa')
|
||||
call delete('Xbbb')
|
||||
%bwipe!
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@ -695,6 +695,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
965,
|
||||
/**/
|
||||
964,
|
||||
/**/
|
||||
|
27
src/window.c
27
src/window.c
@ -1362,7 +1362,7 @@ win_split_ins(
|
||||
win_equal(wp, TRUE,
|
||||
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
|
||||
: dir == 'h' ? 'b' : 'v');
|
||||
else if (*p_spk != 'c' && wp != aucmd_win)
|
||||
else if (*p_spk != 'c' && !is_aucmd_win(wp))
|
||||
win_fix_scroll(FALSE);
|
||||
|
||||
// Don't change the window height/width to 'winheight' / 'winwidth' if a
|
||||
@ -1962,7 +1962,7 @@ win_equal(
|
||||
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
|
||||
topframe, dir, 0, tabline_height(),
|
||||
(int)Columns, topframe->fr_height);
|
||||
if (*p_spk != 'c' && next_curwin != aucmd_win)
|
||||
if (*p_spk != 'c' && !is_aucmd_win(next_curwin))
|
||||
win_fix_scroll(TRUE);
|
||||
}
|
||||
|
||||
@ -2426,7 +2426,7 @@ close_windows(
|
||||
|
||||
/*
|
||||
* Return TRUE if the current window is the only window that exists (ignoring
|
||||
* "aucmd_win").
|
||||
* "aucmd_win[]").
|
||||
* Returns FALSE if there is a window, possibly in another tab page.
|
||||
*/
|
||||
static int
|
||||
@ -2436,7 +2436,7 @@ last_window(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if there is only one window other than "aucmd_win" in the
|
||||
* Return TRUE if there is only one window other than "aucmd_win[]" in the
|
||||
* current tab page.
|
||||
*/
|
||||
int
|
||||
@ -2447,7 +2447,7 @@ one_window(void)
|
||||
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
{
|
||||
if (wp != aucmd_win)
|
||||
if (!is_aucmd_win(wp))
|
||||
{
|
||||
if (seen_one)
|
||||
return FALSE;
|
||||
@ -2588,7 +2588,7 @@ win_close(win_T *win, int free_buf)
|
||||
emsg(_(e_cannot_close_autocmd_or_popup_window));
|
||||
return FAIL;
|
||||
}
|
||||
if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
|
||||
if ((is_aucmd_win(firstwin) || is_aucmd_win(lastwin)) && one_window())
|
||||
{
|
||||
emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
|
||||
return FAIL;
|
||||
@ -3292,11 +3292,12 @@ win_free_all(void)
|
||||
while (first_tabpage->tp_next != NULL)
|
||||
tabpage_close(TRUE);
|
||||
|
||||
if (aucmd_win != NULL)
|
||||
{
|
||||
(void)win_free_mem(aucmd_win, &dummy, NULL);
|
||||
aucmd_win = NULL;
|
||||
}
|
||||
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
|
||||
if (aucmd_win[i].auc_win_used)
|
||||
{
|
||||
(void)win_free_mem(aucmd_win[i].auc_win, &dummy, NULL);
|
||||
aucmd_win[i].auc_win_used = FALSE;
|
||||
}
|
||||
|
||||
while (firstwin != NULL)
|
||||
(void)win_free_mem(firstwin, &dummy, NULL);
|
||||
@ -5663,7 +5664,7 @@ win_free(
|
||||
int
|
||||
win_unlisted(win_T *wp)
|
||||
{
|
||||
return wp == aucmd_win || WIN_IS_POPUP(wp);
|
||||
return is_aucmd_win(wp) || WIN_IS_POPUP(wp);
|
||||
}
|
||||
|
||||
#if defined(FEAT_PROP_POPUP) || defined(PROTO)
|
||||
@ -7257,7 +7258,7 @@ only_one_window(void)
|
||||
# ifdef FEAT_QUICKFIX
|
||||
|| wp->w_p_pvw
|
||||
# endif
|
||||
) || wp == curwin) && wp != aucmd_win)
|
||||
) || wp == curwin) && !is_aucmd_win(wp))
|
||||
++count;
|
||||
return (count <= 1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user