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