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