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