mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
vim-patch: 7.4.330
Problem: Using a regexp pattern to highlight a specific position can be slow. Solution: Add matchaddpos() to highlight specific positions efficiently. (Alexey Radkov.) https://code.google.com/p/vim/source/detail?r=f9fa2e506b9f07549cd91074835c5c553db7b3a7
This commit is contained in:
parent
057f26f0a6
commit
bf3d945798
@ -880,6 +880,28 @@ typedef struct {
|
||||
proftime_T tm; /* for a time limit */
|
||||
} match_T;
|
||||
|
||||
/// number of positions supported by matchaddpos()
|
||||
#define MAXPOSMATCH 8
|
||||
|
||||
/// Same as lpos_T, but with additional field len.
|
||||
typedef struct
|
||||
{
|
||||
linenr_T lnum; ///< line number
|
||||
colnr_T col; ///< column number
|
||||
int len; ///< length: 0 - to the end of line
|
||||
} llpos_T;
|
||||
|
||||
/// posmatch_T provides an array for storing match items for matchaddpos()
|
||||
/// function.
|
||||
typedef struct posmatch posmatch_T;
|
||||
struct posmatch
|
||||
{
|
||||
llpos_T pos[MAXPOSMATCH]; ///< array of positions
|
||||
int cur; ///< internal position counter
|
||||
linenr_T toplnum; ///< top buffer line
|
||||
linenr_T botlnum; ///< bottom buffer line
|
||||
};
|
||||
|
||||
/*
|
||||
* matchitem_T provides a linked list for storing match items for ":match" and
|
||||
* the match functions.
|
||||
@ -892,6 +914,7 @@ struct matchitem {
|
||||
char_u *pattern; /* pattern to highlight */
|
||||
int hlg_id; /* highlight group ID */
|
||||
regmmatch_T match; /* regexp program for pattern */
|
||||
posmatch_T pos; // position matches
|
||||
match_T hl; /* struct for doing the actual highlighting */
|
||||
};
|
||||
|
||||
|
@ -6456,6 +6456,7 @@ static struct fst {
|
||||
{"mapcheck", 1, 3, f_mapcheck},
|
||||
{"match", 2, 4, f_match},
|
||||
{"matchadd", 2, 4, f_matchadd},
|
||||
{"matchaddpos", 2, 4, f_matchaddpos},
|
||||
{"matcharg", 1, 1, f_matcharg},
|
||||
{"matchdelete", 1, 1, f_matchdelete},
|
||||
{"matchend", 2, 4, f_matchend},
|
||||
@ -9300,12 +9301,34 @@ static void f_getline(typval_T *argvars, typval_T *rettv)
|
||||
static void f_getmatches(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
matchitem_T *cur = curwin->w_match_head;
|
||||
int i;
|
||||
|
||||
rettv_list_alloc(rettv);
|
||||
while (cur != NULL) {
|
||||
dict_T *dict = dict_alloc();
|
||||
if (cur->match.regprog == NULL) {
|
||||
// match added with matchaddpos()
|
||||
for (i = 0; i < MAXPOSMATCH; ++i) {
|
||||
llpos_T *llpos;
|
||||
char buf[6];
|
||||
|
||||
llpos = &cur->pos.pos[i];
|
||||
if (llpos->lnum == 0) {
|
||||
break;
|
||||
}
|
||||
list_T *l = list_alloc();
|
||||
list_append_number(l, (varnumber_T)llpos->lnum);
|
||||
if (llpos->col > 0) {
|
||||
list_append_number(l, (varnumber_T)llpos->col);
|
||||
list_append_number(l, (varnumber_T)llpos->len);
|
||||
}
|
||||
sprintf(buf, "pos%d", i + 1);
|
||||
dict_add_list(dict, buf, l);
|
||||
}
|
||||
} else {
|
||||
dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
|
||||
}
|
||||
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);
|
||||
@ -11104,7 +11127,52 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
|
||||
return;
|
||||
}
|
||||
|
||||
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
|
||||
rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
|
||||
}
|
||||
|
||||
static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
rettv->vval.v_number = -1;
|
||||
|
||||
char_u buf[NUMBUFLEN];
|
||||
char_u *group;
|
||||
group = get_tv_string_buf_chk(&argvars[0], buf);
|
||||
if (group == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[1].v_type != VAR_LIST) {
|
||||
EMSG2(_(e_listarg), "matchaddpos()");
|
||||
return;
|
||||
}
|
||||
|
||||
list_T *l;
|
||||
l = argvars[1].vval.v_list;
|
||||
if (l == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int error = false;
|
||||
int prio = 10;
|
||||
int id = -1;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||
prio = get_tv_number_chk(&argvars[2], &error);
|
||||
if (argvars[3].v_type != VAR_UNKNOWN) {
|
||||
id = get_tv_number_chk(&argvars[3], &error);
|
||||
}
|
||||
}
|
||||
if (error == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// id == 3 is ok because matchaddpos() is supposed to substitute :3match
|
||||
if (id == 1 || id == 2) {
|
||||
EMSGN("E798: ID is reserved for \"match\": %" PRId64, id);
|
||||
return;
|
||||
}
|
||||
|
||||
rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -12914,7 +12982,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
|
||||
match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
|
||||
get_dict_string(d, (char_u *)"pattern", FALSE),
|
||||
(int)get_dict_number(d, (char_u *)"priority"),
|
||||
(int)get_dict_number(d, (char_u *)"id"));
|
||||
(int)get_dict_number(d, (char_u *)"id"), NULL);
|
||||
li = li->li_next;
|
||||
}
|
||||
rettv->vval.v_number = 0;
|
||||
|
@ -8859,7 +8859,7 @@ static void ex_match(exarg_T *eap)
|
||||
|
||||
c = *end;
|
||||
*end = NUL;
|
||||
match_add(curwin, g, p + 1, 10, id);
|
||||
match_add(curwin, g, p + 1, 10, id, NULL);
|
||||
free(g);
|
||||
*end = c;
|
||||
}
|
||||
|
@ -2658,38 +2658,42 @@ win_line (
|
||||
shl->startcol = MAXCOL;
|
||||
shl->endcol = MAXCOL;
|
||||
shl->attr_cur = 0;
|
||||
if (shl->rm.regprog != NULL) {
|
||||
v = (long)(ptr - line);
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v);
|
||||
v = (long)(ptr - line);
|
||||
if (cur != NULL) {
|
||||
cur->pos.cur = 0;
|
||||
}
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
|
||||
|
||||
/* Need to get the line again, a multi-line regexp may have made it
|
||||
* invalid. */
|
||||
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||
ptr = line + v;
|
||||
// Need to get the line again, a multi-line regexp may have made it
|
||||
// invalid.
|
||||
line = ml_get_buf(wp->w_buffer, lnum, false);
|
||||
ptr = line + v;
|
||||
|
||||
if (shl->lnum != 0 && shl->lnum <= lnum) {
|
||||
if (shl->lnum == lnum)
|
||||
shl->startcol = shl->rm.startpos[0].col;
|
||||
else
|
||||
shl->startcol = 0;
|
||||
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
|
||||
- shl->rm.startpos[0].lnum)
|
||||
shl->endcol = shl->rm.endpos[0].col;
|
||||
else
|
||||
shl->endcol = MAXCOL;
|
||||
/* Highlight one character for an empty match. */
|
||||
if (shl->startcol == shl->endcol) {
|
||||
if (has_mbyte && line[shl->endcol] != NUL)
|
||||
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
|
||||
else
|
||||
++shl->endcol;
|
||||
}
|
||||
if ((long)shl->startcol < v) { /* match at leftcol */
|
||||
shl->attr_cur = shl->attr;
|
||||
search_attr = shl->attr;
|
||||
}
|
||||
area_highlighting = TRUE;
|
||||
if (shl->lnum != 0 && shl->lnum <= lnum) {
|
||||
if (shl->lnum == lnum) {
|
||||
shl->startcol = shl->rm.startpos[0].col;
|
||||
} else {
|
||||
shl->startcol = 0;
|
||||
}
|
||||
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
|
||||
- shl->rm.startpos[0].lnum) {
|
||||
shl->endcol = shl->rm.endpos[0].col;
|
||||
} else {
|
||||
shl->endcol = MAXCOL;
|
||||
}
|
||||
// Highlight one character for an empty match.
|
||||
if (shl->startcol == shl->endcol) {
|
||||
if (has_mbyte && line[shl->endcol] != NUL) {
|
||||
shl->endcol += (*mb_ptr2len)(line + shl->endcol);
|
||||
} else {
|
||||
++shl->endcol;
|
||||
}
|
||||
}
|
||||
if ((long)shl->startcol < v) { // match at leftcol
|
||||
shl->attr_cur = shl->attr;
|
||||
search_attr = shl->attr;
|
||||
}
|
||||
area_highlighting = true;
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL)
|
||||
cur = cur->next;
|
||||
@ -2699,9 +2703,9 @@ win_line (
|
||||
* when Visual mode is active, because it's not clear what is selected
|
||||
* then. */
|
||||
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
|
||||
&& !(wp == curwin && VIsual_active)) {
|
||||
&& !(wp == curwin && VIsual_active)) {
|
||||
line_attr = hl_attr(HLF_CUL);
|
||||
area_highlighting = TRUE;
|
||||
area_highlighting = true;
|
||||
}
|
||||
|
||||
off = (unsigned)(current_ScreenLine - ScreenLines);
|
||||
@ -2942,7 +2946,13 @@ win_line (
|
||||
shl_flag = TRUE;
|
||||
} else
|
||||
shl = &cur->hl;
|
||||
while (shl->rm.regprog != NULL) {
|
||||
if (cur != NULL) {
|
||||
cur->pos.cur = 0;
|
||||
}
|
||||
bool pos_inprogress = true; // mark that a position match search is
|
||||
// in progress
|
||||
while (shl->rm.regprog != NULL
|
||||
|| (cur != NULL && pos_inprogress)) {
|
||||
if (shl->startcol != MAXCOL
|
||||
&& v >= (long)shl->startcol
|
||||
&& v < (long)shl->endcol) {
|
||||
@ -2950,7 +2960,8 @@ win_line (
|
||||
} else if (v == (long)shl->endcol) {
|
||||
shl->attr_cur = 0;
|
||||
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v);
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
|
||||
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||
|
||||
/* Need to get the line again, a multi-line regexp
|
||||
* may have made it invalid. */
|
||||
@ -5602,9 +5613,16 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
|
||||
NULL, NULL, TRUE, NULL))
|
||||
break;
|
||||
}
|
||||
if (cur != NULL) {
|
||||
cur->pos.cur = 0;
|
||||
}
|
||||
bool pos_inprogress = true; // mark that a position match search is
|
||||
// in progress
|
||||
n = 0;
|
||||
while (shl->first_lnum < lnum && shl->rm.regprog != NULL) {
|
||||
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n);
|
||||
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
|
||||
|| (cur != NULL && pos_inprogress))) {
|
||||
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n, cur);
|
||||
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||
if (shl->lnum != 0) {
|
||||
shl->first_lnum = shl->lnum
|
||||
+ shl->rm.endpos[0].lnum
|
||||
@ -5634,12 +5652,13 @@ next_search_hl (
|
||||
win_T *win,
|
||||
match_T *shl, /* points to search_hl or a match */
|
||||
linenr_T lnum,
|
||||
colnr_T mincol /* minimal column for a match */
|
||||
colnr_T mincol, /* minimal column for a match */
|
||||
matchitem_T *cur /* to retrieve match positions if any */
|
||||
)
|
||||
{
|
||||
linenr_T l;
|
||||
colnr_T matchcol;
|
||||
long nmatched;
|
||||
long nmatched = 0;
|
||||
|
||||
if (shl->lnum != 0) {
|
||||
/* Check for three situations:
|
||||
@ -5674,8 +5693,8 @@ next_search_hl (
|
||||
if (shl->lnum == 0)
|
||||
matchcol = 0;
|
||||
else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL
|
||||
|| (shl->rm.endpos[0].lnum == 0
|
||||
&& shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) {
|
||||
|| (shl->rm.endpos[0].lnum == 0
|
||||
&& shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) {
|
||||
char_u *ml;
|
||||
|
||||
matchcol = shl->rm.startpos[0].col;
|
||||
@ -5693,20 +5712,23 @@ next_search_hl (
|
||||
matchcol = shl->rm.endpos[0].col;
|
||||
|
||||
shl->lnum = lnum;
|
||||
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
|
||||
&(shl->tm)
|
||||
);
|
||||
if (called_emsg || got_int) {
|
||||
/* Error while handling regexp: stop using this regexp. */
|
||||
if (shl == &search_hl) {
|
||||
/* don't free regprog in the match list, it's a copy */
|
||||
vim_regfree(shl->rm.regprog);
|
||||
SET_NO_HLSEARCH(TRUE);
|
||||
if (shl->rm.regprog != NULL) {
|
||||
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
|
||||
if (called_emsg || got_int) {
|
||||
// Error while handling regexp: stop using this regexp.
|
||||
if (shl == &search_hl) {
|
||||
// don't free regprog in the match list, it's a copy
|
||||
vim_regfree(shl->rm.regprog);
|
||||
SET_NO_HLSEARCH(TRUE);
|
||||
}
|
||||
shl->rm.regprog = NULL;
|
||||
shl->lnum = 0;
|
||||
got_int = FALSE; /* avoid the "Type :quit to exit Vim"
|
||||
message */
|
||||
break;
|
||||
}
|
||||
shl->rm.regprog = NULL;
|
||||
shl->lnum = 0;
|
||||
got_int = FALSE; /* avoid the "Type :quit to exit Vim" message */
|
||||
break;
|
||||
} else if (cur != NULL) {
|
||||
nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
|
||||
}
|
||||
if (nmatched == 0) {
|
||||
shl->lnum = 0; /* no match found */
|
||||
@ -5722,6 +5744,59 @@ next_search_hl (
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
next_search_hl_pos(
|
||||
match_T *shl, // points to a match
|
||||
linenr_T lnum,
|
||||
posmatch_T *posmatch, // match positions
|
||||
colnr_T mincol // minimal column for a match
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int bot = -1;
|
||||
|
||||
shl->lnum = 0;
|
||||
for (i = posmatch->cur; i < MAXPOSMATCH; i++) {
|
||||
if (posmatch->pos[i].lnum == 0) {
|
||||
break;
|
||||
}
|
||||
if (posmatch->pos[i].col < mincol) {
|
||||
continue;
|
||||
}
|
||||
if (posmatch->pos[i].lnum == lnum) {
|
||||
if (shl->lnum == lnum) {
|
||||
// partially sort positions by column numbers
|
||||
// on the same line
|
||||
if (posmatch->pos[i].col < posmatch->pos[bot].col) {
|
||||
llpos_T tmp = posmatch->pos[i];
|
||||
|
||||
posmatch->pos[i] = posmatch->pos[bot];
|
||||
posmatch->pos[bot] = tmp;
|
||||
}
|
||||
} else {
|
||||
bot = i;
|
||||
shl->lnum = lnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
posmatch->cur = 0;
|
||||
if (shl->lnum == lnum) {
|
||||
colnr_T start = posmatch->pos[bot].col == 0
|
||||
? 0: posmatch->pos[bot].col - 1;
|
||||
colnr_T end = posmatch->pos[bot].col == 0
|
||||
? MAXCOL : start + posmatch->pos[bot].len;
|
||||
|
||||
shl->rm.startpos[0].lnum = 0;
|
||||
shl->rm.startpos[0].col = start;
|
||||
shl->rm.endpos[0].lnum = 0;
|
||||
shl->rm.endpos[0].col = end;
|
||||
posmatch->cur = bot + 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void screen_start_highlight(int attr)
|
||||
{
|
||||
attrentry_T *aep = NULL;
|
||||
|
@ -1,5 +1,5 @@
|
||||
Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
|
||||
"matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
|
||||
"matchadd()", "matchaddpos()", "matcharg()", "matchdelete()", and "setmatches()".
|
||||
|
||||
STARTTEST
|
||||
:so small.vim
|
||||
@ -147,9 +147,26 @@ STARTTEST
|
||||
:unlet rf1
|
||||
:unlet rf2
|
||||
:unlet rf3
|
||||
:highlight clear MyGroup1
|
||||
:highlight clear MyGroup2
|
||||
:highlight clear MyGroup3
|
||||
:" --- Check that "matchaddpos()" positions matches correctly
|
||||
:let @r .= "*** Test 11:\n"
|
||||
:set nolazyredraw
|
||||
:call setline(1, 'abcdefghijklmnopq')
|
||||
:call matchaddpos("MyGroup1", [[1, 5], [1, 8, 3]], 10, 3)
|
||||
:1
|
||||
:redraw!
|
||||
:let v1 = screenattr(1, 1)
|
||||
:let v5 = screenattr(1, 5)
|
||||
:let v6 = screenattr(1, 6)
|
||||
:let v8 = screenattr(1, 8)
|
||||
:let v10 = screenattr(1, 10)
|
||||
:let v11 = screenattr(1, 11)
|
||||
:let @r .= string(getmatches())."\n"
|
||||
:if v1 != v5 && v6 == v1 && v8 == v5 && v10 == v5 && v11 == v1
|
||||
: let @r .= "OK\n"
|
||||
:else
|
||||
: let @r .= "FAILED\n"
|
||||
:endif
|
||||
:call clearmatches()
|
||||
G"rp
|
||||
:/^Results/,$wq! test.out
|
||||
ENDTEST
|
||||
|
@ -9,3 +9,6 @@ Results of test63:
|
||||
*** Test 8: OK
|
||||
*** Test 9: OK
|
||||
*** Test 10: OK
|
||||
*** Test 11:
|
||||
[{'group': 'MyGroup1', 'id': 3, 'priority': 10, 'pos1': [1, 5, 1], 'pos2': [1, 8, 3]}]
|
||||
OK
|
||||
|
@ -265,7 +265,7 @@ static int included_patches[] = {
|
||||
//333 NA
|
||||
//332 NA
|
||||
331,
|
||||
//330,
|
||||
330,
|
||||
329,
|
||||
328,
|
||||
327,
|
||||
|
@ -5190,16 +5190,18 @@ void restore_buffer(buf_T *save_curbuf)
|
||||
* If no particular ID is desired, -1 must be specified for 'id'.
|
||||
* Return ID of added match, -1 on failure.
|
||||
*/
|
||||
int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
||||
int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)
|
||||
{
|
||||
matchitem_T *cur;
|
||||
matchitem_T *prev;
|
||||
matchitem_T *m;
|
||||
int hlg_id;
|
||||
regprog_T *regprog;
|
||||
regprog_T *regprog = NULL;
|
||||
int rtype = SOME_VALID;
|
||||
|
||||
if (*grp == NUL || *pat == NUL)
|
||||
if (*grp == NUL || (pat != NULL && *pat == NUL)) {
|
||||
return -1;
|
||||
}
|
||||
if (id < -1 || id == 0) {
|
||||
EMSGN("E799: Invalid ID: %" PRId64
|
||||
" (must be greater than or equal to 1)",
|
||||
@ -5220,7 +5222,7 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
||||
EMSG2(_(e_nogroup), grp);
|
||||
return -1;
|
||||
}
|
||||
if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
|
||||
if (pat != NULL && (regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) {
|
||||
EMSG2(_(e_invarg2), pat);
|
||||
return -1;
|
||||
}
|
||||
@ -5236,15 +5238,108 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
||||
}
|
||||
|
||||
/* Build new match. */
|
||||
m = xmalloc(sizeof(matchitem_T));
|
||||
m = xcalloc(1, sizeof(matchitem_T));
|
||||
m->id = id;
|
||||
m->priority = prio;
|
||||
m->pattern = vim_strsave(pat);
|
||||
m->pattern = pat == NULL ? NULL: vim_strsave(pat);
|
||||
m->pos.cur = 0;
|
||||
m->hlg_id = hlg_id;
|
||||
m->match.regprog = regprog;
|
||||
m->match.rmm_ic = FALSE;
|
||||
m->match.rmm_maxcol = 0;
|
||||
|
||||
// Set up position matches
|
||||
if (pos_list != NULL)
|
||||
{
|
||||
linenr_T toplnum = 0;
|
||||
linenr_T botlnum = 0;
|
||||
listitem_T *li;
|
||||
int i;
|
||||
|
||||
for (i = 0, li = pos_list->lv_first; i < MAXPOSMATCH;
|
||||
i++, li = li->li_next) {
|
||||
linenr_T lnum = 0;
|
||||
colnr_T col = 0;
|
||||
int len = 1;
|
||||
list_T *subl;
|
||||
listitem_T *subli;
|
||||
int error;
|
||||
|
||||
if (li == NULL) {
|
||||
m->pos.pos[i].lnum = 0;
|
||||
break;
|
||||
}
|
||||
if (li->li_tv.v_type == VAR_LIST) {
|
||||
subl = li->li_tv.vval.v_list;
|
||||
if (subl == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
subli = subl->lv_first;
|
||||
if (subli == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
lnum = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == TRUE) {
|
||||
goto fail;
|
||||
}
|
||||
m->pos.pos[i].lnum = lnum;
|
||||
if (lnum == 0) {
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
subli = subli->li_next;
|
||||
if (subli != NULL) {
|
||||
col = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == TRUE)
|
||||
goto fail;
|
||||
subli = subli->li_next;
|
||||
if (subli != NULL) {
|
||||
len = get_tv_number_chk(&subli->li_tv, &error);
|
||||
if (error == true) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
m->pos.pos[i].col = col;
|
||||
m->pos.pos[i].len = len;
|
||||
} else if (li->li_tv.v_type == VAR_NUMBER) {
|
||||
if (li->li_tv.vval.v_number == 0)
|
||||
continue;
|
||||
m->pos.pos[i].lnum = li->li_tv.vval.v_number;
|
||||
m->pos.pos[i].col = 0;
|
||||
m->pos.pos[i].len = 0;
|
||||
} else {
|
||||
EMSG(_("List or number required"));
|
||||
goto fail;
|
||||
}
|
||||
if (toplnum == 0 || lnum < toplnum) {
|
||||
toplnum = lnum;
|
||||
}
|
||||
if (botlnum == 0 || lnum > botlnum) {
|
||||
botlnum = lnum;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate top and bottom lines for redrawing area
|
||||
if (toplnum != 0){
|
||||
if (wp->w_buffer->b_mod_set) {
|
||||
if (wp->w_buffer->b_mod_top > toplnum) {
|
||||
wp->w_buffer->b_mod_top = toplnum;
|
||||
}
|
||||
if (wp->w_buffer->b_mod_bot < botlnum) {
|
||||
wp->w_buffer->b_mod_bot = botlnum;
|
||||
}
|
||||
} else {
|
||||
wp->w_buffer->b_mod_top = toplnum;
|
||||
wp->w_buffer->b_mod_bot = botlnum;
|
||||
}
|
||||
m->pos.toplnum = toplnum;
|
||||
m->pos.botlnum = botlnum;
|
||||
wp->w_buffer->b_mod_set = TRUE;
|
||||
rtype = VALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert new match. The match list is in ascending order with regard to
|
||||
* the match priorities. */
|
||||
cur = wp->w_match_head;
|
||||
@ -5259,8 +5354,12 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id)
|
||||
prev->next = m;
|
||||
m->next = cur;
|
||||
|
||||
redraw_later(SOME_VALID);
|
||||
redraw_later(rtype);
|
||||
return id;
|
||||
|
||||
fail:
|
||||
free(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5271,6 +5370,7 @@ int match_delete(win_T *wp, int id, int perr)
|
||||
{
|
||||
matchitem_T *cur = wp->w_match_head;
|
||||
matchitem_T *prev = cur;
|
||||
int rtype = SOME_VALID;
|
||||
|
||||
if (id < 1) {
|
||||
if (perr == TRUE)
|
||||
@ -5294,8 +5394,23 @@ int match_delete(win_T *wp, int id, int perr)
|
||||
prev->next = cur->next;
|
||||
vim_regfree(cur->match.regprog);
|
||||
free(cur->pattern);
|
||||
if (cur->pos.toplnum != 0) {
|
||||
if (wp->w_buffer->b_mod_set) {
|
||||
if (wp->w_buffer->b_mod_top > cur->pos.toplnum) {
|
||||
wp->w_buffer->b_mod_top = cur->pos.toplnum;
|
||||
}
|
||||
if (wp->w_buffer->b_mod_bot < cur->pos.botlnum) {
|
||||
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
|
||||
}
|
||||
} else {
|
||||
wp->w_buffer->b_mod_top = cur->pos.toplnum;
|
||||
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
|
||||
}
|
||||
wp->w_buffer->b_mod_set = TRUE;
|
||||
rtype = VALID;
|
||||
}
|
||||
free(cur);
|
||||
redraw_later(SOME_VALID);
|
||||
redraw_later(rtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user