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