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 #define EXTERN 11 #include "vim.h" 12 13 #ifdef __CYGWIN__ 14 # ifndef MSWIN 15 # include <cygwin/version.h> 16 # include <sys/cygwin.h> // for cygwin_conv_to_posix_path() and/or 17 // cygwin_conv_path() 18 # endif 19 # include <limits.h> 20 #endif 21 22 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 23 # include "iscygpty.h" 24 #endif 25 26 // Values for edit_type. 27 #define EDIT_NONE 0 // no edit type yet 28 #define EDIT_FILE 1 // file name argument[s] given, use argument list 29 #define EDIT_STDIN 2 // read file from stdin 30 #define EDIT_TAG 3 // tag name argument given, use tagname 31 #define EDIT_QF 4 // start in quickfix mode 32 33 #if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN) 34 static int file_owned(char *fname); 35 #endif 36 static void mainerr(int, char_u *); 37 static void early_arg_scan(mparm_T *parmp); 38 #ifndef NO_VIM_MAIN 39 static void usage(void); 40 static void parse_command_name(mparm_T *parmp); 41 static void command_line_scan(mparm_T *parmp); 42 static void check_tty(mparm_T *parmp); 43 static void read_stdin(void); 44 static void create_windows(mparm_T *parmp); 45 static void edit_buffers(mparm_T *parmp, char_u *cwd); 46 static void exe_pre_commands(mparm_T *parmp); 47 static void exe_commands(mparm_T *parmp); 48 static void source_startup_scripts(mparm_T *parmp); 49 static void main_start_gui(void); 50 static void check_swap_exists_action(void); 51 # ifdef FEAT_EVAL 52 static void set_progpath(char_u *argv0); 53 # endif 54 #endif 55 56 57 /* 58 * Different types of error messages. 59 */ 60 static char *(main_errors[]) = 61 { 62 N_("Unknown option argument"), 63 #define ME_UNKNOWN_OPTION 0 64 N_("Too many edit arguments"), 65 #define ME_TOO_MANY_ARGS 1 66 N_("Argument missing after"), 67 #define ME_ARG_MISSING 2 68 N_("Garbage after option argument"), 69 #define ME_GARBAGE 3 70 N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"), 71 #define ME_EXTRA_CMD 4 72 N_("Invalid argument for"), 73 #define ME_INVALID_ARG 5 74 }; 75 76 #ifndef PROTO // don't want a prototype for main() 77 78 // Various parameters passed between main() and other functions. 79 static mparm_T params; 80 81 #ifndef NO_VIM_MAIN // skip this for unittests 82 83 static char_u *start_dir = NULL; // current working dir on startup 84 85 static int has_dash_c_arg = FALSE; 86 87 # ifdef VIMDLL 88 __declspec(dllexport) 89 # endif 90 int 91 # ifdef MSWIN 92 VimMain 93 # else 94 main 95 # endif 96 (int argc, char **argv) 97 { 98 #if defined(STARTUPTIME) || defined(CLEAN_RUNTIMEPATH) 99 int i; 100 #endif 101 102 /* 103 * Do any system-specific initialisations. These can NOT use IObuff or 104 * NameBuff. Thus emsg2() cannot be called! 105 */ 106 mch_early_init(); 107 108 #ifdef MSWIN 109 /* 110 * MinGW expands command line arguments, which confuses our code to 111 * convert when 'encoding' changes. Get the unexpanded arguments. 112 */ 113 argc = get_cmd_argsW(&argv); 114 #endif 115 116 // Many variables are in "params" so that we can pass them to invoked 117 // functions without a lot of arguments. "argc" and "argv" are also 118 // copied, so that they can be changed. 119 CLEAR_FIELD(params); 120 params.argc = argc; 121 params.argv = argv; 122 params.want_full_screen = TRUE; 123 #ifdef FEAT_EVAL 124 params.use_debug_break_level = -1; 125 #endif 126 params.window_count = -1; 127 128 #ifdef FEAT_RUBY 129 { 130 int ruby_stack_start; 131 vim_ruby_init((void *)&ruby_stack_start); 132 } 133 #endif 134 135 #ifdef FEAT_TCL 136 vim_tcl_init(params.argv[0]); 137 #endif 138 139 #ifdef MEM_PROFILE 140 atexit(vim_mem_profile_dump); 141 #endif 142 143 #ifdef STARTUPTIME 144 // Need to find "--startuptime" before actually parsing arguments. 145 for (i = 1; i < argc - 1; ++i) 146 if (STRICMP(argv[i], "--startuptime") == 0) 147 { 148 time_fd = mch_fopen(argv[i + 1], "a"); 149 TIME_MSG("--- VIM STARTING ---"); 150 break; 151 } 152 #endif 153 starttime = time(NULL); 154 155 #ifdef CLEAN_RUNTIMEPATH 156 // Need to find "--clean" before actually parsing arguments. 157 for (i = 1; i < argc; ++i) 158 if (STRICMP(argv[i], "--clean") == 0) 159 { 160 params.clean = TRUE; 161 break; 162 } 163 #endif 164 common_init(¶ms); 165 166 #ifdef VIMDLL 167 // Check if the current executable file is for the GUI subsystem. 168 gui.starting = mch_is_gui_executable(); 169 #elif defined(FEAT_GUI_MSWIN) 170 gui.starting = TRUE; 171 #endif 172 173 #ifdef FEAT_CLIENTSERVER 174 /* 175 * Do the client-server stuff, unless "--servername ''" was used. 176 * This may exit Vim if the command was sent to the server. 177 */ 178 exec_on_server(¶ms); 179 #endif 180 181 /* 182 * Figure out the way to work from the command name argv[0]. 183 * "vimdiff" starts diff mode, "rvim" sets "restricted", etc. 184 */ 185 parse_command_name(¶ms); 186 187 /* 188 * Process the command line arguments. File names are put in the global 189 * argument list "global_alist". 190 */ 191 command_line_scan(¶ms); 192 TIME_MSG("parsing arguments"); 193 194 /* 195 * On some systems, when we compile with the GUI, we always use it. On Mac 196 * there is no terminal version, and on Windows we can't fork one off with 197 * :gui. 198 */ 199 #ifdef ALWAYS_USE_GUI 200 gui.starting = TRUE; 201 #else 202 # if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) 203 /* 204 * Check if the GUI can be started. Reset gui.starting if not. 205 * Don't know about other systems, stay on the safe side and don't check. 206 */ 207 if (gui.starting) 208 { 209 if (gui_init_check() == FAIL) 210 { 211 gui.starting = FALSE; 212 213 // When running "evim" or "gvim -y" we need the menus, exit if we 214 // don't have them. 215 if (params.evim_mode) 216 mch_exit(1); 217 } 218 } 219 # endif 220 #endif 221 222 if (GARGCOUNT > 0) 223 { 224 #ifdef EXPAND_FILENAMES 225 /* 226 * Expand wildcards in file names. 227 */ 228 if (!params.literal) 229 { 230 start_dir = alloc(MAXPATHL); 231 if (start_dir != NULL) 232 mch_dirname(start_dir, MAXPATHL); 233 // Temporarily add '(' and ')' to 'isfname'. These are valid 234 // filename characters but are excluded from 'isfname' to make 235 // "gf" work on a file name in parenthesis (e.g.: see vim.h). 236 do_cmdline_cmd((char_u *)":set isf+=(,)"); 237 alist_expand(NULL, 0); 238 do_cmdline_cmd((char_u *)":set isf&"); 239 if (start_dir != NULL) 240 mch_chdir((char *)start_dir); 241 } 242 #endif 243 params.fname = alist_name(&GARGLIST[0]); 244 } 245 246 #ifdef MSWIN 247 { 248 extern void set_alist_count(void); 249 250 // Remember the number of entries in the argument list. If it changes 251 // we don't react on setting 'encoding'. 252 set_alist_count(); 253 } 254 #endif 255 256 #ifdef MSWIN 257 if (GARGCOUNT == 1 && params.full_path) 258 { 259 /* 260 * If there is one filename, fully qualified, we have very probably 261 * been invoked from explorer, so change to the file's directory. 262 * Hint: to avoid this when typing a command use a forward slash. 263 * If the cd fails, it doesn't matter. 264 */ 265 (void)vim_chdirfile(params.fname, "drop"); 266 if (start_dir != NULL) 267 mch_dirname(start_dir, MAXPATHL); 268 } 269 #endif 270 TIME_MSG("expanding arguments"); 271 272 #ifdef FEAT_DIFF 273 if (params.diff_mode && params.window_count == -1) 274 params.window_count = 0; // open up to 3 windows 275 #endif 276 277 // Don't redraw until much later. 278 ++RedrawingDisabled; 279 280 /* 281 * When listing swap file names, don't do cursor positioning et. al. 282 */ 283 if (recoverymode && params.fname == NULL) 284 params.want_full_screen = FALSE; 285 286 /* 287 * When certain to start the GUI, don't check capabilities of terminal. 288 * For GTK we can't be sure, but when started from the desktop it doesn't 289 * make sense to try using a terminal. 290 */ 291 #if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ 292 || defined(VIMDLL) 293 if (gui.starting 294 # ifdef FEAT_GUI_GTK 295 && !isatty(2) 296 # endif 297 ) 298 params.want_full_screen = FALSE; 299 #endif 300 301 #if defined(FEAT_GUI_MAC) && defined(MACOS_X_DARWIN) 302 // When the GUI is started from Finder, need to display messages in a 303 // message box. isatty(2) returns TRUE anyway, thus we need to check the 304 // name to know we're not started from a terminal. 305 if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0)) 306 { 307 params.want_full_screen = FALSE; 308 309 // Avoid always using "/" as the current directory. Note that when 310 // started from Finder the arglist will be filled later in 311 // HandleODocAE() and "fname" will be NULL. 312 if (getcwd((char *)NameBuff, MAXPATHL) != NULL 313 && STRCMP(NameBuff, "/") == 0) 314 { 315 if (params.fname != NULL) 316 (void)vim_chdirfile(params.fname, "drop"); 317 else 318 { 319 expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); 320 vim_chdir(NameBuff); 321 } 322 if (start_dir != NULL) 323 mch_dirname(start_dir, MAXPATHL); 324 } 325 } 326 #endif 327 328 /* 329 * mch_init() sets up the terminal (window) for use. This must be 330 * done after resetting full_screen, otherwise it may move the cursor. 331 * Note that we may use mch_exit() before mch_init()! 332 */ 333 mch_init(); 334 TIME_MSG("shell init"); 335 336 #ifdef USE_XSMP 337 /* 338 * For want of anywhere else to do it, try to connect to xsmp here. 339 * Fitting it in after gui_mch_init, but before gui_init (via termcapinit). 340 * Hijacking -X 'no X connection' to also disable XSMP connection as that 341 * has a similar delay upon failure. 342 * Only try if SESSION_MANAGER is set to something non-null. 343 */ 344 if (!x_no_connect) 345 { 346 char *p = getenv("SESSION_MANAGER"); 347 348 if (p != NULL && *p != NUL) 349 { 350 xsmp_init(); 351 TIME_MSG("xsmp init"); 352 } 353 } 354 #endif 355 356 /* 357 * Print a warning if stdout is not a terminal. 358 */ 359 check_tty(¶ms); 360 361 #ifdef _IOLBF 362 // Ensure output works usefully without a tty: buffer lines instead of 363 // fully buffered. 364 if (silent_mode) 365 setvbuf(stdout, NULL, _IOLBF, 0); 366 #endif 367 368 // This message comes before term inits, but after setting "silent_mode" 369 // when the input is not a tty. Omit the message with --not-a-term. 370 if (GARGCOUNT > 1 && !silent_mode && !is_not_a_term()) 371 printf(_("%d files to edit\n"), GARGCOUNT); 372 373 if (params.want_full_screen && !silent_mode) 374 { 375 termcapinit(params.term); // set terminal name and get terminal 376 // capabilities (will set full_screen) 377 screen_start(); // don't know where cursor is now 378 TIME_MSG("Termcap init"); 379 } 380 381 /* 382 * Set the default values for the options that use Rows and Columns. 383 */ 384 ui_get_shellsize(); // inits Rows and Columns 385 win_init_size(); 386 #ifdef FEAT_DIFF 387 // Set the 'diff' option now, so that it can be checked for in a .vimrc 388 // file. There is no buffer yet though. 389 if (params.diff_mode) 390 diff_win_options(firstwin, FALSE); 391 #endif 392 393 cmdline_row = Rows - p_ch; 394 msg_row = cmdline_row; 395 screenalloc(FALSE); // allocate screen buffers 396 set_init_2(); 397 TIME_MSG("inits 2"); 398 399 msg_scroll = TRUE; 400 no_wait_return = TRUE; 401 402 init_mappings(); // set up initial mappings 403 404 init_highlight(TRUE, FALSE); // set the default highlight groups 405 TIME_MSG("init highlight"); 406 407 #if defined(FEAT_TERMRESPONSE) 408 init_term_props(TRUE); 409 #endif 410 411 #ifdef FEAT_EVAL 412 // Set the break level after the terminal is initialized. 413 debug_break_level = params.use_debug_break_level; 414 #endif 415 416 // Reset 'loadplugins' for "-u NONE" before "--cmd" arguments. 417 // Allows for setting 'loadplugins' there. 418 if (params.use_vimrc != NULL 419 && (STRCMP(params.use_vimrc, "NONE") == 0 420 || STRCMP(params.use_vimrc, "DEFAULTS") == 0)) 421 p_lpl = FALSE; 422 423 // Execute --cmd arguments. 424 exe_pre_commands(¶ms); 425 426 // Source startup scripts. 427 source_startup_scripts(¶ms); 428 429 #ifdef FEAT_MZSCHEME 430 /* 431 * Newer version of MzScheme (Racket) require earlier (trampolined) 432 * initialisation via scheme_main_setup. 433 * Implement this by initialising it as early as possible 434 * and splitting off remaining Vim main into vim_main2(). 435 * Do source startup scripts, so that 'mzschemedll' can be set. 436 */ 437 return mzscheme_main(); 438 #else 439 return vim_main2(); 440 #endif 441 } 442 #endif // NO_VIM_MAIN 443 #endif // PROTO 444 445 /* 446 * vim_main2() is needed for FEAT_MZSCHEME, but we define it always to keep 447 * things simple. 448 * It is also defined when NO_VIM_MAIN is defined, but then it's empty. 449 */ 450 int 451 vim_main2(void) 452 { 453 #ifndef NO_VIM_MAIN 454 #ifdef FEAT_EVAL 455 /* 456 * Read all the plugin files. 457 * Only when compiled with +eval, since most plugins need it. 458 */ 459 if (p_lpl) 460 { 461 char_u *rtp_copy = NULL; 462 463 // First add all package directories to 'runtimepath', so that their 464 // autoload directories can be found. Only if not done already with a 465 // :packloadall command. 466 // Make a copy of 'runtimepath', so that source_runtime does not use 467 // the pack directories. 468 if (!did_source_packages) 469 { 470 rtp_copy = vim_strsave(p_rtp); 471 add_pack_start_dirs(); 472 } 473 474 source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy, 475 # ifdef VMS // Somehow VMS doesn't handle the "**". 476 (char_u *)"plugin/*.vim", 477 # else 478 (char_u *)"plugin/**/*.vim", 479 # endif 480 DIP_ALL | DIP_NOAFTER, NULL); 481 TIME_MSG("loading plugins"); 482 vim_free(rtp_copy); 483 484 // Only source "start" packages if not done already with a :packloadall 485 // command. 486 if (!did_source_packages) 487 load_start_packages(); 488 TIME_MSG("loading packages"); 489 490 # ifdef VMS // Somehow VMS doesn't handle the "**". 491 source_runtime((char_u *)"plugin/*.vim", DIP_ALL | DIP_AFTER); 492 # else 493 source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER); 494 # endif 495 TIME_MSG("loading after plugins"); 496 497 } 498 #endif 499 500 #ifdef FEAT_DIFF 501 // Decide about window layout for diff mode after reading vimrc. 502 if (params.diff_mode && params.window_layout == 0) 503 { 504 if (diffopt_horizontal()) 505 params.window_layout = WIN_HOR; // use horizontal split 506 else 507 params.window_layout = WIN_VER; // use vertical split 508 } 509 #endif 510 511 /* 512 * Recovery mode without a file name: List swap files. 513 * This uses the 'dir' option, therefore it must be after the 514 * initializations. 515 */ 516 if (recoverymode && params.fname == NULL) 517 { 518 recover_names(NULL, TRUE, 0, NULL); 519 mch_exit(0); 520 } 521 522 /* 523 * Set a few option defaults after reading .vimrc files: 524 * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'. 525 */ 526 set_init_3(); 527 TIME_MSG("inits 3"); 528 529 /* 530 * "-n" argument: Disable swap file by setting 'updatecount' to 0. 531 * Note that this overrides anything from a vimrc file. 532 */ 533 if (params.no_swap_file) 534 p_uc = 0; 535 536 #ifdef FEAT_GUI 537 if (gui.starting) 538 { 539 # if defined(UNIX) || defined(VMS) 540 // When something caused a message from a vimrc script, need to output 541 // an extra newline before the shell prompt. 542 if (did_emsg || msg_didout) 543 putchar('\n'); 544 # endif 545 546 gui_start(NULL); // will set full_screen to TRUE 547 TIME_MSG("starting GUI"); 548 549 // When running "evim" or "gvim -y" we need the menus, exit if we 550 // don't have them. 551 if (!gui.in_use && params.evim_mode) 552 mch_exit(1); 553 } 554 #endif 555 556 #ifdef FEAT_VIMINFO 557 /* 558 * Read in registers, history etc, but not marks, from the viminfo file. 559 * This is where v:oldfiles gets filled. 560 */ 561 if (*p_viminfo != NUL) 562 { 563 read_viminfo(NULL, VIF_WANT_INFO | VIF_GET_OLDFILES); 564 TIME_MSG("reading viminfo"); 565 } 566 #endif 567 #ifdef FEAT_EVAL 568 // It's better to make v:oldfiles an empty list than NULL. 569 if (get_vim_var_list(VV_OLDFILES) == NULL) 570 set_vim_var_list(VV_OLDFILES, list_alloc()); 571 #endif 572 573 #ifdef FEAT_QUICKFIX 574 /* 575 * "-q errorfile": Load the error file now. 576 * If the error file can't be read, exit before doing anything else. 577 */ 578 if (params.edit_type == EDIT_QF) 579 { 580 char_u *enc = NULL; 581 582 enc = p_menc; 583 if (params.use_ef != NULL) 584 set_string_option_direct((char_u *)"ef", -1, 585 params.use_ef, OPT_FREE, SID_CARG); 586 vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef); 587 if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff, enc) < 0) 588 { 589 out_char('\n'); 590 mch_exit(3); 591 } 592 TIME_MSG("reading errorfile"); 593 } 594 #endif 595 596 /* 597 * Start putting things on the screen. 598 * Scroll screen down before drawing over it 599 * Clear screen now, so file message will not be cleared. 600 */ 601 starting = NO_BUFFERS; 602 no_wait_return = FALSE; 603 if (!exmode_active) 604 msg_scroll = FALSE; 605 606 #ifdef FEAT_GUI 607 /* 608 * This seems to be required to make callbacks to be called now, instead 609 * of after things have been put on the screen, which then may be deleted 610 * when getting a resize callback. 611 * For the Mac this handles putting files dropped on the Vim icon to 612 * global_alist. 613 */ 614 if (gui.in_use) 615 { 616 gui_wait_for_chars(50L, typebuf.tb_change_cnt); 617 TIME_MSG("GUI delay"); 618 } 619 #endif 620 621 #if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD) 622 qnx_clip_init(); 623 #endif 624 625 #if defined(MACOS_X) && defined(FEAT_CLIPBOARD) 626 clip_init(TRUE); 627 #endif 628 629 #ifdef FEAT_XCLIPBOARD 630 // Start using the X clipboard, unless the GUI was started. 631 # ifdef FEAT_GUI 632 if (!gui.in_use) 633 # endif 634 { 635 setup_term_clip(); 636 TIME_MSG("setup clipboard"); 637 } 638 #endif 639 640 #ifdef FEAT_CLIENTSERVER 641 // Prepare for being a Vim server. 642 prepare_server(¶ms); 643 #endif 644 645 /* 646 * If "-" argument given: Read file from stdin. 647 * Do this before starting Raw mode, because it may change things that the 648 * writing end of the pipe doesn't like, e.g., in case stdin and stderr 649 * are the same terminal: "cat | vim -". 650 * Using autocommands here may cause trouble... 651 */ 652 if (params.edit_type == EDIT_STDIN && !recoverymode) 653 read_stdin(); 654 655 #if defined(UNIX) || defined(VMS) 656 // When switching screens and something caused a message from a vimrc 657 // script, need to output an extra newline on exit. 658 if ((did_emsg || msg_didout) && *T_TI != NUL) 659 newline_on_exit = TRUE; 660 #endif 661 662 /* 663 * When done something that is not allowed or error message call 664 * wait_return. This must be done before starttermcap(), because it may 665 * switch to another screen. It must be done after settmode(TMODE_RAW), 666 * because we want to react on a single key stroke. 667 * Call settmode and starttermcap here, so the T_KS and T_TI may be 668 * defined by termcapinit and redefined in .exrc. 669 */ 670 settmode(TMODE_RAW); 671 TIME_MSG("setting raw mode"); 672 673 if (need_wait_return || msg_didany) 674 { 675 wait_return(TRUE); 676 TIME_MSG("waiting for return"); 677 } 678 679 starttermcap(); // start termcap if not done by wait_return() 680 TIME_MSG("start termcap"); 681 682 setmouse(); // may start using the mouse 683 if (scroll_region) 684 scroll_region_reset(); // In case Rows changed 685 scroll_start(); // may scroll the screen to the right position 686 687 #if defined(FEAT_TITLE) && (defined(UNIX) || defined(VMS) || defined(MACOS_X)) 688 term_push_title(SAVE_RESTORE_BOTH); 689 #endif 690 691 /* 692 * Don't clear the screen when starting in Ex mode, unless using the GUI. 693 */ 694 if (exmode_active 695 #ifdef FEAT_GUI 696 && !gui.in_use 697 #endif 698 ) 699 must_redraw = CLEAR; 700 else 701 { 702 screenclear(); // clear screen 703 TIME_MSG("clearing screen"); 704 } 705 706 #ifdef FEAT_CRYPT 707 if (params.ask_for_key) 708 { 709 crypt_check_current_method(); 710 (void)crypt_get_key(TRUE, TRUE); 711 TIME_MSG("getting crypt key"); 712 } 713 #endif 714 715 no_wait_return = TRUE; 716 717 /* 718 * Create the requested number of windows and edit buffers in them. 719 * Also does recovery if "recoverymode" set. 720 */ 721 create_windows(¶ms); 722 TIME_MSG("opening buffers"); 723 724 #ifdef FEAT_EVAL 725 // clear v:swapcommand 726 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1); 727 #endif 728 729 // Ex starts at last line of the file 730 if (exmode_active) 731 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 732 733 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); 734 TIME_MSG("BufEnter autocommands"); 735 setpcmark(); 736 737 #ifdef FEAT_QUICKFIX 738 /* 739 * When started with "-q errorfile" jump to first error now. 740 */ 741 if (params.edit_type == EDIT_QF) 742 { 743 qf_jump(NULL, 0, 0, FALSE); 744 TIME_MSG("jump to first error"); 745 } 746 #endif 747 748 /* 749 * If opened more than one window, start editing files in the other 750 * windows. 751 */ 752 edit_buffers(¶ms, start_dir); 753 vim_free(start_dir); 754 755 #ifdef FEAT_DIFF 756 if (params.diff_mode) 757 { 758 win_T *wp; 759 760 // set options in each window for "vimdiff". 761 FOR_ALL_WINDOWS(wp) 762 diff_win_options(wp, TRUE); 763 } 764 #endif 765 766 /* 767 * Shorten any of the filenames, but only when absolute. 768 */ 769 shorten_fnames(FALSE); 770 771 /* 772 * Need to jump to the tag before executing the '-c command'. 773 * Makes "vim -c '/return' -t main" work. 774 */ 775 if (params.tagname != NULL) 776 { 777 swap_exists_did_quit = FALSE; 778 779 vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname); 780 do_cmdline_cmd(IObuff); 781 TIME_MSG("jumping to tag"); 782 783 // If the user doesn't want to edit the file then we quit here. 784 if (swap_exists_did_quit) 785 getout(1); 786 } 787 788 // Execute any "+", "-c" and "-S" arguments. 789 if (params.n_commands > 0) 790 exe_commands(¶ms); 791 792 // Must come before the may_req_ calls. 793 starting = 0; 794 795 #if defined(FEAT_TERMRESPONSE) 796 // Must be done before redrawing, puts a few characters on the screen. 797 check_terminal_behavior(); 798 #endif 799 800 RedrawingDisabled = 0; 801 redraw_all_later(NOT_VALID); 802 no_wait_return = FALSE; 803 804 // 'autochdir' has been postponed 805 DO_AUTOCHDIR; 806 807 #ifdef FEAT_TERMRESPONSE 808 // Requesting the termresponse is postponed until here, so that a "-c q" 809 // argument doesn't make it appear in the shell Vim was started from. 810 may_req_termresponse(); 811 812 may_req_bg_color(); 813 #endif 814 815 // start in insert mode 816 if (p_im) 817 need_start_insertmode = TRUE; 818 819 #ifdef FEAT_EVAL 820 set_vim_var_nr(VV_VIM_DID_ENTER, 1L); 821 #endif 822 apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf); 823 TIME_MSG("VimEnter autocommands"); 824 825 #if defined(FEAT_EVAL) && defined(FEAT_CLIPBOARD) 826 // Adjust default register name for "unnamed" in 'clipboard'. Can only be 827 // done after the clipboard is available and all initial commands that may 828 // modify the 'clipboard' setting have run; i.e. just before entering the 829 // main loop. 830 reset_reg_var(); 831 #endif 832 833 #if defined(FEAT_DIFF) 834 // When a startup script or session file setup for diff'ing and 835 // scrollbind, sync the scrollbind now. 836 if (curwin->w_p_diff && curwin->w_p_scb) 837 { 838 update_topline(); 839 check_scrollbind((linenr_T)0, 0L); 840 TIME_MSG("diff scrollbinding"); 841 } 842 #endif 843 844 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 845 # ifdef VIMDLL 846 if (!gui.in_use) 847 # endif 848 mch_set_winsize_now(); // Allow winsize changes from now on 849 #endif 850 851 #if defined(FEAT_GUI) 852 // When tab pages were created, may need to update the tab pages line and 853 // scrollbars. This is skipped while creating them. 854 if (first_tabpage->tp_next != NULL) 855 { 856 out_flush(); 857 gui_init_which_components(NULL); 858 gui_update_scrollbars(TRUE); 859 } 860 need_mouse_correct = TRUE; 861 #endif 862 863 // If ":startinsert" command used, stuff a dummy command to be able to 864 // call normal_cmd(), which will then start Insert mode. 865 if (restart_edit != 0) 866 stuffcharReadbuff(K_NOP); 867 868 #ifdef FEAT_NETBEANS_INTG 869 if (netbeansArg != NULL && strncmp("-nb", netbeansArg, 3) == 0) 870 { 871 # ifdef FEAT_GUI 872 # if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \ 873 && !defined(FEAT_GUI_MSWIN) 874 if (gui.in_use) 875 { 876 mch_errmsg(_("netbeans is not supported with this GUI\n")); 877 mch_exit(2); 878 } 879 # endif 880 # endif 881 // Tell the client that it can start sending commands. 882 netbeans_open(netbeansArg + 3, TRUE); 883 } 884 #endif 885 886 // Redraw at least once, also when 'lazyredraw' is set, to make sure the 887 // window title gets updated. 888 do_redraw = TRUE; 889 890 TIME_MSG("before starting main loop"); 891 892 /* 893 * Call the main command loop. This never returns. 894 */ 895 main_loop(FALSE, FALSE); 896 897 #endif // NO_VIM_MAIN 898 899 return 0; 900 } 901 902 /* 903 * Initialisation shared by main() and some tests. 904 */ 905 void 906 common_init(mparm_T *paramp) 907 { 908 estack_init(); 909 cmdline_init(); 910 911 (void)mb_init(); // init mb_bytelen_tab[] to ones 912 #ifdef FEAT_EVAL 913 eval_init(); // init global variables 914 #endif 915 916 #ifdef __QNXNTO__ 917 qnx_init(); // PhAttach() for clipboard, (and gui) 918 #endif 919 920 // Init the table of Normal mode commands. 921 init_normal_cmds(); 922 923 /* 924 * Allocate space for the generic buffers (needed for set_init_1() and 925 * emsg()). 926 */ 927 if ((IObuff = alloc(IOSIZE)) == NULL 928 || (NameBuff = alloc(MAXPATHL)) == NULL) 929 mch_exit(0); 930 TIME_MSG("Allocated generic buffers"); 931 932 #ifdef NBDEBUG 933 // Wait a moment for debugging NetBeans. Must be after allocating 934 // NameBuff. 935 nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL"); 936 nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20); 937 TIME_MSG("NetBeans debug wait"); 938 #endif 939 940 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 941 /* 942 * Setup to use the current locale (for ctype() and many other things). 943 * NOTE: Translated messages with encodings other than latin1 will not 944 * work until set_init_1() has been called! 945 */ 946 init_locale(); 947 TIME_MSG("locale set"); 948 #endif 949 950 #ifdef FEAT_GUI 951 gui.dofork = TRUE; // default is to use fork() 952 #endif 953 954 /* 955 * Do a first scan of the arguments in "argv[]": 956 * -display or --display 957 * --server... 958 * --socketid 959 * --windowid 960 */ 961 early_arg_scan(paramp); 962 963 #if defined(FEAT_GUI) 964 // Prepare for possibly starting GUI sometime 965 gui_prepare(¶mp->argc, paramp->argv); 966 TIME_MSG("GUI prepared"); 967 #endif 968 969 #ifdef FEAT_CLIPBOARD 970 clip_init(FALSE); // Initialise clipboard stuff 971 TIME_MSG("clipboard setup"); 972 #endif 973 974 /* 975 * Check if we have an interactive window. 976 * On the Amiga: If there is no window, we open one with a newcli command 977 * (needed for :! to * work). mch_check_win() will also handle the -d or 978 * -dev argument. 979 */ 980 stdout_isatty = (mch_check_win(paramp->argc, paramp->argv) != FAIL); 981 TIME_MSG("window checked"); 982 983 /* 984 * Allocate the first window and buffer. 985 * Can't do anything without it, exit when it fails. 986 */ 987 if (win_alloc_first() == FAIL) 988 mch_exit(0); 989 990 init_yank(); // init yank buffers 991 992 alist_init(&global_alist); // Init the argument list to empty. 993 global_alist.id = 0; 994 995 /* 996 * Set the default values for the options. 997 * NOTE: Non-latin1 translated messages are working only after this, 998 * because this is where "has_mbyte" will be set, which is used by 999 * msg_outtrans_len_attr(). 1000 * First find out the home directory, needed to expand "~" in options. 1001 */ 1002 init_homedir(); // find real value of $HOME 1003 set_init_1(paramp->clean); 1004 TIME_MSG("inits 1"); 1005 1006 #ifdef FEAT_EVAL 1007 // set v:lang and v:ctype 1008 set_lang_var(); 1009 1010 // set v:argv 1011 set_argv_var(paramp->argv, paramp->argc); 1012 #endif 1013 1014 #ifdef FEAT_SIGNS 1015 init_signs(); 1016 #endif 1017 } 1018 1019 /* 1020 * Return TRUE when the --not-a-term argument was found. 1021 */ 1022 int 1023 is_not_a_term() 1024 { 1025 return params.not_a_term; 1026 } 1027 1028 1029 // When TRUE in a safe state when starting to wait for a character. 1030 static int was_safe = FALSE; 1031 static oparg_T *current_oap = NULL; 1032 1033 /* 1034 * Return TRUE if an operator was started but not finished yet. 1035 * Includes typing a count or a register name. 1036 */ 1037 int 1038 op_pending(void) 1039 { 1040 return !(current_oap != NULL 1041 && !finish_op 1042 && current_oap->prev_opcount == 0 1043 && current_oap->prev_count0 == 0 1044 && current_oap->op_type == OP_NOP 1045 && current_oap->regname == NUL); 1046 } 1047 1048 /* 1049 * Return whether currently it is safe, assuming it was safe before (high level 1050 * state didn't change). 1051 */ 1052 static int 1053 is_safe_now(void) 1054 { 1055 return stuff_empty() 1056 && typebuf.tb_len == 0 1057 && scriptin[curscript] == NULL 1058 && !global_busy; 1059 } 1060 1061 /* 1062 * Trigger SafeState if currently in s safe state, that is "safe" is TRUE and 1063 * there is no typeahead. 1064 */ 1065 void 1066 may_trigger_safestate(int safe) 1067 { 1068 int is_safe = safe && is_safe_now(); 1069 1070 #ifdef FEAT_JOB_CHANNEL 1071 if (was_safe != is_safe) 1072 // Only log when the state changes, otherwise it happens at nearly 1073 // every key stroke. 1074 ch_log(NULL, is_safe ? "SafeState: Start triggering" 1075 : "SafeState: Stop triggering"); 1076 #endif 1077 if (is_safe) 1078 apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf); 1079 was_safe = is_safe; 1080 } 1081 1082 /* 1083 * Something changed which causes the state possibly to be unsafe, e.g. a 1084 * character was typed. It will remain unsafe until the next call to 1085 * may_trigger_safestate(). 1086 */ 1087 void 1088 state_no_longer_safe(char *reason UNUSED) 1089 { 1090 #ifdef FEAT_JOB_CHANNEL 1091 if (was_safe) 1092 ch_log(NULL, "SafeState: reset: %s", reason); 1093 #endif 1094 was_safe = FALSE; 1095 } 1096 1097 int 1098 get_was_safe_state(void) 1099 { 1100 return was_safe; 1101 } 1102 1103 /* 1104 * Invoked when leaving code that invokes callbacks. Then trigger 1105 * SafeStateAgain, if it was safe when starting to wait for a character. 1106 */ 1107 void 1108 may_trigger_safestateagain(void) 1109 { 1110 if (!was_safe) 1111 { 1112 // If the safe state was reset in state_no_longer_safe(), e.g. because 1113 // of calling feedkeys(), we check if it's now safe again (all keys 1114 // were consumed). 1115 was_safe = is_safe_now(); 1116 #ifdef FEAT_JOB_CHANNEL 1117 if (was_safe) 1118 ch_log(NULL, "SafeState: undo reset"); 1119 #endif 1120 } 1121 if (was_safe) 1122 { 1123 #ifdef FEAT_JOB_CHANNEL 1124 // Only do this message when another message was given, otherwise we 1125 // get lots of them. 1126 if ((did_repeated_msg & REPEATED_MSG_SAFESTATE) == 0) 1127 { 1128 int did = did_repeated_msg; 1129 1130 ch_log(NULL, 1131 "SafeState: back to waiting, triggering SafeStateAgain"); 1132 did_repeated_msg = did | REPEATED_MSG_SAFESTATE; 1133 } 1134 #endif 1135 apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf); 1136 } 1137 #ifdef FEAT_JOB_CHANNEL 1138 else 1139 ch_log(NULL, 1140 "SafeState: back to waiting, not triggering SafeStateAgain"); 1141 #endif 1142 } 1143 1144 1145 /* 1146 * Main loop: Execute Normal mode commands until exiting Vim. 1147 * Also used to handle commands in the command-line window, until the window 1148 * is closed. 1149 * Also used to handle ":visual" command after ":global": execute Normal mode 1150 * commands, return when entering Ex mode. "noexmode" is TRUE then. 1151 */ 1152 void 1153 main_loop( 1154 int cmdwin, // TRUE when working in the command-line window 1155 int noexmode) // TRUE when return on entering Ex mode 1156 { 1157 oparg_T oa; // operator arguments 1158 oparg_T *prev_oap; // operator arguments 1159 volatile int previous_got_int = FALSE; // "got_int" was TRUE 1160 #ifdef FEAT_CONCEAL 1161 // these are static to avoid a compiler warning 1162 static linenr_T conceal_old_cursor_line = 0; 1163 static linenr_T conceal_new_cursor_line = 0; 1164 static int conceal_update_lines = FALSE; 1165 #endif 1166 1167 prev_oap = current_oap; 1168 current_oap = &oa; 1169 1170 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD) 1171 // Setup to catch a terminating error from the X server. Just ignore 1172 // it, restore the state and continue. This might not always work 1173 // properly, but at least we don't exit unexpectedly when the X server 1174 // exits while Vim is running in a console. 1175 if (!cmdwin && !noexmode && SETJMP(x_jump_env)) 1176 { 1177 State = NORMAL; 1178 VIsual_active = FALSE; 1179 got_int = TRUE; 1180 need_wait_return = FALSE; 1181 global_busy = FALSE; 1182 exmode_active = 0; 1183 skip_redraw = FALSE; 1184 RedrawingDisabled = 0; 1185 no_wait_return = 0; 1186 vgetc_busy = 0; 1187 # ifdef FEAT_EVAL 1188 emsg_skip = 0; 1189 # endif 1190 emsg_off = 0; 1191 setmouse(); 1192 settmode(TMODE_RAW); 1193 starttermcap(); 1194 scroll_start(); 1195 redraw_later_clear(); 1196 } 1197 #endif 1198 1199 clear_oparg(&oa); 1200 while (!cmdwin 1201 #ifdef FEAT_CMDWIN 1202 || cmdwin_result == 0 1203 #endif 1204 ) 1205 { 1206 if (stuff_empty()) 1207 { 1208 did_check_timestamps = FALSE; 1209 if (need_check_timestamps) 1210 check_timestamps(FALSE); 1211 if (need_wait_return) // if wait_return still needed ... 1212 wait_return(FALSE); // ... call it now 1213 if (need_start_insertmode && goto_im() && !VIsual_active) 1214 { 1215 need_start_insertmode = FALSE; 1216 stuffReadbuff((char_u *)"i"); // start insert mode next 1217 // skip the fileinfo message now, because it would be shown 1218 // after insert mode finishes! 1219 need_fileinfo = FALSE; 1220 } 1221 } 1222 1223 // Reset "got_int" now that we got back to the main loop. Except when 1224 // inside a ":g/pat/cmd" command, then the "got_int" needs to abort 1225 // the ":g" command. 1226 // For ":g/pat/vi" we reset "got_int" when used once. When used 1227 // a second time we go back to Ex mode and abort the ":g" command. 1228 if (got_int) 1229 { 1230 if (noexmode && global_busy && !exmode_active && previous_got_int) 1231 { 1232 // Typed two CTRL-C in a row: go back to ex mode as if "Q" was 1233 // used and keep "got_int" set, so that it aborts ":g". 1234 exmode_active = EXMODE_NORMAL; 1235 State = NORMAL; 1236 } 1237 else if (!global_busy || !exmode_active) 1238 { 1239 if (!quit_more) 1240 (void)vgetc(); // flush all buffers 1241 got_int = FALSE; 1242 } 1243 previous_got_int = TRUE; 1244 } 1245 else 1246 previous_got_int = FALSE; 1247 1248 if (!exmode_active) 1249 msg_scroll = FALSE; 1250 quit_more = FALSE; 1251 1252 // it's not safe unless may_trigger_safestate_main() is called 1253 was_safe = FALSE; 1254 1255 /* 1256 * If skip redraw is set (for ":" in wait_return()), don't redraw now. 1257 * If there is nothing in the stuff_buffer or do_redraw is TRUE, 1258 * update cursor and redraw. 1259 */ 1260 if (skip_redraw || exmode_active) 1261 skip_redraw = FALSE; 1262 else if (do_redraw || stuff_empty()) 1263 { 1264 #ifdef FEAT_GUI 1265 // If ui_breakcheck() was used a resize may have been postponed. 1266 gui_may_resize_shell(); 1267 #endif 1268 #ifdef HAVE_DROP_FILE 1269 // If files were dropped while text was locked or the curbuf was 1270 // locked, this would be a good time to handle the drop. 1271 handle_any_postponed_drop(); 1272 #endif 1273 #ifdef FEAT_CONCEAL 1274 if (curwin->w_p_cole == 0) 1275 conceal_update_lines = FALSE; 1276 #endif 1277 1278 // Trigger CursorMoved if the cursor moved. 1279 if (!finish_op && ( 1280 has_cursormoved() 1281 #ifdef FEAT_PROP_POPUP 1282 || popup_visible 1283 #endif 1284 #ifdef FEAT_CONCEAL 1285 || curwin->w_p_cole > 0 1286 #endif 1287 ) 1288 && !EQUAL_POS(last_cursormoved, curwin->w_cursor)) 1289 { 1290 if (has_cursormoved()) 1291 apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, 1292 FALSE, curbuf); 1293 #ifdef FEAT_PROP_POPUP 1294 if (popup_visible) 1295 popup_check_cursor_pos(); 1296 #endif 1297 #ifdef FEAT_CONCEAL 1298 if (curwin->w_p_cole > 0) 1299 { 1300 conceal_old_cursor_line = last_cursormoved.lnum; 1301 conceal_new_cursor_line = curwin->w_cursor.lnum; 1302 conceal_update_lines = TRUE; 1303 } 1304 #endif 1305 last_cursormoved = curwin->w_cursor; 1306 } 1307 1308 #if defined(FEAT_CONCEAL) 1309 if (conceal_update_lines 1310 && (conceal_old_cursor_line != conceal_new_cursor_line 1311 || conceal_cursor_line(curwin) 1312 || need_cursor_line_redraw)) 1313 { 1314 if (conceal_old_cursor_line != conceal_new_cursor_line 1315 && conceal_old_cursor_line != 0 1316 && conceal_old_cursor_line 1317 <= curbuf->b_ml.ml_line_count) 1318 redrawWinline(curwin, conceal_old_cursor_line); 1319 redrawWinline(curwin, conceal_new_cursor_line); 1320 curwin->w_valid &= ~VALID_CROW; 1321 need_cursor_line_redraw = FALSE; 1322 } 1323 #endif 1324 1325 // Trigger TextChanged if b:changedtick differs. 1326 if (!finish_op && has_textchanged() 1327 && curbuf->b_last_changedtick != CHANGEDTICK(curbuf)) 1328 { 1329 apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf); 1330 curbuf->b_last_changedtick = CHANGEDTICK(curbuf); 1331 } 1332 1333 // If nothing is pending and we are going to wait for the user to 1334 // type a character, trigger SafeState. 1335 may_trigger_safestate(!op_pending() && restart_edit == 0); 1336 1337 #if defined(FEAT_DIFF) 1338 // Updating diffs from changed() does not always work properly, 1339 // esp. updating folds. Do an update just before redrawing if 1340 // needed. 1341 if (curtab->tp_diff_update || curtab->tp_diff_invalid) 1342 { 1343 ex_diffupdate(NULL); 1344 curtab->tp_diff_update = FALSE; 1345 } 1346 1347 // Scroll-binding for diff mode may have been postponed until 1348 // here. Avoids doing it for every change. 1349 if (diff_need_scrollbind) 1350 { 1351 check_scrollbind((linenr_T)0, 0L); 1352 diff_need_scrollbind = FALSE; 1353 } 1354 #endif 1355 #if defined(FEAT_FOLDING) 1356 // Include a closed fold completely in the Visual area. 1357 foldAdjustVisual(); 1358 #endif 1359 #ifdef FEAT_FOLDING 1360 /* 1361 * When 'foldclose' is set, apply 'foldlevel' to folds that don't 1362 * contain the cursor. 1363 * When 'foldopen' is "all", open the fold(s) under the cursor. 1364 * This may mark the window for redrawing. 1365 */ 1366 if (hasAnyFolding(curwin) && !char_avail()) 1367 { 1368 foldCheckClose(); 1369 if (fdo_flags & FDO_ALL) 1370 foldOpenCursor(); 1371 } 1372 #endif 1373 1374 /* 1375 * Before redrawing, make sure w_topline is correct, and w_leftcol 1376 * if lines don't wrap, and w_skipcol if lines wrap. 1377 */ 1378 update_topline(); 1379 validate_cursor(); 1380 1381 #ifdef FEAT_SYN_HL 1382 // Might need to update for 'cursorline'. 1383 // When 'cursorlineopt' is "screenline" need to redraw always. 1384 if (curwin->w_p_cul 1385 && (curwin->w_last_cursorline != curwin->w_cursor.lnum 1386 || (curwin->w_p_culopt_flags & CULOPT_SCRLINE)) 1387 && !char_avail()) 1388 redraw_later(VALID); 1389 #endif 1390 if (VIsual_active) 1391 update_curbuf(INVERTED); // update inverted part 1392 else if (must_redraw) 1393 { 1394 mch_disable_flush(); // Stop issuing gui_mch_flush(). 1395 update_screen(0); 1396 mch_enable_flush(); 1397 } 1398 else if (redraw_cmdline || clear_cmdline) 1399 showmode(); 1400 redraw_statuslines(); 1401 #ifdef FEAT_TITLE 1402 if (need_maketitle) 1403 maketitle(); 1404 #endif 1405 #ifdef FEAT_VIMINFO 1406 curbuf->b_last_used = vim_time(); 1407 #endif 1408 // display message after redraw 1409 if (keep_msg != NULL) 1410 { 1411 char_u *p = vim_strsave(keep_msg); 1412 1413 if (p != NULL) 1414 { 1415 // msg_start() will set keep_msg to NULL, make a copy 1416 // first. Don't reset keep_msg, msg_attr_keep() uses it to 1417 // check for duplicates. Never put this message in 1418 // history. 1419 msg_hist_off = TRUE; 1420 msg_attr((char *)p, keep_msg_attr); 1421 msg_hist_off = FALSE; 1422 vim_free(p); 1423 } 1424 } 1425 if (need_fileinfo) // show file info after redraw 1426 { 1427 fileinfo(FALSE, TRUE, FALSE); 1428 need_fileinfo = FALSE; 1429 } 1430 1431 emsg_on_display = FALSE; // can delete error message now 1432 did_emsg = FALSE; 1433 msg_didany = FALSE; // reset lines_left in msg_start() 1434 may_clear_sb_text(); // clear scroll-back text on next msg 1435 showruler(FALSE); 1436 1437 setcursor(); 1438 cursor_on(); 1439 1440 do_redraw = FALSE; 1441 1442 #ifdef STARTUPTIME 1443 // Now that we have drawn the first screen all the startup stuff 1444 // has been done, close any file for startup messages. 1445 if (time_fd != NULL) 1446 { 1447 TIME_MSG("first screen update"); 1448 TIME_MSG("--- VIM STARTED ---"); 1449 fclose(time_fd); 1450 time_fd = NULL; 1451 } 1452 #endif 1453 } 1454 #ifdef FEAT_GUI 1455 if (need_mouse_correct) 1456 gui_mouse_correct(); 1457 #endif 1458 1459 /* 1460 * Update w_curswant if w_set_curswant has been set. 1461 * Postponed until here to avoid computing w_virtcol too often. 1462 */ 1463 update_curswant(); 1464 1465 #ifdef FEAT_EVAL 1466 /* 1467 * May perform garbage collection when waiting for a character, but 1468 * only at the very toplevel. Otherwise we may be using a List or 1469 * Dict internally somewhere. 1470 * "may_garbage_collect" is reset in vgetc() which is invoked through 1471 * do_exmode() and normal_cmd(). 1472 */ 1473 may_garbage_collect = (!cmdwin && !noexmode); 1474 #endif 1475 /* 1476 * If we're invoked as ex, do a round of ex commands. 1477 * Otherwise, get and execute a normal mode command. 1478 */ 1479 if (exmode_active) 1480 { 1481 if (noexmode) // End of ":global/path/visual" commands 1482 goto theend; 1483 do_exmode(exmode_active == EXMODE_VIM); 1484 } 1485 else 1486 { 1487 #ifdef FEAT_TERMINAL 1488 if (term_use_loop() 1489 && oa.op_type == OP_NOP && oa.regname == NUL 1490 && !VIsual_active 1491 && !skip_term_loop) 1492 { 1493 // If terminal_loop() returns OK we got a key that is handled 1494 // in Normal model. With FAIL we first need to position the 1495 // cursor and the screen needs to be redrawn. 1496 if (terminal_loop(TRUE) == OK) 1497 normal_cmd(&oa, TRUE); 1498 } 1499 else 1500 #endif 1501 { 1502 #ifdef FEAT_TERMINAL 1503 skip_term_loop = FALSE; 1504 #endif 1505 normal_cmd(&oa, TRUE); 1506 } 1507 } 1508 } 1509 1510 theend: 1511 current_oap = prev_oap; 1512 } 1513 1514 1515 #if defined(USE_XSMP) || defined(FEAT_GUI) || defined(PROTO) 1516 /* 1517 * Exit, but leave behind swap files for modified buffers. 1518 */ 1519 void 1520 getout_preserve_modified(int exitval) 1521 { 1522 # if defined(SIGHUP) && defined(SIG_IGN) 1523 // Ignore SIGHUP, because a dropped connection causes a read error, which 1524 // makes Vim exit and then handling SIGHUP causes various reentrance 1525 // problems. 1526 signal(SIGHUP, SIG_IGN); 1527 # endif 1528 1529 ml_close_notmod(); // close all not-modified buffers 1530 ml_sync_all(FALSE, FALSE); // preserve all swap files 1531 ml_close_all(FALSE); // close all memfiles, without deleting 1532 getout(exitval); // exit Vim properly 1533 } 1534 #endif 1535 1536 1537 /* 1538 * Exit properly. 1539 */ 1540 void 1541 getout(int exitval) 1542 { 1543 exiting = TRUE; 1544 #if defined(FEAT_JOB_CHANNEL) 1545 ch_log(NULL, "Exiting..."); 1546 #endif 1547 1548 // When running in Ex mode an error causes us to exit with a non-zero exit 1549 // code. POSIX requires this, although it's not 100% clear from the 1550 // standard. 1551 if (exmode_active) 1552 exitval += ex_exitval; 1553 1554 // Position the cursor on the last screen line, below all the text 1555 #ifdef FEAT_GUI 1556 if (!gui.in_use) 1557 #endif 1558 windgoto((int)Rows - 1, 0); 1559 1560 #if defined(FEAT_EVAL) || defined(FEAT_SYN_HL) 1561 // Optionally print hashtable efficiency. 1562 hash_debug_results(); 1563 #endif 1564 1565 #ifdef FEAT_GUI 1566 msg_didany = FALSE; 1567 #endif 1568 1569 if (v_dying <= 1) 1570 { 1571 tabpage_T *tp; 1572 tabpage_T *next_tp; 1573 buf_T *buf; 1574 win_T *wp; 1575 int unblock = 0; 1576 1577 // Trigger BufWinLeave for all windows, but only once per buffer. 1578 for (tp = first_tabpage; tp != NULL; tp = next_tp) 1579 { 1580 next_tp = tp->tp_next; 1581 FOR_ALL_WINDOWS_IN_TAB(tp, wp) 1582 { 1583 if (wp->w_buffer == NULL) 1584 // Autocmd must have close the buffer already, skip. 1585 continue; 1586 buf = wp->w_buffer; 1587 if (CHANGEDTICK(buf) != -1) 1588 { 1589 bufref_T bufref; 1590 1591 set_bufref(&bufref, buf); 1592 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, 1593 buf->b_fname, FALSE, buf); 1594 if (bufref_valid(&bufref)) 1595 CHANGEDTICK(buf) = -1; // note we did it already 1596 1597 // start all over, autocommands may mess up the lists 1598 next_tp = first_tabpage; 1599 break; 1600 } 1601 } 1602 } 1603 1604 // Trigger BufUnload for buffers that are loaded 1605 FOR_ALL_BUFFERS(buf) 1606 if (buf->b_ml.ml_mfp != NULL) 1607 { 1608 bufref_T bufref; 1609 1610 set_bufref(&bufref, buf); 1611 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, 1612 FALSE, buf); 1613 if (!bufref_valid(&bufref)) 1614 // autocmd deleted the buffer 1615 break; 1616 } 1617 1618 // deathtrap() blocks autocommands, but we do want to trigger 1619 // VimLeavePre. 1620 if (is_autocmd_blocked()) 1621 { 1622 unblock_autocmds(); 1623 ++unblock; 1624 } 1625 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); 1626 if (unblock) 1627 block_autocmds(); 1628 } 1629 1630 #ifdef FEAT_VIMINFO 1631 if (*p_viminfo != NUL) 1632 // Write out the registers, history, marks etc, to the viminfo file 1633 write_viminfo(NULL, FALSE); 1634 #endif 1635 1636 if (v_dying <= 1) 1637 { 1638 int unblock = 0; 1639 1640 // deathtrap() blocks autocommands, but we do want to trigger VimLeave. 1641 if (is_autocmd_blocked()) 1642 { 1643 unblock_autocmds(); 1644 ++unblock; 1645 } 1646 apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf); 1647 if (unblock) 1648 block_autocmds(); 1649 } 1650 1651 #ifdef FEAT_PROFILE 1652 profile_dump(); 1653 #endif 1654 1655 if (did_emsg 1656 #ifdef FEAT_GUI 1657 || (gui.in_use && msg_didany && p_verbose > 0) 1658 #endif 1659 ) 1660 { 1661 // give the user a chance to read the (error) message 1662 no_wait_return = FALSE; 1663 wait_return(FALSE); 1664 } 1665 1666 // Position the cursor again, the autocommands may have moved it 1667 #ifdef FEAT_GUI 1668 if (!gui.in_use) 1669 #endif 1670 windgoto((int)Rows - 1, 0); 1671 1672 #ifdef FEAT_JOB_CHANNEL 1673 job_stop_on_exit(); 1674 #endif 1675 #ifdef FEAT_LUA 1676 lua_end(); 1677 #endif 1678 #ifdef FEAT_MZSCHEME 1679 mzscheme_end(); 1680 #endif 1681 #ifdef FEAT_TCL 1682 tcl_end(); 1683 #endif 1684 #ifdef FEAT_RUBY 1685 ruby_end(); 1686 #endif 1687 #ifdef FEAT_PYTHON 1688 python_end(); 1689 #endif 1690 #ifdef FEAT_PYTHON3 1691 python3_end(); 1692 #endif 1693 #ifdef FEAT_PERL 1694 perl_end(); 1695 #endif 1696 #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) 1697 iconv_end(); 1698 #endif 1699 #ifdef FEAT_NETBEANS_INTG 1700 netbeans_end(); 1701 #endif 1702 #ifdef FEAT_CSCOPE 1703 cs_end(); 1704 #endif 1705 #ifdef FEAT_EVAL 1706 if (garbage_collect_at_exit) 1707 garbage_collect(FALSE); 1708 #endif 1709 #ifdef MSWIN 1710 free_cmd_argsW(); 1711 #endif 1712 1713 mch_exit(exitval); 1714 } 1715 1716 /* 1717 * Get the name of the display, before gui_prepare() removes it from 1718 * argv[]. Used for the xterm-clipboard display. 1719 * 1720 * Also find the --server... arguments and --socketid and --windowid 1721 */ 1722 static void 1723 early_arg_scan(mparm_T *parmp UNUSED) 1724 { 1725 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER) \ 1726 || !defined(FEAT_NETBEANS_INTG) 1727 int argc = parmp->argc; 1728 char **argv = parmp->argv; 1729 int i; 1730 1731 for (i = 1; i < argc; i++) 1732 { 1733 if (STRCMP(argv[i], "--") == 0) 1734 break; 1735 # ifdef FEAT_XCLIPBOARD 1736 else if (STRICMP(argv[i], "-display") == 0 1737 # if defined(FEAT_GUI_GTK) 1738 || STRICMP(argv[i], "--display") == 0 1739 # endif 1740 ) 1741 { 1742 if (i == argc - 1) 1743 mainerr_arg_missing((char_u *)argv[i]); 1744 xterm_display = argv[++i]; 1745 } 1746 # endif 1747 # ifdef FEAT_CLIENTSERVER 1748 else if (STRICMP(argv[i], "--servername") == 0) 1749 { 1750 if (i == argc - 1) 1751 mainerr_arg_missing((char_u *)argv[i]); 1752 parmp->serverName_arg = (char_u *)argv[++i]; 1753 } 1754 else if (STRICMP(argv[i], "--serverlist") == 0) 1755 parmp->serverArg = TRUE; 1756 else if (STRNICMP(argv[i], "--remote", 8) == 0) 1757 { 1758 parmp->serverArg = TRUE; 1759 # ifdef FEAT_GUI 1760 if (strstr(argv[i], "-wait") != 0) 1761 // don't fork() when starting the GUI to edit files ourself 1762 gui.dofork = FALSE; 1763 # endif 1764 } 1765 # endif 1766 1767 # if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) 1768 # ifdef FEAT_GUI_MSWIN 1769 else if (STRICMP(argv[i], "--windowid") == 0) 1770 # else 1771 else if (STRICMP(argv[i], "--socketid") == 0) 1772 # endif 1773 { 1774 long_u id; 1775 int count; 1776 1777 if (i == argc - 1) 1778 mainerr_arg_missing((char_u *)argv[i]); 1779 if (STRNICMP(argv[i+1], "0x", 2) == 0) 1780 count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id); 1781 else 1782 count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id); 1783 if (count != 1) 1784 mainerr(ME_INVALID_ARG, (char_u *)argv[i]); 1785 else 1786 # ifdef FEAT_GUI_MSWIN 1787 win_socket_id = id; 1788 # else 1789 gtk_socket_id = id; 1790 # endif 1791 i++; 1792 } 1793 # endif 1794 # ifdef FEAT_GUI_GTK 1795 else if (STRICMP(argv[i], "--echo-wid") == 0) 1796 echo_wid_arg = TRUE; 1797 # endif 1798 # ifndef FEAT_NETBEANS_INTG 1799 else if (strncmp(argv[i], "-nb", (size_t)3) == 0) 1800 { 1801 mch_errmsg(_("'-nb' cannot be used: not enabled at compile time\n")); 1802 mch_exit(2); 1803 } 1804 # endif 1805 1806 } 1807 #endif 1808 } 1809 1810 #ifndef NO_VIM_MAIN 1811 /* 1812 * Get a (optional) count for a Vim argument. 1813 */ 1814 static int 1815 get_number_arg( 1816 char_u *p, // pointer to argument 1817 int *idx, // index in argument, is incremented 1818 int def) // default value 1819 { 1820 if (vim_isdigit(p[*idx])) 1821 { 1822 def = atoi((char *)&(p[*idx])); 1823 while (vim_isdigit(p[*idx])) 1824 *idx = *idx + 1; 1825 } 1826 return def; 1827 } 1828 1829 /* 1830 * Check for: [r][e][g][vi|vim|view][diff][ex[im]] (sort of) 1831 * If the executable name starts with "r" we disable shell commands. 1832 * If the next character is "e" we run in Easy mode. 1833 * If the next character is "g" we run the GUI version. 1834 * If the next characters are "view" we start in readonly mode. 1835 * If the next characters are "diff" or "vimdiff" we start in diff mode. 1836 * If the next characters are "ex" we start in Ex mode. If it's followed 1837 * by "im" use improved Ex mode. 1838 */ 1839 static void 1840 parse_command_name(mparm_T *parmp) 1841 { 1842 char_u *initstr; 1843 1844 initstr = gettail((char_u *)parmp->argv[0]); 1845 1846 #ifdef FEAT_GUI_MAC 1847 // An issue has been seen when launching Vim in such a way that 1848 // $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the 1849 // executable or a symbolic link of it. Until this issue is resolved 1850 // we prohibit the GUI from being used. 1851 if (STRCMP(initstr, parmp->argv[0]) == 0) 1852 disallow_gui = TRUE; 1853 1854 // TODO: On MacOS X default to gui if argv[0] ends in: 1855 // /Vim.app/Contents/MacOS/Vim 1856 #endif 1857 1858 #ifdef FEAT_EVAL 1859 set_vim_var_string(VV_PROGNAME, initstr, -1); 1860 set_progpath((char_u *)parmp->argv[0]); 1861 #endif 1862 1863 if (TOLOWER_ASC(initstr[0]) == 'r') 1864 { 1865 restricted = TRUE; 1866 ++initstr; 1867 } 1868 1869 // Use evim mode for "evim" and "egvim", not for "editor". 1870 if (TOLOWER_ASC(initstr[0]) == 'e' 1871 && (TOLOWER_ASC(initstr[1]) == 'v' 1872 || TOLOWER_ASC(initstr[1]) == 'g')) 1873 { 1874 #ifdef FEAT_GUI 1875 gui.starting = TRUE; 1876 #endif 1877 parmp->evim_mode = TRUE; 1878 ++initstr; 1879 } 1880 1881 // "gvim" starts the GUI. Also accept "Gvim" for MS-Windows. 1882 if (TOLOWER_ASC(initstr[0]) == 'g') 1883 { 1884 main_start_gui(); 1885 #ifdef FEAT_GUI 1886 ++initstr; 1887 #endif 1888 #ifdef GUI_MAY_SPAWN 1889 gui.dospawn = FALSE; // No need to spawn a new process. 1890 #endif 1891 } 1892 #ifdef GUI_MAY_SPAWN 1893 else 1894 gui.dospawn = TRUE; // Not "gvim". Need to spawn gvim.exe. 1895 #endif 1896 1897 1898 if (STRNICMP(initstr, "view", 4) == 0) 1899 { 1900 readonlymode = TRUE; 1901 curbuf->b_p_ro = TRUE; 1902 p_uc = 10000; // don't update very often 1903 initstr += 4; 1904 } 1905 else if (STRNICMP(initstr, "vim", 3) == 0) 1906 initstr += 3; 1907 1908 // Catch "[r][g]vimdiff" and "[r][g]viewdiff". 1909 if (STRICMP(initstr, "diff") == 0) 1910 { 1911 #ifdef FEAT_DIFF 1912 parmp->diff_mode = TRUE; 1913 #else 1914 mch_errmsg(_("This Vim was not compiled with the diff feature.")); 1915 mch_errmsg("\n"); 1916 mch_exit(2); 1917 #endif 1918 } 1919 1920 // Checking for "ex" here may catch some weird names, such as "vimex" or 1921 // "viewex", we assume the user knows that. 1922 if (STRNICMP(initstr, "ex", 2) == 0) 1923 { 1924 if (STRNICMP(initstr + 2, "im", 2) == 0) 1925 exmode_active = EXMODE_VIM; 1926 else 1927 exmode_active = EXMODE_NORMAL; 1928 change_compatible(TRUE); // set 'compatible' 1929 } 1930 } 1931 1932 /* 1933 * Scan the command line arguments. 1934 */ 1935 static void 1936 command_line_scan(mparm_T *parmp) 1937 { 1938 int argc = parmp->argc; 1939 char **argv = parmp->argv; 1940 int argv_idx; // index in argv[n][] 1941 int had_minmin = FALSE; // found "--" argument 1942 int want_argument; // option argument with argument 1943 int c; 1944 char_u *p = NULL; 1945 long n; 1946 1947 --argc; 1948 ++argv; 1949 argv_idx = 1; // active option letter is argv[0][argv_idx] 1950 while (argc > 0) 1951 { 1952 /* 1953 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument. 1954 */ 1955 if (argv[0][0] == '+' && !had_minmin) 1956 { 1957 if (parmp->n_commands >= MAX_ARG_CMDS) 1958 mainerr(ME_EXTRA_CMD, NULL); 1959 argv_idx = -1; // skip to next argument 1960 if (argv[0][1] == NUL) 1961 parmp->commands[parmp->n_commands++] = (char_u *)"$"; 1962 else 1963 parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]); 1964 } 1965 1966 /* 1967 * Optional argument. 1968 */ 1969 else if (argv[0][0] == '-' && !had_minmin) 1970 { 1971 want_argument = FALSE; 1972 c = argv[0][argv_idx++]; 1973 #ifdef VMS 1974 /* 1975 * VMS only uses upper case command lines. Interpret "-X" as "-x" 1976 * and "-/X" as "-X". 1977 */ 1978 if (c == '/') 1979 { 1980 c = argv[0][argv_idx++]; 1981 c = TOUPPER_ASC(c); 1982 } 1983 else 1984 c = TOLOWER_ASC(c); 1985 #endif 1986 switch (c) 1987 { 1988 case NUL: // "vim -" read from stdin 1989 // "ex -" silent mode 1990 if (exmode_active) 1991 silent_mode = TRUE; 1992 else 1993 { 1994 if (parmp->edit_type != EDIT_NONE) 1995 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); 1996 parmp->edit_type = EDIT_STDIN; 1997 read_cmd_fd = 2; // read from stderr instead of stdin 1998 } 1999 argv_idx = -1; // skip to next argument 2000 break; 2001 2002 case '-': // "--" don't take any more option arguments 2003 // "--help" give help message 2004 // "--version" give version message 2005 // "--clean" clean context 2006 // "--literal" take files literally 2007 // "--nofork" don't fork 2008 // "--not-a-term" don't warn for not a term 2009 // "--ttyfail" exit if not a term 2010 // "--noplugin[s]" skip plugins 2011 // "--cmd <cmd>" execute cmd before vimrc 2012 if (STRICMP(argv[0] + argv_idx, "help") == 0) 2013 usage(); 2014 else if (STRICMP(argv[0] + argv_idx, "version") == 0) 2015 { 2016 Columns = 80; // need to init Columns 2017 info_message = TRUE; // use mch_msg(), not mch_errmsg() 2018 list_version(); 2019 msg_putchar('\n'); 2020 msg_didout = FALSE; 2021 mch_exit(0); 2022 } 2023 else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) 2024 { 2025 parmp->use_vimrc = (char_u *)"DEFAULTS"; 2026 #ifdef FEAT_GUI 2027 use_gvimrc = (char_u *)"NONE"; 2028 #endif 2029 parmp->clean = TRUE; 2030 set_option_value((char_u *)"vif", 0L, (char_u *)"NONE", 0); 2031 } 2032 else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) 2033 { 2034 #ifdef EXPAND_FILENAMES 2035 parmp->literal = TRUE; 2036 #endif 2037 } 2038 else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0) 2039 { 2040 #ifdef FEAT_GUI 2041 gui.dofork = FALSE; // don't fork() when starting GUI 2042 #endif 2043 } 2044 else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0) 2045 p_lpl = FALSE; 2046 else if (STRNICMP(argv[0] + argv_idx, "not-a-term", 10) == 0) 2047 parmp->not_a_term = TRUE; 2048 else if (STRNICMP(argv[0] + argv_idx, "ttyfail", 7) == 0) 2049 parmp->tty_fail = TRUE; 2050 else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0) 2051 { 2052 want_argument = TRUE; 2053 argv_idx += 3; 2054 } 2055 else if (STRNICMP(argv[0] + argv_idx, "startuptime", 11) == 0) 2056 { 2057 want_argument = TRUE; 2058 argv_idx += 11; 2059 } 2060 #ifdef FEAT_CLIENTSERVER 2061 else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0) 2062 ; // already processed -- no arg 2063 else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0 2064 || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0) 2065 { 2066 // already processed -- snatch the following arg 2067 if (argc > 1) 2068 { 2069 --argc; 2070 ++argv; 2071 } 2072 } 2073 #endif 2074 #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) 2075 # ifdef FEAT_GUI_GTK 2076 else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0) 2077 # else 2078 else if (STRNICMP(argv[0] + argv_idx, "windowid", 8) == 0) 2079 # endif 2080 { 2081 // already processed -- snatch the following arg 2082 if (argc > 1) 2083 { 2084 --argc; 2085 ++argv; 2086 } 2087 } 2088 #endif 2089 #ifdef FEAT_GUI_GTK 2090 else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0) 2091 { 2092 // already processed, skip 2093 } 2094 #endif 2095 else 2096 { 2097 if (argv[0][argv_idx]) 2098 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]); 2099 had_minmin = TRUE; 2100 } 2101 if (!want_argument) 2102 argv_idx = -1; // skip to next argument 2103 break; 2104 2105 case 'A': // "-A" start in Arabic mode 2106 #ifdef FEAT_ARABIC 2107 set_option_value((char_u *)"arabic", 1L, NULL, 0); 2108 #else 2109 mch_errmsg(_(e_noarabic)); 2110 mch_exit(2); 2111 #endif 2112 break; 2113 2114 case 'b': // "-b" binary mode 2115 // Needs to be effective before expanding file names, because 2116 // for Win32 this makes us edit a shortcut file itself, 2117 // instead of the file it links to. 2118 set_options_bin(curbuf->b_p_bin, 1, 0); 2119 curbuf->b_p_bin = 1; // binary file I/O 2120 break; 2121 2122 case 'C': // "-C" Compatible 2123 change_compatible(TRUE); 2124 has_dash_c_arg = TRUE; 2125 break; 2126 2127 case 'e': // "-e" Ex mode 2128 exmode_active = EXMODE_NORMAL; 2129 break; 2130 2131 case 'E': // "-E" Improved Ex mode 2132 exmode_active = EXMODE_VIM; 2133 break; 2134 2135 case 'f': // "-f" GUI: run in foreground. Amiga: open 2136 // window directly, not with newcli 2137 #ifdef FEAT_GUI 2138 gui.dofork = FALSE; // don't fork() when starting GUI 2139 #endif 2140 break; 2141 2142 case 'g': // "-g" start GUI 2143 main_start_gui(); 2144 break; 2145 2146 case 'F': // "-F" was for Farsi mode 2147 mch_errmsg(_(e_nofarsi)); 2148 mch_exit(2); 2149 break; 2150 2151 case '?': // "-?" give help message (for MS-Windows) 2152 case 'h': // "-h" give help message 2153 #ifdef FEAT_GUI_GNOME 2154 // Tell usage() to exit for "gvim". 2155 gui.starting = FALSE; 2156 #endif 2157 usage(); 2158 break; 2159 2160 case 'H': // "-H" start in Hebrew mode: rl + hkmap set 2161 #ifdef FEAT_RIGHTLEFT 2162 p_hkmap = TRUE; 2163 set_option_value((char_u *)"rl", 1L, NULL, 0); 2164 #else 2165 mch_errmsg(_(e_nohebrew)); 2166 mch_exit(2); 2167 #endif 2168 break; 2169 2170 case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on 2171 #ifdef FEAT_LISP 2172 set_option_value((char_u *)"lisp", 1L, NULL, 0); 2173 p_sm = TRUE; 2174 #endif 2175 break; 2176 2177 case 'M': // "-M" no changes or writing of files 2178 reset_modifiable(); 2179 // FALLTHROUGH 2180 2181 case 'm': // "-m" no writing of files 2182 p_write = FALSE; 2183 break; 2184 2185 case 'y': // "-y" easy mode 2186 #ifdef FEAT_GUI 2187 gui.starting = TRUE; // start GUI a bit later 2188 #endif 2189 parmp->evim_mode = TRUE; 2190 break; 2191 2192 case 'N': // "-N" Nocompatible 2193 change_compatible(FALSE); 2194 break; 2195 2196 case 'n': // "-n" no swap file 2197 #ifdef FEAT_NETBEANS_INTG 2198 // checking for "-nb", netbeans parameters 2199 if (argv[0][argv_idx] == 'b') 2200 { 2201 netbeansArg = argv[0]; 2202 argv_idx = -1; // skip to next argument 2203 } 2204 else 2205 #endif 2206 parmp->no_swap_file = TRUE; 2207 break; 2208 2209 case 'p': // "-p[N]" open N tab pages 2210 #ifdef TARGET_API_MAC_OSX 2211 // For some reason on MacOS X, an argument like: 2212 // -psn_0_10223617 is passed in when invoke from Finder 2213 // or with the 'open' command 2214 if (argv[0][argv_idx] == 's') 2215 { 2216 argv_idx = -1; // bypass full -psn 2217 main_start_gui(); 2218 break; 2219 } 2220 #endif 2221 // default is 0: open window for each file 2222 parmp->window_count = get_number_arg((char_u *)argv[0], 2223 &argv_idx, 0); 2224 parmp->window_layout = WIN_TABS; 2225 break; 2226 2227 case 'o': // "-o[N]" open N horizontal split windows 2228 // default is 0: open window for each file 2229 parmp->window_count = get_number_arg((char_u *)argv[0], 2230 &argv_idx, 0); 2231 parmp->window_layout = WIN_HOR; 2232 break; 2233 2234 case 'O': // "-O[N]" open N vertical split windows 2235 // default is 0: open window for each file 2236 parmp->window_count = get_number_arg((char_u *)argv[0], 2237 &argv_idx, 0); 2238 parmp->window_layout = WIN_VER; 2239 break; 2240 2241 #ifdef FEAT_QUICKFIX 2242 case 'q': // "-q" QuickFix mode 2243 if (parmp->edit_type != EDIT_NONE) 2244 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); 2245 parmp->edit_type = EDIT_QF; 2246 if (argv[0][argv_idx]) // "-q{errorfile}" 2247 { 2248 parmp->use_ef = (char_u *)argv[0] + argv_idx; 2249 argv_idx = -1; 2250 } 2251 else if (argc > 1) // "-q {errorfile}" 2252 want_argument = TRUE; 2253 break; 2254 #endif 2255 2256 case 'R': // "-R" readonly mode 2257 readonlymode = TRUE; 2258 curbuf->b_p_ro = TRUE; 2259 p_uc = 10000; // don't update very often 2260 break; 2261 2262 case 'r': // "-r" recovery mode 2263 case 'L': // "-L" recovery mode 2264 recoverymode = 1; 2265 break; 2266 2267 case 's': 2268 if (exmode_active) // "-s" silent (batch) mode 2269 silent_mode = TRUE; 2270 else // "-s {scriptin}" read from script file 2271 want_argument = TRUE; 2272 break; 2273 2274 case 't': // "-t {tag}" or "-t{tag}" jump to tag 2275 if (parmp->edit_type != EDIT_NONE) 2276 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); 2277 parmp->edit_type = EDIT_TAG; 2278 if (argv[0][argv_idx]) // "-t{tag}" 2279 { 2280 parmp->tagname = (char_u *)argv[0] + argv_idx; 2281 argv_idx = -1; 2282 } 2283 else // "-t {tag}" 2284 want_argument = TRUE; 2285 break; 2286 2287 #ifdef FEAT_EVAL 2288 case 'D': // "-D" Debugging 2289 parmp->use_debug_break_level = 9999; 2290 break; 2291 #endif 2292 #ifdef FEAT_DIFF 2293 case 'd': // "-d" 'diff' 2294 # ifdef AMIGA 2295 // check for "-dev {device}" 2296 if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v') 2297 want_argument = TRUE; 2298 else 2299 # endif 2300 parmp->diff_mode = TRUE; 2301 break; 2302 #endif 2303 case 'V': // "-V{N}" Verbose level 2304 // default is 10: a little bit verbose 2305 p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10); 2306 if (argv[0][argv_idx] != NUL) 2307 { 2308 set_option_value((char_u *)"verbosefile", 0L, 2309 (char_u *)argv[0] + argv_idx, 0); 2310 argv_idx = (int)STRLEN(argv[0]); 2311 } 2312 break; 2313 2314 case 'v': // "-v" Vi-mode (as if called "vi") 2315 exmode_active = 0; 2316 #if defined(FEAT_GUI) && !defined(VIMDLL) 2317 gui.starting = FALSE; // don't start GUI 2318 #endif 2319 break; 2320 2321 case 'w': // "-w{number}" set window height 2322 // "-w {scriptout}" write to script 2323 if (vim_isdigit(((char_u *)argv[0])[argv_idx])) 2324 { 2325 n = get_number_arg((char_u *)argv[0], &argv_idx, 10); 2326 set_option_value((char_u *)"window", n, NULL, 0); 2327 break; 2328 } 2329 want_argument = TRUE; 2330 break; 2331 2332 #ifdef FEAT_CRYPT 2333 case 'x': // "-x" encrypted reading/writing of files 2334 parmp->ask_for_key = TRUE; 2335 break; 2336 #endif 2337 2338 case 'X': // "-X" don't connect to X server 2339 #if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11) 2340 x_no_connect = TRUE; 2341 #endif 2342 break; 2343 2344 case 'Z': // "-Z" restricted mode 2345 restricted = TRUE; 2346 break; 2347 2348 case 'c': // "-c{command}" or "-c {command}" execute 2349 // command 2350 if (argv[0][argv_idx] != NUL) 2351 { 2352 if (parmp->n_commands >= MAX_ARG_CMDS) 2353 mainerr(ME_EXTRA_CMD, NULL); 2354 parmp->commands[parmp->n_commands++] = (char_u *)argv[0] 2355 + argv_idx; 2356 argv_idx = -1; 2357 break; 2358 } 2359 // FALLTHROUGH 2360 case 'S': // "-S {file}" execute Vim script 2361 case 'i': // "-i {viminfo}" use for viminfo 2362 #ifndef FEAT_DIFF 2363 case 'd': // "-d {device}" device (for Amiga) 2364 #endif 2365 case 'T': // "-T {terminal}" terminal name 2366 case 'u': // "-u {vimrc}" vim inits file 2367 case 'U': // "-U {gvimrc}" gvim inits file 2368 case 'W': // "-W {scriptout}" overwrite 2369 #ifdef FEAT_GUI_MSWIN 2370 case 'P': // "-P {parent title}" MDI parent 2371 #endif 2372 want_argument = TRUE; 2373 break; 2374 2375 default: 2376 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]); 2377 } 2378 2379 /* 2380 * Handle option arguments with argument. 2381 */ 2382 if (want_argument) 2383 { 2384 /* 2385 * Check for garbage immediately after the option letter. 2386 */ 2387 if (argv[0][argv_idx] != NUL) 2388 mainerr(ME_GARBAGE, (char_u *)argv[0]); 2389 2390 --argc; 2391 if (argc < 1 && c != 'S') // -S has an optional argument 2392 mainerr_arg_missing((char_u *)argv[0]); 2393 ++argv; 2394 argv_idx = -1; 2395 2396 switch (c) 2397 { 2398 case 'c': // "-c {command}" execute command 2399 case 'S': // "-S {file}" execute Vim script 2400 if (parmp->n_commands >= MAX_ARG_CMDS) 2401 mainerr(ME_EXTRA_CMD, NULL); 2402 if (c == 'S') 2403 { 2404 char *a; 2405 2406 if (argc < 1) 2407 // "-S" without argument: use default session file 2408 // name. 2409 a = SESSION_FILE; 2410 else if (argv[0][0] == '-') 2411 { 2412 // "-S" followed by another option: use default 2413 // session file name. 2414 a = SESSION_FILE; 2415 ++argc; 2416 --argv; 2417 } 2418 else 2419 a = argv[0]; 2420 p = alloc(STRLEN(a) + 4); 2421 if (p == NULL) 2422 mch_exit(2); 2423 sprintf((char *)p, "so %s", a); 2424 parmp->cmds_tofree[parmp->n_commands] = TRUE; 2425 parmp->commands[parmp->n_commands++] = p; 2426 } 2427 else 2428 parmp->commands[parmp->n_commands++] = 2429 (char_u *)argv[0]; 2430 break; 2431 2432 case '-': 2433 if (argv[-1][2] == 'c') 2434 { 2435 // "--cmd {command}" execute command 2436 if (parmp->n_pre_commands >= MAX_ARG_CMDS) 2437 mainerr(ME_EXTRA_CMD, NULL); 2438 parmp->pre_commands[parmp->n_pre_commands++] = 2439 (char_u *)argv[0]; 2440 } 2441 // "--startuptime <file>" already handled 2442 break; 2443 2444 // case 'd': -d {device} is handled in mch_check_win() for the 2445 // Amiga 2446 2447 #ifdef FEAT_QUICKFIX 2448 case 'q': // "-q {errorfile}" QuickFix mode 2449 parmp->use_ef = (char_u *)argv[0]; 2450 break; 2451 #endif 2452 2453 case 'i': // "-i {viminfo}" use for viminfo 2454 set_option_value((char_u *)"vif", 0L, (char_u *)argv[0], 0); 2455 break; 2456 2457 case 's': // "-s {scriptin}" read from script file 2458 if (scriptin[0] != NULL) 2459 { 2460 scripterror: 2461 mch_errmsg(_("Attempt to open script file again: \"")); 2462 mch_errmsg(argv[-1]); 2463 mch_errmsg(" "); 2464 mch_errmsg(argv[0]); 2465 mch_errmsg("\"\n"); 2466 mch_exit(2); 2467 } 2468 if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL) 2469 { 2470 mch_errmsg(_("Cannot open for reading: \"")); 2471 mch_errmsg(argv[0]); 2472 mch_errmsg("\"\n"); 2473 mch_exit(2); 2474 } 2475 if (save_typebuf() == FAIL) 2476 mch_exit(2); // out of memory 2477 break; 2478 2479 case 't': // "-t {tag}" 2480 parmp->tagname = (char_u *)argv[0]; 2481 break; 2482 2483 case 'T': // "-T {terminal}" terminal name 2484 /* 2485 * The -T term argument is always available and when 2486 * HAVE_TERMLIB is supported it overrides the environment 2487 * variable TERM. 2488 */ 2489 #ifdef FEAT_GUI 2490 if (term_is_gui((char_u *)argv[0])) 2491 gui.starting = TRUE; // start GUI a bit later 2492 else 2493 #endif 2494 parmp->term = (char_u *)argv[0]; 2495 break; 2496 2497 case 'u': // "-u {vimrc}" vim inits file 2498 parmp->use_vimrc = (char_u *)argv[0]; 2499 break; 2500 2501 case 'U': // "-U {gvimrc}" gvim inits file 2502 #ifdef FEAT_GUI 2503 use_gvimrc = (char_u *)argv[0]; 2504 #endif 2505 break; 2506 2507 case 'w': // "-w {nr}" 'window' value 2508 // "-w {scriptout}" append to script file 2509 if (vim_isdigit(*((char_u *)argv[0]))) 2510 { 2511 argv_idx = 0; 2512 n = get_number_arg((char_u *)argv[0], &argv_idx, 10); 2513 set_option_value((char_u *)"window", n, NULL, 0); 2514 argv_idx = -1; 2515 break; 2516 } 2517 // FALLTHROUGH 2518 case 'W': // "-W {scriptout}" overwrite script file 2519 if (scriptout != NULL) 2520 goto scripterror; 2521 if ((scriptout = mch_fopen(argv[0], 2522 c == 'w' ? APPENDBIN : WRITEBIN)) == NULL) 2523 { 2524 mch_errmsg(_("Cannot open for script output: \"")); 2525 mch_errmsg(argv[0]); 2526 mch_errmsg("\"\n"); 2527 mch_exit(2); 2528 } 2529 break; 2530 2531 #ifdef FEAT_GUI_MSWIN 2532 case 'P': // "-P {parent title}" MDI parent 2533 gui_mch_set_parent(argv[0]); 2534 break; 2535 #endif 2536 } 2537 } 2538 } 2539 2540 /* 2541 * File name argument. 2542 */ 2543 else 2544 { 2545 argv_idx = -1; // skip to next argument 2546 2547 // Check for only one type of editing. 2548 if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE) 2549 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); 2550 parmp->edit_type = EDIT_FILE; 2551 2552 #ifdef MSWIN 2553 // Remember if the argument was a full path before changing 2554 // slashes to backslashes. 2555 if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\') 2556 parmp->full_path = TRUE; 2557 #endif 2558 2559 // Add the file to the global argument list. 2560 if (ga_grow(&global_alist.al_ga, 1) == FAIL 2561 || (p = vim_strsave((char_u *)argv[0])) == NULL) 2562 mch_exit(2); 2563 #ifdef FEAT_DIFF 2564 if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0 2565 && !mch_isdir(alist_name(&GARGLIST[0]))) 2566 { 2567 char_u *r; 2568 2569 r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE); 2570 if (r != NULL) 2571 { 2572 vim_free(p); 2573 p = r; 2574 } 2575 } 2576 #endif 2577 #if defined(__CYGWIN32__) && !defined(MSWIN) 2578 /* 2579 * If vim is invoked by non-Cygwin tools, convert away any 2580 * DOS paths, so things like .swp files are created correctly. 2581 * Look for evidence of non-Cygwin paths before we bother. 2582 * This is only for when using the Unix files. 2583 */ 2584 if (vim_strpbrk(p, "\\:") != NULL && !path_with_url(p)) 2585 { 2586 char posix_path[MAXPATHL]; 2587 2588 # if CYGWIN_VERSION_DLL_MAJOR >= 1007 2589 cygwin_conv_path(CCP_WIN_A_TO_POSIX, p, posix_path, MAXPATHL); 2590 # else 2591 cygwin_conv_to_posix_path(p, posix_path); 2592 # endif 2593 vim_free(p); 2594 p = vim_strsave((char_u *)posix_path); 2595 if (p == NULL) 2596 mch_exit(2); 2597 } 2598 #endif 2599 2600 #ifdef USE_FNAME_CASE 2601 // Make the case of the file name match the actual file. 2602 fname_case(p, 0); 2603 #endif 2604 2605 alist_add(&global_alist, p, 2606 #ifdef EXPAND_FILENAMES 2607 parmp->literal ? 2 : 0 // add buffer nr after exp. 2608 #else 2609 2 // add buffer number now and use curbuf 2610 #endif 2611 ); 2612 2613 #ifdef MSWIN 2614 { 2615 // Remember this argument has been added to the argument list. 2616 // Needed when 'encoding' is changed. 2617 used_file_arg(argv[0], parmp->literal, parmp->full_path, 2618 # ifdef FEAT_DIFF 2619 parmp->diff_mode 2620 # else 2621 FALSE 2622 # endif 2623 ); 2624 } 2625 #endif 2626 } 2627 2628 /* 2629 * If there are no more letters after the current "-", go to next 2630 * argument. argv_idx is set to -1 when the current argument is to be 2631 * skipped. 2632 */ 2633 if (argv_idx <= 0 || argv[0][argv_idx] == NUL) 2634 { 2635 --argc; 2636 ++argv; 2637 argv_idx = 1; 2638 } 2639 } 2640 2641 #ifdef FEAT_EVAL 2642 // If there is a "+123" or "-c" command, set v:swapcommand to the first 2643 // one. 2644 if (parmp->n_commands > 0) 2645 { 2646 p = alloc(STRLEN(parmp->commands[0]) + 3); 2647 if (p != NULL) 2648 { 2649 sprintf((char *)p, ":%s\r", parmp->commands[0]); 2650 set_vim_var_string(VV_SWAPCOMMAND, p, -1); 2651 vim_free(p); 2652 } 2653 } 2654 #endif 2655 } 2656 2657 /* 2658 * Print a warning if stdout is not a terminal. 2659 * When starting in Ex mode and commands come from a file, set silent_mode. 2660 */ 2661 static void 2662 check_tty(mparm_T *parmp) 2663 { 2664 int input_isatty; // is active input a terminal? 2665 2666 input_isatty = mch_input_isatty(); 2667 if (exmode_active) 2668 { 2669 if (!input_isatty) 2670 silent_mode = TRUE; 2671 } 2672 else if (parmp->want_full_screen && (!stdout_isatty || !input_isatty) 2673 #ifdef FEAT_GUI 2674 // don't want the delay when started from the desktop 2675 && !gui.starting 2676 #endif 2677 && !parmp->not_a_term) 2678 { 2679 #ifdef NBDEBUG 2680 /* 2681 * This shouldn't be necessary. But if I run netbeans with the log 2682 * output coming to the console and XOpenDisplay fails, I get vim 2683 * trying to start with input/output to my console tty. This fills my 2684 * input buffer so fast I can't even kill the process in under 2 2685 * minutes (and it beeps continuously the whole time :-) 2686 */ 2687 if (netbeans_active() && (!stdout_isatty || !input_isatty)) 2688 { 2689 mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n")); 2690 exit(1); 2691 } 2692 #endif 2693 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 2694 if ( 2695 # ifdef VIMDLL 2696 !gui.starting && 2697 # endif 2698 is_cygpty_used()) 2699 { 2700 # if defined(HAVE_BIND_TEXTDOMAIN_CODESET) \ 2701 && defined(FEAT_GETTEXT) 2702 char *s, *tofree = NULL; 2703 2704 // Set the encoding of the error message based on $LC_ALL or 2705 // other environment variables instead of 'encoding'. 2706 // Note that the message is shown on a Cygwin terminal (e.g. 2707 // mintty) which encoding is based on $LC_ALL or etc., not the 2708 // current codepage used by normal Win32 console programs. 2709 tofree = s = (char *)enc_locale_env(NULL); 2710 if (s == NULL) 2711 s = "utf-8"; // Use "utf-8" by default. 2712 (void)bind_textdomain_codeset(VIMPACKAGE, s); 2713 vim_free(tofree); 2714 # endif 2715 mch_errmsg(_("Vim: Error: This version of Vim does not run in a Cygwin terminal\n")); 2716 exit(1); 2717 } 2718 #endif 2719 if (!stdout_isatty) 2720 mch_errmsg(_("Vim: Warning: Output is not to a terminal\n")); 2721 if (!input_isatty) 2722 mch_errmsg(_("Vim: Warning: Input is not from a terminal\n")); 2723 out_flush(); 2724 if (parmp->tty_fail && (!stdout_isatty || !input_isatty)) 2725 exit(1); 2726 if (scriptin[0] == NULL) 2727 ui_delay(2005L, TRUE); 2728 TIME_MSG("Warning delay"); 2729 } 2730 } 2731 2732 /* 2733 * Read text from stdin. 2734 */ 2735 static void 2736 read_stdin(void) 2737 { 2738 int i; 2739 2740 // When getting the ATTENTION prompt here, use a dialog 2741 swap_exists_action = SEA_DIALOG; 2742 2743 no_wait_return = TRUE; 2744 i = msg_didany; 2745 set_buflisted(TRUE); 2746 (void)open_buffer(TRUE, NULL, 0); // create memfile and read file 2747 no_wait_return = FALSE; 2748 msg_didany = i; 2749 TIME_MSG("reading stdin"); 2750 2751 check_swap_exists_action(); 2752 #if !(defined(AMIGA) || defined(MACOS_X)) 2753 /* 2754 * Close stdin and dup it from stderr. Required for GPM to work 2755 * properly, and for running external commands. 2756 * Is there any other system that cannot do this? 2757 */ 2758 close(0); 2759 vim_ignored = dup(2); 2760 #endif 2761 } 2762 2763 /* 2764 * Create the requested number of windows and edit buffers in them. 2765 * Also does recovery if "recoverymode" set. 2766 */ 2767 static void 2768 create_windows(mparm_T *parmp UNUSED) 2769 { 2770 int dorewind; 2771 int done = 0; 2772 2773 /* 2774 * Create the number of windows that was requested. 2775 */ 2776 if (parmp->window_count == -1) // was not set 2777 parmp->window_count = 1; 2778 if (parmp->window_count == 0) 2779 parmp->window_count = GARGCOUNT; 2780 if (parmp->window_count > 1) 2781 { 2782 // Don't change the windows if there was a command in .vimrc that 2783 // already split some windows 2784 if (parmp->window_layout == 0) 2785 parmp->window_layout = WIN_HOR; 2786 if (parmp->window_layout == WIN_TABS) 2787 { 2788 parmp->window_count = make_tabpages(parmp->window_count); 2789 TIME_MSG("making tab pages"); 2790 } 2791 else if (firstwin->w_next == NULL) 2792 { 2793 parmp->window_count = make_windows(parmp->window_count, 2794 parmp->window_layout == WIN_VER); 2795 TIME_MSG("making windows"); 2796 } 2797 else 2798 parmp->window_count = win_count(); 2799 } 2800 else 2801 parmp->window_count = 1; 2802 2803 if (recoverymode) // do recover 2804 { 2805 msg_scroll = TRUE; // scroll message up 2806 ml_recover(TRUE); 2807 if (curbuf->b_ml.ml_mfp == NULL) // failed 2808 getout(1); 2809 do_modelines(0); // do modelines 2810 } 2811 else 2812 { 2813 /* 2814 * Open a buffer for windows that don't have one yet. 2815 * Commands in the .vimrc might have loaded a file or split the window. 2816 * Watch out for autocommands that delete a window. 2817 */ 2818 /* 2819 * Don't execute Win/Buf Enter/Leave autocommands here 2820 */ 2821 ++autocmd_no_enter; 2822 ++autocmd_no_leave; 2823 dorewind = TRUE; 2824 while (done++ < 1000) 2825 { 2826 if (dorewind) 2827 { 2828 if (parmp->window_layout == WIN_TABS) 2829 goto_tabpage(1); 2830 else 2831 curwin = firstwin; 2832 } 2833 else if (parmp->window_layout == WIN_TABS) 2834 { 2835 if (curtab->tp_next == NULL) 2836 break; 2837 goto_tabpage(0); 2838 } 2839 else 2840 { 2841 if (curwin->w_next == NULL) 2842 break; 2843 curwin = curwin->w_next; 2844 } 2845 dorewind = FALSE; 2846 curbuf = curwin->w_buffer; 2847 if (curbuf->b_ml.ml_mfp == NULL) 2848 { 2849 #ifdef FEAT_FOLDING 2850 // Set 'foldlevel' to 'foldlevelstart' if it's not negative. 2851 if (p_fdls >= 0) 2852 curwin->w_p_fdl = p_fdls; 2853 #endif 2854 // When getting the ATTENTION prompt here, use a dialog 2855 swap_exists_action = SEA_DIALOG; 2856 2857 set_buflisted(TRUE); 2858 2859 // create memfile, read file 2860 (void)open_buffer(FALSE, NULL, 0); 2861 2862 if (swap_exists_action == SEA_QUIT) 2863 { 2864 if (got_int || only_one_window()) 2865 { 2866 // abort selected or quit and only one window 2867 did_emsg = FALSE; // avoid hit-enter prompt 2868 getout(1); 2869 } 2870 // We can't close the window, it would disturb what 2871 // happens next. Clear the file name and set the arg 2872 // index to -1 to delete it later. 2873 setfname(curbuf, NULL, NULL, FALSE); 2874 curwin->w_arg_idx = -1; 2875 swap_exists_action = SEA_NONE; 2876 } 2877 else 2878 handle_swap_exists(NULL); 2879 dorewind = TRUE; // start again 2880 } 2881 ui_breakcheck(); 2882 if (got_int) 2883 { 2884 (void)vgetc(); // only break the file loading, not the rest 2885 break; 2886 } 2887 } 2888 if (parmp->window_layout == WIN_TABS) 2889 goto_tabpage(1); 2890 else 2891 curwin = firstwin; 2892 curbuf = curwin->w_buffer; 2893 --autocmd_no_enter; 2894 --autocmd_no_leave; 2895 } 2896 } 2897 2898 /* 2899 * If opened more than one window, start editing files in the other 2900 * windows. make_windows() has already opened the windows. 2901 */ 2902 static void 2903 edit_buffers( 2904 mparm_T *parmp, 2905 char_u *cwd) // current working dir 2906 { 2907 int arg_idx; // index in argument list 2908 int i; 2909 int advance = TRUE; 2910 win_T *win; 2911 char_u *p_shm_save = NULL; 2912 2913 /* 2914 * Don't execute Win/Buf Enter/Leave autocommands here 2915 */ 2916 ++autocmd_no_enter; 2917 ++autocmd_no_leave; 2918 2919 // When w_arg_idx is -1 remove the window (see create_windows()). 2920 if (curwin->w_arg_idx == -1) 2921 { 2922 win_close(curwin, TRUE); 2923 advance = FALSE; 2924 } 2925 2926 arg_idx = 1; 2927 for (i = 1; i < parmp->window_count; ++i) 2928 { 2929 if (cwd != NULL) 2930 mch_chdir((char *)cwd); 2931 // When w_arg_idx is -1 remove the window (see create_windows()). 2932 if (curwin->w_arg_idx == -1) 2933 { 2934 ++arg_idx; 2935 win_close(curwin, TRUE); 2936 advance = FALSE; 2937 continue; 2938 } 2939 2940 if (advance) 2941 { 2942 if (parmp->window_layout == WIN_TABS) 2943 { 2944 if (curtab->tp_next == NULL) // just checking 2945 break; 2946 goto_tabpage(0); 2947 // Temporarily reset 'shm' option to not print fileinfo when 2948 // loading the other buffers. This would overwrite the already 2949 // existing fileinfo for the first tab. 2950 if (i == 1) 2951 { 2952 char buf[100]; 2953 2954 p_shm_save = vim_strsave(p_shm); 2955 vim_snprintf(buf, 100, "F%s", p_shm); 2956 set_option_value((char_u *)"shm", 0L, (char_u *)buf, 0); 2957 } 2958 } 2959 else 2960 { 2961 if (curwin->w_next == NULL) // just checking 2962 break; 2963 win_enter(curwin->w_next, FALSE); 2964 } 2965 } 2966 advance = TRUE; 2967 2968 // Only open the file if there is no file in this window yet (that can 2969 // happen when .vimrc contains ":sall"). 2970 if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL) 2971 { 2972 curwin->w_arg_idx = arg_idx; 2973 // Edit file from arg list, if there is one. When "Quit" selected 2974 // at the ATTENTION prompt close the window. 2975 swap_exists_did_quit = FALSE; 2976 (void)do_ecmd(0, arg_idx < GARGCOUNT 2977 ? alist_name(&GARGLIST[arg_idx]) : NULL, 2978 NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin); 2979 if (swap_exists_did_quit) 2980 { 2981 // abort or quit selected 2982 if (got_int || only_one_window()) 2983 { 2984 // abort selected and only one window 2985 did_emsg = FALSE; // avoid hit-enter prompt 2986 getout(1); 2987 } 2988 win_close(curwin, TRUE); 2989 advance = FALSE; 2990 } 2991 if (arg_idx == GARGCOUNT - 1) 2992 arg_had_last = TRUE; 2993 ++arg_idx; 2994 } 2995 ui_breakcheck(); 2996 if (got_int) 2997 { 2998 (void)vgetc(); // only break the file loading, not the rest 2999 break; 3000 } 3001 } 3002 3003 if (p_shm_save != NULL) 3004 { 3005 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 3006 vim_free(p_shm_save); 3007 } 3008 3009 if (parmp->window_layout == WIN_TABS) 3010 goto_tabpage(1); 3011 --autocmd_no_enter; 3012 3013 // make the first window the current window 3014 win = firstwin; 3015 #if defined(FEAT_QUICKFIX) 3016 // Avoid making a preview window the current window. 3017 while (win->w_p_pvw) 3018 { 3019 win = win->w_next; 3020 if (win == NULL) 3021 { 3022 win = firstwin; 3023 break; 3024 } 3025 } 3026 #endif 3027 win_enter(win, FALSE); 3028 3029 --autocmd_no_leave; 3030 TIME_MSG("editing files in windows"); 3031 if (parmp->window_count > 1 && parmp->window_layout != WIN_TABS) 3032 win_equal(curwin, FALSE, 'b'); // adjust heights 3033 } 3034 3035 /* 3036 * Execute the commands from --cmd arguments "cmds[cnt]". 3037 */ 3038 static void 3039 exe_pre_commands(mparm_T *parmp) 3040 { 3041 char_u **cmds = parmp->pre_commands; 3042 int cnt = parmp->n_pre_commands; 3043 int i; 3044 ESTACK_CHECK_DECLARATION 3045 3046 if (cnt > 0) 3047 { 3048 curwin->w_cursor.lnum = 0; // just in case.. 3049 estack_push(ETYPE_ARGS, (char_u *)_("pre-vimrc command line"), 0); 3050 ESTACK_CHECK_SETUP 3051 # ifdef FEAT_EVAL 3052 current_sctx.sc_sid = SID_CMDARG; 3053 # endif 3054 for (i = 0; i < cnt; ++i) 3055 do_cmdline_cmd(cmds[i]); 3056 ESTACK_CHECK_NOW 3057 estack_pop(); 3058 # ifdef FEAT_EVAL 3059 current_sctx.sc_sid = 0; 3060 # endif 3061 TIME_MSG("--cmd commands"); 3062 } 3063 } 3064 3065 /* 3066 * Execute "+", "-c" and "-S" arguments. 3067 */ 3068 static void 3069 exe_commands(mparm_T *parmp) 3070 { 3071 int i; 3072 ESTACK_CHECK_DECLARATION 3073 3074 /* 3075 * We start commands on line 0, make "vim +/pat file" match a 3076 * pattern on line 1. But don't move the cursor when an autocommand 3077 * with g`" was used. 3078 */ 3079 msg_scroll = TRUE; 3080 if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) 3081 curwin->w_cursor.lnum = 0; 3082 estack_push(ETYPE_ARGS, (char_u *)"command line", 0); 3083 ESTACK_CHECK_SETUP 3084 #ifdef FEAT_EVAL 3085 current_sctx.sc_sid = SID_CARG; 3086 current_sctx.sc_seq = 0; 3087 #endif 3088 for (i = 0; i < parmp->n_commands; ++i) 3089 { 3090 do_cmdline_cmd(parmp->commands[i]); 3091 if (parmp->cmds_tofree[i]) 3092 vim_free(parmp->commands[i]); 3093 } 3094 ESTACK_CHECK_NOW 3095 estack_pop(); 3096 #ifdef FEAT_EVAL 3097 current_sctx.sc_sid = 0; 3098 #endif 3099 if (curwin->w_cursor.lnum == 0) 3100 curwin->w_cursor.lnum = 1; 3101 3102 if (!exmode_active) 3103 msg_scroll = FALSE; 3104 3105 #ifdef FEAT_QUICKFIX 3106 // When started with "-q errorfile" jump to first error again. 3107 if (parmp->edit_type == EDIT_QF) 3108 qf_jump(NULL, 0, 0, FALSE); 3109 #endif 3110 TIME_MSG("executing command arguments"); 3111 } 3112 3113 /* 3114 * Source startup scripts. 3115 */ 3116 static void 3117 source_startup_scripts(mparm_T *parmp) 3118 { 3119 int i; 3120 3121 /* 3122 * For "evim" source evim.vim first of all, so that the user can overrule 3123 * any things he doesn't like. 3124 */ 3125 if (parmp->evim_mode) 3126 { 3127 (void)do_source((char_u *)EVIM_FILE, FALSE, DOSO_NONE, NULL); 3128 TIME_MSG("source evim file"); 3129 } 3130 3131 /* 3132 * If -u argument given, use only the initializations from that file and 3133 * nothing else. 3134 */ 3135 if (parmp->use_vimrc != NULL) 3136 { 3137 if (STRCMP(parmp->use_vimrc, "DEFAULTS") == 0) 3138 do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE, NULL); 3139 else if (STRCMP(parmp->use_vimrc, "NONE") == 0 3140 || STRCMP(parmp->use_vimrc, "NORC") == 0) 3141 { 3142 #ifdef FEAT_GUI 3143 if (use_gvimrc == NULL) // don't load gvimrc either 3144 use_gvimrc = parmp->use_vimrc; 3145 #endif 3146 } 3147 else 3148 { 3149 if (do_source(parmp->use_vimrc, FALSE, DOSO_NONE, NULL) != OK) 3150 semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); 3151 } 3152 } 3153 else if (!silent_mode) 3154 { 3155 #ifdef AMIGA 3156 struct Process *proc = (struct Process *)FindTask(0L); 3157 APTR save_winptr = proc->pr_WindowPtr; 3158 3159 // Avoid a requester here for a volume that doesn't exist. 3160 proc->pr_WindowPtr = (APTR)-1L; 3161 #endif 3162 3163 /* 3164 * Get system wide defaults, if the file name is defined. 3165 */ 3166 #ifdef SYS_VIMRC_FILE 3167 (void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, DOSO_NONE, NULL); 3168 #endif 3169 #ifdef MACOS_X 3170 (void)do_source((char_u *)"$VIMRUNTIME/macmap.vim", FALSE, 3171 DOSO_NONE, NULL); 3172 #endif 3173 3174 /* 3175 * Try to read initialization commands from the following places: 3176 * - environment variable VIMINIT 3177 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise) 3178 * - second user vimrc file ($VIM/.vimrc for Dos) 3179 * - environment variable EXINIT 3180 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise) 3181 * - second user exrc file ($VIM/.exrc for Dos) 3182 * The first that exists is used, the rest is ignored. 3183 */ 3184 if (process_env((char_u *)"VIMINIT", TRUE) != OK) 3185 { 3186 if (do_source((char_u *)USR_VIMRC_FILE, TRUE, 3187 DOSO_VIMRC, NULL) == FAIL 3188 #ifdef USR_VIMRC_FILE2 3189 && do_source((char_u *)USR_VIMRC_FILE2, TRUE, 3190 DOSO_VIMRC, NULL) == FAIL 3191 #endif 3192 #ifdef USR_VIMRC_FILE3 3193 && do_source((char_u *)USR_VIMRC_FILE3, TRUE, 3194 DOSO_VIMRC, NULL) == FAIL 3195 #endif 3196 #ifdef USR_VIMRC_FILE4 3197 && do_source((char_u *)USR_VIMRC_FILE4, TRUE, 3198 DOSO_VIMRC, NULL) == FAIL 3199 #endif 3200 && process_env((char_u *)"EXINIT", FALSE) == FAIL 3201 && do_source((char_u *)USR_EXRC_FILE, FALSE, 3202 DOSO_NONE, NULL) == FAIL 3203 #ifdef USR_EXRC_FILE2 3204 && do_source((char_u *)USR_EXRC_FILE2, FALSE, 3205 DOSO_NONE, NULL) == FAIL 3206 #endif 3207 && !has_dash_c_arg) 3208 { 3209 // When no .vimrc file was found: source defaults.vim. 3210 do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE, NULL); 3211 } 3212 } 3213 3214 /* 3215 * Read initialization commands from ".vimrc" or ".exrc" in current 3216 * directory. This is only done if the 'exrc' option is set. 3217 * Because of security reasons we disallow shell and write commands 3218 * now, except for Unix if the file is owned by the user or 'secure' 3219 * option has been reset in environment of global ".exrc" or ".vimrc". 3220 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or 3221 * SYS_VIMRC_FILE. 3222 */ 3223 if (p_exrc) 3224 { 3225 #if defined(UNIX) || defined(VMS) 3226 // If ".vimrc" file is not owned by user, set 'secure' mode. 3227 if (!file_owned(VIMRC_FILE)) 3228 #endif 3229 secure = p_secure; 3230 3231 i = FAIL; 3232 if (fullpathcmp((char_u *)USR_VIMRC_FILE, 3233 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME 3234 #ifdef USR_VIMRC_FILE2 3235 && fullpathcmp((char_u *)USR_VIMRC_FILE2, 3236 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME 3237 #endif 3238 #ifdef USR_VIMRC_FILE3 3239 && fullpathcmp((char_u *)USR_VIMRC_FILE3, 3240 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME 3241 #endif 3242 #ifdef SYS_VIMRC_FILE 3243 && fullpathcmp((char_u *)SYS_VIMRC_FILE, 3244 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME 3245 #endif 3246 ) 3247 i = do_source((char_u *)VIMRC_FILE, TRUE, DOSO_VIMRC, NULL); 3248 3249 if (i == FAIL) 3250 { 3251 #if defined(UNIX) || defined(VMS) 3252 // if ".exrc" is not owned by user set 'secure' mode 3253 if (!file_owned(EXRC_FILE)) 3254 secure = p_secure; 3255 else 3256 secure = 0; 3257 #endif 3258 if ( fullpathcmp((char_u *)USR_EXRC_FILE, 3259 (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME 3260 #ifdef USR_EXRC_FILE2 3261 && fullpathcmp((char_u *)USR_EXRC_FILE2, 3262 (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME 3263 #endif 3264 ) 3265 (void)do_source((char_u *)EXRC_FILE, FALSE, 3266 DOSO_NONE, NULL); 3267 } 3268 } 3269 if (secure == 2) 3270 need_wait_return = TRUE; 3271 secure = 0; 3272 #ifdef AMIGA 3273 proc->pr_WindowPtr = save_winptr; 3274 #endif 3275 } 3276 TIME_MSG("sourcing vimrc file(s)"); 3277 } 3278 3279 /* 3280 * Setup to start using the GUI. Exit with an error when not available. 3281 */ 3282 static void 3283 main_start_gui(void) 3284 { 3285 #ifdef FEAT_GUI 3286 gui.starting = TRUE; // start GUI a bit later 3287 #else 3288 mch_errmsg(_(e_nogvim)); 3289 mch_errmsg("\n"); 3290 mch_exit(2); 3291 #endif 3292 } 3293 3294 #endif // NO_VIM_MAIN 3295 3296 /* 3297 * Get an environment variable and execute it as Ex commands. 3298 * Returns FAIL if the environment variable was not executed, OK otherwise. 3299 */ 3300 int 3301 process_env( 3302 char_u *env, 3303 int is_viminit) // when TRUE, called for VIMINIT 3304 { 3305 char_u *initstr; 3306 #ifdef FEAT_EVAL 3307 sctx_T save_current_sctx; 3308 #endif 3309 ESTACK_CHECK_DECLARATION 3310 3311 if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) 3312 { 3313 if (is_viminit) 3314 vimrc_found(NULL, NULL); 3315 estack_push(ETYPE_ENV, env, 0); 3316 ESTACK_CHECK_SETUP 3317 #ifdef FEAT_EVAL 3318 save_current_sctx = current_sctx; 3319 current_sctx.sc_sid = SID_ENV; 3320 current_sctx.sc_seq = 0; 3321 current_sctx.sc_lnum = 0; 3322 current_sctx.sc_version = 1; 3323 #endif 3324 do_cmdline_cmd(initstr); 3325 3326 ESTACK_CHECK_NOW 3327 estack_pop(); 3328 #ifdef FEAT_EVAL 3329 current_sctx = save_current_sctx; 3330 #endif 3331 return OK; 3332 } 3333 return FAIL; 3334 } 3335 3336 #if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN) 3337 /* 3338 * Return TRUE if we are certain the user owns the file "fname". 3339 * Used for ".vimrc" and ".exrc". 3340 * Use both stat() and lstat() for extra security. 3341 */ 3342 static int 3343 file_owned(char *fname) 3344 { 3345 stat_T s; 3346 # ifdef UNIX 3347 uid_t uid = getuid(); 3348 # else // VMS 3349 uid_t uid = ((getgid() << 16) | getuid()); 3350 # endif 3351 3352 return !(mch_stat(fname, &s) != 0 || s.st_uid != uid 3353 # ifdef HAVE_LSTAT 3354 || mch_lstat(fname, &s) != 0 || s.st_uid != uid 3355 # endif 3356 ); 3357 } 3358 #endif 3359 3360 /* 3361 * Give an error message main_errors["n"] and exit. 3362 */ 3363 static void 3364 mainerr( 3365 int n, // one of the ME_ defines 3366 char_u *str) // extra argument or NULL 3367 { 3368 #if defined(UNIX) || defined(VMS) 3369 reset_signals(); // kill us with CTRL-C here, if you like 3370 #endif 3371 3372 // If this is a Windows GUI executable, show an error dialog box. 3373 #ifdef VIMDLL 3374 gui.in_use = mch_is_gui_executable(); 3375 #endif 3376 #ifdef FEAT_GUI_MSWIN 3377 gui.starting = FALSE; // Needed to show as error. 3378 #endif 3379 3380 init_longVersion(); 3381 mch_errmsg(longVersion); 3382 mch_errmsg("\n"); 3383 mch_errmsg(_(main_errors[n])); 3384 if (str != NULL) 3385 { 3386 mch_errmsg(": \""); 3387 mch_errmsg((char *)str); 3388 mch_errmsg("\""); 3389 } 3390 mch_errmsg(_("\nMore info with: \"vim -h\"\n")); 3391 3392 mch_exit(1); 3393 } 3394 3395 void 3396 mainerr_arg_missing(char_u *str) 3397 { 3398 mainerr(ME_ARG_MISSING, str); 3399 } 3400 3401 #ifndef NO_VIM_MAIN 3402 /* 3403 * print a message with three spaces prepended and '\n' appended. 3404 */ 3405 static void 3406 main_msg(char *s) 3407 { 3408 mch_msg(" "); 3409 mch_msg(s); 3410 mch_msg("\n"); 3411 } 3412 3413 /* 3414 * Print messages for "vim -h" or "vim --help" and exit. 3415 */ 3416 static void 3417 usage(void) 3418 { 3419 int i; 3420 static char *(use[]) = 3421 { 3422 N_("[file ..] edit specified file(s)"), 3423 N_("- read text from stdin"), 3424 N_("-t tag edit file where tag is defined"), 3425 #ifdef FEAT_QUICKFIX 3426 N_("-q [errorfile] edit file with first error") 3427 #endif 3428 }; 3429 3430 #if defined(UNIX) || defined(VMS) 3431 reset_signals(); // kill us with CTRL-C here, if you like 3432 #endif 3433 3434 init_longVersion(); 3435 mch_msg(longVersion); 3436 mch_msg(_("\n\nUsage:")); 3437 for (i = 0; ; ++i) 3438 { 3439 mch_msg(_(" vim [arguments] ")); 3440 mch_msg(_(use[i])); 3441 if (i == (sizeof(use) / sizeof(char_u *)) - 1) 3442 break; 3443 mch_msg(_("\n or:")); 3444 } 3445 #ifdef VMS 3446 mch_msg(_("\nWhere case is ignored prepend / to make flag upper case")); 3447 #endif 3448 3449 mch_msg(_("\n\nArguments:\n")); 3450 main_msg(_("--\t\t\tOnly file names after this")); 3451 #ifdef EXPAND_FILENAMES 3452 main_msg(_("--literal\t\tDon't expand wildcards")); 3453 #endif 3454 #ifdef FEAT_OLE 3455 main_msg(_("-register\t\tRegister this gvim for OLE")); 3456 main_msg(_("-unregister\t\tUnregister gvim for OLE")); 3457 #endif 3458 #ifdef FEAT_GUI 3459 main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")")); 3460 main_msg(_("-f or --nofork\tForeground: Don't fork when starting GUI")); 3461 #endif 3462 main_msg(_("-v\t\t\tVi mode (like \"vi\")")); 3463 main_msg(_("-e\t\t\tEx mode (like \"ex\")")); 3464 main_msg(_("-E\t\t\tImproved Ex mode")); 3465 main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")")); 3466 #ifdef FEAT_DIFF 3467 main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")")); 3468 #endif 3469 main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)")); 3470 main_msg(_("-R\t\t\tReadonly mode (like \"view\")")); 3471 main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")")); 3472 main_msg(_("-m\t\t\tModifications (writing files) not allowed")); 3473 main_msg(_("-M\t\t\tModifications in text not allowed")); 3474 main_msg(_("-b\t\t\tBinary mode")); 3475 #ifdef FEAT_LISP 3476 main_msg(_("-l\t\t\tLisp mode")); 3477 #endif 3478 main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'")); 3479 main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'")); 3480 main_msg(_("-V[N][fname]\t\tBe verbose [level N] [log messages to fname]")); 3481 #ifdef FEAT_EVAL 3482 main_msg(_("-D\t\t\tDebugging mode")); 3483 #endif 3484 main_msg(_("-n\t\t\tNo swap file, use memory only")); 3485 main_msg(_("-r\t\t\tList swap files and exit")); 3486 main_msg(_("-r (with file name)\tRecover crashed session")); 3487 main_msg(_("-L\t\t\tSame as -r")); 3488 #ifdef AMIGA 3489 main_msg(_("-f\t\t\tDon't use newcli to open window")); 3490 main_msg(_("-dev <device>\t\tUse <device> for I/O")); 3491 #endif 3492 #ifdef FEAT_ARABIC 3493 main_msg(_("-A\t\t\tStart in Arabic mode")); 3494 #endif 3495 #ifdef FEAT_RIGHTLEFT 3496 main_msg(_("-H\t\t\tStart in Hebrew mode")); 3497 #endif 3498 main_msg(_("-T <terminal>\tSet terminal type to <terminal>")); 3499 main_msg(_("--not-a-term\t\tSkip warning for input/output not being a terminal")); 3500 main_msg(_("--ttyfail\t\tExit if input or output is not a terminal")); 3501 main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc")); 3502 #ifdef FEAT_GUI 3503 main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc")); 3504 #endif 3505 main_msg(_("--noplugin\t\tDon't load plugin scripts")); 3506 main_msg(_("-p[N]\t\tOpen N tab pages (default: one for each file)")); 3507 main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)")); 3508 main_msg(_("-O[N]\t\tLike -o but split vertically")); 3509 main_msg(_("+\t\t\tStart at end of file")); 3510 main_msg(_("+<lnum>\t\tStart at line <lnum>")); 3511 main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file")); 3512 main_msg(_("-c <command>\t\tExecute <command> after loading the first file")); 3513 main_msg(_("-S <session>\t\tSource file <session> after loading the first file")); 3514 main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>")); 3515 main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>")); 3516 main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>")); 3517 #ifdef FEAT_CRYPT 3518 main_msg(_("-x\t\t\tEdit encrypted files")); 3519 #endif 3520 #if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11) 3521 # if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) 3522 main_msg(_("-display <display>\tConnect Vim to this particular X-server")); 3523 # endif 3524 main_msg(_("-X\t\t\tDo not connect to X server")); 3525 #endif 3526 #ifdef FEAT_CLIENTSERVER 3527 main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible")); 3528 main_msg(_("--remote-silent <files> Same, don't complain if there is no server")); 3529 main_msg(_("--remote-wait <files> As --remote but wait for files to have been edited")); 3530 main_msg(_("--remote-wait-silent <files> Same, don't complain if there is no server")); 3531 main_msg(_("--remote-tab[-wait][-silent] <files> As --remote but use tab page per file")); 3532 main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit")); 3533 main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result")); 3534 main_msg(_("--serverlist\t\tList available Vim server names and exit")); 3535 main_msg(_("--servername <name>\tSend to/become the Vim server <name>")); 3536 #endif 3537 #ifdef STARTUPTIME 3538 main_msg(_("--startuptime <file>\tWrite startup timing messages to <file>")); 3539 #endif 3540 #ifdef FEAT_VIMINFO 3541 main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo")); 3542 #endif 3543 main_msg(_("--clean\t\t'nocompatible', Vim defaults, no plugins, no viminfo")); 3544 main_msg(_("-h or --help\tPrint Help (this message) and exit")); 3545 main_msg(_("--version\t\tPrint version information and exit")); 3546 3547 #ifdef FEAT_GUI_X11 3548 # ifdef FEAT_GUI_MOTIF 3549 mch_msg(_("\nArguments recognised by gvim (Motif version):\n")); 3550 # else 3551 # ifdef FEAT_GUI_ATHENA 3552 # ifdef FEAT_GUI_NEXTAW 3553 mch_msg(_("\nArguments recognised by gvim (neXtaw version):\n")); 3554 # else 3555 mch_msg(_("\nArguments recognised by gvim (Athena version):\n")); 3556 # endif 3557 # endif 3558 # endif 3559 main_msg(_("-display <display>\tRun Vim on <display>")); 3560 main_msg(_("-iconic\t\tStart Vim iconified")); 3561 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)")); 3562 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)")); 3563 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)")); 3564 main_msg(_("-boldfont <font>\tUse <font> for bold text")); 3565 main_msg(_("-italicfont <font>\tUse <font> for italic text")); 3566 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)")); 3567 main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)")); 3568 main_msg(_("-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)")); 3569 # ifdef FEAT_GUI_ATHENA 3570 main_msg(_("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)")); 3571 # endif 3572 main_msg(_("-reverse\t\tUse reverse video (also: -rv)")); 3573 main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)")); 3574 main_msg(_("-xrm <resource>\tSet the specified resource")); 3575 #endif // FEAT_GUI_X11 3576 #ifdef FEAT_GUI_GTK 3577 mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n")); 3578 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)")); 3579 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)")); 3580 main_msg(_("-reverse\t\tUse reverse video (also: -rv)")); 3581 main_msg(_("-display <display>\tRun Vim on <display> (also: --display)")); 3582 main_msg(_("--role <role>\tSet a unique role to identify the main window")); 3583 main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget")); 3584 main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout")); 3585 #endif 3586 #ifdef FEAT_GUI_MSWIN 3587 # ifdef VIMDLL 3588 if (gui.starting) 3589 # endif 3590 { 3591 main_msg(_("-P <parent title>\tOpen Vim inside parent application")); 3592 main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget")); 3593 } 3594 #endif 3595 3596 #ifdef FEAT_GUI_GNOME 3597 // Gnome gives extra messages for --help if we continue, but not for -h. 3598 if (gui.starting) 3599 { 3600 mch_msg("\n"); 3601 gui.dofork = FALSE; 3602 } 3603 else 3604 #endif 3605 mch_exit(0); 3606 } 3607 3608 /* 3609 * Check the result of the ATTENTION dialog: 3610 * When "Quit" selected, exit Vim. 3611 * When "Recover" selected, recover the file. 3612 */ 3613 static void 3614 check_swap_exists_action(void) 3615 { 3616 if (swap_exists_action == SEA_QUIT) 3617 getout(1); 3618 handle_swap_exists(NULL); 3619 } 3620 3621 #endif // NO_VIM_MAIN 3622 3623 #if !defined(NO_VIM_MAIN) && defined(FEAT_EVAL) 3624 static void 3625 set_progpath(char_u *argv0) 3626 { 3627 char_u *val = argv0; 3628 3629 # ifdef MSWIN 3630 // A relative path containing a "/" will become invalid when using ":cd", 3631 // turn it into a full path. 3632 // On MS-Windows "vim" should be expanded to "vim.exe", thus always do 3633 // this. 3634 char_u *path = NULL; 3635 3636 if (mch_can_exe(argv0, &path, FALSE) && path != NULL) 3637 val = path; 3638 # else 3639 char_u buf[MAXPATHL + 1]; 3640 # ifdef PROC_EXE_LINK 3641 char linkbuf[MAXPATHL + 1]; 3642 ssize_t len; 3643 3644 len = readlink(PROC_EXE_LINK, linkbuf, MAXPATHL); 3645 if (len > 0) 3646 { 3647 linkbuf[len] = NUL; 3648 val = (char_u *)linkbuf; 3649 } 3650 # endif 3651 3652 if (!mch_isFullName(val)) 3653 { 3654 if (gettail(val) != val 3655 && vim_FullName(val, buf, MAXPATHL, TRUE) != FAIL) 3656 val = buf; 3657 } 3658 # endif 3659 3660 set_vim_var_string(VV_PROGPATH, val, -1); 3661 3662 # ifdef MSWIN 3663 vim_free(path); 3664 # endif 3665 } 3666 3667 #endif // NO_VIM_MAIN 3668