mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #17760 from lewis6991/vim-patch-8.1.1734
vim-patch:8.1.{1734,1742,1743}: highlight, match and screen.c refactoring
This commit is contained in:
commit
18900758c3
@ -68,7 +68,6 @@ static char *e_illvar = N_("E461: Illegal variable name: %s");
|
||||
static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
|
||||
static char *e_nowhitespace
|
||||
= N_("E274: No white space allowed before parenthesis");
|
||||
static char *e_invalwindow = N_("E957: Invalid window number");
|
||||
static char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s");
|
||||
static char *e_write2 = N_("E80: Error while writing: %s");
|
||||
static char *e_string_list_or_blob_required = N_("E1098: String, List or Blob required");
|
||||
@ -7323,30 +7322,6 @@ void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, long buf
|
||||
tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);
|
||||
}
|
||||
|
||||
int matchadd_dict_arg(typval_T *tv, const char **conceal_char, win_T **win)
|
||||
{
|
||||
dictitem_T *di;
|
||||
|
||||
if (tv->v_type != VAR_DICT) {
|
||||
emsg(_(e_dictreq));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if ((di = tv_dict_find(tv->vval.v_dict, S_LEN("conceal"))) != NULL) {
|
||||
*conceal_char = tv_get_string(&di->di_tv);
|
||||
}
|
||||
|
||||
if ((di = tv_dict_find(tv->vval.v_dict, S_LEN("window"))) != NULL) {
|
||||
*win = find_win_by_nr_or_id(&di->di_tv);
|
||||
if (*win == NULL) {
|
||||
emsg(_(e_invalwindow));
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void return_register(int regname, typval_T *rettv)
|
||||
{
|
||||
char_u buf[2] = { regname, 0 };
|
||||
|
@ -1124,7 +1124,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
static win_T *get_optional_window(typval_T *argvars, int idx)
|
||||
win_T *get_optional_window(typval_T *argvars, int idx)
|
||||
{
|
||||
win_T *win = curwin;
|
||||
|
||||
@ -1138,16 +1138,6 @@ static win_T *get_optional_window(typval_T *argvars, int idx)
|
||||
return win;
|
||||
}
|
||||
|
||||
/// "clearmatches()" function
|
||||
static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
win_T *win = get_optional_window(argvars, 0);
|
||||
|
||||
if (win != NULL) {
|
||||
clear_matches(win);
|
||||
}
|
||||
}
|
||||
|
||||
/// "col(string)" function
|
||||
static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
@ -3669,61 +3659,6 @@ static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
get_buf_local_marks(buf, rettv->vval.v_list);
|
||||
}
|
||||
|
||||
/// "getmatches()" function
|
||||
static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
matchitem_T *cur;
|
||||
int i;
|
||||
win_T *win = get_optional_window(argvars, 0);
|
||||
|
||||
if (win == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
tv_list_alloc_ret(rettv, kListLenMayKnow);
|
||||
cur = win->w_match_head;
|
||||
while (cur != NULL) {
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
if (cur->match.regprog == NULL) {
|
||||
// match added with matchaddpos()
|
||||
for (i = 0; i < MAXPOSMATCH; i++) {
|
||||
llpos_T *llpos;
|
||||
char buf[30]; // use 30 to avoid compiler warning
|
||||
|
||||
llpos = &cur->pos.pos[i];
|
||||
if (llpos->lnum == 0) {
|
||||
break;
|
||||
}
|
||||
list_T *const l = tv_list_alloc(1 + (llpos->col > 0 ? 2 : 0));
|
||||
tv_list_append_number(l, (varnumber_T)llpos->lnum);
|
||||
if (llpos->col > 0) {
|
||||
tv_list_append_number(l, (varnumber_T)llpos->col);
|
||||
tv_list_append_number(l, (varnumber_T)llpos->len);
|
||||
}
|
||||
int len = snprintf(buf, sizeof(buf), "pos%d", i + 1);
|
||||
assert((size_t)len < sizeof(buf));
|
||||
tv_dict_add_list(dict, buf, (size_t)len, l);
|
||||
}
|
||||
} else {
|
||||
tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cur->pattern);
|
||||
}
|
||||
tv_dict_add_str(dict, S_LEN("group"),
|
||||
(const char *)syn_id2name(cur->hlg_id));
|
||||
tv_dict_add_nr(dict, S_LEN("priority"), (varnumber_T)cur->priority);
|
||||
tv_dict_add_nr(dict, S_LEN("id"), (varnumber_T)cur->id);
|
||||
|
||||
if (cur->conceal_char) {
|
||||
char buf[MB_MAXBYTES + 1];
|
||||
|
||||
buf[utf_char2bytes(cur->conceal_char, (char_u *)buf)] = NUL;
|
||||
tv_dict_add_str(dict, S_LEN("conceal"), buf);
|
||||
}
|
||||
|
||||
tv_list_append_dict(rettv->vval.v_list, dict);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
/// "getmousepos()" function
|
||||
static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
@ -6108,133 +6043,6 @@ static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
find_some_match(argvars, rettv, kSomeMatch);
|
||||
}
|
||||
|
||||
/// "matchadd()" function
|
||||
static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
char grpbuf[NUMBUFLEN];
|
||||
char patbuf[NUMBUFLEN];
|
||||
// group
|
||||
const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf);
|
||||
// pattern
|
||||
const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf);
|
||||
// default priority
|
||||
int prio = 10;
|
||||
int id = -1;
|
||||
bool error = false;
|
||||
const char *conceal_char = NULL;
|
||||
win_T *win = curwin;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
|
||||
if (grp == NULL || pat == NULL) {
|
||||
return;
|
||||
}
|
||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||
prio = tv_get_number_chk(&argvars[2], &error);
|
||||
if (argvars[3].v_type != VAR_UNKNOWN) {
|
||||
id = tv_get_number_chk(&argvars[3], &error);
|
||||
if (argvars[4].v_type != VAR_UNKNOWN
|
||||
&& matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
if (id >= 1 && id <= 3) {
|
||||
semsg(_("E798: ID is reserved for \":match\": %" PRId64), (int64_t)id);
|
||||
return;
|
||||
}
|
||||
|
||||
rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL, conceal_char);
|
||||
}
|
||||
|
||||
static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
rettv->vval.v_number = -1;
|
||||
|
||||
char buf[NUMBUFLEN];
|
||||
const char *const group = tv_get_string_buf_chk(&argvars[0], buf);
|
||||
if (group == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[1].v_type != VAR_LIST) {
|
||||
semsg(_(e_listarg), "matchaddpos()");
|
||||
return;
|
||||
}
|
||||
|
||||
list_T *l;
|
||||
l = argvars[1].vval.v_list;
|
||||
if (l == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
int prio = 10;
|
||||
int id = -1;
|
||||
const char *conceal_char = NULL;
|
||||
win_T *win = curwin;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||
prio = tv_get_number_chk(&argvars[2], &error);
|
||||
if (argvars[3].v_type != VAR_UNKNOWN) {
|
||||
id = tv_get_number_chk(&argvars[3], &error);
|
||||
if (argvars[4].v_type != VAR_UNKNOWN
|
||||
&& matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// id == 3 is ok because matchaddpos() is supposed to substitute :3match
|
||||
if (id == 1 || id == 2) {
|
||||
semsg(_("E798: ID is reserved for \"match\": %" PRId64), (int64_t)id);
|
||||
return;
|
||||
}
|
||||
|
||||
rettv->vval.v_number = match_add(win, group, NULL, prio, id, l, conceal_char);
|
||||
}
|
||||
|
||||
/// "matcharg()" function
|
||||
static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
const int id = tv_get_number(&argvars[0]);
|
||||
|
||||
tv_list_alloc_ret(rettv, (id >= 1 && id <= 3
|
||||
? 2
|
||||
: 0));
|
||||
|
||||
if (id >= 1 && id <= 3) {
|
||||
matchitem_T *const m = get_match(curwin, id);
|
||||
|
||||
if (m != NULL) {
|
||||
tv_list_append_string(rettv->vval.v_list,
|
||||
(const char *)syn_id2name(m->hlg_id), -1);
|
||||
tv_list_append_string(rettv->vval.v_list, (const char *)m->pattern, -1);
|
||||
} else {
|
||||
tv_list_append_string(rettv->vval.v_list, NULL, 0);
|
||||
tv_list_append_string(rettv->vval.v_list, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// "matchdelete()" function
|
||||
static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
win_T *win = get_optional_window(argvars, 1);
|
||||
if (win == NULL) {
|
||||
rettv->vval.v_number = -1;
|
||||
} else {
|
||||
rettv->vval.v_number = match_delete(win,
|
||||
(int)tv_get_number(&argvars[0]), true);
|
||||
}
|
||||
}
|
||||
|
||||
/// "matchend()" function
|
||||
static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
@ -9121,109 +8929,6 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// "setmatches()" function
|
||||
static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
dict_T *d;
|
||||
list_T *s = NULL;
|
||||
win_T *win = get_optional_window(argvars, 1);
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
if (argvars[0].v_type != VAR_LIST) {
|
||||
emsg(_(e_listreq));
|
||||
return;
|
||||
}
|
||||
if (win == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_T *const l = argvars[0].vval.v_list;
|
||||
// To some extent make sure that we are dealing with a list from
|
||||
// "getmatches()".
|
||||
int li_idx = 0;
|
||||
TV_LIST_ITER_CONST(l, li, {
|
||||
if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT
|
||||
|| (d = TV_LIST_ITEM_TV(li)->vval.v_dict) == NULL) {
|
||||
semsg(_("E474: List item %d is either not a dictionary "
|
||||
"or an empty one"), li_idx);
|
||||
return;
|
||||
}
|
||||
if (!(tv_dict_find(d, S_LEN("group")) != NULL
|
||||
&& (tv_dict_find(d, S_LEN("pattern")) != NULL
|
||||
|| tv_dict_find(d, S_LEN("pos1")) != NULL)
|
||||
&& tv_dict_find(d, S_LEN("priority")) != NULL
|
||||
&& tv_dict_find(d, S_LEN("id")) != NULL)) {
|
||||
semsg(_("E474: List item %d is missing one of the required keys"),
|
||||
li_idx);
|
||||
return;
|
||||
}
|
||||
li_idx++;
|
||||
});
|
||||
|
||||
clear_matches(win);
|
||||
bool match_add_failed = false;
|
||||
TV_LIST_ITER_CONST(l, li, {
|
||||
int i = 0;
|
||||
|
||||
d = TV_LIST_ITEM_TV(li)->vval.v_dict;
|
||||
dictitem_T *const di = tv_dict_find(d, S_LEN("pattern"));
|
||||
if (di == NULL) {
|
||||
if (s == NULL) {
|
||||
s = tv_list_alloc(9);
|
||||
}
|
||||
|
||||
// match from matchaddpos()
|
||||
for (i = 1; i < 9; i++) {
|
||||
char buf[30]; // use 30 to avoid compiler warning
|
||||
snprintf(buf, sizeof(buf), "pos%d", i);
|
||||
dictitem_T *const pos_di = tv_dict_find(d, buf, -1);
|
||||
if (pos_di != NULL) {
|
||||
if (pos_di->di_tv.v_type != VAR_LIST) {
|
||||
return;
|
||||
}
|
||||
|
||||
tv_list_append_tv(s, &pos_di->di_tv);
|
||||
tv_list_ref(s);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note: there are three number buffers involved:
|
||||
// - group_buf below.
|
||||
// - numbuf in tv_dict_get_string().
|
||||
// - mybuf in tv_get_string().
|
||||
//
|
||||
// If you change this code make sure that buffers will not get
|
||||
// accidentally reused.
|
||||
char group_buf[NUMBUFLEN];
|
||||
const char *const group = tv_dict_get_string_buf(d, "group", group_buf);
|
||||
const int priority = (int)tv_dict_get_number(d, "priority");
|
||||
const int id = (int)tv_dict_get_number(d, "id");
|
||||
dictitem_T *const conceal_di = tv_dict_find(d, S_LEN("conceal"));
|
||||
const char *const conceal = (conceal_di != NULL
|
||||
? tv_get_string(&conceal_di->di_tv)
|
||||
: NULL);
|
||||
if (i == 0) {
|
||||
if (match_add(win, group,
|
||||
tv_dict_get_string(d, "pattern", false),
|
||||
priority, id, NULL, conceal) != id) {
|
||||
match_add_failed = true;
|
||||
}
|
||||
} else {
|
||||
if (match_add(win, group, NULL, priority, id, s, conceal) != id) {
|
||||
match_add_failed = true;
|
||||
}
|
||||
tv_list_unref(s);
|
||||
s = NULL;
|
||||
}
|
||||
});
|
||||
if (!match_add_failed) {
|
||||
rettv->vval.v_number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// "setpos()" function
|
||||
static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
|
@ -9541,70 +9541,6 @@ static void ex_nohlsearch(exarg_T *eap)
|
||||
redraw_all_later(SOME_VALID);
|
||||
}
|
||||
|
||||
/// ":[N]match {group} {pattern}"
|
||||
/// Sets nextcmd to the start of the next command, if any. Also called when
|
||||
/// skipping commands to find the next command.
|
||||
static void ex_match(exarg_T *eap)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *g = NULL;
|
||||
char_u *end;
|
||||
int c;
|
||||
int id;
|
||||
|
||||
if (eap->line2 <= 3) {
|
||||
id = eap->line2;
|
||||
} else {
|
||||
emsg(e_invcmd);
|
||||
return;
|
||||
}
|
||||
|
||||
// First clear any old pattern.
|
||||
if (!eap->skip) {
|
||||
match_delete(curwin, id, false);
|
||||
}
|
||||
|
||||
if (ends_excmd(*eap->arg)) {
|
||||
end = eap->arg;
|
||||
} else if ((STRNICMP(eap->arg, "none", 4) == 0
|
||||
&& (ascii_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4])))) {
|
||||
end = eap->arg + 4;
|
||||
} else {
|
||||
p = skiptowhite(eap->arg);
|
||||
if (!eap->skip) {
|
||||
g = vim_strnsave(eap->arg, p - eap->arg);
|
||||
}
|
||||
p = skipwhite(p);
|
||||
if (*p == NUL) {
|
||||
// There must be two arguments.
|
||||
xfree(g);
|
||||
semsg(_(e_invarg2), eap->arg);
|
||||
return;
|
||||
}
|
||||
end = skip_regexp(p + 1, *p, true, NULL);
|
||||
if (!eap->skip) {
|
||||
if (*end != NUL && !ends_excmd(*skipwhite(end + 1))) {
|
||||
xfree(g);
|
||||
eap->errmsg = e_trailing;
|
||||
return;
|
||||
}
|
||||
if (*end != *p) {
|
||||
xfree(g);
|
||||
semsg(_(e_invarg2), p);
|
||||
return;
|
||||
}
|
||||
|
||||
c = *end;
|
||||
*end = NUL;
|
||||
match_add(curwin, (const char *)g, (const char *)p + 1, 10, id,
|
||||
NULL, NULL);
|
||||
xfree(g);
|
||||
*end = c;
|
||||
}
|
||||
}
|
||||
eap->nextcmd = find_nextcmd(end);
|
||||
}
|
||||
|
||||
static void ex_fold(exarg_T *eap)
|
||||
{
|
||||
if (foldManualAllowed(true)) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -164,7 +164,6 @@ static bool resizing = false;
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "screen.c.generated.h"
|
||||
#endif
|
||||
#define SEARCH_HL_PRIORITY 0
|
||||
|
||||
static char *provider_err = NULL;
|
||||
|
||||
@ -768,7 +767,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
|
||||
redraw_win_signcol(wp);
|
||||
|
||||
init_search_hl(wp);
|
||||
init_search_hl(wp, &search_hl);
|
||||
|
||||
/* Force redraw when width of 'number' or 'relativenumber' column
|
||||
* changes. */
|
||||
@ -1533,7 +1532,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
|
||||
// will draw "@ " lines below.
|
||||
row = wp->w_grid.Rows + 1;
|
||||
} else {
|
||||
prepare_search_hl(wp, lnum);
|
||||
prepare_search_hl(wp, &search_hl, lnum);
|
||||
// Let the syntax stuff know we skipped a few lines.
|
||||
if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
|
||||
&& syntax_present(wp)) {
|
||||
@ -2095,13 +2094,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
int line_attr_save;
|
||||
int line_attr_lowprio = 0; // low-priority attribute for the line
|
||||
int line_attr_lowprio_save;
|
||||
matchitem_T *cur; // points to the match list
|
||||
match_T *shl; // points to search_hl or a match
|
||||
bool shl_flag; // flag to indicate whether search_hl
|
||||
// has been processed or not
|
||||
bool prevcol_hl_flag; // flag to indicate whether prevcol
|
||||
// equals startcol of search_hl or one
|
||||
// of the matches
|
||||
int prev_c = 0; // previous Arabic character
|
||||
int prev_c1 = 0; // first composing char for prev_c
|
||||
|
||||
@ -2599,66 +2591,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle highlighting the last used search pattern and matches.
|
||||
* Do this for both search_hl and the match list.
|
||||
*/
|
||||
cur = wp->w_match_head;
|
||||
shl_flag = false;
|
||||
while ((cur != NULL || !shl_flag) && !number_only
|
||||
&& !has_fold && !end_fill) {
|
||||
if (!shl_flag) {
|
||||
shl = &search_hl;
|
||||
shl_flag = true;
|
||||
} else {
|
||||
shl = &cur->hl; // -V595
|
||||
}
|
||||
shl->startcol = MAXCOL;
|
||||
shl->endcol = MAXCOL;
|
||||
shl->attr_cur = 0;
|
||||
shl->is_addpos = false;
|
||||
v = (ptr - line);
|
||||
if (cur != NULL) {
|
||||
cur->pos.cur = 0;
|
||||
}
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v,
|
||||
shl == &search_hl ? NULL : cur);
|
||||
|
||||
// Need to get the line again, a multi-line regexp may have made it
|
||||
// invalid.
|
||||
line = ml_get_buf(wp->w_buffer, lnum, false);
|
||||
ptr = line + v;
|
||||
|
||||
if (shl->lnum != 0 && shl->lnum <= lnum) {
|
||||
if (shl->lnum == lnum) {
|
||||
shl->startcol = shl->rm.startpos[0].col;
|
||||
} else {
|
||||
shl->startcol = 0;
|
||||
}
|
||||
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
|
||||
- shl->rm.startpos[0].lnum) {
|
||||
shl->endcol = shl->rm.endpos[0].col;
|
||||
} else {
|
||||
shl->endcol = MAXCOL;
|
||||
}
|
||||
// Highlight one character for an empty match.
|
||||
if (shl->startcol == shl->endcol) {
|
||||
if (line[shl->endcol] != NUL) {
|
||||
shl->endcol += utfc_ptr2len(line + shl->endcol);
|
||||
} else {
|
||||
++shl->endcol;
|
||||
}
|
||||
}
|
||||
if ((long)shl->startcol < v) { // match at leftcol
|
||||
shl->attr_cur = shl->attr;
|
||||
search_attr = shl->attr;
|
||||
search_attr_from_match = shl != &search_hl;
|
||||
}
|
||||
area_highlighting = true;
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
if (!number_only && !has_fold && !end_fill) {
|
||||
v = ptr - line;
|
||||
area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v,
|
||||
&line, &search_hl, &search_attr,
|
||||
&search_attr_from_match);
|
||||
ptr = line + v; // "line" may have been updated
|
||||
}
|
||||
|
||||
unsigned off = 0; // Offset relative start of line
|
||||
@ -3013,115 +2951,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
}
|
||||
|
||||
if (!n_extra) {
|
||||
/*
|
||||
* Check for start/end of search pattern match.
|
||||
* 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 for 'search_hl' and the match list (ordered by
|
||||
* priority).
|
||||
*/
|
||||
// Check for start/end of 'hlsearch' and other matches.
|
||||
// After end, check for start/end of next match.
|
||||
// When another match, have to check for start again.
|
||||
v = (ptr - line);
|
||||
cur = wp->w_match_head;
|
||||
shl_flag = false;
|
||||
while (cur != NULL || !shl_flag) {
|
||||
if (!shl_flag
|
||||
&& (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) {
|
||||
shl = &search_hl;
|
||||
shl_flag = true;
|
||||
} else {
|
||||
shl = &cur->hl;
|
||||
}
|
||||
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) {
|
||||
int tmp_col = v + utfc_ptr2len(ptr);
|
||||
|
||||
if (shl->endcol < tmp_col) {
|
||||
shl->endcol = tmp_col;
|
||||
}
|
||||
shl->attr_cur = shl->attr;
|
||||
// Match with the "Conceal" group results in hiding
|
||||
// the match.
|
||||
if (cur != NULL
|
||||
&& shl != &search_hl
|
||||
&& syn_name2id("Conceal") == cur->hlg_id) {
|
||||
has_match_conc = v == (long)shl->startcol ? 2 : 1;
|
||||
match_conc = cur->conceal_char;
|
||||
} else {
|
||||
has_match_conc = 0;
|
||||
}
|
||||
} else if (v == (long)shl->endcol) {
|
||||
shl->attr_cur = 0;
|
||||
|
||||
next_search_hl(wp, shl, lnum, (colnr_T)v,
|
||||
shl == &search_hl ? NULL : cur);
|
||||
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||
|
||||
// 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 == lnum) {
|
||||
shl->startcol = shl->rm.startpos[0].col;
|
||||
if (shl->rm.endpos[0].lnum == 0) {
|
||||
shl->endcol = shl->rm.endpos[0].col;
|
||||
} else {
|
||||
shl->endcol = MAXCOL;
|
||||
}
|
||||
|
||||
if (shl->startcol == shl->endcol) {
|
||||
// highlight empty match, try again after it
|
||||
shl->endcol += utfc_ptr2len(line + shl->endcol);
|
||||
}
|
||||
|
||||
// Loop to check if the match starts at the
|
||||
// current position
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use attributes from match with highest priority among
|
||||
* 'search_hl' and the match list. */
|
||||
search_attr_from_match = false;
|
||||
search_attr = search_hl.attr_cur;
|
||||
cur = wp->w_match_head;
|
||||
shl_flag = false;
|
||||
while (cur != NULL || !shl_flag) {
|
||||
if (!shl_flag
|
||||
&& (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) {
|
||||
shl = &search_hl;
|
||||
shl_flag = true;
|
||||
} else {
|
||||
shl = &cur->hl;
|
||||
}
|
||||
if (shl->attr_cur != 0) {
|
||||
search_attr = shl->attr_cur;
|
||||
search_attr_from_match = shl != &search_hl;
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
// Only highlight one character after the last column.
|
||||
if (*ptr == NUL
|
||||
&& (wp->w_p_list && lcs_eol_one == -1)) {
|
||||
search_attr = 0;
|
||||
}
|
||||
search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &search_hl, &has_match_conc,
|
||||
&match_conc, lcs_eol_one, &search_attr_from_match);
|
||||
ptr = line + v; // "line" may have been changed
|
||||
|
||||
// Do not allow a conceal over EOL otherwise EOL will be missed
|
||||
// and bad things happen.
|
||||
@ -3939,30 +3775,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
|
||||
// At end of the text line or just after the last character.
|
||||
if (c == NUL && eol_hl_off == 0) {
|
||||
long prevcol = (ptr - line) - 1;
|
||||
|
||||
// we're not really at that column when skipping some text
|
||||
if ((long)(wp->w_p_wrap ? wp->w_skipcol : wp->w_leftcol) > prevcol) {
|
||||
prevcol++;
|
||||
}
|
||||
// flag to indicate whether prevcol equals startcol of search_hl or
|
||||
// one of the matches
|
||||
bool prevcol_hl_flag = get_prevcol_hl_flag(wp, &search_hl,
|
||||
(long)(ptr - line) - 1);
|
||||
|
||||
// Invert at least one char, used for Visual and empty line or
|
||||
// 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'.
|
||||
prevcol_hl_flag = false;
|
||||
if (!search_hl.is_addpos && prevcol == (long)search_hl.startcol) {
|
||||
prevcol_hl_flag = true;
|
||||
} else {
|
||||
cur = wp->w_match_head;
|
||||
while (cur != NULL) {
|
||||
if (!cur->hl.is_addpos && prevcol == (long)cur->hl.startcol) {
|
||||
prevcol_hl_flag = true;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
if (wp->w_p_lcs_chars.eol == lcs_eol_one
|
||||
&& ((area_attr != 0 && vcol == fromcol
|
||||
&& (VIsual_mode != Ctrl_V
|
||||
@ -3993,25 +3814,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|
||||
if (area_attr == 0 && !has_fold) {
|
||||
// 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) {
|
||||
if (!shl_flag
|
||||
&& (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) {
|
||||
shl = &search_hl;
|
||||
shl_flag = true;
|
||||
} else {
|
||||
shl = &cur->hl;
|
||||
}
|
||||
if ((ptr - line) - 1 == (long)shl->startcol
|
||||
&& (shl == &search_hl || !shl->is_addpos)) {
|
||||
char_attr = shl->attr;
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
get_search_match_hl(wp, &search_hl, (long)(ptr - line), &char_attr);
|
||||
}
|
||||
|
||||
int eol_attr = char_attr;
|
||||
@ -6192,277 +5995,6 @@ static void end_search_hl(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init for calling prepare_search_hl().
|
||||
*/
|
||||
static void init_search_hl(win_T *wp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Setup for match and 'hlsearch' highlighting. Disable any previous
|
||||
// match
|
||||
matchitem_T *cur = wp->w_match_head;
|
||||
while (cur != NULL) {
|
||||
cur->hl.rm = cur->match;
|
||||
if (cur->hlg_id == 0) {
|
||||
cur->hl.attr = 0;
|
||||
} else {
|
||||
cur->hl.attr = syn_id2attr(cur->hlg_id);
|
||||
}
|
||||
cur->hl.buf = wp->w_buffer;
|
||||
cur->hl.lnum = 0;
|
||||
cur->hl.first_lnum = 0;
|
||||
// Set the time limit to 'redrawtime'.
|
||||
cur->hl.tm = profile_setlimit(p_rdt);
|
||||
cur = cur->next;
|
||||
}
|
||||
search_hl.buf = wp->w_buffer;
|
||||
search_hl.lnum = 0;
|
||||
search_hl.first_lnum = 0;
|
||||
search_hl.attr = win_hl_attr(wp, HLF_L);
|
||||
|
||||
// time limit is set at the toplevel, for all windows
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance to the match in window "wp" line "lnum" or past it.
|
||||
*/
|
||||
static void prepare_search_hl(win_T *wp, linenr_T lnum)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
matchitem_T *cur; // points to the match list
|
||||
match_T *shl; // points to search_hl or a match
|
||||
bool shl_flag; // flag to indicate whether search_hl
|
||||
// has been processed or not
|
||||
|
||||
// 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 the match list.
|
||||
cur = wp->w_match_head;
|
||||
shl_flag = false;
|
||||
while (cur != NULL || shl_flag == false) {
|
||||
if (shl_flag == false) {
|
||||
shl = &search_hl;
|
||||
shl_flag = true;
|
||||
} else {
|
||||
shl = &cur->hl; // -V595
|
||||
}
|
||||
if (shl->rm.regprog != NULL
|
||||
&& shl->lnum == 0
|
||||
&& re_multiline(shl->rm.regprog)) {
|
||||
if (shl->first_lnum == 0) {
|
||||
for (shl->first_lnum = lnum;
|
||||
shl->first_lnum > wp->w_topline;
|
||||
shl->first_lnum--) {
|
||||
if (hasFoldingWin(wp, shl->first_lnum - 1, 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
|
||||
int n = 0;
|
||||
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
|
||||
|| (cur != NULL && pos_inprogress))) {
|
||||
next_search_hl(wp, shl, shl->first_lnum, (colnr_T)n,
|
||||
shl == &search_hl ? NULL : cur);
|
||||
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
|
||||
if (shl->lnum != 0) {
|
||||
shl->first_lnum = shl->lnum
|
||||
+ shl->rm.endpos[0].lnum
|
||||
- shl->rm.startpos[0].lnum;
|
||||
n = shl->rm.endpos[0].col;
|
||||
} else {
|
||||
++shl->first_lnum;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shl != &search_hl && cur != NULL) {
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for a next 'hlsearch' or match.
|
||||
/// Uses shl->buf.
|
||||
/// Sets shl->lnum and shl->rm contents.
|
||||
/// Note: Assumes a previous match is always before "lnum", unless
|
||||
/// shl->lnum is zero.
|
||||
/// Careful: Any pointers for buffer lines will become invalid.
|
||||
///
|
||||
/// @param shl points to search_hl or a match
|
||||
/// @param mincol minimal column for a match
|
||||
/// @param cur to retrieve match positions if any
|
||||
static void next_search_hl(win_T *win, match_T *shl, linenr_T lnum, colnr_T mincol,
|
||||
matchitem_T *cur)
|
||||
FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
linenr_T l;
|
||||
colnr_T matchcol;
|
||||
long nmatched = 0;
|
||||
int save_called_emsg = called_emsg;
|
||||
|
||||
// for :{range}s/pat only highlight inside the range
|
||||
if (lnum < search_first_line || lnum > search_last_line) {
|
||||
shl->lnum = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shl->lnum != 0) {
|
||||
// Check for three situations:
|
||||
// 1. If the "lnum" is below a previous match, start a new search.
|
||||
// 2. If the previous match includes "mincol", use it.
|
||||
// 3. Continue after the previous match.
|
||||
l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum;
|
||||
if (lnum > l) {
|
||||
shl->lnum = 0;
|
||||
} else if (lnum < l || shl->rm.endpos[0].col > mincol) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat searching for a match until one is found that includes "mincol"
|
||||
* or none is found in this line.
|
||||
*/
|
||||
called_emsg = FALSE;
|
||||
for (;;) {
|
||||
// Stop searching after passing the time limit.
|
||||
if (profile_passed_limit(shl->tm)) {
|
||||
shl->lnum = 0; // no match found in time
|
||||
break;
|
||||
}
|
||||
// Three situations:
|
||||
// 1. No useful previous match: search from start of line.
|
||||
// 2. Not Vi compatible or empty match: continue at next character.
|
||||
// Break the loop if this is beyond the end of the line.
|
||||
// 3. Vi compatible searching: continue at end of previous match.
|
||||
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)) {
|
||||
char_u *ml;
|
||||
|
||||
matchcol = shl->rm.startpos[0].col;
|
||||
ml = ml_get_buf(shl->buf, lnum, false) + matchcol;
|
||||
if (*ml == NUL) {
|
||||
++matchcol;
|
||||
shl->lnum = 0;
|
||||
break;
|
||||
}
|
||||
matchcol += utfc_ptr2len(ml);
|
||||
} else {
|
||||
matchcol = shl->rm.endpos[0].col;
|
||||
}
|
||||
|
||||
shl->lnum = lnum;
|
||||
if (shl->rm.regprog != NULL) {
|
||||
// Remember whether shl->rm is using a copy of the regprog in
|
||||
// cur->match.
|
||||
bool regprog_is_copy = (shl != &search_hl
|
||||
&& cur != NULL
|
||||
&& shl == &cur->hl
|
||||
&& cur->match.regprog == cur->hl.rm.regprog);
|
||||
int timed_out = false;
|
||||
|
||||
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
|
||||
&(shl->tm), &timed_out);
|
||||
// Copy the regprog, in case it got freed and recompiled.
|
||||
if (regprog_is_copy) {
|
||||
cur->match.regprog = cur->hl.rm.regprog;
|
||||
}
|
||||
if (called_emsg || got_int || timed_out) {
|
||||
// Error while handling regexp: stop using this regexp.
|
||||
if (shl == &search_hl) {
|
||||
// don't free regprog in the match list, it's a copy
|
||||
vim_regfree(shl->rm.regprog);
|
||||
set_no_hlsearch(true);
|
||||
}
|
||||
shl->rm.regprog = NULL;
|
||||
shl->lnum = 0;
|
||||
got_int = FALSE; // avoid the "Type :quit to exit Vim" message
|
||||
break;
|
||||
}
|
||||
} else if (cur != NULL) {
|
||||
nmatched = next_search_hl_pos(shl, lnum, &(cur->pos), matchcol);
|
||||
}
|
||||
if (nmatched == 0) {
|
||||
shl->lnum = 0; // no match found
|
||||
break;
|
||||
}
|
||||
if (shl->rm.startpos[0].lnum > 0
|
||||
|| shl->rm.startpos[0].col >= mincol
|
||||
|| nmatched > 1
|
||||
|| shl->rm.endpos[0].col > mincol) {
|
||||
shl->lnum += shl->rm.startpos[0].lnum;
|
||||
break; // useful match found
|
||||
}
|
||||
|
||||
// Restore called_emsg for assert_fails().
|
||||
called_emsg = save_called_emsg;
|
||||
}
|
||||
}
|
||||
|
||||
/// @param shl points to a match. Fill on match.
|
||||
/// @param posmatch match positions
|
||||
/// @param mincol minimal column for a match
|
||||
///
|
||||
/// @return one on match, otherwise return zero.
|
||||
static int next_search_hl_pos(match_T *shl, linenr_T lnum, posmatch_T *posmatch, colnr_T mincol)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int i;
|
||||
int found = -1;
|
||||
|
||||
shl->lnum = 0;
|
||||
for (i = posmatch->cur; i < MAXPOSMATCH; i++) {
|
||||
llpos_T *pos = &posmatch->pos[i];
|
||||
|
||||
if (pos->lnum == 0) {
|
||||
break;
|
||||
}
|
||||
if (pos->len == 0 && pos->col < mincol) {
|
||||
continue;
|
||||
}
|
||||
if (pos->lnum == lnum) {
|
||||
if (found >= 0) {
|
||||
// if this match comes before the one at "found" then swap
|
||||
// them
|
||||
if (pos->col < posmatch->pos[found].col) {
|
||||
llpos_T tmp = *pos;
|
||||
|
||||
*pos = posmatch->pos[found];
|
||||
posmatch->pos[found] = tmp;
|
||||
}
|
||||
} else {
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
posmatch->cur = 0;
|
||||
if (found >= 0) {
|
||||
colnr_T start = posmatch->pos[found].col == 0
|
||||
? 0: posmatch->pos[found].col - 1;
|
||||
colnr_T end = posmatch->pos[found].col == 0
|
||||
? MAXCOL : start + posmatch->pos[found].len;
|
||||
|
||||
shl->lnum = lnum;
|
||||
shl->rm.startpos[0].lnum = 0;
|
||||
shl->rm.startpos[0].col = start;
|
||||
shl->rm.endpos[0].lnum = 0;
|
||||
shl->rm.endpos[0].col = end;
|
||||
shl->is_addpos = true;
|
||||
posmatch->cur = found + 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// Fill the grid from 'start_row' to 'end_row', from 'start_col' to 'end_col'
|
||||
/// with character 'c1' in first column followed by 'c2' in the other columns.
|
||||
/// Use attributes 'attr'.
|
||||
|
@ -6953,286 +6953,6 @@ void restore_buffer(bufref_T *save_curbuf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Add match to the match list of window 'wp'. The pattern 'pat' will be
|
||||
/// highlighted with the group 'grp' with priority 'prio'.
|
||||
/// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
|
||||
///
|
||||
/// @param[in] id a desired ID 'id' can be specified
|
||||
/// (greater than or equal to 1). -1 must be specified if no
|
||||
/// particular ID is desired
|
||||
/// @param[in] conceal_char pointer to conceal replacement char
|
||||
/// @return ID of added match, -1 on failure.
|
||||
int match_add(win_T *wp, const char *const grp, const char *const pat, int prio, int id,
|
||||
list_T *pos_list, const char *const conceal_char)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 2)
|
||||
{
|
||||
matchitem_T *cur;
|
||||
matchitem_T *prev;
|
||||
matchitem_T *m;
|
||||
int hlg_id;
|
||||
regprog_T *regprog = NULL;
|
||||
int rtype = SOME_VALID;
|
||||
|
||||
if (*grp == NUL || (pat != NULL && *pat == NUL)) {
|
||||
return -1;
|
||||
}
|
||||
if (id < -1 || id == 0) {
|
||||
semsg(_("E799: Invalid ID: %" PRId64
|
||||
" (must be greater than or equal to 1)"),
|
||||
(int64_t)id);
|
||||
return -1;
|
||||
}
|
||||
if (id != -1) {
|
||||
cur = wp->w_match_head;
|
||||
while (cur != NULL) {
|
||||
if (cur->id == id) {
|
||||
semsg(_("E801: ID already taken: %" PRId64), (int64_t)id);
|
||||
return -1;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
if ((hlg_id = syn_check_group(grp, strlen(grp))) == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) {
|
||||
semsg(_(e_invarg2), pat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find available match ID.
|
||||
while (id == -1) {
|
||||
cur = wp->w_match_head;
|
||||
while (cur != NULL && cur->id != wp->w_next_match_id) {
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == NULL) {
|
||||
id = wp->w_next_match_id;
|
||||
}
|
||||
wp->w_next_match_id++;
|
||||
}
|
||||
|
||||
// Build new match.
|
||||
m = xcalloc(1, sizeof(matchitem_T));
|
||||
m->id = id;
|
||||
m->priority = prio;
|
||||
m->pattern = pat == NULL ? NULL: (char_u *)xstrdup(pat);
|
||||
m->hlg_id = hlg_id;
|
||||
m->match.regprog = regprog;
|
||||
m->match.rmm_ic = FALSE;
|
||||
m->match.rmm_maxcol = 0;
|
||||
m->conceal_char = 0;
|
||||
if (conceal_char != NULL) {
|
||||
m->conceal_char = utf_ptr2char((const char_u *)conceal_char);
|
||||
}
|
||||
|
||||
// Set up position matches
|
||||
if (pos_list != NULL) {
|
||||
linenr_T toplnum = 0;
|
||||
linenr_T botlnum = 0;
|
||||
|
||||
int i = 0;
|
||||
TV_LIST_ITER(pos_list, li, {
|
||||
linenr_T lnum = 0;
|
||||
colnr_T col = 0;
|
||||
int len = 1;
|
||||
bool error = false;
|
||||
|
||||
if (TV_LIST_ITEM_TV(li)->v_type == VAR_LIST) {
|
||||
const list_T *const subl = TV_LIST_ITEM_TV(li)->vval.v_list;
|
||||
const listitem_T *subli = tv_list_first(subl);
|
||||
if (subli == NULL) {
|
||||
semsg(_("E5030: Empty list at position %d"),
|
||||
(int)tv_list_idx_of_item(pos_list, li));
|
||||
goto fail;
|
||||
}
|
||||
lnum = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
if (lnum <= 0) {
|
||||
continue;
|
||||
}
|
||||
m->pos.pos[i].lnum = lnum;
|
||||
subli = TV_LIST_ITEM_NEXT(subl, subli);
|
||||
if (subli != NULL) {
|
||||
col = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
if (col < 0) {
|
||||
continue;
|
||||
}
|
||||
subli = TV_LIST_ITEM_NEXT(subl, subli);
|
||||
if (subli != NULL) {
|
||||
len = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
|
||||
if (len < 0) {
|
||||
continue;
|
||||
}
|
||||
if (error) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
m->pos.pos[i].col = col;
|
||||
m->pos.pos[i].len = len;
|
||||
} else if (TV_LIST_ITEM_TV(li)->v_type == VAR_NUMBER) {
|
||||
if (TV_LIST_ITEM_TV(li)->vval.v_number <= 0) {
|
||||
continue;
|
||||
}
|
||||
m->pos.pos[i].lnum = TV_LIST_ITEM_TV(li)->vval.v_number;
|
||||
m->pos.pos[i].col = 0;
|
||||
m->pos.pos[i].len = 0;
|
||||
} else {
|
||||
semsg(_("E5031: List or number required at position %d"),
|
||||
(int)tv_list_idx_of_item(pos_list, li));
|
||||
goto fail;
|
||||
}
|
||||
if (toplnum == 0 || lnum < toplnum) {
|
||||
toplnum = lnum;
|
||||
}
|
||||
if (botlnum == 0 || lnum >= botlnum) {
|
||||
botlnum = lnum + 1;
|
||||
}
|
||||
i++;
|
||||
if (i >= MAXPOSMATCH) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 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_set = true;
|
||||
wp->w_buffer->b_mod_top = toplnum;
|
||||
wp->w_buffer->b_mod_bot = botlnum;
|
||||
wp->w_buffer->b_mod_xlines = 0;
|
||||
}
|
||||
m->pos.toplnum = toplnum;
|
||||
m->pos.botlnum = botlnum;
|
||||
rtype = VALID;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert new match. The match list is in ascending order with regard to
|
||||
// the match priorities.
|
||||
cur = wp->w_match_head;
|
||||
prev = cur;
|
||||
while (cur != NULL && prio >= cur->priority) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == prev) {
|
||||
wp->w_match_head = m;
|
||||
} else {
|
||||
prev->next = m;
|
||||
}
|
||||
m->next = cur;
|
||||
|
||||
redraw_later(wp, rtype);
|
||||
return id;
|
||||
|
||||
fail:
|
||||
xfree(m);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/// Delete match with ID 'id' in the match list of window 'wp'.
|
||||
///
|
||||
/// @param perr print error messages if true.
|
||||
int match_delete(win_T *wp, int id, bool perr)
|
||||
{
|
||||
matchitem_T *cur = wp->w_match_head;
|
||||
matchitem_T *prev = cur;
|
||||
int rtype = SOME_VALID;
|
||||
|
||||
if (id < 1) {
|
||||
if (perr) {
|
||||
semsg(_("E802: Invalid ID: %" PRId64
|
||||
" (must be greater than or equal to 1)"),
|
||||
(int64_t)id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
while (cur != NULL && cur->id != id) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == NULL) {
|
||||
if (perr) {
|
||||
semsg(_("E803: ID not found: %" PRId64), (int64_t)id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (cur == prev) {
|
||||
wp->w_match_head = cur->next;
|
||||
} else {
|
||||
prev->next = cur->next;
|
||||
}
|
||||
vim_regfree(cur->match.regprog);
|
||||
xfree(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_set = true;
|
||||
wp->w_buffer->b_mod_top = cur->pos.toplnum;
|
||||
wp->w_buffer->b_mod_bot = cur->pos.botlnum;
|
||||
wp->w_buffer->b_mod_xlines = 0;
|
||||
}
|
||||
rtype = VALID;
|
||||
}
|
||||
xfree(cur);
|
||||
redraw_later(wp, rtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all matches in the match list of window 'wp'.
|
||||
*/
|
||||
void clear_matches(win_T *wp)
|
||||
{
|
||||
matchitem_T *m;
|
||||
|
||||
while (wp->w_match_head != NULL) {
|
||||
m = wp->w_match_head->next;
|
||||
vim_regfree(wp->w_match_head->match.regprog);
|
||||
xfree(wp->w_match_head->pattern);
|
||||
xfree(wp->w_match_head);
|
||||
wp->w_match_head = m;
|
||||
}
|
||||
redraw_later(wp, SOME_VALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get match from ID 'id' in window 'wp'.
|
||||
* Return NULL if match not found.
|
||||
*/
|
||||
matchitem_T *get_match(win_T *wp, int id)
|
||||
{
|
||||
matchitem_T *cur = wp->w_match_head;
|
||||
|
||||
while (cur != NULL && cur->id != id) {
|
||||
cur = cur->next;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
/// Check that "topfrp" and its children are at the right height.
|
||||
///
|
||||
/// @param topfrp top frame pointer
|
||||
|
Loading…
Reference in New Issue
Block a user