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