diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index 359058de6304a0be0e5ce27cf2cfebc88ffd3be6..264a06dc22d733d061e2b20e8d26c9429d05084c 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2005 Jul 23
+*todo.txt*      For Vim version 7.0aa.  Last change: 2005 Jul 24
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -58,9 +58,7 @@ Win32: Crash when pasting Simplified Chinese in utf-8. (rainux, 2005 June 20)
 
 PLANNED FOR VERSION 7.0:
 
--   REFACTORING: The main() function is very long.  Move parts to separate
-    functions, especially loops.  Ideas from Walter Briscoe (2003 Apr 3, 2004
-    Feb 9).
+-   REFACTORING:
     Improve the interface between the generic GUI code and the system-specific
     code.  Generic code handles text window with scrollbars, system-specific
     code menu, toolbar, etc.
diff --git a/src/main.c b/src/main.c
index 0e274adf5d90cf616f77e2312c4c79b72a285723..1beaca47f95bcc413794d28771d23c6dd45c6591 100644
--- a/src/main.c
+++ b/src/main.c
@@ -29,15 +29,71 @@
 # include <limits.h>
 #endif
 
+/* Maximum number of commands from + or -c arguments. */
+#define MAX_ARG_CMDS 10
+
 /* Struct for various parameters passed between main() and other functions. */
 typedef struct
 {
+    int		argc;
+    char	**argv;
+
+    int		evim_mode;		/* started as "evim" */
+    int		bin_mode;		/* -b argument used */
+    char_u	*use_vimrc;		/* vimrc from -u argument */
+
+    int		n_commands;		     /* no. of commands from + or -c */
+    char_u	*commands[MAX_ARG_CMDS];     /* commands from + or -c arg. */
+    char_u	cmds_tofree[MAX_ARG_CMDS];   /* commands that need free() */
+    int		n_pre_commands;		     /* no. of commands from --cmd */
+    char_u	*pre_commands[MAX_ARG_CMDS]; /* commands from --cmd argument */
+
+    int		edit_type;		/* type of editing to do */
+    char_u	*tagname;		/* tag from -t argument */
+#ifdef FEAT_QUICKFIX
+    char_u	*use_ef;		/* 'errorfile' from -q argument */
+#endif
+
+    int		want_full_screen;
+    int		stdout_isatty;		/* is stdout a terminal? */
+    char_u	*term;			/* specified terminal name */
+#ifdef FEAT_CRYPT
+    int		ask_for_key;		/* -x argument */
+#endif
+    int		no_swap_file;		/* "-n" argument used */
+#ifdef FEAT_EVAL
+    int		use_debug_break_level;
+#endif
+#ifdef FEAT_WINDOWS
+    int		window_count;		/* number of windows to use */
+    int		vert_windows;		/* "-O" used instead of "-o" */
+#endif
+
+#ifdef FEAT_CLIENTSERVER
     int		serverArg;		/* TRUE when argument for a server */
     char_u	*serverName_arg;	/* cmdline arg for server name */
-    int		evim_mode;		/* started as "evim" */
-    char_u	*use_vimrc;		/* vimrc from -u option */
+    char_u	*serverStr;		/* remote server command */
+    char_u	*serverStrEnc;		/* encoding of serverStr */
+    char_u	*servername;		/* allocated name for our server */
+#endif
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+    int		literal;		/* don't expand file names */
+#endif
+#ifdef MSWIN
+    int		full_path;		/* file name argument was full path */
+#endif
+#ifdef FEAT_DIFF
+    int		diff_mode;		/* start with 'diff' set */
+#endif
 } mparm_T;
 
+/* Values for edit_type. */
+#define EDIT_NONE   0	    /* no edit type yet */
+#define EDIT_FILE   1	    /* file name argument[s] given, use argument list */
+#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 */
+
 #if defined(UNIX) || defined(VMS)
 static int file_owned __ARGS((char *fname));
 #endif
@@ -45,14 +101,28 @@ 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));
-static void early_arg_scan __ARGS((int argc, char **argv, mparm_T *parmp));
-static void exe_pre_commands __ARGS((char_u **cmds, int cnt));
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+static void init_locale __ARGS((void));
+#endif
+static void parse_command_name __ARGS((mparm_T *parmp));
+static void early_arg_scan __ARGS((mparm_T *parmp));
+static void command_line_scan __ARGS((mparm_T *parmp));
+static void check_tty __ARGS((mparm_T *parmp));
+static void read_stdin __ARGS((void));
+static void create_windows __ARGS((mparm_T *parmp));
+#ifdef FEAT_WINDOWS
+static void edit_buffers __ARGS((mparm_T *parmp));
+#endif
+static void exe_pre_commands __ARGS((mparm_T *parmp));
+static void exe_commands __ARGS((mparm_T *parmp));
 static void source_startup_scripts __ARGS((mparm_T *parmp));
 static void main_start_gui __ARGS((void));
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
 static void check_swap_exists_action __ARGS((void));
 #endif
 #ifdef FEAT_CLIENTSERVER
+static void exec_on_server __ARGS((mparm_T *parmp));
+static void prepare_server __ARGS((mparm_T *parmp));
 static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));
 static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));
 #endif
@@ -67,13 +137,13 @@ static FILE *time_fd = NULL;
  */
 static char *(main_errors[]) =
 {
-    N_("Unknown option"),
+    N_("Unknown option argument"),
 #define ME_UNKNOWN_OPTION	0
     N_("Too many edit arguments"),
 #define ME_TOO_MANY_ARGS	1
     N_("Argument missing after"),
 #define ME_ARG_MISSING		2
-    N_("Garbage after option"),
+    N_("Garbage after option argument"),
 #define ME_GARBAGE		3
     N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),
 #define ME_EXTRA_CMD		4
@@ -81,9 +151,6 @@ static char *(main_errors[]) =
 #define ME_INVALID_ARG		5
 };
 
-/* 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
@@ -101,60 +168,7 @@ main
     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 */
-#ifdef FEAT_QUICKFIX
-    char_u	*use_ef = NULL;		/* 'errorfile' from -q option */
-#endif
-#ifdef FEAT_CRYPT
-    int		ask_for_key = FALSE;    /* -x argument */
-#endif
-    int		n_commands = 0;		/* no. of commands from + or -c */
-    char_u	*commands[MAX_ARG_CMDS]; /* commands from + or -c option */
-    char_u	cmds_tofree[MAX_ARG_CMDS];  /* commands that need free() */
-    int		n_pre_commands = 0;	/* no. of commands from --cmd */
-    char_u	*pre_commands[MAX_ARG_CMDS]; /* commands from --cmd option */
-    int		no_swap_file = FALSE;   /* "-n" option used */
-    int		c;
-    int		i;
-    char_u	*p = NULL;
-    int		bin_mode = FALSE;	/* -b option used */
-#ifdef FEAT_EVAL
-    int		use_debug_break_level = -1;
-#endif
-#ifdef FEAT_WINDOWS
-    int		window_count = -1;	/* number of windows to use */
-    int		arg_idx;		/* index in argument list */
-    int		vert_windows = MAYBE;   /* "-O" used instead of "-o" */
-#endif
-    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 argument list */
-#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 */
-#ifdef FEAT_DIFF
-    int		diff_mode = FALSE;	/* start with 'diff' set */
-#endif
-    int		stdout_isatty;		/* is stdout a terminal? */
-    int		input_isatty;		/* is active input a terminal? */
-#ifdef MSWIN
-    int		full_path = FALSE;
-#endif
-#ifdef FEAT_CLIENTSERVER
-    char_u	*serverStr = NULL;	/* remote server command */
-    char_u	*serverStrEnc = NULL;	/* encoding of serverStr */
-    char_u	*servername = NULL;	/* allocated name for our server */
-#endif
-#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
-    int		literal = FALSE;	/* don't expand file names */
-#endif
     mparm_T	params;			/* various parameters passed between
 					 * main() and other functions. */
 
@@ -164,10 +178,23 @@ main
      */
     mch_early_init();
 
+    /* Many variables are in "params" so that we can pass them to invoked
+     * functions without a lot of arguments.  "argc" and "argv" are also
+     * copied, so that they can be changed. */
     vim_memset(&params, 0, sizeof(params));
+    params.argc = argc;
+    params.argv = argv;
+    params.want_full_screen = TRUE;
+#ifdef FEAT_EVAL
+    params.use_debug_break_level = -1;
+#endif
+#ifdef FEAT_WINDOWS
+    params.window_count = -1;
+    params.vert_windows = MAYBE;
+#endif
 
 #ifdef FEAT_TCL
-    vim_tcl_init(argv[0]);
+    vim_tcl_init(params.argv[0]);
 #endif
 
 #ifdef MEM_PROFILE
@@ -180,7 +207,7 @@ main
 #endif
 
 #ifdef __EMX__
-    _wildcard(&argc, &argv);
+    _wildcard(&params.argc, &params.argv);
 #endif
 
 #ifdef FEAT_MBYTE
@@ -195,13 +222,12 @@ main
 #endif
 
 #ifdef MAC_OS_CLASSIC
+    /* Prepare for possibly starting GUI sometime */
     /* Macintosh needs this before any memory is allocated. */
-    gui_prepare(&argc, argv);	/* Prepare for possibly starting GUI sometime */
+    gui_prepare(&params.argc, params.argv);
     TIME_MSG("GUI prepared");
 #endif
 
-    vim_memset(cmds_tofree, 0, sizeof(cmds_tofree));
-
     /* Init the table of Normal mode commands. */
     init_normal_cmds();
 
@@ -216,7 +242,6 @@ main
     if ((IObuff = alloc(IOSIZE)) == NULL
 	    || (NameBuff = alloc(MAXPATHL)) == NULL)
 	mch_exit(0);
-
     TIME_MSG("Allocated generic buffers");
 
 #ifdef NBDEBUG
@@ -224,6 +249,7 @@ main
      * NameBuff. */
     nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
     nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
+    TIME_MSG("NetBeans debug wait");
 #endif
 
 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -232,30 +258,7 @@ main
      * NOTE: Translated messages with encodings other than latin1 will not
      * work until set_init_1() has been called!
      */
-    setlocale(LC_ALL, "");
-
-# ifdef FEAT_GETTEXT
-    {
-	int	mustfree = FALSE;
-
-#  ifdef DYNAMIC_GETTEXT
-	/* Initialize the gettext library */
-	dyn_libintl_init(NULL);
-#  endif
-	/* expand_env() doesn't work yet, because chartab[] is not initialized
-	 * yet, call vim_getenv() directly */
-	p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
-	if (p != NULL && *p != NUL)
-	{
-	    STRCPY(NameBuff, p);
-	    STRCAT(NameBuff, "/lang");
-	    bindtextdomain(VIMPACKAGE, (char *)NameBuff);
-	}
-	if (mustfree)
-	    vim_free(p);
-	textdomain(VIMPACKAGE);
-    }
-# endif
+    init_locale();
     TIME_MSG("locale set");
 #endif
 
@@ -265,17 +268,18 @@ main
 
     /*
      * Do a first scan of the arguments in "argv[]":
-     *   -display
+     *   -display or --display
      *   --server...
      *   --socketid
      */
-    early_arg_scan(argc, argv, &params);
+    early_arg_scan(&params);
 
 #ifdef FEAT_SUN_WORKSHOP
-    findYourself(argv[0]);
+    findYourself(params.argv[0]);
 #endif
 #if defined(FEAT_GUI) && !defined(MAC_OS_CLASSIC)
-    gui_prepare(&argc, argv);	/* Prepare for possibly starting GUI sometime */
+    /* Prepare for possibly starting GUI sometime */
+    gui_prepare(&params.argc, params.argv);
     TIME_MSG("GUI prepared");
 #endif
 
@@ -290,7 +294,7 @@ main
      * (needed for :! to * work). mch_check_win() will also handle the -d or
      * -dev argument.
      */
-    stdout_isatty = (mch_check_win(argc, argv) != FAIL);
+    params.stdout_isatty = (mch_check_win(params.argc, params.argv) != FAIL);
     TIME_MSG("window checked");
 
     /*
@@ -300,8 +304,7 @@ main
 
     init_yank();		/* init yank buffers */
 
-    /* Init the argument list to empty. */
-    alist_init(&global_alist);
+    alist_init(&global_alist);	/* Init the argument list to empty. */
 
     /*
      * Set the default values for the options.
@@ -321,1993 +324,2018 @@ main
 #ifdef FEAT_CLIENTSERVER
     /*
      * Do the client-server stuff, unless "--servername ''" was used.
+     * This may exit Vim if the command was sent to the server.
      */
-    if (params.serverName_arg == NULL || *params.serverName_arg != NUL)
-    {
-# ifdef WIN32
-	/* Initialise the client/server messaging infrastructure. */
-	serverInitMessaging();
-# endif
-
-	/*
-	 * When a command server argument was found, execute it.  This may
-	 * exit Vim when it was successful.  Otherwise it's executed further
-	 * on.  Remember the encoding used here in "serverStrEnc".
-	 */
-	if (params.serverArg)
-	{
-	    cmdsrv_main(&argc, argv, params.serverName_arg, &serverStr);
-# ifdef FEAT_MBYTE
-	    serverStrEnc = vim_strsave(p_enc);
-# endif
-	}
-
-	/* If we're still running, get the name to register ourselves.
-	 * On Win32 can register right now, for X11 need to setup the
-	 * clipboard first, it's further down. */
-	servername = serverMakeName(params.serverName_arg, argv[0]);
-# ifdef WIN32
-	if (servername != NULL)
-	{
-	    serverSetName(servername);
-	    vim_free(servername);
-	}
-# endif
-    }
+    exec_on_server(&params);
 #endif
 
     /*
-     * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
-     * If the executable name starts with "r" we disable shell commands.
-     * If the next character is "e" we run in Easy mode.
-     * 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 "diff" or "vimdiff" we start in diff mode.
-     * If the next characters are "ex" we start in Ex mode.  If it's followed
-     * by "im" use improved Ex mode.
+     * Figure out the way to work from the command name argv[0].
+     * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
      */
-    initstr = gettail((char_u *)argv[0]);
+    parse_command_name(&params);
 
-#ifdef MACOS_X_UNIX
-    /* An issue has been seen when launching Vim in such a way that
-     * $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the
-     * executable or a symbolic link of it. Until this issue is resolved
-     * we prohibit the GUI from being used.
+    /*
+     * Process the command line arguments.  File names are put in the global
+     * argument list "global_alist".
      */
-    if (STRCMP(initstr, argv[0]) == 0)
-	disallow_gui = TRUE;
-#endif
+    command_line_scan(&params);
+    TIME_MSG("parsing arguments");
 
-#ifdef FEAT_EVAL
-    set_vim_var_string(VV_PROGNAME, initstr, -1);
-#endif
+    /*
+     * 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 fork one off with
+     * :gui.
+     */
+#ifdef ALWAYS_USE_GUI
+    gui.starting = TRUE;
+#else
+# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
+    /*
+     * Check if the GUI can be started.  Reset gui.starting if not.
+     * Don't know about other systems, stay on the safe side and don't check.
+     */
+    if (gui.starting && gui_init_check() == FAIL)
+    {
+	gui.starting = FALSE;
 
-    /* TODO: On MacOS X default to gui if argv[0] ends in:
-     *       /vim.app/Contents/MacOS/Vim */
+	/* When running "evim" or "gvim -y" we need the menus, exit if we
+	 * don't have them. */
+	if (params.evim_mode)
+	    mch_exit(1);
+    }
+# endif
+#endif
 
-    if (TOLOWER_ASC(initstr[0]) == 'r')
+    /* "-b" argument used.  Check before expanding file names, because for
+     * Win32 this makes us edit a shortcut file itself, instead of the file it
+     * links to. */
+    if (params.bin_mode)
     {
-	restricted = TRUE;
-	++initstr;
+	set_options_bin(curbuf->b_p_bin, 1, 0);
+	curbuf->b_p_bin = 1;	    /* binary file I/O */
     }
 
-    /* Avoid using evim mode for "editor". */
-    if (TOLOWER_ASC(initstr[0]) == 'e'
-	    && (TOLOWER_ASC(initstr[1]) == 'v'
-					   || TOLOWER_ASC(initstr[1]) == 'g'))
+    if (GARGCOUNT > 0)
     {
-#ifdef FEAT_GUI
-	gui.starting = TRUE;
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+	/*
+	 * Expand wildcards in file names.
+	 */
+	if (!params.literal)
+	{
+	    /* Temporarily add '(' and ')' to 'isfname'.  These are valid
+	     * filename characters but are excluded from 'isfname' to make
+	     * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
+	    do_cmdline_cmd((char_u *)":set isf+=(,)");
+	    alist_expand(NULL, 0);
+	    do_cmdline_cmd((char_u *)":set isf&");
+	}
 #endif
-	params.evim_mode = TRUE;
-	++initstr;
+	fname = alist_name(&GARGLIST[0]);
     }
 
-    if (TOLOWER_ASC(initstr[0]) == 'g' || initstr[0] == 'k')
+#if defined(WIN32) && defined(FEAT_MBYTE)
     {
-	main_start_gui();
-#ifdef FEAT_GUI
-	++initstr;
-#endif
+	extern void set_alist_count(void);
+
+	/* Remember the number of entries in the argument list.  If it changes
+	 * we don't react on setting 'encoding'. */
+	set_alist_count();
     }
+#endif
 
-    if (STRNICMP(initstr, "view", 4) == 0)
+#ifdef MSWIN
+    if (GARGCOUNT == 1 && params.full_path)
     {
-	readonlymode = TRUE;
-	curbuf->b_p_ro = TRUE;
-	p_uc = 10000;			/* don't update very often */
-	initstr += 4;
+	/*
+	 * If there is one filename, fully qualified, we have very probably
+	 * been invoked from explorer, so change to the file's directory.
+	 * Hint: to avoid this when typing a command use a forward slash.
+	 * If the cd fails, it doesn't matter.
+	 */
+	(void)vim_chdirfile(fname);
     }
-    else if (STRNICMP(initstr, "vim", 3) == 0)
-	initstr += 3;
+#endif
+    TIME_MSG("expanding arguments");
 
-    /* Catch "[r][g]vimdiff" and "[r][g]viewdiff". */
-    if (STRICMP(initstr, "diff") == 0)
-    {
 #ifdef FEAT_DIFF
-	diff_mode = TRUE;
-#else
-	mch_errmsg(_("This Vim was not compiled with the diff feature."));
-	mch_errmsg("\n");
-	mch_exit(2);
+    if (params.diff_mode && params.window_count == -1)
+	params.window_count = 0;	/* open up to 3 files in a window */
 #endif
-    }
-
-    if (STRNICMP(initstr, "ex", 2) == 0)
-    {
-	if (STRNICMP(initstr + 2, "im", 2) == 0)
-	    exmode_active = EXMODE_VIM;
-	else
-	    exmode_active = EXMODE_NORMAL;
-	change_compatible(TRUE);	/* set 'compatible' */
-    }
 
-    initstr = gettail((char_u *)argv[0]);
-    ++argv;
-    --argc;
+    /* Don't redraw until much later. */
+    ++RedrawingDisabled;
 
     /*
-     * Process the command line arguments.
+     * When listing swap file names, don't do cursor positioning et. al.
      */
-    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]);
-	}
+    if (recoverymode && fname == NULL)
+	params.want_full_screen = FALSE;
 
-	/*
-	 * Optional argument.
-	 */
-	else if (argv[0][0] == '-' && !had_minmin)
-	{
-	    want_argument = FALSE;
-	    c = argv[0][argv_idx++];
-#ifdef VMS
-	    /*
-	     * VMS only uses upper case command lines.  Interpret "-X" as "-x"
-	     * and "-/X" as "-X".
-	     */
-	    if (c == '/')
-	    {
-		c = argv[0][argv_idx++];
-		c = TOUPPER_ASC(c);
-	    }
-	    else
-		c = TOLOWER_ASC(c);
-#endif
-	    switch (c)
-	    {
-	    case NUL:		/* "vim -"  read from stdin */
-				/* "ex -" silent mode */
-		if (exmode_active)
-		    silent_mode = TRUE;
-		else
-		{
-		    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 */
-				/* "--literal" take files literally */
-				/* "--nofork" don't fork */
-				/* "--noplugin[s]" skip plugins */
-				/* "--cmd <cmd>" execute cmd before vimrc */
-		if (STRICMP(argv[0] + argv_idx, "help") == 0)
-		    usage();
-		else if (STRICMP(argv[0] + argv_idx, "version") == 0)
-		{
-		    Columns = 80;	/* need to init Columns */
-		    info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
-		    list_version();
-		    msg_putchar('\n');
-		    msg_didout = FALSE;
-		    mch_exit(0);
-		}
-		else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
-		{
-#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
-		    literal = TRUE;
-#endif
-		}
-		else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
-		{
-#ifdef FEAT_GUI
-		    gui.dofork = FALSE;	/* don't fork() when starting GUI */
-#endif
-		}
-		else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
-		    p_lpl = FALSE;
-		else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
-		{
-		    want_argument = TRUE;
-		    argv_idx += 3;
-		}
-#ifdef FEAT_CLIENTSERVER
-		else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
-		    ; /* already processed -- no arg */
-		else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
-		       || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
-		{
-		    /* already processed -- snatch the following arg */
-		    if (argc > 1)
-		    {
-			--argc;
-			++argv;
-		    }
-		}
-#endif
-#ifdef FEAT_GUI_GTK
-		else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
-		{
-		    /* already processed -- snatch the following arg */
-		    if (argc > 1)
-		    {
-			--argc;
-			++argv;
-		    }
-		}
-		else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
-		{
-		    /* already processed, skip */
-		}
+    /*
+     * When certain to start the GUI, don't check capabilities of terminal.
+     * For GTK we can't be sure, but when started from the desktop it doesn't
+     * make sense to try using a terminal.
+     */
+#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
+    if (gui.starting
+# ifdef FEAT_GUI_GTK
+	    && !isatty(2)
+# endif
+	    )
+	params.want_full_screen = FALSE;
 #endif
-		else
-		{
-		    if (argv[0][argv_idx])
-			mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
-		    had_minmin = TRUE;
-		}
-		if (!want_argument)
-		    argv_idx = -1;	/* skip to next argument */
-		break;
 
-	    case 'A':		/* "-A" start in Arabic mode */
-#ifdef FEAT_ARABIC
-		set_option_value((char_u *)"arabic", 1L, NULL, 0);
-#else
-		mch_errmsg(_(e_noarabic));
-		mch_exit(2);
+#if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX)
+    /* When the GUI is started from Finder, need to display messages in a
+     * message box.  isatty(2) returns TRUE anyway, thus we need to check the
+     * name to know we're not started from a terminal. */
+    if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))
+	params.want_full_screen = FALSE;
 #endif
-		break;
 
-	    case 'b':		/* "-b" binary mode */
-		bin_mode = TRUE;    /* postpone to after reading .exrc files */
-		break;
+    /*
+     * mch_init() 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_exit() before mch_init()!
+     */
+    mch_init();
+    TIME_MSG("shell init");
 
-	    case 'C':		/* "-C"  Compatible */
-		change_compatible(TRUE);
-		break;
+#ifdef USE_XSMP
+    /*
+     * For want of anywhere else to do it, try to connect to xsmp here.
+     * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
+     * Hijacking -X 'no X connection' to also disable XSMP connection as that
+     * has a similar delay upon failure.
+     * Only try if SESSION_MANAGER is set to something non-null.
+     */
+    if (!x_no_connect)
+    {
+	char *p = getenv("SESSION_MANAGER");
 
-	    case 'e':		/* "-e" Ex mode */
-		exmode_active = EXMODE_NORMAL;
-		break;
+	if (p != NULL && *p != NUL)
+	{
+	    xsmp_init();
+	    TIME_MSG("xsmp init");
+	}
+    }
+#endif
 
-	    case 'E':		/* "-E" Improved Ex mode */
-		exmode_active = EXMODE_VIM;
-		break;
+    /*
+     * Print a warning if stdout is not a terminal.
+     */
+    check_tty(&params);
 
-	    case 'f':		/* "-f"  GUI: run in foreground.  Amiga: open
-				window directly, not with newcli */
-#ifdef FEAT_GUI
-		gui.dofork = FALSE;	/* don't fork() when starting GUI */
-#endif
-		break;
+    /* This message comes before term inits, but after setting "silent_mode"
+     * when the input is not a tty. */
+    if (GARGCOUNT > 1 && !silent_mode)
+	printf(_("%d files to edit\n"), GARGCOUNT);
 
-	    case 'g':		/* "-g" start GUI */
-		main_start_gui();
-		break;
+    if (params.want_full_screen && !silent_mode)
+    {
+	termcapinit(params.term);	/* set terminal name and get terminal
+				   capabilities (will set full_screen) */
+	screen_start();		/* don't know where cursor is now */
+	TIME_MSG("Termcap init");
+    }
 
-	    case 'F':		/* "-F" start in Farsi mode: rl + fkmap set */
-#ifdef FEAT_FKMAP
-		curwin->w_p_rl = p_fkmap = TRUE;
-#else
-		mch_errmsg(_(e_nofarsi));
-		mch_exit(2);
+    /*
+     * Set the default values for the options that use Rows and Columns.
+     */
+    ui_get_shellsize();		/* inits Rows and Columns */
+#ifdef FEAT_NETBEANS_INTG
+    if (usingNetbeans)
+	Columns += 2;		/* leave room for glyph gutter */
 #endif
-		break;
-
-	    case 'h':		/* "-h" give help message */
-#ifdef FEAT_GUI_GNOME
-		/* Tell usage() to exit for "gvim". */
-		gui.starting = FALSE;
+    firstwin->w_height = Rows - p_ch;
+    topframe->fr_height = Rows - p_ch;
+#ifdef FEAT_VERTSPLIT
+    firstwin->w_width = Columns;
+    topframe->fr_width = Columns;
 #endif
-		usage();
-		break;
-
-	    case 'H':		/* "-H" start in Hebrew mode: rl + hkmap set */
-#ifdef FEAT_RIGHTLEFT
-		curwin->w_p_rl = p_hkmap = TRUE;
-#else
-		mch_errmsg(_(e_nohebrew));
-		mch_exit(2);
+#ifdef FEAT_DIFF
+    /* Set the 'diff' option now, so that it can be checked for in a .vimrc
+     * file.  There is no buffer yet though. */
+    if (params.diff_mode)
+	diff_win_options(firstwin, FALSE);
 #endif
-		break;
 
-	    case 'l':		/* "-l" lisp mode, 'lisp' and 'showmatch' on */
-#ifdef FEAT_LISP
-		set_option_value((char_u *)"lisp", 1L, NULL, 0);
-		p_sm = TRUE;
-#endif
-		break;
+    cmdline_row = Rows - p_ch;
+    msg_row = cmdline_row;
+    screenalloc(FALSE);		/* allocate screen buffers */
+    set_init_2();
+    TIME_MSG("inits 2");
 
-#ifdef TARGET_API_MAC_OSX
-		/* For some reason on MacOS X, an argument like:
-		   -psn_0_10223617 is passed in when invoke from Finder
-		   or with the 'open' command */
-	    case 'p':
-		argv_idx = -1; /* bypass full -psn */
-		main_start_gui();
-		break;
-#endif
-	    case 'M':		/* "-M"  no changes or writing of files */
-		reset_modifiable();
-		/* FALLTHROUGH */
+    msg_scroll = TRUE;
+    no_wait_return = TRUE;
 
-	    case 'm':		/* "-m"  no writing of files */
-		p_write = FALSE;
-		break;
+    init_mappings();		/* set up initial mappings */
 
-	    case 'y':		/* "-y"  easy mode */
-#ifdef FEAT_GUI
-		gui.starting = TRUE;	/* start GUI a bit later */
+    init_highlight(TRUE, FALSE); /* set the default highlight groups */
+    TIME_MSG("init highlight");
+
+#ifdef FEAT_EVAL
+    /* Set the break level after the terminal is initialized. */
+    debug_break_level = params.use_debug_break_level;
 #endif
-		params.evim_mode = TRUE;
-		break;
 
-	    case 'N':		/* "-N"  Nocompatible */
-		change_compatible(FALSE);
-		break;
+    /* Execute --cmd arguments. */
+    exe_pre_commands(&params);
 
-	    case 'n':		/* "-n" no swap file */
-		no_swap_file = TRUE;
-		break;
-
-	    case 'o':		/* "-o[N]" open N horizontal split windows */
-#ifdef FEAT_WINDOWS
-		/* default is 0: open window for each file */
-		window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
-		vert_windows = FALSE;
-#endif
-		break;
-
-		case 'O':	/* "-O[N]" open N vertical split windows */
-#if defined(FEAT_VERTSPLIT) && defined(FEAT_WINDOWS)
-		/* default is 0: open window for each file */
-		window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
-		vert_windows = TRUE;
-#endif
-		break;
+    /* Source startup scripts. */
+    source_startup_scripts(&params);
 
-#ifdef FEAT_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;
+#ifdef FEAT_EVAL
+    /*
+     * Read all the plugin files.
+     * Only when compiled with +eval, since most plugins need it.
+     */
+    if (p_lpl)
+    {
+	cmd_runtime((char_u *)"plugin/*.vim", TRUE);
+	TIME_MSG("loading plugins");
+    }
 #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;
+    /*
+     * 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_exit(0);
+    }
 
-	    case 's':
-		if (exmode_active)	/* "-s" silent (batch) mode */
-		    silent_mode = TRUE;
-		else		/* "-s {scriptin}" read from script file */
-		    want_argument = TRUE;
-		break;
+    /*
+     * Set a few option defaults after reading .vimrc files:
+     * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
+     */
+    set_init_3();
+    TIME_MSG("inits 3");
 
-	    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;
+    /*
+     * "-n" argument: Disable swap file by setting 'updatecount' to 0.
+     * Note that this overrides anything from a vimrc file.
+     */
+    if (params.no_swap_file)
+	p_uc = 0;
 
-#ifdef FEAT_EVAL
-	    case 'D':		/* "-D"		Debugging */
-		use_debug_break_level = 9999;
-		break;
-#endif
-#ifdef FEAT_DIFF
-	    case 'd':		/* "-d"		'diff' */
-# ifdef AMIGA
-		/* check for "-dev {device}" */
-		if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
-		    want_argument = TRUE;
-		else
+#ifdef FEAT_FKMAP
+    if (curwin->w_p_rl && p_altkeymap)
+    {
+	p_hkmap = FALSE;	/* Reset the Hebrew keymap mode */
+# ifdef FEAT_ARABIC
+	curwin->w_p_arab = FALSE; /* Reset the Arabic keymap mode */
 # endif
-		    diff_mode = TRUE;
-		break;
+	p_fkmap = TRUE;		/* Set the Farsi keymap mode */
+    }
 #endif
-	    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);
-		if (argv[0][argv_idx] != NUL)
-		{
-		    set_option_value((char_u *)"verbosefile", 0L,
-					     (char_u *)argv[0] + argv_idx, 0);
-		    argv_idx = STRLEN(argv[0]);
-		}
-		break;
 
-	    case 'v':		/* "-v"  Vi-mode (as if called "vi") */
-		exmode_active = 0;
 #ifdef FEAT_GUI
-		gui.starting = FALSE;	/* don't start GUI */
+    if (gui.starting)
+    {
+#if defined(UNIX) || defined(VMS)
+	/* When something caused a message from a vimrc script, need to output
+	 * an extra newline before the shell prompt. */
+	if (did_emsg || msg_didout)
+	    putchar('\n');
 #endif
-		break;
 
-	    case 'w':		/* "-w{number}"	set window height */
-				/* "-w {scriptout}"	write to script */
-		if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
-		{
-		    i = get_number_arg((char_u *)argv[0], &argv_idx, 10);
-		    set_option_value((char_u *)"window", (long)i, NULL, 0);
-		    break;
-		}
-		want_argument = TRUE;
-		break;
+	gui_start();		/* will set full_screen to TRUE */
+	TIME_MSG("starting GUI");
 
-#ifdef FEAT_CRYPT
-	    case 'x':		/* "-x"  encrypted reading/writing of files */
-		ask_for_key = TRUE;
-		break;
+	/* When running "evim" or "gvim -y" we need the menus, exit if we
+	 * don't have them. */
+	if (!gui.in_use && params.evim_mode)
+	    mch_exit(1);
+    }
 #endif
 
-	    case 'X':		/* "-X"  don't connect to X server */
-#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
-		x_no_connect = TRUE;
+#ifdef SPAWNO		/* special MSDOS swapping library */
+    init_SPAWNO("", SWAP_ANY);
 #endif
-		break;
 
-	    case 'Z':		/* "-Z"  restricted mode */
-		restricted = TRUE;
-		break;
+#ifdef FEAT_VIMINFO
+    /*
+     * Read in registers, history etc, but not marks, from the viminfo file
+     */
+    if (*p_viminfo != NUL)
+    {
+	read_viminfo(NULL, TRUE, FALSE, FALSE);
+	TIME_MSG("reading viminfo");
+    }
+#endif
 
-	    case 'c':		/* "-c{command}" or "-c {command}" execute
-				   command */
-		if (argv[0][argv_idx] != NUL)
-		{
-		    if (n_commands >= MAX_ARG_CMDS)
-			mainerr(ME_EXTRA_CMD, NULL);
-		    commands[n_commands++] = (char_u *)argv[0] + argv_idx;
-		    argv_idx = -1;
-		    break;
-		}
-		/*FALLTHROUGH*/
-	    case 'S':		/* "-S {file}" execute Vim script */
-	    case 'i':		/* "-i {viminfo}" use for viminfo */
-#ifndef FEAT_DIFF
-	    case 'd':		/* "-d {device}" device (for Amiga) */
+#ifdef FEAT_QUICKFIX
+    /*
+     * "-q errorfile": Load the error file now.
+     * If the error file can't be read, exit before doing anything else.
+     */
+    if (params.edit_type == EDIT_QF)
+    {
+	if (params.use_ef != NULL)
+	    set_string_option_direct((char_u *)"ef", -1,
+						     params.use_ef, OPT_FREE);
+	if (qf_init(p_ef, p_efm, TRUE) < 0)
+	{
+	    out_char('\n');
+	    mch_exit(3);
+	}
+	TIME_MSG("reading errorfile");
+    }
 #endif
-	    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 */
-#ifdef FEAT_GUI_W32
-	    case 'P':		/* "-P {parent title}" MDI parent */
+
+    /*
+     * Start putting things on the screen.
+     * Scroll screen down before drawing over it
+     * Clear screen now, so file message will not be cleared.
+     */
+    starting = NO_BUFFERS;
+    no_wait_return = FALSE;
+    if (!exmode_active)
+	msg_scroll = FALSE;
+
+#ifdef FEAT_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.
+     * For the Mac this handles putting files dropped on the Vim icon to
+     * global_alist.
+     */
+    if (gui.in_use)
+    {
+# ifdef FEAT_SUN_WORKSHOP
+	if (!usingSunWorkShop)
+# endif
+	    gui_wait_for_chars(50L);
+	TIME_MSG("GUI delay");
+    }
 #endif
-		want_argument = TRUE;
-		break;
 
-	    default:
-		mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
-	    }
+#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
+    qnx_clip_init();
+#endif
 
-	    /*
-	     * 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]);
+#ifdef FEAT_XCLIPBOARD
+    /* Start using the X clipboard, unless the GUI was started. */
+# ifdef FEAT_GUI
+    if (!gui.in_use)
+# endif
+    {
+	setup_term_clip();
+	TIME_MSG("setup clipboard");
+    }
+#endif
 
-		--argc;
-		if (argc < 1 && c != 'S')
-		    mainerr_arg_missing((char_u *)argv[0]);
-		++argv;
-		argv_idx = -1;
+#ifdef FEAT_CLIENTSERVER
+    /* Prepare for being a Vim server. */
+    prepare_server(&params);
+#endif
 
-		switch (c)
-		{
-		case 'c':	/* "-c {command}" execute command */
-		case 'S':	/* "-S {file}" execute Vim script */
-		    if (n_commands >= MAX_ARG_CMDS)
-			mainerr(ME_EXTRA_CMD, NULL);
-		    if (c == 'S')
-		    {
-			char	*a;
-
-			if (argc < 1)
-			    /* "-S" without argument: use default session file
-			     * name. */
-			    a = SESSION_FILE;
-			else if (argv[0][0] == '-')
-			{
-			    /* "-S" followed by another option: use default
-			     * session file name. */
-			    a = SESSION_FILE;
-			    ++argc;
-			    --argv;
-			}
-			else
-			    a = argv[0];
-			p = alloc((unsigned)(STRLEN(a) + 4));
-			if (p == NULL)
-			    mch_exit(2);
-			sprintf((char *)p, "so %s", a);
-			cmds_tofree[n_commands] = TRUE;
-			commands[n_commands++] = p;
-		    }
-		    else
-			commands[n_commands++] = (char_u *)argv[0];
-		    break;
-
-		case '-':	/* "--cmd {command}" execute command */
-		    if (n_pre_commands >= MAX_ARG_CMDS)
-			mainerr(ME_EXTRA_CMD, NULL);
-		    pre_commands[n_pre_commands++] = (char_u *)argv[0];
-		    break;
-
-	    /*	case 'd':   -d {device} is handled in mch_check_win() for the
-	     *		    Amiga */
+    /*
+     * If "-" argument given: Read file from stdin.
+     * Do this before starting Raw mode, because it may change things that the
+     * writing end of the pipe doesn't like, e.g., in case stdin and stderr
+     * are the same terminal: "cat | vim -".
+     * Using autocommands here may cause trouble...
+     */
+    if (params.edit_type == EDIT_STDIN && !recoverymode)
+	read_stdin();
 
-#ifdef FEAT_QUICKFIX
-		case 'q':	/* "-q {errorfile}" QuickFix mode */
-		    use_ef = (char_u *)argv[0];
-		    break;
+#if defined(UNIX) || defined(VMS)
+    /* When switching screens and something caused a message from a vimrc
+     * script, need to output an extra newline on exit. */
+    if ((did_emsg || msg_didout) && *T_TI != NUL)
+	newline_on_exit = TRUE;
 #endif
 
-		case 'i':	/* "-i {viminfo}" use for viminfo */
-		    use_viminfo = (char_u *)argv[0];
-		    break;
+    /*
+     * 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);
+    TIME_MSG("setting raw mode");
 
-		case 's':	/* "-s {scriptin}" read from script file */
-		    if (scriptin[0] != NULL)
-		    {
-scripterror:
-			mch_errmsg(_("Attempt to open script file again: \""));
-			mch_errmsg(argv[-1]);
-			mch_errmsg(" ");
-			mch_errmsg(argv[0]);
-			mch_errmsg("\"\n");
-			mch_exit(2);
-		    }
-		    if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
-		    {
-			mch_errmsg(_("Cannot open for reading: \""));
-			mch_errmsg(argv[0]);
-			mch_errmsg("\"\n");
-			mch_exit(2);
-		    }
-		    if (save_typebuf() == FAIL)
-			mch_exit(2);	/* out of memory */
-		    break;
+    if (need_wait_return || msg_didany)
+    {
+	wait_return(TRUE);
+	TIME_MSG("waiting for return");
+    }
 
-		case 't':	/* "-t {tag}" */
-		    tagname = (char_u *)argv[0];
-		    break;
+    starttermcap();	    /* start termcap if not done by wait_return() */
+    TIME_MSG("start termcap");
 
-		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 FEAT_GUI
-		    if (term_is_gui((char_u *)argv[0]))
-			gui.starting = TRUE;	/* start GUI a bit later */
-		    else
+#ifdef FEAT_MOUSE
+    setmouse();				/* may start using the mouse */
 #endif
-			term = (char_u *)argv[0];
-		    break;
-
-		case 'u':	/* "-u {vimrc}" vim inits file */
-		    params.use_vimrc = (char_u *)argv[0];
-		    break;
+    if (scroll_region)
+	scroll_region_reset();		/* In case Rows changed */
+    scroll_start();	/* may scroll the screen to the right position */
 
-		case 'U':	/* "-U {gvimrc}" gvim inits file */
+    /*
+     * Don't clear the screen when starting in Ex mode, unless using the GUI.
+     */
+    if (exmode_active
 #ifdef FEAT_GUI
-		    use_gvimrc = (char_u *)argv[0];
+			&& !gui.in_use
 #endif
-		    break;
-
-		case 'w':	/* "-w {nr}" 'window' value */
-				/* "-w {scriptout}" append to script file */
-		    if (vim_isdigit(*((char_u *)argv[0])))
-		    {
-			argv_idx = 0;
-			i = get_number_arg((char_u *)argv[0], &argv_idx, 10);
-			set_option_value((char_u *)"window", (long)i, NULL, 0);
-			argv_idx = -1;
-			break;
-		    }
-		    /*FALLTHROUGH*/
-		case 'W':	/* "-W {scriptout}" overwrite script file */
-		    if (scriptout != NULL)
-			goto scripterror;
-		    if ((scriptout = mch_fopen(argv[0],
-				    c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
-		    {
-			mch_errmsg(_("Cannot open for script output: \""));
-			mch_errmsg(argv[0]);
-			mch_errmsg("\"\n");
-			mch_exit(2);
-		    }
-		    break;
+					)
+	must_redraw = CLEAR;
+    else
+    {
+	screenclear();			/* clear screen */
+	TIME_MSG("clearing screen");
+    }
 
-#ifdef FEAT_GUI_W32
-		case 'P':		/* "-P {parent title}" MDI parent */
-		    gui_mch_set_parent(argv[0]);
-		    break;
+#ifdef FEAT_CRYPT
+    if (params.ask_for_key)
+    {
+	(void)get_crypt_key(TRUE, TRUE);
+	TIME_MSG("getting crypt key");
+    }
 #endif
-		}
-	    }
-	}
-
-	/*
-	 * File name argument.
-	 */
-	else
-	{
-	    argv_idx = -1;	    /* skip to next argument */
 
-	    /* Check for only one type of editing. */
-	    if (edit_type != EDIT_NONE && edit_type != EDIT_FILE)
-		mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
-	    edit_type = EDIT_FILE;
+    no_wait_return = TRUE;
 
-#ifdef MSWIN
-	    /* Remember if the argument was a full path before changing
-	     * slashes to backslashes. */
-	    if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
-		full_path = TRUE;
-#endif
+    /*
+     * Create the requested number of windows and edit buffers in them.
+     * Also does recovery if "recoverymode" set.
+     */
+    create_windows(&params);
+    TIME_MSG("opening buffers");
 
-	    /* Add the file to the global argument list. */
-	    if (ga_grow(&global_alist.al_ga, 1) == FAIL
-		    || (p = vim_strsave((char_u *)argv[0])) == NULL)
-		mch_exit(2);
-#ifdef FEAT_DIFF
-	    if (diff_mode && mch_isdir(p) && GARGCOUNT > 0
-				      && !mch_isdir(alist_name(&GARGLIST[0])))
-	    {
-		char_u	    *r;
+    /* Ex starts at last line of the file */
+    if (exmode_active)
+	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
 
-		r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
-		if (r != NULL)
-		{
-		    vim_free(p);
-		    p = r;
-		}
-	    }
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+    TIME_MSG("BufEnter autocommands");
 #endif
-#if defined(__CYGWIN32__) && !defined(WIN32)
-	    /*
-	     * If vim is invoked by non-Cygwin tools, convert away any
-	     * DOS paths, so things like .swp files are created correctly.
-	     * Look for evidence of non-Cygwin paths before we bother.
-	     * This is only for when using the Unix files.
-	     */
-	    if (strpbrk(p, "\\:") != NULL)
-	    {
-		char posix_path[PATH_MAX];
+    setpcmark();
 
-		cygwin_conv_to_posix_path(p, posix_path);
-		vim_free(p);
-		p = vim_strsave(posix_path);
-		if (p == NULL)
-		    mch_exit(2);
-	    }
+#ifdef FEAT_QUICKFIX
+    /*
+     * When started with "-q errorfile" jump to first error now.
+     */
+    if (params.edit_type == EDIT_QF)
+    {
+	qf_jump(0, 0, FALSE);
+	TIME_MSG("jump to first error");
+    }
 #endif
-	    alist_add(&global_alist, p,
-#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
-		    literal ? 2 : 0	/* add buffer number after expanding */
-#else
-		    2		/* add buffer number now and use curbuf */
+
+#ifdef FEAT_WINDOWS
+    /*
+     * If opened more than one window, start editing files in the other
+     * windows.
+     */
+    edit_buffers(&params);
 #endif
-		    );
 
-#if defined(FEAT_MBYTE) && defined(WIN32)
-	    {
-		extern void used_file_arg(char *, int, int);
+#ifdef FEAT_DIFF
+    if (params.diff_mode)
+    {
+	win_T	*wp;
 
-		/* Remember this argument has been added to the argument list.
-		 * Needed when 'encoding' is changed. */
-		used_file_arg(argv[0], literal, full_path);
-	    }
+	/* set options in each window for "vimdiff". */
+	for (wp = firstwin; wp != NULL; wp = wp->w_next)
+	    diff_win_options(wp, TRUE);
+    }
 #endif
-	}
-
-	/*
-	 * 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;
-	}
-    }
-    TIME_MSG("parsing arguments");
 
     /*
-     * 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.
+     * Shorten any of the filenames, but only when absolute.
      */
-#ifdef ALWAYS_USE_GUI
-    gui.starting = TRUE;
-#else
-# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
+    shorten_fnames(FALSE);
+
     /*
-     * Check if the GUI can be started.  Reset gui.starting if not.
-     * Don't know about other systems, stay on the safe side and don't check.
+     * Need to jump to the tag before executing the '-c command'.
+     * Makes "vim -c '/return' -t main" work.
      */
-    if (gui.starting && gui_init_check() == FAIL)
+    if (params.tagname != NULL)
     {
-	gui.starting = FALSE;
-
-	/* When running "evim" or "gvim -y" we need the menus, exit if we
-	 * don't have them. */
-	if (params.evim_mode)
-	    mch_exit(1);
+	vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
+	do_cmdline_cmd(IObuff);
+	TIME_MSG("jumping to tag");
     }
-# endif
-#endif
 
-    /* "-b" argument used.  Check before expanding file names, because for
-     * Win32 this makes us edit a shortcut file itself, instead of the file it
-     * links to. */
-    if (bin_mode)
-    {
-	set_options_bin(curbuf->b_p_bin, 1, 0);
-	curbuf->b_p_bin = 1;	    /* binary file I/O */
-    }
+    /* Execute any "+", "-c" and "-S" arguments. */
+    if (params.n_commands > 0)
+	exe_commands(&params);
 
-    if (GARGCOUNT > 0)
-    {
-#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
-	/*
-	 * Expand wildcards in file names.
-	 */
-	if (!literal)
-	{
-	    /* Temporarily add '(' and ')' to 'isfname'.  These are valid
-	     * filename characters but are excluded from 'isfname' to make
-	     * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
-	    do_cmdline_cmd((char_u *)":set isf+=(,)");
-	    alist_expand(NULL, 0);
-	    do_cmdline_cmd((char_u *)":set isf&");
-	}
-#endif
-	fname = alist_name(&GARGLIST[0]);
-    }
+    RedrawingDisabled = 0;
+    redraw_all_later(NOT_VALID);
+    no_wait_return = FALSE;
+    starting = 0;
 
-#if defined(WIN32) && defined(FEAT_MBYTE)
-    {
-	extern void set_alist_count(void);
+    /* start in insert mode */
+    if (p_im)
+	need_start_insertmode = TRUE;
 
-	/* Remember the number of entries in the argument list.  If it changes
-	 * we don't react on setting 'encoding'. */
-	set_alist_count();
-    }
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
+    TIME_MSG("VimEnter autocommands");
 #endif
 
-#ifdef MSWIN
-    if (GARGCOUNT == 1 && full_path)
+#if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND)
+    /* When a startup script or session file setup for diff'ing and
+     * scrollbind, sync the scrollbind now. */
+    if (curwin->w_p_diff && curwin->w_p_scb)
     {
-	/*
-	 * If there is one filename, fully qualified, we have very probably
-	 * been invoked from explorer, so change to the file's directory.
-	 * Hint: to avoid this when typing a command use a forward slash.
-	 * If the cd fails, it doesn't matter.
-	 */
-	(void)vim_chdirfile(fname);
+	update_topline();
+	check_scrollbind((linenr_T)0, 0L);
+	TIME_MSG("diff scrollbinding");
     }
 #endif
-    TIME_MSG("expanding arguments");
 
-#ifdef FEAT_DIFF
-    if (diff_mode)
-    {
-	if (window_count == -1)
-	    window_count = 0;		/* open up to 3 files in a window */
-	if (vert_windows == MAYBE)
-	    vert_windows = TRUE;	/* use vertical split */
-    }
+#if defined(WIN3264) && !defined(FEAT_GUI_W32)
+    mch_set_winsize_now();	    /* Allow winsize changes from now on */
 #endif
 
-    ++RedrawingDisabled;
-
-    /*
-     * When listing swap file names, don't do cursor positioning et. al.
-     */
-    if (recoverymode && fname == NULL)
-	want_full_screen = FALSE;
+    /* If ":startinsert" command used, stuff a dummy command to be able to
+     * call normal_cmd(), which will then start Insert mode. */
+    if (restart_edit != 0)
+	stuffcharReadbuff(K_IGNORE);
 
-    /*
-     * When certain to start the GUI, don't check capabilities of terminal.
-     * For GTK we can't be sure, but when started from the desktop it doesn't
-     * make sense to try using a terminal.
-     */
-#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
-    if (gui.starting
-# ifdef FEAT_GUI_GTK
-	    && !isatty(2)
-# endif
-	    )
-	want_full_screen = FALSE;
+#ifdef FEAT_NETBEANS_INTG
+    if (usingNetbeans)
+	/* Tell the client that it can start sending commands. */
+	netbeans_startup_done();
 #endif
 
-#if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX)
-    /* When the GUI is started from Finder, need to display messages in a
-     * message box.  isatty(2) returns TRUE anyway, thus we need to check the
-     * name to know we're not started from a terminal. */
-    if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))
-	want_full_screen = FALSE;
-#endif
+    TIME_MSG("before starting main loop");
 
     /*
-     * mch_init() 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_exit() before mch_init()!
+     * Call the main command loop.  This never returns.
      */
-    mch_init();
-    TIME_MSG("shell init");
+    main_loop(FALSE, FALSE);
 
-#ifdef USE_XSMP
-    /*
-     * For want of anywhere else to do it, try to connect to xsmp here.
-     * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
-     * Hijacking -X 'no X connection' to also disable XSMP connection as that
-     * has a similar delay upon failure.
-     * Only try if SESSION_MANAGER is set to something non-null.
-     */
-    if (!x_no_connect)
+    return 0;
+}
+#endif /* PROTO */
+
+/*
+ * Main loop: Execute Normal mode commands until exiting Vim.
+ * Also used to handle commands in the command-line window, until the window
+ * is closed.
+ * Also used to handle ":visual" command after ":global": execute Normal mode
+ * commands, return when entering Ex mode.  "noexmode" is TRUE then.
+ */
+    void
+main_loop(cmdwin, noexmode)
+    int		cmdwin;	    /* TRUE when working in the command-line window */
+    int		noexmode;   /* TRUE when return on entering Ex mode */
+{
+    oparg_T	oa;	/* operator arguments */
+
+#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
+    /* Setup to catch a terminating error from the X server.  Just ignore
+     * it, restore the state and continue.  This might not always work
+     * properly, but at least we don't exit unexpectedly when the X server
+     * exists while Vim is running in a console. */
+    if (!cmdwin && !noexmode && SETJMP(x_jump_env))
     {
-	p = (char_u *)getenv("SESSION_MANAGER");
-	if (p != NULL && *p != NUL)
-	{
-	    xsmp_init();
-	    TIME_MSG("xsmp init");
-	}
+	State = NORMAL;
+# ifdef FEAT_VISUAL
+	VIsual_active = FALSE;
+# endif
+	got_int = TRUE;
+	need_wait_return = FALSE;
+	global_busy = FALSE;
+	exmode_active = 0;
+	skip_redraw = FALSE;
+	RedrawingDisabled = 0;
+	no_wait_return = 0;
+# ifdef FEAT_EVAL
+	emsg_skip = 0;
+# endif
+	emsg_off = 0;
+# ifdef FEAT_MOUSE
+	setmouse();
+# endif
+	settmode(TMODE_RAW);
+	starttermcap();
+	scroll_start();
+	redraw_later_clear();
     }
 #endif
 
-    /*
-     * 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)
-#ifdef FEAT_GUI
-	    /* don't want the delay when started from the desktop */
-	    && !gui.starting
+    clear_oparg(&oa);
+    while (!cmdwin
+#ifdef FEAT_CMDWIN
+	    || cmdwin_result == 0
 #endif
 	    )
     {
-#ifdef NBDEBUG
+	if (stuff_empty())
+	{
+	    did_check_timestamps = FALSE;
+	    if (need_check_timestamps)
+		check_timestamps(FALSE);
+	    if (need_wait_return)	/* if wait_return still needed ... */
+		wait_return(FALSE);	/* ... call it now */
+	    if (need_start_insertmode && goto_im()
+#ifdef FEAT_VISUAL
+		    && !VIsual_active
+#endif
+		    )
+	    {
+		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;
+	    }
+	}
+	if (got_int && !global_busy)
+	{
+	    if (!quit_more)
+		(void)vgetc();		/* flush all buffers */
+	    got_int = FALSE;
+	}
+	if (!exmode_active)
+	    msg_scroll = FALSE;
+	quit_more = FALSE;
+
 	/*
-	 * This shouldn't be necessary. But if I run netbeans with the log
-	 * output coming to the console and XOpenDisplay fails, I get vim
-	 * trying to start with input/output to my console tty.  This fills my
-	 * input buffer so fast I can't even kill the process in under 2
-	 * minutes (and it beeps continuosly the whole time :-)
+	 * 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 (usingNetbeans && (!stdout_isatty || !input_isatty))
+	if (skip_redraw || exmode_active)
+	    skip_redraw = FALSE;
+	else if (do_redraw || stuff_empty())
 	{
-	    mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
-	    exit(1);
-	}
+#if defined(FEAT_FOLDING) && defined(FEAT_VISUAL)
+	    /* Include a closed fold completely in the Visual area. */
+	    foldAdjustVisual();
+#endif
+#ifdef FEAT_FOLDING
+	    /*
+	     * When 'foldclose' is set, apply 'foldlevel' to folds that don't
+	     * contain the cursor.
+	     * When 'foldopen' is "all", open the fold(s) under the cursor.
+	     * This may mark the window for redrawing.
+	     */
+	    if (hasAnyFolding(curwin) && !char_avail())
+	    {
+		foldCheckClose();
+		if (fdo_flags & FDO_ALL)
+		    foldOpenCursor();
+	    }
 #endif
-	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"));
-	out_flush();
-	if (scriptin[0] == NULL)
-	    ui_delay(2000L, TRUE);
-	TIME_MSG("Warning delay");
-    }
-
-    /* This message comes before term inits, but after setting "silent_mode"
-     * when the input is not a tty. */
-    if (GARGCOUNT > 1 && !silent_mode)
-	printf(_("%d files to edit\n"), GARGCOUNT);
 
-    if (want_full_screen && !silent_mode)
-    {
-	termcapinit(term);	/* set terminal name and get terminal
-				   capabilities (will set full_screen) */
-	screen_start();		/* don't know where cursor is now */
-	TIME_MSG("Termcap init");
-    }
+	    /*
+	     * 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();
 
-    /*
-     * Set the default values for the options that use Rows and Columns.
-     */
-    ui_get_shellsize();		/* inits Rows and Columns */
-#ifdef FEAT_NETBEANS_INTG
-    if (usingNetbeans)
-	Columns += 2;		/* leave room for glyph gutter */
+#ifdef FEAT_VISUAL
+	    if (VIsual_active)
+		update_curbuf(INVERTED);/* update inverted part */
+	    else
 #endif
-    firstwin->w_height = Rows - p_ch;
-    topframe->fr_height = Rows - p_ch;
-#ifdef FEAT_VERTSPLIT
-    firstwin->w_width = Columns;
-    topframe->fr_width = Columns;
+		if (must_redraw)
+		update_screen(0);
+	    else if (redraw_cmdline || clear_cmdline)
+		showmode();
+#ifdef FEAT_WINDOWS
+	    redraw_statuslines();
 #endif
-#ifdef FEAT_DIFF
-    /* Set the 'diff' option now, so that it can be checked for in a .vimrc
-     * file.  There is no buffer yet though. */
-    if (diff_mode)
-	diff_win_options(firstwin, FALSE);
+#ifdef FEAT_TITLE
+	    if (need_maketitle)
+		maketitle();
 #endif
+	    /* display message after redraw */
+	    if (keep_msg != NULL)
+	    {
+		char_u *p;
 
-    cmdline_row = Rows - p_ch;
-    msg_row = cmdline_row;
-    screenalloc(FALSE);		/* allocate screen buffers */
-    set_init_2();
-    TIME_MSG("inits 2");
-
-    msg_scroll = TRUE;
-    no_wait_return = TRUE;
+		/* msg_attr_keep() will set keep_msg to NULL, must free the
+		 * string here. */
+		p = keep_msg;
+		msg_attr(p, keep_msg_attr);
+		vim_free(p);
+	    }
+	    if (need_fileinfo)		/* show file info after redraw */
+	    {
+		fileinfo(FALSE, TRUE, FALSE);
+		need_fileinfo = FALSE;
+	    }
 
-    init_mappings();		/* set up initial mappings */
+	    emsg_on_display = FALSE;	/* can delete error message now */
+	    did_emsg = FALSE;
+	    msg_didany = FALSE;		/* reset lines_left in msg_start() */
+	    showruler(FALSE);
 
-    init_highlight(TRUE, FALSE); /* set the default highlight groups */
-    TIME_MSG("init highlight");
+	    setcursor();
+	    cursor_on();
 
-#ifdef FEAT_EVAL
-    /* Set the break level after the terminal is initialized. */
-    debug_break_level = use_debug_break_level;
+	    do_redraw = FALSE;
+	}
+#ifdef FEAT_GUI
+	if (need_mouse_correct)
+	    gui_mouse_correct();
 #endif
 
-    /* Execute --cmd arguments. */
-    exe_pre_commands(pre_commands, n_pre_commands);
-
-    /* Source startup scripts. */
-    source_startup_scripts(&params);
-
-#ifdef FEAT_EVAL
-    /*
-     * Read all the plugin files.
-     * Only when compiled with +eval, since most plugins need it.
-     */
-    if (p_lpl)
-    {
-	cmd_runtime((char_u *)"plugin/*.vim", TRUE);
-	TIME_MSG("loading plugins");
-    }
-#endif
+	/*
+	 * Update w_curswant if w_set_curswant has been set.
+	 * Postponed until here to avoid computing w_virtcol too often.
+	 */
+	update_curswant();
 
-    /*
-     * 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_exit(0);
+	/*
+	 * If we're invoked as ex, do a round of ex commands.
+	 * Otherwise, get and execute a normal mode command.
+	 */
+	if (exmode_active)
+	{
+	    if (noexmode)   /* End of ":global/path/visual" commands */
+		return;
+	    do_exmode(exmode_active == EXMODE_VIM);
+	}
+	else
+	    normal_cmd(&oa, TRUE);
     }
+}
 
-    /*
-     * Set a few option defaults after reading .vimrc files:
-     * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
-     */
-    set_init_3();
-    TIME_MSG("inits 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 FEAT_FKMAP
-    if (curwin->w_p_rl && p_altkeymap)
-    {
-	p_hkmap = FALSE;	/* Reset the Hebrew keymap mode */
-# ifdef FEAT_ARABIC
-	curwin->w_p_arab = FALSE; /* Reset the Arabic keymap mode */
+#if defined(USE_XSMP) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
+/*
+ * Exit, but leave behind swap files for modified buffers.
+ */
+    void
+getout_preserve_modified(exitval)
+    int		exitval;
+{
+# if defined(SIGHUP) && defined(SIG_IGN)
+    /* Ignore SIGHUP, because a dropped connection causes a read error, which
+     * makes Vim exit and then handling SIGHUP causes various reentrance
+     * problems. */
+    signal(SIGHUP, SIG_IGN);
 # endif
-	p_fkmap = TRUE;		/* Set the Farsi keymap mode */
-    }
+
+    ml_close_notmod();		    /* close all not-modified buffers */
+    ml_sync_all(FALSE, FALSE);	    /* preserve all swap files */
+    ml_close_all(FALSE);	    /* close all memfiles, without deleting */
+    getout(exitval);		    /* exit Vim properly */
+}
 #endif
 
-#ifdef FEAT_GUI
-    if (gui.starting)
-    {
-#if defined(UNIX) || defined(VMS)
-	/* When something caused a message from a vimrc script, need to output
-	 * an extra newline before the shell prompt. */
-	if (did_emsg || msg_didout)
-	    putchar('\n');
+
+/* Exit properly */
+    void
+getout(exitval)
+    int		exitval;
+{
+#ifdef FEAT_AUTOCMD
+    buf_T	*buf;
+    win_T	*wp;
 #endif
 
-	gui_start();		/* will set full_screen to TRUE */
-	TIME_MSG("starting GUI");
+    exiting = TRUE;
 
-	/* When running "evim" or "gvim -y" we need the menus, exit if we
-	 * don't have them. */
-	if (!gui.in_use && params.evim_mode)
-	    mch_exit(1);
-    }
+    /* When running in Ex mode an error causes us to exit with a non-zero exit
+     * code.  POSIX requires this, although it's not 100% clear from the
+     * standard. */
+    if (exmode_active)
+	exitval += ex_exitval;
+
+    /* Position the cursor on the last screen line, below all the text */
+#ifdef FEAT_GUI
+    if (!gui.in_use)
 #endif
+	windgoto((int)Rows - 1, 0);
 
-#ifdef SPAWNO		/* special MSDOS swapping library */
-    init_SPAWNO("", SWAP_ANY);
+#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
+    /* Optionally print hashtable efficiency. */
+    hash_debug_results();
 #endif
 
-#ifdef FEAT_VIMINFO
-    /*
-     * Read in registers, history etc, but not marks, from the viminfo file
-     */
-    if (*p_viminfo != NUL)
-    {
-	read_viminfo(NULL, TRUE, FALSE, FALSE);
-	TIME_MSG("reading viminfo");
-    }
+#ifdef FEAT_GUI
+    msg_didany = FALSE;
 #endif
 
-#ifdef FEAT_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)
+#ifdef FEAT_AUTOCMD
+    /* Trigger BufWinLeave for all windows, but only once per buffer. */
+    for (wp = firstwin; wp != NULL; )
     {
-	if (use_ef != NULL)
-	    set_string_option_direct((char_u *)"ef", -1, use_ef, OPT_FREE);
-	if (qf_init(p_ef, p_efm, TRUE) < 0)
+	buf = wp->w_buffer;
+	if (buf->b_changedtick != -1)
 	{
-	    out_char('\n');
-	    mch_exit(3);
+	    apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
+								  FALSE, buf);
+	    buf->b_changedtick = -1;	/* note that we did it already */
+	    wp = firstwin;		/* restart, window may be closed */
 	}
-	TIME_MSG("reading errorfile");
-    }
+	else
+	    wp = wp->w_next;
+    }
+    /* Trigger BufUnload for buffers that are loaded */
+    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+	if (buf->b_ml.ml_mfp != NULL)
+	{
+	    apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
+								  FALSE, buf);
+	    if (!buf_valid(buf))	/* autocmd may delete the buffer */
+		break;
+	}
+    apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
 #endif
 
-    /*
-     * Start putting things on the screen.
-     * Scroll screen down before drawing over it
-     * Clear screen now, so file message will not be cleared.
-     */
-    starting = NO_BUFFERS;
-    no_wait_return = FALSE;
-    if (!exmode_active)
-	msg_scroll = FALSE;
+#ifdef FEAT_VIMINFO
+    if (*p_viminfo != NUL)
+	/* Write out the registers, history, marks etc, to the viminfo file */
+	write_viminfo(NULL, FALSE);
+#endif
 
-#ifdef FEAT_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.
-     * For the Mac this handles putting files dropped on the Vim icon to
-     * global_alist.
-     */
-    if (gui.in_use)
-    {
-# ifdef FEAT_SUN_WORKSHOP
-	if (!usingSunWorkShop)
-# endif
-	    gui_wait_for_chars(50L);
-	TIME_MSG("GUI delay");
-    }
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
 #endif
 
-#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
-    qnx_clip_init();
+#ifdef FEAT_PROFILE
+    profile_dump();
 #endif
 
-#ifdef FEAT_XCLIPBOARD
-    /* Start using the X clipboard, unless the GUI was started. */
-# ifdef FEAT_GUI
-    if (!gui.in_use)
-# endif
+    if (did_emsg
+#ifdef FEAT_GUI
+	    || (gui.in_use && msg_didany && p_verbose > 0)
+#endif
+	    )
     {
-	setup_term_clip();
-	TIME_MSG("setup clipboard");
+	/* give the user a chance to read the (error) message */
+	no_wait_return = FALSE;
+	wait_return(FALSE);
     }
-#endif
 
-#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
-    /*
-     * Register for remote command execution with :serversend and --remote
-     * unless there was a -X or a --servername '' on the command line.
-     * Only register nongui-vim's with an explicit --servername argument.
-     */
-    if (X_DISPLAY != NULL && servername != NULL && (
+#ifdef FEAT_AUTOCMD
+    /* Position the cursor again, the autocommands may have moved it */
 # ifdef FEAT_GUI
-		gui.in_use ||
+    if (!gui.in_use)
 # endif
-		params.serverName_arg != NULL))
-    {
-	(void)serverRegisterName(X_DISPLAY, servername);
-	vim_free(servername);
-	TIME_MSG("register server name");
-    }
-    else
-	serverDelayedStartName = servername;
+	windgoto((int)Rows - 1, 0);
 #endif
 
-#ifdef FEAT_CLIENTSERVER
-    /*
-     * Execute command ourselves if we're here because the send failed (or
-     * else we would have exited above).
-     */
-    if (serverStr != NULL)
-    {
-	server_to_input_buf(serverConvert(serverStrEnc, serverStr, &p));
-	vim_free(p);
-    }
+#ifdef FEAT_MZSCHEME
+    mzscheme_end();
 #endif
-
-    /*
-     * If "-" argument given: Read file from stdin.
-     * Do this before starting Raw mode, because it may change things that the
-     * writing end of the pipe doesn't like, e.g., in case stdin and stderr
-     * are the same terminal: "cat | vim -".
-     * Using autocommands here may cause trouble...
-     */
-    if (edit_type == EDIT_STDIN && !recoverymode)
-    {
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-	/* When getting the ATTENTION prompt here, use a dialog */
-	swap_exists_action = SEA_DIALOG;
+#ifdef FEAT_TCL
+    tcl_end();
 #endif
-	no_wait_return = TRUE;
-	i = msg_didany;
-	set_buflisted(TRUE);
-	(void)open_buffer(TRUE, NULL);	/* create memfile and read file */
-	no_wait_return = FALSE;
-	msg_didany = i;
-	TIME_MSG("reading stdin");
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-	check_swap_exists_action();
+#ifdef FEAT_RUBY
+    ruby_end();
 #endif
-#if !(defined(AMIGA) || defined(MACOS))
-	/*
-	 * Close stdin and dup it from stderr.  Required for GPM to work
-	 * properly, and for running external commands.
-	 * Is there any other system that cannot do this?
-	 */
-	close(0);
-	dup(2);
+#ifdef FEAT_PYTHON
+    python_end();
 #endif
-    }
-
-#if defined(UNIX) || defined(VMS)
-    /* When switching screens and something caused a message from a vimrc
-     * script, need to output an extra newline on exit. */
-    if ((did_emsg || msg_didout) && *T_TI != NUL)
-	newline_on_exit = TRUE;
+#ifdef FEAT_PERL
+    perl_end();
+#endif
+#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
+    iconv_end();
+#endif
+#ifdef FEAT_NETBEANS_INTG
+    netbeans_end();
 #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);
-    TIME_MSG("setting raw mode");
+    mch_exit(exitval);
+}
 
-    if (need_wait_return || msg_didany)
+/*
+ * 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 (vim_isdigit(p[*idx]))
     {
-	wait_return(TRUE);
-	TIME_MSG("waiting for return");
+	def = atoi((char *)&(p[*idx]));
+	while (vim_isdigit(p[*idx]))
+	    *idx = *idx + 1;
     }
+    return def;
+}
 
-    starttermcap();	    /* start termcap if not done by wait_return() */
-    TIME_MSG("start termcap");
-
-#ifdef FEAT_MOUSE
-    setmouse();				/* may start using the mouse */
-#endif
-    if (scroll_region)
-	scroll_region_reset();		/* In case Rows changed */
-    scroll_start();	/* may scroll the screen to the right position */
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+/*
+ * Setup to use the current locale (for ctype() and many other things).
+ */
+    static void
+init_locale()
+{
+    setlocale(LC_ALL, "");
 
-    /*
-     * Don't clear the screen when starting in Ex mode, unless using the GUI.
-     */
-    if (exmode_active
-#ifdef FEAT_GUI
-			&& !gui.in_use
-#endif
-					)
-	must_redraw = CLEAR;
-    else
+# ifdef FEAT_GETTEXT
     {
-	screenclear();			/* clear screen */
-	TIME_MSG("clearing screen");
-    }
+	int	mustfree = FALSE;
+	char_u	*p;
 
-#ifdef FEAT_CRYPT
-    if (ask_for_key)
-    {
-	(void)get_crypt_key(TRUE, TRUE);
-	TIME_MSG("getting crypt key");
+#  ifdef DYNAMIC_GETTEXT
+	/* Initialize the gettext library */
+	dyn_libintl_init(NULL);
+#  endif
+	/* expand_env() doesn't work yet, because chartab[] is not initialized
+	 * yet, call vim_getenv() directly */
+	p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
+	if (p != NULL && *p != NUL)
+	{
+	    STRCPY(NameBuff, p);
+	    STRCAT(NameBuff, "/lang");
+	    bindtextdomain(VIMPACKAGE, (char *)NameBuff);
+	}
+	if (mustfree)
+	    vim_free(p);
+	textdomain(VIMPACKAGE);
     }
+# endif
+}
 #endif
 
-    no_wait_return = TRUE;
+/*
+ * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
+ * If the executable name starts with "r" we disable shell commands.
+ * If the next character is "e" we run in Easy mode.
+ * 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 "diff" or "vimdiff" we start in diff mode.
+ * If the next characters are "ex" we start in Ex mode.  If it's followed
+ * by "im" use improved Ex mode.
+ */
+    static void
+parse_command_name(parmp)
+    mparm_T	*parmp;
+{
+    char_u	*initstr;
 
-#ifdef FEAT_WINDOWS
-    /*
-     * Create the number of windows that was requested.
+    initstr = gettail((char_u *)parmp->argv[0]);
+
+#ifdef MACOS_X_UNIX
+    /* An issue has been seen when launching Vim in such a way that
+     * $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the
+     * executable or a symbolic link of it. Until this issue is resolved
+     * we prohibit the GUI from being used.
      */
-    if (window_count == -1)	/* was not set */
-	window_count = 1;
-    if (window_count == 0)
-	window_count = GARGCOUNT;
-    if (window_count > 1)
-    {
-	/* Don't change the windows if there was a command in .vimrc that
-	 * already split some windows */
-	if (vert_windows == MAYBE)
-	    vert_windows = FALSE;
-	if (firstwin->w_next == NULL)
-	{
-	    window_count = make_windows(window_count, vert_windows);
-	    TIME_MSG("making windows");
-	}
-	else
-	    window_count = win_count();
-    }
-    else
-	window_count = 1;
+    if (STRCMP(initstr, parmp->argv[0]) == 0)
+	disallow_gui = TRUE;
+
+    /* TODO: On MacOS X default to gui if argv[0] ends in:
+     *       /vim.app/Contents/MacOS/Vim */
 #endif
 
-    if (recoverymode)			/* do recover */
+#ifdef FEAT_EVAL
+    set_vim_var_string(VV_PROGNAME, initstr, -1);
+#endif
+
+    if (TOLOWER_ASC(initstr[0]) == 'r')
     {
-	msg_scroll = TRUE;		/* scroll message up */
-	ml_recover();
-	if (curbuf->b_ml.ml_mfp == NULL) /* failed */
-	    getout(1);
-	do_modelines(FALSE);		/* do modelines */
+	restricted = TRUE;
+	++initstr;
     }
-    else
+
+    /* Avoid using evim mode for "editor". */
+    if (TOLOWER_ASC(initstr[0]) == 'e'
+	    && (TOLOWER_ASC(initstr[1]) == 'v'
+		|| TOLOWER_ASC(initstr[1]) == 'g'))
     {
-	/*
-	 * 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 FEAT_AUTOCMD
-	/*
-	 * Don't execute Win/Buf Enter/Leave autocommands here
-	 */
-	++autocmd_no_enter;
-	++autocmd_no_leave;
-#endif
-#ifdef FEAT_WINDOWS
-	for (curwin = firstwin; curwin != NULL; curwin = W_NEXT(curwin))
-#endif
-	{
-	    curbuf = curwin->w_buffer;
-	    if (curbuf->b_ml.ml_mfp == NULL)
-	    {
-#ifdef FEAT_FOLDING
-		/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
-		if (p_fdls >= 0)
-		    curwin->w_p_fdl = p_fdls;
-#endif
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-		/* When getting the ATTENTION prompt here, use a dialog */
-		swap_exists_action = SEA_DIALOG;
+#ifdef FEAT_GUI
+	gui.starting = TRUE;
 #endif
-		set_buflisted(TRUE);
-		(void)open_buffer(FALSE, NULL); /* create memfile, read file */
+	parmp->evim_mode = TRUE;
+	++initstr;
+    }
 
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-		check_swap_exists_action();
-#endif
-#ifdef FEAT_AUTOCMD
-		curwin = firstwin;	    /* start again */
-#endif
-	    }
-#ifdef FEAT_WINDOWS
-	    ui_breakcheck();
-	    if (got_int)
-	    {
-		(void)vgetc();	/* only break the file loading, not the rest */
-		break;
-	    }
-#endif
-	}
-#ifdef FEAT_AUTOCMD
-	--autocmd_no_enter;
-	--autocmd_no_leave;
-#endif
-#ifdef FEAT_WINDOWS
-	curwin = firstwin;
-	curbuf = curwin->w_buffer;
+    if (TOLOWER_ASC(initstr[0]) == 'g' || initstr[0] == 'k')
+    {
+	main_start_gui();
+#ifdef FEAT_GUI
+	++initstr;
 #endif
     }
-    TIME_MSG("opening buffers");
 
-    /* Ex starts at last line of the file */
-    if (exmode_active)
-	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+    if (STRNICMP(initstr, "view", 4) == 0)
+    {
+	readonlymode = TRUE;
+	curbuf->b_p_ro = TRUE;
+	p_uc = 10000;			/* don't update very often */
+	initstr += 4;
+    }
+    else if (STRNICMP(initstr, "vim", 3) == 0)
+	initstr += 3;
 
-#ifdef FEAT_AUTOCMD
-    apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
-    TIME_MSG("BufEnter autocommands");
+    /* Catch "[r][g]vimdiff" and "[r][g]viewdiff". */
+    if (STRICMP(initstr, "diff") == 0)
+    {
+#ifdef FEAT_DIFF
+	parmp->diff_mode = TRUE;
+#else
+	mch_errmsg(_("This Vim was not compiled with the diff feature."));
+	mch_errmsg("\n");
+	mch_exit(2);
 #endif
-    setpcmark();
+    }
 
-#ifdef FEAT_QUICKFIX
-    /*
-     * When started with "-q errorfile" jump to first error now.
-     */
-    if (edit_type == EDIT_QF)
+    if (STRNICMP(initstr, "ex", 2) == 0)
     {
-	qf_jump(0, 0, FALSE);
-	TIME_MSG("jump to first error");
+	if (STRNICMP(initstr + 2, "im", 2) == 0)
+	    exmode_active = EXMODE_VIM;
+	else
+	    exmode_active = EXMODE_NORMAL;
+	change_compatible(TRUE);	/* set 'compatible' */
     }
-#endif
+}
 
-#ifdef FEAT_WINDOWS
-    /*
-     * If opened more than one window, start editing files in the other
-     * windows.  Make_windows() has already opened the windows.
-     */
-# ifdef FEAT_AUTOCMD
-    /*
-     * Don't execute Win/Buf Enter/Leave autocommands here
-     */
-    ++autocmd_no_enter;
-    ++autocmd_no_leave;
-# endif
-    arg_idx = 1;
-    for (i = 1; i < window_count; ++i)
+/*
+ * Get the name of the display, before gui_prepare() removes it from
+ * argv[].  Used for the xterm-clipboard display.
+ *
+ * Also find the --server... arguments and --socketid
+ */
+/*ARGSUSED*/
+    static void
+early_arg_scan(parmp)
+    mparm_T	*parmp;
+{
+#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER)
+    int		argc = parmp->argc;
+    char	**argv = parmp->argv;
+    int		i;
+
+    for (i = 1; i < argc; i++)
     {
-	if (curwin->w_next == NULL)	    /* just checking */
+	if (STRCMP(argv[i], "--") == 0)
 	    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)
+# ifdef FEAT_XCLIPBOARD
+	else if (STRICMP(argv[i], "-display") == 0
+#  if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
+		|| STRICMP(argv[i], "--display") == 0
+#  endif
+		)
 	{
-	    curwin->w_arg_idx = arg_idx;
-	    /* edit file from arg list, if there is one */
-	    (void)do_ecmd(0, arg_idx < GARGCOUNT
-			  ? alist_name(&GARGLIST[arg_idx]) : NULL,
-			  NULL, NULL, ECMD_LASTL, ECMD_HIDE);
-	    if (arg_idx == GARGCOUNT - 1)
-		arg_had_last = TRUE;
-	    ++arg_idx;
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    xterm_display = argv[++i];
 	}
-	ui_breakcheck();
-	if (got_int)
+# endif
+# ifdef FEAT_CLIENTSERVER
+	else if (STRICMP(argv[i], "--servername") == 0)
 	{
-	    (void)vgetc();	/* only break the file loading, not the rest */
-	    break;
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    parmp->serverName_arg = (char_u *)argv[++i];
+	}
+	else if (STRICMP(argv[i], "--serverlist") == 0
+		|| STRICMP(argv[i], "--remote-send") == 0
+		|| STRICMP(argv[i], "--remote-expr") == 0
+		|| STRICMP(argv[i], "--remote") == 0
+		|| STRICMP(argv[i], "--remote-silent") == 0)
+	    parmp->serverArg = TRUE;
+	else if (STRICMP(argv[i], "--remote-wait") == 0
+		|| STRICMP(argv[i], "--remote-wait-silent") == 0)
+	{
+	    parmp->serverArg = TRUE;
+#ifdef FEAT_GUI
+	    /* don't fork() when starting the GUI to edit the files ourself */
+	    gui.dofork = FALSE;
+#endif
 	}
-    }
-# ifdef FEAT_AUTOCMD
-    --autocmd_no_enter;
-# endif
-    win_enter(firstwin, FALSE);		/* back to first window */
-# ifdef FEAT_AUTOCMD
-    --autocmd_no_leave;
 # endif
-    TIME_MSG("editing files in windows");
-    if (window_count > 1)
-	win_equal(curwin, FALSE, 'b');	/* adjust heights */
-#endif /* FEAT_WINDOWS */
-
-#ifdef FEAT_DIFF
-    if (diff_mode)
-    {
-	win_T	*wp;
+# ifdef FEAT_GUI_GTK
+	else if (STRICMP(argv[i], "--socketid") == 0)
+	{
+	    unsigned int    socket_id;
+	    int		    count;
 
-	/* set options in each window for "vimdiff". */
-	for (wp = firstwin; wp != NULL; wp = wp->w_next)
-	    diff_win_options(wp, TRUE);
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
+		count = sscanf(&(argv[i + 1][2]), "%x", &socket_id);
+	    else
+		count = sscanf(argv[i+1], "%u", &socket_id);
+	    if (count != 1)
+		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
+	    else
+		gtk_socket_id = socket_id;
+	    i++;
+	}
+	else if (STRICMP(argv[i], "--echo-wid") == 0)
+	    echo_wid_arg = TRUE;
+# endif
     }
 #endif
+}
 
-    /*
-     * Shorten any of the filenames, but only when absolute.
-     */
-    shorten_fnames(FALSE);
-
-    /*
-     * Need to jump to the tag before executing the '-c command'.
-     * Makes "vim -c '/return' -t main" work.
-     */
-    if (tagname != NULL)
-    {
-	STRCPY(IObuff, "ta ");
-
-	STRNCAT(IObuff, tagname, IOSIZE - 4);
-	IObuff[IOSIZE - 1] = NUL;
-	do_cmdline_cmd(IObuff);
-	TIME_MSG("jumping to tag");
-    }
+/*
+ * Scan the command line arguments.
+ */
+    static void
+command_line_scan(parmp)
+    mparm_T	*parmp;
+{
+    int		argc = parmp->argc;
+    char	**argv = parmp->argv;
+    int		argv_idx;		/* index in argv[n][] */
+    int		had_minmin = FALSE;	/* found "--" argument */
+    int		want_argument;		/* option argument with argument */
+    int		c;
+    char_u	*p;
+    long	n;
 
-    if (n_commands > 0)
+    --argc;
+    ++argv;
+    argv_idx = 1;	    /* active option letter is argv[0][argv_idx] */
+    while (argc > 0)
     {
 	/*
-	 * We start commands on line 0, make "vim +/pat file" match a
-	 * pattern on line 1.  But don't move the cursor when an autocommand
-	 * with g`" was used.
+	 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
 	 */
-	msg_scroll = TRUE;
-	if (tagname == NULL && curwin->w_cursor.lnum <= 1)
-	    curwin->w_cursor.lnum = 0;
-	sourcing_name = (char_u *)"command line";
-#ifdef FEAT_EVAL
-	current_SID = SID_CARG;
-#endif
-	for (i = 0; i < n_commands; ++i)
+	if (argv[0][0] == '+' && !had_minmin)
 	{
-	    do_cmdline_cmd(commands[i]);
-	    if (cmds_tofree[i])
-		vim_free(commands[i]);
+	    if (parmp->n_commands >= MAX_ARG_CMDS)
+		mainerr(ME_EXTRA_CMD, NULL);
+	    argv_idx = -1;	    /* skip to next argument */
+	    if (argv[0][1] == NUL)
+		parmp->commands[parmp->n_commands++] = (char_u *)"$";
+	    else
+		parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]);
 	}
-	sourcing_name = NULL;
-#ifdef FEAT_EVAL
-	current_SID = 0;
-#endif
-	if (curwin->w_cursor.lnum == 0)
-	    curwin->w_cursor.lnum = 1;
 
-	if (!exmode_active)
-	    msg_scroll = FALSE;
+	/*
+	 * Optional argument.
+	 */
+	else if (argv[0][0] == '-' && !had_minmin)
+	{
+	    want_argument = FALSE;
+	    c = argv[0][argv_idx++];
+#ifdef VMS
+	    /*
+	     * VMS only uses upper case command lines.  Interpret "-X" as "-x"
+	     * and "-/X" as "-X".
+	     */
+	    if (c == '/')
+	    {
+		c = argv[0][argv_idx++];
+		c = TOUPPER_ASC(c);
+	    }
+	    else
+		c = TOLOWER_ASC(c);
+#endif
+	    switch (c)
+	    {
+	    case NUL:		/* "vim -"  read from stdin */
+				/* "ex -" silent mode */
+		if (exmode_active)
+		    silent_mode = TRUE;
+		else
+		{
+		    if (parmp->edit_type != EDIT_NONE)
+			mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		    parmp->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 option arguments */
+				/* "--help" give help message */
+				/* "--version" give version message */
+				/* "--literal" take files literally */
+				/* "--nofork" don't fork */
+				/* "--noplugin[s]" skip plugins */
+				/* "--cmd <cmd>" execute cmd before vimrc */
+		if (STRICMP(argv[0] + argv_idx, "help") == 0)
+		    usage();
+		else if (STRICMP(argv[0] + argv_idx, "version") == 0)
+		{
+		    Columns = 80;	/* need to init Columns */
+		    info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
+		    list_version();
+		    msg_putchar('\n');
+		    msg_didout = FALSE;
+		    mch_exit(0);
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
+		{
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+		    parmp->literal = TRUE;
+#endif
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
+		{
+#ifdef FEAT_GUI
+		    gui.dofork = FALSE;	/* don't fork() when starting GUI */
+#endif
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
+		    p_lpl = FALSE;
+		else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
+		{
+		    want_argument = TRUE;
+		    argv_idx += 3;
+		}
+#ifdef FEAT_CLIENTSERVER
+		else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
+		    ; /* already processed -- no arg */
+		else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
+		       || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
+		{
+		    /* already processed -- snatch the following arg */
+		    if (argc > 1)
+		    {
+			--argc;
+			++argv;
+		    }
+		}
+#endif
+#ifdef FEAT_GUI_GTK
+		else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
+		{
+		    /* already processed -- snatch the following arg */
+		    if (argc > 1)
+		    {
+			--argc;
+			++argv;
+		    }
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
+		{
+		    /* already processed, skip */
+		}
+#endif
+		else
+		{
+		    if (argv[0][argv_idx])
+			mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
+		    had_minmin = TRUE;
+		}
+		if (!want_argument)
+		    argv_idx = -1;	/* skip to next argument */
+		break;
+
+	    case 'A':		/* "-A" start in Arabic mode */
+#ifdef FEAT_ARABIC
+		set_option_value((char_u *)"arabic", 1L, NULL, 0);
+#else
+		mch_errmsg(_(e_noarabic));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'b':		/* "-b" binary mode */
+		parmp->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 = EXMODE_NORMAL;
+		break;
+
+	    case 'E':		/* "-E" Improved Ex mode */
+		exmode_active = EXMODE_VIM;
+		break;
+
+	    case 'f':		/* "-f"  GUI: run in foreground.  Amiga: open
+				window directly, not with newcli */
+#ifdef FEAT_GUI
+		gui.dofork = FALSE;	/* don't fork() when starting GUI */
+#endif
+		break;
+
+	    case 'g':		/* "-g" start GUI */
+		main_start_gui();
+		break;
+
+	    case 'F':		/* "-F" start in Farsi mode: rl + fkmap set */
+#ifdef FEAT_FKMAP
+		curwin->w_p_rl = p_fkmap = TRUE;
+#else
+		mch_errmsg(_(e_nofarsi));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'h':		/* "-h" give help message */
+#ifdef FEAT_GUI_GNOME
+		/* Tell usage() to exit for "gvim". */
+		gui.starting = FALSE;
+#endif
+		usage();
+		break;
+
+	    case 'H':		/* "-H" start in Hebrew mode: rl + hkmap set */
+#ifdef FEAT_RIGHTLEFT
+		curwin->w_p_rl = p_hkmap = TRUE;
+#else
+		mch_errmsg(_(e_nohebrew));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'l':		/* "-l" lisp mode, 'lisp' and 'showmatch' on */
+#ifdef FEAT_LISP
+		set_option_value((char_u *)"lisp", 1L, NULL, 0);
+		p_sm = TRUE;
+#endif
+		break;
+
+#ifdef TARGET_API_MAC_OSX
+		/* For some reason on MacOS X, an argument like:
+		   -psn_0_10223617 is passed in when invoke from Finder
+		   or with the 'open' command */
+	    case 'p':
+		argv_idx = -1; /* bypass full -psn */
+		main_start_gui();
+		break;
+#endif
+	    case 'M':		/* "-M"  no changes or writing of files */
+		reset_modifiable();
+		/* FALLTHROUGH */
+
+	    case 'm':		/* "-m"  no writing of files */
+		p_write = FALSE;
+		break;
+
+	    case 'y':		/* "-y"  easy mode */
+#ifdef FEAT_GUI
+		gui.starting = TRUE;	/* start GUI a bit later */
+#endif
+		parmp->evim_mode = TRUE;
+		break;
+
+	    case 'N':		/* "-N"  Nocompatible */
+		change_compatible(FALSE);
+		break;
+
+	    case 'n':		/* "-n" no swap file */
+		parmp->no_swap_file = TRUE;
+		break;
+
+	    case 'o':		/* "-o[N]" open N horizontal split windows */
+#ifdef FEAT_WINDOWS
+		/* default is 0: open window for each file */
+		parmp->window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
+		parmp->vert_windows = FALSE;
+#endif
+		break;
+
+		case 'O':	/* "-O[N]" open N vertical split windows */
+#if defined(FEAT_VERTSPLIT) && defined(FEAT_WINDOWS)
+		/* default is 0: open window for each file */
+		parmp->window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
+		parmp->vert_windows = TRUE;
+#endif
+		break;
+
+#ifdef FEAT_QUICKFIX
+	    case 'q':		/* "-q" QuickFix mode */
+		if (parmp->edit_type != EDIT_NONE)
+		    mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		parmp->edit_type = EDIT_QF;
+		if (argv[0][argv_idx])		/* "-q{errorfile}" */
+		{
+		    parmp->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 (parmp->edit_type != EDIT_NONE)
+		    mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		parmp->edit_type = EDIT_TAG;
+		if (argv[0][argv_idx])		/* "-t{tag}" */
+		{
+		    parmp->tagname = (char_u *)argv[0] + argv_idx;
+		    argv_idx = -1;
+		}
+		else				/* "-t {tag}" */
+		    want_argument = TRUE;
+		break;
+
+#ifdef FEAT_EVAL
+	    case 'D':		/* "-D"		Debugging */
+		parmp->use_debug_break_level = 9999;
+		break;
+#endif
+#ifdef FEAT_DIFF
+	    case 'd':		/* "-d"		'diff' */
+# ifdef AMIGA
+		/* check for "-dev {device}" */
+		if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
+		    want_argument = TRUE;
+		else
+# endif
+		    parmp->diff_mode = TRUE;
+		break;
+#endif
+	    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);
+		if (argv[0][argv_idx] != NUL)
+		{
+		    set_option_value((char_u *)"verbosefile", 0L,
+					     (char_u *)argv[0] + argv_idx, 0);
+		    argv_idx = STRLEN(argv[0]);
+		}
+		break;
+
+	    case 'v':		/* "-v"  Vi-mode (as if called "vi") */
+		exmode_active = 0;
+#ifdef FEAT_GUI
+		gui.starting = FALSE;	/* don't start GUI */
+#endif
+		break;
+
+	    case 'w':		/* "-w{number}"	set window height */
+				/* "-w {scriptout}"	write to script */
+		if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
+		{
+		    n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
+		    set_option_value((char_u *)"window", n, NULL, 0);
+		    break;
+		}
+		want_argument = TRUE;
+		break;
+
+#ifdef FEAT_CRYPT
+	    case 'x':		/* "-x"  encrypted reading/writing of files */
+		parmp->ask_for_key = TRUE;
+		break;
+#endif
+
+	    case 'X':		/* "-X"  don't connect to X server */
+#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
+		x_no_connect = TRUE;
+#endif
+		break;
+
+	    case 'Z':		/* "-Z"  restricted mode */
+		restricted = TRUE;
+		break;
+
+	    case 'c':		/* "-c{command}" or "-c {command}" execute
+				   command */
+		if (argv[0][argv_idx] != NUL)
+		{
+		    if (parmp->n_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    parmp->commands[parmp->n_commands++] = (char_u *)argv[0] + argv_idx;
+		    argv_idx = -1;
+		    break;
+		}
+		/*FALLTHROUGH*/
+	    case 'S':		/* "-S {file}" execute Vim script */
+	    case 'i':		/* "-i {viminfo}" use for viminfo */
+#ifndef FEAT_DIFF
+	    case 'd':		/* "-d {device}" device (for Amiga) */
+#endif
+	    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 */
+#ifdef FEAT_GUI_W32
+	    case 'P':		/* "-P {parent title}" MDI parent */
+#endif
+		want_argument = TRUE;
+		break;
+
+	    default:
+		mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
+	    }
+
+	    /*
+	     * Handle option arguments 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 && c != 'S')
+		    mainerr_arg_missing((char_u *)argv[0]);
+		++argv;
+		argv_idx = -1;
+
+		switch (c)
+		{
+		case 'c':	/* "-c {command}" execute command */
+		case 'S':	/* "-S {file}" execute Vim script */
+		    if (parmp->n_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    if (c == 'S')
+		    {
+			char	*a;
+
+			if (argc < 1)
+			    /* "-S" without argument: use default session file
+			     * name. */
+			    a = SESSION_FILE;
+			else if (argv[0][0] == '-')
+			{
+			    /* "-S" followed by another option: use default
+			     * session file name. */
+			    a = SESSION_FILE;
+			    ++argc;
+			    --argv;
+			}
+			else
+			    a = argv[0];
+			p = alloc((unsigned)(STRLEN(a) + 4));
+			if (p == NULL)
+			    mch_exit(2);
+			sprintf((char *)p, "so %s", a);
+			parmp->cmds_tofree[parmp->n_commands] = TRUE;
+			parmp->commands[parmp->n_commands++] = p;
+		    }
+		    else
+			parmp->commands[parmp->n_commands++] = (char_u *)argv[0];
+		    break;
+
+		case '-':	/* "--cmd {command}" execute command */
+		    if (parmp->n_pre_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    parmp->pre_commands[parmp->n_pre_commands++] = (char_u *)argv[0];
+		    break;
+
+	    /*	case 'd':   -d {device} is handled in mch_check_win() for the
+	     *		    Amiga */
 
 #ifdef FEAT_QUICKFIX
-	/* When started with "-q errorfile" jump to first error again. */
-	if (edit_type == EDIT_QF)
-	    qf_jump(0, 0, FALSE);
+		case 'q':	/* "-q {errorfile}" QuickFix mode */
+		    parmp->use_ef = (char_u *)argv[0];
+		    break;
 #endif
-	TIME_MSG("executing command arguments");
-    }
-
-    RedrawingDisabled = 0;
-    redraw_all_later(NOT_VALID);
-    no_wait_return = FALSE;
-    starting = 0;
 
-    /* start in insert mode */
-    if (p_im)
-	need_start_insertmode = TRUE;
+		case 'i':	/* "-i {viminfo}" use for viminfo */
+		    use_viminfo = (char_u *)argv[0];
+		    break;
 
-#ifdef FEAT_AUTOCMD
-    apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
-    TIME_MSG("VimEnter autocommands");
-#endif
+		case 's':	/* "-s {scriptin}" read from script file */
+		    if (scriptin[0] != NULL)
+		    {
+scripterror:
+			mch_errmsg(_("Attempt to open script file again: \""));
+			mch_errmsg(argv[-1]);
+			mch_errmsg(" ");
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
+		    {
+			mch_errmsg(_("Cannot open for reading: \""));
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    if (save_typebuf() == FAIL)
+			mch_exit(2);	/* out of memory */
+		    break;
 
-#if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND)
-    /* When a startup script or session file setup for diff'ing and
-     * scrollbind, sync the scrollbind now. */
-    if (curwin->w_p_diff && curwin->w_p_scb)
-    {
-	update_topline();
-	check_scrollbind((linenr_T)0, 0L);
-	TIME_MSG("diff scrollbinding");
-    }
-#endif
+		case 't':	/* "-t {tag}" */
+		    parmp->tagname = (char_u *)argv[0];
+		    break;
 
-#if defined(WIN3264) && !defined(FEAT_GUI_W32)
-    mch_set_winsize_now();	    /* Allow winsize changes from now on */
+		case 'T':	/* "-T {terminal}" terminal name */
+		    /*
+		     * The -T term argument is always available and when
+		     * HAVE_TERMLIB is supported it overrides the environment
+		     * variable TERM.
+		     */
+#ifdef FEAT_GUI
+		    if (term_is_gui((char_u *)argv[0]))
+			gui.starting = TRUE;	/* start GUI a bit later */
+		    else
 #endif
+			parmp->term = (char_u *)argv[0];
+		    break;
 
-    /* If ":startinsert" command used, stuff a dummy command to be able to
-     * call normal_cmd(), which will then start Insert mode. */
-    if (restart_edit != 0)
-	stuffcharReadbuff(K_IGNORE);
+		case 'u':	/* "-u {vimrc}" vim inits file */
+		    parmp->use_vimrc = (char_u *)argv[0];
+		    break;
 
-#ifdef FEAT_NETBEANS_INTG
-    if (usingNetbeans)
-	/* Tell the client that it can start sending commands. */
-	netbeans_startup_done();
+		case 'U':	/* "-U {gvimrc}" gvim inits file */
+#ifdef FEAT_GUI
+		    use_gvimrc = (char_u *)argv[0];
 #endif
+		    break;
 
-    TIME_MSG("before starting main loop");
-
-    /*
-     * Call the main command loop.  This never returns.
-     */
-    main_loop(FALSE, FALSE);
-
-    return 0;
-}
-#endif /* PROTO */
-
-/*
- * Main loop: Execute Normal mode commands until exiting Vim.
- * Also used to handle commands in the command-line window, until the window
- * is closed.
- * Also used to handle ":visual" command after ":global": execute Normal mode
- * commands, return when entering Ex mode.  "noexmode" is TRUE then.
- */
-    void
-main_loop(cmdwin, noexmode)
-    int		cmdwin;	    /* TRUE when working in the command-line window */
-    int		noexmode;   /* TRUE when return on entering Ex mode */
-{
-    oparg_T	oa;	/* operator arguments */
-
-#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
-    /* Setup to catch a terminating error from the X server.  Just ignore
-     * it, restore the state and continue.  This might not always work
-     * properly, but at least we don't exit unexpectedly when the X server
-     * exists while Vim is running in a console. */
-    if (!cmdwin && !noexmode && SETJMP(x_jump_env))
-    {
-	State = NORMAL;
-# ifdef FEAT_VISUAL
-	VIsual_active = FALSE;
-# endif
-	got_int = TRUE;
-	need_wait_return = FALSE;
-	global_busy = FALSE;
-	exmode_active = 0;
-	skip_redraw = FALSE;
-	RedrawingDisabled = 0;
-	no_wait_return = 0;
-# ifdef FEAT_EVAL
-	emsg_skip = 0;
-# endif
-	emsg_off = 0;
-# ifdef FEAT_MOUSE
-	setmouse();
-# endif
-	settmode(TMODE_RAW);
-	starttermcap();
-	scroll_start();
-	redraw_later_clear();
-    }
-#endif
+		case 'w':	/* "-w {nr}" 'window' value */
+				/* "-w {scriptout}" append to script file */
+		    if (vim_isdigit(*((char_u *)argv[0])))
+		    {
+			argv_idx = 0;
+			n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
+			set_option_value((char_u *)"window", n, NULL, 0);
+			argv_idx = -1;
+			break;
+		    }
+		    /*FALLTHROUGH*/
+		case 'W':	/* "-W {scriptout}" overwrite script file */
+		    if (scriptout != NULL)
+			goto scripterror;
+		    if ((scriptout = mch_fopen(argv[0],
+				    c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
+		    {
+			mch_errmsg(_("Cannot open for script output: \""));
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    break;
 
-    clear_oparg(&oa);
-    while (!cmdwin
-#ifdef FEAT_CMDWIN
-	    || cmdwin_result == 0
-#endif
-	    )
-    {
-	if (stuff_empty())
-	{
-	    did_check_timestamps = FALSE;
-	    if (need_check_timestamps)
-		check_timestamps(FALSE);
-	    if (need_wait_return)	/* if wait_return still needed ... */
-		wait_return(FALSE);	/* ... call it now */
-	    if (need_start_insertmode && goto_im()
-#ifdef FEAT_VISUAL
-		    && !VIsual_active
+#ifdef FEAT_GUI_W32
+		case 'P':		/* "-P {parent title}" MDI parent */
+		    gui_mch_set_parent(argv[0]);
+		    break;
 #endif
-		    )
-	    {
-		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;
+		}
 	    }
 	}
-	if (got_int && !global_busy)
-	{
-	    if (!quit_more)
-		(void)vgetc();		/* flush all buffers */
-	    got_int = FALSE;
-	}
-	if (!exmode_active)
-	    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.
+	 * File name argument.
 	 */
-	if (skip_redraw || exmode_active)
-	    skip_redraw = FALSE;
-	else if (do_redraw || stuff_empty())
+	else
 	{
-#if defined(FEAT_FOLDING) && defined(FEAT_VISUAL)
-	    /* Include a closed fold completely in the Visual area. */
-	    foldAdjustVisual();
-#endif
-#ifdef FEAT_FOLDING
-	    /*
-	     * When 'foldclose' is set, apply 'foldlevel' to folds that don't
-	     * contain the cursor.
-	     * When 'foldopen' is "all", open the fold(s) under the cursor.
-	     * This may mark the window for redrawing.
-	     */
-	    if (hasAnyFolding(curwin) && !char_avail())
-	    {
-		foldCheckClose();
-		if (fdo_flags & FDO_ALL)
-		    foldOpenCursor();
-	    }
-#endif
+	    argv_idx = -1;	    /* skip to next argument */
 
-	    /*
-	     * 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();
+	    /* Check for only one type of editing. */
+	    if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
+		mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+	    parmp->edit_type = EDIT_FILE;
 
-#ifdef FEAT_VISUAL
-	    if (VIsual_active)
-		update_curbuf(INVERTED);/* update inverted part */
-	    else
-#endif
-		if (must_redraw)
-		update_screen(0);
-	    else if (redraw_cmdline || clear_cmdline)
-		showmode();
-#ifdef FEAT_WINDOWS
-	    redraw_statuslines();
-#endif
-#ifdef FEAT_TITLE
-	    if (need_maketitle)
-		maketitle();
+#ifdef MSWIN
+	    /* Remember if the argument was a full path before changing
+	     * slashes to backslashes. */
+	    if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
+		parmp->full_path = TRUE;
 #endif
-	    /* display message after redraw */
-	    if (keep_msg != NULL)
+
+	    /* Add the file to the global argument list. */
+	    if (ga_grow(&global_alist.al_ga, 1) == FAIL
+		    || (p = vim_strsave((char_u *)argv[0])) == NULL)
+		mch_exit(2);
+#ifdef FEAT_DIFF
+	    if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
+				      && !mch_isdir(alist_name(&GARGLIST[0])))
 	    {
-		char_u *p;
+		char_u	    *r;
 
-		/* msg_attr_keep() will set keep_msg to NULL, must free the
-		 * string here. */
-		p = keep_msg;
-		msg_attr(p, keep_msg_attr);
-		vim_free(p);
+		r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
+		if (r != NULL)
+		{
+		    vim_free(p);
+		    p = r;
+		}
 	    }
-	    if (need_fileinfo)		/* show file info after redraw */
+#endif
+#if defined(__CYGWIN32__) && !defined(WIN32)
+	    /*
+	     * If vim is invoked by non-Cygwin tools, convert away any
+	     * DOS paths, so things like .swp files are created correctly.
+	     * Look for evidence of non-Cygwin paths before we bother.
+	     * This is only for when using the Unix files.
+	     */
+	    if (strpbrk(p, "\\:") != NULL)
 	    {
-		fileinfo(FALSE, TRUE, FALSE);
-		need_fileinfo = FALSE;
-	    }
+		char posix_path[PATH_MAX];
 
-	    emsg_on_display = FALSE;	/* can delete error message now */
-	    did_emsg = FALSE;
-	    msg_didany = FALSE;		/* reset lines_left in msg_start() */
-	    showruler(FALSE);
+		cygwin_conv_to_posix_path(p, posix_path);
+		vim_free(p);
+		p = vim_strsave(posix_path);
+		if (p == NULL)
+		    mch_exit(2);
+	    }
+#endif
+	    alist_add(&global_alist, p,
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+		    parmp->literal ? 2 : 0	/* add buffer number after expanding */
+#else
+		    2		/* add buffer number now and use curbuf */
+#endif
+		    );
 
-	    setcursor();
-	    cursor_on();
+#if defined(FEAT_MBYTE) && defined(WIN32)
+	    {
+		extern void used_file_arg(char *, int, int);
 
-	    do_redraw = FALSE;
-	}
-#ifdef FEAT_GUI
-	if (need_mouse_correct)
-	    gui_mouse_correct();
+		/* Remember this argument has been added to the argument list.
+		 * Needed when 'encoding' is changed. */
+		used_file_arg(argv[0], parmp->literal, parmp->full_path);
+	    }
 #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 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 (exmode_active)
+	if (argv_idx <= 0 || argv[0][argv_idx] == NUL)
 	{
-	    if (noexmode)   /* End of ":global/path/visual" commands */
-		return;
-	    do_exmode(exmode_active == EXMODE_VIM);
+	    --argc;
+	    ++argv;
+	    argv_idx = 1;
 	}
-	else
-	    normal_cmd(&oa, TRUE);
     }
 }
 
-
-#if defined(USE_XSMP) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
 /*
- * Exit, but leave behind swap files for modified buffers.
+ * Print a warning if stdout is not a terminal.
+ * When starting in Ex mode and commands come from a file, set Silent mode.
  */
-    void
-getout_preserve_modified(exitval)
-    int		exitval;
+    static void
+check_tty(parmp)
+    mparm_T	*parmp;
 {
-# if defined(SIGHUP) && defined(SIG_IGN)
-    /* Ignore SIGHUP, because a dropped connection causes a read error, which
-     * makes Vim exit and then handling SIGHUP causes various reentrance
-     * problems. */
-    signal(SIGHUP, SIG_IGN);
-# endif
+    int		input_isatty;		/* is active input a terminal? */
 
-    ml_close_notmod();		    /* close all not-modified buffers */
-    ml_sync_all(FALSE, FALSE);	    /* preserve all swap files */
-    ml_close_all(FALSE);	    /* close all memfiles, without deleting */
-    getout(exitval);		    /* exit Vim properly */
-}
+    input_isatty = mch_input_isatty();
+    if (exmode_active)
+    {
+	if (!input_isatty)
+	    silent_mode = TRUE;
+    }
+    else if (parmp->want_full_screen && (!parmp->stdout_isatty || !input_isatty)
+#ifdef FEAT_GUI
+	    /* don't want the delay when started from the desktop */
+	    && !gui.starting
 #endif
-
-
-/* Exit properly */
-    void
-getout(exitval)
-    int		exitval;
-{
-#ifdef FEAT_AUTOCMD
-    buf_T	*buf;
-    win_T	*wp;
+	    )
+    {
+#ifdef NBDEBUG
+	/*
+	 * This shouldn't be necessary. But if I run netbeans with the log
+	 * output coming to the console and XOpenDisplay fails, I get vim
+	 * trying to start with input/output to my console tty.  This fills my
+	 * input buffer so fast I can't even kill the process in under 2
+	 * minutes (and it beeps continuosly the whole time :-)
+	 */
+	if (usingNetbeans && (!parmp->stdout_isatty || !input_isatty))
+	{
+	    mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
+	    exit(1);
+	}
 #endif
+	if (!parmp->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"));
+	out_flush();
+	if (scriptin[0] == NULL)
+	    ui_delay(2000L, TRUE);
+	TIME_MSG("Warning delay");
+    }
+}
 
-    exiting = TRUE;
-
-    /* When running in Ex mode an error causes us to exit with a non-zero exit
-     * code.  POSIX requires this, although it's not 100% clear from the
-     * standard. */
-    if (exmode_active)
-	exitval += ex_exitval;
+/*
+ * Read text from stdin.
+ */
+    static void
+read_stdin()
+{
+    int	    i;
 
-    /* Position the cursor on the last screen line, below all the text */
-#ifdef FEAT_GUI
-    if (!gui.in_use)
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+    /* When getting the ATTENTION prompt here, use a dialog */
+    swap_exists_action = SEA_DIALOG;
 #endif
-	windgoto((int)Rows - 1, 0);
-
-#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
-    /* Optionally print hashtable efficiency. */
-    hash_debug_results();
+    no_wait_return = TRUE;
+    i = msg_didany;
+    set_buflisted(TRUE);
+    (void)open_buffer(TRUE, NULL);	/* create memfile and read file */
+    no_wait_return = FALSE;
+    msg_didany = i;
+    TIME_MSG("reading stdin");
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+    check_swap_exists_action();
 #endif
-
-#ifdef FEAT_GUI
-    msg_didany = FALSE;
+#if !(defined(AMIGA) || defined(MACOS))
+    /*
+     * Close stdin and dup it from stderr.  Required for GPM to work
+     * properly, and for running external commands.
+     * Is there any other system that cannot do this?
+     */
+    close(0);
+    dup(2);
 #endif
+}
 
-#ifdef FEAT_AUTOCMD
-    /* Trigger BufWinLeave for all windows, but only once per buffer. */
-    for (wp = firstwin; wp != NULL; )
+/*
+ * Create the requested number of windows and edit buffers in them.
+ * Also does recovery if "recoverymode" set.
+ */
+/*ARGSUSED*/
+    static void
+create_windows(parmp)
+    mparm_T	*parmp;
+{
+#ifdef FEAT_WINDOWS
+    /*
+     * Create the number of windows that was requested.
+     */
+    if (parmp->window_count == -1)	/* was not set */
+	parmp->window_count = 1;
+    if (parmp->window_count == 0)
+	parmp->window_count = GARGCOUNT;
+    if (parmp->window_count > 1)
     {
-	buf = wp->w_buffer;
-	if (buf->b_changedtick != -1)
+	/* Don't change the windows if there was a command in .vimrc that
+	 * already split some windows */
+	if (parmp->vert_windows == MAYBE)
+	    parmp->vert_windows = FALSE;
+	if (firstwin->w_next == NULL)
 	{
-	    apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
-								  FALSE, buf);
-	    buf->b_changedtick = -1;	/* note that we did it already */
-	    wp = firstwin;		/* restart, window may be closed */
+	    parmp->window_count = make_windows(parmp->window_count,
+							 parmp->vert_windows);
+	    TIME_MSG("making windows");
 	}
 	else
-	    wp = wp->w_next;
+	    parmp->window_count = win_count();
     }
-    /* Trigger BufUnload for buffers that are loaded */
-    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
-	if (buf->b_ml.ml_mfp != NULL)
-	{
-	    apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
-								  FALSE, buf);
-	    if (!buf_valid(buf))	/* autocmd may delete the buffer */
-		break;
-	}
-    apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
-#endif
-
-#ifdef FEAT_VIMINFO
-    if (*p_viminfo != NUL)
-	/* Write out the registers, history, marks etc, to the viminfo file */
-	write_viminfo(NULL, FALSE);
-#endif
-
-#ifdef FEAT_AUTOCMD
-    apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
-#endif
-
-#ifdef FEAT_PROFILE
-    profile_dump();
+    else
+	parmp->window_count = 1;
 #endif
 
-    if (did_emsg
-#ifdef FEAT_GUI
-	    || (gui.in_use && msg_didany && p_verbose > 0)
-#endif
-	    )
+    if (recoverymode)			/* do recover */
     {
-	/* give the user a chance to read the (error) message */
-	no_wait_return = FALSE;
-	wait_return(FALSE);
+	msg_scroll = TRUE;		/* scroll message up */
+	ml_recover();
+	if (curbuf->b_ml.ml_mfp == NULL) /* failed */
+	    getout(1);
+	do_modelines(FALSE);		/* do modelines */
     }
-
+    else
+    {
+	/*
+	 * 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 FEAT_AUTOCMD
-    /* Position the cursor again, the autocommands may have moved it */
-# ifdef FEAT_GUI
-    if (!gui.in_use)
-# endif
-	windgoto((int)Rows - 1, 0);
+	/*
+	 * Don't execute Win/Buf Enter/Leave autocommands here
+	 */
+	++autocmd_no_enter;
+	++autocmd_no_leave;
+#endif
+#ifdef FEAT_WINDOWS
+	for (curwin = firstwin; curwin != NULL; curwin = W_NEXT(curwin))
 #endif
-
-#ifdef FEAT_MZSCHEME
-    mzscheme_end();
+	{
+	    curbuf = curwin->w_buffer;
+	    if (curbuf->b_ml.ml_mfp == NULL)
+	    {
+#ifdef FEAT_FOLDING
+		/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
+		if (p_fdls >= 0)
+		    curwin->w_p_fdl = p_fdls;
 #endif
-#ifdef FEAT_TCL
-    tcl_end();
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+		/* When getting the ATTENTION prompt here, use a dialog */
+		swap_exists_action = SEA_DIALOG;
 #endif
-#ifdef FEAT_RUBY
-    ruby_end();
+		set_buflisted(TRUE);
+		(void)open_buffer(FALSE, NULL); /* create memfile, read file */
+
+#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+		check_swap_exists_action();
 #endif
-#ifdef FEAT_PYTHON
-    python_end();
+#ifdef FEAT_AUTOCMD
+		curwin = firstwin;	    /* start again */
 #endif
-#ifdef FEAT_PERL
-    perl_end();
+	    }
+#ifdef FEAT_WINDOWS
+	    ui_breakcheck();
+	    if (got_int)
+	    {
+		(void)vgetc();	/* only break the file loading, not the rest */
+		break;
+	    }
 #endif
-#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
-    iconv_end();
+	}
+#ifdef FEAT_AUTOCMD
+	--autocmd_no_enter;
+	--autocmd_no_leave;
 #endif
-#ifdef FEAT_NETBEANS_INTG
-    netbeans_end();
+#ifdef FEAT_WINDOWS
+	curwin = firstwin;
+	curbuf = curwin->w_buffer;
 #endif
-
-    mch_exit(exitval);
-}
-
-/*
- * 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 (vim_isdigit(p[*idx]))
-    {
-	def = atoi((char *)&(p[*idx]));
-	while (vim_isdigit(p[*idx]))
-	    *idx = *idx + 1;
     }
-    return def;
 }
 
-/*
- * Get the name of the display, before gui_prepare() removes it from
- * argv[].  Used for the xterm-clipboard display.
- *
- * Also find the --server... arguments and --socketid
- */
-/*ARGSUSED*/
+#ifdef FEAT_WINDOWS
+    /*
+     * If opened more than one window, start editing files in the other
+     * windows.  make_windows() has already opened the windows.
+     */
     static void
-early_arg_scan(argc, argv, parmp)
-    int		argc;
-    char	**argv;
+edit_buffers(parmp)
     mparm_T	*parmp;
 {
-#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER)
+    int		arg_idx;		/* index in argument list */
     int		i;
 
-    for (i = 1; i < argc; i++)
+# ifdef FEAT_AUTOCMD
+    /*
+     * Don't execute Win/Buf Enter/Leave autocommands here
+     */
+    ++autocmd_no_enter;
+    ++autocmd_no_leave;
+# endif
+    arg_idx = 1;
+    for (i = 1; i < parmp->window_count; ++i)
     {
-	if (STRCMP(argv[i], "--") == 0)
+	if (curwin->w_next == NULL)	    /* just checking */
 	    break;
-# ifdef FEAT_XCLIPBOARD
-	else if (STRICMP(argv[i], "-display") == 0
-#  if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
-		|| STRICMP(argv[i], "--display") == 0
-#  endif
-		)
-	{
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    xterm_display = argv[++i];
-	}
-# endif
-# ifdef FEAT_CLIENTSERVER
-	else if (STRICMP(argv[i], "--servername") == 0)
+	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)
 	{
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    parmp->serverName_arg = (char_u *)argv[++i];
+	    curwin->w_arg_idx = arg_idx;
+	    /* edit file from arg list, if there is one */
+	    (void)do_ecmd(0, arg_idx < GARGCOUNT
+			  ? alist_name(&GARGLIST[arg_idx]) : NULL,
+			  NULL, NULL, ECMD_LASTL, ECMD_HIDE);
+	    if (arg_idx == GARGCOUNT - 1)
+		arg_had_last = TRUE;
+	    ++arg_idx;
 	}
-	else if (STRICMP(argv[i], "--serverlist") == 0
-		|| STRICMP(argv[i], "--remote-send") == 0
-		|| STRICMP(argv[i], "--remote-expr") == 0
-		|| STRICMP(argv[i], "--remote") == 0
-		|| STRICMP(argv[i], "--remote-silent") == 0)
-	    parmp->serverArg = TRUE;
-	else if (STRICMP(argv[i], "--remote-wait") == 0
-		|| STRICMP(argv[i], "--remote-wait-silent") == 0)
+	ui_breakcheck();
+	if (got_int)
 	{
-	    parmp->serverArg = TRUE;
-#ifdef FEAT_GUI
-	    /* don't fork() when starting the GUI to edit the files ourself */
-	    gui.dofork = FALSE;
-#endif
+	    (void)vgetc();	/* only break the file loading, not the rest */
+	    break;
 	}
+    }
+# ifdef FEAT_AUTOCMD
+    --autocmd_no_enter;
 # endif
-# ifdef FEAT_GUI_GTK
-	else if (STRICMP(argv[i], "--socketid") == 0)
-	{
-	    unsigned int    socket_id;
-	    int		    count;
-
-	    if (i == argc - 1)
-		mainerr_arg_missing((char_u *)argv[i]);
-	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
-		count = sscanf(&(argv[i + 1][2]), "%x", &socket_id);
-	    else
-		count = sscanf(argv[i+1], "%u", &socket_id);
-	    if (count != 1)
-		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
-	    else
-		gtk_socket_id = socket_id;
-	    i++;
-	}
-	else if (STRICMP(argv[i], "--echo-wid") == 0)
-	    echo_wid_arg = TRUE;
+    win_enter(firstwin, FALSE);		/* back to first window */
+# ifdef FEAT_AUTOCMD
+    --autocmd_no_leave;
 # endif
-    }
-#endif
+    TIME_MSG("editing files in windows");
+    if (parmp->window_count > 1)
+	win_equal(curwin, FALSE, 'b');	/* adjust heights */
 }
+#endif /* FEAT_WINDOWS */
 
 /*
  * Execute the commands from --cmd arguments "cmds[cnt]".
  */
     static void
-exe_pre_commands(cmds, cnt)
-    char_u	**cmds;
-    int		cnt;
+exe_pre_commands(parmp)
+    mparm_T	*parmp;
 {
+    char_u	**cmds = parmp->pre_commands;
+    int		cnt = parmp->n_pre_commands;
     int		i;
 
     if (cnt > 0)
@@ -2327,6 +2355,51 @@ exe_pre_commands(cmds, cnt)
     }
 }
 
+/*
+ * Execute "+", "-c" and "-S" arguments.
+ */
+    static void
+exe_commands(parmp)
+    mparm_T	*parmp;
+{
+    int		i;
+
+    /*
+     * We start commands on line 0, make "vim +/pat file" match a
+     * pattern on line 1.  But don't move the cursor when an autocommand
+     * with g`" was used.
+     */
+    msg_scroll = TRUE;
+    if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
+	curwin->w_cursor.lnum = 0;
+    sourcing_name = (char_u *)"command line";
+#ifdef FEAT_EVAL
+    current_SID = SID_CARG;
+#endif
+    for (i = 0; i < parmp->n_commands; ++i)
+    {
+	do_cmdline_cmd(parmp->commands[i]);
+	if (parmp->cmds_tofree[i])
+	    vim_free(parmp->commands[i]);
+    }
+    sourcing_name = NULL;
+#ifdef FEAT_EVAL
+    current_SID = 0;
+#endif
+    if (curwin->w_cursor.lnum == 0)
+	curwin->w_cursor.lnum = 1;
+
+    if (!exmode_active)
+	msg_scroll = FALSE;
+
+#ifdef FEAT_QUICKFIX
+    /* When started with "-q errorfile" jump to first error again. */
+    if (parmp->edit_type == EDIT_QF)
+	qf_jump(0, 0, FALSE);
+#endif
+    TIME_MSG("executing command arguments");
+}
+
 /*
  * Source startup scripts.
  */
@@ -2347,7 +2420,7 @@ source_startup_scripts(parmp)
     }
 
     /*
-     * If -u option given, use only the initializations from that file and
+     * If -u argument given, use only the initializations from that file and
      * nothing else.
      */
     if (parmp->use_vimrc != NULL)
@@ -2930,6 +3003,90 @@ gettimeofday(struct timeval *tv, char *dummy)
 
 static char_u *build_drop_cmd __ARGS((int filec, char **filev, int sendReply));
 
+/*
+ * Do the client-server stuff, unless "--servername ''" was used.
+ */
+    static void
+exec_on_server(parmp)
+    mparm_T	*parmp;
+{
+    if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL)
+    {
+# ifdef WIN32
+	/* Initialise the client/server messaging infrastructure. */
+	serverInitMessaging();
+# endif
+
+	/*
+	 * When a command server argument was found, execute it.  This may
+	 * exit Vim when it was successful.  Otherwise it's executed further
+	 * on.  Remember the encoding used here in "serverStrEnc".
+	 */
+	if (parmp->serverArg)
+	{
+	    cmdsrv_main(&parmp->argc, parmp->argv,
+				    parmp->serverName_arg, &parmp->serverStr);
+# ifdef FEAT_MBYTE
+	    parmp->serverStrEnc = vim_strsave(p_enc);
+# endif
+	}
+
+	/* If we're still running, get the name to register ourselves.
+	 * On Win32 can register right now, for X11 need to setup the
+	 * clipboard first, it's further down. */
+	parmp->servername = serverMakeName(parmp->serverName_arg,
+							      parmp->argv[0]);
+# ifdef WIN32
+	if (parmp->servername != NULL)
+	{
+	    serverSetName(parmp->servername);
+	    vim_free(parmp->servername);
+	}
+# endif
+    }
+}
+
+/*
+ * Prepare for running as a Vim server.
+ */
+    static void
+prepare_server(parmp)
+    mparm_T	*parmp;
+{
+# if defined(FEAT_X11)
+    /*
+     * Register for remote command execution with :serversend and --remote
+     * unless there was a -X or a --servername '' on the command line.
+     * Only register nongui-vim's with an explicit --servername argument.
+     */
+    if (X_DISPLAY != NULL && parmp->servername != NULL && (
+#  ifdef FEAT_GUI
+		gui.in_use ||
+#  endif
+		parmp->serverName_arg != NULL))
+    {
+	(void)serverRegisterName(X_DISPLAY, parmp->servername);
+	vim_free(parmp->servername);
+	TIME_MSG("register server name");
+    }
+    else
+	serverDelayedStartName = parmp->servername;
+# endif
+
+    /*
+     * Execute command ourselves if we're here because the send failed (or
+     * else we would have exited above).
+     */
+    if (parmp->serverStr != NULL)
+    {
+	char_u *p;
+
+	server_to_input_buf(serverConvert(parmp->serverStrEnc,
+						       parmp->serverStr, &p));
+	vim_free(p);
+    }
+}
+
     static void
 cmdsrv_main(argc, argv, serverName_arg, serverStr)
     int		*argc;
@@ -2971,7 +3128,7 @@ cmdsrv_main(argc, argv, serverName_arg, serverStr)
     for (i = 1; i < Argc; i++)
     {
 	res = NULL;
-	if (STRCMP(argv[i], "--") == 0)	/* end of options */
+	if (STRCMP(argv[i], "--") == 0)	/* end of option arguments */
 	{
 	    for (; i < *argc; i++)
 	    {