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