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