summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c249
1 files changed, 197 insertions, 52 deletions
diff --git a/src/window.c b/src/window.c
index 116a5fc7f..927c7a15e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -25,9 +25,9 @@ static void win_exchange __ARGS((long));
static void win_rotate __ARGS((int, int));
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 win_T *win_free_mem __ARGS((win_T *win, int *dirp));
-static win_T *winframe_remove __ARGS((win_T *win, int *dirp));
-static frame_T *win_altframe __ARGS((win_T *win));
+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));
static int frame_has_win __ARGS((frame_T *frp, win_T *wp));
@@ -49,9 +49,9 @@ static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf));
static void frame_fix_height __ARGS((win_T *wp));
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));
+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 *));
+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));
@@ -1262,14 +1262,14 @@ win_exchange(Prenum)
frp2 = curwin->w_frame->fr_prev;
if (wp->w_prev != curwin)
{
- win_remove(curwin);
+ win_remove(curwin, NULL);
frame_remove(curwin->w_frame);
win_append(wp->w_prev, curwin);
frame_insert(frp, curwin->w_frame);
}
if (wp != wp2)
{
- win_remove(wp);
+ win_remove(wp, NULL);
frame_remove(wp->w_frame);
win_append(wp2, wp);
if (frp2 == NULL)
@@ -1353,7 +1353,7 @@ win_rotate(upwards, count)
/* remove first window/frame from the list */
frp = curwin->w_frame->fr_parent->fr_child;
wp1 = frp->fr_win;
- win_remove(wp1);
+ win_remove(wp1, NULL);
frame_remove(frp);
/* find last frame and append removed window/frame after it */
@@ -1372,7 +1372,7 @@ win_rotate(upwards, count)
;
wp1 = frp->fr_win;
wp2 = wp1->w_prev; /* will become last window */
- win_remove(wp1);
+ win_remove(wp1, NULL);
frame_remove(frp);
/* append the removed window/frame before the first in the list */
@@ -1419,8 +1419,8 @@ win_totop(size, flags)
}
/* Remove the window and frame from the tree of frames. */
- (void)winframe_remove(curwin, &dir);
- win_remove(curwin);
+ (void)winframe_remove(curwin, &dir, NULL);
+ win_remove(curwin, NULL);
last_status(FALSE); /* may need to remove last status line */
(void)win_comp_pos(); /* recompute window positions */
@@ -1486,7 +1486,7 @@ win_move_after(win1, win2)
win1->w_vsep_width = 0;
#endif
}
- win_remove(win1);
+ win_remove(win1, NULL);
frame_remove(win1->w_frame);
win_append(win2, win1);
frame_append(win2->w_frame, win1->w_frame);
@@ -1797,23 +1797,50 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
* close all windows for buffer 'buf'
*/
void
-close_windows(buf)
+close_windows(buf, keep_curwin)
buf_T *buf;
+ int keep_curwin; /* don't close "curwin" */
{
- win_T *win;
+ win_T *wp;
+ tabpage_T *tp, *nexttp;
+ int h = tabpageline_height();
++RedrawingDisabled;
- for (win = firstwin; win != NULL && lastwin != firstwin; )
+
+ for (wp = firstwin; wp != NULL && lastwin != firstwin; )
{
- if (win->w_buffer == buf)
+ if (wp->w_buffer == buf && (!keep_curwin || wp != curwin))
{
- win_close(win, FALSE);
- win = firstwin; /* go back to the start */
+ win_close(wp, FALSE);
+
+ /* Start all over, autocommands may change the window layout. */
+ wp = firstwin;
}
else
- win = win->w_next;
+ wp = wp->w_next;
}
+
+ /* Also check windows in other tab pages. */
+ for (tp = first_tabpage; tp != NULL; tp = nexttp)
+ {
+ nexttp = tp->tp_next;
+ if (tp->tp_topframe != topframe)
+ for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
+ if (wp->w_buffer == buf)
+ {
+ win_close_othertab(wp, FALSE, tp);
+
+ /* Start all over, the tab page may be closed and
+ * autocommands may change the window layout. */
+ nexttp = first_tabpage;
+ break;
+ }
+ }
+
--RedrawingDisabled;
+
+ if (h != tabpageline_height())
+ shell_new_rows();
}
/*
@@ -1827,7 +1854,7 @@ last_window()
}
/*
- * close window "win"
+ * Close window "win".
* If "free_buf" is TRUE related buffer may be unloaded.
*
* called by :quit, :close, :xit, :wq and findtag()
@@ -1866,7 +1893,7 @@ win_close(win, free_buf)
* Guess which window is going to be the new current window.
* This may change because of the autocommands (sigh).
*/
- wp = frame2win(win_altframe(win));
+ wp = frame2win(win_altframe(win, NULL));
/*
* Be careful: If autocommands delete the window, return now.
@@ -1899,7 +1926,7 @@ win_close(win, free_buf)
return;
/* Free the memory used for the window. */
- wp = win_free_mem(win, &dir);
+ wp = win_free_mem(win, &dir, NULL);
/* When closing the last window in a tab page go to another tab page. */
if (wp == NULL)
@@ -2004,13 +2031,70 @@ win_close(win, free_buf)
}
/*
+ * Close window "win" in tab page "tp", which is not the current tab page.
+ * This may be the last window ih that tab page and result in closing the tab,
+ * thus "tp" may become invalid!
+ * Called must check if buffer is hidden.
+ */
+ void
+win_close_othertab(win, free_buf, tp)
+ win_T *win;
+ int free_buf;
+ tabpage_T *tp;
+{
+ win_T *wp;
+ int dir;
+ tabpage_T *ptp = NULL;
+
+ /* Close the link to the buffer. */
+ close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0);
+
+ /* Careful: Autocommands may have closed the tab page or made it the
+ * current tab page. */
+ for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next)
+ ;
+ if (ptp == NULL || tp->tp_topframe == topframe)
+ return;
+
+ /* Autocommands may have closed the window already. */
+ for (wp = tp->tp_firstwin; wp != NULL && wp != win; wp = wp->w_next)
+ ;
+ if (wp == NULL)
+ return;
+
+ /* Free the memory used for the window. */
+ wp = win_free_mem(win, &dir, tp);
+
+ /* When closing the last window in a tab page remove the tab page. */
+ if (wp == NULL)
+ {
+ if (tp == first_tabpage)
+ first_tabpage = tp->tp_next;
+ else
+ {
+ for (ptp = first_tabpage; ptp != NULL && ptp->tp_next != tp;
+ ptp = ptp->tp_next)
+ ;
+ if (ptp == NULL)
+ {
+ EMSG2(_(e_intern2), "win_close_othertab()");
+ return;
+ }
+ ptp->tp_next = tp->tp_next;
+ }
+ vim_free(tp);
+ }
+}
+
+/*
* Free the memory used for a window.
* Returns a pointer to the window that got the freed up space.
*/
static win_T *
-win_free_mem(win, dirp)
+win_free_mem(win, dirp, tp)
win_T *win;
int *dirp; /* set to 'v' or 'h' for direction if 'ea' */
+ tabpage_T *tp; /* tab page "win" is in, NULL for current */
{
frame_T *frp;
win_T *wp;
@@ -2024,13 +2108,9 @@ win_free_mem(win, dirp)
/* Remove the window and its frame from the tree of frames. */
frp = win->w_frame;
- if (firstwin == lastwin)
- /* Last window in a tab page. */
- wp = NULL;
- else
- wp = winframe_remove(win, dirp);
+ wp = winframe_remove(win, dirp, tp);
vim_free(frp);
- win_free(win);
+ win_free(win, tp);
return wp;
}
@@ -2041,8 +2121,13 @@ win_free_all()
{
int dummy;
+# ifdef FEAT_WINDOWS
+ while (first_tabpage->tp_next != NULL)
+ tabpage_close(TRUE);
+# endif
+
while (firstwin != NULL)
- (void)win_free_mem(firstwin, &dummy);
+ (void)win_free_mem(firstwin, &dummy, NULL);
}
#endif
@@ -2052,9 +2137,10 @@ win_free_all()
*/
/*ARGSUSED*/
static win_T *
-winframe_remove(win, dirp)
+winframe_remove(win, dirp, tp)
win_T *win;
int *dirp; /* set to 'v' or 'h' for direction if 'ea' */
+ tabpage_T *tp; /* tab page "win" is in, NULL for current */
{
frame_T *frp, *frp2, *frp3;
frame_T *frp_close = win->w_frame;
@@ -2062,12 +2148,15 @@ winframe_remove(win, dirp)
int old_height = 0;
/*
- * Remove the window from its frame.
+ * If there is only one window there is nothing to remove.
*/
- frp2 = win_altframe(win);
- if (frp2 == NULL)
- return NULL; /* deleted the last frame */
+ if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
+ return NULL;
+ /*
+ * Remove the window from its frame.
+ */
+ frp2 = win_altframe(win, tp);
wp = frame2win(frp2);
/* Remove this frame from the list of frames. */
@@ -2160,13 +2249,14 @@ winframe_remove(win, dirp)
* layout.
*/
static frame_T *
-win_altframe(win)
+win_altframe(win, tp)
win_T *win;
+ tabpage_T *tp; /* tab page "win" is in, NULL for current */
{
frame_T *frp;
int b;
- if (firstwin == lastwin)
+ if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
/* Last window in this tab page, will go to next tab page. */
return alt_tabpage()->tp_curwin->w_frame;
@@ -2861,6 +2951,7 @@ win_new_tabpage()
firstwin->w_winrow = tabpageline_height();
newtp->tp_topframe = topframe;
+ last_status(FALSE);
redraw_all_later(CLEAR);
return OK;
}
@@ -2868,6 +2959,7 @@ win_new_tabpage()
/* Failed, get back the previous Tab page */
topframe = tp->tp_topframe;
curwin = tp->tp_curwin;
+ prevwin = tp->tp_prevwin;
firstwin = tp->tp_firstwin;
lastwin = tp->tp_lastwin;
return FAIL;
@@ -2890,6 +2982,36 @@ current_tabpage()
}
/*
+ * Return TRUE when "tpc" points to a valid tab page.
+ */
+ int
+valid_tabpage(tpc)
+ tabpage_T *tpc;
+{
+ tabpage_T *tp;
+
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+ if (tp == tpc)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Find tab page "n" (first one is 1). Returns NULL when not found.
+ */
+ tabpage_T *
+find_tabpage(n)
+ int n;
+{
+ tabpage_T *tp;
+ int i = 1;
+
+ for (tp = first_tabpage; tp != NULL && i != n; tp = tp->tp_next)
+ ++i;
+ return tp;
+}
+
+/*
* Prepare for leaving the current tab page "tp".
*/
static void
@@ -2902,6 +3024,7 @@ leave_tabpage(tp)
gui_remove_scrollbars();
#endif
tp->tp_curwin = curwin;
+ tp->tp_prevwin = prevwin;
tp->tp_firstwin = firstwin;
tp->tp_lastwin = lastwin;
tp->tp_old_Rows = Rows;
@@ -2925,6 +3048,7 @@ enter_tabpage(tp, old_curbuf)
lastwin = tp->tp_lastwin;
topframe = tp->tp_topframe;
win_enter_ext(tp->tp_curwin, FALSE, TRUE);
+ prevwin = tp->tp_prevwin;
#ifdef FEAT_AUTOCMD
if (old_curbuf != curbuf)
@@ -2985,12 +3109,13 @@ goto_tabpage(n)
{
/* Go to tab page "n". */
i = 0;
- for (tp = first_tabpage; ++i != n; tp = tp->tp_next)
- if (tp == NULL)
- {
- beep_flush();
- return;
- }
+ for (tp = first_tabpage; ++i != n && tp != NULL; tp = tp->tp_next)
+ ;
+ if (tp == NULL)
+ {
+ beep_flush();
+ return;
+ }
}
leave_tabpage(otp);
@@ -3418,8 +3543,9 @@ win_alloc(after)
* remove window 'wp' from the window list and free the structure
*/
static void
-win_free(wp)
+win_free(wp, tp)
win_T *wp;
+ tabpage_T *tp; /* tab page "win" is in, NULL for current */
{
int i;
@@ -3478,7 +3604,7 @@ win_free(wp)
}
#endif /* FEAT_GUI */
- win_remove(wp);
+ win_remove(wp, tp);
vim_free(wp);
}
@@ -3512,17 +3638,22 @@ win_append(after, wp)
* Remove a window from the window list.
*/
static void
-win_remove(wp)
+win_remove(wp, tp)
win_T *wp;
+ tabpage_T *tp; /* tab page "win" is in, NULL for current */
{
if (wp->w_prev != NULL)
wp->w_prev->w_next = wp->w_next;
- else
+ else if (tp == NULL)
firstwin = wp->w_next;
+ else
+ tp->tp_firstwin = wp->w_next;
if (wp->w_next != NULL)
wp->w_next->w_prev = wp->w_prev;
- else
+ else if (tp == NULL)
lastwin = wp->w_prev;
+ else
+ tp->tp_lastwin = wp->w_prev;
}
/*
@@ -3600,6 +3731,7 @@ win_free_lsize(wp)
/*
* Called from win_new_shellsize() after Rows changed.
+ * This only does the current tab page, others must be done when made active.
*/
void
shell_new_rows()
@@ -5115,16 +5247,27 @@ vim_FullName(fname, buf, len, force)
min_rows()
{
int total;
+#ifdef FEAT_WINDOWS
+ tabpage_T *tp;
+ int n;
+#endif
if (firstwin == NULL) /* not initialized yet */
return MIN_LINES;
- total = 1; /* count the room for the command line */
#ifdef FEAT_WINDOWS
- total += frame_minheight(topframe, NULL);
+ total = 0;
+ for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+ {
+ n = frame_minheight(tp->tp_topframe, NULL);
+ if (total < n)
+ total = n;
+ }
+ total += tabpageline_height();
#else
- total += 1; /* at least one window should have a line! */
+ total = 1; /* at least one window should have a line! */
#endif
+ total += 1; /* count the room for the command line */
return total;
}
@@ -5169,7 +5312,9 @@ check_lnums(do_curwin)
win_T *wp;
#ifdef FEAT_WINDOWS
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ tabpage_T *tp;
+
+ FOR_ALL_TAB_WINDOWS(tp, wp)
if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf)
#else
wp = curwin;