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