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