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