aboutsummaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c5394
1 files changed, 0 insertions, 5394 deletions
diff --git a/src/window.c b/src/window.c
deleted file mode 100644
index 27582184d7..0000000000
--- a/src/window.c
+++ /dev/null
@@ -1,5394 +0,0 @@
-/*
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read a list of people who contributed.
- * Do ":help credits" in Vim to see a list of people who contributed.
- * See README.txt for an overview of the Vim source code.
- */
-
-#include "vim.h"
-#include "window.h"
-#include "buffer.h"
-#include "charset.h"
-#include "diff.h"
-#include "edit.h"
-#include "eval.h"
-#include "ex_cmds.h"
-#include "ex_cmds2.h"
-#include "ex_docmd.h"
-#include "ex_eval.h"
-#include "ex_getln.h"
-#include "farsi.h"
-#include "fileio.h"
-#include "fold.h"
-#include "getchar.h"
-#include "hashtab.h"
-#include "main.h"
-#include "mark.h"
-#include "memline.h"
-#include "memory.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "file_search.h"
-#include "garray.h"
-#include "move.h"
-#include "normal.h"
-#include "option.h"
-#include "os_unix.h"
-#include "path.h"
-#include "quickfix.h"
-#include "regexp.h"
-#include "screen.h"
-#include "search.h"
-#include "syntax.h"
-#include "term.h"
-#include "undo.h"
-#include "os/os.h"
-
-static void win_init(win_T *newp, win_T *oldp, int flags);
-static void win_init_some(win_T *newp, win_T *oldp);
-static void frame_comp_pos(frame_T *topfrp, int *row, int *col);
-static void frame_setheight(frame_T *curfrp, int height);
-static void frame_setwidth(frame_T *curfrp, int width);
-static void win_exchange(long);
-static void win_rotate(int, int);
-static void win_totop(int size, int flags);
-static void win_equal_rec(win_T *next_curwin, int current, frame_T *topfr,
- int dir, int col, int row, int width,
- int height);
-static int last_window(void);
-static int close_last_window_tabpage(win_T *win, int free_buf,
- tabpage_T *prev_curtab);
-static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp);
-static frame_T *win_altframe(win_T *win, tabpage_T *tp);
-static tabpage_T *alt_tabpage(void);
-static win_T *frame2win(frame_T *frp);
-static int frame_has_win(frame_T *frp, win_T *wp);
-static void frame_new_height(frame_T *topfrp, int height, int topfirst,
- int wfh);
-static int frame_fixed_height(frame_T *frp);
-static int frame_fixed_width(frame_T *frp);
-static void frame_add_statusline(frame_T *frp);
-static void frame_new_width(frame_T *topfrp, int width, int leftfirst,
- int wfw);
-static void frame_add_vsep(frame_T *frp);
-static int frame_minwidth(frame_T *topfrp, win_T *next_curwin);
-static void frame_fix_width(win_T *wp);
-static int win_alloc_firstwin(win_T *oldwin);
-static void new_frame(win_T *wp);
-static tabpage_T *alloc_tabpage(void);
-static int leave_tabpage(buf_T *new_curbuf, int trigger_leave_autocmds);
-static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf,
- int trigger_enter_autocmds,
- int trigger_leave_autocmds);
-static void frame_fix_height(win_T *wp);
-static int frame_minheight(frame_T *topfrp, win_T *next_curwin);
-static void win_enter_ext(win_T *wp, int undo_sync, int no_curwin,
- int trigger_enter_autocmds,
- int trigger_leave_autocmds);
-static void win_free(win_T *wp, tabpage_T *tp);
-static void frame_append(frame_T *after, frame_T *frp);
-static void frame_insert(frame_T *before, frame_T *frp);
-static void frame_remove(frame_T *frp);
-static void win_goto_ver(int up, long count);
-static void win_goto_hor(int left, long count);
-static void frame_add_height(frame_T *frp, int n);
-static void last_status_rec(frame_T *fr, int statusline);
-
-static void make_snapshot_rec(frame_T *fr, frame_T **frp);
-static void clear_snapshot(tabpage_T *tp, int idx);
-static void clear_snapshot_rec(frame_T *fr);
-static int check_snapshot_rec(frame_T *sn, frame_T *fr);
-static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr);
-
-static int frame_check_height(frame_T *topfrp, int height);
-static int frame_check_width(frame_T *topfrp, int width);
-
-
-static win_T *win_alloc(win_T *after, int hidden);
-static void set_fraction(win_T *wp);
-
-#define NOWIN (win_T *)-1 /* non-existing window */
-
-# define ROWS_AVAIL (Rows - p_ch - tabline_height())
-
-
-static char *m_onlyone = N_("Already only one window");
-
-/*
- * all CTRL-W window commands are handled here, called from normal_cmd().
- */
-void
-do_window (
- int nchar,
- long Prenum,
- int xchar /* extra char from ":wincmd gx" or NUL */
-)
-{
- long Prenum1;
- win_T *wp;
- char_u *ptr;
- linenr_T lnum = -1;
- int type = FIND_DEFINE;
- int len;
- char_u cbuf[40];
-
- if (Prenum == 0)
- Prenum1 = 1;
- else
- Prenum1 = Prenum;
-
-# define CHECK_CMDWIN if (cmdwin_type != 0) { EMSG(_(e_cmdwin)); break; }
-
- switch (nchar) {
- /* split current window in two parts, horizontally */
- case 'S':
- case Ctrl_S:
- case 's':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- /* When splitting the quickfix window open a new buffer in it,
- * don't replicate the quickfix buffer. */
- if (bt_quickfix(curbuf))
- goto newwindow;
- win_split((int)Prenum, 0);
- break;
-
- /* split current window in two parts, vertically */
- case Ctrl_V:
- case 'v':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- /* When splitting the quickfix window open a new buffer in it,
- * don't replicate the quickfix buffer. */
- if (bt_quickfix(curbuf))
- goto newwindow;
- win_split((int)Prenum, WSP_VERT);
- break;
-
- /* split current window and edit alternate file */
- case Ctrl_HAT:
- case '^':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- STRCPY(cbuf, "split #");
- if (Prenum)
- vim_snprintf((char *)cbuf + 7, sizeof(cbuf) - 7,
- "%" PRId64, (int64_t)Prenum);
- do_cmdline_cmd(cbuf);
- break;
-
- /* open new window */
- case Ctrl_N:
- case 'n':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
-newwindow:
- if (Prenum)
- /* window height */
- vim_snprintf((char *)cbuf, sizeof(cbuf) - 5, "%" PRId64, (int64_t)Prenum);
- else
- cbuf[0] = NUL;
- if (nchar == 'v' || nchar == Ctrl_V)
- STRCAT(cbuf, "v");
- STRCAT(cbuf, "new");
- do_cmdline_cmd(cbuf);
- break;
-
- /* quit current window */
- case Ctrl_Q:
- case 'q':
- reset_VIsual_and_resel(); /* stop Visual mode */
- do_cmdline_cmd((char_u *)"quit");
- break;
-
- /* close current window */
- case Ctrl_C:
- case 'c':
- reset_VIsual_and_resel(); /* stop Visual mode */
- do_cmdline_cmd((char_u *)"close");
- break;
-
- /* close preview window */
- case Ctrl_Z:
- case 'z':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- do_cmdline_cmd((char_u *)"pclose");
- break;
-
- /* cursor to preview window */
- case 'P':
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- if (wp->w_p_pvw)
- break;
- if (wp == NULL)
- EMSG(_("E441: There is no preview window"));
- else
- win_goto(wp);
- break;
-
- /* close all but current window */
- case Ctrl_O:
- case 'o':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- do_cmdline_cmd((char_u *)"only");
- break;
-
- /* cursor to next window with wrap around */
- case Ctrl_W:
- case 'w':
- /* cursor to previous window with wrap around */
- case 'W':
- CHECK_CMDWIN
- if (firstwin == lastwin && Prenum != 1) /* just one window */
- beep_flush();
- else {
- if (Prenum) { /* go to specified window */
- for (wp = firstwin; --Prenum > 0; ) {
- if (wp->w_next == NULL)
- break;
- else
- wp = wp->w_next;
- }
- } else {
- if (nchar == 'W') { /* go to previous window */
- wp = curwin->w_prev;
- if (wp == NULL)
- wp = lastwin; /* wrap around */
- } else { /* go to next window */
- wp = curwin->w_next;
- if (wp == NULL)
- wp = firstwin; /* wrap around */
- }
- }
- win_goto(wp);
- }
- break;
-
- /* cursor to window below */
- case 'j':
- case K_DOWN:
- case Ctrl_J:
- CHECK_CMDWIN win_goto_ver(FALSE, Prenum1);
- break;
-
- /* cursor to window above */
- case 'k':
- case K_UP:
- case Ctrl_K:
- CHECK_CMDWIN win_goto_ver(TRUE, Prenum1);
- break;
-
- /* cursor to left window */
- case 'h':
- case K_LEFT:
- case Ctrl_H:
- case K_BS:
- CHECK_CMDWIN win_goto_hor(TRUE, Prenum1);
- break;
-
- /* cursor to right window */
- case 'l':
- case K_RIGHT:
- case Ctrl_L:
- CHECK_CMDWIN win_goto_hor(FALSE, Prenum1);
- break;
-
- /* move window to new tab page */
- case 'T':
- if (one_window())
- MSG(_(m_onlyone));
- else {
- tabpage_T *oldtab = curtab;
- tabpage_T *newtab;
-
- /* First create a new tab with the window, then go back to
- * the old tab and close the window there. */
- wp = curwin;
- if (win_new_tabpage((int)Prenum) == OK
- && valid_tabpage(oldtab)) {
- newtab = curtab;
- goto_tabpage_tp(oldtab, TRUE, TRUE);
- if (curwin == wp)
- win_close(curwin, FALSE);
- if (valid_tabpage(newtab))
- goto_tabpage_tp(newtab, TRUE, TRUE);
- }
- }
- break;
-
- /* cursor to top-left window */
- case 't':
- case Ctrl_T:
- win_goto(firstwin);
- break;
-
- /* cursor to bottom-right window */
- case 'b':
- case Ctrl_B:
- win_goto(lastwin);
- break;
-
- /* cursor to last accessed (previous) window */
- case 'p':
- case Ctrl_P:
- if (prevwin == NULL)
- beep_flush();
- else
- win_goto(prevwin);
- break;
-
- /* exchange current and next window */
- case 'x':
- case Ctrl_X:
- CHECK_CMDWIN win_exchange(Prenum);
- break;
-
- /* rotate windows downwards */
- case Ctrl_R:
- case 'r':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- win_rotate(FALSE, (int)Prenum1); /* downwards */
- break;
-
- /* rotate windows upwards */
- case 'R':
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- win_rotate(TRUE, (int)Prenum1); /* upwards */
- break;
-
- /* move window to the very top/bottom/left/right */
- case 'K':
- case 'J':
- case 'H':
- case 'L':
- CHECK_CMDWIN win_totop((int)Prenum,
- ((nchar == 'H' || nchar == 'L') ? WSP_VERT : 0)
- | ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT));
- break;
-
- /* make all windows the same height */
- case '=':
- win_equal(NULL, FALSE, 'b');
- break;
-
- /* increase current window height */
- case '+':
- win_setheight(curwin->w_height + (int)Prenum1);
- break;
-
- /* decrease current window height */
- case '-':
- win_setheight(curwin->w_height - (int)Prenum1);
- break;
-
- /* set current window height */
- case Ctrl__:
- case '_':
- win_setheight(Prenum ? (int)Prenum : 9999);
- break;
-
- /* increase current window width */
- case '>':
- win_setwidth(curwin->w_width + (int)Prenum1);
- break;
-
- /* decrease current window width */
- case '<':
- win_setwidth(curwin->w_width - (int)Prenum1);
- break;
-
- /* set current window width */
- case '|':
- win_setwidth(Prenum != 0 ? (int)Prenum : 9999);
- break;
-
- /* jump to tag and split window if tag exists (in preview window) */
- case '}':
- CHECK_CMDWIN
- if (Prenum)
- g_do_tagpreview = Prenum;
- else
- g_do_tagpreview = p_pvh;
- /*FALLTHROUGH*/
- case ']':
- case Ctrl_RSB:
- CHECK_CMDWIN reset_VIsual_and_resel(); /* stop Visual mode */
- if (Prenum)
- postponed_split = Prenum;
- else
- postponed_split = -1;
-
- /* Execute the command right here, required when
- * "wincmd ]" was used in a function. */
- do_nv_ident(Ctrl_RSB, NUL);
- break;
-
- /* edit file name under cursor in a new window */
- case 'f':
- case 'F':
- case Ctrl_F:
-wingotofile:
- CHECK_CMDWIN
-
- ptr = grab_file_name(Prenum1, &lnum);
- if (ptr != NULL) {
- setpcmark();
- if (win_split(0, 0) == OK) {
- RESET_BINDING(curwin);
- (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL,
- ECMD_HIDE, NULL);
- if (nchar == 'F' && lnum >= 0) {
- curwin->w_cursor.lnum = lnum;
- check_cursor_lnum();
- beginline(BL_SOL | BL_FIX);
- }
- }
- free(ptr);
- }
- break;
-
- /* Go to the first occurrence of the identifier under cursor along path in a
- * new window -- webb
- */
- case 'i': /* Go to any match */
- case Ctrl_I:
- type = FIND_ANY;
- /* FALLTHROUGH */
- case 'd': /* Go to definition, using 'define' */
- case Ctrl_D:
- CHECK_CMDWIN
- if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
- break;
- find_pattern_in_path(ptr, 0, len, TRUE,
- Prenum == 0 ? TRUE : FALSE, type,
- Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM);
- curwin->w_set_curswant = TRUE;
- break;
-
- case K_KENTER:
- case CAR:
- /*
- * In a quickfix window a <CR> jumps to the error under the
- * cursor in a new window.
- */
- if (bt_quickfix(curbuf)) {
- sprintf((char *)cbuf, "split +%" PRId64 "%s",
- (int64_t)curwin->w_cursor.lnum,
- (curwin->w_llist_ref == NULL) ? "cc" : "ll");
- do_cmdline_cmd(cbuf);
- }
- break;
-
-
- /* CTRL-W g extended commands */
- case 'g':
- case Ctrl_G:
- CHECK_CMDWIN
-#ifdef USE_ON_FLY_SCROLL
- dont_scroll = TRUE; /* disallow scrolling here */
-#endif
- ++ no_mapping;
- ++allow_keys; /* no mapping for xchar, but allow key codes */
- if (xchar == NUL)
- xchar = plain_vgetc();
- LANGMAP_ADJUST(xchar, TRUE);
- --no_mapping;
- --allow_keys;
- (void)add_to_showcmd(xchar);
- switch (xchar) {
- case '}':
- xchar = Ctrl_RSB;
- if (Prenum)
- g_do_tagpreview = Prenum;
- else
- g_do_tagpreview = p_pvh;
- /*FALLTHROUGH*/
- case ']':
- case Ctrl_RSB:
- reset_VIsual_and_resel(); /* stop Visual mode */
- if (Prenum)
- postponed_split = Prenum;
- else
- postponed_split = -1;
-
- /* Execute the command right here, required when
- * "wincmd g}" was used in a function. */
- do_nv_ident('g', xchar);
- break;
-
- case 'f': /* CTRL-W gf: "gf" in a new tab page */
- case 'F': /* CTRL-W gF: "gF" in a new tab page */
- cmdmod.tab = tabpage_index(curtab) + 1;
- nchar = xchar;
- goto wingotofile;
- default:
- beep_flush();
- break;
- }
- break;
-
- default: beep_flush();
- break;
- }
-}
-
-/*
- * split the current window, implements CTRL-W s and :split
- *
- * "size" is the height or width for the new window, 0 to use half of current
- * height or width.
- *
- * "flags":
- * WSP_ROOM: require enough room for new window
- * WSP_VERT: vertical split.
- * WSP_TOP: open window at the top-left of the shell (help window).
- * WSP_BOT: open window at the bottom-right of the shell (quickfix window).
- * WSP_HELP: creating the help window, keep layout snapshot
- *
- * return FAIL for failure, OK otherwise
- */
-int win_split(int size, int flags)
-{
- /* When the ":tab" modifier was used open a new tab page instead. */
- if (may_open_tabpage() == OK)
- return OK;
-
- /* Add flags from ":vertical", ":topleft" and ":botright". */
- flags |= cmdmod.split;
- if ((flags & WSP_TOP) && (flags & WSP_BOT)) {
- EMSG(_("E442: Can't split topleft and botright at the same time"));
- return FAIL;
- }
-
- /* 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);
-}
-
-/*
- * When "new_wp" is NULL: split the current window in two.
- * When "new_wp" is not NULL: insert this window at the far
- * top/left/right/bottom.
- * return FAIL for failure, OK otherwise
- */
-int win_split_ins(int size, int flags, win_T *new_wp, int dir)
-{
- win_T *wp = new_wp;
- win_T *oldwin;
- int new_size = size;
- int i;
- int need_status = 0;
- int do_equal = FALSE;
- int needed;
- int available;
- int oldwin_height = 0;
- int layout;
- frame_T *frp, *curfrp;
- int before;
-
- if (flags & WSP_TOP)
- oldwin = firstwin;
- else if (flags & WSP_BOT)
- oldwin = lastwin;
- else
- oldwin = curwin;
-
- /* add a status line when p_ls == 1 and splitting the first window */
- if (lastwin == firstwin && p_ls == 1 && oldwin->w_status_height == 0) {
- if (oldwin->w_height <= p_wmh && new_wp == NULL) {
- EMSG(_(e_noroom));
- return FAIL;
- }
- need_status = STATUS_HEIGHT;
- }
-
-
- if (flags & WSP_VERT) {
- layout = FR_ROW;
-
- /*
- * Check if we are able to split the current window and compute its
- * width.
- */
- needed = p_wmw + 1;
- if (flags & WSP_ROOM)
- needed += p_wiw - p_wmw;
- if (p_ea || (flags & (WSP_BOT | WSP_TOP))) {
- available = topframe->fr_width;
- needed += frame_minwidth(topframe, NULL);
- } else
- available = oldwin->w_width;
- if (available < needed && new_wp == NULL) {
- EMSG(_(e_noroom));
- return FAIL;
- }
- if (new_size == 0)
- new_size = oldwin->w_width / 2;
- if (new_size > oldwin->w_width - p_wmw - 1)
- new_size = oldwin->w_width - p_wmw - 1;
- if (new_size < p_wmw)
- new_size = p_wmw;
-
- /* if it doesn't fit in the current window, need win_equal() */
- if (oldwin->w_width - new_size - 1 < p_wmw)
- do_equal = TRUE;
-
- /* We don't like to take lines for the new window from a
- * 'winfixwidth' window. Take them from a window to the left or right
- * instead, if possible. */
- if (oldwin->w_p_wfw)
- win_setwidth_win(oldwin->w_width + new_size, oldwin);
-
- /* Only make all windows the same width if one of them (except oldwin)
- * is wider than one of the split windows. */
- if (!do_equal && p_ea && size == 0 && *p_ead != 'v'
- && oldwin->w_frame->fr_parent != NULL) {
- frp = oldwin->w_frame->fr_parent->fr_child;
- while (frp != NULL) {
- if (frp->fr_win != oldwin && frp->fr_win != NULL
- && (frp->fr_win->w_width > new_size
- || frp->fr_win->w_width > oldwin->w_width
- - new_size - STATUS_HEIGHT)) {
- do_equal = TRUE;
- break;
- }
- frp = frp->fr_next;
- }
- }
- } else {
- layout = FR_COL;
-
- /*
- * Check if we are able to split the current window and compute its
- * height.
- */
- needed = p_wmh + STATUS_HEIGHT + need_status;
- if (flags & WSP_ROOM)
- needed += p_wh - p_wmh;
- if (p_ea || (flags & (WSP_BOT | WSP_TOP))) {
- available = topframe->fr_height;
- needed += frame_minheight(topframe, NULL);
- } else {
- available = oldwin->w_height;
- needed += p_wmh;
- }
- if (available < needed && new_wp == NULL) {
- EMSG(_(e_noroom));
- return FAIL;
- }
- oldwin_height = oldwin->w_height;
- if (need_status) {
- oldwin->w_status_height = STATUS_HEIGHT;
- oldwin_height -= STATUS_HEIGHT;
- }
- if (new_size == 0)
- new_size = oldwin_height / 2;
-
- if (new_size > oldwin_height - p_wmh - STATUS_HEIGHT)
- new_size = oldwin_height - p_wmh - STATUS_HEIGHT;
- if (new_size < p_wmh)
- new_size = p_wmh;
-
- /* if it doesn't fit in the current window, need win_equal() */
- if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh)
- do_equal = TRUE;
-
- /* We don't like to take lines for the new window from a
- * 'winfixheight' window. Take them from a window above or below
- * instead, if possible. */
- if (oldwin->w_p_wfh) {
- win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
- oldwin);
- oldwin_height = oldwin->w_height;
- if (need_status)
- oldwin_height -= STATUS_HEIGHT;
- }
-
- /* Only make all windows the same height if one of them (except oldwin)
- * is higher than one of the split windows. */
- if (!do_equal && p_ea && size == 0
- && *p_ead != 'h'
- && oldwin->w_frame->fr_parent != NULL) {
- frp = oldwin->w_frame->fr_parent->fr_child;
- while (frp != NULL) {
- if (frp->fr_win != oldwin && frp->fr_win != NULL
- && (frp->fr_win->w_height > new_size
- || frp->fr_win->w_height > oldwin_height - new_size
- - STATUS_HEIGHT)) {
- do_equal = TRUE;
- break;
- }
- frp = frp->fr_next;
- }
- }
- }
-
- /*
- * allocate new window structure and link it in the window list
- */
- if ((flags & WSP_TOP) == 0
- && ((flags & WSP_BOT)
- || (flags & WSP_BELOW)
- || (!(flags & WSP_ABOVE)
- && (
- (flags & WSP_VERT) ? p_spr :
- p_sb)))) {
- /* new window below/right of current one */
- if (new_wp == NULL)
- wp = win_alloc(oldwin, FALSE);
- else
- win_append(oldwin, wp);
- } else {
- if (new_wp == NULL)
- wp = win_alloc(oldwin->w_prev, FALSE);
- else
- win_append(oldwin->w_prev, wp);
- }
-
- if (new_wp == NULL) {
- if (wp == NULL)
- return FAIL;
-
- new_frame(wp);
-
- /* make the contents of the new window the same as the current one */
- win_init(wp, curwin, flags);
- }
-
- /*
- * Reorganise the tree of frames to insert the new window.
- */
- if (flags & (WSP_TOP | WSP_BOT)) {
- if ((topframe->fr_layout == FR_COL && (flags & WSP_VERT) == 0)
- || (topframe->fr_layout == FR_ROW && (flags & WSP_VERT) != 0)) {
- curfrp = topframe->fr_child;
- if (flags & WSP_BOT)
- while (curfrp->fr_next != NULL)
- curfrp = curfrp->fr_next;
- } else
- curfrp = topframe;
- before = (flags & WSP_TOP);
- } else {
- curfrp = oldwin->w_frame;
- if (flags & WSP_BELOW)
- before = FALSE;
- else if (flags & WSP_ABOVE)
- before = TRUE;
- else if (flags & WSP_VERT)
- before = !p_spr;
- else
- before = !p_sb;
- }
- if (curfrp->fr_parent == NULL || curfrp->fr_parent->fr_layout != layout) {
- /* Need to create a new frame in the tree to make a branch. */
- frp = xcalloc(1, sizeof(frame_T));
- *frp = *curfrp;
- curfrp->fr_layout = layout;
- frp->fr_parent = curfrp;
- frp->fr_next = NULL;
- frp->fr_prev = NULL;
- curfrp->fr_child = frp;
- curfrp->fr_win = NULL;
- curfrp = frp;
- if (frp->fr_win != NULL)
- oldwin->w_frame = frp;
- else
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- frp->fr_parent = curfrp;
- }
-
- if (new_wp == NULL)
- frp = wp->w_frame;
- else
- frp = new_wp->w_frame;
- frp->fr_parent = curfrp->fr_parent;
-
- /* Insert the new frame at the right place in the frame list. */
- if (before)
- frame_insert(curfrp, frp);
- else
- frame_append(curfrp, frp);
-
- /* Set w_fraction now so that the cursor keeps the same relative
- * vertical position. */
- if (oldwin->w_height > 0)
- set_fraction(oldwin);
- wp->w_fraction = oldwin->w_fraction;
-
- if (flags & WSP_VERT) {
- wp->w_p_scr = curwin->w_p_scr;
-
- if (need_status) {
- win_new_height(oldwin, oldwin->w_height - 1);
- oldwin->w_status_height = need_status;
- }
- if (flags & (WSP_TOP | WSP_BOT)) {
- /* set height and row of new window to full height */
- wp->w_winrow = tabline_height();
- win_new_height(wp, curfrp->fr_height - (p_ls > 0));
- wp->w_status_height = (p_ls > 0);
- } else {
- /* height and row of new window is same as current window */
- wp->w_winrow = oldwin->w_winrow;
- win_new_height(wp, oldwin->w_height);
- wp->w_status_height = oldwin->w_status_height;
- }
- frp->fr_height = curfrp->fr_height;
-
- /* "new_size" of the current window goes to the new window, use
- * one column for the vertical separator */
- win_new_width(wp, new_size);
- if (before)
- wp->w_vsep_width = 1;
- else {
- wp->w_vsep_width = oldwin->w_vsep_width;
- oldwin->w_vsep_width = 1;
- }
- if (flags & (WSP_TOP | WSP_BOT)) {
- if (flags & WSP_BOT)
- frame_add_vsep(curfrp);
- /* Set width of neighbor frame */
- frame_new_width(curfrp, curfrp->fr_width
- - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
- FALSE);
- } else
- win_new_width(oldwin, oldwin->w_width - (new_size + 1));
- if (before) { /* new window left of current one */
- wp->w_wincol = oldwin->w_wincol;
- oldwin->w_wincol += new_size + 1;
- } else /* new window right of current one */
- wp->w_wincol = oldwin->w_wincol + oldwin->w_width + 1;
- frame_fix_width(oldwin);
- frame_fix_width(wp);
- } else {
- /* width and column of new window is same as current window */
- if (flags & (WSP_TOP | WSP_BOT)) {
- wp->w_wincol = 0;
- win_new_width(wp, Columns);
- wp->w_vsep_width = 0;
- } else {
- wp->w_wincol = oldwin->w_wincol;
- win_new_width(wp, oldwin->w_width);
- wp->w_vsep_width = oldwin->w_vsep_width;
- }
- frp->fr_width = curfrp->fr_width;
-
- /* "new_size" of the current window goes to the new window, use
- * one row for the status line */
- win_new_height(wp, new_size);
- if (flags & (WSP_TOP | WSP_BOT))
- frame_new_height(curfrp, curfrp->fr_height
- - (new_size + STATUS_HEIGHT), flags & WSP_TOP, FALSE);
- else
- win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT));
- if (before) { /* new window above current one */
- wp->w_winrow = oldwin->w_winrow;
- wp->w_status_height = STATUS_HEIGHT;
- oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
- } else { /* new window below current one */
- wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT;
- wp->w_status_height = oldwin->w_status_height;
- oldwin->w_status_height = STATUS_HEIGHT;
- }
- if (flags & WSP_BOT)
- frame_add_statusline(curfrp);
- frame_fix_height(wp);
- frame_fix_height(oldwin);
- }
-
- if (flags & (WSP_TOP | WSP_BOT))
- (void)win_comp_pos();
-
- /*
- * Both windows need redrawing
- */
- redraw_win_later(wp, NOT_VALID);
- wp->w_redr_status = TRUE;
- redraw_win_later(oldwin, NOT_VALID);
- oldwin->w_redr_status = TRUE;
-
- if (need_status) {
- msg_row = Rows - 1;
- msg_col = sc_col;
- msg_clr_eos_force(); /* Old command/ruler may still be there */
- comp_col();
- msg_row = Rows - 1;
- msg_col = 0; /* put position back at start of line */
- }
-
- /*
- * equalize the window sizes.
- */
- if (do_equal || dir != 0)
- win_equal(wp, TRUE,
- (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
- : dir == 'h' ? 'b' :
- 'v');
-
- /* Don't change the window height/width to 'winheight' / 'winwidth' if a
- * size was given. */
- if (flags & WSP_VERT) {
- i = p_wiw;
- if (size != 0)
- p_wiw = size;
-
- } else {
- i = p_wh;
- if (size != 0)
- p_wh = size;
- }
-
- /*
- * make the new window the current window
- */
- win_enter(wp, FALSE);
- if (flags & WSP_VERT)
- p_wiw = i;
- else
- p_wh = i;
-
- return OK;
-}
-
-
-/*
- * Initialize window "newp" from window "oldp".
- * Used when splitting a window and when creating a new tab page.
- * The windows will both edit the same buffer.
- * WSP_NEWLOC may be specified in flags to prevent the location list from
- * being copied.
- */
-static void win_init(win_T *newp, win_T *oldp, int flags)
-{
- int i;
-
- newp->w_buffer = oldp->w_buffer;
- newp->w_s = &(oldp->w_buffer->b_s);
- oldp->w_buffer->b_nwindows++;
- newp->w_cursor = oldp->w_cursor;
- newp->w_valid = 0;
- newp->w_curswant = oldp->w_curswant;
- newp->w_set_curswant = oldp->w_set_curswant;
- newp->w_topline = oldp->w_topline;
- newp->w_topfill = oldp->w_topfill;
- newp->w_leftcol = oldp->w_leftcol;
- newp->w_pcmark = oldp->w_pcmark;
- newp->w_prev_pcmark = oldp->w_prev_pcmark;
- newp->w_alt_fnum = oldp->w_alt_fnum;
- newp->w_wrow = oldp->w_wrow;
- newp->w_fraction = oldp->w_fraction;
- newp->w_prev_fraction_row = oldp->w_prev_fraction_row;
- copy_jumplist(oldp, newp);
- if (flags & WSP_NEWLOC) {
- /* Don't copy the location list. */
- newp->w_llist = NULL;
- newp->w_llist_ref = NULL;
- } else
- copy_loclist(oldp, newp);
- newp->w_localdir = (oldp->w_localdir == NULL)
- ? NULL : 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];
- if (newp->w_tagstack[i].tagname != NULL)
- newp->w_tagstack[i].tagname =
- vim_strsave(newp->w_tagstack[i].tagname);
- }
- newp->w_tagstackidx = oldp->w_tagstackidx;
- newp->w_tagstacklen = oldp->w_tagstacklen;
- copyFoldingState(oldp, newp);
-
- win_init_some(newp, oldp);
-
- check_colorcolumn(newp);
-}
-
-/*
- * Initialize window "newp" from window"old".
- * Only the essential things are copied.
- */
-static void win_init_some(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);
-}
-
-
-/*
- * Check if "win" is a pointer to an existing window.
- */
-int win_valid(win_T *win)
-{
- win_T *wp;
-
- if (win == NULL)
- return FALSE;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- if (wp == win)
- return TRUE;
- return FALSE;
-}
-
-/*
- * Return the number of windows.
- */
-int win_count(void)
-{
- win_T *wp;
- int count = 0;
-
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- ++count;
- return count;
-}
-
-/*
- * Make "count" windows on the screen.
- * Return actual number of windows on the screen.
- * Must be called when there is just one window, filling the whole screen
- * (excluding the command line).
- */
-int
-make_windows (
- int count,
- int vertical /* split windows vertically if TRUE */
-)
-{
- int maxcount;
- int todo;
-
- if (vertical) {
- /* Each windows needs at least 'winminwidth' lines and a separator
- * column. */
- maxcount = (curwin->w_width + curwin->w_vsep_width
- - (p_wiw - p_wmw)) / (p_wmw + 1);
- } else {
- /* Each window needs at least 'winminheight' lines and a status line. */
- maxcount = (curwin->w_height + curwin->w_status_height
- - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
- }
-
- if (maxcount < 2)
- maxcount = 2;
- if (count > maxcount)
- count = maxcount;
-
- /*
- * add status line now, otherwise first window will be too big
- */
- if (count > 1)
- last_status(TRUE);
-
- /*
- * Don't execute autocommands while creating the windows. Must do that
- * when putting the buffers in the windows.
- */
- block_autocmds();
-
- /* todo is number of windows left to create */
- for (todo = count - 1; todo > 0; --todo)
- if (vertical) {
- if (win_split(curwin->w_width - (curwin->w_width - todo)
- / (todo + 1) - 1, WSP_VERT | WSP_ABOVE) == FAIL)
- break;
- } else {
- if (win_split(curwin->w_height - (curwin->w_height - todo
- * STATUS_HEIGHT) / (todo + 1)
- - STATUS_HEIGHT, WSP_ABOVE) == FAIL)
- break;
- }
-
- unblock_autocmds();
-
- /* return actual number of windows */
- return count - todo;
-}
-
-/*
- * Exchange current and next window
- */
-static void win_exchange(long Prenum)
-{
- frame_T *frp;
- frame_T *frp2;
- win_T *wp;
- win_T *wp2;
- int temp;
-
- if (lastwin == firstwin) { /* just one window */
- beep_flush();
- return;
- }
-
-
- /*
- * find window to exchange with
- */
- if (Prenum) {
- frp = curwin->w_frame->fr_parent->fr_child;
- while (frp != NULL && --Prenum > 0)
- frp = frp->fr_next;
- } else if (curwin->w_frame->fr_next != NULL) /* Swap with next */
- frp = curwin->w_frame->fr_next;
- else /* Swap last window in row/col with previous */
- frp = curwin->w_frame->fr_prev;
-
- /* We can only exchange a window with another window, not with a frame