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 #define BACKSPACE_CHAR 1 17 #define BACKSPACE_WORD 2 18 #define BACKSPACE_WORD_NOT_SPACE 3 19 #define BACKSPACE_LINE 4 20 21 // Set when doing something for completion that may call edit() recursively, 22 // which is not allowed. 23 static int compl_busy = FALSE; 24 25 26 static void ins_ctrl_v(void); 27 static void insert_special(int, int, int); 28 static void redo_literal(int c); 29 static void start_arrow_common(pos_T *end_insert_pos, int change); 30 #ifdef FEAT_SPELL 31 static void check_spell_redraw(void); 32 #endif 33 static void stop_insert(pos_T *end_insert_pos, int esc, int nomove); 34 static int echeck_abbr(int); 35 static void mb_replace_pop_ins(int cc); 36 static void replace_flush(void); 37 static void replace_do_bs(int limit_col); 38 static int del_char_after_col(int limit_col); 39 static void ins_reg(void); 40 static void ins_ctrl_g(void); 41 static void ins_ctrl_hat(void); 42 static int ins_esc(long *count, int cmdchar, int nomove); 43 #ifdef FEAT_RIGHTLEFT 44 static void ins_ctrl_(void); 45 #endif 46 static int ins_start_select(int c); 47 static void ins_insert(int replaceState); 48 static void ins_ctrl_o(void); 49 static void ins_shift(int c, int lastc); 50 static void ins_del(void); 51 static int ins_bs(int c, int mode, int *inserted_space_p); 52 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) 53 static void ins_tabline(int c); 54 #endif 55 static void ins_left(void); 56 static void ins_home(int c); 57 static void ins_end(int c); 58 static void ins_s_left(void); 59 static void ins_right(void); 60 static void ins_s_right(void); 61 static void ins_up(int startcol); 62 static void ins_pageup(void); 63 static void ins_down(int startcol); 64 static void ins_pagedown(void); 65 #ifdef FEAT_DND 66 static void ins_drop(void); 67 #endif 68 static int ins_tab(void); 69 #ifdef FEAT_DIGRAPHS 70 static int ins_digraph(void); 71 #endif 72 static int ins_ctrl_ey(int tc); 73 #if defined(FEAT_EVAL) 74 static char_u *do_insert_char_pre(int c); 75 #endif 76 77 static colnr_T Insstart_textlen; // length of line when insert started 78 static colnr_T Insstart_blank_vcol; // vcol for first inserted blank 79 static int update_Insstart_orig = TRUE; // set Insstart_orig to Insstart 80 81 static char_u *last_insert = NULL; // the text of the previous insert, 82 // K_SPECIAL and CSI are escaped 83 static int last_insert_skip; // nr of chars in front of previous insert 84 static int new_insert_skip; // nr of chars in front of current insert 85 static int did_restart_edit; // "restart_edit" when calling edit() 86 87 #ifdef FEAT_CINDENT 88 static int can_cindent; // may do cindenting on this line 89 #endif 90 91 #ifdef FEAT_RIGHTLEFT 92 static int revins_on; // reverse insert mode on 93 static int revins_chars; // how much to skip after edit 94 static int revins_legal; // was the last char 'legal'? 95 static int revins_scol; // start column of revins session 96 #endif 97 98 static int ins_need_undo; // call u_save() before inserting a 99 // char. Set when edit() is called. 100 // after that arrow_used is used. 101 102 static int dont_sync_undo = FALSE; // CTRL-G U prevents syncing undo for 103 // the next left/right cursor key 104 105 /* 106 * edit(): Start inserting text. 107 * 108 * "cmdchar" can be: 109 * 'i' normal insert command 110 * 'a' normal append command 111 * K_PS bracketed paste 112 * 'R' replace command 113 * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo, 114 * but still only one <CR> is inserted. The <Esc> is not used for redo. 115 * 'g' "gI" command. 116 * 'V' "gR" command for Virtual Replace mode. 117 * 'v' "gr" command for single character Virtual Replace mode. 118 * 119 * This function is not called recursively. For CTRL-O commands, it returns 120 * and lets the caller handle the Normal-mode command. 121 * 122 * Return TRUE if a CTRL-O command caused the return (insert mode pending). 123 */ 124 int 125 edit( 126 int cmdchar, 127 int startln, // if set, insert at start of line 128 long count) 129 { 130 int c = 0; 131 char_u *ptr; 132 int lastc = 0; 133 int mincol; 134 static linenr_T o_lnum = 0; 135 int i; 136 int did_backspace = TRUE; // previous char was backspace 137 #ifdef FEAT_CINDENT 138 int line_is_white = FALSE; // line is empty before insert 139 #endif 140 linenr_T old_topline = 0; // topline before insertion 141 #ifdef FEAT_DIFF 142 int old_topfill = -1; 143 #endif 144 int inserted_space = FALSE; // just inserted a space 145 int replaceState = REPLACE; 146 int nomove = FALSE; // don't move cursor on return 147 #ifdef FEAT_JOB_CHANNEL 148 int cmdchar_todo = cmdchar; 149 #endif 150 #ifdef FEAT_CONCEAL 151 int cursor_line_was_concealed; 152 #endif 153 154 // Remember whether editing was restarted after CTRL-O. 155 did_restart_edit = restart_edit; 156 157 // sleep before redrawing, needed for "CTRL-O :" that results in an 158 // error message 159 check_for_delay(TRUE); 160 161 // set Insstart_orig to Insstart 162 update_Insstart_orig = TRUE; 163 164 #ifdef HAVE_SANDBOX 165 // Don't allow inserting in the sandbox. 166 if (sandbox != 0) 167 { 168 emsg(_(e_not_allowed_in_sandbox)); 169 return FALSE; 170 } 171 #endif 172 // Don't allow changes in the buffer while editing the cmdline. The 173 // caller of getcmdline() may get confused. 174 // Don't allow recursive insert mode when busy with completion. 175 if (textwinlock != 0 || textlock != 0 176 || ins_compl_active() || compl_busy || pum_visible()) 177 { 178 emsg(_(e_textwinlock)); 179 return FALSE; 180 } 181 ins_compl_clear(); // clear stuff for CTRL-X mode 182 183 /* 184 * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx". 185 */ 186 if (cmdchar != 'r' && cmdchar != 'v') 187 { 188 pos_T save_cursor = curwin->w_cursor; 189 190 #ifdef FEAT_EVAL 191 if (cmdchar == 'R') 192 ptr = (char_u *)"r"; 193 else if (cmdchar == 'V') 194 ptr = (char_u *)"v"; 195 else 196 ptr = (char_u *)"i"; 197 set_vim_var_string(VV_INSERTMODE, ptr, 1); 198 set_vim_var_string(VV_CHAR, NULL, -1); // clear v:char 199 #endif 200 ins_apply_autocmds(EVENT_INSERTENTER); 201 202 // Check for changed highlighting, e.g. for ModeMsg. 203 if (need_highlight_changed) 204 highlight_changed(); 205 206 // Make sure the cursor didn't move. Do call check_cursor_col() in 207 // case the text was modified. Since Insert mode was not started yet 208 // a call to check_cursor_col() may move the cursor, especially with 209 // the "A" command, thus set State to avoid that. Also check that the 210 // line number is still valid (lines may have been deleted). 211 // Do not restore if v:char was set to a non-empty string. 212 if (!EQUAL_POS(curwin->w_cursor, save_cursor) 213 #ifdef FEAT_EVAL 214 && *get_vim_var_str(VV_CHAR) == NUL 215 #endif 216 && save_cursor.lnum <= curbuf->b_ml.ml_line_count) 217 { 218 int save_state = State; 219 220 curwin->w_cursor = save_cursor; 221 State = INSERT; 222 check_cursor_col(); 223 State = save_state; 224 } 225 } 226 227 #ifdef FEAT_CONCEAL 228 // Check if the cursor line was concealed before changing State. 229 cursor_line_was_concealed = curwin->w_p_cole > 0 230 && conceal_cursor_line(curwin); 231 #endif 232 233 /* 234 * When doing a paste with the middle mouse button, Insstart is set to 235 * where the paste started. 236 */ 237 if (where_paste_started.lnum != 0) 238 Insstart = where_paste_started; 239 else 240 { 241 Insstart = curwin->w_cursor; 242 if (startln) 243 Insstart.col = 0; 244 } 245 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); 246 Insstart_blank_vcol = MAXCOL; 247 if (!did_ai) 248 ai_col = 0; 249 250 if (cmdchar != NUL && restart_edit == 0) 251 { 252 ResetRedobuff(); 253 AppendNumberToRedobuff(count); 254 if (cmdchar == 'V' || cmdchar == 'v') 255 { 256 // "gR" or "gr" command 257 AppendCharToRedobuff('g'); 258 AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R'); 259 } 260 else 261 { 262 if (cmdchar == K_PS) 263 AppendCharToRedobuff('a'); 264 else 265 AppendCharToRedobuff(cmdchar); 266 if (cmdchar == 'g') // "gI" command 267 AppendCharToRedobuff('I'); 268 else if (cmdchar == 'r') // "r<CR>" command 269 count = 1; // insert only one <CR> 270 } 271 } 272 273 if (cmdchar == 'R') 274 { 275 State = REPLACE; 276 } 277 else if (cmdchar == 'V' || cmdchar == 'v') 278 { 279 State = VREPLACE; 280 replaceState = VREPLACE; 281 orig_line_count = curbuf->b_ml.ml_line_count; 282 vr_lines_changed = 1; 283 } 284 else 285 State = INSERT; 286 287 trigger_modechanged(); 288 stop_insert_mode = FALSE; 289 290 #ifdef FEAT_CONCEAL 291 // Check if the cursor line needs redrawing after changing State. If 292 // 'concealcursor' is "n" it needs to be redrawn without concealing. 293 conceal_check_cursor_line(cursor_line_was_concealed); 294 #endif 295 296 /* 297 * Need to recompute the cursor position, it might move when the cursor is 298 * on a TAB or special character. 299 */ 300 curs_columns(TRUE); 301 302 /* 303 * Enable langmap or IME, indicated by 'iminsert'. 304 * Note that IME may enabled/disabled without us noticing here, thus the 305 * 'iminsert' value may not reflect what is actually used. It is updated 306 * when hitting <Esc>. 307 */ 308 if (curbuf->b_p_iminsert == B_IMODE_LMAP) 309 State |= LANGMAP; 310 #ifdef HAVE_INPUT_METHOD 311 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); 312 #endif 313 314 setmouse(); 315 #ifdef FEAT_CMDL_INFO 316 clear_showcmd(); 317 #endif 318 #ifdef FEAT_RIGHTLEFT 319 // there is no reverse replace mode 320 revins_on = (State == INSERT && p_ri); 321 if (revins_on) 322 undisplay_dollar(); 323 revins_chars = 0; 324 revins_legal = 0; 325 revins_scol = -1; 326 #endif 327 if (!p_ek) 328 { 329 #ifdef FEAT_JOB_CHANNEL 330 ch_log_output = TRUE; 331 #endif 332 // Disable bracketed paste mode, we won't recognize the escape 333 // sequences. 334 out_str(T_BD); 335 336 // Disable modifyOtherKeys, keys with modifiers would cause exiting 337 // Insert mode. 338 out_str(T_CTE); 339 } 340 341 /* 342 * Handle restarting Insert mode. 343 * Don't do this for "CTRL-O ." (repeat an insert): In that case we get 344 * here with something in the stuff buffer. 345 */ 346 if (restart_edit != 0 && stuff_empty()) 347 { 348 /* 349 * After a paste we consider text typed to be part of the insert for 350 * the pasted text. You can backspace over the pasted text too. 351 */ 352 if (where_paste_started.lnum) 353 arrow_used = FALSE; 354 else 355 arrow_used = TRUE; 356 restart_edit = 0; 357 358 /* 359 * If the cursor was after the end-of-line before the CTRL-O and it is 360 * now at the end-of-line, put it after the end-of-line (this is not 361 * correct in very rare cases). 362 * Also do this if curswant is greater than the current virtual 363 * column. Eg after "^O$" or "^O80|". 364 */ 365 validate_virtcol(); 366 update_curswant(); 367 if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum) 368 || curwin->w_curswant > curwin->w_virtcol) 369 && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL) 370 { 371 if (ptr[1] == NUL) 372 ++curwin->w_cursor.col; 373 else if (has_mbyte) 374 { 375 i = (*mb_ptr2len)(ptr); 376 if (ptr[i] == NUL) 377 curwin->w_cursor.col += i; 378 } 379 } 380 ins_at_eol = FALSE; 381 } 382 else 383 arrow_used = FALSE; 384 385 // we are in insert mode now, don't need to start it anymore 386 need_start_insertmode = FALSE; 387 388 // Need to save the line for undo before inserting the first char. 389 ins_need_undo = TRUE; 390 391 where_paste_started.lnum = 0; 392 #ifdef FEAT_CINDENT 393 can_cindent = TRUE; 394 #endif 395 #ifdef FEAT_FOLDING 396 // The cursor line is not in a closed fold, unless 'insertmode' is set or 397 // restarting. 398 if (!p_im && did_restart_edit == 0) 399 foldOpenCursor(); 400 #endif 401 402 /* 403 * If 'showmode' is set, show the current (insert/replace/..) mode. 404 * A warning message for changing a readonly file is given here, before 405 * actually changing anything. It's put after the mode, if any. 406 */ 407 i = 0; 408 if (p_smd && msg_silent == 0) 409 i = showmode(); 410 411 if (!p_im && did_restart_edit == 0) 412 change_warning(i == 0 ? 0 : i + 1); 413 414 #ifdef CURSOR_SHAPE 415 ui_cursor_shape(); // may show different cursor shape 416 #endif 417 #ifdef FEAT_DIGRAPHS 418 do_digraph(-1); // clear digraphs 419 #endif 420 421 /* 422 * Get the current length of the redo buffer, those characters have to be 423 * skipped if we want to get to the inserted characters. 424 */ 425 ptr = get_inserted(); 426 if (ptr == NULL) 427 new_insert_skip = 0; 428 else 429 { 430 new_insert_skip = (int)STRLEN(ptr); 431 vim_free(ptr); 432 } 433 434 old_indent = 0; 435 436 /* 437 * Main loop in Insert mode: repeat until Insert mode is left. 438 */ 439 for (;;) 440 { 441 #ifdef FEAT_RIGHTLEFT 442 if (!revins_legal) 443 revins_scol = -1; // reset on illegal motions 444 else 445 revins_legal = 0; 446 #endif 447 if (arrow_used) // don't repeat insert when arrow key used 448 count = 0; 449 450 if (update_Insstart_orig) 451 Insstart_orig = Insstart; 452 453 if (stop_insert_mode && !pum_visible()) 454 { 455 // ":stopinsert" used or 'insertmode' reset 456 count = 0; 457 goto doESCkey; 458 } 459 460 // set curwin->w_curswant for next K_DOWN or K_UP 461 if (!arrow_used) 462 curwin->w_set_curswant = TRUE; 463 464 // If there is no typeahead may check for timestamps (e.g., for when a 465 // menu invoked a shell command). 466 if (stuff_empty()) 467 { 468 did_check_timestamps = FALSE; 469 if (need_check_timestamps) 470 check_timestamps(FALSE); 471 } 472 473 /* 474 * When emsg() was called msg_scroll will have been set. 475 */ 476 msg_scroll = FALSE; 477 478 #ifdef FEAT_GUI 479 // When 'mousefocus' is set a mouse movement may have taken us to 480 // another window. "need_mouse_correct" may then be set because of an 481 // autocommand. 482 if (need_mouse_correct) 483 gui_mouse_correct(); 484 #endif 485 486 #ifdef FEAT_FOLDING 487 // Open fold at the cursor line, according to 'foldopen'. 488 if (fdo_flags & FDO_INSERT) 489 foldOpenCursor(); 490 // Close folds where the cursor isn't, according to 'foldclose' 491 if (!char_avail()) 492 foldCheckClose(); 493 #endif 494 495 #ifdef FEAT_JOB_CHANNEL 496 if (bt_prompt(curbuf)) 497 { 498 init_prompt(cmdchar_todo); 499 cmdchar_todo = NUL; 500 } 501 #endif 502 503 /* 504 * If we inserted a character at the last position of the last line in 505 * the window, scroll the window one line up. This avoids an extra 506 * redraw. 507 * This is detected when the cursor column is smaller after inserting 508 * something. 509 * Don't do this when the topline changed already, it has 510 * already been adjusted (by insertchar() calling open_line())). 511 */ 512 if (curbuf->b_mod_set 513 && curwin->w_p_wrap 514 && !did_backspace 515 && curwin->w_topline == old_topline 516 #ifdef FEAT_DIFF 517 && curwin->w_topfill == old_topfill 518 #endif 519 ) 520 { 521 mincol = curwin->w_wcol; 522 validate_cursor_col(); 523 524 if ( 525 #ifdef FEAT_VARTABS 526 (int)curwin->w_wcol < mincol - tabstop_at( 527 get_nolist_virtcol(), curbuf->b_p_ts, 528 curbuf->b_p_vts_array) 529 #else 530 (int)curwin->w_wcol < mincol - curbuf->b_p_ts 531 #endif 532 && curwin->w_wrow == W_WINROW(curwin) 533 + curwin->w_height - 1 - get_scrolloff_value() 534 && (curwin->w_cursor.lnum != curwin->w_topline 535 #ifdef FEAT_DIFF 536 || curwin->w_topfill > 0 537 #endif 538 )) 539 { 540 #ifdef FEAT_DIFF 541 if (curwin->w_topfill > 0) 542 --curwin->w_topfill; 543 else 544 #endif 545 #ifdef FEAT_FOLDING 546 if (hasFolding(curwin->w_topline, NULL, &old_topline)) 547 set_topline(curwin, old_topline + 1); 548 else 549 #endif 550 set_topline(curwin, curwin->w_topline + 1); 551 } 552 } 553 554 // May need to adjust w_topline to show the cursor. 555 update_topline(); 556 557 did_backspace = FALSE; 558 559 validate_cursor(); // may set must_redraw 560 561 /* 562 * Redraw the display when no characters are waiting. 563 * Also shows mode, ruler and positions cursor. 564 */ 565 ins_redraw(TRUE); 566 567 if (curwin->w_p_scb) 568 do_check_scrollbind(TRUE); 569 570 if (curwin->w_p_crb) 571 do_check_cursorbind(); 572 update_curswant(); 573 old_topline = curwin->w_topline; 574 #ifdef FEAT_DIFF 575 old_topfill = curwin->w_topfill; 576 #endif 577 578 #ifdef USE_ON_FLY_SCROLL 579 dont_scroll = FALSE; // allow scrolling here 580 #endif 581 582 /* 583 * Get a character for Insert mode. Ignore K_IGNORE and K_NOP. 584 */ 585 if (c != K_CURSORHOLD) 586 lastc = c; // remember the previous char for CTRL-D 587 588 // After using CTRL-G U the next cursor key will not break undo. 589 if (dont_sync_undo == MAYBE) 590 dont_sync_undo = TRUE; 591 else 592 dont_sync_undo = FALSE; 593 if (cmdchar == K_PS) 594 // Got here from normal mode when bracketed paste started. 595 c = K_PS; 596 else 597 do 598 { 599 c = safe_vgetc(); 600 601 if (stop_insert_mode) 602 { 603 // Insert mode ended, possibly from a callback. 604 if (c != K_IGNORE && c != K_NOP) 605 vungetc(c); 606 count = 0; 607 nomove = TRUE; 608 ins_compl_prep(ESC); 609 goto doESCkey; 610 } 611 } while (c == K_IGNORE || c == K_NOP); 612 613 // Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. 614 did_cursorhold = TRUE; 615 616 #ifdef FEAT_RIGHTLEFT 617 if (p_hkmap && KeyTyped) 618 c = hkmap(c); // Hebrew mode mapping 619 #endif 620 621 /* 622 * Special handling of keys while the popup menu is visible or wanted 623 * and the cursor is still in the completed word. Only when there is 624 * a match, skip this when no matches were found. 625 */ 626 if (ins_compl_active() 627 && pum_wanted() 628 && curwin->w_cursor.col >= ins_compl_col() 629 && ins_compl_has_shown_match()) 630 { 631 // BS: Delete one character from "compl_leader". 632 if ((c == K_BS || c == Ctrl_H) 633 && curwin->w_cursor.col > ins_compl_col() 634 && (c = ins_compl_bs()) == NUL) 635 continue; 636 637 // When no match was selected or it was edited. 638 if (!ins_compl_used_match()) 639 { 640 // CTRL-L: Add one character from the current match to 641 // "compl_leader". Except when at the original match and 642 // there is nothing to add, CTRL-L works like CTRL-P then. 643 if (c == Ctrl_L 644 && (!ctrl_x_mode_line_or_eval() 645 || ins_compl_long_shown_match())) 646 { 647 ins_compl_addfrommatch(); 648 continue; 649 } 650 651 // A non-white character that fits in with the current 652 // completion: Add to "compl_leader". 653 if (ins_compl_accept_char(c)) 654 { 655 #if defined(FEAT_EVAL) 656 // Trigger InsertCharPre. 657 char_u *str = do_insert_char_pre(c); 658 char_u *p; 659 660 if (str != NULL) 661 { 662 for (p = str; *p != NUL; MB_PTR_ADV(p)) 663 ins_compl_addleader(PTR2CHAR(p)); 664 vim_free(str); 665 } 666 else 667 #endif 668 ins_compl_addleader(c); 669 continue; 670 } 671 672 // Pressing CTRL-Y selects the current match. When 673 // ins_compl_enter_selects() is set the Enter key does the 674 // same. 675 if ((c == Ctrl_Y || (ins_compl_enter_selects() 676 && (c == CAR || c == K_KENTER || c == NL))) 677 && stop_arrow() == OK) 678 { 679 ins_compl_delete(); 680 ins_compl_insert(FALSE); 681 } 682 } 683 } 684 685 // Prepare for or stop CTRL-X mode. This doesn't do completion, but 686 // it does fix up the text when finishing completion. 687 ins_compl_init_get_longest(); 688 if (ins_compl_prep(c)) 689 continue; 690 691 // CTRL-\ CTRL-N goes to Normal mode, 692 // CTRL-\ CTRL-G goes to mode selected with 'insertmode', 693 // CTRL-\ CTRL-O is like CTRL-O but without moving the cursor. 694 if (c == Ctrl_BSL) 695 { 696 // may need to redraw when no more chars available now 697 ins_redraw(FALSE); 698 ++no_mapping; 699 ++allow_keys; 700 c = plain_vgetc(); 701 --no_mapping; 702 --allow_keys; 703 if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O) 704 { 705 // it's something else 706 vungetc(c); 707 c = Ctrl_BSL; 708 } 709 else if (c == Ctrl_G && p_im) 710 continue; 711 else 712 { 713 if (c == Ctrl_O) 714 { 715 ins_ctrl_o(); 716 ins_at_eol = FALSE; // cursor keeps its column 717 nomove = TRUE; 718 } 719 count = 0; 720 goto doESCkey; 721 } 722 } 723 724 #ifdef FEAT_DIGRAPHS 725 c = do_digraph(c); 726 #endif 727 728 if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode_cmdline()) 729 goto docomplete; 730 if (c == Ctrl_V || c == Ctrl_Q) 731 { 732 ins_ctrl_v(); 733 c = Ctrl_V; // pretend CTRL-V is last typed character 734 continue; 735 } 736 737 #ifdef FEAT_CINDENT 738 if (cindent_on() && ctrl_x_mode_none()) 739 { 740 // A key name preceded by a bang means this key is not to be 741 // inserted. Skip ahead to the re-indenting below. 742 // A key name preceded by a star means that indenting has to be 743 // done before inserting the key. 744 line_is_white = inindent(0); 745 if (in_cinkeys(c, '!', line_is_white)) 746 goto force_cindent; 747 if (can_cindent && in_cinkeys(c, '*', line_is_white) 748 && stop_arrow() == OK) 749 do_c_expr_indent(); 750 } 751 #endif 752 753 #ifdef FEAT_RIGHTLEFT 754 if (curwin->w_p_rl) 755 switch (c) 756 { 757 case K_LEFT: c = K_RIGHT; break; 758 case K_S_LEFT: c = K_S_RIGHT; break; 759 case K_C_LEFT: c = K_C_RIGHT; break; 760 case K_RIGHT: c = K_LEFT; break; 761 case K_S_RIGHT: c = K_S_LEFT; break; 762 case K_C_RIGHT: c = K_C_LEFT; break; 763 } 764 #endif 765 766 /* 767 * If 'keymodel' contains "startsel", may start selection. If it 768 * does, a CTRL-O and c will be stuffed, we need to get these 769 * characters. 770 */ 771 if (ins_start_select(c)) 772 continue; 773 774 /* 775 * The big switch to handle a character in insert mode. 776 */ 777 switch (c) 778 { 779 case ESC: // End input mode 780 if (echeck_abbr(ESC + ABBR_OFF)) 781 break; 782 // FALLTHROUGH 783 784 case Ctrl_C: // End input mode 785 #ifdef FEAT_CMDWIN 786 if (c == Ctrl_C && cmdwin_type != 0) 787 { 788 // Close the cmdline window. 789 cmdwin_result = K_IGNORE; 790 got_int = FALSE; // don't stop executing autocommands et al. 791 nomove = TRUE; 792 goto doESCkey; 793 } 794 #endif 795 #ifdef FEAT_JOB_CHANNEL 796 if (c == Ctrl_C && bt_prompt(curbuf)) 797 { 798 if (invoke_prompt_interrupt()) 799 { 800 if (!bt_prompt(curbuf)) 801 // buffer changed to a non-prompt buffer, get out of 802 // Insert mode 803 goto doESCkey; 804 break; 805 } 806 } 807 #endif 808 809 #ifdef UNIX 810 do_intr: 811 #endif 812 // when 'insertmode' set, and not halfway a mapping, don't leave 813 // Insert mode 814 if (goto_im()) 815 { 816 if (got_int) 817 { 818 (void)vgetc(); // flush all buffers 819 got_int = FALSE; 820 } 821 else 822 vim_beep(BO_IM); 823 break; 824 } 825 doESCkey: 826 /* 827 * This is the ONLY return from edit()! 828 */ 829 // Always update o_lnum, so that a "CTRL-O ." that adds a line 830 // still puts the cursor back after the inserted text. 831 if (ins_at_eol && gchar_cursor() == NUL) 832 o_lnum = curwin->w_cursor.lnum; 833 834 if (ins_esc(&count, cmdchar, nomove)) 835 { 836 // When CTRL-C was typed got_int will be set, with the result 837 // that the autocommands won't be executed. When mapped got_int 838 // is not set, but let's keep the behavior the same. 839 if (cmdchar != 'r' && cmdchar != 'v' && c != Ctrl_C) 840 ins_apply_autocmds(EVENT_INSERTLEAVE); 841 did_cursorhold = FALSE; 842 return (c == Ctrl_O); 843 } 844 continue; 845 846 case Ctrl_Z: // suspend when 'insertmode' set 847 if (!p_im) 848 goto normalchar; // insert CTRL-Z as normal char 849 do_cmdline_cmd((char_u *)"stop"); 850 #ifdef CURSOR_SHAPE 851 ui_cursor_shape(); // may need to update cursor shape 852 #endif 853 continue; 854 855 case Ctrl_O: // execute one command 856 #ifdef FEAT_COMPL_FUNC 857 if (ctrl_x_mode_omni()) 858 goto docomplete; 859 #endif 860 if (echeck_abbr(Ctrl_O + ABBR_OFF)) 861 break; 862 ins_ctrl_o(); 863 864 // don't move the cursor left when 'virtualedit' has "onemore". 865 if (get_ve_flags() & VE_ONEMORE) 866 { 867 ins_at_eol = FALSE; 868 nomove = TRUE; 869 } 870 count = 0; 871 goto doESCkey; 872 873 case K_INS: // toggle insert/replace mode 874 case K_KINS: 875 ins_insert(replaceState); 876 break; 877 878 case K_SELECT: // end of Select mode mapping - ignore 879 break; 880 881 case K_HELP: // Help key works like <ESC> <Help> 882 case K_F1: 883 case K_XF1: 884 stuffcharReadbuff(K_HELP); 885 if (p_im) 886 need_start_insertmode = TRUE; 887 goto doESCkey; 888 889 #ifdef FEAT_NETBEANS_INTG 890 case K_F21: // NetBeans command 891 ++no_mapping; // don't map the next key hits 892 i = plain_vgetc(); 893 --no_mapping; 894 netbeans_keycommand(i); 895 break; 896 #endif 897 898 case K_ZERO: // Insert the previously inserted text. 899 case NUL: 900 case Ctrl_A: 901 // For ^@ the trailing ESC will end the insert, unless there is an 902 // error. 903 if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL 904 && c != Ctrl_A && !p_im) 905 goto doESCkey; // quit insert mode 906 inserted_space = FALSE; 907 break; 908 909 case Ctrl_R: // insert the contents of a register 910 ins_reg(); 911 auto_format(FALSE, TRUE); 912 inserted_space = FALSE; 913 break; 914 915 case Ctrl_G: // commands starting with CTRL-G 916 ins_ctrl_g(); 917 break; 918 919 case Ctrl_HAT: // switch input mode and/or langmap 920 ins_ctrl_hat(); 921 break; 922 923 #ifdef FEAT_RIGHTLEFT 924 case Ctrl__: // switch between languages 925 if (!p_ari) 926 goto normalchar; 927 ins_ctrl_(); 928 break; 929 #endif 930 931 case Ctrl_D: // Make indent one shiftwidth smaller. 932 #if defined(FEAT_FIND_ID) 933 if (ctrl_x_mode_path_defines()) 934 goto docomplete; 935 #endif 936 // FALLTHROUGH 937 938 case Ctrl_T: // Make indent one shiftwidth greater. 939 if (c == Ctrl_T && ctrl_x_mode_thesaurus()) 940 { 941 if (has_compl_option(FALSE)) 942 goto docomplete; 943 break; 944 } 945 946 ins_shift(c, lastc); 947 auto_format(FALSE, TRUE); 948 inserted_space = FALSE; 949 break; 950 951 case K_DEL: // delete character under the cursor 952 case K_KDEL: 953 ins_del(); 954 auto_format(FALSE, TRUE); 955 break; 956 957 case K_BS: // delete character before the cursor 958 case Ctrl_H: 959 did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); 960 auto_format(FALSE, TRUE); 961 break; 962 963 case Ctrl_W: // delete word before the cursor 964 #ifdef FEAT_JOB_CHANNEL 965 if (bt_prompt(curbuf) && (mod_mask & MOD_MASK_SHIFT) == 0) 966 { 967 // In a prompt window CTRL-W is used for window commands. 968 // Use Shift-CTRL-W to delete a word. 969 stuffcharReadbuff(Ctrl_W); 970 restart_edit = 'A'; 971 nomove = TRUE; 972 count = 0; 973 goto doESCkey; 974 } 975 #endif 976 did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); 977 auto_format(FALSE, TRUE); 978 break; 979 980 case Ctrl_U: // delete all inserted text in current line 981 # ifdef FEAT_COMPL_FUNC 982 // CTRL-X CTRL-U completes with 'completefunc'. 983 if (ctrl_x_mode_function()) 984 goto docomplete; 985 # endif 986 did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); 987 auto_format(FALSE, TRUE); 988 inserted_space = FALSE; 989 break; 990 991 case K_LEFTMOUSE: // mouse keys 992 case K_LEFTMOUSE_NM: 993 case K_LEFTDRAG: 994 case K_LEFTRELEASE: 995 case K_LEFTRELEASE_NM: 996 case K_MOUSEMOVE: 997 case K_MIDDLEMOUSE: 998 case K_MIDDLEDRAG: 999 case K_MIDDLERELEASE: 1000 case K_RIGHTMOUSE: 1001 case K_RIGHTDRAG: 1002 case K_RIGHTRELEASE: 1003 case K_X1MOUSE: 1004 case K_X1DRAG: 1005 case K_X1RELEASE: 1006 case K_X2MOUSE: 1007 case K_X2DRAG: 1008 case K_X2RELEASE: 1009 ins_mouse(c); 1010 break; 1011 1012 case K_MOUSEDOWN: // Default action for scroll wheel up: scroll up 1013 ins_mousescroll(MSCR_DOWN); 1014 break; 1015 1016 case K_MOUSEUP: // Default action for scroll wheel down: scroll down 1017 ins_mousescroll(MSCR_UP); 1018 break; 1019 1020 case K_MOUSELEFT: // Scroll wheel left 1021 ins_mousescroll(MSCR_LEFT); 1022 break; 1023 1024 case K_MOUSERIGHT: // Scroll wheel right 1025 ins_mousescroll(MSCR_RIGHT); 1026 break; 1027 1028 case K_PS: 1029 bracketed_paste(PASTE_INSERT, FALSE, NULL); 1030 if (cmdchar == K_PS) 1031 // invoked from normal mode, bail out 1032 goto doESCkey; 1033 break; 1034 case K_PE: 1035 // Got K_PE without K_PS, ignore. 1036 break; 1037 1038 #ifdef FEAT_GUI_TABLINE 1039 case K_TABLINE: 1040 case K_TABMENU: 1041 ins_tabline(c); 1042 break; 1043 #endif 1044 1045 case K_IGNORE: // Something mapped to nothing 1046 break; 1047 1048 case K_COMMAND: // <Cmd>command<CR> 1049 do_cmdline(NULL, getcmdkeycmd, NULL, 0); 1050 #ifdef FEAT_TERMINAL 1051 if (term_use_loop()) 1052 // Started a terminal that gets the input, exit Insert mode. 1053 goto doESCkey; 1054 #endif 1055 break; 1056 1057 case K_CURSORHOLD: // Didn't type something for a while. 1058 ins_apply_autocmds(EVENT_CURSORHOLDI); 1059 did_cursorhold = TRUE; 1060 break; 1061 1062 #ifdef FEAT_GUI_MSWIN 1063 // On MS-Windows ignore <M-F4>, we get it when closing the window 1064 // was cancelled. 1065 case K_F4: 1066 if (mod_mask != MOD_MASK_ALT) 1067 goto normalchar; 1068 break; 1069 #endif 1070 1071 #ifdef FEAT_GUI 1072 case K_VER_SCROLLBAR: 1073 ins_scroll(); 1074 break; 1075 1076 case K_HOR_SCROLLBAR: 1077 ins_horscroll(); 1078 break; 1079 #endif 1080 1081 case K_HOME: // <Home> 1082 case K_KHOME: 1083 case K_S_HOME: 1084 case K_C_HOME: 1085 ins_home(c); 1086 break; 1087 1088 case K_END: // <End> 1089 case K_KEND: 1090 case K_S_END: 1091 case K_C_END: 1092 ins_end(c); 1093 break; 1094 1095 case K_LEFT: // <Left> 1096 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1097 ins_s_left(); 1098 else 1099 ins_left(); 1100 break; 1101 1102 case K_S_LEFT: // <S-Left> 1103 case K_C_LEFT: 1104 ins_s_left(); 1105 break; 1106 1107 case K_RIGHT: // <Right> 1108 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1109 ins_s_right(); 1110 else 1111 ins_right(); 1112 break; 1113 1114 case K_S_RIGHT: // <S-Right> 1115 case K_C_RIGHT: 1116 ins_s_right(); 1117 break; 1118 1119 case K_UP: // <Up> 1120 if (pum_visible()) 1121 goto docomplete; 1122 if (mod_mask & MOD_MASK_SHIFT) 1123 ins_pageup(); 1124 else 1125 ins_up(FALSE); 1126 break; 1127 1128 case K_S_UP: // <S-Up> 1129 case K_PAGEUP: 1130 case K_KPAGEUP: 1131 if (pum_visible()) 1132 goto docomplete; 1133 ins_pageup(); 1134 break; 1135 1136 case K_DOWN: // <Down> 1137 if (pum_visible()) 1138 goto docomplete; 1139 if (mod_mask & MOD_MASK_SHIFT) 1140 ins_pagedown(); 1141 else 1142 ins_down(FALSE); 1143 break; 1144 1145 case K_S_DOWN: // <S-Down> 1146 case K_PAGEDOWN: 1147 case K_KPAGEDOWN: 1148 if (pum_visible()) 1149 goto docomplete; 1150 ins_pagedown(); 1151 break; 1152 1153 #ifdef FEAT_DND 1154 case K_DROP: // drag-n-drop event 1155 ins_drop(); 1156 break; 1157 #endif 1158 1159 case K_S_TAB: // When not mapped, use like a normal TAB 1160 c = TAB; 1161 // FALLTHROUGH 1162 1163 case TAB: // TAB or Complete patterns along path 1164 #if defined(FEAT_FIND_ID) 1165 if (ctrl_x_mode_path_patterns()) 1166 goto docomplete; 1167 #endif 1168 inserted_space = FALSE; 1169 if (ins_tab()) 1170 goto normalchar; // insert TAB as a normal char 1171 auto_format(FALSE, TRUE); 1172 break; 1173 1174 case K_KENTER: // <Enter> 1175 c = CAR; 1176 // FALLTHROUGH 1177 case CAR: 1178 case NL: 1179 #if defined(FEAT_QUICKFIX) 1180 // In a quickfix window a <CR> jumps to the error under the 1181 // cursor. 1182 if (bt_quickfix(curbuf) && c == CAR) 1183 { 1184 if (curwin->w_llist_ref == NULL) // quickfix window 1185 do_cmdline_cmd((char_u *)".cc"); 1186 else // location list window 1187 do_cmdline_cmd((char_u *)".ll"); 1188 break; 1189 } 1190 #endif 1191 #ifdef FEAT_CMDWIN 1192 if (cmdwin_type != 0) 1193 { 1194 // Execute the command in the cmdline window. 1195 cmdwin_result = CAR; 1196 goto doESCkey; 1197 } 1198 #endif 1199 #ifdef FEAT_JOB_CHANNEL 1200 if (bt_prompt(curbuf)) 1201 { 1202 invoke_prompt_callback(); 1203 if (!bt_prompt(curbuf)) 1204 // buffer changed to a non-prompt buffer, get out of 1205 // Insert mode 1206 goto doESCkey; 1207 break; 1208 } 1209 #endif 1210 if (ins_eol(c) == FAIL && !p_im) 1211 goto doESCkey; // out of memory 1212 auto_format(FALSE, FALSE); 1213 inserted_space = FALSE; 1214 break; 1215 1216 case Ctrl_K: // digraph or keyword completion 1217 if (ctrl_x_mode_dictionary()) 1218 { 1219 if (has_compl_option(TRUE)) 1220 goto docomplete; 1221 break; 1222 } 1223 #ifdef FEAT_DIGRAPHS 1224 c = ins_digraph(); 1225 if (c == NUL) 1226 break; 1227 #endif 1228 goto normalchar; 1229 1230 case Ctrl_X: // Enter CTRL-X mode 1231 ins_ctrl_x(); 1232 break; 1233 1234 case Ctrl_RSB: // Tag name completion after ^X 1235 if (!ctrl_x_mode_tags()) 1236 goto normalchar; 1237 goto docomplete; 1238 1239 case Ctrl_F: // File name completion after ^X 1240 if (!ctrl_x_mode_files()) 1241 goto normalchar; 1242 goto docomplete; 1243 1244 case 's': // Spelling completion after ^X 1245 case Ctrl_S: 1246 if (!ctrl_x_mode_spell()) 1247 goto normalchar; 1248 goto docomplete; 1249 1250 case Ctrl_L: // Whole line completion after ^X 1251 if (!ctrl_x_mode_whole_line()) 1252 { 1253 // CTRL-L with 'insertmode' set: Leave Insert mode 1254 if (p_im) 1255 { 1256 if (echeck_abbr(Ctrl_L + ABBR_OFF)) 1257 break; 1258 goto doESCkey; 1259 } 1260 goto normalchar; 1261 } 1262 // FALLTHROUGH 1263 1264 case Ctrl_P: // Do previous/next pattern completion 1265 case Ctrl_N: 1266 // if 'complete' is empty then plain ^P is no longer special, 1267 // but it is under other ^X modes 1268 if (*curbuf->b_p_cpt == NUL 1269 && (ctrl_x_mode_normal() || ctrl_x_mode_whole_line()) 1270 && !(compl_cont_status & CONT_LOCAL)) 1271 goto normalchar; 1272 1273 docomplete: 1274 compl_busy = TRUE; 1275 #ifdef FEAT_FOLDING 1276 disable_fold_update++; // don't redraw folds here 1277 #endif 1278 if (ins_complete(c, TRUE) == FAIL) 1279 compl_cont_status = 0; 1280 #ifdef FEAT_FOLDING 1281 disable_fold_update--; 1282 #endif 1283 compl_busy = FALSE; 1284 break; 1285 1286 case Ctrl_Y: // copy from previous line or scroll down 1287 case Ctrl_E: // copy from next line or scroll up 1288 c = ins_ctrl_ey(c); 1289 break; 1290 1291 default: 1292 #ifdef UNIX 1293 if (c == intr_char) // special interrupt char 1294 goto do_intr; 1295 #endif 1296 1297 normalchar: 1298 /* 1299 * Insert a normal character. 1300 */ 1301 #if defined(FEAT_EVAL) 1302 if (!p_paste) 1303 { 1304 // Trigger InsertCharPre. 1305 char_u *str = do_insert_char_pre(c); 1306 char_u *p; 1307 1308 if (str != NULL) 1309 { 1310 if (*str != NUL && stop_arrow() != FAIL) 1311 { 1312 // Insert the new value of v:char literally. 1313 for (p = str; *p != NUL; MB_PTR_ADV(p)) 1314 { 1315 c = PTR2CHAR(p); 1316 if (c == CAR || c == K_KENTER || c == NL) 1317 ins_eol(c); 1318 else 1319 ins_char(c); 1320 } 1321 AppendToRedobuffLit(str, -1); 1322 } 1323 vim_free(str); 1324 c = NUL; 1325 } 1326 1327 // If the new value is already inserted or an empty string 1328 // then don't insert any character. 1329 if (c == NUL) 1330 break; 1331 } 1332 #endif 1333 #ifdef FEAT_SMARTINDENT 1334 // Try to perform smart-indenting. 1335 ins_try_si(c); 1336 #endif 1337 1338 if (c == ' ') 1339 { 1340 inserted_space = TRUE; 1341 #ifdef FEAT_CINDENT 1342 if (inindent(0)) 1343 can_cindent = FALSE; 1344 #endif 1345 if (Insstart_blank_vcol == MAXCOL 1346 && curwin->w_cursor.lnum == Insstart.lnum) 1347 Insstart_blank_vcol = get_nolist_virtcol(); 1348 } 1349 1350 // Insert a normal character and check for abbreviations on a 1351 // special character. Let CTRL-] expand abbreviations without 1352 // inserting it. 1353 if (vim_iswordc(c) || (!echeck_abbr( 1354 // Add ABBR_OFF for characters above 0x100, this is 1355 // what check_abbr() expects. 1356 (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : c) 1357 && c != Ctrl_RSB)) 1358 { 1359 insert_special(c, FALSE, FALSE); 1360 #ifdef FEAT_RIGHTLEFT 1361 revins_legal++; 1362 revins_chars++; 1363 #endif 1364 } 1365 1366 auto_format(FALSE, TRUE); 1367 1368 #ifdef FEAT_FOLDING 1369 // When inserting a character the cursor line must never be in a 1370 // closed fold. 1371 foldOpenCursor(); 1372 #endif 1373 break; 1374 } // end of switch (c) 1375 1376 // If typed something may trigger CursorHoldI again. 1377 if (c != K_CURSORHOLD 1378 #ifdef FEAT_COMPL_FUNC 1379 // but not in CTRL-X mode, a script can't restore the state 1380 && ctrl_x_mode_normal() 1381 #endif 1382 ) 1383 did_cursorhold = FALSE; 1384 1385 // If the cursor was moved we didn't just insert a space 1386 if (arrow_used) 1387 inserted_space = FALSE; 1388 1389 #ifdef FEAT_CINDENT 1390 if (can_cindent && cindent_on() && ctrl_x_mode_normal()) 1391 { 1392 force_cindent: 1393 /* 1394 * Indent now if a key was typed that is in 'cinkeys'. 1395 */ 1396 if (in_cinkeys(c, ' ', line_is_white)) 1397 { 1398 if (stop_arrow() == OK) 1399 // re-indent the current line 1400 do_c_expr_indent(); 1401 } 1402 } 1403 #endif // FEAT_CINDENT 1404 1405 } // for (;;) 1406 // NOTREACHED 1407 } 1408 1409 int 1410 ins_need_undo_get(void) 1411 { 1412 return ins_need_undo; 1413 } 1414 1415 /* 1416 * Redraw for Insert mode. 1417 * This is postponed until getting the next character to make '$' in the 'cpo' 1418 * option work correctly. 1419 * Only redraw when there are no characters available. This speeds up 1420 * inserting sequences of characters (e.g., for CTRL-R). 1421 */ 1422 void 1423 ins_redraw(int ready) // not busy with something 1424 { 1425 #ifdef FEAT_CONCEAL 1426 linenr_T conceal_old_cursor_line = 0; 1427 linenr_T conceal_new_cursor_line = 0; 1428 int conceal_update_lines = FALSE; 1429 #endif 1430 1431 if (char_avail()) 1432 return; 1433 1434 // Trigger CursorMoved if the cursor moved. Not when the popup menu is 1435 // visible, the command might delete it. 1436 if (ready && (has_cursormovedI() 1437 # ifdef FEAT_PROP_POPUP 1438 || popup_visible 1439 # endif 1440 # if defined(FEAT_CONCEAL) 1441 || curwin->w_p_cole > 0 1442 # endif 1443 ) 1444 && !EQUAL_POS(last_cursormoved, curwin->w_cursor) 1445 && !pum_visible()) 1446 { 1447 # ifdef FEAT_SYN_HL 1448 // Need to update the screen first, to make sure syntax 1449 // highlighting is correct after making a change (e.g., inserting 1450 // a "(". The autocommand may also require a redraw, so it's done 1451 // again below, unfortunately. 1452 if (syntax_present(curwin) && must_redraw) 1453 update_screen(0); 1454 # endif 1455 if (has_cursormovedI()) 1456 { 1457 // Make sure curswant is correct, an autocommand may call 1458 // getcurpos(). 1459 update_curswant(); 1460 ins_apply_autocmds(EVENT_CURSORMOVEDI); 1461 } 1462 #ifdef FEAT_PROP_POPUP 1463 if (popup_visible) 1464 popup_check_cursor_pos(); 1465 #endif 1466 # ifdef FEAT_CONCEAL 1467 if (curwin->w_p_cole > 0) 1468 { 1469 conceal_old_cursor_line = last_cursormoved.lnum; 1470 conceal_new_cursor_line = curwin->w_cursor.lnum; 1471 conceal_update_lines = TRUE; 1472 } 1473 # endif 1474 last_cursormoved = curwin->w_cursor; 1475 } 1476 1477 // Trigger TextChangedI if b_changedtick differs. 1478 if (ready && has_textchangedI() 1479 && curbuf->b_last_changedtick != CHANGEDTICK(curbuf) 1480 && !pum_visible()) 1481 { 1482 aco_save_T aco; 1483 varnumber_T tick = CHANGEDTICK(curbuf); 1484 1485 // save and restore curwin and curbuf, in case the autocmd changes them 1486 aucmd_prepbuf(&aco, curbuf); 1487 apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); 1488 aucmd_restbuf(&aco); 1489 curbuf->b_last_changedtick = CHANGEDTICK(curbuf); 1490 if (tick != CHANGEDTICK(curbuf)) // see ins_apply_autocmds() 1491 u_save(curwin->w_cursor.lnum, 1492 (linenr_T)(curwin->w_cursor.lnum + 1)); 1493 } 1494 1495 // Trigger TextChangedP if b_changedtick differs. When the popupmenu closes 1496 // TextChangedI will need to trigger for backwards compatibility, thus use 1497 // different b_last_changedtick* variables. 1498 if (ready && has_textchangedP() 1499 && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf) 1500 && pum_visible()) 1501 { 1502 aco_save_T aco; 1503 varnumber_T tick = CHANGEDTICK(curbuf); 1504 1505 // save and restore curwin and curbuf, in case the autocmd changes them 1506 aucmd_prepbuf(&aco, curbuf); 1507 apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); 1508 aucmd_restbuf(&aco); 1509 curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf); 1510 if (tick != CHANGEDTICK(curbuf)) // see ins_apply_autocmds() 1511 u_save(curwin->w_cursor.lnum, 1512 (linenr_T)(curwin->w_cursor.lnum + 1)); 1513 } 1514 1515 // Trigger SafeState if nothing is pending. 1516 may_trigger_safestate(ready 1517 && !ins_compl_active() 1518 && !pum_visible()); 1519 1520 #if defined(FEAT_CONCEAL) 1521 if ((conceal_update_lines 1522 && (conceal_old_cursor_line != conceal_new_cursor_line 1523 || conceal_cursor_line(curwin))) 1524 || need_cursor_line_redraw) 1525 { 1526 if (conceal_old_cursor_line != conceal_new_cursor_line) 1527 redrawWinline(curwin, conceal_old_cursor_line); 1528 redrawWinline(curwin, conceal_new_cursor_line == 0 1529 ? curwin->w_cursor.lnum : conceal_new_cursor_line); 1530 curwin->w_valid &= ~VALID_CROW; 1531 need_cursor_line_redraw = FALSE; 1532 } 1533 #endif 1534 if (must_redraw) 1535 update_screen(0); 1536 else if (clear_cmdline || redraw_cmdline) 1537 showmode(); // clear cmdline and show mode 1538 showruler(FALSE); 1539 setcursor(); 1540 emsg_on_display = FALSE; // may remove error message now 1541 } 1542 1543 /* 1544 * Handle a CTRL-V or CTRL-Q typed in Insert mode. 1545 */ 1546 static void 1547 ins_ctrl_v(void) 1548 { 1549 int c; 1550 int did_putchar = FALSE; 1551 1552 // may need to redraw when no more chars available now 1553 ins_redraw(FALSE); 1554 1555 if (redrawing() && !char_avail()) 1556 { 1557 edit_putchar('^', TRUE); 1558 did_putchar = TRUE; 1559 } 1560 AppendToRedobuff((char_u *)CTRL_V_STR); // CTRL-V 1561 1562 #ifdef FEAT_CMDL_INFO 1563 add_to_showcmd_c(Ctrl_V); 1564 #endif 1565 1566 // Do not change any modifyOtherKeys ESC sequence to a normal key for 1567 // CTRL-SHIFT-V. 1568 c = get_literal(mod_mask & MOD_MASK_SHIFT); 1569 if (did_putchar) 1570 // when the line fits in 'columns' the '^' is at the start of the next 1571 // line and will not removed by the redraw 1572 edit_unputchar(); 1573 #ifdef FEAT_CMDL_INFO 1574 clear_showcmd(); 1575 #endif 1576 1577 insert_special(c, FALSE, TRUE); 1578 #ifdef FEAT_RIGHTLEFT 1579 revins_chars++; 1580 revins_legal++; 1581 #endif 1582 } 1583 1584 /* 1585 * After getting an ESC or CSI for a literal key: If the typeahead buffer 1586 * contains a modifyOtherKeys sequence then decode it and return the result. 1587 * Otherwise return "c". 1588 * Note that this doesn't wait for characters, they must be in the typeahead 1589 * buffer already. 1590 */ 1591 static int 1592 decodeModifyOtherKeys(int c) 1593 { 1594 char_u *p = typebuf.tb_buf + typebuf.tb_off; 1595 int idx; 1596 int form = 0; 1597 int argidx = 0; 1598 int arg[2] = {0, 0}; 1599 1600 // Recognize: 1601 // form 0: {lead}{key};{modifier}u 1602 // form 1: {lead}27;{modifier};{key}~ 1603 if (typebuf.tb_len >= 4 && (c == CSI || (c == ESC && *p == '['))) 1604 { 1605 idx = (*p == '['); 1606 if (p[idx] == '2' && p[idx + 1] == '7' && p[idx + 2] == ';') 1607 { 1608 form = 1; 1609 idx += 3; 1610 } 1611 while (idx < typebuf.tb_len && argidx < 2) 1612 { 1613 if (p[idx] == ';') 1614 ++argidx; 1615 else if (VIM_ISDIGIT(p[idx])) 1616 arg[argidx] = arg[argidx] * 10 + (p[idx] - '0'); 1617 else 1618 break; 1619 ++idx; 1620 } 1621 if (idx < typebuf.tb_len 1622 && p[idx] == (form == 1 ? '~' : 'u') 1623 && argidx == 1) 1624 { 1625 // Match, consume the code. 1626 typebuf.tb_off += idx + 1; 1627 typebuf.tb_len -= idx + 1; 1628 #if defined(FEAT_CLIENTSERVER) || defined(FEAT_EVAL) 1629 if (typebuf.tb_len == 0) 1630 typebuf_was_filled = FALSE; 1631 #endif 1632 1633 mod_mask = decode_modifiers(arg[!form]); 1634 c = merge_modifyOtherKeys(arg[form], &mod_mask); 1635 } 1636 } 1637 1638 return c; 1639 } 1640 1641 /* 1642 * Put a character directly onto the screen. It's not stored in a buffer. 1643 * Used while handling CTRL-K, CTRL-V, etc. in Insert mode. 1644 */ 1645 static int pc_status; 1646 #define PC_STATUS_UNSET 0 // pc_bytes was not set 1647 #define PC_STATUS_RIGHT 1 // right halve of double-wide char 1648 #define PC_STATUS_LEFT 2 // left halve of double-wide char 1649 #define PC_STATUS_SET 3 // pc_bytes was filled 1650 static char_u pc_bytes[MB_MAXBYTES + 1]; // saved bytes 1651 static int pc_attr; 1652 static int pc_row; 1653 static int pc_col; 1654 1655 void 1656 edit_putchar(int c, int highlight) 1657 { 1658 int attr; 1659 1660 if (ScreenLines != NULL) 1661 { 1662 update_topline(); // just in case w_topline isn't valid 1663 validate_cursor(); 1664 if (highlight) 1665 attr = HL_ATTR(HLF_8); 1666 else 1667 attr = 0; 1668 pc_row = W_WINROW(curwin) + curwin->w_wrow; 1669 pc_col = curwin->w_wincol; 1670 pc_status = PC_STATUS_UNSET; 1671 #ifdef FEAT_RIGHTLEFT 1672 if (curwin->w_p_rl) 1673 { 1674 pc_col += curwin->w_width - 1 - curwin->w_wcol; 1675 if (has_mbyte) 1676 { 1677 int fix_col = mb_fix_col(pc_col, pc_row); 1678 1679 if (fix_col != pc_col) 1680 { 1681 screen_putchar(' ', pc_row, fix_col, attr); 1682 --curwin->w_wcol; 1683 pc_status = PC_STATUS_RIGHT; 1684 } 1685 } 1686 } 1687 else 1688 #endif 1689 { 1690 pc_col += curwin->w_wcol; 1691 if (mb_lefthalve(pc_row, pc_col)) 1692 pc_status = PC_STATUS_LEFT; 1693 } 1694 1695 // save the character to be able to put it back 1696 if (pc_status == PC_STATUS_UNSET) 1697 { 1698 screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr); 1699 pc_status = PC_STATUS_SET; 1700 } 1701 screen_putchar(c, pc_row, pc_col, attr); 1702 } 1703 } 1704 1705 /* 1706 * Set the insert start position for when using a prompt buffer. 1707 */ 1708 void 1709 set_insstart(linenr_T lnum, int col) 1710 { 1711 Insstart.lnum = lnum; 1712 Insstart.col = col; 1713 Insstart_orig = Insstart; 1714 Insstart_textlen = Insstart.col; 1715 Insstart_blank_vcol = MAXCOL; 1716 arrow_used = FALSE; 1717 } 1718 1719 /* 1720 * Undo the previous edit_putchar(). 1721 */ 1722 void 1723 edit_unputchar(void) 1724 { 1725 if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) 1726 { 1727 if (pc_status == PC_STATUS_RIGHT) 1728 ++curwin->w_wcol; 1729 if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) 1730 redrawWinline(curwin, curwin->w_cursor.lnum); 1731 else 1732 screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); 1733 } 1734 } 1735 1736 /* 1737 * Called when p_dollar is set: display a '$' at the end of the changed text 1738 * Only works when cursor is in the line that changes. 1739 */ 1740 void 1741 display_dollar(colnr_T col) 1742 { 1743 colnr_T save_col; 1744 1745 if (!redrawing()) 1746 return; 1747 1748 cursor_off(); 1749 save_col = curwin->w_cursor.col; 1750 curwin->w_cursor.col = col; 1751 if (has_mbyte) 1752 { 1753 char_u *p; 1754 1755 // If on the last byte of a multi-byte move to the first byte. 1756 p = ml_get_curline(); 1757 curwin->w_cursor.col -= (*mb_head_off)(p, p + col); 1758 } 1759 curs_columns(FALSE); // recompute w_wrow and w_wcol 1760 if (curwin->w_wcol < curwin->w_width) 1761 { 1762 edit_putchar('$', FALSE); 1763 dollar_vcol = curwin->w_virtcol; 1764 } 1765 curwin->w_cursor.col = save_col; 1766 } 1767 1768 /* 1769 * Call this function before moving the cursor from the normal insert position 1770 * in insert mode. 1771 */ 1772 void 1773 undisplay_dollar(void) 1774 { 1775 if (dollar_vcol >= 0) 1776 { 1777 dollar_vcol = -1; 1778 redrawWinline(curwin, curwin->w_cursor.lnum); 1779 } 1780 } 1781 1782 /* 1783 * Truncate the space at the end of a line. This is to be used only in an 1784 * insert mode. It handles fixing the replace stack for REPLACE and VREPLACE 1785 * modes. 1786 */ 1787 void 1788 truncate_spaces(char_u *line) 1789 { 1790 int i; 1791 1792 // find start of trailing white space 1793 for (i = (int)STRLEN(line) - 1; i >= 0 && VIM_ISWHITE(line[i]); i--) 1794 { 1795 if (State & REPLACE_FLAG) 1796 replace_join(0); // remove a NUL from the replace stack 1797 } 1798 line[i + 1] = NUL; 1799 } 1800 1801 /* 1802 * Backspace the cursor until the given column. Handles REPLACE and VREPLACE 1803 * modes correctly. May also be used when not in insert mode at all. 1804 * Will attempt not to go before "col" even when there is a composing 1805 * character. 1806 */ 1807 void 1808 backspace_until_column(int col) 1809 { 1810 while ((int)curwin->w_cursor.col > col) 1811 { 1812 curwin->w_cursor.col--; 1813 if (State & REPLACE_FLAG) 1814 replace_do_bs(col); 1815 else if (!del_char_after_col(col)) 1816 break; 1817 } 1818 } 1819 1820 /* 1821 * Like del_char(), but make sure not to go before column "limit_col". 1822 * Only matters when there are composing characters. 1823 * Return TRUE when something was deleted. 1824 */ 1825 static int 1826 del_char_after_col(int limit_col UNUSED) 1827 { 1828 if (enc_utf8 && limit_col >= 0) 1829 { 1830 colnr_T ecol = curwin->w_cursor.col + 1; 1831 1832 // Make sure the cursor is at the start of a character, but 1833 // skip forward again when going too far back because of a 1834 // composing character. 1835 mb_adjust_cursor(); 1836 while (curwin->w_cursor.col < (colnr_T)limit_col) 1837 { 1838 int l = utf_ptr2len(ml_get_cursor()); 1839 1840 if (l == 0) // end of line 1841 break; 1842 curwin->w_cursor.col += l; 1843 } 1844 if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol) 1845 return FALSE; 1846 del_bytes((long)((int)ecol - curwin->w_cursor.col), FALSE, TRUE); 1847 } 1848 else 1849 (void)del_char(FALSE); 1850 return TRUE; 1851 } 1852 1853 /* 1854 * Next character is interpreted literally. 1855 * A one, two or three digit decimal number is interpreted as its byte value. 1856 * If one or two digits are entered, the next character is given to vungetc(). 1857 * For Unicode a character > 255 may be returned. 1858 * If "noReduceKeys" is TRUE do not change any modifyOtherKeys ESC sequence 1859 * into a normal key, return ESC. 1860 */ 1861 int 1862 get_literal(int noReduceKeys) 1863 { 1864 int cc; 1865 int nc; 1866 int i; 1867 int hex = FALSE; 1868 int octal = FALSE; 1869 int unicode = 0; 1870 1871 if (got_int) 1872 return Ctrl_C; 1873 1874 #ifdef FEAT_GUI 1875 /* 1876 * In GUI there is no point inserting the internal code for a special key. 1877 * It is more useful to insert the string "<KEY>" instead. This would 1878 * probably be useful in a text window too, but it would not be 1879 * vi-compatible (maybe there should be an option for it?) -- webb 1880 */ 1881 if (gui.in_use) 1882 ++allow_keys; 1883 #endif 1884 #ifdef USE_ON_FLY_SCROLL 1885 dont_scroll = TRUE; // disallow scrolling here 1886 #endif 1887 ++no_mapping; // don't map the next key hits 1888 cc = 0; 1889 i = 0; 1890 for (;;) 1891 { 1892 nc = plain_vgetc(); 1893 if ((nc == ESC || nc == CSI) && !noReduceKeys) 1894 nc = decodeModifyOtherKeys(nc); 1895 1896 #ifdef FEAT_CMDL_INFO 1897 if (!(State & CMDLINE) && MB_BYTE2LEN_CHECK(nc) == 1) 1898 add_to_showcmd(nc); 1899 #endif 1900 if (nc == 'x' || nc == 'X') 1901 hex = TRUE; 1902 else if (nc == 'o' || nc == 'O') 1903 octal = TRUE; 1904 else if (nc == 'u' || nc == 'U') 1905 unicode = nc; 1906 else 1907 { 1908 if (hex || unicode != 0) 1909 { 1910 if (!vim_isxdigit(nc)) 1911 break; 1912 cc = cc * 16 + hex2nr(nc); 1913 } 1914 else if (octal) 1915 { 1916 if (nc < '0' || nc > '7') 1917 break; 1918 cc = cc * 8 + nc - '0'; 1919 } 1920 else 1921 { 1922 if (!VIM_ISDIGIT(nc)) 1923 break; 1924 cc = cc * 10 + nc - '0'; 1925 } 1926 1927 ++i; 1928 } 1929 1930 if (cc > 255 && unicode == 0) 1931 cc = 255; // limit range to 0-255 1932 nc = 0; 1933 1934 if (hex) // hex: up to two chars 1935 { 1936 if (i >= 2) 1937 break; 1938 } 1939 else if (unicode) // Unicode: up to four or eight chars 1940 { 1941 if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8)) 1942 break; 1943 } 1944 else if (i >= 3) // decimal or octal: up to three chars 1945 break; 1946 } 1947 if (i == 0) // no number entered 1948 { 1949 if (nc == K_ZERO) // NUL is stored as NL 1950 { 1951 cc = '\n'; 1952 nc = 0; 1953 } 1954 else 1955 { 1956 cc = nc; 1957 nc = 0; 1958 } 1959 } 1960 1961 if (cc == 0) // NUL is stored as NL 1962 cc = '\n'; 1963 if (enc_dbcs && (cc & 0xff) == 0) 1964 cc = '?'; // don't accept an illegal DBCS char, the NUL in the 1965 // second byte will cause trouble! 1966 1967 --no_mapping; 1968 #ifdef FEAT_GUI 1969 if (gui.in_use) 1970 --allow_keys; 1971 #endif 1972 if (nc) 1973 vungetc(nc); 1974 got_int = FALSE; // CTRL-C typed after CTRL-V is not an interrupt 1975 return cc; 1976 } 1977 1978 /* 1979 * Insert character, taking care of special keys and mod_mask 1980 */ 1981 static void 1982 insert_special( 1983 int c, 1984 int allow_modmask, 1985 int ctrlv) // c was typed after CTRL-V 1986 { 1987 char_u *p; 1988 int len; 1989 1990 /* 1991 * Special function key, translate into "<Key>". Up to the last '>' is 1992 * inserted with ins_str(), so as not to replace characters in replace 1993 * mode. 1994 * Only use mod_mask for special keys, to avoid things like <S-Space>, 1995 * unless 'allow_modmask' is TRUE. 1996 */ 1997 #ifdef MACOS_X 1998 // Command-key never produces a normal key 1999 if (mod_mask & MOD_MASK_CMD) 2000 allow_modmask = TRUE; 2001 #endif 2002 if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) 2003 { 2004 p = get_special_key_name(c, mod_mask); 2005 len = (int)STRLEN(p); 2006 c = p[len - 1]; 2007 if (len > 2) 2008 { 2009 if (stop_arrow() == FAIL) 2010 return; 2011 p[len - 1] = NUL; 2012 ins_str(p); 2013 AppendToRedobuffLit(p, -1); 2014 ctrlv = FALSE; 2015 } 2016 } 2017 if (stop_arrow() == OK) 2018 insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1); 2019 } 2020 2021 /* 2022 * Special characters in this context are those that need processing other 2023 * than the simple insertion that can be performed here. This includes ESC 2024 * which terminates the insert, and CR/NL which need special processing to 2025 * open up a new line. This routine tries to optimize insertions performed by 2026 * the "redo", "undo" or "put" commands, so it needs to know when it should 2027 * stop and defer processing to the "normal" mechanism. 2028 * '0' and '^' are special, because they can be followed by CTRL-D. 2029 */ 2030 #ifdef EBCDIC 2031 # define ISSPECIAL(c) ((c) < ' ' || (c) == '0' || (c) == '^') 2032 #else 2033 # define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^') 2034 #endif 2035 2036 /* 2037 * "flags": INSCHAR_FORMAT - force formatting 2038 * INSCHAR_CTRLV - char typed just after CTRL-V 2039 * INSCHAR_NO_FEX - don't use 'formatexpr' 2040 * 2041 * NOTE: passes the flags value straight through to internal_format() which, 2042 * beside INSCHAR_FORMAT (above), is also looking for these: 2043 * INSCHAR_DO_COM - format comments 2044 * INSCHAR_COM_LIST - format comments with num list or 2nd line indent 2045 */ 2046 void 2047 insertchar( 2048 int c, // character to insert or NUL 2049 int flags, // INSCHAR_FORMAT, etc. 2050 int second_indent) // indent for second line if >= 0 2051 { 2052 int textwidth; 2053 char_u *p; 2054 int fo_ins_blank; 2055 int force_format = flags & INSCHAR_FORMAT; 2056 2057 textwidth = comp_textwidth(force_format); 2058 fo_ins_blank = has_format_option(FO_INS_BLANK); 2059 2060 /* 2061 * Try to break the line in two or more pieces when: 2062 * - Always do this if we have been called to do formatting only. 2063 * - Always do this when 'formatoptions' has the 'a' flag and the line 2064 * ends in white space. 2065 * - Otherwise: 2066 * - Don't do this if inserting a blank 2067 * - Don't do this if an existing character is being replaced, unless 2068 * we're in VREPLACE mode. 2069 * - Do this if the cursor is not on the line where insert started 2070 * or - 'formatoptions' doesn't have 'l' or the line was not too long 2071 * before the insert. 2072 * - 'formatoptions' doesn't have 'b' or a blank was inserted at or 2073 * before 'textwidth' 2074 */ 2075 if (textwidth > 0 2076 && (force_format 2077 || (!VIM_ISWHITE(c) 2078 && !((State & REPLACE_FLAG) 2079 && !(State & VREPLACE_FLAG) 2080 && *ml_get_cursor() != NUL) 2081 && (curwin->w_cursor.lnum != Insstart.lnum 2082 || ((!has_format_option(FO_INS_LONG) 2083 || Insstart_textlen <= (colnr_T)textwidth) 2084 && (!fo_ins_blank 2085 || Insstart_blank_vcol <= (colnr_T)textwidth 2086 )))))) 2087 { 2088 // Format with 'formatexpr' when it's set. Use internal formatting 2089 // when 'formatexpr' isn't set or it returns non-zero. 2090 #if defined(FEAT_EVAL) 2091 int do_internal = TRUE; 2092 colnr_T virtcol = get_nolist_virtcol() 2093 + char2cells(c != NUL ? c : gchar_cursor()); 2094 2095 if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0 2096 && (force_format || virtcol > (colnr_T)textwidth)) 2097 { 2098 do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); 2099 // It may be required to save for undo again, e.g. when setline() 2100 // was called. 2101 ins_need_undo = TRUE; 2102 } 2103 if (do_internal) 2104 #endif 2105 internal_format(textwidth, second_indent, flags, c == NUL, c); 2106 } 2107 2108 if (c == NUL) // only formatting was wanted 2109 return; 2110 2111 // Check whether this character should end a comment. 2112 if (did_ai && (int)c == end_comment_pending) 2113 { 2114 char_u *line; 2115 char_u lead_end[COM_MAX_LEN]; // end-comment string 2116 int middle_len, end_len; 2117 int i; 2118 2119 /* 2120 * Need to remove existing (middle) comment leader and insert end 2121 * comment leader. First, check what comment leader we can find. 2122 */ 2123 i = get_leader_len(line = ml_get_curline(), &p, FALSE, TRUE); 2124 if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) // Just checking 2125 { 2126 // Skip middle-comment string 2127 while (*p && p[-1] != ':') // find end of middle flags 2128 ++p; 2129 middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 2130 // Don't count trailing white space for middle_len 2131 while (middle_len > 0 && VIM_ISWHITE(lead_end[middle_len - 1])) 2132 --middle_len; 2133 2134 // Find the end-comment string 2135 while (*p && p[-1] != ':') // find end of end flags 2136 ++p; 2137 end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 2138 2139 // Skip white space before the cursor 2140 i = curwin->w_cursor.col; 2141 while (--i >= 0 && VIM_ISWHITE(line[i])) 2142 ; 2143 i++; 2144 2145 // Skip to before the middle leader 2146 i -= middle_len; 2147 2148 // Check some expected things before we go on 2149 if (i >= 0 && lead_end[end_len - 1] == end_comment_pending) 2150 { 2151 // Backspace over all the stuff we want to replace 2152 backspace_until_column(i); 2153 2154 // Insert the end-comment string, except for the last 2155 // character, which will get inserted as normal later. 2156 ins_bytes_len(lead_end, end_len - 1); 2157 } 2158 } 2159 } 2160 end_comment_pending = NUL; 2161 2162 did_ai = FALSE; 2163 #ifdef FEAT_SMARTINDENT 2164 did_si = FALSE; 2165 can_si = FALSE; 2166 can_si_back = FALSE; 2167 #endif 2168 2169 /* 2170 * If there's any pending input, grab up to INPUT_BUFLEN at once. 2171 * This speeds up normal text input considerably. 2172 * Don't do this when 'cindent' or 'indentexpr' is set, because we might 2173 * need to re-indent at a ':', or any other character (but not what 2174 * 'paste' is set).. 2175 * Don't do this when there an InsertCharPre autocommand is defined, 2176 * because we need to fire the event for every character. 2177 * Do the check for InsertCharPre before the call to vpeekc() because the 2178 * InsertCharPre autocommand could change the input buffer. 2179 */ 2180 #ifdef USE_ON_FLY_SCROLL 2181 dont_scroll = FALSE; // allow scrolling here 2182 #endif 2183 2184 if ( !ISSPECIAL(c) 2185 && (!has_mbyte || (*mb_char2len)(c) == 1) 2186 && !has_insertcharpre() 2187 && vpeekc() != NUL 2188 && !(State & REPLACE_FLAG) 2189 #ifdef FEAT_CINDENT 2190 && !cindent_on() 2191 #endif 2192 #ifdef FEAT_RIGHTLEFT 2193 && !p_ri 2194 #endif 2195 ) 2196 { 2197 #define INPUT_BUFLEN 100 2198 char_u buf[INPUT_BUFLEN + 1]; 2199 int i; 2200 colnr_T virtcol = 0; 2201 2202 buf[0] = c; 2203 i = 1; 2204 if (textwidth > 0) 2205 virtcol = get_nolist_virtcol(); 2206 /* 2207 * Stop the string when: 2208 * - no more chars available 2209 * - finding a special character (command key) 2210 * - buffer is full 2211 * - running into the 'textwidth' boundary 2212 * - need to check for abbreviation: A non-word char after a word-char 2213 */ 2214 while ( (c = vpeekc()) != NUL 2215 && !ISSPECIAL(c) 2216 && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1) 2217 && i < INPUT_BUFLEN 2218 && (textwidth == 0 2219 || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth) 2220 && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) 2221 { 2222 #ifdef FEAT_RIGHTLEFT 2223 c = vgetc(); 2224 if (p_hkmap && KeyTyped) 2225 c = hkmap(c); // Hebrew mode mapping 2226 buf[i++] = c; 2227 #else 2228 buf[i++] = vgetc(); 2229 #endif 2230 } 2231 2232 #ifdef FEAT_DIGRAPHS 2233 do_digraph(-1); // clear digraphs 2234 do_digraph(buf[i-1]); // may be the start of a digraph 2235 #endif 2236 buf[i] = NUL; 2237 ins_str(buf); 2238 if (flags & INSCHAR_CTRLV) 2239 { 2240 redo_literal(*buf); 2241 i = 1; 2242 } 2243 else 2244 i = 0; 2245 if (buf[i] != NUL) 2246 AppendToRedobuffLit(buf + i, -1); 2247 } 2248 else 2249 { 2250 int cc; 2251 2252 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) 2253 { 2254 char_u buf[MB_MAXBYTES + 1]; 2255 2256 (*mb_char2bytes)(c, buf); 2257 buf[cc] = NUL; 2258 ins_char_bytes(buf, cc); 2259 AppendCharToRedobuff(c); 2260 } 2261 else 2262 { 2263 ins_char(c); 2264 if (flags & INSCHAR_CTRLV) 2265 redo_literal(c); 2266 else 2267 AppendCharToRedobuff(c); 2268 } 2269 } 2270 } 2271 2272 /* 2273 * Put a character in the redo buffer, for when just after a CTRL-V. 2274 */ 2275 static void 2276 redo_literal(int c) 2277 { 2278 char_u buf[10]; 2279 2280 // Only digits need special treatment. Translate them into a string of 2281 // three digits. 2282 if (VIM_ISDIGIT(c)) 2283 { 2284 vim_snprintf((char *)buf, sizeof(buf), "%03d", c); 2285 AppendToRedobuff(buf); 2286 } 2287 else 2288 AppendCharToRedobuff(c); 2289 } 2290 2291 /* 2292 * start_arrow() is called when an arrow key is used in insert mode. 2293 * For undo/redo it resembles hitting the <ESC> key. 2294 */ 2295 void 2296 start_arrow( 2297 pos_T *end_insert_pos) // can be NULL 2298 { 2299 start_arrow_common(end_insert_pos, TRUE); 2300 } 2301 2302 /* 2303 * Like start_arrow() but with end_change argument. 2304 * Will prepare for redo of CTRL-G U if "end_change" is FALSE. 2305 */ 2306 static void 2307 start_arrow_with_change( 2308 pos_T *end_insert_pos, // can be NULL 2309 int end_change) // end undoable change 2310 { 2311 start_arrow_common(end_insert_pos, end_change); 2312 if (!end_change) 2313 { 2314 AppendCharToRedobuff(Ctrl_G); 2315 AppendCharToRedobuff('U'); 2316 } 2317 } 2318 2319 static void 2320 start_arrow_common( 2321 pos_T *end_insert_pos, // can be NULL 2322 int end_change) // end undoable change 2323 { 2324 if (!arrow_used && end_change) // something has been inserted 2325 { 2326 AppendToRedobuff(ESC_STR); 2327 stop_insert(end_insert_pos, FALSE, FALSE); 2328 arrow_used = TRUE; // this means we stopped the current insert 2329 } 2330 #ifdef FEAT_SPELL 2331 check_spell_redraw(); 2332 #endif 2333 } 2334 2335 #ifdef FEAT_SPELL 2336 /* 2337 * If we skipped highlighting word at cursor, do it now. 2338 * It may be skipped again, thus reset spell_redraw_lnum first. 2339 */ 2340 static void 2341 check_spell_redraw(void) 2342 { 2343 if (spell_redraw_lnum != 0) 2344 { 2345 linenr_T lnum = spell_redraw_lnum; 2346 2347 spell_redraw_lnum = 0; 2348 redrawWinline(curwin, lnum); 2349 } 2350 } 2351 2352 #endif 2353 2354 /* 2355 * stop_arrow() is called before a change is made in insert mode. 2356 * If an arrow key has been used, start a new insertion. 2357 * Returns FAIL if undo is impossible, shouldn't insert then. 2358 */ 2359 int 2360 stop_arrow(void) 2361 { 2362 if (arrow_used) 2363 { 2364 Insstart = curwin->w_cursor; // new insertion starts here 2365 if (Insstart.col > Insstart_orig.col && !ins_need_undo) 2366 // Don't update the original insert position when moved to the 2367 // right, except when nothing was inserted yet. 2368 update_Insstart_orig = FALSE; 2369 Insstart_textlen = (colnr_T)linetabsize(ml_get_curline()); 2370 2371 if (u_save_cursor() == OK) 2372 { 2373 arrow_used = FALSE; 2374 ins_need_undo = FALSE; 2375 } 2376 2377 ai_col = 0; 2378 if (State & VREPLACE_FLAG) 2379 { 2380 orig_line_count = curbuf->b_ml.ml_line_count; 2381 vr_lines_changed = 1; 2382 } 2383 ResetRedobuff(); 2384 AppendToRedobuff((char_u *)"1i"); // pretend we start an insertion 2385 new_insert_skip = 2; 2386 } 2387 else if (ins_need_undo) 2388 { 2389 if (u_save_cursor() == OK) 2390 ins_need_undo = FALSE; 2391 } 2392 2393 #ifdef FEAT_FOLDING 2394 // Always open fold at the cursor line when inserting something. 2395 foldOpenCursor(); 2396 #endif 2397 2398 return (arrow_used || ins_need_undo ? FAIL : OK); 2399 } 2400 2401 /* 2402 * Do a few things to stop inserting. 2403 * "end_insert_pos" is where insert ended. It is NULL when we already jumped 2404 * to another window/buffer. 2405 */ 2406 static void 2407 stop_insert( 2408 pos_T *end_insert_pos, 2409 int esc, // called by ins_esc() 2410 int nomove) // <c-\><c-o>, don't move cursor 2411 { 2412 int cc; 2413 char_u *ptr; 2414 2415 stop_redo_ins(); 2416 replace_flush(); // abandon replace stack 2417 2418 /* 2419 * Save the inserted text for later redo with ^@ and CTRL-A. 2420 * Don't do it when "restart_edit" was set and nothing was inserted, 2421 * otherwise CTRL-O w and then <Left> will clear "last_insert". 2422 */ 2423 ptr = get_inserted(); 2424 if (did_restart_edit == 0 || (ptr != NULL 2425 && (int)STRLEN(ptr) > new_insert_skip)) 2426 { 2427 vim_free(last_insert); 2428 last_insert = ptr; 2429 last_insert_skip = new_insert_skip; 2430 } 2431 else 2432 vim_free(ptr); 2433 2434 if (!arrow_used && end_insert_pos != NULL) 2435 { 2436 // Auto-format now. It may seem strange to do this when stopping an 2437 // insertion (or moving the cursor), but it's required when appending 2438 // a line and having it end in a space. But only do it when something 2439 // was actually inserted, otherwise undo won't work. 2440 if (!ins_need_undo && has_format_option(FO_AUTO)) 2441 { 2442 pos_T tpos = curwin->w_cursor; 2443 2444 // When the cursor is at the end of the line after a space the 2445 // formatting will move it to the following word. Avoid that by 2446 // moving the cursor onto the space. 2447 cc = 'x'; 2448 if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL) 2449 { 2450 dec_cursor(); 2451 cc = gchar_cursor(); 2452 if (!VIM_ISWHITE(cc)) 2453 curwin->w_cursor = tpos; 2454 } 2455 2456 auto_format(TRUE, FALSE); 2457 2458 if (VIM_ISWHITE(cc)) 2459 { 2460 if (gchar_cursor() != NUL) 2461 inc_cursor(); 2462 // If the cursor is still at the same character, also keep 2463 // the "coladd". 2464 if (gchar_cursor() == NUL 2465 && curwin->w_cursor.lnum == tpos.lnum 2466 && curwin->w_cursor.col == tpos.col) 2467 curwin->w_cursor.coladd = tpos.coladd; 2468 } 2469 } 2470 2471 // If a space was inserted for auto-formatting, remove it now. 2472 check_auto_format(TRUE); 2473 2474 // If we just did an auto-indent, remove the white space from the end 2475 // of the line, and put the cursor back. 2476 // Do this when ESC was used or moving the cursor up/down. 2477 // Check for the old position still being valid, just in case the text 2478 // got changed unexpectedly. 2479 if (!nomove && did_ai && (esc || (vim_strchr(p_cpo, CPO_INDENT) == NULL 2480 && curwin->w_cursor.lnum != end_insert_pos->lnum)) 2481 && end_insert_pos->lnum <= curbuf->b_ml.ml_line_count) 2482 { 2483 pos_T tpos = curwin->w_cursor; 2484 2485 curwin->w_cursor = *end_insert_pos; 2486 check_cursor_col(); // make sure it is not past the line 2487 for (;;) 2488 { 2489 if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) 2490 --curwin->w_cursor.col; 2491 cc = gchar_cursor(); 2492 if (!VIM_ISWHITE(cc)) 2493 break; 2494 if (del_char(TRUE) == FAIL) 2495 break; // should not happen 2496 } 2497 if (curwin->w_cursor.lnum != tpos.lnum) 2498 curwin->w_cursor = tpos; 2499 else 2500 { 2501 // reset tpos, could have been invalidated in the loop above 2502 tpos = curwin->w_cursor; 2503 tpos.col++; 2504 if (cc != NUL && gchar_pos(&tpos) == NUL) 2505 ++curwin->w_cursor.col; // put cursor back on the NUL 2506 } 2507 2508 // <C-S-Right> may have started Visual mode, adjust the position for 2509 // deleted characters. 2510 if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) 2511 { 2512 int len = (int)STRLEN(ml_get_curline()); 2513 2514 if (VIsual.col > len) 2515 { 2516 VIsual.col = len; 2517 VIsual.coladd = 0; 2518 } 2519 } 2520 } 2521 } 2522 did_ai = FALSE; 2523 #ifdef FEAT_SMARTINDENT 2524 did_si = FALSE; 2525 can_si = FALSE; 2526 can_si_back = FALSE; 2527 #endif 2528 2529 // Set '[ and '] to the inserted text. When end_insert_pos is NULL we are 2530 // now in a different buffer. 2531 if (end_insert_pos != NULL) 2532 { 2533 curbuf->b_op_start = Insstart; 2534 curbuf->b_op_start_orig = Insstart_orig; 2535 curbuf->b_op_end = *end_insert_pos; 2536 } 2537 } 2538 2539 /* 2540 * Set the last inserted text to a single character. 2541 * Used for the replace command. 2542 */ 2543 void 2544 set_last_insert(int c) 2545 { 2546 char_u *s; 2547 2548 vim_free(last_insert); 2549 last_insert = alloc(MB_MAXBYTES * 3 + 5); 2550 if (last_insert != NULL) 2551 { 2552 s = last_insert; 2553 // Use the CTRL-V only when entering a special char 2554 if (c < ' ' || c == DEL) 2555 *s++ = Ctrl_V; 2556 s = add_char2buf(c, s); 2557 *s++ = ESC; 2558 *s++ = NUL; 2559 last_insert_skip = 0; 2560 } 2561 } 2562 2563 #if defined(EXITFREE) || defined(PROTO) 2564 void 2565 free_last_insert(void) 2566 { 2567 VIM_CLEAR(last_insert); 2568 } 2569 #endif 2570 2571 /* 2572 * Add character "c" to buffer "s". Escape the special meaning of K_SPECIAL 2573 * and CSI. Handle multi-byte characters. 2574 * Returns a pointer to after the added bytes. 2575 */ 2576 char_u * 2577 add_char2buf(int c, char_u *s) 2578 { 2579 char_u temp[MB_MAXBYTES + 1]; 2580 int i; 2581 int len; 2582 2583 len = (*mb_char2bytes)(c, temp); 2584 for (i = 0; i < len; ++i) 2585 { 2586 c = temp[i]; 2587 // Need to escape K_SPECIAL and CSI like in the typeahead buffer. 2588 if (c == K_SPECIAL) 2589 { 2590 *s++ = K_SPECIAL; 2591 *s++ = KS_SPECIAL; 2592 *s++ = KE_FILLER; 2593 } 2594 #ifdef FEAT_GUI 2595 else if (c == CSI) 2596 { 2597 *s++ = CSI; 2598 *s++ = KS_EXTRA; 2599 *s++ = (int)KE_CSI; 2600 } 2601 #endif 2602 else 2603 *s++ = c; 2604 } 2605 return s; 2606 } 2607 2608 /* 2609 * move cursor to start of line 2610 * if flags & BL_WHITE move to first non-white 2611 * if flags & BL_SOL move to first non-white if startofline is set, 2612 * otherwise keep "curswant" column 2613 * if flags & BL_FIX don't leave the cursor on a NUL. 2614 */ 2615 void 2616 beginline(int flags) 2617 { 2618 if ((flags & BL_SOL) && !p_sol) 2619 coladvance(curwin->w_curswant); 2620 else 2621 { 2622 curwin->w_cursor.col = 0; 2623 curwin->w_cursor.coladd = 0; 2624 2625 if (flags & (BL_WHITE | BL_SOL)) 2626 { 2627 char_u *ptr; 2628 2629 for (ptr = ml_get_curline(); VIM_ISWHITE(*ptr) 2630 && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) 2631 ++curwin->w_cursor.col; 2632 } 2633 curwin->w_set_curswant = TRUE; 2634 } 2635 } 2636 2637 /* 2638 * oneright oneleft cursor_down cursor_up 2639 * 2640 * Move one char {right,left,down,up}. 2641 * Doesn't move onto the NUL past the end of the line, unless it is allowed. 2642 * Return OK when successful, FAIL when we hit a line of file boundary. 2643 */ 2644 2645 int 2646 oneright(void) 2647 { 2648 char_u *ptr; 2649 int l; 2650 2651 if (virtual_active()) 2652 { 2653 pos_T prevpos = curwin->w_cursor; 2654 2655 // Adjust for multi-wide char (excluding TAB) 2656 ptr = ml_get_cursor(); 2657 coladvance(getviscol() + ((*ptr != TAB 2658 && vim_isprintc((*mb_ptr2char)(ptr))) 2659 ? ptr2cells(ptr) : 1)); 2660 curwin->w_set_curswant = TRUE; 2661 // Return OK if the cursor moved, FAIL otherwise (at window edge). 2662 return (prevpos.col != curwin->w_cursor.col 2663 || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; 2664 } 2665 2666 ptr = ml_get_cursor(); 2667 if (*ptr == NUL) 2668 return FAIL; // already at the very end 2669 2670 if (has_mbyte) 2671 l = (*mb_ptr2len)(ptr); 2672 else 2673 l = 1; 2674 2675 // move "l" bytes right, but don't end up on the NUL, unless 'virtualedit' 2676 // contains "onemore". 2677 if (ptr[l] == NUL && (get_ve_flags() & VE_ONEMORE) == 0) 2678 return FAIL; 2679 curwin->w_cursor.col += l; 2680 2681 curwin->w_set_curswant = TRUE; 2682 return OK; 2683 } 2684 2685 int 2686 oneleft(void) 2687 { 2688 if (virtual_active()) 2689 { 2690 #ifdef FEAT_LINEBREAK 2691 int width; 2692 #endif 2693 int v = getviscol(); 2694 2695 if (v == 0) 2696 return FAIL; 2697 2698 #ifdef FEAT_LINEBREAK 2699 // We might get stuck on 'showbreak', skip over it. 2700 width = 1; 2701 for (;;) 2702 { 2703 coladvance(v - width); 2704 // getviscol() is slow, skip it when 'showbreak' is empty, 2705 // 'breakindent' is not set and there are no multi-byte 2706 // characters 2707 if ((*get_showbreak_value(curwin) == NUL && !curwin->w_p_bri 2708 && !has_mbyte) || getviscol() < v) 2709 break; 2710 ++width; 2711 } 2712 #else 2713 coladvance(v - 1); 2714 #endif 2715 2716 if (curwin->w_cursor.coladd == 1) 2717 { 2718 char_u *ptr; 2719 2720 // Adjust for multi-wide char (not a TAB) 2721 ptr = ml_get_cursor(); 2722 if (*ptr != TAB && vim_isprintc((*mb_ptr2char)(ptr)) 2723 && ptr2cells(ptr) > 1) 2724 curwin->w_cursor.coladd = 0; 2725 } 2726 2727 curwin->w_set_curswant = TRUE; 2728 return OK; 2729 } 2730 2731 if (curwin->w_cursor.col == 0) 2732 return FAIL; 2733 2734 curwin->w_set_curswant = TRUE; 2735 --curwin->w_cursor.col; 2736 2737 // if the character on the left of the current cursor is a multi-byte 2738 // character, move to its first byte 2739 if (has_mbyte) 2740 mb_adjust_cursor(); 2741 return OK; 2742 } 2743 2744 int 2745 cursor_up( 2746 long n, 2747 int upd_topline) // When TRUE: update topline 2748 { 2749 linenr_T lnum; 2750 2751 if (n > 0) 2752 { 2753 lnum = curwin->w_cursor.lnum; 2754 // This fails if the cursor is already in the first line or the count 2755 // is larger than the line number and '-' is in 'cpoptions' 2756 if (lnum <= 1 || (n >= lnum && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 2757 return FAIL; 2758 if (n >= lnum) 2759 lnum = 1; 2760 else 2761 #ifdef FEAT_FOLDING 2762 if (hasAnyFolding(curwin)) 2763 { 2764 /* 2765 * Count each sequence of folded lines as one logical line. 2766 */ 2767 // go to the start of the current fold 2768 (void)hasFolding(lnum, &lnum, NULL); 2769 2770 while (n--) 2771 { 2772 // move up one line 2773 --lnum; 2774 if (lnum <= 1) 2775 break; 2776 // If we entered a fold, move to the beginning, unless in 2777 // Insert mode or when 'foldopen' contains "all": it will open 2778 // in a moment. 2779 if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL))) 2780 (void)hasFolding(lnum, &lnum, NULL); 2781 } 2782 if (lnum < 1) 2783 lnum = 1; 2784 } 2785 else 2786 #endif 2787 lnum -= n; 2788 curwin->w_cursor.lnum = lnum; 2789 } 2790 2791 // try to advance to the column we want to be at 2792 coladvance(curwin->w_curswant); 2793 2794 if (upd_topline) 2795 update_topline(); // make sure curwin->w_topline is valid 2796 2797 return OK; 2798 } 2799 2800 /* 2801 * Cursor down a number of logical lines. 2802 */ 2803 int 2804 cursor_down( 2805 long n, 2806 int upd_topline) // When TRUE: update topline 2807 { 2808 linenr_T lnum; 2809 2810 if (n > 0) 2811 { 2812 lnum = curwin->w_cursor.lnum; 2813 #ifdef FEAT_FOLDING 2814 // Move to last line of fold, will fail if it's the end-of-file. 2815 (void)hasFolding(lnum, NULL, &lnum); 2816 #endif 2817 // This fails if the cursor is already in the last line or would move 2818 // beyond the last line and '-' is in 'cpoptions' 2819 if (lnum >= curbuf->b_ml.ml_line_count 2820 || (lnum + n > curbuf->b_ml.ml_line_count 2821 && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 2822 return FAIL; 2823 if (lnum + n >= curbuf->b_ml.ml_line_count) 2824 lnum = curbuf->b_ml.ml_line_count; 2825 else 2826 #ifdef FEAT_FOLDING 2827 if (hasAnyFolding(curwin)) 2828 { 2829 linenr_T last; 2830 2831 // count each sequence of folded lines as one logical line 2832 while (n--) 2833 { 2834 if (hasFolding(lnum, NULL, &last)) 2835 lnum = last + 1; 2836 else 2837 ++lnum; 2838 if (lnum >= curbuf->b_ml.ml_line_count) 2839 break; 2840 } 2841 if (lnum > curbuf->b_ml.ml_line_count) 2842 lnum = curbuf->b_ml.ml_line_count; 2843 } 2844 else 2845 #endif 2846 lnum += n; 2847 curwin->w_cursor.lnum = lnum; 2848 } 2849 2850 // try to advance to the column we want to be at 2851 coladvance(curwin->w_curswant); 2852 2853 if (upd_topline) 2854 update_topline(); // make sure curwin->w_topline is valid 2855 2856 return OK; 2857 } 2858 2859 /* 2860 * Stuff the last inserted text in the read buffer. 2861 * Last_insert actually is a copy of the redo buffer, so we 2862 * first have to remove the command. 2863 */ 2864 int 2865 stuff_inserted( 2866 int c, // Command character to be inserted 2867 long count, // Repeat this many times 2868 int no_esc) // Don't add an ESC at the end 2869 { 2870 char_u *esc_ptr; 2871 char_u *ptr; 2872 char_u *last_ptr; 2873 char_u last = NUL; 2874 2875 ptr = get_last_insert(); 2876 if (ptr == NULL) 2877 { 2878 emsg(_(e_no_inserted_text_yet)); 2879 return FAIL; 2880 } 2881 2882 // may want to stuff the command character, to start Insert mode 2883 if (c != NUL) 2884 stuffcharReadbuff(c); 2885 if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL) 2886 *esc_ptr = NUL; // remove the ESC 2887 2888 // when the last char is either "0" or "^" it will be quoted if no ESC 2889 // comes after it OR if it will inserted more than once and "ptr" 2890 // starts with ^D. -- Acevedo 2891 last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1; 2892 if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^') 2893 && (no_esc || (*ptr == Ctrl_D && count > 1))) 2894 { 2895 last = *last_ptr; 2896 *last_ptr = NUL; 2897 } 2898 2899 do 2900 { 2901 stuffReadbuff(ptr); 2902 // a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" 2903 if (last) 2904 stuffReadbuff((char_u *)(last == '0' 2905 ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0") 2906 : IF_EB("\026^", CTRL_V_STR "^"))); 2907 } 2908 while (--count > 0); 2909 2910 if (last) 2911 *last_ptr = last; 2912 2913 if (esc_ptr != NULL) 2914 *esc_ptr = ESC; // put the ESC back 2915 2916 // may want to stuff a trailing ESC, to get out of Insert mode 2917 if (!no_esc) 2918 stuffcharReadbuff(ESC); 2919 2920 return OK; 2921 } 2922 2923 char_u * 2924 get_last_insert(void) 2925 { 2926 if (last_insert == NULL) 2927 return NULL; 2928 return last_insert + last_insert_skip; 2929 } 2930 2931 /* 2932 * Get last inserted string, and remove trailing <Esc>. 2933 * Returns pointer to allocated memory (must be freed) or NULL. 2934 */ 2935 char_u * 2936 get_last_insert_save(void) 2937 { 2938 char_u *s; 2939 int len; 2940 2941 if (last_insert == NULL) 2942 return NULL; 2943 s = vim_strsave(last_insert + last_insert_skip); 2944 if (s != NULL) 2945 { 2946 len = (int)STRLEN(s); 2947 if (len > 0 && s[len - 1] == ESC) // remove trailing ESC 2948 s[len - 1] = NUL; 2949 } 2950 return s; 2951 } 2952 2953 /* 2954 * Check the word in front of the cursor for an abbreviation. 2955 * Called when the non-id character "c" has been entered. 2956 * When an abbreviation is recognized it is removed from the text and 2957 * the replacement string is inserted in typebuf.tb_buf[], followed by "c". 2958 */ 2959 static int 2960 echeck_abbr(int c) 2961 { 2962 // Don't check for abbreviation in paste mode, when disabled and just 2963 // after moving around with cursor keys. 2964 if (p_paste || no_abbr || arrow_used) 2965 return FALSE; 2966 2967 return check_abbr(c, ml_get_curline(), curwin->w_cursor.col, 2968 curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0); 2969 } 2970 2971 /* 2972 * replace-stack functions 2973 * 2974 * When replacing characters, the replaced characters are remembered for each 2975 * new character. This is used to re-insert the old text when backspacing. 2976 * 2977 * There is a NUL headed list of characters for each character that is 2978 * currently in the file after the insertion point. When BS is used, one NUL 2979 * headed list is put back for the deleted character. 2980 * 2981 * For a newline, there are two NUL headed lists. One contains the characters 2982 * that the NL replaced. The extra one stores the characters after the cursor 2983 * that were deleted (always white space). 2984 * 2985 * Replace_offset is normally 0, in which case replace_push will add a new 2986 * character at the end of the stack. If replace_offset is not 0, that many 2987 * characters will be left on the stack above the newly inserted character. 2988 */ 2989 2990 static char_u *replace_stack = NULL; 2991 static long replace_stack_nr = 0; // next entry in replace stack 2992 static long replace_stack_len = 0; // max. number of entries 2993 2994 void 2995 replace_push( 2996 int c) // character that is replaced (NUL is none) 2997 { 2998 char_u *p; 2999 3000 if (replace_stack_nr < replace_offset) // nothing to do 3001 return; 3002 if (replace_stack_len <= replace_stack_nr) 3003 { 3004 replace_stack_len += 50; 3005 p = ALLOC_MULT(char_u, replace_stack_len); 3006 if (p == NULL) // out of memory 3007 { 3008 replace_stack_len -= 50; 3009 return; 3010 } 3011 if (replace_stack != NULL) 3012 { 3013 mch_memmove(p, replace_stack, 3014 (size_t)(replace_stack_nr * sizeof(char_u))); 3015 vim_free(replace_stack); 3016 } 3017 replace_stack = p; 3018 } 3019 p = replace_stack + replace_stack_nr - replace_offset; 3020 if (replace_offset) 3021 mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u))); 3022 *p = c; 3023 ++replace_stack_nr; 3024 } 3025 3026 /* 3027 * Push a character onto the replace stack. Handles a multi-byte character in 3028 * reverse byte order, so that the first byte is popped off first. 3029 * Return the number of bytes done (includes composing characters). 3030 */ 3031 int 3032 replace_push_mb(char_u *p) 3033 { 3034 int l = (*mb_ptr2len)(p); 3035 int j; 3036 3037 for (j = l - 1; j >= 0; --j) 3038 replace_push(p[j]); 3039 return l; 3040 } 3041 3042 /* 3043 * Pop one item from the replace stack. 3044 * return -1 if stack empty 3045 * return replaced character or NUL otherwise 3046 */ 3047 static int 3048 replace_pop(void) 3049 { 3050 if (replace_stack_nr == 0) 3051 return -1; 3052 return (int)replace_stack[--replace_stack_nr]; 3053 } 3054 3055 /* 3056 * Join the top two items on the replace stack. This removes to "off"'th NUL 3057 * encountered. 3058 */ 3059 void 3060 replace_join( 3061 int off) // offset for which NUL to remove 3062 { 3063 int i; 3064 3065 for (i = replace_stack_nr; --i >= 0; ) 3066 if (replace_stack[i] == NUL && off-- <= 0) 3067 { 3068 --replace_stack_nr; 3069 mch_memmove(replace_stack + i, replace_stack + i + 1, 3070 (size_t)(replace_stack_nr - i)); 3071 return; 3072 } 3073 } 3074 3075 /* 3076 * Pop bytes from the replace stack until a NUL is found, and insert them 3077 * before the cursor. Can only be used in REPLACE or VREPLACE mode. 3078 */ 3079 static void 3080 replace_pop_ins(void) 3081 { 3082 int cc; 3083 int oldState = State; 3084 3085 State = NORMAL; // don't want REPLACE here 3086 while ((cc = replace_pop()) > 0) 3087 { 3088 mb_replace_pop_ins(cc); 3089 dec_cursor(); 3090 } 3091 State = oldState; 3092 } 3093 3094 /* 3095 * Insert bytes popped from the replace stack. "cc" is the first byte. If it 3096 * indicates a multi-byte char, pop the other bytes too. 3097 */ 3098 static void 3099 mb_replace_pop_ins(int cc) 3100 { 3101 int n; 3102 char_u buf[MB_MAXBYTES + 1]; 3103 int i; 3104 int c; 3105 3106 if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1) 3107 { 3108 buf[0] = cc; 3109 for (i = 1; i < n; ++i) 3110 buf[i] = replace_pop(); 3111 ins_bytes_len(buf, n); 3112 } 3113 else 3114 ins_char(cc); 3115 3116 if (enc_utf8) 3117 // Handle composing chars. 3118 for (;;) 3119 { 3120 c = replace_pop(); 3121 if (c == -1) // stack empty 3122 break; 3123 if ((n = MB_BYTE2LEN(c)) == 1) 3124 { 3125 // Not a multi-byte char, put it back. 3126 replace_push(c); 3127 break; 3128 } 3129 else 3130 { 3131 buf[0] = c; 3132 for (i = 1; i < n; ++i) 3133 buf[i] = replace_pop(); 3134 if (utf_iscomposing(utf_ptr2char(buf))) 3135 ins_bytes_len(buf, n); 3136 else 3137 { 3138 // Not a composing char, put it back. 3139 for (i = n - 1; i >= 0; --i) 3140 replace_push(buf[i]); 3141 break; 3142 } 3143 } 3144 } 3145 } 3146 3147 /* 3148 * make the replace stack empty 3149 * (called when exiting replace mode) 3150 */ 3151 static void 3152 replace_flush(void) 3153 { 3154 VIM_CLEAR(replace_stack); 3155 replace_stack_len = 0; 3156 replace_stack_nr = 0; 3157 } 3158 3159 /* 3160 * Handle doing a BS for one character. 3161 * cc < 0: replace stack empty, just move cursor 3162 * cc == 0: character was inserted, delete it 3163 * cc > 0: character was replaced, put cc (first byte of original char) back 3164 * and check for more characters to be put back 3165 * When "limit_col" is >= 0, don't delete before this column. Matters when 3166 * using composing characters, use del_char_after_col() instead of del_char(). 3167 */ 3168 static void 3169 replace_do_bs(int limit_col) 3170 { 3171 int cc; 3172 int orig_len = 0; 3173 int ins_len; 3174 int orig_vcols = 0; 3175 colnr_T start_vcol; 3176 char_u *p; 3177 int i; 3178 int vcol; 3179 3180 cc = replace_pop(); 3181 if (cc > 0) 3182 { 3183 #ifdef FEAT_PROP_POPUP 3184 size_t len_before = 0; // init to shut up GCC 3185 3186 if (curbuf->b_has_textprop) 3187 { 3188 // Do not adjust text properties for individual delete and insert 3189 // operations, do it afterwards on the resulting text. 3190 len_before = STRLEN(ml_get_curline()); 3191 ++text_prop_frozen; 3192 } 3193 #endif 3194 if (State & VREPLACE_FLAG) 3195 { 3196 // Get the number of screen cells used by the character we are 3197 // going to delete. 3198 getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL); 3199 orig_vcols = chartabsize(ml_get_cursor(), start_vcol); 3200 } 3201 if (has_mbyte) 3202 { 3203 (void)del_char_after_col(limit_col); 3204 if (State & VREPLACE_FLAG) 3205 orig_len = (int)STRLEN(ml_get_cursor()); 3206 replace_push(cc); 3207 } 3208 else 3209 { 3210 pchar_cursor(cc); 3211 if (State & VREPLACE_FLAG) 3212 orig_len = (int)STRLEN(ml_get_cursor()) - 1; 3213 } 3214 replace_pop_ins(); 3215 3216 if (State & VREPLACE_FLAG) 3217 { 3218 // Get the number of screen cells used by the inserted characters 3219 p = ml_get_cursor(); 3220 ins_len = (int)STRLEN(p) - orig_len; 3221 vcol = start_vcol; 3222 for (i = 0; i < ins_len; ++i) 3223 { 3224 vcol += chartabsize(p + i, vcol); 3225 i += (*mb_ptr2len)(p) - 1; 3226 } 3227 vcol -= start_vcol; 3228 3229 // Delete spaces that were inserted after the cursor to keep the 3230 // text aligned. 3231 curwin->w_cursor.col += ins_len; 3232 while (vcol > orig_vcols && gchar_cursor() == ' ') 3233 { 3234 del_char(FALSE); 3235 ++orig_vcols; 3236 } 3237 curwin->w_cursor.col -= ins_len; 3238 } 3239 3240 // mark the buffer as changed and prepare for displaying 3241 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 3242 3243 #ifdef FEAT_PROP_POPUP 3244 if (curbuf->b_has_textprop) 3245 { 3246 size_t len_now = STRLEN(ml_get_curline()); 3247 3248 --text_prop_frozen; 3249 adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col, 3250 (int)(len_now - len_before), 0); 3251 } 3252 #endif 3253 } 3254 else if (cc == 0) 3255 (void)del_char_after_col(limit_col); 3256 } 3257 3258 #if defined(FEAT_RIGHTLEFT) || defined(PROTO) 3259 /* 3260 * Map Hebrew keyboard when in hkmap mode. 3261 */ 3262 int 3263 hkmap(int c) 3264 { 3265 if (p_hkmapp) // phonetic mapping, by Ilya Dogolazky 3266 { 3267 enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD, 3268 KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN, 3269 PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV}; 3270 static char_u map[26] = 3271 {(char_u)hALEF/*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/, 3272 (char_u)DALET/*d*/, (char_u)-1 /*e*/, (char_u)PEIsofit/*f*/, 3273 (char_u)GIMEL/*g*/, (char_u)HEI /*h*/, (char_u)IUD /*i*/, 3274 (char_u)HET /*j*/, (char_u)KOF /*k*/, (char_u)LAMED /*l*/, 3275 (char_u)MEM /*m*/, (char_u)NUN /*n*/, (char_u)SAMEH /*o*/, 3276 (char_u)PEI /*p*/, (char_u)-1 /*q*/, (char_u)RESH /*r*/, 3277 (char_u)ZAIN /*s*/, (char_u)TAV /*t*/, (char_u)TET /*u*/, 3278 (char_u)VAV /*v*/, (char_u)hSHIN/*w*/, (char_u)-1 /*x*/, 3279 (char_u)AIN /*y*/, (char_u)ZADI /*z*/}; 3280 3281 if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z') 3282 return (int)(map[CharOrd(c)] - 1 + p_aleph); 3283 // '-1'='sofit' 3284 else if (c == 'x') 3285 return 'X'; 3286 else if (c == 'q') 3287 return '\''; // {geresh}={'} 3288 else if (c == 246) 3289 return ' '; // \"o --> ' ' for a german keyboard 3290 else if (c == 228) 3291 return ' '; // \"a --> ' ' -- / -- 3292 else if (c == 252) 3293 return ' '; // \"u --> ' ' -- / -- 3294 #ifdef EBCDIC 3295 else if (islower(c)) 3296 #else 3297 // NOTE: islower() does not do the right thing for us on Linux so we 3298 // do this the same was as 5.7 and previous, so it works correctly on 3299 // all systems. Specifically, the e.g. Delete and Arrow keys are 3300 // munged and won't work if e.g. searching for Hebrew text. 3301 else if (c >= 'a' && c <= 'z') 3302 #endif 3303 return (int)(map[CharOrdLow(c)] + p_aleph); 3304 else 3305 return c; 3306 } 3307 else 3308 { 3309 switch (c) 3310 { 3311 case '`': return ';'; 3312 case '/': return '.'; 3313 case '\'': return ','; 3314 case 'q': return '/'; 3315 case 'w': return '\''; 3316 3317 // Hebrew letters - set offset from 'a' 3318 case ',': c = '{'; break; 3319 case '.': c = 'v'; break; 3320 case ';': c = 't'; break; 3321 default: { 3322 static char str[] = "zqbcxlsjphmkwonu ydafe rig"; 3323 3324 #ifdef EBCDIC 3325 // see note about islower() above 3326 if (!islower(c)) 3327 #else 3328 if (c < 'a' || c > 'z') 3329 #endif 3330 return c; 3331 c = str[CharOrdLow(c)]; 3332 break; 3333 } 3334 } 3335 3336 return (int)(CharOrdLow(c) + p_aleph); 3337 } 3338 } 3339 #endif 3340 3341 static void 3342 ins_reg(void) 3343 { 3344 int need_redraw = FALSE; 3345 int regname; 3346 int literally = 0; 3347 int vis_active = VIsual_active; 3348 3349 /* 3350 * If we are going to wait for a character, show a '"'. 3351 */ 3352 pc_status = PC_STATUS_UNSET; 3353 if (redrawing() && !char_avail()) 3354 { 3355 // may need to redraw when no more chars available now 3356 ins_redraw(FALSE); 3357 3358 edit_putchar('"', TRUE); 3359 #ifdef FEAT_CMDL_INFO 3360 add_to_showcmd_c(Ctrl_R); 3361 #endif 3362 } 3363 3364 #ifdef USE_ON_FLY_SCROLL 3365 dont_scroll = TRUE; // disallow scrolling here 3366 #endif 3367 3368 /* 3369 * Don't map the register name. This also prevents the mode message to be 3370 * deleted when ESC is hit. 3371 */ 3372 ++no_mapping; 3373 ++allow_keys; 3374 regname = plain_vgetc(); 3375 LANGMAP_ADJUST(regname, TRUE); 3376 if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) 3377 { 3378 // Get a third key for literal register insertion 3379 literally = regname; 3380 #ifdef FEAT_CMDL_INFO 3381 add_to_showcmd_c(literally); 3382 #endif 3383 regname = plain_vgetc(); 3384 LANGMAP_ADJUST(regname, TRUE); 3385 } 3386 --no_mapping; 3387 --allow_keys; 3388 3389 #ifdef FEAT_EVAL 3390 // Don't call u_sync() while typing the expression or giving an error 3391 // message for it. Only call it explicitly. 3392 ++no_u_sync; 3393 if (regname == '=') 3394 { 3395 pos_T curpos = curwin->w_cursor; 3396 # ifdef HAVE_INPUT_METHOD 3397 int im_on = im_get_status(); 3398 # endif 3399 // Sync undo when evaluating the expression calls setline() or 3400 // append(), so that it can be undone separately. 3401 u_sync_once = 2; 3402 3403 regname = get_expr_register(); 3404 3405 // Cursor may be moved back a column. 3406 curwin->w_cursor = curpos; 3407 check_cursor(); 3408 # ifdef HAVE_INPUT_METHOD 3409 // Restore the Input Method. 3410 if (im_on) 3411 im_set_active(TRUE); 3412 # endif 3413 } 3414 if (regname == NUL || !valid_yank_reg(regname, FALSE)) 3415 { 3416 vim_beep(BO_REG); 3417 need_redraw = TRUE; // remove the '"' 3418 } 3419 else 3420 { 3421 #endif 3422 if (literally == Ctrl_O || literally == Ctrl_P) 3423 { 3424 // Append the command to the redo buffer. 3425 AppendCharToRedobuff(Ctrl_R); 3426 AppendCharToRedobuff(literally); 3427 AppendCharToRedobuff(regname); 3428 3429 do_put(regname, NULL, BACKWARD, 1L, 3430 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); 3431 } 3432 else if (insert_reg(regname, literally) == FAIL) 3433 { 3434 vim_beep(BO_REG); 3435 need_redraw = TRUE; // remove the '"' 3436 } 3437 else if (stop_insert_mode) 3438 // When the '=' register was used and a function was invoked that 3439 // did ":stopinsert" then stuff_empty() returns FALSE but we won't 3440 // insert anything, need to remove the '"' 3441 need_redraw = TRUE; 3442 3443 #ifdef FEAT_EVAL 3444 } 3445 --no_u_sync; 3446 if (u_sync_once == 1) 3447 ins_need_undo = TRUE; 3448 u_sync_once = 0; 3449 #endif 3450 #ifdef FEAT_CMDL_INFO 3451 clear_showcmd(); 3452 #endif 3453 3454 // If the inserted register is empty, we need to remove the '"' 3455 if (need_redraw || stuff_empty()) 3456 edit_unputchar(); 3457 3458 // Disallow starting Visual mode here, would get a weird mode. 3459 if (!vis_active && VIsual_active) 3460 end_visual_mode(); 3461 } 3462 3463 /* 3464 * CTRL-G commands in Insert mode. 3465 */ 3466 static void 3467 ins_ctrl_g(void) 3468 { 3469 int c; 3470 3471 // Right after CTRL-X the cursor will be after the ruler. 3472 setcursor(); 3473 3474 /* 3475 * Don't map the second key. This also prevents the mode message to be 3476 * deleted when ESC is hit. 3477 */ 3478 ++no_mapping; 3479 ++allow_keys; 3480 c = plain_vgetc(); 3481 --no_mapping; 3482 --allow_keys; 3483 switch (c) 3484 { 3485 // CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col 3486 case K_UP: 3487 case Ctrl_K: 3488 case 'k': ins_up(TRUE); 3489 break; 3490 3491 // CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col 3492 case K_DOWN: 3493 case Ctrl_J: 3494 case 'j': ins_down(TRUE); 3495 break; 3496 3497 // CTRL-G u: start new undoable edit 3498 case 'u': u_sync(TRUE); 3499 ins_need_undo = TRUE; 3500 3501 // Need to reset Insstart, esp. because a BS that joins 3502 // a line to the previous one must save for undo. 3503 update_Insstart_orig = FALSE; 3504 Insstart = curwin->w_cursor; 3505 break; 3506 3507 // CTRL-G U: do not break undo with the next char 3508 case 'U': 3509 // Allow one left/right cursor movement with the next char, 3510 // without breaking undo. 3511 dont_sync_undo = MAYBE; 3512 break; 3513 3514 // Unknown CTRL-G command, reserved for future expansion. 3515 default: vim_beep(BO_CTRLG); 3516 } 3517 } 3518 3519 /* 3520 * CTRL-^ in Insert mode. 3521 */ 3522 static void 3523 ins_ctrl_hat(void) 3524 { 3525 if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) 3526 { 3527 // ":lmap" mappings exists, Toggle use of ":lmap" mappings. 3528 if (State & LANGMAP) 3529 { 3530 curbuf->b_p_iminsert = B_IMODE_NONE; 3531 State &= ~LANGMAP; 3532 } 3533 else 3534 { 3535 curbuf->b_p_iminsert = B_IMODE_LMAP; 3536 State |= LANGMAP; 3537 #ifdef HAVE_INPUT_METHOD 3538 im_set_active(FALSE); 3539 #endif 3540 } 3541 } 3542 #ifdef HAVE_INPUT_METHOD 3543 else 3544 { 3545 // There are no ":lmap" mappings, toggle IM 3546 if (im_get_status()) 3547 { 3548 curbuf->b_p_iminsert = B_IMODE_NONE; 3549 im_set_active(FALSE); 3550 } 3551 else 3552 { 3553 curbuf->b_p_iminsert = B_IMODE_IM; 3554 State &= ~LANGMAP; 3555 im_set_active(TRUE); 3556 } 3557 } 3558 #endif 3559 set_iminsert_global(); 3560 showmode(); 3561 #ifdef FEAT_GUI 3562 // may show different cursor shape or color 3563 if (gui.in_use) 3564 gui_update_cursor(TRUE, FALSE); 3565 #endif 3566 #if defined(FEAT_KEYMAP) 3567 // Show/unshow value of 'keymap' in status lines. 3568 status_redraw_curbuf(); 3569 #endif 3570 } 3571 3572 /* 3573 * Handle ESC in insert mode. 3574 * Returns TRUE when leaving insert mode, FALSE when going to repeat the 3575 * insert. 3576 */ 3577 static int 3578 ins_esc( 3579 long *count, 3580 int cmdchar, 3581 int nomove) // don't move cursor 3582 { 3583 int temp; 3584 static int disabled_redraw = FALSE; 3585 3586 #ifdef FEAT_SPELL 3587 check_spell_redraw(); 3588 #endif 3589 3590 temp = curwin->w_cursor.col; 3591 if (disabled_redraw) 3592 { 3593 --RedrawingDisabled; 3594 disabled_redraw = FALSE; 3595 } 3596 if (!arrow_used) 3597 { 3598 /* 3599 * Don't append the ESC for "r<CR>" and "grx". 3600 * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for 3601 * when "count" is non-zero. 3602 */ 3603 if (cmdchar != 'r' && cmdchar != 'v') 3604 AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); 3605 3606 /* 3607 * Repeating insert may take a long time. Check for 3608 * interrupt now and then. 3609 */ 3610 if (*count > 0) 3611 { 3612 line_breakcheck(); 3613 if (got_int) 3614 *count = 0; 3615 } 3616 3617 if (--*count > 0) // repeat what was typed 3618 { 3619 // Vi repeats the insert without replacing characters. 3620 if (vim_strchr(p_cpo, CPO_REPLCNT) != NULL) 3621 State &= ~REPLACE_FLAG; 3622 3623 (void)start_redo_ins(); 3624 if (cmdchar == 'r' || cmdchar == 'v') 3625 stuffRedoReadbuff(ESC_STR); // no ESC in redo buffer 3626 ++RedrawingDisabled; 3627 disabled_redraw = TRUE; 3628 return FALSE; // repeat the insert 3629 } 3630 stop_insert(&curwin->w_cursor, TRUE, nomove); 3631 undisplay_dollar(); 3632 } 3633 3634 if (cmdchar != 'r' && cmdchar != 'v') 3635 ins_apply_autocmds(EVENT_INSERTLEAVEPRE); 3636 3637 // When an autoindent was removed, curswant stays after the 3638 // indent 3639 if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col) 3640 curwin->w_set_curswant = TRUE; 3641 3642 // Remember the last Insert position in the '^ mark. 3643 if ((cmdmod.cmod_flags & CMOD_KEEPJUMPS) == 0) 3644 curbuf->b_last_insert = curwin->w_cursor; 3645 3646 /* 3647 * The cursor should end up on the last inserted character. 3648 * Don't do it for CTRL-O, unless past the end of the line. 3649 */ 3650 if (!nomove 3651 && (curwin->w_cursor.col != 0 3652 || curwin->w_cursor.coladd > 0) 3653 && (restart_edit == NUL 3654 || (gchar_cursor() == NUL && !VIsual_active)) 3655 #ifdef FEAT_RIGHTLEFT 3656 && !revins_on 3657 #endif 3658 ) 3659 { 3660 if (curwin->w_cursor.coladd > 0 || get_ve_flags() == VE_ALL) 3661 { 3662 oneleft(); 3663 if (restart_edit != NUL) 3664 ++curwin->w_cursor.coladd; 3665 } 3666 else 3667 { 3668 --curwin->w_cursor.col; 3669 // Correct cursor for multi-byte character. 3670 if (has_mbyte) 3671 mb_adjust_cursor(); 3672 } 3673 } 3674 3675 #ifdef HAVE_INPUT_METHOD 3676 // Disable IM to allow typing English directly for Normal mode commands. 3677 // When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as 3678 // well). 3679 if (!(State & LANGMAP)) 3680 im_save_status(&curbuf->b_p_iminsert); 3681 im_set_active(FALSE); 3682 #endif 3683 3684 State = NORMAL; 3685 trigger_modechanged(); 3686 // need to position cursor again (e.g. when on a TAB ) 3687 changed_cline_bef_curs(); 3688 3689 setmouse(); 3690 #ifdef CURSOR_SHAPE 3691 ui_cursor_shape(); // may show different cursor shape 3692 #endif 3693 if (!p_ek) 3694 { 3695 #ifdef FEAT_JOB_CHANNEL 3696 ch_log_output = TRUE; 3697 #endif 3698 // Re-enable bracketed paste mode. 3699 out_str(T_BE); 3700 3701 // Re-enable modifyOtherKeys. 3702 out_str(T_CTI); 3703 } 3704 3705 // When recording or for CTRL-O, need to display the new mode. 3706 // Otherwise remove the mode message. 3707 if (reg_recording != 0 || restart_edit != NUL) 3708 showmode(); 3709 else if (p_smd && (got_int || !skip_showmode())) 3710 msg(""); 3711 3712 return TRUE; // exit Insert mode 3713 } 3714 3715 #ifdef FEAT_RIGHTLEFT 3716 /* 3717 * Toggle language: hkmap and revins_on. 3718 * Move to end of reverse inserted text. 3719 */ 3720 static void 3721 ins_ctrl_(void) 3722 { 3723 if (revins_on && revins_chars && revins_scol >= 0) 3724 { 3725 while (gchar_cursor() != NUL && revins_chars--) 3726 ++curwin->w_cursor.col; 3727 } 3728 p_ri = !p_ri; 3729 revins_on = (State == INSERT && p_ri); 3730 if (revins_on) 3731 { 3732 revins_scol = curwin->w_cursor.col; 3733 revins_legal++; 3734 revins_chars = 0; 3735 undisplay_dollar(); 3736 } 3737 else 3738 revins_scol = -1; 3739 p_hkmap = curwin->w_p_rl ^ p_ri; // be consistent! 3740 showmode(); 3741 } 3742 #endif 3743 3744 /* 3745 * If 'keymodel' contains "startsel", may start selection. 3746 * Returns TRUE when a CTRL-O and other keys stuffed. 3747 */ 3748 static int 3749 ins_start_select(int c) 3750 { 3751 if (km_startsel) 3752 switch (c) 3753 { 3754 case K_KHOME: 3755 case K_KEND: 3756 case K_PAGEUP: 3757 case K_KPAGEUP: 3758 case K_PAGEDOWN: 3759 case K_KPAGEDOWN: 3760 # ifdef MACOS_X 3761 case K_LEFT: 3762 case K_RIGHT: 3763 case K_UP: 3764 case K_DOWN: 3765 case K_END: 3766 case K_HOME: 3767 # endif 3768 if (!(mod_mask & MOD_MASK_SHIFT)) 3769 break; 3770 // FALLTHROUGH 3771 case K_S_LEFT: 3772 case K_S_RIGHT: 3773 case K_S_UP: 3774 case K_S_DOWN: 3775 case K_S_END: 3776 case K_S_HOME: 3777 // Start selection right away, the cursor can move with 3778 // CTRL-O when beyond the end of the line. 3779 start_selection(); 3780 3781 // Execute the key in (insert) Select mode. 3782 stuffcharReadbuff(Ctrl_O); 3783 if (mod_mask) 3784 { 3785 char_u buf[4]; 3786 3787 buf[0] = K_SPECIAL; 3788 buf[1] = KS_MODIFIER; 3789 buf[2] = mod_mask; 3790 buf[3] = NUL; 3791 stuffReadbuff(buf); 3792 } 3793 stuffcharReadbuff(c); 3794 return TRUE; 3795 } 3796 return FALSE; 3797 } 3798 3799 /* 3800 * <Insert> key in Insert mode: toggle insert/replace mode. 3801 */ 3802 static void 3803 ins_insert(int replaceState) 3804 { 3805 #ifdef FEAT_EVAL 3806 set_vim_var_string(VV_INSERTMODE, 3807 (char_u *)((State & REPLACE_FLAG) ? "i" 3808 : replaceState == VREPLACE ? "v" 3809 : "r"), 1); 3810 #endif 3811 ins_apply_autocmds(EVENT_INSERTCHANGE); 3812 if (State & REPLACE_FLAG) 3813 State = INSERT | (State & LANGMAP); 3814 else 3815 State = replaceState | (State & LANGMAP); 3816 trigger_modechanged(); 3817 AppendCharToRedobuff(K_INS); 3818 showmode(); 3819 #ifdef CURSOR_SHAPE 3820 ui_cursor_shape(); // may show different cursor shape 3821 #endif 3822 } 3823 3824 /* 3825 * Pressed CTRL-O in Insert mode. 3826 */ 3827 static void 3828 ins_ctrl_o(void) 3829 { 3830 if (State & VREPLACE_FLAG) 3831 restart_edit = 'V'; 3832 else if (State & REPLACE_FLAG) 3833 restart_edit = 'R'; 3834 else 3835 restart_edit = 'I'; 3836 if (virtual_active()) 3837 ins_at_eol = FALSE; // cursor always keeps its column 3838 else 3839 ins_at_eol = (gchar_cursor() == NUL); 3840 } 3841 3842 /* 3843 * If the cursor is on an indent, ^T/^D insert/delete one 3844 * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". 3845 * Always round the indent to 'shiftwidth', this is compatible 3846 * with vi. But vi only supports ^T and ^D after an 3847 * autoindent, we support it everywhere. 3848 */ 3849 static void 3850 ins_shift(int c, int lastc) 3851 { 3852 if (stop_arrow() == FAIL) 3853 return; 3854 AppendCharToRedobuff(c); 3855 3856 /* 3857 * 0^D and ^^D: remove all indent. 3858 */ 3859 if (c == Ctrl_D && (lastc == '0' || lastc == '^') 3860 && curwin->w_cursor.col > 0) 3861 { 3862 --curwin->w_cursor.col; 3863 (void)del_char(FALSE); // delete the '^' or '0' 3864 // In Replace mode, restore the characters that '^' or '0' replaced. 3865 if (State & REPLACE_FLAG) 3866 replace_pop_ins(); 3867 if (lastc == '^') 3868 old_indent = get_indent(); // remember curr. indent 3869 change_indent(INDENT_SET, 0, TRUE, 0, TRUE); 3870 } 3871 else 3872 change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); 3873 3874 if (did_ai && *skipwhite(ml_get_curline()) != NUL) 3875 did_ai = FALSE; 3876 #ifdef FEAT_SMARTINDENT 3877 did_si = FALSE; 3878 can_si = FALSE; 3879 can_si_back = FALSE; 3880 #endif 3881 #ifdef FEAT_CINDENT 3882 can_cindent = FALSE; // no cindenting after ^D or ^T 3883 #endif 3884 } 3885 3886 static void 3887 ins_del(void) 3888 { 3889 int temp; 3890 3891 if (stop_arrow() == FAIL) 3892 return; 3893 if (gchar_cursor() == NUL) // delete newline 3894 { 3895 temp = curwin->w_cursor.col; 3896 if (!can_bs(BS_EOL) // only if "eol" included 3897 || do_join(2, FALSE, TRUE, FALSE, FALSE) == FAIL) 3898 vim_beep(BO_BS); 3899 else 3900 { 3901 curwin->w_cursor.col = temp; 3902 // Adjust orig_line_count in case more lines have been deleted than 3903 // have been added. That makes sure, that open_line() later 3904 // can access all buffer lines correctly 3905 if (State & VREPLACE_FLAG && 3906 orig_line_count > curbuf->b_ml.ml_line_count) 3907 orig_line_count = curbuf->b_ml.ml_line_count; 3908 } 3909 } 3910 else if (del_char(FALSE) == FAIL) // delete char under cursor 3911 vim_beep(BO_BS); 3912 did_ai = FALSE; 3913 #ifdef FEAT_SMARTINDENT 3914 did_si = FALSE; 3915 can_si = FALSE; 3916 can_si_back = FALSE; 3917 #endif 3918 AppendCharToRedobuff(K_DEL); 3919 } 3920 3921 /* 3922 * Delete one character for ins_bs(). 3923 */ 3924 static void 3925 ins_bs_one(colnr_T *vcolp) 3926 { 3927 dec_cursor(); 3928 getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL); 3929 if (State & REPLACE_FLAG) 3930 { 3931 // Don't delete characters before the insert point when in 3932 // Replace mode 3933 if (curwin->w_cursor.lnum != Insstart.lnum 3934 || curwin->w_cursor.col >= Insstart.col) 3935 replace_do_bs(-1); 3936 } 3937 else 3938 (void)del_char(FALSE); 3939 } 3940 3941 /* 3942 * Handle Backspace, delete-word and delete-line in Insert mode. 3943 * Return TRUE when backspace was actually used. 3944 */ 3945 static int 3946 ins_bs( 3947 int c, 3948 int mode, 3949 int *inserted_space_p) 3950 { 3951 linenr_T lnum; 3952 int cc; 3953 int temp = 0; // init for GCC 3954 colnr_T save_col; 3955 colnr_T mincol; 3956 int did_backspace = FALSE; 3957 int in_indent; 3958 int oldState; 3959 int cpc[MAX_MCO]; // composing characters 3960 3961 /* 3962 * can't delete anything in an empty file 3963 * can't backup past first character in buffer 3964 * can't backup past starting point unless 'backspace' > 1 3965 * can backup to a previous line if 'backspace' == 0 3966 */ 3967 if ( BUFEMPTY() 3968 || ( 3969 #ifdef FEAT_RIGHTLEFT 3970 !revins_on && 3971 #endif 3972 ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0) 3973 || (!can_bs(BS_START) 3974 && ((arrow_used 3975 #ifdef FEAT_JOB_CHANNEL 3976 && !bt_prompt(curbuf) 3977 #endif 3978 ) || (curwin->w_cursor.lnum == Insstart_orig.lnum 3979 && curwin->w_cursor.col <= Insstart_orig.col))) 3980 || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0 3981 && curwin->w_cursor.col <= ai_col) 3982 || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0)))) 3983 { 3984 vim_beep(BO_BS); 3985 return FALSE; 3986 } 3987 3988 if (stop_arrow() == FAIL) 3989 return FALSE; 3990 in_indent = inindent(0); 3991 #ifdef FEAT_CINDENT 3992 if (in_indent) 3993 can_cindent = FALSE; 3994 #endif 3995 end_comment_pending = NUL; // After BS, don't auto-end comment 3996 #ifdef FEAT_RIGHTLEFT 3997 if (revins_on) // put cursor after last inserted char 3998 inc_cursor(); 3999 #endif 4000 4001 // Virtualedit: 4002 // BACKSPACE_CHAR eats a virtual space 4003 // BACKSPACE_WORD eats all coladd 4004 // BACKSPACE_LINE eats all coladd and keeps going 4005 if (curwin->w_cursor.coladd > 0) 4006 { 4007 if (mode == BACKSPACE_CHAR) 4008 { 4009 --curwin->w_cursor.coladd; 4010 return TRUE; 4011 } 4012 if (mode == BACKSPACE_WORD) 4013 { 4014 curwin->w_cursor.coladd = 0; 4015 return TRUE; 4016 } 4017 curwin->w_cursor.coladd = 0; 4018 } 4019 4020 /* 4021 * Delete newline! 4022 */ 4023 if (curwin->w_cursor.col == 0) 4024 { 4025 lnum = Insstart.lnum; 4026 if (curwin->w_cursor.lnum == lnum 4027 #ifdef FEAT_RIGHTLEFT 4028 || revins_on 4029 #endif 4030 ) 4031 { 4032 if (u_save((linenr_T)(curwin->w_cursor.lnum - 2), 4033 (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) 4034 return FALSE; 4035 --Insstart.lnum; 4036 Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum)); 4037 } 4038 /* 4039 * In replace mode: 4040 * cc < 0: NL was inserted, delete it 4041 * cc >= 0: NL was replaced, put original characters back 4042 */ 4043 cc = -1; 4044 if (State & REPLACE_FLAG) 4045 cc = replace_pop(); // returns -1 if NL was inserted 4046 /* 4047 * In replace mode, in the line we started replacing, we only move the 4048 * cursor. 4049 */ 4050 if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum) 4051 { 4052 dec_cursor(); 4053 } 4054 else 4055 { 4056 if (!(State & VREPLACE_FLAG) 4057 || curwin->w_cursor.lnum > orig_line_count) 4058 { 4059 temp = gchar_cursor(); // remember current char 4060 --curwin->w_cursor.lnum; 4061 4062 // When "aw" is in 'formatoptions' we must delete the space at 4063 // the end of the line, otherwise the line will be broken 4064 // again when auto-formatting. 4065 if (has_format_option(FO_AUTO) 4066 && has_format_option(FO_WHITE_PAR)) 4067 { 4068 char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, 4069 TRUE); 4070 int len; 4071 4072 len = (int)STRLEN(ptr); 4073 if (len > 0 && ptr[len - 1] == ' ') 4074 ptr[len - 1] = NUL; 4075 } 4076 4077 (void)do_join(2, FALSE, FALSE, FALSE, FALSE); 4078 if (temp == NUL && gchar_cursor() != NUL) 4079 inc_cursor(); 4080 } 4081 else 4082 dec_cursor(); 4083 4084 /* 4085 * In REPLACE mode we have to put back the text that was replaced 4086 * by the NL. On the replace stack is first a NUL-terminated 4087 * sequence of characters that were deleted and then the 4088 * characters that NL replaced. 4089 */ 4090 if (State & REPLACE_FLAG) 4091 { 4092 /* 4093 * Do the next ins_char() in NORMAL state, to 4094 * prevent ins_char() from replacing characters and 4095 * avoiding showmatch(). 4096 */ 4097 oldState = State; 4098 State = NORMAL; 4099 /* 4100 * restore characters (blanks) deleted after cursor 4101 */ 4102 while (cc > 0) 4103 { 4104 save_col = curwin->w_cursor.col; 4105 mb_replace_pop_ins(cc); 4106 curwin->w_cursor.col = save_col; 4107 cc = replace_pop(); 4108 } 4109 // restore the characters that NL replaced 4110 replace_pop_ins(); 4111 State = oldState; 4112 } 4113 } 4114 did_ai = FALSE; 4115 } 4116 else 4117 { 4118 /* 4119 * Delete character(s) before the cursor. 4120 */ 4121 #ifdef FEAT_RIGHTLEFT 4122 if (revins_on) // put cursor on last inserted char 4123 dec_cursor(); 4124 #endif 4125 mincol = 0; 4126 // keep indent 4127 if (mode == BACKSPACE_LINE 4128 && (curbuf->b_p_ai 4129 #ifdef FEAT_CINDENT 4130 || cindent_on() 4131 #endif 4132 ) 4133 #ifdef FEAT_RIGHTLEFT 4134 && !revins_on 4135 #endif 4136 ) 4137 { 4138 save_col = curwin->w_cursor.col; 4139 beginline(BL_WHITE); 4140 if (curwin->w_cursor.col < save_col) 4141 mincol = curwin->w_cursor.col; 4142 curwin->w_cursor.col = save_col; 4143 } 4144 4145 /* 4146 * Handle deleting one 'shiftwidth' or 'softtabstop'. 4147 */ 4148 if ( mode == BACKSPACE_CHAR 4149 && ((p_sta && in_indent) 4150 || ((get_sts_value() != 0 4151 #ifdef FEAT_VARTABS 4152 || tabstop_count(curbuf->b_p_vsts_array) 4153 #endif 4154 ) 4155 && curwin->w_cursor.col > 0 4156 && (*(ml_get_cursor() - 1) == TAB 4157 || (*(ml_get_cursor() - 1) == ' ' 4158 && (!*inserted_space_p 4159 || arrow_used)))))) 4160 { 4161 int ts; 4162 colnr_T vcol; 4163 colnr_T want_vcol; 4164 colnr_T start_vcol; 4165 4166 *inserted_space_p = FALSE; 4167 // Compute the virtual column where we want to be. Since 4168 // 'showbreak' may get in the way, need to get the last column of 4169 // the previous character. 4170 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 4171 start_vcol = vcol; 4172 dec_cursor(); 4173 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); 4174 inc_cursor(); 4175 #ifdef FEAT_VARTABS 4176 if (p_sta && in_indent) 4177 { 4178 ts = (int)get_sw_value(curbuf); 4179 want_vcol = (want_vcol / ts) * ts; 4180 } 4181 else 4182 want_vcol = tabstop_start(want_vcol, get_sts_value(), 4183 curbuf->b_p_vsts_array); 4184 #else 4185 if (p_sta && in_indent) 4186 ts = (int)get_sw_value(curbuf); 4187 else 4188 ts = (int)get_sts_value(); 4189 want_vcol = (want_vcol / ts) * ts; 4190 #endif 4191 4192 // delete characters until we are at or before want_vcol 4193 while (vcol > want_vcol 4194 && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc))) 4195 ins_bs_one(&vcol); 4196 4197 // insert extra spaces until we are at want_vcol 4198 while (vcol < want_vcol) 4199 { 4200 // Remember the first char we inserted 4201 if (curwin->w_cursor.lnum == Insstart_orig.lnum 4202 && curwin->w_cursor.col < Insstart_orig.col) 4203 Insstart_orig.col = curwin->w_cursor.col; 4204 4205 if (State & VREPLACE_FLAG) 4206 ins_char(' '); 4207 else 4208 { 4209 ins_str((char_u *)" "); 4210 if ((State & REPLACE_FLAG)) 4211 replace_push(NUL); 4212 } 4213 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 4214 } 4215 4216 // If we are now back where we started delete one character. Can 4217 // happen when using 'sts' and 'linebreak'. 4218 if (vcol >= start_vcol) 4219 ins_bs_one(&vcol); 4220 } 4221 4222 /* 4223 * Delete up to starting point, start of line or previous word. 4224 */ 4225 else 4226 { 4227 int cclass = 0, prev_cclass = 0; 4228 4229 if (has_mbyte) 4230 cclass = mb_get_class(ml_get_cursor()); 4231 do 4232 { 4233 #ifdef FEAT_RIGHTLEFT 4234 if (!revins_on) // put cursor on char to be deleted 4235 #endif 4236 dec_cursor(); 4237 4238 cc = gchar_cursor(); 4239 // look multi-byte character class 4240 if (has_mbyte) 4241 { 4242 prev_cclass = cclass; 4243 cclass = mb_get_class(ml_get_cursor()); 4244 } 4245 4246 // start of word? 4247 if (mode == BACKSPACE_WORD && !vim_isspace(cc)) 4248 { 4249 mode = BACKSPACE_WORD_NOT_SPACE; 4250 temp = vim_iswordc(cc); 4251 } 4252 // end of word? 4253 else if (mode == BACKSPACE_WORD_NOT_SPACE 4254 && ((vim_isspace(cc) || vim_iswordc(cc) != temp) 4255 || prev_cclass != cclass)) 4256 { 4257 #ifdef FEAT_RIGHTLEFT 4258 if (!revins_on) 4259 #endif 4260 inc_cursor(); 4261 #ifdef FEAT_RIGHTLEFT 4262 else if (State & REPLACE_FLAG) 4263 dec_cursor(); 4264 #endif 4265 break; 4266 } 4267 if (State & REPLACE_FLAG) 4268 replace_do_bs(-1); 4269 else 4270 { 4271 if (enc_utf8 && p_deco) 4272 (void)utfc_ptr2char(ml_get_cursor(), cpc); 4273 (void)del_char(FALSE); 4274 /* 4275 * If there are combining characters and 'delcombine' is set 4276 * move the cursor back. Don't back up before the base 4277 * character. 4278 */ 4279 if (enc_utf8 && p_deco && cpc[0] != NUL) 4280 inc_cursor(); 4281 #ifdef FEAT_RIGHTLEFT 4282 if (revins_chars) 4283 { 4284 revins_chars--; 4285 revins_legal++; 4286 } 4287 if (revins_on && gchar_cursor() == NUL) 4288 break; 4289 #endif 4290 } 4291 // Just a single backspace?: 4292 if (mode == BACKSPACE_CHAR) 4293 break; 4294 } while ( 4295 #ifdef FEAT_RIGHTLEFT 4296 revins_on || 4297 #endif 4298 (curwin->w_cursor.col > mincol 4299 && (can_bs(BS_NOSTOP) 4300 || (curwin->w_cursor.lnum != Insstart_orig.lnum 4301 || curwin->w_cursor.col != Insstart_orig.col) 4302 ))); 4303 } 4304 did_backspace = TRUE; 4305 } 4306 #ifdef FEAT_SMARTINDENT 4307 did_si = FALSE; 4308 can_si = FALSE; 4309 can_si_back = FALSE; 4310 #endif 4311 if (curwin->w_cursor.col <= 1) 4312 did_ai = FALSE; 4313 /* 4314 * It's a little strange to put backspaces into the redo 4315 * buffer, but it makes auto-indent a lot easier to deal 4316 * with. 4317 */ 4318 AppendCharToRedobuff(c); 4319 4320 // If deleted before the insertion point, adjust it 4321 if (curwin->w_cursor.lnum == Insstart_orig.lnum 4322 && curwin->w_cursor.col < Insstart_orig.col) 4323 Insstart_orig.col = curwin->w_cursor.col; 4324 4325 // vi behaviour: the cursor moves backward but the character that 4326 // was there remains visible 4327 // Vim behaviour: the cursor moves backward and the character that 4328 // was there is erased from the screen. 4329 // We can emulate the vi behaviour by pretending there is a dollar 4330 // displayed even when there isn't. 4331 // --pkv Sun Jan 19 01:56:40 EST 2003 4332 if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == -1) 4333 dollar_vcol = curwin->w_virtcol; 4334 4335 #ifdef FEAT_FOLDING 4336 // When deleting a char the cursor line must never be in a closed fold. 4337 // E.g., when 'foldmethod' is indent and deleting the first non-white 4338 // char before a Tab. 4339 if (did_backspace) 4340 foldOpenCursor(); 4341 #endif 4342 4343 return did_backspace; 4344 } 4345 4346 /* 4347 * Handle receiving P_PS: start paste mode. Inserts the following text up to 4348 * P_PE literally. 4349 * When "drop" is TRUE then consume the text and drop it. 4350 */ 4351 int 4352 bracketed_paste(paste_mode_T mode, int drop, garray_T *gap) 4353 { 4354 int c; 4355 char_u buf[NUMBUFLEN + MB_MAXBYTES]; 4356 int idx = 0; 4357 char_u *end = find_termcode((char_u *)"PE"); 4358 int ret_char = -1; 4359 int save_allow_keys = allow_keys; 4360 int save_paste = p_paste; 4361 4362 // If the end code is too long we can't detect it, read everything. 4363 if (end != NULL && STRLEN(end) >= NUMBUFLEN) 4364 end = NULL; 4365 ++no_mapping; 4366 allow_keys = 0; 4367 if (!p_paste) 4368 // Also have the side effects of setting 'paste' to make it work much 4369 // faster. 4370 set_option_value((char_u *)"paste", TRUE, NULL, 0); 4371 4372 for (;;) 4373 { 4374 // When the end is not defined read everything there is. 4375 if (end == NULL && vpeekc() == NUL) 4376 break; 4377 do 4378 c = vgetc(); 4379 while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR); 4380 if (c == NUL || got_int || (ex_normal_busy > 0 && c == Ctrl_C)) 4381 // When CTRL-C was encountered the typeahead will be flushed and we 4382 // won't get the end sequence. Except when using ":normal". 4383 break; 4384 4385 if (has_mbyte) 4386 idx += (*mb_char2bytes)(c, buf + idx); 4387 else 4388 buf[idx++] = c; 4389 buf[idx] = NUL; 4390 if (end != NULL && STRNCMP(buf, end, idx) == 0) 4391 { 4392 if (end[idx] == NUL) 4393 break; // Found the end of paste code. 4394 continue; 4395 } 4396 if (!drop) 4397 { 4398 switch (mode) 4399 { 4400 case PASTE_CMDLINE: 4401 put_on_cmdline(buf, idx, TRUE); 4402 break; 4403 4404 case PASTE_EX: 4405 if (gap != NULL && ga_grow(gap, idx) == OK) 4406 { 4407 mch_memmove((char *)gap->ga_data + gap->ga_len, 4408 buf, (size_t)idx); 4409 gap->ga_len += idx; 4410 } 4411 break; 4412 4413 case PASTE_INSERT: 4414 if (stop_arrow() == OK) 4415 { 4416 c = buf[0]; 4417 if (idx == 1 && (c == CAR || c == K_KENTER || c == NL)) 4418 ins_eol(c); 4419 else 4420 { 4421 ins_char_bytes(buf, idx); 4422 AppendToRedobuffLit(buf, idx); 4423 } 4424 } 4425 break; 4426 4427 case PASTE_ONE_CHAR: 4428 if (ret_char == -1) 4429 { 4430 if (has_mbyte) 4431 ret_char = (*mb_ptr2char)(buf); 4432 else 4433 ret_char = buf[0]; 4434 } 4435 break; 4436 } 4437 } 4438 idx = 0; 4439 } 4440 4441 --no_mapping; 4442 allow_keys = save_allow_keys; 4443 if (!save_paste) 4444 set_option_value((char_u *)"paste", FALSE, NULL, 0); 4445 4446 return ret_char; 4447 } 4448 4449 #if defined(FEAT_GUI_TABLINE) || defined(PROTO) 4450 static void 4451 ins_tabline(int c) 4452 { 4453 // We will be leaving the current window, unless closing another tab. 4454 if (c != K_TABMENU || current_tabmenu != TABLINE_MENU_CLOSE 4455 || (current_tab != 0 && current_tab != tabpage_index(curtab))) 4456 { 4457 undisplay_dollar(); 4458 start_arrow(&curwin->w_cursor); 4459 # ifdef FEAT_CINDENT 4460 can_cindent = TRUE; 4461 # endif 4462 } 4463 4464 if (c == K_TABLINE) 4465 goto_tabpage(current_tab); 4466 else 4467 { 4468 handle_tabmenu(); 4469 redraw_statuslines(); // will redraw the tabline when needed 4470 } 4471 } 4472 #endif 4473 4474 #if defined(FEAT_GUI) || defined(PROTO) 4475 void 4476 ins_scroll(void) 4477 { 4478 pos_T tpos; 4479 4480 undisplay_dollar(); 4481 tpos = curwin->w_cursor; 4482 if (gui_do_scroll()) 4483 { 4484 start_arrow(&tpos); 4485 # ifdef FEAT_CINDENT 4486 can_cindent = TRUE; 4487 # endif 4488 } 4489 } 4490 4491 void 4492 ins_horscroll(void) 4493 { 4494 pos_T tpos; 4495 4496 undisplay_dollar(); 4497 tpos = curwin->w_cursor; 4498 if (gui_do_horiz_scroll(scrollbar_value, FALSE)) 4499 { 4500 start_arrow(&tpos); 4501 # ifdef FEAT_CINDENT 4502 can_cindent = TRUE; 4503 # endif 4504 } 4505 } 4506 #endif 4507 4508 static void 4509 ins_left(void) 4510 { 4511 pos_T tpos; 4512 int end_change = dont_sync_undo == FALSE; // end undoable change 4513 4514 #ifdef FEAT_FOLDING 4515 if ((fdo_flags & FDO_HOR) && KeyTyped) 4516 foldOpenCursor(); 4517 #endif 4518 undisplay_dollar(); 4519 tpos = curwin->w_cursor; 4520 if (oneleft() == OK) 4521 { 4522 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 4523 // Only call start_arrow() when not busy with preediting, it will 4524 // break undo. K_LEFT is inserted in im_correct_cursor(). 4525 if (p_imst == IM_OVER_THE_SPOT || !im_is_preediting()) 4526 #endif 4527 { 4528 start_arrow_with_change(&tpos, end_change); 4529 if (!end_change) 4530 AppendCharToRedobuff(K_LEFT); 4531 } 4532 #ifdef FEAT_RIGHTLEFT 4533 // If exit reversed string, position is fixed 4534 if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) 4535 revins_legal++; 4536 revins_chars++; 4537 #endif 4538 } 4539 4540 /* 4541 * if 'whichwrap' set for cursor in insert mode may go to 4542 * previous line 4543 */ 4544 else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) 4545 { 4546 // always break undo when moving upwards/downwards, else undo may break 4547 start_arrow(&tpos); 4548 --(curwin->w_cursor.lnum); 4549 coladvance((colnr_T)MAXCOL); 4550 curwin->w_set_curswant = TRUE; // so we stay at the end 4551 } 4552 else 4553 vim_beep(BO_CRSR); 4554 dont_sync_undo = FALSE; 4555 } 4556 4557 static void 4558 ins_home(int c) 4559 { 4560 pos_T tpos; 4561 4562 #ifdef FEAT_FOLDING 4563 if ((fdo_flags & FDO_HOR) && KeyTyped) 4564 foldOpenCursor(); 4565 #endif 4566 undisplay_dollar(); 4567 tpos = curwin->w_cursor; 4568 if (c == K_C_HOME) 4569 curwin->w_cursor.lnum = 1; 4570 curwin->w_cursor.col = 0; 4571 curwin->w_cursor.coladd = 0; 4572 curwin->w_curswant = 0; 4573 start_arrow(&tpos); 4574 } 4575 4576 static void 4577 ins_end(int c) 4578 { 4579 pos_T tpos; 4580 4581 #ifdef FEAT_FOLDING 4582 if ((fdo_flags & FDO_HOR) && KeyTyped) 4583 foldOpenCursor(); 4584 #endif 4585 undisplay_dollar(); 4586 tpos = curwin->w_cursor; 4587 if (c == K_C_END) 4588 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 4589 coladvance((colnr_T)MAXCOL); 4590 curwin->w_curswant = MAXCOL; 4591 4592 start_arrow(&tpos); 4593 } 4594 4595 static void 4596 ins_s_left() 4597 { 4598 int end_change = dont_sync_undo == FALSE; // end undoable change 4599 #ifdef FEAT_FOLDING 4600 if ((fdo_flags & FDO_HOR) && KeyTyped) 4601 foldOpenCursor(); 4602 #endif 4603 undisplay_dollar(); 4604 if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0) 4605 { 4606 start_arrow_with_change(&curwin->w_cursor, end_change); 4607 if (!end_change) 4608 AppendCharToRedobuff(K_S_LEFT); 4609 (void)bck_word(1L, FALSE, FALSE); 4610 curwin->w_set_curswant = TRUE; 4611 } 4612 else 4613 vim_beep(BO_CRSR); 4614 dont_sync_undo = FALSE; 4615 } 4616 4617 static void 4618 ins_right(void) 4619 { 4620 int end_change = dont_sync_undo == FALSE; // end undoable change 4621 4622 #ifdef FEAT_FOLDING 4623 if ((fdo_flags & FDO_HOR) && KeyTyped) 4624 foldOpenCursor(); 4625 #endif 4626 undisplay_dollar(); 4627 if (gchar_cursor() != NUL || virtual_active()) 4628 { 4629 start_arrow_with_change(&curwin->w_cursor, end_change); 4630 if (!end_change) 4631 AppendCharToRedobuff(K_RIGHT); 4632 curwin->w_set_curswant = TRUE; 4633 if (virtual_active()) 4634 oneright(); 4635 else 4636 { 4637 if (has_mbyte) 4638 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor()); 4639 else 4640 ++curwin->w_cursor.col; 4641 } 4642 4643 #ifdef FEAT_RIGHTLEFT 4644 revins_legal++; 4645 if (revins_chars) 4646 revins_chars--; 4647 #endif 4648 } 4649 // if 'whichwrap' set for cursor in insert mode, may move the 4650 // cursor to the next line 4651 else if (vim_strchr(p_ww, ']') != NULL 4652 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 4653 { 4654 start_arrow(&curwin->w_cursor); 4655 curwin->w_set_curswant = TRUE; 4656 ++curwin->w_cursor.lnum; 4657 curwin->w_cursor.col = 0; 4658 } 4659 else 4660 vim_beep(BO_CRSR); 4661 dont_sync_undo = FALSE; 4662 } 4663 4664 static void 4665 ins_s_right() 4666 { 4667 int end_change = dont_sync_undo == FALSE; // end undoable change 4668 #ifdef FEAT_FOLDING 4669 if ((fdo_flags & FDO_HOR) && KeyTyped) 4670 foldOpenCursor(); 4671 #endif 4672 undisplay_dollar(); 4673 if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count 4674 || gchar_cursor() != NUL) 4675 { 4676 start_arrow_with_change(&curwin->w_cursor, end_change); 4677 if (!end_change) 4678 AppendCharToRedobuff(K_S_RIGHT); 4679 (void)fwd_word(1L, FALSE, 0); 4680 curwin->w_set_curswant = TRUE; 4681 } 4682 else 4683 vim_beep(BO_CRSR); 4684 dont_sync_undo = FALSE; 4685 } 4686 4687 static void 4688 ins_up( 4689 int startcol) // when TRUE move to Insstart.col 4690 { 4691 pos_T tpos; 4692 linenr_T old_topline = curwin->w_topline; 4693 #ifdef FEAT_DIFF 4694 int old_topfill = curwin->w_topfill; 4695 #endif 4696 4697 undisplay_dollar(); 4698 tpos = curwin->w_cursor; 4699 if (cursor_up(1L, TRUE) == OK) 4700 { 4701 if (startcol) 4702 coladvance(getvcol_nolist(&Insstart)); 4703 if (old_topline != curwin->w_topline 4704 #ifdef FEAT_DIFF 4705 || old_topfill != curwin->w_topfill 4706 #endif 4707 ) 4708 redraw_later(VALID); 4709 start_arrow(&tpos); 4710 #ifdef FEAT_CINDENT 4711 can_cindent = TRUE; 4712 #endif 4713 } 4714 else 4715 vim_beep(BO_CRSR); 4716 } 4717 4718 static void 4719 ins_pageup(void) 4720 { 4721 pos_T tpos; 4722 4723 undisplay_dollar(); 4724 4725 if (mod_mask & MOD_MASK_CTRL) 4726 { 4727 // <C-PageUp>: tab page back 4728 if (first_tabpage->tp_next != NULL) 4729 { 4730 start_arrow(&curwin->w_cursor); 4731 goto_tabpage(-1); 4732 } 4733 return; 4734 } 4735 4736 tpos = curwin->w_cursor; 4737 if (onepage(BACKWARD, 1L) == OK) 4738 { 4739 start_arrow(&tpos); 4740 #ifdef FEAT_CINDENT 4741 can_cindent = TRUE; 4742 #endif 4743 } 4744 else 4745 vim_beep(BO_CRSR); 4746 } 4747 4748 static void 4749 ins_down( 4750 int startcol) // when TRUE move to Insstart.col 4751 { 4752 pos_T tpos; 4753 linenr_T old_topline = curwin->w_topline; 4754 #ifdef FEAT_DIFF 4755 int old_topfill = curwin->w_topfill; 4756 #endif 4757 4758 undisplay_dollar(); 4759 tpos = curwin->w_cursor; 4760 if (cursor_down(1L, TRUE) == OK) 4761 { 4762 if (startcol) 4763 coladvance(getvcol_nolist(&Insstart)); 4764 if (old_topline != curwin->w_topline 4765 #ifdef FEAT_DIFF 4766 || old_topfill != curwin->w_topfill 4767 #endif 4768 ) 4769 redraw_later(VALID); 4770 start_arrow(&tpos); 4771 #ifdef FEAT_CINDENT 4772 can_cindent = TRUE; 4773 #endif 4774 } 4775 else 4776 vim_beep(BO_CRSR); 4777 } 4778 4779 static void 4780 ins_pagedown(void) 4781 { 4782 pos_T tpos; 4783 4784 undisplay_dollar(); 4785 4786 if (mod_mask & MOD_MASK_CTRL) 4787 { 4788 // <C-PageDown>: tab page forward 4789 if (first_tabpage->tp_next != NULL) 4790 { 4791 start_arrow(&curwin->w_cursor); 4792 goto_tabpage(0); 4793 } 4794 return; 4795 } 4796 4797 tpos = curwin->w_cursor; 4798 if (onepage(FORWARD, 1L) == OK) 4799 { 4800 start_arrow(&tpos); 4801 #ifdef FEAT_CINDENT 4802 can_cindent = TRUE; 4803 #endif 4804 } 4805 else 4806 vim_beep(BO_CRSR); 4807 } 4808 4809 #ifdef FEAT_DND 4810 static void 4811 ins_drop(void) 4812 { 4813 do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND); 4814 } 4815 #endif 4816 4817 /* 4818 * Handle TAB in Insert or Replace mode. 4819 * Return TRUE when the TAB needs to be inserted like a normal character. 4820 */ 4821 static int 4822 ins_tab(void) 4823 { 4824 int ind; 4825 int i; 4826 int temp; 4827 4828 if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum) 4829 Insstart_blank_vcol = get_nolist_virtcol(); 4830 if (echeck_abbr(TAB + ABBR_OFF)) 4831 return FALSE; 4832 4833 ind = inindent(0); 4834 #ifdef FEAT_CINDENT 4835 if (ind) 4836 can_cindent = FALSE; 4837 #endif 4838 4839 /* 4840 * When nothing special, insert TAB like a normal character. 4841 */ 4842 if (!curbuf->b_p_et 4843 #ifdef FEAT_VARTABS 4844 && !(p_sta && ind 4845 // These five lines mean 'tabstop' != 'shiftwidth' 4846 && ((tabstop_count(curbuf->b_p_vts_array) > 1) 4847 || (tabstop_count(curbuf->b_p_vts_array) == 1 4848 && tabstop_first(curbuf->b_p_vts_array) 4849 != get_sw_value(curbuf)) 4850 || (tabstop_count(curbuf->b_p_vts_array) == 0 4851 && curbuf->b_p_ts != get_sw_value(curbuf)))) 4852 && tabstop_count(curbuf->b_p_vsts_array) == 0 4853 #else 4854 && !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf)) 4855 #endif 4856 && get_sts_value() == 0) 4857 return TRUE; 4858 4859 if (stop_arrow() == FAIL) 4860 return TRUE; 4861 4862 did_ai = FALSE; 4863 #ifdef FEAT_SMARTINDENT 4864 did_si = FALSE; 4865 can_si = FALSE; 4866 can_si_back = FALSE; 4867 #endif 4868 AppendToRedobuff((char_u *)"\t"); 4869 4870 #ifdef FEAT_VARTABS 4871 if (p_sta && ind) // insert tab in indent, use 'shiftwidth' 4872 { 4873 temp = (int)get_sw_value(curbuf); 4874 temp -= get_nolist_virtcol() % temp; 4875 } 4876 else if (tabstop_count(curbuf->b_p_vsts_array) > 0 || curbuf->b_p_sts != 0) 4877 // use 'softtabstop' when set 4878 temp = tabstop_padding(get_nolist_virtcol(), get_sts_value(), 4879 curbuf->b_p_vsts_array); 4880 else // otherwise use 'tabstop' 4881 temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_ts, 4882 curbuf->b_p_vts_array); 4883 #else 4884 if (p_sta && ind) // insert tab in indent, use 'shiftwidth' 4885 temp = (int)get_sw_value(curbuf); 4886 else if (curbuf->b_p_sts != 0) // use 'softtabstop' when set 4887 temp = (int)get_sts_value(); 4888 else // otherwise use 'tabstop' 4889 temp = (int)curbuf->b_p_ts; 4890 temp -= get_nolist_virtcol() % temp; 4891 #endif 4892 4893 /* 4894 * Insert the first space with ins_char(). It will delete one char in 4895 * replace mode. Insert the rest with ins_str(); it will not delete any 4896 * chars. For VREPLACE mode, we use ins_char() for all characters. 4897 */ 4898 ins_char(' '); 4899 while (--temp > 0) 4900 { 4901 if (State & VREPLACE_FLAG) 4902 ins_char(' '); 4903 else 4904 { 4905 ins_str((char_u *)" "); 4906 if (State & REPLACE_FLAG) // no char replaced 4907 replace_push(NUL); 4908 } 4909 } 4910 4911 /* 4912 * When 'expandtab' not set: Replace spaces by TABs where possible. 4913 */ 4914 #ifdef FEAT_VARTABS 4915 if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0 4916 || get_sts_value() > 0 4917 || (p_sta && ind))) 4918 #else 4919 if (!curbuf->b_p_et && (get_sts_value() || (p_sta && ind))) 4920 #endif 4921 { 4922 char_u *ptr; 4923 char_u *saved_line = NULL; // init for GCC 4924 pos_T pos; 4925 pos_T fpos; 4926 pos_T *cursor; 4927 colnr_T want_vcol, vcol; 4928 int change_col = -1; 4929 int save_list = curwin->w_p_list; 4930 4931 /* 4932 * Get the current line. For VREPLACE mode, don't make real changes 4933 * yet, just work on a copy of the line. 4934 */ 4935 if (State & VREPLACE_FLAG) 4936 { 4937 pos = curwin->w_cursor; 4938 cursor = &pos; 4939 saved_line = vim_strsave(ml_get_curline()); 4940 if (saved_line == NULL) 4941 return FALSE; 4942 ptr = saved_line + pos.col; 4943 } 4944 else 4945 { 4946 ptr = ml_get_cursor(); 4947 cursor = &curwin->w_cursor; 4948 } 4949 4950 // When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. 4951 if (vim_strchr(p_cpo, CPO_LISTWM) == NULL) 4952 curwin->w_p_list = FALSE; 4953 4954 // Find first white before the cursor 4955 fpos = curwin->w_cursor; 4956 while (fpos.col > 0 && VIM_ISWHITE(ptr[-1])) 4957 { 4958 --fpos.col; 4959 --ptr; 4960 } 4961 4962 // In Replace mode, don't change characters before the insert point. 4963 if ((State & REPLACE_FLAG) 4964 && fpos.lnum == Insstart.lnum 4965 && fpos.col < Insstart.col) 4966 { 4967 ptr += Insstart.col - fpos.col; 4968 fpos.col = Insstart.col; 4969 } 4970 4971 // compute virtual column numbers of first white and cursor 4972 getvcol(curwin, &fpos, &vcol, NULL, NULL); 4973 getvcol(curwin, cursor, &want_vcol, NULL, NULL); 4974 4975 // Use as many TABs as possible. Beware of 'breakindent', 'showbreak' 4976 // and 'linebreak' adding extra virtual columns. 4977 while (VIM_ISWHITE(*ptr)) 4978 { 4979 i = lbr_chartabsize(NULL, (char_u *)"\t", vcol); 4980 if (vcol + i > want_vcol) 4981 break; 4982 if (*ptr != TAB) 4983 { 4984 *ptr = TAB; 4985 if (change_col < 0) 4986 { 4987 change_col = fpos.col; // Column of first change 4988 // May have to adjust Insstart 4989 if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col) 4990 Insstart.col = fpos.col; 4991 } 4992 } 4993 ++fpos.col; 4994 ++ptr; 4995 vcol += i; 4996 } 4997 4998 if (change_col >= 0) 4999 { 5000 int repl_off = 0; 5001 char_u *line = ptr; 5002 5003 // Skip over the spaces we need. 5004 while (vcol < want_vcol && *ptr == ' ') 5005 { 5006 vcol += lbr_chartabsize(line, ptr, vcol); 5007 ++ptr; 5008 ++repl_off; 5009 } 5010 if (vcol > want_vcol) 5011 { 5012 // Must have a char with 'showbreak' just before it. 5013 --ptr; 5014 --repl_off; 5015 } 5016 fpos.col += repl_off; 5017 5018 // Delete following spaces. 5019 i = cursor->col - fpos.col; 5020 if (i > 0) 5021 { 5022 #ifdef FEAT_PROP_POPUP 5023 if (!(State & VREPLACE_FLAG)) 5024 { 5025 char_u *newp; 5026 int col; 5027 5028 newp = alloc(curbuf->b_ml.ml_line_len - i); 5029 if (newp == NULL) 5030 return FALSE; 5031 5032 col = ptr - curbuf->b_ml.ml_line_ptr; 5033 if (col > 0) 5034 mch_memmove(newp, ptr - col, col); 5035 mch_memmove(newp + col, ptr + i, 5036 curbuf->b_ml.ml_line_len - col - i); 5037 5038 if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) 5039 vim_free(curbuf->b_ml.ml_line_ptr); 5040 curbuf->b_ml.ml_line_ptr = newp; 5041 curbuf->b_ml.ml_line_len -= i; 5042 curbuf->b_ml.ml_flags = 5043 (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; 5044 } 5045 else 5046 #endif 5047 STRMOVE(ptr, ptr + i); 5048 // correct replace stack. 5049 if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) 5050 for (temp = i; --temp >= 0; ) 5051 replace_join(repl_off); 5052 } 5053 #ifdef FEAT_NETBEANS_INTG 5054 if (netbeans_active()) 5055 { 5056 netbeans_removed(curbuf, fpos.lnum, cursor->col, (long)(i + 1)); 5057 netbeans_inserted(curbuf, fpos.lnum, cursor->col, 5058 (char_u *)"\t", 1); 5059 } 5060 #endif 5061 cursor->col -= i; 5062 5063 /* 5064 * In VREPLACE mode, we haven't changed anything yet. Do it now by 5065 * backspacing over the changed spacing and then inserting the new 5066 * spacing. 5067 */ 5068 if (State & VREPLACE_FLAG) 5069 { 5070 // Backspace from real cursor to change_col 5071 backspace_until_column(change_col); 5072 5073 // Insert each char in saved_line from changed_col to 5074 // ptr-cursor 5075 ins_bytes_len(saved_line + change_col, 5076 cursor->col - change_col); 5077 } 5078 } 5079 5080 if (State & VREPLACE_FLAG) 5081 vim_free(saved_line); 5082 curwin->w_p_list = save_list; 5083 } 5084 5085 return FALSE; 5086 } 5087 5088 /* 5089 * Handle CR or NL in insert mode. 5090 * Return FAIL when out of memory or can't undo. 5091 */ 5092 int 5093 ins_eol(int c) 5094 { 5095 int i; 5096 5097 if (echeck_abbr(c + ABBR_OFF)) 5098 return OK; 5099 if (stop_arrow() == FAIL) 5100 return FAIL; 5101 undisplay_dollar(); 5102 5103 /* 5104 * Strange Vi behaviour: In Replace mode, typing a NL will not delete the 5105 * character under the cursor. Only push a NUL on the replace stack, 5106 * nothing to put back when the NL is deleted. 5107 */ 5108 if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) 5109 replace_push(NUL); 5110 5111 /* 5112 * In VREPLACE mode, a NL replaces the rest of the line, and starts 5113 * replacing the next line, so we push all of the characters left on the 5114 * line onto the replace stack. This is not done here though, it is done 5115 * in open_line(). 5116 */ 5117 5118 // Put cursor on NUL if on the last char and coladd is 1 (happens after 5119 // CTRL-O). 5120 if (virtual_active() && curwin->w_cursor.coladd > 0) 5121 coladvance(getviscol()); 5122 5123 #ifdef FEAT_RIGHTLEFT 5124 // NL in reverse insert will always start in the end of 5125 // current line. 5126 if (revins_on) 5127 curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor()); 5128 #endif 5129 5130 AppendToRedobuff(NL_STR); 5131 i = open_line(FORWARD, 5132 has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0, old_indent); 5133 old_indent = 0; 5134 #ifdef FEAT_CINDENT 5135 can_cindent = TRUE; 5136 #endif 5137 #ifdef FEAT_FOLDING 5138 // When inserting a line the cursor line must never be in a closed fold. 5139 foldOpenCursor(); 5140 #endif 5141 5142 return i; 5143 } 5144 5145 #ifdef FEAT_DIGRAPHS 5146 /* 5147 * Handle digraph in insert mode. 5148 * Returns character still to be inserted, or NUL when nothing remaining to be 5149 * done. 5150 */ 5151 static int 5152 ins_digraph(void) 5153 { 5154 int c; 5155 int cc; 5156 int did_putchar = FALSE; 5157 5158 pc_status = PC_STATUS_UNSET; 5159 if (redrawing() && !char_avail()) 5160 { 5161 // may need to redraw when no more chars available now 5162 ins_redraw(FALSE); 5163 5164 edit_putchar('?', TRUE); 5165 did_putchar = TRUE; 5166 #ifdef FEAT_CMDL_INFO 5167 add_to_showcmd_c(Ctrl_K); 5168 #endif 5169 } 5170 5171 #ifdef USE_ON_FLY_SCROLL 5172 dont_scroll = TRUE; // disallow scrolling here 5173 #endif 5174 5175 // don't map the digraph chars. This also prevents the 5176 // mode message to be deleted when ESC is hit 5177 ++no_mapping; 5178 ++allow_keys; 5179 c = plain_vgetc(); 5180 --no_mapping; 5181 --allow_keys; 5182 if (did_putchar) 5183 // when the line fits in 'columns' the '?' is at the start of the next 5184 // line and will not be removed by the redraw 5185 edit_unputchar(); 5186 5187 if (IS_SPECIAL(c) || mod_mask) // special key 5188 { 5189 #ifdef FEAT_CMDL_INFO 5190 clear_showcmd(); 5191 #endif 5192 insert_special(c, TRUE, FALSE); 5193 return NUL; 5194 } 5195 if (c != ESC) 5196 { 5197 did_putchar = FALSE; 5198 if (redrawing() && !char_avail()) 5199 { 5200 // may need to redraw when no more chars available now 5201 ins_redraw(FALSE); 5202 5203 if (char2cells(c) == 1) 5204 { 5205 ins_redraw(FALSE); 5206 edit_putchar(c, TRUE); 5207 did_putchar = TRUE; 5208 } 5209 #ifdef FEAT_CMDL_INFO 5210 add_to_showcmd_c(c); 5211 #endif 5212 } 5213 ++no_mapping; 5214 ++allow_keys; 5215 cc = plain_vgetc(); 5216 --no_mapping; 5217 --allow_keys; 5218 if (did_putchar) 5219 // when the line fits in 'columns' the '?' is at the start of the 5220 // next line and will not be removed by a redraw 5221 edit_unputchar(); 5222 if (cc != ESC) 5223 { 5224 AppendToRedobuff((char_u *)CTRL_V_STR); 5225 c = digraph_get(c, cc, TRUE); 5226 #ifdef FEAT_CMDL_INFO 5227 clear_showcmd(); 5228 #endif 5229 return c; 5230 } 5231 } 5232 #ifdef FEAT_CMDL_INFO 5233 clear_showcmd(); 5234 #endif 5235 return NUL; 5236 } 5237 #endif 5238 5239 /* 5240 * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. 5241 * Returns the char to be inserted, or NUL if none found. 5242 */ 5243 int 5244 ins_copychar(linenr_T lnum) 5245 { 5246 int c; 5247 int temp; 5248 char_u *ptr, *prev_ptr; 5249 char_u *line; 5250 5251 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) 5252 { 5253 vim_beep(BO_COPY); 5254 return NUL; 5255 } 5256 5257 // try to advance to the cursor column 5258 temp = 0; 5259 line = ptr = ml_get(lnum); 5260 prev_ptr = ptr; 5261 validate_virtcol(); 5262 while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) 5263 { 5264 prev_ptr = ptr; 5265 temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp); 5266 } 5267 if ((colnr_T)temp > curwin->w_virtcol) 5268 ptr = prev_ptr; 5269 5270 c = (*mb_ptr2char)(ptr); 5271 if (c == NUL) 5272 vim_beep(BO_COPY); 5273 return c; 5274 } 5275 5276 /* 5277 * CTRL-Y or CTRL-E typed in Insert mode. 5278 */ 5279 static int 5280 ins_ctrl_ey(int tc) 5281 { 5282 int c = tc; 5283 5284 if (ctrl_x_mode_scroll()) 5285 { 5286 if (c == Ctrl_Y) 5287 scrolldown_clamp(); 5288 else 5289 scrollup_clamp(); 5290 redraw_later(VALID); 5291 } 5292 else 5293 { 5294 c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1)); 5295 if (c != NUL) 5296 { 5297 long tw_save; 5298 5299 // The character must be taken literally, insert like it 5300 // was typed after a CTRL-V, and pretend 'textwidth' 5301 // wasn't set. Digits, 'o' and 'x' are special after a 5302 // CTRL-V, don't use it for these. 5303 if (c < 256 && !isalnum(c)) 5304 AppendToRedobuff((char_u *)CTRL_V_STR); // CTRL-V 5305 tw_save = curbuf->b_p_tw; 5306 curbuf->b_p_tw = -1; 5307 insert_special(c, TRUE, FALSE); 5308 curbuf->b_p_tw = tw_save; 5309 #ifdef FEAT_RIGHTLEFT 5310 revins_chars++; 5311 revins_legal++; 5312 #endif 5313 c = Ctrl_V; // pretend CTRL-V is last character 5314 auto_format(FALSE, TRUE); 5315 } 5316 } 5317 return c; 5318 } 5319 5320 /* 5321 * Get the value that w_virtcol would have when 'list' is off. 5322 * Unless 'cpo' contains the 'L' flag. 5323 */ 5324 colnr_T 5325 get_nolist_virtcol(void) 5326 { 5327 // check validity of cursor in current buffer 5328 if (curwin->w_buffer == NULL 5329 || curwin->w_buffer->b_ml.ml_mfp == NULL 5330 || curwin->w_cursor.lnum > curwin->w_buffer->b_ml.ml_line_count) 5331 return 0; 5332 if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 5333 return getvcol_nolist(&curwin->w_cursor); 5334 validate_virtcol(); 5335 return curwin->w_virtcol; 5336 } 5337 5338 #if defined(FEAT_EVAL) 5339 /* 5340 * Handle the InsertCharPre autocommand. 5341 * "c" is the character that was typed. 5342 * Return a pointer to allocated memory with the replacement string. 5343 * Return NULL to continue inserting "c". 5344 */ 5345 static char_u * 5346 do_insert_char_pre(int c) 5347 { 5348 char_u *res; 5349 char_u buf[MB_MAXBYTES + 1]; 5350 int save_State = State; 5351 5352 // Return quickly when there is nothing to do. 5353 if (!has_insertcharpre()) 5354 return NULL; 5355 5356 if (has_mbyte) 5357 buf[(*mb_char2bytes)(c, buf)] = NUL; 5358 else 5359 { 5360 buf[0] = c; 5361 buf[1] = NUL; 5362 } 5363 5364 // Lock the text to avoid weird things from happening. 5365 ++textwinlock; 5366 set_vim_var_string(VV_CHAR, buf, -1); // set v:char 5367 5368 res = NULL; 5369 if (ins_apply_autocmds(EVENT_INSERTCHARPRE)) 5370 { 5371 // Get the value of v:char. It may be empty or more than one 5372 // character. Only use it when changed, otherwise continue with the 5373 // original character to avoid breaking autoindent. 5374 if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) 5375 res = vim_strsave(get_vim_var_str(VV_CHAR)); 5376 } 5377 5378 set_vim_var_string(VV_CHAR, NULL, -1); // clear v:char 5379 --textwinlock; 5380 5381 // Restore the State, it may have been changed. 5382 State = save_State; 5383 5384 return res; 5385 } 5386 #endif 5387 5388 #if defined(FEAT_CINDENT) || defined(PROTO) 5389 int 5390 get_can_cindent(void) 5391 { 5392 return can_cindent; 5393 } 5394 5395 void 5396 set_can_cindent(int val) 5397 { 5398 can_cindent = val; 5399 } 5400 #endif 5401 5402 /* 5403 * Trigger "event" and take care of fixing undo. 5404 */ 5405 int 5406 ins_apply_autocmds(event_T event) 5407 { 5408 varnumber_T tick = CHANGEDTICK(curbuf); 5409 int r; 5410 5411 r = apply_autocmds(event, NULL, NULL, FALSE, curbuf); 5412 5413 // If u_savesub() was called then we are not prepared to start 5414 // a new line. Call u_save() with no contents to fix that. 5415 // Except when leaving Insert mode. 5416 if (event != EVENT_INSERTLEAVE && tick != CHANGEDTICK(curbuf)) 5417 u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); 5418 5419 return r; 5420 } 5421