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