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