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