Mercurial > vim
diff src/window.c @ 667:9090f866cd57 v7.0197
updated for version 7.0197
author | vimboss |
---|---|
date | Tue, 14 Feb 2006 22:29:30 +0000 |
parents | d3c978b4c7ce |
children | a29f98030753 |
line wrap: on
line diff
--- a/src/window.c +++ b/src/window.c @@ -29,6 +29,7 @@ static void win_equal_rec __ARGS((win_T 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 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)); static void frame_new_height __ARGS((frame_T *topfrp, int height, int topfirst, int wfh)); @@ -40,6 +41,12 @@ static void frame_add_vsep __ARGS((frame static int frame_minwidth __ARGS((frame_T *topfrp, win_T *next_curwin)); static void frame_fix_width __ARGS((win_T *wp)); #endif +#endif +static int win_alloc_firstwin __ARGS((void)); +#if defined(FEAT_WINDOWS) || defined(PROTO) +static tabpage_T *current_tabpage __ARGS((void)); +static void leave_tabpage __ARGS((tabpage_T *tp)); +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)); @@ -77,6 +84,9 @@ static void win_new_height __ARGS((win_T #ifdef FEAT_WINDOWS static long p_ch_used = 1L; /* value of 'cmdheight' when frame size was set */ +# define ROWS_AVAIL (Rows - p_ch - tabpageline_height()) +#else +# define ROWS_AVAIL (Rows - p_ch) #endif #if defined(FEAT_WINDOWS) || defined(PROTO) @@ -932,7 +942,7 @@ win_split_ins(size, flags, newwin, dir) if (flags & (WSP_TOP | WSP_BOT)) { /* set height and row of new window to full height */ - wp->w_winrow = 0; + wp->w_winrow = tabpageline_height(); wp->w_height = curfrp->fr_height - (p_ls > 0); wp->w_status_height = (p_ls > 0); } @@ -1507,7 +1517,8 @@ win_equal(next_curwin, current, dir) dir = 'b'; #endif win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current, - topframe, dir, 0, 0, (int)Columns, topframe->fr_height); + topframe, dir, 0, tabpageline_height(), + (int)Columns, topframe->fr_height); } /* @@ -1807,6 +1818,16 @@ close_windows(buf) } /* + * Return TRUE if the current window is the only window that exists. + * Returns FALSE if there is a window in another tab page. + */ + int +last_window() +{ + return (lastwin == firstwin && first_tabpage->tp_next == NULL); +} + +/* * close window "win" * If "free_buf" is TRUE related buffer may be unloaded. * @@ -1818,6 +1839,7 @@ win_close(win, free_buf) int free_buf; { win_T *wp; + buf_T *old_curbuf = curbuf; #ifdef FEAT_AUTOCMD int other_buffer = FALSE; #endif @@ -1825,7 +1847,7 @@ win_close(win, free_buf) int dir; int help_window = FALSE; - if (lastwin == firstwin) + if (last_window()) { EMSG(_("E444: Cannot close last window")); return; @@ -1854,11 +1876,11 @@ win_close(win, free_buf) { other_buffer = TRUE; apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); - if (!win_valid(win) || firstwin == lastwin) + if (!win_valid(win) || last_window()) return; } apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); - if (!win_valid(win) || firstwin == lastwin) + if (!win_valid(win) || last_window()) return; # ifdef FEAT_EVAL /* autocmds may abort script processing */ @@ -1874,16 +1896,42 @@ win_close(win, free_buf) close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0); /* Autocommands may have closed the window already, or closed the only * other window. */ - if (!win_valid(win) || firstwin == lastwin) + if (!win_valid(win) || last_window()) return; /* Free the memory used for the window. */ wp = win_free_mem(win, &dir); + /* When closing the last window in a tab page go to another tab page. */ + if (wp == NULL) + { + tabpage_T *ptp = NULL; + tabpage_T *tp; + tabpage_T *atp = alt_tabpage(); + + for (tp = first_tabpage; tp->tp_topframe != topframe; tp = tp->tp_next) + ptp = tp; + if (tp == NULL) + { + EMSG2(_(e_intern2), "win_close()"); + return; + } + if (ptp == NULL) + first_tabpage = tp->tp_next; + else + ptp->tp_next = tp->tp_next; + vim_free(tp); + + /* We don't do the window resizing stuff, let enter_tabpage() take + * care of entering a window in another tab page. */ + enter_tabpage(atp, old_curbuf); + return; + } + /* Make sure curwin isn't invalid. It can cause severe trouble when * printing an error message. For win_equal() curbuf needs to be valid * too. */ - if (win == curwin) + else if (win == curwin) { curwin = wp; #ifdef FEAT_QUICKFIX @@ -1937,8 +1985,8 @@ win_close(win, free_buf) } /* - * if last window has a status line now and we don't want one, - * remove the status line + * If last window has a status line now and we don't want one, + * remove the status line. */ last_status(FALSE); @@ -1975,9 +2023,13 @@ win_free_mem(win, dirp) /* reduce the reference count to the argument list. */ alist_unlink(win->w_alist); - /* remove the window and its frame from the tree of frames. */ + /* Remove the window and its frame from the tree of frames. */ frp = win->w_frame; - wp = winframe_remove(win, dirp); + if (firstwin == lastwin) + /* Last window in a tab page. */ + wp = NULL; + else + wp = winframe_remove(win, dirp); vim_free(frp); win_free(win); @@ -2115,6 +2167,10 @@ win_altframe(win) frame_T *frp; int b; + if (firstwin == lastwin) + /* Last window in this tab page, will go to next tab page. */ + return alt_tabpage()->tp_curwin->w_frame; + frp = win->w_frame; #ifdef FEAT_VERTSPLIT if (frp->fr_parent != NULL && frp->fr_parent->fr_layout == FR_ROW) @@ -2128,6 +2184,28 @@ win_altframe(win) } /* + * Return the tabpage that will be used if the current one is closed. + */ + static tabpage_T * +alt_tabpage() +{ + tabpage_T *tp = current_tabpage(); + + if (tp != NULL) + { + /* Use the next tab page if it exists. */ + if (tp->tp_next != NULL) + return tp->tp_next; + + /* Find the previous tab page. */ + for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next) + if (tp->tp_next == current_tabpage()) + return tp; + } + return first_tabpage; +} + +/* * Find the left-upper window in frame "frp". */ static win_T * @@ -2640,11 +2718,7 @@ close_others(message, forceit) } } - /* - * If current window has a status line and we don't want one, - * remove the status line. - */ - if (lastwin != firstwin) + if (message && lastwin != firstwin) EMSG(_("E445: Other window contains changes")); } @@ -2686,15 +2760,36 @@ win_init(wp) /* * Allocate the first window and put an empty buffer in it. * Called from main(). - * When this fails we can't do anything: exit. + * Return FAIL when something goes wrong (out of memory). */ - void + int win_alloc_first() { + if (win_alloc_firstwin() == FAIL) + return FAIL; + +#ifdef FEAT_WINDOWS + first_tabpage = (tabpage_T *)alloc((unsigned)sizeof(tabpage_T)); + if (first_tabpage == NULL) + return FAIL; + first_tabpage->tp_topframe = topframe; + first_tabpage->tp_next = NULL; +#endif + return OK; +} + +/* + * Allocate one window and put an empty buffer in it. + * Called to create the first window in a new tab page. + * Return FAIL when something goes wrong (out of memory). + */ + static int +win_alloc_firstwin() +{ curwin = win_alloc(NULL); curbuf = buflist_new(NULL, NULL, 1L, BLN_LISTED); if (curwin == NULL || curbuf == NULL) - mch_exit(0); + return FAIL; curwin->w_buffer = curbuf; curbuf->b_nwindows = 1; /* there is one window */ #ifdef FEAT_WINDOWS @@ -2704,7 +2799,7 @@ win_alloc_first() topframe = (frame_T *)alloc_clear((unsigned)sizeof(frame_T)); if (topframe == NULL) - mch_exit(0); + return FAIL; topframe->fr_layout = FR_LEAF; #ifdef FEAT_VERTSPLIT topframe->fr_width = Columns; @@ -2715,9 +2810,169 @@ win_alloc_first() #endif topframe->fr_win = curwin; curwin->w_frame = topframe; + + return OK; +} + +/* + * Initialize the window and frame size to the maximum. + */ + void +win_init_size() +{ + firstwin->w_height = ROWS_AVAIL; + topframe->fr_height = ROWS_AVAIL; +#ifdef FEAT_VERTSPLIT + firstwin->w_width = Columns; + topframe->fr_width = Columns; +#endif } #if defined(FEAT_WINDOWS) || defined(PROTO) +/* + * Create a new Tab page with one empty window. + * Put it just after the current Tab page. + * Return FAIL or OK. + */ + int +win_new_tabpage() +{ + tabpage_T *tp; + tabpage_T *newtp; + + newtp = (tabpage_T *)alloc((unsigned)sizeof(tabpage_T)); + if (newtp == NULL) + return FAIL; + + tp = current_tabpage(); + + /* Remember the current windows in this Tab page. */ + leave_tabpage(tp); + + /* Create a new empty window. */ + if (win_alloc_firstwin() == OK) + { + /* copy options from previous to new curwin */ + win_copy_options(tp->tp_curwin, curwin); + + /* Make the new Tab page the new topframe. */ + newtp->tp_next = tp->tp_next; + tp->tp_next = newtp; + win_init_size(); + firstwin->w_winrow = tabpageline_height(); + + newtp->tp_topframe = topframe; + redraw_all_later(CLEAR); + return OK; + } + + /* Failed, get back the previous Tab page */ + topframe = tp->tp_topframe; + curwin = tp->tp_curwin; + firstwin = tp->tp_firstwin; + lastwin = tp->tp_lastwin; + return FAIL; +} + +/* + * Return a pointer to the current tab page. + */ + static tabpage_T * +current_tabpage() +{ + tabpage_T *tp; + + for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) + if (tp->tp_topframe == topframe) + break; + if (tp == NULL) + EMSG2(_(e_intern2), "current_tabpage()"); + return tp; +} + +/* + * Prepare for leaving the current tab page "tp". + */ + static void +leave_tabpage(tp) + tabpage_T *tp; +{ + tp->tp_curwin = curwin; + tp->tp_firstwin = firstwin; + tp->tp_lastwin = lastwin; + firstwin = NULL; + lastwin = NULL; +} + +/* + * Start using tab page "tp". + */ +/*ARGSUSED*/ + static void +enter_tabpage(tp, old_curbuf) + tabpage_T *tp; + buf_T *old_curbuf; +{ + firstwin = tp->tp_firstwin; + lastwin = tp->tp_lastwin; + topframe = tp->tp_topframe; + win_enter_ext(tp->tp_curwin, FALSE, TRUE); + +#ifdef FEAT_AUTOCMD + if (old_curbuf != curbuf) + apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); +#endif + + /* status line may appear or disappear */ + last_status(FALSE); + +#if defined(FEAT_GUI) && defined(FEAT_VERTSPLIT) + /* When 'guioptions' includes 'L' or 'R' may have to add or remove + * scrollbars. */ + if (gui.in_use && !win_hasvertsplit()) + gui_init_which_components(NULL); +#endif + + redraw_all_later(CLEAR); +} + +/* + * Go to tab page "n". For ":tab N" and "Ngt". + */ + void +goto_tabpage(n) + int n; +{ + tabpage_T *otp = current_tabpage(); + tabpage_T *tp; + int i; + + if (otp == NULL) + return; + + if (n == 0) + { + /* No count, go to next tab page, wrap around end. */ + if (otp->tp_next == NULL) + tp = first_tabpage; + else + tp = otp->tp_next; + } + else + { + /* Go to tab page "n". */ + i = 0; + for (tp = first_tabpage; ++i != n; tp = tp->tp_next) + if (tp == NULL) + { + beep_flush(); + return; + } + } + + leave_tabpage(otp); + enter_tabpage(tp, curbuf); +} /* * Go to another window. @@ -3007,6 +3262,7 @@ win_enter_ext(wp, undo_sync, curwin_inva maketitle(); #endif curwin->w_redr_status = TRUE; + redraw_tabpage = TRUE; if (restart_edit) redraw_later(VALID); /* causes status line redraw */ @@ -3325,7 +3581,7 @@ win_free_lsize(wp) void shell_new_rows() { - int h = (int)(Rows - p_ch); + int h = (int)ROWS_AVAIL; if (firstwin == NULL) /* not initialized yet */ return; @@ -3430,7 +3686,7 @@ win_size_restore(gap) static int win_comp_pos() { - int row = 0; + int row = tabpageline_height(); int col = 0; frame_comp_pos(topframe, &row, &col); @@ -3593,8 +3849,8 @@ frame_setheight(curfrp, height) if (curfrp->fr_parent == NULL) { /* topframe: can only change the command line */ - if (height > Rows - p_ch) - height = Rows - p_ch; + if (height > ROWS_AVAIL) + height = ROWS_AVAIL; if (height > 0) frame_new_height(curfrp, height, FALSE, FALSE); } @@ -3841,7 +4097,7 @@ frame_setwidth(curfrp, width) if (width <= room) break; - if (run == 2 || curfrp->fr_height >= Rows - p_ch) + if (run == 2 || curfrp->fr_height >= ROWS_AVAIL) { if (width > room) width = room; @@ -4524,6 +4780,18 @@ last_status_rec(fr, statusline) } } +/* + * Return TRUE if the tab page line is to be drawn. + */ + int +tabpageline_height() +{ + /* TODO: option to tell when to show the tabs. */ + if (first_tabpage->tp_next == NULL) + return 0; + return 1; +} + #endif /* FEAT_WINDOWS */ #if defined(FEAT_SEARCHPATH) || defined(PROTO) @@ -4846,6 +5114,10 @@ only_one_window() int count = 0; win_T *wp; + /* If there is another tab page there always is another window. */ + if (first_tabpage->tp_next != NULL) + return FALSE; + for (wp = firstwin; wp != NULL; wp = wp->w_next) if (!((wp->w_buffer->b_help && !curbuf->b_help) # ifdef FEAT_QUICKFIX