]>
Commit | Line | Data |
---|---|---|
c6060300 MT |
1 | To: vim_dev@googlegroups.com |
2 | Subject: Patch 7.3.545 | |
3 | Fcc: outbox | |
4 | From: Bram Moolenaar <Bram@moolenaar.net> | |
5 | Mime-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ------------ | |
9 | ||
10 | Patch 7.3.545 | |
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 | |
16 | ||
17 | ||
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 | |
20 | *************** | |
21 | *** 1201,1206 **** | |
22 | --- 1201,1210 ---- | |
23 | typedef struct qf_info_S qf_info_T; | |
24 | #endif | |
25 | ||
26 | + /* | |
27 | + * These are items normally related to a buffer. But when using ":ownsyntax" | |
28 | + * a window may have its own instance. | |
29 | + */ | |
30 | typedef struct { | |
31 | #ifdef FEAT_SYN_HL | |
32 | hashtab_T b_keywtab; /* syntax keywords hash table */ | |
33 | *************** | |
34 | *** 1290,1295 **** | |
35 | --- 1294,1303 ---- | |
36 | int b_nwindows; /* nr of windows open on this buffer */ | |
37 | ||
38 | int b_flags; /* various BF_ flags */ | |
39 | + #ifdef FEAT_AUTOCMD | |
40 | + int b_closing; /* buffer is being closed, don't let | |
41 | + autocommands close it too. */ | |
42 | + #endif | |
43 | ||
44 | /* | |
45 | * b_ffname has the full path of the file (NULL for no name). | |
46 | *************** | |
47 | *** 1853,1858 **** | |
48 | --- 1861,1870 ---- | |
49 | win_T *w_prev; /* link to previous window */ | |
50 | win_T *w_next; /* link to next window */ | |
51 | #endif | |
52 | + #ifdef FEAT_AUTOCMD | |
53 | + int w_closing; /* window is being closed, don't let | |
54 | + autocommands close it too. */ | |
55 | + #endif | |
56 | ||
57 | frame_T *w_frame; /* frame containing this window */ | |
58 | ||
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 | |
61 | *************** | |
62 | *** 377,404 **** | |
63 | /* When the buffer is no longer in a window, trigger BufWinLeave */ | |
64 | if (buf->b_nwindows == 1) | |
65 | { | |
66 | apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, | |
67 | FALSE, buf); | |
68 | ! /* Return if autocommands deleted the buffer or made it the only one. */ | |
69 | ! if (!buf_valid(buf) || (abort_if_last && one_window())) | |
70 | { | |
71 | EMSG(_(e_auabort)); | |
72 | return; | |
73 | } | |
74 | ||
75 | /* When the buffer becomes hidden, but is not unloaded, trigger | |
76 | * BufHidden */ | |
77 | if (!unload_buf) | |
78 | { | |
79 | apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, | |
80 | FALSE, buf); | |
81 | ! /* Return if autocommands deleted the buffer or made it the only | |
82 | ! * one. */ | |
83 | ! if (!buf_valid(buf) || (abort_if_last && one_window())) | |
84 | ! { | |
85 | ! EMSG(_(e_auabort)); | |
86 | ! return; | |
87 | ! } | |
88 | } | |
89 | # ifdef FEAT_EVAL | |
90 | if (aborting()) /* autocmds may abort script processing */ | |
91 | --- 377,411 ---- | |
92 | /* When the buffer is no longer in a window, trigger BufWinLeave */ | |
93 | if (buf->b_nwindows == 1) | |
94 | { | |
95 | + buf->b_closing = TRUE; | |
96 | apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, | |
97 | FALSE, buf); | |
98 | ! if (!buf_valid(buf)) | |
99 | { | |
100 | + /* Autocommands deleted the buffer. */ | |
101 | + aucmd_abort: | |
102 | EMSG(_(e_auabort)); | |
103 | return; | |
104 | } | |
105 | + buf->b_closing = FALSE; | |
106 | + if (abort_if_last && one_window()) | |
107 | + /* Autocommands made this the only window. */ | |
108 | + goto aucmd_abort; | |
109 | ||
110 | /* When the buffer becomes hidden, but is not unloaded, trigger | |
111 | * BufHidden */ | |
112 | if (!unload_buf) | |
113 | { | |
114 | + buf->b_closing = TRUE; | |
115 | apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, | |
116 | FALSE, buf); | |
117 | ! if (!buf_valid(buf)) | |
118 | ! /* Autocommands deleted the buffer. */ | |
119 | ! goto aucmd_abort; | |
120 | ! buf->b_closing = FALSE; | |
121 | ! if (abort_if_last && one_window()) | |
122 | ! /* Autocommands made this the only window. */ | |
123 | ! goto aucmd_abort; | |
124 | } | |
125 | # ifdef FEAT_EVAL | |
126 | if (aborting()) /* autocmds may abort script processing */ | |
127 | *************** | |
128 | *** 552,557 **** | |
129 | --- 559,565 ---- | |
130 | #ifdef FEAT_AUTOCMD | |
131 | int is_curbuf = (buf == curbuf); | |
132 | ||
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 */ | |
136 | return; | |
137 | *************** | |
138 | *** 568,573 **** | |
139 | --- 576,582 ---- | |
140 | if (!buf_valid(buf)) /* autocommands may delete the buffer */ | |
141 | return; | |
142 | } | |
143 | + buf->b_closing = FALSE; | |
144 | # ifdef FEAT_EVAL | |
145 | if (aborting()) /* autocmds may abort script processing */ | |
146 | return; | |
147 | *************** | |
148 | *** 1150,1155 **** | |
149 | --- 1159,1167 ---- | |
150 | * a window with this buffer. | |
151 | */ | |
152 | while (buf == curbuf | |
153 | + # ifdef FEAT_AUTOCMD | |
154 | + && !(curwin->w_closing || curwin->w_buffer->b_closing) | |
155 | + # endif | |
156 | && (firstwin != lastwin || first_tabpage->tp_next != NULL)) | |
157 | win_close(curwin, FALSE); | |
158 | #endif | |
159 | *************** | |
160 | *** 4750,4756 **** | |
161 | #ifdef FEAT_WINDOWS | |
162 | || (had_tab > 0 && wp != firstwin) | |
163 | #endif | |
164 | ! ) && firstwin != lastwin) | |
165 | { | |
166 | win_close(wp, FALSE); | |
167 | #ifdef FEAT_AUTOCMD | |
168 | --- 4762,4772 ---- | |
169 | #ifdef FEAT_WINDOWS | |
170 | || (had_tab > 0 && wp != firstwin) | |
171 | #endif | |
172 | ! ) && firstwin != lastwin | |
173 | ! #ifdef FEAT_AUTOCMD | |
174 | ! && !(wp->w_closing || wp->w_buffer->b_closing) | |
175 | ! #endif | |
176 | ! ) | |
177 | { | |
178 | win_close(wp, FALSE); | |
179 | #ifdef FEAT_AUTOCMD | |
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 | |
182 | *************** | |
183 | *** 6459,6465 **** | |
184 | } | |
185 | #ifdef FEAT_AUTOCMD | |
186 | apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); | |
187 | ! if (curbuf_locked()) | |
188 | return; | |
189 | #endif | |
190 | ||
191 | --- 6459,6467 ---- | |
192 | } | |
193 | #ifdef FEAT_AUTOCMD | |
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)) | |
198 | return; | |
199 | #endif | |
200 | ||
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 | |
203 | *************** | |
204 | *** 2034,2040 **** | |
205 | ||
206 | for (wp = firstwin; wp != NULL && lastwin != firstwin; ) | |
207 | { | |
208 | ! if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)) | |
209 | { | |
210 | win_close(wp, FALSE); | |
211 | ||
212 | --- 2034,2044 ---- | |
213 | ||
214 | for (wp = firstwin; wp != NULL && lastwin != firstwin; ) | |
215 | { | |
216 | ! if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) | |
217 | ! #ifdef FEAT_AUTOCMD | |
218 | ! && !(wp->w_closing || wp->w_buffer->b_closing) | |
219 | ! #endif | |
220 | ! ) | |
221 | { | |
222 | win_close(wp, FALSE); | |
223 | ||
224 | *************** | |
225 | *** 2051,2057 **** | |
226 | nexttp = tp->tp_next; | |
227 | if (tp != curtab) | |
228 | for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) | |
229 | ! if (wp->w_buffer == buf) | |
230 | { | |
231 | win_close_othertab(wp, FALSE, tp); | |
232 | ||
233 | --- 2055,2065 ---- | |
234 | nexttp = tp->tp_next; | |
235 | if (tp != curtab) | |
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) | |
240 | ! #endif | |
241 | ! ) | |
242 | { | |
243 | win_close_othertab(wp, FALSE, tp); | |
244 | ||
245 | *************** | |
246 | *** 2168,2173 **** | |
247 | --- 2176,2183 ---- | |
248 | } | |
249 | ||
250 | #ifdef FEAT_AUTOCMD | |
251 | + if (win->w_closing || win->w_buffer->b_closing) | |
252 | + return; /* window is already being closed */ | |
253 | if (win == aucmd_win) | |
254 | { | |
255 | EMSG(_("E813: Cannot close autocmd window")); | |
256 | *************** | |
257 | *** 2203,2219 **** | |
258 | wp = frame2win(win_altframe(win, NULL)); | |
259 | ||
260 | /* | |
261 | ! * Be careful: If autocommands delete the window, return now. | |
262 | */ | |
263 | if (wp->w_buffer != curbuf) | |
264 | { | |
265 | other_buffer = TRUE; | |
266 | apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); | |
267 | ! if (!win_valid(win) || last_window()) | |
268 | return; | |
269 | } | |
270 | apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); | |
271 | ! if (!win_valid(win) || last_window()) | |
272 | return; | |
273 | # ifdef FEAT_EVAL | |
274 | /* autocmds may abort script processing */ | |
275 | --- 2213,2238 ---- | |
276 | wp = frame2win(win_altframe(win, NULL)); | |
277 | ||
278 | /* | |
279 | ! * Be careful: If autocommands delete the window or cause this window | |
280 | ! * to be the last one left, return now. | |
281 | */ | |
282 | if (wp->w_buffer != curbuf) | |
283 | { | |
284 | other_buffer = TRUE; | |
285 | + win->w_closing = TRUE; | |
286 | apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); | |
287 | ! if (!win_valid(win)) | |
288 | ! return; | |
289 | ! win->w_closing = FALSE; | |
290 | ! if (last_window()) | |
291 | return; | |
292 | } | |
293 | + win->w_closing = TRUE; | |
294 | apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); | |
295 | ! if (!win_valid(win)) | |
296 | ! return; | |
297 | ! win->w_closing = FALSE; | |
298 | ! if (last_window()) | |
299 | return; | |
300 | # ifdef FEAT_EVAL | |
301 | /* autocmds may abort script processing */ | |
302 | *************** | |
303 | *** 2240,2246 **** | |
304 | * Close the link to the buffer. | |
305 | */ | |
306 | if (win->w_buffer != NULL) | |
307 | ! close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE); | |
308 | ||
309 | /* Autocommands may have closed the window already, or closed the only | |
310 | * other window or moved to another tab page. */ | |
311 | --- 2259,2274 ---- | |
312 | * Close the link to the buffer. | |
313 | */ | |
314 | if (win->w_buffer != NULL) | |
315 | ! { | |
316 | ! #ifdef FEAT_AUTOCMD | |
317 | ! win->w_closing = TRUE; | |
318 | ! #endif | |
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; | |
323 | ! #endif | |
324 | ! } | |
325 | ||
326 | /* Autocommands may have closed the window already, or closed the only | |
327 | * other window or moved to another tab page. */ | |
328 | *************** | |
329 | *** 2346,2351 **** | |
330 | --- 2374,2384 ---- | |
331 | tabpage_T *ptp = NULL; | |
332 | int free_tp = FALSE; | |
333 | ||
334 | + #ifdef FEAT_AUTOCMD | |
335 | + if (win->w_closing || win->w_buffer->b_closing) | |
336 | + return; /* window is already being closed */ | |
337 | + #endif | |
338 | + | |
339 | /* Close the link to the buffer. */ | |
340 | close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, FALSE); | |
341 | ||
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 | |
344 | *************** | |
345 | *** 716,717 **** | |
346 | --- 716,719 ---- | |
347 | { /* Add new patch number below this line */ | |
348 | + /**/ | |
349 | + 545, | |
350 | /**/ | |
351 | ||
352 | -- | |
353 | How To Keep A Healthy Level Of Insanity: | |
354 | 4. Put your garbage can on your desk and label it "in". | |
355 | ||
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 /// |