comparison src/window.c @ 4354:c80838526eeb v7.3.926

updated for version 7.3.926 Problem: Autocommands are triggered by setwinvar() et al. Missing BufEnter on :tabclose. Duplicate WinEnter on :tabclose. Wrong order of events for :tablose and :tabnew. Solution: Fix these autocommand events. (Zyx)
author Bram Moolenaar <bram@vim.org>
date Mon, 06 May 2013 04:50:35 +0200
parents 04736b4030ec
children a2f03b41dca7
comparison
equal deleted inserted replaced
4353:1ab21898454f 4354:c80838526eeb
42 #endif 42 #endif
43 static int win_alloc_firstwin __ARGS((win_T *oldwin)); 43 static int win_alloc_firstwin __ARGS((win_T *oldwin));
44 static void new_frame __ARGS((win_T *wp)); 44 static void new_frame __ARGS((win_T *wp));
45 #if defined(FEAT_WINDOWS) || defined(PROTO) 45 #if defined(FEAT_WINDOWS) || defined(PROTO)
46 static tabpage_T *alloc_tabpage __ARGS((void)); 46 static tabpage_T *alloc_tabpage __ARGS((void));
47 static int leave_tabpage __ARGS((buf_T *new_curbuf)); 47 static int leave_tabpage __ARGS((buf_T *new_curbuf, int trigger_leave_autocmds));
48 static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_autocmds)); 48 static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_autocmds, int trigger_leave_autocmds));
49 static void frame_fix_height __ARGS((win_T *wp)); 49 static void frame_fix_height __ARGS((win_T *wp));
50 static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin)); 50 static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
51 static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin)); 51 static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin, int trigger_enter_autocmds, int trigger_leave_autocmds));
52 static void win_free __ARGS((win_T *wp, tabpage_T *tp)); 52 static void win_free __ARGS((win_T *wp, tabpage_T *tp));
53 static void frame_append __ARGS((frame_T *after, frame_T *frp)); 53 static void frame_append __ARGS((frame_T *after, frame_T *frp));
54 static void frame_insert __ARGS((frame_T *before, frame_T *frp)); 54 static void frame_insert __ARGS((frame_T *before, frame_T *frp));
55 static void frame_remove __ARGS((frame_T *frp)); 55 static void frame_remove __ARGS((frame_T *frp));
56 #ifdef FEAT_VERTSPLIT 56 #ifdef FEAT_VERTSPLIT
351 wp = curwin; 351 wp = curwin;
352 if (win_new_tabpage((int)Prenum) == OK 352 if (win_new_tabpage((int)Prenum) == OK
353 && valid_tabpage(oldtab)) 353 && valid_tabpage(oldtab))
354 { 354 {
355 newtab = curtab; 355 newtab = curtab;
356 goto_tabpage_tp(oldtab, TRUE); 356 goto_tabpage_tp(oldtab, TRUE, TRUE);
357 if (curwin == wp) 357 if (curwin == wp)
358 win_close(curwin, FALSE); 358 win_close(curwin, FALSE);
359 if (valid_tabpage(newtab)) 359 if (valid_tabpage(newtab))
360 goto_tabpage_tp(newtab, TRUE); 360 goto_tabpage_tp(newtab, TRUE, TRUE);
361 } 361 }
362 } 362 }
363 break; 363 break;
364 364
365 /* cursor to top-left window */ 365 /* cursor to top-left window */
2122 int free_buf; 2122 int free_buf;
2123 tabpage_T *prev_curtab; 2123 tabpage_T *prev_curtab;
2124 { 2124 {
2125 if (firstwin == lastwin) 2125 if (firstwin == lastwin)
2126 { 2126 {
2127 buf_T *old_curbuf = curbuf;
2128
2127 /* 2129 /*
2128 * Closing the last window in a tab page. First go to another tab 2130 * Closing the last window in a tab page. First go to another tab
2129 * page and then close the window and the tab page. This avoids that 2131 * page and then close the window and the tab page. This avoids that
2130 * curwin and curtab are invalid while we are freeing memory, they may 2132 * curwin and curtab are invalid while we are freeing memory, they may
2131 * be used in GUI events. 2133 * be used in GUI events.
2132 * Don't trigger autocommands yet, they may use wrong values, so do 2134 * Don't trigger autocommands yet, they may use wrong values, so do
2133 * that below. 2135 * that below.
2134 */ 2136 */
2135 goto_tabpage_tp(alt_tabpage(), FALSE); 2137 goto_tabpage_tp(alt_tabpage(), FALSE, TRUE);
2136 redraw_tabline = TRUE; 2138 redraw_tabline = TRUE;
2137 2139
2138 /* Safety check: Autocommands may have closed the window when jumping 2140 /* Safety check: Autocommands may have closed the window when jumping
2139 * to the other tab page. */ 2141 * to the other tab page. */
2140 if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win) 2142 if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win)
2146 shell_new_rows(); 2148 shell_new_rows();
2147 } 2149 }
2148 /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do 2150 /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
2149 * that now. */ 2151 * that now. */
2150 #ifdef FEAT_AUTOCMD 2152 #ifdef FEAT_AUTOCMD
2153 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
2151 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf); 2154 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
2152 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf); 2155 if (old_curbuf != curbuf)
2156 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
2153 #endif 2157 #endif
2154 return TRUE; 2158 return TRUE;
2155 } 2159 }
2156 return FALSE; 2160 return FALSE;
2157 } 2161 }
2339 ); 2343 );
2340 else 2344 else
2341 win_comp_pos(); 2345 win_comp_pos();
2342 if (close_curwin) 2346 if (close_curwin)
2343 { 2347 {
2344 win_enter_ext(wp, FALSE, TRUE); 2348 win_enter_ext(wp, FALSE, TRUE, TRUE, TRUE);
2345 #ifdef FEAT_AUTOCMD 2349 #ifdef FEAT_AUTOCMD
2346 if (other_buffer) 2350 if (other_buffer)
2347 /* careful: after this wp and win may be invalid! */ 2351 /* careful: after this wp and win may be invalid! */
2348 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); 2352 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
2349 #endif 2353 #endif
3527 newtp = alloc_tabpage(); 3531 newtp = alloc_tabpage();
3528 if (newtp == NULL) 3532 if (newtp == NULL)
3529 return FAIL; 3533 return FAIL;
3530 3534
3531 /* Remember the current windows in this Tab page. */ 3535 /* Remember the current windows in this Tab page. */
3532 if (leave_tabpage(curbuf) == FAIL) 3536 if (leave_tabpage(curbuf, TRUE) == FAIL)
3533 { 3537 {
3534 vim_free(newtp); 3538 vim_free(newtp);
3535 return FAIL; 3539 return FAIL;
3536 } 3540 }
3537 curtab = newtp; 3541 curtab = newtp;
3572 gui_may_update_scrollbars(); 3576 gui_may_update_scrollbars();
3573 #endif 3577 #endif
3574 3578
3575 redraw_all_later(CLEAR); 3579 redraw_all_later(CLEAR);
3576 #ifdef FEAT_AUTOCMD 3580 #ifdef FEAT_AUTOCMD
3581 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
3577 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf); 3582 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
3578 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
3579 #endif 3583 #endif
3580 return OK; 3584 return OK;
3581 } 3585 }
3582 3586
3583 /* Failed, get back the previous Tab page */ 3587 /* Failed, get back the previous Tab page */
3584 enter_tabpage(curtab, curbuf, TRUE); 3588 enter_tabpage(curtab, curbuf, TRUE, TRUE);
3585 return FAIL; 3589 return FAIL;
3586 } 3590 }
3587 3591
3588 /* 3592 /*
3589 * Open a new tab page if ":tab cmd" was used. It will edit the same buffer, 3593 * Open a new tab page if ":tab cmd" was used. It will edit the same buffer,
3690 * When autocommands change "curtab" we don't leave the tab page and return 3694 * When autocommands change "curtab" we don't leave the tab page and return
3691 * FAIL. 3695 * FAIL.
3692 * Careful: When OK is returned need to get a new tab page very very soon! 3696 * Careful: When OK is returned need to get a new tab page very very soon!
3693 */ 3697 */
3694 static int 3698 static int
3695 leave_tabpage(new_curbuf) 3699 leave_tabpage(new_curbuf, trigger_leave_autocmds)
3696 buf_T *new_curbuf UNUSED; /* what is going to be the new curbuf, 3700 buf_T *new_curbuf UNUSED; /* what is going to be the new curbuf,
3697 NULL if unknown */ 3701 NULL if unknown */
3702 int trigger_leave_autocmds UNUSED;
3698 { 3703 {
3699 tabpage_T *tp = curtab; 3704 tabpage_T *tp = curtab;
3700 3705
3701 #ifdef FEAT_VISUAL 3706 #ifdef FEAT_VISUAL
3702 reset_VIsual_and_resel(); /* stop Visual mode */ 3707 reset_VIsual_and_resel(); /* stop Visual mode */
3703 #endif 3708 #endif
3704 #ifdef FEAT_AUTOCMD 3709 #ifdef FEAT_AUTOCMD
3705 if (new_curbuf != curbuf) 3710 if (trigger_leave_autocmds)
3706 { 3711 {
3707 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); 3712 if (new_curbuf != curbuf)
3713 {
3714 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
3715 if (curtab != tp)
3716 return FAIL;
3717 }
3718 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
3708 if (curtab != tp) 3719 if (curtab != tp)
3709 return FAIL; 3720 return FAIL;
3710 } 3721 apply_autocmds(EVENT_TABLEAVE, NULL, NULL, FALSE, curbuf);
3711 apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); 3722 if (curtab != tp)
3712 if (curtab != tp) 3723 return FAIL;
3713 return FAIL; 3724 }
3714 apply_autocmds(EVENT_TABLEAVE, NULL, NULL, FALSE, curbuf);
3715 if (curtab != tp)
3716 return FAIL;
3717 #endif 3725 #endif
3718 #if defined(FEAT_GUI) 3726 #if defined(FEAT_GUI)
3719 /* Remove the scrollbars. They may be added back later. */ 3727 /* Remove the scrollbars. They may be added back later. */
3720 if (gui.in_use) 3728 if (gui.in_use)
3721 gui_remove_scrollbars(); 3729 gui_remove_scrollbars();
3732 } 3740 }
3733 3741
3734 /* 3742 /*
3735 * Start using tab page "tp". 3743 * Start using tab page "tp".
3736 * Only to be used after leave_tabpage() or freeing the current tab page. 3744 * Only to be used after leave_tabpage() or freeing the current tab page.
3737 * Only trigger *Enter autocommands when trigger_autocmds is TRUE. 3745 * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
3746 * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
3738 */ 3747 */
3739 static void 3748 static void
3740 enter_tabpage(tp, old_curbuf, trigger_autocmds) 3749 enter_tabpage(tp, old_curbuf, trigger_enter_autocmds, trigger_leave_autocmds)
3741 tabpage_T *tp; 3750 tabpage_T *tp;
3742 buf_T *old_curbuf UNUSED; 3751 buf_T *old_curbuf UNUSED;
3743 int trigger_autocmds UNUSED; 3752 int trigger_enter_autocmds UNUSED;
3753 int trigger_leave_autocmds UNUSED;
3744 { 3754 {
3745 int old_off = tp->tp_firstwin->w_winrow; 3755 int old_off = tp->tp_firstwin->w_winrow;
3746 win_T *next_prevwin = tp->tp_prevwin; 3756 win_T *next_prevwin = tp->tp_prevwin;
3747 3757
3748 curtab = tp; 3758 curtab = tp;
3751 topframe = tp->tp_topframe; 3761 topframe = tp->tp_topframe;
3752 3762
3753 /* We would like doing the TabEnter event first, but we don't have a 3763 /* We would like doing the TabEnter event first, but we don't have a
3754 * valid current window yet, which may break some commands. 3764 * valid current window yet, which may break some commands.
3755 * This triggers autocommands, thus may make "tp" invalid. */ 3765 * This triggers autocommands, thus may make "tp" invalid. */
3756 win_enter_ext(tp->tp_curwin, FALSE, TRUE); 3766 win_enter_ext(tp->tp_curwin, FALSE, TRUE, trigger_enter_autocmds, trigger_leave_autocmds);
3757 prevwin = next_prevwin; 3767 prevwin = next_prevwin;
3758 3768
3759 last_status(FALSE); /* status line may appear or disappear */ 3769 last_status(FALSE); /* status line may appear or disappear */
3760 (void)win_comp_pos(); /* recompute w_winrow for all windows */ 3770 (void)win_comp_pos(); /* recompute w_winrow for all windows */
3761 must_redraw = CLEAR; /* need to redraw everything */ 3771 must_redraw = CLEAR; /* need to redraw everything */
3786 #endif 3796 #endif
3787 3797
3788 #ifdef FEAT_AUTOCMD 3798 #ifdef FEAT_AUTOCMD
3789 /* Apply autocommands after updating the display, when 'rows' and 3799 /* Apply autocommands after updating the display, when 'rows' and
3790 * 'columns' have been set correctly. */ 3800 * 'columns' have been set correctly. */
3791 if (trigger_autocmds) 3801 if (trigger_enter_autocmds)
3792 { 3802 {
3793 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf); 3803 apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
3794 if (old_curbuf != curbuf) 3804 if (old_curbuf != curbuf)
3795 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); 3805 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
3796 } 3806 }
3867 beep_flush(); 3877 beep_flush();
3868 return; 3878 return;
3869 } 3879 }
3870 } 3880 }
3871 3881
3872 goto_tabpage_tp(tp, TRUE); 3882 goto_tabpage_tp(tp, TRUE, TRUE);
3873 3883
3874 #ifdef FEAT_GUI_TABLINE 3884 #ifdef FEAT_GUI_TABLINE
3875 if (gui_use_tabline()) 3885 if (gui_use_tabline())
3876 gui_mch_set_curtab(tabpage_index(curtab)); 3886 gui_mch_set_curtab(tabpage_index(curtab));
3877 #endif 3887 #endif
3878 } 3888 }
3879 3889
3880 /* 3890 /*
3881 * Go to tabpage "tp". 3891 * Go to tabpage "tp".
3882 * Only trigger *Enter autocommands when trigger_autocmds is TRUE. 3892 * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
3893 * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
3883 * Note: doesn't update the GUI tab. 3894 * Note: doesn't update the GUI tab.
3884 */ 3895 */
3885 void 3896 void
3886 goto_tabpage_tp(tp, trigger_autocmds) 3897 goto_tabpage_tp(tp, trigger_enter_autocmds, trigger_leave_autocmds)
3887 tabpage_T *tp; 3898 tabpage_T *tp;
3888 int trigger_autocmds; 3899 int trigger_enter_autocmds;
3900 int trigger_leave_autocmds;
3889 { 3901 {
3890 /* Don't repeat a message in another tab page. */ 3902 /* Don't repeat a message in another tab page. */
3891 set_keep_msg(NULL, 0); 3903 set_keep_msg(NULL, 0);
3892 3904
3893 if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK) 3905 if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer,
3906 trigger_leave_autocmds) == OK)
3894 { 3907 {
3895 if (valid_tabpage(tp)) 3908 if (valid_tabpage(tp))
3896 enter_tabpage(tp, curbuf, trigger_autocmds); 3909 enter_tabpage(tp, curbuf, trigger_enter_autocmds,
3910 trigger_leave_autocmds);
3897 else 3911 else
3898 enter_tabpage(curtab, curbuf, trigger_autocmds); 3912 enter_tabpage(curtab, curbuf, trigger_enter_autocmds,
3913 trigger_leave_autocmds);
3899 } 3914 }
3900 } 3915 }
3901 3916
3902 /* 3917 /*
3903 * Enter window "wp" in tab page "tp". 3918 * Enter window "wp" in tab page "tp".
3906 void 3921 void
3907 goto_tabpage_win(tp, wp) 3922 goto_tabpage_win(tp, wp)
3908 tabpage_T *tp; 3923 tabpage_T *tp;
3909 win_T *wp; 3924 win_T *wp;
3910 { 3925 {
3911 goto_tabpage_tp(tp, TRUE); 3926 goto_tabpage_tp(tp, TRUE, TRUE);
3912 if (curtab == tp && win_valid(wp)) 3927 if (curtab == tp && win_valid(wp))
3913 { 3928 {
3914 win_enter(wp, TRUE); 3929 win_enter(wp, TRUE);
3915 # ifdef FEAT_GUI_TABLINE 3930 # ifdef FEAT_GUI_TABLINE
3916 if (gui_use_tabline()) 3931 if (gui_use_tabline())
4166 void 4181 void
4167 win_enter(wp, undo_sync) 4182 win_enter(wp, undo_sync)
4168 win_T *wp; 4183 win_T *wp;
4169 int undo_sync; 4184 int undo_sync;
4170 { 4185 {
4171 win_enter_ext(wp, undo_sync, FALSE); 4186 win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE);
4172 } 4187 }
4173 4188
4174 /* 4189 /*
4175 * Make window wp the current window. 4190 * Make window wp the current window.
4176 * Can be called with "curwin_invalid" TRUE, which means that curwin has just 4191 * Can be called with "curwin_invalid" TRUE, which means that curwin has just
4177 * been closed and isn't valid. 4192 * been closed and isn't valid.
4178 */ 4193 */
4179 static void 4194 static void
4180 win_enter_ext(wp, undo_sync, curwin_invalid) 4195 win_enter_ext(wp, undo_sync, curwin_invalid, trigger_enter_autocmds, trigger_leave_autocmds)
4181 win_T *wp; 4196 win_T *wp;
4182 int undo_sync; 4197 int undo_sync;
4183 int curwin_invalid; 4198 int curwin_invalid;
4199 int trigger_enter_autocmds UNUSED;
4200 int trigger_leave_autocmds UNUSED;
4184 { 4201 {
4185 #ifdef FEAT_AUTOCMD 4202 #ifdef FEAT_AUTOCMD
4186 int other_buffer = FALSE; 4203 int other_buffer = FALSE;
4187 #endif 4204 #endif
4188 4205
4189 if (wp == curwin && !curwin_invalid) /* nothing to do */ 4206 if (wp == curwin && !curwin_invalid) /* nothing to do */
4190 return; 4207 return;
4191 4208
4192 #ifdef FEAT_AUTOCMD 4209 #ifdef FEAT_AUTOCMD
4193 if (!curwin_invalid) 4210 if (!curwin_invalid && trigger_leave_autocmds)
4194 { 4211 {
4195 /* 4212 /*
4196 * Be careful: If autocommands delete the window, return now. 4213 * Be careful: If autocommands delete the window, return now.
4197 */ 4214 */
4198 if (wp->w_buffer != curbuf) 4215 if (wp->w_buffer != curbuf)
4257 globaldir = NULL; 4274 globaldir = NULL;
4258 shorten_fnames(TRUE); 4275 shorten_fnames(TRUE);
4259 } 4276 }
4260 4277
4261 #ifdef FEAT_AUTOCMD 4278 #ifdef FEAT_AUTOCMD
4262 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf); 4279 if (trigger_enter_autocmds)
4263 if (other_buffer) 4280 {
4264 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); 4281 apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
4282 if (other_buffer)
4283 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
4284 }
4265 #endif 4285 #endif
4266 4286
4267 #ifdef FEAT_TITLE 4287 #ifdef FEAT_TITLE
4268 maketitle(); 4288 maketitle();
4269 #endif 4289 #endif