diff options
Diffstat (limited to 'src/nvim/window.c')
| -rw-r--r-- | src/nvim/window.c | 2420 |
1 files changed, 1200 insertions, 1220 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c index 68c5b42e30..05f84b5a91 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2,21 +2,34 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #include <assert.h> +#include <ctype.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "klib/kvec.h" +#include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#include "nvim/api/vim.h" #include "nvim/arglist.h" #include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/decoration.h" #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" +#include "nvim/eval/window.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" @@ -27,15 +40,19 @@ #include "nvim/fold.h" #include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/hashtab.h" -#include "nvim/highlight.h" +#include "nvim/keycodes.h" +#include "nvim/macros.h" #include "nvim/main.h" -#include "nvim/mapping.h" +#include "nvim/map.h" +#include "nvim/mapping.h" // IWYU pragma: keep (langmap_adjust_mb) #include "nvim/mark.h" #include "nvim/match.h" -#include "nvim/memline.h" +#include "nvim/mbyte.h" +#include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/mouse.h" @@ -44,16 +61,19 @@ #include "nvim/option.h" #include "nvim/optionstr.h" #include "nvim/os/os.h" -#include "nvim/os_unix.h" +#include "nvim/os/os_defs.h" #include "nvim/path.h" #include "nvim/plines.h" +#include "nvim/pos.h" #include "nvim/quickfix.h" -#include "nvim/regexp.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/state.h" +#include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/terminal.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/ui_compositor.h" #include "nvim/undo.h" @@ -125,15 +145,10 @@ win_T *prevwin_curwin(void) /// @param xchar extra char from ":wincmd gx" or NUL void do_window(int nchar, long Prenum, int xchar) { - long Prenum1; - win_T *wp; - char *ptr; - linenr_T lnum = -1; int type = FIND_DEFINE; - size_t len; char cbuf[40]; - Prenum1 = Prenum == 0 ? 1 : Prenum; + long Prenum1 = Prenum == 0 ? 1 : Prenum; #define CHECK_CMDWIN \ do { \ @@ -215,7 +230,7 @@ newwindow: case Ctrl_Q: case 'q': reset_VIsual_and_resel(); // stop Visual mode - cmd_with_count("quit", (char_u *)cbuf, sizeof(cbuf), Prenum); + cmd_with_count("quit", cbuf, sizeof(cbuf), Prenum); do_cmdline_cmd(cbuf); break; @@ -223,7 +238,7 @@ newwindow: case Ctrl_C: case 'c': reset_VIsual_and_resel(); // stop Visual mode - cmd_with_count("close", (char_u *)cbuf, sizeof(cbuf), Prenum); + cmd_with_count("close", cbuf, sizeof(cbuf), Prenum); do_cmdline_cmd(cbuf); break; @@ -236,8 +251,8 @@ newwindow: break; // cursor to preview window - case 'P': - wp = NULL; + case 'P': { + win_T *wp = NULL; FOR_ALL_WINDOWS_IN_TAB(wp2, curtab) { if (wp2->w_p_pvw) { wp = wp2; @@ -250,13 +265,14 @@ newwindow: win_goto(wp); } break; + } // close all but current window case Ctrl_O: case 'o': CHECK_CMDWIN; reset_VIsual_and_resel(); // stop Visual mode - cmd_with_count("only", (char_u *)cbuf, sizeof(cbuf), Prenum); + cmd_with_count("only", cbuf, sizeof(cbuf), Prenum); do_cmdline_cmd(cbuf); break; @@ -269,13 +285,13 @@ newwindow: if (ONE_WINDOW && Prenum != 1) { // just one window beep_flush(); } else { + win_T *wp; if (Prenum) { // go to specified window for (wp = firstwin; --Prenum > 0;) { if (wp->w_next == NULL) { break; - } else { - wp = wp->w_next; } + wp = wp->w_next; } } else { if (nchar == 'W') { // go to previous window @@ -346,7 +362,7 @@ newwindow: // First create a new tab with the window, then go back to // the old tab and close the window there. - wp = curwin; + win_T *wp = curwin; if (win_new_tabpage((int)Prenum, NULL) == OK && valid_tabpage(oldtab)) { newtab = curtab; @@ -417,10 +433,12 @@ newwindow: | ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT)); break; - // make all windows the same height - case '=': - win_equal(NULL, false, 'b'); + // make all windows the same width and/or height + case '=': { + int mod = cmdmod.cmod_split & (WSP_VERT | WSP_HOR); + win_equal(NULL, false, mod == WSP_VERT ? 'v' : mod == WSP_HOR ? 'h' : 'b'); break; + } // increase current window height case '+': @@ -479,16 +497,18 @@ newwindow: // Execute the command right here, required when // "wincmd ]" was used in a function. do_nv_ident(Ctrl_RSB, NUL); + postponed_split = 0; break; // edit file name under cursor in a new window case 'f': case 'F': - case Ctrl_F: + case Ctrl_F: { wingotofile: CHECK_CMDWIN; - ptr = (char *)grab_file_name(Prenum1, &lnum); + linenr_T lnum = -1; + char *ptr = grab_file_name(Prenum1, &lnum); if (ptr != NULL) { tabpage_T *oldtab = curtab; win_T *oldwin = curwin; @@ -508,6 +528,7 @@ wingotofile: xfree(ptr); } break; + } // Go to the first occurrence of the identifier under cursor along path in a // new window -- webb @@ -516,8 +537,10 @@ wingotofile: type = FIND_ANY; FALLTHROUGH; case 'd': // Go to definition, using 'define' - case Ctrl_D: + case Ctrl_D: { CHECK_CMDWIN; + size_t len; + char *ptr; if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0) { break; } @@ -525,11 +548,12 @@ wingotofile: // Make a copy, if the line was changed it will be freed. ptr = xstrnsave(ptr, len); - find_pattern_in_path((char_u *)ptr, 0, len, true, Prenum == 0, + find_pattern_in_path(ptr, 0, len, true, Prenum == 0, type, Prenum1, ACTION_SPLIT, 1, MAXLNUM); xfree(ptr); curwin->w_set_curswant = true; break; + } // Quickfix window only: view the result under the cursor in a new split. case K_KENTER: @@ -552,6 +576,7 @@ wingotofile: no_mapping--; allow_keys--; (void)add_to_showcmd(xchar); + switch (xchar) { case '}': xchar = Ctrl_RSB; @@ -573,6 +598,7 @@ wingotofile: // Execute the command right here, required when // "wincmd g}" was used in a function. do_nv_ident('g', xchar); + postponed_split = 0; break; case 'f': // CTRL-W gf: "gf" in a new tab page @@ -580,6 +606,7 @@ wingotofile: cmdmod.cmod_tab = tabpage_index(curtab) + 1; nchar = xchar; goto wingotofile; + case 't': // CTRL-W gt: go to next tab page goto_tabpage((int)Prenum); break; @@ -622,12 +649,12 @@ wingotofile: } } -static void cmd_with_count(char *cmd, char_u *bufp, size_t bufsize, int64_t Prenum) +static void cmd_with_count(char *cmd, char *bufp, size_t bufsize, int64_t Prenum) { - size_t len = STRLCPY(bufp, cmd, bufsize); + size_t len = xstrlcpy(bufp, cmd, bufsize); if (Prenum > 0 && len < bufsize) { - vim_snprintf((char *)bufp + len, bufsize - len, "%" PRId64, Prenum); + vim_snprintf(bufp + len, bufsize - len, "%" PRId64, Prenum); } } @@ -635,11 +662,13 @@ void win_set_buf(Window window, Buffer buffer, bool noautocmd, Error *err) { win_T *win = find_window_by_handle(window, err); buf_T *buf = find_buffer_by_handle(buffer, err); - tabpage_T *tab = win_find_tabpage(win); if (!win || !buf) { return; } + + tabpage_T *tab = win_find_tabpage(win); + if (noautocmd) { block_autocmds(); } @@ -712,7 +741,7 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err) win_config_float(wp, fconfig); win_set_inner_size(wp, true); wp->w_pos_changed = true; - redraw_later(wp, VALID); + redraw_later(wp, UPD_VALID); return wp; } @@ -727,38 +756,44 @@ void win_set_minimal_style(win_T *wp) // Hide EOB region: use " " fillchar and cleared highlighting if (wp->w_p_fcs_chars.eob != ' ') { - char_u *old = wp->w_p_fcs; + char *old = wp->w_p_fcs; wp->w_p_fcs = ((*old == NUL) - ? (char_u *)xstrdup("eob: ") - : concat_str(old, (char_u *)",eob: ")); + ? xstrdup("eob: ") + : concat_str(old, ",eob: ")); free_string_option(old); } // TODO(bfredl): this could use a highlight namespace directly, - // and avoid pecularities around window options - char_u *old = wp->w_p_winhl; + // and avoid peculiarities around window options + char *old = wp->w_p_winhl; wp->w_p_winhl = ((*old == NUL) - ? (char_u *)xstrdup("EndOfBuffer:") - : concat_str(old, (char_u *)",EndOfBuffer:")); + ? xstrdup("EndOfBuffer:") + : concat_str(old, ",EndOfBuffer:")); free_string_option(old); parse_winhl_opt(wp); // signcolumn: use 'auto' - if (wp->w_p_scl[0] != 'a' || STRLEN(wp->w_p_scl) >= 8) { + if (wp->w_p_scl[0] != 'a' || strlen(wp->w_p_scl) >= 8) { free_string_option(wp->w_p_scl); - wp->w_p_scl = (char_u *)xstrdup("auto"); + wp->w_p_scl = xstrdup("auto"); } // foldcolumn: use '0' if (wp->w_p_fdc[0] != '0') { free_string_option(wp->w_p_fdc); - wp->w_p_fdc = (char_u *)xstrdup("0"); + wp->w_p_fdc = xstrdup("0"); } // colorcolumn: cleared if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) { free_string_option(wp->w_p_cc); - wp->w_p_cc = (char_u *)xstrdup(""); + wp->w_p_cc = xstrdup(""); + } + + // statuscolumn: cleared + if (wp->w_p_stc != NULL && *wp->w_p_stc != NUL) { + free_string_option(wp->w_p_stc); + wp->w_p_stc = xstrdup(""); } } @@ -772,13 +807,22 @@ void win_config_float(win_T *wp, FloatConfig fconfig) fconfig.row += curwin->w_wrow; fconfig.col += curwin->w_wcol; fconfig.window = curwin->handle; + } else if (fconfig.relative == kFloatRelativeMouse) { + int row = mouse_row, col = mouse_col, grid = mouse_grid; + win_T *mouse_win = mouse_find_win(&grid, &row, &col); + if (mouse_win != NULL) { + fconfig.relative = kFloatRelativeWindow; + fconfig.row += row; + fconfig.col += col; + fconfig.window = mouse_win->handle; + } } bool change_external = fconfig.external != wp->w_float_config.external; bool change_border = (fconfig.border != wp->w_float_config.border || memcmp(fconfig.border_hl_ids, wp->w_float_config.border_hl_ids, - sizeof fconfig.border_hl_ids)); + sizeof fconfig.border_hl_ids) != 0); wp->w_float_config = fconfig; @@ -797,12 +841,12 @@ void win_config_float(win_T *wp, FloatConfig fconfig) } win_set_inner_size(wp, true); - must_redraw = MAX(must_redraw, VALID); + must_redraw = MAX(must_redraw, UPD_VALID); wp->w_pos_changed = true; if (change_external || change_border) { wp->w_hl_needs_update = true; - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); } // compute initial position @@ -819,16 +863,16 @@ void win_config_float(win_T *wp, FloatConfig fconfig) grid_adjust(&grid, &row_off, &col_off); row += row_off; col += col_off; + if (wp->w_float_config.bufpos.lnum >= 0) { + pos_T pos = { wp->w_float_config.bufpos.lnum + 1, + wp->w_float_config.bufpos.col, 0 }; + int trow, tcol, tcolc, tcole; + textpos2screenpos(parent, &pos, &trow, &tcol, &tcolc, &tcole, true); + row += trow - 1; + col += tcol - 1; + } } api_clear_error(&dummy); - if (wp->w_float_config.bufpos.lnum >= 0) { - pos_T pos = { wp->w_float_config.bufpos.lnum + 1, - wp->w_float_config.bufpos.col, 0 }; - int trow, tcol, tcolc, tcole; - textpos2screenpos(wp, &pos, &trow, &tcol, &tcolc, &tcole, true); - row += trow - 1; - col += tcol - 1; - } wp->w_winrow = row; wp->w_wincol = col; } else { @@ -839,7 +883,7 @@ void win_config_float(win_T *wp, FloatConfig fconfig) // changing border style while keeping border only requires redrawing border if (fconfig.border) { wp->w_redr_border = true; - redraw_later(wp, VALID); + redraw_later(wp, UPD_VALID); } } @@ -864,13 +908,13 @@ int win_fdccol_count(win_T *wp) const int fdccol = fdc[4] == ':' ? fdc[5] - '0' : 1; int needed_fdccols = getDeepestNesting(wp); return MIN(fdccol, needed_fdccols); - } else { - return fdc[0] - '0'; } + return fdc[0] - '0'; } -void ui_ext_win_position(win_T *wp) +void ui_ext_win_position(win_T *wp, bool validate) { + wp->w_pos_changed = false; if (!wp->w_floating) { ui_call_win_pos(wp->w_grid_alloc.handle, wp->handle, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_height); @@ -908,6 +952,11 @@ void ui_ext_win_position(win_T *wp) grid->handle, row, col, c.focusable, wp->w_grid_alloc.zindex); } else { + bool valid = (wp->w_redr_type == 0); + if (!valid && !validate) { + wp->w_pos_changed = true; + return; + } // TODO(bfredl): ideally, compositor should work like any multigrid UI // and use standard win_pos events. bool east = c.anchor & kFloatAnchorEast; @@ -921,14 +970,13 @@ void ui_ext_win_position(win_T *wp) comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0); wp->w_winrow = comp_row; wp->w_wincol = comp_col; - bool valid = (wp->w_redr_type == 0); ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col, wp->w_height_outer, wp->w_width_outer, valid, false); ui_check_cursor_grid(wp->w_grid_alloc.handle); wp->w_grid_alloc.focusable = wp->w_float_config.focusable; if (!valid) { wp->w_grid_alloc.valid = false; - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); } } } else { @@ -968,21 +1016,19 @@ static int check_split_disallowed(void) return OK; } -/* - * 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 screen (help window). - * WSP_BOT: open window at the bottom-right of the screen (quickfix window). - * WSP_HELP: creating the help window, keep layout snapshot - * - * return FAIL for failure, OK otherwise - */ +// 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 screen (help window). +// WSP_BOT: open window at the bottom-right of the screen (quickfix window). +// WSP_HELP: creating the help window, keep layout snapshot +// +// return FAIL for failure, OK otherwise int win_split(int size, int flags) { if (check_split_disallowed() == FAIL) { @@ -1012,35 +1058,20 @@ int win_split(int size, int flags) 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 - */ +// 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; - bool do_equal = false; - int needed; - int available; - int oldwin_height = 0; - int layout; - frame_T *frp, *curfrp, *frp2, *prevfrp; - int before; - int minheight; - int wmh1; - bool did_set_fraction = false; - // aucmd_win should always remain floating - if (new_wp != NULL && new_wp == aucmd_win) { + // aucmd_win[] should always remain floating + if (new_wp != NULL && is_aucmd_win(new_wp)) { return FAIL; } + win_T *oldwin; if (flags & WSP_TOP) { oldwin = firstwin; } else if (flags & WSP_BOT || curwin->w_floating) { @@ -1050,6 +1081,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) oldwin = curwin; } + int need_status = 0; + int new_size = size; bool new_in_layout = (new_wp == NULL || new_wp->w_floating); // add a status line when p_ls == 1 and splitting the first window @@ -1061,32 +1094,33 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) need_status = STATUS_HEIGHT; } - if (flags & WSP_VERT) { - int wmw1; - int minwidth; - - layout = FR_ROW; + bool do_equal = false; + int oldwin_height = 0; + const int layout = flags & WSP_VERT ? FR_ROW : FR_COL; + bool did_set_fraction = false; - /* - * Check if we are able to split the current window and compute its - * width. - */ + if (flags & WSP_VERT) { + // Check if we are able to split the current window and compute its + // width. // Current window requires at least 1 space. - wmw1 = (p_wmw == 0 ? 1 : (int)p_wmw); - needed = wmw1 + 1; + int wmw1 = (p_wmw == 0 ? 1 : (int)p_wmw); + int needed = wmw1 + 1; if (flags & WSP_ROOM) { needed += (int)p_wiw - wmw1; } + int minwidth; + int available; if (flags & (WSP_BOT | WSP_TOP)) { minwidth = frame_minwidth(topframe, NOWIN); available = topframe->fr_width; needed += minwidth; } else if (p_ea) { minwidth = frame_minwidth(oldwin->w_frame, NOWIN); - prevfrp = oldwin->w_frame; - for (frp = oldwin->w_frame->fr_parent; frp != NULL; + frame_T *prevfrp = oldwin->w_frame; + for (frame_T *frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) { if (frp->fr_layout == FR_ROW) { + frame_T *frp2; FOR_ALL_FRAMES(frp2, frp->fr_child) { if (frp2 != prevfrp) { minwidth += frame_minwidth(frp2, NOWIN); @@ -1132,7 +1166,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // 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; + frame_T *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 @@ -1145,27 +1179,28 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } } else { - layout = FR_COL; - // Check if we are able to split the current window and compute its height. // Current window requires at least 1 space plus space for the window bar. - wmh1 = MAX((int)p_wmh, 1) + oldwin->w_winbar_height; - needed = wmh1 + STATUS_HEIGHT; + int wmh1 = MAX((int)p_wmh, 1) + oldwin->w_winbar_height; + int needed = wmh1 + STATUS_HEIGHT; if (flags & WSP_ROOM) { needed += (int)p_wh - wmh1 + oldwin->w_winbar_height; } if (p_ch < 1) { needed += 1; // Adjust for cmdheight=0. } + int minheight; + int available; if (flags & (WSP_BOT | WSP_TOP)) { minheight = frame_minheight(topframe, NOWIN) + need_status; available = topframe->fr_height; needed += minheight; } else if (p_ea) { minheight = frame_minheight(oldwin->w_frame, NOWIN) + need_status; - prevfrp = oldwin->w_frame; - for (frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) { + frame_T *prevfrp = oldwin->w_frame; + for (frame_T *frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) { if (frp->fr_layout == FR_COL) { + frame_T *frp2; FOR_ALL_FRAMES(frp2, frp->fr_child) { if (frp2 != prevfrp) { minheight += frame_minheight(frp2, NOWIN); @@ -1228,7 +1263,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) if (!do_equal && p_ea && size == 0 && *p_ead != 'h' && oldwin->w_frame->fr_parent != NULL) { - frp = oldwin->w_frame->fr_parent->fr_child; + frame_T *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 @@ -1241,9 +1276,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } - /* - * allocate new window structure and link it in the window list - */ + // allocate new window structure and link it in the window list if ((flags & WSP_TOP) == 0 && ((flags & WSP_BOT) || (flags & WSP_BELOW) @@ -1280,9 +1313,10 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) CLEAR_FIELD(wp->w_border_adj); } - /* - * Reorganise the tree of frames to insert the new window. - */ + int before; + frame_T *curfrp; + + // 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)) { @@ -1299,9 +1333,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } else { curfrp = oldwin->w_frame; if (flags & WSP_BELOW) { - before = FALSE; + before = false; } else if (flags & WSP_ABOVE) { - before = TRUE; + before = true; } else if (flags & WSP_VERT) { before = !p_spr; } else { @@ -1310,7 +1344,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } 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)); + frame_T *frp = xcalloc(1, sizeof(frame_T)); *frp = *curfrp; curfrp->fr_layout = (char)layout; frp->fr_parent = curfrp; @@ -1328,6 +1362,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) } } + frame_T *frp; if (new_wp == NULL) { frp = wp->w_frame; } else { @@ -1474,8 +1509,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // Both windows need redrawing. Update all status lines, in case they // show something related to the window count or position. - redraw_later(wp, NOT_VALID); - redraw_later(oldwin, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); + redraw_later(oldwin, UPD_NOT_VALID); status_redraw_all(); if (need_status) { @@ -1487,13 +1522,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) msg_col = 0; // put position back at start of line } - /* - * equalize the window sizes. - */ + // equalize the window sizes. if (do_equal || dir != 0) { win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v')); + } else if (*p_spk != 'c' && !is_aucmd_win(wp)) { + win_fix_scroll(false); } + int i; + // Don't change the window height/width to 'winheight' / 'winwidth' if a // size was given. if (flags & WSP_VERT) { @@ -1525,17 +1562,13 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) 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. - */ +// 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++; @@ -1565,15 +1598,21 @@ static void win_init(win_T *newp, win_T *oldp, int flags) newp->w_prevdir = (oldp->w_prevdir == NULL) ? NULL : xstrdup(oldp->w_prevdir); + if (*p_spk != 'c') { + newp->w_botline = oldp->w_botline; + newp->w_prev_height = oldp->w_height; + newp->w_prev_winrow = oldp->w_winrow; + } + // copy tagstack and folds - for (i = 0; i < oldp->w_tagstacklen; i++) { + for (int i = 0; i < oldp->w_tagstacklen; i++) { taggy_T *tag = &newp->w_tagstack[i]; *tag = oldp->w_tagstack[i]; if (tag->tagname != NULL) { - tag->tagname = vim_strsave(tag->tagname); + tag->tagname = xstrdup(tag->tagname); } if (tag->user_data != NULL) { - tag->user_data = vim_strsave(tag->user_data); + tag->user_data = xstrdup(tag->user_data); } } newp->w_tagstackidx = oldp->w_tagstackidx; @@ -1589,15 +1628,13 @@ static void win_init(win_T *newp, win_T *oldp, int flags) newp->w_winbar_height = oldp->w_winbar_height; } -/* - * Initialize window "newp" from window "old". - * Only the essential things are copied. - */ +// 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_alist->al_refcount++; newp->w_arg_idx = oldp->w_arg_idx; // copy options from existing window @@ -1627,11 +1664,20 @@ bool win_valid_floating(const win_T *win) /// @param win window to check bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { + return tabpage_win_valid(curtab, win); +} + +/// Check if "win" is a pointer to an existing window in tabpage "tp". +/// +/// @param win window to check +static bool tabpage_win_valid(const tabpage_T *tp, const win_T *win) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ if (win == NULL) { return false; } - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { if (wp == win) { return true; } @@ -1669,9 +1715,7 @@ bool win_valid_any_tab(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return false; } -/* - * Return the number of windows. - */ +// Return the number of windows. int win_count(void) { int count = 0; @@ -1692,7 +1736,6 @@ int win_count(void) int make_windows(int count, bool vertical) { int maxcount; - int todo; if (vertical) { // Each window needs at least 'winminwidth' lines and a separator column. @@ -1722,8 +1765,10 @@ int make_windows(int count, bool vertical) // when putting the buffers in the windows. block_autocmds(); + int todo; + // todo is number of windows left to create - for (todo = count - 1; todo > 0; --todo) { + 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) { @@ -1744,17 +1789,9 @@ int make_windows(int count, bool vertical) return count - todo; } -/* - * Exchange current and next window - */ +// 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 (curwin->w_floating) { emsg(e_floatexchange); return; @@ -1766,9 +1803,9 @@ static void win_exchange(long Prenum) return; } - /* - * find window to exchange with - */ + frame_T *frp; + + // find window to exchange with if (Prenum) { frp = curwin->w_frame->fr_parent->fr_child; while (frp != NULL && --Prenum > 0) { @@ -1785,18 +1822,16 @@ static void win_exchange(long Prenum) if (frp == NULL || frp->fr_win == NULL || frp->fr_win == curwin) { return; } - wp = frp->fr_win; - - /* - * 1. remove curwin from the list. Remember after which window it was in wp2 - * 2. insert curwin before wp in the list - * if wp != wp2 - * 3. remove wp from the list - * 4. insert wp after wp2 - * 5. exchange the status line height, winbar height, hsep height and vsep width. - */ - wp2 = curwin->w_prev; - frp2 = curwin->w_frame->fr_prev; + win_T *wp = frp->fr_win; + + // 1. remove curwin from the list. Remember after which window it was in wp2 + // 2. insert curwin before wp in the list + // if wp != wp2 + // 3. remove wp from the list + // 4. insert wp after wp2 + // 5. exchange the status line height, winbar height, hsep height and vsep width. + win_T *wp2 = curwin->w_prev; + frame_T *frp2 = curwin->w_frame->fr_prev; if (wp->w_prev != curwin) { win_remove(curwin, NULL); frame_remove(curwin->w_frame); @@ -1813,7 +1848,7 @@ static void win_exchange(long Prenum) frame_append(frp2, wp->w_frame); } } - temp = curwin->w_status_height; + int temp = curwin->w_status_height; curwin->w_status_height = wp->w_status_height; wp->w_status_height = temp; temp = curwin->w_vsep_width; @@ -1837,19 +1872,14 @@ static void win_exchange(long Prenum) } win_enter(wp, true); - redraw_later(curwin, NOT_VALID); - redraw_later(wp, NOT_VALID); + redraw_later(curwin, UPD_NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); } // rotate windows: if upwards true the second window becomes the first one // if upwards false the first window becomes the second one static void win_rotate(bool upwards, int count) { - win_T *wp1; - win_T *wp2; - frame_T *frp; - int n; - if (curwin->w_floating) { emsg(e_floatexchange); return; @@ -1862,6 +1892,7 @@ static void win_rotate(bool upwards, int count) } // Check if all frames in this row/col have one window. + frame_T *frp; FOR_ALL_FRAMES(frp, curwin->w_frame->fr_parent->fr_child) { if (frp->fr_win == NULL) { emsg(_("E443: Cannot rotate when another window is split")); @@ -1869,6 +1900,9 @@ static void win_rotate(bool upwards, int count) } } + win_T *wp1; + win_T *wp2; + while (count--) { if (upwards) { // first window becomes last window // remove first window/frame from the list @@ -1901,7 +1935,7 @@ static void win_rotate(bool upwards, int count) } // exchange status height, winbar height, hsep height and vsep width of old and new last window - n = wp2->w_status_height; + int n = wp2->w_status_height; wp2->w_status_height = wp1->w_status_height; wp1->w_status_height = n; n = wp2->w_hsep_height; @@ -1922,12 +1956,10 @@ static void win_rotate(bool upwards, int count) wp1->w_pos_changed = true; wp2->w_pos_changed = true; - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } -/* - * Move the current window to the very top/bottom/left/right of the screen. - */ +// Move the current window to the very top/bottom/left/right of the screen. static void win_totop(int size, int flags) { int dir = 0; @@ -1937,7 +1969,7 @@ static void win_totop(int size, int flags) beep_flush(); return; } - if (curwin == aucmd_win) { + if (is_aucmd_win(curwin)) { return; } if (check_split_disallowed() == FAIL) { @@ -1971,14 +2003,10 @@ static void win_totop(int size, int flags) } } -/* - * Move window "win1" to below/right of "win2" and make "win1" the current - * window. Only works within the same frame! - */ +// Move window "win1" to below/right of "win2" and make "win1" the current +// window. Only works within the same frame! void win_move_after(win_T *win1, win_T *win2) { - int height; - // check if the arguments are reasonable if (win1 == win2) { return; @@ -1994,7 +2022,7 @@ void win_move_after(win_T *win1, win_T *win2) // may need to move the status line, window bar, horizontal or vertical separator of the last // window if (win1 == lastwin) { - height = win1->w_prev->w_status_height; + int height = win1->w_prev->w_status_height; win1->w_prev->w_status_height = win1->w_status_height; win1->w_status_height = height; @@ -2011,7 +2039,7 @@ void win_move_after(win_T *win1, win_T *win2) win1->w_frame->fr_width += 1; } } else if (win2 == lastwin) { - height = win1->w_status_height; + int height = win1->w_status_height; win1->w_status_height = win2->w_status_height; win2->w_status_height = height; @@ -2034,7 +2062,7 @@ void win_move_after(win_T *win1, win_T *win2) frame_append(win2->w_frame, win1->w_frame); (void)win_comp_pos(); // recompute w_winrow for all windows - redraw_later(curwin, NOT_VALID); + redraw_later(curwin, UPD_NOT_VALID); } win_enter(win1, false); @@ -2074,7 +2102,7 @@ static int get_maximum_wincount(frame_T *fr, int height) } /// Make all windows the same height. -///'next_curwin' will soon be the current window, make sure it has enough rows. +/// 'next_curwin' will soon be the current window, make sure it has enough rows. /// /// @param next_curwin pointer to current window to be or NULL /// @param current do only frame with current window @@ -2082,11 +2110,14 @@ static int get_maximum_wincount(frame_T *fr, int height) void win_equal(win_T *next_curwin, bool current, int dir) { if (dir == 0) { - dir = *p_ead; + dir = (unsigned char)(*p_ead); } win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current, topframe, dir, 0, tabline_height(), Columns, topframe->fr_height); + if (*p_spk != 'c' && !is_aucmd_win(next_curwin)) { + win_fix_scroll(true); + } } /// Set a frame to a new position and height, spreading the av |