diff options
Diffstat (limited to 'src/nvim/insexpand.c')
-rw-r--r-- | src/nvim/insexpand.c | 658 |
1 files changed, 387 insertions, 271 deletions
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index ba0a36cafe..fa8e78f624 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -4,11 +4,15 @@ // insexpand.c: functions for Insert mode completion #include <assert.h> -#include <inttypes.h> +#include <limits.h> #include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> #include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/change.h" #include "nvim/charset.h" @@ -18,36 +22,48 @@ #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/eval/userfunc.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/fileio.h" +#include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/highlight_defs.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/insexpand.h" #include "nvim/keycodes.h" +#include "nvim/macros.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" #include "nvim/option.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/popupmenu.h" +#include "nvim/pos.h" #include "nvim/regexp.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/spell.h" #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/tag.h" #include "nvim/textformat.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/vim.h" -#include "nvim/window.h" // Definitions used for CTRL-X submode. // Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[] @@ -55,30 +71,31 @@ #define CTRL_X_WANT_IDENT 0x100 -#define CTRL_X_NORMAL 0 ///< CTRL-N CTRL-P completion, default -#define CTRL_X_NOT_DEFINED_YET 1 -#define CTRL_X_SCROLL 2 -#define CTRL_X_WHOLE_LINE 3 -#define CTRL_X_FILES 4 -#define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT) -#define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT) -#define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT) -#define CTRL_X_FINISHED 8 -#define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT) -#define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT) -#define CTRL_X_CMDLINE 11 -#define CTRL_X_FUNCTION 12 -#define CTRL_X_OMNI 13 -#define CTRL_X_SPELL 14 -#define CTRL_X_LOCAL_MSG 15 ///< only used in "ctrl_x_msgs" -#define CTRL_X_EVAL 16 ///< for builtin function complete() -#define CTRL_X_CMDLINE_CTRL_X 17 ///< CTRL-X typed in CTRL_X_CMDLINE +enum { + CTRL_X_NORMAL = 0, ///< CTRL-N CTRL-P completion, default + CTRL_X_NOT_DEFINED_YET = 1, + CTRL_X_SCROLL = 2, + CTRL_X_WHOLE_LINE = 3, + CTRL_X_FILES = 4, + CTRL_X_TAGS = (5 + CTRL_X_WANT_IDENT), + CTRL_X_PATH_PATTERNS = (6 + CTRL_X_WANT_IDENT), + CTRL_X_PATH_DEFINES = (7 + CTRL_X_WANT_IDENT), + CTRL_X_FINISHED = 8, + CTRL_X_DICTIONARY = (9 + CTRL_X_WANT_IDENT), + CTRL_X_THESAURUS = (10 + CTRL_X_WANT_IDENT), + CTRL_X_CMDLINE = 11, + CTRL_X_FUNCTION = 12, + CTRL_X_OMNI = 13, + CTRL_X_SPELL = 14, + CTRL_X_LOCAL_MSG = 15, ///< only used in "ctrl_x_msgs" + CTRL_X_EVAL = 16, ///< for builtin function complete() + CTRL_X_CMDLINE_CTRL_X = 17, ///< CTRL-X typed in CTRL_X_CMDLINE +}; #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] /// Message for CTRL-X mode, index is ctrl_x_mode. -static char *ctrl_x_msgs[] = -{ +static char *ctrl_x_msgs[] = { N_(" Keyword completion (^N^P)"), // CTRL_X_NORMAL, ^P/^N compl. N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"), NULL, // CTRL_X_SCROLL: depends on state @@ -132,10 +149,10 @@ typedef struct compl_S compl_T; struct compl_S { compl_T *cp_next; compl_T *cp_prev; - char_u *cp_str; ///< matched text - char_u *(cp_text[CPT_COUNT]); ///< text for the menu + char *cp_str; ///< matched text + char *(cp_text[CPT_COUNT]); ///< text for the menu typval_T cp_user_data; - char_u *cp_fname; ///< file containing the match, allocated when + char *cp_fname; ///< file containing the match, allocated when ///< cp_flags has CP_FREE_FNAME int cp_flags; ///< CP_ values int cp_number; ///< sequence number @@ -152,7 +169,7 @@ typedef struct { pos_T first_match_pos; ///< first match position pos_T last_match_pos; ///< last match position bool found_all; ///< found all matches of a certain type. - char_u *dict; ///< dictionary file to search + char *dict; ///< dictionary file to search int dict_f; ///< "dict" is an exact file name or not } ins_compl_next_state_T; @@ -191,7 +208,7 @@ static bool 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 char *compl_leader = NULL; static bool compl_get_longest = false; ///< put longest common string in compl_leader @@ -199,6 +216,8 @@ static bool compl_no_insert = false; ///< false: select & insert ///< true: noinsert static bool compl_no_select = false; ///< false: select & insert ///< true: noselect +static bool compl_longest = false; ///< false: insert full match + ///< true: insert longest prefix /// Selected one of the matches. When false the match was edited or using the /// longest common string. @@ -213,11 +232,11 @@ static bool compl_interrupted = false; static bool compl_restarting = false; ///< don't insert match -///< When the first completion is done "compl_started" is set. When it's -///< false the word to be completed must be located. +/// When the first completion is done "compl_started" is set. When it's +/// false the word to be completed must be located. static bool compl_started = false; -///< Which Ctrl-X mode are we in? +/// Which Ctrl-X mode are we in? static int ctrl_x_mode = CTRL_X_NORMAL; static int compl_matches = 0; ///< number of completion matches @@ -231,14 +250,13 @@ 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 char *compl_orig_text = NULL; ///< text as it was before ///< completion started static int compl_cont_mode = 0; static expand_T compl_xp; // List of flags for method of completion. static int compl_cont_status = 0; - #define CONT_ADDING 1 ///< "normal" or "adding" expansion #define CONT_INTRPT (2 + 4) ///< a ^X interrupted the current expansion ///< it's set only iff N_ADDS is set @@ -418,7 +436,7 @@ void compl_status_clear(void) compl_cont_status = 0; } -// @return true if completion is using the forward direction matches +/// @return true if completion is using the forward direction matches static bool compl_dir_forward(void) { return compl_direction == FORWARD; @@ -450,7 +468,7 @@ bool check_compl_option(bool dict_opt) msg_attr((dict_opt ? _("'dictionary' option is empty") : _("'thesaurus' option is empty")), HL_ATTR(HLF_E)); - if (emsg_silent == 0) { + if (emsg_silent == 0 && !in_assert_fails) { vim_beep(BO_COMPL); setcursor(); ui_flush(); @@ -570,8 +588,8 @@ bool ins_compl_accept_char(int c) /// Get the completed text by inferring the case of the originally typed text. /// If the result is in allocated memory "tofree" is set to it. -static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_char_len, - int min_len, char **tofree) +static char *ins_compl_infercase_gettext(const char *str, int char_len, int compl_char_len, + int min_len, char **tofree) { bool has_lower = false; bool was_letter = false; @@ -579,7 +597,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ // Allocate wide character array for the completion and fill it. int *const wca = xmalloc((size_t)char_len * sizeof(*wca)); { - const char_u *p = str; + const char_u *p = (char_u *)str; for (int i = 0; i < char_len; i++) { wca[i] = mb_ptr2char_adv(&p); } @@ -587,7 +605,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ // Rule 1: Were any chars converted to lower? { - const char_u *p = compl_orig_text; + const char_u *p = (char_u *)compl_orig_text; for (int i = 0; i < min_len; i++) { const int c = mb_ptr2char_adv(&p); if (mb_islower(c)) { @@ -606,7 +624,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ // Rule 2: No lower case, 2nd consecutive letter converted to // upper case. if (!has_lower) { - const char_u *p = compl_orig_text; + const char_u *p = (char_u *)compl_orig_text; for (int i = 0; i < min_len; i++) { const int c = mb_ptr2char_adv(&p); if (was_letter && mb_isupper(c) && mb_islower(wca[i])) { @@ -622,7 +640,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ // Copy the original case of the part we typed. { - const char_u *p = compl_orig_text; + const char_u *p = (char_u *)compl_orig_text; for (int i = 0; i < min_len; i++) { const int c = mb_ptr2char_adv(&p); if (mb_islower(c)) { @@ -635,7 +653,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ // Generate encoding specific output from wide character array. garray_T gap; - char *p = (char *)IObuff; + char *p = IObuff; int i = 0; ga_init(&gap, 1, 500); while (i < char_len) { @@ -644,7 +662,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ assert(gap.ga_data != NULL); // suppress clang "Dereference of NULL pointer" p = (char *)gap.ga_data + gap.ga_len; gap.ga_len += utf_char2bytes(wca[i++], p); - } else if ((p - (char *)IObuff) + 6 >= IOSIZE) { + } else if ((p - IObuff) + 6 >= IOSIZE) { // Multi-byte characters can occupy up to five bytes more than // ASCII characters, and we also need one byte for NUL, so when // getting to six bytes from the edge of IObuff switch to using a @@ -652,7 +670,7 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ ga_grow(&gap, IOSIZE); *p = NUL; STRCPY(gap.ga_data, IObuff); - gap.ga_len = (int)STRLEN(IObuff); + gap.ga_len = (int)strlen(IObuff); } else { p += utf_char2bytes(wca[i++], p); } @@ -674,11 +692,11 @@ static char_u *ins_compl_infercase_gettext(char_u *str, int char_len, int compl_ /// the rest of the word to be in -- webb /// /// @param[in] cont_s_ipos next ^X<> will set initial_pos -int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname, Direction dir, +int ins_compl_add_infercase(char *str_arg, int len, bool icase, char *fname, Direction dir, bool cont_s_ipos) FUNC_ATTR_NONNULL_ARG(1) { - char_u *str = str_arg; + char *str = str_arg; int char_len; // count multi-byte characters int compl_char_len; int flags = 0; @@ -689,7 +707,7 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname, // Find actual length of completion. { - const char_u *p = str; + const char *p = str; char_len = 0; while (*p != NUL) { MB_PTR_ADV(p); @@ -699,7 +717,7 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname, // Find actual length of original text. { - const char_u *p = compl_orig_text; + const char *p = compl_orig_text; compl_char_len = 0; while (*p != NUL) { MB_PTR_ADV(p); @@ -748,9 +766,9 @@ int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname, /// @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, char_u *const fname, - char_u *const *const cptext, const bool cptext_allocated, - typval_T *user_data, const Direction cdir, int flags_arg, const bool adup) +static int ins_compl_add(char *const str, int len, char *const fname, char *const *const cptext, + const bool cptext_allocated, typval_T *user_data, const Direction cdir, + int flags_arg, const bool adup) FUNC_ATTR_NONNULL_ARG(1) { compl_T *match; @@ -775,7 +793,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, return FAIL; } if (len < 0) { - len = (int)STRLEN(str); + len = (int)strlen(str); } // If the same match is already present, don't add it. @@ -783,8 +801,8 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, match = compl_first_match; 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, str, (size_t)len) == 0 + && ((int)strlen(match->cp_str) <= len || match->cp_str[len] == NUL)) { FREE_CPTEXT(cptext, cptext_allocated); return NOTDONE; } @@ -802,7 +820,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, if (flags & CP_ORIGINAL_TEXT) { match->cp_number = 0; } - match->cp_str = vim_strnsave(str, (size_t)len); + match->cp_str = xstrnsave(str, (size_t)len); // match-fname is: // - compl_curr_match->cp_fname if it is a string equal to fname. @@ -811,10 +829,10 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, if (fname != NULL && compl_curr_match != NULL && compl_curr_match->cp_fname != NULL - && STRCMP(fname, compl_curr_match->cp_fname) == 0) { + && strcmp(fname, compl_curr_match->cp_fname) == 0) { match->cp_fname = compl_curr_match->cp_fname; } else if (fname != NULL) { - match->cp_fname = vim_strsave(fname); + match->cp_fname = xstrdup(fname); flags |= CP_FREE_FNAME; } else { match->cp_fname = NULL; @@ -829,9 +847,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, continue; } if (*cptext[i] != NUL) { - match->cp_text[i] = (cptext_allocated - ? cptext[i] - : (char_u *)xstrdup((char *)cptext[i])); + match->cp_text[i] = (cptext_allocated ? cptext[i] : xstrdup(cptext[i])); } else if (cptext_allocated) { xfree(cptext[i]); } @@ -877,7 +893,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname, /// @param match completion match /// @param str character string to check /// @param len length of "str" -static bool ins_compl_equal(compl_T *match, char_u *str, size_t len) +static bool ins_compl_equal(compl_T *match, char *str, size_t len) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { if (match->cp_flags & CP_EQUAL) { @@ -886,23 +902,23 @@ static bool ins_compl_equal(compl_T *match, char_u *str, size_t len) if (match->cp_flags & CP_ICASE) { return STRNICMP(match->cp_str, str, len) == 0; } - return STRNCMP(match->cp_str, str, len) == 0; + return strncmp(match->cp_str, str, len) == 0; } /// Reduce the longest common string for match "match". static void ins_compl_longest_match(compl_T *match) { - char_u *p, *s; + char *p, *s; int c1, c2; int had_match; if (compl_leader == NULL) { // First match, use it as a whole. - compl_leader = vim_strsave(match->cp_str); + compl_leader = xstrdup(match->cp_str); had_match = (curwin->w_cursor.col > compl_col); ins_compl_delete(); - ins_bytes((char *)compl_leader + get_compl_len()); + ins_bytes(compl_leader + get_compl_len()); ins_redraw(false); // When the match isn't there (to avoid matching itself) remove it @@ -919,8 +935,8 @@ static void ins_compl_longest_match(compl_T *match) p = compl_leader; s = match->cp_str; while (*p != NUL) { - c1 = utf_ptr2char((char *)p); - c2 = utf_ptr2char((char *)s); + c1 = utf_ptr2char(p); + c2 = utf_ptr2char(s); if ((match->cp_flags & CP_ICASE) ? (mb_tolower(c1) != mb_tolower(c2)) @@ -936,7 +952,7 @@ static void ins_compl_longest_match(compl_T *match) *p = NUL; had_match = (curwin->w_cursor.col > compl_col); ins_compl_delete(); - ins_bytes((char *)compl_leader + get_compl_len()); + ins_bytes(compl_leader + get_compl_len()); ins_redraw(false); // When the match isn't there (to avoid matching itself) remove it @@ -957,7 +973,7 @@ static void ins_compl_add_matches(int num_matches, char **matches, int icase) Direction dir = compl_direction; for (int i = 0; i < num_matches && add_r != FAIL; i++) { - if ((add_r = ins_compl_add((char_u *)matches[i], -1, NULL, NULL, false, NULL, dir, + if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir, CP_FAST | (icase ? CP_ICASE : 0), false)) == OK) { // If dir was BACKWARD then honor it just once. @@ -999,7 +1015,7 @@ bool ins_compl_has_shown_match(void) bool ins_compl_long_shown_match(void) { return compl_shown_match != NULL && compl_shown_match->cp_str != NULL - && (colnr_T)STRLEN(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col; + && (colnr_T)strlen(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col; } /// Set variables that store noselect and noinsert behavior from the @@ -1008,12 +1024,16 @@ void completeopt_was_set(void) { compl_no_insert = false; compl_no_select = false; + compl_longest = false; if (strstr(p_cot, "noselect") != NULL) { compl_no_select = true; } if (strstr(p_cot, "noinsert") != NULL) { compl_no_insert = true; } + if (strstr(p_cot, "longest") != NULL) { + compl_longest = true; + } } /// "compl_match_array" points the currently displayed list of entries in the @@ -1126,7 +1146,7 @@ static int ins_compl_build_pum(void) XFREE_CLEAR(compl_leader); } - const int lead_len = compl_leader != NULL ? (int)STRLEN(compl_leader) : 0; + const int lead_len = compl_leader != NULL ? (int)strlen(compl_leader) : 0; do { if (!match_at_original_text(compl) @@ -1224,7 +1244,7 @@ void ins_compl_show_pum(void) do_cmdline_cmd("if exists('g:loaded_matchparen')|3match none|endif"); // Update the screen before drawing the popup menu over it. - update_screen(0); + update_screen(); int cur = -1; bool array_changed = false; @@ -1273,10 +1293,10 @@ void ins_compl_show_pum(void) /// /// @param flags DICT_FIRST and/or DICT_EXACT /// @param thesaurus Thesaurus completion -static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, int thesaurus) +static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, int thesaurus) { - char *dict = (char *)dict_start; - char_u *ptr; + char *dict = dict_start; + char *ptr; char *buf; regmatch_T regmatch; char **files; @@ -1307,16 +1327,16 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i // to only match at the start of a line. Otherwise just match the // pattern. Also need to double backslashes. if (ctrl_x_mode_line_or_eval()) { - char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\"); + char *pat_esc = vim_strsave_escaped(pat, "\\"); - size_t len = STRLEN(pat_esc) + 10; + size_t len = strlen(pat_esc) + 10; ptr = xmalloc(len); - vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc); - regmatch.regprog = vim_regcomp((char *)ptr, RE_MAGIC); + vim_snprintf(ptr, len, "^\\s*\\zs\\V%s", pat_esc); + regmatch.regprog = vim_regcomp(ptr, RE_MAGIC); xfree(pat_esc); xfree(ptr); } else { - regmatch.regprog = vim_regcomp((char *)pat, p_magic ? RE_MAGIC : 0); + regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0); if (regmatch.regprog == NULL) { goto theend; } @@ -1334,7 +1354,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i // backticks (for security, the 'dict' option may have been set in // a modeline). copy_option_part(&dict, buf, LSIZE, ","); - if (!thesaurus && STRCMP(buf, "spell") == 0) { + if (!thesaurus && strcmp(buf, "spell") == 0) { count = -1; } else if (vim_strchr(buf, '`') != NULL || expand_wildcards(1, &buf, &count, &files, @@ -1354,7 +1374,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0); } else if (count > 0) { // avoid warning for using "files" uninit ins_compl_files(count, files, thesaurus, flags, - ®match, (char_u *)buf, &dir); + ®match, buf, &dir); if (flags != DICT_EXACT) { FreeWild(count, files); } @@ -1374,12 +1394,12 @@ theend: /// skipping the word at 'skip_word'. /// /// @return OK on success. -static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, char_u *skip_word) +static int thesaurus_add_words_in_line(char *fname, char **buf_arg, int dir, const char *skip_word) { int status = OK; // Add the other matches on the line - char_u *ptr = *buf_arg; + char *ptr = *buf_arg; while (!got_int) { // Find start of the next word. Skip white // space and punctuation. @@ -1387,7 +1407,7 @@ static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, c if (*ptr == NUL || *ptr == NL) { break; } - char_u *wstart = ptr; + char *wstart = ptr; // Find end of the word. // Japanese words may have characters in @@ -1396,7 +1416,7 @@ static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, c while (*ptr != NUL) { const int l = utfc_ptr2len((const char *)ptr); - if (l < 2 && !vim_iswordc(*ptr)) { + if (l < 2 && !vim_iswordc((uint8_t)(*ptr))) { break; } ptr += l; @@ -1405,7 +1425,7 @@ static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, c // Add the word. Skip the regexp match. if (wstart != skip_word) { status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic, - (char_u *)fname, dir, false); + fname, dir, false); if (status == FAIL) { break; } @@ -1419,21 +1439,21 @@ static int thesaurus_add_words_in_line(char *fname, char_u **buf_arg, int dir, c /// Process "count" dictionary/thesaurus "files" and add the text matching /// "regmatch". static void ins_compl_files(int count, char **files, int thesaurus, int flags, regmatch_T *regmatch, - char_u *buf, Direction *dir) + char *buf, Direction *dir) FUNC_ATTR_NONNULL_ARG(2, 7) { - char_u *ptr; + char *ptr; int i; FILE *fp; int add_r; for (i = 0; i < count && !got_int && !compl_interrupted; i++) { fp = os_fopen(files[i], "r"); // open dictionary file - if (flags != DICT_EXACT) { + if (flags != DICT_EXACT && !shortmess(SHM_COMPLETIONSCAN)) { msg_hist_off = true; // reset in msg_trunc_attr() - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Scanning dictionary: %s"), files[i]); - (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); + (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); } if (fp == NULL) { @@ -1444,7 +1464,7 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r // Check each line for a match. while (!got_int && !compl_interrupted && !vim_fgets(buf, LSIZE, fp)) { ptr = buf; - while (vim_regexec(regmatch, (char *)buf, (colnr_T)(ptr - buf))) { + while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf))) { ptr = regmatch->startp[0]; if (ctrl_x_mode_line_or_eval()) { ptr = find_line_end(ptr); @@ -1453,12 +1473,11 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r } add_r = ins_compl_add_infercase(regmatch->startp[0], (int)(ptr - regmatch->startp[0]), - p_ic, (char_u *)files[i], *dir, false); + p_ic, files[i], *dir, false); if (thesaurus) { // For a thesaurus, add all the words in the line ptr = buf; - add_r = thesaurus_add_words_in_line(files[i], &ptr, *dir, - regmatch->startp[0]); + add_r = thesaurus_add_words_in_line(files[i], &ptr, *dir, regmatch->startp[0]); } if (add_r == OK) { // if dir was BACKWARD then honor it just once @@ -1481,24 +1500,24 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r /// Find the start of the next word. /// Returns a pointer to the first char of the word. Also stops at a NUL. -char_u *find_word_start(char_u *ptr) +char *find_word_start(char *ptr) FUNC_ATTR_PURE { while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1) { - ptr += utfc_ptr2len((char *)ptr); + ptr += utfc_ptr2len(ptr); } return ptr; } /// Find the end of the word. Assumes it starts inside a word. /// Returns a pointer to just after the word. -char_u *find_word_end(char_u *ptr) +char *find_word_end(char *ptr) FUNC_ATTR_PURE { const int start_class = mb_get_class(ptr); if (start_class > 1) { while (*ptr != NUL) { - ptr += utfc_ptr2len((char *)ptr); + ptr += utfc_ptr2len(ptr); if (mb_get_class(ptr) != start_class) { break; } @@ -1508,12 +1527,13 @@ char_u *find_word_end(char_u *ptr) } /// Find the end of the line, omitting CR and NL at the end. -/// Returns a pointer to just after the line. -static char_u *find_line_end(char_u *ptr) +/// +/// @return a pointer to just after the line. +static char *find_line_end(char *ptr) { - char_u *s; + char *s; - s = ptr + STRLEN(ptr); + s = ptr + strlen(ptr); while (s > ptr && (s[-1] == CAR || s[-1] == NL)) { s--; } @@ -1621,8 +1641,8 @@ int ins_compl_len(void) /// to be got from the user. int ins_compl_bs(void) { - char_u *line = get_cursor_line_ptr(); - char_u *p = line + curwin->w_cursor.col; + char *line = get_cursor_line_ptr(); + char *p = line + curwin->w_cursor.col; MB_PTR_BACK(line, p); ptrdiff_t p_off = p - line; @@ -1644,12 +1664,12 @@ int ins_compl_bs(void) ins_compl_restart(); } - // ins_compl_restart() calls update_screen(0) which may invalidate the pointer + // ins_compl_restart() calls update_screen() which may invalidate the pointer // TODO(bfredl): get rid of random update_screen() calls deep inside completion logic line = get_cursor_line_ptr(); xfree(compl_leader); - compl_leader = vim_strnsave(line + compl_col, (size_t)(p_off - (ptrdiff_t)compl_col)); + compl_leader = xstrnsave(line + compl_col, (size_t)(p_off - (ptrdiff_t)compl_col)); ins_compl_new_leader(); if (compl_shown_match != NULL) { @@ -1678,7 +1698,7 @@ static void ins_compl_new_leader(void) { ins_compl_del_pum(); ins_compl_delete(); - ins_bytes((char *)compl_leader + get_compl_len()); + ins_bytes(compl_leader + get_compl_len()); compl_used_match = false; if (compl_started) { @@ -1743,8 +1763,8 @@ void ins_compl_addleader(int c) } xfree(compl_leader); - compl_leader = vim_strnsave(get_cursor_line_ptr() + compl_col, - (size_t)(curwin->w_cursor.col - compl_col)); + compl_leader = xstrnsave(get_cursor_line_ptr() + compl_col, + (size_t)(curwin->w_cursor.col - compl_col)); ins_compl_new_leader(); } @@ -1755,7 +1775,7 @@ static void ins_compl_restart(void) // update screen before restart. // so if complete is blocked, // will stay to the last popup menu and reduce flicker - update_screen(0); + update_screen(); // TODO(bfredl): no. ins_compl_free(); compl_started = false; compl_matches = 0; @@ -1764,7 +1784,7 @@ static void ins_compl_restart(void) } /// Set the first match, the original text. -static void ins_compl_set_original_text(char_u *str) +static void ins_compl_set_original_text(char *str) FUNC_ATTR_NONNULL_ALL { // Replace the original text entry. @@ -1772,11 +1792,11 @@ static void ins_compl_set_original_text(char_u *str) // be at the last item for backward completion if (match_at_original_text(compl_first_match)) { // safety check xfree(compl_first_match->cp_str); - compl_first_match->cp_str = vim_strsave(str); + compl_first_match->cp_str = xstrdup(str); } else if (compl_first_match->cp_prev != NULL && match_at_original_text(compl_first_match->cp_prev)) { xfree(compl_first_match->cp_prev->cp_str); - compl_first_match->cp_prev->cp_str = vim_strsave(str); + compl_first_match->cp_prev->cp_str = xstrdup(str); } } @@ -1784,13 +1804,13 @@ static void ins_compl_set_original_text(char_u *str) /// matches. void ins_compl_addfrommatch(void) { - char_u *p; + char *p; int len = (int)curwin->w_cursor.col - (int)compl_col; int c; compl_T *cp; assert(compl_shown_match != NULL); p = compl_shown_match->cp_str; - if ((int)STRLEN(p) <= len) { // the match is too short + if ((int)strlen(p) <= len) { // the match is too short // When still at the original match use the first entry that matches // the leader. if (!match_at_original_text(compl_shown_match)) { @@ -1801,17 +1821,17 @@ void ins_compl_addfrommatch(void) 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, STRLEN(compl_leader))) { + || ins_compl_equal(cp, compl_leader, strlen(compl_leader))) { p = cp->cp_str; break; } } - if (p == NULL || (int)STRLEN(p) <= len) { + if (p == NULL || (int)strlen(p) <= len) { return; } } p += len; - c = utf_ptr2char((char *)p); + c = utf_ptr2char(p); ins_compl_addleader(c); } @@ -1953,7 +1973,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) // of the original text that has changed. // When using the longest match, edited the match or used // CTRL-E then don't use the current match. - char_u *ptr; + char *ptr; if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) { ptr = compl_curr_match->cp_str; } else { @@ -2004,7 +2024,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) // but only do this, if the Popup is still visible if (c == Ctrl_E) { ins_compl_delete(); - char_u *p = NULL; + char *p = NULL; if (compl_leader != NULL) { p = compl_leader; } else if (compl_first_match != NULL) { @@ -2012,9 +2032,9 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) } if (p != NULL) { const int compl_len = get_compl_len(); - const int len = (int)STRLEN(p); + const int len = (int)strlen(p); if (len > compl_len) { - ins_bytes_len((char *)p + compl_len, (size_t)(len - compl_len)); + ins_bytes_len(p + compl_len, (size_t)(len - compl_len)); } } retval = true; @@ -2044,7 +2064,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) if (c == Ctrl_C && cmdwin_type != 0) { // Avoid the popup menu remains displayed when leaving the // command line window. - update_screen(0); + update_screen(); } // Indent now if a key was typed that is in 'cinkeys'. @@ -2105,7 +2125,7 @@ bool ins_compl_prep(int c) // Set "compl_get_longest" when finding the first matches. if (ctrl_x_mode_not_defined_yet() || (ctrl_x_mode_normal() && !compl_started)) { - compl_get_longest = (strstr(p_cot, "longest") != NULL); + compl_get_longest = compl_longest; compl_used_match = true; } @@ -2160,11 +2180,11 @@ bool ins_compl_prep(int c) /// Fix the redo buffer for the completion leader replacing some of the typed /// text. This inserts backspaces and appends the changed text. /// "ptr" is the known leader text or NUL. -static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg) +static void ins_compl_fixRedoBufForLeader(char *ptr_arg) { int len; - char_u *p; - char_u *ptr = ptr_arg; + char *p; + char *ptr = ptr_arg; if (ptr == NULL) { if (compl_leader != NULL) { @@ -2185,7 +2205,7 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg) } else { len = 0; } - AppendToRedobuffLit((char *)ptr + len, -1); + AppendToRedobuffLit(ptr + len, -1); } /// Loops through the list of windows, loaded-buffers or non-loaded-buffers @@ -2220,30 +2240,128 @@ static buf_T *ins_compl_next_buf(buf_T *buf, int flag) return buf; } +static Callback cfu_cb; ///< 'completefunc' callback function +static Callback ofu_cb; ///< 'omnifunc' callback function +static Callback tsrfu_cb; ///< 'thesaurusfunc' callback function + +/// Copy a global callback function to a buffer local callback. +static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb) +{ + callback_free(bufcb); + if (globcb->type != kCallbackNone) { + callback_copy(bufcb, globcb); + } +} + +/// Parse the 'completefunc' option value and set the callback function. +/// Invoked when the 'completefunc' option is set. The option value can be a +/// name of a function (string), or function(<name>) or funcref(<name>) or a +/// lambda expression. +int set_completefunc_option(void) +{ + int retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb); + if (retval == OK) { + set_buflocal_cfu_callback(curbuf); + } + + return retval; +} + +/// Copy the global 'completefunc' callback function to the buffer-local +/// 'completefunc' callback for "buf". +void set_buflocal_cfu_callback(buf_T *buf) +{ + copy_global_to_buflocal_cb(&cfu_cb, &buf->b_cfu_cb); +} + +/// Parse the 'omnifunc' option value and set the callback function. +/// Invoked when the 'omnifunc' option is set. The option value can be a +/// name of a function (string), or function(<name>) or funcref(<name>) or a +/// lambda expression. +int set_omnifunc_option(void) +{ + int retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb); + if (retval == OK) { + set_buflocal_ofu_callback(curbuf); + } + + return retval; +} + +/// Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc' +/// callback for "buf". +void set_buflocal_ofu_callback(buf_T *buf) +{ + copy_global_to_buflocal_cb(&ofu_cb, &buf->b_ofu_cb); +} + +/// Parse the 'thesaurusfunc' option value and set the callback function. +/// Invoked when the 'thesaurusfunc' option is set. The option value can be a +/// name of a function (string), or function(<name>) or funcref(<name>) or a +/// lambda expression. +int set_thesaurusfunc_option(void) +{ + int retval; + + if (*curbuf->b_p_tsrfu != NUL) { + // buffer-local option set + retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb); + } else { + // global option set + retval = option_set_callback_func(p_tsrfu, &tsrfu_cb); + } + + return retval; +} + +/// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with +/// "copyID" so that they are not garbage collected. +bool set_ref_in_insexpand_funcs(int copyID) +{ + bool abort = set_ref_in_callback(&cfu_cb, copyID, NULL, NULL); + abort = abort || set_ref_in_callback(&ofu_cb, copyID, NULL, NULL); + abort = abort || set_ref_in_callback(&tsrfu_cb, copyID, NULL, NULL); + + return abort; +} + /// Get the user-defined completion function name for completion "type" -static char_u *get_complete_funcname(int type) +static char *get_complete_funcname(int type) { switch (type) { case CTRL_X_FUNCTION: - return (char_u *)curbuf->b_p_cfu; + return curbuf->b_p_cfu; case CTRL_X_OMNI: - return (char_u *)curbuf->b_p_ofu; + return curbuf->b_p_ofu; case CTRL_X_THESAURUS: - return *curbuf->b_p_tsrfu == NUL ? (char_u *)p_tsrfu : (char_u *)curbuf->b_p_tsrfu; + return *curbuf->b_p_tsrfu == NUL ? p_tsrfu : curbuf->b_p_tsrfu; default: - return (char_u *)""; + return ""; + } +} + +/// Get the callback to use for insert mode completion. +static Callback *get_insert_callback(int type) +{ + if (type == CTRL_X_FUNCTION) { + return &curbuf->b_cfu_cb; + } + if (type == CTRL_X_OMNI) { + return &curbuf->b_ofu_cb; } + // CTRL_X_THESAURUS + return (*curbuf->b_p_tsrfu != NUL) ? &curbuf->b_tsrfu_cb : &tsrfu_cb; } -/// Execute user defined complete function 'completefunc' or 'omnifunc', and -/// get matches in "matches". +/// Execute user defined complete function 'completefunc', 'omnifunc' or +/// 'thesaurusfunc', and get matches in "matches". /// -/// @param type CTRL_X_OMNI or CTRL_X_FUNCTION -static void expand_by_function(int type, char_u *base) +/// @param type either CTRL_X_OMNI or CTRL_X_FUNCTION or CTRL_X_THESAURUS +static void expand_by_function(int type, char *base) { list_T *matchlist = NULL; dict_T *matchdict = NULL; - char_u *funcname; + char *funcname; pos_T pos; typval_T rettv; const int save_State = State; @@ -2260,7 +2378,7 @@ static void expand_by_function(int type, char_u *base) args[1].v_type = VAR_STRING; args[2].v_type = VAR_UNKNOWN; args[0].vval.v_number = 0; - args[1].vval.v_string = base != NULL ? (char *)base : ""; + args[1].vval.v_string = base != NULL ? base : ""; pos = curwin->w_cursor; // Lock the text to avoid weird things from happening. Also disallow @@ -2268,8 +2386,10 @@ static void expand_by_function(int type, char_u *base) // Insert mode in another buffer. textlock++; + Callback *cb = get_insert_callback(type); + // Call a function, which returns a list or dict. - if (call_vim_function((char *)funcname, 2, args, &rettv) == OK) { + if (callback_call(cb, 2, args, &rettv)) { switch (rettv.v_type) { case VAR_LIST: matchlist = rettv.vval.v_list; @@ -2360,7 +2480,7 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast) tv_clear(&user_data); return FAIL; } - int status = ins_compl_add((char_u *)word, -1, NULL, (char_u **)cptext, true, + int status = ins_compl_add((char *)word, -1, NULL, cptext, true, &user_data, dir, flags, dup); if (status != OK) { tv_clear(&user_data); @@ -2422,6 +2542,7 @@ static void set_completion(colnr_T startcol, list_T *list) } ins_compl_clear(); ins_compl_free(); + compl_get_longest = compl_longest; compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) { @@ -2430,8 +2551,8 @@ static void 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(get_cursor_line_ptr() + compl_col, - (size_t)compl_length); + compl_orig_text = xstrnsave(get_cursor_line_ptr() + compl_col, + (size_t)compl_length); if (p_ic) { flags |= CP_ICASE; } @@ -2451,9 +2572,10 @@ static void set_completion(colnr_T startcol, list_T *list) int save_w_leftcol = curwin->w_leftcol; compl_curr_match = compl_first_match; - if (compl_no_insert || compl_no_select) { + bool no_select = compl_no_select || compl_longest; + if (compl_no_insert || no_select) { ins_complete(K_DOWN, false); - if (compl_no_select) { + if (no_select) { ins_complete(K_UP, false); } } else { @@ -2512,12 +2634,12 @@ void f_complete_check(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// Return Insert completion mode name string -static char_u *ins_compl_mode(void) +static char *ins_compl_mode(void) { if (ctrl_x_mode_not_defined_yet() || ctrl_x_mode_scroll() || compl_started) { - return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT]; + return ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT]; } - return (char_u *)""; + return ""; } /// Assign the sequence number to all the completion matches which don't have @@ -2590,15 +2712,15 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) ; item = TV_LIST_ITEM_NEXT(what_list, item)) { const char *what = tv_get_string(TV_LIST_ITEM_TV(item)); - if (STRCMP(what, "mode") == 0) { + if (strcmp(what, "mode") == 0) { what_flag |= CI_WHAT_MODE; - } else if (STRCMP(what, "pum_visible") == 0) { + } else if (strcmp(what, "pum_visible") == 0) { what_flag |= CI_WHAT_PUM_VISIBLE; - } else if (STRCMP(what, "items") == 0) { + } else if (strcmp(what, "items") == 0) { what_flag |= CI_WHAT_ITEMS; - } else if (STRCMP(what, "selected") == 0) { + } else if (strcmp(what, "selected") == 0) { what_flag |= CI_WHAT_SELECTED; - } else if (STRCMP(what, "inserted") == 0) { + } else if (strcmp(what, "inserted") == 0) { what_flag |= CI_WHAT_INSERTED; } } @@ -2606,8 +2728,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) int ret = OK; if (what_flag & CI_WHAT_MODE) { - ret = tv_dict_add_str(retdict, S_LEN("mode"), - (char *)ins_compl_mode()); + ret = tv_dict_add_str(retdict, S_LEN("mode"), ins_compl_mode()); } if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE)) { @@ -2631,6 +2752,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) tv_dict_add_str(di, S_LEN("kind"), EMPTY_IF_NULL(match->cp_text[CPT_KIND])); tv_dict_add_str(di, S_LEN("info"), EMPTY_IF_NULL(match->cp_text[CPT_INFO])); if (match->cp_user_data.v_type == VAR_UNKNOWN) { + // Add an empty string for backwards compatibility tv_dict_add_str(di, S_LEN("user_data"), ""); } else { tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data); @@ -2726,7 +2848,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar // buffer, so that word at start of buffer is found // correctly. st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count; - st->first_match_pos.col = (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum)); + st->first_match_pos.col = (colnr_T)strlen(ml_get(st->first_match_pos.lnum)); } st->last_match_pos = st->first_match_pos; compl_type = 0; @@ -2750,17 +2872,19 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar goto done; } compl_type = CTRL_X_DICTIONARY; - st->dict = (char_u *)st->ins_buf->b_fname; + st->dict = st->ins_buf->b_fname; st->dict_f = DICT_EXACT; } - msg_hist_off = true; // reset in msg_trunc_attr() - vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"), - st->ins_buf->b_fname == NULL - ? buf_spname(st->ins_buf) - : st->ins_buf->b_sfname == NULL - ? st->ins_buf->b_fname - : st->ins_buf->b_sfname); - (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); + if (!shortmess(SHM_COMPLETIONSCAN)) { + msg_hist_off = true; // reset in msg_trunc_attr() + vim_snprintf(IObuff, IOSIZE, _("Scanning: %s"), + st->ins_buf->b_fname == NULL + ? buf_spname(st->ins_buf) + : st->ins_buf->b_sfname == NULL + ? st->ins_buf->b_fname + : st->ins_buf->b_sfname); + (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + } } else if (*st->e_cpt == NUL) { status = INS_COMPL_CPT_END; } else { @@ -2773,7 +2897,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar compl_type = CTRL_X_THESAURUS; } if (*++st->e_cpt != ',' && *st->e_cpt != NUL) { - st->dict = (char_u *)st->e_cpt; + st->dict = st->e_cpt; st->dict_f = DICT_FIRST; } } else if (*st->e_cpt == 'i') { @@ -2781,16 +2905,18 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar } else if (*st->e_cpt == 'd') { compl_type = CTRL_X_PATH_DEFINES; } else if (*st->e_cpt == ']' || *st->e_cpt == 't') { - msg_hist_off = true; // reset in msg_trunc_attr() compl_type = CTRL_X_TAGS; - vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags.")); - (void)msg_trunc_attr((char *)IObuff, true, HL_ATTR(HLF_R)); + if (!shortmess(SHM_COMPLETIONSCAN)) { + msg_hist_off = true; // reset in msg_trunc_attr() + vim_snprintf(IObuff, IOSIZE, "%s", _("Scanning tags.")); + (void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R)); + } } else { compl_type = -1; } // in any case e_cpt is advanced to the next entry - (void)copy_option_part(&st->e_cpt, (char *)IObuff, IOSIZE, ","); + (void)copy_option_part(&st->e_cpt, IObuff, IOSIZE, ","); st->found_all = true; if (compl_type == -1) { @@ -2807,8 +2933,8 @@ done: /// included files. static void get_next_include_file_completion(int compl_type) { - find_pattern_in_path((char_u *)compl_pattern, compl_direction, - STRLEN(compl_pattern), false, false, + find_pattern_in_path(compl_pattern, compl_direction, + strlen(compl_pattern), false, false, ((compl_type == CTRL_X_PATH_DEFINES && !(compl_cont_status & CONT_SOL)) ? FIND_DEFINE : FIND_ANY), @@ -2817,17 +2943,17 @@ static void get_next_include_file_completion(int compl_type) /// Get the next set of words matching "compl_pattern" in dictionary or /// thesaurus files. -static void get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f) +static void get_next_dict_tsr_completion(int compl_type, char *dict, int dict_f) { if (thesaurus_func_complete(compl_type)) { - expand_by_function(compl_type, (char_u *)compl_pattern); + expand_by_function(compl_type, compl_pattern); } else { ins_compl_dictionaries(dict != NULL ? dict : (compl_type == CTRL_X_THESAURUS - ? (*curbuf->b_p_tsr == NUL ? p_tsr : (char_u *)curbuf->b_p_tsr) + ? (*curbuf->b_p_tsr == NUL ? (char *)p_tsr : curbuf->b_p_tsr) : (*curbuf->b_p_dict == - NUL ? (char_u *)p_dict : (char_u *)curbuf->b_p_dict)), - (char_u *)compl_pattern, + NUL ? p_dict : curbuf->b_p_dict)), + compl_pattern, dict != NULL ? dict_f : 0, compl_type == CTRL_X_THESAURUS); } @@ -2838,7 +2964,7 @@ static void get_next_tag_completion(void) { // set p_ic according to p_ic, p_scs and pat for find_tags(). const int save_p_ic = p_ic; - p_ic = ignorecase((char_u *)compl_pattern); + p_ic = ignorecase(compl_pattern); // Find up to TAG_MANY matches. Avoids that an enormous number // of matches is found when compl_pattern is empty @@ -2866,7 +2992,7 @@ static void get_next_filename_completion(void) } // May change home directory back to "~". - tilde_replace((char_u *)compl_pattern, num_matches, matches); + tilde_replace(compl_pattern, num_matches, matches); #ifdef BACKSLASH_IN_FILENAME if (curbuf->b_p_csl[0] != NUL) { for (int i = 0; i < num_matches; i++) { @@ -2890,8 +3016,8 @@ static void get_next_cmdline_completion(void) { char **matches; int num_matches; - if (expand_cmdline(&compl_xp, (char_u *)compl_pattern, - (int)STRLEN(compl_pattern), + if (expand_cmdline(&compl_xp, compl_pattern, + (int)strlen(compl_pattern), &num_matches, &matches) == EXPAND_OK) { ins_compl_add_matches(num_matches, matches, false); } @@ -2901,7 +3027,7 @@ static void get_next_cmdline_completion(void) static void get_next_spell_completion(linenr_T lnum) { char **matches; - int num_matches = expand_spelling(lnum, (char_u *)compl_pattern, &matches); + int num_matches = expand_spelling(lnum, compl_pattern, &matches); if (num_matches > 0) { ins_compl_add_matches(num_matches, matches, p_ic); } else { @@ -2915,11 +3041,11 @@ static void get_next_spell_completion(linenr_T lnum) /// @param cur_match_pos current match position /// @param match_len /// @param cont_s_ipos next ^X<> will set initial_pos -static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len, - bool *cont_s_ipos) +static char *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len, + bool *cont_s_ipos) { *match_len = 0; - char_u *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col; + char *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col; int len; if (ctrl_x_mode_line_or_eval()) { if (compl_status_adding()) { @@ -2928,14 +3054,14 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p } ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, false); if (!p_paste) { - ptr = (char_u *)skipwhite((char *)ptr); + ptr = skipwhite(ptr); } } - len = (int)STRLEN(ptr); + len = (int)strlen(ptr); } else { - char_u *tmp_ptr = ptr; + char *tmp_ptr = ptr; - if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr)) { + if (compl_status_adding() && compl_length <= (int)strlen(tmp_ptr)) { tmp_ptr += compl_length; // Skip if already inside a word. if (vim_iswordp(tmp_ptr)) { @@ -2952,10 +3078,10 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count) { // Try next line, if any. the new word will be "join" as if the // normal command "J" was used. IOSIZE is always greater than - // compl_length, so the next STRNCPY always works -- Acevedo - STRNCPY(IObuff, ptr, len); // NOLINT(runtime/printf) + // compl_length, so the next strncpy always works -- Acevedo + strncpy(IObuff, ptr, (size_t)len); // NOLINT(runtime/printf) ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, false); - tmp_ptr = ptr = (char_u *)skipwhite((char *)ptr); + tmp_ptr = ptr = skipwhite(ptr); // Find start of next word. tmp_ptr = find_word_start(tmp_ptr); // Find end of next word. @@ -2977,7 +3103,7 @@ static char_u *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_p if (tmp_ptr - ptr >= IOSIZE - len) { tmp_ptr = ptr + IOSIZE - len - 1; } - STRLCPY(IObuff + len, ptr, IOSIZE - len); + xstrlcpy(IObuff + len, ptr, (size_t)(IOSIZE - len)); len += (int)(tmp_ptr - ptr); *cont_s_ipos = true; } @@ -3031,7 +3157,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_ // has added a word that was at the beginning of the line. if (ctrl_x_mode_line_or_eval() || (compl_cont_status & CONT_SOL)) { found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos, - compl_direction, (char_u *)compl_pattern); + compl_direction, compl_pattern); } else { found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos, NULL, compl_direction, (char_u *)compl_pattern, 1L, @@ -3078,13 +3204,13 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_ continue; } int len; - char_u *ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos, - &len, &cont_s_ipos); + char *ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos, + &len, &cont_s_ipos); if (ptr == NULL) { continue; } if (ins_compl_add_infercase(ptr, len, p_ic, - st->ins_buf == curbuf ? NULL : (char_u *)st->ins_buf->b_sfname, + st->ins_buf == curbuf ? NULL : st->ins_buf->b_sfname, 0, cont_s_ipos) != NOTDONE) { found_new_match = OK; break; @@ -3131,7 +3257,7 @@ static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_ case CTRL_X_FUNCTION: case CTRL_X_OMNI: - expand_by_function(type, (char_u *)compl_pattern); + expand_by_function(type, compl_pattern); break; case CTRL_X_SPELL: @@ -3184,7 +3310,7 @@ static int ins_compl_get_exp(pos_T *ini) assert(st.ins_buf != NULL); compl_old_match = compl_curr_match; // remember the last current match - st.cur_match_pos = (compl_dir_forward() ? &st.last_match_pos : &st.first_match_pos); + st.cur_match_pos = compl_dir_forward() ? &st.last_match_pos : &st.first_match_pos; // For ^N/^P loop over all the flags/windows/buffers in 'complete' for (;;) { @@ -3275,7 +3401,7 @@ static int ins_compl_get_exp(pos_T *ini) static void ins_compl_update_shown_match(void) { while (!ins_compl_equal(compl_shown_match, - compl_leader, STRLEN(compl_leader)) + compl_leader, strlen(compl_leader)) && compl_shown_match->cp_next != NULL && !is_first_match(compl_shown_match->cp_next)) { compl_shown_match = compl_shown_match->cp_next; @@ -3284,10 +3410,10 @@ static void ins_compl_update_shown_match(void) // If we didn't find it searching forward, and compl_shows_dir is // backward, find the last match. if (compl_shows_dir_backward() - && !ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader)) + && !ins_compl_equal(compl_shown_match, compl_leader, strlen(compl_leader)) && (compl_shown_match->cp_next == NULL || is_first_match(compl_shown_match->cp_next))) { - while (!ins_compl_equal(compl_shown_match, compl_leader, STRLEN(compl_leader)) + while (!ins_compl_equal(compl_shown_match, compl_leader, strlen(compl_leader)) && compl_shown_match->cp_prev != NULL && !is_first_match(compl_shown_match->cp_prev)) { compl_shown_match = compl_shown_match->cp_prev; @@ -3321,7 +3447,7 @@ void ins_compl_delete(void) /// "in_compl_func" is true when called from complete_check(). void ins_compl_insert(bool in_compl_func) { - ins_bytes((char *)compl_shown_match->cp_str + get_compl_len()); + ins_bytes(compl_shown_match->cp_str + get_compl_len()); compl_used_match = !match_at_original_text(compl_shown_match); dict_T *dict = ins_compl_dict_alloc(compl_shown_match); @@ -3346,7 +3472,7 @@ static void ins_compl_show_filename(void) // the text that fits in "space" between "s" and "e". char *s; char *e; - for (s = e = (char *)compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) { + for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) { space -= ptr2cells(e); while (space < 0) { space += ptr2cells(s); @@ -3354,9 +3480,9 @@ static void ins_compl_show_filename(void) } } msg_hist_off = true; - vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead, - (char_u *)s > compl_shown_match->cp_fname ? "<" : "", s); - msg((char *)IObuff); + vim_snprintf(IObuff, IOSIZE, "%s %s%s", lead, + s > compl_shown_match->cp_fname ? "<" : "", s); + msg(IObuff); msg_hist_off = false; redraw_cmdline = false; // don't overwrite! } @@ -3432,7 +3558,7 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a if (!match_at_original_text(compl_shown_match) && compl_leader != NULL && !ins_compl_equal(compl_shown_match, - compl_leader, STRLEN(compl_leader))) { + compl_leader, strlen(compl_leader))) { todo++; } else { // Remember a matching item. @@ -3513,13 +3639,13 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match // Insert the text of the new completion, or the compl_leader. if (compl_no_insert && !started) { - ins_bytes((char *)compl_orig_text + get_compl_len()); + ins_bytes(compl_orig_text + get_compl_len()); compl_used_match = false; } else if (insert_match) { if (!compl_get_longest || compl_used_match) { ins_compl_insert(in_compl_func); } else { - ins_bytes((char *)compl_leader + get_compl_len()); + ins_bytes(compl_leader + get_compl_len()); } } else { compl_used_match = false; @@ -3527,7 +3653,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match if (!allow_get_expansion) { // redraw to show the user what was inserted - update_screen(0); + update_screen(); // TODO(bfredl): no! // display the updated popup menu ins_compl_show_pum(); @@ -3553,17 +3679,6 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match return num_matches; } -void pum_ext_select_item(int item, bool insert, bool finish) -{ - if (!pum_visible() || item < -1 || item >= compl_match_arraysize) { - return; - } - pum_want.active = true; - pum_want.item = item; - pum_want.insert = insert; - pum_want.finish = finish; -} - /// Call this while finding completions, to check whether the user has hit a key /// that should change the currently displayed completion, or exit completion /// mode. Also, when compl_pending is not zero, show a completion as soon as @@ -3697,36 +3812,36 @@ static bool ins_compl_use_match(int c) /// completion) /// Sets the global variables: compl_col, compl_length and compl_pattern. /// Uses the global variables: compl_cont_status and ctrl_x_mode -static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) +static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col) { if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) { if (!compl_status_adding()) { - while (--startcol >= 0 && vim_isIDc(line[startcol])) {} + while (--startcol >= 0 && vim_isIDc((uint8_t)line[startcol])) {} compl_col += ++startcol; compl_length = curs_col - startcol; } if (p_ic) { - compl_pattern = (char *)str_foldcase(line + compl_col, compl_length, NULL, 0); + compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); } else { - compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length); + compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length); } } else if (compl_status_adding()) { - char_u *prefix = (char_u *)"\\<"; + char *prefix = "\\<"; // we need up to 2 extra chars for the prefix - compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, - compl_length) + 2); + compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2); if (!vim_iswordp(line + compl_col) - || (compl_col > 0 && (vim_iswordp(mb_prevptr(line, line + compl_col))))) { - prefix = (char_u *)""; + || (compl_col > 0 + && (vim_iswordp(mb_prevptr(line, line + compl_col))))) { + prefix = ""; } STRCPY(compl_pattern, prefix); - (void)quote_meta((char_u *)compl_pattern + STRLEN(prefix), + (void)quote_meta(compl_pattern + strlen(prefix), line + compl_col, compl_length); } else if (--startcol < 0 || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) { // Match any word of at least two chars - compl_pattern = (char *)vim_strsave((char_u *)"\\<\\k\\k"); + compl_pattern = xstrdup("\\<\\k\\k"); compl_col += curs_col; compl_length = 0; } else { @@ -3749,13 +3864,12 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) // xmalloc(7) is enough -- Acevedo compl_pattern = xmalloc(7); STRCPY(compl_pattern, "\\<"); - (void)quote_meta((char_u *)compl_pattern + 2, line + compl_col, 1); + (void)quote_meta(compl_pattern + 2, line + compl_col, 1); STRCAT(compl_pattern, "\\k"); } else { - compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, - compl_length) + 2); + compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2); STRCPY(compl_pattern, "\\<"); - (void)quote_meta((char_u *)compl_pattern + 2, line + compl_col, compl_length); + (void)quote_meta(compl_pattern + 2, line + compl_col, compl_length); } } @@ -3765,17 +3879,17 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) /// Get the pattern, column and length for whole line completion or for the /// complete() function. /// Sets the global variables: compl_col, compl_length and compl_pattern. -static int get_wholeline_compl_info(char_u *line, colnr_T curs_col) +static int get_wholeline_compl_info(char *line, colnr_T curs_col) { - compl_col = (colnr_T)getwhitecols((char *)line); + compl_col = (colnr_T)getwhitecols(line); compl_length = (int)curs_col - (int)compl_col; if (compl_length < 0) { // cursor in indent: empty pattern compl_length = 0; } if (p_ic) { - compl_pattern = (char *)str_foldcase(line + compl_col, compl_length, NULL, 0); + compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); } else { - compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length); + compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length); } return OK; @@ -3783,17 +3897,17 @@ static int get_wholeline_compl_info(char_u *line, colnr_T curs_col) /// Get the pattern, column and length for filename completion. /// Sets the global variables: compl_col, compl_length and compl_pattern. -static int get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col) +static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col) { // Go back to just before the first filename character. if (startcol > 0) { - char_u *p = line + startcol; + char *p = line + startcol; MB_PTR_BACK(line, p); - while (p > line && vim_isfilec(utf_ptr2char((char *)p))) { + while (p > line && vim_isfilec(utf_ptr2char(p))) { MB_PTR_BACK(line, p); } - if (p == line && vim_isfilec(utf_ptr2char((char *)p))) { + if (p == line && vim_isfilec(utf_ptr2char(p))) { startcol = 0; } else { startcol = (int)(p - line) + 1; @@ -3802,17 +3916,17 @@ static int get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col) compl_col += startcol; compl_length = (int)curs_col - startcol; - compl_pattern = (char *)addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES); + compl_pattern = addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES); return OK; } /// Get the pattern, column and length for command-line completion. /// Sets the global variables: compl_col, compl_length and compl_pattern. -static int get_cmdline_compl_info(char_u *line, colnr_T curs_col) +static int get_cmdline_compl_info(char *line, colnr_T curs_col) { - compl_pattern = (char *)vim_strnsave(line, (size_t)curs_col); - set_cmd_context(&compl_xp, (char_u *)compl_pattern, (int)STRLEN(compl_pattern), curs_col, false); + compl_pattern = xstrnsave(line, (size_t)curs_col); + set_cmd_context(&compl_xp, compl_pattern, (int)strlen(compl_pattern), 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 @@ -3837,7 +3951,7 @@ static int get_userdefined_compl_info(colnr_T curs_col) const int save_State = State; // Call 'completefunc' or 'omnifunc' and get pattern length as a string - char_u *funcname = get_complete_funcname(ctrl_x_mode); + char *funcname = get_complete_funcname(ctrl_x_mode); if (*funcname == NUL) { semsg(_(e_notset), ctrl_x_mode_function() ? "completefunc" : "omnifunc"); return FAIL; @@ -3852,7 +3966,8 @@ static int get_userdefined_compl_info(colnr_T curs_col) pos_T pos = curwin->w_cursor; textlock++; - colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args); + Callback *cb = get_insert_callback(ctrl_x_mode); + colnr_T col = (colnr_T)callback_call_retnr(cb, 2, args); textlock--; State = save_State; @@ -3893,9 +4008,9 @@ static int get_userdefined_compl_info(colnr_T curs_col) // Setup variables for completion. Need to obtain "line" again, // it may have become invalid. - char_u *line = ml_get(curwin->w_cursor.lnum); + char *line = ml_get(curwin->w_cursor.lnum); compl_length = curs_col - compl_col; - compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length); + compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length); return OK; } @@ -3919,8 +4034,8 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col) compl_length = (int)curs_col - compl_col; } // Need to obtain "line" again, it may have become invalid. - char_u *line = ml_get(curwin->w_cursor.lnum); - compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length); + char *line = ml_get(curwin->w_cursor.lnum); + compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length); return OK; } @@ -3934,7 +4049,7 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col) /// become invalid and needs to be fetched again. /// /// @return OK on success. -static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *line_invalid) +static int compl_get_info(char *line, int startcol, colnr_T curs_col, bool *line_invalid) { if (ctrl_x_mode_normal() || ((ctrl_x_mode & CTRL_X_WANT_IDENT) @@ -3973,7 +4088,7 @@ static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *li /// the same line as the cursor then fix it (the line has been split because it /// was longer than 'tw'). if SOL is set then skip the previous pattern, a word /// at the beginning of the line has been inserted, we'll look for that. -static void ins_compl_continue_search(char_u *line) +static void ins_compl_continue_search(char *line) { // it is a continued search compl_cont_status &= ~CONT_INTRPT; // remove INTRPT @@ -3985,7 +4100,7 @@ static void ins_compl_continue_search(char_u *line) // first non_blank in the line, if it is not a wordchar // include it to get a better pattern, but then we don't // want the "\\<" prefix, check it below. - compl_col = (colnr_T)getwhitecols((char *)line); + compl_col = (colnr_T)getwhitecols(line); compl_startpos.col = compl_col; compl_startpos.lnum = curwin->w_cursor.lnum; compl_cont_status &= ~CONT_SOL; // clear SOL if present @@ -3995,9 +4110,7 @@ static void ins_compl_continue_search(char_u *line) // mode but first we need to redefine compl_startpos if (compl_cont_status & CONT_S_IPOS) { compl_cont_status |= CONT_SOL; - compl_startpos.col = (colnr_T)((char_u *)skipwhite((char *)line - + compl_length - + compl_startpos.col) - line); + compl_startpos.col = (colnr_T)(skipwhite(line + compl_length + compl_startpos.col) - line); } compl_col = compl_startpos.col; } @@ -4036,7 +4149,7 @@ static int ins_compl_start(void) return FAIL; } - char_u *line = ml_get(curwin->w_cursor.lnum); + char *line = ml_get(curwin->w_cursor.lnum); colnr_T curs_col = curwin->w_cursor.col; compl_pending = 0; @@ -4108,7 +4221,7 @@ static int ins_compl_start(void) // Always add completion for the original text. xfree(compl_orig_text); - compl_orig_text = vim_strnsave(line + compl_col, (size_t)compl_length); + compl_orig_text = xstrnsave(line + compl_col, (size_t)compl_length); int flags = CP_ORIGINAL_TEXT; if (p_ic) { flags |= CP_ICASE; @@ -4163,18 +4276,18 @@ static void ins_compl_show_statusmsg(void) if (compl_curr_match->cp_number != -1) { // Space for 10 text chars. + 2x10-digit no.s = 31. // Translations may need more than twice that. - static char_u match_ref[81]; + static char match_ref[81]; if (compl_matches > 0) { - vim_snprintf((char *)match_ref, sizeof(match_ref), + vim_snprintf(match_ref, sizeof(match_ref), _("match %d of %d"), compl_curr_match->cp_number, compl_matches); } else { - vim_snprintf((char *)match_ref, sizeof(match_ref), + vim_snprintf(match_ref, sizeof(match_ref), _("match %d"), compl_curr_match->cp_number); } - edit_submode_extra = (char *)match_ref; + edit_submode_extra = match_ref; edit_submode_highl = HLF_R; if (dollar_vcol >= 0) { curs_columns(curwin, false); @@ -4298,7 +4411,7 @@ static void show_pum(int prev_w_wrow, int prev_w_leftcol) // If dest is not NULL the chars. are copied there quoting (with // a backslash) the metachars, and dest would be NUL terminated. // Returns the length (needed) of dest -static unsigned quote_meta(char_u *dest, char_u *src, int len) +static unsigned quote_meta(char *dest, char *src, int len) { unsigned m = (unsigned)len + 1; // one extra for the NUL @@ -4312,7 +4425,7 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) } FALLTHROUGH; case '~': - if (!p_magic) { // quote these only if magic is set + if (!magic_isset()) { // quote these only if magic is set break; } FALLTHROUGH; @@ -4333,7 +4446,7 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) *dest++ = *src; } // Copy remaining bytes of a multibyte character. - const int mb_len = utfc_ptr2len((char *)src) - 1; + const int mb_len = utfc_ptr2len(src) - 1; if (mb_len > 0 && len >= mb_len) { for (int i = 0; i < mb_len; i++) { len--; @@ -4355,6 +4468,9 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) void free_insexpand_stuff(void) { XFREE_CLEAR(compl_orig_text); + callback_free(&cfu_cb); + callback_free(&ofu_cb); + callback_free(&tsrfu_cb); } #endif |