patch 9.1.0882: too many strlen() calls in insexpand.c
Problem: too many strlen() calls in insexpand.c
Solution: Refactor insexpand.c and reduce number of calls to STRLEN(),
fix a warning get_next_filename_completion(), add new function
ins_compl_leader_len() (John Marriott)
closes: #16095
Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/insexpand.c b/src/insexpand.c
index 9fe9fc5..6bc5075 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -95,7 +95,7 @@
{
compl_T *cp_next;
compl_T *cp_prev;
- char_u *cp_str; // matched text
+ string_T cp_str; // matched text
char_u *(cp_text[CPT_COUNT]); // text for the menu
#ifdef FEAT_EVAL
typval_T cp_user_data;
@@ -136,7 +136,7 @@
// When "compl_leader" is not NULL only matches that start with this string
// are used.
-static char_u *compl_leader = NULL;
+static string_T compl_leader = {NULL, 0};
static int compl_get_longest = FALSE; // put longest common string
// in compl_leader
@@ -162,8 +162,7 @@
static int ctrl_x_mode = CTRL_X_NORMAL;
static int compl_matches = 0; // number of completion matches
-static char_u *compl_pattern = NULL;
-static size_t compl_patternlen = 0;
+static string_T compl_pattern = {NULL, 0};
static int compl_direction = FORWARD;
static int compl_shows_dir = FORWARD;
static int compl_pending = 0; // > 1 for postponed CTRL-N
@@ -173,7 +172,7 @@
static int compl_length = 0;
static colnr_T compl_col = 0; // column where the text starts
// that is being completed
-static char_u *compl_orig_text = NULL; // text as it was before
+static string_T compl_orig_text = {NULL, 0}; // text as it was before
// completion started
static int compl_cont_mode = 0;
static expand_T compl_xp;
@@ -208,7 +207,7 @@
static void ins_compl_new_leader(void);
static int get_compl_len(void);
static void ins_compl_restart(void);
-static void ins_compl_set_original_text(char_u *str);
+static void ins_compl_set_original_text(char_u *str, size_t len);
static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
# if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
static void ins_compl_add_list(list_T *list);
@@ -560,7 +559,7 @@
wca[i] = *(p++);
// Rule 1: Were any chars converted to lower?
- p = compl_orig_text;
+ p = compl_orig_text.string;
for (i = 0; i < min_len; ++i)
{
if (has_mbyte)
@@ -584,7 +583,7 @@
// upper case.
if (!has_lower)
{
- p = compl_orig_text;
+ p = compl_orig_text.string;
for (i = 0; i < min_len; ++i)
{
if (has_mbyte)
@@ -603,7 +602,7 @@
}
// Copy the original case of the part we typed.
- p = compl_orig_text;
+ p = compl_orig_text.string;
for (i = 0; i < min_len; ++i)
{
if (has_mbyte)
@@ -651,7 +650,7 @@
}
*p = NUL;
STRCPY(gap.ga_data, IObuff);
- gap.ga_len = (int)STRLEN(IObuff);
+ gap.ga_len = (int)(p - IObuff);
}
else if (has_mbyte)
p += (*mb_char2bytes)(wca[i++], p);
@@ -715,7 +714,7 @@
// Find actual length of original text.
if (has_mbyte)
{
- p = compl_orig_text;
+ p = compl_orig_text.string;
compl_char_len = 0;
while (*p != NUL)
{
@@ -795,9 +794,9 @@
do
{
if (!match_at_original_text(match)
- && STRNCMP(match->cp_str, str, len) == 0
- && ((int)STRLEN(match->cp_str) <= len
- || match->cp_str[len] == NUL))
+ && STRNCMP(match->cp_str.string, str, len) == 0
+ && ((int)match->cp_str.length <= len
+ || match->cp_str.string[len] == NUL))
return NOTDONE;
match = match->cp_next;
} while (match != NULL && !is_first_match(match));
@@ -814,12 +813,14 @@
match->cp_number = -1;
if (flags & CP_ORIGINAL_TEXT)
match->cp_number = 0;
- if ((match->cp_str = vim_strnsave(str, len)) == NULL)
+ if ((match->cp_str.string = vim_strnsave(str, len)) == NULL)
{
vim_free(match);
return FAIL;
}
+ match->cp_str.length = len;
+
// match-fname is:
// - compl_curr_match->cp_fname if it is a string equal to fname.
// - a copy of fname, CP_FREE_FNAME is set to free later THE allocated mem.
@@ -892,8 +893,8 @@
if (match->cp_flags & CP_EQUAL)
return TRUE;
if (match->cp_flags & CP_ICASE)
- return STRNICMP(match->cp_str, str, (size_t)len) == 0;
- return STRNCMP(match->cp_str, str, (size_t)len) == 0;
+ return STRNICMP(match->cp_str.string, str, (size_t)len) == 0;
+ return STRNCMP(match->cp_str.string, str, (size_t)len) == 0;
}
/*
@@ -906,16 +907,17 @@
int c1, c2;
int had_match;
- if (compl_leader == NULL)
+ if (compl_leader.string == NULL)
{
// First match, use it as a whole.
- compl_leader = vim_strsave(match->cp_str);
- if (compl_leader == NULL)
+ compl_leader.string = vim_strnsave(match->cp_str.string, match->cp_str.length);
+ if (compl_leader.string == NULL)
return;
+ compl_leader.length = match->cp_str.length;
had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes(compl_leader.string + get_compl_len());
ins_redraw(FALSE);
// When the match isn't there (to avoid matching itself) remove it
@@ -928,8 +930,8 @@
}
// Reduce the text if this match differs from compl_leader.
- p = compl_leader;
- s = match->cp_str;
+ p = compl_leader.string;
+ s = match->cp_str.string;
while (*p != NUL)
{
if (has_mbyte)
@@ -961,9 +963,11 @@
{
// Leader was shortened, need to change the inserted text.
*p = NUL;
+ compl_leader.length = (size_t)(p - compl_leader.string);
+
had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes(compl_leader.string + get_compl_len());
ins_redraw(FALSE);
// When the match isn't there (to avoid matching itself) remove it
@@ -1040,7 +1044,7 @@
int
ins_compl_long_shown_match(void)
{
- return (int)STRLEN(compl_shown_match->cp_str)
+ return (int)compl_shown_match->cp_str.length
> curwin->w_cursor.col - compl_col;
}
@@ -1149,7 +1153,7 @@
if (dict == NULL)
return NULL;
- dict_add_string(dict, "word", match->cp_str);
+ dict_add_string(dict, "word", match->cp_str.string);
dict_add_string(dict, "abbr", match->cp_text[CPT_ABBR]);
dict_add_string(dict, "menu", match->cp_text[CPT_MENU]);
dict_add_string(dict, "kind", match->cp_text[CPT_KIND]);
@@ -1225,7 +1229,6 @@
int shown_match_ok = FALSE;
int i;
int cur = -1;
- int lead_len = 0;
int max_fuzzy_score = 0;
unsigned int cur_cot_flags = get_cot_flags();
int compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0;
@@ -1234,19 +1237,17 @@
// Need to build the popup menu list.
compl_match_arraysize = 0;
compl = compl_first_match;
- if (compl_leader != NULL)
- lead_len = (int)STRLEN(compl_leader);
do
{
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
// set the cp_score for later comparisons.
- if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0)
- compl->cp_score = fuzzy_match_str(compl->cp_str, compl_leader);
+ if (compl_fuzzy_match && compl_leader.string != NULL && compl_leader.length > 0)
+ compl->cp_score = fuzzy_match_str(compl->cp_str.string, compl_leader.string);
if (!match_at_original_text(compl)
- && (compl_leader == NULL
- || ins_compl_equal(compl, compl_leader, lead_len)
+ && (compl_leader.string == NULL
+ || ins_compl_equal(compl, compl_leader.string, (int)compl_leader.length)
|| (compl_fuzzy_match && compl->cp_score > 0)))
++compl_match_arraysize;
compl = compl->cp_next;
@@ -1264,8 +1265,8 @@
if (match_at_original_text(compl_shown_match))
shown_match_ok = TRUE;
- if (compl_leader != NULL
- && STRCMP(compl_leader, compl_orig_text) == 0
+ if (compl_leader.string != NULL
+ && STRCMP(compl_leader.string, compl_orig_text.string) == 0
&& shown_match_ok == FALSE)
compl_shown_match = compl_no_select ? compl_first_match
: compl_first_match->cp_next;
@@ -1275,8 +1276,8 @@
do
{
if (!match_at_original_text(compl)
- && (compl_leader == NULL
- || ins_compl_equal(compl, compl_leader, lead_len)
+ && (compl_leader.string == NULL
+ || ins_compl_equal(compl, compl_leader.string, (int)compl_leader.length)
|| (compl_fuzzy_match && compl->cp_score > 0)))
{
if (!shown_match_ok && !compl_fuzzy_match)
@@ -1321,7 +1322,7 @@
// reset the current index.
if (!compl_no_select
&& (max_fuzzy_score > 0
- || (compl_leader == NULL || lead_len == 0)))
+ || (compl_leader.string == NULL || compl_leader.length == 0)))
{
if (match_at_original_text(compl_shown_match))
compl_shown_match = shown_compl;
@@ -1331,7 +1332,7 @@
if (compl->cp_text[CPT_ABBR] != NULL)
compl_match_array[i].pum_text = compl->cp_text[CPT_ABBR];
else
- compl_match_array[i].pum_text = compl->cp_str;
+ compl_match_array[i].pum_text = compl->cp_str.string;
compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
compl_match_array[i].pum_score = compl->cp_score;
@@ -1364,7 +1365,7 @@
compl = compl->cp_next;
} while (compl != NULL && !is_first_match(compl));
- if (compl_fuzzy_match && compl_leader != NULL && lead_len > 0)
+ if (compl_fuzzy_match && compl_leader.string != NULL && compl_leader.length > 0)
{
for (i = 0; i < compl_match_arraysize; i++)
compl_match_array[i].pum_idx = i;
@@ -1404,7 +1405,7 @@
{
// popup menu already exists, only need to find the current item.
for (i = 0; i < compl_match_arraysize; ++i)
- if (compl_match_array[i].pum_text == compl_shown_match->cp_str
+ if (compl_match_array[i].pum_text == compl_shown_match->cp_str.string
|| compl_match_array[i].pum_text
== compl_shown_match->cp_text[CPT_ABBR])
{
@@ -1453,7 +1454,16 @@
char_u *
ins_compl_leader(void)
{
- return compl_leader != NULL ? compl_leader : compl_orig_text;
+ return compl_leader.string != NULL ? compl_leader.string : compl_orig_text.string;
+}
+
+/*
+ * Get current completion leader length
+ */
+ size_t
+ins_compl_leader_len(void)
+{
+ return compl_leader.string != NULL ? compl_leader.length : compl_orig_text.length;
}
/*
@@ -1778,9 +1788,8 @@
compl_T *match;
int i;
- VIM_CLEAR(compl_pattern);
- compl_patternlen = 0;
- VIM_CLEAR(compl_leader);
+ VIM_CLEAR_STRING(compl_pattern);
+ VIM_CLEAR_STRING(compl_leader);
if (compl_first_match == NULL)
return;
@@ -1793,7 +1802,7 @@
{
match = compl_curr_match;
compl_curr_match = compl_curr_match->cp_next;
- vim_free(match->cp_str);
+ VIM_CLEAR_STRING(match->cp_str);
// several entries may use the same fname, free it just once.
if (match->cp_flags & CP_FREE_FNAME)
vim_free(match->cp_fname);
@@ -1818,11 +1827,10 @@
compl_cont_status = 0;
compl_started = FALSE;
compl_matches = 0;
- VIM_CLEAR(compl_pattern);
- compl_patternlen = 0;
- VIM_CLEAR(compl_leader);
+ VIM_CLEAR_STRING(compl_pattern);
+ VIM_CLEAR_STRING(compl_leader);
edit_submode_extra = NULL;
- VIM_CLEAR(compl_orig_text);
+ VIM_CLEAR_STRING(compl_orig_text);
compl_enter_selects = FALSE;
#ifdef FEAT_EVAL
// clear v:completed_item
@@ -1927,10 +1935,14 @@
|| ins_compl_need_restart())
ins_compl_restart();
- vim_free(compl_leader);
- compl_leader = vim_strnsave(line + compl_col, (p - line) - compl_col);
- if (compl_leader == NULL)
+ VIM_CLEAR_STRING(compl_leader);
+ compl_leader.length = (size_t)((p - line) - compl_col);
+ compl_leader.string = vim_strnsave(line + compl_col, compl_leader.length);
+ if (compl_leader.string == NULL)
+ {
+ compl_leader.length = 0;
return K_BS;
+ }
ins_compl_new_leader();
if (compl_shown_match != NULL)
@@ -1963,11 +1975,11 @@
{
ins_compl_del_pum();
ins_compl_delete();
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes(compl_leader.string + get_compl_len());
compl_used_match = FALSE;
if (compl_started)
- ins_compl_set_original_text(compl_leader);
+ ins_compl_set_original_text(compl_leader.string, compl_leader.length);
else
{
#ifdef FEAT_SPELL
@@ -2052,11 +2064,17 @@
// break redo.
if (!compl_opt_refresh_always)
{
- vim_free(compl_leader);
- compl_leader = vim_strnsave(ml_get_curline() + compl_col,
- curwin->w_cursor.col - compl_col);
- if (compl_leader != NULL)
- ins_compl_new_leader();
+ VIM_CLEAR_STRING(compl_leader);
+ compl_leader.length = (size_t)(curwin->w_cursor.col - compl_col);
+ compl_leader.string = vim_strnsave(ml_get_curline() + compl_col,
+ compl_leader.length);
+ if (compl_leader.string == NULL)
+ {
+ compl_leader.length = 0;
+ return;
+ }
+
+ ins_compl_new_leader();
}
}
@@ -2078,31 +2096,31 @@
* Set the first match, the original text.
*/
static void
-ins_compl_set_original_text(char_u *str)
+ins_compl_set_original_text(char_u *str, size_t len)
{
- char_u *p;
-
// Replace the original text entry.
// The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
// be at the last item for backward completion
if (match_at_original_text(compl_first_match)) // safety check
{
- p = vim_strsave(str);
+ char_u *p = vim_strnsave(str, len);
if (p != NULL)
{
- vim_free(compl_first_match->cp_str);
- compl_first_match->cp_str = p;
+ VIM_CLEAR_STRING(compl_first_match->cp_str);
+ compl_first_match->cp_str.string = p;
+ compl_first_match->cp_str.length = len;
}
}
else if (compl_first_match->cp_prev != NULL
&& match_at_original_text(compl_first_match->cp_prev))
{
- p = vim_strsave(str);
- if (p != NULL)
- {
- vim_free(compl_first_match->cp_prev->cp_str);
- compl_first_match->cp_prev->cp_str = p;
- }
+ char_u *p = vim_strnsave(str, len);
+ if (p != NULL)
+ {
+ VIM_CLEAR_STRING(compl_first_match->cp_prev->cp_str);
+ compl_first_match->cp_prev->cp_str.string = p;
+ compl_first_match->cp_prev->cp_str.length = len;
+ }
}
}
@@ -2116,29 +2134,33 @@
char_u *p;
int len = (int)curwin->w_cursor.col - (int)compl_col;
int c;
- compl_T *cp;
- p = compl_shown_match->cp_str;
- if ((int)STRLEN(p) <= len) // the match is too short
+ p = compl_shown_match->cp_str.string;
+ if ((int)compl_shown_match->cp_str.length <= len) // the match is too short
{
+ size_t plen;
+ compl_T *cp;
+
// When still at the original match use the first entry that matches
// the leader.
if (!match_at_original_text(compl_shown_match))
return;
p = NULL;
+ plen = 0;
for (cp = compl_shown_match->cp_next; cp != NULL
&& !is_first_match(cp); cp = cp->cp_next)
{
- if (compl_leader == NULL
- || ins_compl_equal(cp, compl_leader,
- (int)STRLEN(compl_leader)))
+ if (compl_leader.string == NULL
+ || ins_compl_equal(cp, compl_leader.string,
+ (int)compl_leader.length))
{
- p = cp->cp_str;
+ p = cp->cp_str.string;
+ plen = cp->cp_str.length;
break;
}
}
- if (p == NULL || (int)STRLEN(p) <= len)
+ if (p == NULL || (int)plen <= len)
return;
}
p += len;
@@ -2284,14 +2306,15 @@
static int
ins_compl_stop(int c, int prev_mode, int retval)
{
- char_u *ptr;
int want_cindent;
// Get here when we have finished typing a sequence of ^N and
// ^P or other completion characters in CTRL-X mode. Free up
// memory that was used, and make sure we can redo the insert.
- if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
+ if (compl_curr_match != NULL || compl_leader.string != NULL || c == Ctrl_E)
{
+ char_u *ptr;
+
// If any of the original typed text has been changed, eg when
// ignorecase is set, we must add back-spaces to the redo
// buffer. We add as few as necessary to delete just the part
@@ -2299,7 +2322,7 @@
// When using the longest match, edited the match or used
// CTRL-E then don't use the current match.
if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
- ptr = compl_curr_match->cp_str;
+ ptr = compl_curr_match->cp_str.string;
else
ptr = NULL;
ins_compl_fixRedoBufForLeader(ptr);
@@ -2346,19 +2369,25 @@
if (c == Ctrl_E)
{
char_u *p = NULL;
+ size_t plen = 0;
ins_compl_delete();
- if (compl_leader != NULL)
- p = compl_leader;
+ if (compl_leader.string != NULL)
+ {
+ p = compl_leader.string;
+ plen = compl_leader.length;
+ }
else if (compl_first_match != NULL)
- p = compl_orig_text;
+ {
+ p = compl_orig_text.string;
+ plen = compl_orig_text.length;
+ }
if (p != NULL)
{
int compl_len = get_compl_len();
- int len = (int)STRLEN(p);
- if (len > compl_len)
- ins_bytes_len(p + compl_len, len - compl_len);
+ if ((int)plen > compl_len)
+ ins_bytes_len(p + compl_len, (int)(plen - compl_len));
}
retval = TRUE;
}
@@ -2536,20 +2565,20 @@
static void
ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
{
- int len;
+ int len = 0;
char_u *p;
char_u *ptr = ptr_arg;
if (ptr == NULL)
{
- if (compl_leader != NULL)
- ptr = compl_leader;
+ if (compl_leader.string != NULL)
+ ptr = compl_leader.string;
else
return; // nothing to do
}
- if (compl_orig_text != NULL)
+ if (compl_orig_text.string != NULL)
{
- p = compl_orig_text;
+ p = compl_orig_text.string;
for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len)
;
if (len > 0)
@@ -2557,8 +2586,6 @@
for (p += len; *p != NUL; MB_PTR_ADV(p))
AppendCharToRedobuff(K_BS);
}
- else
- len = 0;
if (ptr != NULL)
AppendToRedobuffLit(ptr + len, -1);
}
@@ -2988,12 +3015,18 @@
compl_col = startcol;
compl_length = (int)curwin->w_cursor.col - (int)startcol;
// compl_pattern doesn't need to be set
- compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
+ compl_orig_text.string = vim_strnsave(ml_get_curline() + compl_col, (size_t)compl_length);
if (p_ic)
flags |= CP_ICASE;
- if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
- -1, NULL, NULL, NULL, 0,
- flags | CP_FAST, FALSE, NULL) != OK)
+ if (compl_orig_text.string == NULL)
+ {
+ compl_orig_text.length = 0;
+ return;
+ }
+ compl_orig_text.length = (size_t)compl_length;
+ if (ins_compl_add(compl_orig_text.string,
+ (int)compl_orig_text.length, NULL, NULL, NULL, 0,
+ flags | CP_FAST, FALSE, NULL) != OK)
return;
ctrl_x_mode = CTRL_X_EVAL;
@@ -3223,7 +3256,7 @@
ret = list_append_dict(li, di);
if (ret != OK)
return;
- dict_add_string(di, "word", match->cp_str);
+ dict_add_string(di, "word", match->cp_str.string);
dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
@@ -3470,8 +3503,8 @@
static void
get_next_include_file_completion(int compl_type)
{
- find_pattern_in_path(compl_pattern, compl_direction,
- (int)compl_patternlen, FALSE, FALSE,
+ find_pattern_in_path(compl_pattern.string, compl_direction,
+ (int)compl_pattern.length, FALSE, FALSE,
(compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
@@ -3488,7 +3521,7 @@
{
#ifdef FEAT_COMPL_FUNC
if (thesaurus_func_complete(compl_type))
- expand_by_function(compl_type, compl_pattern);
+ expand_by_function(compl_type, compl_pattern.string);
else
#endif
ins_compl_dictionaries(
@@ -3496,7 +3529,7 @@
: (compl_type == CTRL_X_THESAURUS
? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
: (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
- compl_pattern,
+ compl_pattern.string,
dict != NULL ? dict_f : 0,
compl_type == CTRL_X_THESAURUS);
}
@@ -3513,12 +3546,12 @@
// set p_ic according to p_ic, p_scs and pat for find_tags().
save_p_ic = p_ic;
- p_ic = ignorecase(compl_pattern);
+ p_ic = ignorecase(compl_pattern.string);
// Find up to TAG_MANY matches. Avoids that an enormous number
// of matches is found when compl_pattern is empty
g_tag_at_cursor = TRUE;
- if (find_tags(compl_pattern, &num_matches, &matches,
+ if (find_tags(compl_pattern.string, &num_matches, &matches,
TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
| (ctrl_x_mode_not_default() ? TAG_VERBOSE : 0),
TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
@@ -3553,13 +3586,11 @@
int i;
int score;
char_u *leader = ins_compl_leader();
- size_t leader_len = STRLEN(leader);
+ size_t leader_len = ins_compl_leader_len();;
int in_fuzzy = ((get_cot_flags() & COT_FUZZY) != 0 && leader_len > 0);
char_u **sorted_matches;
int *fuzzy_indices_data;
char_u *last_sep = NULL;
- size_t path_with_wildcard_len;
- char_u *path_with_wildcard;
#ifdef BACKSLASH_IN_FILENAME
char pathsep = (curbuf->b_p_csl[0] == 's') ?
@@ -3573,7 +3604,7 @@
#ifdef BACKSLASH_IN_FILENAME
if (curbuf->b_p_csl[0] == 's')
{
- for (i = 0; i < leader_len; i++)
+ for (i = 0; i < (int)leader_len; i++)
{
if (leader[i] == '\\')
leader[i] = '/';
@@ -3581,7 +3612,7 @@
}
else if (curbuf->b_p_csl[0] == 'b')
{
- for (i = 0; i < leader_len; i++)
+ for (i = 0; i < (int)leader_len; i++)
{
if (leader[i] == '/')
leader[i] = '\\';
@@ -3593,9 +3624,11 @@
{
// No path separator or separator is the last character,
// fuzzy match the whole leader
- vim_free(compl_pattern);
- compl_pattern = vim_strsave((char_u *)"*");
- compl_patternlen = STRLEN(compl_pattern);
+ VIM_CLEAR_STRING(compl_pattern);
+ compl_pattern.string = vim_strnsave((char_u *)"*", 1);
+ if (compl_pattern.string == NULL)
+ return;
+ compl_pattern.length = 1;
}
else if (*(last_sep + 1) == '\0')
in_fuzzy = FALSE;
@@ -3603,29 +3636,29 @@
{
// Split leader into path and file parts
int path_len = last_sep - leader + 1;
- path_with_wildcard_len = path_len + 2;
- path_with_wildcard = alloc(path_with_wildcard_len);
+ char_u *path_with_wildcard;
+
+ path_with_wildcard = alloc(path_len + 2);
if (path_with_wildcard != NULL)
{
- vim_strncpy(path_with_wildcard, leader, path_len);
- vim_strcat(path_with_wildcard, (char_u *)"*", path_with_wildcard_len);
- vim_free(compl_pattern);
- compl_pattern = path_with_wildcard;
- compl_patternlen = STRLEN(compl_pattern);
+ vim_snprintf((char *)path_with_wildcard, path_len + 2, "%*.*s*", path_len, path_len, leader);
+ VIM_CLEAR_STRING(compl_pattern);
+ compl_pattern.string = path_with_wildcard;
+ compl_pattern.length = path_len + 1;
// Move leader to the file part
leader = last_sep + 1;
- leader_len = STRLEN(leader);
+ leader_len -= path_len;
}
}
}
- if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
+ if (expand_wildcards(1, &compl_pattern.string, &num_matches, &matches,
EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK)
return;
// May change home directory back to "~".
- tilde_replace(compl_pattern, num_matches, matches);
+ tilde_replace(compl_pattern.string, num_matches, matches);
#ifdef BACKSLASH_IN_FILENAME
if (curbuf->b_p_csl[0] != NUL)
{
@@ -3701,8 +3734,8 @@
char_u **matches;
int num_matches;
- if (expand_cmdline(&compl_xp, compl_pattern,
- (int)compl_patternlen, &num_matches, &matches) == EXPAND_OK)
+ if (expand_cmdline(&compl_xp, compl_pattern.string,
+ (int)compl_pattern.length, &num_matches, &matches) == EXPAND_OK)
ins_compl_add_matches(num_matches, matches, FALSE);
}
@@ -3716,7 +3749,7 @@
char_u **matches;
int num_matches;
- num_matches = expand_spelling(lnum, compl_pattern, &matches);
+ num_matches = expand_spelling(lnum, compl_pattern.string, &matches);
if (num_matches > 0)
ins_compl_add_matches(num_matches, matches, p_ic);
else
@@ -3741,6 +3774,7 @@
*match_len = 0;
ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, FALSE) +
cur_match_pos->col;
+ len = (int)ml_get_buf_len(ins_buf, cur_match_pos->lnum) - cur_match_pos->col;
if (ctrl_x_mode_line_or_eval())
{
if (compl_status_adding())
@@ -3748,16 +3782,21 @@
if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count)
return NULL;
ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, FALSE);
+ len = ml_get_buf_len(ins_buf, cur_match_pos->lnum + 1);
if (!p_paste)
- ptr = skipwhite(ptr);
+ {
+ char_u *tmp_ptr = ptr;
+
+ ptr = skipwhite(tmp_ptr);
+ len -= (int)(ptr - tmp_ptr);
+ }
}
- len = (int)STRLEN(ptr);
}
else
{
char_u *tmp_ptr = ptr;
- if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr))
+ if (compl_status_adding() && compl_length <= len)
{
tmp_ptr += compl_length;
// Skip if already inside a word.
@@ -3866,14 +3905,14 @@
// has added a word that was at the beginning of the line
if ((ctrl_x_mode_whole_line() && !in_fuzzy) || ctrl_x_mode_eval() || (compl_cont_status & CONT_SOL))
found_new_match = search_for_exact_line(st->ins_buf,
- st->cur_match_pos, compl_direction, compl_pattern);
+ st->cur_match_pos, compl_direction, compl_pattern.string);
else if (in_fuzzy)
found_new_match = search_for_fuzzy_match(st->ins_buf,
st->cur_match_pos, leader, compl_direction,
start_pos, &len, &ptr, ctrl_x_mode_whole_line());
else
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
- NULL, compl_direction, compl_pattern, compl_patternlen,
+ NULL, compl_direction, compl_pattern.string, (int)compl_pattern.length,
1L, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
--msg_silent;
if (!compl_started || st->set_match_pos)
@@ -3981,7 +4020,7 @@
#ifdef FEAT_COMPL_FUNC
case CTRL_X_FUNCTION:
case CTRL_X_OMNI:
- expand_by_function(type, compl_pattern);
+ expand_by_function(type, compl_pattern.string);
break;
#endif
@@ -4071,7 +4110,7 @@
// If complete() was called then compl_pattern has been reset. The
// following won't work then, bail out.
- if (compl_pattern == NULL)
+ if (compl_pattern.string == NULL)
break;
// get the next set of completion matches
@@ -4137,7 +4176,7 @@
ins_compl_update_shown_match(void)
{
while (!ins_compl_equal(compl_shown_match,
- compl_leader, (int)STRLEN(compl_leader))
+ compl_leader.string, (int)compl_leader.length)
&& compl_shown_match->cp_next != NULL
&& !is_first_match(compl_shown_match->cp_next))
compl_shown_match = compl_shown_match->cp_next;
@@ -4146,12 +4185,12 @@
// backward, find the last match.
if (compl_shows_dir_backward()
&& !ins_compl_equal(compl_shown_match,
- compl_leader, (int)STRLEN(compl_leader))
+ compl_leader.string, (int)compl_leader.length)
&& (compl_shown_match->cp_next == NULL
|| is_first_match(compl_shown_match->cp_next)))
{
while (!ins_compl_equal(compl_shown_match,
- compl_leader, (int)STRLEN(compl_leader))
+ compl_leader.string, (int)compl_leader.length)
&& compl_shown_match->cp_prev != NULL
&& !is_first_match(compl_shown_match->cp_prev))
compl_shown_match = compl_shown_match->cp_prev;
@@ -4196,8 +4235,8 @@
// Make sure we don't go over the end of the string, this can happen with
// illegal bytes.
- if (compl_len < (int)STRLEN(compl_shown_match->cp_str))
- ins_bytes(compl_shown_match->cp_str + compl_len);
+ if (compl_len < (int)compl_shown_match->cp_str.length)
+ ins_bytes(compl_shown_match->cp_str.string + compl_len);
if (match_at_original_text(compl_shown_match))
compl_used_match = FALSE;
else
@@ -4277,7 +4316,7 @@
comp = compl_first_match;
do {
- if (comp->cp_score == score && (str == comp->cp_str || str == comp->cp_text[CPT_ABBR]))
+ if (comp->cp_score == score && (str == comp->cp_str.string || str == comp->cp_text[CPT_ABBR]))
return comp;
comp = comp->cp_next;
} while (comp != NULL && !is_first_match(comp));
@@ -4374,9 +4413,9 @@
found_end = FALSE;
}
if (!match_at_original_text(compl_shown_match)
- && compl_leader != NULL
+ && compl_leader.string != NULL
&& !ins_compl_equal(compl_shown_match,
- compl_leader, (int)STRLEN(compl_leader))
+ compl_leader.string, (int)compl_leader.length)
&& !(compl_fuzzy_match && compl_shown_match->cp_score > 0))
++todo;
else
@@ -4436,7 +4475,7 @@
if (compl_shown_match == NULL)
return -1;
- if (compl_leader != NULL
+ if (compl_leader.string != NULL
&& !match_at_original_text(compl_shown_match)
&& !compl_fuzzy_match)
// Update "compl_shown_match" to the actually shown match
@@ -4474,7 +4513,7 @@
// Insert the text of the new completion, or the compl_leader.
if (compl_no_insert && !started)
{
- ins_bytes(compl_orig_text + get_compl_len());
+ ins_bytes(compl_orig_text.string + get_compl_len());
compl_used_match = FALSE;
}
else if (insert_match)
@@ -4482,7 +4521,7 @@
if (!compl_get_longest || compl_used_match)
ins_compl_insert(in_compl_func);
else
- ins_bytes(compl_leader + get_compl_len());
+ ins_bytes(compl_leader.string + get_compl_len());
}
else
compl_used_match = FALSE;
@@ -4662,8 +4701,7 @@
/*
* Get the pattern, column and length for normal completion (CTRL-N CTRL-P
* completion)
- * Sets the global variables: compl_col, compl_length, compl_pattern and
- * compl_patternlen.
+ * Sets the global variables: compl_col, compl_length and compl_pattern.
* Uses the global variables: compl_cont_status and ctrl_x_mode
*/
static int
@@ -4679,29 +4717,33 @@
compl_length = curs_col - startcol;
}
if (p_ic)
- compl_pattern = str_foldcase(line + compl_col,
- compl_length, NULL, 0);
- else
- compl_pattern = vim_strnsave(line + compl_col, compl_length);
- if (compl_pattern == NULL)
{
- compl_patternlen = 0;
- return FAIL;
+ compl_pattern.string = str_foldcase(line + compl_col,
+ compl_length, NULL, 0);
+ if (compl_pattern.string == NULL)
+ {
+ compl_pattern.length = 0;
+ return FAIL;
+ }
+ compl_pattern.length = STRLEN(compl_pattern.string);
+ }
+ else
+ {
+ compl_pattern.string = vim_strnsave(line + compl_col, (size_t)compl_length);
+ if (compl_pattern.string == NULL)
+ {
+ compl_pattern.length = 0;
+ return FAIL;
+ }
+ compl_pattern.length = (size_t)compl_length;
}
}
else if (compl_status_adding())
{
char_u *prefix = (char_u *)"\\<";
size_t prefixlen = STRLEN_LITERAL("\\<");
+ size_t n;
- // we need up to 2 extra chars for the prefix
- compl_pattern = alloc(quote_meta(NULL, line + compl_col,
- compl_length) + prefixlen);
- if (compl_pattern == NULL)
- {
- compl_patternlen = 0;
- return FAIL;
- }
if (!vim_iswordp(line + compl_col)
|| (compl_col > 0
&& (vim_iswordp(mb_prevptr(line, line + compl_col)))))
@@ -4709,20 +4751,33 @@
prefix = (char_u *)"";
prefixlen = 0;
}
- STRCPY((char *)compl_pattern, prefix);
- (void)quote_meta(compl_pattern + prefixlen,
+
+ // we need up to 2 extra chars for the prefix
+ n = quote_meta(NULL, line + compl_col, compl_length) + prefixlen;
+ compl_pattern.string = alloc(n);
+ if (compl_pattern.string == NULL)
+ {
+ compl_pattern.length = 0;
+ return FAIL;
+ }
+ STRCPY((char *)compl_pattern.string, prefix);
+ (void)quote_meta(compl_pattern.string + prefixlen,
line + compl_col, compl_length);
+ compl_pattern.length = n - 1;
}
else if (--startcol < 0
|| !vim_iswordp(mb_prevptr(line, line + startcol + 1)))
{
+ size_t len = STRLEN_LITERAL("\\<\\k\\k");
+
// Match any word of at least two chars
- compl_pattern = vim_strnsave((char_u *)"\\<\\k\\k", STRLEN_LITERAL("\\<\\k\\k"));
- if (compl_pattern == NULL)
+ compl_pattern.string = vim_strnsave((char_u *)"\\<\\k\\k", len);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
+ compl_pattern.length = len;
compl_col += curs_col;
compl_length = 0;
}
@@ -4756,32 +4811,34 @@
// Only match word with at least two chars -- webb
// there's no need to call quote_meta,
// alloc(7) is enough -- Acevedo
- compl_pattern = alloc(7);
- if (compl_pattern == NULL)
+ compl_pattern.string = alloc(7);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- STRCPY((char *)compl_pattern, "\\<");
- (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
- STRCAT((char *)compl_pattern, "\\k");
+ STRCPY((char *)compl_pattern.string, "\\<");
+ (void)quote_meta(compl_pattern.string + 2, line + compl_col, 1);
+ STRCAT((char *)compl_pattern.string, "\\k");
+ compl_pattern.length = STRLEN(compl_pattern.string);
}
else
{
- compl_pattern = alloc(quote_meta(NULL, line + compl_col,
- compl_length) + 2);
- if (compl_pattern == NULL)
+ size_t n = quote_meta(NULL, line + compl_col, compl_length) + 2;
+
+ compl_pattern.string = alloc(n);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- STRCPY((char *)compl_pattern, "\\<");
- (void)quote_meta(compl_pattern + 2, line + compl_col,
+ STRCPY((char *)compl_pattern.string, "\\<");
+ (void)quote_meta(compl_pattern.string + 2, line + compl_col,
compl_length);
+ compl_pattern.length = n - 1;
}
}
- compl_patternlen = STRLEN(compl_pattern);
return OK;
}
@@ -4798,17 +4855,26 @@
if (compl_length < 0) // cursor in indent: empty pattern
compl_length = 0;
if (p_ic)
- compl_pattern = str_foldcase(line + compl_col, compl_length,
- NULL, 0);
- else
- compl_pattern = vim_strnsave(line + compl_col, compl_length);
- if (compl_pattern == NULL)
{
- compl_patternlen = 0;
- return FAIL;
+ compl_pattern.string = str_foldcase(line + compl_col, compl_length,
+ NULL, 0);
+ if (compl_pattern.string == NULL)
+ {
+ compl_pattern.length = 0;
+ return FAIL;
+ }
+ compl_pattern.length = STRLEN(compl_pattern.string);
}
-
- compl_patternlen = STRLEN(compl_pattern);
+ else
+ {
+ compl_pattern.string = vim_strnsave(line + compl_col, (size_t)compl_length);
+ if (compl_pattern.string == NULL)
+ {
+ compl_pattern.length = 0;
+ return FAIL;
+ }
+ compl_pattern.length = (size_t)compl_length;
+ }
return OK;
}
@@ -4836,14 +4902,14 @@
compl_col += startcol;
compl_length = (int)curs_col - startcol;
- compl_pattern = addstar(line + compl_col, compl_length, EXPAND_FILES);
- if (compl_pattern == NULL)
+ compl_pattern.string = addstar(line + compl_col, compl_length, EXPAND_FILES);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- compl_patternlen = STRLEN(compl_pattern);
+ compl_pattern.length = STRLEN(compl_pattern.string);
return OK;
}
@@ -4855,22 +4921,22 @@
static int
get_cmdline_compl_info(char_u *line, colnr_T curs_col)
{
- compl_pattern = vim_strnsave(line, curs_col);
- if (compl_pattern == NULL)
+ compl_pattern.string = vim_strnsave(line, curs_col);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- compl_patternlen = curs_col;
- set_cmd_context(&compl_xp, compl_pattern,
- (int)compl_patternlen, curs_col, FALSE);
+ compl_pattern.length = curs_col;
+ set_cmd_context(&compl_xp, compl_pattern.string,
+ (int)compl_pattern.length, curs_col, FALSE);
if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
|| compl_xp.xp_context == EXPAND_NOTHING)
// No completion possible, use an empty pattern to get a
// "pattern not found" message.
compl_col = curs_col;
else
- compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
+ compl_col = (int)(compl_xp.xp_pattern - compl_pattern.string);
compl_length = curs_col - compl_col;
return OK;
@@ -4959,14 +5025,14 @@
// it may have become invalid.
line = ml_get(curwin->w_cursor.lnum);
compl_length = curs_col - compl_col;
- compl_pattern = vim_strnsave(line + compl_col, compl_length);
- if (compl_pattern == NULL)
+ compl_pattern.string = vim_strnsave(line + compl_col, (size_t)compl_length);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- compl_patternlen = compl_length;
+ compl_pattern.length = (size_t)compl_length;
ret = OK;
#endif
@@ -5001,14 +5067,14 @@
}
// Need to obtain "line" again, it may have become invalid.
line = ml_get(curwin->w_cursor.lnum);
- compl_pattern = vim_strnsave(line + compl_col, compl_length);
- if (compl_pattern == NULL)
+ compl_pattern.string = vim_strnsave(line + compl_col, (size_t)compl_length);
+ if (compl_pattern.string == NULL)
{
- compl_patternlen = 0;
+ compl_pattern.length = 0;
return FAIL;
}
- compl_patternlen = compl_length;
+ compl_pattern.length = (size_t)compl_length;
ret = OK;
#endif
@@ -5227,16 +5293,16 @@
ins_compl_fixRedoBufForLeader(NULL);
// Always add completion for the original text.
- vim_free(compl_orig_text);
- compl_orig_text = vim_strnsave(line + compl_col, compl_length);
+ VIM_CLEAR_STRING(compl_orig_text);
+ compl_orig_text.length = (size_t)compl_length;
+ compl_orig_text.string = vim_strnsave(line + compl_col, (size_t)compl_length);
if (p_ic)
flags |= CP_ICASE;
- if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
- -1, NULL, NULL, NULL, 0, flags, FALSE, NULL) != OK)
+ if (compl_orig_text.string == NULL || ins_compl_add(compl_orig_text.string,
+ (int)compl_orig_text.length, NULL, NULL, NULL, 0, flags, FALSE, NULL) != OK)
{
- VIM_CLEAR(compl_pattern);
- compl_patternlen = 0;
- VIM_CLEAR(compl_orig_text);
+ VIM_CLEAR_STRING(compl_pattern);
+ VIM_CLEAR_STRING(compl_orig_text);
return FAIL;
}
@@ -5505,7 +5571,7 @@
void
free_insexpand_stuff(void)
{
- VIM_CLEAR(compl_orig_text);
+ VIM_CLEAR_STRING(compl_orig_text);
# ifdef FEAT_EVAL
free_callback(&cfu_cb);
free_callback(&ofu_cb);