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