summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-07-22 23:03:57 +0200
committerBram Moolenaar <Bram@vim.org>2019-07-22 23:03:57 +0200
commit29b7d7a9aac591f920edb89241c8cde27378e50b (patch)
tree96368a556edd943bec67f303778bc0c864573860 /src
parente5e6950193ddf365c6c507ddefcd7f9db939e5ac (diff)
patch 8.1.1734: the evalfunc.c file is too bigv8.1.1734
Problem: The evalfunc.c file is too big. Solution: Move some functions to other files.
Diffstat (limited to 'src')
-rw-r--r--src/evalfunc.c309
-rw-r--r--src/globals.h4
-rw-r--r--src/highlight.c543
-rw-r--r--src/json.c49
-rw-r--r--src/proto/evalfunc.pro1
-rw-r--r--src/proto/highlight.pro9
-rw-r--r--src/proto/json.pro4
-rw-r--r--src/proto/window.pro4
-rw-r--r--src/version.c2
-rw-r--r--src/window.c300
10 files changed, 616 insertions, 609 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 864b623c5c..3fbeec26cf 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -24,10 +24,8 @@
# include <time.h> /* 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, typval_T *rettv);
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, typval_T *rettv);
#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, typval_T *rettv);
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, typval_T *rettv)
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, typval_T *rettv UNUSED)
}
/*
- * "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 *rettv)
}
/*
- * "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 *rettv)
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
index d5520017d6..8b10de25e8 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1615,8 +1615,10 @@ EXTERN char e_invalidreg[] INIT(= N_("E850: Invalid register name"));
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
index 9322f962f7..c962c7373d 100644
--- 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
index 3a5de7092c..c9a6230d26 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1127,3 +1127,52 @@ json_find_end(js_read_T *reader, int options)
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
index 64a246d0fe..afd5f631ea 100644
--- 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
index ca4498140c..9dcfdf4dd5 100644
--- a/src/proto/highlight.pro
+++ b/src/proto/highlight.pro
@@ -43,4 +43,13 @@ void set_context_in_highlight_cmd(expand_T *xp, char_u *arg);
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
index b98c2c9fb4..d8afe1fb6c 100644
--- a/src/proto/json.pro
+++ b/src/proto/json.pro
@@ -4,4 +4,8 @@ char_u *json_encode_nr_expr(int nr, typval_T *val, int options);
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
index 94b9f083a1..e9af75b8a6 100644
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -84,10 +84,6 @@ void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, int no_disp
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
index e544975d18..f3493f2d64 100644
--- 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
index b40aae6b2b..8466c46940 100644
--- 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(