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