diff options
author | Bram Moolenaar <Bram@vim.org> | 2014-06-17 17:48:32 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2014-06-17 17:48:32 +0200 |
commit | b3414595c713ca161f082776f89417faddec7d2d (patch) | |
tree | 5f03f600e04a2455ce84033c49db30b680d571c6 /src/window.c | |
parent | ec1561cac59006213dd5405d164a94dc7d002806 (diff) | |
download | vim-git-b3414595c713ca161f082776f89417faddec7d2d.tar.gz |
updated for version 7.4.330v7.4.330
Problem: Using a regexp pattern to highlight a specific position can be
slow.
Solution: Add matchaddpos() to highlight specific positions efficiently.
(Alexey Radkov)
Diffstat (limited to 'src/window.c')
-rw-r--r-- | src/window.c | 147 |
1 files changed, 135 insertions, 12 deletions
diff --git a/src/window.c b/src/window.c index 5215bb8e5..f76812a0e 100644 --- a/src/window.c +++ b/src/window.c @@ -6751,20 +6751,22 @@ win_hasvertsplit() * Return ID of added match, -1 on failure. */ int -match_add(wp, grp, pat, prio, id) +match_add(wp, grp, pat, prio, id, pos_list) 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; + 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) { @@ -6789,7 +6791,7 @@ match_add(wp, grp, pat, prio, 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; @@ -6810,12 +6812,111 @@ match_add(wp, grp, pat, prio, id) m = (matchitem_T *)alloc(sizeof(matchitem_T)); m->id = id; m->priority = prio; - m->pattern = vim_strsave(pat); + m->pattern = pat == NULL ? NULL : vim_strsave(pat); + m->pos.cur = 0; 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; 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; + + if (li == NULL) + { + m->pos.pos[i].lnum = 0; + break; + } + 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; + m->pos.pos[i].lnum = lnum; + if (lnum == 0) + { + --i; + continue; + } + 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) + 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; + } + + /* 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_top = toplnum; + wp->w_buffer->b_mod_bot = botlnum; + } + m->pos.toplnum = toplnum; + m->pos.botlnum = botlnum; + wp->w_buffer->b_mod_set = TRUE; + rtype = VALID; + } + } + /* Insert new match. The match list is in ascending order with regard to * the match priorities. */ cur = wp->w_match_head; @@ -6831,8 +6932,12 @@ match_add(wp, grp, pat, prio, id) prev->next = m; m->next = cur; - redraw_later(SOME_VALID); + redraw_later(rtype); return id; + +fail: + vim_free(m); + return -1; } /* @@ -6845,8 +6950,9 @@ match_delete(wp, id, perr) int id; int perr; { - matchitem_T *cur = wp->w_match_head; - matchitem_T *prev = cur; + matchitem_T *cur = wp->w_match_head; + matchitem_T *prev = cur; + int rtype = SOME_VALID; if (id < 1) { @@ -6872,8 +6978,25 @@ match_delete(wp, id, perr) prev->next = cur->next; vim_regfree(cur->match.regprog); vim_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_top = cur->pos.toplnum; + wp->w_buffer->b_mod_bot = cur->pos.botlnum; + } + wp->w_buffer->b_mod_set = TRUE; + rtype = VALID; + } vim_free(cur); - redraw_later(SOME_VALID); + redraw_later(rtype); return 0; } |