0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

updated for version 7.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)
This commit is contained in:
Bram Moolenaar
2014-06-17 17:48:32 +02:00
parent ec1561cac5
commit b3414595c7
12 changed files with 465 additions and 88 deletions

View File

@@ -1887,6 +1887,8 @@ match( {expr}, {pat}[, {start}[, {count}]])
Number position where {pat} matches in {expr}
matchadd( {group}, {pattern}[, {priority}[, {id}]])
Number highlight {pattern} with {group}
matchaddpos( {group}, {list}[, {priority}[, {id}]])
Number highlight positions with {group}
matcharg( {nr}) List arguments of |:match|
matchdelete( {id}) Number delete match identified by {id}
matchend( {expr}, {pat}[, {start}[, {count}]])
@@ -4380,6 +4382,41 @@ matchadd({group}, {pattern}[, {priority}[, {id}]])
available from |getmatches()|. All matches can be deleted in
one operation by |clearmatches()|.
matchaddpos({group}, {pos}[, {priority}[, {id}]]) *matchaddpos()*
Same as |matchadd()|, but requires a list of positions {pos}
instead of a pattern. This command is faster than |matchadd()|
because it does not require to handle regular expressions and
sets buffer line boundaries to redraw screen. It is supposed
to be used when fast match additions and deletions are
required, for example to highlight matching parentheses.
The list {pos} can contain one of these items:
- A number. This while line will be highlighted. The first
line has number 1.
- A list with one number, e.g., [23]. The whole line with this
number will be highlighted.
- A list with two numbers, e.g., [23, 11]. The first number is
the line number, the second one the column number (first
column is 1). The character at this position will be
highlighted.
- A list with three numbers, e.g., [23, 11, 3]. As above, but
the third number gives the length of the highlight in screen
cells.
The maximum number of positions is 8.
Example: >
:highlight MyGroup ctermbg=green guibg=green
:let m = matchaddpos("MyGroup", [[23, 24], 34])
< Deletion of the pattern: >
:call matchdelete(m)
< Matches added by |matchaddpos()| are returned by
|getmatches()| with an entry "pos1", "pos2", etc., with the
value a list like the {pos} item.
These matches cannot be set via |setmatches()|, however they
can still be deleted by |clearmatches()|.
matcharg({nr}) *matcharg()*
Selects the {nr} match item, as set with a |:match|,
|:2match| or |:3match| command.

View File

@@ -827,6 +827,7 @@ Syntax and highlighting: *syntax-functions* *highlighting-functions*
synconcealed() get info about concealing
diff_hlID() get highlight ID for diff mode at a position
matchadd() define a pattern to highlight (a "match")
matchaddpos() define a list of positions to highlight
matcharg() get info about |:match| arguments
matchdelete() delete a match defined by |matchadd()| or a
|:match| command

View File

@@ -1,6 +1,6 @@
" Vim plugin for showing matching parens
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2013 May 08
" Last Change: 2014 Jun 17
" Exit quickly when:
" - this plugin was already loaded (or disabled)
@@ -39,7 +39,7 @@ set cpo-=C
function! s:Highlight_Matching_Pair()
" Remove any previous match.
if exists('w:paren_hl_on') && w:paren_hl_on
3match none
silent! call matchdelete(3)
let w:paren_hl_on = 0
endif
@@ -152,14 +152,18 @@ function! s:Highlight_Matching_Pair()
" If a match is found setup match highlighting.
if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom
exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) .
\ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
if exists('*matchaddpos')
call matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10, 3)
else
exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) .
\ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
endif
let w:paren_hl_on = 1
endif
endfunction
" Define commands that will disable and enable the plugin.
command! NoMatchParen windo 3match none | unlet! g:loaded_matchparen |
command! NoMatchParen windo silent! call matchdelete(3) | unlet! g:loaded_matchparen |
\ au! matchparen
command! DoMatchParen runtime plugin/matchparen.vim | windo doau CursorMoved

View File

@@ -622,6 +622,7 @@ static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matchaddpos __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv));
static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8054,6 +8055,7 @@ static struct fst
{"mapcheck", 1, 3, f_mapcheck},
{"match", 2, 4, f_match},
{"matchadd", 2, 4, f_matchadd},
{"matchaddpos", 2, 4, f_matchaddpos},
{"matcharg", 1, 1, f_matcharg},
{"matchdelete", 1, 1, f_matchdelete},
{"matchend", 2, 4, f_matchend},
@@ -11767,6 +11769,7 @@ f_getmatches(argvars, rettv)
#ifdef FEAT_SEARCH_EXTRA
dict_T *dict;
matchitem_T *cur = curwin->w_match_head;
int i;
if (rettv_list_alloc(rettv) == OK)
{
@@ -11775,8 +11778,36 @@ f_getmatches(argvars, rettv)
dict = dict_alloc();
if (dict == NULL)
return;
if (cur->match.regprog == NULL)
{
/* match added with matchaddpos() */
for (i = 0; i < MAXPOSMATCH; ++i)
{
llpos_T *llpos;
char buf[6];
list_T *l;
llpos = &cur->pos.pos[i];
if (llpos->lnum == 0)
break;
l = list_alloc();
if (l == NULL)
break;
list_append_number(l, (varnumber_T)llpos->lnum);
if (llpos->col > 0)
{
list_append_number(l, (varnumber_T)llpos->col);
list_append_number(l, (varnumber_T)llpos->len);
}
sprintf(buf, "pos%d", i + 1);
dict_add_list(dict, buf, l);
}
}
else
{
dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
}
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
dict_add_nr_str(dict, "id", (long)cur->id, NULL);
list_append_dict(rettv->vval.v_list, dict);
@@ -14313,7 +14344,58 @@ f_matchadd(argvars, rettv)
return;
}
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
#endif
}
/*
* "matchaddpos()" function
*/
static void
f_matchaddpos(argvars, rettv)
typval_T *argvars UNUSED;
typval_T *rettv UNUSED;
{
#ifdef FEAT_SEARCH_EXTRA
char_u buf[NUMBUFLEN];
char_u *group;
int prio = 10;
int id = -1;
int error = FALSE;
list_T *l;
rettv->vval.v_number = -1;
group = get_tv_string_buf_chk(&argvars[0], buf);
if (group == NULL)
return;
if (argvars[1].v_type != VAR_LIST)
{
EMSG2(_(e_listarg), "matchaddpos()");
return;
}
l = argvars[1].vval.v_list;
if (l == NULL)
return;
if (argvars[2].v_type != VAR_UNKNOWN)
{
prio = get_tv_number_chk(&argvars[2], &error);
if (argvars[3].v_type != VAR_UNKNOWN)
id = get_tv_number_chk(&argvars[3], &error);
}
if (error == TRUE)
return;
/* id == 3 is ok because matchaddpos() is supposed to substitute :3match */
if (id == 1 || id == 2)
{
EMSGN("E798: ID is reserved for \":match\": %ld", id);
return;
}
rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
#endif
}
@@ -16816,7 +16898,7 @@ f_setmatches(argvars, rettv)
match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
get_dict_string(d, (char_u *)"pattern", FALSE),
(int)get_dict_number(d, (char_u *)"priority"),
(int)get_dict_number(d, (char_u *)"id"));
(int)get_dict_number(d, (char_u *)"id"), NULL);
li = li->li_next;
}
rettv->vval.v_number = 0;

View File

@@ -11489,7 +11489,7 @@ ex_match(eap)
c = *end;
*end = NUL;
match_add(curwin, g, p + 1, 10, id);
match_add(curwin, g, p + 1, 10, id, NULL);
vim_free(g);
*end = c;
}

View File

@@ -75,7 +75,7 @@ void restore_win __ARGS((win_T *save_curwin, tabpage_T *save_curtab, int no_disp
void switch_buffer __ARGS((buf_T **save_curbuf, buf_T *buf));
void restore_buffer __ARGS((buf_T *save_curbuf));
int win_hasvertsplit __ARGS((void));
int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos));
int match_delete __ARGS((win_T *wp, int id, int perr));
void clear_matches __ARGS((win_T *wp));
matchitem_T *get_match __ARGS((win_T *wp, int id));

View File

@@ -144,7 +144,8 @@ static void start_search_hl __ARGS((void));
static void end_search_hl __ARGS((void));
static void init_search_hl __ARGS((win_T *wp));
static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol));
static void next_search_hl __ARGS((win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol, matchitem_T *cur));
static int next_search_hl_pos __ARGS((match_T *shl, linenr_T lnum, posmatch_T *pos, colnr_T mincol));
#endif
static void screen_start_highlight __ARGS((int attr));
static void screen_char __ARGS((unsigned off, int row, int col));
@@ -2929,6 +2930,8 @@ win_line(wp, lnum, startrow, endrow, nochange)
match_T *shl; /* points to search_hl or a match */
int shl_flag; /* flag to indicate whether search_hl
has been processed or not */
int pos_inprogress; /* marks that position match search is
in progress */
int prevcol_hl_flag; /* flag to indicate whether prevcol
equals startcol of search_hl or one
of the matches */
@@ -3439,44 +3442,43 @@ win_line(wp, lnum, startrow, endrow, nochange)
shl->startcol = MAXCOL;
shl->endcol = MAXCOL;
shl->attr_cur = 0;
if (shl->rm.regprog != NULL)
v = (long)(ptr - line);
if (cur != NULL)
cur->pos.cur = 0;
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
/* Need to get the line again, a multi-line regexp may have made it
* invalid. */
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
ptr = line + v;
if (shl->lnum != 0 && shl->lnum <= lnum)
{
v = (long)(ptr - line);
next_search_hl(wp, shl, lnum, (colnr_T)v);
/* Need to get the line again, a multi-line regexp may have made it
* invalid. */
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
ptr = line + v;
if (shl->lnum != 0 && shl->lnum <= lnum)
if (shl->lnum == lnum)
shl->startcol = shl->rm.startpos[0].col;
else
shl->startcol = 0;
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
- shl->rm.startpos[0].lnum)
shl->endcol = shl->rm.endpos[0].col;
else
shl->endcol = MAXCOL;
/* Highlight one character for an empty match. */
if (shl->startcol == shl->endcol)
{
if (shl->lnum == lnum)
shl->startcol = shl->rm.startpos[0].col;
else
shl->startcol = 0;
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
- shl->rm.startpos[0].lnum)
shl->endcol = shl->rm.endpos[0].col;
else
shl->endcol = MAXCOL;
/* Highlight one character for an empty match. */
if (shl->startcol == shl->endcol)
{
#ifdef FEAT_MBYTE
if (has_mbyte && line[shl->endcol] != NUL)
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
else
if (has_mbyte && line[shl->endcol] != NUL)
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
else
#endif
++shl->endcol;
}
if ((long)shl->startcol < v) /* match at leftcol */
{
shl->attr_cur = shl->attr;
search_attr = shl->attr;
}
area_highlighting = TRUE;
++shl->endcol;
}
if ((long)shl->startcol < v) /* match at leftcol */
{
shl->attr_cur = shl->attr;
search_attr = shl->attr;
}
area_highlighting = TRUE;
}
if (shl != &search_hl && cur != NULL)
cur = cur->next;
@@ -3488,7 +3490,7 @@ win_line(wp, lnum, startrow, endrow, nochange)
* when Visual mode is active, because it's not clear what is selected
* then. */
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
&& !(wp == curwin && VIsual_active))
&& !(wp == curwin && VIsual_active))
{
line_attr = hl_attr(HLF_CUL);
area_highlighting = TRUE;
@@ -3792,7 +3794,11 @@ win_line(wp, lnum, startrow, endrow, nochange)
}
else
shl = &cur->hl;
while (shl->rm.regprog != NULL)
if (cur != NULL)
cur->pos.cur = 0;
pos_inprogress = TRUE;
while (shl->rm.regprog != NULL
|| (cur != NULL && pos_inprogress))
{
if (shl->startcol != MAXCOL
&& v >= (long)shl->startcol
@@ -3803,8 +3809,9 @@ win_line(wp, lnum, startrow, endrow, nochange)
else if (v == (long)shl->endcol)
{
shl->attr_cur = 0;
next_search_hl(wp, shl, lnum, (colnr_T)v);
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
pos_inprogress = cur == NULL || cur->pos.cur == 0
? FALSE : TRUE;
/* Need to get the line again, a multi-line regexp
* may have made it invalid. */
@@ -7277,6 +7284,8 @@ prepare_search_hl(wp, lnum)
match_T *shl; /* points to search_hl or a match */
int shl_flag; /* flag to indicate whether search_hl
has been processed or not */
int pos_inprogress; /* marks that position match search is
in progress */
int n;
/*
@@ -7311,10 +7320,16 @@ prepare_search_hl(wp, lnum)
shl->first_lnum = wp->w_topline;
# endif
}
if (cur != NULL)
cur->pos.cur = 0;
pos_inprogress = TRUE;
n = 0;
while (shl->first_lnum < lnum && shl->rm.regprog != NULL)
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
|| (cur != NULL && pos_inprogress)))
{
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur);
pos_inprogress = cur == NULL || cur->pos.cur == 0
? FALSE : TRUE;
if (shl->lnum != 0)
{
shl->first_lnum = shl->lnum
@@ -7343,11 +7358,12 @@ prepare_search_hl(wp, lnum)
* Careful: Any pointers for buffer lines will become invalid.
*/
static void
next_search_hl(win, shl, lnum, mincol)
win_T *win;
match_T *shl; /* points to search_hl or a match */
linenr_T lnum;
colnr_T mincol; /* minimal column for a match */
next_search_hl(win, shl, lnum, mincol, cur)
win_T *win;
match_T *shl; /* points to search_hl or a match */
linenr_T lnum;
colnr_T mincol; /* minimal column for a match */
matchitem_T *cur; /* to retrieve match postions if any */
{
linenr_T l;
colnr_T matchcol;
@@ -7415,26 +7431,35 @@ next_search_hl(win, shl, lnum, mincol)
matchcol = shl->rm.endpos[0].col;
shl->lnum = lnum;
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
#ifdef FEAT_RELTIME
&(shl->tm)
#else
NULL
#endif
);
if (called_emsg || got_int)
if (shl->rm.regprog != NULL)
{
/* Error while handling regexp: stop using this regexp. */
if (shl == &search_hl)
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
matchcol,
#ifdef FEAT_RELTIME
&(shl->tm)
#else
NULL
#endif
);
if (called_emsg || got_int)
{
/* don't free regprog in the match list, it's a copy */
vim_regfree(shl->rm.regprog);
SET_NO_HLSEARCH(TRUE);
/* Error while handling regexp: stop using this regexp. */
if (shl == &search_hl)
{
/* don't free regprog in the match list, it's a copy */
vim_regfree(shl->rm.regprog);
SET_NO_HLSEARCH(TRUE);
}
shl->rm.regprog = NULL;
shl->lnum = 0;
got_int = FALSE; /* avoid the "Type :quit to exit Vim"
message */
break;
}
shl->rm.regprog = NULL;
shl->lnum = 0;
got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */
break;
}
else if (cur != NULL)
{
nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
}
if (nmatched == 0)
{
@@ -7453,6 +7478,62 @@ next_search_hl(win, shl, lnum, mincol)
}
#endif
static int
next_search_hl_pos(shl, lnum, posmatch, mincol)
match_T *shl; /* points to a match */
linenr_T lnum;
posmatch_T *posmatch; /* match positions */
colnr_T mincol; /* minimal column for a match */
{
int i;
int bot = -1;
shl->lnum = 0;
for (i = posmatch->cur; i < MAXPOSMATCH; i++)
{
if (posmatch->pos[i].lnum == 0)
break;
if (posmatch->pos[i].col < mincol)
continue;
if (posmatch->pos[i].lnum == lnum)
{
if (shl->lnum == lnum)
{
/* partially sort positions by column numbers
* on the same line */
if (posmatch->pos[i].col < posmatch->pos[bot].col)
{
llpos_T tmp = posmatch->pos[i];
posmatch->pos[i] = posmatch->pos[bot];
posmatch->pos[bot] = tmp;
}
}
else
{
bot = i;
shl->lnum = lnum;
}
}
}
posmatch->cur = 0;
if (shl->lnum == lnum)
{
colnr_T start = posmatch->pos[bot].col == 0
? 0 : posmatch->pos[bot].col - 1;
colnr_T end = posmatch->pos[bot].col == 0
? MAXCOL : start + posmatch->pos[bot].len;
shl->rm.startpos[0].lnum = 0;
shl->rm.startpos[0].col = start;
shl->rm.endpos[0].lnum = 0;
shl->rm.endpos[0].col = end;
posmatch->cur = bot + 1;
return TRUE;
}
return FALSE;
}
static void
screen_start_highlight(attr)
int attr;

View File

@@ -1927,6 +1927,32 @@ typedef struct
#endif
} match_T;
/* number of positions supported by matchaddpos() */
#define MAXPOSMATCH 8
/*
* Same as lpos_T, but with additional field len.
*/
typedef struct
{
linenr_T lnum; /* line number */
colnr_T col; /* column number */
int len; /* length: 0 - to the end of line */
} llpos_T;
/*
* posmatch_T provides an array for storing match items for matchaddpos()
* function.
*/
typedef struct posmatch posmatch_T;
struct posmatch
{
llpos_T pos[MAXPOSMATCH]; /* array of positions */
int cur; /* internal position counter */
linenr_T toplnum; /* top buffer line */
linenr_T botlnum; /* bottom buffer line */
};
/*
* matchitem_T provides a linked list for storing match items for ":match" and
* the match functions.
@@ -1940,6 +1966,7 @@ struct matchitem
char_u *pattern; /* pattern to highlight */
int hlg_id; /* highlight group ID */
regmmatch_T match; /* regexp program for pattern */
posmatch_T pos; /* position matches */
match_T hl; /* struct for doing the actual highlighting */
};

View File

@@ -1,5 +1,5 @@
Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
"matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
"matchadd()", "matchaddpos", "matcharg()", "matchdelete()", and "setmatches()".
STARTTEST
:so small.vim
@@ -147,9 +147,26 @@ STARTTEST
:unlet rf1
:unlet rf2
:unlet rf3
:highlight clear MyGroup1
:highlight clear MyGroup2
:highlight clear MyGroup3
:" --- Check that "matchaddpos()" positions matches correctly
:let @r .= "*** Test 11:\n"
:set nolazyredraw
:call setline(1, 'abcdefghijklmnopq')
:call matchaddpos("MyGroup1", [[1, 5], [1, 8, 3]], 10, 3)
:1
:redraw!
:let v1 = screenattr(1, 1)
:let v5 = screenattr(1, 5)
:let v6 = screenattr(1, 6)
:let v8 = screenattr(1, 8)
:let v10 = screenattr(1, 10)
:let v11 = screenattr(1, 11)
:let @r .= string(getmatches())."\n"
:if v1 != v5 && v6 == v1 && v8 == v5 && v10 == v5 && v11 == v1
: let @r .= "OK\n"
:else
: let @r .= "FAILED\n"
:endif
:call clearmatches()
G"rp
:/^Results/,$wq! test.out
ENDTEST

View File

@@ -9,3 +9,6 @@ Results of test63:
*** Test 8: OK
*** Test 9: OK
*** Test 10: OK
*** Test 11:
[{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}]
OK

View File

@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
330,
/**/
329,
/**/

View File

@@ -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;
}