]> granicus.if.org Git - vim/commitdiff
patch 8.1.1734: the evalfunc.c file is too big v8.1.1734
authorBram Moolenaar <Bram@vim.org>
Mon, 22 Jul 2019 21:03:57 +0000 (23:03 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 22 Jul 2019 21:03:57 +0000 (23:03 +0200)
Problem:    The evalfunc.c file is too big.
Solution:   Move some functions to other files.

src/evalfunc.c
src/globals.h
src/highlight.c
src/json.c
src/proto/evalfunc.pro
src/proto/highlight.pro
src/proto/json.pro
src/proto/window.pro
src/version.c
src/window.c

index 864b623c5c70f8d51cc0443e12b959438ecda401..3fbeec26cfd5b89f43aa7e99894774e69e352191 100644 (file)
 # 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;
@@ -5284,74 +5273,6 @@ f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
 #endif
 }
 
-/*
- * "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
  */
@@ -7384,55 +7305,6 @@ f_join(typval_T *argvars, typval_T *rettv)
        rettv->vval.v_string = NULL;
 }
 
-/*
- * "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
  */
@@ -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
  */
index d5520017d65ccafa86b1bc5a0881c87eca792738..8b10de25e82957614b832f0351c0e7a6d96c3ee1 100644 (file)
@@ -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);
index 9322f962f709369e5472ab4292c709c80f0bcf3e..c962c7373de228c818a9137407ec103dd1e4f6b0 100644 (file)
@@ -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
+}
index 3a5de7092c957d354cd3e9a4ed6fb46f1fbc5114..c9a6230d260715b33fabd3b89fee01c4947869ba 100644 (file)
@@ -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);
+}
index 64a246d0fe857b776af31e562d2ca4d663e9defb..afd5f631eae9a6d82695282b9d8aaabd3290e55d 100644 (file)
@@ -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);
index ca4498140c119b9346bd0063b537616703b1d62c..9dcfdf4dd5d30e81604e6469d28868a8d0c69f77 100644 (file)
@@ -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 : */
index b98c2c9fb451356888fd1579f9167e7e64490e34..d8afe1fb6c5a94a281226bb432aeda5723222079 100644 (file)
@@ -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 : */
index 94b9f083a1ca6445b483f6c98f9979c21f659b93..e9af75b8a65305d9b83633a568e92a76d9292c18 100644 (file)
@@ -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);
index e544975d18caa2997befd6fb47ae6ca20369b46c..f3493f2d6496b23104a472490b2eac6cd1eaa202 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1734,
 /**/
     1733,
 /**/
index b40aae6b2baf570ffe4f85c8e0601b207d9c977d..8466c469404a3730b61b34faf1488196d9abf4b9 100644 (file)
@@ -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)