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