aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r--src/nvim/window.c372
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;