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