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