comparison src/window.c @ 3570:e7ff3251dfa1 v7.3.545

updated for version 7.3.545 Problem: When closing a window or buffer autocommands may close it too, causing problems for where the autocommand was invoked from. Solution: Add the w_closing and b_closing flags. When set disallow ":q" and ":close" to prevent recursive closing.
author Bram Moolenaar <bram@vim.org>
date Wed, 06 Jun 2012 19:02:45 +0200
parents fa17c8646feb
children e83c5dcea112
comparison
equal deleted inserted replaced
3569:6707a6a1ff9c 3570:e7ff3251dfa1
2032 2032
2033 ++RedrawingDisabled; 2033 ++RedrawingDisabled;
2034 2034
2035 for (wp = firstwin; wp != NULL && lastwin != firstwin; ) 2035 for (wp = firstwin; wp != NULL && lastwin != firstwin; )
2036 { 2036 {
2037 if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)) 2037 if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
2038 #ifdef FEAT_AUTOCMD
2039 && !(wp->w_closing || wp->w_buffer->b_closing)
2040 #endif
2041 )
2038 { 2042 {
2039 win_close(wp, FALSE); 2043 win_close(wp, FALSE);
2040 2044
2041 /* Start all over, autocommands may change the window layout. */ 2045 /* Start all over, autocommands may change the window layout. */
2042 wp = firstwin; 2046 wp = firstwin;
2049 for (tp = first_tabpage; tp != NULL; tp = nexttp) 2053 for (tp = first_tabpage; tp != NULL; tp = nexttp)
2050 { 2054 {
2051 nexttp = tp->tp_next; 2055 nexttp = tp->tp_next;
2052 if (tp != curtab) 2056 if (tp != curtab)
2053 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) 2057 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
2054 if (wp->w_buffer == buf) 2058 if (wp->w_buffer == buf
2059 #ifdef FEAT_AUTOCMD
2060 && !(wp->w_closing || wp->w_buffer->b_closing)
2061 #endif
2062 )
2055 { 2063 {
2056 win_close_othertab(wp, FALSE, tp); 2064 win_close_othertab(wp, FALSE, tp);
2057 2065
2058 /* Start all over, the tab page may be closed and 2066 /* Start all over, the tab page may be closed and
2059 * autocommands may change the window layout. */ 2067 * autocommands may change the window layout. */
2166 EMSG(_("E444: Cannot close last window")); 2174 EMSG(_("E444: Cannot close last window"));
2167 return; 2175 return;
2168 } 2176 }
2169 2177
2170 #ifdef FEAT_AUTOCMD 2178 #ifdef FEAT_AUTOCMD
2179 if (win->w_closing || win->w_buffer->b_closing)
2180 return; /* window is already being closed */
2171 if (win == aucmd_win) 2181 if (win == aucmd_win)
2172 { 2182 {
2173 EMSG(_("E813: Cannot close autocmd window")); 2183 EMSG(_("E813: Cannot close autocmd window"));
2174 return; 2184 return;
2175 } 2185 }
2201 * This may change because of the autocommands (sigh). 2211 * This may change because of the autocommands (sigh).
2202 */ 2212 */
2203 wp = frame2win(win_altframe(win, NULL)); 2213 wp = frame2win(win_altframe(win, NULL));
2204 2214
2205 /* 2215 /*
2206 * Be careful: If autocommands delete the window, return now. 2216 * Be careful: If autocommands delete the window or cause this window
2217 * to be the last one left, return now.
2207 */ 2218 */
2208 if (wp->w_buffer != curbuf) 2219 if (wp->w_buffer != curbuf)
2209 { 2220 {
2210 other_buffer = TRUE; 2221 other_buffer = TRUE;
2222 win->w_closing = TRUE;
2211 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); 2223 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
2212 if (!win_valid(win) || last_window()) 2224 if (!win_valid(win))
2213 return; 2225 return;
2214 } 2226 win->w_closing = FALSE;
2227 if (last_window())
2228 return;
2229 }
2230 win->w_closing = TRUE;
2215 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); 2231 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
2216 if (!win_valid(win) || last_window()) 2232 if (!win_valid(win))
2233 return;
2234 win->w_closing = FALSE;
2235 if (last_window())
2217 return; 2236 return;
2218 # ifdef FEAT_EVAL 2237 # ifdef FEAT_EVAL
2219 /* autocmds may abort script processing */ 2238 /* autocmds may abort script processing */
2220 if (aborting()) 2239 if (aborting())
2221 return; 2240 return;
2238 2257
2239 /* 2258 /*
2240 * Close the link to the buffer. 2259 * Close the link to the buffer.
2241 */ 2260 */
2242 if (win->w_buffer != NULL) 2261 if (win->w_buffer != NULL)
2243 close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE); 2262 {
2263 #ifdef FEAT_AUTOCMD
2264 win->w_closing = TRUE;
2265 #endif
2266 close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
2267 #ifdef FEAT_AUTOCMD
2268 if (win_valid(win))
2269 win->w_closing = FALSE;
2270 #endif
2271 }
2244 2272
2245 /* Autocommands may have closed the window already, or closed the only 2273 /* Autocommands may have closed the window already, or closed the only
2246 * other window or moved to another tab page. */ 2274 * other window or moved to another tab page. */
2247 if (!win_valid(win) || last_window() || curtab != prev_curtab 2275 if (!win_valid(win) || last_window() || curtab != prev_curtab
2248 || close_last_window_tabpage(win, free_buf, prev_curtab)) 2276 || close_last_window_tabpage(win, free_buf, prev_curtab))
2343 { 2371 {
2344 win_T *wp; 2372 win_T *wp;
2345 int dir; 2373 int dir;
2346 tabpage_T *ptp = NULL; 2374 tabpage_T *ptp = NULL;
2347 int free_tp = FALSE; 2375 int free_tp = FALSE;
2376
2377 #ifdef FEAT_AUTOCMD
2378 if (win->w_closing || win->w_buffer->b_closing)
2379 return; /* window is already being closed */
2380 #endif
2348 2381
2349 /* Close the link to the buffer. */ 2382 /* Close the link to the buffer. */
2350 close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE); 2383 close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE);
2351 2384
2352 /* Careful: Autocommands may have closed the tab page or made it the 2385 /* Careful: Autocommands may have closed the tab page or made it the