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