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