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