Patch 9.0.0965

6 views
Skip to first unread message

Bram Moolenaar

unread,
Nov 28, 2022, 1:52:36 PM11/28/22
to vim...@googlegroups.com

Patch 9.0.0965
Problem: Using one window for executing autocommands is insufficient.
Solution: Use up to five windows for executing autocommands.
Files: src/globals.h, src/structs.h, src/autocmd.c,
src/proto/autocmd.pro, src/main.c, src/eval.c, src/evalwindow.c,
src/ex_docmd.c, src/screen.c, src/terminal.c, src/window.c,
src/buffer.c, src/bufwrite.c, src/channel.c, src/diff.c,
src/evalbuffer.c, src/evalvars.c, src/ex_cmds2.c, src/fileio.c,
src/if_ruby.c, src/os_unix.c, src/os_win32.c, src/quickfix.c,
src/term.c, src/if_perl.xs, src/if_py_both.h,
src/testdir/test_autocmd.vim


*** ../vim-9.0.0964/src/globals.h 2022-11-26 19:16:44.186717893 +0000
--- src/globals.h 2022-11-28 17:23:59.229580371 +0000
***************
*** 977,984 ****

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

#ifdef FEAT_PROP_POPUP
EXTERN win_T *first_popupwin; // first global popup window
--- 977,994 ----

EXTERN win_T *curwin; // currently active window

! // 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
*** ../vim-9.0.0964/src/structs.h 2022-11-25 16:31:46.964606667 +0000
--- src/structs.h 2022-11-28 17:36:48.730226363 +0000
***************
*** 4160,4166 ****
typedef struct
{
buf_T *save_curbuf; // saved curbuf
! int use_aucmd_win; // using aucmd_win
int save_curwin_id; // ID of saved curwin
int new_curwin_id; // ID of new curwin
int save_prevwin_id; // ID of saved prevwin
--- 4160,4166 ----
typedef struct
{
buf_T *save_curbuf; // saved curbuf
! 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
*** ../vim-9.0.0964/src/autocmd.c 2022-11-22 12:40:44.062427876 +0000
--- src/autocmd.c 2022-11-28 18:01:55.253554954 +0000
***************
*** 629,656 ****
}
}

#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)
{
s = ((char_u **)(augroups.ga_data))[i];
if (s != get_deleted_augroup())
vim_free(s);
}
ga_clear(&augroups);
}
#endif

/*
* Return the event number for event name "start".
* Return NUM_EVENTS if the event name was not found.
* Return a pointer to the next event name in "end".
--- 629,680 ----
}
}

+ void
+ autocmd_init(void)
+ {
+ CLEAR_FIELD(aucmd_win);
+ }
+
#if defined(EXITFREE) || defined(PROTO)
void
free_all_autocmds(void)
{
char_u *s;

for (current_augroup = -1; current_augroup < augroups.ga_len;
++current_augroup)
do_autocmd(NULL, (char_u *)"", TRUE);

! 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.
* Return a pointer to the next event name in "end".
***************
*** 1438,1445 ****
if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
continue;

! // find a window for this buffer and save some values
aucmd_prepbuf(&aco, buf);
set_bufref(&bufref, buf);

// execute the autocommands for this buffer
--- 1462,1477 ----
if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
continue;

! // 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,1455 ****
// 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);

// restore the current window
aucmd_restbuf(&aco);
--- 1481,1487 ----
// Execute the modeline settings, but don't set window-local
// options if we are using the current window for another
// buffer.
! do_modelines(is_aucmd_win(curwin) ? OPT_NOWIN : 0);

// restore the current window
aucmd_restbuf(&aco);
***************
*** 1490,1497 ****
/*
* 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".
* Set "curbuf" and "curwin" to match "buf".
*/
void
aucmd_prepbuf(
--- 1522,1530 ----
/*
* Prepare for executing autocommands for (hidden) buffer "buf".
* Search for a visible window containing the current buffer. If there isn't
! * 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,1529 ****
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)
! {
! aucmd_win = win_alloc_popup_win();
! if (aucmd_win == NULL)
! win = curwin;
! }
! 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;
--- 1545,1573 ----
if (win->w_buffer == buf)
break;

! // Allocate a window when needed.
! win_T *auc_win = NULL;
! int auc_idx = AUCMD_WIN_COUNT;
! if (win == NULL)
! {
! 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;
! }

aco->save_curwin_id = curwin->w_id;
aco->save_curbuf = curbuf;
***************
*** 1533,1556 ****
// 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;
curwin = win;
}
else
{
! // There is no window for "buf", use "aucmd_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;

! win_init_popup_win(aucmd_win, buf);

aco->globaldir = globaldir;
globaldir = NULL;

! // Split the current window, put the aucmd_win in the upper half.
// We don't want the BufEnter or WinEnter autocommands.
block_autocmds();
make_snapshot(SNAP_AUCMD_IDX);
--- 1577,1599 ----
// 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_idx = -1;
curwin = win;
}
else
{
! // 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_idx = auc_idx;

! win_init_popup_win(auc_win, buf);

aco->globaldir = globaldir;
globaldir = NULL;

! // 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,1571 ****

// no redrawing and don't set the window title
++RedrawingDisabled;
! (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
--RedrawingDisabled;
(void)win_comp_pos(); // recompute window positions
p_ea = save_ea;
--- 1608,1614 ----

// no redrawing and don't set the window title
++RedrawingDisabled;
! (void)win_split_ins(0, WSP_TOP, auc_win, 0);
--RedrawingDisabled;
(void)win_comp_pos(); // recompute window positions
p_ea = save_ea;
***************
*** 1573,1579 ****
p_acd = save_acd;
#endif
unblock_autocmds();
! curwin = aucmd_win;
}
curbuf = buf;
aco->new_curwin_id = curwin->w_id;
--- 1616,1622 ----
p_acd = save_acd;
#endif
unblock_autocmds();
! curwin = auc_win;
}
curbuf = buf;
aco->new_curwin_id = curwin->w_id;
***************
*** 1595,1618 ****
int dummy;
win_T *save_curwin;

! if (aco->use_aucmd_win)
{
--curbuf->b_nwindows;
! // Find "aucmd_win", it can't be closed, but it may be in another tab
// page. Do not trigger autocommands here.
block_autocmds();
! if (curwin != aucmd_win)
{
tabpage_T *tp;
win_T *wp;

FOR_ALL_TAB_WINDOWS(tp, wp)
{
! if (wp == aucmd_win)
{
if (tp != curtab)
goto_tabpage_tp(tp, TRUE, TRUE);
! win_goto(aucmd_win);
goto win_found;
}
}
--- 1638,1663 ----
int dummy;
win_T *save_curwin;

! if (aco->use_aucmd_win_idx >= 0)
{
+ win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win;
+
--curbuf->b_nwindows;
! // Find "awp", it can't be closed, but it may be in another tab
// page. Do not trigger autocommands here.
block_autocmds();
! if (curwin != awp)
{
tabpage_T *tp;
win_T *wp;

FOR_ALL_TAB_WINDOWS(tp, wp)
{
! if (wp == awp)
{
if (tp != curtab)
goto_tabpage_tp(tp, TRUE, TRUE);
! win_goto(awp);
goto win_found;
}
}
***************
*** 1622,1628 ****
// Remove the window and frame from the tree of frames.
(void)winframe_remove(curwin, &dummy, NULL);
win_remove(curwin, NULL);
! aucmd_win_used = FALSE;
last_status(FALSE); // may need to remove last status line

if (!valid_tabpage_win(curtab))
--- 1667,1673 ----
// Remove the window and frame from the tree of frames.
(void)winframe_remove(curwin, &dummy, NULL);
win_remove(curwin, NULL);
! 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,1653 ****
#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
#endif
vim_free(globaldir);
globaldir = aco->globaldir;
--- 1691,1698 ----
#endif
prevwin = win_find_by_id(aco->save_prevwin_id);
#ifdef FEAT_EVAL
! 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,1674 ****
#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);
gui_may_update_scrollbars();
}
#endif
--- 1709,1717 ----
#if defined(FEAT_GUI)
if (gui.in_use)
{
! // 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
*** ../vim-9.0.0964/src/proto/autocmd.pro 2022-11-22 12:40:44.062427876 +0000
--- src/proto/autocmd.pro 2022-11-28 17:47:53.893838235 +0000
***************
*** 2,8 ****
--- 2,10 ----
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);
*** ../vim-9.0.0964/src/main.c 2022-11-24 00:08:58.461010529 +0000
--- src/main.c 2022-11-28 17:12:18.551941151 +0000
***************
*** 123,128 ****
--- 123,130 ----
#endif
params.window_count = -1;

+ autocmd_init();
+
#ifdef FEAT_RUBY
{
int ruby_stack_start;
*** ../vim-9.0.0964/src/eval.c 2022-11-18 22:14:04.798988157 +0000
--- src/eval.c 2022-11-28 17:39:42.506319536 +0000
***************
*** 5084,5092 ****
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);
#ifdef FEAT_PROP_POPUP
FOR_ALL_POPUPWINS(wp)
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
--- 5084,5093 ----
FOR_ALL_TAB_WINDOWS(tp, wp)
abort = abort || set_ref_in_item(&wp->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,
*** ../vim-9.0.0964/src/evalwindow.c 2022-11-18 22:14:04.798988157 +0000
--- src/evalwindow.c 2022-11-28 17:40:20.758338784 +0000
***************
*** 1064,1070 ****
return;
}
}
! if (wp == aucmd_win)
rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
#if defined(FEAT_QUICKFIX)
else if (wp->w_p_pvw)
--- 1064,1070 ----
return;
}
}
! if (is_aucmd_win(wp))
rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
#if defined(FEAT_QUICKFIX)
else if (wp->w_p_pvw)
*** ../vim-9.0.0964/src/ex_docmd.c 2022-11-19 13:14:05.737367072 +0000
--- src/ex_docmd.c 2022-11-28 17:40:46.126326544 +0000
***************
*** 6050,6056 ****
buf_T *buf = win->w_buffer;

// Never close the autocommand window.
! if (win == aucmd_win)
{
emsg(_(e_cannot_close_autocmd_or_popup_window));
return;
--- 6050,6056 ----
buf_T *buf = win->w_buffer;

// Never close the autocommand window.
! if (is_aucmd_win(win))
{
emsg(_(e_cannot_close_autocmd_or_popup_window));
return;
*** ../vim-9.0.0964/src/screen.c 2022-11-24 00:08:58.465010528 +0000
--- src/screen.c 2022-11-28 17:54:21.485646564 +0000
***************
*** 2369,2375 ****
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;
--- 2369,2374 ----
***************
*** 2438,2445 ****
*/
FOR_ALL_TAB_WINDOWS(tp, wp)
win_free_lsize(wp);
! if (aucmd_win != NULL)
! win_free_lsize(aucmd_win);
#ifdef FEAT_PROP_POPUP
// global popup windows
FOR_ALL_POPUPWINS(wp)
--- 2437,2445 ----
*/
FOR_ALL_TAB_WINDOWS(tp, wp)
win_free_lsize(wp);
! 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,2461 ****
if (enc_utf8)
{
new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
! for (i = 0; i < p_mco; ++i)
new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
(Rows + 1) * Columns);
}
--- 2455,2461 ----
if (enc_utf8)
{
new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
! for (int i = 0; i < p_mco; ++i)
new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
(Rows + 1) * Columns);
}
***************
*** 2482,2490 ****
goto give_up;
}
}
! if (aucmd_win != NULL && aucmd_win->w_lines == NULL
! && win_alloc_lines(aucmd_win) == FAIL)
! outofmem = TRUE;
#ifdef FEAT_PROP_POPUP
// global popup windows
FOR_ALL_POPUPWINS(wp)
--- 2482,2495 ----
goto give_up;
}
}
! 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,2515 ****

give_up:

! for (i = 0; i < p_mco; ++i)
if (new_ScreenLinesC[i] == NULL)
break;
if (new_ScreenLines == NULL
! || (enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
|| (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
|| new_ScreenAttrs == NULL
|| new_ScreenCols == NULL
--- 2510,2524 ----

give_up:

! 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 || found_null))
|| (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
|| new_ScreenAttrs == NULL
|| new_ScreenCols == NULL
***************
*** 2534,2540 ****
}
VIM_CLEAR(new_ScreenLines);
VIM_CLEAR(new_ScreenLinesUC);
! for (i = 0; i < p_mco; ++i)
VIM_CLEAR(new_ScreenLinesC[i]);
VIM_CLEAR(new_ScreenLines2);
VIM_CLEAR(new_ScreenAttrs);
--- 2543,2549 ----
}
VIM_CLEAR(new_ScreenLines);
VIM_CLEAR(new_ScreenLinesUC);
! for (int i = 0; i < p_mco; ++i)
VIM_CLEAR(new_ScreenLinesC[i]);
VIM_CLEAR(new_ScreenLines2);
VIM_CLEAR(new_ScreenAttrs);
***************
*** 2571,2577 ****
{
(void)vim_memset(new_ScreenLinesUC + new_row * Columns,
0, (size_t)Columns * sizeof(u8char_T));
! for (i = 0; i < p_mco; ++i)
(void)vim_memset(new_ScreenLinesC[i]
+ new_row * Columns,
0, (size_t)Columns * sizeof(u8char_T));
--- 2580,2586 ----
{
(void)vim_memset(new_ScreenLinesUC + new_row * Columns,
0, (size_t)Columns * sizeof(u8char_T));
! 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,2609 ****
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)
mch_memmove(new_ScreenLinesC[i]
+ new_LineOffset[new_row],
ScreenLinesC[i] + LineOffset[old_row],
--- 2612,2618 ----
mch_memmove(new_ScreenLinesUC + new_LineOffset[new_row],
ScreenLinesUC + LineOffset[old_row],
(size_t)len * sizeof(u8char_T));
! for (int i = 0; i < p_mco; ++i)
mch_memmove(new_ScreenLinesC[i]
+ new_LineOffset[new_row],
ScreenLinesC[i] + LineOffset[old_row],
***************
*** 2636,2642 ****
// NOTE: this may result in all pointers to become NULL.
ScreenLines = new_ScreenLines;
ScreenLinesUC = new_ScreenLinesUC;
! for (i = 0; i < p_mco; ++i)
ScreenLinesC[i] = new_ScreenLinesC[i];
Screen_mco = p_mco;
ScreenLines2 = new_ScreenLines2;
--- 2645,2651 ----
// NOTE: this may result in all pointers to become NULL.
ScreenLines = new_ScreenLines;
ScreenLinesUC = new_ScreenLinesUC;
! for (int i = 0; i < p_mco; ++i)
ScreenLinesC[i] = new_ScreenLinesC[i];
Screen_mco = p_mco;
ScreenLines2 = new_ScreenLines2;
*** ../vim-9.0.0964/src/terminal.c 2022-11-25 16:31:46.968606662 +0000
--- src/terminal.c 2022-11-28 18:29:37.183398477 +0000
***************
*** 3560,3574 ****
// ++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);
#ifdef FEAT_PROP_POPUP
if (pwin != NULL)
popup_close_with_retval(pwin, 0);
--- 3560,3577 ----
// ++close or term_finish == "close"
ch_log(NULL, "terminal job finished, closing window");
aucmd_prepbuf(&aco, term->tl_buffer);
! 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);
*** ../vim-9.0.0964/src/window.c 2022-11-28 16:49:18.442868485 +0000
--- src/window.c 2022-11-28 17:47:21.633862191 +0000
***************
*** 1362,1368 ****
win_equal(wp, TRUE,
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
: dir == 'h' ? 'b' : 'v');
! else if (*p_spk != 'c' && wp != aucmd_win)
win_fix_scroll(FALSE);

// Don't change the window height/width to 'winheight' / 'winwidth' if a
--- 1362,1368 ----
win_equal(wp, TRUE,
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
: dir == 'h' ? 'b' : 'v');
! 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,1968 ****
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)
win_fix_scroll(TRUE);
}

--- 1962,1968 ----
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
topframe, dir, 0, tabline_height(),
(int)Columns, topframe->fr_height);
! if (*p_spk != 'c' && !is_aucmd_win(next_curwin))
win_fix_scroll(TRUE);
}

***************
*** 2426,2432 ****

/*
* Return TRUE if the current window is the only window that exists (ignoring
! * "aucmd_win").
* Returns FALSE if there is a window, possibly in another tab page.
*/
static int
--- 2426,2432 ----

/*
* Return TRUE if the current window is the only window that exists (ignoring
! * "aucmd_win[]").
* Returns FALSE if there is a window, possibly in another tab page.
*/
static int
***************
*** 2436,2442 ****
}

/*
! * Return TRUE if there is only one window other than "aucmd_win" in the
* current tab page.
*/
int
--- 2436,2442 ----
}

/*
! * Return TRUE if there is only one window other than "aucmd_win[]" in the
* current tab page.
*/
int
***************
*** 2447,2453 ****

FOR_ALL_WINDOWS(wp)
{
! if (wp != aucmd_win)
{
if (seen_one)
return FALSE;
--- 2447,2453 ----

FOR_ALL_WINDOWS(wp)
{
! if (!is_aucmd_win(wp))
{
if (seen_one)
return FALSE;
***************
*** 2588,2594 ****
emsg(_(e_cannot_close_autocmd_or_popup_window));
return FAIL;
}
! if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
{
emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
return FAIL;
--- 2588,2594 ----
emsg(_(e_cannot_close_autocmd_or_popup_window));
return FAIL;
}
! if ((is_aucmd_win(firstwin) || is_aucmd_win(lastwin)) && one_window())
{
emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
return FAIL;
***************
*** 3292,3302 ****
while (first_tabpage->tp_next != NULL)
tabpage_close(TRUE);

! if (aucmd_win != NULL)
! {
! (void)win_free_mem(aucmd_win, &dummy, NULL);
! aucmd_win = NULL;
! }

while (firstwin != NULL)
(void)win_free_mem(firstwin, &dummy, NULL);
--- 3292,3303 ----
while (first_tabpage->tp_next != NULL)
tabpage_close(TRUE);

! 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,5669 ****
int
win_unlisted(win_T *wp)
{
! return wp == aucmd_win || WIN_IS_POPUP(wp);
}

#if defined(FEAT_PROP_POPUP) || defined(PROTO)
--- 5664,5670 ----
int
win_unlisted(win_T *wp)
{
! return is_aucmd_win(wp) || WIN_IS_POPUP(wp);
}

#if defined(FEAT_PROP_POPUP) || defined(PROTO)
***************
*** 7257,7263 ****
# ifdef FEAT_QUICKFIX
|| wp->w_p_pvw
# endif
! ) || wp == curwin) && wp != aucmd_win)
++count;
return (count <= 1);
}
--- 7258,7264 ----
# ifdef FEAT_QUICKFIX
|| wp->w_p_pvw
# endif
! ) || wp == curwin) && !is_aucmd_win(wp))
++count;
return (count <= 1);
}
*** ../vim-9.0.0964/src/buffer.c 2022-11-25 16:31:46.964606667 +0000
--- src/buffer.c 2022-11-28 18:07:18.013530353 +0000
***************
*** 150,160 ****
{
aco_save_T aco;

aucmd_prepbuf(&aco, buf);
! if (swap_exists_action != SEA_READONLY)
! swap_exists_action = SEA_NONE;
! open_buffer(FALSE, NULL, 0);
! aucmd_restbuf(&aco);
}
}
#endif
--- 150,164 ----
{
aco_save_T aco;

+ // Make sure the buffer is in a window. If not then skip it.
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
! {
! if (swap_exists_action != SEA_READONLY)
! swap_exists_action = SEA_NONE;
! open_buffer(FALSE, NULL, 0);
! aucmd_restbuf(&aco);
! }
}
}
#endif
***************
*** 361,381 ****
{
aco_save_T aco;

! // Go to the buffer that was opened.
aucmd_prepbuf(&aco, old_curbuf.br_buf);
! do_modelines(0);
! curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);

! if ((flags & READ_NOWINENTER) == 0)
#ifdef FEAT_EVAL
! apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
! curbuf, &retval);
#else
! apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
#endif

! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
}
}

--- 365,390 ----
{
aco_save_T aco;

! // 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);
! if (curbuf == old_curbuf.br_buf)
! {
! do_modelines(0);
! curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);

! if ((flags & READ_NOWINENTER) == 0)
#ifdef FEAT_EVAL
! apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL,
! FALSE, curbuf, &retval);
#else
! apply_autocmds(EVENT_BUFWINENTER, NULL, NULL,
! FALSE, curbuf);
#endif

! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! }
}
}

***************
*** 5942,5949 ****
return TRUE;
}

! // set curwin/curbuf to buf and save a few things
aucmd_prepbuf(&aco, newbuf);

if (ml_open(curbuf) == OK
&& readfile(buf->b_ffname, buf->b_fname,
--- 5951,5964 ----
return TRUE;
}

! // 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,
*** ../vim-9.0.0964/src/bufwrite.c 2022-11-02 13:30:37.526314510 +0000
--- src/bufwrite.c 2022-11-28 18:12:05.305522374 +0000
***************
*** 802,809 ****
if (fname == buf->b_sfname)
buf_fname_s = TRUE;

! // set curwin/curbuf to buf and save a few things
aucmd_prepbuf(&aco, buf);
set_bufref(&bufref, buf);

if (append)
--- 802,816 ----
if (fname == buf->b_sfname)
buf_fname_s = TRUE;

! // 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,2614 ****

// Apply POST autocommands.
// Careful: The autocommands may call buf_write() recursively!
aucmd_prepbuf(&aco, 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);
!
! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);

#ifdef FEAT_EVAL
if (aborting()) // autocmds may abort script processing
--- 2599,2624 ----

// 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);

! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! }

#ifdef FEAT_EVAL
if (aborting()) // autocmds may abort script processing
*** ../vim-9.0.0964/src/channel.c 2022-10-16 21:43:03.386665520 +0100
--- src/channel.c 2022-11-28 18:13:21.517521630 +0000
***************
*** 2872,2879 ****

buffer->b_p_ma = TRUE;

! // set curbuf to be our buf, temporarily
aucmd_prepbuf(&aco, buffer);

u_sync(TRUE);
// ignore undo failure, undo is not very useful here
--- 2872,2885 ----

buffer->b_p_ma = TRUE;

! // 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
*** ../vim-9.0.0964/src/diff.c 2022-08-14 14:16:07.983582313 +0100
--- src/diff.c 2022-11-28 18:14:44.625513782 +0000
***************
*** 2786,2793 ****
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
aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
}

// May give the warning for a changed buffer here, which can trigger the
--- 2786,2797 ----
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.
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
*** ../vim-9.0.0964/src/evalbuffer.c 2022-11-27 19:45:45.706989832 +0000
--- src/evalbuffer.c 2022-11-28 18:18:26.628686202 +0000
***************
*** 136,141 ****
--- 136,143 ----
*
* 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,162 ****
// 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;
}
}

--- 158,165 ----
// curwin->w_buffer differ from "curbuf", use the autocmd window.
curbuf = curwin->w_buffer;
aucmd_prepbuf(&cob->cob_aco, buf);
! if (curbuf == buf)
! cob->cob_using_aco = TRUE;
}
}

*** ../vim-9.0.0964/src/evalvars.c 2022-11-25 16:31:46.964606667 +0000
--- src/evalvars.c 2022-11-28 18:19:23.640519052 +0000
***************
*** 4761,4773 ****
{
aco_save_T aco;

! // set curbuf to be our buf, temporarily
aucmd_prepbuf(&aco, buf);

! set_option_from_tv(varname + 1, varp);
!
! // reset notion of buffer
! aucmd_restbuf(&aco);
}
else
{
--- 4761,4776 ----
{
aco_save_T aco;

! // 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);

! // reset notion of buffer
! aucmd_restbuf(&aco);
! }
}
else
{
*** ../vim-9.0.0964/src/ex_cmds2.c 2022-10-09 18:53:29.024591198 +0100
--- src/ex_cmds2.c 2022-11-28 18:19:48.764450172 +0000
***************
*** 705,713 ****
else
{
aucmd_prepbuf(&aco, buf);
! apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
buf->b_fname, TRUE, buf);
! aucmd_restbuf(&aco);
}

// start over, in case autocommands messed things up.
--- 705,716 ----
else
{
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
! {
! apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
buf->b_fname, TRUE, buf);
! aucmd_restbuf(&aco);
! }
}

// start over, in case autocommands messed things up.
*** ../vim-9.0.0964/src/fileio.c 2022-11-01 20:33:39.991400397 +0000
--- src/fileio.c 2022-11-28 18:20:53.384285260 +0000
***************
*** 4369,4376 ****
int flags = READ_NEW;
int prepped = OK;

! // set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);

// 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.
--- 4369,4382 ----
int flags = READ_NEW;
int prepped = OK;

! // 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.
*** ../vim-9.0.0964/src/if_ruby.c 2022-11-25 16:31:46.968606662 +0000
--- src/if_ruby.c 2022-11-28 18:22:55.536015597 +0000
***************
*** 1371,1391 ****

if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
{
! // set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);
!
! 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
#endif
! }

! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! // Careful: autocommands may have made "buf" invalid!

update_curbuf(UPD_NOT_VALID);
}
--- 1371,1394 ----

if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
{
! // Set curwin/curbuf for "buf" and save some things.
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
{
! // 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
#endif
! }

! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! // Careful: autocommands may have made "buf" invalid!
! }

update_curbuf(UPD_NOT_VALID);
}
***************
*** 1415,1438 ****

if (n > 0 && n <= buf->b_ml.ml_line_count)
{
! // set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);
!
! 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);
!
! changed();
}

- // restore curwin/curbuf and a few other things
- aucmd_restbuf(&aco);
- // Careful: autocommands may have made "buf" invalid!
-
update_curbuf(UPD_NOT_VALID);
}
else
--- 1418,1444 ----

if (n > 0 && n <= buf->b_ml.ml_line_count)
{
! // Set curwin/curbuf for "buf" and save some things.
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
{
! // 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);
!
! changed();
! }
!
! // 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,1479 ****
{
// set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);
!
! 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);
!
! changed();
}

- // restore curwin/curbuf and a few other things
- aucmd_restbuf(&aco);
- // Careful: autocommands may have made "buf" invalid!
-
update_curbuf(UPD_NOT_VALID);
}
else
--- 1464,1488 ----
{
// set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
{
! // 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);
!
! changed();
! }
!
! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! // Careful: autocommands may have made "buf" invalid!
}

update_curbuf(UPD_NOT_VALID);
}
else
*** ../vim-9.0.0964/src/os_unix.c 2022-11-25 15:09:30.710402884 +0000
--- src/os_unix.c 2022-11-28 18:24:30.511837561 +0000
***************
*** 4490,4516 ****

// Find a window to make "buf" curbuf.
aucmd_prepbuf(&aco, buf);
!
! clear_oparg(&oa);
! while (term_use_loop())
{
! 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);
! }
! 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.
--- 4490,4519 ----

// Find a window to make "buf" curbuf.
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
{
! // Only when managed to find a window for "buf",
! clear_oparg(&oa);
! while (term_use_loop())
{
! 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);
}
! 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.
*** ../vim-9.0.0964/src/os_win32.c 2022-11-23 22:28:03.552026184 +0000
--- src/os_win32.c 2022-11-28 18:25:11.999767140 +0000
***************
*** 4878,4904 ****

// Find a window to make "buf" curbuf.
aucmd_prepbuf(&aco, buf);
!
! clear_oparg(&oa);
! while (term_use_loop())
{
! 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);
! }
! 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);
--- 4878,4907 ----

// Find a window to make "buf" curbuf.
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
{
! // Only do this when a window was found for "buf".
! clear_oparg(&oa);
! while (term_use_loop())
{
! 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);
}
! 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);
*** ../vim-9.0.0964/src/quickfix.c 2022-11-13 12:54:46.718898500 +0000
--- src/quickfix.c 2022-11-28 18:28:02.135516484 +0000
***************
*** 4598,4618 ****
// 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);

! 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
--- 4598,4626 ----
// autocommands may cause trouble
incr_quickfix_busy();

+ int do_fill = TRUE;
if (old_last == NULL)
+ {
// 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"
+ }

! 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,6406 ****
// need to be done (again). But not the window-local
// options!
aucmd_prepbuf(&aco, buf);
#if defined(FEAT_SYN_HL)
! apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
buf->b_fname, TRUE, buf);
#endif
! do_modelines(OPT_NOWIN);
! aucmd_restbuf(&aco);
}
}
}
--- 6403,6417 ----
// 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,
buf->b_fname, TRUE, buf);
#endif
! do_modelines(OPT_NOWIN);
! aucmd_restbuf(&aco);
! }
}
}
}
***************
*** 6593,6632 ****

// 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))
! {
! 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);
if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
wipe_buffer(newbuf_to_wipe.br_buf, FALSE);

--- 6604,6646 ----

// set curwin/curbuf to buf and save a few things
aucmd_prepbuf(&aco, newbuf);
+ 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))
{
! 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);
}

if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
wipe_buffer(newbuf_to_wipe.br_buf, FALSE);

*** ../vim-9.0.0964/src/term.c 2022-11-26 19:16:44.186717893 +0000
--- src/term.c 2022-11-28 18:28:32.775476943 +0000
***************
*** 2232,2241 ****
if (curbuf->b_ml.ml_mfp != NULL)
{
aucmd_prepbuf(&aco, buf);
! apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
curbuf);
! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
}
}
}
--- 2232,2244 ----
if (curbuf->b_ml.ml_mfp != NULL)
{
aucmd_prepbuf(&aco, buf);
! if (curbuf == buf)
! {
! apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
curbuf);
! // restore curwin/curbuf and a few other things
! aucmd_restbuf(&aco);
! }
}
}
}
*** ../vim-9.0.0964/src/if_perl.xs 2022-11-14 15:31:04.041587447 +0000
--- src/if_perl.xs 2022-11-28 18:32:20.335223624 +0000
***************
*** 1869,1886 ****
{
aco_save_T aco;

! /* set curwin/curbuf for "vimbuf" and save some things */
aucmd_prepbuf(&aco, vimbuf);
!
! 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! */
}
}
}
--- 1869,1889 ----
{
aco_save_T aco;

! /* Set curwin/curbuf for "vimbuf" and save some things. */
aucmd_prepbuf(&aco, vimbuf);
! if (curbuf == vimbuf)
{
! /* 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! */
! }
}
}
}
***************
*** 1921,1938 ****

/* set curwin/curbuf for "vimbuf" and save some things */
aucmd_prepbuf(&aco, vimbuf);
!
! 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! */
-
update_curbuf(UPD_VALID);
}
}
--- 1924,1945 ----

/* set curwin/curbuf for "vimbuf" and save some things */
aucmd_prepbuf(&aco, vimbuf);
! if (curbuf == vimbuf)
{
! /* 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! */
}

update_curbuf(UPD_VALID);
}
}
***************
*** 1963,1978 ****

/* set curwin/curbuf for "vimbuf" and save some things */
aucmd_prepbuf(&aco, vimbuf);
!
! 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! */

update_curbuf(UPD_VALID);
}
--- 1970,1988 ----

/* set curwin/curbuf for "vimbuf" and save some things */
aucmd_prepbuf(&aco, vimbuf);
! if (curbuf == vimbuf)
{
! /* 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! */
! }

update_curbuf(UPD_VALID);
}
*** ../vim-9.0.0964/src/if_py_both.h 2022-11-25 16:31:46.968606662 +0000
--- src/if_py_both.h 2022-11-28 18:33:06.435179423 +0000
***************
*** 5283,5290 ****
VimTryStart();
// Using aucmd_*: autocommands will be executed by rename_buffer
aucmd_prepbuf(&aco, self->buf);
! ren_ret = rename_buffer(val);
! aucmd_restbuf(&aco);
Py_XDECREF(todecref);
if (VimTryEnd())
return -1;
--- 5283,5293 ----
VimTryStart();
// Using aucmd_*: autocommands will be executed by rename_buffer
aucmd_prepbuf(&aco, self->buf);
! if (curbuf == self->buf)
! {
! ren_ret = rename_buffer(val);
! aucmd_restbuf(&aco);
! }
Py_XDECREF(todecref);
if (VimTryEnd())
return -1;
*** ../vim-9.0.0964/src/testdir/test_autocmd.vim 2022-11-25 16:31:46.972606656 +0000
--- src/testdir/test_autocmd.vim 2022-11-28 17:06:57.506202897 +0000
***************
*** 4068,4071 ****
--- 4068,4094 ----
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
*** ../vim-9.0.0964/src/version.c 2022-11-28 16:49:18.446868480 +0000
--- src/version.c 2022-11-28 17:03:08.590102217 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 965,
/**/

--
Living in Hollywood is like living in a bowl of granola. What ain't
fruits and nuts is flakes.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

John Marriott

unread,
Nov 28, 2022, 2:06:11 PM11/28/22
to vim...@googlegroups.com

On 29-Nov-2022 05:52, Bram Moolenaar wrote:
Patch 9.0.0965
Problem:    Using one window for executing autocommands is insufficient.
Solution:   Use up to five windows for executing autocommands.
Files:      src/globals.h, src/structs.h, src/autocmd.c,
            src/proto/autocmd.pro, src/main.c, src/eval.c, src/evalwindow.c,
            src/ex_docmd.c, src/screen.c, src/terminal.c, src/window.c,
            src/buffer.c, src/bufwrite.c, src/channel.c, src/diff.c,
            src/evalbuffer.c, src/evalvars.c, src/ex_cmds2.c, src/fileio.c,
            src/if_ruby.c, src/os_unix.c, src/os_win32.c, src/quickfix.c,
            src/term.c, src/if_perl.xs, src/if_py_both.h,
            src/testdir/test_autocmd.vim


After this patch mingw64 (clang 15.0.5) gives this build error:
</snip>
clang -c -I. -Iproto -DWIN32 -DWINVER=0x0603 -D_WIN32_WINNT=0x0603 -DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -D__USE_MINGW_ANSI_STDIO -pipe -Wall -O3 -fomit-frame-pointer -fpie -fPIE -DFEAT_GUI_MSWIN -DFEAT_CLIPBOARD screen.c -o gobjx86-64/screen.o
screen.c:2513:5: error: expected expression
    int found_null = FALSE;
    ^
screen.c:2517:6: error: use of undeclared identifier 'found_null'
            found_null = TRUE;
            ^
screen.c:2521:52: error: use of undeclared identifier 'found_null'; did you mean 'func_call'?

            || (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
                                                          ^~~~~~~~~~
                                                          func_call
proto/userfunc.pro:35:5: note: 'func_call' declared here
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
    ^
screen.c:2521:52: warning: address of function 'func_call' will always evaluate to 'true' [-Wpointer-bool-conversion]

            || (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
                                                       ~~ ^~~~~~~~~~
screen.c:2521:52: note: prefix with the address-of operator to silence this warning

            || (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
                                                          ^
                                                          &
1 warning and 3 errors generated.
make: *** [Make_cyg_ming.mak:1204: gobjx86-64/screen.o] Error 1
</snip>


The attached patch tries to fix it.
Cheers
John
screen.c.9.0.0965.patch
Reply all
Reply to author
Forward
0 new messages