1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * ex_docmd.c: functions for executing an Ex command line. 12 */ 13 14 #include "vim.h" 15 16 static int quitmore = 0; 17 static int ex_pressedreturn = FALSE; 18 #ifndef FEAT_PRINTER 19 # define ex_hardcopy ex_ni 20 #endif 21 22 #ifdef FEAT_USR_CMDS 23 typedef struct ucmd 24 { 25 char_u *uc_name; /* The command name */ 26 long_u uc_argt; /* The argument type */ 27 char_u *uc_rep; /* The command's replacement string */ 28 long uc_def; /* The default value for a range/count */ 29 int uc_compl; /* completion type */ 30 int uc_addr_type; /* The command's address type */ 31 # ifdef FEAT_EVAL 32 scid_T uc_scriptID; /* SID where the command was defined */ 33 # ifdef FEAT_CMDL_COMPL 34 char_u *uc_compl_arg; /* completion argument if any */ 35 # endif 36 # endif 37 } ucmd_T; 38 39 #define UC_BUFFER 1 /* -buffer: local to current buffer */ 40 41 static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL}; 42 43 #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i]) 44 #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i]) 45 46 static void do_ucmd(exarg_T *eap); 47 static void ex_command(exarg_T *eap); 48 static void ex_delcommand(exarg_T *eap); 49 # ifdef FEAT_CMDL_COMPL 50 static char_u *get_user_command_name(int idx); 51 # endif 52 53 /* Wether a command index indicates a user command. */ 54 # define IS_USER_CMDIDX(idx) ((int)(idx) < 0) 55 56 #else 57 # define ex_command ex_ni 58 # define ex_comclear ex_ni 59 # define ex_delcommand ex_ni 60 /* Wether a command index indicates a user command. */ 61 # define IS_USER_CMDIDX(idx) (FALSE) 62 #endif 63 64 static int compute_buffer_local_count(int addr_type, int lnum, int local); 65 #ifdef FEAT_EVAL 66 static char_u *do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie); 67 #else 68 static char_u *do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie); 69 static int if_level = 0; /* depth in :if */ 70 #endif 71 static void append_command(char_u *cmd); 72 static char_u *find_command(exarg_T *eap, int *full); 73 74 static void ex_abbreviate(exarg_T *eap); 75 static void ex_map(exarg_T *eap); 76 static void ex_unmap(exarg_T *eap); 77 static void ex_mapclear(exarg_T *eap); 78 static void ex_abclear(exarg_T *eap); 79 #ifndef FEAT_MENU 80 # define ex_emenu ex_ni 81 # define ex_menu ex_ni 82 # define ex_menutranslate ex_ni 83 #endif 84 #ifdef FEAT_AUTOCMD 85 static void ex_autocmd(exarg_T *eap); 86 static void ex_doautocmd(exarg_T *eap); 87 #else 88 # define ex_autocmd ex_ni 89 # define ex_doautocmd ex_ni 90 # define ex_doautoall ex_ni 91 #endif 92 #ifdef FEAT_LISTCMDS 93 static void ex_bunload(exarg_T *eap); 94 static void ex_buffer(exarg_T *eap); 95 static void ex_bmodified(exarg_T *eap); 96 static void ex_bnext(exarg_T *eap); 97 static void ex_bprevious(exarg_T *eap); 98 static void ex_brewind(exarg_T *eap); 99 static void ex_blast(exarg_T *eap); 100 #else 101 # define ex_bunload ex_ni 102 # define ex_buffer ex_ni 103 # define ex_bmodified ex_ni 104 # define ex_bnext ex_ni 105 # define ex_bprevious ex_ni 106 # define ex_brewind ex_ni 107 # define ex_blast ex_ni 108 # define buflist_list ex_ni 109 # define ex_checktime ex_ni 110 #endif 111 #if !defined(FEAT_LISTCMDS) 112 # define ex_buffer_all ex_ni 113 #endif 114 static char_u *getargcmd(char_u **); 115 static char_u *skip_cmd_arg(char_u *p, int rembs); 116 static int getargopt(exarg_T *eap); 117 #ifndef FEAT_QUICKFIX 118 # define ex_make ex_ni 119 # define ex_cbuffer ex_ni 120 # define ex_cc ex_ni 121 # define ex_cnext ex_ni 122 # define ex_cfile ex_ni 123 # define qf_list ex_ni 124 # define qf_age ex_ni 125 # define qf_history ex_ni 126 # define ex_helpgrep ex_ni 127 # define ex_vimgrep ex_ni 128 #endif 129 #if !defined(FEAT_QUICKFIX) 130 # define ex_cclose ex_ni 131 # define ex_copen ex_ni 132 # define ex_cwindow ex_ni 133 # define ex_cbottom ex_ni 134 #endif 135 #if !defined(FEAT_QUICKFIX) || !defined(FEAT_EVAL) 136 # define ex_cexpr ex_ni 137 #endif 138 139 static int check_more(int, int); 140 static linenr_T get_address(exarg_T *, char_u **, int addr_type, int skip, int to_other_file, int address_count); 141 static void get_flags(exarg_T *eap); 142 #if !defined(FEAT_PERL) \ 143 || !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \ 144 || !defined(FEAT_TCL) \ 145 || !defined(FEAT_RUBY) \ 146 || !defined(FEAT_LUA) \ 147 || !defined(FEAT_MZSCHEME) 148 # define HAVE_EX_SCRIPT_NI 149 static void ex_script_ni(exarg_T *eap); 150 #endif 151 static char_u *invalid_range(exarg_T *eap); 152 static void correct_range(exarg_T *eap); 153 #ifdef FEAT_QUICKFIX 154 static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep); 155 #endif 156 static char_u *repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep); 157 static void ex_highlight(exarg_T *eap); 158 static void ex_colorscheme(exarg_T *eap); 159 static void ex_quit(exarg_T *eap); 160 static void ex_cquit(exarg_T *eap); 161 static void ex_quit_all(exarg_T *eap); 162 static void ex_close(exarg_T *eap); 163 static void ex_win_close(int forceit, win_T *win, tabpage_T *tp); 164 static void ex_only(exarg_T *eap); 165 static void ex_resize(exarg_T *eap); 166 static void ex_stag(exarg_T *eap); 167 static void ex_tabclose(exarg_T *eap); 168 static void ex_tabonly(exarg_T *eap); 169 static void ex_tabnext(exarg_T *eap); 170 static void ex_tabmove(exarg_T *eap); 171 static void ex_tabs(exarg_T *eap); 172 #if defined(FEAT_QUICKFIX) 173 static void ex_pclose(exarg_T *eap); 174 static void ex_ptag(exarg_T *eap); 175 static void ex_pedit(exarg_T *eap); 176 #else 177 # define ex_pclose ex_ni 178 # define ex_ptag ex_ni 179 # define ex_pedit ex_ni 180 #endif 181 static void ex_hide(exarg_T *eap); 182 static void ex_stop(exarg_T *eap); 183 static void ex_exit(exarg_T *eap); 184 static void ex_print(exarg_T *eap); 185 #ifdef FEAT_BYTEOFF 186 static void ex_goto(exarg_T *eap); 187 #else 188 # define ex_goto ex_ni 189 #endif 190 static void ex_shell(exarg_T *eap); 191 static void ex_preserve(exarg_T *eap); 192 static void ex_recover(exarg_T *eap); 193 #ifndef FEAT_LISTCMDS 194 # define ex_argedit ex_ni 195 # define ex_argadd ex_ni 196 # define ex_argdelete ex_ni 197 # define ex_listdo ex_ni 198 #endif 199 static void ex_mode(exarg_T *eap); 200 static void ex_wrongmodifier(exarg_T *eap); 201 static void ex_find(exarg_T *eap); 202 static void ex_open(exarg_T *eap); 203 static void ex_edit(exarg_T *eap); 204 #if !defined(FEAT_GUI) && !defined(FEAT_CLIENTSERVER) 205 # define ex_drop ex_ni 206 #endif 207 #ifndef FEAT_GUI 208 # define ex_gui ex_nogui 209 static void ex_nogui(exarg_T *eap); 210 #endif 211 #if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF) 212 static void ex_tearoff(exarg_T *eap); 213 #else 214 # define ex_tearoff ex_ni 215 #endif 216 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU) 217 static void ex_popup(exarg_T *eap); 218 #else 219 # define ex_popup ex_ni 220 #endif 221 #ifndef FEAT_GUI_MSWIN 222 # define ex_simalt ex_ni 223 #endif 224 #if !defined(FEAT_GUI_MSWIN) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF) 225 # define gui_mch_find_dialog ex_ni 226 # define gui_mch_replace_dialog ex_ni 227 #endif 228 #if !defined(FEAT_GUI_GTK) 229 # define ex_helpfind ex_ni 230 #endif 231 #ifndef FEAT_CSCOPE 232 # define ex_cscope ex_ni 233 # define ex_scscope ex_ni 234 # define ex_cstag ex_ni 235 #endif 236 #ifndef FEAT_SYN_HL 237 # define ex_syntax ex_ni 238 # define ex_ownsyntax ex_ni 239 #endif 240 #if !defined(FEAT_SYN_HL) || !defined(FEAT_PROFILE) 241 # define ex_syntime ex_ni 242 #endif 243 #ifndef FEAT_SPELL 244 # define ex_spell ex_ni 245 # define ex_mkspell ex_ni 246 # define ex_spelldump ex_ni 247 # define ex_spellinfo ex_ni 248 # define ex_spellrepall ex_ni 249 #endif 250 #ifndef FEAT_PERSISTENT_UNDO 251 # define ex_rundo ex_ni 252 # define ex_wundo ex_ni 253 #endif 254 #ifndef FEAT_LUA 255 # define ex_lua ex_script_ni 256 # define ex_luado ex_ni 257 # define ex_luafile ex_ni 258 #endif 259 #ifndef FEAT_MZSCHEME 260 # define ex_mzscheme ex_script_ni 261 # define ex_mzfile ex_ni 262 #endif 263 #ifndef FEAT_PERL 264 # define ex_perl ex_script_ni 265 # define ex_perldo ex_ni 266 #endif 267 #ifndef FEAT_PYTHON 268 # define ex_python ex_script_ni 269 # define ex_pydo ex_ni 270 # define ex_pyfile ex_ni 271 #endif 272 #ifndef FEAT_PYTHON3 273 # define ex_py3 ex_script_ni 274 # define ex_py3do ex_ni 275 # define ex_py3file ex_ni 276 #endif 277 #if !defined(FEAT_PYTHON) && !defined(FEAT_PYTHON3) 278 # define ex_pyx ex_script_ni 279 # define ex_pyxdo ex_ni 280 # define ex_pyxfile ex_ni 281 #endif 282 #ifndef FEAT_TCL 283 # define ex_tcl ex_script_ni 284 # define ex_tcldo ex_ni 285 # define ex_tclfile ex_ni 286 #endif 287 #ifndef FEAT_RUBY 288 # define ex_ruby ex_script_ni 289 # define ex_rubydo ex_ni 290 # define ex_rubyfile ex_ni 291 #endif 292 #ifndef FEAT_KEYMAP 293 # define ex_loadkeymap ex_ni 294 #endif 295 static void ex_swapname(exarg_T *eap); 296 static void ex_syncbind(exarg_T *eap); 297 static void ex_read(exarg_T *eap); 298 static void ex_pwd(exarg_T *eap); 299 static void ex_equal(exarg_T *eap); 300 static void ex_sleep(exarg_T *eap); 301 static void do_exmap(exarg_T *eap, int isabbrev); 302 static void ex_winsize(exarg_T *eap); 303 static void ex_wincmd(exarg_T *eap); 304 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN) 305 static void ex_winpos(exarg_T *eap); 306 #else 307 # define ex_winpos ex_ni 308 #endif 309 static void ex_operators(exarg_T *eap); 310 static void ex_put(exarg_T *eap); 311 static void ex_copymove(exarg_T *eap); 312 static void ex_submagic(exarg_T *eap); 313 static void ex_join(exarg_T *eap); 314 static void ex_at(exarg_T *eap); 315 static void ex_bang(exarg_T *eap); 316 static void ex_undo(exarg_T *eap); 317 #ifdef FEAT_PERSISTENT_UNDO 318 static void ex_wundo(exarg_T *eap); 319 static void ex_rundo(exarg_T *eap); 320 #endif 321 static void ex_redo(exarg_T *eap); 322 static void ex_later(exarg_T *eap); 323 static void ex_redir(exarg_T *eap); 324 static void ex_redrawstatus(exarg_T *eap); 325 static void close_redir(void); 326 static void ex_mkrc(exarg_T *eap); 327 static void ex_mark(exarg_T *eap); 328 #ifdef FEAT_USR_CMDS 329 static char_u *uc_fun_cmd(void); 330 static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *compl); 331 #endif 332 static void ex_startinsert(exarg_T *eap); 333 static void ex_stopinsert(exarg_T *eap); 334 #ifdef FEAT_FIND_ID 335 static void ex_checkpath(exarg_T *eap); 336 static void ex_findpat(exarg_T *eap); 337 #else 338 # define ex_findpat ex_ni 339 # define ex_checkpath ex_ni 340 #endif 341 #if defined(FEAT_FIND_ID) && defined(FEAT_QUICKFIX) 342 static void ex_psearch(exarg_T *eap); 343 #else 344 # define ex_psearch ex_ni 345 #endif 346 static void ex_tag(exarg_T *eap); 347 static void ex_tag_cmd(exarg_T *eap, char_u *name); 348 #ifndef FEAT_EVAL 349 # define ex_scriptnames ex_ni 350 # define ex_finish ex_ni 351 # define ex_echo ex_ni 352 # define ex_echohl ex_ni 353 # define ex_execute ex_ni 354 # define ex_call ex_ni 355 # define ex_if ex_ni 356 # define ex_endif ex_ni 357 # define ex_else ex_ni 358 # define ex_while ex_ni 359 # define ex_continue ex_ni 360 # define ex_break ex_ni 361 # define ex_endwhile ex_ni 362 # define ex_throw ex_ni 363 # define ex_try ex_ni 364 # define ex_catch ex_ni 365 # define ex_finally ex_ni 366 # define ex_endtry ex_ni 367 # define ex_endfunction ex_ni 368 # define ex_let ex_ni 369 # define ex_unlet ex_ni 370 # define ex_lockvar ex_ni 371 # define ex_unlockvar ex_ni 372 # define ex_function ex_ni 373 # define ex_delfunction ex_ni 374 # define ex_return ex_ni 375 # define ex_oldfiles ex_ni 376 #endif 377 static char_u *arg_all(void); 378 #ifdef FEAT_SESSION 379 static int makeopens(FILE *fd, char_u *dirnow); 380 static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx); 381 static void ex_loadview(exarg_T *eap); 382 static char_u *get_view_file(int c); 383 static int did_lcd; /* whether ":lcd" was produced for a session */ 384 #else 385 # define ex_loadview ex_ni 386 #endif 387 #ifndef FEAT_EVAL 388 # define ex_compiler ex_ni 389 #endif 390 #ifdef FEAT_VIMINFO 391 static void ex_viminfo(exarg_T *eap); 392 #else 393 # define ex_viminfo ex_ni 394 #endif 395 static void ex_behave(exarg_T *eap); 396 #ifdef FEAT_AUTOCMD 397 static void ex_filetype(exarg_T *eap); 398 static void ex_setfiletype(exarg_T *eap); 399 #else 400 # define ex_filetype ex_ni 401 # define ex_setfiletype ex_ni 402 #endif 403 #ifndef FEAT_DIFF 404 # define ex_diffoff ex_ni 405 # define ex_diffpatch ex_ni 406 # define ex_diffgetput ex_ni 407 # define ex_diffsplit ex_ni 408 # define ex_diffthis ex_ni 409 # define ex_diffupdate ex_ni 410 #endif 411 static void ex_digraphs(exarg_T *eap); 412 static void ex_set(exarg_T *eap); 413 #if !defined(FEAT_EVAL) || !defined(FEAT_AUTOCMD) 414 # define ex_options ex_ni 415 #endif 416 #ifdef FEAT_SEARCH_EXTRA 417 static void ex_nohlsearch(exarg_T *eap); 418 static void ex_match(exarg_T *eap); 419 #else 420 # define ex_nohlsearch ex_ni 421 # define ex_match ex_ni 422 #endif 423 #ifdef FEAT_CRYPT 424 static void ex_X(exarg_T *eap); 425 #else 426 # define ex_X ex_ni 427 #endif 428 #ifdef FEAT_FOLDING 429 static void ex_fold(exarg_T *eap); 430 static void ex_foldopen(exarg_T *eap); 431 static void ex_folddo(exarg_T *eap); 432 #else 433 # define ex_fold ex_ni 434 # define ex_foldopen ex_ni 435 # define ex_folddo ex_ni 436 #endif 437 #if !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 438 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE))) 439 # define ex_language ex_ni 440 #endif 441 #ifndef FEAT_SIGNS 442 # define ex_sign ex_ni 443 #endif 444 #ifndef FEAT_SUN_WORKSHOP 445 # define ex_wsverb ex_ni 446 #endif 447 #ifndef FEAT_NETBEANS_INTG 448 # define ex_nbclose ex_ni 449 # define ex_nbkey ex_ni 450 # define ex_nbstart ex_ni 451 #endif 452 453 #ifndef FEAT_EVAL 454 # define ex_debug ex_ni 455 # define ex_breakadd ex_ni 456 # define ex_debuggreedy ex_ni 457 # define ex_breakdel ex_ni 458 # define ex_breaklist ex_ni 459 #endif 460 461 #ifndef FEAT_CMDHIST 462 # define ex_history ex_ni 463 #endif 464 #ifndef FEAT_JUMPLIST 465 # define ex_jumps ex_ni 466 # define ex_clearjumps ex_ni 467 # define ex_changes ex_ni 468 #endif 469 470 #ifndef FEAT_PROFILE 471 # define ex_profile ex_ni 472 #endif 473 #ifndef FEAT_TERMINAL 474 # define ex_terminal ex_ni 475 #endif 476 477 /* 478 * Declare cmdnames[]. 479 */ 480 #define DO_DECLARE_EXCMD 481 #include "ex_cmds.h" 482 #include "ex_cmdidxs.h" 483 484 static char_u dollar_command[2] = {'$', 0}; 485 486 487 #ifdef FEAT_EVAL 488 /* Struct for storing a line inside a while/for loop */ 489 typedef struct 490 { 491 char_u *line; /* command line */ 492 linenr_T lnum; /* sourcing_lnum of the line */ 493 } wcmd_T; 494 495 /* 496 * Structure used to store info for line position in a while or for loop. 497 * This is required, because do_one_cmd() may invoke ex_function(), which 498 * reads more lines that may come from the while/for loop. 499 */ 500 struct loop_cookie 501 { 502 garray_T *lines_gap; /* growarray with line info */ 503 int current_line; /* last read line from growarray */ 504 int repeating; /* TRUE when looping a second time */ 505 /* When "repeating" is FALSE use "getline" and "cookie" to get lines */ 506 char_u *(*getline)(int, void *, int); 507 void *cookie; 508 }; 509 510 static char_u *get_loop_line(int c, void *cookie, int indent); 511 static int store_loop_line(garray_T *gap, char_u *line); 512 static void free_cmdlines(garray_T *gap); 513 514 /* Struct to save a few things while debugging. Used in do_cmdline() only. */ 515 struct dbg_stuff 516 { 517 int trylevel; 518 int force_abort; 519 except_T *caught_stack; 520 char_u *vv_exception; 521 char_u *vv_throwpoint; 522 int did_emsg; 523 int got_int; 524 int did_throw; 525 int need_rethrow; 526 int check_cstack; 527 except_T *current_exception; 528 }; 529 530 static void save_dbg_stuff(struct dbg_stuff *dsp); 531 static void restore_dbg_stuff(struct dbg_stuff *dsp); 532 533 static void 534 save_dbg_stuff(struct dbg_stuff *dsp) 535 { 536 dsp->trylevel = trylevel; trylevel = 0; 537 dsp->force_abort = force_abort; force_abort = FALSE; 538 dsp->caught_stack = caught_stack; caught_stack = NULL; 539 dsp->vv_exception = v_exception(NULL); 540 dsp->vv_throwpoint = v_throwpoint(NULL); 541 542 /* Necessary for debugging an inactive ":catch", ":finally", ":endtry" */ 543 dsp->did_emsg = did_emsg; did_emsg = FALSE; 544 dsp->got_int = got_int; got_int = FALSE; 545 dsp->did_throw = did_throw; did_throw = FALSE; 546 dsp->need_rethrow = need_rethrow; need_rethrow = FALSE; 547 dsp->check_cstack = check_cstack; check_cstack = FALSE; 548 dsp->current_exception = current_exception; current_exception = NULL; 549 } 550 551 static void 552 restore_dbg_stuff(struct dbg_stuff *dsp) 553 { 554 suppress_errthrow = FALSE; 555 trylevel = dsp->trylevel; 556 force_abort = dsp->force_abort; 557 caught_stack = dsp->caught_stack; 558 (void)v_exception(dsp->vv_exception); 559 (void)v_throwpoint(dsp->vv_throwpoint); 560 did_emsg = dsp->did_emsg; 561 got_int = dsp->got_int; 562 did_throw = dsp->did_throw; 563 need_rethrow = dsp->need_rethrow; 564 check_cstack = dsp->check_cstack; 565 current_exception = dsp->current_exception; 566 } 567 #endif 568 569 /* 570 * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi" 571 * command is given. 572 */ 573 void 574 do_exmode( 575 int improved) /* TRUE for "improved Ex" mode */ 576 { 577 int save_msg_scroll; 578 int prev_msg_row; 579 linenr_T prev_line; 580 varnumber_T changedtick; 581 582 if (improved) 583 exmode_active = EXMODE_VIM; 584 else 585 exmode_active = EXMODE_NORMAL; 586 State = NORMAL; 587 588 /* When using ":global /pat/ visual" and then "Q" we return to continue 589 * the :global command. */ 590 if (global_busy) 591 return; 592 593 save_msg_scroll = msg_scroll; 594 ++RedrawingDisabled; /* don't redisplay the window */ 595 ++no_wait_return; /* don't wait for return */ 596 #ifdef FEAT_GUI 597 /* Ignore scrollbar and mouse events in Ex mode */ 598 ++hold_gui_events; 599 #endif 600 601 MSG(_("Entering Ex mode. Type \"visual\" to go to Normal mode.")); 602 while (exmode_active) 603 { 604 /* Check for a ":normal" command and no more characters left. */ 605 if (ex_normal_busy > 0 && typebuf.tb_len == 0) 606 { 607 exmode_active = FALSE; 608 break; 609 } 610 msg_scroll = TRUE; 611 need_wait_return = FALSE; 612 ex_pressedreturn = FALSE; 613 ex_no_reprint = FALSE; 614 changedtick = CHANGEDTICK(curbuf); 615 prev_msg_row = msg_row; 616 prev_line = curwin->w_cursor.lnum; 617 if (improved) 618 { 619 cmdline_row = msg_row; 620 do_cmdline(NULL, getexline, NULL, 0); 621 } 622 else 623 do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT); 624 lines_left = Rows - 1; 625 626 if ((prev_line != curwin->w_cursor.lnum 627 || changedtick != CHANGEDTICK(curbuf)) && !ex_no_reprint) 628 { 629 if (curbuf->b_ml.ml_flags & ML_EMPTY) 630 EMSG(_(e_emptybuf)); 631 else 632 { 633 if (ex_pressedreturn) 634 { 635 /* go up one line, to overwrite the ":<CR>" line, so the 636 * output doesn't contain empty lines. */ 637 msg_row = prev_msg_row; 638 if (prev_msg_row == Rows - 1) 639 msg_row--; 640 } 641 msg_col = 0; 642 print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE); 643 msg_clr_eos(); 644 } 645 } 646 else if (ex_pressedreturn && !ex_no_reprint) /* must be at EOF */ 647 { 648 if (curbuf->b_ml.ml_flags & ML_EMPTY) 649 EMSG(_(e_emptybuf)); 650 else 651 EMSG(_("E501: At end-of-file")); 652 } 653 } 654 655 #ifdef FEAT_GUI 656 --hold_gui_events; 657 #endif 658 --RedrawingDisabled; 659 --no_wait_return; 660 update_screen(CLEAR); 661 need_wait_return = FALSE; 662 msg_scroll = save_msg_scroll; 663 } 664 665 /* 666 * Execute a simple command line. Used for translated commands like "*". 667 */ 668 int 669 do_cmdline_cmd(char_u *cmd) 670 { 671 return do_cmdline(cmd, NULL, NULL, 672 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED); 673 } 674 675 /* 676 * do_cmdline(): execute one Ex command line 677 * 678 * 1. Execute "cmdline" when it is not NULL. 679 * If "cmdline" is NULL, or more lines are needed, fgetline() is used. 680 * 2. Split up in parts separated with '|'. 681 * 682 * This function can be called recursively! 683 * 684 * flags: 685 * DOCMD_VERBOSE - The command will be included in the error message. 686 * DOCMD_NOWAIT - Don't call wait_return() and friends. 687 * DOCMD_REPEAT - Repeat execution until fgetline() returns NULL. 688 * DOCMD_KEYTYPED - Don't reset KeyTyped. 689 * DOCMD_EXCRESET - Reset the exception environment (used for debugging). 690 * DOCMD_KEEPLINE - Store first typed line (for repeating with "."). 691 * 692 * return FAIL if cmdline could not be executed, OK otherwise 693 */ 694 int 695 do_cmdline( 696 char_u *cmdline, 697 char_u *(*fgetline)(int, void *, int), 698 void *cookie, /* argument for fgetline() */ 699 int flags) 700 { 701 char_u *next_cmdline; /* next cmd to execute */ 702 char_u *cmdline_copy = NULL; /* copy of cmd line */ 703 int used_getline = FALSE; /* used "fgetline" to obtain command */ 704 static int recursive = 0; /* recursive depth */ 705 int msg_didout_before_start = 0; 706 int count = 0; /* line number count */ 707 int did_inc = FALSE; /* incremented RedrawingDisabled */ 708 int retval = OK; 709 #ifdef FEAT_EVAL 710 struct condstack cstack; /* conditional stack */ 711 garray_T lines_ga; /* keep lines for ":while"/":for" */ 712 int current_line = 0; /* active line in lines_ga */ 713 char_u *fname = NULL; /* function or script name */ 714 linenr_T *breakpoint = NULL; /* ptr to breakpoint field in cookie */ 715 int *dbg_tick = NULL; /* ptr to dbg_tick field in cookie */ 716 struct dbg_stuff debug_saved; /* saved things for debug mode */ 717 int initial_trylevel; 718 struct msglist **saved_msg_list = NULL; 719 struct msglist *private_msg_list; 720 721 /* "fgetline" and "cookie" passed to do_one_cmd() */ 722 char_u *(*cmd_getline)(int, void *, int); 723 void *cmd_cookie; 724 struct loop_cookie cmd_loop_cookie; 725 void *real_cookie; 726 int getline_is_func; 727 #else 728 # define cmd_getline fgetline 729 # define cmd_cookie cookie 730 #endif 731 static int call_depth = 0; /* recursiveness */ 732 733 #ifdef FEAT_EVAL 734 /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory 735 * location for storing error messages to be converted to an exception. 736 * This ensures that the do_errthrow() call in do_one_cmd() does not 737 * combine the messages stored by an earlier invocation of do_one_cmd() 738 * with the command name of the later one. This would happen when 739 * BufWritePost autocommands are executed after a write error. */ 740 saved_msg_list = msg_list; 741 msg_list = &private_msg_list; 742 private_msg_list = NULL; 743 #endif 744 745 /* It's possible to create an endless loop with ":execute", catch that 746 * here. The value of 200 allows nested function calls, ":source", etc. 747 * Allow 200 or 'maxfuncdepth', whatever is larger. */ 748 if (call_depth >= 200 749 #ifdef FEAT_EVAL 750 && call_depth >= p_mfd 751 #endif 752 ) 753 { 754 EMSG(_("E169: Command too recursive")); 755 #ifdef FEAT_EVAL 756 /* When converting to an exception, we do not include the command name 757 * since this is not an error of the specific command. */ 758 do_errthrow((struct condstack *)NULL, (char_u *)NULL); 759 msg_list = saved_msg_list; 760 #endif 761 return FAIL; 762 } 763 ++call_depth; 764 765 #ifdef FEAT_EVAL 766 cstack.cs_idx = -1; 767 cstack.cs_looplevel = 0; 768 cstack.cs_trylevel = 0; 769 cstack.cs_emsg_silent_list = NULL; 770 cstack.cs_lflags = 0; 771 ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10); 772 773 real_cookie = getline_cookie(fgetline, cookie); 774 775 /* Inside a function use a higher nesting level. */ 776 getline_is_func = getline_equal(fgetline, cookie, get_func_line); 777 if (getline_is_func && ex_nesting_level == func_level(real_cookie)) 778 ++ex_nesting_level; 779 780 /* Get the function or script name and the address where the next breakpoint 781 * line and the debug tick for a function or script are stored. */ 782 if (getline_is_func) 783 { 784 fname = func_name(real_cookie); 785 breakpoint = func_breakpoint(real_cookie); 786 dbg_tick = func_dbg_tick(real_cookie); 787 } 788 else if (getline_equal(fgetline, cookie, getsourceline)) 789 { 790 fname = sourcing_name; 791 breakpoint = source_breakpoint(real_cookie); 792 dbg_tick = source_dbg_tick(real_cookie); 793 } 794 795 /* 796 * Initialize "force_abort" and "suppress_errthrow" at the top level. 797 */ 798 if (!recursive) 799 { 800 force_abort = FALSE; 801 suppress_errthrow = FALSE; 802 } 803 804 /* 805 * If requested, store and reset the global values controlling the 806 * exception handling (used when debugging). Otherwise clear it to avoid 807 * a bogus compiler warning when the optimizer uses inline functions... 808 */ 809 if (flags & DOCMD_EXCRESET) 810 save_dbg_stuff(&debug_saved); 811 else 812 vim_memset(&debug_saved, 0, sizeof(debug_saved)); 813 814 initial_trylevel = trylevel; 815 816 /* 817 * "did_throw" will be set to TRUE when an exception is being thrown. 818 */ 819 did_throw = FALSE; 820 #endif 821 /* 822 * "did_emsg" will be set to TRUE when emsg() is used, in which case we 823 * cancel the whole command line, and any if/endif or loop. 824 * If force_abort is set, we cancel everything. 825 */ 826 did_emsg = FALSE; 827 828 /* 829 * KeyTyped is only set when calling vgetc(). Reset it here when not 830 * calling vgetc() (sourced command lines). 831 */ 832 if (!(flags & DOCMD_KEYTYPED) 833 && !getline_equal(fgetline, cookie, getexline)) 834 KeyTyped = FALSE; 835 836 /* 837 * Continue executing command lines: 838 * - when inside an ":if", ":while" or ":for" 839 * - for multiple commands on one line, separated with '|' 840 * - when repeating until there are no more lines (for ":source") 841 */ 842 next_cmdline = cmdline; 843 do 844 { 845 #ifdef FEAT_EVAL 846 getline_is_func = getline_equal(fgetline, cookie, get_func_line); 847 #endif 848 849 /* stop skipping cmds for an error msg after all endif/while/for */ 850 if (next_cmdline == NULL 851 #ifdef FEAT_EVAL 852 && !force_abort 853 && cstack.cs_idx < 0 854 && !(getline_is_func && func_has_abort(real_cookie)) 855 #endif 856 ) 857 did_emsg = FALSE; 858 859 /* 860 * 1. If repeating a line in a loop, get a line from lines_ga. 861 * 2. If no line given: Get an allocated line with fgetline(). 862 * 3. If a line is given: Make a copy, so we can mess with it. 863 */ 864 865 #ifdef FEAT_EVAL 866 /* 1. If repeating, get a previous line from lines_ga. */ 867 if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len) 868 { 869 /* Each '|' separated command is stored separately in lines_ga, to 870 * be able to jump to it. Don't use next_cmdline now. */ 871 vim_free(cmdline_copy); 872 cmdline_copy = NULL; 873 874 /* Check if a function has returned or, unless it has an unclosed 875 * try conditional, aborted. */ 876 if (getline_is_func) 877 { 878 # ifdef FEAT_PROFILE 879 if (do_profiling == PROF_YES) 880 func_line_end(real_cookie); 881 # endif 882 if (func_has_ended(real_cookie)) 883 { 884 retval = FAIL; 885 break; 886 } 887 } 888 #ifdef FEAT_PROFILE 889 else if (do_profiling == PROF_YES 890 && getline_equal(fgetline, cookie, getsourceline)) 891 script_line_end(); 892 #endif 893 894 /* Check if a sourced file hit a ":finish" command. */ 895 if (source_finished(fgetline, cookie)) 896 { 897 retval = FAIL; 898 break; 899 } 900 901 /* If breakpoints have been added/deleted need to check for it. */ 902 if (breakpoint != NULL && dbg_tick != NULL 903 && *dbg_tick != debug_tick) 904 { 905 *breakpoint = dbg_find_breakpoint( 906 getline_equal(fgetline, cookie, getsourceline), 907 fname, sourcing_lnum); 908 *dbg_tick = debug_tick; 909 } 910 911 next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line; 912 sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum; 913 914 /* Did we encounter a breakpoint? */ 915 if (breakpoint != NULL && *breakpoint != 0 916 && *breakpoint <= sourcing_lnum) 917 { 918 dbg_breakpoint(fname, sourcing_lnum); 919 /* Find next breakpoint. */ 920 *breakpoint = dbg_find_breakpoint( 921 getline_equal(fgetline, cookie, getsourceline), 922 fname, sourcing_lnum); 923 *dbg_tick = debug_tick; 924 } 925 # ifdef FEAT_PROFILE 926 if (do_profiling == PROF_YES) 927 { 928 if (getline_is_func) 929 func_line_start(real_cookie); 930 else if (getline_equal(fgetline, cookie, getsourceline)) 931 script_line_start(); 932 } 933 # endif 934 } 935 936 if (cstack.cs_looplevel > 0) 937 { 938 /* Inside a while/for loop we need to store the lines and use them 939 * again. Pass a different "fgetline" function to do_one_cmd() 940 * below, so that it stores lines in or reads them from 941 * "lines_ga". Makes it possible to define a function inside a 942 * while/for loop. */ 943 cmd_getline = get_loop_line; 944 cmd_cookie = (void *)&cmd_loop_cookie; 945 cmd_loop_cookie.lines_gap = &lines_ga; 946 cmd_loop_cookie.current_line = current_line; 947 cmd_loop_cookie.getline = fgetline; 948 cmd_loop_cookie.cookie = cookie; 949 cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len); 950 } 951 else 952 { 953 cmd_getline = fgetline; 954 cmd_cookie = cookie; 955 } 956 #endif 957 958 /* 2. If no line given, get an allocated line with fgetline(). */ 959 if (next_cmdline == NULL) 960 { 961 /* 962 * Need to set msg_didout for the first line after an ":if", 963 * otherwise the ":if" will be overwritten. 964 */ 965 if (count == 1 && getline_equal(fgetline, cookie, getexline)) 966 msg_didout = TRUE; 967 if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, 968 #ifdef FEAT_EVAL 969 cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2 970 #else 971 0 972 #endif 973 )) == NULL) 974 { 975 /* Don't call wait_return for aborted command line. The NULL 976 * returned for the end of a sourced file or executed function 977 * doesn't do this. */ 978 if (KeyTyped && !(flags & DOCMD_REPEAT)) 979 need_wait_return = FALSE; 980 retval = FAIL; 981 break; 982 } 983 used_getline = TRUE; 984 985 /* 986 * Keep the first typed line. Clear it when more lines are typed. 987 */ 988 if (flags & DOCMD_KEEPLINE) 989 { 990 vim_free(repeat_cmdline); 991 if (count == 0) 992 repeat_cmdline = vim_strsave(next_cmdline); 993 else 994 repeat_cmdline = NULL; 995 } 996 } 997 998 /* 3. Make a copy of the command so we can mess with it. */ 999 else if (cmdline_copy == NULL) 1000 { 1001 next_cmdline = vim_strsave(next_cmdline); 1002 if (next_cmdline == NULL) 1003 { 1004 EMSG(_(e_outofmem)); 1005 retval = FAIL; 1006 break; 1007 } 1008 } 1009 cmdline_copy = next_cmdline; 1010 1011 #ifdef FEAT_EVAL 1012 /* 1013 * Save the current line when inside a ":while" or ":for", and when 1014 * the command looks like a ":while" or ":for", because we may need it 1015 * later. When there is a '|' and another command, it is stored 1016 * separately, because we need to be able to jump back to it from an 1017 * :endwhile/:endfor. 1018 */ 1019 if (current_line == lines_ga.ga_len 1020 && (cstack.cs_looplevel || has_loop_cmd(next_cmdline))) 1021 { 1022 if (store_loop_line(&lines_ga, next_cmdline) == FAIL) 1023 { 1024 retval = FAIL; 1025 break; 1026 } 1027 } 1028 did_endif = FALSE; 1029 #endif 1030 1031 if (count++ == 0) 1032 { 1033 /* 1034 * All output from the commands is put below each other, without 1035 * waiting for a return. Don't do this when executing commands 1036 * from a script or when being called recursive (e.g. for ":e 1037 * +command file"). 1038 */ 1039 if (!(flags & DOCMD_NOWAIT) && !recursive) 1040 { 1041 msg_didout_before_start = msg_didout; 1042 msg_didany = FALSE; /* no output yet */ 1043 msg_start(); 1044 msg_scroll = TRUE; /* put messages below each other */ 1045 ++no_wait_return; /* don't wait for return until finished */ 1046 ++RedrawingDisabled; 1047 did_inc = TRUE; 1048 } 1049 } 1050 1051 if (p_verbose >= 15 && sourcing_name != NULL) 1052 { 1053 ++no_wait_return; 1054 verbose_enter_scroll(); 1055 1056 smsg((char_u *)_("line %ld: %s"), 1057 (long)sourcing_lnum, cmdline_copy); 1058 if (msg_silent == 0) 1059 msg_puts((char_u *)"\n"); /* don't overwrite this */ 1060 1061 verbose_leave_scroll(); 1062 --no_wait_return; 1063 } 1064 1065 /* 1066 * 2. Execute one '|' separated command. 1067 * do_one_cmd() will return NULL if there is no trailing '|'. 1068 * "cmdline_copy" can change, e.g. for '%' and '#' expansion. 1069 */ 1070 ++recursive; 1071 next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE, 1072 #ifdef FEAT_EVAL 1073 &cstack, 1074 #endif 1075 cmd_getline, cmd_cookie); 1076 --recursive; 1077 1078 #ifdef FEAT_EVAL 1079 if (cmd_cookie == (void *)&cmd_loop_cookie) 1080 /* Use "current_line" from "cmd_loop_cookie", it may have been 1081 * incremented when defining a function. */ 1082 current_line = cmd_loop_cookie.current_line; 1083 #endif 1084 1085 if (next_cmdline == NULL) 1086 { 1087 vim_free(cmdline_copy); 1088 cmdline_copy = NULL; 1089 #ifdef FEAT_CMDHIST 1090 /* 1091 * If the command was typed, remember it for the ':' register. 1092 * Do this AFTER executing the command to make :@: work. 1093 */ 1094 if (getline_equal(fgetline, cookie, getexline) 1095 && new_last_cmdline != NULL) 1096 { 1097 vim_free(last_cmdline); 1098 last_cmdline = new_last_cmdline; 1099 new_last_cmdline = NULL; 1100 } 1101 #endif 1102 } 1103 else 1104 { 1105 /* need to copy the command after the '|' to cmdline_copy, for the 1106 * next do_one_cmd() */ 1107 STRMOVE(cmdline_copy, next_cmdline); 1108 next_cmdline = cmdline_copy; 1109 } 1110 1111 1112 #ifdef FEAT_EVAL 1113 /* reset did_emsg for a function that is not aborted by an error */ 1114 if (did_emsg && !force_abort 1115 && getline_equal(fgetline, cookie, get_func_line) 1116 && !func_has_abort(real_cookie)) 1117 did_emsg = FALSE; 1118 1119 if (cstack.cs_looplevel > 0) 1120 { 1121 ++current_line; 1122 1123 /* 1124 * An ":endwhile", ":endfor" and ":continue" is handled here. 1125 * If we were executing commands, jump back to the ":while" or 1126 * ":for". 1127 * If we were not executing commands, decrement cs_looplevel. 1128 */ 1129 if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP)) 1130 { 1131 cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP); 1132 1133 /* Jump back to the matching ":while" or ":for". Be careful 1134 * not to use a cs_line[] from an entry that isn't a ":while" 1135 * or ":for": It would make "current_line" invalid and can 1136 * cause a crash. */ 1137 if (!did_emsg && !got_int && !did_throw 1138 && cstack.cs_idx >= 0 1139 && (cstack.cs_flags[cstack.cs_idx] 1140 & (CSF_WHILE | CSF_FOR)) 1141 && cstack.cs_line[cstack.cs_idx] >= 0 1142 && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE)) 1143 { 1144 current_line = cstack.cs_line[cstack.cs_idx]; 1145 /* remember we jumped there */ 1146 cstack.cs_lflags |= CSL_HAD_LOOP; 1147 line_breakcheck(); /* check if CTRL-C typed */ 1148 1149 /* Check for the next breakpoint at or after the ":while" 1150 * or ":for". */ 1151 if (breakpoint != NULL) 1152 { 1153 *breakpoint = dbg_find_breakpoint( 1154 getline_equal(fgetline, cookie, getsourceline), 1155 fname, 1156 ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1); 1157 *dbg_tick = debug_tick; 1158 } 1159 } 1160 else 1161 { 1162 /* can only get here with ":endwhile" or ":endfor" */ 1163 if (cstack.cs_idx >= 0) 1164 rewind_conditionals(&cstack, cstack.cs_idx - 1, 1165 CSF_WHILE | CSF_FOR, &cstack.cs_looplevel); 1166 } 1167 } 1168 1169 /* 1170 * For a ":while" or ":for" we need to remember the line number. 1171 */ 1172 else if (cstack.cs_lflags & CSL_HAD_LOOP) 1173 { 1174 cstack.cs_lflags &= ~CSL_HAD_LOOP; 1175 cstack.cs_line[cstack.cs_idx] = current_line - 1; 1176 } 1177 } 1178 1179 /* 1180 * When not inside any ":while" loop, clear remembered lines. 1181 */ 1182 if (cstack.cs_looplevel == 0) 1183 { 1184 if (lines_ga.ga_len > 0) 1185 { 1186 sourcing_lnum = 1187 ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; 1188 free_cmdlines(&lines_ga); 1189 } 1190 current_line = 0; 1191 } 1192 1193 /* 1194 * A ":finally" makes did_emsg, got_int, and did_throw pending for 1195 * being restored at the ":endtry". Reset them here and set the 1196 * ACTIVE and FINALLY flags, so that the finally clause gets executed. 1197 * This includes the case where a missing ":endif", ":endwhile" or 1198 * ":endfor" was detected by the ":finally" itself. 1199 */ 1200 if (cstack.cs_lflags & CSL_HAD_FINA) 1201 { 1202 cstack.cs_lflags &= ~CSL_HAD_FINA; 1203 report_make_pending(cstack.cs_pending[cstack.cs_idx] 1204 & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW), 1205 did_throw ? (void *)current_exception : NULL); 1206 did_emsg = got_int = did_throw = FALSE; 1207 cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY; 1208 } 1209 1210 /* Update global "trylevel" for recursive calls to do_cmdline() from 1211 * within this loop. */ 1212 trylevel = initial_trylevel + cstack.cs_trylevel; 1213 1214 /* 1215 * If the outermost try conditional (across function calls and sourced 1216 * files) is aborted because of an error, an interrupt, or an uncaught 1217 * exception, cancel everything. If it is left normally, reset 1218 * force_abort to get the non-EH compatible abortion behavior for 1219 * the rest of the script. 1220 */ 1221 if (trylevel == 0 && !did_emsg && !got_int && !did_throw) 1222 force_abort = FALSE; 1223 1224 /* Convert an interrupt to an exception if appropriate. */ 1225 (void)do_intthrow(&cstack); 1226 #endif /* FEAT_EVAL */ 1227 1228 } 1229 /* 1230 * Continue executing command lines when: 1231 * - no CTRL-C typed, no aborting error, no exception thrown or try 1232 * conditionals need to be checked for executing finally clauses or 1233 * catching an interrupt exception 1234 * - didn't get an error message or lines are not typed 1235 * - there is a command after '|', inside a :if, :while, :for or :try, or 1236 * looping for ":source" command or function call. 1237 */ 1238 while (!((got_int 1239 #ifdef FEAT_EVAL 1240 || (did_emsg && force_abort) || did_throw 1241 #endif 1242 ) 1243 #ifdef FEAT_EVAL 1244 && cstack.cs_trylevel == 0 1245 #endif 1246 ) 1247 && !(did_emsg 1248 #ifdef FEAT_EVAL 1249 /* Keep going when inside try/catch, so that the error can be 1250 * deal with, except when it is a syntax error, it may cause 1251 * the :endtry to be missed. */ 1252 && (cstack.cs_trylevel == 0 || did_emsg_syntax) 1253 #endif 1254 && used_getline 1255 && (getline_equal(fgetline, cookie, getexmodeline) 1256 || getline_equal(fgetline, cookie, getexline))) 1257 && (next_cmdline != NULL 1258 #ifdef FEAT_EVAL 1259 || cstack.cs_idx >= 0 1260 #endif 1261 || (flags & DOCMD_REPEAT))); 1262 1263 vim_free(cmdline_copy); 1264 did_emsg_syntax = FALSE; 1265 #ifdef FEAT_EVAL 1266 free_cmdlines(&lines_ga); 1267 ga_clear(&lines_ga); 1268 1269 if (cstack.cs_idx >= 0) 1270 { 1271 /* 1272 * If a sourced file or executed function ran to its end, report the 1273 * unclosed conditional. 1274 */ 1275 if (!got_int && !did_throw 1276 && ((getline_equal(fgetline, cookie, getsourceline) 1277 && !source_finished(fgetline, cookie)) 1278 || (getline_equal(fgetline, cookie, get_func_line) 1279 && !func_has_ended(real_cookie)))) 1280 { 1281 if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY) 1282 EMSG(_(e_endtry)); 1283 else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE) 1284 EMSG(_(e_endwhile)); 1285 else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR) 1286 EMSG(_(e_endfor)); 1287 else 1288 EMSG(_(e_endif)); 1289 } 1290 1291 /* 1292 * Reset "trylevel" in case of a ":finish" or ":return" or a missing 1293 * ":endtry" in a sourced file or executed function. If the try 1294 * conditional is in its finally clause, ignore anything pending. 1295 * If it is in a catch clause, finish the caught exception. 1296 * Also cleanup any "cs_forinfo" structures. 1297 */ 1298 do 1299 { 1300 int idx = cleanup_conditionals(&cstack, 0, TRUE); 1301 1302 if (idx >= 0) 1303 --idx; /* remove try block not in its finally clause */ 1304 rewind_conditionals(&cstack, idx, CSF_WHILE | CSF_FOR, 1305 &cstack.cs_looplevel); 1306 } 1307 while (cstack.cs_idx >= 0); 1308 trylevel = initial_trylevel; 1309 } 1310 1311 /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory 1312 * lack was reported above and the error message is to be converted to an 1313 * exception, do this now after rewinding the cstack. */ 1314 do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line) 1315 ? (char_u *)"endfunction" : (char_u *)NULL); 1316 1317 if (trylevel == 0) 1318 { 1319 /* 1320 * When an exception is being thrown out of the outermost try 1321 * conditional, discard the uncaught exception, disable the conversion 1322 * of interrupts or errors to exceptions, and ensure that no more 1323 * commands are executed. 1324 */ 1325 if (did_throw) 1326 { 1327 void *p = NULL; 1328 char_u *saved_sourcing_name; 1329 int saved_sourcing_lnum; 1330 struct msglist *messages = NULL, *next; 1331 1332 /* 1333 * If the uncaught exception is a user exception, report it as an 1334 * error. If it is an error exception, display the saved error 1335 * message now. For an interrupt exception, do nothing; the 1336 * interrupt message is given elsewhere. 1337 */ 1338 switch (current_exception->type) 1339 { 1340 case ET_USER: 1341 vim_snprintf((char *)IObuff, IOSIZE, 1342 _("E605: Exception not caught: %s"), 1343 current_exception->value); 1344 p = vim_strsave(IObuff); 1345 break; 1346 case ET_ERROR: 1347 messages = current_exception->messages; 1348 current_exception->messages = NULL; 1349 break; 1350 case ET_INTERRUPT: 1351 break; 1352 } 1353 1354 saved_sourcing_name = sourcing_name; 1355 saved_sourcing_lnum = sourcing_lnum; 1356 sourcing_name = current_exception->throw_name; 1357 sourcing_lnum = current_exception->throw_lnum; 1358 current_exception->throw_name = NULL; 1359 1360 discard_current_exception(); /* uses IObuff if 'verbose' */ 1361 suppress_errthrow = TRUE; 1362 force_abort = TRUE; 1363 1364 if (messages != NULL) 1365 { 1366 do 1367 { 1368 next = messages->next; 1369 emsg(messages->msg); 1370 vim_free(messages->msg); 1371 vim_free(messages); 1372 messages = next; 1373 } 1374 while (messages != NULL); 1375 } 1376 else if (p != NULL) 1377 { 1378 emsg(p); 1379 vim_free(p); 1380 } 1381 vim_free(sourcing_name); 1382 sourcing_name = saved_sourcing_name; 1383 sourcing_lnum = saved_sourcing_lnum; 1384 } 1385 1386 /* 1387 * On an interrupt or an aborting error not converted to an exception, 1388 * disable the conversion of errors to exceptions. (Interrupts are not 1389 * converted any more, here.) This enables also the interrupt message 1390 * when force_abort is set and did_emsg unset in case of an interrupt 1391 * from a finally clause after an error. 1392 */ 1393 else if (got_int || (did_emsg && force_abort)) 1394 suppress_errthrow = TRUE; 1395 } 1396 1397 /* 1398 * The current cstack will be freed when do_cmdline() returns. An uncaught 1399 * exception will have to be rethrown in the previous cstack. If a function 1400 * has just returned or a script file was just finished and the previous 1401 * cstack belongs to the same function or, respectively, script file, it 1402 * will have to be checked for finally clauses to be executed due to the 1403 * ":return" or ":finish". This is done in do_one_cmd(). 1404 */ 1405 if (did_throw) 1406 need_rethrow = TRUE; 1407 if ((getline_equal(fgetline, cookie, getsourceline) 1408 && ex_nesting_level > source_level(real_cookie)) 1409 || (getline_equal(fgetline, cookie, get_func_line) 1410 && ex_nesting_level > func_level(real_cookie) + 1)) 1411 { 1412 if (!did_throw) 1413 check_cstack = TRUE; 1414 } 1415 else 1416 { 1417 /* When leaving a function, reduce nesting level. */ 1418 if (getline_equal(fgetline, cookie, get_func_line)) 1419 --ex_nesting_level; 1420 /* 1421 * Go to debug mode when returning from a function in which we are 1422 * single-stepping. 1423 */ 1424 if ((getline_equal(fgetline, cookie, getsourceline) 1425 || getline_equal(fgetline, cookie, get_func_line)) 1426 && ex_nesting_level + 1 <= debug_break_level) 1427 do_debug(getline_equal(fgetline, cookie, getsourceline) 1428 ? (char_u *)_("End of sourced file") 1429 : (char_u *)_("End of function")); 1430 } 1431 1432 /* 1433 * Restore the exception environment (done after returning from the 1434 * debugger). 1435 */ 1436 if (flags & DOCMD_EXCRESET) 1437 restore_dbg_stuff(&debug_saved); 1438 1439 msg_list = saved_msg_list; 1440 #endif /* FEAT_EVAL */ 1441 1442 /* 1443 * If there was too much output to fit on the command line, ask the user to 1444 * hit return before redrawing the screen. With the ":global" command we do 1445 * this only once after the command is finished. 1446 */ 1447 if (did_inc) 1448 { 1449 --RedrawingDisabled; 1450 --no_wait_return; 1451 msg_scroll = FALSE; 1452 1453 /* 1454 * When just finished an ":if"-":else" which was typed, no need to 1455 * wait for hit-return. Also for an error situation. 1456 */ 1457 if (retval == FAIL 1458 #ifdef FEAT_EVAL 1459 || (did_endif && KeyTyped && !did_emsg) 1460 #endif 1461 ) 1462 { 1463 need_wait_return = FALSE; 1464 msg_didany = FALSE; /* don't wait when restarting edit */ 1465 } 1466 else if (need_wait_return) 1467 { 1468 /* 1469 * The msg_start() above clears msg_didout. The wait_return we do 1470 * here should not overwrite the command that may be shown before 1471 * doing that. 1472 */ 1473 msg_didout |= msg_didout_before_start; 1474 wait_return(FALSE); 1475 } 1476 } 1477 1478 #ifdef FEAT_EVAL 1479 did_endif = FALSE; /* in case do_cmdline used recursively */ 1480 #else 1481 /* 1482 * Reset if_level, in case a sourced script file contains more ":if" than 1483 * ":endif" (could be ":if x | foo | endif"). 1484 */ 1485 if_level = 0; 1486 #endif 1487 1488 --call_depth; 1489 return retval; 1490 } 1491 1492 #ifdef FEAT_EVAL 1493 /* 1494 * Obtain a line when inside a ":while" or ":for" loop. 1495 */ 1496 static char_u * 1497 get_loop_line(int c, void *cookie, int indent) 1498 { 1499 struct loop_cookie *cp = (struct loop_cookie *)cookie; 1500 wcmd_T *wp; 1501 char_u *line; 1502 1503 if (cp->current_line + 1 >= cp->lines_gap->ga_len) 1504 { 1505 if (cp->repeating) 1506 return NULL; /* trying to read past ":endwhile"/":endfor" */ 1507 1508 /* First time inside the ":while"/":for": get line normally. */ 1509 if (cp->getline == NULL) 1510 line = getcmdline(c, 0L, indent); 1511 else 1512 line = cp->getline(c, cp->cookie, indent); 1513 if (line != NULL && store_loop_line(cp->lines_gap, line) == OK) 1514 ++cp->current_line; 1515 1516 return line; 1517 } 1518 1519 KeyTyped = FALSE; 1520 ++cp->current_line; 1521 wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line; 1522 sourcing_lnum = wp->lnum; 1523 return vim_strsave(wp->line); 1524 } 1525 1526 /* 1527 * Store a line in "gap" so that a ":while" loop can execute it again. 1528 */ 1529 static int 1530 store_loop_line(garray_T *gap, char_u *line) 1531 { 1532 if (ga_grow(gap, 1) == FAIL) 1533 return FAIL; 1534 ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line); 1535 ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum; 1536 ++gap->ga_len; 1537 return OK; 1538 } 1539 1540 /* 1541 * Free the lines stored for a ":while" or ":for" loop. 1542 */ 1543 static void 1544 free_cmdlines(garray_T *gap) 1545 { 1546 while (gap->ga_len > 0) 1547 { 1548 vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line); 1549 --gap->ga_len; 1550 } 1551 } 1552 #endif 1553 1554 /* 1555 * If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals 1556 * "func". * Otherwise return TRUE when "fgetline" equals "func". 1557 */ 1558 int 1559 getline_equal( 1560 char_u *(*fgetline)(int, void *, int), 1561 void *cookie UNUSED, /* argument for fgetline() */ 1562 char_u *(*func)(int, void *, int)) 1563 { 1564 #ifdef FEAT_EVAL 1565 char_u *(*gp)(int, void *, int); 1566 struct loop_cookie *cp; 1567 1568 /* When "fgetline" is "get_loop_line()" use the "cookie" to find the 1569 * function that's originally used to obtain the lines. This may be 1570 * nested several levels. */ 1571 gp = fgetline; 1572 cp = (struct loop_cookie *)cookie; 1573 while (gp == get_loop_line) 1574 { 1575 gp = cp->getline; 1576 cp = cp->cookie; 1577 } 1578 return gp == func; 1579 #else 1580 return fgetline == func; 1581 #endif 1582 } 1583 1584 #if defined(FEAT_EVAL) || defined(FEAT_MBYTE) || defined(PROTO) 1585 /* 1586 * If "fgetline" is get_loop_line(), return the cookie used by the original 1587 * getline function. Otherwise return "cookie". 1588 */ 1589 void * 1590 getline_cookie( 1591 char_u *(*fgetline)(int, void *, int) UNUSED, 1592 void *cookie) /* argument for fgetline() */ 1593 { 1594 # ifdef FEAT_EVAL 1595 char_u *(*gp)(int, void *, int); 1596 struct loop_cookie *cp; 1597 1598 /* When "fgetline" is "get_loop_line()" use the "cookie" to find the 1599 * cookie that's originally used to obtain the lines. This may be nested 1600 * several levels. */ 1601 gp = fgetline; 1602 cp = (struct loop_cookie *)cookie; 1603 while (gp == get_loop_line) 1604 { 1605 gp = cp->getline; 1606 cp = cp->cookie; 1607 } 1608 return cp; 1609 # else 1610 return cookie; 1611 # endif 1612 } 1613 #endif 1614 1615 1616 /* 1617 * Helper function to apply an offset for buffer commands, i.e. ":bdelete", 1618 * ":bwipeout", etc. 1619 * Returns the buffer number. 1620 */ 1621 static int 1622 compute_buffer_local_count(int addr_type, int lnum, int offset) 1623 { 1624 buf_T *buf; 1625 buf_T *nextbuf; 1626 int count = offset; 1627 1628 buf = firstbuf; 1629 while (buf->b_next != NULL && buf->b_fnum < lnum) 1630 buf = buf->b_next; 1631 while (count != 0) 1632 { 1633 count += (offset < 0) ? 1 : -1; 1634 nextbuf = (offset < 0) ? buf->b_prev : buf->b_next; 1635 if (nextbuf == NULL) 1636 break; 1637 buf = nextbuf; 1638 if (addr_type == ADDR_LOADED_BUFFERS) 1639 /* skip over unloaded buffers */ 1640 while (buf->b_ml.ml_mfp == NULL) 1641 { 1642 nextbuf = (offset < 0) ? buf->b_prev : buf->b_next; 1643 if (nextbuf == NULL) 1644 break; 1645 buf = nextbuf; 1646 } 1647 } 1648 /* we might have gone too far, last buffer is not loadedd */ 1649 if (addr_type == ADDR_LOADED_BUFFERS) 1650 while (buf->b_ml.ml_mfp == NULL) 1651 { 1652 nextbuf = (offset >= 0) ? buf->b_prev : buf->b_next; 1653 if (nextbuf == NULL) 1654 break; 1655 buf = nextbuf; 1656 } 1657 return buf->b_fnum; 1658 } 1659 1660 static int current_win_nr(win_T *win); 1661 static int current_tab_nr(tabpage_T *tab); 1662 1663 static int 1664 current_win_nr(win_T *win) 1665 { 1666 win_T *wp; 1667 int nr = 0; 1668 1669 FOR_ALL_WINDOWS(wp) 1670 { 1671 ++nr; 1672 if (wp == win) 1673 break; 1674 } 1675 return nr; 1676 } 1677 1678 static int 1679 current_tab_nr(tabpage_T *tab) 1680 { 1681 tabpage_T *tp; 1682 int nr = 0; 1683 1684 FOR_ALL_TABPAGES(tp) 1685 { 1686 ++nr; 1687 if (tp == tab) 1688 break; 1689 } 1690 return nr; 1691 } 1692 1693 # define CURRENT_WIN_NR current_win_nr(curwin) 1694 # define LAST_WIN_NR current_win_nr(NULL) 1695 # define CURRENT_TAB_NR current_tab_nr(curtab) 1696 # define LAST_TAB_NR current_tab_nr(NULL) 1697 1698 /* 1699 * Execute one Ex command. 1700 * 1701 * If 'sourcing' is TRUE, the command will be included in the error message. 1702 * 1703 * 1. skip comment lines and leading space 1704 * 2. handle command modifiers 1705 * 3. find the command 1706 * 4. parse range 1707 * 5. Parse the command. 1708 * 6. parse arguments 1709 * 7. switch on command name 1710 * 1711 * Note: "fgetline" can be NULL. 1712 * 1713 * This function may be called recursively! 1714 */ 1715 #if (_MSC_VER == 1200) 1716 /* 1717 * Avoid optimisation bug in VC++ version 6.0 1718 */ 1719 #pragma optimize( "g", off ) 1720 #endif 1721 static char_u * 1722 do_one_cmd( 1723 char_u **cmdlinep, 1724 int sourcing, 1725 #ifdef FEAT_EVAL 1726 struct condstack *cstack, 1727 #endif 1728 char_u *(*fgetline)(int, void *, int), 1729 void *cookie) /* argument for fgetline() */ 1730 { 1731 char_u *p; 1732 linenr_T lnum; 1733 long n; 1734 char_u *errormsg = NULL; /* error message */ 1735 char_u *after_modifier = NULL; 1736 exarg_T ea; /* Ex command arguments */ 1737 long verbose_save = -1; 1738 int save_msg_scroll = msg_scroll; 1739 int save_msg_silent = -1; 1740 int did_esilent = 0; 1741 #ifdef HAVE_SANDBOX 1742 int did_sandbox = FALSE; 1743 #endif 1744 cmdmod_T save_cmdmod; 1745 int ni; /* set when Not Implemented */ 1746 char_u *cmd; 1747 int address_count = 1; 1748 1749 vim_memset(&ea, 0, sizeof(ea)); 1750 ea.line1 = 1; 1751 ea.line2 = 1; 1752 #ifdef FEAT_EVAL 1753 ++ex_nesting_level; 1754 #endif 1755 1756 /* When the last file has not been edited :q has to be typed twice. */ 1757 if (quitmore 1758 #ifdef FEAT_EVAL 1759 /* avoid that a function call in 'statusline' does this */ 1760 && !getline_equal(fgetline, cookie, get_func_line) 1761 #endif 1762 #ifdef FEAT_AUTOCMD 1763 /* avoid that an autocommand, e.g. QuitPre, does this */ 1764 && !getline_equal(fgetline, cookie, getnextac) 1765 #endif 1766 ) 1767 --quitmore; 1768 1769 /* 1770 * Reset browse, confirm, etc.. They are restored when returning, for 1771 * recursive calls. 1772 */ 1773 save_cmdmod = cmdmod; 1774 vim_memset(&cmdmod, 0, sizeof(cmdmod)); 1775 1776 /* "#!anything" is handled like a comment. */ 1777 if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!') 1778 goto doend; 1779 1780 /* 1781 * Repeat until no more command modifiers are found. 1782 */ 1783 ea.cmd = *cmdlinep; 1784 for (;;) 1785 { 1786 /* 1787 * 1. Skip comment lines and leading white space and colons. 1788 */ 1789 while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':') 1790 ++ea.cmd; 1791 1792 /* in ex mode, an empty line works like :+ */ 1793 if (*ea.cmd == NUL && exmode_active 1794 && (getline_equal(fgetline, cookie, getexmodeline) 1795 || getline_equal(fgetline, cookie, getexline)) 1796 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 1797 { 1798 ea.cmd = (char_u *)"+"; 1799 ex_pressedreturn = TRUE; 1800 } 1801 1802 /* ignore comment and empty lines */ 1803 if (*ea.cmd == '"') 1804 goto doend; 1805 if (*ea.cmd == NUL) 1806 { 1807 ex_pressedreturn = TRUE; 1808 goto doend; 1809 } 1810 1811 /* 1812 * 2. Handle command modifiers. 1813 */ 1814 p = skip_range(ea.cmd, NULL); 1815 switch (*p) 1816 { 1817 /* When adding an entry, also modify cmd_exists(). */ 1818 case 'a': if (!checkforcmd(&ea.cmd, "aboveleft", 3)) 1819 break; 1820 cmdmod.split |= WSP_ABOVE; 1821 continue; 1822 1823 case 'b': if (checkforcmd(&ea.cmd, "belowright", 3)) 1824 { 1825 cmdmod.split |= WSP_BELOW; 1826 continue; 1827 } 1828 if (checkforcmd(&ea.cmd, "browse", 3)) 1829 { 1830 #ifdef FEAT_BROWSE_CMD 1831 cmdmod.browse = TRUE; 1832 #endif 1833 continue; 1834 } 1835 if (!checkforcmd(&ea.cmd, "botright", 2)) 1836 break; 1837 cmdmod.split |= WSP_BOT; 1838 continue; 1839 1840 case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4)) 1841 break; 1842 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1843 cmdmod.confirm = TRUE; 1844 #endif 1845 continue; 1846 1847 case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3)) 1848 { 1849 cmdmod.keepmarks = TRUE; 1850 continue; 1851 } 1852 if (checkforcmd(&ea.cmd, "keepalt", 5)) 1853 { 1854 cmdmod.keepalt = TRUE; 1855 continue; 1856 } 1857 if (checkforcmd(&ea.cmd, "keeppatterns", 5)) 1858 { 1859 cmdmod.keeppatterns = TRUE; 1860 continue; 1861 } 1862 if (!checkforcmd(&ea.cmd, "keepjumps", 5)) 1863 break; 1864 cmdmod.keepjumps = TRUE; 1865 continue; 1866 1867 case 'f': /* only accept ":filter {pat} cmd" */ 1868 { 1869 char_u *reg_pat; 1870 1871 if (!checkforcmd(&p, "filter", 4) 1872 || *p == NUL || ends_excmd(*p)) 1873 break; 1874 if (*p == '!') 1875 { 1876 cmdmod.filter_force = TRUE; 1877 p = skipwhite(p + 1); 1878 if (*p == NUL || ends_excmd(*p)) 1879 break; 1880 } 1881 p = skip_vimgrep_pat(p, ®_pat, NULL); 1882 if (p == NULL || *p == NUL) 1883 break; 1884 cmdmod.filter_regmatch.regprog = 1885 vim_regcomp(reg_pat, RE_MAGIC); 1886 if (cmdmod.filter_regmatch.regprog == NULL) 1887 break; 1888 ea.cmd = p; 1889 continue; 1890 } 1891 1892 /* ":hide" and ":hide | cmd" are not modifiers */ 1893 case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3) 1894 || *p == NUL || ends_excmd(*p)) 1895 break; 1896 ea.cmd = p; 1897 cmdmod.hide = TRUE; 1898 continue; 1899 1900 case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3)) 1901 { 1902 cmdmod.lockmarks = TRUE; 1903 continue; 1904 } 1905 1906 if (!checkforcmd(&ea.cmd, "leftabove", 5)) 1907 break; 1908 cmdmod.split |= WSP_ABOVE; 1909 continue; 1910 1911 case 'n': if (checkforcmd(&ea.cmd, "noautocmd", 3)) 1912 { 1913 #ifdef FEAT_AUTOCMD 1914 if (cmdmod.save_ei == NULL) 1915 { 1916 /* Set 'eventignore' to "all". Restore the 1917 * existing option value later. */ 1918 cmdmod.save_ei = vim_strsave(p_ei); 1919 set_string_option_direct((char_u *)"ei", -1, 1920 (char_u *)"all", OPT_FREE, SID_NONE); 1921 } 1922 #endif 1923 continue; 1924 } 1925 if (!checkforcmd(&ea.cmd, "noswapfile", 3)) 1926 break; 1927 cmdmod.noswapfile = TRUE; 1928 continue; 1929 1930 case 'r': if (!checkforcmd(&ea.cmd, "rightbelow", 6)) 1931 break; 1932 cmdmod.split |= WSP_BELOW; 1933 continue; 1934 1935 case 's': if (checkforcmd(&ea.cmd, "sandbox", 3)) 1936 { 1937 #ifdef HAVE_SANDBOX 1938 if (!did_sandbox) 1939 ++sandbox; 1940 did_sandbox = TRUE; 1941 #endif 1942 continue; 1943 } 1944 if (!checkforcmd(&ea.cmd, "silent", 3)) 1945 break; 1946 if (save_msg_silent == -1) 1947 save_msg_silent = msg_silent; 1948 ++msg_silent; 1949 if (*ea.cmd == '!' && !VIM_ISWHITE(ea.cmd[-1])) 1950 { 1951 /* ":silent!", but not "silent !cmd" */ 1952 ea.cmd = skipwhite(ea.cmd + 1); 1953 ++emsg_silent; 1954 ++did_esilent; 1955 } 1956 continue; 1957 1958 case 't': if (checkforcmd(&p, "tab", 3)) 1959 { 1960 long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, 1961 ea.skip, FALSE, 1); 1962 if (tabnr == MAXLNUM) 1963 cmdmod.tab = tabpage_index(curtab) + 1; 1964 else 1965 { 1966 if (tabnr < 0 || tabnr > LAST_TAB_NR) 1967 { 1968 errormsg = (char_u *)_(e_invrange); 1969 goto doend; 1970 } 1971 cmdmod.tab = tabnr + 1; 1972 } 1973 ea.cmd = p; 1974 continue; 1975 } 1976 if (!checkforcmd(&ea.cmd, "topleft", 2)) 1977 break; 1978 cmdmod.split |= WSP_TOP; 1979 continue; 1980 1981 case 'u': if (!checkforcmd(&ea.cmd, "unsilent", 3)) 1982 break; 1983 if (save_msg_silent == -1) 1984 save_msg_silent = msg_silent; 1985 msg_silent = 0; 1986 continue; 1987 1988 case 'v': if (checkforcmd(&ea.cmd, "vertical", 4)) 1989 { 1990 cmdmod.split |= WSP_VERT; 1991 continue; 1992 } 1993 if (!checkforcmd(&p, "verbose", 4)) 1994 break; 1995 if (verbose_save < 0) 1996 verbose_save = p_verbose; 1997 if (vim_isdigit(*ea.cmd)) 1998 p_verbose = atoi((char *)ea.cmd); 1999 else 2000 p_verbose = 1; 2001 ea.cmd = p; 2002 continue; 2003 } 2004 break; 2005 } 2006 after_modifier = ea.cmd; 2007 2008 #ifdef FEAT_EVAL 2009 ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0 2010 && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)); 2011 #else 2012 ea.skip = (if_level > 0); 2013 #endif 2014 2015 #ifdef FEAT_EVAL 2016 # ifdef FEAT_PROFILE 2017 /* Count this line for profiling if ea.skip is FALSE. */ 2018 if (do_profiling == PROF_YES && !ea.skip) 2019 { 2020 if (getline_equal(fgetline, cookie, get_func_line)) 2021 func_line_exec(getline_cookie(fgetline, cookie)); 2022 else if (getline_equal(fgetline, cookie, getsourceline)) 2023 script_line_exec(); 2024 } 2025 #endif 2026 2027 /* May go to debug mode. If this happens and the ">quit" debug command is 2028 * used, throw an interrupt exception and skip the next command. */ 2029 dbg_check_breakpoint(&ea); 2030 if (!ea.skip && got_int) 2031 { 2032 ea.skip = TRUE; 2033 (void)do_intthrow(cstack); 2034 } 2035 #endif 2036 2037 /* 2038 * 3. Skip over the range to find the command. Let "p" point to after it. 2039 * 2040 * We need the command to know what kind of range it uses. 2041 */ 2042 cmd = ea.cmd; 2043 ea.cmd = skip_range(ea.cmd, NULL); 2044 if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) 2045 ea.cmd = skipwhite(ea.cmd + 1); 2046 p = find_command(&ea, NULL); 2047 2048 /* 2049 * 4. parse a range specifier of the form: addr [,addr] [;addr] .. 2050 * 2051 * where 'addr' is: 2052 * 2053 * % (entire file) 2054 * $ [+-NUM] 2055 * 'x [+-NUM] (where x denotes a currently defined mark) 2056 * . [+-NUM] 2057 * [+-NUM].. 2058 * NUM 2059 * 2060 * The ea.cmd pointer is updated to point to the first character following the 2061 * range spec. If an initial address is found, but no second, the upper bound 2062 * is equal to the lower. 2063 */ 2064 2065 /* ea.addr_type for user commands is set by find_ucmd */ 2066 if (!IS_USER_CMDIDX(ea.cmdidx)) 2067 { 2068 if (ea.cmdidx != CMD_SIZE) 2069 ea.addr_type = cmdnames[(int)ea.cmdidx].cmd_addr_type; 2070 else 2071 ea.addr_type = ADDR_LINES; 2072 2073 /* :wincmd range depends on the argument. */ 2074 if (ea.cmdidx == CMD_wincmd && p != NULL) 2075 get_wincmd_addr_type(skipwhite(p), &ea); 2076 } 2077 2078 /* repeat for all ',' or ';' separated addresses */ 2079 ea.cmd = cmd; 2080 for (;;) 2081 { 2082 ea.line1 = ea.line2; 2083 switch (ea.addr_type) 2084 { 2085 case ADDR_LINES: 2086 /* default is current line number */ 2087 ea.line2 = curwin->w_cursor.lnum; 2088 break; 2089 case ADDR_WINDOWS: 2090 ea.line2 = CURRENT_WIN_NR; 2091 break; 2092 case ADDR_ARGUMENTS: 2093 ea.line2 = curwin->w_arg_idx + 1; 2094 if (ea.line2 > ARGCOUNT) 2095 ea.line2 = ARGCOUNT; 2096 break; 2097 case ADDR_LOADED_BUFFERS: 2098 case ADDR_BUFFERS: 2099 ea.line2 = curbuf->b_fnum; 2100 break; 2101 case ADDR_TABS: 2102 ea.line2 = CURRENT_TAB_NR; 2103 break; 2104 case ADDR_TABS_RELATIVE: 2105 ea.line2 = 1; 2106 break; 2107 #ifdef FEAT_QUICKFIX 2108 case ADDR_QUICKFIX: 2109 ea.line2 = qf_get_cur_valid_idx(&ea); 2110 break; 2111 #endif 2112 } 2113 ea.cmd = skipwhite(ea.cmd); 2114 lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip, 2115 ea.addr_count == 0, address_count++); 2116 if (ea.cmd == NULL) /* error detected */ 2117 goto doend; 2118 if (lnum == MAXLNUM) 2119 { 2120 if (*ea.cmd == '%') /* '%' - all lines */ 2121 { 2122 ++ea.cmd; 2123 switch (ea.addr_type) 2124 { 2125 case ADDR_LINES: 2126 ea.line1 = 1; 2127 ea.line2 = curbuf->b_ml.ml_line_count; 2128 break; 2129 case ADDR_LOADED_BUFFERS: 2130 { 2131 buf_T *buf = firstbuf; 2132 2133 while (buf->b_next != NULL 2134 && buf->b_ml.ml_mfp == NULL) 2135 buf = buf->b_next; 2136 ea.line1 = buf->b_fnum; 2137 buf = lastbuf; 2138 while (buf->b_prev != NULL 2139 && buf->b_ml.ml_mfp == NULL) 2140 buf = buf->b_prev; 2141 ea.line2 = buf->b_fnum; 2142 break; 2143 } 2144 case ADDR_BUFFERS: 2145 ea.line1 = firstbuf->b_fnum; 2146 ea.line2 = lastbuf->b_fnum; 2147 break; 2148 case ADDR_WINDOWS: 2149 case ADDR_TABS: 2150 if (IS_USER_CMDIDX(ea.cmdidx)) 2151 { 2152 ea.line1 = 1; 2153 ea.line2 = ea.addr_type == ADDR_WINDOWS 2154 ? LAST_WIN_NR : LAST_TAB_NR; 2155 } 2156 else 2157 { 2158 /* there is no Vim command which uses '%' and 2159 * ADDR_WINDOWS or ADDR_TABS */ 2160 errormsg = (char_u *)_(e_invrange); 2161 goto doend; 2162 } 2163 break; 2164 case ADDR_TABS_RELATIVE: 2165 errormsg = (char_u *)_(e_invrange); 2166 goto doend; 2167 break; 2168 case ADDR_ARGUMENTS: 2169 if (ARGCOUNT == 0) 2170 ea.line1 = ea.line2 = 0; 2171 else 2172 { 2173 ea.line1 = 1; 2174 ea.line2 = ARGCOUNT; 2175 } 2176 break; 2177 #ifdef FEAT_QUICKFIX 2178 case ADDR_QUICKFIX: 2179 ea.line1 = 1; 2180 ea.line2 = qf_get_size(&ea); 2181 if (ea.line2 == 0) 2182 ea.line2 = 1; 2183 break; 2184 #endif 2185 } 2186 ++ea.addr_count; 2187 } 2188 /* '*' - visual area */ 2189 else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) 2190 { 2191 pos_T *fp; 2192 2193 if (ea.addr_type != ADDR_LINES) 2194 { 2195 errormsg = (char_u *)_(e_invrange); 2196 goto doend; 2197 } 2198 2199 ++ea.cmd; 2200 if (!ea.skip) 2201 { 2202 fp = getmark('<', FALSE); 2203 if (check_mark(fp) == FAIL) 2204 goto doend; 2205 ea.line1 = fp->lnum; 2206 fp = getmark('>', FALSE); 2207 if (check_mark(fp) == FAIL) 2208 goto doend; 2209 ea.line2 = fp->lnum; 2210 ++ea.addr_count; 2211 } 2212 } 2213 } 2214 else 2215 ea.line2 = lnum; 2216 ea.addr_count++; 2217 2218 if (*ea.cmd == ';') 2219 { 2220 if (!ea.skip) 2221 { 2222 curwin->w_cursor.lnum = ea.line2; 2223 /* don't leave the cursor on an illegal line or column */ 2224 check_cursor(); 2225 } 2226 } 2227 else if (*ea.cmd != ',') 2228 break; 2229 ++ea.cmd; 2230 } 2231 2232 /* One address given: set start and end lines */ 2233 if (ea.addr_count == 1) 2234 { 2235 ea.line1 = ea.line2; 2236 /* ... but only implicit: really no address given */ 2237 if (lnum == MAXLNUM) 2238 ea.addr_count = 0; 2239 } 2240 2241 /* 2242 * 5. Parse the command. 2243 */ 2244 2245 /* 2246 * Skip ':' and any white space 2247 */ 2248 ea.cmd = skipwhite(ea.cmd); 2249 while (*ea.cmd == ':') 2250 ea.cmd = skipwhite(ea.cmd + 1); 2251 2252 /* 2253 * If we got a line, but no command, then go to the line. 2254 * If we find a '|' or '\n' we set ea.nextcmd. 2255 */ 2256 if (*ea.cmd == NUL || *ea.cmd == '"' 2257 || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) 2258 { 2259 /* 2260 * strange vi behaviour: 2261 * ":3" jumps to line 3 2262 * ":3|..." prints line 3 2263 * ":|" prints current line 2264 */ 2265 if (ea.skip) /* skip this if inside :if */ 2266 goto doend; 2267 if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) 2268 { 2269 ea.cmdidx = CMD_print; 2270 ea.argt = RANGE+COUNT+TRLBAR; 2271 if ((errormsg = invalid_range(&ea)) == NULL) 2272 { 2273 correct_range(&ea); 2274 ex_print(&ea); 2275 } 2276 } 2277 else if (ea.addr_count != 0) 2278 { 2279 if (ea.line2 > curbuf->b_ml.ml_line_count) 2280 { 2281 /* With '-' in 'cpoptions' a line number past the file is an 2282 * error, otherwise put it at the end of the file. */ 2283 if (vim_strchr(p_cpo, CPO_MINUS) != NULL) 2284 ea.line2 = -1; 2285 else 2286 ea.line2 = curbuf->b_ml.ml_line_count; 2287 } 2288 2289 if (ea.line2 < 0) 2290 errormsg = (char_u *)_(e_invrange); 2291 else 2292 { 2293 if (ea.line2 == 0) 2294 curwin->w_cursor.lnum = 1; 2295 else 2296 curwin->w_cursor.lnum = ea.line2; 2297 beginline(BL_SOL | BL_FIX); 2298 } 2299 } 2300 goto doend; 2301 } 2302 2303 #ifdef FEAT_AUTOCMD 2304 /* If this looks like an undefined user command and there are CmdUndefined 2305 * autocommands defined, trigger the matching autocommands. */ 2306 if (p != NULL && ea.cmdidx == CMD_SIZE && !ea.skip 2307 && ASCII_ISUPPER(*ea.cmd) 2308 && has_cmdundefined()) 2309 { 2310 int ret; 2311 2312 p = ea.cmd; 2313 while (ASCII_ISALNUM(*p)) 2314 ++p; 2315 p = vim_strnsave(ea.cmd, (int)(p - ea.cmd)); 2316 ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, TRUE, NULL); 2317 vim_free(p); 2318 /* If the autocommands did something and didn't cause an error, try 2319 * finding the command again. */ 2320 p = (ret && !aborting()) ? find_command(&ea, NULL) : ea.cmd; 2321 } 2322 #endif 2323 2324 #ifdef FEAT_USR_CMDS 2325 if (p == NULL) 2326 { 2327 if (!ea.skip) 2328 errormsg = (char_u *)_("E464: Ambiguous use of user-defined command"); 2329 goto doend; 2330 } 2331 /* Check for wrong commands. */ 2332 if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78 2333 && !IS_USER_CMDIDX(ea.cmdidx)) 2334 { 2335 errormsg = uc_fun_cmd(); 2336 goto doend; 2337 } 2338 #endif 2339 if (ea.cmdidx == CMD_SIZE) 2340 { 2341 if (!ea.skip) 2342 { 2343 STRCPY(IObuff, _("E492: Not an editor command")); 2344 if (!sourcing) 2345 { 2346 /* If the modifier was parsed OK the error must be in the 2347 * following command */ 2348 if (after_modifier != NULL) 2349 append_command(after_modifier); 2350 else 2351 append_command(*cmdlinep); 2352 } 2353 errormsg = IObuff; 2354 did_emsg_syntax = TRUE; 2355 } 2356 goto doend; 2357 } 2358 2359 ni = (!IS_USER_CMDIDX(ea.cmdidx) 2360 && (cmdnames[ea.cmdidx].cmd_func == ex_ni 2361 #ifdef HAVE_EX_SCRIPT_NI 2362 || cmdnames[ea.cmdidx].cmd_func == ex_script_ni 2363 #endif 2364 )); 2365 2366 #ifndef FEAT_EVAL 2367 /* 2368 * When the expression evaluation is disabled, recognize the ":if" and 2369 * ":endif" commands and ignore everything in between it. 2370 */ 2371 if (ea.cmdidx == CMD_if) 2372 ++if_level; 2373 if (if_level) 2374 { 2375 if (ea.cmdidx == CMD_endif) 2376 --if_level; 2377 goto doend; 2378 } 2379 2380 #endif 2381 2382 /* forced commands */ 2383 if (*p == '!' && ea.cmdidx != CMD_substitute 2384 && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) 2385 { 2386 ++p; 2387 ea.forceit = TRUE; 2388 } 2389 else 2390 ea.forceit = FALSE; 2391 2392 /* 2393 * 6. Parse arguments. 2394 */ 2395 if (!IS_USER_CMDIDX(ea.cmdidx)) 2396 ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt; 2397 2398 if (!ea.skip) 2399 { 2400 #ifdef HAVE_SANDBOX 2401 if (sandbox != 0 && !(ea.argt & SBOXOK)) 2402 { 2403 /* Command not allowed in sandbox. */ 2404 errormsg = (char_u *)_(e_sandbox); 2405 goto doend; 2406 } 2407 #endif 2408 if (!curbuf->b_p_ma && (ea.argt & MODIFY)) 2409 { 2410 /* Command not allowed in non-'modifiable' buffer */ 2411 errormsg = (char_u *)_(e_modifiable); 2412 goto doend; 2413 } 2414 2415 if (text_locked() && !(ea.argt & CMDWIN) 2416 && !IS_USER_CMDIDX(ea.cmdidx)) 2417 { 2418 /* Command not allowed when editing the command line. */ 2419 errormsg = (char_u *)_(get_text_locked_msg()); 2420 goto doend; 2421 } 2422 #ifdef FEAT_AUTOCMD 2423 /* Disallow editing another buffer when "curbuf_lock" is set. 2424 * Do allow ":edit" (check for argument later). 2425 * Do allow ":checktime" (it's postponed). */ 2426 if (!(ea.argt & CMDWIN) 2427 && ea.cmdidx != CMD_edit 2428 && ea.cmdidx != CMD_checktime 2429 && !IS_USER_CMDIDX(ea.cmdidx) 2430 && curbuf_locked()) 2431 goto doend; 2432 #endif 2433 2434 if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) 2435 { 2436 /* no range allowed */ 2437 errormsg = (char_u *)_(e_norange); 2438 goto doend; 2439 } 2440 } 2441 2442 if (!ni && !(ea.argt & BANG) && ea.forceit) /* no <!> allowed */ 2443 { 2444 errormsg = (char_u *)_(e_nobang); 2445 goto doend; 2446 } 2447 2448 /* 2449 * Don't complain about the range if it is not used 2450 * (could happen if line_count is accidentally set to 0). 2451 */ 2452 if (!ea.skip && !ni) 2453 { 2454 /* 2455 * If the range is backwards, ask for confirmation and, if given, swap 2456 * ea.line1 & ea.line2 so it's forwards again. 2457 * When global command is busy, don't ask, will fail below. 2458 */ 2459 if (!global_busy && ea.line1 > ea.line2) 2460 { 2461 if (msg_silent == 0) 2462 { 2463 if (sourcing || exmode_active) 2464 { 2465 errormsg = (char_u *)_("E493: Backwards range given"); 2466 goto doend; 2467 } 2468 if (ask_yesno((char_u *) 2469 _("Backwards range given, OK to swap"), FALSE) != 'y') 2470 goto doend; 2471 } 2472 lnum = ea.line1; 2473 ea.line1 = ea.line2; 2474 ea.line2 = lnum; 2475 } 2476 if ((errormsg = invalid_range(&ea)) != NULL) 2477 goto doend; 2478 } 2479 2480 if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */ 2481 ea.line2 = 1; 2482 2483 correct_range(&ea); 2484 2485 #ifdef FEAT_FOLDING 2486 if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy 2487 && ea.addr_type == ADDR_LINES) 2488 { 2489 /* Put the first line at the start of a closed fold, put the last line 2490 * at the end of a closed fold. */ 2491 (void)hasFolding(ea.line1, &ea.line1, NULL); 2492 (void)hasFolding(ea.line2, NULL, &ea.line2); 2493 } 2494 #endif 2495 2496 #ifdef FEAT_QUICKFIX 2497 /* 2498 * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg' 2499 * option here, so things like % get expanded. 2500 */ 2501 p = replace_makeprg(&ea, p, cmdlinep); 2502 if (p == NULL) 2503 goto doend; 2504 #endif 2505 2506 /* 2507 * Skip to start of argument. 2508 * Don't do this for the ":!" command, because ":!! -l" needs the space. 2509 */ 2510 if (ea.cmdidx == CMD_bang) 2511 ea.arg = p; 2512 else 2513 ea.arg = skipwhite(p); 2514 2515 /* 2516 * Check for "++opt=val" argument. 2517 * Must be first, allow ":w ++enc=utf8 !cmd" 2518 */ 2519 if (ea.argt & ARGOPT) 2520 while (ea.arg[0] == '+' && ea.arg[1] == '+') 2521 if (getargopt(&ea) == FAIL && !ni) 2522 { 2523 errormsg = (char_u *)_(e_invarg); 2524 goto doend; 2525 } 2526 2527 if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) 2528 { 2529 if (*ea.arg == '>') /* append */ 2530 { 2531 if (*++ea.arg != '>') /* typed wrong */ 2532 { 2533 errormsg = (char_u *)_("E494: Use w or w>>"); 2534 goto doend; 2535 } 2536 ea.arg = skipwhite(ea.arg + 1); 2537 ea.append = TRUE; 2538 } 2539 else if (*ea.arg == '!' && ea.cmdidx == CMD_write) /* :w !filter */ 2540 { 2541 ++ea.arg; 2542 ea.usefilter = TRUE; 2543 } 2544 } 2545 2546 if (ea.cmdidx == CMD_read) 2547 { 2548 if (ea.forceit) 2549 { 2550 ea.usefilter = TRUE; /* :r! filter if ea.forceit */ 2551 ea.forceit = FALSE; 2552 } 2553 else if (*ea.arg == '!') /* :r !filter */ 2554 { 2555 ++ea.arg; 2556 ea.usefilter = TRUE; 2557 } 2558 } 2559 2560 if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) 2561 { 2562 ea.amount = 1; 2563 while (*ea.arg == *ea.cmd) /* count number of '>' or '<' */ 2564 { 2565 ++ea.arg; 2566 ++ea.amount; 2567 } 2568 ea.arg = skipwhite(ea.arg); 2569 } 2570 2571 /* 2572 * Check for "+command" argument, before checking for next command. 2573 * Don't do this for ":read !cmd" and ":write !cmd". 2574 */ 2575 if ((ea.argt & EDITCMD) && !ea.usefilter) 2576 ea.do_ecmd_cmd = getargcmd(&ea.arg); 2577 2578 /* 2579 * Check for '|' to separate commands and '"' to start comments. 2580 * Don't do this for ":read !cmd" and ":write !cmd". 2581 */ 2582 if ((ea.argt & TRLBAR) && !ea.usefilter) 2583 separate_nextcmd(&ea); 2584 2585 /* 2586 * Check for <newline> to end a shell command. 2587 * Also do this for ":read !cmd", ":write !cmd" and ":global". 2588 * Any others? 2589 */ 2590 else if (ea.cmdidx == CMD_bang 2591 || ea.cmdidx == CMD_terminal 2592 || ea.cmdidx == CMD_global 2593 || ea.cmdidx == CMD_vglobal 2594 || ea.usefilter) 2595 { 2596 for (p = ea.arg; *p; ++p) 2597 { 2598 /* Remove one backslash before a newline, so that it's possible to 2599 * pass a newline to the shell and also a newline that is preceded 2600 * with a backslash. This makes it impossible to end a shell 2601 * command in a backslash, but that doesn't appear useful. 2602 * Halving the number of backslashes is incompatible with previous 2603 * versions. */ 2604 if (*p == '\\' && p[1] == '\n') 2605 STRMOVE(p, p + 1); 2606 else if (*p == '\n') 2607 { 2608 ea.nextcmd = p + 1; 2609 *p = NUL; 2610 break; 2611 } 2612 } 2613 } 2614 2615 if ((ea.argt & DFLALL) && ea.addr_count == 0) 2616 { 2617 buf_T *buf; 2618 2619 ea.line1 = 1; 2620 switch (ea.addr_type) 2621 { 2622 case ADDR_LINES: 2623 ea.line2 = curbuf->b_ml.ml_line_count; 2624 break; 2625 case ADDR_LOADED_BUFFERS: 2626 buf = firstbuf; 2627 while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL) 2628 buf = buf->b_next; 2629 ea.line1 = buf->b_fnum; 2630 buf = lastbuf; 2631 while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL) 2632 buf = buf->b_prev; 2633 ea.line2 = buf->b_fnum; 2634 break; 2635 case ADDR_BUFFERS: 2636 ea.line1 = firstbuf->b_fnum; 2637 ea.line2 = lastbuf->b_fnum; 2638 break; 2639 case ADDR_WINDOWS: 2640 ea.line2 = LAST_WIN_NR; 2641 break; 2642 case ADDR_TABS: 2643 ea.line2 = LAST_TAB_NR; 2644 break; 2645 case ADDR_TABS_RELATIVE: 2646 ea.line2 = 1; 2647 break; 2648 case ADDR_ARGUMENTS: 2649 if (ARGCOUNT == 0) 2650 ea.line1 = ea.line2 = 0; 2651 else 2652 ea.line2 = ARGCOUNT; 2653 break; 2654 #ifdef FEAT_QUICKFIX 2655 case ADDR_QUICKFIX: 2656 ea.line2 = qf_get_size(&ea); 2657 if (ea.line2 == 0) 2658 ea.line2 = 1; 2659 break; 2660 #endif 2661 } 2662 } 2663 2664 /* accept numbered register only when no count allowed (:put) */ 2665 if ( (ea.argt & REGSTR) 2666 && *ea.arg != NUL 2667 /* Do not allow register = for user commands */ 2668 && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') 2669 && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg))) 2670 { 2671 #ifndef FEAT_CLIPBOARD 2672 /* check these explicitly for a more specific error message */ 2673 if (*ea.arg == '*' || *ea.arg == '+') 2674 { 2675 errormsg = (char_u *)_(e_invalidreg); 2676 goto doend; 2677 } 2678 #endif 2679 if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put 2680 && !IS_USER_CMDIDX(ea.cmdidx)))) 2681 { 2682 ea.regname = *ea.arg++; 2683 #ifdef FEAT_EVAL 2684 /* for '=' register: accept the rest of the line as an expression */ 2685 if (ea.arg[-1] == '=' && ea.arg[0] != NUL) 2686 { 2687 set_expr_line(vim_strsave(ea.arg)); 2688 ea.arg += STRLEN(ea.arg); 2689 } 2690 #endif 2691 ea.arg = skipwhite(ea.arg); 2692 } 2693 } 2694 2695 /* 2696 * Check for a count. When accepting a BUFNAME, don't use "123foo" as a 2697 * count, it's a buffer name. 2698 */ 2699 if ((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg) 2700 && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL 2701 || VIM_ISWHITE(*p))) 2702 { 2703 n = getdigits(&ea.arg); 2704 ea.arg = skipwhite(ea.arg); 2705 if (n <= 0 && !ni && (ea.argt & ZEROR) == 0) 2706 { 2707 errormsg = (char_u *)_(e_zerocount); 2708 goto doend; 2709 } 2710 if (ea.argt & NOTADR) /* e.g. :buffer 2, :sleep 3 */ 2711 { 2712 ea.line2 = n; 2713 if (ea.addr_count == 0) 2714 ea.addr_count = 1; 2715 } 2716 else 2717 { 2718 ea.line1 = ea.line2; 2719 ea.line2 += n - 1; 2720 ++ea.addr_count; 2721 /* 2722 * Be vi compatible: no error message for out of range. 2723 */ 2724 if (ea.addr_type == ADDR_LINES 2725 && ea.line2 > curbuf->b_ml.ml_line_count) 2726 ea.line2 = curbuf->b_ml.ml_line_count; 2727 } 2728 } 2729 2730 /* 2731 * Check for flags: 'l', 'p' and '#'. 2732 */ 2733 if (ea.argt & EXFLAGS) 2734 get_flags(&ea); 2735 /* no arguments allowed */ 2736 if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL 2737 && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & TRLBAR) == 0)) 2738 { 2739 errormsg = (char_u *)_(e_trailing); 2740 goto doend; 2741 } 2742 2743 if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL) 2744 { 2745 errormsg = (char_u *)_(e_argreq); 2746 goto doend; 2747 } 2748 2749 #ifdef FEAT_EVAL 2750 /* 2751 * Skip the command when it's not going to be executed. 2752 * The commands like :if, :endif, etc. always need to be executed. 2753 * Also make an exception for commands that handle a trailing command 2754 * themselves. 2755 */ 2756 if (ea.skip) 2757 { 2758 switch (ea.cmdidx) 2759 { 2760 /* commands that need evaluation */ 2761 case CMD_while: 2762 case CMD_endwhile: 2763 case CMD_for: 2764 case CMD_endfor: 2765 case CMD_if: 2766 case CMD_elseif: 2767 case CMD_else: 2768 case CMD_endif: 2769 case CMD_try: 2770 case CMD_catch: 2771 case CMD_finally: 2772 case CMD_endtry: 2773 case CMD_function: 2774 break; 2775 2776 /* Commands that handle '|' themselves. Check: A command should 2777 * either have the TRLBAR flag, appear in this list or appear in 2778 * the list at ":help :bar". */ 2779 case CMD_aboveleft: 2780 case CMD_and: 2781 case CMD_belowright: 2782 case CMD_botright: 2783 case CMD_browse: 2784 case CMD_call: 2785 case CMD_confirm: 2786 case CMD_delfunction: 2787 case CMD_djump: 2788 case CMD_dlist: 2789 case CMD_dsearch: 2790 case CMD_dsplit: 2791 case CMD_echo: 2792 case CMD_echoerr: 2793 case CMD_echomsg: 2794 case CMD_echon: 2795 case CMD_execute: 2796 case CMD_filter: 2797 case CMD_help: 2798 case CMD_hide: 2799 case CMD_ijump: 2800 case CMD_ilist: 2801 case CMD_isearch: 2802 case CMD_isplit: 2803 case CMD_keepalt: 2804 case CMD_keepjumps: 2805 case CMD_keepmarks: 2806 case CMD_keeppatterns: 2807 case CMD_leftabove: 2808 case CMD_let: 2809 case CMD_lockmarks: 2810 case CMD_lua: 2811 case CMD_match: 2812 case CMD_mzscheme: 2813 case CMD_noautocmd: 2814 case CMD_noswapfile: 2815 case CMD_perl: 2816 case CMD_psearch: 2817 case CMD_python: 2818 case CMD_py3: 2819 case CMD_python3: 2820 case CMD_return: 2821 case CMD_rightbelow: 2822 case CMD_ruby: 2823 case CMD_silent: 2824 case CMD_smagic: 2825 case CMD_snomagic: 2826 case CMD_substitute: 2827 case CMD_syntax: 2828 case CMD_tab: 2829 case CMD_tcl: 2830 case CMD_throw: 2831 case CMD_tilde: 2832 case CMD_topleft: 2833 case CMD_unlet: 2834 case CMD_verbose: 2835 case CMD_vertical: 2836 case CMD_wincmd: 2837 break; 2838 2839 default: goto doend; 2840 } 2841 } 2842 #endif 2843 2844 if (ea.argt & XFILE) 2845 { 2846 if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) 2847 goto doend; 2848 } 2849 2850 #ifdef FEAT_LISTCMDS 2851 /* 2852 * Accept buffer name. Cannot be used at the same time with a buffer 2853 * number. Don't do this for a user command. 2854 */ 2855 if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0 2856 && !IS_USER_CMDIDX(ea.cmdidx)) 2857 { 2858 /* 2859 * :bdelete, :bwipeout and :bunload take several arguments, separated 2860 * by spaces: find next space (skipping over escaped characters). 2861 * The others take one argument: ignore trailing spaces. 2862 */ 2863 if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout 2864 || ea.cmdidx == CMD_bunload) 2865 p = skiptowhite_esc(ea.arg); 2866 else 2867 { 2868 p = ea.arg + STRLEN(ea.arg); 2869 while (p > ea.arg && VIM_ISWHITE(p[-1])) 2870 --p; 2871 } 2872 ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0, 2873 FALSE, FALSE); 2874 if (ea.line2 < 0) /* failed */ 2875 goto doend; 2876 ea.addr_count = 1; 2877 ea.arg = skipwhite(p); 2878 } 2879 #endif 2880 2881 /* 2882 * 7. Switch on command name. 2883 * 2884 * The "ea" structure holds the arguments that can be used. 2885 */ 2886 ea.cmdlinep = cmdlinep; 2887 ea.getline = fgetline; 2888 ea.cookie = cookie; 2889 #ifdef FEAT_EVAL 2890 ea.cstack = cstack; 2891 #endif 2892 2893 #ifdef FEAT_USR_CMDS 2894 if (IS_USER_CMDIDX(ea.cmdidx)) 2895 { 2896 /* 2897 * Execute a user-defined command. 2898 */ 2899 do_ucmd(&ea); 2900 } 2901 else 2902 #endif 2903 { 2904 /* 2905 * Call the function to execute the command. 2906 */ 2907 ea.errmsg = NULL; 2908 (cmdnames[ea.cmdidx].cmd_func)(&ea); 2909 if (ea.errmsg != NULL) 2910 errormsg = (char_u *)_(ea.errmsg); 2911 } 2912 2913 #ifdef FEAT_EVAL 2914 /* 2915 * If the command just executed called do_cmdline(), any throw or ":return" 2916 * or ":finish" encountered there must also check the cstack of the still 2917 * active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught 2918 * exception, or reanimate a returned function or finished script file and 2919 * return or finish it again. 2920 */ 2921 if (need_rethrow) 2922 do_throw(cstack); 2923 else if (check_cstack) 2924 { 2925 if (source_finished(fgetline, cookie)) 2926 do_finish(&ea, TRUE); 2927 else if (getline_equal(fgetline, cookie, get_func_line) 2928 && current_func_returned()) 2929 do_return(&ea, TRUE, FALSE, NULL); 2930 } 2931 need_rethrow = check_cstack = FALSE; 2932 #endif 2933 2934 doend: 2935 if (curwin->w_cursor.lnum == 0) /* can happen with zero line number */ 2936 { 2937 curwin->w_cursor.lnum = 1; 2938 curwin->w_cursor.col = 0; 2939 } 2940 2941 if (errormsg != NULL && *errormsg != NUL && !did_emsg) 2942 { 2943 if (sourcing) 2944 { 2945 if (errormsg != IObuff) 2946 { 2947 STRCPY(IObuff, errormsg); 2948 errormsg = IObuff; 2949 } 2950 append_command(*cmdlinep); 2951 } 2952 emsg(errormsg); 2953 } 2954 #ifdef FEAT_EVAL 2955 do_errthrow(cstack, 2956 (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx)) 2957 ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL); 2958 #endif 2959 2960 if (verbose_save >= 0) 2961 p_verbose = verbose_save; 2962 #ifdef FEAT_AUTOCMD 2963 if (cmdmod.save_ei != NULL) 2964 { 2965 /* Restore 'eventignore' to the value before ":noautocmd". */ 2966 set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei, 2967 OPT_FREE, SID_NONE); 2968 free_string_option(cmdmod.save_ei); 2969 } 2970 #endif 2971 if (cmdmod.filter_regmatch.regprog != NULL) 2972 vim_regfree(cmdmod.filter_regmatch.regprog); 2973 2974 cmdmod = save_cmdmod; 2975 2976 if (save_msg_silent != -1) 2977 { 2978 /* messages could be enabled for a serious error, need to check if the 2979 * counters don't become negative */ 2980 if (!did_emsg || msg_silent > save_msg_silent) 2981 msg_silent = save_msg_silent; 2982 emsg_silent -= did_esilent; 2983 if (emsg_silent < 0) 2984 emsg_silent = 0; 2985 /* Restore msg_scroll, it's set by file I/O commands, even when no 2986 * message is actually displayed. */ 2987 msg_scroll = save_msg_scroll; 2988 2989 /* "silent reg" or "silent echo x" inside "redir" leaves msg_col 2990 * somewhere in the line. Put it back in the first column. */ 2991 if (redirecting()) 2992 msg_col = 0; 2993 } 2994 2995 #ifdef HAVE_SANDBOX 2996 if (did_sandbox) 2997 --sandbox; 2998 #endif 2999 3000 if (ea.nextcmd && *ea.nextcmd == NUL) /* not really a next command */ 3001 ea.nextcmd = NULL; 3002 3003 #ifdef FEAT_EVAL 3004 --ex_nesting_level; 3005 #endif 3006 3007 return ea.nextcmd; 3008 } 3009 #if (_MSC_VER == 1200) 3010 #pragma optimize( "", on ) 3011 #endif 3012 3013 /* 3014 * Check for an Ex command with optional tail. 3015 * If there is a match advance "pp" to the argument and return TRUE. 3016 */ 3017 int 3018 checkforcmd( 3019 char_u **pp, /* start of command */ 3020 char *cmd, /* name of command */ 3021 int len) /* required length */ 3022 { 3023 int i; 3024 3025 for (i = 0; cmd[i] != NUL; ++i) 3026 if (((char_u *)cmd)[i] != (*pp)[i]) 3027 break; 3028 if (i >= len && !isalpha((*pp)[i])) 3029 { 3030 *pp = skipwhite(*pp + i); 3031 return TRUE; 3032 } 3033 return FALSE; 3034 } 3035 3036 /* 3037 * Append "cmd" to the error message in IObuff. 3038 * Takes care of limiting the length and handling 0xa0, which would be 3039 * invisible otherwise. 3040 */ 3041 static void 3042 append_command(char_u *cmd) 3043 { 3044 char_u *s = cmd; 3045 char_u *d; 3046 3047 STRCAT(IObuff, ": "); 3048 d = IObuff + STRLEN(IObuff); 3049 while (*s != NUL && d - IObuff < IOSIZE - 7) 3050 { 3051 if ( 3052 #ifdef FEAT_MBYTE 3053 enc_utf8 ? (s[0] == 0xc2 && s[1] == 0xa0) : 3054 #endif 3055 *s == 0xa0) 3056 { 3057 s += 3058 #ifdef FEAT_MBYTE 3059 enc_utf8 ? 2 : 3060 #endif 3061 1; 3062 STRCPY(d, "<a0>"); 3063 d += 4; 3064 } 3065 else 3066 MB_COPY_CHAR(s, d); 3067 } 3068 *d = NUL; 3069 } 3070 3071 /* 3072 * Find an Ex command by its name, either built-in or user. 3073 * Start of the name can be found at eap->cmd. 3074 * Returns pointer to char after the command name. 3075 * "full" is set to TRUE if the whole command name matched. 3076 * Returns NULL for an ambiguous user command. 3077 */ 3078 static char_u * 3079 find_command(exarg_T *eap, int *full UNUSED) 3080 { 3081 int len; 3082 char_u *p; 3083 int i; 3084 3085 /* 3086 * Isolate the command and search for it in the command table. 3087 * Exceptions: 3088 * - the 'k' command can directly be followed by any character. 3089 * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' 3090 * but :sre[wind] is another command, as are :scr[iptnames], 3091 * :scs[cope], :sim[alt], :sig[ns] and :sil[ent]. 3092 * - the "d" command can directly be followed by 'l' or 'p' flag. 3093 */ 3094 p = eap->cmd; 3095 if (*p == 'k') 3096 { 3097 eap->cmdidx = CMD_k; 3098 ++p; 3099 } 3100 else if (p[0] == 's' 3101 && ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r' 3102 && (p[3] == NUL || (p[3] != 'i' && p[4] != 'p'))))) 3103 || p[1] == 'g' 3104 || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g') 3105 || p[1] == 'I' 3106 || (p[1] == 'r' && p[2] != 'e'))) 3107 { 3108 eap->cmdidx = CMD_substitute; 3109 ++p; 3110 } 3111 else 3112 { 3113 while (ASCII_ISALPHA(*p)) 3114 ++p; 3115 /* for python 3.x support ":py3", ":python3", ":py3file", etc. */ 3116 if (eap->cmd[0] == 'p' && eap->cmd[1] == 'y') 3117 while (ASCII_ISALNUM(*p)) 3118 ++p; 3119 3120 /* check for non-alpha command */ 3121 if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) 3122 ++p; 3123 len = (int)(p - eap->cmd); 3124 if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) 3125 { 3126 /* Check for ":dl", ":dell", etc. to ":deletel": that's 3127 * :delete with the 'l' flag. Same for 'p'. */ 3128 for (i = 0; i < len; ++i) 3129 if (eap->cmd[i] != ((char_u *)"delete")[i]) 3130 break; 3131 if (i == len - 1) 3132 { 3133 --len; 3134 if (p[-1] == 'l') 3135 eap->flags |= EXFLAG_LIST; 3136 else 3137 eap->flags |= EXFLAG_PRINT; 3138 } 3139 } 3140 3141 if (ASCII_ISLOWER(eap->cmd[0])) 3142 { 3143 int c1 = eap->cmd[0]; 3144 int c2 = eap->cmd[1]; 3145 3146 if (command_count != (int)CMD_SIZE) 3147 { 3148 iemsg((char_u *)_("E943: Command table needs to be updated, run 'make cmdidxs'")); 3149 getout(1); 3150 } 3151 3152 /* Use a precomputed index for fast look-up in cmdnames[] 3153 * taking into account the first 2 letters of eap->cmd. */ 3154 eap->cmdidx = cmdidxs1[CharOrdLow(c1)]; 3155 if (ASCII_ISLOWER(c2)) 3156 eap->cmdidx += cmdidxs2[CharOrdLow(c1)][CharOrdLow(c2)]; 3157 } 3158 else 3159 eap->cmdidx = CMD_bang; 3160 3161 for ( ; (int)eap->cmdidx < (int)CMD_SIZE; 3162 eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1)) 3163 if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd, 3164 (size_t)len) == 0) 3165 { 3166 #ifdef FEAT_EVAL 3167 if (full != NULL 3168 && cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL) 3169 *full = TRUE; 3170 #endif 3171 break; 3172 } 3173 3174 #ifdef FEAT_USR_CMDS 3175 /* Look for a user defined command as a last resort. Let ":Print" be 3176 * overruled by a user defined command. */ 3177 if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print) 3178 && *eap->cmd >= 'A' && *eap->cmd <= 'Z') 3179 { 3180 /* User defined commands may contain digits. */ 3181 while (ASCII_ISALNUM(*p)) 3182 ++p; 3183 p = find_ucmd(eap, p, full, NULL, NULL); 3184 } 3185 #endif 3186 if (p == eap->cmd) 3187 eap->cmdidx = CMD_SIZE; 3188 } 3189 3190 return p; 3191 } 3192 3193 #ifdef FEAT_USR_CMDS 3194 /* 3195 * Search for a user command that matches "eap->cmd". 3196 * Return cmdidx in "eap->cmdidx", flags in "eap->argt", idx in "eap->useridx". 3197 * Return a pointer to just after the command. 3198 * Return NULL if there is no matching command. 3199 */ 3200 static char_u * 3201 find_ucmd( 3202 exarg_T *eap, 3203 char_u *p, /* end of the command (possibly including count) */ 3204 int *full, /* set to TRUE for a full match */ 3205 expand_T *xp, /* used for completion, NULL otherwise */ 3206 int *compl) /* completion flags or NULL */ 3207 { 3208 int len = (int)(p - eap->cmd); 3209 int j, k, matchlen = 0; 3210 ucmd_T *uc; 3211 int found = FALSE; 3212 int possible = FALSE; 3213 char_u *cp, *np; /* Point into typed cmd and test name */ 3214 garray_T *gap; 3215 int amb_local = FALSE; /* Found ambiguous buffer-local command, 3216 only full match global is accepted. */ 3217 3218 /* 3219 * Look for buffer-local user commands first, then global ones. 3220 */ 3221 gap = &curbuf->b_ucmds; 3222 for (;;) 3223 { 3224 for (j = 0; j < gap->ga_len; ++j) 3225 { 3226 uc = USER_CMD_GA(gap, j); 3227 cp = eap->cmd; 3228 np = uc->uc_name; 3229 k = 0; 3230 while (k < len && *np != NUL && *cp++ == *np++) 3231 k++; 3232 if (k == len || (*np == NUL && vim_isdigit(eap->cmd[k]))) 3233 { 3234 /* If finding a second match, the command is ambiguous. But 3235 * not if a buffer-local command wasn't a full match and a 3236 * global command is a full match. */ 3237 if (k == len && found && *np != NUL) 3238 { 3239 if (gap == &ucmds) 3240 return NULL; 3241 amb_local = TRUE; 3242 } 3243 3244 if (!found || (k == len && *np == NUL)) 3245 { 3246 /* If we matched up to a digit, then there could 3247 * be another command including the digit that we 3248 * should use instead. 3249 */ 3250 if (k == len) 3251 found = TRUE; 3252 else 3253 possible = TRUE; 3254 3255 if (gap == &ucmds) 3256 eap->cmdidx = CMD_USER; 3257 else 3258 eap->cmdidx = CMD_USER_BUF; 3259 eap->argt = (long)uc->uc_argt; 3260 eap->useridx = j; 3261 eap->addr_type = uc->uc_addr_type; 3262 3263 # ifdef FEAT_CMDL_COMPL 3264 if (compl != NULL) 3265 *compl = uc->uc_compl; 3266 # ifdef FEAT_EVAL 3267 if (xp != NULL) 3268 { 3269 xp->xp_arg = uc->uc_compl_arg; 3270 xp->xp_scriptID = uc->uc_scriptID; 3271 } 3272 # endif 3273 # endif 3274 /* Do not search for further abbreviations 3275 * if this is an exact match. */ 3276 matchlen = k; 3277 if (k == len && *np == NUL) 3278 { 3279 if (full != NULL) 3280 *full = TRUE; 3281 amb_local = FALSE; 3282 break; 3283 } 3284 } 3285 } 3286 } 3287 3288 /* Stop if we found a full match or searched all. */ 3289 if (j < gap->ga_len || gap == &ucmds) 3290 break; 3291 gap = &ucmds; 3292 } 3293 3294 /* Only found ambiguous matches. */ 3295 if (amb_local) 3296 { 3297 if (xp != NULL) 3298 xp->xp_context = EXPAND_UNSUCCESSFUL; 3299 return NULL; 3300 } 3301 3302 /* The match we found may be followed immediately by a number. Move "p" 3303 * back to point to it. */ 3304 if (found || possible) 3305 return p + (matchlen - len); 3306 return p; 3307 } 3308 #endif 3309 3310 #if defined(FEAT_EVAL) || defined(PROTO) 3311 static struct cmdmod 3312 { 3313 char *name; 3314 int minlen; 3315 int has_count; /* :123verbose :3tab */ 3316 } cmdmods[] = { 3317 {"aboveleft", 3, FALSE}, 3318 {"belowright", 3, FALSE}, 3319 {"botright", 2, FALSE}, 3320 {"browse", 3, FALSE}, 3321 {"confirm", 4, FALSE}, 3322 {"filter", 4, FALSE}, 3323 {"hide", 3, FALSE}, 3324 {"keepalt", 5, FALSE}, 3325 {"keepjumps", 5, FALSE}, 3326 {"keepmarks", 3, FALSE}, 3327 {"keeppatterns", 5, FALSE}, 3328 {"leftabove", 5, FALSE}, 3329 {"lockmarks", 3, FALSE}, 3330 {"noautocmd", 3, FALSE}, 3331 {"noswapfile", 3, FALSE}, 3332 {"rightbelow", 6, FALSE}, 3333 {"sandbox", 3, FALSE}, 3334 {"silent", 3, FALSE}, 3335 {"tab", 3, TRUE}, 3336 {"topleft", 2, FALSE}, 3337 {"unsilent", 3, FALSE}, 3338 {"verbose", 4, TRUE}, 3339 {"vertical", 4, FALSE}, 3340 }; 3341 3342 /* 3343 * Return length of a command modifier (including optional count). 3344 * Return zero when it's not a modifier. 3345 */ 3346 int 3347 modifier_len(char_u *cmd) 3348 { 3349 int i, j; 3350 char_u *p = cmd; 3351 3352 if (VIM_ISDIGIT(*cmd)) 3353 p = skipwhite(skipdigits(cmd)); 3354 for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i) 3355 { 3356 for (j = 0; p[j] != NUL; ++j) 3357 if (p[j] != cmdmods[i].name[j]) 3358 break; 3359 if (!ASCII_ISALPHA(p[j]) && j >= cmdmods[i].minlen 3360 && (p == cmd || cmdmods[i].has_count)) 3361 return j + (int)(p - cmd); 3362 } 3363 return 0; 3364 } 3365 3366 /* 3367 * Return > 0 if an Ex command "name" exists. 3368 * Return 2 if there is an exact match. 3369 * Return 3 if there is an ambiguous match. 3370 */ 3371 int 3372 cmd_exists(char_u *name) 3373 { 3374 exarg_T ea; 3375 int full = FALSE; 3376 int i; 3377 int j; 3378 char_u *p; 3379 3380 /* Check command modifiers. */ 3381 for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i) 3382 { 3383 for (j = 0; name[j] != NUL; ++j) 3384 if (name[j] != cmdmods[i].name[j]) 3385 break; 3386 if (name[j] == NUL && j >= cmdmods[i].minlen) 3387 return (cmdmods[i].name[j] == NUL ? 2 : 1); 3388 } 3389 3390 /* Check built-in commands and user defined commands. 3391 * For ":2match" and ":3match" we need to skip the number. */ 3392 ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name; 3393 ea.cmdidx = (cmdidx_T)0; 3394 p = find_command(&ea, &full); 3395 if (p == NULL) 3396 return 3; 3397 if (vim_isdigit(*name) && ea.cmdidx != CMD_match) 3398 return 0; 3399 if (*skipwhite(p) != NUL) 3400 return 0; /* trailing garbage */ 3401 return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1)); 3402 } 3403 #endif 3404 3405 /* 3406 * This is all pretty much copied from do_one_cmd(), with all the extra stuff 3407 * we don't need/want deleted. Maybe this could be done better if we didn't 3408 * repeat all this stuff. The only problem is that they may not stay 3409 * perfectly compatible with each other, but then the command line syntax 3410 * probably won't change that much -- webb. 3411 */ 3412 char_u * 3413 set_one_cmd_context( 3414 expand_T *xp, 3415 char_u *buff) /* buffer for command string */ 3416 { 3417 char_u *p; 3418 char_u *cmd, *arg; 3419 int len = 0; 3420 exarg_T ea; 3421 #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) 3422 int compl = EXPAND_NOTHING; 3423 #endif 3424 #ifdef FEAT_CMDL_COMPL 3425 int delim; 3426 #endif 3427 int forceit = FALSE; 3428 int usefilter = FALSE; /* filter instead of file name */ 3429 3430 ExpandInit(xp); 3431 xp->xp_pattern = buff; 3432 xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */ 3433 ea.argt = 0; 3434 3435 /* 3436 * 1. skip comment lines and leading space, colons or bars 3437 */ 3438 for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) 3439 ; 3440 xp->xp_pattern = cmd; 3441 3442 if (*cmd == NUL) 3443 return NULL; 3444 if (*cmd == '"') /* ignore comment lines */ 3445 { 3446 xp->xp_context = EXPAND_NOTHING; 3447 return NULL; 3448 } 3449 3450 /* 3451 * 3. Skip over the range to find the command. 3452 */ 3453 cmd = skip_range(cmd, &xp->xp_context); 3454 xp->xp_pattern = cmd; 3455 if (*cmd == NUL) 3456 return NULL; 3457 if (*cmd == '"') 3458 { 3459 xp->xp_context = EXPAND_NOTHING; 3460 return NULL; 3461 } 3462 3463 if (*cmd == '|' || *cmd == '\n') 3464 return cmd + 1; /* There's another command */ 3465 3466 /* 3467 * Isolate the command and search for it in the command table. 3468 * Exceptions: 3469 * - the 'k' command can directly be followed by any character, but 3470 * do accept "keepmarks", "keepalt" and "keepjumps". 3471 * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' 3472 */ 3473 if (*cmd == 'k' && cmd[1] != 'e') 3474 { 3475 ea.cmdidx = CMD_k; 3476 p = cmd + 1; 3477 } 3478 else 3479 { 3480 p = cmd; 3481 while (ASCII_ISALPHA(*p) || *p == '*') /* Allow * wild card */ 3482 ++p; 3483 /* a user command may contain digits */ 3484 if (ASCII_ISUPPER(cmd[0])) 3485 while (ASCII_ISALNUM(*p) || *p == '*') 3486 ++p; 3487 /* for python 3.x: ":py3*" commands completion */ 3488 if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') 3489 { 3490 ++p; 3491 while (ASCII_ISALPHA(*p) || *p == '*') 3492 ++p; 3493 } 3494 /* check for non-alpha command */ 3495 if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) 3496 ++p; 3497 len = (int)(p - cmd); 3498 3499 if (len == 0) 3500 { 3501 xp->xp_context = EXPAND_UNSUCCESSFUL; 3502 return NULL; 3503 } 3504 for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE; 3505 ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) 3506 if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, 3507 (size_t)len) == 0) 3508 break; 3509 3510 #ifdef FEAT_USR_CMDS 3511 if (cmd[0] >= 'A' && cmd[0] <= 'Z') 3512 while (ASCII_ISALNUM(*p) || *p == '*') /* Allow * wild card */ 3513 ++p; 3514 #endif 3515 } 3516 3517 /* 3518 * If the cursor is touching the command, and it ends in an alpha-numeric 3519 * character, complete the command name. 3520 */ 3521 if (*p == NUL && ASCII_ISALNUM(p[-1])) 3522 return NULL; 3523 3524 if (ea.cmdidx == CMD_SIZE) 3525 { 3526 if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) 3527 { 3528 ea.cmdidx = CMD_substitute; 3529 p = cmd + 1; 3530 } 3531 #ifdef FEAT_USR_CMDS 3532 else if (cmd[0] >= 'A' && cmd[0] <= 'Z') 3533 { 3534 ea.cmd = cmd; 3535 p = find_ucmd(&ea, p, NULL, xp, 3536 # if defined(FEAT_CMDL_COMPL) 3537 &compl 3538 # else 3539 NULL 3540 # endif 3541 ); 3542 if (p == NULL) 3543 ea.cmdidx = CMD_SIZE; /* ambiguous user command */ 3544 } 3545 #endif 3546 } 3547 if (ea.cmdidx == CMD_SIZE) 3548 { 3549 /* Not still touching the command and it was an illegal one */ 3550 xp->xp_context = EXPAND_UNSUCCESSFUL; 3551 return NULL; 3552 } 3553 3554 xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */ 3555 3556 if (*p == '!') /* forced commands */ 3557 { 3558 forceit = TRUE; 3559 ++p; 3560 } 3561 3562 /* 3563 * 6. parse arguments 3564 */ 3565 if (!IS_USER_CMDIDX(ea.cmdidx)) 3566 ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt; 3567 3568 arg = skipwhite(p); 3569 3570 if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) 3571 { 3572 if (*arg == '>') /* append */ 3573 { 3574 if (*++arg == '>') 3575 ++arg; 3576 arg = skipwhite(arg); 3577 } 3578 else if (*arg == '!' && ea.cmdidx == CMD_write) /* :w !filter */ 3579 { 3580 ++arg; 3581 usefilter = TRUE; 3582 } 3583 } 3584 3585 if (ea.cmdidx == CMD_read) 3586 { 3587 usefilter = forceit; /* :r! filter if forced */ 3588 if (*arg == '!') /* :r !filter */ 3589 { 3590 ++arg; 3591 usefilter = TRUE; 3592 } 3593 } 3594 3595 if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) 3596 { 3597 while (*arg == *cmd) /* allow any number of '>' or '<' */ 3598 ++arg; 3599 arg = skipwhite(arg); 3600 } 3601 3602 /* Does command allow "+command"? */ 3603 if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') 3604 { 3605 /* Check if we're in the +command */ 3606 p = arg + 1; 3607 arg = skip_cmd_arg(arg, FALSE); 3608 3609 /* Still touching the command after '+'? */ 3610 if (*arg == NUL) 3611 return p; 3612 3613 /* Skip space(s) after +command to get to the real argument */ 3614 arg = skipwhite(arg); 3615 } 3616 3617 /* 3618 * Check for '|' to separate commands and '"' to start comments. 3619 * Don't do this for ":read !cmd" and ":write !cmd". 3620 */ 3621 if ((ea.argt & TRLBAR) && !usefilter) 3622 { 3623 p = arg; 3624 /* ":redir @" is not the start of a comment */ 3625 if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') 3626 p += 2; 3627 while (*p) 3628 { 3629 if (*p == Ctrl_V) 3630 { 3631 if (p[1] != NUL) 3632 ++p; 3633 } 3634 else if ( (*p == '"' && !(ea.argt & NOTRLCOM)) 3635 || *p == '|' || *p == '\n') 3636 { 3637 if (*(p - 1) != '\\') 3638 { 3639 if (*p == '|' || *p == '\n') 3640 return p + 1; 3641 return NULL; /* It's a comment */ 3642 } 3643 } 3644 MB_PTR_ADV(p); 3645 } 3646 } 3647 3648 /* no arguments allowed */ 3649 if (!(ea.argt & EXTRA) && *arg != NUL && 3650 vim_strchr((char_u *)"|\"", *arg) == NULL) 3651 return NULL; 3652 3653 /* Find start of last argument (argument just before cursor): */ 3654 p = buff; 3655 xp->xp_pattern = p; 3656 len = (int)STRLEN(buff); 3657 while (*p && p < buff + len) 3658 { 3659 if (*p == ' ' || *p == TAB) 3660 { 3661 /* argument starts after a space */ 3662 xp->xp_pattern = ++p; 3663 } 3664 else 3665 { 3666 if (*p == '\\' && *(p + 1) != NUL) 3667 ++p; /* skip over escaped character */ 3668 MB_PTR_ADV(p); 3669 } 3670 } 3671 3672 if (ea.argt & XFILE) 3673 { 3674 int c; 3675 int in_quote = FALSE; 3676 char_u *bow = NULL; /* Beginning of word */ 3677 3678 /* 3679 * Allow spaces within back-quotes to count as part of the argument 3680 * being expanded. 3681 */ 3682 xp->xp_pattern = skipwhite(arg); 3683 p = xp->xp_pattern; 3684 while (*p != NUL) 3685 { 3686 #ifdef FEAT_MBYTE 3687 if (has_mbyte) 3688 c = mb_ptr2char(p); 3689 else 3690 #endif 3691 c = *p; 3692 if (c == '\\' && p[1] != NUL) 3693 ++p; 3694 else if (c == '`') 3695 { 3696 if (!in_quote) 3697 { 3698 xp->xp_pattern = p; 3699 bow = p + 1; 3700 } 3701 in_quote = !in_quote; 3702 } 3703 /* An argument can contain just about everything, except 3704 * characters that end the command and white space. */ 3705 else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) 3706 #ifdef SPACE_IN_FILENAME 3707 && (!(ea.argt & NOSPC) || usefilter) 3708 #endif 3709 )) 3710 { 3711 len = 0; /* avoid getting stuck when space is in 'isfname' */ 3712 while (*p != NUL) 3713 { 3714 #ifdef FEAT_MBYTE 3715 if (has_mbyte) 3716 c = mb_ptr2char(p); 3717 else 3718 #endif 3719 c = *p; 3720 if (c == '`' || vim_isfilec_or_wc(c)) 3721 break; 3722 #ifdef FEAT_MBYTE 3723 if (has_mbyte) 3724 len = (*mb_ptr2len)(p); 3725 else 3726 #endif 3727 len = 1; 3728 MB_PTR_ADV(p); 3729 } 3730 if (in_quote) 3731 bow = p; 3732 else 3733 xp->xp_pattern = p; 3734 p -= len; 3735 } 3736 MB_PTR_ADV(p); 3737 } 3738 3739 /* 3740 * If we are still inside the quotes, and we passed a space, just 3741 * expand from there. 3742 */ 3743 if (bow != NULL && in_quote) 3744 xp->xp_pattern = bow; 3745 xp->xp_context = EXPAND_FILES; 3746 3747 /* For a shell command more chars need to be escaped. */ 3748 if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) 3749 { 3750 #ifndef BACKSLASH_IN_FILENAME 3751 xp->xp_shell = TRUE; 3752 #endif 3753 /* When still after the command name expand executables. */ 3754 if (xp->xp_pattern == skipwhite(arg)) 3755 xp->xp_context = EXPAND_SHELLCMD; 3756 } 3757 3758 /* Check for environment variable */ 3759 if (*xp->xp_pattern == '$' 3760 #if defined(MSWIN) 3761 || *xp->xp_pattern == '%' 3762 #endif 3763 ) 3764 { 3765 for (p = xp->xp_pattern + 1; *p != NUL; ++p) 3766 if (!vim_isIDc(*p)) 3767 break; 3768 if (*p == NUL) 3769 { 3770 xp->xp_context = EXPAND_ENV_VARS; 3771 ++xp->xp_pattern; 3772 #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) 3773 /* Avoid that the assignment uses EXPAND_FILES again. */ 3774 if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) 3775 compl = EXPAND_ENV_VARS; 3776 #endif 3777 } 3778 } 3779 #if defined(FEAT_CMDL_COMPL) 3780 /* Check for user names */ 3781 if (*xp->xp_pattern == '~') 3782 { 3783 for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) 3784 ; 3785 /* Complete ~user only if it partially matches a user name. 3786 * A full match ~user<Tab> will be replaced by user's home 3787 * directory i.e. something like ~user<Tab> -> /home/user/ */ 3788 if (*p == NUL && p > xp->xp_pattern + 1 3789 && match_user(xp->xp_pattern + 1) == 1) 3790 { 3791 xp->xp_context = EXPAND_USER; 3792 ++xp->xp_pattern; 3793 } 3794 } 3795 #endif 3796 } 3797 3798 /* 3799 * 6. Switch on command name. 3800 */ 3801 switch (ea.cmdidx) 3802 { 3803 case CMD_find: 3804 case CMD_sfind: 3805 case CMD_tabfind: 3806 if (xp->xp_context == EXPAND_FILES) 3807 xp->xp_context = EXPAND_FILES_IN_PATH; 3808 break; 3809 case CMD_cd: 3810 case CMD_chdir: 3811 case CMD_lcd: 3812 case CMD_lchdir: 3813 if (xp->xp_context == EXPAND_FILES) 3814 xp->xp_context = EXPAND_DIRECTORIES; 3815 break; 3816 case CMD_help: 3817 xp->xp_context = EXPAND_HELP; 3818 xp->xp_pattern = arg; 3819 break; 3820 3821 /* Command modifiers: return the argument. 3822 * Also for commands with an argument that is a command. */ 3823 case CMD_aboveleft: 3824 case CMD_argdo: 3825 case CMD_belowright: 3826 case CMD_botright: 3827 case CMD_browse: 3828 case CMD_bufdo: 3829 case CMD_cdo: 3830 case CMD_cfdo: 3831 case CMD_confirm: 3832 case CMD_debug: 3833 case CMD_folddoclosed: 3834 case CMD_folddoopen: 3835 case CMD_hide: 3836 case CMD_keepalt: 3837 case CMD_keepjumps: 3838 case CMD_keepmarks: 3839 case CMD_keeppatterns: 3840 case CMD_ldo: 3841 case CMD_leftabove: 3842 case CMD_lfdo: 3843 case CMD_lockmarks: 3844 case CMD_noautocmd: 3845 case CMD_noswapfile: 3846 case CMD_rightbelow: 3847 case CMD_sandbox: 3848 case CMD_silent: 3849 case CMD_tab: 3850 case CMD_tabdo: 3851 case CMD_topleft: 3852 case CMD_verbose: 3853 case CMD_vertical: 3854 case CMD_windo: 3855 return arg; 3856 3857 case CMD_filter: 3858 if (*arg != NUL) 3859 arg = skip_vimgrep_pat(arg, NULL, NULL); 3860 if (arg == NULL || *arg == NUL) 3861 { 3862 xp->xp_context = EXPAND_NOTHING; 3863 return NULL; 3864 } 3865 return skipwhite(arg); 3866 3867 #ifdef FEAT_CMDL_COMPL 3868 # ifdef FEAT_SEARCH_EXTRA 3869 case CMD_match: 3870 if (*arg == NUL || !ends_excmd(*arg)) 3871 { 3872 /* also complete "None" */ 3873 set_context_in_echohl_cmd(xp, arg); 3874 arg = skipwhite(skiptowhite(arg)); 3875 if (*arg != NUL) 3876 { 3877 xp->xp_context = EXPAND_NOTHING; 3878 arg = skip_regexp(arg + 1, *arg, p_magic, NULL); 3879 } 3880 } 3881 return find_nextcmd(arg); 3882 # endif 3883 3884 /* 3885 * All completion for the +cmdline_compl feature goes here. 3886 */ 3887 3888 # ifdef FEAT_USR_CMDS 3889 case CMD_command: 3890 /* Check for attributes */ 3891 while (*arg == '-') 3892 { 3893 arg++; /* Skip "-" */ 3894 p = skiptowhite(arg); 3895 if (*p == NUL) 3896 { 3897 /* Cursor is still in the attribute */ 3898 p = vim_strchr(arg, '='); 3899 if (p == NULL) 3900 { 3901 /* No "=", so complete attribute names */ 3902 xp->xp_context = EXPAND_USER_CMD_FLAGS; 3903 xp->xp_pattern = arg; 3904 return NULL; 3905 } 3906 3907 /* For the -complete, -nargs and -addr attributes, we complete 3908 * their arguments as well. 3909 */ 3910 if (STRNICMP(arg, "complete", p - arg) == 0) 3911 { 3912 xp->xp_context = EXPAND_USER_COMPLETE; 3913 xp->xp_pattern = p + 1; 3914 return NULL; 3915 } 3916 else if (STRNICMP(arg, "nargs", p - arg) == 0) 3917 { 3918 xp->xp_context = EXPAND_USER_NARGS; 3919 xp->xp_pattern = p + 1; 3920 return NULL; 3921 } 3922 else if (STRNICMP(arg, "addr", p - arg) == 0) 3923 { 3924 xp->xp_context = EXPAND_USER_ADDR_TYPE; 3925 xp->xp_pattern = p + 1; 3926 return NULL; 3927 } 3928 return NULL; 3929 } 3930 arg = skipwhite(p); 3931 } 3932 3933 /* After the attributes comes the new command name */ 3934 p = skiptowhite(arg); 3935 if (*p == NUL) 3936 { 3937 xp->xp_context = EXPAND_USER_COMMANDS; 3938 xp->xp_pattern = arg; 3939 break; 3940 } 3941 3942 /* And finally comes a normal command */ 3943 return skipwhite(p); 3944 3945 case CMD_delcommand: 3946 xp->xp_context = EXPAND_USER_COMMANDS; 3947 xp->xp_pattern = arg; 3948 break; 3949 # endif 3950 3951 case CMD_global: 3952 case CMD_vglobal: 3953 delim = *arg; /* get the delimiter */ 3954 if (delim) 3955 ++arg; /* skip delimiter if there is one */ 3956 3957 while (arg[0] != NUL && arg[0] != delim) 3958 { 3959 if (arg[0] == '\\' && arg[1] != NUL) 3960 ++arg; 3961 ++arg; 3962 } 3963 if (arg[0] != NUL) 3964 return arg + 1; 3965 break; 3966 case CMD_and: 3967 case CMD_substitute: 3968 delim = *arg; 3969 if (delim) 3970 { 3971 /* skip "from" part */ 3972 ++arg; 3973 arg = skip_regexp(arg, delim, p_magic, NULL); 3974 } 3975 /* skip "to" part */ 3976 while (arg[0] != NUL && arg[0] != delim) 3977 { 3978 if (arg[0] == '\\' && arg[1] != NUL) 3979 ++arg; 3980 ++arg; 3981 } 3982 if (arg[0] != NUL) /* skip delimiter */ 3983 ++arg; 3984 while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL) 3985 ++arg; 3986 if (arg[0] != NUL) 3987 return arg; 3988 break; 3989 case CMD_isearch: 3990 case CMD_dsearch: 3991 case CMD_ilist: 3992 case CMD_dlist: 3993 case CMD_ijump: 3994 case CMD_psearch: 3995 case CMD_djump: 3996 case CMD_isplit: 3997 case CMD_dsplit: 3998 arg = skipwhite(skipdigits(arg)); /* skip count */ 3999 if (*arg == '/') /* Match regexp, not just whole words */ 4000 { 4001 for (++arg; *arg && *arg != '/'; arg++) 4002 if (*arg == '\\' && arg[1] != NUL) 4003 arg++; 4004 if (*arg) 4005 { 4006 arg = skipwhite(arg + 1); 4007 4008 /* Check for trailing illegal characters */ 4009 if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL) 4010 xp->xp_context = EXPAND_NOTHING; 4011 else 4012 return arg; 4013 } 4014 } 4015 break; 4016 #ifdef FEAT_AUTOCMD 4017 case CMD_autocmd: 4018 return set_context_in_autocmd(xp, arg, FALSE); 4019 4020 case CMD_doautocmd: 4021 case CMD_doautoall: 4022 return set_context_in_autocmd(xp, arg, TRUE); 4023 #endif 4024 case CMD_set: 4025 set_context_in_set_cmd(xp, arg, 0); 4026 break; 4027 case CMD_setglobal: 4028 set_context_in_set_cmd(xp, arg, OPT_GLOBAL); 4029 break; 4030 case CMD_setlocal: 4031 set_context_in_set_cmd(xp, arg, OPT_LOCAL); 4032 break; 4033 case CMD_tag: 4034 case CMD_stag: 4035 case CMD_ptag: 4036 case CMD_ltag: 4037 case CMD_tselect: 4038 case CMD_stselect: 4039 case CMD_ptselect: 4040 case CMD_tjump: 4041 case CMD_stjump: 4042 case CMD_ptjump: 4043 if (*p_wop != NUL) 4044 xp->xp_context = EXPAND_TAGS_LISTFILES; 4045 else 4046 xp->xp_context = EXPAND_TAGS; 4047 xp->xp_pattern = arg; 4048 break; 4049 case CMD_augroup: 4050 xp->xp_context = EXPAND_AUGROUP; 4051 xp->xp_pattern = arg; 4052 break; 4053 #ifdef FEAT_SYN_HL 4054 case CMD_syntax: 4055 set_context_in_syntax_cmd(xp, arg); 4056 break; 4057 #endif 4058 #ifdef FEAT_EVAL 4059 case CMD_let: 4060 case CMD_if: 4061 case CMD_elseif: 4062 case CMD_while: 4063 case CMD_for: 4064 case CMD_echo: 4065 case CMD_echon: 4066 case CMD_execute: 4067 case CMD_echomsg: 4068 case CMD_echoerr: 4069 case CMD_call: 4070 case CMD_return: 4071 case CMD_cexpr: 4072 case CMD_caddexpr: 4073 case CMD_cgetexpr: 4074 case CMD_lexpr: 4075 case CMD_laddexpr: 4076 case CMD_lgetexpr: 4077 set_context_for_expression(xp, arg, ea.cmdidx); 4078 break; 4079 4080 case CMD_unlet: 4081 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 4082 arg = xp->xp_pattern + 1; 4083 xp->xp_context = EXPAND_USER_VARS; 4084 xp->xp_pattern = arg; 4085 break; 4086 4087 case CMD_function: 4088 case CMD_delfunction: 4089 xp->xp_context = EXPAND_USER_FUNC; 4090 xp->xp_pattern = arg; 4091 break; 4092 4093 case CMD_echohl: 4094 set_context_in_echohl_cmd(xp, arg); 4095 break; 4096 #endif 4097 case CMD_highlight: 4098 set_context_in_highlight_cmd(xp, arg); 4099 break; 4100 #ifdef FEAT_CSCOPE 4101 case CMD_cscope: 4102 case CMD_lcscope: 4103 case CMD_scscope: 4104 set_context_in_cscope_cmd(xp, arg, ea.cmdidx); 4105 break; 4106 #endif 4107 #ifdef FEAT_SIGNS 4108 case CMD_sign: 4109 set_context_in_sign_cmd(xp, arg); 4110 break; 4111 #endif 4112 #ifdef FEAT_LISTCMDS 4113 case CMD_bdelete: 4114 case CMD_bwipeout: 4115 case CMD_bunload: 4116 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) 4117 arg = xp->xp_pattern + 1; 4118 /* FALLTHROUGH */ 4119 case CMD_buffer: 4120 case CMD_sbuffer: 4121 case CMD_checktime: 4122 xp->xp_context = EXPAND_BUFFERS; 4123 xp->xp_pattern = arg; 4124 break; 4125 #endif 4126 #ifdef FEAT_USR_CMDS 4127 case CMD_USER: 4128 case CMD_USER_BUF: 4129 if (compl != EXPAND_NOTHING) 4130 { 4131 /* XFILE: file names are handled above */ 4132 if (!(ea.argt & XFILE)) 4133 { 4134 # ifdef FEAT_MENU 4135 if (compl == EXPAND_MENUS) 4136 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 4137 # endif 4138 if (compl == EXPAND_COMMANDS) 4139 return arg; 4140 if (compl == EXPAND_MAPPINGS) 4141 return set_context_in_map_cmd(xp, (char_u *)"map", 4142 arg, forceit, FALSE, FALSE, CMD_map); 4143 /* Find start of last argument. */ 4144 p = arg; 4145 while (*p) 4146 { 4147 if (*p == ' ') 4148 /* argument starts after a space */ 4149 arg = p + 1; 4150 else if (*p == '\\' && *(p + 1) != NUL) 4151 ++p; /* skip over escaped character */ 4152 MB_PTR_ADV(p); 4153 } 4154 xp->xp_pattern = arg; 4155 } 4156 xp->xp_context = compl; 4157 } 4158 break; 4159 #endif 4160 case CMD_map: case CMD_noremap: 4161 case CMD_nmap: case CMD_nnoremap: 4162 case CMD_vmap: case CMD_vnoremap: 4163 case CMD_omap: case CMD_onoremap: 4164 case CMD_imap: case CMD_inoremap: 4165 case CMD_cmap: case CMD_cnoremap: 4166 case CMD_lmap: case CMD_lnoremap: 4167 case CMD_smap: case CMD_snoremap: 4168 case CMD_tmap: case CMD_tnoremap: 4169 case CMD_xmap: case CMD_xnoremap: 4170 return set_context_in_map_cmd(xp, cmd, arg, forceit, 4171 FALSE, FALSE, ea.cmdidx); 4172 case CMD_unmap: 4173 case CMD_nunmap: 4174 case CMD_vunmap: 4175 case CMD_ounmap: 4176 case CMD_iunmap: 4177 case CMD_cunmap: 4178 case CMD_lunmap: 4179 case CMD_sunmap: 4180 case CMD_tunmap: 4181 case CMD_xunmap: 4182 return set_context_in_map_cmd(xp, cmd, arg, forceit, 4183 FALSE, TRUE, ea.cmdidx); 4184 case CMD_mapclear: 4185 case CMD_nmapclear: 4186 case CMD_vmapclear: 4187 case CMD_omapclear: 4188 case CMD_imapclear: 4189 case CMD_cmapclear: 4190 case CMD_lmapclear: 4191 case CMD_smapclear: 4192 case CMD_tmapclear: 4193 case CMD_xmapclear: 4194 xp->xp_context = EXPAND_MAPCLEAR; 4195 xp->xp_pattern = arg; 4196 break; 4197 4198 case CMD_abbreviate: case CMD_noreabbrev: 4199 case CMD_cabbrev: case CMD_cnoreabbrev: 4200 case CMD_iabbrev: case CMD_inoreabbrev: 4201 return set_context_in_map_cmd(xp, cmd, arg, forceit, 4202 TRUE, FALSE, ea.cmdidx); 4203 case CMD_unabbreviate: 4204 case CMD_cunabbrev: 4205 case CMD_iunabbrev: 4206 return set_context_in_map_cmd(xp, cmd, arg, forceit, 4207 TRUE, TRUE, ea.cmdidx); 4208 #ifdef FEAT_MENU 4209 case CMD_menu: case CMD_noremenu: case CMD_unmenu: 4210 case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: 4211 case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: 4212 case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: 4213 case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu: 4214 case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: 4215 case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: 4216 case CMD_tmenu: case CMD_tunmenu: 4217 case CMD_popup: case CMD_tearoff: case CMD_emenu: 4218 return set_context_in_menu_cmd(xp, cmd, arg, forceit); 4219 #endif 4220 4221 case CMD_colorscheme: 4222 xp->xp_context = EXPAND_COLORS; 4223 xp->xp_pattern = arg; 4224 break; 4225 4226 case CMD_compiler: 4227 xp->xp_context = EXPAND_COMPILER; 4228 xp->xp_pattern = arg; 4229 break; 4230 4231 case CMD_ownsyntax: 4232 xp->xp_context = EXPAND_OWNSYNTAX; 4233 xp->xp_pattern = arg; 4234 break; 4235 4236 case CMD_setfiletype: 4237 xp->xp_context = EXPAND_FILETYPE; 4238 xp->xp_pattern = arg; 4239 break; 4240 4241 case CMD_packadd: 4242 xp->xp_context = EXPAND_PACKADD; 4243 xp->xp_pattern = arg; 4244 break; 4245 4246 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 4247 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) 4248 case CMD_language: 4249 p = skiptowhite(arg); 4250 if (*p == NUL) 4251 { 4252 xp->xp_context = EXPAND_LANGUAGE; 4253 xp->xp_pattern = arg; 4254 } 4255 else 4256 { 4257 if ( STRNCMP(arg, "messages", p - arg) == 0 4258 || STRNCMP(arg, "ctype", p - arg) == 0 4259 || STRNCMP(arg, "time", p - arg) == 0) 4260 { 4261 xp->xp_context = EXPAND_LOCALES; 4262 xp->xp_pattern = skipwhite(p); 4263 } 4264 else 4265 xp->xp_context = EXPAND_NOTHING; 4266 } 4267 break; 4268 #endif 4269 #if defined(FEAT_PROFILE) 4270 case CMD_profile: 4271 set_context_in_profile_cmd(xp, arg); 4272 break; 4273 #endif 4274 case CMD_behave: 4275 xp->xp_context = EXPAND_BEHAVE; 4276 xp->xp_pattern = arg; 4277 break; 4278 4279 case CMD_messages: 4280 xp->xp_context = EXPAND_MESSAGES; 4281 xp->xp_pattern = arg; 4282 break; 4283 4284 #if defined(FEAT_CMDHIST) 4285 case CMD_history: 4286 xp->xp_context = EXPAND_HISTORY; 4287 xp->xp_pattern = arg; 4288 break; 4289 #endif 4290 #if defined(FEAT_PROFILE) 4291 case CMD_syntime: 4292 xp->xp_context = EXPAND_SYNTIME; 4293 xp->xp_pattern = arg; 4294 break; 4295 #endif 4296 4297 #endif /* FEAT_CMDL_COMPL */ 4298 4299 default: 4300 break; 4301 } 4302 return NULL; 4303 } 4304 4305 /* 4306 * skip a range specifier of the form: addr [,addr] [;addr] .. 4307 * 4308 * Backslashed delimiters after / or ? will be skipped, and commands will 4309 * not be expanded between /'s and ?'s or after "'". 4310 * 4311 * Also skip white space and ":" characters. 4312 * Returns the "cmd" pointer advanced to beyond the range. 4313 */ 4314 char_u * 4315 skip_range( 4316 char_u *cmd, 4317 int *ctx) /* pointer to xp_context or NULL */ 4318 { 4319 unsigned delim; 4320 4321 while (vim_strchr((char_u *)" \t0123456789.$%'/?-+,;\\", *cmd) != NULL) 4322 { 4323 if (*cmd == '\\') 4324 { 4325 if (cmd[1] == '?' || cmd[1] == '/' || cmd[1] == '&') 4326 ++cmd; 4327 else 4328 break; 4329 } 4330 else if (*cmd == '\'') 4331 { 4332 if (*++cmd == NUL && ctx != NULL) 4333 *ctx = EXPAND_NOTHING; 4334 } 4335 else if (*cmd == '/' || *cmd == '?') 4336 { 4337 delim = *cmd++; 4338 while (*cmd != NUL && *cmd != delim) 4339 if (*cmd++ == '\\' && *cmd != NUL) 4340 ++cmd; 4341 if (*cmd == NUL && ctx != NULL) 4342 *ctx = EXPAND_NOTHING; 4343 } 4344 if (*cmd != NUL) 4345 ++cmd; 4346 } 4347 4348 /* Skip ":" and white space. */ 4349 while (*cmd == ':') 4350 cmd = skipwhite(cmd + 1); 4351 4352 return cmd; 4353 } 4354 4355 /* 4356 * get a single EX address 4357 * 4358 * Set ptr to the next character after the part that was interpreted. 4359 * Set ptr to NULL when an error is encountered. 4360 * 4361 * Return MAXLNUM when no Ex address was found. 4362 */ 4363 static linenr_T 4364 get_address( 4365 exarg_T *eap UNUSED, 4366 char_u **ptr, 4367 int addr_type, /* flag: one of ADDR_LINES, ... */ 4368 int skip, /* only skip the address, don't use it */ 4369 int to_other_file, /* flag: may jump to other file */ 4370 int address_count UNUSED) /* 1 for first address, >1 after comma */ 4371 { 4372 int c; 4373 int i; 4374 long n; 4375 char_u *cmd; 4376 pos_T pos; 4377 pos_T *fp; 4378 linenr_T lnum; 4379 buf_T *buf; 4380 4381 cmd = skipwhite(*ptr); 4382 lnum = MAXLNUM; 4383 do 4384 { 4385 switch (*cmd) 4386 { 4387 case '.': /* '.' - Cursor position */ 4388 ++cmd; 4389 switch (addr_type) 4390 { 4391 case ADDR_LINES: 4392 lnum = curwin->w_cursor.lnum; 4393 break; 4394 case ADDR_WINDOWS: 4395 lnum = CURRENT_WIN_NR; 4396 break; 4397 case ADDR_ARGUMENTS: 4398 lnum = curwin->w_arg_idx + 1; 4399 break; 4400 case ADDR_LOADED_BUFFERS: 4401 case ADDR_BUFFERS: 4402 lnum = curbuf->b_fnum; 4403 break; 4404 case ADDR_TABS: 4405 lnum = CURRENT_TAB_NR; 4406 break; 4407 case ADDR_TABS_RELATIVE: 4408 EMSG(_(e_invrange)); 4409 cmd = NULL; 4410 goto error; 4411 break; 4412 #ifdef FEAT_QUICKFIX 4413 case ADDR_QUICKFIX: 4414 lnum = qf_get_cur_valid_idx(eap); 4415 break; 4416 #endif 4417 } 4418 break; 4419 4420 case '$': /* '$' - last line */ 4421 ++cmd; 4422 switch (addr_type) 4423 { 4424 case ADDR_LINES: 4425 lnum = curbuf->b_ml.ml_line_count; 4426 break; 4427 case ADDR_WINDOWS: 4428 lnum = LAST_WIN_NR; 4429 break; 4430 case ADDR_ARGUMENTS: 4431 lnum = ARGCOUNT; 4432 break; 4433 case ADDR_LOADED_BUFFERS: 4434 buf = lastbuf; 4435 while (buf->b_ml.ml_mfp == NULL) 4436 { 4437 if (buf->b_prev == NULL) 4438 break; 4439 buf = buf->b_prev; 4440 } 4441 lnum = buf->b_fnum; 4442 break; 4443 case ADDR_BUFFERS: 4444 lnum = lastbuf->b_fnum; 4445 break; 4446 case ADDR_TABS: 4447 lnum = LAST_TAB_NR; 4448 break; 4449 case ADDR_TABS_RELATIVE: 4450 EMSG(_(e_invrange)); 4451 cmd = NULL; 4452 goto error; 4453 break; 4454 #ifdef FEAT_QUICKFIX 4455 case ADDR_QUICKFIX: 4456 lnum = qf_get_size(eap); 4457 if (lnum == 0) 4458 lnum = 1; 4459 break; 4460 #endif 4461 } 4462 break; 4463 4464 case '\'': /* ''' - mark */ 4465 if (*++cmd == NUL) 4466 { 4467 cmd = NULL; 4468 goto error; 4469 } 4470 if (addr_type != ADDR_LINES) 4471 { 4472 EMSG(_(e_invaddr)); 4473 cmd = NULL; 4474 goto error; 4475 } 4476 if (skip) 4477 ++cmd; 4478 else 4479 { 4480 /* Only accept a mark in another file when it is 4481 * used by itself: ":'M". */ 4482 fp = getmark(*cmd, to_other_file && cmd[1] == NUL); 4483 ++cmd; 4484 if (fp == (pos_T *)-1) 4485 /* Jumped to another file. */ 4486 lnum = curwin->w_cursor.lnum; 4487 else 4488 { 4489 if (check_mark(fp) == FAIL) 4490 { 4491 cmd = NULL; 4492 goto error; 4493 } 4494 lnum = fp->lnum; 4495 } 4496 } 4497 break; 4498 4499 case '/': 4500 case '?': /* '/' or '?' - search */ 4501 c = *cmd++; 4502 if (addr_type != ADDR_LINES) 4503 { 4504 EMSG(_(e_invaddr)); 4505 cmd = NULL; 4506 goto error; 4507 } 4508 if (skip) /* skip "/pat/" */ 4509 { 4510 cmd = skip_regexp(cmd, c, (int)p_magic, NULL); 4511 if (*cmd == c) 4512 ++cmd; 4513 } 4514 else 4515 { 4516 pos = curwin->w_cursor; /* save curwin->w_cursor */ 4517 /* 4518 * When '/' or '?' follows another address, start 4519 * from there. 4520 */ 4521 if (lnum != MAXLNUM) 4522 curwin->w_cursor.lnum = lnum; 4523 /* 4524 * Start a forward search at the end of the line. 4525 * Start a backward search at the start of the line. 4526 * This makes sure we never match in the current 4527 * line, and can match anywhere in the 4528 * next/previous line. 4529 */ 4530 if (c == '/') 4531 curwin->w_cursor.col = MAXCOL; 4532 else 4533 curwin->w_cursor.col = 0; 4534 searchcmdlen = 0; 4535 if (!do_search(NULL, c, cmd, 1L, 4536 SEARCH_HIS | SEARCH_MSG, NULL, NULL)) 4537 { 4538 curwin->w_cursor = pos; 4539 cmd = NULL; 4540 goto error; 4541 } 4542 lnum = curwin->w_cursor.lnum; 4543 curwin->w_cursor = pos; 4544 /* adjust command string pointer */ 4545 cmd += searchcmdlen; 4546 } 4547 break; 4548 4549 case '\\': /* "\?", "\/" or "\&", repeat search */ 4550 ++cmd; 4551 if (addr_type != ADDR_LINES) 4552 { 4553 EMSG(_(e_invaddr)); 4554 cmd = NULL; 4555 goto error; 4556 } 4557 if (*cmd == '&') 4558 i = RE_SUBST; 4559 else if (*cmd == '?' || *cmd == '/') 4560 i = RE_SEARCH; 4561 else 4562 { 4563 EMSG(_(e_backslash)); 4564 cmd = NULL; 4565 goto error; 4566 } 4567 4568 if (!skip) 4569 { 4570 /* 4571 * When search follows another address, start from 4572 * there. 4573 */ 4574 if (lnum != MAXLNUM) 4575 pos.lnum = lnum; 4576 else 4577 pos.lnum = curwin->w_cursor.lnum; 4578 4579 /* 4580 * Start the search just like for the above 4581 * do_search(). 4582 */ 4583 if (*cmd != '?') 4584 pos.col = MAXCOL; 4585 else 4586 pos.col = 0; 4587 #ifdef FEAT_VIRTUALEDIT 4588 pos.coladd = 0; 4589 #endif 4590 if (searchit(curwin, curbuf, &pos, 4591 *cmd == '?' ? BACKWARD : FORWARD, 4592 (char_u *)"", 1L, SEARCH_MSG, 4593 i, (linenr_T)0, NULL, NULL) != FAIL) 4594 lnum = pos.lnum; 4595 else 4596 { 4597 cmd = NULL; 4598 goto error; 4599 } 4600 } 4601 ++cmd; 4602 break; 4603 4604 default: 4605 if (VIM_ISDIGIT(*cmd)) /* absolute line number */ 4606 lnum = getdigits(&cmd); 4607 } 4608 4609 for (;;) 4610 { 4611 cmd = skipwhite(cmd); 4612 if (*cmd != '-' && *cmd != '+' && !VIM_ISDIGIT(*cmd)) 4613 break; 4614 4615 if (lnum == MAXLNUM) 4616 { 4617 switch (addr_type) 4618 { 4619 case ADDR_LINES: 4620 /* "+1" is same as ".+1" */ 4621 lnum = curwin->w_cursor.lnum; 4622 break; 4623 case ADDR_WINDOWS: 4624 lnum = CURRENT_WIN_NR; 4625 break; 4626 case ADDR_ARGUMENTS: 4627 lnum = curwin->w_arg_idx + 1; 4628 break; 4629 case ADDR_LOADED_BUFFERS: 4630 case ADDR_BUFFERS: 4631 lnum = curbuf->b_fnum; 4632 break; 4633 case ADDR_TABS: 4634 lnum = CURRENT_TAB_NR; 4635 break; 4636 case ADDR_TABS_RELATIVE: 4637 lnum = 1; 4638 break; 4639 #ifdef FEAT_QUICKFIX 4640 case ADDR_QUICKFIX: 4641 lnum = qf_get_cur_valid_idx(eap); 4642 break; 4643 #endif 4644 } 4645 } 4646 4647 if (VIM_ISDIGIT(*cmd)) 4648 i = '+'; /* "number" is same as "+number" */ 4649 else 4650 i = *cmd++; 4651 if (!VIM_ISDIGIT(*cmd)) /* '+' is '+1', but '+0' is not '+1' */ 4652 n = 1; 4653 else 4654 n = getdigits(&cmd); 4655 4656 if (addr_type == ADDR_TABS_RELATIVE) 4657 { 4658 EMSG(_(e_invrange)); 4659 cmd = NULL; 4660 goto error; 4661 } 4662 else if (addr_type == ADDR_LOADED_BUFFERS 4663 || addr_type == ADDR_BUFFERS) 4664 lnum = compute_buffer_local_count( 4665 addr_type, lnum, (i == '-') ? -1 * n : n); 4666 else 4667 { 4668 #ifdef FEAT_FOLDING 4669 /* Relative line addressing, need to adjust for folded lines 4670 * now, but only do it after the first address. */ 4671 if (addr_type == ADDR_LINES && (i == '-' || i == '+') 4672 && address_count >= 2) 4673 (void)hasFolding(lnum, NULL, &lnum); 4674 #endif 4675 if (i == '-') 4676 lnum -= n; 4677 else 4678 lnum += n; 4679 } 4680 } 4681 } while (*cmd == '/' || *cmd == '?'); 4682 4683 error: 4684 *ptr = cmd; 4685 return lnum; 4686 } 4687 4688 /* 4689 * Get flags from an Ex command argument. 4690 */ 4691 static void 4692 get_flags(exarg_T *eap) 4693 { 4694 while (vim_strchr((char_u *)"lp#", *eap->arg) != NULL) 4695 { 4696 if (*eap->arg == 'l') 4697 eap->flags |= EXFLAG_LIST; 4698 else if (*eap->arg == 'p') 4699 eap->flags |= EXFLAG_PRINT; 4700 else 4701 eap->flags |= EXFLAG_NR; 4702 eap->arg = skipwhite(eap->arg + 1); 4703 } 4704 } 4705 4706 /* 4707 * Function called for command which is Not Implemented. NI! 4708 */ 4709 void 4710 ex_ni(exarg_T *eap) 4711 { 4712 if (!eap->skip) 4713 eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version"); 4714 } 4715 4716 #ifdef HAVE_EX_SCRIPT_NI 4717 /* 4718 * Function called for script command which is Not Implemented. NI! 4719 * Skips over ":perl <<EOF" constructs. 4720 */ 4721 static void 4722 ex_script_ni(exarg_T *eap) 4723 { 4724 if (!eap->skip) 4725 ex_ni(eap); 4726 else 4727 vim_free(script_get(eap, eap->arg)); 4728 } 4729 #endif 4730 4731 /* 4732 * Check range in Ex command for validity. 4733 * Return NULL when valid, error message when invalid. 4734 */ 4735 static char_u * 4736 invalid_range(exarg_T *eap) 4737 { 4738 buf_T *buf; 4739 if ( eap->line1 < 0 4740 || eap->line2 < 0 4741 || eap->line1 > eap->line2) 4742 return (char_u *)_(e_invrange); 4743 4744 if (eap->argt & RANGE) 4745 { 4746 switch(eap->addr_type) 4747 { 4748 case ADDR_LINES: 4749 if (!(eap->argt & NOTADR) 4750 && eap->line2 > curbuf->b_ml.ml_line_count 4751 #ifdef FEAT_DIFF 4752 + (eap->cmdidx == CMD_diffget) 4753 #endif 4754 ) 4755 return (char_u *)_(e_invrange); 4756 break; 4757 case ADDR_ARGUMENTS: 4758 /* add 1 if ARGCOUNT is 0 */ 4759 if (eap->line2 > ARGCOUNT + (!ARGCOUNT)) 4760 return (char_u *)_(e_invrange); 4761 break; 4762 case ADDR_BUFFERS: 4763 if (eap->line1 < firstbuf->b_fnum 4764 || eap->line2 > lastbuf->b_fnum) 4765 return (char_u *)_(e_invrange); 4766 break; 4767 case ADDR_LOADED_BUFFERS: 4768 buf = firstbuf; 4769 while (buf->b_ml.ml_mfp == NULL) 4770 { 4771 if (buf->b_next == NULL) 4772 return (char_u *)_(e_invrange); 4773 buf = buf->b_next; 4774 } 4775 if (eap->line1 < buf->b_fnum) 4776 return (char_u *)_(e_invrange); 4777 buf = lastbuf; 4778 while (buf->b_ml.ml_mfp == NULL) 4779 { 4780 if (buf->b_prev == NULL) 4781 return (char_u *)_(e_invrange); 4782 buf = buf->b_prev; 4783 } 4784 if (eap->line2 > buf->b_fnum) 4785 return (char_u *)_(e_invrange); 4786 break; 4787 case ADDR_WINDOWS: 4788 if (eap->line2 > LAST_WIN_NR) 4789 return (char_u *)_(e_invrange); 4790 break; 4791 case ADDR_TABS: 4792 if (eap->line2 > LAST_TAB_NR) 4793 return (char_u *)_(e_invrange); 4794 break; 4795 case ADDR_TABS_RELATIVE: 4796 /* Do nothing */ 4797 break; 4798 #ifdef FEAT_QUICKFIX 4799 case ADDR_QUICKFIX: 4800 if (eap->line2 != 1 && eap->line2 > qf_get_size(eap)) 4801 return (char_u *)_(e_invrange); 4802 break; 4803 #endif 4804 } 4805 } 4806 return NULL; 4807 } 4808 4809 /* 4810 * Correct the range for zero line number, if required. 4811 */ 4812 static void 4813 correct_range(exarg_T *eap) 4814 { 4815 if (!(eap->argt & ZEROR)) /* zero in range not allowed */ 4816 { 4817 if (eap->line1 == 0) 4818 eap->line1 = 1; 4819 if (eap->line2 == 0) 4820 eap->line2 = 1; 4821 } 4822 } 4823 4824 #ifdef FEAT_QUICKFIX 4825 static char_u *skip_grep_pat(exarg_T *eap); 4826 4827 /* 4828 * For a ":vimgrep" or ":vimgrepadd" command return a pointer past the 4829 * pattern. Otherwise return eap->arg. 4830 */ 4831 static char_u * 4832 skip_grep_pat(exarg_T *eap) 4833 { 4834 char_u *p = eap->arg; 4835 4836 if (*p != NUL && (eap->cmdidx == CMD_vimgrep || eap->cmdidx == CMD_lvimgrep 4837 || eap->cmdidx == CMD_vimgrepadd 4838 || eap->cmdidx == CMD_lvimgrepadd 4839 || grep_internal(eap->cmdidx))) 4840 { 4841 p = skip_vimgrep_pat(p, NULL, NULL); 4842 if (p == NULL) 4843 p = eap->arg; 4844 } 4845 return p; 4846 } 4847 4848 /* 4849 * For the ":make" and ":grep" commands insert the 'makeprg'/'grepprg' option 4850 * in the command line, so that things like % get expanded. 4851 */ 4852 static char_u * 4853 replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) 4854 { 4855 char_u *new_cmdline; 4856 char_u *program; 4857 char_u *pos; 4858 char_u *ptr; 4859 int len; 4860 int i; 4861 4862 /* 4863 * Don't do it when ":vimgrep" is used for ":grep". 4864 */ 4865 if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake 4866 || eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep 4867 || eap->cmdidx == CMD_grepadd 4868 || eap->cmdidx == CMD_lgrepadd) 4869 && !grep_internal(eap->cmdidx)) 4870 { 4871 if (eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep 4872 || eap->cmdidx == CMD_grepadd || eap->cmdidx == CMD_lgrepadd) 4873 { 4874 if (*curbuf->b_p_gp == NUL) 4875 program = p_gp; 4876 else 4877 program = curbuf->b_p_gp; 4878 } 4879 else 4880 { 4881 if (*curbuf->b_p_mp == NUL) 4882 program = p_mp; 4883 else 4884 program = curbuf->b_p_mp; 4885 } 4886 4887 p = skipwhite(p); 4888 4889 if ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) 4890 { 4891 /* replace $* by given arguments */ 4892 i = 1; 4893 while ((pos = (char_u *)strstr((char *)pos + 2, "$*")) != NULL) 4894 ++i; 4895 len = (int)STRLEN(p); 4896 new_cmdline = alloc((int)(STRLEN(program) + i * (len - 2) + 1)); 4897 if (new_cmdline == NULL) 4898 return NULL; /* out of memory */ 4899 ptr = new_cmdline; 4900 while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) 4901 { 4902 i = (int)(pos - program); 4903 STRNCPY(ptr, program, i); 4904 STRCPY(ptr += i, p); 4905 ptr += len; 4906 program = pos + 2; 4907 } 4908 STRCPY(ptr, program); 4909 } 4910 else 4911 { 4912 new_cmdline = alloc((int)(STRLEN(program) + STRLEN(p) + 2)); 4913 if (new_cmdline == NULL) 4914 return NULL; /* out of memory */ 4915 STRCPY(new_cmdline, program); 4916 STRCAT(new_cmdline, " "); 4917 STRCAT(new_cmdline, p); 4918 } 4919 msg_make(p); 4920 4921 /* 'eap->cmd' is not set here, because it is not used at CMD_make */ 4922 vim_free(*cmdlinep); 4923 *cmdlinep = new_cmdline; 4924 p = new_cmdline; 4925 } 4926 return p; 4927 } 4928 #endif 4929 4930 /* 4931 * Expand file name in Ex command argument. 4932 * Return FAIL for failure, OK otherwise. 4933 */ 4934 int 4935 expand_filename( 4936 exarg_T *eap, 4937 char_u **cmdlinep, 4938 char_u **errormsgp) 4939 { 4940 int has_wildcards; /* need to expand wildcards */ 4941 char_u *repl; 4942 int srclen; 4943 char_u *p; 4944 int n; 4945 int escaped; 4946 4947 #ifdef FEAT_QUICKFIX 4948 /* Skip a regexp pattern for ":vimgrep[add] pat file..." */ 4949 p = skip_grep_pat(eap); 4950 #else 4951 p = eap->arg; 4952 #endif 4953 4954 /* 4955 * Decide to expand wildcards *before* replacing '%', '#', etc. If 4956 * the file name contains a wildcard it should not cause expanding. 4957 * (it will be expanded anyway if there is a wildcard before replacing). 4958 */ 4959 has_wildcards = mch_has_wildcard(p); 4960 while (*p != NUL) 4961 { 4962 #ifdef FEAT_EVAL 4963 /* Skip over `=expr`, wildcards in it are not expanded. */ 4964 if (p[0] == '`' && p[1] == '=') 4965 { 4966 p += 2; 4967 (void)skip_expr(&p); 4968 if (*p == '`') 4969 ++p; 4970 continue; 4971 } 4972 #endif 4973 /* 4974 * Quick check if this cannot be the start of a special string. 4975 * Also removes backslash before '%', '#' and '<'. 4976 */ 4977 if (vim_strchr((char_u *)"%#<", *p) == NULL) 4978 { 4979 ++p; 4980 continue; 4981 } 4982 4983 /* 4984 * Try to find a match at this position. 4985 */ 4986 repl = eval_vars(p, eap->arg, &srclen, &(eap->do_ecmd_lnum), 4987 errormsgp, &escaped); 4988 if (*errormsgp != NULL) /* error detected */ 4989 return FAIL; 4990 if (repl == NULL) /* no match found */ 4991 { 4992 p += srclen; 4993 continue; 4994 } 4995 4996 /* Wildcards won't be expanded below, the replacement is taken 4997 * literally. But do expand "~/file", "~user/file" and "$HOME/file". */ 4998 if (vim_strchr(repl, '$') != NULL || vim_strchr(repl, '~') != NULL) 4999 { 5000 char_u *l = repl; 5001 5002 repl = expand_env_save(repl); 5003 vim_free(l); 5004 } 5005 5006 /* Need to escape white space et al. with a backslash. 5007 * Don't do this for: 5008 * - replacement that already has been escaped: "##" 5009 * - shell commands (may have to use quotes instead). 5010 * - non-unix systems when there is a single argument (spaces don't 5011 * separate arguments then). 5012 */ 5013 if (!eap->usefilter 5014 && !escaped 5015 && eap->cmdidx != CMD_bang 5016 && eap->cmdidx != CMD_grep 5017 && eap->cmdidx != CMD_grepadd 5018 && eap->cmdidx != CMD_hardcopy 5019 && eap->cmdidx != CMD_lgrep 5020 && eap->cmdidx != CMD_lgrepadd 5021 && eap->cmdidx != CMD_lmake 5022 && eap->cmdidx != CMD_make 5023 && eap->cmdidx != CMD_terminal 5024 #ifndef UNIX 5025 && !(eap->argt & NOSPC) 5026 #endif 5027 ) 5028 { 5029 char_u *l; 5030 #ifdef BACKSLASH_IN_FILENAME 5031 /* Don't escape a backslash here, because rem_backslash() doesn't 5032 * remove it later. */ 5033 static char_u *nobslash = (char_u *)" \t\"|"; 5034 # define ESCAPE_CHARS nobslash 5035 #else 5036 # define ESCAPE_CHARS escape_chars 5037 #endif 5038 5039 for (l = repl; *l; ++l) 5040 if (vim_strchr(ESCAPE_CHARS, *l) != NULL) 5041 { 5042 l = vim_strsave_escaped(repl, ESCAPE_CHARS); 5043 if (l != NULL) 5044 { 5045 vim_free(repl); 5046 repl = l; 5047 } 5048 break; 5049 } 5050 } 5051 5052 /* For a shell command a '!' must be escaped. */ 5053 if ((eap->usefilter || eap->cmdidx == CMD_bang 5054 || eap->cmdidx == CMD_terminal) 5055 && vim_strpbrk(repl, (char_u *)"!") != NULL) 5056 { 5057 char_u *l; 5058 5059 l = vim_strsave_escaped(repl, (char_u *)"!"); 5060 if (l != NULL) 5061 { 5062 vim_free(repl); 5063 repl = l; 5064 } 5065 } 5066 5067 p = repl_cmdline(eap, p, srclen, repl, cmdlinep); 5068 vim_free(repl); 5069 if (p == NULL) 5070 return FAIL; 5071 } 5072 5073 /* 5074 * One file argument: Expand wildcards. 5075 * Don't do this with ":r !command" or ":w !command". 5076 */ 5077 if ((eap->argt & NOSPC) && !eap->usefilter) 5078 { 5079 /* 5080 * May do this twice: 5081 * 1. Replace environment variables. 5082 * 2. Replace any other wildcards, remove backslashes. 5083 */ 5084 for (n = 1; n <= 2; ++n) 5085 { 5086 if (n == 2) 5087 { 5088 /* 5089 * Halve the number of backslashes (this is Vi compatible). 5090 * For Unix and OS/2, when wildcards are expanded, this is 5091 * done by ExpandOne() below. 5092 */ 5093 #if defined(UNIX) 5094 if (!has_wildcards) 5095 #endif 5096 backslash_halve(eap->arg); 5097 } 5098 5099 if (has_wildcards) 5100 { 5101 if (n == 1) 5102 { 5103 /* 5104 * First loop: May expand environment variables. This 5105 * can be done much faster with expand_env() than with 5106 * something else (e.g., calling a shell). 5107 * After expanding environment variables, check again 5108 * if there are still wildcards present. 5109 */ 5110 if (vim_strchr(eap->arg, '$') != NULL 5111 || vim_strchr(eap->arg, '~') != NULL) 5112 { 5113 expand_env_esc(eap->arg, NameBuff, MAXPATHL, 5114 TRUE, TRUE, NULL); 5115 has_wildcards = mch_has_wildcard(NameBuff); 5116 p = NameBuff; 5117 } 5118 else 5119 p = NULL; 5120 } 5121 else /* n == 2 */ 5122 { 5123 expand_T xpc; 5124 int options = WILD_LIST_NOTFOUND|WILD_ADD_SLASH; 5125 5126 ExpandInit(&xpc); 5127 xpc.xp_context = EXPAND_FILES; 5128 if (p_wic) 5129 options += WILD_ICASE; 5130 p = ExpandOne(&xpc, eap->arg, NULL, 5131 options, WILD_EXPAND_FREE); 5132 if (p == NULL) 5133 return FAIL; 5134 } 5135 if (p != NULL) 5136 { 5137 (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg), 5138 p, cmdlinep); 5139 if (n == 2) /* p came from ExpandOne() */ 5140 vim_free(p); 5141 } 5142 } 5143 } 5144 } 5145 return OK; 5146 } 5147 5148 /* 5149 * Replace part of the command line, keeping eap->cmd, eap->arg and 5150 * eap->nextcmd correct. 5151 * "src" points to the part that is to be replaced, of length "srclen". 5152 * "repl" is the replacement string. 5153 * Returns a pointer to the character after the replaced string. 5154 * Returns NULL for failure. 5155 */ 5156 static char_u * 5157 repl_cmdline( 5158 exarg_T *eap, 5159 char_u *src, 5160 int srclen, 5161 char_u *repl, 5162 char_u **cmdlinep) 5163 { 5164 int len; 5165 int i; 5166 char_u *new_cmdline; 5167 5168 /* 5169 * The new command line is build in new_cmdline[]. 5170 * First allocate it. 5171 * Careful: a "+cmd" argument may have been NUL terminated. 5172 */ 5173 len = (int)STRLEN(repl); 5174 i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3; 5175 if (eap->nextcmd != NULL) 5176 i += (int)STRLEN(eap->nextcmd);/* add space for next command */ 5177 if ((new_cmdline = alloc((unsigned)i)) == NULL) 5178 return NULL; /* out of memory! */ 5179 5180 /* 5181 * Copy the stuff before the expanded part. 5182 * Copy the expanded stuff. 5183 * Copy what came after the expanded part. 5184 * Copy the next commands, if there are any. 5185 */ 5186 i = (int)(src - *cmdlinep); /* length of part before match */ 5187 mch_memmove(new_cmdline, *cmdlinep, (size_t)i); 5188 5189 mch_memmove(new_cmdline + i, repl, (size_t)len); 5190 i += len; /* remember the end of the string */ 5191 STRCPY(new_cmdline + i, src + srclen); 5192 src = new_cmdline + i; /* remember where to continue */ 5193 5194 if (eap->nextcmd != NULL) /* append next command */ 5195 { 5196 i = (int)STRLEN(new_cmdline) + 1; 5197 STRCPY(new_cmdline + i, eap->nextcmd); 5198 eap->nextcmd = new_cmdline + i; 5199 } 5200 eap->cmd = new_cmdline + (eap->cmd - *cmdlinep); 5201 eap->arg = new_cmdline + (eap->arg - *cmdlinep); 5202 if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command) 5203 eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep); 5204 vim_free(*cmdlinep); 5205 *cmdlinep = new_cmdline; 5206 5207 return src; 5208 } 5209 5210 /* 5211 * Check for '|' to separate commands and '"' to start comments. 5212 */ 5213 void 5214 separate_nextcmd(exarg_T *eap) 5215 { 5216 char_u *p; 5217 5218 #ifdef FEAT_QUICKFIX 5219 p = skip_grep_pat(eap); 5220 #else 5221 p = eap->arg; 5222 #endif 5223 5224 for ( ; *p; MB_PTR_ADV(p)) 5225 { 5226 if (*p == Ctrl_V) 5227 { 5228 if (eap->argt & (USECTRLV | XFILE)) 5229 ++p; /* skip CTRL-V and next char */ 5230 else 5231 /* remove CTRL-V and skip next char */ 5232 STRMOVE(p, p + 1); 5233 if (*p == NUL) /* stop at NUL after CTRL-V */ 5234 break; 5235 } 5236 5237 #ifdef FEAT_EVAL 5238 /* Skip over `=expr` when wildcards are expanded. */ 5239 else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) 5240 { 5241 p += 2; 5242 (void)skip_expr(&p); 5243 } 5244 #endif 5245 5246 /* Check for '"': start of comment or '|': next command */ 5247 /* :@" and :*" do not start a comment! 5248 * :redir @" doesn't either. */ 5249 else if ((*p == '"' && !(eap->argt & NOTRLCOM) 5250 && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star) 5251 || p != eap->arg) 5252 && (eap->cmdidx != CMD_redir 5253 || p != eap->arg + 1 || p[-1] != '@')) 5254 || *p == '|' || *p == '\n') 5255 { 5256 /* 5257 * We remove the '\' before the '|', unless USECTRLV is used 5258 * AND 'b' is present in 'cpoptions'. 5259 */ 5260 if ((vim_strchr(p_cpo, CPO_BAR) == NULL 5261 || !(eap->argt & USECTRLV)) && *(p - 1) == '\\') 5262 { 5263 STRMOVE(p - 1, p); /* remove the '\' */ 5264 --p; 5265 } 5266 else 5267 { 5268 eap->nextcmd = check_nextcmd(p); 5269 *p = NUL; 5270 break; 5271 } 5272 } 5273 } 5274 5275 if (!(eap->argt & NOTRLCOM)) /* remove trailing spaces */ 5276 del_trailing_spaces(eap->arg); 5277 } 5278 5279 /* 5280 * get + command from ex argument 5281 */ 5282 static char_u * 5283 getargcmd(char_u **argp) 5284 { 5285 char_u *arg = *argp; 5286 char_u *command = NULL; 5287 5288 if (*arg == '+') /* +[command] */ 5289 { 5290 ++arg; 5291 if (vim_isspace(*arg) || *arg == NUL) 5292 command = dollar_command; 5293 else 5294 { 5295 command = arg; 5296 arg = skip_cmd_arg(command, TRUE); 5297 if (*arg != NUL) 5298 *arg++ = NUL; /* terminate command with NUL */ 5299 } 5300 5301 arg = skipwhite(arg); /* skip over spaces */ 5302 *argp = arg; 5303 } 5304 return command; 5305 } 5306 5307 /* 5308 * Find end of "+command" argument. Skip over "\ " and "\\". 5309 */ 5310 static char_u * 5311 skip_cmd_arg( 5312 char_u *p, 5313 int rembs) /* TRUE to halve the number of backslashes */ 5314 { 5315 while (*p && !vim_isspace(*p)) 5316 { 5317 if (*p == '\\' && p[1] != NUL) 5318 { 5319 if (rembs) 5320 STRMOVE(p, p + 1); 5321 else 5322 ++p; 5323 } 5324 MB_PTR_ADV(p); 5325 } 5326 return p; 5327 } 5328 5329 /* 5330 * Get "++opt=arg" argument. 5331 * Return FAIL or OK. 5332 */ 5333 static int 5334 getargopt(exarg_T *eap) 5335 { 5336 char_u *arg = eap->arg + 2; 5337 int *pp = NULL; 5338 #ifdef FEAT_MBYTE 5339 int bad_char_idx; 5340 char_u *p; 5341 #endif 5342 5343 /* ":edit ++[no]bin[ary] file" */ 5344 if (STRNCMP(arg, "bin", 3) == 0 || STRNCMP(arg, "nobin", 5) == 0) 5345 { 5346 if (*arg == 'n') 5347 { 5348 arg += 2; 5349 eap->force_bin = FORCE_NOBIN; 5350 } 5351 else 5352 eap->force_bin = FORCE_BIN; 5353 if (!checkforcmd(&arg, "binary", 3)) 5354 return FAIL; 5355 eap->arg = skipwhite(arg); 5356 return OK; 5357 } 5358 5359 /* ":read ++edit file" */ 5360 if (STRNCMP(arg, "edit", 4) == 0) 5361 { 5362 eap->read_edit = TRUE; 5363 eap->arg = skipwhite(arg + 4); 5364 return OK; 5365 } 5366 5367 if (STRNCMP(arg, "ff", 2) == 0) 5368 { 5369 arg += 2; 5370 pp = &eap->force_ff; 5371 } 5372 else if (STRNCMP(arg, "fileformat", 10) == 0) 5373 { 5374 arg += 10; 5375 pp = &eap->force_ff; 5376 } 5377 #ifdef FEAT_MBYTE 5378 else if (STRNCMP(arg, "enc", 3) == 0) 5379 { 5380 if (STRNCMP(arg, "encoding", 8) == 0) 5381 arg += 8; 5382 else 5383 arg += 3; 5384 pp = &eap->force_enc; 5385 } 5386 else if (STRNCMP(arg, "bad", 3) == 0) 5387 { 5388 arg += 3; 5389 pp = &bad_char_idx; 5390 } 5391 #endif 5392 5393 if (pp == NULL || *arg != '=') 5394 return FAIL; 5395 5396 ++arg; 5397 *pp = (int)(arg - eap->cmd); 5398 arg = skip_cmd_arg(arg, FALSE); 5399 eap->arg = skipwhite(arg); 5400 *arg = NUL; 5401 5402 #ifdef FEAT_MBYTE 5403 if (pp == &eap->force_ff) 5404 { 5405 #endif 5406 if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) 5407 return FAIL; 5408 #ifdef FEAT_MBYTE 5409 } 5410 else if (pp == &eap->force_enc) 5411 { 5412 /* Make 'fileencoding' lower case. */ 5413 for (p = eap->cmd + eap->force_enc; *p != NUL; ++p) 5414 *p = TOLOWER_ASC(*p); 5415 } 5416 else 5417 { 5418 /* Check ++bad= argument. Must be a single-byte character, "keep" or 5419 * "drop". */ 5420 p = eap->cmd + bad_char_idx; 5421 if (STRICMP(p, "keep") == 0) 5422 eap->bad_char = BAD_KEEP; 5423 else if (STRICMP(p, "drop") == 0) 5424 eap->bad_char = BAD_DROP; 5425 else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL) 5426 eap->bad_char = *p; 5427 else 5428 return FAIL; 5429 } 5430 #endif 5431 5432 return OK; 5433 } 5434 5435 /* 5436 * ":abbreviate" and friends. 5437 */ 5438 static void 5439 ex_abbreviate(exarg_T *eap) 5440 { 5441 do_exmap(eap, TRUE); /* almost the same as mapping */ 5442 } 5443 5444 /* 5445 * ":map" and friends. 5446 */ 5447 static void 5448 ex_map(exarg_T *eap) 5449 { 5450 /* 5451 * If we are sourcing .exrc or .vimrc in current directory we 5452 * print the mappings for security reasons. 5453 */ 5454 if (secure) 5455 { 5456 secure = 2; 5457 msg_outtrans(eap->cmd); 5458 msg_putchar('\n'); 5459 } 5460 do_exmap(eap, FALSE); 5461 } 5462 5463 /* 5464 * ":unmap" and friends. 5465 */ 5466 static void 5467 ex_unmap(exarg_T *eap) 5468 { 5469 do_exmap(eap, FALSE); 5470 } 5471 5472 /* 5473 * ":mapclear" and friends. 5474 */ 5475 static void 5476 ex_mapclear(exarg_T *eap) 5477 { 5478 map_clear(eap->cmd, eap->arg, eap->forceit, FALSE); 5479 } 5480 5481 /* 5482 * ":abclear" and friends. 5483 */ 5484 static void 5485 ex_abclear(exarg_T *eap) 5486 { 5487 map_clear(eap->cmd, eap->arg, TRUE, TRUE); 5488 } 5489 5490 #if defined(FEAT_AUTOCMD) || defined(PROTO) 5491 static void 5492 ex_autocmd(exarg_T *eap) 5493 { 5494 /* 5495 * Disallow auto commands from .exrc and .vimrc in current 5496 * directory for security reasons. 5497 */ 5498 if (secure) 5499 { 5500 secure = 2; 5501 eap->errmsg = e_curdir; 5502 } 5503 else if (eap->cmdidx == CMD_autocmd) 5504 do_autocmd(eap->arg, eap->forceit); 5505 else 5506 do_augroup(eap->arg, eap->forceit); 5507 } 5508 5509 /* 5510 * ":doautocmd": Apply the automatic commands to the current buffer. 5511 */ 5512 static void 5513 ex_doautocmd(exarg_T *eap) 5514 { 5515 char_u *arg = eap->arg; 5516 int call_do_modelines = check_nomodeline(&arg); 5517 int did_aucmd; 5518 5519 (void)do_doautocmd(arg, TRUE, &did_aucmd); 5520 /* Only when there is no <nomodeline>. */ 5521 if (call_do_modelines && did_aucmd) 5522 do_modelines(0); 5523 } 5524 #endif 5525 5526 #ifdef FEAT_LISTCMDS 5527 /* 5528 * :[N]bunload[!] [N] [bufname] unload buffer 5529 * :[N]bdelete[!] [N] [bufname] delete buffer from buffer list 5530 * :[N]bwipeout[!] [N] [bufname] delete buffer really 5531 */ 5532 static void 5533 ex_bunload(exarg_T *eap) 5534 { 5535 eap->errmsg = do_bufdel( 5536 eap->cmdidx == CMD_bdelete ? DOBUF_DEL 5537 : eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE 5538 : DOBUF_UNLOAD, eap->arg, 5539 eap->addr_count, (int)eap->line1, (int)eap->line2, eap->forceit); 5540 } 5541 5542 /* 5543 * :[N]buffer [N] to buffer N 5544 * :[N]sbuffer [N] to buffer N 5545 */ 5546 static void 5547 ex_buffer(exarg_T *eap) 5548 { 5549 if (*eap->arg) 5550 eap->errmsg = e_trailing; 5551 else 5552 { 5553 if (eap->addr_count == 0) /* default is current buffer */ 5554 goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0); 5555 else 5556 goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2); 5557 if (eap->do_ecmd_cmd != NULL) 5558 do_cmdline_cmd(eap->do_ecmd_cmd); 5559 } 5560 } 5561 5562 /* 5563 * :[N]bmodified [N] to next mod. buffer 5564 * :[N]sbmodified [N] to next mod. buffer 5565 */ 5566 static void 5567 ex_bmodified(exarg_T *eap) 5568 { 5569 goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2); 5570 if (eap->do_ecmd_cmd != NULL) 5571 do_cmdline_cmd(eap->do_ecmd_cmd); 5572 } 5573 5574 /* 5575 * :[N]bnext [N] to next buffer 5576 * :[N]sbnext [N] split and to next buffer 5577 */ 5578 static void 5579 ex_bnext(exarg_T *eap) 5580 { 5581 goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2); 5582 if (eap->do_ecmd_cmd != NULL) 5583 do_cmdline_cmd(eap->do_ecmd_cmd); 5584 } 5585 5586 /* 5587 * :[N]bNext [N] to previous buffer 5588 * :[N]bprevious [N] to previous buffer 5589 * :[N]sbNext [N] split and to previous buffer 5590 * :[N]sbprevious [N] split and to previous buffer 5591 */ 5592 static void 5593 ex_bprevious(exarg_T *eap) 5594 { 5595 goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2); 5596 if (eap->do_ecmd_cmd != NULL) 5597 do_cmdline_cmd(eap->do_ecmd_cmd); 5598 } 5599 5600 /* 5601 * :brewind to first buffer 5602 * :bfirst to first buffer 5603 * :sbrewind split and to first buffer 5604 * :sbfirst split and to first buffer 5605 */ 5606 static void 5607 ex_brewind(exarg_T *eap) 5608 { 5609 goto_buffer(eap, DOBUF_FIRST, FORWARD, 0); 5610 if (eap->do_ecmd_cmd != NULL) 5611 do_cmdline_cmd(eap->do_ecmd_cmd); 5612 } 5613 5614 /* 5615 * :blast to last buffer 5616 * :sblast split and to last buffer 5617 */ 5618 static void 5619 ex_blast(exarg_T *eap) 5620 { 5621 goto_buffer(eap, DOBUF_LAST, BACKWARD, 0); 5622 if (eap->do_ecmd_cmd != NULL) 5623 do_cmdline_cmd(eap->do_ecmd_cmd); 5624 } 5625 #endif 5626 5627 int 5628 ends_excmd(int c) 5629 { 5630 return (c == NUL || c == '|' || c == '"' || c == '\n'); 5631 } 5632 5633 #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \ 5634 || defined(PROTO) 5635 /* 5636 * Return the next command, after the first '|' or '\n'. 5637 * Return NULL if not found. 5638 */ 5639 char_u * 5640 find_nextcmd(char_u *p) 5641 { 5642 while (*p != '|' && *p != '\n') 5643 { 5644 if (*p == NUL) 5645 return NULL; 5646 ++p; 5647 } 5648 return (p + 1); 5649 } 5650 #endif 5651 5652 /* 5653 * Check if *p is a separator between Ex commands, skipping over white space. 5654 * Return NULL if it isn't, the following character if it is. 5655 */ 5656 char_u * 5657 check_nextcmd(char_u *p) 5658 { 5659 char_u *s = skipwhite(p); 5660 5661 if (*s == '|' || *s == '\n') 5662 return (s + 1); 5663 else 5664 return NULL; 5665 } 5666 5667 /* 5668 * - if there are more files to edit 5669 * - and this is the last window 5670 * - and forceit not used 5671 * - and not repeated twice on a row 5672 * return FAIL and give error message if 'message' TRUE 5673 * return OK otherwise 5674 */ 5675 static int 5676 check_more( 5677 int message, /* when FALSE check only, no messages */ 5678 int forceit) 5679 { 5680 int n = ARGCOUNT - curwin->w_arg_idx - 1; 5681 5682 if (!forceit && only_one_window() 5683 && ARGCOUNT > 1 && !arg_had_last && n >= 0 && quitmore == 0) 5684 { 5685 if (message) 5686 { 5687 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 5688 if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL) 5689 { 5690 char_u buff[DIALOG_MSG_SIZE]; 5691 5692 if (n == 1) 5693 vim_strncpy(buff, 5694 (char_u *)_("1 more file to edit. Quit anyway?"), 5695 DIALOG_MSG_SIZE - 1); 5696 else 5697 vim_snprintf((char *)buff, DIALOG_MSG_SIZE, 5698 _("%d more files to edit. Quit anyway?"), n); 5699 if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) 5700 return OK; 5701 return FAIL; 5702 } 5703 #endif 5704 if (n == 1) 5705 EMSG(_("E173: 1 more file to edit")); 5706 else 5707 EMSGN(_("E173: %ld more files to edit"), n); 5708 quitmore = 2; /* next try to quit is allowed */ 5709 } 5710 return FAIL; 5711 } 5712 return OK; 5713 } 5714 5715 #ifdef FEAT_CMDL_COMPL 5716 /* 5717 * Function given to ExpandGeneric() to obtain the list of command names. 5718 */ 5719 char_u * 5720 get_command_name(expand_T *xp UNUSED, int idx) 5721 { 5722 if (idx >= (int)CMD_SIZE) 5723 # ifdef FEAT_USR_CMDS 5724 return get_user_command_name(idx); 5725 # else 5726 return NULL; 5727 # endif 5728 return cmdnames[idx].cmd_name; 5729 } 5730 #endif 5731 5732 #if defined(FEAT_USR_CMDS) || defined(PROTO) 5733 static int uc_add_command(char_u *name, size_t name_len, char_u *rep, long argt, long def, int flags, int compl, char_u *compl_arg, int addr_type, int force); 5734 static void uc_list(char_u *name, size_t name_len); 5735 static int uc_scan_attr(char_u *attr, size_t len, long *argt, long *def, int *flags, int *compl, char_u **compl_arg, int* attr_type_arg); 5736 static char_u *uc_split_args(char_u *arg, size_t *lenp); 5737 static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd, exarg_T *eap, char_u **split_buf, size_t *split_len); 5738 5739 static int 5740 uc_add_command( 5741 char_u *name, 5742 size_t name_len, 5743 char_u *rep, 5744 long argt, 5745 long def, 5746 int flags, 5747 int compl, 5748 char_u *compl_arg, 5749 int addr_type, 5750 int force) 5751 { 5752 ucmd_T *cmd = NULL; 5753 char_u *p; 5754 int i; 5755 int cmp = 1; 5756 char_u *rep_buf = NULL; 5757 garray_T *gap; 5758 5759 replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE); 5760 if (rep_buf == NULL) 5761 { 5762 /* Can't replace termcodes - try using the string as is */ 5763 rep_buf = vim_strsave(rep); 5764 5765 /* Give up if out of memory */ 5766 if (rep_buf == NULL) 5767 return FAIL; 5768 } 5769 5770 /* get address of growarray: global or in curbuf */ 5771 if (flags & UC_BUFFER) 5772 { 5773 gap = &curbuf->b_ucmds; 5774 if (gap->ga_itemsize == 0) 5775 ga_init2(gap, (int)sizeof(ucmd_T), 4); 5776 } 5777 else 5778 gap = &ucmds; 5779 5780 /* Search for the command in the already defined commands. */ 5781 for (i = 0; i < gap->ga_len; ++i) 5782 { 5783 size_t len; 5784 5785 cmd = USER_CMD_GA(gap, i); 5786 len = STRLEN(cmd->uc_name); 5787 cmp = STRNCMP(name, cmd->uc_name, name_len); 5788 if (cmp == 0) 5789 { 5790 if (name_len < len) 5791 cmp = -1; 5792 else if (name_len > len) 5793 cmp = 1; 5794 } 5795 5796 if (cmp == 0) 5797 { 5798 if (!force) 5799 { 5800 EMSG(_("E174: Command already exists: add ! to replace it")); 5801 goto fail; 5802 } 5803 5804 vim_free(cmd->uc_rep); 5805 cmd->uc_rep = NULL; 5806 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 5807 vim_free(cmd->uc_compl_arg); 5808 cmd->uc_compl_arg = NULL; 5809 #endif 5810 break; 5811 } 5812 5813 /* Stop as soon as we pass the name to add */ 5814 if (cmp < 0) 5815 break; 5816 } 5817 5818 /* Extend the array unless we're replacing an existing command */ 5819 if (cmp != 0) 5820 { 5821 if (ga_grow(gap, 1) != OK) 5822 goto fail; 5823 if ((p = vim_strnsave(name, (int)name_len)) == NULL) 5824 goto fail; 5825 5826 cmd = USER_CMD_GA(gap, i); 5827 mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T)); 5828 5829 ++gap->ga_len; 5830 5831 cmd->uc_name = p; 5832 } 5833 5834 cmd->uc_rep = rep_buf; 5835 cmd->uc_argt = argt; 5836 cmd->uc_def = def; 5837 cmd->uc_compl = compl; 5838 #ifdef FEAT_EVAL 5839 cmd->uc_scriptID = current_SID; 5840 # ifdef FEAT_CMDL_COMPL 5841 cmd->uc_compl_arg = compl_arg; 5842 # endif 5843 #endif 5844 cmd->uc_addr_type = addr_type; 5845 5846 return OK; 5847 5848 fail: 5849 vim_free(rep_buf); 5850 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 5851 vim_free(compl_arg); 5852 #endif 5853 return FAIL; 5854 } 5855 #endif 5856 5857 #if defined(FEAT_USR_CMDS) 5858 static struct 5859 { 5860 int expand; 5861 char *name; 5862 } addr_type_complete[] = 5863 { 5864 {ADDR_ARGUMENTS, "arguments"}, 5865 {ADDR_LINES, "lines"}, 5866 {ADDR_LOADED_BUFFERS, "loaded_buffers"}, 5867 {ADDR_TABS, "tabs"}, 5868 {ADDR_BUFFERS, "buffers"}, 5869 {ADDR_WINDOWS, "windows"}, 5870 {ADDR_QUICKFIX, "quickfix"}, 5871 {-1, NULL} 5872 }; 5873 #endif 5874 5875 #if defined(FEAT_USR_CMDS) || defined(FEAT_EVAL) || defined(PROTO) 5876 /* 5877 * List of names for completion for ":command" with the EXPAND_ flag. 5878 * Must be alphabetical for completion. 5879 */ 5880 static struct 5881 { 5882 int expand; 5883 char *name; 5884 } command_complete[] = 5885 { 5886 {EXPAND_AUGROUP, "augroup"}, 5887 {EXPAND_BEHAVE, "behave"}, 5888 {EXPAND_BUFFERS, "buffer"}, 5889 {EXPAND_COLORS, "color"}, 5890 {EXPAND_COMMANDS, "command"}, 5891 {EXPAND_COMPILER, "compiler"}, 5892 #if defined(FEAT_CSCOPE) 5893 {EXPAND_CSCOPE, "cscope"}, 5894 #endif 5895 #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 5896 {EXPAND_USER_DEFINED, "custom"}, 5897 {EXPAND_USER_LIST, "customlist"}, 5898 #endif 5899 {EXPAND_DIRECTORIES, "dir"}, 5900 {EXPAND_ENV_VARS, "environment"}, 5901 {EXPAND_EVENTS, "event"}, 5902 {EXPAND_EXPRESSION, "expression"}, 5903 {EXPAND_FILES, "file"}, 5904 {EXPAND_FILES_IN_PATH, "file_in_path"}, 5905 {EXPAND_FILETYPE, "filetype"}, 5906 {EXPAND_FUNCTIONS, "function"}, 5907 {EXPAND_HELP, "help"}, 5908 {EXPAND_HIGHLIGHT, "highlight"}, 5909 #if defined(FEAT_CMDHIST) 5910 {EXPAND_HISTORY, "history"}, 5911 #endif 5912 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 5913 && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) 5914 {EXPAND_LOCALES, "locale"}, 5915 #endif 5916 {EXPAND_MAPCLEAR, "mapclear"}, 5917 {EXPAND_MAPPINGS, "mapping"}, 5918 {EXPAND_MENUS, "menu"}, 5919 {EXPAND_MESSAGES, "messages"}, 5920 {EXPAND_OWNSYNTAX, "syntax"}, 5921 #if defined(FEAT_PROFILE) 5922 {EXPAND_SYNTIME, "syntime"}, 5923 #endif 5924 {EXPAND_SETTINGS, "option"}, 5925 {EXPAND_PACKADD, "packadd"}, 5926 {EXPAND_SHELLCMD, "shellcmd"}, 5927 #if defined(FEAT_SIGNS) 5928 {EXPAND_SIGN, "sign"}, 5929 #endif 5930 {EXPAND_TAGS, "tag"}, 5931 {EXPAND_TAGS_LISTFILES, "tag_listfiles"}, 5932 {EXPAND_USER, "user"}, 5933 {EXPAND_USER_VARS, "var"}, 5934 {0, NULL} 5935 }; 5936 #endif 5937 5938 #if defined(FEAT_USR_CMDS) || defined(PROTO) 5939 static void 5940 uc_list(char_u *name, size_t name_len) 5941 { 5942 int i, j; 5943 int found = FALSE; 5944 ucmd_T *cmd; 5945 int len; 5946 long a; 5947 garray_T *gap; 5948 5949 gap = &curbuf->b_ucmds; 5950 for (;;) 5951 { 5952 for (i = 0; i < gap->ga_len; ++i) 5953 { 5954 cmd = USER_CMD_GA(gap, i); 5955 a = (long)cmd->uc_argt; 5956 5957 /* Skip commands which don't match the requested prefix and 5958 * commands filtered out. */ 5959 if (STRNCMP(name, cmd->uc_name, name_len) != 0 5960 || message_filtered(cmd->uc_name)) 5961 continue; 5962 5963 /* Put out the title first time */ 5964 if (!found) 5965 MSG_PUTS_TITLE(_("\n Name Args Address Complete Definition")); 5966 found = TRUE; 5967 msg_putchar('\n'); 5968 if (got_int) 5969 break; 5970 5971 /* Special cases */ 5972 msg_putchar(a & BANG ? '!' : ' '); 5973 msg_putchar(a & REGSTR ? '"' : ' '); 5974 msg_putchar(gap != &ucmds ? 'b' : ' '); 5975 msg_putchar(' '); 5976 5977 msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D)); 5978 len = (int)STRLEN(cmd->uc_name) + 4; 5979 5980 do { 5981 msg_putchar(' '); 5982 ++len; 5983 } while (len < 16); 5984 5985 len = 0; 5986 5987 /* Arguments */ 5988 switch ((int)(a & (EXTRA|NOSPC|NEEDARG))) 5989 { 5990 case 0: IObuff[len++] = '0'; break; 5991 case (EXTRA): IObuff[len++] = '*'; break; 5992 case (EXTRA|NOSPC): IObuff[len++] = '?'; break; 5993 case (EXTRA|NEEDARG): IObuff[len++] = '+'; break; 5994 case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break; 5995 } 5996 5997 do { 5998 IObuff[len++] = ' '; 5999 } while (len < 5); 6000 6001 /* Range */ 6002 if (a & (RANGE|COUNT)) 6003 { 6004 if (a & COUNT) 6005 { 6006 /* -count=N */ 6007 sprintf((char *)IObuff + len, "%ldc", cmd->uc_def); 6008 len += (int)STRLEN(IObuff + len); 6009 } 6010 else if (a & DFLALL) 6011 IObuff[len++] = '%'; 6012 else if (cmd->uc_def >= 0) 6013 { 6014 /* -range=N */ 6015 sprintf((char *)IObuff + len, "%ld", cmd->uc_def); 6016 len += (int)STRLEN(IObuff + len); 6017 } 6018 else 6019 IObuff[len++] = '.'; 6020 } 6021 6022 do { 6023 IObuff[len++] = ' '; 6024 } while (len < 11); 6025 6026 /* Address Type */ 6027 for (j = 0; addr_type_complete[j].expand != -1; ++j) 6028 if (addr_type_complete[j].expand != ADDR_LINES 6029 && addr_type_complete[j].expand == cmd->uc_addr_type) 6030 { 6031 STRCPY(IObuff + len, addr_type_complete[j].name); 6032 len += (int)STRLEN(IObuff + len); 6033 break; 6034 } 6035 6036 do { 6037 IObuff[len++] = ' '; 6038 } while (len < 21); 6039 6040 /* Completion */ 6041 for (j = 0; command_complete[j].expand != 0; ++j) 6042 if (command_complete[j].expand == cmd->uc_compl) 6043 { 6044 STRCPY(IObuff + len, command_complete[j].name); 6045 len += (int)STRLEN(IObuff + len); 6046 break; 6047 } 6048 6049 do { 6050 IObuff[len++] = ' '; 6051 } while (len < 35); 6052 6053 IObuff[len] = '\0'; 6054 msg_outtrans(IObuff); 6055 6056 msg_outtrans_special(cmd->uc_rep, FALSE); 6057 #ifdef FEAT_EVAL 6058 if (p_verbose > 0) 6059 last_set_msg(cmd->uc_scriptID); 6060 #endif 6061 out_flush(); 6062 ui_breakcheck(); 6063 if (got_int) 6064 break; 6065 } 6066 if (gap == &ucmds || i < gap->ga_len) 6067 break; 6068 gap = &ucmds; 6069 } 6070 6071 if (!found) 6072 MSG(_("No user-defined commands found")); 6073 } 6074 6075 static char_u * 6076 uc_fun_cmd(void) 6077 { 6078 static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4, 6079 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60, 6080 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2, 6081 0xb9, 0x7f, 0}; 6082 int i; 6083 6084 for (i = 0; fcmd[i]; ++i) 6085 IObuff[i] = fcmd[i] - 0x40; 6086 IObuff[i] = 0; 6087 return IObuff; 6088 } 6089 6090 static int 6091 uc_scan_attr( 6092 char_u *attr, 6093 size_t len, 6094 long *argt, 6095 long *def, 6096 int *flags, 6097 int *compl, 6098 char_u **compl_arg, 6099 int *addr_type_arg) 6100 { 6101 char_u *p; 6102 6103 if (len == 0) 6104 { 6105 EMSG(_("E175: No attribute specified")); 6106 return FAIL; 6107 } 6108 6109 /* First, try the simple attributes (no arguments) */ 6110 if (STRNICMP(attr, "bang", len) == 0) 6111 *argt |= BANG; 6112 else if (STRNICMP(attr, "buffer", len) == 0) 6113 *flags |= UC_BUFFER; 6114 else if (STRNICMP(attr, "register", len) == 0) 6115 *argt |= REGSTR; 6116 else if (STRNICMP(attr, "bar", len) == 0) 6117 *argt |= TRLBAR; 6118 else 6119 { 6120 int i; 6121 char_u *val = NULL; 6122 size_t vallen = 0; 6123 size_t attrlen = len; 6124 6125 /* Look for the attribute name - which is the part before any '=' */ 6126 for (i = 0; i < (int)len; ++i) 6127 { 6128 if (attr[i] == '=') 6129 { 6130 val = &attr[i + 1]; 6131 vallen = len - i - 1; 6132 attrlen = i; 6133 break; 6134 } 6135 } 6136 6137 if (STRNICMP(attr, "nargs", attrlen) == 0) 6138 { 6139 if (vallen == 1) 6140 { 6141 if (*val == '0') 6142 /* Do nothing - this is the default */; 6143 else if (*val == '1') 6144 *argt |= (EXTRA | NOSPC | NEEDARG); 6145 else if (*val == '*') 6146 *argt |= EXTRA; 6147 else if (*val == '?') 6148 *argt |= (EXTRA | NOSPC); 6149 else if (*val == '+') 6150 *argt |= (EXTRA | NEEDARG); 6151 else 6152 goto wrong_nargs; 6153 } 6154 else 6155 { 6156 wrong_nargs: 6157 EMSG(_("E176: Invalid number of arguments")); 6158 return FAIL; 6159 } 6160 } 6161 else if (STRNICMP(attr, "range", attrlen) == 0) 6162 { 6163 *argt |= RANGE; 6164 if (vallen == 1 && *val == '%') 6165 *argt |= DFLALL; 6166 else if (val != NULL) 6167 { 6168 p = val; 6169 if (*def >= 0) 6170 { 6171 two_count: 6172 EMSG(_("E177: Count cannot be specified twice")); 6173 return FAIL; 6174 } 6175 6176 *def = getdigits(&p); 6177 *argt |= (ZEROR | NOTADR); 6178 6179 if (p != val + vallen || vallen == 0) 6180 { 6181 invalid_count: 6182 EMSG(_("E178: Invalid default value for count")); 6183 return FAIL; 6184 } 6185 } 6186 } 6187 else if (STRNICMP(attr, "count", attrlen) == 0) 6188 { 6189 *argt |= (COUNT | ZEROR | RANGE | NOTADR); 6190 6191 if (val != NULL) 6192 { 6193 p = val; 6194 if (*def >= 0) 6195 goto two_count; 6196 6197 *def = getdigits(&p); 6198 6199 if (p != val + vallen) 6200 goto invalid_count; 6201 } 6202 6203 if (*def < 0) 6204 *def = 0; 6205 } 6206 else if (STRNICMP(attr, "complete", attrlen) == 0) 6207 { 6208 if (val == NULL) 6209 { 6210 EMSG(_("E179: argument required for -complete")); 6211 return FAIL; 6212 } 6213 6214 if (parse_compl_arg(val, (int)vallen, compl, argt, compl_arg) 6215 == FAIL) 6216 return FAIL; 6217 } 6218 else if (STRNICMP(attr, "addr", attrlen) == 0) 6219 { 6220 *argt |= RANGE; 6221 if (val == NULL) 6222 { 6223 EMSG(_("E179: argument required for -addr")); 6224 return FAIL; 6225 } 6226 if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) 6227 == FAIL) 6228 return FAIL; 6229 if (addr_type_arg != ADDR_LINES) 6230 *argt |= (ZEROR | NOTADR) ; 6231 } 6232 else 6233 { 6234 char_u ch = attr[len]; 6235 attr[len] = '\0'; 6236 EMSG2(_("E181: Invalid attribute: %s"), attr); 6237 attr[len] = ch; 6238 return FAIL; 6239 } 6240 } 6241 6242 return OK; 6243 } 6244 6245 /* 6246 * ":command ..." 6247 */ 6248 static void 6249 ex_command(exarg_T *eap) 6250 { 6251 char_u *name; 6252 char_u *end; 6253 char_u *p; 6254 long argt = 0; 6255 long def = -1; 6256 int flags = 0; 6257 int compl = EXPAND_NOTHING; 6258 char_u *compl_arg = NULL; 6259 int addr_type_arg = ADDR_LINES; 6260 int has_attr = (eap->arg[0] == '-'); 6261 int name_len; 6262 6263 p = eap->arg; 6264 6265 /* Check for attributes */ 6266 while (*p == '-') 6267 { 6268 ++p; 6269 end = skiptowhite(p); 6270 if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, 6271 &compl_arg, &addr_type_arg) 6272 == FAIL) 6273 return; 6274 p = skipwhite(end); 6275 } 6276 6277 /* Get the name (if any) and skip to the following argument */ 6278 name = p; 6279 if (ASCII_ISALPHA(*p)) 6280 while (ASCII_ISALNUM(*p)) 6281 ++p; 6282 if (!ends_excmd(*p) && !VIM_ISWHITE(*p)) 6283 { 6284 EMSG(_("E182: Invalid command name")); 6285 return; 6286 } 6287 end = p; 6288 name_len = (int)(end - name); 6289 6290 /* If there is nothing after the name, and no attributes were specified, 6291 * we are listing commands 6292 */ 6293 p = skipwhite(end); 6294 if (!has_attr && ends_excmd(*p)) 6295 { 6296 uc_list(name, end - name); 6297 } 6298 else if (!ASCII_ISUPPER(*name)) 6299 { 6300 EMSG(_("E183: User defined commands must start with an uppercase letter")); 6301 return; 6302 } 6303 else if ((name_len == 1 && *name == 'X') 6304 || (name_len <= 4 6305 && STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0)) 6306 { 6307 EMSG(_("E841: Reserved name, cannot be used for user defined command")); 6308 return; 6309 } 6310 else 6311 uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, 6312 addr_type_arg, eap->forceit); 6313 } 6314 6315 /* 6316 * ":comclear" 6317 * Clear all user commands, global and for current buffer. 6318 */ 6319 void 6320 ex_comclear(exarg_T *eap UNUSED) 6321 { 6322 uc_clear(&ucmds); 6323 uc_clear(&curbuf->b_ucmds); 6324 } 6325 6326 /* 6327 * Clear all user commands for "gap". 6328 */ 6329 void 6330 uc_clear(garray_T *gap) 6331 { 6332 int i; 6333 ucmd_T *cmd; 6334 6335 for (i = 0; i < gap->ga_len; ++i) 6336 { 6337 cmd = USER_CMD_GA(gap, i); 6338 vim_free(cmd->uc_name); 6339 vim_free(cmd->uc_rep); 6340 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 6341 vim_free(cmd->uc_compl_arg); 6342 # endif 6343 } 6344 ga_clear(gap); 6345 } 6346 6347 static void 6348 ex_delcommand(exarg_T *eap) 6349 { 6350 int i = 0; 6351 ucmd_T *cmd = NULL; 6352 int cmp = -1; 6353 garray_T *gap; 6354 6355 gap = &curbuf->b_ucmds; 6356 for (;;) 6357 { 6358 for (i = 0; i < gap->ga_len; ++i) 6359 { 6360 cmd = USER_CMD_GA(gap, i); 6361 cmp = STRCMP(eap->arg, cmd->uc_name); 6362 if (cmp <= 0) 6363 break; 6364 } 6365 if (gap == &ucmds || cmp == 0) 6366 break; 6367 gap = &ucmds; 6368 } 6369 6370 if (cmp != 0) 6371 { 6372 EMSG2(_("E184: No such user-defined command: %s"), eap->arg); 6373 return; 6374 } 6375 6376 vim_free(cmd->uc_name); 6377 vim_free(cmd->uc_rep); 6378 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 6379 vim_free(cmd->uc_compl_arg); 6380 # endif 6381 6382 --gap->ga_len; 6383 6384 if (i < gap->ga_len) 6385 mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T)); 6386 } 6387 6388 /* 6389 * split and quote args for <f-args> 6390 */ 6391 static char_u * 6392 uc_split_args(char_u *arg, size_t *lenp) 6393 { 6394 char_u *buf; 6395 char_u *p; 6396 char_u *q; 6397 int len; 6398 6399 /* Precalculate length */ 6400 p = arg; 6401 len = 2; /* Initial and final quotes */ 6402 6403 while (*p) 6404 { 6405 if (p[0] == '\\' && p[1] == '\\') 6406 { 6407 len += 2; 6408 p += 2; 6409 } 6410 else if (p[0] == '\\' && VIM_ISWHITE(p[1])) 6411 { 6412 len += 1; 6413 p += 2; 6414 } 6415 else if (*p == '\\' || *p == '"') 6416 { 6417 len += 2; 6418 p += 1; 6419 } 6420 else if (VIM_ISWHITE(*p)) 6421 { 6422 p = skipwhite(p); 6423 if (*p == NUL) 6424 break; 6425 len += 3; /* "," */ 6426 } 6427 else 6428 { 6429 #ifdef FEAT_MBYTE 6430 int charlen = (*mb_ptr2len)(p); 6431 len += charlen; 6432 p += charlen; 6433 #else 6434 ++len; 6435 ++p; 6436 #endif 6437 } 6438 } 6439 6440 buf = alloc(len + 1); 6441 if (buf == NULL) 6442 { 6443 *lenp = 0; 6444 return buf; 6445 } 6446 6447 p = arg; 6448 q = buf; 6449 *q++ = '"'; 6450 while (*p) 6451 { 6452 if (p[0] == '\\' && p[1] == '\\') 6453 { 6454 *q++ = '\\'; 6455 *q++ = '\\'; 6456 p += 2; 6457 } 6458 else if (p[0] == '\\' && VIM_ISWHITE(p[1])) 6459 { 6460 *q++ = p[1]; 6461 p += 2; 6462 } 6463 else if (*p == '\\' || *p == '"') 6464 { 6465 *q++ = '\\'; 6466 *q++ = *p++; 6467 } 6468 else if (VIM_ISWHITE(*p)) 6469 { 6470 p = skipwhite(p); 6471 if (*p == NUL) 6472 break; 6473 *q++ = '"'; 6474 *q++ = ','; 6475 *q++ = '"'; 6476 } 6477 else 6478 { 6479 MB_COPY_CHAR(p, q); 6480 } 6481 } 6482 *q++ = '"'; 6483 *q = 0; 6484 6485 *lenp = len; 6486 return buf; 6487 } 6488 6489 static size_t 6490 add_cmd_modifier(char_u *buf, char *mod_str, int *multi_mods) 6491 { 6492 size_t result; 6493 6494 result = STRLEN(mod_str); 6495 if (*multi_mods) 6496 result += 1; 6497 if (buf != NULL) 6498 { 6499 if (*multi_mods) 6500 STRCAT(buf, " "); 6501 STRCAT(buf, mod_str); 6502 } 6503 6504 *multi_mods = 1; 6505 6506 return result; 6507 } 6508 6509 /* 6510 * Check for a <> code in a user command. 6511 * "code" points to the '<'. "len" the length of the <> (inclusive). 6512 * "buf" is where the result is to be added. 6513 * "split_buf" points to a buffer used for splitting, caller should free it. 6514 * "split_len" is the length of what "split_buf" contains. 6515 * Returns the length of the replacement, which has been added to "buf". 6516 * Returns -1 if there was no match, and only the "<" has been copied. 6517 */ 6518 static size_t 6519 uc_check_code( 6520 char_u *code, 6521 size_t len, 6522 char_u *buf, 6523 ucmd_T *cmd, /* the user command we're expanding */ 6524 exarg_T *eap, /* ex arguments */ 6525 char_u **split_buf, 6526 size_t *split_len) 6527 { 6528 size_t result = 0; 6529 char_u *p = code + 1; 6530 size_t l = len - 2; 6531 int quote = 0; 6532 enum { 6533 ct_ARGS, 6534 ct_BANG, 6535 ct_COUNT, 6536 ct_LINE1, 6537 ct_LINE2, 6538 ct_RANGE, 6539 ct_MODS, 6540 ct_REGISTER, 6541 ct_LT, 6542 ct_NONE 6543 } type = ct_NONE; 6544 6545 if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-') 6546 { 6547 quote = (*p == 'q' || *p == 'Q') ? 1 : 2; 6548 p += 2; 6549 l -= 2; 6550 } 6551 6552 ++l; 6553 if (l <= 1) 6554 type = ct_NONE; 6555 else if (STRNICMP(p, "args>", l) == 0) 6556 type = ct_ARGS; 6557 else if (STRNICMP(p, "bang>", l) == 0) 6558 type = ct_BANG; 6559 else if (STRNICMP(p, "count>", l) == 0) 6560 type = ct_COUNT; 6561 else if (STRNICMP(p, "line1>", l) == 0) 6562 type = ct_LINE1; 6563 else if (STRNICMP(p, "line2>", l) == 0) 6564 type = ct_LINE2; 6565 else if (STRNICMP(p, "range>", l) == 0) 6566 type = ct_RANGE; 6567 else if (STRNICMP(p, "lt>", l) == 0) 6568 type = ct_LT; 6569 else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0) 6570 type = ct_REGISTER; 6571 else if (STRNICMP(p, "mods>", l) == 0) 6572 type = ct_MODS; 6573 6574 switch (type) 6575 { 6576 case ct_ARGS: 6577 /* Simple case first */ 6578 if (*eap->arg == NUL) 6579 { 6580 if (quote == 1) 6581 { 6582 result = 2; 6583 if (buf != NULL) 6584 STRCPY(buf, "''"); 6585 } 6586 else 6587 result = 0; 6588 break; 6589 } 6590 6591 /* When specified there is a single argument don't split it. 6592 * Works for ":Cmd %" when % is "a b c". */ 6593 if ((eap->argt & NOSPC) && quote == 2) 6594 quote = 1; 6595 6596 switch (quote) 6597 { 6598 case 0: /* No quoting, no splitting */ 6599 result = STRLEN(eap->arg); 6600 if (buf != NULL) 6601 STRCPY(buf, eap->arg); 6602 break; 6603 case 1: /* Quote, but don't split */ 6604 result = STRLEN(eap->arg) + 2; 6605 for (p = eap->arg; *p; ++p) 6606 { 6607 #ifdef FEAT_MBYTE 6608 if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2) 6609 /* DBCS can contain \ in a trail byte, skip the 6610 * double-byte character. */ 6611 ++p; 6612 else 6613 #endif 6614 if (*p == '\\' || *p == '"') 6615 ++result; 6616 } 6617 6618 if (buf != NULL) 6619 { 6620 *buf++ = '"'; 6621 for (p = eap->arg; *p; ++p) 6622 { 6623 #ifdef FEAT_MBYTE 6624 if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2) 6625 /* DBCS can contain \ in a trail byte, copy the 6626 * double-byte character to avoid escaping. */ 6627 *buf++ = *p++; 6628 else 6629 #endif 6630 if (*p == '\\' || *p == '"') 6631 *buf++ = '\\'; 6632 *buf++ = *p; 6633 } 6634 *buf = '"'; 6635 } 6636 6637 break; 6638 case 2: /* Quote and split (<f-args>) */ 6639 /* This is hard, so only do it once, and cache the result */ 6640 if (*split_buf == NULL) 6641 *split_buf = uc_split_args(eap->arg, split_len); 6642 6643 result = *split_len; 6644 if (buf != NULL && result != 0) 6645 STRCPY(buf, *split_buf); 6646 6647 break; 6648 } 6649 break; 6650 6651 case ct_BANG: 6652 result = eap->forceit ? 1 : 0; 6653 if (quote) 6654 result += 2; 6655 if (buf != NULL) 6656 { 6657 if (quote) 6658 *buf++ = '"'; 6659 if (eap->forceit) 6660 *buf++ = '!'; 6661 if (quote) 6662 *buf = '"'; 6663 } 6664 break; 6665 6666 case ct_LINE1: 6667 case ct_LINE2: 6668 case ct_RANGE: 6669 case ct_COUNT: 6670 { 6671 char num_buf[20]; 6672 long num = (type == ct_LINE1) ? eap->line1 : 6673 (type == ct_LINE2) ? eap->line2 : 6674 (type == ct_RANGE) ? eap->addr_count : 6675 (eap->addr_count > 0) ? eap->line2 : cmd->uc_def; 6676 size_t num_len; 6677 6678 sprintf(num_buf, "%ld", num); 6679 num_len = STRLEN(num_buf); 6680 result = num_len; 6681 6682 if (quote) 6683 result += 2; 6684 6685 if (buf != NULL) 6686 { 6687 if (quote) 6688 *buf++ = '"'; 6689 STRCPY(buf, num_buf); 6690 buf += num_len; 6691 if (quote) 6692 *buf = '"'; 6693 } 6694 6695 break; 6696 } 6697 6698 case ct_MODS: 6699 { 6700 int multi_mods = 0; 6701 typedef struct { 6702 int *varp; 6703 char *name; 6704 } mod_entry_T; 6705 static mod_entry_T mod_entries[] = { 6706 #ifdef FEAT_BROWSE_CMD 6707 {&cmdmod.browse, "browse"}, 6708 #endif 6709 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 6710 {&cmdmod.confirm, "confirm"}, 6711 #endif 6712 {&cmdmod.hide, "hide"}, 6713 {&cmdmod.keepalt, "keepalt"}, 6714 {&cmdmod.keepjumps, "keepjumps"}, 6715 {&cmdmod.keepmarks, "keepmarks"}, 6716 {&cmdmod.keeppatterns, "keeppatterns"}, 6717 {&cmdmod.lockmarks, "lockmarks"}, 6718 {&cmdmod.noswapfile, "noswapfile"}, 6719 {NULL, NULL} 6720 }; 6721 int i; 6722 6723 result = quote ? 2 : 0; 6724 if (buf != NULL) 6725 { 6726 if (quote) 6727 *buf++ = '"'; 6728 *buf = '\0'; 6729 } 6730 6731 /* :aboveleft and :leftabove */ 6732 if (cmdmod.split & WSP_ABOVE) 6733 result += add_cmd_modifier(buf, "aboveleft", &multi_mods); 6734 /* :belowright and :rightbelow */ 6735 if (cmdmod.split & WSP_BELOW) 6736 result += add_cmd_modifier(buf, "belowright", &multi_mods); 6737 /* :botright */ 6738 if (cmdmod.split & WSP_BOT) 6739 result += add_cmd_modifier(buf, "botright", &multi_mods); 6740 6741 /* the modifiers that are simple flags */ 6742 for (i = 0; mod_entries[i].varp != NULL; ++i) 6743 if (*mod_entries[i].varp) 6744 result += add_cmd_modifier(buf, mod_entries[i].name, 6745 &multi_mods); 6746 6747 /* TODO: How to support :noautocmd? */ 6748 #ifdef HAVE_SANDBOX 6749 /* TODO: How to support :sandbox?*/ 6750 #endif 6751 /* :silent */ 6752 if (msg_silent > 0) 6753 result += add_cmd_modifier(buf, 6754 emsg_silent > 0 ? "silent!" : "silent", &multi_mods); 6755 /* :tab */ 6756 if (cmdmod.tab > 0) 6757 result += add_cmd_modifier(buf, "tab", &multi_mods); 6758 /* :topleft */ 6759 if (cmdmod.split & WSP_TOP) 6760 result += add_cmd_modifier(buf, "topleft", &multi_mods); 6761 /* TODO: How to support :unsilent?*/ 6762 /* :verbose */ 6763 if (p_verbose > 0) 6764 result += add_cmd_modifier(buf, "verbose", &multi_mods); 6765 /* :vertical */ 6766 if (cmdmod.split & WSP_VERT) 6767 result += add_cmd_modifier(buf, "vertical", &multi_mods); 6768 if (quote && buf != NULL) 6769 { 6770 buf += result - 2; 6771 *buf = '"'; 6772 } 6773 break; 6774 } 6775 6776 case ct_REGISTER: 6777 result = eap->regname ? 1 : 0; 6778 if (quote) 6779 result += 2; 6780 if (buf != NULL) 6781 { 6782 if (quote) 6783 *buf++ = '\''; 6784 if (eap->regname) 6785 *buf++ = eap->regname; 6786 if (quote) 6787 *buf = '\''; 6788 } 6789 break; 6790 6791 case ct_LT: 6792 result = 1; 6793 if (buf != NULL) 6794 *buf = '<'; 6795 break; 6796 6797 default: 6798 /* Not recognized: just copy the '<' and return -1. */ 6799 result = (size_t)-1; 6800 if (buf != NULL) 6801 *buf = '<'; 6802 break; 6803 } 6804 6805 return result; 6806 } 6807 6808 static void 6809 do_ucmd(exarg_T *eap) 6810 { 6811 char_u *buf; 6812 char_u *p; 6813 char_u *q; 6814 6815 char_u *start; 6816 char_u *end = NULL; 6817 char_u *ksp; 6818 size_t len, totlen; 6819 6820 size_t split_len = 0; 6821 char_u *split_buf = NULL; 6822 ucmd_T *cmd; 6823 #ifdef FEAT_EVAL 6824 scid_T save_current_SID = current_SID; 6825 #endif 6826 6827 if (eap->cmdidx == CMD_USER) 6828 cmd = USER_CMD(eap->useridx); 6829 else 6830 cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx); 6831 6832 /* 6833 * Replace <> in the command by the arguments. 6834 * First round: "buf" is NULL, compute length, allocate "buf". 6835 * Second round: copy result into "buf". 6836 */ 6837 buf = NULL; 6838 for (;;) 6839 { 6840 p = cmd->uc_rep; /* source */ 6841 q = buf; /* destination */ 6842 totlen = 0; 6843 6844 for (;;) 6845 { 6846 start = vim_strchr(p, '<'); 6847 if (start != NULL) 6848 end = vim_strchr(start + 1, '>'); 6849 if (buf != NULL) 6850 { 6851 for (ksp = p; *ksp != NUL && *ksp != K_SPECIAL; ++ksp) 6852 ; 6853 if (*ksp == K_SPECIAL 6854 && (start == NULL || ksp < start || end == NULL) 6855 && ((ksp[1] == KS_SPECIAL && ksp[2] == KE_FILLER) 6856 # ifdef FEAT_GUI 6857 || (ksp[1] == KS_EXTRA && ksp[2] == (int)KE_CSI) 6858 # endif 6859 )) 6860 { 6861 /* K_SPECIAL has been put in the buffer as K_SPECIAL 6862 * KS_SPECIAL KE_FILLER, like for mappings, but 6863 * do_cmdline() doesn't handle that, so convert it back. 6864 * Also change K_SPECIAL KS_EXTRA KE_CSI into CSI. */ 6865 len = ksp - p; 6866 if (len > 0) 6867 { 6868 mch_memmove(q, p, len); 6869 q += len; 6870 } 6871 *q++ = ksp[1] == KS_SPECIAL ? K_SPECIAL : CSI; 6872 p = ksp + 3; 6873 continue; 6874 } 6875 } 6876 6877 /* break if there no <item> is found */ 6878 if (start == NULL || end == NULL) 6879 break; 6880 6881 /* Include the '>' */ 6882 ++end; 6883 6884 /* Take everything up to the '<' */ 6885 len = start - p; 6886 if (buf == NULL) 6887 totlen += len; 6888 else 6889 { 6890 mch_memmove(q, p, len); 6891 q += len; 6892 } 6893 6894 len = uc_check_code(start, end - start, q, cmd, eap, 6895 &split_buf, &split_len); 6896 if (len == (size_t)-1) 6897 { 6898 /* no match, continue after '<' */ 6899 p = start + 1; 6900 len = 1; 6901 } 6902 else 6903 p = end; 6904 if (buf == NULL) 6905 totlen += len; 6906 else 6907 q += len; 6908 } 6909 if (buf != NULL) /* second time here, finished */ 6910 { 6911 STRCPY(q, p); 6912 break; 6913 } 6914 6915 totlen += STRLEN(p); /* Add on the trailing characters */ 6916 buf = alloc((unsigned)(totlen + 1)); 6917 if (buf == NULL) 6918 { 6919 vim_free(split_buf); 6920 return; 6921 } 6922 } 6923 6924 #ifdef FEAT_EVAL 6925 current_SID = cmd->uc_scriptID; 6926 #endif 6927 (void)do_cmdline(buf, eap->getline, eap->cookie, 6928 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED); 6929 #ifdef FEAT_EVAL 6930 current_SID = save_current_SID; 6931 #endif 6932 vim_free(buf); 6933 vim_free(split_buf); 6934 } 6935 6936 # if defined(FEAT_CMDL_COMPL) || defined(PROTO) 6937 static char_u * 6938 get_user_command_name(int idx) 6939 { 6940 return get_user_commands(NULL, idx - (int)CMD_SIZE); 6941 } 6942 6943 /* 6944 * Function given to ExpandGeneric() to obtain the list of user command names. 6945 */ 6946 char_u * 6947 get_user_commands(expand_T *xp UNUSED, int idx) 6948 { 6949 if (idx < curbuf->b_ucmds.ga_len) 6950 return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name; 6951 idx -= curbuf->b_ucmds.ga_len; 6952 if (idx < ucmds.ga_len) 6953 return USER_CMD(idx)->uc_name; 6954 return NULL; 6955 } 6956 6957 /* 6958 * Function given to ExpandGeneric() to obtain the list of user address type names. 6959 */ 6960 char_u * 6961 get_user_cmd_addr_type(expand_T *xp UNUSED, int idx) 6962 { 6963 return (char_u *)addr_type_complete[idx].name; 6964 } 6965 6966 /* 6967 * Function given to ExpandGeneric() to obtain the list of user command 6968 * attributes. 6969 */ 6970 char_u * 6971 get_user_cmd_flags(expand_T *xp UNUSED, int idx) 6972 { 6973 static char *user_cmd_flags[] = 6974 {"addr", "bang", "bar", "buffer", "complete", 6975 "count", "nargs", "range", "register"}; 6976 6977 if (idx >= (int)(sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0]))) 6978 return NULL; 6979 return (char_u *)user_cmd_flags[idx]; 6980 } 6981 6982 /* 6983 * Function given to ExpandGeneric() to obtain the list of values for -nargs. 6984 */ 6985 char_u * 6986 get_user_cmd_nargs(expand_T *xp UNUSED, int idx) 6987 { 6988 static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"}; 6989 6990 if (idx >= (int)(sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0]))) 6991 return NULL; 6992 return (char_u *)user_cmd_nargs[idx]; 6993 } 6994 6995 /* 6996 * Function given to ExpandGeneric() to obtain the list of values for -complete. 6997 */ 6998 char_u * 6999 get_user_cmd_complete(expand_T *xp UNUSED, int idx) 7000 { 7001 return (char_u *)command_complete[idx].name; 7002 } 7003 # endif /* FEAT_CMDL_COMPL */ 7004 7005 /* 7006 * Parse address type argument 7007 */ 7008 int 7009 parse_addr_type_arg( 7010 char_u *value, 7011 int vallen, 7012 long *argt, 7013 int *addr_type_arg) 7014 { 7015 int i, a, b; 7016 7017 for (i = 0; addr_type_complete[i].expand != -1; ++i) 7018 { 7019 a = (int)STRLEN(addr_type_complete[i].name) == vallen; 7020 b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0; 7021 if (a && b) 7022 { 7023 *addr_type_arg = addr_type_complete[i].expand; 7024 break; 7025 } 7026 } 7027 7028 if (addr_type_complete[i].expand == -1) 7029 { 7030 char_u *err = value; 7031 7032 for (i = 0; err[i] != NUL && !VIM_ISWHITE(err[i]); i++) 7033 ; 7034 err[i] = NUL; 7035 EMSG2(_("E180: Invalid address type value: %s"), err); 7036 return FAIL; 7037 } 7038 7039 if (*addr_type_arg != ADDR_LINES) 7040 *argt |= NOTADR; 7041 7042 return OK; 7043 } 7044 7045 #endif /* FEAT_USR_CMDS */ 7046 7047 #if defined(FEAT_USR_CMDS) || defined(FEAT_EVAL) || defined(PROTO) 7048 /* 7049 * Parse a completion argument "value[vallen]". 7050 * The detected completion goes in "*complp", argument type in "*argt". 7051 * When there is an argument, for function and user defined completion, it's 7052 * copied to allocated memory and stored in "*compl_arg". 7053 * Returns FAIL if something is wrong. 7054 */ 7055 int 7056 parse_compl_arg( 7057 char_u *value, 7058 int vallen, 7059 int *complp, 7060 long *argt, 7061 char_u **compl_arg UNUSED) 7062 { 7063 char_u *arg = NULL; 7064 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 7065 size_t arglen = 0; 7066 # endif 7067 int i; 7068 int valend = vallen; 7069 7070 /* Look for any argument part - which is the part after any ',' */ 7071 for (i = 0; i < vallen; ++i) 7072 { 7073 if (value[i] == ',') 7074 { 7075 arg = &value[i + 1]; 7076 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 7077 arglen = vallen - i - 1; 7078 # endif 7079 valend = i; 7080 break; 7081 } 7082 } 7083 7084 for (i = 0; command_complete[i].expand != 0; ++i) 7085 { 7086 if ((int)STRLEN(command_complete[i].name) == valend 7087 && STRNCMP(value, command_complete[i].name, valend) == 0) 7088 { 7089 *complp = command_complete[i].expand; 7090 if (command_complete[i].expand == EXPAND_BUFFERS) 7091 *argt |= BUFNAME; 7092 else if (command_complete[i].expand == EXPAND_DIRECTORIES 7093 || command_complete[i].expand == EXPAND_FILES) 7094 *argt |= XFILE; 7095 break; 7096 } 7097 } 7098 7099 if (command_complete[i].expand == 0) 7100 { 7101 EMSG2(_("E180: Invalid complete value: %s"), value); 7102 return FAIL; 7103 } 7104 7105 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 7106 if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST 7107 && arg != NULL) 7108 # else 7109 if (arg != NULL) 7110 # endif 7111 { 7112 EMSG(_("E468: Completion argument only allowed for custom completion")); 7113 return FAIL; 7114 } 7115 7116 # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL) 7117 if ((*complp == EXPAND_USER_DEFINED || *complp == EXPAND_USER_LIST) 7118 && arg == NULL) 7119 { 7120 EMSG(_("E467: Custom completion requires a function argument")); 7121 return FAIL; 7122 } 7123 7124 if (arg != NULL) 7125 *compl_arg = vim_strnsave(arg, (int)arglen); 7126 # endif 7127 return OK; 7128 } 7129 7130 int 7131 cmdcomplete_str_to_type(char_u *complete_str) 7132 { 7133 int i; 7134 7135 for (i = 0; command_complete[i].expand != 0; ++i) 7136 if (STRCMP(complete_str, command_complete[i].name) == 0) 7137 return command_complete[i].expand; 7138 7139 return EXPAND_NOTHING; 7140 } 7141 #endif 7142 7143 static void 7144 ex_colorscheme(exarg_T *eap) 7145 { 7146 if (*eap->arg == NUL) 7147 { 7148 #ifdef FEAT_EVAL 7149 char_u *expr = vim_strsave((char_u *)"g:colors_name"); 7150 char_u *p = NULL; 7151 7152 if (expr != NULL) 7153 { 7154 ++emsg_off; 7155 p = eval_to_string(expr, NULL, FALSE); 7156 --emsg_off; 7157 vim_free(expr); 7158 } 7159 if (p != NULL) 7160 { 7161 MSG(p); 7162 vim_free(p); 7163 } 7164 else 7165 MSG("default"); 7166 #else 7167 MSG(_("unknown")); 7168 #endif 7169 } 7170 else if (load_colors(eap->arg) == FAIL) 7171 EMSG2(_("E185: Cannot find color scheme '%s'"), eap->arg); 7172 } 7173 7174 static void 7175 ex_highlight(exarg_T *eap) 7176 { 7177 if (*eap->arg == NUL && eap->cmd[2] == '!') 7178 MSG(_("Greetings, Vim user!")); 7179 do_highlight(eap->arg, eap->forceit, FALSE); 7180 } 7181 7182 7183 /* 7184 * Call this function if we thought we were going to exit, but we won't 7185 * (because of an error). May need to restore the terminal mode. 7186 */ 7187 void 7188 not_exiting(void) 7189 { 7190 exiting = FALSE; 7191 settmode(TMODE_RAW); 7192 } 7193 7194 /* 7195 * ":quit": quit current window, quit Vim if the last window is closed. 7196 */ 7197 static void 7198 ex_quit(exarg_T *eap) 7199 { 7200 win_T *wp; 7201 7202 #ifdef FEAT_CMDWIN 7203 if (cmdwin_type != 0) 7204 { 7205 cmdwin_result = Ctrl_C; 7206 return; 7207 } 7208 #endif 7209 /* Don't quit while editing the command line. */ 7210 if (text_locked()) 7211 { 7212 text_locked_msg(); 7213 return; 7214 } 7215 if (eap->addr_count > 0) 7216 { 7217 int wnr = eap->line2; 7218 7219 for (wp = firstwin; wp->w_next != NULL; wp = wp->w_next) 7220 if (--wnr <= 0) 7221 break; 7222 } 7223 else 7224 wp = curwin; 7225 7226 #ifdef FEAT_AUTOCMD 7227 /* Refuse to quit when locked. */ 7228 if (curbuf_locked()) 7229 return; 7230 apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, wp->w_buffer); 7231 /* Bail out when autocommands closed the window. 7232 * Refuse to quit when the buffer in the last window is being closed (can 7233 * only happen in autocommands). */ 7234 if (!win_valid(wp) 7235 || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0)) 7236 return; 7237 #endif 7238 7239 #ifdef FEAT_NETBEANS_INTG 7240 netbeansForcedQuit = eap->forceit; 7241 #endif 7242 7243 /* 7244 * If there are more files or windows we won't exit. 7245 */ 7246 if (check_more(FALSE, eap->forceit) == OK && only_one_window()) 7247 exiting = TRUE; 7248 if ((!buf_hide(wp->w_buffer) 7249 && check_changed(wp->w_buffer, (p_awa ? CCGD_AW : 0) 7250 | (eap->forceit ? CCGD_FORCEIT : 0) 7251 | CCGD_EXCMD)) 7252 || check_more(TRUE, eap->forceit) == FAIL 7253 || (only_one_window() && check_changed_any(eap->forceit, TRUE))) 7254 { 7255 not_exiting(); 7256 } 7257 else 7258 { 7259 /* quit last window 7260 * Note: only_one_window() returns true, even so a help window is 7261 * still open. In that case only quit, if no address has been 7262 * specified. Example: 7263 * :h|wincmd w|1q - don't quit 7264 * :h|wincmd w|q - quit 7265 */ 7266 if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) 7267 getout(0); 7268 not_exiting(); 7269 #ifdef FEAT_GUI 7270 need_mouse_correct = TRUE; 7271 #endif 7272 /* close window; may free buffer */ 7273 win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit); 7274 } 7275 } 7276 7277 /* 7278 * ":cquit". 7279 */ 7280 static void 7281 ex_cquit(exarg_T *eap UNUSED) 7282 { 7283 getout(1); /* this does not always pass on the exit code to the Manx 7284 compiler. why? */ 7285 } 7286 7287 /* 7288 * ":qall": try to quit all windows 7289 */ 7290 static void 7291 ex_quit_all(exarg_T *eap) 7292 { 7293 # ifdef FEAT_CMDWIN 7294 if (cmdwin_type != 0) 7295 { 7296 if (eap->forceit) 7297 cmdwin_result = K_XF1; /* ex_window() takes care of this */ 7298 else 7299 cmdwin_result = K_XF2; 7300 return; 7301 } 7302 # endif 7303 7304 /* Don't quit while editing the command line. */ 7305 if (text_locked()) 7306 { 7307 text_locked_msg(); 7308 return; 7309 } 7310 #ifdef FEAT_AUTOCMD 7311 apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); 7312 /* Refuse to quit when locked or when the buffer in the last window is 7313 * being closed (can only happen in autocommands). */ 7314 if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) 7315 return; 7316 #endif 7317 7318 exiting = TRUE; 7319 if (eap->forceit || !check_changed_any(FALSE, FALSE)) 7320 getout(0); 7321 not_exiting(); 7322 } 7323 7324 /* 7325 * ":close": close current window, unless it is the last one 7326 */ 7327 static void 7328 ex_close(exarg_T *eap) 7329 { 7330 win_T *win; 7331 int winnr = 0; 7332 #ifdef FEAT_CMDWIN 7333 if (cmdwin_type != 0) 7334 cmdwin_result = Ctrl_C; 7335 else 7336 #endif 7337 if (!text_locked() 7338 #ifdef FEAT_AUTOCMD 7339 && !curbuf_locked() 7340 #endif 7341 ) 7342 { 7343 if (eap->addr_count == 0) 7344 ex_win_close(eap->forceit, curwin, NULL); 7345 else { 7346 FOR_ALL_WINDOWS(win) 7347 { 7348 winnr++; 7349 if (winnr == eap->line2) 7350 break; 7351 } 7352 if (win == NULL) 7353 win = lastwin; 7354 ex_win_close(eap->forceit, win, NULL); 7355 } 7356 } 7357 } 7358 7359 #ifdef FEAT_QUICKFIX 7360 /* 7361 * ":pclose": Close any preview window. 7362 */ 7363 static void 7364 ex_pclose(exarg_T *eap) 7365 { 7366 win_T *win; 7367 7368 FOR_ALL_WINDOWS(win) 7369 if (win->w_p_pvw) 7370 { 7371 ex_win_close(eap->forceit, win, NULL); 7372 break; 7373 } 7374 } 7375 #endif 7376 7377 /* 7378 * Close window "win" and take care of handling closing the last window for a 7379 * modified buffer. 7380 */ 7381 static void 7382 ex_win_close( 7383 int forceit, 7384 win_T *win, 7385 tabpage_T *tp) /* NULL or the tab page "win" is in */ 7386 { 7387 int need_hide; 7388 buf_T *buf = win->w_buffer; 7389 7390 need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); 7391 if (need_hide && !buf_hide(buf) && !forceit) 7392 { 7393 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 7394 if ((p_confirm || cmdmod.confirm) && p_write) 7395 { 7396 bufref_T bufref; 7397 7398 set_bufref(&bufref, buf); 7399 dialog_changed(buf, FALSE); 7400 if (bufref_valid(&bufref) && bufIsChanged(buf)) 7401 return; 7402 need_hide = FALSE; 7403 } 7404 else 7405 #endif 7406 { 7407 no_write_message(); 7408 return; 7409 } 7410 } 7411 7412 #ifdef FEAT_GUI 7413 need_mouse_correct = TRUE; 7414 #endif 7415 7416 /* free buffer when not hiding it or when it's a scratch buffer */ 7417 if (tp == NULL) 7418 win_close(win, !need_hide && !buf_hide(buf)); 7419 else 7420 win_close_othertab(win, !need_hide && !buf_hide(buf), tp); 7421 } 7422 7423 /* 7424 * Handle the argument for a tabpage related ex command. 7425 * Returns a tabpage number. 7426 * When an error is encountered then eap->errmsg is set. 7427 */ 7428 static int 7429 get_tabpage_arg(exarg_T *eap) 7430 { 7431 int tab_number; 7432 int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1; 7433 7434 if (eap->arg && *eap->arg != NUL) 7435 { 7436 char_u *p = eap->arg; 7437 char_u *p_save; 7438 int relative = 0; /* argument +N/-N means: go to N places to the 7439 * right/left relative to the current position. */ 7440 7441 if (*p == '-') 7442 { 7443 relative = -1; 7444 p++; 7445 } 7446 else if (*p == '+') 7447 { 7448 relative = 1; 7449 p++; 7450 } 7451 7452 p_save = p; 7453 tab_number = getdigits(&p); 7454 7455 if (relative == 0) 7456 { 7457 if (STRCMP(p, "$") == 0) 7458 tab_number = LAST_TAB_NR; 7459 else if (p == p_save || *p_save == '-' || *p != NUL 7460 || tab_number > LAST_TAB_NR) 7461 { 7462 /* No numbers as argument. */ 7463 eap->errmsg = e_invarg; 7464 goto theend; 7465 } 7466 } 7467 else 7468 { 7469 if (*p_save == NUL) 7470 tab_number = 1; 7471 else if (p == p_save || *p_save == '-' || *p != NUL 7472 || tab_number == 0) 7473 { 7474 /* No numbers as argument. */ 7475 eap->errmsg = e_invarg; 7476 goto theend; 7477 } 7478 tab_number = tab_number * relative + tabpage_index(curtab); 7479 if (!unaccept_arg0 && relative == -1) 7480 --tab_number; 7481 } 7482 if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR) 7483 eap->errmsg = e_invarg; 7484 } 7485 else if (eap->addr_count > 0) 7486 { 7487 if (unaccept_arg0 && eap->line2 == 0) 7488 { 7489 eap->errmsg = e_invrange; 7490 tab_number = 0; 7491 } 7492 else 7493 { 7494 tab_number = eap->line2; 7495 if (!unaccept_arg0 && **eap->cmdlinep == '-') 7496 { 7497 --tab_number; 7498 if (tab_number < unaccept_arg0) 7499 eap->errmsg = e_invarg; 7500 } 7501 } 7502 } 7503 else 7504 { 7505 switch (eap->cmdidx) 7506 { 7507 case CMD_tabnext: 7508 tab_number = tabpage_index(curtab) + 1; 7509 if (tab_number > LAST_TAB_NR) 7510 tab_number = 1; 7511 break; 7512 case CMD_tabmove: 7513 tab_number = LAST_TAB_NR; 7514 break; 7515 default: 7516 tab_number = tabpage_index(curtab); 7517 } 7518 } 7519 7520 theend: 7521 return tab_number; 7522 } 7523 7524 /* 7525 * ":tabclose": close current tab page, unless it is the last one. 7526 * ":tabclose N": close tab page N. 7527 */ 7528 static void 7529 ex_tabclose(exarg_T *eap) 7530 { 7531 tabpage_T *tp; 7532 int tab_number; 7533 7534 # ifdef FEAT_CMDWIN 7535 if (cmdwin_type != 0) 7536 cmdwin_result = K_IGNORE; 7537 else 7538 # endif 7539 if (first_tabpage->tp_next == NULL) 7540 EMSG(_("E784: Cannot close last tab page")); 7541 else 7542 { 7543 tab_number = get_tabpage_arg(eap); 7544 if (eap->errmsg == NULL) 7545 { 7546 tp = find_tabpage(tab_number); 7547 if (tp == NULL) 7548 { 7549 beep_flush(); 7550 return; 7551 } 7552 if (tp != curtab) 7553 { 7554 tabpage_close_other(tp, eap->forceit); 7555 return; 7556 } 7557 else if (!text_locked() 7558 #ifdef FEAT_AUTOCMD 7559 && !curbuf_locked() 7560 #endif 7561 ) 7562 tabpage_close(eap->forceit); 7563 } 7564 } 7565 } 7566 7567 /* 7568 * ":tabonly": close all tab pages except the current one 7569 */ 7570 static void 7571 ex_tabonly(exarg_T *eap) 7572 { 7573 tabpage_T *tp; 7574 int done; 7575 int tab_number; 7576 7577 # ifdef FEAT_CMDWIN 7578 if (cmdwin_type != 0) 7579 cmdwin_result = K_IGNORE; 7580 else 7581 # endif 7582 if (first_tabpage->tp_next == NULL) 7583 MSG(_("Already only one tab page")); 7584 else 7585 { 7586 tab_number = get_tabpage_arg(eap); 7587 if (eap->errmsg == NULL) 7588 { 7589 goto_tabpage(tab_number); 7590 /* Repeat this up to a 1000 times, because autocommands may 7591 * mess up the lists. */ 7592 for (done = 0; done < 1000; ++done) 7593 { 7594 FOR_ALL_TABPAGES(tp) 7595 if (tp->tp_topframe != topframe) 7596 { 7597 tabpage_close_other(tp, eap->forceit); 7598 /* if we failed to close it quit */ 7599 if (valid_tabpage(tp)) 7600 done = 1000; 7601 /* start over, "tp" is now invalid */ 7602 break; 7603 } 7604 if (first_tabpage->tp_next == NULL) 7605 break; 7606 } 7607 } 7608 } 7609 } 7610 7611 /* 7612 * Close the current tab page. 7613 */ 7614 void 7615 tabpage_close(int forceit) 7616 { 7617 /* First close all the windows but the current one. If that worked then 7618 * close the last window in this tab, that will close it. */ 7619 if (!ONE_WINDOW) 7620 close_others(TRUE, forceit); 7621 if (ONE_WINDOW) 7622 ex_win_close(forceit, curwin, NULL); 7623 # ifdef FEAT_GUI 7624 need_mouse_correct = TRUE; 7625 # endif 7626 } 7627 7628 /* 7629 * Close tab page "tp", which is not the current tab page. 7630 * Note that autocommands may make "tp" invalid. 7631 * Also takes care of the tab pages line disappearing when closing the 7632 * last-but-one tab page. 7633 */ 7634 void 7635 tabpage_close_other(tabpage_T *tp, int forceit) 7636 { 7637 int done = 0; 7638 win_T *wp; 7639 int h = tabline_height(); 7640 7641 /* Limit to 1000 windows, autocommands may add a window while we close 7642 * one. OK, so I'm paranoid... */ 7643 while (++done < 1000) 7644 { 7645 wp = tp->tp_firstwin; 7646 ex_win_close(forceit, wp, tp); 7647 7648 /* Autocommands may delete the tab page under our fingers and we may 7649 * fail to close a window with a modified buffer. */ 7650 if (!valid_tabpage(tp) || tp->tp_firstwin == wp) 7651 break; 7652 } 7653 7654 #ifdef FEAT_AUTOCMD 7655 apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf); 7656 #endif 7657 7658 redraw_tabline = TRUE; 7659 if (h != tabline_height()) 7660 shell_new_rows(); 7661 } 7662 7663 /* 7664 * ":only". 7665 */ 7666 static void 7667 ex_only(exarg_T *eap) 7668 { 7669 win_T *wp; 7670 int wnr; 7671 # ifdef FEAT_GUI 7672 need_mouse_correct = TRUE; 7673 # endif 7674 if (eap->addr_count > 0) 7675 { 7676 wnr = eap->line2; 7677 for (wp = firstwin; --wnr > 0; ) 7678 { 7679 if (wp->w_next == NULL) 7680 break; 7681 else 7682 wp = wp->w_next; 7683 } 7684 win_goto(wp); 7685 } 7686 close_others(TRUE, eap->forceit); 7687 } 7688 7689 /* 7690 * ":all" and ":sall". 7691 * Also used for ":tab drop file ..." after setting the argument list. 7692 */ 7693 void 7694 ex_all(exarg_T *eap) 7695 { 7696 if (eap->addr_count == 0) 7697 eap->line2 = 9999; 7698 do_arg_all((int)eap->line2, eap->forceit, eap->cmdidx == CMD_drop); 7699 } 7700 7701 static void 7702 ex_hide(exarg_T *eap UNUSED) 7703 { 7704 /* ":hide" or ":hide | cmd": hide current window */ 7705 if (!eap->skip) 7706 { 7707 #ifdef FEAT_GUI 7708 need_mouse_correct = TRUE; 7709 #endif 7710 if (eap->addr_count == 0) 7711 win_close(curwin, FALSE); /* don't free buffer */ 7712 else 7713 { 7714 int winnr = 0; 7715 win_T *win; 7716 7717 FOR_ALL_WINDOWS(win) 7718 { 7719 winnr++; 7720 if (winnr == eap->line2) 7721 break; 7722 } 7723 if (win == NULL) 7724 win = lastwin; 7725 win_close(win, FALSE); 7726 } 7727 } 7728 } 7729 7730 /* 7731 * ":stop" and ":suspend": Suspend Vim. 7732 */ 7733 static void 7734 ex_stop(exarg_T *eap) 7735 { 7736 /* 7737 * Disallow suspending for "rvim". 7738 */ 7739 if (!check_restricted()) 7740 { 7741 if (!eap->forceit) 7742 autowrite_all(); 7743 windgoto((int)Rows - 1, 0); 7744 out_char('\n'); 7745 out_flush(); 7746 stoptermcap(); 7747 out_flush(); /* needed for SUN to restore xterm buffer */ 7748 #ifdef FEAT_TITLE 7749 mch_restore_title(3); /* restore window titles */ 7750 #endif 7751 ui_suspend(); /* call machine specific function */ 7752 #ifdef FEAT_TITLE 7753 maketitle(); 7754 resettitle(); /* force updating the title */ 7755 #endif 7756 starttermcap(); 7757 scroll_start(); /* scroll screen before redrawing */ 7758 redraw_later_clear(); 7759 shell_resized(); /* may have resized window */ 7760 } 7761 } 7762 7763 /* 7764 * ":exit", ":xit" and ":wq": Write file and exit Vim. 7765 */ 7766 static void 7767 ex_exit(exarg_T *eap) 7768 { 7769 #ifdef FEAT_CMDWIN 7770 if (cmdwin_type != 0) 7771 { 7772 cmdwin_result = Ctrl_C; 7773 return; 7774 } 7775 #endif 7776 /* Don't quit while editing the command line. */ 7777 if (text_locked()) 7778 { 7779 text_locked_msg(); 7780 return; 7781 } 7782 #ifdef FEAT_AUTOCMD 7783 apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); 7784 /* Refuse to quit when locked or when the buffer in the last window is 7785 * being closed (can only happen in autocommands). */ 7786 if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0)) 7787 return; 7788 #endif 7789 7790 /* 7791 * if more files or windows we won't exit 7792 */ 7793 if (check_more(FALSE, eap->forceit) == OK && only_one_window()) 7794 exiting = TRUE; 7795 if ( ((eap->cmdidx == CMD_wq 7796 || curbufIsChanged()) 7797 && do_write(eap) == FAIL) 7798 || check_more(TRUE, eap->forceit) == FAIL 7799 || (only_one_window() && check_changed_any(eap->forceit, FALSE))) 7800 { 7801 not_exiting(); 7802 } 7803 else 7804 { 7805 if (only_one_window()) /* quit last window, exit Vim */ 7806 getout(0); 7807 not_exiting(); 7808 # ifdef FEAT_GUI 7809 need_mouse_correct = TRUE; 7810 # endif 7811 /* Quit current window, may free the buffer. */ 7812 win_close(curwin, !buf_hide(curwin->w_buffer)); 7813 } 7814 } 7815 7816 /* 7817 * ":print", ":list", ":number". 7818 */ 7819 static void 7820 ex_print(exarg_T *eap) 7821 { 7822 if (curbuf->b_ml.ml_flags & ML_EMPTY) 7823 EMSG(_(e_emptybuf)); 7824 else 7825 { 7826 for ( ;!got_int; ui_breakcheck()) 7827 { 7828 print_line(eap->line1, 7829 (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound 7830 || (eap->flags & EXFLAG_NR)), 7831 eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST)); 7832 if (++eap->line1 > eap->line2) 7833 break; 7834 out_flush(); /* show one line at a time */ 7835 } 7836 setpcmark(); 7837 /* put cursor at last line */ 7838 curwin->w_cursor.lnum = eap->line2; 7839 beginline(BL_SOL | BL_FIX); 7840 } 7841 7842 ex_no_reprint = TRUE; 7843 } 7844 7845 #ifdef FEAT_BYTEOFF 7846 static void 7847 ex_goto(exarg_T *eap) 7848 { 7849 goto_byte(eap->line2); 7850 } 7851 #endif 7852 7853 /* 7854 * ":shell". 7855 */ 7856 static void 7857 ex_shell(exarg_T *eap UNUSED) 7858 { 7859 do_shell(NULL, 0); 7860 } 7861 7862 #if defined(HAVE_DROP_FILE) \ 7863 || (defined(FEAT_GUI_GTK) && defined(FEAT_DND)) \ 7864 || defined(FEAT_GUI_MSWIN) \ 7865 || defined(FEAT_GUI_MAC) \ 7866 || defined(PROTO) 7867 7868 /* 7869 * Handle a file drop. The code is here because a drop is *nearly* like an 7870 * :args command, but not quite (we have a list of exact filenames, so we 7871 * don't want to (a) parse a command line, or (b) expand wildcards. So the 7872 * code is very similar to :args and hence needs access to a lot of the static 7873 * functions in this file. 7874 * 7875 * The list should be allocated using alloc(), as should each item in the 7876 * list. This function takes over responsibility for freeing the list. 7877 * 7878 * XXX The list is made into the argument list. This is freed using 7879 * FreeWild(), which does a series of vim_free() calls. 7880 */ 7881 void 7882 handle_drop( 7883 int filec, /* the number of files dropped */ 7884 char_u **filev, /* the list of files dropped */ 7885 int split) /* force splitting the window */ 7886 { 7887 exarg_T ea; 7888 int save_msg_scroll = msg_scroll; 7889 7890 /* Postpone this while editing the command line. */ 7891 if (text_locked()) 7892 return; 7893 #ifdef FEAT_AUTOCMD 7894 if (curbuf_locked()) 7895 return; 7896 #endif 7897 /* When the screen is being updated we should not change buffers and 7898 * windows structures, it may cause freed memory to be used. */ 7899 if (updating_screen) 7900 return; 7901 7902 /* Check whether the current buffer is changed. If so, we will need 7903 * to split the current window or data could be lost. 7904 * We don't need to check if the 'hidden' option is set, as in this 7905 * case the buffer won't be lost. 7906 */ 7907 if (!buf_hide(curbuf) && !split) 7908 { 7909 ++emsg_off; 7910 split = check_changed(curbuf, CCGD_AW); 7911 --emsg_off; 7912 } 7913 if (split) 7914 { 7915 if (win_split(0, 0) == FAIL) 7916 return; 7917 RESET_BINDING(curwin); 7918 7919 /* When splitting the window, create a new alist. Otherwise the 7920 * existing one is overwritten. */ 7921 alist_unlink(curwin->w_alist); 7922 alist_new(); 7923 } 7924 7925 /* 7926 * Set up the new argument list. 7927 */ 7928 alist_set(ALIST(curwin), filec, filev, FALSE, NULL, 0); 7929 7930 /* 7931 * Move to the first file. 7932 */ 7933 /* Fake up a minimal "next" command for do_argfile() */ 7934 vim_memset(&ea, 0, sizeof(ea)); 7935 ea.cmd = (char_u *)"next"; 7936 do_argfile(&ea, 0); 7937 7938 /* do_ecmd() may set need_start_insertmode, but since we never left Insert 7939 * mode that is not needed here. */ 7940 need_start_insertmode = FALSE; 7941 7942 /* Restore msg_scroll, otherwise a following command may cause scrolling 7943 * unexpectedly. The screen will be redrawn by the caller, thus 7944 * msg_scroll being set by displaying a message is irrelevant. */ 7945 msg_scroll = save_msg_scroll; 7946 } 7947 #endif 7948 7949 /* 7950 * Clear an argument list: free all file names and reset it to zero entries. 7951 */ 7952 void 7953 alist_clear(alist_T *al) 7954 { 7955 while (--al->al_ga.ga_len >= 0) 7956 vim_free(AARGLIST(al)[al->al_ga.ga_len].ae_fname); 7957 ga_clear(&al->al_ga); 7958 } 7959 7960 /* 7961 * Init an argument list. 7962 */ 7963 void 7964 alist_init(alist_T *al) 7965 { 7966 ga_init2(&al->al_ga, (int)sizeof(aentry_T), 5); 7967 } 7968 7969 /* 7970 * Remove a reference from an argument list. 7971 * Ignored when the argument list is the global one. 7972 * If the argument list is no longer used by any window, free it. 7973 */ 7974 void 7975 alist_unlink(alist_T *al) 7976 { 7977 if (al != &global_alist && --al->al_refcount <= 0) 7978 { 7979 alist_clear(al); 7980 vim_free(al); 7981 } 7982 } 7983 7984 #if defined(FEAT_LISTCMDS) || defined(HAVE_DROP_FILE) || defined(PROTO) 7985 /* 7986 * Create a new argument list and use it for the current window. 7987 */ 7988 void 7989 alist_new(void) 7990 { 7991 curwin->w_alist = (alist_T *)alloc((unsigned)sizeof(alist_T)); 7992 if (curwin->w_alist == NULL) 7993 { 7994 curwin->w_alist = &global_alist; 7995 ++global_alist.al_refcount; 7996 } 7997 else 7998 { 7999 curwin->w_alist->al_refcount = 1; 8000 curwin->w_alist->id = ++max_alist_id; 8001 alist_init(curwin->w_alist); 8002 } 8003 } 8004 #endif 8005 8006 #if !defined(UNIX) || defined(PROTO) 8007 /* 8008 * Expand the file names in the global argument list. 8009 * If "fnum_list" is not NULL, use "fnum_list[fnum_len]" as a list of buffer 8010 * numbers to be re-used. 8011 */ 8012 void 8013 alist_expand(int *fnum_list, int fnum_len) 8014 { 8015 char_u **old_arg_files; 8016 int old_arg_count; 8017 char_u **new_arg_files; 8018 int new_arg_file_count; 8019 char_u *save_p_su = p_su; 8020 int i; 8021 8022 /* Don't use 'suffixes' here. This should work like the shell did the 8023 * expansion. Also, the vimrc file isn't read yet, thus the user 8024 * can't set the options. */ 8025 p_su = empty_option; 8026 old_arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * GARGCOUNT)); 8027 if (old_arg_files != NULL) 8028 { 8029 for (i = 0; i < GARGCOUNT; ++i) 8030 old_arg_files[i] = vim_strsave(GARGLIST[i].ae_fname); 8031 old_arg_count = GARGCOUNT; 8032 if (expand_wildcards(old_arg_count, old_arg_files, 8033 &new_arg_file_count, &new_arg_files, 8034 EW_FILE|EW_NOTFOUND|EW_ADDSLASH|EW_NOERROR) == OK 8035 && new_arg_file_count > 0) 8036 { 8037 alist_set(&global_alist, new_arg_file_count, new_arg_files, 8038 TRUE, fnum_list, fnum_len); 8039 FreeWild(old_arg_count, old_arg_files); 8040 } 8041 } 8042 p_su = save_p_su; 8043 } 8044 #endif 8045 8046 /* 8047 * Set the argument list for the current window. 8048 * Takes over the allocated files[] and the allocated fnames in it. 8049 */ 8050 void 8051 alist_set( 8052 alist_T *al, 8053 int count, 8054 char_u **files, 8055 int use_curbuf, 8056 int *fnum_list, 8057 int fnum_len) 8058 { 8059 int i; 8060 8061 alist_clear(al); 8062 if (ga_grow(&al->al_ga, count) == OK) 8063 { 8064 for (i = 0; i < count; ++i) 8065 { 8066 if (got_int) 8067 { 8068 /* When adding many buffers this can take a long time. Allow 8069 * interrupting here. */ 8070 while (i < count) 8071 vim_free(files[i++]); 8072 break; 8073 } 8074 8075 /* May set buffer name of a buffer previously used for the 8076 * argument list, so that it's re-used by alist_add. */ 8077 if (fnum_list != NULL && i < fnum_len) 8078 buf_set_name(fnum_list[i], files[i]); 8079 8080 alist_add(al, files[i], use_curbuf ? 2 : 1); 8081 ui_breakcheck(); 8082 } 8083 vim_free(files); 8084 } 8085 else 8086 FreeWild(count, files); 8087 if (al == &global_alist) 8088 arg_had_last = FALSE; 8089 } 8090 8091 /* 8092 * Add file "fname" to argument list "al". 8093 * "fname" must have been allocated and "al" must have been checked for room. 8094 */ 8095 void 8096 alist_add( 8097 alist_T *al, 8098 char_u *fname, 8099 int set_fnum) /* 1: set buffer number; 2: re-use curbuf */ 8100 { 8101 if (fname == NULL) /* don't add NULL file names */ 8102 return; 8103 #ifdef BACKSLASH_IN_FILENAME 8104 slash_adjust(fname); 8105 #endif 8106 AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname; 8107 if (set_fnum > 0) 8108 AARGLIST(al)[al->al_ga.ga_len].ae_fnum = 8109 buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0)); 8110 ++al->al_ga.ga_len; 8111 } 8112 8113 #if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) 8114 /* 8115 * Adjust slashes in file names. Called after 'shellslash' was set. 8116 */ 8117 void 8118 alist_slash_adjust(void) 8119 { 8120 int i; 8121 win_T *wp; 8122 tabpage_T *tp; 8123 8124 for (i = 0; i < GARGCOUNT; ++i) 8125 if (GARGLIST[i].ae_fname != NULL) 8126 slash_adjust(GARGLIST[i].ae_fname); 8127 FOR_ALL_TAB_WINDOWS(tp, wp) 8128 if (wp->w_alist != &global_alist) 8129 for (i = 0; i < WARGCOUNT(wp); ++i) 8130 if (WARGLIST(wp)[i].ae_fname != NULL) 8131 slash_adjust(WARGLIST(wp)[i].ae_fname); 8132 } 8133 #endif 8134 8135 /* 8136 * ":preserve". 8137 */ 8138 static void 8139 ex_preserve(exarg_T *eap UNUSED) 8140 { 8141 curbuf->b_flags |= BF_PRESERVED; 8142 ml_preserve(curbuf, TRUE); 8143 } 8144 8145 /* 8146 * ":recover". 8147 */ 8148 static void 8149 ex_recover(exarg_T *eap) 8150 { 8151 /* Set recoverymode right away to avoid the ATTENTION prompt. */ 8152 recoverymode = TRUE; 8153 if (!check_changed(curbuf, (p_awa ? CCGD_AW : 0) 8154 | CCGD_MULTWIN 8155 | (eap->forceit ? CCGD_FORCEIT : 0) 8156 | CCGD_EXCMD) 8157 8158 && (*eap->arg == NUL 8159 || setfname(curbuf, eap->arg, NULL, TRUE) == OK)) 8160 ml_recover(); 8161 recoverymode = FALSE; 8162 } 8163 8164 /* 8165 * Command modifier used in a wrong way. 8166 */ 8167 static void 8168 ex_wrongmodifier(exarg_T *eap) 8169 { 8170 eap->errmsg = e_invcmd; 8171 } 8172 8173 /* 8174 * :sview [+command] file split window with new file, read-only 8175 * :split [[+command] file] split window with current or new file 8176 * :vsplit [[+command] file] split window vertically with current or new file 8177 * :new [[+command] file] split window with no or new file 8178 * :vnew [[+command] file] split vertically window with no or new file 8179 * :sfind [+command] file split window with file in 'path' 8180 * 8181 * :tabedit open new Tab page with empty window 8182 * :tabedit [+command] file open new Tab page and edit "file" 8183 * :tabnew [[+command] file] just like :tabedit 8184 * :tabfind [+command] file open new Tab page and find "file" 8185 */ 8186 void 8187 ex_splitview(exarg_T *eap) 8188 { 8189 win_T *old_curwin = curwin; 8190 #if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE) 8191 char_u *fname = NULL; 8192 #endif 8193 #ifdef FEAT_BROWSE 8194 int browse_flag = cmdmod.browse; 8195 #endif 8196 8197 #ifdef FEAT_GUI 8198 need_mouse_correct = TRUE; 8199 #endif 8200 8201 #ifdef FEAT_QUICKFIX 8202 /* A ":split" in the quickfix window works like ":new". Don't want two 8203 * quickfix windows. But it's OK when doing ":tab split". */ 8204 if (bt_quickfix(curbuf) && cmdmod.tab == 0) 8205 { 8206 if (eap->cmdidx == CMD_split) 8207 eap->cmdidx = CMD_new; 8208 if (eap->cmdidx == CMD_vsplit) 8209 eap->cmdidx = CMD_vnew; 8210 } 8211 #endif 8212 8213 #ifdef FEAT_SEARCHPATH 8214 if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind) 8215 { 8216 fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), 8217 FNAME_MESS, TRUE, curbuf->b_ffname); 8218 if (fname == NULL) 8219 goto theend; 8220 eap->arg = fname; 8221 } 8222 # ifdef FEAT_BROWSE 8223 else 8224 # endif 8225 #endif 8226 #ifdef FEAT_BROWSE 8227 if (cmdmod.browse 8228 && eap->cmdidx != CMD_vnew 8229 && eap->cmdidx != CMD_new) 8230 { 8231 # ifdef FEAT_AUTOCMD 8232 if ( 8233 # ifdef FEAT_GUI 8234 !gui.in_use && 8235 # endif 8236 au_has_group((char_u *)"FileExplorer")) 8237 { 8238 /* No browsing supported but we do have the file explorer: 8239 * Edit the directory. */ 8240 if (*eap->arg == NUL || !mch_isdir(eap->arg)) 8241 eap->arg = (char_u *)"."; 8242 } 8243 else 8244 # endif 8245 { 8246 fname = do_browse(0, (char_u *)_("Edit File in new window"), 8247 eap->arg, NULL, NULL, NULL, curbuf); 8248 if (fname == NULL) 8249 goto theend; 8250 eap->arg = fname; 8251 } 8252 } 8253 cmdmod.browse = FALSE; /* Don't browse again in do_ecmd(). */ 8254 #endif 8255 8256 /* 8257 * Either open new tab page or split the window. 8258 */ 8259 if (eap->cmdidx == CMD_tabedit 8260 || eap->cmdidx == CMD_tabfind 8261 || eap->cmdidx == CMD_tabnew) 8262 { 8263 if (win_new_tabpage(cmdmod.tab != 0 ? cmdmod.tab 8264 : eap->addr_count == 0 ? 0 8265 : (int)eap->line2 + 1) != FAIL) 8266 { 8267 do_exedit(eap, old_curwin); 8268 8269 /* set the alternate buffer for the window we came from */ 8270 if (curwin != old_curwin 8271 && win_valid(old_curwin) 8272 && old_curwin->w_buffer != curbuf 8273 && !cmdmod.keepalt) 8274 old_curwin->w_alt_fnum = curbuf->b_fnum; 8275 } 8276 } 8277 else if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0, 8278 *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL) 8279 { 8280 # ifdef FEAT_SCROLLBIND 8281 /* Reset 'scrollbind' when editing another file, but keep it when 8282 * doing ":split" without arguments. */ 8283 if (*eap->arg != NUL 8284 # ifdef FEAT_BROWSE 8285 || cmdmod.browse 8286 # endif 8287 ) 8288 { 8289 RESET_BINDING(curwin); 8290 } 8291 else 8292 do_check_scrollbind(FALSE); 8293 # endif 8294 do_exedit(eap, old_curwin); 8295 } 8296 8297 # ifdef FEAT_BROWSE 8298 cmdmod.browse = browse_flag; 8299 # endif 8300 8301 # if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE) 8302 theend: 8303 vim_free(fname); 8304 # endif 8305 } 8306 8307 /* 8308 * Open a new tab page. 8309 */ 8310 void 8311 tabpage_new(void) 8312 { 8313 exarg_T ea; 8314 8315 vim_memset(&ea, 0, sizeof(ea)); 8316 ea.cmdidx = CMD_tabnew; 8317 ea.cmd = (char_u *)"tabn"; 8318 ea.arg = (char_u *)""; 8319 ex_splitview(&ea); 8320 } 8321 8322 /* 8323 * :tabnext command 8324 */ 8325 static void 8326 ex_tabnext(exarg_T *eap) 8327 { 8328 int tab_number; 8329 8330 switch (eap->cmdidx) 8331 { 8332 case CMD_tabfirst: 8333 case CMD_tabrewind: 8334 goto_tabpage(1); 8335 break; 8336 case CMD_tablast: 8337 goto_tabpage(9999); 8338 break; 8339 case CMD_tabprevious: 8340 case CMD_tabNext: 8341 if (eap->arg && *eap->arg != NUL) 8342 { 8343 char_u *p = eap->arg; 8344 char_u *p_save = p; 8345 8346 tab_number = getdigits(&p); 8347 if (p == p_save || *p_save == '-' || *p != NUL 8348 || tab_number == 0) 8349 { 8350 /* No numbers as argument. */ 8351 eap->errmsg = e_invarg; 8352 return; 8353 } 8354 } 8355 else 8356 { 8357 if (eap->addr_count == 0) 8358 tab_number = 1; 8359 else 8360 { 8361 tab_number = eap->line2; 8362 if (tab_number < 1) 8363 { 8364 eap->errmsg = e_invrange; 8365 return; 8366 } 8367 } 8368 } 8369 goto_tabpage(-tab_number); 8370 break; 8371 default: /* CMD_tabnext */ 8372 tab_number = get_tabpage_arg(eap); 8373 if (eap->errmsg == NULL) 8374 goto_tabpage(tab_number); 8375 break; 8376 } 8377 } 8378 8379 /* 8380 * :tabmove command 8381 */ 8382 static void 8383 ex_tabmove(exarg_T *eap) 8384 { 8385 int tab_number; 8386 8387 tab_number = get_tabpage_arg(eap); 8388 if (eap->errmsg == NULL) 8389 tabpage_move(tab_number); 8390 } 8391 8392 /* 8393 * :tabs command: List tabs and their contents. 8394 */ 8395 static void 8396 ex_tabs(exarg_T *eap UNUSED) 8397 { 8398 tabpage_T *tp; 8399 win_T *wp; 8400 int tabcount = 1; 8401 8402 msg_start(); 8403 msg_scroll = TRUE; 8404 for (tp = first_tabpage; tp != NULL && !got_int; tp = tp->tp_next) 8405 { 8406 msg_putchar('\n'); 8407 vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++); 8408 msg_outtrans_attr(IObuff, HL_ATTR(HLF_T)); 8409 out_flush(); /* output one line at a time */ 8410 ui_breakcheck(); 8411 8412 if (tp == curtab) 8413 wp = firstwin; 8414 else 8415 wp = tp->tp_firstwin; 8416 for ( ; wp != NULL && !got_int; wp = wp->w_next) 8417 { 8418 msg_putchar('\n'); 8419 msg_putchar(wp == curwin ? '>' : ' '); 8420 msg_putchar(' '); 8421 msg_putchar(bufIsChanged(wp->w_buffer) ? '+' : ' '); 8422 msg_putchar(' '); 8423 if (buf_spname(wp->w_buffer) != NULL) 8424 vim_strncpy(IObuff, buf_spname(wp->w_buffer), IOSIZE - 1); 8425 else 8426 home_replace(wp->w_buffer, wp->w_buffer->b_fname, 8427 IObuff, IOSIZE, TRUE); 8428 msg_outtrans(IObuff); 8429 out_flush(); /* output one line at a time */ 8430 ui_breakcheck(); 8431 } 8432 } 8433 } 8434 8435 /* 8436 * ":mode": Set screen mode. 8437 * If no argument given, just get the screen size and redraw. 8438 */ 8439 static void 8440 ex_mode(exarg_T *eap) 8441 { 8442 if (*eap->arg == NUL) 8443 shell_resized(); 8444 else 8445 mch_screenmode(eap->arg); 8446 } 8447 8448 /* 8449 * ":resize". 8450 * set, increment or decrement current window height 8451 */ 8452 static void 8453 ex_resize(exarg_T *eap) 8454 { 8455 int n; 8456 win_T *wp = curwin; 8457 8458 if (eap->addr_count > 0) 8459 { 8460 n = eap->line2; 8461 for (wp = firstwin; wp->w_next != NULL && --n > 0; wp = wp->w_next) 8462 ; 8463 } 8464 8465 # ifdef FEAT_GUI 8466 need_mouse_correct = TRUE; 8467 # endif 8468 n = atol((char *)eap->arg); 8469 if (cmdmod.split & WSP_VERT) 8470 { 8471 if (*eap->arg == '-' || *eap->arg == '+') 8472 n += curwin->w_width; 8473 else if (n == 0 && eap->arg[0] == NUL) /* default is very wide */ 8474 n = 9999; 8475 win_setwidth_win((int)n, wp); 8476 } 8477 else 8478 { 8479 if (*eap->arg == '-' || *eap->arg == '+') 8480 n += curwin->w_height; 8481 else if (n == 0 && eap->arg[0] == NUL) /* default is very high */ 8482 n = 9999; 8483 win_setheight_win((int)n, wp); 8484 } 8485 } 8486 8487 /* 8488 * ":find [+command] <file>" command. 8489 */ 8490 static void 8491 ex_find(exarg_T *eap) 8492 { 8493 #ifdef FEAT_SEARCHPATH 8494 char_u *fname; 8495 int count; 8496 8497 fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS, 8498 TRUE, curbuf->b_ffname); 8499 if (eap->addr_count > 0) 8500 { 8501 /* Repeat finding the file "count" times. This matters when it 8502 * appears several times in the path. */ 8503 count = eap->line2; 8504 while (fname != NULL && --count > 0) 8505 { 8506 vim_free(fname); 8507 fname = find_file_in_path(NULL, 0, FNAME_MESS, 8508 FALSE, curbuf->b_ffname); 8509 } 8510 } 8511 8512 if (fname != NULL) 8513 { 8514 eap->arg = fname; 8515 #endif 8516 do_exedit(eap, NULL); 8517 #ifdef FEAT_SEARCHPATH 8518 vim_free(fname); 8519 } 8520 #endif 8521 } 8522 8523 /* 8524 * ":open" simulation: for now just work like ":visual". 8525 */ 8526 static void 8527 ex_open(exarg_T *eap) 8528 { 8529 regmatch_T regmatch; 8530 char_u *p; 8531 8532 curwin->w_cursor.lnum = eap->line2; 8533 beginline(BL_SOL | BL_FIX); 8534 if (*eap->arg == '/') 8535 { 8536 /* ":open /pattern/": put cursor in column found with pattern */ 8537 ++eap->arg; 8538 p = skip_regexp(eap->arg, '/', p_magic, NULL); 8539 *p = NUL; 8540 regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0); 8541 if (regmatch.regprog != NULL) 8542 { 8543 regmatch.rm_ic = p_ic; 8544 p = ml_get_curline(); 8545 if (vim_regexec(®match, p, (colnr_T)0)) 8546 curwin->w_cursor.col = (colnr_T)(regmatch.startp[0] - p); 8547 else 8548 EMSG(_(e_nomatch)); 8549 vim_regfree(regmatch.regprog); 8550 } 8551 /* Move to the NUL, ignore any other arguments. */ 8552 eap->arg += STRLEN(eap->arg); 8553 } 8554 check_cursor(); 8555 8556 eap->cmdidx = CMD_visual; 8557 do_exedit(eap, NULL); 8558 } 8559 8560 /* 8561 * ":edit", ":badd", ":visual". 8562 */ 8563 static void 8564 ex_edit(exarg_T *eap) 8565 { 8566 do_exedit(eap, NULL); 8567 } 8568 8569 /* 8570 * ":edit <file>" command and alikes. 8571 */ 8572 void 8573 do_exedit( 8574 exarg_T *eap, 8575 win_T *old_curwin) /* curwin before doing a split or NULL */ 8576 { 8577 int n; 8578 int need_hide; 8579 int exmode_was = exmode_active; 8580 8581 /* 8582 * ":vi" command ends Ex mode. 8583 */ 8584 if (exmode_active && (eap->cmdidx == CMD_visual 8585 || eap->cmdidx == CMD_view)) 8586 { 8587 exmode_active = FALSE; 8588 if (*eap->arg == NUL) 8589 { 8590 /* Special case: ":global/pat/visual\NLvi-commands" */ 8591 if (global_busy) 8592 { 8593 int rd = RedrawingDisabled; 8594 int nwr = no_wait_return; 8595 int ms = msg_scroll; 8596 #ifdef FEAT_GUI 8597 int he = hold_gui_events; 8598 #endif 8599 8600 if (eap->nextcmd != NULL) 8601 { 8602 stuffReadbuff(eap->nextcmd); 8603 eap->nextcmd = NULL; 8604 } 8605 8606 if (exmode_was != EXMODE_VIM) 8607 settmode(TMODE_RAW); 8608 RedrawingDisabled = 0; 8609 no_wait_return = 0; 8610 need_wait_return = FALSE; 8611 msg_scroll = 0; 8612 #ifdef FEAT_GUI 8613 hold_gui_events = 0; 8614 #endif 8615 must_redraw = CLEAR; 8616 8617 main_loop(FALSE, TRUE); 8618 8619 RedrawingDisabled = rd; 8620 no_wait_return = nwr; 8621 msg_scroll = ms; 8622 #ifdef FEAT_GUI 8623 hold_gui_events = he; 8624 #endif 8625 } 8626 return; 8627 } 8628 } 8629 8630 if ((eap->cmdidx == CMD_new 8631 || eap->cmdidx == CMD_tabnew 8632 || eap->cmdidx == CMD_tabedit 8633 || eap->cmdidx == CMD_vnew) && *eap->arg == NUL) 8634 { 8635 /* ":new" or ":tabnew" without argument: edit an new empty buffer */ 8636 setpcmark(); 8637 (void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE, 8638 ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0), 8639 old_curwin == NULL ? curwin : NULL); 8640 } 8641 else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit) 8642 || *eap->arg != NUL 8643 #ifdef FEAT_BROWSE 8644 || cmdmod.browse 8645 #endif 8646 ) 8647 { 8648 #ifdef FEAT_AUTOCMD 8649 /* Can't edit another file when "curbuf_lock" is set. Only ":edit" 8650 * can bring us here, others are stopped earlier. */ 8651 if (*eap->arg != NUL && curbuf_locked()) 8652 return; 8653 #endif 8654 n = readonlymode; 8655 if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview) 8656 readonlymode = TRUE; 8657 else if (eap->cmdidx == CMD_enew) 8658 readonlymode = FALSE; /* 'readonly' doesn't make sense in an 8659 empty buffer */ 8660 setpcmark(); 8661 if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg), 8662 NULL, eap, 8663 /* ":edit" goes to first line if Vi compatible */ 8664 (*eap->arg == NUL && eap->do_ecmd_lnum == 0 8665 && vim_strchr(p_cpo, CPO_GOTO1) != NULL) 8666 ? ECMD_ONE : eap->do_ecmd_lnum, 8667 (buf_hide(curbuf) ? ECMD_HIDE : 0) 8668 + (eap->forceit ? ECMD_FORCEIT : 0) 8669 /* after a split we can use an existing buffer */ 8670 + (old_curwin != NULL ? ECMD_OLDBUF : 0) 8671 #ifdef FEAT_LISTCMDS 8672 + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 ) 8673 #endif 8674 , old_curwin == NULL ? curwin : NULL) == FAIL) 8675 { 8676 /* Editing the file failed. If the window was split, close it. */ 8677 if (old_curwin != NULL) 8678 { 8679 need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1); 8680 if (!need_hide || buf_hide(curbuf)) 8681 { 8682 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) 8683 cleanup_T cs; 8684 8685 /* Reset the error/interrupt/exception state here so that 8686 * aborting() returns FALSE when closing a window. */ 8687 enter_cleanup(&cs); 8688 #endif 8689 #ifdef FEAT_GUI 8690 need_mouse_correct = TRUE; 8691 #endif 8692 win_close(curwin, !need_hide && !buf_hide(curbuf)); 8693 8694 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) 8695 /* Restore the error/interrupt/exception state if not 8696 * discarded by a new aborting error, interrupt, or 8697 * uncaught exception. */ 8698 leave_cleanup(&cs); 8699 #endif 8700 } 8701 } 8702 } 8703 else if (readonlymode && curbuf->b_nwindows == 1) 8704 { 8705 /* When editing an already visited buffer, 'readonly' won't be set 8706 * but the previous value is kept. With ":view" and ":sview" we 8707 * want the file to be readonly, except when another window is 8708 * editing the same buffer. */ 8709 curbuf->b_p_ro = TRUE; 8710 } 8711 readonlymode = n; 8712 } 8713 else 8714 { 8715 if (eap->do_ecmd_cmd != NULL) 8716 do_cmdline_cmd(eap->do_ecmd_cmd); 8717 #ifdef FEAT_TITLE 8718 n = curwin->w_arg_idx_invalid; 8719 #endif 8720 check_arg_idx(curwin); 8721 #ifdef FEAT_TITLE 8722 if (n != curwin->w_arg_idx_invalid) 8723 maketitle(); 8724 #endif 8725 } 8726 8727 /* 8728 * if ":split file" worked, set alternate file name in old window to new 8729 * file 8730 */ 8731 if (old_curwin != NULL 8732 && *eap->arg != NUL 8733 && curwin != old_curwin 8734 && win_valid(old_curwin) 8735 && old_curwin->w_buffer != curbuf 8736 && !cmdmod.keepalt) 8737 old_curwin->w_alt_fnum = curbuf->b_fnum; 8738 8739 ex_no_reprint = TRUE; 8740 } 8741 8742 #ifndef FEAT_GUI 8743 /* 8744 * ":gui" and ":gvim" when there is no GUI. 8745 */ 8746 static void 8747 ex_nogui(exarg_T *eap) 8748 { 8749 eap->errmsg = e_nogvim; 8750 } 8751 #endif 8752 8753 #if defined(FEAT_GUI_W32) && defined(FEAT_MENU) && defined(FEAT_TEAROFF) 8754 static void 8755 ex_tearoff(exarg_T *eap) 8756 { 8757 gui_make_tearoff(eap->arg); 8758 } 8759 #endif 8760 8761 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)) && defined(FEAT_MENU) 8762 static void 8763 ex_popup(exarg_T *eap) 8764 { 8765 gui_make_popup(eap->arg, eap->forceit); 8766 } 8767 #endif 8768 8769 static void 8770 ex_swapname(exarg_T *eap UNUSED) 8771 { 8772 if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL) 8773 MSG(_("No swap file")); 8774 else 8775 msg(curbuf->b_ml.ml_mfp->mf_fname); 8776 } 8777 8778 /* 8779 * ":syncbind" forces all 'scrollbind' windows to have the same relative 8780 * offset. 8781 * (1998-11-02 16:21:01 R. Edward Ralston <[email protected]>) 8782 */ 8783 static void 8784 ex_syncbind(exarg_T *eap UNUSED) 8785 { 8786 #ifdef FEAT_SCROLLBIND 8787 win_T *wp; 8788 win_T *save_curwin = curwin; 8789 buf_T *save_curbuf = curbuf; 8790 long topline; 8791 long y; 8792 linenr_T old_linenr = curwin->w_cursor.lnum; 8793 8794 setpcmark(); 8795 8796 /* 8797 * determine max topline 8798 */ 8799 if (curwin->w_p_scb) 8800 { 8801 topline = curwin->w_topline; 8802 FOR_ALL_WINDOWS(wp) 8803 { 8804 if (wp->w_p_scb && wp->w_buffer) 8805 { 8806 y = wp->w_buffer->b_ml.ml_line_count - p_so; 8807 if (topline > y) 8808 topline = y; 8809 } 8810 } 8811 if (topline < 1) 8812 topline = 1; 8813 } 8814 else 8815 { 8816 topline = 1; 8817 } 8818 8819 8820 /* 8821 * Set all scrollbind windows to the same topline. 8822 */ 8823 FOR_ALL_WINDOWS(curwin) 8824 { 8825 if (curwin->w_p_scb) 8826 { 8827 curbuf = curwin->w_buffer; 8828 y = topline - curwin->w_topline; 8829 if (y > 0) 8830 scrollup(y, TRUE); 8831 else 8832 scrolldown(-y, TRUE); 8833 curwin->w_scbind_pos = topline; 8834 redraw_later(VALID); 8835 cursor_correct(); 8836 curwin->w_redr_status = TRUE; 8837 } 8838 } 8839 curwin = save_curwin; 8840 curbuf = save_curbuf; 8841 if (curwin->w_p_scb) 8842 { 8843 did_syncbind = TRUE; 8844 checkpcmark(); 8845 if (old_linenr != curwin->w_cursor.lnum) 8846 { 8847 char_u ctrl_o[2]; 8848 8849 ctrl_o[0] = Ctrl_O; 8850 ctrl_o[1] = 0; 8851 ins_typebuf(ctrl_o, REMAP_NONE, 0, TRUE, FALSE); 8852 } 8853 } 8854 #endif 8855 } 8856 8857 8858 static void 8859 ex_read(exarg_T *eap) 8860 { 8861 int i; 8862 int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); 8863 linenr_T lnum; 8864 8865 if (eap->usefilter) /* :r!cmd */ 8866 do_bang(1, eap, FALSE, FALSE, TRUE); 8867 else 8868 { 8869 if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) 8870 return; 8871 8872 #ifdef FEAT_BROWSE 8873 if (cmdmod.browse) 8874 { 8875 char_u *browseFile; 8876 8877 browseFile = do_browse(0, (char_u *)_("Append File"), eap->arg, 8878 NULL, NULL, NULL, curbuf); 8879 if (browseFile != NULL) 8880 { 8881 i = readfile(browseFile, NULL, 8882 eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0); 8883 vim_free(browseFile); 8884 } 8885 else 8886 i = OK; 8887 } 8888 else 8889 #endif 8890 if (*eap->arg == NUL) 8891 { 8892 if (check_fname() == FAIL) /* check for no file name */ 8893 return; 8894 i = readfile(curbuf->b_ffname, curbuf->b_fname, 8895 eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0); 8896 } 8897 else 8898 { 8899 if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL) 8900 (void)setaltfname(eap->arg, eap->arg, (linenr_T)1); 8901 i = readfile(eap->arg, NULL, 8902 eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0); 8903 8904 } 8905 if (i != OK) 8906 { 8907 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) 8908 if (!aborting()) 8909 #endif 8910 EMSG2(_(e_notopen), eap->arg); 8911 } 8912 else 8913 { 8914 if (empty && exmode_active) 8915 { 8916 /* Delete the empty line that remains. Historically ex does 8917 * this but vi doesn't. */ 8918 if (eap->line2 == 0) 8919 lnum = curbuf->b_ml.ml_line_count; 8920 else 8921 lnum = 1; 8922 if (*ml_get(lnum) == NUL && u_savedel(lnum, 1L) == OK) 8923 { 8924 ml_delete(lnum, FALSE); 8925 if (curwin->w_cursor.lnum > 1 8926 && curwin->w_cursor.lnum >= lnum) 8927 --curwin->w_cursor.lnum; 8928 deleted_lines_mark(lnum, 1L); 8929 } 8930 } 8931 redraw_curbuf_later(VALID); 8932 } 8933 } 8934 } 8935 8936 static char_u *prev_dir = NULL; 8937 8938 #if defined(EXITFREE) || defined(PROTO) 8939 void 8940 free_cd_dir(void) 8941 { 8942 vim_free(prev_dir); 8943 prev_dir = NULL; 8944 8945 vim_free(globaldir); 8946 globaldir = NULL; 8947 } 8948 #endif 8949 8950 /* 8951 * Deal with the side effects of changing the current directory. 8952 * When "local" is TRUE then this was after an ":lcd" command. 8953 */ 8954 void 8955 post_chdir(int local) 8956 { 8957 vim_free(curwin->w_localdir); 8958 curwin->w_localdir = NULL; 8959 if (local) 8960 { 8961 /* If still in global directory, need to remember current 8962 * directory as global directory. */ 8963 if (globaldir == NULL && prev_dir != NULL) 8964 globaldir = vim_strsave(prev_dir); 8965 /* Remember this local directory for the window. */ 8966 if (mch_dirname(NameBuff, MAXPATHL) == OK) 8967 curwin->w_localdir = vim_strsave(NameBuff); 8968 } 8969 else 8970 { 8971 /* We are now in the global directory, no need to remember its 8972 * name. */ 8973 vim_free(globaldir); 8974 globaldir = NULL; 8975 } 8976 8977 shorten_fnames(TRUE); 8978 } 8979 8980 8981 /* 8982 * ":cd", ":lcd", ":chdir" and ":lchdir". 8983 */ 8984 void 8985 ex_cd(exarg_T *eap) 8986 { 8987 char_u *new_dir; 8988 char_u *tofree; 8989 8990 new_dir = eap->arg; 8991 #if !defined(UNIX) && !defined(VMS) 8992 /* for non-UNIX ":cd" means: print current directory */ 8993 if (*new_dir == NUL) 8994 ex_pwd(NULL); 8995 else 8996 #endif 8997 { 8998 #ifdef FEAT_AUTOCMD 8999 if (allbuf_locked()) 9000 return; 9001 #endif 9002 if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() 9003 && !eap->forceit) 9004 { 9005 EMSG(_("E747: Cannot change directory, buffer is modified (add ! to override)")); 9006 return; 9007 } 9008 9009 /* ":cd -": Change to previous directory */ 9010 if (STRCMP(new_dir, "-") == 0) 9011 { 9012 if (prev_dir == NULL) 9013 { 9014 EMSG(_("E186: No previous directory")); 9015 return; 9016 } 9017 new_dir = prev_dir; 9018 } 9019 9020 /* Save current directory for next ":cd -" */ 9021 tofree = prev_dir; 9022 if (mch_dirname(NameBuff, MAXPATHL) == OK) 9023 prev_dir = vim_strsave(NameBuff); 9024 else 9025 prev_dir = NULL; 9026 9027 #if defined(UNIX) || defined(VMS) 9028 /* for UNIX ":cd" means: go to home directory */ 9029 if (*new_dir == NUL) 9030 { 9031 /* use NameBuff for home directory name */ 9032 # ifdef VMS 9033 char_u *p; 9034 9035 p = mch_getenv((char_u *)"SYS$LOGIN"); 9036 if (p == NULL || *p == NUL) /* empty is the same as not set */ 9037 NameBuff[0] = NUL; 9038 else 9039 vim_strncpy(NameBuff, p, MAXPATHL - 1); 9040 # else 9041 expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); 9042 # endif 9043 new_dir = NameBuff; 9044 } 9045 #endif 9046 if (new_dir == NULL || vim_chdir(new_dir)) 9047 EMSG(_(e_failed)); 9048 else 9049 { 9050 post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir); 9051 9052 /* Echo the new current directory if the command was typed. */ 9053 if (KeyTyped || p_verbose >= 5) 9054 ex_pwd(eap); 9055 } 9056 vim_free(tofree); 9057 } 9058 } 9059 9060 /* 9061 * ":pwd". 9062 */ 9063 static void 9064 ex_pwd(exarg_T *eap UNUSED) 9065 { 9066 if (mch_dirname(NameBuff, MAXPATHL) == OK) 9067 { 9068 #ifdef BACKSLASH_IN_FILENAME 9069 slash_adjust(NameBuff); 9070 #endif 9071 msg(NameBuff); 9072 } 9073 else 9074 EMSG(_("E187: Unknown")); 9075 } 9076 9077 /* 9078 * ":=". 9079 */ 9080 static void 9081 ex_equal(exarg_T *eap) 9082 { 9083 smsg((char_u *)"%ld", (long)eap->line2); 9084 ex_may_print(eap); 9085 } 9086 9087 static void 9088 ex_sleep(exarg_T *eap) 9089 { 9090 int n; 9091 long len; 9092 9093 if (cursor_valid()) 9094 { 9095 n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled; 9096 if (n >= 0) 9097 windgoto((int)n, curwin->w_wincol + curwin->w_wcol); 9098 } 9099 9100 len = eap->line2; 9101 switch (*eap->arg) 9102 { 9103 case 'm': break; 9104 case NUL: len *= 1000L; break; 9105 default: EMSG2(_(e_invarg2), eap->arg); return; 9106 } 9107 do_sleep(len); 9108 } 9109 9110 /* 9111 * Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second. 9112 */ 9113 void 9114 do_sleep(long msec) 9115 { 9116 long done; 9117 long wait_now; 9118 9119 cursor_on(); 9120 out_flush(); 9121 for (done = 0; !got_int && done < msec; done += wait_now) 9122 { 9123 wait_now = msec - done > 1000L ? 1000L : msec - done; 9124 #ifdef FEAT_TIMERS 9125 { 9126 long due_time = check_due_timer(); 9127 9128 if (due_time > 0 && due_time < wait_now) 9129 wait_now = due_time; 9130 } 9131 #endif 9132 #ifdef FEAT_JOB_CHANNEL 9133 if (has_any_channel() && wait_now > 100L) 9134 wait_now = 100L; 9135 #endif 9136 ui_delay(wait_now, TRUE); 9137 #ifdef FEAT_JOB_CHANNEL 9138 if (has_any_channel()) 9139 ui_breakcheck_force(TRUE); 9140 else 9141 #endif 9142 ui_breakcheck(); 9143 #ifdef MESSAGE_QUEUE 9144 /* Process the netbeans and clientserver messages that may have been 9145 * received in the call to ui_breakcheck() when the GUI is in use. This 9146 * may occur when running a test case. */ 9147 parse_queued_messages(); 9148 #endif 9149 } 9150 } 9151 9152 static void 9153 do_exmap(exarg_T *eap, int isabbrev) 9154 { 9155 int mode; 9156 char_u *cmdp; 9157 9158 cmdp = eap->cmd; 9159 mode = get_map_mode(&cmdp, eap->forceit || isabbrev); 9160 9161 switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), 9162 eap->arg, mode, isabbrev)) 9163 { 9164 case 1: EMSG(_(e_invarg)); 9165 break; 9166 case 2: EMSG(isabbrev ? _(e_noabbr) : _(e_nomap)); 9167 break; 9168 } 9169 } 9170 9171 /* 9172 * ":winsize" command (obsolete). 9173 */ 9174 static void 9175 ex_winsize(exarg_T *eap) 9176 { 9177 int w, h; 9178 char_u *arg = eap->arg; 9179 char_u *p; 9180 9181 w = getdigits(&arg); 9182 arg = skipwhite(arg); 9183 p = arg; 9184 h = getdigits(&arg); 9185 if (*p != NUL && *arg == NUL) 9186 set_shellsize(w, h, TRUE); 9187 else 9188 EMSG(_("E465: :winsize requires two number arguments")); 9189 } 9190 9191 static void 9192 ex_wincmd(exarg_T *eap) 9193 { 9194 int xchar = NUL; 9195 char_u *p; 9196 9197 if (*eap->arg == 'g' || *eap->arg == Ctrl_G) 9198 { 9199 /* CTRL-W g and CTRL-W CTRL-G have an extra command character */ 9200 if (eap->arg[1] == NUL) 9201 { 9202 EMSG(_(e_invarg)); 9203 return; 9204 } 9205 xchar = eap->arg[1]; 9206 p = eap->arg + 2; 9207 } 9208 else 9209 p = eap->arg + 1; 9210 9211 eap->nextcmd = check_nextcmd(p); 9212 p = skipwhite(p); 9213 if (*p != NUL && *p != '"' && eap->nextcmd == NULL) 9214 EMSG(_(e_invarg)); 9215 else if (!eap->skip) 9216 { 9217 /* Pass flags on for ":vertical wincmd ]". */ 9218 postponed_split_flags = cmdmod.split; 9219 postponed_split_tab = cmdmod.tab; 9220 do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar); 9221 postponed_split_flags = 0; 9222 postponed_split_tab = 0; 9223 } 9224 } 9225 9226 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN) 9227 /* 9228 * ":winpos". 9229 */ 9230 static void 9231 ex_winpos(exarg_T *eap) 9232 { 9233 int x, y; 9234 char_u *arg = eap->arg; 9235 char_u *p; 9236 9237 if (*arg == NUL) 9238 { 9239 # if defined(FEAT_GUI) || defined(MSWIN) 9240 # ifdef FEAT_GUI 9241 if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL) 9242 # else 9243 if (mch_get_winpos(&x, &y) != FAIL) 9244 # endif 9245 { 9246 sprintf((char *)IObuff, _("Window position: X %d, Y %d"), x, y); 9247 msg(IObuff); 9248 } 9249 else 9250 # endif 9251 EMSG(_("E188: Obtaining window position not implemented for this platform")); 9252 } 9253 else 9254 { 9255 x = getdigits(&arg); 9256 arg = skipwhite(arg); 9257 p = arg; 9258 y = getdigits(&arg); 9259 if (*p == NUL || *arg != NUL) 9260 { 9261 EMSG(_("E466: :winpos requires two number arguments")); 9262 return; 9263 } 9264 # ifdef FEAT_GUI 9265 if (gui.in_use) 9266 gui_mch_set_winpos(x, y); 9267 else if (gui.starting) 9268 { 9269 /* Remember the coordinates for when the window is opened. */ 9270 gui_win_x = x; 9271 gui_win_y = y; 9272 } 9273 # ifdef HAVE_TGETENT 9274 else 9275 # endif 9276 # else 9277 # ifdef MSWIN 9278 mch_set_winpos(x, y); 9279 # endif 9280 # endif 9281 # ifdef HAVE_TGETENT 9282 if (*T_CWP) 9283 term_set_winpos(x, y); 9284 # endif 9285 } 9286 } 9287 #endif 9288 9289 /* 9290 * Handle command that work like operators: ":delete", ":yank", ":>" and ":<". 9291 */ 9292 static void 9293 ex_operators(exarg_T *eap) 9294 { 9295 oparg_T oa; 9296 9297 clear_oparg(&oa); 9298 oa.regname = eap->regname; 9299 oa.start.lnum = eap->line1; 9300 oa.end.lnum = eap->line2; 9301 oa.line_count = eap->line2 - eap->line1 + 1; 9302 oa.motion_type = MLINE; 9303 #ifdef FEAT_VIRTUALEDIT 9304 virtual_op = FALSE; 9305 #endif 9306 if (eap->cmdidx != CMD_yank) /* position cursor for undo */ 9307 { 9308 setpcmark(); 9309 curwin->w_cursor.lnum = eap->line1; 9310 beginline(BL_SOL | BL_FIX); 9311 } 9312 9313 if (VIsual_active) 9314 end_visual_mode(); 9315 9316 switch (eap->cmdidx) 9317 { 9318 case CMD_delete: 9319 oa.op_type = OP_DELETE; 9320 op_delete(&oa); 9321 break; 9322 9323 case CMD_yank: 9324 oa.op_type = OP_YANK; 9325 (void)op_yank(&oa, FALSE, TRUE); 9326 break; 9327 9328 default: /* CMD_rshift or CMD_lshift */ 9329 if ( 9330 #ifdef FEAT_RIGHTLEFT 9331 (eap->cmdidx == CMD_rshift) ^ curwin->w_p_rl 9332 #else 9333 eap->cmdidx == CMD_rshift 9334 #endif 9335 ) 9336 oa.op_type = OP_RSHIFT; 9337 else 9338 oa.op_type = OP_LSHIFT; 9339 op_shift(&oa, FALSE, eap->amount); 9340 break; 9341 } 9342 #ifdef FEAT_VIRTUALEDIT 9343 virtual_op = MAYBE; 9344 #endif 9345 ex_may_print(eap); 9346 } 9347 9348 /* 9349 * ":put". 9350 */ 9351 static void 9352 ex_put(exarg_T *eap) 9353 { 9354 /* ":0put" works like ":1put!". */ 9355 if (eap->line2 == 0) 9356 { 9357 eap->line2 = 1; 9358 eap->forceit = TRUE; 9359 } 9360 curwin->w_cursor.lnum = eap->line2; 9361 do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, 9362 PUT_LINE|PUT_CURSLINE); 9363 } 9364 9365 /* 9366 * Handle ":copy" and ":move". 9367 */ 9368 static void 9369 ex_copymove(exarg_T *eap) 9370 { 9371 long n; 9372 9373 n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, 1); 9374 if (eap->arg == NULL) /* error detected */ 9375 { 9376 eap->nextcmd = NULL; 9377 return; 9378 } 9379 get_flags(eap); 9380 9381 /* 9382 * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n' 9383 */ 9384 if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count) 9385 { 9386 EMSG(_(e_invaddr)); 9387 return; 9388 } 9389 9390 if (eap->cmdidx == CMD_move) 9391 { 9392 if (do_move(eap->line1, eap->line2, n) == FAIL) 9393 return; 9394 } 9395 else 9396 ex_copy(eap->line1, eap->line2, n); 9397 u_clearline(); 9398 beginline(BL_SOL | BL_FIX); 9399 ex_may_print(eap); 9400 } 9401 9402 /* 9403 * Print the current line if flags were given to the Ex command. 9404 */ 9405 void 9406 ex_may_print(exarg_T *eap) 9407 { 9408 if (eap->flags != 0) 9409 { 9410 print_line(curwin->w_cursor.lnum, (eap->flags & EXFLAG_NR), 9411 (eap->flags & EXFLAG_LIST)); 9412 ex_no_reprint = TRUE; 9413 } 9414 } 9415 9416 /* 9417 * ":smagic" and ":snomagic". 9418 */ 9419 static void 9420 ex_submagic(exarg_T *eap) 9421 { 9422 int magic_save = p_magic; 9423 9424 p_magic = (eap->cmdidx == CMD_smagic); 9425 do_sub(eap); 9426 p_magic = magic_save; 9427 } 9428 9429 /* 9430 * ":join". 9431 */ 9432 static void 9433 ex_join(exarg_T *eap) 9434 { 9435 curwin->w_cursor.lnum = eap->line1; 9436 if (eap->line1 == eap->line2) 9437 { 9438 if (eap->addr_count >= 2) /* :2,2join does nothing */ 9439 return; 9440 if (eap->line2 == curbuf->b_ml.ml_line_count) 9441 { 9442 beep_flush(); 9443 return; 9444 } 9445 ++eap->line2; 9446 } 9447 (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit, TRUE, TRUE, TRUE); 9448 beginline(BL_WHITE | BL_FIX); 9449 ex_may_print(eap); 9450 } 9451 9452 /* 9453 * ":[addr]@r" or ":[addr]*r": execute register 9454 */ 9455 static void 9456 ex_at(exarg_T *eap) 9457 { 9458 int c; 9459 int prev_len = typebuf.tb_len; 9460 9461 curwin->w_cursor.lnum = eap->line2; 9462 check_cursor_col(); 9463 9464 #ifdef USE_ON_FLY_SCROLL 9465 dont_scroll = TRUE; /* disallow scrolling here */ 9466 #endif 9467 9468 /* get the register name. No name means to use the previous one */ 9469 c = *eap->arg; 9470 if (c == NUL || (c == '*' && *eap->cmd == '*')) 9471 c = '@'; 9472 /* Put the register in the typeahead buffer with the "silent" flag. */ 9473 if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL, TRUE) 9474 == FAIL) 9475 { 9476 beep_flush(); 9477 } 9478 else 9479 { 9480 int save_efr = exec_from_reg; 9481 9482 exec_from_reg = TRUE; 9483 9484 /* 9485 * Execute from the typeahead buffer. 9486 * Continue until the stuff buffer is empty and all added characters 9487 * have been consumed. 9488 */ 9489 while (!stuff_empty() || typebuf.tb_len > prev_len) 9490 (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE); 9491 9492 exec_from_reg = save_efr; 9493 } 9494 } 9495 9496 /* 9497 * ":!". 9498 */ 9499 static void 9500 ex_bang(exarg_T *eap) 9501 { 9502 do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE); 9503 } 9504 9505 /* 9506 * ":undo". 9507 */ 9508 static void 9509 ex_undo(exarg_T *eap) 9510 { 9511 if (eap->addr_count == 1) /* :undo 123 */ 9512 undo_time(eap->line2, FALSE, FALSE, TRUE); 9513 else 9514 u_undo(1); 9515 } 9516 9517 #ifdef FEAT_PERSISTENT_UNDO 9518 static void 9519 ex_wundo(exarg_T *eap) 9520 { 9521 char_u hash[UNDO_HASH_SIZE]; 9522 9523 u_compute_hash(hash); 9524 u_write_undo(eap->arg, eap->forceit, curbuf, hash); 9525 } 9526 9527 static void 9528 ex_rundo(exarg_T *eap) 9529 { 9530 char_u hash[UNDO_HASH_SIZE]; 9531 9532 u_compute_hash(hash); 9533 u_read_undo(eap->arg, hash, NULL); 9534 } 9535 #endif 9536 9537 /* 9538 * ":redo". 9539 */ 9540 static void 9541 ex_redo(exarg_T *eap UNUSED) 9542 { 9543 u_redo(1); 9544 } 9545 9546 /* 9547 * ":earlier" and ":later". 9548 */ 9549 static void 9550 ex_later(exarg_T *eap) 9551 { 9552 long count = 0; 9553 int sec = FALSE; 9554 int file = FALSE; 9555 char_u *p = eap->arg; 9556 9557 if (*p == NUL) 9558 count = 1; 9559 else if (isdigit(*p)) 9560 { 9561 count = getdigits(&p); 9562 switch (*p) 9563 { 9564 case 's': ++p; sec = TRUE; break; 9565 case 'm': ++p; sec = TRUE; count *= 60; break; 9566 case 'h': ++p; sec = TRUE; count *= 60 * 60; break; 9567 case 'd': ++p; sec = TRUE; count *= 24 * 60 * 60; break; 9568 case 'f': ++p; file = TRUE; break; 9569 } 9570 } 9571 9572 if (*p != NUL) 9573 EMSG2(_(e_invarg2), eap->arg); 9574 else 9575 undo_time(eap->cmdidx == CMD_earlier ? -count : count, 9576 sec, file, FALSE); 9577 } 9578 9579 /* 9580 * ":redir": start/stop redirection. 9581 */ 9582 static void 9583 ex_redir(exarg_T *eap) 9584 { 9585 char *mode; 9586 char_u *fname; 9587 char_u *arg = eap->arg; 9588 9589 #ifdef FEAT_EVAL 9590 if (redir_execute) 9591 { 9592 EMSG(_("E930: Cannot use :redir inside execute()")); 9593 return; 9594 } 9595 #endif 9596 9597 if (STRICMP(eap->arg, "END") == 0) 9598 close_redir(); 9599 else 9600 { 9601 if (*arg == '>') 9602 { 9603 ++arg; 9604 if (*arg == '>') 9605 { 9606 ++arg; 9607 mode = "a"; 9608 } 9609 else 9610 mode = "w"; 9611 arg = skipwhite(arg); 9612 9613 close_redir(); 9614 9615 /* Expand environment variables and "~/". */ 9616 fname = expand_env_save(arg); 9617 if (fname == NULL) 9618 return; 9619 #ifdef FEAT_BROWSE 9620 if (cmdmod.browse) 9621 { 9622 char_u *browseFile; 9623 9624 browseFile = do_browse(BROWSE_SAVE, 9625 (char_u *)_("Save Redirection"), 9626 fname, NULL, NULL, BROWSE_FILTER_ALL_FILES, curbuf); 9627 if (browseFile == NULL) 9628 return; /* operation cancelled */ 9629 vim_free(fname); 9630 fname = browseFile; 9631 eap->forceit = TRUE; /* since dialog already asked */ 9632 } 9633 #endif 9634 9635 redir_fd = open_exfile(fname, eap->forceit, mode); 9636 vim_free(fname); 9637 } 9638 #ifdef FEAT_EVAL 9639 else if (*arg == '@') 9640 { 9641 /* redirect to a register a-z (resp. A-Z for appending) */ 9642 close_redir(); 9643 ++arg; 9644 if (ASCII_ISALPHA(*arg) 9645 # ifdef FEAT_CLIPBOARD 9646 || *arg == '*' 9647 || *arg == '+' 9648 # endif 9649 || *arg == '"') 9650 { 9651 redir_reg = *arg++; 9652 if (*arg == '>' && arg[1] == '>') /* append */ 9653 arg += 2; 9654 else 9655 { 9656 /* Can use both "@a" and "@a>". */ 9657 if (*arg == '>') 9658 arg++; 9659 /* Make register empty when not using @A-@Z and the 9660 * command is valid. */ 9661 if (*arg == NUL && !isupper(redir_reg)) 9662 write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); 9663 } 9664 } 9665 if (*arg != NUL) 9666 { 9667 redir_reg = 0; 9668 EMSG2(_(e_invarg2), eap->arg); 9669 } 9670 } 9671 else if (*arg == '=' && arg[1] == '>') 9672 { 9673 int append; 9674 9675 /* redirect to a variable */ 9676 close_redir(); 9677 arg += 2; 9678 9679 if (*arg == '>') 9680 { 9681 ++arg; 9682 append = TRUE; 9683 } 9684 else 9685 append = FALSE; 9686 9687 if (var_redir_start(skipwhite(arg), append) == OK) 9688 redir_vname = 1; 9689 } 9690 #endif 9691 9692 /* TODO: redirect to a buffer */ 9693 9694 else 9695 EMSG2(_(e_invarg2), eap->arg); 9696 } 9697 9698 /* Make sure redirection is not off. Can happen for cmdline completion 9699 * that indirectly invokes a command to catch its output. */ 9700 if (redir_fd != NULL 9701 #ifdef FEAT_EVAL 9702 || redir_reg || redir_vname 9703 #endif 9704 ) 9705 redir_off = FALSE; 9706 } 9707 9708 /* 9709 * ":redraw": force redraw 9710 */ 9711 void 9712 ex_redraw(exarg_T *eap) 9713 { 9714 int r = RedrawingDisabled; 9715 int p = p_lz; 9716 9717 RedrawingDisabled = 0; 9718 p_lz = FALSE; 9719 validate_cursor(); 9720 update_topline(); 9721 update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : 0); 9722 #ifdef FEAT_TITLE 9723 if (need_maketitle) 9724 maketitle(); 9725 #endif 9726 RedrawingDisabled = r; 9727 p_lz = p; 9728 9729 /* Reset msg_didout, so that a message that's there is overwritten. */ 9730 msg_didout = FALSE; 9731 msg_col = 0; 9732 9733 /* No need to wait after an intentional redraw. */ 9734 need_wait_return = FALSE; 9735 9736 out_flush(); 9737 } 9738 9739 /* 9740 * ":redrawstatus": force redraw of status line(s) 9741 */ 9742 static void 9743 ex_redrawstatus(exarg_T *eap UNUSED) 9744 { 9745 int r = RedrawingDisabled; 9746 int p = p_lz; 9747 9748 RedrawingDisabled = 0; 9749 p_lz = FALSE; 9750 if (eap->forceit) 9751 status_redraw_all(); 9752 else 9753 status_redraw_curbuf(); 9754 update_screen(VIsual_active ? INVERTED : 0); 9755 RedrawingDisabled = r; 9756 p_lz = p; 9757 out_flush(); 9758 } 9759 9760 static void 9761 close_redir(void) 9762 { 9763 if (redir_fd != NULL) 9764 { 9765 fclose(redir_fd); 9766 redir_fd = NULL; 9767 } 9768 #ifdef FEAT_EVAL 9769 redir_reg = 0; 9770 if (redir_vname) 9771 { 9772 var_redir_stop(); 9773 redir_vname = 0; 9774 } 9775 #endif 9776 } 9777 9778 #if defined(FEAT_SESSION) && defined(USE_CRNL) 9779 # define MKSESSION_NL 9780 static int mksession_nl = FALSE; /* use NL only in put_eol() */ 9781 #endif 9782 9783 /* 9784 * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession". 9785 */ 9786 static void 9787 ex_mkrc( 9788 exarg_T *eap) 9789 { 9790 FILE *fd; 9791 int failed = FALSE; 9792 char_u *fname; 9793 #ifdef FEAT_BROWSE 9794 char_u *browseFile = NULL; 9795 #endif 9796 #ifdef FEAT_SESSION 9797 int view_session = FALSE; 9798 int using_vdir = FALSE; /* using 'viewdir'? */ 9799 char_u *viewFile = NULL; 9800 unsigned *flagp; 9801 #endif 9802 9803 if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview) 9804 { 9805 #ifdef FEAT_SESSION 9806 view_session = TRUE; 9807 #else 9808 ex_ni(eap); 9809 return; 9810 #endif 9811 } 9812 9813 #ifdef FEAT_SESSION 9814 /* Use the short file name until ":lcd" is used. We also don't use the 9815 * short file name when 'acd' is set, that is checked later. */ 9816 did_lcd = FALSE; 9817 9818 /* ":mkview" or ":mkview 9": generate file name with 'viewdir' */ 9819 if (eap->cmdidx == CMD_mkview 9820 && (*eap->arg == NUL 9821 || (vim_isdigit(*eap->arg) && eap->arg[1] == NUL))) 9822 { 9823 eap->forceit = TRUE; 9824 fname = get_view_file(*eap->arg); 9825 if (fname == NULL) 9826 return; 9827 viewFile = fname; 9828 using_vdir = TRUE; 9829 } 9830 else 9831 #endif 9832 if (*eap->arg != NUL) 9833 fname = eap->arg; 9834 else if (eap->cmdidx == CMD_mkvimrc) 9835 fname = (char_u *)VIMRC_FILE; 9836 #ifdef FEAT_SESSION 9837 else if (eap->cmdidx == CMD_mksession) 9838 fname = (char_u *)SESSION_FILE; 9839 #endif 9840 else 9841 fname = (char_u *)EXRC_FILE; 9842 9843 #ifdef FEAT_BROWSE 9844 if (cmdmod.browse) 9845 { 9846 browseFile = do_browse(BROWSE_SAVE, 9847 # ifdef FEAT_SESSION 9848 eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") : 9849 eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") : 9850 # endif 9851 (char_u *)_("Save Setup"), 9852 fname, (char_u *)"vim", NULL, BROWSE_FILTER_MACROS, NULL); 9853 if (browseFile == NULL) 9854 goto theend; 9855 fname = browseFile; 9856 eap->forceit = TRUE; /* since dialog already asked */ 9857 } 9858 #endif 9859 9860 #if defined(FEAT_SESSION) && defined(vim_mkdir) 9861 /* When using 'viewdir' may have to create the directory. */ 9862 if (using_vdir && !mch_isdir(p_vdir)) 9863 vim_mkdir_emsg(p_vdir, 0755); 9864 #endif 9865 9866 fd = open_exfile(fname, eap->forceit, WRITEBIN); 9867 if (fd != NULL) 9868 { 9869 #ifdef FEAT_SESSION 9870 if (eap->cmdidx == CMD_mkview) 9871 flagp = &vop_flags; 9872 else 9873 flagp = &ssop_flags; 9874 #endif 9875 9876 #ifdef MKSESSION_NL 9877 /* "unix" in 'sessionoptions': use NL line separator */ 9878 if (view_session && (*flagp & SSOP_UNIX)) 9879 mksession_nl = TRUE; 9880 #endif 9881 9882 /* Write the version command for :mkvimrc */ 9883 if (eap->cmdidx == CMD_mkvimrc) 9884 (void)put_line(fd, "version 6.0"); 9885 9886 #ifdef FEAT_SESSION 9887 if (eap->cmdidx == CMD_mksession) 9888 { 9889 if (put_line(fd, "let SessionLoad = 1") == FAIL) 9890 failed = TRUE; 9891 } 9892 9893 if (eap->cmdidx != CMD_mkview) 9894 #endif 9895 { 9896 /* Write setting 'compatible' first, because it has side effects. 9897 * For that same reason only do it when needed. */ 9898 if (p_cp) 9899 (void)put_line(fd, "if !&cp | set cp | endif"); 9900 else 9901 (void)put_line(fd, "if &cp | set nocp | endif"); 9902 } 9903 9904 #ifdef FEAT_SESSION 9905 if (!view_session 9906 || (eap->cmdidx == CMD_mksession 9907 && (*flagp & SSOP_OPTIONS))) 9908 #endif 9909 failed |= (makemap(fd, NULL) == FAIL 9910 || makeset(fd, OPT_GLOBAL, FALSE) == FAIL); 9911 9912 #ifdef FEAT_SESSION 9913 if (!failed && view_session) 9914 { 9915 if (put_line(fd, "let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0") == FAIL) 9916 failed = TRUE; 9917 if (eap->cmdidx == CMD_mksession) 9918 { 9919 char_u *dirnow; /* current directory */ 9920 9921 dirnow = alloc(MAXPATHL); 9922 if (dirnow == NULL) 9923 failed = TRUE; 9924 else 9925 { 9926 /* 9927 * Change to session file's dir. 9928 */ 9929 if (mch_dirname(dirnow, MAXPATHL) == FAIL 9930 || mch_chdir((char *)dirnow) != 0) 9931 *dirnow = NUL; 9932 if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) 9933 { 9934 if (vim_chdirfile(fname) == OK) 9935 shorten_fnames(TRUE); 9936 } 9937 else if (*dirnow != NUL 9938 && (ssop_flags & SSOP_CURDIR) && globaldir != NULL) 9939 { 9940 if (mch_chdir((char *)globaldir) == 0) 9941 shorten_fnames(TRUE); 9942 } 9943 9944 failed |= (makeopens(fd, dirnow) == FAIL); 9945 9946 /* restore original dir */ 9947 if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR) 9948 || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL))) 9949 { 9950 if (mch_chdir((char *)dirnow) != 0) 9951 EMSG(_(e_prev_dir)); 9952 shorten_fnames(TRUE); 9953 } 9954 vim_free(dirnow); 9955 } 9956 } 9957 else 9958 { 9959 failed |= (put_view(fd, curwin, !using_vdir, flagp, 9960 -1) == FAIL); 9961 } 9962 if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save") 9963 == FAIL) 9964 failed = TRUE; 9965 if (put_line(fd, "doautoall SessionLoadPost") == FAIL) 9966 failed = TRUE; 9967 if (eap->cmdidx == CMD_mksession) 9968 { 9969 if (put_line(fd, "unlet SessionLoad") == FAIL) 9970 failed = TRUE; 9971 } 9972 } 9973 #endif 9974 if (put_line(fd, "\" vim: set ft=vim :") == FAIL) 9975 failed = TRUE; 9976 9977 failed |= fclose(fd); 9978 9979 if (failed) 9980 EMSG(_(e_write)); 9981 #if defined(FEAT_EVAL) && defined(FEAT_SESSION) 9982 else if (eap->cmdidx == CMD_mksession) 9983 { 9984 /* successful session write - set this_session var */ 9985 char_u *tbuf; 9986 9987 tbuf = alloc(MAXPATHL); 9988 if (tbuf != NULL) 9989 { 9990 if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK) 9991 set_vim_var_string(VV_THIS_SESSION, tbuf, -1); 9992 vim_free(tbuf); 9993 } 9994 } 9995 #endif 9996 #ifdef MKSESSION_NL 9997 mksession_nl = FALSE; 9998 #endif 9999 } 10000 10001 #ifdef FEAT_BROWSE 10002 theend: 10003 vim_free(browseFile); 10004 #endif 10005 #ifdef FEAT_SESSION 10006 vim_free(viewFile); 10007 #endif 10008 } 10009 10010 #if ((defined(FEAT_SESSION) || defined(FEAT_EVAL)) && defined(vim_mkdir)) \ 10011 || defined(PROTO) 10012 int 10013 vim_mkdir_emsg(char_u *name, int prot) 10014 { 10015 if (vim_mkdir(name, prot) != 0) 10016 { 10017 EMSG2(_("E739: Cannot create directory: %s"), name); 10018 return FAIL; 10019 } 10020 return OK; 10021 } 10022 #endif 10023 10024 /* 10025 * Open a file for writing for an Ex command, with some checks. 10026 * Return file descriptor, or NULL on failure. 10027 */ 10028 FILE * 10029 open_exfile( 10030 char_u *fname, 10031 int forceit, 10032 char *mode) /* "w" for create new file or "a" for append */ 10033 { 10034 FILE *fd; 10035 10036 #ifdef UNIX 10037 /* with Unix it is possible to open a directory */ 10038 if (mch_isdir(fname)) 10039 { 10040 EMSG2(_(e_isadir2), fname); 10041 return NULL; 10042 } 10043 #endif 10044 if (!forceit && *mode != 'a' && vim_fexists(fname)) 10045 { 10046 EMSG2(_("E189: \"%s\" exists (add ! to override)"), fname); 10047 return NULL; 10048 } 10049 10050 if ((fd = mch_fopen((char *)fname, mode)) == NULL) 10051 EMSG2(_("E190: Cannot open \"%s\" for writing"), fname); 10052 10053 return fd; 10054 } 10055 10056 /* 10057 * ":mark" and ":k". 10058 */ 10059 static void 10060 ex_mark(exarg_T *eap) 10061 { 10062 pos_T pos; 10063 10064 if (*eap->arg == NUL) /* No argument? */ 10065 EMSG(_(e_argreq)); 10066 else if (eap->arg[1] != NUL) /* more than one character? */ 10067 EMSG(_(e_trailing)); 10068 else 10069 { 10070 pos = curwin->w_cursor; /* save curwin->w_cursor */ 10071 curwin->w_cursor.lnum = eap->line2; 10072 beginline(BL_WHITE | BL_FIX); 10073 if (setmark(*eap->arg) == FAIL) /* set mark */ 10074 EMSG(_("E191: Argument must be a letter or forward/backward quote")); 10075 curwin->w_cursor = pos; /* restore curwin->w_cursor */ 10076 } 10077 } 10078 10079 /* 10080 * Update w_topline, w_leftcol and the cursor position. 10081 */ 10082 void 10083 update_topline_cursor(void) 10084 { 10085 check_cursor(); /* put cursor on valid line */ 10086 update_topline(); 10087 if (!curwin->w_p_wrap) 10088 validate_cursor(); 10089 update_curswant(); 10090 } 10091 10092 /* 10093 * Save the current State and go to Normal mode. 10094 * Return TRUE if the typeahead could be saved. 10095 */ 10096 int 10097 save_current_state(save_state_T *sst) 10098 { 10099 sst->save_msg_scroll = msg_scroll; 10100 sst->save_restart_edit = restart_edit; 10101 sst->save_msg_didout = msg_didout; 10102 sst->save_State = State; 10103 sst->save_insertmode = p_im; 10104 sst->save_finish_op = finish_op; 10105 sst->save_opcount = opcount; 10106 10107 msg_scroll = FALSE; /* no msg scrolling in Normal mode */ 10108 restart_edit = 0; /* don't go to Insert mode */ 10109 p_im = FALSE; /* don't use 'insertmode' */ 10110 10111 /* 10112 * Save the current typeahead. This is required to allow using ":normal" 10113 * from an event handler and makes sure we don't hang when the argument 10114 * ends with half a command. 10115 */ 10116 save_typeahead(&sst->tabuf); 10117 return sst->tabuf.typebuf_valid; 10118 } 10119 10120 void 10121 restore_current_state(save_state_T *sst) 10122 { 10123 /* Restore the previous typeahead. */ 10124 restore_typeahead(&sst->tabuf); 10125 10126 msg_scroll = sst->save_msg_scroll; 10127 restart_edit = sst->save_restart_edit; 10128 p_im = sst->save_insertmode; 10129 finish_op = sst->save_finish_op; 10130 opcount = sst->save_opcount; 10131 msg_didout |= sst->save_msg_didout; /* don't reset msg_didout now */ 10132 10133 /* Restore the state (needed when called from a function executed for 10134 * 'indentexpr'). Update the mouse and cursor, they may have changed. */ 10135 State = sst->save_State; 10136 #ifdef CURSOR_SHAPE 10137 ui_cursor_shape(); /* may show different cursor shape */ 10138 #endif 10139 } 10140 10141 /* 10142 * ":normal[!] {commands}": Execute normal mode commands. 10143 */ 10144 void 10145 ex_normal(exarg_T *eap) 10146 { 10147 save_state_T save_state; 10148 #ifdef FEAT_MBYTE 10149 char_u *arg = NULL; 10150 int l; 10151 char_u *p; 10152 #endif 10153 10154 if (ex_normal_lock > 0) 10155 { 10156 EMSG(_(e_secure)); 10157 return; 10158 } 10159 if (ex_normal_busy >= p_mmd) 10160 { 10161 EMSG(_("E192: Recursive use of :normal too deep")); 10162 return; 10163 } 10164 10165 #ifdef FEAT_MBYTE 10166 /* 10167 * vgetc() expects a CSI and K_SPECIAL to have been escaped. Don't do 10168 * this for the K_SPECIAL leading byte, otherwise special keys will not 10169 * work. 10170 */ 10171 if (has_mbyte) 10172 { 10173 int len = 0; 10174 10175 /* Count the number of characters to be escaped. */ 10176 for (p = eap->arg; *p != NUL; ++p) 10177 { 10178 # ifdef FEAT_GUI 10179 if (*p == CSI) /* leadbyte CSI */ 10180 len += 2; 10181 # endif 10182 for (l = (*mb_ptr2len)(p) - 1; l > 0; --l) 10183 if (*++p == K_SPECIAL /* trailbyte K_SPECIAL or CSI */ 10184 # ifdef FEAT_GUI 10185 || *p == CSI 10186 # endif 10187 ) 10188 len += 2; 10189 } 10190 if (len > 0) 10191 { 10192 arg = alloc((unsigned)(STRLEN(eap->arg) + len + 1)); 10193 if (arg != NULL) 10194 { 10195 len = 0; 10196 for (p = eap->arg; *p != NUL; ++p) 10197 { 10198 arg[len++] = *p; 10199 # ifdef FEAT_GUI 10200 if (*p == CSI) 10201 { 10202 arg[len++] = KS_EXTRA; 10203 arg[len++] = (int)KE_CSI; 10204 } 10205 # endif 10206 for (l = (*mb_ptr2len)(p) - 1; l > 0; --l) 10207 { 10208 arg[len++] = *++p; 10209 if (*p == K_SPECIAL) 10210 { 10211 arg[len++] = KS_SPECIAL; 10212 arg[len++] = KE_FILLER; 10213 } 10214 # ifdef FEAT_GUI 10215 else if (*p == CSI) 10216 { 10217 arg[len++] = KS_EXTRA; 10218 arg[len++] = (int)KE_CSI; 10219 } 10220 # endif 10221 } 10222 arg[len] = NUL; 10223 } 10224 } 10225 } 10226 } 10227 #endif 10228 10229 ++ex_normal_busy; 10230 if (save_current_state(&save_state)) 10231 { 10232 /* 10233 * Repeat the :normal command for each line in the range. When no 10234 * range given, execute it just once, without positioning the cursor 10235 * first. 10236 */ 10237 do 10238 { 10239 if (eap->addr_count != 0) 10240 { 10241 curwin->w_cursor.lnum = eap->line1++; 10242 curwin->w_cursor.col = 0; 10243 check_cursor_moved(curwin); 10244 } 10245 10246 exec_normal_cmd( 10247 #ifdef FEAT_MBYTE 10248 arg != NULL ? arg : 10249 #endif 10250 eap->arg, eap->forceit ? REMAP_NONE : REMAP_YES, FALSE); 10251 } 10252 while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int); 10253 } 10254 10255 /* Might not return to the main loop when in an event handler. */ 10256 update_topline_cursor(); 10257 10258 restore_current_state(&save_state); 10259 --ex_normal_busy; 10260 #ifdef FEAT_MOUSE 10261 setmouse(); 10262 #endif 10263 #ifdef CURSOR_SHAPE 10264 ui_cursor_shape(); /* may show different cursor shape */ 10265 #endif 10266 10267 #ifdef FEAT_MBYTE 10268 vim_free(arg); 10269 #endif 10270 } 10271 10272 /* 10273 * ":startinsert", ":startreplace" and ":startgreplace" 10274 */ 10275 static void 10276 ex_startinsert(exarg_T *eap) 10277 { 10278 if (eap->forceit) 10279 { 10280 /* cursor line can be zero on startup */ 10281 if (!curwin->w_cursor.lnum) 10282 curwin->w_cursor.lnum = 1; 10283 coladvance((colnr_T)MAXCOL); 10284 curwin->w_curswant = MAXCOL; 10285 curwin->w_set_curswant = FALSE; 10286 } 10287 10288 /* Ignore the command when already in Insert mode. Inserting an 10289 * expression register that invokes a function can do this. */ 10290 if (State & INSERT) 10291 return; 10292 10293 if (eap->cmdidx == CMD_startinsert) 10294 restart_edit = 'a'; 10295 else if (eap->cmdidx == CMD_startreplace) 10296 restart_edit = 'R'; 10297 else 10298 restart_edit = 'V'; 10299 10300 if (!eap->forceit) 10301 { 10302 if (eap->cmdidx == CMD_startinsert) 10303 restart_edit = 'i'; 10304 curwin->w_curswant = 0; /* avoid MAXCOL */ 10305 } 10306 } 10307 10308 /* 10309 * ":stopinsert" 10310 */ 10311 static void 10312 ex_stopinsert(exarg_T *eap UNUSED) 10313 { 10314 restart_edit = 0; 10315 stop_insert_mode = TRUE; 10316 clearmode(); 10317 } 10318 10319 /* 10320 * Execute normal mode command "cmd". 10321 * "remap" can be REMAP_NONE or REMAP_YES. 10322 */ 10323 void 10324 exec_normal_cmd(char_u *cmd, int remap, int silent) 10325 { 10326 /* Stuff the argument into the typeahead buffer. */ 10327 ins_typebuf(cmd, remap, 0, TRUE, silent); 10328 exec_normal(FALSE); 10329 } 10330 10331 /* 10332 * Execute normal_cmd() until there is no typeahead left. 10333 */ 10334 void 10335 exec_normal(int was_typed) 10336 { 10337 oparg_T oa; 10338 10339 clear_oparg(&oa); 10340 finish_op = FALSE; 10341 while ((!stuff_empty() || ((was_typed || !typebuf_typed()) 10342 && typebuf.tb_len > 0)) && !got_int) 10343 { 10344 update_topline_cursor(); 10345 normal_cmd(&oa, TRUE); /* execute a Normal mode cmd */ 10346 } 10347 } 10348 10349 #ifdef FEAT_FIND_ID 10350 static void 10351 ex_checkpath(exarg_T *eap) 10352 { 10353 find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L, 10354 eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW, 10355 (linenr_T)1, (linenr_T)MAXLNUM); 10356 } 10357 10358 #if defined(FEAT_QUICKFIX) 10359 /* 10360 * ":psearch" 10361 */ 10362 static void 10363 ex_psearch(exarg_T *eap) 10364 { 10365 g_do_tagpreview = p_pvh; 10366 ex_findpat(eap); 10367 g_do_tagpreview = 0; 10368 } 10369 #endif 10370 10371 static void 10372 ex_findpat(exarg_T *eap) 10373 { 10374 int whole = TRUE; 10375 long n; 10376 char_u *p; 10377 int action; 10378 10379 switch (cmdnames[eap->cmdidx].cmd_name[2]) 10380 { 10381 case 'e': /* ":psearch", ":isearch" and ":dsearch" */ 10382 if (cmdnames[eap->cmdidx].cmd_name[0] == 'p') 10383 action = ACTION_GOTO; 10384 else 10385 action = ACTION_SHOW; 10386 break; 10387 case 'i': /* ":ilist" and ":dlist" */ 10388 action = ACTION_SHOW_ALL; 10389 break; 10390 case 'u': /* ":ijump" and ":djump" */ 10391 action = ACTION_GOTO; 10392 break; 10393 default: /* ":isplit" and ":dsplit" */ 10394 action = ACTION_SPLIT; 10395 break; 10396 } 10397 10398 n = 1; 10399 if (vim_isdigit(*eap->arg)) /* get count */ 10400 { 10401 n = getdigits(&eap->arg); 10402 eap->arg = skipwhite(eap->arg); 10403 } 10404 if (*eap->arg == '/') /* Match regexp, not just whole words */ 10405 { 10406 whole = FALSE; 10407 ++eap->arg; 10408 p = skip_regexp(eap->arg, '/', p_magic, NULL); 10409 if (*p) 10410 { 10411 *p++ = NUL; 10412 p = skipwhite(p); 10413 10414 /* Check for trailing illegal characters */ 10415 if (!ends_excmd(*p)) 10416 eap->errmsg = e_trailing; 10417 else 10418 eap->nextcmd = check_nextcmd(p); 10419 } 10420 } 10421 if (!eap->skip) 10422 find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg), 10423 whole, !eap->forceit, 10424 *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, 10425 n, action, eap->line1, eap->line2); 10426 } 10427 #endif 10428 10429 10430 #ifdef FEAT_QUICKFIX 10431 /* 10432 * ":ptag", ":ptselect", ":ptjump", ":ptnext", etc. 10433 */ 10434 static void 10435 ex_ptag(exarg_T *eap) 10436 { 10437 g_do_tagpreview = p_pvh; /* will be reset to 0 in ex_tag_cmd() */ 10438 ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1); 10439 } 10440 10441 /* 10442 * ":pedit" 10443 */ 10444 static void 10445 ex_pedit(exarg_T *eap) 10446 { 10447 win_T *curwin_save = curwin; 10448 10449 g_do_tagpreview = p_pvh; 10450 prepare_tagpreview(TRUE); 10451 keep_help_flag = bt_help(curwin_save->w_buffer); 10452 do_exedit(eap, NULL); 10453 keep_help_flag = FALSE; 10454 if (curwin != curwin_save && win_valid(curwin_save)) 10455 { 10456 /* Return cursor to where we were */ 10457 validate_cursor(); 10458 redraw_later(VALID); 10459 win_enter(curwin_save, TRUE); 10460 } 10461 g_do_tagpreview = 0; 10462 } 10463 #endif 10464 10465 /* 10466 * ":stag", ":stselect" and ":stjump". 10467 */ 10468 static void 10469 ex_stag(exarg_T *eap) 10470 { 10471 postponed_split = -1; 10472 postponed_split_flags = cmdmod.split; 10473 postponed_split_tab = cmdmod.tab; 10474 ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1); 10475 postponed_split_flags = 0; 10476 postponed_split_tab = 0; 10477 } 10478 10479 /* 10480 * ":tag", ":tselect", ":tjump", ":tnext", etc. 10481 */ 10482 static void 10483 ex_tag(exarg_T *eap) 10484 { 10485 ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name); 10486 } 10487 10488 static void 10489 ex_tag_cmd(exarg_T *eap, char_u *name) 10490 { 10491 int cmd; 10492 10493 switch (name[1]) 10494 { 10495 case 'j': cmd = DT_JUMP; /* ":tjump" */ 10496 break; 10497 case 's': cmd = DT_SELECT; /* ":tselect" */ 10498 break; 10499 case 'p': cmd = DT_PREV; /* ":tprevious" */ 10500 break; 10501 case 'N': cmd = DT_PREV; /* ":tNext" */ 10502 break; 10503 case 'n': cmd = DT_NEXT; /* ":tnext" */ 10504 break; 10505 case 'o': cmd = DT_POP; /* ":pop" */ 10506 break; 10507 case 'f': /* ":tfirst" */ 10508 case 'r': cmd = DT_FIRST; /* ":trewind" */ 10509 break; 10510 case 'l': cmd = DT_LAST; /* ":tlast" */ 10511 break; 10512 default: /* ":tag" */ 10513 #ifdef FEAT_CSCOPE 10514 if (p_cst && *eap->arg != NUL) 10515 { 10516 ex_cstag(eap); 10517 return; 10518 } 10519 #endif 10520 cmd = DT_TAG; 10521 break; 10522 } 10523 10524 if (name[0] == 'l') 10525 { 10526 #ifndef FEAT_QUICKFIX 10527 ex_ni(eap); 10528 return; 10529 #else 10530 cmd = DT_LTAG; 10531 #endif 10532 } 10533 10534 do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1, 10535 eap->forceit, TRUE); 10536 } 10537 10538 /* 10539 * Check "str" for starting with a special cmdline variable. 10540 * If found return one of the SPEC_ values and set "*usedlen" to the length of 10541 * the variable. Otherwise return -1 and "*usedlen" is unchanged. 10542 */ 10543 int 10544 find_cmdline_var(char_u *src, int *usedlen) 10545 { 10546 int len; 10547 int i; 10548 static char *(spec_str[]) = { 10549 "%", 10550 #define SPEC_PERC 0 10551 "#", 10552 #define SPEC_HASH (SPEC_PERC + 1) 10553 "<cword>", /* cursor word */ 10554 #define SPEC_CWORD (SPEC_HASH + 1) 10555 "<cWORD>", /* cursor WORD */ 10556 #define SPEC_CCWORD (SPEC_CWORD + 1) 10557 "<cexpr>", /* expr under cursor */ 10558 #define SPEC_CEXPR (SPEC_CCWORD + 1) 10559 "<cfile>", /* cursor path name */ 10560 #define SPEC_CFILE (SPEC_CEXPR + 1) 10561 "<sfile>", /* ":so" file name */ 10562 #define SPEC_SFILE (SPEC_CFILE + 1) 10563 "<slnum>", /* ":so" file line number */ 10564 #define SPEC_SLNUM (SPEC_SFILE + 1) 10565 #ifdef FEAT_AUTOCMD 10566 "<afile>", /* autocommand file name */ 10567 # define SPEC_AFILE (SPEC_SLNUM + 1) 10568 "<abuf>", /* autocommand buffer number */ 10569 # define SPEC_ABUF (SPEC_AFILE + 1) 10570 "<amatch>", /* autocommand match name */ 10571 # define SPEC_AMATCH (SPEC_ABUF + 1) 10572 #endif 10573 #ifdef FEAT_CLIENTSERVER 10574 "<client>" 10575 # ifdef FEAT_AUTOCMD 10576 # define SPEC_CLIENT (SPEC_AMATCH + 1) 10577 # else 10578 # define SPEC_CLIENT (SPEC_SLNUM + 1) 10579 # endif 10580 #endif 10581 }; 10582 10583 for (i = 0; i < (int)(sizeof(spec_str) / sizeof(char *)); ++i) 10584 { 10585 len = (int)STRLEN(spec_str[i]); 10586 if (STRNCMP(src, spec_str[i], len) == 0) 10587 { 10588 *usedlen = len; 10589 return i; 10590 } 10591 } 10592 return -1; 10593 } 10594 10595 /* 10596 * Evaluate cmdline variables. 10597 * 10598 * change '%' to curbuf->b_ffname 10599 * '#' to curwin->w_altfile 10600 * '<cword>' to word under the cursor 10601 * '<cWORD>' to WORD under the cursor 10602 * '<cfile>' to path name under the cursor 10603 * '<sfile>' to sourced file name 10604 * '<slnum>' to sourced file line number 10605 * '<afile>' to file name for autocommand 10606 * '<abuf>' to buffer number for autocommand 10607 * '<amatch>' to matching name for autocommand 10608 * 10609 * When an error is detected, "errormsg" is set to a non-NULL pointer (may be 10610 * "" for error without a message) and NULL is returned. 10611 * Returns an allocated string if a valid match was found. 10612 * Returns NULL if no match was found. "usedlen" then still contains the 10613 * number of characters to skip. 10614 */ 10615 char_u * 10616 eval_vars( 10617 char_u *src, /* pointer into commandline */ 10618 char_u *srcstart, /* beginning of valid memory for src */ 10619 int *usedlen, /* characters after src that are used */ 10620 linenr_T *lnump, /* line number for :e command, or NULL */ 10621 char_u **errormsg, /* pointer to error message */ 10622 int *escaped) /* return value has escaped white space (can 10623 * be NULL) */ 10624 { 10625 int i; 10626 char_u *s; 10627 char_u *result; 10628 char_u *resultbuf = NULL; 10629 int resultlen; 10630 buf_T *buf; 10631 int valid = VALID_HEAD + VALID_PATH; /* assume valid result */ 10632 int spec_idx; 10633 #ifdef FEAT_MODIFY_FNAME 10634 int skip_mod = FALSE; 10635 #endif 10636 char_u strbuf[30]; 10637 10638 *errormsg = NULL; 10639 if (escaped != NULL) 10640 *escaped = FALSE; 10641 10642 /* 10643 * Check if there is something to do. 10644 */ 10645 spec_idx = find_cmdline_var(src, usedlen); 10646 if (spec_idx < 0) /* no match */ 10647 { 10648 *usedlen = 1; 10649 return NULL; 10650 } 10651 10652 /* 10653 * Skip when preceded with a backslash "\%" and "\#". 10654 * Note: In "\\%" the % is also not recognized! 10655 */ 10656 if (src > srcstart && src[-1] == '\\') 10657 { 10658 *usedlen = 0; 10659 STRMOVE(src - 1, src); /* remove backslash */ 10660 return NULL; 10661 } 10662 10663 /* 10664 * word or WORD under cursor 10665 */ 10666 if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD 10667 || spec_idx == SPEC_CEXPR) 10668 { 10669 resultlen = find_ident_under_cursor(&result, 10670 spec_idx == SPEC_CWORD ? (FIND_IDENT | FIND_STRING) 10671 : spec_idx == SPEC_CEXPR ? (FIND_IDENT | FIND_STRING | FIND_EVAL) 10672 : FIND_STRING); 10673 if (resultlen == 0) 10674 { 10675 *errormsg = (char_u *)""; 10676 return NULL; 10677 } 10678 } 10679 10680 /* 10681 * '#': Alternate file name 10682 * '%': Current file name 10683 * File name under the cursor 10684 * File name for autocommand 10685 * and following modifiers 10686 */ 10687 else 10688 { 10689 switch (spec_idx) 10690 { 10691 case SPEC_PERC: /* '%': current file */ 10692 if (curbuf->b_fname == NULL) 10693 { 10694 result = (char_u *)""; 10695 valid = 0; /* Must have ":p:h" to be valid */ 10696 } 10697 else 10698 result = curbuf->b_fname; 10699 break; 10700 10701 case SPEC_HASH: /* '#' or "#99": alternate file */ 10702 if (src[1] == '#') /* "##": the argument list */ 10703 { 10704 result = arg_all(); 10705 resultbuf = result; 10706 *usedlen = 2; 10707 if (escaped != NULL) 10708 *escaped = TRUE; 10709 #ifdef FEAT_MODIFY_FNAME 10710 skip_mod = TRUE; 10711 #endif 10712 break; 10713 } 10714 s = src + 1; 10715 if (*s == '<') /* "#<99" uses v:oldfiles */ 10716 ++s; 10717 i = (int)getdigits(&s); 10718 if (s == src + 2 && src[1] == '-') 10719 /* just a minus sign, don't skip over it */ 10720 s--; 10721 *usedlen = (int)(s - src); /* length of what we expand */ 10722 10723 if (src[1] == '<' && i != 0) 10724 { 10725 if (*usedlen < 2) 10726 { 10727 /* Should we give an error message for #<text? */ 10728 *usedlen = 1; 10729 return NULL; 10730 } 10731 #ifdef FEAT_EVAL 10732 result = list_find_str(get_vim_var_list(VV_OLDFILES), 10733 (long)i); 10734 if (result == NULL) 10735 { 10736 *errormsg = (char_u *)""; 10737 return NULL; 10738 } 10739 #else 10740 *errormsg = (char_u *)_("E809: #< is not available without the +eval feature"); 10741 return NULL; 10742 #endif 10743 } 10744 else 10745 { 10746 if (i == 0 && src[1] == '<' && *usedlen > 1) 10747 *usedlen = 1; 10748 buf = buflist_findnr(i); 10749 if (buf == NULL) 10750 { 10751 *errormsg = (char_u *)_("E194: No alternate file name to substitute for '#'"); 10752 return NULL; 10753 } 10754 if (lnump != NULL) 10755 *lnump = ECMD_LAST; 10756 if (buf->b_fname == NULL) 10757 { 10758 result = (char_u *)""; 10759 valid = 0; /* Must have ":p:h" to be valid */ 10760 } 10761 else 10762 result = buf->b_fname; 10763 } 10764 break; 10765 10766 #ifdef FEAT_SEARCHPATH 10767 case SPEC_CFILE: /* file name under cursor */ 10768 result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL); 10769 if (result == NULL) 10770 { 10771 *errormsg = (char_u *)""; 10772 return NULL; 10773 } 10774 resultbuf = result; /* remember allocated string */ 10775 break; 10776 #endif 10777 10778 #ifdef FEAT_AUTOCMD 10779 case SPEC_AFILE: /* file name for autocommand */ 10780 result = autocmd_fname; 10781 if (result != NULL && !autocmd_fname_full) 10782 { 10783 /* Still need to turn the fname into a full path. It is 10784 * postponed to avoid a delay when <afile> is not used. */ 10785 autocmd_fname_full = TRUE; 10786 result = FullName_save(autocmd_fname, FALSE); 10787 vim_free(autocmd_fname); 10788 autocmd_fname = result; 10789 } 10790 if (result == NULL) 10791 { 10792 *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"<afile>\""); 10793 return NULL; 10794 } 10795 result = shorten_fname1(result); 10796 break; 10797 10798 case SPEC_ABUF: /* buffer number for autocommand */ 10799 if (autocmd_bufnr <= 0) 10800 { 10801 *errormsg = (char_u *)_("E496: no autocommand buffer number to substitute for \"<abuf>\""); 10802 return NULL; 10803 } 10804 sprintf((char *)strbuf, "%d", autocmd_bufnr); 10805 result = strbuf; 10806 break; 10807 10808 case SPEC_AMATCH: /* match name for autocommand */ 10809 result = autocmd_match; 10810 if (result == NULL) 10811 { 10812 *errormsg = (char_u *)_("E497: no autocommand match name to substitute for \"<amatch>\""); 10813 return NULL; 10814 } 10815 break; 10816 10817 #endif 10818 case SPEC_SFILE: /* file name for ":so" command */ 10819 result = sourcing_name; 10820 if (result == NULL) 10821 { 10822 *errormsg = (char_u *)_("E498: no :source file name to substitute for \"<sfile>\""); 10823 return NULL; 10824 } 10825 break; 10826 case SPEC_SLNUM: /* line in file for ":so" command */ 10827 if (sourcing_name == NULL || sourcing_lnum == 0) 10828 { 10829 *errormsg = (char_u *)_("E842: no line number to use for \"<slnum>\""); 10830 return NULL; 10831 } 10832 sprintf((char *)strbuf, "%ld", (long)sourcing_lnum); 10833 result = strbuf; 10834 break; 10835 #if defined(FEAT_CLIENTSERVER) 10836 case SPEC_CLIENT: /* Source of last submitted input */ 10837 sprintf((char *)strbuf, PRINTF_HEX_LONG_U, 10838 (long_u)clientWindow); 10839 result = strbuf; 10840 break; 10841 #endif 10842 default: 10843 result = (char_u *)""; /* avoid gcc warning */ 10844 break; 10845 } 10846 10847 resultlen = (int)STRLEN(result); /* length of new string */ 10848 if (src[*usedlen] == '<') /* remove the file name extension */ 10849 { 10850 ++*usedlen; 10851 if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result)) 10852 resultlen = (int)(s - result); 10853 } 10854 #ifdef FEAT_MODIFY_FNAME 10855 else if (!skip_mod) 10856 { 10857 valid |= modify_fname(src, usedlen, &result, &resultbuf, 10858 &resultlen); 10859 if (result == NULL) 10860 { 10861 *errormsg = (char_u *)""; 10862 return NULL; 10863 } 10864 } 10865 #endif 10866 } 10867 10868 if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH) 10869 { 10870 if (valid != VALID_HEAD + VALID_PATH) 10871 /* xgettext:no-c-format */ 10872 *errormsg = (char_u *)_("E499: Empty file name for '%' or '#', only works with \":p:h\""); 10873 else 10874 *errormsg = (char_u *)_("E500: Evaluates to an empty string"); 10875 result = NULL; 10876 } 10877 else 10878 result = vim_strnsave(result, resultlen); 10879 vim_free(resultbuf); 10880 return result; 10881 } 10882 10883 /* 10884 * Concatenate all files in the argument list, separated by spaces, and return 10885 * it in one allocated string. 10886 * Spaces and backslashes in the file names are escaped with a backslash. 10887 * Returns NULL when out of memory. 10888 */ 10889 static char_u * 10890 arg_all(void) 10891 { 10892 int len; 10893 int idx; 10894 char_u *retval = NULL; 10895 char_u *p; 10896 10897 /* 10898 * Do this loop two times: 10899 * first time: compute the total length 10900 * second time: concatenate the names 10901 */ 10902 for (;;) 10903 { 10904 len = 0; 10905 for (idx = 0; idx < ARGCOUNT; ++idx) 10906 { 10907 p = alist_name(&ARGLIST[idx]); 10908 if (p != NULL) 10909 { 10910 if (len > 0) 10911 { 10912 /* insert a space in between names */ 10913 if (retval != NULL) 10914 retval[len] = ' '; 10915 ++len; 10916 } 10917 for ( ; *p != NUL; ++p) 10918 { 10919 if (*p == ' ' 10920 #ifndef BACKSLASH_IN_FILENAME 10921 || *p == '\\' 10922 #endif 10923 ) 10924 { 10925 /* insert a backslash */ 10926 if (retval != NULL) 10927 retval[len] = '\\'; 10928 ++len; 10929 } 10930 if (retval != NULL) 10931 retval[len] = *p; 10932 ++len; 10933 } 10934 } 10935 } 10936 10937 /* second time: break here */ 10938 if (retval != NULL) 10939 { 10940 retval[len] = NUL; 10941 break; 10942 } 10943 10944 /* allocate memory */ 10945 retval = alloc((unsigned)len + 1); 10946 if (retval == NULL) 10947 break; 10948 } 10949 10950 return retval; 10951 } 10952 10953 #if defined(FEAT_AUTOCMD) || defined(PROTO) 10954 /* 10955 * Expand the <sfile> string in "arg". 10956 * 10957 * Returns an allocated string, or NULL for any error. 10958 */ 10959 char_u * 10960 expand_sfile(char_u *arg) 10961 { 10962 char_u *errormsg; 10963 int len; 10964 char_u *result; 10965 char_u *newres; 10966 char_u *repl; 10967 int srclen; 10968 char_u *p; 10969 10970 result = vim_strsave(arg); 10971 if (result == NULL) 10972 return NULL; 10973 10974 for (p = result; *p; ) 10975 { 10976 if (STRNCMP(p, "<sfile>", 7) != 0) 10977 ++p; 10978 else 10979 { 10980 /* replace "<sfile>" with the sourced file name, and do ":" stuff */ 10981 repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL); 10982 if (errormsg != NULL) 10983 { 10984 if (*errormsg) 10985 emsg(errormsg); 10986 vim_free(result); 10987 return NULL; 10988 } 10989 if (repl == NULL) /* no match (cannot happen) */ 10990 { 10991 p += srclen; 10992 continue; 10993 } 10994 len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1; 10995 newres = alloc(len); 10996 if (newres == NULL) 10997 { 10998 vim_free(repl); 10999 vim_free(result); 11000 return NULL; 11001 } 11002 mch_memmove(newres, result, (size_t)(p - result)); 11003 STRCPY(newres + (p - result), repl); 11004 len = (int)STRLEN(newres); 11005 STRCAT(newres, p + srclen); 11006 vim_free(repl); 11007 vim_free(result); 11008 result = newres; 11009 p = newres + len; /* continue after the match */ 11010 } 11011 } 11012 11013 return result; 11014 } 11015 #endif 11016 11017 #ifdef FEAT_SESSION 11018 static int ses_winsizes(FILE *fd, int restore_size, 11019 win_T *tab_firstwin); 11020 static int ses_win_rec(FILE *fd, frame_T *fr); 11021 static frame_T *ses_skipframe(frame_T *fr); 11022 static int ses_do_frame(frame_T *fr); 11023 static int ses_do_win(win_T *wp); 11024 static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp); 11025 static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp); 11026 static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, int add_eol); 11027 11028 /* 11029 * Write openfile commands for the current buffers to an .exrc file. 11030 * Return FAIL on error, OK otherwise. 11031 */ 11032 static int 11033 makeopens( 11034 FILE *fd, 11035 char_u *dirnow) /* Current directory name */ 11036 { 11037 buf_T *buf; 11038 int only_save_windows = TRUE; 11039 int nr; 11040 int restore_size = TRUE; 11041 win_T *wp; 11042 char_u *sname; 11043 win_T *edited_win = NULL; 11044 int tabnr; 11045 int restore_stal = FALSE; 11046 win_T *tab_firstwin; 11047 frame_T *tab_topframe; 11048 int cur_arg_idx = 0; 11049 int next_arg_idx = 0; 11050 11051 if (ssop_flags & SSOP_BUFFERS) 11052 only_save_windows = FALSE; /* Save ALL buffers */ 11053 11054 /* 11055 * Begin by setting the this_session variable, and then other 11056 * sessionable variables. 11057 */ 11058 #ifdef FEAT_EVAL 11059 if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL) 11060 return FAIL; 11061 if (ssop_flags & SSOP_GLOBALS) 11062 if (store_session_globals(fd) == FAIL) 11063 return FAIL; 11064 #endif 11065 11066 /* 11067 * Close all windows but one. 11068 */ 11069 if (put_line(fd, "silent only") == FAIL) 11070 return FAIL; 11071 11072 /* 11073 * Now a :cd command to the session directory or the current directory 11074 */ 11075 if (ssop_flags & SSOP_SESDIR) 11076 { 11077 if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')") 11078 == FAIL) 11079 return FAIL; 11080 } 11081 else if (ssop_flags & SSOP_CURDIR) 11082 { 11083 sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow); 11084 if (sname == NULL 11085 || fputs("cd ", fd) < 0 11086 || ses_put_fname(fd, sname, &ssop_flags) == FAIL 11087 || put_eol(fd) == FAIL) 11088 { 11089 vim_free(sname); 11090 return FAIL; 11091 } 11092 vim_free(sname); 11093 } 11094 11095 /* 11096 * If there is an empty, unnamed buffer we will wipe it out later. 11097 * Remember the buffer number. 11098 */ 11099 if (put_line(fd, "if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''") == FAIL) 11100 return FAIL; 11101 if (put_line(fd, " let s:wipebuf = bufnr('%')") == FAIL) 11102 return FAIL; 11103 if (put_line(fd, "endif") == FAIL) 11104 return FAIL; 11105 11106 /* 11107 * Now save the current files, current buffer first. 11108 */ 11109 if (put_line(fd, "set shortmess=aoO") == FAIL) 11110 return FAIL; 11111 11112 /* Now put the other buffers into the buffer list */ 11113 FOR_ALL_BUFFERS(buf) 11114 { 11115 if (!(only_save_windows && buf->b_nwindows == 0) 11116 && !(buf->b_help && !(ssop_flags & SSOP_HELP)) 11117 && buf->b_fname != NULL 11118 && buf->b_p_bl) 11119 { 11120 if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L 11121 : buf->b_wininfo->wi_fpos.lnum) < 0 11122 || ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL) 11123 return FAIL; 11124 } 11125 } 11126 11127 /* the global argument list */ 11128 if (ses_arglist(fd, "argglobal", &global_alist.al_ga, 11129 !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL) 11130 return FAIL; 11131 11132 if (ssop_flags & SSOP_RESIZE) 11133 { 11134 /* Note: after the restore we still check it worked!*/ 11135 if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0 11136 || put_eol(fd) == FAIL) 11137 return FAIL; 11138 } 11139 11140 #ifdef FEAT_GUI 11141 if (gui.in_use && (ssop_flags & SSOP_WINPOS)) 11142 { 11143 int x, y; 11144 11145 if (gui_mch_get_winpos(&x, &y) == OK) 11146 { 11147 /* Note: after the restore we still check it worked!*/ 11148 if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL) 11149 return FAIL; 11150 } 11151 } 11152 #endif 11153 11154 /* 11155 * When there are two or more tabpages and 'showtabline' is 1 the tabline 11156 * will be displayed when creating the next tab. That resizes the windows 11157 * in the first tab, which may cause problems. Set 'showtabline' to 2 11158 * temporarily to avoid that. 11159 */ 11160 if (p_stal == 1 && first_tabpage->tp_next != NULL) 11161 { 11162 if (put_line(fd, "set stal=2") == FAIL) 11163 return FAIL; 11164 restore_stal = TRUE; 11165 } 11166 11167 /* 11168 * May repeat putting Windows for each tab, when "tabpages" is in 11169 * 'sessionoptions'. 11170 * Don't use goto_tabpage(), it may change directory and trigger 11171 * autocommands. 11172 */ 11173 tab_firstwin = firstwin; /* first window in tab page "tabnr" */ 11174 tab_topframe = topframe; 11175 for (tabnr = 1; ; ++tabnr) 11176 { 11177 int need_tabnew = FALSE; 11178 int cnr = 1; 11179 11180 if ((ssop_flags & SSOP_TABPAGES)) 11181 { 11182 tabpage_T *tp = find_tabpage(tabnr); 11183 11184 if (tp == NULL) 11185 break; /* done all tab pages */ 11186 if (tp == curtab) 11187 { 11188 tab_firstwin = firstwin; 11189 tab_topframe = topframe; 11190 } 11191 else 11192 { 11193 tab_firstwin = tp->tp_firstwin; 11194 tab_topframe = tp->tp_topframe; 11195 } 11196 if (tabnr > 1) 11197 need_tabnew = TRUE; 11198 } 11199 11200 /* 11201 * Before creating the window layout, try loading one file. If this 11202 * is aborted we don't end up with a number of useless windows. 11203 * This may have side effects! (e.g., compressed or network file). 11204 */ 11205 for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) 11206 { 11207 if (ses_do_win(wp) 11208 && wp->w_buffer->b_ffname != NULL 11209 && !bt_help(wp->w_buffer) 11210 #ifdef FEAT_QUICKFIX 11211 && !bt_nofile(wp->w_buffer) 11212 #endif 11213 ) 11214 { 11215 if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0 11216 || ses_fname(fd, wp->w_buffer, &ssop_flags, TRUE) 11217 == FAIL) 11218 return FAIL; 11219 need_tabnew = FALSE; 11220 if (!wp->w_arg_idx_invalid) 11221 edited_win = wp; 11222 break; 11223 } 11224 } 11225 11226 /* If no file got edited create an empty tab page. */ 11227 if (need_tabnew && put_line(fd, "tabnew") == FAIL) 11228 return FAIL; 11229 11230 /* 11231 * Save current window layout. 11232 */ 11233 if (put_line(fd, "set splitbelow splitright") == FAIL) 11234 return FAIL; 11235 if (ses_win_rec(fd, tab_topframe) == FAIL) 11236 return FAIL; 11237 if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL) 11238 return FAIL; 11239 if (!p_spr && put_line(fd, "set nosplitright") == FAIL) 11240 return FAIL; 11241 11242 /* 11243 * Check if window sizes can be restored (no windows omitted). 11244 * Remember the window number of the current window after restoring. 11245 */ 11246 nr = 0; 11247 for (wp = tab_firstwin; wp != NULL; wp = W_NEXT(wp)) 11248 { 11249 if (ses_do_win(wp)) 11250 ++nr; 11251 else 11252 restore_size = FALSE; 11253 if (curwin == wp) 11254 cnr = nr; 11255 } 11256 11257 /* Go to the first window. */ 11258 if (put_line(fd, "wincmd t") == FAIL) 11259 return FAIL; 11260 11261 /* 11262 * If more than one window, see if sizes can be restored. 11263 * First set 'winheight' and 'winwidth' to 1 to avoid the windows being 11264 * resized when moving between windows. 11265 * Do this before restoring the view, so that the topline and the 11266 * cursor can be set. This is done again below. 11267 * winminheight and winminwidth need to be set to avoid an error if the 11268 * user has set winheight or winwidth. 11269 */ 11270 if (put_line(fd, "set winminheight=1 winheight=1 winminwidth=1 winwidth=1") == FAIL) 11271 return FAIL; 11272 if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) 11273 return FAIL; 11274 11275 /* 11276 * Restore the view of the window (options, file, cursor, etc.). 11277 */ 11278 for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) 11279 { 11280 if (!ses_do_win(wp)) 11281 continue; 11282 if (put_view(fd, wp, wp != edited_win, &ssop_flags, 11283 cur_arg_idx) == FAIL) 11284 return FAIL; 11285 if (nr > 1 && put_line(fd, "wincmd w") == FAIL) 11286 return FAIL; 11287 next_arg_idx = wp->w_arg_idx; 11288 } 11289 11290 /* The argument index in the first tab page is zero, need to set it in 11291 * each window. For further tab pages it's the window where we do 11292 * "tabedit". */ 11293 cur_arg_idx = next_arg_idx; 11294 11295 /* 11296 * Restore cursor to the current window if it's not the first one. 11297 */ 11298 if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0 11299 || put_eol(fd) == FAIL)) 11300 return FAIL; 11301 11302 /* 11303 * Restore window sizes again after jumping around in windows, because 11304 * the current window has a minimum size while others may not. 11305 */ 11306 if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) 11307 return FAIL; 11308 11309 /* Don't continue in another tab page when doing only the current one 11310 * or when at the last tab page. */ 11311 if (!(ssop_flags & SSOP_TABPAGES)) 11312 break; 11313 } 11314 11315 if (ssop_flags & SSOP_TABPAGES) 11316 { 11317 if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0 11318 || put_eol(fd) == FAIL) 11319 return FAIL; 11320 } 11321 if (restore_stal && put_line(fd, "set stal=1") == FAIL) 11322 return FAIL; 11323 11324 /* 11325 * Wipe out an empty unnamed buffer we started in. 11326 */ 11327 if (put_line(fd, "if exists('s:wipebuf')") == FAIL) 11328 return FAIL; 11329 if (put_line(fd, " silent exe 'bwipe ' . s:wipebuf") == FAIL) 11330 return FAIL; 11331 if (put_line(fd, "endif") == FAIL) 11332 return FAIL; 11333 if (put_line(fd, "unlet! s:wipebuf") == FAIL) 11334 return FAIL; 11335 11336 /* Re-apply 'winheight', 'winwidth' and 'shortmess'. */ 11337 if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s", 11338 p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL) 11339 return FAIL; 11340 /* Re-apply 'winminheight' and 'winminwidth'. */ 11341 if (fprintf(fd, "set winminheight=%ld winminwidth=%ld", 11342 p_wmh, p_wmw) < 0 || put_eol(fd) == FAIL) 11343 return FAIL; 11344 11345 /* 11346 * Lastly, execute the x.vim file if it exists. 11347 */ 11348 if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL 11349 || put_line(fd, "if file_readable(s:sx)") == FAIL 11350 || put_line(fd, " exe \"source \" . fnameescape(s:sx)") == FAIL 11351 || put_line(fd, "endif") == FAIL) 11352 return FAIL; 11353 11354 return OK; 11355 } 11356 11357 static int 11358 ses_winsizes( 11359 FILE *fd, 11360 int restore_size, 11361 win_T *tab_firstwin) 11362 { 11363 int n = 0; 11364 win_T *wp; 11365 11366 if (restore_size && (ssop_flags & SSOP_WINSIZE)) 11367 { 11368 for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) 11369 { 11370 if (!ses_do_win(wp)) 11371 continue; 11372 ++n; 11373 11374 /* restore height when not full height */ 11375 if (wp->w_height + wp->w_status_height < topframe->fr_height 11376 && (fprintf(fd, 11377 "exe '%dresize ' . ((&lines * %ld + %ld) / %ld)", 11378 n, (long)wp->w_height, Rows / 2, Rows) < 0 11379 || put_eol(fd) == FAIL)) 11380 return FAIL; 11381 11382 /* restore width when not full width */ 11383 if (wp->w_width < Columns && (fprintf(fd, 11384 "exe 'vert %dresize ' . ((&columns * %ld + %ld) / %ld)", 11385 n, (long)wp->w_width, Columns / 2, Columns) < 0 11386 || put_eol(fd) == FAIL)) 11387 return FAIL; 11388 } 11389 } 11390 else 11391 { 11392 /* Just equalise window sizes */ 11393 if (put_line(fd, "wincmd =") == FAIL) 11394 return FAIL; 11395 } 11396 return OK; 11397 } 11398 11399 /* 11400 * Write commands to "fd" to recursively create windows for frame "fr", 11401 * horizontally and vertically split. 11402 * After the commands the last window in the frame is the current window. 11403 * Returns FAIL when writing the commands to "fd" fails. 11404 */ 11405 static int 11406 ses_win_rec(FILE *fd, frame_T *fr) 11407 { 11408 frame_T *frc; 11409 int count = 0; 11410 11411 if (fr->fr_layout != FR_LEAF) 11412 { 11413 /* Find first frame that's not skipped and then create a window for 11414 * each following one (first frame is already there). */ 11415 frc = ses_skipframe(fr->fr_child); 11416 if (frc != NULL) 11417 while ((frc = ses_skipframe(frc->fr_next)) != NULL) 11418 { 11419 /* Make window as big as possible so that we have lots of room 11420 * to split. */ 11421 if (put_line(fd, "wincmd _ | wincmd |") == FAIL 11422 || put_line(fd, fr->fr_layout == FR_COL 11423 ? "split" : "vsplit") == FAIL) 11424 return FAIL; 11425 ++count; 11426 } 11427 11428 /* Go back to the first window. */ 11429 if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL 11430 ? "%dwincmd k" : "%dwincmd h", count) < 0 11431 || put_eol(fd) == FAIL)) 11432 return FAIL; 11433 11434 /* Recursively create frames/windows in each window of this column or 11435 * row. */ 11436 frc = ses_skipframe(fr->fr_child); 11437 while (frc != NULL) 11438 { 11439 ses_win_rec(fd, frc); 11440 frc = ses_skipframe(frc->fr_next); 11441 /* Go to next window. */ 11442 if (frc != NULL && put_line(fd, "wincmd w") == FAIL) 11443 return FAIL; 11444 } 11445 } 11446 return OK; 11447 } 11448 11449 /* 11450 * Skip frames that don't contain windows we want to save in the Session. 11451 * Returns NULL when there none. 11452 */ 11453 static frame_T * 11454 ses_skipframe(frame_T *fr) 11455 { 11456 frame_T *frc; 11457 11458 for (frc = fr; frc != NULL; frc = frc->fr_next) 11459 if (ses_do_frame(frc)) 11460 break; 11461 return frc; 11462 } 11463 11464 /* 11465 * Return TRUE if frame "fr" has a window somewhere that we want to save in 11466 * the Session. 11467 */ 11468 static int 11469 ses_do_frame(frame_T *fr) 11470 { 11471 frame_T *frc; 11472 11473 if (fr->fr_layout == FR_LEAF) 11474 return ses_do_win(fr->fr_win); 11475 for (frc = fr->fr_child; frc != NULL; frc = frc->fr_next) 11476 if (ses_do_frame(frc)) 11477 return TRUE; 11478 return FALSE; 11479 } 11480 11481 /* 11482 * Return non-zero if window "wp" is to be stored in the Session. 11483 */ 11484 static int 11485 ses_do_win(win_T *wp) 11486 { 11487 if (wp->w_buffer->b_fname == NULL 11488 #ifdef FEAT_QUICKFIX 11489 /* When 'buftype' is "nofile" can't restore the window contents. */ 11490 || bt_nofile(wp->w_buffer) 11491 #endif 11492 ) 11493 return (ssop_flags & SSOP_BLANK); 11494 if (bt_help(wp->w_buffer)) 11495 return (ssop_flags & SSOP_HELP); 11496 return TRUE; 11497 } 11498 11499 /* 11500 * Write commands to "fd" to restore the view of a window. 11501 * Caller must make sure 'scrolloff' is zero. 11502 */ 11503 static int 11504 put_view( 11505 FILE *fd, 11506 win_T *wp, 11507 int add_edit, /* add ":edit" command to view */ 11508 unsigned *flagp, /* vop_flags or ssop_flags */ 11509 int current_arg_idx) /* current argument index of the window, use 11510 * -1 if unknown */ 11511 { 11512 win_T *save_curwin; 11513 int f; 11514 int do_cursor; 11515 int did_next = FALSE; 11516 11517 /* Always restore cursor position for ":mksession". For ":mkview" only 11518 * when 'viewoptions' contains "cursor". */ 11519 do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR); 11520 11521 /* 11522 * Local argument list. 11523 */ 11524 if (wp->w_alist == &global_alist) 11525 { 11526 if (put_line(fd, "argglobal") == FAIL) 11527 return FAIL; 11528 } 11529 else 11530 { 11531 if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga, 11532 flagp == &vop_flags 11533 || !(*flagp & SSOP_CURDIR) 11534 || wp->w_localdir != NULL, flagp) == FAIL) 11535 return FAIL; 11536 } 11537 11538 /* Only when part of a session: restore the argument index. Some 11539 * arguments may have been deleted, check if the index is valid. */ 11540 if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx < WARGCOUNT(wp) 11541 && flagp == &ssop_flags) 11542 { 11543 if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0 11544 || put_eol(fd) == FAIL) 11545 return FAIL; 11546 did_next = TRUE; 11547 } 11548 11549 /* Edit the file. Skip this when ":next" already did it. */ 11550 if (add_edit && (!did_next || wp->w_arg_idx_invalid)) 11551 { 11552 /* 11553 * Load the file. 11554 */ 11555 if (wp->w_buffer->b_ffname != NULL 11556 #ifdef FEAT_QUICKFIX 11557 && !bt_nofile(wp->w_buffer) 11558 #endif 11559 ) 11560 { 11561 /* 11562 * Editing a file in this buffer: use ":edit file". 11563 * This may have side effects! (e.g., compressed or network file). 11564 * 11565 * Note, if a buffer for that file already exists, use :badd to 11566 * edit that buffer, to not lose folding information (:edit resets 11567 * folds in other buffers) 11568 */ 11569 if (fputs("if bufexists('", fd) < 0 11570 || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL 11571 || fputs("') | buffer ", fd) < 0 11572 || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL 11573 || fputs(" | else | edit ", fd) < 0 11574 || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL 11575 || fputs(" | endif", fd) < 0 11576 || 11577 put_eol(fd) == FAIL) 11578 return FAIL; 11579 } 11580 else 11581 { 11582 /* No file in this buffer, just make it empty. */ 11583 if (put_line(fd, "enew") == FAIL) 11584 return FAIL; 11585 #ifdef FEAT_QUICKFIX 11586 if (wp->w_buffer->b_ffname != NULL) 11587 { 11588 /* The buffer does have a name, but it's not a file name. */ 11589 if (fputs("file ", fd) < 0 11590 || ses_fname(fd, wp->w_buffer, flagp, TRUE) == FAIL) 11591 return FAIL; 11592 } 11593 #endif 11594 do_cursor = FALSE; 11595 } 11596 } 11597 11598 /* 11599 * Local mappings and abbreviations. 11600 */ 11601 if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS)) 11602 && makemap(fd, wp->w_buffer) == FAIL) 11603 return FAIL; 11604 11605 /* 11606 * Local options. Need to go to the window temporarily. 11607 * Store only local values when using ":mkview" and when ":mksession" is 11608 * used and 'sessionoptions' doesn't include "options". 11609 * Some folding options are always stored when "folds" is included, 11610 * otherwise the folds would not be restored correctly. 11611 */ 11612 save_curwin = curwin; 11613 curwin = wp; 11614 curbuf = curwin->w_buffer; 11615 if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS)) 11616 f = makeset(fd, OPT_LOCAL, 11617 flagp == &vop_flags || !(*flagp & SSOP_OPTIONS)); 11618 #ifdef FEAT_FOLDING 11619 else if (*flagp & SSOP_FOLDS) 11620 f = makefoldset(fd); 11621 #endif 11622 else 11623 f = OK; 11624 curwin = save_curwin; 11625 curbuf = curwin->w_buffer; 11626 if (f == FAIL) 11627 return FAIL; 11628 11629 #ifdef FEAT_FOLDING 11630 /* 11631 * Save Folds when 'buftype' is empty and for help files. 11632 */ 11633 if ((*flagp & SSOP_FOLDS) 11634 && wp->w_buffer->b_ffname != NULL 11635 && (*wp->w_buffer->b_p_bt == NUL || bt_help(wp->w_buffer))) 11636 { 11637 if (put_folds(fd, wp) == FAIL) 11638 return FAIL; 11639 } 11640 #endif 11641 11642 /* 11643 * Set the cursor after creating folds, since that moves the cursor. 11644 */ 11645 if (do_cursor) 11646 { 11647 11648 /* Restore the cursor line in the file and relatively in the 11649 * window. Don't use "G", it changes the jumplist. */ 11650 if (fprintf(fd, "let s:l = %ld - ((%ld * winheight(0) + %ld) / %ld)", 11651 (long)wp->w_cursor.lnum, 11652 (long)(wp->w_cursor.lnum - wp->w_topline), 11653 (long)wp->w_height / 2, (long)wp->w_height) < 0 11654 || put_eol(fd) == FAIL 11655 || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL 11656 || put_line(fd, "exe s:l") == FAIL 11657 || put_line(fd, "normal! zt") == FAIL 11658 || fprintf(fd, "%ld", (long)wp->w_cursor.lnum) < 0 11659 || put_eol(fd) == FAIL) 11660 return FAIL; 11661 /* Restore the cursor column and left offset when not wrapping. */ 11662 if (wp->w_cursor.col == 0) 11663 { 11664 if (put_line(fd, "normal! 0") == FAIL) 11665 return FAIL; 11666 } 11667 else 11668 { 11669 if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0) 11670 { 11671 if (fprintf(fd, 11672 "let s:c = %ld - ((%ld * winwidth(0) + %ld) / %ld)", 11673 (long)wp->w_virtcol + 1, 11674 (long)(wp->w_virtcol - wp->w_leftcol), 11675 (long)wp->w_width / 2, (long)wp->w_width) < 0 11676 || put_eol(fd) == FAIL 11677 || put_line(fd, "if s:c > 0") == FAIL 11678 || fprintf(fd, 11679 " exe 'normal! ' . s:c . '|zs' . %ld . '|'", 11680 (long)wp->w_virtcol + 1) < 0 11681 || put_eol(fd) == FAIL 11682 || put_line(fd, "else") == FAIL 11683 || fprintf(fd, " normal! 0%d|", wp->w_virtcol + 1) < 0 11684 || put_eol(fd) == FAIL 11685 || put_line(fd, "endif") == FAIL) 11686 return FAIL; 11687 } 11688 else 11689 { 11690 if (fprintf(fd, "normal! 0%d|", wp->w_virtcol + 1) < 0 11691 || put_eol(fd) == FAIL) 11692 return FAIL; 11693 } 11694 } 11695 } 11696 11697 /* 11698 * Local directory. 11699 */ 11700 if (wp->w_localdir != NULL) 11701 { 11702 if (fputs("lcd ", fd) < 0 11703 || ses_put_fname(fd, wp->w_localdir, flagp) == FAIL 11704 || put_eol(fd) == FAIL) 11705 return FAIL; 11706 did_lcd = TRUE; 11707 } 11708 11709 return OK; 11710 } 11711 11712 /* 11713 * Write an argument list to the session file. 11714 * Returns FAIL if writing fails. 11715 */ 11716 static int 11717 ses_arglist( 11718 FILE *fd, 11719 char *cmd, 11720 garray_T *gap, 11721 int fullname, /* TRUE: use full path name */ 11722 unsigned *flagp) 11723 { 11724 int i; 11725 char_u *buf = NULL; 11726 char_u *s; 11727 11728 if (fputs(cmd, fd) < 0 || put_eol(fd) == FAIL) 11729 return FAIL; 11730 if (put_line(fd, "silent! argdel *") == FAIL) 11731 return FAIL; 11732 for (i = 0; i < gap->ga_len; ++i) 11733 { 11734 /* NULL file names are skipped (only happens when out of memory). */ 11735 s = alist_name(&((aentry_T *)gap->ga_data)[i]); 11736 if (s != NULL) 11737 { 11738 if (fullname) 11739 { 11740 buf = alloc(MAXPATHL); 11741 if (buf != NULL) 11742 { 11743 (void)vim_FullName(s, buf, MAXPATHL, FALSE); 11744 s = buf; 11745 } 11746 } 11747 if (fputs("$argadd ", fd) < 0 11748 || ses_put_fname(fd, s, flagp) == FAIL 11749 || put_eol(fd) == FAIL) 11750 { 11751 vim_free(buf); 11752 return FAIL; 11753 } 11754 vim_free(buf); 11755 } 11756 } 11757 return OK; 11758 } 11759 11760 /* 11761 * Write a buffer name to the session file. 11762 * Also ends the line, if "add_eol" is TRUE. 11763 * Returns FAIL if writing fails. 11764 */ 11765 static int 11766 ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, int add_eol) 11767 { 11768 char_u *name; 11769 11770 /* Use the short file name if the current directory is known at the time 11771 * the session file will be sourced. 11772 * Don't do this for ":mkview", we don't know the current directory. 11773 * Don't do this after ":lcd", we don't keep track of what the current 11774 * directory is. */ 11775 if (buf->b_sfname != NULL 11776 && flagp == &ssop_flags 11777 && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR)) 11778 #ifdef FEAT_AUTOCHDIR 11779 && !p_acd 11780 #endif 11781 && !did_lcd) 11782 name = buf->b_sfname; 11783 else 11784 name = buf->b_ffname; 11785 if (ses_put_fname(fd, name, flagp) == FAIL 11786 || (add_eol && put_eol(fd) == FAIL)) 11787 return FAIL; 11788 return OK; 11789 } 11790 11791 /* 11792 * Write a file name to the session file. 11793 * Takes care of the "slash" option in 'sessionoptions' and escapes special 11794 * characters. 11795 * Returns FAIL if writing fails or out of memory. 11796 */ 11797 static int 11798 ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) 11799 { 11800 char_u *sname; 11801 char_u *p; 11802 int retval = OK; 11803 11804 sname = home_replace_save(NULL, name); 11805 if (sname == NULL) 11806 return FAIL; 11807 11808 if (*flagp & SSOP_SLASH) 11809 { 11810 /* change all backslashes to forward slashes */ 11811 for (p = sname; *p != NUL; MB_PTR_ADV(p)) 11812 if (*p == '\\') 11813 *p = '/'; 11814 } 11815 11816 /* escape special characters */ 11817 p = vim_strsave_fnameescape(sname, FALSE); 11818 vim_free(sname); 11819 if (p == NULL) 11820 return FAIL; 11821 11822 /* write the result */ 11823 if (fputs((char *)p, fd) < 0) 11824 retval = FAIL; 11825 11826 vim_free(p); 11827 return retval; 11828 } 11829 11830 /* 11831 * ":loadview [nr]" 11832 */ 11833 static void 11834 ex_loadview(exarg_T *eap) 11835 { 11836 char_u *fname; 11837 11838 fname = get_view_file(*eap->arg); 11839 if (fname != NULL) 11840 { 11841 do_source(fname, FALSE, DOSO_NONE); 11842 vim_free(fname); 11843 } 11844 } 11845 11846 /* 11847 * Get the name of the view file for the current buffer. 11848 */ 11849 static char_u * 11850 get_view_file(int c) 11851 { 11852 int len = 0; 11853 char_u *p, *s; 11854 char_u *retval; 11855 char_u *sname; 11856 11857 if (curbuf->b_ffname == NULL) 11858 { 11859 EMSG(_(e_noname)); 11860 return NULL; 11861 } 11862 sname = home_replace_save(NULL, curbuf->b_ffname); 11863 if (sname == NULL) 11864 return NULL; 11865 11866 /* 11867 * We want a file name without separators, because we're not going to make 11868 * a directory. 11869 * "normal" path separator -> "=+" 11870 * "=" -> "==" 11871 * ":" path separator -> "=-" 11872 */ 11873 for (p = sname; *p; ++p) 11874 if (*p == '=' || vim_ispathsep(*p)) 11875 ++len; 11876 retval = alloc((unsigned)(STRLEN(sname) + len + STRLEN(p_vdir) + 9)); 11877 if (retval != NULL) 11878 { 11879 STRCPY(retval, p_vdir); 11880 add_pathsep(retval); 11881 s = retval + STRLEN(retval); 11882 for (p = sname; *p; ++p) 11883 { 11884 if (*p == '=') 11885 { 11886 *s++ = '='; 11887 *s++ = '='; 11888 } 11889 else if (vim_ispathsep(*p)) 11890 { 11891 *s++ = '='; 11892 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(VMS) 11893 if (*p == ':') 11894 *s++ = '-'; 11895 else 11896 #endif 11897 *s++ = '+'; 11898 } 11899 else 11900 *s++ = *p; 11901 } 11902 *s++ = '='; 11903 *s++ = c; 11904 STRCPY(s, ".vim"); 11905 } 11906 11907 vim_free(sname); 11908 return retval; 11909 } 11910 11911 #endif /* FEAT_SESSION */ 11912 11913 /* 11914 * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession". 11915 * Return FAIL for a write error. 11916 */ 11917 int 11918 put_eol(FILE *fd) 11919 { 11920 if ( 11921 #ifdef USE_CRNL 11922 ( 11923 # ifdef MKSESSION_NL 11924 !mksession_nl && 11925 # endif 11926 (putc('\r', fd) < 0)) || 11927 #endif 11928 (putc('\n', fd) < 0)) 11929 return FAIL; 11930 return OK; 11931 } 11932 11933 /* 11934 * Write a line to "fd". 11935 * Return FAIL for a write error. 11936 */ 11937 int 11938 put_line(FILE *fd, char *s) 11939 { 11940 if (fputs(s, fd) < 0 || put_eol(fd) == FAIL) 11941 return FAIL; 11942 return OK; 11943 } 11944 11945 #ifdef FEAT_VIMINFO 11946 /* 11947 * ":rviminfo" and ":wviminfo". 11948 */ 11949 static void 11950 ex_viminfo( 11951 exarg_T *eap) 11952 { 11953 char_u *save_viminfo; 11954 11955 save_viminfo = p_viminfo; 11956 if (*p_viminfo == NUL) 11957 p_viminfo = (char_u *)"'100"; 11958 if (eap->cmdidx == CMD_rviminfo) 11959 { 11960 if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS 11961 | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL) 11962 EMSG(_("E195: Cannot open viminfo file for reading")); 11963 } 11964 else 11965 write_viminfo(eap->arg, eap->forceit); 11966 p_viminfo = save_viminfo; 11967 } 11968 #endif 11969 11970 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) 11971 /* 11972 * Make a dialog message in "buff[DIALOG_MSG_SIZE]". 11973 * "format" must contain "%s". 11974 */ 11975 void 11976 dialog_msg(char_u *buff, char *format, char_u *fname) 11977 { 11978 if (fname == NULL) 11979 fname = (char_u *)_("Untitled"); 11980 vim_snprintf((char *)buff, DIALOG_MSG_SIZE, format, fname); 11981 } 11982 #endif 11983 11984 /* 11985 * ":behave {mswin,xterm}" 11986 */ 11987 static void 11988 ex_behave(exarg_T *eap) 11989 { 11990 if (STRCMP(eap->arg, "mswin") == 0) 11991 { 11992 set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0); 11993 set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0); 11994 set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0); 11995 set_option_value((char_u *)"keymodel", 0L, 11996 (char_u *)"startsel,stopsel", 0); 11997 } 11998 else if (STRCMP(eap->arg, "xterm") == 0) 11999 { 12000 set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0); 12001 set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0); 12002 set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0); 12003 set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0); 12004 } 12005 else 12006 EMSG2(_(e_invarg2), eap->arg); 12007 } 12008 12009 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 12010 /* 12011 * Function given to ExpandGeneric() to obtain the possible arguments of the 12012 * ":behave {mswin,xterm}" command. 12013 */ 12014 char_u * 12015 get_behave_arg(expand_T *xp UNUSED, int idx) 12016 { 12017 if (idx == 0) 12018 return (char_u *)"mswin"; 12019 if (idx == 1) 12020 return (char_u *)"xterm"; 12021 return NULL; 12022 } 12023 12024 /* 12025 * Function given to ExpandGeneric() to obtain the possible arguments of the 12026 * ":messages {clear}" command. 12027 */ 12028 char_u * 12029 get_messages_arg(expand_T *xp UNUSED, int idx) 12030 { 12031 if (idx == 0) 12032 return (char_u *)"clear"; 12033 return NULL; 12034 } 12035 #endif 12036 12037 char_u * 12038 get_mapclear_arg(expand_T *xp UNUSED, int idx) 12039 { 12040 if (idx == 0) 12041 return (char_u *)"<buffer>"; 12042 return NULL; 12043 } 12044 12045 #ifdef FEAT_AUTOCMD 12046 static int filetype_detect = FALSE; 12047 static int filetype_plugin = FALSE; 12048 static int filetype_indent = FALSE; 12049 12050 /* 12051 * ":filetype [plugin] [indent] {on,off,detect}" 12052 * on: Load the filetype.vim file to install autocommands for file types. 12053 * off: Load the ftoff.vim file to remove all autocommands for file types. 12054 * plugin on: load filetype.vim and ftplugin.vim 12055 * plugin off: load ftplugof.vim 12056 * indent on: load filetype.vim and indent.vim 12057 * indent off: load indoff.vim 12058 */ 12059 static void 12060 ex_filetype(exarg_T *eap) 12061 { 12062 char_u *arg = eap->arg; 12063 int plugin = FALSE; 12064 int indent = FALSE; 12065 12066 if (*eap->arg == NUL) 12067 { 12068 /* Print current status. */ 12069 smsg((char_u *)"filetype detection:%s plugin:%s indent:%s", 12070 filetype_detect ? "ON" : "OFF", 12071 filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF", 12072 filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF"); 12073 return; 12074 } 12075 12076 /* Accept "plugin" and "indent" in any order. */ 12077 for (;;) 12078 { 12079 if (STRNCMP(arg, "plugin", 6) == 0) 12080 { 12081 plugin = TRUE; 12082 arg = skipwhite(arg + 6); 12083 continue; 12084 } 12085 if (STRNCMP(arg, "indent", 6) == 0) 12086 { 12087 indent = TRUE; 12088 arg = skipwhite(arg + 6); 12089 continue; 12090 } 12091 break; 12092 } 12093 if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0) 12094 { 12095 if (*arg == 'o' || !filetype_detect) 12096 { 12097 source_runtime((char_u *)FILETYPE_FILE, DIP_ALL); 12098 filetype_detect = TRUE; 12099 if (plugin) 12100 { 12101 source_runtime((char_u *)FTPLUGIN_FILE, DIP_ALL); 12102 filetype_plugin = TRUE; 12103 } 12104 if (indent) 12105 { 12106 source_runtime((char_u *)INDENT_FILE, DIP_ALL); 12107 filetype_indent = TRUE; 12108 } 12109 } 12110 if (*arg == 'd') 12111 { 12112 (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE, NULL); 12113 do_modelines(0); 12114 } 12115 } 12116 else if (STRCMP(arg, "off") == 0) 12117 { 12118 if (plugin || indent) 12119 { 12120 if (plugin) 12121 { 12122 source_runtime((char_u *)FTPLUGOF_FILE, DIP_ALL); 12123 filetype_plugin = FALSE; 12124 } 12125 if (indent) 12126 { 12127 source_runtime((char_u *)INDOFF_FILE, DIP_ALL); 12128 filetype_indent = FALSE; 12129 } 12130 } 12131 else 12132 { 12133 source_runtime((char_u *)FTOFF_FILE, DIP_ALL); 12134 filetype_detect = FALSE; 12135 } 12136 } 12137 else 12138 EMSG2(_(e_invarg2), arg); 12139 } 12140 12141 /* 12142 * ":setfiletype [FALLBACK] {name}" 12143 */ 12144 static void 12145 ex_setfiletype(exarg_T *eap) 12146 { 12147 if (!did_filetype) 12148 { 12149 char_u *arg = eap->arg; 12150 12151 if (STRNCMP(arg, "FALLBACK ", 9) == 0) 12152 arg += 9; 12153 12154 set_option_value((char_u *)"filetype", 0L, arg, OPT_LOCAL); 12155 if (arg != eap->arg) 12156 did_filetype = FALSE; 12157 } 12158 } 12159 #endif 12160 12161 static void 12162 ex_digraphs(exarg_T *eap UNUSED) 12163 { 12164 #ifdef FEAT_DIGRAPHS 12165 if (*eap->arg != NUL) 12166 putdigraph(eap->arg); 12167 else 12168 listdigraphs(); 12169 #else 12170 EMSG(_("E196: No digraphs in this version")); 12171 #endif 12172 } 12173 12174 static void 12175 ex_set(exarg_T *eap) 12176 { 12177 int flags = 0; 12178 12179 if (eap->cmdidx == CMD_setlocal) 12180 flags = OPT_LOCAL; 12181 else if (eap->cmdidx == CMD_setglobal) 12182 flags = OPT_GLOBAL; 12183 #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD) && defined(FEAT_BROWSE) 12184 if (cmdmod.browse && flags == 0) 12185 ex_options(eap); 12186 else 12187 #endif 12188 (void)do_set(eap->arg, flags); 12189 } 12190 12191 #ifdef FEAT_SEARCH_EXTRA 12192 /* 12193 * ":nohlsearch" 12194 */ 12195 static void 12196 ex_nohlsearch(exarg_T *eap UNUSED) 12197 { 12198 SET_NO_HLSEARCH(TRUE); 12199 redraw_all_later(SOME_VALID); 12200 } 12201 12202 /* 12203 * ":[N]match {group} {pattern}" 12204 * Sets nextcmd to the start of the next command, if any. Also called when 12205 * skipping commands to find the next command. 12206 */ 12207 static void 12208 ex_match(exarg_T *eap) 12209 { 12210 char_u *p; 12211 char_u *g = NULL; 12212 char_u *end; 12213 int c; 12214 int id; 12215 12216 if (eap->line2 <= 3) 12217 id = eap->line2; 12218 else 12219 { 12220 EMSG(e_invcmd); 12221 return; 12222 } 12223 12224 /* First clear any old pattern. */ 12225 if (!eap->skip) 12226 match_delete(curwin, id, FALSE); 12227 12228 if (ends_excmd(*eap->arg)) 12229 end = eap->arg; 12230 else if ((STRNICMP(eap->arg, "none", 4) == 0 12231 && (VIM_ISWHITE(eap->arg[4]) || ends_excmd(eap->arg[4])))) 12232 end = eap->arg + 4; 12233 else 12234 { 12235 p = skiptowhite(eap->arg); 12236 if (!eap->skip) 12237 g = vim_strnsave(eap->arg, (int)(p - eap->arg)); 12238 p = skipwhite(p); 12239 if (*p == NUL) 12240 { 12241 /* There must be two arguments. */ 12242 vim_free(g); 12243 EMSG2(_(e_invarg2), eap->arg); 12244 return; 12245 } 12246 end = skip_regexp(p + 1, *p, TRUE, NULL); 12247 if (!eap->skip) 12248 { 12249 if (*end != NUL && !ends_excmd(*skipwhite(end + 1))) 12250 { 12251 vim_free(g); 12252 eap->errmsg = e_trailing; 12253 return; 12254 } 12255 if (*end != *p) 12256 { 12257 vim_free(g); 12258 EMSG2(_(e_invarg2), p); 12259 return; 12260 } 12261 12262 c = *end; 12263 *end = NUL; 12264 match_add(curwin, g, p + 1, 10, id, NULL, NULL); 12265 vim_free(g); 12266 *end = c; 12267 } 12268 } 12269 eap->nextcmd = find_nextcmd(end); 12270 } 12271 #endif 12272 12273 #ifdef FEAT_CRYPT 12274 /* 12275 * ":X": Get crypt key 12276 */ 12277 static void 12278 ex_X(exarg_T *eap UNUSED) 12279 { 12280 crypt_check_current_method(); 12281 (void)crypt_get_key(TRUE, TRUE); 12282 } 12283 #endif 12284 12285 #ifdef FEAT_FOLDING 12286 static void 12287 ex_fold(exarg_T *eap) 12288 { 12289 if (foldManualAllowed(TRUE)) 12290 foldCreate(eap->line1, eap->line2); 12291 } 12292 12293 static void 12294 ex_foldopen(exarg_T *eap) 12295 { 12296 opFoldRange(eap->line1, eap->line2, eap->cmdidx == CMD_foldopen, 12297 eap->forceit, FALSE); 12298 } 12299 12300 static void 12301 ex_folddo(exarg_T *eap) 12302 { 12303 linenr_T lnum; 12304 12305 #ifdef FEAT_CLIPBOARD 12306 start_global_changes(); 12307 #endif 12308 12309 /* First set the marks for all lines closed/open. */ 12310 for (lnum = eap->line1; lnum <= eap->line2; ++lnum) 12311 if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) 12312 ml_setmarked(lnum); 12313 12314 /* Execute the command on the marked lines. */ 12315 global_exe(eap->arg); 12316 ml_clearmarked(); /* clear rest of the marks */ 12317 #ifdef FEAT_CLIPBOARD 12318 end_global_changes(); 12319 #endif 12320 } 12321 #endif 12322 12323 # if defined(FEAT_TIMERS) || defined(PROTO) 12324 int 12325 get_pressedreturn(void) 12326 { 12327 return ex_pressedreturn; 12328 } 12329 12330 void 12331 set_pressedreturn(int val) 12332 { 12333 ex_pressedreturn = val; 12334 } 12335 #endif 12336