/* vi:set ts=8 sts=4 sw=4: * * 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. */ /* * edit.c: functions for Insert mode */ #include "vim.h" #ifdef FEAT_INS_EXPAND/* * definitions used for CTRL-X submode */#define CTRL_X_WANT_IDENT 0x100 #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_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] static char *ctrl_x_msgs[] ={ N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */ N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"), NULL, 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, 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)"),}; static char_u e_hitend[] = N_("Hit end of paragraph"); /* * 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; /* 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_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; 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 void ins_ctrl_x __ARGS((void));static int has_compl_option __ARGS((int dict_opt));static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup));static int ins_compl_equal __ARGS((compl_T *match, char_u *str, int len));static void ins_compl_longest_match __ARGS((compl_T *match));static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int icase));static int ins_compl_make_cyclic __ARGS((void));static void ins_compl_upd_pum __ARGS((void));static void ins_compl_del_pum __ARGS((void));static int pum_wanted __ARGS((void));static int pum_enough_matches __ARGS((void));static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int flags, int thesaurus));static void ins_compl_files __ARGS((int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir));static char_u *find_line_end __ARGS((char_u *ptr));static void ins_compl_free __ARGS((void));static void ins_compl_clear __ARGS((void));static int ins_compl_bs __ARGS((void));static void ins_compl_new_leader __ARGS((void));static void ins_compl_addleader __ARGS((int c));static void ins_compl_restart __ARGS((void));static void ins_compl_set_original_text __ARGS((char_u *str));static void ins_compl_addfrommatch __ARGS((void));static int ins_compl_prep __ARGS((int c));static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)static void ins_compl_add_list __ARGS((list_T *list));#endifstatic int ins_compl_get_exp __ARGS((pos_T *ini));static void ins_compl_delete __ARGS((void));static void ins_compl_insert __ARGS((void));static int ins_compl_next __ARGS((int allow_get_expansion, int count, int insert_match));static int ins_compl_key2dir __ARGS((int c));static int ins_compl_pum_key __ARGS((int c));static int ins_compl_key2count __ARGS((int c));static int ins_compl_use_match __ARGS((int c));static int ins_complete __ARGS((int c));static int quote_meta __ARGS((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 __ARGS((int ready));static void ins_ctrl_v __ARGS((void));static void undisplay_dollar __ARGS((void));static void insert_special __ARGS((int, int, int));static void internal_format __ARGS((int textwidth, int second_indent, int flags, int format_only));static void check_auto_format __ARGS((int));static void redo_literal __ARGS((int c));static void start_arrow __ARGS((pos_T *end_insert_pos));#ifdef FEAT_SPELLstatic void check_spell_redraw __ARGS((void));static void spell_back_to_badword __ARGS((void));static int spell_bad_len = 0; /* length of located bad word */#endifstatic void stop_insert __ARGS((pos_T *end_insert_pos, int esc));static int echeck_abbr __ARGS((int));#if 0static void replace_push_off __ARGS((int c));#endifstatic int replace_pop __ARGS((void));static void replace_join __ARGS((int off));static void replace_pop_ins __ARGS((void));#ifdef FEAT_MBYTEstatic void mb_replace_pop_ins __ARGS((int cc));#endifstatic void replace_flush __ARGS((void));static void replace_do_bs __ARGS((void));#ifdef FEAT_CINDENTstatic int cindent_on __ARGS((void));#endifstatic void ins_reg __ARGS((void));static void ins_ctrl_g __ARGS((void));static void ins_ctrl_hat __ARGS((void));static int ins_esc __ARGS((long *count, int cmdchar, int nomove));#ifdef FEAT_RIGHTLEFTstatic void ins_ctrl_ __ARGS((void));#endif#ifdef FEAT_VISUALstatic int ins_start_select __ARGS((int c));#endifstatic void ins_insert __ARGS((int replaceState));static void ins_ctrl_o __ARGS((void));static void ins_shift __ARGS((int c, int lastc));static void ins_del __ARGS((void));static int ins_bs __ARGS((int c, int mode, int *inserted_space_p));#ifdef FEAT_MOUSEstatic void ins_mouse __ARGS((int c));static void ins_mousescroll __ARGS((int up));#endif#if defined(FEAT_GUI_TABLINE) || defined(PROTO)static void ins_tabline __ARGS((int c));#endifstatic void ins_left __ARGS((void));static void ins_home __ARGS((int c));static void ins_end __ARGS((int c));static void ins_s_left __ARGS((void));static void ins_right __ARGS((void));static void ins_s_right __ARGS((void));static void ins_up __ARGS((int startcol));static void ins_pageup __ARGS((void));static void ins_down __ARGS((int startcol));static void ins_pagedown __ARGS((void));#ifdef FEAT_DNDstatic void ins_drop __ARGS((void));#endifstatic int ins_tab __ARGS((void));static int ins_eol __ARGS((int c));#ifdef FEAT_DIGRAPHSstatic int ins_digraph __ARGS((void));#endifstatic int ins_copychar __ARGS((linenr_T lnum));static int ins_ctrl_ey __ARGS((int tc));#ifdef FEAT_SMARTINDENTstatic void ins_try_si __ARGS((int c));#endifstatic colnr_T get_nolist_virtcol __ARGS((void)); static colnr_T Insstart_textlen; /* length of line when insert started */static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ static char_u *last_insert = NULL; /* the text of the previous insert, K_SPECIAL and CSI are escaped */static int last_insert_skip; /* nr of chars in front of previous insert */static int new_insert_skip; /* nr of chars in front of current insert */static int did_restart_edit; /* "restart_edit" when calling edit() */ #ifdef FEAT_CINDENTstatic int can_cindent; /* may do cindenting on this line */#endif static int old_indent = 0; /* for ^^D command in insert mode */ #ifdef FEAT_RIGHTLEFTstatic int revins_on; /* reverse insert mode on */static int revins_chars; /* how much to skip after edit */static int revins_legal; /* was the last char 'legal'? */static int revins_scol; /* start column of revins session */#endif static int ins_need_undo; /* call u_save() before inserting a char. Set when edit() is called. after that arrow_used is used. */ static int did_add_space = FALSE; /* auto_format() added an extra space under the cursor */ /* * edit(): Start inserting text. * * "cmdchar" can be: * 'i' normal insert command * 'a' normal append command * 'R' replace command * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo, * but still only one <CR> is inserted. The <Esc> is not used for redo. * 'g' "gI" command. * 'V' "gR" command for Virtual Replace mode. * 'v' "gr" command for single character Virtual Replace mode. * * This function is not called recursively. For CTRL-O commands, it returns * and lets the caller handle the Normal-mode command. * * Return TRUE if a CTRL-O command caused the return (insert mode pending). */ intedit(cmdchar, startln, count) int cmdchar; int startln; /* if set, insert at start of line */ long count;{ int c = 0; char_u *ptr; int lastc; colnr_T mincol; static linenr_T o_lnum = 0; int i; int did_backspace = TRUE; /* previous char was backspace */#ifdef FEAT_CINDENT int line_is_white = FALSE; /* line is empty before insert */#endif linenr_T old_topline = 0; /* topline before insertion */#ifdef FEAT_DIFF int old_topfill = -1;#endif int inserted_space = FALSE; /* just inserted a space */ int replaceState = REPLACE; int nomove = FALSE; /* don't move cursor on return */ /* Remember whether editing was restarted after CTRL-O. */ did_restart_edit = restart_edit; /* sleep before redrawing, needed for "CTRL-O :" that results in an * error message */ check_for_delay(TRUE); #ifdef HAVE_SANDBOX /* Don't allow inserting in the sandbox. */ if (sandbox != 0) { EMSG(_(e_sandbox)); return FALSE; }#endif /* Don't allow changes in the buffer while editing the cmdline. The * caller of getcmdline() may get confused. */ if (textlock != 0) { EMSG(_(e_secure)); return FALSE; } #ifdef FEAT_INS_EXPAND /* Don't allow recursive insert mode when busy with completion. */ if (compl_started || pum_visible()) { EMSG(_(e_secure)); return FALSE; } ins_compl_clear(); /* clear stuff for CTRL-X mode */#endif #ifdef FEAT_AUTOCMD /* * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx". */ if (cmdchar != 'r' && cmdchar != 'v') {# ifdef FEAT_EVAL if (cmdchar == 'R') ptr = (char_u *)"r"; else if (cmdchar == 'V') ptr = (char_u *)"v"; else ptr = (char_u *)"i"; set_vim_var_string(VV_INSERTMODE, ptr, 1);# endif apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf); }#endif #ifdef FEAT_MOUSE /* * When doing a paste with the middle mouse button, Insstart is set to * where the paste started. */ if (where_paste_started.lnum != 0) Insstart = where_paste_started; else#endif { Insstart = curwin->w_cursor; if (startln) Insstart.col = 0; } Insstart_textlen = linetabsize(ml_get_curline()); Insstart_blank_vcol = MAXCOL; if (!did_ai) ai_col = 0; if (cmdchar != NUL && restart_edit == 0) { ResetRedobuff(); AppendNumberToRedobuff(count);#ifdef FEAT_VREPLACE if (cmdchar == 'V' || cmdchar == 'v') { /* "gR" or "gr" command */ AppendCharToRedobuff('g'); AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R'); } else#endif { AppendCharToRedobuff(cmdchar); if (cmdchar == 'g') /* "gI" command */ AppendCharToRedobuff('I'); else if (cmdchar == 'r') /* "r<CR>" command */ count = 1; /* insert only one <CR> */ } } if (cmdchar == 'R') {#ifdef FEAT_FKMAP if (p_fkmap && p_ri) { beep_flush(); EMSG(farsi_text_3); /* encoded in Farsi */ State = INSERT; } else#endif State = REPLACE; }#ifdef FEAT_VREPLACE else if (cmdchar == 'V' || cmdchar == 'v') { State = VREPLACE; replaceState = VREPLACE; orig_line_count = curbuf->b_ml.ml_line_count; vr_lines_changed = 1; }#endif else State = INSERT; stop_insert_mode = FALSE; /* * Need to recompute the cursor position, it might move when the cursor is * on a TAB or special character. */ curs_columns(TRUE); /* * Enable langmap or IME, indicated by 'iminsert'. * Note that IME may enabled/disabled without us noticing here, thus the * 'iminsert' value may not reflect what is actually used. It is updated * when hitting <Esc>. */ if (curbuf->b_p_iminsert == B_IMODE_LMAP) State |= LANGMAP;#ifdef USE_IM_CONTROL im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);#endif #ifdef FEAT_MOUSE setmouse();#endif#ifdef FEAT_CMDL_INFO clear_showcmd();#endif#ifdef FEAT_RIGHTLEFT /* there is no reverse replace mode */ revins_on = (State == INSERT && p_ri); if (revins_on) undisplay_dollar(); revins_chars = 0; revins_legal = 0; revins_scol = -1;#endif /* * Handle restarting Insert mode. * Don't do this for "CTRL-O ." (repeat an insert): we get here with * restart_edit non-zero, and something in the stuff buffer. */ if (restart_edit != 0 && stuff_empty()) {#ifdef FEAT_MOUSE /* * After a paste we consider text typed to be part of the insert for * the pasted text. You can backspace over the pasted text too. */ if (where_paste_started.lnum) arrow_used = FALSE; else#endif arrow_used = TRUE; restart_edit = 0; /* * If the cursor was after the end-of-line before the CTRL-O and it is * now at the end-of-line, put it after the end-of-line (this is not * correct in very rare cases). * Also do this if curswant is greater than the current virtual * column. Eg after "^O$" or "^O80|". */Lines 1–500 of 9506. Load more
/* vi:set ts=8 sts=4 sw=4: * * 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. */ /* * edit.c: functions for Insert mode */ #include "vim.h" #ifdef FEAT_INS_EXPAND /* * definitions used for CTRL-X submode */ #define CTRL_X_WANT_IDENT 0x100 #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_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] static char *ctrl_x_msgs[] = { N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */ N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"), NULL, 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, 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)"), }; static char_u e_hitend[] = N_("Hit end of paragraph"); /* * 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; /* 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_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; 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 void ins_ctrl_x __ARGS((void)); static int has_compl_option __ARGS((int dict_opt)); static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup)); static int ins_compl_equal __ARGS((compl_T *match, char_u *str, int len)); static void ins_compl_longest_match __ARGS((compl_T *match)); static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int icase)); static int ins_compl_make_cyclic __ARGS((void)); static void ins_compl_upd_pum __ARGS((void)); static void ins_compl_del_pum __ARGS((void)); static int pum_wanted __ARGS((void)); static int pum_enough_matches __ARGS((void)); static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int flags, int thesaurus)); static void ins_compl_files __ARGS((int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir)); static char_u *find_line_end __ARGS((char_u *ptr)); static void ins_compl_free __ARGS((void)); static void ins_compl_clear __ARGS((void)); static int ins_compl_bs __ARGS((void)); static void ins_compl_new_leader __ARGS((void)); static void ins_compl_addleader __ARGS((int c)); static void ins_compl_restart __ARGS((void)); static void ins_compl_set_original_text __ARGS((char_u *str)); static void ins_compl_addfrommatch __ARGS((void)); static int ins_compl_prep __ARGS((int c)); static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag)); #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) static void ins_compl_add_list __ARGS((list_T *list)); #endif static int ins_compl_get_exp __ARGS((pos_T *ini)); static void ins_compl_delete __ARGS((void)); static void ins_compl_insert __ARGS((void)); static int ins_compl_next __ARGS((int allow_get_expansion, int count, int insert_match)); static int ins_compl_key2dir __ARGS((int c)); static int ins_compl_pum_key __ARGS((int c)); static int ins_compl_key2count __ARGS((int c)); static int ins_compl_use_match __ARGS((int c)); static int ins_complete __ARGS((int c)); static int quote_meta __ARGS((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 __ARGS((int ready)); static void ins_ctrl_v __ARGS((void)); static void undisplay_dollar __ARGS((void)); static void insert_special __ARGS((int, int, int)); static void internal_format __ARGS((int textwidth, int second_indent, int flags, int format_only)); static void check_auto_format __ARGS((int)); static void redo_literal __ARGS((int c)); static void start_arrow __ARGS((pos_T *end_insert_pos)); #ifdef FEAT_SPELL static void check_spell_redraw __ARGS((void)); static void spell_back_to_badword __ARGS((void)); static int spell_bad_len = 0; /* length of located bad word */ #endif static void stop_insert __ARGS((pos_T *end_insert_pos, int esc)); static int echeck_abbr __ARGS((int)); #if 0 static void replace_push_off __ARGS((int c)); #endif static int replace_pop __ARGS((void)); static void replace_join __ARGS((int off)); static void replace_pop_ins __ARGS((void)); #ifdef FEAT_MBYTE static void mb_replace_pop_ins __ARGS((int cc)); #endif static void replace_flush __ARGS((void)); static void replace_do_bs __ARGS((void)); #ifdef FEAT_CINDENT static int cindent_on __ARGS((void)); #endif static void ins_reg __ARGS((void)); static void ins_ctrl_g __ARGS((void)); static void ins_ctrl_hat __ARGS((void)); static int ins_esc __ARGS((long *count, int cmdchar, int nomove)); #ifdef FEAT_RIGHTLEFT static void ins_ctrl_ __ARGS((void)); #endif #ifdef FEAT_VISUAL static int ins_start_select __ARGS((int c)); #endif static void ins_insert __ARGS((int replaceState)); static void ins_ctrl_o __ARGS((void)); static void ins_shift __ARGS((int c, int lastc)); static void ins_del __ARGS((void)); static int ins_bs __ARGS((int c, int mode, int *inserted_space_p)); #ifdef FEAT_MOUSE static void ins_mouse __ARGS((int c)); static void ins_mousescroll __ARGS((int up)); #endif #if defined(FEAT_GUI_TABLINE) || defined(PROTO) static void ins_tabline __ARGS((int c)); #endif static void ins_left __ARGS((void)); static void ins_home __ARGS((int c)); static void ins_end __ARGS((int c)); static void ins_s_left __ARGS((void)); static void ins_right __ARGS((void)); static void ins_s_right __ARGS((void)); static void ins_up __ARGS((int startcol)); static void ins_pageup __ARGS((void)); static void ins_down __ARGS((int startcol)); static void ins_pagedown __ARGS((void)); #ifdef FEAT_DND static void ins_drop __ARGS((void)); #endif static int ins_tab __ARGS((void)); static int ins_eol __ARGS((int c)); #ifdef FEAT_DIGRAPHS static int ins_digraph __ARGS((void)); #endif static int ins_copychar __ARGS((linenr_T lnum)); static int ins_ctrl_ey __ARGS((int tc)); #ifdef FEAT_SMARTINDENT static void ins_try_si __ARGS((int c)); #endif static colnr_T get_nolist_virtcol __ARGS((void)); static colnr_T Insstart_textlen; /* length of line when insert started */ static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ static char_u *last_insert = NULL; /* the text of the previous insert, K_SPECIAL and CSI are escaped */ static int last_insert_skip; /* nr of chars in front of previous insert */ static int new_insert_skip; /* nr of chars in front of current insert */ static int did_restart_edit; /* "restart_edit" when calling edit() */ #ifdef FEAT_CINDENT static int can_cindent; /* may do cindenting on this line */ #endif static int old_indent = 0; /* for ^^D command in insert mode */ #ifdef FEAT_RIGHTLEFT static int revins_on; /* reverse insert mode on */ static int revins_chars; /* how much to skip after edit */ static int revins_legal; /* was the last char 'legal'? */ static int revins_scol; /* start column of revins session */ #endif static int ins_need_undo; /* call u_save() before inserting a char. Set when edit() is called. after that arrow_used is used. */ static int did_add_space = FALSE; /* auto_format() added an extra space under the cursor */ /* * edit(): Start inserting text. * * "cmdchar" can be: * 'i' normal insert command * 'a' normal append command * 'R' replace command * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo, * but still only one <CR> is inserted. The <Esc> is not used for redo. * 'g' "gI" command. * 'V' "gR" command for Virtual Replace mode. * 'v' "gr" command for single character Virtual Replace mode. * * This function is not called recursively. For CTRL-O commands, it returns * and lets the caller handle the Normal-mode command. * * Return TRUE if a CTRL-O command caused the return (insert mode pending). */ int edit(cmdchar, startln, count) int cmdchar; int startln; /* if set, insert at start of line */ long count; { int c = 0; char_u *ptr; int lastc; colnr_T mincol; static linenr_T o_lnum = 0; int i; int did_backspace = TRUE; /* previous char was backspace */ #ifdef FEAT_CINDENT int line_is_white = FALSE; /* line is empty before insert */ #endif linenr_T old_topline = 0; /* topline before insertion */ #ifdef FEAT_DIFF int old_topfill = -1; #endif int inserted_space = FALSE; /* just inserted a space */ int replaceState = REPLACE; int nomove = FALSE; /* don't move cursor on return */ /* Remember whether editing was restarted after CTRL-O. */ did_restart_edit = restart_edit; /* sleep before redrawing, needed for "CTRL-O :" that results in an * error message */ check_for_delay(TRUE); #ifdef HAVE_SANDBOX /* Don't allow inserting in the sandbox. */ if (sandbox != 0) { EMSG(_(e_sandbox)); return FALSE; } #endif /* Don't allow changes in the buffer while editing the cmdline. The * caller of getcmdline() may get confused. */ if (textlock != 0) { EMSG(_(e_secure)); return FALSE; } #ifdef FEAT_INS_EXPAND /* Don't allow recursive insert mode when busy with completion. */ if (compl_started || pum_visible()) { EMSG(_(e_secure)); return FALSE; } ins_compl_clear(); /* clear stuff for CTRL-X mode */ #endif #ifdef FEAT_AUTOCMD /* * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx". */ if (cmdchar != 'r' && cmdchar != 'v') { # ifdef FEAT_EVAL if (cmdchar == 'R') ptr = (char_u *)"r"; else if (cmdchar == 'V') ptr = (char_u *)"v"; else ptr = (char_u *)"i"; set_vim_var_string(VV_INSERTMODE, ptr, 1); # endif apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf); } #endif #ifdef FEAT_MOUSE /* * When doing a paste with the middle mouse button, Insstart is set to * where the paste started. */ if (where_paste_started.lnum != 0) Insstart = where_paste_started; else #endif { Insstart = curwin->w_cursor; if (startln) Insstart.col = 0; } Insstart_textlen = linetabsize(ml_get_curline()); Insstart_blank_vcol = MAXCOL; if (!did_ai) ai_col = 0; if (cmdchar != NUL && restart_edit == 0) { ResetRedobuff(); AppendNumberToRedobuff(count); #ifdef FEAT_VREPLACE if (cmdchar == 'V' || cmdchar == 'v') { /* "gR" or "gr" command */ AppendCharToRedobuff('g'); AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R'); } else #endif { AppendCharToRedobuff(cmdchar); if (cmdchar == 'g') /* "gI" command */ AppendCharToRedobuff('I'); else if (cmdchar == 'r') /* "r<CR>" command */ count = 1; /* insert only one <CR> */ } } if (cmdchar == 'R') { #ifdef FEAT_FKMAP if (p_fkmap && p_ri) { beep_flush(); EMSG(farsi_text_3); /* encoded in Farsi */ State = INSERT; } else #endif State = REPLACE; } #ifdef FEAT_VREPLACE else if (cmdchar == 'V' || cmdchar == 'v') { State = VREPLACE; replaceState = VREPLACE; orig_line_count = curbuf->b_ml.ml_line_count; vr_lines_changed = 1; } #endif else State = INSERT; stop_insert_mode = FALSE; /* * Need to recompute the cursor position, it might move when the cursor is * on a TAB or special character. */ curs_columns(TRUE); /* * Enable langmap or IME, indicated by 'iminsert'. * Note that IME may enabled/disabled without us noticing here, thus the * 'iminsert' value may not reflect what is actually used. It is updated * when hitting <Esc>. */ if (curbuf->b_p_iminsert == B_IMODE_LMAP) State |= LANGMAP; #ifdef USE_IM_CONTROL im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); #endif #ifdef FEAT_MOUSE setmouse(); #endif #ifdef FEAT_CMDL_INFO clear_showcmd(); #endif #ifdef FEAT_RIGHTLEFT /* there is no reverse replace mode */ revins_on = (State == INSERT && p_ri); if (revins_on) undisplay_dollar(); revins_chars = 0; revins_legal = 0; revins_scol = -1; #endif /* * Handle restarting Insert mode. * Don't do this for "CTRL-O ." (repeat an insert): we get here with * restart_edit non-zero, and something in the stuff buffer. */ if (restart_edit != 0 && stuff_empty()) { #ifdef FEAT_MOUSE /* * After a paste we consider text typed to be part of the insert for * the pasted text. You can backspace over the pasted text too. */ if (where_paste_started.lnum) arrow_used = FALSE; else #endif arrow_used = TRUE; restart_edit = 0; /* * If the cursor was after the end-of-line before the CTRL-O and it is * now at the end-of-line, put it after the end-of-line (this is not * correct in very rare cases). * Also do this if curswant is greater than the current virtual * column. Eg after "^O$" or "^O80|". */