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 #if defined(FEAT_MBYTE) && defined(WIN32) 1070 { 1071 extern void used_file_arg(char *, int, int); 1072 1073 /* Remember this argument has been added to the argument list. 1074 * Needed when 'encoding' is changed. */ 1075 used_file_arg(argv[0], literal, full_path); 1076 } 1077 #endif 1078 } 1079 1080 /* 1081 * If there are no more letters after the current "-", go to next 1082 * argument. argv_idx is set to -1 when the current argument is to be 1083 * skipped. 1084 */ 1085 if (argv_idx <= 0 || argv[0][argv_idx] == NUL) 1086 { 1087 --argc; 1088 ++argv; 1089 argv_idx = 1; 1090 } 1091 } 1092 TIME_MSG("parsing arguments"); 1093 1094 /* 1095 * On some systems, when we compile with the GUI, we always use it. On Mac 1096 * there is no terminal version, and on Windows we can't figure out how to 1097 * fork one off with :gui. 1098 */ 1099 #ifdef ALWAYS_USE_GUI 1100 gui.starting = TRUE; 1101 #else 1102 # if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE) 1103 /* 1104 * Check if the GUI can be started. Reset gui.starting if not. 1105 * Don't know about other systems, stay on the safe side and don't check. 1106 */ 1107 if (gui.starting && gui_init_check() == FAIL) 1108 { 1109 gui.starting = FALSE; 1110 1111 /* When running "evim" or "gvim -y" we need the menus, exit if we 1112 * don't have them. */ 1113 if (evim_mode) 1114 mch_exit(1); 1115 } 1116 # endif 1117 #endif 1118 1119 /* "-b" argument used. Check before expanding file names, because for 1120 * Win32 this makes us edit a shortcut file itself, instead of the file it 1121 * links to. */ 1122 if (bin_mode) 1123 { 1124 set_options_bin(curbuf->b_p_bin, 1, 0); 1125 curbuf->b_p_bin = 1; /* binary file I/O */ 1126 } 1127 1128 if (GARGCOUNT > 0) 1129 { 1130 #if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) 1131 /* 1132 * Expand wildcards in file names. 1133 */ 1134 if (!literal) 1135 { 1136 /* Temporarily add '(' and ')' to 'isfname'. These are valid 1137 * filename characters but are excluded from 'isfname' to make 1138 * "gf" work on a file name in parenthesis (e.g.: see vim.h). */ 1139 do_cmdline_cmd((char_u *)":set isf+=(,)"); 1140 alist_expand(); 1141 do_cmdline_cmd((char_u *)":set isf&"); 1142 } 1143 #endif 1144 fname = alist_name(&GARGLIST[0]); 1145 } 1146 1147 #if defined(WIN32) && defined(FEAT_MBYTE) 1148 { 1149 extern void set_alist_count(void); 1150 1151 /* Remember the number of entries in the argument list. If it changes 1152 * we don't react on setting 'encoding'. */ 1153 set_alist_count(); 1154 } 1155 #endif 1156 1157 if (GARGCOUNT > 1) 1158 printf(_("%d files to edit\n"), GARGCOUNT); 1159 #ifdef MSWIN 1160 else if (GARGCOUNT == 1 && full_path) 1161 { 1162 /* 1163 * If there is one filename, fully qualified, we have very probably 1164 * been invoked from explorer, so change to the file's directory. 1165 * Hint: to avoid this when typing a command use a forward slash. 1166 * If the cd fails, it doesn't matter. 1167 */ 1168 (void)vim_chdirfile(fname); 1169 } 1170 #endif 1171 TIME_MSG("expanding arguments"); 1172 1173 #ifdef FEAT_DIFF 1174 if (diff_mode) 1175 { 1176 if (window_count == -1) 1177 window_count = 0; /* open up to 3 files in a window */ 1178 if (vert_windows == MAYBE) 1179 vert_windows = TRUE; /* use vertical split */ 1180 } 1181 #endif 1182 1183 ++RedrawingDisabled; 1184 1185 /* 1186 * When listing swap file names, don't do cursor positioning et. al. 1187 */ 1188 if (recoverymode && fname == NULL) 1189 want_full_screen = FALSE; 1190 1191 /* 1192 * When certain to start the GUI, don't check capabilities of terminal. 1193 * For GTK we can't be sure, but when started from the desktop it doesn't 1194 * make sense to try using a terminal. 1195 */ 1196 #if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE) 1197 if (gui.starting 1198 # ifdef FEAT_GUI_GTK 1199 && !isatty(2) 1200 # endif 1201 ) 1202 want_full_screen = FALSE; 1203 #endif 1204 1205 #if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX) 1206 /* When the GUI is started from Finder, need to display messages in a 1207 * message box. isatty(2) returns TRUE anyway, thus we need to check the 1208 * name to know we're not started from a terminal. */ 1209 if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0)) 1210 want_full_screen = FALSE; 1211 #endif 1212 1213 /* 1214 * mch_init() sets up the terminal (window) for use. This must be 1215 * done after resetting full_screen, otherwise it may move the cursor 1216 * (MSDOS). 1217 * Note that we may use mch_exit() before mch_init()! 1218 */ 1219 mch_init(); 1220 TIME_MSG("shell init"); 1221 1222 #ifdef USE_XSMP 1223 /* 1224 * For want of anywhere else to do it, try to connect to xsmp here. 1225 * Fitting it in after gui_mch_init, but before gui_init (via termcapinit). 1226 * Hijacking -X 'no X connection' to also disable XSMP connection as that 1227 * has a similar delay upon failure. 1228 * Only try if SESSION_MANAGER is set to something non-null. 1229 */ 1230 if (!x_no_connect) 1231 { 1232 p = (char_u *)getenv("SESSION_MANAGER"); 1233 if (p != NULL && *p != NUL) 1234 { 1235 xsmp_init(); 1236 TIME_MSG("xsmp init"); 1237 } 1238 } 1239 #endif 1240 1241 /* 1242 * Print a warning if stdout is not a terminal. 1243 * When starting in Ex mode and commands come from a file, set Silent mode. 1244 */ 1245 input_isatty = mch_input_isatty(); 1246 if (exmode_active) 1247 { 1248 if (!input_isatty) 1249 silent_mode = TRUE; 1250 } 1251 else if (want_full_screen && (!stdout_isatty || !input_isatty) 1252 #ifdef FEAT_GUI 1253 /* don't want the delay when started from the desktop */ 1254 && !gui.starting 1255 #endif 1256 ) 1257 { 1258 if (!stdout_isatty) 1259 mch_errmsg(_("Vim: Warning: Output is not to a terminal\n")); 1260 if (!input_isatty) 1261 mch_errmsg(_("Vim: Warning: Input is not from a terminal\n")); 1262 out_flush(); 1263 if (scriptin[0] == NULL) 1264 ui_delay(2000L, TRUE); 1265 TIME_MSG("Warning delay"); 1266 } 1267 1268 if (want_full_screen) 1269 { 1270 termcapinit(term); /* set terminal name and get terminal 1271 capabilities (will set full_screen) */ 1272 screen_start(); /* don't know where cursor is now */ 1273 TIME_MSG("Termcap init"); 1274 } 1275 1276 /* 1277 * Set the default values for the options that use Rows and Columns. 1278 */ 1279 ui_get_shellsize(); /* inits Rows and Columns */ 1280 #ifdef FEAT_NETBEANS_INTG 1281 if (usingNetbeans) 1282 Columns += 2; /* leave room for glyph gutter */ 1283 #endif 1284 firstwin->w_height = Rows - p_ch; 1285 topframe->fr_height = Rows - p_ch; 1286 #ifdef FEAT_VERTSPLIT 1287 firstwin->w_width = Columns; 1288 topframe->fr_width = Columns; 1289 #endif 1290 #ifdef FEAT_DIFF 1291 /* Set the 'diff' option now, so that it can be checked for in a .vimrc 1292 * file. There is no buffer yet though. */ 1293 if (diff_mode) 1294 diff_win_options(firstwin, FALSE); 1295 #endif 1296 1297 cmdline_row = Rows - p_ch; 1298 msg_row = cmdline_row; 1299 screenalloc(FALSE); /* allocate screen buffers */ 1300 set_init_2(); 1301 TIME_MSG("inits 2"); 1302 1303 msg_scroll = TRUE; 1304 no_wait_return = TRUE; 1305 1306 init_mappings(); /* set up initial mappings */ 1307 1308 init_highlight(TRUE, FALSE); /* set the default highlight groups */ 1309 TIME_MSG("init highlight"); 1310 #ifdef CURSOR_SHAPE 1311 parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */ 1312 #endif 1313 #ifdef FEAT_MOUSESHAPE 1314 parse_shape_opt(SHAPE_MOUSE); /* set mouse shapes from 'mouseshape' */ 1315 #endif 1316 #ifdef FEAT_PRINTER 1317 parse_list_options(p_popt, printer_opts, OPT_PRINT_NUM_OPTIONS); 1318 #endif 1319 1320 #ifdef FEAT_EVAL 1321 /* Set the break level after the terminal is initialized. */ 1322 debug_break_level = use_debug_break_level; 1323 #endif 1324 1325 #ifdef FEAT_PRECOMMANDS 1326 if (p_commands > 0) 1327 { 1328 curwin->w_cursor.lnum = 0; /* just in case.. */ 1329 sourcing_name = (char_u *)_("pre-vimrc command line"); 1330 # ifdef FEAT_EVAL 1331 current_SID = SID_CMDARG; 1332 # endif 1333 for (i = 0; i < p_commands; ++i) 1334 do_cmdline_cmd(pre_commands[i]); 1335 sourcing_name = NULL; 1336 # ifdef FEAT_EVAL 1337 current_SID = 0; 1338 # endif 1339 } 1340 #endif 1341 1342 /* 1343 * For "evim" source evim.vim first of all, so that the user can overrule 1344 * any things he doesn't like. 1345 */ 1346 if (evim_mode) 1347 { 1348 (void)do_source((char_u *)EVIM_FILE, FALSE, FALSE); 1349 TIME_MSG("source evim file"); 1350 } 1351 1352 /* 1353 * If -u option given, use only the initializations from that file and 1354 * nothing else. 1355 */ 1356 if (use_vimrc != NULL) 1357 { 1358 if (STRCMP(use_vimrc, "NONE") == 0 || STRCMP(use_vimrc, "NORC") == 0) 1359 { 1360 #ifdef FEAT_GUI 1361 if (use_gvimrc == NULL) /* don't load gvimrc either */ 1362 use_gvimrc = use_vimrc; 1363 #endif 1364 if (use_vimrc[2] == 'N') 1365 p_lpl = FALSE; /* don't load plugins either */ 1366 } 1367 else 1368 { 1369 if (do_source(use_vimrc, FALSE, FALSE) != OK) 1370 EMSG2(_("E282: Cannot read from \"%s\""), use_vimrc); 1371 } 1372 } 1373 else if (!silent_mode) 1374 { 1375 #ifdef AMIGA 1376 struct Process *proc = (struct Process *)FindTask(0L); 1377 APTR save_winptr = proc->pr_WindowPtr; 1378 1379 /* Avoid a requester here for a volume that doesn't exist. */ 1380 proc->pr_WindowPtr = (APTR)-1L; 1381 #endif 1382 1383 /* 1384 * Get system wide defaults, if the file name is defined. 1385 */ 1386 #ifdef SYS_VIMRC_FILE 1387 (void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, FALSE); 1388 #endif 1389 1390 /* 1391 * Try to read initialization commands from the following places: 1392 * - environment variable VIMINIT 1393 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise) 1394 * - second user vimrc file ($VIM/.vimrc for Dos) 1395 * - environment variable EXINIT 1396 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise) 1397 * - second user exrc file ($VIM/.exrc for Dos) 1398 * The first that exists is used, the rest is ignored. 1399 */ 1400 if (process_env((char_u *)"VIMINIT", TRUE) != OK) 1401 { 1402 if (do_source((char_u *)USR_VIMRC_FILE, TRUE, TRUE) == FAIL 1403 #ifdef USR_VIMRC_FILE2 1404 && do_source((char_u *)USR_VIMRC_FILE2, TRUE, TRUE) == FAIL 1405 #endif 1406 #ifdef USR_VIMRC_FILE3 1407 && do_source((char_u *)USR_VIMRC_FILE3, TRUE, TRUE) == FAIL 1408 #endif 1409 && process_env((char_u *)"EXINIT", FALSE) == FAIL 1410 && do_source((char_u *)USR_EXRC_FILE, FALSE, FALSE) == FAIL) 1411 { 1412 #ifdef USR_EXRC_FILE2 1413 (void)do_source((char_u *)USR_EXRC_FILE2, FALSE, FALSE); 1414 #endif 1415 } 1416 } 1417 1418 /* 1419 * Read initialization commands from ".vimrc" or ".exrc" in current 1420 * directory. This is only done if the 'exrc' option is set. 1421 * Because of security reasons we disallow shell and write commands 1422 * now, except for unix if the file is owned by the user or 'secure' 1423 * option has been reset in environmet of global ".exrc" or ".vimrc". 1424 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or 1425 * SYS_VIMRC_FILE. 1426 */ 1427 if (p_exrc) 1428 { 1429 #if defined(UNIX) || defined(VMS) 1430 /* If ".vimrc" file is not owned by user, set 'secure' mode. */ 1431 if (!file_owned(VIMRC_FILE)) 1432 #endif 1433 secure = p_secure; 1434 1435 i = FAIL; 1436 if (fullpathcmp((char_u *)USR_VIMRC_FILE, 1437 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME 1438 #ifdef USR_VIMRC_FILE2 1439 && fullpathcmp((char_u *)USR_VIMRC_FILE2, 1440 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME 1441 #endif 1442 #ifdef USR_VIMRC_FILE3 1443 && fullpathcmp((char_u *)USR_VIMRC_FILE3, 1444 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME 1445 #endif 1446 #ifdef SYS_VIMRC_FILE 1447 && fullpathcmp((char_u *)SYS_VIMRC_FILE, 1448 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME 1449 #endif 1450 ) 1451 i = do_source((char_u *)VIMRC_FILE, TRUE, TRUE); 1452 1453 if (i == FAIL) 1454 { 1455 #if defined(UNIX) || defined(VMS) 1456 /* if ".exrc" is not owned by user set 'secure' mode */ 1457 if (!file_owned(EXRC_FILE)) 1458 secure = p_secure; 1459 else 1460 secure = 0; 1461 #endif 1462 if ( fullpathcmp((char_u *)USR_EXRC_FILE, 1463 (char_u *)EXRC_FILE, FALSE) != FPC_SAME 1464 #ifdef USR_EXRC_FILE2 1465 && fullpathcmp((char_u *)USR_EXRC_FILE2, 1466 (char_u *)EXRC_FILE, FALSE) != FPC_SAME 1467 #endif 1468 ) 1469 (void)do_source((char_u *)EXRC_FILE, FALSE, FALSE); 1470 } 1471 } 1472 if (secure == 2) 1473 need_wait_return = TRUE; 1474 secure = 0; 1475 #ifdef AMIGA 1476 proc->pr_WindowPtr = save_winptr; 1477 #endif 1478 } 1479 TIME_MSG("sourcing vimrc file(s)"); 1480 1481 #ifdef FEAT_EVAL 1482 /* 1483 * Read all the plugin files. 1484 * Only when compiled with +eval, since most plugins need it. 1485 */ 1486 if (p_lpl) 1487 { 1488 cmd_runtime((char_u *)"plugin/*.vim", TRUE); 1489 TIME_MSG("loading plugins"); 1490 } 1491 #endif 1492 1493 /* 1494 * Recovery mode without a file name: List swap files. 1495 * This uses the 'dir' option, therefore it must be after the 1496 * initializations. 1497 */ 1498 if (recoverymode && fname == NULL) 1499 { 1500 recover_names(NULL, TRUE, 0); 1501 mch_exit(0); 1502 } 1503 1504 /* 1505 * Set a few option defaults after reading .vimrc files: 1506 * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'. 1507 */ 1508 set_init_3(); 1509 TIME_MSG("inits 3"); 1510 1511 /* 1512 * "-n" argument: Disable swap file by setting 'updatecount' to 0. 1513 * Note that this overrides anything from a vimrc file. 1514 */ 1515 if (no_swap_file) 1516 p_uc = 0; 1517 1518 #ifdef FEAT_FKMAP 1519 if (curwin->w_p_rl && p_altkeymap) 1520 { 1521 p_hkmap = FALSE; /* Reset the Hebrew keymap mode */ 1522 # ifdef FEAT_ARABIC 1523 curwin->w_p_arab = FALSE; /* Reset the Arabic keymap mode */ 1524 # endif 1525 p_fkmap = TRUE; /* Set the Farsi keymap mode */ 1526 } 1527 #endif 1528 1529 #ifdef FEAT_GUI 1530 if (gui.starting) 1531 { 1532 #if defined(UNIX) || defined(VMS) 1533 /* When something caused a message from a vimrc script, need to output 1534 * an extra newline before the shell prompt. */ 1535 if (did_emsg || msg_didout) 1536 putchar('\n'); 1537 #endif 1538 1539 gui_start(); /* will set full_screen to TRUE */ 1540 TIME_MSG("starting GUI"); 1541 1542 /* When running "evim" or "gvim -y" we need the menus, exit if we 1543 * don't have them. */ 1544 if (!gui.in_use && evim_mode) 1545 mch_exit(1); 1546 } 1547 #endif 1548 1549 #ifdef SPAWNO /* special MSDOS swapping library */ 1550 init_SPAWNO("", SWAP_ANY); 1551 #endif 1552 1553 #ifdef FEAT_VIMINFO 1554 /* 1555 * Read in registers, history etc, but not marks, from the viminfo file 1556 */ 1557 if (*p_viminfo != NUL) 1558 { 1559 read_viminfo(NULL, TRUE, FALSE, FALSE); 1560 TIME_MSG("reading viminfo"); 1561 } 1562 #endif 1563 1564 #ifdef FEAT_QUICKFIX 1565 /* 1566 * "-q errorfile": Load the error file now. 1567 * If the error file can't be read, exit before doing anything else. 1568 */ 1569 if (edit_type == EDIT_QF) 1570 { 1571 if (use_ef != NULL) 1572 set_string_option_direct((char_u *)"ef", -1, use_ef, OPT_FREE); 1573 if (qf_init(p_ef, p_efm, TRUE) < 0) 1574 { 1575 out_char('\n'); 1576 mch_exit(3); 1577 } 1578 TIME_MSG("reading errorfile"); 1579 } 1580 #endif 1581 1582 /* 1583 * Start putting things on the screen. 1584 * Scroll screen down before drawing over it 1585 * Clear screen now, so file message will not be cleared. 1586 */ 1587 starting = NO_BUFFERS; 1588 no_wait_return = FALSE; 1589 if (!exmode_active) 1590 msg_scroll = FALSE; 1591 1592 #ifdef FEAT_GUI 1593 /* 1594 * This seems to be required to make callbacks to be called now, instead 1595 * of after things have been put on the screen, which then may be deleted 1596 * when getting a resize callback. 1597 * For the Mac this handles putting files dropped on the Vim icon to 1598 * global_alist. 1599 */ 1600 if (gui.in_use) 1601 { 1602 # ifdef FEAT_SUN_WORKSHOP 1603 if (!usingSunWorkShop) 1604 # endif 1605 gui_wait_for_chars(50L); 1606 TIME_MSG("GUI delay"); 1607 } 1608 #endif 1609 1610 #if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD) 1611 qnx_clip_init(); 1612 #endif 1613 1614 #ifdef FEAT_XCLIPBOARD 1615 /* Start using the X clipboard, unless the GUI was started. */ 1616 # ifdef FEAT_GUI 1617 if (!gui.in_use) 1618 # endif 1619 { 1620 setup_term_clip(); 1621 TIME_MSG("setup clipboard"); 1622 } 1623 #endif 1624 1625 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) 1626 /* 1627 * Register for remote command execution with :serversend and --remote 1628 * unless there was a -X or a --servername '' on the command line. 1629 * Only register nongui-vim's with an explicit --servername argument. 1630 */ 1631 if (X_DISPLAY != NULL && servername != NULL && ( 1632 # ifdef FEAT_GUI 1633 gui.in_use || 1634 # endif 1635 serverName_arg != NULL)) 1636 { 1637 (void)serverRegisterName(X_DISPLAY, servername); 1638 vim_free(servername); 1639 TIME_MSG("register server name"); 1640 } 1641 else 1642 serverDelayedStartName = servername; 1643 #endif 1644 1645 #ifdef FEAT_CLIENTSERVER 1646 /* 1647 * Execute command ourselves if we're here because the send failed (or 1648 * else we would have exited above). 1649 */ 1650 if (serverStr != NULL) 1651 server_to_input_buf(serverStr); 1652 #endif 1653 1654 /* 1655 * If "-" argument given: Read file from stdin. 1656 * Do this before starting Raw mode, because it may change things that the 1657 * writing end of the pipe doesn't like, e.g., in case stdin and stderr 1658 * are the same terminal: "cat | vim -". 1659 * Using autocommands here may cause trouble... 1660 */ 1661 if (edit_type == EDIT_STDIN && !recoverymode) 1662 { 1663 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1664 /* When getting the ATTENTION prompt here, use a dialog */ 1665 swap_exists_action = SEA_DIALOG; 1666 #endif 1667 no_wait_return = TRUE; 1668 i = msg_didany; 1669 set_buflisted(TRUE); 1670 (void)open_buffer(TRUE, NULL); /* create memfile and read file */ 1671 no_wait_return = FALSE; 1672 msg_didany = i; 1673 TIME_MSG("reading stdin"); 1674 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1675 check_swap_exists_action(); 1676 #endif 1677 #if !(defined(AMIGA) || defined(MACOS)) 1678 /* 1679 * Close stdin and dup it from stderr. Required for GPM to work 1680 * properly, and for running external commands. 1681 * Is there any other system that cannot do this? 1682 */ 1683 close(0); 1684 dup(2); 1685 #endif 1686 } 1687 1688 #if defined(UNIX) || defined(VMS) 1689 /* When switching screens and something caused a message from a vimrc 1690 * script, need to output an extra newline on exit. */ 1691 if ((did_emsg || msg_didout) && *T_TI != NUL) 1692 newline_on_exit = TRUE; 1693 #endif 1694 1695 /* 1696 * When done something that is not allowed or error message call 1697 * wait_return. This must be done before starttermcap(), because it may 1698 * switch to another screen. It must be done after settmode(TMODE_RAW), 1699 * because we want to react on a single key stroke. 1700 * Call settmode and starttermcap here, so the T_KS and T_TI may be 1701 * defined by termcapinit and redifined in .exrc. 1702 */ 1703 settmode(TMODE_RAW); 1704 TIME_MSG("setting raw mode"); 1705 1706 if (need_wait_return || msg_didany) 1707 { 1708 wait_return(TRUE); 1709 TIME_MSG("waiting for return"); 1710 } 1711 1712 starttermcap(); /* start termcap if not done by wait_return() */ 1713 TIME_MSG("start termcap"); 1714 1715 #ifdef FEAT_MOUSE 1716 setmouse(); /* may start using the mouse */ 1717 #endif 1718 if (scroll_region) 1719 scroll_region_reset(); /* In case Rows changed */ 1720 1721 scroll_start(); 1722 1723 /* 1724 * Don't clear the screen when starting in Ex mode, unless using the GUI. 1725 */ 1726 if (exmode_active 1727 #ifdef FEAT_GUI 1728 && !gui.in_use 1729 #endif 1730 ) 1731 must_redraw = CLEAR; 1732 else 1733 { 1734 screenclear(); /* clear screen */ 1735 TIME_MSG("clearing screen"); 1736 } 1737 1738 #ifdef FEAT_CRYPT 1739 if (ask_for_key) 1740 { 1741 (void)get_crypt_key(TRUE, TRUE); 1742 TIME_MSG("getting crypt key"); 1743 } 1744 #endif 1745 1746 no_wait_return = TRUE; 1747 1748 #ifdef FEAT_WINDOWS 1749 /* 1750 * Create the number of windows that was requested. 1751 */ 1752 if (window_count == -1) /* was not set */ 1753 window_count = 1; 1754 if (window_count == 0) 1755 window_count = GARGCOUNT; 1756 if (window_count > 1) 1757 { 1758 /* Don't change the windows if there was a command in .vimrc that 1759 * already split some windows */ 1760 if (vert_windows == MAYBE) 1761 vert_windows = FALSE; 1762 if (firstwin->w_next == NULL) 1763 { 1764 window_count = make_windows(window_count, vert_windows); 1765 TIME_MSG("making windows"); 1766 } 1767 else 1768 window_count = win_count(); 1769 } 1770 else 1771 window_count = 1; 1772 #endif 1773 1774 if (recoverymode) /* do recover */ 1775 { 1776 msg_scroll = TRUE; /* scroll message up */ 1777 ml_recover(); 1778 if (curbuf->b_ml.ml_mfp == NULL) /* failed */ 1779 getout(1); 1780 do_modelines(FALSE); /* do modelines */ 1781 } 1782 else 1783 { 1784 /* 1785 * Open a buffer for windows that don't have one yet. 1786 * Commands in the .vimrc might have loaded a file or split the window. 1787 * Watch out for autocommands that delete a window. 1788 */ 1789 #ifdef FEAT_AUTOCMD 1790 /* 1791 * Don't execute Win/Buf Enter/Leave autocommands here 1792 */ 1793 ++autocmd_no_enter; 1794 ++autocmd_no_leave; 1795 #endif 1796 #ifdef FEAT_WINDOWS 1797 for (curwin = firstwin; curwin != NULL; curwin = W_NEXT(curwin)) 1798 #endif 1799 { 1800 curbuf = curwin->w_buffer; 1801 if (curbuf->b_ml.ml_mfp == NULL) 1802 { 1803 #ifdef FEAT_FOLDING 1804 /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */ 1805 if (p_fdls >= 0) 1806 curwin->w_p_fdl = p_fdls; 1807 #endif 1808 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1809 /* When getting the ATTENTION prompt here, use a dialog */ 1810 swap_exists_action = SEA_DIALOG; 1811 #endif 1812 set_buflisted(TRUE); 1813 (void)open_buffer(FALSE, NULL); /* create memfile, read file */ 1814 1815 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1816 check_swap_exists_action(); 1817 #endif 1818 #ifdef FEAT_AUTOCMD 1819 curwin = firstwin; /* start again */ 1820 #endif 1821 } 1822 #ifdef FEAT_WINDOWS 1823 ui_breakcheck(); 1824 if (got_int) 1825 { 1826 (void)vgetc(); /* only break the file loading, not the rest */ 1827 break; 1828 } 1829 #endif 1830 } 1831 #ifdef FEAT_AUTOCMD 1832 --autocmd_no_enter; 1833 --autocmd_no_leave; 1834 #endif 1835 #ifdef FEAT_WINDOWS 1836 curwin = firstwin; 1837 curbuf = curwin->w_buffer; 1838 #endif 1839 } 1840 TIME_MSG("opening buffers"); 1841 1842 /* Ex starts at last line of the file */ 1843 if (exmode_active) 1844 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 1845 1846 #ifdef FEAT_AUTOCMD 1847 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); 1848 TIME_MSG("BufEnter autocommands"); 1849 #endif 1850 setpcmark(); 1851 1852 #ifdef FEAT_QUICKFIX 1853 /* 1854 * When started with "-q errorfile" jump to first error now. 1855 */ 1856 if (edit_type == EDIT_QF) 1857 { 1858 qf_jump(0, 0, FALSE); 1859 TIME_MSG("jump to first error"); 1860 } 1861 #endif 1862 1863 #ifdef FEAT_WINDOWS 1864 /* 1865 * If opened more than one window, start editing files in the other 1866 * windows. Make_windows() has already opened the windows. 1867 */ 1868 # ifdef FEAT_AUTOCMD 1869 /* 1870 * Don't execute Win/Buf Enter/Leave autocommands here 1871 */ 1872 ++autocmd_no_enter; 1873 ++autocmd_no_leave; 1874 # endif 1875 arg_idx = 1; 1876 for (i = 1; i < window_count; ++i) 1877 { 1878 if (curwin->w_next == NULL) /* just checking */ 1879 break; 1880 win_enter(curwin->w_next, FALSE); 1881 1882 /* Only open the file if there is no file in this window yet (that can 1883 * happen when .vimrc contains ":sall") */ 1884 if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL) 1885 { 1886 curwin->w_arg_idx = arg_idx; 1887 /* edit file from arg list, if there is one */ 1888 (void)do_ecmd(0, arg_idx < GARGCOUNT 1889 ? alist_name(&GARGLIST[arg_idx]) : NULL, 1890 NULL, NULL, ECMD_LASTL, ECMD_HIDE); 1891 if (arg_idx == GARGCOUNT - 1) 1892 arg_had_last = TRUE; 1893 ++arg_idx; 1894 } 1895 ui_breakcheck(); 1896 if (got_int) 1897 { 1898 (void)vgetc(); /* only break the file loading, not the rest */ 1899 break; 1900 } 1901 } 1902 # ifdef FEAT_AUTOCMD 1903 --autocmd_no_enter; 1904 # endif 1905 win_enter(firstwin, FALSE); /* back to first window */ 1906 # ifdef FEAT_AUTOCMD 1907 --autocmd_no_leave; 1908 # endif 1909 TIME_MSG("editing files in windows"); 1910 if (window_count > 1) 1911 win_equal(curwin, FALSE, 'b'); /* adjust heights */ 1912 #endif /* FEAT_WINDOWS */ 1913 1914 #ifdef FEAT_DIFF 1915 if (diff_mode) 1916 { 1917 win_T *wp; 1918 1919 /* set options in each window for "vimdiff". */ 1920 for (wp = firstwin; wp != NULL; wp = wp->w_next) 1921 diff_win_options(wp, TRUE); 1922 } 1923 #endif 1924 1925 /* 1926 * Shorten any of the filenames, but only when absolute. 1927 */ 1928 shorten_fnames(FALSE); 1929 1930 /* 1931 * Need to jump to the tag before executing the '-c command'. 1932 * Makes "vim -c '/return' -t main" work. 1933 */ 1934 if (tagname != NULL) 1935 { 1936 STRCPY(IObuff, "ta "); 1937 1938 STRNCAT(IObuff, tagname, IOSIZE - 4); 1939 IObuff[IOSIZE - 1] = NUL; 1940 do_cmdline_cmd(IObuff); 1941 TIME_MSG("jumping to tag"); 1942 } 1943 1944 if (n_commands > 0) 1945 { 1946 /* 1947 * We start commands on line 0, make "vim +/pat file" match a 1948 * pattern on line 1. 1949 */ 1950 msg_scroll = TRUE; 1951 if (tagname == NULL) 1952 curwin->w_cursor.lnum = 0; 1953 sourcing_name = (char_u *)"command line"; 1954 #ifdef FEAT_EVAL 1955 current_SID = SID_CARG; 1956 #endif 1957 for (i = 0; i < n_commands; ++i) 1958 do_cmdline_cmd(commands[i]); 1959 sourcing_name = NULL; 1960 #ifdef FEAT_EVAL 1961 current_SID = 0; 1962 #endif 1963 if (curwin->w_cursor.lnum == 0) 1964 curwin->w_cursor.lnum = 1; 1965 1966 if (!exmode_active) 1967 msg_scroll = FALSE; 1968 1969 #ifdef FEAT_QUICKFIX 1970 /* When started with "-q errorfile" jump to first error again. */ 1971 if (edit_type == EDIT_QF) 1972 qf_jump(0, 0, FALSE); 1973 #endif 1974 TIME_MSG("executing command arguments"); 1975 } 1976 1977 RedrawingDisabled = 0; 1978 redraw_all_later(NOT_VALID); 1979 no_wait_return = FALSE; 1980 starting = 0; 1981 1982 /* start in insert mode */ 1983 if (p_im) 1984 need_start_insertmode = TRUE; 1985 1986 #ifdef FEAT_AUTOCMD 1987 apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf); 1988 TIME_MSG("VimEnter autocommands"); 1989 #endif 1990 1991 #if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND) 1992 /* When a startup script or session file setup for diff'ing and 1993 * scrollbind, sync the scrollbind now. */ 1994 if (curwin->w_p_diff && curwin->w_p_scb) 1995 { 1996 update_topline(); 1997 check_scrollbind((linenr_T)0, 0L); 1998 TIME_MSG("diff scrollbinding"); 1999 } 2000 #endif 2001 2002 #if defined(WIN3264) && !defined(FEAT_GUI_W32) 2003 mch_set_winsize_now(); /* Allow winsize changes from now on */ 2004 #endif 2005 2006 /* If ":startinsert" command used, stuff a dummy command to be able to 2007 * call normal_cmd(), which will then start Insert mode. */ 2008 if (restart_edit != 0) 2009 stuffcharReadbuff(K_IGNORE); 2010 2011 #ifdef FEAT_NETBEANS_INTG 2012 if (usingNetbeans) 2013 /* Tell the client that it can start sending commands. */ 2014 netbeans_startup_done(); 2015 #endif 2016 2017 TIME_MSG("before starting main loop"); 2018 2019 /* 2020 * Call the main command loop. This never returns. 2021 */ 2022 main_loop(FALSE); 2023 2024 return 0; 2025 } 2026 #endif /* PROTO */ 2027 2028 /* 2029 * Main loop: Execute Normal mode commands until exiting Vim. 2030 * Also used to handle commands in the command-line window, until the window 2031 * is closed. 2032 */ 2033 void 2034 main_loop(cmdwin) 2035 int cmdwin; /* TRUE when working in the command-line window */ 2036 { 2037 oparg_T oa; /* operator arguments */ 2038 2039 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD) 2040 /* Setup to catch a terminating error from the X server. Just ignore 2041 * it, restore the state and continue. This might not always work 2042 * properly, but at least we don't exit unexpectedly when the X server 2043 * exists while Vim is running in a console. */ 2044 if (!cmdwin && SETJMP(x_jump_env)) 2045 { 2046 State = NORMAL; 2047 # ifdef FEAT_VISUAL 2048 VIsual_active = FALSE; 2049 # endif 2050 got_int = TRUE; 2051 need_wait_return = FALSE; 2052 global_busy = FALSE; 2053 exmode_active = 0; 2054 skip_redraw = FALSE; 2055 RedrawingDisabled = 0; 2056 no_wait_return = 0; 2057 # ifdef FEAT_EVAL 2058 emsg_skip = 0; 2059 # endif 2060 emsg_off = 0; 2061 # ifdef FEAT_MOUSE 2062 setmouse(); 2063 # endif 2064 settmode(TMODE_RAW); 2065 starttermcap(); 2066 scroll_start(); 2067 redraw_later_clear(); 2068 } 2069 #endif 2070 2071 clear_oparg(&oa); 2072 while (!cmdwin 2073 #ifdef FEAT_CMDWIN 2074 || cmdwin_result == 0 2075 #endif 2076 ) 2077 { 2078 if (stuff_empty()) 2079 { 2080 did_check_timestamps = FALSE; 2081 if (need_check_timestamps) 2082 check_timestamps(FALSE); 2083 if (need_wait_return) /* if wait_return still needed ... */ 2084 wait_return(FALSE); /* ... call it now */ 2085 if (need_start_insertmode && goto_im() 2086 #ifdef FEAT_VISUAL 2087 && !VIsual_active 2088 #endif 2089 ) 2090 { 2091 need_start_insertmode = FALSE; 2092 stuffReadbuff((char_u *)"i"); /* start insert mode next */ 2093 /* skip the fileinfo message now, because it would be shown 2094 * after insert mode finishes! */ 2095 need_fileinfo = FALSE; 2096 } 2097 } 2098 if (got_int && !global_busy) 2099 { 2100 if (!quit_more) 2101 (void)vgetc(); /* flush all buffers */ 2102 got_int = FALSE; 2103 } 2104 if (!exmode_active) 2105 msg_scroll = FALSE; 2106 quit_more = FALSE; 2107 2108 /* 2109 * If skip redraw is set (for ":" in wait_return()), don't redraw now. 2110 * If there is nothing in the stuff_buffer or do_redraw is TRUE, 2111 * update cursor and redraw. 2112 */ 2113 if (skip_redraw || exmode_active) 2114 skip_redraw = FALSE; 2115 else if (do_redraw || stuff_empty()) 2116 { 2117 #if defined(FEAT_FOLDING) && defined(FEAT_VISUAL) 2118 /* Include a closed fold completely in the Visual area. */ 2119 foldAdjustVisual(); 2120 #endif 2121 #ifdef FEAT_FOLDING 2122 /* 2123 * When 'foldclose' is set, apply 'foldlevel' to folds that don't 2124 * contain the cursor. 2125 * When 'foldopen' is "all", open the fold(s) under the cursor. 2126 * This may mark the window for redrawing. 2127 */ 2128 if (hasAnyFolding(curwin) && !char_avail()) 2129 { 2130 foldCheckClose(); 2131 if (fdo_flags & FDO_ALL) 2132 foldOpenCursor(); 2133 } 2134 #endif 2135 2136 /* 2137 * Before redrawing, make sure w_topline is correct, and w_leftcol 2138 * if lines don't wrap, and w_skipcol if lines wrap. 2139 */ 2140 update_topline(); 2141 validate_cursor(); 2142 2143 #ifdef FEAT_VISUAL 2144 if (VIsual_active) 2145 update_curbuf(INVERTED);/* update inverted part */ 2146 else 2147 #endif 2148 if (must_redraw) 2149 update_screen(0); 2150 else if (redraw_cmdline || clear_cmdline) 2151 showmode(); 2152 #ifdef FEAT_WINDOWS 2153 redraw_statuslines(); 2154 #endif 2155 #ifdef FEAT_TITLE 2156 if (need_maketitle) 2157 maketitle(); 2158 #endif 2159 /* display message after redraw */ 2160 if (keep_msg != NULL) 2161 { 2162 char_u *p; 2163 2164 /* msg_attr_keep() will set keep_msg to NULL, must free the 2165 * string here. */ 2166 p = keep_msg; 2167 msg_attr(p, keep_msg_attr); 2168 vim_free(p); 2169 } 2170 if (need_fileinfo) /* show file info after redraw */ 2171 { 2172 fileinfo(FALSE, TRUE, FALSE); 2173 need_fileinfo = FALSE; 2174 } 2175 2176 emsg_on_display = FALSE; /* can delete error message now */ 2177 did_emsg = FALSE; 2178 msg_didany = FALSE; /* reset lines_left in msg_start() */ 2179 showruler(FALSE); 2180 2181 setcursor(); 2182 cursor_on(); 2183 2184 do_redraw = FALSE; 2185 } 2186 #ifdef FEAT_GUI 2187 if (need_mouse_correct) 2188 gui_mouse_correct(); 2189 #endif 2190 2191 /* 2192 * Update w_curswant if w_set_curswant has been set. 2193 * Postponed until here to avoid computing w_virtcol too often. 2194 */ 2195 update_curswant(); 2196 2197 /* 2198 * If we're invoked as ex, do a round of ex commands. 2199 * Otherwise, get and execute a normal mode command. 2200 */ 2201 if (exmode_active) 2202 do_exmode(exmode_active == EXMODE_VIM); 2203 else 2204 normal_cmd(&oa, TRUE); 2205 } 2206 } 2207 2208 2209 #if defined(USE_XSMP) || defined(FEAT_GUI_MSWIN) || defined(PROTO) 2210 /* 2211 * Exit, but leave behind swap files for modified buffers. 2212 */ 2213 void 2214 getout_preserve_modified(exitval) 2215 int exitval; 2216 { 2217 ml_close_notmod(); /* close all not-modified buffers */ 2218 ml_sync_all(FALSE, FALSE); /* preserve all swap files */ 2219 ml_close_all(FALSE); /* close all memfiles, without deleting */ 2220 getout(exitval); /* exit Vim properly */ 2221 } 2222 #endif 2223 2224 2225 /* Exit properly */ 2226 void 2227 getout(exitval) 2228 int exitval; 2229 { 2230 #ifdef FEAT_AUTOCMD 2231 buf_T *buf; 2232 win_T *wp; 2233 #endif 2234 2235 exiting = TRUE; 2236 2237 /* Position the cursor on the last screen line, below all the text */ 2238 #ifdef FEAT_GUI 2239 if (!gui.in_use) 2240 #endif 2241 windgoto((int)Rows - 1, 0); 2242 2243 #ifdef FEAT_GUI 2244 msg_didany = FALSE; 2245 #endif 2246 2247 #ifdef FEAT_AUTOCMD 2248 /* Trigger BufWinLeave for all windows, but only once per buffer. */ 2249 for (wp = firstwin; wp != NULL; ) 2250 { 2251 buf = wp->w_buffer; 2252 if (buf->b_changedtick != -1) 2253 { 2254 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, 2255 FALSE, buf); 2256 buf->b_changedtick = -1; /* note that we did it already */ 2257 wp = firstwin; /* restart, window may be closed */ 2258 } 2259 else 2260 wp = wp->w_next; 2261 } 2262 /* Trigger BufUnload for buffers that are loaded */ 2263 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 2264 if (buf->b_ml.ml_mfp != NULL) 2265 { 2266 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, 2267 FALSE, buf); 2268 if (!buf_valid(buf)) /* autocmd may delete the buffer */ 2269 break; 2270 } 2271 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); 2272 #endif 2273 2274 #ifdef FEAT_VIMINFO 2275 if (*p_viminfo != NUL) 2276 /* Write out the registers, history, marks etc, to the viminfo file */ 2277 write_viminfo(NULL, FALSE); 2278 #endif 2279 2280 #ifdef FEAT_AUTOCMD 2281 apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf); 2282 #endif 2283 2284 if (did_emsg 2285 #ifdef FEAT_GUI 2286 || (gui.in_use && msg_didany && p_verbose > 0) 2287 #endif 2288 ) 2289 { 2290 /* give the user a chance to read the (error) message */ 2291 no_wait_return = FALSE; 2292 wait_return(FALSE); 2293 } 2294 2295 #ifdef FEAT_AUTOCMD 2296 /* Position the cursor again, the autocommands may have moved it */ 2297 # ifdef FEAT_GUI 2298 if (!gui.in_use) 2299 # endif 2300 windgoto((int)Rows - 1, 0); 2301 #endif 2302 2303 #ifdef FEAT_MZSCHEME 2304 mzscheme_end(); 2305 #endif 2306 #ifdef FEAT_TCL 2307 tcl_end(); 2308 #endif 2309 #ifdef FEAT_RUBY 2310 ruby_end(); 2311 #endif 2312 #ifdef FEAT_PYTHON 2313 python_end(); 2314 #endif 2315 #ifdef FEAT_PERL 2316 perl_end(); 2317 #endif 2318 #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) 2319 iconv_end(); 2320 #endif 2321 #ifdef FEAT_NETBEANS_INTG 2322 netbeans_end(); 2323 #endif 2324 2325 mch_exit(exitval); 2326 } 2327 2328 /* 2329 * Get a (optional) count for a Vim argument. 2330 */ 2331 static int 2332 get_number_arg(p, idx, def) 2333 char_u *p; /* pointer to argument */ 2334 int *idx; /* index in argument, is incremented */ 2335 int def; /* default value */ 2336 { 2337 if (vim_isdigit(p[*idx])) 2338 { 2339 def = atoi((char *)&(p[*idx])); 2340 while (vim_isdigit(p[*idx])) 2341 *idx = *idx + 1; 2342 } 2343 return def; 2344 } 2345 2346 /* 2347 * Setup to start using the GUI. Exit with an error when not available. 2348 */ 2349 static void 2350 main_start_gui() 2351 { 2352 #ifdef FEAT_GUI 2353 gui.starting = TRUE; /* start GUI a bit later */ 2354 #else 2355 mch_errmsg(_(e_nogvim)); 2356 mch_errmsg("\n"); 2357 mch_exit(2); 2358 #endif 2359 } 2360 2361 /* 2362 * Get an evironment variable, and execute it as Ex commands. 2363 * Returns FAIL if the environment variable was not executed, OK otherwise. 2364 */ 2365 int 2366 process_env(env, is_viminit) 2367 char_u *env; 2368 int is_viminit; /* when TRUE, called for VIMINIT */ 2369 { 2370 char_u *initstr; 2371 char_u *save_sourcing_name; 2372 linenr_T save_sourcing_lnum; 2373 #ifdef FEAT_EVAL 2374 scid_T save_sid; 2375 #endif 2376 2377 if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) 2378 { 2379 if (is_viminit) 2380 vimrc_found(); 2381 save_sourcing_name = sourcing_name; 2382 save_sourcing_lnum = sourcing_lnum; 2383 sourcing_name = env; 2384 sourcing_lnum = 0; 2385 #ifdef FEAT_EVAL 2386 save_sid = current_SID; 2387 current_SID = SID_ENV; 2388 #endif 2389 do_cmdline_cmd(initstr); 2390 sourcing_name = save_sourcing_name; 2391 sourcing_lnum = save_sourcing_lnum; 2392 #ifdef FEAT_EVAL 2393 current_SID = save_sid;; 2394 #endif 2395 return OK; 2396 } 2397 return FAIL; 2398 } 2399 2400 #if defined(UNIX) || defined(VMS) 2401 /* 2402 * Return TRUE if we are certain the user owns the file "fname". 2403 * Used for ".vimrc" and ".exrc". 2404 * Use both stat() and lstat() for extra security. 2405 */ 2406 static int 2407 file_owned(fname) 2408 char *fname; 2409 { 2410 struct stat s; 2411 # ifdef UNIX 2412 uid_t uid = getuid(); 2413 # else /* VMS */ 2414 uid_t uid = ((getgid() << 16) | getuid()); 2415 # endif 2416 2417 return !(mch_stat(fname, &s) != 0 || s.st_uid != uid 2418 # ifdef HAVE_LSTAT 2419 || mch_lstat(fname, &s) != 0 || s.st_uid != uid 2420 # endif 2421 ); 2422 } 2423 #endif 2424 2425 /* 2426 * Give an error message main_errors["n"] and exit. 2427 */ 2428 static void 2429 mainerr(n, str) 2430 int n; /* one of the ME_ defines */ 2431 char_u *str; /* extra argument or NULL */ 2432 { 2433 #if defined(UNIX) || defined(__EMX__) || defined(VMS) 2434 reset_signals(); /* kill us with CTRL-C here, if you like */ 2435 #endif 2436 2437 mch_errmsg(longVersion); 2438 mch_errmsg("\n"); 2439 mch_errmsg(_(main_errors[n])); 2440 if (str != NULL) 2441 { 2442 mch_errmsg(": \""); 2443 mch_errmsg((char *)str); 2444 mch_errmsg("\""); 2445 } 2446 mch_errmsg(_("\nMore info with: \"vim -h\"\n")); 2447 2448 mch_exit(1); 2449 } 2450 2451 void 2452 mainerr_arg_missing(str) 2453 char_u *str; 2454 { 2455 mainerr(ME_ARG_MISSING, str); 2456 } 2457 2458 /* 2459 * print a message with three spaces prepended and '\n' appended. 2460 */ 2461 static void 2462 main_msg(s) 2463 char *s; 2464 { 2465 mch_msg(" "); 2466 mch_msg(s); 2467 mch_msg("\n"); 2468 } 2469 2470 /* 2471 * Print messages for "vim -h" or "vim --help" and exit. 2472 */ 2473 static void 2474 usage() 2475 { 2476 int i; 2477 static char *(use[]) = 2478 { 2479 N_("[file ..] edit specified file(s)"), 2480 N_("- read text from stdin"), 2481 N_("-t tag edit file where tag is defined"), 2482 #ifdef FEAT_QUICKFIX 2483 N_("-q [errorfile] edit file with first error") 2484 #endif 2485 }; 2486 2487 #if defined(UNIX) || defined(__EMX__) || defined(VMS) 2488 reset_signals(); /* kill us with CTRL-C here, if you like */ 2489 #endif 2490 2491 mch_msg(longVersion); 2492 mch_msg(_("\n\nusage:")); 2493 for (i = 0; ; ++i) 2494 { 2495 mch_msg(_(" vim [arguments] ")); 2496 mch_msg(_(use[i])); 2497 if (i == (sizeof(use) / sizeof(char_u *)) - 1) 2498 break; 2499 mch_msg(_("\n or:")); 2500 } 2501 #ifdef VMS 2502 mch_msg(_("where case is ignored prepend / to make flag upper case")); 2503 #endif 2504 2505 mch_msg(_("\n\nArguments:\n")); 2506 main_msg(_("--\t\t\tOnly file names after this")); 2507 #if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) 2508 main_msg(_("--literal\t\tDon't expand wildcards")); 2509 #endif 2510 #ifdef FEAT_OLE 2511 main_msg(_("-register\t\tRegister this gvim for OLE")); 2512 main_msg(_("-unregister\t\tUnregister gvim for OLE")); 2513 #endif 2514 #ifdef FEAT_GUI 2515 main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")")); 2516 main_msg(_("-f or --nofork\tForeground: Don't fork when starting GUI")); 2517 #endif 2518 main_msg(_("-v\t\t\tVi mode (like \"vi\")")); 2519 main_msg(_("-e\t\t\tEx mode (like \"ex\")")); 2520 main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")")); 2521 #ifdef FEAT_DIFF 2522 main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")")); 2523 #endif 2524 main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)")); 2525 main_msg(_("-R\t\t\tReadonly mode (like \"view\")")); 2526 main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")")); 2527 main_msg(_("-m\t\t\tModifications (writing files) not allowed")); 2528 main_msg(_("-M\t\t\tModifications in text not allowed")); 2529 main_msg(_("-b\t\t\tBinary mode")); 2530 #ifdef FEAT_LISP 2531 main_msg(_("-l\t\t\tLisp mode")); 2532 #endif 2533 main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'")); 2534 main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'")); 2535 main_msg(_("-V[N]\t\tVerbose level")); 2536 main_msg(_("-D\t\t\tDebugging mode")); 2537 main_msg(_("-n\t\t\tNo swap file, use memory only")); 2538 main_msg(_("-r\t\t\tList swap files and exit")); 2539 main_msg(_("-r (with file name)\tRecover crashed session")); 2540 main_msg(_("-L\t\t\tSame as -r")); 2541 #ifdef AMIGA 2542 main_msg(_("-f\t\t\tDon't use newcli to open window")); 2543 main_msg(_("-dev <device>\t\tUse <device> for I/O")); 2544 #endif 2545 #ifdef FEAT_ARABIC 2546 main_msg(_("-A\t\t\tstart in Arabic mode")); 2547 #endif 2548 #ifdef FEAT_RIGHTLEFT 2549 main_msg(_("-H\t\t\tStart in Hebrew mode")); 2550 #endif 2551 #ifdef FEAT_FKMAP 2552 main_msg(_("-F\t\t\tStart in Farsi mode")); 2553 #endif 2554 main_msg(_("-T <terminal>\tSet terminal type to <terminal>")); 2555 main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc")); 2556 #ifdef FEAT_GUI 2557 main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc")); 2558 #endif 2559 main_msg(_("--noplugin\t\tDon't load plugin scripts")); 2560 main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)")); 2561 main_msg(_("-O[N]\t\tLike -o but split vertically")); 2562 main_msg(_("+\t\t\tStart at end of file")); 2563 main_msg(_("+<lnum>\t\tStart at line <lnum>")); 2564 #ifdef FEAT_PRECOMMANDS 2565 main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file")); 2566 #endif 2567 main_msg(_("-c <command>\t\tExecute <command> after loading the first file")); 2568 main_msg(_("-S <session>\t\tSource file <session> after loading the first file")); 2569 main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>")); 2570 main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>")); 2571 main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>")); 2572 #ifdef FEAT_CRYPT 2573 main_msg(_("-x\t\t\tEdit encrypted files")); 2574 #endif 2575 #if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11) 2576 # if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) 2577 main_msg(_("-display <display>\tConnect vim to this particular X-server")); 2578 # endif 2579 main_msg(_("-X\t\t\tDo not connect to X server")); 2580 #endif 2581 #ifdef FEAT_CLIENTSERVER 2582 main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible")); 2583 main_msg(_("--remote-silent <files> Same, don't complain if there is no server")); 2584 main_msg(_("--remote-wait <files> As --remote but wait for files to have been edited")); 2585 main_msg(_("--remote-wait-silent <files> Same, don't complain if there is no server")); 2586 main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit")); 2587 main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result")); 2588 main_msg(_("--serverlist\t\tList available Vim server names and exit")); 2589 main_msg(_("--servername <name>\tSend to/become the Vim server <name>")); 2590 #endif 2591 #ifdef FEAT_VIMINFO 2592 main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo")); 2593 #endif 2594 main_msg(_("-h or --help\tPrint Help (this message) and exit")); 2595 main_msg(_("--version\t\tPrint version information and exit")); 2596 2597 #ifdef FEAT_GUI_X11 2598 # ifdef FEAT_GUI_MOTIF 2599 mch_msg(_("\nArguments recognised by gvim (Motif version):\n")); 2600 # else 2601 # ifdef FEAT_GUI_ATHENA 2602 # ifdef FEAT_GUI_NEXTAW 2603 mch_msg(_("\nArguments recognised by gvim (neXtaw version):\n")); 2604 # else 2605 mch_msg(_("\nArguments recognised by gvim (Athena version):\n")); 2606 # endif 2607 # endif 2608 # endif 2609 main_msg(_("-display <display>\tRun vim on <display>")); 2610 main_msg(_("-iconic\t\tStart vim iconified")); 2611 # if 0 2612 main_msg(_("-name <name>\t\tUse resource as if vim was <name>")); 2613 mch_msg(_("\t\t\t (Unimplemented)\n")); 2614 # endif 2615 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)")); 2616 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)")); 2617 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)")); 2618 main_msg(_("-boldfont <font>\tUse <font> for bold text")); 2619 main_msg(_("-italicfont <font>\tUse <font> for italic text")); 2620 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)")); 2621 main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)")); 2622 main_msg(_("-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)")); 2623 # ifdef FEAT_GUI_ATHENA 2624 main_msg(_("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)")); 2625 # endif 2626 main_msg(_("-reverse\t\tUse reverse video (also: -rv)")); 2627 main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)")); 2628 main_msg(_("-xrm <resource>\tSet the specified resource")); 2629 #endif /* FEAT_GUI_X11 */ 2630 #if defined(FEAT_GUI) && defined(RISCOS) 2631 mch_msg(_("\nArguments recognised by gvim (RISC OS version):\n")); 2632 main_msg(_("--columns <number>\tInitial width of window in columns")); 2633 main_msg(_("--rows <number>\tInitial height of window in rows")); 2634 #endif 2635 #ifdef FEAT_GUI_GTK 2636 mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n")); 2637 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)")); 2638 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)")); 2639 main_msg(_("-reverse\t\tUse reverse video (also: -rv)")); 2640 main_msg(_("-display <display>\tRun vim on <display> (also: --display)")); 2641 # ifdef HAVE_GTK2 2642 main_msg(_("--role <role>\tSet a unique role to identify the main window")); 2643 # endif 2644 main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget")); 2645 #endif 2646 #ifdef FEAT_GUI_KDE 2647 mch_msg(_("\nArguments recognised by kvim (KDE version):\n")); 2648 main_msg(_("-black\t\tUse reverse video")); 2649 #if QT_VERSION>=300 2650 main_msg(_("-tip\t\t\tDisplay the tip dialog on startup")); 2651 main_msg(_("-notip\t\tDisable the tip dialog")); 2652 #endif 2653 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)")); 2654 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)")); 2655 main_msg(_("--display <display>\tRun vim on <display>")); 2656 #endif 2657 #ifdef FEAT_GUI_W32 2658 main_msg(_("-P <parent title>\tOpen Vim inside parent application")); 2659 #endif 2660 2661 #ifdef FEAT_GUI_GNOME 2662 /* Gnome gives extra messages for --help if we continue, but not for -h. */ 2663 if (gui.starting) 2664 mch_msg("\n"); 2665 else 2666 #endif 2667 mch_exit(0); 2668 } 2669 2670 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2671 /* 2672 * Check the result of the ATTENTION dialog: 2673 * When "Quit" selected, exit Vim. 2674 * When "Recover" selected, recover the file. 2675 */ 2676 static void 2677 check_swap_exists_action() 2678 { 2679 if (swap_exists_action == SEA_QUIT) 2680 getout(1); 2681 handle_swap_exists(NULL); 2682 } 2683 #endif 2684 2685 #if defined(STARTUPTIME) || defined(PROTO) 2686 static void time_diff __ARGS((struct timeval *then, struct timeval *now)); 2687 2688 static struct timeval prev_timeval; 2689 2690 /* 2691 * Save the previous time before doing something that could nest. 2692 * set "*tv_rel" to the time elapsed so far. 2693 */ 2694 void 2695 time_push(tv_rel, tv_start) 2696 void *tv_rel, *tv_start; 2697 { 2698 *((struct timeval *)tv_rel) = prev_timeval; 2699 gettimeofday(&prev_timeval, NULL); 2700 ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec 2701 - ((struct timeval *)tv_rel)->tv_usec; 2702 ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec 2703 - ((struct timeval *)tv_rel)->tv_sec; 2704 if (((struct timeval *)tv_rel)->tv_usec < 0) 2705 { 2706 ((struct timeval *)tv_rel)->tv_usec += 1000000; 2707 --((struct timeval *)tv_rel)->tv_sec; 2708 } 2709 *(struct timeval *)tv_start = prev_timeval; 2710 } 2711 2712 /* 2713 * Compute the previous time after doing something that could nest. 2714 * Subtract "*tp" from prev_timeval; 2715 * Note: The arguments are (void *) to avoid trouble with systems that don't 2716 * have struct timeval. 2717 */ 2718 void 2719 time_pop(tp) 2720 void *tp; /* actually (struct timeval *) */ 2721 { 2722 prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec; 2723 prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec; 2724 if (prev_timeval.tv_usec < 0) 2725 { 2726 prev_timeval.tv_usec += 1000000; 2727 --prev_timeval.tv_sec; 2728 } 2729 } 2730 2731 static void 2732 time_diff(then, now) 2733 struct timeval *then; 2734 struct timeval *now; 2735 { 2736 long usec; 2737 long msec; 2738 2739 usec = now->tv_usec - then->tv_usec; 2740 msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L, 2741 usec = usec % 1000L; 2742 fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L); 2743 } 2744 2745 void 2746 time_msg(msg, tv_start) 2747 char *msg; 2748 void *tv_start; /* only for do_source: start time; actually 2749 (struct timeval *) */ 2750 { 2751 static struct timeval start; 2752 struct timeval now; 2753 2754 if (time_fd != NULL) 2755 { 2756 if (strstr(msg, "STARTING") != NULL) 2757 { 2758 gettimeofday(&start, NULL); 2759 prev_timeval = start; 2760 fprintf(time_fd, "\n\ntimes in msec\n"); 2761 fprintf(time_fd, " clock self+sourced self: sourced script\n"); 2762 fprintf(time_fd, " clock elapsed: other lines\n\n"); 2763 } 2764 gettimeofday(&now, NULL); 2765 time_diff(&start, &now); 2766 if (((struct timeval *)tv_start) != NULL) 2767 { 2768 fprintf(time_fd, " "); 2769 time_diff(((struct timeval *)tv_start), &now); 2770 } 2771 fprintf(time_fd, " "); 2772 time_diff(&prev_timeval, &now); 2773 prev_timeval = now; 2774 fprintf(time_fd, ": %s\n", msg); 2775 } 2776 } 2777 2778 # ifdef WIN3264 2779 /* 2780 * Windows doesn't have gettimeofday(), although it does have struct timeval. 2781 */ 2782 int 2783 gettimeofday(struct timeval *tv, char *dummy) 2784 { 2785 long t = clock(); 2786 tv->tv_sec = t / CLOCKS_PER_SEC; 2787 tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC; 2788 return 0; 2789 } 2790 # endif 2791 2792 #endif 2793 2794 #if defined(FEAT_CLIENTSERVER) || defined(PROTO) 2795 2796 /* 2797 * Common code for the X command server and the Win32 command server. 2798 */ 2799 2800 static char_u *build_drop_cmd __ARGS((int filec, char **filev, int sendReply)); 2801 2802 static void 2803 cmdsrv_main(argc, argv, serverName_arg, serverStr) 2804 int *argc; 2805 char **argv; 2806 char_u *serverName_arg; 2807 char_u **serverStr; 2808 { 2809 char_u *res; 2810 int i; 2811 char_u *sname; 2812 int ret; 2813 int didone = FALSE; 2814 int exiterr = 0; 2815 char **newArgV = argv + 1; 2816 int newArgC = 1, 2817 Argc = *argc; 2818 int argtype; 2819 #define ARGTYPE_OTHER 0 2820 #define ARGTYPE_EDIT 1 2821 #define ARGTYPE_EDIT_WAIT 2 2822 #define ARGTYPE_SEND 3 2823 int silent = FALSE; 2824 # ifndef FEAT_X11 2825 HWND srv; 2826 # else 2827 Window srv; 2828 2829 setup_term_clip(); 2830 # endif 2831 2832 sname = serverMakeName(serverName_arg, argv[0]); 2833 if (sname == NULL) 2834 return; 2835 2836 /* 2837 * Execute the command server related arguments and remove them 2838 * from the argc/argv array; We may have to return into main() 2839 */ 2840 for (i = 1; i < Argc; i++) 2841 { 2842 res = NULL; 2843 if (STRCMP(argv[i], "--") == 0) /* end of options */ 2844 { 2845 for (; i < *argc; i++) 2846 { 2847 *newArgV++ = argv[i]; 2848 newArgC++; 2849 } 2850 break; 2851 } 2852 2853 if (STRICMP(argv[i], "--remote") == 0) 2854 argtype = ARGTYPE_EDIT; 2855 else if (STRICMP(argv[i], "--remote-silent") == 0) 2856 { 2857 argtype = ARGTYPE_EDIT; 2858 silent = TRUE; 2859 } 2860 else if (STRICMP(argv[i], "--remote-wait") == 0) 2861 argtype = ARGTYPE_EDIT_WAIT; 2862 else if (STRICMP(argv[i], "--remote-wait-silent") == 0) 2863 { 2864 argtype = ARGTYPE_EDIT_WAIT; 2865 silent = TRUE; 2866 } 2867 else if (STRICMP(argv[i], "--remote-send") == 0) 2868 argtype = ARGTYPE_SEND; 2869 else 2870 argtype = ARGTYPE_OTHER; 2871 if (argtype != ARGTYPE_OTHER) 2872 { 2873 if (i == *argc - 1) 2874 mainerr_arg_missing((char_u *)argv[i]); 2875 if (argtype == ARGTYPE_SEND) 2876 { 2877 *serverStr = (char_u *)argv[i + 1]; 2878 i++; 2879 } 2880 else 2881 { 2882 *serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1, 2883 argtype == ARGTYPE_EDIT_WAIT); 2884 if (*serverStr == NULL) 2885 { 2886 /* Probably out of memory, exit. */ 2887 didone = TRUE; 2888 exiterr = 1; 2889 break; 2890 } 2891 Argc = i; 2892 } 2893 # ifdef FEAT_X11 2894 if (xterm_dpy == NULL) 2895 { 2896 mch_errmsg(_("No display")); 2897 ret = -1; 2898 } 2899 else 2900 ret = serverSendToVim(xterm_dpy, sname, *serverStr, 2901 NULL, &srv, 0, 0, silent); 2902 # else 2903 /* Win32 always works? */ 2904 ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, silent); 2905 # endif 2906 if (ret < 0) 2907 { 2908 if (argtype == ARGTYPE_SEND) 2909 { 2910 /* Failed to send, abort. */ 2911 mch_errmsg(_(": Send failed.\n")); 2912 didone = TRUE; 2913 exiterr = 1; 2914 } 2915 else if (!silent) 2916 /* Let vim start normally. */ 2917 mch_errmsg(_(": Send failed. Trying to execute locally\n")); 2918 break; 2919 } 2920 2921 # ifdef FEAT_GUI_W32 2922 /* Guess that when the server name starts with "g" it's a GUI 2923 * server, which we can bring to the foreground here. 2924 * Foreground() in the server doesn't work very well. */ 2925 if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G') 2926 SetForegroundWindow(srv); 2927 # endif 2928 2929 /* 2930 * For --remote-wait: Wait until the server did edit each 2931 * file. Also detect that the server no longer runs. 2932 */ 2933 if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT) 2934 { 2935 int numFiles = *argc - i - 1; 2936 int j; 2937 char_u *done = alloc(numFiles); 2938 char_u *p; 2939 # ifdef FEAT_GUI_W32 2940 NOTIFYICONDATA ni; 2941 int count = 0; 2942 extern HWND message_window; 2943 # endif 2944 2945 if (numFiles > 0 && argv[i + 1][0] == '+') 2946 /* Skip "+cmd" argument, don't wait for it to be edited. */ 2947 --numFiles; 2948 2949 # ifdef FEAT_GUI_W32 2950 ni.cbSize = sizeof(ni); 2951 ni.hWnd = message_window; 2952 ni.uID = 0; 2953 ni.uFlags = NIF_ICON|NIF_TIP; 2954 ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM"); 2955 sprintf(ni.szTip, _("%d of %d edited"), count, numFiles); 2956 Shell_NotifyIcon(NIM_ADD, &ni); 2957 # endif 2958 2959 /* Wait for all files to unload in remote */ 2960 memset(done, 0, numFiles); 2961 while (memchr(done, 0, numFiles) != NULL) 2962 { 2963 # ifdef WIN32 2964 p = serverGetReply(srv, NULL, TRUE, TRUE); 2965 if (p == NULL) 2966 break; 2967 # else 2968 if (serverReadReply(xterm_dpy, srv, &p, TRUE) < 0) 2969 break; 2970 # endif 2971 j = atoi((char *)p); 2972 if (j >= 0 && j < numFiles) 2973 { 2974 # ifdef FEAT_GUI_W32 2975 ++count; 2976 sprintf(ni.szTip, _("%d of %d edited"), 2977 count, numFiles); 2978 Shell_NotifyIcon(NIM_MODIFY, &ni); 2979 # endif 2980 done[j] = 1; 2981 } 2982 } 2983 # ifdef FEAT_GUI_W32 2984 Shell_NotifyIcon(NIM_DELETE, &ni); 2985 # endif 2986 } 2987 } 2988 else if (STRICMP(argv[i], "--remote-expr") == 0) 2989 { 2990 if (i == *argc - 1) 2991 mainerr_arg_missing((char_u *)argv[i]); 2992 # ifdef WIN32 2993 /* Win32 always works? */ 2994 if (serverSendToVim(sname, (char_u *)argv[i + 1], 2995 &res, NULL, 1, FALSE) < 0) 2996 # else 2997 if (xterm_dpy == NULL) 2998 mch_errmsg(_("No display: Send expression failed.\n")); 2999 else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1], 3000 &res, NULL, 1, 1, FALSE) < 0) 3001 # endif 3002 { 3003 if (res != NULL && *res != NUL) 3004 { 3005 /* Output error from remote */ 3006 mch_errmsg((char *)res); 3007 vim_free(res); 3008 res = NULL; 3009 } 3010 mch_errmsg(_(": Send expression failed.\n")); 3011 } 3012 } 3013 else if (STRICMP(argv[i], "--serverlist") == 0) 3014 { 3015 # ifdef WIN32 3016 /* Win32 always works? */ 3017 res = serverGetVimNames(); 3018 # else 3019 if (xterm_dpy != NULL) 3020 res = serverGetVimNames(xterm_dpy); 3021 # endif 3022 if (called_emsg) 3023 mch_errmsg("\n"); 3024 } 3025 else if (STRICMP(argv[i], "--servername") == 0) 3026 { 3027 /* Alredy processed. Take it out of the command line */ 3028 i++; 3029 continue; 3030 } 3031 else 3032 { 3033 *newArgV++ = argv[i]; 3034 newArgC++; 3035 continue; 3036 } 3037 didone = TRUE; 3038 if (res != NULL && *res != NUL) 3039 { 3040 mch_msg((char *)res); 3041 if (res[STRLEN(res) - 1] != '\n') 3042 mch_msg("\n"); 3043 } 3044 vim_free(res); 3045 } 3046 3047 if (didone) 3048 { 3049 display_errors(); /* display any collected messages */ 3050 exit(exiterr); /* Mission accomplished - get out */ 3051 } 3052 3053 /* Return back into main() */ 3054 *argc = newArgC; 3055 vim_free(sname); 3056 } 3057 3058 /* 3059 * Build a ":drop" command to send to a Vim server. 3060 */ 3061 static char_u * 3062 build_drop_cmd(filec, filev, sendReply) 3063 int filec; 3064 char **filev; 3065 int sendReply; 3066 { 3067 garray_T ga; 3068 int i; 3069 char_u *inicmd = NULL; 3070 char_u *p; 3071 char_u cwd[MAXPATHL]; 3072 3073 if (filec > 0 && filev[0][0] == '+') 3074 { 3075 inicmd = (char_u *)filev[0] + 1; 3076 filev++; 3077 filec--; 3078 } 3079 /* Check if we have at least one argument. */ 3080 if (filec <= 0) 3081 mainerr_arg_missing((char_u *)filev[-1]); 3082 if (mch_dirname(cwd, MAXPATHL) != OK) 3083 return NULL; 3084 if ((p = vim_strsave_escaped_ext(cwd, PATH_ESC_CHARS, '\\', TRUE)) == NULL) 3085 return NULL; 3086 ga_init2(&ga, 1, 100); 3087 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd "); 3088 ga_concat(&ga, p); 3089 /* Call inputsave() so that a prompt for an encryption key works. */ 3090 ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|drop"); 3091 vim_free(p); 3092 for (i = 0; i < filec; i++) 3093 { 3094 /* On Unix the shell has already expanded the wildcards, don't want to 3095 * do it again in the Vim server. On MS-Windows only need to escape a 3096 * space. */ 3097 p = vim_strsave_escaped((char_u *)filev[i], 3098 #ifdef UNIX 3099 PATH_ESC_CHARS 3100 #else 3101 (char_u *)" " 3102 #endif 3103 ); 3104 if (p == NULL) 3105 { 3106 vim_free(ga.ga_data); 3107 return NULL; 3108 } 3109 ga_concat(&ga, (char_u *)" "); 3110 ga_concat(&ga, p); 3111 vim_free(p); 3112 } 3113 /* The :drop commands goes to Insert mode when 'insertmode' is set, use 3114 * CTRL-\ CTRL-N again. */ 3115 ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>"); 3116 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd -"); 3117 if (sendReply) 3118 ga_concat(&ga, (char_u *)"<CR>:call SetupRemoteReplies()"); 3119 ga_concat(&ga, (char_u *)"<CR>:"); 3120 if (inicmd != NULL) 3121 { 3122 /* Can't use <CR> after "inicmd", because an "startinsert" would cause 3123 * the following commands to be inserted as text. Use a "|", 3124 * hopefully "inicmd" does allow this... */ 3125 ga_concat(&ga, inicmd); 3126 ga_concat(&ga, (char_u *)"|"); 3127 } 3128 /* Bring the window to the foreground, goto Insert mode when 'im' set and 3129 * clear command line. */ 3130 ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|ec<CR>"); 3131 ga_append(&ga, NUL); 3132 return ga.ga_data; 3133 } 3134 3135 /* 3136 * Replace termcodes such as <CR> and insert as key presses if there is room. 3137 */ 3138 void 3139 server_to_input_buf(str) 3140 char_u *str; 3141 { 3142 char_u *ptr = NULL; 3143 char_u *cpo_save = p_cpo; 3144 3145 /* Set 'cpoptions' the way we want it. 3146 * B set - backslashes are *not* treated specially 3147 * k set - keycodes are *not* reverse-engineered 3148 * < unset - <Key> sequences *are* interpreted 3149 * The last parameter of replace_termcodes() is TRUE so that the <lt> 3150 * sequence is recognised - needed for a real backslash. 3151 */ 3152 p_cpo = (char_u *)"Bk"; 3153 str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE); 3154 p_cpo = cpo_save; 3155 3156 if (*ptr != NUL) /* trailing CTRL-V results in nothing */ 3157 { 3158 /* 3159 * Add the string to the input stream. 3160 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes. 3161 * 3162 * First clear typed characters from the typeahead buffer, there could 3163 * be half a mapping there. Then append to the existing string, so 3164 * that multiple commands from a client are concatenated. 3165 */ 3166 if (typebuf.tb_maplen < typebuf.tb_len) 3167 del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen); 3168 (void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE); 3169 3170 /* Let input_available() know we inserted text in the typeahead 3171 * buffer. */ 3172 received_from_client = TRUE; 3173 } 3174 vim_free((char_u *)ptr); 3175 } 3176 3177 /* 3178 * Evaluate an expression that the client sent to a string. 3179 * Handles disabling error messages and disables debugging, otherwise Vim 3180 * hangs, waiting for "cont" to be typed. 3181 */ 3182 char_u * 3183 eval_client_expr_to_string(expr) 3184 char_u *expr; 3185 { 3186 char_u *res; 3187 int save_dbl = debug_break_level; 3188 int save_ro = redir_off; 3189 3190 debug_break_level = -1; 3191 redir_off = 0; 3192 ++emsg_skip; 3193 3194 res = eval_to_string(expr, NULL); 3195 3196 debug_break_level = save_dbl; 3197 redir_off = save_ro; 3198 --emsg_skip; 3199 3200 return res; 3201 } 3202 3203 3204 /* 3205 * Make our basic server name: use the specified "arg" if given, otherwise use 3206 * the tail of the command "cmd" we were started with. 3207 * Return the name in allocated memory. This doesn't include a serial number. 3208 */ 3209 static char_u * 3210 serverMakeName(arg, cmd) 3211 char_u *arg; 3212 char *cmd; 3213 { 3214 char_u *p; 3215 3216 if (arg != NULL && *arg != NUL) 3217 p = vim_strsave_up(arg); 3218 else 3219 { 3220 p = vim_strsave_up(gettail((char_u *)cmd)); 3221 /* Remove .exe or .bat from the name. */ 3222 if (p != NULL && vim_strchr(p, '.') != NULL) 3223 *vim_strchr(p, '.') = NUL; 3224 } 3225 return p; 3226 } 3227 #endif /* FEAT_CLIENTSERVER */ 3228 3229 /* 3230 * When FEAT_FKMAP is defined, also compile the Farsi source code. 3231 */ 3232 #if defined(FEAT_FKMAP) || defined(PROTO) 3233 # include "farsi.c" 3234 #endif 3235 3236 /* 3237 * When FEAT_ARABIC is defined, also compile the Arabic source code. 3238 */ 3239 #if defined(FEAT_ARABIC) || defined(PROTO) 3240 # include "arabic.c" 3241 #endif 3242