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