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