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