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