diff options
author | Bram Moolenaar <Bram@vim.org> | 2007-07-26 20:58:42 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2007-07-26 20:58:42 +0000 |
commit | 6ee10162b24109d5b3a0558304c110ffc9dc25b7 (patch) | |
tree | 499b2caf889484c944c88eafc6a7c5f7c73838cb | |
parent | f621048b53fb2ac84608886102b1733d7a338708 (diff) |
updated for version 7.1-040v7.1.040
-rw-r--r-- | runtime/doc/eval.txt | 89 | ||||
-rw-r--r-- | runtime/doc/pattern.txt | 16 | ||||
-rw-r--r-- | runtime/doc/usr_41.txt | 9 | ||||
-rw-r--r-- | src/eval.c | 188 | ||||
-rw-r--r-- | src/ex_docmd.c | 33 | ||||
-rw-r--r-- | src/proto/window.pro | 4 | ||||
-rw-r--r-- | src/screen.c | 216 | ||||
-rw-r--r-- | src/structs.h | 40 | ||||
-rw-r--r-- | src/syntax.c | 2 | ||||
-rw-r--r-- | src/testdir/Makefile | 4 | ||||
-rw-r--r-- | src/testdir/test63.in | 157 | ||||
-rw-r--r-- | src/testdir/test63.ok | 11 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/window.c | 181 |
14 files changed, 833 insertions, 119 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index a18b048c77..95ef5372b2 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.1. Last change: 2007 Jul 11 +*eval.txt* For Vim version 7.1. Last change: 2007 Jul 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1557,6 +1557,7 @@ call( {func}, {arglist} [, {dict}]) changenr() Number current change number char2nr( {expr}) Number ASCII value of first char in {expr} cindent( {lnum}) Number C indent for line {lnum} +clearmatches() None clear all matches col( {expr}) Number column nr of cursor or mark complete({startcol}, {matches}) String set Insert mode completion complete_add( {expr}) Number add completion match @@ -1622,6 +1623,7 @@ getftype( {fname}) String description of type of file {fname} getline( {lnum}) String line {lnum} of current buffer getline( {lnum}, {end}) List lines {lnum} to {end} of current buffer getloclist({nr}) List list of location list items +getmatches() List list of current matches getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items getreg( [{regname} [, 1]]) String contents of register @@ -1676,7 +1678,10 @@ mapcheck( {name}[, {mode} [, {abbr}]]) String check for mappings matching {name} match( {expr}, {pat}[, {start}[, {count}]]) Number position where {pat} matches in {expr} +matchadd( {group}, {pattern}[, {priority}[, {id}]]) + Number highlight {pattern} with {group} matcharg( {nr}) List arguments of |:match| +matchdelete( {id}) Number delete match identified by {id} matchend( {expr}, {pat}[, {start}[, {count}]]) Number position where {pat} ends in {expr} matchlist( {expr}, {pat}[, {start}[, {count}]]) @@ -1731,6 +1736,7 @@ setcmdpos( {pos}) Number set cursor position in command-line setline( {lnum}, {line}) Number set line {lnum} to {line} setloclist( {nr}, {list}[, {action}]) Number modify location list using {list} +setmatches( {list}) Number restore a list of matches setpos( {expr}, {list}) none set the {expr} position to {list} setqflist( {list}[, {action}]) Number modify quickfix list using {list} setreg( {n}, {v}[, {opt}]) Number set register to value and type @@ -2012,6 +2018,10 @@ cindent({lnum}) *cindent()* feature, -1 is returned. See |C-indenting|. +clearmatches() *clearmatches()* + Clears all matches previously defined by |matchadd()| and the + |:match| commands. + *col()* col({expr}) The result is a Number, which is the byte index of the column position given with {expr}. The accepted positions are: @@ -2918,6 +2928,28 @@ getloclist({nr}) *getloclist()* returned. For an invalid window number {nr}, an empty list is returned. Otherwise, same as getqflist(). +getmatches() *getmatches()* + Returns a |List| with all matches previously defined by + |matchadd()| and the |:match| commands. |getmatches()| is + useful in combination with |setmatches()|, as |setmatches()| + can restore a list of matches saved by |getmatches()|. + Example: > + :echo getmatches() +< [{'group': 'MyGroup1', 'pattern': 'TODO', + 'priority': 10, 'id': 1}, {'group': 'MyGroup2', + 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > + :let m = getmatches() + :call clearmatches() + :echo getmatches() +< [] > + :call setmatches(m) + :echo getmatches() +< [{'group': 'MyGroup1', 'pattern': 'TODO', + 'priority': 10, 'id': 1}, {'group': 'MyGroup2', + 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > + :unlet m +< + getqflist() *getqflist()* Returns a list with all the current quickfix errors. Each list item is a dictionary with these entries: @@ -3622,6 +3654,44 @@ match({expr}, {pat}[, {start}[, {count}]]) *match()* the pattern. 'smartcase' is NOT used. The matching is always done like 'magic' is set and 'cpoptions' is empty. + *matchadd()* *E798* *E799* *E801* +matchadd({group}, {pattern}[, {priority}[, {id}]]) + Defines a pattern to be highlighted in the current window (a + "match"). It will be highlighted with {group}. Returns an + identification number (ID), which can be used to delete the + match using |matchdelete()|. + + The optional {priority} argument assigns a priority to the + match. A match with a high priority will have its + highlighting overrule that of a match with a lower priority. + A priority is specified as an integer (negative numbers are no + exception). If the {priority} argument is not specified, the + default priority is 10. The priority of 'hlsearch' is zero, + hence all matches with a priority greater than zero will + overrule it. Syntax highlighting (see 'syntax') is a separate + mechanism, and regardless of the chosen priority a match will + always overrule syntax highlighting. + + The optional {id} argument allows the request for a specific + match ID. If a specified ID is already taken, an error + message will appear and the match will not be added. An ID + is specified as a positive integer (zero excluded). IDs 1, 2 + and 3 are reserved for |:match|, |:2match| and |:3match|, + respectively. If the {id} argument is not specified, + |matchadd()| automatically chooses a free ID. + + The number of matches is not limited, as it is the case with + the |:match| commands. + + Example: > + :highlight MyGroup ctermbg=green guibg=green + :let m = matchadd("MyGroup", "TODO") +< Deletion of the pattern: > + :call matchdelete(m) + +< A list of matches defined by |matchadd()| and |:match| are + available from |getmatches()|. All matches can be deleted in + one operation by |clearmatches()|. matcharg({nr}) *matcharg()* Selects the {nr} match item, as set with a |:match|, @@ -3631,8 +3701,15 @@ matcharg({nr}) *matcharg()* The pattern used. When {nr} is not 1, 2 or 3 returns an empty |List|. When there is no match item set returns ['', '']. - This is usef to save and restore a |:match|. + This is useful to save and restore a |:match|. + Highlighting matches using the |:match| commands are limited + to three matches. |matchadd()| does not have this limitation. +matchdelete({id}) *matchdelete()* *E802* *E803* + Deletes a match with ID {id} previously defined by |matchadd()| + or one of the |:match| commands. Returns 0 if succesfull, + otherwise -1. See example for |matchadd()|. All matches can + be deleted in one operation by |clearmatches()|. matchend({expr}, {pat}[, {start}[, {count}]]) *matchend()* Same as match(), but return the index of first character after @@ -4385,7 +4462,13 @@ setloclist({nr}, {list} [, {action}]) *setloclist()* When {nr} is zero the current window is used. For a location list window, the displayed location list is modified. For an invalid window number {nr}, -1 is returned. - Otherwise, same as setqflist(). + Otherwise, same as |setqflist()|. + Also see |location-list|. + +setmatches({list}) *setmatches()* + Restores a list of matches saved by |getmatches()|. Returns 0 + if succesfull, otherwise -1. All current matches are cleared + before the list is restored. See example for |getmatches()|. *setpos()* setpos({expr}, {list}) diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 22c5782a8f..5331cfec41 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1212,7 +1212,10 @@ Finally, these constructs are unique to Perl: {group} must exist at the moment this command is executed. The {group} highlighting still applies when a character is - to be highlighted for 'hlsearch'. + to be highlighted for 'hlsearch', as the highlighting for + matches is given higher priority than that of 'hlsearch'. + Syntax highlighting (see 'syntax') is also overruled by + matches. Note that highlighting the last used search pattern with 'hlsearch' is used in all windows, while the pattern defined @@ -1226,8 +1229,15 @@ Finally, these constructs are unique to Perl: display you may get unexpected results. That is because Vim looks for a match in the line where redrawing starts. - Also see |matcharg()|, it returns the highlight group and - pattern of a previous :match command. + Also see |matcharg()|and |getmatches()|. The former returns + the highlight group and pattern of a previous |:match| + command. The latter returns a list with highlight groups and + patterns defined by both |matchadd()| and |:match|. + + Highlighting matches using |:match| are limited to three + matches (aside from |:match|, |:2match| and |:3match|are + available). |matchadd()| does not have this limitation and in + addition makes it possible to prioritize matches. Another example, which highlights all characters in virtual column 72 and more: > diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index da5bf7ce91..64cf78d3b2 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -763,13 +763,22 @@ Folding: foldtextresult() get the text displayed for a closed fold Syntax and highlighting: + clearmatches() clear all matches defined by |matchadd()| and + the |:match| commands + getmatches() get all matches defined by |matchadd()| and + the |:match| commands hlexists() check if a highlight group exists hlID() get ID of a highlight group synID() get syntax ID at a specific position synIDattr() get a specific attribute of a syntax ID synIDtrans() get translated syntax ID diff_hlID() get highlight ID for diff mode at a position + matchadd() define a pattern to highlight (a "match") matcharg() get info about |:match| arguments + matchdelete() delete a match defined by |matchadd()| or a + |:match| command + setmatches() restore a list of matches saved by + |getmatches()| Spelling: spellbadword() locate badly spelled word at or after cursor diff --git a/src/eval.c b/src/eval.c index 5dc6c01da8..10df05b42a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -475,6 +475,7 @@ static void f_call __ARGS((typval_T *argvars, typval_T *rettv)); static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_col __ARGS((typval_T *argvars, typval_T *rettv)); #if defined(FEAT_INS_EXPAND) static void f_complete __ARGS((typval_T *argvars, typval_T *rettv)); @@ -529,6 +530,7 @@ static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getline __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv)); @@ -577,7 +579,9 @@ static void f_map __ARGS((typval_T *argvars, typval_T *rettv)); static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv)); static void f_match __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv)); @@ -618,6 +622,7 @@ static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setline __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7046,6 +7051,7 @@ static struct fst {"changenr", 0, 0, f_changenr}, {"char2nr", 1, 1, f_char2nr}, {"cindent", 1, 1, f_cindent}, + {"clearmatches", 0, 0, f_clearmatches}, {"col", 1, 1, f_col}, #if defined(FEAT_INS_EXPAND) {"complete", 2, 2, f_complete}, @@ -7102,6 +7108,7 @@ static struct fst {"getftype", 1, 1, f_getftype}, {"getline", 1, 2, f_getline}, {"getloclist", 1, 1, f_getqflist}, + {"getmatches", 0, 0, f_getmatches}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, {"getreg", 0, 2, f_getreg}, @@ -7152,7 +7159,9 @@ static struct fst {"maparg", 1, 3, f_maparg}, {"mapcheck", 1, 3, f_mapcheck}, {"match", 2, 4, f_match}, + {"matchadd", 2, 4, f_matchadd}, {"matcharg", 1, 1, f_matcharg}, + {"matchdelete", 1, 1, f_matchdelete}, {"matchend", 2, 4, f_matchend}, {"matchlist", 2, 4, f_matchlist}, {"matchstr", 2, 4, f_matchstr}, @@ -7193,6 +7202,7 @@ static struct fst {"setcmdpos", 1, 1, f_setcmdpos}, {"setline", 2, 2, f_setline}, {"setloclist", 2, 3, f_setloclist}, + {"setmatches", 1, 1, f_setmatches}, {"setpos", 2, 2, f_setpos}, {"setqflist", 1, 2, f_setqflist}, {"setreg", 2, 3, f_setreg}, @@ -8243,6 +8253,20 @@ f_cindent(argvars, rettv) } /* + * "clearmatches()" function + */ +/*ARGSUSED*/ + static void +f_clearmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + clear_matches(curwin); +#endif +} + +/* * "col(string)" function */ static void @@ -10278,6 +10302,40 @@ f_getline(argvars, rettv) } /* + * "getmatches()" function + */ +/*ARGSUSED*/ + static void +f_getmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + dict_T *dict; + matchitem_T *cur = curwin->w_match_head; + + rettv->vval.v_number = 0; + + if (rettv_list_alloc(rettv) == OK) + { + while (cur != NULL) + { + dict = dict_alloc(); + if (dict == NULL) + return; + ++dict->dv_refcount; + dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); + dict_add_nr_str(dict, "pattern", 0L, cur->pattern); + dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); + dict_add_nr_str(dict, "id", (long)cur->id, NULL); + list_append_dict(rettv->vval.v_list, dict); + cur = cur->next; + } + } +#endif +} + +/* * "getpos(string)" function */ static void @@ -12448,6 +12506,42 @@ f_match(argvars, rettv) } /* + * "matchadd()" function + */ + static void +f_matchadd(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + char_u buf[NUMBUFLEN]; + char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ + char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */ + int prio = 10; /* default priority */ + int id = -1; + int error = FALSE; + + rettv->vval.v_number = -1; + + if (grp == NULL || pat == NULL) + return; + if (argvars[2].v_type != VAR_UNKNOWN) + prio = get_tv_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) + id = get_tv_number_chk(&argvars[3], &error); + if (error == TRUE) + return; + if (id >= 1 && id <= 3) + { + EMSGN("E798: ID is reserved for \":match\": %ld", id); + return; + } + + rettv->vval.v_number = match_add(curwin, grp, pat, prio, id); +#endif +} + +/* * "matcharg()" function */ static void @@ -12458,20 +12552,42 @@ f_matcharg(argvars, rettv) if (rettv_list_alloc(rettv) == OK) { #ifdef FEAT_SEARCH_EXTRA - int mi = get_tv_number(&argvars[0]); + int id = get_tv_number(&argvars[0]); + matchitem_T *m; - if (mi >= 1 && mi <= 3) + if (id >= 1 && id <= 3) { - list_append_string(rettv->vval.v_list, - syn_id2name(curwin->w_match_id[mi - 1]), -1); - list_append_string(rettv->vval.v_list, - curwin->w_match_pat[mi - 1], -1); + if ((m = (matchitem_T *)get_match(curwin, id)) != NULL) + { + list_append_string(rettv->vval.v_list, + syn_id2name(m->hlg_id), -1); + list_append_string(rettv->vval.v_list, m->pattern, -1); + } + else + { + list_append_string(rettv->vval.v_list, NUL, -1); + list_append_string(rettv->vval.v_list, NUL, -1); + } } #endif } } /* + * "matchdelete()" function + */ + static void +f_matchdelete(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + rettv->vval.v_number = match_delete(curwin, + (int)get_tv_number(&argvars[0]), TRUE); +#endif +} + +/* * "matchend()" function */ static void @@ -14509,6 +14625,66 @@ f_setloclist(argvars, rettv) } /* + * "setmatches()" function + */ + static void +f_setmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + list_T *l; + listitem_T *li; + dict_T *d; + + rettv->vval.v_number = -1; + if (argvars[0].v_type != VAR_LIST) + { + EMSG(_(e_listreq)); + return; + } + if ((l = argvars[0].vval.v_list) != NULL) + { + + /* To some extent make sure that we are dealing with a list from + * "getmatches()". */ + li = l->lv_first; + while (li != NULL) + { + if (li->li_tv.v_type != VAR_DICT + || (d = li->li_tv.vval.v_dict) == NULL) + { + EMSG(_(e_invarg)); + return; + } + if (!(dict_find(d, (char_u *)"group", -1) != NULL + && dict_find(d, (char_u *)"pattern", -1) != NULL + && dict_find(d, (char_u *)"priority", -1) != NULL + && dict_find(d, (char_u *)"id", -1) != NULL)) + { + EMSG(_(e_invarg)); + return; + } + li = li->li_next; + } + + clear_matches(curwin); + li = l->lv_first; + while (li != NULL) + { + d = li->li_tv.vval.v_dict; + match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE), + get_dict_string(d, (char_u *)"pattern", FALSE), + (int)get_dict_number(d, (char_u *)"priority"), + (int)get_dict_number(d, (char_u *)"id")); + li = li->li_next; + } + rettv->vval.v_number = 0; + } +#endif +} + +/* * "setpos()" function */ /*ARGSUSED*/ diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 3605a422ca..0d889942d0 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -10817,12 +10817,13 @@ ex_match(eap) exarg_T *eap; { char_u *p; + char_u *g; char_u *end; int c; - int mi; + int id; if (eap->line2 <= 3) - mi = eap->line2 - 1; + id = eap->line2; else { EMSG(e_invcmd); @@ -10831,13 +10832,7 @@ ex_match(eap) /* First clear any old pattern. */ if (!eap->skip) - { - vim_free(curwin->w_match[mi].regprog); - curwin->w_match[mi].regprog = NULL; - vim_free(curwin->w_match_pat[mi]); - curwin->w_match_pat[mi] = NULL; - redraw_later(SOME_VALID); /* always need a redraw */ - } + match_delete(curwin, id, FALSE); if (ends_excmd(*eap->arg)) end = eap->arg; @@ -10848,15 +10843,7 @@ ex_match(eap) { p = skiptowhite(eap->arg); if (!eap->skip) - { - curwin->w_match_id[mi] = syn_namen2id(eap->arg, - (int)(p - eap->arg)); - if (curwin->w_match_id[mi] == 0) - { - EMSG2(_(e_nogroup), eap->arg); - return; - } - } + g = vim_strnsave(eap->arg, (int)(p - eap->arg)); p = skipwhite(p); if (*p == NUL) { @@ -10880,14 +10867,8 @@ ex_match(eap) c = *end; *end = NUL; - curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC); - if (curwin->w_match[mi].regprog == NULL) - { - EMSG2(_(e_invarg2), p); - *end = c; - return; - } - curwin->w_match_pat[mi] = vim_strsave(p + 1); + match_add(curwin, g, p + 1, 10, id); + vim_free(g); *end = c; } } diff --git a/src/proto/window.pro b/src/proto/window.pro index 45a90b82a5..bcf171c9e6 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -59,4 +59,8 @@ int min_rows __ARGS((void)); int only_one_window __ARGS((void)); void check_lnums __ARGS((int do_curwin)); int win_hasvertsplit __ARGS((void)); +int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id)); +int match_delete __ARGS((win_T *wp, int id, int perr)); +void clear_matches __ARGS((win_T *wp)); +matchitem_T *get_match __ARGS((win_T *wp, int id)); /* vim: set ft=c : */ diff --git a/src/screen.c b/src/screen.c index 5c4faddedb..11344c317d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -100,27 +100,7 @@ static int screen_attr = 0; static int screen_cur_row, screen_cur_col; /* last known cursor position */ #ifdef FEAT_SEARCH_EXTRA -/* - * Struct used for highlighting 'hlsearch' matches for the last use search - * pattern or a ":match" item. - * For 'hlsearch' there is one pattern for all windows. For ":match" there is - * a different pattern for each window. - */ -typedef struct -{ - regmmatch_T rm; /* points to the regexp program; contains last found - match (may continue in next line) */ - buf_T *buf; /* the buffer to search for a match */ - linenr_T lnum; /* the line to search for a match */ - int attr; /* attributes to be used for a match */ - int attr_cur; /* attributes currently active in win_line() */ - linenr_T first_lnum; /* first lnum to search for multi-line pat */ - colnr_T startcol; /* in win_line() points to char where HL starts */ - colnr_T endcol; /* in win_line() points to char where HL ends */ -} match_T; - static match_T search_hl; /* used for 'hlsearch' highlight matching */ -static match_T match_hl[3]; /* used for ":match" highlight matching */ #endif #ifdef FEAT_FOLDING @@ -155,6 +135,7 @@ static void draw_vsep_win __ARGS((win_T *wp, int row)); static void redraw_custum_statusline __ARGS((win_T *wp)); #endif #ifdef FEAT_SEARCH_EXTRA +#define SEARCH_HL_PRIORITY 0 static void start_search_hl __ARGS((void)); static void end_search_hl __ARGS((void)); static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum)); @@ -787,6 +768,7 @@ win_update(wp) w_topline got smaller a bit */ #endif #ifdef FEAT_SEARCH_EXTRA + matchitem_T *cur; /* points to the match list */ int top_to_mod = FALSE; /* redraw above mod_top */ #endif @@ -848,18 +830,20 @@ win_update(wp) #endif #ifdef FEAT_SEARCH_EXTRA - /* Setup for ":match" and 'hlsearch' highlighting. Disable any previous + /* Setup for match and 'hlsearch' highlighting. Disable any previous * match */ - for (i = 0; i < 3; ++i) + cur = wp->w_match_head; + while (cur != NULL) { - match_hl[i].rm = wp->w_match[i]; - if (wp->w_match_id[i] == 0) - match_hl[i].attr = 0; + cur->hl.rm = cur->match; + if (cur->hlg_id == 0) + cur->hl.attr = 0; else - match_hl[i].attr = syn_id2attr(wp->w_match_id[i]); - match_hl[i].buf = buf; - match_hl[i].lnum = 0; - match_hl[i].first_lnum = 0; + cur->hl.attr = syn_id2attr(cur->hlg_id); + cur->hl.buf = buf; + cur->hl.lnum = 0; + cur->hl.first_lnum = 0; + cur = cur->next; } search_hl.buf = buf; search_hl.lnum = 0; @@ -923,19 +907,25 @@ win_update(wp) * change in one line may make the Search highlighting in a * previous line invalid. Simple solution: redraw all visible * lines above the change. - * Same for a ":match" pattern. + * Same for a match pattern. */ if (search_hl.rm.regprog != NULL && re_multiline(search_hl.rm.regprog)) top_to_mod = TRUE; else - for (i = 0; i < 3; ++i) - if (match_hl[i].rm.regprog != NULL - && re_multiline(match_hl[i].rm.regprog)) + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (cur->match.regprog != NULL + && re_multiline(cur->match.regprog)) { top_to_mod = TRUE; break; } + cur = cur->next; + } + } #endif } #ifdef FEAT_FOLDING @@ -2626,10 +2616,13 @@ win_line(wp, lnum, startrow, endrow, nochange) int line_attr = 0; /* atrribute for the whole line */ #endif #ifdef FEAT_SEARCH_EXTRA - match_T *shl; /* points to search_hl or match_hl */ -#endif -#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_MBYTE) - int i; + matchitem_T *cur; /* points to the match list */ + match_T *shl; /* points to search_hl or a match */ + int shl_flag; /* flag to indicate whether search_hl + has been processed or not */ + int prevcol_hl_flag; /* flag to indicate whether prevcol + equals startcol of search_hl or one + of the matches */ #endif #ifdef FEAT_ARABIC int prev_c = 0; /* previous Arabic character */ @@ -3074,12 +3067,20 @@ win_line(wp, lnum, startrow, endrow, nochange) #ifdef FEAT_SEARCH_EXTRA /* - * Handle highlighting the last used search pattern and ":match". - * Do this for both search_hl and match_hl[3]. + * Handle highlighting the last used search pattern and matches. + * Do this for both search_hl and the match list. */ - for (i = 3; i >= 0; --i) + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - shl = (i == 3) ? &search_hl : &match_hl[i]; + if (shl_flag == FALSE) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; @@ -3122,6 +3123,8 @@ win_line(wp, lnum, startrow, endrow, nochange) area_highlighting = TRUE; } } + if (shl != &search_hl && cur != NULL) + cur = cur->next; } #endif @@ -3388,13 +3391,24 @@ win_line(wp, lnum, startrow, endrow, nochange) * After end, check for start/end of next match. * When another match, have to check for start again. * Watch out for matching an empty string! - * Do this first for search_hl, then for match_hl, so that - * ":match" overrules 'hlsearch'. + * Do this for 'search_hl' and the match list (ordered by + * priority). */ v = (long)(ptr - line); - for (i = 3; i >= 0; --i) + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - shl = (i == 3) ? &search_hl : &match_hl[i]; + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; while (shl->rm.regprog != NULL) { if (shl->startcol != MAXCOL @@ -3442,17 +3456,32 @@ win_line(wp, lnum, startrow, endrow, nochange) } break; } + if (shl != &search_hl && cur != NULL) + cur = cur->next; } - /* ":match" highlighting overrules 'hlsearch' */ - for (i = 0; i <= 3; ++i) - if (i == 3) - search_attr = search_hl.attr_cur; - else if (match_hl[i].attr_cur != 0) + /* Use attributes from match with highest priority among + * 'search_hl' and the match list. */ + search_attr = search_hl.attr_cur; + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) + { + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) { - search_attr = match_hl[i].attr_cur; - break; + shl = &search_hl; + shl_flag = TRUE; } + else + shl = &cur->hl; + if (shl->attr_cur != 0) + search_attr = shl->attr_cur; + if (shl != &search_hl && cur != NULL) + cur = cur->next; + } } #endif @@ -3613,6 +3642,8 @@ win_line(wp, lnum, startrow, endrow, nochange) * Draw it as a space with a composing char. */ if (utf_iscomposing(mb_c)) { + int i; + for (i = Screen_mco - 1; i > 0; --i) u8cc[i] = u8cc[i - 1]; u8cc[0] = mb_c; @@ -4256,14 +4287,29 @@ win_line(wp, lnum, startrow, endrow, nochange) * highlight match at end of line. If it's beyond the last * char on the screen, just overwrite that one (tricky!) Not * needed when a '$' was displayed for 'list'. */ +#ifdef FEAT_SEARCH_EXTRA + prevcol_hl_flag = FALSE; + if (prevcol == (long)search_hl.startcol) + prevcol_hl_flag = TRUE; + else + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (prevcol == (long)cur->hl.startcol) + { + prevcol_hl_flag = TRUE; + break; + } + cur = cur->next; + } + } +#endif if (lcs_eol == lcs_eol_one && ((area_attr != 0 && vcol == fromcol && c == NUL) #ifdef FEAT_SEARCH_EXTRA /* highlight 'hlsearch' match at end of line */ - || ((prevcol == (long)search_hl.startcol - || prevcol == (long)match_hl[0].startcol - || prevcol == (long)match_hl[1].startcol - || prevcol == (long)match_hl[2].startcol) + || (prevcol_hl_flag == TRUE # if defined(LINE_ATTR) && did_line_attr <= 1 # endif @@ -4304,15 +4350,27 @@ win_line(wp, lnum, startrow, endrow, nochange) #ifdef FEAT_SEARCH_EXTRA if (area_attr == 0) { - for (i = 0; i <= 3; ++i) + /* Use attributes from match with highest priority among + * 'search_hl' and the match list. */ + char_attr = search_hl.attr; + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - if (i == 3) - char_attr = search_hl.attr; - else if ((ptr - line) - 1 == (long)match_hl[i].startcol) + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) { - char_attr = match_hl[i].attr; - break; + shl = &search_hl; + shl_flag = TRUE; } + else + shl = &cur->hl; + if ((ptr - line) - 1 == (long)shl->startcol) + char_attr = shl->attr; + if (shl != &search_hl && cur != NULL) + cur = cur->next; } } #endif @@ -4462,6 +4520,8 @@ win_line(wp, lnum, startrow, endrow, nochange) { if (mb_utf8) { + int i; + ScreenLinesUC[off] = mb_c; if ((c & 0xff) == 0) ScreenLines[off] = 0x80; /* avoid storing zero */ @@ -6320,7 +6380,7 @@ screen_puts_len(text, len, row, col, attr) #ifdef FEAT_SEARCH_EXTRA /* - * Prepare for 'searchhl' highlighting. + * Prepare for 'hlsearch' highlighting. */ static void start_search_hl() @@ -6333,7 +6393,7 @@ start_search_hl() } /* - * Clean up for 'searchhl' highlighting. + * Clean up for 'hlsearch' highlighting. */ static void end_search_hl() @@ -6353,18 +6413,28 @@ prepare_search_hl(wp, lnum) win_T *wp; linenr_T lnum; { - match_T *shl; /* points to search_hl or match_hl */ + matchitem_T *cur; /* points to the match list */ + match_T *shl; /* points to search_hl or a match */ + int shl_flag; /* flag to indicate whether search_hl + has been processed or not */ int n; - int i; /* * When using a multi-line pattern, start searching at the top * of the window or just after a closed fold. - * Do this both for search_hl and match_hl[3]. + * Do this both for search_hl and the match list. */ - for (i = 3; i >= 0; --i) + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - shl = (i == 3) ? &search_hl : &match_hl[i]; + if (shl_flag == FALSE) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; if (shl->rm.regprog != NULL && shl->lnum == 0 && re_multiline(shl->rm.regprog)) @@ -6399,11 +6469,13 @@ prepare_search_hl(wp, lnum) } } } + if (shl != &search_hl & |