diff options
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r-- | src/nvim/window.c | 372 |
1 files changed, 245 insertions, 127 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c index b737215616..74ea1172ee 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6,11 +6,14 @@ #include <stdbool.h> #include "nvim/api/private/helpers.h" +#include "nvim/api/vim.h" +#include "nvim/arglist.h" #include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/diff.h" +#include "nvim/drawscreen.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/vars.h" @@ -25,7 +28,9 @@ #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/globals.h" +#include "nvim/grid.h" #include "nvim/hashtab.h" +#include "nvim/highlight.h" #include "nvim/main.h" #include "nvim/mapping.h" #include "nvim/mark.h" @@ -37,13 +42,13 @@ #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" +#include "nvim/optionstr.h" #include "nvim/os/os.h" #include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/plines.h" #include "nvim/quickfix.h" #include "nvim/regexp.h" -#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/state.h" #include "nvim/strings.h" @@ -122,7 +127,7 @@ void do_window(int nchar, long Prenum, int xchar) { long Prenum1; win_T *wp; - char_u *ptr; + char *ptr; linenr_T lnum = -1; int type = FIND_DEFINE; size_t len; @@ -210,7 +215,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; @@ -218,7 +223,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; @@ -251,7 +256,7 @@ newwindow: 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; @@ -483,14 +488,14 @@ newwindow: wingotofile: CHECK_CMDWIN; - ptr = grab_file_name(Prenum1, &lnum); + ptr = (char *)grab_file_name(Prenum1, &lnum); if (ptr != NULL) { tabpage_T *oldtab = curtab; win_T *oldwin = curwin; setpcmark(); if (win_split(0, 0) == OK) { RESET_BINDING(curwin); - if (do_ecmd(0, (char *)ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { + if (do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) { // Failed to open the file, close the window opened for it. win_close(curwin, false, false); goto_tabpage_win(oldtab, oldwin); @@ -518,9 +523,9 @@ wingotofile: } // Make a copy, if the line was changed it will be freed. - ptr = vim_strnsave(ptr, len); + ptr = xstrnsave(ptr, len); - find_pattern_in_path(ptr, 0, len, true, Prenum == 0, + find_pattern_in_path((char_u *)ptr, 0, len, true, Prenum == 0, type, Prenum1, ACTION_SPLIT, 1, MAXLNUM); xfree(ptr); curwin->w_set_curswant = true; @@ -617,12 +622,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); if (Prenum > 0 && len < bufsize) { - vim_snprintf((char *)bufp + len, bufsize - len, "%" PRId64, Prenum); + vim_snprintf(bufp + len, bufsize - len, "%" PRId64, Prenum); } } @@ -698,16 +703,16 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err) win_remove(wp, NULL); win_append(lastwin_nofloating(), wp); } - wp->w_floating = 1; + wp->w_floating = true; wp->w_status_height = 0; wp->w_winbar_height = 0; wp->w_hsep_height = 0; wp->w_vsep_width = 0; win_config_float(wp, fconfig); - win_set_inner_size(wp); + win_set_inner_size(wp, true); wp->w_pos_changed = true; - redraw_later(wp, VALID); + redraw_later(wp, UPD_VALID); return wp; } @@ -722,36 +727,38 @@ 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_u *old = (char_u *)wp->w_p_fcs; wp->w_p_fcs = ((*old == NUL) - ? (char_u *)xstrdup("eob: ") - : concat_str(old, (char_u *)",eob: ")); - free_string_option(old); - } - if (wp->w_hl_ids[HLF_EOB] != -1) { - char_u *old = wp->w_p_winhl; - wp->w_p_winhl = ((*old == NUL) - ? (char_u *)xstrdup("EndOfBuffer:") - : concat_str(old, (char_u *)",EndOfBuffer:")); - free_string_option(old); + ? xstrdup("eob: ") + : concat_str((char *)old, ",eob: ")); + free_string_option((char *)old); } + // TODO(bfredl): this could use a highlight namespace directly, + // and avoid pecularities around window options + char_u *old = (char_u *)wp->w_p_winhl; + wp->w_p_winhl = ((*old == NUL) + ? xstrdup("EndOfBuffer:") + : concat_str((char *)old, ",EndOfBuffer:")); + free_string_option((char *)old); + parse_winhl_opt(wp); + // signcolumn: use 'auto' 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(""); } } @@ -789,13 +796,13 @@ void win_config_float(win_T *wp, FloatConfig fconfig) wp->w_width = MIN(wp->w_width, Columns - win_border_width(wp)); } - win_set_inner_size(wp); - must_redraw = MAX(must_redraw, VALID); + win_set_inner_size(wp, true); + 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 @@ -832,7 +839,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); } } @@ -921,7 +928,7 @@ void ui_ext_win_position(win_T *wp) 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 { @@ -1270,7 +1277,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) wp->w_floating = false; // non-floating window doesn't store float config or have a border. wp->w_float_config = FLOAT_CONFIG_INIT; - memset(wp->w_border_adj, 0, sizeof(wp->w_border_adj)); + CLEAR_FIELD(wp->w_border_adj); } /* @@ -1292,9 +1299,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 { @@ -1467,8 +1474,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) { @@ -1563,10 +1570,10 @@ static void win_init(win_T *newp, win_T *oldp, int flags) 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; @@ -1590,7 +1597,7 @@ 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 @@ -1670,7 +1677,7 @@ int win_count(void) int count = 0; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - ++count; + count++; } return count; } @@ -1716,7 +1723,7 @@ int make_windows(int count, bool vertical) block_autocmds(); // 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) { @@ -1830,8 +1837,8 @@ 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 @@ -1915,7 +1922,7 @@ 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); } /* @@ -2027,7 +2034,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); @@ -2075,7 +2082,7 @@ 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(), @@ -2118,7 +2125,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int frame_new_height(topfr, height, false, false); topfr->fr_win->w_wincol = col; frame_new_width(topfr, width, false, false); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } } else if (topfr->fr_layout == FR_ROW) { topfr->fr_width = width; @@ -2193,7 +2200,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int } if (has_next_curwin) { - --totwincount; // don't count curwin + totwincount--; // don't count curwin } } @@ -2323,7 +2330,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int } if (has_next_curwin) { - --totwincount; // don't count curwin + totwincount--; // don't count curwin } } @@ -2429,7 +2436,7 @@ void entering_window(win_T *const win) void win_init_empty(win_T *wp) { - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); wp->w_lines_valid = 0; wp->w_cursor.lnum = 1; wp->w_curswant = wp->w_cursor.col = 0; @@ -2459,7 +2466,7 @@ void close_windows(buf_T *buf, bool keep_curwin) tabpage_T *tp, *nexttp; int h = tabline_height(); - ++RedrawingDisabled; + RedrawingDisabled++; // Start from lastwin to close floating windows with the same buffer first. // When the autocommand window is involved win_close() may need to print an error message. @@ -2496,7 +2503,7 @@ void close_windows(buf_T *buf, bool keep_curwin) } } - --RedrawingDisabled; + RedrawingDisabled--; redraw_tabline = true; if (h != tabline_height()) { @@ -2928,7 +2935,7 @@ int win_close(win_T *win, bool free_buf, bool force) } curwin->w_pos_changed = true; - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); return OK; } @@ -3089,7 +3096,7 @@ void win_free_all(void) cmdwin_type = 0; while (first_tabpage->tp_next != NULL) { - tabpage_close(TRUE); + tabpage_close(true); } while (lastwin != NULL && lastwin->w_floating) { @@ -3688,7 +3695,7 @@ static void frame_add_vsep(const frame_T *frp) wp = frp->fr_win; if (wp->w_vsep_width == 0) { if (wp->w_width > 0) { // don't make it negative - --wp->w_width; + wp->w_width--; } wp->w_vsep_width = 1; } @@ -3820,7 +3827,7 @@ static int frame_minwidth(frame_T *topfrp, win_T *next_curwin) m = (int)p_wmw + topfrp->fr_win->w_vsep_width; // Current window is minimal one column wide if (p_wmw == 0 && topfrp->fr_win == curwin && next_curwin == NULL) { - ++m; + m++; } } } else if (topfrp->fr_layout == FR_COL) { @@ -4018,7 +4025,7 @@ static tabpage_T *alloc_tabpage(void) // Init t: variables. tp->tp_vars = tv_dict_alloc(); init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE); - tp->tp_diff_invalid = TRUE; + tp->tp_diff_invalid = true; tp->tp_ch_used = p_ch; return tp; @@ -4030,7 +4037,7 @@ void free_tabpage(tabpage_T *tp) pmap_del(handle_T)(&tabpage_handles, tp->handle); diff_clear(tp); - for (idx = 0; idx < SNAP_COUNT; ++idx) { + for (idx = 0; idx < SNAP_COUNT; idx++) { clear_snapshot(tp, idx); } vars_clear(&tp->tp_vars->dv_hashtab); // free all t: variables @@ -4093,7 +4100,7 @@ int win_new_tabpage(int after, char_u *filename) n = 2; for (tp = first_tabpage; tp->tp_next != NULL && n < after; tp = tp->tp_next) { - ++n; + n++; } } newtp->tp_next = tp->tp_next; @@ -4108,7 +4115,7 @@ int win_new_tabpage(int after, char_u *filename) newtp->tp_topframe = topframe; last_status(false); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); tabpage_check_windows(old_curtab); @@ -4166,7 +4173,7 @@ int make_tabpages(int maxcount) */ block_autocmds(); - for (todo = count - 1; todo > 0; --todo) { + for (todo = count - 1; todo > 0; todo--) { if (win_new_tabpage(0, NULL) == FAIL) { break; } @@ -4239,7 +4246,7 @@ tabpage_T *find_tabpage(int n) int i = 1; for (tp = first_tabpage; tp != NULL && i != n; tp = tp->tp_next) { - ++i; + i++; } return tp; } @@ -4254,7 +4261,7 @@ int tabpage_index(tabpage_T *ftp) tabpage_T *tp; for (tp = first_tabpage; tp != NULL && tp != ftp; tp = tp->tp_next) { - ++i; + i++; } return i; } @@ -4336,6 +4343,11 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a // Use the stored value of p_ch, so that it can be different for each tab page. if (p_ch != curtab->tp_ch_used) { clear_cmdline = true; + if (msg_grid.chars && p_ch < curtab->tp_ch_used) { + // TODO(bfredl): a bit expensive, should be enough to invalidate the + // region between the old and the new p_ch. + grid_invalidate(&msg_grid); + } } p_ch = curtab->tp_ch_used; @@ -4366,7 +4378,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a } } - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } /// tells external UI that windows and inline floats in old_curtab are invisible @@ -4433,7 +4445,7 @@ void goto_tabpage(int n) // "gT": go to previous tab page, wrap around end. "N gT" repeats // this N times. ttp = curtab; - for (i = n; i < 0; ++i) { + for (i = n; i < 0; i++) { for (tp = first_tabpage; tp->tp_next != ttp && tp->tp_next != NULL; tp = tp->tp_next) {} ttp = tp; @@ -4516,7 +4528,7 @@ void tabpage_move(int nr) } for (tp = first_tabpage; tp->tp_next != NULL && n < nr; tp = tp->tp_next) { - ++n; + n++; } if (tp == curtab || (nr > 0 && tp->tp_next != NULL @@ -4829,7 +4841,7 @@ static void win_enter_ext(win_T *const wp, const int flags) } if (!curwin_invalid) { prevwin = curwin; // remember for CTRL-W p - curwin->w_redr_status = TRUE; + curwin->w_redr_status = true; } curwin = wp; curbuf = wp->w_buffer; @@ -4860,13 +4872,20 @@ static void win_enter_ext(win_T *const wp, const int flags) curwin->w_redr_status = true; redraw_tabline = true; if (restart_edit) { - redraw_later(curwin, VALID); // causes status line redraw + redraw_later(curwin, UPD_VALID); // causes status line redraw } - if (HL_ATTR(HLF_INACTIVE) - || (prevwin && prevwin->w_hl_ids[HLF_INACTIVE]) - || curwin->w_hl_ids[HLF_INACTIVE]) { - redraw_all_later(NOT_VALID); + // change background color according to NormalNC, + // but only if actually defined (otherwise no extra redraw) + if (curwin->w_hl_attr_normal != curwin->w_hl_attr_normalnc) { + // TODO(bfredl): eventually we should be smart enough + // to only recompose the window, not redraw it. + redraw_later(curwin, UPD_NOT_VALID); + } + if (prevwin) { + if (prevwin->w_hl_attr_normal != prevwin->w_hl_attr_normalnc) { + redraw_later(prevwin, UPD_NOT_VALID); + } } // set window height to desired minimal value @@ -5035,6 +5054,8 @@ static win_T *win_alloc(win_T *after, bool hidden) new_wp->w_float_config = FLOAT_CONFIG_INIT; new_wp->w_viewport_invalid = true; + new_wp->w_ns_hl = -1; + // use global option for global-local options new_wp->w_p_so = -1; new_wp->w_p_siso = -1; @@ -5175,7 +5196,7 @@ void win_free_grid(win_T *wp, bool reinit) grid_free(&wp->w_grid_alloc); if (reinit) { // if a float is turned into a split, the grid data structure will be reused - memset(&wp->w_grid_alloc, 0, sizeof(wp->w_grid_alloc)); + CLEAR_FIELD(wp->w_grid_alloc); } } @@ -5346,6 +5367,7 @@ void may_trigger_winscrolled(void) win_T *wp = curwin; if (wp->w_last_topline != wp->w_topline || wp->w_last_leftcol != wp->w_leftcol + || wp->w_last_skipcol != wp->w_skipcol || wp->w_last_width != wp->w_width || wp->w_last_height != wp->w_height) { char winid[NUMBUFLEN]; @@ -5359,6 +5381,7 @@ void may_trigger_winscrolled(void) if (win_valid_any_tab(wp)) { wp->w_last_topline = wp->w_topline; wp->w_last_leftcol = wp->w_leftcol; + wp->w_last_skipcol = wp->w_skipcol; wp->w_last_width = wp->w_width; wp->w_last_height = wp->w_height; } @@ -5454,7 +5477,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col) // position changed, redraw wp->w_winrow = *row; wp->w_wincol = *col; - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); wp->w_redr_status = true; wp->w_pos_changed = true; } @@ -5497,7 +5520,7 @@ void win_setheight_win(int height, win_T *win) if (win->w_floating) { win->w_float_config.height = height; win_config_float(win, win->w_float_config); - redraw_later(win, NOT_VALID); + redraw_later(win, UPD_NOT_VALID); } else { frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height); @@ -5517,7 +5540,7 @@ void win_setheight_win(int height, win_T *win) curtab->tp_ch_used = p_ch; msg_row = row; msg_col = 0; - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); redraw_cmdline = true; } } @@ -5551,7 +5574,7 @@ static void frame_setheight(frame_T *curfrp, int height) } if (curfrp->fr_parent == NULL) { - // topframe: can only change the command line + // topframe: can only change the command line height if (height > ROWS_AVAIL) { // If height is greater than the available space, try to create space for // the frame by reducing 'cmdheight' if possible, while making sure @@ -5580,7 +5603,7 @@ static void frame_setheight(frame_T *curfrp, int height) * 2: compute the room available and adjust the height to it. * Try not to reduce the height of a window with 'winfixheight' set. */ - for (run = 1; run <= 2; ++run) { + for (run = 1; run <= 2; run++) { room = 0; room_reserved = 0; FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) { @@ -5653,7 +5676,7 @@ static void frame_setheight(frame_T *curfrp, int height) * that is not enough, takes lines from frames above the current * frame. */ - for (run = 0; run < 2; ++run) { + for (run = 0; run < 2; run++) { if (run == 0) { frp = curfrp->fr_next; // 1st run: start with next window } else { @@ -5719,13 +5742,13 @@ void win_setwidth_win(int width, win_T *wp) if (wp->w_floating) { wp->w_float_config.width = width; win_config_float(wp, wp->w_float_config); - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); } else { frame_setwidth(wp->w_frame, width + wp->w_vsep_width); // recompute the window positions (void)win_comp_pos(); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } } @@ -5772,7 +5795,7 @@ static void frame_setwidth(frame_T *curfrp, int width) * containing frame. * 2: compute the room available and adjust the width to it. */ - for (run = 1; run <= 2; ++run) { + for (run = 1; run <= 2; run++) { room = 0; room_reserved = 0; FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) { @@ -5825,7 +5848,7 @@ static void frame_setwidth(frame_T *curfrp, int width) * that is not enough, takes lines from frames left of the current * frame. */ - for (run = 0; run < 2; ++run) { + for (run = 0; run < 2; run++) { if (run == 0) { frp = curfrp->fr_next; // 1st run: start with next window } else { @@ -5914,6 +5937,13 @@ void win_drag_status_line(win_T *dragwin, int offset) int row; bool up; // if true, drag status line up, otherwise down int n; + static bool p_ch_was_zero = false; + + // If the user explicitly set 'cmdheight' to zero, then allow for dragging + // the status line making it zero again. + if (p_ch == 0) { + p_ch_was_zero = true; + } fr = dragwin->w_frame; curfr = fr; @@ -5964,6 +5994,8 @@ void win_drag_status_line(win_T *dragwin, int offset) room = Rows - cmdline_row; if (curfr->fr_next != NULL) { room -= (int)p_ch + global_stl_height(); + } else if (!p_ch_was_zero) { + room--; } if (room < 0) { room = 0; @@ -6019,9 +6051,9 @@ void win_drag_status_line(win_T *dragwin, int offset) clear_cmdline = true; } cmdline_row = row; - p_ch = MAX(Rows - cmdline_row, 0); + p_ch = MAX(Rows - cmdline_row, p_ch_was_zero ? 0 : 1); curtab->tp_ch_used = p_ch; - redraw_all_later(SOME_VALID); + redraw_all_later(UPD_SOME_VALID); showmode(); } @@ -6128,7 +6160,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset) } } (void)win_comp_pos(); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } #define FRACTION_MULT 16384L @@ -6162,7 +6194,7 @@ void win_new_height(win_T *wp, int height) wp->w_height = height; wp->w_pos_changed = true; - win_set_inner_size(wp); + win_set_inner_size(wp, true); } void scroll_to_fraction(win_T *wp, int prev_height) @@ -6225,7 +6257,7 @@ void scroll_to_fraction(win_T *wp, int prev_height) if (lnum == 1) { // first line in buffer is folded line_size = 1; - --sline; + sline--; break; } lnum--; @@ -6266,12 +6298,12 @@ void scroll_to_fraction(win_T *wp, int prev_height) } win_comp_scroll(wp); - redraw_later(wp, SOME_VALID); + redraw_later(wp, UPD_SOME_VALID); wp->w_redr_status = true; invalidate_botline_win(wp); } -void win_set_inner_size(win_T *wp) +void win_set_inner_size(win_T *wp, bool valid_cursor) { int width = wp->w_width_request; if (width == 0) { @@ -6285,7 +6317,7 @@ void win_set_inner_size(win_T *wp) } if (height != prev_height) { - if (height > 0) { + if (height > 0 && valid_cursor) { if (wp == curwin) { // w_wrow needs to be valid. When setting 'laststatus' this may // call win_new_height() recursively. @@ -6304,22 +6336,24 @@ void win_set_inner_size(win_T *wp) // There is no point in adjusting the scroll position when exiting. Some // values might be invalid. // Skip scroll_to_fraction() when 'cmdheight' was set to one from zero. - if (!exiting && !made_cmdheight_nonzero) { + if (!exiting && !made_cmdheight_nonzero && valid_cursor) { scroll_to_fraction(wp, prev_height); } - redraw_later(wp, NOT_VALID); // SOME_VALID?? + redraw_later(wp, UPD_NOT_VALID); // UPD_SOME_VALID?? } if (width != wp->w_width_inner) { wp->w_width_inner = width; wp->w_lines_valid = 0; - changed_line_abv_curs_win(wp); - invalidate_botline_win(wp); - if (wp == curwin) { - update_topline(wp); - curs_columns(wp, true); // validate w_wrow + if (valid_cursor) { + changed_line_abv_curs_win(wp); + invalidate_botline_win(wp); + if (wp == curwin) { + update_topline(wp); + curs_columns(wp, true); // validate w_wrow + } } - redraw_later(wp, NOT_VALID); + redraw_later(wp, UPD_NOT_VALID); } if (wp->w_buffer->terminal) { @@ -6346,7 +6380,7 @@ static int win_border_width(win_T *wp) void win_new_width(win_T *wp, int width) { wp->w_width = width; - win_set_inner_size(wp); + win_set_inner_size(wp, true); wp->w_redr_status = true; wp->w_pos_changed = true; @@ -6381,6 +6415,19 @@ void command_height(void) // p_ch was changed in another tab page. curtab->tp_ch_used = p_ch; + // If the space for the command line is already more than 'cmdheight' there + // is nothing to do (window size must have decreased). + if (p_ch > old_p_ch && cmdline_row <= Rows - p_ch) { + return; + } + + // If cmdline_row is smaller than what it is supposed to be for 'cmdheight' + // then set old_p_ch to what it would be, so that the windows get resized + // properly for the new value. + if (cmdline_row < Rows - p_ch) { + old_p_ch = Rows - cmdline_row; + } + // Find bottom frame with width of screen. frp = lastwin_nofloating()->w_frame; while (frp->fr_width != Columns && frp->fr_parent != NULL) { @@ -6465,17 +6512,17 @@ char_u *grab_file_name(long count, linenr_T *file_lnum) int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC; if (VIsual_active) { size_t len; - char_u *ptr; + char *ptr; if (get_visual_text(NULL, &ptr, &len) == FAIL) { return NULL; } // Only recognize ":123" here if (file_lnum != NULL && ptr[len] == ':' && isdigit(ptr[len + 1])) { - char *p = (char *)ptr + len + 1; + char *p = ptr + len + 1; *file_lnum = (linenr_T)getdigits_long(&p, false, 0); } - return find_file_name_in_path(ptr, len, options, count, (char_u *)curbuf->b_ffname); + return find_file_name_in_path((char_u *)ptr, len, options, count, (char_u *)curbuf->b_ffname); } return file_name_at_cursor(options | FNAME_HYP, count, file_lnum); } @@ -6542,7 +6589,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u /* * Search forward for the last char of the file name. - * Also allow "://" when ':' is not in 'isfname'. + * Also allow ":/" when ':' is not in 'isfname'. */ len = 0; while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ') @@ -6561,7 +6608,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u if (ptr[len] == '\\' && ptr[len + 1] == ' ') { // Skip over the "\" in "\ ". - ++len; + len++; } len += (size_t)(utfc_ptr2len(ptr + len)); } @@ -6572,7 +6619,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u */ if (len > 2 && vim_strchr(".,:;!", ptr[len - 1]) != NULL && ptr[len - 2] != '.') { - --len; + len--; } if (file_lnum != NULL) { @@ -6726,7 +6773,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) wp->w_hsep_height = 0; comp_col(); } - redraw_all_later(SOME_VALID); + redraw_all_later(UPD_SOME_VALID); } else { // For a column or row frame, recursively call this function for all child frames FOR_ALL_FRAMES(fp, fr->fr_child) { @@ -6738,9 +6785,11 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) /// Add or remove window bar from window "wp". /// /// @param make_room Whether to resize frames to make room for winbar. +/// @param valid_cursor Whether the cursor is valid and should be used while +/// resizing. /// /// @return Success status. -int set_winbar_win(win_T *wp, bool make_room) +int set_winbar_win(win_T *wp, bool make_room, bool valid_cursor) { // Require the local value to be set in order to show winbar on a floating window. int winbar_height = wp->w_floating ? ((*wp->w_p_wbr != NUL) ? 1 : 0) @@ -6756,7 +6805,7 @@ int set_winbar_win(win_T *wp, bool make_room) } } wp->w_winbar_height = winbar_height; - win_set_inner_size(wp); + win_set_inner_size(wp, valid_cursor); wp->w_redr_status = wp->w_redr_status || winbar_height; if (winbar_height == 0) { @@ -6777,7 +6826,7 @@ int set_winbar_win(win_T *wp, bool make_room) void set_winbar(bool make_room) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (set_winbar_win(wp, make_room) == FAIL) { + if (set_winbar_win(wp, make_room, true) == FAIL) { break; } } @@ -7024,7 +7073,7 @@ void restore_snapshot(int idx, int close_curwin) if (wp != NULL && close_curwin) { win_goto(wp); } - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } clear_snapshot(curtab, idx); } @@ -7095,7 +7144,7 @@ int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_displa // As switch_win() but without blocking autocommands. int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display) { - memset(switchwin, 0, sizeof(switchwin_T)); + CLEAR_POINTER(switchwin); switchwin->sw_curwin = curwin; if (win == curwin) { switchwin->sw_same_win = true; @@ -7228,6 +7277,88 @@ static bool frame_check_width(const frame_T *topfrp, int width) return true; } +/// Simple int comparison function for use with qsort() +static int int_cmp(const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} + +/// Handle setting 'colorcolumn' or 'textwidth' in window "wp". +/// +/// @return error message, NULL if it's OK. +char *check_colorcolumn(win_T *wp) +{ + char *s; + int col; + unsigned int count = 0; + int color_cols[256]; + int j = 0; + + if (wp->w_buffer == NULL) { + return NULL; // buffer was closed + } + + for (s = wp->w_p_cc; *s != NUL && count < 255;) { + if (*s == '-' || *s == '+') { + // -N and +N: add to 'textwidth' + col = (*s == '-') ? -1 : 1; + s++; + if (!ascii_isdigit(*s)) { + return e_invarg; + } + col = col * getdigits_int(&s, true, 0); + if (wp->w_buffer->b_p_tw == 0) { + goto skip; // 'textwidth' not set, skip this item + } + assert((col >= 0 + && wp->w_buffer->b_p_tw <= INT_MAX - col + && wp->w_buffer->b_p_tw + col >= INT_MIN) + || (col < 0 + && wp->w_buffer->b_p_tw >= INT_MIN - col + && wp->w_buffer->b_p_tw + col <= INT_MAX)); + col += (int)wp->w_buffer->b_p_tw; + if (col < 0) { + goto skip; + } + } else if (ascii_isdigit(*s)) { + col = getdigits_int(&s, true, 0); + } else { + return e_invarg; + } + color_cols[count++] = col - 1; // 1-based to 0-based +skip: + if (*s == NUL) { + break; + } + if (*s != ',') { + return e_invarg; + } + if (*++s == NUL) { + return e_invarg; // illegal trailing comma as in "set cc=80," + } + } + + xfree(wp->w_p_cc_cols); + if (count == 0) { + wp->w_p_cc_cols = NULL; + } else { + wp->w_p_cc_cols = xmalloc(sizeof(int) * (count + 1)); + // sort the columns for faster usage on screen redraw inside + // win_line() + qsort(color_cols, count, sizeof(int), int_cmp); + + for (unsigned int i = 0; i < count; i++) { + // skip duplicates + if (j == 0 || wp->w_p_cc_cols[j - 1] != color_cols[i]) { + wp->w_p_cc_cols[j++] = color_cols[i]; + } + } + wp->w_p_cc_cols[j] = -1; // end marker + } + + return NULL; // no error +} + int win_getid(typval_T *argvars) { if (argvars[0].v_type == VAR_UNKNOWN) { @@ -7265,19 +7396,6 @@ int win_getid(typval_T *argvars) return 0; } -int win_gotoid(typval_T *argvars) -{ - int id = (int)tv_get_number(&argvars[0]); - - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp->handle == id) { - goto_tabpage_win(tp, wp); - return 1; - } - } - return 0; -} - void win_get_tabwin(handle_T id, int *tabnr, int *winnr) { *tabnr = 0; |