1 To: vim_dev@googlegroups.com
4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 Problem: When closing a window or buffer autocommands may close it too,
12 causing problems for where the autocommand was invoked from.
13 Solution: Add the w_closing and b_closing flags. When set disallow ":q" and
14 ":close" to prevent recursive closing.
15 Files: src/structs.h, src/buffer.c, src/ex_docmd.c, src/window.c
18 *** ../vim-7.3.544/src/structs.h 2012-02-04 21:57:44.000000000 +0100
19 --- src/structs.h 2012-06-06 16:43:34.000000000 +0200
23 typedef struct qf_info_S qf_info_T;
27 + * These are items normally related to a buffer. But when using ":ownsyntax"
28 + * a window may have its own instance.
32 hashtab_T b_keywtab; /* syntax keywords hash table */
36 int b_nwindows; /* nr of windows open on this buffer */
38 int b_flags; /* various BF_ flags */
40 + int b_closing; /* buffer is being closed, don't let
41 + autocommands close it too. */
45 * b_ffname has the full path of the file (NULL for no name).
49 win_T *w_prev; /* link to previous window */
50 win_T *w_next; /* link to next window */
53 + int w_closing; /* window is being closed, don't let
54 + autocommands close it too. */
57 frame_T *w_frame; /* frame containing this window */
59 *** ../vim-7.3.544/src/buffer.c 2012-03-16 14:32:10.000000000 +0100
60 --- src/buffer.c 2012-06-06 18:57:27.000000000 +0200
63 /* When the buffer is no longer in a window, trigger BufWinLeave */
64 if (buf->b_nwindows == 1)
66 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
68 ! /* Return if autocommands deleted the buffer or made it the only one. */
69 ! if (!buf_valid(buf) || (abort_if_last && one_window()))
75 /* When the buffer becomes hidden, but is not unloaded, trigger
79 apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
81 ! /* Return if autocommands deleted the buffer or made it the only
83 ! if (!buf_valid(buf) || (abort_if_last && one_window()))
90 if (aborting()) /* autocmds may abort script processing */
92 /* When the buffer is no longer in a window, trigger BufWinLeave */
93 if (buf->b_nwindows == 1)
95 + buf->b_closing = TRUE;
96 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
98 ! if (!buf_valid(buf))
100 + /* Autocommands deleted the buffer. */
105 + buf->b_closing = FALSE;
106 + if (abort_if_last && one_window())
107 + /* Autocommands made this the only window. */
110 /* When the buffer becomes hidden, but is not unloaded, trigger
114 + buf->b_closing = TRUE;
115 apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
117 ! if (!buf_valid(buf))
118 ! /* Autocommands deleted the buffer. */
120 ! buf->b_closing = FALSE;
121 ! if (abort_if_last && one_window())
122 ! /* Autocommands made this the only window. */
126 if (aborting()) /* autocmds may abort script processing */
131 int is_curbuf = (buf == curbuf);
133 + buf->b_closing = TRUE;
134 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf);
135 if (!buf_valid(buf)) /* autocommands may delete the buffer */
140 if (!buf_valid(buf)) /* autocommands may delete the buffer */
143 + buf->b_closing = FALSE;
145 if (aborting()) /* autocmds may abort script processing */
150 * a window with this buffer.
153 + # ifdef FEAT_AUTOCMD
154 + && !(curwin->w_closing || curwin->w_buffer->b_closing)
156 && (firstwin != lastwin || first_tabpage->tp_next != NULL))
157 win_close(curwin, FALSE);
162 || (had_tab > 0 && wp != firstwin)
164 ! ) && firstwin != lastwin)
166 win_close(wp, FALSE);
170 || (had_tab > 0 && wp != firstwin)
172 ! ) && firstwin != lastwin
173 ! #ifdef FEAT_AUTOCMD
174 ! && !(wp->w_closing || wp->w_buffer->b_closing)
178 win_close(wp, FALSE);
180 *** ../vim-7.3.544/src/ex_docmd.c 2012-06-06 18:03:01.000000000 +0200
181 --- src/ex_docmd.c 2012-06-06 18:06:46.000000000 +0200
186 apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
187 ! if (curbuf_locked())
194 apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
195 ! /* Refuse to quick when locked or when the buffer in the last window is
196 ! * being closed (can only happen in autocommands). */
197 ! if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing))
201 *** ../vim-7.3.544/src/window.c 2012-05-25 12:38:57.000000000 +0200
202 --- src/window.c 2012-06-06 18:47:19.000000000 +0200
206 for (wp = firstwin; wp != NULL && lastwin != firstwin; )
208 ! if (wp->w_buffer == buf && (!keep_curwin || wp != curwin))
210 win_close(wp, FALSE);
214 for (wp = firstwin; wp != NULL && lastwin != firstwin; )
216 ! if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
217 ! #ifdef FEAT_AUTOCMD
218 ! && !(wp->w_closing || wp->w_buffer->b_closing)
222 win_close(wp, FALSE);
226 nexttp = tp->tp_next;
228 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
229 ! if (wp->w_buffer == buf)
231 win_close_othertab(wp, FALSE, tp);
234 nexttp = tp->tp_next;
236 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
237 ! if (wp->w_buffer == buf
238 ! #ifdef FEAT_AUTOCMD
239 ! && !(wp->w_closing || wp->w_buffer->b_closing)
243 win_close_othertab(wp, FALSE, tp);
251 + if (win->w_closing || win->w_buffer->b_closing)
252 + return; /* window is already being closed */
253 if (win == aucmd_win)
255 EMSG(_("E813: Cannot close autocmd window"));
258 wp = frame2win(win_altframe(win, NULL));
261 ! * Be careful: If autocommands delete the window, return now.
263 if (wp->w_buffer != curbuf)
266 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
267 ! if (!win_valid(win) || last_window())
270 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
271 ! if (!win_valid(win) || last_window())
274 /* autocmds may abort script processing */
276 wp = frame2win(win_altframe(win, NULL));
279 ! * Be careful: If autocommands delete the window or cause this window
280 ! * to be the last one left, return now.
282 if (wp->w_buffer != curbuf)
285 + win->w_closing = TRUE;
286 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
287 ! if (!win_valid(win))
289 ! win->w_closing = FALSE;
293 + win->w_closing = TRUE;
294 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
295 ! if (!win_valid(win))
297 ! win->w_closing = FALSE;
301 /* autocmds may abort script processing */
304 * Close the link to the buffer.
306 if (win->w_buffer != NULL)
307 ! close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE);
309 /* Autocommands may have closed the window already, or closed the only
310 * other window or moved to another tab page. */
312 * Close the link to the buffer.
314 if (win->w_buffer != NULL)
316 ! #ifdef FEAT_AUTOCMD
317 ! win->w_closing = TRUE;
319 ! close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
320 ! #ifdef FEAT_AUTOCMD
321 ! if (win_valid(win))
322 ! win->w_closing = FALSE;
326 /* Autocommands may have closed the window already, or closed the only
327 * other window or moved to another tab page. */
331 tabpage_T *ptp = NULL;
334 + #ifdef FEAT_AUTOCMD
335 + if (win->w_closing || win->w_buffer->b_closing)
336 + return; /* window is already being closed */
339 /* Close the link to the buffer. */
340 close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
342 *** ../vim-7.3.544/src/version.c 2012-06-06 18:03:01.000000000 +0200
343 --- src/version.c 2012-06-06 18:53:06.000000000 +0200
347 { /* Add new patch number below this line */
353 How To Keep A Healthy Level Of Insanity:
354 4. Put your garbage can on your desk and label it "in".
356 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
357 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
358 \\\ an exciting new programming language -- http://www.Zimbu.org ///
359 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///