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