*: Move some dictionary functions to typval.h and use char*

Also fixes buffer reusage in setmatches() and complete().
This commit is contained in:
ZyX
2016-08-20 22:24:34 +03:00
parent 50a48f2a0e
commit e18a578308
52 changed files with 2215 additions and 1844 deletions

View File

@@ -2094,38 +2094,56 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
xfree(wca);
return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
flags, FALSE);
return ins_compl_add(IObuff, len, icase, fname, NULL, true, dir, flags,
false);
}
return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false);
}
/*
* Add a match to the list of matches.
* If the given string is already in the list of completions, then return
* NOTDONE, otherwise add it to the list and return OK. If there is an error
* then FAIL is returned.
*/
static int
ins_compl_add (
char_u *str,
int len,
int icase,
char_u *fname,
char_u **cptext, /* extra text for popup menu or NULL */
int cdir,
int flags,
int adup /* accept duplicate match */
)
/// Add a match to the list of matches
///
/// @param[in] str Match to add.
/// @param[in] len Match length, -1 to use #STRLEN.
/// @param[in] icase Whether case is to be ignored.
/// @param[in] fname File name match comes from. May be NULL.
/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
/// must have exactly #CPT_COUNT items.
/// @param[in] cptext_allocated If true, will not copy cptext strings.
///
/// @note Will free strings in case of error.
/// cptext itself will not be freed.
/// @param[in] cdir Completion direction.
/// @param[in] adup True if duplicate matches are to be accepted.
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
/// returned in case of error.
static int ins_compl_add(char_u *const str, int len,
const bool icase, char_u *const fname,
char_u *const *const cptext,
const bool cptext_allocated,
const Direction cdir, int flags, const bool adup)
FUNC_ATTR_NONNULL_ARG(1)
{
compl_T *match;
int dir = (cdir == 0 ? compl_direction : cdir);
int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
os_breakcheck();
if (got_int)
#define FREE_CPTEXT(cptext, cptext_allocated) \
do { \
if (cptext_allocated) { \
for (size_t i = 0; i < CPT_COUNT; i++) { \
xfree(cptext[i]); \
} \
} \
} while (0)
if (got_int) {
FREE_CPTEXT(cptext, cptext_allocated);
return FAIL;
if (len < 0)
}
if (len < 0) {
len = (int)STRLEN(str);
}
/*
* If the same match is already present, don't add it.
@@ -2133,10 +2151,12 @@ ins_compl_add (
if (compl_first_match != NULL && !adup) {
match = compl_first_match;
do {
if ( !(match->cp_flags & ORIGINAL_TEXT)
&& STRNCMP(match->cp_str, str, len) == 0
&& match->cp_str[len] == NUL)
if (!(match->cp_flags & ORIGINAL_TEXT)
&& STRNCMP(match->cp_str, str, len) == 0
&& match->cp_str[len] == NUL) {
FREE_CPTEXT(cptext, cptext_allocated);
return NOTDONE;
}
match = match->cp_next;
} while (match != NULL && match != compl_first_match);
}
@@ -2167,16 +2187,26 @@ ins_compl_add (
else if (fname != NULL) {
match->cp_fname = vim_strsave(fname);
flags |= FREE_FNAME;
} else
} else {
match->cp_fname = NULL;
}
match->cp_flags = flags;
if (cptext != NULL) {
int i;
for (i = 0; i < CPT_COUNT; ++i)
if (cptext[i] != NULL && *cptext[i] != NUL)
match->cp_text[i] = vim_strsave(cptext[i]);
for (i = 0; i < CPT_COUNT; i++) {
if (cptext[i] == NULL) {
continue;
}
if (*cptext[i] != NUL) {
match->cp_text[i] = (cptext_allocated
? cptext[i]
: (char_u *)xstrdup((char *)cptext[i]));
} else if (cptext_allocated) {
xfree(cptext[i]);
}
}
}
/*
@@ -2299,9 +2329,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
for (i = 0; i < num_matches && add_r != FAIL; i++)
if ((add_r = ins_compl_add(matches[i], -1, icase,
NULL, NULL, dir, 0, FALSE)) == OK)
/* if dir was BACKWARD then honor it just once */
NULL, NULL, false, dir, 0, false)) == OK) {
// If dir was BACKWARD then honor it just once.
dir = FORWARD;
}
FreeWild(num_matches, matches);
}
@@ -2365,8 +2396,8 @@ void set_completion(colnr_T startcol, list_T *list)
/* compl_pattern doesn't need to be set */
compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
compl_length);
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
ORIGINAL_TEXT, FALSE) != OK) {
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
ORIGINAL_TEXT, false) != OK) {
return;
}
@@ -2888,7 +2919,7 @@ static void ins_compl_clear(void)
compl_orig_text = NULL;
compl_enter_selects = FALSE;
// clear v:completed_item
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
/// Check that Insert completion is active.
@@ -3486,7 +3517,7 @@ expand_by_function (
theend:
if (matchdict != NULL) {
dict_unref(matchdict);
tv_dict_unref(matchdict);
}
if (matchlist != NULL) {
tv_list_unref(matchlist);
@@ -3519,53 +3550,60 @@ static void ins_compl_add_dict(dict_T *dict)
dictitem_T *di_refresh;
dictitem_T *di_words;
/* Check for optional "refresh" item. */
compl_opt_refresh_always = FALSE;
di_refresh = dict_find(dict, (char_u *)"refresh", 7);
// Check for optional "refresh" item.
compl_opt_refresh_always = false;
di_refresh = tv_dict_find(dict, S_LEN("refresh"));
if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
char_u *v = di_refresh->di_tv.vval.v_string;
const char *v = (const char *)di_refresh->di_tv.vval.v_string;
if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
compl_opt_refresh_always = TRUE;
if (v != NULL && strcmp(v, "always") == 0) {
compl_opt_refresh_always = true;
}
}
/* Add completions from a "words" list. */
di_words = dict_find(dict, (char_u *)"words", 5);
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
// Add completions from a "words" list.
di_words = tv_dict_find(dict, S_LEN("words"));
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
ins_compl_add_list(di_words->di_tv.vval.v_list);
}
}
/*
* Add a match to the list of matches from a typeval_T.
* If the given string is already in the list of completions, then return
* NOTDONE, otherwise add it to the list and return OK. If there is an error
* then FAIL is returned.
*/
int ins_compl_add_tv(typval_T *tv, int dir)
/// Add a match to the list of matches from VimL object
///
/// @param[in] tv Object to get matches from.
/// @param[in] dir Completion direction.
///
/// @return NOTDONE if the given string is already in the list of completions,
/// otherwise it is added to the list and OK is returned. FAIL will be
/// returned in case of error.
int ins_compl_add_tv(typval_T *const tv, const Direction dir)
FUNC_ATTR_NONNULL_ALL
{
char_u *word;
int icase = FALSE;
int adup = FALSE;
int aempty = FALSE;
char_u *(cptext[CPT_COUNT]);
const char *word;
bool icase = false;
bool adup = false;
bool aempty = false;
char *(cptext[CPT_COUNT]);
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
word = get_dict_string(tv->vval.v_dict, "word", false);
cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false);
cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false);
cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false);
cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false);
word = tv_dict_get_string(tv->vval.v_dict, "word", false);
cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true);
cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true);
cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true);
cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
icase = get_dict_number(tv->vval.v_dict, "icase");
adup = get_dict_number(tv->vval.v_dict, "dup");
aempty = get_dict_number(tv->vval.v_dict, "empty");
icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase");
adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
} else {
word = get_tv_string_chk(tv);
word = (const char *)get_tv_string_chk(tv);
memset(cptext, 0, sizeof(cptext));
}
if (word == NULL || (!aempty && *word == NUL))
if (word == NULL || (!aempty && *word == NUL)) {
return FAIL;
return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
}
return ins_compl_add((char_u *)word, -1, icase, NULL,
(char_u **)cptext, true, dir, 0, adup);
}
/*
@@ -3980,7 +4018,7 @@ static void ins_compl_delete(void)
// causes flicker, thus we can't do that.
changed_cline_bef_curs();
// clear v:completed_item
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
}
// Insert the new text being completed.
@@ -3995,7 +4033,7 @@ static void ins_compl_insert(int in_compl_func)
// Set completed item.
// { word, abbr, menu, kind, info }
dict_T *dict = dict_alloc();
dict_T *dict = tv_dict_alloc();
dict_add_nr_str(dict, "word", 0L,
EMPTY_IF_NULL(compl_shown_match->cp_str));
dict_add_nr_str(dict, "abbr", 0L,
@@ -4667,8 +4705,8 @@ static int ins_complete(int c, bool enable_pum)
/* Always add completion for the original text. */
xfree(compl_orig_text);
compl_orig_text = vim_strnsave(line + compl_col, compl_length);
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
ORIGINAL_TEXT, FALSE) != OK) {
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
ORIGINAL_TEXT, false) != OK) {
xfree(compl_pattern);
compl_pattern = NULL;
xfree(compl_orig_text);