1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * edit.c: functions for Insert mode 12 */ 13 14 #include "vim.h" 15 16 #ifdef FEAT_INS_EXPAND 17 /* 18 * definitions used for CTRL-X submode 19 */ 20 #define CTRL_X_WANT_IDENT 0x100 21 22 #define CTRL_X_NOT_DEFINED_YET 1 23 #define CTRL_X_SCROLL 2 24 #define CTRL_X_WHOLE_LINE 3 25 #define CTRL_X_FILES 4 26 #define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT) 27 #define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT) 28 #define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT) 29 #define CTRL_X_FINISHED 8 30 #define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT) 31 #define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT) 32 #define CTRL_X_CMDLINE 11 33 #define CTRL_X_FUNCTION 12 34 #define CTRL_X_OMNI 13 35 #define CTRL_X_SPELL 14 36 #define CTRL_X_LOCAL_MSG 15 /* only used in "ctrl_x_msgs" */ 37 #define CTRL_X_EVAL 16 /* for builtin function complete() */ 38 39 #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] 40 #define CTRL_X_MODE_LINE_OR_EVAL(m) (m == CTRL_X_WHOLE_LINE || m == CTRL_X_EVAL) 41 42 static char *ctrl_x_msgs[] = 43 { 44 N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */ 45 N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"), 46 NULL, 47 N_(" Whole line completion (^L^N^P)"), 48 N_(" File name completion (^F^N^P)"), 49 N_(" Tag completion (^]^N^P)"), 50 N_(" Path pattern completion (^N^P)"), 51 N_(" Definition completion (^D^N^P)"), 52 NULL, 53 N_(" Dictionary completion (^K^N^P)"), 54 N_(" Thesaurus completion (^T^N^P)"), 55 N_(" Command-line completion (^V^N^P)"), 56 N_(" User defined completion (^U^N^P)"), 57 N_(" Omni completion (^O^N^P)"), 58 N_(" Spelling suggestion (s^N^P)"), 59 N_(" Keyword Local completion (^N^P)"), 60 NULL, /* CTRL_X_EVAL doesn't use msg. */ 61 }; 62 63 static char e_hitend[] = N_("Hit end of paragraph"); 64 #ifdef FEAT_COMPL_FUNC 65 static char e_complwin[] = N_("E839: Completion function changed window"); 66 static char e_compldel[] = N_("E840: Completion function deleted text"); 67 #endif 68 69 /* 70 * Structure used to store one match for insert completion. 71 */ 72 typedef struct compl_S compl_T; 73 struct compl_S 74 { 75 compl_T *cp_next; 76 compl_T *cp_prev; 77 char_u *cp_str; /* matched text */ 78 char cp_icase; /* TRUE or FALSE: ignore case */ 79 char_u *(cp_text[CPT_COUNT]); /* text for the menu */ 80 char_u *cp_fname; /* file containing the match, allocated when 81 * cp_flags has FREE_FNAME */ 82 int cp_flags; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */ 83 int cp_number; /* sequence number */ 84 }; 85 86 #define ORIGINAL_TEXT (1) /* the original text when the expansion begun */ 87 #define FREE_FNAME (2) 88 89 /* 90 * All the current matches are stored in a list. 91 * "compl_first_match" points to the start of the list. 92 * "compl_curr_match" points to the currently selected entry. 93 * "compl_shown_match" is different from compl_curr_match during 94 * ins_compl_get_exp(). 95 */ 96 static compl_T *compl_first_match = NULL; 97 static compl_T *compl_curr_match = NULL; 98 static compl_T *compl_shown_match = NULL; 99 static compl_T *compl_old_match = NULL; 100 101 /* After using a cursor key <Enter> selects a match in the popup menu, 102 * otherwise it inserts a line break. */ 103 static int compl_enter_selects = FALSE; 104 105 /* When "compl_leader" is not NULL only matches that start with this string 106 * are used. */ 107 static char_u *compl_leader = NULL; 108 109 static int compl_get_longest = FALSE; /* put longest common string 110 in compl_leader */ 111 112 static int compl_no_insert = FALSE; /* FALSE: select & insert 113 TRUE: noinsert */ 114 static int compl_no_select = FALSE; /* FALSE: select & insert 115 TRUE: noselect */ 116 117 static int compl_used_match; /* Selected one of the matches. When 118 FALSE the match was edited or using 119 the longest common string. */ 120 121 static int compl_was_interrupted = FALSE; /* didn't finish finding 122 completions. */ 123 124 static int compl_restarting = FALSE; /* don't insert match */ 125 126 /* When the first completion is done "compl_started" is set. When it's 127 * FALSE the word to be completed must be located. */ 128 static int compl_started = FALSE; 129 130 /* Set when doing something for completion that may call edit() recursively, 131 * which is not allowed. */ 132 static int compl_busy = FALSE; 133 134 static int compl_matches = 0; 135 static char_u *compl_pattern = NULL; 136 static int compl_direction = FORWARD; 137 static int compl_shows_dir = FORWARD; 138 static int compl_pending = 0; /* > 1 for postponed CTRL-N */ 139 static pos_T compl_startpos; 140 static colnr_T compl_col = 0; /* column where the text starts 141 * that is being completed */ 142 static char_u *compl_orig_text = NULL; /* text as it was before 143 * completion started */ 144 static int compl_cont_mode = 0; 145 static expand_T compl_xp; 146 147 static int compl_opt_refresh_always = FALSE; 148 149 static void ins_ctrl_x(void); 150 static int has_compl_option(int dict_opt); 151 static int ins_compl_accept_char(int c); 152 static int ins_compl_add(char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup); 153 static int ins_compl_equal(compl_T *match, char_u *str, int len); 154 static void ins_compl_longest_match(compl_T *match); 155 static void ins_compl_add_matches(int num_matches, char_u **matches, int icase); 156 static int ins_compl_make_cyclic(void); 157 static void ins_compl_upd_pum(void); 158 static void ins_compl_del_pum(void); 159 static int pum_wanted(void); 160 static int pum_enough_matches(void); 161 static void ins_compl_dictionaries(char_u *dict, char_u *pat, int flags, int thesaurus); 162 static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir); 163 static char_u *find_line_end(char_u *ptr); 164 static void ins_compl_free(void); 165 static void ins_compl_clear(void); 166 static int ins_compl_bs(void); 167 static int ins_compl_need_restart(void); 168 static void ins_compl_new_leader(void); 169 static void ins_compl_addleader(int c); 170 static int ins_compl_len(void); 171 static void ins_compl_restart(void); 172 static void ins_compl_set_original_text(char_u *str); 173 static void ins_compl_addfrommatch(void); 174 static int ins_compl_prep(int c); 175 static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg); 176 static buf_T *ins_compl_next_buf(buf_T *buf, int flag); 177 #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) 178 static void ins_compl_add_list(list_T *list); 179 static void ins_compl_add_dict(dict_T *dict); 180 #endif 181 static int ins_compl_get_exp(pos_T *ini); 182 static void ins_compl_delete(void); 183 static void ins_compl_insert(int in_compl_func); 184 static int ins_compl_next(int allow_get_expansion, int count, int insert_match, int in_compl_func); 185 static int ins_compl_key2dir(int c); 186 static int ins_compl_pum_key(int c); 187 static int ins_compl_key2count(int c); 188 static int ins_compl_use_match(int c); 189 static int ins_complete(int c, int enable_pum); 190 static void show_pum(int prev_w_wrow, int prev_w_leftcol); 191 static unsigned quote_meta(char_u *dest, char_u *str, int len); 192 #endif /* FEAT_INS_EXPAND */ 193 194 #define BACKSPACE_CHAR 1 195 #define BACKSPACE_WORD 2 196 #define BACKSPACE_WORD_NOT_SPACE 3 197 #define BACKSPACE_LINE 4 198 199 static void ins_redraw(int ready); 200 static void ins_ctrl_v(void); 201 static void undisplay_dollar(void); 202 static void insert_special(int, int, int); 203 static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c); 204 static void check_auto_format(int); 205 static void redo_literal(int c); 206 static void start_arrow(pos_T *end_insert_pos); 207 static void start_arrow_with_change(pos_T *end_insert_pos, int change); 208 static void start_arrow_common(pos_T *end_insert_pos, int change); 209 #ifdef FEAT_SPELL 210 static void check_spell_redraw(void); 211 static void spell_back_to_badword(void); 212 static int spell_bad_len = 0; /* length of located bad word */ 213 #endif 214 static void stop_insert(pos_T *end_insert_pos, int esc, int nomove); 215 static int echeck_abbr(int); 216 static int replace_pop(void); 217 static void replace_join(int off); 218 static void replace_pop_ins(void); 219 #ifdef FEAT_MBYTE 220 static void mb_replace_pop_ins(int cc); 221 #endif 222 static void replace_flush(void); 223 static void replace_do_bs(int limit_col); 224 static int del_char_after_col(int limit_col); 225 #ifdef FEAT_CINDENT 226 static int cindent_on(void); 227 #endif 228 static void ins_reg(void); 229 static void ins_ctrl_g(void); 230 static void ins_ctrl_hat(void); 231 static int ins_esc(long *count, int cmdchar, int nomove); 232 #ifdef FEAT_RIGHTLEFT 233 static void ins_ctrl_(void); 234 #endif 235 static int ins_start_select(int c); 236 static void ins_insert(int replaceState); 237 static void ins_ctrl_o(void); 238 static void ins_shift(int c, int lastc); 239 static void ins_del(void); 240 static int ins_bs(int c, int mode, int *inserted_space_p); 241 #ifdef FEAT_MOUSE 242 static void ins_mouse(int c); 243 static void ins_mousescroll(int dir); 244 #endif 245 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) 246 static void ins_tabline(int c); 247 #endif 248 static void ins_left(int end_change); 249 static void ins_home(int c); 250 static void ins_end(int c); 251 static void ins_s_left(void); 252 static void ins_right(int end_change); 253 static void ins_s_right(void); 254 static void ins_up(int startcol); 255 static void ins_pageup(void); 256 static void ins_down(int startcol); 257 static void ins_pagedown(void); 258 #ifdef FEAT_DND 259 static void ins_drop(void); 260 #endif 261 static int ins_tab(void); 262 static int ins_eol(int c); 263 #ifdef FEAT_DIGRAPHS 264 static int ins_digraph(void); 265 #endif 266 static int ins_ctrl_ey(int tc); 267 #ifdef FEAT_SMARTINDENT 268 static void ins_try_si(int c); 269 #endif 270 static colnr_T get_nolist_virtcol(void); 271 #ifdef FEAT_AUTOCMD 272 static char_u *do_insert_char_pre(int c); 273 #endif 274 275 static colnr_T Insstart_textlen; /* length of line when insert started */ 276 static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ 277 static int update_Insstart_orig = TRUE; /* set Insstart_orig to Insstart */ 278 279 static char_u *last_insert = NULL; /* the text of the previous insert, 280 K_SPECIAL and CSI are escaped */ 281 static int last_insert_skip; /* nr of chars in front of previous insert */ 282 static int new_insert_skip; /* nr of chars in front of current insert */ 283 static int did_restart_edit; /* "restart_edit" when calling edit() */ 284 285 #ifdef FEAT_CINDENT 286 static int can_cindent; /* may do cindenting on this line */ 287 #endif 288 289 static int old_indent = 0; /* for ^^D command in insert mode */ 290 291 #ifdef FEAT_RIGHTLEFT 292 static int revins_on; /* reverse insert mode on */ 293 static int revins_chars; /* how much to skip after edit */ 294 static int revins_legal; /* was the last char 'legal'? */ 295 static int revins_scol; /* start column of revins session */ 296 #endif 297 298 static int ins_need_undo; /* call u_save() before inserting a 299 char. Set when edit() is called. 300 after that arrow_used is used. */ 301 302 static int did_add_space = FALSE; /* auto_format() added an extra space 303 under the cursor */ 304 static int dont_sync_undo = FALSE; /* CTRL-G U prevents syncing undo for 305 the next left/right cursor */ 306 307 /* 308 * edit(): Start inserting text. 309 * 310 * "cmdchar" can be: 311 * 'i' normal insert command 312 * 'a' normal append command 313 * K_PS bracketed paste 314 * 'R' replace command 315 * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo, 316 * but still only one <CR> is inserted. The <Esc> is not used for redo. 317 * 'g' "gI" command. 318 * 'V' "gR" command for Virtual Replace mode. 319 * 'v' "gr" command for single character Virtual Replace mode. 320 * 321 * This function is not called recursively. For CTRL-O commands, it returns 322 * and lets the caller handle the Normal-mode command. 323 * 324 * Return TRUE if a CTRL-O command caused the return (insert mode pending). 325 */ 326 int 327 edit( 328 int cmdchar, 329 int startln, /* if set, insert at start of line */ 330 long count) 331 { 332 int c = 0; 333 char_u *ptr; 334 int lastc = 0; 335 int mincol; 336 static linenr_T o_lnum = 0; 337 int i; 338 int did_backspace = TRUE; /* previous char was backspace */ 339 #ifdef FEAT_CINDENT 340 int line_is_white = FALSE; /* line is empty before insert */ 341 #endif 342 linenr_T old_topline = 0; /* topline before insertion */ 343 #ifdef FEAT_DIFF 344 int old_topfill = -1; 345 #endif 346 int inserted_space = FALSE; /* just inserted a space */ 347 int replaceState = REPLACE; 348 int nomove = FALSE; /* don't move cursor on return */ 349 350 /* Remember whether editing was restarted after CTRL-O. */ 351 did_restart_edit = restart_edit; 352 353 /* sleep before redrawing, needed for "CTRL-O :" that results in an 354 * error message */ 355 check_for_delay(TRUE); 356 357 /* set Insstart_orig to Insstart */ 358 update_Insstart_orig = TRUE; 359 360 #ifdef HAVE_SANDBOX 361 /* Don't allow inserting in the sandbox. */ 362 if (sandbox != 0) 363 { 364 EMSG(_(e_sandbox)); 365 return FALSE; 366 } 367 #endif 368 /* Don't allow changes in the buffer while editing the cmdline. The 369 * caller of getcmdline() may get confused. */ 370 if (textlock != 0) 371 { 372 EMSG(_(e_secure)); 373 return FALSE; 374 } 375 376 #ifdef FEAT_INS_EXPAND 377 /* Don't allow recursive insert mode when busy with completion. */ 378 if (compl_started || compl_busy || pum_visible()) 379 { 380 EMSG(_(e_secure)); 381 return FALSE; 382 } 383 ins_compl_clear(); /* clear stuff for CTRL-X mode */ 384 #endif 385 386 #ifdef FEAT_AUTOCMD 387 /* 388 * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx". 389 */ 390 if (cmdchar != 'r' && cmdchar != 'v') 391 { 392 pos_T save_cursor = curwin->w_cursor; 393 394 # ifdef FEAT_EVAL 395 if (cmdchar == 'R') 396 ptr = (char_u *)"r"; 397 else if (cmdchar == 'V') 398 ptr = (char_u *)"v"; 399 else 400 ptr = (char_u *)"i"; 401 set_vim_var_string(VV_INSERTMODE, ptr, 1); 402 set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */ 403 # endif 404 apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf); 405 406 /* Make sure the cursor didn't move. Do call check_cursor_col() in 407 * case the text was modified. Since Insert mode was not started yet 408 * a call to check_cursor_col() may move the cursor, especially with 409 * the "A" command, thus set State to avoid that. Also check that the 410 * line number is still valid (lines may have been deleted). 411 * Do not restore if v:char was set to a non-empty string. */ 412 if (!EQUAL_POS(curwin->w_cursor, save_cursor) 413 # ifdef FEAT_EVAL 414 && *get_vim_var_str(VV_CHAR) == NUL 415 # endif 416 && save_cursor.lnum <= curbuf->b_ml.ml_line_count) 417 { 418 int save_state = State; 419 420 curwin->w_cursor = save_cursor; 421 State = INSERT; 422 check_cursor_col(); 423 State = save_state; 424 } 425 } 426 #endif 427 428 #ifdef FEAT_CONCEAL 429 /* Check if the cursor line needs redrawing before changing State. If 430 * 'concealcursor' is "n" it needs to be redrawn without concealing. */ 431 conceal_check_cursur_line(); 432 #endif 433 434 #ifdef FEAT_MOUSE 435 /* 436 * When doing a paste with the middle mouse button, Insstart is set to 437 * where the paste started. 438 */ 439 if (where_paste_started.lnum != 0) 440 Insstart = where_paste_started; 441 else 442 #endif 443 { 444 Insstart = curwin->w_cursor; 445 if (startln) 446 Insstart.col = 0; 447 } 448 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); 449 Insstart_blank_vcol = MAXCOL; 450 if (!did_ai) 451 ai_col = 0; 452 453 if (cmdchar != NUL && restart_edit == 0) 454 { 455 ResetRedobuff(); 456 AppendNumberToRedobuff(count); 457 #ifdef FEAT_VREPLACE 458 if (cmdchar == 'V' || cmdchar == 'v') 459 { 460 /* "gR" or "gr" command */ 461 AppendCharToRedobuff('g'); 462 AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R'); 463 } 464 else 465 #endif 466 { 467 if (cmdchar == K_PS) 468 AppendCharToRedobuff('a'); 469 else 470 AppendCharToRedobuff(cmdchar); 471 if (cmdchar == 'g') /* "gI" command */ 472 AppendCharToRedobuff('I'); 473 else if (cmdchar == 'r') /* "r<CR>" command */ 474 count = 1; /* insert only one <CR> */ 475 } 476 } 477 478 if (cmdchar == 'R') 479 { 480 #ifdef FEAT_FKMAP 481 if (p_fkmap && p_ri) 482 { 483 beep_flush(); 484 EMSG(farsi_text_3); /* encoded in Farsi */ 485 State = INSERT; 486 } 487 else 488 #endif 489 State = REPLACE; 490 } 491 #ifdef FEAT_VREPLACE 492 else if (cmdchar == 'V' || cmdchar == 'v') 493 { 494 State = VREPLACE; 495 replaceState = VREPLACE; 496 orig_line_count = curbuf->b_ml.ml_line_count; 497 vr_lines_changed = 1; 498 } 499 #endif 500 else 501 State = INSERT; 502 503 stop_insert_mode = FALSE; 504 505 /* 506 * Need to recompute the cursor position, it might move when the cursor is 507 * on a TAB or special character. 508 */ 509 curs_columns(TRUE); 510 511 /* 512 * Enable langmap or IME, indicated by 'iminsert'. 513 * Note that IME may enabled/disabled without us noticing here, thus the 514 * 'iminsert' value may not reflect what is actually used. It is updated 515 * when hitting <Esc>. 516 */ 517 if (curbuf->b_p_iminsert == B_IMODE_LMAP) 518 State |= LANGMAP; 519 #ifdef USE_IM_CONTROL 520 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); 521 #endif 522 523 #ifdef FEAT_MOUSE 524 setmouse(); 525 #endif 526 #ifdef FEAT_CMDL_INFO 527 clear_showcmd(); 528 #endif 529 #ifdef FEAT_RIGHTLEFT 530 /* there is no reverse replace mode */ 531 revins_on = (State == INSERT && p_ri); 532 if (revins_on) 533 undisplay_dollar(); 534 revins_chars = 0; 535 revins_legal = 0; 536 revins_scol = -1; 537 #endif 538 if (!p_ek) 539 /* Disable bracketed paste mode, we won't recognize the escape 540 * sequences. */ 541 out_str(T_BD); 542 543 /* 544 * Handle restarting Insert mode. 545 * Don't do this for "CTRL-O ." (repeat an insert): In that case we get 546 * here with something in the stuff buffer. 547 */ 548 if (restart_edit != 0 && stuff_empty()) 549 { 550 #ifdef FEAT_MOUSE 551 /* 552 * After a paste we consider text typed to be part of the insert for 553 * the pasted text. You can backspace over the pasted text too. 554 */ 555 if (where_paste_started.lnum) 556 arrow_used = FALSE; 557 else 558 #endif 559 arrow_used = TRUE; 560 restart_edit = 0; 561 562 /* 563 * If the cursor was after the end-of-line before the CTRL-O and it is 564 * now at the end-of-line, put it after the end-of-line (this is not 565 * correct in very rare cases). 566 * Also do this if curswant is greater than the current virtual 567 * column. Eg after "^O$" or "^O80|". 568 */ 569 validate_virtcol(); 570 update_curswant(); 571 if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum) 572 || curwin->w_curswant > curwin->w_virtcol) 573 && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL) 574 { 575 if (ptr[1] == NUL) 576 ++curwin->w_cursor.col; 577 #ifdef FEAT_MBYTE 578 else if (has_mbyte) 579 { 580 i = (*mb_ptr2len)(ptr); 581 if (ptr[i] == NUL) 582 curwin->w_cursor.col += i; 583 } 584 #endif 585 } 586 ins_at_eol = FALSE; 587 } 588 else 589 arrow_used = FALSE; 590 591 /* we are in insert mode now, don't need to start it anymore */ 592 need_start_insertmode = FALSE; 593 594 /* Need to save the line for undo before inserting the first char. */ 595 ins_need_undo = TRUE; 596 597 #ifdef FEAT_MOUSE 598 where_paste_started.lnum = 0; 599 #endif 600 #ifdef FEAT_CINDENT 601 can_cindent = TRUE; 602 #endif 603 #ifdef FEAT_FOLDING 604 /* The cursor line is not in a closed fold, unless 'insertmode' is set or 605 * restarting. */ 606 if (!p_im && did_restart_edit == 0) 607 foldOpenCursor(); 608 #endif 609 610 /* 611 * If 'showmode' is set, show the current (insert/replace/..) mode. 612 * A warning message for changing a readonly file is given here, before 613 * actually changing anything. It's put after the mode, if any. 614 */ 615 i = 0; 616 if (p_smd && msg_silent == 0) 617 i = showmode(); 618 619 if (!p_im && did_restart_edit == 0) 620 change_warning(i == 0 ? 0 : i + 1); 621 622 #ifdef CURSOR_SHAPE 623 ui_cursor_shape(); /* may show different cursor shape */ 624 #endif 625 #ifdef FEAT_DIGRAPHS 626 do_digraph(-1); /* clear digraphs */ 627 #endif 628 629 /* 630 * Get the current length of the redo buffer, those characters have to be 631 * skipped if we want to get to the inserted characters. 632 */ 633 ptr = get_inserted(); 634 if (ptr == NULL) 635 new_insert_skip = 0; 636 else 637 { 638 new_insert_skip = (int)STRLEN(ptr); 639 vim_free(ptr); 640 } 641 642 old_indent = 0; 643 644 /* 645 * Main loop in Insert mode: repeat until Insert mode is left. 646 */ 647 for (;;) 648 { 649 #ifdef FEAT_RIGHTLEFT 650 if (!revins_legal) 651 revins_scol = -1; /* reset on illegal motions */ 652 else 653 revins_legal = 0; 654 #endif 655 if (arrow_used) /* don't repeat insert when arrow key used */ 656 count = 0; 657 658 if (update_Insstart_orig) 659 Insstart_orig = Insstart; 660 661 if (stop_insert_mode 662 #ifdef FEAT_INS_EXPAND 663 && !pum_visible() 664 #endif 665 ) 666 { 667 /* ":stopinsert" used or 'insertmode' reset */ 668 count = 0; 669 goto doESCkey; 670 } 671 672 /* set curwin->w_curswant for next K_DOWN or K_UP */ 673 if (!arrow_used) 674 curwin->w_set_curswant = TRUE; 675 676 /* If there is no typeahead may check for timestamps (e.g., for when a 677 * menu invoked a shell command). */ 678 if (stuff_empty()) 679 { 680 did_check_timestamps = FALSE; 681 if (need_check_timestamps) 682 check_timestamps(FALSE); 683 } 684 685 /* 686 * When emsg() was called msg_scroll will have been set. 687 */ 688 msg_scroll = FALSE; 689 690 #ifdef FEAT_GUI 691 /* When 'mousefocus' is set a mouse movement may have taken us to 692 * another window. "need_mouse_correct" may then be set because of an 693 * autocommand. */ 694 if (need_mouse_correct) 695 gui_mouse_correct(); 696 #endif 697 698 #ifdef FEAT_FOLDING 699 /* Open fold at the cursor line, according to 'foldopen'. */ 700 if (fdo_flags & FDO_INSERT) 701 foldOpenCursor(); 702 /* Close folds where the cursor isn't, according to 'foldclose' */ 703 if (!char_avail()) 704 foldCheckClose(); 705 #endif 706 707 /* 708 * If we inserted a character at the last position of the last line in 709 * the window, scroll the window one line up. This avoids an extra 710 * redraw. 711 * This is detected when the cursor column is smaller after inserting 712 * something. 713 * Don't do this when the topline changed already, it has 714 * already been adjusted (by insertchar() calling open_line())). 715 */ 716 if (curbuf->b_mod_set 717 && curwin->w_p_wrap 718 && !did_backspace 719 && curwin->w_topline == old_topline 720 #ifdef FEAT_DIFF 721 && curwin->w_topfill == old_topfill 722 #endif 723 ) 724 { 725 mincol = curwin->w_wcol; 726 validate_cursor_col(); 727 728 if ((int)curwin->w_wcol < mincol - curbuf->b_p_ts 729 && curwin->w_wrow == W_WINROW(curwin) 730 + curwin->w_height - 1 - p_so 731 && (curwin->w_cursor.lnum != curwin->w_topline 732 #ifdef FEAT_DIFF 733 || curwin->w_topfill > 0 734 #endif 735 )) 736 { 737 #ifdef FEAT_DIFF 738 if (curwin->w_topfill > 0) 739 --curwin->w_topfill; 740 else 741 #endif 742 #ifdef FEAT_FOLDING 743 if (hasFolding(curwin->w_topline, NULL, &old_topline)) 744 set_topline(curwin, old_topline + 1); 745 else 746 #endif 747 set_topline(curwin, curwin->w_topline + 1); 748 } 749 } 750 751 /* May need to adjust w_topline to show the cursor. */ 752 update_topline(); 753 754 did_backspace = FALSE; 755 756 validate_cursor(); /* may set must_redraw */ 757 758 /* 759 * Redraw the display when no characters are waiting. 760 * Also shows mode, ruler and positions cursor. 761 */ 762 ins_redraw(TRUE); 763 764 #ifdef FEAT_SCROLLBIND 765 if (curwin->w_p_scb) 766 do_check_scrollbind(TRUE); 767 #endif 768 769 #ifdef FEAT_CURSORBIND 770 if (curwin->w_p_crb) 771 do_check_cursorbind(); 772 #endif 773 update_curswant(); 774 old_topline = curwin->w_topline; 775 #ifdef FEAT_DIFF 776 old_topfill = curwin->w_topfill; 777 #endif 778 779 #ifdef USE_ON_FLY_SCROLL 780 dont_scroll = FALSE; /* allow scrolling here */ 781 #endif 782 783 /* 784 * Get a character for Insert mode. Ignore K_IGNORE. 785 */ 786 if (c != K_CURSORHOLD) 787 lastc = c; /* remember the previous char for CTRL-D */ 788 789 /* After using CTRL-G U the next cursor key will not break undo. */ 790 if (dont_sync_undo == MAYBE) 791 dont_sync_undo = TRUE; 792 else 793 dont_sync_undo = FALSE; 794 if (cmdchar == K_PS) 795 /* Got here from normal mode when bracketed paste started. */ 796 c = K_PS; 797 else 798 do 799 { 800 c = safe_vgetc(); 801 } while (c == K_IGNORE); 802 803 #ifdef FEAT_AUTOCMD 804 /* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */ 805 did_cursorhold = TRUE; 806 #endif 807 808 #ifdef FEAT_RIGHTLEFT 809 if (p_hkmap && KeyTyped) 810 c = hkmap(c); /* Hebrew mode mapping */ 811 #endif 812 #ifdef FEAT_FKMAP 813 if (p_fkmap && KeyTyped) 814 c = fkmap(c); /* Farsi mode mapping */ 815 #endif 816 817 #ifdef FEAT_INS_EXPAND 818 /* 819 * Special handling of keys while the popup menu is visible or wanted 820 * and the cursor is still in the completed word. Only when there is 821 * a match, skip this when no matches were found. 822 */ 823 if (compl_started 824 && pum_wanted() 825 && curwin->w_cursor.col >= compl_col 826 && (compl_shown_match == NULL 827 || compl_shown_match != compl_shown_match->cp_next)) 828 { 829 /* BS: Delete one character from "compl_leader". */ 830 if ((c == K_BS || c == Ctrl_H) 831 && curwin->w_cursor.col > compl_col 832 && (c = ins_compl_bs()) == NUL) 833 continue; 834 835 /* When no match was selected or it was edited. */ 836 if (!compl_used_match) 837 { 838 /* CTRL-L: Add one character from the current match to 839 * "compl_leader". Except when at the original match and 840 * there is nothing to add, CTRL-L works like CTRL-P then. */ 841 if (c == Ctrl_L 842 && (!CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode) 843 || (int)STRLEN(compl_shown_match->cp_str) 844 > curwin->w_cursor.col - compl_col)) 845 { 846 ins_compl_addfrommatch(); 847 continue; 848 } 849 850 /* A non-white character that fits in with the current 851 * completion: Add to "compl_leader". */ 852 if (ins_compl_accept_char(c)) 853 { 854 #ifdef FEAT_AUTOCMD 855 /* Trigger InsertCharPre. */ 856 char_u *str = do_insert_char_pre(c); 857 char_u *p; 858 859 if (str != NULL) 860 { 861 for (p = str; *p != NUL; MB_PTR_ADV(p)) 862 ins_compl_addleader(PTR2CHAR(p)); 863 vim_free(str); 864 } 865 else 866 #endif 867 ins_compl_addleader(c); 868 continue; 869 } 870 871 /* Pressing CTRL-Y selects the current match. When 872 * compl_enter_selects is set the Enter key does the same. */ 873 if ((c == Ctrl_Y || (compl_enter_selects 874 && (c == CAR || c == K_KENTER || c == NL))) 875 && stop_arrow() == OK) 876 { 877 ins_compl_delete(); 878 ins_compl_insert(FALSE); 879 } 880 } 881 } 882 883 /* Prepare for or stop CTRL-X mode. This doesn't do completion, but 884 * it does fix up the text when finishing completion. */ 885 compl_get_longest = FALSE; 886 if (ins_compl_prep(c)) 887 continue; 888 #endif 889 890 /* CTRL-\ CTRL-N goes to Normal mode, 891 * CTRL-\ CTRL-G goes to mode selected with 'insertmode', 892 * CTRL-\ CTRL-O is like CTRL-O but without moving the cursor. */ 893 if (c == Ctrl_BSL) 894 { 895 /* may need to redraw when no more chars available now */ 896 ins_redraw(FALSE); 897 ++no_mapping; 898 ++allow_keys; 899 c = plain_vgetc(); 900 --no_mapping; 901 --allow_keys; 902 if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O) 903 { 904 /* it's something else */ 905 vungetc(c); 906 c = Ctrl_BSL; 907 } 908 else if (c == Ctrl_G && p_im) 909 continue; 910 else 911 { 912 if (c == Ctrl_O) 913 { 914 ins_ctrl_o(); 915 ins_at_eol = FALSE; /* cursor keeps its column */ 916 nomove = TRUE; 917 } 918 count = 0; 919 goto doESCkey; 920 } 921 } 922 923 #ifdef FEAT_DIGRAPHS 924 c = do_digraph(c); 925 #endif 926 927 #ifdef FEAT_INS_EXPAND 928 if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE) 929 goto docomplete; 930 #endif 931 if (c == Ctrl_V || c == Ctrl_Q) 932 { 933 ins_ctrl_v(); 934 c = Ctrl_V; /* pretend CTRL-V is last typed character */ 935 continue; 936 } 937 938 #ifdef FEAT_CINDENT 939 if (cindent_on() 940 # ifdef FEAT_INS_EXPAND 941 && ctrl_x_mode == 0 942 # endif 943 ) 944 { 945 /* A key name preceded by a bang means this key is not to be 946 * inserted. Skip ahead to the re-indenting below. 947 * A key name preceded by a star means that indenting has to be 948 * done before inserting the key. */ 949 line_is_white = inindent(0); 950 if (in_cinkeys(c, '!', line_is_white)) 951 goto force_cindent; 952 if (can_cindent && in_cinkeys(c, '*', line_is_white) 953 && stop_arrow() == OK) 954 do_c_expr_indent(); 955 } 956 #endif 957 958 #ifdef FEAT_RIGHTLEFT 959 if (curwin->w_p_rl) 960 switch (c) 961 { 962 case K_LEFT: c = K_RIGHT; break; 963 case K_S_LEFT: c = K_S_RIGHT; break; 964 case K_C_LEFT: c = K_C_RIGHT; break; 965 case K_RIGHT: c = K_LEFT; break; 966 case K_S_RIGHT: c = K_S_LEFT; break; 967 case K_C_RIGHT: c = K_C_LEFT; break; 968 } 969 #endif 970 971 /* 972 * If 'keymodel' contains "startsel", may start selection. If it 973 * does, a CTRL-O and c will be stuffed, we need to get these 974 * characters. 975 */ 976 if (ins_start_select(c)) 977 continue; 978 979 /* 980 * The big switch to handle a character in insert mode. 981 */ 982 switch (c) 983 { 984 case ESC: /* End input mode */ 985 if (echeck_abbr(ESC + ABBR_OFF)) 986 break; 987 /* FALLTHROUGH */ 988 989 case Ctrl_C: /* End input mode */ 990 #ifdef FEAT_CMDWIN 991 if (c == Ctrl_C && cmdwin_type != 0) 992 { 993 /* Close the cmdline window. */ 994 cmdwin_result = K_IGNORE; 995 got_int = FALSE; /* don't stop executing autocommands et al. */ 996 nomove = TRUE; 997 goto doESCkey; 998 } 999 #endif 1000 1001 #ifdef UNIX 1002 do_intr: 1003 #endif 1004 /* when 'insertmode' set, and not halfway a mapping, don't leave 1005 * Insert mode */ 1006 if (goto_im()) 1007 { 1008 if (got_int) 1009 { 1010 (void)vgetc(); /* flush all buffers */ 1011 got_int = FALSE; 1012 } 1013 else 1014 vim_beep(BO_IM); 1015 break; 1016 } 1017 doESCkey: 1018 /* 1019 * This is the ONLY return from edit()! 1020 */ 1021 /* Always update o_lnum, so that a "CTRL-O ." that adds a line 1022 * still puts the cursor back after the inserted text. */ 1023 if (ins_at_eol && gchar_cursor() == NUL) 1024 o_lnum = curwin->w_cursor.lnum; 1025 1026 if (ins_esc(&count, cmdchar, nomove)) 1027 { 1028 #ifdef FEAT_AUTOCMD 1029 if (cmdchar != 'r' && cmdchar != 'v') 1030 apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, 1031 FALSE, curbuf); 1032 did_cursorhold = FALSE; 1033 #endif 1034 return (c == Ctrl_O); 1035 } 1036 continue; 1037 1038 case Ctrl_Z: /* suspend when 'insertmode' set */ 1039 if (!p_im) 1040 goto normalchar; /* insert CTRL-Z as normal char */ 1041 do_cmdline_cmd((char_u *)"stop"); 1042 #ifdef CURSOR_SHAPE 1043 ui_cursor_shape(); /* may need to update cursor shape */ 1044 #endif 1045 continue; 1046 1047 case Ctrl_O: /* execute one command */ 1048 #ifdef FEAT_COMPL_FUNC 1049 if (ctrl_x_mode == CTRL_X_OMNI) 1050 goto docomplete; 1051 #endif 1052 if (echeck_abbr(Ctrl_O + ABBR_OFF)) 1053 break; 1054 ins_ctrl_o(); 1055 1056 #ifdef FEAT_VIRTUALEDIT 1057 /* don't move the cursor left when 'virtualedit' has "onemore". */ 1058 if (ve_flags & VE_ONEMORE) 1059 { 1060 ins_at_eol = FALSE; 1061 nomove = TRUE; 1062 } 1063 #endif 1064 count = 0; 1065 goto doESCkey; 1066 1067 case K_INS: /* toggle insert/replace mode */ 1068 case K_KINS: 1069 ins_insert(replaceState); 1070 break; 1071 1072 case K_SELECT: /* end of Select mode mapping - ignore */ 1073 break; 1074 1075 case K_HELP: /* Help key works like <ESC> <Help> */ 1076 case K_F1: 1077 case K_XF1: 1078 stuffcharReadbuff(K_HELP); 1079 if (p_im) 1080 need_start_insertmode = TRUE; 1081 goto doESCkey; 1082 1083 #ifdef FEAT_NETBEANS_INTG 1084 case K_F21: /* NetBeans command */ 1085 ++no_mapping; /* don't map the next key hits */ 1086 i = plain_vgetc(); 1087 --no_mapping; 1088 netbeans_keycommand(i); 1089 break; 1090 #endif 1091 1092 case K_ZERO: /* Insert the previously inserted text. */ 1093 case NUL: 1094 case Ctrl_A: 1095 /* For ^@ the trailing ESC will end the insert, unless there is an 1096 * error. */ 1097 if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL 1098 && c != Ctrl_A && !p_im) 1099 goto doESCkey; /* quit insert mode */ 1100 inserted_space = FALSE; 1101 break; 1102 1103 case Ctrl_R: /* insert the contents of a register */ 1104 ins_reg(); 1105 auto_format(FALSE, TRUE); 1106 inserted_space = FALSE; 1107 break; 1108 1109 case Ctrl_G: /* commands starting with CTRL-G */ 1110 ins_ctrl_g(); 1111 break; 1112 1113 case Ctrl_HAT: /* switch input mode and/or langmap */ 1114 ins_ctrl_hat(); 1115 break; 1116 1117 #ifdef FEAT_RIGHTLEFT 1118 case Ctrl__: /* switch between languages */ 1119 if (!p_ari) 1120 goto normalchar; 1121 ins_ctrl_(); 1122 break; 1123 #endif 1124 1125 case Ctrl_D: /* Make indent one shiftwidth smaller. */ 1126 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) 1127 if (ctrl_x_mode == CTRL_X_PATH_DEFINES) 1128 goto docomplete; 1129 #endif 1130 /* FALLTHROUGH */ 1131 1132 case Ctrl_T: /* Make indent one shiftwidth greater. */ 1133 # ifdef FEAT_INS_EXPAND 1134 if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS) 1135 { 1136 if (has_compl_option(FALSE)) 1137 goto docomplete; 1138 break; 1139 } 1140 # endif 1141 ins_shift(c, lastc); 1142 auto_format(FALSE, TRUE); 1143 inserted_space = FALSE; 1144 break; 1145 1146 case K_DEL: /* delete character under the cursor */ 1147 case K_KDEL: 1148 ins_del(); 1149 auto_format(FALSE, TRUE); 1150 break; 1151 1152 case K_BS: /* delete character before the cursor */ 1153 case Ctrl_H: 1154 did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); 1155 auto_format(FALSE, TRUE); 1156 break; 1157 1158 case Ctrl_W: /* delete word before the cursor */ 1159 did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); 1160 auto_format(FALSE, TRUE); 1161 break; 1162 1163 case Ctrl_U: /* delete all inserted text in current line */ 1164 # ifdef FEAT_COMPL_FUNC 1165 /* CTRL-X CTRL-U completes with 'completefunc'. */ 1166 if (ctrl_x_mode == CTRL_X_FUNCTION) 1167 goto docomplete; 1168 # endif 1169 did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); 1170 auto_format(FALSE, TRUE); 1171 inserted_space = FALSE; 1172 break; 1173 1174 #ifdef FEAT_MOUSE 1175 case K_LEFTMOUSE: /* mouse keys */ 1176 case K_LEFTMOUSE_NM: 1177 case K_LEFTDRAG: 1178 case K_LEFTRELEASE: 1179 case K_LEFTRELEASE_NM: 1180 case K_MIDDLEMOUSE: 1181 case K_MIDDLEDRAG: 1182 case K_MIDDLERELEASE: 1183 case K_RIGHTMOUSE: 1184 case K_RIGHTDRAG: 1185 case K_RIGHTRELEASE: 1186 case K_X1MOUSE: 1187 case K_X1DRAG: 1188 case K_X1RELEASE: 1189 case K_X2MOUSE: 1190 case K_X2DRAG: 1191 case K_X2RELEASE: 1192 ins_mouse(c); 1193 break; 1194 1195 case K_MOUSEDOWN: /* Default action for scroll wheel up: scroll up */ 1196 ins_mousescroll(MSCR_DOWN); 1197 break; 1198 1199 case K_MOUSEUP: /* Default action for scroll wheel down: scroll down */ 1200 ins_mousescroll(MSCR_UP); 1201 break; 1202 1203 case K_MOUSELEFT: /* Scroll wheel left */ 1204 ins_mousescroll(MSCR_LEFT); 1205 break; 1206 1207 case K_MOUSERIGHT: /* Scroll wheel right */ 1208 ins_mousescroll(MSCR_RIGHT); 1209 break; 1210 #endif 1211 case K_PS: 1212 bracketed_paste(PASTE_INSERT, FALSE, NULL); 1213 if (cmdchar == K_PS) 1214 /* invoked from normal mode, bail out */ 1215 goto doESCkey; 1216 break; 1217 case K_PE: 1218 /* Got K_PE without K_PS, ignore. */ 1219 break; 1220 1221 #ifdef FEAT_GUI_TABLINE 1222 case K_TABLINE: 1223 case K_TABMENU: 1224 ins_tabline(c); 1225 break; 1226 #endif 1227 1228 case K_IGNORE: /* Something mapped to nothing */ 1229 break; 1230 1231 #ifdef FEAT_AUTOCMD 1232 case K_CURSORHOLD: /* Didn't type something for a while. */ 1233 apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf); 1234 did_cursorhold = TRUE; 1235 break; 1236 #endif 1237 1238 #ifdef FEAT_GUI_W32 1239 /* On Win32 ignore <M-F4>, we get it when closing the window was 1240 * cancelled. */ 1241 case K_F4: 1242 if (mod_mask != MOD_MASK_ALT) 1243 goto normalchar; 1244 break; 1245 #endif 1246 1247 #ifdef FEAT_GUI 1248 case K_VER_SCROLLBAR: 1249 ins_scroll(); 1250 break; 1251 1252 case K_HOR_SCROLLBAR: 1253 ins_horscroll(); 1254 break; 1255 #endif 1256 1257 case K_HOME: /* <Home> */ 1258 case K_KHOME: 1259 case K_S_HOME: 1260 case K_C_HOME: 1261 ins_home(c); 1262 break; 1263 1264 case K_END: /* <End> */ 1265 case K_KEND: 1266 case K_S_END: 1267 case K_C_END: 1268 ins_end(c); 1269 break; 1270 1271 case K_LEFT: /* <Left> */ 1272 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1273 ins_s_left(); 1274 else 1275 ins_left(dont_sync_undo == FALSE); 1276 break; 1277 1278 case K_S_LEFT: /* <S-Left> */ 1279 case K_C_LEFT: 1280 ins_s_left(); 1281 break; 1282 1283 case K_RIGHT: /* <Right> */ 1284 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1285 ins_s_right(); 1286 else 1287 ins_right(dont_sync_undo == FALSE); 1288 break; 1289 1290 case K_S_RIGHT: /* <S-Right> */ 1291 case K_C_RIGHT: 1292 ins_s_right(); 1293 break; 1294 1295 case K_UP: /* <Up> */ 1296 #ifdef FEAT_INS_EXPAND 1297 if (pum_visible()) 1298 goto docomplete; 1299 #endif 1300 if (mod_mask & MOD_MASK_SHIFT) 1301 ins_pageup(); 1302 else 1303 ins_up(FALSE); 1304 break; 1305 1306 case K_S_UP: /* <S-Up> */ 1307 case K_PAGEUP: 1308 case K_KPAGEUP: 1309 #ifdef FEAT_INS_EXPAND 1310 if (pum_visible()) 1311 goto docomplete; 1312 #endif 1313 ins_pageup(); 1314 break; 1315 1316 case K_DOWN: /* <Down> */ 1317 #ifdef FEAT_INS_EXPAND 1318 if (pum_visible()) 1319 goto docomplete; 1320 #endif 1321 if (mod_mask & MOD_MASK_SHIFT) 1322 ins_pagedown(); 1323 else 1324 ins_down(FALSE); 1325 break; 1326 1327 case K_S_DOWN: /* <S-Down> */ 1328 case K_PAGEDOWN: 1329 case K_KPAGEDOWN: 1330 #ifdef FEAT_INS_EXPAND 1331 if (pum_visible()) 1332 goto docomplete; 1333 #endif 1334 ins_pagedown(); 1335 break; 1336 1337 #ifdef FEAT_DND 1338 case K_DROP: /* drag-n-drop event */ 1339 ins_drop(); 1340 break; 1341 #endif 1342 1343 case K_S_TAB: /* When not mapped, use like a normal TAB */ 1344 c = TAB; 1345 /* FALLTHROUGH */ 1346 1347 case TAB: /* TAB or Complete patterns along path */ 1348 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) 1349 if (ctrl_x_mode == CTRL_X_PATH_PATTERNS) 1350 goto docomplete; 1351 #endif 1352 inserted_space = FALSE; 1353 if (ins_tab()) 1354 goto normalchar; /* insert TAB as a normal char */ 1355 auto_format(FALSE, TRUE); 1356 break; 1357 1358 case K_KENTER: /* <Enter> */ 1359 c = CAR; 1360 /* FALLTHROUGH */ 1361 case CAR: 1362 case NL: 1363 #if defined(FEAT_QUICKFIX) 1364 /* In a quickfix window a <CR> jumps to the error under the 1365 * cursor. */ 1366 if (bt_quickfix(curbuf) && c == CAR) 1367 { 1368 if (curwin->w_llist_ref == NULL) /* quickfix window */ 1369 do_cmdline_cmd((char_u *)".cc"); 1370 else /* location list window */ 1371 do_cmdline_cmd((char_u *)".ll"); 1372 break; 1373 } 1374 #endif 1375 #ifdef FEAT_CMDWIN 1376 if (cmdwin_type != 0) 1377 { 1378 /* Execute the command in the cmdline window. */ 1379 cmdwin_result = CAR; 1380 goto doESCkey; 1381 } 1382 #endif 1383 if (ins_eol(c) && !p_im) 1384 goto doESCkey; /* out of memory */ 1385 auto_format(FALSE, FALSE); 1386 inserted_space = FALSE; 1387 break; 1388 1389 #if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND) 1390 case Ctrl_K: /* digraph or keyword completion */ 1391 # ifdef FEAT_INS_EXPAND 1392 if (ctrl_x_mode == CTRL_X_DICTIONARY) 1393 { 1394 if (has_compl_option(TRUE)) 1395 goto docomplete; 1396 break; 1397 } 1398 # endif 1399 # ifdef FEAT_DIGRAPHS 1400 c = ins_digraph(); 1401 if (c == NUL) 1402 break; 1403 # endif 1404 goto normalchar; 1405 #endif 1406 1407 #ifdef FEAT_INS_EXPAND 1408 case Ctrl_X: /* Enter CTRL-X mode */ 1409 ins_ctrl_x(); 1410 break; 1411 1412 case Ctrl_RSB: /* Tag name completion after ^X */ 1413 if (ctrl_x_mode != CTRL_X_TAGS) 1414 goto normalchar; 1415 goto docomplete; 1416 1417 case Ctrl_F: /* File name completion after ^X */ 1418 if (ctrl_x_mode != CTRL_X_FILES) 1419 goto normalchar; 1420 goto docomplete; 1421 1422 case 's': /* Spelling completion after ^X */ 1423 case Ctrl_S: 1424 if (ctrl_x_mode != CTRL_X_SPELL) 1425 goto normalchar; 1426 goto docomplete; 1427 #endif 1428 1429 case Ctrl_L: /* Whole line completion after ^X */ 1430 #ifdef FEAT_INS_EXPAND 1431 if (ctrl_x_mode != CTRL_X_WHOLE_LINE) 1432 #endif 1433 { 1434 /* CTRL-L with 'insertmode' set: Leave Insert mode */ 1435 if (p_im) 1436 { 1437 if (echeck_abbr(Ctrl_L + ABBR_OFF)) 1438 break; 1439 goto doESCkey; 1440 } 1441 goto normalchar; 1442 } 1443 #ifdef FEAT_INS_EXPAND 1444 /* FALLTHROUGH */ 1445 1446 case Ctrl_P: /* Do previous/next pattern completion */ 1447 case Ctrl_N: 1448 /* if 'complete' is empty then plain ^P is no longer special, 1449 * but it is under other ^X modes */ 1450 if (*curbuf->b_p_cpt == NUL 1451 && ctrl_x_mode != 0 1452 && !(compl_cont_status & CONT_LOCAL)) 1453 goto normalchar; 1454 1455 docomplete: 1456 compl_busy = TRUE; 1457 #ifdef FEAT_FOLDING 1458 disable_fold_update++; /* don't redraw folds here */ 1459 #endif 1460 if (ins_complete(c, TRUE) == FAIL) 1461 compl_cont_status = 0; 1462 #ifdef FEAT_FOLDING 1463 disable_fold_update--; 1464 #endif 1465 compl_busy = FALSE; 1466 break; 1467 #endif /* FEAT_INS_EXPAND */ 1468 1469 case Ctrl_Y: /* copy from previous line or scroll down */ 1470 case Ctrl_E: /* copy from next line or scroll up */ 1471 c = ins_ctrl_ey(c); 1472 break; 1473 1474 default: 1475 #ifdef UNIX 1476 if (c == intr_char) /* special interrupt char */ 1477 goto do_intr; 1478 #endif 1479 1480 normalchar: 1481 /* 1482 * Insert a normal character. 1483 */ 1484 #ifdef FEAT_AUTOCMD 1485 if (!p_paste) 1486 { 1487 /* Trigger InsertCharPre. */ 1488 char_u *str = do_insert_char_pre(c); 1489 char_u *p; 1490 1491 if (str != NULL) 1492 { 1493 if (*str != NUL && stop_arrow() != FAIL) 1494 { 1495 /* Insert the new value of v:char literally. */ 1496 for (p = str; *p != NUL; MB_PTR_ADV(p)) 1497 { 1498 c = PTR2CHAR(p); 1499 if (c == CAR || c == K_KENTER || c == NL) 1500 ins_eol(c); 1501 else 1502 ins_char(c); 1503 } 1504 AppendToRedobuffLit(str, -1); 1505 } 1506 vim_free(str); 1507 c = NUL; 1508 } 1509 1510 /* If the new value is already inserted or an empty string 1511 * then don't insert any character. */ 1512 if (c == NUL) 1513 break; 1514 } 1515 #endif 1516 #ifdef FEAT_SMARTINDENT 1517 /* Try to perform smart-indenting. */ 1518 ins_try_si(c); 1519 #endif 1520 1521 if (c == ' ') 1522 { 1523 inserted_space = TRUE; 1524 #ifdef FEAT_CINDENT 1525 if (inindent(0)) 1526 can_cindent = FALSE; 1527 #endif 1528 if (Insstart_blank_vcol == MAXCOL 1529 && curwin->w_cursor.lnum == Insstart.lnum) 1530 Insstart_blank_vcol = get_nolist_virtcol(); 1531 } 1532 1533 /* Insert a normal character and check for abbreviations on a 1534 * special character. Let CTRL-] expand abbreviations without 1535 * inserting it. */ 1536 if (vim_iswordc(c) || (!echeck_abbr( 1537 #ifdef FEAT_MBYTE 1538 /* Add ABBR_OFF for characters above 0x100, this is 1539 * what check_abbr() expects. */ 1540 (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : 1541 #endif 1542 c) && c != Ctrl_RSB)) 1543 { 1544 insert_special(c, FALSE, FALSE); 1545 #ifdef FEAT_RIGHTLEFT 1546 revins_legal++; 1547 revins_chars++; 1548 #endif 1549 } 1550 1551 auto_format(FALSE, TRUE); 1552 1553 #ifdef FEAT_FOLDING 1554 /* When inserting a character the cursor line must never be in a 1555 * closed fold. */ 1556 foldOpenCursor(); 1557 #endif 1558 break; 1559 } /* end of switch (c) */ 1560 1561 #ifdef FEAT_AUTOCMD 1562 /* If typed something may trigger CursorHoldI again. */ 1563 if (c != K_CURSORHOLD 1564 # ifdef FEAT_COMPL_FUNC 1565 /* but not in CTRL-X mode, a script can't restore the state */ 1566 && ctrl_x_mode == 0 1567 # endif 1568 ) 1569 did_cursorhold = FALSE; 1570 #endif 1571 1572 /* If the cursor was moved we didn't just insert a space */ 1573 if (arrow_used) 1574 inserted_space = FALSE; 1575 1576 #ifdef FEAT_CINDENT 1577 if (can_cindent && cindent_on() 1578 # ifdef FEAT_INS_EXPAND 1579 && ctrl_x_mode == 0 1580 # endif 1581 ) 1582 { 1583 force_cindent: 1584 /* 1585 * Indent now if a key was typed that is in 'cinkeys'. 1586 */ 1587 if (in_cinkeys(c, ' ', line_is_white)) 1588 { 1589 if (stop_arrow() == OK) 1590 /* re-indent the current line */ 1591 do_c_expr_indent(); 1592 } 1593 } 1594 #endif /* FEAT_CINDENT */ 1595 1596 } /* for (;;) */ 1597 /* NOTREACHED */ 1598 } 1599 1600 /* 1601 * Redraw for Insert mode. 1602 * This is postponed until getting the next character to make '$' in the 'cpo' 1603 * option work correctly. 1604 * Only redraw when there are no characters available. This speeds up 1605 * inserting sequences of characters (e.g., for CTRL-R). 1606 */ 1607 static void 1608 ins_redraw( 1609 int ready UNUSED) /* not busy with something */ 1610 { 1611 #ifdef FEAT_CONCEAL 1612 linenr_T conceal_old_cursor_line = 0; 1613 linenr_T conceal_new_cursor_line = 0; 1614 int conceal_update_lines = FALSE; 1615 #endif 1616 1617 if (char_avail()) 1618 return; 1619 1620 #if defined(FEAT_AUTOCMD) || defined(FEAT_CONCEAL) 1621 /* Trigger CursorMoved if the cursor moved. Not when the popup menu is 1622 * visible, the command might delete it. */ 1623 if (ready && ( 1624 # ifdef FEAT_AUTOCMD 1625 has_cursormovedI() 1626 # endif 1627 # if defined(FEAT_AUTOCMD) && defined(FEAT_CONCEAL) 1628 || 1629 # endif 1630 # ifdef FEAT_CONCEAL 1631 curwin->w_p_cole > 0 1632 # endif 1633 ) 1634 # ifdef FEAT_AUTOCMD 1635 && !EQUAL_POS(last_cursormoved, curwin->w_cursor) 1636 # endif 1637 # ifdef FEAT_INS_EXPAND 1638 && !pum_visible() 1639 # endif 1640 ) 1641 { 1642 # ifdef FEAT_SYN_HL 1643 /* Need to update the screen first, to make sure syntax 1644 * highlighting is correct after making a change (e.g., inserting 1645 * a "(". The autocommand may also require a redraw, so it's done 1646 * again below, unfortunately. */ 1647 if (syntax_present(curwin) && must_redraw) 1648 update_screen(0); 1649 # endif 1650 # ifdef FEAT_AUTOCMD 1651 if (has_cursormovedI()) 1652 { 1653 /* Make sure curswant is correct, an autocommand may call 1654 * getcurpos(). */ 1655 update_curswant(); 1656 apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf); 1657 } 1658 # endif 1659 # ifdef FEAT_CONCEAL 1660 if (curwin->w_p_cole > 0) 1661 { 1662 # ifdef FEAT_AUTOCMD 1663 conceal_old_cursor_line = last_cursormoved.lnum; 1664 # endif 1665 conceal_new_cursor_line = curwin->w_cursor.lnum; 1666 conceal_update_lines = TRUE; 1667 } 1668 # endif 1669 # ifdef FEAT_AUTOCMD 1670 last_cursormoved = curwin->w_cursor; 1671 # endif 1672 } 1673 #endif 1674 1675 #ifdef FEAT_AUTOCMD 1676 /* Trigger TextChangedI if b_changedtick differs. */ 1677 if (ready && has_textchangedI() 1678 && last_changedtick != CHANGEDTICK(curbuf) 1679 # ifdef FEAT_INS_EXPAND 1680 && !pum_visible() 1681 # endif 1682 ) 1683 { 1684 if (last_changedtick_buf == curbuf) 1685 apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); 1686 last_changedtick_buf = curbuf; 1687 last_changedtick = CHANGEDTICK(curbuf); 1688 } 1689 #endif 1690 1691 if (must_redraw) 1692 update_screen(0); 1693 else if (clear_cmdline || redraw_cmdline) 1694 showmode(); /* clear cmdline and show mode */ 1695 # if defined(FEAT_CONCEAL) 1696 if ((conceal_update_lines 1697 && (conceal_old_cursor_line != conceal_new_cursor_line 1698 || conceal_cursor_line(curwin))) 1699 || need_cursor_line_redraw) 1700 { 1701 if (conceal_old_cursor_line != conceal_new_cursor_line) 1702 update_single_line(curwin, conceal_old_cursor_line); 1703 update_single_line(curwin, conceal_new_cursor_line == 0 1704 ? curwin->w_cursor.lnum : conceal_new_cursor_line); 1705 curwin->w_valid &= ~VALID_CROW; 1706 } 1707 # endif 1708 showruler(FALSE); 1709 setcursor(); 1710 emsg_on_display = FALSE; /* may remove error message now */ 1711 } 1712 1713 /* 1714 * Handle a CTRL-V or CTRL-Q typed in Insert mode. 1715 */ 1716 static void 1717 ins_ctrl_v(void) 1718 { 1719 int c; 1720 int did_putchar = FALSE; 1721 1722 /* may need to redraw when no more chars available now */ 1723 ins_redraw(FALSE); 1724 1725 if (redrawing() && !char_avail()) 1726 { 1727 edit_putchar('^', TRUE); 1728 did_putchar = TRUE; 1729 } 1730 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ 1731 1732 #ifdef FEAT_CMDL_INFO 1733 add_to_showcmd_c(Ctrl_V); 1734 #endif 1735 1736 c = get_literal(); 1737 if (did_putchar) 1738 /* when the line fits in 'columns' the '^' is at the start of the next 1739 * line and will not removed by the redraw */ 1740 edit_unputchar(); 1741 #ifdef FEAT_CMDL_INFO 1742 clear_showcmd(); 1743 #endif 1744 insert_special(c, FALSE, TRUE); 1745 #ifdef FEAT_RIGHTLEFT 1746 revins_chars++; 1747 revins_legal++; 1748 #endif 1749 } 1750 1751 /* 1752 * Put a character directly onto the screen. It's not stored in a buffer. 1753 * Used while handling CTRL-K, CTRL-V, etc. in Insert mode. 1754 */ 1755 static int pc_status; 1756 #define PC_STATUS_UNSET 0 /* pc_bytes was not set */ 1757 #define PC_STATUS_RIGHT 1 /* right halve of double-wide char */ 1758 #define PC_STATUS_LEFT 2 /* left halve of double-wide char */ 1759 #define PC_STATUS_SET 3 /* pc_bytes was filled */ 1760 static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */ 1761 static int pc_attr; 1762 static int pc_row; 1763 static int pc_col; 1764 1765 void 1766 edit_putchar(int c, int highlight) 1767 { 1768 int attr; 1769 1770 if (ScreenLines != NULL) 1771 { 1772 update_topline(); /* just in case w_topline isn't valid */ 1773 validate_cursor(); 1774 if (highlight) 1775 attr = HL_ATTR(HLF_8); 1776 else 1777 attr = 0; 1778 pc_row = W_WINROW(curwin) + curwin->w_wrow; 1779 pc_col = curwin->w_wincol; 1780 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE) 1781 pc_status = PC_STATUS_UNSET; 1782 #endif 1783 #ifdef FEAT_RIGHTLEFT 1784 if (curwin->w_p_rl) 1785 { 1786 pc_col += curwin->w_width - 1 - curwin->w_wcol; 1787 # ifdef FEAT_MBYTE 1788 if (has_mbyte) 1789 { 1790 int fix_col = mb_fix_col(pc_col, pc_row); 1791 1792 if (fix_col != pc_col) 1793 { 1794 screen_putchar(' ', pc_row, fix_col, attr); 1795 --curwin->w_wcol; 1796 pc_status = PC_STATUS_RIGHT; 1797 } 1798 } 1799 # endif 1800 } 1801 else 1802 #endif 1803 { 1804 pc_col += curwin->w_wcol; 1805 #ifdef FEAT_MBYTE 1806 if (mb_lefthalve(pc_row, pc_col)) 1807 pc_status = PC_STATUS_LEFT; 1808 #endif 1809 } 1810 1811 /* save the character to be able to put it back */ 1812 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE) 1813 if (pc_status == PC_STATUS_UNSET) 1814 #endif 1815 { 1816 screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr); 1817 pc_status = PC_STATUS_SET; 1818 } 1819 screen_putchar(c, pc_row, pc_col, attr); 1820 } 1821 } 1822 1823 /* 1824 * Undo the previous edit_putchar(). 1825 */ 1826 void 1827 edit_unputchar(void) 1828 { 1829 if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) 1830 { 1831 #if defined(FEAT_MBYTE) 1832 if (pc_status == PC_STATUS_RIGHT) 1833 ++curwin->w_wcol; 1834 if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) 1835 redrawWinline(curwin->w_cursor.lnum, FALSE); 1836 else 1837 #endif 1838 screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); 1839 } 1840 } 1841 1842 /* 1843 * Called when p_dollar is set: display a '$' at the end of the changed text 1844 * Only works when cursor is in the line that changes. 1845 */ 1846 void 1847 display_dollar(colnr_T col) 1848 { 1849 colnr_T save_col; 1850 1851 if (!redrawing()) 1852 return; 1853 1854 cursor_off(); 1855 save_col = curwin->w_cursor.col; 1856 curwin->w_cursor.col = col; 1857 #ifdef FEAT_MBYTE 1858 if (has_mbyte) 1859 { 1860 char_u *p; 1861 1862 /* If on the last byte of a multi-byte move to the first byte. */ 1863 p = ml_get_curline(); 1864 curwin->w_cursor.col -= (*mb_head_off)(p, p + col); 1865 } 1866 #endif 1867 curs_columns(FALSE); /* recompute w_wrow and w_wcol */ 1868 if (curwin->w_wcol < curwin->w_width) 1869 { 1870 edit_putchar('$', FALSE); 1871 dollar_vcol = curwin->w_virtcol; 1872 } 1873 curwin->w_cursor.col = save_col; 1874 } 1875 1876 /* 1877 * Call this function before moving the cursor from the normal insert position 1878 * in insert mode. 1879 */ 1880 static void 1881 undisplay_dollar(void) 1882 { 1883 if (dollar_vcol >= 0) 1884 { 1885 dollar_vcol = -1; 1886 redrawWinline(curwin->w_cursor.lnum, FALSE); 1887 } 1888 } 1889 1890 /* 1891 * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D). 1892 * Keep the cursor on the same character. 1893 * type == INDENT_INC increase indent (for CTRL-T or <Tab>) 1894 * type == INDENT_DEC decrease indent (for CTRL-D) 1895 * type == INDENT_SET set indent to "amount" 1896 * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec). 1897 */ 1898 void 1899 change_indent( 1900 int type, 1901 int amount, 1902 int round, 1903 int replaced, /* replaced character, put on replace stack */ 1904 int call_changed_bytes) /* call changed_bytes() */ 1905 { 1906 int vcol; 1907 int last_vcol; 1908 int insstart_less; /* reduction for Insstart.col */ 1909 int new_cursor_col; 1910 int i; 1911 char_u *ptr; 1912 int save_p_list; 1913 int start_col; 1914 colnr_T vc; 1915 #ifdef FEAT_VREPLACE 1916 colnr_T orig_col = 0; /* init for GCC */ 1917 char_u *new_line, *orig_line = NULL; /* init for GCC */ 1918 1919 /* VREPLACE mode needs to know what the line was like before changing */ 1920 if (State & VREPLACE_FLAG) 1921 { 1922 orig_line = vim_strsave(ml_get_curline()); /* Deal with NULL below */ 1923 orig_col = curwin->w_cursor.col; 1924 } 1925 #endif 1926 1927 /* for the following tricks we don't want list mode */ 1928 save_p_list = curwin->w_p_list; 1929 curwin->w_p_list = FALSE; 1930 vc = getvcol_nolist(&curwin->w_cursor); 1931 vcol = vc; 1932 1933 /* 1934 * For Replace mode we need to fix the replace stack later, which is only 1935 * possible when the cursor is in the indent. Remember the number of 1936 * characters before the cursor if it's possible. 1937 */ 1938 start_col = curwin->w_cursor.col; 1939 1940 /* determine offset from first non-blank */ 1941 new_cursor_col = curwin->w_cursor.col; 1942 beginline(BL_WHITE); 1943 new_cursor_col -= curwin->w_cursor.col; 1944 1945 insstart_less = curwin->w_cursor.col; 1946 1947 /* 1948 * If the cursor is in the indent, compute how many screen columns the 1949 * cursor is to the left of the first non-blank. 1950 */ 1951 if (new_cursor_col < 0) 1952 vcol = get_indent() - vcol; 1953 1954 if (new_cursor_col > 0) /* can't fix replace stack */ 1955 start_col = -1; 1956 1957 /* 1958 * Set the new indent. The cursor will be put on the first non-blank. 1959 */ 1960 if (type == INDENT_SET) 1961 (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0); 1962 else 1963 { 1964 #ifdef FEAT_VREPLACE 1965 int save_State = State; 1966 1967 /* Avoid being called recursively. */ 1968 if (State & VREPLACE_FLAG) 1969 State = INSERT; 1970 #endif 1971 shift_line(type == INDENT_DEC, round, 1, call_changed_bytes); 1972 #ifdef FEAT_VREPLACE 1973 State = save_State; 1974 #endif 1975 } 1976 insstart_less -= curwin->w_cursor.col; 1977 1978 /* 1979 * Try to put cursor on same character. 1980 * If the cursor is at or after the first non-blank in the line, 1981 * compute the cursor column relative to the column of the first 1982 * non-blank character. 1983 * If we are not in insert mode, leave the cursor on the first non-blank. 1984 * If the cursor is before the first non-blank, position it relative 1985 * to the first non-blank, counted in screen columns. 1986 */ 1987 if (new_cursor_col >= 0) 1988 { 1989 /* 1990 * When changing the indent while the cursor is touching it, reset 1991 * Insstart_col to 0. 1992 */ 1993 if (new_cursor_col == 0) 1994 insstart_less = MAXCOL; 1995 new_cursor_col += curwin->w_cursor.col; 1996 } 1997 else if (!(State & INSERT)) 1998 new_cursor_col = curwin->w_cursor.col; 1999 else 2000 { 2001 /* 2002 * Compute the screen column where the cursor should be. 2003 */ 2004 vcol = get_indent() - vcol; 2005 curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol); 2006 2007 /* 2008 * Advance the cursor until we reach the right screen column. 2009 */ 2010 vcol = last_vcol = 0; 2011 new_cursor_col = -1; 2012 ptr = ml_get_curline(); 2013 while (vcol <= (int)curwin->w_virtcol) 2014 { 2015 last_vcol = vcol; 2016 #ifdef FEAT_MBYTE 2017 if (has_mbyte && new_cursor_col >= 0) 2018 new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col); 2019 else 2020 #endif 2021 ++new_cursor_col; 2022 vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol); 2023 } 2024 vcol = last_vcol; 2025 2026 /* 2027 * May need to insert spaces to be able to position the cursor on 2028 * the right screen column. 2029 */ 2030 if (vcol != (int)curwin->w_virtcol) 2031 { 2032 curwin->w_cursor.col = (colnr_T)new_cursor_col; 2033 i = (int)curwin->w_virtcol - vcol; 2034 ptr = alloc((unsigned)(i + 1)); 2035 if (ptr != NULL) 2036 { 2037 new_cursor_col += i; 2038 ptr[i] = NUL; 2039 while (--i >= 0) 2040 ptr[i] = ' '; 2041 ins_str(ptr); 2042 vim_free(ptr); 2043 } 2044 } 2045 2046 /* 2047 * When changing the indent while the cursor is in it, reset 2048 * Insstart_col to 0. 2049 */ 2050 insstart_less = MAXCOL; 2051 } 2052 2053 curwin->w_p_list = save_p_list; 2054 2055 if (new_cursor_col <= 0) 2056 curwin->w_cursor.col = 0; 2057 else 2058 curwin->w_cursor.col = (colnr_T)new_cursor_col; 2059 curwin->w_set_curswant = TRUE; 2060 changed_cline_bef_curs(); 2061 2062 /* 2063 * May have to adjust the start of the insert. 2064 */ 2065 if (State & INSERT) 2066 { 2067 if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0) 2068 { 2069 if ((int)Insstart.col <= insstart_less) 2070 Insstart.col = 0; 2071 else 2072 Insstart.col -= insstart_less; 2073 } 2074 if ((int)ai_col <= insstart_less) 2075 ai_col = 0; 2076 else 2077 ai_col -= insstart_less; 2078 } 2079 2080 /* 2081 * For REPLACE mode, may have to fix the replace stack, if it's possible. 2082 * If the number of characters before the cursor decreased, need to pop a 2083 * few characters from the replace stack. 2084 * If the number of characters before the cursor increased, need to push a 2085 * few NULs onto the replace stack. 2086 */ 2087 if (REPLACE_NORMAL(State) && start_col >= 0) 2088 { 2089 while (start_col > (int)curwin->w_cursor.col) 2090 { 2091 replace_join(0); /* remove a NUL from the replace stack */ 2092 --start_col; 2093 } 2094 while (start_col < (int)curwin->w_cursor.col || replaced) 2095 { 2096 replace_push(NUL); 2097 if (replaced) 2098 { 2099 replace_push(replaced); 2100 replaced = NUL; 2101 } 2102 ++start_col; 2103 } 2104 } 2105 2106 #ifdef FEAT_VREPLACE 2107 /* 2108 * For VREPLACE mode, we also have to fix the replace stack. In this case 2109 * it is always possible because we backspace over the whole line and then 2110 * put it back again the way we wanted it. 2111 */ 2112 if (State & VREPLACE_FLAG) 2113 { 2114 /* If orig_line didn't allocate, just return. At least we did the job, 2115 * even if you can't backspace. */ 2116 if (orig_line == NULL) 2117 return; 2118 2119 /* Save new line */ 2120 new_line = vim_strsave(ml_get_curline()); 2121 if (new_line == NULL) 2122 return; 2123 2124 /* We only put back the new line up to the cursor */ 2125 new_line[curwin->w_cursor.col] = NUL; 2126 2127 /* Put back original line */ 2128 ml_replace(curwin->w_cursor.lnum, orig_line, FALSE); 2129 curwin->w_cursor.col = orig_col; 2130 2131 /* Backspace from cursor to start of line */ 2132 backspace_until_column(0); 2133 2134 /* Insert new stuff into line again */ 2135 ins_bytes(new_line); 2136 2137 vim_free(new_line); 2138 } 2139 #endif 2140 } 2141 2142 /* 2143 * Truncate the space at the end of a line. This is to be used only in an 2144 * insert mode. It handles fixing the replace stack for REPLACE and VREPLACE 2145 * modes. 2146 */ 2147 void 2148 truncate_spaces(char_u *line) 2149 { 2150 int i; 2151 2152 /* find start of trailing white space */ 2153 for (i = (int)STRLEN(line) - 1; i >= 0 && VIM_ISWHITE(line[i]); i--) 2154 { 2155 if (State & REPLACE_FLAG) 2156 replace_join(0); /* remove a NUL from the replace stack */ 2157 } 2158 line[i + 1] = NUL; 2159 } 2160 2161 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \ 2162 || defined(FEAT_COMMENTS) || defined(PROTO) 2163 /* 2164 * Backspace the cursor until the given column. Handles REPLACE and VREPLACE 2165 * modes correctly. May also be used when not in insert mode at all. 2166 * Will attempt not to go before "col" even when there is a composing 2167 * character. 2168 */ 2169 void 2170 backspace_until_column(int col) 2171 { 2172 while ((int)curwin->w_cursor.col > col) 2173 { 2174 curwin->w_cursor.col--; 2175 if (State & REPLACE_FLAG) 2176 replace_do_bs(col); 2177 else if (!del_char_after_col(col)) 2178 break; 2179 } 2180 } 2181 #endif 2182 2183 /* 2184 * Like del_char(), but make sure not to go before column "limit_col". 2185 * Only matters when there are composing characters. 2186 * Return TRUE when something was deleted. 2187 */ 2188 static int 2189 del_char_after_col(int limit_col UNUSED) 2190 { 2191 #ifdef FEAT_MBYTE 2192 if (enc_utf8 && limit_col >= 0) 2193 { 2194 colnr_T ecol = curwin->w_cursor.col + 1; 2195 2196 /* Make sure the cursor is at the start of a character, but 2197 * skip forward again when going too far back because of a 2198 * composing character. */ 2199 mb_adjust_cursor(); 2200 while (curwin->w_cursor.col < (colnr_T)limit_col) 2201 { 2202 int l = utf_ptr2len(ml_get_cursor()); 2203 2204 if (l == 0) /* end of line */ 2205 break; 2206 curwin->w_cursor.col += l; 2207 } 2208 if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol) 2209 return FALSE; 2210 del_bytes((long)((int)ecol - curwin->w_cursor.col), FALSE, TRUE); 2211 } 2212 else 2213 #endif 2214 (void)del_char(FALSE); 2215 return TRUE; 2216 } 2217 2218 #if defined(FEAT_INS_EXPAND) || defined(PROTO) 2219 /* 2220 * CTRL-X pressed in Insert mode. 2221 */ 2222 static void 2223 ins_ctrl_x(void) 2224 { 2225 /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X 2226 * CTRL-V works like CTRL-N */ 2227 if (ctrl_x_mode != CTRL_X_CMDLINE) 2228 { 2229 /* if the next ^X<> won't ADD nothing, then reset 2230 * compl_cont_status */ 2231 if (compl_cont_status & CONT_N_ADDS) 2232 compl_cont_status |= CONT_INTRPT; 2233 else 2234 compl_cont_status = 0; 2235 /* We're not sure which CTRL-X mode it will be yet */ 2236 ctrl_x_mode = CTRL_X_NOT_DEFINED_YET; 2237 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); 2238 edit_submode_pre = NULL; 2239 showmode(); 2240 } 2241 } 2242 2243 /* 2244 * Return TRUE if the 'dict' or 'tsr' option can be used. 2245 */ 2246 static int 2247 has_compl_option(int dict_opt) 2248 { 2249 if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL 2250 # ifdef FEAT_SPELL 2251 && !curwin->w_p_spell 2252 # endif 2253 ) 2254 : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) 2255 { 2256 ctrl_x_mode = 0; 2257 edit_submode = NULL; 2258 msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty") 2259 : (char_u *)_("'thesaurus' option is empty"), 2260 HL_ATTR(HLF_E)); 2261 if (emsg_silent == 0) 2262 { 2263 vim_beep(BO_COMPL); 2264 setcursor(); 2265 out_flush(); 2266 #ifdef FEAT_EVAL 2267 if (!get_vim_var_nr(VV_TESTING)) 2268 #endif 2269 ui_delay(2000L, FALSE); 2270 } 2271 return FALSE; 2272 } 2273 return TRUE; 2274 } 2275 2276 /* 2277 * Is the character 'c' a valid key to go to or keep us in CTRL-X mode? 2278 * This depends on the current mode. 2279 */ 2280 int 2281 vim_is_ctrl_x_key(int c) 2282 { 2283 /* Always allow ^R - let it's results then be checked */ 2284 if (c == Ctrl_R) 2285 return TRUE; 2286 2287 /* Accept <PageUp> and <PageDown> if the popup menu is visible. */ 2288 if (ins_compl_pum_key(c)) 2289 return TRUE; 2290 2291 switch (ctrl_x_mode) 2292 { 2293 case 0: /* Not in any CTRL-X mode */ 2294 return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X); 2295 case CTRL_X_NOT_DEFINED_YET: 2296 return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E 2297 || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB 2298 || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P 2299 || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V 2300 || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O 2301 || c == Ctrl_S || c == Ctrl_K || c == 's'); 2302 case CTRL_X_SCROLL: 2303 return (c == Ctrl_Y || c == Ctrl_E); 2304 case CTRL_X_WHOLE_LINE: 2305 return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N); 2306 case CTRL_X_FILES: 2307 return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N); 2308 case CTRL_X_DICTIONARY: 2309 return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N); 2310 case CTRL_X_THESAURUS: 2311 return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N); 2312 case CTRL_X_TAGS: 2313 return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N); 2314 #ifdef FEAT_FIND_ID 2315 case CTRL_X_PATH_PATTERNS: 2316 return (c == Ctrl_P || c == Ctrl_N); 2317 case CTRL_X_PATH_DEFINES: 2318 return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N); 2319 #endif 2320 case CTRL_X_CMDLINE: 2321 return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N 2322 || c == Ctrl_X); 2323 #ifdef FEAT_COMPL_FUNC 2324 case CTRL_X_FUNCTION: 2325 return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N); 2326 case CTRL_X_OMNI: 2327 return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N); 2328 #endif 2329 case CTRL_X_SPELL: 2330 return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N); 2331 case CTRL_X_EVAL: 2332 return (c == Ctrl_P || c == Ctrl_N); 2333 } 2334 internal_error("vim_is_ctrl_x_key()"); 2335 return FALSE; 2336 } 2337 2338 /* 2339 * Return TRUE when character "c" is part of the item currently being 2340 * completed. Used to decide whether to abandon complete mode when the menu 2341 * is visible. 2342 */ 2343 static int 2344 ins_compl_accept_char(int c) 2345 { 2346 if (ctrl_x_mode & CTRL_X_WANT_IDENT) 2347 /* When expanding an identifier only accept identifier chars. */ 2348 return vim_isIDc(c); 2349 2350 switch (ctrl_x_mode) 2351 { 2352 case CTRL_X_FILES: 2353 /* When expanding file name only accept file name chars. But not 2354 * path separators, so that "proto/<Tab>" expands files in 2355 * "proto", not "proto/" as a whole */ 2356 return vim_isfilec(c) && !vim_ispathsep(c); 2357 2358 case CTRL_X_CMDLINE: 2359 case CTRL_X_OMNI: 2360 /* Command line and Omni completion can work with just about any 2361 * printable character, but do stop at white space. */ 2362 return vim_isprintc(c) && !VIM_ISWHITE(c); 2363 2364 case CTRL_X_WHOLE_LINE: 2365 /* For while line completion a space can be part of the line. */ 2366 return vim_isprintc(c); 2367 } 2368 return vim_iswordc(c); 2369 } 2370 2371 /* 2372 * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the 2373 * case of the originally typed text is used, and the case of the completed 2374 * text is inferred, ie this tries to work out what case you probably wanted 2375 * the rest of the word to be in -- webb 2376 */ 2377 int 2378 ins_compl_add_infercase( 2379 char_u *str, 2380 int len, 2381 int icase, 2382 char_u *fname, 2383 int dir, 2384 int flags) 2385 { 2386 char_u *p; 2387 int i, c; 2388 int actual_len; /* Take multi-byte characters */ 2389 int actual_compl_length; /* into account. */ 2390 int min_len; 2391 int *wca; /* Wide character array. */ 2392 int has_lower = FALSE; 2393 int was_letter = FALSE; 2394 2395 if (p_ic && curbuf->b_p_inf && len > 0) 2396 { 2397 /* Infer case of completed part. */ 2398 2399 /* Find actual length of completion. */ 2400 #ifdef FEAT_MBYTE 2401 if (has_mbyte) 2402 { 2403 p = str; 2404 actual_len = 0; 2405 while (*p != NUL) 2406 { 2407 MB_PTR_ADV(p); 2408 ++actual_len; 2409 } 2410 } 2411 else 2412 #endif 2413 actual_len = len; 2414 2415 /* Find actual length of original text. */ 2416 #ifdef FEAT_MBYTE 2417 if (has_mbyte) 2418 { 2419 p = compl_orig_text; 2420 actual_compl_length = 0; 2421 while (*p != NUL) 2422 { 2423 MB_PTR_ADV(p); 2424 ++actual_compl_length; 2425 } 2426 } 2427 else 2428 #endif 2429 actual_compl_length = compl_length; 2430 2431 /* "actual_len" may be smaller than "actual_compl_length" when using 2432 * thesaurus, only use the minimum when comparing. */ 2433 min_len = actual_len < actual_compl_length 2434 ? actual_len : actual_compl_length; 2435 2436 /* Allocate wide character array for the completion and fill it. */ 2437 wca = (int *)alloc((unsigned)(actual_len * sizeof(int))); 2438 if (wca != NULL) 2439 { 2440 p = str; 2441 for (i = 0; i < actual_len; ++i) 2442 #ifdef FEAT_MBYTE 2443 if (has_mbyte) 2444 wca[i] = mb_ptr2char_adv(&p); 2445 else 2446 #endif 2447 wca[i] = *(p++); 2448 2449 /* Rule 1: Were any chars converted to lower? */ 2450 p = compl_orig_text; 2451 for (i = 0; i < min_len; ++i) 2452 { 2453 #ifdef FEAT_MBYTE 2454 if (has_mbyte) 2455 c = mb_ptr2char_adv(&p); 2456 else 2457 #endif 2458 c = *(p++); 2459 if (MB_ISLOWER(c)) 2460 { 2461 has_lower = TRUE; 2462 if (MB_ISUPPER(wca[i])) 2463 { 2464 /* Rule 1 is satisfied. */ 2465 for (i = actual_compl_length; i < actual_len; ++i) 2466 wca[i] = MB_TOLOWER(wca[i]); 2467 break; 2468 } 2469 } 2470 } 2471 2472 /* 2473 * Rule 2: No lower case, 2nd consecutive letter converted to 2474 * upper case. 2475 */ 2476 if (!has_lower) 2477 { 2478 p = compl_orig_text; 2479 for (i = 0; i < min_len; ++i) 2480 { 2481 #ifdef FEAT_MBYTE 2482 if (has_mbyte) 2483 c = mb_ptr2char_adv(&p); 2484 else 2485 #endif 2486 c = *(p++); 2487 if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i])) 2488 { 2489 /* Rule 2 is satisfied. */ 2490 for (i = actual_compl_length; i < actual_len; ++i) 2491 wca[i] = MB_TOUPPER(wca[i]); 2492 break; 2493 } 2494 was_letter = MB_ISLOWER(c) || MB_ISUPPER(c); 2495 } 2496 } 2497 2498 /* Copy the original case of the part we typed. */ 2499 p = compl_orig_text; 2500 for (i = 0; i < min_len; ++i) 2501 { 2502 #ifdef FEAT_MBYTE 2503 if (has_mbyte) 2504 c = mb_ptr2char_adv(&p); 2505 else 2506 #endif 2507 c = *(p++); 2508 if (MB_ISLOWER(c)) 2509 wca[i] = MB_TOLOWER(wca[i]); 2510 else if (MB_ISUPPER(c)) 2511 wca[i] = MB_TOUPPER(wca[i]); 2512 } 2513 2514 /* 2515 * Generate encoding specific output from wide character array. 2516 * Multi-byte characters can occupy up to five bytes more than 2517 * ASCII characters, and we also need one byte for NUL, so stay 2518 * six bytes away from the edge of IObuff. 2519 */ 2520 p = IObuff; 2521 i = 0; 2522 while (i < actual_len && (p - IObuff + 6) < IOSIZE) 2523 #ifdef FEAT_MBYTE 2524 if (has_mbyte) 2525 p += (*mb_char2bytes)(wca[i++], p); 2526 else 2527 #endif 2528 *(p++) = wca[i++]; 2529 *p = NUL; 2530 2531 vim_free(wca); 2532 } 2533 2534 return ins_compl_add(IObuff, len, icase, fname, NULL, dir, 2535 flags, FALSE); 2536 } 2537 return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE); 2538 } 2539 2540 /* 2541 * Add a match to the list of matches. 2542 * If the given string is already in the list of completions, then return 2543 * NOTDONE, otherwise add it to the list and return OK. If there is an error, 2544 * maybe because alloc() returns NULL, then FAIL is returned. 2545 */ 2546 static int 2547 ins_compl_add( 2548 char_u *str, 2549 int len, 2550 int icase, 2551 char_u *fname, 2552 char_u **cptext, /* extra text for popup menu or NULL */ 2553 int cdir, 2554 int flags, 2555 int adup) /* accept duplicate match */ 2556 { 2557 compl_T *match; 2558 int dir = (cdir == 0 ? compl_direction : cdir); 2559 2560 ui_breakcheck(); 2561 if (got_int) 2562 return FAIL; 2563 if (len < 0) 2564 len = (int)STRLEN(str); 2565 2566 /* 2567 * If the same match is already present, don't add it. 2568 */ 2569 if (compl_first_match != NULL && !adup) 2570 { 2571 match = compl_first_match; 2572 do 2573 { 2574 if ( !(match->cp_flags & ORIGINAL_TEXT) 2575 && STRNCMP(match->cp_str, str, len) == 0 2576 && match->cp_str[len] == NUL) 2577 return NOTDONE; 2578 match = match->cp_next; 2579 } while (match != NULL && match != compl_first_match); 2580 } 2581 2582 /* Remove any popup menu before changing the list of matches. */ 2583 ins_compl_del_pum(); 2584 2585 /* 2586 * Allocate a new match structure. 2587 * Copy the values to the new match structure. 2588 */ 2589 match = (compl_T *)alloc_clear((unsigned)sizeof(compl_T)); 2590 if (match == NULL) 2591 return FAIL; 2592 match->cp_number = -1; 2593 if (flags & ORIGINAL_TEXT) 2594 match->cp_number = 0; 2595 if ((match->cp_str = vim_strnsave(str, len)) == NULL) 2596 { 2597 vim_free(match); 2598 return FAIL; 2599 } 2600 match->cp_icase = icase; 2601 2602 /* match-fname is: 2603 * - compl_curr_match->cp_fname if it is a string equal to fname. 2604 * - a copy of fname, FREE_FNAME is set to free later THE allocated mem. 2605 * - NULL otherwise. --Acevedo */ 2606 if (fname != NULL 2607 && compl_curr_match != NULL 2608 && compl_curr_match->cp_fname != NULL 2609 && STRCMP(fname, compl_curr_match->cp_fname) == 0) 2610 match->cp_fname = compl_curr_match->cp_fname; 2611 else if (fname != NULL) 2612 { 2613 match->cp_fname = vim_strsave(fname); 2614 flags |= FREE_FNAME; 2615 } 2616 else 2617 match->cp_fname = NULL; 2618 match->cp_flags = flags; 2619 2620 if (cptext != NULL) 2621 { 2622 int i; 2623 2624 for (i = 0; i < CPT_COUNT; ++i) 2625 if (cptext[i] != NULL && *cptext[i] != NUL) 2626 match->cp_text[i] = vim_strsave(cptext[i]); 2627 } 2628 2629 /* 2630 * Link the new match structure in the list of matches. 2631 */ 2632 if (compl_first_match == NULL) 2633 match->cp_next = match->cp_prev = NULL; 2634 else if (dir == FORWARD) 2635 { 2636 match->cp_next = compl_curr_match->cp_next; 2637 match->cp_prev = compl_curr_match; 2638 } 2639 else /* BACKWARD */ 2640 { 2641 match->cp_next = compl_curr_match; 2642 match->cp_prev = compl_curr_match->cp_prev; 2643 } 2644 if (match->cp_next) 2645 match->cp_next->cp_prev = match; 2646 if (match->cp_prev) 2647 match->cp_prev->cp_next = match; 2648 else /* if there's nothing before, it is the first match */ 2649 compl_first_match = match; 2650 compl_curr_match = match; 2651 2652 /* 2653 * Find the longest common string if still doing that. 2654 */ 2655 if (compl_get_longest && (flags & ORIGINAL_TEXT) == 0) 2656 ins_compl_longest_match(match); 2657 2658 return OK; 2659 } 2660 2661 /* 2662 * Return TRUE if "str[len]" matches with match->cp_str, considering 2663 * match->cp_icase. 2664 */ 2665 static int 2666 ins_compl_equal(compl_T *match, char_u *str, int len) 2667 { 2668 if (match->cp_icase) 2669 return STRNICMP(match->cp_str, str, (size_t)len) == 0; 2670 return STRNCMP(match->cp_str, str, (size_t)len) == 0; 2671 } 2672 2673 /* 2674 * Reduce the longest common string for match "match". 2675 */ 2676 static void 2677 ins_compl_longest_match(compl_T *match) 2678 { 2679 char_u *p, *s; 2680 int c1, c2; 2681 int had_match; 2682 2683 if (compl_leader == NULL) 2684 { 2685 /* First match, use it as a whole. */ 2686 compl_leader = vim_strsave(match->cp_str); 2687 if (compl_leader != NULL) 2688 { 2689 had_match = (curwin->w_cursor.col > compl_col); 2690 ins_compl_delete(); 2691 ins_bytes(compl_leader + ins_compl_len()); 2692 ins_redraw(FALSE); 2693 2694 /* When the match isn't there (to avoid matching itself) remove it 2695 * again after redrawing. */ 2696 if (!had_match) 2697 ins_compl_delete(); 2698 compl_used_match = FALSE; 2699 } 2700 } 2701 else 2702 { 2703 /* Reduce the text if this match differs from compl_leader. */ 2704 p = compl_leader; 2705 s = match->cp_str; 2706 while (*p != NUL) 2707 { 2708 #ifdef FEAT_MBYTE 2709 if (has_mbyte) 2710 { 2711 c1 = mb_ptr2char(p); 2712 c2 = mb_ptr2char(s); 2713 } 2714 else 2715 #endif 2716 { 2717 c1 = *p; 2718 c2 = *s; 2719 } 2720 if (match->cp_icase ? (MB_TOLOWER(c1) != MB_TOLOWER(c2)) 2721 : (c1 != c2)) 2722 break; 2723 #ifdef FEAT_MBYTE 2724 if (has_mbyte) 2725 { 2726 MB_PTR_ADV(p); 2727 MB_PTR_ADV(s); 2728 } 2729 else 2730 #endif 2731 { 2732 ++p; 2733 ++s; 2734 } 2735 } 2736 2737 if (*p != NUL) 2738 { 2739 /* Leader was shortened, need to change the inserted text. */ 2740 *p = NUL; 2741 had_match = (curwin->w_cursor.col > compl_col); 2742 ins_compl_delete(); 2743 ins_bytes(compl_leader + ins_compl_len()); 2744 ins_redraw(FALSE); 2745 2746 /* When the match isn't there (to avoid matching itself) remove it 2747 * again after redrawing. */ 2748 if (!had_match) 2749 ins_compl_delete(); 2750 } 2751 2752 compl_used_match = FALSE; 2753 } 2754 } 2755 2756 /* 2757 * Add an array of matches to the list of matches. 2758 * Frees matches[]. 2759 */ 2760 static void 2761 ins_compl_add_matches( 2762 int num_matches, 2763 char_u **matches, 2764 int icase) 2765 { 2766 int i; 2767 int add_r = OK; 2768 int dir = compl_direction; 2769 2770 for (i = 0; i < num_matches && add_r != FAIL; i++) 2771 if ((add_r = ins_compl_add(matches[i], -1, icase, 2772 NULL, NULL, dir, 0, FALSE)) == OK) 2773 /* if dir was BACKWARD then honor it just once */ 2774 dir = FORWARD; 2775 FreeWild(num_matches, matches); 2776 } 2777 2778 /* Make the completion list cyclic. 2779 * Return the number of matches (excluding the original). 2780 */ 2781 static int 2782 ins_compl_make_cyclic(void) 2783 { 2784 compl_T *match; 2785 int count = 0; 2786 2787 if (compl_first_match != NULL) 2788 { 2789 /* 2790 * Find the end of the list. 2791 */ 2792 match = compl_first_match; 2793 /* there's always an entry for the compl_orig_text, it doesn't count. */ 2794 while (match->cp_next != NULL && match->cp_next != compl_first_match) 2795 { 2796 match = match->cp_next; 2797 ++count; 2798 } 2799 match->cp_next = compl_first_match; 2800 compl_first_match->cp_prev = match; 2801 } 2802 return count; 2803 } 2804 2805 /* 2806 * Set variables that store noselect and noinsert behavior from the 2807 * 'completeopt' value. 2808 */ 2809 void 2810 completeopt_was_set(void) 2811 { 2812 compl_no_insert = FALSE; 2813 compl_no_select = FALSE; 2814 if (strstr((char *)p_cot, "noselect") != NULL) 2815 compl_no_select = TRUE; 2816 if (strstr((char *)p_cot, "noinsert") != NULL) 2817 compl_no_insert = TRUE; 2818 } 2819 2820 /* 2821 * Start completion for the complete() function. 2822 * "startcol" is where the matched text starts (1 is first column). 2823 * "list" is the list of matches. 2824 */ 2825 void 2826 set_completion(colnr_T startcol, list_T *list) 2827 { 2828 int save_w_wrow = curwin->w_wrow; 2829 int save_w_leftcol = curwin->w_leftcol; 2830 2831 /* If already doing completions stop it. */ 2832 if (ctrl_x_mode != 0) 2833 ins_compl_prep(' '); 2834 ins_compl_clear(); 2835 ins_compl_free(); 2836 2837 compl_direction = FORWARD; 2838 if (startcol > curwin->w_cursor.col) 2839 startcol = curwin->w_cursor.col; 2840 compl_col = startcol; 2841 compl_length = (int)curwin->w_cursor.col - (int)startcol; 2842 /* compl_pattern doesn't need to be set */ 2843 compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length); 2844 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, 2845 -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) 2846 return; 2847 2848 ctrl_x_mode = CTRL_X_EVAL; 2849 2850 ins_compl_add_list(list); 2851 compl_matches = ins_compl_make_cyclic(); 2852 compl_started = TRUE; 2853 compl_used_match = TRUE; 2854 compl_cont_status = 0; 2855 2856 compl_curr_match = compl_first_match; 2857 if (compl_no_insert || compl_no_select) 2858 { 2859 ins_complete(K_DOWN, FALSE); 2860 if (compl_no_select) 2861 /* Down/Up has no real effect. */ 2862 ins_complete(K_UP, FALSE); 2863 } 2864 else 2865 ins_complete(Ctrl_N, FALSE); 2866 compl_enter_selects = compl_no_insert; 2867 2868 /* Lazily show the popup menu, unless we got interrupted. */ 2869 if (!compl_interrupted) 2870 show_pum(save_w_wrow, save_w_leftcol); 2871 out_flush(); 2872 } 2873 2874 2875 /* "compl_match_array" points the currently displayed list of entries in the 2876 * popup menu. It is NULL when there is no popup menu. */ 2877 static pumitem_T *compl_match_array = NULL; 2878 static int compl_match_arraysize; 2879 2880 /* 2881 * Update the screen and when there is any scrolling remove the popup menu. 2882 */ 2883 static void 2884 ins_compl_upd_pum(void) 2885 { 2886 int h; 2887 2888 if (compl_match_array != NULL) 2889 { 2890 h = curwin->w_cline_height; 2891 update_screen(0); 2892 if (h != curwin->w_cline_height) 2893 ins_compl_del_pum(); 2894 } 2895 } 2896 2897 /* 2898 * Remove any popup menu. 2899 */ 2900 static void 2901 ins_compl_del_pum(void) 2902 { 2903 if (compl_match_array != NULL) 2904 { 2905 pum_undisplay(); 2906 vim_free(compl_match_array); 2907 compl_match_array = NULL; 2908 } 2909 } 2910 2911 /* 2912 * Return TRUE if the popup menu should be displayed. 2913 */ 2914 static int 2915 pum_wanted(void) 2916 { 2917 /* 'completeopt' must contain "menu" or "menuone" */ 2918 if (vim_strchr(p_cot, 'm') == NULL) 2919 return FALSE; 2920 2921 /* The display looks bad on a B&W display. */ 2922 if (t_colors < 8 2923 #ifdef FEAT_GUI 2924 && !gui.in_use 2925 #endif 2926 ) 2927 return FALSE; 2928 return TRUE; 2929 } 2930 2931 /* 2932 * Return TRUE if there are two or more matches to be shown in the popup menu. 2933 * One if 'completopt' contains "menuone". 2934 */ 2935 static int 2936 pum_enough_matches(void) 2937 { 2938 compl_T *compl; 2939 int i; 2940 2941 /* Don't display the popup menu if there are no matches or there is only 2942 * one (ignoring the original text). */ 2943 compl = compl_first_match; 2944 i = 0; 2945 do 2946 { 2947 if (compl == NULL 2948 || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2)) 2949 break; 2950 compl = compl->cp_next; 2951 } while (compl != compl_first_match); 2952 2953 if (strstr((char *)p_cot, "menuone") != NULL) 2954 return (i >= 1); 2955 return (i >= 2); 2956 } 2957 2958 /* 2959 * Show the popup menu for the list of matches. 2960 * Also adjusts "compl_shown_match" to an entry that is actually displayed. 2961 */ 2962 void 2963 ins_compl_show_pum(void) 2964 { 2965 compl_T *compl; 2966 compl_T *shown_compl = NULL; 2967 int did_find_shown_match = FALSE; 2968 int shown_match_ok = FALSE; 2969 int i; 2970 int cur = -1; 2971 colnr_T col; 2972 int lead_len = 0; 2973 2974 if (!pum_wanted() || !pum_enough_matches()) 2975 return; 2976 2977 #if defined(FEAT_EVAL) 2978 /* Dirty hard-coded hack: remove any matchparen highlighting. */ 2979 do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|3match none|endif"); 2980 #endif 2981 2982 /* Update the screen before drawing the popup menu over it. */ 2983 update_screen(0); 2984 2985 if (compl_match_array == NULL) 2986 { 2987 /* Need to build the popup menu list. */ 2988 compl_match_arraysize = 0; 2989 compl = compl_first_match; 2990 if (compl_leader != NULL) 2991 lead_len = (int)STRLEN(compl_leader); 2992 do 2993 { 2994 if ((compl->cp_flags & ORIGINAL_TEXT) == 0 2995 && (compl_leader == NULL 2996 || ins_compl_equal(compl, compl_leader, lead_len))) 2997 ++compl_match_arraysize; 2998 compl = compl->cp_next; 2999 } while (compl != NULL && compl != compl_first_match); 3000 if (compl_match_arraysize == 0) 3001 return; 3002 compl_match_array = (pumitem_T *)alloc_clear( 3003 (unsigned)(sizeof(pumitem_T) 3004 * compl_match_arraysize)); 3005 if (compl_match_array != NULL) 3006 { 3007 /* If the current match is the original text don't find the first 3008 * match after it, don't highlight anything. */ 3009 if (compl_shown_match->cp_flags & ORIGINAL_TEXT) 3010 shown_match_ok = TRUE; 3011 3012 i = 0; 3013 compl = compl_first_match; 3014 do 3015 { 3016 if ((compl->cp_flags & ORIGINAL_TEXT) == 0 3017 && (compl_leader == NULL 3018 || ins_compl_equal(compl, compl_leader, lead_len))) 3019 { 3020 if (!shown_match_ok) 3021 { 3022 if (compl == compl_shown_match || did_find_shown_match) 3023 { 3024 /* This item is the shown match or this is the 3025 * first displayed item after the shown match. */ 3026 compl_shown_match = compl; 3027 did_find_shown_match = TRUE; 3028 shown_match_ok = TRUE; 3029 } 3030 else 3031 /* Remember this displayed match for when the 3032 * shown match is just below it. */ 3033 shown_compl = compl; 3034 cur = i; 3035 } 3036 3037 if (compl->cp_text[CPT_ABBR] != NULL) 3038 compl_match_array[i].pum_text = 3039 compl->cp_text[CPT_ABBR]; 3040 else 3041 compl_match_array[i].pum_text = compl->cp_str; 3042 compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND]; 3043 compl_match_array[i].pum_info = compl->cp_text[CPT_INFO]; 3044 if (compl->cp_text[CPT_MENU] != NULL) 3045 compl_match_array[i++].pum_extra = 3046 compl->cp_text[CPT_MENU]; 3047 else 3048 compl_match_array[i++].pum_extra = compl->cp_fname; 3049 } 3050 3051 if (compl == compl_shown_match) 3052 { 3053 did_find_shown_match = TRUE; 3054 3055 /* When the original text is the shown match don't set 3056 * compl_shown_match. */ 3057 if (compl->cp_flags & ORIGINAL_TEXT) 3058 shown_match_ok = TRUE; 3059 3060 if (!shown_match_ok && shown_compl != NULL) 3061 { 3062 /* The shown match isn't displayed, set it to the 3063 * previously displayed match. */ 3064 compl_shown_match = shown_compl; 3065 shown_match_ok = TRUE; 3066 } 3067 } 3068 compl = compl->cp_next; 3069 } while (compl != NULL && compl != compl_first_match); 3070 3071 if (!shown_match_ok) /* no displayed match at all */ 3072 cur = -1; 3073 } 3074 } 3075 else 3076 { 3077 /* popup menu already exists, only need to find the current item.*/ 3078 for (i = 0; i < compl_match_arraysize; ++i) 3079 if (compl_match_array[i].pum_text == compl_shown_match->cp_str 3080 || compl_match_array[i].pum_text 3081 == compl_shown_match->cp_text[CPT_ABBR]) 3082 { 3083 cur = i; 3084 break; 3085 } 3086 } 3087 3088 if (compl_match_array != NULL) 3089 { 3090 /* In Replace mode when a $ is displayed at the end of the line only 3091 * part of the screen would be updated. We do need to redraw here. */ 3092 dollar_vcol = -1; 3093 3094 /* Compute the screen column of the start of the completed text. 3095 * Use the cursor to get all wrapping and other settings right. */ 3096 col = curwin->w_cursor.col; 3097 curwin->w_cursor.col = compl_col; 3098 pum_display(compl_match_array, compl_match_arraysize, cur); 3099 curwin->w_cursor.col = col; 3100 } 3101 } 3102 3103 #define DICT_FIRST (1) /* use just first element in "dict" */ 3104 #define DICT_EXACT (2) /* "dict" is the exact name of a file */ 3105 3106 /* 3107 * Add any identifiers that match the given pattern in the list of dictionary 3108 * files "dict_start" to the list of completions. 3109 */ 3110 static void 3111 ins_compl_dictionaries( 3112 char_u *dict_start, 3113 char_u *pat, 3114 int flags, /* DICT_FIRST and/or DICT_EXACT */ 3115 int thesaurus) /* Thesaurus completion */ 3116 { 3117 char_u *dict = dict_start; 3118 char_u *ptr; 3119 char_u *buf; 3120 regmatch_T regmatch; 3121 char_u **files; 3122 int count; 3123 int save_p_scs; 3124 int dir = compl_direction; 3125 3126 if (*dict == NUL) 3127 { 3128 #ifdef FEAT_SPELL 3129 /* When 'dictionary' is empty and spell checking is enabled use 3130 * "spell". */ 3131 if (!thesaurus && curwin->w_p_spell) 3132 dict = (char_u *)"spell"; 3133 else 3134 #endif 3135 return; 3136 } 3137 3138 buf = alloc(LSIZE); 3139 if (buf == NULL) 3140 return; 3141 regmatch.regprog = NULL; /* so that we can goto theend */ 3142 3143 /* If 'infercase' is set, don't use 'smartcase' here */ 3144 save_p_scs = p_scs; 3145 if (curbuf->b_p_inf) 3146 p_scs = FALSE; 3147 3148 /* When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern 3149 * to only match at the start of a line. Otherwise just match the 3150 * pattern. Also need to double backslashes. */ 3151 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 3152 { 3153 char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\"); 3154 size_t len; 3155 3156 if (pat_esc == NULL) 3157 goto theend; 3158 len = STRLEN(pat_esc) + 10; 3159 ptr = alloc((unsigned)len); 3160 if (ptr == NULL) 3161 { 3162 vim_free(pat_esc); 3163 goto theend; 3164 } 3165 vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc); 3166 regmatch.regprog = vim_regcomp(ptr, RE_MAGIC); 3167 vim_free(pat_esc); 3168 vim_free(ptr); 3169 } 3170 else 3171 { 3172 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0); 3173 if (regmatch.regprog == NULL) 3174 goto theend; 3175 } 3176 3177 /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */ 3178 regmatch.rm_ic = ignorecase(pat); 3179 while (*dict != NUL && !got_int && !compl_interrupted) 3180 { 3181 /* copy one dictionary file name into buf */ 3182 if (flags == DICT_EXACT) 3183 { 3184 count = 1; 3185 files = &dict; 3186 } 3187 else 3188 { 3189 /* Expand wildcards in the dictionary name, but do not allow 3190 * backticks (for security, the 'dict' option may have been set in 3191 * a modeline). */ 3192 copy_option_part(&dict, buf, LSIZE, ","); 3193 # ifdef FEAT_SPELL 3194 if (!thesaurus && STRCMP(buf, "spell") == 0) 3195 count = -1; 3196 else 3197 # endif 3198 if (vim_strchr(buf, '`') != NULL 3199 || expand_wildcards(1, &buf, &count, &files, 3200 EW_FILE|EW_SILENT) != OK) 3201 count = 0; 3202 } 3203 3204 # ifdef FEAT_SPELL 3205 if (count == -1) 3206 { 3207 /* Complete from active spelling. Skip "\<" in the pattern, we 3208 * don't use it as a RE. */ 3209 if (pat[0] == '\\' && pat[1] == '<') 3210 ptr = pat + 2; 3211 else 3212 ptr = pat; 3213 spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0); 3214 } 3215 else 3216 # endif 3217 if (count > 0) /* avoid warning for using "files" uninit */ 3218 { 3219 ins_compl_files(count, files, thesaurus, flags, 3220 ®match, buf, &dir); 3221 if (flags != DICT_EXACT) 3222 FreeWild(count, files); 3223 } 3224 if (flags != 0) 3225 break; 3226 } 3227 3228 theend: 3229 p_scs = save_p_scs; 3230 vim_regfree(regmatch.regprog); 3231 vim_free(buf); 3232 } 3233 3234 static void 3235 ins_compl_files( 3236 int count, 3237 char_u **files, 3238 int thesaurus, 3239 int flags, 3240 regmatch_T *regmatch, 3241 char_u *buf, 3242 int *dir) 3243 { 3244 char_u *ptr; 3245 int i; 3246 FILE *fp; 3247 int add_r; 3248 3249 for (i = 0; i < count && !got_int && !compl_interrupted; i++) 3250 { 3251 fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */ 3252 if (flags != DICT_EXACT) 3253 { 3254 vim_snprintf((char *)IObuff, IOSIZE, 3255 _("Scanning dictionary: %s"), (char *)files[i]); 3256 (void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R)); 3257 } 3258 3259 if (fp != NULL) 3260 { 3261 /* 3262 * Read dictionary file line by line. 3263 * Check each line for a match. 3264 */ 3265 while (!got_int && !compl_interrupted 3266 && !vim_fgets(buf, LSIZE, fp)) 3267 { 3268 ptr = buf; 3269 while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf))) 3270 { 3271 ptr = regmatch->startp[0]; 3272 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 3273 ptr = find_line_end(ptr); 3274 else 3275 ptr = find_word_end(ptr); 3276 add_r = ins_compl_add_infercase(regmatch->startp[0], 3277 (int)(ptr - regmatch->startp[0]), 3278 p_ic, files[i], *dir, 0); 3279 if (thesaurus) 3280 { 3281 char_u *wstart; 3282 3283 /* 3284 * Add the other matches on the line 3285 */ 3286 ptr = buf; 3287 while (!got_int) 3288 { 3289 /* Find start of the next word. Skip white 3290 * space and punctuation. */ 3291 ptr = find_word_start(ptr); 3292 if (*ptr == NUL || *ptr == NL) 3293 break; 3294 wstart = ptr; 3295 3296 /* Find end of the word. */ 3297 #ifdef FEAT_MBYTE 3298 if (has_mbyte) 3299 /* Japanese words may have characters in 3300 * different classes, only separate words 3301 * with single-byte non-word characters. */ 3302 while (*ptr != NUL) 3303 { 3304 int l = (*mb_ptr2len)(ptr); 3305 3306 if (l < 2 && !vim_iswordc(*ptr)) 3307 break; 3308 ptr += l; 3309 } 3310 else 3311 #endif 3312 ptr = find_word_end(ptr); 3313 3314 /* Add the word. Skip the regexp match. */ 3315 if (wstart != regmatch->startp[0]) 3316 add_r = ins_compl_add_infercase(wstart, 3317 (int)(ptr - wstart), 3318 p_ic, files[i], *dir, 0); 3319 } 3320 } 3321 if (add_r == OK) 3322 /* if dir was BACKWARD then honor it just once */ 3323 *dir = FORWARD; 3324 else if (add_r == FAIL) 3325 break; 3326 /* avoid expensive call to vim_regexec() when at end 3327 * of line */ 3328 if (*ptr == '\n' || got_int) 3329 break; 3330 } 3331 line_breakcheck(); 3332 ins_compl_check_keys(50, FALSE); 3333 } 3334 fclose(fp); 3335 } 3336 } 3337 } 3338 3339 /* 3340 * Find the start of the next word. 3341 * Returns a pointer to the first char of the word. Also stops at a NUL. 3342 */ 3343 char_u * 3344 find_word_start(char_u *ptr) 3345 { 3346 #ifdef FEAT_MBYTE 3347 if (has_mbyte) 3348 while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1) 3349 ptr += (*mb_ptr2len)(ptr); 3350 else 3351 #endif 3352 while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr)) 3353 ++ptr; 3354 return ptr; 3355 } 3356 3357 /* 3358 * Find the end of the word. Assumes it starts inside a word. 3359 * Returns a pointer to just after the word. 3360 */ 3361 char_u * 3362 find_word_end(char_u *ptr) 3363 { 3364 #ifdef FEAT_MBYTE 3365 int start_class; 3366 3367 if (has_mbyte) 3368 { 3369 start_class = mb_get_class(ptr); 3370 if (start_class > 1) 3371 while (*ptr != NUL) 3372 { 3373 ptr += (*mb_ptr2len)(ptr); 3374 if (mb_get_class(ptr) != start_class) 3375 break; 3376 } 3377 } 3378 else 3379 #endif 3380 while (vim_iswordc(*ptr)) 3381 ++ptr; 3382 return ptr; 3383 } 3384 3385 /* 3386 * Find the end of the line, omitting CR and NL at the end. 3387 * Returns a pointer to just after the line. 3388 */ 3389 static char_u * 3390 find_line_end(char_u *ptr) 3391 { 3392 char_u *s; 3393 3394 s = ptr + STRLEN(ptr); 3395 while (s > ptr && (s[-1] == CAR || s[-1] == NL)) 3396 --s; 3397 return s; 3398 } 3399 3400 /* 3401 * Free the list of completions 3402 */ 3403 static void 3404 ins_compl_free(void) 3405 { 3406 compl_T *match; 3407 int i; 3408 3409 vim_free(compl_pattern); 3410 compl_pattern = NULL; 3411 vim_free(compl_leader); 3412 compl_leader = NULL; 3413 3414 if (compl_first_match == NULL) 3415 return; 3416 3417 ins_compl_del_pum(); 3418 pum_clear(); 3419 3420 compl_curr_match = compl_first_match; 3421 do 3422 { 3423 match = compl_curr_match; 3424 compl_curr_match = compl_curr_match->cp_next; 3425 vim_free(match->cp_str); 3426 /* several entries may use the same fname, free it just once. */ 3427 if (match->cp_flags & FREE_FNAME) 3428 vim_free(match->cp_fname); 3429 for (i = 0; i < CPT_COUNT; ++i) 3430 vim_free(match->cp_text[i]); 3431 vim_free(match); 3432 } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); 3433 compl_first_match = compl_curr_match = NULL; 3434 compl_shown_match = NULL; 3435 compl_old_match = NULL; 3436 } 3437 3438 static void 3439 ins_compl_clear(void) 3440 { 3441 compl_cont_status = 0; 3442 compl_started = FALSE; 3443 compl_matches = 0; 3444 vim_free(compl_pattern); 3445 compl_pattern = NULL; 3446 vim_free(compl_leader); 3447 compl_leader = NULL; 3448 edit_submode_extra = NULL; 3449 vim_free(compl_orig_text); 3450 compl_orig_text = NULL; 3451 compl_enter_selects = FALSE; 3452 /* clear v:completed_item */ 3453 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); 3454 } 3455 3456 /* 3457 * Return TRUE when Insert completion is active. 3458 */ 3459 int 3460 ins_compl_active(void) 3461 { 3462 return compl_started; 3463 } 3464 3465 /* 3466 * Delete one character before the cursor and show the subset of the matches 3467 * that match the word that is now before the cursor. 3468 * Returns the character to be used, NUL if the work is done and another char 3469 * to be got from the user. 3470 */ 3471 static int 3472 ins_compl_bs(void) 3473 { 3474 char_u *line; 3475 char_u *p; 3476 3477 line = ml_get_curline(); 3478 p = line + curwin->w_cursor.col; 3479 MB_PTR_BACK(line, p); 3480 3481 /* Stop completion when the whole word was deleted. For Omni completion 3482 * allow the word to be deleted, we won't match everything. 3483 * Respect the 'backspace' option. */ 3484 if ((int)(p - line) - (int)compl_col < 0 3485 || ((int)(p - line) - (int)compl_col == 0 3486 && ctrl_x_mode != CTRL_X_OMNI) || ctrl_x_mode == CTRL_X_EVAL 3487 || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col 3488 - compl_length < 0)) 3489 return K_BS; 3490 3491 /* Deleted more than what was used to find matches or didn't finish 3492 * finding all matches: need to look for matches all over again. */ 3493 if (curwin->w_cursor.col <= compl_col + compl_length 3494 || ins_compl_need_restart()) 3495 ins_compl_restart(); 3496 3497 vim_free(compl_leader); 3498 compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col); 3499 if (compl_leader != NULL) 3500 { 3501 ins_compl_new_leader(); 3502 if (compl_shown_match != NULL) 3503 /* Make sure current match is not a hidden item. */ 3504 compl_curr_match = compl_shown_match; 3505 return NUL; 3506 } 3507 return K_BS; 3508 } 3509 3510 /* 3511 * Return TRUE when we need to find matches again, ins_compl_restart() is to 3512 * be called. 3513 */ 3514 static int 3515 ins_compl_need_restart(void) 3516 { 3517 /* Return TRUE if we didn't complete finding matches or when the 3518 * 'completefunc' returned "always" in the "refresh" dictionary item. */ 3519 return compl_was_interrupted 3520 || ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) 3521 && compl_opt_refresh_always); 3522 } 3523 3524 /* 3525 * Called after changing "compl_leader". 3526 * Show the popup menu with a different set of matches. 3527 * May also search for matches again if the previous search was interrupted. 3528 */ 3529 static void 3530 ins_compl_new_leader(void) 3531 { 3532 ins_compl_del_pum(); 3533 ins_compl_delete(); 3534 ins_bytes(compl_leader + ins_compl_len()); 3535 compl_used_match = FALSE; 3536 3537 if (compl_started) 3538 ins_compl_set_original_text(compl_leader); 3539 else 3540 { 3541 #ifdef FEAT_SPELL 3542 spell_bad_len = 0; /* need to redetect bad word */ 3543 #endif 3544 /* 3545 * Matches were cleared, need to search for them now. First display 3546 * the changed text before the cursor. Set "compl_restarting" to 3547 * avoid that the first match is inserted. 3548 */ 3549 update_screen(0); 3550 #ifdef FEAT_GUI 3551 if (gui.in_use) 3552 { 3553 /* Show the cursor after the match, not after the redrawn text. */ 3554 setcursor(); 3555 out_flush(); 3556 gui_update_cursor(FALSE, FALSE); 3557 } 3558 #endif 3559 compl_restarting = TRUE; 3560 if (ins_complete(Ctrl_N, TRUE) == FAIL) 3561 compl_cont_status = 0; 3562 compl_restarting = FALSE; 3563 } 3564 3565 compl_enter_selects = !compl_used_match; 3566 3567 /* Show the popup menu with a different set of matches. */ 3568 ins_compl_show_pum(); 3569 3570 /* Don't let Enter select the original text when there is no popup menu. */ 3571 if (compl_match_array == NULL) 3572 compl_enter_selects = FALSE; 3573 } 3574 3575 /* 3576 * Return the length of the completion, from the completion start column to 3577 * the cursor column. Making sure it never goes below zero. 3578 */ 3579 static int 3580 ins_compl_len(void) 3581 { 3582 int off = (int)curwin->w_cursor.col - (int)compl_col; 3583 3584 if (off < 0) 3585 return 0; 3586 return off; 3587 } 3588 3589 /* 3590 * Append one character to the match leader. May reduce the number of 3591 * matches. 3592 */ 3593 static void 3594 ins_compl_addleader(int c) 3595 { 3596 #ifdef FEAT_MBYTE 3597 int cc; 3598 #endif 3599 3600 if (stop_arrow() == FAIL) 3601 return; 3602 #ifdef FEAT_MBYTE 3603 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) 3604 { 3605 char_u buf[MB_MAXBYTES + 1]; 3606 3607 (*mb_char2bytes)(c, buf); 3608 buf[cc] = NUL; 3609 ins_char_bytes(buf, cc); 3610 if (compl_opt_refresh_always) 3611 AppendToRedobuff(buf); 3612 } 3613 else 3614 #endif 3615 { 3616 ins_char(c); 3617 if (compl_opt_refresh_always) 3618 AppendCharToRedobuff(c); 3619 } 3620 3621 /* If we didn't complete finding matches we must search again. */ 3622 if (ins_compl_need_restart()) 3623 ins_compl_restart(); 3624 3625 /* When 'always' is set, don't reset compl_leader. While completing, 3626 * cursor doesn't point original position, changing compl_leader would 3627 * break redo. */ 3628 if (!compl_opt_refresh_always) 3629 { 3630 vim_free(compl_leader); 3631 compl_leader = vim_strnsave(ml_get_curline() + compl_col, 3632 (int)(curwin->w_cursor.col - compl_col)); 3633 if (compl_leader != NULL) 3634 ins_compl_new_leader(); 3635 } 3636 } 3637 3638 /* 3639 * Setup for finding completions again without leaving CTRL-X mode. Used when 3640 * BS or a key was typed while still searching for matches. 3641 */ 3642 static void 3643 ins_compl_restart(void) 3644 { 3645 ins_compl_free(); 3646 compl_started = FALSE; 3647 compl_matches = 0; 3648 compl_cont_status = 0; 3649 compl_cont_mode = 0; 3650 } 3651 3652 /* 3653 * Set the first match, the original text. 3654 */ 3655 static void 3656 ins_compl_set_original_text(char_u *str) 3657 { 3658 char_u *p; 3659 3660 /* Replace the original text entry. */ 3661 if (compl_first_match->cp_flags & ORIGINAL_TEXT) /* safety check */ 3662 { 3663 p = vim_strsave(str); 3664 if (p != NULL) 3665 { 3666 vim_free(compl_first_match->cp_str); 3667 compl_first_match->cp_str = p; 3668 } 3669 } 3670 } 3671 3672 /* 3673 * Append one character to the match leader. May reduce the number of 3674 * matches. 3675 */ 3676 static void 3677 ins_compl_addfrommatch(void) 3678 { 3679 char_u *p; 3680 int len = (int)curwin->w_cursor.col - (int)compl_col; 3681 int c; 3682 compl_T *cp; 3683 3684 p = compl_shown_match->cp_str; 3685 if ((int)STRLEN(p) <= len) /* the match is too short */ 3686 { 3687 /* When still at the original match use the first entry that matches 3688 * the leader. */ 3689 if (compl_shown_match->cp_flags & ORIGINAL_TEXT) 3690 { 3691 p = NULL; 3692 for (cp = compl_shown_match->cp_next; cp != NULL 3693 && cp != compl_first_match; cp = cp->cp_next) 3694 { 3695 if (compl_leader == NULL 3696 || ins_compl_equal(cp, compl_leader, 3697 (int)STRLEN(compl_leader))) 3698 { 3699 p = cp->cp_str; 3700 break; 3701 } 3702 } 3703 if (p == NULL || (int)STRLEN(p) <= len) 3704 return; 3705 } 3706 else 3707 return; 3708 } 3709 p += len; 3710 c = PTR2CHAR(p); 3711 ins_compl_addleader(c); 3712 } 3713 3714 /* 3715 * Prepare for Insert mode completion, or stop it. 3716 * Called just after typing a character in Insert mode. 3717 * Returns TRUE when the character is not to be inserted; 3718 */ 3719 static int 3720 ins_compl_prep(int c) 3721 { 3722 char_u *ptr; 3723 int want_cindent; 3724 int retval = FALSE; 3725 3726 /* Forget any previous 'special' messages if this is actually 3727 * a ^X mode key - bar ^R, in which case we wait to see what it gives us. 3728 */ 3729 if (c != Ctrl_R && vim_is_ctrl_x_key(c)) 3730 edit_submode_extra = NULL; 3731 3732 /* Ignore end of Select mode mapping and mouse scroll buttons. */ 3733 if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP 3734 || c == K_MOUSELEFT || c == K_MOUSERIGHT) 3735 return retval; 3736 3737 /* Set "compl_get_longest" when finding the first matches. */ 3738 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET 3739 || (ctrl_x_mode == 0 && !compl_started)) 3740 { 3741 compl_get_longest = (strstr((char *)p_cot, "longest") != NULL); 3742 compl_used_match = TRUE; 3743 3744 } 3745 3746 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET) 3747 { 3748 /* 3749 * We have just typed CTRL-X and aren't quite sure which CTRL-X mode 3750 * it will be yet. Now we decide. 3751 */ 3752 switch (c) 3753 { 3754 case Ctrl_E: 3755 case Ctrl_Y: 3756 ctrl_x_mode = CTRL_X_SCROLL; 3757 if (!(State & REPLACE_FLAG)) 3758 edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)"); 3759 else 3760 edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)"); 3761 edit_submode_pre = NULL; 3762 showmode(); 3763 break; 3764 case Ctrl_L: 3765 ctrl_x_mode = CTRL_X_WHOLE_LINE; 3766 break; 3767 case Ctrl_F: 3768 ctrl_x_mode = CTRL_X_FILES; 3769 break; 3770 case Ctrl_K: 3771 ctrl_x_mode = CTRL_X_DICTIONARY; 3772 break; 3773 case Ctrl_R: 3774 /* Simply allow ^R to happen without affecting ^X mode */ 3775 break; 3776 case Ctrl_T: 3777 ctrl_x_mode = CTRL_X_THESAURUS; 3778 break; 3779 #ifdef FEAT_COMPL_FUNC 3780 case Ctrl_U: 3781 ctrl_x_mode = CTRL_X_FUNCTION; 3782 break; 3783 case Ctrl_O: 3784 ctrl_x_mode = CTRL_X_OMNI; 3785 break; 3786 #endif 3787 case 's': 3788 case Ctrl_S: 3789 ctrl_x_mode = CTRL_X_SPELL; 3790 #ifdef FEAT_SPELL 3791 ++emsg_off; /* Avoid getting the E756 error twice. */ 3792 spell_back_to_badword(); 3793 --emsg_off; 3794 #endif 3795 break; 3796 case Ctrl_RSB: 3797 ctrl_x_mode = CTRL_X_TAGS; 3798 break; 3799 #ifdef FEAT_FIND_ID 3800 case Ctrl_I: 3801 case K_S_TAB: 3802 ctrl_x_mode = CTRL_X_PATH_PATTERNS; 3803 break; 3804 case Ctrl_D: 3805 ctrl_x_mode = CTRL_X_PATH_DEFINES; 3806 break; 3807 #endif 3808 case Ctrl_V: 3809 case Ctrl_Q: 3810 ctrl_x_mode = CTRL_X_CMDLINE; 3811 break; 3812 case Ctrl_P: 3813 case Ctrl_N: 3814 /* ^X^P means LOCAL expansion if nothing interrupted (eg we 3815 * just started ^X mode, or there were enough ^X's to cancel 3816 * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below) 3817 * do normal expansion when interrupting a different mode (say 3818 * ^X^F^X^P or ^P^X^X^P, see below) 3819 * nothing changes if interrupting mode 0, (eg, the flag 3820 * doesn't change when going to ADDING mode -- Acevedo */ 3821 if (!(compl_cont_status & CONT_INTRPT)) 3822 compl_cont_status |= CONT_LOCAL; 3823 else if (compl_cont_mode != 0) 3824 compl_cont_status &= ~CONT_LOCAL; 3825 /* FALLTHROUGH */ 3826 default: 3827 /* If we have typed at least 2 ^X's... for modes != 0, we set 3828 * compl_cont_status = 0 (eg, as if we had just started ^X 3829 * mode). 3830 * For mode 0, we set "compl_cont_mode" to an impossible 3831 * value, in both cases ^X^X can be used to restart the same 3832 * mode (avoiding ADDING mode). 3833 * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start 3834 * 'complete' and local ^P expansions respectively. 3835 * In mode 0 an extra ^X is needed since ^X^P goes to ADDING 3836 * mode -- Acevedo */ 3837 if (c == Ctrl_X) 3838 { 3839 if (compl_cont_mode != 0) 3840 compl_cont_status = 0; 3841 else 3842 compl_cont_mode = CTRL_X_NOT_DEFINED_YET; 3843 } 3844 ctrl_x_mode = 0; 3845 edit_submode = NULL; 3846 showmode(); 3847 break; 3848 } 3849 } 3850 else if (ctrl_x_mode != 0) 3851 { 3852 /* We're already in CTRL-X mode, do we stay in it? */ 3853 if (!vim_is_ctrl_x_key(c)) 3854 { 3855 if (ctrl_x_mode == CTRL_X_SCROLL) 3856 ctrl_x_mode = 0; 3857 else 3858 ctrl_x_mode = CTRL_X_FINISHED; 3859 edit_submode = NULL; 3860 } 3861 showmode(); 3862 } 3863 3864 if (compl_started || ctrl_x_mode == CTRL_X_FINISHED) 3865 { 3866 /* Show error message from attempted keyword completion (probably 3867 * 'Pattern not found') until another key is hit, then go back to 3868 * showing what mode we are in. */ 3869 showmode(); 3870 if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R 3871 && !ins_compl_pum_key(c)) 3872 || ctrl_x_mode == CTRL_X_FINISHED) 3873 { 3874 /* Get here when we have finished typing a sequence of ^N and 3875 * ^P or other completion characters in CTRL-X mode. Free up 3876 * memory that was used, and make sure we can redo the insert. */ 3877 if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E) 3878 { 3879 /* 3880 * If any of the original typed text has been changed, eg when 3881 * ignorecase is set, we must add back-spaces to the redo 3882 * buffer. We add as few as necessary to delete just the part 3883 * of the original text that has changed. 3884 * When using the longest match, edited the match or used 3885 * CTRL-E then don't use the current match. 3886 */ 3887 if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) 3888 ptr = compl_curr_match->cp_str; 3889 else 3890 ptr = NULL; 3891 ins_compl_fixRedoBufForLeader(ptr); 3892 } 3893 3894 #ifdef FEAT_CINDENT 3895 want_cindent = (can_cindent && cindent_on()); 3896 #endif 3897 /* 3898 * When completing whole lines: fix indent for 'cindent'. 3899 * Otherwise, break line if it's too long. 3900 */ 3901 if (compl_cont_mode == CTRL_X_WHOLE_LINE) 3902 { 3903 #ifdef FEAT_CINDENT 3904 /* re-indent the current line */ 3905 if (want_cindent) 3906 { 3907 do_c_expr_indent(); 3908 want_cindent = FALSE; /* don't do it again */ 3909 } 3910 #endif 3911 } 3912 else 3913 { 3914 int prev_col = curwin->w_cursor.col; 3915 3916 /* put the cursor on the last char, for 'tw' formatting */ 3917 if (prev_col > 0) 3918 dec_cursor(); 3919 /* only format when something was inserted */ 3920 if (!arrow_used && !ins_need_undo && c != Ctrl_E) 3921 insertchar(NUL, 0, -1); 3922 if (prev_col > 0 3923 && ml_get_curline()[curwin->w_cursor.col] != NUL) 3924 inc_cursor(); 3925 } 3926 3927 /* If the popup menu is displayed pressing CTRL-Y means accepting 3928 * the selection without inserting anything. When 3929 * compl_enter_selects is set the Enter key does the same. */ 3930 if ((c == Ctrl_Y || (compl_enter_selects 3931 && (c == CAR || c == K_KENTER || c == NL))) 3932 && pum_visible()) 3933 retval = TRUE; 3934 3935 /* CTRL-E means completion is Ended, go back to the typed text. 3936 * but only do this, if the Popup is still visible */ 3937 if (c == Ctrl_E) 3938 { 3939 ins_compl_delete(); 3940 if (compl_leader != NULL) 3941 ins_bytes(compl_leader + ins_compl_len()); 3942 else if (compl_first_match != NULL) 3943 ins_bytes(compl_orig_text + ins_compl_len()); 3944 retval = TRUE; 3945 } 3946 3947 auto_format(FALSE, TRUE); 3948 3949 ins_compl_free(); 3950 compl_started = FALSE; 3951 compl_matches = 0; 3952 if (!shortmess(SHM_COMPLETIONMENU)) 3953 msg_clr_cmdline(); /* necessary for "noshowmode" */ 3954 ctrl_x_mode = 0; 3955 compl_enter_selects = FALSE; 3956 if (edit_submode != NULL) 3957 { 3958 edit_submode = NULL; 3959 showmode(); 3960 } 3961 3962 #ifdef FEAT_CMDWIN 3963 if (c == Ctrl_C && cmdwin_type != 0) 3964 /* Avoid the popup menu remains displayed when leaving the 3965 * command line window. */ 3966 update_screen(0); 3967 #endif 3968 #ifdef FEAT_CINDENT 3969 /* 3970 * Indent now if a key was typed that is in 'cinkeys'. 3971 */ 3972 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) 3973 do_c_expr_indent(); 3974 #endif 3975 #ifdef FEAT_AUTOCMD 3976 /* Trigger the CompleteDone event to give scripts a chance to act 3977 * upon the completion. */ 3978 apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); 3979 #endif 3980 } 3981 } 3982 #ifdef FEAT_AUTOCMD 3983 else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) 3984 /* Trigger the CompleteDone event to give scripts a chance to act 3985 * upon the (possibly failed) completion. */ 3986 apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); 3987 #endif 3988 3989 /* reset continue_* if we left expansion-mode, if we stay they'll be 3990 * (re)set properly in ins_complete() */ 3991 if (!vim_is_ctrl_x_key(c)) 3992 { 3993 compl_cont_status = 0; 3994 compl_cont_mode = 0; 3995 } 3996 3997 return retval; 3998 } 3999 4000 /* 4001 * Fix the redo buffer for the completion leader replacing some of the typed 4002 * text. This inserts backspaces and appends the changed text. 4003 * "ptr" is the known leader text or NUL. 4004 */ 4005 static void 4006 ins_compl_fixRedoBufForLeader(char_u *ptr_arg) 4007 { 4008 int len; 4009 char_u *p; 4010 char_u *ptr = ptr_arg; 4011 4012 if (ptr == NULL) 4013 { 4014 if (compl_leader != NULL) 4015 ptr = compl_leader; 4016 else 4017 return; /* nothing to do */ 4018 } 4019 if (compl_orig_text != NULL) 4020 { 4021 p = compl_orig_text; 4022 for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len) 4023 ; 4024 #ifdef FEAT_MBYTE 4025 if (len > 0) 4026 len -= (*mb_head_off)(p, p + len); 4027 #endif 4028 for (p += len; *p != NUL; MB_PTR_ADV(p)) 4029 AppendCharToRedobuff(K_BS); 4030 } 4031 else 4032 len = 0; 4033 if (ptr != NULL) 4034 AppendToRedobuffLit(ptr + len, -1); 4035 } 4036 4037 /* 4038 * Loops through the list of windows, loaded-buffers or non-loaded-buffers 4039 * (depending on flag) starting from buf and looking for a non-scanned 4040 * buffer (other than curbuf). curbuf is special, if it is called with 4041 * buf=curbuf then it has to be the first call for a given flag/expansion. 4042 * 4043 * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo 4044 */ 4045 static buf_T * 4046 ins_compl_next_buf(buf_T *buf, int flag) 4047 { 4048 static win_T *wp; 4049 4050 if (flag == 'w') /* just windows */ 4051 { 4052 if (buf == curbuf) /* first call for this flag/expansion */ 4053 wp = curwin; 4054 while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin 4055 && wp->w_buffer->b_scanned) 4056 ; 4057 buf = wp->w_buffer; 4058 } 4059 else 4060 /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U' 4061 * (unlisted buffers) 4062 * When completing whole lines skip unloaded buffers. */ 4063 while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf 4064 && ((flag == 'U' 4065 ? buf->b_p_bl 4066 : (!buf->b_p_bl 4067 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u'))) 4068 || buf->b_scanned)) 4069 ; 4070 return buf; 4071 } 4072 4073 #ifdef FEAT_COMPL_FUNC 4074 /* 4075 * Execute user defined complete function 'completefunc' or 'omnifunc', and 4076 * get matches in "matches". 4077 */ 4078 static void 4079 expand_by_function( 4080 int type, /* CTRL_X_OMNI or CTRL_X_FUNCTION */ 4081 char_u *base) 4082 { 4083 list_T *matchlist = NULL; 4084 dict_T *matchdict = NULL; 4085 char_u *args[2]; 4086 char_u *funcname; 4087 pos_T pos; 4088 win_T *curwin_save; 4089 buf_T *curbuf_save; 4090 typval_T rettv; 4091 4092 funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu; 4093 if (*funcname == NUL) 4094 return; 4095 4096 /* Call 'completefunc' to obtain the list of matches. */ 4097 args[0] = (char_u *)"0"; 4098 args[1] = base; 4099 4100 pos = curwin->w_cursor; 4101 curwin_save = curwin; 4102 curbuf_save = curbuf; 4103 4104 /* Call a function, which returns a list or dict. */ 4105 if (call_vim_function(funcname, 2, args, FALSE, FALSE, &rettv) == OK) 4106 { 4107 switch (rettv.v_type) 4108 { 4109 case VAR_LIST: 4110 matchlist = rettv.vval.v_list; 4111 break; 4112 case VAR_DICT: 4113 matchdict = rettv.vval.v_dict; 4114 break; 4115 default: 4116 /* TODO: Give error message? */ 4117 clear_tv(&rettv); 4118 break; 4119 } 4120 } 4121 4122 if (curwin_save != curwin || curbuf_save != curbuf) 4123 { 4124 EMSG(_(e_complwin)); 4125 goto theend; 4126 } 4127 curwin->w_cursor = pos; /* restore the cursor position */ 4128 validate_cursor(); 4129 if (!EQUAL_POS(curwin->w_cursor, pos)) 4130 { 4131 EMSG(_(e_compldel)); 4132 goto theend; 4133 } 4134 4135 if (matchlist != NULL) 4136 ins_compl_add_list(matchlist); 4137 else if (matchdict != NULL) 4138 ins_compl_add_dict(matchdict); 4139 4140 theend: 4141 if (matchdict != NULL) 4142 dict_unref(matchdict); 4143 if (matchlist != NULL) 4144 list_unref(matchlist); 4145 } 4146 #endif /* FEAT_COMPL_FUNC */ 4147 4148 #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO) 4149 /* 4150 * Add completions from a list. 4151 */ 4152 static void 4153 ins_compl_add_list(list_T *list) 4154 { 4155 listitem_T *li; 4156 int dir = compl_direction; 4157 4158 /* Go through the List with matches and add each of them. */ 4159 for (li = list->lv_first; li != NULL; li = li->li_next) 4160 { 4161 if (ins_compl_add_tv(&li->li_tv, dir) == OK) 4162 /* if dir was BACKWARD then honor it just once */ 4163 dir = FORWARD; 4164 else if (did_emsg) 4165 break; 4166 } 4167 } 4168 4169 /* 4170 * Add completions from a dict. 4171 */ 4172 static void 4173 ins_compl_add_dict(dict_T *dict) 4174 { 4175 dictitem_T *di_refresh; 4176 dictitem_T *di_words; 4177 4178 /* Check for optional "refresh" item. */ 4179 compl_opt_refresh_always = FALSE; 4180 di_refresh = dict_find(dict, (char_u *)"refresh", 7); 4181 if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) 4182 { 4183 char_u *v = di_refresh->di_tv.vval.v_string; 4184 4185 if (v != NULL && STRCMP(v, (char_u *)"always") == 0) 4186 compl_opt_refresh_always = TRUE; 4187 } 4188 4189 /* Add completions from a "words" list. */ 4190 di_words = dict_find(dict, (char_u *)"words", 5); 4191 if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) 4192 ins_compl_add_list(di_words->di_tv.vval.v_list); 4193 } 4194 4195 /* 4196 * Add a match to the list of matches from a typeval_T. 4197 * If the given string is already in the list of completions, then return 4198 * NOTDONE, otherwise add it to the list and return OK. If there is an error, 4199 * maybe because alloc() returns NULL, then FAIL is returned. 4200 */ 4201 int 4202 ins_compl_add_tv(typval_T *tv, int dir) 4203 { 4204 char_u *word; 4205 int icase = FALSE; 4206 int adup = FALSE; 4207 int aempty = FALSE; 4208 char_u *(cptext[CPT_COUNT]); 4209 4210 if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) 4211 { 4212 word = get_dict_string(tv->vval.v_dict, (char_u *)"word", FALSE); 4213 cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, 4214 (char_u *)"abbr", FALSE); 4215 cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, 4216 (char_u *)"menu", FALSE); 4217 cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, 4218 (char_u *)"kind", FALSE); 4219 cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, 4220 (char_u *)"info", FALSE); 4221 if (get_dict_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL) 4222 icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase"); 4223 if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL) 4224 adup = get_dict_number(tv->vval.v_dict, (char_u *)"dup"); 4225 if (get_dict_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL) 4226 aempty = get_dict_number(tv->vval.v_dict, (char_u *)"empty"); 4227 } 4228 else 4229 { 4230 word = get_tv_string_chk(tv); 4231 vim_memset(cptext, 0, sizeof(cptext)); 4232 } 4233 if (word == NULL || (!aempty && *word == NUL)) 4234 return FAIL; 4235 return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup); 4236 } 4237 #endif 4238 4239 /* 4240 * Get the next expansion(s), using "compl_pattern". 4241 * The search starts at position "ini" in curbuf and in the direction 4242 * compl_direction. 4243 * When "compl_started" is FALSE start at that position, otherwise continue 4244 * where we stopped searching before. 4245 * This may return before finding all the matches. 4246 * Return the total number of matches or -1 if still unknown -- Acevedo 4247 */ 4248 static int 4249 ins_compl_get_exp(pos_T *ini) 4250 { 4251 static pos_T first_match_pos; 4252 static pos_T last_match_pos; 4253 static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */ 4254 static int found_all = FALSE; /* Found all matches of a 4255 certain type. */ 4256 static buf_T *ins_buf = NULL; /* buffer being scanned */ 4257 4258 pos_T *pos; 4259 char_u **matches; 4260 int save_p_scs; 4261 int save_p_ws; 4262 int save_p_ic; 4263 int i; 4264 int num_matches; 4265 int len; 4266 int found_new_match; 4267 int type = ctrl_x_mode; 4268 char_u *ptr; 4269 char_u *dict = NULL; 4270 int dict_f = 0; 4271 int set_match_pos; 4272 4273 if (!compl_started) 4274 { 4275 FOR_ALL_BUFFERS(ins_buf) 4276 ins_buf->b_scanned = 0; 4277 found_all = FALSE; 4278 ins_buf = curbuf; 4279 e_cpt = (compl_cont_status & CONT_LOCAL) 4280 ? (char_u *)"." : curbuf->b_p_cpt; 4281 last_match_pos = first_match_pos = *ini; 4282 } 4283 4284 compl_old_match = compl_curr_match; /* remember the last current match */ 4285 pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos; 4286 /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */ 4287 for (;;) 4288 { 4289 found_new_match = FAIL; 4290 set_match_pos = FALSE; 4291 4292 /* For ^N/^P pick a new entry from e_cpt if compl_started is off, 4293 * or if found_all says this entry is done. For ^X^L only use the 4294 * entries from 'complete' that look in loaded buffers. */ 4295 if ((ctrl_x_mode == 0 || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4296 && (!compl_started || found_all)) 4297 { 4298 found_all = FALSE; 4299 while (*e_cpt == ',' || *e_cpt == ' ') 4300 e_cpt++; 4301 if (*e_cpt == '.' && !curbuf->b_scanned) 4302 { 4303 ins_buf = curbuf; 4304 first_match_pos = *ini; 4305 /* Move the cursor back one character so that ^N can match the 4306 * word immediately after the cursor. */ 4307 if (ctrl_x_mode == 0 && dec(&first_match_pos) < 0) 4308 { 4309 /* Move the cursor to after the last character in the 4310 * buffer, so that word at start of buffer is found 4311 * correctly. */ 4312 first_match_pos.lnum = ins_buf->b_ml.ml_line_count; 4313 first_match_pos.col = 4314 (colnr_T)STRLEN(ml_get(first_match_pos.lnum)); 4315 } 4316 last_match_pos = first_match_pos; 4317 type = 0; 4318 4319 /* Remember the first match so that the loop stops when we 4320 * wrap and come back there a second time. */ 4321 set_match_pos = TRUE; 4322 } 4323 else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL 4324 && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf) 4325 { 4326 /* Scan a buffer, but not the current one. */ 4327 if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */ 4328 { 4329 compl_started = TRUE; 4330 first_match_pos.col = last_match_pos.col = 0; 4331 first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1; 4332 last_match_pos.lnum = 0; 4333 type = 0; 4334 } 4335 else /* unloaded buffer, scan like dictionary */ 4336 { 4337 found_all = TRUE; 4338 if (ins_buf->b_fname == NULL) 4339 continue; 4340 type = CTRL_X_DICTIONARY; 4341 dict = ins_buf->b_fname; 4342 dict_f = DICT_EXACT; 4343 } 4344 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"), 4345 ins_buf->b_fname == NULL 4346 ? buf_spname(ins_buf) 4347 : ins_buf->b_sfname == NULL 4348 ? ins_buf->b_fname 4349 : ins_buf->b_sfname); 4350 (void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R)); 4351 } 4352 else if (*e_cpt == NUL) 4353 break; 4354 else 4355 { 4356 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4357 type = -1; 4358 else if (*e_cpt == 'k' || *e_cpt == 's') 4359 { 4360 if (*e_cpt == 'k') 4361 type = CTRL_X_DICTIONARY; 4362 else 4363 type = CTRL_X_THESAURUS; 4364 if (*++e_cpt != ',' && *e_cpt != NUL) 4365 { 4366 dict = e_cpt; 4367 dict_f = DICT_FIRST; 4368 } 4369 } 4370 #ifdef FEAT_FIND_ID 4371 else if (*e_cpt == 'i') 4372 type = CTRL_X_PATH_PATTERNS; 4373 else if (*e_cpt == 'd') 4374 type = CTRL_X_PATH_DEFINES; 4375 #endif 4376 else if (*e_cpt == ']' || *e_cpt == 't') 4377 { 4378 type = CTRL_X_TAGS; 4379 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags.")); 4380 (void)msg_trunc_attr(IObuff, TRUE, HL_ATTR(HLF_R)); 4381 } 4382 else 4383 type = -1; 4384 4385 /* in any case e_cpt is advanced to the next entry */ 4386 (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ","); 4387 4388 found_all = TRUE; 4389 if (type == -1) 4390 continue; 4391 } 4392 } 4393 4394 /* If complete() was called then compl_pattern has been reset. The 4395 * following won't work then, bail out. */ 4396 if (compl_pattern == NULL) 4397 break; 4398 4399 switch (type) 4400 { 4401 case -1: 4402 break; 4403 #ifdef FEAT_FIND_ID 4404 case CTRL_X_PATH_PATTERNS: 4405 case CTRL_X_PATH_DEFINES: 4406 find_pattern_in_path(compl_pattern, compl_direction, 4407 (int)STRLEN(compl_pattern), FALSE, FALSE, 4408 (type == CTRL_X_PATH_DEFINES 4409 && !(compl_cont_status & CONT_SOL)) 4410 ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND, 4411 (linenr_T)1, (linenr_T)MAXLNUM); 4412 break; 4413 #endif 4414 4415 case CTRL_X_DICTIONARY: 4416 case CTRL_X_THESAURUS: 4417 ins_compl_dictionaries( 4418 dict != NULL ? dict 4419 : (type == CTRL_X_THESAURUS 4420 ? (*curbuf->b_p_tsr == NUL 4421 ? p_tsr 4422 : curbuf->b_p_tsr) 4423 : (*curbuf->b_p_dict == NUL 4424 ? p_dict 4425 : curbuf->b_p_dict)), 4426 compl_pattern, 4427 dict != NULL ? dict_f 4428 : 0, type == CTRL_X_THESAURUS); 4429 dict = NULL; 4430 break; 4431 4432 case CTRL_X_TAGS: 4433 /* set p_ic according to p_ic, p_scs and pat for find_tags(). */ 4434 save_p_ic = p_ic; 4435 p_ic = ignorecase(compl_pattern); 4436 4437 /* Find up to TAG_MANY matches. Avoids that an enormous number 4438 * of matches is found when compl_pattern is empty */ 4439 if (find_tags(compl_pattern, &num_matches, &matches, 4440 TAG_REGEXP | TAG_NAMES | TAG_NOIC | 4441 TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), 4442 TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) 4443 { 4444 ins_compl_add_matches(num_matches, matches, p_ic); 4445 } 4446 p_ic = save_p_ic; 4447 break; 4448 4449 case CTRL_X_FILES: 4450 if (expand_wildcards(1, &compl_pattern, &num_matches, &matches, 4451 EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) 4452 { 4453 4454 /* May change home directory back to "~". */ 4455 tilde_replace(compl_pattern, num_matches, matches); 4456 ins_compl_add_matches(num_matches, matches, p_fic || p_wic); 4457 } 4458 break; 4459 4460 case CTRL_X_CMDLINE: 4461 if (expand_cmdline(&compl_xp, compl_pattern, 4462 (int)STRLEN(compl_pattern), 4463 &num_matches, &matches) == EXPAND_OK) 4464 ins_compl_add_matches(num_matches, matches, FALSE); 4465 break; 4466 4467 #ifdef FEAT_COMPL_FUNC 4468 case CTRL_X_FUNCTION: 4469 case CTRL_X_OMNI: 4470 expand_by_function(type, compl_pattern); 4471 break; 4472 #endif 4473 4474 case CTRL_X_SPELL: 4475 #ifdef FEAT_SPELL 4476 num_matches = expand_spelling(first_match_pos.lnum, 4477 compl_pattern, &matches); 4478 if (num_matches > 0) 4479 ins_compl_add_matches(num_matches, matches, p_ic); 4480 #endif 4481 break; 4482 4483 default: /* normal ^P/^N and ^X^L */ 4484 /* 4485 * If 'infercase' is set, don't use 'smartcase' here 4486 */ 4487 save_p_scs = p_scs; 4488 if (ins_buf->b_p_inf) 4489 p_scs = FALSE; 4490 4491 /* Buffers other than curbuf are scanned from the beginning or the 4492 * end but never from the middle, thus setting nowrapscan in this 4493 * buffers is a good idea, on the other hand, we always set 4494 * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */ 4495 save_p_ws = p_ws; 4496 if (ins_buf != curbuf) 4497 p_ws = FALSE; 4498 else if (*e_cpt == '.') 4499 p_ws = TRUE; 4500 for (;;) 4501 { 4502 int flags = 0; 4503 4504 ++msg_silent; /* Don't want messages for wrapscan. */ 4505 4506 /* CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode) 4507 * || word-wise search that 4508 * has added a word that was at the beginning of the line */ 4509 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode) 4510 || (compl_cont_status & CONT_SOL)) 4511 found_new_match = search_for_exact_line(ins_buf, pos, 4512 compl_direction, compl_pattern); 4513 else 4514 found_new_match = searchit(NULL, ins_buf, pos, 4515 compl_direction, 4516 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, 4517 RE_LAST, (linenr_T)0, NULL, NULL); 4518 --msg_silent; 4519 if (!compl_started || set_match_pos) 4520 { 4521 /* set "compl_started" even on fail */ 4522 compl_started = TRUE; 4523 first_match_pos = *pos; 4524 last_match_pos = *pos; 4525 set_match_pos = FALSE; 4526 } 4527 else if (first_match_pos.lnum == last_match_pos.lnum 4528 && first_match_pos.col == last_match_pos.col) 4529 found_new_match = FAIL; 4530 if (found_new_match == FAIL) 4531 { 4532 if (ins_buf == curbuf) 4533 found_all = TRUE; 4534 break; 4535 } 4536 4537 /* when ADDING, the text before the cursor matches, skip it */ 4538 if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf 4539 && ini->lnum == pos->lnum 4540 && ini->col == pos->col) 4541 continue; 4542 ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col; 4543 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4544 { 4545 if (compl_cont_status & CONT_ADDING) 4546 { 4547 if (pos->lnum >= ins_buf->b_ml.ml_line_count) 4548 continue; 4549 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); 4550 if (!p_paste) 4551 ptr = skipwhite(ptr); 4552 } 4553 len = (int)STRLEN(ptr); 4554 } 4555 else 4556 { 4557 char_u *tmp_ptr = ptr; 4558 4559 if (compl_cont_status & CONT_ADDING) 4560 { 4561 tmp_ptr += compl_length; 4562 /* Skip if already inside a word. */ 4563 if (vim_iswordp(tmp_ptr)) 4564 continue; 4565 /* Find start of next word. */ 4566 tmp_ptr = find_word_start(tmp_ptr); 4567 } 4568 /* Find end of this word. */ 4569 tmp_ptr = find_word_end(tmp_ptr); 4570 len = (int)(tmp_ptr - ptr); 4571 4572 if ((compl_cont_status & CONT_ADDING) 4573 && len == compl_length) 4574 { 4575 if (pos->lnum < ins_buf->b_ml.ml_line_count) 4576 { 4577 /* Try next line, if any. the new word will be 4578 * "join" as if the normal command "J" was used. 4579 * IOSIZE is always greater than 4580 * compl_length, so the next STRNCPY always 4581 * works -- Acevedo */ 4582 STRNCPY(IObuff, ptr, len); 4583 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); 4584 tmp_ptr = ptr = skipwhite(ptr); 4585 /* Find start of next word. */ 4586 tmp_ptr = find_word_start(tmp_ptr); 4587 /* Find end of next word. */ 4588 tmp_ptr = find_word_end(tmp_ptr); 4589 if (tmp_ptr > ptr) 4590 { 4591 if (*ptr != ')' && IObuff[len - 1] != TAB) 4592 { 4593 if (IObuff[len - 1] != ' ') 4594 IObuff[len++] = ' '; 4595 /* IObuf =~ "\k.* ", thus len >= 2 */ 4596 if (p_js 4597 && (IObuff[len - 2] == '.' 4598 || (vim_strchr(p_cpo, CPO_JOINSP) 4599 == NULL 4600 && (IObuff[len - 2] == '?' 4601 || IObuff[len - 2] == '!')))) 4602 IObuff[len++] = ' '; 4603 } 4604 /* copy as much as possible of the new word */ 4605 if (tmp_ptr - ptr >= IOSIZE - len) 4606 tmp_ptr = ptr + IOSIZE - len - 1; 4607 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr); 4608 len += (int)(tmp_ptr - ptr); 4609 flags |= CONT_S_IPOS; 4610 } 4611 IObuff[len] = NUL; 4612 ptr = IObuff; 4613 } 4614 if (len == compl_length) 4615 continue; 4616 } 4617 } 4618 if (ins_compl_add_infercase(ptr, len, p_ic, 4619 ins_buf == curbuf ? NULL : ins_buf->b_sfname, 4620 0, flags) != NOTDONE) 4621 { 4622 found_new_match = OK; 4623 break; 4624 } 4625 } 4626 p_scs = save_p_scs; 4627 p_ws = save_p_ws; 4628 } 4629 4630 /* check if compl_curr_match has changed, (e.g. other type of 4631 * expansion added something) */ 4632 if (type != 0 && compl_curr_match != compl_old_match) 4633 found_new_match = OK; 4634 4635 /* break the loop for specialized modes (use 'complete' just for the 4636 * generic ctrl_x_mode == 0) or when we've found a new match */ 4637 if ((ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4638 || found_new_match != FAIL) 4639 { 4640 if (got_int) 4641 break; 4642 /* Fill the popup menu as soon as possible. */ 4643 if (type != -1) 4644 ins_compl_check_keys(0, FALSE); 4645 4646 if ((ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4647 || compl_interrupted) 4648 break; 4649 compl_started = TRUE; 4650 } 4651 else 4652 { 4653 /* Mark a buffer scanned when it has been scanned completely */ 4654 if (type == 0 || type == CTRL_X_PATH_PATTERNS) 4655 ins_buf->b_scanned = TRUE; 4656 4657 compl_started = FALSE; 4658 } 4659 } 4660 compl_started = TRUE; 4661 4662 if ((ctrl_x_mode == 0 || CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 4663 && *e_cpt == NUL) /* Got to end of 'complete' */ 4664 found_new_match = FAIL; 4665 4666 i = -1; /* total of matches, unknown */ 4667 if (found_new_match == FAIL 4668 || (ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))) 4669 i = ins_compl_make_cyclic(); 4670 4671 if (compl_old_match != NULL) 4672 { 4673 /* If several matches were added (FORWARD) or the search failed and has 4674 * just been made cyclic then we have to move compl_curr_match to the 4675 * next or previous entry (if any) -- Acevedo */ 4676 compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next 4677 : compl_old_match->cp_prev; 4678 if (compl_curr_match == NULL) 4679 compl_curr_match = compl_old_match; 4680 } 4681 return i; 4682 } 4683 4684 /* Delete the old text being completed. */ 4685 static void 4686 ins_compl_delete(void) 4687 { 4688 int col; 4689 4690 /* 4691 * In insert mode: Delete the typed part. 4692 * In replace mode: Put the old characters back, if any. 4693 */ 4694 col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); 4695 if ((int)curwin->w_cursor.col > col) 4696 { 4697 if (stop_arrow() == FAIL) 4698 return; 4699 backspace_until_column(col); 4700 } 4701 4702 /* TODO: is this sufficient for redrawing? Redrawing everything causes 4703 * flicker, thus we can't do that. */ 4704 changed_cline_bef_curs(); 4705 /* clear v:completed_item */ 4706 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); 4707 } 4708 4709 /* 4710 * Insert the new text being completed. 4711 * "in_compl_func" is TRUE when called from complete_check(). 4712 */ 4713 static void 4714 ins_compl_insert(int in_compl_func) 4715 { 4716 dict_T *dict; 4717 4718 ins_bytes(compl_shown_match->cp_str + ins_compl_len()); 4719 if (compl_shown_match->cp_flags & ORIGINAL_TEXT) 4720 compl_used_match = FALSE; 4721 else 4722 compl_used_match = TRUE; 4723 4724 /* Set completed item. */ 4725 /* { word, abbr, menu, kind, info } */ 4726 dict = dict_alloc(); 4727 if (dict != NULL) 4728 { 4729 dict_add_nr_str(dict, "word", 0L, 4730 EMPTY_IF_NULL(compl_shown_match->cp_str)); 4731 dict_add_nr_str(dict, "abbr", 0L, 4732 EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); 4733 dict_add_nr_str(dict, "menu", 0L, 4734 EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); 4735 dict_add_nr_str(dict, "kind", 0L, 4736 EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); 4737 dict_add_nr_str(dict, "info", 0L, 4738 EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); 4739 } 4740 set_vim_var_dict(VV_COMPLETED_ITEM, dict); 4741 if (!in_compl_func) 4742 compl_curr_match = compl_shown_match; 4743 } 4744 4745 /* 4746 * Fill in the next completion in the current direction. 4747 * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to 4748 * get more completions. If it is FALSE, then we just do nothing when there 4749 * are no more completions in a given direction. The latter case is used when 4750 * we are still in the middle of finding completions, to allow browsing 4751 * through the ones found so far. 4752 * Return the total number of matches, or -1 if still unknown -- webb. 4753 * 4754 * compl_curr_match is currently being used by ins_compl_get_exp(), so we use 4755 * compl_shown_match here. 4756 * 4757 * Note that this function may be called recursively once only. First with 4758 * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn 4759 * calls this function with "allow_get_expansion" FALSE. 4760 */ 4761 static int 4762 ins_compl_next( 4763 int allow_get_expansion, 4764 int count, /* repeat completion this many times; should 4765 be at least 1 */ 4766 int insert_match, /* Insert the newly selected match */ 4767 int in_compl_func) /* called from complete_check() */ 4768 { 4769 int num_matches = -1; 4770 int todo = count; 4771 compl_T *found_compl = NULL; 4772 int found_end = FALSE; 4773 int advance; 4774 int started = compl_started; 4775 4776 /* When user complete function return -1 for findstart which is next 4777 * time of 'always', compl_shown_match become NULL. */ 4778 if (compl_shown_match == NULL) 4779 return -1; 4780 4781 if (compl_leader != NULL 4782 && (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0) 4783 { 4784 /* Set "compl_shown_match" to the actually shown match, it may differ 4785 * when "compl_leader" is used to omit some of the matches. */ 4786 while (!ins_compl_equal(compl_shown_match, 4787 compl_leader, (int)STRLEN(compl_leader)) 4788 && compl_shown_match->cp_next != NULL 4789 && compl_shown_match->cp_next != compl_first_match) 4790 compl_shown_match = compl_shown_match->cp_next; 4791 4792 /* If we didn't find it searching forward, and compl_shows_dir is 4793 * backward, find the last match. */ 4794 if (compl_shows_dir == BACKWARD 4795 && !ins_compl_equal(compl_shown_match, 4796 compl_leader, (int)STRLEN(compl_leader)) 4797 && (compl_shown_match->cp_next == NULL 4798 || compl_shown_match->cp_next == compl_first_match)) 4799 { 4800 while (!ins_compl_equal(compl_shown_match, 4801 compl_leader, (int)STRLEN(compl_leader)) 4802 && compl_shown_match->cp_prev != NULL 4803 && compl_shown_match->cp_prev != compl_first_match) 4804 compl_shown_match = compl_shown_match->cp_prev; 4805 } 4806 } 4807 4808 if (allow_get_expansion && insert_match 4809 && (!(compl_get_longest || compl_restarting) || compl_used_match)) 4810 /* Delete old text to be replaced */ 4811 ins_compl_delete(); 4812 4813 /* When finding the longest common text we stick at the original text, 4814 * don't let CTRL-N or CTRL-P move to the first match. */ 4815 advance = count != 1 || !allow_get_expansion || !compl_get_longest; 4816 4817 /* When restarting the search don't insert the first match either. */ 4818 if (compl_restarting) 4819 { 4820 advance = FALSE; 4821 compl_restarting = FALSE; 4822 } 4823 4824 /* Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap 4825 * around. */ 4826 while (--todo >= 0) 4827 { 4828 if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL) 4829 { 4830 compl_shown_match = compl_shown_match->cp_next; 4831 found_end = (compl_first_match != NULL 4832 && (compl_shown_match->cp_next == compl_first_match 4833 || compl_shown_match == compl_first_match)); 4834 } 4835 else if (compl_shows_dir == BACKWARD 4836 && compl_shown_match->cp_prev != NULL) 4837 { 4838 found_end = (compl_shown_match == compl_first_match); 4839 compl_shown_match = compl_shown_match->cp_prev; 4840 found_end |= (compl_shown_match == compl_first_match); 4841 } 4842 else 4843 { 4844 if (!allow_get_expansion) 4845 { 4846 if (advance) 4847 { 4848 if (compl_shows_dir == BACKWARD) 4849 compl_pending -= todo + 1; 4850 else 4851 compl_pending += todo + 1; 4852 } 4853 return -1; 4854 } 4855 4856 if (!compl_no_select && advance) 4857 { 4858 if (compl_shows_dir == BACKWARD) 4859 --compl_pending; 4860 else 4861 ++compl_pending; 4862 } 4863 4864 /* Find matches. */ 4865 num_matches = ins_compl_get_exp(&compl_startpos); 4866 4867 /* handle any pending completions */ 4868 while (compl_pending != 0 && compl_direction == compl_shows_dir 4869 && advance) 4870 { 4871 if (compl_pending > 0 && compl_shown_match->cp_next != NULL) 4872 { 4873 compl_shown_match = compl_shown_match->cp_next; 4874 --compl_pending; 4875 } 4876 if (compl_pending < 0 && compl_shown_match->cp_prev != NULL) 4877 { 4878 compl_shown_match = compl_shown_match->cp_prev; 4879 ++compl_pending; 4880 } 4881 else 4882 break; 4883 } 4884 found_end = FALSE; 4885 } 4886 if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0 4887 && compl_leader != NULL 4888 && !ins_compl_equal(compl_shown_match, 4889 compl_leader, (int)STRLEN(compl_leader))) 4890 ++todo; 4891 else 4892 /* Remember a matching item. */ 4893 found_compl = compl_shown_match; 4894 4895 /* Stop at the end of the list when we found a usable match. */ 4896 if (found_end) 4897 { 4898 if (found_compl != NULL) 4899 { 4900 compl_shown_match = found_compl; 4901 break; 4902 } 4903 todo = 1; /* use first usable match after wrapping around */ 4904 } 4905 } 4906 4907 /* Insert the text of the new completion, or the compl_leader. */ 4908 if (compl_no_insert && !started) 4909 { 4910 ins_bytes(compl_orig_text + ins_compl_len()); 4911 compl_used_match = FALSE; 4912 } 4913 else if (insert_match) 4914 { 4915 if (!compl_get_longest || compl_used_match) 4916 ins_compl_insert(in_compl_func); 4917 else 4918 ins_bytes(compl_leader + ins_compl_len()); 4919 } 4920 else 4921 compl_used_match = FALSE; 4922 4923 if (!allow_get_expansion) 4924 { 4925 /* may undisplay the popup menu first */ 4926 ins_compl_upd_pum(); 4927 4928 /* redraw to show the user what was inserted */ 4929 update_screen(0); 4930 4931 /* display the updated popup menu */ 4932 ins_compl_show_pum(); 4933 #ifdef FEAT_GUI 4934 if (gui.in_use) 4935 { 4936 /* Show the cursor after the match, not after the redrawn text. */ 4937 setcursor(); 4938 out_flush(); 4939 gui_update_cursor(FALSE, FALSE); 4940 } 4941 #endif 4942 4943 /* Delete old text to be replaced, since we're still searching and 4944 * don't want to match ourselves! */ 4945 ins_compl_delete(); 4946 } 4947 4948 /* Enter will select a match when the match wasn't inserted and the popup 4949 * menu is visible. */ 4950 if (compl_no_insert && !started) 4951 compl_enter_selects = TRUE; 4952 else 4953 compl_enter_selects = !insert_match && compl_match_array != NULL; 4954 4955 /* 4956 * Show the file name for the match (if any) 4957 * Truncate the file name to avoid a wait for return. 4958 */ 4959 if (compl_shown_match->cp_fname != NULL) 4960 { 4961 char *lead = _("match in file"); 4962 int space = sc_col - vim_strsize((char_u *)lead) - 2; 4963 char_u *s; 4964 char_u *e; 4965 4966 if (space > 0) 4967 { 4968 /* We need the tail that fits. With double-byte encoding going 4969 * back from the end is very slow, thus go from the start and keep 4970 * the text that fits in "space" between "s" and "e". */ 4971 for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e)) 4972 { 4973 space -= ptr2cells(e); 4974 while (space < 0) 4975 { 4976 space += ptr2cells(s); 4977 MB_PTR_ADV(s); 4978 } 4979 } 4980 vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead, 4981 s > compl_shown_match->cp_fname ? "<" : "", s); 4982 msg(IObuff); 4983 redraw_cmdline = FALSE; /* don't overwrite! */ 4984 } 4985 } 4986 4987 return num_matches; 4988 } 4989 4990 /* 4991 * Call this while finding completions, to check whether the user has hit a key 4992 * that should change the currently displayed completion, or exit completion 4993 * mode. Also, when compl_pending is not zero, show a completion as soon as 4994 * possible. -- webb 4995 * "frequency" specifies out of how many calls we actually check. 4996 * "in_compl_func" is TRUE when called from complete_check(), don't set 4997 * compl_curr_match. 4998 */ 4999 void 5000 ins_compl_check_keys(int frequency, int in_compl_func) 5001 { 5002 static int count = 0; 5003 5004 int c; 5005 5006 /* Don't check when reading keys from a script. That would break the test 5007 * scripts */ 5008 if (using_script()) 5009 return; 5010 5011 /* Only do this at regular intervals */ 5012 if (++count < frequency) 5013 return; 5014 count = 0; 5015 5016 /* Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key() 5017 * can't do its work correctly. */ 5018 c = vpeekc_any(); 5019 if (c != NUL) 5020 { 5021 if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) 5022 { 5023 c = safe_vgetc(); /* Eat the character */ 5024 compl_shows_dir = ins_compl_key2dir(c); 5025 (void)ins_compl_next(FALSE, ins_compl_key2count(c), 5026 c != K_UP && c != K_DOWN, in_compl_func); 5027 } 5028 else 5029 { 5030 /* Need to get the character to have KeyTyped set. We'll put it 5031 * back with vungetc() below. But skip K_IGNORE. */ 5032 c = safe_vgetc(); 5033 if (c != K_IGNORE) 5034 { 5035 /* Don't interrupt completion when the character wasn't typed, 5036 * e.g., when doing @q to replay keys. */ 5037 if (c != Ctrl_R && KeyTyped) 5038 compl_interrupted = TRUE; 5039 5040 vungetc(c); 5041 } 5042 } 5043 } 5044 if (compl_pending != 0 && !got_int && !compl_no_insert) 5045 { 5046 int todo = compl_pending > 0 ? compl_pending : -compl_pending; 5047 5048 compl_pending = 0; 5049 (void)ins_compl_next(FALSE, todo, TRUE, in_compl_func); 5050 } 5051 } 5052 5053 /* 5054 * Decide the direction of Insert mode complete from the key typed. 5055 * Returns BACKWARD or FORWARD. 5056 */ 5057 static int 5058 ins_compl_key2dir(int c) 5059 { 5060 if (c == Ctrl_P || c == Ctrl_L 5061 || c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP || c == K_UP) 5062 return BACKWARD; 5063 return FORWARD; 5064 } 5065 5066 /* 5067 * Return TRUE for keys that are used for completion only when the popup menu 5068 * is visible. 5069 */ 5070 static int 5071 ins_compl_pum_key(int c) 5072 { 5073 return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP 5074 || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN 5075 || c == K_UP || c == K_DOWN); 5076 } 5077 5078 /* 5079 * Decide the number of completions to move forward. 5080 * Returns 1 for most keys, height of the popup menu for page-up/down keys. 5081 */ 5082 static int 5083 ins_compl_key2count(int c) 5084 { 5085 int h; 5086 5087 if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN) 5088 { 5089 h = pum_get_height(); 5090 if (h > 3) 5091 h -= 2; /* keep some context */ 5092 return h; 5093 } 5094 return 1; 5095 } 5096 5097 /* 5098 * Return TRUE if completion with "c" should insert the match, FALSE if only 5099 * to change the currently selected completion. 5100 */ 5101 static int 5102 ins_compl_use_match(int c) 5103 { 5104 switch (c) 5105 { 5106 case K_UP: 5107 case K_DOWN: 5108 case K_PAGEDOWN: 5109 case K_KPAGEDOWN: 5110 case K_S_DOWN: 5111 case K_PAGEUP: 5112 case K_KPAGEUP: 5113 case K_S_UP: 5114 return FALSE; 5115 } 5116 return TRUE; 5117 } 5118 5119 /* 5120 * Do Insert mode completion. 5121 * Called when character "c" was typed, which has a meaning for completion. 5122 * Returns OK if completion was done, FAIL if something failed (out of mem). 5123 */ 5124 static int 5125 ins_complete(int c, int enable_pum) 5126 { 5127 char_u *line; 5128 int startcol = 0; /* column where searched text starts */ 5129 colnr_T curs_col; /* cursor column */ 5130 int n; 5131 int save_w_wrow; 5132 int save_w_leftcol; 5133 int insert_match; 5134 int save_did_ai = did_ai; 5135 5136 compl_direction = ins_compl_key2dir(c); 5137 insert_match = ins_compl_use_match(c); 5138 5139 if (!compl_started) 5140 { 5141 /* First time we hit ^N or ^P (in a row, I mean) */ 5142 5143 did_ai = FALSE; 5144 #ifdef FEAT_SMARTINDENT 5145 did_si = FALSE; 5146 can_si = FALSE; 5147 can_si_back = FALSE; 5148 #endif 5149 if (stop_arrow() == FAIL) 5150 return FAIL; 5151 5152 line = ml_get(curwin->w_cursor.lnum); 5153 curs_col = curwin->w_cursor.col; 5154 compl_pending = 0; 5155 5156 /* If this same ctrl_x_mode has been interrupted use the text from 5157 * "compl_startpos" to the cursor as a pattern to add a new word 5158 * instead of expand the one before the cursor, in word-wise if 5159 * "compl_startpos" is not in the same line as the cursor then fix it 5160 * (the line has been split because it was longer than 'tw'). if SOL 5161 * is set then skip the previous pattern, a word at the beginning of 5162 * the line has been inserted, we'll look for that -- Acevedo. */ 5163 if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT 5164 && compl_cont_mode == ctrl_x_mode) 5165 { 5166 /* 5167 * it is a continued search 5168 */ 5169 compl_cont_status &= ~CONT_INTRPT; /* remove INTRPT */ 5170 if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS 5171 || ctrl_x_mode == CTRL_X_PATH_DEFINES) 5172 { 5173 if (compl_startpos.lnum != curwin->w_cursor.lnum) 5174 { 5175 /* line (probably) wrapped, set compl_startpos to the 5176 * first non_blank in the line, if it is not a wordchar 5177 * include it to get a better pattern, but then we don't 5178 * want the "\\<" prefix, check it bellow */ 5179 compl_col = (colnr_T)getwhitecols(line); 5180 compl_startpos.col = compl_col; 5181 compl_startpos.lnum = curwin->w_cursor.lnum; 5182 compl_cont_status &= ~CONT_SOL; /* clear SOL if present */ 5183 } 5184 else 5185 { 5186 /* S_IPOS was set when we inserted a word that was at the 5187 * beginning of the line, which means that we'll go to SOL 5188 * mode but first we need to redefine compl_startpos */ 5189 if (compl_cont_status & CONT_S_IPOS) 5190 { 5191 compl_cont_status |= CONT_SOL; 5192 compl_startpos.col = (colnr_T)(skipwhite( 5193 line + compl_length 5194 + compl_startpos.col) - line); 5195 } 5196 compl_col = compl_startpos.col; 5197 } 5198 compl_length = curwin->w_cursor.col - (int)compl_col; 5199 /* IObuff is used to add a "word from the next line" would we 5200 * have enough space? just being paranoid */ 5201 #define MIN_SPACE 75 5202 if (compl_length > (IOSIZE - MIN_SPACE)) 5203 { 5204 compl_cont_status &= ~CONT_SOL; 5205 compl_length = (IOSIZE - MIN_SPACE); 5206 compl_col = curwin->w_cursor.col - compl_length; 5207 } 5208 compl_cont_status |= CONT_ADDING | CONT_N_ADDS; 5209 if (compl_length < 1) 5210 compl_cont_status &= CONT_LOCAL; 5211 } 5212 else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 5213 compl_cont_status = CONT_ADDING | CONT_N_ADDS; 5214 else 5215 compl_cont_status = 0; 5216 } 5217 else 5218 compl_cont_status &= CONT_LOCAL; 5219 5220 if (!(compl_cont_status & CONT_ADDING)) /* normal expansion */ 5221 { 5222 compl_cont_mode = ctrl_x_mode; 5223 if (ctrl_x_mode != 0) /* Remove LOCAL if ctrl_x_mode != 0 */ 5224 compl_cont_status = 0; 5225 compl_cont_status |= CONT_N_ADDS; 5226 compl_startpos = curwin->w_cursor; 5227 startcol = (int)curs_col; 5228 compl_col = 0; 5229 } 5230 5231 /* Work out completion pattern and original text -- webb */ 5232 if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT)) 5233 { 5234 if ((compl_cont_status & CONT_SOL) 5235 || ctrl_x_mode == CTRL_X_PATH_DEFINES) 5236 { 5237 if (!(compl_cont_status & CONT_ADDING)) 5238 { 5239 while (--startcol >= 0 && vim_isIDc(line[startcol])) 5240 ; 5241 compl_col += ++startcol; 5242 compl_length = curs_col - startcol; 5243 } 5244 if (p_ic) 5245 compl_pattern = str_foldcase(line + compl_col, 5246 compl_length, NULL, 0); 5247 else 5248 compl_pattern = vim_strnsave(line + compl_col, 5249 compl_length); 5250 if (compl_pattern == NULL) 5251 return FAIL; 5252 } 5253 else if (compl_cont_status & CONT_ADDING) 5254 { 5255 char_u *prefix = (char_u *)"\\<"; 5256 5257 /* we need up to 2 extra chars for the prefix */ 5258 compl_pattern = alloc(quote_meta(NULL, line + compl_col, 5259 compl_length) + 2); 5260 if (compl_pattern == NULL) 5261 return FAIL; 5262 if (!vim_iswordp(line + compl_col) 5263 || (compl_col > 0 5264 && ( 5265 #ifdef FEAT_MBYTE 5266 vim_iswordp(mb_prevptr(line, line + compl_col)) 5267 #else 5268 vim_iswordc(line[compl_col - 1]) 5269 #endif 5270 ))) 5271 prefix = (char_u *)""; 5272 STRCPY((char *)compl_pattern, prefix); 5273 (void)quote_meta(compl_pattern + STRLEN(prefix), 5274 line + compl_col, compl_length); 5275 } 5276 else if (--startcol < 0 || 5277 #ifdef FEAT_MBYTE 5278 !vim_iswordp(mb_prevptr(line, line + startcol + 1)) 5279 #else 5280 !vim_iswordc(line[startcol]) 5281 #endif 5282 ) 5283 { 5284 /* Match any word of at least two chars */ 5285 compl_pattern = vim_strsave((char_u *)"\\<\\k\\k"); 5286 if (compl_pattern == NULL) 5287 return FAIL; 5288 compl_col += curs_col; 5289 compl_length = 0; 5290 } 5291 else 5292 { 5293 #ifdef FEAT_MBYTE 5294 /* Search the point of change class of multibyte character 5295 * or not a word single byte character backward. */ 5296 if (has_mbyte) 5297 { 5298 int base_class; 5299 int head_off; 5300 5301 startcol -= (*mb_head_off)(line, line + startcol); 5302 base_class = mb_get_class(line + startcol); 5303 while (--startcol >= 0) 5304 { 5305 head_off = (*mb_head_off)(line, line + startcol); 5306 if (base_class != mb_get_class(line + startcol 5307 - head_off)) 5308 break; 5309 startcol -= head_off; 5310 } 5311 } 5312 else 5313 #endif 5314 while (--startcol >= 0 && vim_iswordc(line[startcol])) 5315 ; 5316 compl_col += ++startcol; 5317 compl_length = (int)curs_col - startcol; 5318 if (compl_length == 1) 5319 { 5320 /* Only match word with at least two chars -- webb 5321 * there's no need to call quote_meta, 5322 * alloc(7) is enough -- Acevedo 5323 */ 5324 compl_pattern = alloc(7); 5325 if (compl_pattern == NULL) 5326 return FAIL; 5327 STRCPY((char *)compl_pattern, "\\<"); 5328 (void)quote_meta(compl_pattern + 2, line + compl_col, 1); 5329 STRCAT((char *)compl_pattern, "\\k"); 5330 } 5331 else 5332 { 5333 compl_pattern = alloc(quote_meta(NULL, line + compl_col, 5334 compl_length) + 2); 5335 if (compl_pattern == NULL) 5336 return FAIL; 5337 STRCPY((char *)compl_pattern, "\\<"); 5338 (void)quote_meta(compl_pattern + 2, line + compl_col, 5339 compl_length); 5340 } 5341 } 5342 } 5343 else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 5344 { 5345 compl_col = (colnr_T)getwhitecols(line); 5346 compl_length = (int)curs_col - (int)compl_col; 5347 if (compl_length < 0) /* cursor in indent: empty pattern */ 5348 compl_length = 0; 5349 if (p_ic) 5350 compl_pattern = str_foldcase(line + compl_col, compl_length, 5351 NULL, 0); 5352 else 5353 compl_pattern = vim_strnsave(line + compl_col, compl_length); 5354 if (compl_pattern == NULL) 5355 return FAIL; 5356 } 5357 else if (ctrl_x_mode == CTRL_X_FILES) 5358 { 5359 /* Go back to just before the first filename character. */ 5360 if (startcol > 0) 5361 { 5362 char_u *p = line + startcol; 5363 5364 MB_PTR_BACK(line, p); 5365 while (p > line && vim_isfilec(PTR2CHAR(p))) 5366 MB_PTR_BACK(line, p); 5367 if (p == line && vim_isfilec(PTR2CHAR(p))) 5368 startcol = 0; 5369 else 5370 startcol = (int)(p - line) + 1; 5371 } 5372 5373 compl_col += startcol; 5374 compl_length = (int)curs_col - startcol; 5375 compl_pattern = addstar(line + compl_col, compl_length, 5376 EXPAND_FILES); 5377 if (compl_pattern == NULL) 5378 return FAIL; 5379 } 5380 else if (ctrl_x_mode == CTRL_X_CMDLINE) 5381 { 5382 compl_pattern = vim_strnsave(line, curs_col); 5383 if (compl_pattern == NULL) 5384 return FAIL; 5385 set_cmd_context(&compl_xp, compl_pattern, 5386 (int)STRLEN(compl_pattern), curs_col, FALSE); 5387 if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL 5388 || compl_xp.xp_context == EXPAND_NOTHING) 5389 /* No completion possible, use an empty pattern to get a 5390 * "pattern not found" message. */ 5391 compl_col = curs_col; 5392 else 5393 compl_col = (int)(compl_xp.xp_pattern - compl_pattern); 5394 compl_length = curs_col - compl_col; 5395 } 5396 else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) 5397 { 5398 #ifdef FEAT_COMPL_FUNC 5399 /* 5400 * Call user defined function 'completefunc' with "a:findstart" 5401 * set to 1 to obtain the length of text to use for completion. 5402 */ 5403 char_u *args[2]; 5404 int col; 5405 char_u *funcname; 5406 pos_T pos; 5407 win_T *curwin_save; 5408 buf_T *curbuf_save; 5409 5410 /* Call 'completefunc' or 'omnifunc' and get pattern length as a 5411 * string */ 5412 funcname = ctrl_x_mode == CTRL_X_FUNCTION 5413 ? curbuf->b_p_cfu : curbuf->b_p_ofu; 5414 if (*funcname == NUL) 5415 { 5416 EMSG2(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION 5417 ? "completefunc" : "omnifunc"); 5418 /* restore did_ai, so that adding comment leader works */ 5419 did_ai = save_did_ai; 5420 return FAIL; 5421 } 5422 5423 args[0] = (char_u *)"1"; 5424 args[1] = NULL; 5425 pos = curwin->w_cursor; 5426 curwin_save = curwin; 5427 curbuf_save = curbuf; 5428 col = call_func_retnr(funcname, 2, args, FALSE); 5429 if (curwin_save != curwin || curbuf_save != curbuf) 5430 { 5431 EMSG(_(e_complwin)); 5432 return FAIL; 5433 } 5434 curwin->w_cursor = pos; /* restore the cursor position */ 5435 validate_cursor(); 5436 if (!EQUAL_POS(curwin->w_cursor, pos)) 5437 { 5438 EMSG(_(e_compldel)); 5439 return FAIL; 5440 } 5441 5442 /* Return value -2 means the user complete function wants to 5443 * cancel the complete without an error. 5444 * Return value -3 does the same as -2 and leaves CTRL-X mode.*/ 5445 if (col == -2) 5446 return FAIL; 5447 if (col == -3) 5448 { 5449 ctrl_x_mode = 0; 5450 edit_submode = NULL; 5451 if (!shortmess(SHM_COMPLETIONMENU)) 5452 msg_clr_cmdline(); 5453 return FAIL; 5454 } 5455 5456 /* 5457 * Reset extended parameters of completion, when start new 5458 * completion. 5459 */ 5460 compl_opt_refresh_always = FALSE; 5461 5462 if (col < 0) 5463 col = curs_col; 5464 compl_col = col; 5465 if (compl_col > curs_col) 5466 compl_col = curs_col; 5467 5468 /* Setup variables for completion. Need to obtain "line" again, 5469 * it may have become invalid. */ 5470 line = ml_get(curwin->w_cursor.lnum); 5471 compl_length = curs_col - compl_col; 5472 compl_pattern = vim_strnsave(line + compl_col, compl_length); 5473 if (compl_pattern == NULL) 5474 #endif 5475 return FAIL; 5476 } 5477 else if (ctrl_x_mode == CTRL_X_SPELL) 5478 { 5479 #ifdef FEAT_SPELL 5480 if (spell_bad_len > 0) 5481 compl_col = curs_col - spell_bad_len; 5482 else 5483 compl_col = spell_word_start(startcol); 5484 if (compl_col >= (colnr_T)startcol) 5485 { 5486 compl_length = 0; 5487 compl_col = curs_col; 5488 } 5489 else 5490 { 5491 spell_expand_check_cap(compl_col); 5492 compl_length = (int)curs_col - compl_col; 5493 } 5494 /* Need to obtain "line" again, it may have become invalid. */ 5495 line = ml_get(curwin->w_cursor.lnum); 5496 compl_pattern = vim_strnsave(line + compl_col, compl_length); 5497 if (compl_pattern == NULL) 5498 #endif 5499 return FAIL; 5500 } 5501 else 5502 { 5503 internal_error("ins_complete()"); 5504 return FAIL; 5505 } 5506 5507 if (compl_cont_status & CONT_ADDING) 5508 { 5509 edit_submode_pre = (char_u *)_(" Adding"); 5510 if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) 5511 { 5512 /* Insert a new line, keep indentation but ignore 'comments' */ 5513 #ifdef FEAT_COMMENTS 5514 char_u *old = curbuf->b_p_com; 5515 5516 curbuf->b_p_com = (char_u *)""; 5517 #endif 5518 compl_startpos.lnum = curwin->w_cursor.lnum; 5519 compl_startpos.col = compl_col; 5520 ins_eol('\r'); 5521 #ifdef FEAT_COMMENTS 5522 curbuf->b_p_com = old; 5523 #endif 5524 compl_length = 0; 5525 compl_col = curwin->w_cursor.col; 5526 } 5527 } 5528 else 5529 { 5530 edit_submode_pre = NULL; 5531 compl_startpos.col = compl_col; 5532 } 5533 5534 if (compl_cont_status & CONT_LOCAL) 5535 edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]); 5536 else 5537 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); 5538 5539 /* If any of the original typed text has been changed we need to fix 5540 * the redo buffer. */ 5541 ins_compl_fixRedoBufForLeader(NULL); 5542 5543 /* Always add completion for the original text. */ 5544 vim_free(compl_orig_text); 5545 compl_orig_text = vim_strnsave(line + compl_col, compl_length); 5546 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, 5547 -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) 5548 { 5549 vim_free(compl_pattern); 5550 compl_pattern = NULL; 5551 vim_free(compl_orig_text); 5552 compl_orig_text = NULL; 5553 return FAIL; 5554 } 5555 5556 /* showmode might reset the internal line pointers, so it must 5557 * be called before line = ml_get(), or when this address is no 5558 * longer needed. -- Acevedo. 5559 */ 5560 edit_submode_extra = (char_u *)_("-- Searching..."); 5561 edit_submode_highl = HLF_COUNT; 5562 showmode(); 5563 edit_submode_extra = NULL; 5564 out_flush(); 5565 } 5566 else if (insert_match && stop_arrow() == FAIL) 5567 return FAIL; 5568 5569 compl_shown_match = compl_curr_match; 5570 compl_shows_dir = compl_direction; 5571 5572 /* 5573 * Find next match (and following matches). 5574 */ 5575 save_w_wrow = curwin->w_wrow; 5576 save_w_leftcol = curwin->w_leftcol; 5577 n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE); 5578 5579 /* may undisplay the popup menu */ 5580 ins_compl_upd_pum(); 5581 5582 if (n > 1) /* all matches have been found */ 5583 compl_matches = n; 5584 compl_curr_match = compl_shown_match; 5585 compl_direction = compl_shows_dir; 5586 5587 /* Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert 5588 * mode. */ 5589 if (got_int && !global_busy) 5590 { 5591 (void)vgetc(); 5592 got_int = FALSE; 5593 } 5594 5595 /* we found no match if the list has only the "compl_orig_text"-entry */ 5596 if (compl_first_match == compl_first_match->cp_next) 5597 { 5598 edit_submode_extra = (compl_cont_status & CONT_ADDING) 5599 && compl_length > 1 5600 ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf); 5601 edit_submode_highl = HLF_E; 5602 /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode, 5603 * because we couldn't expand anything at first place, but if we used 5604 * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word 5605 * (such as M in M'exico) if not tried already. -- Acevedo */ 5606 if ( compl_length > 1 5607 || (compl_cont_status & CONT_ADDING) 5608 || (ctrl_x_mode != 0 5609 && ctrl_x_mode != CTRL_X_PATH_PATTERNS 5610 && ctrl_x_mode != CTRL_X_PATH_DEFINES)) 5611 compl_cont_status &= ~CONT_N_ADDS; 5612 } 5613 5614 if (compl_curr_match->cp_flags & CONT_S_IPOS) 5615 compl_cont_status |= CONT_S_IPOS; 5616 else 5617 compl_cont_status &= ~CONT_S_IPOS; 5618 5619 if (edit_submode_extra == NULL) 5620 { 5621 if (compl_curr_match->cp_flags & ORIGINAL_TEXT) 5622 { 5623 edit_submode_extra = (char_u *)_("Back at original"); 5624 edit_submode_highl = HLF_W; 5625 } 5626 else if (compl_cont_status & CONT_S_IPOS) 5627 { 5628 edit_submode_extra = (char_u *)_("Word from other line"); 5629 edit_submode_highl = HLF_COUNT; 5630 } 5631 else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) 5632 { 5633 edit_submode_extra = (char_u *)_("The only match"); 5634 edit_submode_highl = HLF_COUNT; 5635 } 5636 else 5637 { 5638 /* Update completion sequence number when needed. */ 5639 if (compl_curr_match->cp_number == -1) 5640 { 5641 int number = 0; 5642 compl_T *match; 5643 5644 if (compl_direction == FORWARD) 5645 { 5646 /* search backwards for the first valid (!= -1) number. 5647 * This should normally succeed already at the first loop 5648 * cycle, so it's fast! */ 5649 for (match = compl_curr_match->cp_prev; match != NULL 5650 && match != compl_first_match; 5651 match = match->cp_prev) 5652 if (match->cp_number != -1) 5653 { 5654 number = match->cp_number; 5655 break; 5656 } 5657 if (match != NULL) 5658 /* go up and assign all numbers which are not assigned 5659 * yet */ 5660 for (match = match->cp_next; 5661 match != NULL && match->cp_number == -1; 5662 match = match->cp_next) 5663 match->cp_number = ++number; 5664 } 5665 else /* BACKWARD */ 5666 { 5667 /* search forwards (upwards) for the first valid (!= -1) 5668 * number. This should normally succeed already at the 5669 * first loop cycle, so it's fast! */ 5670 for (match = compl_curr_match->cp_next; match != NULL 5671 && match != compl_first_match; 5672 match = match->cp_next) 5673 if (match->cp_number != -1) 5674 { 5675 number = match->cp_number; 5676 break; 5677 } 5678 if (match != NULL) 5679 /* go down and assign all numbers which are not 5680 * assigned yet */ 5681 for (match = match->cp_prev; match 5682 && match->cp_number == -1; 5683 match = match->cp_prev) 5684 match->cp_number = ++number; 5685 } 5686 } 5687 5688 /* The match should always have a sequence number now, this is 5689 * just a safety check. */ 5690 if (compl_curr_match->cp_number != -1) 5691 { 5692 /* Space for 10 text chars. + 2x10-digit no.s = 31. 5693 * Translations may need more than twice that. */ 5694 static char_u match_ref[81]; 5695 5696 if (compl_matches > 0) 5697 vim_snprintf((char *)match_ref, sizeof(match_ref), 5698 _("match %d of %d"), 5699 compl_curr_match->cp_number, compl_matches); 5700 else 5701 vim_snprintf((char *)match_ref, sizeof(match_ref), 5702 _("match %d"), 5703 compl_curr_match->cp_number); 5704 edit_submode_extra = match_ref; 5705 edit_submode_highl = HLF_R; 5706 if (dollar_vcol >= 0) 5707 curs_columns(FALSE); 5708 } 5709 } 5710 } 5711 5712 /* Show a message about what (completion) mode we're in. */ 5713 showmode(); 5714 if (!shortmess(SHM_COMPLETIONMENU)) 5715 { 5716 if (edit_submode_extra != NULL) 5717 { 5718 if (!p_smd) 5719 msg_attr(edit_submode_extra, 5720 edit_submode_highl < HLF_COUNT 5721 ? HL_ATTR(edit_submode_highl) : 0); 5722 } 5723 else 5724 msg_clr_cmdline(); /* necessary for "noshowmode" */ 5725 } 5726 5727 /* Show the popup menu, unless we got interrupted. */ 5728 if (enable_pum && !compl_interrupted) 5729 show_pum(save_w_wrow, save_w_leftcol); 5730 5731 compl_was_interrupted = compl_interrupted; 5732 compl_interrupted = FALSE; 5733 5734 return OK; 5735 } 5736 5737 static void 5738 show_pum(int prev_w_wrow, int prev_w_leftcol) 5739 { 5740 /* RedrawingDisabled may be set when invoked through complete(). */ 5741 int n = RedrawingDisabled; 5742 5743 RedrawingDisabled = 0; 5744 5745 /* If the cursor moved or the display scrolled we need to remove the pum 5746 * first. */ 5747 setcursor(); 5748 if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol) 5749 ins_compl_del_pum(); 5750 5751 ins_compl_show_pum(); 5752 setcursor(); 5753 RedrawingDisabled = n; 5754 } 5755 5756 /* 5757 * Looks in the first "len" chars. of "src" for search-metachars. 5758 * If dest is not NULL the chars. are copied there quoting (with 5759 * a backslash) the metachars, and dest would be NUL terminated. 5760 * Returns the length (needed) of dest 5761 */ 5762 static unsigned 5763 quote_meta(char_u *dest, char_u *src, int len) 5764 { 5765 unsigned m = (unsigned)len + 1; /* one extra for the NUL */ 5766 5767 for ( ; --len >= 0; src++) 5768 { 5769 switch (*src) 5770 { 5771 case '.': 5772 case '*': 5773 case '[': 5774 if (ctrl_x_mode == CTRL_X_DICTIONARY 5775 || ctrl_x_mode == CTRL_X_THESAURUS) 5776 break; 5777 /* FALLTHROUGH */ 5778 case '~': 5779 if (!p_magic) /* quote these only if magic is set */ 5780 break; 5781 /* FALLTHROUGH */ 5782 case '\\': 5783 if (ctrl_x_mode == CTRL_X_DICTIONARY 5784 || ctrl_x_mode == CTRL_X_THESAURUS) 5785 break; 5786 /* FALLTHROUGH */ 5787 case '^': /* currently it's not needed. */ 5788 case '$': 5789 m++; 5790 if (dest != NULL) 5791 *dest++ = '\\'; 5792 break; 5793 } 5794 if (dest != NULL) 5795 *dest++ = *src; 5796 # ifdef FEAT_MBYTE 5797 /* Copy remaining bytes of a multibyte character. */ 5798 if (has_mbyte) 5799 { 5800 int i, mb_len; 5801 5802 mb_len = (*mb_ptr2len)(src) - 1; 5803 if (mb_len > 0 && len >= mb_len) 5804 for (i = 0; i < mb_len; ++i) 5805 { 5806 --len; 5807 ++src; 5808 if (dest != NULL) 5809 *dest++ = *src; 5810 } 5811 } 5812 # endif 5813 } 5814 if (dest != NULL) 5815 *dest = NUL; 5816 5817 return m; 5818 } 5819 #endif /* FEAT_INS_EXPAND */ 5820 5821 /* 5822 * Next character is interpreted literally. 5823 * A one, two or three digit decimal number is interpreted as its byte value. 5824 * If one or two digits are entered, the next character is given to vungetc(). 5825 * For Unicode a character > 255 may be returned. 5826 */ 5827 int 5828 get_literal(void) 5829 { 5830 int cc; 5831 int nc; 5832 int i; 5833 int hex = FALSE; 5834 int octal = FALSE; 5835 #ifdef FEAT_MBYTE 5836 int unicode = 0; 5837 #endif 5838 5839 if (got_int) 5840 return Ctrl_C; 5841 5842 #ifdef FEAT_GUI 5843 /* 5844 * In GUI there is no point inserting the internal code for a special key. 5845 * It is more useful to insert the string "<KEY>" instead. This would 5846 * probably be useful in a text window too, but it would not be 5847 * vi-compatible (maybe there should be an option for it?) -- webb 5848 */ 5849 if (gui.in_use) 5850 ++allow_keys; 5851 #endif 5852 #ifdef USE_ON_FLY_SCROLL 5853 dont_scroll = TRUE; /* disallow scrolling here */ 5854 #endif 5855 ++no_mapping; /* don't map the next key hits */ 5856 cc = 0; 5857 i = 0; 5858 for (;;) 5859 { 5860 nc = plain_vgetc(); 5861 #ifdef FEAT_CMDL_INFO 5862 if (!(State & CMDLINE) 5863 # ifdef FEAT_MBYTE 5864 && MB_BYTE2LEN_CHECK(nc) == 1 5865 # endif 5866 ) 5867 add_to_showcmd(nc); 5868 #endif 5869 if (nc == 'x' || nc == 'X') 5870 hex = TRUE; 5871 else if (nc == 'o' || nc == 'O') 5872 octal = TRUE; 5873 #ifdef FEAT_MBYTE 5874 else if (nc == 'u' || nc == 'U') 5875 unicode = nc; 5876 #endif 5877 else 5878 { 5879 if (hex 5880 #ifdef FEAT_MBYTE 5881 || unicode != 0 5882 #endif 5883 ) 5884 { 5885 if (!vim_isxdigit(nc)) 5886 break; 5887 cc = cc * 16 + hex2nr(nc); 5888 } 5889 else if (octal) 5890 { 5891 if (nc < '0' || nc > '7') 5892 break; 5893 cc = cc * 8 + nc - '0'; 5894 } 5895 else 5896 { 5897 if (!VIM_ISDIGIT(nc)) 5898 break; 5899 cc = cc * 10 + nc - '0'; 5900 } 5901 5902 ++i; 5903 } 5904 5905 if (cc > 255 5906 #ifdef FEAT_MBYTE 5907 && unicode == 0 5908 #endif 5909 ) 5910 cc = 255; /* limit range to 0-255 */ 5911 nc = 0; 5912 5913 if (hex) /* hex: up to two chars */ 5914 { 5915 if (i >= 2) 5916 break; 5917 } 5918 #ifdef FEAT_MBYTE 5919 else if (unicode) /* Unicode: up to four or eight chars */ 5920 { 5921 if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8)) 5922 break; 5923 } 5924 #endif 5925 else if (i >= 3) /* decimal or octal: up to three chars */ 5926 break; 5927 } 5928 if (i == 0) /* no number entered */ 5929 { 5930 if (nc == K_ZERO) /* NUL is stored as NL */ 5931 { 5932 cc = '\n'; 5933 nc = 0; 5934 } 5935 else 5936 { 5937 cc = nc; 5938 nc = 0; 5939 } 5940 } 5941 5942 if (cc == 0) /* NUL is stored as NL */ 5943 cc = '\n'; 5944 #ifdef FEAT_MBYTE 5945 if (enc_dbcs && (cc & 0xff) == 0) 5946 cc = '?'; /* don't accept an illegal DBCS char, the NUL in the 5947 second byte will cause trouble! */ 5948 #endif 5949 5950 --no_mapping; 5951 #ifdef FEAT_GUI 5952 if (gui.in_use) 5953 --allow_keys; 5954 #endif 5955 if (nc) 5956 vungetc(nc); 5957 got_int = FALSE; /* CTRL-C typed after CTRL-V is not an interrupt */ 5958 return cc; 5959 } 5960 5961 /* 5962 * Insert character, taking care of special keys and mod_mask 5963 */ 5964 static void 5965 insert_special( 5966 int c, 5967 int allow_modmask, 5968 int ctrlv) /* c was typed after CTRL-V */ 5969 { 5970 char_u *p; 5971 int len; 5972 5973 /* 5974 * Special function key, translate into "<Key>". Up to the last '>' is 5975 * inserted with ins_str(), so as not to replace characters in replace 5976 * mode. 5977 * Only use mod_mask for special keys, to avoid things like <S-Space>, 5978 * unless 'allow_modmask' is TRUE. 5979 */ 5980 #ifdef MACOS_X 5981 /* Command-key never produces a normal key */ 5982 if (mod_mask & MOD_MASK_CMD) 5983 allow_modmask = TRUE; 5984 #endif 5985 if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) 5986 { 5987 p = get_special_key_name(c, mod_mask); 5988 len = (int)STRLEN(p); 5989 c = p[len - 1]; 5990 if (len > 2) 5991 { 5992 if (stop_arrow() == FAIL) 5993 return; 5994 p[len - 1] = NUL; 5995 ins_str(p); 5996 AppendToRedobuffLit(p, -1); 5997 ctrlv = FALSE; 5998 } 5999 } 6000 if (stop_arrow() == OK) 6001 insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1); 6002 } 6003 6004 /* 6005 * Special characters in this context are those that need processing other 6006 * than the simple insertion that can be performed here. This includes ESC 6007 * which terminates the insert, and CR/NL which need special processing to 6008 * open up a new line. This routine tries to optimize insertions performed by 6009 * the "redo", "undo" or "put" commands, so it needs to know when it should 6010 * stop and defer processing to the "normal" mechanism. 6011 * '0' and '^' are special, because they can be followed by CTRL-D. 6012 */ 6013 #ifdef EBCDIC 6014 # define ISSPECIAL(c) ((c) < ' ' || (c) == '0' || (c) == '^') 6015 #else 6016 # define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^') 6017 #endif 6018 6019 #ifdef FEAT_MBYTE 6020 # define WHITECHAR(cc) (VIM_ISWHITE(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1)))) 6021 #else 6022 # define WHITECHAR(cc) VIM_ISWHITE(cc) 6023 #endif 6024 6025 /* 6026 * "flags": INSCHAR_FORMAT - force formatting 6027 * INSCHAR_CTRLV - char typed just after CTRL-V 6028 * INSCHAR_NO_FEX - don't use 'formatexpr' 6029 * 6030 * NOTE: passes the flags value straight through to internal_format() which, 6031 * beside INSCHAR_FORMAT (above), is also looking for these: 6032 * INSCHAR_DO_COM - format comments 6033 * INSCHAR_COM_LIST - format comments with num list or 2nd line indent 6034 */ 6035 void 6036 insertchar( 6037 int c, /* character to insert or NUL */ 6038 int flags, /* INSCHAR_FORMAT, etc. */ 6039 int second_indent) /* indent for second line if >= 0 */ 6040 { 6041 int textwidth; 6042 #ifdef FEAT_COMMENTS 6043 char_u *p; 6044 #endif 6045 int fo_ins_blank; 6046 int force_format = flags & INSCHAR_FORMAT; 6047 6048 textwidth = comp_textwidth(force_format); 6049 fo_ins_blank = has_format_option(FO_INS_BLANK); 6050 6051 /* 6052 * Try to break the line in two or more pieces when: 6053 * - Always do this if we have been called to do formatting only. 6054 * - Always do this when 'formatoptions' has the 'a' flag and the line 6055 * ends in white space. 6056 * - Otherwise: 6057 * - Don't do this if inserting a blank 6058 * - Don't do this if an existing character is being replaced, unless 6059 * we're in VREPLACE mode. 6060 * - Do this if the cursor is not on the line where insert started 6061 * or - 'formatoptions' doesn't have 'l' or the line was not too long 6062 * before the insert. 6063 * - 'formatoptions' doesn't have 'b' or a blank was inserted at or 6064 * before 'textwidth' 6065 */ 6066 if (textwidth > 0 6067 && (force_format 6068 || (!VIM_ISWHITE(c) 6069 && !((State & REPLACE_FLAG) 6070 #ifdef FEAT_VREPLACE 6071 && !(State & VREPLACE_FLAG) 6072 #endif 6073 && *ml_get_cursor() != NUL) 6074 && (curwin->w_cursor.lnum != Insstart.lnum 6075 || ((!has_format_option(FO_INS_LONG) 6076 || Insstart_textlen <= (colnr_T)textwidth) 6077 && (!fo_ins_blank 6078 || Insstart_blank_vcol <= (colnr_T)textwidth 6079 )))))) 6080 { 6081 /* Format with 'formatexpr' when it's set. Use internal formatting 6082 * when 'formatexpr' isn't set or it returns non-zero. */ 6083 #if defined(FEAT_EVAL) 6084 int do_internal = TRUE; 6085 colnr_T virtcol = get_nolist_virtcol() 6086 + char2cells(c != NUL ? c : gchar_cursor()); 6087 6088 if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0 6089 && (force_format || virtcol > (colnr_T)textwidth)) 6090 { 6091 do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); 6092 /* It may be required to save for undo again, e.g. when setline() 6093 * was called. */ 6094 ins_need_undo = TRUE; 6095 } 6096 if (do_internal) 6097 #endif 6098 internal_format(textwidth, second_indent, flags, c == NUL, c); 6099 } 6100 6101 if (c == NUL) /* only formatting was wanted */ 6102 return; 6103 6104 #ifdef FEAT_COMMENTS 6105 /* Check whether this character should end a comment. */ 6106 if (did_ai && (int)c == end_comment_pending) 6107 { 6108 char_u *line; 6109 char_u lead_end[COM_MAX_LEN]; /* end-comment string */ 6110 int middle_len, end_len; 6111 int i; 6112 6113 /* 6114 * Need to remove existing (middle) comment leader and insert end 6115 * comment leader. First, check what comment leader we can find. 6116 */ 6117 i = get_leader_len(line = ml_get_curline(), &p, FALSE, TRUE); 6118 if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) /* Just checking */ 6119 { 6120 /* Skip middle-comment string */ 6121 while (*p && p[-1] != ':') /* find end of middle flags */ 6122 ++p; 6123 middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 6124 /* Don't count trailing white space for middle_len */ 6125 while (middle_len > 0 && VIM_ISWHITE(lead_end[middle_len - 1])) 6126 --middle_len; 6127 6128 /* Find the end-comment string */ 6129 while (*p && p[-1] != ':') /* find end of end flags */ 6130 ++p; 6131 end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 6132 6133 /* Skip white space before the cursor */ 6134 i = curwin->w_cursor.col; 6135 while (--i >= 0 && VIM_ISWHITE(line[i])) 6136 ; 6137 i++; 6138 6139 /* Skip to before the middle leader */ 6140 i -= middle_len; 6141 6142 /* Check some expected things before we go on */ 6143 if (i >= 0 && lead_end[end_len - 1] == end_comment_pending) 6144 { 6145 /* Backspace over all the stuff we want to replace */ 6146 backspace_until_column(i); 6147 6148 /* 6149 * Insert the end-comment string, except for the last 6150 * character, which will get inserted as normal later. 6151 */ 6152 ins_bytes_len(lead_end, end_len - 1); 6153 } 6154 } 6155 } 6156 end_comment_pending = NUL; 6157 #endif 6158 6159 did_ai = FALSE; 6160 #ifdef FEAT_SMARTINDENT 6161 did_si = FALSE; 6162 can_si = FALSE; 6163 can_si_back = FALSE; 6164 #endif 6165 6166 /* 6167 * If there's any pending input, grab up to INPUT_BUFLEN at once. 6168 * This speeds up normal text input considerably. 6169 * Don't do this when 'cindent' or 'indentexpr' is set, because we might 6170 * need to re-indent at a ':', or any other character (but not what 6171 * 'paste' is set).. 6172 * Don't do this when there an InsertCharPre autocommand is defined, 6173 * because we need to fire the event for every character. 6174 */ 6175 #ifdef USE_ON_FLY_SCROLL 6176 dont_scroll = FALSE; /* allow scrolling here */ 6177 #endif 6178 6179 if ( !ISSPECIAL(c) 6180 #ifdef FEAT_MBYTE 6181 && (!has_mbyte || (*mb_char2len)(c) == 1) 6182 #endif 6183 && vpeekc() != NUL 6184 && !(State & REPLACE_FLAG) 6185 #ifdef FEAT_CINDENT 6186 && !cindent_on() 6187 #endif 6188 #ifdef FEAT_RIGHTLEFT 6189 && !p_ri 6190 #endif 6191 #ifdef FEAT_AUTOCMD 6192 && !has_insertcharpre() 6193 #endif 6194 ) 6195 { 6196 #define INPUT_BUFLEN 100 6197 char_u buf[INPUT_BUFLEN + 1]; 6198 int i; 6199 colnr_T virtcol = 0; 6200 6201 buf[0] = c; 6202 i = 1; 6203 if (textwidth > 0) 6204 virtcol = get_nolist_virtcol(); 6205 /* 6206 * Stop the string when: 6207 * - no more chars available 6208 * - finding a special character (command key) 6209 * - buffer is full 6210 * - running into the 'textwidth' boundary 6211 * - need to check for abbreviation: A non-word char after a word-char 6212 */ 6213 while ( (c = vpeekc()) != NUL 6214 && !ISSPECIAL(c) 6215 #ifdef FEAT_MBYTE 6216 && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1) 6217 #endif 6218 && i < INPUT_BUFLEN 6219 # ifdef FEAT_FKMAP 6220 && !(p_fkmap && KeyTyped) /* Farsi mode mapping moves cursor */ 6221 # endif 6222 && (textwidth == 0 6223 || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth) 6224 && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) 6225 { 6226 #ifdef FEAT_RIGHTLEFT 6227 c = vgetc(); 6228 if (p_hkmap && KeyTyped) 6229 c = hkmap(c); /* Hebrew mode mapping */ 6230 buf[i++] = c; 6231 #else 6232 buf[i++] = vgetc(); 6233 #endif 6234 } 6235 6236 #ifdef FEAT_DIGRAPHS 6237 do_digraph(-1); /* clear digraphs */ 6238 do_digraph(buf[i-1]); /* may be the start of a digraph */ 6239 #endif 6240 buf[i] = NUL; 6241 ins_str(buf); 6242 if (flags & INSCHAR_CTRLV) 6243 { 6244 redo_literal(*buf); 6245 i = 1; 6246 } 6247 else 6248 i = 0; 6249 if (buf[i] != NUL) 6250 AppendToRedobuffLit(buf + i, -1); 6251 } 6252 else 6253 { 6254 #ifdef FEAT_MBYTE 6255 int cc; 6256 6257 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) 6258 { 6259 char_u buf[MB_MAXBYTES + 1]; 6260 6261 (*mb_char2bytes)(c, buf); 6262 buf[cc] = NUL; 6263 ins_char_bytes(buf, cc); 6264 AppendCharToRedobuff(c); 6265 } 6266 else 6267 #endif 6268 { 6269 ins_char(c); 6270 if (flags & INSCHAR_CTRLV) 6271 redo_literal(c); 6272 else 6273 AppendCharToRedobuff(c); 6274 } 6275 } 6276 } 6277 6278 /* 6279 * Format text at the current insert position. 6280 * 6281 * If the INSCHAR_COM_LIST flag is present, then the value of second_indent 6282 * will be the comment leader length sent to open_line(). 6283 */ 6284 static void 6285 internal_format( 6286 int textwidth, 6287 int second_indent, 6288 int flags, 6289 int format_only, 6290 int c) /* character to be inserted (can be NUL) */ 6291 { 6292 int cc; 6293 int save_char = NUL; 6294 int haveto_redraw = FALSE; 6295 int fo_ins_blank = has_format_option(FO_INS_BLANK); 6296 #ifdef FEAT_MBYTE 6297 int fo_multibyte = has_format_option(FO_MBYTE_BREAK); 6298 #endif 6299 int fo_white_par = has_format_option(FO_WHITE_PAR); 6300 int first_line = TRUE; 6301 #ifdef FEAT_COMMENTS 6302 colnr_T leader_len; 6303 int no_leader = FALSE; 6304 int do_comments = (flags & INSCHAR_DO_COM); 6305 #endif 6306 #ifdef FEAT_LINEBREAK 6307 int has_lbr = curwin->w_p_lbr; 6308 6309 /* make sure win_lbr_chartabsize() counts correctly */ 6310 curwin->w_p_lbr = FALSE; 6311 #endif 6312 6313 /* 6314 * When 'ai' is off we don't want a space under the cursor to be 6315 * deleted. Replace it with an 'x' temporarily. 6316 */ 6317 if (!curbuf->b_p_ai 6318 #ifdef FEAT_VREPLACE 6319 && !(State & VREPLACE_FLAG) 6320 #endif 6321 ) 6322 { 6323 cc = gchar_cursor(); 6324 if (VIM_ISWHITE(cc)) 6325 { 6326 save_char = cc; 6327 pchar_cursor('x'); 6328 } 6329 } 6330 6331 /* 6332 * Repeat breaking lines, until the current line is not too long. 6333 */ 6334 while (!got_int) 6335 { 6336 int startcol; /* Cursor column at entry */ 6337 int wantcol; /* column at textwidth border */ 6338 int foundcol; /* column for start of spaces */ 6339 int end_foundcol = 0; /* column for start of word */ 6340 colnr_T len; 6341 colnr_T virtcol; 6342 #ifdef FEAT_VREPLACE 6343 int orig_col = 0; 6344 char_u *saved_text = NULL; 6345 #endif 6346 colnr_T col; 6347 colnr_T end_col; 6348 6349 virtcol = get_nolist_virtcol() 6350 + char2cells(c != NUL ? c : gchar_cursor()); 6351 if (virtcol <= (colnr_T)textwidth) 6352 break; 6353 6354 #ifdef FEAT_COMMENTS 6355 if (no_leader) 6356 do_comments = FALSE; 6357 else if (!(flags & INSCHAR_FORMAT) 6358 && has_format_option(FO_WRAP_COMS)) 6359 do_comments = TRUE; 6360 6361 /* Don't break until after the comment leader */ 6362 if (do_comments) 6363 leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE); 6364 else 6365 leader_len = 0; 6366 6367 /* If the line doesn't start with a comment leader, then don't 6368 * start one in a following broken line. Avoids that a %word 6369 * moved to the start of the next line causes all following lines 6370 * to start with %. */ 6371 if (leader_len == 0) 6372 no_leader = TRUE; 6373 #endif 6374 if (!(flags & INSCHAR_FORMAT) 6375 #ifdef FEAT_COMMENTS 6376 && leader_len == 0 6377 #endif 6378 && !has_format_option(FO_WRAP)) 6379 6380 break; 6381 if ((startcol = curwin->w_cursor.col) == 0) 6382 break; 6383 6384 /* find column of textwidth border */ 6385 coladvance((colnr_T)textwidth); 6386 wantcol = curwin->w_cursor.col; 6387 6388 curwin->w_cursor.col = startcol; 6389 foundcol = 0; 6390 6391 /* 6392 * Find position to break at. 6393 * Stop at first entered white when 'formatoptions' has 'v' 6394 */ 6395 while ((!fo_ins_blank && !has_format_option(FO_INS_VI)) 6396 || (flags & INSCHAR_FORMAT) 6397 || curwin->w_cursor.lnum != Insstart.lnum 6398 || curwin->w_cursor.col >= Insstart.col) 6399 { 6400 if (curwin->w_cursor.col == startcol && c != NUL) 6401 cc = c; 6402 else 6403 cc = gchar_cursor(); 6404 if (WHITECHAR(cc)) 6405 { 6406 /* remember position of blank just before text */ 6407 end_col = curwin->w_cursor.col; 6408 6409 /* find start of sequence of blanks */ 6410 while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) 6411 { 6412 dec_cursor(); 6413 cc = gchar_cursor(); 6414 } 6415 if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) 6416 break; /* only spaces in front of text */ 6417 #ifdef FEAT_COMMENTS 6418 /* Don't break until after the comment leader */ 6419 if (curwin->w_cursor.col < leader_len) 6420 break; 6421 #endif 6422 if (has_format_option(FO_ONE_LETTER)) 6423 { 6424 /* do not break after one-letter words */ 6425 if (curwin->w_cursor.col == 0) 6426 break; /* one-letter word at begin */ 6427 #ifdef FEAT_COMMENTS 6428 /* do not break "#a b" when 'tw' is 2 */ 6429 if (curwin->w_cursor.col <= leader_len) 6430 break; 6431 #endif 6432 col = curwin->w_cursor.col; 6433 dec_cursor(); 6434 cc = gchar_cursor(); 6435 6436 if (WHITECHAR(cc)) 6437 continue; /* one-letter, continue */ 6438 curwin->w_cursor.col = col; 6439 } 6440 6441 inc_cursor(); 6442 6443 end_foundcol = end_col + 1; 6444 foundcol = curwin->w_cursor.col; 6445 if (curwin->w_cursor.col <= (colnr_T)wantcol) 6446 break; 6447 } 6448 #ifdef FEAT_MBYTE 6449 else if (cc >= 0x100 && fo_multibyte) 6450 { 6451 /* Break after or before a multi-byte character. */ 6452 if (curwin->w_cursor.col != startcol) 6453 { 6454 #ifdef FEAT_COMMENTS 6455 /* Don't break until after the comment leader */ 6456 if (curwin->w_cursor.col < leader_len) 6457 break; 6458 #endif 6459 col = curwin->w_cursor.col; 6460 inc_cursor(); 6461 /* Don't change end_foundcol if already set. */ 6462 if (foundcol != curwin->w_cursor.col) 6463 { 6464 foundcol = curwin->w_cursor.col; 6465 end_foundcol = foundcol; 6466 if (curwin->w_cursor.col <= (colnr_T)wantcol) 6467 break; 6468 } 6469 curwin->w_cursor.col = col; 6470 } 6471 6472 if (curwin->w_cursor.col == 0) 6473 break; 6474 6475 col = curwin->w_cursor.col; 6476 6477 dec_cursor(); 6478 cc = gchar_cursor(); 6479 6480 if (WHITECHAR(cc)) 6481 continue; /* break with space */ 6482 #ifdef FEAT_COMMENTS 6483 /* Don't break until after the comment leader */ 6484 if (curwin->w_cursor.col < leader_len) 6485 break; 6486 #endif 6487 6488 curwin->w_cursor.col = col; 6489 6490 foundcol = curwin->w_cursor.col; 6491 end_foundcol = foundcol; 6492 if (curwin->w_cursor.col <= (colnr_T)wantcol) 6493 break; 6494 } 6495 #endif 6496 if (curwin->w_cursor.col == 0) 6497 break; 6498 dec_cursor(); 6499 } 6500 6501 if (foundcol == 0) /* no spaces, cannot break line */ 6502 { 6503 curwin->w_cursor.col = startcol; 6504 break; 6505 } 6506 6507 /* Going to break the line, remove any "$" now. */ 6508 undisplay_dollar(); 6509 6510 /* 6511 * Offset between cursor position and line break is used by replace 6512 * stack functions. VREPLACE does not use this, and backspaces 6513 * over the text instead. 6514 */ 6515 #ifdef FEAT_VREPLACE 6516 if (State & VREPLACE_FLAG) 6517 orig_col = startcol; /* Will start backspacing from here */ 6518 else 6519 #endif 6520 replace_offset = startcol - end_foundcol; 6521 6522 /* 6523 * adjust startcol for spaces that will be deleted and 6524 * characters that will remain on top line 6525 */ 6526 curwin->w_cursor.col = foundcol; 6527 while ((cc = gchar_cursor(), WHITECHAR(cc)) 6528 && (!fo_white_par || curwin->w_cursor.col < startcol)) 6529 inc_cursor(); 6530 startcol -= curwin->w_cursor.col; 6531 if (startcol < 0) 6532 startcol = 0; 6533 6534 #ifdef FEAT_VREPLACE 6535 if (State & VREPLACE_FLAG) 6536 { 6537 /* 6538 * In VREPLACE mode, we will backspace over the text to be 6539 * wrapped, so save a copy now to put on the next line. 6540 */ 6541 saved_text = vim_strsave(ml_get_cursor()); 6542 curwin->w_cursor.col = orig_col; 6543 if (saved_text == NULL) 6544 break; /* Can't do it, out of memory */ 6545 saved_text[startcol] = NUL; 6546 6547 /* Backspace over characters that will move to the next line */ 6548 if (!fo_white_par) 6549 backspace_until_column(foundcol); 6550 } 6551 else 6552 #endif 6553 { 6554 /* put cursor after pos. to break line */ 6555 if (!fo_white_par) 6556 curwin->w_cursor.col = foundcol; 6557 } 6558 6559 /* 6560 * Split the line just before the margin. 6561 * Only insert/delete lines, but don't really redraw the window. 6562 */ 6563 open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX 6564 + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) 6565 #ifdef FEAT_COMMENTS 6566 + (do_comments ? OPENLINE_DO_COM : 0) 6567 + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0) 6568 #endif 6569 , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent)); 6570 if (!(flags & INSCHAR_COM_LIST)) 6571 old_indent = 0; 6572 6573 replace_offset = 0; 6574 if (first_line) 6575 { 6576 if (!(flags & INSCHAR_COM_LIST)) 6577 { 6578 /* 6579 * This section is for auto-wrap of numeric lists. When not 6580 * in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST 6581 * flag will be set and open_line() will handle it (as seen 6582 * above). The code here (and in get_number_indent()) will 6583 * recognize comments if needed... 6584 */ 6585 if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) 6586 second_indent = 6587 get_number_indent(curwin->w_cursor.lnum - 1); 6588 if (second_indent >= 0) 6589 { 6590 #ifdef FEAT_VREPLACE 6591 if (State & VREPLACE_FLAG) 6592 change_indent(INDENT_SET, second_indent, 6593 FALSE, NUL, TRUE); 6594 else 6595 #endif 6596 #ifdef FEAT_COMMENTS 6597 if (leader_len > 0 && second_indent - leader_len > 0) 6598 { 6599 int i; 6600 int padding = second_indent - leader_len; 6601 6602 /* We started at the first_line of a numbered list 6603 * that has a comment. the open_line() function has 6604 * inserted the proper comment leader and positioned 6605 * the cursor at the end of the split line. Now we 6606 * add the additional whitespace needed after the 6607 * comment leader for the numbered list. */ 6608 for (i = 0; i < padding; i++) 6609 ins_str((char_u *)" "); 6610 changed_bytes(curwin->w_cursor.lnum, leader_len); 6611 } 6612 else 6613 { 6614 #endif 6615 (void)set_indent(second_indent, SIN_CHANGED); 6616 #ifdef FEAT_COMMENTS 6617 } 6618 #endif 6619 } 6620 } 6621 first_line = FALSE; 6622 } 6623 6624 #ifdef FEAT_VREPLACE 6625 if (State & VREPLACE_FLAG) 6626 { 6627 /* 6628 * In VREPLACE mode we have backspaced over the text to be 6629 * moved, now we re-insert it into the new line. 6630 */ 6631 ins_bytes(saved_text); 6632 vim_free(saved_text); 6633 } 6634 else 6635 #endif 6636 { 6637 /* 6638 * Check if cursor is not past the NUL off the line, cindent 6639 * may have added or removed indent. 6640 */ 6641 curwin->w_cursor.col += startcol; 6642 len = (colnr_T)STRLEN(ml_get_curline()); 6643 if (curwin->w_cursor.col > len) 6644 curwin->w_cursor.col = len; 6645 } 6646 6647 haveto_redraw = TRUE; 6648 #ifdef FEAT_CINDENT 6649 can_cindent = TRUE; 6650 #endif 6651 /* moved the cursor, don't autoindent or cindent now */ 6652 did_ai = FALSE; 6653 #ifdef FEAT_SMARTINDENT 6654 did_si = FALSE; 6655 can_si = FALSE; 6656 can_si_back = FALSE; 6657 #endif 6658 line_breakcheck(); 6659 } 6660 6661 if (save_char != NUL) /* put back space after cursor */ 6662 pchar_cursor(save_char); 6663 6664 #ifdef FEAT_LINEBREAK 6665 curwin->w_p_lbr = has_lbr; 6666 #endif 6667 if (!format_only && haveto_redraw) 6668 { 6669 update_topline(); 6670 redraw_curbuf_later(VALID); 6671 } 6672 } 6673 6674 /* 6675 * Called after inserting or deleting text: When 'formatoptions' includes the 6676 * 'a' flag format from the current line until the end of the paragraph. 6677 * Keep the cursor at the same position relative to the text. 6678 * The caller must have saved the cursor line for undo, following ones will be 6679 * saved here. 6680 */ 6681 void 6682 auto_format( 6683 int trailblank, /* when TRUE also format with trailing blank */ 6684 int prev_line) /* may start in previous line */ 6685 { 6686 pos_T pos; 6687 colnr_T len; 6688 char_u *old; 6689 char_u *new, *pnew; 6690 int wasatend; 6691 int cc; 6692 6693 if (!has_format_option(FO_AUTO)) 6694 return; 6695 6696 pos = curwin->w_cursor; 6697 old = ml_get_curline(); 6698 6699 /* may remove added space */ 6700 check_auto_format(FALSE); 6701 6702 /* Don't format in Insert mode when the cursor is on a trailing blank, the 6703 * user might insert normal text next. Also skip formatting when "1" is 6704 * in 'formatoptions' and there is a single character before the cursor. 6705 * Otherwise the line would be broken and when typing another non-white 6706 * next they are not joined back together. */ 6707 wasatend = (pos.col == (colnr_T)STRLEN(old)); 6708 if (*old != NUL && !trailblank && wasatend) 6709 { 6710 dec_cursor(); 6711 cc = gchar_cursor(); 6712 if (!WHITECHAR(cc) && curwin->w_cursor.col > 0 6713 && has_format_option(FO_ONE_LETTER)) 6714 dec_cursor(); 6715 cc = gchar_cursor(); 6716 if (WHITECHAR(cc)) 6717 { 6718 curwin->w_cursor = pos; 6719 return; 6720 } 6721 curwin->w_cursor = pos; 6722 } 6723 6724 #ifdef FEAT_COMMENTS 6725 /* With the 'c' flag in 'formatoptions' and 't' missing: only format 6726 * comments. */ 6727 if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP) 6728 && get_leader_len(old, NULL, FALSE, TRUE) == 0) 6729 return; 6730 #endif 6731 6732 /* 6733 * May start formatting in a previous line, so that after "x" a word is 6734 * moved to the previous line if it fits there now. Only when this is not 6735 * the start of a paragraph. 6736 */ 6737 if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) 6738 { 6739 --curwin->w_cursor.lnum; 6740 if (u_save_cursor() == FAIL) 6741 return; 6742 } 6743 6744 /* 6745 * Do the formatting and restore the cursor position. "saved_cursor" will 6746 * be adjusted for the text formatting. 6747 */ 6748 saved_cursor = pos; 6749 format_lines((linenr_T)-1, FALSE); 6750 curwin->w_cursor = saved_cursor; 6751 saved_cursor.lnum = 0; 6752 6753 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 6754 { 6755 /* "cannot happen" */ 6756 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 6757 coladvance((colnr_T)MAXCOL); 6758 } 6759 else 6760 check_cursor_col(); 6761 6762 /* Insert mode: If the cursor is now after the end of the line while it 6763 * previously wasn't, the line was broken. Because of the rule above we 6764 * need to add a space when 'w' is in 'formatoptions' to keep a paragraph 6765 * formatted. */ 6766 if (!wasatend && has_format_option(FO_WHITE_PAR)) 6767 { 6768 new = ml_get_curline(); 6769 len = (colnr_T)STRLEN(new); 6770 if (curwin->w_cursor.col == len) 6771 { 6772 pnew = vim_strnsave(new, len + 2); 6773 pnew[len] = ' '; 6774 pnew[len + 1] = NUL; 6775 ml_replace(curwin->w_cursor.lnum, pnew, FALSE); 6776 /* remove the space later */ 6777 did_add_space = TRUE; 6778 } 6779 else 6780 /* may remove added space */ 6781 check_auto_format(FALSE); 6782 } 6783 6784 check_cursor(); 6785 } 6786 6787 /* 6788 * When an extra space was added to continue a paragraph for auto-formatting, 6789 * delete it now. The space must be under the cursor, just after the insert 6790 * position. 6791 */ 6792 static void 6793 check_auto_format( 6794 int end_insert) /* TRUE when ending Insert mode */ 6795 { 6796 int c = ' '; 6797 int cc; 6798 6799 if (did_add_space) 6800 { 6801 cc = gchar_cursor(); 6802 if (!WHITECHAR(cc)) 6803 /* Somehow the space was removed already. */ 6804 did_add_space = FALSE; 6805 else 6806 { 6807 if (!end_insert) 6808 { 6809 inc_cursor(); 6810 c = gchar_cursor(); 6811 dec_cursor(); 6812 } 6813 if (c != NUL) 6814 { 6815 /* The space is no longer at the end of the line, delete it. */ 6816 del_char(FALSE); 6817 did_add_space = FALSE; 6818 } 6819 } 6820 } 6821 } 6822 6823 /* 6824 * Find out textwidth to be used for formatting: 6825 * if 'textwidth' option is set, use it 6826 * else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin' 6827 * if invalid value, use 0. 6828 * Set default to window width (maximum 79) for "gq" operator. 6829 */ 6830 int 6831 comp_textwidth( 6832 int ff) /* force formatting (for "gq" command) */ 6833 { 6834 int textwidth; 6835 6836 textwidth = curbuf->b_p_tw; 6837 if (textwidth == 0 && curbuf->b_p_wm) 6838 { 6839 /* The width is the window width minus 'wrapmargin' minus all the 6840 * things that add to the margin. */ 6841 textwidth = curwin->w_width - curbuf->b_p_wm; 6842 #ifdef FEAT_CMDWIN 6843 if (cmdwin_type != 0) 6844 textwidth -= 1; 6845 #endif 6846 #ifdef FEAT_FOLDING 6847 textwidth -= curwin->w_p_fdc; 6848 #endif 6849 #ifdef FEAT_SIGNS 6850 if (signcolumn_on(curwin)) 6851 textwidth -= 1; 6852 #endif 6853 if (curwin->w_p_nu || curwin->w_p_rnu) 6854 textwidth -= 8; 6855 } 6856 if (textwidth < 0) 6857 textwidth = 0; 6858 if (ff && textwidth == 0) 6859 { 6860 textwidth = curwin->w_width - 1; 6861 if (textwidth > 79) 6862 textwidth = 79; 6863 } 6864 return textwidth; 6865 } 6866 6867 /* 6868 * Put a character in the redo buffer, for when just after a CTRL-V. 6869 */ 6870 static void 6871 redo_literal(int c) 6872 { 6873 char_u buf[10]; 6874 6875 /* Only digits need special treatment. Translate them into a string of 6876 * three digits. */ 6877 if (VIM_ISDIGIT(c)) 6878 { 6879 vim_snprintf((char *)buf, sizeof(buf), "%03d", c); 6880 AppendToRedobuff(buf); 6881 } 6882 else 6883 AppendCharToRedobuff(c); 6884 } 6885 6886 /* 6887 * start_arrow() is called when an arrow key is used in insert mode. 6888 * For undo/redo it resembles hitting the <ESC> key. 6889 */ 6890 static void 6891 start_arrow( 6892 pos_T *end_insert_pos) /* can be NULL */ 6893 { 6894 start_arrow_common(end_insert_pos, TRUE); 6895 } 6896 6897 /* 6898 * Like start_arrow() but with end_change argument. 6899 * Will prepare for redo of CTRL-G U if "end_change" is FALSE. 6900 */ 6901 static void 6902 start_arrow_with_change( 6903 pos_T *end_insert_pos, /* can be NULL */ 6904 int end_change) /* end undoable change */ 6905 { 6906 start_arrow_common(end_insert_pos, end_change); 6907 if (!end_change) 6908 { 6909 AppendCharToRedobuff(Ctrl_G); 6910 AppendCharToRedobuff('U'); 6911 } 6912 } 6913 6914 static void 6915 start_arrow_common( 6916 pos_T *end_insert_pos, /* can be NULL */ 6917 int end_change) /* end undoable change */ 6918 { 6919 if (!arrow_used && end_change) /* something has been inserted */ 6920 { 6921 AppendToRedobuff(ESC_STR); 6922 stop_insert(end_insert_pos, FALSE, FALSE); 6923 arrow_used = TRUE; /* this means we stopped the current insert */ 6924 } 6925 #ifdef FEAT_SPELL 6926 check_spell_redraw(); 6927 #endif 6928 } 6929 6930 #ifdef FEAT_SPELL 6931 /* 6932 * If we skipped highlighting word at cursor, do it now. 6933 * It may be skipped again, thus reset spell_redraw_lnum first. 6934 */ 6935 static void 6936 check_spell_redraw(void) 6937 { 6938 if (spell_redraw_lnum != 0) 6939 { 6940 linenr_T lnum = spell_redraw_lnum; 6941 6942 spell_redraw_lnum = 0; 6943 redrawWinline(lnum, FALSE); 6944 } 6945 } 6946 6947 /* 6948 * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly 6949 * spelled word, if there is one. 6950 */ 6951 static void 6952 spell_back_to_badword(void) 6953 { 6954 pos_T tpos = curwin->w_cursor; 6955 6956 spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL); 6957 if (curwin->w_cursor.col != tpos.col) 6958 start_arrow(&tpos); 6959 } 6960 #endif 6961 6962 /* 6963 * stop_arrow() is called before a change is made in insert mode. 6964 * If an arrow key has been used, start a new insertion. 6965 * Returns FAIL if undo is impossible, shouldn't insert then. 6966 */ 6967 int 6968 stop_arrow(void) 6969 { 6970 if (arrow_used) 6971 { 6972 Insstart = curwin->w_cursor; /* new insertion starts here */ 6973 if (Insstart.col > Insstart_orig.col && !ins_need_undo) 6974 /* Don't update the original insert position when moved to the 6975 * right, except when nothing was inserted yet. */ 6976 update_Insstart_orig = FALSE; 6977 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); 6978 6979 if (u_save_cursor() == OK) 6980 { 6981 arrow_used = FALSE; 6982 ins_need_undo = FALSE; 6983 } 6984 6985 ai_col = 0; 6986 #ifdef FEAT_VREPLACE 6987 if (State & VREPLACE_FLAG) 6988 { 6989 orig_line_count = curbuf->b_ml.ml_line_count; 6990 vr_lines_changed = 1; 6991 } 6992 #endif 6993 ResetRedobuff(); 6994 AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */ 6995 new_insert_skip = 2; 6996 } 6997 else if (ins_need_undo) 6998 { 6999 if (u_save_cursor() == OK) 7000 ins_need_undo = FALSE; 7001 } 7002 7003 #ifdef FEAT_FOLDING 7004 /* Always open fold at the cursor line when inserting something. */ 7005 foldOpenCursor(); 7006 #endif 7007 7008 return (arrow_used || ins_need_undo ? FAIL : OK); 7009 } 7010 7011 /* 7012 * Do a few things to stop inserting. 7013 * "end_insert_pos" is where insert ended. It is NULL when we already jumped 7014 * to another window/buffer. 7015 */ 7016 static void 7017 stop_insert( 7018 pos_T *end_insert_pos, 7019 int esc, /* called by ins_esc() */ 7020 int nomove) /* <c-\><c-o>, don't move cursor */ 7021 { 7022 int cc; 7023 char_u *ptr; 7024 7025 stop_redo_ins(); 7026 replace_flush(); /* abandon replace stack */ 7027 7028 /* 7029 * Save the inserted text for later redo with ^@ and CTRL-A. 7030 * Don't do it when "restart_edit" was set and nothing was inserted, 7031 * otherwise CTRL-O w and then <Left> will clear "last_insert". 7032 */ 7033 ptr = get_inserted(); 7034 if (did_restart_edit == 0 || (ptr != NULL 7035 && (int)STRLEN(ptr) > new_insert_skip)) 7036 { 7037 vim_free(last_insert); 7038 last_insert = ptr; 7039 last_insert_skip = new_insert_skip; 7040 } 7041 else 7042 vim_free(ptr); 7043 7044 if (!arrow_used && end_insert_pos != NULL) 7045 { 7046 /* Auto-format now. It may seem strange to do this when stopping an 7047 * insertion (or moving the cursor), but it's required when appending 7048 * a line and having it end in a space. But only do it when something 7049 * was actually inserted, otherwise undo won't work. */ 7050 if (!ins_need_undo && has_format_option(FO_AUTO)) 7051 { 7052 pos_T tpos = curwin->w_cursor; 7053 7054 /* When the cursor is at the end of the line after a space the 7055 * formatting will move it to the following word. Avoid that by 7056 * moving the cursor onto the space. */ 7057 cc = 'x'; 7058 if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL) 7059 { 7060 dec_cursor(); 7061 cc = gchar_cursor(); 7062 if (!VIM_ISWHITE(cc)) 7063 curwin->w_cursor = tpos; 7064 } 7065 7066 auto_format(TRUE, FALSE); 7067 7068 if (VIM_ISWHITE(cc)) 7069 { 7070 if (gchar_cursor() != NUL) 7071 inc_cursor(); 7072 #ifdef FEAT_VIRTUALEDIT 7073 /* If the cursor is still at the same character, also keep 7074 * the "coladd". */ 7075 if (gchar_cursor() == NUL 7076 && curwin->w_cursor.lnum == tpos.lnum 7077 && curwin->w_cursor.col == tpos.col) 7078 curwin->w_cursor.coladd = tpos.coladd; 7079 #endif 7080 } 7081 } 7082 7083 /* If a space was inserted for auto-formatting, remove it now. */ 7084 check_auto_format(TRUE); 7085 7086 /* If we just did an auto-indent, remove the white space from the end 7087 * of the line, and put the cursor back. 7088 * Do this when ESC was used or moving the cursor up/down. 7089 * Check for the old position still being valid, just in case the text 7090 * got changed unexpectedly. */ 7091 if (!nomove && did_ai && (esc || (vim_strchr(p_cpo, CPO_INDENT) == NULL 7092 && curwin->w_cursor.lnum != end_insert_pos->lnum)) 7093 && end_insert_pos->lnum <= curbuf->b_ml.ml_line_count) 7094 { 7095 pos_T tpos = curwin->w_cursor; 7096 7097 curwin->w_cursor = *end_insert_pos; 7098 check_cursor_col(); /* make sure it is not past the line */ 7099 for (;;) 7100 { 7101 if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) 7102 --curwin->w_cursor.col; 7103 cc = gchar_cursor(); 7104 if (!VIM_ISWHITE(cc)) 7105 break; 7106 if (del_char(TRUE) == FAIL) 7107 break; /* should not happen */ 7108 } 7109 if (curwin->w_cursor.lnum != tpos.lnum) 7110 curwin->w_cursor = tpos; 7111 else 7112 { 7113 /* reset tpos, could have been invalidated in the loop above */ 7114 tpos = curwin->w_cursor; 7115 tpos.col++; 7116 if (cc != NUL && gchar_pos(&tpos) == NUL) 7117 ++curwin->w_cursor.col; /* put cursor back on the NUL */ 7118 } 7119 7120 /* <C-S-Right> may have started Visual mode, adjust the position for 7121 * deleted characters. */ 7122 if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) 7123 { 7124 int len = (int)STRLEN(ml_get_curline()); 7125 7126 if (VIsual.col > len) 7127 { 7128 VIsual.col = len; 7129 #ifdef FEAT_VIRTUALEDIT 7130 VIsual.coladd = 0; 7131 #endif 7132 } 7133 } 7134 } 7135 } 7136 did_ai = FALSE; 7137 #ifdef FEAT_SMARTINDENT 7138 did_si = FALSE; 7139 can_si = FALSE; 7140 can_si_back = FALSE; 7141 #endif 7142 7143 /* Set '[ and '] to the inserted text. When end_insert_pos is NULL we are 7144 * now in a different buffer. */ 7145 if (end_insert_pos != NULL) 7146 { 7147 curbuf->b_op_start = Insstart; 7148 curbuf->b_op_start_orig = Insstart_orig; 7149 curbuf->b_op_end = *end_insert_pos; 7150 } 7151 } 7152 7153 /* 7154 * Set the last inserted text to a single character. 7155 * Used for the replace command. 7156 */ 7157 void 7158 set_last_insert(int c) 7159 { 7160 char_u *s; 7161 7162 vim_free(last_insert); 7163 last_insert = alloc(MB_MAXBYTES * 3 + 5); 7164 if (last_insert != NULL) 7165 { 7166 s = last_insert; 7167 /* Use the CTRL-V only when entering a special char */ 7168 if (c < ' ' || c == DEL) 7169 *s++ = Ctrl_V; 7170 s = add_char2buf(c, s); 7171 *s++ = ESC; 7172 *s++ = NUL; 7173 last_insert_skip = 0; 7174 } 7175 } 7176 7177 #if defined(EXITFREE) || defined(PROTO) 7178 void 7179 free_last_insert(void) 7180 { 7181 vim_free(last_insert); 7182 last_insert = NULL; 7183 # ifdef FEAT_INS_EXPAND 7184 vim_free(compl_orig_text); 7185 compl_orig_text = NULL; 7186 # endif 7187 } 7188 #endif 7189 7190 /* 7191 * Add character "c" to buffer "s". Escape the special meaning of K_SPECIAL 7192 * and CSI. Handle multi-byte characters. 7193 * Returns a pointer to after the added bytes. 7194 */ 7195 char_u * 7196 add_char2buf(int c, char_u *s) 7197 { 7198 #ifdef FEAT_MBYTE 7199 char_u temp[MB_MAXBYTES + 1]; 7200 int i; 7201 int len; 7202 7203 len = (*mb_char2bytes)(c, temp); 7204 for (i = 0; i < len; ++i) 7205 { 7206 c = temp[i]; 7207 #endif 7208 /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */ 7209 if (c == K_SPECIAL) 7210 { 7211 *s++ = K_SPECIAL; 7212 *s++ = KS_SPECIAL; 7213 *s++ = KE_FILLER; 7214 } 7215 #ifdef FEAT_GUI 7216 else if (c == CSI) 7217 { 7218 *s++ = CSI; 7219 *s++ = KS_EXTRA; 7220 *s++ = (int)KE_CSI; 7221 } 7222 #endif 7223 else 7224 *s++ = c; 7225 #ifdef FEAT_MBYTE 7226 } 7227 #endif 7228 return s; 7229 } 7230 7231 /* 7232 * move cursor to start of line 7233 * if flags & BL_WHITE move to first non-white 7234 * if flags & BL_SOL move to first non-white if startofline is set, 7235 * otherwise keep "curswant" column 7236 * if flags & BL_FIX don't leave the cursor on a NUL. 7237 */ 7238 void 7239 beginline(int flags) 7240 { 7241 if ((flags & BL_SOL) && !p_sol) 7242 coladvance(curwin->w_curswant); 7243 else 7244 { 7245 curwin->w_cursor.col = 0; 7246 #ifdef FEAT_VIRTUALEDIT 7247 curwin->w_cursor.coladd = 0; 7248 #endif 7249 7250 if (flags & (BL_WHITE | BL_SOL)) 7251 { 7252 char_u *ptr; 7253 7254 for (ptr = ml_get_curline(); VIM_ISWHITE(*ptr) 7255 && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) 7256 ++curwin->w_cursor.col; 7257 } 7258 curwin->w_set_curswant = TRUE; 7259 } 7260 } 7261 7262 /* 7263 * oneright oneleft cursor_down cursor_up 7264 * 7265 * Move one char {right,left,down,up}. 7266 * Doesn't move onto the NUL past the end of the line, unless it is allowed. 7267 * Return OK when successful, FAIL when we hit a line of file boundary. 7268 */ 7269 7270 int 7271 oneright(void) 7272 { 7273 char_u *ptr; 7274 int l; 7275 7276 #ifdef FEAT_VIRTUALEDIT 7277 if (virtual_active()) 7278 { 7279 pos_T prevpos = curwin->w_cursor; 7280 7281 /* Adjust for multi-wide char (excluding TAB) */ 7282 ptr = ml_get_cursor(); 7283 coladvance(getviscol() + ((*ptr != TAB && vim_isprintc( 7284 # ifdef FEAT_MBYTE 7285 (*mb_ptr2char)(ptr) 7286 # else 7287 *ptr 7288 # endif 7289 )) 7290 ? ptr2cells(ptr) : 1)); 7291 curwin->w_set_curswant = TRUE; 7292 /* Return OK if the cursor moved, FAIL otherwise (at window edge). */ 7293 return (prevpos.col != curwin->w_cursor.col 7294 || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; 7295 } 7296 #endif 7297 7298 ptr = ml_get_cursor(); 7299 if (*ptr == NUL) 7300 return FAIL; /* already at the very end */ 7301 7302 #ifdef FEAT_MBYTE 7303 if (has_mbyte) 7304 l = (*mb_ptr2len)(ptr); 7305 else 7306 #endif 7307 l = 1; 7308 7309 /* move "l" bytes right, but don't end up on the NUL, unless 'virtualedit' 7310 * contains "onemore". */ 7311 if (ptr[l] == NUL 7312 #ifdef FEAT_VIRTUALEDIT 7313 && (ve_flags & VE_ONEMORE) == 0 7314 #endif 7315 ) 7316 return FAIL; 7317 curwin->w_cursor.col += l; 7318 7319 curwin->w_set_curswant = TRUE; 7320 return OK; 7321 } 7322 7323 int 7324 oneleft(void) 7325 { 7326 #ifdef FEAT_VIRTUALEDIT 7327 if (virtual_active()) 7328 { 7329 # ifdef FEAT_LINEBREAK 7330 int width; 7331 # endif 7332 int v = getviscol(); 7333 7334 if (v == 0) 7335 return FAIL; 7336 7337 # ifdef FEAT_LINEBREAK 7338 /* We might get stuck on 'showbreak', skip over it. */ 7339 width = 1; 7340 for (;;) 7341 { 7342 coladvance(v - width); 7343 /* getviscol() is slow, skip it when 'showbreak' is empty, 7344 * 'breakindent' is not set and there are no multi-byte 7345 * characters */ 7346 if ((*p_sbr == NUL && !curwin->w_p_bri 7347 # ifdef FEAT_MBYTE 7348 && !has_mbyte 7349 # endif 7350 ) || getviscol() < v) 7351 break; 7352 ++width; 7353 } 7354 # else 7355 coladvance(v - 1); 7356 # endif 7357 7358 if (curwin->w_cursor.coladd == 1) 7359 { 7360 char_u *ptr; 7361 7362 /* Adjust for multi-wide char (not a TAB) */ 7363 ptr = ml_get_cursor(); 7364 if (*ptr != TAB && vim_isprintc( 7365 # ifdef FEAT_MBYTE 7366 (*mb_ptr2char)(ptr) 7367 # else 7368 *ptr 7369 # endif 7370 ) && ptr2cells(ptr) > 1) 7371 curwin->w_cursor.coladd = 0; 7372 } 7373 7374 curwin->w_set_curswant = TRUE; 7375 return OK; 7376 } 7377 #endif 7378 7379 if (curwin->w_cursor.col == 0) 7380 return FAIL; 7381 7382 curwin->w_set_curswant = TRUE; 7383 --curwin->w_cursor.col; 7384 7385 #ifdef FEAT_MBYTE 7386 /* if the character on the left of the current cursor is a multi-byte 7387 * character, move to its first byte */ 7388 if (has_mbyte) 7389 mb_adjust_cursor(); 7390 #endif 7391 return OK; 7392 } 7393 7394 int 7395 cursor_up( 7396 long n, 7397 int upd_topline) /* When TRUE: update topline */ 7398 { 7399 linenr_T lnum; 7400 7401 if (n > 0) 7402 { 7403 lnum = curwin->w_cursor.lnum; 7404 /* This fails if the cursor is already in the first line or the count 7405 * is larger than the line number and '-' is in 'cpoptions' */ 7406 if (lnum <= 1 || (n >= lnum && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 7407 return FAIL; 7408 if (n >= lnum) 7409 lnum = 1; 7410 else 7411 #ifdef FEAT_FOLDING 7412 if (hasAnyFolding(curwin)) 7413 { 7414 /* 7415 * Count each sequence of folded lines as one logical line. 7416 */ 7417 /* go to the start of the current fold */ 7418 (void)hasFolding(lnum, &lnum, NULL); 7419 7420 while (n--) 7421 { 7422 /* move up one line */ 7423 --lnum; 7424 if (lnum <= 1) 7425 break; 7426 /* If we entered a fold, move to the beginning, unless in 7427 * Insert mode or when 'foldopen' contains "all": it will open 7428 * in a moment. */ 7429 if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL))) 7430 (void)hasFolding(lnum, &lnum, NULL); 7431 } 7432 if (lnum < 1) 7433 lnum = 1; 7434 } 7435 else 7436 #endif 7437 lnum -= n; 7438 curwin->w_cursor.lnum = lnum; 7439 } 7440 7441 /* try to advance to the column we want to be at */ 7442 coladvance(curwin->w_curswant); 7443 7444 if (upd_topline) 7445 update_topline(); /* make sure curwin->w_topline is valid */ 7446 7447 return OK; 7448 } 7449 7450 /* 7451 * Cursor down a number of logical lines. 7452 */ 7453 int 7454 cursor_down( 7455 long n, 7456 int upd_topline) /* When TRUE: update topline */ 7457 { 7458 linenr_T lnum; 7459 7460 if (n > 0) 7461 { 7462 lnum = curwin->w_cursor.lnum; 7463 #ifdef FEAT_FOLDING 7464 /* Move to last line of fold, will fail if it's the end-of-file. */ 7465 (void)hasFolding(lnum, NULL, &lnum); 7466 #endif 7467 /* This fails if the cursor is already in the last line or would move 7468 * beyond the last line and '-' is in 'cpoptions' */ 7469 if (lnum >= curbuf->b_ml.ml_line_count 7470 || (lnum + n > curbuf->b_ml.ml_line_count 7471 && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 7472 return FAIL; 7473 if (lnum + n >= curbuf->b_ml.ml_line_count) 7474 lnum = curbuf->b_ml.ml_line_count; 7475 else 7476 #ifdef FEAT_FOLDING 7477 if (hasAnyFolding(curwin)) 7478 { 7479 linenr_T last; 7480 7481 /* count each sequence of folded lines as one logical line */ 7482 while (n--) 7483 { 7484 if (hasFolding(lnum, NULL, &last)) 7485 lnum = last + 1; 7486 else 7487 ++lnum; 7488 if (lnum >= curbuf->b_ml.ml_line_count) 7489 break; 7490 } 7491 if (lnum > curbuf->b_ml.ml_line_count) 7492 lnum = curbuf->b_ml.ml_line_count; 7493 } 7494 else 7495 #endif 7496 lnum += n; 7497 curwin->w_cursor.lnum = lnum; 7498 } 7499 7500 /* try to advance to the column we want to be at */ 7501 coladvance(curwin->w_curswant); 7502 7503 if (upd_topline) 7504 update_topline(); /* make sure curwin->w_topline is valid */ 7505 7506 return OK; 7507 } 7508 7509 /* 7510 * Stuff the last inserted text in the read buffer. 7511 * Last_insert actually is a copy of the redo buffer, so we 7512 * first have to remove the command. 7513 */ 7514 int 7515 stuff_inserted( 7516 int c, /* Command character to be inserted */ 7517 long count, /* Repeat this many times */ 7518 int no_esc) /* Don't add an ESC at the end */ 7519 { 7520 char_u *esc_ptr; 7521 char_u *ptr; 7522 char_u *last_ptr; 7523 char_u last = NUL; 7524 7525 ptr = get_last_insert(); 7526 if (ptr == NULL) 7527 { 7528 EMSG(_(e_noinstext)); 7529 return FAIL; 7530 } 7531 7532 /* may want to stuff the command character, to start Insert mode */ 7533 if (c != NUL) 7534 stuffcharReadbuff(c); 7535 if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL) 7536 *esc_ptr = NUL; /* remove the ESC */ 7537 7538 /* when the last char is either "0" or "^" it will be quoted if no ESC 7539 * comes after it OR if it will inserted more than once and "ptr" 7540 * starts with ^D. -- Acevedo 7541 */ 7542 last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1; 7543 if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^') 7544 && (no_esc || (*ptr == Ctrl_D && count > 1))) 7545 { 7546 last = *last_ptr; 7547 *last_ptr = NUL; 7548 } 7549 7550 do 7551 { 7552 stuffReadbuff(ptr); 7553 /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */ 7554 if (last) 7555 stuffReadbuff((char_u *)(last == '0' 7556 ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0") 7557 : IF_EB("\026^", CTRL_V_STR "^"))); 7558 } 7559 while (--count > 0); 7560 7561 if (last) 7562 *last_ptr = last; 7563 7564 if (esc_ptr != NULL) 7565 *esc_ptr = ESC; /* put the ESC back */ 7566 7567 /* may want to stuff a trailing ESC, to get out of Insert mode */ 7568 if (!no_esc) 7569 stuffcharReadbuff(ESC); 7570 7571 return OK; 7572 } 7573 7574 char_u * 7575 get_last_insert(void) 7576 { 7577 if (last_insert == NULL) 7578 return NULL; 7579 return last_insert + last_insert_skip; 7580 } 7581 7582 /* 7583 * Get last inserted string, and remove trailing <Esc>. 7584 * Returns pointer to allocated memory (must be freed) or NULL. 7585 */ 7586 char_u * 7587 get_last_insert_save(void) 7588 { 7589 char_u *s; 7590 int len; 7591 7592 if (last_insert == NULL) 7593 return NULL; 7594 s = vim_strsave(last_insert + last_insert_skip); 7595 if (s != NULL) 7596 { 7597 len = (int)STRLEN(s); 7598 if (len > 0 && s[len - 1] == ESC) /* remove trailing ESC */ 7599 s[len - 1] = NUL; 7600 } 7601 return s; 7602 } 7603 7604 /* 7605 * Check the word in front of the cursor for an abbreviation. 7606 * Called when the non-id character "c" has been entered. 7607 * When an abbreviation is recognized it is removed from the text and 7608 * the replacement string is inserted in typebuf.tb_buf[], followed by "c". 7609 */ 7610 static int 7611 echeck_abbr(int c) 7612 { 7613 /* Don't check for abbreviation in paste mode, when disabled and just 7614 * after moving around with cursor keys. */ 7615 if (p_paste || no_abbr || arrow_used) 7616 return FALSE; 7617 7618 return check_abbr(c, ml_get_curline(), curwin->w_cursor.col, 7619 curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0); 7620 } 7621 7622 /* 7623 * replace-stack functions 7624 * 7625 * When replacing characters, the replaced characters are remembered for each 7626 * new character. This is used to re-insert the old text when backspacing. 7627 * 7628 * There is a NUL headed list of characters for each character that is 7629 * currently in the file after the insertion point. When BS is used, one NUL 7630 * headed list is put back for the deleted character. 7631 * 7632 * For a newline, there are two NUL headed lists. One contains the characters 7633 * that the NL replaced. The extra one stores the characters after the cursor 7634 * that were deleted (always white space). 7635 * 7636 * Replace_offset is normally 0, in which case replace_push will add a new 7637 * character at the end of the stack. If replace_offset is not 0, that many 7638 * characters will be left on the stack above the newly inserted character. 7639 */ 7640 7641 static char_u *replace_stack = NULL; 7642 static long replace_stack_nr = 0; /* next entry in replace stack */ 7643 static long replace_stack_len = 0; /* max. number of entries */ 7644 7645 void 7646 replace_push( 7647 int c) /* character that is replaced (NUL is none) */ 7648 { 7649 char_u *p; 7650 7651 if (replace_stack_nr < replace_offset) /* nothing to do */ 7652 return; 7653 if (replace_stack_len <= replace_stack_nr) 7654 { 7655 replace_stack_len += 50; 7656 p = lalloc(sizeof(char_u) * replace_stack_len, TRUE); 7657 if (p == NULL) /* out of memory */ 7658 { 7659 replace_stack_len -= 50; 7660 return; 7661 } 7662 if (replace_stack != NULL) 7663 { 7664 mch_memmove(p, replace_stack, 7665 (size_t)(replace_stack_nr * sizeof(char_u))); 7666 vim_free(replace_stack); 7667 } 7668 replace_stack = p; 7669 } 7670 p = replace_stack + replace_stack_nr - replace_offset; 7671 if (replace_offset) 7672 mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u))); 7673 *p = c; 7674 ++replace_stack_nr; 7675 } 7676 7677 #if defined(FEAT_MBYTE) || defined(PROTO) 7678 /* 7679 * Push a character onto the replace stack. Handles a multi-byte character in 7680 * reverse byte order, so that the first byte is popped off first. 7681 * Return the number of bytes done (includes composing characters). 7682 */ 7683 int 7684 replace_push_mb(char_u *p) 7685 { 7686 int l = (*mb_ptr2len)(p); 7687 int j; 7688 7689 for (j = l - 1; j >= 0; --j) 7690 replace_push(p[j]); 7691 return l; 7692 } 7693 #endif 7694 7695 /* 7696 * Pop one item from the replace stack. 7697 * return -1 if stack empty 7698 * return replaced character or NUL otherwise 7699 */ 7700 static int 7701 replace_pop(void) 7702 { 7703 if (replace_stack_nr == 0) 7704 return -1; 7705 return (int)replace_stack[--replace_stack_nr]; 7706 } 7707 7708 /* 7709 * Join the top two items on the replace stack. This removes to "off"'th NUL 7710 * encountered. 7711 */ 7712 static void 7713 replace_join( 7714 int off) /* offset for which NUL to remove */ 7715 { 7716 int i; 7717 7718 for (i = replace_stack_nr; --i >= 0; ) 7719 if (replace_stack[i] == NUL && off-- <= 0) 7720 { 7721 --replace_stack_nr; 7722 mch_memmove(replace_stack + i, replace_stack + i + 1, 7723 (size_t)(replace_stack_nr - i)); 7724 return; 7725 } 7726 } 7727 7728 /* 7729 * Pop bytes from the replace stack until a NUL is found, and insert them 7730 * before the cursor. Can only be used in REPLACE or VREPLACE mode. 7731 */ 7732 static void 7733 replace_pop_ins(void) 7734 { 7735 int cc; 7736 int oldState = State; 7737 7738 State = NORMAL; /* don't want REPLACE here */ 7739 while ((cc = replace_pop()) > 0) 7740 { 7741 #ifdef FEAT_MBYTE 7742 mb_replace_pop_ins(cc); 7743 #else 7744 ins_char(cc); 7745 #endif 7746 dec_cursor(); 7747 } 7748 State = oldState; 7749 } 7750 7751 #ifdef FEAT_MBYTE 7752 /* 7753 * Insert bytes popped from the replace stack. "cc" is the first byte. If it 7754 * indicates a multi-byte char, pop the other bytes too. 7755 */ 7756 static void 7757 mb_replace_pop_ins(int cc) 7758 { 7759 int n; 7760 char_u buf[MB_MAXBYTES + 1]; 7761 int i; 7762 int c; 7763 7764 if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1) 7765 { 7766 buf[0] = cc; 7767 for (i = 1; i < n; ++i) 7768 buf[i] = replace_pop(); 7769 ins_bytes_len(buf, n); 7770 } 7771 else 7772 ins_char(cc); 7773 7774 if (enc_utf8) 7775 /* Handle composing chars. */ 7776 for (;;) 7777 { 7778 c = replace_pop(); 7779 if (c == -1) /* stack empty */ 7780 break; 7781 if ((n = MB_BYTE2LEN(c)) == 1) 7782 { 7783 /* Not a multi-byte char, put it back. */ 7784 replace_push(c); 7785 break; 7786 } 7787 else 7788 { 7789 buf[0] = c; 7790 for (i = 1; i < n; ++i) 7791 buf[i] = replace_pop(); 7792 if (utf_iscomposing(utf_ptr2char(buf))) 7793 ins_bytes_len(buf, n); 7794 else 7795 { 7796 /* Not a composing char, put it back. */ 7797 for (i = n - 1; i >= 0; --i) 7798 replace_push(buf[i]); 7799 break; 7800 } 7801 } 7802 } 7803 } 7804 #endif 7805 7806 /* 7807 * make the replace stack empty 7808 * (called when exiting replace mode) 7809 */ 7810 static void 7811 replace_flush(void) 7812 { 7813 vim_free(replace_stack); 7814 replace_stack = NULL; 7815 replace_stack_len = 0; 7816 replace_stack_nr = 0; 7817 } 7818 7819 /* 7820 * Handle doing a BS for one character. 7821 * cc < 0: replace stack empty, just move cursor 7822 * cc == 0: character was inserted, delete it 7823 * cc > 0: character was replaced, put cc (first byte of original char) back 7824 * and check for more characters to be put back 7825 * When "limit_col" is >= 0, don't delete before this column. Matters when 7826 * using composing characters, use del_char_after_col() instead of del_char(). 7827 */ 7828 static void 7829 replace_do_bs(int limit_col) 7830 { 7831 int cc; 7832 #ifdef FEAT_VREPLACE 7833 int orig_len = 0; 7834 int ins_len; 7835 int orig_vcols = 0; 7836 colnr_T start_vcol; 7837 char_u *p; 7838 int i; 7839 int vcol; 7840 #endif 7841 7842 cc = replace_pop(); 7843 if (cc > 0) 7844 { 7845 #ifdef FEAT_VREPLACE 7846 if (State & VREPLACE_FLAG) 7847 { 7848 /* Get the number of screen cells used by the character we are 7849 * going to delete. */ 7850 getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL); 7851 orig_vcols = chartabsize(ml_get_cursor(), start_vcol); 7852 } 7853 #endif 7854 #ifdef FEAT_MBYTE 7855 if (has_mbyte) 7856 { 7857 (void)del_char_after_col(limit_col); 7858 # ifdef FEAT_VREPLACE 7859 if (State & VREPLACE_FLAG) 7860 orig_len = (int)STRLEN(ml_get_cursor()); 7861 # endif 7862 replace_push(cc); 7863 } 7864 else 7865 #endif 7866 { 7867 pchar_cursor(cc); 7868 #ifdef FEAT_VREPLACE 7869 if (State & VREPLACE_FLAG) 7870 orig_len = (int)STRLEN(ml_get_cursor()) - 1; 7871 #endif 7872 } 7873 replace_pop_ins(); 7874 7875 #ifdef FEAT_VREPLACE 7876 if (State & VREPLACE_FLAG) 7877 { 7878 /* Get the number of screen cells used by the inserted characters */ 7879 p = ml_get_cursor(); 7880 ins_len = (int)STRLEN(p) - orig_len; 7881 vcol = start_vcol; 7882 for (i = 0; i < ins_len; ++i) 7883 { 7884 vcol += chartabsize(p + i, vcol); 7885 #ifdef FEAT_MBYTE 7886 i += (*mb_ptr2len)(p) - 1; 7887 #endif 7888 } 7889 vcol -= start_vcol; 7890 7891 /* Delete spaces that were inserted after the cursor to keep the 7892 * text aligned. */ 7893 curwin->w_cursor.col += ins_len; 7894 while (vcol > orig_vcols && gchar_cursor() == ' ') 7895 { 7896 del_char(FALSE); 7897 ++orig_vcols; 7898 } 7899 curwin->w_cursor.col -= ins_len; 7900 } 7901 #endif 7902 7903 /* mark the buffer as changed and prepare for displaying */ 7904 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 7905 } 7906 else if (cc == 0) 7907 (void)del_char_after_col(limit_col); 7908 } 7909 7910 #ifdef FEAT_CINDENT 7911 /* 7912 * Return TRUE if C-indenting is on. 7913 */ 7914 static int 7915 cindent_on(void) 7916 { 7917 return (!p_paste && (curbuf->b_p_cin 7918 # ifdef FEAT_EVAL 7919 || *curbuf->b_p_inde != NUL 7920 # endif 7921 )); 7922 } 7923 #endif 7924 7925 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO) 7926 /* 7927 * Re-indent the current line, based on the current contents of it and the 7928 * surrounding lines. Fixing the cursor position seems really easy -- I'm very 7929 * confused what all the part that handles Control-T is doing that I'm not. 7930 * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent. 7931 */ 7932 7933 void 7934 fixthisline(int (*get_the_indent)(void)) 7935 { 7936 int amount = get_the_indent(); 7937 7938 if (amount >= 0) 7939 { 7940 change_indent(INDENT_SET, amount, FALSE, 0, TRUE); 7941 if (linewhite(curwin->w_cursor.lnum)) 7942 did_ai = TRUE; /* delete the indent if the line stays empty */ 7943 } 7944 } 7945 7946 void 7947 fix_indent(void) 7948 { 7949 if (p_paste) 7950 return; 7951 # ifdef FEAT_LISP 7952 if (curbuf->b_p_lisp && curbuf->b_p_ai) 7953 fixthisline(get_lisp_indent); 7954 # endif 7955 # if defined(FEAT_LISP) && defined(FEAT_CINDENT) 7956 else 7957 # endif 7958 # ifdef FEAT_CINDENT 7959 if (cindent_on()) 7960 do_c_expr_indent(); 7961 # endif 7962 } 7963 7964 #endif 7965 7966 #ifdef FEAT_CINDENT 7967 /* 7968 * return TRUE if 'cinkeys' contains the key "keytyped", 7969 * when == '*': Only if key is preceded with '*' (indent before insert) 7970 * when == '!': Only if key is preceded with '!' (don't insert) 7971 * when == ' ': Only if key is not preceded with '*'(indent afterwards) 7972 * 7973 * "keytyped" can have a few special values: 7974 * KEY_OPEN_FORW 7975 * KEY_OPEN_BACK 7976 * KEY_COMPLETE just finished completion. 7977 * 7978 * If line_is_empty is TRUE accept keys with '0' before them. 7979 */ 7980 int 7981 in_cinkeys( 7982 int keytyped, 7983 int when, 7984 int line_is_empty) 7985 { 7986 char_u *look; 7987 int try_match; 7988 int try_match_word; 7989 char_u *p; 7990 char_u *line; 7991 int icase; 7992 int i; 7993 7994 if (keytyped == NUL) 7995 /* Can happen with CTRL-Y and CTRL-E on a short line. */ 7996 return FALSE; 7997 7998 #ifdef FEAT_EVAL 7999 if (*curbuf->b_p_inde != NUL) 8000 look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */ 8001 else 8002 #endif 8003 look = curbuf->b_p_cink; /* 'indentexpr' empty: use 'cinkeys' */ 8004 while (*look) 8005 { 8006 /* 8007 * Find out if we want to try a match with this key, depending on 8008 * 'when' and a '*' or '!' before the key. 8009 */ 8010 switch (when) 8011 { 8012 case '*': try_match = (*look == '*'); break; 8013 case '!': try_match = (*look == '!'); break; 8014 default: try_match = (*look != '*'); break; 8015 } 8016 if (*look == '*' || *look == '!') 8017 ++look; 8018 8019 /* 8020 * If there is a '0', only accept a match if the line is empty. 8021 * But may still match when typing last char of a word. 8022 */ 8023 if (*look == '0') 8024 { 8025 try_match_word = try_match; 8026 if (!line_is_empty) 8027 try_match = FALSE; 8028 ++look; 8029 } 8030 else 8031 try_match_word = FALSE; 8032 8033 /* 8034 * does it look like a control character? 8035 */ 8036 if (*look == '^' 8037 #ifdef EBCDIC 8038 && (Ctrl_chr(look[1]) != 0) 8039 #else 8040 && look[1] >= '?' && look[1] <= '_' 8041 #endif 8042 ) 8043 { 8044 if (try_match && keytyped == Ctrl_chr(look[1])) 8045 return TRUE; 8046 look += 2; 8047 } 8048 /* 8049 * 'o' means "o" command, open forward. 8050 * 'O' means "O" command, open backward. 8051 */ 8052 else if (*look == 'o') 8053 { 8054 if (try_match && keytyped == KEY_OPEN_FORW) 8055 return TRUE; 8056 ++look; 8057 } 8058 else if (*look == 'O') 8059 { 8060 if (try_match && keytyped == KEY_OPEN_BACK) 8061 return TRUE; 8062 ++look; 8063 } 8064 8065 /* 8066 * 'e' means to check for "else" at start of line and just before the 8067 * cursor. 8068 */ 8069 else if (*look == 'e') 8070 { 8071 if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) 8072 { 8073 p = ml_get_curline(); 8074 if (skipwhite(p) == p + curwin->w_cursor.col - 4 && 8075 STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) 8076 return TRUE; 8077 } 8078 ++look; 8079 } 8080 8081 /* 8082 * ':' only causes an indent if it is at the end of a label or case 8083 * statement, or when it was before typing the ':' (to fix 8084 * class::method for C++). 8085 */ 8086 else if (*look == ':') 8087 { 8088 if (try_match && keytyped == ':') 8089 { 8090 p = ml_get_curline(); 8091 if (cin_iscase(p, FALSE) || cin_isscopedecl(p) || cin_islabel()) 8092 return TRUE; 8093 /* Need to get the line again after cin_islabel(). */ 8094 p = ml_get_curline(); 8095 if (curwin->w_cursor.col > 2 8096 && p[curwin->w_cursor.col - 1] == ':' 8097 && p[curwin->w_cursor.col - 2] == ':') 8098 { 8099 p[curwin->w_cursor.col - 1] = ' '; 8100 i = (cin_iscase(p, FALSE) || cin_isscopedecl(p) 8101 || cin_islabel()); 8102 p = ml_get_curline(); 8103 p[curwin->w_cursor.col - 1] = ':'; 8104 if (i) 8105 return TRUE; 8106 } 8107 } 8108 ++look; 8109 } 8110 8111 8112 /* 8113 * Is it a key in <>, maybe? 8114 */ 8115 else if (*look == '<') 8116 { 8117 if (try_match) 8118 { 8119 /* 8120 * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>, 8121 * <:> and <!> so that people can re-indent on o, O, e, 0, <, 8122 * >, *, : and ! keys if they really really want to. 8123 */ 8124 if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL 8125 && keytyped == look[1]) 8126 return TRUE; 8127 8128 if (keytyped == get_special_key_code(look + 1)) 8129 return TRUE; 8130 } 8131 while (*look && *look != '>') 8132 look++; 8133 while (*look == '>') 8134 look++; 8135 } 8136 8137 /* 8138 * Is it a word: "=word"? 8139 */ 8140 else if (*look == '=' && look[1] != ',' && look[1] != NUL) 8141 { 8142 ++look; 8143 if (*look == '~') 8144 { 8145 icase = TRUE; 8146 ++look; 8147 } 8148 else 8149 icase = FALSE; 8150 p = vim_strchr(look, ','); 8151 if (p == NULL) 8152 p = look + STRLEN(look); 8153 if ((try_match || try_match_word) 8154 && curwin->w_cursor.col >= (colnr_T)(p - look)) 8155 { 8156 int match = FALSE; 8157 8158 #ifdef FEAT_INS_EXPAND 8159 if (keytyped == KEY_COMPLETE) 8160 { 8161 char_u *s; 8162 8163 /* Just completed a word, check if it starts with "look". 8164 * search back for the start of a word. */ 8165 line = ml_get_curline(); 8166 # ifdef FEAT_MBYTE 8167 if (has_mbyte) 8168 { 8169 char_u *n; 8170 8171 for (s = line + curwin->w_cursor.col; s > line; s = n) 8172 { 8173 n = mb_prevptr(line, s); 8174 if (!vim_iswordp(n)) 8175 break; 8176 } 8177 } 8178 else 8179 # endif 8180 for (s = line + curwin->w_cursor.col; s > line; --s) 8181 if (!vim_iswordc(s[-1])) 8182 break; 8183 if (s + (p - look) <= line + curwin->w_cursor.col 8184 && (icase 8185 ? MB_STRNICMP(s, look, p - look) 8186 : STRNCMP(s, look, p - look)) == 0) 8187 match = TRUE; 8188 } 8189 else 8190 #endif 8191 /* TODO: multi-byte */ 8192 if (keytyped == (int)p[-1] || (icase && keytyped < 256 8193 && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) 8194 { 8195 line = ml_get_cursor(); 8196 if ((curwin->w_cursor.col == (colnr_T)(p - look) 8197 || !vim_iswordc(line[-(p - look) - 1])) 8198 && (icase 8199 ? MB_STRNICMP(line - (p - look), look, p - look) 8200 : STRNCMP(line - (p - look), look, p - look)) 8201 == 0) 8202 match = TRUE; 8203 } 8204 if (match && try_match_word && !try_match) 8205 { 8206 /* "0=word": Check if there are only blanks before the 8207 * word. */ 8208 if (getwhitecols_curline() != 8209 (int)(curwin->w_cursor.col - (p - look))) 8210 match = FALSE; 8211 } 8212 if (match) 8213 return TRUE; 8214 } 8215 look = p; 8216 } 8217 8218 /* 8219 * ok, it's a boring generic character. 8220 */ 8221 else 8222 { 8223 if (try_match && *look == keytyped) 8224 return TRUE; 8225 if (*look != NUL) 8226 ++look; 8227 } 8228 8229 /* 8230 * Skip over ", ". 8231 */ 8232 look = skip_to_option_part(look); 8233 } 8234 return FALSE; 8235 } 8236 #endif /* FEAT_CINDENT */ 8237 8238 #if defined(FEAT_RIGHTLEFT) || defined(PROTO) 8239 /* 8240 * Map Hebrew keyboard when in hkmap mode. 8241 */ 8242 int 8243 hkmap(int c) 8244 { 8245 if (p_hkmapp) /* phonetic mapping, by Ilya Dogolazky */ 8246 { 8247 enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD, 8248 KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN, 8249 PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV}; 8250 static char_u map[26] = 8251 {(char_u)hALEF/*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/, 8252 (char_u)DALET/*d*/, (char_u)-1 /*e*/, (char_u)PEIsofit/*f*/, 8253 (char_u)GIMEL/*g*/, (char_u)HEI /*h*/, (char_u)IUD /*i*/, 8254 (char_u)HET /*j*/, (char_u)KOF /*k*/, (char_u)LAMED /*l*/, 8255 (char_u)MEM /*m*/, (char_u)NUN /*n*/, (char_u)SAMEH /*o*/, 8256 (char_u)PEI /*p*/, (char_u)-1 /*q*/, (char_u)RESH /*r*/, 8257 (char_u)ZAIN /*s*/, (char_u)TAV /*t*/, (char_u)TET /*u*/, 8258 (char_u)VAV /*v*/, (char_u)hSHIN/*w*/, (char_u)-1 /*x*/, 8259 (char_u)AIN /*y*/, (char_u)ZADI /*z*/}; 8260 8261 if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z') 8262 return (int)(map[CharOrd(c)] - 1 + p_aleph); 8263 /* '-1'='sofit' */ 8264 else if (c == 'x') 8265 return 'X'; 8266 else if (c == 'q') 8267 return '\''; /* {geresh}={'} */ 8268 else if (c == 246) 8269 return ' '; /* \"o --> ' ' for a german keyboard */ 8270 else if (c == 228) 8271 return ' '; /* \"a --> ' ' -- / -- */ 8272 else if (c == 252) 8273 return ' '; /* \"u --> ' ' -- / -- */ 8274 #ifdef EBCDIC 8275 else if (islower(c)) 8276 #else 8277 /* NOTE: islower() does not do the right thing for us on Linux so we 8278 * do this the same was as 5.7 and previous, so it works correctly on 8279 * all systems. Specifically, the e.g. Delete and Arrow keys are 8280 * munged and won't work if e.g. searching for Hebrew text. 8281 */ 8282 else if (c >= 'a' && c <= 'z') 8283 #endif 8284 return (int)(map[CharOrdLow(c)] + p_aleph); 8285 else 8286 return c; 8287 } 8288 else 8289 { 8290 switch (c) 8291 { 8292 case '`': return ';'; 8293 case '/': return '.'; 8294 case '\'': return ','; 8295 case 'q': return '/'; 8296 case 'w': return '\''; 8297 8298 /* Hebrew letters - set offset from 'a' */ 8299 case ',': c = '{'; break; 8300 case '.': c = 'v'; break; 8301 case ';': c = 't'; break; 8302 default: { 8303 static char str[] = "zqbcxlsjphmkwonu ydafe rig"; 8304 8305 #ifdef EBCDIC 8306 /* see note about islower() above */ 8307 if (!islower(c)) 8308 #else 8309 if (c < 'a' || c > 'z') 8310 #endif 8311 return c; 8312 c = str[CharOrdLow(c)]; 8313 break; 8314 } 8315 } 8316 8317 return (int)(CharOrdLow(c) + p_aleph); 8318 } 8319 } 8320 #endif 8321 8322 static void 8323 ins_reg(void) 8324 { 8325 int need_redraw = FALSE; 8326 int regname; 8327 int literally = 0; 8328 int vis_active = VIsual_active; 8329 8330 /* 8331 * If we are going to wait for a character, show a '"'. 8332 */ 8333 pc_status = PC_STATUS_UNSET; 8334 if (redrawing() && !char_avail()) 8335 { 8336 /* may need to redraw when no more chars available now */ 8337 ins_redraw(FALSE); 8338 8339 edit_putchar('"', TRUE); 8340 #ifdef FEAT_CMDL_INFO 8341 add_to_showcmd_c(Ctrl_R); 8342 #endif 8343 } 8344 8345 #ifdef USE_ON_FLY_SCROLL 8346 dont_scroll = TRUE; /* disallow scrolling here */ 8347 #endif 8348 8349 /* 8350 * Don't map the register name. This also prevents the mode message to be 8351 * deleted when ESC is hit. 8352 */ 8353 ++no_mapping; 8354 regname = plain_vgetc(); 8355 LANGMAP_ADJUST(regname, TRUE); 8356 if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) 8357 { 8358 /* Get a third key for literal register insertion */ 8359 literally = regname; 8360 #ifdef FEAT_CMDL_INFO 8361 add_to_showcmd_c(literally); 8362 #endif 8363 regname = plain_vgetc(); 8364 LANGMAP_ADJUST(regname, TRUE); 8365 } 8366 --no_mapping; 8367 8368 #ifdef FEAT_EVAL 8369 /* Don't call u_sync() while typing the expression or giving an error 8370 * message for it. Only call it explicitly. */ 8371 ++no_u_sync; 8372 if (regname == '=') 8373 { 8374 # ifdef USE_IM_CONTROL 8375 int im_on = im_get_status(); 8376 # endif 8377 /* Sync undo when evaluating the expression calls setline() or 8378 * append(), so that it can be undone separately. */ 8379 u_sync_once = 2; 8380 8381 regname = get_expr_register(); 8382 # ifdef USE_IM_CONTROL 8383 /* Restore the Input Method. */ 8384 if (im_on) 8385 im_set_active(TRUE); 8386 # endif 8387 } 8388 if (regname == NUL || !valid_yank_reg(regname, FALSE)) 8389 { 8390 vim_beep(BO_REG); 8391 need_redraw = TRUE; /* remove the '"' */ 8392 } 8393 else 8394 { 8395 #endif 8396 if (literally == Ctrl_O || literally == Ctrl_P) 8397 { 8398 /* Append the command to the redo buffer. */ 8399 AppendCharToRedobuff(Ctrl_R); 8400 AppendCharToRedobuff(literally); 8401 AppendCharToRedobuff(regname); 8402 8403 do_put(regname, BACKWARD, 1L, 8404 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); 8405 } 8406 else if (insert_reg(regname, literally) == FAIL) 8407 { 8408 vim_beep(BO_REG); 8409 need_redraw = TRUE; /* remove the '"' */ 8410 } 8411 else if (stop_insert_mode) 8412 /* When the '=' register was used and a function was invoked that 8413 * did ":stopinsert" then stuff_empty() returns FALSE but we won't 8414 * insert anything, need to remove the '"' */ 8415 need_redraw = TRUE; 8416 8417 #ifdef FEAT_EVAL 8418 } 8419 --no_u_sync; 8420 if (u_sync_once == 1) 8421 ins_need_undo = TRUE; 8422 u_sync_once = 0; 8423 #endif 8424 #ifdef FEAT_CMDL_INFO 8425 clear_showcmd(); 8426 #endif 8427 8428 /* If the inserted register is empty, we need to remove the '"' */ 8429 if (need_redraw || stuff_empty()) 8430 edit_unputchar(); 8431 8432 /* Disallow starting Visual mode here, would get a weird mode. */ 8433 if (!vis_active && VIsual_active) 8434 end_visual_mode(); 8435 } 8436 8437 /* 8438 * CTRL-G commands in Insert mode. 8439 */ 8440 static void 8441 ins_ctrl_g(void) 8442 { 8443 int c; 8444 8445 #ifdef FEAT_INS_EXPAND 8446 /* Right after CTRL-X the cursor will be after the ruler. */ 8447 setcursor(); 8448 #endif 8449 8450 /* 8451 * Don't map the second key. This also prevents the mode message to be 8452 * deleted when ESC is hit. 8453 */ 8454 ++no_mapping; 8455 c = plain_vgetc(); 8456 --no_mapping; 8457 switch (c) 8458 { 8459 /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */ 8460 case K_UP: 8461 case Ctrl_K: 8462 case 'k': ins_up(TRUE); 8463 break; 8464 8465 /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */ 8466 case K_DOWN: 8467 case Ctrl_J: 8468 case 'j': ins_down(TRUE); 8469 break; 8470 8471 /* CTRL-G u: start new undoable edit */ 8472 case 'u': u_sync(TRUE); 8473 ins_need_undo = TRUE; 8474 8475 /* Need to reset Insstart, esp. because a BS that joins 8476 * a line to the previous one must save for undo. */ 8477 update_Insstart_orig = FALSE; 8478 Insstart = curwin->w_cursor; 8479 break; 8480 8481 /* CTRL-G U: do not break undo with the next char */ 8482 case 'U': 8483 /* Allow one left/right cursor movement with the next char, 8484 * without breaking undo. */ 8485 dont_sync_undo = MAYBE; 8486 break; 8487 8488 /* Unknown CTRL-G command, reserved for future expansion. */ 8489 default: vim_beep(BO_CTRLG); 8490 } 8491 } 8492 8493 /* 8494 * CTRL-^ in Insert mode. 8495 */ 8496 static void 8497 ins_ctrl_hat(void) 8498 { 8499 if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) 8500 { 8501 /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ 8502 if (State & LANGMAP) 8503 { 8504 curbuf->b_p_iminsert = B_IMODE_NONE; 8505 State &= ~LANGMAP; 8506 } 8507 else 8508 { 8509 curbuf->b_p_iminsert = B_IMODE_LMAP; 8510 State |= LANGMAP; 8511 #ifdef USE_IM_CONTROL 8512 im_set_active(FALSE); 8513 #endif 8514 } 8515 } 8516 #ifdef USE_IM_CONTROL 8517 else 8518 { 8519 /* There are no ":lmap" mappings, toggle IM */ 8520 if (im_get_status()) 8521 { 8522 curbuf->b_p_iminsert = B_IMODE_NONE; 8523 im_set_active(FALSE); 8524 } 8525 else 8526 { 8527 curbuf->b_p_iminsert = B_IMODE_IM; 8528 State &= ~LANGMAP; 8529 im_set_active(TRUE); 8530 } 8531 } 8532 #endif 8533 set_iminsert_global(); 8534 showmode(); 8535 #ifdef FEAT_GUI 8536 /* may show different cursor shape or color */ 8537 if (gui.in_use) 8538 gui_update_cursor(TRUE, FALSE); 8539 #endif 8540 #if defined(FEAT_KEYMAP) 8541 /* Show/unshow value of 'keymap' in status lines. */ 8542 status_redraw_curbuf(); 8543 #endif 8544 } 8545 8546 /* 8547 * Handle ESC in insert mode. 8548 * Returns TRUE when leaving insert mode, FALSE when going to repeat the 8549 * insert. 8550 */ 8551 static int 8552 ins_esc( 8553 long *count, 8554 int cmdchar, 8555 int nomove) /* don't move cursor */ 8556 { 8557 int temp; 8558 static int disabled_redraw = FALSE; 8559 8560 #ifdef FEAT_SPELL 8561 check_spell_redraw(); 8562 #endif 8563 #if defined(FEAT_HANGULIN) 8564 # if defined(ESC_CHG_TO_ENG_MODE) 8565 hangul_input_state_set(0); 8566 # endif 8567 if (composing_hangul) 8568 { 8569 push_raw_key(composing_hangul_buffer, 2); 8570 composing_hangul = 0; 8571 } 8572 #endif 8573 8574 temp = curwin->w_cursor.col; 8575 if (disabled_redraw) 8576 { 8577 --RedrawingDisabled; 8578 disabled_redraw = FALSE; 8579 } 8580 if (!arrow_used) 8581 { 8582 /* 8583 * Don't append the ESC for "r<CR>" and "grx". 8584 * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for 8585 * when "count" is non-zero. 8586 */ 8587 if (cmdchar != 'r' && cmdchar != 'v') 8588 AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); 8589 8590 /* 8591 * Repeating insert may take a long time. Check for 8592 * interrupt now and then. 8593 */ 8594 if (*count > 0) 8595 { 8596 line_breakcheck(); 8597 if (got_int) 8598 *count = 0; 8599 } 8600 8601 if (--*count > 0) /* repeat what was typed */ 8602 { 8603 /* Vi repeats the insert without replacing characters. */ 8604 if (vim_strchr(p_cpo, CPO_REPLCNT) != NULL) 8605 State &= ~REPLACE_FLAG; 8606 8607 (void)start_redo_ins(); 8608 if (cmdchar == 'r' || cmdchar == 'v') 8609 stuffRedoReadbuff(ESC_STR); /* no ESC in redo buffer */ 8610 ++RedrawingDisabled; 8611 disabled_redraw = TRUE; 8612 return FALSE; /* repeat the insert */ 8613 } 8614 stop_insert(&curwin->w_cursor, TRUE, nomove); 8615 undisplay_dollar(); 8616 } 8617 8618 /* When an autoindent was removed, curswant stays after the 8619 * indent */ 8620 if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col) 8621 curwin->w_set_curswant = TRUE; 8622 8623 /* Remember the last Insert position in the '^ mark. */ 8624 if (!cmdmod.keepjumps) 8625 curbuf->b_last_insert = curwin->w_cursor; 8626 8627 /* 8628 * The cursor should end up on the last inserted character. 8629 * Don't do it for CTRL-O, unless past the end of the line. 8630 */ 8631 if (!nomove 8632 && (curwin->w_cursor.col != 0 8633 #ifdef FEAT_VIRTUALEDIT 8634 || curwin->w_cursor.coladd > 0 8635 #endif 8636 ) 8637 && (restart_edit == NUL 8638 || (gchar_cursor() == NUL && !VIsual_active)) 8639 #ifdef FEAT_RIGHTLEFT 8640 && !revins_on 8641 #endif 8642 ) 8643 { 8644 #ifdef FEAT_VIRTUALEDIT 8645 if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL) 8646 { 8647 oneleft(); 8648 if (restart_edit != NUL) 8649 ++curwin->w_cursor.coladd; 8650 } 8651 else 8652 #endif 8653 { 8654 --curwin->w_cursor.col; 8655 #ifdef FEAT_MBYTE 8656 /* Correct cursor for multi-byte character. */ 8657 if (has_mbyte) 8658 mb_adjust_cursor(); 8659 #endif 8660 } 8661 } 8662 8663 #ifdef USE_IM_CONTROL 8664 /* Disable IM to allow typing English directly for Normal mode commands. 8665 * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as 8666 * well). */ 8667 if (!(State & LANGMAP)) 8668 im_save_status(&curbuf->b_p_iminsert); 8669 im_set_active(FALSE); 8670 #endif 8671 8672 State = NORMAL; 8673 /* need to position cursor again (e.g. when on a TAB ) */ 8674 changed_cline_bef_curs(); 8675 8676 #ifdef FEAT_MOUSE 8677 setmouse(); 8678 #endif 8679 #ifdef CURSOR_SHAPE 8680 ui_cursor_shape(); /* may show different cursor shape */ 8681 #endif 8682 if (!p_ek) 8683 /* Re-enable bracketed paste mode. */ 8684 out_str(T_BE); 8685 8686 /* 8687 * When recording or for CTRL-O, need to display the new mode. 8688 * Otherwise remove the mode message. 8689 */ 8690 if (Recording || restart_edit != NUL) 8691 showmode(); 8692 else if (p_smd) 8693 MSG(""); 8694 8695 return TRUE; /* exit Insert mode */ 8696 } 8697 8698 #ifdef FEAT_RIGHTLEFT 8699 /* 8700 * Toggle language: hkmap and revins_on. 8701 * Move to end of reverse inserted text. 8702 */ 8703 static void 8704 ins_ctrl_(void) 8705 { 8706 if (revins_on && revins_chars && revins_scol >= 0) 8707 { 8708 while (gchar_cursor() != NUL && revins_chars--) 8709 ++curwin->w_cursor.col; 8710 } 8711 p_ri = !p_ri; 8712 revins_on = (State == INSERT && p_ri); 8713 if (revins_on) 8714 { 8715 revins_scol = curwin->w_cursor.col; 8716 revins_legal++; 8717 revins_chars = 0; 8718 undisplay_dollar(); 8719 } 8720 else 8721 revins_scol = -1; 8722 #ifdef FEAT_FKMAP 8723 if (p_altkeymap) 8724 { 8725 /* 8726 * to be consistent also for redo command, using '.' 8727 * set arrow_used to true and stop it - causing to redo 8728 * characters entered in one mode (normal/reverse insert). 8729 */ 8730 arrow_used = TRUE; 8731 (void)stop_arrow(); 8732 p_fkmap = curwin->w_p_rl ^ p_ri; 8733 if (p_fkmap && p_ri) 8734 State = INSERT; 8735 } 8736 else 8737 #endif 8738 p_hkmap = curwin->w_p_rl ^ p_ri; /* be consistent! */ 8739 showmode(); 8740 } 8741 #endif 8742 8743 /* 8744 * If 'keymodel' contains "startsel", may start selection. 8745 * Returns TRUE when a CTRL-O and other keys stuffed. 8746 */ 8747 static int 8748 ins_start_select(int c) 8749 { 8750 if (km_startsel) 8751 switch (c) 8752 { 8753 case K_KHOME: 8754 case K_KEND: 8755 case K_PAGEUP: 8756 case K_KPAGEUP: 8757 case K_PAGEDOWN: 8758 case K_KPAGEDOWN: 8759 # ifdef MACOS_X 8760 case K_LEFT: 8761 case K_RIGHT: 8762 case K_UP: 8763 case K_DOWN: 8764 case K_END: 8765 case K_HOME: 8766 # endif 8767 if (!(mod_mask & MOD_MASK_SHIFT)) 8768 break; 8769 /* FALLTHROUGH */ 8770 case K_S_LEFT: 8771 case K_S_RIGHT: 8772 case K_S_UP: 8773 case K_S_DOWN: 8774 case K_S_END: 8775 case K_S_HOME: 8776 /* Start selection right away, the cursor can move with 8777 * CTRL-O when beyond the end of the line. */ 8778 start_selection(); 8779 8780 /* Execute the key in (insert) Select mode. */ 8781 stuffcharReadbuff(Ctrl_O); 8782 if (mod_mask) 8783 { 8784 char_u buf[4]; 8785 8786 buf[0] = K_SPECIAL; 8787 buf[1] = KS_MODIFIER; 8788 buf[2] = mod_mask; 8789 buf[3] = NUL; 8790 stuffReadbuff(buf); 8791 } 8792 stuffcharReadbuff(c); 8793 return TRUE; 8794 } 8795 return FALSE; 8796 } 8797 8798 /* 8799 * <Insert> key in Insert mode: toggle insert/replace mode. 8800 */ 8801 static void 8802 ins_insert(int replaceState) 8803 { 8804 #ifdef FEAT_FKMAP 8805 if (p_fkmap && p_ri) 8806 { 8807 beep_flush(); 8808 EMSG(farsi_text_3); /* encoded in Farsi */ 8809 return; 8810 } 8811 #endif 8812 8813 #ifdef FEAT_AUTOCMD 8814 # ifdef FEAT_EVAL 8815 set_vim_var_string(VV_INSERTMODE, 8816 (char_u *)((State & REPLACE_FLAG) ? "i" : 8817 # ifdef FEAT_VREPLACE 8818 replaceState == VREPLACE ? "v" : 8819 # endif 8820 "r"), 1); 8821 # endif 8822 apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf); 8823 #endif 8824 if (State & REPLACE_FLAG) 8825 State = INSERT | (State & LANGMAP); 8826 else 8827 State = replaceState | (State & LANGMAP); 8828 AppendCharToRedobuff(K_INS); 8829 showmode(); 8830 #ifdef CURSOR_SHAPE 8831 ui_cursor_shape(); /* may show different cursor shape */ 8832 #endif 8833 } 8834 8835 /* 8836 * Pressed CTRL-O in Insert mode. 8837 */ 8838 static void 8839 ins_ctrl_o(void) 8840 { 8841 #ifdef FEAT_VREPLACE 8842 if (State & VREPLACE_FLAG) 8843 restart_edit = 'V'; 8844 else 8845 #endif 8846 if (State & REPLACE_FLAG) 8847 restart_edit = 'R'; 8848 else 8849 restart_edit = 'I'; 8850 #ifdef FEAT_VIRTUALEDIT 8851 if (virtual_active()) 8852 ins_at_eol = FALSE; /* cursor always keeps its column */ 8853 else 8854 #endif 8855 ins_at_eol = (gchar_cursor() == NUL); 8856 } 8857 8858 /* 8859 * If the cursor is on an indent, ^T/^D insert/delete one 8860 * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". 8861 * Always round the indent to 'shiftwidth', this is compatible 8862 * with vi. But vi only supports ^T and ^D after an 8863 * autoindent, we support it everywhere. 8864 */ 8865 static void 8866 ins_shift(int c, int lastc) 8867 { 8868 if (stop_arrow() == FAIL) 8869 return; 8870 AppendCharToRedobuff(c); 8871 8872 /* 8873 * 0^D and ^^D: remove all indent. 8874 */ 8875 if (c == Ctrl_D && (lastc == '0' || lastc == '^') 8876 && curwin->w_cursor.col > 0) 8877 { 8878 --curwin->w_cursor.col; 8879 (void)del_char(FALSE); /* delete the '^' or '0' */ 8880 /* In Replace mode, restore the characters that '^' or '0' replaced. */ 8881 if (State & REPLACE_FLAG) 8882 replace_pop_ins(); 8883 if (lastc == '^') 8884 old_indent = get_indent(); /* remember curr. indent */ 8885 change_indent(INDENT_SET, 0, TRUE, 0, TRUE); 8886 } 8887 else 8888 change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); 8889 8890 if (did_ai && *skipwhite(ml_get_curline()) != NUL) 8891 did_ai = FALSE; 8892 #ifdef FEAT_SMARTINDENT 8893 did_si = FALSE; 8894 can_si = FALSE; 8895 can_si_back = FALSE; 8896 #endif 8897 #ifdef FEAT_CINDENT 8898 can_cindent = FALSE; /* no cindenting after ^D or ^T */ 8899 #endif 8900 } 8901 8902 static void 8903 ins_del(void) 8904 { 8905 int temp; 8906 8907 if (stop_arrow() == FAIL) 8908 return; 8909 if (gchar_cursor() == NUL) /* delete newline */ 8910 { 8911 temp = curwin->w_cursor.col; 8912 if (!can_bs(BS_EOL) /* only if "eol" included */ 8913 || do_join(2, FALSE, TRUE, FALSE, FALSE) == FAIL) 8914 vim_beep(BO_BS); 8915 else 8916 curwin->w_cursor.col = temp; 8917 } 8918 else if (del_char(FALSE) == FAIL) /* delete char under cursor */ 8919 vim_beep(BO_BS); 8920 did_ai = FALSE; 8921 #ifdef FEAT_SMARTINDENT 8922 did_si = FALSE; 8923 can_si = FALSE; 8924 can_si_back = FALSE; 8925 #endif 8926 AppendCharToRedobuff(K_DEL); 8927 } 8928 8929 static void ins_bs_one(colnr_T *vcolp); 8930 8931 /* 8932 * Delete one character for ins_bs(). 8933 */ 8934 static void 8935 ins_bs_one(colnr_T *vcolp) 8936 { 8937 dec_cursor(); 8938 getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL); 8939 if (State & REPLACE_FLAG) 8940 { 8941 /* Don't delete characters before the insert point when in 8942 * Replace mode */ 8943 if (curwin->w_cursor.lnum != Insstart.lnum 8944 || curwin->w_cursor.col >= Insstart.col) 8945 replace_do_bs(-1); 8946 } 8947 else 8948 (void)del_char(FALSE); 8949 } 8950 8951 /* 8952 * Handle Backspace, delete-word and delete-line in Insert mode. 8953 * Return TRUE when backspace was actually used. 8954 */ 8955 static int 8956 ins_bs( 8957 int c, 8958 int mode, 8959 int *inserted_space_p) 8960 { 8961 linenr_T lnum; 8962 int cc; 8963 int temp = 0; /* init for GCC */ 8964 colnr_T save_col; 8965 colnr_T mincol; 8966 int did_backspace = FALSE; 8967 int in_indent; 8968 int oldState; 8969 #ifdef FEAT_MBYTE 8970 int cpc[MAX_MCO]; /* composing characters */ 8971 #endif 8972 8973 /* 8974 * can't delete anything in an empty file 8975 * can't backup past first character in buffer 8976 * can't backup past starting point unless 'backspace' > 1 8977 * can backup to a previous line if 'backspace' == 0 8978 */ 8979 if ( BUFEMPTY() 8980 || ( 8981 #ifdef FEAT_RIGHTLEFT 8982 !revins_on && 8983 #endif 8984 ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0) 8985 || (!can_bs(BS_START) 8986 && (arrow_used 8987 || (curwin->w_cursor.lnum == Insstart_orig.lnum 8988 && curwin->w_cursor.col <= Insstart_orig.col))) 8989 || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0 8990 && curwin->w_cursor.col <= ai_col) 8991 || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0)))) 8992 { 8993 vim_beep(BO_BS); 8994 return FALSE; 8995 } 8996 8997 if (stop_arrow() == FAIL) 8998 return FALSE; 8999 in_indent = inindent(0); 9000 #ifdef FEAT_CINDENT 9001 if (in_indent) 9002 can_cindent = FALSE; 9003 #endif 9004 #ifdef FEAT_COMMENTS 9005 end_comment_pending = NUL; /* After BS, don't auto-end comment */ 9006 #endif 9007 #ifdef FEAT_RIGHTLEFT 9008 if (revins_on) /* put cursor after last inserted char */ 9009 inc_cursor(); 9010 #endif 9011 9012 #ifdef FEAT_VIRTUALEDIT 9013 /* Virtualedit: 9014 * BACKSPACE_CHAR eats a virtual space 9015 * BACKSPACE_WORD eats all coladd 9016 * BACKSPACE_LINE eats all coladd and keeps going 9017 */ 9018 if (curwin->w_cursor.coladd > 0) 9019 { 9020 if (mode == BACKSPACE_CHAR) 9021 { 9022 --curwin->w_cursor.coladd; 9023 return TRUE; 9024 } 9025 if (mode == BACKSPACE_WORD) 9026 { 9027 curwin->w_cursor.coladd = 0; 9028 return TRUE; 9029 } 9030 curwin->w_cursor.coladd = 0; 9031 } 9032 #endif 9033 9034 /* 9035 * Delete newline! 9036 */ 9037 if (curwin->w_cursor.col == 0) 9038 { 9039 lnum = Insstart.lnum; 9040 if (curwin->w_cursor.lnum == lnum 9041 #ifdef FEAT_RIGHTLEFT 9042 || revins_on 9043 #endif 9044 ) 9045 { 9046 if (u_save((linenr_T)(curwin->w_cursor.lnum - 2), 9047 (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) 9048 return FALSE; 9049 --Insstart.lnum; 9050 Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum)); 9051 } 9052 /* 9053 * In replace mode: 9054 * cc < 0: NL was inserted, delete it 9055 * cc >= 0: NL was replaced, put original characters back 9056 */ 9057 cc = -1; 9058 if (State & REPLACE_FLAG) 9059 cc = replace_pop(); /* returns -1 if NL was inserted */ 9060 /* 9061 * In replace mode, in the line we started replacing, we only move the 9062 * cursor. 9063 */ 9064 if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum) 9065 { 9066 dec_cursor(); 9067 } 9068 else 9069 { 9070 #ifdef FEAT_VREPLACE 9071 if (!(State & VREPLACE_FLAG) 9072 || curwin->w_cursor.lnum > orig_line_count) 9073 #endif 9074 { 9075 temp = gchar_cursor(); /* remember current char */ 9076 --curwin->w_cursor.lnum; 9077 9078 /* When "aw" is in 'formatoptions' we must delete the space at 9079 * the end of the line, otherwise the line will be broken 9080 * again when auto-formatting. */ 9081 if (has_format_option(FO_AUTO) 9082 && has_format_option(FO_WHITE_PAR)) 9083 { 9084 char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, 9085 TRUE); 9086 int len; 9087 9088 len = (int)STRLEN(ptr); 9089 if (len > 0 && ptr[len - 1] == ' ') 9090 ptr[len - 1] = NUL; 9091 } 9092 9093 (void)do_join(2, FALSE, FALSE, FALSE, FALSE); 9094 if (temp == NUL && gchar_cursor() != NUL) 9095 inc_cursor(); 9096 } 9097 #ifdef FEAT_VREPLACE 9098 else 9099 dec_cursor(); 9100 #endif 9101 9102 /* 9103 * In REPLACE mode we have to put back the text that was replaced 9104 * by the NL. On the replace stack is first a NUL-terminated 9105 * sequence of characters that were deleted and then the 9106 * characters that NL replaced. 9107 */ 9108 if (State & REPLACE_FLAG) 9109 { 9110 /* 9111 * Do the next ins_char() in NORMAL state, to 9112 * prevent ins_char() from replacing characters and 9113 * avoiding showmatch(). 9114 */ 9115 oldState = State; 9116 State = NORMAL; 9117 /* 9118 * restore characters (blanks) deleted after cursor 9119 */ 9120 while (cc > 0) 9121 { 9122 save_col = curwin->w_cursor.col; 9123 #ifdef FEAT_MBYTE 9124 mb_replace_pop_ins(cc); 9125 #else 9126 ins_char(cc); 9127 #endif 9128 curwin->w_cursor.col = save_col; 9129 cc = replace_pop(); 9130 } 9131 /* restore the characters that NL replaced */ 9132 replace_pop_ins(); 9133 State = oldState; 9134 } 9135 } 9136 did_ai = FALSE; 9137 } 9138 else 9139 { 9140 /* 9141 * Delete character(s) before the cursor. 9142 */ 9143 #ifdef FEAT_RIGHTLEFT 9144 if (revins_on) /* put cursor on last inserted char */ 9145 dec_cursor(); 9146 #endif 9147 mincol = 0; 9148 /* keep indent */ 9149 if (mode == BACKSPACE_LINE 9150 && (curbuf->b_p_ai 9151 #ifdef FEAT_CINDENT 9152 || cindent_on() 9153 #endif 9154 ) 9155 #ifdef FEAT_RIGHTLEFT 9156 && !revins_on 9157 #endif 9158 ) 9159 { 9160 save_col = curwin->w_cursor.col; 9161 beginline(BL_WHITE); 9162 if (curwin->w_cursor.col < save_col) 9163 mincol = curwin->w_cursor.col; 9164 curwin->w_cursor.col = save_col; 9165 } 9166 9167 /* 9168 * Handle deleting one 'shiftwidth' or 'softtabstop'. 9169 */ 9170 if ( mode == BACKSPACE_CHAR 9171 && ((p_sta && in_indent) 9172 || (get_sts_value() != 0 9173 && curwin->w_cursor.col > 0 9174 && (*(ml_get_cursor() - 1) == TAB 9175 || (*(ml_get_cursor() - 1) == ' ' 9176 && (!*inserted_space_p 9177 || arrow_used)))))) 9178 { 9179 int ts; 9180 colnr_T vcol; 9181 colnr_T want_vcol; 9182 colnr_T start_vcol; 9183 9184 *inserted_space_p = FALSE; 9185 if (p_sta && in_indent) 9186 ts = (int)get_sw_value(curbuf); 9187 else 9188 ts = (int)get_sts_value(); 9189 /* Compute the virtual column where we want to be. Since 9190 * 'showbreak' may get in the way, need to get the last column of 9191 * the previous character. */ 9192 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 9193 start_vcol = vcol; 9194 dec_cursor(); 9195 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); 9196 inc_cursor(); 9197 want_vcol = (want_vcol / ts) * ts; 9198 9199 /* delete characters until we are at or before want_vcol */ 9200 while (vcol > want_vcol 9201 && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc))) 9202 ins_bs_one(&vcol); 9203 9204 /* insert extra spaces until we are at want_vcol */ 9205 while (vcol < want_vcol) 9206 { 9207 /* Remember the first char we inserted */ 9208 if (curwin->w_cursor.lnum == Insstart_orig.lnum 9209 && curwin->w_cursor.col < Insstart_orig.col) 9210 Insstart_orig.col = curwin->w_cursor.col; 9211 9212 #ifdef FEAT_VREPLACE 9213 if (State & VREPLACE_FLAG) 9214 ins_char(' '); 9215 else 9216 #endif 9217 { 9218 ins_str((char_u *)" "); 9219 if ((State & REPLACE_FLAG)) 9220 replace_push(NUL); 9221 } 9222 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 9223 } 9224 9225 /* If we are now back where we started delete one character. Can 9226 * happen when using 'sts' and 'linebreak'. */ 9227 if (vcol >= start_vcol) 9228 ins_bs_one(&vcol); 9229 } 9230 9231 /* 9232 * Delete upto starting point, start of line or previous word. 9233 */ 9234 else 9235 { 9236 #ifdef FEAT_MBYTE 9237 int cclass = 0, prev_cclass = 0; 9238 9239 if (has_mbyte) 9240 cclass = mb_get_class(ml_get_cursor()); 9241 #endif 9242 do 9243 { 9244 #ifdef FEAT_RIGHTLEFT 9245 if (!revins_on) /* put cursor on char to be deleted */ 9246 #endif 9247 dec_cursor(); 9248 9249 cc = gchar_cursor(); 9250 #ifdef FEAT_MBYTE 9251 /* look multi-byte character class */ 9252 if (has_mbyte) 9253 { 9254 prev_cclass = cclass; 9255 cclass = mb_get_class(ml_get_cursor()); 9256 } 9257 #endif 9258 9259 /* start of word? */ 9260 if (mode == BACKSPACE_WORD && !vim_isspace(cc)) 9261 { 9262 mode = BACKSPACE_WORD_NOT_SPACE; 9263 temp = vim_iswordc(cc); 9264 } 9265 /* end of word? */ 9266 else if (mode == BACKSPACE_WORD_NOT_SPACE 9267 && ((vim_isspace(cc) || vim_iswordc(cc) != temp) 9268 #ifdef FEAT_MBYTE 9269 || prev_cclass != cclass 9270 #endif 9271 )) 9272 { 9273 #ifdef FEAT_RIGHTLEFT 9274 if (!revins_on) 9275 #endif 9276 inc_cursor(); 9277 #ifdef FEAT_RIGHTLEFT 9278 else if (State & REPLACE_FLAG) 9279 dec_cursor(); 9280 #endif 9281 break; 9282 } 9283 if (State & REPLACE_FLAG) 9284 replace_do_bs(-1); 9285 else 9286 { 9287 #ifdef FEAT_MBYTE 9288 if (enc_utf8 && p_deco) 9289 (void)utfc_ptr2char(ml_get_cursor(), cpc); 9290 #endif 9291 (void)del_char(FALSE); 9292 #ifdef FEAT_MBYTE 9293 /* 9294 * If there are combining characters and 'delcombine' is set 9295 * move the cursor back. Don't back up before the base 9296 * character. 9297 */ 9298 if (enc_utf8 && p_deco && cpc[0] != NUL) 9299 inc_cursor(); 9300 #endif 9301 #ifdef FEAT_RIGHTLEFT 9302 if (revins_chars) 9303 { 9304 revins_chars--; 9305 revins_legal++; 9306 } 9307 if (revins_on && gchar_cursor() == NUL) 9308 break; 9309 #endif 9310 } 9311 /* Just a single backspace?: */ 9312 if (mode == BACKSPACE_CHAR) 9313 break; 9314 } while ( 9315 #ifdef FEAT_RIGHTLEFT 9316 revins_on || 9317 #endif 9318 (curwin->w_cursor.col > mincol 9319 && (curwin->w_cursor.lnum != Insstart_orig.lnum 9320 || curwin->w_cursor.col != Insstart_orig.col))); 9321 } 9322 did_backspace = TRUE; 9323 } 9324 #ifdef FEAT_SMARTINDENT 9325 did_si = FALSE; 9326 can_si = FALSE; 9327 can_si_back = FALSE; 9328 #endif 9329 if (curwin->w_cursor.col <= 1) 9330 did_ai = FALSE; 9331 /* 9332 * It's a little strange to put backspaces into the redo 9333 * buffer, but it makes auto-indent a lot easier to deal 9334 * with. 9335 */ 9336 AppendCharToRedobuff(c); 9337 9338 /* If deleted before the insertion point, adjust it */ 9339 if (curwin->w_cursor.lnum == Insstart_orig.lnum 9340 && curwin->w_cursor.col < Insstart_orig.col) 9341 Insstart_orig.col = curwin->w_cursor.col; 9342 9343 /* vi behaviour: the cursor moves backward but the character that 9344 * was there remains visible 9345 * Vim behaviour: the cursor moves backward and the character that 9346 * was there is erased from the screen. 9347 * We can emulate the vi behaviour by pretending there is a dollar 9348 * displayed even when there isn't. 9349 * --pkv Sun Jan 19 01:56:40 EST 2003 */ 9350 if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == -1) 9351 dollar_vcol = curwin->w_virtcol; 9352 9353 #ifdef FEAT_FOLDING 9354 /* When deleting a char the cursor line must never be in a closed fold. 9355 * E.g., when 'foldmethod' is indent and deleting the first non-white 9356 * char before a Tab. */ 9357 if (did_backspace) 9358 foldOpenCursor(); 9359 #endif 9360 9361 return did_backspace; 9362 } 9363 9364 #ifdef FEAT_MOUSE 9365 static void 9366 ins_mouse(int c) 9367 { 9368 pos_T tpos; 9369 win_T *old_curwin = curwin; 9370 9371 # ifdef FEAT_GUI 9372 /* When GUI is active, also move/paste when 'mouse' is empty */ 9373 if (!gui.in_use) 9374 # endif 9375 if (!mouse_has(MOUSE_INSERT)) 9376 return; 9377 9378 undisplay_dollar(); 9379 tpos = curwin->w_cursor; 9380 if (do_mouse(NULL, c, BACKWARD, 1L, 0)) 9381 { 9382 win_T *new_curwin = curwin; 9383 9384 if (curwin != old_curwin && win_valid(old_curwin)) 9385 { 9386 /* Mouse took us to another window. We need to go back to the 9387 * previous one to stop insert there properly. */ 9388 curwin = old_curwin; 9389 curbuf = curwin->w_buffer; 9390 } 9391 start_arrow(curwin == old_curwin ? &tpos : NULL); 9392 if (curwin != new_curwin && win_valid(new_curwin)) 9393 { 9394 curwin = new_curwin; 9395 curbuf = curwin->w_buffer; 9396 } 9397 # ifdef FEAT_CINDENT 9398 can_cindent = TRUE; 9399 # endif 9400 } 9401 9402 /* redraw status lines (in case another window became active) */ 9403 redraw_statuslines(); 9404 } 9405 9406 static void 9407 ins_mousescroll(int dir) 9408 { 9409 pos_T tpos; 9410 win_T *old_curwin = curwin, *wp; 9411 # ifdef FEAT_INS_EXPAND 9412 int did_scroll = FALSE; 9413 # endif 9414 9415 tpos = curwin->w_cursor; 9416 9417 if (mouse_row >= 0 && mouse_col >= 0) 9418 { 9419 int row, col; 9420 9421 row = mouse_row; 9422 col = mouse_col; 9423 9424 /* find the window at the pointer coordinates */ 9425 wp = mouse_find_win(&row, &col); 9426 if (wp == NULL) 9427 return; 9428 curwin = wp; 9429 curbuf = curwin->w_buffer; 9430 } 9431 if (curwin == old_curwin) 9432 undisplay_dollar(); 9433 9434 # ifdef FEAT_INS_EXPAND 9435 /* Don't scroll the window in which completion is being done. */ 9436 if (!pum_visible() || curwin != old_curwin) 9437 # endif 9438 { 9439 if (dir == MSCR_DOWN || dir == MSCR_UP) 9440 { 9441 if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) 9442 scroll_redraw(dir, 9443 (long)(curwin->w_botline - curwin->w_topline)); 9444 else 9445 scroll_redraw(dir, 3L); 9446 } 9447 #ifdef FEAT_GUI 9448 else 9449 { 9450 int val, step = 6; 9451 9452 if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) 9453 step = curwin->w_width; 9454 val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step); 9455 if (val < 0) 9456 val = 0; 9457 gui_do_horiz_scroll(val, TRUE); 9458 } 9459 #endif 9460 # ifdef FEAT_INS_EXPAND 9461 did_scroll = TRUE; 9462 # endif 9463 } 9464 9465 curwin->w_redr_status = TRUE; 9466 9467 curwin = old_curwin; 9468 curbuf = curwin->w_buffer; 9469 9470 # ifdef FEAT_INS_EXPAND 9471 /* The popup menu may overlay the window, need to redraw it. 9472 * TODO: Would be more efficient to only redraw the windows that are 9473 * overlapped by the popup menu. */ 9474 if (pum_visible() && did_scroll) 9475 { 9476 redraw_all_later(NOT_VALID); 9477 ins_compl_show_pum(); 9478 } 9479 # endif 9480 9481 if (!EQUAL_POS(curwin->w_cursor, tpos)) 9482 { 9483 start_arrow(&tpos); 9484 # ifdef FEAT_CINDENT 9485 can_cindent = TRUE; 9486 # endif 9487 } 9488 } 9489 #endif 9490 9491 /* 9492 * Handle receiving P_PS: start paste mode. Inserts the following text up to 9493 * P_PE literally. 9494 * When "drop" is TRUE then consume the text and drop it. 9495 */ 9496 int 9497 bracketed_paste(paste_mode_T mode, int drop, garray_T *gap) 9498 { 9499 int c; 9500 char_u buf[NUMBUFLEN + MB_MAXBYTES]; 9501 int idx = 0; 9502 char_u *end = find_termcode((char_u *)"PE"); 9503 int ret_char = -1; 9504 int save_allow_keys = allow_keys; 9505 int save_paste = p_paste; 9506 int save_ai = curbuf->b_p_ai; 9507 9508 /* If the end code is too long we can't detect it, read everything. */ 9509 if (STRLEN(end) >= NUMBUFLEN) 9510 end = NULL; 9511 ++no_mapping; 9512 allow_keys = 0; 9513 p_paste = TRUE; 9514 curbuf->b_p_ai = FALSE; 9515 9516 for (;;) 9517 { 9518 /* When the end is not defined read everything. */ 9519 if (end == NULL && vpeekc() == NUL) 9520 break; 9521 c = plain_vgetc(); 9522 #ifdef FEAT_MBYTE 9523 if (has_mbyte) 9524 idx += (*mb_char2bytes)(c, buf + idx); 9525 else 9526 #endif 9527 buf[idx++] = c; 9528 buf[idx] = NUL; 9529 if (end != NULL && STRNCMP(buf, end, idx) == 0) 9530 { 9531 if (end[idx] == NUL) 9532 break; /* Found the end of paste code. */ 9533 continue; 9534 } 9535 if (!drop) 9536 { 9537 switch (mode) 9538 { 9539 case PASTE_CMDLINE: 9540 put_on_cmdline(buf, idx, TRUE); 9541 break; 9542 9543 case PASTE_EX: 9544 if (gap != NULL && ga_grow(gap, idx) == OK) 9545 { 9546 mch_memmove((char *)gap->ga_data + gap->ga_len, 9547 buf, (size_t)idx); 9548 gap->ga_len += idx; 9549 } 9550 break; 9551 9552 case PASTE_INSERT: 9553 if (stop_arrow() == OK) 9554 { 9555 c = buf[0]; 9556 if (idx == 1 && (c == CAR || c == K_KENTER || c == NL)) 9557 ins_eol(c); 9558 else 9559 { 9560 ins_char_bytes(buf, idx); 9561 AppendToRedobuffLit(buf, idx); 9562 } 9563 } 9564 break; 9565 9566 case PASTE_ONE_CHAR: 9567 if (ret_char == -1) 9568 { 9569 #ifdef FEAT_MBYTE 9570 if (has_mbyte) 9571 ret_char = (*mb_ptr2char)(buf); 9572 else 9573 #endif 9574 ret_char = buf[0]; 9575 } 9576 break; 9577 } 9578 } 9579 idx = 0; 9580 } 9581 9582 --no_mapping; 9583 allow_keys = save_allow_keys; 9584 p_paste = save_paste; 9585 curbuf->b_p_ai = save_ai; 9586 9587 return ret_char; 9588 } 9589 9590 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) 9591 static void 9592 ins_tabline(int c) 9593 { 9594 /* We will be leaving the current window, unless closing another tab. */ 9595 if (c != K_TABMENU || current_tabmenu != TABLINE_MENU_CLOSE 9596 || (current_tab != 0 && current_tab != tabpage_index(curtab))) 9597 { 9598 undisplay_dollar(); 9599 start_arrow(&curwin->w_cursor); 9600 # ifdef FEAT_CINDENT 9601 can_cindent = TRUE; 9602 # endif 9603 } 9604 9605 if (c == K_TABLINE) 9606 goto_tabpage(current_tab); 9607 else 9608 { 9609 handle_tabmenu(); 9610 redraw_statuslines(); /* will redraw the tabline when needed */ 9611 } 9612 } 9613 #endif 9614 9615 #if defined(FEAT_GUI) || defined(PROTO) 9616 void 9617 ins_scroll(void) 9618 { 9619 pos_T tpos; 9620 9621 undisplay_dollar(); 9622 tpos = curwin->w_cursor; 9623 if (gui_do_scroll()) 9624 { 9625 start_arrow(&tpos); 9626 # ifdef FEAT_CINDENT 9627 can_cindent = TRUE; 9628 # endif 9629 } 9630 } 9631 9632 void 9633 ins_horscroll(void) 9634 { 9635 pos_T tpos; 9636 9637 undisplay_dollar(); 9638 tpos = curwin->w_cursor; 9639 if (gui_do_horiz_scroll(scrollbar_value, FALSE)) 9640 { 9641 start_arrow(&tpos); 9642 # ifdef FEAT_CINDENT 9643 can_cindent = TRUE; 9644 # endif 9645 } 9646 } 9647 #endif 9648 9649 static void 9650 ins_left( 9651 int end_change) /* end undoable change */ 9652 { 9653 pos_T tpos; 9654 9655 #ifdef FEAT_FOLDING 9656 if ((fdo_flags & FDO_HOR) && KeyTyped) 9657 foldOpenCursor(); 9658 #endif 9659 undisplay_dollar(); 9660 tpos = curwin->w_cursor; 9661 if (oneleft() == OK) 9662 { 9663 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 9664 /* Only call start_arrow() when not busy with preediting, it will 9665 * break undo. K_LEFT is inserted in im_correct_cursor(). */ 9666 if (p_imst == IM_OVER_THE_SPOT || !im_is_preediting()) 9667 #endif 9668 { 9669 start_arrow_with_change(&tpos, end_change); 9670 if (!end_change) 9671 AppendCharToRedobuff(K_LEFT); 9672 } 9673 #ifdef FEAT_RIGHTLEFT 9674 /* If exit reversed string, position is fixed */ 9675 if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) 9676 revins_legal++; 9677 revins_chars++; 9678 #endif 9679 } 9680 9681 /* 9682 * if 'whichwrap' set for cursor in insert mode may go to 9683 * previous line 9684 */ 9685 else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) 9686 { 9687 /* always break undo when moving upwards/downwards, else undo may break */ 9688 start_arrow(&tpos); 9689 --(curwin->w_cursor.lnum); 9690 coladvance((colnr_T)MAXCOL); 9691 curwin->w_set_curswant = TRUE; /* so we stay at the end */ 9692 } 9693 else 9694 vim_beep(BO_CRSR); 9695 dont_sync_undo = FALSE; 9696 } 9697 9698 static void 9699 ins_home(int c) 9700 { 9701 pos_T tpos; 9702 9703 #ifdef FEAT_FOLDING 9704 if ((fdo_flags & FDO_HOR) && KeyTyped) 9705 foldOpenCursor(); 9706 #endif 9707 undisplay_dollar(); 9708 tpos = curwin->w_cursor; 9709 if (c == K_C_HOME) 9710 curwin->w_cursor.lnum = 1; 9711 curwin->w_cursor.col = 0; 9712 #ifdef FEAT_VIRTUALEDIT 9713 curwin->w_cursor.coladd = 0; 9714 #endif 9715 curwin->w_curswant = 0; 9716 start_arrow(&tpos); 9717 } 9718 9719 static void 9720 ins_end(int c) 9721 { 9722 pos_T tpos; 9723 9724 #ifdef FEAT_FOLDING 9725 if ((fdo_flags & FDO_HOR) && KeyTyped) 9726 foldOpenCursor(); 9727 #endif 9728 undisplay_dollar(); 9729 tpos = curwin->w_cursor; 9730 if (c == K_C_END) 9731 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 9732 coladvance((colnr_T)MAXCOL); 9733 curwin->w_curswant = MAXCOL; 9734 9735 start_arrow(&tpos); 9736 } 9737 9738 static void 9739 ins_s_left(void) 9740 { 9741 #ifdef FEAT_FOLDING 9742 if ((fdo_flags & FDO_HOR) && KeyTyped) 9743 foldOpenCursor(); 9744 #endif 9745 undisplay_dollar(); 9746 if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0) 9747 { 9748 start_arrow(&curwin->w_cursor); 9749 (void)bck_word(1L, FALSE, FALSE); 9750 curwin->w_set_curswant = TRUE; 9751 } 9752 else 9753 vim_beep(BO_CRSR); 9754 } 9755 9756 static void 9757 ins_right( 9758 int end_change) /* end undoable change */ 9759 { 9760 #ifdef FEAT_FOLDING 9761 if ((fdo_flags & FDO_HOR) && KeyTyped) 9762 foldOpenCursor(); 9763 #endif 9764 undisplay_dollar(); 9765 if (gchar_cursor() != NUL 9766 #ifdef FEAT_VIRTUALEDIT 9767 || virtual_active() 9768 #endif 9769 ) 9770 { 9771 start_arrow_with_change(&curwin->w_cursor, end_change); 9772 if (!end_change) 9773 AppendCharToRedobuff(K_RIGHT); 9774 curwin->w_set_curswant = TRUE; 9775 #ifdef FEAT_VIRTUALEDIT 9776 if (virtual_active()) 9777 oneright(); 9778 else 9779 #endif 9780 { 9781 #ifdef FEAT_MBYTE 9782 if (has_mbyte) 9783 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor()); 9784 else 9785 #endif 9786 ++curwin->w_cursor.col; 9787 } 9788 9789 #ifdef FEAT_RIGHTLEFT 9790 revins_legal++; 9791 if (revins_chars) 9792 revins_chars--; 9793 #endif 9794 } 9795 /* if 'whichwrap' set for cursor in insert mode, may move the 9796 * cursor to the next line */ 9797 else if (vim_strchr(p_ww, ']') != NULL 9798 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 9799 { 9800 start_arrow(&curwin->w_cursor); 9801 curwin->w_set_curswant = TRUE; 9802 ++curwin->w_cursor.lnum; 9803 curwin->w_cursor.col = 0; 9804 } 9805 else 9806 vim_beep(BO_CRSR); 9807 dont_sync_undo = FALSE; 9808 } 9809 9810 static void 9811 ins_s_right(void) 9812 { 9813 #ifdef FEAT_FOLDING 9814 if ((fdo_flags & FDO_HOR) && KeyTyped) 9815 foldOpenCursor(); 9816 #endif 9817 undisplay_dollar(); 9818 if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count 9819 || gchar_cursor() != NUL) 9820 { 9821 start_arrow(&curwin->w_cursor); 9822 (void)fwd_word(1L, FALSE, 0); 9823 curwin->w_set_curswant = TRUE; 9824 } 9825 else 9826 vim_beep(BO_CRSR); 9827 } 9828 9829 static void 9830 ins_up( 9831 int startcol) /* when TRUE move to Insstart.col */ 9832 { 9833 pos_T tpos; 9834 linenr_T old_topline = curwin->w_topline; 9835 #ifdef FEAT_DIFF 9836 int old_topfill = curwin->w_topfill; 9837 #endif 9838 9839 undisplay_dollar(); 9840 tpos = curwin->w_cursor; 9841 if (cursor_up(1L, TRUE) == OK) 9842 { 9843 if (startcol) 9844 coladvance(getvcol_nolist(&Insstart)); 9845 if (old_topline != curwin->w_topline 9846 #ifdef FEAT_DIFF 9847 || old_topfill != curwin->w_topfill 9848 #endif 9849 ) 9850 redraw_later(VALID); 9851 start_arrow(&tpos); 9852 #ifdef FEAT_CINDENT 9853 can_cindent = TRUE; 9854 #endif 9855 } 9856 else 9857 vim_beep(BO_CRSR); 9858 } 9859 9860 static void 9861 ins_pageup(void) 9862 { 9863 pos_T tpos; 9864 9865 undisplay_dollar(); 9866 9867 if (mod_mask & MOD_MASK_CTRL) 9868 { 9869 /* <C-PageUp>: tab page back */ 9870 if (first_tabpage->tp_next != NULL) 9871 { 9872 start_arrow(&curwin->w_cursor); 9873 goto_tabpage(-1); 9874 } 9875 return; 9876 } 9877 9878 tpos = curwin->w_cursor; 9879 if (onepage(BACKWARD, 1L) == OK) 9880 { 9881 start_arrow(&tpos); 9882 #ifdef FEAT_CINDENT 9883 can_cindent = TRUE; 9884 #endif 9885 } 9886 else 9887 vim_beep(BO_CRSR); 9888 } 9889 9890 static void 9891 ins_down( 9892 int startcol) /* when TRUE move to Insstart.col */ 9893 { 9894 pos_T tpos; 9895 linenr_T old_topline = curwin->w_topline; 9896 #ifdef FEAT_DIFF 9897 int old_topfill = curwin->w_topfill; 9898 #endif 9899 9900 undisplay_dollar(); 9901 tpos = curwin->w_cursor; 9902 if (cursor_down(1L, TRUE) == OK) 9903 { 9904 if (startcol) 9905 coladvance(getvcol_nolist(&Insstart)); 9906 if (old_topline != curwin->w_topline 9907 #ifdef FEAT_DIFF 9908 || old_topfill != curwin->w_topfill 9909 #endif 9910 ) 9911 redraw_later(VALID); 9912 start_arrow(&tpos); 9913 #ifdef FEAT_CINDENT 9914 can_cindent = TRUE; 9915 #endif 9916 } 9917 else 9918 vim_beep(BO_CRSR); 9919 } 9920 9921 static void 9922 ins_pagedown(void) 9923 { 9924 pos_T tpos; 9925 9926 undisplay_dollar(); 9927 9928 if (mod_mask & MOD_MASK_CTRL) 9929 { 9930 /* <C-PageDown>: tab page forward */ 9931 if (first_tabpage->tp_next != NULL) 9932 { 9933 start_arrow(&curwin->w_cursor); 9934 goto_tabpage(0); 9935 } 9936 return; 9937 } 9938 9939 tpos = curwin->w_cursor; 9940 if (onepage(FORWARD, 1L) == OK) 9941 { 9942 start_arrow(&tpos); 9943 #ifdef FEAT_CINDENT 9944 can_cindent = TRUE; 9945 #endif 9946 } 9947 else 9948 vim_beep(BO_CRSR); 9949 } 9950 9951 #ifdef FEAT_DND 9952 static void 9953 ins_drop(void) 9954 { 9955 do_put('~', BACKWARD, 1L, PUT_CURSEND); 9956 } 9957 #endif 9958 9959 /* 9960 * Handle TAB in Insert or Replace mode. 9961 * Return TRUE when the TAB needs to be inserted like a normal character. 9962 */ 9963 static int 9964 ins_tab(void) 9965 { 9966 int ind; 9967 int i; 9968 int temp; 9969 9970 if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum) 9971 Insstart_blank_vcol = get_nolist_virtcol(); 9972 if (echeck_abbr(TAB + ABBR_OFF)) 9973 return FALSE; 9974 9975 ind = inindent(0); 9976 #ifdef FEAT_CINDENT 9977 if (ind) 9978 can_cindent = FALSE; 9979 #endif 9980 9981 /* 9982 * When nothing special, insert TAB like a normal character 9983 */ 9984 if (!curbuf->b_p_et 9985 && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf)) 9986 && get_sts_value() == 0) 9987 return TRUE; 9988 9989 if (stop_arrow() == FAIL) 9990 return TRUE; 9991 9992 did_ai = FALSE; 9993 #ifdef FEAT_SMARTINDENT 9994 did_si = FALSE; 9995 can_si = FALSE; 9996 can_si_back = FALSE; 9997 #endif 9998 AppendToRedobuff((char_u *)"\t"); 9999 10000 if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */ 10001 temp = (int)get_sw_value(curbuf); 10002 else if (curbuf->b_p_sts != 0) /* use 'softtabstop' when set */ 10003 temp = (int)get_sts_value(); 10004 else /* otherwise use 'tabstop' */ 10005 temp = (int)curbuf->b_p_ts; 10006 temp -= get_nolist_virtcol() % temp; 10007 10008 /* 10009 * Insert the first space with ins_char(). It will delete one char in 10010 * replace mode. Insert the rest with ins_str(); it will not delete any 10011 * chars. For VREPLACE mode, we use ins_char() for all characters. 10012 */ 10013 ins_char(' '); 10014 while (--temp > 0) 10015 { 10016 #ifdef FEAT_VREPLACE 10017 if (State & VREPLACE_FLAG) 10018 ins_char(' '); 10019 else 10020 #endif 10021 { 10022 ins_str((char_u *)" "); 10023 if (State & REPLACE_FLAG) /* no char replaced */ 10024 replace_push(NUL); 10025 } 10026 } 10027 10028 /* 10029 * When 'expandtab' not set: Replace spaces by TABs where possible. 10030 */ 10031 if (!curbuf->b_p_et && (get_sts_value() || (p_sta && ind))) 10032 { 10033 char_u *ptr; 10034 #ifdef FEAT_VREPLACE 10035 char_u *saved_line = NULL; /* init for GCC */ 10036 pos_T pos; 10037 #endif 10038 pos_T fpos; 10039 pos_T *cursor; 10040 colnr_T want_vcol, vcol; 10041 int change_col = -1; 10042 int save_list = curwin->w_p_list; 10043 10044 /* 10045 * Get the current line. For VREPLACE mode, don't make real changes 10046 * yet, just work on a copy of the line. 10047 */ 10048 #ifdef FEAT_VREPLACE 10049 if (State & VREPLACE_FLAG) 10050 { 10051 pos = curwin->w_cursor; 10052 cursor = &pos; 10053 saved_line = vim_strsave(ml_get_curline()); 10054 if (saved_line == NULL) 10055 return FALSE; 10056 ptr = saved_line + pos.col; 10057 } 10058 else 10059 #endif 10060 { 10061 ptr = ml_get_cursor(); 10062 cursor = &curwin->w_cursor; 10063 } 10064 10065 /* When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. */ 10066 if (vim_strchr(p_cpo, CPO_LISTWM) == NULL) 10067 curwin->w_p_list = FALSE; 10068 10069 /* Find first white before the cursor */ 10070 fpos = curwin->w_cursor; 10071 while (fpos.col > 0 && VIM_ISWHITE(ptr[-1])) 10072 { 10073 --fpos.col; 10074 --ptr; 10075 } 10076 10077 /* In Replace mode, don't change characters before the insert point. */ 10078 if ((State & REPLACE_FLAG) 10079 && fpos.lnum == Insstart.lnum 10080 && fpos.col < Insstart.col) 10081 { 10082 ptr += Insstart.col - fpos.col; 10083 fpos.col = Insstart.col; 10084 } 10085 10086 /* compute virtual column numbers of first white and cursor */ 10087 getvcol(curwin, &fpos, &vcol, NULL, NULL); 10088 getvcol(curwin, cursor, &want_vcol, NULL, NULL); 10089 10090 /* Use as many TABs as possible. Beware of 'breakindent', 'showbreak' 10091 * and 'linebreak' adding extra virtual columns. */ 10092 while (VIM_ISWHITE(*ptr)) 10093 { 10094 i = lbr_chartabsize(NULL, (char_u *)"\t", vcol); 10095 if (vcol + i > want_vcol) 10096 break; 10097 if (*ptr != TAB) 10098 { 10099 *ptr = TAB; 10100 if (change_col < 0) 10101 { 10102 change_col = fpos.col; /* Column of first change */ 10103 /* May have to adjust Insstart */ 10104 if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col) 10105 Insstart.col = fpos.col; 10106 } 10107 } 10108 ++fpos.col; 10109 ++ptr; 10110 vcol += i; 10111 } 10112 10113 if (change_col >= 0) 10114 { 10115 int repl_off = 0; 10116 char_u *line = ptr; 10117 10118 /* Skip over the spaces we need. */ 10119 while (vcol < want_vcol && *ptr == ' ') 10120 { 10121 vcol += lbr_chartabsize(line, ptr, vcol); 10122 ++ptr; 10123 ++repl_off; 10124 } 10125 if (vcol > want_vcol) 10126 { 10127 /* Must have a char with 'showbreak' just before it. */ 10128 --ptr; 10129 --repl_off; 10130 } 10131 fpos.col += repl_off; 10132 10133 /* Delete following spaces. */ 10134 i = cursor->col - fpos.col; 10135 if (i > 0) 10136 { 10137 STRMOVE(ptr, ptr + i); 10138 /* correct replace stack. */ 10139 if ((State & REPLACE_FLAG) 10140 #ifdef FEAT_VREPLACE 10141 && !(State & VREPLACE_FLAG) 10142 #endif 10143 ) 10144 for (temp = i; --temp >= 0; ) 10145 replace_join(repl_off); 10146 } 10147 #ifdef FEAT_NETBEANS_INTG 10148 if (netbeans_active()) 10149 { 10150 netbeans_removed(curbuf, fpos.lnum, cursor->col, (long)(i + 1)); 10151 netbeans_inserted(curbuf, fpos.lnum, cursor->col, 10152 (char_u *)"\t", 1); 10153 } 10154 #endif 10155 cursor->col -= i; 10156 10157 #ifdef FEAT_VREPLACE 10158 /* 10159 * In VREPLACE mode, we haven't changed anything yet. Do it now by 10160 * backspacing over the changed spacing and then inserting the new 10161 * spacing. 10162 */ 10163 if (State & VREPLACE_FLAG) 10164 { 10165 /* Backspace from real cursor to change_col */ 10166 backspace_until_column(change_col); 10167 10168 /* Insert each char in saved_line from changed_col to 10169 * ptr-cursor */ 10170 ins_bytes_len(saved_line + change_col, 10171 cursor->col - change_col); 10172 } 10173 #endif 10174 } 10175 10176 #ifdef FEAT_VREPLACE 10177 if (State & VREPLACE_FLAG) 10178 vim_free(saved_line); 10179 #endif 10180 curwin->w_p_list = save_list; 10181 } 10182 10183 return FALSE; 10184 } 10185 10186 /* 10187 * Handle CR or NL in insert mode. 10188 * Return TRUE when out of memory or can't undo. 10189 */ 10190 static int 10191 ins_eol(int c) 10192 { 10193 int i; 10194 10195 if (echeck_abbr(c + ABBR_OFF)) 10196 return FALSE; 10197 if (stop_arrow() == FAIL) 10198 return TRUE; 10199 undisplay_dollar(); 10200 10201 /* 10202 * Strange Vi behaviour: In Replace mode, typing a NL will not delete the 10203 * character under the cursor. Only push a NUL on the replace stack, 10204 * nothing to put back when the NL is deleted. 10205 */ 10206 if ((State & REPLACE_FLAG) 10207 #ifdef FEAT_VREPLACE 10208 && !(State & VREPLACE_FLAG) 10209 #endif 10210 ) 10211 replace_push(NUL); 10212 10213 /* 10214 * In VREPLACE mode, a NL replaces the rest of the line, and starts 10215 * replacing the next line, so we push all of the characters left on the 10216 * line onto the replace stack. This is not done here though, it is done 10217 * in open_line(). 10218 */ 10219 10220 #ifdef FEAT_VIRTUALEDIT 10221 /* Put cursor on NUL if on the last char and coladd is 1 (happens after 10222 * CTRL-O). */ 10223 if (virtual_active() && curwin->w_cursor.coladd > 0) 10224 coladvance(getviscol()); 10225 #endif 10226 10227 #ifdef FEAT_RIGHTLEFT 10228 # ifdef FEAT_FKMAP 10229 if (p_altkeymap && p_fkmap) 10230 fkmap(NL); 10231 # endif 10232 /* NL in reverse insert will always start in the end of 10233 * current line. */ 10234 if (revins_on) 10235 curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor()); 10236 #endif 10237 10238 AppendToRedobuff(NL_STR); 10239 i = open_line(FORWARD, 10240 #ifdef FEAT_COMMENTS 10241 has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 10242 #endif 10243 0, old_indent); 10244 old_indent = 0; 10245 #ifdef FEAT_CINDENT 10246 can_cindent = TRUE; 10247 #endif 10248 #ifdef FEAT_FOLDING 10249 /* When inserting a line the cursor line must never be in a closed fold. */ 10250 foldOpenCursor(); 10251 #endif 10252 10253 return (!i); 10254 } 10255 10256 #ifdef FEAT_DIGRAPHS 10257 /* 10258 * Handle digraph in insert mode. 10259 * Returns character still to be inserted, or NUL when nothing remaining to be 10260 * done. 10261 */ 10262 static int 10263 ins_digraph(void) 10264 { 10265 int c; 10266 int cc; 10267 int did_putchar = FALSE; 10268 10269 pc_status = PC_STATUS_UNSET; 10270 if (redrawing() && !char_avail()) 10271 { 10272 /* may need to redraw when no more chars available now */ 10273 ins_redraw(FALSE); 10274 10275 edit_putchar('?', TRUE); 10276 did_putchar = TRUE; 10277 #ifdef FEAT_CMDL_INFO 10278 add_to_showcmd_c(Ctrl_K); 10279 #endif 10280 } 10281 10282 #ifdef USE_ON_FLY_SCROLL 10283 dont_scroll = TRUE; /* disallow scrolling here */ 10284 #endif 10285 10286 /* don't map the digraph chars. This also prevents the 10287 * mode message to be deleted when ESC is hit */ 10288 ++no_mapping; 10289 ++allow_keys; 10290 c = plain_vgetc(); 10291 --no_mapping; 10292 --allow_keys; 10293 if (did_putchar) 10294 /* when the line fits in 'columns' the '?' is at the start of the next 10295 * line and will not be removed by the redraw */ 10296 edit_unputchar(); 10297 10298 if (IS_SPECIAL(c) || mod_mask) /* special key */ 10299 { 10300 #ifdef FEAT_CMDL_INFO 10301 clear_showcmd(); 10302 #endif 10303 insert_special(c, TRUE, FALSE); 10304 return NUL; 10305 } 10306 if (c != ESC) 10307 { 10308 did_putchar = FALSE; 10309 if (redrawing() && !char_avail()) 10310 { 10311 /* may need to redraw when no more chars available now */ 10312 ins_redraw(FALSE); 10313 10314 if (char2cells(c) == 1) 10315 { 10316 ins_redraw(FALSE); 10317 edit_putchar(c, TRUE); 10318 did_putchar = TRUE; 10319 } 10320 #ifdef FEAT_CMDL_INFO 10321 add_to_showcmd_c(c); 10322 #endif 10323 } 10324 ++no_mapping; 10325 ++allow_keys; 10326 cc = plain_vgetc(); 10327 --no_mapping; 10328 --allow_keys; 10329 if (did_putchar) 10330 /* when the line fits in 'columns' the '?' is at the start of the 10331 * next line and will not be removed by a redraw */ 10332 edit_unputchar(); 10333 if (cc != ESC) 10334 { 10335 AppendToRedobuff((char_u *)CTRL_V_STR); 10336 c = getdigraph(c, cc, TRUE); 10337 #ifdef FEAT_CMDL_INFO 10338 clear_showcmd(); 10339 #endif 10340 return c; 10341 } 10342 } 10343 #ifdef FEAT_CMDL_INFO 10344 clear_showcmd(); 10345 #endif 10346 return NUL; 10347 } 10348 #endif 10349 10350 /* 10351 * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. 10352 * Returns the char to be inserted, or NUL if none found. 10353 */ 10354 int 10355 ins_copychar(linenr_T lnum) 10356 { 10357 int c; 10358 int temp; 10359 char_u *ptr, *prev_ptr; 10360 char_u *line; 10361 10362 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) 10363 { 10364 vim_beep(BO_COPY); 10365 return NUL; 10366 } 10367 10368 /* try to advance to the cursor column */ 10369 temp = 0; 10370 line = ptr = ml_get(lnum); 10371 prev_ptr = ptr; 10372 validate_virtcol(); 10373 while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) 10374 { 10375 prev_ptr = ptr; 10376 temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp); 10377 } 10378 if ((colnr_T)temp > curwin->w_virtcol) 10379 ptr = prev_ptr; 10380 10381 #ifdef FEAT_MBYTE 10382 c = (*mb_ptr2char)(ptr); 10383 #else 10384 c = *ptr; 10385 #endif 10386 if (c == NUL) 10387 vim_beep(BO_COPY); 10388 return c; 10389 } 10390 10391 /* 10392 * CTRL-Y or CTRL-E typed in Insert mode. 10393 */ 10394 static int 10395 ins_ctrl_ey(int tc) 10396 { 10397 int c = tc; 10398 10399 #ifdef FEAT_INS_EXPAND 10400 if (ctrl_x_mode == CTRL_X_SCROLL) 10401 { 10402 if (c == Ctrl_Y) 10403 scrolldown_clamp(); 10404 else 10405 scrollup_clamp(); 10406 redraw_later(VALID); 10407 } 10408 else 10409 #endif 10410 { 10411 c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1)); 10412 if (c != NUL) 10413 { 10414 long tw_save; 10415 10416 /* The character must be taken literally, insert like it 10417 * was typed after a CTRL-V, and pretend 'textwidth' 10418 * wasn't set. Digits, 'o' and 'x' are special after a 10419 * CTRL-V, don't use it for these. */ 10420 if (c < 256 && !isalnum(c)) 10421 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ 10422 tw_save = curbuf->b_p_tw; 10423 curbuf->b_p_tw = -1; 10424 insert_special(c, TRUE, FALSE); 10425 curbuf->b_p_tw = tw_save; 10426 #ifdef FEAT_RIGHTLEFT 10427 revins_chars++; 10428 revins_legal++; 10429 #endif 10430 c = Ctrl_V; /* pretend CTRL-V is last character */ 10431 auto_format(FALSE, TRUE); 10432 } 10433 } 10434 return c; 10435 } 10436 10437 #ifdef FEAT_SMARTINDENT 10438 /* 10439 * Try to do some very smart auto-indenting. 10440 * Used when inserting a "normal" character. 10441 */ 10442 static void 10443 ins_try_si(int c) 10444 { 10445 pos_T *pos, old_pos; 10446 char_u *ptr; 10447 int i; 10448 int temp; 10449 10450 /* 10451 * do some very smart indenting when entering '{' or '}' 10452 */ 10453 if (((did_si || can_si_back) && c == '{') || (can_si && c == '}')) 10454 { 10455 /* 10456 * for '}' set indent equal to indent of line containing matching '{' 10457 */ 10458 if (c == '}' && (pos = findmatch(NULL, '{')) != NULL) 10459 { 10460 old_pos = curwin->w_cursor; 10461 /* 10462 * If the matching '{' has a ')' immediately before it (ignoring 10463 * white-space), then line up with the start of the line 10464 * containing the matching '(' if there is one. This handles the 10465 * case where an "if (..\n..) {" statement continues over multiple 10466 * lines -- webb 10467 */ 10468 ptr = ml_get(pos->lnum); 10469 i = pos->col; 10470 if (i > 0) /* skip blanks before '{' */ 10471 while (--i > 0 && VIM_ISWHITE(ptr[i])) 10472 ; 10473 curwin->w_cursor.lnum = pos->lnum; 10474 curwin->w_cursor.col = i; 10475 if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL) 10476 curwin->w_cursor = *pos; 10477 i = get_indent(); 10478 curwin->w_cursor = old_pos; 10479 #ifdef FEAT_VREPLACE 10480 if (State & VREPLACE_FLAG) 10481 change_indent(INDENT_SET, i, FALSE, NUL, TRUE); 10482 else 10483 #endif 10484 (void)set_indent(i, SIN_CHANGED); 10485 } 10486 else if (curwin->w_cursor.col > 0) 10487 { 10488 /* 10489 * when inserting '{' after "O" reduce indent, but not 10490 * more than indent of previous line 10491 */ 10492 temp = TRUE; 10493 if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1) 10494 { 10495 old_pos = curwin->w_cursor; 10496 i = get_indent(); 10497 while (curwin->w_cursor.lnum > 1) 10498 { 10499 ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum))); 10500 10501 /* ignore empty lines and lines starting with '#'. */ 10502 if (*ptr != '#' && *ptr != NUL) 10503 break; 10504 } 10505 if (get_indent() >= i) 10506 temp = FALSE; 10507 curwin->w_cursor = old_pos; 10508 } 10509 if (temp) 10510 shift_line(TRUE, FALSE, 1, TRUE); 10511 } 10512 } 10513 10514 /* 10515 * set indent of '#' always to 0 10516 */ 10517 if (curwin->w_cursor.col > 0 && can_si && c == '#') 10518 { 10519 /* remember current indent for next line */ 10520 old_indent = get_indent(); 10521 (void)set_indent(0, SIN_CHANGED); 10522 } 10523 10524 /* Adjust ai_col, the char at this position can be deleted. */ 10525 if (ai_col > curwin->w_cursor.col) 10526 ai_col = curwin->w_cursor.col; 10527 } 10528 #endif 10529 10530 /* 10531 * Get the value that w_virtcol would have when 'list' is off. 10532 * Unless 'cpo' contains the 'L' flag. 10533 */ 10534 static colnr_T 10535 get_nolist_virtcol(void) 10536 { 10537 if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 10538 return getvcol_nolist(&curwin->w_cursor); 10539 validate_virtcol(); 10540 return curwin->w_virtcol; 10541 } 10542 10543 #ifdef FEAT_AUTOCMD 10544 /* 10545 * Handle the InsertCharPre autocommand. 10546 * "c" is the character that was typed. 10547 * Return a pointer to allocated memory with the replacement string. 10548 * Return NULL to continue inserting "c". 10549 */ 10550 static char_u * 10551 do_insert_char_pre(int c) 10552 { 10553 char_u *res; 10554 char_u buf[MB_MAXBYTES + 1]; 10555 10556 /* Return quickly when there is nothing to do. */ 10557 if (!has_insertcharpre()) 10558 return NULL; 10559 10560 #ifdef FEAT_MBYTE 10561 if (has_mbyte) 10562 buf[(*mb_char2bytes)(c, buf)] = NUL; 10563 else 10564 #endif 10565 { 10566 buf[0] = c; 10567 buf[1] = NUL; 10568 } 10569 10570 /* Lock the text to avoid weird things from happening. */ 10571 ++textlock; 10572 set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */ 10573 10574 res = NULL; 10575 if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf)) 10576 { 10577 /* Get the value of v:char. It may be empty or more than one 10578 * character. Only use it when changed, otherwise continue with the 10579 * original character to avoid breaking autoindent. */ 10580 if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) 10581 res = vim_strsave(get_vim_var_str(VV_CHAR)); 10582 } 10583 10584 set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */ 10585 --textlock; 10586 10587 return res; 10588 } 10589 #endif 10590