diff options
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r-- | src/nvim/window.c | 207 |
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; } |