]> git.pld-linux.org Git - packages/vim.git/blob - 7.1.040
- updated to 7.1.100
[packages/vim.git] / 7.1.040
1 To: vim-dev@vim.org
2 Subject: patch 7.1.040
3 Fcc: outbox
4 From: Bram Moolenaar <Bram@moolenaar.net>
5 Mime-Version: 1.0
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
8 ------------
9
10 Patch 7.1.040
11 Problem:    ":match" only supports three matches.
12 Solution:   Add functions clearmatches(), getmatches(), matchadd(),
13             matchdelete() and setmatches().  Changed the data structures for
14             this.  A small bug in syntax.c is fixed, so newly created
15             highlight groups can have their name resolved correctly from their
16             ID.  (Martin Toft)
17 Files:      runtime/doc/eval.txt, runtime/doc/pattern.txt,
18             runtime/doc/usr_41.txt, src/eval.c, src/ex_docmd.c,
19             src/proto/window.pro, src/screen.c, src/structs.h, src/syntax.c,
20             src/testdir/Makefile, src/testdir/test63.in,
21             src/testdir/test63.ok, src/window.c
22
23
24 *** ../vim-7.1.039/runtime/doc/eval.txt Tue Jul 17 16:31:15 2007
25 --- runtime/doc/eval.txt        Wed Jul 25 21:05:56 2007
26 ***************
27 *** 1,4 ****
28 ! *eval.txt*      For Vim version 7.1.  Last change: 2007 Jul 11
29   
30   
31                   VIM REFERENCE MANUAL    by Bram Moolenaar
32 --- 1,4 ----
33 ! *eval.txt*      For Vim version 7.1.  Last change: 2007 Jul 25
34   
35   
36                   VIM REFERENCE MANUAL    by Bram Moolenaar
37 ***************
38 *** 1557,1562 ****
39 --- 1557,1563 ----
40   changenr()                    Number  current change number
41   char2nr( {expr})              Number  ASCII value of first char in {expr}
42   cindent( {lnum})              Number  C indent for line {lnum}
43 + clearmatches()                        None    clear all matches
44   col( {expr})                  Number  column nr of cursor or mark
45   complete({startcol}, {matches})       String  set Insert mode completion
46   complete_add( {expr})         Number  add completion match
47 ***************
48 *** 1622,1627 ****
49 --- 1623,1629 ----
50   getline( {lnum})              String  line {lnum} of current buffer
51   getline( {lnum}, {end})               List    lines {lnum} to {end} of current buffer
52   getloclist({nr})              List    list of location list items
53 + getmatches()                  List    list of current matches
54   getpos( {expr})                       List    position of cursor, mark, etc.
55   getqflist()                   List    list of quickfix items
56   getreg( [{regname} [, 1]])    String  contents of register
57 ***************
58 *** 1676,1682 ****
59 --- 1678,1687 ----
60                                 String  check for mappings matching {name}
61   match( {expr}, {pat}[, {start}[, {count}]])
62                                 Number  position where {pat} matches in {expr}
63 + matchadd( {group}, {pattern}[, {priority}[, {id}]])
64 +                               Number  highlight {pattern} with {group}
65   matcharg( {nr})                       List    arguments of |:match|
66 + matchdelete( {id})            Number  delete match identified by {id}
67   matchend( {expr}, {pat}[, {start}[, {count}]])
68                                 Number  position where {pat} ends in {expr}
69   matchlist( {expr}, {pat}[, {start}[, {count}]])
70 ***************
71 *** 1731,1736 ****
72 --- 1736,1742 ----
73   setline( {lnum}, {line})      Number  set line {lnum} to {line}
74   setloclist( {nr}, {list}[, {action}])
75                                 Number  modify location list using {list}
76 + setmatches( {list})           Number  restore a list of matches
77   setpos( {expr}, {list})               none    set the {expr} position to {list}
78   setqflist( {list}[, {action}])        Number  modify quickfix list using {list}
79   setreg( {n}, {v}[, {opt}])    Number  set register to value and type
80 ***************
81 *** 2012,2017 ****
82 --- 2018,2027 ----
83                 feature, -1 is returned.
84                 See |C-indenting|.
85   
86 + clearmatches()                                                *clearmatches()*
87 +               Clears all matches previously defined by |matchadd()| and the
88 +               |:match| commands.
89
90                                                         *col()*
91   col({expr})   The result is a Number, which is the byte index of the column
92                 position given with {expr}.  The accepted positions are:
93 ***************
94 *** 2918,2923 ****
95 --- 2928,2955 ----
96                 returned.  For an invalid window number {nr}, an empty list is
97                 returned. Otherwise, same as getqflist().
98   
99 + getmatches()                                          *getmatches()*
100 +               Returns a |List| with all matches previously defined by
101 +               |matchadd()| and the |:match| commands.  |getmatches()| is
102 +               useful in combination with |setmatches()|, as |setmatches()|
103 +               can restore a list of matches saved by |getmatches()|.
104 +               Example: >
105 +                       :echo getmatches()
106 + <                     [{'group': 'MyGroup1', 'pattern': 'TODO',
107 +                       'priority': 10, 'id': 1}, {'group': 'MyGroup2',
108 +                       'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
109 +                       :let m = getmatches()
110 +                       :call clearmatches()
111 +                       :echo getmatches()
112 + <                     [] >
113 +                       :call setmatches(m)
114 +                       :echo getmatches()
115 + <                     [{'group': 'MyGroup1', 'pattern': 'TODO',
116 +                       'priority': 10, 'id': 1}, {'group': 'MyGroup2',
117 +                       'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
118 +                       :unlet m
119 + <
120
121   getqflist()                                           *getqflist()*
122                 Returns a list with all the current quickfix errors.  Each
123                 list item is a dictionary with these entries:
124 ***************
125 *** 3622,3627 ****
126 --- 3654,3697 ----
127                 the pattern.  'smartcase' is NOT used.  The matching is always
128                 done like 'magic' is set and 'cpoptions' is empty.
129   
130 +                                       *matchadd()* *E798* *E799* *E801*
131 + matchadd({group}, {pattern}[, {priority}[, {id}]])
132 +               Defines a pattern to be highlighted in the current window (a
133 +               "match").  It will be highlighted with {group}.  Returns an
134 +               identification number (ID), which can be used to delete the
135 +               match using |matchdelete()|.
136
137 +               The optional {priority} argument assigns a priority to the
138 +               match.  A match with a high priority will have its
139 +               highlighting overrule that of a match with a lower priority.
140 +               A priority is specified as an integer (negative numbers are no
141 +               exception).  If the {priority} argument is not specified, the
142 +               default priority is 10.  The priority of 'hlsearch' is zero,
143 +               hence all matches with a priority greater than zero will
144 +               overrule it.  Syntax highlighting (see 'syntax') is a separate
145 +               mechanism, and regardless of the chosen priority a match will
146 +               always overrule syntax highlighting.
147
148 +               The optional {id} argument allows the request for a specific
149 +               match ID.  If a specified ID is already taken, an error
150 +               message will appear and the match will not be added.  An ID
151 +               is specified as a positive integer (zero excluded).  IDs 1, 2
152 +               and 3 are reserved for |:match|, |:2match| and |:3match|,
153 +               respectively.  If the {id} argument is not specified,
154 +               |matchadd()| automatically chooses a free ID.
155
156 +               The number of matches is not limited, as it is the case with
157 +               the |:match| commands.
158
159 +               Example: >
160 +                       :highlight MyGroup ctermbg=green guibg=green
161 +                       :let m = matchadd("MyGroup", "TODO")
162 + <             Deletion of the pattern: >
163 +                       :call matchdelete(m)
164
165 + <             A list of matches defined by |matchadd()| and |:match| are
166 +               available from |getmatches()|.  All matches can be deleted in
167 +               one operation by |clearmatches()|.
168   
169   matcharg({nr})                                                        *matcharg()*
170                 Selects the {nr} match item, as set with a |:match|,
171 ***************
172 *** 3631,3638 ****
173                         The pattern used.
174                 When {nr} is not 1, 2 or 3 returns an empty |List|.
175                 When there is no match item set returns ['', ''].
176 !               This is usef to save and restore a |:match|.
177
178   
179   matchend({expr}, {pat}[, {start}[, {count}]])                 *matchend()*
180                 Same as match(), but return the index of first character after
181 --- 3701,3715 ----
182                         The pattern used.
183                 When {nr} is not 1, 2 or 3 returns an empty |List|.
184                 When there is no match item set returns ['', ''].
185 !               This is useful to save and restore a |:match|.
186 !               Highlighting matches using the |:match| commands are limited
187 !               to three matches. |matchadd()| does not have this limitation.
188
189 ! matchdelete({id})                            *matchdelete()* *E802* *E803*
190 !               Deletes a match with ID {id} previously defined by |matchadd()|
191 !               or one of the |:match| commands.  Returns 0 if succesfull,
192 !               otherwise -1.  See example for |matchadd()|.  All matches can
193 !               be deleted in one operation by |clearmatches()|.
194   
195   matchend({expr}, {pat}[, {start}[, {count}]])                 *matchend()*
196                 Same as match(), but return the index of first character after
197 ***************
198 *** 4385,4391 ****
199                 When {nr} is zero the current window is used. For a location
200                 list window, the displayed location list is modified.  For an
201                 invalid window number {nr}, -1 is returned.
202 !               Otherwise, same as setqflist().
203   
204                                                         *setpos()*
205   setpos({expr}, {list})
206 --- 4462,4474 ----
207                 When {nr} is zero the current window is used. For a location
208                 list window, the displayed location list is modified.  For an
209                 invalid window number {nr}, -1 is returned.
210 !               Otherwise, same as |setqflist()|.
211 !               Also see |location-list|.
212
213 ! setmatches({list})                                    *setmatches()*
214 !               Restores a list of matches saved by |getmatches()|.  Returns 0
215 !               if succesfull, otherwise -1.  All current matches are cleared
216 !               before the list is restored.  See example for |getmatches()|.
217   
218                                                         *setpos()*
219   setpos({expr}, {list})
220 *** ../vim-7.1.039/runtime/doc/pattern.txt      Sat May 12 16:57:31 2007
221 --- runtime/doc/pattern.txt     Tue Jul 24 15:47:01 2007
222 ***************
223 *** 1212,1218 ****
224                 {group} must exist at the moment this command is executed.
225   
226                 The {group} highlighting still applies when a character is
227 !               to be highlighted for 'hlsearch'.
228   
229                 Note that highlighting the last used search pattern with
230                 'hlsearch' is used in all windows, while the pattern defined
231 --- 1212,1221 ----
232                 {group} must exist at the moment this command is executed.
233   
234                 The {group} highlighting still applies when a character is
235 !               to be highlighted for 'hlsearch', as the highlighting for
236 !               matches is given higher priority than that of 'hlsearch'.
237 !               Syntax highlighting (see 'syntax') is also overruled by
238 !               matches.
239   
240                 Note that highlighting the last used search pattern with
241                 'hlsearch' is used in all windows, while the pattern defined
242 ***************
243 *** 1226,1233 ****
244                 display you may get unexpected results.  That is because Vim
245                 looks for a match in the line where redrawing starts.
246   
247 !               Also see |matcharg()|, it returns the highlight group and
248 !               pattern of a previous :match command.
249   
250                 Another example, which highlights all characters in virtual
251                 column 72 and more: >
252 --- 1229,1243 ----
253                 display you may get unexpected results.  That is because Vim
254                 looks for a match in the line where redrawing starts.
255   
256 !               Also see |matcharg()|and |getmatches()|. The former returns
257 !               the highlight group and pattern of a previous |:match|
258 !               command.  The latter returns a list with highlight groups and
259 !               patterns defined by both |matchadd()| and |:match|.
260
261 !               Highlighting matches using |:match| are limited to three
262 !               matches (aside from |:match|, |:2match| and |:3match|are
263 !               available). |matchadd()| does not have this limitation and in
264 !               addition makes it possible to prioritize matches.
265   
266                 Another example, which highlights all characters in virtual
267                 column 72 and more: >
268 *** ../vim-7.1.039/runtime/doc/usr_41.txt       Sat May 12 15:54:55 2007
269 --- runtime/doc/usr_41.txt      Tue Jul 24 15:47:01 2007
270 ***************
271 *** 763,775 ****
272 --- 763,784 ----
273         foldtextresult()        get the text displayed for a closed fold
274   
275   Syntax and highlighting:
276 +       clearmatches()          clear all matches defined by |matchadd()| and
277 +                               the |:match| commands
278 +       getmatches()            get all matches defined by |matchadd()| and
279 +                               the |:match| commands
280         hlexists()              check if a highlight group exists
281         hlID()                  get ID of a highlight group
282         synID()                 get syntax ID at a specific position
283         synIDattr()             get a specific attribute of a syntax ID
284         synIDtrans()            get translated syntax ID
285         diff_hlID()             get highlight ID for diff mode at a position
286 +       matchadd()              define a pattern to highlight (a "match")
287         matcharg()              get info about |:match| arguments
288 +       matchdelete()           delete a match defined by |matchadd()| or a
289 +                               |:match| command
290 +       setmatches()            restore a list of matches saved by
291 +                               |getmatches()|
292   
293   Spelling:
294         spellbadword()          locate badly spelled word at or after cursor
295 *** ../vim-7.1.039/src/eval.c   Tue Jul 24 14:32:44 2007
296 --- src/eval.c  Tue Jul 24 20:40:52 2007
297 ***************
298 *** 475,480 ****
299 --- 475,481 ----
300   static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
301   static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
302   static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
303 + static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv));
304   static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
305   #if defined(FEAT_INS_EXPAND)
306   static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));
307 ***************
308 *** 529,534 ****
309 --- 530,536 ----
310   static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
311   static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
312   static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
313 + static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv));
314   static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv));
315   static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
316   static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
317 ***************
318 *** 577,583 ****
319 --- 579,587 ----
320   static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
321   static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
322   static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
323 + static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
324   static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
325 + static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv));
326   static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
327   static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
328   static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
329 ***************
330 *** 618,623 ****
331 --- 622,628 ----
332   static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
333   static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
334   static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
335 + static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv));
336   static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
337   static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
338   static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
339 ***************
340 *** 7046,7051 ****
341 --- 7051,7057 ----
342       {"changenr",      0, 0, f_changenr},
343       {"char2nr",               1, 1, f_char2nr},
344       {"cindent",               1, 1, f_cindent},
345 +     {"clearmatches",  0, 0, f_clearmatches},
346       {"col",           1, 1, f_col},
347   #if defined(FEAT_INS_EXPAND)
348       {"complete",      2, 2, f_complete},
349 ***************
350 *** 7102,7107 ****
351 --- 7108,7114 ----
352       {"getftype",      1, 1, f_getftype},
353       {"getline",               1, 2, f_getline},
354       {"getloclist",    1, 1, f_getqflist},
355 +     {"getmatches",    0, 0, f_getmatches},
356       {"getpos",                1, 1, f_getpos},
357       {"getqflist",     0, 0, f_getqflist},
358       {"getreg",                0, 2, f_getreg},
359 ***************
360 *** 7152,7158 ****
361 --- 7159,7167 ----
362       {"maparg",                1, 3, f_maparg},
363       {"mapcheck",      1, 3, f_mapcheck},
364       {"match",         2, 4, f_match},
365 +     {"matchadd",      2, 4, f_matchadd},
366       {"matcharg",      1, 1, f_matcharg},
367 +     {"matchdelete",   1, 1, f_matchdelete},
368       {"matchend",      2, 4, f_matchend},
369       {"matchlist",     2, 4, f_matchlist},
370       {"matchstr",      2, 4, f_matchstr},
371 ***************
372 *** 7193,7198 ****
373 --- 7202,7208 ----
374       {"setcmdpos",     1, 1, f_setcmdpos},
375       {"setline",               2, 2, f_setline},
376       {"setloclist",    2, 3, f_setloclist},
377 +     {"setmatches",    1, 1, f_setmatches},
378       {"setpos",                2, 2, f_setpos},
379       {"setqflist",     1, 2, f_setqflist},
380       {"setreg",                2, 3, f_setreg},
381 ***************
382 *** 8243,8248 ****
383 --- 8253,8272 ----
384   }
385   
386   /*
387 +  * "clearmatches()" function
388 +  */
389 + /*ARGSUSED*/
390 +     static void
391 + f_clearmatches(argvars, rettv)
392 +     typval_T  *argvars;
393 +     typval_T  *rettv;
394 + {
395 + #ifdef FEAT_SEARCH_EXTRA
396 +     clear_matches(curwin);
397 + #endif
398 + }
399
400 + /*
401    * "col(string)" function
402    */
403       static void
404 ***************
405 *** 10278,10283 ****
406 --- 10302,10341 ----
407   }
408   
409   /*
410 +  * "getmatches()" function
411 +  */
412 + /*ARGSUSED*/
413 +     static void
414 + f_getmatches(argvars, rettv)
415 +     typval_T  *argvars;
416 +     typval_T  *rettv;
417 + {
418 + #ifdef FEAT_SEARCH_EXTRA
419 +     dict_T    *dict;
420 +     matchitem_T       *cur = curwin->w_match_head;
421
422 +     rettv->vval.v_number = 0;
423
424 +     if (rettv_list_alloc(rettv) == OK)
425 +     {
426 +       while (cur != NULL)
427 +       {
428 +           dict = dict_alloc();
429 +           if (dict == NULL)
430 +               return;
431 +           ++dict->dv_refcount;
432 +           dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
433 +           dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
434 +           dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
435 +           dict_add_nr_str(dict, "id", (long)cur->id, NULL);
436 +           list_append_dict(rettv->vval.v_list, dict);
437 +           cur = cur->next;
438 +       }
439 +     }
440 + #endif
441 + }
442
443 + /*
444    * "getpos(string)" function
445    */
446       static void
447 ***************
448 *** 12448,12453 ****
449 --- 12506,12547 ----
450   }
451   
452   /*
453 +  * "matchadd()" function
454 +  */
455 +     static void
456 + f_matchadd(argvars, rettv)
457 +     typval_T  *argvars;
458 +     typval_T  *rettv;
459 + {
460 + #ifdef FEAT_SEARCH_EXTRA
461 +     char_u    buf[NUMBUFLEN];
462 +     char_u    *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */
463 +     char_u    *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */
464 +     int               prio = 10;      /* default priority */
465 +     int               id = -1;
466 +     int               error = FALSE;
467
468 +     rettv->vval.v_number = -1;
469
470 +     if (grp == NULL || pat == NULL)
471 +       return;
472 +     if (argvars[2].v_type != VAR_UNKNOWN)
473 +       prio = get_tv_number_chk(&argvars[2], &error);
474 +     if (argvars[3].v_type != VAR_UNKNOWN)
475 +       id = get_tv_number_chk(&argvars[3], &error);
476 +     if (error == TRUE)
477 +       return;
478 +     if (id >= 1 && id <= 3)
479 +     {
480 +       EMSGN("E798: ID is reserved for \":match\": %ld", id);
481 +       return;
482 +     }
483
484 +     rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
485 + #endif
486 + }
487
488 + /*
489    * "matcharg()" function
490    */
491       static void
492 ***************
493 *** 12458,12477 ****
494       if (rettv_list_alloc(rettv) == OK)
495       {
496   #ifdef FEAT_SEARCH_EXTRA
497 !       int     mi = get_tv_number(&argvars[0]);
498   
499 !       if (mi >= 1 && mi <= 3)
500         {
501 !           list_append_string(rettv->vval.v_list,
502 !                                syn_id2name(curwin->w_match_id[mi - 1]), -1);
503 !           list_append_string(rettv->vval.v_list,
504 !                                            curwin->w_match_pat[mi - 1], -1);
505         }
506   #endif
507       }
508   }
509   
510   /*
511    * "matchend()" function
512    */
513       static void
514 --- 12552,12593 ----
515       if (rettv_list_alloc(rettv) == OK)
516       {
517   #ifdef FEAT_SEARCH_EXTRA
518 !       int         id = get_tv_number(&argvars[0]);
519 !       matchitem_T *m;
520   
521 !       if (id >= 1 && id <= 3)
522         {
523 !           if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
524 !           {
525 !               list_append_string(rettv->vval.v_list,
526 !                                               syn_id2name(m->hlg_id), -1);
527 !               list_append_string(rettv->vval.v_list, m->pattern, -1);
528 !           }
529 !           else
530 !           {
531 !               list_append_string(rettv->vval.v_list, NUL, -1);
532 !               list_append_string(rettv->vval.v_list, NUL, -1);
533 !           }
534         }
535   #endif
536       }
537   }
538   
539   /*
540 +  * "matchdelete()" function
541 +  */
542 +     static void
543 + f_matchdelete(argvars, rettv)
544 +     typval_T  *argvars;
545 +     typval_T  *rettv;
546 + {
547 + #ifdef FEAT_SEARCH_EXTRA
548 +     rettv->vval.v_number = match_delete(curwin,
549 +                                      (int)get_tv_number(&argvars[0]), TRUE);
550 + #endif
551 + }
552
553 + /*
554    * "matchend()" function
555    */
556       static void
557 ***************
558 *** 14506,14511 ****
559 --- 14622,14687 ----
560       win = find_win_by_nr(&argvars[0], NULL);
561       if (win != NULL)
562         set_qf_ll_list(win, &argvars[1], &argvars[2], rettv);
563 + }
564
565 + /*
566 +  * "setmatches()" function
567 +  */
568 +     static void
569 + f_setmatches(argvars, rettv)
570 +     typval_T  *argvars;
571 +     typval_T  *rettv;
572 + {
573 + #ifdef FEAT_SEARCH_EXTRA
574 +     list_T    *l;
575 +     listitem_T        *li;
576 +     dict_T    *d;
577
578 +     rettv->vval.v_number = -1;
579 +     if (argvars[0].v_type != VAR_LIST)
580 +     {
581 +       EMSG(_(e_listreq));
582 +       return;
583 +     }
584 +     if ((l = argvars[0].vval.v_list) != NULL)
585 +     {
586
587 +       /* To some extent make sure that we are dealing with a list from
588 +        * "getmatches()". */
589 +       li = l->lv_first;
590 +       while (li != NULL)
591 +       {
592 +           if (li->li_tv.v_type != VAR_DICT
593 +                   || (d = li->li_tv.vval.v_dict) == NULL)
594 +           {
595 +               EMSG(_(e_invarg));
596 +               return;
597 +           }
598 +           if (!(dict_find(d, (char_u *)"group", -1) != NULL
599 +                       && dict_find(d, (char_u *)"pattern", -1) != NULL
600 +                       && dict_find(d, (char_u *)"priority", -1) != NULL
601 +                       && dict_find(d, (char_u *)"id", -1) != NULL))
602 +           {
603 +               EMSG(_(e_invarg));
604 +               return;
605 +           }
606 +           li = li->li_next;
607 +       }
608
609 +       clear_matches(curwin);
610 +       li = l->lv_first;
611 +       while (li != NULL)
612 +       {
613 +           d = li->li_tv.vval.v_dict;
614 +           match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
615 +                   get_dict_string(d, (char_u *)"pattern", FALSE),
616 +                   (int)get_dict_number(d, (char_u *)"priority"),
617 +                   (int)get_dict_number(d, (char_u *)"id"));
618 +           li = li->li_next;
619 +       }
620 +       rettv->vval.v_number = 0;
621 +     }
622 + #endif
623   }
624   
625   /*
626 *** ../vim-7.1.039/src/ex_docmd.c       Tue Jul 24 14:32:44 2007
627 --- src/ex_docmd.c      Tue Jul 24 15:47:01 2007
628 ***************
629 *** 10817,10828 ****
630       exarg_T   *eap;
631   {
632       char_u    *p;
633       char_u    *end;
634       int               c;
635 !     int               mi;
636   
637       if (eap->line2 <= 3)
638 !       mi = eap->line2 - 1;
639       else
640       {
641         EMSG(e_invcmd);
642 --- 10817,10829 ----
643       exarg_T   *eap;
644   {
645       char_u    *p;
646 +     char_u    *g;
647       char_u    *end;
648       int               c;
649 !     int               id;
650   
651       if (eap->line2 <= 3)
652 !       id = eap->line2;
653       else
654       {
655         EMSG(e_invcmd);
656 ***************
657 *** 10831,10843 ****
658   
659       /* First clear any old pattern. */
660       if (!eap->skip)
661 !     {
662 !       vim_free(curwin->w_match[mi].regprog);
663 !       curwin->w_match[mi].regprog = NULL;
664 !       vim_free(curwin->w_match_pat[mi]);
665 !       curwin->w_match_pat[mi] = NULL;
666 !       redraw_later(SOME_VALID);       /* always need a redraw */
667 !     }
668   
669       if (ends_excmd(*eap->arg))
670         end = eap->arg;
671 --- 10832,10838 ----
672   
673       /* First clear any old pattern. */
674       if (!eap->skip)
675 !       match_delete(curwin, id, FALSE);
676   
677       if (ends_excmd(*eap->arg))
678         end = eap->arg;
679 ***************
680 *** 10848,10862 ****
681       {
682         p = skiptowhite(eap->arg);
683         if (!eap->skip)
684 !       {
685 !           curwin->w_match_id[mi] = syn_namen2id(eap->arg,
686 !                                                        (int)(p - eap->arg));
687 !           if (curwin->w_match_id[mi] == 0)
688 !           {
689 !               EMSG2(_(e_nogroup), eap->arg);
690 !               return;
691 !           }
692 !       }
693         p = skipwhite(p);
694         if (*p == NUL)
695         {
696 --- 10843,10849 ----
697       {
698         p = skiptowhite(eap->arg);
699         if (!eap->skip)
700 !           g = vim_strnsave(eap->arg, (int)(p - eap->arg));
701         p = skipwhite(p);
702         if (*p == NUL)
703         {
704 ***************
705 *** 10880,10893 ****
706   
707             c = *end;
708             *end = NUL;
709 !           curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC);
710 !           if (curwin->w_match[mi].regprog == NULL)
711 !           {
712 !               EMSG2(_(e_invarg2), p);
713 !               *end = c;
714 !               return;
715 !           }
716 !           curwin->w_match_pat[mi] = vim_strsave(p + 1);
717             *end = c;
718         }
719       }
720 --- 10867,10874 ----
721   
722             c = *end;
723             *end = NUL;
724 !           match_add(curwin, g, p + 1, 10, id);
725 !           vim_free(g);
726             *end = c;
727         }
728       }
729 *** ../vim-7.1.039/src/proto/window.pro Sat May  5 19:52:36 2007
730 --- src/proto/window.pro        Tue Jul 24 16:38:19 2007
731 ***************
732 *** 59,62 ****
733 --- 59,66 ----
734   int only_one_window __ARGS((void));
735   void check_lnums __ARGS((int do_curwin));
736   int win_hasvertsplit __ARGS((void));
737 + int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
738 + int match_delete __ARGS((win_T *wp, int id, int perr));
739 + void clear_matches __ARGS((win_T *wp));
740 + matchitem_T *get_match __ARGS((win_T *wp, int id));
741   /* vim: set ft=c : */
742 *** ../vim-7.1.039/src/screen.c Tue Jun 19 17:49:12 2007
743 --- src/screen.c        Thu Jul 26 21:55:40 2007
744 ***************
745 *** 100,126 ****
746   static int    screen_cur_row, screen_cur_col; /* last known cursor position */
747   
748   #ifdef FEAT_SEARCH_EXTRA
749 - /*
750 -  * Struct used for highlighting 'hlsearch' matches for the last use search
751 -  * pattern or a ":match" item.
752 -  * For 'hlsearch' there is one pattern for all windows.  For ":match" there is
753 -  * a different pattern for each window.
754 -  */
755 - typedef struct
756 - {
757 -     regmmatch_T       rm;     /* points to the regexp program; contains last found
758 -                          match (may continue in next line) */
759 -     buf_T     *buf;   /* the buffer to search for a match */
760 -     linenr_T  lnum;   /* the line to search for a match */
761 -     int               attr;   /* attributes to be used for a match */
762 -     int               attr_cur; /* attributes currently active in win_line() */
763 -     linenr_T  first_lnum;     /* first lnum to search for multi-line pat */
764 -     colnr_T   startcol; /* in win_line() points to char where HL starts */
765 -     colnr_T   endcol;  /* in win_line() points to char where HL ends */
766 - } match_T;
767
768   static match_T search_hl;     /* used for 'hlsearch' highlight matching */
769 - static match_T match_hl[3];   /* used for ":match" highlight matching */
770   #endif
771   
772   #ifdef FEAT_FOLDING
773 --- 100,106 ----
774 ***************
775 *** 155,160 ****
776 --- 135,141 ----
777   static void redraw_custum_statusline __ARGS((win_T *wp));
778   #endif
779   #ifdef FEAT_SEARCH_EXTRA
780 + #define SEARCH_HL_PRIORITY 0
781   static void start_search_hl __ARGS((void));
782   static void end_search_hl __ARGS((void));
783   static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
784 ***************
785 *** 787,792 ****
786 --- 768,774 ----
787                                            w_topline got smaller a bit */
788   #endif
789   #ifdef FEAT_SEARCH_EXTRA
790 +     matchitem_T *cur;         /* points to the match list */
791       int               top_to_mod = FALSE;    /* redraw above mod_top */
792   #endif
793   
794 ***************
795 *** 848,865 ****
796   #endif
797   
798   #ifdef FEAT_SEARCH_EXTRA
799 !     /* Setup for ":match" and 'hlsearch' highlighting.  Disable any previous
800        * match */
801 !     for (i = 0; i < 3; ++i)
802       {
803 !       match_hl[i].rm = wp->w_match[i];
804 !       if (wp->w_match_id[i] == 0)
805 !           match_hl[i].attr = 0;
806         else
807 !           match_hl[i].attr = syn_id2attr(wp->w_match_id[i]);
808 !       match_hl[i].buf = buf;
809 !       match_hl[i].lnum = 0;
810 !       match_hl[i].first_lnum = 0;
811       }
812       search_hl.buf = buf;
813       search_hl.lnum = 0;
814 --- 830,849 ----
815   #endif
816   
817   #ifdef FEAT_SEARCH_EXTRA
818 !     /* Setup for match and 'hlsearch' highlighting.  Disable any previous
819        * match */
820 !     cur = wp->w_match_head;
821 !     while (cur != NULL)
822       {
823 !       cur->hl.rm = cur->match;
824 !       if (cur->hlg_id == 0)
825 !           cur->hl.attr = 0;
826         else
827 !           cur->hl.attr = syn_id2attr(cur->hlg_id);
828 !       cur->hl.buf = buf;
829 !       cur->hl.lnum = 0;
830 !       cur->hl.first_lnum = 0;
831 !       cur = cur->next;
832       }
833       search_hl.buf = buf;
834       search_hl.lnum = 0;
835 ***************
836 *** 923,941 ****
837              * change in one line may make the Search highlighting in a
838              * previous line invalid.  Simple solution: redraw all visible
839              * lines above the change.
840 !            * Same for a ":match" pattern.
841              */
842             if (search_hl.rm.regprog != NULL
843                                         && re_multiline(search_hl.rm.regprog))
844                 top_to_mod = TRUE;
845             else
846 !               for (i = 0; i < 3; ++i)
847 !                   if (match_hl[i].rm.regprog != NULL
848 !                                     && re_multiline(match_hl[i].rm.regprog))
849                     {
850                         top_to_mod = TRUE;
851                         break;
852                     }
853   #endif
854         }
855   #ifdef FEAT_FOLDING
856 --- 907,931 ----
857              * change in one line may make the Search highlighting in a
858              * previous line invalid.  Simple solution: redraw all visible
859              * lines above the change.
860 !            * Same for a match pattern.
861              */
862             if (search_hl.rm.regprog != NULL
863                                         && re_multiline(search_hl.rm.regprog))
864                 top_to_mod = TRUE;
865             else
866 !           {
867 !               cur = wp->w_match_head;
868 !               while (cur != NULL)
869 !               {
870 !                   if (cur->match.regprog != NULL
871 !                                          && re_multiline(cur->match.regprog))
872                     {
873                         top_to_mod = TRUE;
874                         break;
875                     }
876 +                   cur = cur->next;
877 +               }
878 +           }
879   #endif
880         }
881   #ifdef FEAT_FOLDING
882 ***************
883 *** 2626,2635 ****
884       int               line_attr = 0;          /* atrribute for the whole line */
885   #endif
886   #ifdef FEAT_SEARCH_EXTRA
887 !     match_T   *shl;                   /* points to search_hl or match_hl */
888 ! #endif
889 ! #if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_MBYTE)
890 !     int               i;
891   #endif
892   #ifdef FEAT_ARABIC
893       int               prev_c = 0;             /* previous Arabic character */
894 --- 2634,2646 ----
895       int               line_attr = 0;          /* atrribute for the whole line */
896   #endif
897   #ifdef FEAT_SEARCH_EXTRA
898 !     matchitem_T *cur;                 /* points to the match list */
899 !     match_T   *shl;                   /* points to search_hl or a match */
900 !     int               shl_flag;               /* flag to indicate whether search_hl
901 !                                          has been processed or not */
902 !     int               prevcol_hl_flag;        /* flag to indicate whether prevcol
903 !                                          equals startcol of search_hl or one
904 !                                          of the matches */
905   #endif
906   #ifdef FEAT_ARABIC
907       int               prev_c = 0;             /* previous Arabic character */
908 ***************
909 *** 3074,3085 ****
910   
911   #ifdef FEAT_SEARCH_EXTRA
912       /*
913 !      * Handle highlighting the last used search pattern and ":match".
914 !      * Do this for both search_hl and match_hl[3].
915        */
916 !     for (i = 3; i >= 0; --i)
917       {
918 !       shl = (i == 3) ? &search_hl : &match_hl[i];
919         shl->startcol = MAXCOL;
920         shl->endcol = MAXCOL;
921         shl->attr_cur = 0;
922 --- 3085,3104 ----
923   
924   #ifdef FEAT_SEARCH_EXTRA
925       /*
926 !      * Handle highlighting the last used search pattern and matches.
927 !      * Do this for both search_hl and the match list.
928        */
929 !     cur = wp->w_match_head;
930 !     shl_flag = FALSE;
931 !     while (cur != NULL || shl_flag == FALSE)
932       {
933 !       if (shl_flag == FALSE)
934 !       {
935 !           shl = &search_hl;
936 !           shl_flag = TRUE;
937 !       }
938 !       else
939 !           shl = &cur->hl;
940         shl->startcol = MAXCOL;
941         shl->endcol = MAXCOL;
942         shl->attr_cur = 0;
943 ***************
944 *** 3122,3127 ****
945 --- 3141,3148 ----
946                 area_highlighting = TRUE;
947             }
948         }
949 +       if (shl != &search_hl && cur != NULL)
950 +           cur = cur->next;
951       }
952   #endif
953   
954 ***************
955 *** 3388,3400 ****
956                  * After end, check for start/end of next match.
957                  * When another match, have to check for start again.
958                  * Watch out for matching an empty string!
959 !                * Do this first for search_hl, then for match_hl, so that
960 !                * ":match" overrules 'hlsearch'.
961                  */
962                 v = (long)(ptr - line);
963 !               for (i = 3; i >= 0; --i)
964 !               {
965 !                   shl = (i == 3) ? &search_hl : &match_hl[i];
966                     while (shl->rm.regprog != NULL)
967                     {
968                         if (shl->startcol != MAXCOL
969 --- 3409,3432 ----
970                  * After end, check for start/end of next match.
971                  * When another match, have to check for start again.
972                  * Watch out for matching an empty string!
973 !                * Do this for 'search_hl' and the match list (ordered by
974 !                * priority).
975                  */
976                 v = (long)(ptr - line);
977 !               cur = wp->w_match_head;
978 !               shl_flag = FALSE;
979 !               while (cur != NULL || shl_flag == FALSE)
980 !               {
981 !                   if (shl_flag == FALSE
982 !                           && ((cur != NULL
983 !                                   && cur->priority > SEARCH_HL_PRIORITY)
984 !                               || cur == NULL))
985 !                   {
986 !                       shl = &search_hl;
987 !                       shl_flag = TRUE;
988 !                   }
989 !                   else
990 !                       shl = &cur->hl;
991                     while (shl->rm.regprog != NULL)
992                     {
993                         if (shl->startcol != MAXCOL
994 ***************
995 *** 3442,3458 ****
996                         }
997                         break;
998                     }
999                 }
1000   
1001 !               /* ":match" highlighting overrules 'hlsearch' */
1002 !               for (i = 0; i <= 3; ++i)
1003 !                   if (i == 3)
1004 !                       search_attr = search_hl.attr_cur;
1005 !                   else if (match_hl[i].attr_cur != 0)
1006                     {
1007 !                       search_attr = match_hl[i].attr_cur;
1008 !                       break;
1009                     }
1010             }
1011   #endif
1012   
1013 --- 3474,3505 ----
1014                         }
1015                         break;
1016                     }
1017 +                   if (shl != &search_hl && cur != NULL)
1018 +                       cur = cur->next;
1019                 }
1020   
1021 !               /* Use attributes from match with highest priority among
1022 !                * 'search_hl' and the match list. */
1023 !               search_attr = search_hl.attr_cur;
1024 !               cur = wp->w_match_head;
1025 !               shl_flag = FALSE;
1026 !               while (cur != NULL || shl_flag == FALSE)
1027 !               {
1028 !                   if (shl_flag == FALSE
1029 !                           && ((cur != NULL
1030 !                                   && cur->priority > SEARCH_HL_PRIORITY)
1031 !                               || cur == NULL))
1032                     {
1033 !                       shl = &search_hl;
1034 !                       shl_flag = TRUE;
1035                     }
1036 +                   else
1037 +                       shl = &cur->hl;
1038 +                   if (shl->attr_cur != 0)
1039 +                       search_attr = shl->attr_cur;
1040 +                   if (shl != &search_hl && cur != NULL)
1041 +                       cur = cur->next;
1042 +               }
1043             }
1044   #endif
1045   
1046 ***************
1047 *** 3613,3618 ****
1048 --- 3660,3667 ----
1049                          * Draw it as a space with a composing char. */
1050                         if (utf_iscomposing(mb_c))
1051                         {
1052 +                           int i;
1053
1054                             for (i = Screen_mco - 1; i > 0; --i)
1055                                 u8cc[i] = u8cc[i - 1];
1056                             u8cc[0] = mb_c;
1057 ***************
1058 *** 4256,4269 ****
1059              * highlight match at end of line. If it's beyond the last
1060              * char on the screen, just overwrite that one (tricky!)  Not
1061              * needed when a '$' was displayed for 'list'. */
1062             if (lcs_eol == lcs_eol_one
1063                     && ((area_attr != 0 && vcol == fromcol && c == NUL)
1064   #ifdef FEAT_SEARCH_EXTRA
1065                         /* highlight 'hlsearch' match at end of line */
1066 !                       || ((prevcol == (long)search_hl.startcol
1067 !                               || prevcol == (long)match_hl[0].startcol
1068 !                               || prevcol == (long)match_hl[1].startcol
1069 !                               || prevcol == (long)match_hl[2].startcol)
1070   # if defined(LINE_ATTR)
1071                             && did_line_attr <= 1
1072   # endif
1073 --- 4305,4333 ----
1074              * highlight match at end of line. If it's beyond the last
1075              * char on the screen, just overwrite that one (tricky!)  Not
1076              * needed when a '$' was displayed for 'list'. */
1077 + #ifdef FEAT_SEARCH_EXTRA
1078 +           prevcol_hl_flag = FALSE;
1079 +           if (prevcol == (long)search_hl.startcol)
1080 +               prevcol_hl_flag = TRUE;
1081 +           else
1082 +           {
1083 +               cur = wp->w_match_head;
1084 +               while (cur != NULL)
1085 +               {
1086 +                   if (prevcol == (long)cur->hl.startcol)
1087 +                   {
1088 +                       prevcol_hl_flag = TRUE;
1089 +                       break;
1090 +                   }
1091 +                   cur = cur->next;
1092 +               }
1093 +           }
1094 + #endif
1095             if (lcs_eol == lcs_eol_one
1096                     && ((area_attr != 0 && vcol == fromcol && c == NUL)
1097   #ifdef FEAT_SEARCH_EXTRA
1098                         /* highlight 'hlsearch' match at end of line */
1099 !                       || (prevcol_hl_flag == TRUE
1100   # if defined(LINE_ATTR)
1101                             && did_line_attr <= 1
1102   # endif
1103 ***************
1104 *** 4304,4318 ****
1105   #ifdef FEAT_SEARCH_EXTRA
1106                 if (area_attr == 0)
1107                 {
1108 !                   for (i = 0; i <= 3; ++i)
1109 !                   {
1110 !                       if (i == 3)
1111 !                           char_attr = search_hl.attr;
1112 !                       else if ((ptr - line) - 1 == (long)match_hl[i].startcol)
1113                         {
1114 !                           char_attr = match_hl[i].attr;
1115 !                           break;
1116                         }
1117                     }
1118                 }
1119   #endif
1120 --- 4368,4394 ----
1121   #ifdef FEAT_SEARCH_EXTRA
1122                 if (area_attr == 0)
1123                 {
1124 !                   /* Use attributes from match with highest priority among
1125 !                    * 'search_hl' and the match list. */
1126 !                   char_attr = search_hl.attr;
1127 !                   cur = wp->w_match_head;
1128 !                   shl_flag = FALSE;
1129 !                   while (cur != NULL || shl_flag == FALSE)
1130 !                   {
1131 !                       if (shl_flag == FALSE
1132 !                               && ((cur != NULL
1133 !                                       && cur->priority > SEARCH_HL_PRIORITY)
1134 !                                   || cur == NULL))
1135                         {
1136 !                           shl = &search_hl;
1137 !                           shl_flag = TRUE;
1138                         }
1139 +                       else
1140 +                           shl = &cur->hl;
1141 +                       if ((ptr - line) - 1 == (long)shl->startcol)
1142 +                           char_attr = shl->attr;
1143 +                       if (shl != &search_hl && cur != NULL)
1144 +                           cur = cur->next;
1145                     }
1146                 }
1147   #endif
1148 ***************
1149 *** 4462,4467 ****
1150 --- 4538,4545 ----
1151             {
1152                 if (mb_utf8)
1153                 {
1154 +                   int i;
1155
1156                     ScreenLinesUC[off] = mb_c;
1157                     if ((c & 0xff) == 0)
1158                         ScreenLines[off] = 0x80;   /* avoid storing zero */
1159 ***************
1160 *** 6320,6326 ****
1161   
1162   #ifdef FEAT_SEARCH_EXTRA
1163   /*
1164 !  * Prepare for 'searchhl' highlighting.
1165    */
1166       static void
1167   start_search_hl()
1168 --- 6398,6404 ----
1169   
1170   #ifdef FEAT_SEARCH_EXTRA
1171   /*
1172 !  * Prepare for 'hlsearch' highlighting.
1173    */
1174       static void
1175   start_search_hl()
1176 ***************
1177 *** 6333,6339 ****
1178   }
1179   
1180   /*
1181 !  * Clean up for 'searchhl' highlighting.
1182    */
1183       static void
1184   end_search_hl()
1185 --- 6411,6417 ----
1186   }
1187   
1188   /*
1189 !  * Clean up for 'hlsearch' highlighting.
1190    */
1191       static void
1192   end_search_hl()
1193 ***************
1194 *** 6353,6370 ****
1195       win_T     *wp;
1196       linenr_T  lnum;
1197   {
1198 !     match_T   *shl;           /* points to search_hl or match_hl */
1199       int               n;
1200 -     int               i;
1201   
1202       /*
1203        * When using a multi-line pattern, start searching at the top
1204        * of the window or just after a closed fold.
1205 !      * Do this both for search_hl and match_hl[3].
1206        */
1207 !     for (i = 3; i >= 0; --i)
1208       {
1209 !       shl = (i == 3) ? &search_hl : &match_hl[i];
1210         if (shl->rm.regprog != NULL
1211                 && shl->lnum == 0
1212                 && re_multiline(shl->rm.regprog))
1213 --- 6431,6458 ----
1214       win_T     *wp;
1215       linenr_T  lnum;
1216   {
1217 !     matchitem_T *cur;         /* points to the match list */
1218 !     match_T   *shl;           /* points to search_hl or a match */
1219 !     int               shl_flag;       /* flag to indicate whether search_hl
1220 !                                  has been processed or not */
1221       int               n;
1222   
1223       /*
1224        * When using a multi-line pattern, start searching at the top
1225        * of the window or just after a closed fold.
1226 !      * Do this both for search_hl and the match list.
1227        */
1228 !     cur = wp->w_match_head;
1229 !     shl_flag = FALSE;
1230 !     while (cur != NULL || shl_flag == FALSE)
1231       {
1232 !       if (shl_flag == FALSE)
1233 !       {
1234 !           shl = &search_hl;
1235 !           shl_flag = TRUE;
1236 !       }
1237 !       else
1238 !           shl = &cur->hl;
1239         if (shl->rm.regprog != NULL
1240                 && shl->lnum == 0
1241                 && re_multiline(shl->rm.regprog))
1242 ***************
1243 *** 6399,6409 ****
1244                 }
1245             }
1246         }
1247       }
1248   }
1249   
1250   /*
1251 !  * Search for a next 'searchl' or ":match" match.
1252    * Uses shl->buf.
1253    * Sets shl->lnum and shl->rm contents.
1254    * Note: Assumes a previous match is always before "lnum", unless
1255 --- 6487,6499 ----
1256                 }
1257             }
1258         }
1259 +       if (shl != &search_hl && cur != NULL)
1260 +           cur = cur->next;
1261       }
1262   }
1263   
1264   /*
1265 !  * Search for a next 'hlsearch' or match.
1266    * Uses shl->buf.
1267    * Sets shl->lnum and shl->rm contents.
1268    * Note: Assumes a previous match is always before "lnum", unless
1269 ***************
1270 *** 6413,6419 ****
1271       static void
1272   next_search_hl(win, shl, lnum, mincol)
1273       win_T     *win;
1274 !     match_T   *shl;           /* points to search_hl or match_hl */
1275       linenr_T  lnum;
1276       colnr_T   mincol;         /* minimal column for a match */
1277   {
1278 --- 6503,6509 ----
1279       static void
1280   next_search_hl(win, shl, lnum, mincol)
1281       win_T     *win;
1282 !     match_T   *shl;           /* points to search_hl or a match */
1283       linenr_T  lnum;
1284       colnr_T   mincol;         /* minimal column for a match */
1285   {
1286 ***************
1287 *** 6481,6487 ****
1288             /* Error while handling regexp: stop using this regexp. */
1289             if (shl == &search_hl)
1290             {
1291 !               /* don't free the regprog in match_hl[], it's a copy */
1292                 vim_free(shl->rm.regprog);
1293                 no_hlsearch = TRUE;
1294             }
1295 --- 6571,6577 ----
1296             /* Error while handling regexp: stop using this regexp. */
1297             if (shl == &search_hl)
1298             {
1299 !               /* don't free regprog in the match list, it's a copy */
1300                 vim_free(shl->rm.regprog);
1301                 no_hlsearch = TRUE;
1302             }
1303 *** ../vim-7.1.039/src/structs.h        Thu May 10 20:32:30 2007
1304 --- src/structs.h       Wed Jul 25 21:08:46 2007
1305 ***************
1306 *** 1694,1699 ****
1307 --- 1694,1734 ----
1308   #define FR_COL        2       /* frame with a column of windows */
1309   
1310   /*
1311 +  * Struct used for highlighting 'hlsearch' matches, matches defined by
1312 +  * ":match" and matches defined by match functions.
1313 +  * For 'hlsearch' there is one pattern for all windows.  For ":match" and the
1314 +  * match functions there is a different pattern for each window.
1315 +  */
1316 + typedef struct
1317 + {
1318 +     regmmatch_T       rm;     /* points to the regexp program; contains last found
1319 +                          match (may continue in next line) */
1320 +     buf_T     *buf;   /* the buffer to search for a match */
1321 +     linenr_T  lnum;   /* the line to search for a match */
1322 +     int               attr;   /* attributes to be used for a match */
1323 +     int               attr_cur; /* attributes currently active in win_line() */
1324 +     linenr_T  first_lnum;     /* first lnum to search for multi-line pat */
1325 +     colnr_T   startcol; /* in win_line() points to char where HL starts */
1326 +     colnr_T   endcol;  /* in win_line() points to char where HL ends */
1327 + } match_T;
1328
1329 + /*
1330 +  * matchitem_T provides a linked list for storing match items for ":match" and
1331 +  * the match functions.
1332 +  */
1333 + typedef struct matchitem matchitem_T;
1334 + struct matchitem
1335 + {
1336 +     matchitem_T       *next;
1337 +     int               id;         /* match ID */
1338 +     int               priority;   /* match priority */
1339 +     char_u    *pattern;   /* pattern to highlight */
1340 +     int               hlg_id;     /* highlight group ID */
1341 +     regmmatch_T       match;      /* regexp program for pattern */
1342 +     match_T   hl;         /* struct for doing the actual highlighting */
1343 + };
1344
1345 + /*
1346    * Structure which contains all information that belongs to a window
1347    *
1348    * All row numbers are relative to the start of the window, except w_winrow.
1349 ***************
1350 *** 1934,1942 ****
1351   #endif
1352   
1353   #ifdef FEAT_SEARCH_EXTRA
1354 !     regmmatch_T       w_match[3];         /* regexp programs for ":match" */
1355 !     char_u    *(w_match_pat[3]);  /* patterns for ":match" */
1356 !     int               w_match_id[3];      /* highlight IDs for ":match" */
1357   #endif
1358   
1359       /*
1360 --- 1969,1976 ----
1361   #endif
1362   
1363   #ifdef FEAT_SEARCH_EXTRA
1364 !     matchitem_T       *w_match_head;          /* head of match list */
1365 !     int               w_next_match_id;        /* next match ID */
1366   #endif
1367   
1368       /*
1369 *** ../vim-7.1.039/src/syntax.c Tue Jul 24 14:32:44 2007
1370 --- src/syntax.c        Tue Jul 24 15:47:01 2007
1371 ***************
1372 *** 8504,8510 ****
1373   syn_id2name(id)
1374       int               id;
1375   {
1376 !     if (id <= 0 || id >= highlight_ga.ga_len)
1377         return (char_u *)"";
1378       return HL_TABLE()[id - 1].sg_name;
1379   }
1380 --- 8504,8510 ----
1381   syn_id2name(id)
1382       int               id;
1383   {
1384 !     if (id <= 0 || id > highlight_ga.ga_len)
1385         return (char_u *)"";
1386       return HL_TABLE()[id - 1].sg_name;
1387   }
1388 *** ../vim-7.1.039/src/testdir/Makefile Sun Apr 30 20:48:47 2006
1389 --- src/testdir/Makefile        Tue Jul 24 15:34:33 2007
1390 ***************
1391 *** 1,5 ****
1392   #
1393 ! # Makefile to run al tests for Vim
1394   #
1395   
1396   VIMPROG = ../vim
1397 --- 1,5 ----
1398   #
1399 ! # Makefile to run all tests for Vim
1400   #
1401   
1402   VIMPROG = ../vim
1403 ***************
1404 *** 15,21 ****
1405                 test43.out test44.out test45.out test46.out test47.out \
1406                 test48.out test49.out test51.out test52.out test53.out \
1407                 test54.out test55.out test56.out test57.out test58.out \
1408 !               test59.out test60.out test61.out test62.out
1409   
1410   SCRIPTS_GUI = test16.out
1411   
1412 --- 15,21 ----
1413                 test43.out test44.out test45.out test46.out test47.out \
1414                 test48.out test49.out test51.out test52.out test53.out \
1415                 test54.out test55.out test56.out test57.out test58.out \
1416 !               test59.out test60.out test61.out test62.out test63.out
1417   
1418   SCRIPTS_GUI = test16.out
1419   
1420 *** ../vim-7.1.039/src/testdir/test63.in        Tue Jul 24 16:45:02 2007
1421 --- src/testdir/test63.in       Tue Jul 24 15:32:30 2007
1422 ***************
1423 *** 0 ****
1424 --- 1,157 ----
1425 + Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
1426 + "matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
1427
1428 + STARTTEST
1429 + :so small.vim
1430 + :" --- Check that "matcharg()" returns the correct group and pattern if a match
1431 + :" --- is defined.
1432 + :let @r = "*** Test 1: "
1433 + :highlight MyGroup1 ctermbg=red
1434 + :highlight MyGroup2 ctermbg=green
1435 + :highlight MyGroup3 ctermbg=blue
1436 + :match MyGroup1 /TODO/
1437 + :2match MyGroup2 /FIXME/
1438 + :3match MyGroup3 /XXX/
1439 + :if matcharg(1) == ['MyGroup1', 'TODO'] && matcharg(2) == ['MyGroup2', 'FIXME'] && matcharg(3) == ['MyGroup3', 'XXX']
1440 + :  let @r .= "OK\n"
1441 + :else
1442 + :  let @r .= "FAILED\n"
1443 + :endif
1444 + :" --- Check that "matcharg()" returns an empty list if the argument is not 1,
1445 + :" --- 2 or 3 (only 0 and 4 are tested).
1446 + :let @r .= "*** Test 2: "
1447 + :if matcharg(0) == [] && matcharg(4) == []
1448 + :  let @r .= "OK\n"
1449 + :else
1450 + :  let @r .= "FAILED\n"
1451 + :endif
1452 + :" --- Check that "matcharg()" returns ['', ''] if a match is not defined.
1453 + :let @r .= "*** Test 3: "
1454 + :match
1455 + :2match
1456 + :3match
1457 + :if matcharg(1) == ['', ''] && matcharg(2) == ['', ''] && matcharg(3) == ['', '']
1458 + :  let @r .= "OK\n"
1459 + :else
1460 + :  let @r .= "FAILED\n"
1461 + :endif
1462 + :" --- Check that "matchadd()" and "getmatches()" agree on added matches and
1463 + :" --- that default values apply.
1464 + :let @r .= "*** Test 4: "
1465 + :let m1 = matchadd("MyGroup1", "TODO")
1466 + :let m2 = matchadd("MyGroup2", "FIXME", 42)
1467 + :let m3 = matchadd("MyGroup3", "XXX", 60, 17)
1468 + :if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 4}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 42, 'id': 5}, {'group': 'MyGroup3', 'pattern': 'XXX', 'priority': 60, 'id': 17}]
1469 + :  let @r .= "OK\n"
1470 + :else
1471 + :  let @r .= "FAILED\n"
1472 + :endif
1473 + :" --- Check that "matchdelete()" deletes the matches defined in the previous
1474 + :" --- test correctly.
1475 + :let @r .= "*** Test 5: "
1476 + :call matchdelete(m1)
1477 + :call matchdelete(m2)
1478 + :call matchdelete(m3)
1479 + :unlet m1
1480 + :unlet m2
1481 + :unlet m3
1482 + :if getmatches() == []
1483 + :  let @r .= "OK\n"
1484 + :else
1485 + :  let @r .= "FAILED\n"
1486 + :endif
1487 + :" --- Check that "matchdelete()" returns 0 if succesfull and otherwise -1.
1488 + :let @r .= "*** Test 6: "
1489 + :let m = matchadd("MyGroup1", "TODO")
1490 + :let r1 = matchdelete(m)
1491 + :let r2 = matchdelete(42)
1492 + :if r1 == 0 && r2 == -1
1493 + :  let @r .= "OK\n"
1494 + :else
1495 + :  let @r .= "FAILED\n"
1496 + :endif
1497 + :unlet m
1498 + :unlet r1
1499 + :unlet r2
1500 + :" --- Check that "clearmatches()" clears all matches defined by ":match" and
1501 + :" --- "matchadd()".
1502 + :let @r .= "*** Test 7: "
1503 + :let m1 = matchadd("MyGroup1", "TODO")
1504 + :let m2 = matchadd("MyGroup2", "FIXME", 42)
1505 + :let m3 = matchadd("MyGroup3", "XXX", 60, 17)
1506 + :match MyGroup1 /COFFEE/
1507 + :2match MyGroup2 /HUMPPA/
1508 + :3match MyGroup3 /VIM/
1509 + :call clearmatches()
1510 + :if getmatches() == []
1511 + :  let @r .= "OK\n"
1512 + :else
1513 + :  let @r .= "FAILED\n"
1514 + :endif
1515 + :unlet m1
1516 + :unlet m2
1517 + :unlet m3
1518 + :" --- Check that "setmatches()" restores a list of matches saved by
1519 + :" --- "getmatches()" without changes. (Matches with equal priority must also
1520 + :" --- remain in the same order.)
1521 + :let @r .= "*** Test 8: "
1522 + :let m1 = matchadd("MyGroup1", "TODO")
1523 + :let m2 = matchadd("MyGroup2", "FIXME", 42)
1524 + :let m3 = matchadd("MyGroup3", "XXX", 60, 17)
1525 + :match MyGroup1 /COFFEE/
1526 + :2match MyGroup2 /HUMPPA/
1527 + :3match MyGroup3 /VIM/
1528 + :let ml = getmatches()
1529 + :call clearmatches()
1530 + :call setmatches(ml)
1531 + :if getmatches() == ml
1532 + :  let @r .= "OK\n"
1533 + :else
1534 + :  let @r .= "FAILED\n"
1535 + :endif
1536 + :call clearmatches()
1537 + :unlet m1
1538 + :unlet m2
1539 + :unlet m3
1540 + :unlet ml
1541 + :" --- Check that "setmatches()" will not add two matches with the same ID. The
1542 + :" --- expected behaviour (for now) is to add the first match but not the
1543 + :" --- second and to return 0 (even though it is a matter of debate whether
1544 + :" --- this can be considered succesfull behaviour).
1545 + :let @r .= "*** Test 9: "
1546 + :let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])
1547 + :if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}] && r1 == 0
1548 + :  let @r .= "OK\n"
1549 + :else
1550 + :  let @r .= "FAILED\n"
1551 + :endif
1552 + :call clearmatches()
1553 + :unlet r1
1554 + :" --- Check that "setmatches()" returns 0 if succesfull and otherwise -1.
1555 + :" --- (A range of valid and invalid input values are tried out to generate the
1556 + :" --- return values.)
1557 + :let @r .= "*** Test 10: "
1558 + :let rs1 = setmatches([])
1559 + :let rs2 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])
1560 + :call clearmatches()
1561 + :let rf1 = setmatches(0)
1562 + :let rf2 = setmatches([0])
1563 + :let rf3 = setmatches([{'wrong key': 'wrong value'}])
1564 + :if rs1 == 0 && rs2 == 0 && rf1 == -1 && rf2 == -1 && rf3 == -1
1565 + :  let @r .= "OK\n"
1566 + :else
1567 + :  let @r .= "FAILED\n"
1568 + :endif
1569 + :unlet rs1
1570 + :unlet rs2
1571 + :unlet rf1
1572 + :unlet rf2
1573 + :unlet rf3
1574 + :highlight clear MyGroup1
1575 + :highlight clear MyGroup2
1576 + :highlight clear MyGroup3
1577 + G"rp
1578 + :/^Results/,$wq! test.out
1579 + ENDTEST
1580
1581 + Results of test63:
1582 *** ../vim-7.1.039/src/testdir/test63.ok        Tue Jul 24 16:45:02 2007
1583 --- src/testdir/test63.ok       Tue Jul 24 15:32:30 2007
1584 ***************
1585 *** 0 ****
1586 --- 1,11 ----
1587 + Results of test63:
1588 + *** Test 1: OK
1589 + *** Test 2: OK
1590 + *** Test 3: OK
1591 + *** Test 4: OK
1592 + *** Test 5: OK
1593 + *** Test 6: OK
1594 + *** Test 7: OK
1595 + *** Test 8: OK
1596 + *** Test 9: OK
1597 + *** Test 10: OK
1598 *** ../vim-7.1.039/src/window.c Thu May 10 18:42:26 2007
1599 --- src/window.c        Tue Jul 24 20:38:58 2007
1600 ***************
1601 *** 75,80 ****
1602 --- 75,81 ----
1603   static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
1604   
1605   #endif /* FEAT_WINDOWS */
1606
1607   static win_T *win_alloc __ARGS((win_T *after));
1608   static void win_new_height __ARGS((win_T *, int));
1609   
1610 ***************
1611 *** 4128,4133 ****
1612 --- 4129,4138 ----
1613   #ifdef FEAT_AUTOCMD
1614         --autocmd_block;
1615   #endif
1616 + #ifdef FEAT_SEARCH_EXTRA
1617 +       newwin->w_match_head = NULL;
1618 +       newwin->w_next_match_id = 4;
1619 + #endif
1620       }
1621       return newwin;
1622   }
1623 ***************
1624 *** 4185,4195 ****
1625         vim_free(wp->w_tagstack[i].tagname);
1626   
1627       vim_free(wp->w_localdir);
1628   #ifdef FEAT_SEARCH_EXTRA
1629 !     vim_free(wp->w_match[0].regprog);
1630 !     vim_free(wp->w_match[1].regprog);
1631 !     vim_free(wp->w_match[2].regprog);
1632   #endif
1633   #ifdef FEAT_JUMPLIST
1634       free_jumplist(wp);
1635   #endif
1636 --- 4190,4200 ----
1637         vim_free(wp->w_tagstack[i].tagname);
1638   
1639       vim_free(wp->w_localdir);
1640
1641   #ifdef FEAT_SEARCH_EXTRA
1642 !     clear_matches(wp);
1643   #endif
1644
1645   #ifdef FEAT_JUMPLIST
1646       free_jumplist(wp);
1647   #endif
1648 ***************
1649 *** 6172,6176 ****
1650 --- 6177,6351 ----
1651                 return TRUE;
1652   
1653       return FALSE;
1654 + }
1655 + #endif
1656
1657 + #if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
1658 + /*
1659 +  * Add match to the match list of window 'wp'.  The pattern 'pat' will be
1660 +  * highligted with the group 'grp' with priority 'prio'.
1661 +  * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
1662 +  * If no particular ID is desired, -1 must be specified for 'id'.
1663 +  * Return ID of added match, -1 on failure.
1664 +  */
1665 +     int
1666 + match_add(wp, grp, pat, prio, id)
1667 +     win_T     *wp;
1668 +     char_u    *grp;
1669 +     char_u    *pat;
1670 +     int               prio;
1671 +     int               id;
1672 + {
1673 +     matchitem_T *cur;
1674 +     matchitem_T *prev;
1675 +     matchitem_T *m;
1676 +     int               hlg_id;
1677 +     regmmatch_T match;
1678
1679 +     if (*grp == NUL || *pat == NUL)
1680 +       return -1;
1681 +     if (id < -1 || id == 0)
1682 +     {
1683 +       EMSGN("E799: Invalid ID: %ld (must be greater than or equal to 1)", id);
1684 +       return -1;
1685 +     }
1686 +     if (id != -1)
1687 +     {
1688 +       cur = wp->w_match_head;
1689 +       while (cur != NULL)
1690 +       {
1691 +           if (cur->id == id)
1692 +           {
1693 +               EMSGN("E801: ID already taken: %ld", id);
1694 +               return -1;
1695 +           }
1696 +           cur = cur->next;
1697 +       }
1698 +     }
1699 +     if ((hlg_id = syn_namen2id(grp, STRLEN(grp))) == 0)
1700 +     {
1701 +       EMSG2(_(e_nogroup), grp);
1702 +       return -1;
1703 +     }
1704 +     if ((match.regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
1705 +     {
1706 +       EMSG2(_(e_invarg2), pat);
1707 +       return -1;
1708 +     }
1709
1710 +     /* Find available match ID. */
1711 +     while (id == -1)
1712 +     {
1713 +       cur = wp->w_match_head;
1714 +       while (cur != NULL && cur->id != wp->w_next_match_id)
1715 +           cur = cur->next;
1716 +       if (cur == NULL)
1717 +           id = wp->w_next_match_id;
1718 +       wp->w_next_match_id++;
1719 +     }
1720
1721 +     /* Build new match. */
1722 +     m = (matchitem_T *)alloc(sizeof(matchitem_T));
1723 +     m->id = id;
1724 +     m->priority = prio;
1725 +     m->pattern = vim_strsave(pat);
1726 +     m->hlg_id = hlg_id;
1727 +     m->match.regprog = match.regprog;
1728
1729 +     /* Insert new match.  The match list is in ascending order with regard to
1730 +      * the match priorities. */
1731 +     cur = wp->w_match_head;
1732 +     prev = cur;
1733 +     while (cur != NULL && prio >= cur->priority)
1734 +     {
1735 +       prev = cur;
1736 +       cur = cur->next;
1737 +     }
1738 +     if (cur == prev)
1739 +       wp->w_match_head = m;
1740 +     else
1741 +       prev->next = m;
1742 +     m->next = cur;
1743
1744 +     redraw_later(SOME_VALID);
1745 +     return id;
1746 + }
1747
1748 + /*
1749 +  * Delete match with ID 'id' in the match list of window 'wp'.
1750 +  * Print error messages if 'perr' is TRUE.
1751 +  */
1752 +     int
1753 + match_delete(wp, id, perr)
1754 +     win_T     *wp;
1755 +     int               id;
1756 +     int               perr;
1757 + {
1758 +     matchitem_T *cur = wp->w_match_head;
1759 +     matchitem_T *prev = cur;
1760
1761 +     if (id < 1)
1762 +     {
1763 +       if (perr == TRUE)
1764 +           EMSGN("E802: Invalid ID: %ld (must be greater than or equal to 1)",
1765 +                                                                         id);
1766 +       return -1;
1767 +     }
1768 +     while (cur != NULL && cur->id != id)
1769 +     {
1770 +       prev = cur;
1771 +       cur = cur->next;
1772 +     }
1773 +     if (cur == NULL)
1774 +     {
1775 +       if (perr == TRUE)
1776 +           EMSGN("E803: ID not found: %ld", id);
1777 +       return -1;
1778 +     }
1779 +     if (cur == prev)
1780 +       wp->w_match_head = cur->next;
1781 +     else
1782 +       prev->next = cur->next;
1783 +     vim_free(cur->match.regprog);
1784 +     vim_free(cur->pattern);
1785 +     vim_free(cur);
1786 +     redraw_later(SOME_VALID);
1787 +     return 0;
1788 + }
1789
1790 + /*
1791 +  * Delete all matches in the match list of window 'wp'.
1792 +  */
1793 +     void
1794 + clear_matches(wp)
1795 +     win_T     *wp;
1796 + {
1797 +     matchitem_T *m;
1798
1799 +     while (wp->w_match_head != NULL)
1800 +     {
1801 +       m = wp->w_match_head->next;
1802 +       vim_free(wp->w_match_head->match.regprog);
1803 +       vim_free(wp->w_match_head->pattern);
1804 +       vim_free(wp->w_match_head);
1805 +       wp->w_match_head = m;
1806 +     }
1807 +     redraw_later(SOME_VALID);
1808 + }
1809
1810 + /*
1811 +  * Get match from ID 'id' in window 'wp'.
1812 +  * Return NULL if match not found.
1813 +  */
1814 +     matchitem_T *
1815 + get_match(wp, id)
1816 +     win_T     *wp;
1817 +     int               id;
1818 + {
1819 +     matchitem_T *cur = wp->w_match_head;
1820
1821 +     while (cur != NULL && cur->id != id)
1822 +       cur = cur->next;
1823 +     return cur;
1824   }
1825   #endif
1826 *** ../vim-7.1.039/src/version.c        Wed Jul 25 22:55:22 2007
1827 --- src/version.c       Thu Jul 26 22:50:54 2007
1828 ***************
1829 *** 668,669 ****
1830 --- 668,671 ----
1831   {   /* Add new patch number below this line */
1832 + /**/
1833 +     40,
1834   /**/
1835
1836 -- 
1837 It is hard to understand how a cemetery raised its burial
1838 cost and blamed it on the cost of living.
1839
1840  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
1841 ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
1842 \\\        download, build and distribute -- http://www.A-A-P.org        ///
1843  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
This page took 2.812818 seconds and 3 git commands to generate.