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