1 /* vi:set ts=8 sts=4 sw=4 noet: 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 * ex_getln.c: Functions for entering and editing an Ex command line. 12 */ 13 14 #include "vim.h" 15 16 #ifndef MAX 17 # define MAX(x,y) ((x) > (y) ? (x) : (y)) 18 #endif 19 20 /* 21 * Variables shared between getcmdline(), redrawcmdline() and others. 22 * These need to be saved when using CTRL-R |, that's why they are in a 23 * structure. 24 */ 25 struct cmdline_info 26 { 27 char_u *cmdbuff; /* pointer to command line buffer */ 28 int cmdbufflen; /* length of cmdbuff */ 29 int cmdlen; /* number of chars in command line */ 30 int cmdpos; /* current cursor position */ 31 int cmdspos; /* cursor column on screen */ 32 int cmdfirstc; /* ':', '/', '?', '=', '>' or NUL */ 33 int cmdindent; /* number of spaces before cmdline */ 34 char_u *cmdprompt; /* message in front of cmdline */ 35 int cmdattr; /* attributes for prompt */ 36 int overstrike; /* Typing mode on the command line. Shared by 37 getcmdline() and put_on_cmdline(). */ 38 expand_T *xpc; /* struct being used for expansion, xp_pattern 39 may point into cmdbuff */ 40 int xp_context; /* type of expansion */ 41 # ifdef FEAT_EVAL 42 char_u *xp_arg; /* user-defined expansion arg */ 43 int input_fn; /* when TRUE Invoked for input() function */ 44 # endif 45 }; 46 47 // The current cmdline_info. It is initialized in getcmdline() and after that 48 // used by other functions. When invoking getcmdline() recursively it needs 49 // to be saved with save_cmdline() and restored with restore_cmdline(). 50 static struct cmdline_info ccline; 51 52 static int cmd_showtail; /* Only show path tail in lists ? */ 53 54 #ifdef FEAT_EVAL 55 static int new_cmdpos; /* position set by set_cmdline_pos() */ 56 #endif 57 58 static int extra_char = NUL; /* extra character to display when redrawing 59 * the command line */ 60 static int extra_char_shift; 61 62 #ifdef FEAT_CMDHIST 63 typedef struct hist_entry 64 { 65 int hisnum; /* identifying number */ 66 int viminfo; /* when TRUE hisstr comes from viminfo */ 67 char_u *hisstr; /* actual entry, separator char after the NUL */ 68 time_t time_set; /* when it was typed, zero if unknown */ 69 } histentry_T; 70 71 static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL}; 72 static int hisidx[HIST_COUNT] = {-1, -1, -1, -1, -1}; /* lastused entry */ 73 static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0}; 74 /* identifying (unique) number of newest history entry */ 75 static int hislen = 0; /* actual length of history tables */ 76 77 static int hist_char2type(int c); 78 #endif 79 80 #ifdef FEAT_RIGHTLEFT 81 static int cmd_hkmap = 0; /* Hebrew mapping during command line */ 82 #endif 83 84 static char_u *getcmdline_int(int firstc, long count, int indent, int init_ccline); 85 static int cmdline_charsize(int idx); 86 static void set_cmdspos(void); 87 static void set_cmdspos_cursor(void); 88 static void correct_cmdspos(int idx, int cells); 89 static void alloc_cmdbuff(int len); 90 static int realloc_cmdbuff(int len); 91 static void draw_cmdline(int start, int len); 92 static void save_cmdline(struct cmdline_info *ccp); 93 static void restore_cmdline(struct cmdline_info *ccp); 94 static int cmdline_paste(int regname, int literally, int remcr); 95 #ifdef FEAT_WILDMENU 96 static void cmdline_del(int from); 97 #endif 98 static void redrawcmdprompt(void); 99 static void cursorcmd(void); 100 static int ccheck_abbr(int); 101 static int nextwild(expand_T *xp, int type, int options, int escape); 102 static void escape_fname(char_u **pp); 103 static int showmatches(expand_T *xp, int wildmenu); 104 static void set_expand_context(expand_T *xp); 105 static int ExpandFromContext(expand_T *xp, char_u *, int *, char_u ***, int); 106 static int expand_showtail(expand_T *xp); 107 #ifdef FEAT_CMDL_COMPL 108 static int expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg); 109 static int ExpandRTDir(char_u *pat, int flags, int *num_file, char_u ***file, char *dirname[]); 110 static int ExpandPackAddDir(char_u *pat, int *num_file, char_u ***file); 111 # ifdef FEAT_CMDHIST 112 static char_u *get_history_arg(expand_T *xp, int idx); 113 # endif 114 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) 115 static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file); 116 static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file); 117 # endif 118 #endif 119 #ifdef FEAT_CMDHIST 120 static void clear_hist_entry(histentry_T *hisptr); 121 #endif 122 123 #ifdef FEAT_CMDWIN 124 static int open_cmdwin(void); 125 #endif 126 127 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 128 static int 129 #ifdef __BORLANDC__ 130 _RTLENTRYF 131 #endif 132 sort_func_compare(const void *s1, const void *s2); 133 #endif 134 135 136 static void 137 trigger_cmd_autocmd(int typechar, int evt) 138 { 139 char_u typestr[2]; 140 141 typestr[0] = typechar; 142 typestr[1] = NUL; 143 apply_autocmds(evt, typestr, typestr, FALSE, curbuf); 144 } 145 146 /* 147 * Abandon the command line. 148 */ 149 static void 150 abandon_cmdline(void) 151 { 152 VIM_CLEAR(ccline.cmdbuff); 153 if (msg_scrolled == 0) 154 compute_cmdrow(); 155 msg(""); 156 redraw_cmdline = TRUE; 157 } 158 159 #ifdef FEAT_SEARCH_EXTRA 160 /* 161 * Guess that the pattern matches everything. Only finds specific cases, such 162 * as a trailing \|, which can happen while typing a pattern. 163 */ 164 static int 165 empty_pattern(char_u *p) 166 { 167 size_t n = STRLEN(p); 168 169 /* remove trailing \v and the like */ 170 while (n >= 2 && p[n - 2] == '\\' 171 && vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL) 172 n -= 2; 173 return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|'); 174 } 175 176 // Struct to store the viewstate during 'incsearch' highlighting. 177 typedef struct { 178 colnr_T vs_curswant; 179 colnr_T vs_leftcol; 180 linenr_T vs_topline; 181 # ifdef FEAT_DIFF 182 int vs_topfill; 183 # endif 184 linenr_T vs_botline; 185 linenr_T vs_empty_rows; 186 } viewstate_T; 187 188 static void 189 save_viewstate(viewstate_T *vs) 190 { 191 vs->vs_curswant = curwin->w_curswant; 192 vs->vs_leftcol = curwin->w_leftcol; 193 vs->vs_topline = curwin->w_topline; 194 # ifdef FEAT_DIFF 195 vs->vs_topfill = curwin->w_topfill; 196 # endif 197 vs->vs_botline = curwin->w_botline; 198 vs->vs_empty_rows = curwin->w_empty_rows; 199 } 200 201 static void 202 restore_viewstate(viewstate_T *vs) 203 { 204 curwin->w_curswant = vs->vs_curswant; 205 curwin->w_leftcol = vs->vs_leftcol; 206 curwin->w_topline = vs->vs_topline; 207 # ifdef FEAT_DIFF 208 curwin->w_topfill = vs->vs_topfill; 209 # endif 210 curwin->w_botline = vs->vs_botline; 211 curwin->w_empty_rows = vs->vs_empty_rows; 212 } 213 214 // Struct to store the state of 'incsearch' highlighting. 215 typedef struct { 216 pos_T search_start; // where 'incsearch' starts searching 217 pos_T save_cursor; 218 viewstate_T init_viewstate; 219 viewstate_T old_viewstate; 220 pos_T match_start; 221 pos_T match_end; 222 int did_incsearch; 223 int incsearch_postponed; 224 int magic_save; 225 } incsearch_state_T; 226 227 static void 228 init_incsearch_state(incsearch_state_T *is_state) 229 { 230 is_state->match_start = curwin->w_cursor; 231 is_state->did_incsearch = FALSE; 232 is_state->incsearch_postponed = FALSE; 233 is_state->magic_save = p_magic; 234 CLEAR_POS(&is_state->match_end); 235 is_state->save_cursor = curwin->w_cursor; // may be restored later 236 is_state->search_start = curwin->w_cursor; 237 save_viewstate(&is_state->init_viewstate); 238 save_viewstate(&is_state->old_viewstate); 239 } 240 241 /* 242 * First move cursor to end of match, then to the start. This 243 * moves the whole match onto the screen when 'nowrap' is set. 244 */ 245 static void 246 set_search_match(pos_T *t) 247 { 248 t->lnum += search_match_lines; 249 t->col = search_match_endcol; 250 if (t->lnum > curbuf->b_ml.ml_line_count) 251 { 252 t->lnum = curbuf->b_ml.ml_line_count; 253 coladvance((colnr_T)MAXCOL); 254 } 255 } 256 257 /* 258 * Return TRUE when 'incsearch' highlighting is to be done. 259 * Sets search_first_line and search_last_line to the address range. 260 * May change the last search pattern. 261 */ 262 static int 263 do_incsearch_highlighting(int firstc, incsearch_state_T *is_state, 264 int *skiplen, int *patlen) 265 { 266 char_u *cmd; 267 cmdmod_T save_cmdmod = cmdmod; 268 char_u *p; 269 int delim_optional = FALSE; 270 int delim; 271 char_u *end; 272 char *dummy; 273 exarg_T ea; 274 pos_T save_cursor; 275 int use_last_pat; 276 277 *skiplen = 0; 278 *patlen = ccline.cmdlen; 279 280 if (!p_is || cmd_silent) 281 return FALSE; 282 283 // by default search all lines 284 search_first_line = 0; 285 search_last_line = MAXLNUM; 286 287 if (firstc == '/' || firstc == '?') 288 return TRUE; 289 if (firstc != ':') 290 return FALSE; 291 292 vim_memset(&ea, 0, sizeof(ea)); 293 ea.line1 = 1; 294 ea.line2 = 1; 295 ea.cmd = ccline.cmdbuff; 296 ea.addr_type = ADDR_LINES; 297 298 parse_command_modifiers(&ea, &dummy, TRUE); 299 cmdmod = save_cmdmod; 300 301 cmd = skip_range(ea.cmd, NULL); 302 if (vim_strchr((char_u *)"sgvl", *cmd) == NULL) 303 return FALSE; 304 305 // Skip over "substitute" to find the pattern separator. 306 for (p = cmd; ASCII_ISALPHA(*p); ++p) 307 ; 308 if (*skipwhite(p) == NUL) 309 return FALSE; 310 311 if (STRNCMP(cmd, "substitute", p - cmd) == 0 312 || STRNCMP(cmd, "smagic", p - cmd) == 0 313 || STRNCMP(cmd, "snomagic", MAX(p - cmd, 3)) == 0 314 || STRNCMP(cmd, "vglobal", p - cmd) == 0) 315 { 316 if (*cmd == 's' && cmd[1] == 'm') 317 p_magic = TRUE; 318 else if (*cmd == 's' && cmd[1] == 'n') 319 p_magic = FALSE; 320 } 321 else if (STRNCMP(cmd, "sort", MAX(p - cmd, 3)) == 0) 322 { 323 // skip over flags 324 while (ASCII_ISALPHA(*(p = skipwhite(p)))) 325 ++p; 326 if (*p == NUL) 327 return FALSE; 328 } 329 else if (STRNCMP(cmd, "vimgrep", MAX(p - cmd, 3)) == 0 330 || STRNCMP(cmd, "vimgrepadd", MAX(p - cmd, 8)) == 0 331 || STRNCMP(cmd, "lvimgrep", MAX(p - cmd, 2)) == 0 332 || STRNCMP(cmd, "lvimgrepadd", MAX(p - cmd, 9)) == 0 333 || STRNCMP(cmd, "global", p - cmd) == 0) 334 { 335 // skip over "!" 336 if (*p == '!') 337 { 338 p++; 339 if (*skipwhite(p) == NUL) 340 return FALSE; 341 } 342 if (*cmd != 'g') 343 delim_optional = TRUE; 344 } 345 else 346 return FALSE; 347 348 p = skipwhite(p); 349 delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++; 350 end = skip_regexp(p, delim, p_magic, NULL); 351 352 use_last_pat = end == p && *end == delim; 353 354 if (end == p && !use_last_pat) 355 return FALSE; 356 357 // Don't do 'hlsearch' highlighting if the pattern matches everything. 358 if (!use_last_pat) 359 { 360 char c = *end; 361 int empty; 362 363 *end = NUL; 364 empty = empty_pattern(p); 365 *end = c; 366 if (empty) 367 return FALSE; 368 } 369 370 // found a non-empty pattern or // 371 *skiplen = (int)(p - ccline.cmdbuff); 372 *patlen = (int)(end - p); 373 374 // parse the address range 375 save_cursor = curwin->w_cursor; 376 curwin->w_cursor = is_state->search_start; 377 parse_cmd_address(&ea, &dummy, TRUE); 378 if (ea.addr_count > 0) 379 { 380 // Allow for reverse match. 381 if (ea.line2 < ea.line1) 382 { 383 search_first_line = ea.line2; 384 search_last_line = ea.line1; 385 } 386 else 387 { 388 search_first_line = ea.line1; 389 search_last_line = ea.line2; 390 } 391 } 392 else if (cmd[0] == 's' && cmd[1] != 'o') 393 { 394 // :s defaults to the current line 395 search_first_line = curwin->w_cursor.lnum; 396 search_last_line = curwin->w_cursor.lnum; 397 } 398 399 curwin->w_cursor = save_cursor; 400 return TRUE; 401 } 402 403 static void 404 finish_incsearch_highlighting( 405 int gotesc, 406 incsearch_state_T *is_state, 407 int call_update_screen) 408 { 409 if (is_state->did_incsearch) 410 { 411 is_state->did_incsearch = FALSE; 412 if (gotesc) 413 curwin->w_cursor = is_state->save_cursor; 414 else 415 { 416 if (!EQUAL_POS(is_state->save_cursor, is_state->search_start)) 417 { 418 // put the '" mark at the original position 419 curwin->w_cursor = is_state->save_cursor; 420 setpcmark(); 421 } 422 curwin->w_cursor = is_state->search_start; 423 } 424 restore_viewstate(&is_state->old_viewstate); 425 highlight_match = FALSE; 426 427 // by default search all lines 428 search_first_line = 0; 429 search_last_line = MAXLNUM; 430 431 p_magic = is_state->magic_save; 432 433 validate_cursor(); /* needed for TAB */ 434 redraw_all_later(SOME_VALID); 435 if (call_update_screen) 436 update_screen(SOME_VALID); 437 } 438 } 439 440 /* 441 * Do 'incsearch' highlighting if desired. 442 */ 443 static void 444 may_do_incsearch_highlighting( 445 int firstc, 446 long count, 447 incsearch_state_T *is_state) 448 { 449 int skiplen, patlen; 450 int found; // do_search() result 451 pos_T end_pos; 452 #ifdef FEAT_RELTIME 453 proftime_T tm; 454 #endif 455 int next_char; 456 int use_last_pat; 457 458 // Parsing range may already set the last search pattern. 459 // NOTE: must call restore_last_search_pattern() before returning! 460 save_last_search_pattern(); 461 462 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) 463 { 464 restore_last_search_pattern(); 465 finish_incsearch_highlighting(FALSE, is_state, TRUE); 466 return; 467 } 468 469 // If there is a character waiting, search and redraw later. 470 if (char_avail()) 471 { 472 restore_last_search_pattern(); 473 is_state->incsearch_postponed = TRUE; 474 return; 475 } 476 is_state->incsearch_postponed = FALSE; 477 478 if (search_first_line == 0) 479 // start at the original cursor position 480 curwin->w_cursor = is_state->search_start; 481 else if (search_first_line > curbuf->b_ml.ml_line_count) 482 { 483 // start after the last line 484 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 485 curwin->w_cursor.col = MAXCOL; 486 } 487 else 488 { 489 // start at the first line in the range 490 curwin->w_cursor.lnum = search_first_line; 491 curwin->w_cursor.col = 0; 492 } 493 494 // Use the previous pattern for ":s//". 495 next_char = ccline.cmdbuff[skiplen + patlen]; 496 use_last_pat = patlen == 0 && skiplen > 0 497 && ccline.cmdbuff[skiplen - 1] == next_char; 498 499 // If there is no pattern, don't do anything. 500 if (patlen == 0 && !use_last_pat) 501 { 502 found = 0; 503 set_no_hlsearch(TRUE); // turn off previous highlight 504 redraw_all_later(SOME_VALID); 505 } 506 else 507 { 508 int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK; 509 510 cursor_off(); // so the user knows we're busy 511 out_flush(); 512 ++emsg_off; // so it doesn't beep if bad expr 513 #ifdef FEAT_RELTIME 514 // Set the time limit to half a second. 515 profile_setlimit(500L, &tm); 516 #endif 517 if (!p_hls) 518 search_flags += SEARCH_KEEP; 519 if (search_first_line != 0) 520 search_flags += SEARCH_START; 521 ccline.cmdbuff[skiplen + patlen] = NUL; 522 found = do_search(NULL, firstc == ':' ? '/' : firstc, 523 ccline.cmdbuff + skiplen, count, search_flags, 524 #ifdef FEAT_RELTIME 525 &tm, NULL 526 #else 527 NULL, NULL 528 #endif 529 ); 530 ccline.cmdbuff[skiplen + patlen] = next_char; 531 --emsg_off; 532 533 if (curwin->w_cursor.lnum < search_first_line 534 || curwin->w_cursor.lnum > search_last_line) 535 { 536 // match outside of address range 537 found = 0; 538 curwin->w_cursor = is_state->search_start; 539 } 540 541 // if interrupted while searching, behave like it failed 542 if (got_int) 543 { 544 (void)vpeekc(); // remove <C-C> from input stream 545 got_int = FALSE; // don't abandon the command line 546 found = 0; 547 } 548 else if (char_avail()) 549 // cancelled searching because a char was typed 550 is_state->incsearch_postponed = TRUE; 551 } 552 if (found != 0) 553 highlight_match = TRUE; // highlight position 554 else 555 highlight_match = FALSE; // remove highlight 556 557 // First restore the old curwin values, so the screen is positioned in the 558 // same way as the actual search command. 559 restore_viewstate(&is_state->old_viewstate); 560 changed_cline_bef_curs(); 561 update_topline(); 562 563 if (found != 0) 564 { 565 pos_T save_pos = curwin->w_cursor; 566 567 is_state->match_start = curwin->w_cursor; 568 set_search_match(&curwin->w_cursor); 569 validate_cursor(); 570 end_pos = curwin->w_cursor; 571 is_state->match_end = end_pos; 572 curwin->w_cursor = save_pos; 573 } 574 else 575 end_pos = curwin->w_cursor; // shutup gcc 4 576 577 // Disable 'hlsearch' highlighting if the pattern matches everything. 578 // Avoids a flash when typing "foo\|". 579 if (!use_last_pat) 580 { 581 next_char = ccline.cmdbuff[skiplen + patlen]; 582 ccline.cmdbuff[skiplen + patlen] = NUL; 583 if (empty_pattern(ccline.cmdbuff) && !no_hlsearch) 584 { 585 redraw_all_later(SOME_VALID); 586 set_no_hlsearch(TRUE); 587 } 588 ccline.cmdbuff[skiplen + patlen] = next_char; 589 } 590 591 validate_cursor(); 592 // May redraw the status line to show the cursor position. 593 if (p_ru && curwin->w_status_height > 0) 594 curwin->w_redr_status = TRUE; 595 596 update_screen(SOME_VALID); 597 restore_last_search_pattern(); 598 599 // Leave it at the end to make CTRL-R CTRL-W work. But not when beyond the 600 // end of the pattern, e.g. for ":s/pat/". 601 if (ccline.cmdbuff[skiplen + patlen] != NUL) 602 curwin->w_cursor = is_state->search_start; 603 else if (found != 0) 604 curwin->w_cursor = end_pos; 605 606 msg_starthere(); 607 redrawcmdline(); 608 is_state->did_incsearch = TRUE; 609 } 610 611 /* 612 * May adjust 'incsearch' highlighting for typing CTRL-G and CTRL-T, go to next 613 * or previous match. 614 * Returns FAIL when jumping to cmdline_not_changed; 615 */ 616 static int 617 may_adjust_incsearch_highlighting( 618 int firstc, 619 long count, 620 incsearch_state_T *is_state, 621 int c) 622 { 623 int skiplen, patlen; 624 pos_T t; 625 char_u *pat; 626 int search_flags = SEARCH_NOOF; 627 int i; 628 int save; 629 630 // Parsing range may already set the last search pattern. 631 // NOTE: must call restore_last_search_pattern() before returning! 632 save_last_search_pattern(); 633 634 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) 635 { 636 restore_last_search_pattern(); 637 return OK; 638 } 639 if (patlen == 0 && ccline.cmdbuff[skiplen] == NUL) 640 { 641 restore_last_search_pattern(); 642 return FAIL; 643 } 644 645 if (firstc == ccline.cmdbuff[skiplen]) 646 { 647 pat = last_search_pattern(); 648 skiplen = 0; 649 patlen = (int)STRLEN(pat); 650 } 651 else 652 pat = ccline.cmdbuff + skiplen; 653 654 cursor_off(); 655 out_flush(); 656 if (c == Ctrl_G) 657 { 658 t = is_state->match_end; 659 if (LT_POS(is_state->match_start, is_state->match_end)) 660 // Start searching at the end of the match not at the beginning of 661 // the next column. 662 (void)decl(&t); 663 search_flags += SEARCH_COL; 664 } 665 else 666 t = is_state->match_start; 667 if (!p_hls) 668 search_flags += SEARCH_KEEP; 669 ++emsg_off; 670 save = pat[patlen]; 671 pat[patlen] = NUL; 672 i = searchit(curwin, curbuf, &t, NULL, 673 c == Ctrl_G ? FORWARD : BACKWARD, 674 pat, count, search_flags, 675 RE_SEARCH, 0, NULL, NULL); 676 --emsg_off; 677 pat[patlen] = save; 678 if (i) 679 { 680 is_state->search_start = is_state->match_start; 681 is_state->match_end = t; 682 is_state->match_start = t; 683 if (c == Ctrl_T && firstc != '?') 684 { 685 // Move just before the current match, so that when nv_search 686 // finishes the cursor will be put back on the match. 687 is_state->search_start = t; 688 (void)decl(&is_state->search_start); 689 } 690 else if (c == Ctrl_G && firstc == '?') 691 { 692 // Move just after the current match, so that when nv_search 693 // finishes the cursor will be put back on the match. 694 is_state->search_start = t; 695 (void)incl(&is_state->search_start); 696 } 697 if (LT_POS(t, is_state->search_start) && c == Ctrl_G) 698 { 699 // wrap around 700 is_state->search_start = t; 701 if (firstc == '?') 702 (void)incl(&is_state->search_start); 703 else 704 (void)decl(&is_state->search_start); 705 } 706 707 set_search_match(&is_state->match_end); 708 curwin->w_cursor = is_state->match_start; 709 changed_cline_bef_curs(); 710 update_topline(); 711 validate_cursor(); 712 highlight_match = TRUE; 713 save_viewstate(&is_state->old_viewstate); 714 update_screen(NOT_VALID); 715 redrawcmdline(); 716 } 717 else 718 vim_beep(BO_ERROR); 719 restore_last_search_pattern(); 720 return FAIL; 721 } 722 723 /* 724 * When CTRL-L typed: add character from the match to the pattern. 725 * May set "*c" to the added character. 726 * Return OK when jumping to cmdline_not_changed. 727 */ 728 static int 729 may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) 730 { 731 int skiplen, patlen; 732 733 // Parsing range may already set the last search pattern. 734 // NOTE: must call restore_last_search_pattern() before returning! 735 save_last_search_pattern(); 736 737 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) 738 { 739 restore_last_search_pattern(); 740 return FAIL; 741 } 742 restore_last_search_pattern(); 743 744 // Add a character from under the cursor for 'incsearch'. 745 if (is_state->did_incsearch) 746 { 747 curwin->w_cursor = is_state->match_end; 748 if (!EQUAL_POS(curwin->w_cursor, is_state->search_start)) 749 { 750 *c = gchar_cursor(); 751 752 // If 'ignorecase' and 'smartcase' are set and the 753 // command line has no uppercase characters, convert 754 // the character to lowercase. 755 if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen)) 756 *c = MB_TOLOWER(*c); 757 if (*c != NUL) 758 { 759 if (*c == firstc || vim_strchr((char_u *)( 760 p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) 761 { 762 // put a backslash before special characters 763 stuffcharReadbuff(*c); 764 *c = '\\'; 765 } 766 // add any composing characters 767 if (mb_char2len(*c) != mb_ptr2len(ml_get_cursor())) 768 { 769 int save_c = *c; 770 771 while (mb_char2len(*c) != mb_ptr2len(ml_get_cursor())) 772 { 773 curwin->w_cursor.col += mb_char2len(*c); 774 *c = gchar_cursor(); 775 stuffcharReadbuff(*c); 776 } 777 *c = save_c; 778 } 779 return FAIL; 780 } 781 } 782 } 783 return OK; 784 } 785 #endif 786 787 void 788 cmdline_init(void) 789 { 790 vim_memset(&ccline, 0, sizeof(struct cmdline_info)); 791 } 792 793 /* 794 * getcmdline() - accept a command line starting with firstc. 795 * 796 * firstc == ':' get ":" command line. 797 * firstc == '/' or '?' get search pattern 798 * firstc == '=' get expression 799 * firstc == '@' get text for input() function 800 * firstc == '>' get text for debug mode 801 * firstc == NUL get text for :insert command 802 * firstc == -1 like NUL, and break on CTRL-C 803 * 804 * The line is collected in ccline.cmdbuff, which is reallocated to fit the 805 * command line. 806 * 807 * Careful: getcmdline() can be called recursively! 808 * 809 * Return pointer to allocated string if there is a commandline, NULL 810 * otherwise. 811 */ 812 char_u * 813 getcmdline( 814 int firstc, 815 long count, // only used for incremental search 816 int indent) // indent for inside conditionals 817 { 818 return getcmdline_int(firstc, count, indent, TRUE); 819 } 820 821 static char_u * 822 getcmdline_int( 823 int firstc, 824 long count UNUSED, // only used for incremental search 825 int indent, // indent for inside conditionals 826 int init_ccline) // clear ccline first 827 { 828 int c; 829 int i; 830 int j; 831 int gotesc = FALSE; /* TRUE when <ESC> just typed */ 832 int do_abbr; /* when TRUE check for abbr. */ 833 #ifdef FEAT_CMDHIST 834 char_u *lookfor = NULL; /* string to match */ 835 int hiscnt; /* current history line in use */ 836 int histype; /* history type to be used */ 837 #endif 838 #ifdef FEAT_SEARCH_EXTRA 839 incsearch_state_T is_state; 840 #endif 841 int did_wild_list = FALSE; /* did wild_list() recently */ 842 int wim_index = 0; /* index in wim_flags[] */ 843 int res; 844 int save_msg_scroll = msg_scroll; 845 int save_State = State; /* remember State when called */ 846 int some_key_typed = FALSE; /* one of the keys was typed */ 847 #ifdef FEAT_MOUSE 848 /* mouse drag and release events are ignored, unless they are 849 * preceded with a mouse down event */ 850 int ignore_drag_release = TRUE; 851 #endif 852 #ifdef FEAT_EVAL 853 int break_ctrl_c = FALSE; 854 #endif 855 expand_T xpc; 856 long *b_im_ptr = NULL; 857 struct cmdline_info save_ccline; 858 int did_save_ccline = FALSE; 859 int cmdline_type; 860 861 if (ccline.cmdbuff != NULL) 862 { 863 // Being called recursively. Since ccline is global, we need to save 864 // the current buffer and restore it when returning. 865 save_cmdline(&save_ccline); 866 did_save_ccline = TRUE; 867 } 868 if (init_ccline) 869 vim_memset(&ccline, 0, sizeof(struct cmdline_info)); 870 871 #ifdef FEAT_EVAL 872 if (firstc == -1) 873 { 874 firstc = NUL; 875 break_ctrl_c = TRUE; 876 } 877 #endif 878 #ifdef FEAT_RIGHTLEFT 879 /* start without Hebrew mapping for a command line */ 880 if (firstc == ':' || firstc == '=' || firstc == '>') 881 cmd_hkmap = 0; 882 #endif 883 884 ccline.overstrike = FALSE; /* always start in insert mode */ 885 886 #ifdef FEAT_SEARCH_EXTRA 887 init_incsearch_state(&is_state); 888 #endif 889 890 /* 891 * set some variables for redrawcmd() 892 */ 893 ccline.cmdfirstc = (firstc == '@' ? 0 : firstc); 894 ccline.cmdindent = (firstc > 0 ? indent : 0); 895 896 /* alloc initial ccline.cmdbuff */ 897 alloc_cmdbuff(exmode_active ? 250 : indent + 1); 898 if (ccline.cmdbuff == NULL) 899 goto theend; // out of memory 900 ccline.cmdlen = ccline.cmdpos = 0; 901 ccline.cmdbuff[0] = NUL; 902 sb_text_start_cmdline(); 903 904 /* autoindent for :insert and :append */ 905 if (firstc <= 0) 906 { 907 vim_memset(ccline.cmdbuff, ' ', indent); 908 ccline.cmdbuff[indent] = NUL; 909 ccline.cmdpos = indent; 910 ccline.cmdspos = indent; 911 ccline.cmdlen = indent; 912 } 913 914 ExpandInit(&xpc); 915 ccline.xpc = &xpc; 916 917 #ifdef FEAT_RIGHTLEFT 918 if (curwin->w_p_rl && *curwin->w_p_rlc == 's' 919 && (firstc == '/' || firstc == '?')) 920 cmdmsg_rl = TRUE; 921 else 922 cmdmsg_rl = FALSE; 923 #endif 924 925 redir_off = TRUE; /* don't redirect the typed command */ 926 if (!cmd_silent) 927 { 928 i = msg_scrolled; 929 msg_scrolled = 0; /* avoid wait_return message */ 930 gotocmdline(TRUE); 931 msg_scrolled += i; 932 redrawcmdprompt(); /* draw prompt or indent */ 933 set_cmdspos(); 934 } 935 xpc.xp_context = EXPAND_NOTHING; 936 xpc.xp_backslash = XP_BS_NONE; 937 #ifndef BACKSLASH_IN_FILENAME 938 xpc.xp_shell = FALSE; 939 #endif 940 941 #if defined(FEAT_EVAL) 942 if (ccline.input_fn) 943 { 944 xpc.xp_context = ccline.xp_context; 945 xpc.xp_pattern = ccline.cmdbuff; 946 # if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) 947 xpc.xp_arg = ccline.xp_arg; 948 # endif 949 } 950 #endif 951 952 /* 953 * Avoid scrolling when called by a recursive do_cmdline(), e.g. when 954 * doing ":@0" when register 0 doesn't contain a CR. 955 */ 956 msg_scroll = FALSE; 957 958 State = CMDLINE; 959 960 if (firstc == '/' || firstc == '?' || firstc == '@') 961 { 962 /* Use ":lmap" mappings for search pattern and input(). */ 963 if (curbuf->b_p_imsearch == B_IMODE_USE_INSERT) 964 b_im_ptr = &curbuf->b_p_iminsert; 965 else 966 b_im_ptr = &curbuf->b_p_imsearch; 967 if (*b_im_ptr == B_IMODE_LMAP) 968 State |= LANGMAP; 969 #ifdef HAVE_INPUT_METHOD 970 im_set_active(*b_im_ptr == B_IMODE_IM); 971 #endif 972 } 973 #ifdef HAVE_INPUT_METHOD 974 else if (p_imcmdline) 975 im_set_active(TRUE); 976 #endif 977 978 #ifdef FEAT_MOUSE 979 setmouse(); 980 #endif 981 #ifdef CURSOR_SHAPE 982 ui_cursor_shape(); /* may show different cursor shape */ 983 #endif 984 985 /* When inside an autocommand for writing "exiting" may be set and 986 * terminal mode set to cooked. Need to set raw mode here then. */ 987 settmode(TMODE_RAW); 988 989 /* Trigger CmdlineEnter autocommands. */ 990 cmdline_type = firstc == NUL ? '-' : firstc; 991 trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINEENTER); 992 993 #ifdef FEAT_CMDHIST 994 init_history(); 995 hiscnt = hislen; /* set hiscnt to impossible history value */ 996 histype = hist_char2type(firstc); 997 #endif 998 999 #ifdef FEAT_DIGRAPHS 1000 do_digraph(-1); /* init digraph typeahead */ 1001 #endif 1002 1003 /* If something above caused an error, reset the flags, we do want to type 1004 * and execute commands. Display may be messed up a bit. */ 1005 if (did_emsg) 1006 redrawcmd(); 1007 did_emsg = FALSE; 1008 got_int = FALSE; 1009 1010 /* 1011 * Collect the command string, handling editing keys. 1012 */ 1013 for (;;) 1014 { 1015 redir_off = TRUE; /* Don't redirect the typed command. 1016 Repeated, because a ":redir" inside 1017 completion may switch it on. */ 1018 #ifdef USE_ON_FLY_SCROLL 1019 dont_scroll = FALSE; /* allow scrolling here */ 1020 #endif 1021 quit_more = FALSE; /* reset after CTRL-D which had a more-prompt */ 1022 1023 did_emsg = FALSE; /* There can't really be a reason why an error 1024 that occurs while typing a command should 1025 cause the command not to be executed. */ 1026 1027 cursorcmd(); /* set the cursor on the right spot */ 1028 1029 /* Get a character. Ignore K_IGNORE and K_NOP, they should not do 1030 * anything, such as stop completion. */ 1031 do 1032 { 1033 c = safe_vgetc(); 1034 } while (c == K_IGNORE || c == K_NOP); 1035 1036 if (KeyTyped) 1037 { 1038 some_key_typed = TRUE; 1039 #ifdef FEAT_RIGHTLEFT 1040 if (cmd_hkmap) 1041 c = hkmap(c); 1042 if (cmdmsg_rl && !KeyStuffed) 1043 { 1044 /* Invert horizontal movements and operations. Only when 1045 * typed by the user directly, not when the result of a 1046 * mapping. */ 1047 switch (c) 1048 { 1049 case K_RIGHT: c = K_LEFT; break; 1050 case K_S_RIGHT: c = K_S_LEFT; break; 1051 case K_C_RIGHT: c = K_C_LEFT; break; 1052 case K_LEFT: c = K_RIGHT; break; 1053 case K_S_LEFT: c = K_S_RIGHT; break; 1054 case K_C_LEFT: c = K_C_RIGHT; break; 1055 } 1056 } 1057 #endif 1058 } 1059 1060 /* 1061 * Ignore got_int when CTRL-C was typed here. 1062 * Don't ignore it in :global, we really need to break then, e.g., for 1063 * ":g/pat/normal /pat" (without the <CR>). 1064 * Don't ignore it for the input() function. 1065 */ 1066 if ((c == Ctrl_C 1067 #ifdef UNIX 1068 || c == intr_char 1069 #endif 1070 ) 1071 #if defined(FEAT_EVAL) || defined(FEAT_CRYPT) 1072 && firstc != '@' 1073 #endif 1074 #ifdef FEAT_EVAL 1075 && !break_ctrl_c 1076 #endif 1077 && !global_busy) 1078 got_int = FALSE; 1079 1080 #ifdef FEAT_CMDHIST 1081 /* free old command line when finished moving around in the history 1082 * list */ 1083 if (lookfor != NULL 1084 && c != K_S_DOWN && c != K_S_UP 1085 && c != K_DOWN && c != K_UP 1086 && c != K_PAGEDOWN && c != K_PAGEUP 1087 && c != K_KPAGEDOWN && c != K_KPAGEUP 1088 && c != K_LEFT && c != K_RIGHT 1089 && (xpc.xp_numfiles > 0 || (c != Ctrl_P && c != Ctrl_N))) 1090 VIM_CLEAR(lookfor); 1091 #endif 1092 1093 /* 1094 * When there are matching completions to select <S-Tab> works like 1095 * CTRL-P (unless 'wc' is <S-Tab>). 1096 */ 1097 if (c != p_wc && c == K_S_TAB && xpc.xp_numfiles > 0) 1098 c = Ctrl_P; 1099 1100 #ifdef FEAT_WILDMENU 1101 /* Special translations for 'wildmenu' */ 1102 if (did_wild_list && p_wmnu) 1103 { 1104 if (c == K_LEFT) 1105 c = Ctrl_P; 1106 else if (c == K_RIGHT) 1107 c = Ctrl_N; 1108 } 1109 /* Hitting CR after "emenu Name.": complete submenu */ 1110 if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu 1111 && ccline.cmdpos > 1 1112 && ccline.cmdbuff[ccline.cmdpos - 1] == '.' 1113 && ccline.cmdbuff[ccline.cmdpos - 2] != '\\' 1114 && (c == '\n' || c == '\r' || c == K_KENTER)) 1115 c = K_DOWN; 1116 #endif 1117 1118 /* free expanded names when finished walking through matches */ 1119 if (xpc.xp_numfiles != -1 1120 && !(c == p_wc && KeyTyped) && c != p_wcm 1121 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_A 1122 && c != Ctrl_L) 1123 { 1124 (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE); 1125 did_wild_list = FALSE; 1126 #ifdef FEAT_WILDMENU 1127 if (!p_wmnu || (c != K_UP && c != K_DOWN)) 1128 #endif 1129 xpc.xp_context = EXPAND_NOTHING; 1130 wim_index = 0; 1131 #ifdef FEAT_WILDMENU 1132 if (p_wmnu && wild_menu_showing != 0) 1133 { 1134 int skt = KeyTyped; 1135 int old_RedrawingDisabled = RedrawingDisabled; 1136 1137 if (ccline.input_fn) 1138 RedrawingDisabled = 0; 1139 1140 if (wild_menu_showing == WM_SCROLLED) 1141 { 1142 /* Entered command line, move it up */ 1143 cmdline_row--; 1144 redrawcmd(); 1145 } 1146 else if (save_p_ls != -1) 1147 { 1148 /* restore 'laststatus' and 'winminheight' */ 1149 p_ls = save_p_ls; 1150 p_wmh = save_p_wmh; 1151 last_status(FALSE); 1152 update_screen(VALID); /* redraw the screen NOW */ 1153 redrawcmd(); 1154 save_p_ls = -1; 1155 } 1156 else 1157 { 1158 win_redraw_last_status(topframe); 1159 redraw_statuslines(); 1160 } 1161 KeyTyped = skt; 1162 wild_menu_showing = 0; 1163 if (ccline.input_fn) 1164 RedrawingDisabled = old_RedrawingDisabled; 1165 } 1166 #endif 1167 } 1168 1169 #ifdef FEAT_WILDMENU 1170 /* Special translations for 'wildmenu' */ 1171 if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) 1172 { 1173 /* Hitting <Down> after "emenu Name.": complete submenu */ 1174 if (c == K_DOWN && ccline.cmdpos > 0 1175 && ccline.cmdbuff[ccline.cmdpos - 1] == '.') 1176 c = p_wc; 1177 else if (c == K_UP) 1178 { 1179 /* Hitting <Up>: Remove one submenu name in front of the 1180 * cursor */ 1181 int found = FALSE; 1182 1183 j = (int)(xpc.xp_pattern - ccline.cmdbuff); 1184 i = 0; 1185 while (--j > 0) 1186 { 1187 /* check for start of menu name */ 1188 if (ccline.cmdbuff[j] == ' ' 1189 && ccline.cmdbuff[j - 1] != '\\') 1190 { 1191 i = j + 1; 1192 break; 1193 } 1194 /* check for start of submenu name */ 1195 if (ccline.cmdbuff[j] == '.' 1196 && ccline.cmdbuff[j - 1] != '\\') 1197 { 1198 if (found) 1199 { 1200 i = j + 1; 1201 break; 1202 } 1203 else 1204 found = TRUE; 1205 } 1206 } 1207 if (i > 0) 1208 cmdline_del(i); 1209 c = p_wc; 1210 xpc.xp_context = EXPAND_NOTHING; 1211 } 1212 } 1213 if ((xpc.xp_context == EXPAND_FILES 1214 || xpc.xp_context == EXPAND_DIRECTORIES 1215 || xpc.xp_context == EXPAND_SHELLCMD) && p_wmnu) 1216 { 1217 char_u upseg[5]; 1218 1219 upseg[0] = PATHSEP; 1220 upseg[1] = '.'; 1221 upseg[2] = '.'; 1222 upseg[3] = PATHSEP; 1223 upseg[4] = NUL; 1224 1225 if (c == K_DOWN 1226 && ccline.cmdpos > 0 1227 && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP 1228 && (ccline.cmdpos < 3 1229 || ccline.cmdbuff[ccline.cmdpos - 2] != '.' 1230 || ccline.cmdbuff[ccline.cmdpos - 3] != '.')) 1231 { 1232 /* go down a directory */ 1233 c = p_wc; 1234 } 1235 else if (STRNCMP(xpc.xp_pattern, upseg + 1, 3) == 0 && c == K_DOWN) 1236 { 1237 /* If in a direct ancestor, strip off one ../ to go down */ 1238 int found = FALSE; 1239 1240 j = ccline.cmdpos; 1241 i = (int)(xpc.xp_pattern - ccline.cmdbuff); 1242 while (--j > i) 1243 { 1244 if (has_mbyte) 1245 j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j); 1246 if (vim_ispathsep(ccline.cmdbuff[j])) 1247 { 1248 found = TRUE; 1249 break; 1250 } 1251 } 1252 if (found 1253 && ccline.cmdbuff[j - 1] == '.' 1254 && ccline.cmdbuff[j - 2] == '.' 1255 && (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2)) 1256 { 1257 cmdline_del(j - 2); 1258 c = p_wc; 1259 } 1260 } 1261 else if (c == K_UP) 1262 { 1263 /* go up a directory */ 1264 int found = FALSE; 1265 1266 j = ccline.cmdpos - 1; 1267 i = (int)(xpc.xp_pattern - ccline.cmdbuff); 1268 while (--j > i) 1269 { 1270 if (has_mbyte) 1271 j -= (*mb_head_off)(ccline.cmdbuff, ccline.cmdbuff + j); 1272 if (vim_ispathsep(ccline.cmdbuff[j]) 1273 #ifdef BACKSLASH_IN_FILENAME 1274 && vim_strchr((char_u *)" *?[{`$%#", 1275 ccline.cmdbuff[j + 1]) == NULL 1276 #endif 1277 ) 1278 { 1279 if (found) 1280 { 1281 i = j + 1; 1282 break; 1283 } 1284 else 1285 found = TRUE; 1286 } 1287 } 1288 1289 if (!found) 1290 j = i; 1291 else if (STRNCMP(ccline.cmdbuff + j, upseg, 4) == 0) 1292 j += 4; 1293 else if (STRNCMP(ccline.cmdbuff + j, upseg + 1, 3) == 0 1294 && j == i) 1295 j += 3; 1296 else 1297 j = 0; 1298 if (j > 0) 1299 { 1300 /* TODO this is only for DOS/UNIX systems - need to put in 1301 * machine-specific stuff here and in upseg init */ 1302 cmdline_del(j); 1303 put_on_cmdline(upseg + 1, 3, FALSE); 1304 } 1305 else if (ccline.cmdpos > i) 1306 cmdline_del(i); 1307 1308 /* Now complete in the new directory. Set KeyTyped in case the 1309 * Up key came from a mapping. */ 1310 c = p_wc; 1311 KeyTyped = TRUE; 1312 } 1313 } 1314 1315 #endif /* FEAT_WILDMENU */ 1316 1317 /* CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert 1318 * mode when 'insertmode' is set, CTRL-\ e prompts for an expression. */ 1319 if (c == Ctrl_BSL) 1320 { 1321 ++no_mapping; 1322 ++allow_keys; 1323 c = plain_vgetc(); 1324 --no_mapping; 1325 --allow_keys; 1326 /* CTRL-\ e doesn't work when obtaining an expression, unless it 1327 * is in a mapping. */ 1328 if (c != Ctrl_N && c != Ctrl_G && (c != 'e' 1329 || (ccline.cmdfirstc == '=' && KeyTyped) 1330 #ifdef FEAT_EVAL 1331 || cmdline_star > 0 1332 #endif 1333 )) 1334 { 1335 vungetc(c); 1336 c = Ctrl_BSL; 1337 } 1338 #ifdef FEAT_EVAL 1339 else if (c == 'e') 1340 { 1341 char_u *p = NULL; 1342 int len; 1343 1344 /* 1345 * Replace the command line with the result of an expression. 1346 * Need to save and restore the current command line, to be 1347 * able to enter a new one... 1348 */ 1349 if (ccline.cmdpos == ccline.cmdlen) 1350 new_cmdpos = 99999; /* keep it at the end */ 1351 else 1352 new_cmdpos = ccline.cmdpos; 1353 1354 c = get_expr_register(); 1355 if (c == '=') 1356 { 1357 /* Need to save and restore ccline. And set "textlock" 1358 * to avoid nasty things like going to another buffer when 1359 * evaluating an expression. */ 1360 ++textlock; 1361 p = get_expr_line(); 1362 --textlock; 1363 1364 if (p != NULL) 1365 { 1366 len = (int)STRLEN(p); 1367 if (realloc_cmdbuff(len + 1) == OK) 1368 { 1369 ccline.cmdlen = len; 1370 STRCPY(ccline.cmdbuff, p); 1371 vim_free(p); 1372 1373 /* Restore the cursor or use the position set with 1374 * set_cmdline_pos(). */ 1375 if (new_cmdpos > ccline.cmdlen) 1376 ccline.cmdpos = ccline.cmdlen; 1377 else 1378 ccline.cmdpos = new_cmdpos; 1379 1380 KeyTyped = FALSE; /* Don't do p_wc completion. */ 1381 redrawcmd(); 1382 goto cmdline_changed; 1383 } 1384 vim_free(p); 1385 } 1386 } 1387 beep_flush(); 1388 got_int = FALSE; /* don't abandon the command line */ 1389 did_emsg = FALSE; 1390 emsg_on_display = FALSE; 1391 redrawcmd(); 1392 goto cmdline_not_changed; 1393 } 1394 #endif 1395 else 1396 { 1397 if (c == Ctrl_G && p_im && restart_edit == 0) 1398 restart_edit = 'a'; 1399 gotesc = TRUE; /* will free ccline.cmdbuff after putting it 1400 in history */ 1401 goto returncmd; /* back to Normal mode */ 1402 } 1403 } 1404 1405 #ifdef FEAT_CMDWIN 1406 if (c == cedit_key || c == K_CMDWIN) 1407 { 1408 if (ex_normal_busy == 0 && got_int == FALSE) 1409 { 1410 /* 1411 * Open a window to edit the command line (and history). 1412 */ 1413 c = open_cmdwin(); 1414 some_key_typed = TRUE; 1415 } 1416 } 1417 # ifdef FEAT_DIGRAPHS 1418 else 1419 # endif 1420 #endif 1421 #ifdef FEAT_DIGRAPHS 1422 c = do_digraph(c); 1423 #endif 1424 1425 if (c == '\n' || c == '\r' || c == K_KENTER || (c == ESC 1426 && (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL))) 1427 { 1428 /* In Ex mode a backslash escapes a newline. */ 1429 if (exmode_active 1430 && c != ESC 1431 && ccline.cmdpos == ccline.cmdlen 1432 && ccline.cmdpos > 0 1433 && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') 1434 { 1435 if (c == K_KENTER) 1436 c = '\n'; 1437 } 1438 else 1439 { 1440 gotesc = FALSE; /* Might have typed ESC previously, don't 1441 truncate the cmdline now. */ 1442 if (ccheck_abbr(c + ABBR_OFF)) 1443 goto cmdline_changed; 1444 if (!cmd_silent) 1445 { 1446 windgoto(msg_row, 0); 1447 out_flush(); 1448 } 1449 break; 1450 } 1451 } 1452 1453 /* 1454 * Completion for 'wildchar' or 'wildcharm' key. 1455 * - hitting <ESC> twice means: abandon command line. 1456 * - wildcard expansion is only done when the 'wildchar' key is really 1457 * typed, not when it comes from a macro 1458 */ 1459 if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm) 1460 { 1461 if (xpc.xp_numfiles > 0) /* typed p_wc at least twice */ 1462 { 1463 /* if 'wildmode' contains "list" may still need to list */ 1464 if (xpc.xp_numfiles > 1 1465 && !did_wild_list 1466 && (wim_flags[wim_index] & WIM_LIST)) 1467 { 1468 (void)showmatches(&xpc, FALSE); 1469 redrawcmd(); 1470 did_wild_list = TRUE; 1471 } 1472 if (wim_flags[wim_index] & WIM_LONGEST) 1473 res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, 1474 firstc != '@'); 1475 else if (wim_flags[wim_index] & WIM_FULL) 1476 res = nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP, 1477 firstc != '@'); 1478 else 1479 res = OK; /* don't insert 'wildchar' now */ 1480 } 1481 else /* typed p_wc first time */ 1482 { 1483 wim_index = 0; 1484 j = ccline.cmdpos; 1485 /* if 'wildmode' first contains "longest", get longest 1486 * common part */ 1487 if (wim_flags[0] & WIM_LONGEST) 1488 res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, 1489 firstc != '@'); 1490 else 1491 res = nextwild(&xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP, 1492 firstc != '@'); 1493 1494 /* if interrupted while completing, behave like it failed */ 1495 if (got_int) 1496 { 1497 (void)vpeekc(); /* remove <C-C> from input stream */ 1498 got_int = FALSE; /* don't abandon the command line */ 1499 (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE); 1500 #ifdef FEAT_WILDMENU 1501 xpc.xp_context = EXPAND_NOTHING; 1502 #endif 1503 goto cmdline_changed; 1504 } 1505 1506 /* when more than one match, and 'wildmode' first contains 1507 * "list", or no change and 'wildmode' contains "longest,list", 1508 * list all matches */ 1509 if (res == OK && xpc.xp_numfiles > 1) 1510 { 1511 /* a "longest" that didn't do anything is skipped (but not 1512 * "list:longest") */ 1513 if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j) 1514 wim_index = 1; 1515 if ((wim_flags[wim_index] & WIM_LIST) 1516 #ifdef FEAT_WILDMENU 1517 || (p_wmnu && (wim_flags[wim_index] & WIM_FULL) != 0) 1518 #endif 1519 ) 1520 { 1521 if (!(wim_flags[0] & WIM_LONGEST)) 1522 { 1523 #ifdef FEAT_WILDMENU 1524 int p_wmnu_save = p_wmnu; 1525 p_wmnu = 0; 1526 #endif 1527 /* remove match */ 1528 nextwild(&xpc, WILD_PREV, 0, firstc != '@'); 1529 #ifdef FEAT_WILDMENU 1530 p_wmnu = p_wmnu_save; 1531 #endif 1532 } 1533 #ifdef FEAT_WILDMENU 1534 (void)showmatches(&xpc, p_wmnu 1535 && ((wim_flags[wim_index] & WIM_LIST) == 0)); 1536 #else 1537 (void)showmatches(&xpc, FALSE); 1538 #endif 1539 redrawcmd(); 1540 did_wild_list = TRUE; 1541 if (wim_flags[wim_index] & WIM_LONGEST) 1542 nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, 1543 firstc != '@'); 1544 else if (wim_flags[wim_index] & WIM_FULL) 1545 nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP, 1546 firstc != '@'); 1547 } 1548 else 1549 vim_beep(BO_WILD); 1550 } 1551 #ifdef FEAT_WILDMENU 1552 else if (xpc.xp_numfiles == -1) 1553 xpc.xp_context = EXPAND_NOTHING; 1554 #endif 1555 } 1556 if (wim_index < 3) 1557 ++wim_index; 1558 if (c == ESC) 1559 gotesc = TRUE; 1560 if (res == OK) 1561 goto cmdline_changed; 1562 } 1563 1564 gotesc = FALSE; 1565 1566 /* <S-Tab> goes to last match, in a clumsy way */ 1567 if (c == K_S_TAB && KeyTyped) 1568 { 1569 if (nextwild(&xpc, WILD_EXPAND_KEEP, 0, firstc != '@') == OK 1570 && nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK 1571 && nextwild(&xpc, WILD_PREV, 0, firstc != '@') == OK) 1572 goto cmdline_changed; 1573 } 1574 1575 if (c == NUL || c == K_ZERO) /* NUL is stored as NL */ 1576 c = NL; 1577 1578 do_abbr = TRUE; /* default: check for abbreviation */ 1579 1580 /* 1581 * Big switch for a typed command line character. 1582 */ 1583 switch (c) 1584 { 1585 case K_BS: 1586 case Ctrl_H: 1587 case K_DEL: 1588 case K_KDEL: 1589 case Ctrl_W: 1590 if (c == K_KDEL) 1591 c = K_DEL; 1592 1593 /* 1594 * delete current character is the same as backspace on next 1595 * character, except at end of line 1596 */ 1597 if (c == K_DEL && ccline.cmdpos != ccline.cmdlen) 1598 ++ccline.cmdpos; 1599 if (has_mbyte && c == K_DEL) 1600 ccline.cmdpos += mb_off_next(ccline.cmdbuff, 1601 ccline.cmdbuff + ccline.cmdpos); 1602 if (ccline.cmdpos > 0) 1603 { 1604 char_u *p; 1605 1606 j = ccline.cmdpos; 1607 p = ccline.cmdbuff + j; 1608 if (has_mbyte) 1609 { 1610 p = mb_prevptr(ccline.cmdbuff, p); 1611 if (c == Ctrl_W) 1612 { 1613 while (p > ccline.cmdbuff && vim_isspace(*p)) 1614 p = mb_prevptr(ccline.cmdbuff, p); 1615 i = mb_get_class(p); 1616 while (p > ccline.cmdbuff && mb_get_class(p) == i) 1617 p = mb_prevptr(ccline.cmdbuff, p); 1618 if (mb_get_class(p) != i) 1619 p += (*mb_ptr2len)(p); 1620 } 1621 } 1622 else if (c == Ctrl_W) 1623 { 1624 while (p > ccline.cmdbuff && vim_isspace(p[-1])) 1625 --p; 1626 i = vim_iswordc(p[-1]); 1627 while (p > ccline.cmdbuff && !vim_isspace(p[-1]) 1628 && vim_iswordc(p[-1]) == i) 1629 --p; 1630 } 1631 else 1632 --p; 1633 ccline.cmdpos = (int)(p - ccline.cmdbuff); 1634 ccline.cmdlen -= j - ccline.cmdpos; 1635 i = ccline.cmdpos; 1636 while (i < ccline.cmdlen) 1637 ccline.cmdbuff[i++] = ccline.cmdbuff[j++]; 1638 1639 /* Truncate at the end, required for multi-byte chars. */ 1640 ccline.cmdbuff[ccline.cmdlen] = NUL; 1641 #ifdef FEAT_SEARCH_EXTRA 1642 if (ccline.cmdlen == 0) 1643 { 1644 is_state.search_start = is_state.save_cursor; 1645 /* save view settings, so that the screen 1646 * won't be restored at the wrong position */ 1647 is_state.old_viewstate = is_state.init_viewstate; 1648 } 1649 #endif 1650 redrawcmd(); 1651 } 1652 else if (ccline.cmdlen == 0 && c != Ctrl_W 1653 && ccline.cmdprompt == NULL && indent == 0) 1654 { 1655 /* In ex and debug mode it doesn't make sense to return. */ 1656 if (exmode_active 1657 #ifdef FEAT_EVAL 1658 || ccline.cmdfirstc == '>' 1659 #endif 1660 ) 1661 goto cmdline_not_changed; 1662 1663 VIM_CLEAR(ccline.cmdbuff); /* no commandline to return */ 1664 if (!cmd_silent) 1665 { 1666 #ifdef FEAT_RIGHTLEFT 1667 if (cmdmsg_rl) 1668 msg_col = Columns; 1669 else 1670 #endif 1671 msg_col = 0; 1672 msg_putchar(' '); /* delete ':' */ 1673 } 1674 #ifdef FEAT_SEARCH_EXTRA 1675 if (ccline.cmdlen == 0) 1676 is_state.search_start = is_state.save_cursor; 1677 #endif 1678 redraw_cmdline = TRUE; 1679 goto returncmd; /* back to cmd mode */ 1680 } 1681 goto cmdline_changed; 1682 1683 case K_INS: 1684 case K_KINS: 1685 ccline.overstrike = !ccline.overstrike; 1686 #ifdef CURSOR_SHAPE 1687 ui_cursor_shape(); /* may show different cursor shape */ 1688 #endif 1689 goto cmdline_not_changed; 1690 1691 case Ctrl_HAT: 1692 if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) 1693 { 1694 /* ":lmap" mappings exists, toggle use of mappings. */ 1695 State ^= LANGMAP; 1696 #ifdef HAVE_INPUT_METHOD 1697 im_set_active(FALSE); /* Disable input method */ 1698 #endif 1699 if (b_im_ptr != NULL) 1700 { 1701 if (State & LANGMAP) 1702 *b_im_ptr = B_IMODE_LMAP; 1703 else 1704 *b_im_ptr = B_IMODE_NONE; 1705 } 1706 } 1707 #ifdef HAVE_INPUT_METHOD 1708 else 1709 { 1710 /* There are no ":lmap" mappings, toggle IM. When 1711 * 'imdisable' is set don't try getting the status, it's 1712 * always off. */ 1713 if ((p_imdisable && b_im_ptr != NULL) 1714 ? *b_im_ptr == B_IMODE_IM : im_get_status()) 1715 { 1716 im_set_active(FALSE); /* Disable input method */ 1717 if (b_im_ptr != NULL) 1718 *b_im_ptr = B_IMODE_NONE; 1719 } 1720 else 1721 { 1722 im_set_active(TRUE); /* Enable input method */ 1723 if (b_im_ptr != NULL) 1724 *b_im_ptr = B_IMODE_IM; 1725 } 1726 } 1727 #endif 1728 if (b_im_ptr != NULL) 1729 { 1730 if (b_im_ptr == &curbuf->b_p_iminsert) 1731 set_iminsert_global(); 1732 else 1733 set_imsearch_global(); 1734 } 1735 #ifdef CURSOR_SHAPE 1736 ui_cursor_shape(); /* may show different cursor shape */ 1737 #endif 1738 #if defined(FEAT_KEYMAP) 1739 /* Show/unshow value of 'keymap' in status lines later. */ 1740 status_redraw_curbuf(); 1741 #endif 1742 goto cmdline_not_changed; 1743 1744 /* case '@': only in very old vi */ 1745 case Ctrl_U: 1746 /* delete all characters left of the cursor */ 1747 j = ccline.cmdpos; 1748 ccline.cmdlen -= j; 1749 i = ccline.cmdpos = 0; 1750 while (i < ccline.cmdlen) 1751 ccline.cmdbuff[i++] = ccline.cmdbuff[j++]; 1752 /* Truncate at the end, required for multi-byte chars. */ 1753 ccline.cmdbuff[ccline.cmdlen] = NUL; 1754 #ifdef FEAT_SEARCH_EXTRA 1755 if (ccline.cmdlen == 0) 1756 is_state.search_start = is_state.save_cursor; 1757 #endif 1758 redrawcmd(); 1759 goto cmdline_changed; 1760 1761 #ifdef FEAT_CLIPBOARD 1762 case Ctrl_Y: 1763 /* Copy the modeless selection, if there is one. */ 1764 if (clip_star.state != SELECT_CLEARED) 1765 { 1766 if (clip_star.state == SELECT_DONE) 1767 clip_copy_modeless_selection(TRUE); 1768 goto cmdline_not_changed; 1769 } 1770 break; 1771 #endif 1772 1773 case ESC: /* get here if p_wc != ESC or when ESC typed twice */ 1774 case Ctrl_C: 1775 /* In exmode it doesn't make sense to return. Except when 1776 * ":normal" runs out of characters. */ 1777 if (exmode_active 1778 && (ex_normal_busy == 0 || typebuf.tb_len > 0)) 1779 goto cmdline_not_changed; 1780 1781 gotesc = TRUE; /* will free ccline.cmdbuff after 1782 putting it in history */ 1783 goto returncmd; /* back to cmd mode */ 1784 1785 case Ctrl_R: /* insert register */ 1786 #ifdef USE_ON_FLY_SCROLL 1787 dont_scroll = TRUE; /* disallow scrolling here */ 1788 #endif 1789 putcmdline('"', TRUE); 1790 ++no_mapping; 1791 i = c = plain_vgetc(); /* CTRL-R <char> */ 1792 if (i == Ctrl_O) 1793 i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */ 1794 if (i == Ctrl_R) 1795 c = plain_vgetc(); /* CTRL-R CTRL-R <char> */ 1796 extra_char = NUL; 1797 --no_mapping; 1798 #ifdef FEAT_EVAL 1799 /* 1800 * Insert the result of an expression. 1801 * Need to save the current command line, to be able to enter 1802 * a new one... 1803 */ 1804 new_cmdpos = -1; 1805 if (c == '=') 1806 { 1807 if (ccline.cmdfirstc == '=' // can't do this recursively 1808 || cmdline_star > 0) // or when typing a password 1809 { 1810 beep_flush(); 1811 c = ESC; 1812 } 1813 else 1814 c = get_expr_register(); 1815 } 1816 #endif 1817 if (c != ESC) /* use ESC to cancel inserting register */ 1818 { 1819 cmdline_paste(c, i == Ctrl_R, FALSE); 1820 1821 #ifdef FEAT_EVAL 1822 /* When there was a serious error abort getting the 1823 * command line. */ 1824 if (aborting()) 1825 { 1826 gotesc = TRUE; /* will free ccline.cmdbuff after 1827 putting it in history */ 1828 goto returncmd; /* back to cmd mode */ 1829 } 1830 #endif 1831 KeyTyped = FALSE; /* Don't do p_wc completion. */ 1832 #ifdef FEAT_EVAL 1833 if (new_cmdpos >= 0) 1834 { 1835 /* set_cmdline_pos() was used */ 1836 if (new_cmdpos > ccline.cmdlen) 1837 ccline.cmdpos = ccline.cmdlen; 1838 else 1839 ccline.cmdpos = new_cmdpos; 1840 } 1841 #endif 1842 } 1843 redrawcmd(); 1844 goto cmdline_changed; 1845 1846 case Ctrl_D: 1847 if (showmatches(&xpc, FALSE) == EXPAND_NOTHING) 1848 break; /* Use ^D as normal char instead */ 1849 1850 redrawcmd(); 1851 continue; /* don't do incremental search now */ 1852 1853 case K_RIGHT: 1854 case K_S_RIGHT: 1855 case K_C_RIGHT: 1856 do 1857 { 1858 if (ccline.cmdpos >= ccline.cmdlen) 1859 break; 1860 i = cmdline_charsize(ccline.cmdpos); 1861 if (KeyTyped && ccline.cmdspos + i >= Columns * Rows) 1862 break; 1863 ccline.cmdspos += i; 1864 if (has_mbyte) 1865 ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff 1866 + ccline.cmdpos); 1867 else 1868 ++ccline.cmdpos; 1869 } 1870 while ((c == K_S_RIGHT || c == K_C_RIGHT 1871 || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) 1872 && ccline.cmdbuff[ccline.cmdpos] != ' '); 1873 if (has_mbyte) 1874 set_cmdspos_cursor(); 1875 goto cmdline_not_changed; 1876 1877 case K_LEFT: 1878 case K_S_LEFT: 1879 case K_C_LEFT: 1880 if (ccline.cmdpos == 0) 1881 goto cmdline_not_changed; 1882 do 1883 { 1884 --ccline.cmdpos; 1885 if (has_mbyte) /* move to first byte of char */ 1886 ccline.cmdpos -= (*mb_head_off)(ccline.cmdbuff, 1887 ccline.cmdbuff + ccline.cmdpos); 1888 ccline.cmdspos -= cmdline_charsize(ccline.cmdpos); 1889 } 1890 while (ccline.cmdpos > 0 1891 && (c == K_S_LEFT || c == K_C_LEFT 1892 || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) 1893 && ccline.cmdbuff[ccline.cmdpos - 1] != ' '); 1894 if (has_mbyte) 1895 set_cmdspos_cursor(); 1896 goto cmdline_not_changed; 1897 1898 case K_IGNORE: 1899 /* Ignore mouse event or open_cmdwin() result. */ 1900 goto cmdline_not_changed; 1901 1902 #ifdef FEAT_GUI_MSWIN 1903 /* On MS-Windows ignore <M-F4>, we get it when closing the window 1904 * was cancelled. */ 1905 case K_F4: 1906 if (mod_mask == MOD_MASK_ALT) 1907 { 1908 redrawcmd(); /* somehow the cmdline is cleared */ 1909 goto cmdline_not_changed; 1910 } 1911 break; 1912 #endif 1913 1914 #ifdef FEAT_MOUSE 1915 case K_MIDDLEDRAG: 1916 case K_MIDDLERELEASE: 1917 goto cmdline_not_changed; /* Ignore mouse */ 1918 1919 case K_MIDDLEMOUSE: 1920 # ifdef FEAT_GUI 1921 /* When GUI is active, also paste when 'mouse' is empty */ 1922 if (!gui.in_use) 1923 # endif 1924 if (!mouse_has(MOUSE_COMMAND)) 1925 goto cmdline_not_changed; /* Ignore mouse */ 1926 # ifdef FEAT_CLIPBOARD 1927 if (clip_star.available) 1928 cmdline_paste('*', TRUE, TRUE); 1929 else 1930 # endif 1931 cmdline_paste(0, TRUE, TRUE); 1932 redrawcmd(); 1933 goto cmdline_changed; 1934 1935 # ifdef FEAT_DND 1936 case K_DROP: 1937 cmdline_paste('~', TRUE, FALSE); 1938 redrawcmd(); 1939 goto cmdline_changed; 1940 # endif 1941 1942 case K_LEFTDRAG: 1943 case K_LEFTRELEASE: 1944 case K_RIGHTDRAG: 1945 case K_RIGHTRELEASE: 1946 /* Ignore drag and release events when the button-down wasn't 1947 * seen before. */ 1948 if (ignore_drag_release) 1949 goto cmdline_not_changed; 1950 /* FALLTHROUGH */ 1951 case K_LEFTMOUSE: 1952 case K_RIGHTMOUSE: 1953 if (c == K_LEFTRELEASE || c == K_RIGHTRELEASE) 1954 ignore_drag_release = TRUE; 1955 else 1956 ignore_drag_release = FALSE; 1957 # ifdef FEAT_GUI 1958 /* When GUI is active, also move when 'mouse' is empty */ 1959 if (!gui.in_use) 1960 # endif 1961 if (!mouse_has(MOUSE_COMMAND)) 1962 goto cmdline_not_changed; /* Ignore mouse */ 1963 # ifdef FEAT_CLIPBOARD 1964 if (mouse_row < cmdline_row && clip_star.available) 1965 { 1966 int button, is_click, is_drag; 1967 1968 /* 1969 * Handle modeless selection. 1970 */ 1971 button = get_mouse_button(KEY2TERMCAP1(c), 1972 &is_click, &is_drag); 1973 if (mouse_model_popup() && button == MOUSE_LEFT 1974 && (mod_mask & MOD_MASK_SHIFT)) 1975 { 1976 /* Translate shift-left to right button. */ 1977 button = MOUSE_RIGHT; 1978 mod_mask &= ~MOD_MASK_SHIFT; 1979 } 1980 clip_modeless(button, is_click, is_drag); 1981 goto cmdline_not_changed; 1982 } 1983 # endif 1984 1985 set_cmdspos(); 1986 for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen; 1987 ++ccline.cmdpos) 1988 { 1989 i = cmdline_charsize(ccline.cmdpos); 1990 if (mouse_row <= cmdline_row + ccline.cmdspos / Columns 1991 && mouse_col < ccline.cmdspos % Columns + i) 1992 break; 1993 if (has_mbyte) 1994 { 1995 /* Count ">" for double-wide char that doesn't fit. */ 1996 correct_cmdspos(ccline.cmdpos, i); 1997 ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff 1998 + ccline.cmdpos) - 1; 1999 } 2000 ccline.cmdspos += i; 2001 } 2002 goto cmdline_not_changed; 2003 2004 /* Mouse scroll wheel: ignored here */ 2005 case K_MOUSEDOWN: 2006 case K_MOUSEUP: 2007 case K_MOUSELEFT: 2008 case K_MOUSERIGHT: 2009 /* Alternate buttons ignored here */ 2010 case K_X1MOUSE: 2011 case K_X1DRAG: 2012 case K_X1RELEASE: 2013 case K_X2MOUSE: 2014 case K_X2DRAG: 2015 case K_X2RELEASE: 2016 case K_MOUSEMOVE: 2017 goto cmdline_not_changed; 2018 2019 #endif /* FEAT_MOUSE */ 2020 2021 #ifdef FEAT_GUI 2022 case K_LEFTMOUSE_NM: /* mousefocus click, ignored */ 2023 case K_LEFTRELEASE_NM: 2024 goto cmdline_not_changed; 2025 2026 case K_VER_SCROLLBAR: 2027 if (msg_scrolled == 0) 2028 { 2029 gui_do_scroll(); 2030 redrawcmd(); 2031 } 2032 goto cmdline_not_changed; 2033 2034 case K_HOR_SCROLLBAR: 2035 if (msg_scrolled == 0) 2036 { 2037 gui_do_horiz_scroll(scrollbar_value, FALSE); 2038 redrawcmd(); 2039 } 2040 goto cmdline_not_changed; 2041 #endif 2042 #ifdef FEAT_GUI_TABLINE 2043 case K_TABLINE: 2044 case K_TABMENU: 2045 /* Don't want to change any tabs here. Make sure the same tab 2046 * is still selected. */ 2047 if (gui_use_tabline()) 2048 gui_mch_set_curtab(tabpage_index(curtab)); 2049 goto cmdline_not_changed; 2050 #endif 2051 2052 case K_SELECT: /* end of Select mode mapping - ignore */ 2053 goto cmdline_not_changed; 2054 2055 case Ctrl_B: /* begin of command line */ 2056 case K_HOME: 2057 case K_KHOME: 2058 case K_S_HOME: 2059 case K_C_HOME: 2060 ccline.cmdpos = 0; 2061 set_cmdspos(); 2062 goto cmdline_not_changed; 2063 2064 case Ctrl_E: /* end of command line */ 2065 case K_END: 2066 case K_KEND: 2067 case K_S_END: 2068 case K_C_END: 2069 ccline.cmdpos = ccline.cmdlen; 2070 set_cmdspos_cursor(); 2071 goto cmdline_not_changed; 2072 2073 case Ctrl_A: /* all matches */ 2074 if (nextwild(&xpc, WILD_ALL, 0, firstc != '@') == FAIL) 2075 break; 2076 goto cmdline_changed; 2077 2078 case Ctrl_L: 2079 #ifdef FEAT_SEARCH_EXTRA 2080 if (may_add_char_to_search(firstc, &c, &is_state) == OK) 2081 goto cmdline_not_changed; 2082 #endif 2083 2084 /* completion: longest common part */ 2085 if (nextwild(&xpc, WILD_LONGEST, 0, firstc != '@') == FAIL) 2086 break; 2087 goto cmdline_changed; 2088 2089 case Ctrl_N: /* next match */ 2090 case Ctrl_P: /* previous match */ 2091 if (xpc.xp_numfiles > 0) 2092 { 2093 if (nextwild(&xpc, (c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 2094 0, firstc != '@') == FAIL) 2095 break; 2096 goto cmdline_not_changed; 2097 } 2098 #ifdef FEAT_CMDHIST 2099 /* FALLTHROUGH */ 2100 case K_UP: 2101 case K_DOWN: 2102 case K_S_UP: 2103 case K_S_DOWN: 2104 case K_PAGEUP: 2105 case K_KPAGEUP: 2106 case K_PAGEDOWN: 2107 case K_KPAGEDOWN: 2108 if (hislen == 0 || firstc == NUL) /* no history */ 2109 goto cmdline_not_changed; 2110 2111 i = hiscnt; 2112 2113 /* save current command string so it can be restored later */ 2114 if (lookfor == NULL) 2115 { 2116 if ((lookfor = vim_strsave(ccline.cmdbuff)) == NULL) 2117 goto cmdline_not_changed; 2118 lookfor[ccline.cmdpos] = NUL; 2119 } 2120 2121 j = (int)STRLEN(lookfor); 2122 for (;;) 2123 { 2124 /* one step backwards */ 2125 if (c == K_UP|| c == K_S_UP || c == Ctrl_P 2126 || c == K_PAGEUP || c == K_KPAGEUP) 2127 { 2128 if (hiscnt == hislen) /* first time */ 2129 hiscnt = hisidx[histype]; 2130 else if (hiscnt == 0 && hisidx[histype] != hislen - 1) 2131 hiscnt = hislen - 1; 2132 else if (hiscnt != hisidx[histype] + 1) 2133 --hiscnt; 2134 else /* at top of list */ 2135 { 2136 hiscnt = i; 2137 break; 2138 } 2139 } 2140 else /* one step forwards */ 2141 { 2142 /* on last entry, clear the line */ 2143 if (hiscnt == hisidx[histype]) 2144 { 2145 hiscnt = hislen; 2146 break; 2147 } 2148 2149 /* not on a history line, nothing to do */ 2150 if (hiscnt == hislen) 2151 break; 2152 if (hiscnt == hislen - 1) /* wrap around */ 2153 hiscnt = 0; 2154 else 2155 ++hiscnt; 2156 } 2157 if (hiscnt < 0 || history[histype][hiscnt].hisstr == NULL) 2158 { 2159 hiscnt = i; 2160 break; 2161 } 2162 if ((c != K_UP && c != K_DOWN) 2163 || hiscnt == i 2164 || STRNCMP(history[histype][hiscnt].hisstr, 2165 lookfor, (size_t)j) == 0) 2166 break; 2167 } 2168 2169 if (hiscnt != i) /* jumped to other entry */ 2170 { 2171 char_u *p; 2172 int len; 2173 int old_firstc; 2174 2175 VIM_CLEAR(ccline.cmdbuff); 2176 xpc.xp_context = EXPAND_NOTHING; 2177 if (hiscnt == hislen) 2178 p = lookfor; /* back to the old one */ 2179 else 2180 p = history[histype][hiscnt].hisstr; 2181 2182 if (histype == HIST_SEARCH 2183 && p != lookfor 2184 && (old_firstc = p[STRLEN(p) + 1]) != firstc) 2185 { 2186 /* Correct for the separator character used when 2187 * adding the history entry vs the one used now. 2188 * First loop: count length. 2189 * Second loop: copy the characters. */ 2190 for (i = 0; i <= 1; ++i) 2191 { 2192 len = 0; 2193 for (j = 0; p[j] != NUL; ++j) 2194 { 2195 /* Replace old sep with new sep, unless it is 2196 * escaped. */ 2197 if (p[j] == old_firstc 2198 && (j == 0 || p[j - 1] != '\\')) 2199 { 2200 if (i > 0) 2201 ccline.cmdbuff[len] = firstc; 2202 } 2203 else 2204 { 2205 /* Escape new sep, unless it is already 2206 * escaped. */ 2207 if (p[j] == firstc 2208 && (j == 0 || p[j - 1] != '\\')) 2209 { 2210 if (i > 0) 2211 ccline.cmdbuff[len] = '\\'; 2212 ++len; 2213 } 2214 if (i > 0) 2215 ccline.cmdbuff[len] = p[j]; 2216 } 2217 ++len; 2218 } 2219 if (i == 0) 2220 { 2221 alloc_cmdbuff(len); 2222 if (ccline.cmdbuff == NULL) 2223 goto returncmd; 2224 } 2225 } 2226 ccline.cmdbuff[len] = NUL; 2227 } 2228 else 2229 { 2230 alloc_cmdbuff((int)STRLEN(p)); 2231 if (ccline.cmdbuff == NULL) 2232 goto returncmd; 2233 STRCPY(ccline.cmdbuff, p); 2234 } 2235 2236 ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); 2237 redrawcmd(); 2238 goto cmdline_changed; 2239 } 2240 beep_flush(); 2241 #endif 2242 goto cmdline_not_changed; 2243 2244 #ifdef FEAT_SEARCH_EXTRA 2245 case Ctrl_G: /* next match */ 2246 case Ctrl_T: /* previous match */ 2247 if (may_adjust_incsearch_highlighting( 2248 firstc, count, &is_state, c) == FAIL) 2249 goto cmdline_not_changed; 2250 break; 2251 #endif 2252 2253 case Ctrl_V: 2254 case Ctrl_Q: 2255 #ifdef FEAT_MOUSE 2256 ignore_drag_release = TRUE; 2257 #endif 2258 putcmdline('^', TRUE); 2259 c = get_literal(); /* get next (two) character(s) */ 2260 do_abbr = FALSE; /* don't do abbreviation now */ 2261 extra_char = NUL; 2262 /* may need to remove ^ when composing char was typed */ 2263 if (enc_utf8 && utf_iscomposing(c) && !cmd_silent) 2264 { 2265 draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); 2266 msg_putchar(' '); 2267 cursorcmd(); 2268 } 2269 break; 2270 2271 #ifdef FEAT_DIGRAPHS 2272 case Ctrl_K: 2273 #ifdef FEAT_MOUSE 2274 ignore_drag_release = TRUE; 2275 #endif 2276 putcmdline('?', TRUE); 2277 #ifdef USE_ON_FLY_SCROLL 2278 dont_scroll = TRUE; /* disallow scrolling here */ 2279 #endif 2280 c = get_digraph(TRUE); 2281 extra_char = NUL; 2282 if (c != NUL) 2283 break; 2284 2285 redrawcmd(); 2286 goto cmdline_not_changed; 2287 #endif /* FEAT_DIGRAPHS */ 2288 2289 #ifdef FEAT_RIGHTLEFT 2290 case Ctrl__: /* CTRL-_: switch language mode */ 2291 if (!p_ari) 2292 break; 2293 cmd_hkmap = !cmd_hkmap; 2294 goto cmdline_not_changed; 2295 #endif 2296 2297 case K_PS: 2298 bracketed_paste(PASTE_CMDLINE, FALSE, NULL); 2299 goto cmdline_changed; 2300 2301 default: 2302 #ifdef UNIX 2303 if (c == intr_char) 2304 { 2305 gotesc = TRUE; /* will free ccline.cmdbuff after 2306 putting it in history */ 2307 goto returncmd; /* back to Normal mode */ 2308 } 2309 #endif 2310 /* 2311 * Normal character with no special meaning. Just set mod_mask 2312 * to 0x0 so that typing Shift-Space in the GUI doesn't enter 2313 * the string <S-Space>. This should only happen after ^V. 2314 */ 2315 if (!IS_SPECIAL(c)) 2316 mod_mask = 0x0; 2317 break; 2318 } 2319 /* 2320 * End of switch on command line character. 2321 * We come here if we have a normal character. 2322 */ 2323 2324 if (do_abbr && (IS_SPECIAL(c) || !vim_iswordc(c)) 2325 && (ccheck_abbr( 2326 // Add ABBR_OFF for characters above 0x100, this is 2327 // what check_abbr() expects. 2328 (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : c) 2329 || c == Ctrl_RSB)) 2330 goto cmdline_changed; 2331 2332 /* 2333 * put the character in the command line 2334 */ 2335 if (IS_SPECIAL(c) || mod_mask != 0) 2336 put_on_cmdline(get_special_key_name(c, mod_mask), -1, TRUE); 2337 else 2338 { 2339 if (has_mbyte) 2340 { 2341 j = (*mb_char2bytes)(c, IObuff); 2342 IObuff[j] = NUL; /* exclude composing chars */ 2343 put_on_cmdline(IObuff, j, TRUE); 2344 } 2345 else 2346 { 2347 IObuff[0] = c; 2348 put_on_cmdline(IObuff, 1, TRUE); 2349 } 2350 } 2351 goto cmdline_changed; 2352 2353 /* 2354 * This part implements incremental searches for "/" and "?" 2355 * Jump to cmdline_not_changed when a character has been read but the command 2356 * line did not change. Then we only search and redraw if something changed in 2357 * the past. 2358 * Jump to cmdline_changed when the command line did change. 2359 * (Sorry for the goto's, I know it is ugly). 2360 */ 2361 cmdline_not_changed: 2362 #ifdef FEAT_SEARCH_EXTRA 2363 if (!is_state.incsearch_postponed) 2364 continue; 2365 #endif 2366 2367 cmdline_changed: 2368 /* Trigger CmdlineChanged autocommands. */ 2369 trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED); 2370 2371 #ifdef FEAT_SEARCH_EXTRA 2372 may_do_incsearch_highlighting(firstc, count, &is_state); 2373 #endif 2374 2375 #ifdef FEAT_RIGHTLEFT 2376 if (cmdmsg_rl 2377 # ifdef FEAT_ARABIC 2378 || (p_arshape && !p_tbidi && enc_utf8) 2379 # endif 2380 ) 2381 /* Always redraw the whole command line to fix shaping and 2382 * right-left typing. Not efficient, but it works. 2383 * Do it only when there are no characters left to read 2384 * to avoid useless intermediate redraws. */ 2385 if (vpeekc() == NUL) 2386 redrawcmd(); 2387 #endif 2388 } 2389 2390 returncmd: 2391 2392 #ifdef FEAT_RIGHTLEFT 2393 cmdmsg_rl = FALSE; 2394 #endif 2395 2396 ExpandCleanup(&xpc); 2397 ccline.xpc = NULL; 2398 2399 #ifdef FEAT_SEARCH_EXTRA 2400 finish_incsearch_highlighting(gotesc, &is_state, FALSE); 2401 #endif 2402 2403 if (ccline.cmdbuff != NULL) 2404 { 2405 /* 2406 * Put line in history buffer (":" and "=" only when it was typed). 2407 */ 2408 #ifdef FEAT_CMDHIST 2409 if (ccline.cmdlen && firstc != NUL 2410 && (some_key_typed || histype == HIST_SEARCH)) 2411 { 2412 add_to_history(histype, ccline.cmdbuff, TRUE, 2413 histype == HIST_SEARCH ? firstc : NUL); 2414 if (firstc == ':') 2415 { 2416 vim_free(new_last_cmdline); 2417 new_last_cmdline = vim_strsave(ccline.cmdbuff); 2418 } 2419 } 2420 #endif 2421 2422 if (gotesc) 2423 abandon_cmdline(); 2424 } 2425 2426 /* 2427 * If the screen was shifted up, redraw the whole screen (later). 2428 * If the line is too long, clear it, so ruler and shown command do 2429 * not get printed in the middle of it. 2430 */ 2431 msg_check(); 2432 msg_scroll = save_msg_scroll; 2433 redir_off = FALSE; 2434 2435 /* When the command line was typed, no need for a wait-return prompt. */ 2436 if (some_key_typed) 2437 need_wait_return = FALSE; 2438 2439 /* Trigger CmdlineLeave autocommands. */ 2440 trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINELEAVE); 2441 2442 State = save_State; 2443 #ifdef HAVE_INPUT_METHOD 2444 if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP) 2445 im_save_status(b_im_ptr); 2446 im_set_active(FALSE); 2447 #endif 2448 #ifdef FEAT_MOUSE 2449 setmouse(); 2450 #endif 2451 #ifdef CURSOR_SHAPE 2452 ui_cursor_shape(); /* may show different cursor shape */ 2453 #endif 2454 sb_text_end_cmdline(); 2455 2456 theend: 2457 { 2458 char_u *p = ccline.cmdbuff; 2459 2460 if (did_save_ccline) 2461 restore_cmdline(&save_ccline); 2462 else 2463 ccline.cmdbuff = NULL; 2464 return p; 2465 } 2466 } 2467 2468 #if (defined(FEAT_CRYPT) || defined(FEAT_EVAL)) || defined(PROTO) 2469 /* 2470 * Get a command line with a prompt. 2471 * This is prepared to be called recursively from getcmdline() (e.g. by 2472 * f_input() when evaluating an expression from CTRL-R =). 2473 * Returns the command line in allocated memory, or NULL. 2474 */ 2475 char_u * 2476 getcmdline_prompt( 2477 int firstc, 2478 char_u *prompt, /* command line prompt */ 2479 int attr, /* attributes for prompt */ 2480 int xp_context, /* type of expansion */ 2481 char_u *xp_arg) /* user-defined expansion argument */ 2482 { 2483 char_u *s; 2484 struct cmdline_info save_ccline; 2485 int did_save_ccline = FALSE; 2486 int msg_col_save = msg_col; 2487 int msg_silent_save = msg_silent; 2488 2489 if (ccline.cmdbuff != NULL) 2490 { 2491 // Save the values of the current cmdline and restore them below. 2492 save_cmdline(&save_ccline); 2493 did_save_ccline = TRUE; 2494 } 2495 2496 vim_memset(&ccline, 0, sizeof(struct cmdline_info)); 2497 ccline.cmdprompt = prompt; 2498 ccline.cmdattr = attr; 2499 # ifdef FEAT_EVAL 2500 ccline.xp_context = xp_context; 2501 ccline.xp_arg = xp_arg; 2502 ccline.input_fn = (firstc == '@'); 2503 # endif 2504 msg_silent = 0; 2505 s = getcmdline_int(firstc, 1L, 0, FALSE); 2506 2507 if (did_save_ccline) 2508 restore_cmdline(&save_ccline); 2509 2510 msg_silent = msg_silent_save; 2511 /* Restore msg_col, the prompt from input() may have changed it. 2512 * But only if called recursively and the commandline is therefore being 2513 * restored to an old one; if not, the input() prompt stays on the screen, 2514 * so we need its modified msg_col left intact. */ 2515 if (ccline.cmdbuff != NULL) 2516 msg_col = msg_col_save; 2517 2518 return s; 2519 } 2520 #endif 2521 2522 /* 2523 * Return TRUE when the text must not be changed and we can't switch to 2524 * another window or buffer. Used when editing the command line, evaluating 2525 * 'balloonexpr', etc. 2526 */ 2527 int 2528 text_locked(void) 2529 { 2530 #ifdef FEAT_CMDWIN 2531 if (cmdwin_type != 0) 2532 return TRUE; 2533 #endif 2534 return textlock != 0; 2535 } 2536 2537 /* 2538 * Give an error message for a command that isn't allowed while the cmdline 2539 * window is open or editing the cmdline in another way. 2540 */ 2541 void 2542 text_locked_msg(void) 2543 { 2544 emsg(_(get_text_locked_msg())); 2545 } 2546 2547 char * 2548 get_text_locked_msg(void) 2549 { 2550 #ifdef FEAT_CMDWIN 2551 if (cmdwin_type != 0) 2552 return e_cmdwin; 2553 #endif 2554 return e_secure; 2555 } 2556 2557 /* 2558 * Check if "curbuf_lock" or "allbuf_lock" is set and return TRUE when it is 2559 * and give an error message. 2560 */ 2561 int 2562 curbuf_locked(void) 2563 { 2564 if (curbuf_lock > 0) 2565 { 2566 emsg(_("E788: Not allowed to edit another buffer now")); 2567 return TRUE; 2568 } 2569 return allbuf_locked(); 2570 } 2571 2572 /* 2573 * Check if "allbuf_lock" is set and return TRUE when it is and give an error 2574 * message. 2575 */ 2576 int 2577 allbuf_locked(void) 2578 { 2579 if (allbuf_lock > 0) 2580 { 2581 emsg(_("E811: Not allowed to change buffer information now")); 2582 return TRUE; 2583 } 2584 return FALSE; 2585 } 2586 2587 static int 2588 cmdline_charsize(int idx) 2589 { 2590 #if defined(FEAT_CRYPT) || defined(FEAT_EVAL) 2591 if (cmdline_star > 0) /* showing '*', always 1 position */ 2592 return 1; 2593 #endif 2594 return ptr2cells(ccline.cmdbuff + idx); 2595 } 2596 2597 /* 2598 * Compute the offset of the cursor on the command line for the prompt and 2599 * indent. 2600 */ 2601 static void 2602 set_cmdspos(void) 2603 { 2604 if (ccline.cmdfirstc != NUL) 2605 ccline.cmdspos = 1 + ccline.cmdindent; 2606 else 2607 ccline.cmdspos = 0 + ccline.cmdindent; 2608 } 2609 2610 /* 2611 * Compute the screen position for the cursor on the command line. 2612 */ 2613 static void 2614 set_cmdspos_cursor(void) 2615 { 2616 int i, m, c; 2617 2618 set_cmdspos(); 2619 if (KeyTyped) 2620 { 2621 m = Columns * Rows; 2622 if (m < 0) /* overflow, Columns or Rows at weird value */ 2623 m = MAXCOL; 2624 } 2625 else 2626 m = MAXCOL; 2627 for (i = 0; i < ccline.cmdlen && i < ccline.cmdpos; ++i) 2628 { 2629 c = cmdline_charsize(i); 2630 /* Count ">" for double-wide multi-byte char that doesn't fit. */ 2631 if (has_mbyte) 2632 correct_cmdspos(i, c); 2633 /* If the cmdline doesn't fit, show cursor on last visible char. 2634 * Don't move the cursor itself, so we can still append. */ 2635 if ((ccline.cmdspos += c) >= m) 2636 { 2637 ccline.cmdspos -= c; 2638 break; 2639 } 2640 if (has_mbyte) 2641 i += (*mb_ptr2len)(ccline.cmdbuff + i) - 1; 2642 } 2643 } 2644 2645 /* 2646 * Check if the character at "idx", which is "cells" wide, is a multi-byte 2647 * character that doesn't fit, so that a ">" must be displayed. 2648 */ 2649 static void 2650 correct_cmdspos(int idx, int cells) 2651 { 2652 if ((*mb_ptr2len)(ccline.cmdbuff + idx) > 1 2653 && (*mb_ptr2cells)(ccline.cmdbuff + idx) > 1 2654 && ccline.cmdspos % Columns + cells > Columns) 2655 ccline.cmdspos++; 2656 } 2657 2658 /* 2659 * Get an Ex command line for the ":" command. 2660 */ 2661 char_u * 2662 getexline( 2663 int c, /* normally ':', NUL for ":append" */ 2664 void *cookie UNUSED, 2665 int indent) /* indent for inside conditionals */ 2666 { 2667 /* When executing a register, remove ':' that's in front of each line. */ 2668 if (exec_from_reg && vpeekc() == ':') 2669 (void)vgetc(); 2670 return getcmdline(c, 1L, indent); 2671 } 2672 2673 /* 2674 * Get an Ex command line for Ex mode. 2675 * In Ex mode we only use the OS supplied line editing features and no 2676 * mappings or abbreviations. 2677 * Returns a string in allocated memory or NULL. 2678 */ 2679 char_u * 2680 getexmodeline( 2681 int promptc, /* normally ':', NUL for ":append" and '?' for 2682 :s prompt */ 2683 void *cookie UNUSED, 2684 int indent) /* indent for inside conditionals */ 2685 { 2686 garray_T line_ga; 2687 char_u *pend; 2688 int startcol = 0; 2689 int c1 = 0; 2690 int escaped = FALSE; /* CTRL-V typed */ 2691 int vcol = 0; 2692 char_u *p; 2693 int prev_char; 2694 int len; 2695 2696 /* Switch cursor on now. This avoids that it happens after the "\n", which 2697 * confuses the system function that computes tabstops. */ 2698 cursor_on(); 2699 2700 /* always start in column 0; write a newline if necessary */ 2701 compute_cmdrow(); 2702 if ((msg_col || msg_didout) && promptc != '?') 2703 msg_putchar('\n'); 2704 if (promptc == ':') 2705 { 2706 /* indent that is only displayed, not in the line itself */ 2707 if (p_prompt) 2708 msg_putchar(':'); 2709 while (indent-- > 0) 2710 msg_putchar(' '); 2711 startcol = msg_col; 2712 } 2713 2714 ga_init2(&line_ga, 1, 30); 2715 2716 /* autoindent for :insert and :append is in the line itself */ 2717 if (promptc <= 0) 2718 { 2719 vcol = indent; 2720 while (indent >= 8) 2721 { 2722 ga_append(&line_ga, TAB); 2723 msg_puts(" "); 2724 indent -= 8; 2725 } 2726 while (indent-- > 0) 2727 { 2728 ga_append(&line_ga, ' '); 2729 msg_putchar(' '); 2730 } 2731 } 2732 ++no_mapping; 2733 ++allow_keys; 2734 2735 /* 2736 * Get the line, one character at a time. 2737 */ 2738 got_int = FALSE; 2739 while (!got_int) 2740 { 2741 long sw; 2742 char_u *s; 2743 2744 if (ga_grow(&line_ga, 40) == FAIL) 2745 break; 2746 2747 /* 2748 * Get one character at a time. 2749 */ 2750 prev_char = c1; 2751 2752 /* Check for a ":normal" command and no more characters left. */ 2753 if (ex_normal_busy > 0 && typebuf.tb_len == 0) 2754 c1 = '\n'; 2755 else 2756 c1 = vgetc(); 2757 2758 /* 2759 * Handle line editing. 2760 * Previously this was left to the system, putting the terminal in 2761 * cooked mode, but then CTRL-D and CTRL-T can't be used properly. 2762 */ 2763 if (got_int) 2764 { 2765 msg_putchar('\n'); 2766 break; 2767 } 2768 2769 if (c1 == K_PS) 2770 { 2771 bracketed_paste(PASTE_EX, FALSE, &line_ga); 2772 goto redraw; 2773 } 2774 2775 if (!escaped) 2776 { 2777 /* CR typed means "enter", which is NL */ 2778 if (c1 == '\r') 2779 c1 = '\n'; 2780 2781 if (c1 == BS || c1 == K_BS 2782 || c1 == DEL || c1 == K_DEL || c1 == K_KDEL) 2783 { 2784 if (line_ga.ga_len > 0) 2785 { 2786 if (has_mbyte) 2787 { 2788 p = (char_u *)line_ga.ga_data; 2789 p[line_ga.ga_len] = NUL; 2790 len = (*mb_head_off)(p, p + line_ga.ga_len - 1) + 1; 2791 line_ga.ga_len -= len; 2792 } 2793 else 2794 --line_ga.ga_len; 2795 goto redraw; 2796 } 2797 continue; 2798 } 2799 2800 if (c1 == Ctrl_U) 2801 { 2802 msg_col = startcol; 2803 msg_clr_eos(); 2804 line_ga.ga_len = 0; 2805 goto redraw; 2806 } 2807 2808 if (c1 == Ctrl_T) 2809 { 2810 sw = get_sw_value(curbuf); 2811 p = (char_u *)line_ga.ga_data; 2812 p[line_ga.ga_len] = NUL; 2813 indent = get_indent_str(p, 8, FALSE); 2814 indent += sw - indent % sw; 2815 add_indent: 2816 while (get_indent_str(p, 8, FALSE) < indent) 2817 { 2818 (void)ga_grow(&line_ga, 2); /* one more for the NUL */ 2819 p = (char_u *)line_ga.ga_data; 2820 s = skipwhite(p); 2821 mch_memmove(s + 1, s, line_ga.ga_len - (s - p) + 1); 2822 *s = ' '; 2823 ++line_ga.ga_len; 2824 } 2825 redraw: 2826 /* redraw the line */ 2827 msg_col = startcol; 2828 vcol = 0; 2829 p = (char_u *)line_ga.ga_data; 2830 p[line_ga.ga_len] = NUL; 2831 while (p < (char_u *)line_ga.ga_data + line_ga.ga_len) 2832 { 2833 if (*p == TAB) 2834 { 2835 do 2836 { 2837 msg_putchar(' '); 2838 } while (++vcol % 8); 2839 ++p; 2840 } 2841 else 2842 { 2843 len = MB_PTR2LEN(p); 2844 msg_outtrans_len(p, len); 2845 vcol += ptr2cells(p); 2846 p += len; 2847 } 2848 } 2849 msg_clr_eos(); 2850 windgoto(msg_row, msg_col); 2851 continue; 2852 } 2853 2854 if (c1 == Ctrl_D) 2855 { 2856 /* Delete one shiftwidth. */ 2857 p = (char_u *)line_ga.ga_data; 2858 if (prev_char == '0' || prev_char == '^') 2859 { 2860 if (prev_char == '^') 2861 ex_keep_indent = TRUE; 2862 indent = 0; 2863 p[--line_ga.ga_len] = NUL; 2864 } 2865 else 2866 { 2867 p[line_ga.ga_len] = NUL; 2868 indent = get_indent_str(p, 8, FALSE); 2869 if (indent > 0) 2870 { 2871 --indent; 2872 indent -= indent % get_sw_value(curbuf); 2873 } 2874 } 2875 while (get_indent_str(p, 8, FALSE) > indent) 2876 { 2877 s = skipwhite(p); 2878 mch_memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); 2879 --line_ga.ga_len; 2880 } 2881 goto add_indent; 2882 } 2883 2884 if (c1 == Ctrl_V || c1 == Ctrl_Q) 2885 { 2886 escaped = TRUE; 2887 continue; 2888 } 2889 2890 /* Ignore special key codes: mouse movement, K_IGNORE, etc. */ 2891 if (IS_SPECIAL(c1)) 2892 continue; 2893 } 2894 2895 if (IS_SPECIAL(c1)) 2896 c1 = '?'; 2897 if (has_mbyte) 2898 len = (*mb_char2bytes)(c1, 2899 (char_u *)line_ga.ga_data + line_ga.ga_len); 2900 else 2901 { 2902 len = 1; 2903 ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1; 2904 } 2905 if (c1 == '\n') 2906 msg_putchar('\n'); 2907 else if (c1 == TAB) 2908 { 2909 /* Don't use chartabsize(), 'ts' can be different */ 2910 do 2911 { 2912 msg_putchar(' '); 2913 } while (++vcol % 8); 2914 } 2915 else 2916 { 2917 msg_outtrans_len( 2918 ((char_u *)line_ga.ga_data) + line_ga.ga_len, len); 2919 vcol += char2cells(c1); 2920 } 2921 line_ga.ga_len += len; 2922 escaped = FALSE; 2923 2924 windgoto(msg_row, msg_col); 2925 pend = (char_u *)(line_ga.ga_data) + line_ga.ga_len; 2926 2927 /* We are done when a NL is entered, but not when it comes after an 2928 * odd number of backslashes, that results in a NUL. */ 2929 if (line_ga.ga_len > 0 && pend[-1] == '\n') 2930 { 2931 int bcount = 0; 2932 2933 while (line_ga.ga_len - 2 >= bcount && pend[-2 - bcount] == '\\') 2934 ++bcount; 2935 2936 if (bcount > 0) 2937 { 2938 /* Halve the number of backslashes: "\NL" -> "NUL", "\\NL" -> 2939 * "\NL", etc. */ 2940 line_ga.ga_len -= (bcount + 1) / 2; 2941 pend -= (bcount + 1) / 2; 2942 pend[-1] = '\n'; 2943 } 2944 2945 if ((bcount & 1) == 0) 2946 { 2947 --line_ga.ga_len; 2948 --pend; 2949 *pend = NUL; 2950 break; 2951 } 2952 } 2953 } 2954 2955 --no_mapping; 2956 --allow_keys; 2957 2958 /* make following messages go to the next line */ 2959 msg_didout = FALSE; 2960 msg_col = 0; 2961 if (msg_row < Rows - 1) 2962 ++msg_row; 2963 emsg_on_display = FALSE; /* don't want ui_delay() */ 2964 2965 if (got_int) 2966 ga_clear(&line_ga); 2967 2968 return (char_u *)line_ga.ga_data; 2969 } 2970 2971 # if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \ 2972 || defined(FEAT_MOUSESHAPE) || defined(PROTO) 2973 /* 2974 * Return TRUE if ccline.overstrike is on. 2975 */ 2976 int 2977 cmdline_overstrike(void) 2978 { 2979 return ccline.overstrike; 2980 } 2981 2982 /* 2983 * Return TRUE if the cursor is at the end of the cmdline. 2984 */ 2985 int 2986 cmdline_at_end(void) 2987 { 2988 return (ccline.cmdpos >= ccline.cmdlen); 2989 } 2990 #endif 2991 2992 #if (defined(FEAT_XIM) && (defined(FEAT_GUI_GTK))) || defined(PROTO) 2993 /* 2994 * Return the virtual column number at the current cursor position. 2995 * This is used by the IM code to obtain the start of the preedit string. 2996 */ 2997 colnr_T 2998 cmdline_getvcol_cursor(void) 2999 { 3000 if (ccline.cmdbuff == NULL || ccline.cmdpos > ccline.cmdlen) 3001 return MAXCOL; 3002 3003 if (has_mbyte) 3004 { 3005 colnr_T col; 3006 int i = 0; 3007 3008 for (col = 0; i < ccline.cmdpos; ++col) 3009 i += (*mb_ptr2len)(ccline.cmdbuff + i); 3010 3011 return col; 3012 } 3013 else 3014 return ccline.cmdpos; 3015 } 3016 #endif 3017 3018 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 3019 /* 3020 * If part of the command line is an IM preedit string, redraw it with 3021 * IM feedback attributes. The cursor position is restored after drawing. 3022 */ 3023 static void 3024 redrawcmd_preedit(void) 3025 { 3026 if ((State & CMDLINE) 3027 && xic != NULL 3028 /* && im_get_status() doesn't work when using SCIM */ 3029 && !p_imdisable 3030 && im_is_preediting()) 3031 { 3032 int cmdpos = 0; 3033 int cmdspos; 3034 int old_row; 3035 int old_col; 3036 colnr_T col; 3037 3038 old_row = msg_row; 3039 old_col = msg_col; 3040 cmdspos = ((ccline.cmdfirstc != NUL) ? 1 : 0) + ccline.cmdindent; 3041 3042 if (has_mbyte) 3043 { 3044 for (col = 0; col < preedit_start_col 3045 && cmdpos < ccline.cmdlen; ++col) 3046 { 3047 cmdspos += (*mb_ptr2cells)(ccline.cmdbuff + cmdpos); 3048 cmdpos += (*mb_ptr2len)(ccline.cmdbuff + cmdpos); 3049 } 3050 } 3051 else 3052 { 3053 cmdspos += preedit_start_col; 3054 cmdpos += preedit_start_col; 3055 } 3056 3057 msg_row = cmdline_row + (cmdspos / (int)Columns); 3058 msg_col = cmdspos % (int)Columns; 3059 if (msg_row >= Rows) 3060 msg_row = Rows - 1; 3061 3062 for (col = 0; cmdpos < ccline.cmdlen; ++col) 3063 { 3064 int char_len; 3065 int char_attr; 3066 3067 char_attr = im_get_feedback_attr(col); 3068 if (char_attr < 0) 3069 break; /* end of preedit string */ 3070 3071 if (has_mbyte) 3072 char_len = (*mb_ptr2len)(ccline.cmdbuff + cmdpos); 3073 else 3074 char_len = 1; 3075 3076 msg_outtrans_len_attr(ccline.cmdbuff + cmdpos, char_len, char_attr); 3077 cmdpos += char_len; 3078 } 3079 3080 msg_row = old_row; 3081 msg_col = old_col; 3082 } 3083 } 3084 #endif /* FEAT_XIM && FEAT_GUI_GTK */ 3085 3086 /* 3087 * Allocate a new command line buffer. 3088 * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. 3089 */ 3090 static void 3091 alloc_cmdbuff(int len) 3092 { 3093 /* 3094 * give some extra space to avoid having to allocate all the time 3095 */ 3096 if (len < 80) 3097 len = 100; 3098 else 3099 len += 20; 3100 3101 ccline.cmdbuff = alloc(len); /* caller should check for out-of-memory */ 3102 ccline.cmdbufflen = len; 3103 } 3104 3105 /* 3106 * Re-allocate the command line to length len + something extra. 3107 * return FAIL for failure, OK otherwise 3108 */ 3109 static int 3110 realloc_cmdbuff(int len) 3111 { 3112 char_u *p; 3113 3114 if (len < ccline.cmdbufflen) 3115 return OK; /* no need to resize */ 3116 3117 p = ccline.cmdbuff; 3118 alloc_cmdbuff(len); /* will get some more */ 3119 if (ccline.cmdbuff == NULL) /* out of memory */ 3120 { 3121 ccline.cmdbuff = p; /* keep the old one */ 3122 return FAIL; 3123 } 3124 /* There isn't always a NUL after the command, but it may need to be 3125 * there, thus copy up to the NUL and add a NUL. */ 3126 mch_memmove(ccline.cmdbuff, p, (size_t)ccline.cmdlen); 3127 ccline.cmdbuff[ccline.cmdlen] = NUL; 3128 vim_free(p); 3129 3130 if (ccline.xpc != NULL 3131 && ccline.xpc->xp_pattern != NULL 3132 && ccline.xpc->xp_context != EXPAND_NOTHING 3133 && ccline.xpc->xp_context != EXPAND_UNSUCCESSFUL) 3134 { 3135 int i = (int)(ccline.xpc->xp_pattern - p); 3136 3137 /* If xp_pattern points inside the old cmdbuff it needs to be adjusted 3138 * to point into the newly allocated memory. */ 3139 if (i >= 0 && i <= ccline.cmdlen) 3140 ccline.xpc->xp_pattern = ccline.cmdbuff + i; 3141 } 3142 3143 return OK; 3144 } 3145 3146 #if defined(FEAT_ARABIC) || defined(PROTO) 3147 static char_u *arshape_buf = NULL; 3148 3149 # if defined(EXITFREE) || defined(PROTO) 3150 void 3151 free_cmdline_buf(void) 3152 { 3153 vim_free(arshape_buf); 3154 } 3155 # endif 3156 #endif 3157 3158 /* 3159 * Draw part of the cmdline at the current cursor position. But draw stars 3160 * when cmdline_star is TRUE. 3161 */ 3162 static void 3163 draw_cmdline(int start, int len) 3164 { 3165 #if defined(FEAT_CRYPT) || defined(FEAT_EVAL) 3166 int i; 3167 3168 if (cmdline_star > 0) 3169 for (i = 0; i < len; ++i) 3170 { 3171 msg_putchar('*'); 3172 if (has_mbyte) 3173 i += (*mb_ptr2len)(ccline.cmdbuff + start + i) - 1; 3174 } 3175 else 3176 #endif 3177 #ifdef FEAT_ARABIC 3178 if (p_arshape && !p_tbidi && enc_utf8 && len > 0) 3179 { 3180 static int buflen = 0; 3181 char_u *p; 3182 int j; 3183 int newlen = 0; 3184 int mb_l; 3185 int pc, pc1 = 0; 3186 int prev_c = 0; 3187 int prev_c1 = 0; 3188 int u8c; 3189 int u8cc[MAX_MCO]; 3190 int nc = 0; 3191 3192 /* 3193 * Do arabic shaping into a temporary buffer. This is very 3194 * inefficient! 3195 */ 3196 if (len * 2 + 2 > buflen) 3197 { 3198 /* Re-allocate the buffer. We keep it around to avoid a lot of 3199 * alloc()/free() calls. */ 3200 vim_free(arshape_buf); 3201 buflen = len * 2 + 2; 3202 arshape_buf = alloc(buflen); 3203 if (arshape_buf == NULL) 3204 return; /* out of memory */ 3205 } 3206 3207 if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) 3208 { 3209 /* Prepend a space to draw the leading composing char on. */ 3210 arshape_buf[0] = ' '; 3211 newlen = 1; 3212 } 3213 3214 for (j = start; j < start + len; j += mb_l) 3215 { 3216 p = ccline.cmdbuff + j; 3217 u8c = utfc_ptr2char_len(p, u8cc, start + len - j); 3218 mb_l = utfc_ptr2len_len(p, start + len - j); 3219 if (ARABIC_CHAR(u8c)) 3220 { 3221 /* Do Arabic shaping. */ 3222 if (cmdmsg_rl) 3223 { 3224 /* displaying from right to left */ 3225 pc = prev_c; 3226 pc1 = prev_c1; 3227 prev_c1 = u8cc[0]; 3228 if (j + mb_l >= start + len) 3229 nc = NUL; 3230 else 3231 nc = utf_ptr2char(p + mb_l); 3232 } 3233 else 3234 { 3235 /* displaying from left to right */ 3236 if (j + mb_l >= start + len) 3237 pc = NUL; 3238 else 3239 { 3240 int pcc[MAX_MCO]; 3241 3242 pc = utfc_ptr2char_len(p + mb_l, pcc, 3243 start + len - j - mb_l); 3244 pc1 = pcc[0]; 3245 } 3246 nc = prev_c; 3247 } 3248 prev_c = u8c; 3249 3250 u8c = arabic_shape(u8c, NULL, &u8cc[0], pc, pc1, nc); 3251 3252 newlen += (*mb_char2bytes)(u8c, arshape_buf + newlen); 3253 if (u8cc[0] != 0) 3254 { 3255 newlen += (*mb_char2bytes)(u8cc[0], arshape_buf + newlen); 3256 if (u8cc[1] != 0) 3257 newlen += (*mb_char2bytes)(u8cc[1], 3258 arshape_buf + newlen); 3259 } 3260 } 3261 else 3262 { 3263 prev_c = u8c; 3264 mch_memmove(arshape_buf + newlen, p, mb_l); 3265 newlen += mb_l; 3266 } 3267 } 3268 3269 msg_outtrans_len(arshape_buf, newlen); 3270 } 3271 else 3272 #endif 3273 msg_outtrans_len(ccline.cmdbuff + start, len); 3274 } 3275 3276 /* 3277 * Put a character on the command line. Shifts the following text to the 3278 * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc. 3279 * "c" must be printable (fit in one display cell)! 3280 */ 3281 void 3282 putcmdline(int c, int shift) 3283 { 3284 if (cmd_silent) 3285 return; 3286 msg_no_more = TRUE; 3287 msg_putchar(c); 3288 if (shift) 3289 draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); 3290 msg_no_more = FALSE; 3291 cursorcmd(); 3292 extra_char = c; 3293 extra_char_shift = shift; 3294 } 3295 3296 /* 3297 * Undo a putcmdline(c, FALSE). 3298 */ 3299 void 3300 unputcmdline(void) 3301 { 3302 if (cmd_silent) 3303 return; 3304 msg_no_more = TRUE; 3305 if (ccline.cmdlen == ccline.cmdpos) 3306 msg_putchar(' '); 3307 else if (has_mbyte) 3308 draw_cmdline(ccline.cmdpos, 3309 (*mb_ptr2len)(ccline.cmdbuff + ccline.cmdpos)); 3310 else 3311 draw_cmdline(ccline.cmdpos, 1); 3312 msg_no_more = FALSE; 3313 cursorcmd(); 3314 extra_char = NUL; 3315 } 3316 3317 /* 3318 * Put the given string, of the given length, onto the command line. 3319 * If len is -1, then STRLEN() is used to calculate the length. 3320 * If 'redraw' is TRUE then the new part of the command line, and the remaining 3321 * part will be redrawn, otherwise it will not. If this function is called 3322 * twice in a row, then 'redraw' should be FALSE and redrawcmd() should be 3323 * called afterwards. 3324 */ 3325 int 3326 put_on_cmdline(char_u *str, int len, int redraw) 3327 { 3328 int retval; 3329 int i; 3330 int m; 3331 int c; 3332 3333 if (len < 0) 3334 len = (int)STRLEN(str); 3335 3336 /* Check if ccline.cmdbuff needs to be longer */ 3337 if (ccline.cmdlen + len + 1 >= ccline.cmdbufflen) 3338 retval = realloc_cmdbuff(ccline.cmdlen + len + 1); 3339 else 3340 retval = OK; 3341 if (retval == OK) 3342 { 3343 if (!ccline.overstrike) 3344 { 3345 mch_memmove(ccline.cmdbuff + ccline.cmdpos + len, 3346 ccline.cmdbuff + ccline.cmdpos, 3347 (size_t)(ccline.cmdlen - ccline.cmdpos)); 3348 ccline.cmdlen += len; 3349 } 3350 else 3351 { 3352 if (has_mbyte) 3353 { 3354 /* Count nr of characters in the new string. */ 3355 m = 0; 3356 for (i = 0; i < len; i += (*mb_ptr2len)(str + i)) 3357 ++m; 3358 /* Count nr of bytes in cmdline that are overwritten by these 3359 * characters. */ 3360 for (i = ccline.cmdpos; i < ccline.cmdlen && m > 0; 3361 i += (*mb_ptr2len)(ccline.cmdbuff + i)) 3362 --m; 3363 if (i < ccline.cmdlen) 3364 { 3365 mch_memmove(ccline.cmdbuff + ccline.cmdpos + len, 3366 ccline.cmdbuff + i, (size_t)(ccline.cmdlen - i)); 3367 ccline.cmdlen += ccline.cmdpos + len - i; 3368 } 3369 else 3370 ccline.cmdlen = ccline.cmdpos + len; 3371 } 3372 else if (ccline.cmdpos + len > ccline.cmdlen) 3373 ccline.cmdlen = ccline.cmdpos + len; 3374 } 3375 mch_memmove(ccline.cmdbuff + ccline.cmdpos, str, (size_t)len); 3376 ccline.cmdbuff[ccline.cmdlen] = NUL; 3377 3378 if (enc_utf8) 3379 { 3380 /* When the inserted text starts with a composing character, 3381 * backup to the character before it. There could be two of them. 3382 */ 3383 i = 0; 3384 c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos); 3385 while (ccline.cmdpos > 0 && utf_iscomposing(c)) 3386 { 3387 i = (*mb_head_off)(ccline.cmdbuff, 3388 ccline.cmdbuff + ccline.cmdpos - 1) + 1; 3389 ccline.cmdpos -= i; 3390 len += i; 3391 c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos); 3392 } 3393 #ifdef FEAT_ARABIC 3394 if (i == 0 && ccline.cmdpos > 0 && arabic_maycombine(c)) 3395 { 3396 /* Check the previous character for Arabic combining pair. */ 3397 i = (*mb_head_off)(ccline.cmdbuff, 3398 ccline.cmdbuff + ccline.cmdpos - 1) + 1; 3399 if (arabic_combine(utf_ptr2char(ccline.cmdbuff 3400 + ccline.cmdpos - i), c)) 3401 { 3402 ccline.cmdpos -= i; 3403 len += i; 3404 } 3405 else 3406 i = 0; 3407 } 3408 #endif 3409 if (i != 0) 3410 { 3411 /* Also backup the cursor position. */ 3412 i = ptr2cells(ccline.cmdbuff + ccline.cmdpos); 3413 ccline.cmdspos -= i; 3414 msg_col -= i; 3415 if (msg_col < 0) 3416 { 3417 msg_col += Columns; 3418 --msg_row; 3419 } 3420 } 3421 } 3422 3423 if (redraw && !cmd_silent) 3424 { 3425 msg_no_more = TRUE; 3426 i = cmdline_row; 3427 cursorcmd(); 3428 draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); 3429 /* Avoid clearing the rest of the line too often. */ 3430 if (cmdline_row != i || ccline.overstrike) 3431 msg_clr_eos(); 3432 msg_no_more = FALSE; 3433 } 3434 if (KeyTyped) 3435 { 3436 m = Columns * Rows; 3437 if (m < 0) /* overflow, Columns or Rows at weird value */ 3438 m = MAXCOL; 3439 } 3440 else 3441 m = MAXCOL; 3442 for (i = 0; i < len; ++i) 3443 { 3444 c = cmdline_charsize(ccline.cmdpos); 3445 /* count ">" for a double-wide char that doesn't fit. */ 3446 if (has_mbyte) 3447 correct_cmdspos(ccline.cmdpos, c); 3448 /* Stop cursor at the end of the screen, but do increment the 3449 * insert position, so that entering a very long command 3450 * works, even though you can't see it. */ 3451 if (ccline.cmdspos + c < m) 3452 ccline.cmdspos += c; 3453 3454 if (has_mbyte) 3455 { 3456 c = (*mb_ptr2len)(ccline.cmdbuff + ccline.cmdpos) - 1; 3457 if (c > len - i - 1) 3458 c = len - i - 1; 3459 ccline.cmdpos += c; 3460 i += c; 3461 } 3462 ++ccline.cmdpos; 3463 } 3464 } 3465 if (redraw) 3466 msg_check(); 3467 return retval; 3468 } 3469 3470 static struct cmdline_info prev_ccline; 3471 static int prev_ccline_used = FALSE; 3472 3473 /* 3474 * Save ccline, because obtaining the "=" register may execute "normal :cmd" 3475 * and overwrite it. But get_cmdline_str() may need it, thus make it 3476 * available globally in prev_ccline. 3477 */ 3478 static void 3479 save_cmdline(struct cmdline_info *ccp) 3480 { 3481 if (!prev_ccline_used) 3482 { 3483 vim_memset(&prev_ccline, 0, sizeof(struct cmdline_info)); 3484 prev_ccline_used = TRUE; 3485 } 3486 *ccp = prev_ccline; 3487 prev_ccline = ccline; 3488 ccline.cmdbuff = NULL; // signal that ccline is not in use 3489 } 3490 3491 /* 3492 * Restore ccline after it has been saved with save_cmdline(). 3493 */ 3494 static void 3495 restore_cmdline(struct cmdline_info *ccp) 3496 { 3497 ccline = prev_ccline; 3498 prev_ccline = *ccp; 3499 } 3500 3501 /* 3502 * Paste a yank register into the command line. 3503 * Used by CTRL-R command in command-line mode. 3504 * insert_reg() can't be used here, because special characters from the 3505 * register contents will be interpreted as commands. 3506 * 3507 * Return FAIL for failure, OK otherwise. 3508 */ 3509 static int 3510 cmdline_paste( 3511 int regname, 3512 int literally, /* Insert text literally instead of "as typed" */ 3513 int remcr) /* remove trailing CR */ 3514 { 3515 long i; 3516 char_u *arg; 3517 char_u *p; 3518 int allocated; 3519 3520 /* check for valid regname; also accept special characters for CTRL-R in 3521 * the command line */ 3522 if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W 3523 && regname != Ctrl_A && regname != Ctrl_L 3524 && !valid_yank_reg(regname, FALSE)) 3525 return FAIL; 3526 3527 /* A register containing CTRL-R can cause an endless loop. Allow using 3528 * CTRL-C to break the loop. */ 3529 line_breakcheck(); 3530 if (got_int) 3531 return FAIL; 3532 3533 #ifdef FEAT_CLIPBOARD 3534 regname = may_get_selection(regname); 3535 #endif 3536 3537 // Need to set "textlock" to avoid nasty things like going to another 3538 // buffer when evaluating an expression. 3539 ++textlock; 3540 i = get_spec_reg(regname, &arg, &allocated, TRUE); 3541 --textlock; 3542 3543 if (i) 3544 { 3545 /* Got the value of a special register in "arg". */ 3546 if (arg == NULL) 3547 return FAIL; 3548 3549 /* When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate 3550 * part of the word. */ 3551 p = arg; 3552 if (p_is && regname == Ctrl_W) 3553 { 3554 char_u *w; 3555 int len; 3556 3557 /* Locate start of last word in the cmd buffer. */ 3558 for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) 3559 { 3560 if (has_mbyte) 3561 { 3562 len = (*mb_head_off)(ccline.cmdbuff, w - 1) + 1; 3563 if (!vim_iswordc(mb_ptr2char(w - len))) 3564 break; 3565 w -= len; 3566 } 3567 else 3568 { 3569 if (!vim_iswordc(w[-1])) 3570 break; 3571 --w; 3572 } 3573 } 3574 len = (int)((ccline.cmdbuff + ccline.cmdpos) - w); 3575 if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0) 3576 p += len; 3577 } 3578 3579 cmdline_paste_str(p, literally); 3580 if (allocated) 3581 vim_free(arg); 3582 return OK; 3583 } 3584 3585 return cmdline_paste_reg(regname, literally, remcr); 3586 } 3587 3588 /* 3589 * Put a string on the command line. 3590 * When "literally" is TRUE, insert literally. 3591 * When "literally" is FALSE, insert as typed, but don't leave the command 3592 * line. 3593 */ 3594 void 3595 cmdline_paste_str(char_u *s, int literally) 3596 { 3597 int c, cv; 3598 3599 if (literally) 3600 put_on_cmdline(s, -1, TRUE); 3601 else 3602 while (*s != NUL) 3603 { 3604 cv = *s; 3605 if (cv == Ctrl_V && s[1]) 3606 ++s; 3607 if (has_mbyte) 3608 c = mb_cptr2char_adv(&s); 3609 else 3610 c = *s++; 3611 if (cv == Ctrl_V || c == ESC || c == Ctrl_C 3612 || c == CAR || c == NL || c == Ctrl_L 3613 #ifdef UNIX 3614 || c == intr_char 3615 #endif 3616 || (c == Ctrl_BSL && *s == Ctrl_N)) 3617 stuffcharReadbuff(Ctrl_V); 3618 stuffcharReadbuff(c); 3619 } 3620 } 3621 3622 #ifdef FEAT_WILDMENU 3623 /* 3624 * Delete characters on the command line, from "from" to the current 3625 * position. 3626 */ 3627 static void 3628 cmdline_del(int from) 3629 { 3630 mch_memmove(ccline.cmdbuff + from, ccline.cmdbuff + ccline.cmdpos, 3631 (size_t)(ccline.cmdlen - ccline.cmdpos + 1)); 3632 ccline.cmdlen -= ccline.cmdpos - from; 3633 ccline.cmdpos = from; 3634 } 3635 #endif 3636 3637 /* 3638 * This function is called when the screen size changes and with incremental 3639 * search and in other situations where the command line may have been 3640 * overwritten. 3641 */ 3642 void 3643 redrawcmdline(void) 3644 { 3645 redrawcmdline_ex(TRUE); 3646 } 3647 3648 void 3649 redrawcmdline_ex(int do_compute_cmdrow) 3650 { 3651 if (cmd_silent) 3652 return; 3653 need_wait_return = FALSE; 3654 if (do_compute_cmdrow) 3655 compute_cmdrow(); 3656 redrawcmd(); 3657 cursorcmd(); 3658 } 3659 3660 static void 3661 redrawcmdprompt(void) 3662 { 3663 int i; 3664 3665 if (cmd_silent) 3666 return; 3667 if (ccline.cmdfirstc != NUL) 3668 msg_putchar(ccline.cmdfirstc); 3669 if (ccline.cmdprompt != NULL) 3670 { 3671 msg_puts_attr((char *)ccline.cmdprompt, ccline.cmdattr); 3672 ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; 3673 /* do the reverse of set_cmdspos() */ 3674 if (ccline.cmdfirstc != NUL) 3675 --ccline.cmdindent; 3676 } 3677 else 3678 for (i = ccline.cmdindent; i > 0; --i) 3679 msg_putchar(' '); 3680 } 3681 3682 /* 3683 * Redraw what is currently on the command line. 3684 */ 3685 void 3686 redrawcmd(void) 3687 { 3688 if (cmd_silent) 3689 return; 3690 3691 /* when 'incsearch' is set there may be no command line while redrawing */ 3692 if (ccline.cmdbuff == NULL) 3693 { 3694 windgoto(cmdline_row, 0); 3695 msg_clr_eos(); 3696 return; 3697 } 3698 3699 msg_start(); 3700 redrawcmdprompt(); 3701 3702 /* Don't use more prompt, truncate the cmdline if it doesn't fit. */ 3703 msg_no_more = TRUE; 3704 draw_cmdline(0, ccline.cmdlen); 3705 msg_clr_eos(); 3706 msg_no_more = FALSE; 3707 3708 set_cmdspos_cursor(); 3709 if (extra_char != NUL) 3710 putcmdline(extra_char, extra_char_shift); 3711 3712 /* 3713 * An emsg() before may have set msg_scroll. This is used in normal mode, 3714 * in cmdline mode we can reset them now. 3715 */ 3716 msg_scroll = FALSE; /* next message overwrites cmdline */ 3717 3718 /* Typing ':' at the more prompt may set skip_redraw. We don't want this 3719 * in cmdline mode */ 3720 skip_redraw = FALSE; 3721 } 3722 3723 void 3724 compute_cmdrow(void) 3725 { 3726 if (exmode_active || msg_scrolled != 0) 3727 cmdline_row = Rows - 1; 3728 else 3729 cmdline_row = W_WINROW(lastwin) + lastwin->w_height 3730 + lastwin->w_status_height; 3731 } 3732 3733 static void 3734 cursorcmd(void) 3735 { 3736 if (cmd_silent) 3737 return; 3738 3739 #ifdef FEAT_RIGHTLEFT 3740 if (cmdmsg_rl) 3741 { 3742 msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1)); 3743 msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1; 3744 if (msg_row <= 0) 3745 msg_row = Rows - 1; 3746 } 3747 else 3748 #endif 3749 { 3750 msg_row = cmdline_row + (ccline.cmdspos / (int)Columns); 3751 msg_col = ccline.cmdspos % (int)Columns; 3752 if (msg_row >= Rows) 3753 msg_row = Rows - 1; 3754 } 3755 3756 windgoto(msg_row, msg_col); 3757 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 3758 if (p_imst == IM_ON_THE_SPOT) 3759 redrawcmd_preedit(); 3760 #endif 3761 #ifdef MCH_CURSOR_SHAPE 3762 mch_update_cursor(); 3763 #endif 3764 } 3765 3766 void 3767 gotocmdline(int clr) 3768 { 3769 msg_start(); 3770 #ifdef FEAT_RIGHTLEFT 3771 if (cmdmsg_rl) 3772 msg_col = Columns - 1; 3773 else 3774 #endif 3775 msg_col = 0; /* always start in column 0 */ 3776 if (clr) /* clear the bottom line(s) */ 3777 msg_clr_eos(); /* will reset clear_cmdline */ 3778 windgoto(cmdline_row, 0); 3779 } 3780 3781 /* 3782 * Check the word in front of the cursor for an abbreviation. 3783 * Called when the non-id character "c" has been entered. 3784 * When an abbreviation is recognized it is removed from the text with 3785 * backspaces and the replacement string is inserted, followed by "c". 3786 */ 3787 static int 3788 ccheck_abbr(int c) 3789 { 3790 int spos = 0; 3791 3792 if (p_paste || no_abbr) /* no abbreviations or in paste mode */ 3793 return FALSE; 3794 3795 /* Do not consider '<,'> be part of the mapping, skip leading whitespace. 3796 * Actually accepts any mark. */ 3797 while (VIM_ISWHITE(ccline.cmdbuff[spos]) && spos < ccline.cmdlen) 3798 spos++; 3799 if (ccline.cmdlen - spos > 5 3800 && ccline.cmdbuff[spos] == '\'' 3801 && ccline.cmdbuff[spos + 2] == ',' 3802 && ccline.cmdbuff[spos + 3] == '\'') 3803 spos += 5; 3804 else 3805 /* check abbreviation from the beginning of the commandline */ 3806 spos = 0; 3807 3808 return check_abbr(c, ccline.cmdbuff, ccline.cmdpos, spos); 3809 } 3810 3811 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3812 static int 3813 #ifdef __BORLANDC__ 3814 _RTLENTRYF 3815 #endif 3816 sort_func_compare(const void *s1, const void *s2) 3817 { 3818 char_u *p1 = *(char_u **)s1; 3819 char_u *p2 = *(char_u **)s2; 3820 3821 if (*p1 != '<' && *p2 == '<') return -1; 3822 if (*p1 == '<' && *p2 != '<') return 1; 3823 return STRCMP(p1, p2); 3824 } 3825 #endif 3826 3827 /* 3828 * Return FAIL if this is not an appropriate context in which to do 3829 * completion of anything, return OK if it is (even if there are no matches). 3830 * For the caller, this means that the character is just passed through like a 3831 * normal character (instead of being expanded). This allows :s/^I^D etc. 3832 */ 3833 static int 3834 nextwild( 3835 expand_T *xp, 3836 int type, 3837 int options, /* extra options for ExpandOne() */ 3838 int escape) /* if TRUE, escape the returned matches */ 3839 { 3840 int i, j; 3841 char_u *p1; 3842 char_u *p2; 3843 int difflen; 3844 int v; 3845 3846 if (xp->xp_numfiles == -1) 3847 { 3848 set_expand_context(xp); 3849 cmd_showtail = expand_showtail(xp); 3850 } 3851 3852 if (xp->xp_context == EXPAND_UNSUCCESSFUL) 3853 { 3854 beep_flush(); 3855 return OK; /* Something illegal on command line */ 3856 } 3857 if (xp->xp_context == EXPAND_NOTHING) 3858 { 3859 /* Caller can use the character as a normal char instead */ 3860 return FAIL; 3861 } 3862 3863 msg_puts("..."); /* show that we are busy */ 3864 out_flush(); 3865 3866 i = (int)(xp->xp_pattern - ccline.cmdbuff); 3867 xp->xp_pattern_len = ccline.cmdpos - i; 3868 3869 if (type == WILD_NEXT || type == WILD_PREV) 3870 { 3871 /* 3872 * Get next/previous match for a previous expanded pattern. 3873 */ 3874 p2 = ExpandOne(xp, NULL, NULL, 0, type); 3875 } 3876 else 3877 { 3878 /* 3879 * Translate string into pattern and expand it. 3880 */ 3881 if ((p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, 3882 xp->xp_context)) == NULL) 3883 p2 = NULL; 3884 else 3885 { 3886 int use_options = options | 3887 WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT; 3888 if (escape) 3889 use_options |= WILD_ESCAPE; 3890 3891 if (p_wic) 3892 use_options += WILD_ICASE; 3893 p2 = ExpandOne(xp, p1, 3894 vim_strnsave(&ccline.cmdbuff[i], xp->xp_pattern_len), 3895 use_options, type); 3896 vim_free(p1); 3897 /* longest match: make sure it is not shorter, happens with :help */ 3898 if (p2 != NULL && type == WILD_LONGEST) 3899 { 3900 for (j = 0; j < xp->xp_pattern_len; ++j) 3901 if (ccline.cmdbuff[i + j] == '*' 3902 || ccline.cmdbuff[i + j] == '?') 3903 break; 3904 if ((int)STRLEN(p2) < j) 3905 VIM_CLEAR(p2); 3906 } 3907 } 3908 } 3909 3910 if (p2 != NULL && !got_int) 3911 { 3912 difflen = (int)STRLEN(p2) - xp->xp_pattern_len; 3913 if (ccline.cmdlen + difflen + 4 > ccline.cmdbufflen) 3914 { 3915 v = realloc_cmdbuff(ccline.cmdlen + difflen + 4); 3916 xp->xp_pattern = ccline.cmdbuff + i; 3917 } 3918 else 3919 v = OK; 3920 if (v == OK) 3921 { 3922 mch_memmove(&ccline.cmdbuff[ccline.cmdpos + difflen], 3923 &ccline.cmdbuff[ccline.cmdpos], 3924 (size_t)(ccline.cmdlen - ccline.cmdpos + 1)); 3925 mch_memmove(&ccline.cmdbuff[i], p2, STRLEN(p2)); 3926 ccline.cmdlen += difflen; 3927 ccline.cmdpos += difflen; 3928 } 3929 } 3930 vim_free(p2); 3931 3932 redrawcmd(); 3933 cursorcmd(); 3934 3935 /* When expanding a ":map" command and no matches are found, assume that 3936 * the key is supposed to be inserted literally */ 3937 if (xp->xp_context == EXPAND_MAPPINGS && p2 == NULL) 3938 return FAIL; 3939 3940 if (xp->xp_numfiles <= 0 && p2 == NULL) 3941 beep_flush(); 3942 else if (xp->xp_numfiles == 1) 3943 /* free expanded pattern */ 3944 (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE); 3945 3946 return OK; 3947 } 3948 3949 /* 3950 * Do wildcard expansion on the string 'str'. 3951 * Chars that should not be expanded must be preceded with a backslash. 3952 * Return a pointer to allocated memory containing the new string. 3953 * Return NULL for failure. 3954 * 3955 * "orig" is the originally expanded string, copied to allocated memory. It 3956 * should either be kept in orig_save or freed. When "mode" is WILD_NEXT or 3957 * WILD_PREV "orig" should be NULL. 3958 * 3959 * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode" 3960 * is WILD_EXPAND_FREE or WILD_ALL. 3961 * 3962 * mode = WILD_FREE: just free previously expanded matches 3963 * mode = WILD_EXPAND_FREE: normal expansion, do not keep matches 3964 * mode = WILD_EXPAND_KEEP: normal expansion, keep matches 3965 * mode = WILD_NEXT: use next match in multiple match, wrap to first 3966 * mode = WILD_PREV: use previous match in multiple match, wrap to first 3967 * mode = WILD_ALL: return all matches concatenated 3968 * mode = WILD_LONGEST: return longest matched part 3969 * mode = WILD_ALL_KEEP: get all matches, keep matches 3970 * 3971 * options = WILD_LIST_NOTFOUND: list entries without a match 3972 * options = WILD_HOME_REPLACE: do home_replace() for buffer names 3973 * options = WILD_USE_NL: Use '\n' for WILD_ALL 3974 * options = WILD_NO_BEEP: Don't beep for multiple matches 3975 * options = WILD_ADD_SLASH: add a slash after directory names 3976 * options = WILD_KEEP_ALL: don't remove 'wildignore' entries 3977 * options = WILD_SILENT: don't print warning messages 3978 * options = WILD_ESCAPE: put backslash before special chars 3979 * options = WILD_ICASE: ignore case for files 3980 * 3981 * The variables xp->xp_context and xp->xp_backslash must have been set! 3982 */ 3983 char_u * 3984 ExpandOne( 3985 expand_T *xp, 3986 char_u *str, 3987 char_u *orig, /* allocated copy of original of expanded string */ 3988 int options, 3989 int mode) 3990 { 3991 char_u *ss = NULL; 3992 static int findex; 3993 static char_u *orig_save = NULL; /* kept value of orig */ 3994 int orig_saved = FALSE; 3995 int i; 3996 long_u len; 3997 int non_suf_match; /* number without matching suffix */ 3998 3999 /* 4000 * first handle the case of using an old match 4001 */ 4002 if (mode == WILD_NEXT || mode == WILD_PREV) 4003 { 4004 if (xp->xp_numfiles > 0) 4005 { 4006 if (mode == WILD_PREV) 4007 { 4008 if (findex == -1) 4009 findex = xp->xp_numfiles; 4010 --findex; 4011 } 4012 else /* mode == WILD_NEXT */ 4013 ++findex; 4014 4015 /* 4016 * When wrapping around, return the original string, set findex to 4017 * -1. 4018 */ 4019 if (findex < 0) 4020 { 4021 if (orig_save == NULL) 4022 findex = xp->xp_numfiles - 1; 4023 else 4024 findex = -1; 4025 } 4026 if (findex >= xp->xp_numfiles) 4027 { 4028 if (orig_save == NULL) 4029 findex = 0; 4030 else 4031 findex = -1; 4032 } 4033 #ifdef FEAT_WILDMENU 4034 if (p_wmnu) 4035 win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, 4036 findex, cmd_showtail); 4037 #endif 4038 if (findex == -1) 4039 return vim_strsave(orig_save); 4040 return vim_strsave(xp->xp_files[findex]); 4041 } 4042 else 4043 return NULL; 4044 } 4045 4046 /* free old names */ 4047 if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST) 4048 { 4049 FreeWild(xp->xp_numfiles, xp->xp_files); 4050 xp->xp_numfiles = -1; 4051 VIM_CLEAR(orig_save); 4052 } 4053 findex = 0; 4054 4055 if (mode == WILD_FREE) /* only release file name */ 4056 return NULL; 4057 4058 if (xp->xp_numfiles == -1) 4059 { 4060 vim_free(orig_save); 4061 orig_save = orig; 4062 orig_saved = TRUE; 4063 4064 /* 4065 * Do the expansion. 4066 */ 4067 if (ExpandFromContext(xp, str, &xp->xp_numfiles, &xp->xp_files, 4068 options) == FAIL) 4069 { 4070 #ifdef FNAME_ILLEGAL 4071 /* Illegal file name has been silently skipped. But when there 4072 * are wildcards, the real problem is that there was no match, 4073 * causing the pattern to be added, which has illegal characters. 4074 */ 4075 if (!(options & WILD_SILENT) && (options & WILD_LIST_NOTFOUND)) 4076 semsg(_(e_nomatch2), str); 4077 #endif 4078 } 4079 else if (xp->xp_numfiles == 0) 4080 { 4081 if (!(options & WILD_SILENT)) 4082 semsg(_(e_nomatch2), str); 4083 } 4084 else 4085 { 4086 /* Escape the matches for use on the command line. */ 4087 ExpandEscape(xp, str, xp->xp_numfiles, xp->xp_files, options); 4088 4089 /* 4090 * Check for matching suffixes in file names. 4091 */ 4092 if (mode != WILD_ALL && mode != WILD_ALL_KEEP 4093 && mode != WILD_LONGEST) 4094 { 4095 if (xp->xp_numfiles) 4096 non_suf_match = xp->xp_numfiles; 4097 else 4098 non_suf_match = 1; 4099 if ((xp->xp_context == EXPAND_FILES 4100 || xp->xp_context == EXPAND_DIRECTORIES) 4101 && xp->xp_numfiles > 1) 4102 { 4103 /* 4104 * More than one match; check suffix. 4105 * The files will have been sorted on matching suffix in 4106 * expand_wildcards, only need to check the first two. 4107 */ 4108 non_suf_match = 0; 4109 for (i = 0; i < 2; ++i) 4110 if (match_suffix(xp->xp_files[i])) 4111 ++non_suf_match; 4112 } 4113 if (non_suf_match != 1) 4114 { 4115 /* Can we ever get here unless it's while expanding 4116 * interactively? If not, we can get rid of this all 4117 * together. Don't really want to wait for this message 4118 * (and possibly have to hit return to continue!). 4119 */ 4120 if (!(options & WILD_SILENT)) 4121 emsg(_(e_toomany)); 4122 else if (!(options & WILD_NO_BEEP)) 4123 beep_flush(); 4124 } 4125 if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) 4126 ss = vim_strsave(xp->xp_files[0]); 4127 } 4128 } 4129 } 4130 4131 /* Find longest common part */ 4132 if (mode == WILD_LONGEST && xp->xp_numfiles > 0) 4133 { 4134 int mb_len = 1; 4135 int c0, ci; 4136 4137 for (len = 0; xp->xp_files[0][len]; len += mb_len) 4138 { 4139 if (has_mbyte) 4140 { 4141 mb_len = (*mb_ptr2len)(&xp->xp_files[0][len]); 4142 c0 =(* mb_ptr2char)(&xp->xp_files[0][len]); 4143 } 4144 else 4145 c0 = xp->xp_files[0][len]; 4146 for (i = 1; i < xp->xp_numfiles; ++i) 4147 { 4148 if (has_mbyte) 4149 ci =(* mb_ptr2char)(&xp->xp_files[i][len]); 4150 else 4151 ci = xp->xp_files[i][len]; 4152 if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES 4153 || xp->xp_context == EXPAND_FILES 4154 || xp->xp_context == EXPAND_SHELLCMD 4155 || xp->xp_context == EXPAND_BUFFERS)) 4156 { 4157 if (MB_TOLOWER(c0) != MB_TOLOWER(ci)) 4158 break; 4159 } 4160 else if (c0 != ci) 4161 break; 4162 } 4163 if (i < xp->xp_numfiles) 4164 { 4165 if (!(options & WILD_NO_BEEP)) 4166 vim_beep(BO_WILD); 4167 break; 4168 } 4169 } 4170 4171 ss = alloc((unsigned)len + 1); 4172 if (ss) 4173 vim_strncpy(ss, xp->xp_files[0], (size_t)len); 4174 findex = -1; /* next p_wc gets first one */ 4175 } 4176 4177 /* Concatenate all matching names */ 4178 if (mode == WILD_ALL && xp->xp_numfiles > 0) 4179 { 4180 len = 0; 4181 for (i = 0; i < xp->xp_numfiles; ++i) 4182 len += (long_u)STRLEN(xp->xp_files[i]) + 1; 4183 ss = lalloc(len, TRUE); 4184 if (ss != NULL) 4185 { 4186 *ss = NUL; 4187 for (i = 0; i < xp->xp_numfiles; ++i) 4188 { 4189 STRCAT(ss, xp->xp_files[i]); 4190 if (i != xp->xp_numfiles - 1) 4191 STRCAT(ss, (options & WILD_USE_NL) ? "\n" : " "); 4192 } 4193 } 4194 } 4195 4196 if (mode == WILD_EXPAND_FREE || mode == WILD_ALL) 4197 ExpandCleanup(xp); 4198 4199 /* Free "orig" if it wasn't stored in "orig_save". */ 4200 if (!orig_saved) 4201 vim_free(orig); 4202 4203 return ss; 4204 } 4205 4206 /* 4207 * Prepare an expand structure for use. 4208 */ 4209 void 4210 ExpandInit(expand_T *xp) 4211 { 4212 xp->xp_pattern = NULL; 4213 xp->xp_pattern_len = 0; 4214 xp->xp_backslash = XP_BS_NONE; 4215 #ifndef BACKSLASH_IN_FILENAME 4216 xp->xp_shell = FALSE; 4217 #endif 4218 xp->xp_numfiles = -1; 4219 xp->xp_files = NULL; 4220 #if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 4221 xp->xp_arg = NULL; 4222 #endif 4223 xp->xp_line = NULL; 4224 } 4225 4226 /* 4227 * Cleanup an expand structure after use. 4228 */ 4229 void 4230 ExpandCleanup(expand_T *xp) 4231 { 4232 if (xp->xp_numfiles >= 0) 4233 { 4234 FreeWild(xp->xp_numfiles, xp->xp_files); 4235 xp->xp_numfiles = -1; 4236 } 4237 } 4238 4239 void 4240 ExpandEscape( 4241 expand_T *xp, 4242 char_u *str, 4243 int numfiles, 4244 char_u **files, 4245 int options) 4246 { 4247 int i; 4248 char_u *p; 4249 4250 /* 4251 * May change home directory back to "~" 4252 */ 4253 if (options & WILD_HOME_REPLACE) 4254 tilde_replace(str, numfiles, files); 4255 4256 if (options & WILD_ESCAPE) 4257 { 4258 if (xp->xp_context == EXPAND_FILES 4259 || xp->xp_context == EXPAND_FILES_IN_PATH 4260 || xp->xp_context == EXPAND_SHELLCMD 4261 || xp->xp_context == EXPAND_BUFFERS 4262 || xp->xp_context == EXPAND_DIRECTORIES) 4263 { 4264 /* 4265 * Insert a backslash into a file name before a space, \, %, # 4266 * and wildmatch characters, except '~'. 4267 */ 4268 for (i = 0; i < numfiles; ++i) 4269 { 4270 /* for ":set path=" we need to escape spaces twice */ 4271 if (xp->xp_backslash == XP_BS_THREE) 4272 { 4273 p = vim_strsave_escaped(files[i], (char_u *)" "); 4274 if (p != NULL) 4275 { 4276 vim_free(files[i]); 4277 files[i] = p; 4278 #if defined(BACKSLASH_IN_FILENAME) 4279 p = vim_strsave_escaped(files[i], (char_u *)" "); 4280 if (p != NULL) 4281 { 4282 vim_free(files[i]); 4283 files[i] = p; 4284 } 4285 #endif 4286 } 4287 } 4288 #ifdef BACKSLASH_IN_FILENAME 4289 p = vim_strsave_fnameescape(files[i], FALSE); 4290 #else 4291 p = vim_strsave_fnameescape(files[i], xp->xp_shell); 4292 #endif 4293 if (p != NULL) 4294 { 4295 vim_free(files[i]); 4296 files[i] = p; 4297 } 4298 4299 /* If 'str' starts with "\~", replace "~" at start of 4300 * files[i] with "\~". */ 4301 if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') 4302 escape_fname(&files[i]); 4303 } 4304 xp->xp_backslash = XP_BS_NONE; 4305 4306 /* If the first file starts with a '+' escape it. Otherwise it 4307 * could be seen as "+cmd". */ 4308 if (*files[0] == '+') 4309 escape_fname(&files[0]); 4310 } 4311 else if (xp->xp_context == EXPAND_TAGS) 4312 { 4313 /* 4314 * Insert a backslash before characters in a tag name that 4315 * would terminate the ":tag" command. 4316 */ 4317 for (i = 0; i < numfiles; ++i) 4318 { 4319 p = vim_strsave_escaped(files[i], (char_u *)"\\|\""); 4320 if (p != NULL) 4321 { 4322 vim_free(files[i]); 4323 files[i] = p; 4324 } 4325 } 4326 } 4327 } 4328 } 4329 4330 /* 4331 * Escape special characters in "fname" for when used as a file name argument 4332 * after a Vim command, or, when "shell" is non-zero, a shell command. 4333 * Returns the result in allocated memory. 4334 */ 4335 char_u * 4336 vim_strsave_fnameescape(char_u *fname, int shell) 4337 { 4338 char_u *p; 4339 #ifdef BACKSLASH_IN_FILENAME 4340 char_u buf[20]; 4341 int j = 0; 4342 4343 /* Don't escape '[', '{' and '!' if they are in 'isfname'. */ 4344 for (p = PATH_ESC_CHARS; *p != NUL; ++p) 4345 if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) 4346 buf[j++] = *p; 4347 buf[j] = NUL; 4348 p = vim_strsave_escaped(fname, buf); 4349 #else 4350 p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); 4351 if (shell && csh_like_shell() && p != NULL) 4352 { 4353 char_u *s; 4354 4355 /* For csh and similar shells need to put two backslashes before '!'. 4356 * One is taken by Vim, one by the shell. */ 4357 s = vim_strsave_escaped(p, (char_u *)"!"); 4358 vim_free(p); 4359 p = s; 4360 } 4361 #endif 4362 4363 /* '>' and '+' are special at the start of some commands, e.g. ":edit" and 4364 * ":write". "cd -" has a special meaning. */ 4365 if (p != NULL && (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL))) 4366 escape_fname(&p); 4367 4368 return p; 4369 } 4370 4371 /* 4372 * Put a backslash before the file name in "pp", which is in allocated memory. 4373 */ 4374 static void 4375 escape_fname(char_u **pp) 4376 { 4377 char_u *p; 4378 4379 p = alloc((unsigned)(STRLEN(*pp) + 2)); 4380 if (p != NULL) 4381 { 4382 p[0] = '\\'; 4383 STRCPY(p + 1, *pp); 4384 vim_free(*pp); 4385 *pp = p; 4386 } 4387 } 4388 4389 /* 4390 * For each file name in files[num_files]: 4391 * If 'orig_pat' starts with "~/", replace the home directory with "~". 4392 */ 4393 void 4394 tilde_replace( 4395 char_u *orig_pat, 4396 int num_files, 4397 char_u **files) 4398 { 4399 int i; 4400 char_u *p; 4401 4402 if (orig_pat[0] == '~' && vim_ispathsep(orig_pat[1])) 4403 { 4404 for (i = 0; i < num_files; ++i) 4405 { 4406 p = home_replace_save(NULL, files[i]); 4407 if (p != NULL) 4408 { 4409 vim_free(files[i]); 4410 files[i] = p; 4411 } 4412 } 4413 } 4414 } 4415 4416 /* 4417 * Show all matches for completion on the command line. 4418 * Returns EXPAND_NOTHING when the character that triggered expansion should 4419 * be inserted like a normal character. 4420 */ 4421 static int 4422 showmatches(expand_T *xp, int wildmenu UNUSED) 4423 { 4424 #define L_SHOWFILE(m) (showtail ? sm_gettail(files_found[m]) : files_found[m]) 4425 int num_files; 4426 char_u **files_found; 4427 int i, j, k; 4428 int maxlen; 4429 int lines; 4430 int columns; 4431 char_u *p; 4432 int lastlen; 4433 int attr; 4434 int showtail; 4435 4436 if (xp->xp_numfiles == -1) 4437 { 4438 set_expand_context(xp); 4439 i = expand_cmdline(xp, ccline.cmdbuff, ccline.cmdpos, 4440 &num_files, &files_found); 4441 showtail = expand_showtail(xp); 4442 if (i != EXPAND_OK) 4443 return i; 4444 4445 } 4446 else 4447 { 4448 num_files = xp->xp_numfiles; 4449 files_found = xp->xp_files; 4450 showtail = cmd_showtail; 4451 } 4452 4453 #ifdef FEAT_WILDMENU 4454 if (!wildmenu) 4455 { 4456 #endif 4457 msg_didany = FALSE; /* lines_left will be set */ 4458 msg_start(); /* prepare for paging */ 4459 msg_putchar('\n'); 4460 out_flush(); 4461 cmdline_row = msg_row; 4462 msg_didany = FALSE; /* lines_left will be set again */ 4463 msg_start(); /* prepare for paging */ 4464 #ifdef FEAT_WILDMENU 4465 } 4466 #endif 4467 4468 if (got_int) 4469 got_int = FALSE; /* only int. the completion, not the cmd line */ 4470 #ifdef FEAT_WILDMENU 4471 else if (wildmenu) 4472 win_redr_status_matches(xp, num_files, files_found, -1, showtail); 4473 #endif 4474 else 4475 { 4476 /* find the length of the longest file name */ 4477 maxlen = 0; 4478 for (i = 0; i < num_files; ++i) 4479 { 4480 if (!showtail && (xp->xp_context == EXPAND_FILES 4481 || xp->xp_context == EXPAND_SHELLCMD 4482 || xp->xp_context == EXPAND_BUFFERS)) 4483 { 4484 home_replace(NULL, files_found[i], NameBuff, MAXPATHL, TRUE); 4485 j = vim_strsize(NameBuff); 4486 } 4487 else 4488 j = vim_strsize(L_SHOWFILE(i)); 4489 if (j > maxlen) 4490 maxlen = j; 4491 } 4492 4493 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 4494 lines = num_files; 4495 else 4496 { 4497 /* compute the number of columns and lines for the listing */ 4498 maxlen += 2; /* two spaces between file names */ 4499 columns = ((int)Columns + 2) / maxlen; 4500 if (columns < 1) 4501 columns = 1; 4502 lines = (num_files + columns - 1) / columns; 4503 } 4504 4505 attr = HL_ATTR(HLF_D); /* find out highlighting for directories */ 4506 4507 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 4508 { 4509 msg_puts_attr(_("tagname"), HL_ATTR(HLF_T)); 4510 msg_clr_eos(); 4511 msg_advance(maxlen - 3); 4512 msg_puts_attr(_(" kind file\n"), HL_ATTR(HLF_T)); 4513 } 4514 4515 /* list the files line by line */ 4516 for (i = 0; i < lines; ++i) 4517 { 4518 lastlen = 999; 4519 for (k = i; k < num_files; k += lines) 4520 { 4521 if (xp->xp_context == EXPAND_TAGS_LISTFILES) 4522 { 4523 msg_outtrans_attr(files_found[k], HL_ATTR(HLF_D)); 4524 p = files_found[k] + STRLEN(files_found[k]) + 1; 4525 msg_advance(maxlen + 1); 4526 msg_puts((char *)p); 4527 msg_advance(maxlen + 3); 4528 msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D)); 4529 break; 4530 } 4531 for (j = maxlen - lastlen; --j >= 0; ) 4532 msg_putchar(' '); 4533 if (xp->xp_context == EXPAND_FILES 4534 || xp->xp_context == EXPAND_SHELLCMD 4535 || xp->xp_context == EXPAND_BUFFERS) 4536 { 4537 /* highlight directories */ 4538 if (xp->xp_numfiles != -1) 4539 { 4540 char_u *halved_slash; 4541 char_u *exp_path; 4542 4543 /* Expansion was done before and special characters 4544 * were escaped, need to halve backslashes. Also 4545 * $HOME has been replaced with ~/. */ 4546 exp_path = expand_env_save_opt(files_found[k], TRUE); 4547 halved_slash = backslash_halve_save( 4548 exp_path != NULL ? exp_path : files_found[k]); 4549 j = mch_isdir(halved_slash != NULL ? halved_slash 4550 : files_found[k]); 4551 vim_free(exp_path); 4552 vim_free(halved_slash); 4553 } 4554 else 4555 /* Expansion was done here, file names are literal. */ 4556 j = mch_isdir(files_found[k]); 4557 if (showtail) 4558 p = L_SHOWFILE(k); 4559 else 4560 { 4561 home_replace(NULL, files_found[k], NameBuff, MAXPATHL, 4562 TRUE); 4563 p = NameBuff; 4564 } 4565 } 4566 else 4567 { 4568 j = FALSE; 4569 p = L_SHOWFILE(k); 4570 } 4571 lastlen = msg_outtrans_attr(p, j ? attr : 0); 4572 } 4573 if (msg_col > 0) /* when not wrapped around */ 4574 { 4575 msg_clr_eos(); 4576 msg_putchar('\n'); 4577 } 4578 out_flush(); /* show one line at a time */ 4579 if (got_int) 4580 { 4581 got_int = FALSE; 4582 break; 4583 } 4584 } 4585 4586 /* 4587 * we redraw the command below the lines that we have just listed 4588 * This is a bit tricky, but it saves a lot of screen updating. 4589 */ 4590 cmdline_row = msg_row; /* will put it back later */ 4591 } 4592 4593 if (xp->xp_numfiles == -1) 4594 FreeWild(num_files, files_found); 4595 4596 return EXPAND_OK; 4597 } 4598 4599 /* 4600 * Private gettail for showmatches() (and win_redr_status_matches()): 4601 * Find tail of file name path, but ignore trailing "/". 4602 */ 4603 char_u * 4604 sm_gettail(char_u *s) 4605 { 4606 char_u *p; 4607 char_u *t = s; 4608 int had_sep = FALSE; 4609 4610 for (p = s; *p != NUL; ) 4611 { 4612 if (vim_ispathsep(*p) 4613 #ifdef BACKSLASH_IN_FILENAME 4614 && !rem_backslash(p) 4615 #endif 4616 ) 4617 had_sep = TRUE; 4618 else if (had_sep) 4619 { 4620 t = p; 4621 had_sep = FALSE; 4622 } 4623 MB_PTR_ADV(p); 4624 } 4625 return t; 4626 } 4627 4628 /* 4629 * Return TRUE if we only need to show the tail of completion matches. 4630 * When not completing file names or there is a wildcard in the path FALSE is 4631 * returned. 4632 */ 4633 static int 4634 expand_showtail(expand_T *xp) 4635 { 4636 char_u *s; 4637 char_u *end; 4638 4639 /* When not completing file names a "/" may mean something different. */ 4640 if (xp->xp_context != EXPAND_FILES 4641 && xp->xp_context != EXPAND_SHELLCMD 4642 && xp->xp_context != EXPAND_DIRECTORIES) 4643 return FALSE; 4644 4645 end = gettail(xp->xp_pattern); 4646 if (end == xp->xp_pattern) /* there is no path separator */ 4647 return FALSE; 4648 4649 for (s = xp->xp_pattern; s < end; s++) 4650 { 4651 /* Skip escaped wildcards. Only when the backslash is not a path 4652 * separator, on DOS the '*' "path\*\file" must not be skipped. */ 4653 if (rem_backslash(s)) 4654 ++s; 4655 else if (vim_strchr((char_u *)"*?[", *s) != NULL) 4656 return FALSE; 4657 } 4658 return TRUE; 4659 } 4660 4661 /* 4662 * Prepare a string for expansion. 4663 * When expanding file names: The string will be used with expand_wildcards(). 4664 * Copy "fname[len]" into allocated memory and add a '*' at the end. 4665 * When expanding other names: The string will be used with regcomp(). Copy 4666 * the name into allocated memory and prepend "^". 4667 */ 4668 char_u * 4669 addstar( 4670 char_u *fname, 4671 int len, 4672 int context) /* EXPAND_FILES etc. */ 4673 { 4674 char_u *retval; 4675 int i, j; 4676 int new_len; 4677 char_u *tail; 4678 int ends_in_star; 4679 4680 if (context != EXPAND_FILES 4681 && context != EXPAND_FILES_IN_PATH 4682 && context != EXPAND_SHELLCMD 4683 && context != EXPAND_DIRECTORIES) 4684 { 4685 /* 4686 * Matching will be done internally (on something other than files). 4687 * So we convert the file-matching-type wildcards into our kind for 4688 * use with vim_regcomp(). First work out how long it will be: 4689 */ 4690 4691 /* For help tags the translation is done in find_help_tags(). 4692 * For a tag pattern starting with "/" no translation is needed. */ 4693 if (context == EXPAND_HELP 4694 || context == EXPAND_COLORS 4695 || context == EXPAND_COMPILER 4696 || context == EXPAND_OWNSYNTAX 4697 || context == EXPAND_FILETYPE 4698 || context == EXPAND_PACKADD 4699 || ((context == EXPAND_TAGS_LISTFILES 4700 || context == EXPAND_TAGS) 4701 && fname[0] == '/')) 4702 retval = vim_strnsave(fname, len); 4703 else 4704 { 4705 new_len = len + 2; /* +2 for '^' at start, NUL at end */ 4706 for (i = 0; i < len; i++) 4707 { 4708 if (fname[i] == '*' || fname[i] == '~') 4709 new_len++; /* '*' needs to be replaced by ".*" 4710 '~' needs to be replaced by "\~" */ 4711 4712 /* Buffer names are like file names. "." should be literal */ 4713 if (context == EXPAND_BUFFERS && fname[i] == '.') 4714 new_len++; /* "." becomes "\." */ 4715 4716 /* Custom expansion takes care of special things, match 4717 * backslashes literally (perhaps also for other types?) */ 4718 if ((context == EXPAND_USER_DEFINED 4719 || context == EXPAND_USER_LIST) && fname[i] == '\\') 4720 new_len++; /* '\' becomes "\\" */ 4721 } 4722 retval = alloc(new_len); 4723 if (retval != NULL) 4724 { 4725 retval[0] = '^'; 4726 j = 1; 4727 for (i = 0; i < len; i++, j++) 4728 { 4729 /* Skip backslash. But why? At least keep it for custom 4730 * expansion. */ 4731 if (context != EXPAND_USER_DEFINED 4732 && context != EXPAND_USER_LIST 4733 && fname[i] == '\\' 4734 && ++i == len) 4735 break; 4736 4737 switch (fname[i]) 4738 { 4739 case '*': retval[j++] = '.'; 4740 break; 4741 case '~': retval[j++] = '\\'; 4742 break; 4743 case '?': retval[j] = '.'; 4744 continue; 4745 case '.': if (context == EXPAND_BUFFERS) 4746 retval[j++] = '\\'; 4747 break; 4748 case '\\': if (context == EXPAND_USER_DEFINED 4749 || context == EXPAND_USER_LIST) 4750 retval[j++] = '\\'; 4751 break; 4752 } 4753 retval[j] = fname[i]; 4754 } 4755 retval[j] = NUL; 4756 } 4757 } 4758 } 4759 else 4760 { 4761 retval = alloc(len + 4); 4762 if (retval != NULL) 4763 { 4764 vim_strncpy(retval, fname, len); 4765 4766 /* 4767 * Don't add a star to *, ~, ~user, $var or `cmd`. 4768 * * would become **, which walks the whole tree. 4769 * ~ would be at the start of the file name, but not the tail. 4770 * $ could be anywhere in the tail. 4771 * ` could be anywhere in the file name. 4772 * When the name ends in '$' don't add a star, remove the '$'. 4773 */ 4774 tail = gettail(retval); 4775 ends_in_star = (len > 0 && retval[len - 1] == '*'); 4776 #ifndef BACKSLASH_IN_FILENAME 4777 for (i = len - 2; i >= 0; --i) 4778 { 4779 if (retval[i] != '\\') 4780 break; 4781 ends_in_star = !ends_in_star; 4782 } 4783 #endif 4784 if ((*retval != '~' || tail != retval) 4785 && !ends_in_star 4786 && vim_strchr(tail, '$') == NULL 4787 && vim_strchr(retval, '`') == NULL) 4788 retval[len++] = '*'; 4789 else if (len > 0 && retval[len - 1] == '$') 4790 --len; 4791 retval[len] = NUL; 4792 } 4793 } 4794 return retval; 4795 } 4796 4797 /* 4798 * Must parse the command line so far to work out what context we are in. 4799 * Completion can then be done based on that context. 4800 * This routine sets the variables: 4801 * xp->xp_pattern The start of the pattern to be expanded within 4802 * the command line (ends at the cursor). 4803 * xp->xp_context The type of thing to expand. Will be one of: 4804 * 4805 * EXPAND_UNSUCCESSFUL Used sometimes when there is something illegal on 4806 * the command line, like an unknown command. Caller 4807 * should beep. 4808 * EXPAND_NOTHING Unrecognised context for completion, use char like 4809 * a normal char, rather than for completion. eg 4810 * :s/^I/ 4811 * EXPAND_COMMANDS Cursor is still touching the command, so complete 4812 * it. 4813 * EXPAND_BUFFERS Complete file names for :buf and :sbuf commands. 4814 * EXPAND_FILES After command with XFILE set, or after setting 4815 * with P_EXPAND set. eg :e ^I, :w>>^I 4816 * EXPAND_DIRECTORIES In some cases this is used instead of the latter 4817 * when we know only directories are of interest. eg 4818 * :set dir=^I 4819 * EXPAND_SHELLCMD After ":!cmd", ":r !cmd" or ":w !cmd". 4820 * EXPAND_SETTINGS Complete variable names. eg :set d^I 4821 * EXPAND_BOOL_SETTINGS Complete boolean variables only, eg :set no^I 4822 * EXPAND_TAGS Complete tags from the files in p_tags. eg :ta a^I 4823 * EXPAND_TAGS_LISTFILES As above, but list filenames on ^D, after :tselect 4824 * EXPAND_HELP Complete tags from the file 'helpfile'/tags 4825 * EXPAND_EVENTS Complete event names 4826 * EXPAND_SYNTAX Complete :syntax command arguments 4827 * EXPAND_HIGHLIGHT Complete highlight (syntax) group names 4828 * EXPAND_AUGROUP Complete autocommand group names 4829 * EXPAND_USER_VARS Complete user defined variable names, eg :unlet a^I 4830 * EXPAND_MAPPINGS Complete mapping and abbreviation names, 4831 * eg :unmap a^I , :cunab x^I 4832 * EXPAND_FUNCTIONS Complete internal or user defined function names, 4833 * eg :call sub^I 4834 * EXPAND_USER_FUNC Complete user defined function names, eg :delf F^I 4835 * EXPAND_EXPRESSION Complete internal or user defined function/variable 4836 * names in expressions, eg :while s^I 4837 * EXPAND_ENV_VARS Complete environment variable names 4838 * EXPAND_USER Complete user names 4839 */ 4840 static void 4841 set_expand_context(expand_T *xp) 4842 { 4843 /* only expansion for ':', '>' and '=' command-lines */ 4844 if (ccline.cmdfirstc != ':' 4845 #ifdef FEAT_EVAL 4846 && ccline.cmdfirstc != '>' && ccline.cmdfirstc != '=' 4847 && !ccline.input_fn 4848 #endif 4849 ) 4850 { 4851 xp->xp_context = EXPAND_NOTHING; 4852 return; 4853 } 4854 set_cmd_context(xp, ccline.cmdbuff, ccline.cmdlen, ccline.cmdpos, TRUE); 4855 } 4856 4857 void 4858 set_cmd_context( 4859 expand_T *xp, 4860 char_u *str, /* start of command line */ 4861 int len, /* length of command line (excl. NUL) */ 4862 int col, /* position of cursor */ 4863 int use_ccline UNUSED) /* use ccline for info */ 4864 { 4865 int old_char = NUL; 4866 char_u *nextcomm; 4867 4868 /* 4869 * Avoid a UMR warning from Purify, only save the character if it has been 4870 * written before. 4871 */ 4872 if (col < len) 4873 old_char = str[col]; 4874 str[col] = NUL; 4875 nextcomm = str; 4876 4877 #ifdef FEAT_EVAL 4878 if (use_ccline && ccline.cmdfirstc == '=') 4879 { 4880 # ifdef FEAT_CMDL_COMPL 4881 /* pass CMD_SIZE because there is no real command */ 4882 set_context_for_expression(xp, str, CMD_SIZE); 4883 # endif 4884 } 4885 else if (use_ccline && ccline.input_fn) 4886 { 4887 xp->xp_context = ccline.xp_context; 4888 xp->xp_pattern = ccline.cmdbuff; 4889 # if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) 4890 xp->xp_arg = ccline.xp_arg; 4891 # endif 4892 } 4893 else 4894 #endif 4895 while (nextcomm != NULL) 4896 nextcomm = set_one_cmd_context(xp, nextcomm); 4897 4898 /* Store the string here so that call_user_expand_func() can get to them 4899 * easily. */ 4900 xp->xp_line = str; 4901 xp->xp_col = col; 4902 4903 str[col] = old_char; 4904 } 4905 4906 /* 4907 * Expand the command line "str" from context "xp". 4908 * "xp" must have been set by set_cmd_context(). 4909 * xp->xp_pattern points into "str", to where the text that is to be expanded 4910 * starts. 4911 * Returns EXPAND_UNSUCCESSFUL when there is something illegal before the 4912 * cursor. 4913 * Returns EXPAND_NOTHING when there is nothing to expand, might insert the 4914 * key that triggered expansion literally. 4915 * Returns EXPAND_OK otherwise. 4916 */ 4917 int 4918 expand_cmdline( 4919 expand_T *xp, 4920 char_u *str, /* start of command line */ 4921 int col, /* position of cursor */ 4922 int *matchcount, /* return: nr of matches */ 4923 char_u ***matches) /* return: array of pointers to matches */ 4924 { 4925 char_u *file_str = NULL; 4926 int options = WILD_ADD_SLASH|WILD_SILENT; 4927 4928 if (xp->xp_context == EXPAND_UNSUCCESSFUL) 4929 { 4930 beep_flush(); 4931 return EXPAND_UNSUCCESSFUL; /* Something illegal on command line */ 4932 } 4933 if (xp->xp_context == EXPAND_NOTHING) 4934 { 4935 /* Caller can use the character as a normal char instead */ 4936 return EXPAND_NOTHING; 4937 } 4938 4939 /* add star to file name, or convert to regexp if not exp. files. */ 4940 xp->xp_pattern_len = (int)(str + col - xp->xp_pattern); 4941 file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context); 4942 if (file_str == NULL) 4943 return EXPAND_UNSUCCESSFUL; 4944 4945 if (p_wic) 4946 options += WILD_ICASE; 4947 4948 /* find all files that match the description */ 4949 if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL) 4950 { 4951 *matchcount = 0; 4952 *matches = NULL; 4953 } 4954 vim_free(file_str); 4955 4956 return EXPAND_OK; 4957 } 4958 4959 #ifdef FEAT_MULTI_LANG 4960 /* 4961 * Cleanup matches for help tags: 4962 * Remove "@ab" if the top of 'helplang' is "ab" and the language of the first 4963 * tag matches it. Otherwise remove "@en" if "en" is the only language. 4964 */ 4965 static void 4966 cleanup_help_tags(int num_file, char_u **file) 4967 { 4968 int i, j; 4969 int len; 4970 char_u buf[4]; 4971 char_u *p = buf; 4972 4973 if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n')) 4974 { 4975 *p++ = '@'; 4976 *p++ = p_hlg[0]; 4977 *p++ = p_hlg[1]; 4978 } 4979 *p = NUL; 4980 4981 for (i = 0; i < num_file; ++i) 4982 { 4983 len = (int)STRLEN(file[i]) - 3; 4984 if (len <= 0) 4985 continue; 4986 if (STRCMP(file[i] + len, "@en") == 0) 4987 { 4988 /* Sorting on priority means the same item in another language may 4989 * be anywhere. Search all items for a match up to the "@en". */ 4990 for (j = 0; j < num_file; ++j) 4991 if (j != i && (int)STRLEN(file[j]) == len + 3 4992 && STRNCMP(file[i], file[j], len + 1) == 0) 4993 break; 4994 if (j == num_file) 4995 /* item only exists with @en, remove it */ 4996 file[i][len] = NUL; 4997 } 4998 } 4999 5000 if (*buf != NUL) 5001 for (i = 0; i < num_file; ++i) 5002 { 5003 len = (int)STRLEN(file[i]) - 3; 5004 if (len <= 0) 5005 continue; 5006 if (STRCMP(file[i] + len, buf) == 0) 5007 { 5008 /* remove the default language */ 5009 file[i][len] = NUL; 5010 } 5011 } 5012 } 5013 #endif 5014 5015 /* 5016 * Do the expansion based on xp->xp_context and "pat". 5017 */ 5018 static int 5019 ExpandFromContext( 5020 expand_T *xp, 5021 char_u *pat, 5022 int *num_file, 5023 char_u ***file, 5024 int options) /* EW_ flags */ 5025 { 5026 #ifdef FEAT_CMDL_COMPL 5027 regmatch_T regmatch; 5028 #endif 5029 int ret; 5030 int flags; 5031 5032 flags = EW_DIR; /* include directories */ 5033 if (options & WILD_LIST_NOTFOUND) 5034 flags |= EW_NOTFOUND; 5035 if (options & WILD_ADD_SLASH) 5036 flags |= EW_ADDSLASH; 5037 if (options & WILD_KEEP_ALL) 5038 flags |= EW_KEEPALL; 5039 if (options & WILD_SILENT) 5040 flags |= EW_SILENT; 5041 if (options & WILD_ALLLINKS) 5042 flags |= EW_ALLLINKS; 5043 5044 if (xp->xp_context == EXPAND_FILES 5045 || xp->xp_context == EXPAND_DIRECTORIES 5046 || xp->xp_context == EXPAND_FILES_IN_PATH) 5047 { 5048 /* 5049 * Expand file or directory names. 5050 */ 5051 int free_pat = FALSE; 5052 int i; 5053 5054 /* for ":set path=" and ":set tags=" halve backslashes for escaped 5055 * space */ 5056 if (xp->xp_backslash != XP_BS_NONE) 5057 { 5058 free_pat = TRUE; 5059 pat = vim_strsave(pat); 5060 for (i = 0; pat[i]; ++i) 5061 if (pat[i] == '\\') 5062 { 5063 if (xp->xp_backslash == XP_BS_THREE 5064 && pat[i + 1] == '\\' 5065 && pat[i + 2] == '\\' 5066 && pat[i + 3] == ' ') 5067 STRMOVE(pat + i, pat + i + 3); 5068 if (xp->xp_backslash == XP_BS_ONE 5069 && pat[i + 1] == ' ') 5070 STRMOVE(pat + i, pat + i + 1); 5071 } 5072 } 5073 5074 if (xp->xp_context == EXPAND_FILES) 5075 flags |= EW_FILE; 5076 else if (xp->xp_context == EXPAND_FILES_IN_PATH) 5077 flags |= (EW_FILE | EW_PATH); 5078 else 5079 flags = (flags | EW_DIR) & ~EW_FILE; 5080 if (options & WILD_ICASE) 5081 flags |= EW_ICASE; 5082 5083 /* Expand wildcards, supporting %:h and the like. */ 5084 ret = expand_wildcards_eval(&pat, num_file, file, flags); 5085 if (free_pat) 5086 vim_free(pat); 5087 return ret; 5088 } 5089 5090 *file = (char_u **)""; 5091 *num_file = 0; 5092 if (xp->xp_context == EXPAND_HELP) 5093 { 5094 /* With an empty argument we would get all the help tags, which is 5095 * very slow. Get matches for "help" instead. */ 5096 if (find_help_tags(*pat == NUL ? (char_u *)"help" : pat, 5097 num_file, file, FALSE) == OK) 5098 { 5099 #ifdef FEAT_MULTI_LANG 5100 cleanup_help_tags(*num_file, *file); 5101 #endif 5102 return OK; 5103 } 5104 return FAIL; 5105 } 5106 5107 #ifndef FEAT_CMDL_COMPL 5108 return FAIL; 5109 #else 5110 if (xp->xp_context == EXPAND_SHELLCMD) 5111 return expand_shellcmd(pat, num_file, file, flags); 5112 if (xp->xp_context == EXPAND_OLD_SETTING) 5113 return ExpandOldSetting(num_file, file); 5114 if (xp->xp_context == EXPAND_BUFFERS) 5115 return ExpandBufnames(pat, num_file, file, options); 5116 if (xp->xp_context == EXPAND_TAGS 5117 || xp->xp_context == EXPAND_TAGS_LISTFILES) 5118 return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file); 5119 if (xp->xp_context == EXPAND_COLORS) 5120 { 5121 char *directories[] = {"colors", NULL}; 5122 return ExpandRTDir(pat, DIP_START + DIP_OPT, num_file, file, 5123 directories); 5124 } 5125 if (xp->xp_context == EXPAND_COMPILER) 5126 { 5127 char *directories[] = {"compiler", NULL}; 5128 return ExpandRTDir(pat, 0, num_file, file, directories); 5129 } 5130 if (xp->xp_context == EXPAND_OWNSYNTAX) 5131 { 5132 char *directories[] = {"syntax", NULL}; 5133 return ExpandRTDir(pat, 0, num_file, file, directories); 5134 } 5135 if (xp->xp_context == EXPAND_FILETYPE) 5136 { 5137 char *directories[] = {"syntax", "indent", "ftplugin", NULL}; 5138 return ExpandRTDir(pat, 0, num_file, file, directories); 5139 } 5140 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) 5141 if (xp->xp_context == EXPAND_USER_LIST) 5142 return ExpandUserList(xp, num_file, file); 5143 # endif 5144 if (xp->xp_context == EXPAND_PACKADD) 5145 return ExpandPackAddDir(pat, num_file, file); 5146 5147 regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0); 5148 if (regmatch.regprog == NULL) 5149 return FAIL; 5150 5151 /* set ignore-case according to p_ic, p_scs and pat */ 5152 regmatch.rm_ic = ignorecase(pat); 5153 5154 if (xp->xp_context == EXPAND_SETTINGS 5155 || xp->xp_context == EXPAND_BOOL_SETTINGS) 5156 ret = ExpandSettings(xp, ®match, num_file, file); 5157 else if (xp->xp_context == EXPAND_MAPPINGS) 5158 ret = ExpandMappings(®match, num_file, file); 5159 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) 5160 else if (xp->xp_context == EXPAND_USER_DEFINED) 5161 ret = ExpandUserDefined(xp, ®match, num_file, file); 5162 # endif 5163 else 5164 { 5165 static struct expgen 5166 { 5167 int context; 5168 char_u *((*func)(expand_T *, int)); 5169 int ic; 5170 int escaped; 5171 } tab[] = 5172 { 5173 {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, 5174 {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, 5175 {EXPAND_MAPCLEAR, get_mapclear_arg, TRUE, TRUE}, 5176 {EXPAND_MESSAGES, get_messages_arg, TRUE, TRUE}, 5177 #ifdef FEAT_CMDHIST 5178 {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, 5179 #endif 5180 #ifdef FEAT_USR_CMDS 5181 {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, 5182 {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE}, 5183 {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, 5184 {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, 5185 {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, 5186 #endif 5187 #ifdef FEAT_EVAL 5188 {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, 5189 {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, 5190 {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, 5191 {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, 5192 #endif 5193 #ifdef FEAT_MENU 5194 {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, 5195 {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, 5196 #endif 5197 #ifdef FEAT_SYN_HL 5198 {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, 5199 #endif 5200 #ifdef FEAT_PROFILE 5201 {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, 5202 #endif 5203 {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, 5204 {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, 5205 {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, 5206 #ifdef FEAT_CSCOPE 5207 {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, 5208 #endif 5209 #ifdef FEAT_SIGNS 5210 {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, 5211 #endif 5212 #ifdef FEAT_PROFILE 5213 {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, 5214 #endif 5215 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 5216 {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, 5217 {EXPAND_LOCALES, get_locales, TRUE, FALSE}, 5218 #endif 5219 {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, 5220 {EXPAND_USER, get_users, TRUE, FALSE}, 5221 {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, 5222 }; 5223 int i; 5224 5225 /* 5226 * Find a context in the table and call the ExpandGeneric() with the 5227 * right function to do the expansion. 5228 */ 5229 ret = FAIL; 5230 for (i = 0; i < (int)(sizeof(tab) / sizeof(struct expgen)); ++i) 5231 if (xp->xp_context == tab[i].context) 5232 { 5233 if (tab[i].ic) 5234 regmatch.rm_ic = TRUE; 5235 ret = ExpandGeneric(xp, ®match, num_file, file, 5236 tab[i].func, tab[i].escaped); 5237 break; 5238 } 5239 } 5240 5241 vim_regfree(regmatch.regprog); 5242 5243 return ret; 5244 #endif /* FEAT_CMDL_COMPL */ 5245 } 5246 5247 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 5248 /* 5249 * Expand a list of names. 5250 * 5251 * Generic function for command line completion. It calls a function to 5252 * obtain strings, one by one. The strings are matched against a regexp 5253 * program. Matching strings are copied into an array, which is returned. 5254 * 5255 * Returns OK when no problems encountered, FAIL for error (out of memory). 5256 */ 5257 int 5258 ExpandGeneric( 5259 expand_T *xp, 5260 regmatch_T *regmatch, 5261 int *num_file, 5262 char_u ***file, 5263 char_u *((*func)(expand_T *, int)), 5264 /* returns a string from the list */ 5265 int escaped) 5266 { 5267 int i; 5268 int count = 0; 5269 int round; 5270 char_u *str; 5271 5272 /* do this loop twice: 5273 * round == 0: count the number of matching names 5274 * round == 1: copy the matching names into allocated memory 5275 */ 5276 for (round = 0; round <= 1; ++round) 5277 { 5278 for (i = 0; ; ++i) 5279 { 5280 str = (*func)(xp, i); 5281 if (str == NULL) /* end of list */ 5282 break; 5283 if (*str == NUL) /* skip empty strings */ 5284 continue; 5285 5286 if (vim_regexec(regmatch, str, (colnr_T)0)) 5287 { 5288 if (round) 5289 { 5290 if (escaped) 5291 str = vim_strsave_escaped(str, (char_u *)" \t\\."); 5292 else 5293 str = vim_strsave(str); 5294 (*file)[count] = str; 5295 #ifdef FEAT_MENU 5296 if (func == get_menu_names && str != NULL) 5297 { 5298 /* test for separator added by get_menu_names() */ 5299 str += STRLEN(str) - 1; 5300 if (*str == '\001') 5301 *str = '.'; 5302 } 5303 #endif 5304 } 5305 ++count; 5306 } 5307 } 5308 if (round == 0) 5309 { 5310 if (count == 0) 5311 return OK; 5312 *num_file = count; 5313 *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *))); 5314 if (*file == NULL) 5315 { 5316 *file = (char_u **)""; 5317 return FAIL; 5318 } 5319 count = 0; 5320 } 5321 } 5322 5323 /* Sort the results. Keep menu's in the specified order. */ 5324 if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) 5325 { 5326 if (xp->xp_context == EXPAND_EXPRESSION 5327 || xp->xp_context == EXPAND_FUNCTIONS 5328 || xp->xp_context == EXPAND_USER_FUNC) 5329 /* <SNR> functions should be sorted to the end. */ 5330 qsort((void *)*file, (size_t)*num_file, sizeof(char_u *), 5331 sort_func_compare); 5332 else 5333 sort_strings(*file, *num_file); 5334 } 5335 5336 #ifdef FEAT_CMDL_COMPL 5337 /* Reset the variables used for special highlight names expansion, so that 5338 * they don't show up when getting normal highlight names by ID. */ 5339 reset_expand_highlight(); 5340 #endif 5341 5342 return OK; 5343 } 5344 5345 /* 5346 * Complete a shell command. 5347 * Returns FAIL or OK; 5348 */ 5349 static int 5350 expand_shellcmd( 5351 char_u *filepat, /* pattern to match with command names */ 5352 int *num_file, /* return: number of matches */ 5353 char_u ***file, /* return: array with matches */ 5354 int flagsarg) /* EW_ flags */ 5355 { 5356 char_u *pat; 5357 int i; 5358 char_u *path = NULL; 5359 int mustfree = FALSE; 5360 garray_T ga; 5361 char_u *buf = alloc(MAXPATHL); 5362 size_t l; 5363 char_u *s, *e; 5364 int flags = flagsarg; 5365 int ret; 5366 int did_curdir = FALSE; 5367 hashtab_T found_ht; 5368 hashitem_T *hi; 5369 hash_T hash; 5370 5371 if (buf == NULL) 5372 return FAIL; 5373 5374 /* for ":set path=" and ":set tags=" halve backslashes for escaped 5375 * space */ 5376 pat = vim_strsave(filepat); 5377 for (i = 0; pat[i]; ++i) 5378 if (pat[i] == '\\' && pat[i + 1] == ' ') 5379 STRMOVE(pat + i, pat + i + 1); 5380 5381 flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; 5382 5383 if (pat[0] == '.' && (vim_ispathsep(pat[1]) 5384 || (pat[1] == '.' && vim_ispathsep(pat[2])))) 5385 path = (char_u *)"."; 5386 else 5387 { 5388 /* For an absolute name we don't use $PATH. */ 5389 if (!mch_isFullName(pat)) 5390 path = vim_getenv((char_u *)"PATH", &mustfree); 5391 if (path == NULL) 5392 path = (char_u *)""; 5393 } 5394 5395 /* 5396 * Go over all directories in $PATH. Expand matches in that directory and 5397 * collect them in "ga". When "." is not in $PATH also expand for the 5398 * current directory, to find "subdir/cmd". 5399 */ 5400 ga_init2(&ga, (int)sizeof(char *), 10); 5401 hash_init(&found_ht); 5402 for (s = path; ; s = e) 5403 { 5404 #if defined(MSWIN) 5405 e = vim_strchr(s, ';'); 5406 #else 5407 e = vim_strchr(s, ':'); 5408 #endif 5409 if (e == NULL) 5410 e = s + STRLEN(s); 5411 5412 if (*s == NUL) 5413 { 5414 if (did_curdir) 5415 break; 5416 // Find directories in the current directory, path is empty. 5417 did_curdir = TRUE; 5418 flags |= EW_DIR; 5419 } 5420 else if (STRNCMP(s, ".", (int)(e - s)) == 0) 5421 { 5422 did_curdir = TRUE; 5423 flags |= EW_DIR; 5424 } 5425 else 5426 // Do not match directories inside a $PATH item. 5427 flags &= ~EW_DIR; 5428 5429 l = e - s; 5430 if (l > MAXPATHL - 5) 5431 break; 5432 vim_strncpy(buf, s, l); 5433 add_pathsep(buf); 5434 l = STRLEN(buf); 5435 vim_strncpy(buf + l, pat, MAXPATHL - 1 - l); 5436 5437 /* Expand matches in one directory of $PATH. */ 5438 ret = expand_wildcards(1, &buf, num_file, file, flags); 5439 if (ret == OK) 5440 { 5441 if (ga_grow(&ga, *num_file) == FAIL) 5442 FreeWild(*num_file, *file); 5443 else 5444 { 5445 for (i = 0; i < *num_file; ++i) 5446 { 5447 char_u *name = (*file)[i]; 5448 5449 if (STRLEN(name) > l) 5450 { 5451 // Check if this name was already found. 5452 hash = hash_hash(name + l); 5453 hi = hash_lookup(&found_ht, name + l, hash); 5454 if (HASHITEM_EMPTY(hi)) 5455 { 5456 // Remove the path that was prepended. 5457 STRMOVE(name, name + l); 5458 ((char_u **)ga.ga_data)[ga.ga_len++] = name; 5459 hash_add_item(&found_ht, hi, name, hash); 5460 name = NULL; 5461 } 5462 } 5463 vim_free(name); 5464 } 5465 vim_free(*file); 5466 } 5467 } 5468 if (*e != NUL) 5469 ++e; 5470 } 5471 *file = ga.ga_data; 5472 *num_file = ga.ga_len; 5473 5474 vim_free(buf); 5475 vim_free(pat); 5476 if (mustfree) 5477 vim_free(path); 5478 hash_clear(&found_ht); 5479 return OK; 5480 } 5481 5482 5483 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) 5484 /* 5485 * Call "user_expand_func()" to invoke a user defined Vim script function and 5486 * return the result (either a string or a List). 5487 */ 5488 static void * 5489 call_user_expand_func( 5490 void *(*user_expand_func)(char_u *, int, typval_T *), 5491 expand_T *xp, 5492 int *num_file, 5493 char_u ***file) 5494 { 5495 int keep = 0; 5496 typval_T args[4]; 5497 sctx_T save_current_sctx = current_sctx; 5498 char_u *pat = NULL; 5499 void *ret; 5500 5501 if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) 5502 return NULL; 5503 *num_file = 0; 5504 *file = NULL; 5505 5506 if (ccline.cmdbuff != NULL) 5507 { 5508 keep = ccline.cmdbuff[ccline.cmdlen]; 5509 ccline.cmdbuff[ccline.cmdlen] = 0; 5510 } 5511 5512 pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len); 5513 5514 args[0].v_type = VAR_STRING; 5515 args[0].vval.v_string = pat; 5516 args[1].v_type = VAR_STRING; 5517 args[1].vval.v_string = xp->xp_line; 5518 args[2].v_type = VAR_NUMBER; 5519 args[2].vval.v_number = xp->xp_col; 5520 args[3].v_type = VAR_UNKNOWN; 5521 5522 current_sctx = xp->xp_script_ctx; 5523 5524 ret = user_expand_func(xp->xp_arg, 3, args); 5525 5526 current_sctx = save_current_sctx; 5527 if (ccline.cmdbuff != NULL) 5528 ccline.cmdbuff[ccline.cmdlen] = keep; 5529 5530 vim_free(pat); 5531 return ret; 5532 } 5533 5534 /* 5535 * Expand names with a function defined by the user. 5536 */ 5537 static int 5538 ExpandUserDefined( 5539 expand_T *xp, 5540 regmatch_T *regmatch, 5541 int *num_file, 5542 char_u ***file) 5543 { 5544 char_u *retstr; 5545 char_u *s; 5546 char_u *e; 5547 int keep; 5548 garray_T ga; 5549 int skip; 5550 5551 retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); 5552 if (retstr == NULL) 5553 return FAIL; 5554 5555 ga_init2(&ga, (int)sizeof(char *), 3); 5556 for (s = retstr; *s != NUL; s = e) 5557 { 5558 e = vim_strchr(s, '\n'); 5559 if (e == NULL) 5560 e = s + STRLEN(s); 5561 keep = *e; 5562 *e = NUL; 5563 5564 skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0; 5565 *e = keep; 5566 5567 if (!skip) 5568 { 5569 if (ga_grow(&ga, 1) == FAIL) 5570 break; 5571 ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, (int)(e - s)); 5572 ++ga.ga_len; 5573 } 5574 5575 if (*e != NUL) 5576 ++e; 5577 } 5578 vim_free(retstr); 5579 *file = ga.ga_data; 5580 *num_file = ga.ga_len; 5581 return OK; 5582 } 5583 5584 /* 5585 * Expand names with a list returned by a function defined by the user. 5586 */ 5587 static int 5588 ExpandUserList( 5589 expand_T *xp, 5590 int *num_file, 5591 char_u ***file) 5592 { 5593 list_T *retlist; 5594 listitem_T *li; 5595 garray_T ga; 5596 5597 retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); 5598 if (retlist == NULL) 5599 return FAIL; 5600 5601 ga_init2(&ga, (int)sizeof(char *), 3); 5602 /* Loop over the items in the list. */ 5603 for (li = retlist->lv_first; li != NULL; li = li->li_next) 5604 { 5605 if (li->li_tv.v_type != VAR_STRING || li->li_tv.vval.v_string == NULL) 5606 continue; /* Skip non-string items and empty strings */ 5607 5608 if (ga_grow(&ga, 1) == FAIL) 5609 break; 5610 5611 ((char_u **)ga.ga_data)[ga.ga_len] = 5612 vim_strsave(li->li_tv.vval.v_string); 5613 ++ga.ga_len; 5614 } 5615 list_unref(retlist); 5616 5617 *file = ga.ga_data; 5618 *num_file = ga.ga_len; 5619 return OK; 5620 } 5621 #endif 5622 5623 /* 5624 * Expand color scheme, compiler or filetype names. 5625 * Search from 'runtimepath': 5626 * 'runtimepath'/{dirnames}/{pat}.vim 5627 * When "flags" has DIP_START: search also from 'start' of 'packpath': 5628 * 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim 5629 * When "flags" has DIP_OPT: search also from 'opt' of 'packpath': 5630 * 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim 5631 * "dirnames" is an array with one or more directory names. 5632 */ 5633 static int 5634 ExpandRTDir( 5635 char_u *pat, 5636 int flags, 5637 int *num_file, 5638 char_u ***file, 5639 char *dirnames[]) 5640 { 5641 char_u *s; 5642 char_u *e; 5643 char_u *match; 5644 garray_T ga; 5645 int i; 5646 int pat_len; 5647 5648 *num_file = 0; 5649 *file = NULL; 5650 pat_len = (int)STRLEN(pat); 5651 ga_init2(&ga, (int)sizeof(char *), 10); 5652 5653 for (i = 0; dirnames[i] != NULL; ++i) 5654 { 5655 s = alloc((unsigned)(STRLEN(dirnames[i]) + pat_len + 7)); 5656 if (s == NULL) 5657 { 5658 ga_clear_strings(&ga); 5659 return FAIL; 5660 } 5661 sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); 5662 globpath(p_rtp, s, &ga, 0); 5663 vim_free(s); 5664 } 5665 5666 if (flags & DIP_START) { 5667 for (i = 0; dirnames[i] != NULL; ++i) 5668 { 5669 s = alloc((unsigned)(STRLEN(dirnames[i]) + pat_len + 22)); 5670 if (s == NULL) 5671 { 5672 ga_clear_strings(&ga); 5673 return FAIL; 5674 } 5675 sprintf((char *)s, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); 5676 globpath(p_pp, s, &ga, 0); 5677 vim_free(s); 5678 } 5679 } 5680 5681 if (flags & DIP_OPT) { 5682 for (i = 0; dirnames[i] != NULL; ++i) 5683 { 5684 s = alloc((unsigned)(STRLEN(dirnames[i]) + pat_len + 20)); 5685 if (s == NULL) 5686 { 5687 ga_clear_strings(&ga); 5688 return FAIL; 5689 } 5690 sprintf((char *)s, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); 5691 globpath(p_pp, s, &ga, 0); 5692 vim_free(s); 5693 } 5694 } 5695 5696 for (i = 0; i < ga.ga_len; ++i) 5697 { 5698 match = ((char_u **)ga.ga_data)[i]; 5699 s = match; 5700 e = s + STRLEN(s); 5701 if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) 5702 { 5703 e -= 4; 5704 for (s = e; s > match; MB_PTR_BACK(match, s)) 5705 if (s < match || vim_ispathsep(*s)) 5706 break; 5707 ++s; 5708 *e = NUL; 5709 mch_memmove(match, s, e - s + 1); 5710 } 5711 } 5712 5713 if (ga.ga_len == 0) 5714 return FAIL; 5715 5716 /* Sort and remove duplicates which can happen when specifying multiple 5717 * directories in dirnames. */ 5718 remove_duplicates(&ga); 5719 5720 *file = ga.ga_data; 5721 *num_file = ga.ga_len; 5722 return OK; 5723 } 5724 5725 /* 5726 * Expand loadplugin names: 5727 * 'packpath'/pack/ * /opt/{pat} 5728 */ 5729 static int 5730 ExpandPackAddDir( 5731 char_u *pat, 5732 int *num_file, 5733 char_u ***file) 5734 { 5735 char_u *s; 5736 char_u *e; 5737 char_u *match; 5738 garray_T ga; 5739 int i; 5740 int pat_len; 5741 5742 *num_file = 0; 5743 *file = NULL; 5744 pat_len = (int)STRLEN(pat); 5745 ga_init2(&ga, (int)sizeof(char *), 10); 5746 5747 s = alloc((unsigned)(pat_len + 26)); 5748 if (s == NULL) 5749 { 5750 ga_clear_strings(&ga); 5751 return FAIL; 5752 } 5753 sprintf((char *)s, "pack/*/opt/%s*", pat); 5754 globpath(p_pp, s, &ga, 0); 5755 vim_free(s); 5756 5757 for (i = 0; i < ga.ga_len; ++i) 5758 { 5759 match = ((char_u **)ga.ga_data)[i]; 5760 s = gettail(match); 5761 e = s + STRLEN(s); 5762 mch_memmove(match, s, e - s + 1); 5763 } 5764 5765 if (ga.ga_len == 0) 5766 return FAIL; 5767 5768 /* Sort and remove duplicates which can happen when specifying multiple 5769 * directories in dirnames. */ 5770 remove_duplicates(&ga); 5771 5772 *file = ga.ga_data; 5773 *num_file = ga.ga_len; 5774 return OK; 5775 } 5776 5777 #endif 5778 5779 #if defined(FEAT_CMDL_COMPL) || defined(FEAT_EVAL) || defined(PROTO) 5780 /* 5781 * Expand "file" for all comma-separated directories in "path". 5782 * Adds the matches to "ga". Caller must init "ga". 5783 */ 5784 void 5785 globpath( 5786 char_u *path, 5787 char_u *file, 5788 garray_T *ga, 5789 int expand_options) 5790 { 5791 expand_T xpc; 5792 char_u *buf; 5793 int i; 5794 int num_p; 5795 char_u **p; 5796 5797 buf = alloc(MAXPATHL); 5798 if (buf == NULL) 5799 return; 5800 5801 ExpandInit(&xpc); 5802 xpc.xp_context = EXPAND_FILES; 5803 5804 /* Loop over all entries in {path}. */ 5805 while (*path != NUL) 5806 { 5807 /* Copy one item of the path to buf[] and concatenate the file name. */ 5808 copy_option_part(&path, buf, MAXPATHL, ","); 5809 if (STRLEN(buf) + STRLEN(file) + 2 < MAXPATHL) 5810 { 5811 # if defined(MSWIN) 5812 /* Using the platform's path separator (\) makes vim incorrectly 5813 * treat it as an escape character, use '/' instead. */ 5814 if (*buf != NUL && !after_pathsep(buf, buf + STRLEN(buf))) 5815 STRCAT(buf, "/"); 5816 # else 5817 add_pathsep(buf); 5818 # endif 5819 STRCAT(buf, file); 5820 if (ExpandFromContext(&xpc, buf, &num_p, &p, 5821 WILD_SILENT|expand_options) != FAIL && num_p > 0) 5822 { 5823 ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); 5824 5825 if (ga_grow(ga, num_p) == OK) 5826 { 5827 for (i = 0; i < num_p; ++i) 5828 { 5829 ((char_u **)ga->ga_data)[ga->ga_len] = 5830 vim_strnsave(p[i], (int)STRLEN(p[i])); 5831 ++ga->ga_len; 5832 } 5833 } 5834 5835 FreeWild(num_p, p); 5836 } 5837 } 5838 } 5839 5840 vim_free(buf); 5841 } 5842 5843 #endif 5844 5845 #if defined(FEAT_CMDHIST) || defined(PROTO) 5846 5847 /********************************* 5848 * Command line history stuff * 5849 *********************************/ 5850 5851 /* 5852 * Translate a history character to the associated type number. 5853 */ 5854 static int 5855 hist_char2type(int c) 5856 { 5857 if (c == ':') 5858 return HIST_CMD; 5859 if (c == '=') 5860 return HIST_EXPR; 5861 if (c == '@') 5862 return HIST_INPUT; 5863 if (c == '>') 5864 return HIST_DEBUG; 5865 return HIST_SEARCH; /* must be '?' or '/' */ 5866 } 5867 5868 /* 5869 * Table of history names. 5870 * These names are used in :history and various hist...() functions. 5871 * It is sufficient to give the significant prefix of a history name. 5872 */ 5873 5874 static char *(history_names[]) = 5875 { 5876 "cmd", 5877 "search", 5878 "expr", 5879 "input", 5880 "debug", 5881 NULL 5882 }; 5883 5884 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 5885 /* 5886 * Function given to ExpandGeneric() to obtain the possible first 5887 * arguments of the ":history command. 5888 */ 5889 static char_u * 5890 get_history_arg(expand_T *xp UNUSED, int idx) 5891 { 5892 static char_u compl[2] = { NUL, NUL }; 5893 char *short_names = ":=@>?/"; 5894 int short_names_count = (int)STRLEN(short_names); 5895 int history_name_count = sizeof(history_names) / sizeof(char *) - 1; 5896 5897 if (idx < short_names_count) 5898 { 5899 compl[0] = (char_u)short_names[idx]; 5900 return compl; 5901 } 5902 if (idx < short_names_count + history_name_count) 5903 return (char_u *)history_names[idx - short_names_count]; 5904 if (idx == short_names_count + history_name_count) 5905 return (char_u *)"all"; 5906 return NULL; 5907 } 5908 #endif 5909 5910 /* 5911 * init_history() - Initialize the command line history. 5912 * Also used to re-allocate the history when the size changes. 5913 */ 5914 void 5915 init_history(void) 5916 { 5917 int newlen; /* new length of history table */ 5918 histentry_T *temp; 5919 int i; 5920 int j; 5921 int type; 5922 5923 /* 5924 * If size of history table changed, reallocate it 5925 */ 5926 newlen = (int)p_hi; 5927 if (newlen != hislen) /* history length changed */ 5928 { 5929 for (type = 0; type < HIST_COUNT; ++type) /* adjust the tables */ 5930 { 5931 if (newlen) 5932 { 5933 temp = (histentry_T *)lalloc( 5934 (long_u)(newlen * sizeof(histentry_T)), TRUE); 5935 if (temp == NULL) /* out of memory! */ 5936 { 5937 if (type == 0) /* first one: just keep the old length */ 5938 { 5939 newlen = hislen; 5940 break; 5941 } 5942 /* Already changed one table, now we can only have zero 5943 * length for all tables. */ 5944 newlen = 0; 5945 type = -1; 5946 continue; 5947 } 5948 } 5949 else 5950 temp = NULL; 5951 if (newlen == 0 || temp != NULL) 5952 { 5953 if (hisidx[type] < 0) /* there are no entries yet */ 5954 { 5955 for (i = 0; i < newlen; ++i) 5956 clear_hist_entry(&temp[i]); 5957 } 5958 else if (newlen > hislen) /* array becomes bigger */ 5959 { 5960 for (i = 0; i <= hisidx[type]; ++i) 5961 temp[i] = history[type][i]; 5962 j = i; 5963 for ( ; i <= newlen - (hislen - hisidx[type]); ++i) 5964 clear_hist_entry(&temp[i]); 5965 for ( ; j < hislen; ++i, ++j) 5966 temp[i] = history[type][j]; 5967 } 5968 else /* array becomes smaller or 0 */ 5969 { 5970 j = hisidx[type]; 5971 for (i = newlen - 1; ; --i) 5972 { 5973 if (i >= 0) /* copy newest entries */ 5974 temp[i] = history[type][j]; 5975 else /* remove older entries */ 5976 vim_free(history[type][j].hisstr); 5977 if (--j < 0) 5978 j = hislen - 1; 5979 if (j == hisidx[type]) 5980 break; 5981 } 5982 hisidx[type] = newlen - 1; 5983 } 5984 vim_free(history[type]); 5985 history[type] = temp; 5986 } 5987 } 5988 hislen = newlen; 5989 } 5990 } 5991 5992 static void 5993 clear_hist_entry(histentry_T *hisptr) 5994 { 5995 hisptr->hisnum = 0; 5996 hisptr->viminfo = FALSE; 5997 hisptr->hisstr = NULL; 5998 hisptr->time_set = 0; 5999 } 6000 6001 /* 6002 * Check if command line 'str' is already in history. 6003 * If 'move_to_front' is TRUE, matching entry is moved to end of history. 6004 */ 6005 static int 6006 in_history( 6007 int type, 6008 char_u *str, 6009 int move_to_front, /* Move the entry to the front if it exists */ 6010 int sep, 6011 int writing) /* ignore entries read from viminfo */ 6012 { 6013 int i; 6014 int last_i = -1; 6015 char_u *p; 6016 6017 if (hisidx[type] < 0) 6018 return FALSE; 6019 i = hisidx[type]; 6020 do 6021 { 6022 if (history[type][i].hisstr == NULL) 6023 return FALSE; 6024 6025 /* For search history, check that the separator character matches as 6026 * well. */ 6027 p = history[type][i].hisstr; 6028 if (STRCMP(str, p) == 0 6029 && !(writing && history[type][i].viminfo) 6030 && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) 6031 { 6032 if (!move_to_front) 6033 return TRUE; 6034 last_i = i; 6035 break; 6036 } 6037 if (--i < 0) 6038 i = hislen - 1; 6039 } while (i != hisidx[type]); 6040 6041 if (last_i >= 0) 6042 { 6043 str = history[type][i].hisstr; 6044 while (i != hisidx[type]) 6045 { 6046 if (++i >= hislen) 6047 i = 0; 6048 history[type][last_i] = history[type][i]; 6049 last_i = i; 6050 } 6051 history[type][i].hisnum = ++hisnum[type]; 6052 history[type][i].viminfo = FALSE; 6053 history[type][i].hisstr = str; 6054 history[type][i].time_set = vim_time(); 6055 return TRUE; 6056 } 6057 return FALSE; 6058 } 6059 6060 /* 6061 * Convert history name (from table above) to its HIST_ equivalent. 6062 * When "name" is empty, return "cmd" history. 6063 * Returns -1 for unknown history name. 6064 */ 6065 int 6066 get_histtype(char_u *name) 6067 { 6068 int i; 6069 int len = (int)STRLEN(name); 6070 6071 /* No argument: use current history. */ 6072 if (len == 0) 6073 return hist_char2type(ccline.cmdfirstc); 6074 6075 for (i = 0; history_names[i] != NULL; ++i) 6076 if (STRNICMP(name, history_names[i], len) == 0) 6077 return i; 6078 6079 if (vim_strchr((char_u *)":=@>?/", name[0]) != NULL && name[1] == NUL) 6080 return hist_char2type(name[0]); 6081 6082 return -1; 6083 } 6084 6085 static int last_maptick = -1; /* last seen maptick */ 6086 6087 /* 6088 * Add the given string to the given history. If the string is already in the 6089 * history then it is moved to the front. "histype" may be one of he HIST_ 6090 * values. 6091 */ 6092 void 6093 add_to_history( 6094 int histype, 6095 char_u *new_entry, 6096 int in_map, /* consider maptick when inside a mapping */ 6097 int sep) /* separator character used (search hist) */ 6098 { 6099 histentry_T *hisptr; 6100 int len; 6101 6102 if (hislen == 0) /* no history */ 6103 return; 6104 6105 if (cmdmod.keeppatterns && histype == HIST_SEARCH) 6106 return; 6107 6108 /* 6109 * Searches inside the same mapping overwrite each other, so that only 6110 * the last line is kept. Be careful not to remove a line that was moved 6111 * down, only lines that were added. 6112 */ 6113 if (histype == HIST_SEARCH && in_map) 6114 { 6115 if (maptick == last_maptick && hisidx[HIST_SEARCH] >= 0) 6116 { 6117 /* Current line is from the same mapping, remove it */ 6118 hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]]; 6119 vim_free(hisptr->hisstr); 6120 clear_hist_entry(hisptr); 6121 --hisnum[histype]; 6122 if (--hisidx[HIST_SEARCH] < 0) 6123 hisidx[HIST_SEARCH] = hislen - 1; 6124 } 6125 last_maptick = -1; 6126 } 6127 if (!in_history(histype, new_entry, TRUE, sep, FALSE)) 6128 { 6129 if (++hisidx[histype] == hislen) 6130 hisidx[histype] = 0; 6131 hisptr = &history[histype][hisidx[histype]]; 6132 vim_free(hisptr->hisstr); 6133 6134 /* Store the separator after the NUL of the string. */ 6135 len = (int)STRLEN(new_entry); 6136 hisptr->hisstr = vim_strnsave(new_entry, len + 2); 6137 if (hisptr->hisstr != NULL) 6138 hisptr->hisstr[len + 1] = sep; 6139 6140 hisptr->hisnum = ++hisnum[histype]; 6141 hisptr->viminfo = FALSE; 6142 hisptr->time_set = vim_time(); 6143 if (histype == HIST_SEARCH && in_map) 6144 last_maptick = maptick; 6145 } 6146 } 6147 6148 #if defined(FEAT_EVAL) || defined(PROTO) 6149 6150 /* 6151 * Get identifier of newest history entry. 6152 * "histype" may be one of the HIST_ values. 6153 */ 6154 int 6155 get_history_idx(int histype) 6156 { 6157 if (hislen == 0 || histype < 0 || histype >= HIST_COUNT 6158 || hisidx[histype] < 0) 6159 return -1; 6160 6161 return history[histype][hisidx[histype]].hisnum; 6162 } 6163 6164 /* 6165 * Calculate history index from a number: 6166 * num > 0: seen as identifying number of a history entry 6167 * num < 0: relative position in history wrt newest entry 6168 * "histype" may be one of the HIST_ values. 6169 */ 6170 static int 6171 calc_hist_idx(int histype, int num) 6172 { 6173 int i; 6174 histentry_T *hist; 6175 int wrapped = FALSE; 6176 6177 if (hislen == 0 || histype < 0 || histype >= HIST_COUNT 6178 || (i = hisidx[histype]) < 0 || num == 0) 6179 return -1; 6180 6181 hist = history[histype]; 6182 if (num > 0) 6183 { 6184 while (hist[i].hisnum > num) 6185 if (--i < 0) 6186 { 6187 if (wrapped) 6188 break; 6189 i += hislen; 6190 wrapped = TRUE; 6191 } 6192 if (hist[i].hisnum == num && hist[i].hisstr != NULL) 6193 return i; 6194 } 6195 else if (-num <= hislen) 6196 { 6197 i += num + 1; 6198 if (i < 0) 6199 i += hislen; 6200 if (hist[i].hisstr != NULL) 6201 return i; 6202 } 6203 return -1; 6204 } 6205 6206 /* 6207 * Get a history entry by its index. 6208 * "histype" may be one of the HIST_ values. 6209 */ 6210 char_u * 6211 get_history_entry(int histype, int idx) 6212 { 6213 idx = calc_hist_idx(histype, idx); 6214 if (idx >= 0) 6215 return history[histype][idx].hisstr; 6216 else 6217 return (char_u *)""; 6218 } 6219 6220 /* 6221 * Clear all entries of a history. 6222 * "histype" may be one of the HIST_ values. 6223 */ 6224 int 6225 clr_history(int histype) 6226 { 6227 int i; 6228 histentry_T *hisptr; 6229 6230 if (hislen != 0 && histype >= 0 && histype < HIST_COUNT) 6231 { 6232 hisptr = history[histype]; 6233 for (i = hislen; i--;) 6234 { 6235 vim_free(hisptr->hisstr); 6236 clear_hist_entry(hisptr); 6237 hisptr++; 6238 } 6239 hisidx[histype] = -1; /* mark history as cleared */ 6240 hisnum[histype] = 0; /* reset identifier counter */ 6241 return OK; 6242 } 6243 return FAIL; 6244 } 6245 6246 /* 6247 * Remove all entries matching {str} from a history. 6248 * "histype" may be one of the HIST_ values. 6249 */ 6250 int 6251 del_history_entry(int histype, char_u *str) 6252 { 6253 regmatch_T regmatch; 6254 histentry_T *hisptr; 6255 int idx; 6256 int i; 6257 int last; 6258 int found = FALSE; 6259 6260 regmatch.regprog = NULL; 6261 regmatch.rm_ic = FALSE; /* always match case */ 6262 if (hislen != 0 6263 && histype >= 0 6264 && histype < HIST_COUNT 6265 && *str != NUL 6266 && (idx = hisidx[histype]) >= 0 6267 && (regmatch.regprog = vim_regcomp(str, RE_MAGIC + RE_STRING)) 6268 != NULL) 6269 { 6270 i = last = idx; 6271 do 6272 { 6273 hisptr = &history[histype][i]; 6274 if (hisptr->hisstr == NULL) 6275 break; 6276 if (vim_regexec(®match, hisptr->hisstr, (colnr_T)0)) 6277 { 6278 found = TRUE; 6279 vim_free(hisptr->hisstr); 6280 clear_hist_entry(hisptr); 6281 } 6282 else 6283 { 6284 if (i != last) 6285 { 6286 history[histype][last] = *hisptr; 6287 clear_hist_entry(hisptr); 6288 } 6289 if (--last < 0) 6290 last += hislen; 6291 } 6292 if (--i < 0) 6293 i += hislen; 6294 } while (i != idx); 6295 if (history[histype][idx].hisstr == NULL) 6296 hisidx[histype] = -1; 6297 } 6298 vim_regfree(regmatch.regprog); 6299 return found; 6300 } 6301 6302 /* 6303 * Remove an indexed entry from a history. 6304 * "histype" may be one of the HIST_ values. 6305 */ 6306 int 6307 del_history_idx(int histype, int idx) 6308 { 6309 int i, j; 6310 6311 i = calc_hist_idx(histype, idx); 6312 if (i < 0) 6313 return FALSE; 6314 idx = hisidx[histype]; 6315 vim_free(history[histype][i].hisstr); 6316 6317 /* When deleting the last added search string in a mapping, reset 6318 * last_maptick, so that the last added search string isn't deleted again. 6319 */ 6320 if (histype == HIST_SEARCH && maptick == last_maptick && i == idx) 6321 last_maptick = -1; 6322 6323 while (i != idx) 6324 { 6325 j = (i + 1) % hislen; 6326 history[histype][i] = history[histype][j]; 6327 i = j; 6328 } 6329 clear_hist_entry(&history[histype][i]); 6330 if (--i < 0) 6331 i += hislen; 6332 hisidx[histype] = i; 6333 return TRUE; 6334 } 6335 6336 #endif /* FEAT_EVAL */ 6337 6338 #if defined(FEAT_CRYPT) || defined(PROTO) 6339 /* 6340 * Very specific function to remove the value in ":set key=val" from the 6341 * history. 6342 */ 6343 void 6344 remove_key_from_history(void) 6345 { 6346 char_u *p; 6347 int i; 6348 6349 i = hisidx[HIST_CMD]; 6350 if (i < 0) 6351 return; 6352 p = history[HIST_CMD][i].hisstr; 6353 if (p != NULL) 6354 for ( ; *p; ++p) 6355 if (STRNCMP(p, "key", 3) == 0 && !isalpha(p[3])) 6356 { 6357 p = vim_strchr(p + 3, '='); 6358 if (p == NULL) 6359 break; 6360 ++p; 6361 for (i = 0; p[i] && !VIM_ISWHITE(p[i]); ++i) 6362 if (p[i] == '\\' && p[i + 1]) 6363 ++i; 6364 STRMOVE(p, p + i); 6365 --p; 6366 } 6367 } 6368 #endif 6369 6370 #endif /* FEAT_CMDHIST */ 6371 6372 #if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO) 6373 /* 6374 * Get pointer to the command line info to use. save_ccline() may clear 6375 * ccline and put the previous value in prev_ccline. 6376 */ 6377 static struct cmdline_info * 6378 get_ccline_ptr(void) 6379 { 6380 if ((State & CMDLINE) == 0) 6381 return NULL; 6382 if (ccline.cmdbuff != NULL) 6383 return &ccline; 6384 if (prev_ccline_used && prev_ccline.cmdbuff != NULL) 6385 return &prev_ccline; 6386 return NULL; 6387 } 6388 #endif 6389 6390 #if defined(FEAT_EVAL) || defined(PROTO) 6391 /* 6392 * Get the current command line in allocated memory. 6393 * Only works when the command line is being edited. 6394 * Returns NULL when something is wrong. 6395 */ 6396 char_u * 6397 get_cmdline_str(void) 6398 { 6399 struct cmdline_info *p; 6400 6401 if (cmdline_star > 0) 6402 return NULL; 6403 p = get_ccline_ptr(); 6404 if (p == NULL) 6405 return NULL; 6406 return vim_strnsave(p->cmdbuff, p->cmdlen); 6407 } 6408 6409 /* 6410 * Get the current command line position, counted in bytes. 6411 * Zero is the first position. 6412 * Only works when the command line is being edited. 6413 * Returns -1 when something is wrong. 6414 */ 6415 int 6416 get_cmdline_pos(void) 6417 { 6418 struct cmdline_info *p = get_ccline_ptr(); 6419 6420 if (p == NULL) 6421 return -1; 6422 return p->cmdpos; 6423 } 6424 6425 /* 6426 * Set the command line byte position to "pos". Zero is the first position. 6427 * Only works when the command line is being edited. 6428 * Returns 1 when failed, 0 when OK. 6429 */ 6430 int 6431 set_cmdline_pos( 6432 int pos) 6433 { 6434 struct cmdline_info *p = get_ccline_ptr(); 6435 6436 if (p == NULL) 6437 return 1; 6438 6439 /* The position is not set directly but after CTRL-\ e or CTRL-R = has 6440 * changed the command line. */ 6441 if (pos < 0) 6442 new_cmdpos = 0; 6443 else 6444 new_cmdpos = pos; 6445 return 0; 6446 } 6447 #endif 6448 6449 #if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO) 6450 /* 6451 * Get the current command-line type. 6452 * Returns ':' or '/' or '?' or '@' or '>' or '-' 6453 * Only works when the command line is being edited. 6454 * Returns NUL when something is wrong. 6455 */ 6456 int 6457 get_cmdline_type(void) 6458 { 6459 struct cmdline_info *p = get_ccline_ptr(); 6460 6461 if (p == NULL) 6462 return NUL; 6463 if (p->cmdfirstc == NUL) 6464 return 6465 # ifdef FEAT_EVAL 6466 (p->input_fn) ? '@' : 6467 # endif 6468 '-'; 6469 return p->cmdfirstc; 6470 } 6471 #endif 6472 6473 #if defined(FEAT_QUICKFIX) || defined(FEAT_CMDHIST) || defined(PROTO) 6474 /* 6475 * Get indices "num1,num2" that specify a range within a list (not a range of 6476 * text lines in a buffer!) from a string. Used for ":history" and ":clist". 6477 * Returns OK if parsed successfully, otherwise FAIL. 6478 */ 6479 int 6480 get_list_range(char_u **str, int *num1, int *num2) 6481 { 6482 int len; 6483 int first = FALSE; 6484 varnumber_T num; 6485 6486 *str = skipwhite(*str); 6487 if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */ 6488 { 6489 vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); 6490 *str += len; 6491 *num1 = (int)num; 6492 first = TRUE; 6493 } 6494 *str = skipwhite(*str); 6495 if (**str == ',') /* parse "to" part of range */ 6496 { 6497 *str = skipwhite(*str + 1); 6498 vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0); 6499 if (len > 0) 6500 { 6501 *num2 = (int)num; 6502 *str = skipwhite(*str + len); 6503 } 6504 else if (!first) /* no number given at all */ 6505 return FAIL; 6506 } 6507 else if (first) /* only one number given */ 6508 *num2 = *num1; 6509 return OK; 6510 } 6511 #endif 6512 6513 #if defined(FEAT_CMDHIST) || defined(PROTO) 6514 /* 6515 * :history command - print a history 6516 */ 6517 void 6518 ex_history(exarg_T *eap) 6519 { 6520 histentry_T *hist; 6521 int histype1 = HIST_CMD; 6522 int histype2 = HIST_CMD; 6523 int hisidx1 = 1; 6524 int hisidx2 = -1; 6525 int idx; 6526 int i, j, k; 6527 char_u *end; 6528 char_u *arg = eap->arg; 6529 6530 if (hislen == 0) 6531 { 6532 msg(_("'history' option is zero")); 6533 return; 6534 } 6535 6536 if (!(VIM_ISDIGIT(*arg) || *arg == '-' || *arg == ',')) 6537 { 6538 end = arg; 6539 while (ASCII_ISALPHA(*end) 6540 || vim_strchr((char_u *)":=@>/?", *end) != NULL) 6541 end++; 6542 i = *end; 6543 *end = NUL; 6544 histype1 = get_histtype(arg); 6545 if (histype1 == -1) 6546 { 6547 if (STRNICMP(arg, "all", STRLEN(arg)) == 0) 6548 { 6549 histype1 = 0; 6550 histype2 = HIST_COUNT-1; 6551 } 6552 else 6553 { 6554 *end = i; 6555 emsg(_(e_trailing)); 6556 return; 6557 } 6558 } 6559 else 6560 histype2 = histype1; 6561 *end = i; 6562 } 6563 else 6564 end = arg; 6565 if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) 6566 { 6567 emsg(_(e_trailing)); 6568 return; 6569 } 6570 6571 for (; !got_int && histype1 <= histype2; ++histype1) 6572 { 6573 STRCPY(IObuff, "\n # "); 6574 STRCAT(STRCAT(IObuff, history_names[histype1]), " history"); 6575 msg_puts_title((char *)IObuff); 6576 idx = hisidx[histype1]; 6577 hist = history[histype1]; 6578 j = hisidx1; 6579 k = hisidx2; 6580 if (j < 0) 6581 j = (-j > hislen) ? 0 : hist[(hislen+j+idx+1) % hislen].hisnum; 6582 if (k < 0) 6583 k = (-k > hislen) ? 0 : hist[(hislen+k+idx+1) % hislen].hisnum; 6584 if (idx >= 0 && j <= k) 6585 for (i = idx + 1; !got_int; ++i) 6586 { 6587 if (i == hislen) 6588 i = 0; 6589 if (hist[i].hisstr != NULL 6590 && hist[i].hisnum >= j && hist[i].hisnum <= k) 6591 { 6592 msg_putchar('\n'); 6593 sprintf((char *)IObuff, "%c%6d ", i == idx ? '>' : ' ', 6594 hist[i].hisnum); 6595 if (vim_strsize(hist[i].hisstr) > (int)Columns - 10) 6596 trunc_string(hist[i].hisstr, IObuff + STRLEN(IObuff), 6597 (int)Columns - 10, IOSIZE - (int)STRLEN(IObuff)); 6598 else 6599 STRCAT(IObuff, hist[i].hisstr); 6600 msg_outtrans(IObuff); 6601 out_flush(); 6602 } 6603 if (i == idx) 6604 break; 6605 } 6606 } 6607 } 6608 #endif 6609 6610 #if (defined(FEAT_VIMINFO) && defined(FEAT_CMDHIST)) || defined(PROTO) 6611 /* 6612 * Buffers for history read from a viminfo file. Only valid while reading. 6613 */ 6614 static histentry_T *viminfo_history[HIST_COUNT] = 6615 {NULL, NULL, NULL, NULL, NULL}; 6616 static int viminfo_hisidx[HIST_COUNT] = {0, 0, 0, 0, 0}; 6617 static int viminfo_hislen[HIST_COUNT] = {0, 0, 0, 0, 0}; 6618 static int viminfo_add_at_front = FALSE; 6619 6620 /* 6621 * Translate a history type number to the associated character. 6622 */ 6623 static int 6624 hist_type2char( 6625 int type, 6626 int use_question) /* use '?' instead of '/' */ 6627 { 6628 if (type == HIST_CMD) 6629 return ':'; 6630 if (type == HIST_SEARCH) 6631 { 6632 if (use_question) 6633 return '?'; 6634 else 6635 return '/'; 6636 } 6637 if (type == HIST_EXPR) 6638 return '='; 6639 return '@'; 6640 } 6641 6642 /* 6643 * Prepare for reading the history from the viminfo file. 6644 * This allocates history arrays to store the read history lines. 6645 */ 6646 void 6647 prepare_viminfo_history(int asklen, int writing) 6648 { 6649 int i; 6650 int num; 6651 int type; 6652 int len; 6653 6654 init_history(); 6655 viminfo_add_at_front = (asklen != 0 && !writing); 6656 if (asklen > hislen) 6657 asklen = hislen; 6658 6659 for (type = 0; type < HIST_COUNT; ++type) 6660 { 6661 /* Count the number of empty spaces in the history list. Entries read 6662 * from viminfo previously are also considered empty. If there are 6663 * more spaces available than we request, then fill them up. */ 6664 for (i = 0, num = 0; i < hislen; i++) 6665 if (history[type][i].hisstr == NULL || history[type][i].viminfo) 6666 num++; 6667 len = asklen; 6668 if (num > len) 6669 len = num; 6670 if (len <= 0) 6671 viminfo_history[type] = NULL; 6672 else 6673 viminfo_history[type] = (histentry_T *)lalloc( 6674 (long_u)(len * sizeof(histentry_T)), FALSE); 6675 if (viminfo_history[type] == NULL) 6676 len = 0; 6677 viminfo_hislen[type] = len; 6678 viminfo_hisidx[type] = 0; 6679 } 6680 } 6681 6682 /* 6683 * Accept a line from the viminfo, store it in the history array when it's 6684 * new. 6685 */ 6686 int 6687 read_viminfo_history(vir_T *virp, int writing) 6688 { 6689 int type; 6690 long_u len; 6691 char_u *val; 6692 char_u *p; 6693 6694 type = hist_char2type(virp->vir_line[0]); 6695 if (viminfo_hisidx[type] < viminfo_hislen[type]) 6696 { 6697 val = viminfo_readstring(virp, 1, TRUE); 6698 if (val != NULL && *val != NUL) 6699 { 6700 int sep = (*val == ' ' ? NUL : *val); 6701 6702 if (!in_history(type, val + (type == HIST_SEARCH), 6703 viminfo_add_at_front, sep, writing)) 6704 { 6705 /* Need to re-allocate to append the separator byte. */ 6706 len = STRLEN(val); 6707 p = lalloc(len + 2, TRUE); 6708 if (p != NULL) 6709 { 6710 if (type == HIST_SEARCH) 6711 { 6712 /* Search entry: Move the separator from the first 6713 * column to after the NUL. */ 6714 mch_memmove(p, val + 1, (size_t)len); 6715 p[len] = sep; 6716 } 6717 else 6718 { 6719 /* Not a search entry: No separator in the viminfo 6720 * file, add a NUL separator. */ 6721 mch_memmove(p, val, (size_t)len + 1); 6722 p[len + 1] = NUL; 6723 } 6724 viminfo_history[type][viminfo_hisidx[type]].hisstr = p; 6725 viminfo_history[type][viminfo_hisidx[type]].time_set = 0; 6726 viminfo_history[type][viminfo_hisidx[type]].viminfo = TRUE; 6727 viminfo_history[type][viminfo_hisidx[type]].hisnum = 0; 6728 viminfo_hisidx[type]++; 6729 } 6730 } 6731 } 6732 vim_free(val); 6733 } 6734 return viminfo_readline(virp); 6735 } 6736 6737 /* 6738 * Accept a new style history line from the viminfo, store it in the history 6739 * array when it's new. 6740 */ 6741 void 6742 handle_viminfo_history( 6743 garray_T *values, 6744 int writing) 6745 { 6746 int type; 6747 long_u len; 6748 char_u *val; 6749 char_u *p; 6750 bval_T *vp = (bval_T *)values->ga_data; 6751 6752 /* Check the format: 6753 * |{bartype},{histtype},{timestamp},{separator},"text" */ 6754 if (values->ga_len < 4 6755 || vp[0].bv_type != BVAL_NR 6756 || vp[1].bv_type != BVAL_NR 6757 || (vp[2].bv_type != BVAL_NR && vp[2].bv_type != BVAL_EMPTY) 6758 || vp[3].bv_type != BVAL_STRING) 6759 return; 6760 6761 type = vp[0].bv_nr; 6762 if (type >= HIST_COUNT) 6763 return; 6764 if (viminfo_hisidx[type] < viminfo_hislen[type]) 6765 { 6766 val = vp[3].bv_string; 6767 if (val != NULL && *val != NUL) 6768 { 6769 int sep = type == HIST_SEARCH && vp[2].bv_type == BVAL_NR 6770 ? vp[2].bv_nr : NUL; 6771 int idx; 6772 int overwrite = FALSE; 6773 6774 if (!in_history(type, val, viminfo_add_at_front, sep, writing)) 6775 { 6776 /* If lines were written by an older Vim we need to avoid 6777 * getting duplicates. See if the entry already exists. */ 6778 for (idx = 0; idx < viminfo_hisidx[type]; ++idx) 6779 { 6780 p = viminfo_history[type][idx].hisstr; 6781 if (STRCMP(val, p) == 0 6782 && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) 6783 { 6784 overwrite = TRUE; 6785 break; 6786 } 6787 } 6788 6789 if (!overwrite) 6790 { 6791 /* Need to re-allocate to append the separator byte. */ 6792 len = vp[3].bv_len; 6793 p = lalloc(len + 2, TRUE); 6794 } 6795 else 6796 len = 0; /* for picky compilers */ 6797 if (p != NULL) 6798 { 6799 viminfo_history[type][idx].time_set = vp[1].bv_nr; 6800 if (!overwrite) 6801 { 6802 mch_memmove(p, val, (size_t)len + 1); 6803 /* Put the separator after the NUL. */ 6804 p[len + 1] = sep; 6805 viminfo_history[type][idx].hisstr = p; 6806 viminfo_history[type][idx].hisnum = 0; 6807 viminfo_history[type][idx].viminfo = TRUE; 6808 viminfo_hisidx[type]++; 6809 } 6810 } 6811 } 6812 } 6813 } 6814 } 6815 6816 /* 6817 * Concatenate history lines from viminfo after the lines typed in this Vim. 6818 */ 6819 static void 6820 concat_history(int type) 6821 { 6822 int idx; 6823 int i; 6824 6825 idx = hisidx[type] + viminfo_hisidx[type]; 6826 if (idx >= hislen) 6827 idx -= hislen; 6828 else if (idx < 0) 6829 idx = hislen - 1; 6830 if (viminfo_add_at_front) 6831 hisidx[type] = idx; 6832 else 6833 { 6834 if (hisidx[type] == -1) 6835 hisidx[type] = hislen - 1; 6836 do 6837 { 6838 if (history[type][idx].hisstr != NULL 6839 || history[type][idx].viminfo) 6840 break; 6841 if (++idx == hislen) 6842 idx = 0; 6843 } while (idx != hisidx[type]); 6844 if (idx != hisidx[type] && --idx < 0) 6845 idx = hislen - 1; 6846 } 6847 for (i = 0; i < viminfo_hisidx[type]; i++) 6848 { 6849 vim_free(history[type][idx].hisstr); 6850 history[type][idx].hisstr = viminfo_history[type][i].hisstr; 6851 history[type][idx].viminfo = TRUE; 6852 history[type][idx].time_set = viminfo_history[type][i].time_set; 6853 if (--idx < 0) 6854 idx = hislen - 1; 6855 } 6856 idx += 1; 6857 idx %= hislen; 6858 for (i = 0; i < viminfo_hisidx[type]; i++) 6859 { 6860 history[type][idx++].hisnum = ++hisnum[type]; 6861 idx %= hislen; 6862 } 6863 } 6864 6865 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 6866 static int 6867 #ifdef __BORLANDC__ 6868 _RTLENTRYF 6869 #endif 6870 sort_hist(const void *s1, const void *s2) 6871 { 6872 histentry_T *p1 = *(histentry_T **)s1; 6873 histentry_T *p2 = *(histentry_T **)s2; 6874 6875 if (p1->time_set < p2->time_set) return -1; 6876 if (p1->time_set > p2->time_set) return 1; 6877 return 0; 6878 } 6879 #endif 6880 6881 /* 6882 * Merge history lines from viminfo and lines typed in this Vim based on the 6883 * timestamp; 6884 */ 6885 static void 6886 merge_history(int type) 6887 { 6888 int max_len; 6889 histentry_T **tot_hist; 6890 histentry_T *new_hist; 6891 int i; 6892 int len; 6893 6894 /* Make one long list with all entries. */ 6895 max_len = hislen + viminfo_hisidx[type]; 6896 tot_hist = (histentry_T **)alloc(max_len * (int)sizeof(histentry_T *)); 6897 new_hist = (histentry_T *)alloc(hislen * (int)sizeof(histentry_T)); 6898 if (tot_hist == NULL || new_hist == NULL) 6899 { 6900 vim_free(tot_hist); 6901 vim_free(new_hist); 6902 return; 6903 } 6904 for (i = 0; i < viminfo_hisidx[type]; i++) 6905 tot_hist[i] = &viminfo_history[type][i]; 6906 len = i; 6907 for (i = 0; i < hislen; i++) 6908 if (history[type][i].hisstr != NULL) 6909 tot_hist[len++] = &history[type][i]; 6910 6911 /* Sort the list on timestamp. */ 6912 qsort((void *)tot_hist, (size_t)len, sizeof(histentry_T *), sort_hist); 6913 6914 /* Keep the newest ones. */ 6915 for (i = 0; i < hislen; i++) 6916 { 6917 if (i < len) 6918 { 6919 new_hist[i] = *tot_hist[i]; 6920 tot_hist[i]->hisstr = NULL; 6921 if (new_hist[i].hisnum == 0) 6922 new_hist[i].hisnum = ++hisnum[type]; 6923 } 6924 else 6925 clear_hist_entry(&new_hist[i]); 6926 } 6927 hisidx[type] = (i < len ? i : len) - 1; 6928 6929 /* Free what is not kept. */ 6930 for (i = 0; i < viminfo_hisidx[type]; i++) 6931 vim_free(viminfo_history[type][i].hisstr); 6932 for (i = 0; i < hislen; i++) 6933 vim_free(history[type][i].hisstr); 6934 vim_free(history[type]); 6935 history[type] = new_hist; 6936 vim_free(tot_hist); 6937 } 6938 6939 /* 6940 * Finish reading history lines from viminfo. Not used when writing viminfo. 6941 */ 6942 void 6943 finish_viminfo_history(vir_T *virp) 6944 { 6945 int type; 6946 int merge = virp->vir_version >= VIMINFO_VERSION_WITH_HISTORY; 6947 6948 for (type = 0; type < HIST_COUNT; ++type) 6949 { 6950 if (history[type] == NULL) 6951 continue; 6952 6953 if (merge) 6954 merge_history(type); 6955 else 6956 concat_history(type); 6957 6958 VIM_CLEAR(viminfo_history[type]); 6959 viminfo_hisidx[type] = 0; 6960 } 6961 } 6962 6963 /* 6964 * Write history to viminfo file in "fp". 6965 * When "merge" is TRUE merge history lines with a previously read viminfo 6966 * file, data is in viminfo_history[]. 6967 * When "merge" is FALSE just write all history lines. Used for ":wviminfo!". 6968 */ 6969 void 6970 write_viminfo_history(FILE *fp, int merge) 6971 { 6972 int i; 6973 int type; 6974 int num_saved; 6975 int round; 6976 6977 init_history(); 6978 if (hislen == 0) 6979 return; 6980 for (type = 0; type < HIST_COUNT; ++type) 6981 { 6982 num_saved = get_viminfo_parameter(hist_type2char(type, FALSE)); 6983 if (num_saved == 0) 6984 continue; 6985 if (num_saved < 0) /* Use default */ 6986 num_saved = hislen; 6987 fprintf(fp, _("\n# %s History (newest to oldest):\n"), 6988 type == HIST_CMD ? _("Command Line") : 6989 type == HIST_SEARCH ? _("Search String") : 6990 type == HIST_EXPR ? _("Expression") : 6991 type == HIST_INPUT ? _("Input Line") : 6992 _("Debug Line")); 6993 if (num_saved > hislen) 6994 num_saved = hislen; 6995 6996 /* 6997 * Merge typed and viminfo history: 6998 * round 1: history of typed commands. 6999 * round 2: history from recently read viminfo. 7000 */ 7001 for (round = 1; round <= 2; ++round) 7002 { 7003 if (round == 1) 7004 /* start at newest entry, somewhere in the list */ 7005 i = hisidx[type]; 7006 else if (viminfo_hisidx[type] > 0) 7007 /* start at newest entry, first in the list */ 7008 i = 0; 7009 else 7010 /* empty list */ 7011 i = -1; 7012 if (i >= 0) 7013 while (num_saved > 0 7014 && !(round == 2 && i >= viminfo_hisidx[type])) 7015 { 7016 char_u *p; 7017 time_t timestamp; 7018 int c = NUL; 7019 7020 if (round == 1) 7021 { 7022 p = history[type][i].hisstr; 7023 timestamp = history[type][i].time_set; 7024 } 7025 else 7026 { 7027 p = viminfo_history[type] == NULL ? NULL 7028 : viminfo_history[type][i].hisstr; 7029 timestamp = viminfo_history[type] == NULL ? 0 7030 : viminfo_history[type][i].time_set; 7031 } 7032 7033 if (p != NULL && (round == 2 7034 || !merge 7035 || !history[type][i].viminfo)) 7036 { 7037 --num_saved; 7038 fputc(hist_type2char(type, TRUE), fp); 7039 /* For the search history: put the separator in the 7040 * second column; use a space if there isn't one. */ 7041 if (type == HIST_SEARCH) 7042 { 7043 c = p[STRLEN(p) + 1]; 7044 putc(c == NUL ? ' ' : c, fp); 7045 } 7046 viminfo_writestring(fp, p); 7047 7048 { 7049 char cbuf[NUMBUFLEN]; 7050 7051 /* New style history with a bar line. Format: 7052 * |{bartype},{histtype},{timestamp},{separator},"text" */ 7053 if (c == NUL) 7054 cbuf[0] = NUL; 7055 else 7056 sprintf(cbuf, "%d", c); 7057 fprintf(fp, "|%d,%d,%ld,%s,", BARTYPE_HISTORY, 7058 type, (long)timestamp, cbuf); 7059 barline_writestring(fp, p, LSIZE - 20); 7060 putc('\n', fp); 7061 } 7062 } 7063 if (round == 1) 7064 { 7065 /* Decrement index, loop around and stop when back at 7066 * the start. */ 7067 if (--i < 0) 7068 i = hislen - 1; 7069 if (i == hisidx[type]) 7070 break; 7071 } 7072 else 7073 { 7074 /* Increment index. Stop at the end in the while. */ 7075 ++i; 7076 } 7077 } 7078 } 7079 for (i = 0; i < viminfo_hisidx[type]; ++i) 7080 if (viminfo_history[type] != NULL) 7081 vim_free(viminfo_history[type][i].hisstr); 7082 VIM_CLEAR(viminfo_history[type]); 7083 viminfo_hisidx[type] = 0; 7084 } 7085 } 7086 #endif /* FEAT_VIMINFO */ 7087 7088 #if defined(FEAT_CMDWIN) || defined(PROTO) 7089 /* 7090 * Open a window on the current command line and history. Allow editing in 7091 * the window. Returns when the window is closed. 7092 * Returns: 7093 * CR if the command is to be executed 7094 * Ctrl_C if it is to be abandoned 7095 * K_IGNORE if editing continues 7096 */ 7097 static int 7098 open_cmdwin(void) 7099 { 7100 bufref_T old_curbuf; 7101 win_T *old_curwin = curwin; 7102 bufref_T bufref; 7103 win_T *wp; 7104 int i; 7105 linenr_T lnum; 7106 int histtype; 7107 garray_T winsizes; 7108 int save_restart_edit = restart_edit; 7109 int save_State = State; 7110 int save_exmode = exmode_active; 7111 #ifdef FEAT_RIGHTLEFT 7112 int save_cmdmsg_rl = cmdmsg_rl; 7113 #endif 7114 #ifdef FEAT_FOLDING 7115 int save_KeyTyped; 7116 #endif 7117 7118 /* Can't do this recursively. Can't do it when typing a password. */ 7119 if (cmdwin_type != 0 7120 # if defined(FEAT_CRYPT) || defined(FEAT_EVAL) 7121 || cmdline_star > 0 7122 # endif 7123 ) 7124 { 7125 beep_flush(); 7126 return K_IGNORE; 7127 } 7128 set_bufref(&old_curbuf, curbuf); 7129 7130 /* Save current window sizes. */ 7131 win_size_save(&winsizes); 7132 7133 /* Don't execute autocommands while creating the window. */ 7134 block_autocmds(); 7135 7136 #if defined(FEAT_INS_EXPAND) 7137 // When using completion in Insert mode with <C-R>=<C-F> one can open the 7138 // command line window, but we don't want the popup menu then. 7139 pum_undisplay(); 7140 #endif 7141 7142 /* don't use a new tab page */ 7143 cmdmod.tab = 0; 7144 cmdmod.noswapfile = 1; 7145 7146 /* Create a window for the command-line buffer. */ 7147 if (win_split((int)p_cwh, WSP_BOT) == FAIL) 7148 { 7149 beep_flush(); 7150 unblock_autocmds(); 7151 return K_IGNORE; 7152 } 7153 cmdwin_type = get_cmdline_type(); 7154 7155 /* Create the command-line buffer empty. */ 7156 (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL); 7157 (void)setfname(curbuf, (char_u *)"[Command Line]", NULL, TRUE); 7158 set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); 7159 curbuf->b_p_ma = TRUE; 7160 #ifdef FEAT_FOLDING 7161 curwin->w_p_fen = FALSE; 7162 #endif 7163 # ifdef FEAT_RIGHTLEFT 7164 curwin->w_p_rl = cmdmsg_rl; 7165 cmdmsg_rl = FALSE; 7166 # endif 7167 RESET_BINDING(curwin); 7168 7169 /* Do execute autocommands for setting the filetype (load syntax). */ 7170 unblock_autocmds(); 7171 /* But don't allow switching to another buffer. */ 7172 ++curbuf_lock; 7173 7174 /* Showing the prompt may have set need_wait_return, reset it. */ 7175 need_wait_return = FALSE; 7176 7177 histtype = hist_char2type(cmdwin_type); 7178 if (histtype == HIST_CMD || histtype == HIST_DEBUG) 7179 { 7180 if (p_wc == TAB) 7181 { 7182 add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT); 7183 add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL); 7184 } 7185 set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL); 7186 } 7187 --curbuf_lock; 7188 7189 /* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin 7190 * sets 'textwidth' to 78). */ 7191 curbuf->b_p_tw = 0; 7192 7193 /* Fill the buffer with the history. */ 7194 init_history(); 7195 if (hislen > 0) 7196 { 7197 i = hisidx[histtype]; 7198 if (i >= 0) 7199 { 7200 lnum = 0; 7201 do 7202 { 7203 if (++i == hislen) 7204 i = 0; 7205 if (history[histtype][i].hisstr != NULL) 7206 ml_append(lnum++, history[histtype][i].hisstr, 7207 (colnr_T)0, FALSE); 7208 } 7209 while (i != hisidx[histtype]); 7210 } 7211 } 7212 7213 /* Replace the empty last line with the current command-line and put the 7214 * cursor there. */ 7215 ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, TRUE); 7216 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 7217 curwin->w_cursor.col = ccline.cmdpos; 7218 changed_line_abv_curs(); 7219 invalidate_botline(); 7220 redraw_later(SOME_VALID); 7221 7222 /* No Ex mode here! */ 7223 exmode_active = 0; 7224 7225 State = NORMAL; 7226 # ifdef FEAT_MOUSE 7227 setmouse(); 7228 # endif 7229 7230 /* Trigger CmdwinEnter autocommands. */ 7231 trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINENTER); 7232 if (restart_edit != 0) /* autocmd with ":startinsert" */ 7233 stuffcharReadbuff(K_NOP); 7234 7235 i = RedrawingDisabled; 7236 RedrawingDisabled = 0; 7237 7238 /* 7239 * Call the main loop until <CR> or CTRL-C is typed. 7240 */ 7241 cmdwin_result = 0; 7242 main_loop(TRUE, FALSE); 7243 7244 RedrawingDisabled = i; 7245 7246 # ifdef FEAT_FOLDING 7247 save_KeyTyped = KeyTyped; 7248 # endif 7249 7250 /* Trigger CmdwinLeave autocommands. */ 7251 trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINLEAVE); 7252 7253 # ifdef FEAT_FOLDING 7254 /* Restore KeyTyped in case it is modified by autocommands */ 7255 KeyTyped = save_KeyTyped; 7256 # endif 7257 7258 cmdwin_type = 0; 7259 exmode_active = save_exmode; 7260 7261 /* Safety check: The old window or buffer was deleted: It's a bug when 7262 * this happens! */ 7263 if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) 7264 { 7265 cmdwin_result = Ctrl_C; 7266 emsg(_("E199: Active window or buffer deleted")); 7267 } 7268 else 7269 { 7270 # if defined(FEAT_EVAL) 7271 /* autocmds may abort script processing */ 7272 if (aborting() && cmdwin_result != K_IGNORE) 7273 cmdwin_result = Ctrl_C; 7274 # endif 7275 /* Set the new command line from the cmdline buffer. */ 7276 vim_free(ccline.cmdbuff); 7277 if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) /* :qa[!] typed */ 7278 { 7279 char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; 7280 7281 if (histtype == HIST_CMD) 7282 { 7283 /* Execute the command directly. */ 7284 ccline.cmdbuff = vim_strsave((char_u *)p); 7285 cmdwin_result = CAR; 7286 } 7287 else 7288 { 7289 /* First need to cancel what we were doing. */ 7290 ccline.cmdbuff = NULL; 7291 stuffcharReadbuff(':'); 7292 stuffReadbuff((char_u *)p); 7293 stuffcharReadbuff(CAR); 7294 } 7295 } 7296 else if (cmdwin_result == K_XF2) /* :qa typed */ 7297 { 7298 ccline.cmdbuff = vim_strsave((char_u *)"qa"); 7299 cmdwin_result = CAR; 7300 } 7301 else if (cmdwin_result == Ctrl_C) 7302 { 7303 /* :q or :close, don't execute any command 7304 * and don't modify the cmd window. */ 7305 ccline.cmdbuff = NULL; 7306 } 7307 else 7308 ccline.cmdbuff = vim_strsave(ml_get_curline()); 7309 if (ccline.cmdbuff == NULL) 7310 { 7311 ccline.cmdbuff = vim_strsave((char_u *)""); 7312 ccline.cmdlen = 0; 7313 ccline.cmdbufflen = 1; 7314 ccline.cmdpos = 0; 7315 cmdwin_result = Ctrl_C; 7316 } 7317 else 7318 { 7319 ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); 7320 ccline.cmdbufflen = ccline.cmdlen + 1; 7321 ccline.cmdpos = curwin->w_cursor.col; 7322 if (ccline.cmdpos > ccline.cmdlen) 7323 ccline.cmdpos = ccline.cmdlen; 7324 if (cmdwin_result == K_IGNORE) 7325 { 7326 set_cmdspos_cursor(); 7327 redrawcmd(); 7328 } 7329 } 7330 7331 /* Don't execute autocommands while deleting the window. */ 7332 block_autocmds(); 7333 # ifdef FEAT_CONCEAL 7334 /* Avoid command-line window first character being concealed. */ 7335 curwin->w_p_cole = 0; 7336 # endif 7337 wp = curwin; 7338 set_bufref(&bufref, curbuf); 7339 win_goto(old_curwin); 7340 win_close(wp, TRUE); 7341 7342 /* win_close() may have already wiped the buffer when 'bh' is 7343 * set to 'wipe' */ 7344 if (bufref_valid(&bufref)) 7345 close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, FALSE); 7346 7347 /* Restore window sizes. */ 7348 win_size_restore(&winsizes); 7349 7350 unblock_autocmds(); 7351 } 7352 7353 ga_clear(&winsizes); 7354 restart_edit = save_restart_edit; 7355 # ifdef FEAT_RIGHTLEFT 7356 cmdmsg_rl = save_cmdmsg_rl; 7357 # endif 7358 7359 State = save_State; 7360 # ifdef FEAT_MOUSE 7361 setmouse(); 7362 # endif 7363 7364 return cmdwin_result; 7365 } 7366 #endif /* FEAT_CMDWIN */ 7367 7368 /* 7369 * Used for commands that either take a simple command string argument, or: 7370 * cmd << endmarker 7371 * {script} 7372 * endmarker 7373 * Returns a pointer to allocated memory with {script} or NULL. 7374 */ 7375 char_u * 7376 script_get(exarg_T *eap, char_u *cmd) 7377 { 7378 char_u *theline; 7379 char *end_pattern = NULL; 7380 char dot[] = "."; 7381 garray_T ga; 7382 7383 if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) 7384 return NULL; 7385 7386 ga_init2(&ga, 1, 0x400); 7387 7388 if (cmd[2] != NUL) 7389 end_pattern = (char *)skipwhite(cmd + 2); 7390 else 7391 end_pattern = dot; 7392 7393 for (;;) 7394 { 7395 theline = eap->getline( 7396 #ifdef FEAT_EVAL 7397 eap->cstack->cs_looplevel > 0 ? -1 : 7398 #endif 7399 NUL, eap->cookie, 0); 7400 7401 if (theline == NULL || STRCMP(end_pattern, theline) == 0) 7402 { 7403 vim_free(theline); 7404 break; 7405 } 7406 7407 ga_concat(&ga, theline); 7408 ga_append(&ga, '\n'); 7409 vim_free(theline); 7410 } 7411 ga_append(&ga, NUL); 7412 7413 return (char_u *)ga.ga_data; 7414 } 7415