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