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