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