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