home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / patches / 7.1 / 7.1.040 < prev    next >
Encoding:
Internet Message Format  |  2007-11-19  |  52.2 KB

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