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