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