summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1076
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1076')
-rw-r--r--data/vim/patches/8.1.10769225
1 files changed, 0 insertions, 9225 deletions
diff --git a/data/vim/patches/8.1.1076 b/data/vim/patches/8.1.1076
deleted file mode 100644
index 4e18d4463..000000000
--- a/data/vim/patches/8.1.1076
+++ /dev/null
@@ -1,9225 +0,0 @@
-To: vim_dev@googlegroups.com
-Subject: Patch 8.1.1076
-Fcc: outbox
-From: Bram Moolenaar <Bram@moolenaar.net>
-Mime-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-------------
-
-Patch 8.1.1076
-Problem: File for Insert mode is much too big.
-Solution: Split off the code for Insert completion. (Yegappan Lakshmanan,
- closes #4044)
-Files: Filelist, src/Make_bc5.mak, src/Make_cyg_ming.mak,
- src/Make_dice.mak, src/Make_ivc.mak, src/Make_manx.mak,
- src/Make_morph.mak, src/Make_mvc.mak, src/Make_sas.mak,
- src/Make_vms.mms, src/Makefile, src/edit.c, src/evalfunc.c,
- src/globals.h, src/insexpand.c, src/misc2.c, src/proto.h,
- src/proto/edit.pro, src/proto/insexpand.pro, src/search.c,
- src/spell.c, src/structs.h, src/tag.c
-
-
-*** ../vim-8.1.1075/Filelist 2019-03-29 13:09:37.972782868 +0100
---- Filelist 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 48,53 ****
---- 48,54 ----
- src/hardcopy.c \
- src/hashtab.c \
- src/indent.c \
-+ src/insexpand.c \
- src/json.c \
- src/json_test.c \
- src/kword_test.c \
-***************
-*** 175,180 ****
---- 176,182 ----
- src/proto/hardcopy.pro \
- src/proto/hashtab.pro \
- src/proto/indent.pro \
-+ src/proto/insexpand.pro \
- src/proto/json.pro \
- src/proto/list.pro \
- src/proto/main.pro \
-*** ../vim-8.1.1075/src/Make_bc5.mak 2019-03-28 22:43:12.103997449 +0100
---- src/Make_bc5.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 534,539 ****
---- 534,540 ----
- $(OBJDIR)\hardcopy.obj \
- $(OBJDIR)\hashtab.obj \
- $(OBJDIR)\indent.obj \
-+ $(OBJDIR)\insexpand.obj \
- $(OBJDIR)\json.obj \
- $(OBJDIR)\list.obj \
- $(OBJDIR)\main.obj \
-*** ../vim-8.1.1075/src/Make_cyg_ming.mak 2019-03-22 16:57:42.061691287 +0100
---- src/Make_cyg_ming.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 721,726 ****
---- 721,727 ----
- $(OUTDIR)/hardcopy.o \
- $(OUTDIR)/hashtab.o \
- $(OUTDIR)/indent.o \
-+ $(OUTDIR)/insexpand.o \
- $(OUTDIR)/json.o \
- $(OUTDIR)/list.o \
- $(OUTDIR)/main.o \
-*** ../vim-8.1.1075/src/Make_dice.mak 2019-02-16 15:09:21.221946179 +0100
---- src/Make_dice.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 51,56 ****
---- 51,57 ----
- hardcopy.c \
- hashtab.c \
- indent.c \
-+ insexpand.c \
- json.c \
- list.c \
- main.c \
-***************
-*** 110,115 ****
---- 111,117 ----
- o/hardcopy.o \
- o/hashtab.o \
- o/indent.o \
-+ o/insexpand.o \
- o/json.o \
- o/list.o \
- o/main.o \
-***************
-*** 213,218 ****
---- 215,222 ----
-
- o/indent.o: indent.c $(SYMS)
-
-+ o/insexpand.o: insexpand.c $(SYMS)
-+
- o/json.o: json.c $(SYMS)
-
- o/list.o: list.c $(SYMS)
-*** ../vim-8.1.1075/src/Make_ivc.mak 2019-02-18 21:41:34.477750367 +0100
---- src/Make_ivc.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 235,240 ****
---- 235,241 ----
- "$(INTDIR)/hardcopy.obj" \
- "$(INTDIR)/hashtab.obj" \
- "$(INTDIR)/indent.obj" \
-+ "$(INTDIR)/insexpand.obj" \
- "$(INTDIR)/json.obj" \
- "$(INTDIR)/list.obj" \
- "$(INTDIR)/main.obj" \
-***************
-*** 439,444 ****
---- 440,449 ----
- SOURCE=.\indent.c
- # End Source File
- # Begin Source File
-+ #
-+ SOURCE=.\insexpand.c
-+ # End Source File
-+ # Begin Source File
-
- SOURCE=.\gui.c
-
-*** ../vim-8.1.1075/src/Make_manx.mak 2019-02-16 15:09:21.221946179 +0100
---- src/Make_manx.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 61,66 ****
---- 61,67 ----
- hardcopy.c \
- hashtab.c \
- indent.c \
-+ insexpand.c \
- json.c \
- list.c \
- main.c \
-***************
-*** 122,127 ****
---- 123,129 ----
- obj/hardcopy.o \
- obj/hashtab.o \
- obj/indent.o \
-+ obj/insexpand.o \
- obj/json.o \
- obj/list.o \
- obj/main.o \
-***************
-*** 181,186 ****
---- 183,189 ----
- proto/hardcopy.pro \
- proto/hashtab.pro \
- proto/indent.pro \
-+ proto/insexpand.pro \
- proto/json.pro \
- proto/list.pro \
- proto/main.pro \
-***************
-*** 335,340 ****
---- 338,346 ----
- obj/indent.o: indent.c
- $(CCSYM) $@ indent.c
-
-+ obj/insexpand.o: insexpand.c
-+ $(CCSYM) $@ insexpand.c
-+
- obj/json.o: json.c
- $(CCSYM) $@ json.c
-
-*** ../vim-8.1.1075/src/Make_morph.mak 2019-02-16 15:09:21.221946179 +0100
---- src/Make_morph.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 49,54 ****
---- 49,55 ----
- hardcopy.c \
- hashtab.c \
- indent.c \
-+ insexpand.c \
- json.c \
- list.c \
- main.c \
-*** ../vim-8.1.1075/src/Make_mvc.mak 2019-03-22 16:57:42.061691287 +0100
---- src/Make_mvc.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 725,730 ****
---- 725,731 ----
- $(OUTDIR)\hardcopy.obj \
- $(OUTDIR)\hashtab.obj \
- $(OUTDIR)\indent.obj \
-+ $(OUTDIR)\insexpand.obj \
- $(OUTDIR)\json.obj \
- $(OUTDIR)\list.obj \
- $(OUTDIR)\main.obj \
-***************
-*** 1416,1421 ****
---- 1417,1424 ----
-
- $(OUTDIR)/indent.obj: $(OUTDIR) indent.c $(INCL)
-
-+ $(OUTDIR)/insexpand.obj: $(OUTDIR) insexpand.c $(INCL)
-+
- $(OUTDIR)/gui.obj: $(OUTDIR) gui.c $(INCL) $(GUI_INCL)
-
- $(OUTDIR)/gui_beval.obj: $(OUTDIR) gui_beval.c $(INCL) $(GUI_INCL)
-***************
-*** 1648,1653 ****
---- 1651,1657 ----
- proto/hardcopy.pro \
- proto/hashtab.pro \
- proto/indent.pro \
-+ proto/insexpand.pro \
- proto/json.pro \
- proto/list.pro \
- proto/main.pro \
-*** ../vim-8.1.1075/src/Make_sas.mak 2019-02-16 15:09:21.221946179 +0100
---- src/Make_sas.mak 2019-03-30 12:54:54.297407936 +0100
-***************
-*** 114,119 ****
---- 114,120 ----
- hardcopy.c \
- hashtab.c \
- indent.c \
-+ insexpand.c \
- json.c \
- list.c \
- main.c \
-***************
-*** 174,179 ****
---- 175,181 ----
- hardcopy.o \
- hashtab.o \
- indent.o \
-+ insexpand.o \
- json.o \
- list.o \
- main.o \
-***************
-*** 234,239 ****
---- 236,242 ----
- proto/hardcopy.pro \
- proto/hashtab.pro \
- proto/indent.pro \
-+ proto/insexpand.pro \
- proto/json.pro \
- proto/list.pro \
- proto/main.pro \
-***************
-*** 373,378 ****
---- 376,383 ----
- proto/hashtab.pro: hashtab.c
- indent.o: indent.c
- proto/indent.pro: indent.c
-+ insexpand.o: insexpand.c
-+ proto/insexpand.pro: insexpand.c
- json.o: json.c
- proto/json.pro: json.c
- list.o: list.c
-*** ../vim-8.1.1075/src/Make_vms.mms 2019-03-22 17:03:01.783689365 +0100
---- src/Make_vms.mms 2019-03-30 12:54:54.301407905 +0100
-***************
-*** 311,319 ****
- crypt.c crypt_zip.c dict.c diff.c digraph.c edit.c eval.c evalfunc.c \
- ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c if_cscope.c \
- if_xcmdsrv.c fileio.c findfile.c fold.c getchar.c hardcopy.c \
-! hashtab.c indent.c json.c list.c main.c mark.c menu.c mbyte.c \
-! memfile.c memline.c message.c misc1.c misc2.c move.c normal.c ops.c \
-! option.c popupmnu.c quickfix.c regexp.c search.c sha256.c sign.c \
- spell.c spellfile.c syntax.c tag.c term.c termlib.c textprop.c ui.c \
- undo.c userfunc.c version.c screen.c window.c os_unix.c os_vms.c \
- pathdef.c
---- 311,319 ----
- crypt.c crypt_zip.c dict.c diff.c digraph.c edit.c eval.c evalfunc.c \
- ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c if_cscope.c \
- if_xcmdsrv.c fileio.c findfile.c fold.c getchar.c hardcopy.c \
-! hashtab.c indent.c insexpand.c json.c list.c main.c mark.c menu.c \
-! mbyte.c memfile.c memline.c message.c misc1.c misc2.c move.c normal.c \
-! ops.c option.c popupmnu.c quickfix.c regexp.c search.c sha256.c sign.c \
- spell.c spellfile.c syntax.c tag.c term.c termlib.c textprop.c ui.c \
- undo.c userfunc.c version.c screen.c window.c os_unix.c os_vms.c \
- pathdef.c
-***************
-*** 325,337 ****
- edit.obj eval.obj evalfunc.obj ex_cmds.obj ex_cmds2.obj ex_docmd.obj \
- ex_eval.obj ex_getln.obj if_cscope.obj if_xcmdsrv.obj \
- fileio.obj findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \
-! indent.obj json.obj list.obj main.obj mark.obj menu.obj memfile.obj \
-! memline.obj message.obj misc1.obj misc2.obj move.obj mbyte.obj \
-! normal.obj ops.obj option.obj popupmnu.obj quickfix.obj regexp.obj \
-! search.obj sha256.obj sign.obj spell.obj spellfile.obj syntax.obj \
-! tag.obj term.obj termlib.obj textprop.obj ui.obj undo.obj \
-! userfunc.obj screen.obj version.obj window.obj os_unix.obj os_vms.obj \
-! pathdef.obj if_mzsch.obj \
- $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \
- $(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ) $(XDIFF_OBJ)
-
---- 325,337 ----
- edit.obj eval.obj evalfunc.obj ex_cmds.obj ex_cmds2.obj ex_docmd.obj \
- ex_eval.obj ex_getln.obj if_cscope.obj if_xcmdsrv.obj \
- fileio.obj findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \
-! indent.obj insexpand.obj json.obj list.obj main.obj mark.obj \
-! menu.obj memfile.obj memline.obj message.obj misc1.obj misc2.obj \
-! move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj \
-! quickfix.obj regexp.obj search.obj sha256.obj sign.obj spell.obj \
-! spellfile.obj syntax.obj tag.obj term.obj termlib.obj textprop.obj \
-! ui.obj undo.obj userfunc.obj screen.obj version.obj window.obj \
-! os_unix.obj os_vms.obj pathdef.obj if_mzsch.obj \
- $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \
- $(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ) $(XDIFF_OBJ)
-
-***************
-*** 603,608 ****
---- 603,609 ----
- regexp.h gui.h beval.h [.proto]gui_beval.pro ex_cmds.h proto.h \
- globals.h if_mzsch.h
- indent.obj : indent.c vim.h [.auto]config.h feature.h os_unix.h
-+ insexpand.obj : insexpand.c vim.h [.auto]config.h feature.h os_unix.h
- json.obj : json.c vim.h [.auto]config.h feature.h os_unix.h \
- ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
- [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \
-*** ../vim-8.1.1075/src/Makefile 2019-03-22 16:33:03.487016094 +0100
---- src/Makefile 2019-03-30 12:54:54.301407905 +0100
-***************
-*** 1599,1604 ****
---- 1599,1605 ----
- if_cscope.c \
- if_xcmdsrv.c \
- indent.c \
-+ insexpand.c \
- json.c \
- list.c \
- main.c \
-***************
-*** 1713,1718 ****
---- 1714,1720 ----
- objects/if_cscope.o \
- objects/if_xcmdsrv.o \
- objects/indent.o \
-+ objects/insexpand.o \
- objects/list.o \
- objects/mark.o \
- objects/memline.o \
-***************
-*** 1844,1849 ****
---- 1846,1852 ----
- if_ruby.pro \
- if_xcmdsrv.pro \
- indent.pro \
-+ insexpand.pro \
- json.pro \
- list.pro \
- main.pro \
-***************
-*** 3098,3103 ****
---- 3101,3109 ----
- objects/indent.o: indent.c
- $(CCC) -o $@ indent.c
-
-+ objects/insexpand.o: insexpand.c
-+ $(CCC) -o $@ insexpand.c
-+
- objects/json.o: json.c
- $(CCC) -o $@ json.c
-
-***************
-*** 3500,3505 ****
---- 3506,3515 ----
- auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
- proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
- proto.h globals.h
-+ objects/insexpand.o: insexpand.c vim.h protodef.h auto/config.h feature.h \
-+ os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
-+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
-+ proto.h globals.h
- objects/json.o: json.c vim.h protodef.h auto/config.h feature.h os_unix.h \
- auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
- proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
-*** ../vim-8.1.1075/src/edit.c 2019-03-29 12:19:34.953348924 +0100
---- src/edit.c 2019-03-30 13:46:18.517111390 +0100
-***************
-*** 13,222 ****
-
- #include "vim.h"
-
-! #ifdef FEAT_INS_EXPAND
-! /*
-! * Definitions used for CTRL-X submode.
-! * Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[] and
-! * ctrl_x_mode_names[].
-! */
-! # define CTRL_X_WANT_IDENT 0x100
-!
-! # define CTRL_X_NORMAL 0 /* CTRL-N CTRL-P completion, default */
-! # define CTRL_X_NOT_DEFINED_YET 1
-! # define CTRL_X_SCROLL 2
-! # define CTRL_X_WHOLE_LINE 3
-! # define CTRL_X_FILES 4
-! # define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
-! # define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
-! # define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
-! # define CTRL_X_FINISHED 8
-! # define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
-! # define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT)
-! # define CTRL_X_CMDLINE 11
-! # define CTRL_X_FUNCTION 12
-! # define CTRL_X_OMNI 13
-! # define CTRL_X_SPELL 14
-! # define CTRL_X_LOCAL_MSG 15 /* only used in "ctrl_x_msgs" */
-! # define CTRL_X_EVAL 16 /* for builtin function complete() */
-!
-! # define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
-! # define CTRL_X_MODE_LINE_OR_EVAL(m) ((m) == CTRL_X_WHOLE_LINE || (m) == CTRL_X_EVAL)
-!
-! // Message for CTRL-X mode, index is ctrl_x_mode.
-! static char *ctrl_x_msgs[] =
-! {
-! N_(" Keyword completion (^N^P)"), // CTRL_X_NORMAL, ^P/^N compl.
-! N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
-! NULL, // CTRL_X_SCROLL: depends on state
-! N_(" Whole line completion (^L^N^P)"),
-! N_(" File name completion (^F^N^P)"),
-! N_(" Tag completion (^]^N^P)"),
-! N_(" Path pattern completion (^N^P)"),
-! N_(" Definition completion (^D^N^P)"),
-! NULL, // CTRL_X_FINISHED
-! N_(" Dictionary completion (^K^N^P)"),
-! N_(" Thesaurus completion (^T^N^P)"),
-! N_(" Command-line completion (^V^N^P)"),
-! N_(" User defined completion (^U^N^P)"),
-! N_(" Omni completion (^O^N^P)"),
-! N_(" Spelling suggestion (s^N^P)"),
-! N_(" Keyword Local completion (^N^P)"),
-! NULL, // CTRL_X_EVAL doesn't use msg.
-! };
-!
-! static char *ctrl_x_mode_names[] = {
-! "keyword",
-! "ctrl_x",
-! "unknown", // CTRL_X_SCROLL
-! "whole_line",
-! "files",
-! "tags",
-! "path_patterns",
-! "path_defines",
-! "unknown", // CTRL_X_FINISHED
-! "dictionary",
-! "thesaurus",
-! "cmdline",
-! "function",
-! "omni",
-! "spell",
-! NULL, // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
-! "eval"
-! };
-!
-!
-! static char e_hitend[] = N_("Hit end of paragraph");
-! # ifdef FEAT_COMPL_FUNC
-! static char e_complwin[] = N_("E839: Completion function changed window");
-! static char e_compldel[] = N_("E840: Completion function deleted text");
-! # endif
-!
-! /*
-! * Structure used to store one match for insert completion.
-! */
-! typedef struct compl_S compl_T;
-! struct compl_S
-! {
-! compl_T *cp_next;
-! compl_T *cp_prev;
-! char_u *cp_str; /* matched text */
-! char cp_icase; /* TRUE or FALSE: ignore case */
-! char_u *(cp_text[CPT_COUNT]); /* text for the menu */
-! char_u *cp_fname; /* file containing the match, allocated when
-! * cp_flags has FREE_FNAME */
-! int cp_flags; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
-! int cp_number; /* sequence number */
-! };
-!
-! # define ORIGINAL_TEXT (1) /* the original text when the expansion begun */
-! # define FREE_FNAME (2)
-!
-! /*
-! * All the current matches are stored in a list.
-! * "compl_first_match" points to the start of the list.
-! * "compl_curr_match" points to the currently selected entry.
-! * "compl_shown_match" is different from compl_curr_match during
-! * ins_compl_get_exp().
-! */
-! static compl_T *compl_first_match = NULL;
-! static compl_T *compl_curr_match = NULL;
-! static compl_T *compl_shown_match = NULL;
-! static compl_T *compl_old_match = NULL;
-!
-! /* After using a cursor key <Enter> selects a match in the popup menu,
-! * otherwise it inserts a line break. */
-! static int compl_enter_selects = FALSE;
-!
-! /* When "compl_leader" is not NULL only matches that start with this string
-! * are used. */
-! static char_u *compl_leader = NULL;
-!
-! static int compl_get_longest = FALSE; /* put longest common string
-! in compl_leader */
-!
-! static int compl_no_insert = FALSE; /* FALSE: select & insert
-! TRUE: noinsert */
-! static int compl_no_select = FALSE; /* FALSE: select & insert
-! TRUE: noselect */
-!
-! static int compl_used_match; /* Selected one of the matches. When
-! FALSE the match was edited or using
-! the longest common string. */
-!
-! static int compl_was_interrupted = FALSE; /* didn't finish finding
-! completions. */
-!
-! static int compl_restarting = FALSE; /* don't insert match */
-!
-! /* When the first completion is done "compl_started" is set. When it's
-! * FALSE the word to be completed must be located. */
-! static int compl_started = FALSE;
-!
-! /* Which Ctrl-X mode are we in? */
-! static int ctrl_x_mode = CTRL_X_NORMAL;
-
- /* Set when doing something for completion that may call edit() recursively,
- * which is not allowed. */
-! static int compl_busy = FALSE;
-!
-! static int compl_matches = 0;
-! static char_u *compl_pattern = NULL;
-! static int compl_direction = FORWARD;
-! static int compl_shows_dir = FORWARD;
-! static int compl_pending = 0; /* > 1 for postponed CTRL-N */
-! static pos_T compl_startpos;
-! static colnr_T compl_col = 0; /* column where the text starts
-! * that is being completed */
-! static char_u *compl_orig_text = NULL; /* text as it was before
-! * completion started */
-! static int compl_cont_mode = 0;
-! static expand_T compl_xp;
-!
-! static int compl_opt_refresh_always = FALSE;
-! static int compl_opt_suppress_empty = FALSE;
-!
-! static void ins_ctrl_x(void);
-! static int has_compl_option(int dict_opt);
-! static int ins_compl_accept_char(int c);
-! static int ins_compl_add(char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup);
-! static void ins_compl_longest_match(compl_T *match);
-! static void ins_compl_del_pum(void);
-! static int pum_wanted(void);
-! static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir);
-! static char_u *find_line_end(char_u *ptr);
-! static void ins_compl_free(void);
-! static void ins_compl_clear(void);
-! static char_u *ins_compl_mode(void);
-! static int ins_compl_bs(void);
-! static int ins_compl_need_restart(void);
-! static void ins_compl_new_leader(void);
-! static void ins_compl_addleader(int c);
-! static int ins_compl_len(void);
-! static void ins_compl_restart(void);
-! static void ins_compl_set_original_text(char_u *str);
-! static void ins_compl_addfrommatch(void);
-! static int ins_compl_prep(int c);
-! static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
-! # if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
-! static void ins_compl_add_list(list_T *list);
-! static void ins_compl_add_dict(dict_T *dict);
-! # endif
-! static void ins_compl_delete(void);
-! static void ins_compl_insert(int in_compl_func);
-! static int ins_compl_key2dir(int c);
-! static int ins_compl_pum_key(int c);
-! static int ins_compl_key2count(int c);
-! static int ins_complete(int c, int enable_pum);
-! static void show_pum(int prev_w_wrow, int prev_w_leftcol);
-! static unsigned quote_meta(char_u *dest, char_u *str, int len);
- #endif /* FEAT_INS_EXPAND */
-
-- #define BACKSPACE_CHAR 1
-- #define BACKSPACE_WORD 2
-- #define BACKSPACE_WORD_NOT_SPACE 3
-- #define BACKSPACE_LINE 4
-
-- static void ins_redraw(int ready);
- static void ins_ctrl_v(void);
- #ifdef FEAT_JOB_CHANNEL
- static void init_prompt(int cmdchar_todo);
---- 13,30 ----
-
- #include "vim.h"
-
-! #define BACKSPACE_CHAR 1
-! #define BACKSPACE_WORD 2
-! #define BACKSPACE_WORD_NOT_SPACE 3
-! #define BACKSPACE_LINE 4
-
-+ #ifdef FEAT_INS_EXPAND
- /* Set when doing something for completion that may call edit() recursively,
- * which is not allowed. */
-! static int compl_busy = FALSE;
- #endif /* FEAT_INS_EXPAND */
-
-
- static void ins_ctrl_v(void);
- #ifdef FEAT_JOB_CHANNEL
- static void init_prompt(int cmdchar_todo);
-***************
-*** 226,237 ****
- static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c);
- static void check_auto_format(int);
- static void redo_literal(int c);
-- static void start_arrow(pos_T *end_insert_pos);
- static void start_arrow_common(pos_T *end_insert_pos, int change);
- #ifdef FEAT_SPELL
- static void check_spell_redraw(void);
-- static void spell_back_to_badword(void);
-- static int spell_bad_len = 0; /* length of located bad word */
- #endif
- static void stop_insert(pos_T *end_insert_pos, int esc, int nomove);
- static int echeck_abbr(int);
---- 34,42 ----
-***************
-*** 274,280 ****
- static void ins_drop(void);
- #endif
- static int ins_tab(void);
-- static int ins_eol(int c);
- #ifdef FEAT_DIGRAPHS
- static int ins_digraph(void);
- #endif
---- 79,84 ----
-***************
-*** 285,291 ****
- #if defined(FEAT_EVAL)
- static char_u *do_insert_char_pre(int c);
- #endif
-- static int ins_apply_autocmds(event_T event);
-
- static colnr_T Insstart_textlen; /* length of line when insert started */
- static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */
---- 89,94 ----
-***************
-*** 393,399 ****
-
- #ifdef FEAT_INS_EXPAND
- /* Don't allow recursive insert mode when busy with completion. */
-! if (compl_started || compl_busy || pum_visible())
- {
- emsg(_(e_secure));
- return FALSE;
---- 196,202 ----
-
- #ifdef FEAT_INS_EXPAND
- /* Don't allow recursive insert mode when busy with completion. */
-! if (ins_compl_active() || compl_busy || pum_visible())
- {
- emsg(_(e_secure));
- return FALSE;
-***************
-*** 834,861 ****
- * and the cursor is still in the completed word. Only when there is
- * a match, skip this when no matches were found.
- */
-! if (compl_started
- && pum_wanted()
-! && curwin->w_cursor.col >= compl_col
-! && (compl_shown_match == NULL
-! || compl_shown_match != compl_shown_match->cp_next))
- {
- /* BS: Delete one character from "compl_leader". */
- if ((c == K_BS || c == Ctrl_H)
-! && curwin->w_cursor.col > compl_col
- && (c = ins_compl_bs()) == NUL)
- continue;
-
- /* When no match was selected or it was edited. */
-! if (!compl_used_match)
- {
- /* CTRL-L: Add one character from the current match to
- * "compl_leader". Except when at the original match and
- * there is nothing to add, CTRL-L works like CTRL-P then. */
- if (c == Ctrl_L
-! && (!CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
-! || (int)STRLEN(compl_shown_match->cp_str)
-! > curwin->w_cursor.col - compl_col))
- {
- ins_compl_addfrommatch();
- continue;
---- 637,662 ----
- * and the cursor is still in the completed word. Only when there is
- * a match, skip this when no matches were found.
- */
-! if (ins_compl_active()
- && pum_wanted()
-! && curwin->w_cursor.col >= ins_compl_col()
-! && ins_compl_has_shown_match())
- {
- /* BS: Delete one character from "compl_leader". */
- if ((c == K_BS || c == Ctrl_H)
-! && curwin->w_cursor.col > ins_compl_col()
- && (c = ins_compl_bs()) == NUL)
- continue;
-
- /* When no match was selected or it was edited. */
-! if (!ins_compl_used_match())
- {
- /* CTRL-L: Add one character from the current match to
- * "compl_leader". Except when at the original match and
- * there is nothing to add, CTRL-L works like CTRL-P then. */
- if (c == Ctrl_L
-! && (!ctrl_x_mode_line_or_eval()
-! || ins_compl_long_shown_match()))
- {
- ins_compl_addfrommatch();
- continue;
-***************
-*** 883,890 ****
- }
-
- /* Pressing CTRL-Y selects the current match. When
-! * compl_enter_selects is set the Enter key does the same. */
-! if ((c == Ctrl_Y || (compl_enter_selects
- && (c == CAR || c == K_KENTER || c == NL)))
- && stop_arrow() == OK)
- {
---- 684,692 ----
- }
-
- /* Pressing CTRL-Y selects the current match. When
-! * ins_compl_enter_selects() is set the Enter key does the
-! * same. */
-! if ((c == Ctrl_Y || (ins_compl_enter_selects()
- && (c == CAR || c == K_KENTER || c == NL)))
- && stop_arrow() == OK)
- {
-***************
-*** 896,902 ****
-
- /* Prepare for or stop CTRL-X mode. This doesn't do completion, but
- * it does fix up the text when finishing completion. */
-! compl_get_longest = FALSE;
- if (ins_compl_prep(c))
- continue;
- #endif
---- 698,704 ----
-
- /* Prepare for or stop CTRL-X mode. This doesn't do completion, but
- * it does fix up the text when finishing completion. */
-! ins_compl_init_get_longest();
- if (ins_compl_prep(c))
- continue;
- #endif
-***************
-*** 939,945 ****
- #endif
-
- #ifdef FEAT_INS_EXPAND
-! if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE)
- goto docomplete;
- #endif
- if (c == Ctrl_V || c == Ctrl_Q)
---- 741,747 ----
- #endif
-
- #ifdef FEAT_INS_EXPAND
-! if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode_cmdline())
- goto docomplete;
- #endif
- if (c == Ctrl_V || c == Ctrl_Q)
-***************
-*** 952,958 ****
- #ifdef FEAT_CINDENT
- if (cindent_on()
- # ifdef FEAT_INS_EXPAND
-! && ctrl_x_mode == 0
- # endif
- )
- {
---- 754,760 ----
- #ifdef FEAT_CINDENT
- if (cindent_on()
- # ifdef FEAT_INS_EXPAND
-! && ctrl_x_mode_none()
- # endif
- )
- {
-***************
-*** 1073,1079 ****
-
- case Ctrl_O: /* execute one command */
- #ifdef FEAT_COMPL_FUNC
-! if (ctrl_x_mode == CTRL_X_OMNI)
- goto docomplete;
- #endif
- if (echeck_abbr(Ctrl_O + ABBR_OFF))
---- 875,881 ----
-
- case Ctrl_O: /* execute one command */
- #ifdef FEAT_COMPL_FUNC
-! if (ctrl_x_mode_omni())
- goto docomplete;
- #endif
- if (echeck_abbr(Ctrl_O + ABBR_OFF))
-***************
-*** 1149,1162 ****
-
- case Ctrl_D: /* Make indent one shiftwidth smaller. */
- #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
-! if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
- goto docomplete;
- #endif
- /* FALLTHROUGH */
-
- case Ctrl_T: /* Make indent one shiftwidth greater. */
- # ifdef FEAT_INS_EXPAND
-! if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
- {
- if (has_compl_option(FALSE))
- goto docomplete;
---- 951,964 ----
-
- case Ctrl_D: /* Make indent one shiftwidth smaller. */
- #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
-! if (ctrl_x_mode_path_defines())
- goto docomplete;
- #endif
- /* FALLTHROUGH */
-
- case Ctrl_T: /* Make indent one shiftwidth greater. */
- # ifdef FEAT_INS_EXPAND
-! if (c == Ctrl_T && ctrl_x_mode_thesaurus())
- {
- if (has_compl_option(FALSE))
- goto docomplete;
-***************
-*** 1200,1206 ****
- case Ctrl_U: /* delete all inserted text in current line */
- # ifdef FEAT_COMPL_FUNC
- /* CTRL-X CTRL-U completes with 'completefunc'. */
-! if (ctrl_x_mode == CTRL_X_FUNCTION)
- goto docomplete;
- # endif
- did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
---- 1002,1008 ----
- case Ctrl_U: /* delete all inserted text in current line */
- # ifdef FEAT_COMPL_FUNC
- /* CTRL-X CTRL-U completes with 'completefunc'. */
-! if (ctrl_x_mode_function())
- goto docomplete;
- # endif
- did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
-***************
-*** 1382,1388 ****
-
- case TAB: /* TAB or Complete patterns along path */
- #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
-! if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
- goto docomplete;
- #endif
- inserted_space = FALSE;
---- 1184,1190 ----
-
- case TAB: /* TAB or Complete patterns along path */
- #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
-! if (ctrl_x_mode_path_patterns())
- goto docomplete;
- #endif
- inserted_space = FALSE;
-***************
-*** 1436,1442 ****
- #if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND)
- case Ctrl_K: /* digraph or keyword completion */
- # ifdef FEAT_INS_EXPAND
-! if (ctrl_x_mode == CTRL_X_DICTIONARY)
- {
- if (has_compl_option(TRUE))
- goto docomplete;
---- 1238,1244 ----
- #if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND)
- case Ctrl_K: /* digraph or keyword completion */
- # ifdef FEAT_INS_EXPAND
-! if (ctrl_x_mode_dictionary())
- {
- if (has_compl_option(TRUE))
- goto docomplete;
-***************
-*** 1457,1481 ****
- break;
-
- case Ctrl_RSB: /* Tag name completion after ^X */
-! if (ctrl_x_mode != CTRL_X_TAGS)
- goto normalchar;
- goto docomplete;
-
- case Ctrl_F: /* File name completion after ^X */
-! if (ctrl_x_mode != CTRL_X_FILES)
- goto normalchar;
- goto docomplete;
-
- case 's': /* Spelling completion after ^X */
- case Ctrl_S:
-! if (ctrl_x_mode != CTRL_X_SPELL)
- goto normalchar;
- goto docomplete;
- #endif
-
- case Ctrl_L: /* Whole line completion after ^X */
- #ifdef FEAT_INS_EXPAND
-! if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
- #endif
- {
- /* CTRL-L with 'insertmode' set: Leave Insert mode */
---- 1259,1283 ----
- break;
-
- case Ctrl_RSB: /* Tag name completion after ^X */
-! if (!ctrl_x_mode_tags())
- goto normalchar;
- goto docomplete;
-
- case Ctrl_F: /* File name completion after ^X */
-! if (!ctrl_x_mode_files())
- goto normalchar;
- goto docomplete;
-
- case 's': /* Spelling completion after ^X */
- case Ctrl_S:
-! if (!ctrl_x_mode_spell())
- goto normalchar;
- goto docomplete;
- #endif
-
- case Ctrl_L: /* Whole line completion after ^X */
- #ifdef FEAT_INS_EXPAND
-! if (!ctrl_x_mode_whole_line())
- #endif
- {
- /* CTRL-L with 'insertmode' set: Leave Insert mode */
-***************
-*** 1495,1502 ****
- /* if 'complete' is empty then plain ^P is no longer special,
- * but it is under other ^X modes */
- if (*curbuf->b_p_cpt == NUL
-! && (ctrl_x_mode == CTRL_X_NORMAL
-! || ctrl_x_mode == CTRL_X_WHOLE_LINE)
- && !(compl_cont_status & CONT_LOCAL))
- goto normalchar;
-
---- 1297,1303 ----
- /* if 'complete' is empty then plain ^P is no longer special,
- * but it is under other ^X modes */
- if (*curbuf->b_p_cpt == NUL
-! && (ctrl_x_mode_normal() || ctrl_x_mode_whole_line())
- && !(compl_cont_status & CONT_LOCAL))
- goto normalchar;
-
-***************
-*** 1608,1614 ****
- if (c != K_CURSORHOLD
- #ifdef FEAT_COMPL_FUNC
- /* but not in CTRL-X mode, a script can't restore the state */
-! && ctrl_x_mode == CTRL_X_NORMAL
- #endif
- )
- did_cursorhold = FALSE;
---- 1409,1415 ----
- if (c != K_CURSORHOLD
- #ifdef FEAT_COMPL_FUNC
- /* but not in CTRL-X mode, a script can't restore the state */
-! && ctrl_x_mode_normal()
- #endif
- )
- did_cursorhold = FALSE;
-***************
-*** 1620,1626 ****
- #ifdef FEAT_CINDENT
- if (can_cindent && cindent_on()
- # ifdef FEAT_INS_EXPAND
-! && ctrl_x_mode == CTRL_X_NORMAL
- # endif
- )
- {
---- 1421,1427 ----
- #ifdef FEAT_CINDENT
- if (can_cindent && cindent_on()
- # ifdef FEAT_INS_EXPAND
-! && ctrl_x_mode_normal()
- # endif
- )
- {
-***************
-*** 1641,1646 ****
---- 1442,1453 ----
- /* NOTREACHED */
- }
-
-+ int
-+ ins_need_undo_get(void)
-+ {
-+ return ins_need_undo;
-+ }
-+
- /*
- * Redraw for Insert mode.
- * This is postponed until getting the next character to make '$' in the 'cpo'
-***************
-*** 1648,1654 ****
- * Only redraw when there are no characters available. This speeds up
- * inserting sequences of characters (e.g., for CTRL-R).
- */
-! static void
- ins_redraw(
- int ready UNUSED) /* not busy with something */
- {
---- 1455,1461 ----
- * Only redraw when there are no characters available. This speeds up
- * inserting sequences of characters (e.g., for CTRL-R).
- */
-! void
- ins_redraw(
- int ready UNUSED) /* not busy with something */
- {
-***************
-*** 2313,6031 ****
- return TRUE;
- }
-
-- #if defined(FEAT_INS_EXPAND) || defined(PROTO)
-- /*
-- * CTRL-X pressed in Insert mode.
-- */
-- static void
-- ins_ctrl_x(void)
-- {
-- /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X
-- * CTRL-V works like CTRL-N */
-- if (ctrl_x_mode != CTRL_X_CMDLINE)
-- {
-- /* if the next ^X<> won't ADD nothing, then reset
-- * compl_cont_status */
-- if (compl_cont_status & CONT_N_ADDS)
-- compl_cont_status |= CONT_INTRPT;
-- else
-- compl_cont_status = 0;
-- /* We're not sure which CTRL-X mode it will be yet */
-- ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
-- edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
-- edit_submode_pre = NULL;
-- showmode();
-- }
-- }
--
-- /*
-- * Whether other than default completion has been selected.
-- */
-- int
-- ctrl_x_mode_not_default(void)
-- {
-- return ctrl_x_mode != CTRL_X_NORMAL;
-- }
--
-- /*
-- * Whether CTRL-X was typed without a following character.
-- */
-- int
-- ctrl_x_mode_not_defined_yet(void)
-- {
-- return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
-- }
--
-- /*
-- * Return TRUE if the 'dict' or 'tsr' option can be used.
-- */
-- static int
-- has_compl_option(int dict_opt)
-- {
-- if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
-- # ifdef FEAT_SPELL
-- && !curwin->w_p_spell
-- # endif
-- )
-- : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL))
-- {
-- ctrl_x_mode = CTRL_X_NORMAL;
-- edit_submode = NULL;
-- msg_attr(dict_opt ? _("'dictionary' option is empty")
-- : _("'thesaurus' option is empty"),
-- HL_ATTR(HLF_E));
-- if (emsg_silent == 0)
-- {
-- vim_beep(BO_COMPL);
-- setcursor();
-- out_flush();
-- #ifdef FEAT_EVAL
-- if (!get_vim_var_nr(VV_TESTING))
-- #endif
-- ui_delay(2000L, FALSE);
-- }
-- return FALSE;
-- }
-- return TRUE;
-- }
--
-- /*
-- * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
-- * This depends on the current mode.
-- */
-- int
-- vim_is_ctrl_x_key(int c)
-- {
-- // Always allow ^R - let its results then be checked
-- if (c == Ctrl_R)
-- return TRUE;
--
-- /* Accept <PageUp> and <PageDown> if the popup menu is visible. */
-- if (ins_compl_pum_key(c))
-- return TRUE;
--
-- switch (ctrl_x_mode)
-- {
-- case 0: /* Not in any CTRL-X mode */
-- return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
-- case CTRL_X_NOT_DEFINED_YET:
-- return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
-- || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
-- || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
-- || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
-- || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
-- || c == Ctrl_S || c == Ctrl_K || c == 's');
-- case CTRL_X_SCROLL:
-- return (c == Ctrl_Y || c == Ctrl_E);
-- case CTRL_X_WHOLE_LINE:
-- return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_FILES:
-- return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_DICTIONARY:
-- return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_THESAURUS:
-- return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_TAGS:
-- return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
-- #ifdef FEAT_FIND_ID
-- case CTRL_X_PATH_PATTERNS:
-- return (c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_PATH_DEFINES:
-- return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
-- #endif
-- case CTRL_X_CMDLINE:
-- return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
-- || c == Ctrl_X);
-- #ifdef FEAT_COMPL_FUNC
-- case CTRL_X_FUNCTION:
-- return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_OMNI:
-- return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N);
-- #endif
-- case CTRL_X_SPELL:
-- return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N);
-- case CTRL_X_EVAL:
-- return (c == Ctrl_P || c == Ctrl_N);
-- }
-- internal_error("vim_is_ctrl_x_key()");
-- return FALSE;
-- }
--
-- /*
-- * Return TRUE when character "c" is part of the item currently being
-- * completed. Used to decide whether to abandon complete mode when the menu
-- * is visible.
-- */
-- static int
-- ins_compl_accept_char(int c)
-- {
-- if (ctrl_x_mode & CTRL_X_WANT_IDENT)
-- /* When expanding an identifier only accept identifier chars. */
-- return vim_isIDc(c);
--
-- switch (ctrl_x_mode)
-- {
-- case CTRL_X_FILES:
-- /* When expanding file name only accept file name chars. But not
-- * path separators, so that "proto/<Tab>" expands files in
-- * "proto", not "proto/" as a whole */
-- return vim_isfilec(c) && !vim_ispathsep(c);
--
-- case CTRL_X_CMDLINE:
-- case CTRL_X_OMNI:
-- /* Command line and Omni completion can work with just about any
-- * printable character, but do stop at white space. */
-- return vim_isprintc(c) && !VIM_ISWHITE(c);
--
-- case CTRL_X_WHOLE_LINE:
-- /* For while line completion a space can be part of the line. */
-- return vim_isprintc(c);
-- }
-- return vim_iswordc(c);
-- }
--
-- /*
-- * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
-- * case of the originally typed text is used, and the case of the completed
-- * text is inferred, ie this tries to work out what case you probably wanted
-- * the rest of the word to be in -- webb
-- */
-- int
-- ins_compl_add_infercase(
-- char_u *str,
-- int len,
-- int icase,
-- char_u *fname,
-- int dir,
-- int flags)
-- {
-- char_u *p;
-- int i, c;
-- int actual_len; /* Take multi-byte characters */
-- int actual_compl_length; /* into account. */
-- int min_len;
-- int *wca; /* Wide character array. */
-- int has_lower = FALSE;
-- int was_letter = FALSE;
--
-- if (p_ic && curbuf->b_p_inf && len > 0)
-- {
-- /* Infer case of completed part. */
--
-- /* Find actual length of completion. */
-- if (has_mbyte)
-- {
-- p = str;
-- actual_len = 0;
-- while (*p != NUL)
-- {
-- MB_PTR_ADV(p);
-- ++actual_len;
-- }
-- }
-- else
-- actual_len = len;
--
-- /* Find actual length of original text. */
-- if (has_mbyte)
-- {
-- p = compl_orig_text;
-- actual_compl_length = 0;
-- while (*p != NUL)
-- {
-- MB_PTR_ADV(p);
-- ++actual_compl_length;
-- }
-- }
-- else
-- actual_compl_length = compl_length;
--
-- /* "actual_len" may be smaller than "actual_compl_length" when using
-- * thesaurus, only use the minimum when comparing. */
-- min_len = actual_len < actual_compl_length
-- ? actual_len : actual_compl_length;
--
-- /* Allocate wide character array for the completion and fill it. */
-- wca = (int *)alloc((unsigned)(actual_len * sizeof(int)));
-- if (wca != NULL)
-- {
-- p = str;
-- for (i = 0; i < actual_len; ++i)
-- if (has_mbyte)
-- wca[i] = mb_ptr2char_adv(&p);
-- else
-- wca[i] = *(p++);
--
-- /* Rule 1: Were any chars converted to lower? */
-- p = compl_orig_text;
-- for (i = 0; i < min_len; ++i)
-- {
-- if (has_mbyte)
-- c = mb_ptr2char_adv(&p);
-- else
-- c = *(p++);
-- if (MB_ISLOWER(c))
-- {
-- has_lower = TRUE;
-- if (MB_ISUPPER(wca[i]))
-- {
-- /* Rule 1 is satisfied. */
-- for (i = actual_compl_length; i < actual_len; ++i)
-- wca[i] = MB_TOLOWER(wca[i]);
-- break;
-- }
-- }
-- }
--
-- /*
-- * Rule 2: No lower case, 2nd consecutive letter converted to
-- * upper case.
-- */
-- if (!has_lower)
-- {
-- p = compl_orig_text;
-- for (i = 0; i < min_len; ++i)
-- {
-- if (has_mbyte)
-- c = mb_ptr2char_adv(&p);
-- else
-- c = *(p++);
-- if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
-- {
-- /* Rule 2 is satisfied. */
-- for (i = actual_compl_length; i < actual_len; ++i)
-- wca[i] = MB_TOUPPER(wca[i]);
-- break;
-- }
-- was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
-- }
-- }
--
-- /* Copy the original case of the part we typed. */
-- p = compl_orig_text;
-- for (i = 0; i < min_len; ++i)
-- {
-- if (has_mbyte)
-- c = mb_ptr2char_adv(&p);
-- else
-- c = *(p++);
-- if (MB_ISLOWER(c))
-- wca[i] = MB_TOLOWER(wca[i]);
-- else if (MB_ISUPPER(c))
-- wca[i] = MB_TOUPPER(wca[i]);
-- }
--
-- /*
-- * Generate encoding specific output from wide character array.
-- * Multi-byte characters can occupy up to five bytes more than
-- * ASCII characters, and we also need one byte for NUL, so stay
-- * six bytes away from the edge of IObuff.
-- */
-- p = IObuff;
-- i = 0;
-- while (i < actual_len && (p - IObuff + 6) < IOSIZE)
-- if (has_mbyte)
-- p += (*mb_char2bytes)(wca[i++], p);
-- else
-- *(p++) = wca[i++];
-- *p = NUL;
--
-- vim_free(wca);
-- }
--
-- return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
-- flags, FALSE);
-- }
-- return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
-- }
--
-- /*
-- * Add a match to the list of matches.
-- * If the given string is already in the list of completions, then return
-- * NOTDONE, otherwise add it to the list and return OK. If there is an error,
-- * maybe because alloc() returns NULL, then FAIL is returned.
-- */
-- static int
-- ins_compl_add(
-- char_u *str,
-- int len,
-- int icase,
-- char_u *fname,
-- char_u **cptext, /* extra text for popup menu or NULL */
-- int cdir,
-- int flags,
-- int adup) /* accept duplicate match */
-- {
-- compl_T *match;
-- int dir = (cdir == 0 ? compl_direction : cdir);
--
-- ui_breakcheck();
-- if (got_int)
-- return FAIL;
-- if (len < 0)
-- len = (int)STRLEN(str);
--
-- /*
-- * If the same match is already present, don't add it.
-- */
-- if (compl_first_match != NULL && !adup)
-- {
-- match = compl_first_match;
-- do
-- {
-- if ( !(match->cp_flags & ORIGINAL_TEXT)
-- && STRNCMP(match->cp_str, str, len) == 0
-- && match->cp_str[len] == NUL)
-- return NOTDONE;
-- match = match->cp_next;
-- } while (match != NULL && match != compl_first_match);
-- }
--
-- /* Remove any popup menu before changing the list of matches. */
-- ins_compl_del_pum();
--
-- /*
-- * Allocate a new match structure.
-- * Copy the values to the new match structure.
-- */
-- match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T));
-- if (match == NULL)
-- return FAIL;
-- match->cp_number = -1;
-- if (flags & ORIGINAL_TEXT)
-- match->cp_number = 0;
-- if ((match->cp_str = vim_strnsave(str, len)) == NULL)
-- {
-- vim_free(match);
-- return FAIL;
-- }
-- match->cp_icase = icase;
--
-- /* match-fname is:
-- * - compl_curr_match->cp_fname if it is a string equal to fname.
-- * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
-- * - NULL otherwise. --Acevedo */
-- if (fname != NULL
-- && compl_curr_match != NULL
-- && compl_curr_match->cp_fname != NULL
-- && STRCMP(fname, compl_curr_match->cp_fname) == 0)
-- match->cp_fname = compl_curr_match->cp_fname;
-- else if (fname != NULL)
-- {
-- match->cp_fname = vim_strsave(fname);
-- flags |= FREE_FNAME;
-- }
-- else
-- match->cp_fname = NULL;
-- match->cp_flags = flags;
--
-- if (cptext != NULL)
-- {
-- int i;
--
-- for (i = 0; i < CPT_COUNT; ++i)
-- if (cptext[i] != NULL && *cptext[i] != NUL)
-- match->cp_text[i] = vim_strsave(cptext[i]);
-- }
--
-- /*
-- * Link the new match structure in the list of matches.
-- */
-- if (compl_first_match == NULL)
-- match->cp_next = match->cp_prev = NULL;
-- else if (dir == FORWARD)
-- {
-- match->cp_next = compl_curr_match->cp_next;
-- match->cp_prev = compl_curr_match;
-- }
-- else /* BACKWARD */
-- {
-- match->cp_next = compl_curr_match;
-- match->cp_prev = compl_curr_match->cp_prev;
-- }
-- if (match->cp_next)
-- match->cp_next->cp_prev = match;
-- if (match->cp_prev)
-- match->cp_prev->cp_next = match;
-- else /* if there's nothing before, it is the first match */
-- compl_first_match = match;
-- compl_curr_match = match;
--
-- /*
-- * Find the longest common string if still doing that.
-- */
-- if (compl_get_longest && (flags & ORIGINAL_TEXT) == 0)
-- ins_compl_longest_match(match);
--
-- return OK;
-- }
--
-- /*
-- * Return TRUE if "str[len]" matches with match->cp_str, considering
-- * match->cp_icase.
-- */
-- static int
-- ins_compl_equal(compl_T *match, char_u *str, int len)
-- {
-- if (match->cp_icase)
-- return STRNICMP(match->cp_str, str, (size_t)len) == 0;
-- return STRNCMP(match->cp_str, str, (size_t)len) == 0;
-- }
--
-- /*
-- * Reduce the longest common string for match "match".
-- */
-- static void
-- ins_compl_longest_match(compl_T *match)
-- {
-- char_u *p, *s;
-- int c1, c2;
-- int had_match;
--
-- if (compl_leader == NULL)
-- {
-- /* First match, use it as a whole. */
-- compl_leader = vim_strsave(match->cp_str);
-- if (compl_leader != NULL)
-- {
-- had_match = (curwin->w_cursor.col > compl_col);
-- ins_compl_delete();
-- ins_bytes(compl_leader + ins_compl_len());
-- ins_redraw(FALSE);
--
-- /* When the match isn't there (to avoid matching itself) remove it
-- * again after redrawing. */
-- if (!had_match)
-- ins_compl_delete();
-- compl_used_match = FALSE;
-- }
-- }
-- else
-- {
-- /* Reduce the text if this match differs from compl_leader. */
-- p = compl_leader;
-- s = match->cp_str;
-- while (*p != NUL)
-- {
-- if (has_mbyte)
-- {
-- c1 = mb_ptr2char(p);
-- c2 = mb_ptr2char(s);
-- }
-- else
-- {
-- c1 = *p;
-- c2 = *s;
-- }
-- if (match->cp_icase ? (MB_TOLOWER(c1) != MB_TOLOWER(c2))
-- : (c1 != c2))
-- break;
-- if (has_mbyte)
-- {
-- MB_PTR_ADV(p);
-- MB_PTR_ADV(s);
-- }
-- else
-- {
-- ++p;
-- ++s;
-- }
-- }
--
-- if (*p != NUL)
-- {
-- /* Leader was shortened, need to change the inserted text. */
-- *p = NUL;
-- had_match = (curwin->w_cursor.col > compl_col);
-- ins_compl_delete();
-- ins_bytes(compl_leader + ins_compl_len());
-- ins_redraw(FALSE);
--
-- /* When the match isn't there (to avoid matching itself) remove it
-- * again after redrawing. */
-- if (!had_match)
-- ins_compl_delete();
-- }
--
-- compl_used_match = FALSE;
-- }
-- }
--
-- /*
-- * Add an array of matches to the list of matches.
-- * Frees matches[].
-- */
-- static void
-- ins_compl_add_matches(
-- int num_matches,
-- char_u **matches,
-- int icase)
-- {
-- int i;
-- int add_r = OK;
-- int dir = compl_direction;
--
-- for (i = 0; i < num_matches && add_r != FAIL; i++)
-- if ((add_r = ins_compl_add(matches[i], -1, icase,
-- NULL, NULL, dir, 0, FALSE)) == OK)
-- /* if dir was BACKWARD then honor it just once */
-- dir = FORWARD;
-- FreeWild(num_matches, matches);
-- }
--
-- /* Make the completion list cyclic.
-- * Return the number of matches (excluding the original).
-- */
-- static int
-- ins_compl_make_cyclic(void)
-- {
-- compl_T *match;
-- int count = 0;
--
-- if (compl_first_match != NULL)
-- {
-- /*
-- * Find the end of the list.
-- */
-- match = compl_first_match;
-- /* there's always an entry for the compl_orig_text, it doesn't count. */
-- while (match->cp_next != NULL && match->cp_next != compl_first_match)
-- {
-- match = match->cp_next;
-- ++count;
-- }
-- match->cp_next = compl_first_match;
-- compl_first_match->cp_prev = match;
-- }
-- return count;
-- }
--
-- /*
-- * Set variables that store noselect and noinsert behavior from the
-- * 'completeopt' value.
-- */
-- void
-- completeopt_was_set(void)
-- {
-- compl_no_insert = FALSE;
-- compl_no_select = FALSE;
-- if (strstr((char *)p_cot, "noselect") != NULL)
-- compl_no_select = TRUE;
-- if (strstr((char *)p_cot, "noinsert") != NULL)
-- compl_no_insert = TRUE;
-- }
--
-- /*
-- * Start completion for the complete() function.
-- * "startcol" is where the matched text starts (1 is first column).
-- * "list" is the list of matches.
-- */
-- void
-- set_completion(colnr_T startcol, list_T *list)
-- {
-- int save_w_wrow = curwin->w_wrow;
-- int save_w_leftcol = curwin->w_leftcol;
--
-- /* If already doing completions stop it. */
-- if (ctrl_x_mode != CTRL_X_NORMAL)
-- ins_compl_prep(' ');
-- ins_compl_clear();
-- ins_compl_free();
--
-- compl_direction = FORWARD;
-- if (startcol > curwin->w_cursor.col)
-- startcol = curwin->w_cursor.col;
-- compl_col = startcol;
-- compl_length = (int)curwin->w_cursor.col - (int)startcol;
-- /* compl_pattern doesn't need to be set */
-- compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
-- if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
-- -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
-- return;
--
-- ctrl_x_mode = CTRL_X_EVAL;
--
-- ins_compl_add_list(list);
-- compl_matches = ins_compl_make_cyclic();
-- compl_started = TRUE;
-- compl_used_match = TRUE;
-- compl_cont_status = 0;
--
-- compl_curr_match = compl_first_match;
-- if (compl_no_insert || compl_no_select)
-- {
-- ins_complete(K_DOWN, FALSE);
-- if (compl_no_select)
-- /* Down/Up has no real effect. */
-- ins_complete(K_UP, FALSE);
-- }
-- else
-- ins_complete(Ctrl_N, FALSE);
-- compl_enter_selects = compl_no_insert;
--
-- /* Lazily show the popup menu, unless we got interrupted. */
-- if (!compl_interrupted)
-- show_pum(save_w_wrow, save_w_leftcol);
-- out_flush();
-- }
--
--
-- /* "compl_match_array" points the currently displayed list of entries in the
-- * popup menu. It is NULL when there is no popup menu. */
-- static pumitem_T *compl_match_array = NULL;
-- static int compl_match_arraysize;
--
-- /*
-- * Update the screen and when there is any scrolling remove the popup menu.
-- */
-- static void
-- ins_compl_upd_pum(void)
-- {
-- int h;
--
-- if (compl_match_array != NULL)
-- {
-- h = curwin->w_cline_height;
-- // Update the screen later, before drawing the popup menu over it.
-- pum_call_update_screen();
-- if (h != curwin->w_cline_height)
-- ins_compl_del_pum();
-- }
-- }
--
-- /*
-- * Remove any popup menu.
-- */
-- static void
-- ins_compl_del_pum(void)
-- {
-- if (compl_match_array != NULL)
-- {
-- pum_undisplay();
-- VIM_CLEAR(compl_match_array);
-- }
-- }
--
-- /*
-- * Return TRUE if the popup menu should be displayed.
-- */
-- static int
-- pum_wanted(void)
-- {
-- /* 'completeopt' must contain "menu" or "menuone" */
-- if (vim_strchr(p_cot, 'm') == NULL)
-- return FALSE;
--
-- /* The display looks bad on a B&W display. */
-- if (t_colors < 8
-- #ifdef FEAT_GUI
-- && !gui.in_use
-- #endif
-- )
-- return FALSE;
-- return TRUE;
-- }
--
-- /*
-- * Return TRUE if there are two or more matches to be shown in the popup menu.
-- * One if 'completopt' contains "menuone".
-- */
-- static int
-- pum_enough_matches(void)
-- {
-- compl_T *compl;
-- int i;
--
-- /* Don't display the popup menu if there are no matches or there is only
-- * one (ignoring the original text). */
-- compl = compl_first_match;
-- i = 0;
-- do
-- {
-- if (compl == NULL
-- || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2))
-- break;
-- compl = compl->cp_next;
-- } while (compl != compl_first_match);
--
-- if (strstr((char *)p_cot, "menuone") != NULL)
-- return (i >= 1);
-- return (i >= 2);
-- }
--
-- /*
-- * Show the popup menu for the list of matches.
-- * Also adjusts "compl_shown_match" to an entry that is actually displayed.
-- */
-- void
-- ins_compl_show_pum(void)
-- {
-- compl_T *compl;
-- compl_T *shown_compl = NULL;
-- int did_find_shown_match = FALSE;
-- int shown_match_ok = FALSE;
-- int i;
-- int cur = -1;
-- colnr_T col;
-- int lead_len = 0;
--
-- if (!pum_wanted() || !pum_enough_matches())
-- return;
--
-- #if defined(FEAT_EVAL)
-- /* Dirty hard-coded hack: remove any matchparen highlighting. */
-- do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif");
-- #endif
--
-- // Update the screen later, before drawing the popup menu over it.
-- pum_call_update_screen();
--
-- if (compl_match_array == NULL)
-- {
-- /* Need to build the popup menu list. */
-- compl_match_arraysize = 0;
-- compl = compl_first_match;
-- if (compl_leader != NULL)
-- lead_len = (int)STRLEN(compl_leader);
-- do
-- {
-- if ((compl->cp_flags & ORIGINAL_TEXT) == 0
-- && (compl_leader == NULL
-- || ins_compl_equal(compl, compl_leader, lead_len)))
-- ++compl_match_arraysize;
-- compl = compl->cp_next;
-- } while (compl != NULL && compl != compl_first_match);
-- if (compl_match_arraysize == 0)
-- return;
-- compl_match_array = (pumitem_T *)alloc_clear(
-- (unsigned)(sizeof(pumitem_T)
-- * compl_match_arraysize));
-- if (compl_match_array != NULL)
-- {
-- /* If the current match is the original text don't find the first
-- * match after it, don't highlight anything. */
-- if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-- shown_match_ok = TRUE;
--
-- i = 0;
-- compl = compl_first_match;
-- do
-- {
-- if ((compl->cp_flags & ORIGINAL_TEXT) == 0
-- && (compl_leader == NULL
-- || ins_compl_equal(compl, compl_leader, lead_len)))
-- {
-- if (!shown_match_ok)
-- {
-- if (compl == compl_shown_match || did_find_shown_match)
-- {
-- /* This item is the shown match or this is the
-- * first displayed item after the shown match. */
-- compl_shown_match = compl;
-- did_find_shown_match = TRUE;
-- shown_match_ok = TRUE;
-- }
-- else
-- /* Remember this displayed match for when the
-- * shown match is just below it. */
-- shown_compl = compl;
-- cur = i;
-- }
--
-- if (compl->cp_text[CPT_ABBR] != NULL)
-- compl_match_array[i].pum_text =
-- compl->cp_text[CPT_ABBR];
-- else
-- compl_match_array[i].pum_text = compl->cp_str;
-- compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
-- compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
-- if (compl->cp_text[CPT_MENU] != NULL)
-- compl_match_array[i++].pum_extra =
-- compl->cp_text[CPT_MENU];
-- else
-- compl_match_array[i++].pum_extra = compl->cp_fname;
-- }
--
-- if (compl == compl_shown_match)
-- {
-- did_find_shown_match = TRUE;
--
-- /* When the original text is the shown match don't set
-- * compl_shown_match. */
-- if (compl->cp_flags & ORIGINAL_TEXT)
-- shown_match_ok = TRUE;
--
-- if (!shown_match_ok && shown_compl != NULL)
-- {
-- /* The shown match isn't displayed, set it to the
-- * previously displayed match. */
-- compl_shown_match = shown_compl;
-- shown_match_ok = TRUE;
-- }
-- }
-- compl = compl->cp_next;
-- } while (compl != NULL && compl != compl_first_match);
--
-- if (!shown_match_ok) /* no displayed match at all */
-- cur = -1;
-- }
-- }
-- else
-- {
-- /* popup menu already exists, only need to find the current item.*/
-- for (i = 0; i < compl_match_arraysize; ++i)
-- if (compl_match_array[i].pum_text == compl_shown_match->cp_str
-- || compl_match_array[i].pum_text
-- == compl_shown_match->cp_text[CPT_ABBR])
-- {
-- cur = i;
-- break;
-- }
-- }
--
-- if (compl_match_array != NULL)
-- {
-- /* In Replace mode when a $ is displayed at the end of the line only
-- * part of the screen would be updated. We do need to redraw here. */
-- dollar_vcol = -1;
--
-- /* Compute the screen column of the start of the completed text.
-- * Use the cursor to get all wrapping and other settings right. */
-- col = curwin->w_cursor.col;
-- curwin->w_cursor.col = compl_col;
-- pum_display(compl_match_array, compl_match_arraysize, cur);
-- curwin->w_cursor.col = col;
-- }
-- }
--
-- #define DICT_FIRST (1) /* use just first element in "dict" */
-- #define DICT_EXACT (2) /* "dict" is the exact name of a file */
--
-- /*
-- * Add any identifiers that match the given pattern in the list of dictionary
-- * files "dict_start" to the list of completions.
-- */
-- static void
-- ins_compl_dictionaries(
-- char_u *dict_start,
-- char_u *pat,
-- int flags, /* DICT_FIRST and/or DICT_EXACT */
-- int thesaurus) /* Thesaurus completion */
-- {
-- char_u *dict = dict_start;
-- char_u *ptr;
-- char_u *buf;
-- regmatch_T regmatch;
-- char_u **files;
-- int count;
-- int save_p_scs;
-- int dir = compl_direction;
--
-- if (*dict == NUL)
-- {
-- #ifdef FEAT_SPELL
-- /* When 'dictionary' is empty and spell checking is enabled use
-- * "spell". */
-- if (!thesaurus && curwin->w_p_spell)
-- dict = (char_u *)"spell";
-- else
-- #endif
-- return;
-- }
--
-- buf = alloc(LSIZE);
-- if (buf == NULL)
-- return;
-- regmatch.regprog = NULL; /* so that we can goto theend */
--
-- /* If 'infercase' is set, don't use 'smartcase' here */
-- save_p_scs = p_scs;
-- if (curbuf->b_p_inf)
-- p_scs = FALSE;
--
-- /* When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
-- * to only match at the start of a line. Otherwise just match the
-- * pattern. Also need to double backslashes. */
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- {
-- char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\");
-- size_t len;
--
-- if (pat_esc == NULL)
-- goto theend;
-- len = STRLEN(pat_esc) + 10;
-- ptr = alloc((unsigned)len);
-- if (ptr == NULL)
-- {
-- vim_free(pat_esc);
-- goto theend;
-- }
-- vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc);
-- regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
-- vim_free(pat_esc);
-- vim_free(ptr);
-- }
-- else
-- {
-- regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
-- if (regmatch.regprog == NULL)
-- goto theend;
-- }
--
-- /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
-- regmatch.rm_ic = ignorecase(pat);
-- while (*dict != NUL && !got_int && !compl_interrupted)
-- {
-- /* copy one dictionary file name into buf */
-- if (flags == DICT_EXACT)
-- {
-- count = 1;
-- files = &dict;
-- }
-- else
-- {
-- /* Expand wildcards in the dictionary name, but do not allow
-- * backticks (for security, the 'dict' option may have been set in
-- * a modeline). */
-- copy_option_part(&dict, buf, LSIZE, ",");
-- # ifdef FEAT_SPELL
-- if (!thesaurus && STRCMP(buf, "spell") == 0)
-- count = -1;
-- else
-- # endif
-- if (vim_strchr(buf, '`') != NULL
-- || expand_wildcards(1, &buf, &count, &files,
-- EW_FILE|EW_SILENT) != OK)
-- count = 0;
-- }
--
-- # ifdef FEAT_SPELL
-- if (count == -1)
-- {
-- /* Complete from active spelling. Skip "\<" in the pattern, we
-- * don't use it as a RE. */
-- if (pat[0] == '\\' && pat[1] == '<')
-- ptr = pat + 2;
-- else
-- ptr = pat;
-- spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
-- }
-- else
-- # endif
-- if (count > 0) /* avoid warning for using "files" uninit */
-- {
-- ins_compl_files(count, files, thesaurus, flags,
-- &regmatch, buf, &dir);
-- if (flags != DICT_EXACT)
-- FreeWild(count, files);
-- }
-- if (flags != 0)
-- break;
-- }
--
-- theend:
-- p_scs = save_p_scs;
-- vim_regfree(regmatch.regprog);
-- vim_free(buf);
-- }
--
-- static void
-- ins_compl_files(
-- int count,
-- char_u **files,
-- int thesaurus,
-- int flags,
-- regmatch_T *regmatch,
-- char_u *buf,
-- int *dir)
-- {
-- char_u *ptr;
-- int i;
-- FILE *fp;
-- int add_r;
--
-- for (i = 0; i < count && !got_int && !compl_interrupted; i++)
-- {
-- fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */
-- if (flags != DICT_EXACT)
-- {
-- vim_snprintf((char *)IObuff, IOSIZE,
-- _("Scanning dictionary: %s"), (char *)files[i]);
-- (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-- }
--
-- if (fp != NULL)
-- {
-- /*
-- * Read dictionary file line by line.
-- * Check each line for a match.
-- */
-- while (!got_int && !compl_interrupted
-- && !vim_fgets(buf, LSIZE, fp))
-- {
-- ptr = buf;
-- while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf)))
-- {
-- ptr = regmatch->startp[0];
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- ptr = find_line_end(ptr);
-- else
-- ptr = find_word_end(ptr);
-- add_r = ins_compl_add_infercase(regmatch->startp[0],
-- (int)(ptr - regmatch->startp[0]),
-- p_ic, files[i], *dir, 0);
-- if (thesaurus)
-- {
-- char_u *wstart;
--
-- /*
-- * Add the other matches on the line
-- */
-- ptr = buf;
-- while (!got_int)
-- {
-- /* Find start of the next word. Skip white
-- * space and punctuation. */
-- ptr = find_word_start(ptr);
-- if (*ptr == NUL || *ptr == NL)
-- break;
-- wstart = ptr;
--
-- /* Find end of the word. */
-- if (has_mbyte)
-- /* Japanese words may have characters in
-- * different classes, only separate words
-- * with single-byte non-word characters. */
-- while (*ptr != NUL)
-- {
-- int l = (*mb_ptr2len)(ptr);
--
-- if (l < 2 && !vim_iswordc(*ptr))
-- break;
-- ptr += l;
-- }
-- else
-- ptr = find_word_end(ptr);
--
-- /* Add the word. Skip the regexp match. */
-- if (wstart != regmatch->startp[0])
-- add_r = ins_compl_add_infercase(wstart,
-- (int)(ptr - wstart),
-- p_ic, files[i], *dir, 0);
-- }
-- }
-- if (add_r == OK)
-- /* if dir was BACKWARD then honor it just once */
-- *dir = FORWARD;
-- else if (add_r == FAIL)
-- break;
-- /* avoid expensive call to vim_regexec() when at end
-- * of line */
-- if (*ptr == '\n' || got_int)
-- break;
-- }
-- line_breakcheck();
-- ins_compl_check_keys(50, FALSE);
-- }
-- fclose(fp);
-- }
-- }
-- }
--
-- /*
-- * Find the start of the next word.
-- * Returns a pointer to the first char of the word. Also stops at a NUL.
-- */
-- char_u *
-- find_word_start(char_u *ptr)
-- {
-- if (has_mbyte)
-- while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
-- ptr += (*mb_ptr2len)(ptr);
-- else
-- while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
-- ++ptr;
-- return ptr;
-- }
--
-- /*
-- * Find the end of the word. Assumes it starts inside a word.
-- * Returns a pointer to just after the word.
-- */
-- char_u *
-- find_word_end(char_u *ptr)
-- {
-- int start_class;
--
-- if (has_mbyte)
-- {
-- start_class = mb_get_class(ptr);
-- if (start_class > 1)
-- while (*ptr != NUL)
-- {
-- ptr += (*mb_ptr2len)(ptr);
-- if (mb_get_class(ptr) != start_class)
-- break;
-- }
-- }
-- else
-- while (vim_iswordc(*ptr))
-- ++ptr;
-- return ptr;
-- }
--
-- /*
-- * Find the end of the line, omitting CR and NL at the end.
-- * Returns a pointer to just after the line.
-- */
-- static char_u *
-- find_line_end(char_u *ptr)
-- {
-- char_u *s;
--
-- s = ptr + STRLEN(ptr);
-- while (s > ptr && (s[-1] == CAR || s[-1] == NL))
-- --s;
-- return s;
-- }
--
-- /*
-- * Free the list of completions
-- */
-- static void
-- ins_compl_free(void)
-- {
-- compl_T *match;
-- int i;
--
-- VIM_CLEAR(compl_pattern);
-- VIM_CLEAR(compl_leader);
--
-- if (compl_first_match == NULL)
-- return;
--
-- ins_compl_del_pum();
-- pum_clear();
--
-- compl_curr_match = compl_first_match;
-- do
-- {
-- match = compl_curr_match;
-- compl_curr_match = compl_curr_match->cp_next;
-- vim_free(match->cp_str);
-- /* several entries may use the same fname, free it just once. */
-- if (match->cp_flags & FREE_FNAME)
-- vim_free(match->cp_fname);
-- for (i = 0; i < CPT_COUNT; ++i)
-- vim_free(match->cp_text[i]);
-- vim_free(match);
-- } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
-- compl_first_match = compl_curr_match = NULL;
-- compl_shown_match = NULL;
-- compl_old_match = NULL;
-- }
--
-- static void
-- ins_compl_clear(void)
-- {
-- compl_cont_status = 0;
-- compl_started = FALSE;
-- compl_matches = 0;
-- VIM_CLEAR(compl_pattern);
-- VIM_CLEAR(compl_leader);
-- edit_submode_extra = NULL;
-- VIM_CLEAR(compl_orig_text);
-- compl_enter_selects = FALSE;
-- /* clear v:completed_item */
-- set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
-- }
--
-- /*
-- * Return TRUE when Insert completion is active.
-- */
-- int
-- ins_compl_active(void)
-- {
-- return compl_started;
-- }
--
--
-- /*
-- * Get complete information
-- */
-- void
-- get_complete_info(list_T *what_list, dict_T *retdict)
-- {
-- int ret = OK;
-- listitem_T *item;
-- #define CI_WHAT_MODE 0x01
-- #define CI_WHAT_PUM_VISIBLE 0x02
-- #define CI_WHAT_ITEMS 0x04
-- #define CI_WHAT_SELECTED 0x08
-- #define CI_WHAT_INSERTED 0x10
-- #define CI_WHAT_ALL 0xff
-- int what_flag;
--
-- if (what_list == NULL)
-- what_flag = CI_WHAT_ALL;
-- else
-- {
-- what_flag = 0;
-- for (item = what_list->lv_first; item != NULL; item = item->li_next)
-- {
-- char_u *what = tv_get_string(&item->li_tv);
--
-- if (STRCMP(what, "mode") == 0)
-- what_flag |= CI_WHAT_MODE;
-- else if (STRCMP(what, "pum_visible") == 0)
-- what_flag |= CI_WHAT_PUM_VISIBLE;
-- else if (STRCMP(what, "items") == 0)
-- what_flag |= CI_WHAT_ITEMS;
-- else if (STRCMP(what, "selected") == 0)
-- what_flag |= CI_WHAT_SELECTED;
-- else if (STRCMP(what, "inserted") == 0)
-- what_flag |= CI_WHAT_INSERTED;
-- }
-- }
--
-- if (ret == OK && (what_flag & CI_WHAT_MODE))
-- ret = dict_add_string(retdict, "mode", ins_compl_mode());
--
-- if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE))
-- ret = dict_add_number(retdict, "pum_visible", pum_visible());
--
-- if (ret == OK && (what_flag & CI_WHAT_ITEMS))
-- {
-- list_T *li;
-- dict_T *di;
-- compl_T *match;
--
-- li = list_alloc();
-- if (li == NULL)
-- return;
-- ret = dict_add_list(retdict, "items", li);
-- if (ret == OK && compl_first_match != NULL)
-- {
-- match = compl_first_match;
-- do
-- {
-- if (!(match->cp_flags & ORIGINAL_TEXT))
-- {
-- di = dict_alloc();
-- if (di == NULL)
-- return;
-- ret = list_append_dict(li, di);
-- if (ret != OK)
-- return;
-- dict_add_string(di, "word", match->cp_str);
-- dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
-- dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
-- dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
-- dict_add_string(di, "info", match->cp_text[CPT_INFO]);
-- dict_add_string(di, "user_data",
-- match->cp_text[CPT_USER_DATA]);
-- }
-- match = match->cp_next;
-- }
-- while (match != NULL && match != compl_first_match);
-- }
-- }
--
-- if (ret == OK && (what_flag & CI_WHAT_SELECTED))
-- ret = dict_add_number(retdict, "selected", (compl_curr_match != NULL) ?
-- compl_curr_match->cp_number - 1 : -1);
--
-- // TODO
-- // if (ret == OK && (what_flag & CI_WHAT_INSERTED))
-- }
--
-- /*
-- * Return Insert completion mode name string
-- */
-- static char_u *
-- ins_compl_mode(void)
-- {
-- if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || compl_started)
-- return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
--
-- return (char_u *)"";
-- }
--
-- /*
-- * Delete one character before the cursor and show the subset of the matches
-- * that match the word that is now before the cursor.
-- * Returns the character to be used, NUL if the work is done and another char
-- * to be got from the user.
-- */
-- static int
-- ins_compl_bs(void)
-- {
-- char_u *line;
-- char_u *p;
--
-- line = ml_get_curline();
-- p = line + curwin->w_cursor.col;
-- MB_PTR_BACK(line, p);
--
-- /* Stop completion when the whole word was deleted. For Omni completion
-- * allow the word to be deleted, we won't match everything.
-- * Respect the 'backspace' option. */
-- if ((int)(p - line) - (int)compl_col < 0
-- || ((int)(p - line) - (int)compl_col == 0
-- && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL
-- || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
-- - compl_length < 0))
-- return K_BS;
--
-- /* Deleted more than what was used to find matches or didn't finish
-- * finding all matches: need to look for matches all over again. */
-- if (curwin->w_cursor.col <= compl_col + compl_length
-- || ins_compl_need_restart())
-- ins_compl_restart();
--
-- vim_free(compl_leader);
-- compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col);
-- if (compl_leader != NULL)
-- {
-- ins_compl_new_leader();
-- if (compl_shown_match != NULL)
-- /* Make sure current match is not a hidden item. */
-- compl_curr_match = compl_shown_match;
-- return NUL;
-- }
-- return K_BS;
-- }
--
-- /*
-- * Return TRUE when we need to find matches again, ins_compl_restart() is to
-- * be called.
-- */
-- static int
-- ins_compl_need_restart(void)
-- {
-- /* Return TRUE if we didn't complete finding matches or when the
-- * 'completefunc' returned "always" in the "refresh" dictionary item. */
-- return compl_was_interrupted
-- || ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
-- && compl_opt_refresh_always);
-- }
--
-- /*
-- * Called after changing "compl_leader".
-- * Show the popup menu with a different set of matches.
-- * May also search for matches again if the previous search was interrupted.
-- */
-- static void
-- ins_compl_new_leader(void)
-- {
-- ins_compl_del_pum();
-- ins_compl_delete();
-- ins_bytes(compl_leader + ins_compl_len());
-- compl_used_match = FALSE;
--
-- if (compl_started)
-- ins_compl_set_original_text(compl_leader);
-- else
-- {
-- #ifdef FEAT_SPELL
-- spell_bad_len = 0; /* need to redetect bad word */
-- #endif
-- /*
-- * Matches were cleared, need to search for them now. Befor drawing
-- * the popup menu display the changed text before the cursor. Set
-- * "compl_restarting" to avoid that the first match is inserted.
-- */
-- pum_call_update_screen();
-- #ifdef FEAT_GUI
-- if (gui.in_use)
-- {
-- /* Show the cursor after the match, not after the redrawn text. */
-- setcursor();
-- out_flush_cursor(FALSE, FALSE);
-- }
-- #endif
-- compl_restarting = TRUE;
-- if (ins_complete(Ctrl_N, TRUE) == FAIL)
-- compl_cont_status = 0;
-- compl_restarting = FALSE;
-- }
--
-- compl_enter_selects = !compl_used_match;
--
-- /* Show the popup menu with a different set of matches. */
-- ins_compl_show_pum();
--
-- /* Don't let Enter select the original text when there is no popup menu. */
-- if (compl_match_array == NULL)
-- compl_enter_selects = FALSE;
-- }
--
-- /*
-- * Return the length of the completion, from the completion start column to
-- * the cursor column. Making sure it never goes below zero.
-- */
-- static int
-- ins_compl_len(void)
-- {
-- int off = (int)curwin->w_cursor.col - (int)compl_col;
--
-- if (off < 0)
-- return 0;
-- return off;
-- }
--
-- /*
-- * Append one character to the match leader. May reduce the number of
-- * matches.
-- */
-- static void
-- ins_compl_addleader(int c)
-- {
-- int cc;
--
-- if (stop_arrow() == FAIL)
-- return;
-- if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
-- {
-- char_u buf[MB_MAXBYTES + 1];
--
-- (*mb_char2bytes)(c, buf);
-- buf[cc] = NUL;
-- ins_char_bytes(buf, cc);
-- if (compl_opt_refresh_always)
-- AppendToRedobuff(buf);
-- }
-- else
-- {
-- ins_char(c);
-- if (compl_opt_refresh_always)
-- AppendCharToRedobuff(c);
-- }
--
-- /* If we didn't complete finding matches we must search again. */
-- if (ins_compl_need_restart())
-- ins_compl_restart();
--
-- /* When 'always' is set, don't reset compl_leader. While completing,
-- * cursor doesn't point original position, changing compl_leader would
-- * break redo. */
-- if (!compl_opt_refresh_always)
-- {
-- vim_free(compl_leader);
-- compl_leader = vim_strnsave(ml_get_curline() + compl_col,
-- (int)(curwin->w_cursor.col - compl_col));
-- if (compl_leader != NULL)
-- ins_compl_new_leader();
-- }
-- }
--
-- /*
-- * Setup for finding completions again without leaving CTRL-X mode. Used when
-- * BS or a key was typed while still searching for matches.
-- */
-- static void
-- ins_compl_restart(void)
-- {
-- ins_compl_free();
-- compl_started = FALSE;
-- compl_matches = 0;
-- compl_cont_status = 0;
-- compl_cont_mode = 0;
-- }
--
-- /*
-- * Set the first match, the original text.
-- */
-- static void
-- ins_compl_set_original_text(char_u *str)
-- {
-- char_u *p;
--
-- /* Replace the original text entry.
-- * The ORIGINAL_TEXT flag is either at the first item or might possibly be
-- * at the last item for backward completion */
-- if (compl_first_match->cp_flags & ORIGINAL_TEXT) /* safety check */
-- {
-- p = vim_strsave(str);
-- if (p != NULL)
-- {
-- vim_free(compl_first_match->cp_str);
-- compl_first_match->cp_str = p;
-- }
-- }
-- else if (compl_first_match->cp_prev != NULL
-- && (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT))
-- {
-- p = vim_strsave(str);
-- if (p != NULL)
-- {
-- vim_free(compl_first_match->cp_prev->cp_str);
-- compl_first_match->cp_prev->cp_str = p;
-- }
-- }
-- }
--
-- /*
-- * Append one character to the match leader. May reduce the number of
-- * matches.
-- */
-- static void
-- ins_compl_addfrommatch(void)
-- {
-- char_u *p;
-- int len = (int)curwin->w_cursor.col - (int)compl_col;
-- int c;
-- compl_T *cp;
--
-- p = compl_shown_match->cp_str;
-- if ((int)STRLEN(p) <= len) /* the match is too short */
-- {
-- /* When still at the original match use the first entry that matches
-- * the leader. */
-- if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-- {
-- p = NULL;
-- for (cp = compl_shown_match->cp_next; cp != NULL
-- && cp != compl_first_match; cp = cp->cp_next)
-- {
-- if (compl_leader == NULL
-- || ins_compl_equal(cp, compl_leader,
-- (int)STRLEN(compl_leader)))
-- {
-- p = cp->cp_str;
-- break;
-- }
-- }
-- if (p == NULL || (int)STRLEN(p) <= len)
-- return;
-- }
-- else
-- return;
-- }
-- p += len;
-- c = PTR2CHAR(p);
-- ins_compl_addleader(c);
-- }
--
-- /*
-- * Prepare for Insert mode completion, or stop it.
-- * Called just after typing a character in Insert mode.
-- * Returns TRUE when the character is not to be inserted;
-- */
-- static int
-- ins_compl_prep(int c)
-- {
-- char_u *ptr;
-- int want_cindent;
-- int retval = FALSE;
--
-- /* Forget any previous 'special' messages if this is actually
-- * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
-- */
-- if (c != Ctrl_R && vim_is_ctrl_x_key(c))
-- edit_submode_extra = NULL;
--
-- /* Ignore end of Select mode mapping and mouse scroll buttons. */
-- if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
-- || c == K_MOUSELEFT || c == K_MOUSERIGHT)
-- return retval;
--
-- /* Set "compl_get_longest" when finding the first matches. */
-- if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
-- || (ctrl_x_mode == CTRL_X_NORMAL && !compl_started))
-- {
-- compl_get_longest = (strstr((char *)p_cot, "longest") != NULL);
-- compl_used_match = TRUE;
--
-- }
--
-- if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
-- {
-- /*
-- * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
-- * it will be yet. Now we decide.
-- */
-- switch (c)
-- {
-- case Ctrl_E:
-- case Ctrl_Y:
-- ctrl_x_mode = CTRL_X_SCROLL;
-- if (!(State & REPLACE_FLAG))
-- edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
-- else
-- edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
-- edit_submode_pre = NULL;
-- showmode();
-- break;
-- case Ctrl_L:
-- ctrl_x_mode = CTRL_X_WHOLE_LINE;
-- break;
-- case Ctrl_F:
-- ctrl_x_mode = CTRL_X_FILES;
-- break;
-- case Ctrl_K:
-- ctrl_x_mode = CTRL_X_DICTIONARY;
-- break;
-- case Ctrl_R:
-- /* Simply allow ^R to happen without affecting ^X mode */
-- break;
-- case Ctrl_T:
-- ctrl_x_mode = CTRL_X_THESAURUS;
-- break;
-- #ifdef FEAT_COMPL_FUNC
-- case Ctrl_U:
-- ctrl_x_mode = CTRL_X_FUNCTION;
-- break;
-- case Ctrl_O:
-- ctrl_x_mode = CTRL_X_OMNI;
-- break;
-- #endif
-- case 's':
-- case Ctrl_S:
-- ctrl_x_mode = CTRL_X_SPELL;
-- #ifdef FEAT_SPELL
-- ++emsg_off; /* Avoid getting the E756 error twice. */
-- spell_back_to_badword();
-- --emsg_off;
-- #endif
-- break;
-- case Ctrl_RSB:
-- ctrl_x_mode = CTRL_X_TAGS;
-- break;
-- #ifdef FEAT_FIND_ID
-- case Ctrl_I:
-- case K_S_TAB:
-- ctrl_x_mode = CTRL_X_PATH_PATTERNS;
-- break;
-- case Ctrl_D:
-- ctrl_x_mode = CTRL_X_PATH_DEFINES;
-- break;
-- #endif
-- case Ctrl_V:
-- case Ctrl_Q:
-- ctrl_x_mode = CTRL_X_CMDLINE;
-- break;
-- case Ctrl_P:
-- case Ctrl_N:
-- /* ^X^P means LOCAL expansion if nothing interrupted (eg we
-- * just started ^X mode, or there were enough ^X's to cancel
-- * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
-- * do normal expansion when interrupting a different mode (say
-- * ^X^F^X^P or ^P^X^X^P, see below)
-- * nothing changes if interrupting mode 0, (eg, the flag
-- * doesn't change when going to ADDING mode -- Acevedo */
-- if (!(compl_cont_status & CONT_INTRPT))
-- compl_cont_status |= CONT_LOCAL;
-- else if (compl_cont_mode != 0)
-- compl_cont_status &= ~CONT_LOCAL;
-- /* FALLTHROUGH */
-- default:
-- /* If we have typed at least 2 ^X's... for modes != 0, we set
-- * compl_cont_status = 0 (eg, as if we had just started ^X
-- * mode).
-- * For mode 0, we set "compl_cont_mode" to an impossible
-- * value, in both cases ^X^X can be used to restart the same
-- * mode (avoiding ADDING mode).
-- * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
-- * 'complete' and local ^P expansions respectively.
-- * In mode 0 an extra ^X is needed since ^X^P goes to ADDING
-- * mode -- Acevedo */
-- if (c == Ctrl_X)
-- {
-- if (compl_cont_mode != 0)
-- compl_cont_status = 0;
-- else
-- compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
-- }
-- ctrl_x_mode = CTRL_X_NORMAL;
-- edit_submode = NULL;
-- showmode();
-- break;
-- }
-- }
-- else if (ctrl_x_mode != CTRL_X_NORMAL)
-- {
-- /* We're already in CTRL-X mode, do we stay in it? */
-- if (!vim_is_ctrl_x_key(c))
-- {
-- if (ctrl_x_mode == CTRL_X_SCROLL)
-- ctrl_x_mode = CTRL_X_NORMAL;
-- else
-- ctrl_x_mode = CTRL_X_FINISHED;
-- edit_submode = NULL;
-- }
-- showmode();
-- }
--
-- if (compl_started || ctrl_x_mode == CTRL_X_FINISHED)
-- {
-- /* Show error message from attempted keyword completion (probably
-- * 'Pattern not found') until another key is hit, then go back to
-- * showing what mode we are in. */
-- showmode();
-- if ((ctrl_x_mode == CTRL_X_NORMAL && c != Ctrl_N && c != Ctrl_P
-- && c != Ctrl_R && !ins_compl_pum_key(c))
-- || ctrl_x_mode == CTRL_X_FINISHED)
-- {
-- /* Get here when we have finished typing a sequence of ^N and
-- * ^P or other completion characters in CTRL-X mode. Free up
-- * memory that was used, and make sure we can redo the insert. */
-- if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
-- {
-- /*
-- * If any of the original typed text has been changed, eg when
-- * ignorecase is set, we must add back-spaces to the redo
-- * buffer. We add as few as necessary to delete just the part
-- * of the original text that has changed.
-- * When using the longest match, edited the match or used
-- * CTRL-E then don't use the current match.
-- */
-- if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
-- ptr = compl_curr_match->cp_str;
-- else
-- ptr = NULL;
-- ins_compl_fixRedoBufForLeader(ptr);
-- }
--
-- #ifdef FEAT_CINDENT
-- want_cindent = (can_cindent && cindent_on());
-- #endif
-- /*
-- * When completing whole lines: fix indent for 'cindent'.
-- * Otherwise, break line if it's too long.
-- */
-- if (compl_cont_mode == CTRL_X_WHOLE_LINE)
-- {
-- #ifdef FEAT_CINDENT
-- /* re-indent the current line */
-- if (want_cindent)
-- {
-- do_c_expr_indent();
-- want_cindent = FALSE; /* don't do it again */
-- }
-- #endif
-- }
-- else
-- {
-- int prev_col = curwin->w_cursor.col;
--
-- /* put the cursor on the last char, for 'tw' formatting */
-- if (prev_col > 0)
-- dec_cursor();
-- /* only format when something was inserted */
-- if (!arrow_used && !ins_need_undo && c != Ctrl_E)
-- insertchar(NUL, 0, -1);
-- if (prev_col > 0
-- && ml_get_curline()[curwin->w_cursor.col] != NUL)
-- inc_cursor();
-- }
--
-- /* If the popup menu is displayed pressing CTRL-Y means accepting
-- * the selection without inserting anything. When
-- * compl_enter_selects is set the Enter key does the same. */
-- if ((c == Ctrl_Y || (compl_enter_selects
-- && (c == CAR || c == K_KENTER || c == NL)))
-- && pum_visible())
-- retval = TRUE;
--
-- /* CTRL-E means completion is Ended, go back to the typed text.
-- * but only do this, if the Popup is still visible */
-- if (c == Ctrl_E)
-- {
-- ins_compl_delete();
-- if (compl_leader != NULL)
-- ins_bytes(compl_leader + ins_compl_len());
-- else if (compl_first_match != NULL)
-- ins_bytes(compl_orig_text + ins_compl_len());
-- retval = TRUE;
-- }
--
-- auto_format(FALSE, TRUE);
--
-- ins_compl_free();
-- compl_started = FALSE;
-- compl_matches = 0;
-- if (!shortmess(SHM_COMPLETIONMENU))
-- msg_clr_cmdline(); /* necessary for "noshowmode" */
-- ctrl_x_mode = CTRL_X_NORMAL;
-- compl_enter_selects = FALSE;
-- if (edit_submode != NULL)
-- {
-- edit_submode = NULL;
-- showmode();
-- }
--
-- #ifdef FEAT_CMDWIN
-- if (c == Ctrl_C && cmdwin_type != 0)
-- /* Avoid the popup menu remains displayed when leaving the
-- * command line window. */
-- update_screen(0);
-- #endif
-- #ifdef FEAT_CINDENT
-- /*
-- * Indent now if a key was typed that is in 'cinkeys'.
-- */
-- if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
-- do_c_expr_indent();
-- #endif
-- /* Trigger the CompleteDone event to give scripts a chance to act
-- * upon the completion. */
-- ins_apply_autocmds(EVENT_COMPLETEDONE);
-- }
-- }
-- else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
-- /* Trigger the CompleteDone event to give scripts a chance to act
-- * upon the (possibly failed) completion. */
-- ins_apply_autocmds(EVENT_COMPLETEDONE);
--
-- /* reset continue_* if we left expansion-mode, if we stay they'll be
-- * (re)set properly in ins_complete() */
-- if (!vim_is_ctrl_x_key(c))
-- {
-- compl_cont_status = 0;
-- compl_cont_mode = 0;
-- }
--
-- return retval;
-- }
--
-- /*
-- * Fix the redo buffer for the completion leader replacing some of the typed
-- * text. This inserts backspaces and appends the changed text.
-- * "ptr" is the known leader text or NUL.
-- */
-- static void
-- ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
-- {
-- int len;
-- char_u *p;
-- char_u *ptr = ptr_arg;
--
-- if (ptr == NULL)
-- {
-- if (compl_leader != NULL)
-- ptr = compl_leader;
-- else
-- return; /* nothing to do */
-- }
-- if (compl_orig_text != NULL)
-- {
-- p = compl_orig_text;
-- for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len)
-- ;
-- if (len > 0)
-- len -= (*mb_head_off)(p, p + len);
-- for (p += len; *p != NUL; MB_PTR_ADV(p))
-- AppendCharToRedobuff(K_BS);
-- }
-- else
-- len = 0;
-- if (ptr != NULL)
-- AppendToRedobuffLit(ptr + len, -1);
-- }
--
-- /*
-- * Loops through the list of windows, loaded-buffers or non-loaded-buffers
-- * (depending on flag) starting from buf and looking for a non-scanned
-- * buffer (other than curbuf). curbuf is special, if it is called with
-- * buf=curbuf then it has to be the first call for a given flag/expansion.
-- *
-- * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
-- */
-- static buf_T *
-- ins_compl_next_buf(buf_T *buf, int flag)
-- {
-- static win_T *wp = NULL;
--
-- if (flag == 'w') // just windows
-- {
-- if (buf == curbuf || wp == NULL) // first call for this flag/expansion
-- wp = curwin;
-- while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
-- && wp->w_buffer->b_scanned)
-- ;
-- buf = wp->w_buffer;
-- }
-- else
-- /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
-- * (unlisted buffers)
-- * When completing whole lines skip unloaded buffers. */
-- while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf
-- && ((flag == 'U'
-- ? buf->b_p_bl
-- : (!buf->b_p_bl
-- || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
-- || buf->b_scanned))
-- ;
-- return buf;
-- }
--
-- #ifdef FEAT_COMPL_FUNC
-- /*
-- * Execute user defined complete function 'completefunc' or 'omnifunc', and
-- * get matches in "matches".
-- */
-- static void
-- expand_by_function(
-- int type, /* CTRL_X_OMNI or CTRL_X_FUNCTION */
-- char_u *base)
-- {
-- list_T *matchlist = NULL;
-- dict_T *matchdict = NULL;
-- typval_T args[3];
-- char_u *funcname;
-- pos_T pos;
-- win_T *curwin_save;
-- buf_T *curbuf_save;
-- typval_T rettv;
-- int save_State = State;
--
-- funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
-- if (*funcname == NUL)
-- return;
--
-- /* Call 'completefunc' to obtain the list of matches. */
-- args[0].v_type = VAR_NUMBER;
-- args[0].vval.v_number = 0;
-- args[1].v_type = VAR_STRING;
-- args[1].vval.v_string = base != NULL ? base : (char_u *)"";
-- args[2].v_type = VAR_UNKNOWN;
--
-- pos = curwin->w_cursor;
-- curwin_save = curwin;
-- curbuf_save = curbuf;
--
-- /* Call a function, which returns a list or dict. */
-- if (call_vim_function(funcname, 2, args, &rettv) == OK)
-- {
-- switch (rettv.v_type)
-- {
-- case VAR_LIST:
-- matchlist = rettv.vval.v_list;
-- break;
-- case VAR_DICT:
-- matchdict = rettv.vval.v_dict;
-- break;
-- case VAR_SPECIAL:
-- if (rettv.vval.v_number == VVAL_NONE)
-- compl_opt_suppress_empty = TRUE;
-- // FALLTHROUGH
-- default:
-- // TODO: Give error message?
-- clear_tv(&rettv);
-- break;
-- }
-- }
--
-- if (curwin_save != curwin || curbuf_save != curbuf)
-- {
-- emsg(_(e_complwin));
-- goto theend;
-- }
-- curwin->w_cursor = pos; /* restore the cursor position */
-- validate_cursor();
-- if (!EQUAL_POS(curwin->w_cursor, pos))
-- {
-- emsg(_(e_compldel));
-- goto theend;
-- }
--
-- if (matchlist != NULL)
-- ins_compl_add_list(matchlist);
-- else if (matchdict != NULL)
-- ins_compl_add_dict(matchdict);
--
-- theend:
-- // Restore State, it might have been changed.
-- State = save_State;
--
-- if (matchdict != NULL)
-- dict_unref(matchdict);
-- if (matchlist != NULL)
-- list_unref(matchlist);
-- }
-- #endif /* FEAT_COMPL_FUNC */
--
-- #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO)
-- /*
-- * Add completions from a list.
-- */
-- static void
-- ins_compl_add_list(list_T *list)
-- {
-- listitem_T *li;
-- int dir = compl_direction;
--
-- /* Go through the List with matches and add each of them. */
-- for (li = list->lv_first; li != NULL; li = li->li_next)
-- {
-- if (ins_compl_add_tv(&li->li_tv, dir) == OK)
-- /* if dir was BACKWARD then honor it just once */
-- dir = FORWARD;
-- else if (did_emsg)
-- break;
-- }
-- }
--
-- /*
-- * Add completions from a dict.
-- */
-- static void
-- ins_compl_add_dict(dict_T *dict)
-- {
-- dictitem_T *di_refresh;
-- dictitem_T *di_words;
--
-- /* Check for optional "refresh" item. */
-- compl_opt_refresh_always = FALSE;
-- di_refresh = dict_find(dict, (char_u *)"refresh", 7);
-- if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING)
-- {
-- char_u *v = di_refresh->di_tv.vval.v_string;
--
-- if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
-- compl_opt_refresh_always = TRUE;
-- }
--
-- /* Add completions from a "words" list. */
-- di_words = dict_find(dict, (char_u *)"words", 5);
-- if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
-- ins_compl_add_list(di_words->di_tv.vval.v_list);
-- }
--
-- /*
-- * Add a match to the list of matches from a typeval_T.
-- * If the given string is already in the list of completions, then return
-- * NOTDONE, otherwise add it to the list and return OK. If there is an error,
-- * maybe because alloc() returns NULL, then FAIL is returned.
-- */
-- int
-- ins_compl_add_tv(typval_T *tv, int dir)
-- {
-- char_u *word;
-- int icase = FALSE;
-- int adup = FALSE;
-- int aempty = FALSE;
-- char_u *(cptext[CPT_COUNT]);
--
-- if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
-- {
-- word = dict_get_string(tv->vval.v_dict, (char_u *)"word", FALSE);
-- cptext[CPT_ABBR] = dict_get_string(tv->vval.v_dict,
-- (char_u *)"abbr", FALSE);
-- cptext[CPT_MENU] = dict_get_string(tv->vval.v_dict,
-- (char_u *)"menu", FALSE);
-- cptext[CPT_KIND] = dict_get_string(tv->vval.v_dict,
-- (char_u *)"kind", FALSE);
-- cptext[CPT_INFO] = dict_get_string(tv->vval.v_dict,
-- (char_u *)"info", FALSE);
-- cptext[CPT_USER_DATA] = dict_get_string(tv->vval.v_dict,
-- (char_u *)"user_data", FALSE);
-- if (dict_get_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL)
-- icase = dict_get_number(tv->vval.v_dict, (char_u *)"icase");
-- if (dict_get_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
-- adup = dict_get_number(tv->vval.v_dict, (char_u *)"dup");
-- if (dict_get_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL)
-- aempty = dict_get_number(tv->vval.v_dict, (char_u *)"empty");
-- }
-- else
-- {
-- word = tv_get_string_chk(tv);
-- vim_memset(cptext, 0, sizeof(cptext));
-- }
-- if (word == NULL || (!aempty && *word == NUL))
-- return FAIL;
-- return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
-- }
-- #endif
--
-- /*
-- * Get the next expansion(s), using "compl_pattern".
-- * The search starts at position "ini" in curbuf and in the direction
-- * compl_direction.
-- * When "compl_started" is FALSE start at that position, otherwise continue
-- * where we stopped searching before.
-- * This may return before finding all the matches.
-- * Return the total number of matches or -1 if still unknown -- Acevedo
-- */
-- static int
-- ins_compl_get_exp(pos_T *ini)
-- {
-- static pos_T first_match_pos;
-- static pos_T last_match_pos;
-- static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */
-- static int found_all = FALSE; /* Found all matches of a
-- certain type. */
-- static buf_T *ins_buf = NULL; /* buffer being scanned */
--
-- pos_T *pos;
-- char_u **matches;
-- int save_p_scs;
-- int save_p_ws;
-- int save_p_ic;
-- int i;
-- int num_matches;
-- int len;
-- int found_new_match;
-- int type = ctrl_x_mode;
-- char_u *ptr;
-- char_u *dict = NULL;
-- int dict_f = 0;
-- int set_match_pos;
--
-- if (!compl_started)
-- {
-- FOR_ALL_BUFFERS(ins_buf)
-- ins_buf->b_scanned = 0;
-- found_all = FALSE;
-- ins_buf = curbuf;
-- e_cpt = (compl_cont_status & CONT_LOCAL)
-- ? (char_u *)"." : curbuf->b_p_cpt;
-- last_match_pos = first_match_pos = *ini;
-- }
-- else if (ins_buf != curbuf && !buf_valid(ins_buf))
-- ins_buf = curbuf; // In case the buffer was wiped out.
--
-- compl_old_match = compl_curr_match; /* remember the last current match */
-- pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
--
-- /*
-- * For ^N/^P loop over all the flags/windows/buffers in 'complete'.
-- */
-- for (;;)
-- {
-- found_new_match = FAIL;
-- set_match_pos = FALSE;
--
-- /* For ^N/^P pick a new entry from e_cpt if compl_started is off,
-- * or if found_all says this entry is done. For ^X^L only use the
-- * entries from 'complete' that look in loaded buffers. */
-- if ((ctrl_x_mode == CTRL_X_NORMAL
-- || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- && (!compl_started || found_all))
-- {
-- found_all = FALSE;
-- while (*e_cpt == ',' || *e_cpt == ' ')
-- e_cpt++;
-- if (*e_cpt == '.' && !curbuf->b_scanned)
-- {
-- ins_buf = curbuf;
-- first_match_pos = *ini;
-- /* Move the cursor back one character so that ^N can match the
-- * word immediately after the cursor. */
-- if (ctrl_x_mode == CTRL_X_NORMAL && dec(&first_match_pos) < 0)
-- {
-- /* Move the cursor to after the last character in the
-- * buffer, so that word at start of buffer is found
-- * correctly. */
-- first_match_pos.lnum = ins_buf->b_ml.ml_line_count;
-- first_match_pos.col =
-- (colnr_T)STRLEN(ml_get(first_match_pos.lnum));
-- }
-- last_match_pos = first_match_pos;
-- type = 0;
--
-- /* Remember the first match so that the loop stops when we
-- * wrap and come back there a second time. */
-- set_match_pos = TRUE;
-- }
-- else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
-- && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
-- {
-- /* Scan a buffer, but not the current one. */
-- if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */
-- {
-- compl_started = TRUE;
-- first_match_pos.col = last_match_pos.col = 0;
-- first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
-- last_match_pos.lnum = 0;
-- type = 0;
-- }
-- else /* unloaded buffer, scan like dictionary */
-- {
-- found_all = TRUE;
-- if (ins_buf->b_fname == NULL)
-- continue;
-- type = CTRL_X_DICTIONARY;
-- dict = ins_buf->b_fname;
-- dict_f = DICT_EXACT;
-- }
-- vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
-- ins_buf->b_fname == NULL
-- ? buf_spname(ins_buf)
-- : ins_buf->b_sfname == NULL
-- ? ins_buf->b_fname
-- : ins_buf->b_sfname);
-- (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-- }
-- else if (*e_cpt == NUL)
-- break;
-- else
-- {
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- type = -1;
-- else if (*e_cpt == 'k' || *e_cpt == 's')
-- {
-- if (*e_cpt == 'k')
-- type = CTRL_X_DICTIONARY;
-- else
-- type = CTRL_X_THESAURUS;
-- if (*++e_cpt != ',' && *e_cpt != NUL)
-- {
-- dict = e_cpt;
-- dict_f = DICT_FIRST;
-- }
-- }
-- #ifdef FEAT_FIND_ID
-- else if (*e_cpt == 'i')
-- type = CTRL_X_PATH_PATTERNS;
-- else if (*e_cpt == 'd')
-- type = CTRL_X_PATH_DEFINES;
-- #endif
-- else if (*e_cpt == ']' || *e_cpt == 't')
-- {
-- type = CTRL_X_TAGS;
-- vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags."));
-- (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-- }
-- else
-- type = -1;
--
-- /* in any case e_cpt is advanced to the next entry */
-- (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
--
-- found_all = TRUE;
-- if (type == -1)
-- continue;
-- }
-- }
--
-- /* If complete() was called then compl_pattern has been reset. The
-- * following won't work then, bail out. */
-- if (compl_pattern == NULL)
-- break;
--
-- switch (type)
-- {
-- case -1:
-- break;
-- #ifdef FEAT_FIND_ID
-- case CTRL_X_PATH_PATTERNS:
-- case CTRL_X_PATH_DEFINES:
-- find_pattern_in_path(compl_pattern, compl_direction,
-- (int)STRLEN(compl_pattern), FALSE, FALSE,
-- (type == CTRL_X_PATH_DEFINES
-- && !(compl_cont_status & CONT_SOL))
-- ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
-- (linenr_T)1, (linenr_T)MAXLNUM);
-- break;
-- #endif
--
-- case CTRL_X_DICTIONARY:
-- case CTRL_X_THESAURUS:
-- ins_compl_dictionaries(
-- dict != NULL ? dict
-- : (type == CTRL_X_THESAURUS
-- ? (*curbuf->b_p_tsr == NUL
-- ? p_tsr
-- : curbuf->b_p_tsr)
-- : (*curbuf->b_p_dict == NUL
-- ? p_dict
-- : curbuf->b_p_dict)),
-- compl_pattern,
-- dict != NULL ? dict_f
-- : 0, type == CTRL_X_THESAURUS);
-- dict = NULL;
-- break;
--
-- case CTRL_X_TAGS:
-- /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
-- save_p_ic = p_ic;
-- p_ic = ignorecase(compl_pattern);
--
-- /* Find up to TAG_MANY matches. Avoids that an enormous number
-- * of matches is found when compl_pattern is empty */
-- if (find_tags(compl_pattern, &num_matches, &matches,
-- TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
-- | (ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
-- TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
-- {
-- ins_compl_add_matches(num_matches, matches, p_ic);
-- }
-- p_ic = save_p_ic;
-- break;
--
-- case CTRL_X_FILES:
-- if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
-- EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
-- {
--
-- /* May change home directory back to "~". */
-- tilde_replace(compl_pattern, num_matches, matches);
-- ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
-- }
-- break;
--
-- case CTRL_X_CMDLINE:
-- if (expand_cmdline(&compl_xp, compl_pattern,
-- (int)STRLEN(compl_pattern),
-- &num_matches, &matches) == EXPAND_OK)
-- ins_compl_add_matches(num_matches, matches, FALSE);
-- break;
--
-- #ifdef FEAT_COMPL_FUNC
-- case CTRL_X_FUNCTION:
-- case CTRL_X_OMNI:
-- expand_by_function(type, compl_pattern);
-- break;
-- #endif
--
-- case CTRL_X_SPELL:
-- #ifdef FEAT_SPELL
-- num_matches = expand_spelling(first_match_pos.lnum,
-- compl_pattern, &matches);
-- if (num_matches > 0)
-- ins_compl_add_matches(num_matches, matches, p_ic);
-- #endif
-- break;
--
-- default: /* normal ^P/^N and ^X^L */
-- /*
-- * If 'infercase' is set, don't use 'smartcase' here
-- */
-- save_p_scs = p_scs;
-- if (ins_buf->b_p_inf)
-- p_scs = FALSE;
--
-- /* Buffers other than curbuf are scanned from the beginning or the
-- * end but never from the middle, thus setting nowrapscan in this
-- * buffers is a good idea, on the other hand, we always set
-- * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
-- save_p_ws = p_ws;
-- if (ins_buf != curbuf)
-- p_ws = FALSE;
-- else if (*e_cpt == '.')
-- p_ws = TRUE;
-- for (;;)
-- {
-- int flags = 0;
--
-- ++msg_silent; /* Don't want messages for wrapscan. */
--
-- /* CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
-- * || word-wise search that
-- * has added a word that was at the beginning of the line */
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)
-- || (compl_cont_status & CONT_SOL))
-- found_new_match = search_for_exact_line(ins_buf, pos,
-- compl_direction, compl_pattern);
-- else
-- found_new_match = searchit(NULL, ins_buf, pos, NULL,
-- compl_direction,
-- compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
-- RE_LAST, (linenr_T)0, NULL, NULL);
-- --msg_silent;
-- if (!compl_started || set_match_pos)
-- {
-- /* set "compl_started" even on fail */
-- compl_started = TRUE;
-- first_match_pos = *pos;
-- last_match_pos = *pos;
-- set_match_pos = FALSE;
-- }
-- else if (first_match_pos.lnum == last_match_pos.lnum
-- && first_match_pos.col == last_match_pos.col)
-- found_new_match = FAIL;
-- if (found_new_match == FAIL)
-- {
-- if (ins_buf == curbuf)
-- found_all = TRUE;
-- break;
-- }
--
-- /* when ADDING, the text before the cursor matches, skip it */
-- if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf
-- && ini->lnum == pos->lnum
-- && ini->col == pos->col)
-- continue;
-- ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- {
-- if (compl_cont_status & CONT_ADDING)
-- {
-- if (pos->lnum >= ins_buf->b_ml.ml_line_count)
-- continue;
-- ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
-- if (!p_paste)
-- ptr = skipwhite(ptr);
-- }
-- len = (int)STRLEN(ptr);
-- }
-- else
-- {
-- char_u *tmp_ptr = ptr;
--
-- if (compl_cont_status & CONT_ADDING)
-- {
-- tmp_ptr += compl_length;
-- /* Skip if already inside a word. */
-- if (vim_iswordp(tmp_ptr))
-- continue;
-- /* Find start of next word. */
-- tmp_ptr = find_word_start(tmp_ptr);
-- }
-- /* Find end of this word. */
-- tmp_ptr = find_word_end(tmp_ptr);
-- len = (int)(tmp_ptr - ptr);
--
-- if ((compl_cont_status & CONT_ADDING)
-- && len == compl_length)
-- {
-- if (pos->lnum < ins_buf->b_ml.ml_line_count)
-- {
-- /* Try next line, if any. the new word will be
-- * "join" as if the normal command "J" was used.
-- * IOSIZE is always greater than
-- * compl_length, so the next STRNCPY always
-- * works -- Acevedo */
-- STRNCPY(IObuff, ptr, len);
-- ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
-- tmp_ptr = ptr = skipwhite(ptr);
-- /* Find start of next word. */
-- tmp_ptr = find_word_start(tmp_ptr);
-- /* Find end of next word. */
-- tmp_ptr = find_word_end(tmp_ptr);
-- if (tmp_ptr > ptr)
-- {
-- if (*ptr != ')' && IObuff[len - 1] != TAB)
-- {
-- if (IObuff[len - 1] != ' ')
-- IObuff[len++] = ' ';
-- /* IObuf =~ "\k.* ", thus len >= 2 */
-- if (p_js
-- && (IObuff[len - 2] == '.'
-- || (vim_strchr(p_cpo, CPO_JOINSP)
-- == NULL
-- && (IObuff[len - 2] == '?'
-- || IObuff[len - 2] == '!'))))
-- IObuff[len++] = ' ';
-- }
-- /* copy as much as possible of the new word */
-- if (tmp_ptr - ptr >= IOSIZE - len)
-- tmp_ptr = ptr + IOSIZE - len - 1;
-- STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
-- len += (int)(tmp_ptr - ptr);
-- flags |= CONT_S_IPOS;
-- }
-- IObuff[len] = NUL;
-- ptr = IObuff;
-- }
-- if (len == compl_length)
-- continue;
-- }
-- }
-- if (ins_compl_add_infercase(ptr, len, p_ic,
-- ins_buf == curbuf ? NULL : ins_buf->b_sfname,
-- 0, flags) != NOTDONE)
-- {
-- found_new_match = OK;
-- break;
-- }
-- }
-- p_scs = save_p_scs;
-- p_ws = save_p_ws;
-- }
--
-- /* check if compl_curr_match has changed, (e.g. other type of
-- * expansion added something) */
-- if (type != 0 && compl_curr_match != compl_old_match)
-- found_new_match = OK;
--
-- /* break the loop for specialized modes (use 'complete' just for the
-- * generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new
-- * match */
-- if ((ctrl_x_mode != CTRL_X_NORMAL
-- && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- || found_new_match != FAIL)
-- {
-- if (got_int)
-- break;
-- /* Fill the popup menu as soon as possible. */
-- if (type != -1)
-- ins_compl_check_keys(0, FALSE);
--
-- if ((ctrl_x_mode != CTRL_X_NORMAL
-- && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- || compl_interrupted)
-- break;
-- compl_started = TRUE;
-- }
-- else
-- {
-- /* Mark a buffer scanned when it has been scanned completely */
-- if (type == 0 || type == CTRL_X_PATH_PATTERNS)
-- ins_buf->b_scanned = TRUE;
--
-- compl_started = FALSE;
-- }
-- }
-- compl_started = TRUE;
--
-- if ((ctrl_x_mode == CTRL_X_NORMAL || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- && *e_cpt == NUL) /* Got to end of 'complete' */
-- found_new_match = FAIL;
--
-- i = -1; /* total of matches, unknown */
-- if (found_new_match == FAIL || (ctrl_x_mode != CTRL_X_NORMAL
-- && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)))
-- i = ins_compl_make_cyclic();
--
-- if (compl_old_match != NULL)
-- {
-- /* If several matches were added (FORWARD) or the search failed and has
-- * just been made cyclic then we have to move compl_curr_match to the
-- * next or previous entry (if any) -- Acevedo */
-- compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next
-- : compl_old_match->cp_prev;
-- if (compl_curr_match == NULL)
-- compl_curr_match = compl_old_match;
-- }
-- return i;
-- }
--
-- /* Delete the old text being completed. */
-- static void
-- ins_compl_delete(void)
-- {
-- int col;
--
-- /*
-- * In insert mode: Delete the typed part.
-- * In replace mode: Put the old characters back, if any.
-- */
-- col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
-- if ((int)curwin->w_cursor.col > col)
-- {
-- if (stop_arrow() == FAIL)
-- return;
-- backspace_until_column(col);
-- }
--
-- /* TODO: is this sufficient for redrawing? Redrawing everything causes
-- * flicker, thus we can't do that. */
-- changed_cline_bef_curs();
-- /* clear v:completed_item */
-- set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
-- }
--
-- /*
-- * Insert the new text being completed.
-- * "in_compl_func" is TRUE when called from complete_check().
-- */
-- static void
-- ins_compl_insert(int in_compl_func)
-- {
-- dict_T *dict;
--
-- ins_bytes(compl_shown_match->cp_str + ins_compl_len());
-- if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-- compl_used_match = FALSE;
-- else
-- compl_used_match = TRUE;
--
-- /* Set completed item. */
-- /* { word, abbr, menu, kind, info } */
-- dict = dict_alloc_lock(VAR_FIXED);
-- if (dict != NULL)
-- {
-- dict_add_string(dict, "word", compl_shown_match->cp_str);
-- dict_add_string(dict, "abbr", compl_shown_match->cp_text[CPT_ABBR]);
-- dict_add_string(dict, "menu", compl_shown_match->cp_text[CPT_MENU]);
-- dict_add_string(dict, "kind", compl_shown_match->cp_text[CPT_KIND]);
-- dict_add_string(dict, "info", compl_shown_match->cp_text[CPT_INFO]);
-- dict_add_string(dict, "user_data",
-- compl_shown_match->cp_text[CPT_USER_DATA]);
-- }
-- set_vim_var_dict(VV_COMPLETED_ITEM, dict);
-- if (!in_compl_func)
-- compl_curr_match = compl_shown_match;
-- }
--
-- /*
-- * Fill in the next completion in the current direction.
-- * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to
-- * get more completions. If it is FALSE, then we just do nothing when there
-- * are no more completions in a given direction. The latter case is used when
-- * we are still in the middle of finding completions, to allow browsing
-- * through the ones found so far.
-- * Return the total number of matches, or -1 if still unknown -- webb.
-- *
-- * compl_curr_match is currently being used by ins_compl_get_exp(), so we use
-- * compl_shown_match here.
-- *
-- * Note that this function may be called recursively once only. First with
-- * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn
-- * calls this function with "allow_get_expansion" FALSE.
-- */
-- static int
-- ins_compl_next(
-- int allow_get_expansion,
-- int count, /* repeat completion this many times; should
-- be at least 1 */
-- int insert_match, /* Insert the newly selected match */
-- int in_compl_func) /* called from complete_check() */
-- {
-- int num_matches = -1;
-- int todo = count;
-- compl_T *found_compl = NULL;
-- int found_end = FALSE;
-- int advance;
-- int started = compl_started;
--
-- /* When user complete function return -1 for findstart which is next
-- * time of 'always', compl_shown_match become NULL. */
-- if (compl_shown_match == NULL)
-- return -1;
--
-- if (compl_leader != NULL
-- && (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0)
-- {
-- /* Set "compl_shown_match" to the actually shown match, it may differ
-- * when "compl_leader" is used to omit some of the matches. */
-- while (!ins_compl_equal(compl_shown_match,
-- compl_leader, (int)STRLEN(compl_leader))
-- && compl_shown_match->cp_next != NULL
-- && compl_shown_match->cp_next != compl_first_match)
-- compl_shown_match = compl_shown_match->cp_next;
--
-- /* If we didn't find it searching forward, and compl_shows_dir is
-- * backward, find the last match. */
-- if (compl_shows_dir == BACKWARD
-- && !ins_compl_equal(compl_shown_match,
-- compl_leader, (int)STRLEN(compl_leader))
-- && (compl_shown_match->cp_next == NULL
-- || compl_shown_match->cp_next == compl_first_match))
-- {
-- while (!ins_compl_equal(compl_shown_match,
-- compl_leader, (int)STRLEN(compl_leader))
-- && compl_shown_match->cp_prev != NULL
-- && compl_shown_match->cp_prev != compl_first_match)
-- compl_shown_match = compl_shown_match->cp_prev;
-- }
-- }
--
-- if (allow_get_expansion && insert_match
-- && (!(compl_get_longest || compl_restarting) || compl_used_match))
-- /* Delete old text to be replaced */
-- ins_compl_delete();
--
-- /* When finding the longest common text we stick at the original text,
-- * don't let CTRL-N or CTRL-P move to the first match. */
-- advance = count != 1 || !allow_get_expansion || !compl_get_longest;
--
-- /* When restarting the search don't insert the first match either. */
-- if (compl_restarting)
-- {
-- advance = FALSE;
-- compl_restarting = FALSE;
-- }
--
-- /* Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
-- * around. */
-- while (--todo >= 0)
-- {
-- if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL)
-- {
-- compl_shown_match = compl_shown_match->cp_next;
-- found_end = (compl_first_match != NULL
-- && (compl_shown_match->cp_next == compl_first_match
-- || compl_shown_match == compl_first_match));
-- }
-- else if (compl_shows_dir == BACKWARD
-- && compl_shown_match->cp_prev != NULL)
-- {
-- found_end = (compl_shown_match == compl_first_match);
-- compl_shown_match = compl_shown_match->cp_prev;
-- found_end |= (compl_shown_match == compl_first_match);
-- }
-- else
-- {
-- if (!allow_get_expansion)
-- {
-- if (advance)
-- {
-- if (compl_shows_dir == BACKWARD)
-- compl_pending -= todo + 1;
-- else
-- compl_pending += todo + 1;
-- }
-- return -1;
-- }
--
-- if (!compl_no_select && advance)
-- {
-- if (compl_shows_dir == BACKWARD)
-- --compl_pending;
-- else
-- ++compl_pending;
-- }
--
-- /* Find matches. */
-- num_matches = ins_compl_get_exp(&compl_startpos);
--
-- /* handle any pending completions */
-- while (compl_pending != 0 && compl_direction == compl_shows_dir
-- && advance)
-- {
-- if (compl_pending > 0 && compl_shown_match->cp_next != NULL)
-- {
-- compl_shown_match = compl_shown_match->cp_next;
-- --compl_pending;
-- }
-- if (compl_pending < 0 && compl_shown_match->cp_prev != NULL)
-- {
-- compl_shown_match = compl_shown_match->cp_prev;
-- ++compl_pending;
-- }
-- else
-- break;
-- }
-- found_end = FALSE;
-- }
-- if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0
-- && compl_leader != NULL
-- && !ins_compl_equal(compl_shown_match,
-- compl_leader, (int)STRLEN(compl_leader)))
-- ++todo;
-- else
-- /* Remember a matching item. */
-- found_compl = compl_shown_match;
--
-- /* Stop at the end of the list when we found a usable match. */
-- if (found_end)
-- {
-- if (found_compl != NULL)
-- {
-- compl_shown_match = found_compl;
-- break;
-- }
-- todo = 1; /* use first usable match after wrapping around */
-- }
-- }
--
-- /* Insert the text of the new completion, or the compl_leader. */
-- if (compl_no_insert && !started)
-- {
-- ins_bytes(compl_orig_text + ins_compl_len());
-- compl_used_match = FALSE;
-- }
-- else if (insert_match)
-- {
-- if (!compl_get_longest || compl_used_match)
-- ins_compl_insert(in_compl_func);
-- else
-- ins_bytes(compl_leader + ins_compl_len());
-- }
-- else
-- compl_used_match = FALSE;
--
-- if (!allow_get_expansion)
-- {
-- /* may undisplay the popup menu first */
-- ins_compl_upd_pum();
--
-- if (pum_enough_matches())
-- // Will display the popup menu, don't redraw yet to avoid flicker.
-- pum_call_update_screen();
-- else
-- // Not showing the popup menu yet, redraw to show the user what was
-- // inserted.
-- update_screen(0);
--
-- /* display the updated popup menu */
-- ins_compl_show_pum();
-- #ifdef FEAT_GUI
-- if (gui.in_use)
-- {
-- /* Show the cursor after the match, not after the redrawn text. */
-- setcursor();
-- out_flush_cursor(FALSE, FALSE);
-- }
-- #endif
--
-- /* Delete old text to be replaced, since we're still searching and
-- * don't want to match ourselves! */
-- ins_compl_delete();
-- }
--
-- /* Enter will select a match when the match wasn't inserted and the popup
-- * menu is visible. */
-- if (compl_no_insert && !started)
-- compl_enter_selects = TRUE;
-- else
-- compl_enter_selects = !insert_match && compl_match_array != NULL;
--
-- /*
-- * Show the file name for the match (if any)
-- * Truncate the file name to avoid a wait for return.
-- */
-- if (compl_shown_match->cp_fname != NULL)
-- {
-- char *lead = _("match in file");
-- int space = sc_col - vim_strsize((char_u *)lead) - 2;
-- char_u *s;
-- char_u *e;
--
-- if (space > 0)
-- {
-- /* We need the tail that fits. With double-byte encoding going
-- * back from the end is very slow, thus go from the start and keep
-- * the text that fits in "space" between "s" and "e". */
-- for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e))
-- {
-- space -= ptr2cells(e);
-- while (space < 0)
-- {
-- space += ptr2cells(s);
-- MB_PTR_ADV(s);
-- }
-- }
-- vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
-- s > compl_shown_match->cp_fname ? "<" : "", s);
-- msg((char *)IObuff);
-- redraw_cmdline = FALSE; /* don't overwrite! */
-- }
-- }
--
-- return num_matches;
-- }
--
-- /*
-- * Call this while finding completions, to check whether the user has hit a key
-- * that should change the currently displayed completion, or exit completion
-- * mode. Also, when compl_pending is not zero, show a completion as soon as
-- * possible. -- webb
-- * "frequency" specifies out of how many calls we actually check.
-- * "in_compl_func" is TRUE when called from complete_check(), don't set
-- * compl_curr_match.
-- */
-- void
-- ins_compl_check_keys(int frequency, int in_compl_func)
-- {
-- static int count = 0;
-- int c;
--
-- /* Don't check when reading keys from a script, :normal or feedkeys().
-- * That would break the test scripts. But do check for keys when called
-- * from complete_check(). */
-- if (!in_compl_func && (using_script() || ex_normal_busy))
-- return;
--
-- /* Only do this at regular intervals */
-- if (++count < frequency)
-- return;
-- count = 0;
--
-- /* Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key()
-- * can't do its work correctly. */
-- c = vpeekc_any();
-- if (c != NUL)
-- {
-- if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
-- {
-- c = safe_vgetc(); /* Eat the character */
-- compl_shows_dir = ins_compl_key2dir(c);
-- (void)ins_compl_next(FALSE, ins_compl_key2count(c),
-- c != K_UP && c != K_DOWN, in_compl_func);
-- }
-- else
-- {
-- /* Need to get the character to have KeyTyped set. We'll put it
-- * back with vungetc() below. But skip K_IGNORE. */
-- c = safe_vgetc();
-- if (c != K_IGNORE)
-- {
-- /* Don't interrupt completion when the character wasn't typed,
-- * e.g., when doing @q to replay keys. */
-- if (c != Ctrl_R && KeyTyped)
-- compl_interrupted = TRUE;
--
-- vungetc(c);
-- }
-- }
-- }
-- if (compl_pending != 0 && !got_int && !compl_no_insert)
-- {
-- int todo = compl_pending > 0 ? compl_pending : -compl_pending;
--
-- compl_pending = 0;
-- (void)ins_compl_next(FALSE, todo, TRUE, in_compl_func);
-- }
-- }
--
-- /*
-- * Decide the direction of Insert mode complete from the key typed.
-- * Returns BACKWARD or FORWARD.
-- */
-- static int
-- ins_compl_key2dir(int c)
-- {
-- if (c == Ctrl_P || c == Ctrl_L
-- || c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP || c == K_UP)
-- return BACKWARD;
-- return FORWARD;
-- }
--
-- /*
-- * Return TRUE for keys that are used for completion only when the popup menu
-- * is visible.
-- */
-- static int
-- ins_compl_pum_key(int c)
-- {
-- return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
-- || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN
-- || c == K_UP || c == K_DOWN);
-- }
--
-- /*
-- * Decide the number of completions to move forward.
-- * Returns 1 for most keys, height of the popup menu for page-up/down keys.
-- */
-- static int
-- ins_compl_key2count(int c)
-- {
-- int h;
--
-- if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN)
-- {
-- h = pum_get_height();
-- if (h > 3)
-- h -= 2; /* keep some context */
-- return h;
-- }
-- return 1;
-- }
--
-- /*
-- * Return TRUE if completion with "c" should insert the match, FALSE if only
-- * to change the currently selected completion.
-- */
-- static int
-- ins_compl_use_match(int c)
-- {
-- switch (c)
-- {
-- case K_UP:
-- case K_DOWN:
-- case K_PAGEDOWN:
-- case K_KPAGEDOWN:
-- case K_S_DOWN:
-- case K_PAGEUP:
-- case K_KPAGEUP:
-- case K_S_UP:
-- return FALSE;
-- }
-- return TRUE;
-- }
--
-- /*
-- * Do Insert mode completion.
-- * Called when character "c" was typed, which has a meaning for completion.
-- * Returns OK if completion was done, FAIL if something failed (out of mem).
-- */
-- static int
-- ins_complete(int c, int enable_pum)
-- {
-- char_u *line;
-- int startcol = 0; /* column where searched text starts */
-- colnr_T curs_col; /* cursor column */
-- int n;
-- int save_w_wrow;
-- int save_w_leftcol;
-- int insert_match;
-- int save_did_ai = did_ai;
--
-- compl_direction = ins_compl_key2dir(c);
-- insert_match = ins_compl_use_match(c);
--
-- if (!compl_started)
-- {
-- /* First time we hit ^N or ^P (in a row, I mean) */
--
-- did_ai = FALSE;
-- #ifdef FEAT_SMARTINDENT
-- did_si = FALSE;
-- can_si = FALSE;
-- can_si_back = FALSE;
-- #endif
-- if (stop_arrow() == FAIL)
-- return FAIL;
--
-- line = ml_get(curwin->w_cursor.lnum);
-- curs_col = curwin->w_cursor.col;
-- compl_pending = 0;
--
-- /* If this same ctrl_x_mode has been interrupted use the text from
-- * "compl_startpos" to the cursor as a pattern to add a new word
-- * instead of expand the one before the cursor, in word-wise if
-- * "compl_startpos" is not in the same line as the cursor then fix it
-- * (the line has been split because it was longer than 'tw'). if SOL
-- * is set then skip the previous pattern, a word at the beginning of
-- * the line has been inserted, we'll look for that -- Acevedo. */
-- if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
-- && compl_cont_mode == ctrl_x_mode)
-- {
-- /*
-- * it is a continued search
-- */
-- compl_cont_status &= ~CONT_INTRPT; /* remove INTRPT */
-- if (ctrl_x_mode == CTRL_X_NORMAL
-- || ctrl_x_mode == CTRL_X_PATH_PATTERNS
-- || ctrl_x_mode == CTRL_X_PATH_DEFINES)
-- {
-- if (compl_startpos.lnum != curwin->w_cursor.lnum)
-- {
-- /* line (probably) wrapped, set compl_startpos to the
-- * first non_blank in the line, if it is not a wordchar
-- * include it to get a better pattern, but then we don't
-- * want the "\\<" prefix, check it bellow */
-- compl_col = (colnr_T)getwhitecols(line);
-- compl_startpos.col = compl_col;
-- compl_startpos.lnum = curwin->w_cursor.lnum;
-- compl_cont_status &= ~CONT_SOL; /* clear SOL if present */
-- }
-- else
-- {
-- /* S_IPOS was set when we inserted a word that was at the
-- * beginning of the line, which means that we'll go to SOL
-- * mode but first we need to redefine compl_startpos */
-- if (compl_cont_status & CONT_S_IPOS)
-- {
-- compl_cont_status |= CONT_SOL;
-- compl_startpos.col = (colnr_T)(skipwhite(
-- line + compl_length
-- + compl_startpos.col) - line);
-- }
-- compl_col = compl_startpos.col;
-- }
-- compl_length = curwin->w_cursor.col - (int)compl_col;
-- /* IObuff is used to add a "word from the next line" would we
-- * have enough space? just being paranoid */
-- #define MIN_SPACE 75
-- if (compl_length > (IOSIZE - MIN_SPACE))
-- {
-- compl_cont_status &= ~CONT_SOL;
-- compl_length = (IOSIZE - MIN_SPACE);
-- compl_col = curwin->w_cursor.col - compl_length;
-- }
-- compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
-- if (compl_length < 1)
-- compl_cont_status &= CONT_LOCAL;
-- }
-- else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- compl_cont_status = CONT_ADDING | CONT_N_ADDS;
-- else
-- compl_cont_status = 0;
-- }
-- else
-- compl_cont_status &= CONT_LOCAL;
--
-- if (!(compl_cont_status & CONT_ADDING)) /* normal expansion */
-- {
-- compl_cont_mode = ctrl_x_mode;
-- if (ctrl_x_mode != CTRL_X_NORMAL)
-- /* Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL */
-- compl_cont_status = 0;
-- compl_cont_status |= CONT_N_ADDS;
-- compl_startpos = curwin->w_cursor;
-- startcol = (int)curs_col;
-- compl_col = 0;
-- }
--
-- /* Work out completion pattern and original text -- webb */
-- if (ctrl_x_mode == CTRL_X_NORMAL || (ctrl_x_mode & CTRL_X_WANT_IDENT))
-- {
-- if ((compl_cont_status & CONT_SOL)
-- || ctrl_x_mode == CTRL_X_PATH_DEFINES)
-- {
-- if (!(compl_cont_status & CONT_ADDING))
-- {
-- while (--startcol >= 0 && vim_isIDc(line[startcol]))
-- ;
-- compl_col += ++startcol;
-- compl_length = curs_col - startcol;
-- }
-- if (p_ic)
-- compl_pattern = str_foldcase(line + compl_col,
-- compl_length, NULL, 0);
-- else
-- compl_pattern = vim_strnsave(line + compl_col,
-- compl_length);
-- if (compl_pattern == NULL)
-- return FAIL;
-- }
-- else if (compl_cont_status & CONT_ADDING)
-- {
-- char_u *prefix = (char_u *)"\\<";
--
-- /* we need up to 2 extra chars for the prefix */
-- compl_pattern = alloc(quote_meta(NULL, line + compl_col,
-- compl_length) + 2);
-- if (compl_pattern == NULL)
-- return FAIL;
-- if (!vim_iswordp(line + compl_col)
-- || (compl_col > 0
-- && (vim_iswordp(mb_prevptr(line, line + compl_col)))))
-- prefix = (char_u *)"";
-- STRCPY((char *)compl_pattern, prefix);
-- (void)quote_meta(compl_pattern + STRLEN(prefix),
-- line + compl_col, compl_length);
-- }
-- else if (--startcol < 0
-- || !vim_iswordp(mb_prevptr(line, line + startcol + 1)))
-- {
-- /* Match any word of at least two chars */
-- compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
-- if (compl_pattern == NULL)
-- return FAIL;
-- compl_col += curs_col;
-- compl_length = 0;
-- }
-- else
-- {
-- /* Search the point of change class of multibyte character
-- * or not a word single byte character backward. */
-- if (has_mbyte)
-- {
-- int base_class;
-- int head_off;
--
-- startcol -= (*mb_head_off)(line, line + startcol);
-- base_class = mb_get_class(line + startcol);
-- while (--startcol >= 0)
-- {
-- head_off = (*mb_head_off)(line, line + startcol);
-- if (base_class != mb_get_class(line + startcol
-- - head_off))
-- break;
-- startcol -= head_off;
-- }
-- }
-- else
-- while (--startcol >= 0 && vim_iswordc(line[startcol]))
-- ;
-- compl_col += ++startcol;
-- compl_length = (int)curs_col - startcol;
-- if (compl_length == 1)
-- {
-- /* Only match word with at least two chars -- webb
-- * there's no need to call quote_meta,
-- * alloc(7) is enough -- Acevedo
-- */
-- compl_pattern = alloc(7);
-- if (compl_pattern == NULL)
-- return FAIL;
-- STRCPY((char *)compl_pattern, "\\<");
-- (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
-- STRCAT((char *)compl_pattern, "\\k");
-- }
-- else
-- {
-- compl_pattern = alloc(quote_meta(NULL, line + compl_col,
-- compl_length) + 2);
-- if (compl_pattern == NULL)
-- return FAIL;
-- STRCPY((char *)compl_pattern, "\\<");
-- (void)quote_meta(compl_pattern + 2, line + compl_col,
-- compl_length);
-- }
-- }
-- }
-- else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- {
-- compl_col = (colnr_T)getwhitecols(line);
-- compl_length = (int)curs_col - (int)compl_col;
-- if (compl_length < 0) /* cursor in indent: empty pattern */
-- compl_length = 0;
-- if (p_ic)
-- compl_pattern = str_foldcase(line + compl_col, compl_length,
-- NULL, 0);
-- else
-- compl_pattern = vim_strnsave(line + compl_col, compl_length);
-- if (compl_pattern == NULL)
-- return FAIL;
-- }
-- else if (ctrl_x_mode == CTRL_X_FILES)
-- {
-- /* Go back to just before the first filename character. */
-- if (startcol > 0)
-- {
-- char_u *p = line + startcol;
--
-- MB_PTR_BACK(line, p);
-- while (p > line && vim_isfilec(PTR2CHAR(p)))
-- MB_PTR_BACK(line, p);
-- if (p == line && vim_isfilec(PTR2CHAR(p)))
-- startcol = 0;
-- else
-- startcol = (int)(p - line) + 1;
-- }
--
-- compl_col += startcol;
-- compl_length = (int)curs_col - startcol;
-- compl_pattern = addstar(line + compl_col, compl_length,
-- EXPAND_FILES);
-- if (compl_pattern == NULL)
-- return FAIL;
-- }
-- else if (ctrl_x_mode == CTRL_X_CMDLINE)
-- {
-- compl_pattern = vim_strnsave(line, curs_col);
-- if (compl_pattern == NULL)
-- return FAIL;
-- set_cmd_context(&compl_xp, compl_pattern,
-- (int)STRLEN(compl_pattern), curs_col, FALSE);
-- if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
-- || compl_xp.xp_context == EXPAND_NOTHING)
-- /* No completion possible, use an empty pattern to get a
-- * "pattern not found" message. */
-- compl_col = curs_col;
-- else
-- compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
-- compl_length = curs_col - compl_col;
-- }
-- else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
-- {
-- #ifdef FEAT_COMPL_FUNC
-- /*
-- * Call user defined function 'completefunc' with "a:findstart"
-- * set to 1 to obtain the length of text to use for completion.
-- */
-- typval_T args[3];
-- int col;
-- char_u *funcname;
-- pos_T pos;
-- win_T *curwin_save;
-- buf_T *curbuf_save;
-- int save_State = State;
--
-- /* Call 'completefunc' or 'omnifunc' and get pattern length as a
-- * string */
-- funcname = ctrl_x_mode == CTRL_X_FUNCTION
-- ? curbuf->b_p_cfu : curbuf->b_p_ofu;
-- if (*funcname == NUL)
-- {
-- semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION
-- ? "completefunc" : "omnifunc");
-- /* restore did_ai, so that adding comment leader works */
-- did_ai = save_did_ai;
-- return FAIL;
-- }
--
-- args[0].v_type = VAR_NUMBER;
-- args[0].vval.v_number = 1;
-- args[1].v_type = VAR_STRING;
-- args[1].vval.v_string = (char_u *)"";
-- args[2].v_type = VAR_UNKNOWN;
-- pos = curwin->w_cursor;
-- curwin_save = curwin;
-- curbuf_save = curbuf;
-- col = call_func_retnr(funcname, 2, args);
--
-- State = save_State;
-- if (curwin_save != curwin || curbuf_save != curbuf)
-- {
-- emsg(_(e_complwin));
-- return FAIL;
-- }
-- curwin->w_cursor = pos; /* restore the cursor position */
-- validate_cursor();
-- if (!EQUAL_POS(curwin->w_cursor, pos))
-- {
-- emsg(_(e_compldel));
-- return FAIL;
-- }
--
-- /* Return value -2 means the user complete function wants to
-- * cancel the complete without an error.
-- * Return value -3 does the same as -2 and leaves CTRL-X mode.*/
-- if (col == -2)
-- return FAIL;
-- if (col == -3)
-- {
-- ctrl_x_mode = CTRL_X_NORMAL;
-- edit_submode = NULL;
-- if (!shortmess(SHM_COMPLETIONMENU))
-- msg_clr_cmdline();
-- return FAIL;
-- }
--
-- /*
-- * Reset extended parameters of completion, when start new
-- * completion.
-- */
-- compl_opt_refresh_always = FALSE;
-- compl_opt_suppress_empty = FALSE;
--
-- if (col < 0)
-- col = curs_col;
-- compl_col = col;
-- if (compl_col > curs_col)
-- compl_col = curs_col;
--
-- /* Setup variables for completion. Need to obtain "line" again,
-- * it may have become invalid. */
-- line = ml_get(curwin->w_cursor.lnum);
-- compl_length = curs_col - compl_col;
-- compl_pattern = vim_strnsave(line + compl_col, compl_length);
-- if (compl_pattern == NULL)
-- #endif
-- return FAIL;
-- }
-- else if (ctrl_x_mode == CTRL_X_SPELL)
-- {
-- #ifdef FEAT_SPELL
-- if (spell_bad_len > 0)
-- compl_col = curs_col - spell_bad_len;
-- else
-- compl_col = spell_word_start(startcol);
-- if (compl_col >= (colnr_T)startcol)
-- {
-- compl_length = 0;
-- compl_col = curs_col;
-- }
-- else
-- {
-- spell_expand_check_cap(compl_col);
-- compl_length = (int)curs_col - compl_col;
-- }
-- /* Need to obtain "line" again, it may have become invalid. */
-- line = ml_get(curwin->w_cursor.lnum);
-- compl_pattern = vim_strnsave(line + compl_col, compl_length);
-- if (compl_pattern == NULL)
-- #endif
-- return FAIL;
-- }
-- else
-- {
-- internal_error("ins_complete()");
-- return FAIL;
-- }
--
-- if (compl_cont_status & CONT_ADDING)
-- {
-- edit_submode_pre = (char_u *)_(" Adding");
-- if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
-- {
-- /* Insert a new line, keep indentation but ignore 'comments' */
-- #ifdef FEAT_COMMENTS
-- char_u *old = curbuf->b_p_com;
--
-- curbuf->b_p_com = (char_u *)"";
-- #endif
-- compl_startpos.lnum = curwin->w_cursor.lnum;
-- compl_startpos.col = compl_col;
-- ins_eol('\r');
-- #ifdef FEAT_COMMENTS
-- curbuf->b_p_com = old;
-- #endif
-- compl_length = 0;
-- compl_col = curwin->w_cursor.col;
-- }
-- }
-- else
-- {
-- edit_submode_pre = NULL;
-- compl_startpos.col = compl_col;
-- }
--
-- if (compl_cont_status & CONT_LOCAL)
-- edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
-- else
-- edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
--
-- /* If any of the original typed text has been changed we need to fix
-- * the redo buffer. */
-- ins_compl_fixRedoBufForLeader(NULL);
--
-- /* Always add completion for the original text. */
-- vim_free(compl_orig_text);
-- compl_orig_text = vim_strnsave(line + compl_col, compl_length);
-- if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
-- -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
-- {
-- VIM_CLEAR(compl_pattern);
-- VIM_CLEAR(compl_orig_text);
-- return FAIL;
-- }
--
-- /* showmode might reset the internal line pointers, so it must
-- * be called before line = ml_get(), or when this address is no
-- * longer needed. -- Acevedo.
-- */
-- edit_submode_extra = (char_u *)_("-- Searching...");
-- edit_submode_highl = HLF_COUNT;
-- showmode();
-- edit_submode_extra = NULL;
-- out_flush();
-- }
-- else if (insert_match && stop_arrow() == FAIL)
-- return FAIL;
--
-- compl_shown_match = compl_curr_match;
-- compl_shows_dir = compl_direction;
--
-- /*
-- * Find next match (and following matches).
-- */
-- save_w_wrow = curwin->w_wrow;
-- save_w_leftcol = curwin->w_leftcol;
-- n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
--
-- /* may undisplay the popup menu */
-- ins_compl_upd_pum();
--
-- if (n > 1) /* all matches have been found */
-- compl_matches = n;
-- compl_curr_match = compl_shown_match;
-- compl_direction = compl_shows_dir;
--
-- /* Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
-- * mode. */
-- if (got_int && !global_busy)
-- {
-- (void)vgetc();
-- got_int = FALSE;
-- }
--
-- /* we found no match if the list has only the "compl_orig_text"-entry */
-- if (compl_first_match == compl_first_match->cp_next)
-- {
-- edit_submode_extra = (compl_cont_status & CONT_ADDING)
-- && compl_length > 1
-- ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
-- edit_submode_highl = HLF_E;
-- /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
-- * because we couldn't expand anything at first place, but if we used
-- * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
-- * (such as M in M'exico) if not tried already. -- Acevedo */
-- if ( compl_length > 1
-- || (compl_cont_status & CONT_ADDING)
-- || (ctrl_x_mode != CTRL_X_NORMAL
-- && ctrl_x_mode != CTRL_X_PATH_PATTERNS
-- && ctrl_x_mode != CTRL_X_PATH_DEFINES))
-- compl_cont_status &= ~CONT_N_ADDS;
-- }
--
-- if (compl_curr_match->cp_flags & CONT_S_IPOS)
-- compl_cont_status |= CONT_S_IPOS;
-- else
-- compl_cont_status &= ~CONT_S_IPOS;
--
-- if (edit_submode_extra == NULL)
-- {
-- if (compl_curr_match->cp_flags & ORIGINAL_TEXT)
-- {
-- edit_submode_extra = (char_u *)_("Back at original");
-- edit_submode_highl = HLF_W;
-- }
-- else if (compl_cont_status & CONT_S_IPOS)
-- {
-- edit_submode_extra = (char_u *)_("Word from other line");
-- edit_submode_highl = HLF_COUNT;
-- }
-- else if (compl_curr_match->cp_next == compl_curr_match->cp_prev)
-- {
-- edit_submode_extra = (char_u *)_("The only match");
-- edit_submode_highl = HLF_COUNT;
-- }
-- else
-- {
-- /* Update completion sequence number when needed. */
-- if (compl_curr_match->cp_number == -1)
-- {
-- int number = 0;
-- compl_T *match;
--
-- if (compl_direction == FORWARD)
-- {
-- /* search backwards for the first valid (!= -1) number.
-- * This should normally succeed already at the first loop
-- * cycle, so it's fast! */
-- for (match = compl_curr_match->cp_prev; match != NULL
-- && match != compl_first_match;
-- match = match->cp_prev)
-- if (match->cp_number != -1)
-- {
-- number = match->cp_number;
-- break;
-- }
-- if (match != NULL)
-- /* go up and assign all numbers which are not assigned
-- * yet */
-- for (match = match->cp_next;
-- match != NULL && match->cp_number == -1;
-- match = match->cp_next)
-- match->cp_number = ++number;
-- }
-- else /* BACKWARD */
-- {
-- /* search forwards (upwards) for the first valid (!= -1)
-- * number. This should normally succeed already at the
-- * first loop cycle, so it's fast! */
-- for (match = compl_curr_match->cp_next; match != NULL
-- && match != compl_first_match;
-- match = match->cp_next)
-- if (match->cp_number != -1)
-- {
-- number = match->cp_number;
-- break;
-- }
-- if (match != NULL)
-- /* go down and assign all numbers which are not
-- * assigned yet */
-- for (match = match->cp_prev; match
-- && match->cp_number == -1;
-- match = match->cp_prev)
-- match->cp_number = ++number;
-- }
-- }
--
-- /* The match should always have a sequence number now, this is
-- * just a safety check. */
-- if (compl_curr_match->cp_number != -1)
-- {
-- /* Space for 10 text chars. + 2x10-digit no.s = 31.
-- * Translations may need more than twice that. */
-- static char_u match_ref[81];
--
-- if (compl_matches > 0)
-- vim_snprintf((char *)match_ref, sizeof(match_ref),
-- _("match %d of %d"),
-- compl_curr_match->cp_number, compl_matches);
-- else
-- vim_snprintf((char *)match_ref, sizeof(match_ref),
-- _("match %d"),
-- compl_curr_match->cp_number);
-- edit_submode_extra = match_ref;
-- edit_submode_highl = HLF_R;
-- if (dollar_vcol >= 0)
-- curs_columns(FALSE);
-- }
-- }
-- }
--
-- // Show a message about what (completion) mode we're in.
-- if (!compl_opt_suppress_empty)
-- {
-- showmode();
-- if (!shortmess(SHM_COMPLETIONMENU))
-- {
-- if (edit_submode_extra != NULL)
-- {
-- if (!p_smd)
-- msg_attr((char *)edit_submode_extra,
-- edit_submode_highl < HLF_COUNT
-- ? HL_ATTR(edit_submode_highl) : 0);
-- }
-- else
-- msg_clr_cmdline(); // necessary for "noshowmode"
-- }
-- }
--
-- /* Show the popup menu, unless we got interrupted. */
-- if (enable_pum && !compl_interrupted)
-- show_pum(save_w_wrow, save_w_leftcol);
--
-- compl_was_interrupted = compl_interrupted;
-- compl_interrupted = FALSE;
--
-- return OK;
-- }
--
-- static void
-- show_pum(int prev_w_wrow, int prev_w_leftcol)
-- {
-- /* RedrawingDisabled may be set when invoked through complete(). */
-- int n = RedrawingDisabled;
--
-- RedrawingDisabled = 0;
--
-- /* If the cursor moved or the display scrolled we need to remove the pum
-- * first. */
-- setcursor();
-- if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol)
-- ins_compl_del_pum();
--
-- ins_compl_show_pum();
-- setcursor();
-- RedrawingDisabled = n;
-- }
--
-- /*
-- * Looks in the first "len" chars. of "src" for search-metachars.
-- * If dest is not NULL the chars. are copied there quoting (with
-- * a backslash) the metachars, and dest would be NUL terminated.
-- * Returns the length (needed) of dest
-- */
-- static unsigned
-- quote_meta(char_u *dest, char_u *src, int len)
-- {
-- unsigned m = (unsigned)len + 1; /* one extra for the NUL */
--
-- for ( ; --len >= 0; src++)
-- {
-- switch (*src)
-- {
-- case '.':
-- case '*':
-- case '[':
-- if (ctrl_x_mode == CTRL_X_DICTIONARY
-- || ctrl_x_mode == CTRL_X_THESAURUS)
-- break;
-- /* FALLTHROUGH */
-- case '~':
-- if (!p_magic) /* quote these only if magic is set */
-- break;
-- /* FALLTHROUGH */
-- case '\\':
-- if (ctrl_x_mode == CTRL_X_DICTIONARY
-- || ctrl_x_mode == CTRL_X_THESAURUS)
-- break;
-- /* FALLTHROUGH */
-- case '^': /* currently it's not needed. */
-- case '$':
-- m++;
-- if (dest != NULL)
-- *dest++ = '\\';
-- break;
-- }
-- if (dest != NULL)
-- *dest++ = *src;
-- /* Copy remaining bytes of a multibyte character. */
-- if (has_mbyte)
-- {
-- int i, mb_len;
--
-- mb_len = (*mb_ptr2len)(src) - 1;
-- if (mb_len > 0 && len >= mb_len)
-- for (i = 0; i < mb_len; ++i)
-- {
-- --len;
-- ++src;
-- if (dest != NULL)
-- *dest++ = *src;
-- }
-- }
-- }
-- if (dest != NULL)
-- *dest = NUL;
--
-- return m;
-- }
-- #endif /* FEAT_INS_EXPAND */
--
- /*
- * Next character is interpreted literally.
- * A one, two or three digit decimal number is interpreted as its byte value.
---- 2120,2125 ----
-***************
-*** 7054,7060 ****
- * start_arrow() is called when an arrow key is used in insert mode.
- * For undo/redo it resembles hitting the <ESC> key.
- */
-! static void
- start_arrow(
- pos_T *end_insert_pos) /* can be NULL */
- {
---- 3148,3154 ----
- * start_arrow() is called when an arrow key is used in insert mode.
- * For undo/redo it resembles hitting the <ESC> key.
- */
-! void
- start_arrow(
- pos_T *end_insert_pos) /* can be NULL */
- {
-***************
-*** 7111,7129 ****
- }
- }
-
-- /*
-- * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
-- * spelled word, if there is one.
-- */
-- static void
-- spell_back_to_badword(void)
-- {
-- pos_T tpos = curwin->w_cursor;
--
-- spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
-- if (curwin->w_cursor.col != tpos.col)
-- start_arrow(&tpos);
-- }
- #endif
-
- /*
---- 3205,3210 ----
-***************
-*** 7340,7348 ****
- free_last_insert(void)
- {
- VIM_CLEAR(last_insert);
-- # ifdef FEAT_INS_EXPAND
-- VIM_CLEAR(compl_orig_text);
-- # endif
- }
- #endif
-
---- 3421,3426 ----
-***************
-*** 9978,9984 ****
- * Handle CR or NL in insert mode.
- * Return FAIL when out of memory or can't undo.
- */
-! static int
- ins_eol(int c)
- {
- int i;
---- 6056,6062 ----
- * Handle CR or NL in insert mode.
- * Return FAIL when out of memory or can't undo.
- */
-! int
- ins_eol(int c)
- {
- int i;
-***************
-*** 10174,10180 ****
- int c = tc;
-
- #ifdef FEAT_INS_EXPAND
-! if (ctrl_x_mode == CTRL_X_SCROLL)
- {
- if (c == Ctrl_Y)
- scrolldown_clamp();
---- 6252,6258 ----
- int c = tc;
-
- #ifdef FEAT_INS_EXPAND
-! if (ctrl_x_mode_scroll())
- {
- if (c == Ctrl_Y)
- scrolldown_clamp();
-***************
-*** 10370,10379 ****
- }
- #endif
-
- /*
- * Trigger "event" and take care of fixing undo.
- */
-! static int
- ins_apply_autocmds(event_T event)
- {
- varnumber_T tick = CHANGEDTICK(curbuf);
---- 6448,6465 ----
- }
- #endif
-
-+ #if defined(FEAT_CINDENT) || defined(PROTO)
-+ int
-+ can_cindent_get(void)
-+ {
-+ return can_cindent;
-+ }
-+ #endif
-+
- /*
- * Trigger "event" and take care of fixing undo.
- */
-! int
- ins_apply_autocmds(event_T event)
- {
- varnumber_T tick = CHANGEDTICK(curbuf);
-*** ../vim-8.1.1075/src/evalfunc.c 2019-03-29 14:16:34.142861770 +0100
---- src/evalfunc.c 2019-03-30 12:54:54.305407871 +0100
-***************
-*** 2603,2609 ****
-
- RedrawingDisabled = 0;
- ins_compl_check_keys(0, TRUE);
-! rettv->vval.v_number = compl_interrupted;
- RedrawingDisabled = saved;
- }
-
---- 2603,2609 ----
-
- RedrawingDisabled = 0;
- ins_compl_check_keys(0, TRUE);
-! rettv->vval.v_number = ins_compl_interrupted();
- RedrawingDisabled = saved;
- }
-
-*** ../vim-8.1.1075/src/globals.h 2019-03-22 16:33:03.483016118 +0100
---- src/globals.h 2019-03-30 12:54:54.305407871 +0100
-***************
-*** 119,128 ****
- * by the match.) */
- EXTERN int compl_length INIT(= 0);
-
-- /* Set when character typed while looking for matches and it means we should
-- * stop looking for matches. */
-- EXTERN int compl_interrupted INIT(= FALSE);
--
- /* List of flags for method of completion. */
- EXTERN int compl_cont_status INIT(= 0);
- # define CONT_ADDING 1 /* "normal" or "adding" expansion */
---- 119,124 ----
-*** ../vim-8.1.1075/src/insexpand.c 2019-03-30 13:32:12.890308674 +0100
---- src/insexpand.c 2019-03-30 13:48:00.960469588 +0100
-***************
-*** 0 ****
---- 1,3992 ----
-+ /* vi:set ts=8 sts=4 sw=4 noet:
-+ *
-+ * VIM - Vi IMproved by Bram Moolenaar
-+ *
-+ * Do ":help uganda" in Vim to read copying and usage conditions.
-+ * Do ":help credits" in Vim to see a list of people who contributed.
-+ * See README.txt for an overview of the Vim source code.
-+ */
-+
-+ /*
-+ * insexpand.c: functions for Insert mode completion
-+ */
-+
-+ #include "vim.h"
-+
-+ #ifdef FEAT_INS_EXPAND
-+ /*
-+ * Definitions used for CTRL-X submode.
-+ * Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[] and
-+ * ctrl_x_mode_names[] below.
-+ */
-+ # define CTRL_X_WANT_IDENT 0x100
-+
-+ # define CTRL_X_NORMAL 0 /* CTRL-N CTRL-P completion, default */
-+ # define CTRL_X_NOT_DEFINED_YET 1
-+ # define CTRL_X_SCROLL 2
-+ # define CTRL_X_WHOLE_LINE 3
-+ # define CTRL_X_FILES 4
-+ # define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
-+ # define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
-+ # define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
-+ # define CTRL_X_FINISHED 8
-+ # define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
-+ # define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT)
-+ # define CTRL_X_CMDLINE 11
-+ # define CTRL_X_FUNCTION 12
-+ # define CTRL_X_OMNI 13
-+ # define CTRL_X_SPELL 14
-+ # define CTRL_X_LOCAL_MSG 15 /* only used in "ctrl_x_msgs" */
-+ # define CTRL_X_EVAL 16 /* for builtin function complete() */
-+
-+ # define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
-+
-+ // Message for CTRL-X mode, index is ctrl_x_mode.
-+ static char *ctrl_x_msgs[] =
-+ {
-+ N_(" Keyword completion (^N^P)"), // CTRL_X_NORMAL, ^P/^N compl.
-+ N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
-+ NULL, // CTRL_X_SCROLL: depends on state
-+ N_(" Whole line completion (^L^N^P)"),
-+ N_(" File name completion (^F^N^P)"),
-+ N_(" Tag completion (^]^N^P)"),
-+ N_(" Path pattern completion (^N^P)"),
-+ N_(" Definition completion (^D^N^P)"),
-+ NULL, // CTRL_X_FINISHED
-+ N_(" Dictionary completion (^K^N^P)"),
-+ N_(" Thesaurus completion (^T^N^P)"),
-+ N_(" Command-line completion (^V^N^P)"),
-+ N_(" User defined completion (^U^N^P)"),
-+ N_(" Omni completion (^O^N^P)"),
-+ N_(" Spelling suggestion (s^N^P)"),
-+ N_(" Keyword Local completion (^N^P)"),
-+ NULL, // CTRL_X_EVAL doesn't use msg.
-+ };
-+
-+ static char *ctrl_x_mode_names[] = {
-+ "keyword",
-+ "ctrl_x",
-+ "unknown", // CTRL_X_SCROLL
-+ "whole_line",
-+ "files",
-+ "tags",
-+ "path_patterns",
-+ "path_defines",
-+ "unknown", // CTRL_X_FINISHED
-+ "dictionary",
-+ "thesaurus",
-+ "cmdline",
-+ "function",
-+ "omni",
-+ "spell",
-+ NULL, // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
-+ "eval"
-+ };
-+
-+ /*
-+ * Array indexes used for cp_text[].
-+ */
-+ #define CPT_ABBR 0 // "abbr"
-+ #define CPT_MENU 1 // "menu"
-+ #define CPT_KIND 2 // "kind"
-+ #define CPT_INFO 3 // "info"
-+ #define CPT_USER_DATA 4 // "user data"
-+ #define CPT_COUNT 5 // Number of entries
-+
-+ /*
-+ * Structure used to store one match for insert completion.
-+ */
-+ typedef struct compl_S compl_T;
-+ struct compl_S
-+ {
-+ compl_T *cp_next;
-+ compl_T *cp_prev;
-+ char_u *cp_str; /* matched text */
-+ char cp_icase; /* TRUE or FALSE: ignore case */
-+ char_u *(cp_text[CPT_COUNT]); /* text for the menu */
-+ char_u *cp_fname; /* file containing the match, allocated when
-+ * cp_flags has FREE_FNAME */
-+ int cp_flags; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
-+ int cp_number; /* sequence number */
-+ };
-+
-+ # define ORIGINAL_TEXT (1) /* the original text when the expansion begun */
-+ # define FREE_FNAME (2)
-+
-+ static char e_hitend[] = N_("Hit end of paragraph");
-+ # ifdef FEAT_COMPL_FUNC
-+ static char e_complwin[] = N_("E839: Completion function changed window");
-+ static char e_compldel[] = N_("E840: Completion function deleted text");
-+ # endif
-+
-+ /*
-+ * All the current matches are stored in a list.
-+ * "compl_first_match" points to the start of the list.
-+ * "compl_curr_match" points to the currently selected entry.
-+ * "compl_shown_match" is different from compl_curr_match during
-+ * ins_compl_get_exp().
-+ */
-+ static compl_T *compl_first_match = NULL;
-+ static compl_T *compl_curr_match = NULL;
-+ static compl_T *compl_shown_match = NULL;
-+ static compl_T *compl_old_match = NULL;
-+
-+ // After using a cursor key <Enter> selects a match in the popup menu,
-+ // otherwise it inserts a line break.
-+ static int compl_enter_selects = FALSE;
-+
-+ // When "compl_leader" is not NULL only matches that start with this string
-+ // are used.
-+ static char_u *compl_leader = NULL;
-+
-+ static int compl_get_longest = FALSE; // put longest common string
-+ // in compl_leader
-+
-+ static int compl_no_insert = FALSE; // FALSE: select & insert
-+ // TRUE: noinsert
-+ static int compl_no_select = FALSE; // FALSE: select & insert
-+ // TRUE: noselect
-+
-+ // Selected one of the matches. When FALSE the match was edited or using the
-+ // longest common string.
-+ static int compl_used_match;
-+
-+ // didn't finish finding completions.
-+ static int compl_was_interrupted = FALSE;
-+
-+ // Set when character typed while looking for matches and it means we should
-+ // stop looking for matches.
-+ static int compl_interrupted = FALSE;
-+
-+ static int compl_restarting = FALSE; // don't insert match
-+
-+ // When the first completion is done "compl_started" is set. When it's
-+ // FALSE the word to be completed must be located.
-+ static int compl_started = FALSE;
-+
-+ // Which Ctrl-X mode are we in?
-+ static int ctrl_x_mode = CTRL_X_NORMAL;
-+
-+ static int compl_matches = 0;
-+ static char_u *compl_pattern = NULL;
-+ static int compl_direction = FORWARD;
-+ static int compl_shows_dir = FORWARD;
-+ static int compl_pending = 0; // > 1 for postponed CTRL-N
-+ static pos_T compl_startpos;
-+ static colnr_T compl_col = 0; // column where the text starts
-+ // that is being completed
-+ static char_u *compl_orig_text = NULL; // text as it was before
-+ // completion started
-+ static int compl_cont_mode = 0;
-+ static expand_T compl_xp;
-+
-+ static int compl_opt_refresh_always = FALSE;
-+ static int compl_opt_suppress_empty = FALSE;
-+
-+ static int ins_compl_add(char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup);
-+ static void ins_compl_longest_match(compl_T *match);
-+ static void ins_compl_del_pum(void);
-+ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir);
-+ static char_u *find_line_end(char_u *ptr);
-+ static void ins_compl_free(void);
-+ static char_u *ins_compl_mode(void);
-+ static int ins_compl_need_restart(void);
-+ static void ins_compl_new_leader(void);
-+ static int ins_compl_len(void);
-+ static void ins_compl_restart(void);
-+ static void ins_compl_set_original_text(char_u *str);
-+ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
-+ # if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
-+ static void ins_compl_add_list(list_T *list);
-+ static void ins_compl_add_dict(dict_T *dict);
-+ # endif
-+ static int ins_compl_key2dir(int c);
-+ static int ins_compl_pum_key(int c);
-+ static int ins_compl_key2count(int c);
-+ static void show_pum(int prev_w_wrow, int prev_w_leftcol);
-+ static unsigned quote_meta(char_u *dest, char_u *str, int len);
-+ #endif // FEAT_INS_EXPAND
-+
-+ #ifdef FEAT_SPELL
-+ static void spell_back_to_badword(void);
-+ static int spell_bad_len = 0; // length of located bad word
-+ #endif
-+
-+ #if defined(FEAT_INS_EXPAND) || defined(PROTO)
-+ /*
-+ * CTRL-X pressed in Insert mode.
-+ */
-+ void
-+ ins_ctrl_x(void)
-+ {
-+ // CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X
-+ // CTRL-V works like CTRL-N
-+ if (ctrl_x_mode != CTRL_X_CMDLINE)
-+ {
-+ // if the next ^X<> won't ADD nothing, then reset
-+ // compl_cont_status
-+ if (compl_cont_status & CONT_N_ADDS)
-+ compl_cont_status |= CONT_INTRPT;
-+ else
-+ compl_cont_status = 0;
-+ // We're not sure which CTRL-X mode it will be yet
-+ ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
-+ edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
-+ edit_submode_pre = NULL;
-+ showmode();
-+ }
-+ }
-+
-+ /*
-+ * Functions to check the current CTRL-X mode.
-+ */
-+ int ctrl_x_mode_none(void) { return ctrl_x_mode == 0; }
-+ int ctrl_x_mode_normal(void) { return ctrl_x_mode == CTRL_X_NORMAL; }
-+ int ctrl_x_mode_scroll(void) { return ctrl_x_mode == CTRL_X_SCROLL; }
-+ int ctrl_x_mode_whole_line(void) { return ctrl_x_mode == CTRL_X_WHOLE_LINE; }
-+ int ctrl_x_mode_files(void) { return ctrl_x_mode == CTRL_X_FILES; }
-+ int ctrl_x_mode_tags(void) { return ctrl_x_mode == CTRL_X_TAGS; }
-+ int ctrl_x_mode_path_patterns(void) {
-+ return ctrl_x_mode == CTRL_X_PATH_PATTERNS; }
-+ int ctrl_x_mode_path_defines(void) {
-+ return ctrl_x_mode == CTRL_X_PATH_DEFINES; }
-+ int ctrl_x_mode_dictionary(void) { return ctrl_x_mode == CTRL_X_DICTIONARY; }
-+ int ctrl_x_mode_thesaurus(void) { return ctrl_x_mode == CTRL_X_THESAURUS; }
-+ int ctrl_x_mode_cmdline(void) { return ctrl_x_mode == CTRL_X_CMDLINE; }
-+ int ctrl_x_mode_function(void) { return ctrl_x_mode == CTRL_X_FUNCTION; }
-+ int ctrl_x_mode_omni(void) { return ctrl_x_mode == CTRL_X_OMNI; }
-+ int ctrl_x_mode_spell(void) { return ctrl_x_mode == CTRL_X_SPELL; }
-+ int ctrl_x_mode_line_or_eval(void) {
-+ return ctrl_x_mode == CTRL_X_WHOLE_LINE || ctrl_x_mode == CTRL_X_EVAL; }
-+
-+ /*
-+ * Whether other than default completion has been selected.
-+ */
-+ int
-+ ctrl_x_mode_not_default(void)
-+ {
-+ return ctrl_x_mode != CTRL_X_NORMAL;
-+ }
-+
-+ /*
-+ * Whether CTRL-X was typed without a following character.
-+ */
-+ int
-+ ctrl_x_mode_not_defined_yet(void)
-+ {
-+ return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
-+ }
-+
-+ /*
-+ * Return TRUE if the 'dict' or 'tsr' option can be used.
-+ */
-+ int
-+ has_compl_option(int dict_opt)
-+ {
-+ if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
-+ # ifdef FEAT_SPELL
-+ && !curwin->w_p_spell
-+ # endif
-+ )
-+ : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL))
-+ {
-+ ctrl_x_mode = CTRL_X_NORMAL;
-+ edit_submode = NULL;
-+ msg_attr(dict_opt ? _("'dictionary' option is empty")
-+ : _("'thesaurus' option is empty"),
-+ HL_ATTR(HLF_E));
-+ if (emsg_silent == 0)
-+ {
-+ vim_beep(BO_COMPL);
-+ setcursor();
-+ out_flush();
-+ #ifdef FEAT_EVAL
-+ if (!get_vim_var_nr(VV_TESTING))
-+ #endif
-+ ui_delay(2000L, FALSE);
-+ }
-+ return FALSE;
-+ }
-+ return TRUE;
-+ }
-+
-+ /*
-+ * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
-+ * This depends on the current mode.
-+ */
-+ int
-+ vim_is_ctrl_x_key(int c)
-+ {
-+ // Always allow ^R - let its results then be checked
-+ if (c == Ctrl_R)
-+ return TRUE;
-+
-+ // Accept <PageUp> and <PageDown> if the popup menu is visible.
-+ if (ins_compl_pum_key(c))
-+ return TRUE;
-+
-+ switch (ctrl_x_mode)
-+ {
-+ case 0: // Not in any CTRL-X mode
-+ return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
-+ case CTRL_X_NOT_DEFINED_YET:
-+ return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
-+ || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
-+ || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
-+ || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
-+ || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
-+ || c == Ctrl_S || c == Ctrl_K || c == 's');
-+ case CTRL_X_SCROLL:
-+ return (c == Ctrl_Y || c == Ctrl_E);
-+ case CTRL_X_WHOLE_LINE:
-+ return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_FILES:
-+ return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_DICTIONARY:
-+ return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_THESAURUS:
-+ return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_TAGS:
-+ return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
-+ #ifdef FEAT_FIND_ID
-+ case CTRL_X_PATH_PATTERNS:
-+ return (c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_PATH_DEFINES:
-+ return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
-+ #endif
-+ case CTRL_X_CMDLINE:
-+ return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
-+ || c == Ctrl_X);
-+ #ifdef FEAT_COMPL_FUNC
-+ case CTRL_X_FUNCTION:
-+ return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_OMNI:
-+ return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N);
-+ #endif
-+ case CTRL_X_SPELL:
-+ return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N);
-+ case CTRL_X_EVAL:
-+ return (c == Ctrl_P || c == Ctrl_N);
-+ }
-+ internal_error("vim_is_ctrl_x_key()");
-+ return FALSE;
-+ }
-+
-+ /*
-+ * Return TRUE when character "c" is part of the item currently being
-+ * completed. Used to decide whether to abandon complete mode when the menu
-+ * is visible.
-+ */
-+ int
-+ ins_compl_accept_char(int c)
-+ {
-+ if (ctrl_x_mode & CTRL_X_WANT_IDENT)
-+ // When expanding an identifier only accept identifier chars.
-+ return vim_isIDc(c);
-+
-+ switch (ctrl_x_mode)
-+ {
-+ case CTRL_X_FILES:
-+ // When expanding file name only accept file name chars. But not
-+ // path separators, so that "proto/<Tab>" expands files in
-+ // "proto", not "proto/" as a whole
-+ return vim_isfilec(c) && !vim_ispathsep(c);
-+
-+ case CTRL_X_CMDLINE:
-+ case CTRL_X_OMNI:
-+ // Command line and Omni completion can work with just about any
-+ // printable character, but do stop at white space.
-+ return vim_isprintc(c) && !VIM_ISWHITE(c);
-+
-+ case CTRL_X_WHOLE_LINE:
-+ // For while line completion a space can be part of the line.
-+ return vim_isprintc(c);
-+ }
-+ return vim_iswordc(c);
-+ }
-+
-+ /*
-+ * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
-+ * case of the originally typed text is used, and the case of the completed
-+ * text is inferred, ie this tries to work out what case you probably wanted
-+ * the rest of the word to be in -- webb
-+ */
-+ int
-+ ins_compl_add_infercase(
-+ char_u *str,
-+ int len,
-+ int icase,
-+ char_u *fname,
-+ int dir,
-+ int flags)
-+ {
-+ char_u *p;
-+ int i, c;
-+ int actual_len; // Take multi-byte characters
-+ int actual_compl_length; // into account.
-+ int min_len;
-+ int *wca; // Wide character array.
-+ int has_lower = FALSE;
-+ int was_letter = FALSE;
-+
-+ if (p_ic && curbuf->b_p_inf && len > 0)
-+ {
-+ // Infer case of completed part.
-+
-+ // Find actual length of completion.
-+ if (has_mbyte)
-+ {
-+ p = str;
-+ actual_len = 0;
-+ while (*p != NUL)
-+ {
-+ MB_PTR_ADV(p);
-+ ++actual_len;
-+ }
-+ }
-+ else
-+ actual_len = len;
-+
-+ // Find actual length of original text.
-+ if (has_mbyte)
-+ {
-+ p = compl_orig_text;
-+ actual_compl_length = 0;
-+ while (*p != NUL)
-+ {
-+ MB_PTR_ADV(p);
-+ ++actual_compl_length;
-+ }
-+ }
-+ else
-+ actual_compl_length = compl_length;
-+
-+ // "actual_len" may be smaller than "actual_compl_length" when using
-+ // thesaurus, only use the minimum when comparing.
-+ min_len = actual_len < actual_compl_length
-+ ? actual_len : actual_compl_length;
-+
-+ // Allocate wide character array for the completion and fill it.
-+ wca = (int *)alloc((unsigned)(actual_len * sizeof(int)));
-+ if (wca != NULL)
-+ {
-+ p = str;
-+ for (i = 0; i < actual_len; ++i)
-+ if (has_mbyte)
-+ wca[i] = mb_ptr2char_adv(&p);
-+ else
-+ wca[i] = *(p++);
-+
-+ // Rule 1: Were any chars converted to lower?
-+ p = compl_orig_text;
-+ for (i = 0; i < min_len; ++i)
-+ {
-+ if (has_mbyte)
-+ c = mb_ptr2char_adv(&p);
-+ else
-+ c = *(p++);
-+ if (MB_ISLOWER(c))
-+ {
-+ has_lower = TRUE;
-+ if (MB_ISUPPER(wca[i]))
-+ {
-+ // Rule 1 is satisfied.
-+ for (i = actual_compl_length; i < actual_len; ++i)
-+ wca[i] = MB_TOLOWER(wca[i]);
-+ break;
-+ }
-+ }
-+ }
-+
-+ // Rule 2: No lower case, 2nd consecutive letter converted to
-+ // upper case.
-+ if (!has_lower)
-+ {
-+ p = compl_orig_text;
-+ for (i = 0; i < min_len; ++i)
-+ {
-+ if (has_mbyte)
-+ c = mb_ptr2char_adv(&p);
-+ else
-+ c = *(p++);
-+ if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
-+ {
-+ // Rule 2 is satisfied.
-+ for (i = actual_compl_length; i < actual_len; ++i)
-+ wca[i] = MB_TOUPPER(wca[i]);
-+ break;
-+ }
-+ was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
-+ }
-+ }
-+
-+ // Copy the original case of the part we typed.
-+ p = compl_orig_text;
-+ for (i = 0; i < min_len; ++i)
-+ {
-+ if (has_mbyte)
-+ c = mb_ptr2char_adv(&p);
-+ else
-+ c = *(p++);
-+ if (MB_ISLOWER(c))
-+ wca[i] = MB_TOLOWER(wca[i]);
-+ else if (MB_ISUPPER(c))
-+ wca[i] = MB_TOUPPER(wca[i]);
-+ }
-+
-+ // Generate encoding specific output from wide character array.
-+ // Multi-byte characters can occupy up to five bytes more than
-+ // ASCII characters, and we also need one byte for NUL, so stay
-+ // six bytes away from the edge of IObuff.
-+ p = IObuff;
-+ i = 0;
-+ while (i < actual_len && (p - IObuff + 6) < IOSIZE)
-+ if (has_mbyte)
-+ p += (*mb_char2bytes)(wca[i++], p);
-+ else
-+ *(p++) = wca[i++];
-+ *p = NUL;
-+
-+ vim_free(wca);
-+ }
-+
-+ return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
-+ flags, FALSE);
-+ }
-+ return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
-+ }
-+
-+ /*
-+ * Add a match to the list of matches.
-+ * If the given string is already in the list of completions, then return
-+ * NOTDONE, otherwise add it to the list and return OK. If there is an error,
-+ * maybe because alloc() returns NULL, then FAIL is returned.
-+ */
-+ static int
-+ ins_compl_add(
-+ char_u *str,
-+ int len,
-+ int icase,
-+ char_u *fname,
-+ char_u **cptext, // extra text for popup menu or NULL
-+ int cdir,
-+ int flags,
-+ int adup) // accept duplicate match
-+ {
-+ compl_T *match;
-+ int dir = (cdir == 0 ? compl_direction : cdir);
-+
-+ ui_breakcheck();
-+ if (got_int)
-+ return FAIL;
-+ if (len < 0)
-+ len = (int)STRLEN(str);
-+
-+ // If the same match is already present, don't add it.
-+ if (compl_first_match != NULL && !adup)
-+ {
-+ match = compl_first_match;
-+ do
-+ {
-+ if ( !(match->cp_flags & ORIGINAL_TEXT)
-+ && STRNCMP(match->cp_str, str, len) == 0
-+ && match->cp_str[len] == NUL)
-+ return NOTDONE;
-+ match = match->cp_next;
-+ } while (match != NULL && match != compl_first_match);
-+ }
-+
-+ // Remove any popup menu before changing the list of matches.
-+ ins_compl_del_pum();
-+
-+ // Allocate a new match structure.
-+ // Copy the values to the new match structure.
-+ match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T));
-+ if (match == NULL)
-+ return FAIL;
-+ match->cp_number = -1;
-+ if (flags & ORIGINAL_TEXT)
-+ match->cp_number = 0;
-+ if ((match->cp_str = vim_strnsave(str, len)) == NULL)
-+ {
-+ vim_free(match);
-+ return FAIL;
-+ }
-+ match->cp_icase = icase;
-+
-+ // match-fname is:
-+ // - compl_curr_match->cp_fname if it is a string equal to fname.
-+ // - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
-+ // - NULL otherwise. --Acevedo
-+ if (fname != NULL
-+ && compl_curr_match != NULL
-+ && compl_curr_match->cp_fname != NULL
-+ && STRCMP(fname, compl_curr_match->cp_fname) == 0)
-+ match->cp_fname = compl_curr_match->cp_fname;
-+ else if (fname != NULL)
-+ {
-+ match->cp_fname = vim_strsave(fname);
-+ flags |= FREE_FNAME;
-+ }
-+ else
-+ match->cp_fname = NULL;
-+ match->cp_flags = flags;
-+
-+ if (cptext != NULL)
-+ {
-+ int i;
-+
-+ for (i = 0; i < CPT_COUNT; ++i)
-+ if (cptext[i] != NULL && *cptext[i] != NUL)
-+ match->cp_text[i] = vim_strsave(cptext[i]);
-+ }
-+
-+ // Link the new match structure in the list of matches.
-+ if (compl_first_match == NULL)
-+ match->cp_next = match->cp_prev = NULL;
-+ else if (dir == FORWARD)
-+ {
-+ match->cp_next = compl_curr_match->cp_next;
-+ match->cp_prev = compl_curr_match;
-+ }
-+ else // BACKWARD
-+ {
-+ match->cp_next = compl_curr_match;
-+ match->cp_prev = compl_curr_match->cp_prev;
-+ }
-+ if (match->cp_next)
-+ match->cp_next->cp_prev = match;
-+ if (match->cp_prev)
-+ match->cp_prev->cp_next = match;
-+ else // if there's nothing before, it is the first match
-+ compl_first_match = match;
-+ compl_curr_match = match;
-+
-+ // Find the longest common string if still doing that.
-+ if (compl_get_longest && (flags & ORIGINAL_TEXT) == 0)
-+ ins_compl_longest_match(match);
-+
-+ return OK;
-+ }
-+
-+ /*
-+ * Return TRUE if "str[len]" matches with match->cp_str, considering
-+ * match->cp_icase.
-+ */
-+ static int
-+ ins_compl_equal(compl_T *match, char_u *str, int len)
-+ {
-+ if (match->cp_icase)
-+ return STRNICMP(match->cp_str, str, (size_t)len) == 0;
-+ return STRNCMP(match->cp_str, str, (size_t)len) == 0;
-+ }
-+
-+ /*
-+ * Reduce the longest common string for match "match".
-+ */
-+ static void
-+ ins_compl_longest_match(compl_T *match)
-+ {
-+ char_u *p, *s;
-+ int c1, c2;
-+ int had_match;
-+
-+ if (compl_leader == NULL)
-+ {
-+ // First match, use it as a whole.
-+ compl_leader = vim_strsave(match->cp_str);
-+ if (compl_leader != NULL)
-+ {
-+ had_match = (curwin->w_cursor.col > compl_col);
-+ ins_compl_delete();
-+ ins_bytes(compl_leader + ins_compl_len());
-+ ins_redraw(FALSE);
-+
-+ // When the match isn't there (to avoid matching itself) remove it
-+ // again after redrawing.
-+ if (!had_match)
-+ ins_compl_delete();
-+ compl_used_match = FALSE;
-+ }
-+ }
-+ else
-+ {
-+ // Reduce the text if this match differs from compl_leader.
-+ p = compl_leader;
-+ s = match->cp_str;
-+ while (*p != NUL)
-+ {
-+ if (has_mbyte)
-+ {
-+ c1 = mb_ptr2char(p);
-+ c2 = mb_ptr2char(s);
-+ }
-+ else
-+ {
-+ c1 = *p;
-+ c2 = *s;
-+ }
-+ if (match->cp_icase ? (MB_TOLOWER(c1) != MB_TOLOWER(c2))
-+ : (c1 != c2))
-+ break;
-+ if (has_mbyte)
-+ {
-+ MB_PTR_ADV(p);
-+ MB_PTR_ADV(s);
-+ }
-+ else
-+ {
-+ ++p;
-+ ++s;
-+ }
-+ }
-+
-+ if (*p != NUL)
-+ {
-+ // Leader was shortened, need to change the inserted text.
-+ *p = NUL;
-+ had_match = (curwin->w_cursor.col > compl_col);
-+ ins_compl_delete();
-+ ins_bytes(compl_leader + ins_compl_len());
-+ ins_redraw(FALSE);
-+
-+ // When the match isn't there (to avoid matching itself) remove it
-+ // again after redrawing.
-+ if (!had_match)
-+ ins_compl_delete();
-+ }
-+
-+ compl_used_match = FALSE;
-+ }
-+ }
-+
-+ /*
-+ * Add an array of matches to the list of matches.
-+ * Frees matches[].
-+ */
-+ static void
-+ ins_compl_add_matches(
-+ int num_matches,
-+ char_u **matches,
-+ int icase)
-+ {
-+ int i;
-+ int add_r = OK;
-+ int dir = compl_direction;
-+
-+ for (i = 0; i < num_matches && add_r != FAIL; i++)
-+ if ((add_r = ins_compl_add(matches[i], -1, icase,
-+ NULL, NULL, dir, 0, FALSE)) == OK)
-+ // if dir was BACKWARD then honor it just once
-+ dir = FORWARD;
-+ FreeWild(num_matches, matches);
-+ }
-+
-+ /*
-+ * Make the completion list cyclic.
-+ * Return the number of matches (excluding the original).
-+ */
-+ static int
-+ ins_compl_make_cyclic(void)
-+ {
-+ compl_T *match;
-+ int count = 0;
-+
-+ if (compl_first_match != NULL)
-+ {
-+ // Find the end of the list.
-+ match = compl_first_match;
-+ // there's always an entry for the compl_orig_text, it doesn't count.
-+ while (match->cp_next != NULL && match->cp_next != compl_first_match)
-+ {
-+ match = match->cp_next;
-+ ++count;
-+ }
-+ match->cp_next = compl_first_match;
-+ compl_first_match->cp_prev = match;
-+ }
-+ return count;
-+ }
-+
-+ /*
-+ * Return whether there currently is a shown match.
-+ */
-+ int
-+ ins_compl_has_shown_match(void)
-+ {
-+ return compl_shown_match == NULL
-+ || compl_shown_match != compl_shown_match->cp_next;
-+ }
-+
-+ /*
-+ * Return whether the shown match is long enough.
-+ */
-+ int
-+ ins_compl_long_shown_match(void)
-+ {
-+ return (int)STRLEN(compl_shown_match->cp_str)
-+ > curwin->w_cursor.col - compl_col;
-+ }
-+
-+ /*
-+ * Set variables that store noselect and noinsert behavior from the
-+ * 'completeopt' value.
-+ */
-+ void
-+ completeopt_was_set(void)
-+ {
-+ compl_no_insert = FALSE;
-+ compl_no_select = FALSE;
-+ if (strstr((char *)p_cot, "noselect") != NULL)
-+ compl_no_select = TRUE;
-+ if (strstr((char *)p_cot, "noinsert") != NULL)
-+ compl_no_insert = TRUE;
-+ }
-+
-+ /*
-+ * Start completion for the complete() function.
-+ * "startcol" is where the matched text starts (1 is first column).
-+ * "list" is the list of matches.
-+ */
-+ void
-+ set_completion(colnr_T startcol, list_T *list)
-+ {
-+ int save_w_wrow = curwin->w_wrow;
-+ int save_w_leftcol = curwin->w_leftcol;
-+
-+ // If already doing completions stop it.
-+ if (ctrl_x_mode != CTRL_X_NORMAL)
-+ ins_compl_prep(' ');
-+ ins_compl_clear();
-+ ins_compl_free();
-+
-+ compl_direction = FORWARD;
-+ if (startcol > curwin->w_cursor.col)
-+ startcol = curwin->w_cursor.col;
-+ compl_col = startcol;
-+ compl_length = (int)curwin->w_cursor.col - (int)startcol;
-+ // compl_pattern doesn't need to be set
-+ compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
-+ if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
-+ -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
-+ return;
-+
-+ ctrl_x_mode = CTRL_X_EVAL;
-+
-+ ins_compl_add_list(list);
-+ compl_matches = ins_compl_make_cyclic();
-+ compl_started = TRUE;
-+ compl_used_match = TRUE;
-+ compl_cont_status = 0;
-+
-+ compl_curr_match = compl_first_match;
-+ if (compl_no_insert || compl_no_select)
-+ {
-+ ins_complete(K_DOWN, FALSE);
-+ if (compl_no_select)
-+ // Down/Up has no real effect.
-+ ins_complete(K_UP, FALSE);
-+ }
-+ else
-+ ins_complete(Ctrl_N, FALSE);
-+ compl_enter_selects = compl_no_insert;
-+
-+ // Lazily show the popup menu, unless we got interrupted.
-+ if (!compl_interrupted)
-+ show_pum(save_w_wrow, save_w_leftcol);
-+ out_flush();
-+ }
-+
-+
-+ // "compl_match_array" points the currently displayed list of entries in the
-+ // popup menu. It is NULL when there is no popup menu.
-+ static pumitem_T *compl_match_array = NULL;
-+ static int compl_match_arraysize;
-+
-+ /*
-+ * Update the screen and when there is any scrolling remove the popup menu.
-+ */
-+ static void
-+ ins_compl_upd_pum(void)
-+ {
-+ int h;
-+
-+ if (compl_match_array != NULL)
-+ {
-+ h = curwin->w_cline_height;
-+ // Update the screen later, before drawing the popup menu over it.
-+ pum_call_update_screen();
-+ if (h != curwin->w_cline_height)
-+ ins_compl_del_pum();
-+ }
-+ }
-+
-+ /*
-+ * Remove any popup menu.
-+ */
-+ static void
-+ ins_compl_del_pum(void)
-+ {
-+ if (compl_match_array != NULL)
-+ {
-+ pum_undisplay();
-+ VIM_CLEAR(compl_match_array);
-+ }
-+ }
-+
-+ /*
-+ * Return TRUE if the popup menu should be displayed.
-+ */
-+ int
-+ pum_wanted(void)
-+ {
-+ // 'completeopt' must contain "menu" or "menuone"
-+ if (vim_strchr(p_cot, 'm') == NULL)
-+ return FALSE;
-+
-+ // The display looks bad on a B&W display.
-+ if (t_colors < 8
-+ #ifdef FEAT_GUI
-+ && !gui.in_use
-+ #endif
-+ )
-+ return FALSE;
-+ return TRUE;
-+ }
-+
-+ /*
-+ * Return TRUE if there are two or more matches to be shown in the popup menu.
-+ * One if 'completopt' contains "menuone".
-+ */
-+ static int
-+ pum_enough_matches(void)
-+ {
-+ compl_T *compl;
-+ int i;
-+
-+ // Don't display the popup menu if there are no matches or there is only
-+ // one (ignoring the original text).
-+ compl = compl_first_match;
-+ i = 0;
-+ do
-+ {
-+ if (compl == NULL
-+ || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2))
-+ break;
-+ compl = compl->cp_next;
-+ } while (compl != compl_first_match);
-+
-+ if (strstr((char *)p_cot, "menuone") != NULL)
-+ return (i >= 1);
-+ return (i >= 2);
-+ }
-+
-+ /*
-+ * Show the popup menu for the list of matches.
-+ * Also adjusts "compl_shown_match" to an entry that is actually displayed.
-+ */
-+ void
-+ ins_compl_show_pum(void)
-+ {
-+ compl_T *compl;
-+ compl_T *shown_compl = NULL;
-+ int did_find_shown_match = FALSE;
-+ int shown_match_ok = FALSE;
-+ int i;
-+ int cur = -1;
-+ colnr_T col;
-+ int lead_len = 0;
-+
-+ if (!pum_wanted() || !pum_enough_matches())
-+ return;
-+
-+ #if defined(FEAT_EVAL)
-+ // Dirty hard-coded hack: remove any matchparen highlighting.
-+ do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif");
-+ #endif
-+
-+ // Update the screen later, before drawing the popup menu over it.
-+ pum_call_update_screen();
-+
-+ if (compl_match_array == NULL)
-+ {
-+ // Need to build the popup menu list.
-+ compl_match_arraysize = 0;
-+ compl = compl_first_match;
-+ if (compl_leader != NULL)
-+ lead_len = (int)STRLEN(compl_leader);
-+ do
-+ {
-+ if ((compl->cp_flags & ORIGINAL_TEXT) == 0
-+ && (compl_leader == NULL
-+ || ins_compl_equal(compl, compl_leader, lead_len)))
-+ ++compl_match_arraysize;
-+ compl = compl->cp_next;
-+ } while (compl != NULL && compl != compl_first_match);
-+ if (compl_match_arraysize == 0)
-+ return;
-+ compl_match_array = (pumitem_T *)alloc_clear(
-+ (unsigned)(sizeof(pumitem_T)
-+ * compl_match_arraysize));
-+ if (compl_match_array != NULL)
-+ {
-+ // If the current match is the original text don't find the first
-+ // match after it, don't highlight anything.
-+ if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-+ shown_match_ok = TRUE;
-+
-+ i = 0;
-+ compl = compl_first_match;
-+ do
-+ {
-+ if ((compl->cp_flags & ORIGINAL_TEXT) == 0
-+ && (compl_leader == NULL
-+ || ins_compl_equal(compl, compl_leader, lead_len)))
-+ {
-+ if (!shown_match_ok)
-+ {
-+ if (compl == compl_shown_match || did_find_shown_match)
-+ {
-+ // This item is the shown match or this is the
-+ // first displayed item after the shown match.
-+ compl_shown_match = compl;
-+ did_find_shown_match = TRUE;
-+ shown_match_ok = TRUE;
-+ }
-+ else
-+ // Remember this displayed match for when the
-+ // shown match is just below it.
-+ shown_compl = compl;
-+ cur = i;
-+ }
-+
-+ if (compl->cp_text[CPT_ABBR] != NULL)
-+ compl_match_array[i].pum_text =
-+ compl->cp_text[CPT_ABBR];
-+ else
-+ compl_match_array[i].pum_text = compl->cp_str;
-+ compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
-+ compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
-+ if (compl->cp_text[CPT_MENU] != NULL)
-+ compl_match_array[i++].pum_extra =
-+ compl->cp_text[CPT_MENU];
-+ else
-+ compl_match_array[i++].pum_extra = compl->cp_fname;
-+ }
-+
-+ if (compl == compl_shown_match)
-+ {
-+ did_find_shown_match = TRUE;
-+
-+ // When the original text is the shown match don't set
-+ // compl_shown_match.
-+ if (compl->cp_flags & ORIGINAL_TEXT)
-+ shown_match_ok = TRUE;
-+
-+ if (!shown_match_ok && shown_compl != NULL)
-+ {
-+ // The shown match isn't displayed, set it to the
-+ // previously displayed match.
-+ compl_shown_match = shown_compl;
-+ shown_match_ok = TRUE;
-+ }
-+ }
-+ compl = compl->cp_next;
-+ } while (compl != NULL && compl != compl_first_match);
-+
-+ if (!shown_match_ok) // no displayed match at all
-+ cur = -1;
-+ }
-+ }
-+ else
-+ {
-+ // popup menu already exists, only need to find the current item.
-+ for (i = 0; i < compl_match_arraysize; ++i)
-+ if (compl_match_array[i].pum_text == compl_shown_match->cp_str
-+ || compl_match_array[i].pum_text
-+ == compl_shown_match->cp_text[CPT_ABBR])
-+ {
-+ cur = i;
-+ break;
-+ }
-+ }
-+
-+ if (compl_match_array != NULL)
-+ {
-+ // In Replace mode when a $ is displayed at the end of the line only
-+ // part of the screen would be updated. We do need to redraw here.
-+ dollar_vcol = -1;
-+
-+ // Compute the screen column of the start of the completed text.
-+ // Use the cursor to get all wrapping and other settings right.
-+ col = curwin->w_cursor.col;
-+ curwin->w_cursor.col = compl_col;
-+ pum_display(compl_match_array, compl_match_arraysize, cur);
-+ curwin->w_cursor.col = col;
-+ }
-+ }
-+
-+ #define DICT_FIRST (1) // use just first element in "dict"
-+ #define DICT_EXACT (2) // "dict" is the exact name of a file
-+
-+ /*
-+ * Add any identifiers that match the given pattern in the list of dictionary
-+ * files "dict_start" to the list of completions.
-+ */
-+ static void
-+ ins_compl_dictionaries(
-+ char_u *dict_start,
-+ char_u *pat,
-+ int flags, // DICT_FIRST and/or DICT_EXACT
-+ int thesaurus) // Thesaurus completion
-+ {
-+ char_u *dict = dict_start;
-+ char_u *ptr;
-+ char_u *buf;
-+ regmatch_T regmatch;
-+ char_u **files;
-+ int count;
-+ int save_p_scs;
-+ int dir = compl_direction;
-+
-+ if (*dict == NUL)
-+ {
-+ #ifdef FEAT_SPELL
-+ // When 'dictionary' is empty and spell checking is enabled use
-+ // "spell".
-+ if (!thesaurus && curwin->w_p_spell)
-+ dict = (char_u *)"spell";
-+ else
-+ #endif
-+ return;
-+ }
-+
-+ buf = alloc(LSIZE);
-+ if (buf == NULL)
-+ return;
-+ regmatch.regprog = NULL; // so that we can goto theend
-+
-+ // If 'infercase' is set, don't use 'smartcase' here
-+ save_p_scs = p_scs;
-+ if (curbuf->b_p_inf)
-+ p_scs = FALSE;
-+
-+ // When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
-+ // to only match at the start of a line. Otherwise just match the
-+ // pattern. Also need to double backslashes.
-+ if (ctrl_x_mode_line_or_eval())
-+ {
-+ char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\");
-+ size_t len;
-+
-+ if (pat_esc == NULL)
-+ goto theend;
-+ len = STRLEN(pat_esc) + 10;
-+ ptr = alloc((unsigned)len);
-+ if (ptr == NULL)
-+ {
-+ vim_free(pat_esc);
-+ goto theend;
-+ }
-+ vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc);
-+ regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
-+ vim_free(pat_esc);
-+ vim_free(ptr);
-+ }
-+ else
-+ {
-+ regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
-+ if (regmatch.regprog == NULL)
-+ goto theend;
-+ }
-+
-+ // ignore case depends on 'ignorecase', 'smartcase' and "pat"
-+ regmatch.rm_ic = ignorecase(pat);
-+ while (*dict != NUL && !got_int && !compl_interrupted)
-+ {
-+ // copy one dictionary file name into buf
-+ if (flags == DICT_EXACT)
-+ {
-+ count = 1;
-+ files = &dict;
-+ }
-+ else
-+ {
-+ // Expand wildcards in the dictionary name, but do not allow
-+ // backticks (for security, the 'dict' option may have been set in
-+ // a modeline).
-+ copy_option_part(&dict, buf, LSIZE, ",");
-+ # ifdef FEAT_SPELL
-+ if (!thesaurus && STRCMP(buf, "spell") == 0)
-+ count = -1;
-+ else
-+ # endif
-+ if (vim_strchr(buf, '`') != NULL
-+ || expand_wildcards(1, &buf, &count, &files,
-+ EW_FILE|EW_SILENT) != OK)
-+ count = 0;
-+ }
-+
-+ # ifdef FEAT_SPELL
-+ if (count == -1)
-+ {
-+ // Complete from active spelling. Skip "\<" in the pattern, we
-+ // don't use it as a RE.
-+ if (pat[0] == '\\' && pat[1] == '<')
-+ ptr = pat + 2;
-+ else
-+ ptr = pat;
-+ spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
-+ }
-+ else
-+ # endif
-+ if (count > 0) // avoid warning for using "files" uninit
-+ {
-+ ins_compl_files(count, files, thesaurus, flags,
-+ &regmatch, buf, &dir);
-+ if (flags != DICT_EXACT)
-+ FreeWild(count, files);
-+ }
-+ if (flags != 0)
-+ break;
-+ }
-+
-+ theend:
-+ p_scs = save_p_scs;
-+ vim_regfree(regmatch.regprog);
-+ vim_free(buf);
-+ }
-+
-+ static void
-+ ins_compl_files(
-+ int count,
-+ char_u **files,
-+ int thesaurus,
-+ int flags,
-+ regmatch_T *regmatch,
-+ char_u *buf,
-+ int *dir)
-+ {
-+ char_u *ptr;
-+ int i;
-+ FILE *fp;
-+ int add_r;
-+
-+ for (i = 0; i < count && !got_int && !compl_interrupted; i++)
-+ {
-+ fp = mch_fopen((char *)files[i], "r"); // open dictionary file
-+ if (flags != DICT_EXACT)
-+ {
-+ vim_snprintf((char *)IObuff, IOSIZE,
-+ _("Scanning dictionary: %s"), (char *)files[i]);
-+ (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-+ }
-+
-+ if (fp != NULL)
-+ {
-+ // Read dictionary file line by line.
-+ // Check each line for a match.
-+ while (!got_int && !compl_interrupted
-+ && !vim_fgets(buf, LSIZE, fp))
-+ {
-+ ptr = buf;
-+ while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf)))
-+ {
-+ ptr = regmatch->startp[0];
-+ if (ctrl_x_mode_line_or_eval())
-+ ptr = find_line_end(ptr);
-+ else
-+ ptr = find_word_end(ptr);
-+ add_r = ins_compl_add_infercase(regmatch->startp[0],
-+ (int)(ptr - regmatch->startp[0]),
-+ p_ic, files[i], *dir, 0);
-+ if (thesaurus)
-+ {
-+ char_u *wstart;
-+
-+ // Add the other matches on the line
-+ ptr = buf;
-+ while (!got_int)
-+ {
-+ // Find start of the next word. Skip white
-+ // space and punctuation.
-+ ptr = find_word_start(ptr);
-+ if (*ptr == NUL || *ptr == NL)
-+ break;
-+ wstart = ptr;
-+
-+ // Find end of the word.
-+ if (has_mbyte)
-+ // Japanese words may have characters in
-+ // different classes, only separate words
-+ // with single-byte non-word characters.
-+ while (*ptr != NUL)
-+ {
-+ int l = (*mb_ptr2len)(ptr);
-+
-+ if (l < 2 && !vim_iswordc(*ptr))
-+ break;
-+ ptr += l;
-+ }
-+ else
-+ ptr = find_word_end(ptr);
-+
-+ // Add the word. Skip the regexp match.
-+ if (wstart != regmatch->startp[0])
-+ add_r = ins_compl_add_infercase(wstart,
-+ (int)(ptr - wstart),
-+ p_ic, files[i], *dir, 0);
-+ }
-+ }
-+ if (add_r == OK)
-+ // if dir was BACKWARD then honor it just once
-+ *dir = FORWARD;
-+ else if (add_r == FAIL)
-+ break;
-+ // avoid expensive call to vim_regexec() when at end
-+ // of line
-+ if (*ptr == '\n' || got_int)
-+ break;
-+ }
-+ line_breakcheck();
-+ ins_compl_check_keys(50, FALSE);
-+ }
-+ fclose(fp);
-+ }
-+ }
-+ }
-+
-+ /*
-+ * Find the start of the next word.
-+ * Returns a pointer to the first char of the word. Also stops at a NUL.
-+ */
-+ char_u *
-+ find_word_start(char_u *ptr)
-+ {
-+ if (has_mbyte)
-+ while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
-+ ptr += (*mb_ptr2len)(ptr);
-+ else
-+ while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
-+ ++ptr;
-+ return ptr;
-+ }
-+
-+ /*
-+ * Find the end of the word. Assumes it starts inside a word.
-+ * Returns a pointer to just after the word.
-+ */
-+ char_u *
-+ find_word_end(char_u *ptr)
-+ {
-+ int start_class;
-+
-+ if (has_mbyte)
-+ {
-+ start_class = mb_get_class(ptr);
-+ if (start_class > 1)
-+ while (*ptr != NUL)
-+ {
-+ ptr += (*mb_ptr2len)(ptr);
-+ if (mb_get_class(ptr) != start_class)
-+ break;
-+ }
-+ }
-+ else
-+ while (vim_iswordc(*ptr))
-+ ++ptr;
-+ return ptr;
-+ }
-+
-+ /*
-+ * Find the end of the line, omitting CR and NL at the end.
-+ * Returns a pointer to just after the line.
-+ */
-+ static char_u *
-+ find_line_end(char_u *ptr)
-+ {
-+ char_u *s;
-+
-+ s = ptr + STRLEN(ptr);
-+ while (s > ptr && (s[-1] == CAR || s[-1] == NL))
-+ --s;
-+ return s;
-+ }
-+
-+ /*
-+ * Free the list of completions
-+ */
-+ static void
-+ ins_compl_free(void)
-+ {
-+ compl_T *match;
-+ int i;
-+
-+ VIM_CLEAR(compl_pattern);
-+ VIM_CLEAR(compl_leader);
-+
-+ if (compl_first_match == NULL)
-+ return;
-+
-+ ins_compl_del_pum();
-+ pum_clear();
-+
-+ compl_curr_match = compl_first_match;
-+ do
-+ {
-+ match = compl_curr_match;
-+ compl_curr_match = compl_curr_match->cp_next;
-+ vim_free(match->cp_str);
-+ // several entries may use the same fname, free it just once.
-+ if (match->cp_flags & FREE_FNAME)
-+ vim_free(match->cp_fname);
-+ for (i = 0; i < CPT_COUNT; ++i)
-+ vim_free(match->cp_text[i]);
-+ vim_free(match);
-+ } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
-+ compl_first_match = compl_curr_match = NULL;
-+ compl_shown_match = NULL;
-+ compl_old_match = NULL;
-+ }
-+
-+ void
-+ ins_compl_clear(void)
-+ {
-+ compl_cont_status = 0;
-+ compl_started = FALSE;
-+ compl_matches = 0;
-+ VIM_CLEAR(compl_pattern);
-+ VIM_CLEAR(compl_leader);
-+ edit_submode_extra = NULL;
-+ VIM_CLEAR(compl_orig_text);
-+ compl_enter_selects = FALSE;
-+ // clear v:completed_item
-+ set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
-+ }
-+
-+ /*
-+ * Return TRUE when Insert completion is active.
-+ */
-+ int
-+ ins_compl_active(void)
-+ {
-+ return compl_started;
-+ }
-+
-+ /*
-+ * Get complete information
-+ */
-+ void
-+ get_complete_info(list_T *what_list, dict_T *retdict)
-+ {
-+ int ret = OK;
-+ listitem_T *item;
-+ #define CI_WHAT_MODE 0x01
-+ #define CI_WHAT_PUM_VISIBLE 0x02
-+ #define CI_WHAT_ITEMS 0x04
-+ #define CI_WHAT_SELECTED 0x08
-+ #define CI_WHAT_INSERTED 0x10
-+ #define CI_WHAT_ALL 0xff
-+ int what_flag;
-+
-+ if (what_list == NULL)
-+ what_flag = CI_WHAT_ALL;
-+ else
-+ {
-+ what_flag = 0;
-+ for (item = what_list->lv_first; item != NULL; item = item->li_next)
-+ {
-+ char_u *what = tv_get_string(&item->li_tv);
-+
-+ if (STRCMP(what, "mode") == 0)
-+ what_flag |= CI_WHAT_MODE;
-+ else if (STRCMP(what, "pum_visible") == 0)
-+ what_flag |= CI_WHAT_PUM_VISIBLE;
-+ else if (STRCMP(what, "items") == 0)
-+ what_flag |= CI_WHAT_ITEMS;
-+ else if (STRCMP(what, "selected") == 0)
-+ what_flag |= CI_WHAT_SELECTED;
-+ else if (STRCMP(what, "inserted") == 0)
-+ what_flag |= CI_WHAT_INSERTED;
-+ }
-+ }
-+
-+ if (ret == OK && (what_flag & CI_WHAT_MODE))
-+ ret = dict_add_string(retdict, "mode", ins_compl_mode());
-+
-+ if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE))
-+ ret = dict_add_number(retdict, "pum_visible", pum_visible());
-+
-+ if (ret == OK && (what_flag & CI_WHAT_ITEMS))
-+ {
-+ list_T *li;
-+ dict_T *di;
-+ compl_T *match;
-+
-+ li = list_alloc();
-+ if (li == NULL)
-+ return;
-+ ret = dict_add_list(retdict, "items", li);
-+ if (ret == OK && compl_first_match != NULL)
-+ {
-+ match = compl_first_match;
-+ do
-+ {
-+ if (!(match->cp_flags & ORIGINAL_TEXT))
-+ {
-+ di = dict_alloc();
-+ if (di == NULL)
-+ return;
-+ ret = list_append_dict(li, di);
-+ if (ret != OK)
-+ return;
-+ dict_add_string(di, "word", match->cp_str);
-+ dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
-+ dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
-+ dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
-+ dict_add_string(di, "info", match->cp_text[CPT_INFO]);
-+ dict_add_string(di, "user_data",
-+ match->cp_text[CPT_USER_DATA]);
-+ }
-+ match = match->cp_next;
-+ }
-+ while (match != NULL && match != compl_first_match);
-+ }
-+ }
-+
-+ if (ret == OK && (what_flag & CI_WHAT_SELECTED))
-+ ret = dict_add_number(retdict, "selected", (compl_curr_match != NULL) ?
-+ compl_curr_match->cp_number - 1 : -1);
-+
-+ // TODO
-+ // if (ret == OK && (what_flag & CI_WHAT_INSERTED))
-+ }
-+
-+ /*
-+ * Return Insert completion mode name string
-+ */
-+ static char_u *
-+ ins_compl_mode(void)
-+ {
-+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || compl_started)
-+ return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
-+
-+ return (char_u *)"";
-+ }
-+
-+ /*
-+ * Selected one of the matches. When FALSE the match was edited or using the
-+ * longest common string.
-+ */
-+ int
-+ ins_compl_used_match(void)
-+ {
-+ return compl_used_match;
-+ }
-+
-+ /*
-+ * Initialize get longest common string.
-+ */
-+ void
-+ ins_compl_init_get_longest(void)
-+ {
-+ compl_get_longest = FALSE;
-+ }
-+
-+ /*
-+ * Returns TRUE when insert completion is interrupted.
-+ */
-+ int
-+ ins_compl_interrupted(void)
-+ {
-+ return compl_interrupted;
-+ }
-+
-+ /*
-+ * Returns TRUE if the <Enter> key selects a match in the completion popup
-+ * menu.
-+ */
-+ int
-+ ins_compl_enter_selects(void)
-+ {
-+ return compl_enter_selects;
-+ }
-+
-+ /*
-+ * Return the column where the text starts that is being completed
-+ */
-+ colnr_T
-+ ins_compl_col(void)
-+ {
-+ return compl_col;
-+ }
-+
-+ /*
-+ * Delete one character before the cursor and show the subset of the matches
-+ * that match the word that is now before the cursor.
-+ * Returns the character to be used, NUL if the work is done and another char
-+ * to be got from the user.
-+ */
-+ int
-+ ins_compl_bs(void)
-+ {
-+ char_u *line;
-+ char_u *p;
-+
-+ line = ml_get_curline();
-+ p = line + curwin->w_cursor.col;
-+ MB_PTR_BACK(line, p);
-+
-+ // Stop completion when the whole word was deleted. For Omni completion
-+ // allow the word to be deleted, we won't match everything.
-+ // Respect the 'backspace' option.
-+ if ((int)(p - line) - (int)compl_col < 0
-+ || ((int)(p - line) - (int)compl_col == 0
-+ && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL
-+ || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
-+ - compl_length < 0))
-+ return K_BS;
-+
-+ // Deleted more than what was used to find matches or didn't finish
-+ // finding all matches: need to look for matches all over again.
-+ if (curwin->w_cursor.col <= compl_col + compl_length
-+ || ins_compl_need_restart())
-+ ins_compl_restart();
-+
-+ vim_free(compl_leader);
-+ compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col);
-+ if (compl_leader != NULL)
-+ {
-+ ins_compl_new_leader();
-+ if (compl_shown_match != NULL)
-+ // Make sure current match is not a hidden item.
-+ compl_curr_match = compl_shown_match;
-+ return NUL;
-+ }
-+ return K_BS;
-+ }
-+
-+ /*
-+ * Return TRUE when we need to find matches again, ins_compl_restart() is to
-+ * be called.
-+ */
-+ static int
-+ ins_compl_need_restart(void)
-+ {
-+ // Return TRUE if we didn't complete finding matches or when the
-+ // 'completefunc' returned "always" in the "refresh" dictionary item.
-+ return compl_was_interrupted
-+ || ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
-+ && compl_opt_refresh_always);
-+ }
-+
-+ /*
-+ * Called after changing "compl_leader".
-+ * Show the popup menu with a different set of matches.
-+ * May also search for matches again if the previous search was interrupted.
-+ */
-+ static void
-+ ins_compl_new_leader(void)
-+ {
-+ ins_compl_del_pum();
-+ ins_compl_delete();
-+ ins_bytes(compl_leader + ins_compl_len());
-+ compl_used_match = FALSE;
-+
-+ if (compl_started)
-+ ins_compl_set_original_text(compl_leader);
-+ else
-+ {
-+ #ifdef FEAT_SPELL
-+ spell_bad_len = 0; // need to redetect bad word
-+ #endif
-+ // Matches were cleared, need to search for them now. Befor drawing
-+ // the popup menu display the changed text before the cursor. Set
-+ // "compl_restarting" to avoid that the first match is inserted.
-+ pum_call_update_screen();
-+ #ifdef FEAT_GUI
-+ if (gui.in_use)
-+ {
-+ // Show the cursor after the match, not after the redrawn text.
-+ setcursor();
-+ out_flush_cursor(FALSE, FALSE);
-+ }
-+ #endif
-+ compl_restarting = TRUE;
-+ if (ins_complete(Ctrl_N, TRUE) == FAIL)
-+ compl_cont_status = 0;
-+ compl_restarting = FALSE;
-+ }
-+
-+ compl_enter_selects = !compl_used_match;
-+
-+ // Show the popup menu with a different set of matches.
-+ ins_compl_show_pum();
-+
-+ // Don't let Enter select the original text when there is no popup menu.
-+ if (compl_match_array == NULL)
-+ compl_enter_selects = FALSE;
-+ }
-+
-+ /*
-+ * Return the length of the completion, from the completion start column to
-+ * the cursor column. Making sure it never goes below zero.
-+ */
-+ static int
-+ ins_compl_len(void)
-+ {
-+ int off = (int)curwin->w_cursor.col - (int)compl_col;
-+
-+ if (off < 0)
-+ return 0;
-+ return off;
-+ }
-+
-+ /*
-+ * Append one character to the match leader. May reduce the number of
-+ * matches.
-+ */
-+ void
-+ ins_compl_addleader(int c)
-+ {
-+ int cc;
-+
-+ if (stop_arrow() == FAIL)
-+ return;
-+ if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
-+ {
-+ char_u buf[MB_MAXBYTES + 1];
-+
-+ (*mb_char2bytes)(c, buf);
-+ buf[cc] = NUL;
-+ ins_char_bytes(buf, cc);
-+ if (compl_opt_refresh_always)
-+ AppendToRedobuff(buf);
-+ }
-+ else
-+ {
-+ ins_char(c);
-+ if (compl_opt_refresh_always)
-+ AppendCharToRedobuff(c);
-+ }
-+
-+ // If we didn't complete finding matches we must search again.
-+ if (ins_compl_need_restart())
-+ ins_compl_restart();
-+
-+ // When 'always' is set, don't reset compl_leader. While completing,
-+ // cursor doesn't point original position, changing compl_leader would
-+ // break redo.
-+ if (!compl_opt_refresh_always)
-+ {
-+ vim_free(compl_leader);
-+ compl_leader = vim_strnsave(ml_get_curline() + compl_col,
-+ (int)(curwin->w_cursor.col - compl_col));
-+ if (compl_leader != NULL)
-+ ins_compl_new_leader();
-+ }
-+ }
-+
-+ /*
-+ * Setup for finding completions again without leaving CTRL-X mode. Used when
-+ * BS or a key was typed while still searching for matches.
-+ */
-+ static void
-+ ins_compl_restart(void)
-+ {
-+ ins_compl_free();
-+ compl_started = FALSE;
-+ compl_matches = 0;
-+ compl_cont_status = 0;
-+ compl_cont_mode = 0;
-+ }
-+
-+ /*
-+ * Set the first match, the original text.
-+ */
-+ static void
-+ ins_compl_set_original_text(char_u *str)
-+ {
-+ char_u *p;
-+
-+ // Replace the original text entry.
-+ // The ORIGINAL_TEXT flag is either at the first item or might possibly be
-+ // at the last item for backward completion
-+ if (compl_first_match->cp_flags & ORIGINAL_TEXT) // safety check
-+ {
-+ p = vim_strsave(str);
-+ if (p != NULL)
-+ {
-+ vim_free(compl_first_match->cp_str);
-+ compl_first_match->cp_str = p;
-+ }
-+ }
-+ else if (compl_first_match->cp_prev != NULL
-+ && (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT))
-+ {
-+ p = vim_strsave(str);
-+ if (p != NULL)
-+ {
-+ vim_free(compl_first_match->cp_prev->cp_str);
-+ compl_first_match->cp_prev->cp_str = p;
-+ }
-+ }
-+ }
-+
-+ /*
-+ * Append one character to the match leader. May reduce the number of
-+ * matches.
-+ */
-+ void
-+ ins_compl_addfrommatch(void)
-+ {
-+ char_u *p;
-+ int len = (int)curwin->w_cursor.col - (int)compl_col;
-+ int c;
-+ compl_T *cp;
-+
-+ p = compl_shown_match->cp_str;
-+ if ((int)STRLEN(p) <= len) // the match is too short
-+ {
-+ // When still at the original match use the first entry that matches
-+ // the leader.
-+ if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-+ {
-+ p = NULL;
-+ for (cp = compl_shown_match->cp_next; cp != NULL
-+ && cp != compl_first_match; cp = cp->cp_next)
-+ {
-+ if (compl_leader == NULL
-+ || ins_compl_equal(cp, compl_leader,
-+ (int)STRLEN(compl_leader)))
-+ {
-+ p = cp->cp_str;
-+ break;
-+ }
-+ }
-+ if (p == NULL || (int)STRLEN(p) <= len)
-+ return;
-+ }
-+ else
-+ return;
-+ }
-+ p += len;
-+ c = PTR2CHAR(p);
-+ ins_compl_addleader(c);
-+ }
-+
-+ /*
-+ * Prepare for Insert mode completion, or stop it.
-+ * Called just after typing a character in Insert mode.
-+ * Returns TRUE when the character is not to be inserted;
-+ */
-+ int
-+ ins_compl_prep(int c)
-+ {
-+ char_u *ptr;
-+ int want_cindent;
-+ int retval = FALSE;
-+
-+ // Forget any previous 'special' messages if this is actually
-+ // a ^X mode key - bar ^R, in which case we wait to see what it gives us.
-+ if (c != Ctrl_R && vim_is_ctrl_x_key(c))
-+ edit_submode_extra = NULL;
-+
-+ // Ignore end of Select mode mapping and mouse scroll buttons.
-+ if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
-+ || c == K_MOUSELEFT || c == K_MOUSERIGHT)
-+ return retval;
-+
-+ // Set "compl_get_longest" when finding the first matches.
-+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
-+ || (ctrl_x_mode == CTRL_X_NORMAL && !compl_started))
-+ {
-+ compl_get_longest = (strstr((char *)p_cot, "longest") != NULL);
-+ compl_used_match = TRUE;
-+
-+ }
-+
-+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
-+ {
-+ // We have just typed CTRL-X and aren't quite sure which CTRL-X mode
-+ // it will be yet. Now we decide.
-+ switch (c)
-+ {
-+ case Ctrl_E:
-+ case Ctrl_Y:
-+ ctrl_x_mode = CTRL_X_SCROLL;
-+ if (!(State & REPLACE_FLAG))
-+ edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
-+ else
-+ edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
-+ edit_submode_pre = NULL;
-+ showmode();
-+ break;
-+ case Ctrl_L:
-+ ctrl_x_mode = CTRL_X_WHOLE_LINE;
-+ break;
-+ case Ctrl_F:
-+ ctrl_x_mode = CTRL_X_FILES;
-+ break;
-+ case Ctrl_K:
-+ ctrl_x_mode = CTRL_X_DICTIONARY;
-+ break;
-+ case Ctrl_R:
-+ // Simply allow ^R to happen without affecting ^X mode
-+ break;
-+ case Ctrl_T:
-+ ctrl_x_mode = CTRL_X_THESAURUS;
-+ break;
-+ #ifdef FEAT_COMPL_FUNC
-+ case Ctrl_U:
-+ ctrl_x_mode = CTRL_X_FUNCTION;
-+ break;
-+ case Ctrl_O:
-+ ctrl_x_mode = CTRL_X_OMNI;
-+ break;
-+ #endif
-+ case 's':
-+ case Ctrl_S:
-+ ctrl_x_mode = CTRL_X_SPELL;
-+ #ifdef FEAT_SPELL
-+ ++emsg_off; // Avoid getting the E756 error twice.
-+ spell_back_to_badword();
-+ --emsg_off;
-+ #endif
-+ break;
-+ case Ctrl_RSB:
-+ ctrl_x_mode = CTRL_X_TAGS;
-+ break;
-+ #ifdef FEAT_FIND_ID
-+ case Ctrl_I:
-+ case K_S_TAB:
-+ ctrl_x_mode = CTRL_X_PATH_PATTERNS;
-+ break;
-+ case Ctrl_D:
-+ ctrl_x_mode = CTRL_X_PATH_DEFINES;
-+ break;
-+ #endif
-+ case Ctrl_V:
-+ case Ctrl_Q:
-+ ctrl_x_mode = CTRL_X_CMDLINE;
-+ break;
-+ case Ctrl_P:
-+ case Ctrl_N:
-+ // ^X^P means LOCAL expansion if nothing interrupted (eg we
-+ // just started ^X mode, or there were enough ^X's to cancel
-+ // the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
-+ // do normal expansion when interrupting a different mode (say
-+ // ^X^F^X^P or ^P^X^X^P, see below)
-+ // nothing changes if interrupting mode 0, (eg, the flag
-+ // doesn't change when going to ADDING mode -- Acevedo
-+ if (!(compl_cont_status & CONT_INTRPT))
-+ compl_cont_status |= CONT_LOCAL;
-+ else if (compl_cont_mode != 0)
-+ compl_cont_status &= ~CONT_LOCAL;
-+ // FALLTHROUGH
-+ default:
-+ // If we have typed at least 2 ^X's... for modes != 0, we set
-+ // compl_cont_status = 0 (eg, as if we had just started ^X
-+ // mode).
-+ // For mode 0, we set "compl_cont_mode" to an impossible
-+ // value, in both cases ^X^X can be used to restart the same
-+ // mode (avoiding ADDING mode).
-+ // Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
-+ // 'complete' and local ^P expansions respectively.
-+ // In mode 0 an extra ^X is needed since ^X^P goes to ADDING
-+ // mode -- Acevedo
-+ if (c == Ctrl_X)
-+ {
-+ if (compl_cont_mode != 0)
-+ compl_cont_status = 0;
-+ else
-+ compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
-+ }
-+ ctrl_x_mode = CTRL_X_NORMAL;
-+ edit_submode = NULL;
-+ showmode();
-+ break;
-+ }
-+ }
-+ else if (ctrl_x_mode != CTRL_X_NORMAL)
-+ {
-+ // We're already in CTRL-X mode, do we stay in it?
-+ if (!vim_is_ctrl_x_key(c))
-+ {
-+ if (ctrl_x_mode == CTRL_X_SCROLL)
-+ ctrl_x_mode = CTRL_X_NORMAL;
-+ else
-+ ctrl_x_mode = CTRL_X_FINISHED;
-+ edit_submode = NULL;
-+ }
-+ showmode();
-+ }
-+
-+ if (compl_started || ctrl_x_mode == CTRL_X_FINISHED)
-+ {
-+ // Show error message from attempted keyword completion (probably
-+ // 'Pattern not found') until another key is hit, then go back to
-+ // showing what mode we are in.
-+ showmode();
-+ if ((ctrl_x_mode == CTRL_X_NORMAL && c != Ctrl_N && c != Ctrl_P
-+ && c != Ctrl_R && !ins_compl_pum_key(c))
-+ || ctrl_x_mode == CTRL_X_FINISHED)
-+ {
-+ // Get here when we have finished typing a sequence of ^N and
-+ // ^P or other completion characters in CTRL-X mode. Free up
-+ // memory that was used, and make sure we can redo the insert.
-+ if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
-+ {
-+ // If any of the original typed text has been changed, eg when
-+ // ignorecase is set, we must add back-spaces to the redo
-+ // buffer. We add as few as necessary to delete just the part
-+ // of the original text that has changed.
-+ // When using the longest match, edited the match or used
-+ // CTRL-E then don't use the current match.
-+ if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
-+ ptr = compl_curr_match->cp_str;
-+ else
-+ ptr = NULL;
-+ ins_compl_fixRedoBufForLeader(ptr);
-+ }
-+
-+ #ifdef FEAT_CINDENT
-+ want_cindent = (can_cindent_get() && cindent_on());
-+ #endif
-+ // When completing whole lines: fix indent for 'cindent'.
-+ // Otherwise, break line if it's too long.
-+ if (compl_cont_mode == CTRL_X_WHOLE_LINE)
-+ {
-+ #ifdef FEAT_CINDENT
-+ // re-indent the current line
-+ if (want_cindent)
-+ {
-+ do_c_expr_indent();
-+ want_cindent = FALSE; // don't do it again
-+ }
-+ #endif
-+ }
-+ else
-+ {
-+ int prev_col = curwin->w_cursor.col;
-+
-+ // put the cursor on the last char, for 'tw' formatting
-+ if (prev_col > 0)
-+ dec_cursor();
-+ // only format when something was inserted
-+ if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E)
-+ insertchar(NUL, 0, -1);
-+ if (prev_col > 0
-+ && ml_get_curline()[curwin->w_cursor.col] != NUL)
-+ inc_cursor();
-+ }
-+
-+ // If the popup menu is displayed pressing CTRL-Y means accepting
-+ // the selection without inserting anything. When
-+ // compl_enter_selects is set the Enter key does the same.
-+ if ((c == Ctrl_Y || (compl_enter_selects
-+ && (c == CAR || c == K_KENTER || c == NL)))
-+ && pum_visible())
-+ retval = TRUE;
-+
-+ // CTRL-E means completion is Ended, go back to the typed text.
-+ // but only do this, if the Popup is still visible
-+ if (c == Ctrl_E)
-+ {
-+ ins_compl_delete();
-+ if (compl_leader != NULL)
-+ ins_bytes(compl_leader + ins_compl_len());
-+ else if (compl_first_match != NULL)
-+ ins_bytes(compl_orig_text + ins_compl_len());
-+ retval = TRUE;
-+ }
-+
-+ auto_format(FALSE, TRUE);
-+
-+ ins_compl_free();
-+ compl_started = FALSE;
-+ compl_matches = 0;
-+ if (!shortmess(SHM_COMPLETIONMENU))
-+ msg_clr_cmdline(); // necessary for "noshowmode"
-+ ctrl_x_mode = CTRL_X_NORMAL;
-+ compl_enter_selects = FALSE;
-+ if (edit_submode != NULL)
-+ {
-+ edit_submode = NULL;
-+ showmode();
-+ }
-+
-+ #ifdef FEAT_CMDWIN
-+ if (c == Ctrl_C && cmdwin_type != 0)
-+ // Avoid the popup menu remains displayed when leaving the
-+ // command line window.
-+ update_screen(0);
-+ #endif
-+ #ifdef FEAT_CINDENT
-+ // Indent now if a key was typed that is in 'cinkeys'.
-+ if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
-+ do_c_expr_indent();
-+ #endif
-+ // Trigger the CompleteDone event to give scripts a chance to act
-+ // upon the completion.
-+ ins_apply_autocmds(EVENT_COMPLETEDONE);
-+ }
-+ }
-+ else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
-+ // Trigger the CompleteDone event to give scripts a chance to act
-+ // upon the (possibly failed) completion.
-+ ins_apply_autocmds(EVENT_COMPLETEDONE);
-+
-+ // reset continue_* if we left expansion-mode, if we stay they'll be
-+ // (re)set properly in ins_complete()
-+ if (!vim_is_ctrl_x_key(c))
-+ {
-+ compl_cont_status = 0;
-+ compl_cont_mode = 0;
-+ }
-+
-+ return retval;
-+ }
-+
-+ /*
-+ * Fix the redo buffer for the completion leader replacing some of the typed
-+ * text. This inserts backspaces and appends the changed text.
-+ * "ptr" is the known leader text or NUL.
-+ */
-+ static void
-+ ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
-+ {
-+ int len;
-+ char_u *p;
-+ char_u *ptr = ptr_arg;
-+
-+ if (ptr == NULL)
-+ {
-+ if (compl_leader != NULL)
-+ ptr = compl_leader;
-+ else
-+ return; // nothing to do
-+ }
-+ if (compl_orig_text != NULL)
-+ {
-+ p = compl_orig_text;
-+ for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len)
-+ ;
-+ if (len > 0)
-+ len -= (*mb_head_off)(p, p + len);
-+ for (p += len; *p != NUL; MB_PTR_ADV(p))
-+ AppendCharToRedobuff(K_BS);
-+ }
-+ else
-+ len = 0;
-+ if (ptr != NULL)
-+ AppendToRedobuffLit(ptr + len, -1);
-+ }
-+
-+ /*
-+ * Loops through the list of windows, loaded-buffers or non-loaded-buffers
-+ * (depending on flag) starting from buf and looking for a non-scanned
-+ * buffer (other than curbuf). curbuf is special, if it is called with
-+ * buf=curbuf then it has to be the first call for a given flag/expansion.
-+ *
-+ * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
-+ */
-+ static buf_T *
-+ ins_compl_next_buf(buf_T *buf, int flag)
-+ {
-+ static win_T *wp = NULL;
-+
-+ if (flag == 'w') // just windows
-+ {
-+ if (buf == curbuf || wp == NULL) // first call for this flag/expansion
-+ wp = curwin;
-+ while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
-+ && wp->w_buffer->b_scanned)
-+ ;
-+ buf = wp->w_buffer;
-+ }
-+ else
-+ // 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
-+ // (unlisted buffers)
-+ // When completing whole lines skip unloaded buffers.
-+ while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf
-+ && ((flag == 'U'
-+ ? buf->b_p_bl
-+ : (!buf->b_p_bl
-+ || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
-+ || buf->b_scanned))
-+ ;
-+ return buf;
-+ }
-+
-+ #ifdef FEAT_COMPL_FUNC
-+ /*
-+ * Execute user defined complete function 'completefunc' or 'omnifunc', and
-+ * get matches in "matches".
-+ */
-+ static void
-+ expand_by_function(
-+ int type, // CTRL_X_OMNI or CTRL_X_FUNCTION
-+ char_u *base)
-+ {
-+ list_T *matchlist = NULL;
-+ dict_T *matchdict = NULL;
-+ typval_T args[3];
-+ char_u *funcname;
-+ pos_T pos;
-+ win_T *curwin_save;
-+ buf_T *curbuf_save;
-+ typval_T rettv;
-+ int save_State = State;
-+
-+ funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
-+ if (*funcname == NUL)
-+ return;
-+
-+ // Call 'completefunc' to obtain the list of matches.
-+ args[0].v_type = VAR_NUMBER;
-+ args[0].vval.v_number = 0;
-+ args[1].v_type = VAR_STRING;
-+ args[1].vval.v_string = base != NULL ? base : (char_u *)"";
-+ args[2].v_type = VAR_UNKNOWN;
-+
-+ pos = curwin->w_cursor;
-+ curwin_save = curwin;
-+ curbuf_save = curbuf;
-+
-+ // Call a function, which returns a list or dict.
-+ if (call_vim_function(funcname, 2, args, &rettv) == OK)
-+ {
-+ switch (rettv.v_type)
-+ {
-+ case VAR_LIST:
-+ matchlist = rettv.vval.v_list;
-+ break;
-+ case VAR_DICT:
-+ matchdict = rettv.vval.v_dict;
-+ break;
-+ case VAR_SPECIAL:
-+ if (rettv.vval.v_number == VVAL_NONE)
-+ compl_opt_suppress_empty = TRUE;
-+ // FALLTHROUGH
-+ default:
-+ // TODO: Give error message?
-+ clear_tv(&rettv);
-+ break;
-+ }
-+ }
-+
-+ if (curwin_save != curwin || curbuf_save != curbuf)
-+ {
-+ emsg(_(e_complwin));
-+ goto theend;
-+ }
-+ curwin->w_cursor = pos; // restore the cursor position
-+ validate_cursor();
-+ if (!EQUAL_POS(curwin->w_cursor, pos))
-+ {
-+ emsg(_(e_compldel));
-+ goto theend;
-+ }
-+
-+ if (matchlist != NULL)
-+ ins_compl_add_list(matchlist);
-+ else if (matchdict != NULL)
-+ ins_compl_add_dict(matchdict);
-+
-+ theend:
-+ // Restore State, it might have been changed.
-+ State = save_State;
-+
-+ if (matchdict != NULL)
-+ dict_unref(matchdict);
-+ if (matchlist != NULL)
-+ list_unref(matchlist);
-+ }
-+ #endif // FEAT_COMPL_FUNC
-+
-+ #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO)
-+ /*
-+ * Add completions from a list.
-+ */
-+ static void
-+ ins_compl_add_list(list_T *list)
-+ {
-+ listitem_T *li;
-+ int dir = compl_direction;
-+
-+ // Go through the List with matches and add each of them.
-+ for (li = list->lv_first; li != NULL; li = li->li_next)
-+ {
-+ if (ins_compl_add_tv(&li->li_tv, dir) == OK)
-+ // if dir was BACKWARD then honor it just once
-+ dir = FORWARD;
-+ else if (did_emsg)
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * Add completions from a dict.
-+ */
-+ static void
-+ ins_compl_add_dict(dict_T *dict)
-+ {
-+ dictitem_T *di_refresh;
-+ dictitem_T *di_words;
-+
-+ // Check for optional "refresh" item.
-+ compl_opt_refresh_always = FALSE;
-+ di_refresh = dict_find(dict, (char_u *)"refresh", 7);
-+ if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING)
-+ {
-+ char_u *v = di_refresh->di_tv.vval.v_string;
-+
-+ if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
-+ compl_opt_refresh_always = TRUE;
-+ }
-+
-+ // Add completions from a "words" list.
-+ di_words = dict_find(dict, (char_u *)"words", 5);
-+ if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
-+ ins_compl_add_list(di_words->di_tv.vval.v_list);
-+ }
-+
-+ /*
-+ * Add a match to the list of matches from a typeval_T.
-+ * If the given string is already in the list of completions, then return
-+ * NOTDONE, otherwise add it to the list and return OK. If there is an error,
-+ * maybe because alloc() returns NULL, then FAIL is returned.
-+ */
-+ int
-+ ins_compl_add_tv(typval_T *tv, int dir)
-+ {
-+ char_u *word;
-+ int icase = FALSE;
-+ int adup = FALSE;
-+ int aempty = FALSE;
-+ char_u *(cptext[CPT_COUNT]);
-+
-+ if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
-+ {
-+ word = dict_get_string(tv->vval.v_dict, (char_u *)"word", FALSE);
-+ cptext[CPT_ABBR] = dict_get_string(tv->vval.v_dict,
-+ (char_u *)"abbr", FALSE);
-+ cptext[CPT_MENU] = dict_get_string(tv->vval.v_dict,
-+ (char_u *)"menu", FALSE);
-+ cptext[CPT_KIND] = dict_get_string(tv->vval.v_dict,
-+ (char_u *)"kind", FALSE);
-+ cptext[CPT_INFO] = dict_get_string(tv->vval.v_dict,
-+ (char_u *)"info", FALSE);
-+ cptext[CPT_USER_DATA] = dict_get_string(tv->vval.v_dict,
-+ (char_u *)"user_data", FALSE);
-+ if (dict_get_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL)
-+ icase = dict_get_number(tv->vval.v_dict, (char_u *)"icase");
-+ if (dict_get_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
-+ adup = dict_get_number(tv->vval.v_dict, (char_u *)"dup");
-+ if (dict_get_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL)
-+ aempty = dict_get_number(tv->vval.v_dict, (char_u *)"empty");
-+ }
-+ else
-+ {
-+ word = tv_get_string_chk(tv);
-+ vim_memset(cptext, 0, sizeof(cptext));
-+ }
-+ if (word == NULL || (!aempty && *word == NUL))
-+ return FAIL;
-+ return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
-+ }
-+ #endif
-+
-+ /*
-+ * Get the next expansion(s), using "compl_pattern".
-+ * The search starts at position "ini" in curbuf and in the direction
-+ * compl_direction.
-+ * When "compl_started" is FALSE start at that position, otherwise continue
-+ * where we stopped searching before.
-+ * This may return before finding all the matches.
-+ * Return the total number of matches or -1 if still unknown -- Acevedo
-+ */
-+ static int
-+ ins_compl_get_exp(pos_T *ini)
-+ {
-+ static pos_T first_match_pos;
-+ static pos_T last_match_pos;
-+ static char_u *e_cpt = (char_u *)""; // curr. entry in 'complete'
-+ static int found_all = FALSE; // Found all matches of a
-+ // certain type.
-+ static buf_T *ins_buf = NULL; // buffer being scanned
-+
-+ pos_T *pos;
-+ char_u **matches;
-+ int save_p_scs;
-+ int save_p_ws;
-+ int save_p_ic;
-+ int i;
-+ int num_matches;
-+ int len;
-+ int found_new_match;
-+ int type = ctrl_x_mode;
-+ char_u *ptr;
-+ char_u *dict = NULL;
-+ int dict_f = 0;
-+ int set_match_pos;
-+
-+ if (!compl_started)
-+ {
-+ FOR_ALL_BUFFERS(ins_buf)
-+ ins_buf->b_scanned = 0;
-+ found_all = FALSE;
-+ ins_buf = curbuf;
-+ e_cpt = (compl_cont_status & CONT_LOCAL)
-+ ? (char_u *)"." : curbuf->b_p_cpt;
-+ last_match_pos = first_match_pos = *ini;
-+ }
-+ else if (ins_buf != curbuf && !buf_valid(ins_buf))
-+ ins_buf = curbuf; // In case the buffer was wiped out.
-+
-+ compl_old_match = compl_curr_match; // remember the last current match
-+ pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
-+
-+ // For ^N/^P loop over all the flags/windows/buffers in 'complete'.
-+ for (;;)
-+ {
-+ found_new_match = FAIL;
-+ set_match_pos = FALSE;
-+
-+ // For ^N/^P pick a new entry from e_cpt if compl_started is off,
-+ // or if found_all says this entry is done. For ^X^L only use the
-+ // entries from 'complete' that look in loaded buffers.
-+ if ((ctrl_x_mode == CTRL_X_NORMAL
-+ || ctrl_x_mode_line_or_eval())
-+ && (!compl_started || found_all))
-+ {
-+ found_all = FALSE;
-+ while (*e_cpt == ',' || *e_cpt == ' ')
-+ e_cpt++;
-+ if (*e_cpt == '.' && !curbuf->b_scanned)
-+ {
-+ ins_buf = curbuf;
-+ first_match_pos = *ini;
-+ // Move the cursor back one character so that ^N can match the
-+ // word immediately after the cursor.
-+ if (ctrl_x_mode == CTRL_X_NORMAL && dec(&first_match_pos) < 0)
-+ {
-+ // Move the cursor to after the last character in the
-+ // buffer, so that word at start of buffer is found
-+ // correctly.
-+ first_match_pos.lnum = ins_buf->b_ml.ml_line_count;
-+ first_match_pos.col =
-+ (colnr_T)STRLEN(ml_get(first_match_pos.lnum));
-+ }
-+ last_match_pos = first_match_pos;
-+ type = 0;
-+
-+ // Remember the first match so that the loop stops when we
-+ // wrap and come back there a second time.
-+ set_match_pos = TRUE;
-+ }
-+ else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
-+ && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
-+ {
-+ // Scan a buffer, but not the current one.
-+ if (ins_buf->b_ml.ml_mfp != NULL) // loaded buffer
-+ {
-+ compl_started = TRUE;
-+ first_match_pos.col = last_match_pos.col = 0;
-+ first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
-+ last_match_pos.lnum = 0;
-+ type = 0;
-+ }
-+ else // unloaded buffer, scan like dictionary
-+ {
-+ found_all = TRUE;
-+ if (ins_buf->b_fname == NULL)
-+ continue;
-+ type = CTRL_X_DICTIONARY;
-+ dict = ins_buf->b_fname;
-+ dict_f = DICT_EXACT;
-+ }
-+ vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
-+ ins_buf->b_fname == NULL
-+ ? buf_spname(ins_buf)
-+ : ins_buf->b_sfname == NULL
-+ ? ins_buf->b_fname
-+ : ins_buf->b_sfname);
-+ (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-+ }
-+ else if (*e_cpt == NUL)
-+ break;
-+ else
-+ {
-+ if (ctrl_x_mode_line_or_eval())
-+ type = -1;
-+ else if (*e_cpt == 'k' || *e_cpt == 's')
-+ {
-+ if (*e_cpt == 'k')
-+ type = CTRL_X_DICTIONARY;
-+ else
-+ type = CTRL_X_THESAURUS;
-+ if (*++e_cpt != ',' && *e_cpt != NUL)
-+ {
-+ dict = e_cpt;
-+ dict_f = DICT_FIRST;
-+ }
-+ }
-+ #ifdef FEAT_FIND_ID
-+ else if (*e_cpt == 'i')
-+ type = CTRL_X_PATH_PATTERNS;
-+ else if (*e_cpt == 'd')
-+ type = CTRL_X_PATH_DEFINES;
-+ #endif
-+ else if (*e_cpt == ']' || *e_cpt == 't')
-+ {
-+ type = CTRL_X_TAGS;
-+ vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags."));
-+ (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
-+ }
-+ else
-+ type = -1;
-+
-+ // in any case e_cpt is advanced to the next entry
-+ (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
-+
-+ found_all = TRUE;
-+ if (type == -1)
-+ continue;
-+ }
-+ }
-+
-+ // If complete() was called then compl_pattern has been reset. The
-+ // following won't work then, bail out.
-+ if (compl_pattern == NULL)
-+ break;
-+
-+ switch (type)
-+ {
-+ case -1:
-+ break;
-+ #ifdef FEAT_FIND_ID
-+ case CTRL_X_PATH_PATTERNS:
-+ case CTRL_X_PATH_DEFINES:
-+ find_pattern_in_path(compl_pattern, compl_direction,
-+ (int)STRLEN(compl_pattern), FALSE, FALSE,
-+ (type == CTRL_X_PATH_DEFINES
-+ && !(compl_cont_status & CONT_SOL))
-+ ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
-+ (linenr_T)1, (linenr_T)MAXLNUM);
-+ break;
-+ #endif
-+
-+ case CTRL_X_DICTIONARY:
-+ case CTRL_X_THESAURUS:
-+ ins_compl_dictionaries(
-+ dict != NULL ? dict
-+ : (type == CTRL_X_THESAURUS
-+ ? (*curbuf->b_p_tsr == NUL
-+ ? p_tsr
-+ : curbuf->b_p_tsr)
-+ : (*curbuf->b_p_dict == NUL
-+ ? p_dict
-+ : curbuf->b_p_dict)),
-+ compl_pattern,
-+ dict != NULL ? dict_f
-+ : 0, type == CTRL_X_THESAURUS);
-+ dict = NULL;
-+ break;
-+
-+ case CTRL_X_TAGS:
-+ // set p_ic according to p_ic, p_scs and pat for find_tags().
-+ save_p_ic = p_ic;
-+ p_ic = ignorecase(compl_pattern);
-+
-+ // Find up to TAG_MANY matches. Avoids that an enormous number
-+ // of matches is found when compl_pattern is empty
-+ if (find_tags(compl_pattern, &num_matches, &matches,
-+ TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
-+ | (ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
-+ TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
-+ {
-+ ins_compl_add_matches(num_matches, matches, p_ic);
-+ }
-+ p_ic = save_p_ic;
-+ break;
-+
-+ case CTRL_X_FILES:
-+ if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
-+ EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
-+ {
-+
-+ // May change home directory back to "~".
-+ tilde_replace(compl_pattern, num_matches, matches);
-+ ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
-+ }
-+ break;
-+
-+ case CTRL_X_CMDLINE:
-+ if (expand_cmdline(&compl_xp, compl_pattern,
-+ (int)STRLEN(compl_pattern),
-+ &num_matches, &matches) == EXPAND_OK)
-+ ins_compl_add_matches(num_matches, matches, FALSE);
-+ break;
-+
-+ #ifdef FEAT_COMPL_FUNC
-+ case CTRL_X_FUNCTION:
-+ case CTRL_X_OMNI:
-+ expand_by_function(type, compl_pattern);
-+ break;
-+ #endif
-+
-+ case CTRL_X_SPELL:
-+ #ifdef FEAT_SPELL
-+ num_matches = expand_spelling(first_match_pos.lnum,
-+ compl_pattern, &matches);
-+ if (num_matches > 0)
-+ ins_compl_add_matches(num_matches, matches, p_ic);
-+ #endif
-+ break;
-+
-+ default: // normal ^P/^N and ^X^L
-+ // If 'infercase' is set, don't use 'smartcase' here
-+ save_p_scs = p_scs;
-+ if (ins_buf->b_p_inf)
-+ p_scs = FALSE;
-+
-+ // Buffers other than curbuf are scanned from the beginning or the
-+ // end but never from the middle, thus setting nowrapscan in this
-+ // buffers is a good idea, on the other hand, we always set
-+ // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
-+ save_p_ws = p_ws;
-+ if (ins_buf != curbuf)
-+ p_ws = FALSE;
-+ else if (*e_cpt == '.')
-+ p_ws = TRUE;
-+ for (;;)
-+ {
-+ int flags = 0;
-+
-+ ++msg_silent; // Don't want messages for wrapscan.
-+
-+ // ctrl_x_mode_line_or_eval() || word-wise search that
-+ // has added a word that was at the beginning of the line
-+ if (ctrl_x_mode_line_or_eval()
-+ || (compl_cont_status & CONT_SOL))
-+ found_new_match = search_for_exact_line(ins_buf, pos,
-+ compl_direction, compl_pattern);
-+ else
-+ found_new_match = searchit(NULL, ins_buf, pos, NULL,
-+ compl_direction,
-+ compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
-+ RE_LAST, (linenr_T)0, NULL, NULL);
-+ --msg_silent;
-+ if (!compl_started || set_match_pos)
-+ {
-+ // set "compl_started" even on fail
-+ compl_started = TRUE;
-+ first_match_pos = *pos;
-+ last_match_pos = *pos;
-+ set_match_pos = FALSE;
-+ }
-+ else if (first_match_pos.lnum == last_match_pos.lnum
-+ && first_match_pos.col == last_match_pos.col)
-+ found_new_match = FAIL;
-+ if (found_new_match == FAIL)
-+ {
-+ if (ins_buf == curbuf)
-+ found_all = TRUE;
-+ break;
-+ }
-+
-+ // when ADDING, the text before the cursor matches, skip it
-+ if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf
-+ && ini->lnum == pos->lnum
-+ && ini->col == pos->col)
-+ continue;
-+ ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
-+ if (ctrl_x_mode_line_or_eval())
-+ {
-+ if (compl_cont_status & CONT_ADDING)
-+ {
-+ if (pos->lnum >= ins_buf->b_ml.ml_line_count)
-+ continue;
-+ ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
-+ if (!p_paste)
-+ ptr = skipwhite(ptr);
-+ }
-+ len = (int)STRLEN(ptr);
-+ }
-+ else
-+ {
-+ char_u *tmp_ptr = ptr;
-+
-+ if (compl_cont_status & CONT_ADDING)
-+ {
-+ tmp_ptr += compl_length;
-+ // Skip if already inside a word.
-+ if (vim_iswordp(tmp_ptr))
-+ continue;
-+ // Find start of next word.
-+ tmp_ptr = find_word_start(tmp_ptr);
-+ }
-+ // Find end of this word.
-+ tmp_ptr = find_word_end(tmp_ptr);
-+ len = (int)(tmp_ptr - ptr);
-+
-+ if ((compl_cont_status & CONT_ADDING)
-+ && len == compl_length)
-+ {
-+ if (pos->lnum < ins_buf->b_ml.ml_line_count)
-+ {
-+ // Try next line, if any. the new word will be
-+ // "join" as if the normal command "J" was used.
-+ // IOSIZE is always greater than
-+ // compl_length, so the next STRNCPY always
-+ // works -- Acevedo
-+ STRNCPY(IObuff, ptr, len);
-+ ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
-+ tmp_ptr = ptr = skipwhite(ptr);
-+ // Find start of next word.
-+ tmp_ptr = find_word_start(tmp_ptr);
-+ // Find end of next word.
-+ tmp_ptr = find_word_end(tmp_ptr);
-+ if (tmp_ptr > ptr)
-+ {
-+ if (*ptr != ')' && IObuff[len - 1] != TAB)
-+ {
-+ if (IObuff[len - 1] != ' ')
-+ IObuff[len++] = ' ';
-+ // IObuf =~ "\k.* ", thus len >= 2
-+ if (p_js
-+ && (IObuff[len - 2] == '.'
-+ || (vim_strchr(p_cpo, CPO_JOINSP)
-+ == NULL
-+ && (IObuff[len - 2] == '?'
-+ || IObuff[len - 2] == '!'))))
-+ IObuff[len++] = ' ';
-+ }
-+ // copy as much as possible of the new word
-+ if (tmp_ptr - ptr >= IOSIZE - len)
-+ tmp_ptr = ptr + IOSIZE - len - 1;
-+ STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
-+ len += (int)(tmp_ptr - ptr);
-+ flags |= CONT_S_IPOS;
-+ }
-+ IObuff[len] = NUL;
-+ ptr = IObuff;
-+ }
-+ if (len == compl_length)
-+ continue;
-+ }
-+ }
-+ if (ins_compl_add_infercase(ptr, len, p_ic,
-+ ins_buf == curbuf ? NULL : ins_buf->b_sfname,
-+ 0, flags) != NOTDONE)
-+ {
-+ found_new_match = OK;
-+ break;
-+ }
-+ }
-+ p_scs = save_p_scs;
-+ p_ws = save_p_ws;
-+ }
-+
-+ // check if compl_curr_match has changed, (e.g. other type of
-+ // expansion added something)
-+ if (type != 0 && compl_curr_match != compl_old_match)
-+ found_new_match = OK;
-+
-+ // break the loop for specialized modes (use 'complete' just for the
-+ // generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new
-+ // match
-+ if ((ctrl_x_mode != CTRL_X_NORMAL
-+ && !ctrl_x_mode_line_or_eval()) || found_new_match != FAIL)
-+ {
-+ if (got_int)
-+ break;
-+ // Fill the popup menu as soon as possible.
-+ if (type != -1)
-+ ins_compl_check_keys(0, FALSE);
-+
-+ if ((ctrl_x_mode != CTRL_X_NORMAL
-+ && !ctrl_x_mode_line_or_eval()) || compl_interrupted)
-+ break;
-+ compl_started = TRUE;
-+ }
-+ else
-+ {
-+ // Mark a buffer scanned when it has been scanned completely
-+ if (type == 0 || type == CTRL_X_PATH_PATTERNS)
-+ ins_buf->b_scanned = TRUE;
-+
-+ compl_started = FALSE;
-+ }
-+ }
-+ compl_started = TRUE;
-+
-+ if ((ctrl_x_mode == CTRL_X_NORMAL || ctrl_x_mode_line_or_eval())
-+ && *e_cpt == NUL) // Got to end of 'complete'
-+ found_new_match = FAIL;
-+
-+ i = -1; // total of matches, unknown
-+ if (found_new_match == FAIL || (ctrl_x_mode != CTRL_X_NORMAL
-+ && !ctrl_x_mode_line_or_eval()))
-+ i = ins_compl_make_cyclic();
-+
-+ if (compl_old_match != NULL)
-+ {
-+ // If several matches were added (FORWARD) or the search failed and has
-+ // just been made cyclic then we have to move compl_curr_match to the
-+ // next or previous entry (if any) -- Acevedo
-+ compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next
-+ : compl_old_match->cp_prev;
-+ if (compl_curr_match == NULL)
-+ compl_curr_match = compl_old_match;
-+ }
-+ return i;
-+ }
-+
-+ /*
-+ * Delete the old text being completed.
-+ */
-+ void
-+ ins_compl_delete(void)
-+ {
-+ int col;
-+
-+ // In insert mode: Delete the typed part.
-+ // In replace mode: Put the old characters back, if any.
-+ col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
-+ if ((int)curwin->w_cursor.col > col)
-+ {
-+ if (stop_arrow() == FAIL)
-+ return;
-+ backspace_until_column(col);
-+ }
-+
-+ // TODO: is this sufficient for redrawing? Redrawing everything causes
-+ // flicker, thus we can't do that.
-+ changed_cline_bef_curs();
-+ // clear v:completed_item
-+ set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
-+ }
-+
-+ /*
-+ * Insert the new text being completed.
-+ * "in_compl_func" is TRUE when called from complete_check().
-+ */
-+ void
-+ ins_compl_insert(int in_compl_func)
-+ {
-+ dict_T *dict;
-+
-+ ins_bytes(compl_shown_match->cp_str + ins_compl_len());
-+ if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
-+ compl_used_match = FALSE;
-+ else
-+ compl_used_match = TRUE;
-+
-+ // Set completed item.
-+ // { word, abbr, menu, kind, info }
-+ dict = dict_alloc_lock(VAR_FIXED);
-+ if (dict != NULL)
-+ {
-+ dict_add_string(dict, "word", compl_shown_match->cp_str);
-+ dict_add_string(dict, "abbr", compl_shown_match->cp_text[CPT_ABBR]);
-+ dict_add_string(dict, "menu", compl_shown_match->cp_text[CPT_MENU]);
-+ dict_add_string(dict, "kind", compl_shown_match->cp_text[CPT_KIND]);
-+ dict_add_string(dict, "info", compl_shown_match->cp_text[CPT_INFO]);
-+ dict_add_string(dict, "user_data",
-+ compl_shown_match->cp_text[CPT_USER_DATA]);
-+ }
-+ set_vim_var_dict(VV_COMPLETED_ITEM, dict);
-+ if (!in_compl_func)
-+ compl_curr_match = compl_shown_match;
-+ }
-+
-+ /*
-+ * Fill in the next completion in the current direction.
-+ * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to
-+ * get more completions. If it is FALSE, then we just do nothing when there
-+ * are no more completions in a given direction. The latter case is used when
-+ * we are still in the middle of finding completions, to allow browsing
-+ * through the ones found so far.
-+ * Return the total number of matches, or -1 if still unknown -- webb.
-+ *
-+ * compl_curr_match is currently being used by ins_compl_get_exp(), so we use
-+ * compl_shown_match here.
-+ *
-+ * Note that this function may be called recursively once only. First with
-+ * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn
-+ * calls this function with "allow_get_expansion" FALSE.
-+ */
-+ static int
-+ ins_compl_next(
-+ int allow_get_expansion,
-+ int count, // repeat completion this many times; should
-+ // be at least 1
-+ int insert_match, // Insert the newly selected match
-+ int in_compl_func) // called from complete_check()
-+ {
-+ int num_matches = -1;
-+ int todo = count;
-+ compl_T *found_compl = NULL;
-+ int found_end = FALSE;
-+ int advance;
-+ int started = compl_started;
-+
-+ // When user complete function return -1 for findstart which is next
-+ // time of 'always', compl_shown_match become NULL.
-+ if (compl_shown_match == NULL)
-+ return -1;
-+
-+ if (compl_leader != NULL
-+ && (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0)
-+ {
-+ // Set "compl_shown_match" to the actually shown match, it may differ
-+ // when "compl_leader" is used to omit some of the matches.
-+ while (!ins_compl_equal(compl_shown_match,
-+ compl_leader, (int)STRLEN(compl_leader))
-+ && compl_shown_match->cp_next != NULL
-+ && compl_shown_match->cp_next != compl_first_match)
-+ compl_shown_match = compl_shown_match->cp_next;
-+
-+ // If we didn't find it searching forward, and compl_shows_dir is
-+ // backward, find the last match.
-+ if (compl_shows_dir == BACKWARD
-+ && !ins_compl_equal(compl_shown_match,
-+ compl_leader, (int)STRLEN(compl_leader))
-+ && (compl_shown_match->cp_next == NULL
-+ || compl_shown_match->cp_next == compl_first_match))
-+ {
-+ while (!ins_compl_equal(compl_shown_match,
-+ compl_leader, (int)STRLEN(compl_leader))
-+ && compl_shown_match->cp_prev != NULL
-+ && compl_shown_match->cp_prev != compl_first_match)
-+ compl_shown_match = compl_shown_match->cp_prev;
-+ }
-+ }
-+
-+ if (allow_get_expansion && insert_match
-+ && (!(compl_get_longest || compl_restarting) || compl_used_match))
-+ // Delete old text to be replaced
-+ ins_compl_delete();
-+
-+ // When finding the longest common text we stick at the original text,
-+ // don't let CTRL-N or CTRL-P move to the first match.
-+ advance = count != 1 || !allow_get_expansion || !compl_get_longest;
-+
-+ // When restarting the search don't insert the first match either.
-+ if (compl_restarting)
-+ {
-+ advance = FALSE;
-+ compl_restarting = FALSE;
-+ }
-+
-+ // Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
-+ // around.
-+ while (--todo >= 0)
-+ {
-+ if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL)
-+ {
-+ compl_shown_match = compl_shown_match->cp_next;
-+ found_end = (compl_first_match != NULL
-+ && (compl_shown_match->cp_next == compl_first_match
-+ || compl_shown_match == compl_first_match));
-+ }
-+ else if (compl_shows_dir == BACKWARD
-+ && compl_shown_match->cp_prev != NULL)
-+ {
-+ found_end = (compl_shown_match == compl_first_match);
-+ compl_shown_match = compl_shown_match->cp_prev;
-+ found_end |= (compl_shown_match == compl_first_match);
-+ }
-+ else
-+ {
-+ if (!allow_get_expansion)
-+ {
-+ if (advance)
-+ {
-+ if (compl_shows_dir == BACKWARD)
-+ compl_pending -= todo + 1;
-+ else
-+ compl_pending += todo + 1;
-+ }
-+ return -1;
-+ }
-+
-+ if (!compl_no_select && advance)
-+ {
-+ if (compl_shows_dir == BACKWARD)
-+ --compl_pending;
-+ else
-+ ++compl_pending;
-+ }
-+
-+ // Find matches.
-+ num_matches = ins_compl_get_exp(&compl_startpos);
-+
-+ // handle any pending completions
-+ while (compl_pending != 0 && compl_direction == compl_shows_dir
-+ && advance)
-+ {
-+ if (compl_pending > 0 && compl_shown_match->cp_next != NULL)
-+ {
-+ compl_shown_match = compl_shown_match->cp_next;
-+ --compl_pending;
-+ }
-+ if (compl_pending < 0 && compl_shown_match->cp_prev != NULL)
-+ {
-+ compl_shown_match = compl_shown_match->cp_prev;
-+ ++compl_pending;
-+ }
-+ else
-+ break;
-+ }
-+ found_end = FALSE;
-+ }
-+ if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0
-+ && compl_leader != NULL
-+ && !ins_compl_equal(compl_shown_match,
-+ compl_leader, (int)STRLEN(compl_leader)))
-+ ++todo;
-+ else
-+ // Remember a matching item.
-+ found_compl = compl_shown_match;
-+
-+ // Stop at the end of the list when we found a usable match.
-+ if (found_end)
-+ {
-+ if (found_compl != NULL)
-+ {
-+ compl_shown_match = found_compl;
-+ break;
-+ }
-+ todo = 1; // use first usable match after wrapping around
-+ }
-+ }
-+
-+ // Insert the text of the new completion, or the compl_leader.
-+ if (compl_no_insert && !started)
-+ {
-+ ins_bytes(compl_orig_text + ins_compl_len());
-+ compl_used_match = FALSE;
-+ }
-+ else if (insert_match)
-+ {
-+ if (!compl_get_longest || compl_used_match)
-+ ins_compl_insert(in_compl_func);
-+ else
-+ ins_bytes(compl_leader + ins_compl_len());
-+ }
-+ else
-+ compl_used_match = FALSE;
-+
-+ if (!allow_get_expansion)
-+ {
-+ // may undisplay the popup menu first
-+ ins_compl_upd_pum();
-+
-+ if (pum_enough_matches())
-+ // Will display the popup menu, don't redraw yet to avoid flicker.
-+ pum_call_update_screen();
-+ else
-+ // Not showing the popup menu yet, redraw to show the user what was
-+ // inserted.
-+ update_screen(0);
-+
-+ // display the updated popup menu
-+ ins_compl_show_pum();
-+ #ifdef FEAT_GUI
-+ if (gui.in_use)
-+ {
-+ // Show the cursor after the match, not after the redrawn text.
-+ setcursor();
-+ out_flush_cursor(FALSE, FALSE);
-+ }
-+ #endif
-+
-+ // Delete old text to be replaced, since we're still searching and
-+ // don't want to match ourselves!
-+ ins_compl_delete();
-+ }
-+
-+ // Enter will select a match when the match wasn't inserted and the popup
-+ // menu is visible.
-+ if (compl_no_insert && !started)
-+ compl_enter_selects = TRUE;
-+ else
-+ compl_enter_selects = !insert_match && compl_match_array != NULL;
-+
-+ // Show the file name for the match (if any)
-+ // Truncate the file name to avoid a wait for return.
-+ if (compl_shown_match->cp_fname != NULL)
-+ {
-+ char *lead = _("match in file");
-+ int space = sc_col - vim_strsize((char_u *)lead) - 2;
-+ char_u *s;
-+ char_u *e;
-+
-+ if (space > 0)
-+ {
-+ // We need the tail that fits. With double-byte encoding going
-+ // back from the end is very slow, thus go from the start and keep
-+ // the text that fits in "space" between "s" and "e".
-+ for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e))
-+ {
-+ space -= ptr2cells(e);
-+ while (space < 0)
-+ {
-+ space += ptr2cells(s);
-+ MB_PTR_ADV(s);
-+ }
-+ }
-+ vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
-+ s > compl_shown_match->cp_fname ? "<" : "", s);
-+ msg((char *)IObuff);
-+ redraw_cmdline = FALSE; // don't overwrite!
-+ }
-+ }
-+
-+ return num_matches;
-+ }
-+
-+ /*
-+ * Call this while finding completions, to check whether the user has hit a key
-+ * that should change the currently displayed completion, or exit completion
-+ * mode. Also, when compl_pending is not zero, show a completion as soon as
-+ * possible. -- webb
-+ * "frequency" specifies out of how many calls we actually check.
-+ * "in_compl_func" is TRUE when called from complete_check(), don't set
-+ * compl_curr_match.
-+ */
-+ void
-+ ins_compl_check_keys(int frequency, int in_compl_func)
-+ {
-+ static int count = 0;
-+ int c;
-+
-+ // Don't check when reading keys from a script, :normal or feedkeys().
-+ // That would break the test scripts. But do check for keys when called
-+ // from complete_check().
-+ if (!in_compl_func && (using_script() || ex_normal_busy))
-+ return;
-+
-+ // Only do this at regular intervals
-+ if (++count < frequency)
-+ return;
-+ count = 0;
-+
-+ // Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key()
-+ // can't do its work correctly.
-+ c = vpeekc_any();
-+ if (c != NUL)
-+ {
-+ if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
-+ {
-+ c = safe_vgetc(); // Eat the character
-+ compl_shows_dir = ins_compl_key2dir(c);
-+ (void)ins_compl_next(FALSE, ins_compl_key2count(c),
-+ c != K_UP && c != K_DOWN, in_compl_func);
-+ }
-+ else
-+ {
-+ // Need to get the character to have KeyTyped set. We'll put it
-+ // back with vungetc() below. But skip K_IGNORE.
-+ c = safe_vgetc();
-+ if (c != K_IGNORE)
-+ {
-+ // Don't interrupt completion when the character wasn't typed,
-+ // e.g., when doing @q to replay keys.
-+ if (c != Ctrl_R && KeyTyped)
-+ compl_interrupted = TRUE;
-+
-+ vungetc(c);
-+ }
-+ }
-+ }
-+ if (compl_pending != 0 && !got_int && !compl_no_insert)
-+ {
-+ int todo = compl_pending > 0 ? compl_pending : -compl_pending;
-+
-+ compl_pending = 0;
-+ (void)ins_compl_next(FALSE, todo, TRUE, in_compl_func);
-+ }
-+ }
-+
-+ /*
-+ * Decide the direction of Insert mode complete from the key typed.
-+ * Returns BACKWARD or FORWARD.
-+ */
-+ static int
-+ ins_compl_key2dir(int c)
-+ {
-+ if (c == Ctrl_P || c == Ctrl_L
-+ || c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP || c == K_UP)
-+ return BACKWARD;
-+ return FORWARD;
-+ }
-+
-+ /*
-+ * Return TRUE for keys that are used for completion only when the popup menu
-+ * is visible.
-+ */
-+ static int
-+ ins_compl_pum_key(int c)
-+ {
-+ return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
-+ || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN
-+ || c == K_UP || c == K_DOWN);
-+ }
-+
-+ /*
-+ * Decide the number of completions to move forward.
-+ * Returns 1 for most keys, height of the popup menu for page-up/down keys.
-+ */
-+ static int
-+ ins_compl_key2count(int c)
-+ {
-+ int h;
-+
-+ if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN)
-+ {
-+ h = pum_get_height();
-+ if (h > 3)
-+ h -= 2; // keep some context
-+ return h;
-+ }
-+ return 1;
-+ }
-+
-+ /*
-+ * Return TRUE if completion with "c" should insert the match, FALSE if only
-+ * to change the currently selected completion.
-+ */
-+ static int
-+ ins_compl_use_match(int c)
-+ {
-+ switch (c)
-+ {
-+ case K_UP:
-+ case K_DOWN:
-+ case K_PAGEDOWN:
-+ case K_KPAGEDOWN:
-+ case K_S_DOWN:
-+ case K_PAGEUP:
-+ case K_KPAGEUP:
-+ case K_S_UP:
-+ return FALSE;
-+ }
-+ return TRUE;
-+ }
-+
-+ /*
-+ * Do Insert mode completion.
-+ * Called when character "c" was typed, which has a meaning for completion.
-+ * Returns OK if completion was done, FAIL if something failed (out of mem).
-+ */
-+ int
-+ ins_complete(int c, int enable_pum)
-+ {
-+ char_u *line;
-+ int startcol = 0; // column where searched text starts
-+ colnr_T curs_col; // cursor column
-+ int n;
-+ int save_w_wrow;
-+ int save_w_leftcol;
-+ int insert_match;
-+ int save_did_ai = did_ai;
-+
-+ compl_direction = ins_compl_key2dir(c);
-+ insert_match = ins_compl_use_match(c);
-+
-+ if (!compl_started)
-+ {
-+ // First time we hit ^N or ^P (in a row, I mean)
-+
-+ did_ai = FALSE;
-+ #ifdef FEAT_SMARTINDENT
-+ did_si = FALSE;
-+ can_si = FALSE;
-+ can_si_back = FALSE;
-+ #endif
-+ if (stop_arrow() == FAIL)
-+ return FAIL;
-+
-+ line = ml_get(curwin->w_cursor.lnum);
-+ curs_col = curwin->w_cursor.col;
-+ compl_pending = 0;
-+
-+ // If this same ctrl_x_mode has been interrupted use the text from
-+ // "compl_startpos" to the cursor as a pattern to add a new word
-+ // instead of expand the one before the cursor, in word-wise if
-+ // "compl_startpos" is not in the same line as the cursor then fix it
-+ // (the line has been split because it was longer than 'tw'). if SOL
-+ // is set then skip the previous pattern, a word at the beginning of
-+ // the line has been inserted, we'll look for that -- Acevedo.
-+ if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
-+ && compl_cont_mode == ctrl_x_mode)
-+ {
-+ // it is a continued search
-+ compl_cont_status &= ~CONT_INTRPT; // remove INTRPT
-+ if (ctrl_x_mode == CTRL_X_NORMAL
-+ || ctrl_x_mode == CTRL_X_PATH_PATTERNS
-+ || ctrl_x_mode == CTRL_X_PATH_DEFINES)
-+ {
-+ if (compl_startpos.lnum != curwin->w_cursor.lnum)
-+ {
-+ // line (probably) wrapped, set compl_startpos to the
-+ // first non_blank in the line, if it is not a wordchar
-+ // include it to get a better pattern, but then we don't
-+ // want the "\\<" prefix, check it bellow
-+ compl_col = (colnr_T)getwhitecols(line);
-+ compl_startpos.col = compl_col;
-+ compl_startpos.lnum = curwin->w_cursor.lnum;
-+ compl_cont_status &= ~CONT_SOL; // clear SOL if present
-+ }
-+ else
-+ {
-+ // S_IPOS was set when we inserted a word that was at the
-+ // beginning of the line, which means that we'll go to SOL
-+ // mode but first we need to redefine compl_startpos
-+ if (compl_cont_status & CONT_S_IPOS)
-+ {
-+ compl_cont_status |= CONT_SOL;
-+ compl_startpos.col = (colnr_T)(skipwhite(
-+ line + compl_length
-+ + compl_startpos.col) - line);
-+ }
-+ compl_col = compl_startpos.col;
-+ }
-+ compl_length = curwin->w_cursor.col - (int)compl_col;
-+ // IObuff is used to add a "word from the next line" would we
-+ // have enough space? just being paranoid
-+ #define MIN_SPACE 75
-+ if (compl_length > (IOSIZE - MIN_SPACE))
-+ {
-+ compl_cont_status &= ~CONT_SOL;
-+ compl_length = (IOSIZE - MIN_SPACE);
-+ compl_col = curwin->w_cursor.col - compl_length;
-+ }
-+ compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
-+ if (compl_length < 1)
-+ compl_cont_status &= CONT_LOCAL;
-+ }
-+ else if (ctrl_x_mode_line_or_eval())
-+ compl_cont_status = CONT_ADDING | CONT_N_ADDS;
-+ else
-+ compl_cont_status = 0;
-+ }
-+ else
-+ compl_cont_status &= CONT_LOCAL;
-+
-+ if (!(compl_cont_status & CONT_ADDING)) // normal expansion
-+ {
-+ compl_cont_mode = ctrl_x_mode;
-+ if (ctrl_x_mode != CTRL_X_NORMAL)
-+ // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
-+ compl_cont_status = 0;
-+ compl_cont_status |= CONT_N_ADDS;
-+ compl_startpos = curwin->w_cursor;
-+ startcol = (int)curs_col;
-+ compl_col = 0;
-+ }
-+
-+ // Work out completion pattern and original text -- webb
-+ if (ctrl_x_mode == CTRL_X_NORMAL || (ctrl_x_mode & CTRL_X_WANT_IDENT))
-+ {
-+ if ((compl_cont_status & CONT_SOL)
-+ || ctrl_x_mode == CTRL_X_PATH_DEFINES)
-+ {
-+ if (!(compl_cont_status & CONT_ADDING))
-+ {
-+ while (--startcol >= 0 && vim_isIDc(line[startcol]))
-+ ;
-+ compl_col += ++startcol;
-+ compl_length = curs_col - startcol;
-+ }
-+ if (p_ic)
-+ compl_pattern = str_foldcase(line + compl_col,
-+ compl_length, NULL, 0);
-+ else
-+ compl_pattern = vim_strnsave(line + compl_col,
-+ compl_length);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ }
-+ else if (compl_cont_status & CONT_ADDING)
-+ {
-+ char_u *prefix = (char_u *)"\\<";
-+
-+ // we need up to 2 extra chars for the prefix
-+ compl_pattern = alloc(quote_meta(NULL, line + compl_col,
-+ compl_length) + 2);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ if (!vim_iswordp(line + compl_col)
-+ || (compl_col > 0
-+ && (vim_iswordp(mb_prevptr(line, line + compl_col)))))
-+ prefix = (char_u *)"";
-+ STRCPY((char *)compl_pattern, prefix);
-+ (void)quote_meta(compl_pattern + STRLEN(prefix),
-+ line + compl_col, compl_length);
-+ }
-+ else if (--startcol < 0
-+ || !vim_iswordp(mb_prevptr(line, line + startcol + 1)))
-+ {
-+ // Match any word of at least two chars
-+ compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ compl_col += curs_col;
-+ compl_length = 0;
-+ }
-+ else
-+ {
-+ // Search the point of change class of multibyte character
-+ // or not a word single byte character backward.
-+ if (has_mbyte)
-+ {
-+ int base_class;
-+ int head_off;
-+
-+ startcol -= (*mb_head_off)(line, line + startcol);
-+ base_class = mb_get_class(line + startcol);
-+ while (--startcol >= 0)
-+ {
-+ head_off = (*mb_head_off)(line, line + startcol);
-+ if (base_class != mb_get_class(line + startcol
-+ - head_off))
-+ break;
-+ startcol -= head_off;
-+ }
-+ }
-+ else
-+ while (--startcol >= 0 && vim_iswordc(line[startcol]))
-+ ;
-+ compl_col += ++startcol;
-+ compl_length = (int)curs_col - startcol;
-+ if (compl_length == 1)
-+ {
-+ // Only match word with at least two chars -- webb
-+ // there's no need to call quote_meta,
-+ // alloc(7) is enough -- Acevedo
-+ compl_pattern = alloc(7);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ STRCPY((char *)compl_pattern, "\\<");
-+ (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
-+ STRCAT((char *)compl_pattern, "\\k");
-+ }
-+ else
-+ {
-+ compl_pattern = alloc(quote_meta(NULL, line + compl_col,
-+ compl_length) + 2);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ STRCPY((char *)compl_pattern, "\\<");
-+ (void)quote_meta(compl_pattern + 2, line + compl_col,
-+ compl_length);
-+ }
-+ }
-+ }
-+ else if (ctrl_x_mode_line_or_eval())
-+ {
-+ compl_col = (colnr_T)getwhitecols(line);
-+ compl_length = (int)curs_col - (int)compl_col;
-+ if (compl_length < 0) // cursor in indent: empty pattern
-+ compl_length = 0;
-+ if (p_ic)
-+ compl_pattern = str_foldcase(line + compl_col, compl_length,
-+ NULL, 0);
-+ else
-+ compl_pattern = vim_strnsave(line + compl_col, compl_length);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ }
-+ else if (ctrl_x_mode == CTRL_X_FILES)
-+ {
-+ // Go back to just before the first filename character.
-+ if (startcol > 0)
-+ {
-+ char_u *p = line + startcol;
-+
-+ MB_PTR_BACK(line, p);
-+ while (p > line && vim_isfilec(PTR2CHAR(p)))
-+ MB_PTR_BACK(line, p);
-+ if (p == line && vim_isfilec(PTR2CHAR(p)))
-+ startcol = 0;
-+ else
-+ startcol = (int)(p - line) + 1;
-+ }
-+
-+ compl_col += startcol;
-+ compl_length = (int)curs_col - startcol;
-+ compl_pattern = addstar(line + compl_col, compl_length,
-+ EXPAND_FILES);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ }
-+ else if (ctrl_x_mode == CTRL_X_CMDLINE)
-+ {
-+ compl_pattern = vim_strnsave(line, curs_col);
-+ if (compl_pattern == NULL)
-+ return FAIL;
-+ set_cmd_context(&compl_xp, compl_pattern,
-+ (int)STRLEN(compl_pattern), curs_col, FALSE);
-+ if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
-+ || compl_xp.xp_context == EXPAND_NOTHING)
-+ // No completion possible, use an empty pattern to get a
-+ // "pattern not found" message.
-+ compl_col = curs_col;
-+ else
-+ compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
-+ compl_length = curs_col - compl_col;
-+ }
-+ else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
-+ {
-+ #ifdef FEAT_COMPL_FUNC
-+ // Call user defined function 'completefunc' with "a:findstart"
-+ // set to 1 to obtain the length of text to use for completion.
-+ typval_T args[3];
-+ int col;
-+ char_u *funcname;
-+ pos_T pos;
-+ win_T *curwin_save;
-+ buf_T *curbuf_save;
-+ int save_State = State;
-+
-+ // Call 'completefunc' or 'omnifunc' and get pattern length as a
-+ // string
-+ funcname = ctrl_x_mode == CTRL_X_FUNCTION
-+ ? curbuf->b_p_cfu : curbuf->b_p_ofu;
-+ if (*funcname == NUL)
-+ {
-+ semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION
-+ ? "completefunc" : "omnifunc");
-+ // restore did_ai, so that adding comment leader works
-+ did_ai = save_did_ai;
-+ return FAIL;
-+ }
-+
-+ args[0].v_type = VAR_NUMBER;
-+ args[0].vval.v_number = 1;
-+ args[1].v_type = VAR_STRING;
-+ args[1].vval.v_string = (char_u *)"";
-+ args[2].v_type = VAR_UNKNOWN;
-+ pos = curwin->w_cursor;
-+ curwin_save = curwin;
-+ curbuf_save = curbuf;
-+ col = call_func_retnr(funcname, 2, args);
-+
-+ State = save_State;
-+ if (curwin_save != curwin || curbuf_save != curbuf)
-+ {
-+ emsg(_(e_complwin));
-+ return FAIL;
-+ }
-+ curwin->w_cursor = pos; // restore the cursor position
-+ validate_cursor();
-+ if (!EQUAL_POS(curwin->w_cursor, pos))
-+ {
-+ emsg(_(e_compldel));
-+ return FAIL;
-+ }
-+
-+ // Return value -2 means the user complete function wants to
-+ // cancel the complete without an error.
-+ // Return value -3 does the same as -2 and leaves CTRL-X mode.
-+ if (col == -2)
-+ return FAIL;
-+ if (col == -3)
-+ {
-+ ctrl_x_mode = CTRL_X_NORMAL;
-+ edit_submode = NULL;
-+ if (!shortmess(SHM_COMPLETIONMENU))
-+ msg_clr_cmdline();
-+ return FAIL;
-+ }
-+
-+ // Reset extended parameters of completion, when start new
-+ // completion.
-+ compl_opt_refresh_always = FALSE;
-+ compl_opt_suppress_empty = FALSE;
-+
-+ if (col < 0)
-+ col = curs_col;
-+ compl_col = col;
-+ if (compl_col > curs_col)
-+ compl_col = curs_col;
-+
-+ // Setup variables for completion. Need to obtain "line" again,
-+ // it may have become invalid.
-+ line = ml_get(curwin->w_cursor.lnum);
-+ compl_length = curs_col - compl_col;
-+ compl_pattern = vim_strnsave(line + compl_col, compl_length);
-+ if (compl_pattern == NULL)
-+ #endif
-+ return FAIL;
-+ }
-+ else if (ctrl_x_mode == CTRL_X_SPELL)
-+ {
-+ #ifdef FEAT_SPELL
-+ if (spell_bad_len > 0)
-+ compl_col = curs_col - spell_bad_len;
-+ else
-+ compl_col = spell_word_start(startcol);
-+ if (compl_col >= (colnr_T)startcol)
-+ {
-+ compl_length = 0;
-+ compl_col = curs_col;
-+ }
-+ else
-+ {
-+ spell_expand_check_cap(compl_col);
-+ compl_length = (int)curs_col - compl_col;
-+ }
-+ // Need to obtain "line" again, it may have become invalid.
-+ line = ml_get(curwin->w_cursor.lnum);
-+ compl_pattern = vim_strnsave(line + compl_col, compl_length);
-+ if (compl_pattern == NULL)
-+ #endif
-+ return FAIL;
-+ }
-+ else
-+ {
-+ internal_error("ins_complete()");
-+ return FAIL;
-+ }
-+
-+ if (compl_cont_status & CONT_ADDING)
-+ {
-+ edit_submode_pre = (char_u *)_(" Adding");
-+ if (ctrl_x_mode_line_or_eval())
-+ {
-+ // Insert a new line, keep indentation but ignore 'comments'
-+ #ifdef FEAT_COMMENTS
-+ char_u *old = curbuf->b_p_com;
-+
-+ curbuf->b_p_com = (char_u *)"";
-+ #endif
-+ compl_startpos.lnum = curwin->w_cursor.lnum;
-+ compl_startpos.col = compl_col;
-+ ins_eol('\r');
-+ #ifdef FEAT_COMMENTS
-+ curbuf->b_p_com = old;
-+ #endif
-+ compl_length = 0;
-+ compl_col = curwin->w_cursor.col;
-+ }
-+ }
-+ else
-+ {
-+ edit_submode_pre = NULL;
-+ compl_startpos.col = compl_col;
-+ }
-+
-+ if (compl_cont_status & CONT_LOCAL)
-+ edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
-+ else
-+ edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
-+
-+ // If any of the original typed text has been changed we need to fix
-+ // the redo buffer.
-+ ins_compl_fixRedoBufForLeader(NULL);
-+
-+ // Always add completion for the original text.
-+ vim_free(compl_orig_text);
-+ compl_orig_text = vim_strnsave(line + compl_col, compl_length);
-+ if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
-+ -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK)
-+ {
-+ VIM_CLEAR(compl_pattern);
-+ VIM_CLEAR(compl_orig_text);
-+ return FAIL;
-+ }
-+
-+ // showmode might reset the internal line pointers, so it must
-+ // be called before line = ml_get(), or when this address is no
-+ // longer needed. -- Acevedo.
-+ edit_submode_extra = (char_u *)_("-- Searching...");
-+ edit_submode_highl = HLF_COUNT;
-+ showmode();
-+ edit_submode_extra = NULL;
-+ out_flush();
-+ }
-+ else if (insert_match && stop_arrow() == FAIL)
-+ return FAIL;
-+
-+ compl_shown_match = compl_curr_match;
-+ compl_shows_dir = compl_direction;
-+
-+ // Find next match (and following matches).
-+ save_w_wrow = curwin->w_wrow;
-+ save_w_leftcol = curwin->w_leftcol;
-+ n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
-+
-+ // may undisplay the popup menu
-+ ins_compl_upd_pum();
-+
-+ if (n > 1) // all matches have been found
-+ compl_matches = n;
-+ compl_curr_match = compl_shown_match;
-+ compl_direction = compl_shows_dir;
-+
-+ // Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
-+ // mode.
-+ if (got_int && !global_busy)
-+ {
-+ (void)vgetc();
-+ got_int = FALSE;
-+ }
-+
-+ // we found no match if the list has only the "compl_orig_text"-entry
-+ if (compl_first_match == compl_first_match->cp_next)
-+ {
-+ edit_submode_extra = (compl_cont_status & CONT_ADDING)
-+ && compl_length > 1
-+ ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
-+ edit_submode_highl = HLF_E;
-+ // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
-+ // because we couldn't expand anything at first place, but if we used
-+ // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
-+ // (such as M in M'exico) if not tried already. -- Acevedo
-+ if ( compl_length > 1
-+ || (compl_cont_status & CONT_ADDING)
-+ || (ctrl_x_mode != CTRL_X_NORMAL
-+ && ctrl_x_mode != CTRL_X_PATH_PATTERNS
-+ && ctrl_x_mode != CTRL_X_PATH_DEFINES))
-+ compl_cont_status &= ~CONT_N_ADDS;
-+ }
-+
-+ if (compl_curr_match->cp_flags & CONT_S_IPOS)
-+ compl_cont_status |= CONT_S_IPOS;
-+ else
-+ compl_cont_status &= ~CONT_S_IPOS;
-+
-+ if (edit_submode_extra == NULL)
-+ {
-+ if (compl_curr_match->cp_flags & ORIGINAL_TEXT)
-+ {
-+ edit_submode_extra = (char_u *)_("Back at original");
-+ edit_submode_highl = HLF_W;
-+ }
-+ else if (compl_cont_status & CONT_S_IPOS)
-+ {
-+ edit_submode_extra = (char_u *)_("Word from other line");
-+ edit_submode_highl = HLF_COUNT;
-+ }
-+ else if (compl_curr_match->cp_next == compl_curr_match->cp_prev)
-+ {
-+ edit_submode_extra = (char_u *)_("The only match");
-+ edit_submode_highl = HLF_COUNT;
-+ }
-+ else
-+ {
-+ // Update completion sequence number when needed.
-+ if (compl_curr_match->cp_number == -1)
-+ {
-+ int number = 0;
-+ compl_T *match;
-+
-+ if (compl_direction == FORWARD)
-+ {
-+ // search backwards for the first valid (!= -1) number.
-+ // This should normally succeed already at the first loop
-+ // cycle, so it's fast!
-+ for (match = compl_curr_match->cp_prev; match != NULL
-+ && match != compl_first_match;
-+ match = match->cp_prev)
-+ if (match->cp_number != -1)
-+ {
-+ number = match->cp_number;
-+ break;
-+ }
-+ if (match != NULL)
-+ // go up and assign all numbers which are not assigned
-+ // yet
-+ for (match = match->cp_next;
-+ match != NULL && match->cp_number == -1;
-+ match = match->cp_next)
-+ match->cp_number = ++number;
-+ }
-+ else // BACKWARD
-+ {
-+ // search forwards (upwards) for the first valid (!= -1)
-+ // number. This should normally succeed already at the
-+ // first loop cycle, so it's fast!
-+ for (match = compl_curr_match->cp_next; match != NULL
-+ && match != compl_first_match;
-+ match = match->cp_next)
-+ if (match->cp_number != -1)
-+ {
-+ number = match->cp_number;
-+ break;
-+ }
-+ if (match != NULL)
-+ // go down and assign all numbers which are not
-+ // assigned yet
-+ for (match = match->cp_prev; match
-+ && match->cp_number == -1;
-+ match = match->cp_prev)
-+ match->cp_number = ++number;
-+ }
-+ }
-+
-+ // The match should always have a sequence number now, this is
-+ // just a safety check.
-+ if (compl_curr_match->cp_number != -1)
-+ {
-+ // Space for 10 text chars. + 2x10-digit no.s = 31.
-+ // Translations may need more than twice that.
-+ static char_u match_ref[81];
-+
-+ if (compl_matches > 0)
-+ vim_snprintf((char *)match_ref, sizeof(match_ref),
-+ _("match %d of %d"),
-+ compl_curr_match->cp_number, compl_matches);
-+ else
-+ vim_snprintf((char *)match_ref, sizeof(match_ref),
-+ _("match %d"),
-+ compl_curr_match->cp_number);
-+ edit_submode_extra = match_ref;
-+ edit_submode_highl = HLF_R;
-+ if (dollar_vcol >= 0)
-+ curs_columns(FALSE);
-+ }
-+ }
-+ }
-+
-+ // Show a message about what (completion) mode we're in.
-+ if (!compl_opt_suppress_empty)
-+ {
-+ showmode();
-+ if (!shortmess(SHM_COMPLETIONMENU))
-+ {
-+ if (edit_submode_extra != NULL)
-+ {
-+ if (!p_smd)
-+ msg_attr((char *)edit_submode_extra,
-+ edit_submode_highl < HLF_COUNT
-+ ? HL_ATTR(edit_submode_highl) : 0);
-+ }
-+ else
-+ msg_clr_cmdline(); // necessary for "noshowmode"
-+ }
-+ }
-+
-+ // Show the popup menu, unless we got interrupted.
-+ if (enable_pum && !compl_interrupted)
-+ show_pum(save_w_wrow, save_w_leftcol);
-+
-+ compl_was_interrupted = compl_interrupted;
-+ compl_interrupted = FALSE;
-+
-+ return OK;
-+ }
-+
-+ static void
-+ show_pum(int prev_w_wrow, int prev_w_leftcol)
-+ {
-+ // RedrawingDisabled may be set when invoked through complete().
-+ int n = RedrawingDisabled;
-+
-+ RedrawingDisabled = 0;
-+
-+ // If the cursor moved or the display scrolled we need to remove the pum
-+ // first.
-+ setcursor();
-+ if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol)
-+ ins_compl_del_pum();
-+
-+ ins_compl_show_pum();
-+ setcursor();
-+ RedrawingDisabled = n;
-+ }
-+
-+ /*
-+ * Looks in the first "len" chars. of "src" for search-metachars.
-+ * If dest is not NULL the chars. are copied there quoting (with
-+ * a backslash) the metachars, and dest would be NUL terminated.
-+ * Returns the length (needed) of dest
-+ */
-+ static unsigned
-+ quote_meta(char_u *dest, char_u *src, int len)
-+ {
-+ unsigned m = (unsigned)len + 1; // one extra for the NUL
-+
-+ for ( ; --len >= 0; src++)
-+ {
-+ switch (*src)
-+ {
-+ case '.':
-+ case '*':
-+ case '[':
-+ if (ctrl_x_mode == CTRL_X_DICTIONARY
-+ || ctrl_x_mode == CTRL_X_THESAURUS)
-+ break;
-+ // FALLTHROUGH
-+ case '~':
-+ if (!p_magic) // quote these only if magic is set
-+ break;
-+ // FALLTHROUGH
-+ case '\\':
-+ if (ctrl_x_mode == CTRL_X_DICTIONARY
-+ || ctrl_x_mode == CTRL_X_THESAURUS)
-+ break;
-+ // FALLTHROUGH
-+ case '^': // currently it's not needed.
-+ case '$':
-+ m++;
-+ if (dest != NULL)
-+ *dest++ = '\\';
-+ break;
-+ }
-+ if (dest != NULL)
-+ *dest++ = *src;
-+ // Copy remaining bytes of a multibyte character.
-+ if (has_mbyte)
-+ {
-+ int i, mb_len;
-+
-+ mb_len = (*mb_ptr2len)(src) - 1;
-+ if (mb_len > 0 && len >= mb_len)
-+ for (i = 0; i < mb_len; ++i)
-+ {
-+ --len;
-+ ++src;
-+ if (dest != NULL)
-+ *dest++ = *src;
-+ }
-+ }
-+ }
-+ if (dest != NULL)
-+ *dest = NUL;
-+
-+ return m;
-+ }
-+
-+ # if defined(EXITFREE) || defined(PROTO)
-+ void
-+ free_insexpand_stuff(void)
-+ {
-+ VIM_CLEAR(compl_orig_text);
-+ }
-+ # endif
-+
-+ # ifdef FEAT_SPELL
-+ /*
-+ * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
-+ * spelled word, if there is one.
-+ */
-+ static void
-+ spell_back_to_badword(void)
-+ {
-+ pos_T tpos = curwin->w_cursor;
-+
-+ spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
-+ if (curwin->w_cursor.col != tpos.col)
-+ start_arrow(&tpos);
-+ }
-+ # endif
-+
-+ #endif // FEAT_INS_EXPAND
-*** ../vim-8.1.1075/src/misc2.c 2019-03-22 12:03:26.583533911 +0100
---- src/misc2.c 2019-03-30 12:54:54.305407871 +0100
-***************
-*** 1130,1135 ****
---- 1130,1136 ----
- free_search_patterns();
- free_old_sub();
- free_last_insert();
-+ free_insexpand_stuff();
- free_prev_shellcmd();
- free_regexp_stuff();
- free_tag_stuff();
-*** ../vim-8.1.1075/src/proto.h 2019-02-19 21:34:01.987747438 +0100
---- src/proto.h 2019-03-30 12:54:54.305407871 +0100
-***************
-*** 89,94 ****
---- 89,97 ----
- # include "hardcopy.pro"
- # include "hashtab.pro"
- # include "indent.pro"
-+ # ifdef FEAT_INS_EXPAND
-+ # include "insexpand.pro"
-+ # endif
- # include "json.pro"
- # include "list.pro"
- # include "blob.pro"
-*** ../vim-8.1.1075/src/proto/edit.pro 2019-03-29 12:19:34.953348924 +0100
---- src/proto/edit.pro 2019-03-30 12:56:24.004687230 +0100
-***************
-*** 1,5 ****
---- 1,7 ----
- /* edit.c */
- int edit(int cmdchar, int startln, long count);
-+ int ins_need_undo_get(void);
-+ void ins_redraw(int ready);
- void edit_putchar(int c, int highlight);
- char_u *prompt_text(void);
- int prompt_curpos_editable(void);
-***************
-*** 8,30 ****
- void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes);
- void truncate_spaces(char_u *line);
- void backspace_until_column(int col);
-- int ctrl_x_mode_not_default(void);
-- int ctrl_x_mode_not_defined_yet(void);
-- int vim_is_ctrl_x_key(int c);
-- int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags);
-- void completeopt_was_set(void);
-- void set_completion(colnr_T startcol, list_T *list);
-- void ins_compl_show_pum(void);
-- char_u *find_word_start(char_u *ptr);
-- char_u *find_word_end(char_u *ptr);
-- int ins_compl_active(void);
-- void get_complete_info(list_T *what_list, dict_T *retdict);
-- int ins_compl_add_tv(typval_T *tv, int dir);
-- void ins_compl_check_keys(int frequency, int in_compl_func);
- int get_literal(void);
- void insertchar(int c, int flags, int second_indent);
- void auto_format(int trailblank, int prev_line);
- int comp_textwidth(int ff);
- int stop_arrow(void);
- void set_last_insert(int c);
- void free_last_insert(void);
---- 10,20 ----
- void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes);
- void truncate_spaces(char_u *line);
- void backspace_until_column(int col);
- int get_literal(void);
- void insertchar(int c, int flags, int second_indent);
- void auto_format(int trailblank, int prev_line);
- int comp_textwidth(int ff);
-+ void start_arrow(pos_T *end_insert_pos);
- int stop_arrow(void);
- void set_last_insert(int c);
- void free_last_insert(void);
-***************
-*** 43,48 ****
---- 33,41 ----
- int bracketed_paste(paste_mode_T mode, int drop, garray_T *gap);
- void ins_scroll(void);
- void ins_horscroll(void);
-+ int ins_eol(int c);
- int ins_copychar(linenr_T lnum);
- colnr_T get_nolist_virtcol(void);
-+ int can_cindent_get(void);
-+ int ins_apply_autocmds(event_T event);
- /* vim: set ft=c : */
-*** ../vim-8.1.1075/src/proto/insexpand.pro 2019-03-30 13:32:12.906308579 +0100
---- src/proto/insexpand.pro 2019-03-30 13:49:17.191991200 +0100
-***************
-*** 0 ****
---- 1,50 ----
-+ /* insexpand.c */
-+ void ins_ctrl_x(void);
-+ int ctrl_x_mode_none(void);
-+ int ctrl_x_mode_normal(void);
-+ int ctrl_x_mode_scroll(void);
-+ int ctrl_x_mode_whole_line(void);
-+ int ctrl_x_mode_files(void);
-+ int ctrl_x_mode_tags(void);
-+ int ctrl_x_mode_path_patterns(void);
-+ int ctrl_x_mode_path_defines(void);
-+ int ctrl_x_mode_dictionary(void);
-+ int ctrl_x_mode_thesaurus(void);
-+ int ctrl_x_mode_cmdline(void);
-+ int ctrl_x_mode_function(void);
-+ int ctrl_x_mode_omni(void);
-+ int ctrl_x_mode_spell(void);
-+ int ctrl_x_mode_line_or_eval(void);
-+ int ctrl_x_mode_not_default(void);
-+ int ctrl_x_mode_not_defined_yet(void);
-+ int has_compl_option(int dict_opt);
-+ int vim_is_ctrl_x_key(int c);
-+ int ins_compl_accept_char(int c);
-+ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags);
-+ int ins_compl_has_shown_match(void);
-+ int ins_compl_long_shown_match(void);
-+ void completeopt_was_set(void);
-+ void set_completion(colnr_T startcol, list_T *list);
-+ int pum_wanted(void);
-+ void ins_compl_show_pum(void);
-+ char_u *find_word_start(char_u *ptr);
-+ char_u *find_word_end(char_u *ptr);
-+ void ins_compl_clear(void);
-+ int ins_compl_active(void);
-+ void get_complete_info(list_T *what_list, dict_T *retdict);
-+ int ins_compl_used_match(void);
-+ void ins_compl_init_get_longest(void);
-+ int ins_compl_interrupted(void);
-+ int ins_compl_enter_selects(void);
-+ colnr_T ins_compl_col(void);
-+ int ins_compl_bs(void);
-+ void ins_compl_addleader(int c);
-+ void ins_compl_addfrommatch(void);
-+ int ins_compl_prep(int c);
-+ int ins_compl_add_tv(typval_T *tv, int dir);
-+ void ins_compl_delete(void);
-+ void ins_compl_insert(int in_compl_func);
-+ void ins_compl_check_keys(int frequency, int in_compl_func);
-+ int ins_complete(int c, int enable_pum);
-+ void free_insexpand_stuff(void);
-+ /* vim: set ft=c : */
-*** ../vim-8.1.1075/src/search.c 2019-03-03 14:42:04.782109771 +0100
---- src/search.c 2019-03-30 12:54:54.305407871 +0100
-***************
-*** 5479,5485 ****
- #ifdef FEAT_INS_EXPAND
- if (action == ACTION_EXPAND)
- ins_compl_check_keys(30, FALSE);
-! if (got_int || compl_interrupted)
- #else
- if (got_int)
- #endif
---- 5479,5485 ----
- #ifdef FEAT_INS_EXPAND
- if (action == ACTION_EXPAND)
- ins_compl_check_keys(30, FALSE);
-! if (got_int || ins_compl_interrupted())
- #else
- if (got_int)
- #endif
-***************
-*** 5550,5556 ****
- )
- {
- #ifdef FEAT_INS_EXPAND
-! if (got_int || compl_interrupted)
- #else
- if (got_int)
- #endif
---- 5550,5556 ----
- )
- {
- #ifdef FEAT_INS_EXPAND
-! if (got_int || ins_compl_interrupted())
- #else
- if (got_int)
- #endif
-*** ../vim-8.1.1075/src/spell.c 2019-01-26 17:28:22.232599086 +0100
---- src/spell.c 2019-03-30 13:33:40.365785214 +0100
-***************
-*** 8473,8479 ****
- arridx[0] = 0;
- curi[0] = 1;
- while (depth >= 0 && !got_int
-! && (pat == NULL || !compl_interrupted))
- {
- if (curi[depth] > byts[arridx[depth]])
- {
---- 8473,8479 ----
- arridx[0] = 0;
- curi[0] = 1;
- while (depth >= 0 && !got_int
-! && (pat == NULL || !ins_compl_interrupted()))
- {
- if (curi[depth] > byts[arridx[depth]])
- {
-*** ../vim-8.1.1075/src/structs.h 2019-03-04 11:40:06.274241644 +0100
---- src/structs.h 2019-03-30 13:47:56.176499590 +0100
-***************
-*** 1191,1226 ****
- # ifdef PROTO
- typedef long varnumber_T;
- typedef unsigned long uvarnumber_T;
-! #define VARNUM_MIN LONG_MIN
-! #define VARNUM_MAX LONG_MAX
-! #define UVARNUM_MAX ULONG_MAX
- # else
- typedef __int64 varnumber_T;
- typedef unsigned __int64 uvarnumber_T;
-! #define VARNUM_MIN _I64_MIN
-! #define VARNUM_MAX _I64_MAX
-! #define UVARNUM_MAX _UI64_MAX
- # endif
- # elif defined(HAVE_STDINT_H)
- typedef int64_t varnumber_T;
- typedef uint64_t uvarnumber_T;
-! #define VARNUM_MIN INT64_MIN
-! #define VARNUM_MAX INT64_MAX
-! #define UVARNUM_MAX UINT64_MAX
- # else
- typedef long varnumber_T;
- typedef unsigned long uvarnumber_T;
-! #define VARNUM_MIN LONG_MIN
-! #define VARNUM_MAX LONG_MAX
-! #define UVARNUM_MAX ULONG_MAX
- # endif
- #else
- /* Use 32-bit Number. */
- typedef int varnumber_T;
- typedef unsigned int uvarnumber_T;
-! #define VARNUM_MIN INT_MIN
-! #define VARNUM_MAX INT_MAX
-! #define UVARNUM_MAX UINT_MAX
- #endif
-
- typedef double float_T;
---- 1191,1226 ----
- # ifdef PROTO
- typedef long varnumber_T;
- typedef unsigned long uvarnumber_T;
-! # define VARNUM_MIN LONG_MIN
-! # define VARNUM_MAX LONG_MAX
-! # define UVARNUM_MAX ULONG_MAX
- # else
- typedef __int64 varnumber_T;
- typedef unsigned __int64 uvarnumber_T;
-! # define VARNUM_MIN _I64_MIN
-! # define VARNUM_MAX _I64_MAX
-! # define UVARNUM_MAX _UI64_MAX
- # endif
- # elif defined(HAVE_STDINT_H)
- typedef int64_t varnumber_T;
- typedef uint64_t uvarnumber_T;
-! # define VARNUM_MIN INT64_MIN
-! # define VARNUM_MAX INT64_MAX
-! # define UVARNUM_MAX UINT64_MAX
- # else
- typedef long varnumber_T;
- typedef unsigned long uvarnumber_T;
-! # define VARNUM_MIN LONG_MIN
-! # define VARNUM_MAX LONG_MAX
-! # define UVARNUM_MAX ULONG_MAX
- # endif
- #else
- /* Use 32-bit Number. */
- typedef int varnumber_T;
- typedef unsigned int uvarnumber_T;
-! # define VARNUM_MIN INT_MIN
-! # define VARNUM_MAX INT_MAX
-! # define UVARNUM_MAX UINT_MAX
- #endif
-
- typedef double float_T;
-***************
-*** 3340,3355 ****
- void *tn_search_ctx;
- } tagname_T;
-
-- /*
-- * Array indexes used for cptext argument of ins_compl_add().
-- */
-- #define CPT_ABBR 0 /* "abbr" */
-- #define CPT_MENU 1 /* "menu" */
-- #define CPT_KIND 2 /* "kind" */
-- #define CPT_INFO 3 /* "info" */
-- #define CPT_USER_DATA 4 /* "user data" */
-- #define CPT_COUNT 5 /* Number of entries */
--
- typedef struct {
- UINT32_T total[2];
- UINT32_T state[8];
---- 3340,3345 ----
-*** ../vim-8.1.1075/src/tag.c 2019-03-22 17:03:01.779689390 +0100
---- src/tag.c 2019-03-30 12:54:54.309407840 +0100
-***************
-*** 1591,1597 ****
- #ifdef FEAT_INS_EXPAND
- if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
- ins_compl_check_keys(30, FALSE);
-! if (got_int || compl_interrupted)
- #else
- if (got_int)
- #endif
---- 1591,1597 ----
- #ifdef FEAT_INS_EXPAND
- if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
- ins_compl_check_keys(30, FALSE);
-! if (got_int || ins_compl_interrupted())
- #else
- if (got_int)
- #endif
-*** ../vim-8.1.1075/src/version.c 2019-03-30 12:51:18.626808012 +0100
---- src/version.c 2019-03-30 13:00:27.254840750 +0100
-***************
-*** 777,778 ****
---- 777,780 ----
- { /* Add new patch number below this line */
-+ /**/
-+ 1076,
- /**/
-
---
-hundred-and-one symptoms of being an internet addict:
-154. You fondle your mouse.
-
- /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
-/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
-\\\ an exciting new programming language -- http://www.Zimbu.org ///
- \\\ help me help AIDS victims -- http://ICCF-Holland.org ///