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