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