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