1 /* vi:set ts=8 sts=4 sw=4: 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 #ifdef FEAT_INS_EXPAND 17 /* 18 * definitions used for CTRL-X submode 19 */ 20 #define CTRL_X_WANT_IDENT 0x100 21 22 #define CTRL_X_NOT_DEFINED_YET 1 23 #define CTRL_X_SCROLL 2 24 #define CTRL_X_WHOLE_LINE 3 25 #define CTRL_X_FILES 4 26 #define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT) 27 #define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT) 28 #define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT) 29 #define CTRL_X_FINISHED 8 30 #define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT) 31 #define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT) 32 #define CTRL_X_CMDLINE 11 33 #define CTRL_X_FUNCTION 12 34 #define CTRL_X_OCCULT 13 35 #define CTRL_X_SPELL 14 36 #define CTRL_X_LOCAL_MSG 15 /* only used in "ctrl_x_msgs" */ 37 38 #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT] 39 40 static char *ctrl_x_msgs[] = 41 { 42 N_(" Keyword completion (^N^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */ 43 N_(" ^X mode (^]^D^E^F^I^K^L^N^O^P^S^U^V^Y)"), 44 NULL, 45 N_(" Whole line completion (^L^N^P)"), 46 N_(" File name completion (^F^N^P)"), 47 N_(" Tag completion (^]^N^P)"), 48 N_(" Path pattern completion (^N^P)"), 49 N_(" Definition completion (^D^N^P)"), 50 NULL, 51 N_(" Dictionary completion (^K^N^P)"), 52 N_(" Thesaurus completion (^T^N^P)"), 53 N_(" Command-line completion (^V^N^P)"), 54 N_(" User defined completion (^U^N^P)"), 55 N_(" Occult completion (^O^N^P)"), 56 N_(" Spelling suggestion (^S^N^P)"), 57 N_(" Keyword Local completion (^N^P)"), 58 }; 59 60 static char_u e_hitend[] = N_("Hit end of paragraph"); 61 62 /* 63 * Structure used to store one match for insert completion. 64 */ 65 typedef struct Completion compl_T; 66 struct Completion 67 { 68 compl_T *cp_next; 69 compl_T *cp_prev; 70 char_u *cp_str; /* matched text */ 71 char_u *cp_fname; /* file containing the match */ 72 int cp_flags; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */ 73 int cp_number; /* sequence number */ 74 }; 75 76 #define ORIGINAL_TEXT (1) /* the original text when the expansion begun */ 77 #define FREE_FNAME (2) 78 79 /* 80 * All the current matches are stored in a list. 81 * "compl_first_match" points to the start of the list. 82 * "compl_curr_match" points to the currently selected entry. 83 * "compl_shown_match" is different from compl_curr_match during 84 * ins_compl_get_exp(). 85 */ 86 static compl_T *compl_first_match = NULL; 87 static compl_T *compl_curr_match = NULL; 88 static compl_T *compl_shown_match = NULL; 89 90 /* When the first completion is done "compl_started" is set. When it's 91 * FALSE the word to be completed must be located. */ 92 static int compl_started = FALSE; 93 94 static int compl_matches = 0; 95 static char_u *compl_pattern = NULL; 96 static int compl_direction = FORWARD; 97 static int compl_shows_dir = FORWARD; 98 static int compl_pending = FALSE; 99 static pos_T compl_startpos; 100 static colnr_T compl_col = 0; /* column where the text starts 101 * that is being completed */ 102 static int save_sm = -1; 103 static char_u *compl_orig_text = NULL; /* text as it was before 104 * completion started */ 105 static int compl_cont_mode = 0; 106 static expand_T compl_xp; 107 108 static void ins_ctrl_x __ARGS((void)); 109 static int has_compl_option __ARGS((int dict_opt)); 110 static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir)); 111 static int ins_compl_make_cyclic __ARGS((void)); 112 static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags, int thesaurus)); 113 static void ins_compl_free __ARGS((void)); 114 static void ins_compl_clear __ARGS((void)); 115 static void ins_compl_prep __ARGS((int c)); 116 static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag)); 117 static int ins_compl_get_exp __ARGS((pos_T *ini, int dir)); 118 static void ins_compl_delete __ARGS((void)); 119 static void ins_compl_insert __ARGS((void)); 120 static int ins_compl_next __ARGS((int allow_get_expansion)); 121 static int ins_complete __ARGS((int c)); 122 static int quote_meta __ARGS((char_u *dest, char_u *str, int len)); 123 #endif /* FEAT_INS_EXPAND */ 124 125 #define BACKSPACE_CHAR 1 126 #define BACKSPACE_WORD 2 127 #define BACKSPACE_WORD_NOT_SPACE 3 128 #define BACKSPACE_LINE 4 129 130 static void ins_redraw __ARGS((void)); 131 static void ins_ctrl_v __ARGS((void)); 132 static void undisplay_dollar __ARGS((void)); 133 static void insert_special __ARGS((int, int, int)); 134 static void check_auto_format __ARGS((int)); 135 static void redo_literal __ARGS((int c)); 136 static void start_arrow __ARGS((pos_T *end_insert_pos)); 137 #ifdef FEAT_SYN_HL 138 static void check_spell_redraw __ARGS((void)); 139 #endif 140 static void stop_insert __ARGS((pos_T *end_insert_pos, int esc)); 141 static int echeck_abbr __ARGS((int)); 142 static void replace_push_off __ARGS((int c)); 143 static int replace_pop __ARGS((void)); 144 static void replace_join __ARGS((int off)); 145 static void replace_pop_ins __ARGS((void)); 146 #ifdef FEAT_MBYTE 147 static void mb_replace_pop_ins __ARGS((int cc)); 148 #endif 149 static void replace_flush __ARGS((void)); 150 static void replace_do_bs __ARGS((void)); 151 #ifdef FEAT_CINDENT 152 static int cindent_on __ARGS((void)); 153 #endif 154 static void ins_reg __ARGS((void)); 155 static void ins_ctrl_g __ARGS((void)); 156 static void ins_ctrl_hat __ARGS((void)); 157 static int ins_esc __ARGS((long *count, int cmdchar, int nomove)); 158 #ifdef FEAT_RIGHTLEFT 159 static void ins_ctrl_ __ARGS((void)); 160 #endif 161 #ifdef FEAT_VISUAL 162 static int ins_start_select __ARGS((int c)); 163 #endif 164 static void ins_insert __ARGS((int replaceState)); 165 static void ins_ctrl_o __ARGS((void)); 166 static void ins_shift __ARGS((int c, int lastc)); 167 static void ins_del __ARGS((void)); 168 static int ins_bs __ARGS((int c, int mode, int *inserted_space_p)); 169 #ifdef FEAT_MOUSE 170 static void ins_mouse __ARGS((int c)); 171 static void ins_mousescroll __ARGS((int up)); 172 #endif 173 static void ins_left __ARGS((void)); 174 static void ins_home __ARGS((int c)); 175 static void ins_end __ARGS((int c)); 176 static void ins_s_left __ARGS((void)); 177 static void ins_right __ARGS((void)); 178 static void ins_s_right __ARGS((void)); 179 static void ins_up __ARGS((int startcol)); 180 static void ins_pageup __ARGS((void)); 181 static void ins_down __ARGS((int startcol)); 182 static void ins_pagedown __ARGS((void)); 183 #ifdef FEAT_DND 184 static void ins_drop __ARGS((void)); 185 #endif 186 static int ins_tab __ARGS((void)); 187 static int ins_eol __ARGS((int c)); 188 #ifdef FEAT_DIGRAPHS 189 static int ins_digraph __ARGS((void)); 190 #endif 191 static int ins_copychar __ARGS((linenr_T lnum)); 192 static int ins_ctrl_ey __ARGS((int tc)); 193 #ifdef FEAT_SMARTINDENT 194 static void ins_try_si __ARGS((int c)); 195 #endif 196 static colnr_T get_nolist_virtcol __ARGS((void)); 197 198 static colnr_T Insstart_textlen; /* length of line when insert started */ 199 static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ 200 201 static char_u *last_insert = NULL; /* the text of the previous insert, 202 K_SPECIAL and CSI are escaped */ 203 static int last_insert_skip; /* nr of chars in front of previous insert */ 204 static int new_insert_skip; /* nr of chars in front of current insert */ 205 206 #ifdef FEAT_CINDENT 207 static int can_cindent; /* may do cindenting on this line */ 208 #endif 209 210 static int old_indent = 0; /* for ^^D command in insert mode */ 211 212 #ifdef FEAT_RIGHTLEFT 213 static int revins_on; /* reverse insert mode on */ 214 static int revins_chars; /* how much to skip after edit */ 215 static int revins_legal; /* was the last char 'legal'? */ 216 static int revins_scol; /* start column of revins session */ 217 #endif 218 219 #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC) 220 static short previous_script = smRoman; 221 #endif 222 223 static int ins_need_undo; /* call u_save() before inserting a 224 char. Set when edit() is called. 225 after that arrow_used is used. */ 226 227 static int did_add_space = FALSE; /* auto_format() added an extra space 228 under the cursor */ 229 230 /* 231 * edit(): Start inserting text. 232 * 233 * "cmdchar" can be: 234 * 'i' normal insert command 235 * 'a' normal append command 236 * 'R' replace command 237 * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo, 238 * but still only one <CR> is inserted. The <Esc> is not used for redo. 239 * 'g' "gI" command. 240 * 'V' "gR" command for Virtual Replace mode. 241 * 'v' "gr" command for single character Virtual Replace mode. 242 * 243 * This function is not called recursively. For CTRL-O commands, it returns 244 * and lets the caller handle the Normal-mode command. 245 * 246 * Return TRUE if a CTRL-O command caused the return (insert mode pending). 247 */ 248 int 249 edit(cmdchar, startln, count) 250 int cmdchar; 251 int startln; /* if set, insert at start of line */ 252 long count; 253 { 254 int c = 0; 255 char_u *ptr; 256 int lastc; 257 colnr_T mincol; 258 static linenr_T o_lnum = 0; 259 int i; 260 int did_backspace = TRUE; /* previous char was backspace */ 261 #ifdef FEAT_CINDENT 262 int line_is_white = FALSE; /* line is empty before insert */ 263 #endif 264 linenr_T old_topline = 0; /* topline before insertion */ 265 #ifdef FEAT_DIFF 266 int old_topfill = -1; 267 #endif 268 int inserted_space = FALSE; /* just inserted a space */ 269 int replaceState = REPLACE; 270 int did_restart_edit = restart_edit; 271 int nomove = FALSE; /* don't move cursor on return */ 272 273 /* sleep before redrawing, needed for "CTRL-O :" that results in an 274 * error message */ 275 check_for_delay(TRUE); 276 277 #ifdef HAVE_SANDBOX 278 /* Don't allow inserting in the sandbox. */ 279 if (sandbox != 0) 280 { 281 EMSG(_(e_sandbox)); 282 return FALSE; 283 } 284 #endif 285 286 #ifdef FEAT_INS_EXPAND 287 ins_compl_clear(); /* clear stuff for CTRL-X mode */ 288 #endif 289 290 #ifdef FEAT_AUTOCMD 291 /* 292 * Trigger InsertEnter autocommands. Do not do this for "r<CR>" or "grx". 293 */ 294 if (cmdchar != 'r' && cmdchar != 'v') 295 { 296 if (cmdchar == 'R') 297 ptr = (char_u *)"r"; 298 else if (cmdchar == 'V') 299 ptr = (char_u *)"v"; 300 else 301 ptr = (char_u *)"i"; 302 set_vim_var_string(VV_INSERTMODE, ptr, 1); 303 apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf); 304 } 305 #endif 306 307 #ifdef FEAT_MOUSE 308 /* 309 * When doing a paste with the middle mouse button, Insstart is set to 310 * where the paste started. 311 */ 312 if (where_paste_started.lnum != 0) 313 Insstart = where_paste_started; 314 else 315 #endif 316 { 317 Insstart = curwin->w_cursor; 318 if (startln) 319 Insstart.col = 0; 320 } 321 Insstart_textlen = linetabsize(ml_get_curline()); 322 Insstart_blank_vcol = MAXCOL; 323 if (!did_ai) 324 ai_col = 0; 325 326 if (cmdchar != NUL && restart_edit == 0) 327 { 328 ResetRedobuff(); 329 AppendNumberToRedobuff(count); 330 #ifdef FEAT_VREPLACE 331 if (cmdchar == 'V' || cmdchar == 'v') 332 { 333 /* "gR" or "gr" command */ 334 AppendCharToRedobuff('g'); 335 AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R'); 336 } 337 else 338 #endif 339 { 340 AppendCharToRedobuff(cmdchar); 341 if (cmdchar == 'g') /* "gI" command */ 342 AppendCharToRedobuff('I'); 343 else if (cmdchar == 'r') /* "r<CR>" command */ 344 count = 1; /* insert only one <CR> */ 345 } 346 } 347 348 if (cmdchar == 'R') 349 { 350 #ifdef FEAT_FKMAP 351 if (p_fkmap && p_ri) 352 { 353 beep_flush(); 354 EMSG(farsi_text_3); /* encoded in Farsi */ 355 State = INSERT; 356 } 357 else 358 #endif 359 State = REPLACE; 360 } 361 #ifdef FEAT_VREPLACE 362 else if (cmdchar == 'V' || cmdchar == 'v') 363 { 364 State = VREPLACE; 365 replaceState = VREPLACE; 366 orig_line_count = curbuf->b_ml.ml_line_count; 367 vr_lines_changed = 1; 368 } 369 #endif 370 else 371 State = INSERT; 372 373 stop_insert_mode = FALSE; 374 375 /* 376 * Need to recompute the cursor position, it might move when the cursor is 377 * on a TAB or special character. 378 */ 379 curs_columns(TRUE); 380 381 /* 382 * Enable langmap or IME, indicated by 'iminsert'. 383 * Note that IME may enabled/disabled without us noticing here, thus the 384 * 'iminsert' value may not reflect what is actually used. It is updated 385 * when hitting <Esc>. 386 */ 387 if (curbuf->b_p_iminsert == B_IMODE_LMAP) 388 State |= LANGMAP; 389 #ifdef USE_IM_CONTROL 390 im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); 391 #endif 392 393 #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC) 394 KeyScript(previous_script); 395 #endif 396 397 #ifdef FEAT_MOUSE 398 setmouse(); 399 #endif 400 #ifdef FEAT_CMDL_INFO 401 clear_showcmd(); 402 #endif 403 #ifdef FEAT_RIGHTLEFT 404 /* there is no reverse replace mode */ 405 revins_on = (State == INSERT && p_ri); 406 if (revins_on) 407 undisplay_dollar(); 408 revins_chars = 0; 409 revins_legal = 0; 410 revins_scol = -1; 411 #endif 412 413 /* 414 * Handle restarting Insert mode. 415 * Don't do this for "CTRL-O ." (repeat an insert): we get here with 416 * restart_edit non-zero, and something in the stuff buffer. 417 */ 418 if (restart_edit != 0 && stuff_empty()) 419 { 420 #ifdef FEAT_MOUSE 421 /* 422 * After a paste we consider text typed to be part of the insert for 423 * the pasted text. You can backspace over the pasted text too. 424 */ 425 if (where_paste_started.lnum) 426 arrow_used = FALSE; 427 else 428 #endif 429 arrow_used = TRUE; 430 restart_edit = 0; 431 432 /* 433 * If the cursor was after the end-of-line before the CTRL-O and it is 434 * now at the end-of-line, put it after the end-of-line (this is not 435 * correct in very rare cases). 436 * Also do this if curswant is greater than the current virtual 437 * column. Eg after "^O$" or "^O80|". 438 */ 439 validate_virtcol(); 440 update_curswant(); 441 if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum) 442 || curwin->w_curswant > curwin->w_virtcol) 443 && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL) 444 { 445 if (ptr[1] == NUL) 446 ++curwin->w_cursor.col; 447 #ifdef FEAT_MBYTE 448 else if (has_mbyte) 449 { 450 i = (*mb_ptr2len)(ptr); 451 if (ptr[i] == NUL) 452 curwin->w_cursor.col += i; 453 } 454 #endif 455 } 456 ins_at_eol = FALSE; 457 } 458 else 459 arrow_used = FALSE; 460 461 /* we are in insert mode now, don't need to start it anymore */ 462 need_start_insertmode = FALSE; 463 464 /* Need to save the line for undo before inserting the first char. */ 465 ins_need_undo = TRUE; 466 467 #ifdef FEAT_MOUSE 468 where_paste_started.lnum = 0; 469 #endif 470 #ifdef FEAT_CINDENT 471 can_cindent = TRUE; 472 #endif 473 #ifdef FEAT_FOLDING 474 /* The cursor line is not in a closed fold, unless 'insertmode' is set or 475 * restarting. */ 476 if (!p_im && did_restart_edit == 0) 477 foldOpenCursor(); 478 #endif 479 480 /* 481 * If 'showmode' is set, show the current (insert/replace/..) mode. 482 * A warning message for changing a readonly file is given here, before 483 * actually changing anything. It's put after the mode, if any. 484 */ 485 i = 0; 486 if (p_smd) 487 i = showmode(); 488 489 if (!p_im && did_restart_edit == 0) 490 change_warning(i + 1); 491 492 #ifdef CURSOR_SHAPE 493 ui_cursor_shape(); /* may show different cursor shape */ 494 #endif 495 #ifdef FEAT_DIGRAPHS 496 do_digraph(-1); /* clear digraphs */ 497 #endif 498 499 /* 500 * Get the current length of the redo buffer, those characters have to be 501 * skipped if we want to get to the inserted characters. 502 */ 503 ptr = get_inserted(); 504 if (ptr == NULL) 505 new_insert_skip = 0; 506 else 507 { 508 new_insert_skip = (int)STRLEN(ptr); 509 vim_free(ptr); 510 } 511 512 old_indent = 0; 513 514 /* 515 * Main loop in Insert mode: repeat until Insert mode is left. 516 */ 517 for (;;) 518 { 519 #ifdef FEAT_RIGHTLEFT 520 if (!revins_legal) 521 revins_scol = -1; /* reset on illegal motions */ 522 else 523 revins_legal = 0; 524 #endif 525 if (arrow_used) /* don't repeat insert when arrow key used */ 526 count = 0; 527 528 if (stop_insert_mode) 529 { 530 /* ":stopinsert" used or 'insertmode' reset */ 531 count = 0; 532 goto doESCkey; 533 } 534 535 /* set curwin->w_curswant for next K_DOWN or K_UP */ 536 if (!arrow_used) 537 curwin->w_set_curswant = TRUE; 538 539 /* If there is no typeahead may check for timestamps (e.g., for when a 540 * menu invoked a shell command). */ 541 if (stuff_empty()) 542 { 543 did_check_timestamps = FALSE; 544 if (need_check_timestamps) 545 check_timestamps(FALSE); 546 } 547 548 /* 549 * When emsg() was called msg_scroll will have been set. 550 */ 551 msg_scroll = FALSE; 552 553 #ifdef FEAT_GUI 554 /* When 'mousefocus' is set a mouse movement may have taken us to 555 * another window. "need_mouse_correct" may then be set because of an 556 * autocommand. */ 557 if (need_mouse_correct) 558 gui_mouse_correct(); 559 #endif 560 561 #ifdef FEAT_FOLDING 562 /* Open fold at the cursor line, according to 'foldopen'. */ 563 if (fdo_flags & FDO_INSERT) 564 foldOpenCursor(); 565 /* Close folds where the cursor isn't, according to 'foldclose' */ 566 if (!char_avail()) 567 foldCheckClose(); 568 #endif 569 570 /* 571 * If we inserted a character at the last position of the last line in 572 * the window, scroll the window one line up. This avoids an extra 573 * redraw. 574 * This is detected when the cursor column is smaller after inserting 575 * something. 576 * Don't do this when the topline changed already, it has 577 * already been adjusted (by insertchar() calling open_line())). 578 */ 579 if (curbuf->b_mod_set 580 && curwin->w_p_wrap 581 && !did_backspace 582 && curwin->w_topline == old_topline 583 #ifdef FEAT_DIFF 584 && curwin->w_topfill == old_topfill 585 #endif 586 ) 587 { 588 mincol = curwin->w_wcol; 589 validate_cursor_col(); 590 591 if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts 592 && curwin->w_wrow == W_WINROW(curwin) 593 + curwin->w_height - 1 - p_so 594 && (curwin->w_cursor.lnum != curwin->w_topline 595 #ifdef FEAT_DIFF 596 || curwin->w_topfill > 0 597 #endif 598 )) 599 { 600 #ifdef FEAT_DIFF 601 if (curwin->w_topfill > 0) 602 --curwin->w_topfill; 603 else 604 #endif 605 #ifdef FEAT_FOLDING 606 if (hasFolding(curwin->w_topline, NULL, &old_topline)) 607 set_topline(curwin, old_topline + 1); 608 else 609 #endif 610 set_topline(curwin, curwin->w_topline + 1); 611 } 612 } 613 614 /* May need to adjust w_topline to show the cursor. */ 615 update_topline(); 616 617 did_backspace = FALSE; 618 619 validate_cursor(); /* may set must_redraw */ 620 621 /* 622 * Redraw the display when no characters are waiting. 623 * Also shows mode, ruler and positions cursor. 624 */ 625 ins_redraw(); 626 627 #ifdef FEAT_SCROLLBIND 628 if (curwin->w_p_scb) 629 do_check_scrollbind(TRUE); 630 #endif 631 632 update_curswant(); 633 old_topline = curwin->w_topline; 634 #ifdef FEAT_DIFF 635 old_topfill = curwin->w_topfill; 636 #endif 637 638 #ifdef USE_ON_FLY_SCROLL 639 dont_scroll = FALSE; /* allow scrolling here */ 640 #endif 641 642 /* 643 * Get a character for Insert mode. 644 */ 645 lastc = c; /* remember previous char for CTRL-D */ 646 c = safe_vgetc(); 647 648 #ifdef FEAT_RIGHTLEFT 649 if (p_hkmap && KeyTyped) 650 c = hkmap(c); /* Hebrew mode mapping */ 651 #endif 652 #ifdef FEAT_FKMAP 653 if (p_fkmap && KeyTyped) 654 c = fkmap(c); /* Farsi mode mapping */ 655 #endif 656 657 #ifdef FEAT_INS_EXPAND 658 /* Prepare for or stop CTRL-X mode. This doesn't do completion, but 659 * it does fix up the text when finishing completion. */ 660 if (c != K_IGNORE) 661 ins_compl_prep(c); 662 #endif 663 664 /* CTRL-\ CTRL-N goes to Normal mode, 665 * CTRL-\ CTRL-G goes to mode selected with 'insertmode', 666 * CTRL-\ CTRL-O is like CTRL-O but without moving the cursor. */ 667 if (c == Ctrl_BSL) 668 { 669 /* may need to redraw when no more chars available now */ 670 ins_redraw(); 671 ++no_mapping; 672 ++allow_keys; 673 c = safe_vgetc(); 674 --no_mapping; 675 --allow_keys; 676 if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O) 677 { 678 /* it's something else */ 679 vungetc(c); 680 c = Ctrl_BSL; 681 } 682 else if (c == Ctrl_G && p_im) 683 continue; 684 else 685 { 686 if (c == Ctrl_O) 687 { 688 ins_ctrl_o(); 689 ins_at_eol = FALSE; /* cursor keeps its column */ 690 nomove = TRUE; 691 } 692 count = 0; 693 goto doESCkey; 694 } 695 } 696 697 #ifdef FEAT_DIGRAPHS 698 c = do_digraph(c); 699 #endif 700 701 #ifdef FEAT_INS_EXPAND 702 if ((c == Ctrl_V || c == Ctrl_Q) && ctrl_x_mode == CTRL_X_CMDLINE) 703 goto docomplete; 704 #endif 705 if (c == Ctrl_V || c == Ctrl_Q) 706 { 707 ins_ctrl_v(); 708 c = Ctrl_V; /* pretend CTRL-V is last typed character */ 709 continue; 710 } 711 712 #ifdef FEAT_CINDENT 713 if (cindent_on() 714 # ifdef FEAT_INS_EXPAND 715 && ctrl_x_mode == 0 716 # endif 717 ) 718 { 719 /* A key name preceded by a bang means this key is not to be 720 * inserted. Skip ahead to the re-indenting below. 721 * A key name preceded by a star means that indenting has to be 722 * done before inserting the key. */ 723 line_is_white = inindent(0); 724 if (in_cinkeys(c, '!', line_is_white)) 725 goto force_cindent; 726 if (can_cindent && in_cinkeys(c, '*', line_is_white) 727 && stop_arrow() == OK) 728 do_c_expr_indent(); 729 } 730 #endif 731 732 #ifdef FEAT_RIGHTLEFT 733 if (curwin->w_p_rl) 734 switch (c) 735 { 736 case K_LEFT: c = K_RIGHT; break; 737 case K_S_LEFT: c = K_S_RIGHT; break; 738 case K_C_LEFT: c = K_C_RIGHT; break; 739 case K_RIGHT: c = K_LEFT; break; 740 case K_S_RIGHT: c = K_S_LEFT; break; 741 case K_C_RIGHT: c = K_C_LEFT; break; 742 } 743 #endif 744 745 #ifdef FEAT_VISUAL 746 /* 747 * If 'keymodel' contains "startsel", may start selection. If it 748 * does, a CTRL-O and c will be stuffed, we need to get these 749 * characters. 750 */ 751 if (ins_start_select(c)) 752 continue; 753 #endif 754 755 /* 756 * The big switch to handle a character in insert mode. 757 */ 758 switch (c) 759 { 760 case ESC: /* End input mode */ 761 if (echeck_abbr(ESC + ABBR_OFF)) 762 break; 763 /*FALLTHROUGH*/ 764 765 case Ctrl_C: /* End input mode */ 766 #ifdef FEAT_CMDWIN 767 if (c == Ctrl_C && cmdwin_type != 0) 768 { 769 /* Close the cmdline window. */ 770 cmdwin_result = K_IGNORE; 771 got_int = FALSE; /* don't stop executing autocommands et al. */ 772 goto doESCkey; 773 } 774 #endif 775 776 #ifdef UNIX 777 do_intr: 778 #endif 779 /* when 'insertmode' set, and not halfway a mapping, don't leave 780 * Insert mode */ 781 if (goto_im()) 782 { 783 if (got_int) 784 { 785 (void)vgetc(); /* flush all buffers */ 786 got_int = FALSE; 787 } 788 else 789 vim_beep(); 790 break; 791 } 792 doESCkey: 793 /* 794 * This is the ONLY return from edit()! 795 */ 796 /* Always update o_lnum, so that a "CTRL-O ." that adds a line 797 * still puts the cursor back after the inserted text. */ 798 if (ins_at_eol && gchar_cursor() == NUL) 799 o_lnum = curwin->w_cursor.lnum; 800 801 if (ins_esc(&count, cmdchar, nomove)) 802 { 803 #ifdef FEAT_AUTOCMD 804 if (cmdchar != 'r' && cmdchar != 'v') 805 apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, 806 FALSE, curbuf); 807 #endif 808 return (c == Ctrl_O); 809 } 810 continue; 811 812 case Ctrl_Z: /* suspend when 'insertmode' set */ 813 if (!p_im) 814 goto normalchar; /* insert CTRL-Z as normal char */ 815 stuffReadbuff((char_u *)":st\r"); 816 c = Ctrl_O; 817 /*FALLTHROUGH*/ 818 819 case Ctrl_O: /* execute one command */ 820 #ifdef FEAT_INS_EXPAND 821 if (ctrl_x_mode == CTRL_X_OCCULT) 822 goto docomplete; 823 #endif 824 if (echeck_abbr(Ctrl_O + ABBR_OFF)) 825 break; 826 ins_ctrl_o(); 827 count = 0; 828 goto doESCkey; 829 830 case K_INS: /* toggle insert/replace mode */ 831 case K_KINS: 832 ins_insert(replaceState); 833 break; 834 835 case K_SELECT: /* end of Select mode mapping - ignore */ 836 break; 837 838 #ifdef FEAT_SNIFF 839 case K_SNIFF: /* Sniff command received */ 840 stuffcharReadbuff(K_SNIFF); 841 goto doESCkey; 842 #endif 843 844 case K_HELP: /* Help key works like <ESC> <Help> */ 845 case K_F1: 846 case K_XF1: 847 stuffcharReadbuff(K_HELP); 848 if (p_im) 849 need_start_insertmode = TRUE; 850 goto doESCkey; 851 852 #ifdef FEAT_NETBEANS_INTG 853 case K_F21: /* NetBeans command */ 854 ++no_mapping; /* don't map the next key hits */ 855 i = safe_vgetc(); 856 --no_mapping; 857 netbeans_keycommand(i); 858 break; 859 #endif 860 861 case K_ZERO: /* Insert the previously inserted text. */ 862 case NUL: 863 case Ctrl_A: 864 /* For ^@ the trailing ESC will end the insert, unless there is an 865 * error. */ 866 if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL 867 && c != Ctrl_A && !p_im) 868 goto doESCkey; /* quit insert mode */ 869 inserted_space = FALSE; 870 break; 871 872 case Ctrl_R: /* insert the contents of a register */ 873 ins_reg(); 874 auto_format(FALSE, TRUE); 875 inserted_space = FALSE; 876 break; 877 878 case Ctrl_G: /* commands starting with CTRL-G */ 879 ins_ctrl_g(); 880 break; 881 882 case Ctrl_HAT: /* switch input mode and/or langmap */ 883 ins_ctrl_hat(); 884 break; 885 886 #ifdef FEAT_RIGHTLEFT 887 case Ctrl__: /* switch between languages */ 888 if (!p_ari) 889 goto normalchar; 890 ins_ctrl_(); 891 break; 892 #endif 893 894 case Ctrl_D: /* Make indent one shiftwidth smaller. */ 895 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) 896 if (ctrl_x_mode == CTRL_X_PATH_DEFINES) 897 goto docomplete; 898 #endif 899 /* FALLTHROUGH */ 900 901 case Ctrl_T: /* Make indent one shiftwidth greater. */ 902 # ifdef FEAT_INS_EXPAND 903 if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS) 904 { 905 if (has_compl_option(FALSE)) 906 goto docomplete; 907 break; 908 } 909 # endif 910 ins_shift(c, lastc); 911 auto_format(FALSE, TRUE); 912 inserted_space = FALSE; 913 break; 914 915 case K_DEL: /* delete character under the cursor */ 916 case K_KDEL: 917 ins_del(); 918 auto_format(FALSE, TRUE); 919 break; 920 921 case K_BS: /* delete character before the cursor */ 922 case Ctrl_H: 923 did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space); 924 auto_format(FALSE, TRUE); 925 break; 926 927 case Ctrl_W: /* delete word before the cursor */ 928 did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space); 929 auto_format(FALSE, TRUE); 930 break; 931 932 case Ctrl_U: /* delete all inserted text in current line */ 933 # ifdef FEAT_COMPL_FUNC 934 /* CTRL-X CTRL-U completes with 'completefunc'. */ 935 if (ctrl_x_mode == CTRL_X_FUNCTION) 936 goto docomplete; 937 # endif 938 did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space); 939 auto_format(FALSE, TRUE); 940 inserted_space = FALSE; 941 break; 942 943 #ifdef FEAT_MOUSE 944 case K_LEFTMOUSE: /* mouse keys */ 945 case K_LEFTMOUSE_NM: 946 case K_LEFTDRAG: 947 case K_LEFTRELEASE: 948 case K_LEFTRELEASE_NM: 949 case K_MIDDLEMOUSE: 950 case K_MIDDLEDRAG: 951 case K_MIDDLERELEASE: 952 case K_RIGHTMOUSE: 953 case K_RIGHTDRAG: 954 case K_RIGHTRELEASE: 955 case K_X1MOUSE: 956 case K_X1DRAG: 957 case K_X1RELEASE: 958 case K_X2MOUSE: 959 case K_X2DRAG: 960 case K_X2RELEASE: 961 ins_mouse(c); 962 break; 963 964 case K_MOUSEDOWN: /* Default action for scroll wheel up: scroll up */ 965 ins_mousescroll(FALSE); 966 break; 967 968 case K_MOUSEUP: /* Default action for scroll wheel down: scroll down */ 969 ins_mousescroll(TRUE); 970 break; 971 #endif 972 973 case K_IGNORE: /* Something mapped to nothing */ 974 break; 975 976 #ifdef FEAT_GUI 977 case K_VER_SCROLLBAR: 978 ins_scroll(); 979 break; 980 981 case K_HOR_SCROLLBAR: 982 ins_horscroll(); 983 break; 984 #endif 985 986 case K_HOME: /* <Home> */ 987 case K_KHOME: 988 case K_S_HOME: 989 case K_C_HOME: 990 ins_home(c); 991 break; 992 993 case K_END: /* <End> */ 994 case K_KEND: 995 case K_S_END: 996 case K_C_END: 997 ins_end(c); 998 break; 999 1000 case K_LEFT: /* <Left> */ 1001 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1002 ins_s_left(); 1003 else 1004 ins_left(); 1005 break; 1006 1007 case K_S_LEFT: /* <S-Left> */ 1008 case K_C_LEFT: 1009 ins_s_left(); 1010 break; 1011 1012 case K_RIGHT: /* <Right> */ 1013 if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) 1014 ins_s_right(); 1015 else 1016 ins_right(); 1017 break; 1018 1019 case K_S_RIGHT: /* <S-Right> */ 1020 case K_C_RIGHT: 1021 ins_s_right(); 1022 break; 1023 1024 case K_UP: /* <Up> */ 1025 if (mod_mask & MOD_MASK_SHIFT) 1026 ins_pageup(); 1027 else 1028 ins_up(FALSE); 1029 break; 1030 1031 case K_S_UP: /* <S-Up> */ 1032 case K_PAGEUP: 1033 case K_KPAGEUP: 1034 ins_pageup(); 1035 break; 1036 1037 case K_DOWN: /* <Down> */ 1038 if (mod_mask & MOD_MASK_SHIFT) 1039 ins_pagedown(); 1040 else 1041 ins_down(FALSE); 1042 break; 1043 1044 case K_S_DOWN: /* <S-Down> */ 1045 case K_PAGEDOWN: 1046 case K_KPAGEDOWN: 1047 ins_pagedown(); 1048 break; 1049 1050 #ifdef FEAT_DND 1051 case K_DROP: /* drag-n-drop event */ 1052 ins_drop(); 1053 break; 1054 #endif 1055 1056 case K_S_TAB: /* When not mapped, use like a normal TAB */ 1057 c = TAB; 1058 /* FALLTHROUGH */ 1059 1060 case TAB: /* TAB or Complete patterns along path */ 1061 #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID) 1062 if (ctrl_x_mode == CTRL_X_PATH_PATTERNS) 1063 goto docomplete; 1064 #endif 1065 inserted_space = FALSE; 1066 if (ins_tab()) 1067 goto normalchar; /* insert TAB as a normal char */ 1068 auto_format(FALSE, TRUE); 1069 break; 1070 1071 case K_KENTER: /* <Enter> */ 1072 c = CAR; 1073 /* FALLTHROUGH */ 1074 case CAR: 1075 case NL: 1076 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) 1077 /* In a quickfix window a <CR> jumps to the error under the 1078 * cursor. */ 1079 if (bt_quickfix(curbuf) && c == CAR) 1080 { 1081 do_cmdline_cmd((char_u *)".cc"); 1082 break; 1083 } 1084 #endif 1085 #ifdef FEAT_CMDWIN 1086 if (cmdwin_type != 0) 1087 { 1088 /* Execute the command in the cmdline window. */ 1089 cmdwin_result = CAR; 1090 goto doESCkey; 1091 } 1092 #endif 1093 if (ins_eol(c) && !p_im) 1094 goto doESCkey; /* out of memory */ 1095 auto_format(FALSE, FALSE); 1096 inserted_space = FALSE; 1097 break; 1098 1099 #if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND) 1100 case Ctrl_K: /* digraph or keyword completion */ 1101 # ifdef FEAT_INS_EXPAND 1102 if (ctrl_x_mode == CTRL_X_DICTIONARY) 1103 { 1104 if (has_compl_option(TRUE)) 1105 goto docomplete; 1106 break; 1107 } 1108 # endif 1109 # ifdef FEAT_DIGRAPHS 1110 c = ins_digraph(); 1111 if (c == NUL) 1112 break; 1113 # endif 1114 goto normalchar; 1115 #endif 1116 1117 #ifdef FEAT_INS_EXPAND 1118 case Ctrl_X: /* Enter CTRL-X mode */ 1119 ins_ctrl_x(); 1120 break; 1121 1122 case Ctrl_RSB: /* Tag name completion after ^X */ 1123 if (ctrl_x_mode != CTRL_X_TAGS) 1124 goto normalchar; 1125 goto docomplete; 1126 1127 case Ctrl_F: /* File name completion after ^X */ 1128 if (ctrl_x_mode != CTRL_X_FILES) 1129 goto normalchar; 1130 goto docomplete; 1131 1132 case 's': /* Spelling completion after ^X */ 1133 case Ctrl_S: 1134 if (ctrl_x_mode != CTRL_X_SPELL) 1135 goto normalchar; 1136 goto docomplete; 1137 #endif 1138 1139 case Ctrl_L: /* Whole line completion after ^X */ 1140 #ifdef FEAT_INS_EXPAND 1141 if (ctrl_x_mode != CTRL_X_WHOLE_LINE) 1142 #endif 1143 { 1144 /* CTRL-L with 'insertmode' set: Leave Insert mode */ 1145 if (p_im) 1146 { 1147 if (echeck_abbr(Ctrl_L + ABBR_OFF)) 1148 break; 1149 goto doESCkey; 1150 } 1151 goto normalchar; 1152 } 1153 #ifdef FEAT_INS_EXPAND 1154 /* FALLTHROUGH */ 1155 1156 case Ctrl_P: /* Do previous/next pattern completion */ 1157 case Ctrl_N: 1158 /* if 'complete' is empty then plain ^P is no longer special, 1159 * but it is under other ^X modes */ 1160 if (*curbuf->b_p_cpt == NUL 1161 && ctrl_x_mode != 0 1162 && !(compl_cont_status & CONT_LOCAL)) 1163 goto normalchar; 1164 1165 docomplete: 1166 if (ins_complete(c) == FAIL) 1167 compl_cont_status = 0; 1168 break; 1169 #endif /* FEAT_INS_EXPAND */ 1170 1171 case Ctrl_Y: /* copy from previous line or scroll down */ 1172 case Ctrl_E: /* copy from next line or scroll up */ 1173 c = ins_ctrl_ey(c); 1174 break; 1175 1176 default: 1177 #ifdef UNIX 1178 if (c == intr_char) /* special interrupt char */ 1179 goto do_intr; 1180 #endif 1181 1182 /* 1183 * Insert a nomal character. 1184 */ 1185 normalchar: 1186 #ifdef FEAT_SMARTINDENT 1187 /* Try to perform smart-indenting. */ 1188 ins_try_si(c); 1189 #endif 1190 1191 if (c == ' ') 1192 { 1193 inserted_space = TRUE; 1194 #ifdef FEAT_CINDENT 1195 if (inindent(0)) 1196 can_cindent = FALSE; 1197 #endif 1198 if (Insstart_blank_vcol == MAXCOL 1199 && curwin->w_cursor.lnum == Insstart.lnum) 1200 Insstart_blank_vcol = get_nolist_virtcol(); 1201 } 1202 1203 if (vim_iswordc(c) || !echeck_abbr( 1204 #ifdef FEAT_MBYTE 1205 /* Add ABBR_OFF for characters above 0x100, this is 1206 * what check_abbr() expects. */ 1207 (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : 1208 #endif 1209 c)) 1210 { 1211 insert_special(c, FALSE, FALSE); 1212 #ifdef FEAT_RIGHTLEFT 1213 revins_legal++; 1214 revins_chars++; 1215 #endif 1216 } 1217 1218 auto_format(FALSE, TRUE); 1219 1220 #ifdef FEAT_FOLDING 1221 /* When inserting a character the cursor line must never be in a 1222 * closed fold. */ 1223 foldOpenCursor(); 1224 #endif 1225 break; 1226 } /* end of switch (c) */ 1227 1228 /* If the cursor was moved we didn't just insert a space */ 1229 if (arrow_used) 1230 inserted_space = FALSE; 1231 1232 #ifdef FEAT_CINDENT 1233 if (can_cindent && cindent_on() 1234 # ifdef FEAT_INS_EXPAND 1235 && ctrl_x_mode == 0 1236 # endif 1237 ) 1238 { 1239 force_cindent: 1240 /* 1241 * Indent now if a key was typed that is in 'cinkeys'. 1242 */ 1243 if (in_cinkeys(c, ' ', line_is_white)) 1244 { 1245 if (stop_arrow() == OK) 1246 /* re-indent the current line */ 1247 do_c_expr_indent(); 1248 } 1249 } 1250 #endif /* FEAT_CINDENT */ 1251 1252 } /* for (;;) */ 1253 /* NOTREACHED */ 1254 } 1255 1256 /* 1257 * Redraw for Insert mode. 1258 * This is postponed until getting the next character to make '$' in the 'cpo' 1259 * option work correctly. 1260 * Only redraw when there are no characters available. This speeds up 1261 * inserting sequences of characters (e.g., for CTRL-R). 1262 */ 1263 static void 1264 ins_redraw() 1265 { 1266 if (!char_avail()) 1267 { 1268 if (must_redraw) 1269 update_screen(0); 1270 else if (clear_cmdline || redraw_cmdline) 1271 showmode(); /* clear cmdline and show mode */ 1272 showruler(FALSE); 1273 setcursor(); 1274 emsg_on_display = FALSE; /* may remove error message now */ 1275 } 1276 } 1277 1278 /* 1279 * Handle a CTRL-V or CTRL-Q typed in Insert mode. 1280 */ 1281 static void 1282 ins_ctrl_v() 1283 { 1284 int c; 1285 1286 /* may need to redraw when no more chars available now */ 1287 ins_redraw(); 1288 1289 if (redrawing() && !char_avail()) 1290 edit_putchar('^', TRUE); 1291 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ 1292 1293 #ifdef FEAT_CMDL_INFO 1294 add_to_showcmd_c(Ctrl_V); 1295 #endif 1296 1297 c = get_literal(); 1298 #ifdef FEAT_CMDL_INFO 1299 clear_showcmd(); 1300 #endif 1301 insert_special(c, FALSE, TRUE); 1302 #ifdef FEAT_RIGHTLEFT 1303 revins_chars++; 1304 revins_legal++; 1305 #endif 1306 } 1307 1308 /* 1309 * Put a character directly onto the screen. It's not stored in a buffer. 1310 * Used while handling CTRL-K, CTRL-V, etc. in Insert mode. 1311 */ 1312 static int pc_status; 1313 #define PC_STATUS_UNSET 0 /* pc_bytes was not set */ 1314 #define PC_STATUS_RIGHT 1 /* right halve of double-wide char */ 1315 #define PC_STATUS_LEFT 2 /* left halve of double-wide char */ 1316 #define PC_STATUS_SET 3 /* pc_bytes was filled */ 1317 #ifdef FEAT_MBYTE 1318 static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */ 1319 #else 1320 static char_u pc_bytes[2]; /* saved bytes */ 1321 #endif 1322 static int pc_attr; 1323 static int pc_row; 1324 static int pc_col; 1325 1326 void 1327 edit_putchar(c, highlight) 1328 int c; 1329 int highlight; 1330 { 1331 int attr; 1332 1333 if (ScreenLines != NULL) 1334 { 1335 update_topline(); /* just in case w_topline isn't valid */ 1336 validate_cursor(); 1337 if (highlight) 1338 attr = hl_attr(HLF_8); 1339 else 1340 attr = 0; 1341 pc_row = W_WINROW(curwin) + curwin->w_wrow; 1342 pc_col = W_WINCOL(curwin); 1343 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE) 1344 pc_status = PC_STATUS_UNSET; 1345 #endif 1346 #ifdef FEAT_RIGHTLEFT 1347 if (curwin->w_p_rl) 1348 { 1349 pc_col += W_WIDTH(curwin) - 1 - curwin->w_wcol; 1350 # ifdef FEAT_MBYTE 1351 if (has_mbyte) 1352 { 1353 int fix_col = mb_fix_col(pc_col, pc_row); 1354 1355 if (fix_col != pc_col) 1356 { 1357 screen_putchar(' ', pc_row, fix_col, attr); 1358 --curwin->w_wcol; 1359 pc_status = PC_STATUS_RIGHT; 1360 } 1361 } 1362 # endif 1363 } 1364 else 1365 #endif 1366 { 1367 pc_col += curwin->w_wcol; 1368 #ifdef FEAT_MBYTE 1369 if (mb_lefthalve(pc_row, pc_col)) 1370 pc_status = PC_STATUS_LEFT; 1371 #endif 1372 } 1373 1374 /* save the character to be able to put it back */ 1375 #if defined(FEAT_RIGHTLEFT) || defined(FEAT_MBYTE) 1376 if (pc_status == PC_STATUS_UNSET) 1377 #endif 1378 { 1379 screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr); 1380 pc_status = PC_STATUS_SET; 1381 } 1382 screen_putchar(c, pc_row, pc_col, attr); 1383 } 1384 } 1385 1386 /* 1387 * Undo the previous edit_putchar(). 1388 */ 1389 void 1390 edit_unputchar() 1391 { 1392 if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) 1393 { 1394 #if defined(FEAT_MBYTE) 1395 if (pc_status == PC_STATUS_RIGHT) 1396 ++curwin->w_wcol; 1397 if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) 1398 redrawWinline(curwin->w_cursor.lnum, FALSE); 1399 else 1400 #endif 1401 screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); 1402 } 1403 } 1404 1405 /* 1406 * Called when p_dollar is set: display a '$' at the end of the changed text 1407 * Only works when cursor is in the line that changes. 1408 */ 1409 void 1410 display_dollar(col) 1411 colnr_T col; 1412 { 1413 colnr_T save_col; 1414 1415 if (!redrawing()) 1416 return; 1417 1418 cursor_off(); 1419 save_col = curwin->w_cursor.col; 1420 curwin->w_cursor.col = col; 1421 #ifdef FEAT_MBYTE 1422 if (has_mbyte) 1423 { 1424 char_u *p; 1425 1426 /* If on the last byte of a multi-byte move to the first byte. */ 1427 p = ml_get_curline(); 1428 curwin->w_cursor.col -= (*mb_head_off)(p, p + col); 1429 } 1430 #endif 1431 curs_columns(FALSE); /* recompute w_wrow and w_wcol */ 1432 if (curwin->w_wcol < W_WIDTH(curwin)) 1433 { 1434 edit_putchar('$', FALSE); 1435 dollar_vcol = curwin->w_virtcol; 1436 } 1437 curwin->w_cursor.col = save_col; 1438 } 1439 1440 /* 1441 * Call this function before moving the cursor from the normal insert position 1442 * in insert mode. 1443 */ 1444 static void 1445 undisplay_dollar() 1446 { 1447 if (dollar_vcol) 1448 { 1449 dollar_vcol = 0; 1450 redrawWinline(curwin->w_cursor.lnum, FALSE); 1451 } 1452 } 1453 1454 /* 1455 * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D). 1456 * Keep the cursor on the same character. 1457 * type == INDENT_INC increase indent (for CTRL-T or <Tab>) 1458 * type == INDENT_DEC decrease indent (for CTRL-D) 1459 * type == INDENT_SET set indent to "amount" 1460 * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec). 1461 */ 1462 void 1463 change_indent(type, amount, round, replaced) 1464 int type; 1465 int amount; 1466 int round; 1467 int replaced; /* replaced character, put on replace stack */ 1468 { 1469 int vcol; 1470 int last_vcol; 1471 int insstart_less; /* reduction for Insstart.col */ 1472 int new_cursor_col; 1473 int i; 1474 char_u *ptr; 1475 int save_p_list; 1476 int start_col; 1477 colnr_T vc; 1478 #ifdef FEAT_VREPLACE 1479 colnr_T orig_col = 0; /* init for GCC */ 1480 char_u *new_line, *orig_line = NULL; /* init for GCC */ 1481 1482 /* VREPLACE mode needs to know what the line was like before changing */ 1483 if (State & VREPLACE_FLAG) 1484 { 1485 orig_line = vim_strsave(ml_get_curline()); /* Deal with NULL below */ 1486 orig_col = curwin->w_cursor.col; 1487 } 1488 #endif 1489 1490 /* for the following tricks we don't want list mode */ 1491 save_p_list = curwin->w_p_list; 1492 curwin->w_p_list = FALSE; 1493 vc = getvcol_nolist(&curwin->w_cursor); 1494 vcol = vc; 1495 1496 /* 1497 * For Replace mode we need to fix the replace stack later, which is only 1498 * possible when the cursor is in the indent. Remember the number of 1499 * characters before the cursor if it's possible. 1500 */ 1501 start_col = curwin->w_cursor.col; 1502 1503 /* determine offset from first non-blank */ 1504 new_cursor_col = curwin->w_cursor.col; 1505 beginline(BL_WHITE); 1506 new_cursor_col -= curwin->w_cursor.col; 1507 1508 insstart_less = curwin->w_cursor.col; 1509 1510 /* 1511 * If the cursor is in the indent, compute how many screen columns the 1512 * cursor is to the left of the first non-blank. 1513 */ 1514 if (new_cursor_col < 0) 1515 vcol = get_indent() - vcol; 1516 1517 if (new_cursor_col > 0) /* can't fix replace stack */ 1518 start_col = -1; 1519 1520 /* 1521 * Set the new indent. The cursor will be put on the first non-blank. 1522 */ 1523 if (type == INDENT_SET) 1524 (void)set_indent(amount, SIN_CHANGED); 1525 else 1526 { 1527 #ifdef FEAT_VREPLACE 1528 int save_State = State; 1529 1530 /* Avoid being called recursively. */ 1531 if (State & VREPLACE_FLAG) 1532 State = INSERT; 1533 #endif 1534 shift_line(type == INDENT_DEC, round, 1); 1535 #ifdef FEAT_VREPLACE 1536 State = save_State; 1537 #endif 1538 } 1539 insstart_less -= curwin->w_cursor.col; 1540 1541 /* 1542 * Try to put cursor on same character. 1543 * If the cursor is at or after the first non-blank in the line, 1544 * compute the cursor column relative to the column of the first 1545 * non-blank character. 1546 * If we are not in insert mode, leave the cursor on the first non-blank. 1547 * If the cursor is before the first non-blank, position it relative 1548 * to the first non-blank, counted in screen columns. 1549 */ 1550 if (new_cursor_col >= 0) 1551 { 1552 /* 1553 * When changing the indent while the cursor is touching it, reset 1554 * Insstart_col to 0. 1555 */ 1556 if (new_cursor_col == 0) 1557 insstart_less = MAXCOL; 1558 new_cursor_col += curwin->w_cursor.col; 1559 } 1560 else if (!(State & INSERT)) 1561 new_cursor_col = curwin->w_cursor.col; 1562 else 1563 { 1564 /* 1565 * Compute the screen column where the cursor should be. 1566 */ 1567 vcol = get_indent() - vcol; 1568 curwin->w_virtcol = (vcol < 0) ? 0 : vcol; 1569 1570 /* 1571 * Advance the cursor until we reach the right screen column. 1572 */ 1573 vcol = last_vcol = 0; 1574 new_cursor_col = -1; 1575 ptr = ml_get_curline(); 1576 while (vcol <= (int)curwin->w_virtcol) 1577 { 1578 last_vcol = vcol; 1579 #ifdef FEAT_MBYTE 1580 if (has_mbyte && new_cursor_col >= 0) 1581 new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col); 1582 else 1583 #endif 1584 ++new_cursor_col; 1585 vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol); 1586 } 1587 vcol = last_vcol; 1588 1589 /* 1590 * May need to insert spaces to be able to position the cursor on 1591 * the right screen column. 1592 */ 1593 if (vcol != (int)curwin->w_virtcol) 1594 { 1595 curwin->w_cursor.col = new_cursor_col; 1596 i = (int)curwin->w_virtcol - vcol; 1597 ptr = alloc(i + 1); 1598 if (ptr != NULL) 1599 { 1600 new_cursor_col += i; 1601 ptr[i] = NUL; 1602 while (--i >= 0) 1603 ptr[i] = ' '; 1604 ins_str(ptr); 1605 vim_free(ptr); 1606 } 1607 } 1608 1609 /* 1610 * When changing the indent while the cursor is in it, reset 1611 * Insstart_col to 0. 1612 */ 1613 insstart_less = MAXCOL; 1614 } 1615 1616 curwin->w_p_list = save_p_list; 1617 1618 if (new_cursor_col <= 0) 1619 curwin->w_cursor.col = 0; 1620 else 1621 curwin->w_cursor.col = new_cursor_col; 1622 curwin->w_set_curswant = TRUE; 1623 changed_cline_bef_curs(); 1624 1625 /* 1626 * May have to adjust the start of the insert. 1627 */ 1628 if (State & INSERT) 1629 { 1630 if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0) 1631 { 1632 if ((int)Insstart.col <= insstart_less) 1633 Insstart.col = 0; 1634 else 1635 Insstart.col -= insstart_less; 1636 } 1637 if ((int)ai_col <= insstart_less) 1638 ai_col = 0; 1639 else 1640 ai_col -= insstart_less; 1641 } 1642 1643 /* 1644 * For REPLACE mode, may have to fix the replace stack, if it's possible. 1645 * If the number of characters before the cursor decreased, need to pop a 1646 * few characters from the replace stack. 1647 * If the number of characters before the cursor increased, need to push a 1648 * few NULs onto the replace stack. 1649 */ 1650 if (REPLACE_NORMAL(State) && start_col >= 0) 1651 { 1652 while (start_col > (int)curwin->w_cursor.col) 1653 { 1654 replace_join(0); /* remove a NUL from the replace stack */ 1655 --start_col; 1656 } 1657 while (start_col < (int)curwin->w_cursor.col || replaced) 1658 { 1659 replace_push(NUL); 1660 if (replaced) 1661 { 1662 replace_push(replaced); 1663 replaced = NUL; 1664 } 1665 ++start_col; 1666 } 1667 } 1668 1669 #ifdef FEAT_VREPLACE 1670 /* 1671 * For VREPLACE mode, we also have to fix the replace stack. In this case 1672 * it is always possible because we backspace over the whole line and then 1673 * put it back again the way we wanted it. 1674 */ 1675 if (State & VREPLACE_FLAG) 1676 { 1677 /* If orig_line didn't allocate, just return. At least we did the job, 1678 * even if you can't backspace. */ 1679 if (orig_line == NULL) 1680 return; 1681 1682 /* Save new line */ 1683 new_line = vim_strsave(ml_get_curline()); 1684 if (new_line == NULL) 1685 return; 1686 1687 /* We only put back the new line up to the cursor */ 1688 new_line[curwin->w_cursor.col] = NUL; 1689 1690 /* Put back original line */ 1691 ml_replace(curwin->w_cursor.lnum, orig_line, FALSE); 1692 curwin->w_cursor.col = orig_col; 1693 1694 /* Backspace from cursor to start of line */ 1695 backspace_until_column(0); 1696 1697 /* Insert new stuff into line again */ 1698 ins_bytes(new_line); 1699 1700 vim_free(new_line); 1701 } 1702 #endif 1703 } 1704 1705 /* 1706 * Truncate the space at the end of a line. This is to be used only in an 1707 * insert mode. It handles fixing the replace stack for REPLACE and VREPLACE 1708 * modes. 1709 */ 1710 void 1711 truncate_spaces(line) 1712 char_u *line; 1713 { 1714 int i; 1715 1716 /* find start of trailing white space */ 1717 for (i = (int)STRLEN(line) - 1; i >= 0 && vim_iswhite(line[i]); i--) 1718 { 1719 if (State & REPLACE_FLAG) 1720 replace_join(0); /* remove a NUL from the replace stack */ 1721 } 1722 line[i + 1] = NUL; 1723 } 1724 1725 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \ 1726 || defined(FEAT_COMMENTS) || defined(PROTO) 1727 /* 1728 * Backspace the cursor until the given column. Handles REPLACE and VREPLACE 1729 * modes correctly. May also be used when not in insert mode at all. 1730 */ 1731 void 1732 backspace_until_column(col) 1733 int col; 1734 { 1735 while ((int)curwin->w_cursor.col > col) 1736 { 1737 curwin->w_cursor.col--; 1738 if (State & REPLACE_FLAG) 1739 replace_do_bs(); 1740 else 1741 (void)del_char(FALSE); 1742 } 1743 } 1744 #endif 1745 1746 #if defined(FEAT_INS_EXPAND) || defined(PROTO) 1747 /* 1748 * CTRL-X pressed in Insert mode. 1749 */ 1750 static void 1751 ins_ctrl_x() 1752 { 1753 /* CTRL-X after CTRL-X CTRL-V doesn't do anything, so that CTRL-X 1754 * CTRL-V works like CTRL-N */ 1755 if (ctrl_x_mode != CTRL_X_CMDLINE) 1756 { 1757 /* if the next ^X<> won't ADD nothing, then reset 1758 * compl_cont_status */ 1759 if (compl_cont_status & CONT_N_ADDS) 1760 compl_cont_status = (compl_cont_status | CONT_INTRPT); 1761 else 1762 compl_cont_status = 0; 1763 /* We're not sure which CTRL-X mode it will be yet */ 1764 ctrl_x_mode = CTRL_X_NOT_DEFINED_YET; 1765 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); 1766 edit_submode_pre = NULL; 1767 showmode(); 1768 } 1769 } 1770 1771 /* 1772 * Return TRUE if the 'dict' or 'tsr' option can be used. 1773 */ 1774 static int 1775 has_compl_option(dict_opt) 1776 int dict_opt; 1777 { 1778 if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL) 1779 : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) 1780 { 1781 ctrl_x_mode = 0; 1782 edit_submode = NULL; 1783 msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty") 1784 : (char_u *)_("'thesaurus' option is empty"), 1785 hl_attr(HLF_E)); 1786 if (emsg_silent == 0) 1787 { 1788 vim_beep(); 1789 setcursor(); 1790 out_flush(); 1791 ui_delay(2000L, FALSE); 1792 } 1793 return FALSE; 1794 } 1795 return TRUE; 1796 } 1797 1798 /* 1799 * Is the character 'c' a valid key to go to or keep us in CTRL-X mode? 1800 * This depends on the current mode. 1801 */ 1802 int 1803 vim_is_ctrl_x_key(c) 1804 int c; 1805 { 1806 /* Always allow ^R - let it's results then be checked */ 1807 if (c == Ctrl_R) 1808 return TRUE; 1809 1810 switch (ctrl_x_mode) 1811 { 1812 case 0: /* Not in any CTRL-X mode */ 1813 return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X); 1814 case CTRL_X_NOT_DEFINED_YET: 1815 return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E 1816 || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB 1817 || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P 1818 || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V 1819 || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O 1820 || c == Ctrl_S || c == 's'); 1821 case CTRL_X_SCROLL: 1822 return (c == Ctrl_Y || c == Ctrl_E); 1823 case CTRL_X_WHOLE_LINE: 1824 return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N); 1825 case CTRL_X_FILES: 1826 return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N); 1827 case CTRL_X_DICTIONARY: 1828 return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N); 1829 case CTRL_X_THESAURUS: 1830 return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N); 1831 case CTRL_X_TAGS: 1832 return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N); 1833 #ifdef FEAT_FIND_ID 1834 case CTRL_X_PATH_PATTERNS: 1835 return (c == Ctrl_P || c == Ctrl_N); 1836 case CTRL_X_PATH_DEFINES: 1837 return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N); 1838 #endif 1839 case CTRL_X_CMDLINE: 1840 return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N 1841 || c == Ctrl_X); 1842 #ifdef FEAT_COMPL_FUNC 1843 case CTRL_X_FUNCTION: 1844 return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N); 1845 #endif 1846 case CTRL_X_OCCULT: 1847 return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N); 1848 case CTRL_X_SPELL: 1849 return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N); 1850 } 1851 EMSG(_(e_internal)); 1852 return FALSE; 1853 } 1854 1855 /* 1856 * This is like ins_compl_add(), but if ic and inf are set, then the 1857 * case of the originally typed text is used, and the case of the completed 1858 * text is infered, ie this tries to work out what case you probably wanted 1859 * the rest of the word to be in -- webb 1860 * TODO: make this work for multi-byte characters. 1861 */ 1862 int 1863 ins_compl_add_infercase(str, len, fname, dir, flags) 1864 char_u *str; 1865 int len; 1866 char_u *fname; 1867 int dir; 1868 int flags; 1869 { 1870 int has_lower = FALSE; 1871 int was_letter = FALSE; 1872 int idx; 1873 1874 if (p_ic && curbuf->b_p_inf && len < IOSIZE) 1875 { 1876 /* Infer case of completed part -- webb */ 1877 /* Use IObuff, str would change text in buffer! */ 1878 vim_strncpy(IObuff, str, len); 1879 1880 /* Rule 1: Were any chars converted to lower? */ 1881 for (idx = 0; idx < compl_length; ++idx) 1882 { 1883 if (islower(compl_orig_text[idx])) 1884 { 1885 has_lower = TRUE; 1886 if (isupper(IObuff[idx])) 1887 { 1888 /* Rule 1 is satisfied */ 1889 for (idx = compl_length; idx < len; ++idx) 1890 IObuff[idx] = TOLOWER_LOC(IObuff[idx]); 1891 break; 1892 } 1893 } 1894 } 1895 1896 /* 1897 * Rule 2: No lower case, 2nd consecutive letter converted to 1898 * upper case. 1899 */ 1900 if (!has_lower) 1901 { 1902 for (idx = 0; idx < compl_length; ++idx) 1903 { 1904 if (was_letter && isupper(compl_orig_text[idx]) 1905 && islower(IObuff[idx])) 1906 { 1907 /* Rule 2 is satisfied */ 1908 for (idx = compl_length; idx < len; ++idx) 1909 IObuff[idx] = TOUPPER_LOC(IObuff[idx]); 1910 break; 1911 } 1912 was_letter = isalpha(compl_orig_text[idx]); 1913 } 1914 } 1915 1916 /* Copy the original case of the part we typed */ 1917 STRNCPY(IObuff, compl_orig_text, compl_length); 1918 1919 return ins_compl_add(IObuff, len, fname, dir, flags); 1920 } 1921 return ins_compl_add(str, len, fname, dir, flags); 1922 } 1923 1924 /* 1925 * Add a match to the list of matches. 1926 * If the given string is already in the list of completions, then return 1927 * FAIL, otherwise add it to the list and return OK. If there is an error, 1928 * maybe because alloc() returns NULL, then RET_ERROR is returned -- webb. 1929 * 1930 * New: 1931 * If the given string is already in the list of completions, then return 1932 * NOTDONE, otherwise add it to the list and return OK. If there is an error, 1933 * maybe because alloc() returns NULL, then FAIL is returned -- webb. 1934 */ 1935 int 1936 ins_compl_add(str, len, fname, dir, flags) 1937 char_u *str; 1938 int len; 1939 char_u *fname; 1940 int dir; 1941 int flags; 1942 { 1943 compl_T *match; 1944 1945 ui_breakcheck(); 1946 if (got_int) 1947 return FAIL; 1948 if (len < 0) 1949 len = (int)STRLEN(str); 1950 1951 /* 1952 * If the same match is already present, don't add it. 1953 */ 1954 if (compl_first_match != NULL) 1955 { 1956 match = compl_first_match; 1957 do 1958 { 1959 if ( !(match->cp_flags & ORIGINAL_TEXT) 1960 && STRNCMP(match->cp_str, str, (size_t)len) == 0 1961 && match->cp_str[len] == NUL) 1962 return NOTDONE; 1963 match = match->cp_next; 1964 } while (match != NULL && match != compl_first_match); 1965 } 1966 1967 /* 1968 * Allocate a new match structure. 1969 * Copy the values to the new match structure. 1970 */ 1971 match = (compl_T *)alloc((unsigned)sizeof(compl_T)); 1972 if (match == NULL) 1973 return FAIL; 1974 match->cp_number = -1; 1975 if (flags & ORIGINAL_TEXT) 1976 { 1977 match->cp_number = 0; 1978 match->cp_str = compl_orig_text; 1979 } 1980 else if ((match->cp_str = vim_strnsave(str, len)) == NULL) 1981 { 1982 vim_free(match); 1983 return FAIL; 1984 } 1985 /* match-fname is: 1986 * - compl_curr_match->cp_fname if it is a string equal to fname. 1987 * - a copy of fname, FREE_FNAME is set to free later THE allocated mem. 1988 * - NULL otherwise. --Acevedo */ 1989 if (fname && compl_curr_match && compl_curr_match->cp_fname 1990 && STRCMP(fname, compl_curr_match->cp_fname) == 0) 1991 match->cp_fname = compl_curr_match->cp_fname; 1992 else if (fname && (match->cp_fname = vim_strsave(fname)) != NULL) 1993 flags |= FREE_FNAME; 1994 else 1995 match->cp_fname = NULL; 1996 match->cp_flags = flags; 1997 1998 /* 1999 * Link the new match structure in the list of matches. 2000 */ 2001 if (compl_first_match == NULL) 2002 match->cp_next = match->cp_prev = NULL; 2003 else if (dir == FORWARD) 2004 { 2005 match->cp_next = compl_curr_match->cp_next; 2006 match->cp_prev = compl_curr_match; 2007 } 2008 else /* BACKWARD */ 2009 { 2010 match->cp_next = compl_curr_match; 2011 match->cp_prev = compl_curr_match->cp_prev; 2012 } 2013 if (match->cp_next) 2014 match->cp_next->cp_prev = match; 2015 if (match->cp_prev) 2016 match->cp_prev->cp_next = match; 2017 else /* if there's nothing before, it is the first match */ 2018 compl_first_match = match; 2019 compl_curr_match = match; 2020 2021 return OK; 2022 } 2023 2024 /* 2025 * Add an array of matches to the list of matches. 2026 * Frees matches[]. 2027 */ 2028 static void 2029 ins_compl_add_matches(num_matches, matches, dir) 2030 int num_matches; 2031 char_u **matches; 2032 int dir; 2033 { 2034 int i; 2035 int add_r = OK; 2036 int ldir = dir; 2037 2038 for (i = 0; i < num_matches && add_r != FAIL; i++) 2039 if ((add_r = ins_compl_add(matches[i], -1, NULL, ldir, 0)) == OK) 2040 /* if dir was BACKWARD then honor it just once */ 2041 ldir = FORWARD; 2042 FreeWild(num_matches, matches); 2043 } 2044 2045 /* Make the completion list cyclic. 2046 * Return the number of matches (excluding the original). 2047 */ 2048 static int 2049 ins_compl_make_cyclic() 2050 { 2051 compl_T *match; 2052 int count = 0; 2053 2054 if (compl_first_match != NULL) 2055 { 2056 /* 2057 * Find the end of the list. 2058 */ 2059 match = compl_first_match; 2060 /* there's always an entry for the compl_orig_text, it doesn't count. */ 2061 while (match->cp_next != NULL && match->cp_next != compl_first_match) 2062 { 2063 match = match->cp_next; 2064 ++count; 2065 } 2066 match->cp_next = compl_first_match; 2067 compl_first_match->cp_prev = match; 2068 } 2069 return count; 2070 } 2071 2072 #define DICT_FIRST (1) /* use just first element in "dict" */ 2073 #define DICT_EXACT (2) /* "dict" is the exact name of a file */ 2074 /* 2075 * Add any identifiers that match the given pattern to the list of 2076 * completions. 2077 */ 2078 static void 2079 ins_compl_dictionaries(dict, pat, dir, flags, thesaurus) 2080 char_u *dict; 2081 char_u *pat; 2082 int dir; 2083 int flags; 2084 int thesaurus; 2085 { 2086 char_u *ptr; 2087 char_u *buf; 2088 FILE *fp; 2089 regmatch_T regmatch; 2090 int add_r; 2091 char_u **files; 2092 int count; 2093 int i; 2094 int save_p_scs; 2095 2096 buf = alloc(LSIZE); 2097 /* If 'infercase' is set, don't use 'smartcase' here */ 2098 save_p_scs = p_scs; 2099 if (curbuf->b_p_inf) 2100 p_scs = FALSE; 2101 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0); 2102 /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */ 2103 regmatch.rm_ic = ignorecase(pat); 2104 while (buf != NULL && regmatch.regprog != NULL && *dict != NUL 2105 && !got_int && !compl_interrupted) 2106 { 2107 /* copy one dictionary file name into buf */ 2108 if (flags == DICT_EXACT) 2109 { 2110 count = 1; 2111 files = &dict; 2112 } 2113 else 2114 { 2115 /* Expand wildcards in the dictionary name, but do not allow 2116 * backticks (for security, the 'dict' option may have been set in 2117 * a modeline). */ 2118 copy_option_part(&dict, buf, LSIZE, ","); 2119 if (vim_strchr(buf, '`') != NULL 2120 || expand_wildcards(1, &buf, &count, &files, 2121 EW_FILE|EW_SILENT) != OK) 2122 count = 0; 2123 } 2124 2125 for (i = 0; i < count && !got_int && !compl_interrupted; i++) 2126 { 2127 fp = mch_fopen((char *)files[i], "r"); /* open dictionary file */ 2128 if (flags != DICT_EXACT) 2129 { 2130 vim_snprintf((char *)IObuff, IOSIZE, 2131 _("Scanning dictionary: %s"), (char *)files[i]); 2132 msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R)); 2133 } 2134 2135 if (fp != NULL) 2136 { 2137 /* 2138 * Read dictionary file line by line. 2139 * Check each line for a match. 2140 */ 2141 while (!got_int && !compl_interrupted 2142 && !vim_fgets(buf, LSIZE, fp)) 2143 { 2144 ptr = buf; 2145 while (vim_regexec(®match, buf, (colnr_T)(ptr - buf))) 2146 { 2147 ptr = regmatch.startp[0]; 2148 ptr = find_word_end(ptr); 2149 add_r = ins_compl_add_infercase(regmatch.startp[0], 2150 (int)(ptr - regmatch.startp[0]), 2151 files[i], dir, 0); 2152 if (thesaurus) 2153 { 2154 char_u *wstart; 2155 2156 /* 2157 * Add the other matches on the line 2158 */ 2159 while (!got_int) 2160 { 2161 /* Find start of the next word. Skip white 2162 * space and punctuation. */ 2163 ptr = find_word_start(ptr); 2164 if (*ptr == NUL || *ptr == NL) 2165 break; 2166 wstart = ptr; 2167 2168 /* Find end of the word and add it. */ 2169 #ifdef FEAT_MBYTE 2170 if (has_mbyte) 2171 /* Japanese words may have characters in 2172 * different classes, only separate words 2173 * with single-byte non-word characters. */ 2174 while (*ptr != NUL) 2175 { 2176 int l = (*mb_ptr2len)(ptr); 2177 2178 if (l < 2 && !vim_iswordc(*ptr)) 2179 break; 2180 ptr += l; 2181 } 2182 else 2183 #endif 2184 ptr = find_word_end(ptr); 2185 add_r = ins_compl_add_infercase(wstart, 2186 (int)(ptr - wstart), files[i], dir, 0); 2187 } 2188 } 2189 if (add_r == OK) 2190 /* if dir was BACKWARD then honor it just once */ 2191 dir = FORWARD; 2192 else if (add_r == FAIL) 2193 break; 2194 /* avoid expensive call to vim_regexec() when at end 2195 * of line */ 2196 if (*ptr == '\n' || got_int) 2197 break; 2198 } 2199 line_breakcheck(); 2200 ins_compl_check_keys(50); 2201 } 2202 fclose(fp); 2203 } 2204 } 2205 if (flags != DICT_EXACT) 2206 FreeWild(count, files); 2207 if (flags) 2208 break; 2209 } 2210 p_scs = save_p_scs; 2211 vim_free(regmatch.regprog); 2212 vim_free(buf); 2213 } 2214 2215 /* 2216 * Find the start of the next word. 2217 * Returns a pointer to the first char of the word. Also stops at a NUL. 2218 */ 2219 char_u * 2220 find_word_start(ptr) 2221 char_u *ptr; 2222 { 2223 #ifdef FEAT_MBYTE 2224 if (has_mbyte) 2225 while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1) 2226 ptr += (*mb_ptr2len)(ptr); 2227 else 2228 #endif 2229 while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr)) 2230 ++ptr; 2231 return ptr; 2232 } 2233 2234 /* 2235 * Find the end of the word. Assumes it starts inside a word. 2236 * Returns a pointer to just after the word. 2237 */ 2238 char_u * 2239 find_word_end(ptr) 2240 char_u *ptr; 2241 { 2242 #ifdef FEAT_MBYTE 2243 int start_class; 2244 2245 if (has_mbyte) 2246 { 2247 start_class = mb_get_class(ptr); 2248 if (start_class > 1) 2249 while (*ptr != NUL) 2250 { 2251 ptr += (*mb_ptr2len)(ptr); 2252 if (mb_get_class(ptr) != start_class) 2253 break; 2254 } 2255 } 2256 else 2257 #endif 2258 while (vim_iswordc(*ptr)) 2259 ++ptr; 2260 return ptr; 2261 } 2262 2263 /* 2264 * Free the list of completions 2265 */ 2266 static void 2267 ins_compl_free() 2268 { 2269 compl_T *match; 2270 2271 vim_free(compl_pattern); 2272 compl_pattern = NULL; 2273 2274 if (compl_first_match == NULL) 2275 return; 2276 compl_curr_match = compl_first_match; 2277 do 2278 { 2279 match = compl_curr_match; 2280 compl_curr_match = compl_curr_match->cp_next; 2281 vim_free(match->cp_str); 2282 /* several entries may use the same fname, free it just once. */ 2283 if (match->cp_flags & FREE_FNAME) 2284 vim_free(match->cp_fname); 2285 vim_free(match); 2286 } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); 2287 compl_first_match = compl_curr_match = NULL; 2288 } 2289 2290 static void 2291 ins_compl_clear() 2292 { 2293 compl_cont_status = 0; 2294 compl_started = FALSE; 2295 compl_matches = 0; 2296 vim_free(compl_pattern); 2297 compl_pattern = NULL; 2298 save_sm = -1; 2299 edit_submode_extra = NULL; 2300 } 2301 2302 /* 2303 * Prepare for Insert mode completion, or stop it. 2304 * Called just after typing a character in Insert mode. 2305 */ 2306 static void 2307 ins_compl_prep(c) 2308 int c; 2309 { 2310 char_u *ptr; 2311 int temp; 2312 int want_cindent; 2313 2314 /* Forget any previous 'special' messages if this is actually 2315 * a ^X mode key - bar ^R, in which case we wait to see what it gives us. 2316 */ 2317 if (c != Ctrl_R && vim_is_ctrl_x_key(c)) 2318 edit_submode_extra = NULL; 2319 2320 /* Ignore end of Select mode mapping */ 2321 if (c == K_SELECT) 2322 return; 2323 2324 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET) 2325 { 2326 /* 2327 * We have just typed CTRL-X and aren't quite sure which CTRL-X mode 2328 * it will be yet. Now we decide. 2329 */ 2330 switch (c) 2331 { 2332 case Ctrl_E: 2333 case Ctrl_Y: 2334 ctrl_x_mode = CTRL_X_SCROLL; 2335 if (!(State & REPLACE_FLAG)) 2336 edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)"); 2337 else 2338 edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)"); 2339 edit_submode_pre = NULL; 2340 showmode(); 2341 break; 2342 case Ctrl_L: 2343 ctrl_x_mode = CTRL_X_WHOLE_LINE; 2344 break; 2345 case Ctrl_F: 2346 ctrl_x_mode = CTRL_X_FILES; 2347 break; 2348 case Ctrl_K: 2349 ctrl_x_mode = CTRL_X_DICTIONARY; 2350 break; 2351 case Ctrl_R: 2352 /* Simply allow ^R to happen without affecting ^X mode */ 2353 break; 2354 case Ctrl_T: 2355 ctrl_x_mode = CTRL_X_THESAURUS; 2356 break; 2357 #ifdef FEAT_COMPL_FUNC 2358 case Ctrl_U: 2359 ctrl_x_mode = CTRL_X_FUNCTION; 2360 break; 2361 #endif 2362 case Ctrl_O: 2363 ctrl_x_mode = CTRL_X_OCCULT; 2364 break; 2365 case 's': 2366 case Ctrl_S: 2367 ctrl_x_mode = CTRL_X_SPELL; 2368 break; 2369 case Ctrl_RSB: 2370 ctrl_x_mode = CTRL_X_TAGS; 2371 break; 2372 #ifdef FEAT_FIND_ID 2373 case Ctrl_I: 2374 case K_S_TAB: 2375 ctrl_x_mode = CTRL_X_PATH_PATTERNS; 2376 break; 2377 case Ctrl_D: 2378 ctrl_x_mode = CTRL_X_PATH_DEFINES; 2379 break; 2380 #endif 2381 case Ctrl_V: 2382 case Ctrl_Q: 2383 ctrl_x_mode = CTRL_X_CMDLINE; 2384 break; 2385 case Ctrl_P: 2386 case Ctrl_N: 2387 /* ^X^P means LOCAL expansion if nothing interrupted (eg we 2388 * just started ^X mode, or there were enough ^X's to cancel 2389 * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below) 2390 * do normal expansion when interrupting a different mode (say 2391 * ^X^F^X^P or ^P^X^X^P, see below) 2392 * nothing changes if interrupting mode 0, (eg, the flag 2393 * doesn't change when going to ADDING mode -- Acevedo */ 2394 if (!(compl_cont_status & CONT_INTRPT)) 2395 compl_cont_status |= CONT_LOCAL; 2396 else if (compl_cont_mode != 0) 2397 compl_cont_status &= ~CONT_LOCAL; 2398 /* FALLTHROUGH */ 2399 default: 2400 /* If we have typed at least 2 ^X's... for modes != 0, we set 2401 * compl_cont_status = 0 (eg, as if we had just started ^X 2402 * mode). 2403 * For mode 0, we set "compl_cont_mode" to an impossible 2404 * value, in both cases ^X^X can be used to restart the same 2405 * mode (avoiding ADDING mode). 2406 * Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start 2407 * 'complete' and local ^P expansions respectively. 2408 * In mode 0 an extra ^X is needed since ^X^P goes to ADDING 2409 * mode -- Acevedo */ 2410 if (c == Ctrl_X) 2411 { 2412 if (compl_cont_mode != 0) 2413 compl_cont_status = 0; 2414 else 2415 compl_cont_mode = CTRL_X_NOT_DEFINED_YET; 2416 } 2417 ctrl_x_mode = 0; 2418 edit_submode = NULL; 2419 showmode(); 2420 break; 2421 } 2422 } 2423 else if (ctrl_x_mode != 0) 2424 { 2425 /* We're already in CTRL-X mode, do we stay in it? */ 2426 if (!vim_is_ctrl_x_key(c)) 2427 { 2428 if (ctrl_x_mode == CTRL_X_SCROLL) 2429 ctrl_x_mode = 0; 2430 else 2431 ctrl_x_mode = CTRL_X_FINISHED; 2432 edit_submode = NULL; 2433 } 2434 showmode(); 2435 } 2436 2437 if (compl_started || ctrl_x_mode == CTRL_X_FINISHED) 2438 { 2439 /* Show error message from attempted keyword completion (probably 2440 * 'Pattern not found') until another key is hit, then go back to 2441 * showing what mode we are in. */ 2442 showmode(); 2443 if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R) 2444 || ctrl_x_mode == CTRL_X_FINISHED) 2445 { 2446 /* Get here when we have finished typing a sequence of ^N and 2447 * ^P or other completion characters in CTRL-X mode. Free up 2448 * memory that was used, and make sure we can redo the insert. */ 2449 if (compl_curr_match != NULL) 2450 { 2451 char_u *p; 2452 2453 /* 2454 * If any of the original typed text has been changed, 2455 * eg when ignorecase is set, we must add back-spaces to 2456 * the redo buffer. We add as few as necessary to delete 2457 * just the part of the original text that has changed. 2458 */ 2459 ptr = compl_curr_match->cp_str; 2460 p = compl_orig_text; 2461 while (*p && *p == *ptr) 2462 { 2463 ++p; 2464 ++ptr; 2465 } 2466 for (temp = 0; p[temp]; ++temp) 2467 AppendCharToRedobuff(K_BS); 2468 AppendToRedobuffLit(ptr); 2469 } 2470 2471 #ifdef FEAT_CINDENT 2472 want_cindent = (can_cindent && cindent_on()); 2473 #endif 2474 /* 2475 * When completing whole lines: fix indent for 'cindent'. 2476 * Otherwise, break line if it's too long. 2477 */ 2478 if (compl_cont_mode == CTRL_X_WHOLE_LINE) 2479 { 2480 #ifdef FEAT_CINDENT 2481 /* re-indent the current line */ 2482 if (want_cindent) 2483 { 2484 do_c_expr_indent(); 2485 want_cindent = FALSE; /* don't do it again */ 2486 } 2487 #endif 2488 } 2489 else 2490 { 2491 /* put the cursor on the last char, for 'tw' formatting */ 2492 curwin->w_cursor.col--; 2493 if (stop_arrow() == OK) 2494 insertchar(NUL, 0, -1); 2495 curwin->w_cursor.col++; 2496 } 2497 2498 auto_format(FALSE, TRUE); 2499 2500 ins_compl_free(); 2501 compl_started = FALSE; 2502 compl_matches = 0; 2503 msg_clr_cmdline(); /* necessary for "noshowmode" */ 2504 ctrl_x_mode = 0; 2505 if (save_sm >= 0) 2506 p_sm = save_sm; 2507 if (edit_submode != NULL) 2508 { 2509 edit_submode = NULL; 2510 showmode(); 2511 } 2512 2513 #ifdef FEAT_CINDENT 2514 /* 2515 * Indent now if a key was typed that is in 'cinkeys'. 2516 */ 2517 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) 2518 do_c_expr_indent(); 2519 #endif 2520 } 2521 } 2522 2523 /* reset continue_* if we left expansion-mode, if we stay they'll be 2524 * (re)set properly in ins_complete() */ 2525 if (!vim_is_ctrl_x_key(c)) 2526 { 2527 compl_cont_status = 0; 2528 compl_cont_mode = 0; 2529 } 2530 } 2531 2532 /* 2533 * Loops through the list of windows, loaded-buffers or non-loaded-buffers 2534 * (depending on flag) starting from buf and looking for a non-scanned 2535 * buffer (other than curbuf). curbuf is special, if it is called with 2536 * buf=curbuf then it has to be the first call for a given flag/expansion. 2537 * 2538 * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo 2539 */ 2540 static buf_T * 2541 ins_compl_next_buf(buf, flag) 2542 buf_T *buf; 2543 int flag; 2544 { 2545 #ifdef FEAT_WINDOWS 2546 static win_T *wp; 2547 #endif 2548 2549 if (flag == 'w') /* just windows */ 2550 { 2551 #ifdef FEAT_WINDOWS 2552 if (buf == curbuf) /* first call for this flag/expansion */ 2553 wp = curwin; 2554 while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin 2555 && wp->w_buffer->b_scanned) 2556 ; 2557 buf = wp->w_buffer; 2558 #else 2559 buf = curbuf; 2560 #endif 2561 } 2562 else 2563 /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U' 2564 * (unlisted buffers) 2565 * When completing whole lines skip unloaded buffers. */ 2566 while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf 2567 && ((flag == 'U' 2568 ? buf->b_p_bl 2569 : (!buf->b_p_bl 2570 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u'))) 2571 || buf->b_scanned 2572 || (buf->b_ml.ml_mfp == NULL 2573 && ctrl_x_mode == CTRL_X_WHOLE_LINE))) 2574 ; 2575 return buf; 2576 } 2577 2578 #ifdef FEAT_COMPL_FUNC 2579 static int expand_by_function __ARGS((int col, char_u *base, char_u ***matches)); 2580 2581 /* 2582 * Execute user defined complete function 'completefunc', and get matches in 2583 * "matches". 2584 * Return value is number of matches. 2585 */ 2586 static int 2587 expand_by_function(col, base, matches) 2588 int col; 2589 char_u *base; 2590 char_u ***matches; 2591 { 2592 list_T *matchlist; 2593 char_u colbuf[30]; 2594 char_u *args[3]; 2595 listitem_T *li; 2596 garray_T ga; 2597 char_u *p; 2598 2599 if (*curbuf->b_p_cfu == NUL) 2600 return 0; 2601 2602 /* Call 'completefunc' to obtain the list of matches. */ 2603 args[0] = (char_u *)"0"; 2604 sprintf((char *)colbuf, "%d", col + (int)STRLEN(base)); 2605 args[1] = colbuf; 2606 args[2] = base; 2607 2608 matchlist = call_func_retlist(curbuf->b_p_cfu, 3, args, FALSE); 2609 if (matchlist == NULL) 2610 return 0; 2611 2612 /* Go through the List with matches and put them in an array. */ 2613 ga_init2(&ga, (int)sizeof(char_u *), 8); 2614 for (li = matchlist->lv_first; li != NULL; li = li->li_next) 2615 { 2616 p = get_tv_string_chk(&li->li_tv); 2617 if (p != NULL && *p != NUL) 2618 { 2619 if (ga_grow(&ga, 1) == FAIL) 2620 break; 2621 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strsave(p); 2622 ++ga.ga_len; 2623 } 2624 } 2625 2626 list_unref(matchlist); 2627 *matches = (char_u **)ga.ga_data; 2628 return ga.ga_len; 2629 } 2630 #endif /* FEAT_COMPL_FUNC */ 2631 2632 static int expand_occult __ARGS((linenr_T lnum, int col, char_u *base, char_u ***matches)); 2633 2634 /* 2635 * Perform occult completion' 2636 * Return value is number of candidates and array of candidates as "matchp". 2637 */ 2638 static int 2639 expand_occult(lnum, col, pat, matchp) 2640 linenr_T lnum; 2641 int col; 2642 char_u *pat; 2643 char_u ***matchp; 2644 { 2645 int num_matches; 2646 2647 /* Use tag completion for now. */ 2648 if (find_tags(pat, &num_matches, matchp, 2649 TAG_REGEXP | TAG_NAMES | TAG_NOIC | 2650 TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), 2651 TAG_MANY, curbuf->b_ffname) == FAIL) 2652 return 0; 2653 return num_matches; 2654 } 2655 2656 /* 2657 * Get the next expansion(s), using "compl_pattern". 2658 * The search starts at position "ini" in curbuf and in the direction dir. 2659 * When "compl_started" is FALSE start at that position, otherwise 2660 * continue where we stopped searching before. 2661 * This may return before finding all the matches. 2662 * Return the total number of matches or -1 if still unknown -- Acevedo 2663 */ 2664 static int 2665 ins_compl_get_exp(ini, dir) 2666 pos_T *ini; 2667 int dir; 2668 { 2669 static pos_T first_match_pos; 2670 static pos_T last_match_pos; 2671 static char_u *e_cpt = (char_u *)""; /* curr. entry in 'complete' */ 2672 static int found_all = FALSE; /* Found all matches of a 2673 certain type. */ 2674 static buf_T *ins_buf = NULL; /* buffer being scanned */ 2675 2676 pos_T *pos; 2677 char_u **matches; 2678 int save_p_scs; 2679 int save_p_ws; 2680 int save_p_ic; 2681 int i; 2682 int num_matches; 2683 int len; 2684 int found_new_match; 2685 int type = ctrl_x_mode; 2686 char_u *ptr; 2687 char_u *dict = NULL; 2688 int dict_f = 0; 2689 compl_T *old_match; 2690 2691 if (!compl_started) 2692 { 2693 for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next) 2694 ins_buf->b_scanned = 0; 2695 found_all = FALSE; 2696 ins_buf = curbuf; 2697 e_cpt = (compl_cont_status & CONT_LOCAL) 2698 ? (char_u *)"." : curbuf->b_p_cpt; 2699 last_match_pos = first_match_pos = *ini; 2700 } 2701 2702 old_match = compl_curr_match; /* remember the last current match */ 2703 pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos; 2704 /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */ 2705 for (;;) 2706 { 2707 found_new_match = FAIL; 2708 2709 /* For ^N/^P pick a new entry from e_cpt if compl_started is off, 2710 * or if found_all says this entry is done. For ^X^L only use the 2711 * entries from 'complete' that look in loaded buffers. */ 2712 if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE) 2713 && (!compl_started || found_all)) 2714 { 2715 found_all = FALSE; 2716 while (*e_cpt == ',' || *e_cpt == ' ') 2717 e_cpt++; 2718 if (*e_cpt == '.' && !curbuf->b_scanned) 2719 { 2720 ins_buf = curbuf; 2721 first_match_pos = *ini; 2722 /* So that ^N can match word immediately after cursor */ 2723 if (ctrl_x_mode == 0) 2724 dec(&first_match_pos); 2725 last_match_pos = first_match_pos; 2726 type = 0; 2727 } 2728 else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL 2729 && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf) 2730 { 2731 /* Scan a buffer, but not the current one. */ 2732 if (ins_buf->b_ml.ml_mfp != NULL) /* loaded buffer */ 2733 { 2734 compl_started = TRUE; 2735 first_match_pos.col = last_match_pos.col = 0; 2736 first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1; 2737 last_match_pos.lnum = 0; 2738 type = 0; 2739 } 2740 else /* unloaded buffer, scan like dictionary */ 2741 { 2742 found_all = TRUE; 2743 if (ins_buf->b_fname == NULL) 2744 continue; 2745 type = CTRL_X_DICTIONARY; 2746 dict = ins_buf->b_fname; 2747 dict_f = DICT_EXACT; 2748 } 2749 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"), 2750 ins_buf->b_fname == NULL 2751 ? buf_spname(ins_buf) 2752 : ins_buf->b_sfname == NULL 2753 ? (char *)ins_buf->b_fname 2754 : (char *)ins_buf->b_sfname); 2755 msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R)); 2756 } 2757 else if (*e_cpt == NUL) 2758 break; 2759 else 2760 { 2761 if (ctrl_x_mode == CTRL_X_WHOLE_LINE) 2762 type = -1; 2763 else if (*e_cpt == 'k' || *e_cpt == 's') 2764 { 2765 if (*e_cpt == 'k') 2766 type = CTRL_X_DICTIONARY; 2767 else 2768 type = CTRL_X_THESAURUS; 2769 if (*++e_cpt != ',' && *e_cpt != NUL) 2770 { 2771 dict = e_cpt; 2772 dict_f = DICT_FIRST; 2773 } 2774 } 2775 #ifdef FEAT_FIND_ID 2776 else if (*e_cpt == 'i') 2777 type = CTRL_X_PATH_PATTERNS; 2778 else if (*e_cpt == 'd') 2779 type = CTRL_X_PATH_DEFINES; 2780 #endif 2781 else if (*e_cpt == ']' || *e_cpt == 't') 2782 { 2783 type = CTRL_X_TAGS; 2784 sprintf((char*)IObuff, _("Scanning tags.")); 2785 msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R)); 2786 } 2787 else 2788 type = -1; 2789 2790 /* in any case e_cpt is advanced to the next entry */ 2791 (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ","); 2792 2793 found_all = TRUE; 2794 if (type == -1) 2795 continue; 2796 } 2797 } 2798 2799 switch (type) 2800 { 2801 case -1: 2802 break; 2803 #ifdef FEAT_FIND_ID 2804 case CTRL_X_PATH_PATTERNS: 2805 case CTRL_X_PATH_DEFINES: 2806 find_pattern_in_path(compl_pattern, dir, 2807 (int)STRLEN(compl_pattern), FALSE, FALSE, 2808 (type == CTRL_X_PATH_DEFINES 2809 && !(compl_cont_status & CONT_SOL)) 2810 ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND, 2811 (linenr_T)1, (linenr_T)MAXLNUM); 2812 break; 2813 #endif 2814 2815 case CTRL_X_DICTIONARY: 2816 case CTRL_X_THESAURUS: 2817 ins_compl_dictionaries( 2818 dict ? dict 2819 : (type == CTRL_X_THESAURUS 2820 ? (*curbuf->b_p_tsr == NUL 2821 ? p_tsr 2822 : curbuf->b_p_tsr) 2823 : (*curbuf->b_p_dict == NUL 2824 ? p_dict 2825 : curbuf->b_p_dict)), 2826 compl_pattern, dir, 2827 dict ? dict_f : 0, type == CTRL_X_THESAURUS); 2828 dict = NULL; 2829 break; 2830 2831 case CTRL_X_TAGS: 2832 /* set p_ic according to p_ic, p_scs and pat for find_tags(). */ 2833 save_p_ic = p_ic; 2834 p_ic = ignorecase(compl_pattern); 2835 2836 /* Find up to TAG_MANY matches. Avoids that an enourmous number 2837 * of matches is found when compl_pattern is empty */ 2838 if (find_tags(compl_pattern, &num_matches, &matches, 2839 TAG_REGEXP | TAG_NAMES | TAG_NOIC | 2840 TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), 2841 TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) 2842 { 2843 ins_compl_add_matches(num_matches, matches, dir); 2844 } 2845 p_ic = save_p_ic; 2846 break; 2847 2848 case CTRL_X_FILES: 2849 if (expand_wildcards(1, &compl_pattern, &num_matches, &matches, 2850 EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK) 2851 { 2852 2853 /* May change home directory back to "~". */ 2854 tilde_replace(compl_pattern, num_matches, matches); 2855 ins_compl_add_matches(num_matches, matches, dir); 2856 } 2857 break; 2858 2859 case CTRL_X_CMDLINE: 2860 if (expand_cmdline(&compl_xp, compl_pattern, 2861 (int)STRLEN(compl_pattern), 2862 &num_matches, &matches) == EXPAND_OK) 2863 ins_compl_add_matches(num_matches, matches, dir); 2864 break; 2865 2866 #ifdef FEAT_COMPL_FUNC 2867 case CTRL_X_FUNCTION: 2868 num_matches = expand_by_function(first_match_pos.col, 2869 compl_pattern, &matches); 2870 if (num_matches > 0) 2871 ins_compl_add_matches(num_matches, matches, dir); 2872 break; 2873 #endif 2874 2875 case CTRL_X_OCCULT: 2876 num_matches = expand_occult(first_match_pos.lnum, 2877 first_match_pos.col, compl_pattern, &matches); 2878 if (num_matches > 0) 2879 ins_compl_add_matches(num_matches, matches, dir); 2880 break; 2881 2882 case CTRL_X_SPELL: 2883 #ifdef FEAT_SYN_HL 2884 num_matches = expand_spelling(first_match_pos.lnum, 2885 first_match_pos.col, compl_pattern, &matches); 2886 if (num_matches > 0) 2887 ins_compl_add_matches(num_matches, matches, dir); 2888 #endif 2889 break; 2890 2891 default: /* normal ^P/^N and ^X^L */ 2892 /* 2893 * If 'infercase' is set, don't use 'smartcase' here 2894 */ 2895 save_p_scs = p_scs; 2896 if (ins_buf->b_p_inf) 2897 p_scs = FALSE; 2898 2899 /* buffers other than curbuf are scanned from the beginning or the 2900 * end but never from the middle, thus setting nowrapscan in this 2901 * buffers is a good idea, on the other hand, we always set 2902 * wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */ 2903 save_p_ws = p_ws; 2904 if (ins_buf != curbuf) 2905 p_ws = FALSE; 2906 else if (*e_cpt == '.') 2907 p_ws = TRUE; 2908 for (;;) 2909 { 2910 int flags = 0; 2911 2912 /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has 2913 * added a word that was at the beginning of the line */ 2914 if ( ctrl_x_mode == CTRL_X_WHOLE_LINE 2915 || (compl_cont_status & CONT_SOL)) 2916 found_new_match = search_for_exact_line(ins_buf, pos, 2917 dir, compl_pattern); 2918 else 2919 found_new_match = searchit(NULL, ins_buf, pos, dir, 2920 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, 2921 RE_LAST); 2922 if (!compl_started) 2923 { 2924 /* set compl_started even on fail */ 2925 compl_started = TRUE; 2926 first_match_pos = *pos; 2927 last_match_pos = *pos; 2928 } 2929 else if (first_match_pos.lnum == last_match_pos.lnum 2930 && first_match_pos.col == last_match_pos.col) 2931 found_new_match = FAIL; 2932 if (found_new_match == FAIL) 2933 { 2934 if (ins_buf == curbuf) 2935 found_all = TRUE; 2936 break; 2937 } 2938 2939 /* when ADDING, the text before the cursor matches, skip it */ 2940 if ( (compl_cont_status & CONT_ADDING) && ins_buf == curbuf 2941 && ini->lnum == pos->lnum 2942 && ini->col == pos->col) 2943 continue; 2944 ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col; 2945 if (ctrl_x_mode == CTRL_X_WHOLE_LINE) 2946 { 2947 if (compl_cont_status & CONT_ADDING) 2948 { 2949 if (pos->lnum >= ins_buf->b_ml.ml_line_count) 2950 continue; 2951 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); 2952 if (!p_paste) 2953 ptr = skipwhite(ptr); 2954 } 2955 len = (int)STRLEN(ptr); 2956 } 2957 else 2958 { 2959 char_u *tmp_ptr = ptr; 2960 2961 if (compl_cont_status & CONT_ADDING) 2962 { 2963 tmp_ptr += compl_length; 2964 /* Skip if already inside a word. */ 2965 if (vim_iswordp(tmp_ptr)) 2966 continue; 2967 /* Find start of next word. */ 2968 tmp_ptr = find_word_start(tmp_ptr); 2969 } 2970 /* Find end of this word. */ 2971 tmp_ptr = find_word_end(tmp_ptr); 2972 len = (int)(tmp_ptr - ptr); 2973 2974 if ((compl_cont_status & CONT_ADDING) 2975 && len == compl_length) 2976 { 2977 if (pos->lnum < ins_buf->b_ml.ml_line_count) 2978 { 2979 /* Try next line, if any. the new word will be 2980 * "join" as if the normal command "J" was used. 2981 * IOSIZE is always greater than 2982 * compl_length, so the next STRNCPY always 2983 * works -- Acevedo */ 2984 STRNCPY(IObuff, ptr, len); 2985 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); 2986 tmp_ptr = ptr = skipwhite(ptr); 2987 /* Find start of next word. */ 2988 tmp_ptr = find_word_start(tmp_ptr); 2989 /* Find end of next word. */ 2990 tmp_ptr = find_word_end(tmp_ptr); 2991 if (tmp_ptr > ptr) 2992 { 2993 if (*ptr != ')' && IObuff[len - 1] != TAB) 2994 { 2995 if (IObuff[len - 1] != ' ') 2996 IObuff[len++] = ' '; 2997 /* IObuf =~ "\k.* ", thus len >= 2 */ 2998 if (p_js 2999 && (IObuff[len - 2] == '.' 3000 || (vim_strchr(p_cpo, CPO_JOINSP) 3001 == NULL 3002 && (IObuff[len - 2] == '?' 3003 || IObuff[len - 2] == '!')))) 3004 IObuff[len++] = ' '; 3005 } 3006 /* copy as much as posible of the new word */ 3007 if (tmp_ptr - ptr >= IOSIZE - len) 3008 tmp_ptr = ptr + IOSIZE - len - 1; 3009 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr); 3010 len += (int)(tmp_ptr - ptr); 3011 flags |= CONT_S_IPOS; 3012 } 3013 IObuff[len] = NUL; 3014 ptr = IObuff; 3015 } 3016 if (len == compl_length) 3017 continue; 3018 } 3019 } 3020 if (ins_compl_add_infercase(ptr, len, 3021 ins_buf == curbuf ? NULL : ins_buf->b_sfname, 3022 dir, flags) != NOTDONE) 3023 { 3024 found_new_match = OK; 3025 break; 3026 } 3027 } 3028 p_scs = save_p_scs; 3029 p_ws = save_p_ws; 3030 } 3031 /* check if compl_curr_match has changed, (e.g. other type of 3032 * expansion added somenthing) */ 3033 if (compl_curr_match != old_match) 3034 found_new_match = OK; 3035 3036 /* break the loop for specialized modes (use 'complete' just for the 3037 * generic ctrl_x_mode == 0) or when we've found a new match */ 3038 if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE) 3039 || found_new_match != FAIL) 3040 break; 3041 3042 /* Mark a buffer scanned when it has been scanned completely */ 3043 if (type == 0 || type == CTRL_X_PATH_PATTERNS) 3044 ins_buf->b_scanned = TRUE; 3045 3046 compl_started = FALSE; 3047 } 3048 compl_started = TRUE; 3049 3050 if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE) 3051 && *e_cpt == NUL) /* Got to end of 'complete' */ 3052 found_new_match = FAIL; 3053 3054 i = -1; /* total of matches, unknown */ 3055 if (found_new_match == FAIL 3056 || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)) 3057 i = ins_compl_make_cyclic(); 3058 3059 /* If several matches were added (FORWARD) or the search failed and has 3060 * just been made cyclic then we have to move compl_curr_match to the next 3061 * or previous entry (if any) -- Acevedo */ 3062 compl_curr_match = dir == FORWARD ? old_match->cp_next : old_match->cp_prev; 3063 if (compl_curr_match == NULL) 3064 compl_curr_match = old_match; 3065 return i; 3066 } 3067 3068 /* Delete the old text being completed. */ 3069 static void 3070 ins_compl_delete() 3071 { 3072 int i; 3073 3074 /* 3075 * In insert mode: Delete the typed part. 3076 * In replace mode: Put the old characters back, if any. 3077 */ 3078 i = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); 3079 backspace_until_column(i); 3080 changed_cline_bef_curs(); 3081 } 3082 3083 /* Insert the new text being completed. */ 3084 static void 3085 ins_compl_insert() 3086 { 3087 ins_bytes(compl_shown_match->cp_str + curwin->w_cursor.col - compl_col); 3088 } 3089 3090 /* 3091 * Fill in the next completion in the current direction. 3092 * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to 3093 * get more completions. If it is FALSE, then we just do nothing when there 3094 * are no more completions in a given direction. The latter case is used when 3095 * we are still in the middle of finding completions, to allow browsing 3096 * through the ones found so far. 3097 * Return the total number of matches, or -1 if still unknown -- webb. 3098 * 3099 * compl_curr_match is currently being used by ins_compl_get_exp(), so we use 3100 * compl_shown_match here. 3101 * 3102 * Note that this function may be called recursively once only. First with 3103 * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn 3104 * calls this function with "allow_get_expansion" FALSE. 3105 */ 3106 static int 3107 ins_compl_next(allow_get_expansion) 3108 int allow_get_expansion; 3109 { 3110 int num_matches = -1; 3111 int i; 3112 3113 if (allow_get_expansion) 3114 { 3115 /* Delete old text to be replaced */ 3116 ins_compl_delete(); 3117 } 3118 compl_pending = FALSE; 3119 if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL) 3120 compl_shown_match = compl_shown_match->cp_next; 3121 else if (compl_shows_dir == BACKWARD && compl_shown_match->cp_prev != NULL) 3122 compl_shown_match = compl_shown_match->cp_prev; 3123 else 3124 { 3125 compl_pending = TRUE; 3126 if (allow_get_expansion) 3127 { 3128 num_matches = ins_compl_get_exp(&compl_startpos, 3129 compl_direction); 3130 if (compl_pending) 3131 { 3132 if (compl_direction == compl_shows_dir) 3133 compl_shown_match = compl_curr_match; 3134 } 3135 } 3136 else 3137 return -1; 3138 } 3139 3140 /* Insert the text of the new completion */ 3141 ins_compl_insert(); 3142 3143 if (!allow_get_expansion) 3144 { 3145 /* Display the current match. */ 3146 update_screen(0); 3147 3148 /* Delete old text to be replaced, since we're still searching and 3149 * don't want to match ourselves! */ 3150 ins_compl_delete(); 3151 } 3152 3153 /* 3154 * Show the file name for the match (if any) 3155 * Truncate the file name to avoid a wait for return. 3156 */ 3157 if (compl_shown_match->cp_fname != NULL) 3158 { 3159 STRCPY(IObuff, "match in file "); 3160 i = (vim_strsize(compl_shown_match->cp_fname) + 16) - sc_col; 3161 if (i <= 0) 3162 i = 0; 3163 else 3164 STRCAT(IObuff, "<"); 3165 STRCAT(IObuff, compl_shown_match->cp_fname + i); 3166 msg(IObuff); 3167 redraw_cmdline = FALSE; /* don't overwrite! */ 3168 } 3169 3170 return num_matches; 3171 } 3172 3173 /* 3174 * Call this while finding completions, to check whether the user has hit a key 3175 * that should change the currently displayed completion, or exit completion 3176 * mode. Also, when compl_pending is TRUE, show a completion as soon as 3177 * possible. -- webb 3178 * "frequency" specifies out of how many calls we actually check. 3179 */ 3180 void 3181 ins_compl_check_keys(frequency) 3182 int frequency; 3183 { 3184 static int count = 0; 3185 3186 int c; 3187 3188 /* Don't check when reading keys from a script. That would break the test 3189 * scripts */ 3190 if (using_script()) 3191 return; 3192 3193 /* Only do this at regular intervals */ 3194 if (++count < frequency) 3195 return; 3196 count = 0; 3197 3198 ++no_mapping; 3199 c = vpeekc_any(); 3200 --no_mapping; 3201 if (c != NUL) 3202 { 3203 if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) 3204 { 3205 c = safe_vgetc(); /* Eat the character */ 3206 if (c == Ctrl_P || c == Ctrl_L) 3207 compl_shows_dir = BACKWARD; 3208 else 3209 compl_shows_dir = FORWARD; 3210 (void)ins_compl_next(FALSE); 3211 } 3212 else if (c != Ctrl_R) 3213 compl_interrupted = TRUE; 3214 } 3215 if (compl_pending && !got_int) 3216 (void)ins_compl_next(FALSE); 3217 } 3218 3219 /* 3220 * Do Insert mode completion. 3221 * Called when character "c" was typed, which has a meaning for completion. 3222 * Returns OK if completion was done, FAIL if something failed (out of mem). 3223 */ 3224 static int 3225 ins_complete(c) 3226 int c; 3227 { 3228 char_u *line; 3229 int startcol = 0; /* column where searched text starts */ 3230 colnr_T curs_col; /* cursor column */ 3231 int n; 3232 3233 if (c == Ctrl_P || c == Ctrl_L) 3234 compl_direction = BACKWARD; 3235 else 3236 compl_direction = FORWARD; 3237 if (!compl_started) 3238 { 3239 /* First time we hit ^N or ^P (in a row, I mean) */ 3240 3241 /* Turn off 'sm' so we don't show matches with ^X^L */ 3242 save_sm = p_sm; 3243 p_sm = FALSE; 3244 3245 did_ai = FALSE; 3246 #ifdef FEAT_SMARTINDENT 3247 did_si = FALSE; 3248 can_si = FALSE; 3249 can_si_back = FALSE; 3250 #endif 3251 if (stop_arrow() == FAIL) 3252 return FAIL; 3253 3254 line = ml_get(curwin->w_cursor.lnum); 3255 curs_col = curwin->w_cursor.col; 3256 3257 /* if this same ctrl_x_mode has been interrupted use the text from 3258 * "compl_startpos" to the cursor as a pattern to add a new word 3259 * instead of expand the one before the cursor, in word-wise if 3260 * "compl_startpos" 3261 * is not in the same line as the cursor then fix it (the line has 3262 * been split because it was longer than 'tw'). if SOL is set then 3263 * skip the previous pattern, a word at the beginning of the line has 3264 * been inserted, we'll look for that -- Acevedo. */ 3265 if ((compl_cont_status & CONT_INTRPT) && compl_cont_mode == ctrl_x_mode) 3266 { 3267 /* 3268 * it is a continued search 3269 */ 3270 compl_cont_status &= ~CONT_INTRPT; /* remove INTRPT */ 3271 if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS 3272 || ctrl_x_mode == CTRL_X_PATH_DEFINES) 3273 { 3274 if (compl_startpos.lnum != curwin->w_cursor.lnum) 3275 { 3276 /* line (probably) wrapped, set compl_startpos to the 3277 * first non_blank in the line, if it is not a wordchar 3278 * include it to get a better pattern, but then we don't 3279 * want the "\\<" prefix, check it bellow */ 3280 compl_col = (colnr_T)(skipwhite(line) - line); 3281 compl_startpos.col = compl_col; 3282 compl_startpos.lnum = curwin->w_cursor.lnum; 3283 compl_cont_status &= ~CONT_SOL; /* clear SOL if present */ 3284 } 3285 else 3286 { 3287 /* S_IPOS was set when we inserted a word that was at the 3288 * beginning of the line, which means that we'll go to SOL 3289 * mode but first we need to redefine compl_startpos */ 3290 if (compl_cont_status & CONT_S_IPOS) 3291 { 3292 compl_cont_status |= CONT_SOL; 3293 compl_startpos.col = (colnr_T)(skipwhite( 3294 line + compl_length 3295 + compl_startpos.col) - line); 3296 } 3297 compl_col = compl_startpos.col; 3298 } 3299 compl_length = curwin->w_cursor.col - (int)compl_col; 3300 /* IObuf is used to add a "word from the next line" would we 3301 * have enough space? just being paranoic */ 3302 #define MIN_SPACE 75 3303 if (compl_length > (IOSIZE - MIN_SPACE)) 3304 { 3305 compl_cont_status &= ~CONT_SOL; 3306 compl_length = (IOSIZE - MIN_SPACE); 3307 compl_col = curwin->w_cursor.col - compl_length; 3308 } 3309 compl_cont_status |= CONT_ADDING | CONT_N_ADDS; 3310 if (compl_length < 1) 3311 compl_cont_status &= CONT_LOCAL; 3312 } 3313 else if (ctrl_x_mode == CTRL_X_WHOLE_LINE) 3314 compl_cont_status = CONT_ADDING | CONT_N_ADDS; 3315 else 3316 compl_cont_status = 0; 3317 } 3318 else 3319 compl_cont_status &= CONT_LOCAL; 3320 3321 if (!(compl_cont_status & CONT_ADDING)) /* normal expansion */ 3322 { 3323 compl_cont_mode = ctrl_x_mode; 3324 if (ctrl_x_mode != 0) /* Remove LOCAL if ctrl_x_mode != 0 */ 3325 compl_cont_status = 0; 3326 compl_cont_status |= CONT_N_ADDS; 3327 compl_startpos = curwin->w_cursor; 3328 startcol = (int)curs_col; 3329 compl_col = 0; 3330 } 3331 3332 /* Work out completion pattern and original text -- webb */ 3333 if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT)) 3334 { 3335 if ((compl_cont_status & CONT_SOL) 3336 || ctrl_x_mode == CTRL_X_PATH_DEFINES) 3337 { 3338 if (!(compl_cont_status & CONT_ADDING)) 3339 { 3340 while (--startcol >= 0 && vim_isIDc(line[startcol])) 3341 ; 3342 compl_col += ++startcol; 3343 compl_length = curs_col - startcol; 3344 } 3345 if (p_ic) 3346 compl_pattern = str_foldcase(line + compl_col, 3347 compl_length, NULL, 0); 3348 else 3349 compl_pattern = vim_strnsave(line + compl_col, 3350 compl_length); 3351 if (compl_pattern == NULL) 3352 return FAIL; 3353 } 3354 else if (compl_cont_status & CONT_ADDING) 3355 { 3356 char_u *prefix = (char_u *)"\\<"; 3357 3358 /* we need 3 extra chars, 1 for the NUL and 3359 * 2 >= strlen(prefix) -- Acevedo */ 3360 compl_pattern = alloc(quote_meta(NULL, line + compl_col, 3361 compl_length) + 3); 3362 if (compl_pattern == NULL) 3363 return FAIL; 3364 if (!vim_iswordp(line + compl_col) 3365 || (compl_col > 0 3366 && ( 3367 #ifdef FEAT_MBYTE 3368 vim_iswordp(mb_prevptr(line, line + compl_col)) 3369 #else 3370 vim_iswordc(line[compl_col - 1]) 3371 #endif 3372 ))) 3373 prefix = (char_u *)""; 3374 STRCPY((char *)compl_pattern, prefix); 3375 (void)quote_meta(compl_pattern + STRLEN(prefix), 3376 line + compl_col, compl_length); 3377 } 3378 else if (--startcol < 0 || 3379 #ifdef FEAT_MBYTE 3380 !vim_iswordp(mb_prevptr(line, line + startcol + 1)) 3381 #else 3382 !vim_iswordc(line[startcol]) 3383 #endif 3384 ) 3385 { 3386 /* Match any word of at least two chars */ 3387 compl_pattern = vim_strsave((char_u *)"\\<\\k\\k"); 3388 if (compl_pattern == NULL) 3389 return FAIL; 3390 compl_col += curs_col; 3391 compl_length = 0; 3392 } 3393 else 3394 { 3395 #ifdef FEAT_MBYTE 3396 /* Search the point of change class of multibyte character 3397 * or not a word single byte character backward. */ 3398 if (has_mbyte) 3399 { 3400 int base_class; 3401 int head_off; 3402 3403 startcol -= (*mb_head_off)(line, line + startcol); 3404 base_class = mb_get_class(line + startcol); 3405 while (--startcol >= 0) 3406 { 3407 head_off = (*mb_head_off)(line, line + startcol); 3408 if (base_class != mb_get_class(line + startcol 3409 - head_off)) 3410 break; 3411 startcol -= head_off; 3412 } 3413 } 3414 else 3415 #endif 3416 while (--startcol >= 0 && vim_iswordc(line[startcol])) 3417 ; 3418 compl_col += ++startcol; 3419 compl_length = (int)curs_col - startcol; 3420 if (compl_length == 1) 3421 { 3422 /* Only match word with at least two chars -- webb 3423 * there's no need to call quote_meta, 3424 * alloc(7) is enough -- Acevedo 3425 */ 3426 compl_pattern = alloc(7); 3427 if (compl_pattern == NULL) 3428 return FAIL; 3429 STRCPY((char *)compl_pattern, "\\<"); 3430 (void)quote_meta(compl_pattern + 2, line + compl_col, 1); 3431 STRCAT((char *)compl_pattern, "\\k"); 3432 } 3433 else 3434 { 3435 compl_pattern = alloc(quote_meta(NULL, line + compl_col, 3436 compl_length) + 3); 3437 if (compl_pattern == NULL) 3438 return FAIL; 3439 STRCPY((char *)compl_pattern, "\\<"); 3440 (void)quote_meta(compl_pattern + 2, line + compl_col, 3441 compl_length); 3442 } 3443 } 3444 } 3445 else if (ctrl_x_mode == CTRL_X_WHOLE_LINE) 3446 { 3447 compl_col = skipwhite(line) - line; 3448 compl_length = (int)curs_col - (int)compl_col; 3449 if (compl_length < 0) /* cursor in indent: empty pattern */ 3450 compl_length = 0; 3451 if (p_ic) 3452 compl_pattern = str_foldcase(line + compl_col, compl_length, 3453 NULL, 0); 3454 else 3455 compl_pattern = vim_strnsave(line + compl_col, compl_length); 3456 if (compl_pattern == NULL) 3457 return FAIL; 3458 } 3459 else if (ctrl_x_mode == CTRL_X_FILES) 3460 { 3461 while (--startcol >= 0 && vim_isfilec(line[startcol])) 3462 ; 3463 compl_col += ++startcol; 3464 compl_length = (int)curs_col - startcol; 3465 compl_pattern = addstar(line + compl_col, compl_length, 3466 EXPAND_FILES); 3467 if (compl_pattern == NULL) 3468 return FAIL; 3469 } 3470 else if (ctrl_x_mode == CTRL_X_CMDLINE) 3471 { 3472 compl_pattern = vim_strnsave(line, curs_col); 3473 if (compl_pattern == NULL) 3474 return FAIL; 3475 set_cmd_context(&compl_xp, compl_pattern, 3476 (int)STRLEN(compl_pattern), curs_col); 3477 if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL 3478 || compl_xp.xp_context == EXPAND_NOTHING) 3479 return FAIL; 3480 startcol = (int)(compl_xp.xp_pattern - compl_pattern); 3481 compl_col = startcol; 3482 compl_length = curs_col - startcol; 3483 } 3484 #ifdef FEAT_COMPL_FUNC 3485 else if (ctrl_x_mode == CTRL_X_FUNCTION) 3486 { 3487 /* 3488 * Call user defined function 'completefunc' with "a:findstart" is 3489 * 1 to obtain the length of text to use for completion. 3490 */ 3491 char_u colbuf[30]; 3492 char_u *args[3]; 3493 int col; 3494 3495 /* Call 'completefunc' and get pattern length as a string */ 3496 if (*curbuf->b_p_cfu == NUL) 3497 return FAIL; 3498 3499 args[0] = (char_u *)"1"; 3500 sprintf((char *)colbuf, "%d", (int)curs_col); 3501 args[1] = colbuf; 3502 args[2] = NULL; 3503 3504 col = call_func_retnr(curbuf->b_p_cfu, 3, args, FALSE); 3505 if (col < 0) 3506 return FAIL; 3507 compl_col = col; 3508 if ((colnr_T)compl_col > curs_col) 3509 compl_col = curs_col; 3510 3511 /* Setup variables for completion. Need to obtain "line" again, 3512 * it may have become invalid. */ 3513 line = ml_get(curwin->w_cursor.lnum); 3514 compl_length = curs_col - compl_col; 3515 compl_pattern = vim_strnsave(line + compl_col, compl_length); 3516 if (compl_pattern == NULL) 3517 return FAIL; 3518 } 3519 #endif 3520 else if (ctrl_x_mode == CTRL_X_OCCULT) 3521 { 3522 /* TODO: let language-specific function handle locating the text 3523 * to be completed. */ 3524 while (--startcol >= 0 && vim_isIDc(line[startcol])) 3525 ; 3526 compl_col += ++startcol; 3527 compl_length = (int)curs_col - startcol; 3528 compl_pattern = vim_strnsave(line + compl_col, compl_length); 3529 if (compl_pattern == NULL) 3530 return FAIL; 3531 } 3532 else if (ctrl_x_mode == CTRL_X_SPELL) 3533 { 3534 #ifdef FEAT_SYN_HL 3535 compl_col = spell_word_start(startcol); 3536 if (compl_col == startcol) 3537 return FAIL; 3538 compl_length = (int)curs_col - compl_col; 3539 compl_pattern = vim_strnsave(line + compl_col, compl_length); 3540 if (compl_pattern == NULL) 3541 #endif 3542 return FAIL; 3543 } 3544 else 3545 { 3546 EMSG2(_(e_intern2), "ins_complete()"); 3547 return FAIL; 3548 } 3549 3550 if (compl_cont_status & CONT_ADDING) 3551 { 3552 edit_submode_pre = (char_u *)_(" Adding"); 3553 if (ctrl_x_mode == CTRL_X_WHOLE_LINE) 3554 { 3555 /* Insert a new line, keep indentation but ignore 'comments' */ 3556 #ifdef FEAT_COMMENTS 3557 char_u *old = curbuf->b_p_com; 3558 3559 curbuf->b_p_com = (char_u *)""; 3560 #endif 3561 compl_startpos.lnum = curwin->w_cursor.lnum; 3562 compl_startpos.col = compl_col; 3563 ins_eol('\r'); 3564 #ifdef FEAT_COMMENTS 3565 curbuf->b_p_com = old; 3566 #endif 3567 compl_length = 0; 3568 compl_col = curwin->w_cursor.col; 3569 } 3570 } 3571 else 3572 { 3573 edit_submode_pre = NULL; 3574 compl_startpos.col = compl_col; 3575 } 3576 3577 if (compl_cont_status & CONT_LOCAL) 3578 edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]); 3579 else 3580 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); 3581 3582 /* Always add completion for the original text. Note that 3583 * "compl_orig_text" itself (not a copy) is added, it will be freed 3584 * when the list of matches is freed. */ 3585 compl_orig_text = vim_strnsave(line + compl_col, compl_length); 3586 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, 3587 -1, NULL, 0, ORIGINAL_TEXT) != OK) 3588 { 3589 vim_free(compl_pattern); 3590 compl_pattern = NULL; 3591 vim_free(compl_orig_text); 3592 compl_orig_text = NULL; 3593 return FAIL; 3594 } 3595 3596 /* showmode might reset the internal line pointers, so it must 3597 * be called before line = ml_get(), or when this address is no 3598 * longer needed. -- Acevedo. 3599 */ 3600 edit_submode_extra = (char_u *)_("-- Searching..."); 3601 edit_submode_highl = HLF_COUNT; 3602 showmode(); 3603 edit_submode_extra = NULL; 3604 out_flush(); 3605 } 3606 3607 compl_shown_match = compl_curr_match; 3608 compl_shows_dir = compl_direction; 3609 3610 /* 3611 * Find next match. 3612 */ 3613 n = ins_compl_next(TRUE); 3614 3615 if (n > 1) /* all matches have been found */ 3616 compl_matches = n; 3617 compl_curr_match = compl_shown_match; 3618 compl_direction = compl_shows_dir; 3619 compl_interrupted = FALSE; 3620 3621 /* eat the ESC to avoid leaving insert mode */ 3622 if (got_int && !global_busy) 3623 { 3624 (void)vgetc(); 3625 got_int = FALSE; 3626 } 3627 3628 /* we found no match if the list has only the "compl_orig_text"-entry */ 3629 if (compl_first_match == compl_first_match->cp_next) 3630 { 3631 edit_submode_extra = (compl_cont_status & CONT_ADDING) 3632 && compl_length > 1 3633 ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf); 3634 edit_submode_highl = HLF_E; 3635 /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode, 3636 * because we couldn't expand anything at first place, but if we used 3637 * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word 3638 * (such as M in M'exico) if not tried already. -- Acevedo */ 3639 if ( compl_length > 1 3640 || (compl_cont_status & CONT_ADDING) 3641 || (ctrl_x_mode != 0 3642 && ctrl_x_mode != CTRL_X_PATH_PATTERNS 3643 && ctrl_x_mode != CTRL_X_PATH_DEFINES)) 3644 compl_cont_status &= ~CONT_N_ADDS; 3645 } 3646 3647 if (compl_curr_match->cp_flags & CONT_S_IPOS) 3648 compl_cont_status |= CONT_S_IPOS; 3649 else 3650 compl_cont_status &= ~CONT_S_IPOS; 3651 3652 if (edit_submode_extra == NULL) 3653 { 3654 if (compl_curr_match->cp_flags & ORIGINAL_TEXT) 3655 { 3656 edit_submode_extra = (char_u *)_("Back at original"); 3657 edit_submode_highl = HLF_W; 3658 } 3659 else if (compl_cont_status & CONT_S_IPOS) 3660 { 3661 edit_submode_extra = (char_u *)_("Word from other line"); 3662 edit_submode_highl = HLF_COUNT; 3663 } 3664 else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) 3665 { 3666 edit_submode_extra = (char_u *)_("The only match"); 3667 edit_submode_highl = HLF_COUNT; 3668 } 3669 else 3670 { 3671 /* Update completion sequence number when needed. */ 3672 if (compl_curr_match->cp_number == -1) 3673 { 3674 int number = 0; 3675 compl_T *match; 3676 3677 if (compl_direction == FORWARD) 3678 { 3679 /* search backwards for the first valid (!= -1) number. 3680 * This should normally succeed already at the first loop 3681 * cycle, so it's fast! */ 3682 for (match = compl_curr_match->cp_prev; match != NULL 3683 && match != compl_first_match; 3684 match = match->cp_prev) 3685 if (match->cp_number != -1) 3686 { 3687 number = match->cp_number; 3688 break; 3689 } 3690 if (match != NULL) 3691 /* go up and assign all numbers which are not assigned 3692 * yet */ 3693 for (match = match->cp_next; match 3694 && match->cp_number == -1; 3695 match = match->cp_next) 3696 match->cp_number = ++number; 3697 } 3698 else /* BACKWARD */ 3699 { 3700 /* search forwards (upwards) for the first valid (!= -1) 3701 * number. This should normally succeed already at the 3702 * first loop cycle, so it's fast! */ 3703 for (match = compl_curr_match->cp_next; match != NULL 3704 && match != compl_first_match; 3705 match = match->cp_next) 3706 if (match->cp_number != -1) 3707 { 3708 number = match->cp_number; 3709 break; 3710 } 3711 if (match != NULL) 3712 /* go down and assign all numbers which are not 3713 * assigned yet */ 3714 for (match = match->cp_prev; match 3715 && match->cp_number == -1; 3716 match = match->cp_prev) 3717 match->cp_number = ++number; 3718 } 3719 } 3720 3721 /* The match should always have a sequnce number now, this is just 3722 * a safety check. */ 3723 if (compl_curr_match->cp_number != -1) 3724 { 3725 /* Space for 10 text chars. + 2x10-digit no.s */ 3726 static char_u match_ref[31]; 3727 3728 if (compl_matches > 0) 3729 sprintf((char *)IObuff, _("match %d of %d"), 3730 compl_curr_match->cp_number, compl_matches); 3731 else 3732 sprintf((char *)IObuff, _("match %d"), 3733 compl_curr_match->cp_number); 3734 vim_strncpy(match_ref, IObuff, 30); 3735 edit_submode_extra = match_ref; 3736 edit_submode_highl = HLF_R; 3737 if (dollar_vcol) 3738 curs_columns(FALSE); 3739 } 3740 } 3741 } 3742 3743 /* Show a message about what (completion) mode we're in. */ 3744 showmode(); 3745 if (edit_submode_extra != NULL) 3746 { 3747 if (!p_smd) 3748 msg_attr(edit_submode_extra, 3749 edit_submode_highl < HLF_COUNT 3750 ? hl_attr(edit_submode_highl) : 0); 3751 } 3752 else 3753 msg_clr_cmdline(); /* necessary for "noshowmode" */ 3754 3755 return OK; 3756 } 3757 3758 /* 3759 * Looks in the first "len" chars. of "src" for search-metachars. 3760 * If dest is not NULL the chars. are copied there quoting (with 3761 * a backslash) the metachars, and dest would be NUL terminated. 3762 * Returns the length (needed) of dest 3763 */ 3764 static int 3765 quote_meta(dest, src, len) 3766 char_u *dest; 3767 char_u *src; 3768 int len; 3769 { 3770 int m; 3771 3772 for (m = len; --len >= 0; src++) 3773 { 3774 switch (*src) 3775 { 3776 case '.': 3777 case '*': 3778 case '[': 3779 if (ctrl_x_mode == CTRL_X_DICTIONARY 3780 || ctrl_x_mode == CTRL_X_THESAURUS) 3781 break; 3782 case '~': 3783 if (!p_magic) /* quote these only if magic is set */ 3784 break; 3785 case '\\': 3786 if (ctrl_x_mode == CTRL_X_DICTIONARY 3787 || ctrl_x_mode == CTRL_X_THESAURUS) 3788 break; 3789 case '^': /* currently it's not needed. */ 3790 case '$': 3791 m++; 3792 if (dest != NULL) 3793 *dest++ = '\\'; 3794 break; 3795 } 3796 if (dest != NULL) 3797 *dest++ = *src; 3798 # ifdef FEAT_MBYTE 3799 /* Copy remaining bytes of a multibyte character. */ 3800 if (has_mbyte) 3801 { 3802 int i, mb_len; 3803 3804 mb_len = (*mb_ptr2len)(src) - 1; 3805 if (mb_len > 0 && len >= mb_len) 3806 for (i = 0; i < mb_len; ++i) 3807 { 3808 --len; 3809 ++src; 3810 if (dest != NULL) 3811 *dest++ = *src; 3812 } 3813 } 3814 # endif 3815 } 3816 if (dest != NULL) 3817 *dest = NUL; 3818 3819 return m; 3820 } 3821 #endif /* FEAT_INS_EXPAND */ 3822 3823 /* 3824 * Next character is interpreted literally. 3825 * A one, two or three digit decimal number is interpreted as its byte value. 3826 * If one or two digits are entered, the next character is given to vungetc(). 3827 * For Unicode a character > 255 may be returned. 3828 */ 3829 int 3830 get_literal() 3831 { 3832 int cc; 3833 int nc; 3834 int i; 3835 int hex = FALSE; 3836 int octal = FALSE; 3837 #ifdef FEAT_MBYTE 3838 int unicode = 0; 3839 #endif 3840 3841 if (got_int) 3842 return Ctrl_C; 3843 3844 #ifdef FEAT_GUI 3845 /* 3846 * In GUI there is no point inserting the internal code for a special key. 3847 * It is more useful to insert the string "<KEY>" instead. This would 3848 * probably be useful in a text window too, but it would not be 3849 * vi-compatible (maybe there should be an option for it?) -- webb 3850 */ 3851 if (gui.in_use) 3852 ++allow_keys; 3853 #endif 3854 #ifdef USE_ON_FLY_SCROLL 3855 dont_scroll = TRUE; /* disallow scrolling here */ 3856 #endif 3857 ++no_mapping; /* don't map the next key hits */ 3858 cc = 0; 3859 i = 0; 3860 for (;;) 3861 { 3862 do 3863 nc = safe_vgetc(); 3864 while (nc == K_IGNORE || nc == K_VER_SCROLLBAR 3865 || nc == K_HOR_SCROLLBAR); 3866 #ifdef FEAT_CMDL_INFO 3867 if (!(State & CMDLINE) 3868 # ifdef FEAT_MBYTE 3869 && MB_BYTE2LEN_CHECK(nc) == 1 3870 # endif 3871 ) 3872 add_to_showcmd(nc); 3873 #endif 3874 if (nc == 'x' || nc == 'X') 3875 hex = TRUE; 3876 else if (nc == 'o' || nc == 'O') 3877 octal = TRUE; 3878 #ifdef FEAT_MBYTE 3879 else if (nc == 'u' || nc == 'U') 3880 unicode = nc; 3881 #endif 3882 else 3883 { 3884 if (hex 3885 #ifdef FEAT_MBYTE 3886 || unicode != 0 3887 #endif 3888 ) 3889 { 3890 if (!vim_isxdigit(nc)) 3891 break; 3892 cc = cc * 16 + hex2nr(nc); 3893 } 3894 else if (octal) 3895 { 3896 if (nc < '0' || nc > '7') 3897 break; 3898 cc = cc * 8 + nc - '0'; 3899 } 3900 else 3901 { 3902 if (!VIM_ISDIGIT(nc)) 3903 break; 3904 cc = cc * 10 + nc - '0'; 3905 } 3906 3907 ++i; 3908 } 3909 3910 if (cc > 255 3911 #ifdef FEAT_MBYTE 3912 && unicode == 0 3913 #endif 3914 ) 3915 cc = 255; /* limit range to 0-255 */ 3916 nc = 0; 3917 3918 if (hex) /* hex: up to two chars */ 3919 { 3920 if (i >= 2) 3921 break; 3922 } 3923 #ifdef FEAT_MBYTE 3924 else if (unicode) /* Unicode: up to four or eight chars */ 3925 { 3926 if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8)) 3927 break; 3928 } 3929 #endif 3930 else if (i >= 3) /* decimal or octal: up to three chars */ 3931 break; 3932 } 3933 if (i == 0) /* no number entered */ 3934 { 3935 if (nc == K_ZERO) /* NUL is stored as NL */ 3936 { 3937 cc = '\n'; 3938 nc = 0; 3939 } 3940 else 3941 { 3942 cc = nc; 3943 nc = 0; 3944 } 3945 } 3946 3947 if (cc == 0) /* NUL is stored as NL */ 3948 cc = '\n'; 3949 #ifdef FEAT_MBYTE 3950 if (enc_dbcs && (cc & 0xff) == 0) 3951 cc = '?'; /* don't accept an illegal DBCS char, the NUL in the 3952 second byte will cause trouble! */ 3953 #endif 3954 3955 --no_mapping; 3956 #ifdef FEAT_GUI 3957 if (gui.in_use) 3958 --allow_keys; 3959 #endif 3960 if (nc) 3961 vungetc(nc); 3962 got_int = FALSE; /* CTRL-C typed after CTRL-V is not an interrupt */ 3963 return cc; 3964 } 3965 3966 /* 3967 * Insert character, taking care of special keys and mod_mask 3968 */ 3969 static void 3970 insert_special(c, allow_modmask, ctrlv) 3971 int c; 3972 int allow_modmask; 3973 int ctrlv; /* c was typed after CTRL-V */ 3974 { 3975 char_u *p; 3976 int len; 3977 3978 /* 3979 * Special function key, translate into "<Key>". Up to the last '>' is 3980 * inserted with ins_str(), so as not to replace characters in replace 3981 * mode. 3982 * Only use mod_mask for special keys, to avoid things like <S-Space>, 3983 * unless 'allow_modmask' is TRUE. 3984 */ 3985 #ifdef MACOS 3986 /* Command-key never produces a normal key */ 3987 if (mod_mask & MOD_MASK_CMD) 3988 allow_modmask = TRUE; 3989 #endif 3990 if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) 3991 { 3992 p = get_special_key_name(c, mod_mask); 3993 len = (int)STRLEN(p); 3994 c = p[len - 1]; 3995 if (len > 2) 3996 { 3997 if (stop_arrow() == FAIL) 3998 return; 3999 p[len - 1] = NUL; 4000 ins_str(p); 4001 AppendToRedobuffLit(p); 4002 ctrlv = FALSE; 4003 } 4004 } 4005 if (stop_arrow() == OK) 4006 insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1); 4007 } 4008 4009 /* 4010 * Special characters in this context are those that need processing other 4011 * than the simple insertion that can be performed here. This includes ESC 4012 * which terminates the insert, and CR/NL which need special processing to 4013 * open up a new line. This routine tries to optimize insertions performed by 4014 * the "redo", "undo" or "put" commands, so it needs to know when it should 4015 * stop and defer processing to the "normal" mechanism. 4016 * '0' and '^' are special, because they can be followed by CTRL-D. 4017 */ 4018 #ifdef EBCDIC 4019 # define ISSPECIAL(c) ((c) < ' ' || (c) == '0' || (c) == '^') 4020 #else 4021 # define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^') 4022 #endif 4023 4024 #ifdef FEAT_MBYTE 4025 # define WHITECHAR(cc) (vim_iswhite(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1)))) 4026 #else 4027 # define WHITECHAR(cc) vim_iswhite(cc) 4028 #endif 4029 4030 void 4031 insertchar(c, flags, second_indent) 4032 int c; /* character to insert or NUL */ 4033 int flags; /* INSCHAR_FORMAT, etc. */ 4034 int second_indent; /* indent for second line if >= 0 */ 4035 { 4036 int haveto_redraw = FALSE; 4037 int textwidth; 4038 #ifdef FEAT_COMMENTS 4039 colnr_T leader_len; 4040 char_u *p; 4041 int no_leader = FALSE; 4042 int do_comments = (flags & INSCHAR_DO_COM); 4043 #endif 4044 int fo_white_par; 4045 int first_line = TRUE; 4046 int fo_ins_blank; 4047 #ifdef FEAT_MBYTE 4048 int fo_multibyte; 4049 #endif 4050 int save_char = NUL; 4051 int cc; 4052 4053 textwidth = comp_textwidth(flags & INSCHAR_FORMAT); 4054 fo_ins_blank = has_format_option(FO_INS_BLANK); 4055 #ifdef FEAT_MBYTE 4056 fo_multibyte = has_format_option(FO_MBYTE_BREAK); 4057 #endif 4058 fo_white_par = has_format_option(FO_WHITE_PAR); 4059 4060 /* 4061 * Try to break the line in two or more pieces when: 4062 * - Always do this if we have been called to do formatting only. 4063 * - Always do this when 'formatoptions' has the 'a' flag and the line 4064 * ends in white space. 4065 * - Otherwise: 4066 * - Don't do this if inserting a blank 4067 * - Don't do this if an existing character is being replaced, unless 4068 * we're in VREPLACE mode. 4069 * - Do this if the cursor is not on the line where insert started 4070 * or - 'formatoptions' doesn't have 'l' or the line was not too long 4071 * before the insert. 4072 * - 'formatoptions' doesn't have 'b' or a blank was inserted at or 4073 * before 'textwidth' 4074 */ 4075 if (textwidth 4076 && ((flags & INSCHAR_FORMAT) 4077 || (!vim_iswhite(c) 4078 && !((State & REPLACE_FLAG) 4079 #ifdef FEAT_VREPLACE 4080 && !(State & VREPLACE_FLAG) 4081 #endif 4082 && *ml_get_cursor() != NUL) 4083 && (curwin->w_cursor.lnum != Insstart.lnum 4084 || ((!has_format_option(FO_INS_LONG) 4085 || Insstart_textlen <= (colnr_T)textwidth) 4086 && (!fo_ins_blank 4087 || Insstart_blank_vcol <= (colnr_T)textwidth 4088 )))))) 4089 { 4090 /* 4091 * When 'ai' is off we don't want a space under the cursor to be 4092 * deleted. Replace it with an 'x' temporarily. 4093 */ 4094 if (!curbuf->b_p_ai) 4095 { 4096 cc = gchar_cursor(); 4097 if (vim_iswhite(cc)) 4098 { 4099 save_char = cc; 4100 pchar_cursor('x'); 4101 } 4102 } 4103 4104 /* 4105 * Repeat breaking lines, until the current line is not too long. 4106 */ 4107 while (!got_int) 4108 { 4109 int startcol; /* Cursor column at entry */ 4110 int wantcol; /* column at textwidth border */ 4111 int foundcol; /* column for start of spaces */ 4112 int end_foundcol = 0; /* column for start of word */ 4113 colnr_T len; 4114 colnr_T virtcol; 4115 #ifdef FEAT_VREPLACE 4116 int orig_col = 0; 4117 char_u *saved_text = NULL; 4118 #endif 4119 colnr_T col; 4120 4121 virtcol = get_nolist_virtcol(); 4122 if (virtcol < (colnr_T)textwidth) 4123 break; 4124 4125 #ifdef FEAT_COMMENTS 4126 if (no_leader) 4127 do_comments = FALSE; 4128 else if (!(flags & INSCHAR_FORMAT) 4129 && has_format_option(FO_WRAP_COMS)) 4130 do_comments = TRUE; 4131 4132 /* Don't break until after the comment leader */ 4133 if (do_comments) 4134 leader_len = get_leader_len(ml_get_curline(), NULL, FALSE); 4135 else 4136 leader_len = 0; 4137 4138 /* If the line doesn't start with a comment leader, then don't 4139 * start one in a following broken line. Avoids that a %word 4140 * moved to the start of the next line causes all following lines 4141 * to start with %. */ 4142 if (leader_len == 0) 4143 no_leader = TRUE; 4144 #endif 4145 if (!(flags & INSCHAR_FORMAT) 4146 #ifdef FEAT_COMMENTS 4147 && leader_len == 0 4148 #endif 4149 && !has_format_option(FO_WRAP)) 4150 4151 { 4152 textwidth = 0; 4153 break; 4154 } 4155 if ((startcol = curwin->w_cursor.col) == 0) 4156 break; 4157 4158 /* find column of textwidth border */ 4159 coladvance((colnr_T)textwidth); 4160 wantcol = curwin->w_cursor.col; 4161 4162 curwin->w_cursor.col = startcol - 1; 4163 #ifdef FEAT_MBYTE 4164 /* Correct cursor for multi-byte character. */ 4165 if (has_mbyte) 4166 mb_adjust_cursor(); 4167 #endif 4168 foundcol = 0; 4169 4170 /* 4171 * Find position to break at. 4172 * Stop at first entered white when 'formatoptions' has 'v' 4173 */ 4174 while ((!fo_ins_blank && !has_format_option(FO_INS_VI)) 4175 || curwin->w_cursor.lnum != Insstart.lnum 4176 || curwin->w_cursor.col >= Insstart.col) 4177 { 4178 cc = gchar_cursor(); 4179 if (WHITECHAR(cc)) 4180 { 4181 /* remember position of blank just before text */ 4182 end_foundcol = curwin->w_cursor.col; 4183 4184 /* find start of sequence of blanks */ 4185 while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) 4186 { 4187 dec_cursor(); 4188 cc = gchar_cursor(); 4189 } 4190 if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) 4191 break; /* only spaces in front of text */ 4192 #ifdef FEAT_COMMENTS 4193 /* Don't break until after the comment leader */ 4194 if (curwin->w_cursor.col < leader_len) 4195 break; 4196 #endif 4197 if (has_format_option(FO_ONE_LETTER)) 4198 { 4199 /* do not break after one-letter words */ 4200 if (curwin->w_cursor.col == 0) 4201 break; /* one-letter word at begin */ 4202 4203 col = curwin->w_cursor.col; 4204 dec_cursor(); 4205 cc = gchar_cursor(); 4206 4207 if (WHITECHAR(cc)) 4208 continue; /* one-letter, continue */ 4209 curwin->w_cursor.col = col; 4210 } 4211 #ifdef FEAT_MBYTE 4212 if (has_mbyte) 4213 foundcol = curwin->w_cursor.col 4214 + (*mb_ptr2len)(ml_get_cursor()); 4215 else 4216 #endif 4217 foundcol = curwin->w_cursor.col + 1; 4218 if (curwin->w_cursor.col < (colnr_T)wantcol) 4219 break; 4220 } 4221 #ifdef FEAT_MBYTE 4222 else if (cc >= 0x100 && fo_multibyte 4223 && curwin->w_cursor.col <= (colnr_T)wantcol) 4224 { 4225 /* Break after or before a multi-byte character. */ 4226 foundcol = curwin->w_cursor.col; 4227 if (curwin->w_cursor.col < (colnr_T)wantcol) 4228 foundcol += (*mb_char2len)(cc); 4229 end_foundcol = foundcol; 4230 break; 4231 } 4232 #endif 4233 if (curwin->w_cursor.col == 0) 4234 break; 4235 dec_cursor(); 4236 } 4237 4238 if (foundcol == 0) /* no spaces, cannot break line */ 4239 { 4240 curwin->w_cursor.col = startcol; 4241 break; 4242 } 4243 4244 /* Going to break the line, remove any "$" now. */ 4245 undisplay_dollar(); 4246 4247 /* 4248 * Offset between cursor position and line break is used by replace 4249 * stack functions. VREPLACE does not use this, and backspaces 4250 * over the text instead. 4251 */ 4252 #ifdef FEAT_VREPLACE 4253 if (State & VREPLACE_FLAG) 4254 orig_col = startcol; /* Will start backspacing from here */ 4255 else 4256 #endif 4257 replace_offset = startcol - end_foundcol - 1; 4258 4259 /* 4260 * adjust startcol for spaces that will be deleted and 4261 * characters that will remain on top line 4262 */ 4263 curwin->w_cursor.col = foundcol; 4264 while (cc = gchar_cursor(), WHITECHAR(cc)) 4265 inc_cursor(); 4266 startcol -= curwin->w_cursor.col; 4267 if (startcol < 0) 4268 startcol = 0; 4269 4270 #ifdef FEAT_VREPLACE 4271 if (State & VREPLACE_FLAG) 4272 { 4273 /* 4274 * In VREPLACE mode, we will backspace over the text to be 4275 * wrapped, so save a copy now to put on the next line. 4276 */ 4277 saved_text = vim_strsave(ml_get_cursor()); 4278 curwin->w_cursor.col = orig_col; 4279 if (saved_text == NULL) 4280 break; /* Can't do it, out of memory */ 4281 saved_text[startcol] = NUL; 4282 4283 /* Backspace over characters that will move to the next line */ 4284 if (!fo_white_par) 4285 backspace_until_column(foundcol); 4286 } 4287 else 4288 #endif 4289 { 4290 /* put cursor after pos. to break line */ 4291 if (!fo_white_par) 4292 curwin->w_cursor.col = foundcol; 4293 } 4294 4295 /* 4296 * Split the line just before the margin. 4297 * Only insert/delete lines, but don't really redraw the window. 4298 */ 4299 open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX 4300 + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) 4301 #ifdef FEAT_COMMENTS 4302 + (do_comments ? OPENLINE_DO_COM : 0) 4303 #endif 4304 , old_indent); 4305 old_indent = 0; 4306 4307 replace_offset = 0; 4308 if (first_line) 4309 { 4310 if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) 4311 second_indent = get_number_indent(curwin->w_cursor.lnum -1); 4312 if (second_indent >= 0) 4313 { 4314 #ifdef FEAT_VREPLACE 4315 if (State & VREPLACE_FLAG) 4316 change_indent(INDENT_SET, second_indent, FALSE, NUL); 4317 else 4318 #endif 4319 (void)set_indent(second_indent, SIN_CHANGED); 4320 } 4321 first_line = FALSE; 4322 } 4323 4324 #ifdef FEAT_VREPLACE 4325 if (State & VREPLACE_FLAG) 4326 { 4327 /* 4328 * In VREPLACE mode we have backspaced over the text to be 4329 * moved, now we re-insert it into the new line. 4330 */ 4331 ins_bytes(saved_text); 4332 vim_free(saved_text); 4333 } 4334 else 4335 #endif 4336 { 4337 /* 4338 * Check if cursor is not past the NUL off the line, cindent 4339 * may have added or removed indent. 4340 */ 4341 curwin->w_cursor.col += startcol; 4342 len = (colnr_T)STRLEN(ml_get_curline()); 4343 if (curwin->w_cursor.col > len) 4344 curwin->w_cursor.col = len; 4345 } 4346 4347 haveto_redraw = TRUE; 4348 #ifdef FEAT_CINDENT 4349 can_cindent = TRUE; 4350 #endif 4351 /* moved the cursor, don't autoindent or cindent now */ 4352 did_ai = FALSE; 4353 #ifdef FEAT_SMARTINDENT 4354 did_si = FALSE; 4355 can_si = FALSE; 4356 can_si_back = FALSE; 4357 #endif 4358 line_breakcheck(); 4359 } 4360 4361 if (save_char) /* put back space after cursor */ 4362 pchar_cursor(save_char); 4363 4364 if (c == NUL) /* formatting only */ 4365 return; 4366 if (haveto_redraw) 4367 { 4368 update_topline(); 4369 redraw_curbuf_later(VALID); 4370 } 4371 } 4372 if (c == NUL) /* only formatting was wanted */ 4373 return; 4374 4375 #ifdef FEAT_COMMENTS 4376 /* Check whether this character should end a comment. */ 4377 if (did_ai && (int)c == end_comment_pending) 4378 { 4379 char_u *line; 4380 char_u lead_end[COM_MAX_LEN]; /* end-comment string */ 4381 int middle_len, end_len; 4382 int i; 4383 4384 /* 4385 * Need to remove existing (middle) comment leader and insert end 4386 * comment leader. First, check what comment leader we can find. 4387 */ 4388 i = get_leader_len(line = ml_get_curline(), &p, FALSE); 4389 if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) /* Just checking */ 4390 { 4391 /* Skip middle-comment string */ 4392 while (*p && p[-1] != ':') /* find end of middle flags */ 4393 ++p; 4394 middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 4395 /* Don't count trailing white space for middle_len */ 4396 while (middle_len > 0 && vim_iswhite(lead_end[middle_len - 1])) 4397 --middle_len; 4398 4399 /* Find the end-comment string */ 4400 while (*p && p[-1] != ':') /* find end of end flags */ 4401 ++p; 4402 end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 4403 4404 /* Skip white space before the cursor */ 4405 i = curwin->w_cursor.col; 4406 while (--i >= 0 && vim_iswhite(line[i])) 4407 ; 4408 i++; 4409 4410 /* Skip to before the middle leader */ 4411 i -= middle_len; 4412 4413 /* Check some expected things before we go on */ 4414 if (i >= 0 && lead_end[end_len - 1] == end_comment_pending) 4415 { 4416 /* Backspace over all the stuff we want to replace */ 4417 backspace_until_column(i); 4418 4419 /* 4420 * Insert the end-comment string, except for the last 4421 * character, which will get inserted as normal later. 4422 */ 4423 ins_bytes_len(lead_end, end_len - 1); 4424 } 4425 } 4426 } 4427 end_comment_pending = NUL; 4428 #endif 4429 4430 did_ai = FALSE; 4431 #ifdef FEAT_SMARTINDENT 4432 did_si = FALSE; 4433 can_si = FALSE; 4434 can_si_back = FALSE; 4435 #endif 4436 4437 /* 4438 * If there's any pending input, grab up to INPUT_BUFLEN at once. 4439 * This speeds up normal text input considerably. 4440 * Don't do this when 'cindent' or 'indentexpr' is set, because we might 4441 * need to re-indent at a ':', or any other character (but not what 4442 * 'paste' is set).. 4443 */ 4444 #ifdef USE_ON_FLY_SCROLL 4445 dont_scroll = FALSE; /* allow scrolling here */ 4446 #endif 4447 4448 if ( !ISSPECIAL(c) 4449 #ifdef FEAT_MBYTE 4450 && (!has_mbyte || (*mb_char2len)(c) == 1) 4451 #endif 4452 && vpeekc() != NUL 4453 && !(State & REPLACE_FLAG) 4454 #ifdef FEAT_CINDENT 4455 && !cindent_on() 4456 #endif 4457 #ifdef FEAT_RIGHTLEFT 4458 && !p_ri 4459 #endif 4460 ) 4461 { 4462 #define INPUT_BUFLEN 100 4463 char_u buf[INPUT_BUFLEN + 1]; 4464 int i; 4465 colnr_T virtcol = 0; 4466 4467 buf[0] = c; 4468 i = 1; 4469 if (textwidth) 4470 virtcol = get_nolist_virtcol(); 4471 /* 4472 * Stop the string when: 4473 * - no more chars available 4474 * - finding a special character (command key) 4475 * - buffer is full 4476 * - running into the 'textwidth' boundary 4477 * - need to check for abbreviation: A non-word char after a word-char 4478 */ 4479 while ( (c = vpeekc()) != NUL 4480 && !ISSPECIAL(c) 4481 #ifdef FEAT_MBYTE 4482 && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1) 4483 #endif 4484 && i < INPUT_BUFLEN 4485 && (textwidth == 0 4486 || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth) 4487 && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) 4488 { 4489 #ifdef FEAT_RIGHTLEFT 4490 c = vgetc(); 4491 if (p_hkmap && KeyTyped) 4492 c = hkmap(c); /* Hebrew mode mapping */ 4493 # ifdef FEAT_FKMAP 4494 if (p_fkmap && KeyTyped) 4495 c = fkmap(c); /* Farsi mode mapping */ 4496 # endif 4497 buf[i++] = c; 4498 #else 4499 buf[i++] = vgetc(); 4500 #endif 4501 } 4502 4503 #ifdef FEAT_DIGRAPHS 4504 do_digraph(-1); /* clear digraphs */ 4505 do_digraph(buf[i-1]); /* may be the start of a digraph */ 4506 #endif 4507 buf[i] = NUL; 4508 ins_str(buf); 4509 if (flags & INSCHAR_CTRLV) 4510 { 4511 redo_literal(*buf); 4512 i = 1; 4513 } 4514 else 4515 i = 0; 4516 if (buf[i] != NUL) 4517 AppendToRedobuffLit(buf + i); 4518 } 4519 else 4520 { 4521 #ifdef FEAT_MBYTE 4522 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) 4523 { 4524 char_u buf[MB_MAXBYTES + 1]; 4525 4526 (*mb_char2bytes)(c, buf); 4527 buf[cc] = NUL; 4528 ins_char_bytes(buf, cc); 4529 AppendCharToRedobuff(c); 4530 } 4531 else 4532 #endif 4533 { 4534 ins_char(c); 4535 if (flags & INSCHAR_CTRLV) 4536 redo_literal(c); 4537 else 4538 AppendCharToRedobuff(c); 4539 } 4540 } 4541 } 4542 4543 /* 4544 * Called after inserting or deleting text: When 'formatoptions' includes the 4545 * 'a' flag format from the current line until the end of the paragraph. 4546 * Keep the cursor at the same position relative to the text. 4547 * The caller must have saved the cursor line for undo, following ones will be 4548 * saved here. 4549 */ 4550 void 4551 auto_format(trailblank, prev_line) 4552 int trailblank; /* when TRUE also format with trailing blank */ 4553 int prev_line; /* may start in previous line */ 4554 { 4555 pos_T pos; 4556 colnr_T len; 4557 char_u *old; 4558 char_u *new, *pnew; 4559 int wasatend; 4560 int cc; 4561 4562 if (!has_format_option(FO_AUTO)) 4563 return; 4564 4565 pos = curwin->w_cursor; 4566 old = ml_get_curline(); 4567 4568 /* may remove added space */ 4569 check_auto_format(FALSE); 4570 4571 /* Don't format in Insert mode when the cursor is on a trailing blank, the 4572 * user might insert normal text next. Also skip formatting when "1" is 4573 * in 'formatoptions' and there is a single character before the cursor. 4574 * Otherwise the line would be broken and when typing another non-white 4575 * next they are not joined back together. */ 4576 wasatend = (pos.col == STRLEN(old)); 4577 if (*old != NUL && !trailblank && wasatend) 4578 { 4579 dec_cursor(); 4580 cc = gchar_cursor(); 4581 if (!WHITECHAR(cc) && curwin->w_cursor.col > 0 4582 && has_format_option(FO_ONE_LETTER)) 4583 dec_cursor(); 4584 cc = gchar_cursor(); 4585 if (WHITECHAR(cc)) 4586 { 4587 curwin->w_cursor = pos; 4588 return; 4589 } 4590 curwin->w_cursor = pos; 4591 } 4592 4593 #ifdef FEAT_COMMENTS 4594 /* With the 'c' flag in 'formatoptions' and 't' missing: only format 4595 * comments. */ 4596 if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP) 4597 && get_leader_len(old, NULL, FALSE) == 0) 4598 return; 4599 #endif 4600 4601 /* 4602 * May start formatting in a previous line, so that after "x" a word is 4603 * moved to the previous line if it fits there now. Only when this is not 4604 * the start of a paragraph. 4605 */ 4606 if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) 4607 { 4608 --curwin->w_cursor.lnum; 4609 if (u_save_cursor() == FAIL) 4610 return; 4611 } 4612 4613 /* 4614 * Do the formatting and restore the cursor position. "saved_cursor" will 4615 * be adjusted for the text formatting. 4616 */ 4617 saved_cursor = pos; 4618 format_lines((linenr_T)-1); 4619 curwin->w_cursor = saved_cursor; 4620 saved_cursor.lnum = 0; 4621 4622 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 4623 { 4624 /* "cannot happen" */ 4625 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 4626 coladvance((colnr_T)MAXCOL); 4627 } 4628 else 4629 check_cursor_col(); 4630 4631 /* Insert mode: If the cursor is now after the end of the line while it 4632 * previously wasn't, the line was broken. Because of the rule above we 4633 * need to add a space when 'w' is in 'formatoptions' to keep a paragraph 4634 * formatted. */ 4635 if (!wasatend && has_format_option(FO_WHITE_PAR)) 4636 { 4637 new = ml_get_curline(); 4638 len = STRLEN(new); 4639 if (curwin->w_cursor.col == len) 4640 { 4641 pnew = vim_strnsave(new, len + 2); 4642 pnew[len] = ' '; 4643 pnew[len + 1] = NUL; 4644 ml_replace(curwin->w_cursor.lnum, pnew, FALSE); 4645 /* remove the space later */ 4646 did_add_space = TRUE; 4647 } 4648 else 4649 /* may remove added space */ 4650 check_auto_format(FALSE); 4651 } 4652 4653 check_cursor(); 4654 } 4655 4656 /* 4657 * When an extra space was added to continue a paragraph for auto-formatting, 4658 * delete it now. The space must be under the cursor, just after the insert 4659 * position. 4660 */ 4661 static void 4662 check_auto_format(end_insert) 4663 int end_insert; /* TRUE when ending Insert mode */ 4664 { 4665 int c = ' '; 4666 int cc; 4667 4668 if (did_add_space) 4669 { 4670 cc = gchar_cursor(); 4671 if (!WHITECHAR(cc)) 4672 /* Somehow the space was removed already. */ 4673 did_add_space = FALSE; 4674 else 4675 { 4676 if (!end_insert) 4677 { 4678 inc_cursor(); 4679 c = gchar_cursor(); 4680 dec_cursor(); 4681 } 4682 if (c != NUL) 4683 { 4684 /* The space is no longer at the end of the line, delete it. */ 4685 del_char(FALSE); 4686 did_add_space = FALSE; 4687 } 4688 } 4689 } 4690 } 4691 4692 /* 4693 * Find out textwidth to be used for formatting: 4694 * if 'textwidth' option is set, use it 4695 * else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin' 4696 * if invalid value, use 0. 4697 * Set default to window width (maximum 79) for "gq" operator. 4698 */ 4699 int 4700 comp_textwidth(ff) 4701 int ff; /* force formatting (for "Q" command) */ 4702 { 4703 int textwidth; 4704 4705 textwidth = curbuf->b_p_tw; 4706 if (textwidth == 0 && curbuf->b_p_wm) 4707 { 4708 /* The width is the window width minus 'wrapmargin' minus all the 4709 * things that add to the margin. */ 4710 textwidth = W_WIDTH(curwin) - curbuf->b_p_wm; 4711 #ifdef FEAT_CMDWIN 4712 if (cmdwin_type != 0) 4713 textwidth -= 1; 4714 #endif 4715 #ifdef FEAT_FOLDING 4716 textwidth -= curwin->w_p_fdc; 4717 #endif 4718 #ifdef FEAT_SIGNS 4719 if (curwin->w_buffer->b_signlist != NULL 4720 # ifdef FEAT_NETBEANS_INTG 4721 || usingNetbeans 4722 # endif 4723 ) 4724 textwidth -= 1; 4725 #endif 4726 if (curwin->w_p_nu) 4727 textwidth -= 8; 4728 } 4729 if (textwidth < 0) 4730 textwidth = 0; 4731 if (ff && textwidth == 0) 4732 { 4733 textwidth = W_WIDTH(curwin) - 1; 4734 if (textwidth > 79) 4735 textwidth = 79; 4736 } 4737 return textwidth; 4738 } 4739 4740 /* 4741 * Put a character in the redo buffer, for when just after a CTRL-V. 4742 */ 4743 static void 4744 redo_literal(c) 4745 int c; 4746 { 4747 char_u buf[10]; 4748 4749 /* Only digits need special treatment. Translate them into a string of 4750 * three digits. */ 4751 if (VIM_ISDIGIT(c)) 4752 { 4753 sprintf((char *)buf, "%03d", c); 4754 AppendToRedobuff(buf); 4755 } 4756 else 4757 AppendCharToRedobuff(c); 4758 } 4759 4760 /* 4761 * start_arrow() is called when an arrow key is used in insert mode. 4762 * It resembles hitting the <ESC> key. 4763 */ 4764 static void 4765 start_arrow(end_insert_pos) 4766 pos_T *end_insert_pos; 4767 { 4768 if (!arrow_used) /* something has been inserted */ 4769 { 4770 AppendToRedobuff(ESC_STR); 4771 stop_insert(end_insert_pos, FALSE); 4772 arrow_used = TRUE; /* this means we stopped the current insert */ 4773 } 4774 #ifdef FEAT_SYN_HL 4775 check_spell_redraw(); 4776 #endif 4777 } 4778 4779 #ifdef FEAT_SYN_HL 4780 /* 4781 * If we skipped highlighting word at cursor, do it now. 4782 * It may be skipped again, thus reset spell_redraw_lnum first. 4783 */ 4784 static void 4785 check_spell_redraw() 4786 { 4787 if (spell_redraw_lnum != 0) 4788 { 4789 linenr_T lnum = spell_redraw_lnum; 4790 4791 spell_redraw_lnum = 0; 4792 redrawWinline(lnum, FALSE); 4793 } 4794 } 4795 #endif 4796 4797 /* 4798 * stop_arrow() is called before a change is made in insert mode. 4799 * If an arrow key has been used, start a new insertion. 4800 * Returns FAIL if undo is impossible, shouldn't insert then. 4801 */ 4802 int 4803 stop_arrow() 4804 { 4805 if (arrow_used) 4806 { 4807 if (u_save_cursor() == OK) 4808 { 4809 arrow_used = FALSE; 4810 ins_need_undo = FALSE; 4811 } 4812 Insstart = curwin->w_cursor; /* new insertion starts here */ 4813 Insstart_textlen = linetabsize(ml_get_curline()); 4814 ai_col = 0; 4815 #ifdef FEAT_VREPLACE 4816 if (State & VREPLACE_FLAG) 4817 { 4818 orig_line_count = curbuf->b_ml.ml_line_count; 4819 vr_lines_changed = 1; 4820 } 4821 #endif 4822 ResetRedobuff(); 4823 AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */ 4824 } 4825 else if (ins_need_undo) 4826 { 4827 if (u_save_cursor() == OK) 4828 ins_need_undo = FALSE; 4829 } 4830 4831 #ifdef FEAT_FOLDING 4832 /* Always open fold at the cursor line when inserting something. */ 4833 foldOpenCursor(); 4834 #endif 4835 4836 return (arrow_used || ins_need_undo ? FAIL : OK); 4837 } 4838 4839 /* 4840 * do a few things to stop inserting 4841 */ 4842 static void 4843 stop_insert(end_insert_pos, esc) 4844 pos_T *end_insert_pos; /* where insert ended */ 4845 int esc; /* called by ins_esc() */ 4846 { 4847 int cc; 4848 4849 stop_redo_ins(); 4850 replace_flush(); /* abandon replace stack */ 4851 4852 /* 4853 * save the inserted text for later redo with ^@ 4854 */ 4855 vim_free(last_insert); 4856 last_insert = get_inserted(); 4857 last_insert_skip = new_insert_skip; 4858 4859 if (!arrow_used) 4860 { 4861 /* Auto-format now. It may seem strange to do this when stopping an 4862 * insertion (or moving the cursor), but it's required when appending 4863 * a line and having it end in a space. But only do it when something 4864 * was actually inserted, otherwise undo won't work. */ 4865 if (!ins_need_undo && has_format_option(FO_AUTO)) 4866 { 4867 pos_T tpos = curwin->w_cursor; 4868 4869 /* When the cursor is at the end of the line after a space the 4870 * formatting will move it to the following word. Avoid that by 4871 * moving the cursor onto the space. */ 4872 cc = 'x'; 4873 if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL) 4874 { 4875 dec_cursor(); 4876 cc = gchar_cursor(); 4877 if (!vim_iswhite(cc)) 4878 curwin->w_cursor = tpos; 4879 } 4880 4881 auto_format(TRUE, FALSE); 4882 4883 if (vim_iswhite(cc)) 4884 { 4885 if (gchar_cursor() != NUL) 4886 inc_cursor(); 4887 #ifdef FEAT_VIRTUALEDIT 4888 /* If the cursor is still at the same character, also keep 4889 * the "coladd". */ 4890 if (gchar_cursor() == NUL 4891 && curwin->w_cursor.lnum == tpos.lnum 4892 && curwin->w_cursor.col == tpos.col) 4893 curwin->w_cursor.coladd = tpos.coladd; 4894 #endif 4895 } 4896 } 4897 4898 /* If a space was inserted for auto-formatting, remove it now. */ 4899 check_auto_format(TRUE); 4900 4901 /* If we just did an auto-indent, remove the white space from the end 4902 * of the line, and put the cursor back. 4903 * Do this when ESC was used or moving the cursor up/down. */ 4904 if (did_ai && (esc || (vim_strchr(p_cpo, CPO_INDENT) == NULL 4905 && curwin->w_cursor.lnum != end_insert_pos->lnum))) 4906 { 4907 pos_T tpos = curwin->w_cursor; 4908 4909 curwin->w_cursor = *end_insert_pos; 4910 if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) 4911 --curwin->w_cursor.col; 4912 while (cc = gchar_cursor(), vim_iswhite(cc)) 4913 (void)del_char(TRUE); 4914 if (curwin->w_cursor.lnum != tpos.lnum) 4915 curwin->w_cursor = tpos; 4916 else if (cc != NUL) 4917 ++curwin->w_cursor.col; /* put cursor back on the NUL */ 4918 4919 #ifdef FEAT_VISUAL 4920 /* <C-S-Right> may have started Visual mode, adjust the position for 4921 * deleted characters. */ 4922 if (VIsual_active && VIsual.lnum == curwin->w_cursor.lnum) 4923 { 4924 cc = STRLEN(ml_get_curline()); 4925 if (VIsual.col > (colnr_T)cc) 4926 { 4927 VIsual.col = cc; 4928 # ifdef FEAT_VIRTUALEDIT 4929 VIsual.coladd = 0; 4930 # endif 4931 } 4932 } 4933 #endif 4934 } 4935 } 4936 did_ai = FALSE; 4937 #ifdef FEAT_SMARTINDENT 4938 did_si = FALSE; 4939 can_si = FALSE; 4940 can_si_back = FALSE; 4941 #endif 4942 4943 /* set '[ and '] to the inserted text */ 4944 curbuf->b_op_start = Insstart; 4945 curbuf->b_op_end = *end_insert_pos; 4946 } 4947 4948 /* 4949 * Set the last inserted text to a single character. 4950 * Used for the replace command. 4951 */ 4952 void 4953 set_last_insert(c) 4954 int c; 4955 { 4956 char_u *s; 4957 4958 vim_free(last_insert); 4959 #ifdef FEAT_MBYTE 4960 last_insert = alloc(MB_MAXBYTES * 3 + 5); 4961 #else 4962 last_insert = alloc(6); 4963 #endif 4964 if (last_insert != NULL) 4965 { 4966 s = last_insert; 4967 /* Use the CTRL-V only when entering a special char */ 4968 if (c < ' ' || c == DEL) 4969 *s++ = Ctrl_V; 4970 s = add_char2buf(c, s); 4971 *s++ = ESC; 4972 *s++ = NUL; 4973 last_insert_skip = 0; 4974 } 4975 } 4976 4977 #if defined(EXITFREE) || defined(PROTO) 4978 void 4979 free_last_insert() 4980 { 4981 vim_free(last_insert); 4982 last_insert = NULL; 4983 } 4984 #endif 4985 4986 /* 4987 * Add character "c" to buffer "s". Escape the special meaning of K_SPECIAL 4988 * and CSI. Handle multi-byte characters. 4989 * Returns a pointer to after the added bytes. 4990 */ 4991 char_u * 4992 add_char2buf(c, s) 4993 int c; 4994 char_u *s; 4995 { 4996 #ifdef FEAT_MBYTE 4997 char_u temp[MB_MAXBYTES]; 4998 int i; 4999 int len; 5000 5001 len = (*mb_char2bytes)(c, temp); 5002 for (i = 0; i < len; ++i) 5003 { 5004 c = temp[i]; 5005 #endif 5006 /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */ 5007 if (c == K_SPECIAL) 5008 { 5009 *s++ = K_SPECIAL; 5010 *s++ = KS_SPECIAL; 5011 *s++ = KE_FILLER; 5012 } 5013 #ifdef FEAT_GUI 5014 else if (c == CSI) 5015 { 5016 *s++ = CSI; 5017 *s++ = KS_EXTRA; 5018 *s++ = (int)KE_CSI; 5019 } 5020 #endif 5021 else 5022 *s++ = c; 5023 #ifdef FEAT_MBYTE 5024 } 5025 #endif 5026 return s; 5027 } 5028 5029 /* 5030 * move cursor to start of line 5031 * if flags & BL_WHITE move to first non-white 5032 * if flags & BL_SOL move to first non-white if startofline is set, 5033 * otherwise keep "curswant" column 5034 * if flags & BL_FIX don't leave the cursor on a NUL. 5035 */ 5036 void 5037 beginline(flags) 5038 int flags; 5039 { 5040 if ((flags & BL_SOL) && !p_sol) 5041 coladvance(curwin->w_curswant); 5042 else 5043 { 5044 curwin->w_cursor.col = 0; 5045 #ifdef FEAT_VIRTUALEDIT 5046 curwin->w_cursor.coladd = 0; 5047 #endif 5048 5049 if (flags & (BL_WHITE | BL_SOL)) 5050 { 5051 char_u *ptr; 5052 5053 for (ptr = ml_get_curline(); vim_iswhite(*ptr) 5054 && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) 5055 ++curwin->w_cursor.col; 5056 } 5057 curwin->w_set_curswant = TRUE; 5058 } 5059 } 5060 5061 /* 5062 * oneright oneleft cursor_down cursor_up 5063 * 5064 * Move one char {right,left,down,up}. 5065 * Doesn't move onto the NUL past the end of the line. 5066 * Return OK when successful, FAIL when we hit a line of file boundary. 5067 */ 5068 5069 int 5070 oneright() 5071 { 5072 char_u *ptr; 5073 #ifdef FEAT_MBYTE 5074 int l; 5075 #endif 5076 5077 #ifdef FEAT_VIRTUALEDIT 5078 if (virtual_active()) 5079 { 5080 pos_T prevpos = curwin->w_cursor; 5081 5082 /* Adjust for multi-wide char (excluding TAB) */ 5083 ptr = ml_get_cursor(); 5084 coladvance(getviscol() + ((*ptr != TAB && vim_isprintc( 5085 #ifdef FEAT_MBYTE 5086 (*mb_ptr2char)(ptr) 5087 #else 5088 *ptr 5089 #endif 5090 )) 5091 ? ptr2cells(ptr) : 1)); 5092 curwin->w_set_curswant = TRUE; 5093 /* Return OK if the cursor moved, FAIL otherwise (at window edge). */ 5094 return (prevpos.col != curwin->w_cursor.col 5095 || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; 5096 } 5097 #endif 5098 5099 ptr = ml_get_cursor(); 5100 #ifdef FEAT_MBYTE 5101 if (has_mbyte && (l = (*mb_ptr2len)(ptr)) > 1) 5102 { 5103 /* The character under the cursor is a multi-byte character, move 5104 * several bytes right, but don't end up on the NUL. */ 5105 if (ptr[l] == NUL) 5106 return FAIL; 5107 curwin->w_cursor.col += l; 5108 } 5109 else 5110 #endif 5111 { 5112 if (*ptr++ == NUL || *ptr == NUL) 5113 return FAIL; 5114 ++curwin->w_cursor.col; 5115 } 5116 5117 curwin->w_set_curswant = TRUE; 5118 return OK; 5119 } 5120 5121 int 5122 oneleft() 5123 { 5124 #ifdef FEAT_VIRTUALEDIT 5125 if (virtual_active()) 5126 { 5127 int width; 5128 int v = getviscol(); 5129 5130 if (v == 0) 5131 return FAIL; 5132 5133 # ifdef FEAT_LINEBREAK 5134 /* We might get stuck on 'showbreak', skip over it. */ 5135 width = 1; 5136 for (;;) 5137 { 5138 coladvance(v - width); 5139 /* getviscol() is slow, skip it when 'showbreak' is empty and 5140 * there are no multi-byte characters */ 5141 if ((*p_sbr == NUL 5142 # ifdef FEAT_MBYTE 5143 && !has_mbyte 5144 # endif 5145 ) || getviscol() < v) 5146 break; 5147 ++width; 5148 } 5149 # else 5150 coladvance(v - 1); 5151 # endif 5152 5153 if (curwin->w_cursor.coladd == 1) 5154 { 5155 char_u *ptr; 5156 5157 /* Adjust for multi-wide char (not a TAB) */ 5158 ptr = ml_get_cursor(); 5159 if (*ptr != TAB && vim_isprintc( 5160 # ifdef FEAT_MBYTE 5161 (*mb_ptr2char)(ptr) 5162 # else 5163 *ptr 5164 # endif 5165 ) && ptr2cells(ptr) > 1) 5166 curwin->w_cursor.coladd = 0; 5167 } 5168 5169 curwin->w_set_curswant = TRUE; 5170 return OK; 5171 } 5172 #endif 5173 5174 if (curwin->w_cursor.col == 0) 5175 return FAIL; 5176 5177 curwin->w_set_curswant = TRUE; 5178 --curwin->w_cursor.col; 5179 5180 #ifdef FEAT_MBYTE 5181 /* if the character on the left of the current cursor is a multi-byte 5182 * character, move to its first byte */ 5183 if (has_mbyte) 5184 mb_adjust_cursor(); 5185 #endif 5186 return OK; 5187 } 5188 5189 int 5190 cursor_up(n, upd_topline) 5191 long n; 5192 int upd_topline; /* When TRUE: update topline */ 5193 { 5194 linenr_T lnum; 5195 5196 if (n > 0) 5197 { 5198 lnum = curwin->w_cursor.lnum; 5199 /* This fails if the cursor is already in the first line or the count 5200 * is larger than the line number and '-' is in 'cpoptions' */ 5201 if (lnum <= 1 || (n >= lnum && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 5202 return FAIL; 5203 if (n >= lnum) 5204 lnum = 1; 5205 else 5206 #ifdef FEAT_FOLDING 5207 if (hasAnyFolding(curwin)) 5208 { 5209 /* 5210 * Count each sequence of folded lines as one logical line. 5211 */ 5212 /* go to the the start of the current fold */ 5213 (void)hasFolding(lnum, &lnum, NULL); 5214 5215 while (n--) 5216 { 5217 /* move up one line */ 5218 --lnum; 5219 if (lnum <= 1) 5220 break; 5221 /* If we entered a fold, move to the beginning, unless in 5222 * Insert mode or when 'foldopen' contains "all": it will open 5223 * in a moment. */ 5224 if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL))) 5225 (void)hasFolding(lnum, &lnum, NULL); 5226 } 5227 if (lnum < 1) 5228 lnum = 1; 5229 } 5230 else 5231 #endif 5232 lnum -= n; 5233 curwin->w_cursor.lnum = lnum; 5234 } 5235 5236 /* try to advance to the column we want to be at */ 5237 coladvance(curwin->w_curswant); 5238 5239 if (upd_topline) 5240 update_topline(); /* make sure curwin->w_topline is valid */ 5241 5242 return OK; 5243 } 5244 5245 /* 5246 * Cursor down a number of logical lines. 5247 */ 5248 int 5249 cursor_down(n, upd_topline) 5250 long n; 5251 int upd_topline; /* When TRUE: update topline */ 5252 { 5253 linenr_T lnum; 5254 5255 if (n > 0) 5256 { 5257 lnum = curwin->w_cursor.lnum; 5258 #ifdef FEAT_FOLDING 5259 /* Move to last line of fold, will fail if it's the end-of-file. */ 5260 (void)hasFolding(lnum, NULL, &lnum); 5261 #endif 5262 /* This fails if the cursor is already in the last line or would move 5263 * beyound the last line and '-' is in 'cpoptions' */ 5264 if (lnum >= curbuf->b_ml.ml_line_count 5265 || (lnum + n > curbuf->b_ml.ml_line_count 5266 && vim_strchr(p_cpo, CPO_MINUS) != NULL)) 5267 return FAIL; 5268 if (lnum + n >= curbuf->b_ml.ml_line_count) 5269 lnum = curbuf->b_ml.ml_line_count; 5270 else 5271 #ifdef FEAT_FOLDING 5272 if (hasAnyFolding(curwin)) 5273 { 5274 linenr_T last; 5275 5276 /* count each sequence of folded lines as one logical line */ 5277 while (n--) 5278 { 5279 if (hasFolding(lnum, NULL, &last)) 5280 lnum = last + 1; 5281 else 5282 ++lnum; 5283 if (lnum >= curbuf->b_ml.ml_line_count) 5284 break; 5285 } 5286 if (lnum > curbuf->b_ml.ml_line_count) 5287 lnum = curbuf->b_ml.ml_line_count; 5288 } 5289 else 5290 #endif 5291 lnum += n; 5292 curwin->w_cursor.lnum = lnum; 5293 } 5294 5295 /* try to advance to the column we want to be at */ 5296 coladvance(curwin->w_curswant); 5297 5298 if (upd_topline) 5299 update_topline(); /* make sure curwin->w_topline is valid */ 5300 5301 return OK; 5302 } 5303 5304 /* 5305 * Stuff the last inserted text in the read buffer. 5306 * Last_insert actually is a copy of the redo buffer, so we 5307 * first have to remove the command. 5308 */ 5309 int 5310 stuff_inserted(c, count, no_esc) 5311 int c; /* Command character to be inserted */ 5312 long count; /* Repeat this many times */ 5313 int no_esc; /* Don't add an ESC at the end */ 5314 { 5315 char_u *esc_ptr; 5316 char_u *ptr; 5317 char_u *last_ptr; 5318 char_u last = NUL; 5319 5320 ptr = get_last_insert(); 5321 if (ptr == NULL) 5322 { 5323 EMSG(_(e_noinstext)); 5324 return FAIL; 5325 } 5326 5327 /* may want to stuff the command character, to start Insert mode */ 5328 if (c != NUL) 5329 stuffcharReadbuff(c); 5330 if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL) 5331 *esc_ptr = NUL; /* remove the ESC */ 5332 5333 /* when the last char is either "0" or "^" it will be quoted if no ESC 5334 * comes after it OR if it will inserted more than once and "ptr" 5335 * starts with ^D. -- Acevedo 5336 */ 5337 last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1; 5338 if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^') 5339 && (no_esc || (*ptr == Ctrl_D && count > 1))) 5340 { 5341 last = *last_ptr; 5342 *last_ptr = NUL; 5343 } 5344 5345 do 5346 { 5347 stuffReadbuff(ptr); 5348 /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */ 5349 if (last) 5350 stuffReadbuff((char_u *)(last == '0' 5351 ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0") 5352 : IF_EB("\026^", CTRL_V_STR "^"))); 5353 } 5354 while (--count > 0); 5355 5356 if (last) 5357 *last_ptr = last; 5358 5359 if (esc_ptr != NULL) 5360 *esc_ptr = ESC; /* put the ESC back */ 5361 5362 /* may want to stuff a trailing ESC, to get out of Insert mode */ 5363 if (!no_esc) 5364 stuffcharReadbuff(ESC); 5365 5366 return OK; 5367 } 5368 5369 char_u * 5370 get_last_insert() 5371 { 5372 if (last_insert == NULL) 5373 return NULL; 5374 return last_insert + last_insert_skip; 5375 } 5376 5377 /* 5378 * Get last inserted string, and remove trailing <Esc>. 5379 * Returns pointer to allocated memory (must be freed) or NULL. 5380 */ 5381 char_u * 5382 get_last_insert_save() 5383 { 5384 char_u *s; 5385 int len; 5386 5387 if (last_insert == NULL) 5388 return NULL; 5389 s = vim_strsave(last_insert + last_insert_skip); 5390 if (s != NULL) 5391 { 5392 len = (int)STRLEN(s); 5393 if (len > 0 && s[len - 1] == ESC) /* remove trailing ESC */ 5394 s[len - 1] = NUL; 5395 } 5396 return s; 5397 } 5398 5399 /* 5400 * Check the word in front of the cursor for an abbreviation. 5401 * Called when the non-id character "c" has been entered. 5402 * When an abbreviation is recognized it is removed from the text and 5403 * the replacement string is inserted in typebuf.tb_buf[], followed by "c". 5404 */ 5405 static int 5406 echeck_abbr(c) 5407 int c; 5408 { 5409 /* Don't check for abbreviation in paste mode, when disabled and just 5410 * after moving around with cursor keys. */ 5411 if (p_paste || no_abbr || arrow_used) 5412 return FALSE; 5413 5414 return check_abbr(c, ml_get_curline(), curwin->w_cursor.col, 5415 curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0); 5416 } 5417 5418 /* 5419 * replace-stack functions 5420 * 5421 * When replacing characters, the replaced characters are remembered for each 5422 * new character. This is used to re-insert the old text when backspacing. 5423 * 5424 * There is a NUL headed list of characters for each character that is 5425 * currently in the file after the insertion point. When BS is used, one NUL 5426 * headed list is put back for the deleted character. 5427 * 5428 * For a newline, there are two NUL headed lists. One contains the characters 5429 * that the NL replaced. The extra one stores the characters after the cursor 5430 * that were deleted (always white space). 5431 * 5432 * Replace_offset is normally 0, in which case replace_push will add a new 5433 * character at the end of the stack. If replace_offset is not 0, that many 5434 * characters will be left on the stack above the newly inserted character. 5435 */ 5436 5437 static char_u *replace_stack = NULL; 5438 static long replace_stack_nr = 0; /* next entry in replace stack */ 5439 static long replace_stack_len = 0; /* max. number of entries */ 5440 5441 void 5442 replace_push(c) 5443 int c; /* character that is replaced (NUL is none) */ 5444 { 5445 char_u *p; 5446 5447 if (replace_stack_nr < replace_offset) /* nothing to do */ 5448 return; 5449 if (replace_stack_len <= replace_stack_nr) 5450 { 5451 replace_stack_len += 50; 5452 p = lalloc(sizeof(char_u) * replace_stack_len, TRUE); 5453 if (p == NULL) /* out of memory */ 5454 { 5455 replace_stack_len -= 50; 5456 return; 5457 } 5458 if (replace_stack != NULL) 5459 { 5460 mch_memmove(p, replace_stack, 5461 (size_t)(replace_stack_nr * sizeof(char_u))); 5462 vim_free(replace_stack); 5463 } 5464 replace_stack = p; 5465 } 5466 p = replace_stack + replace_stack_nr - replace_offset; 5467 if (replace_offset) 5468 mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u))); 5469 *p = c; 5470 ++replace_stack_nr; 5471 } 5472 5473 /* 5474 * call replace_push(c) with replace_offset set to the first NUL. 5475 */ 5476 static void 5477 replace_push_off(c) 5478 int c; 5479 { 5480 char_u *p; 5481 5482 p = replace_stack + replace_stack_nr; 5483 for (replace_offset = 1; replace_offset < replace_stack_nr; 5484 ++replace_offset) 5485 if (*--p == NUL) 5486 break; 5487 replace_push(c); 5488 replace_offset = 0; 5489 } 5490 5491 /* 5492 * Pop one item from the replace stack. 5493 * return -1 if stack empty 5494 * return replaced character or NUL otherwise 5495 */ 5496 static int 5497 replace_pop() 5498 { 5499 if (replace_stack_nr == 0) 5500 return -1; 5501 return (int)replace_stack[--replace_stack_nr]; 5502 } 5503 5504 /* 5505 * Join the top two items on the replace stack. This removes to "off"'th NUL 5506 * encountered. 5507 */ 5508 static void 5509 replace_join(off) 5510 int off; /* offset for which NUL to remove */ 5511 { 5512 int i; 5513 5514 for (i = replace_stack_nr; --i >= 0; ) 5515 if (replace_stack[i] == NUL && off-- <= 0) 5516 { 5517 --replace_stack_nr; 5518 mch_memmove(replace_stack + i, replace_stack + i + 1, 5519 (size_t)(replace_stack_nr - i)); 5520 return; 5521 } 5522 } 5523 5524 /* 5525 * Pop bytes from the replace stack until a NUL is found, and insert them 5526 * before the cursor. Can only be used in REPLACE or VREPLACE mode. 5527 */ 5528 static void 5529 replace_pop_ins() 5530 { 5531 int cc; 5532 int oldState = State; 5533 5534 State = NORMAL; /* don't want REPLACE here */ 5535 while ((cc = replace_pop()) > 0) 5536 { 5537 #ifdef FEAT_MBYTE 5538 mb_replace_pop_ins(cc); 5539 #else 5540 ins_char(cc); 5541 #endif 5542 dec_cursor(); 5543 } 5544 State = oldState; 5545 } 5546 5547 #ifdef FEAT_MBYTE 5548 /* 5549 * Insert bytes popped from the replace stack. "cc" is the first byte. If it 5550 * indicates a multi-byte char, pop the other bytes too. 5551 */ 5552 static void 5553 mb_replace_pop_ins(cc) 5554 int cc; 5555 { 5556 int n; 5557 char_u buf[MB_MAXBYTES]; 5558 int i; 5559 int c; 5560 5561 if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1) 5562 { 5563 buf[0] = cc; 5564 for (i = 1; i < n; ++i) 5565 buf[i] = replace_pop(); 5566 ins_bytes_len(buf, n); 5567 } 5568 else 5569 ins_char(cc); 5570 5571 if (enc_utf8) 5572 /* Handle composing chars. */ 5573 for (;;) 5574 { 5575 c = replace_pop(); 5576 if (c == -1) /* stack empty */ 5577 break; 5578 if ((n = MB_BYTE2LEN(c)) == 1) 5579 { 5580 /* Not a multi-byte char, put it back. */ 5581 replace_push(c); 5582 break; 5583 } 5584 else 5585 { 5586 buf[0] = c; 5587 for (i = 1; i < n; ++i) 5588 buf[i] = replace_pop(); 5589 if (utf_iscomposing(utf_ptr2char(buf))) 5590 ins_bytes_len(buf, n); 5591 else 5592 { 5593 /* Not a composing char, put it back. */ 5594 for (i = n - 1; i >= 0; --i) 5595 replace_push(buf[i]); 5596 break; 5597 } 5598 } 5599 } 5600 } 5601 #endif 5602 5603 /* 5604 * make the replace stack empty 5605 * (called when exiting replace mode) 5606 */ 5607 static void 5608 replace_flush() 5609 { 5610 vim_free(replace_stack); 5611 replace_stack = NULL; 5612 replace_stack_len = 0; 5613 replace_stack_nr = 0; 5614 } 5615 5616 /* 5617 * Handle doing a BS for one character. 5618 * cc < 0: replace stack empty, just move cursor 5619 * cc == 0: character was inserted, delete it 5620 * cc > 0: character was replaced, put cc (first byte of original char) back 5621 * and check for more characters to be put back 5622 */ 5623 static void 5624 replace_do_bs() 5625 { 5626 int cc; 5627 #ifdef FEAT_VREPLACE 5628 int orig_len = 0; 5629 int ins_len; 5630 int orig_vcols = 0; 5631 colnr_T start_vcol; 5632 char_u *p; 5633 int i; 5634 int vcol; 5635 #endif 5636 5637 cc = replace_pop(); 5638 if (cc > 0) 5639 { 5640 #ifdef FEAT_VREPLACE 5641 if (State & VREPLACE_FLAG) 5642 { 5643 /* Get the number of screen cells used by the character we are 5644 * going to delete. */ 5645 getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL); 5646 orig_vcols = chartabsize(ml_get_cursor(), start_vcol); 5647 } 5648 #endif 5649 #ifdef FEAT_MBYTE 5650 if (has_mbyte) 5651 { 5652 del_char(FALSE); 5653 # ifdef FEAT_VREPLACE 5654 if (State & VREPLACE_FLAG) 5655 orig_len = STRLEN(ml_get_cursor()); 5656 # endif 5657 replace_push(cc); 5658 } 5659 else 5660 #endif 5661 { 5662 pchar_cursor(cc); 5663 #ifdef FEAT_VREPLACE 5664 if (State & VREPLACE_FLAG) 5665 orig_len = STRLEN(ml_get_cursor()) - 1; 5666 #endif 5667 } 5668 replace_pop_ins(); 5669 5670 #ifdef FEAT_VREPLACE 5671 if (State & VREPLACE_FLAG) 5672 { 5673 /* Get the number of screen cells used by the inserted characters */ 5674 p = ml_get_cursor(); 5675 ins_len = STRLEN(p) - orig_len; 5676 vcol = start_vcol; 5677 for (i = 0; i < ins_len; ++i) 5678 { 5679 vcol += chartabsize(p + i, vcol); 5680 #ifdef FEAT_MBYTE 5681 i += (*mb_ptr2len)(p) - 1; 5682 #endif 5683 } 5684 vcol -= start_vcol; 5685 5686 /* Delete spaces that were inserted after the cursor to keep the 5687 * text aligned. */ 5688 curwin->w_cursor.col += ins_len; 5689 while (vcol > orig_vcols && gchar_cursor() == ' ') 5690 { 5691 del_char(FALSE); 5692 ++orig_vcols; 5693 } 5694 curwin->w_cursor.col -= ins_len; 5695 } 5696 #endif 5697 5698 /* mark the buffer as changed and prepare for displaying */ 5699 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 5700 } 5701 else if (cc == 0) 5702 (void)del_char(FALSE); 5703 } 5704 5705 #ifdef FEAT_CINDENT 5706 /* 5707 * Return TRUE if C-indenting is on. 5708 */ 5709 static int 5710 cindent_on() 5711 { 5712 return (!p_paste && (curbuf->b_p_cin 5713 # ifdef FEAT_EVAL 5714 || *curbuf->b_p_inde != NUL 5715 # endif 5716 )); 5717 } 5718 #endif 5719 5720 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO) 5721 /* 5722 * Re-indent the current line, based on the current contents of it and the 5723 * surrounding lines. Fixing the cursor position seems really easy -- I'm very 5724 * confused what all the part that handles Control-T is doing that I'm not. 5725 * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent. 5726 */ 5727 5728 void 5729 fixthisline(get_the_indent) 5730 int (*get_the_indent) __ARGS((void)); 5731 { 5732 change_indent(INDENT_SET, get_the_indent(), FALSE, 0); 5733 if (linewhite(curwin->w_cursor.lnum)) 5734 did_ai = TRUE; /* delete the indent if the line stays empty */ 5735 } 5736 5737 void 5738 fix_indent() 5739 { 5740 if (p_paste) 5741 return; 5742 # ifdef FEAT_LISP 5743 if (curbuf->b_p_lisp && curbuf->b_p_ai) 5744 fixthisline(get_lisp_indent); 5745 # endif 5746 # if defined(FEAT_LISP) && defined(FEAT_CINDENT) 5747 else 5748 # endif 5749 # ifdef FEAT_CINDENT 5750 if (cindent_on()) 5751 do_c_expr_indent(); 5752 # endif 5753 } 5754 5755 #endif 5756 5757 #ifdef FEAT_CINDENT 5758 /* 5759 * return TRUE if 'cinkeys' contains the key "keytyped", 5760 * when == '*': Only if key is preceded with '*' (indent before insert) 5761 * when == '!': Only if key is prededed with '!' (don't insert) 5762 * when == ' ': Only if key is not preceded with '*'(indent afterwards) 5763 * 5764 * "keytyped" can have a few special values: 5765 * KEY_OPEN_FORW 5766 * KEY_OPEN_BACK 5767 * KEY_COMPLETE just finished completion. 5768 * 5769 * If line_is_empty is TRUE accept keys with '0' before them. 5770 */ 5771 int 5772 in_cinkeys(keytyped, when, line_is_empty) 5773 int keytyped; 5774 int when; 5775 int line_is_empty; 5776 { 5777 char_u *look; 5778 int try_match; 5779 int try_match_word; 5780 char_u *p; 5781 char_u *line; 5782 int icase; 5783 int i; 5784 5785 #ifdef FEAT_EVAL 5786 if (*curbuf->b_p_inde != NUL) 5787 look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */ 5788 else 5789 #endif 5790 look = curbuf->b_p_cink; /* 'indentexpr' empty: use 'cinkeys' */ 5791 while (*look) 5792 { 5793 /* 5794 * Find out if we want to try a match with this key, depending on 5795 * 'when' and a '*' or '!' before the key. 5796 */ 5797 switch (when) 5798 { 5799 case '*': try_match = (*look == '*'); break; 5800 case '!': try_match = (*look == '!'); break; 5801 default: try_match = (*look != '*'); break; 5802 } 5803 if (*look == '*' || *look == '!') 5804 ++look; 5805 5806 /* 5807 * If there is a '0', only accept a match if the line is empty. 5808 * But may still match when typing last char of a word. 5809 */ 5810 if (*look == '0') 5811 { 5812 try_match_word = try_match; 5813 if (!line_is_empty) 5814 try_match = FALSE; 5815 ++look; 5816 } 5817 else 5818 try_match_word = FALSE; 5819 5820 /* 5821 * does it look like a control character? 5822 */ 5823 if (*look == '^' 5824 #ifdef EBCDIC 5825 && (Ctrl_chr(look[1]) != 0) 5826 #else 5827 && look[1] >= '?' && look[1] <= '_' 5828 #endif 5829 ) 5830 { 5831 if (try_match && keytyped == Ctrl_chr(look[1])) 5832 return TRUE; 5833 look += 2; 5834 } 5835 /* 5836 * 'o' means "o" command, open forward. 5837 * 'O' means "O" command, open backward. 5838 */ 5839 else if (*look == 'o') 5840 { 5841 if (try_match && keytyped == KEY_OPEN_FORW) 5842 return TRUE; 5843 ++look; 5844 } 5845 else if (*look == 'O') 5846 { 5847 if (try_match && keytyped == KEY_OPEN_BACK) 5848 return TRUE; 5849 ++look; 5850 } 5851 5852 /* 5853 * 'e' means to check for "else" at start of line and just before the 5854 * cursor. 5855 */ 5856 else if (*look == 'e') 5857 { 5858 if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) 5859 { 5860 p = ml_get_curline(); 5861 if (skipwhite(p) == p + curwin->w_cursor.col - 4 && 5862 STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) 5863 return TRUE; 5864 } 5865 ++look; 5866 } 5867 5868 /* 5869 * ':' only causes an indent if it is at the end of a label or case 5870 * statement, or when it was before typing the ':' (to fix 5871 * class::method for C++). 5872 */ 5873 else if (*look == ':') 5874 { 5875 if (try_match && keytyped == ':') 5876 { 5877 p = ml_get_curline(); 5878 if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30)) 5879 return TRUE; 5880 if (curwin->w_cursor.col > 2 5881 && p[curwin->w_cursor.col - 1] == ':' 5882 && p[curwin->w_cursor.col - 2] == ':') 5883 { 5884 p[curwin->w_cursor.col - 1] = ' '; 5885 i = (cin_iscase(p) || cin_isscopedecl(p) 5886 || cin_islabel(30)); 5887 p = ml_get_curline(); 5888 p[curwin->w_cursor.col - 1] = ':'; 5889 if (i) 5890 return TRUE; 5891 } 5892 } 5893 ++look; 5894 } 5895 5896 5897 /* 5898 * Is it a key in <>, maybe? 5899 */ 5900 else if (*look == '<') 5901 { 5902 if (try_match) 5903 { 5904 /* 5905 * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>, 5906 * <:> and <!> so that people can re-indent on o, O, e, 0, <, 5907 * >, *, : and ! keys if they really really want to. 5908 */ 5909 if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL 5910 && keytyped == look[1]) 5911 return TRUE; 5912 5913 if (keytyped == get_special_key_code(look + 1)) 5914 return TRUE; 5915 } 5916 while (*look && *look != '>') 5917 look++; 5918 while (*look == '>') 5919 look++; 5920 } 5921 5922 /* 5923 * Is it a word: "=word"? 5924 */ 5925 else if (*look == '=' && look[1] != ',' && look[1] != NUL) 5926 { 5927 ++look; 5928 if (*look == '~') 5929 { 5930 icase = TRUE; 5931 ++look; 5932 } 5933 else 5934 icase = FALSE; 5935 p = vim_strchr(look, ','); 5936 if (p == NULL) 5937 p = look + STRLEN(look); 5938 if ((try_match || try_match_word) 5939 && curwin->w_cursor.col >= (colnr_T)(p - look)) 5940 { 5941 int match = FALSE; 5942 5943 #ifdef FEAT_INS_EXPAND 5944 if (keytyped == KEY_COMPLETE) 5945 { 5946 char_u *s; 5947 5948 /* Just completed a word, check if it starts with "look". 5949 * search back for the start of a word. */ 5950 line = ml_get_curline(); 5951 # ifdef FEAT_MBYTE 5952 if (has_mbyte) 5953 { 5954 char_u *n; 5955 5956 for (s = line + curwin->w_cursor.col; s > line; s = n) 5957 { 5958 n = mb_prevptr(line, s); 5959 if (!vim_iswordp(n)) 5960 break; 5961 } 5962 } 5963 else 5964 # endif 5965 for (s = line + curwin->w_cursor.col; s > line; --s) 5966 if (!vim_iswordc(s[-1])) 5967 break; 5968 if (s + (p - look) <= line + curwin->w_cursor.col 5969 && (icase 5970 ? MB_STRNICMP(s, look, p - look) 5971 : STRNCMP(s, look, p - look)) == 0) 5972 match = TRUE; 5973 } 5974 else 5975 #endif 5976 /* TODO: multi-byte */ 5977 if (keytyped == (int)p[-1] || (icase && keytyped < 256 5978 && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) 5979 { 5980 line = ml_get_cursor(); 5981 if ((curwin->w_cursor.col == (colnr_T)(p - look) 5982 || !vim_iswordc(line[-(p - look) - 1])) 5983 && (icase 5984 ? MB_STRNICMP(line - (p - look), look, p - look) 5985 : STRNCMP(line - (p - look), look, p - look)) 5986 == 0) 5987 match = TRUE; 5988 } 5989 if (match && try_match_word && !try_match) 5990 { 5991 /* "0=word": Check if there are only blanks before the 5992 * word. */ 5993 line = ml_get_curline(); 5994 if ((int)(skipwhite(line) - line) != 5995 (int)(curwin->w_cursor.col - (p - look))) 5996 match = FALSE; 5997 } 5998 if (match) 5999 return TRUE; 6000 } 6001 look = p; 6002 } 6003 6004 /* 6005 * ok, it's a boring generic character. 6006 */ 6007 else 6008 { 6009 if (try_match && *look == keytyped) 6010 return TRUE; 6011 ++look; 6012 } 6013 6014 /* 6015 * Skip over ", ". 6016 */ 6017 look = skip_to_option_part(look); 6018 } 6019 return FALSE; 6020 } 6021 #endif /* FEAT_CINDENT */ 6022 6023 #if defined(FEAT_RIGHTLEFT) || defined(PROTO) 6024 /* 6025 * Map Hebrew keyboard when in hkmap mode. 6026 */ 6027 int 6028 hkmap(c) 6029 int c; 6030 { 6031 if (p_hkmapp) /* phonetic mapping, by Ilya Dogolazky */ 6032 { 6033 enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD, 6034 KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN, 6035 PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV}; 6036 static char_u map[26] = 6037 {(char_u)hALEF/*a*/, (char_u)BET /*b*/, (char_u)hKAF /*c*/, 6038 (char_u)DALET/*d*/, (char_u)-1 /*e*/, (char_u)PEIsofit/*f*/, 6039 (char_u)GIMEL/*g*/, (char_u)HEI /*h*/, (char_u)IUD /*i*/, 6040 (char_u)HET /*j*/, (char_u)KOF /*k*/, (char_u)LAMED /*l*/, 6041 (char_u)MEM /*m*/, (char_u)NUN /*n*/, (char_u)SAMEH /*o*/, 6042 (char_u)PEI /*p*/, (char_u)-1 /*q*/, (char_u)RESH /*r*/, 6043 (char_u)ZAIN /*s*/, (char_u)TAV /*t*/, (char_u)TET /*u*/, 6044 (char_u)VAV /*v*/, (char_u)hSHIN/*w*/, (char_u)-1 /*x*/, 6045 (char_u)AIN /*y*/, (char_u)ZADI /*z*/}; 6046 6047 if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z') 6048 return (int)(map[CharOrd(c)] - 1 + p_aleph); 6049 /* '-1'='sofit' */ 6050 else if (c == 'x') 6051 return 'X'; 6052 else if (c == 'q') 6053 return '\''; /* {geresh}={'} */ 6054 else if (c == 246) 6055 return ' '; /* \"o --> ' ' for a german keyboard */ 6056 else if (c == 228) 6057 return ' '; /* \"a --> ' ' -- / -- */ 6058 else if (c == 252) 6059 return ' '; /* \"u --> ' ' -- / -- */ 6060 #ifdef EBCDIC 6061 else if (islower(c)) 6062 #else 6063 /* NOTE: islower() does not do the right thing for us on Linux so we 6064 * do this the same was as 5.7 and previous, so it works correctly on 6065 * all systems. Specifically, the e.g. Delete and Arrow keys are 6066 * munged and won't work if e.g. searching for Hebrew text. 6067 */ 6068 else if (c >= 'a' && c <= 'z') 6069 #endif 6070 return (int)(map[CharOrdLow(c)] + p_aleph); 6071 else 6072 return c; 6073 } 6074 else 6075 { 6076 switch (c) 6077 { 6078 case '`': return ';'; 6079 case '/': return '.'; 6080 case '\'': return ','; 6081 case 'q': return '/'; 6082 case 'w': return '\''; 6083 6084 /* Hebrew letters - set offset from 'a' */ 6085 case ',': c = '{'; break; 6086 case '.': c = 'v'; break; 6087 case ';': c = 't'; break; 6088 default: { 6089 static char str[] = "zqbcxlsjphmkwonu ydafe rig"; 6090 6091 #ifdef EBCDIC 6092 /* see note about islower() above */ 6093 if (!islower(c)) 6094 #else 6095 if (c < 'a' || c > 'z') 6096 #endif 6097 return c; 6098 c = str[CharOrdLow(c)]; 6099 break; 6100 } 6101 } 6102 6103 return (int)(CharOrdLow(c) + p_aleph); 6104 } 6105 } 6106 #endif 6107 6108 static void 6109 ins_reg() 6110 { 6111 int need_redraw = FALSE; 6112 int regname; 6113 int literally = 0; 6114 6115 /* 6116 * If we are going to wait for a character, show a '"'. 6117 */ 6118 pc_status = PC_STATUS_UNSET; 6119 if (redrawing() && !char_avail()) 6120 { 6121 /* may need to redraw when no more chars available now */ 6122 ins_redraw(); 6123 6124 edit_putchar('"', TRUE); 6125 #ifdef FEAT_CMDL_INFO 6126 add_to_showcmd_c(Ctrl_R); 6127 #endif 6128 } 6129 6130 #ifdef USE_ON_FLY_SCROLL 6131 dont_scroll = TRUE; /* disallow scrolling here */ 6132 #endif 6133 6134 /* 6135 * Don't map the register name. This also prevents the mode message to be 6136 * deleted when ESC is hit. 6137 */ 6138 ++no_mapping; 6139 regname = safe_vgetc(); 6140 #ifdef FEAT_LANGMAP 6141 LANGMAP_ADJUST(regname, TRUE); 6142 #endif 6143 if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) 6144 { 6145 /* Get a third key for literal register insertion */ 6146 literally = regname; 6147 #ifdef FEAT_CMDL_INFO 6148 add_to_showcmd_c(literally); 6149 #endif 6150 regname = safe_vgetc(); 6151 #ifdef FEAT_LANGMAP 6152 LANGMAP_ADJUST(regname, TRUE); 6153 #endif 6154 } 6155 --no_mapping; 6156 6157 #ifdef FEAT_EVAL 6158 /* 6159 * Don't call u_sync() while getting the expression, 6160 * evaluating it or giving an error message for it! 6161 */ 6162 ++no_u_sync; 6163 if (regname == '=') 6164 { 6165 # ifdef USE_IM_CONTROL 6166 int im_on = im_get_status(); 6167 # endif 6168 regname = get_expr_register(); 6169 # ifdef USE_IM_CONTROL 6170 /* Restore the Input Method. */ 6171 if (im_on) 6172 im_set_active(TRUE); 6173 # endif 6174 } 6175 if (regname == NUL || !valid_yank_reg(regname, FALSE)) 6176 { 6177 vim_beep(); 6178 need_redraw = TRUE; /* remove the '"' */ 6179 } 6180 else 6181 { 6182 #endif 6183 if (literally == Ctrl_O || literally == Ctrl_P) 6184 { 6185 /* Append the command to the redo buffer. */ 6186 AppendCharToRedobuff(Ctrl_R); 6187 AppendCharToRedobuff(literally); 6188 AppendCharToRedobuff(regname); 6189 6190 do_put(regname, BACKWARD, 1L, 6191 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); 6192 } 6193 else if (insert_reg(regname, literally) == FAIL) 6194 { 6195 vim_beep(); 6196 need_redraw = TRUE; /* remove the '"' */ 6197 } 6198 else if (stop_insert_mode) 6199 /* When the '=' register was used and a function was invoked that 6200 * did ":stopinsert" then stuff_empty() returns FALSE but we won't 6201 * insert anything, need to remove the '"' */ 6202 need_redraw = TRUE; 6203 6204 #ifdef FEAT_EVAL 6205 } 6206 --no_u_sync; 6207 #endif 6208 #ifdef FEAT_CMDL_INFO 6209 clear_showcmd(); 6210 #endif 6211 6212 /* If the inserted register is empty, we need to remove the '"' */ 6213 if (need_redraw || stuff_empty()) 6214 edit_unputchar(); 6215 } 6216 6217 /* 6218 * CTRL-G commands in Insert mode. 6219 */ 6220 static void 6221 ins_ctrl_g() 6222 { 6223 int c; 6224 6225 #ifdef FEAT_INS_EXPAND 6226 /* Right after CTRL-X the cursor will be after the ruler. */ 6227 setcursor(); 6228 #endif 6229 6230 /* 6231 * Don't map the second key. This also prevents the mode message to be 6232 * deleted when ESC is hit. 6233 */ 6234 ++no_mapping; 6235 c = safe_vgetc(); 6236 --no_mapping; 6237 switch (c) 6238 { 6239 /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */ 6240 case K_UP: 6241 case Ctrl_K: 6242 case 'k': ins_up(TRUE); 6243 break; 6244 6245 /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */ 6246 case K_DOWN: 6247 case Ctrl_J: 6248 case 'j': ins_down(TRUE); 6249 break; 6250 6251 /* CTRL-G u: start new undoable edit */ 6252 case 'u': u_sync(); 6253 ins_need_undo = TRUE; 6254 break; 6255 6256 /* Unknown CTRL-G command, reserved for future expansion. */ 6257 default: vim_beep(); 6258 } 6259 } 6260 6261 /* 6262 * CTRL-^ in Insert mode. 6263 */ 6264 static void 6265 ins_ctrl_hat() 6266 { 6267 if (map_to_exists_mode((char_u *)"", LANGMAP)) 6268 { 6269 /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */ 6270 if (State & LANGMAP) 6271 { 6272 curbuf->b_p_iminsert = B_IMODE_NONE; 6273 State &= ~LANGMAP; 6274 } 6275 else 6276 { 6277 curbuf->b_p_iminsert = B_IMODE_LMAP; 6278 State |= LANGMAP; 6279 #ifdef USE_IM_CONTROL 6280 im_set_active(FALSE); 6281 #endif 6282 } 6283 } 6284 #ifdef USE_IM_CONTROL 6285 else 6286 { 6287 /* There are no ":lmap" mappings, toggle IM */ 6288 if (im_get_status()) 6289 { 6290 curbuf->b_p_iminsert = B_IMODE_NONE; 6291 im_set_active(FALSE); 6292 } 6293 else 6294 { 6295 curbuf->b_p_iminsert = B_IMODE_IM; 6296 State &= ~LANGMAP; 6297 im_set_active(TRUE); 6298 } 6299 } 6300 #endif 6301 set_iminsert_global(); 6302 showmode(); 6303 #ifdef FEAT_GUI 6304 /* may show different cursor shape or color */ 6305 if (gui.in_use) 6306 gui_update_cursor(TRUE, FALSE); 6307 #endif 6308 #if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP) 6309 /* Show/unshow value of 'keymap' in status lines. */ 6310 status_redraw_curbuf(); 6311 #endif 6312 } 6313 6314 /* 6315 * Handle ESC in insert mode. 6316 * Returns TRUE when leaving insert mode, FALSE when going to repeat the 6317 * insert. 6318 */ 6319 static int 6320 ins_esc(count, cmdchar, nomove) 6321 long *count; 6322 int cmdchar; 6323 int nomove; /* don't move cursor */ 6324 { 6325 int temp; 6326 static int disabled_redraw = FALSE; 6327 6328 #ifdef FEAT_SYN_HL 6329 check_spell_redraw(); 6330 #endif 6331 #if defined(FEAT_HANGULIN) 6332 # if defined(ESC_CHG_TO_ENG_MODE) 6333 hangul_input_state_set(0); 6334 # endif 6335 if (composing_hangul) 6336 { 6337 push_raw_key(composing_hangul_buffer, 2); 6338 composing_hangul = 0; 6339 } 6340 #endif 6341 #if defined(FEAT_MBYTE) && defined(MACOS_CLASSIC) 6342 previous_script = GetScriptManagerVariable(smKeyScript); 6343 KeyScript(smKeyRoman); /* or smKeySysScript */ 6344 #endif 6345 6346 temp = curwin->w_cursor.col; 6347 if (disabled_redraw) 6348 { 6349 --RedrawingDisabled; 6350 disabled_redraw = FALSE; 6351 } 6352 if (!arrow_used) 6353 { 6354 /* 6355 * Don't append the ESC for "r<CR>" and "grx". 6356 * When 'insertmode' is set only CTRL-L stops Insert mode. Needed for 6357 * when "count" is non-zero. 6358 */ 6359 if (cmdchar != 'r' && cmdchar != 'v') 6360 AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR); 6361 6362 /* 6363 * Repeating insert may take a long time. Check for 6364 * interrupt now and then. 6365 */ 6366 if (*count > 0) 6367 { 6368 line_breakcheck(); 6369 if (got_int) 6370 *count = 0; 6371 } 6372 6373 if (--*count > 0) /* repeat what was typed */ 6374 { 6375 /* Vi repeats the insert without replacing characters. */ 6376 if (vim_strchr(p_cpo, CPO_REPLCNT) != NULL) 6377 State &= ~REPLACE_FLAG; 6378 6379 (void)start_redo_ins(); 6380 if (cmdchar == 'r' || cmdchar == 'v') 6381 stuffReadbuff(ESC_STR); /* no ESC in redo buffer */ 6382 ++RedrawingDisabled; 6383 disabled_redraw = TRUE; 6384 return FALSE; /* repeat the insert */ 6385 } 6386 stop_insert(&curwin->w_cursor, TRUE); 6387 undisplay_dollar(); 6388 } 6389 6390 /* When an autoindent was removed, curswant stays after the 6391 * indent */ 6392 if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col) 6393 curwin->w_set_curswant = TRUE; 6394 6395 /* Remember the last Insert position in the '^ mark. */ 6396 if (!cmdmod.keepjumps) 6397 curbuf->b_last_insert = curwin->w_cursor; 6398 6399 /* 6400 * The cursor should end up on the last inserted character. 6401 * Don't do it for CTRL-O, unless past the end of the line. 6402 */ 6403 if (!nomove 6404 && (curwin->w_cursor.col != 0 6405 #ifdef FEAT_VIRTUALEDIT 6406 || curwin->w_cursor.coladd > 0 6407 #endif 6408 ) 6409 && (restart_edit == NUL 6410 || (gchar_cursor() == NUL 6411 #ifdef FEAT_VISUAL 6412 && !VIsual_active 6413 #endif 6414 )) 6415 #ifdef FEAT_RIGHTLEFT 6416 && !revins_on 6417 #endif 6418 ) 6419 { 6420 #ifdef FEAT_VIRTUALEDIT 6421 if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL) 6422 { 6423 oneleft(); 6424 if (restart_edit != NUL) 6425 ++curwin->w_cursor.coladd; 6426 } 6427 else 6428 #endif 6429 { 6430 --curwin->w_cursor.col; 6431 #ifdef FEAT_MBYTE 6432 /* Correct cursor for multi-byte character. */ 6433 if (has_mbyte) 6434 mb_adjust_cursor(); 6435 #endif 6436 } 6437 } 6438 6439 #ifdef USE_IM_CONTROL 6440 /* Disable IM to allow typing English directly for Normal mode commands. 6441 * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as 6442 * well). */ 6443 if (!(State & LANGMAP)) 6444 im_save_status(&curbuf->b_p_iminsert); 6445 im_set_active(FALSE); 6446 #endif 6447 6448 State = NORMAL; 6449 /* need to position cursor again (e.g. when on a TAB ) */ 6450 changed_cline_bef_curs(); 6451 6452 #ifdef FEAT_MOUSE 6453 setmouse(); 6454 #endif 6455 #ifdef CURSOR_SHAPE 6456 ui_cursor_shape(); /* may show different cursor shape */ 6457 #endif 6458 6459 /* 6460 * When recording or for CTRL-O, need to display the new mode. 6461 * Otherwise remove the mode message. 6462 */ 6463 if (Recording || restart_edit != NUL) 6464 showmode(); 6465 else if (p_smd) 6466 MSG(""); 6467 6468 return TRUE; /* exit Insert mode */ 6469 } 6470 6471 #ifdef FEAT_RIGHTLEFT 6472 /* 6473 * Toggle language: hkmap and revins_on. 6474 * Move to end of reverse inserted text. 6475 */ 6476 static void 6477 ins_ctrl_() 6478 { 6479 if (revins_on && revins_chars && revins_scol >= 0) 6480 { 6481 while (gchar_cursor() != NUL && revins_chars--) 6482 ++curwin->w_cursor.col; 6483 } 6484 p_ri = !p_ri; 6485 revins_on = (State == INSERT && p_ri); 6486 if (revins_on) 6487 { 6488 revins_scol = curwin->w_cursor.col; 6489 revins_legal++; 6490 revins_chars = 0; 6491 undisplay_dollar(); 6492 } 6493 else 6494 revins_scol = -1; 6495 #ifdef FEAT_FKMAP 6496 if (p_altkeymap) 6497 { 6498 /* 6499 * to be consistent also for redo command, using '.' 6500 * set arrow_used to true and stop it - causing to redo 6501 * characters entered in one mode (normal/reverse insert). 6502 */ 6503 arrow_used = TRUE; 6504 (void)stop_arrow(); 6505 p_fkmap = curwin->w_p_rl ^ p_ri; 6506 if (p_fkmap && p_ri) 6507 State = INSERT; 6508 } 6509 else 6510 #endif 6511 p_hkmap = curwin->w_p_rl ^ p_ri; /* be consistent! */ 6512 showmode(); 6513 } 6514 #endif 6515 6516 #ifdef FEAT_VISUAL 6517 /* 6518 * If 'keymodel' contains "startsel", may start selection. 6519 * Returns TRUE when a CTRL-O and other keys stuffed. 6520 */ 6521 static int 6522 ins_start_select(c) 6523 int c; 6524 { 6525 if (km_startsel) 6526 switch (c) 6527 { 6528 case K_KHOME: 6529 case K_KEND: 6530 case K_PAGEUP: 6531 case K_KPAGEUP: 6532 case K_PAGEDOWN: 6533 case K_KPAGEDOWN: 6534 # ifdef MACOS 6535 case K_LEFT: 6536 case K_RIGHT: 6537 case K_UP: 6538 case K_DOWN: 6539 case K_END: 6540 case K_HOME: 6541 # endif 6542 if (!(mod_mask & MOD_MASK_SHIFT)) 6543 break; 6544 /* FALLTHROUGH */ 6545 case K_S_LEFT: 6546 case K_S_RIGHT: 6547 case K_S_UP: 6548 case K_S_DOWN: 6549 case K_S_END: 6550 case K_S_HOME: 6551 /* Start selection right away, the cursor can move with 6552 * CTRL-O when beyond the end of the line. */ 6553 start_selection(); 6554 6555 /* Execute the key in (insert) Select mode. */ 6556 stuffcharReadbuff(Ctrl_O); 6557 if (mod_mask) 6558 { 6559 char_u buf[4]; 6560 6561 buf[0] = K_SPECIAL; 6562 buf[1] = KS_MODIFIER; 6563 buf[2] = mod_mask; 6564 buf[3] = NUL; 6565 stuffReadbuff(buf); 6566 } 6567 stuffcharReadbuff(c); 6568 return TRUE; 6569 } 6570 return FALSE; 6571 } 6572 #endif 6573 6574 /* 6575 * <Insert> key in Insert mode: toggle insert/remplace mode. 6576 */ 6577 static void 6578 ins_insert(replaceState) 6579 int replaceState; 6580 { 6581 #ifdef FEAT_FKMAP 6582 if (p_fkmap && p_ri) 6583 { 6584 beep_flush(); 6585 EMSG(farsi_text_3); /* encoded in Farsi */ 6586 return; 6587 } 6588 #endif 6589 6590 #ifdef FEAT_AUTOCMD 6591 set_vim_var_string(VV_INSERTMODE, 6592 (char_u *)((State & REPLACE_FLAG) ? "i" : 6593 replaceState == VREPLACE ? "v" : "r"), 1); 6594 apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf); 6595 #endif 6596 if (State & REPLACE_FLAG) 6597 State = INSERT | (State & LANGMAP); 6598 else 6599 State = replaceState | (State & LANGMAP); 6600 AppendCharToRedobuff(K_INS); 6601 showmode(); 6602 #ifdef CURSOR_SHAPE 6603 ui_cursor_shape(); /* may show different cursor shape */ 6604 #endif 6605 } 6606 6607 /* 6608 * Pressed CTRL-O in Insert mode. 6609 */ 6610 static void 6611 ins_ctrl_o() 6612 { 6613 #ifdef FEAT_VREPLACE 6614 if (State & VREPLACE_FLAG) 6615 restart_edit = 'V'; 6616 else 6617 #endif 6618 if (State & REPLACE_FLAG) 6619 restart_edit = 'R'; 6620 else 6621 restart_edit = 'I'; 6622 #ifdef FEAT_VIRTUALEDIT 6623 if (virtual_active()) 6624 ins_at_eol = FALSE; /* cursor always keeps its column */ 6625 else 6626 #endif 6627 ins_at_eol = (gchar_cursor() == NUL); 6628 } 6629 6630 /* 6631 * If the cursor is on an indent, ^T/^D insert/delete one 6632 * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". 6633 * Always round the indent to 'shiftwith', this is compatible 6634 * with vi. But vi only supports ^T and ^D after an 6635 * autoindent, we support it everywhere. 6636 */ 6637 static void 6638 ins_shift(c, lastc) 6639 int c; 6640 int lastc; 6641 { 6642 if (stop_arrow() == FAIL) 6643 return; 6644 AppendCharToRedobuff(c); 6645 6646 /* 6647 * 0^D and ^^D: remove all indent. 6648 */ 6649 if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col) 6650 { 6651 --curwin->w_cursor.col; 6652 (void)del_char(FALSE); /* delete the '^' or '0' */ 6653 /* In Replace mode, restore the characters that '^' or '0' replaced. */ 6654 if (State & REPLACE_FLAG) 6655 replace_pop_ins(); 6656 if (lastc == '^') 6657 old_indent = get_indent(); /* remember curr. indent */ 6658 change_indent(INDENT_SET, 0, TRUE, 0); 6659 } 6660 else 6661 change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0); 6662 6663 if (did_ai && *skipwhite(ml_get_curline()) != NUL) 6664 did_ai = FALSE; 6665 #ifdef FEAT_SMARTINDENT 6666 did_si = FALSE; 6667 can_si = FALSE; 6668 can_si_back = FALSE; 6669 #endif 6670 #ifdef FEAT_CINDENT 6671 can_cindent = FALSE; /* no cindenting after ^D or ^T */ 6672 #endif 6673 } 6674 6675 static void 6676 ins_del() 6677 { 6678 int temp; 6679 6680 if (stop_arrow() == FAIL) 6681 return; 6682 if (gchar_cursor() == NUL) /* delete newline */ 6683 { 6684 temp = curwin->w_cursor.col; 6685 if (!can_bs(BS_EOL) /* only if "eol" included */ 6686 || u_save((linenr_T)(curwin->w_cursor.lnum - 1), 6687 (linenr_T)(curwin->w_cursor.lnum + 2)) == FAIL 6688 || do_join(FALSE) == FAIL) 6689 vim_beep(); 6690 else 6691 curwin->w_cursor.col = temp; 6692 } 6693 else if (del_char(FALSE) == FAIL) /* delete char under cursor */ 6694 vim_beep(); 6695 did_ai = FALSE; 6696 #ifdef FEAT_SMARTINDENT 6697 did_si = FALSE; 6698 can_si = FALSE; 6699 can_si_back = FALSE; 6700 #endif 6701 AppendCharToRedobuff(K_DEL); 6702 } 6703 6704 /* 6705 * Handle Backspace, delete-word and delete-line in Insert mode. 6706 * Return TRUE when backspace was actually used. 6707 */ 6708 static int 6709 ins_bs(c, mode, inserted_space_p) 6710 int c; 6711 int mode; 6712 int *inserted_space_p; 6713 { 6714 linenr_T lnum; 6715 int cc; 6716 int temp = 0; /* init for GCC */ 6717 colnr_T mincol; 6718 int did_backspace = FALSE; 6719 int in_indent; 6720 int oldState; 6721 #ifdef FEAT_MBYTE 6722 int p1, p2; 6723 #endif 6724 6725 /* 6726 * can't delete anything in an empty file 6727 * can't backup past first character in buffer 6728 * can't backup past starting point unless 'backspace' > 1 6729 * can backup to a previous line if 'backspace' == 0 6730 */ 6731 if ( bufempty() 6732 || ( 6733 #ifdef FEAT_RIGHTLEFT 6734 !revins_on && 6735 #endif 6736 ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0) 6737 || (!can_bs(BS_START) 6738 && (arrow_used 6739 || (curwin->w_cursor.lnum == Insstart.lnum 6740 && curwin->w_cursor.col <= Insstart.col))) 6741 || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0 6742 && curwin->w_cursor.col <= ai_col) 6743 || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0)))) 6744 { 6745 vim_beep(); 6746 return FALSE; 6747 } 6748 6749 if (stop_arrow() == FAIL) 6750 return FALSE; 6751 in_indent = inindent(0); 6752 #ifdef FEAT_CINDENT 6753 if (in_indent) 6754 can_cindent = FALSE; 6755 #endif 6756 #ifdef FEAT_COMMENTS 6757 end_comment_pending = NUL; /* After BS, don't auto-end comment */ 6758 #endif 6759 #ifdef FEAT_RIGHTLEFT 6760 if (revins_on) /* put cursor after last inserted char */ 6761 inc_cursor(); 6762 #endif 6763 6764 #ifdef FEAT_VIRTUALEDIT 6765 /* Virtualedit: 6766 * BACKSPACE_CHAR eats a virtual space 6767 * BACKSPACE_WORD eats all coladd 6768 * BACKSPACE_LINE eats all coladd and keeps going 6769 */ 6770 if (curwin->w_cursor.coladd > 0) 6771 { 6772 if (mode == BACKSPACE_CHAR) 6773 { 6774 --curwin->w_cursor.coladd; 6775 return TRUE; 6776 } 6777 if (mode == BACKSPACE_WORD) 6778 { 6779 curwin->w_cursor.coladd = 0; 6780 return TRUE; 6781 } 6782 curwin->w_cursor.coladd = 0; 6783 } 6784 #endif 6785 6786 /* 6787 * delete newline! 6788 */ 6789 if (curwin->w_cursor.col == 0) 6790 { 6791 lnum = Insstart.lnum; 6792 if (curwin->w_cursor.lnum == Insstart.lnum 6793 #ifdef FEAT_RIGHTLEFT 6794 || revins_on 6795 #endif 6796 ) 6797 { 6798 if (u_save((linenr_T)(curwin->w_cursor.lnum - 2), 6799 (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) 6800 return FALSE; 6801 --Insstart.lnum; 6802 Insstart.col = MAXCOL; 6803 } 6804 /* 6805 * In replace mode: 6806 * cc < 0: NL was inserted, delete it 6807 * cc >= 0: NL was replaced, put original characters back 6808 */ 6809 cc = -1; 6810 if (State & REPLACE_FLAG) 6811 cc = replace_pop(); /* returns -1 if NL was inserted */ 6812 /* 6813 * In replace mode, in the line we started replacing, we only move the 6814 * cursor. 6815 */ 6816 if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum) 6817 { 6818 dec_cursor(); 6819 } 6820 else 6821 { 6822 #ifdef FEAT_VREPLACE 6823 if (!(State & VREPLACE_FLAG) 6824 || curwin->w_cursor.lnum > orig_line_count) 6825 #endif 6826 { 6827 temp = gchar_cursor(); /* remember current char */ 6828 --curwin->w_cursor.lnum; 6829 6830 /* When "aw" is in 'formatoptions' we must delete the space at 6831 * the end of the line, otherwise the line will be broken 6832 * again when auto-formatting. */ 6833 if (has_format_option(FO_AUTO) 6834 && has_format_option(FO_WHITE_PAR)) 6835 { 6836 char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, 6837 TRUE); 6838 int len; 6839 6840 len = STRLEN(ptr); 6841 if (len > 0 && ptr[len - 1] == ' ') 6842 ptr[len - 1] = NUL; 6843 } 6844 6845 (void)do_join(FALSE); 6846 if (temp == NUL && gchar_cursor() != NUL) 6847 inc_cursor(); 6848 } 6849 #ifdef FEAT_VREPLACE 6850 else 6851 dec_cursor(); 6852 #endif 6853 6854 /* 6855 * In REPLACE mode we have to put back the text that was replaced 6856 * by the NL. On the replace stack is first a NUL-terminated 6857 * sequence of characters that were deleted and then the 6858 * characters that NL replaced. 6859 */ 6860 if (State & REPLACE_FLAG) 6861 { 6862 /* 6863 * Do the next ins_char() in NORMAL state, to 6864 * prevent ins_char() from replacing characters and 6865 * avoiding showmatch(). 6866 */ 6867 oldState = State; 6868 State = NORMAL; 6869 /* 6870 * restore characters (blanks) deleted after cursor 6871 */ 6872 while (cc > 0) 6873 { 6874 temp = curwin->w_cursor.col; 6875 #ifdef FEAT_MBYTE 6876 mb_replace_pop_ins(cc); 6877 #else 6878 ins_char(cc); 6879 #endif 6880 curwin->w_cursor.col = temp; 6881 cc = replace_pop(); 6882 } 6883 /* restore the characters that NL replaced */ 6884 replace_pop_ins(); 6885 State = oldState; 6886 } 6887 } 6888 did_ai = FALSE; 6889 } 6890 else 6891 { 6892 /* 6893 * Delete character(s) before the cursor. 6894 */ 6895 #ifdef FEAT_RIGHTLEFT 6896 if (revins_on) /* put cursor on last inserted char */ 6897 dec_cursor(); 6898 #endif 6899 mincol = 0; 6900 /* keep indent */ 6901 if (mode == BACKSPACE_LINE && curbuf->b_p_ai 6902 #ifdef FEAT_RIGHTLEFT 6903 && !revins_on 6904 #endif 6905 ) 6906 { 6907 temp = curwin->w_cursor.col; 6908 beginline(BL_WHITE); 6909 if (curwin->w_cursor.col < (colnr_T)temp) 6910 mincol = curwin->w_cursor.col; 6911 curwin->w_cursor.col = temp; 6912 } 6913 6914 /* 6915 * Handle deleting one 'shiftwidth' or 'softtabstop'. 6916 */ 6917 if ( mode == BACKSPACE_CHAR 6918 && ((p_sta && in_indent) 6919 || (curbuf->b_p_sts 6920 && (*(ml_get_cursor() - 1) == TAB 6921 || (*(ml_get_cursor() - 1) == ' ' 6922 && (!*inserted_space_p 6923 || arrow_used)))))) 6924 { 6925 int ts; 6926 colnr_T vcol; 6927 colnr_T want_vcol; 6928 int extra = 0; 6929 6930 *inserted_space_p = FALSE; 6931 if (p_sta) 6932 ts = curbuf->b_p_sw; 6933 else 6934 ts = curbuf->b_p_sts; 6935 /* Compute the virtual column where we want to be. Since 6936 * 'showbreak' may get in the way, need to get the last column of 6937 * the previous character. */ 6938 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 6939 dec_cursor(); 6940 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); 6941 inc_cursor(); 6942 want_vcol = (want_vcol / ts) * ts; 6943 6944 /* delete characters until we are at or before want_vcol */ 6945 while (vcol > want_vcol 6946 && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc))) 6947 { 6948 dec_cursor(); 6949 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 6950 if (State & REPLACE_FLAG) 6951 { 6952 /* Don't delete characters before the insert point when in 6953 * Replace mode */ 6954 if (curwin->w_cursor.lnum != Insstart.lnum 6955 || curwin->w_cursor.col >= Insstart.col) 6956 { 6957 #if 0 /* what was this for? It causes problems when sw != ts. */ 6958 if (State == REPLACE && (int)vcol < want_vcol) 6959 { 6960 (void)del_char(FALSE); 6961 extra = 2; /* don't pop too much */ 6962 } 6963 else 6964 #endif 6965 replace_do_bs(); 6966 } 6967 } 6968 else 6969 (void)del_char(FALSE); 6970 } 6971 6972 /* insert extra spaces until we are at want_vcol */ 6973 while (vcol < want_vcol) 6974 { 6975 /* Remember the first char we inserted */ 6976 if (curwin->w_cursor.lnum == Insstart.lnum 6977 && curwin->w_cursor.col < Insstart.col) 6978 Insstart.col = curwin->w_cursor.col; 6979 6980 #ifdef FEAT_VREPLACE 6981 if (State & VREPLACE_FLAG) 6982 ins_char(' '); 6983 else 6984 #endif 6985 { 6986 ins_str((char_u *)" "); 6987 if ((State & REPLACE_FLAG) && extra <= 1) 6988 { 6989 if (extra) 6990 replace_push_off(NUL); 6991 else 6992 replace_push(NUL); 6993 } 6994 if (extra == 2) 6995 extra = 1; 6996 } 6997 getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); 6998 } 6999 } 7000 7001 /* 7002 * Delete upto starting point, start of line or previous word. 7003 */ 7004 else do 7005 { 7006 #ifdef FEAT_RIGHTLEFT 7007 if (!revins_on) /* put cursor on char to be deleted */ 7008 #endif 7009 dec_cursor(); 7010 7011 /* start of word? */ 7012 if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor())) 7013 { 7014 mode = BACKSPACE_WORD_NOT_SPACE; 7015 temp = vim_iswordc(gchar_cursor()); 7016 } 7017 /* end of word? */ 7018 else if (mode == BACKSPACE_WORD_NOT_SPACE 7019 && (vim_isspace(cc = gchar_cursor()) 7020 || vim_iswordc(cc) != temp)) 7021 { 7022 #ifdef FEAT_RIGHTLEFT 7023 if (!revins_on) 7024 #endif 7025 inc_cursor(); 7026 #ifdef FEAT_RIGHTLEFT 7027 else if (State & REPLACE_FLAG) 7028 dec_cursor(); 7029 #endif 7030 break; 7031 } 7032 if (State & REPLACE_FLAG) 7033 replace_do_bs(); 7034 else 7035 { 7036 #ifdef FEAT_MBYTE 7037 if (enc_utf8 && p_deco) 7038 (void)utfc_ptr2char(ml_get_cursor(), &p1, &p2); 7039 #endif 7040 (void)del_char(FALSE); 7041 #ifdef FEAT_MBYTE 7042 /* 7043 * If p1 or p2 is non-zero, there are combining characters we 7044 * need to take account of. Don't back up before the base 7045 * character. 7046 */ 7047 if (enc_utf8 && p_deco && (p1 != NUL || p2 != NUL)) 7048 inc_cursor(); 7049 #endif 7050 #ifdef FEAT_RIGHTLEFT 7051 if (revins_chars) 7052 { 7053 revins_chars--; 7054 revins_legal++; 7055 } 7056 if (revins_on && gchar_cursor() == NUL) 7057 break; 7058 #endif 7059 } 7060 /* Just a single backspace?: */ 7061 if (mode == BACKSPACE_CHAR) 7062 break; 7063 } while ( 7064 #ifdef FEAT_RIGHTLEFT 7065 revins_on || 7066 #endif 7067 (curwin->w_cursor.col > mincol 7068 && (curwin->w_cursor.lnum != Insstart.lnum 7069 || curwin->w_cursor.col != Insstart.col))); 7070 did_backspace = TRUE; 7071 } 7072 #ifdef FEAT_SMARTINDENT 7073 did_si = FALSE; 7074 can_si = FALSE; 7075 can_si_back = FALSE; 7076 #endif 7077 if (curwin->w_cursor.col <= 1) 7078 did_ai = FALSE; 7079 /* 7080 * It's a little strange to put backspaces into the redo 7081 * buffer, but it makes auto-indent a lot easier to deal 7082 * with. 7083 */ 7084 AppendCharToRedobuff(c); 7085 7086 /* If deleted before the insertion point, adjust it */ 7087 if (curwin->w_cursor.lnum == Insstart.lnum 7088 && curwin->w_cursor.col < Insstart.col) 7089 Insstart.col = curwin->w_cursor.col; 7090 7091 /* vi behaviour: the cursor moves backward but the character that 7092 * was there remains visible 7093 * Vim behaviour: the cursor moves backward and the character that 7094 * was there is erased from the screen. 7095 * We can emulate the vi behaviour by pretending there is a dollar 7096 * displayed even when there isn't. 7097 * --pkv Sun Jan 19 01:56:40 EST 2003 */ 7098 if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0) 7099 dollar_vcol = curwin->w_virtcol; 7100 7101 return did_backspace; 7102 } 7103 7104 #ifdef FEAT_MOUSE 7105 static void 7106 ins_mouse(c) 7107 int c; 7108 { 7109 pos_T tpos; 7110 7111 # ifdef FEAT_GUI 7112 /* When GUI is active, also move/paste when 'mouse' is empty */ 7113 if (!gui.in_use) 7114 # endif 7115 if (!mouse_has(MOUSE_INSERT)) 7116 return; 7117 7118 undisplay_dollar(); 7119 tpos = curwin->w_cursor; 7120 if (do_mouse(NULL, c, BACKWARD, 1L, 0)) 7121 { 7122 start_arrow(&tpos); 7123 # ifdef FEAT_CINDENT 7124 can_cindent = TRUE; 7125 # endif 7126 } 7127 7128 #ifdef FEAT_WINDOWS 7129 /* redraw status lines (in case another window became active) */ 7130 redraw_statuslines(); 7131 #endif 7132 } 7133 7134 static void 7135 ins_mousescroll(up) 7136 int up; 7137 { 7138 pos_T tpos; 7139 # if defined(FEAT_GUI) && defined(FEAT_WINDOWS) 7140 win_T *old_curwin; 7141 # endif 7142 7143 tpos = curwin->w_cursor; 7144 7145 # if defined(FEAT_GUI) && defined(FEAT_WINDOWS) 7146 old_curwin = curwin; 7147 7148 /* Currently the mouse coordinates are only known in the GUI. */ 7149 if (gui.in_use && mouse_row >= 0 && mouse_col >= 0) 7150 { 7151 int row, col; 7152 7153 row = mouse_row; 7154 col = mouse_col; 7155 7156 /* find the window at the pointer coordinates */ 7157 curwin = mouse_find_win(&row, &col); 7158 curbuf = curwin->w_buffer; 7159 } 7160 if (curwin == old_curwin) 7161 # endif 7162 undisplay_dollar(); 7163 7164 if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) 7165 scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline)); 7166 else 7167 scroll_redraw(up, 3L); 7168 7169 # if defined(FEAT_GUI) && defined(FEAT_WINDOWS) 7170 curwin->w_redr_status = TRUE; 7171 7172 curwin = old_curwin; 7173 curbuf = curwin->w_buffer; 7174 # endif 7175 7176 if (!equalpos(curwin->w_cursor, tpos)) 7177 { 7178 start_arrow(&tpos); 7179 # ifdef FEAT_CINDENT 7180 can_cindent = TRUE; 7181 # endif 7182 } 7183 } 7184 #endif 7185 7186 #ifdef FEAT_GUI 7187 void 7188 ins_scroll() 7189 { 7190 pos_T tpos; 7191 7192 undisplay_dollar(); 7193 tpos = curwin->w_cursor; 7194 if (gui_do_scroll()) 7195 { 7196 start_arrow(&tpos); 7197 # ifdef FEAT_CINDENT 7198 can_cindent = TRUE; 7199 # endif 7200 } 7201 } 7202 7203 void 7204 ins_horscroll() 7205 { 7206 pos_T tpos; 7207 7208 undisplay_dollar(); 7209 tpos = curwin->w_cursor; 7210 if (gui_do_horiz_scroll()) 7211 { 7212 start_arrow(&tpos); 7213 # ifdef FEAT_CINDENT 7214 can_cindent = TRUE; 7215 # endif 7216 } 7217 } 7218 #endif 7219 7220 static void 7221 ins_left() 7222 { 7223 pos_T tpos; 7224 7225 #ifdef FEAT_FOLDING 7226 if ((fdo_flags & FDO_HOR) && KeyTyped) 7227 foldOpenCursor(); 7228 #endif 7229 undisplay_dollar(); 7230 tpos = curwin->w_cursor; 7231 if (oneleft() == OK) 7232 { 7233 start_arrow(&tpos); 7234 #ifdef FEAT_RIGHTLEFT 7235 /* If exit reversed string, position is fixed */ 7236 if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) 7237 revins_legal++; 7238 revins_chars++; 7239 #endif 7240 } 7241 7242 /* 7243 * if 'whichwrap' set for cursor in insert mode may go to 7244 * previous line 7245 */ 7246 else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) 7247 { 7248 start_arrow(&tpos); 7249 --(curwin->w_cursor.lnum); 7250 coladvance((colnr_T)MAXCOL); 7251 curwin->w_set_curswant = TRUE; /* so we stay at the end */ 7252 } 7253 else 7254 vim_beep(); 7255 } 7256 7257 static void 7258 ins_home(c) 7259 int c; 7260 { 7261 pos_T tpos; 7262 7263 #ifdef FEAT_FOLDING 7264 if ((fdo_flags & FDO_HOR) && KeyTyped) 7265 foldOpenCursor(); 7266 #endif 7267 undisplay_dollar(); 7268 tpos = curwin->w_cursor; 7269 if (c == K_C_HOME) 7270 curwin->w_cursor.lnum = 1; 7271 curwin->w_cursor.col = 0; 7272 #ifdef FEAT_VIRTUALEDIT 7273 curwin->w_cursor.coladd = 0; 7274 #endif 7275 curwin->w_curswant = 0; 7276 start_arrow(&tpos); 7277 } 7278 7279 static void 7280 ins_end(c) 7281 int c; 7282 { 7283 pos_T tpos; 7284 7285 #ifdef FEAT_FOLDING 7286 if ((fdo_flags & FDO_HOR) && KeyTyped) 7287 foldOpenCursor(); 7288 #endif 7289 undisplay_dollar(); 7290 tpos = curwin->w_cursor; 7291 if (c == K_C_END) 7292 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 7293 coladvance((colnr_T)MAXCOL); 7294 curwin->w_curswant = MAXCOL; 7295 7296 start_arrow(&tpos); 7297 } 7298 7299 static void 7300 ins_s_left() 7301 { 7302 #ifdef FEAT_FOLDING 7303 if ((fdo_flags & FDO_HOR) && KeyTyped) 7304 foldOpenCursor(); 7305 #endif 7306 undisplay_dollar(); 7307 if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0) 7308 { 7309 start_arrow(&curwin->w_cursor); 7310 (void)bck_word(1L, FALSE, FALSE); 7311 curwin->w_set_curswant = TRUE; 7312 } 7313 else 7314 vim_beep(); 7315 } 7316 7317 static void 7318 ins_right() 7319 { 7320 #ifdef FEAT_FOLDING 7321 if ((fdo_flags & FDO_HOR) && KeyTyped) 7322 foldOpenCursor(); 7323 #endif 7324 undisplay_dollar(); 7325 if (gchar_cursor() != NUL || virtual_active() 7326 ) 7327 { 7328 start_arrow(&curwin->w_cursor); 7329 curwin->w_set_curswant = TRUE; 7330 #ifdef FEAT_VIRTUALEDIT 7331 if (virtual_active()) 7332 oneright(); 7333 else 7334 #endif 7335 { 7336 #ifdef FEAT_MBYTE 7337 if (has_mbyte) 7338 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor()); 7339 else 7340 #endif 7341 ++curwin->w_cursor.col; 7342 } 7343 7344 #ifdef FEAT_RIGHTLEFT 7345 revins_legal++; 7346 if (revins_chars) 7347 revins_chars--; 7348 #endif 7349 } 7350 /* if 'whichwrap' set for cursor in insert mode, may move the 7351 * cursor to the next line */ 7352 else if (vim_strchr(p_ww, ']') != NULL 7353 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 7354 { 7355 start_arrow(&curwin->w_cursor); 7356 curwin->w_set_curswant = TRUE; 7357 ++curwin->w_cursor.lnum; 7358 curwin->w_cursor.col = 0; 7359 } 7360 else 7361 vim_beep(); 7362 } 7363 7364 static void 7365 ins_s_right() 7366 { 7367 #ifdef FEAT_FOLDING 7368 if ((fdo_flags & FDO_HOR) && KeyTyped) 7369 foldOpenCursor(); 7370 #endif 7371 undisplay_dollar(); 7372 if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count 7373 || gchar_cursor() != NUL) 7374 { 7375 start_arrow(&curwin->w_cursor); 7376 (void)fwd_word(1L, FALSE, 0); 7377 curwin->w_set_curswant = TRUE; 7378 } 7379 else 7380 vim_beep(); 7381 } 7382 7383 static void 7384 ins_up(startcol) 7385 int startcol; /* when TRUE move to Insstart.col */ 7386 { 7387 pos_T tpos; 7388 linenr_T old_topline = curwin->w_topline; 7389 #ifdef FEAT_DIFF 7390 int old_topfill = curwin->w_topfill; 7391 #endif 7392 7393 undisplay_dollar(); 7394 tpos = curwin->w_cursor; 7395 if (cursor_up(1L, TRUE) == OK) 7396 { 7397 if (startcol) 7398 coladvance(getvcol_nolist(&Insstart)); 7399 if (old_topline != curwin->w_topline 7400 #ifdef FEAT_DIFF 7401 || old_topfill != curwin->w_topfill 7402 #endif 7403 ) 7404 redraw_later(VALID); 7405 start_arrow(&tpos); 7406 #ifdef FEAT_CINDENT 7407 can_cindent = TRUE; 7408 #endif 7409 } 7410 else 7411 vim_beep(); 7412 } 7413 7414 static void 7415 ins_pageup() 7416 { 7417 pos_T tpos; 7418 7419 undisplay_dollar(); 7420 tpos = curwin->w_cursor; 7421 if (onepage(BACKWARD, 1L) == OK) 7422 { 7423 start_arrow(&tpos); 7424 #ifdef FEAT_CINDENT 7425 can_cindent = TRUE; 7426 #endif 7427 } 7428 else 7429 vim_beep(); 7430 } 7431 7432 static void 7433 ins_down(startcol) 7434 int startcol; /* when TRUE move to Insstart.col */ 7435 { 7436 pos_T tpos; 7437 linenr_T old_topline = curwin->w_topline; 7438 #ifdef FEAT_DIFF 7439 int old_topfill = curwin->w_topfill; 7440 #endif 7441 7442 undisplay_dollar(); 7443 tpos = curwin->w_cursor; 7444 if (cursor_down(1L, TRUE) == OK) 7445 { 7446 if (startcol) 7447 coladvance(getvcol_nolist(&Insstart)); 7448 if (old_topline != curwin->w_topline 7449 #ifdef FEAT_DIFF 7450 || old_topfill != curwin->w_topfill 7451 #endif 7452 ) 7453 redraw_later(VALID); 7454 start_arrow(&tpos); 7455 #ifdef FEAT_CINDENT 7456 can_cindent = TRUE; 7457 #endif 7458 } 7459 else 7460 vim_beep(); 7461 } 7462 7463 static void 7464 ins_pagedown() 7465 { 7466 pos_T tpos; 7467 7468 undisplay_dollar(); 7469 tpos = curwin->w_cursor; 7470 if (onepage(FORWARD, 1L) == OK) 7471 { 7472 start_arrow(&tpos); 7473 #ifdef FEAT_CINDENT 7474 can_cindent = TRUE; 7475 #endif 7476 } 7477 else 7478 vim_beep(); 7479 } 7480 7481 #ifdef FEAT_DND 7482 static void 7483 ins_drop() 7484 { 7485 do_put('~', BACKWARD, 1L, PUT_CURSEND); 7486 } 7487 #endif 7488 7489 /* 7490 * Handle TAB in Insert or Replace mode. 7491 * Return TRUE when the TAB needs to be inserted like a normal character. 7492 */ 7493 static int 7494 ins_tab() 7495 { 7496 int ind; 7497 int i; 7498 int temp; 7499 7500 if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum) 7501 Insstart_blank_vcol = get_nolist_virtcol(); 7502 if (echeck_abbr(TAB + ABBR_OFF)) 7503 return FALSE; 7504 7505 ind = inindent(0); 7506 #ifdef FEAT_CINDENT 7507 if (ind) 7508 can_cindent = FALSE; 7509 #endif 7510 7511 /* 7512 * When nothing special, insert TAB like a normal character 7513 */ 7514 if (!curbuf->b_p_et 7515 && !(p_sta && ind && curbuf->b_p_ts != curbuf->b_p_sw) 7516 && curbuf->b_p_sts == 0) 7517 return TRUE; 7518 7519 if (stop_arrow() == FAIL) 7520 return TRUE; 7521 7522 did_ai = FALSE; 7523 #ifdef FEAT_SMARTINDENT 7524 did_si = FALSE; 7525 can_si = FALSE; 7526 can_si_back = FALSE; 7527 #endif 7528 AppendToRedobuff((char_u *)"\t"); 7529 7530 if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */ 7531 temp = (int)curbuf->b_p_sw; 7532 else if (curbuf->b_p_sts > 0) /* use 'softtabstop' when set */ 7533 temp = (int)curbuf->b_p_sts; 7534 else /* otherwise use 'tabstop' */ 7535 temp = (int)curbuf->b_p_ts; 7536 temp -= get_nolist_virtcol() % temp; 7537 7538 /* 7539 * Insert the first space with ins_char(). It will delete one char in 7540 * replace mode. Insert the rest with ins_str(); it will not delete any 7541 * chars. For VREPLACE mode, we use ins_char() for all characters. 7542 */ 7543 ins_char(' '); 7544 while (--temp > 0) 7545 { 7546 #ifdef FEAT_VREPLACE 7547 if (State & VREPLACE_FLAG) 7548 ins_char(' '); 7549 else 7550 #endif 7551 { 7552 ins_str((char_u *)" "); 7553 if (State & REPLACE_FLAG) /* no char replaced */ 7554 replace_push(NUL); 7555 } 7556 } 7557 7558 /* 7559 * When 'expandtab' not set: Replace spaces by TABs where possible. 7560 */ 7561 if (!curbuf->b_p_et && (curbuf->b_p_sts || (p_sta && ind))) 7562 { 7563 char_u *ptr; 7564 #ifdef FEAT_VREPLACE 7565 char_u *saved_line = NULL; /* init for GCC */ 7566 pos_T pos; 7567 #endif 7568 pos_T fpos; 7569 pos_T *cursor; 7570 colnr_T want_vcol, vcol; 7571 int change_col = -1; 7572 int save_list = curwin->w_p_list; 7573 7574 /* 7575 * Get the current line. For VREPLACE mode, don't make real changes 7576 * yet, just work on a copy of the line. 7577 */ 7578 #ifdef FEAT_VREPLACE 7579 if (State & VREPLACE_FLAG) 7580 { 7581 pos = curwin->w_cursor; 7582 cursor = &pos; 7583 saved_line = vim_strsave(ml_get_curline()); 7584 if (saved_line == NULL) 7585 return FALSE; 7586 ptr = saved_line + pos.col; 7587 } 7588 else 7589 #endif 7590 { 7591 ptr = ml_get_cursor(); 7592 cursor = &curwin->w_cursor; 7593 } 7594 7595 /* When 'L' is not in 'cpoptions' a tab always takes up 'ts' spaces. */ 7596 if (vim_strchr(p_cpo, CPO_LISTWM) == NULL) 7597 curwin->w_p_list = FALSE; 7598 7599 /* Find first white before the cursor */ 7600 fpos = curwin->w_cursor; 7601 while (fpos.col > 0 && vim_iswhite(ptr[-1])) 7602 { 7603 --fpos.col; 7604 --ptr; 7605 } 7606 7607 /* In Replace mode, don't change characters before the insert point. */ 7608 if ((State & REPLACE_FLAG) 7609 && fpos.lnum == Insstart.lnum 7610 && fpos.col < Insstart.col) 7611 { 7612 ptr += Insstart.col - fpos.col; 7613 fpos.col = Insstart.col; 7614 } 7615 7616 /* compute virtual column numbers of first white and cursor */ 7617 getvcol(curwin, &fpos, &vcol, NULL, NULL); 7618 getvcol(curwin, cursor, &want_vcol, NULL, NULL); 7619 7620 /* Use as many TABs as possible. Beware of 'showbreak' and 7621 * 'linebreak' adding extra virtual columns. */ 7622 while (vim_iswhite(*ptr)) 7623 { 7624 i = lbr_chartabsize((char_u *)"\t", vcol); 7625 if (vcol + i > want_vcol) 7626 break; 7627 if (*ptr != TAB) 7628 { 7629 *ptr = TAB; 7630 if (change_col < 0) 7631 { 7632 change_col = fpos.col; /* Column of first change */ 7633 /* May have to adjust Insstart */ 7634 if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col) 7635 Insstart.col = fpos.col; 7636 } 7637 } 7638 ++fpos.col; 7639 ++ptr; 7640 vcol += i; 7641 } 7642 7643 if (change_col >= 0) 7644 { 7645 int repl_off = 0; 7646 7647 /* Skip over the spaces we need. */ 7648 while (vcol < want_vcol && *ptr == ' ') 7649 { 7650 vcol += lbr_chartabsize(ptr, vcol); 7651 ++ptr; 7652 ++repl_off; 7653 } 7654 if (vcol > want_vcol) 7655 { 7656 /* Must have a char with 'showbreak' just before it. */ 7657 --ptr; 7658 --repl_off; 7659 } 7660 fpos.col += repl_off; 7661 7662 /* Delete following spaces. */ 7663 i = cursor->col - fpos.col; 7664 if (i > 0) 7665 { 7666 mch_memmove(ptr, ptr + i, STRLEN(ptr + i) + 1); 7667 /* correct replace stack. */ 7668 if ((State & REPLACE_FLAG) 7669 #ifdef FEAT_VREPLACE 7670 && !(State & VREPLACE_FLAG) 7671 #endif 7672 ) 7673 for (temp = i; --temp >= 0; ) 7674 replace_join(repl_off); 7675 } 7676 #ifdef FEAT_NETBEANS_INTG 7677 if (usingNetbeans) 7678 { 7679 netbeans_removed(curbuf, fpos.lnum, cursor->col, 7680 (long)(i + 1)); 7681 netbeans_inserted(curbuf, fpos.lnum, cursor->col, 7682 (char_u *)"\t", 1); 7683 } 7684 #endif 7685 cursor->col -= i; 7686 7687 #ifdef FEAT_VREPLACE 7688 /* 7689 * In VREPLACE mode, we haven't changed anything yet. Do it now by 7690 * backspacing over the changed spacing and then inserting the new 7691 * spacing. 7692 */ 7693 if (State & VREPLACE_FLAG) 7694 { 7695 /* Backspace from real cursor to change_col */ 7696 backspace_until_column(change_col); 7697 7698 /* Insert each char in saved_line from changed_col to 7699 * ptr-cursor */ 7700 ins_bytes_len(saved_line + change_col, 7701 cursor->col - change_col); 7702 } 7703 #endif 7704 } 7705 7706 #ifdef FEAT_VREPLACE 7707 if (State & VREPLACE_FLAG) 7708 vim_free(saved_line); 7709 #endif 7710 curwin->w_p_list = save_list; 7711 } 7712 7713 return FALSE; 7714 } 7715 7716 /* 7717 * Handle CR or NL in insert mode. 7718 * Return TRUE when out of memory or can't undo. 7719 */ 7720 static int 7721 ins_eol(c) 7722 int c; 7723 { 7724 int i; 7725 7726 if (echeck_abbr(c + ABBR_OFF)) 7727 return FALSE; 7728 if (stop_arrow() == FAIL) 7729 return TRUE; 7730 undisplay_dollar(); 7731 7732 /* 7733 * Strange Vi behaviour: In Replace mode, typing a NL will not delete the 7734 * character under the cursor. Only push a NUL on the replace stack, 7735 * nothing to put back when the NL is deleted. 7736 */ 7737 if ((State & REPLACE_FLAG) 7738 #ifdef FEAT_VREPLACE 7739 && !(State & VREPLACE_FLAG) 7740 #endif 7741 ) 7742 replace_push(NUL); 7743 7744 /* 7745 * In VREPLACE mode, a NL replaces the rest of the line, and starts 7746 * replacing the next line, so we push all of the characters left on the 7747 * line onto the replace stack. This is not done here though, it is done 7748 * in open_line(). 7749 */ 7750 7751 #ifdef FEAT_RIGHTLEFT 7752 # ifdef FEAT_FKMAP 7753 if (p_altkeymap && p_fkmap) 7754 fkmap(NL); 7755 # endif 7756 /* NL in reverse insert will always start in the end of 7757 * current line. */ 7758 if (revins_on) 7759 curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor()); 7760 #endif 7761 7762 AppendToRedobuff(NL_STR); 7763 i = open_line(FORWARD, 7764 #ifdef FEAT_COMMENTS 7765 has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 7766 #endif 7767 0, old_indent); 7768 old_indent = 0; 7769 #ifdef FEAT_CINDENT 7770 can_cindent = TRUE; 7771 #endif 7772 7773 return (!i); 7774 } 7775 7776 #ifdef FEAT_DIGRAPHS 7777 /* 7778 * Handle digraph in insert mode. 7779 * Returns character still to be inserted, or NUL when nothing remaining to be 7780 * done. 7781 */ 7782 static int 7783 ins_digraph() 7784 { 7785 int c; 7786 int cc; 7787 7788 pc_status = PC_STATUS_UNSET; 7789 if (redrawing() && !char_avail()) 7790 { 7791 /* may need to redraw when no more chars available now */ 7792 ins_redraw(); 7793 7794 edit_putchar('?', TRUE); 7795 #ifdef FEAT_CMDL_INFO 7796 add_to_showcmd_c(Ctrl_K); 7797 #endif 7798 } 7799 7800 #ifdef USE_ON_FLY_SCROLL 7801 dont_scroll = TRUE; /* disallow scrolling here */ 7802 #endif 7803 7804 /* don't map the digraph chars. This also prevents the 7805 * mode message to be deleted when ESC is hit */ 7806 ++no_mapping; 7807 ++allow_keys; 7808 c = safe_vgetc(); 7809 --no_mapping; 7810 --allow_keys; 7811 if (IS_SPECIAL(c) || mod_mask) /* special key */ 7812 { 7813 #ifdef FEAT_CMDL_INFO 7814 clear_showcmd(); 7815 #endif 7816 insert_special(c, TRUE, FALSE); 7817 return NUL; 7818 } 7819 if (c != ESC) 7820 { 7821 if (redrawing() && !char_avail()) 7822 { 7823 /* may need to redraw when no more chars available now */ 7824 ins_redraw(); 7825 7826 if (char2cells(c) == 1) 7827 { 7828 /* first remove the '?', otherwise it's restored when typing 7829 * an ESC next */ 7830 edit_unputchar(); 7831 ins_redraw(); 7832 edit_putchar(c, TRUE); 7833 } 7834 #ifdef FEAT_CMDL_INFO 7835 add_to_showcmd_c(c); 7836 #endif 7837 } 7838 ++no_mapping; 7839 ++allow_keys; 7840 cc = safe_vgetc(); 7841 --no_mapping; 7842 --allow_keys; 7843 if (cc != ESC) 7844 { 7845 AppendToRedobuff((char_u *)CTRL_V_STR); 7846 c = getdigraph(c, cc, TRUE); 7847 #ifdef FEAT_CMDL_INFO 7848 clear_showcmd(); 7849 #endif 7850 return c; 7851 } 7852 } 7853 edit_unputchar(); 7854 #ifdef FEAT_CMDL_INFO 7855 clear_showcmd(); 7856 #endif 7857 return NUL; 7858 } 7859 #endif 7860 7861 /* 7862 * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. 7863 * Returns the char to be inserted, or NUL if none found. 7864 */ 7865 static int 7866 ins_copychar(lnum) 7867 linenr_T lnum; 7868 { 7869 int c; 7870 int temp; 7871 char_u *ptr, *prev_ptr; 7872 7873 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) 7874 { 7875 vim_beep(); 7876 return NUL; 7877 } 7878 7879 /* try to advance to the cursor column */ 7880 temp = 0; 7881 ptr = ml_get(lnum); 7882 prev_ptr = ptr; 7883 validate_virtcol(); 7884 while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) 7885 { 7886 prev_ptr = ptr; 7887 temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp); 7888 } 7889 if ((colnr_T)temp > curwin->w_virtcol) 7890 ptr = prev_ptr; 7891 7892 #ifdef FEAT_MBYTE 7893 c = (*mb_ptr2char)(ptr); 7894 #else 7895 c = *ptr; 7896 #endif 7897 if (c == NUL) 7898 vim_beep(); 7899 return c; 7900 } 7901 7902 /* 7903 * CTRL-Y or CTRL-E typed in Insert mode. 7904 */ 7905 static int 7906 ins_ctrl_ey(tc) 7907 int tc; 7908 { 7909 int c = tc; 7910 7911 #ifdef FEAT_INS_EXPAND 7912 if (ctrl_x_mode == CTRL_X_SCROLL) 7913 { 7914 if (c == Ctrl_Y) 7915 scrolldown_clamp(); 7916 else 7917 scrollup_clamp(); 7918 redraw_later(VALID); 7919 } 7920 else 7921 #endif 7922 { 7923 c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1)); 7924 if (c != NUL) 7925 { 7926 long tw_save; 7927 7928 /* The character must be taken literally, insert like it 7929 * was typed after a CTRL-V, and pretend 'textwidth' 7930 * wasn't set. Digits, 'o' and 'x' are special after a 7931 * CTRL-V, don't use it for these. */ 7932 if (c < 256 && !isalnum(c)) 7933 AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ 7934 tw_save = curbuf->b_p_tw; 7935 curbuf->b_p_tw = -1; 7936 insert_special(c, TRUE, FALSE); 7937 curbuf->b_p_tw = tw_save; 7938 #ifdef FEAT_RIGHTLEFT 7939 revins_chars++; 7940 revins_legal++; 7941 #endif 7942 c = Ctrl_V; /* pretend CTRL-V is last character */ 7943 auto_format(FALSE, TRUE); 7944 } 7945 } 7946 return c; 7947 } 7948 7949 #ifdef FEAT_SMARTINDENT 7950 /* 7951 * Try to do some very smart auto-indenting. 7952 * Used when inserting a "normal" character. 7953 */ 7954 static void 7955 ins_try_si(c) 7956 int c; 7957 { 7958 pos_T *pos, old_pos; 7959 char_u *ptr; 7960 int i; 7961 int temp; 7962 7963 /* 7964 * do some very smart indenting when entering '{' or '}' 7965 */ 7966 if (((did_si || can_si_back) && c == '{') || (can_si && c == '}')) 7967 { 7968 /* 7969 * for '}' set indent equal to indent of line containing matching '{' 7970 */ 7971 if (c == '}' && (pos = findmatch(NULL, '{')) != NULL) 7972 { 7973 old_pos = curwin->w_cursor; 7974 /* 7975 * If the matching '{' has a ')' immediately before it (ignoring 7976 * white-space), then line up with the start of the line 7977 * containing the matching '(' if there is one. This handles the 7978 * case where an "if (..\n..) {" statement continues over multiple 7979 * lines -- webb 7980 */ 7981 ptr = ml_get(pos->lnum); 7982 i = pos->col; 7983 if (i > 0) /* skip blanks before '{' */ 7984 while (--i > 0 && vim_iswhite(ptr[i])) 7985 ; 7986 curwin->w_cursor.lnum = pos->lnum; 7987 curwin->w_cursor.col = i; 7988 if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL) 7989 curwin->w_cursor = *pos; 7990 i = get_indent(); 7991 curwin->w_cursor = old_pos; 7992 #ifdef FEAT_VREPLACE 7993 if (State & VREPLACE_FLAG) 7994 change_indent(INDENT_SET, i, FALSE, NUL); 7995 else 7996 #endif 7997 (void)set_indent(i, SIN_CHANGED); 7998 } 7999 else if (curwin->w_cursor.col > 0) 8000 { 8001 /* 8002 * when inserting '{' after "O" reduce indent, but not 8003 * more than indent of previous line 8004 */ 8005 temp = TRUE; 8006 if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1) 8007 { 8008 old_pos = curwin->w_cursor; 8009 i = get_indent(); 8010 while (curwin->w_cursor.lnum > 1) 8011 { 8012 ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum))); 8013 8014 /* ignore empty lines and lines starting with '#'. */ 8015 if (*ptr != '#' && *ptr != NUL) 8016 break; 8017 } 8018 if (get_indent() >= i) 8019 temp = FALSE; 8020 curwin->w_cursor = old_pos; 8021 } 8022 if (temp) 8023 shift_line(TRUE, FALSE, 1); 8024 } 8025 } 8026 8027 /* 8028 * set indent of '#' always to 0 8029 */ 8030 if (curwin->w_cursor.col > 0 && can_si && c == '#') 8031 { 8032 /* remember current indent for next line */ 8033 old_indent = get_indent(); 8034 (void)set_indent(0, SIN_CHANGED); 8035 } 8036 8037 /* Adjust ai_col, the char at this position can be deleted. */ 8038 if (ai_col > curwin->w_cursor.col) 8039 ai_col = curwin->w_cursor.col; 8040 } 8041 #endif 8042 8043 /* 8044 * Get the value that w_virtcol would have when 'list' is off. 8045 * Unless 'cpo' contains the 'L' flag. 8046 */ 8047 static colnr_T 8048 get_nolist_virtcol() 8049 { 8050 if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 8051 return getvcol_nolist(&curwin->w_cursor); 8052 validate_virtcol(); 8053 return curwin->w_virtcol; 8054 } 8055