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