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