To: vim_dev@googlegroups.com Subject: Patch 8.1.1734 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1734 Problem: The evalfunc.c file is too big. Solution: Move some functions to other files. Files: src/evalfunc.c, src/proto/evalfunc.pro, src/json.c, src/proto/json.pro src/window.c, src/proto/window.pro, src/highlight.c, src/proto/highlight.pro, src/globals.h *** ../vim-8.1.1733/src/evalfunc.c 2019-07-14 14:55:20.368881426 +0200 --- src/evalfunc.c 2019-07-22 22:34:05.646370098 +0200 *************** *** 24,33 **** # 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); --- 24,31 ---- *************** *** 164,170 **** 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); --- 162,167 ---- *************** *** 213,222 **** #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); --- 210,215 ---- *************** *** 238,247 **** 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); --- 231,236 ---- *************** *** 2202,2208 **** rettv->vval.v_number = -1; } ! static win_T * get_optional_window(typval_T *argvars, int idx) { win_T *win = curwin; --- 2191,2197 ---- rettv->vval.v_number = -1; } ! win_T * get_optional_window(typval_T *argvars, int idx) { win_T *win = curwin; *************** *** 5285,5358 **** } /* - * "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 --- 5274,5279 ---- *************** *** 7385,7439 **** } /* - * "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 --- 7306,7311 ---- *************** *** 8071,8255 **** 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 */ --- 7943,7948 ---- *** ../vim-8.1.1733/src/proto/evalfunc.pro 2019-06-29 07:56:26.042876840 +0200 --- src/proto/evalfunc.pro 2019-07-22 22:32:35.018842500 +0200 *************** *** 7,12 **** --- 7,13 ---- 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); *** ../vim-8.1.1733/src/json.c 2019-05-27 20:01:38.117491996 +0200 --- src/json.c 2019-07-22 22:16:18.643827525 +0200 *************** *** 1127,1129 **** --- 1127,1178 ---- 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); + } *** ../vim-8.1.1733/src/proto/json.pro 2018-05-17 13:52:41.000000000 +0200 --- src/proto/json.pro 2019-07-22 22:17:19.803453591 +0200 *************** *** 4,7 **** --- 4,11 ---- 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 : */ *** ../vim-8.1.1733/src/window.c 2019-06-30 22:16:06.931821750 +0200 --- src/window.c 2019-07-22 22:22:56.545521038 +0200 *************** *** 4589,4595 **** redraw_later(VALID); /* causes status line redraw */ /* set window height to desired minimal value */ ! if (curwin->w_height < p_wh && !curwin->w_p_wfh) win_setheight((int)p_wh); else if (curwin->w_height == 0) win_setheight(1); --- 4589,4599 ---- redraw_later(VALID); /* causes status line redraw */ /* set window height to desired minimal value */ ! 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,6968 **** } #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) --- 6673,6678 ---- *** ../vim-8.1.1733/src/proto/window.pro 2019-06-13 23:59:46.788290732 +0200 --- src/proto/window.pro 2019-07-22 22:27:12.684427335 +0200 *************** *** 84,93 **** 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); --- 84,89 ---- *** ../vim-8.1.1733/src/highlight.c 2019-07-15 22:40:19.061741740 +0200 --- src/highlight.c 2019-07-22 22:33:59.650401624 +0200 *************** *** 8,14 **** */ /* ! * Highlighting stuff */ #include "vim.h" --- 8,15 ---- */ /* ! * Highlighting stuff. ! * Includes highlighting matches. */ #include "vim.h" *************** *** 3653,3655 **** --- 3654,4196 ---- # 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 + } *** ../vim-8.1.1733/src/proto/highlight.pro 2019-07-15 22:40:19.061741740 +0200 --- src/proto/highlight.pro 2019-07-22 22:34:09.478349929 +0200 *************** *** 43,46 **** --- 43,55 ---- 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 : */ *** ../vim-8.1.1733/src/globals.h 2019-07-21 19:25:16.654609424 +0200 --- src/globals.h 2019-07-22 22:30:53.003362161 +0200 *************** *** 1615,1622 **** 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")); #endif #ifdef FEAT_GUI_MAC EXTERN short disallow_gui INIT(= FALSE); --- 1615,1624 ---- 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")); #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); *** ../vim-8.1.1733/src/version.c 2019-07-22 22:08:54.294523746 +0200 --- src/version.c 2019-07-22 23:03:05.686486480 +0200 *************** *** 779,780 **** --- 779,782 ---- { /* Add new patch number below this line */ + /**/ + 1734, /**/ -- System administrators are just like women: You can't live with them and you can't live without them. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///