We have been running into bugs caused by executing autocommands on a
buffer that is not in a visible window. The latest one was that folds
get messed up in the current window, they are refreshed for the wrong
buffer.
To avoid these problems "for once and for all" I have been exploring
various options. The main goal is to use a temporary window, put the
hidden buffer in it, run the autocommands, the close the window.
This is tricky stuff, autocommands may do unexpected stuff. I found and
fixed the ones I could think of, but there probably are a few others.
Please try out the patch below and see if you can crash Vim, or notice
any side effects.
What I have been doing is having a buffer in another tab page, modifying
it outside of Vim, and then using ":checktime". Vim will offer you to
reload the buffer, which now happens in the temp window.
Let me know what you think.
*** ../vim-7.2.197/src/fileio.c 2009-05-16 17:29:37.000000000 +0200
--- src/fileio.c 2009-06-10 21:20:07.000000000 +0200
***************
*** 4824,4829 ****
--- 4824,4831 ----
char_u *sfname;
{
#ifdef FEAT_AUTOCMD
+ buf_T *buf = curbuf;
+
/* It's like the unnamed buffer is deleted.... */
if (curbuf->b_p_bl)
apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
***************
*** 4832,4837 ****
--- 4834,4845 ----
if (aborting()) /* autocmds may abort script processing */
return FAIL;
# endif
+ if (curbuf != buf)
+ {
+ /* We are in another buffer now, don't do the renaming. */
+ EMSG(_(e_auchangedbuf));
+ return FAIL;
+ }
#endif
if (setfname(curbuf, fname, sfname, FALSE) == OK)
***************
*** 8357,8363 ****
/* Execute the modeline settings, but don't set window-local
* options if we are using the current window for another buffer. */
! do_modelines(aco.save_curwin == NULL ? OPT_NOWIN : 0);
/* restore the current window */
aucmd_restbuf(&aco);
--- 8365,8371 ----
/* 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);
***************
*** 8373,8380 ****
/*
* Prepare for executing autocommands for (hidden) buffer "buf".
! * Search a window for the current buffer. Save the cursor position and
! * screen offset.
* Set "curbuf" and "curwin" to match "buf".
* When FEAT_AUTOCMD is not defined another version is used, see below.
*/
--- 8381,8388 ----
/*
* 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".
* When FEAT_AUTOCMD is not defined another version is used, see below.
*/
***************
*** 8384,8391 ****
buf_T *buf; /* new curbuf */
{
win_T *win;
!
! aco->new_curbuf = buf;
/* Find a window that is for the new buffer */
if (buf == curbuf) /* be quick when buf is curbuf */
--- 8392,8400 ----
buf_T *buf; /* new curbuf */
{
win_T *win;
! #ifdef FEAT_WINDOWS
! int save_ea;
! #endif
/* Find a window that is for the new buffer */
if (buf == curbuf) /* be quick when buf is curbuf */
***************
*** 8399,8440 ****
win = NULL;
#endif
! /*
! * Prefer to use an existing window for the buffer, it has the least side
! * effects (esp. if "buf" is curbuf).
! * Otherwise, use curwin for "buf". It might make some items in the
! * window invalid. At least save the cursor and topline.
! */
if (win != NULL)
{
! /* there is a window for "buf", make it the curwin */
! aco->save_curwin = curwin;
curwin = win;
- aco->save_buf = win->w_buffer;
- aco->new_curwin = win;
}
else
{
! /* there is no window for "buf", use curwin */
! aco->save_curwin = NULL;
! aco->save_buf = curbuf;
! --curbuf->b_nwindows;
curwin->w_buffer = buf;
++buf->b_nwindows;
! /* save cursor and topline, set them to safe values */
! aco->save_cursor = curwin->w_cursor;
! curwin->w_cursor.lnum = 1;
! curwin->w_cursor.col = 0;
! aco->save_topline = curwin->w_topline;
! curwin->w_topline = 1;
! #ifdef FEAT_DIFF
! aco->save_topfill = curwin->w_topfill;
! curwin->w_topfill = 0;
#endif
}
-
curbuf = buf;
}
/*
--- 8408,8460 ----
win = NULL;
#endif
! /* Allocate "aucmd_win" when needed. If this fails (out of memory) fall
! * back to using the current window. */
! if (win == NULL && aucmd_win == NULL)
! {
! win_alloc_aucmd_win();
! if (aucmd_win == NULL)
! win = curwin;
! }
!
! aco->save_curwin = curwin;
! aco->save_curbuf = curbuf;
if (win != NULL)
{
! /* 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). */
curwin = win;
}
else
{
! /* There is no window for "buf", use "aucmd_win". To minimize the side
! * effects, insert it in a the current tab page.
! * Anything related to a window (e.g., setting folds) may have
! * unexpected results. */
! curwin = aucmd_win;
curwin->w_buffer = buf;
++buf->b_nwindows;
! #ifdef FEAT_WINDOWS
! /* Split the current window, put the aucmd_win in the upper half. */
! make_snapshot(SNAP_AUCMD_IDX);
! save_ea = p_ea;
! p_ea = FALSE;
! (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
! (void)win_comp_pos(); /* recompute window positions */
! p_ea = save_ea;
! #endif
! /* set cursor and topline to safe values */
! curwin_init();
! #ifdef FEAT_VERTSPLIT
! curwin->w_wincol = 0;
! curwin->w_width = Columns;
#endif
}
curbuf = buf;
+ aco->new_curwin = curwin;
+ aco->new_curbuf = curbuf;
}
/*
***************
*** 8446,8466 ****
aucmd_restbuf(aco)
aco_save_T *aco; /* structure holding saved values */
{
! if (aco->save_curwin != NULL)
{
/* restore curwin */
#ifdef FEAT_WINDOWS
if (win_valid(aco->save_curwin))
#endif
{
! /* restore the buffer which was previously edited by curwin, if
! * it's still the same window and it's valid */
if (curwin == aco->new_curwin
! && buf_valid(aco->save_buf)
! && aco->save_buf->b_ml.ml_mfp != NULL)
{
--curbuf->b_nwindows;
! curbuf = aco->save_buf;
curwin->w_buffer = curbuf;
++curbuf->b_nwindows;
}
--- 8466,8545 ----
aucmd_restbuf(aco)
aco_save_T *aco; /* structure holding saved values */
{
! #ifdef FEAT_WINDOWS
! int dummy;
! #endif
!
! if (aco->new_curwin == aucmd_win)
! {
! --curbuf->b_nwindows;
! #ifdef FEAT_WINDOWS
! /* Find "aucmd_win", it can't be closed, but it may be in another tab
! * page. */
! 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);
! win_goto(aucmd_win);
! break;
! }
! }
! }
!
! /* Remove the window and frame from the tree of frames. */
! (void)winframe_remove(curwin, &dummy, NULL);
! win_remove(curwin, NULL);
! last_status(FALSE); /* may need to remove last status line */
! restore_snapshot(SNAP_AUCMD_IDX, FALSE);
! (void)win_comp_pos(); /* recompute window positions */
!
! if (win_valid(aco->save_curwin))
! curwin = aco->save_curwin;
! else
! /* Hmm, original window disappeared. Just use the first one. */
! curwin = firstwin;
! # ifdef FEAT_EVAL
! vars_clear(&aucmd_win->w_vars.dv_hashtab); /* free all w: variables */
! # endif
! #else
! curwin = aco->save_curwin;
! #endif
! curbuf = curwin->w_buffer;
!
! /* the buffer contents may have changed */
! check_cursor();
! if (curwin->w_topline > curbuf->b_ml.ml_line_count)
! {
! curwin->w_topline = curbuf->b_ml.ml_line_count;
! #ifdef FEAT_DIFF
! curwin->w_topfill = 0;
! #endif
! }
! }
! else
{
/* restore curwin */
#ifdef FEAT_WINDOWS
if (win_valid(aco->save_curwin))
#endif
{
! /* Restore the buffer which was previously edited by curwin, if
! * it was chagned, we are still the same window and the buffer is
! * valid. */
if (curwin == aco->new_curwin
! && curbuf != aco->new_curbuf
! && buf_valid(aco->new_curbuf)
! && aco->new_curbuf->b_ml.ml_mfp != NULL)
{
--curbuf->b_nwindows;
! curbuf = aco->new_curbuf;
curwin->w_buffer = curbuf;
++curbuf->b_nwindows;
}
***************
*** 8469,8502 ****
curbuf = curwin->w_buffer;
}
}
- else
- {
- /* restore buffer for curwin if it still exists and is loaded */
- if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
- {
- --curbuf->b_nwindows;
- curbuf = aco->save_buf;
- curwin->w_buffer = curbuf;
- ++curbuf->b_nwindows;
- curwin->w_cursor = aco->save_cursor;
- check_cursor();
- /* check topline < line_count, in case lines got deleted */
- if (aco->save_topline <= curbuf->b_ml.ml_line_count)
- {
- curwin->w_topline = aco->save_topline;
- #ifdef FEAT_DIFF
- curwin->w_topfill = aco->save_topfill;
- #endif
- }
- else
- {
- curwin->w_topline = curbuf->b_ml.ml_line_count;
- #ifdef FEAT_DIFF
- curwin->w_topfill = 0;
- #endif
- }
- }
- }
}
static int autocmd_nested = FALSE;
--- 8548,8553 ----
***************
*** 9411,9419 ****
aco_save_T *aco; /* structure to save values in */
buf_T *buf; /* new curbuf */
{
! aco->save_buf = curbuf;
curbuf = buf;
curwin->w_buffer = buf;
}
/*
--- 9462,9472 ----
aco_save_T *aco; /* structure to save values in */
buf_T *buf; /* new curbuf */
{
! aco->save_curbuf = curbuf;
! --curbuf->b_nwindows;
curbuf = buf;
curwin->w_buffer = buf;
+ ++curbuf->b_nwindows;
}
/*
***************
*** 9424,9431 ****
aucmd_restbuf(aco)
aco_save_T *aco; /* structure holding saved values */
{
! curbuf = aco->save_buf;
curwin->w_buffer = curbuf;
}
#endif /* FEAT_AUTOCMD */
--- 9477,9486 ----
aucmd_restbuf(aco)
aco_save_T *aco; /* structure holding saved values */
{
! --curbuf->b_nwindows;
! curbuf = aco->save_curbuf;
curwin->w_buffer = curbuf;
+ ++curbuf->b_nwindows;
}
#endif /* FEAT_AUTOCMD */
*** ../vim-7.2.197/src/globals.h 2009-06-10 18:15:49.000000000 +0200
--- src/globals.h 2009-06-10 15:52:18.000000000 +0200
***************
*** 538,543 ****
--- 538,547 ----
EXTERN win_T *curwin; /* currently active window */
+ #ifdef FEAT_AUTOCMD
+ EXTERN win_T *aucmd_win; /* window used in aucmd_prepbuf() */
+ #endif
+
/*
* The window layout is kept in a tree of frames. topframe points to the top
* of the tree.
*** ../vim-7.2.197/src/if_perl.xs 2008-12-03 13:18:16.000000000 +0100
--- src/if_perl.xs 2009-06-03 17:52:51.000000000 +0200
***************
*** 720,728 ****
--- 720,730 ----
#ifdef HAVE_SANDBOX
if (sandbox)
{
+ # ifndef MAKE_TEST /* avoid a warning for unreachable code */
if ((safe = perl_get_sv( "VIM::safe", FALSE )) == NULL || !SvTRUE(safe))
EMSG(_("E299: Perl evaluation forbidden in sandbox without the Safe
module"));
else
+ # endif
{
PUSHMARK(SP);
XPUSHs(safe);
***************
*** 1234,1240 ****
{
ml_delete(lnum, 0);
deleted_lines_mark(lnum, 1L);
! if (aco.save_buf == curbuf)
check_cursor();
}
--- 1236,1242 ----
{
ml_delete(lnum, 0);
deleted_lines_mark(lnum, 1L);
! if (aco.save_curbuf == curbuf)
check_cursor();
}
*** ../vim-7.2.197/src/proto/window.pro 2007-07-26 22:57:45.000000000 +0200
--- src/proto/window.pro 2009-06-10 21:20:39.000000000 +0200
***************
*** 1,6 ****
--- 1,7 ----
/* window.c */
void do_window __ARGS((int nchar, long Prenum, int xchar));
int win_split __ARGS((int size, int flags));
+ int win_split_ins __ARGS((int size, int flags, win_T *newwin, int dir));
int win_valid __ARGS((win_T *win));
int win_count __ARGS((void));
int make_windows __ARGS((int count, int vertical));
***************
*** 10,18 ****
--- 11,21 ----
void win_close __ARGS((win_T *win, int free_buf));
void win_close_othertab __ARGS((win_T *win, int free_buf, tabpage_T *tp));
void win_free_all __ARGS((void));
+ win_T *winframe_remove __ARGS((win_T *win, int *dirp, tabpage_T *tp));
void close_others __ARGS((int message, int forceit));
void curwin_init __ARGS((void));
int win_alloc_first __ARGS((void));
+ void win_alloc_aucmd_win __ARGS((void));
void win_init_size __ARGS((void));
void free_tabpage __ARGS((tabpage_T *tp));
int win_new_tabpage __ARGS((int after));
***************
*** 30,35 ****
--- 33,40 ----
void win_enter __ARGS((win_T *wp, int undo_sync));
win_T *buf_jump_open_win __ARGS((buf_T *buf));
win_T *buf_jump_open_tab __ARGS((buf_T *buf));
+ void win_append __ARGS((win_T *after, win_T *wp));
+ void win_remove __ARGS((win_T *wp, tabpage_T *tp));
int win_alloc_lines __ARGS((win_T *wp));
void win_free_lsize __ARGS((win_T *wp));
void shell_new_rows __ARGS((void));
***************
*** 58,63 ****
--- 63,70 ----
int min_rows __ARGS((void));
int only_one_window __ARGS((void));
void check_lnums __ARGS((int do_curwin));
+ void make_snapshot __ARGS((int idx));
+ void restore_snapshot __ARGS((int idx, int close_curwin));
int win_hasvertsplit __ARGS((void));
int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
int match_delete __ARGS((win_T *wp, int id, int perr));
*** ../vim-7.2.197/src/screen.c 2009-05-17 13:30:58.000000000 +0200
--- src/screen.c 2009-06-10 16:41:45.000000000 +0200
***************
*** 7495,7500 ****
--- 7495,7504 ----
#endif
}
}
+ #ifdef FEAT_AUTOCMD
+ if (aucmd_win != NULL && win_alloc_lines(aucmd_win) == FAIL)
+ outofmem = TRUE;
+ #endif
#ifdef FEAT_WINDOWS
give_up:
#endif
*** ../vim-7.2.197/src/structs.h 2009-05-16 16:36:25.000000000 +0200
--- src/structs.h 2009-06-10 21:16:32.000000000 +0200
***************
*** 1621,1626 ****
--- 1621,1634 ----
};
#endif
+ #ifdef FEAT_AUTOCMD
+ # define SNAP_HELP_IDX 0
+ # define SNAP_AUCMD_IDX 1
+ # define SNAP_COUNT 2
+ #else
+ # define SNAP_COUNT 1
+ #endif
+
/*
* Tab pages point to the top frame of each tab page.
* Note: Most values are NOT valid for the current tab page! Use "curwin",
***************
*** 1649,1655 ****
buf_T *(tp_diffbuf[DB_COUNT]);
int tp_diff_invalid; /* list of diffs is outdated */
#endif
! frame_T *tp_snapshot; /* window layout snapshot */
#ifdef FEAT_EVAL
dictitem_T tp_winvar; /* variable for "t:" Dictionary */
dict_T tp_vars; /* internal variables, local to tab page */
--- 1657,1663 ----
buf_T *(tp_diffbuf[DB_COUNT]);
int tp_diff_invalid; /* list of diffs is outdated */
#endif
! frame_T *(tp_snapshot[SNAP_COUNT]); /* window layout snapshots */
#ifdef FEAT_EVAL
dictitem_T tp_winvar; /* variable for "t:" Dictionary */
dict_T tp_vars; /* internal variables, local to tab page */
***************
*** 2276,2291 ****
*/
typedef struct
{
! buf_T *save_buf; /* saved curbuf */
#ifdef FEAT_AUTOCMD
! buf_T *new_curbuf; /* buffer to be used */
! win_T *save_curwin; /* saved curwin, NULL if it didn't change */
! win_T *new_curwin; /* new curwin if save_curwin != NULL */
! pos_T save_cursor; /* saved cursor pos of save_curwin */
! linenr_T save_topline; /* saved topline of save_curwin */
! # ifdef FEAT_DIFF
! int save_topfill; /* saved topfill of save_curwin */
! # endif
#endif
} aco_save_T;
--- 2284,2294 ----
*/
typedef struct
{
! buf_T *save_curbuf; /* saved curbuf */
#ifdef FEAT_AUTOCMD
! win_T *save_curwin; /* saved curwin */
! win_T *new_curwin; /* new curwin */
! buf_T *new_curbuf; /* new curbuf */
#endif
} aco_save_T;
*** ../vim-7.2.197/src/window.c 2009-05-21 23:25:38.000000000 +0200
--- src/window.c 2009-06-10 21:20:27.000000000 +0200
***************
*** 11,18 ****
static int path_is_url __ARGS((char_u *p));
#if defined(FEAT_WINDOWS) || defined(PROTO)
! static int win_split_ins __ARGS((int size, int flags, win_T *newwin, int
dir));
static void win_init __ARGS((win_T *newp, win_T *oldp, int flags));
static void frame_comp_pos __ARGS((frame_T *topfrp, int *row, int *col));
static void frame_setheight __ARGS((frame_T *curfrp, int height));
#ifdef FEAT_VERTSPLIT
--- 11,19 ----
static int path_is_url __ARGS((char_u *p));
#if defined(FEAT_WINDOWS) || defined(PROTO)
! static void new_frame __ARGS((win_T *wp));
static void win_init __ARGS((win_T *newp, win_T *oldp, int flags));
+ static void win_init_some __ARGS((win_T *newp, win_T *oldp));
static void frame_comp_pos __ARGS((frame_T *topfrp, int *row, int *col));
static void frame_setheight __ARGS((frame_T *curfrp, int height));
#ifdef FEAT_VERTSPLIT
***************
*** 23,30 ****
static void win_totop __ARGS((int size, int flags));
static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T
*topfr, int dir, int col, int row, int width, int height));
static int last_window __ARGS((void));
static win_T *win_free_mem __ARGS((win_T *win, int *dirp, tabpage_T *tp));
- static win_T *winframe_remove __ARGS((win_T *win, int *dirp, tabpage_T *tp));
static frame_T *win_altframe __ARGS((win_T *win, tabpage_T *tp));
static tabpage_T *alt_tabpage __ARGS((void));
static win_T *frame2win __ARGS((frame_T *frp));
--- 24,31 ----
static void win_totop __ARGS((int size, int flags));
static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T
*topfr, int dir, int col, int row, int width, int height));
static int last_window __ARGS((void));
+ static int one_window __ARGS((void));
static win_T *win_free_mem __ARGS((win_T *win, int *dirp, tabpage_T *tp));
static frame_T *win_altframe __ARGS((win_T *win, tabpage_T *tp));
static tabpage_T *alt_tabpage __ARGS((void));
static win_T *frame2win __ARGS((frame_T *frp));
***************
*** 49,56 ****
static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
static void win_free __ARGS((win_T *wp, tabpage_T *tp));
- static void win_append __ARGS((win_T *, win_T *));
- static void win_remove __ARGS((win_T *, tabpage_T *tp));
static void frame_append __ARGS((frame_T *after, frame_T *frp));
static void frame_insert __ARGS((frame_T *before, frame_T *frp));
static void frame_remove __ARGS((frame_T *frp));
--- 50,55 ----
***************
*** 62,78 ****
static void frame_add_height __ARGS((frame_T *frp, int n));
static void last_status_rec __ARGS((frame_T *fr, int statusline));
- static void make_snapshot __ARGS((void));
static void make_snapshot_rec __ARGS((frame_T *fr, frame_T **frp));
! static void clear_snapshot __ARGS((tabpage_T *tp));
static void clear_snapshot_rec __ARGS((frame_T *fr));
- static void restore_snapshot __ARGS((int close_curwin));
static int check_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
#endif /* FEAT_WINDOWS */
! static win_T *win_alloc __ARGS((win_T *after));
static void win_new_height __ARGS((win_T *, int));
#define URL_SLASH 1 /* path_is_url() has found "://" */
--- 61,75 ----
static void frame_add_height __ARGS((frame_T *frp, int n));
static void last_status_rec __ARGS((frame_T *fr, int statusline));
static void make_snapshot_rec __ARGS((frame_T *fr, frame_T **frp));
! static void clear_snapshot __ARGS((tabpage_T *tp, int idx));
static void clear_snapshot_rec __ARGS((frame_T *fr));
static int check_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
#endif /* FEAT_WINDOWS */
! static win_T *win_alloc __ARGS((win_T *after, int hidden));
static void win_new_height __ARGS((win_T *, int));
#define URL_SLASH 1 /* path_is_url() has found "://" */
***************
*** 259,265 ****
/* cursor to previous window with wrap around */
case 'W':
CHECK_CMDWIN
! if (lastwin == firstwin && Prenum != 1) /* just one window */
beep_flush();
else
{
--- 256,262 ----
/* cursor to previous window with wrap around */
case 'W':
CHECK_CMDWIN
! if (firstwin == lastwin && Prenum != 1) /* just one window */
beep_flush();
else
{
***************
*** 343,349 ****
/* move window to new tab page */
case 'T':
! if (firstwin == lastwin)
MSG(_(m_onlyone));
else
{
--- 340,346 ----
/* move window to new tab page */
case 'T':
! if (one_window())
MSG(_(m_onlyone));
else
{
***************
*** 679,687 ****
/* When creating the help window make a snapshot of the window layout.
* Otherwise clear the snapshot, it's now invalid. */
if (flags & WSP_HELP)
! make_snapshot();
else
! clear_snapshot(curtab);
return win_split_ins(size, flags, NULL, 0);
}
--- 676,684 ----
/* When creating the help window make a snapshot of the window layout.
* Otherwise clear the snapshot, it's now invalid. */
if (flags & WSP_HELP)
! make_snapshot(SNAP_HELP_IDX);
else
! clear_snapshot(curtab, SNAP_HELP_IDX);
return win_split_ins(size, flags, NULL, 0);
}
***************
*** 692,698 ****
* top/left/right/bottom.
* return FAIL for failure, OK otherwise
*/
! static int
win_split_ins(size, flags, newwin, dir)
int size;
int flags;
--- 689,695 ----
* top/left/right/bottom.
* return FAIL for failure, OK otherwise
*/
! int
win_split_ins(size, flags, newwin, dir)
int size;
int flags;
***************
*** 893,906 ****
{
/* new window below/right of current one */
if (newwin == NULL)
! wp = win_alloc(oldwin);
else
win_append(oldwin, wp);
}
else
{
if (newwin == NULL)
! wp = win_alloc(oldwin->w_prev);
else
win_append(oldwin->w_prev, wp);
}
--- 890,903 ----
{
/* new window below/right of current one */
if (newwin == NULL)
! wp = win_alloc(oldwin, FALSE);
else
win_append(oldwin, wp);
}
else
{
if (newwin == NULL)
! wp = win_alloc(oldwin->w_prev, FALSE);
else
win_append(oldwin->w_prev, wp);
}
***************
*** 910,915 ****
--- 907,919 ----
if (wp == NULL)
return FAIL;
+ new_frame(wp);
+ if (wp->w_frame == NULL)
+ {
+ win_free(wp, NULL);
+ return FAIL;
+ }
+
/* make the contents of the new window the same as the current one */
win_init(wp, curwin, flags);
}
***************
*** 970,982 ****
}
if (newwin == NULL)
! {
! /* Create a frame for the new window. */
! frp = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
! frp->fr_layout = FR_LEAF;
! frp->fr_win = wp;
! wp->w_frame = frp;
! }
else
frp = newwin->w_frame;
frp->fr_parent = curfrp->fr_parent;
--- 974,980 ----
}
if (newwin == NULL)
! frp = wp->w_frame;
else
frp = newwin->w_frame;
frp->fr_parent = curfrp->fr_parent;
***************
*** 1156,1161 ****
--- 1154,1176 ----
return OK;
}
+
+ /*
+ * Create a frame for window "wp".
+ */
+ static void
+ new_frame(win_T *wp)
+ {
+ frame_T *frp = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
+
+ wp->w_frame = frp;
+ if (frp != NULL)
+ {
+ frp->fr_layout = FR_LEAF;
+ frp->fr_win = wp;
+ }
+ }
+
/*
* Initialize window "newp" from window "oldp".
* Used when splitting a window and when creating a new tab page.
***************
*** 1204,1217 ****
if (oldp->w_localdir != NULL)
newp->w_localdir = vim_strsave(oldp->w_localdir);
! /* Use the same argument list. */
! newp->w_alist = oldp->w_alist;
! ++newp->w_alist->al_refcount;
! newp->w_arg_idx = oldp->w_arg_idx;
!
! /*
! * copy tagstack and options from existing window
! */
for (i = 0; i < oldp->w_tagstacklen; i++)
{
newp->w_tagstack[i] = oldp->w_tagstack[i];
--- 1219,1225 ----
if (oldp->w_localdir != NULL)
newp->w_localdir = vim_strsave(oldp->w_localdir);
! /* copy tagstack and folds */
for (i = 0; i < oldp->w_tagstacklen; i++)
{
newp->w_tagstack[i] = oldp->w_tagstack[i];
***************
*** 1221,1230 ****
}
newp->w_tagstackidx = oldp->w_tagstackidx;
newp->w_tagstacklen = oldp->w_tagstacklen;
- win_copy_options(oldp, newp);
# ifdef FEAT_FOLDING
copyFoldingState(oldp, newp);
# endif
}
#endif /* FEAT_WINDOWS */
--- 1229,1257 ----
}
newp->w_tagstackidx = oldp->w_tagstackidx;
newp->w_tagstacklen = oldp->w_tagstacklen;
# ifdef FEAT_FOLDING
copyFoldingState(oldp, newp);
# endif
+
+ win_init_some(newp, oldp);
+ }
+
+ /*
+ * Initialize window "newp" from window"old".
+ * Only the essential things are copied.
+ */
+ static void
+ win_init_some(newp, oldp)
+ win_T *newp;
+ win_T *oldp;
+ {
+ /* Use the same argument list. */
+ newp->w_alist = oldp->w_alist;
+ ++newp->w_alist->al_refcount;
+ newp->w_arg_idx = oldp->w_arg_idx;
+
+ /* copy options from existing window */
+ win_copy_options(oldp, newp);
}
#endif /* FEAT_WINDOWS */
***************
*** 2048,2060 ****
}
/*
! * Return TRUE if the current window is the only window that exists.
* Returns FALSE if there is a window, possibly in another tab page.
*/
static int
last_window()
{
! return (lastwin == firstwin && first_tabpage->tp_next == NULL);
}
/*
--- 2075,2114 ----
}
/*
! * 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
last_window()
{
! return (one_window() && first_tabpage->tp_next == NULL);
! }
!
! /*
! * Return TRUE if there is only one window other than "aucmd_win" in the
! * current tab page.
! */
! static int
! one_window()
! {
! #ifdef FEAT_AUTOCMD
! win_T *wp;
! int seen_one = FALSE;
!
! FOR_ALL_WINDOWS(wp)
! {
! if (wp != aucmd_win)
! {
! if (seen_one)
! return FALSE;
! seen_one = TRUE;
! }
! }
! return TRUE;
! #else
! return firstwin == lastwin;
! #endif
}
/*
***************
*** 2083,2088 ****
--- 2137,2155 ----
return;
}
+ #ifdef FEAT_AUTOCMD
+ if (win == aucmd_win)
+ {
+ EMSG(_("E813: Cannot close autocmd window"));
+ return;
+ }
+ if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
+ {
+ EMSG(_("E814: Cannot close window, only autocmd window would remain"));
+ return;
+ }
+ #endif
+
/*
* When closing the last window in a tab page first go to another tab
* page and then close the window and the tab page. This avoids that
***************
*** 2112,2118 ****
if (win->w_buffer->b_help)
help_window = TRUE;
else
! clear_snapshot(curtab);
#ifdef FEAT_AUTOCMD
if (win == curwin)
--- 2179,2185 ----
if (win->w_buffer->b_help)
help_window = TRUE;
else
! clear_snapshot(curtab, SNAP_HELP_IDX);
#ifdef FEAT_AUTOCMD
if (win == curwin)
***************
*** 2229,2235 ****
/* After closing the help window, try restoring the window layout from
* before it was opened. */
if (help_window)
! restore_snapshot(close_curwin);
#if defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)
/* When 'guioptions' includes 'L' or 'R' may have to remove scrollbars. */
--- 2296,2302 ----
/* After closing the help window, try restoring the window layout from
* before it was opened. */
if (help_window)
! restore_snapshot(SNAP_HELP_IDX, close_curwin);
#if defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)
/* When 'guioptions' includes 'L' or 'R' may have to remove scrollbars. */
***************
*** 2344,2349 ****
--- 2411,2424 ----
while (firstwin != NULL)
(void)win_free_mem(firstwin, &dummy, NULL);
+
+ # ifdef FEAT_AUTOCMD
+ if (aucmd_win != NULL)
+ {
+ (void)win_free_mem(aucmd_win, &dummy, NULL);
+ aucmd_win = NULL;
+ }
+ # endif
}
#endif
***************
*** 2351,2357 ****
* Remove a window and its frame from the tree of frames.
* Returns a pointer to the window that got the freed up space.
*/
! static win_T *
winframe_remove(win, dirp, tp)
win_T *win;
int *dirp UNUSED; /* set to 'v' or 'h' for direction if
'ea' */
--- 2426,2432 ----
* Remove a window and its frame from the tree of frames.
* Returns a pointer to the window that got the freed up space.
*/
! win_T *
winframe_remove(win, dirp, tp)
win_T *win;
int *dirp UNUSED; /* set to 'v' or 'h' for direction if
'ea' */
***************
*** 3090,3096 ****
win_T *nextwp;
int r;
! if (lastwin == firstwin)
{
if (message
#ifdef FEAT_AUTOCMD
--- 3165,3171 ----
win_T *nextwp;
int r;
! if (one_window())
{
if (message
#ifdef FEAT_AUTOCMD
***************
*** 3194,3202 ****
--- 3269,3298 ----
first_tabpage->tp_topframe = topframe;
curtab = first_tabpage;
#endif
+
return OK;
}
+ #if defined(FEAT_AUTOCMD) || defined(PROTO)
+ /*
+ * Init "aucmd_win". This can only be done after the first
+ * window is fully initialized, thus it can't be in win_alloc_first().
+ */
+ void
+ win_alloc_aucmd_win()
+ {
+ aucmd_win = win_alloc(NULL, TRUE);
+ if (aucmd_win != NULL)
+ {
+ win_init_some(aucmd_win, curwin);
+ # ifdef FEAT_SCROLLBIND
+ aucmd_win->w_p_scb = FALSE;
+ # endif
+ new_frame(aucmd_win);
+ }
+ }
+ #endif
+
/*
* Allocate the first window or the first window in a new tab page.
* When "oldwin" is NULL create an empty buffer for it.
***************
*** 3208,3214 ****
win_alloc_firstwin(oldwin)
win_T *oldwin;
{
! curwin = win_alloc(NULL);
if (oldwin == NULL)
{
/* Very first window, need to create an empty buffer for it and
--- 3304,3310 ----
win_alloc_firstwin(oldwin)
win_T *oldwin;
{
! curwin = win_alloc(NULL, FALSE);
if (oldwin == NULL)
{
/* Very first window, need to create an empty buffer for it and
***************
*** 3236,3251 ****
}
#endif
! topframe = (frame_T *)alloc_clear((unsigned)sizeof(frame_T));
! if (topframe == NULL)
return FAIL;
! topframe->fr_layout = FR_LEAF;
#ifdef FEAT_VERTSPLIT
topframe->fr_width = Columns;
#endif
topframe->fr_height = Rows - p_ch;
topframe->fr_win = curwin;
- curwin->w_frame = topframe;
return OK;
}
--- 3332,3346 ----
}
#endif
! new_frame(curwin);
! if (curwin->w_frame == NULL)
return FAIL;
! topframe = curwin->w_frame;
#ifdef FEAT_VERTSPLIT
topframe->fr_width = Columns;
#endif
topframe->fr_height = Rows - p_ch;
topframe->fr_win = curwin;
return OK;
}
***************
*** 3300,3309 ****
free_tabpage(tp)
tabpage_T *tp;
{
# ifdef FEAT_DIFF
diff_clear(tp);
# endif
! clear_snapshot(tp);
#ifdef FEAT_EVAL
vars_clear(&tp->tp_vars.dv_hashtab); /* free all t: variables */
#endif
--- 3395,3407 ----
free_tabpage(tp)
tabpage_T *tp;
{
+ int idx;
+
# ifdef FEAT_DIFF
diff_clear(tp);
# endif
! for (idx = 0; idx < SNAP_COUNT; ++idx)
! clear_snapshot(tp, idx);
#ifdef FEAT_EVAL
vars_clear(&tp->tp_vars.dv_hashtab); /* free all t: variables */
#endif
***************
*** 4150,4160 ****
#endif
/*
! * allocate a window structure and link it in the window list
*/
static win_T *
! win_alloc(after)
win_T *after UNUSED;
{
win_T *newwin;
--- 4248,4260 ----
#endif
/*
! * Allocate a window structure and link it in the window list when "hidden" is
! * FALSE.
*/
static win_T *
! win_alloc(after, hidden)
win_T *after UNUSED;
+ int hidden UNUSED;
{
win_T *newwin;
***************
*** 4180,4186 ****
* link the window in the window list
*/
#ifdef FEAT_WINDOWS
! win_append(after, newwin);
#endif
#ifdef FEAT_VERTSPLIT
newwin->w_wincol = 0;
--- 4280,4287 ----
* link the window in the window list
*/
#ifdef FEAT_WINDOWS
! if (!hidden)
! win_append(after, newwin);
#endif
#ifdef FEAT_VERTSPLIT
newwin->w_wincol = 0;
***************
*** 4314,4320 ****
/*
* Append window "wp" in the window list after window "after".
*/
! static void
win_append(after, wp)
win_T *after, *wp;
{
--- 4415,4421 ----
/*
* Append window "wp" in the window list after window "after".
*/
! void
win_append(after, wp)
win_T *after, *wp;
{
***************
*** 4340,4346 ****
/*
* Remove a window from the window list.
*/
! static void
win_remove(wp, tp)
win_T *wp;
tabpage_T *tp; /* tab page "win" is in, NULL for current */
--- 4441,4447 ----
/*
* Remove a window from the window list.
*/
! void
win_remove(wp, tp)
win_T *wp;
tabpage_T *tp; /* tab page "win" is in, NULL for current */
***************
*** 6040,6045 ****
--- 6141,6147 ----
/*
* Return TRUE if there is only one window (in the current tab page), not
* counting a help or preview window, unless it is the current window.
+ * Does not count "aucmd_win".
*/
int
only_one_window()
***************
*** 6053,6063 ****
return FALSE;
for (wp = firstwin; wp != NULL; wp = wp->w_next)
! if (!((wp->w_buffer->b_help && !curbuf->b_help)
# ifdef FEAT_QUICKFIX
|| wp->w_p_pvw
# endif
) || wp == curwin)
++count;
return (count <= 1);
#else
--- 6155,6169 ----
return FALSE;
for (wp = firstwin; wp != NULL; wp = wp->w_next)
! if ((!((wp->w_buffer->b_help && !curbuf->b_help)
# ifdef FEAT_QUICKFIX
|| wp->w_p_pvw
# endif
) || wp == curwin)
+ # ifdef FEAT_AUTOCMD
+ && wp != aucmd_win
+ # endif
+ )
++count;
return (count <= 1);
#else
***************
*** 6112,6122 ****
/*
* Create a snapshot of the current frame sizes.
*/
! static void
! make_snapshot()
{
! clear_snapshot(curtab);
! make_snapshot_rec(topframe, &curtab->tp_snapshot);
}
static void
--- 6218,6229 ----
/*
* Create a snapshot of the current frame sizes.
*/
! void
! make_snapshot(idx)
! int idx;
{
! clear_snapshot(curtab, idx);
! make_snapshot_rec(topframe, &curtab->tp_snapshot[idx]);
}
static void
***************
*** 6144,6154 ****
* Remove any existing snapshot.
*/
static void
! clear_snapshot(tp)
tabpage_T *tp;
{
! clear_snapshot_rec(tp->tp_snapshot);
! tp->tp_snapshot = NULL;
}
static void
--- 6251,6262 ----
* Remove any existing snapshot.
*/
static void
! clear_snapshot(tp, idx)
tabpage_T *tp;
+ int idx;
{
! clear_snapshot_rec(tp->tp_snapshot[idx]);
! tp->tp_snapshot[idx] = NULL;
}
static void
***************
*** 6168,6193 ****
* This is only done if the screen size didn't change and the window layout is
* still the same.
*/
! static void
! restore_snapshot(close_curwin)
int close_curwin; /* closing current window */
{
win_T *wp;
! if (curtab->tp_snapshot != NULL
# ifdef FEAT_VERTSPLIT
! && curtab->tp_snapshot->fr_width == topframe->fr_width
# endif
! && curtab->tp_snapshot->fr_height == topframe->fr_height
! && check_snapshot_rec(curtab->tp_snapshot, topframe) == OK)
{
! wp = restore_snapshot_rec(curtab->tp_snapshot, topframe);
win_comp_pos();
if (wp != NULL && close_curwin)
win_goto(wp);
redraw_all_later(CLEAR);
}
! clear_snapshot(curtab);
}
/*
--- 6276,6302 ----
* This is only done if the screen size didn't change and the window layout is
* still the same.
*/
! void
! restore_snapshot(idx, close_curwin)
! int idx;
int close_curwin; /* closing current window */
{
win_T *wp;
! if (curtab->tp_snapshot[idx] != NULL
# ifdef FEAT_VERTSPLIT
! && curtab->tp_snapshot[idx]->fr_width == topframe->fr_width
# endif
! && curtab->tp_snapshot[idx]->fr_height == topframe->fr_height
! && check_snapshot_rec(curtab->tp_snapshot[idx], topframe) == OK)
{
! wp = restore_snapshot_rec(curtab->tp_snapshot[idx], topframe);
win_comp_pos();
if (wp != NULL && close_curwin)
win_goto(wp);
redraw_all_later(CLEAR);
}
! clear_snapshot(curtab, idx);
}
/*
--
Shift happens.
-- Doppler
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ download, build and distribute -- http://www.A-A-P.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---