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

Raspunde prin e-mail lui