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