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