A new version: next_search_hl_pos() moved into next_search_hl().
A number of fixes added.
Docs were added too, here is an excerpt:
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} accepts sublists: positions like [23, 24] or
plain numbers like 34. In the first case the 24th character in
line 23 will be highlighted; in the second case the whole line
34 will be highlighted. 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)
Still no tests, will add them soon.
2014-05-31 17:06 GMT+04:00 Alexey Radkov <[email protected]>:
> Hi Bram.
>
> See my comments below.
>
>
> 2014-05-31 15:43 GMT+04:00 Bram Moolenaar <[email protected]>:
>
>
>> Alexey Radkov wrote:
>>
>> > This is a preliminary implementation of matchaddpos() that requires a
>> list
>> > of positions. See changes in matchparen.vim as example of using it. It
>> > works fine with the new matchparen. The implementation does not involve
>> > regexps and redraws only part of screen. Probably i missed something or
>> > something could be done simpler...
>> >
>> > The implementation extends struct matchitem_T adding 4 new elements:
>> > positions pos, current position index counter cur_pos and redrawing
>> > boundaries (top and bottom buffer lines which are calculated from pos).
>> If
>> > the idea of the patch is Ok then i will do some cleanup, docs etc.,
>> > implement suggestions and send changes.
>>
>> Thanks for doing this.
>>
>> Please also write the documentation for matchaddpos(), so we can discuss
>> how it could be used.
>>
>
> Ok.
>
>
>>
>> It's also good to add tests. Although it might be difficult to check
>> that the highlighting shows up in the right place. You should be able
>> to do this with screenattr().
>>
>
> Ok.
>
>
>>
>> I had a quick look at your changes, but it's not clear to me why you do
>> it the way you do. I would think next_search_hl() can work for both a
>> pattern and position, where a position would just use the one position
>> that is stores, instead of searching for a match. Thus just use one
>> list of matches, mixing both pattern matches and position matches.
>>
>
> Yes, you are right. By some reason i held in my head that next_search_hl()
> is only for regexps. Now i see that i can move next_search_hl_pos() into
> next_search_hl(). In this case it would look cleaner.
>
>
>>
>> > (Btw i do not understand difference between NUL and NULL, what should i
>> use
>> > and where?)
>>
>> NUL is an integer, used for a character, NULL is for a pointer.
>> NUL is defined by Vim, NULL is defined by C.
>>
>
> Ok, clear.
>
>
>>
>> --
>> hundred-and-one symptoms of being an internet addict:
>> 241. You try to look for Net Search even when you're in File Manager.
>>
>> /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net
>> \\\
>> /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/
>> \\\
>> \\\ an exciting new programming language -- http://www.Zimbu.org
>> ///
>> \\\ help me help AIDS victims -- http://ICCF-Holland.org
>> ///
>>
>
>
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff -r bed71c37618c runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Thu May 29 14:36:29 2014 +0200
+++ b/runtime/doc/eval.txt Sun Jun 01 20:54:56 2014 +0400
@@ -1887,6 +1887,8 @@
Number position where {pat} matches in {expr}
matchadd( {group}, {pattern}[, {priority}[, {id}]])
Number highlight {pattern} with {group}
+matchaddpos( {group}, {list}[, {priority}[, {id}]])
+ Number highlight {list} of positions with {group}
matcharg( {nr}) List arguments of |:match|
matchdelete( {id}) Number delete match identified by {id}
matchend( {expr}, {pat}[, {start}[, {count}]])
@@ -4348,6 +4350,25 @@
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} accepts sublists: positions like [23, 24] or
+ plain numbers like 34. In the first case the 24th character in
+ line 23 will be highlighted; in the second case the whole line
+ 34 will be highlighted. 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)
+
matcharg({nr}) *matcharg()*
Selects the {nr} match item, as set with a |:match|,
|:2match| or |:3match| command.
diff -r bed71c37618c runtime/doc/pattern.txt
--- a/runtime/doc/pattern.txt Thu May 29 14:36:29 2014 +0200
+++ b/runtime/doc/pattern.txt Sun Jun 01 20:54:56 2014 +0400
@@ -1332,7 +1332,7 @@
patterns defined by both |matchadd()| and |:match|.
Highlighting matches using |:match| are limited to three
- matches (aside from |:match|, |:2match| and |:3match|are
+ matches (aside from |:match|, |:2match| and |:3match| are
available). |matchadd()| does not have this limitation and in
addition makes it possible to prioritize matches.
diff -r bed71c37618c runtime/doc/usr_41.txt
--- a/runtime/doc/usr_41.txt Thu May 29 14:36:29 2014 +0200
+++ b/runtime/doc/usr_41.txt Sun Jun 01 20:54:56 2014 +0400
@@ -826,6 +826,7 @@
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
diff -r bed71c37618c runtime/plugin/matchparen.vim
--- a/runtime/plugin/matchparen.vim Thu May 29 14:36:29 2014 +0200
+++ b/runtime/plugin/matchparen.vim Sun Jun 01 20:54:56 2014 +0400
@@ -39,7 +39,7 @@
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,13 @@
" 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\)/'
+ call matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10, 3)
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
diff -r bed71c37618c src/eval.c
--- a/src/eval.c Thu May 29 14:36:29 2014 +0200
+++ b/src/eval.c Sun Jun 01 20:54:56 2014 +0400
@@ -619,6 +619,7 @@
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));
@@ -8039,6 +8040,7 @@
{"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},
@@ -14298,7 +14300,58 @@
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 *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */
+ char_u *pat = NULL; /* pattern */
+ int prio = 10; /* default priority */
+ int id = -1;
+ int error = FALSE;
+ list_T *l;
+ listitem_T *li;
+
+ rettv->vval.v_number = -1;
+
+ if (grp == 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, grp, NULL, prio, id, l);
#endif
}
@@ -16801,7 +16854,7 @@
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;
diff -r bed71c37618c src/ex_docmd.c
--- a/src/ex_docmd.c Thu May 29 14:36:29 2014 +0200
+++ b/src/ex_docmd.c Sun Jun 01 20:54:56 2014 +0400
@@ -11489,7 +11489,7 @@
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;
}
diff -r bed71c37618c src/proto/window.pro
--- a/src/proto/window.pro Thu May 29 14:36:29 2014 +0200
+++ b/src/proto/window.pro Sun Jun 01 20:54:56 2014 +0400
@@ -75,7 +75,7 @@
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));
diff -r bed71c37618c src/screen.c
--- a/src/screen.c Thu May 29 14:36:29 2014 +0200
+++ b/src/screen.c Sun Jun 01 20:54:56 2014 +0400
@@ -144,7 +144,8 @@
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 @@
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 @@
shl->startcol = MAXCOL;
shl->endcol = MAXCOL;
shl->attr_cur = 0;
- if (shl->rm.regprog != NULL)
- {
- 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;
+ 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)
+ {
+ 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
- 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
-#endif
- ++shl->endcol;
- }
- if ((long)shl->startcol < v) /* match at leftcol */
- {
- shl->attr_cur = shl->attr;
- search_attr = shl->attr;
- }
- area_highlighting = TRUE;
- }
+#endif
+ ++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 @@
* 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 @@
}
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 @@
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 @@
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 @@
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)
- {
- next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
+ while (shl->first_lnum < lnum && (shl->rm.regprog != NULL ||
+ (cur != NULL && pos_inprogress)))
+ {
+ 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 @@
* 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 @@
matchcol = shl->rm.endpos[0].col;
shl->lnum = lnum;
- nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
+ if (shl->rm.regprog != NULL)
+ {
+ nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
+ matchcol,
#ifdef FEAT_RELTIME
- &(shl->tm)
+ &(shl->tm)
#else
- NULL
-#endif
- );
- if (called_emsg || got_int)
- {
- /* 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;
+ NULL
+#endif
+ );
+ if (called_emsg || got_int)
+ {
+ /* 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;
+ }
+ }
+ else if (cur != NULL)
+ {
+ nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
}
if (nmatched == 0)
{
@@ -7453,6 +7478,59 @@
}
#endif
+ static int
+next_search_hl_pos(shl, lnum, pos, mincol)
+ match_T *shl; /* points to a match */
+ linenr_T lnum;
+ posmatch_T *pos; /* match positions */
+ colnr_T mincol; /* minimal column for a match */
+{
+ int i;
+ int bot = -1;
+
+ shl->lnum = 0;
+ for (i = pos->cur; i < MAXPOSMATCH; i++)
+ {
+ if (pos->m[i].lnum == 0)
+ break;
+ if (pos->m[i].col < mincol)
+ continue;
+ if (pos->m[i].lnum == lnum)
+ {
+ if (shl->lnum == lnum)
+ {
+ /* partially sort column numbers on the same line */
+ if (pos->m[i].col < pos->m[bot].col)
+ {
+ colnr_T tmp = pos->m[i].col;
+
+ pos->m[i].col = pos->m[bot].col;
+ pos->m[bot].col = tmp;
+ }
+ }
+ else
+ {
+ bot = i;
+ shl->lnum = lnum;
+ }
+ }
+ }
+ pos->cur = 0;
+ if (shl->lnum == lnum)
+ {
+ colnr_T start = pos->m[bot].col == 0 ? 0 : pos->m[bot].col - 1;
+ colnr_T end = pos->m[bot].col == 0 ? MAXCOL : pos->m[bot].col;
+
+ shl->rm.startpos[0].lnum = 0;
+ shl->rm.startpos[0].col = start;
+ shl->rm.endpos[0].lnum = 0;
+ shl->rm.endpos[0].col = end;
+ pos->cur = bot + 1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
screen_start_highlight(attr)
int attr;
diff -r bed71c37618c src/structs.h
--- a/src/structs.h Thu May 29 14:36:29 2014 +0200
+++ b/src/structs.h Sun Jun 01 20:54:56 2014 +0400
@@ -1927,6 +1927,21 @@
#endif
} match_T;
+#define MAXPOSMATCH 8
+
+/*
+ * posmatch_T provides an array for storing match items for matchaddpos()
+ * function.
+ */
+typedef struct posmatch posmatch_T;
+struct posmatch
+{
+ lpos_T m[MAXPOSMATCH]; /* array of positions */
+ int cur; /* internal position counter */
+ int topl; /* top buffer line */
+ int botl; /* bottom buffer line */
+};
+
/*
* matchitem_T provides a linked list for storing match items for ":match" and
* the match functions.
@@ -1940,6 +1955,7 @@
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 */
};
diff -r bed71c37618c src/window.c
--- a/src/window.c Thu May 29 14:36:29 2014 +0200
+++ b/src/window.c Sun Jun 01 20:54:56 2014 +0400
@@ -6729,20 +6729,22 @@
* Return ID of added match, -1 on failure.
*/
int
-match_add(wp, grp, pat, prio, id)
+match_add(wp, grp, pat, prio, id, pos)
win_T *wp;
char_u *grp;
char_u *pat;
int prio;
int id;
+ list_T *pos;
{
- matchitem_T *cur;
- matchitem_T *prev;
- matchitem_T *m;
+ matchitem_T *cur;
+ matchitem_T *prev;
+ matchitem_T *m;
int hlg_id;
- regprog_T *regprog;
-
- if (*grp == NUL || *pat == NUL)
+ regprog_T *regprog = NULL;
+ int rtype = SOME_VALID;
+
+ if (*grp == NUL || (pat != NULL && *pat == NUL))
return -1;
if (id < -1 || id == 0)
{
@@ -6767,7 +6769,7 @@
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;
@@ -6788,12 +6790,107 @@
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 != NULL)
+ {
+ int topl = 0;
+ int botl = 0;
+ listitem_T *li = pos->lv_first;
+ int i;
+
+ for (i = 0; i < MAXPOSMATCH; i++)
+ {
+ linenr_T lnum;
+ colnr_T col;
+ list_T *subl;
+ listitem_T *subli;
+ int error;
+
+ if (li == NULL)
+ {
+ m->pos.m[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;
+ if (lnum == 0)
+ {
+ li = li->li_next;
+ continue;
+ }
+ subli = subli->li_next;
+ if (subli == NULL)
+ {
+ col = 0;
+ }
+ else
+ {
+ col = get_tv_number_chk(&subli->li_tv, &error);
+ if (error == TRUE)
+ goto fail;
+ }
+ m->pos.m[i].lnum = lnum;
+ m->pos.m[i].col = col;
+ }
+ else if (li->li_tv.v_type == VAR_NUMBER)
+ {
+ if (li->li_tv.vval.v_number == 0)
+ {
+ li = li->li_next;
+ continue;
+ }
+ m->pos.m[i].lnum = li->li_tv.vval.v_number;
+ m->pos.m[i].col = 0;
+ }
+ else
+ {
+ EMSG(_("List or number required"));
+ goto fail;
+ }
+ if (topl == 0 || lnum < topl)
+ topl = lnum;
+ if (botl == 0 || lnum > botl)
+ botl = lnum;
+ li = li->li_next;
+ }
+ /* Calculate top and bottom lines for redrawing area */
+ if (topl != 0)
+ {
+ if (wp->w_buffer->b_mod_set)
+ {
+ if (wp->w_buffer->b_mod_top > topl)
+ wp->w_buffer->b_mod_top = topl;
+ if (wp->w_buffer->b_mod_bot < botl)
+ wp->w_buffer->b_mod_bot = botl;
+ }
+ else
+ {
+ wp->w_buffer->b_mod_top = topl;
+ wp->w_buffer->b_mod_bot = botl;
+ }
+ m->pos.topl = topl;
+ m->pos.botl = botl;
+ 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;
@@ -6809,8 +6906,12 @@
prev->next = m;
m->next = cur;
- redraw_later(SOME_VALID);
+ redraw_later(rtype);
return id;
+
+fail:
+ vim_free(m);
+ return -1;
}
/*
@@ -6823,8 +6924,9 @@
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)
{
@@ -6850,8 +6952,25 @@
prev->next = cur->next;
vim_regfree(cur->match.regprog);
vim_free(cur->pattern);
+ if (cur->pos.topl != 0)
+ {
+ if (wp->w_buffer->b_mod_set)
+ {
+ if (wp->w_buffer->b_mod_top > cur->pos.topl)
+ wp->w_buffer->b_mod_top = cur->pos.topl;
+ if (wp->w_buffer->b_mod_bot < cur->pos.botl)
+ wp->w_buffer->b_mod_bot = cur->pos.botl;
+ }
+ else
+ {
+ wp->w_buffer->b_mod_top = cur->pos.topl;
+ wp->w_buffer->b_mod_bot = cur->pos.botl;
+ }
+ wp->w_buffer->b_mod_set = TRUE;
+ rtype = VALID;
+ }
vim_free(cur);
- redraw_later(SOME_VALID);
+ redraw_later(rtype);
return 0;
}