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