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