]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0882: too many strlen() calls in insexpand.c v9.1.0882
authorJohn Marriott <basilisk@internode.on.net>
Sat, 23 Nov 2024 13:01:57 +0000 (14:01 +0100)
committerChristian Brabandt <cb@256bit.org>
Sat, 23 Nov 2024 13:01:57 +0000 (14:01 +0100)
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>
src/insexpand.c
src/proto/insexpand.pro
src/version.c

index 9fe9fc5c56855e1f5234a61995b5fb2a2929e20f..6bc5075cbd84fff9db4fcf3406c9e03d59a4692b 100644 (file)
@@ -95,7 +95,7 @@ struct compl_S
 {
     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 @@ static int    compl_enter_selects = FALSE;
 
 // 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    compl_started = FALSE;
 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 pos_T          compl_startpos;
 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 int  ins_compl_need_restart(void);
 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 @@ ins_compl_infercase_gettext(
            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 @@ ins_compl_infercase_gettext(
     // 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 @@ ins_compl_infercase_gettext(
     }
 
     // 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 @@ ins_compl_infercase_gettext(
            }
            *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 @@ ins_compl_add_infercase(
        // 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 @@ ins_compl_add(
        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 @@ ins_compl_add(
     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 @@ ins_compl_equal(compl_T *match, char_u *str, int len)
     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 @@ ins_compl_longest_match(compl_T *match)
     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 @@ ins_compl_longest_match(compl_T *match)
     }
 
     // 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 @@ ins_compl_longest_match(compl_T *match)
     {
        // 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 @@ ins_compl_has_shown_match(void)
     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 @@ ins_compl_dict_alloc(compl_T *match)
     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 @@ ins_compl_build_pum(void)
     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 @@ ins_compl_build_pum(void)
     // 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 @@ ins_compl_build_pum(void)
     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 @@ ins_compl_build_pum(void)
     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 @@ ins_compl_build_pum(void)
                // 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 @@ ins_compl_build_pum(void)
            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 @@ ins_compl_build_pum(void)
        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 @@ ins_compl_show_pum(void)
     {
        // 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 @@ ins_compl_show_pum(void)
     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 @@ ins_compl_free(void)
     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 @@ ins_compl_free(void)
     {
        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 @@ ins_compl_clear(void)
     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_bs(void)
                                                  || 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_new_leader(void)
 {
     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 @@ ins_compl_addleader(int c)
     // 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 @@ ins_compl_restart(void)
  * 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 @@ ins_compl_addfrommatch(void)
     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 @@ set_ctrl_x_mode(int c)
     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 @@ ins_compl_stop(int c, int prev_mode, int retval)
        // 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 @@ ins_compl_stop(int c, int prev_mode, int retval)
     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 @@ ins_compl_prep(int c)
     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 @@ ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
        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 @@ set_completion(colnr_T startcol, list_T *list)
     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 @@ get_complete_info(list_T *what_list, dict_T *retdict)
                        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 @@ done:
     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 @@ get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f)
 {
 #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 @@ get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f)
                : (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 @@ get_next_tag_completion(void)
 
     // 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 @@ get_next_filename_completion(void)
     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 @@ get_next_filename_completion(void)
 #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 @@ get_next_filename_completion(void)
        }
        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 @@ get_next_filename_completion(void)
        {
            // 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 @@ get_next_filename_completion(void)
        {
            // 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 @@ get_next_cmdline_completion(void)
     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 @@ get_next_spell_completion(linenr_T lnum UNUSED)
     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 @@ ins_compl_get_next_word_or_line(
     *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 @@ ins_compl_get_next_word_or_line(
            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 @@ get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
        // 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 @@ get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
 #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 @@ ins_compl_get_exp(pos_T *ini)
 
        // 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_get_exp(pos_T *ini)
 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 @@ ins_compl_update_shown_match(void)
     // 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 @@ ins_compl_insert(int in_compl_func)
 
     // 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 @@ find_comp_when_fuzzy(void)
 
     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 @@ find_next_completion_match(
            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 @@ ins_compl_next(
     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 @@ ins_compl_next(
     // 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 @@ ins_compl_next(
        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 @@ ins_compl_use_match(int c)
 /*
  * 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 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
            compl_length = curs_col - startcol;
        }
        if (p_ic)
-           compl_pattern = str_foldcase(line + compl_col,
+       {
+           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 = vim_strnsave(line + compl_col, compl_length);
-       if (compl_pattern == NULL)
        {
-           compl_patternlen = 0;
-           return FAIL;
+           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 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
            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 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
            // 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,18 +4855,27 @@ get_wholeline_compl_info(char_u *line, colnr_T curs_col)
     if (compl_length < 0)      // cursor in indent: empty pattern
        compl_length = 0;
     if (p_ic)
-       compl_pattern = str_foldcase(line + compl_col, compl_length,
+    {
+       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 = vim_strnsave(line + compl_col, compl_length);
-    if (compl_pattern == NULL)
     {
-       compl_patternlen = 0;
-       return FAIL;
+       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;
     }
 
-    compl_patternlen = STRLEN(compl_pattern);
-
     return OK;
 }
 
@@ -4836,14 +4902,14 @@ get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col)
 
     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 @@ get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col)
     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 @@ get_userdefined_compl_info(colnr_T curs_col UNUSED)
     // 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 @@ get_spell_compl_info(int startcol UNUSED, colnr_T curs_col UNUSED)
     }
     // 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_start(void)
     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 @@ quote_meta(char_u *dest, char_u *src, int len)
     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);
index dbd5ef7efa67f488c561e0e3eeed38a99217127f..4feab85854d4aee02141744bcd0e7c3a5ee951d4 100644 (file)
@@ -31,6 +31,7 @@ unsigned int get_cot_flags(void);
 int pum_wanted(void);
 void ins_compl_show_pum(void);
 char_u *ins_compl_leader(void);
+size_t ins_compl_leader_len(void);
 char_u *find_word_start(char_u *ptr);
 char_u *find_word_end(char_u *ptr);
 void ins_compl_clear(void);
index 4eea94afc32bd4c6f9c195c5938ba79d37c20925..9adbf9ba80fe7ed27b07da72bbecb3108a0be457 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    882,
 /**/
     881,
 /**/