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