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