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