neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

insexpand.c (209189B)


      1 // insexpand.c: functions for Insert mode completion
      2 
      3 #include <assert.h>
      4 #include <limits.h>
      5 #include <stdbool.h>
      6 #include <stddef.h>
      7 #include <stdint.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 
     12 #include "klib/kvec.h"
     13 #include "nvim/api/private/helpers.h"
     14 #include "nvim/ascii_defs.h"
     15 #include "nvim/autocmd.h"
     16 #include "nvim/autocmd_defs.h"
     17 #include "nvim/buffer.h"
     18 #include "nvim/buffer_defs.h"
     19 #include "nvim/change.h"
     20 #include "nvim/charset.h"
     21 #include "nvim/cmdexpand.h"
     22 #include "nvim/cmdexpand_defs.h"
     23 #include "nvim/cursor.h"
     24 #include "nvim/drawscreen.h"
     25 #include "nvim/edit.h"
     26 #include "nvim/errors.h"
     27 #include "nvim/eval.h"
     28 #include "nvim/eval/executor.h"
     29 #include "nvim/eval/typval.h"
     30 #include "nvim/eval/typval_defs.h"
     31 #include "nvim/eval/userfunc.h"
     32 #include "nvim/eval/vars.h"
     33 #include "nvim/ex_eval.h"
     34 #include "nvim/ex_getln.h"
     35 #include "nvim/extmark.h"
     36 #include "nvim/extmark_defs.h"
     37 #include "nvim/fileio.h"
     38 #include "nvim/fuzzy.h"
     39 #include "nvim/garray.h"
     40 #include "nvim/garray_defs.h"
     41 #include "nvim/getchar.h"
     42 #include "nvim/gettext_defs.h"
     43 #include "nvim/globals.h"
     44 #include "nvim/highlight_defs.h"
     45 #include "nvim/highlight_group.h"
     46 #include "nvim/indent.h"
     47 #include "nvim/indent_c.h"
     48 #include "nvim/insexpand.h"
     49 #include "nvim/keycodes.h"
     50 #include "nvim/lua/executor.h"
     51 #include "nvim/macros_defs.h"
     52 #include "nvim/mark_defs.h"
     53 #include "nvim/mbyte.h"
     54 #include "nvim/mbyte_defs.h"
     55 #include "nvim/memline.h"
     56 #include "nvim/memory.h"
     57 #include "nvim/message.h"
     58 #include "nvim/move.h"
     59 #include "nvim/option.h"
     60 #include "nvim/option_defs.h"
     61 #include "nvim/option_vars.h"
     62 #include "nvim/os/fs.h"
     63 #include "nvim/os/input.h"
     64 #include "nvim/os/time.h"
     65 #include "nvim/path.h"
     66 #include "nvim/popupmenu.h"
     67 #include "nvim/pos_defs.h"
     68 #include "nvim/regexp.h"
     69 #include "nvim/regexp_defs.h"
     70 #include "nvim/register.h"
     71 #include "nvim/search.h"
     72 #include "nvim/spell.h"
     73 #include "nvim/state.h"
     74 #include "nvim/state_defs.h"
     75 #include "nvim/strings.h"
     76 #include "nvim/tag.h"
     77 #include "nvim/textformat.h"
     78 #include "nvim/types_defs.h"
     79 #include "nvim/ui.h"
     80 #include "nvim/undo.h"
     81 #include "nvim/vim_defs.h"
     82 #include "nvim/window.h"
     83 #include "nvim/winfloat.h"
     84 
     85 // Definitions used for CTRL-X submode.
     86 // Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[]
     87 // and ctrl_x_mode_names[].
     88 
     89 #define CTRL_X_WANT_IDENT       0x100
     90 
     91 enum {
     92  CTRL_X_NORMAL = 0,  ///< CTRL-N CTRL-P completion, default
     93  CTRL_X_NOT_DEFINED_YET = 1,
     94  CTRL_X_SCROLL = 2,
     95  CTRL_X_WHOLE_LINE = 3,
     96  CTRL_X_FILES = 4,
     97  CTRL_X_TAGS = (5 + CTRL_X_WANT_IDENT),
     98  CTRL_X_PATH_PATTERNS = (6 + CTRL_X_WANT_IDENT),
     99  CTRL_X_PATH_DEFINES = (7 + CTRL_X_WANT_IDENT),
    100  CTRL_X_FINISHED = 8,
    101  CTRL_X_DICTIONARY = (9 + CTRL_X_WANT_IDENT),
    102  CTRL_X_THESAURUS = (10 + CTRL_X_WANT_IDENT),
    103  CTRL_X_CMDLINE = 11,
    104  CTRL_X_FUNCTION = 12,
    105  CTRL_X_OMNI = 13,
    106  CTRL_X_SPELL = 14,
    107  CTRL_X_LOCAL_MSG = 15,       ///< only used in "ctrl_x_msgs"
    108  CTRL_X_EVAL = 16,            ///< for builtin function complete()
    109  CTRL_X_CMDLINE_CTRL_X = 17,  ///< CTRL-X typed in CTRL_X_CMDLINE
    110  CTRL_X_BUFNAMES = 18,
    111  CTRL_X_REGISTER = 19,        ///< complete words from registers
    112 };
    113 
    114 #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
    115 
    116 /// Message for CTRL-X mode, index is ctrl_x_mode.
    117 static char *ctrl_x_msgs[] = {
    118  N_(" Keyword completion (^N^P)"),  // CTRL_X_NORMAL, ^P/^N compl.
    119  N_(" ^X mode (^]^D^E^F^I^K^L^N^O^P^Rs^U^V^Y)"),
    120  NULL,  // CTRL_X_SCROLL: depends on state
    121  N_(" Whole line completion (^L^N^P)"),
    122  N_(" File name completion (^F^N^P)"),
    123  N_(" Tag completion (^]^N^P)"),
    124  N_(" Path pattern completion (^N^P)"),
    125  N_(" Definition completion (^D^N^P)"),
    126  NULL,  // CTRL_X_FINISHED
    127  N_(" Dictionary completion (^K^N^P)"),
    128  N_(" Thesaurus completion (^T^N^P)"),
    129  N_(" Command-line completion (^V^N^P)"),
    130  N_(" User defined completion (^U^N^P)"),
    131  N_(" Omni completion (^O^N^P)"),
    132  N_(" Spelling suggestion (^S^N^P)"),
    133  N_(" Keyword Local completion (^N^P)"),
    134  NULL,  // CTRL_X_EVAL doesn't use msg.
    135  N_(" Command-line completion (^V^N^P)"),
    136  NULL,
    137  N_(" Register completion (^N^P)"),
    138 };
    139 
    140 static char *ctrl_x_mode_names[] = {
    141  "keyword",
    142  "ctrl_x",
    143  "scroll",
    144  "whole_line",
    145  "files",
    146  "tags",
    147  "path_patterns",
    148  "path_defines",
    149  "unknown",          // CTRL_X_FINISHED
    150  "dictionary",
    151  "thesaurus",
    152  "cmdline",
    153  "function",
    154  "omni",
    155  "spell",
    156  NULL,               // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
    157  "eval",
    158  "cmdline",
    159  NULL,               // CTRL_X_BUFNAME
    160  "register",
    161 };
    162 
    163 /// Structure used to store one match for insert completion.
    164 typedef struct compl_S compl_T;
    165 struct compl_S {
    166  compl_T *cp_next;
    167  compl_T *cp_prev;
    168  compl_T *cp_match_next;        ///< matched next compl_T
    169  String cp_str;                 ///< matched text
    170  char *(cp_text[CPT_COUNT]);    ///< text for the menu
    171  typval_T cp_user_data;
    172  char *cp_fname;                ///< file containing the match, allocated when
    173                                 ///< cp_flags has CP_FREE_FNAME
    174  int cp_flags;                  ///< CP_ values
    175  int cp_number;                 ///< sequence number
    176  int cp_score;                  ///< fuzzy match score or proximity score
    177  bool cp_in_match_array;        ///< collected by compl_match_array
    178  int cp_user_abbr_hlattr;       ///< highlight attribute for abbr
    179  int cp_user_kind_hlattr;       ///< highlight attribute for kind
    180  int cp_cpt_source_idx;         ///< index of this match's source in 'cpt' option
    181 };
    182 
    183 /// state information used for getting the next set of insert completion
    184 /// matches.
    185 typedef struct {
    186  char *e_cpt_copy;       ///< copy of 'complete'
    187  char *e_cpt;            ///< current entry in "e_cpt_copy"
    188  buf_T *ins_buf;         ///< buffer being scanned
    189  pos_T *cur_match_pos;   ///< current match position
    190  pos_T prev_match_pos;   ///< previous match position
    191  bool set_match_pos;     ///< save first_match_pos/last_match_pos
    192  pos_T first_match_pos;  ///< first match position
    193  pos_T last_match_pos;   ///< last match position
    194  bool found_all;         ///< found all matches of a certain type.
    195  char *dict;             ///< dictionary file to search
    196  int dict_f;             ///< "dict" is an exact file name or not
    197  Callback *func_cb;      ///< callback of function in 'cpt' option
    198 } ins_compl_next_state_T;
    199 
    200 #include "insexpand.c.generated.h"
    201 
    202 /// values for cp_flags
    203 typedef enum {
    204  CP_ORIGINAL_TEXT = 1,  ///< the original text when the expansion begun
    205  CP_FREE_FNAME = 2,     ///< cp_fname is allocated
    206  CP_CONT_S_IPOS = 4,    ///< use CONT_S_IPOS for compl_cont_status
    207  CP_EQUAL = 8,          ///< ins_compl_equal() always returns true
    208  CP_ICASE = 16,         ///< ins_compl_equal ignores case
    209  CP_FAST = 32,          ///< use fast_breakcheck instead of os_breakcheck
    210 } cp_flags_T;
    211 
    212 static const char e_hitend[] = N_("Hit end of paragraph");
    213 static const char e_compldel[] = N_("E840: Completion function deleted text");
    214 
    215 // All the current matches are stored in a list.
    216 // "compl_first_match" points to the start of the list.
    217 // "compl_curr_match" points to the currently selected entry.
    218 // "compl_shown_match" is different from compl_curr_match during
    219 // ins_compl_get_exp(), when new matches are added to the list.
    220 // "compl_old_match" points to previous "compl_curr_match".
    221 
    222 static compl_T *compl_first_match = NULL;
    223 static compl_T *compl_curr_match = NULL;
    224 static compl_T *compl_shown_match = NULL;
    225 static compl_T *compl_old_match = NULL;
    226 
    227 /// list used to store the compl_T which have the max score
    228 static compl_T **compl_best_matches = NULL;
    229 static int compl_num_bests = 0;
    230 
    231 /// After using a cursor key <Enter> selects a match in the popup menu,
    232 /// otherwise it inserts a line break.
    233 static bool compl_enter_selects = false;
    234 
    235 /// When "compl_leader" is not NULL only matches that start with this string
    236 /// are used.
    237 static String compl_leader = STRING_INIT;
    238 
    239 static bool compl_get_longest = false;  ///< put longest common string in compl_leader
    240 
    241 /// This flag is false when no match is selected (by ^N/^P) or the match was
    242 /// edited or using the longest common string.
    243 static bool compl_used_match;
    244 
    245 /// didn't finish finding completions.
    246 static bool compl_was_interrupted = false;
    247 
    248 // Set when character typed while looking for matches and it means we should
    249 // stop looking for matches.
    250 static bool compl_interrupted = false;
    251 
    252 static bool compl_restarting = false;   ///< don't insert match
    253 
    254 /// When the first completion is done "compl_started" is set.  When it's
    255 /// false the word to be completed must be located.
    256 static bool compl_started = false;
    257 
    258 /// Which Ctrl-X mode are we in?
    259 static int ctrl_x_mode = CTRL_X_NORMAL;
    260 
    261 static int compl_matches = 0;           ///< number of completion matches
    262 static String compl_pattern = STRING_INIT;      ///< search pattern for matching items
    263 static String cpt_compl_pattern = STRING_INIT;  ///< pattern returned by func in 'cpt'
    264 static Direction compl_direction = FORWARD;
    265 static Direction compl_shows_dir = FORWARD;
    266 static int compl_pending = 0;           ///< > 1 for postponed CTRL-N
    267 static pos_T compl_startpos;
    268 /// Length in bytes of the text being completed (this is deleted to be replaced
    269 /// by the match.)
    270 static int compl_length = 0;
    271 static linenr_T compl_lnum = 0;         ///< lnum where the completion start
    272 static colnr_T compl_col = 0;           ///< column where the text starts
    273                                        ///< that is being completed
    274 static colnr_T compl_ins_end_col = 0;
    275 static String compl_orig_text = STRING_INIT;  ///< text as it was before
    276                                              ///< completion started
    277 /// Undo information to restore extmarks for original text.
    278 static extmark_undo_vec_t compl_orig_extmarks;
    279 static int compl_cont_mode = 0;
    280 static expand_T compl_xp;
    281 
    282 static win_T *compl_curr_win = NULL;  ///< win where completion is active
    283 static buf_T *compl_curr_buf = NULL;  ///< buf where completion is active
    284 
    285 #define COMPL_INITIAL_TIMEOUT_MS    80
    286 // Autocomplete uses a decaying timeout: starting from COMPL_INITIAL_TIMEOUT_MS,
    287 // if the current source exceeds its timeout, it is interrupted and the next
    288 // begins with half the time. A small minimum timeout ensures every source
    289 // gets at least a brief chance.
    290 // Special case: when 'complete' contains "F" or "o" (function sources), a
    291 // longer fixed timeout is used (COMPL_FUNC_TIMEOUT_MS or
    292 // COMPL_FUNC_TIMEOUT_NON_KW_MS). - girish
    293 static bool compl_autocomplete = false;        ///< whether autocompletion is active
    294 static uint64_t compl_timeout_ms = COMPL_INITIAL_TIMEOUT_MS;
    295 static bool compl_time_slice_expired = false;  ///< time budget exceeded for current source
    296 static bool compl_from_nonkeyword = false;     ///< completion started from non-keyword
    297 static bool compl_hi_on_autocompl_longest = false;  ///< apply "PreInsert" highlight
    298 
    299 // Halve the current completion timeout, simulating exponential decay.
    300 #define COMPL_MIN_TIMEOUT_MS    5
    301 #define DECAY_COMPL_TIMEOUT() \
    302  do { \
    303    if (compl_timeout_ms > COMPL_MIN_TIMEOUT_MS) { \
    304      compl_timeout_ms /= 2; \
    305    } \
    306  } while (0)
    307 
    308 // Timeout values for F{func}, F and o values in 'complete'
    309 #define COMPL_FUNC_TIMEOUT_MS           300
    310 #define COMPL_FUNC_TIMEOUT_NON_KW_MS    1000
    311 
    312 // List of flags for method of completion.
    313 static int compl_cont_status = 0;
    314 #define CONT_ADDING    1        ///< "normal" or "adding" expansion
    315 #define CONT_INTRPT    (2 + 4)  ///< a ^X interrupted the current expansion
    316                                ///< it's set only iff N_ADDS is set
    317 #define CONT_N_ADDS    4        ///< next ^X<> will add-new or expand-current
    318 #define CONT_S_IPOS    8        ///< next ^X<> will set initial_pos?
    319                                ///< if so, word-wise-expansion will set SOL
    320 #define CONT_SOL       16       ///< pattern includes start of line, just for
    321                                ///< word-wise expansion, not set for ^X^L
    322 #define CONT_LOCAL     32       ///< for ctrl_x_mode 0, ^X^P/^X^N do a local
    323                                ///< expansion, (eg use complete=.)
    324 
    325 static bool compl_opt_refresh_always = false;
    326 
    327 static size_t spell_bad_len = 0;   // length of located bad word
    328 
    329 static int compl_selected_item = -1;
    330 
    331 static int *compl_fuzzy_scores;
    332 
    333 /// Define the structure for completion source (in 'cpt' option) information
    334 typedef struct cpt_source_T {
    335  bool cs_refresh_always;   ///< Whether 'refresh:always' is set for func
    336  int cs_startcol;          ///< Start column returned by func
    337  int cs_max_matches;       ///< Max items to display from this source
    338  uint64_t compl_start_tv;  ///< Timestamp when match collection starts
    339  char cs_flag;             ///< Flag indicating the type of source
    340 } cpt_source_T;
    341 
    342 /// Pointer to the array of completion sources
    343 static cpt_source_T *cpt_sources_array;
    344 /// Total number of completion sources specified in the 'cpt' option
    345 static int cpt_sources_count;
    346 /// Index of the current completion source being expanded
    347 static int cpt_sources_index = -1;
    348 
    349 // "compl_match_array" points the currently displayed list of entries in the
    350 // popup menu.  It is NULL when there is no popup menu.
    351 static pumitem_T *compl_match_array = NULL;
    352 static int compl_match_arraysize;
    353 
    354 /// CTRL-X pressed in Insert mode.
    355 void ins_ctrl_x(void)
    356 {
    357  if (!ctrl_x_mode_cmdline()) {
    358    // if the next ^X<> won't ADD nothing, then reset compl_cont_status
    359    if (compl_cont_status & CONT_N_ADDS) {
    360      compl_cont_status |= CONT_INTRPT;
    361    } else {
    362      compl_cont_status = 0;
    363    }
    364    // We're not sure which CTRL-X mode it will be yet
    365    ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
    366    edit_submode = _(CTRL_X_MSG(ctrl_x_mode));
    367    edit_submode_pre = NULL;
    368    redraw_mode = true;
    369  } else {
    370    // CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X
    371    // CTRL-V look like CTRL-N
    372    ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
    373  }
    374 
    375  may_trigger_modechanged();
    376 }
    377 
    378 // Functions to check the current CTRL-X mode.
    379 
    380 bool ctrl_x_mode_none(void)
    381  FUNC_ATTR_PURE
    382 {
    383  return ctrl_x_mode == 0;
    384 }
    385 
    386 bool ctrl_x_mode_normal(void)
    387  FUNC_ATTR_PURE
    388 {
    389  return ctrl_x_mode == CTRL_X_NORMAL;
    390 }
    391 
    392 bool ctrl_x_mode_scroll(void)
    393  FUNC_ATTR_PURE
    394 {
    395  return ctrl_x_mode == CTRL_X_SCROLL;
    396 }
    397 
    398 bool ctrl_x_mode_whole_line(void)
    399  FUNC_ATTR_PURE
    400 {
    401  return ctrl_x_mode == CTRL_X_WHOLE_LINE;
    402 }
    403 
    404 bool ctrl_x_mode_files(void)
    405  FUNC_ATTR_PURE
    406 {
    407  return ctrl_x_mode == CTRL_X_FILES;
    408 }
    409 
    410 bool ctrl_x_mode_tags(void)
    411  FUNC_ATTR_PURE
    412 {
    413  return ctrl_x_mode == CTRL_X_TAGS;
    414 }
    415 
    416 bool ctrl_x_mode_path_patterns(void)
    417  FUNC_ATTR_PURE
    418 {
    419  return ctrl_x_mode == CTRL_X_PATH_PATTERNS;
    420 }
    421 
    422 bool ctrl_x_mode_path_defines(void)
    423  FUNC_ATTR_PURE
    424 {
    425  return ctrl_x_mode == CTRL_X_PATH_DEFINES;
    426 }
    427 
    428 bool ctrl_x_mode_dictionary(void)
    429  FUNC_ATTR_PURE
    430 {
    431  return ctrl_x_mode == CTRL_X_DICTIONARY;
    432 }
    433 
    434 bool ctrl_x_mode_thesaurus(void)
    435  FUNC_ATTR_PURE
    436 {
    437  return ctrl_x_mode == CTRL_X_THESAURUS;
    438 }
    439 
    440 bool ctrl_x_mode_cmdline(void)
    441  FUNC_ATTR_PURE
    442 {
    443  return ctrl_x_mode == CTRL_X_CMDLINE || ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X;
    444 }
    445 
    446 bool ctrl_x_mode_function(void)
    447  FUNC_ATTR_PURE
    448 {
    449  return ctrl_x_mode == CTRL_X_FUNCTION;
    450 }
    451 
    452 bool ctrl_x_mode_omni(void)
    453  FUNC_ATTR_PURE
    454 {
    455  return ctrl_x_mode == CTRL_X_OMNI;
    456 }
    457 
    458 bool ctrl_x_mode_spell(void)
    459  FUNC_ATTR_PURE
    460 {
    461  return ctrl_x_mode == CTRL_X_SPELL;
    462 }
    463 
    464 static bool ctrl_x_mode_eval(void)
    465  FUNC_ATTR_PURE
    466 {
    467  return ctrl_x_mode == CTRL_X_EVAL;
    468 }
    469 
    470 bool ctrl_x_mode_line_or_eval(void)
    471  FUNC_ATTR_PURE
    472 {
    473  return ctrl_x_mode == CTRL_X_WHOLE_LINE || ctrl_x_mode == CTRL_X_EVAL;
    474 }
    475 
    476 bool ctrl_x_mode_register(void)
    477  FUNC_ATTR_PURE
    478 {
    479  return ctrl_x_mode == CTRL_X_REGISTER;
    480 }
    481 
    482 /// Whether other than default completion has been selected.
    483 bool ctrl_x_mode_not_default(void)
    484  FUNC_ATTR_PURE
    485 {
    486  return ctrl_x_mode != CTRL_X_NORMAL;
    487 }
    488 
    489 /// Whether CTRL-X was typed without a following character,
    490 /// not including when in CTRL-X CTRL-V mode.
    491 bool ctrl_x_mode_not_defined_yet(void)
    492  FUNC_ATTR_PURE
    493 {
    494  return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
    495 }
    496 
    497 /// @return  true if currently in "normal" or "adding" insert completion matches state
    498 bool compl_status_adding(void)
    499 {
    500  return compl_cont_status & CONT_ADDING;
    501 }
    502 
    503 /// @return  true if the completion pattern includes start of line, just for
    504 ///          word-wise expansion.
    505 bool compl_status_sol(void)
    506 {
    507  return compl_cont_status & CONT_SOL;
    508 }
    509 
    510 /// @return  true if ^X^P/^X^N will do a local completion (i.e. use complete=.)
    511 bool compl_status_local(void)
    512 {
    513  return compl_cont_status & CONT_LOCAL;
    514 }
    515 
    516 /// Clear the completion status flags
    517 void compl_status_clear(void)
    518 {
    519  compl_cont_status = 0;
    520 }
    521 
    522 /// @return  true if completion is using the forward direction matches
    523 static bool compl_dir_forward(void)
    524 {
    525  return compl_direction == FORWARD;
    526 }
    527 
    528 /// @return  true if currently showing forward completion matches
    529 static bool compl_shows_dir_forward(void)
    530 {
    531  return compl_shows_dir == FORWARD;
    532 }
    533 
    534 /// @return  true if currently showing backward completion matches
    535 static bool compl_shows_dir_backward(void)
    536 {
    537  return compl_shows_dir == BACKWARD;
    538 }
    539 
    540 /// Check that the 'dictionary' or 'thesaurus' option can be used.
    541 ///
    542 /// @param  dict_opt  check 'dictionary' when true, 'thesaurus' when false.
    543 bool check_compl_option(bool dict_opt)
    544 {
    545  if (dict_opt
    546      ? (*curbuf->b_p_dict == NUL && *p_dict == NUL && !curwin->w_p_spell)
    547      : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL
    548         && *curbuf->b_p_tsrfu == NUL && *p_tsrfu == NUL)) {
    549    ctrl_x_mode = CTRL_X_NORMAL;
    550    edit_submode = NULL;
    551    emsg(dict_opt ? _("'dictionary' option is empty") : _("'thesaurus' option is empty"));
    552    if (emsg_silent == 0 && !in_assert_fails) {
    553      vim_beep(kOptBoFlagComplete);
    554      setcursor();
    555      msg_delay(2004, false);
    556    }
    557    return false;
    558  }
    559  return true;
    560 }
    561 
    562 /// Check that the character "c" a valid key to go to or keep us in CTRL-X mode?
    563 /// This depends on the current mode.
    564 ///
    565 /// @param  c  character to check
    566 bool vim_is_ctrl_x_key(int c)
    567  FUNC_ATTR_WARN_UNUSED_RESULT
    568 {
    569  // Always allow ^R - let its results then be checked
    570  if (c == Ctrl_R && ctrl_x_mode != CTRL_X_REGISTER) {
    571    return true;
    572  }
    573 
    574  // Accept <PageUp> and <PageDown> if the popup menu is visible.
    575  if (ins_compl_pum_key(c)) {
    576    return true;
    577  }
    578 
    579  switch (ctrl_x_mode) {
    580  case 0:  // Not in any CTRL-X mode
    581    return c == Ctrl_N || c == Ctrl_P || c == Ctrl_X;
    582  case CTRL_X_NOT_DEFINED_YET:
    583  case CTRL_X_CMDLINE_CTRL_X:
    584    return c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
    585           || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
    586           || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
    587           || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
    588           || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
    589           || c == Ctrl_S || c == Ctrl_K || c == 's'
    590           || c == Ctrl_Z || c == Ctrl_R;
    591  case CTRL_X_SCROLL:
    592    return c == Ctrl_Y || c == Ctrl_E;
    593  case CTRL_X_WHOLE_LINE:
    594    return c == Ctrl_L || c == Ctrl_P || c == Ctrl_N;
    595  case CTRL_X_FILES:
    596    return c == Ctrl_F || c == Ctrl_P || c == Ctrl_N;
    597  case CTRL_X_DICTIONARY:
    598    return c == Ctrl_K || c == Ctrl_P || c == Ctrl_N;
    599  case CTRL_X_THESAURUS:
    600    return c == Ctrl_T || c == Ctrl_P || c == Ctrl_N;
    601  case CTRL_X_TAGS:
    602    return c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N;
    603  case CTRL_X_PATH_PATTERNS:
    604    return c == Ctrl_P || c == Ctrl_N;
    605  case CTRL_X_PATH_DEFINES:
    606    return c == Ctrl_D || c == Ctrl_P || c == Ctrl_N;
    607  case CTRL_X_CMDLINE:
    608    return c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
    609           || c == Ctrl_X;
    610  case CTRL_X_FUNCTION:
    611    return c == Ctrl_U || c == Ctrl_P || c == Ctrl_N;
    612  case CTRL_X_OMNI:
    613    return c == Ctrl_O || c == Ctrl_P || c == Ctrl_N;
    614  case CTRL_X_SPELL:
    615    return c == Ctrl_S || c == Ctrl_P || c == Ctrl_N;
    616  case CTRL_X_EVAL:
    617    return (c == Ctrl_P || c == Ctrl_N);
    618  case CTRL_X_BUFNAMES:
    619    return (c == Ctrl_P || c == Ctrl_N);
    620  case CTRL_X_REGISTER:
    621    return (c == Ctrl_R || c == Ctrl_P || c == Ctrl_N);
    622  }
    623  internal_error("vim_is_ctrl_x_key()");
    624  return false;
    625 }
    626 
    627 /// @return  true if "match" is the original text when the completion began.
    628 static bool match_at_original_text(const compl_T *const match)
    629 {
    630  return match->cp_flags & CP_ORIGINAL_TEXT;
    631 }
    632 
    633 /// @return  true if "match" is the first match in the completion list.
    634 static bool is_first_match(const compl_T *const match)
    635 {
    636  return match == compl_first_match;
    637 }
    638 
    639 static void do_autocmd_completedone(int c, int mode, char *word)
    640 {
    641  save_v_event_T save_v_event;
    642  dict_T *v_event = get_v_event(&save_v_event);
    643 
    644  mode = mode & ~CTRL_X_WANT_IDENT;
    645  char *mode_str = NULL;
    646  if (ctrl_x_mode_names[mode]) {
    647    mode_str = ctrl_x_mode_names[mode];
    648  }
    649  tv_dict_add_str(v_event, S_LEN("complete_word"), word != NULL ? word : "");
    650  tv_dict_add_str(v_event, S_LEN("complete_type"), mode_str != NULL ? mode_str : "");
    651 
    652  tv_dict_add_str(v_event, S_LEN("reason"),
    653                  (c == Ctrl_Y ? "accept" : (c == Ctrl_E ? "cancel" : "discard")));
    654  tv_dict_set_keys_readonly(v_event);
    655 
    656  ins_apply_autocmds(EVENT_COMPLETEDONE);
    657  restore_v_event(v_event, &save_v_event);
    658 }
    659 
    660 /// Check that character "c" is part of the item currently being
    661 /// completed.  Used to decide whether to abandon complete mode when the menu
    662 /// is visible.
    663 ///
    664 /// @param  c  character to check
    665 bool ins_compl_accept_char(int c)
    666  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
    667 {
    668  if (compl_autocomplete && compl_from_nonkeyword) {
    669    return false;
    670  }
    671 
    672  if (ctrl_x_mode & CTRL_X_WANT_IDENT) {
    673    // When expanding an identifier only accept identifier chars.
    674    return vim_isIDc(c);
    675  }
    676 
    677  switch (ctrl_x_mode) {
    678  case CTRL_X_FILES:
    679    // When expanding file name only accept file name chars. But not
    680    // path separators, so that "proto/<Tab>" expands files in
    681    // "proto", not "proto/" as a whole
    682    return vim_isfilec(c) && !vim_ispathsep(c);
    683 
    684  case CTRL_X_CMDLINE:
    685  case CTRL_X_CMDLINE_CTRL_X:
    686  case CTRL_X_OMNI:
    687    // Command line and Omni completion can work with just about any
    688    // printable character, but do stop at white space.
    689    return vim_isprintc(c) && !ascii_iswhite(c);
    690 
    691  case CTRL_X_WHOLE_LINE:
    692    // For while line completion a space can be part of the line.
    693    return vim_isprintc(c);
    694  }
    695  return vim_iswordc(c);
    696 }
    697 
    698 /// Get the completed text by inferring the case of the originally typed text.
    699 /// If the result is in allocated memory "tofree" is set to it.
    700 static char *ins_compl_infercase_gettext(const char *str, int char_len, int compl_char_len,
    701                                         int min_len, char **tofree)
    702 {
    703  bool has_lower = false;
    704 
    705  // Allocate wide character array for the completion and fill it.
    706  int *const wca = xmalloc((size_t)char_len * sizeof(*wca));
    707  {
    708    const char *p = str;
    709    for (int i = 0; i < char_len; i++) {
    710      wca[i] = mb_ptr2char_adv(&p);
    711    }
    712  }
    713 
    714  // Rule 1: Were any chars converted to lower?
    715  {
    716    const char *p = compl_orig_text.data;
    717    for (int i = 0; i < min_len; i++) {
    718      const int c = mb_ptr2char_adv(&p);
    719      if (mb_islower(c)) {
    720        has_lower = true;
    721        if (mb_isupper(wca[i])) {
    722          // Rule 1 is satisfied.
    723          for (i = compl_char_len; i < char_len; i++) {
    724            wca[i] = mb_tolower(wca[i]);
    725          }
    726          break;
    727        }
    728      }
    729    }
    730  }
    731 
    732  // Rule 2: No lower case, 2nd consecutive letter converted to
    733  // upper case.
    734  if (!has_lower) {
    735    bool was_letter = false;
    736    const char *p = compl_orig_text.data;
    737    for (int i = 0; i < min_len; i++) {
    738      const int c = mb_ptr2char_adv(&p);
    739      if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
    740        // Rule 2 is satisfied.
    741        for (i = compl_char_len; i < char_len; i++) {
    742          wca[i] = mb_toupper(wca[i]);
    743        }
    744        break;
    745      }
    746      was_letter = mb_islower(c) || mb_isupper(c);
    747    }
    748  }
    749 
    750  // Copy the original case of the part we typed.
    751  {
    752    const char *p = compl_orig_text.data;
    753    for (int i = 0; i < min_len; i++) {
    754      const int c = mb_ptr2char_adv(&p);
    755      if (mb_islower(c)) {
    756        wca[i] = mb_tolower(wca[i]);
    757      } else if (mb_isupper(c)) {
    758        wca[i] = mb_toupper(wca[i]);
    759      }
    760    }
    761  }
    762 
    763  // Generate encoding specific output from wide character array.
    764  garray_T gap;
    765  char *p = IObuff;
    766  int i = 0;
    767  ga_init(&gap, 1, 500);
    768  while (i < char_len) {
    769    if (gap.ga_data != NULL) {
    770      ga_grow(&gap, 10);
    771      assert(gap.ga_data != NULL);  // suppress clang "Dereference of NULL pointer"
    772      p = (char *)gap.ga_data + gap.ga_len;
    773      gap.ga_len += utf_char2bytes(wca[i++], p);
    774    } else if ((p - IObuff) + 6 >= IOSIZE) {
    775      // Multi-byte characters can occupy up to five bytes more than
    776      // ASCII characters, and we also need one byte for NUL, so when
    777      // getting to six bytes from the edge of IObuff switch to using a
    778      // growarray.  Add the character in the next round.
    779      ga_grow(&gap, IOSIZE);
    780      *p = NUL;
    781      STRCPY(gap.ga_data, IObuff);
    782      gap.ga_len = (int)(p - IObuff);
    783    } else {
    784      p += utf_char2bytes(wca[i++], p);
    785    }
    786  }
    787  xfree(wca);
    788 
    789  if (gap.ga_data != NULL) {
    790    *tofree = gap.ga_data;
    791    return gap.ga_data;
    792  }
    793 
    794  *p = NUL;
    795  return IObuff;
    796 }
    797 
    798 /// This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
    799 /// case of the originally typed text is used, and the case of the completed
    800 /// text is inferred, ie this tries to work out what case you probably wanted
    801 /// the rest of the word to be in -- webb
    802 ///
    803 /// @param[in]  cont_s_ipos  next ^X<> will set initial_pos
    804 int ins_compl_add_infercase(char *str_arg, int len, bool icase, char *fname, Direction dir,
    805                            bool cont_s_ipos, int score)
    806  FUNC_ATTR_NONNULL_ARG(1)
    807 {
    808  char *str = str_arg;
    809  int char_len;  // count multi-byte characters
    810  int compl_char_len;
    811  int flags = 0;
    812  char *tofree = NULL;
    813 
    814  if (p_ic && curbuf->b_p_inf && len > 0) {
    815    // Infer case of completed part.
    816 
    817    // Find actual length of completion.
    818    {
    819      const char *p = str;
    820      char_len = 0;
    821      while (*p != NUL) {
    822        MB_PTR_ADV(p);
    823        char_len++;
    824      }
    825    }
    826 
    827    // Find actual length of original text.
    828    {
    829      const char *p = compl_orig_text.data;
    830      compl_char_len = 0;
    831      while (*p != NUL) {
    832        MB_PTR_ADV(p);
    833        compl_char_len++;
    834      }
    835    }
    836 
    837    // "char_len" may be smaller than "compl_char_len" when using
    838    // thesaurus, only use the minimum when comparing.
    839    int min_len = MIN(char_len, compl_char_len);
    840 
    841    str = ins_compl_infercase_gettext(str, char_len, compl_char_len, min_len, &tofree);
    842  }
    843  if (cont_s_ipos) {
    844    flags |= CP_CONT_S_IPOS;
    845  }
    846  if (icase) {
    847    flags |= CP_ICASE;
    848  }
    849 
    850  int res = ins_compl_add(str, len, fname, NULL, false, NULL, dir, flags, false, NULL, score);
    851  xfree(tofree);
    852  return res;
    853 }
    854 
    855 /// free cptext
    856 static inline void free_cptext(char *const *const cptext)
    857 {
    858  if (cptext != NULL) {
    859    for (size_t i = 0; i < CPT_COUNT; i++) {
    860      xfree(cptext[i]);
    861    }
    862  }
    863 }
    864 
    865 /// Check if fuzzy matching is enabled
    866 static bool cot_fuzzy(void)
    867 {
    868  return (get_cot_flags() & kOptCotFlagFuzzy) != 0 && !ctrl_x_mode_thesaurus();
    869 }
    870 
    871 /// Returns true if matches should be sorted based on proximity to the cursor.
    872 static bool is_nearest_active(void)
    873 {
    874  return (compl_autocomplete || (get_cot_flags() & kOptCotFlagNearest))
    875         && !cot_fuzzy();
    876 }
    877 
    878 /// True if a match is selected (even if it is not inserted).
    879 bool ins_compl_is_match_selected(void)
    880 {
    881  return compl_shown_match != NULL && !is_first_match(compl_shown_match);
    882 }
    883 
    884 /// Returns true if autocomplete is active and the pre-insert effect targets the
    885 /// longest prefix.
    886 bool ins_compl_preinsert_longest(void)
    887 {
    888  return compl_autocomplete
    889         && (get_cot_flags() & (kOptCotFlagLongest | kOptCotFlagPreinsert | kOptCotFlagFuzzy))
    890         == kOptCotFlagLongest;
    891 }
    892 
    893 /// Add a match to the list of matches
    894 ///
    895 /// @param[in]  str     text of the match to add
    896 /// @param[in]  len     length of "str". If -1, then the length of "str" is computed.
    897 /// @param[in]  fname   file name to associate with this match. May be NULL.
    898 /// @param[in]  cptext  list of strings to use with this match (for abbr, menu, info
    899 ///                     and kind). May be NULL.
    900 ///                     If not NULL, must have exactly #CPT_COUNT items.
    901 /// @param[in]  cptext_allocated  If true, will not copy cptext strings.
    902 ///
    903 ///                               @note Will free strings in case of error.
    904 ///                                     cptext itself will not be freed.
    905 /// @param[in]  user_data  user supplied data (any vim type) for this match
    906 /// @param[in]  cdir       match direction. If 0, use "compl_direction".
    907 /// @param[in]  flags_arg  match flags (cp_flags)
    908 /// @param[in]  adup       accept this match even if it is already present.
    909 /// @param[in]  user_hl    list of extra highlight attributes for abbr kind.
    910 ///
    911 /// If "cdir" is FORWARD, then the match is added after the current match.
    912 /// Otherwise, it is added before the current match.
    913 ///
    914 /// @return NOTDONE if the given string is already in the list of completions,
    915 ///         otherwise it is added to the list and  OK is returned. FAIL will be
    916 ///         returned in case of error.
    917 static int ins_compl_add(char *const str, int len, char *const fname, char *const *const cptext,
    918                         const bool cptext_allocated, typval_T *user_data, const Direction cdir,
    919                         int flags_arg, const bool adup, const int *user_hl, const int score)
    920  FUNC_ATTR_NONNULL_ARG(1)
    921 {
    922  compl_T *match;
    923  const Direction dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
    924  int flags = flags_arg;
    925  bool inserted = false;
    926 
    927  if (flags & CP_FAST) {
    928    fast_breakcheck();
    929  } else {
    930    os_breakcheck();
    931  }
    932  if (got_int) {
    933    if (cptext_allocated) {
    934      free_cptext(cptext);
    935    }
    936    return FAIL;
    937  }
    938  if (len < 0) {
    939    len = (int)strlen(str);
    940  }
    941 
    942  // If the same match is already present, don't add it.
    943  if (compl_first_match != NULL && !adup) {
    944    match = compl_first_match;
    945    do {
    946      if (!match_at_original_text(match)
    947          && strncmp(match->cp_str.data, str, (size_t)len) == 0
    948          && ((int)match->cp_str.size <= len || match->cp_str.data[len] == NUL)) {
    949        if (is_nearest_active() && score > 0 && score < match->cp_score) {
    950          match->cp_score = score;
    951        }
    952        if (cptext_allocated) {
    953          free_cptext(cptext);
    954        }
    955        return NOTDONE;
    956      }
    957      match = match->cp_next;
    958    } while (match != NULL && !is_first_match(match));
    959  }
    960 
    961  // Remove any popup menu before changing the list of matches.
    962  ins_compl_del_pum();
    963 
    964  // Allocate a new match structure.
    965  // Copy the values to the new match structure.
    966  match = xcalloc(1, sizeof(compl_T));
    967  match->cp_number = flags & CP_ORIGINAL_TEXT ? 0 : -1;
    968  match->cp_str = cbuf_to_string(str, (size_t)len);
    969 
    970  // match-fname is:
    971  // - compl_curr_match->cp_fname if it is a string equal to fname.
    972  // - a copy of fname, CP_FREE_FNAME is set to free later THE allocated mem.
    973  // - NULL otherwise.  --Acevedo
    974  if (fname != NULL
    975      && compl_curr_match != NULL
    976      && compl_curr_match->cp_fname != NULL
    977      && strcmp(fname, compl_curr_match->cp_fname) == 0) {
    978    match->cp_fname = compl_curr_match->cp_fname;
    979  } else if (fname != NULL) {
    980    match->cp_fname = xstrdup(fname);
    981    flags |= CP_FREE_FNAME;
    982  } else {
    983    match->cp_fname = NULL;
    984  }
    985  match->cp_flags = flags;
    986  match->cp_user_abbr_hlattr = user_hl ? user_hl[0] : -1;
    987  match->cp_user_kind_hlattr = user_hl ? user_hl[1] : -1;
    988  match->cp_score = score;
    989  match->cp_cpt_source_idx = cpt_sources_index;
    990 
    991  if (cptext != NULL) {
    992    for (int i = 0; i < CPT_COUNT; i++) {
    993      if (cptext[i] == NULL) {
    994        continue;
    995      }
    996      if (*cptext[i] != NUL) {
    997        match->cp_text[i] = (cptext_allocated ? cptext[i] : xstrdup(cptext[i]));
    998      } else if (cptext_allocated) {
    999        xfree(cptext[i]);
   1000      }
   1001    }
   1002  }
   1003 
   1004  if (user_data != NULL) {
   1005    match->cp_user_data = *user_data;
   1006  }
   1007 
   1008  // Link the new match structure after (FORWARD) or before (BACKWARD) the
   1009  // current match in the list of matches .
   1010  if (compl_first_match == NULL) {
   1011    match->cp_next = match->cp_prev = NULL;
   1012  } else if (cot_fuzzy() && score != FUZZY_SCORE_NONE && compl_get_longest) {
   1013    compl_T *current = compl_first_match->cp_next;
   1014    compl_T *prev = compl_first_match;
   1015    inserted = false;
   1016    // The direction is ignored when using longest and fuzzy match, because
   1017    // matches are inserted and sorted by score.
   1018    while (current != NULL && current != compl_first_match) {
   1019      if (current->cp_score < score) {
   1020        match->cp_next = current;
   1021        match->cp_prev = current->cp_prev;
   1022        if (current->cp_prev) {
   1023          current->cp_prev->cp_next = match;
   1024        }
   1025        current->cp_prev = match;
   1026        inserted = true;
   1027        break;
   1028      }
   1029      prev = current;
   1030      current = current->cp_next;
   1031    }
   1032    if (!inserted) {
   1033      prev->cp_next = match;
   1034      match->cp_prev = prev;
   1035      match->cp_next = compl_first_match;
   1036      compl_first_match->cp_prev = match;
   1037    }
   1038  } else if (dir == FORWARD) {
   1039    match->cp_next = compl_curr_match->cp_next;
   1040    match->cp_prev = compl_curr_match;
   1041  } else {    // BACKWARD
   1042    match->cp_next = compl_curr_match;
   1043    match->cp_prev = compl_curr_match->cp_prev;
   1044  }
   1045  if (match->cp_next) {
   1046    match->cp_next->cp_prev = match;
   1047  }
   1048  if (match->cp_prev) {
   1049    match->cp_prev->cp_next = match;
   1050  } else {        // if there's nothing before, it is the first match
   1051    compl_first_match = match;
   1052  }
   1053  compl_curr_match = match;
   1054 
   1055  // Find the longest common string if still doing that.
   1056  if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0 && !cot_fuzzy()
   1057      && !ins_compl_preinsert_longest() && !ctrl_x_mode_thesaurus()) {
   1058    ins_compl_longest_match(match);
   1059  }
   1060 
   1061  return OK;
   1062 }
   1063 
   1064 /// Check that "str[len]" matches with "match->cp_str", considering
   1065 /// "match->cp_flags".
   1066 ///
   1067 /// @param  match  completion match
   1068 /// @param  str    character string to check
   1069 /// @param  len    length of "str"
   1070 static bool ins_compl_equal(compl_T *match, char *str, size_t len)
   1071  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
   1072 {
   1073  if (match->cp_flags & CP_EQUAL) {
   1074    return true;
   1075  }
   1076  if (match->cp_flags & CP_ICASE) {
   1077    return STRNICMP(match->cp_str.data, str, len) == 0;
   1078  }
   1079  return strncmp(match->cp_str.data, str, len) == 0;
   1080 }
   1081 
   1082 /// when len is -1 mean use whole length of p otherwise part of p
   1083 static void ins_compl_insert_bytes(char *p, int len)
   1084  FUNC_ATTR_NONNULL_ALL
   1085 {
   1086  if (len == -1) {
   1087    len = (int)strlen(p);
   1088  }
   1089  assert(len >= 0);
   1090  ins_bytes_len(p, (size_t)len);
   1091  compl_ins_end_col = curwin->w_cursor.col;
   1092 }
   1093 
   1094 /// Get current completion leader
   1095 char *ins_compl_leader(void)
   1096 {
   1097  return compl_leader.data != NULL ? compl_leader.data : compl_orig_text.data;
   1098 }
   1099 
   1100 /// Get current completion leader length
   1101 static size_t ins_compl_leader_len(void)
   1102 {
   1103  return compl_leader.data != NULL ? compl_leader.size : compl_orig_text.size;
   1104 }
   1105 
   1106 /// Checks if the column is within the currently inserted completion text
   1107 /// column range. If it is, it returns a special highlight attribute.
   1108 /// -1 means normal item.
   1109 int ins_compl_col_range_attr(linenr_T lnum, int col)
   1110 {
   1111  const bool has_preinsert = ins_compl_has_preinsert() || ins_compl_preinsert_longest();
   1112 
   1113  int attr;
   1114  if (cot_fuzzy()
   1115      || (!compl_hi_on_autocompl_longest && ins_compl_preinsert_longest())
   1116      || (attr = syn_name2attr(has_preinsert ? "PreInsert" : "ComplMatchIns")) == 0) {
   1117    return -1;
   1118  }
   1119 
   1120  int start_col = compl_col + (int)ins_compl_leader_len();
   1121  if (!ins_compl_has_multiple()) {
   1122    return (col >= start_col && col < compl_ins_end_col) ? attr : -1;
   1123  }
   1124 
   1125  // Multiple lines
   1126  if ((lnum == compl_lnum && col >= start_col && col < MAXCOL)
   1127      || (lnum > compl_lnum && lnum < curwin->w_cursor.lnum)
   1128      || (lnum == curwin->w_cursor.lnum && col <= compl_ins_end_col)) {
   1129    return attr;
   1130  }
   1131 
   1132  return -1;
   1133 }
   1134 
   1135 /// Returns true if the current completion string contains newline characters,
   1136 /// indicating it's a multi-line completion.
   1137 static bool ins_compl_has_multiple(void)
   1138 {
   1139  return vim_strchr(compl_shown_match->cp_str.data, '\n') != NULL;
   1140 }
   1141 
   1142 /// Returns true if the given line number falls within the range of a multi-line
   1143 /// completion, i.e. between the starting line (compl_lnum) and current cursor
   1144 /// line. Always returns false for single-line completions.
   1145 bool ins_compl_lnum_in_range(linenr_T lnum)
   1146 {
   1147  if (!ins_compl_has_multiple()) {
   1148    return false;
   1149  }
   1150  return lnum >= compl_lnum && lnum <= curwin->w_cursor.lnum;
   1151 }
   1152 
   1153 /// Reduce the longest common string for match "match".
   1154 static void ins_compl_longest_match(compl_T *match)
   1155 {
   1156  if (compl_leader.data == NULL) {
   1157    // First match, use it as a whole.
   1158    compl_leader = copy_string(match->cp_str, NULL);
   1159 
   1160    bool had_match = (curwin->w_cursor.col > compl_col);
   1161    ins_compl_longest_insert(compl_leader.data);
   1162 
   1163    // When the match isn't there (to avoid matching itself) remove it
   1164    // again after redrawing.
   1165    if (!had_match) {
   1166      ins_compl_delete(false);
   1167    }
   1168    compl_used_match = false;
   1169 
   1170    return;
   1171  }
   1172 
   1173  // Reduce the text if this match differs from compl_leader.
   1174  char *p = compl_leader.data;
   1175  char *s = match->cp_str.data;
   1176  while (*p != NUL) {
   1177    int c1 = utf_ptr2char(p);
   1178    int c2 = utf_ptr2char(s);
   1179 
   1180    if ((match->cp_flags & CP_ICASE)
   1181        ? (mb_tolower(c1) != mb_tolower(c2))
   1182        : (c1 != c2)) {
   1183      break;
   1184    }
   1185    MB_PTR_ADV(p);
   1186    MB_PTR_ADV(s);
   1187  }
   1188 
   1189  if (*p != NUL) {
   1190    // Leader was shortened, need to change the inserted text.
   1191    *p = NUL;
   1192    compl_leader.size = (size_t)(p - compl_leader.data);
   1193 
   1194    bool had_match = (curwin->w_cursor.col > compl_col);
   1195    ins_compl_longest_insert(compl_leader.data);
   1196 
   1197    // When the match isn't there (to avoid matching itself) remove it
   1198    // again after redrawing.
   1199    if (!had_match) {
   1200      ins_compl_delete(false);
   1201    }
   1202  }
   1203 
   1204  compl_used_match = false;
   1205 }
   1206 
   1207 /// Add an array of matches to the list of matches.
   1208 /// Frees matches[].
   1209 static void ins_compl_add_matches(int num_matches, char **matches, int icase)
   1210 {
   1211  int add_r = OK;
   1212  Direction dir = compl_direction;
   1213 
   1214  for (int i = 0; i < num_matches && add_r != FAIL; i++) {
   1215    add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
   1216                          CP_FAST | (icase ? CP_ICASE : 0), false, NULL,
   1217                          FUZZY_SCORE_NONE);
   1218    if (add_r == OK) {
   1219      // If dir was BACKWARD then honor it just once.
   1220      dir = FORWARD;
   1221    }
   1222  }
   1223  FreeWild(num_matches, matches);
   1224 }
   1225 
   1226 /// Make the completion list cyclic.
   1227 /// Return the number of matches (excluding the original).
   1228 static int ins_compl_make_cyclic(void)
   1229 {
   1230  if (compl_first_match == NULL) {
   1231    return 0;
   1232  }
   1233 
   1234  // Find the end of the list.
   1235  compl_T *match = compl_first_match;
   1236  int count = 0;
   1237  // there's always an entry for the compl_orig_text, it doesn't count.
   1238  while (match->cp_next != NULL && !is_first_match(match->cp_next)) {
   1239    match = match->cp_next;
   1240    count++;
   1241  }
   1242  match->cp_next = compl_first_match;
   1243  compl_first_match->cp_prev = match;
   1244 
   1245  return count;
   1246 }
   1247 
   1248 /// Return whether there currently is a shown match.
   1249 bool ins_compl_has_shown_match(void)
   1250 {
   1251  return compl_shown_match == NULL || compl_shown_match != compl_shown_match->cp_next;
   1252 }
   1253 
   1254 /// Return whether the shown match is long enough.
   1255 bool ins_compl_long_shown_match(void)
   1256 {
   1257  return compl_shown_match != NULL && compl_shown_match->cp_str.data != NULL
   1258         && (colnr_T)compl_shown_match->cp_str.size > curwin->w_cursor.col - compl_col;
   1259 }
   1260 
   1261 /// Get the local or global value of 'completeopt' flags.
   1262 unsigned get_cot_flags(void)
   1263 {
   1264  return curbuf->b_cot_flags != 0 ? curbuf->b_cot_flags : cot_flags;
   1265 }
   1266 
   1267 /// Remove any popup menu.
   1268 static void ins_compl_del_pum(void)
   1269 {
   1270  if (compl_match_array == NULL) {
   1271    return;
   1272  }
   1273 
   1274  pum_undisplay(false);
   1275  XFREE_CLEAR(compl_match_array);
   1276 }
   1277 
   1278 /// Check if the popup menu should be displayed.
   1279 bool pum_wanted(void)
   1280  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   1281 {
   1282  // "completeopt" must contain "menu" or "menuone"
   1283  return (get_cot_flags() & (kOptCotFlagMenu | kOptCotFlagMenuone)) != 0 || compl_autocomplete;
   1284 }
   1285 
   1286 /// Check that there are two or more matches to be shown in the popup menu.
   1287 /// One if "completopt" contains "menuone".
   1288 static bool pum_enough_matches(void)
   1289  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   1290 {
   1291  // Don't display the popup menu if there are no matches or there is only
   1292  // one (ignoring the original text).
   1293  compl_T *comp = compl_first_match;
   1294  int i = 0;
   1295  do {
   1296    if (comp == NULL || (!match_at_original_text(comp) && ++i == 2)) {
   1297      break;
   1298    }
   1299    comp = comp->cp_next;
   1300  } while (!is_first_match(comp));
   1301 
   1302  if ((get_cot_flags() & kOptCotFlagMenuone) || compl_autocomplete) {
   1303    return i >= 1;
   1304  }
   1305  return i >= 2;
   1306 }
   1307 
   1308 /// Convert to complete item dict
   1309 static dict_T *ins_compl_dict_alloc(compl_T *match)
   1310 {
   1311  // { word, abbr, menu, kind, info }
   1312  dict_T *dict = tv_dict_alloc_lock(VAR_FIXED);
   1313  tv_dict_add_str(dict, S_LEN("word"), match->cp_str.data);
   1314  tv_dict_add_str(dict, S_LEN("abbr"), match->cp_text[CPT_ABBR]);
   1315  tv_dict_add_str(dict, S_LEN("menu"), match->cp_text[CPT_MENU]);
   1316  tv_dict_add_str(dict, S_LEN("kind"), match->cp_text[CPT_KIND]);
   1317  tv_dict_add_str(dict, S_LEN("info"), match->cp_text[CPT_INFO]);
   1318  if (match->cp_user_data.v_type == VAR_UNKNOWN) {
   1319    tv_dict_add_str(dict, S_LEN("user_data"), "");
   1320  } else {
   1321    tv_dict_add_tv(dict, S_LEN("user_data"), &match->cp_user_data);
   1322  }
   1323  return dict;
   1324 }
   1325 
   1326 /// Trigger the CompleteChanged autocmd event. Invoked each time the Insert mode
   1327 /// completion menu is changed.
   1328 static void trigger_complete_changed_event(int cur)
   1329 {
   1330  static bool recursive = false;
   1331  save_v_event_T save_v_event;
   1332 
   1333  if (recursive) {
   1334    return;
   1335  }
   1336 
   1337  dict_T *item = cur < 0 ? tv_dict_alloc() : ins_compl_dict_alloc(compl_curr_match);
   1338  dict_T *v_event = get_v_event(&save_v_event);
   1339  tv_dict_add_dict(v_event, S_LEN("completed_item"), item);
   1340  pum_set_event_info(v_event);
   1341  tv_dict_set_keys_readonly(v_event);
   1342 
   1343  recursive = true;
   1344  textlock++;
   1345  apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, false, curbuf);
   1346  textlock--;
   1347  recursive = false;
   1348 
   1349  restore_v_event(v_event, &save_v_event);
   1350 }
   1351 
   1352 // Helper functions for mergesort_list().
   1353 
   1354 static void *cp_get_next(void *node)
   1355 {
   1356  return ((compl_T *)node)->cp_next;
   1357 }
   1358 
   1359 static void cp_set_next(void *node, void *next)
   1360 {
   1361  ((compl_T *)node)->cp_next = (compl_T *)next;
   1362 }
   1363 
   1364 static void *cp_get_prev(void *node)
   1365 {
   1366  return ((compl_T *)node)->cp_prev;
   1367 }
   1368 
   1369 static void cp_set_prev(void *node, void *prev)
   1370 {
   1371  ((compl_T *)node)->cp_prev = (compl_T *)prev;
   1372 }
   1373 
   1374 static int cp_compare_fuzzy(const void *a, const void *b)
   1375 {
   1376  int score_a = ((compl_T *)a)->cp_score;
   1377  int score_b = ((compl_T *)b)->cp_score;
   1378  return (score_b > score_a) ? 1 : (score_b < score_a) ? -1 : 0;
   1379 }
   1380 
   1381 static int cp_compare_nearest(const void *a, const void *b)
   1382 {
   1383  int score_a = ((compl_T *)a)->cp_score;
   1384  int score_b = ((compl_T *)b)->cp_score;
   1385  if (score_a == FUZZY_SCORE_NONE || score_b == FUZZY_SCORE_NONE) {
   1386    return 0;
   1387  }
   1388  return (score_a > score_b) ? 1 : (score_a < score_b) ? -1 : 0;
   1389 }
   1390 
   1391 /// Constructs a new string by prepending text from the current line (from
   1392 /// startcol to compl_col) to the given source string. Stores the result in
   1393 /// dest.
   1394 static void prepend_startcol_text(String *dest, String *src, int startcol)
   1395 {
   1396  int prepend_len = compl_col - startcol;
   1397  int new_length = prepend_len + (int)src->size;
   1398 
   1399  dest->size = (size_t)new_length;
   1400  dest->data = xmalloc((size_t)new_length + 1);  // +1 for NUL
   1401 
   1402  char *line = ml_get(curwin->w_cursor.lnum);
   1403 
   1404  memmove(dest->data, line + startcol, (size_t)prepend_len);
   1405  memmove(dest->data + prepend_len, src->data, src->size);
   1406  dest->data[new_length] = NUL;
   1407 }
   1408 
   1409 /// Returns the completion leader string adjusted for a specific source's
   1410 /// startcol. If the source's startcol is before compl_col, prepends text from
   1411 /// the buffer line to the original compl_leader.
   1412 static String *get_leader_for_startcol(compl_T *match, bool cached)
   1413 {
   1414  static String adjusted_leader = STRING_INIT;
   1415 
   1416  if (match == NULL) {
   1417    API_CLEAR_STRING(adjusted_leader);
   1418    return NULL;
   1419  }
   1420 
   1421  if (cpt_sources_array == NULL) {
   1422    goto theend;
   1423  }
   1424 
   1425  int cpt_idx = match->cp_cpt_source_idx;
   1426  if (cpt_idx < 0) {
   1427    goto theend;
   1428  }
   1429  int startcol = cpt_sources_array[cpt_idx].cs_startcol;
   1430 
   1431  if (compl_leader.data == NULL) {
   1432    // When leader is not set (e.g. 'autocomplete' first fires before
   1433    // compl_leader is initialised), fall back to compl_orig_text for
   1434    // matches starting at or after compl_col.  Matches starting before
   1435    // compl_col carry pre-compl_col text and must not be compared with
   1436    // compl_orig_text, so return &compl_leader (NULL string) to signal
   1437    // "pass through" (no prefix filter).
   1438    if (startcol < 0 || startcol >= compl_col) {
   1439      return &compl_orig_text;
   1440    }
   1441    return &compl_leader;  // pass through (startcol < compl_col)
   1442  }
   1443 
   1444  if (compl_col <= 0) {
   1445    goto theend;
   1446  }
   1447 
   1448  if (startcol >= 0 && startcol < compl_col) {
   1449    int prepend_len = compl_col - startcol;
   1450    int new_length = prepend_len + (int)compl_leader.size;
   1451    if (cached && (size_t)new_length == adjusted_leader.size
   1452        && adjusted_leader.data != NULL) {
   1453      return &adjusted_leader;
   1454    }
   1455 
   1456    API_CLEAR_STRING(adjusted_leader);
   1457    prepend_startcol_text(&adjusted_leader, &compl_leader, startcol);
   1458    return &adjusted_leader;
   1459  }
   1460 theend:
   1461  return &compl_leader;
   1462 }
   1463 
   1464 /// Set fuzzy score for completion matches.
   1465 static void set_fuzzy_score(void)
   1466 {
   1467  if (compl_first_match == NULL) {
   1468    return;
   1469  }
   1470 
   1471  // Determine the pattern to match against
   1472  bool use_leader = (compl_leader.data != NULL && compl_leader.size > 0);
   1473  char *pattern;
   1474  if (!use_leader) {
   1475    if (compl_orig_text.data == NULL || compl_orig_text.size == 0) {
   1476      return;
   1477    }
   1478    pattern = compl_orig_text.data;
   1479  } else {
   1480    // Clear the leader cache once before the loop
   1481    (void)get_leader_for_startcol(NULL, true);
   1482    pattern = NULL;  // Will be computed per-completion
   1483  }
   1484 
   1485  // Score all completion matches
   1486  compl_T *comp = compl_first_match;
   1487  do {
   1488    if (use_leader) {
   1489      pattern = get_leader_for_startcol(comp, true)->data;
   1490    }
   1491 
   1492    comp->cp_score = fuzzy_match_str(comp->cp_str.data, pattern);
   1493    comp = comp->cp_next;
   1494  } while (comp != NULL && !is_first_match(comp));
   1495 }
   1496 
   1497 /// Sort completion matches, excluding the node that contains the leader.
   1498 static void sort_compl_match_list(MergeSortCompareFunc compare)
   1499 {
   1500  if (!compl_first_match || is_first_match(compl_first_match->cp_next)) {
   1501    return;
   1502  }
   1503 
   1504  compl_T *comp = compl_first_match->cp_prev;
   1505  ins_compl_make_linear();
   1506  if (compl_shows_dir_forward()) {
   1507    compl_first_match->cp_next->cp_prev = NULL;
   1508    compl_first_match->cp_next = mergesort_list(compl_first_match->cp_next,
   1509                                                cp_get_next, cp_set_next,
   1510                                                cp_get_prev, cp_set_prev,
   1511                                                compare);
   1512    compl_first_match->cp_next->cp_prev = compl_first_match;
   1513  } else {
   1514    comp->cp_prev->cp_next = NULL;
   1515    compl_first_match = mergesort_list(compl_first_match, cp_get_next, cp_set_next,
   1516                                       cp_get_prev, cp_set_prev, compare);
   1517    compl_T *tail = compl_first_match;
   1518    while (tail->cp_next != NULL) {
   1519      tail = tail->cp_next;
   1520    }
   1521    tail->cp_next = comp;
   1522    comp->cp_prev = tail;
   1523  }
   1524  (void)ins_compl_make_cyclic();
   1525 }
   1526 
   1527 /// Build a popup menu to show the completion matches.
   1528 ///
   1529 /// @return  the popup menu entry that should be selected,
   1530 ///          -1 if nothing should be selected.
   1531 static int ins_compl_build_pum(void)
   1532 {
   1533  // Need to build the popup menu list.
   1534  compl_match_arraysize = 0;
   1535 
   1536  // If it's user complete function and refresh_always,
   1537  // do not use "compl_leader" as prefix filter.
   1538  if (ins_compl_need_restart()) {
   1539    XFREE_CLEAR(compl_leader);
   1540  }
   1541 
   1542  bool compl_no_select = (get_cot_flags() & kOptCotFlagNoselect) != 0
   1543                         || (compl_autocomplete && !ins_compl_has_preinsert());
   1544 
   1545  compl_T *match_head = NULL, *match_tail = NULL;
   1546  int *match_count = NULL;
   1547  bool is_forward = compl_shows_dir_forward();
   1548  bool is_cpt_completion = (cpt_sources_array != NULL);
   1549 
   1550  // If the current match is the original text don't find the first
   1551  // match after it, don't highlight anything.
   1552  bool shown_match_ok = match_at_original_text(compl_shown_match);
   1553 
   1554  if (strequal(compl_leader.data, compl_orig_text.data) && !shown_match_ok) {
   1555    compl_shown_match = compl_no_select ? compl_first_match : compl_first_match->cp_next;
   1556  }
   1557 
   1558  bool did_find_shown_match = false;
   1559  compl_T *comp;
   1560  compl_T *shown_compl = NULL;
   1561  int i = 0;
   1562  int cur = -1;
   1563 
   1564  if (is_cpt_completion) {
   1565    match_count = xcalloc((size_t)cpt_sources_count, sizeof(int));
   1566  }
   1567 
   1568  (void)get_leader_for_startcol(NULL, true);  // Clear the cache
   1569 
   1570  comp = compl_first_match;
   1571  do {
   1572    comp->cp_in_match_array = false;
   1573 
   1574    String *leader = get_leader_for_startcol(comp, true);
   1575 
   1576    // Apply 'smartcase' behavior during normal mode
   1577    if (ctrl_x_mode_normal() && !p_inf && leader->data
   1578        && !ignorecase(leader->data) && !cot_fuzzy()) {
   1579      comp->cp_flags &= ~CP_ICASE;
   1580    }
   1581 
   1582    if (!match_at_original_text(comp)
   1583        && (leader->data == NULL
   1584            || ins_compl_equal(comp, leader->data, leader->size)
   1585            || (cot_fuzzy() && comp->cp_score != FUZZY_SCORE_NONE))) {
   1586      // Limit number of items from each source if max_items is set.
   1587      bool match_limit_exceeded = false;
   1588      int cur_source = comp->cp_cpt_source_idx;
   1589      if (is_forward && cur_source != -1 && is_cpt_completion) {
   1590        match_count[cur_source]++;
   1591        int max_matches = cpt_sources_array[cur_source].cs_max_matches;
   1592        if (max_matches > 0 && match_count[cur_source] > max_matches) {
   1593          match_limit_exceeded = true;
   1594        }
   1595      }
   1596 
   1597      if (!match_limit_exceeded) {
   1598        compl_match_arraysize++;
   1599        comp->cp_in_match_array = true;
   1600        if (match_head == NULL) {
   1601          match_head = comp;
   1602        } else {
   1603          match_tail->cp_match_next = comp;
   1604        }
   1605        match_tail = comp;
   1606 
   1607        if (!shown_match_ok && !cot_fuzzy()) {
   1608          if (comp == compl_shown_match || did_find_shown_match) {
   1609            // This item is the shown match or this is the
   1610            // first displayed item after the shown match.
   1611            compl_shown_match = comp;
   1612            did_find_shown_match = true;
   1613            shown_match_ok = true;
   1614          } else {
   1615            // Remember this displayed match for when the
   1616            // shown match is just below it.
   1617            shown_compl = comp;
   1618          }
   1619          cur = i;
   1620        } else if (cot_fuzzy()) {
   1621          if (i == 0) {
   1622            shown_compl = comp;
   1623          }
   1624 
   1625          if (!shown_match_ok && comp == compl_shown_match) {
   1626            cur = i;
   1627            shown_match_ok = true;
   1628          }
   1629        }
   1630        i++;
   1631      }
   1632    }
   1633 
   1634    if (comp == compl_shown_match && !cot_fuzzy()) {
   1635      did_find_shown_match = true;
   1636      // When the original text is the shown match don't set
   1637      // compl_shown_match.
   1638      if (match_at_original_text(comp)) {
   1639        shown_match_ok = true;
   1640      }
   1641      if (!shown_match_ok && shown_compl != NULL) {
   1642        // The shown match isn't displayed, set it to the
   1643        // previously displayed match.
   1644        compl_shown_match = shown_compl;
   1645        shown_match_ok = true;
   1646      }
   1647    }
   1648    comp = comp->cp_next;
   1649  } while (comp != NULL && !is_first_match(comp));
   1650 
   1651  xfree(match_count);
   1652 
   1653  if (compl_match_arraysize == 0) {
   1654    return -1;
   1655  }
   1656 
   1657  if (cot_fuzzy() && !compl_no_select && !shown_match_ok) {
   1658    compl_shown_match = shown_compl;
   1659    shown_match_ok = true;
   1660    cur = 0;
   1661  }
   1662 
   1663  assert(compl_match_arraysize >= 0);
   1664  compl_match_array = xcalloc((size_t)compl_match_arraysize, sizeof(pumitem_T));
   1665 
   1666  i = 0;
   1667  comp = match_head;
   1668  while (comp != NULL) {
   1669    compl_match_array[i].pum_text = comp->cp_text[CPT_ABBR] != NULL
   1670                                    ? comp->cp_text[CPT_ABBR] : comp->cp_str.data;
   1671    compl_match_array[i].pum_kind = comp->cp_text[CPT_KIND];
   1672    compl_match_array[i].pum_info = comp->cp_text[CPT_INFO];
   1673    compl_match_array[i].pum_cpt_source_idx = comp->cp_cpt_source_idx;
   1674    compl_match_array[i].pum_user_abbr_hlattr = comp->cp_user_abbr_hlattr;
   1675    compl_match_array[i].pum_user_kind_hlattr = comp->cp_user_kind_hlattr;
   1676    compl_match_array[i++].pum_extra = comp->cp_text[CPT_MENU] != NULL
   1677                                       ? comp->cp_text[CPT_MENU] : comp->cp_fname;
   1678    compl_T *match_next = comp->cp_match_next;
   1679    comp->cp_match_next = NULL;
   1680    comp = match_next;
   1681  }
   1682 
   1683  if (!shown_match_ok) {  // no displayed match at all
   1684    cur = -1;
   1685  }
   1686 
   1687  return cur;
   1688 }
   1689 
   1690 /// Show the popup menu for the list of matches.
   1691 /// Also adjusts "compl_shown_match" to an entry that is actually displayed.
   1692 void ins_compl_show_pum(void)
   1693 {
   1694  if (!pum_wanted() || !pum_enough_matches()) {
   1695    return;
   1696  }
   1697 
   1698  // Update the screen before drawing the popup menu over it.
   1699  update_screen();
   1700 
   1701  int cur = -1;
   1702  bool array_changed = false;
   1703 
   1704  if (compl_match_array == NULL) {
   1705    array_changed = true;
   1706    // Need to build the popup menu list.
   1707    cur = ins_compl_build_pum();
   1708  } else {
   1709    // popup menu already exists, only need to find the current item.
   1710    for (int i = 0; i < compl_match_arraysize; i++) {
   1711      if (compl_match_array[i].pum_text == compl_shown_match->cp_str.data
   1712          || compl_match_array[i].pum_text == compl_shown_match->cp_text[CPT_ABBR]) {
   1713        cur = i;
   1714        break;
   1715      }
   1716    }
   1717  }
   1718 
   1719  if (compl_match_array == NULL) {
   1720    if (compl_started && has_event(EVENT_COMPLETECHANGED)) {
   1721      trigger_complete_changed_event(cur);
   1722    }
   1723    return;
   1724  }
   1725 
   1726  // In Replace mode when a $ is displayed at the end of the line only
   1727  // part of the screen would be updated.  We do need to redraw here.
   1728  dollar_vcol = -1;
   1729 
   1730  // Compute the screen column of the start of the completed text.
   1731  // Use the cursor to get all wrapping and other settings right.
   1732  const colnr_T col = curwin->w_cursor.col;
   1733  curwin->w_cursor.col = compl_col;
   1734  compl_selected_item = cur;
   1735  pum_display(compl_match_array, compl_match_arraysize, cur, array_changed, 0);
   1736  curwin->w_cursor.col = col;
   1737 
   1738  // After adding leader, set the current match to shown match.
   1739  if (compl_started && compl_curr_match != compl_shown_match) {
   1740    compl_curr_match = compl_shown_match;
   1741  }
   1742 
   1743  if (has_event(EVENT_COMPLETECHANGED)) {
   1744    trigger_complete_changed_event(cur);
   1745  }
   1746 }
   1747 
   1748 /// check selected is current match.
   1749 ///
   1750 /// @param selected the item which is selected.
   1751 /// @return bool    return true when is current match otherwise is false.
   1752 bool compl_match_curr_select(int selected)
   1753 {
   1754  if (selected < 0) {
   1755    return false;
   1756  }
   1757  compl_T *match = compl_first_match;
   1758  int selected_idx = -1, list_idx = 0;
   1759  do {
   1760    if (!match_at_original_text(match)) {
   1761      if (compl_curr_match != NULL
   1762          && compl_curr_match->cp_number == match->cp_number) {
   1763        selected_idx = list_idx;
   1764        break;
   1765      }
   1766      list_idx += 1;
   1767    }
   1768    match = match->cp_next;
   1769  } while (match != NULL && !is_first_match(match));
   1770 
   1771  return selected == selected_idx;
   1772 }
   1773 
   1774 #define DICT_FIRST      (1)     ///< use just first element in "dict"
   1775 #define DICT_EXACT      (2)     ///< "dict" is the exact name of a file
   1776 
   1777 /// Add any identifiers that match the given pattern "pat" in the list of
   1778 /// dictionary files "dict_start" to the list of completions.
   1779 ///
   1780 /// @param flags      DICT_FIRST and/or DICT_EXACT
   1781 /// @param thesaurus  Thesaurus completion
   1782 static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, bool thesaurus)
   1783 {
   1784  char *dict = dict_start;
   1785  char *ptr;
   1786  regmatch_T regmatch;
   1787  char **files;
   1788  int count;
   1789  Direction dir = compl_direction;
   1790 
   1791  if (*dict == NUL) {
   1792    // When 'dictionary' is empty and spell checking is enabled use
   1793    // "spell".
   1794    if (!thesaurus && curwin->w_p_spell) {
   1795      dict = "spell";
   1796    } else {
   1797      return;
   1798    }
   1799  }
   1800 
   1801  char *buf = xmalloc(LSIZE);
   1802  regmatch.regprog = NULL;      // so that we can goto theend
   1803 
   1804  // If 'infercase' is set, don't use 'smartcase' here
   1805  int save_p_scs = p_scs;
   1806  if (curbuf->b_p_inf) {
   1807    p_scs = false;
   1808  }
   1809 
   1810  // When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
   1811  // to only match at the start of a line.  Otherwise just match the
   1812  // pattern. Also need to double backslashes.
   1813  if (ctrl_x_mode_line_or_eval()) {
   1814    char *pat_esc = vim_strsave_escaped(pat, "\\");
   1815 
   1816    size_t len = strlen(pat_esc) + 10;
   1817    ptr = xmalloc(len);
   1818    vim_snprintf(ptr, len, "^\\s*\\zs\\V%s", pat_esc);
   1819    regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
   1820    xfree(pat_esc);
   1821    xfree(ptr);
   1822  } else {
   1823    regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
   1824    if (regmatch.regprog == NULL) {
   1825      goto theend;
   1826    }
   1827  }
   1828 
   1829  // ignore case depends on 'ignorecase', 'smartcase' and "pat"
   1830  regmatch.rm_ic = ignorecase(pat);
   1831  while (*dict != NUL && !got_int && !compl_interrupted) {
   1832    // copy one dictionary file name into buf
   1833    if (flags == DICT_EXACT) {
   1834      count = 1;
   1835      files = &dict;
   1836    } else {
   1837      // Expand wildcards in the dictionary name, but do not allow
   1838      // backticks (for security, the 'dict' option may have been set in
   1839      // a modeline).
   1840      copy_option_part(&dict, buf, LSIZE, ",");
   1841      if (!thesaurus && strcmp(buf, "spell") == 0) {
   1842        count = -1;
   1843      } else if (vim_strchr(buf, '`') != NULL
   1844                 || expand_wildcards(1, &buf, &count, &files,
   1845                                     EW_FILE|EW_SILENT) != OK) {
   1846        count = 0;
   1847      }
   1848    }
   1849 
   1850    if (count == -1) {
   1851      // Complete from active spelling.  Skip "\<" in the pattern, we
   1852      // don't use it as a RE.
   1853      if (pat[0] == '\\' && pat[1] == '<') {
   1854        ptr = pat + 2;
   1855      } else {
   1856        ptr = pat;
   1857      }
   1858      spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
   1859    } else if (count > 0) {  // avoid warning for using "files" uninit
   1860      ins_compl_files(count, files, thesaurus, flags, &regmatch, buf, &dir);
   1861      if (flags != DICT_EXACT) {
   1862        FreeWild(count, files);
   1863      }
   1864    }
   1865    if (flags != 0) {
   1866      break;
   1867    }
   1868  }
   1869 
   1870 theend:
   1871  p_scs = save_p_scs;
   1872  vim_regfree(regmatch.regprog);
   1873  xfree(buf);
   1874 }
   1875 
   1876 /// Add all the words in the line "*buf_arg" from the thesaurus file "fname"
   1877 /// skipping the word at 'skip_word'.
   1878 ///
   1879 /// @return  OK on success.
   1880 static int thesaurus_add_words_in_line(char *fname, char **buf_arg, int dir, const char *skip_word)
   1881 {
   1882  int status = OK;
   1883 
   1884  // Add the other matches on the line
   1885  char *ptr = *buf_arg;
   1886  while (!got_int) {
   1887    // Find start of the next word.  Skip white
   1888    // space and punctuation.
   1889    ptr = find_word_start(ptr);
   1890    if (*ptr == NUL || *ptr == NL) {
   1891      break;
   1892    }
   1893    char *wstart = ptr;
   1894 
   1895    // Find end of the word.
   1896    // Japanese words may have characters in
   1897    // different classes, only separate words
   1898    // with single-byte non-word characters.
   1899    while (*ptr != NUL) {
   1900      const int l = utfc_ptr2len(ptr);
   1901 
   1902      if (l < 2 && !vim_iswordc((uint8_t)(*ptr))) {
   1903        break;
   1904      }
   1905      ptr += l;
   1906    }
   1907 
   1908    // Add the word. Skip the regexp match.
   1909    if (wstart != skip_word) {
   1910      status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic,
   1911                                       fname, dir, false, FUZZY_SCORE_NONE);
   1912      if (status == FAIL) {
   1913        break;
   1914      }
   1915    }
   1916  }
   1917 
   1918  *buf_arg = ptr;
   1919  return status;
   1920 }
   1921 
   1922 /// Process "count" dictionary/thesaurus "files" and add the text matching
   1923 /// "regmatch".
   1924 static void ins_compl_files(int count, char **files, bool thesaurus, int flags,
   1925                            regmatch_T *regmatch, char *buf, Direction *dir)
   1926  FUNC_ATTR_NONNULL_ARG(2, 7)
   1927 {
   1928  char *leader = cot_fuzzy() ? ins_compl_leader() : NULL;
   1929  int leader_len = cot_fuzzy() ? (int)ins_compl_leader_len() : 0;
   1930 
   1931  for (int i = 0; i < count && !got_int && !ins_compl_interrupted(); i++) {
   1932    FILE *fp = os_fopen(files[i], "r");  // open dictionary file
   1933    if (flags != DICT_EXACT && !shortmess(SHM_COMPLETIONSCAN) && !compl_autocomplete) {
   1934      msg_hist_off = true;  // reset in msg_trunc()
   1935      msg_ext_set_kind("completion");
   1936      vim_snprintf(IObuff, IOSIZE,
   1937                   _("Scanning dictionary: %s"), files[i]);
   1938      msg_trunc(IObuff, true, HLF_R);
   1939    }
   1940 
   1941    if (fp == NULL) {
   1942      continue;
   1943    }
   1944 
   1945    // Read dictionary file line by line.
   1946    // Check each line for a match.
   1947    while (!got_int && !ins_compl_interrupted() && !vim_fgets(buf, LSIZE, fp)) {
   1948      char *ptr = buf;
   1949      if (cot_fuzzy() && leader_len > 0) {
   1950        char *line_end = find_line_end(ptr);
   1951        while (ptr < line_end) {
   1952          int score = 0;
   1953          int len = 0;
   1954          if (fuzzy_match_str_in_line(&ptr, leader, &len, NULL, &score)) {
   1955            char *end_ptr = ctrl_x_mode_line_or_eval()
   1956                            ? find_line_end(ptr) : find_word_end(ptr);
   1957            int add_r = ins_compl_add_infercase(ptr, (int)(end_ptr - ptr),
   1958                                                p_ic, files[i], *dir, false, score);
   1959            if (add_r == FAIL) {
   1960              break;
   1961            }
   1962            ptr = end_ptr;  // start from next word
   1963            if (compl_get_longest && ctrl_x_mode_normal()
   1964                && compl_first_match->cp_next
   1965                && score == compl_first_match->cp_next->cp_score) {
   1966              compl_num_bests++;
   1967            }
   1968          }
   1969        }
   1970      } else if (regmatch != NULL) {
   1971        while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf))) {
   1972          ptr = regmatch->startp[0];
   1973          ptr = ctrl_x_mode_line_or_eval() ? find_line_end(ptr) : find_word_end(ptr);
   1974          int add_r = ins_compl_add_infercase(regmatch->startp[0],
   1975                                              (int)(ptr - regmatch->startp[0]),
   1976                                              p_ic, files[i], *dir, false,
   1977                                              FUZZY_SCORE_NONE);
   1978          if (thesaurus) {
   1979            // For a thesaurus, add all the words in the line
   1980            ptr = buf;
   1981            add_r = thesaurus_add_words_in_line(files[i], &ptr, *dir, regmatch->startp[0]);
   1982          }
   1983          if (add_r == OK) {
   1984            // if dir was BACKWARD then honor it just once
   1985            *dir = FORWARD;
   1986          } else if (add_r == FAIL) {
   1987            break;
   1988          }
   1989          // avoid expensive call to vim_regexec() when at end
   1990          // of line
   1991          if (*ptr == '\n' || got_int) {
   1992            break;
   1993          }
   1994        }
   1995      }
   1996      line_breakcheck();
   1997      ins_compl_check_keys(50, false);
   1998    }
   1999    fclose(fp);
   2000  }
   2001 }
   2002 
   2003 /// Find the start of the next word.
   2004 /// Returns a pointer to the first char of the word.  Also stops at a NUL.
   2005 char *find_word_start(char *ptr)
   2006  FUNC_ATTR_PURE
   2007 {
   2008  while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1) {
   2009    ptr += utfc_ptr2len(ptr);
   2010  }
   2011  return ptr;
   2012 }
   2013 
   2014 /// Find the end of the word.  Assumes it starts inside a word.
   2015 /// Returns a pointer to just after the word.
   2016 char *find_word_end(char *ptr)
   2017  FUNC_ATTR_PURE
   2018 {
   2019  const int start_class = mb_get_class(ptr);
   2020  if (start_class > 1) {
   2021    while (*ptr != NUL) {
   2022      ptr += utfc_ptr2len(ptr);
   2023      if (mb_get_class(ptr) != start_class) {
   2024        break;
   2025      }
   2026    }
   2027  }
   2028  return ptr;
   2029 }
   2030 
   2031 /// Find the end of the line, omitting CR and NL at the end.
   2032 ///
   2033 /// @return  a pointer to just after the line.
   2034 char *find_line_end(char *ptr)
   2035 {
   2036  char *s = ptr + strlen(ptr);
   2037  while (s > ptr && (s[-1] == CAR || s[-1] == NL)) {
   2038    s--;
   2039  }
   2040  return s;
   2041 }
   2042 
   2043 /// Free a completion item in the list
   2044 static void ins_compl_item_free(compl_T *match)
   2045 {
   2046  API_CLEAR_STRING(match->cp_str);
   2047  // several entries may use the same fname, free it just once.
   2048  if (match->cp_flags & CP_FREE_FNAME) {
   2049    xfree(match->cp_fname);
   2050  }
   2051  free_cptext(match->cp_text);
   2052  tv_clear(&match->cp_user_data);
   2053  xfree(match);
   2054 }
   2055 
   2056 /// Free the list of completions
   2057 static void ins_compl_free(void)
   2058 {
   2059  API_CLEAR_STRING(compl_pattern);
   2060  API_CLEAR_STRING(compl_leader);
   2061 
   2062  if (compl_first_match == NULL) {
   2063    return;
   2064  }
   2065 
   2066  ins_compl_del_pum();
   2067  pum_clear();
   2068 
   2069  compl_curr_match = compl_first_match;
   2070  do {
   2071    compl_T *match = compl_curr_match;
   2072    compl_curr_match = compl_curr_match->cp_next;
   2073    ins_compl_item_free(match);
   2074  } while (compl_curr_match != NULL && !is_first_match(compl_curr_match));
   2075  compl_first_match = compl_curr_match = NULL;
   2076  compl_shown_match = NULL;
   2077  compl_old_match = NULL;
   2078 }
   2079 
   2080 /// Reset/clear the completion state.
   2081 void ins_compl_clear(void)
   2082 {
   2083  compl_cont_status = 0;
   2084  compl_started = false;
   2085  compl_matches = 0;
   2086  compl_selected_item = -1;
   2087  compl_ins_end_col = 0;
   2088  compl_curr_win = NULL;
   2089  compl_curr_buf = NULL;
   2090  API_CLEAR_STRING(compl_pattern);
   2091  API_CLEAR_STRING(compl_leader);
   2092  edit_submode_extra = NULL;
   2093  kv_destroy(compl_orig_extmarks);
   2094  API_CLEAR_STRING(compl_orig_text);
   2095  compl_enter_selects = false;
   2096  cpt_sources_clear();
   2097  compl_autocomplete = false;
   2098  compl_from_nonkeyword = false;
   2099  compl_num_bests = 0;
   2100  // clear v:completed_item
   2101  set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc_lock(VAR_FIXED));
   2102 }
   2103 
   2104 /// Check that Insert completion is active.
   2105 bool ins_compl_active(void)
   2106  FUNC_ATTR_PURE
   2107 {
   2108  return compl_started;
   2109 }
   2110 
   2111 /// Return true when wp is the actual completion window
   2112 bool ins_compl_win_active(win_T *wp)
   2113 {
   2114  return ins_compl_active() && wp == compl_curr_win && wp->w_buffer == compl_curr_buf;
   2115 }
   2116 
   2117 /// Selected one of the matches.  When false, the match was edited or
   2118 /// using the longest common string.
   2119 bool ins_compl_used_match(void)
   2120 {
   2121  return compl_used_match;
   2122 }
   2123 
   2124 /// Initialize get longest common string.
   2125 void ins_compl_init_get_longest(void)
   2126 {
   2127  compl_get_longest = false;
   2128 }
   2129 
   2130 /// Returns true when insert completion is interrupted.
   2131 bool ins_compl_interrupted(void)
   2132 {
   2133  return compl_interrupted || compl_time_slice_expired;
   2134 }
   2135 
   2136 /// Returns true if the <Enter> key selects a match in the completion popup
   2137 /// menu.
   2138 bool ins_compl_enter_selects(void)
   2139 {
   2140  return compl_enter_selects;
   2141 }
   2142 
   2143 /// Return the column where the text starts that is being completed
   2144 colnr_T ins_compl_col(void)
   2145 {
   2146  return compl_col;
   2147 }
   2148 
   2149 /// Return the length in bytes of the text being completed
   2150 int ins_compl_len(void)
   2151 {
   2152  return compl_length;
   2153 }
   2154 
   2155 /// Return true when the 'completeopt' "preinsert" flag is in effect,
   2156 /// otherwise return false.
   2157 bool ins_compl_has_preinsert(void)
   2158 {
   2159  unsigned cur_cot_flags = get_cot_flags();
   2160  if (compl_autocomplete && p_ic && !p_inf) {
   2161    return false;
   2162  }
   2163  return (!compl_autocomplete
   2164          ? (cur_cot_flags & (kOptCotFlagPreinsert|kOptCotFlagFuzzy|kOptCotFlagMenuone))
   2165          == (kOptCotFlagPreinsert|kOptCotFlagMenuone)
   2166          : (cur_cot_flags & (kOptCotFlagPreinsert|kOptCotFlagFuzzy))
   2167          == kOptCotFlagPreinsert);
   2168 }
   2169 
   2170 /// Returns true if the pre-insert effect is valid and the cursor is within
   2171 /// the `compl_ins_end_col` range.
   2172 bool ins_compl_preinsert_effect(void)
   2173 {
   2174  if (!ins_compl_has_preinsert() && !ins_compl_preinsert_longest()) {
   2175    return false;
   2176  }
   2177 
   2178  return curwin->w_cursor.col < compl_ins_end_col;
   2179 }
   2180 
   2181 /// Delete one character before the cursor and show the subset of the matches
   2182 /// that match the word that is now before the cursor.
   2183 /// Returns the character to be used, NUL if the work is done and another char
   2184 /// to be got from the user.
   2185 int ins_compl_bs(void)
   2186 {
   2187  if (ins_compl_preinsert_effect()) {
   2188    ins_compl_delete(false);
   2189  }
   2190 
   2191  char *line = get_cursor_line_ptr();
   2192  char *p = line + curwin->w_cursor.col;
   2193  MB_PTR_BACK(line, p);
   2194  ptrdiff_t p_off = p - line;
   2195 
   2196  // Stop completion when the whole word was deleted.  For Omni completion
   2197  // allow the word to be deleted, we won't match everything.
   2198  // Respect the 'backspace' option.
   2199  if ((int)(p - line) - (int)compl_col < 0
   2200      || ((int)(p - line) - (int)compl_col == 0 && !ctrl_x_mode_omni())
   2201      || ctrl_x_mode_eval()
   2202      || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
   2203          - compl_length < 0)) {
   2204    return K_BS;
   2205  }
   2206 
   2207  // Deleted more than what was used to find matches or didn't finish
   2208  // finding all matches: need to look for matches all over again.
   2209  if (curwin->w_cursor.col <= compl_col + compl_length
   2210      || ins_compl_need_restart()) {
   2211    ins_compl_restart();
   2212  }
   2213 
   2214  // ins_compl_restart() calls update_screen() which may invalidate the pointer
   2215  // TODO(bfredl): get rid of random update_screen() calls deep inside completion logic
   2216  line = get_cursor_line_ptr();
   2217 
   2218  API_CLEAR_STRING(compl_leader);
   2219  compl_leader = cbuf_to_string(line + compl_col,
   2220                                (size_t)(p_off - (ptrdiff_t)compl_col));
   2221 
   2222  // Clear selection if a menu item is currently selected in autocompletion
   2223  if (compl_autocomplete && compl_first_match && !ins_compl_has_preinsert()) {
   2224    compl_shown_match = compl_first_match;
   2225  }
   2226 
   2227  ins_compl_new_leader();
   2228  if (compl_shown_match != NULL) {
   2229    // Make sure current match is not a hidden item.
   2230    compl_curr_match = compl_shown_match;
   2231  }
   2232  return NUL;
   2233 }
   2234 
   2235 /// Check if the complete function returned "always" in the "refresh" dictionary item.
   2236 static bool ins_compl_refresh_always(void)
   2237  FUNC_ATTR_PURE
   2238 {
   2239  return (ctrl_x_mode_function() || ctrl_x_mode_omni()) && compl_opt_refresh_always;
   2240 }
   2241 
   2242 /// Check that we need to find matches again, ins_compl_restart() is to
   2243 /// be called.
   2244 static bool ins_compl_need_restart(void)
   2245  FUNC_ATTR_PURE
   2246 {
   2247  // Return true if we didn't complete finding matches or when the
   2248  // "completefunc" returned "always" in the "refresh" dictionary item.
   2249  return compl_was_interrupted || ins_compl_refresh_always();
   2250 }
   2251 
   2252 /// Return true if 'autocomplete' option is set
   2253 bool ins_compl_has_autocomplete(void)
   2254 {
   2255  // Use buffer-local setting if defined (>= 0), otherwise use global
   2256  return curbuf->b_p_ac >= 0 ? curbuf->b_p_ac : p_ac;
   2257 }
   2258 
   2259 /// Calculate fuzzy score and sort completion matches unless sorting is disabled.
   2260 static void ins_compl_fuzzy_sort(void)
   2261 {
   2262  unsigned cur_cot_flags = get_cot_flags();
   2263 
   2264  // Set the fuzzy score in cp_score and sort
   2265  set_fuzzy_score();
   2266  if (!(cur_cot_flags & kOptCotFlagNosort)) {
   2267    sort_compl_match_list(cp_compare_fuzzy);
   2268    // Reset the shown item since sorting reorders items
   2269    if ((cur_cot_flags & (kOptCotFlagNoinsert|kOptCotFlagNoselect)) == kOptCotFlagNoinsert) {
   2270      bool none_selected = compl_shown_match == (compl_shows_dir_forward()
   2271                                                 ? compl_first_match : compl_first_match->cp_prev);
   2272      if (!none_selected) {
   2273        compl_shown_match = (!compl_autocomplete && compl_shows_dir_forward())
   2274                            ? compl_first_match->cp_next : compl_first_match;
   2275      }
   2276    }
   2277  }
   2278 }
   2279 
   2280 /// Called after changing "compl_leader".
   2281 /// Show the popup menu with a different set of matches.
   2282 /// May also search for matches again if the previous search was interrupted.
   2283 static void ins_compl_new_leader(void)
   2284 {
   2285  ins_compl_del_pum();
   2286  ins_compl_delete(true);
   2287  ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
   2288  compl_used_match = false;
   2289 
   2290  if (p_acl > 0) {
   2291    pum_undisplay(true);
   2292    redraw_later(curwin, UPD_VALID);
   2293    update_screen();  // Show char (deletion) immediately
   2294    ui_flush();
   2295  }
   2296 
   2297  if (compl_started) {
   2298    ins_compl_set_original_text(compl_leader.data, compl_leader.size);
   2299    if (is_cpt_func_refresh_always()) {
   2300      cpt_compl_refresh();
   2301    }
   2302    if (cot_fuzzy()) {
   2303      ins_compl_fuzzy_sort();
   2304    }
   2305  } else {
   2306    spell_bad_len = 0;  // need to redetect bad word
   2307    // Matches were cleared, need to search for them now.
   2308    // Set "compl_restarting" to avoid that the first match is inserted.
   2309    compl_restarting = true;
   2310    if (ins_compl_has_autocomplete()) {
   2311      ins_compl_enable_autocomplete();
   2312    } else {
   2313      compl_autocomplete = false;
   2314    }
   2315    if (ins_complete(Ctrl_N, true) == FAIL) {
   2316      compl_cont_status = 0;
   2317    }
   2318    compl_restarting = false;
   2319  }
   2320 
   2321  compl_enter_selects = !compl_used_match && compl_selected_item != -1;
   2322 
   2323  // Show the popup menu with a different set of matches.
   2324  ins_compl_show_pum();
   2325 
   2326  // Don't let Enter select the original text when there is no popup menu.
   2327  if (compl_match_array == NULL) {
   2328    compl_enter_selects = false;
   2329  } else if (ins_compl_has_preinsert() && compl_leader.size > 0) {
   2330    ins_compl_insert(true, false);
   2331  } else if (compl_started && ins_compl_preinsert_longest()
   2332             && compl_leader.size > 0 && !ins_compl_preinsert_effect()) {
   2333    ins_compl_insert(true, true);
   2334  }
   2335  // Don't let Enter select when use user function and refresh_always is set
   2336  if (ins_compl_refresh_always()) {
   2337    compl_enter_selects = false;
   2338  }
   2339 }
   2340 
   2341 /// Return the length of the completion, from the completion start column to
   2342 /// the cursor column.  Making sure it never goes below zero.
   2343 static int get_compl_len(void)
   2344 {
   2345  int off = (int)curwin->w_cursor.col - (int)compl_col;
   2346  return MAX(0, off);
   2347 }
   2348 
   2349 /// Append one character to the match leader.  May reduce the number of
   2350 /// matches.
   2351 void ins_compl_addleader(int c)
   2352 {
   2353  int cc;
   2354 
   2355  if (ins_compl_preinsert_effect()) {
   2356    ins_compl_delete(false);
   2357  }
   2358 
   2359  if (stop_arrow() == FAIL) {
   2360    return;
   2361  }
   2362  if ((cc = utf_char2len(c)) > 1) {
   2363    char buf[MB_MAXCHAR + 1];
   2364 
   2365    utf_char2bytes(c, buf);
   2366    buf[cc] = NUL;
   2367    ins_char_bytes(buf, (size_t)cc);
   2368  } else {
   2369    ins_char(c);
   2370  }
   2371 
   2372  // If we didn't complete finding matches we must search again.
   2373  if (ins_compl_need_restart()) {
   2374    ins_compl_restart();
   2375  }
   2376 
   2377  API_CLEAR_STRING(compl_leader);
   2378  compl_leader = cbuf_to_string(get_cursor_line_ptr() + compl_col,
   2379                                (size_t)(curwin->w_cursor.col - compl_col));
   2380  ins_compl_new_leader();
   2381 }
   2382 
   2383 /// Setup for finding completions again without leaving CTRL-X mode.  Used when
   2384 /// BS or a key was typed while still searching for matches.
   2385 static void ins_compl_restart(void)
   2386 {
   2387  // update screen before restart.
   2388  // so if complete is blocked,
   2389  // will stay to the last popup menu and reduce flicker
   2390  update_screen();  // TODO(bfredl): no.
   2391  ins_compl_free();
   2392  compl_started = false;
   2393  compl_matches = 0;
   2394  compl_cont_status = 0;
   2395  compl_cont_mode = 0;
   2396  cpt_sources_clear();
   2397  compl_autocomplete = false;
   2398  compl_from_nonkeyword = false;
   2399  compl_num_bests = 0;
   2400 }
   2401 
   2402 /// Set the first match, the original text.
   2403 static void ins_compl_set_original_text(char *str, size_t len)
   2404  FUNC_ATTR_NONNULL_ALL
   2405 {
   2406  // Replace the original text entry.
   2407  // The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
   2408  // be at the last item for backward completion
   2409  if (match_at_original_text(compl_first_match)) {  // safety check
   2410    API_CLEAR_STRING(compl_first_match->cp_str);
   2411    compl_first_match->cp_str = cbuf_to_string(str, len);
   2412  } else if (compl_first_match->cp_prev != NULL
   2413             && match_at_original_text(compl_first_match->cp_prev)) {
   2414    API_CLEAR_STRING(compl_first_match->cp_prev->cp_str);
   2415    compl_first_match->cp_prev->cp_str = cbuf_to_string(str, len);
   2416  }
   2417 }
   2418 
   2419 /// Append one character to the match leader.  May reduce the number of
   2420 /// matches.
   2421 void ins_compl_addfrommatch(void)
   2422 {
   2423  int len = (int)curwin->w_cursor.col - (int)compl_col;
   2424  assert(compl_shown_match != NULL);
   2425  char *p = compl_shown_match->cp_str.data;
   2426  if ((int)compl_shown_match->cp_str.size <= len) {   // the match is too short
   2427    // When still at the original match use the first entry that matches
   2428    // the leader.
   2429    if (!match_at_original_text(compl_shown_match)) {
   2430      return;
   2431    }
   2432 
   2433    p = NULL;
   2434    size_t plen = 0;
   2435    for (compl_T *cp = compl_shown_match->cp_next; cp != NULL
   2436         && !is_first_match(cp); cp = cp->cp_next) {
   2437      if (compl_leader.data == NULL
   2438          || ins_compl_equal(cp, compl_leader.data, compl_leader.size)) {
   2439        p = cp->cp_str.data;
   2440        plen = cp->cp_str.size;
   2441        break;
   2442      }
   2443    }
   2444    if (p == NULL || (int)plen <= len) {
   2445      return;
   2446    }
   2447  }
   2448  p += len;
   2449  int c = utf_ptr2char(p);
   2450  ins_compl_addleader(c);
   2451 }
   2452 
   2453 /// Set the CTRL-X completion mode based on the key "c" typed after a CTRL-X.
   2454 /// Uses the global variables: ctrl_x_mode, edit_submode, edit_submode_pre,
   2455 /// compl_cont_mode and compl_cont_status.
   2456 ///
   2457 /// @return  true when the character is not to be inserted.
   2458 static bool set_ctrl_x_mode(const int c)
   2459 {
   2460  bool retval = false;
   2461 
   2462  switch (c) {
   2463  case Ctrl_E:
   2464  case Ctrl_Y:
   2465    // scroll the window one line up or down
   2466    ctrl_x_mode = CTRL_X_SCROLL;
   2467    if (!(State & REPLACE_FLAG)) {
   2468      edit_submode = _(" (insert) Scroll (^E/^Y)");
   2469    } else {
   2470      edit_submode = _(" (replace) Scroll (^E/^Y)");
   2471    }
   2472    edit_submode_pre = NULL;
   2473    redraw_mode = true;
   2474    break;
   2475  case Ctrl_L:
   2476    // complete whole line
   2477    ctrl_x_mode = CTRL_X_WHOLE_LINE;
   2478    break;
   2479  case Ctrl_F:
   2480    // complete filenames
   2481    ctrl_x_mode = CTRL_X_FILES;
   2482    break;
   2483  case Ctrl_K:
   2484    // complete words from a dictionary
   2485    ctrl_x_mode = CTRL_X_DICTIONARY;
   2486    break;
   2487  case Ctrl_R:
   2488    // When CTRL-R is followed by '=', don't trigger register completion
   2489    // This allows expressions like <C-R>=func()<CR> to work normally
   2490    if (vpeekc() == '=') {
   2491      break;
   2492    }
   2493    ctrl_x_mode = CTRL_X_REGISTER;
   2494    break;
   2495  case Ctrl_T:
   2496    // complete words from a thesaurus
   2497    ctrl_x_mode = CTRL_X_THESAURUS;
   2498    break;
   2499  case Ctrl_U:
   2500    // user defined completion
   2501    ctrl_x_mode = CTRL_X_FUNCTION;
   2502    break;
   2503  case Ctrl_O:
   2504    // omni completion
   2505    ctrl_x_mode = CTRL_X_OMNI;
   2506    break;
   2507  case 's':
   2508  case Ctrl_S:
   2509    // complete spelling suggestions
   2510    ctrl_x_mode = CTRL_X_SPELL;
   2511    emsg_off++;  // Avoid getting the E756 error twice.
   2512    spell_back_to_badword();
   2513    emsg_off--;
   2514    break;
   2515  case Ctrl_RSB:
   2516    // complete tag names
   2517    ctrl_x_mode = CTRL_X_TAGS;
   2518    break;
   2519  case Ctrl_I:
   2520  case K_S_TAB:
   2521    // complete keywords from included files
   2522    ctrl_x_mode = CTRL_X_PATH_PATTERNS;
   2523    break;
   2524  case Ctrl_D:
   2525    // complete definitions from included files
   2526    ctrl_x_mode = CTRL_X_PATH_DEFINES;
   2527    break;
   2528  case Ctrl_V:
   2529  case Ctrl_Q:
   2530    // complete vim commands
   2531    ctrl_x_mode = CTRL_X_CMDLINE;
   2532    break;
   2533  case Ctrl_Z:
   2534    // stop completion
   2535    ctrl_x_mode = CTRL_X_NORMAL;
   2536    edit_submode = NULL;
   2537    redraw_mode = true;
   2538    retval = true;
   2539    break;
   2540  case Ctrl_P:
   2541  case Ctrl_N:
   2542    // ^X^P means LOCAL expansion if nothing interrupted (eg we
   2543    // just started ^X mode, or there were enough ^X's to cancel
   2544    // the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
   2545    // do normal expansion when interrupting a different mode (say
   2546    // ^X^F^X^P or ^P^X^X^P, see below)
   2547    // nothing changes if interrupting mode 0, (eg, the flag
   2548    // doesn't change when going to ADDING mode  -- Acevedo
   2549    if (!(compl_cont_status & CONT_INTRPT)) {
   2550      compl_cont_status |= CONT_LOCAL;
   2551    } else if (compl_cont_mode != 0) {
   2552      compl_cont_status &= ~CONT_LOCAL;
   2553    }
   2554    FALLTHROUGH;
   2555  default:
   2556    // If we have typed at least 2 ^X's... for modes != 0, we set
   2557    // compl_cont_status = 0 (eg, as if we had just started ^X
   2558    // mode).
   2559    // For mode 0, we set "compl_cont_mode" to an impossible
   2560    // value, in both cases ^X^X can be used to restart the same
   2561    // mode (avoiding ADDING mode).
   2562    // Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
   2563    // 'complete' and local ^P expansions respectively.
   2564    // In mode 0 an extra ^X is needed since ^X^P goes to ADDING
   2565    // mode  -- Acevedo
   2566    if (c == Ctrl_X) {
   2567      if (compl_cont_mode != 0) {
   2568        compl_cont_status = 0;
   2569      } else {
   2570        compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
   2571      }
   2572    }
   2573    ctrl_x_mode = CTRL_X_NORMAL;
   2574    edit_submode = NULL;
   2575    redraw_mode = true;
   2576    break;
   2577  }
   2578 
   2579  return retval;
   2580 }
   2581 
   2582 /// Stop insert completion mode
   2583 static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
   2584 {
   2585  // Remove pre-inserted text when present.
   2586  if (ins_compl_preinsert_effect() && ins_compl_win_active(curwin)) {
   2587    ins_compl_delete(false);
   2588  }
   2589 
   2590  // Get here when we have finished typing a sequence of ^N and
   2591  // ^P or other completion characters in CTRL-X mode.  Free up
   2592  // memory that was used, and make sure we can redo the insert.
   2593  if (compl_curr_match != NULL || compl_leader.data != NULL || c == Ctrl_E) {
   2594    // If any of the original typed text has been changed, eg when
   2595    // ignorecase is set, we must add back-spaces to the redo
   2596    // buffer.  We add as few as necessary to delete just the part
   2597    // of the original text that has changed.
   2598    // When using the longest match, edited the match or used
   2599    // CTRL-E then don't use the current match.
   2600    char *ptr = NULL;
   2601    if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) {
   2602      ptr = compl_curr_match->cp_str.data;
   2603    }
   2604    ins_compl_fixRedoBufForLeader(ptr);
   2605  }
   2606 
   2607  bool want_cindent = (get_can_cindent() && cindent_on());
   2608 
   2609  // When completing whole lines: fix indent for 'cindent'.
   2610  // Otherwise, break line if it's too long.
   2611  if (compl_cont_mode == CTRL_X_WHOLE_LINE) {
   2612    // re-indent the current line
   2613    if (want_cindent) {
   2614      do_c_expr_indent();
   2615      want_cindent = false;                 // don't do it again
   2616    }
   2617  } else {
   2618    const int prev_col = curwin->w_cursor.col;
   2619 
   2620    // put the cursor on the last char, for 'tw' formatting
   2621    if (prev_col > 0) {
   2622      dec_cursor();
   2623    }
   2624 
   2625    // only format when something was inserted
   2626    if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E) {
   2627      insertchar(NUL, 0, -1);
   2628    }
   2629 
   2630    if (prev_col > 0
   2631        && get_cursor_line_ptr()[curwin->w_cursor.col] != NUL) {
   2632      inc_cursor();
   2633    }
   2634  }
   2635 
   2636  char *word = NULL;
   2637  // If the popup menu is displayed pressing CTRL-Y means accepting
   2638  // the selection without inserting anything.  When
   2639  // compl_enter_selects is set the Enter key does the same.
   2640  if ((c == Ctrl_Y || (compl_enter_selects
   2641                       && (c == CAR || c == K_KENTER || c == NL)))
   2642      && pum_visible()) {
   2643    word = xstrdup(compl_shown_match->cp_str.data);
   2644    retval = true;
   2645    // May need to remove ComplMatchIns highlight.
   2646    redrawWinline(curwin, curwin->w_cursor.lnum);
   2647  }
   2648 
   2649  // CTRL-E means completion is Ended, go back to the typed text.
   2650  // but only do this, if the Popup is still visible
   2651  if (c == Ctrl_E) {
   2652    ins_compl_delete(false);
   2653    char *p = NULL;
   2654    size_t plen = 0;
   2655    if (compl_leader.data != NULL) {
   2656      p = compl_leader.data;
   2657      plen = compl_leader.size;
   2658    } else if (compl_first_match != NULL) {
   2659      p = compl_orig_text.data;
   2660      plen = compl_orig_text.size;
   2661    }
   2662    if (p != NULL) {
   2663      const int compl_len = get_compl_len();
   2664      if ((int)plen > compl_len) {
   2665        ins_compl_insert_bytes(p + compl_len, (int)plen - compl_len);
   2666      }
   2667    }
   2668    restore_orig_extmarks();
   2669    retval = true;
   2670  }
   2671 
   2672  auto_format(false, true);
   2673 
   2674  // Trigger the CompleteDonePre event to give scripts a chance to
   2675  // act upon the completion before clearing the info, and restore
   2676  // ctrl_x_mode, so that complete_info() can be used.
   2677  ctrl_x_mode = prev_mode;
   2678  ins_apply_autocmds(EVENT_COMPLETEDONEPRE);
   2679 
   2680  ins_compl_free();
   2681  compl_started = false;
   2682  compl_matches = 0;
   2683  if (!shortmess(SHM_COMPLETIONMENU)) {
   2684    msg_clr_cmdline();  // necessary for "noshowmode"
   2685  }
   2686  ctrl_x_mode = CTRL_X_NORMAL;
   2687  compl_enter_selects = false;
   2688  if (edit_submode != NULL) {
   2689    edit_submode = NULL;
   2690    redraw_mode = true;
   2691  }
   2692  compl_autocomplete = false;
   2693  compl_from_nonkeyword = false;
   2694  compl_best_matches = 0;
   2695  compl_ins_end_col = 0;
   2696 
   2697  if (c == Ctrl_C && cmdwin_type != 0) {
   2698    // Avoid the popup menu remains displayed when leaving the
   2699    // command line window.
   2700    update_screen();
   2701  }
   2702 
   2703  // Indent now if a key was typed that is in 'cinkeys'.
   2704  if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) {
   2705    do_c_expr_indent();
   2706  }
   2707  // Trigger the CompleteDone event to give scripts a chance to act
   2708  // upon the end of completion.
   2709  do_autocmd_completedone(c, prev_mode, word);
   2710  xfree(word);
   2711 
   2712  return retval;
   2713 }
   2714 
   2715 /// Cancel completion.
   2716 bool ins_compl_cancel(void)
   2717 {
   2718  return ins_compl_stop(' ', ctrl_x_mode, true);
   2719 }
   2720 
   2721 /// Prepare for Insert mode completion, or stop it.
   2722 /// Called just after typing a character in Insert mode.
   2723 ///
   2724 /// @param  c  character that was typed
   2725 ///
   2726 /// @return true when the character is not to be inserted;
   2727 bool ins_compl_prep(int c)
   2728 {
   2729  bool retval = false;
   2730  const int prev_mode = ctrl_x_mode;
   2731 
   2732  // Forget any previous 'special' messages if this is actually
   2733  // a ^X mode key - bar ^R, in which case we wait to see what it gives us.
   2734  if (c != Ctrl_R && vim_is_ctrl_x_key(c)) {
   2735    edit_submode_extra = NULL;
   2736  }
   2737 
   2738  // Ignore end of Select mode mapping and mouse scroll/movement.
   2739  if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
   2740      || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_MOUSEMOVE
   2741      || c == K_EVENT || c == K_COMMAND || c == K_LUA) {
   2742    return retval;
   2743  }
   2744 
   2745  if (ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X && c != Ctrl_X) {
   2746    if (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_Z || ins_compl_pum_key(c)
   2747        || !vim_is_ctrl_x_key(c)) {
   2748      // Not starting another completion mode.
   2749      ctrl_x_mode = CTRL_X_CMDLINE;
   2750 
   2751      // CTRL-X CTRL-Z should stop completion without inserting anything
   2752      if (c == Ctrl_Z) {
   2753        retval = true;
   2754      }
   2755    } else {
   2756      ctrl_x_mode = CTRL_X_CMDLINE;
   2757 
   2758      // Other CTRL-X keys first stop completion, then start another
   2759      // completion mode.
   2760      ins_compl_prep(' ');
   2761      ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
   2762    }
   2763  }
   2764 
   2765  // Set "compl_get_longest" when finding the first matches.
   2766  if (ctrl_x_mode_not_defined_yet()
   2767      || (ctrl_x_mode_normal() && !compl_started)) {
   2768    compl_get_longest = (get_cot_flags() & kOptCotFlagLongest) != 0;
   2769    compl_used_match = true;
   2770  }
   2771 
   2772  if (ctrl_x_mode_not_defined_yet()) {
   2773    // We have just typed CTRL-X and aren't quite sure which CTRL-X mode
   2774    // it will be yet.  Now we decide.
   2775    retval = set_ctrl_x_mode(c);
   2776  } else if (ctrl_x_mode_not_default()) {
   2777    // We're already in CTRL-X mode, do we stay in it?
   2778    if (!vim_is_ctrl_x_key(c)) {
   2779      ctrl_x_mode = ctrl_x_mode_scroll() ? CTRL_X_NORMAL : CTRL_X_FINISHED;
   2780      edit_submode = NULL;
   2781    }
   2782    redraw_mode = true;
   2783  }
   2784 
   2785  if (compl_started || ctrl_x_mode == CTRL_X_FINISHED) {
   2786    // Show error message from attempted keyword completion (probably
   2787    // 'Pattern not found') until another key is hit, then go back to
   2788    // showing what mode we are in.
   2789    redraw_mode = true;
   2790    if ((ctrl_x_mode_normal()
   2791         && c != Ctrl_N
   2792         && c != Ctrl_P
   2793         && c != Ctrl_R
   2794         && !ins_compl_pum_key(c))
   2795        || ctrl_x_mode == CTRL_X_FINISHED) {
   2796      retval = ins_compl_stop(c, prev_mode, retval);
   2797    }
   2798  } else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) {
   2799    // Trigger the CompleteDone event to give scripts a chance to act
   2800    // upon the (possibly failed) completion.
   2801    do_autocmd_completedone(c, ctrl_x_mode, NULL);
   2802  }
   2803 
   2804  may_trigger_modechanged();
   2805 
   2806  // reset continue_* if we left expansion-mode, if we stay they'll be
   2807  // (re)set properly in ins_complete()
   2808  if (!vim_is_ctrl_x_key(c)) {
   2809    compl_cont_status = 0;
   2810    compl_cont_mode = 0;
   2811  }
   2812 
   2813  return retval;
   2814 }
   2815 
   2816 /// Fix the redo buffer for the completion leader replacing some of the typed
   2817 /// text.  This inserts backspaces and appends the changed text.
   2818 /// "ptr" is the known leader text or NUL.
   2819 static void ins_compl_fixRedoBufForLeader(char *ptr_arg)
   2820 {
   2821  int len = 0;
   2822  char *ptr = ptr_arg;
   2823 
   2824  if (ptr == NULL) {
   2825    if (compl_leader.data != NULL) {
   2826      ptr = compl_leader.data;
   2827    } else {
   2828      return;        // nothing to do
   2829    }
   2830  }
   2831  if (compl_orig_text.data != NULL) {
   2832    char *p = compl_orig_text.data;
   2833    // Find length of common prefix between original text and new completion
   2834    while (p[len] != NUL && p[len] == ptr[len]) {
   2835      len++;
   2836    }
   2837    // Adjust length to not break inside a multi-byte character
   2838    if (len > 0) {
   2839      len -= utf_head_off(p, p + len);
   2840    }
   2841    // Add backspace characters for each remaining character in original text
   2842    for (p += len; *p != NUL; MB_PTR_ADV(p)) {
   2843      AppendCharToRedobuff(K_BS);
   2844    }
   2845  }
   2846  AppendToRedobuffLit(ptr + len, -1);
   2847 }
   2848 
   2849 /// Loops through the list of windows, loaded-buffers or non-loaded-buffers
   2850 /// (depending on flag) starting from buf and looking for a non-scanned
   2851 /// buffer (other than curbuf).  curbuf is special, if it is called with
   2852 /// buf=curbuf then it has to be the first call for a given flag/expansion.
   2853 ///
   2854 /// Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
   2855 static buf_T *ins_compl_next_buf(buf_T *buf, int flag)
   2856 {
   2857  static win_T *wp = NULL;
   2858 
   2859  if (flag == 'w') {            // just windows
   2860    if (buf == curbuf || !win_valid(wp)) {
   2861      // first call for this flag/expansion or window was closed
   2862      wp = curwin;
   2863    }
   2864 
   2865    assert(wp);
   2866    while (true) {
   2867      // Move to next window (wrap to first window if at the end)
   2868      wp = (wp->w_next != NULL) ? wp->w_next : firstwin;
   2869      // Break if we're back at start or found an unscanned buffer (in a focusable window)
   2870      if (wp == curwin || (!wp->w_buffer->b_scanned && wp->w_config.focusable)) {
   2871        break;
   2872      }
   2873    }
   2874    buf = wp->w_buffer;
   2875  } else {
   2876    // 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
   2877    // (unlisted buffers)
   2878    // When completing whole lines skip unloaded buffers.
   2879    while (true) {
   2880      // Move to next buffer (wrap to first buffer if at the end)
   2881      buf = (buf->b_next != NULL) ? buf->b_next : firstbuf;
   2882      // Break if we're back at start buffer
   2883      if (buf == curbuf) {
   2884        break;
   2885      }
   2886 
   2887      bool skip_buffer;
   2888      // Check buffer conditions based on flag
   2889      if (flag == 'U') {
   2890        skip_buffer = buf->b_p_bl;
   2891      } else {
   2892        skip_buffer = !buf->b_p_bl || (buf->b_ml.ml_mfp == NULL) != (flag == 'u');
   2893      }
   2894 
   2895      // Break if we found a buffer that matches our criteria
   2896      if (!skip_buffer && !buf->b_scanned) {
   2897        break;
   2898      }
   2899    }
   2900  }
   2901  return buf;
   2902 }
   2903 
   2904 /// Count the number of entries in the 'complete' option (curbuf->b_p_cpt).
   2905 /// Each non-empty, comma-separated segment is counted as one entry.
   2906 static int get_cpt_sources_count(void)
   2907 {
   2908  char dummy[LSIZE];
   2909  int count = 0;
   2910 
   2911  for (char *p = curbuf->b_p_cpt; *p != NUL;) {
   2912    while (*p == ',' || *p == ' ') {
   2913      p++;  // Skip delimiters
   2914    }
   2915    if (*p != NUL) {
   2916      (void)copy_option_part(&p, dummy, LSIZE, ",");  // Advance p
   2917      count++;
   2918    }
   2919  }
   2920 
   2921  return count;
   2922 }
   2923 
   2924 static Callback cfu_cb;    ///< 'completefunc' callback function
   2925 static Callback ofu_cb;    ///< 'omnifunc' callback function
   2926 static Callback tsrfu_cb;  ///< 'thesaurusfunc' callback function
   2927 static Callback *cpt_cb;   ///< Callback functions associated with F{func}
   2928 static int cpt_cb_count;   ///< Number of cpt callbacks
   2929 
   2930 /// Copy a global callback function to a buffer local callback.
   2931 static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
   2932 {
   2933  callback_free(bufcb);
   2934  if (globcb->type != kCallbackNone) {
   2935    callback_copy(bufcb, globcb);
   2936  }
   2937 }
   2938 
   2939 /// Parse the 'completefunc' option value and set the callback function.
   2940 /// Invoked when the 'completefunc' option is set. The option value can be a
   2941 /// name of a function (string), or function(<name>) or funcref(<name>) or a
   2942 /// lambda expression.
   2943 const char *did_set_completefunc(optset_T *args)
   2944 {
   2945  buf_T *buf = (buf_T *)args->os_buf;
   2946  int retval;
   2947 
   2948  if (args->os_flags & OPT_LOCAL) {
   2949    retval = option_set_callback_func(args->os_newval.string.data, &buf->b_cfu_cb);
   2950  } else {
   2951    retval = option_set_callback_func(args->os_newval.string.data, &cfu_cb);
   2952    if (retval == OK && !(args->os_flags & OPT_GLOBAL)) {
   2953      set_buflocal_cfu_callback(buf);
   2954    }
   2955  }
   2956 
   2957  return retval == FAIL ? e_invarg : NULL;
   2958 }
   2959 
   2960 /// Copy the global 'completefunc' callback function to the buffer-local
   2961 /// 'completefunc' callback for "buf".
   2962 void set_buflocal_cfu_callback(buf_T *buf)
   2963 {
   2964  copy_global_to_buflocal_cb(&cfu_cb, &buf->b_cfu_cb);
   2965 }
   2966 
   2967 /// Parse the 'omnifunc' option value and set the callback function.
   2968 /// Invoked when the 'omnifunc' option is set. The option value can be a
   2969 /// name of a function (string), or function(<name>) or funcref(<name>) or a
   2970 /// lambda expression.
   2971 const char *did_set_omnifunc(optset_T *args)
   2972 {
   2973  buf_T *buf = (buf_T *)args->os_buf;
   2974  int retval;
   2975 
   2976  if (args->os_flags & OPT_LOCAL) {
   2977    retval = option_set_callback_func(args->os_newval.string.data, &buf->b_ofu_cb);
   2978  } else {
   2979    retval = option_set_callback_func(args->os_newval.string.data, &ofu_cb);
   2980    if (retval == OK && !(args->os_flags & OPT_GLOBAL)) {
   2981      set_buflocal_ofu_callback(buf);
   2982    }
   2983  }
   2984 
   2985  return retval == FAIL ? e_invarg : NULL;
   2986 }
   2987 
   2988 /// Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
   2989 /// callback for "buf".
   2990 void set_buflocal_ofu_callback(buf_T *buf)
   2991 {
   2992  copy_global_to_buflocal_cb(&ofu_cb, &buf->b_ofu_cb);
   2993 }
   2994 
   2995 /// Free an array of 'complete' F{func} callbacks and set the pointer to NULL.
   2996 void clear_cpt_callbacks(Callback **callbacks, int count)
   2997 {
   2998  if (callbacks == NULL || *callbacks == NULL) {
   2999    return;
   3000  }
   3001 
   3002  for (int i = 0; i < count; i++) {
   3003    callback_free(&(*callbacks)[i]);
   3004  }
   3005 
   3006  XFREE_CLEAR(*callbacks);
   3007 }
   3008 
   3009 /// Copies a list of Callback structs from src to *dest, clearing any existing
   3010 /// entries and allocating memory for the destination.
   3011 static void copy_cpt_callbacks(Callback **dest, int *dest_cnt, Callback *src, int cnt)
   3012 {
   3013  if (cnt == 0) {
   3014    return;
   3015  }
   3016 
   3017  clear_cpt_callbacks(dest, *dest_cnt);
   3018  *dest = xcalloc((size_t)cnt, sizeof(Callback));
   3019  *dest_cnt = cnt;
   3020 
   3021  for (int i = 0; i < cnt; i++) {
   3022    if (src[i].type != kCallbackNone) {
   3023      callback_copy(&(*dest)[i], &src[i]);
   3024    }
   3025  }
   3026 }
   3027 
   3028 /// Copy global 'complete' F{func} callbacks into the given buffer's local
   3029 /// callback array. Clears any existing buffer-local callbacks first.
   3030 void set_buflocal_cpt_callbacks(buf_T *buf)
   3031 {
   3032  if (buf == NULL || cpt_cb_count == 0) {
   3033    return;
   3034  }
   3035  copy_cpt_callbacks(&buf->b_p_cpt_cb, &buf->b_p_cpt_count, cpt_cb, cpt_cb_count);
   3036 }
   3037 
   3038 /// Parse 'complete' option and initialize F{func} callbacks.
   3039 /// Frees any existing callbacks and allocates new ones.
   3040 /// Only F{func} entries are processed; others are ignored.
   3041 int set_cpt_callbacks(optset_T *args)
   3042 {
   3043  bool local = (args->os_flags & OPT_LOCAL) != 0;
   3044 
   3045  if (curbuf == NULL) {
   3046    return FAIL;
   3047  }
   3048 
   3049  clear_cpt_callbacks(&curbuf->b_p_cpt_cb, curbuf->b_p_cpt_count);
   3050  curbuf->b_p_cpt_count = 0;
   3051 
   3052  int count = get_cpt_sources_count();
   3053  if (count == 0) {
   3054    return OK;
   3055  }
   3056 
   3057  curbuf->b_p_cpt_cb = xcalloc((size_t)count, sizeof(Callback));
   3058  curbuf->b_p_cpt_count = count;
   3059 
   3060  char buf[LSIZE];
   3061  int idx = 0;
   3062  for (char *p = curbuf->b_p_cpt; *p != NUL;) {
   3063    while (*p == ',' || *p == ' ') {
   3064      p++;  // Skip delimiters
   3065    }
   3066    if (*p != NUL) {
   3067      size_t slen = copy_option_part(&p, buf, LSIZE, ",");  // Advance p
   3068      if (slen > 0 && buf[0] == 'F' && buf[1] != NUL) {
   3069        char *caret = vim_strchr(buf, '^');
   3070        if (caret != NULL) {
   3071          *caret = NUL;
   3072        }
   3073        if (option_set_callback_func(buf + 1, &curbuf->b_p_cpt_cb[idx]) != OK) {
   3074          curbuf->b_p_cpt_cb[idx].type = kCallbackNone;
   3075        }
   3076      }
   3077      idx++;
   3078    }
   3079  }
   3080 
   3081  if (!local) {  // ':set' used instead of ':setlocal'
   3082    // Cache the callback array
   3083    copy_cpt_callbacks(&cpt_cb, &cpt_cb_count, curbuf->b_p_cpt_cb,
   3084                       curbuf->b_p_cpt_count);
   3085  }
   3086 
   3087  return OK;
   3088 }
   3089 
   3090 /// Parse the 'thesaurusfunc' option value and set the callback function.
   3091 /// Invoked when the 'thesaurusfunc' option is set. The option value can be a
   3092 /// name of a function (string), or function(<name>) or funcref(<name>) or a
   3093 /// lambda expression.
   3094 const char *did_set_thesaurusfunc(optset_T *args FUNC_ATTR_UNUSED)
   3095 {
   3096  buf_T *buf = (buf_T *)args->os_buf;
   3097  int retval;
   3098 
   3099  if (args->os_flags & OPT_LOCAL) {
   3100    // buffer-local option set
   3101    retval = option_set_callback_func(buf->b_p_tsrfu, &buf->b_tsrfu_cb);
   3102  } else {
   3103    // global option set
   3104    retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
   3105    // when using :set, free the local callback
   3106    if (!(args->os_flags & OPT_GLOBAL)) {
   3107      callback_free(&buf->b_tsrfu_cb);
   3108    }
   3109  }
   3110 
   3111  return retval == FAIL ? e_invarg : NULL;
   3112 }
   3113 
   3114 /// Mark "copyID" references in an array of F{func} callbacks so that they are
   3115 /// not garbage collected.
   3116 bool set_ref_in_cpt_callbacks(Callback *callbacks, int count, int copyID)
   3117 {
   3118  bool abort = false;
   3119 
   3120  if (callbacks == NULL) {
   3121    return false;
   3122  }
   3123 
   3124  for (int i = 0; i < count; i++) {
   3125    abort = abort || set_ref_in_callback(&callbacks[i], copyID, NULL, NULL);
   3126  }
   3127  return abort;
   3128 }
   3129 
   3130 /// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
   3131 /// "copyID" so that they are not garbage collected.
   3132 bool set_ref_in_insexpand_funcs(int copyID)
   3133 {
   3134  bool abort = set_ref_in_callback(&cfu_cb, copyID, NULL, NULL);
   3135  abort = abort || set_ref_in_callback(&ofu_cb, copyID, NULL, NULL);
   3136  abort = abort || set_ref_in_callback(&tsrfu_cb, copyID, NULL, NULL);
   3137  abort = abort || set_ref_in_cpt_callbacks(cpt_cb, cpt_cb_count, copyID);
   3138 
   3139  return abort;
   3140 }
   3141 
   3142 /// Get the user-defined completion function name for completion "type"
   3143 static char *get_complete_funcname(int type)
   3144 {
   3145  switch (type) {
   3146  case CTRL_X_FUNCTION:
   3147    return curbuf->b_p_cfu;
   3148  case CTRL_X_OMNI:
   3149    return curbuf->b_p_ofu;
   3150  case CTRL_X_THESAURUS:
   3151    return *curbuf->b_p_tsrfu == NUL ? p_tsrfu : curbuf->b_p_tsrfu;
   3152  default:
   3153    return "";
   3154  }
   3155 }
   3156 
   3157 /// Get the callback to use for insert mode completion.
   3158 static Callback *get_insert_callback(int type)
   3159 {
   3160  if (type == CTRL_X_FUNCTION) {
   3161    return &curbuf->b_cfu_cb;
   3162  }
   3163  if (type == CTRL_X_OMNI) {
   3164    return &curbuf->b_ofu_cb;
   3165  }
   3166  // CTRL_X_THESAURUS
   3167  return (*curbuf->b_p_tsrfu != NUL) ? &curbuf->b_tsrfu_cb : &tsrfu_cb;
   3168 }
   3169 
   3170 /// Execute user defined complete function 'completefunc', 'omnifunc' or
   3171 /// 'thesaurusfunc', and get matches in "matches".
   3172 ///
   3173 /// @param type  one of CTRL_X_OMNI or CTRL_X_FUNCTION or CTRL_X_THESAURUS
   3174 /// @param cb    set if triggered by a function in 'cpt' option, otherwise NULL
   3175 static void expand_by_function(int type, char *base, Callback *cb)
   3176 {
   3177  list_T *matchlist = NULL;
   3178  dict_T *matchdict = NULL;
   3179  typval_T rettv;
   3180  const int save_State = State;
   3181 
   3182  assert(curbuf != NULL);
   3183 
   3184  const bool is_cpt_function = (cb != NULL);
   3185  if (!is_cpt_function) {
   3186    char *funcname = get_complete_funcname(type);
   3187    if (*funcname == NUL) {
   3188      return;
   3189    }
   3190    cb = get_insert_callback(type);
   3191  }
   3192 
   3193  // Call 'completefunc' to obtain the list of matches.
   3194  typval_T args[3];
   3195  args[0].v_type = VAR_NUMBER;
   3196  args[1].v_type = VAR_STRING;
   3197  args[2].v_type = VAR_UNKNOWN;
   3198  args[0].vval.v_number = 0;
   3199  args[1].vval.v_string = base != NULL ? base : "";
   3200 
   3201  pos_T pos = curwin->w_cursor;
   3202  // Lock the text to avoid weird things from happening.  Also disallow
   3203  // switching to another window, it should not be needed and may end up in
   3204  // Insert mode in another buffer.
   3205  textlock++;
   3206 
   3207  // Call a function, which returns a list or dict.
   3208  if (callback_call(cb, 2, args, &rettv)) {
   3209    switch (rettv.v_type) {
   3210    case VAR_LIST:
   3211      matchlist = rettv.vval.v_list;
   3212      break;
   3213    case VAR_DICT:
   3214      matchdict = rettv.vval.v_dict;
   3215      break;
   3216    case VAR_SPECIAL:
   3217      FALLTHROUGH;
   3218    default:
   3219      // TODO(brammool): Give error message?
   3220      tv_clear(&rettv);
   3221      break;
   3222    }
   3223  }
   3224  textlock--;
   3225 
   3226  curwin->w_cursor = pos;  // restore the cursor position
   3227  check_cursor(curwin);  // make sure cursor position is valid, just in case
   3228  validate_cursor(curwin);
   3229  if (!equalpos(curwin->w_cursor, pos)) {
   3230    emsg(_(e_compldel));
   3231    goto theend;
   3232  }
   3233 
   3234  if (matchlist != NULL) {
   3235    ins_compl_add_list(matchlist);
   3236  } else if (matchdict != NULL) {
   3237    ins_compl_add_dict(matchdict);
   3238  }
   3239 
   3240 theend:
   3241  // Restore State, it might have been changed.
   3242  State = save_State;
   3243 
   3244  if (matchdict != NULL) {
   3245    tv_dict_unref(matchdict);
   3246  }
   3247  if (matchlist != NULL) {
   3248    tv_list_unref(matchlist);
   3249  }
   3250 }
   3251 
   3252 static inline int get_user_highlight_attr(const char *hlname)
   3253 {
   3254  if (hlname != NULL && *hlname != NUL) {
   3255    return syn_name2attr(hlname);
   3256  }
   3257  return -1;
   3258 }
   3259 
   3260 /// Add a match to the list of matches from Vimscript object
   3261 ///
   3262 /// @param[in]  tv  Object to get matches from.
   3263 /// @param[in]  dir  Completion direction.
   3264 /// @param[in]  fast  use fast_breakcheck() instead of os_breakcheck().
   3265 ///
   3266 /// @return NOTDONE if the given string is already in the list of completions,
   3267 ///         otherwise it is added to the list and  OK is returned. FAIL will be
   3268 ///         returned in case of error.
   3269 static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
   3270  FUNC_ATTR_NONNULL_ALL
   3271 {
   3272  const char *word;
   3273  bool dup = false;
   3274  bool empty = false;
   3275  int flags = fast ? CP_FAST : 0;
   3276  char *(cptext[CPT_COUNT]);
   3277  char *user_abbr_hlname = NULL;
   3278  char *user_kind_hlname = NULL;
   3279  int user_hl[2] = { -1, -1 };
   3280  typval_T user_data;
   3281 
   3282  user_data.v_type = VAR_UNKNOWN;
   3283  if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
   3284    word = tv_dict_get_string(tv->vval.v_dict, "word", false);
   3285    cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true);
   3286    cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true);
   3287    cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true);
   3288    cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
   3289 
   3290    user_abbr_hlname = tv_dict_get_string(tv->vval.v_dict, "abbr_hlgroup", false);
   3291    user_hl[0] = get_user_highlight_attr(user_abbr_hlname);
   3292 
   3293    user_kind_hlname = tv_dict_get_string(tv->vval.v_dict, "kind_hlgroup", false);
   3294    user_hl[1] = get_user_highlight_attr(user_kind_hlname);
   3295 
   3296    tv_dict_get_tv(tv->vval.v_dict, "user_data", &user_data);
   3297 
   3298    if (tv_dict_get_number(tv->vval.v_dict, "icase")) {
   3299      flags |= CP_ICASE;
   3300    }
   3301    dup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
   3302    empty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
   3303    if (tv_dict_get_string(tv->vval.v_dict, "equal", false) != NULL
   3304        && tv_dict_get_number(tv->vval.v_dict, "equal")) {
   3305      flags |= CP_EQUAL;
   3306    }
   3307  } else {
   3308    word = tv_get_string_chk(tv);
   3309    CLEAR_FIELD(cptext);
   3310  }
   3311  if (word == NULL || (!empty && *word == NUL)) {
   3312    free_cptext(cptext);
   3313    tv_clear(&user_data);
   3314    return FAIL;
   3315  }
   3316  int status = ins_compl_add((char *)word, -1, NULL, cptext, true,
   3317                             &user_data, dir, flags, dup, user_hl, FUZZY_SCORE_NONE);
   3318  if (status != OK) {
   3319    tv_clear(&user_data);
   3320  }
   3321  return status;
   3322 }
   3323 
   3324 /// Add completions from a list.
   3325 static void ins_compl_add_list(list_T *const list)
   3326 {
   3327  Direction dir = compl_direction;
   3328 
   3329  // Go through the List with matches and add each of them.
   3330  TV_LIST_ITER(list, li, {
   3331    if (ins_compl_add_tv(TV_LIST_ITEM_TV(li), dir, true) == OK) {
   3332      // If dir was BACKWARD then honor it just once.
   3333      dir = FORWARD;
   3334    } else if (did_emsg) {
   3335      break;
   3336    }
   3337  });
   3338 }
   3339 
   3340 /// Add completions from a dict.
   3341 static void ins_compl_add_dict(dict_T *dict)
   3342 {
   3343  // Check for optional "refresh" item.
   3344  compl_opt_refresh_always = false;
   3345  dictitem_T *di_refresh = tv_dict_find(dict, S_LEN("refresh"));
   3346  if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
   3347    const char *v = di_refresh->di_tv.vval.v_string;
   3348 
   3349    if (v != NULL && strcmp(v, "always") == 0) {
   3350      compl_opt_refresh_always = true;
   3351    }
   3352  }
   3353 
   3354  // Add completions from a "words" list.
   3355  dictitem_T *di_words = tv_dict_find(dict, S_LEN("words"));
   3356  if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
   3357    ins_compl_add_list(di_words->di_tv.vval.v_list);
   3358  }
   3359 }
   3360 
   3361 /// Save extmarks in "compl_orig_text" so that they may be restored when the
   3362 /// completion is cancelled, or the original text is completed.
   3363 static void save_orig_extmarks(void)
   3364 {
   3365  extmark_splice_delete(curbuf, curwin->w_cursor.lnum - 1, compl_col, curwin->w_cursor.lnum - 1,
   3366                        compl_col + compl_length, &compl_orig_extmarks, true, kExtmarkUndo);
   3367 }
   3368 
   3369 static void restore_orig_extmarks(void)
   3370 {
   3371  for (long i = (int)kv_size(compl_orig_extmarks) - 1; i > -1; i--) {
   3372    ExtmarkUndoObject undo_info = kv_A(compl_orig_extmarks, i);
   3373    extmark_apply_undo(undo_info, true);
   3374  }
   3375 }
   3376 
   3377 /// Start completion for the complete() function.
   3378 ///
   3379 /// @param startcol  where the matched text starts (1 is first column).
   3380 /// @param list      the list of matches.
   3381 static void set_completion(colnr_T startcol, list_T *list)
   3382 {
   3383  int flags = CP_ORIGINAL_TEXT;
   3384  unsigned cur_cot_flags = get_cot_flags();
   3385  bool compl_longest = (cur_cot_flags & kOptCotFlagLongest) != 0;
   3386  bool compl_no_insert = (cur_cot_flags & kOptCotFlagNoinsert) != 0;
   3387  bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0;
   3388 
   3389  // If already doing completions stop it.
   3390  if (ctrl_x_mode_not_default()) {
   3391    ins_compl_prep(' ');
   3392  }
   3393  ins_compl_clear();
   3394  ins_compl_free();
   3395  compl_get_longest = compl_longest;
   3396 
   3397  compl_direction = FORWARD;
   3398  if (startcol > curwin->w_cursor.col) {
   3399    startcol = curwin->w_cursor.col;
   3400  }
   3401  compl_col = startcol;
   3402  compl_lnum = curwin->w_cursor.lnum;
   3403  compl_length = curwin->w_cursor.col - startcol;
   3404  // compl_pattern doesn't need to be set
   3405  compl_orig_text = cbuf_to_string(get_cursor_line_ptr() + compl_col,
   3406                                   (size_t)compl_length);
   3407  save_orig_extmarks();
   3408  if (p_ic) {
   3409    flags |= CP_ICASE;
   3410  }
   3411  if (ins_compl_add(compl_orig_text.data, (int)compl_orig_text.size,
   3412                    NULL, NULL, false, NULL, 0,
   3413                    flags | CP_FAST, false, NULL, FUZZY_SCORE_NONE) != OK) {
   3414    return;
   3415  }
   3416 
   3417  ctrl_x_mode = CTRL_X_EVAL;
   3418 
   3419  ins_compl_add_list(list);
   3420  compl_matches = ins_compl_make_cyclic();
   3421  compl_started = true;
   3422  compl_used_match = true;
   3423  compl_cont_status = 0;
   3424  int save_w_wrow = curwin->w_wrow;
   3425  int save_w_leftcol = curwin->w_leftcol;
   3426 
   3427  compl_curr_match = compl_first_match;
   3428  bool no_select = compl_no_select || compl_longest;
   3429  if (compl_no_insert || no_select) {
   3430    ins_complete(K_DOWN, false);
   3431    if (no_select) {
   3432      ins_complete(K_UP, false);
   3433    }
   3434  } else {
   3435    ins_complete(Ctrl_N, false);
   3436  }
   3437  compl_enter_selects = compl_no_insert;
   3438 
   3439  // Lazily show the popup menu, unless we got interrupted.
   3440  if (!compl_interrupted) {
   3441    show_pum(save_w_wrow, save_w_leftcol);
   3442  }
   3443 
   3444  may_trigger_modechanged();
   3445  ui_flush();
   3446 }
   3447 
   3448 /// "complete()" function
   3449 void f_complete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3450 {
   3451  if ((State & MODE_INSERT) == 0) {
   3452    emsg(_("E785: complete() can only be used in Insert mode"));
   3453    return;
   3454  }
   3455 
   3456  // Check for undo allowed here, because if something was already inserted
   3457  // the line was already saved for undo and this check isn't done.
   3458  if (!undo_allowed(curbuf)) {
   3459    return;
   3460  }
   3461 
   3462  if (argvars[1].v_type != VAR_LIST) {
   3463    emsg(_(e_invarg));
   3464  } else {
   3465    const colnr_T startcol = (colnr_T)tv_get_number_chk(&argvars[0], NULL);
   3466    if (startcol > 0) {
   3467      set_completion(startcol - 1, argvars[1].vval.v_list);
   3468    }
   3469  }
   3470 }
   3471 
   3472 /// "complete_add()" function
   3473 void f_complete_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3474 {
   3475  rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false);
   3476 }
   3477 
   3478 /// "complete_check()" function
   3479 void f_complete_check(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3480 {
   3481  int saved = RedrawingDisabled;
   3482 
   3483  RedrawingDisabled = 0;
   3484  ins_compl_check_keys(0, true);
   3485  rettv->vval.v_number = ins_compl_interrupted();
   3486  RedrawingDisabled = saved;
   3487 }
   3488 
   3489 /// Return Insert completion mode name string
   3490 static char *ins_compl_mode(void)
   3491 {
   3492  if (ctrl_x_mode_not_defined_yet() || ctrl_x_mode_scroll() || compl_started) {
   3493    return ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
   3494  }
   3495  return "";
   3496 }
   3497 
   3498 /// Assign the sequence number to all the completion matches which don't have
   3499 /// one assigned yet.
   3500 static void ins_compl_update_sequence_numbers(void)
   3501 {
   3502  int number = 0;
   3503  compl_T *match;
   3504 
   3505  if (compl_dir_forward()) {
   3506    // Search backwards for the first valid (!= -1) number.
   3507    // This should normally succeed already at the first loop
   3508    // cycle, so it's fast!
   3509    for (match = compl_curr_match->cp_prev;
   3510         match != NULL && !is_first_match(match); match = match->cp_prev) {
   3511      if (match->cp_number != -1) {
   3512        number = match->cp_number;
   3513        break;
   3514      }
   3515    }
   3516    if (match != NULL) {
   3517      // go up and assign all numbers which are not assigned yet
   3518      for (match = match->cp_next;
   3519           match != NULL && match->cp_number == -1;
   3520           match = match->cp_next) {
   3521        match->cp_number = ++number;
   3522      }
   3523    }
   3524  } else {  // BACKWARD
   3525    assert(compl_direction == BACKWARD);
   3526    // Search forwards (upwards) for the first valid (!= -1)
   3527    // number.  This should normally succeed already at the
   3528    // first loop cycle, so it's fast!
   3529    for (match = compl_curr_match->cp_next;
   3530         match != NULL && !is_first_match(match); match = match->cp_next) {
   3531      if (match->cp_number != -1) {
   3532        number = match->cp_number;
   3533        break;
   3534      }
   3535    }
   3536    if (match != NULL) {
   3537      // go down and assign all numbers which are not assigned yet
   3538      for (match = match->cp_prev;
   3539           match && match->cp_number == -1;
   3540           match = match->cp_prev) {
   3541        match->cp_number = ++number;
   3542      }
   3543    }
   3544  }
   3545 }
   3546 
   3547 /// Fill the dict of complete_info
   3548 static void fill_complete_info_dict(dict_T *di, compl_T *match, bool add_match)
   3549 {
   3550  tv_dict_add_str(di, S_LEN("word"), match->cp_str.data);
   3551  tv_dict_add_str(di, S_LEN("abbr"), match->cp_text[CPT_ABBR]);
   3552  tv_dict_add_str(di, S_LEN("menu"), match->cp_text[CPT_MENU]);
   3553  tv_dict_add_str(di, S_LEN("kind"), match->cp_text[CPT_KIND]);
   3554  tv_dict_add_str(di, S_LEN("info"), match->cp_text[CPT_INFO]);
   3555  if (add_match) {
   3556    tv_dict_add_bool(di, S_LEN("match"), match->cp_in_match_array);
   3557  }
   3558  if (match->cp_user_data.v_type == VAR_UNKNOWN) {
   3559    // Add an empty string for backwards compatibility
   3560    tv_dict_add_str(di, S_LEN("user_data"), "");
   3561  } else {
   3562    tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data);
   3563  }
   3564 }
   3565 
   3566 /// Get complete information
   3567 static void get_complete_info(list_T *what_list, dict_T *retdict)
   3568 {
   3569 #define CI_WHAT_MODE                0x01
   3570 #define CI_WHAT_PUM_VISIBLE         0x02
   3571 #define CI_WHAT_ITEMS               0x04
   3572 #define CI_WHAT_SELECTED            0x08
   3573 #define CI_WHAT_COMPLETED           0x10
   3574 #define CI_WHAT_MATCHES             0x20
   3575 #define CI_WHAT_PREINSERTED_TEXT    0x40
   3576 #define CI_WHAT_ALL                 0xff
   3577  int what_flag;
   3578 
   3579  if (what_list == NULL) {
   3580    what_flag = CI_WHAT_ALL & ~(CI_WHAT_MATCHES|CI_WHAT_COMPLETED);
   3581  } else {
   3582    what_flag = 0;
   3583    for (listitem_T *item = tv_list_first(what_list)
   3584         ; item != NULL
   3585         ; item = TV_LIST_ITEM_NEXT(what_list, item)) {
   3586      const char *what = tv_get_string(TV_LIST_ITEM_TV(item));
   3587 
   3588      if (strcmp(what, "mode") == 0) {
   3589        what_flag |= CI_WHAT_MODE;
   3590      } else if (strcmp(what, "pum_visible") == 0) {
   3591        what_flag |= CI_WHAT_PUM_VISIBLE;
   3592      } else if (strcmp(what, "items") == 0) {
   3593        what_flag |= CI_WHAT_ITEMS;
   3594      } else if (strcmp(what, "selected") == 0) {
   3595        what_flag |= CI_WHAT_SELECTED;
   3596      } else if (strcmp(what, "completed") == 0) {
   3597        what_flag |= CI_WHAT_COMPLETED;
   3598      } else if (strcmp(what, "preinserted_text") == 0) {
   3599        what_flag |= CI_WHAT_PREINSERTED_TEXT;
   3600      } else if (strcmp(what, "matches") == 0) {
   3601        what_flag |= CI_WHAT_MATCHES;
   3602      }
   3603    }
   3604  }
   3605 
   3606  int ret = OK;
   3607  if (what_flag & CI_WHAT_MODE) {
   3608    ret = tv_dict_add_str(retdict, S_LEN("mode"), ins_compl_mode());
   3609  }
   3610 
   3611  if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE)) {
   3612    ret = tv_dict_add_nr(retdict, S_LEN("pum_visible"), pum_visible());
   3613  }
   3614 
   3615  if (ret == OK && (what_flag & CI_WHAT_PREINSERTED_TEXT)) {
   3616    char *line = get_cursor_line_ptr();
   3617    int len = compl_ins_end_col - curwin->w_cursor.col;
   3618    ret = tv_dict_add_str_len(retdict, S_LEN("preinserted_text"),
   3619                              len > 0 ? line + curwin->w_cursor.col : "", MAX(len, 0));
   3620  }
   3621 
   3622  if (ret == OK && (what_flag & (CI_WHAT_ITEMS|CI_WHAT_SELECTED
   3623                                 |CI_WHAT_MATCHES|CI_WHAT_COMPLETED))) {
   3624    list_T *li = NULL;
   3625    int selected_idx = -1;
   3626    bool has_items = what_flag & CI_WHAT_ITEMS;
   3627    bool has_matches = what_flag & CI_WHAT_MATCHES;
   3628    bool has_completed = what_flag & CI_WHAT_COMPLETED;
   3629    if (has_items || has_matches) {
   3630      li = tv_list_alloc(kListLenMayKnow);
   3631      const char *key = (has_matches && !has_items) ? "matches" : "items";
   3632      ret = tv_dict_add_list(retdict, key, strlen(key), li);
   3633    }
   3634    if (ret == OK && what_flag & CI_WHAT_SELECTED) {
   3635      if (compl_curr_match != NULL && compl_curr_match->cp_number == -1) {
   3636        ins_compl_update_sequence_numbers();
   3637      }
   3638    }
   3639    if (ret == OK && compl_first_match != NULL) {
   3640      int list_idx = 0;
   3641      compl_T *match = compl_first_match;
   3642      do {
   3643        if (!match_at_original_text(match)) {
   3644          if (has_items || (has_matches && match->cp_in_match_array)) {
   3645            dict_T *di = tv_dict_alloc();
   3646            tv_list_append_dict(li, di);
   3647            fill_complete_info_dict(di, match, has_matches && has_items);
   3648          }
   3649          if (compl_curr_match != NULL
   3650              && compl_curr_match->cp_number == match->cp_number) {
   3651            selected_idx = list_idx;
   3652          }
   3653          if (!has_matches || match->cp_in_match_array) {
   3654            list_idx++;
   3655          }
   3656        }
   3657        match = match->cp_next;
   3658      } while (match != NULL && !is_first_match(match));
   3659    }
   3660    if (ret == OK && (what_flag & CI_WHAT_SELECTED)) {
   3661      ret = tv_dict_add_nr(retdict, S_LEN("selected"), selected_idx);
   3662      win_T *wp = win_float_find_preview();
   3663      if (wp != NULL) {
   3664        tv_dict_add_nr(retdict, S_LEN("preview_winid"), wp->handle);
   3665        tv_dict_add_nr(retdict, S_LEN("preview_bufnr"), wp->w_buffer->handle);
   3666      }
   3667    }
   3668    if (ret == OK && selected_idx != -1 && has_completed) {
   3669      dict_T *di = tv_dict_alloc();
   3670      fill_complete_info_dict(di, compl_curr_match, false);
   3671      ret = tv_dict_add_dict(retdict, S_LEN("completed"), di);
   3672    }
   3673  }
   3674 
   3675  (void)ret;
   3676 }
   3677 
   3678 /// "complete_info()" function
   3679 void f_complete_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   3680 {
   3681  tv_dict_alloc_ret(rettv);
   3682 
   3683  list_T *what_list = NULL;
   3684 
   3685  if (argvars[0].v_type != VAR_UNKNOWN) {
   3686    if (argvars[0].v_type != VAR_LIST) {
   3687      emsg(_(e_listreq));
   3688      return;
   3689    }
   3690    what_list = argvars[0].vval.v_list;
   3691  }
   3692  get_complete_info(what_list, rettv->vval.v_dict);
   3693 }
   3694 
   3695 /// Returns true when using a user-defined function for thesaurus completion.
   3696 static bool thesaurus_func_complete(int type)
   3697 {
   3698  return type == CTRL_X_THESAURUS
   3699         && (*curbuf->b_p_tsrfu != NUL || *p_tsrfu != NUL);
   3700 }
   3701 
   3702 /// Check if 'cpt' list index can be advanced to the next completion source.
   3703 static bool may_advance_cpt_index(const char *cpt)
   3704 {
   3705  const char *p = cpt;
   3706 
   3707  if (cpt_sources_index == -1) {
   3708    return false;
   3709  }
   3710  while (*p == ',' || *p == ' ') {  // Skip delimiters
   3711    p++;
   3712  }
   3713  return (*p != NUL);
   3714 }
   3715 
   3716 /// Return value of process_next_cpt_value()
   3717 enum {
   3718  INS_COMPL_CPT_OK = 1,
   3719  INS_COMPL_CPT_CONT,
   3720  INS_COMPL_CPT_END,
   3721 };
   3722 
   3723 /// Process the next 'complete' option value in st->e_cpt.
   3724 ///
   3725 /// If successful, the arguments are set as below:
   3726 ///   st->cpt - pointer to the next option value in "st->cpt"
   3727 ///   compl_type_arg - type of insert mode completion to use
   3728 ///   st->found_all - all matches of this type are found
   3729 ///   st->ins_buf - search for completions in this buffer
   3730 ///   st->first_match_pos - position of the first completion match
   3731 ///   st->last_match_pos - position of the last completion match
   3732 ///   st->set_match_pos - true if the first match position should be saved to
   3733 ///                       avoid loops after the search wraps around.
   3734 ///   st->dict - name of the dictionary or thesaurus file to search
   3735 ///   st->dict_f - flag specifying whether "dict" is an exact file name or not
   3736 ///
   3737 /// @return  INS_COMPL_CPT_OK if the next value is processed successfully.
   3738 ///          INS_COMPL_CPT_CONT to skip the current completion source matching
   3739 ///          the "st->e_cpt" option value and process the next matching source.
   3740 ///          INS_COMPL_CPT_END if all the values in "st->e_cpt" are processed.
   3741 static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_arg,
   3742                                  pos_T *start_match_pos, bool fuzzy_collect, bool *advance_cpt_idx)
   3743 {
   3744  int compl_type = -1;
   3745  int status = INS_COMPL_CPT_OK;
   3746  bool skip_source = compl_autocomplete && compl_from_nonkeyword;
   3747 
   3748  st->found_all = false;
   3749  *advance_cpt_idx = false;
   3750 
   3751  while (*st->e_cpt == ',' || *st->e_cpt == ' ') {
   3752    st->e_cpt++;
   3753  }
   3754 
   3755  if (*st->e_cpt == '.' && !curbuf->b_scanned && !skip_source
   3756      && !compl_time_slice_expired) {
   3757    st->ins_buf = curbuf;
   3758    st->first_match_pos = *start_match_pos;
   3759    // Move the cursor back one character so that ^N can match the
   3760    // word immediately after the cursor.
   3761    if (ctrl_x_mode_normal() && (!fuzzy_collect && dec(&st->first_match_pos) < 0)) {
   3762      // Move the cursor to after the last character in the
   3763      // buffer, so that word at start of buffer is found
   3764      // correctly.
   3765      st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count;
   3766      st->first_match_pos.col = ml_get_len(st->first_match_pos.lnum);
   3767    }
   3768    st->last_match_pos = st->first_match_pos;
   3769    compl_type = 0;
   3770 
   3771    // Remember the first match so that the loop stops when we
   3772    // wrap and come back there a second time.
   3773    st->set_match_pos = true;
   3774  } else if (!skip_source && !compl_time_slice_expired
   3775             && vim_strchr("buwU", (uint8_t)(*st->e_cpt)) != NULL
   3776             && (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf) {
   3777    // Scan a buffer, but not the current one.
   3778    if (st->ins_buf->b_ml.ml_mfp != NULL) {  // loaded buffer
   3779      compl_started = true;
   3780      st->first_match_pos.col = st->last_match_pos.col = 0;
   3781      st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count + 1;
   3782      st->last_match_pos.lnum = 0;
   3783      compl_type = 0;
   3784    } else {  // unloaded buffer, scan like dictionary
   3785      st->found_all = true;
   3786      if (st->ins_buf->b_fname == NULL) {
   3787        status = INS_COMPL_CPT_CONT;
   3788        goto done;
   3789      }
   3790      compl_type = CTRL_X_DICTIONARY;
   3791      st->dict = st->ins_buf->b_fname;
   3792      st->dict_f = DICT_EXACT;
   3793    }
   3794    if (!shortmess(SHM_COMPLETIONSCAN) && !compl_autocomplete) {
   3795      msg_hist_off = true;  // reset in msg_trunc()
   3796      msg_ext_overwrite = true;
   3797      msg_ext_set_kind("completion");
   3798      vim_snprintf(IObuff, IOSIZE, _("Scanning: %s"),
   3799                   st->ins_buf->b_fname == NULL
   3800                   ? buf_spname(st->ins_buf)
   3801                   : st->ins_buf->b_sfname == NULL
   3802                   ? st->ins_buf->b_fname
   3803                   : st->ins_buf->b_sfname);
   3804      msg_trunc(IObuff, true, HLF_R);
   3805    }
   3806  } else if (*st->e_cpt == NUL) {
   3807    status = INS_COMPL_CPT_END;
   3808  } else {
   3809    if (ctrl_x_mode_line_or_eval()) {
   3810      // compl_type = -1;
   3811    } else if (*st->e_cpt == 'F' || *st->e_cpt == 'o') {
   3812      compl_type = CTRL_X_FUNCTION;
   3813      st->func_cb = get_callback_if_cpt_func(st->e_cpt, cpt_sources_index);
   3814      if (!st->func_cb) {
   3815        compl_type = -1;
   3816      }
   3817    } else if (!skip_source) {
   3818      if (*st->e_cpt == 'k' || *st->e_cpt == 's') {
   3819        if (*st->e_cpt == 'k') {
   3820          compl_type = CTRL_X_DICTIONARY;
   3821        } else {
   3822          compl_type = CTRL_X_THESAURUS;
   3823        }
   3824        if (*++st->e_cpt != ',' && *st->e_cpt != NUL) {
   3825          st->dict = st->e_cpt;
   3826          st->dict_f = DICT_FIRST;
   3827        }
   3828      } else if (*st->e_cpt == 'i') {
   3829        compl_type = CTRL_X_PATH_PATTERNS;
   3830      } else if (*st->e_cpt == 'd') {
   3831        compl_type = CTRL_X_PATH_DEFINES;
   3832      } else if (*st->e_cpt == 'f') {
   3833        compl_type = CTRL_X_BUFNAMES;
   3834      } else if (*st->e_cpt == ']' || *st->e_cpt == 't') {
   3835        compl_type = CTRL_X_TAGS;
   3836        if (!shortmess(SHM_COMPLETIONSCAN) && !compl_autocomplete) {
   3837          msg_ext_set_kind("completion");
   3838          msg_hist_off = true;  // reset in msg_trunc()
   3839          msg_ext_overwrite = true;
   3840          vim_snprintf(IObuff, IOSIZE, "%s", _("Scanning tags."));
   3841          msg_trunc(IObuff, true, HLF_R);
   3842        }
   3843      }
   3844    }
   3845 
   3846    // in any case e_cpt is advanced to the next entry
   3847    copy_option_part(&st->e_cpt, IObuff, IOSIZE, ",");
   3848    *advance_cpt_idx = may_advance_cpt_index(st->e_cpt);
   3849 
   3850    st->found_all = true;
   3851    if (compl_type == -1) {
   3852      status = INS_COMPL_CPT_CONT;
   3853    }
   3854  }
   3855 
   3856 done:
   3857  *compl_type_arg = compl_type;
   3858  return status;
   3859 }
   3860 
   3861 /// Get the next set of identifiers or defines matching "compl_pattern" in
   3862 /// included files.
   3863 static void get_next_include_file_completion(int compl_type)
   3864 {
   3865  find_pattern_in_path(compl_pattern.data, compl_direction,
   3866                       compl_pattern.size, false, false,
   3867                       ((compl_type == CTRL_X_PATH_DEFINES
   3868                         && !(compl_cont_status & CONT_SOL))
   3869                        ? FIND_DEFINE : FIND_ANY),
   3870                       1, ACTION_EXPAND, 1, MAXLNUM, false, compl_autocomplete);
   3871 }
   3872 
   3873 /// Get the next set of words matching "compl_pattern" in dictionary or
   3874 /// thesaurus files.
   3875 static void get_next_dict_tsr_completion(int compl_type, char *dict, int dict_f)
   3876 {
   3877  if (thesaurus_func_complete(compl_type)) {
   3878    expand_by_function(compl_type, compl_pattern.data, NULL);
   3879  } else {
   3880    ins_compl_dictionaries(dict != NULL
   3881                           ? dict
   3882                           : (compl_type == CTRL_X_THESAURUS
   3883                              ? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
   3884                              : (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
   3885                           compl_pattern.data,
   3886                           dict != NULL ? dict_f : 0,
   3887                           compl_type == CTRL_X_THESAURUS);
   3888  }
   3889 }
   3890 
   3891 /// Get the next set of tag names matching "compl_pattern".
   3892 static void get_next_tag_completion(void)
   3893 {
   3894  // set p_ic according to p_ic, p_scs and pat for find_tags().
   3895  const int save_p_ic = p_ic;
   3896  p_ic = ignorecase(compl_pattern.data);
   3897 
   3898  // Find up to TAG_MANY matches.  Avoids that an enormous number
   3899  // of matches is found when compl_pattern is empty
   3900  g_tag_at_cursor = true;
   3901  char **matches;
   3902  int num_matches;
   3903  if (find_tags(compl_pattern.data, &num_matches, &matches,
   3904                TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
   3905                | (ctrl_x_mode_not_default() ? TAG_VERBOSE : 0),
   3906                TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) {
   3907    ins_compl_add_matches(num_matches, matches, p_ic);
   3908  }
   3909  g_tag_at_cursor = false;
   3910  p_ic = save_p_ic;
   3911 }
   3912 
   3913 /// Compare function for qsort
   3914 static int compare_scores(const void *a, const void *b)
   3915 {
   3916  int idx_a = *(const int *)a;
   3917  int idx_b = *(const int *)b;
   3918  int score_a = compl_fuzzy_scores[idx_a];
   3919  int score_b = compl_fuzzy_scores[idx_b];
   3920  return score_a == score_b ? (idx_a == idx_b ? 0 : (idx_a < idx_b ? -1 : 1))
   3921                            : (score_a > score_b ? -1 : 1);
   3922 }
   3923 
   3924 /// insert prefix with redraw
   3925 static void ins_compl_longest_insert(char *prefix)
   3926 {
   3927  ins_compl_delete(false);
   3928  ins_compl_insert_bytes(prefix + get_compl_len(), -1);
   3929  ins_redraw(false);
   3930 }
   3931 
   3932 /// Calculate the longest common prefix among the best fuzzy matches
   3933 /// stored in compl_best_matches, and insert it as the longest.
   3934 static void fuzzy_longest_match(void)
   3935 {
   3936  if (compl_num_bests == 0) {
   3937    return;
   3938  }
   3939 
   3940  compl_T *nn_compl = compl_first_match->cp_next->cp_next;
   3941  bool more_candidates = nn_compl && nn_compl != compl_first_match;
   3942 
   3943  compl_T *compl = ctrl_x_mode_whole_line() ? compl_first_match
   3944                                            : compl_first_match->cp_next;
   3945  if (compl_num_bests == 1) {
   3946    // no more candidates insert the match str
   3947    if (!more_candidates) {
   3948      ins_compl_longest_insert(compl->cp_str.data);
   3949      compl_num_bests = 0;
   3950    }
   3951    compl_num_bests = 0;
   3952    return;
   3953  }
   3954 
   3955  compl_best_matches = (compl_T **)xmalloc((size_t)compl_num_bests * sizeof(compl_T *));
   3956 
   3957  for (int i = 0; compl != NULL && i < compl_num_bests; i++) {
   3958    compl_best_matches[i] = compl;
   3959    compl = compl->cp_next;
   3960  }
   3961 
   3962  char *prefix = compl_best_matches[0]->cp_str.data;
   3963  int prefix_len = (int)compl_best_matches[0]->cp_str.size;
   3964 
   3965  for (int i = 1; i < compl_num_bests; i++) {
   3966    char *match_str = compl_best_matches[i]->cp_str.data;
   3967    char *prefix_ptr = prefix;
   3968    char *match_ptr = match_str;
   3969    int j = 0;
   3970 
   3971    while (j < prefix_len && *match_ptr != NUL && *prefix_ptr != NUL) {
   3972      if (strncmp(prefix_ptr, match_ptr, (size_t)utfc_ptr2len(prefix_ptr)) != 0) {
   3973        break;
   3974      }
   3975 
   3976      MB_PTR_ADV(prefix_ptr);
   3977      MB_PTR_ADV(match_ptr);
   3978      j++;
   3979    }
   3980 
   3981    if (j > 0) {
   3982      prefix_len = j;
   3983    }
   3984  }
   3985 
   3986  char *leader = ins_compl_leader();
   3987  size_t leader_len = ins_compl_leader_len();
   3988 
   3989  // skip non-consecutive prefixes
   3990  if (leader_len > 0 && strncmp(prefix, leader, leader_len) != 0) {
   3991    goto end;
   3992  }
   3993 
   3994  prefix = xmemdupz(prefix, (size_t)prefix_len);
   3995  ins_compl_longest_insert(prefix);
   3996  xfree(prefix);
   3997 
   3998 end:
   3999  xfree(compl_best_matches);
   4000  compl_best_matches = NULL;
   4001  compl_num_bests = 0;
   4002 }
   4003 
   4004 /// Get the next set of filename matching "compl_pattern".
   4005 static void get_next_filename_completion(void)
   4006 {
   4007  char **matches;
   4008  int num_matches;
   4009  char *leader = ins_compl_leader();
   4010  size_t leader_len = ins_compl_leader_len();
   4011  bool in_fuzzy_collect = (cot_fuzzy() && leader_len > 0);
   4012  bool need_collect_bests = in_fuzzy_collect && compl_get_longest;
   4013  int max_score = 0;
   4014  Direction dir = compl_direction;
   4015 
   4016 #ifdef BACKSLASH_IN_FILENAME
   4017  char pathsep = (curbuf->b_p_csl[0] == 's')
   4018                 ? '/' : (curbuf->b_p_csl[0] == 'b') ? '\\' : PATHSEP;
   4019 #else
   4020  char pathsep = PATHSEP;
   4021 #endif
   4022 
   4023  if (in_fuzzy_collect) {
   4024 #ifdef BACKSLASH_IN_FILENAME
   4025    if (curbuf->b_p_csl[0] == 's') {
   4026      for (size_t i = 0; i < leader_len; i++) {
   4027        if (leader[i] == '\\') {
   4028          leader[i] = '/';
   4029        }
   4030      }
   4031    } else if (curbuf->b_p_csl[0] == 'b') {
   4032      for (size_t i = 0; i < leader_len; i++) {
   4033        if (leader[i] == '/') {
   4034          leader[i] = '\\';
   4035        }
   4036      }
   4037    }
   4038 #endif
   4039    char *last_sep = strrchr(leader, pathsep);
   4040    if (last_sep == NULL) {
   4041      // No path separator or separator is the last character,
   4042      // fuzzy match the whole leader
   4043      API_CLEAR_STRING(compl_pattern);
   4044      compl_pattern = cbuf_to_string("*", 1);
   4045    } else if (*(last_sep + 1) == NUL) {
   4046      in_fuzzy_collect = false;
   4047    } else {
   4048      // Split leader into path and file parts
   4049      size_t path_len = (size_t)(last_sep - leader) + 1;
   4050      char *path_with_wildcard = xmalloc(path_len + 2);
   4051      vim_snprintf(path_with_wildcard, path_len + 2, "%*.*s*",
   4052                   (int)path_len, (int)path_len, leader);
   4053      API_CLEAR_STRING(compl_pattern);
   4054      compl_pattern.data = path_with_wildcard;
   4055      compl_pattern.size = path_len + 1;
   4056 
   4057      // Move leader to the file part
   4058      leader = last_sep + 1;
   4059      leader_len -= path_len;
   4060    }
   4061  }
   4062 
   4063  if (expand_wildcards(1, &compl_pattern.data, &num_matches, &matches,
   4064                       EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK) {
   4065    return;
   4066  }
   4067 
   4068  // May change home directory back to "~".
   4069  tilde_replace(compl_pattern.data, num_matches, matches);
   4070 #ifdef BACKSLASH_IN_FILENAME
   4071  if (curbuf->b_p_csl[0] != NUL) {
   4072    for (int i = 0; i < num_matches; i++) {
   4073      char *ptr = matches[i];
   4074      while (*ptr != NUL) {
   4075        if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
   4076          *ptr = '/';
   4077        } else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/') {
   4078          *ptr = '\\';
   4079        }
   4080        ptr += utfc_ptr2len(ptr);
   4081      }
   4082    }
   4083  }
   4084 #endif
   4085 
   4086  if (in_fuzzy_collect) {
   4087    garray_T fuzzy_indices;
   4088    ga_init(&fuzzy_indices, sizeof(int), 10);
   4089    compl_fuzzy_scores = (int *)xmalloc(sizeof(int) * (size_t)num_matches);
   4090 
   4091    for (int i = 0; i < num_matches; i++) {
   4092      char *ptr = matches[i];
   4093      int score = fuzzy_match_str(ptr, leader);
   4094      if (score != FUZZY_SCORE_NONE) {
   4095        GA_APPEND(int, &fuzzy_indices, i);
   4096        compl_fuzzy_scores[i] = score;
   4097      }
   4098    }
   4099 
   4100    // prevent qsort from deref NULL pointer
   4101    if (fuzzy_indices.ga_len > 0) {
   4102      int *fuzzy_indices_data = (int *)fuzzy_indices.ga_data;
   4103      qsort(fuzzy_indices_data, (size_t)fuzzy_indices.ga_len, sizeof(int), compare_scores);
   4104 
   4105      for (int i = 0; i < fuzzy_indices.ga_len; i++) {
   4106        char *match = matches[fuzzy_indices_data[i]];
   4107        int current_score = compl_fuzzy_scores[fuzzy_indices_data[i]];
   4108        if (ins_compl_add(match, -1, NULL, NULL, false, NULL, dir,
   4109                          CP_FAST | ((p_fic || p_wic) ? CP_ICASE : 0),
   4110                          false, NULL, current_score) == OK) {
   4111          dir = FORWARD;
   4112        }
   4113 
   4114        if (need_collect_bests) {
   4115          if (i == 0 || current_score == max_score) {
   4116            compl_num_bests++;
   4117            max_score = current_score;
   4118          }
   4119        }
   4120      }
   4121 
   4122      FreeWild(num_matches, matches);
   4123    } else if (leader_len > 0) {
   4124      FreeWild(num_matches, matches);
   4125      num_matches = 0;
   4126    }
   4127 
   4128    xfree(compl_fuzzy_scores);
   4129    ga_clear(&fuzzy_indices);
   4130 
   4131    if (compl_num_bests > 0 && compl_get_longest) {
   4132      fuzzy_longest_match();
   4133    }
   4134    return;
   4135  }
   4136 
   4137  if (num_matches > 0) {
   4138    ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
   4139  }
   4140 }
   4141 
   4142 /// Get the next set of command-line completions matching "compl_pattern".
   4143 static void get_next_cmdline_completion(void)
   4144 {
   4145  char **matches;
   4146  int num_matches;
   4147  if (expand_cmdline(&compl_xp, compl_pattern.data,
   4148                     (int)compl_pattern.size, &num_matches, &matches) == EXPAND_OK) {
   4149    ins_compl_add_matches(num_matches, matches, false);
   4150  }
   4151 }
   4152 
   4153 /// Get the next set of spell suggestions matching "compl_pattern".
   4154 static void get_next_spell_completion(linenr_T lnum)
   4155 {
   4156  char **matches;
   4157  int num_matches = expand_spelling(lnum, compl_pattern.data, &matches);
   4158  if (num_matches > 0) {
   4159    ins_compl_add_matches(num_matches, matches, p_ic);
   4160  } else {
   4161    xfree(matches);
   4162  }
   4163 }
   4164 
   4165 /// Return the next word or line from buffer "ins_buf" at position
   4166 /// "cur_match_pos" for completion.  The length of the match is set in "len".
   4167 /// @param ins_buf        buffer being scanned
   4168 /// @param cur_match_pos  current match position
   4169 /// @param match_len
   4170 /// @param cont_s_ipos    next ^X<> will set initial_pos
   4171 static char *ins_compl_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len,
   4172                                             bool *cont_s_ipos)
   4173 {
   4174  *match_len = 0;
   4175  char *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum) + cur_match_pos->col;
   4176  int len = ml_get_buf_len(ins_buf, cur_match_pos->lnum) - cur_match_pos->col;
   4177  if (ctrl_x_mode_line_or_eval()) {
   4178    if (compl_status_adding()) {
   4179      if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count) {
   4180        return NULL;
   4181      }
   4182      ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1);
   4183      len = ml_get_buf_len(ins_buf, cur_match_pos->lnum + 1);
   4184      if (!p_paste) {
   4185        char *tmp_ptr = ptr;
   4186        ptr = skipwhite(tmp_ptr);
   4187        len -= (int)(ptr - tmp_ptr);
   4188      }
   4189    }
   4190  } else {
   4191    char *tmp_ptr = ptr;
   4192 
   4193    if (compl_status_adding() && compl_length <= len) {
   4194      tmp_ptr += compl_length;
   4195      // Skip if already inside a word.
   4196      if (vim_iswordp(tmp_ptr)) {
   4197        return NULL;
   4198      }
   4199      // Find start of next word.
   4200      tmp_ptr = find_word_start(tmp_ptr);
   4201    }
   4202    // Find end of this word.
   4203    tmp_ptr = find_word_end(tmp_ptr);
   4204    len = (int)(tmp_ptr - ptr);
   4205 
   4206    if (compl_status_adding() && len == compl_length) {
   4207      if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count) {
   4208        // Try next line, if any. the new word will be "join" as if the
   4209        // normal command "J" was used. IOSIZE is always greater than
   4210        // compl_length, so the next strncpy always works -- Acevedo
   4211        strncpy(IObuff, ptr, (size_t)len);  // NOLINT(runtime/printf)
   4212        ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1);
   4213        tmp_ptr = ptr = skipwhite(ptr);
   4214        // Find start of next word.
   4215        tmp_ptr = find_word_start(tmp_ptr);
   4216        // Find end of next word.
   4217        tmp_ptr = find_word_end(tmp_ptr);
   4218        if (tmp_ptr > ptr) {
   4219          if (*ptr != ')' && IObuff[len - 1] != TAB) {
   4220            if (IObuff[len - 1] != ' ') {
   4221              IObuff[len++] = ' ';
   4222            }
   4223            // IObuf =~ "\k.* ", thus len >= 2
   4224            if (p_js
   4225                && (IObuff[len - 2] == '.'
   4226                    || IObuff[len - 2] == '?'
   4227                    || IObuff[len - 2] == '!')) {
   4228              IObuff[len++] = ' ';
   4229            }
   4230          }
   4231          // copy as much as possible of the new word
   4232          if (tmp_ptr - ptr >= IOSIZE - len) {
   4233            tmp_ptr = ptr + IOSIZE - len - 1;
   4234          }
   4235          xstrlcpy(IObuff + len, ptr, (size_t)(IOSIZE - len));
   4236          len += (int)(tmp_ptr - ptr);
   4237          *cont_s_ipos = true;
   4238        }
   4239        IObuff[len] = NUL;
   4240        ptr = IObuff;
   4241      }
   4242      if (len == compl_length) {
   4243        return NULL;
   4244      }
   4245    }
   4246  }
   4247 
   4248  *match_len = len;
   4249  return ptr;
   4250 }
   4251 
   4252 /// Get the next set of words matching "compl_pattern" for default completion(s)
   4253 /// (normal ^P/^N and ^X^L).
   4254 /// Search for "compl_pattern" in the buffer "st->ins_buf" starting from the
   4255 /// position "st->start_pos" in the "compl_direction" direction. If
   4256 /// "st->set_match_pos" is true, then set the "st->first_match_pos" and
   4257 /// "st->last_match_pos".
   4258 ///
   4259 /// @return  OK if a new next match is found, otherwise FAIL.
   4260 static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
   4261 {
   4262  char *ptr = NULL;
   4263  int len = 0;
   4264  bool in_fuzzy_collect = !compl_status_adding() && cot_fuzzy() && compl_length > 0;
   4265  char *leader = ins_compl_leader();
   4266  int score = FUZZY_SCORE_NONE;
   4267  const bool in_curbuf = st->ins_buf == curbuf;
   4268 
   4269  // If 'infercase' is set, don't use 'smartcase' here
   4270  const int save_p_scs = p_scs;
   4271  assert(st->ins_buf);
   4272  if (st->ins_buf->b_p_inf) {
   4273    p_scs = false;
   4274  }
   4275 
   4276  // Buffers other than curbuf are scanned from the beginning or the
   4277  // end but never from the middle, thus setting nowrapscan in this
   4278  // buffers is a good idea, on the other hand, we always set
   4279  // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
   4280  const int save_p_ws = p_ws;
   4281  if (!in_curbuf) {
   4282    p_ws = false;
   4283  } else if (*st->e_cpt == '.') {
   4284    p_ws = true;
   4285  }
   4286  bool looped_around = false;
   4287  int found_new_match = FAIL;
   4288  while (true) {
   4289    bool cont_s_ipos = false;
   4290 
   4291    msg_silent++;  // Don't want messages for wrapscan.
   4292 
   4293    if (in_fuzzy_collect) {
   4294      found_new_match = search_for_fuzzy_match(st->ins_buf,
   4295                                               st->cur_match_pos, leader, compl_direction,
   4296                                               start_pos, &len, &ptr, &score);
   4297      // ctrl_x_mode_line_or_eval() || word-wise search that
   4298      // has added a word that was at the beginning of the line.
   4299    } else if (ctrl_x_mode_whole_line() || ctrl_x_mode_eval()
   4300               || (compl_cont_status & CONT_SOL)) {
   4301      found_new_match = search_for_exact_line(st->ins_buf, st->cur_match_pos,
   4302                                              compl_direction, compl_pattern.data);
   4303    } else {
   4304      found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
   4305                                 NULL, compl_direction, compl_pattern.data,
   4306                                 compl_pattern.size,
   4307                                 1, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
   4308    }
   4309    msg_silent--;
   4310    if (!compl_started || st->set_match_pos) {
   4311      // set "compl_started" even on fail
   4312      compl_started = true;
   4313      st->first_match_pos = *st->cur_match_pos;
   4314      st->last_match_pos = *st->cur_match_pos;
   4315      st->set_match_pos = false;
   4316    } else if (st->first_match_pos.lnum == st->last_match_pos.lnum
   4317               && st->first_match_pos.col == st->last_match_pos.col) {
   4318      found_new_match = FAIL;
   4319    } else if (compl_dir_forward()
   4320               && (st->prev_match_pos.lnum > st->cur_match_pos->lnum
   4321                   || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
   4322                       && st->prev_match_pos.col >= st->cur_match_pos->col))) {
   4323      if (looped_around) {
   4324        found_new_match = FAIL;
   4325      } else {
   4326        looped_around = true;
   4327      }
   4328    } else if (!compl_dir_forward()
   4329               && (st->prev_match_pos.lnum < st->cur_match_pos->lnum
   4330                   || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
   4331                       && st->prev_match_pos.col <= st->cur_match_pos->col))) {
   4332      if (looped_around) {
   4333        found_new_match = FAIL;
   4334      } else {
   4335        looped_around = true;
   4336      }
   4337    }
   4338    st->prev_match_pos = *st->cur_match_pos;
   4339    if (found_new_match == FAIL) {
   4340      break;
   4341    }
   4342 
   4343    // when ADDING, the text before the cursor matches, skip it
   4344    if (compl_status_adding() && in_curbuf
   4345        && start_pos->lnum == st->cur_match_pos->lnum
   4346        && start_pos->col == st->cur_match_pos->col) {
   4347      continue;
   4348    }
   4349 
   4350    if (!in_fuzzy_collect) {
   4351      ptr = ins_compl_get_next_word_or_line(st->ins_buf,
   4352                                            st->cur_match_pos, &len, &cont_s_ipos);
   4353    }
   4354    if (ptr == NULL || (ins_compl_has_preinsert()
   4355                        && strcmp(ptr, ins_compl_leader()) == 0)) {
   4356      continue;
   4357    }
   4358 
   4359    if (is_nearest_active() && in_curbuf) {
   4360      score = st->cur_match_pos->lnum - curwin->w_cursor.lnum;
   4361      if (score < 0) {
   4362        score = -score;
   4363      }
   4364    }
   4365 
   4366    if (ins_compl_add_infercase(ptr, len, p_ic,
   4367                                in_curbuf ? NULL : st->ins_buf->b_sfname,
   4368                                0, cont_s_ipos, score) != NOTDONE) {
   4369      if (in_fuzzy_collect && score == compl_first_match->cp_next->cp_score) {
   4370        compl_num_bests++;
   4371      }
   4372      found_new_match = OK;
   4373      break;
   4374    }
   4375  }
   4376  p_scs = save_p_scs;
   4377  p_ws = save_p_ws;
   4378 
   4379  return found_new_match;
   4380 }
   4381 
   4382 /// Get completion matches from register contents.
   4383 /// Extracts words from all available registers and adds them to the completion list.
   4384 static void get_register_completion(void)
   4385 {
   4386  Direction dir = compl_direction;
   4387  bool adding_mode = compl_status_adding();
   4388 
   4389  for (int i = 0; i < NUM_REGISTERS; i++) {
   4390    int regname = get_register_name(i);
   4391    // Skip invalid or black hole register
   4392    if (!valid_yank_reg(regname, false) || regname == '_') {
   4393      continue;
   4394    }
   4395 
   4396    yankreg_T *reg = copy_register(regname);
   4397 
   4398    if (reg->y_array == NULL || reg->y_size == 0) {
   4399      free_register(reg);
   4400      xfree(reg);
   4401      continue;
   4402    }
   4403 
   4404    for (size_t j = 0; j < reg->y_size; j++) {
   4405      char *str = reg->y_array[j].data;
   4406      if (str == NULL) {
   4407        continue;
   4408      }
   4409 
   4410      if (adding_mode) {
   4411        int str_len = (int)strlen(str);
   4412        if (str_len == 0) {
   4413          continue;
   4414        }
   4415 
   4416        if (!compl_orig_text.data
   4417            || (p_ic ? STRNICMP(str, compl_orig_text.data,
   4418                                compl_orig_text.size) == 0
   4419                     : strncmp(str, compl_orig_text.data,
   4420                               compl_orig_text.size) == 0)) {
   4421          if (ins_compl_add_infercase(str, str_len, p_ic, NULL,
   4422                                      dir, false, FUZZY_SCORE_NONE) == OK) {
   4423            dir = FORWARD;
   4424          }
   4425        }
   4426      } else {
   4427        // Calculate the safe end of string to avoid null byte issues
   4428        char *str_end = str + strlen(str);
   4429        char *p = str;
   4430 
   4431        // Safely iterate through the string
   4432        while (p < str_end && *p != NUL) {
   4433          char *old_p = p;
   4434          p = find_word_start(p);
   4435          if (p >= str_end || *p == NUL) {
   4436            break;
   4437          }
   4438 
   4439          char *word_end = find_word_end(p);
   4440 
   4441          if (word_end <= p) {
   4442            word_end = p + utfc_ptr2len(p);
   4443          }
   4444 
   4445          if (word_end > str_end) {
   4446            word_end = str_end;
   4447          }
   4448 
   4449          int len = (int)(word_end - p);
   4450          if (len > 0 && (!compl_orig_text.data
   4451                          || (p_ic ? STRNICMP(p, compl_orig_text.data,
   4452                                              compl_orig_text.size) == 0
   4453                                   : strncmp(p, compl_orig_text.data,
   4454                                             compl_orig_text.size) == 0))) {
   4455            if (ins_compl_add_infercase(p, len, p_ic, NULL,
   4456                                        dir, false, FUZZY_SCORE_NONE) == OK) {
   4457              dir = FORWARD;
   4458            }
   4459          }
   4460 
   4461          p = word_end;
   4462 
   4463          if (p <= old_p) {
   4464            p = old_p + utfc_ptr2len(old_p);
   4465          }
   4466        }
   4467      }
   4468    }
   4469 
   4470    free_register(reg);
   4471    xfree(reg);
   4472  }
   4473 }
   4474 
   4475 /// Return the callback function associated with "p" if it refers to a
   4476 /// user-defined function in the 'complete' option.
   4477 /// The "idx" parameter is used for indexing callback entries.
   4478 static Callback *get_callback_if_cpt_func(char *p, int idx)
   4479 {
   4480  if (*p == 'o') {
   4481    return &curbuf->b_ofu_cb;
   4482  }
   4483 
   4484  if (*p == 'F') {
   4485    if (*++p != ',' && *p != NUL) {
   4486      // 'F{func}' case
   4487      return curbuf->b_p_cpt_cb[idx].type != kCallbackNone
   4488             ? &curbuf->b_p_cpt_cb[idx] : NULL;
   4489    } else {
   4490      return &curbuf->b_cfu_cb;  // 'cfu'
   4491    }
   4492  }
   4493 
   4494  return NULL;
   4495 }
   4496 
   4497 /// get the next set of completion matches for "type".
   4498 /// @return  true if a new match is found, otherwise false.
   4499 static bool get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
   4500 {
   4501  int found_new_match = FAIL;
   4502 
   4503  switch (type) {
   4504  case -1:
   4505    break;
   4506  case CTRL_X_PATH_PATTERNS:
   4507  case CTRL_X_PATH_DEFINES:
   4508    get_next_include_file_completion(type);
   4509    break;
   4510 
   4511  case CTRL_X_DICTIONARY:
   4512  case CTRL_X_THESAURUS:
   4513    get_next_dict_tsr_completion(type, st->dict, st->dict_f);
   4514    st->dict = NULL;
   4515    break;
   4516 
   4517  case CTRL_X_TAGS:
   4518    get_next_tag_completion();
   4519    break;
   4520 
   4521  case CTRL_X_FILES:
   4522    get_next_filename_completion();
   4523    break;
   4524 
   4525  case CTRL_X_CMDLINE:
   4526  case CTRL_X_CMDLINE_CTRL_X:
   4527    get_next_cmdline_completion();
   4528    break;
   4529 
   4530  case CTRL_X_FUNCTION:
   4531    if (ctrl_x_mode_normal()) {  // Invoked by a func in 'cpt' option
   4532      get_cpt_func_completion_matches(st->func_cb);
   4533    } else {
   4534      expand_by_function(type, compl_pattern.data, NULL);
   4535    }
   4536    break;
   4537  case CTRL_X_OMNI:
   4538    expand_by_function(type, compl_pattern.data, NULL);
   4539    break;
   4540 
   4541  case CTRL_X_SPELL:
   4542    get_next_spell_completion(st->first_match_pos.lnum);
   4543    break;
   4544  case CTRL_X_BUFNAMES:
   4545    get_next_bufname_token();
   4546    break;
   4547  case CTRL_X_REGISTER:
   4548    get_register_completion();
   4549    break;
   4550 
   4551  default:            // normal ^P/^N and ^X^L
   4552    found_new_match = get_next_default_completion(st, ini);
   4553    if (found_new_match == FAIL && st->ins_buf == curbuf) {
   4554      st->found_all = true;
   4555    }
   4556  }
   4557 
   4558  // check if compl_curr_match has changed, (e.g. other type of
   4559  // expansion added something)
   4560  if (type != 0 && compl_curr_match != compl_old_match) {
   4561    found_new_match = OK;
   4562  }
   4563 
   4564  return found_new_match;
   4565 }
   4566 
   4567 static void get_next_bufname_token(void)
   4568 {
   4569  FOR_ALL_BUFFERS(b) {
   4570    if (b->b_p_bl && b->b_sfname != NULL) {
   4571      char *tail = path_tail(b->b_sfname);
   4572      if (strncmp(tail, compl_orig_text.data, compl_orig_text.size) == 0) {
   4573        ins_compl_add(tail, (int)strlen(tail), NULL, NULL, false, NULL, 0,
   4574                      p_ic ? CP_ICASE : 0, false, NULL, FUZZY_SCORE_NONE);
   4575      }
   4576    }
   4577  }
   4578 }
   4579 
   4580 /// Strips carets followed by numbers. This suffix typically represents the
   4581 /// max_matches setting.
   4582 static void strip_caret_numbers_in_place(char *str)
   4583 {
   4584  char *read = str, *write = str, *p;
   4585 
   4586  if (str == NULL) {
   4587    return;
   4588  }
   4589 
   4590  while (*read) {
   4591    if (*read == '^') {
   4592      p = read + 1;
   4593      while (ascii_isdigit(*p)) {
   4594        p++;
   4595      }
   4596      if ((*p == ',' || *p == '\0') && p != read + 1) {
   4597        read = p;
   4598        continue;
   4599      } else {
   4600        *write++ = *read++;
   4601      }
   4602    } else {
   4603      *write++ = *read++;
   4604    }
   4605  }
   4606  *write = '\0';
   4607 }
   4608 
   4609 /// Call functions specified in the 'cpt' option with findstart=1,
   4610 /// and retrieve the startcol.
   4611 static void prepare_cpt_compl_funcs(void)
   4612 {
   4613  // Make a copy of 'cpt' in case the buffer gets wiped out
   4614  char *cpt = xstrdup(curbuf->b_p_cpt);
   4615  strip_caret_numbers_in_place(cpt);
   4616 
   4617  int idx = 0;
   4618  for (char *p = cpt; *p;) {
   4619    while (*p == ',' || *p == ' ') {  // Skip delimiters
   4620      p++;
   4621    }
   4622    if (*p == NUL) {
   4623      break;
   4624    }
   4625 
   4626    Callback *cb = get_callback_if_cpt_func(p, idx);
   4627    if (cb) {
   4628      int startcol;
   4629      if (get_userdefined_compl_info(curwin->w_cursor.col, cb, &startcol) == FAIL) {
   4630        if (startcol == -3) {
   4631          cpt_sources_array[idx].cs_refresh_always = false;
   4632        } else {
   4633          startcol = -2;
   4634        }
   4635      } else if (startcol < 0 || startcol > curwin->w_cursor.col) {
   4636        startcol = curwin->w_cursor.col;
   4637      }
   4638      cpt_sources_array[idx].cs_startcol = startcol;
   4639    } else {
   4640      cpt_sources_array[idx].cs_startcol = -3;
   4641    }
   4642 
   4643    (void)copy_option_part(&p, IObuff, IOSIZE, ",");  // Advance p
   4644    idx++;
   4645  }
   4646 
   4647  xfree(cpt);
   4648 }
   4649 
   4650 /// Start the timer for the current completion source.
   4651 static void compl_source_start_timer(int source_idx)
   4652 {
   4653  if (compl_autocomplete || p_cto > 0) {
   4654    cpt_sources_array[source_idx].compl_start_tv = os_hrtime();
   4655    compl_time_slice_expired = false;
   4656  }
   4657 }
   4658 
   4659 /// Safely advance the cpt_sources_index by one.
   4660 static int advance_cpt_sources_index_safe(void)
   4661 {
   4662  if (cpt_sources_index >= 0 && cpt_sources_index < cpt_sources_count - 1) {
   4663    cpt_sources_index++;
   4664    return OK;
   4665  }
   4666  semsg(_(e_list_index_out_of_range_nr), cpt_sources_index);
   4667  return FAIL;
   4668 }
   4669 
   4670 /// Get the next expansion(s), using "compl_pattern".
   4671 /// The search starts at position "ini" in curbuf and in the direction
   4672 /// compl_direction.
   4673 /// When "compl_started" is false start at that position, otherwise continue
   4674 /// where we stopped searching before.
   4675 /// This may return before finding all the matches.
   4676 /// Return the total number of matches or -1 if still unknown -- Acevedo
   4677 static int ins_compl_get_exp(pos_T *ini)
   4678 {
   4679  static ins_compl_next_state_T st;
   4680  static bool st_cleared = false;
   4681  int found_new_match;
   4682  int type = ctrl_x_mode;
   4683  bool may_advance_cpt_idx = false;
   4684  pos_T start_pos = *ini;
   4685 
   4686  assert(curbuf != NULL);
   4687 
   4688  if (!compl_started) {
   4689    FOR_ALL_BUFFERS(buf) {
   4690      buf->b_scanned = false;
   4691    }
   4692    if (!st_cleared) {
   4693      CLEAR_FIELD(st);
   4694      st_cleared = true;
   4695    }
   4696    st.found_all = false;
   4697    st.ins_buf = curbuf;
   4698    xfree(st.e_cpt_copy);
   4699    // Make a copy of 'complete', in case the buffer is wiped out.
   4700    st.e_cpt_copy = xstrdup((compl_cont_status & CONT_LOCAL) ? "." : curbuf->b_p_cpt);
   4701    strip_caret_numbers_in_place(st.e_cpt_copy);
   4702    st.e_cpt = st.e_cpt_copy;
   4703 
   4704    // In large buffers, timeout may miss nearby matches — search above cursor
   4705 #define LOOKBACK_LINE_COUNT     1000
   4706    if (compl_autocomplete && is_nearest_active()) {
   4707      start_pos.lnum = MAX(1, start_pos.lnum - LOOKBACK_LINE_COUNT);
   4708      start_pos.col = 0;
   4709    }
   4710    st.last_match_pos = st.first_match_pos = start_pos;
   4711  } else if (st.ins_buf != curbuf && !buf_valid(st.ins_buf)) {
   4712    st.ins_buf = curbuf;  // In case the buffer was wiped out.
   4713  }
   4714  assert(st.ins_buf != NULL);
   4715 
   4716  compl_old_match = compl_curr_match;   // remember the last current match
   4717  st.cur_match_pos = compl_dir_forward() ? &st.last_match_pos : &st.first_match_pos;
   4718 
   4719  bool normal_mode_strict = ctrl_x_mode_normal() && !ctrl_x_mode_line_or_eval()
   4720                            && !(compl_cont_status & CONT_LOCAL)
   4721                            && cpt_sources_array != NULL;
   4722  if (normal_mode_strict) {
   4723    cpt_sources_index = 0;
   4724    if (compl_autocomplete || p_cto > 0) {
   4725      compl_source_start_timer(0);
   4726      compl_time_slice_expired = false;
   4727      compl_timeout_ms = compl_autocomplete
   4728                         ? (uint64_t)MAX(COMPL_INITIAL_TIMEOUT_MS, p_act)
   4729                         : (uint64_t)p_cto;
   4730    }
   4731  }
   4732 
   4733  // For ^N/^P loop over all the flags/windows/buffers in 'complete'
   4734  while (true) {
   4735    found_new_match = FAIL;
   4736    st.set_match_pos = false;
   4737 
   4738    // For ^N/^P pick a new entry from e_cpt if compl_started is off,
   4739    // or if found_all says this entry is done.  For ^X^L only use the
   4740    // entries from 'complete' that look in loaded buffers.
   4741    if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
   4742        && (!compl_started || st.found_all)) {
   4743      int status = process_next_cpt_value(&st, &type, &start_pos,
   4744                                          cot_fuzzy(), &may_advance_cpt_idx);
   4745      if (status == INS_COMPL_CPT_END) {
   4746        break;
   4747      }
   4748      if (status == INS_COMPL_CPT_CONT) {
   4749        if (may_advance_cpt_idx) {
   4750          if (!advance_cpt_sources_index_safe()) {
   4751            break;
   4752          }
   4753          compl_source_start_timer(cpt_sources_index);
   4754        }
   4755        continue;
   4756      }
   4757    }
   4758 
   4759    uint64_t compl_timeout_save = 0;
   4760    if (normal_mode_strict && type == CTRL_X_FUNCTION
   4761        && (compl_autocomplete || p_cto > 0)) {
   4762      // LSP servers may sporadically take >1s to respond (e.g., while
   4763      // loading modules), but other sources might already have matches.
   4764      // To show results quickly use a short timeout for keyword
   4765      // completion. Allow longer timeout for non-keyword completion
   4766      // where only function based sources (e.g. LSP) are active.
   4767      compl_timeout_save = compl_timeout_ms;
   4768      compl_timeout_ms = compl_from_nonkeyword
   4769                         ? COMPL_FUNC_TIMEOUT_NON_KW_MS : COMPL_FUNC_TIMEOUT_MS;
   4770    }
   4771 
   4772    // get the next set of completion matches
   4773    found_new_match = get_next_completion_match(type, &st, &start_pos);
   4774 
   4775    // If complete() was called then compl_pattern has been reset.
   4776    // The following won't work then, bail out.
   4777    if (compl_pattern.data == NULL) {
   4778      break;
   4779    }
   4780 
   4781    if (may_advance_cpt_idx) {
   4782      if (!advance_cpt_sources_index_safe()) {
   4783        break;
   4784      }
   4785      compl_source_start_timer(cpt_sources_index);
   4786    }
   4787 
   4788    // break the loop for specialized modes (use 'complete' just for the
   4789    // generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new match
   4790    if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
   4791        || found_new_match != FAIL) {
   4792      if (got_int) {
   4793        break;
   4794      }
   4795      // Fill the popup menu as soon as possible.
   4796      if (type != -1) {
   4797        ins_compl_check_keys(0, false);
   4798      }
   4799 
   4800      if ((ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())
   4801          || compl_interrupted) {
   4802        break;
   4803      }
   4804      compl_started = !compl_time_slice_expired;
   4805    } else {
   4806      // Mark a buffer scanned when it has been scanned completely
   4807      if (buf_valid(st.ins_buf) && (type == 0 || type == CTRL_X_PATH_PATTERNS)) {
   4808        assert(st.ins_buf);
   4809        st.ins_buf->b_scanned = true;
   4810      }
   4811 
   4812      compl_started = false;
   4813    }
   4814 
   4815    // Restore the timeout after collecting matches from function source
   4816    if (normal_mode_strict && type == CTRL_X_FUNCTION
   4817        && (compl_autocomplete || p_cto > 0)) {
   4818      compl_timeout_ms = compl_timeout_save;
   4819    }
   4820 
   4821    // For `^P` completion, reset `compl_curr_match` to the head to avoid
   4822    // mixing matches from different sources.
   4823    if (!compl_dir_forward()) {
   4824      while (compl_curr_match->cp_prev
   4825             && !match_at_original_text(compl_curr_match->cp_prev)) {
   4826        compl_curr_match = compl_curr_match->cp_prev;
   4827      }
   4828    }
   4829  }
   4830  cpt_sources_index = -1;
   4831  compl_started = true;
   4832 
   4833  if ((ctrl_x_mode_normal() || ctrl_x_mode_line_or_eval())
   4834      && *st.e_cpt == NUL) {  // Got to end of 'complete'
   4835    found_new_match = FAIL;
   4836  }
   4837 
   4838  int match_count = -1;  // total of matches, unknown
   4839  if (found_new_match == FAIL
   4840      || (ctrl_x_mode_not_default() && !ctrl_x_mode_line_or_eval())) {
   4841    match_count = ins_compl_make_cyclic();
   4842  }
   4843 
   4844  if (cot_fuzzy() && compl_get_longest && compl_num_bests > 0) {
   4845    fuzzy_longest_match();
   4846  }
   4847 
   4848  if (compl_old_match != NULL) {
   4849    // If several matches were added (FORWARD) or the search failed and has
   4850    // just been made cyclic then we have to move compl_curr_match to the
   4851    // next or previous entry (if any) -- Acevedo
   4852    compl_curr_match = compl_dir_forward()
   4853                       ? compl_old_match->cp_next
   4854                       : compl_old_match->cp_prev;
   4855    if (compl_curr_match == NULL) {
   4856      compl_curr_match = compl_old_match;
   4857    }
   4858  }
   4859  may_trigger_modechanged();
   4860 
   4861  if (match_count > 0 && !ctrl_x_mode_spell()) {
   4862    if (is_nearest_active() && !ins_compl_has_preinsert()) {
   4863      sort_compl_match_list(cp_compare_nearest);
   4864    }
   4865 
   4866    if (cot_fuzzy() && ins_compl_leader_len() > 0) {
   4867      ins_compl_fuzzy_sort();
   4868    }
   4869  }
   4870 
   4871  return match_count;
   4872 }
   4873 
   4874 /// Update "compl_shown_match" to the actually shown match, it may differ when
   4875 /// "compl_leader" is used to omit some of the matches.
   4876 static void ins_compl_update_shown_match(void)
   4877 {
   4878  (void)get_leader_for_startcol(NULL, true);  // Clear the cache
   4879  String *leader = get_leader_for_startcol(compl_shown_match, true);
   4880 
   4881  while (!ins_compl_equal(compl_shown_match, leader->data, leader->size)
   4882         && compl_shown_match->cp_next != NULL
   4883         && !is_first_match(compl_shown_match->cp_next)) {
   4884    compl_shown_match = compl_shown_match->cp_next;
   4885    leader = get_leader_for_startcol(compl_shown_match, true);
   4886  }
   4887 
   4888  // If we didn't find it searching forward, and compl_shows_dir is
   4889  // backward, find the last match.
   4890  if (compl_shows_dir_backward()
   4891      && !ins_compl_equal(compl_shown_match, leader->data, leader->size)
   4892      && (compl_shown_match->cp_next == NULL
   4893          || is_first_match(compl_shown_match->cp_next))) {
   4894    while (!ins_compl_equal(compl_shown_match, leader->data, leader->size)
   4895           && compl_shown_match->cp_prev != NULL
   4896           && !is_first_match(compl_shown_match->cp_prev)) {
   4897      compl_shown_match = compl_shown_match->cp_prev;
   4898      leader = get_leader_for_startcol(compl_shown_match, true);
   4899    }
   4900  }
   4901 }
   4902 
   4903 /// Delete the old text being completed.
   4904 void ins_compl_delete(bool new_leader)
   4905 {
   4906  // Avoid deleting text that will be reinserted when changing leader. This
   4907  // allows marks present on the original text to shrink/grow appropriately.
   4908  int orig_col = 0;
   4909  if (new_leader) {
   4910    char *orig = compl_orig_text.data;
   4911    char *leader = ins_compl_leader();
   4912    while (*orig != NUL && utf_ptr2char(orig) == utf_ptr2char(leader)) {
   4913      leader += utf_ptr2len(leader);
   4914      orig += utf_ptr2len(orig);
   4915    }
   4916    orig_col = (int)(orig - compl_orig_text.data);
   4917  }
   4918 
   4919  // In insert mode: Delete the typed part.
   4920  // In replace mode: Put the old characters back, if any.
   4921  int col = compl_col + (compl_status_adding() ? compl_length : orig_col);
   4922 
   4923  if (ins_compl_preinsert_effect()) {
   4924    col += (int)ins_compl_leader_len();
   4925    curwin->w_cursor.col = compl_ins_end_col;
   4926  }
   4927 
   4928  String remaining = STRING_INIT;
   4929  if (curwin->w_cursor.lnum > compl_lnum) {
   4930    if (curwin->w_cursor.col < get_cursor_line_len()) {
   4931      remaining = cbuf_to_string(get_cursor_pos_ptr(), (size_t)get_cursor_pos_len());
   4932    }
   4933 
   4934    while (curwin->w_cursor.lnum > compl_lnum) {
   4935      if (ml_delete(curwin->w_cursor.lnum) == FAIL) {
   4936        if (remaining.data) {
   4937          xfree(remaining.data);
   4938        }
   4939        return;
   4940      }
   4941      deleted_lines_mark(curwin->w_cursor.lnum, 1);
   4942      curwin->w_cursor.lnum--;
   4943    }
   4944    // move cursor to end of line
   4945    curwin->w_cursor.col = get_cursor_line_len();
   4946  }
   4947 
   4948  if ((int)curwin->w_cursor.col > col) {
   4949    if (stop_arrow() == FAIL) {
   4950      if (remaining.data) {
   4951        xfree(remaining.data);
   4952      }
   4953      return;
   4954    }
   4955    backspace_until_column(col);
   4956    compl_ins_end_col = curwin->w_cursor.col;
   4957  }
   4958 
   4959  if (remaining.data != NULL) {
   4960    orig_col = curwin->w_cursor.col;
   4961    ins_str(remaining.data, remaining.size);
   4962    curwin->w_cursor.col = orig_col;
   4963    xfree(remaining.data);
   4964  }
   4965 
   4966  // TODO(vim): is this sufficient for redrawing?  Redrawing everything
   4967  // causes flicker, thus we can't do that.
   4968  changed_cline_bef_curs(curwin);
   4969  // clear v:completed_item
   4970  set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc_lock(VAR_FIXED));
   4971 }
   4972 
   4973 /// Insert a completion string that contains newlines.
   4974 /// The string is split and inserted line by line.
   4975 static void ins_compl_expand_multiple(char *str)
   4976 {
   4977  char *start = str;
   4978  char *curr = str;
   4979  int base_indent = get_indent();
   4980  while (*curr != NUL) {
   4981    if (*curr == '\n') {
   4982      // Insert the text chunk before newline
   4983      if (curr > start) {
   4984        ins_char_bytes(start, (size_t)(curr - start));
   4985      }
   4986 
   4987      // Handle newline
   4988      open_line(FORWARD, OPENLINE_KEEPTRAIL | OPENLINE_FORCE_INDENT, base_indent, NULL);
   4989      start = curr + 1;
   4990    }
   4991    curr++;
   4992  }
   4993 
   4994  // Handle remaining text after last newline (if any)
   4995  if (curr > start) {
   4996    ins_char_bytes(start, (size_t)(curr - start));
   4997  }
   4998 
   4999  compl_ins_end_col = curwin->w_cursor.col;
   5000 }
   5001 
   5002 /// Find the longest common prefix among the current completion matches.
   5003 /// Returns a pointer to the first match string, with *prefix_len set to
   5004 /// the length of the common prefix.
   5005 /// If "curbuf_only" is true, restrict matches to the current buffer
   5006 /// ('.' source in 'complete').
   5007 static char *find_common_prefix(size_t *prefix_len, bool curbuf_only)
   5008 {
   5009  bool is_cpt_completion = (cpt_sources_array != NULL);
   5010 
   5011  if (!is_cpt_completion) {
   5012    return NULL;
   5013  }
   5014 
   5015  int *match_count = xcalloc((size_t)cpt_sources_count, sizeof(int));
   5016 
   5017  (void)get_leader_for_startcol(NULL, true);  // Clear the cache
   5018 
   5019  compl_T *compl = compl_first_match;
   5020  char *first = NULL;
   5021  int len = -1;
   5022  do {
   5023    String *leader = get_leader_for_startcol(compl, true);
   5024 
   5025    // Apply 'smartcase' behavior during normal mode
   5026    if (ctrl_x_mode_normal() && !p_inf && leader->data && !ignorecase(leader->data)) {
   5027      compl->cp_flags &= ~CP_ICASE;
   5028    }
   5029 
   5030    if (!match_at_original_text(compl)
   5031        && (leader->data == NULL
   5032            || ins_compl_equal(compl, leader->data, leader->size))) {
   5033      // Limit number of items from each source if max_items is set.
   5034      bool match_limit_exceeded = false;
   5035      int cur_source = compl->cp_cpt_source_idx;
   5036 
   5037      if (cur_source != -1) {
   5038        match_count[cur_source]++;
   5039        int max_matches = cpt_sources_array[cur_source].cs_max_matches;
   5040        if (max_matches > 0 && match_count[cur_source] > max_matches) {
   5041          match_limit_exceeded = true;
   5042        }
   5043      }
   5044 
   5045      if (!match_limit_exceeded
   5046          && (!curbuf_only || cpt_sources_array[cur_source].cs_flag == '.')) {
   5047        if (first == NULL && strncmp(ins_compl_leader(), compl->cp_str.data,
   5048                                     ins_compl_leader_len()) == 0) {
   5049          first = compl->cp_str.data;
   5050          len = (int)strlen(first);
   5051        } else if (first != NULL) {
   5052          int j = 0;  // count in bytes
   5053          char *s1 = first;
   5054          char *s2 = compl->cp_str.data;
   5055 
   5056          while (j < len && *s1 != NUL && *s2 != NUL) {
   5057            if (MB_BYTE2LEN((uint8_t)(*s1)) != MB_BYTE2LEN((uint8_t)(*s2))
   5058                || memcmp(s1, s2, MB_BYTE2LEN((uint8_t)(*s1))) != 0) {
   5059              break;
   5060            }
   5061 
   5062            j += MB_BYTE2LEN((uint8_t)(*s1));
   5063            MB_PTR_ADV(s1);
   5064            MB_PTR_ADV(s2);
   5065          }
   5066          len = j;
   5067 
   5068          if (len == 0) {
   5069            break;
   5070          }
   5071        }
   5072      }
   5073    }
   5074    compl = compl->cp_next;
   5075  } while (compl != NULL && !is_first_match(compl));
   5076 
   5077  xfree(match_count);
   5078 
   5079  if (len > (int)ins_compl_leader_len()) {
   5080    assert(first != NULL);
   5081    // Avoid inserting text that duplicates the text already present
   5082    // after the cursor.
   5083    if (len == (int)strlen(first)) {
   5084      char *line = get_cursor_line_ptr();
   5085      char *p = line + curwin->w_cursor.col;
   5086      if (p && !ascii_iswhite_or_nul(*p)) {
   5087        char *end = find_word_end(p);
   5088        int text_len = (int)(end - p);
   5089        if (text_len > 0 && text_len < (len - (int)ins_compl_leader_len())
   5090            && strncmp(first + len - text_len, p, (size_t)text_len) == 0) {
   5091          len -= text_len;
   5092        }
   5093      }
   5094    }
   5095    *prefix_len = (size_t)len;
   5096    return first;
   5097  }
   5098  return NULL;
   5099 }
   5100 
   5101 /// Insert the new text being completed.
   5102 /// "move_cursor" is used when 'completeopt' includes "preinsert" and when true
   5103 /// cursor needs to move back from the inserted text to the compl_leader.
   5104 /// When "insert_prefix" is true the longest common prefix is inserted instead
   5105 /// of shown match.
   5106 void ins_compl_insert(bool move_cursor, bool insert_prefix)
   5107 {
   5108  int compl_len = get_compl_len();
   5109  bool preinsert = ins_compl_has_preinsert();
   5110  char *cp_str = compl_shown_match->cp_str.data;
   5111  size_t cp_str_len = compl_shown_match->cp_str.size;
   5112  size_t leader_len = ins_compl_leader_len();
   5113  char *has_multiple = strchr(cp_str, '\n');
   5114 
   5115  if (insert_prefix) {
   5116    cp_str = find_common_prefix(&cp_str_len, false);
   5117    if (cp_str == NULL) {
   5118      cp_str = find_common_prefix(&cp_str_len, true);
   5119      if (cp_str == NULL) {
   5120        cp_str = compl_shown_match->cp_str.data;
   5121        cp_str_len = compl_shown_match->cp_str.size;
   5122      }
   5123    }
   5124  } else if (cpt_sources_array != NULL) {
   5125    // Since completion sources may provide matches with varying start
   5126    // positions, insert only the portion of the match that corresponds to the
   5127    // intended replacement range.
   5128    int cpt_idx = compl_shown_match->cp_cpt_source_idx;
   5129    if (cpt_idx >= 0 && compl_col >= 0) {
   5130      int startcol = cpt_sources_array[cpt_idx].cs_startcol;
   5131      if (startcol >= 0 && startcol < (int)compl_col) {
   5132        int skip = (int)compl_col - startcol;
   5133        if ((size_t)skip <= cp_str_len) {
   5134          cp_str_len -= (size_t)skip;
   5135          cp_str += skip;
   5136        }
   5137      }
   5138    }
   5139  }
   5140 
   5141  // Make sure we don't go over the end of the string, this can happen with
   5142  // illegal bytes.
   5143  if (compl_len < (int)cp_str_len) {
   5144    if (has_multiple) {
   5145      ins_compl_expand_multiple(cp_str + compl_len);
   5146    } else {
   5147      ins_compl_insert_bytes(cp_str + compl_len,
   5148                             insert_prefix ? (int)cp_str_len - compl_len : -1);
   5149      if ((preinsert || insert_prefix) && move_cursor) {
   5150        curwin->w_cursor.col -= (colnr_T)(cp_str_len - leader_len);
   5151      }
   5152    }
   5153  }
   5154  compl_used_match = !(match_at_original_text(compl_shown_match)
   5155                       || (preinsert && !insert_prefix));
   5156 
   5157  dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
   5158  set_vim_var_dict(VV_COMPLETED_ITEM, dict);
   5159  compl_hi_on_autocompl_longest = insert_prefix && move_cursor;
   5160 }
   5161 
   5162 /// show the file name for the completion match (if any).  Truncate the file
   5163 /// name to avoid a wait for return.
   5164 static void ins_compl_show_filename(void)
   5165 {
   5166  char *const lead = _("match in file");
   5167  int space = sc_col - vim_strsize(lead) - 2;
   5168  if (space <= 0) {
   5169    return;
   5170  }
   5171 
   5172  // We need the tail that fits.  With double-byte encoding going
   5173  // back from the end is very slow, thus go from the start and keep
   5174  // the text that fits in "space" between "s" and "e".
   5175  char *s;
   5176  char *e;
   5177  for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) {
   5178    space -= ptr2cells(e);
   5179    while (space < 0) {
   5180      space += ptr2cells(s);
   5181      MB_PTR_ADV(s);
   5182    }
   5183  }
   5184  if (!compl_autocomplete) {
   5185    msg_hist_off = true;
   5186    vim_snprintf(IObuff, IOSIZE, "%s %s%s", lead,
   5187                 s > compl_shown_match->cp_fname ? "<" : "", s);
   5188    msg(IObuff, 0);
   5189    msg_hist_off = false;
   5190    redraw_cmdline = false;  // don't overwrite!
   5191  }
   5192 }
   5193 
   5194 /// Find the appropriate completion item when 'complete' ('cpt') includes
   5195 /// a 'max_matches' postfix. In this case, we search for a match where
   5196 /// 'cp_in_match_array' is set, indicating that the match is also present
   5197 /// in 'compl_match_array'.
   5198 static compl_T *find_next_match_in_menu(void)
   5199 {
   5200  bool is_forward = compl_shows_dir_forward();
   5201  compl_T *match = compl_shown_match;
   5202 
   5203  do {
   5204    match = is_forward ? match->cp_next : match->cp_prev;
   5205  } while (match->cp_next && !match->cp_in_match_array
   5206           && !match_at_original_text(match));
   5207  return match;
   5208 }
   5209 
   5210 /// Find the next set of matches for completion. Repeat the completion "todo"
   5211 /// times.  The number of matches found is returned in 'num_matches'.
   5212 ///
   5213 /// @param allow_get_expansion  If true, then ins_compl_get_exp() may be called to
   5214 ///                             get more completions.
   5215 ///                             If false, then do nothing when there are no more
   5216 ///                             completions in the given direction.
   5217 /// @param todo  repeat completion this many times
   5218 /// @param advance  If true, then completion will move to the first match.
   5219 ///                 Otherwise, the original text will be shown.
   5220 ///
   5221 /// @return  OK on success and -1 if the number of matches are unknown.
   5222 static int find_next_completion_match(bool allow_get_expansion, int todo, bool advance,
   5223                                      int *num_matches)
   5224 {
   5225  bool found_end = false;
   5226  compl_T *found_compl = NULL;
   5227  unsigned cur_cot_flags = get_cot_flags();
   5228  bool compl_no_select = (cur_cot_flags & kOptCotFlagNoselect) != 0
   5229                         || (compl_autocomplete && !ins_compl_has_preinsert());
   5230 
   5231  while (--todo >= 0) {
   5232    if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) {
   5233      if (compl_match_array != NULL) {
   5234        compl_shown_match = find_next_match_in_menu();
   5235      } else {
   5236        compl_shown_match = compl_shown_match->cp_next;
   5237      }
   5238      found_end = (compl_first_match != NULL
   5239                   && (is_first_match(compl_shown_match->cp_next)
   5240                       || is_first_match(compl_shown_match)));
   5241    } else if (compl_shows_dir_backward()
   5242               && compl_shown_match->cp_prev != NULL) {
   5243      found_end = is_first_match(compl_shown_match);
   5244      if (compl_match_array != NULL) {
   5245        compl_shown_match = find_next_match_in_menu();
   5246      } else {
   5247        compl_shown_match = compl_shown_match->cp_prev;
   5248      }
   5249      found_end |= is_first_match(compl_shown_match);
   5250    } else {
   5251      if (!allow_get_expansion) {
   5252        if (advance) {
   5253          if (compl_shows_dir_backward()) {
   5254            compl_pending -= todo + 1;
   5255          } else {
   5256            compl_pending += todo + 1;
   5257          }
   5258        }
   5259        return -1;
   5260      }
   5261 
   5262      if (!compl_no_select && advance) {
   5263        if (compl_shows_dir_backward()) {
   5264          compl_pending--;
   5265        } else {
   5266          compl_pending++;
   5267        }
   5268      }
   5269 
   5270      // Find matches.
   5271      *num_matches = ins_compl_get_exp(&compl_startpos);
   5272 
   5273      // handle any pending completions
   5274      while (compl_pending != 0 && compl_direction == compl_shows_dir
   5275             && advance) {
   5276        if (compl_pending > 0 && compl_shown_match->cp_next != NULL) {
   5277          compl_shown_match = compl_shown_match->cp_next;
   5278          compl_pending--;
   5279        }
   5280        if (compl_pending < 0 && compl_shown_match->cp_prev != NULL) {
   5281          compl_shown_match = compl_shown_match->cp_prev;
   5282          compl_pending++;
   5283        } else {
   5284          break;
   5285        }
   5286      }
   5287      found_end = false;
   5288    }
   5289 
   5290    String *leader = get_leader_for_startcol(compl_shown_match, false);
   5291 
   5292    if (!match_at_original_text(compl_shown_match)
   5293        && leader->data != NULL
   5294        && !ins_compl_equal(compl_shown_match, leader->data, leader->size)
   5295        && !(cot_fuzzy() && compl_shown_match->cp_score != FUZZY_SCORE_NONE)) {
   5296      todo++;
   5297    } else {
   5298      // Remember a matching item.
   5299      found_compl = compl_shown_match;
   5300    }
   5301 
   5302    // Stop at the end of the list when we found a usable match.
   5303    if (found_end) {
   5304      if (found_compl != NULL) {
   5305        compl_shown_match = found_compl;
   5306        break;
   5307      }
   5308      todo = 1;             // use first usable match after wrapping around
   5309    }
   5310  }
   5311 
   5312  return OK;
   5313 }
   5314 
   5315 /// Fill in the next completion in the current direction.
   5316 /// If "allow_get_expansion" is true, then we may call ins_compl_get_exp() to
   5317 /// get more completions.  If it is false, then we just do nothing when there
   5318 /// are no more completions in a given direction.  The latter case is used when
   5319 /// we are still in the middle of finding completions, to allow browsing
   5320 /// through the ones found so far.
   5321 /// @return  the total number of matches, or -1 if still unknown -- webb.
   5322 ///
   5323 /// compl_curr_match is currently being used by ins_compl_get_exp(), so we use
   5324 /// compl_shown_match here.
   5325 ///
   5326 /// Note that this function may be called recursively once only.  First with
   5327 /// "allow_get_expansion" true, which calls ins_compl_get_exp(), which in turn
   5328 /// calls this function with "allow_get_expansion" false.
   5329 ///
   5330 /// @param count          Repeat completion this many times; should be at least 1
   5331 /// @param insert_match   Insert the newly selected match
   5332 static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match)
   5333 {
   5334  int num_matches = -1;
   5335  int todo = count;
   5336  const bool started = compl_started;
   5337  buf_T *const orig_curbuf = curbuf;
   5338  unsigned cur_cot_flags = get_cot_flags();
   5339  bool compl_no_insert = (cur_cot_flags & kOptCotFlagNoinsert) != 0
   5340                         || (compl_autocomplete && !ins_compl_has_preinsert());
   5341  bool compl_preinsert = ins_compl_has_preinsert();
   5342  bool has_autocomplete_delay = (compl_autocomplete && p_acl > 0);
   5343 
   5344  // When user complete function return -1 for findstart which is next
   5345  // time of 'always', compl_shown_match become NULL.
   5346  if (compl_shown_match == NULL) {
   5347    return -1;
   5348  }
   5349 
   5350  if (compl_leader.data != NULL
   5351      && !match_at_original_text(compl_shown_match)
   5352      && !cot_fuzzy()) {
   5353    // Update "compl_shown_match" to the actually shown match
   5354    ins_compl_update_shown_match();
   5355  }
   5356 
   5357  if (allow_get_expansion && insert_match
   5358      && (!compl_get_longest || compl_used_match)) {
   5359    // Delete old text to be replaced
   5360    ins_compl_delete(false);
   5361  }
   5362 
   5363  // When finding the longest common text we stick at the original text,
   5364  // don't let CTRL-N or CTRL-P move to the first match.
   5365  bool advance = count != 1 || !allow_get_expansion || !compl_get_longest;
   5366 
   5367  // When restarting the search don't insert the first match either.
   5368  if (compl_restarting) {
   5369    advance = false;
   5370    compl_restarting = false;
   5371  }
   5372 
   5373  // Repeat this for when <PageUp> or <PageDown> is typed.  But don't wrap
   5374  // around.
   5375  if (find_next_completion_match(allow_get_expansion, todo, advance,
   5376                                 &num_matches) == -1) {
   5377    return -1;
   5378  }
   5379 
   5380  if (curbuf != orig_curbuf) {
   5381    // In case some completion function switched buffer, don't want to
   5382    // insert the completion elsewhere.
   5383    return -1;
   5384  }
   5385 
   5386  // Insert the text of the new completion, or the compl_leader.
   5387  if (!started && ins_compl_preinsert_longest()) {
   5388    ins_compl_insert(true, true);
   5389    if (has_autocomplete_delay) {
   5390      update_screen();  // Show the inserted text right away
   5391    }
   5392  } else if (compl_no_insert && !started && !compl_preinsert) {
   5393    ins_compl_insert_bytes(compl_orig_text.data + get_compl_len(), -1);
   5394    compl_used_match = false;
   5395    restore_orig_extmarks();
   5396  } else if (insert_match) {
   5397    if (!compl_get_longest || compl_used_match) {
   5398      bool preinsert_longest = ins_compl_preinsert_longest()
   5399                               && match_at_original_text(compl_shown_match);  // none selected
   5400      ins_compl_insert(compl_preinsert || preinsert_longest, preinsert_longest);
   5401    } else {
   5402      assert(compl_leader.data != NULL);
   5403      ins_compl_insert_bytes(compl_leader.data + get_compl_len(), -1);
   5404    }
   5405    if (strequal(compl_shown_match->cp_str.data, compl_orig_text.data)) {
   5406      restore_orig_extmarks();
   5407    }
   5408  } else {
   5409    compl_used_match = false;
   5410  }
   5411 
   5412  if (!allow_get_expansion) {
   5413    // redraw to show the user what was inserted
   5414    update_screen();  // TODO(bfredl): no!
   5415 
   5416    if (!has_autocomplete_delay) {
   5417      // display the updated popup menu
   5418      ins_compl_show_pum();
   5419    }
   5420 
   5421    // Delete old text to be replaced, since we're still searching and
   5422    // don't want to match ourselves!
   5423    ins_compl_delete(false);
   5424  }
   5425 
   5426  // Enter will select a match when the match wasn't inserted and the popup
   5427  // menu is visible.
   5428  if (compl_no_insert && !started && !match_at_original_text(compl_shown_match)) {
   5429    compl_enter_selects = true;
   5430  } else {
   5431    compl_enter_selects = !insert_match && compl_match_array != NULL;
   5432  }
   5433 
   5434  // Show the file name for the match (if any)
   5435  if (compl_shown_match->cp_fname != NULL) {
   5436    ins_compl_show_filename();
   5437  }
   5438 
   5439  return num_matches;
   5440 }
   5441 
   5442 /// Check if the current completion source exceeded its timeout. If so, stop
   5443 /// collecting, and halve the timeout.
   5444 static void check_elapsed_time(void)
   5445 {
   5446  uint64_t start_tv = cpt_sources_array[cpt_sources_index].compl_start_tv;
   5447  uint64_t elapsed_ms = (os_hrtime() - start_tv) / 1000000;
   5448 
   5449  if (elapsed_ms > compl_timeout_ms) {
   5450    compl_time_slice_expired = true;
   5451    DECAY_COMPL_TIMEOUT();
   5452  }
   5453 }
   5454 
   5455 /// Call this while finding completions, to check whether the user has hit a key
   5456 /// that should change the currently displayed completion, or exit completion
   5457 /// mode.  Also, when compl_pending is not zero, show a completion as soon as
   5458 /// possible. -- webb
   5459 ///
   5460 /// @param frequency      specifies out of how many calls we actually check.
   5461 /// @param in_compl_func  true when called from complete_check(), don't set
   5462 ///                       compl_curr_match.
   5463 void ins_compl_check_keys(int frequency, bool in_compl_func)
   5464 {
   5465  static int count = 0;
   5466 
   5467  // Don't check when reading keys from a script, :normal or feedkeys().
   5468  // That would break the test scripts.  But do check for keys when called
   5469  // from complete_check().
   5470  if (!in_compl_func && (using_script() || ex_normal_busy)) {
   5471    return;
   5472  }
   5473 
   5474  // Only do this at regular intervals
   5475  if (++count < frequency) {
   5476    return;
   5477  }
   5478  count = 0;
   5479 
   5480  // Check for a typed key.  Do use mappings, otherwise vim_is_ctrl_x_key()
   5481  // can't do its work correctly.
   5482  int c = vpeekc_any();
   5483  if (c != NUL && !test_disable_char_avail) {
   5484    if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) {
   5485      c = safe_vgetc();         // Eat the character
   5486      compl_shows_dir = ins_compl_key2dir(c);
   5487      ins_compl_next(false, ins_compl_key2count(c), c != K_UP && c != K_DOWN);
   5488    } else {
   5489      // Need to get the character to have KeyTyped set.  We'll put it
   5490      // back with vungetc() below.  But skip K_IGNORE.
   5491      c = safe_vgetc();
   5492      if (c != K_IGNORE) {
   5493        // Don't interrupt completion when the character wasn't typed,
   5494        // e.g., when doing @q to replay keys.
   5495        if (c != Ctrl_R && KeyTyped) {
   5496          compl_interrupted = true;
   5497        }
   5498 
   5499        vungetc(c);
   5500      }
   5501    }
   5502  } else {
   5503    bool normal_mode_strict = ctrl_x_mode_normal() && !ctrl_x_mode_line_or_eval()
   5504                              && !(compl_cont_status & CONT_LOCAL)
   5505                              && cpt_sources_array != NULL && cpt_sources_index >= 0;
   5506    if (normal_mode_strict && (compl_autocomplete || p_cto > 0)) {
   5507      check_elapsed_time();
   5508    }
   5509  }
   5510 
   5511  if (compl_pending
   5512      && !got_int
   5513      && !(cot_flags & (kOptCotFlagNoinsert | kOptCotFlagFuzzy))
   5514      && (!compl_autocomplete || ins_compl_has_preinsert())) {
   5515    // Insert the first match immediately and advance compl_shown_match,
   5516    // before finding other matches.
   5517    int todo = compl_pending > 0 ? compl_pending : -compl_pending;
   5518 
   5519    compl_pending = 0;
   5520    ins_compl_next(false, todo, true);
   5521  }
   5522 }
   5523 
   5524 /// Decide the direction of Insert mode complete from the key typed.
   5525 /// Returns BACKWARD or FORWARD.
   5526 static int ins_compl_key2dir(int c)
   5527 {
   5528  if (c == K_EVENT || c == K_COMMAND || c == K_LUA) {
   5529    return pum_want.item < compl_selected_item ? BACKWARD : FORWARD;
   5530  }
   5531  if (c == Ctrl_P || c == Ctrl_L
   5532      || c == K_PAGEUP || c == K_KPAGEUP
   5533      || c == K_S_UP || c == K_UP) {
   5534    return BACKWARD;
   5535  }
   5536  return FORWARD;
   5537 }
   5538 
   5539 /// Check that "c" is a valid completion key only while the popup menu is shown
   5540 ///
   5541 /// @param  c  character to check
   5542 static bool ins_compl_pum_key(int c)
   5543  FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
   5544 {
   5545  return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
   5546                           || c == K_PAGEDOWN || c == K_KPAGEDOWN
   5547                           || c == K_S_DOWN || c == K_UP || c == K_DOWN);
   5548 }
   5549 
   5550 /// Decide the number of completions to move forward.
   5551 /// Returns 1 for most keys, height of the popup menu for page-up/down keys.
   5552 static int ins_compl_key2count(int c)
   5553 {
   5554  if (c == K_EVENT || c == K_COMMAND || c == K_LUA) {
   5555    int offset = pum_want.item - compl_selected_item;
   5556    return abs(offset);
   5557  }
   5558 
   5559  if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN) {
   5560    int h = pum_get_height();
   5561    if (h > 3) {
   5562      h -= 2;       // keep some context
   5563    }
   5564    return h;
   5565  }
   5566  return 1;
   5567 }
   5568 
   5569 /// Check that completion with "c" should insert the match, false if only
   5570 /// to change the currently selected completion.
   5571 ///
   5572 /// @param  c  character to check
   5573 static bool ins_compl_use_match(int c)
   5574  FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
   5575 {
   5576  switch (c) {
   5577  case K_UP:
   5578  case K_DOWN:
   5579  case K_PAGEDOWN:
   5580  case K_KPAGEDOWN:
   5581  case K_S_DOWN:
   5582  case K_PAGEUP:
   5583  case K_KPAGEUP:
   5584  case K_S_UP:
   5585    return false;
   5586  case K_EVENT:
   5587  case K_COMMAND:
   5588  case K_LUA:
   5589    return pum_want.active && pum_want.insert;
   5590  }
   5591  return true;
   5592 }
   5593 
   5594 /// Get the pattern, column and length for normal completion (CTRL-N CTRL-P
   5595 /// completion)
   5596 /// Sets the global variables: compl_col, compl_length and compl_pattern.
   5597 /// Uses the global variables: compl_cont_status and ctrl_x_mode
   5598 static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
   5599 {
   5600  if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) {
   5601    if (!compl_status_adding()) {
   5602      while (--startcol >= 0 && vim_isIDc((uint8_t)line[startcol])) {}
   5603      compl_col += ++startcol;
   5604      compl_length = curs_col - startcol;
   5605    }
   5606    if (p_ic) {
   5607      compl_pattern = cstr_as_string(str_foldcase(line + compl_col,
   5608                                                  compl_length, NULL, 0));
   5609    } else {
   5610      compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
   5611    }
   5612  } else if (compl_status_adding()) {
   5613    char *prefix = "\\<";
   5614    size_t prefixlen = STRLEN_LITERAL("\\<");
   5615 
   5616    if (!vim_iswordp(line + compl_col)
   5617        || (compl_col > 0
   5618            && (vim_iswordp(mb_prevptr(line, line + compl_col))))) {
   5619      prefix = "";
   5620      prefixlen = 0;
   5621    }
   5622 
   5623    // we need up to 2 extra chars for the prefix
   5624    size_t n = quote_meta(NULL, line + compl_col, compl_length) + prefixlen;
   5625    compl_pattern.data = xmalloc(n);
   5626    STRCPY(compl_pattern.data, prefix);
   5627    quote_meta(compl_pattern.data + prefixlen, line + compl_col, compl_length);
   5628    compl_pattern.size = n - 1;
   5629  } else if (--startcol < 0
   5630             || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) {
   5631    // Match any word of at least two chars
   5632    compl_pattern = cbuf_to_string(S_LEN("\\<\\k\\k"));
   5633    compl_col += curs_col;
   5634    compl_length = 0;
   5635    compl_from_nonkeyword = true;
   5636  } else {
   5637    // Search the point of change class of multibyte character
   5638    // or not a word single byte character backward.
   5639    startcol -= utf_head_off(line, line + startcol);
   5640    int base_class = mb_get_class(line + startcol);
   5641    while (--startcol >= 0) {
   5642      int head_off = utf_head_off(line, line + startcol);
   5643      if (base_class != mb_get_class(line + startcol - head_off)) {
   5644        break;
   5645      }
   5646      startcol -= head_off;
   5647    }
   5648 
   5649    compl_col += ++startcol;
   5650    compl_length = (int)curs_col - startcol;
   5651    if (compl_length == 1) {
   5652      // Only match word with at least two chars -- webb
   5653      // there's no need to call quote_meta,
   5654      // xmalloc(7) is enough  -- Acevedo
   5655      compl_pattern.data = xmalloc(7);
   5656      STRCPY(compl_pattern.data, "\\<");
   5657      quote_meta(compl_pattern.data + 2, line + compl_col, 1);
   5658      strcat(compl_pattern.data, "\\k");
   5659      compl_pattern.size = strlen(compl_pattern.data);
   5660    } else {
   5661      size_t n = quote_meta(NULL, line + compl_col, compl_length) + 2;
   5662      compl_pattern.data = xmalloc(n);
   5663      STRCPY(compl_pattern.data, "\\<");
   5664      quote_meta(compl_pattern.data + 2, line + compl_col, compl_length);
   5665      compl_pattern.size = n - 1;
   5666    }
   5667  }
   5668 
   5669  // Call functions in 'complete' with 'findstart=1'
   5670  if (ctrl_x_mode_normal() && !(compl_cont_status & CONT_LOCAL)) {
   5671    // ^N completion, not complete() or ^X^N
   5672    setup_cpt_sources();
   5673    prepare_cpt_compl_funcs();
   5674  }
   5675 
   5676  return OK;
   5677 }
   5678 
   5679 /// Get the pattern, column and length for whole line completion or for the
   5680 /// complete() function.
   5681 /// Sets the global variables: compl_col, compl_length and compl_pattern.
   5682 static int get_wholeline_compl_info(char *line, colnr_T curs_col)
   5683 {
   5684  compl_col = (colnr_T)getwhitecols(line);
   5685  compl_length = (int)curs_col - (int)compl_col;
   5686  if (compl_length < 0) {  // cursor in indent: empty pattern
   5687    compl_length = 0;
   5688  }
   5689  if (p_ic) {
   5690    compl_pattern = cstr_as_string(str_foldcase(line + compl_col,
   5691                                                compl_length, NULL, 0));
   5692  } else {
   5693    compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
   5694  }
   5695 
   5696  return OK;
   5697 }
   5698 
   5699 /// Get the pattern, column and length for filename completion.
   5700 /// Sets the global variables: compl_col, compl_length and compl_pattern.
   5701 static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
   5702 {
   5703  // Go back to just before the first filename character.
   5704  if (startcol > 0) {
   5705    char *p = line + startcol;
   5706 
   5707    MB_PTR_BACK(line, p);
   5708    while (p > line && vim_isfilec(utf_ptr2char(p))) {
   5709      MB_PTR_BACK(line, p);
   5710    }
   5711    bool p_is_filec = false;
   5712 #ifdef MSWIN
   5713    // check for drive letters on mswin
   5714    if (p > line && path_has_drive_letter(p - 1, line + startcol - (p - 1))) {
   5715      p -= p == line + 1 ? 1 : 2;
   5716      p_is_filec = true;
   5717    }
   5718 #endif
   5719    p_is_filec = p_is_filec || vim_isfilec(utf_ptr2char(p));
   5720 
   5721    if (p == line && p_is_filec) {
   5722      startcol = 0;
   5723    } else {
   5724      startcol = (int)(p - line) + 1;
   5725    }
   5726  }
   5727 
   5728  compl_col += startcol;
   5729  compl_length = (int)curs_col - startcol;
   5730  compl_pattern = cstr_as_string(addstar(line + compl_col,
   5731                                         (size_t)compl_length, EXPAND_FILES));
   5732 
   5733  return OK;
   5734 }
   5735 
   5736 /// Get the pattern, column and length for command-line completion.
   5737 /// Sets the global variables: compl_col, compl_length and compl_pattern.
   5738 static int get_cmdline_compl_info(char *line, colnr_T curs_col)
   5739 {
   5740  compl_pattern = cbuf_to_string(line, (size_t)curs_col);
   5741  set_cmd_context(&compl_xp, compl_pattern.data,
   5742                  (int)compl_pattern.size, curs_col, false);
   5743  if (compl_xp.xp_context == EXPAND_LUA) {
   5744    nlua_expand_pat(&compl_xp);
   5745  }
   5746  if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
   5747      || compl_xp.xp_context == EXPAND_NOTHING) {
   5748    // No completion possible, use an empty pattern to get a
   5749    // "pattern not found" message.
   5750    compl_col = curs_col;
   5751  } else {
   5752    compl_col = (int)(compl_xp.xp_pattern - compl_pattern.data);
   5753  }
   5754  compl_length = curs_col - compl_col;
   5755 
   5756  return OK;
   5757 }
   5758 
   5759 /// Set global variables related to completion:
   5760 /// compl_col, compl_length, compl_pattern, and cpt_compl_pattern.
   5761 static void set_compl_globals(int startcol, colnr_T curs_col, bool is_cpt_compl)
   5762 {
   5763  if (is_cpt_compl) {
   5764    API_CLEAR_STRING(cpt_compl_pattern);
   5765    if (startcol < compl_col) {
   5766      prepend_startcol_text(&cpt_compl_pattern, &compl_orig_text, startcol);
   5767      return;
   5768    } else {
   5769      cpt_compl_pattern = copy_string(compl_orig_text, NULL);
   5770    }
   5771  } else {
   5772    if (startcol < 0 || startcol > curs_col) {
   5773      startcol = curs_col;
   5774    }
   5775 
   5776    // Re-obtain line in case it has changed
   5777    char *line = ml_get(curwin->w_cursor.lnum);
   5778    int len = curs_col - startcol;
   5779 
   5780    compl_pattern = cbuf_to_string(line + startcol, (size_t)len);
   5781    compl_col = startcol;
   5782    compl_length = len;
   5783  }
   5784 }
   5785 
   5786 /// Get the pattern, column and length for user defined completion ('omnifunc',
   5787 /// 'completefunc' and 'thesaurusfunc')
   5788 /// Uses the global variable: spell_bad_len
   5789 ///
   5790 /// @param cb        set if triggered by a function in the 'cpt' option, otherwise NULL
   5791 /// @param startcol  when not NULL, contains the column returned by function.
   5792 static int get_userdefined_compl_info(colnr_T curs_col, Callback *cb, int *startcol)
   5793 {
   5794  // Call user defined function 'completefunc' with "a:findstart"
   5795  // set to 1 to obtain the length of text to use for completion.
   5796  const int save_State = State;
   5797 
   5798  const bool is_cpt_function = (cb != NULL);
   5799  if (!is_cpt_function) {
   5800    // Call 'completefunc' or 'omnifunc' or 'thesaurusfunc' and get pattern
   5801    // length as a string
   5802    char *funcname = get_complete_funcname(ctrl_x_mode);
   5803    if (*funcname == NUL) {
   5804      semsg(_(e_notset), ctrl_x_mode_function() ? "completefunc" : "omnifunc");
   5805      return FAIL;
   5806    }
   5807    cb = get_insert_callback(ctrl_x_mode);
   5808  }
   5809 
   5810  typval_T args[3];
   5811  args[0].v_type = VAR_NUMBER;
   5812  args[1].v_type = VAR_STRING;
   5813  args[2].v_type = VAR_UNKNOWN;
   5814  args[0].vval.v_number = 1;
   5815  args[1].vval.v_string = "";
   5816 
   5817  pos_T pos = curwin->w_cursor;
   5818  textlock++;
   5819  colnr_T col = (colnr_T)callback_call_retnr(cb, 2, args);
   5820  textlock--;
   5821 
   5822  State = save_State;
   5823  curwin->w_cursor = pos;  // restore the cursor position
   5824  check_cursor(curwin);  // make sure cursor position is valid, just in case
   5825  validate_cursor(curwin);
   5826  if (!equalpos(curwin->w_cursor, pos)) {
   5827    emsg(_(e_compldel));
   5828    return FAIL;
   5829  }
   5830 
   5831  if (startcol != NULL) {
   5832    *startcol = col;
   5833  }
   5834 
   5835  // Return value -2 means the user complete function wants to cancel the
   5836  // complete without an error, do the same if the function did not execute
   5837  // successfully.
   5838  if (col == -2 || aborting()) {
   5839    return FAIL;
   5840  }
   5841 
   5842  // Return value -3 does the same as -2 and leaves CTRL-X mode.
   5843  if (col == -3) {
   5844    if (is_cpt_function) {
   5845      return FAIL;
   5846    }
   5847    ctrl_x_mode = CTRL_X_NORMAL;
   5848    edit_submode = NULL;
   5849    if (!shortmess(SHM_COMPLETIONMENU)) {
   5850      msg_clr_cmdline();
   5851    }
   5852    return FAIL;
   5853  }
   5854 
   5855  // Reset extended parameters of completion, when starting new
   5856  // completion.
   5857  compl_opt_refresh_always = false;
   5858 
   5859  if (!is_cpt_function) {
   5860    set_compl_globals(col, curs_col, false);
   5861  }
   5862  return OK;
   5863 }
   5864 
   5865 /// Get the pattern, column and length for spell completion.
   5866 /// Sets the global variables: compl_col, compl_length and compl_pattern.
   5867 /// Uses the global variable: spell_bad_len
   5868 static int get_spell_compl_info(int startcol, colnr_T curs_col)
   5869 {
   5870  if (spell_bad_len > 0) {
   5871    assert(spell_bad_len <= INT_MAX);
   5872    compl_col = curs_col - (int)spell_bad_len;
   5873  } else {
   5874    compl_col = spell_word_start(startcol);
   5875  }
   5876  if (compl_col >= (colnr_T)startcol) {
   5877    compl_length = 0;
   5878    compl_col = curs_col;
   5879  } else {
   5880    spell_expand_check_cap(compl_col);
   5881    compl_length = (int)curs_col - compl_col;
   5882  }
   5883  // Need to obtain "line" again, it may have become invalid.
   5884  char *line = ml_get(curwin->w_cursor.lnum);
   5885  compl_pattern = cbuf_to_string(line + compl_col, (size_t)compl_length);
   5886 
   5887  return OK;
   5888 }
   5889 
   5890 /// Get the completion pattern, column and length.
   5891 ///
   5892 /// @param startcol  start column number of the completion pattern/text
   5893 /// @param cur_col   current cursor column
   5894 ///
   5895 /// On return, "line_invalid" is set to true, if the current line may have
   5896 /// become invalid and needs to be fetched again.
   5897 ///
   5898 /// @return  OK on success.
   5899 static int compl_get_info(char *line, int startcol, colnr_T curs_col, bool *line_invalid)
   5900 {
   5901  if (ctrl_x_mode_normal() || ctrl_x_mode_register()
   5902      || ((ctrl_x_mode & CTRL_X_WANT_IDENT)
   5903          && !thesaurus_func_complete(ctrl_x_mode))) {
   5904    if (get_normal_compl_info(line, startcol, curs_col) != OK) {
   5905      return FAIL;
   5906    }
   5907    *line_invalid = true;  // 'cpt' func may have invalidated "line"
   5908  } else if (ctrl_x_mode_line_or_eval()) {
   5909    return get_wholeline_compl_info(line, curs_col);
   5910  } else if (ctrl_x_mode_files()) {
   5911    return get_filename_compl_info(line, startcol, curs_col);
   5912  } else if (ctrl_x_mode == CTRL_X_CMDLINE) {
   5913    return get_cmdline_compl_info(line, curs_col);
   5914  } else if (ctrl_x_mode_function() || ctrl_x_mode_omni()
   5915             || thesaurus_func_complete(ctrl_x_mode)) {
   5916    if (get_userdefined_compl_info(curs_col, NULL, NULL) != OK) {
   5917      return FAIL;
   5918    }
   5919    *line_invalid = true;  // "line" may have become invalid
   5920  } else if (ctrl_x_mode_spell()) {
   5921    if (get_spell_compl_info(startcol, curs_col) == FAIL) {
   5922      return FAIL;
   5923    }
   5924    *line_invalid = true;  // "line" may have become invalid
   5925  } else {
   5926    internal_error("ins_complete()");
   5927    return FAIL;
   5928  }
   5929 
   5930  return OK;
   5931 }
   5932 
   5933 /// Continue an interrupted completion mode search in "line".
   5934 ///
   5935 /// If this same ctrl_x_mode has been interrupted use the text from
   5936 /// "compl_startpos" to the cursor as a pattern to add a new word instead of
   5937 /// expand the one before the cursor, in word-wise if "compl_startpos" is not in
   5938 /// the same line as the cursor then fix it (the line has been split because it
   5939 /// was longer than 'tw').  if SOL is set then skip the previous pattern, a word
   5940 /// at the beginning of the line has been inserted, we'll look for that.
   5941 static void ins_compl_continue_search(char *line)
   5942 {
   5943  // it is a continued search
   5944  compl_cont_status &= ~CONT_INTRPT;  // remove INTRPT
   5945  if (ctrl_x_mode_normal()
   5946      || ctrl_x_mode_path_patterns()
   5947      || ctrl_x_mode_path_defines()) {
   5948    if (compl_startpos.lnum != curwin->w_cursor.lnum) {
   5949      // line (probably) wrapped, set compl_startpos to the
   5950      // first non_blank in the line, if it is not a wordchar
   5951      // include it to get a better pattern, but then we don't
   5952      // want the "\\<" prefix, check it below.
   5953      compl_col = (colnr_T)getwhitecols(line);
   5954      compl_startpos.col = compl_col;
   5955      compl_startpos.lnum = curwin->w_cursor.lnum;
   5956      compl_cont_status &= ~CONT_SOL;  // clear SOL if present
   5957    } else {
   5958      // S_IPOS was set when we inserted a word that was at the
   5959      // beginning of the line, which means that we'll go to SOL
   5960      // mode but first we need to redefine compl_startpos
   5961      if (compl_cont_status & CONT_S_IPOS) {
   5962        compl_cont_status |= CONT_SOL;
   5963        compl_startpos.col = (colnr_T)(skipwhite(line + compl_length + compl_startpos.col) - line);
   5964      }
   5965      compl_col = compl_startpos.col;
   5966    }
   5967    compl_length = curwin->w_cursor.col - (int)compl_col;
   5968    // IObuff is used to add a "word from the next line" would we
   5969    // have enough space?  just being paranoid
   5970 #define MIN_SPACE 75
   5971    if (compl_length > (IOSIZE - MIN_SPACE)) {
   5972      compl_cont_status &= ~CONT_SOL;
   5973      compl_length = (IOSIZE - MIN_SPACE);
   5974      compl_col = curwin->w_cursor.col - compl_length;
   5975    }
   5976    compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
   5977    if (compl_length < 1) {
   5978      compl_cont_status &= CONT_LOCAL;
   5979    }
   5980  } else if (ctrl_x_mode_line_or_eval() || ctrl_x_mode_register()) {
   5981    compl_cont_status = CONT_ADDING | CONT_N_ADDS;
   5982  } else {
   5983    compl_cont_status = 0;
   5984  }
   5985 }
   5986 
   5987 /// start insert mode completion
   5988 static int ins_compl_start(void)
   5989 {
   5990  const bool save_did_ai = did_ai;
   5991 
   5992  // First time we hit ^N or ^P (in a row, I mean)
   5993 
   5994  did_ai = false;
   5995  did_si = false;
   5996  can_si = false;
   5997  can_si_back = false;
   5998  if (stop_arrow() == FAIL) {
   5999    did_ai = save_did_ai;
   6000    return FAIL;
   6001  }
   6002 
   6003  char *line = ml_get(curwin->w_cursor.lnum);
   6004  colnr_T curs_col = curwin->w_cursor.col;
   6005  compl_pending = 0;
   6006  compl_lnum = curwin->w_cursor.lnum;
   6007 
   6008  if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
   6009      && compl_cont_mode == ctrl_x_mode) {
   6010    // this same ctrl-x_mode was interrupted previously. Continue the
   6011    // completion.
   6012    ins_compl_continue_search(line);
   6013  } else {
   6014    compl_cont_status &= CONT_LOCAL;
   6015  }
   6016 
   6017  int startcol = 0;  // column where searched text starts
   6018  if (!compl_status_adding()) {   // normal expansion
   6019    compl_cont_mode = ctrl_x_mode;
   6020    if (ctrl_x_mode_not_default()) {
   6021      // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
   6022      compl_cont_status = 0;
   6023    }
   6024    compl_cont_status |= CONT_N_ADDS;
   6025    compl_startpos = curwin->w_cursor;
   6026    startcol = (int)curs_col;
   6027    compl_col = 0;
   6028  }
   6029 
   6030  // Work out completion pattern and original text -- webb
   6031  bool line_invalid = false;
   6032  if (compl_get_info(line, startcol, curs_col, &line_invalid) == FAIL) {
   6033    if (ctrl_x_mode_function() || ctrl_x_mode_omni()
   6034        || thesaurus_func_complete(ctrl_x_mode)) {
   6035      // restore did_ai, so that adding comment leader works
   6036      did_ai = save_did_ai;
   6037    }
   6038    return FAIL;
   6039  }
   6040  // If "line" was changed while getting completion info get it again.
   6041  if (line_invalid) {
   6042    line = ml_get(curwin->w_cursor.lnum);
   6043  }
   6044 
   6045  if (compl_status_adding()) {
   6046    if (!shortmess(SHM_COMPLETIONMENU)) {
   6047      edit_submode_pre = _(" Adding");
   6048    }
   6049    if (ctrl_x_mode_line_or_eval()) {
   6050      // Insert a new line, keep indentation but ignore 'comments'.
   6051      char *old = curbuf->b_p_com;
   6052 
   6053      curbuf->b_p_com = "";
   6054      compl_startpos.lnum = curwin->w_cursor.lnum;
   6055      compl_startpos.col = compl_col;
   6056      ins_eol('\r');
   6057      curbuf->b_p_com = old;
   6058      compl_length = 0;
   6059      compl_col = curwin->w_cursor.col;
   6060      compl_lnum = curwin->w_cursor.lnum;
   6061    }
   6062  } else {
   6063    edit_submode_pre = NULL;
   6064    compl_startpos.col = compl_col;
   6065  }
   6066 
   6067  if (!shortmess(SHM_COMPLETIONMENU) && !compl_autocomplete) {
   6068    if (compl_cont_status & CONT_LOCAL) {
   6069      edit_submode = _(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
   6070    } else {
   6071      edit_submode = _(CTRL_X_MSG(ctrl_x_mode));
   6072    }
   6073  }
   6074 
   6075  // If any of the original typed text has been changed we need to fix
   6076  // the redo buffer.
   6077  ins_compl_fixRedoBufForLeader(NULL);
   6078 
   6079  // Always add completion for the original text.
   6080  API_CLEAR_STRING(compl_orig_text);
   6081  kv_destroy(compl_orig_extmarks);
   6082  compl_orig_text = cbuf_to_string(line + compl_col, (size_t)compl_length);
   6083  save_orig_extmarks();
   6084  int flags = CP_ORIGINAL_TEXT;
   6085  if (p_ic) {
   6086    flags |= CP_ICASE;
   6087  }
   6088  if (ins_compl_add(compl_orig_text.data, (int)compl_orig_text.size,
   6089                    NULL, NULL, false, NULL, 0,
   6090                    flags, false, NULL, FUZZY_SCORE_NONE) != OK) {
   6091    API_CLEAR_STRING(compl_pattern);
   6092    API_CLEAR_STRING(compl_orig_text);
   6093    kv_destroy(compl_orig_extmarks);
   6094    did_ai = save_did_ai;
   6095    return FAIL;
   6096  }
   6097 
   6098  // showmode might reset the internal line pointers, so it must
   6099  // be called before line = ml_get(), or when this address is no
   6100  // longer needed.  -- Acevedo.
   6101  if (!shortmess(SHM_COMPLETIONMENU) && !compl_autocomplete) {
   6102    edit_submode_extra = _("-- Searching...");
   6103    edit_submode_highl = HLF_COUNT;
   6104    showmode();
   6105    edit_submode_extra = NULL;
   6106    ui_flush();
   6107  }
   6108 
   6109  did_ai = save_did_ai;
   6110  return OK;
   6111 }
   6112 
   6113 /// display the completion status message
   6114 static void ins_compl_show_statusmsg(void)
   6115 {
   6116  // we found no match if the list has only the "compl_orig_text"-entry
   6117  if (is_first_match(compl_first_match->cp_next)) {
   6118    edit_submode_extra = compl_status_adding() && compl_length > 1 ? _(e_hitend) : _(e_patnotf);
   6119    edit_submode_highl = HLF_E;
   6120  }
   6121 
   6122  if (edit_submode_extra == NULL) {
   6123    if (match_at_original_text(compl_curr_match)) {
   6124      edit_submode_extra = _("Back at original");
   6125      edit_submode_highl = HLF_W;
   6126    } else if (compl_cont_status & CONT_S_IPOS) {
   6127      edit_submode_extra = _("Word from other line");
   6128      edit_submode_highl = HLF_COUNT;
   6129    } else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) {
   6130      edit_submode_extra = _("The only match");
   6131      edit_submode_highl = HLF_COUNT;
   6132      compl_curr_match->cp_number = 1;
   6133    } else {
   6134      // Update completion sequence number when needed.
   6135      if (compl_curr_match->cp_number == -1) {
   6136        ins_compl_update_sequence_numbers();
   6137      }
   6138 
   6139      // The match should always have a sequence number now, this is
   6140      // just a safety check.
   6141      if (compl_curr_match->cp_number != -1) {
   6142        // Space for 10 text chars. + 2x10-digit no.s = 31.
   6143        // Translations may need more than twice that.
   6144        static char match_ref[81];
   6145 
   6146        if (compl_matches > 0) {
   6147          vim_snprintf(match_ref, sizeof(match_ref),
   6148                       _("match %d of %d"),
   6149                       compl_curr_match->cp_number, compl_matches);
   6150        } else {
   6151          vim_snprintf(match_ref, sizeof(match_ref),
   6152                       _("match %d"),
   6153                       compl_curr_match->cp_number);
   6154        }
   6155        edit_submode_extra = match_ref;
   6156        edit_submode_highl = HLF_R;
   6157        if (dollar_vcol >= 0) {
   6158          curs_columns(curwin, false);
   6159        }
   6160      }
   6161    }
   6162  }
   6163 
   6164  // Show a message about what (completion) mode we're in.
   6165  redraw_mode = true;
   6166  if (!shortmess(SHM_COMPLETIONMENU)) {
   6167    if (edit_submode_extra != NULL) {
   6168      if (!p_smd) {
   6169        msg_hist_off = true;
   6170        msg_ext_set_kind("completion");
   6171        msg(edit_submode_extra, (edit_submode_highl < HLF_COUNT
   6172                                 ? (int)edit_submode_highl + 1 : 0));
   6173        msg_hist_off = false;
   6174      }
   6175    } else {
   6176      msg_clr_cmdline();  // necessary for "noshowmode"
   6177    }
   6178  }
   6179 }
   6180 
   6181 /// Do Insert mode completion.
   6182 /// Called when character "c" was typed, which has a meaning for completion.
   6183 /// Returns OK if completion was done, FAIL if something failed.
   6184 int ins_complete(int c, bool enable_pum)
   6185 {
   6186  const bool disable_ac_delay = compl_started && ctrl_x_mode_normal()
   6187                                && (c == Ctrl_N || c == Ctrl_P || c == Ctrl_R
   6188                                    || ins_compl_pum_key(c));
   6189 
   6190  compl_direction = ins_compl_key2dir(c);
   6191  int insert_match = ins_compl_use_match(c);
   6192 
   6193  if (!compl_started) {
   6194    if (ins_compl_start() == FAIL) {
   6195      return FAIL;
   6196    }
   6197  } else if (insert_match && stop_arrow() == FAIL) {
   6198    return FAIL;
   6199  }
   6200 
   6201  uint64_t compl_start_tv = 0;  ///< Time when match collection starts
   6202  if (compl_autocomplete && p_acl > 0 && !disable_ac_delay) {
   6203    compl_start_tv = os_hrtime();
   6204  }
   6205  compl_curr_win = curwin;
   6206  compl_curr_buf = curwin->w_buffer;
   6207  compl_shown_match = compl_curr_match;
   6208  compl_shows_dir = compl_direction;
   6209  compl_num_bests = 0;
   6210 
   6211  // Find next match (and following matches).
   6212  int save_w_wrow = curwin->w_wrow;
   6213  int save_w_leftcol = curwin->w_leftcol;
   6214  int n = ins_compl_next(true, ins_compl_key2count(c), insert_match);
   6215 
   6216  // Reset autocompletion timer expiry flag
   6217  if (compl_autocomplete) {
   6218    compl_time_slice_expired = false;
   6219  }
   6220 
   6221  if (n > 1) {          // all matches have been found
   6222    compl_matches = n;
   6223  }
   6224  compl_curr_match = compl_shown_match;
   6225  compl_direction = compl_shows_dir;
   6226 
   6227  // Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
   6228  // mode.
   6229  if (got_int && !global_busy) {
   6230    vgetc();
   6231    got_int = false;
   6232  }
   6233 
   6234  // we found no match if the list has only the "compl_orig_text"-entry
   6235  bool no_matches_found = is_first_match(compl_first_match->cp_next);
   6236  if (no_matches_found) {
   6237    // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
   6238    // because we couldn't expand anything at first place, but if we used
   6239    // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
   6240    // (such as M in M'exico) if not tried already.  -- Acevedo
   6241    if (compl_length > 1
   6242        || compl_status_adding()
   6243        || (ctrl_x_mode_not_default()
   6244            && !ctrl_x_mode_path_patterns()
   6245            && !ctrl_x_mode_path_defines())) {
   6246      compl_cont_status &= ~CONT_N_ADDS;
   6247    }
   6248  }
   6249 
   6250  if (compl_curr_match->cp_flags & CP_CONT_S_IPOS) {
   6251    compl_cont_status |= CONT_S_IPOS;
   6252  } else {
   6253    compl_cont_status &= ~CONT_S_IPOS;
   6254  }
   6255 
   6256  if (!shortmess(SHM_COMPLETIONMENU) && !compl_autocomplete) {
   6257    ins_compl_show_statusmsg();
   6258  }
   6259 
   6260  // Wait for the autocompletion delay to expire
   6261  if (compl_autocomplete && p_acl > 0 && !disable_ac_delay && !no_matches_found
   6262      && (os_hrtime() - compl_start_tv) / 1000000 < (uint64_t)p_acl) {
   6263    setcursor();
   6264    ui_flush();
   6265    do {
   6266      if (char_avail()) {
   6267        if (ins_compl_preinsert_effect() && ins_compl_win_active(curwin)) {
   6268          ins_compl_delete(false);  // Remove pre-inserted text
   6269          compl_ins_end_col = compl_col;
   6270        }
   6271        ins_compl_restart();
   6272        compl_interrupted = true;
   6273        break;
   6274      } else {
   6275        os_delay(2L, true);
   6276      }
   6277    } while ((os_hrtime() - compl_start_tv) / 1000000 < (uint64_t)p_acl);
   6278  }
   6279 
   6280  // Show the popup menu, unless we got interrupted.
   6281  if (enable_pum && !compl_interrupted) {
   6282    show_pum(save_w_wrow, save_w_leftcol);
   6283  }
   6284  compl_was_interrupted = compl_interrupted;
   6285  compl_interrupted = false;
   6286 
   6287  return OK;
   6288 }
   6289 
   6290 /// Enable autocompletion
   6291 void ins_compl_enable_autocomplete(void)
   6292 {
   6293  compl_autocomplete = true;
   6294  compl_get_longest = false;
   6295 }
   6296 
   6297 /// Remove (if needed) and show the popup menu
   6298 static void show_pum(int prev_w_wrow, int prev_w_leftcol)
   6299 {
   6300  // RedrawingDisabled may be set when invoked through complete().
   6301  int n = RedrawingDisabled;
   6302  RedrawingDisabled = 0;
   6303 
   6304  // If the cursor moved or the display scrolled we need to remove the pum
   6305  // first.
   6306  setcursor();
   6307  if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol) {
   6308    ins_compl_del_pum();
   6309  }
   6310 
   6311  ins_compl_show_pum();
   6312  setcursor();
   6313  RedrawingDisabled = n;
   6314 }
   6315 
   6316 // Looks in the first "len" chars. of "src" for search-metachars.
   6317 // If dest is not NULL the chars. are copied there quoting (with
   6318 // a backslash) the metachars, and dest would be NUL terminated.
   6319 // Returns the length (needed) of dest
   6320 static unsigned quote_meta(char *dest, char *src, int len)
   6321 {
   6322  unsigned m = (unsigned)len + 1;       // one extra for the NUL
   6323 
   6324  for (; --len >= 0; src++) {
   6325    switch (*src) {
   6326    case '.':
   6327    case '*':
   6328    case '[':
   6329      if (ctrl_x_mode_dictionary() || ctrl_x_mode_thesaurus()) {
   6330        break;
   6331      }
   6332      FALLTHROUGH;
   6333    case '~':
   6334      if (!magic_isset()) {  // quote these only if magic is set
   6335        break;
   6336      }
   6337      FALLTHROUGH;
   6338    case '\\':
   6339      if (ctrl_x_mode_dictionary() || ctrl_x_mode_thesaurus()) {
   6340        break;
   6341      }
   6342      FALLTHROUGH;
   6343    case '^':                   // currently it's not needed.
   6344    case '$':
   6345      m++;
   6346      if (dest != NULL) {
   6347        *dest++ = '\\';
   6348      }
   6349      break;
   6350    }
   6351    if (dest != NULL) {
   6352      *dest++ = *src;
   6353    }
   6354    // Copy remaining bytes of a multibyte character.
   6355    const int mb_len = utfc_ptr2len(src) - 1;
   6356    if (mb_len > 0 && len >= mb_len) {
   6357      for (int i = 0; i < mb_len; i++) {
   6358        len--;
   6359        src++;
   6360        if (dest != NULL) {
   6361          *dest++ = *src;
   6362        }
   6363      }
   6364    }
   6365  }
   6366  if (dest != NULL) {
   6367    *dest = NUL;
   6368  }
   6369 
   6370  return m;
   6371 }
   6372 
   6373 #if defined(EXITFREE)
   6374 void free_insexpand_stuff(void)
   6375 {
   6376  API_CLEAR_STRING(compl_orig_text);
   6377  kv_destroy(compl_orig_extmarks);
   6378  callback_free(&cfu_cb);
   6379  callback_free(&ofu_cb);
   6380  callback_free(&tsrfu_cb);
   6381  clear_cpt_callbacks(&cpt_cb, cpt_cb_count);
   6382 }
   6383 #endif
   6384 
   6385 /// Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
   6386 /// spelled word, if there is one.
   6387 static void spell_back_to_badword(void)
   6388 {
   6389  pos_T tpos = curwin->w_cursor;
   6390  spell_bad_len = spell_move_to(curwin, BACKWARD, SMT_ALL, true, NULL);
   6391  if (curwin->w_cursor.col != tpos.col) {
   6392    start_arrow(&tpos);
   6393  }
   6394 }
   6395 
   6396 /// Reset the info associated with completion sources.
   6397 static void cpt_sources_clear(void)
   6398 {
   6399  XFREE_CLEAR(cpt_sources_array);
   6400  cpt_sources_index = -1;
   6401  cpt_sources_count = 0;
   6402 }
   6403 
   6404 /// Setup completion sources.
   6405 static void setup_cpt_sources(void)
   6406 {
   6407  cpt_sources_clear();
   6408 
   6409  int count = get_cpt_sources_count();
   6410  if (count == 0) {
   6411    return;
   6412  }
   6413 
   6414  cpt_sources_array = xcalloc((size_t)count, sizeof(cpt_source_T));
   6415 
   6416  char buf[LSIZE];
   6417  int idx = 0;
   6418  for (char *p = curbuf->b_p_cpt; *p;) {
   6419    while (*p == ',' || *p == ' ') {  // Skip delimiters
   6420      p++;
   6421    }
   6422    if (*p) {  // If not end of string, count this segment
   6423      cpt_sources_array[idx].cs_flag = *p;
   6424      memset(buf, 0, LSIZE);
   6425      size_t slen = copy_option_part(&p, buf, LSIZE, ",");  // Advance p
   6426      if (slen > 0) {
   6427        char *caret = vim_strchr(buf, '^');
   6428        if (caret != NULL) {
   6429          cpt_sources_array[idx].cs_max_matches = atoi(caret + 1);
   6430        }
   6431      }
   6432      idx++;
   6433    }
   6434  }
   6435 
   6436  cpt_sources_count = count;
   6437 }
   6438 
   6439 /// Return true if any of the completion sources have 'refresh' set to 'always'.
   6440 static bool is_cpt_func_refresh_always(void)
   6441 {
   6442  for (int i = 0; i < cpt_sources_count; i++) {
   6443    if (cpt_sources_array[i].cs_refresh_always) {
   6444      return true;
   6445    }
   6446  }
   6447  return false;
   6448 }
   6449 
   6450 /// Make the completion list non-cyclic.
   6451 static void ins_compl_make_linear(void)
   6452 {
   6453  if (compl_first_match == NULL || compl_first_match->cp_prev == NULL) {
   6454    return;
   6455  }
   6456  compl_T *m = compl_first_match->cp_prev;
   6457  m->cp_next = NULL;
   6458  compl_first_match->cp_prev = NULL;
   6459 }
   6460 
   6461 /// Remove the matches linked to the current completion source (as indicated by
   6462 /// cpt_sources_index) from the completion list.
   6463 static void remove_old_matches(void)
   6464 {
   6465  bool shown_match_removed = false;
   6466  bool forward = (compl_first_match->cp_cpt_source_idx < 0);
   6467 
   6468  if (cpt_sources_index < 0) {
   6469    return;
   6470  }
   6471 
   6472  compl_direction = forward ? FORWARD : BACKWARD;
   6473  compl_shows_dir = compl_direction;
   6474 
   6475  // When 'fuzzy' is enabled, items are not ordered by their original source
   6476  // order (cpt_sources_index). So, remove items one by one.
   6477  for (compl_T *current = compl_first_match; current != NULL;) {
   6478    if (current->cp_cpt_source_idx == cpt_sources_index) {
   6479      compl_T *to_delete = current;
   6480 
   6481      if (!shown_match_removed && compl_shown_match == current) {
   6482        shown_match_removed = true;
   6483      }
   6484 
   6485      current = current->cp_next;
   6486 
   6487      if (to_delete == compl_first_match) {  // node to remove is at head
   6488        compl_first_match = to_delete->cp_next;
   6489        compl_first_match->cp_prev = NULL;
   6490      } else if (to_delete->cp_next == NULL) {  // node to remove is at tail
   6491        to_delete->cp_prev->cp_next = NULL;
   6492      } else {          // node is in the moddle
   6493        to_delete->cp_prev->cp_next = to_delete->cp_next;
   6494        to_delete->cp_next->cp_prev = to_delete->cp_prev;
   6495      }
   6496      ins_compl_item_free(to_delete);
   6497    } else {
   6498      current = current->cp_next;
   6499    }
   6500  }
   6501 
   6502  // Re-assign compl_shown_match if necessary
   6503  if (shown_match_removed) {
   6504    if (forward) {
   6505      compl_shown_match = compl_first_match;
   6506    } else {    // Last node will have the prefix that is being completed
   6507      compl_T *current;
   6508      for (current = compl_first_match; current->cp_next != NULL;
   6509           current = current->cp_next) {}
   6510      compl_shown_match = current;
   6511    }
   6512  }
   6513 
   6514  // Re-assign compl_curr_match
   6515  compl_curr_match = compl_first_match;
   6516  for (compl_T *current = compl_first_match; current != NULL;) {
   6517    if ((forward ? current->cp_cpt_source_idx < cpt_sources_index
   6518                 : current->cp_cpt_source_idx > cpt_sources_index)) {
   6519      compl_curr_match = forward ? current : current->cp_next;
   6520      current = current->cp_next;
   6521    } else {
   6522      break;
   6523    }
   6524  }
   6525 }
   6526 
   6527 /// Retrieve completion matches using the callback function "cb" and store the
   6528 /// 'refresh:always' flag.
   6529 static void get_cpt_func_completion_matches(Callback *cb)
   6530 {
   6531  cpt_source_T *cpt_src = &cpt_sources_array[cpt_sources_index];
   6532  int startcol = cpt_src->cs_startcol;
   6533 
   6534  if (startcol == -2 || startcol == -3) {
   6535    return;
   6536  }
   6537 
   6538  set_compl_globals(startcol, curwin->w_cursor.col, true);
   6539 
   6540  // Insert the leader string (previously removed) before expansion.
   6541  // This prevents flicker when `func` (e.g. an LSP client) is slow and
   6542  // calls 'sleep', which triggers ui_flush().
   6543  if (!cpt_src->cs_refresh_always) {
   6544    ins_compl_insert_bytes(ins_compl_leader(), -1);
   6545  }
   6546 
   6547  expand_by_function(0, cpt_compl_pattern.data, cb);
   6548 
   6549  if (!cpt_src->cs_refresh_always) {
   6550    ins_compl_delete(false);
   6551  }
   6552 
   6553  cpt_src->cs_refresh_always = compl_opt_refresh_always;
   6554  compl_opt_refresh_always = false;
   6555 }
   6556 
   6557 /// Retrieve completion matches from functions in the 'cpt' option where the
   6558 /// 'refresh:always' flag is set.
   6559 static void cpt_compl_refresh(void)
   6560 {
   6561  // Make the completion list linear (non-cyclic)
   6562  ins_compl_make_linear();
   6563  // Make a copy of 'cpt' in case the buffer gets wiped out
   6564  char *cpt = xstrdup(curbuf->b_p_cpt);
   6565  strip_caret_numbers_in_place(cpt);
   6566 
   6567  cpt_sources_index = 0;
   6568  for (char *p = cpt; *p;) {
   6569    while (*p == ',' || *p == ' ') {  // Skip delimiters
   6570      p++;
   6571    }
   6572    if (*p == NUL) {
   6573      break;
   6574    }
   6575 
   6576    if (cpt_sources_array[cpt_sources_index].cs_refresh_always) {
   6577      Callback *cb = get_callback_if_cpt_func(p, cpt_sources_index);
   6578      if (cb) {
   6579        remove_old_matches();
   6580        int startcol;
   6581        int ret = get_userdefined_compl_info(curwin->w_cursor.col, cb, &startcol);
   6582        if (ret == FAIL) {
   6583          if (startcol == -3) {
   6584            cpt_sources_array[cpt_sources_index].cs_refresh_always = false;
   6585          } else {
   6586            startcol = -2;
   6587          }
   6588        } else if (startcol < 0 || startcol > curwin->w_cursor.col) {
   6589          startcol = curwin->w_cursor.col;
   6590        }
   6591        cpt_sources_array[cpt_sources_index].cs_startcol = startcol;
   6592        if (ret == OK) {
   6593          compl_source_start_timer(cpt_sources_index);
   6594          get_cpt_func_completion_matches(cb);
   6595        }
   6596      }
   6597    }
   6598 
   6599    (void)copy_option_part(&p, IObuff, IOSIZE, ",");  // Advance p
   6600    if (may_advance_cpt_index(p)) {
   6601      (void)advance_cpt_sources_index_safe();
   6602    }
   6603  }
   6604  cpt_sources_index = -1;
   6605 
   6606  xfree(cpt);
   6607  // Make the list cyclic
   6608  compl_matches = ins_compl_make_cyclic();
   6609 }
   6610 
   6611 /// "preinserted()" function
   6612 void f_preinserted(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
   6613 {
   6614  if (ins_compl_preinsert_effect()) {
   6615    rettv->vval.v_number = 1;
   6616  }
   6617 }