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