# HG changeset patch # User Bram Moolenaar # Date 1563830105 -7200 # Node ID dfd87ef822aaa6f313c5e9532f23e6176c73e65e # Parent c7151df86441afc1b8658e4f38db9c9f8ff93906 patch 8.1.1734: the evalfunc.c file is too big commit https://github.com/vim/vim/commit/29b7d7a9aac591f920edb89241c8cde27378e50b Author: Bram Moolenaar Date: Mon Jul 22 23:03:57 2019 +0200 patch 8.1.1734: the evalfunc.c file is too big Problem: The evalfunc.c file is too big. Solution: Move some functions to other files. diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -24,10 +24,8 @@ # include /* for time_t */ #endif -static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static char *e_stringreq = N_("E928: String required"); -static char *e_invalwindow = N_("E957: Invalid window number"); #ifdef FEAT_FLOAT static void f_abs(typval_T *argvars, typval_T *rettv); @@ -164,7 +162,6 @@ static void f_getftype(typval_T *argvars static void f_getjumplist(typval_T *argvars, typval_T *rettv); static void f_getline(typval_T *argvars, typval_T *rettv); static void f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED); -static void f_getmatches(typval_T *argvars, typval_T *rettv); static void f_getpid(typval_T *argvars, typval_T *rettv); static void f_getcurpos(typval_T *argvars, typval_T *rettv); static void f_getpos(typval_T *argvars, typval_T *rettv); @@ -213,10 +210,6 @@ static void f_isnan(typval_T *argvars, t #endif static void f_items(typval_T *argvars, typval_T *rettv); static void f_join(typval_T *argvars, typval_T *rettv); -static void f_js_decode(typval_T *argvars, typval_T *rettv); -static void f_js_encode(typval_T *argvars, typval_T *rettv); -static void f_json_decode(typval_T *argvars, typval_T *rettv); -static void f_json_encode(typval_T *argvars, typval_T *rettv); static void f_keys(typval_T *argvars, typval_T *rettv); static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv); static void f_len(typval_T *argvars, typval_T *rettv); @@ -238,10 +231,6 @@ static void f_map(typval_T *argvars, typ static void f_maparg(typval_T *argvars, typval_T *rettv); static void f_mapcheck(typval_T *argvars, typval_T *rettv); static void f_match(typval_T *argvars, typval_T *rettv); -static void f_matchadd(typval_T *argvars, typval_T *rettv); -static void f_matchaddpos(typval_T *argvars, typval_T *rettv); -static void f_matcharg(typval_T *argvars, typval_T *rettv); -static void f_matchdelete(typval_T *argvars, typval_T *rettv); static void f_matchend(typval_T *argvars, typval_T *rettv); static void f_matchlist(typval_T *argvars, typval_T *rettv); static void f_matchstr(typval_T *argvars, typval_T *rettv); @@ -2202,7 +2191,7 @@ f_cindent(typval_T *argvars UNUSED, typv rettv->vval.v_number = -1; } - static win_T * + win_T * get_optional_window(typval_T *argvars, int idx) { win_T *win = curwin; @@ -5285,74 +5274,6 @@ f_getloclist(typval_T *argvars UNUSED, t } /* - * "getmatches()" function - */ - static void -f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ -#ifdef FEAT_SEARCH_EXTRA - dict_T *dict; - matchitem_T *cur; - int i; - win_T *win = get_optional_window(argvars, 0); - - if (rettv_list_alloc(rettv) == FAIL || win == NULL) - return; - - cur = win->w_match_head; - while (cur != NULL) - { - dict = dict_alloc(); - if (dict == NULL) - return; - 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 - list_T *l; - - llpos = &cur->pos.pos[i]; - if (llpos->lnum == 0) - break; - l = list_alloc(); - if (l == NULL) - break; - 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_string(dict, "pattern", cur->pattern); - } - dict_add_string(dict, "group", syn_id2name(cur->hlg_id)); - dict_add_number(dict, "priority", (long)cur->priority); - dict_add_number(dict, "id", (long)cur->id); -# if defined(FEAT_CONCEAL) - if (cur->conceal_char) - { - char_u buf[MB_MAXBYTES + 1]; - - buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; - dict_add_string(dict, "conceal", (char_u *)&buf); - } -# endif - list_append_dict(rettv->vval.v_list, dict); - cur = cur->next; - } -#endif -} - -/* * "getpid()" function */ static void @@ -7385,55 +7306,6 @@ f_join(typval_T *argvars, typval_T *rett } /* - * "js_decode()" function - */ - static void -f_js_decode(typval_T *argvars, typval_T *rettv) -{ - js_read_T reader; - - reader.js_buf = tv_get_string(&argvars[0]); - reader.js_fill = NULL; - reader.js_used = 0; - if (json_decode_all(&reader, rettv, JSON_JS) != OK) - emsg(_(e_invarg)); -} - -/* - * "js_encode()" function - */ - static void -f_js_encode(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = json_encode(&argvars[0], JSON_JS); -} - -/* - * "json_decode()" function - */ - static void -f_json_decode(typval_T *argvars, typval_T *rettv) -{ - js_read_T reader; - - reader.js_buf = tv_get_string(&argvars[0]); - reader.js_fill = NULL; - reader.js_used = 0; - json_decode_all(&reader, rettv, 0); -} - -/* - * "json_encode()" function - */ - static void -f_json_encode(typval_T *argvars, typval_T *rettv) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = json_encode(&argvars[0], 0); -} - -/* * "keys()" function */ static void @@ -8071,185 +7943,6 @@ f_match(typval_T *argvars, typval_T *ret find_some_match(argvars, rettv, MATCH_MATCH); } -#ifdef FEAT_SEARCH_EXTRA - static int -matchadd_dict_arg(typval_T *tv, char_u **conceal_char, win_T **win) -{ - dictitem_T *di; - - if (tv->v_type != VAR_DICT) - { - emsg(_(e_dictreq)); - return FAIL; - } - - if (dict_find(tv->vval.v_dict, (char_u *)"conceal", -1) != NULL) - *conceal_char = dict_get_string(tv->vval.v_dict, - (char_u *)"conceal", FALSE); - - if ((di = dict_find(tv->vval.v_dict, (char_u *)"window", -1)) != NULL) - { - *win = find_win_by_nr_or_id(&di->di_tv); - if (*win == NULL) - { - emsg(_(e_invalwindow)); - return FAIL; - } - } - - return OK; -} -#endif - -/* - * "matchadd()" function - */ - static void -f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ -#ifdef FEAT_SEARCH_EXTRA - char_u buf[NUMBUFLEN]; - char_u *grp = tv_get_string_buf_chk(&argvars[0], buf); /* group */ - char_u *pat = tv_get_string_buf_chk(&argvars[1], buf); /* pattern */ - int prio = 10; /* default priority */ - int id = -1; - int error = FALSE; - char_u *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 = (int)tv_get_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) - { - id = (int)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; - if (id >= 1 && id <= 3) - { - semsg(_("E798: ID is reserved for \":match\": %d"), id); - return; - } - - rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL, - conceal_char); -#endif -} - -/* - * "matchaddpos()" function - */ - static void -f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ -#ifdef FEAT_SEARCH_EXTRA - char_u buf[NUMBUFLEN]; - char_u *group; - int prio = 10; - int id = -1; - int error = FALSE; - list_T *l; - char_u *conceal_char = NULL; - win_T *win = curwin; - - rettv->vval.v_number = -1; - - 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; - } - l = argvars[1].vval.v_list; - if (l == NULL) - return; - - if (argvars[2].v_type != VAR_UNKNOWN) - { - prio = (int)tv_get_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) - { - id = (int)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\": %d"), id); - return; - } - - rettv->vval.v_number = match_add(win, group, NULL, prio, id, l, - conceal_char); -#endif -} - -/* - * "matcharg()" function - */ - static void -f_matcharg(typval_T *argvars UNUSED, typval_T *rettv) -{ - if (rettv_list_alloc(rettv) == OK) - { -#ifdef FEAT_SEARCH_EXTRA - int id = (int)tv_get_number(&argvars[0]); - matchitem_T *m; - - if (id >= 1 && id <= 3) - { - 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, NULL, -1); - list_append_string(rettv->vval.v_list, NULL, -1); - } - } -#endif - } -} - -/* - * "matchdelete()" function - */ - static void -f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ -#ifdef FEAT_SEARCH_EXTRA - 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); -#endif -} - /* * "matchend()" function */ diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -1615,8 +1615,10 @@ EXTERN char e_invalidreg[] INIT(= N_( EXTERN char e_dirnotf[] INIT(= N_("E919: Directory not found in '%s': \"%s\"")); EXTERN char e_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior")); #ifdef FEAT_MENU -EXTERN char e_menuothermode[] INIT(= N_("E328: Menu only exists in another mode")); +EXTERN char e_menuothermode[] INIT(= N_("E328: Menu only exists in another mode")); #endif +EXTERN char e_invalwindow[] INIT(= N_("E957: Invalid window number")); +EXTERN char e_listarg[] INIT(= N_("E686: Argument of %s must be a List")); #ifdef FEAT_GUI_MAC EXTERN short disallow_gui INIT(= FALSE); diff --git a/src/highlight.c b/src/highlight.c --- a/src/highlight.c +++ b/src/highlight.c @@ -8,7 +8,8 @@ */ /* - * Highlighting stuff + * Highlighting stuff. + * Includes highlighting matches. */ #include "vim.h" @@ -3653,3 +3654,543 @@ free_highlight_fonts(void) # endif } #endif + + +#if defined(FEAT_SEARCH_EXTRA) || defined(PROTO) +/* + * 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). + * 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, + list_T *pos_list, + char_u *conceal_char UNUSED) /* pointer to conceal replacement char */ +{ + 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: %d (must be greater than or equal to 1)"), id); + return -1; + } + if (id != -1) + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (cur->id == id) + { + semsg(_("E801: ID already taken: %d"), id); + return -1; + } + cur = cur->next; + } + } + if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) + { + semsg(_(e_nogroup), grp); + return -1; + } + if (pat != NULL && (regprog = vim_regcomp(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 = ALLOC_CLEAR_ONE(matchitem_T); + m->id = id; + m->priority = prio; + m->pattern = pat == NULL ? NULL : vim_strsave(pat); + m->hlg_id = hlg_id; + m->match.regprog = regprog; + m->match.rmm_ic = FALSE; + m->match.rmm_maxcol = 0; +# if defined(FEAT_CONCEAL) + m->conceal_char = 0; + if (conceal_char != NULL) + m->conceal_char = (*mb_ptr2char)(conceal_char); +# endif + + /* 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; li != NULL && 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 = FALSE; + + 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 = tv_get_number_chk(&subli->li_tv, &error); + if (error == TRUE) + goto fail; + if (lnum == 0) + { + --i; + continue; + } + m->pos.pos[i].lnum = lnum; + subli = subli->li_next; + if (subli != NULL) + { + col = tv_get_number_chk(&subli->li_tv, &error); + if (error == TRUE) + goto fail; + subli = subli->li_next; + if (subli != NULL) + { + len = tv_get_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) + { + --i; + 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 + 1; + } + + /* 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(rtype); + return id; + +fail: + vim_free(m); + return -1; +} + +/* + * Delete match with ID 'id' in the match list of window 'wp'. + * Print error messages if 'perr' is TRUE. + */ + 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) + semsg(_("E802: Invalid ID: %d (must be greater than or equal to 1)"), + id); + return -1; + } + while (cur != NULL && cur->id != id) + { + prev = cur; + cur = cur->next; + } + if (cur == NULL) + { + if (perr == TRUE) + semsg(_("E803: ID not found: %d"), id); + return -1; + } + if (cur == prev) + wp->w_match_head = cur->next; + else + prev->next = cur->next; + vim_regfree(cur->match.regprog); + vim_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_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; + } + vim_free(cur); + redraw_later(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); + vim_free(wp->w_match_head->pattern); + vim_free(wp->w_match_head); + wp->w_match_head = m; + } + redraw_later(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; +} + + static int +matchadd_dict_arg(typval_T *tv, char_u **conceal_char, win_T **win) +{ + dictitem_T *di; + + if (tv->v_type != VAR_DICT) + { + emsg(_(e_dictreq)); + return FAIL; + } + + if (dict_find(tv->vval.v_dict, (char_u *)"conceal", -1) != NULL) + *conceal_char = dict_get_string(tv->vval.v_dict, + (char_u *)"conceal", FALSE); + + if ((di = dict_find(tv->vval.v_dict, (char_u *)"window", -1)) != NULL) + { + *win = find_win_by_nr_or_id(&di->di_tv); + if (*win == NULL) + { + emsg(_(e_invalwindow)); + return FAIL; + } + } + + return OK; +} +#endif + +/* + * "getmatches()" function + */ + void +f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_SEARCH_EXTRA + dict_T *dict; + matchitem_T *cur; + int i; + win_T *win = get_optional_window(argvars, 0); + + if (rettv_list_alloc(rettv) == FAIL || win == NULL) + return; + + cur = win->w_match_head; + while (cur != NULL) + { + dict = dict_alloc(); + if (dict == NULL) + return; + 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 + list_T *l; + + llpos = &cur->pos.pos[i]; + if (llpos->lnum == 0) + break; + l = list_alloc(); + if (l == NULL) + break; + 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_string(dict, "pattern", cur->pattern); + } + dict_add_string(dict, "group", syn_id2name(cur->hlg_id)); + dict_add_number(dict, "priority", (long)cur->priority); + dict_add_number(dict, "id", (long)cur->id); +# if defined(FEAT_CONCEAL) + if (cur->conceal_char) + { + char_u buf[MB_MAXBYTES + 1]; + + buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; + dict_add_string(dict, "conceal", (char_u *)&buf); + } +# endif + list_append_dict(rettv->vval.v_list, dict); + cur = cur->next; + } +#endif +} + +/* + * "matchadd()" function + */ + void +f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_SEARCH_EXTRA + char_u buf[NUMBUFLEN]; + char_u *grp = tv_get_string_buf_chk(&argvars[0], buf); /* group */ + char_u *pat = tv_get_string_buf_chk(&argvars[1], buf); /* pattern */ + int prio = 10; /* default priority */ + int id = -1; + int error = FALSE; + char_u *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 = (int)tv_get_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) + { + id = (int)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; + if (id >= 1 && id <= 3) + { + semsg(_("E798: ID is reserved for \":match\": %d"), id); + return; + } + + rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL, + conceal_char); +#endif +} + +/* + * "matchaddpos()" function + */ + void +f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_SEARCH_EXTRA + char_u buf[NUMBUFLEN]; + char_u *group; + int prio = 10; + int id = -1; + int error = FALSE; + list_T *l; + char_u *conceal_char = NULL; + win_T *win = curwin; + + rettv->vval.v_number = -1; + + 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; + } + l = argvars[1].vval.v_list; + if (l == NULL) + return; + + if (argvars[2].v_type != VAR_UNKNOWN) + { + prio = (int)tv_get_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) + { + id = (int)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\": %d"), id); + return; + } + + rettv->vval.v_number = match_add(win, group, NULL, prio, id, l, + conceal_char); +#endif +} + +/* + * "matcharg()" function + */ + void +f_matcharg(typval_T *argvars UNUSED, typval_T *rettv) +{ + if (rettv_list_alloc(rettv) == OK) + { +#ifdef FEAT_SEARCH_EXTRA + int id = (int)tv_get_number(&argvars[0]); + matchitem_T *m; + + if (id >= 1 && id <= 3) + { + 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, NULL, -1); + list_append_string(rettv->vval.v_list, NULL, -1); + } + } +#endif + } +} + +/* + * "matchdelete()" function + */ + void +f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_SEARCH_EXTRA + 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); +#endif +} diff --git a/src/json.c b/src/json.c --- a/src/json.c +++ b/src/json.c @@ -1127,3 +1127,52 @@ json_find_end(js_read_T *reader, int opt return ret; } #endif + +/* + * "js_decode()" function + */ + void +f_js_decode(typval_T *argvars, typval_T *rettv) +{ + js_read_T reader; + + reader.js_buf = tv_get_string(&argvars[0]); + reader.js_fill = NULL; + reader.js_used = 0; + if (json_decode_all(&reader, rettv, JSON_JS) != OK) + emsg(_(e_invarg)); +} + +/* + * "js_encode()" function + */ + void +f_js_encode(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = json_encode(&argvars[0], JSON_JS); +} + +/* + * "json_decode()" function + */ + void +f_json_decode(typval_T *argvars, typval_T *rettv) +{ + js_read_T reader; + + reader.js_buf = tv_get_string(&argvars[0]); + reader.js_fill = NULL; + reader.js_used = 0; + json_decode_all(&reader, rettv, 0); +} + +/* + * "json_encode()" function + */ + void +f_json_encode(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = json_encode(&argvars[0], 0); +} diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro --- a/src/proto/evalfunc.pro +++ b/src/proto/evalfunc.pro @@ -7,6 +7,7 @@ linenr_T tv_get_lnum(typval_T *argvars); buf_T *buflist_find_by_name(char_u *name, int curtab_only); buf_T *tv_get_buf(typval_T *tv, int curtab_only); buf_T *get_buf_arg(typval_T *arg); +win_T *get_optional_window(typval_T *argvars, int idx); void execute_redir_str(char_u *value, int value_len); void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv); float_T vim_round(float_T f); diff --git a/src/proto/highlight.pro b/src/proto/highlight.pro --- a/src/proto/highlight.pro +++ b/src/proto/highlight.pro @@ -43,4 +43,13 @@ void set_context_in_highlight_cmd(expand char_u *get_highlight_name(expand_T *xp, int idx); char_u *get_highlight_name_ext(expand_T *xp, int idx, int skip_cleared); void free_highlight_fonts(void); +int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list, char_u *conceal_char); +int match_delete(win_T *wp, int id, int perr); +void clear_matches(win_T *wp); +matchitem_T *get_match(win_T *wp, int id); +void f_getmatches(typval_T *argvars, typval_T *rettv); +void f_matchadd(typval_T *argvars, typval_T *rettv); +void f_matchaddpos(typval_T *argvars, typval_T *rettv); +void f_matcharg(typval_T *argvars, typval_T *rettv); +void f_matchdelete(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/proto/json.pro b/src/proto/json.pro --- a/src/proto/json.pro +++ b/src/proto/json.pro @@ -4,4 +4,8 @@ char_u *json_encode_nr_expr(int nr, typv int json_decode_all(js_read_T *reader, typval_T *res, int options); int json_decode(js_read_T *reader, typval_T *res, int options); int json_find_end(js_read_T *reader, int options); +void f_js_decode(typval_T *argvars, typval_T *rettv); +void f_js_encode(typval_T *argvars, typval_T *rettv); +void f_json_decode(typval_T *argvars, typval_T *rettv); +void f_json_encode(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/proto/window.pro b/src/proto/window.pro --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -84,10 +84,6 @@ void restore_win_noblock(win_T *save_cur void switch_buffer(bufref_T *save_curbuf, buf_T *buf); void restore_buffer(bufref_T *save_curbuf); int win_hasvertsplit(void); -int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list, char_u *conceal_char); -int match_delete(win_T *wp, int id, int perr); -void clear_matches(win_T *wp); -matchitem_T *get_match(win_T *wp, int id); int get_win_number(win_T *wp, win_T *first_win); int get_tab_number(tabpage_T *tp); int win_getid(typval_T *argvars); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1734, +/**/ 1733, /**/ 1732, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -4589,7 +4589,11 @@ win_enter_ext( redraw_later(VALID); /* causes status line redraw */ /* set window height to desired minimal value */ - if (curwin->w_height < p_wh && !curwin->w_p_wfh) + if (curwin->w_height < p_wh && !curwin->w_p_wfh +#ifdef FEAT_TEXT_PROP + && !popup_is_popup(curwin) +#endif + ) win_setheight((int)p_wh); else if (curwin->w_height == 0) win_setheight(1); @@ -6669,300 +6673,6 @@ win_hasvertsplit(void) } #endif -#if defined(FEAT_SEARCH_EXTRA) || defined(PROTO) -/* - * 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). - * 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, - list_T *pos_list, - char_u *conceal_char UNUSED) /* pointer to conceal replacement char */ -{ - 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: %d (must be greater than or equal to 1)"), id); - return -1; - } - if (id != -1) - { - cur = wp->w_match_head; - while (cur != NULL) - { - if (cur->id == id) - { - semsg(_("E801: ID already taken: %d"), id); - return -1; - } - cur = cur->next; - } - } - if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) - { - semsg(_(e_nogroup), grp); - return -1; - } - if (pat != NULL && (regprog = vim_regcomp(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 = ALLOC_CLEAR_ONE(matchitem_T); - m->id = id; - m->priority = prio; - m->pattern = pat == NULL ? NULL : vim_strsave(pat); - m->hlg_id = hlg_id; - m->match.regprog = regprog; - m->match.rmm_ic = FALSE; - m->match.rmm_maxcol = 0; -# if defined(FEAT_CONCEAL) - m->conceal_char = 0; - if (conceal_char != NULL) - m->conceal_char = (*mb_ptr2char)(conceal_char); -# endif - - /* 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; li != NULL && 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 = FALSE; - - 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 = tv_get_number_chk(&subli->li_tv, &error); - if (error == TRUE) - goto fail; - if (lnum == 0) - { - --i; - continue; - } - m->pos.pos[i].lnum = lnum; - subli = subli->li_next; - if (subli != NULL) - { - col = tv_get_number_chk(&subli->li_tv, &error); - if (error == TRUE) - goto fail; - subli = subli->li_next; - if (subli != NULL) - { - len = tv_get_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) - { - --i; - 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 + 1; - } - - /* 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(rtype); - return id; - -fail: - vim_free(m); - return -1; -} - -/* - * Delete match with ID 'id' in the match list of window 'wp'. - * Print error messages if 'perr' is TRUE. - */ - 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) - semsg(_("E802: Invalid ID: %d (must be greater than or equal to 1)"), - id); - return -1; - } - while (cur != NULL && cur->id != id) - { - prev = cur; - cur = cur->next; - } - if (cur == NULL) - { - if (perr == TRUE) - semsg(_("E803: ID not found: %d"), id); - return -1; - } - if (cur == prev) - wp->w_match_head = cur->next; - else - prev->next = cur->next; - vim_regfree(cur->match.regprog); - vim_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_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; - } - vim_free(cur); - redraw_later(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); - vim_free(wp->w_match_head->pattern); - vim_free(wp->w_match_head); - wp->w_match_head = m; - } - redraw_later(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; -} -#endif - #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO) int get_win_number(win_T *wp, win_T *first_win)