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