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