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.c207
1 files changed, 163 insertions, 44 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 3499b14688..27fb160035 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -982,13 +982,13 @@ static void win_init_some(win_T *newp, win_T *oldp)
*/
int win_valid(win_T *win)
{
- win_T *wp;
-
if (win == NULL)
return FALSE;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- if (wp == win)
+ FOR_ALL_WINDOWS(wp) {
+ if (wp == win) {
return TRUE;
+ }
+ }
return FALSE;
}
@@ -997,11 +997,11 @@ int win_valid(win_T *win)
*/
int win_count(void)
{
- win_T *wp;
int count = 0;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
++count;
+ }
return count;
}
@@ -1677,20 +1677,19 @@ static int last_window(void)
* Return TRUE if there is only one window other than "aucmd_win" in the
* current tab page.
*/
-int one_window(void)
+bool one_window(void)
{
- win_T *wp;
- int seen_one = FALSE;
+ bool seen_one = false;
- FOR_ALL_WINDOWS(wp)
- {
+ FOR_ALL_WINDOWS(wp) {
if (wp != aucmd_win) {
- if (seen_one)
- return FALSE;
- seen_one = TRUE;
+ if (seen_one) {
+ return false;
+ }
+ seen_one = true;
}
}
- return TRUE;
+ return true;
}
/*
@@ -2002,6 +2001,10 @@ void win_free_all(void)
while (firstwin != NULL)
(void)win_free_mem(firstwin, &dummy, NULL);
+
+ // No window should be used after this. Set curwin to NULL to crash
+ // instead of using freed memory.
+ curwin = NULL;
}
#endif
@@ -3476,14 +3479,14 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, int tri
*/
win_T *buf_jump_open_win(buf_T *buf)
{
- win_T *wp;
+ FOR_ALL_WINDOWS(wp) {
+ if (wp->w_buffer == buf) {
+ win_enter(wp, false);
+ return wp;
+ }
+ }
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- if (wp->w_buffer == buf)
- break;
- if (wp != NULL)
- win_enter(wp, false);
- return wp;
+ return NULL;
}
/*
@@ -3785,11 +3788,9 @@ void shell_new_columns(void)
void win_size_save(garray_T *gap)
{
- win_T *wp;
-
ga_init(gap, (int)sizeof(int), 1);
ga_grow(gap, win_count() * 2);
- for (wp = firstwin; wp != NULL; wp = wp->w_next) {
+ FOR_ALL_WINDOWS(wp) {
((int *)gap->ga_data)[gap->ga_len++] =
wp->w_width + wp->w_vsep_width;
((int *)gap->ga_data)[gap->ga_len++] = wp->w_height;
@@ -3802,13 +3803,16 @@ void win_size_save(garray_T *gap)
*/
void win_size_restore(garray_T *gap)
{
- win_T *wp;
-
if (win_count() * 2 == gap->ga_len) {
- int i = 0;
- for (wp = firstwin; wp != NULL; wp = wp->w_next) {
- frame_setwidth(wp->w_frame, ((int *)gap->ga_data)[i++]);
- win_setheight_win(((int *)gap->ga_data)[i++], wp);
+ /* The order matters, because frames contain other frames, but it's
+ * difficult to get right. The easy way out is to do it twice. */
+ for (int j = 0; j < 2; ++j)
+ {
+ int i = 0;
+ FOR_ALL_WINDOWS(wp) {
+ frame_setwidth(wp->w_frame, ((int *)gap->ga_data)[i++]);
+ win_setheight_win(((int *)gap->ga_data)[i++], wp);
+ }
}
/* recompute the window positions */
(void)win_comp_pos();
@@ -4234,14 +4238,14 @@ void win_setminheight(void)
{
int room;
int first = TRUE;
- win_T *wp;
/* loop until there is a 'winminheight' that is possible */
while (p_wmh > 0) {
/* TODO: handle vertical splits */
room = -p_wh;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
room += wp->w_height - p_wmh;
+ }
if (room >= 0)
break;
--p_wmh;
@@ -4932,20 +4936,21 @@ int min_rows(void)
int only_one_window(void)
{
int count = 0;
- win_T *wp;
/* If there is another tab page there always is another window. */
if (first_tabpage->tp_next != NULL)
return FALSE;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
+ FOR_ALL_WINDOWS(wp) {
if (wp->w_buffer != NULL
&& (!((wp->w_buffer->b_help && !curbuf->b_help)
|| wp->w_p_pvw
) || wp == curwin)
&& wp != aucmd_win
- )
+ ) {
++count;
+ }
+ }
return count <= 1;
}
@@ -5190,16 +5195,18 @@ void restore_buffer(buf_T *save_curbuf)
* If no particular ID is desired, -1 must be specified for 'id'.
* Return ID of added match, -1 on failure.
*/
-int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
+int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)
{
matchitem_T *cur;
matchitem_T *prev;
matchitem_T *m;
int hlg_id;
- regprog_T *regprog;
+ regprog_T *regprog = NULL;
+ int rtype = SOME_VALID;
- if (*grp == NUL || *pat == NUL)
+ if (*grp == NUL || (pat != NULL && *pat == NUL)) {
return -1;
+ }
if (id < -1 || id == 0) {
EMSGN("E799: Invalid ID: %" PRId64
" (must be greater than or equal to 1)",
@@ -5220,7 +5227,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
EMSG2(_(e_nogroup), grp);
return -1;
}
- if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
+ if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
EMSG2(_(e_invarg2), pat);
return -1;
}
@@ -5236,15 +5243,106 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
}
/* Build new match. */
- m = xmalloc(sizeof(matchitem_T));
+ m = xcalloc(1, sizeof(matchitem_T));
m->id = id;
m->priority = prio;
- m->pattern = vim_strsave(pat);
+ m->pattern = pat == NULL ? NULL: vim_strsave(pat);
m->hlg_id = hlg_id;
m->match.regprog = regprog;
m->match.rmm_ic = FALSE;
m->match.rmm_maxcol = 0;
+ // Set up position matches
+ if (pos_list != NULL)
+ {
+ linenr_T toplnum = 0;
+ linenr_T botlnum = 0;
+ listitem_T *li;
+ int i;
+
+ for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH;
+ i++, li = li->li_next) {
+ linenr_T lnum = 0;
+ colnr_T col = 0;
+ int len = 1;
+ list_T *subl;
+ listitem_T *subli;
+ int error = false;
+
+ if (li->li_tv.v_type == VAR_LIST) {
+ subl = li->li_tv.vval.v_list;
+ if (subl == NULL) {
+ goto fail;
+ }
+ subli = subl->lv_first;
+ if (subli == NULL) {
+ goto fail;
+ }
+ lnum = get_tv_number_chk(&subli->li_tv, &error);
+ if (error == true) {
+ goto fail;
+ }
+ if (lnum == 0) {
+ --i;
+ continue;
+ }
+ m->pos.pos[i].lnum = lnum;
+ subli = subli->li_next;
+ if (subli != NULL) {
+ col = get_tv_number_chk(&subli->li_tv, &error);
+ if (error == true)
+ goto fail;
+ subli = subli->li_next;
+ if (subli != NULL) {
+ len = get_tv_number_chk(&subli->li_tv, &error);
+ if (error == true) {
+ goto fail;
+ }
+ }
+ }
+ m->pos.pos[i].col = col;
+ m->pos.pos[i].len = len;
+ } else if (li->li_tv.v_type == VAR_NUMBER) {
+ if (li->li_tv.vval.v_number == 0) {
+ --i;
+ continue;
+ }
+ m->pos.pos[i].lnum = li->li_tv.vval.v_number;
+ m->pos.pos[i].col = 0;
+ m->pos.pos[i].len = 0;
+ } else {
+ EMSG(_("List or number required"));
+ goto fail;
+ }
+ if (toplnum == 0 || lnum < toplnum) {
+ toplnum = lnum;
+ }
+ if (botlnum == 0 || lnum >= botlnum) {
+ botlnum = lnum + 1;
+ }
+ }
+
+ // Calculate top and bottom lines for redrawing area
+ if (toplnum != 0){
+ if (wp->w_buffer->b_mod_set) {
+ if (wp->w_buffer->b_mod_top > toplnum) {
+ wp->w_buffer->b_mod_top = toplnum;
+ }
+ if (wp->w_buffer->b_mod_bot < botlnum) {
+ wp->w_buffer->b_mod_bot = botlnum;
+ }
+ } else {
+ wp->w_buffer->b_mod_set = TRUE;
+ wp->w_buffer->b_mod_top = toplnum;
+ wp->w_buffer->b_mod_bot = botlnum;
+ wp->w_buffer->b_mod_xlines = 0;
+ }
+ m->pos.toplnum = toplnum;
+ m->pos.botlnum = botlnum;
+ rtype = VALID;
+ }
+ }
+
/* Insert new match. The match list is in ascending order with regard to
* the match priorities. */
cur = wp->w_match_head;
@@ -5259,8 +5357,12 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
prev->next = m;
m->next = cur;
- redraw_later(SOME_VALID);
+ redraw_later(rtype);
return id;
+
+fail:
+ free(m);
+ return -1;
}
/*
@@ -5271,6 +5373,7 @@ int match_delete(win_T *wp, int id, int perr)
{
matchitem_T *cur = wp->w_match_head;
matchitem_T *prev = cur;
+ int rtype = SOME_VALID;
if (id < 1) {
if (perr == TRUE)
@@ -5294,8 +5397,24 @@ int match_delete(win_T *wp, int id, int perr)
prev->next = cur->next;
vim_regfree(cur->match.regprog);
free(cur->pattern);
+ if (cur->pos.toplnum != 0) {
+ if (wp->w_buffer->b_mod_set) {
+ if (wp->w_buffer->b_mod_top > cur->pos.toplnum) {
+ wp->w_buffer->b_mod_top = cur->pos.toplnum;
+ }
+ if (wp->w_buffer->b_mod_bot < cur->pos.botlnum) {
+ wp->w_buffer->b_mod_bot = cur->pos.botlnum;
+ }
+ } else {
+ wp->w_buffer->b_mod_set = TRUE;
+ wp->w_buffer->b_mod_top = cur->pos.toplnum;
+ wp->w_buffer->b_mod_bot = cur->pos.botlnum;
+ wp->w_buffer->b_mod_xlines = 0;
+ }
+ rtype = VALID;
+ }
free(cur);
- redraw_later(SOME_VALID);
+ redraw_later(rtype);
return 0;
}