www.pudn.com > vim53src.zip > main.c
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. */ #define EXTERN #include "vim.h" #ifdef SPAWNO # include/* special MSDOS swapping library */ #endif static void mainerr __ARGS((int, char_u *)); static void main_msg __ARGS((char *s)); static void usage __ARGS((void)); static int get_number_arg __ARGS((char_u *p, int *idx, int def)); /* * Type of error message. These must match with errors[] in mainerr(). */ #define ME_UNKNOWN_OPTION 0 #define ME_TOO_MANY_ARGS 1 #define ME_ARG_MISSING 2 #define ME_GARBAGE 3 #define ME_EXTRA_CMD 4 static void mainerr(n, str) int n; char_u *str; { static char *(errors[]) = { "Unknown option", "Too many edit arguments", "Argument missing after", "Garbage after option", "Too many \"+command\" or \"-c command\" arguments", }; #if defined(UNIX) || defined(__EMX__) reset_signals(); /* kill us with CTRL-C here, if you like */ #endif mch_errmsg(longVersion); mch_errmsg("\n"); mch_errmsg(errors[n]); if (str != NULL) { mch_errmsg(": \""); mch_errmsg((char *)str); mch_errmsg("\""); } mch_errmsg("\nMore info with: \"vim -h\"\n"); mch_windexit(1); } /* * print a message with three spaces prepended and '\n' appended. */ static void main_msg(s) char *s; { mch_msg(" "); mch_msg(s); mch_msg("\n"); } static void usage() { int i; static char_u *(use[]) = { (char_u *)"[file ..] edit specified file(s)", (char_u *)"- read from stdin", (char_u *)"-t tag edit file where tag is defined", #ifdef QUICKFIX (char_u *)"-q [errorfile] edit file with first error" #endif }; #if defined(UNIX) || defined(__EMX__) reset_signals(); /* kill us with CTRL-C here, if you like */ #endif mch_msg(longVersion); mch_msg("\nusage:"); for (i = 0; ; ++i) { mch_msg(" vim [options] "); mch_msg((char *)use[i]); if (i == (sizeof(use) / sizeof(char_u *)) - 1) break; mch_msg("\n or:"); } mch_msg("\n\nOptions:\n"); main_msg("--\t\t\tEnd of options"); #ifdef HAVE_OLE main_msg("-register\t\tRegister this gvim for OLE"); main_msg("-unregister\t\tUnregister gvim for OLE"); #endif #ifdef USE_GUI main_msg("-g\t\t\tRun using GUI (like \"gvim\")"); main_msg("-f\t\t\tForeground: Don't fork when starting GUI"); #endif main_msg("-v\t\t\tVi mode (like \"vi\")"); main_msg("-e\t\t\tEx mode (like \"ex\")"); main_msg("-s\t\t\tSilent (batch) mode (only for \"ex\")"); main_msg("-R\t\t\tReadonly mode (like \"view\")"); main_msg("-Z\t\t\tRestricted mode (like \"rvim\")"); main_msg("-b\t\t\tBinary mode"); #ifdef LISPINDENT main_msg("-l\t\t\tLisp mode"); #endif main_msg("-C\t\t\tCompatible with Vi: 'compatible'"); main_msg("-N\t\t\tNot fully Vi compatible: 'nocompatible'"); main_msg("-V[N]\t\tVerbose level"); main_msg("-n\t\t\tNo swap file, use memory only"); main_msg("-r\t\t\tList swap files and exit"); main_msg("-r (with file name)\tRecover crashed session"); main_msg("-L\t\t\tSame as -r"); #ifdef AMIGA main_msg("-f\t\t\tDon't use newcli to open window"); main_msg("-d \t\tUse for I/O"); #endif #ifdef RIGHTLEFT main_msg("-H\t\t\tstart in Hebrew mode"); #endif #ifdef FKMAP main_msg("-F\t\t\tstart in Farsi mode"); #endif main_msg("-T \tSet terminal type to "); main_msg("-o[N]\t\tOpen N windows (default: one for each file)"); main_msg("+\t\t\tStart at end of file"); main_msg("+ \t\tStart at line "); main_msg("-c \t\tExecute first"); main_msg("-s \tRead commands from script file "); main_msg("-w \tAppend commands to script file "); main_msg("-W \tWrite commands to script file "); main_msg("-u \t\tUse instead of any .vimrc"); #ifdef USE_GUI main_msg("-U \t\tUse instead of any .gvimrc"); #endif #ifdef VIMINFO main_msg("-i \t\tUse instead of .viminfo"); #endif main_msg("-h\t\t\tprint Help (this message) and exit"); main_msg("--version\t\tprint version information and exit"); #ifdef USE_GUI_X11 # ifdef USE_GUI_MOTIF mch_msg("\nOptions recognised by gvim (Motif version):\n"); # else # ifdef USE_GUI_ATHENA mch_msg("\nOptions recognised by gvim (Athena version):\n"); # endif /* USE_GUI_ATHENA */ # endif /* USE_GUI_MOTIF */ main_msg("-display \tRun vim on "); main_msg("-iconic\t\tStart vim iconified"); # if 0 main_msg("-name \t\tUse resource as if vim was "); mch_msg("\t\t\t (Unimplemented)\n"); # endif main_msg("-background \tUse for the background (also: -bg)"); main_msg("-foreground \tUse for normal text (also: -fg)"); main_msg("-font \t\tUse for normal text (also: -fn)"); main_msg("-boldfont \tUse for bold text"); main_msg("-italicfont \tUse for italic text"); main_msg("-geometry \tUse for initial geometry (also: -geom)"); main_msg("-borderwidth \tUse a border width of (also: -bw)"); main_msg("-scrollbarwidth \tUse a scrollbar width of (also: -sw)"); main_msg("-menuheight \tUse a menu bar height of (also: -mh)"); main_msg("-reverse\t\tUse reverse video (also: -rv)"); main_msg("+reverse\t\tDon't use reverse video (also: +rv)"); main_msg("-xrm \tSet the specified resource"); #endif /* USE_GUI_X11 */ mch_windexit(1); } #ifdef HAVE_LOCALE_H # include #endif /* Maximum number of commands from + or -c options */ #define MAX_ARG_CMDS 10 #ifndef PROTO /* don't want a prototype for main() */ int #ifdef VIMDLL _export #endif main(argc, argv) int argc; char **argv; { char_u *initstr; /* init string from environment */ char_u *term = NULL; /* specified terminal name */ char_u *fname = NULL; /* file name from command line */ char_u *tagname = NULL; /* tag from -t option */ char_u *use_vimrc = NULL; /* vimrc from -u option */ #ifdef QUICKFIX char_u *use_ef = NULL; /* 'errorfile' from -q option */ #endif int n_commands = 0; /* no. of commands from + or -c */ char_u *commands[MAX_ARG_CMDS]; /* commands from + or -c option */ int no_swap_file = FALSE; /* "-n" option used */ int c; int i; int bin_mode = FALSE; /* -b option used */ int window_count = 1; /* number of windows to use */ int arg_idx = 0; /* index for arg_files[] */ int had_minmin = FALSE; /* found "--" option */ int argv_idx; /* index in argv[n][] */ int want_full_screen = TRUE; int want_argument; /* option with argument */ #define EDIT_NONE 0 /* no edit type yet */ #define EDIT_FILE 1 /* file name argument[s] given, use arg_files[] */ #define EDIT_STDIN 2 /* read file from stdin */ #define EDIT_TAG 3 /* tag name argument given, use tagname */ #define EDIT_QF 4 /* start in quickfix mode */ int edit_type = EDIT_NONE; /* type of editing to do */ int stdout_isatty; /* is stdout a terminal? */ int input_isatty; /* is active input a terminal? */ OPARG oa; /* operator arguments */ #ifdef RISCOS /* Turn off all the horrible filename munging in UnixLib. */ __uname_control = __UNAME_NO_PROCESS; #endif #if defined(MSDOS) || defined(WIN32) || defined(OS2) /* * Default mappings for some often used keys. * Use the Windows (CUA) keybindings. */ static struct initmap { char_u *arg; int mode; } initmappings[] = { # ifdef USE_GUI {(char_u *)" H", NORMAL+VISUAL}, {(char_u *)" H",INSERT}, {(char_u *)" L$", NORMAL+VISUAL}, {(char_u *)" L $", INSERT}, /* paste, copy and cut */ {(char_u *)" \"*P", NORMAL}, {(char_u *)" \"-d\"*P", VISUAL}, {(char_u *)" *", INSERT+CMDLINE}, {(char_u *)" \"*y", VISUAL}, {(char_u *)" \"*d", VISUAL}, {(char_u *)" \"*d", VISUAL}, {(char_u *)" \"*d", VISUAL}, /* Missing: CTRL-C (can't be mapped) and CTRL-V (means something) */ # else {(char_u *)"\316\204 H", NORMAL+VISUAL}, /* CTRL-PageUp is "H" */ {(char_u *)"\316\204 \017H",INSERT}, /* CTRL-PageUp is "^OH"*/ {(char_u *)"\316v L$", NORMAL+VISUAL}, /* CTRL-PageDown is "L$" */ {(char_u *)"\316v \017L\017$", INSERT}, /* CTRL-PageDown ="^OL^O$"*/ {(char_u *)"\316w ", NORMAL+VISUAL}, {(char_u *)"\316w ", INSERT+CMDLINE}, {(char_u *)"\316u ", NORMAL+VISUAL}, {(char_u *)"\316u ", INSERT+CMDLINE}, /* paste, copy and cut */ # ifdef USE_CLIPBOARD {(char_u *)"\316\324 \"*P", NORMAL}, /* SHIFT-Insert is "*P */ {(char_u *)"\316\324 \"-d\"*P", VISUAL}, /* SHIFT-Insert is "-d"*P */ {(char_u *)"\316\324 \017\"*P", INSERT}, /* SHIFT-Insert is ^O"*P */ {(char_u *)"\316\325 \"*y", VISUAL}, /* CTRL-Insert is "*y */ {(char_u *)"\316\327 \"*d", VISUAL}, /* SHIFT-Del is "*d */ {(char_u *)"\316\330 \"*d", VISUAL}, /* CTRL-Del is "*d */ {(char_u *)"\030 \"-d", VISUAL}, /* CTRL-X is "-d */ # else {(char_u *)"\316\324 P", NORMAL}, /* SHIFT-Insert is P */ {(char_u *)"\316\324 d\"0P", VISUAL}, /* SHIFT-Insert is d"0P */ {(char_u *)"\316\324 \017P", INSERT}, /* SHIFT-Insert is ^OP */ {(char_u *)"\316\325 y", VISUAL}, /* CTRL-Insert is y */ {(char_u *)"\316\327 d", VISUAL}, /* SHIFT-Del is d */ {(char_u *)"\316\330 d", VISUAL}, /* CTRL-Del is d */ # endif # endif }; #endif #if defined(macintosh) /* * Default mappings for some often used keys. * Use the Standard MacOS binding. */ static struct initmap { char_u *arg; int mode; } initmappings[] = { /* paste, copy and cut */ {(char_u *)" \"*P", NORMAL}, {(char_u *)" \"-d\"*P", VISUAL}, {(char_u *)" *", INSERT+CMDLINE}, {(char_u *)" \"*y", VISUAL}, {(char_u *)" \"*d", VISUAL}, {(char_u *)" \"-d", VISUAL}, }; #endif #ifdef MEM_PROFILE atexit(vim_mem_profile_dump); #endif #ifdef __EMX__ _wildcard(&argc, &argv); #endif #ifdef HAVE_LOCALE_H setlocale(LC_ALL, ""); /* for ctype() and the like */ #endif #if defined(USE_GUI_WIN32) && defined(HAVE_OLE) /* Check for special OLE command line parameters */ if (argc == 2 && (argv[1][0] == '-' || argv[1][0] == '/')) { /* Register Vim as an OLE Automation server */ if (STRICMP(argv[1] + 1, "register") == 0) { RegisterMe(); mch_windexit(0); } /* Unregister Vim as an OLE Automation server */ if (STRICMP(argv[1] + 1, "unregister") == 0) { UnregisterMe(TRUE); mch_windexit(0); } /* Ignore an -embedding argument. It is only relevant if the * application wants to treat the case when it is started manually * differently from the case where it is started via automation (and * we don't). */ if (STRICMP(argv[1] + 1, "embedding") == 0) argc = 1; } { int bDoRestart = FALSE; InitOLE(&bDoRestart); /* automatically exit after registering */ if (bDoRestart) mch_windexit(0); } #endif #ifdef USE_GUI gui_prepare(&argc, argv); /* Prepare for possibly starting GUI sometime */ #endif #ifdef USE_CLIPBOARD clip_init(FALSE); /* Initialise clipboard stuff */ #endif /* * Check if we have an interactive window. * On the Amiga: If there is no window, we open one with a newcli command * (needed for :! to * work). mch_check_win() will also handle the -d * argument. */ stdout_isatty = (mch_check_win(argc, argv) != FAIL); /* * allocate the first window and buffer. Can't do anything without it */ if ((curwin = win_alloc(NULL)) == NULL || (curbuf = buflist_new(NULL, NULL, 1L, FALSE)) == NULL) mch_windexit(0); curwin->w_buffer = curbuf; curbuf->b_nwindows = 1; /* there is one window */ win_init(curwin); /* init current window */ init_yank(); /* init yank buffers */ /* * Allocate space for the generic buffers (needed for set_init_1()). */ if ((IObuff = alloc(IOSIZE)) == NULL || (NameBuff = alloc(MAXPATHL)) == NULL) mch_windexit(0); /* * Set the default values for the options. * First find out the home directory, needed to expand "~" in options. */ init_homedir(); /* find real value of $HOME */ set_init_1(); /* * If the executable name starts with "r" we disable shell commands. * If the next character is "g" we run the GUI version. * If the next characters are "view" we start in readonly mode. * If the next characters are "ex" we start in ex mode. */ initstr = gettail((char_u *)argv[0]); if (initstr[0] == 'r') { restricted = TRUE; ++initstr; } if (initstr[0] == 'g') { #ifdef USE_GUI gui.starting = TRUE; ++initstr; #else mch_errmsg((char *)e_nogvim); mch_windexit(2); #endif } if (STRNCMP(initstr, "view", 4) == 0) { readonlymode = TRUE; curbuf->b_p_ro = TRUE; p_uc = 10000; /* don't update very often */ } if (STRNCMP(initstr, "ex", 2) == 0) { exmode_active = TRUE; change_compatible(TRUE); /* set 'compatible' */ } /* * On some systems, when we compile with the GUI, we always use it. On Mac * there is no terminal version, and on Windows we can't figure out how to * fork one off with :gui. */ #ifdef ALWAYS_USE_GUI gui.starting = TRUE; #endif ++argv; --argc; #ifndef macintosh /* * Allocate arg_files[], big enough to hold all potential file name * arguments. */ arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * (argc + 1))); if (arg_files == NULL) mch_windexit(2); #else arg_files = NULL; #endif arg_file_count = 0; /* * Process the command line arguments. */ argv_idx = 1; /* active option letter is argv[0][argv_idx] */ while (argc > 0) { /* * "+" or "+{number}" or "+/{pat}" or "+{command}" argument. */ if (argv[0][0] == '+' && !had_minmin) { if (n_commands >= MAX_ARG_CMDS) mainerr(ME_EXTRA_CMD, NULL); argv_idx = -1; /* skip to next argument */ if (argv[0][1] == NUL) commands[n_commands++] = (char_u *)"$"; else commands[n_commands++] = (char_u *)&(argv[0][1]); } /* * Option argument. */ else if (argv[0][0] == '-' && !had_minmin) { want_argument = FALSE; c = argv[0][argv_idx++]; switch (c) { case NUL: /* "-" read from stdin */ if (edit_type != EDIT_NONE) mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); edit_type = EDIT_STDIN; read_cmd_fd = 2; /* read from stderr instead of stdin */ argv_idx = -1; /* skip to next argument */ break; case '-': /* "--" don't take any more options */ /* "--help" give help message */ /* "--version" give version message */ if (STRCMP(argv[0] + argv_idx, "help") == 0) usage(); if (STRCMP(argv[0] + argv_idx, "version") == 0) { Columns = 80; /* need to init Columns */ do_version((char_u *)""); mch_windexit(1); } if (argv[0][argv_idx]) mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]); had_minmin = TRUE; argv_idx = -1; /* skip to next argument */ break; case 'b': /* "-b" binary mode */ bin_mode = TRUE; /* postpone to after reading .exrc files */ break; case 'C': /* "-C" Compatible */ change_compatible(TRUE); break; case 'e': /* "-e" Ex mode */ exmode_active = TRUE; break; case 'f': /* "-f" GUI: run in foreground. Amiga: open window directly, not with newcli */ #ifdef USE_GUI gui.dofork = FALSE; /* don't fork() when starting GUI */ #endif break; case 'g': /* "-g" start GUI */ #ifdef USE_GUI gui.starting = TRUE; /* start GUI a bit later */ #else mch_errmsg((char *)e_nogvim); mch_windexit(2); #endif break; case 'F': /* "-F" start in Farsi mode: rl + fkmap set */ #ifdef FKMAP curwin->w_p_rl = p_fkmap = TRUE; #else mch_errmsg((char *)e_nofarsi); mch_windexit(2); #endif break; case 'h': /* "-h" give help message */ usage(); break; case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */ #ifdef RIGHTLEFT curwin->w_p_rl = p_hkmap = TRUE; #else mch_errmsg((char *)e_nohebrew); mch_windexit(2); #endif break; case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */ #ifdef LISPINDENT curbuf->b_p_lisp = TRUE; p_sm = TRUE; #endif break; case 'N': /* "-N" Nocompatible */ change_compatible(FALSE); break; case 'n': /* "-n" no swap file */ no_swap_file = TRUE; break; case 'o': /* "-o[N]" open N windows */ /* default is 0: open window for each file */ window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0); break; #ifdef QUICKFIX case 'q': /* "-q" QuickFix mode */ if (edit_type != EDIT_NONE) mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); edit_type = EDIT_QF; if (argv[0][argv_idx]) /* "-q{errorfile}" */ { use_ef = (char_u *)argv[0] + argv_idx; argv_idx = -1; } else if (argc > 1) /* "-q {errorfile}" */ want_argument = TRUE; break; #endif case 'R': /* "-R" readonly mode */ readonlymode = TRUE; curbuf->b_p_ro = TRUE; p_uc = 10000; /* don't update very often */ break; case 'r': /* "-r" recovery mode */ case 'L': /* "-L" recovery mode */ recoverymode = 1; break; case 's': if (exmode_active) /* "-s" silent (batch) mode */ silent_mode = TRUE; else /* "-s {scriptin}" read from script file */ want_argument = TRUE; break; case 't': /* "-t {tag}" or "-t{tag}" jump to tag */ if (edit_type != EDIT_NONE) mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); edit_type = EDIT_TAG; if (argv[0][argv_idx]) /* "-t{tag}" */ { tagname = (char_u *)argv[0] + argv_idx; argv_idx = -1; } else /* "-t {tag}" */ want_argument = TRUE; break; case 'V': /* "-V{N}" Verbose level */ /* default is 10: a little bit verbose */ p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10); break; case 'v': /* "-v" Vi-mode (as if called "vi") */ exmode_active = FALSE; break; case 'w': /* "-w{number}" set window height */ /* "-w {scriptout}" write to script */ if (isdigit(((char_u *)argv[0])[argv_idx])) { argv_idx = -1; break; /* not implemented, ignored */ } want_argument = TRUE; break; case 'x': /* "-x" use "crypt" for reading/writing files. */ /* TODO */ break; case 'Z': /* "-Z" restricted mode */ restricted = TRUE; break; case 'c': /* "-c {command}" execute command */ case 'd': /* "-d {device}" device (for Amiga) */ case 'i': /* "-i {viminfo}" use for viminfo */ case 'T': /* "-T {terminal}" terminal name */ case 'u': /* "-u {vimrc}" vim inits file */ case 'U': /* "-U {gvimrc}" gvim inits file */ case 'W': /* "-W {scriptout}" overwrite */ want_argument = TRUE; break; default: mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]); } /* * Handle options with argument. */ if (want_argument) { /* * Check for garbage immediately after the option letter. */ if (argv[0][argv_idx] != NUL) mainerr(ME_GARBAGE, (char_u *)argv[0]); --argc; if (argc < 1) mainerr(ME_ARG_MISSING, (char_u *)argv[0]); ++argv; argv_idx = -1; switch (c) { case 'c': /* "-c {command}" execute command */ if (n_commands >= MAX_ARG_CMDS) mainerr(ME_EXTRA_CMD, NULL); commands[n_commands++] = (char_u *)argv[0]; break; /* case 'd': This is handled in mch_check_win() */ #ifdef QUICKFIX case 'q': /* "-q {errorfile}" QuickFix mode */ use_ef = (char_u *)argv[0]; break; #endif case 'i': /* "-i {viminfo}" use for viminfo */ use_viminfo = (char_u *)argv[0]; break; case 's': /* "-s {scriptin}" read from script file */ if (scriptin[0] != NULL) { mch_errmsg("Attempt to open script file again: \""); mch_errmsg(argv[-1]); mch_errmsg(" "); mch_errmsg(argv[0]); mch_errmsg("\"\n"); mch_windexit(2); } if ((scriptin[0] = fopen(argv[0], READBIN)) == NULL) { mch_errmsg("Cannot open \""); mch_errmsg(argv[0]); mch_errmsg("\" for reading\n"); mch_windexit(2); } if (save_typebuf() == FAIL) mch_windexit(2); /* out of memory */ break; case 't': /* "-t {tag}" */ tagname = (char_u *)argv[0]; break; case 'T': /* "-T {terminal}" terminal name */ /* * The -T term option is always available and when * HAVE_TERMLIB is supported it overrides the environment * variable TERM. */ #ifdef USE_GUI if (term_is_gui((char_u *)argv[0])) gui.starting = TRUE; /* start GUI a bit later */ else #endif term = (char_u *)argv[0]; break; case 'u': /* "-u {vimrc}" vim inits file */ use_vimrc = (char_u *)argv[0]; break; case 'U': /* "-U {gvimrc}" gvim inits file */ use_gvimrc = (char_u *)argv[0]; break; case 'w': /* "-w {scriptout}" append to script file */ case 'W': /* "-W {scriptout}" overwrite script file */ if (scriptout != NULL) { mch_errmsg("Attempt to open script file again: \""); mch_errmsg(argv[-1]); mch_errmsg(" "); mch_errmsg(argv[0]); mch_errmsg("\"\n"); mch_windexit(2); } if ((scriptout = fopen(argv[0], c == 'w' ? APPENDBIN : WRITEBIN)) == NULL) { mch_errmsg("cannot open \""); mch_errmsg(argv[0]); mch_errmsg("\" for output\n"); mch_windexit(2); } break; } } } /* * File name argument. */ else { argv_idx = -1; /* skip to next argument */ if (edit_type != EDIT_NONE && edit_type != EDIT_FILE) mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]); edit_type = EDIT_FILE; arg_files[arg_file_count] = vim_strsave((char_u *)argv[0]); if (arg_files[arg_file_count] != NULL) ++arg_file_count; } /* * If there are no more letters after the current "-", go to next * argument. argv_idx is set to -1 when the current argument is to be * skipped. */ if (argv_idx <= 0 || argv[0][argv_idx] == NUL) { --argc; ++argv; argv_idx = 1; } } /* * May expand wildcards in file names. */ if (arg_file_count > 0) { #if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE) char_u **new_arg_files; int new_arg_file_count; if (expand_wildcards(arg_file_count, arg_files, &new_arg_file_count, &new_arg_files, EW_FILE|EW_NOTFOUND) == OK && new_arg_file_count != 0) { FreeWild(arg_file_count, arg_files); arg_file_count = new_arg_file_count; arg_files = new_arg_files; } #endif fname = arg_files[0]; } if (arg_file_count > 1) printf("%d files to edit\n", arg_file_count); #ifdef WIN32 else if (arg_file_count == 1) { /* * If there is one filename, fully qualified, we have very probably * been invoked from explorer, so change to the file's directory. */ if (fname[0] != NUL && fname[1] == ':' && fname[2] == '\\') { /* If the cd fails, it doesn't matter.. */ (void)vim_chdirfile(fname); } } #endif RedrawingDisabled = TRUE; /* * When listing swap file names, don't do cursor positioning et. al. */ if (recoverymode && fname == NULL) want_full_screen = FALSE; /* * When starting the GUI, don't need to check capabilities of terminal. */ #ifdef USE_GUI if (gui.starting) want_full_screen = FALSE; #endif /* * mch_windinit() sets up the terminal (window) for use. This must be * done after resetting full_screen, otherwise it may move the cursor * (MSDOS). * Note that we may use mch_windexit() before mch_windinit()! */ mch_windinit(); /* * Print a warning if stdout is not a terminal. * When starting in Ex mode and commands come from a file, set Silent mode. */ input_isatty = mch_input_isatty(); if (exmode_active) { if (!input_isatty) silent_mode = TRUE; } else if (want_full_screen && (!stdout_isatty || !input_isatty)) { if (!stdout_isatty) mch_errmsg("Vim: Warning: Output is not to a terminal\n"); if (!input_isatty) mch_errmsg("Vim: Warning: Input is not from a terminal\n"); ui_delay(2000L, TRUE); } if (want_full_screen) { termcapinit(term); /* set terminal name and get terminal capabilities (will set full_screen) */ screen_start(); /* don't know where cursor is now */ } screenclear(); /* clear screen (just inits screen structures, because starting is TRUE) */ /* * Set the default values for the options that use Rows and Columns. */ ui_get_winsize(); /* inits Rows and Columns */ set_init_2(); firstwin->w_height = Rows - 1; cmdline_row = Rows - 1; if (full_screen) msg_start(); /* in case a mapping or error message is printed */ msg_scroll = TRUE; no_wait_return = TRUE; #if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(macintosh) /* * Default mappings for some often used keys. * Need to put string in allocated memory, because do_map() will modify it. */ { char_u *cpo_save = p_cpo; p_cpo = (char_u *)""; /* Allow <> notation */ for (i = 0; i < sizeof(initmappings) / sizeof(struct initmap); ++i) { initstr = vim_strsave(initmappings[i].arg); if (initstr != NULL) { do_map(0, initstr, initmappings[i].mode, FALSE); vim_free(initstr); } } p_cpo = cpo_save; } #endif init_highlight(TRUE); /* set the default highlight groups */ #ifdef CURSOR_SHAPE parse_guicursor(); /* set cursor shapes from 'guicursor' */ #endif /* * If -u option given, use only the initializations from that file and * nothing else. */ if (use_vimrc != NULL) { if (STRCMP(use_vimrc, "NONE") == 0) { if (use_gvimrc == NULL) /* don't load gvimrc either */ use_gvimrc = use_vimrc; } else { if (do_source(use_vimrc, FALSE, FALSE) != OK) EMSG2("Cannot read from \"%s\"", use_vimrc); } } else if (!silent_mode) { /* * Get system wide defaults, if the file name is defined. */ #ifdef SYS_VIMRC_FILE (void)do_source((char_u *)SYS_VIMRC_FILE, TRUE, FALSE); #endif /* * Try to read initialization commands from the following places: * - environment variable VIMINIT * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise) * - second user vimrc file ($VIM/.vimrc for Dos) * - environment variable EXINIT * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise) * - second user exrc file ($VIM/.exrc for Dos) * The first that exists is used, the rest is ignored. */ if (process_env((char_u *)"VIMINIT") == OK) vimrc_found(); else { if (do_source((char_u *)USR_VIMRC_FILE, TRUE, TRUE) == FAIL #ifdef USR_VIMRC_FILE2 && do_source((char_u *)USR_VIMRC_FILE2, TRUE, TRUE) == FAIL #endif && process_env((char_u *)"EXINIT") == FAIL && do_source((char_u *)USR_EXRC_FILE, FALSE, FALSE) == FAIL) { #ifdef USR_EXRC_FILE2 (void)do_source((char_u *)USR_EXRC_FILE2, FALSE, FALSE); #endif } } /* * Read initialization commands from ".vimrc" or ".exrc" in current * directory. This is only done if the 'exrc' option is set. * Because of security reasons we disallow shell and write commands * now, except for unix if the file is owned by the user or 'secure' * option has been reset in environmet of global ".exrc" or ".vimrc". * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or * SYS_VIMRC_FILE. */ if (p_exrc) { #ifdef UNIX { struct stat s; /* if ".vimrc" file is not owned by user, set 'secure' mode */ if (stat(VIMRC_FILE, &s) || s.st_uid != getuid()) secure = p_secure; } #else secure = p_secure; #endif i = FAIL; if (fullpathcmp((char_u *)USR_VIMRC_FILE, (char_u *)VIMRC_FILE, FALSE) != FPC_SAME #ifdef USR_VIMRC_FILE2 && fullpathcmp((char_u *)USR_VIMRC_FILE2, (char_u *)VIMRC_FILE, FALSE) != FPC_SAME #endif #ifdef SYS_VIMRC_FILE && fullpathcmp((char_u *)SYS_VIMRC_FILE, (char_u *)VIMRC_FILE, FALSE) != FPC_SAME #endif ) i = do_source((char_u *)VIMRC_FILE, TRUE, TRUE); if (i == FAIL) { #ifdef UNIX struct stat s; /* if ".exrc" is not owned by user set 'secure' mode */ if (stat(EXRC_FILE, &s) || s.st_uid != getuid()) secure = p_secure; else secure = 0; #endif if ( fullpathcmp((char_u *)USR_EXRC_FILE, (char_u *)EXRC_FILE, FALSE) != FPC_SAME #ifdef USR_EXRC_FILE2 && fullpathcmp((char_u *)USR_EXRC_FILE2, (char_u *)EXRC_FILE, FALSE) != FPC_SAME #endif ) (void)do_source((char_u *)EXRC_FILE, FALSE, FALSE); } } if (secure == 2) need_wait_return = TRUE; secure = 0; } /* * Recovery mode without a file name: List swap files. * This uses the 'dir' option, therefore it must be after the * initializations. */ if (recoverymode && fname == NULL) { recover_names(NULL, TRUE, 0); mch_windexit(0); } /* * Set a few option defaults after reading .vimrc files: * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'. */ set_init_3(); /* * "-n" argument: Disable swap file by setting 'updatecount' to 0. * Note that this overrides anything from a vimrc file. */ if (no_swap_file) p_uc = 0; #ifdef FKMAP if (curwin->w_p_rl && p_altkeymap) { p_hkmap = FALSE; /* Reset the Hebrew keymap mode */ p_fkmap = TRUE; /* Set the Farsi keymap mode */ } #endif if (bin_mode) /* "-b" argument used */ { set_options_bin(curbuf->b_p_bin, 1); curbuf->b_p_bin = 1; /* binary file I/O */ } #ifdef USE_GUI if (gui.starting) gui_start(); /* will set full_screen to TRUE */ #endif #ifdef VIMINFO /* * Read in registers, history etc, but not marks, from the viminfo file */ if (*p_viminfo != NUL) read_viminfo(NULL, TRUE, FALSE, FALSE); #endif /* VIMINFO */ #ifdef SPAWNO /* special MSDOS swapping library */ init_SPAWNO("", SWAP_ANY); #endif #ifdef QUICKFIX /* * "-q errorfile": Load the error file now. * If the error file can't be read, exit before doing anything else. */ if (edit_type == EDIT_QF) { if (use_ef != NULL) set_string_option_direct((char_u *)"ef", -1, use_ef, TRUE); if (qf_init(p_ef, p_efm) < 0) { out_char('\n'); mch_windexit(3); } } #endif /* * Don't set the file name if there was a command in .vimrc that already * loaded the file */ if (curbuf->b_ffname == NULL) { (void)setfname(fname, NULL, TRUE); /* includes maketitle() */ ++arg_idx; /* used first argument name */ } if (window_count == 0) window_count = arg_file_count; if (window_count > 1) { /* Don't change the windows if there was a command in .vimrc that * already split some windows */ if (firstwin->w_next == NULL) window_count = make_windows(window_count); else window_count = win_count(); } else window_count = 1; /* * Start putting things on the screen. * Scroll screen down before drawing over it * Clear screen now, so file message will not be cleared. */ starting = FALSE; no_wait_return = FALSE; msg_scroll = FALSE; #ifdef USE_GUI /* * This seems to be required to make callbacks to be called now, instead * of after things have been put on the screen, which then may be deleted * when getting a resize callback. */ if (gui.in_use) gui_wait_for_chars(50L); #endif /* * When done something that is not allowed or error message call * wait_return. This must be done before starttermcap(), because it may * switch to another screen. It must be done after settmode(TMODE_RAW), * because we want to react on a single key stroke. * Call settmode and starttermcap here, so the T_KS and T_TI may be * defined by termcapinit and redifined in .exrc. */ settmode(TMODE_RAW); if (need_wait_return || msg_didany) wait_return(TRUE); starttermcap(); /* start termcap if not done by wait_return() */ #ifdef USE_MOUSE setmouse(); /* may start using the mouse */ #endif if (scroll_region) scroll_region_reset(); /* In case Rows changed */ scroll_start(); /* * Don't clear the screen when starting in Ex mode, unless using the GUI. */ if (exmode_active #ifdef USE_GUI && !gui.in_use #endif ) must_redraw = CLEAR; else screenclear(); /* clear screen */ no_wait_return = TRUE; if (recoverymode) /* do recover */ { msg_scroll = TRUE; /* scroll message up */ ml_recover(); msg_scroll = FALSE; if (curbuf->b_ml.ml_mfp == NULL) /* failed */ getout(1); do_modelines(); /* do modelines */ } else { /* * If "-" argument given: read file from stdin. * Need to stop Raw mode for terminal in case stdin and stderr are the * same terminal: "cat | vim -". */ if (edit_type == EDIT_STDIN) { stoptermcap(); settmode(TMODE_COOK); /* set to normal mode */ (void)open_buffer(TRUE); /* create memfile and read file */ if (!termcap_active) /* if readfile() didn't do it already */ { settmode(TMODE_RAW); /* set to raw mode */ starttermcap(); } } /* * Open a buffer for windows that don't have one yet. * Commands in the .vimrc might have loaded a file or split the window. * Watch out for autocommands that delete a window. */ #ifdef AUTOCMD /* * Don't execute Win/Buf Enter/Leave autocommands here */ ++autocmd_no_enter; ++autocmd_no_leave; #endif for (curwin = firstwin; curwin != NULL; curwin = curwin->w_next) { curbuf = curwin->w_buffer; if (curbuf->b_ml.ml_mfp == NULL) { (void)open_buffer(FALSE); /* create memfile and read file */ #ifdef AUTOCMD curwin = firstwin; /* start again */ #endif } ui_breakcheck(); if (got_int) { (void)vgetc(); /* only break the file loading, not the rest */ break; } } #ifdef AUTOCMD --autocmd_no_enter; --autocmd_no_leave; #endif curwin = firstwin; curbuf = curwin->w_buffer; } /* Ex starts at last line of the file */ if (exmode_active) curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; #ifdef AUTOCMD apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf); #endif setpcmark(); #ifdef QUICKFIX /* * When started with "-q errorfile" jump to first error now. */ if (edit_type == EDIT_QF) qf_jump(0, 0, FALSE); #endif /* * If opened more than one window, start editing files in the other * windows. Make_windows() has already opened the windows. */ #ifdef AUTOCMD /* * Don't execute Win/Buf Enter/Leave autocommands here */ ++autocmd_no_enter; ++autocmd_no_leave; #endif for (i = 1; i < window_count; ++i) { if (curwin->w_next == NULL) /* just checking */ break; win_enter(curwin->w_next, FALSE); /* Only open the file if there is no file in this window yet (that can * happen when .vimrc contains ":sall") */ if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL) { curwin->w_arg_idx = arg_idx; /* edit file from arg list, if there is one */ (void)do_ecmd(0, arg_idx < arg_file_count ? arg_files[arg_idx] : NULL, NULL, NULL, (linenr_t)0, ECMD_HIDE); if (arg_idx == arg_file_count - 1) arg_had_last = TRUE; ++arg_idx; } ui_breakcheck(); if (got_int) { (void)vgetc(); /* only break the file loading, not the rest */ break; } } #ifdef AUTOCMD --autocmd_no_enter; #endif win_enter(firstwin, FALSE); /* back to first window */ #ifdef AUTOCMD --autocmd_no_leave; #endif if (window_count > 1) win_equal(curwin, FALSE); /* adjust heights */ /* * If there are more file names in the argument list than windows, * put the rest of the names in the buffer list. */ while (arg_idx < arg_file_count) (void)buflist_add(arg_files[arg_idx++]); /* * Now shorten any of the filenames if possible */ shorten_fnames(); /* * Need to jump to the tag before executing the '-c command'. * Makes "vim -c '/return' -t main" work. */ if (tagname) { STRCPY(IObuff, "ta "); STRCAT(IObuff, tagname); do_cmdline(IObuff, NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE); } if (n_commands > 0) { /* * We start commands on line 0, make "vim +/pat file" match a * pattern on line 1. */ curwin->w_cursor.lnum = 0; sourcing_name = (char_u *)"command line"; for (i = 0; i < n_commands; ++i) do_cmdline(commands[i], NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE); sourcing_name = NULL; if (curwin->w_cursor.lnum == 0) curwin->w_cursor.lnum = 1; #ifdef QUICKFIX /* When started with "-q errorfile" jump to first again. */ if (edit_type == EDIT_QF) qf_jump(0, 0, FALSE); #endif } RedrawingDisabled = FALSE; redraw_later(NOT_VALID); no_wait_return = FALSE; /* start in insert mode */ if (p_im) need_start_insertmode = TRUE; #ifdef AUTOCMD apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf); #endif #if defined(WIN32) && !defined(USE_GUI_WIN32) mch_set_winsize_now(); /* Allow winsize changes from now on */ #endif /* * main command loop */ clear_oparg(&oa); for (;;) { if (stuff_empty()) { if (need_check_timestamps) check_timestamps(); if (need_wait_return) /* if wait_return still needed ... */ wait_return(FALSE); /* ... call it now */ if (need_start_insertmode && goto_im()) { need_start_insertmode = FALSE; stuffReadbuff((char_u *)"i"); /* start insert mode next */ /* skip the fileinfo message now, because it would be shown * after insert mode finishes! */ need_fileinfo = FALSE; } } dont_wait_return = FALSE; if (got_int && !global_busy) { (void)vgetc(); /* flush all buffers */ got_int = FALSE; } msg_scroll = FALSE; quit_more = FALSE; /* * If skip redraw is set (for ":" in wait_return()), don't redraw now. * If there is nothing in the stuff_buffer or do_redraw is TRUE, * update cursor and redraw. */ if (skip_redraw || exmode_active) skip_redraw = FALSE; else if (do_redraw || stuff_empty()) { /* * Before redrawing, make sure w_topline is correct, and w_leftcol * if lines don't wrap, and w_skipcol if lines wrap. */ update_topline(); validate_cursor(); if (VIsual_active) update_curbuf(INVERTED);/* update inverted part */ else if (must_redraw) update_screen(must_redraw); else if (redraw_cmdline || clear_cmdline) showmode(); redraw_statuslines(); /* display message after redraw */ if (keep_msg != NULL) msg_attr(keep_msg, keep_msg_attr); if (need_fileinfo) /* show file info after redraw */ { fileinfo(FALSE, TRUE, FALSE); need_fileinfo = FALSE; } emsg_on_display = FALSE; /* can delete error message now */ msg_didany = FALSE; /* reset lines_left in msg_start() */ do_redraw = FALSE; showruler(FALSE); setcursor(); cursor_on(); } #ifdef USE_GUI if (need_mouse_correct) gui_mouse_correct(); #endif /* * Update w_curswant if w_set_curswant has been set. * Postponed until here to avoid computing w_virtcol too often. */ update_curswant(); /* * If we're invoked as ex, do a round of ex commands. * Otherwise, get and execute a normal mode command. */ if (exmode_active) do_exmode(); else normal_cmd(&oa, TRUE); } /*NOTREACHED*/ #if !defined(MSDOS) || defined(DJGPP) return 0; /* Borland C++ gives a "not reached" error message here */ #endif } #endif /* PROTO */ /* * Get a (optional) count for a Vim argument. */ static int get_number_arg(p, idx, def) char_u *p; /* pointer to argument */ int *idx; /* index in argument, is incremented */ int def; /* default value */ { if (isdigit(p[*idx])) { def = atoi((char *)&(p[*idx])); while (isdigit(p[*idx])) *idx = *idx + 1; } return def; } /* * Get an evironment variable, and execute it as Ex commands. * Returns FAIL if the environment variable was not executed, OK otherwise. */ int process_env(env) char_u *env; { char_u *initstr; char_u *save_sourcing_name; if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) { save_sourcing_name = sourcing_name; sourcing_name = env; do_cmdline(initstr, NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE); sourcing_name = save_sourcing_name; return OK; } return FAIL; } void getout(r) int r; { exiting = TRUE; /* Position the cursor on the last screen line, below all the text */ #ifdef USE_GUI if (!gui.in_use) #endif windgoto((int)Rows - 1, 0); #ifdef AUTOCMD apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf); #endif #ifdef VIMINFO if (*p_viminfo != NUL) { /* Write out the registers, history, marks etc, to the viminfo file */ msg_didany = FALSE; write_viminfo(NULL, FALSE); if (msg_didany) /* make the user read the error message */ { no_wait_return = FALSE; wait_return(FALSE); } } #endif /* VIMINFO */ #ifdef AUTOCMD apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf); /* Position the cursor again, the autocommands may have moved it */ # ifdef USE_GUI if (!gui.in_use) # endif windgoto((int)Rows - 1, 0); #endif #ifdef HAVE_PERL_INTERP perl_end(); #endif mch_windexit(r); } /* * When FKMAP is defined, also compile the Farsi source code. */ #if defined(FKMAP) || defined(PROTO) # include "farsi.c" #endif