blob: a57b196cf7e16cdeeaa70fc9fcde5abde7622fe7 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002 *
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
Bram Moolenaarb4210b32004-06-13 14:51:16 +000010#define EXTERN
11#include "vim.h"
12
Bram Moolenaarb4210b32004-06-13 14:51:16 +000013#ifdef __CYGWIN__
Bram Moolenaar4f974752019-02-17 17:44:42 +010014# ifndef MSWIN
Bram Moolenaar0d1498e2008-06-29 12:00:49 +000015# include <cygwin/version.h>
16# include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() and/or
17 * cygwin_conv_path() */
Bram Moolenaarb4210b32004-06-13 14:51:16 +000018# endif
19# include <limits.h>
20#endif
21
Bram Moolenaarafde13b2019-04-28 19:46:49 +020022#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
Bram Moolenaar97ff9b92016-06-26 20:37:46 +020023# include "iscygpty.h"
24#endif
25
Bram Moolenaarc013cb62005-07-24 21:18:31 +000026/* 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
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010033#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010034static int file_owned(char *fname);
Bram Moolenaarb4210b32004-06-13 14:51:16 +000035#endif
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010036static void mainerr(int, char_u *);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +020037# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
38static void init_locale(void);
39# endif
40static void early_arg_scan(mparm_T *parmp);
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010041#ifndef NO_VIM_MAIN
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010042static void usage(void);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010043static void parse_command_name(mparm_T *parmp);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010044static void command_line_scan(mparm_T *parmp);
45static void check_tty(mparm_T *parmp);
46static void read_stdin(void);
47static void create_windows(mparm_T *parmp);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010048static void edit_buffers(mparm_T *parmp, char_u *cwd);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010049static void exe_pre_commands(mparm_T *parmp);
50static void exe_commands(mparm_T *parmp);
51static void source_startup_scripts(mparm_T *parmp);
52static void main_start_gui(void);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010053static void check_swap_exists_action(void);
Bram Moolenaar08cab962017-03-04 14:37:18 +010054# ifdef FEAT_EVAL
55static void set_progpath(char_u *argv0);
56# endif
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010057# if defined(FEAT_CLIENTSERVER) || defined(PROTO)
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010058static void exec_on_server(mparm_T *parmp);
59static void prepare_server(mparm_T *parmp);
60static void cmdsrv_main(int *argc, char **argv, char_u *serverName_arg, char_u **serverStr);
61static char_u *serverMakeName(char_u *arg, char *cmd);
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010062# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +000063#endif
64
65
Bram Moolenaarb4210b32004-06-13 14:51:16 +000066/*
67 * Different types of error messages.
68 */
69static char *(main_errors[]) =
70{
Bram Moolenaarc013cb62005-07-24 21:18:31 +000071 N_("Unknown option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +000072#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
Bram Moolenaarc013cb62005-07-24 21:18:31 +000077 N_("Garbage after option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +000078#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
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010085#ifndef PROTO /* don't want a prototype for main() */
Bram Moolenaara6044292017-04-02 18:19:53 +020086
87/* Various parameters passed between main() and other functions. */
88static mparm_T params;
89
Bram Moolenaar8866d272012-11-28 15:55:42 +010090#ifndef NO_VIM_MAIN /* skip this for unittests */
Bram Moolenaarf9bde2b2015-04-17 22:08:16 +020091
92static char_u *start_dir = NULL; /* current working dir on startup */
93
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +020094static int has_dash_c_arg = FALSE;
95
Bram Moolenaarafde13b2019-04-28 19:46:49 +020096# ifdef VIMDLL
97__declspec(dllexport)
98# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +000099 int
Bram Moolenaar796cc422019-04-03 20:31:00 +0200100# ifdef MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000101# ifdef __BORLANDC__
102_cdecl
103# endif
104VimMain
105# else
106main
107# endif
Bram Moolenaar52ea13d2016-01-30 18:51:09 +0100108(int argc, char **argv)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000109{
Bram Moolenaar77780b62018-03-01 23:10:45 +0100110#if defined(STARTUPTIME) || defined(CLEAN_RUNTIMEPATH)
Bram Moolenaar3f269672009-11-03 11:11:11 +0000111 int i;
112#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000113
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000114 /*
115 * Do any system-specific initialisations. These can NOT use IObuff or
116 * NameBuff. Thus emsg2() cannot be called!
117 */
118 mch_early_init();
119
Bram Moolenaar4f974752019-02-17 17:44:42 +0100120#ifdef MSWIN
Bram Moolenaar14993322014-09-09 12:25:33 +0200121 /*
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200122 * MinGW expands command line arguments, which confuses our code to
Bram Moolenaar14993322014-09-09 12:25:33 +0200123 * convert when 'encoding' changes. Get the unexpanded arguments.
124 */
125 argc = get_cmd_argsW(&argv);
126#endif
127
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000128 /* Many variables are in "params" so that we can pass them to invoked
129 * functions without a lot of arguments. "argc" and "argv" are also
130 * copied, so that they can be changed. */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000131 vim_memset(&params, 0, sizeof(params));
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000132 params.argc = argc;
133 params.argv = argv;
134 params.want_full_screen = TRUE;
135#ifdef FEAT_EVAL
136 params.use_debug_break_level = -1;
137#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000138 params.window_count = -1;
Bram Moolenaar58d98232005-07-23 22:25:46 +0000139
Bram Moolenaar99685e62013-05-11 13:56:18 +0200140#ifdef FEAT_RUBY
141 {
142 int ruby_stack_start;
143 vim_ruby_init((void *)&ruby_stack_start);
144 }
145#endif
146
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000147#ifdef FEAT_TCL
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000148 vim_tcl_init(params.argv[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000149#endif
150
151#ifdef MEM_PROFILE
152 atexit(vim_mem_profile_dump);
153#endif
154
155#ifdef STARTUPTIME
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200156 /* Need to find "--startuptime" before actually parsing arguments. */
Bram Moolenaar07268702018-03-01 21:57:32 +0100157 for (i = 1; i < argc - 1; ++i)
158 if (STRICMP(argv[i], "--startuptime") == 0)
Bram Moolenaar3f269672009-11-03 11:11:11 +0000159 {
Bram Moolenaaref94eec2009-11-11 13:22:11 +0000160 time_fd = mch_fopen(argv[i + 1], "a");
Bram Moolenaar3f269672009-11-03 11:11:11 +0000161 TIME_MSG("--- VIM STARTING ---");
162 break;
163 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000164#endif
Bram Moolenaarca003e12006-03-17 23:19:38 +0000165 starttime = time(NULL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000166
Bram Moolenaar07268702018-03-01 21:57:32 +0100167#ifdef CLEAN_RUNTIMEPATH
168 /* Need to find "--clean" before actually parsing arguments. */
169 for (i = 1; i < argc; ++i)
170 if (STRICMP(argv[i], "--clean") == 0)
171 {
172 params.clean = TRUE;
173 break;
174 }
175#endif
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200176 common_init(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000177
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200178#ifdef VIMDLL
179 // Check if the current executable file is for the GUI subsystem.
180 gui.starting = mch_is_gui_executable();
181#endif
182
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000183#ifdef FEAT_CLIENTSERVER
184 /*
185 * Do the client-server stuff, unless "--servername ''" was used.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000186 * This may exit Vim if the command was sent to the server.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000187 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000188 exec_on_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000189#endif
190
191 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000192 * Figure out the way to work from the command name argv[0].
193 * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000194 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000195 parse_command_name(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000196
197 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000198 * Process the command line arguments. File names are put in the global
199 * argument list "global_alist".
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000200 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000201 command_line_scan(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000202 TIME_MSG("parsing arguments");
203
204 /*
205 * On some systems, when we compile with the GUI, we always use it. On Mac
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000206 * there is no terminal version, and on Windows we can't fork one off with
207 * :gui.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000208 */
209#ifdef ALWAYS_USE_GUI
210 gui.starting = TRUE;
211#else
Bram Moolenaar241a8aa2005-12-06 20:04:44 +0000212# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000213 /*
214 * Check if the GUI can be started. Reset gui.starting if not.
215 * Don't know about other systems, stay on the safe side and don't check.
216 */
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000217 if (gui.starting)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000218 {
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000219 if (gui_init_check() == FAIL)
220 {
221 gui.starting = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000222
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000223 /* When running "evim" or "gvim -y" we need the menus, exit if we
224 * don't have them. */
225 if (params.evim_mode)
226 mch_exit(1);
227 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000228 }
229# endif
230#endif
231
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000232 if (GARGCOUNT > 0)
233 {
Bram Moolenaar53076832015-12-31 19:53:21 +0100234#ifdef EXPAND_FILENAMES
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000235 /*
236 * Expand wildcards in file names.
237 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000238 if (!params.literal)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000239 {
Bram Moolenaarf6303872015-04-03 17:59:43 +0200240 start_dir = alloc(MAXPATHL);
241 if (start_dir != NULL)
242 mch_dirname(start_dir, MAXPATHL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000243 /* Temporarily add '(' and ')' to 'isfname'. These are valid
244 * filename characters but are excluded from 'isfname' to make
245 * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
246 do_cmdline_cmd((char_u *)":set isf+=(,)");
Bram Moolenaar86b68352004-12-27 21:59:20 +0000247 alist_expand(NULL, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000248 do_cmdline_cmd((char_u *)":set isf&");
Bram Moolenaarf6303872015-04-03 17:59:43 +0200249 if (start_dir != NULL)
250 mch_chdir((char *)start_dir);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000251 }
252#endif
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200253 params.fname = alist_name(&GARGLIST[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000254 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000255
Bram Moolenaar4f974752019-02-17 17:44:42 +0100256#ifdef MSWIN
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000257 {
258 extern void set_alist_count(void);
259
260 /* Remember the number of entries in the argument list. If it changes
261 * we don't react on setting 'encoding'. */
262 set_alist_count();
263 }
264#endif
265
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000266#ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000267 if (GARGCOUNT == 1 && params.full_path)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000268 {
269 /*
270 * If there is one filename, fully qualified, we have very probably
271 * been invoked from explorer, so change to the file's directory.
272 * Hint: to avoid this when typing a command use a forward slash.
273 * If the cd fails, it doesn't matter.
274 */
Bram Moolenaarb7407d32018-02-03 17:36:27 +0100275 (void)vim_chdirfile(params.fname, "drop");
Bram Moolenaarf6303872015-04-03 17:59:43 +0200276 if (start_dir != NULL)
277 mch_dirname(start_dir, MAXPATHL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000278 }
279#endif
280 TIME_MSG("expanding arguments");
281
282#ifdef FEAT_DIFF
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000283 if (params.diff_mode && params.window_count == -1)
284 params.window_count = 0; /* open up to 3 windows */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000285#endif
286
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000287 /* Don't redraw until much later. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000288 ++RedrawingDisabled;
289
290 /*
291 * When listing swap file names, don't do cursor positioning et. al.
292 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200293 if (recoverymode && params.fname == NULL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000294 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000295
296 /*
297 * When certain to start the GUI, don't check capabilities of terminal.
298 * For GTK we can't be sure, but when started from the desktop it doesn't
299 * make sense to try using a terminal.
300 */
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200301#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \
302 || defined(VIMDLL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000303 if (gui.starting
304# ifdef FEAT_GUI_GTK
305 && !isatty(2)
306# endif
307 )
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000308 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000309#endif
310
Bram Moolenaard0573012017-10-28 21:11:06 +0200311#if defined(FEAT_GUI_MAC) && defined(MACOS_X_DARWIN)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000312 /* When the GUI is started from Finder, need to display messages in a
313 * message box. isatty(2) returns TRUE anyway, thus we need to check the
314 * name to know we're not started from a terminal. */
315 if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))
Bram Moolenaard2cec5b2006-03-28 21:08:56 +0000316 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000317 params.want_full_screen = FALSE;
Bram Moolenaard2cec5b2006-03-28 21:08:56 +0000318
319 /* Avoid always using "/" as the current directory. Note that when
320 * started from Finder the arglist will be filled later in
321 * HandleODocAE() and "fname" will be NULL. */
322 if (getcwd((char *)NameBuff, MAXPATHL) != NULL
323 && STRCMP(NameBuff, "/") == 0)
324 {
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200325 if (params.fname != NULL)
Bram Moolenaarb7407d32018-02-03 17:36:27 +0100326 (void)vim_chdirfile(params.fname, "drop");
Bram Moolenaard2cec5b2006-03-28 21:08:56 +0000327 else
328 {
329 expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
330 vim_chdir(NameBuff);
331 }
Bram Moolenaarf6303872015-04-03 17:59:43 +0200332 if (start_dir != NULL)
333 mch_dirname(start_dir, MAXPATHL);
Bram Moolenaard2cec5b2006-03-28 21:08:56 +0000334 }
335 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000336#endif
337
338 /*
339 * mch_init() sets up the terminal (window) for use. This must be
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100340 * done after resetting full_screen, otherwise it may move the cursor.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000341 * Note that we may use mch_exit() before mch_init()!
342 */
343 mch_init();
344 TIME_MSG("shell init");
345
346#ifdef USE_XSMP
347 /*
348 * For want of anywhere else to do it, try to connect to xsmp here.
349 * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
350 * Hijacking -X 'no X connection' to also disable XSMP connection as that
351 * has a similar delay upon failure.
352 * Only try if SESSION_MANAGER is set to something non-null.
353 */
354 if (!x_no_connect)
355 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000356 char *p = getenv("SESSION_MANAGER");
357
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000358 if (p != NULL && *p != NUL)
359 {
360 xsmp_init();
361 TIME_MSG("xsmp init");
362 }
363 }
364#endif
365
366 /*
367 * Print a warning if stdout is not a terminal.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000368 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000369 check_tty(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000370
Bram Moolenaar42b23fa2018-02-03 14:46:45 +0100371#ifdef _IOLBF
372 /* Ensure output works usefully without a tty: buffer lines instead of
373 * fully buffered. */
374 if (silent_mode)
375 setvbuf(stdout, NULL, _IOLBF, 0);
376#endif
377
Bram Moolenaar9404a182019-05-03 22:25:40 +0200378 // This message comes before term inits, but after setting "silent_mode"
379 // when the input is not a tty. Omit the message with --not-a-term.
380 if (GARGCOUNT > 1 && !silent_mode && !is_not_a_term())
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000381 printf(_("%d files to edit\n"), GARGCOUNT);
382
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000383 if (params.want_full_screen && !silent_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000384 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000385 termcapinit(params.term); /* set terminal name and get terminal
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000386 capabilities (will set full_screen) */
387 screen_start(); /* don't know where cursor is now */
388 TIME_MSG("Termcap init");
389 }
390
391 /*
392 * Set the default values for the options that use Rows and Columns.
393 */
394 ui_get_shellsize(); /* inits Rows and Columns */
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000395 win_init_size();
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000396#ifdef FEAT_DIFF
397 /* Set the 'diff' option now, so that it can be checked for in a .vimrc
398 * file. There is no buffer yet though. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000399 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000400 diff_win_options(firstwin, FALSE);
401#endif
402
403 cmdline_row = Rows - p_ch;
404 msg_row = cmdline_row;
405 screenalloc(FALSE); /* allocate screen buffers */
406 set_init_2();
407 TIME_MSG("inits 2");
408
409 msg_scroll = TRUE;
410 no_wait_return = TRUE;
411
412 init_mappings(); /* set up initial mappings */
413
414 init_highlight(TRUE, FALSE); /* set the default highlight groups */
415 TIME_MSG("init highlight");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000416
417#ifdef FEAT_EVAL
418 /* Set the break level after the terminal is initialized. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000419 debug_break_level = params.use_debug_break_level;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000420#endif
421
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200422 /* Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
423 * Allows for setting 'loadplugins' there. */
424 if (params.use_vimrc != NULL
425 && (STRCMP(params.use_vimrc, "NONE") == 0
426 || STRCMP(params.use_vimrc, "DEFAULTS") == 0))
427 p_lpl = FALSE;
428
429 /* Execute --cmd arguments. */
430 exe_pre_commands(&params);
431
432 /* Source startup scripts. */
433 source_startup_scripts(&params);
434
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100435#ifdef FEAT_MZSCHEME
436 /*
437 * Newer version of MzScheme (Racket) require earlier (trampolined)
438 * initialisation via scheme_main_setup.
439 * Implement this by initialising it as early as possible
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200440 * and splitting off remaining Vim main into vim_main2().
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200441 * Do source startup scripts, so that 'mzschemedll' can be set.
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100442 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200443 return mzscheme_main();
444#else
445 return vim_main2();
Bram Moolenaar8866d272012-11-28 15:55:42 +0100446#endif
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200447}
Bram Moolenaar8866d272012-11-28 15:55:42 +0100448#endif /* NO_VIM_MAIN */
Bram Moolenaara357e442016-08-10 20:45:07 +0200449#endif /* PROTO */
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100450
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200451/*
452 * vim_main2() is needed for FEAT_MZSCHEME, but we define it always to keep
453 * things simple.
454 * It is also defined when NO_VIM_MAIN is defined, but then it's empty.
455 */
Bram Moolenaar8866d272012-11-28 15:55:42 +0100456 int
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200457vim_main2(void)
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100458{
Bram Moolenaar8866d272012-11-28 15:55:42 +0100459#ifndef NO_VIM_MAIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000460#ifdef FEAT_EVAL
461 /*
462 * Read all the plugin files.
463 * Only when compiled with +eval, since most plugins need it.
464 */
465 if (p_lpl)
466 {
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200467 char_u *rtp_copy = NULL;
468
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200469 /* First add all package directories to 'runtimepath', so that their
470 * autoload directories can be found. Only if not done already with a
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200471 * :packloadall command.
472 * Make a copy of 'runtimepath', so that source_runtime does not use
473 * the pack directories. */
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200474 if (!did_source_packages)
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200475 {
476 rtp_copy = vim_strsave(p_rtp);
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200477 add_pack_start_dirs();
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200478 }
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200479
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200480 source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy,
Bram Moolenaarc1cb78c2006-06-20 16:51:47 +0000481# ifdef VMS /* Somehow VMS doesn't handle the "**". */
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200482 (char_u *)"plugin/*.vim",
Bram Moolenaarc1cb78c2006-06-20 16:51:47 +0000483# else
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200484 (char_u *)"plugin/**/*.vim",
Bram Moolenaarc1cb78c2006-06-20 16:51:47 +0000485# endif
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200486 DIP_ALL | DIP_NOAFTER);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000487 TIME_MSG("loading plugins");
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200488 vim_free(rtp_copy);
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +0100489
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200490 /* Only source "start" packages if not done already with a :packloadall
491 * command. */
492 if (!did_source_packages)
493 load_start_packages();
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +0100494 TIME_MSG("loading packages");
Bram Moolenaar66459b72016-08-06 19:01:55 +0200495
496# ifdef VMS /* Somehow VMS doesn't handle the "**". */
497 source_runtime((char_u *)"plugin/*.vim", DIP_ALL | DIP_AFTER);
498# else
499 source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER);
500# endif
501 TIME_MSG("loading after plugins");
502
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000503 }
504#endif
505
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000506#ifdef FEAT_DIFF
507 /* Decide about window layout for diff mode after reading vimrc. */
508 if (params.diff_mode && params.window_layout == 0)
509 {
510 if (diffopt_horizontal())
511 params.window_layout = WIN_HOR; /* use horizontal split */
512 else
513 params.window_layout = WIN_VER; /* use vertical split */
514 }
515#endif
516
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000517 /*
518 * Recovery mode without a file name: List swap files.
519 * This uses the 'dir' option, therefore it must be after the
520 * initializations.
521 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200522 if (recoverymode && params.fname == NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000523 {
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +0200524 recover_names(NULL, TRUE, 0, NULL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000525 mch_exit(0);
526 }
527
528 /*
529 * Set a few option defaults after reading .vimrc files:
530 * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
531 */
532 set_init_3();
533 TIME_MSG("inits 3");
534
535 /*
536 * "-n" argument: Disable swap file by setting 'updatecount' to 0.
537 * Note that this overrides anything from a vimrc file.
538 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000539 if (params.no_swap_file)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000540 p_uc = 0;
541
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000542#ifdef FEAT_GUI
543 if (gui.starting)
544 {
545#if defined(UNIX) || defined(VMS)
546 /* When something caused a message from a vimrc script, need to output
547 * an extra newline before the shell prompt. */
548 if (did_emsg || msg_didout)
549 putchar('\n');
550#endif
551
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200552 gui_start(NULL); /* will set full_screen to TRUE */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000553 TIME_MSG("starting GUI");
554
555 /* When running "evim" or "gvim -y" we need the menus, exit if we
556 * don't have them. */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000557 if (!gui.in_use && params.evim_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000558 mch_exit(1);
559 }
560#endif
561
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000562#ifdef FEAT_VIMINFO
563 /*
Bram Moolenaard812df62008-11-09 12:46:09 +0000564 * Read in registers, history etc, but not marks, from the viminfo file.
565 * This is where v:oldfiles gets filled.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000566 */
567 if (*p_viminfo != NUL)
568 {
Bram Moolenaard812df62008-11-09 12:46:09 +0000569 read_viminfo(NULL, VIF_WANT_INFO | VIF_GET_OLDFILES);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000570 TIME_MSG("reading viminfo");
571 }
572#endif
Bram Moolenaar2cd36962014-01-14 12:57:05 +0100573#ifdef FEAT_EVAL
574 /* It's better to make v:oldfiles an empty list than NULL. */
575 if (get_vim_var_list(VV_OLDFILES) == NULL)
576 set_vim_var_list(VV_OLDFILES, list_alloc());
577#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000578
579#ifdef FEAT_QUICKFIX
580 /*
581 * "-q errorfile": Load the error file now.
582 * If the error file can't be read, exit before doing anything else.
583 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000584 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000585 {
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100586 char_u *enc = NULL;
587
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100588 enc = p_menc;
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000589 if (params.use_ef != NULL)
590 set_string_option_direct((char_u *)"ef", -1,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000591 params.use_ef, OPT_FREE, SID_CARG);
Bram Moolenaar7fd73202010-07-25 16:58:46 +0200592 vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100593 if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff, enc) < 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000594 {
595 out_char('\n');
596 mch_exit(3);
597 }
598 TIME_MSG("reading errorfile");
599 }
600#endif
601
602 /*
603 * Start putting things on the screen.
604 * Scroll screen down before drawing over it
605 * Clear screen now, so file message will not be cleared.
606 */
607 starting = NO_BUFFERS;
608 no_wait_return = FALSE;
609 if (!exmode_active)
610 msg_scroll = FALSE;
611
612#ifdef FEAT_GUI
613 /*
614 * This seems to be required to make callbacks to be called now, instead
615 * of after things have been put on the screen, which then may be deleted
616 * when getting a resize callback.
617 * For the Mac this handles putting files dropped on the Vim icon to
618 * global_alist.
619 */
620 if (gui.in_use)
621 {
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100622 gui_wait_for_chars(50L, typebuf.tb_change_cnt);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000623 TIME_MSG("GUI delay");
624 }
625#endif
626
627#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
628 qnx_clip_init();
629#endif
630
Bram Moolenaarc8bbaa32010-07-14 16:54:21 +0200631#if defined(MACOS_X) && defined(FEAT_CLIPBOARD)
632 clip_init(TRUE);
633#endif
634
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000635#ifdef FEAT_XCLIPBOARD
636 /* Start using the X clipboard, unless the GUI was started. */
637# ifdef FEAT_GUI
638 if (!gui.in_use)
639# endif
640 {
641 setup_term_clip();
642 TIME_MSG("setup clipboard");
643 }
644#endif
645
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000646#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000647 /* Prepare for being a Vim server. */
648 prepare_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000649#endif
650
651 /*
652 * If "-" argument given: Read file from stdin.
653 * Do this before starting Raw mode, because it may change things that the
654 * writing end of the pipe doesn't like, e.g., in case stdin and stderr
655 * are the same terminal: "cat | vim -".
656 * Using autocommands here may cause trouble...
657 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000658 if (params.edit_type == EDIT_STDIN && !recoverymode)
659 read_stdin();
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000660
661#if defined(UNIX) || defined(VMS)
662 /* When switching screens and something caused a message from a vimrc
663 * script, need to output an extra newline on exit. */
664 if ((did_emsg || msg_didout) && *T_TI != NUL)
665 newline_on_exit = TRUE;
666#endif
667
668 /*
669 * When done something that is not allowed or error message call
670 * wait_return. This must be done before starttermcap(), because it may
671 * switch to another screen. It must be done after settmode(TMODE_RAW),
672 * because we want to react on a single key stroke.
673 * Call settmode and starttermcap here, so the T_KS and T_TI may be
Bram Moolenaar49325942007-05-10 19:19:59 +0000674 * defined by termcapinit and redefined in .exrc.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000675 */
676 settmode(TMODE_RAW);
677 TIME_MSG("setting raw mode");
678
679 if (need_wait_return || msg_didany)
680 {
681 wait_return(TRUE);
682 TIME_MSG("waiting for return");
683 }
684
685 starttermcap(); /* start termcap if not done by wait_return() */
686 TIME_MSG("start termcap");
687
688#ifdef FEAT_MOUSE
689 setmouse(); /* may start using the mouse */
690#endif
691 if (scroll_region)
692 scroll_region_reset(); /* In case Rows changed */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000693 scroll_start(); /* may scroll the screen to the right position */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000694
Bram Moolenaar980bab42018-08-07 22:42:53 +0200695#if defined(FEAT_TITLE) && (defined(UNIX) || defined(VMS) || defined(MACOS_X))
Bram Moolenaar40385db2018-08-07 22:31:44 +0200696 term_push_title(SAVE_RESTORE_BOTH);
697#endif
698
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000699 /*
700 * Don't clear the screen when starting in Ex mode, unless using the GUI.
701 */
702 if (exmode_active
703#ifdef FEAT_GUI
704 && !gui.in_use
705#endif
706 )
707 must_redraw = CLEAR;
708 else
709 {
710 screenclear(); /* clear screen */
711 TIME_MSG("clearing screen");
712 }
713
714#ifdef FEAT_CRYPT
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000715 if (params.ask_for_key)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000716 {
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100717 crypt_check_current_method();
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200718 (void)crypt_get_key(TRUE, TRUE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000719 TIME_MSG("getting crypt key");
720 }
721#endif
722
723 no_wait_return = TRUE;
724
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000725 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000726 * Create the requested number of windows and edit buffers in them.
727 * Also does recovery if "recoverymode" set.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000728 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000729 create_windows(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000730 TIME_MSG("opening buffers");
731
Bram Moolenaar867a4b72007-03-18 20:51:46 +0000732#ifdef FEAT_EVAL
733 /* clear v:swapcommand */
734 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
735#endif
736
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000737 /* Ex starts at last line of the file */
738 if (exmode_active)
739 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
740
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000741 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
742 TIME_MSG("BufEnter autocommands");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000743 setpcmark();
744
745#ifdef FEAT_QUICKFIX
746 /*
747 * When started with "-q errorfile" jump to first error now.
748 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000749 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000750 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000751 qf_jump(NULL, 0, 0, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000752 TIME_MSG("jump to first error");
753 }
754#endif
755
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000756 /*
757 * If opened more than one window, start editing files in the other
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000758 * windows.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000759 */
Bram Moolenaarf6303872015-04-03 17:59:43 +0200760 edit_buffers(&params, start_dir);
Bram Moolenaarf6303872015-04-03 17:59:43 +0200761 vim_free(start_dir);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000762
763#ifdef FEAT_DIFF
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000764 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000765 {
766 win_T *wp;
767
768 /* set options in each window for "vimdiff". */
Bram Moolenaar29323592016-07-24 22:04:11 +0200769 FOR_ALL_WINDOWS(wp)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000770 diff_win_options(wp, TRUE);
771 }
772#endif
773
774 /*
775 * Shorten any of the filenames, but only when absolute.
776 */
777 shorten_fnames(FALSE);
778
779 /*
780 * Need to jump to the tag before executing the '-c command'.
781 * Makes "vim -c '/return' -t main" work.
782 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000783 if (params.tagname != NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000784 {
Bram Moolenaar146522e2005-12-16 21:55:46 +0000785 swap_exists_did_quit = FALSE;
Bram Moolenaar146522e2005-12-16 21:55:46 +0000786
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000787 vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000788 do_cmdline_cmd(IObuff);
789 TIME_MSG("jumping to tag");
Bram Moolenaar146522e2005-12-16 21:55:46 +0000790
Bram Moolenaar146522e2005-12-16 21:55:46 +0000791 /* If the user doesn't want to edit the file then we quit here. */
792 if (swap_exists_did_quit)
793 getout(1);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000794 }
795
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000796 /* Execute any "+", "-c" and "-S" arguments. */
797 if (params.n_commands > 0)
798 exe_commands(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000799
Bram Moolenaar6b1da332017-06-09 21:35:47 +0200800 /* Must come before the may_req_ calls. */
801 starting = 0;
802
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100803#if defined(FEAT_TERMRESPONSE)
Bram Moolenaar976787d2017-06-04 15:45:50 +0200804 /* Must be done before redrawing, puts a few characters on the screen. */
805 may_req_ambiguous_char_width();
806#endif
807
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000808 RedrawingDisabled = 0;
809 redraw_all_later(NOT_VALID);
810 no_wait_return = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000811
Bram Moolenaarbaec5c12016-04-06 23:06:23 +0200812 /* 'autochdir' has been postponed */
Bram Moolenaar6f470022018-04-10 18:47:20 +0200813 DO_AUTOCHDIR;
Bram Moolenaarbaec5c12016-04-06 23:06:23 +0200814
Bram Moolenaara40ceaf2006-01-13 22:35:40 +0000815#ifdef FEAT_TERMRESPONSE
816 /* Requesting the termresponse is postponed until here, so that a "-c q"
817 * argument doesn't make it appear in the shell Vim was started from. */
818 may_req_termresponse();
Bram Moolenaarfc8f1112017-04-18 18:51:35 +0200819
Bram Moolenaarfc8f1112017-04-18 18:51:35 +0200820 may_req_bg_color();
Bram Moolenaara40ceaf2006-01-13 22:35:40 +0000821#endif
822
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000823 /* start in insert mode */
824 if (p_im)
825 need_start_insertmode = TRUE;
826
Bram Moolenaar14735512016-03-26 21:00:08 +0100827#ifdef FEAT_EVAL
828 set_vim_var_nr(VV_VIM_DID_ENTER, 1L);
829#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000830 apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
831 TIME_MSG("VimEnter autocommands");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000832
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200833#if defined(FEAT_EVAL) && defined(FEAT_CLIPBOARD)
834 /* Adjust default register name for "unnamed" in 'clipboard'. Can only be
835 * done after the clipboard is available and all initial commands that may
836 * modify the 'clipboard' setting have run; i.e. just before entering the
837 * main loop. */
838 {
839 int default_regname = 0;
Bram Moolenaar53076832015-12-31 19:53:21 +0100840
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200841 adjust_clip_reg(&default_regname);
842 set_reg_var(default_regname);
843 }
844#endif
845
Bram Moolenaar8a3bb562018-03-04 20:14:14 +0100846#if defined(FEAT_DIFF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000847 /* When a startup script or session file setup for diff'ing and
848 * scrollbind, sync the scrollbind now. */
849 if (curwin->w_p_diff && curwin->w_p_scb)
850 {
851 update_topline();
852 check_scrollbind((linenr_T)0, 0L);
853 TIME_MSG("diff scrollbinding");
854 }
855#endif
856
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200857#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
858# ifdef VIMDLL
859 if (!gui.in_use)
860# endif
861 mch_set_winsize_now(); /* Allow winsize changes from now on */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000862#endif
863
Bram Moolenaar4033c552017-09-16 20:54:51 +0200864#if defined(FEAT_GUI)
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000865 /* When tab pages were created, may need to update the tab pages line and
866 * scrollbars. This is skipped while creating them. */
867 if (first_tabpage->tp_next != NULL)
868 {
869 out_flush();
870 gui_init_which_components(NULL);
871 gui_update_scrollbars(TRUE);
872 }
873 need_mouse_correct = TRUE;
874#endif
875
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000876 /* If ":startinsert" command used, stuff a dummy command to be able to
877 * call normal_cmd(), which will then start Insert mode. */
878 if (restart_edit != 0)
Bram Moolenaarebefac62005-12-28 22:39:57 +0000879 stuffcharReadbuff(K_NOP);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000880
881#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200882 if (netbeansArg != NULL && strncmp("-nb", netbeansArg, 3) == 0)
Bram Moolenaar67c53842010-05-22 18:28:27 +0200883 {
884# ifdef FEAT_GUI
Bram Moolenaar173c9852010-09-29 17:27:01 +0200885# if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \
Bram Moolenaar4f974752019-02-17 17:44:42 +0100886 && !defined(FEAT_GUI_MSWIN)
Bram Moolenaar67c53842010-05-22 18:28:27 +0200887 if (gui.in_use)
888 {
889 mch_errmsg(_("netbeans is not supported with this GUI\n"));
890 mch_exit(2);
891 }
892# endif
893# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000894 /* Tell the client that it can start sending commands. */
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200895 netbeans_open(netbeansArg + 3, TRUE);
Bram Moolenaar67c53842010-05-22 18:28:27 +0200896 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000897#endif
898
899 TIME_MSG("before starting main loop");
900
901 /*
902 * Call the main command loop. This never returns.
Bram Moolenaar92d147b2018-07-29 17:35:23 +0200903 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000904 main_loop(FALSE, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000905
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200906#endif /* NO_VIM_MAIN */
907
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000908 return 0;
909}
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000910
911/*
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200912 * Initialisation shared by main() and some tests.
913 */
914 void
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200915common_init(mparm_T *paramp)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200916{
Bram Moolenaar438d1762018-09-30 17:11:48 +0200917 cmdline_init();
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200918
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200919 (void)mb_init(); /* init mb_bytelen_tab[] to ones */
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200920#ifdef FEAT_EVAL
921 eval_init(); /* init global variables */
922#endif
923
924#ifdef __QNXNTO__
925 qnx_init(); /* PhAttach() for clipboard, (and gui) */
926#endif
927
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200928 /* Init the table of Normal mode commands. */
929 init_normal_cmds();
930
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200931 /*
932 * Allocate space for the generic buffers (needed for set_init_1() and
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100933 * emsg()).
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200934 */
935 if ((IObuff = alloc(IOSIZE)) == NULL
936 || (NameBuff = alloc(MAXPATHL)) == NULL)
937 mch_exit(0);
938 TIME_MSG("Allocated generic buffers");
939
940#ifdef NBDEBUG
941 /* Wait a moment for debugging NetBeans. Must be after allocating
942 * NameBuff. */
943 nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
944 nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
945 TIME_MSG("NetBeans debug wait");
946#endif
947
948#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
949 /*
950 * Setup to use the current locale (for ctype() and many other things).
951 * NOTE: Translated messages with encodings other than latin1 will not
952 * work until set_init_1() has been called!
953 */
954 init_locale();
955 TIME_MSG("locale set");
956#endif
957
958#ifdef FEAT_GUI
959 gui.dofork = TRUE; /* default is to use fork() */
960#endif
961
962 /*
963 * Do a first scan of the arguments in "argv[]":
964 * -display or --display
965 * --server...
966 * --socketid
967 * --windowid
968 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200969 early_arg_scan(paramp);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200970
Bram Moolenaard0573012017-10-28 21:11:06 +0200971#if defined(FEAT_GUI)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200972 /* Prepare for possibly starting GUI sometime */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200973 gui_prepare(&paramp->argc, paramp->argv);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200974 TIME_MSG("GUI prepared");
975#endif
976
977#ifdef FEAT_CLIPBOARD
978 clip_init(FALSE); /* Initialise clipboard stuff */
979 TIME_MSG("clipboard setup");
980#endif
981
982 /*
983 * Check if we have an interactive window.
984 * On the Amiga: If there is no window, we open one with a newcli command
985 * (needed for :! to * work). mch_check_win() will also handle the -d or
986 * -dev argument.
987 */
Bram Moolenaar2cab0e12016-11-24 15:09:07 +0100988 stdout_isatty = (mch_check_win(paramp->argc, paramp->argv) != FAIL);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200989 TIME_MSG("window checked");
990
991 /*
992 * Allocate the first window and buffer.
993 * Can't do anything without it, exit when it fails.
994 */
995 if (win_alloc_first() == FAIL)
996 mch_exit(0);
997
998 init_yank(); /* init yank buffers */
999
1000 alist_init(&global_alist); /* Init the argument list to empty. */
1001 global_alist.id = 0;
1002
1003 /*
1004 * Set the default values for the options.
1005 * NOTE: Non-latin1 translated messages are working only after this,
1006 * because this is where "has_mbyte" will be set, which is used by
1007 * msg_outtrans_len_attr().
1008 * First find out the home directory, needed to expand "~" in options.
1009 */
1010 init_homedir(); /* find real value of $HOME */
Bram Moolenaar07268702018-03-01 21:57:32 +01001011 set_init_1(paramp->clean);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001012 TIME_MSG("inits 1");
1013
1014#ifdef FEAT_EVAL
1015 set_lang_var(); /* set v:lang and v:ctype */
1016#endif
Bram Moolenaar6436cd82018-12-27 00:28:33 +01001017
1018#ifdef FEAT_SIGNS
1019 init_signs();
1020#endif
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001021}
1022
1023/*
Bram Moolenaar08f88b12017-04-02 17:21:16 +02001024 * Return TRUE when the --not-a-term argument was found.
1025 */
1026 int
1027is_not_a_term()
1028{
1029 return params.not_a_term;
1030}
1031
1032/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001033 * Main loop: Execute Normal mode commands until exiting Vim.
1034 * Also used to handle commands in the command-line window, until the window
1035 * is closed.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001036 * Also used to handle ":visual" command after ":global": execute Normal mode
1037 * commands, return when entering Ex mode. "noexmode" is TRUE then.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001038 */
1039 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001040main_loop(
1041 int cmdwin, /* TRUE when working in the command-line window */
1042 int noexmode) /* TRUE when return on entering Ex mode */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001043{
Bram Moolenaardf2c7742018-04-16 17:06:09 +02001044 oparg_T oa; /* operator arguments */
Bram Moolenaar8872ef12015-02-10 19:27:05 +01001045 volatile int previous_got_int = FALSE; /* "got_int" was TRUE */
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001046#ifdef FEAT_CONCEAL
Bram Moolenaar1db43b12015-07-12 16:21:23 +02001047 /* these are static to avoid a compiler warning */
1048 static linenr_T conceal_old_cursor_line = 0;
1049 static linenr_T conceal_new_cursor_line = 0;
1050 static int conceal_update_lines = FALSE;
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001051#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001052
1053#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1054 /* Setup to catch a terminating error from the X server. Just ignore
1055 * it, restore the state and continue. This might not always work
1056 * properly, but at least we don't exit unexpectedly when the X server
Bram Moolenaar2cd36962014-01-14 12:57:05 +01001057 * exits while Vim is running in a console. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001058 if (!cmdwin && !noexmode && SETJMP(x_jump_env))
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001059 {
1060 State = NORMAL;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001061 VIsual_active = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001062 got_int = TRUE;
1063 need_wait_return = FALSE;
1064 global_busy = FALSE;
1065 exmode_active = 0;
1066 skip_redraw = FALSE;
1067 RedrawingDisabled = 0;
1068 no_wait_return = 0;
Bram Moolenaar7701c242011-10-04 16:43:53 +02001069 vgetc_busy = 0;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001070# ifdef FEAT_EVAL
1071 emsg_skip = 0;
1072# endif
1073 emsg_off = 0;
1074# ifdef FEAT_MOUSE
1075 setmouse();
1076# endif
1077 settmode(TMODE_RAW);
1078 starttermcap();
1079 scroll_start();
1080 redraw_later_clear();
1081 }
1082#endif
1083
1084 clear_oparg(&oa);
1085 while (!cmdwin
1086#ifdef FEAT_CMDWIN
1087 || cmdwin_result == 0
1088#endif
1089 )
1090 {
1091 if (stuff_empty())
1092 {
1093 did_check_timestamps = FALSE;
1094 if (need_check_timestamps)
1095 check_timestamps(FALSE);
1096 if (need_wait_return) /* if wait_return still needed ... */
1097 wait_return(FALSE); /* ... call it now */
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001098 if (need_start_insertmode && goto_im() && !VIsual_active)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001099 {
1100 need_start_insertmode = FALSE;
1101 stuffReadbuff((char_u *)"i"); /* start insert mode next */
1102 /* skip the fileinfo message now, because it would be shown
1103 * after insert mode finishes! */
1104 need_fileinfo = FALSE;
1105 }
1106 }
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001107
1108 /* Reset "got_int" now that we got back to the main loop. Except when
1109 * inside a ":g/pat/cmd" command, then the "got_int" needs to abort
1110 * the ":g" command.
1111 * For ":g/pat/vi" we reset "got_int" when used once. When used
1112 * a second time we go back to Ex mode and abort the ":g" command. */
1113 if (got_int)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001114 {
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001115 if (noexmode && global_busy && !exmode_active && previous_got_int)
1116 {
1117 /* Typed two CTRL-C in a row: go back to ex mode as if "Q" was
1118 * used and keep "got_int" set, so that it aborts ":g". */
1119 exmode_active = EXMODE_NORMAL;
1120 State = NORMAL;
1121 }
1122 else if (!global_busy || !exmode_active)
1123 {
1124 if (!quit_more)
1125 (void)vgetc(); /* flush all buffers */
1126 got_int = FALSE;
1127 }
1128 previous_got_int = TRUE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001129 }
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001130 else
1131 previous_got_int = FALSE;
1132
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001133 if (!exmode_active)
1134 msg_scroll = FALSE;
1135 quit_more = FALSE;
1136
1137 /*
1138 * If skip redraw is set (for ":" in wait_return()), don't redraw now.
1139 * If there is nothing in the stuff_buffer or do_redraw is TRUE,
1140 * update cursor and redraw.
1141 */
1142 if (skip_redraw || exmode_active)
1143 skip_redraw = FALSE;
1144 else if (do_redraw || stuff_empty())
1145 {
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001146#ifdef FEAT_GUI
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001147 // If ui_breakcheck() was used a resize may have been postponed.
Bram Moolenaar6b40f302017-02-03 22:01:47 +01001148 gui_may_resize_shell();
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001149#endif
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001150#ifdef HAVE_DROP_FILE
1151 // If files were dropped while text was locked or the curbuf was
1152 // locked, this would be a good time to handle the drop.
1153 handle_any_postponed_drop();
1154#endif
Bram Moolenaarbbee8d52019-01-14 21:51:40 +01001155#ifdef FEAT_CONCEAL
1156 if (curwin->w_p_cole == 0)
1157 conceal_update_lines = FALSE;
1158#endif
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001159
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001160 /* Trigger CursorMoved if the cursor moved. */
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001161 if (!finish_op && (
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001162 has_cursormoved()
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001163#ifdef FEAT_CONCEAL
1164 || curwin->w_p_cole > 0
1165#endif
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001166 )
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001167 && !EQUAL_POS(last_cursormoved, curwin->w_cursor))
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001168 {
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001169 if (has_cursormoved())
1170 apply_autocmds(EVENT_CURSORMOVED, NULL, NULL,
1171 FALSE, curbuf);
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001172# ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001173 if (curwin->w_p_cole > 0)
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001174 {
1175 conceal_old_cursor_line = last_cursormoved.lnum;
1176 conceal_new_cursor_line = curwin->w_cursor.lnum;
1177 conceal_update_lines = TRUE;
1178 }
1179# endif
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001180 last_cursormoved = curwin->w_cursor;
1181 }
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001182
Bram Moolenaar535d5b62019-01-11 20:45:36 +01001183#if defined(FEAT_CONCEAL)
1184 if (conceal_update_lines
1185 && (conceal_old_cursor_line != conceal_new_cursor_line
1186 || conceal_cursor_line(curwin)
1187 || need_cursor_line_redraw))
1188 {
1189 if (conceal_old_cursor_line != conceal_new_cursor_line
Bram Moolenaarbbee8d52019-01-14 21:51:40 +01001190 && conceal_old_cursor_line != 0
Bram Moolenaar535d5b62019-01-11 20:45:36 +01001191 && conceal_old_cursor_line
1192 <= curbuf->b_ml.ml_line_count)
1193 redrawWinline(curwin, conceal_old_cursor_line);
1194 redrawWinline(curwin, conceal_new_cursor_line);
1195 curwin->w_valid &= ~VALID_CROW;
1196 need_cursor_line_redraw = FALSE;
1197 }
1198#endif
1199
Bram Moolenaar95c526e2017-02-25 14:59:34 +01001200 /* Trigger TextChanged if b:changedtick differs. */
Bram Moolenaar186628f2013-03-19 13:33:23 +01001201 if (!finish_op && has_textchanged()
Bram Moolenaar5a093432018-02-10 18:15:19 +01001202 && curbuf->b_last_changedtick != CHANGEDTICK(curbuf))
Bram Moolenaar186628f2013-03-19 13:33:23 +01001203 {
Bram Moolenaar5a093432018-02-10 18:15:19 +01001204 apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf);
1205 curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
Bram Moolenaar186628f2013-03-19 13:33:23 +01001206 }
Bram Moolenaar186628f2013-03-19 13:33:23 +01001207
Bram Moolenaar8a3bb562018-03-04 20:14:14 +01001208#if defined(FEAT_DIFF)
Bram Moolenaare3521d92018-09-16 14:10:31 +02001209 // Updating diffs from changed() does not always work properly,
1210 // esp. updating folds. Do an update just before redrawing if
1211 // needed.
1212 if (curtab->tp_diff_update || curtab->tp_diff_invalid)
1213 {
1214 ex_diffupdate(NULL);
1215 curtab->tp_diff_update = FALSE;
1216 }
1217
Bram Moolenaar33aec762006-01-22 23:30:12 +00001218 /* Scroll-binding for diff mode may have been postponed until
1219 * here. Avoids doing it for every change. */
1220 if (diff_need_scrollbind)
1221 {
1222 check_scrollbind((linenr_T)0, 0L);
1223 diff_need_scrollbind = FALSE;
1224 }
1225#endif
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001226#if defined(FEAT_FOLDING)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001227 /* Include a closed fold completely in the Visual area. */
1228 foldAdjustVisual();
1229#endif
1230#ifdef FEAT_FOLDING
1231 /*
1232 * When 'foldclose' is set, apply 'foldlevel' to folds that don't
1233 * contain the cursor.
1234 * When 'foldopen' is "all", open the fold(s) under the cursor.
1235 * This may mark the window for redrawing.
1236 */
1237 if (hasAnyFolding(curwin) && !char_avail())
1238 {
1239 foldCheckClose();
1240 if (fdo_flags & FDO_ALL)
1241 foldOpenCursor();
1242 }
1243#endif
1244
1245 /*
1246 * Before redrawing, make sure w_topline is correct, and w_leftcol
1247 * if lines don't wrap, and w_skipcol if lines wrap.
1248 */
1249 update_topline();
1250 validate_cursor();
1251
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001252 if (VIsual_active)
1253 update_curbuf(INVERTED);/* update inverted part */
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001254 else if (must_redraw)
Bram Moolenaara338adc2018-01-31 20:51:47 +01001255 {
1256 mch_disable_flush(); /* Stop issuing gui_mch_flush(). */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001257 update_screen(0);
Bram Moolenaara338adc2018-01-31 20:51:47 +01001258 mch_enable_flush();
1259 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001260 else if (redraw_cmdline || clear_cmdline)
1261 showmode();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001262 redraw_statuslines();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001263#ifdef FEAT_TITLE
1264 if (need_maketitle)
1265 maketitle();
1266#endif
Bram Moolenaarab9c89b2016-07-03 17:47:26 +02001267#ifdef FEAT_VIMINFO
1268 curbuf->b_last_used = vim_time();
1269#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001270 /* display message after redraw */
1271 if (keep_msg != NULL)
1272 {
1273 char_u *p;
1274
1275 /* msg_attr_keep() will set keep_msg to NULL, must free the
Bram Moolenaarf638cbc2014-09-09 17:47:38 +02001276 * string here. Don't reset keep_msg, msg_attr_keep() uses it
1277 * to check for duplicates. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001278 p = keep_msg;
Bram Moolenaar63c0ccd2019-01-19 21:06:58 +01001279 msg_attr((char *)p, keep_msg_attr);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001280 vim_free(p);
1281 }
1282 if (need_fileinfo) /* show file info after redraw */
1283 {
1284 fileinfo(FALSE, TRUE, FALSE);
1285 need_fileinfo = FALSE;
1286 }
1287
1288 emsg_on_display = FALSE; /* can delete error message now */
1289 did_emsg = FALSE;
1290 msg_didany = FALSE; /* reset lines_left in msg_start() */
Bram Moolenaar661b1822005-07-28 22:36:45 +00001291 may_clear_sb_text(); /* clear scroll-back text on next msg */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001292 showruler(FALSE);
1293
1294 setcursor();
1295 cursor_on();
1296
1297 do_redraw = FALSE;
Bram Moolenaar3f269672009-11-03 11:11:11 +00001298
1299#ifdef STARTUPTIME
1300 /* Now that we have drawn the first screen all the startup stuff
1301 * has been done, close any file for startup messages. */
1302 if (time_fd != NULL)
1303 {
1304 TIME_MSG("first screen update");
1305 TIME_MSG("--- VIM STARTED ---");
1306 fclose(time_fd);
1307 time_fd = NULL;
1308 }
1309#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001310 }
1311#ifdef FEAT_GUI
1312 if (need_mouse_correct)
1313 gui_mouse_correct();
1314#endif
1315
1316 /*
1317 * Update w_curswant if w_set_curswant has been set.
1318 * Postponed until here to avoid computing w_virtcol too often.
1319 */
1320 update_curswant();
1321
Bram Moolenaar9fecb462006-09-05 10:59:47 +00001322#ifdef FEAT_EVAL
1323 /*
1324 * May perform garbage collection when waiting for a character, but
1325 * only at the very toplevel. Otherwise we may be using a List or
1326 * Dict internally somewhere.
1327 * "may_garbage_collect" is reset in vgetc() which is invoked through
1328 * do_exmode() and normal_cmd().
1329 */
1330 may_garbage_collect = (!cmdwin && !noexmode);
1331#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001332 /*
1333 * If we're invoked as ex, do a round of ex commands.
1334 * Otherwise, get and execute a normal mode command.
1335 */
1336 if (exmode_active)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001337 {
1338 if (noexmode) /* End of ":global/path/visual" commands */
1339 return;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001340 do_exmode(exmode_active == EXMODE_VIM);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001341 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001342 else
Bram Moolenaar938783d2017-07-16 20:13:26 +02001343 {
1344#ifdef FEAT_TERMINAL
Bram Moolenaar6d819742017-08-06 14:57:49 +02001345 if (term_use_loop()
Bram Moolenaaraaa8a352017-08-05 20:17:00 +02001346 && oa.op_type == OP_NOP && oa.regname == NUL
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001347 && !VIsual_active
1348 && !skip_term_loop)
Bram Moolenaar423802d2017-07-30 16:52:24 +02001349 {
1350 /* If terminal_loop() returns OK we got a key that is handled
Bram Moolenaar6d819742017-08-06 14:57:49 +02001351 * in Normal model. With FAIL we first need to position the
1352 * cursor and the screen needs to be redrawn. */
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +02001353 if (terminal_loop(TRUE) == OK)
Bram Moolenaar423802d2017-07-30 16:52:24 +02001354 normal_cmd(&oa, TRUE);
1355 }
1356 else
Bram Moolenaar938783d2017-07-16 20:13:26 +02001357#endif
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001358 {
1359#ifdef FEAT_TERMINAL
1360 skip_term_loop = FALSE;
1361#endif
Bram Moolenaar423802d2017-07-30 16:52:24 +02001362 normal_cmd(&oa, TRUE);
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001363 }
Bram Moolenaar938783d2017-07-16 20:13:26 +02001364 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001365 }
1366}
1367
1368
Bram Moolenaar6d8d8492016-03-19 14:48:31 +01001369#if defined(USE_XSMP) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001370/*
1371 * Exit, but leave behind swap files for modified buffers.
1372 */
1373 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001374getout_preserve_modified(int exitval)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001375{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001376# if defined(SIGHUP) && defined(SIG_IGN)
1377 /* Ignore SIGHUP, because a dropped connection causes a read error, which
1378 * makes Vim exit and then handling SIGHUP causes various reentrance
1379 * problems. */
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001380 signal(SIGHUP, SIG_IGN);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001381# endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001382
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001383 ml_close_notmod(); /* close all not-modified buffers */
1384 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
1385 ml_close_all(FALSE); /* close all memfiles, without deleting */
1386 getout(exitval); /* exit Vim properly */
1387}
1388#endif
1389
1390
Bram Moolenaar6d8d8492016-03-19 14:48:31 +01001391/*
1392 * Exit properly.
1393 */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001394 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001395getout(int exitval)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001396{
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001397 exiting = TRUE;
Bram Moolenaar0bd052b2018-03-22 20:33:56 +01001398#if defined(FEAT_JOB_CHANNEL)
1399 ch_log(NULL, "Exiting...");
1400#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001401
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001402 /* When running in Ex mode an error causes us to exit with a non-zero exit
1403 * code. POSIX requires this, although it's not 100% clear from the
1404 * standard. */
1405 if (exmode_active)
1406 exitval += ex_exitval;
1407
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001408 /* Position the cursor on the last screen line, below all the text */
1409#ifdef FEAT_GUI
1410 if (!gui.in_use)
1411#endif
1412 windgoto((int)Rows - 1, 0);
1413
Bram Moolenaar0e21a3f2005-04-17 20:28:32 +00001414#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
1415 /* Optionally print hashtable efficiency. */
1416 hash_debug_results();
1417#endif
1418
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001419#ifdef FEAT_GUI
1420 msg_didany = FALSE;
1421#endif
1422
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001423 if (v_dying <= 1)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001424 {
Bram Moolenaardf2c7742018-04-16 17:06:09 +02001425 tabpage_T *tp;
1426 tabpage_T *next_tp;
1427 buf_T *buf;
1428 win_T *wp;
1429
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001430 /* Trigger BufWinLeave for all windows, but only once per buffer. */
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001431 for (tp = first_tabpage; tp != NULL; tp = next_tp)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001432 {
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001433 next_tp = tp->tp_next;
Bram Moolenaar29323592016-07-24 22:04:11 +02001434 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaarf740b292006-02-16 22:11:02 +00001435 {
Bram Moolenaar802418d2013-01-17 14:00:11 +01001436 if (wp->w_buffer == NULL)
1437 /* Autocmd must have close the buffer already, skip. */
1438 continue;
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001439 buf = wp->w_buffer;
Bram Moolenaar95c526e2017-02-25 14:59:34 +01001440 if (CHANGEDTICK(buf) != -1)
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001441 {
Bram Moolenaar606d45c2017-12-18 16:21:44 +01001442 bufref_T bufref;
1443
1444 set_bufref(&bufref, buf);
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001445 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
1446 buf->b_fname, FALSE, buf);
Bram Moolenaar606d45c2017-12-18 16:21:44 +01001447 if (bufref_valid(&bufref))
1448 CHANGEDTICK(buf) = -1; /* note we did it already */
1449
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001450 /* start all over, autocommands may mess up the lists */
1451 next_tp = first_tabpage;
1452 break;
1453 }
Bram Moolenaarf740b292006-02-16 22:11:02 +00001454 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001455 }
Bram Moolenaar33aec762006-01-22 23:30:12 +00001456
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001457 /* Trigger BufUnload for buffers that are loaded */
Bram Moolenaar29323592016-07-24 22:04:11 +02001458 FOR_ALL_BUFFERS(buf)
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001459 if (buf->b_ml.ml_mfp != NULL)
1460 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001461 bufref_T bufref;
1462
1463 set_bufref(&bufref, buf);
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001464 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001465 FALSE, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001466 if (!bufref_valid(&bufref))
1467 /* autocmd deleted the buffer */
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001468 break;
1469 }
1470 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
1471 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001472
1473#ifdef FEAT_VIMINFO
1474 if (*p_viminfo != NUL)
1475 /* Write out the registers, history, marks etc, to the viminfo file */
1476 write_viminfo(NULL, FALSE);
1477#endif
1478
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001479 if (v_dying <= 1)
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001480 apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001481
Bram Moolenaar05159a02005-02-26 23:04:13 +00001482#ifdef FEAT_PROFILE
1483 profile_dump();
1484#endif
1485
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001486 if (did_emsg
1487#ifdef FEAT_GUI
1488 || (gui.in_use && msg_didany && p_verbose > 0)
1489#endif
1490 )
1491 {
1492 /* give the user a chance to read the (error) message */
1493 no_wait_return = FALSE;
1494 wait_return(FALSE);
1495 }
1496
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001497 /* Position the cursor again, the autocommands may have moved it */
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001498#ifdef FEAT_GUI
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001499 if (!gui.in_use)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001500#endif
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001501 windgoto((int)Rows - 1, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001502
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01001503#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar65edff82016-02-21 16:40:11 +01001504 job_stop_on_exit();
1505#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001506#ifdef FEAT_LUA
1507 lua_end();
1508#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00001509#ifdef FEAT_MZSCHEME
1510 mzscheme_end();
1511#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001512#ifdef FEAT_TCL
1513 tcl_end();
1514#endif
1515#ifdef FEAT_RUBY
1516 ruby_end();
1517#endif
1518#ifdef FEAT_PYTHON
1519 python_end();
1520#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +02001521#ifdef FEAT_PYTHON3
1522 python3_end();
1523#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001524#ifdef FEAT_PERL
1525 perl_end();
1526#endif
1527#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
1528 iconv_end();
1529#endif
1530#ifdef FEAT_NETBEANS_INTG
1531 netbeans_end();
1532#endif
Bram Moolenaar02b06312007-09-06 15:39:22 +00001533#ifdef FEAT_CSCOPE
1534 cs_end();
1535#endif
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00001536#ifdef FEAT_EVAL
1537 if (garbage_collect_at_exit)
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02001538 garbage_collect(FALSE);
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00001539#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01001540#ifdef MSWIN
Bram Moolenaar14993322014-09-09 12:25:33 +02001541 free_cmd_argsW();
1542#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001543
1544 mch_exit(exitval);
1545}
1546
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001547#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
1548/*
1549 * Setup to use the current locale (for ctype() and many other things).
1550 */
1551 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01001552init_locale(void)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001553{
1554 setlocale(LC_ALL, "");
Bram Moolenaar8c8de832008-06-24 22:58:06 +00001555
Bram Moolenaarc6af8122010-05-21 12:04:55 +02001556# ifdef FEAT_GUI_GTK
1557 /* Tell Gtk not to change our locale settings. */
1558 gtk_disable_setlocale();
1559# endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +00001560# if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
1561 /* Make sure strtod() uses a decimal point, not a comma. */
1562 setlocale(LC_NUMERIC, "C");
1563# endif
1564
Bram Moolenaar4f974752019-02-17 17:44:42 +01001565# ifdef MSWIN
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00001566 /* Apparently MS-Windows printf() may cause a crash when we give it 8-bit
1567 * text while it's expecting text in the current locale. This call avoids
1568 * that. */
1569 setlocale(LC_CTYPE, "C");
1570# endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001571
1572# ifdef FEAT_GETTEXT
1573 {
1574 int mustfree = FALSE;
1575 char_u *p;
1576
1577# ifdef DYNAMIC_GETTEXT
1578 /* Initialize the gettext library */
Bram Moolenaar286eacd2016-01-16 18:05:50 +01001579 dyn_libintl_init();
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001580# endif
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +01001581 /* expand_env() doesn't work yet, because g_chartab[] is not
1582 * initialized yet, call vim_getenv() directly */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001583 p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
1584 if (p != NULL && *p != NUL)
1585 {
Bram Moolenaar1ad2f132007-06-19 18:27:18 +00001586 vim_snprintf((char *)NameBuff, MAXPATHL, "%s/lang", p);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001587 bindtextdomain(VIMPACKAGE, (char *)NameBuff);
1588 }
1589 if (mustfree)
1590 vim_free(p);
1591 textdomain(VIMPACKAGE);
1592 }
1593# endif
1594}
1595#endif
1596
1597/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00001598 * Get the name of the display, before gui_prepare() removes it from
1599 * argv[]. Used for the xterm-clipboard display.
1600 *
Bram Moolenaar78e17622007-08-30 10:26:19 +00001601 * Also find the --server... arguments and --socketid and --windowid
Bram Moolenaar58d98232005-07-23 22:25:46 +00001602 */
Bram Moolenaar58d98232005-07-23 22:25:46 +00001603 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01001604early_arg_scan(mparm_T *parmp UNUSED)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001605{
Bram Moolenaar03005972008-11-20 13:12:36 +00001606#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER) \
1607 || !defined(FEAT_NETBEANS_INTG)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001608 int argc = parmp->argc;
1609 char **argv = parmp->argv;
Bram Moolenaar58d98232005-07-23 22:25:46 +00001610 int i;
1611
1612 for (i = 1; i < argc; i++)
1613 {
1614 if (STRCMP(argv[i], "--") == 0)
1615 break;
1616# ifdef FEAT_XCLIPBOARD
1617 else if (STRICMP(argv[i], "-display") == 0
Bram Moolenaar241a8aa2005-12-06 20:04:44 +00001618# if defined(FEAT_GUI_GTK)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001619 || STRICMP(argv[i], "--display") == 0
1620# endif
1621 )
1622 {
1623 if (i == argc - 1)
1624 mainerr_arg_missing((char_u *)argv[i]);
1625 xterm_display = argv[++i];
1626 }
1627# endif
1628# ifdef FEAT_CLIENTSERVER
1629 else if (STRICMP(argv[i], "--servername") == 0)
1630 {
1631 if (i == argc - 1)
1632 mainerr_arg_missing((char_u *)argv[i]);
1633 parmp->serverName_arg = (char_u *)argv[++i];
1634 }
Bram Moolenaareb94e552006-03-11 21:35:11 +00001635 else if (STRICMP(argv[i], "--serverlist") == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001636 parmp->serverArg = TRUE;
Bram Moolenaareb94e552006-03-11 21:35:11 +00001637 else if (STRNICMP(argv[i], "--remote", 8) == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001638 {
1639 parmp->serverArg = TRUE;
Bram Moolenaareb94e552006-03-11 21:35:11 +00001640# ifdef FEAT_GUI
1641 if (strstr(argv[i], "-wait") != 0)
1642 /* don't fork() when starting the GUI to edit files ourself */
1643 gui.dofork = FALSE;
1644# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001645 }
1646# endif
Bram Moolenaar78e17622007-08-30 10:26:19 +00001647
Bram Moolenaar4f974752019-02-17 17:44:42 +01001648# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
1649# ifdef FEAT_GUI_MSWIN
Bram Moolenaar78e17622007-08-30 10:26:19 +00001650 else if (STRICMP(argv[i], "--windowid") == 0)
1651# else
Bram Moolenaar58d98232005-07-23 22:25:46 +00001652 else if (STRICMP(argv[i], "--socketid") == 0)
Bram Moolenaar78e17622007-08-30 10:26:19 +00001653# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001654 {
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001655 long_u id;
1656 int count;
Bram Moolenaar58d98232005-07-23 22:25:46 +00001657
1658 if (i == argc - 1)
1659 mainerr_arg_missing((char_u *)argv[i]);
1660 if (STRNICMP(argv[i+1], "0x", 2) == 0)
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001661 count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id);
Bram Moolenaar58d98232005-07-23 22:25:46 +00001662 else
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001663 count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id);
Bram Moolenaar58d98232005-07-23 22:25:46 +00001664 if (count != 1)
1665 mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
1666 else
Bram Moolenaar4f974752019-02-17 17:44:42 +01001667# ifdef FEAT_GUI_MSWIN
Bram Moolenaar78e17622007-08-30 10:26:19 +00001668 win_socket_id = id;
1669# else
1670 gtk_socket_id = id;
1671# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001672 i++;
1673 }
Bram Moolenaar78e17622007-08-30 10:26:19 +00001674# endif
1675# ifdef FEAT_GUI_GTK
Bram Moolenaar58d98232005-07-23 22:25:46 +00001676 else if (STRICMP(argv[i], "--echo-wid") == 0)
1677 echo_wid_arg = TRUE;
1678# endif
Bram Moolenaar03005972008-11-20 13:12:36 +00001679# ifndef FEAT_NETBEANS_INTG
1680 else if (strncmp(argv[i], "-nb", (size_t)3) == 0)
Bram Moolenaar67c53842010-05-22 18:28:27 +02001681 {
1682 mch_errmsg(_("'-nb' cannot be used: not enabled at compile time\n"));
1683 mch_exit(2);
1684 }
Bram Moolenaar03005972008-11-20 13:12:36 +00001685# endif
1686
Bram Moolenaar58d98232005-07-23 22:25:46 +00001687 }
1688#endif
1689}
1690
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001691#ifndef NO_VIM_MAIN
1692/*
1693 * Get a (optional) count for a Vim argument.
1694 */
1695 static int
1696get_number_arg(
1697 char_u *p, /* pointer to argument */
1698 int *idx, /* index in argument, is incremented */
1699 int def) /* default value */
1700{
1701 if (vim_isdigit(p[*idx]))
1702 {
1703 def = atoi((char *)&(p[*idx]));
1704 while (vim_isdigit(p[*idx]))
1705 *idx = *idx + 1;
1706 }
1707 return def;
1708}
1709
1710/*
Bram Moolenaar27e80c82018-10-14 21:41:01 +02001711 * Check for: [r][e][g][vi|vim|view][diff][ex[im]] (sort of)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001712 * If the executable name starts with "r" we disable shell commands.
1713 * If the next character is "e" we run in Easy mode.
1714 * If the next character is "g" we run the GUI version.
1715 * If the next characters are "view" we start in readonly mode.
1716 * If the next characters are "diff" or "vimdiff" we start in diff mode.
1717 * If the next characters are "ex" we start in Ex mode. If it's followed
1718 * by "im" use improved Ex mode.
1719 */
1720 static void
1721parse_command_name(mparm_T *parmp)
1722{
1723 char_u *initstr;
1724
1725 initstr = gettail((char_u *)parmp->argv[0]);
1726
Bram Moolenaard0573012017-10-28 21:11:06 +02001727#ifdef FEAT_GUI_MAC
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001728 /* An issue has been seen when launching Vim in such a way that
1729 * $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the
1730 * executable or a symbolic link of it. Until this issue is resolved
1731 * we prohibit the GUI from being used.
1732 */
1733 if (STRCMP(initstr, parmp->argv[0]) == 0)
1734 disallow_gui = TRUE;
1735
1736 /* TODO: On MacOS X default to gui if argv[0] ends in:
1737 * /Vim.app/Contents/MacOS/Vim */
1738#endif
1739
1740#ifdef FEAT_EVAL
1741 set_vim_var_string(VV_PROGNAME, initstr, -1);
Bram Moolenaar08cab962017-03-04 14:37:18 +01001742 set_progpath((char_u *)parmp->argv[0]);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001743#endif
1744
1745 if (TOLOWER_ASC(initstr[0]) == 'r')
1746 {
1747 restricted = TRUE;
1748 ++initstr;
1749 }
1750
1751 /* Use evim mode for "evim" and "egvim", not for "editor". */
1752 if (TOLOWER_ASC(initstr[0]) == 'e'
1753 && (TOLOWER_ASC(initstr[1]) == 'v'
1754 || TOLOWER_ASC(initstr[1]) == 'g'))
1755 {
1756#ifdef FEAT_GUI
1757 gui.starting = TRUE;
1758#endif
1759 parmp->evim_mode = TRUE;
1760 ++initstr;
1761 }
1762
1763 /* "gvim" starts the GUI. Also accept "Gvim" for MS-Windows. */
1764 if (TOLOWER_ASC(initstr[0]) == 'g')
1765 {
1766 main_start_gui();
1767#ifdef FEAT_GUI
1768 ++initstr;
1769#endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +02001770#ifdef GUI_MAY_SPAWN
1771 gui.dospawn = FALSE; // No need to spawn a new process.
1772#endif
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001773 }
Bram Moolenaarafde13b2019-04-28 19:46:49 +02001774#ifdef GUI_MAY_SPAWN
1775 else
1776 gui.dospawn = TRUE; // Not "gvim". Need to spawn gvim.exe.
1777#endif
1778
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001779
1780 if (STRNICMP(initstr, "view", 4) == 0)
1781 {
1782 readonlymode = TRUE;
1783 curbuf->b_p_ro = TRUE;
1784 p_uc = 10000; /* don't update very often */
1785 initstr += 4;
1786 }
1787 else if (STRNICMP(initstr, "vim", 3) == 0)
1788 initstr += 3;
1789
Bram Moolenaar27e80c82018-10-14 21:41:01 +02001790 // Catch "[r][g]vimdiff" and "[r][g]viewdiff".
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001791 if (STRICMP(initstr, "diff") == 0)
1792 {
1793#ifdef FEAT_DIFF
1794 parmp->diff_mode = TRUE;
1795#else
1796 mch_errmsg(_("This Vim was not compiled with the diff feature."));
1797 mch_errmsg("\n");
1798 mch_exit(2);
1799#endif
1800 }
1801
Bram Moolenaar27e80c82018-10-14 21:41:01 +02001802 // Checking for "ex" here may catch some weir names, such as "vimex" or
1803 // "viewex", we assume the user knows that.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001804 if (STRNICMP(initstr, "ex", 2) == 0)
1805 {
1806 if (STRNICMP(initstr + 2, "im", 2) == 0)
1807 exmode_active = EXMODE_VIM;
1808 else
1809 exmode_active = EXMODE_NORMAL;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02001810 change_compatible(TRUE); // set 'compatible'
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001811 }
1812}
1813
Bram Moolenaar58d98232005-07-23 22:25:46 +00001814/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001815 * Scan the command line arguments.
1816 */
1817 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01001818command_line_scan(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001819{
1820 int argc = parmp->argc;
1821 char **argv = parmp->argv;
1822 int argv_idx; /* index in argv[n][] */
1823 int had_minmin = FALSE; /* found "--" argument */
1824 int want_argument; /* option argument with argument */
1825 int c;
Bram Moolenaar231334e2005-07-25 20:46:57 +00001826 char_u *p = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001827 long n;
1828
1829 --argc;
1830 ++argv;
1831 argv_idx = 1; /* active option letter is argv[0][argv_idx] */
1832 while (argc > 0)
1833 {
1834 /*
1835 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
1836 */
1837 if (argv[0][0] == '+' && !had_minmin)
1838 {
1839 if (parmp->n_commands >= MAX_ARG_CMDS)
1840 mainerr(ME_EXTRA_CMD, NULL);
1841 argv_idx = -1; /* skip to next argument */
1842 if (argv[0][1] == NUL)
1843 parmp->commands[parmp->n_commands++] = (char_u *)"$";
1844 else
1845 parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]);
1846 }
1847
1848 /*
1849 * Optional argument.
1850 */
1851 else if (argv[0][0] == '-' && !had_minmin)
1852 {
1853 want_argument = FALSE;
1854 c = argv[0][argv_idx++];
1855#ifdef VMS
1856 /*
1857 * VMS only uses upper case command lines. Interpret "-X" as "-x"
1858 * and "-/X" as "-X".
1859 */
1860 if (c == '/')
1861 {
1862 c = argv[0][argv_idx++];
1863 c = TOUPPER_ASC(c);
1864 }
1865 else
1866 c = TOLOWER_ASC(c);
1867#endif
1868 switch (c)
1869 {
1870 case NUL: /* "vim -" read from stdin */
1871 /* "ex -" silent mode */
1872 if (exmode_active)
1873 silent_mode = TRUE;
1874 else
1875 {
1876 if (parmp->edit_type != EDIT_NONE)
1877 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
1878 parmp->edit_type = EDIT_STDIN;
1879 read_cmd_fd = 2; /* read from stderr instead of stdin */
1880 }
1881 argv_idx = -1; /* skip to next argument */
1882 break;
1883
1884 case '-': /* "--" don't take any more option arguments */
1885 /* "--help" give help message */
1886 /* "--version" give version message */
Bram Moolenaarc4da1132017-07-15 19:39:43 +02001887 /* "--clean" clean context */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001888 /* "--literal" take files literally */
1889 /* "--nofork" don't fork */
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01001890 /* "--not-a-term" don't warn for not a term */
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01001891 /* "--ttyfail" exit if not a term */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001892 /* "--noplugin[s]" skip plugins */
1893 /* "--cmd <cmd>" execute cmd before vimrc */
1894 if (STRICMP(argv[0] + argv_idx, "help") == 0)
1895 usage();
1896 else if (STRICMP(argv[0] + argv_idx, "version") == 0)
1897 {
1898 Columns = 80; /* need to init Columns */
1899 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
1900 list_version();
1901 msg_putchar('\n');
1902 msg_didout = FALSE;
1903 mch_exit(0);
1904 }
Bram Moolenaarc4da1132017-07-15 19:39:43 +02001905 else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0)
1906 {
1907 parmp->use_vimrc = (char_u *)"DEFAULTS";
Bram Moolenaar62dd4522018-03-14 21:20:02 +01001908#ifdef FEAT_GUI
1909 use_gvimrc = (char_u *)"NONE";
1910#endif
Bram Moolenaar07268702018-03-01 21:57:32 +01001911 parmp->clean = TRUE;
Bram Moolenaarc4da1132017-07-15 19:39:43 +02001912 set_option_value((char_u *)"vif", 0L, (char_u *)"NONE", 0);
1913 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001914 else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
1915 {
Bram Moolenaar53076832015-12-31 19:53:21 +01001916#ifdef EXPAND_FILENAMES
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001917 parmp->literal = TRUE;
1918#endif
1919 }
1920 else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
1921 {
1922#ifdef FEAT_GUI
1923 gui.dofork = FALSE; /* don't fork() when starting GUI */
1924#endif
1925 }
1926 else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
1927 p_lpl = FALSE;
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01001928 else if (STRNICMP(argv[0] + argv_idx, "not-a-term", 10) == 0)
1929 parmp->not_a_term = TRUE;
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01001930 else if (STRNICMP(argv[0] + argv_idx, "ttyfail", 7) == 0)
1931 parmp->tty_fail = TRUE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001932 else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
1933 {
1934 want_argument = TRUE;
1935 argv_idx += 3;
1936 }
Bram Moolenaaref94eec2009-11-11 13:22:11 +00001937 else if (STRNICMP(argv[0] + argv_idx, "startuptime", 11) == 0)
1938 {
1939 want_argument = TRUE;
1940 argv_idx += 11;
1941 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001942#ifdef FEAT_CLIENTSERVER
1943 else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
1944 ; /* already processed -- no arg */
1945 else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
1946 || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
1947 {
1948 /* already processed -- snatch the following arg */
1949 if (argc > 1)
1950 {
1951 --argc;
1952 ++argv;
1953 }
1954 }
1955#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01001956#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
Bram Moolenaar78e17622007-08-30 10:26:19 +00001957# ifdef FEAT_GUI_GTK
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001958 else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
Bram Moolenaar78e17622007-08-30 10:26:19 +00001959# else
1960 else if (STRNICMP(argv[0] + argv_idx, "windowid", 8) == 0)
1961# endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001962 {
1963 /* already processed -- snatch the following arg */
1964 if (argc > 1)
1965 {
1966 --argc;
1967 ++argv;
1968 }
1969 }
Bram Moolenaar78e17622007-08-30 10:26:19 +00001970#endif
1971#ifdef FEAT_GUI_GTK
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001972 else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
1973 {
1974 /* already processed, skip */
1975 }
1976#endif
1977 else
1978 {
1979 if (argv[0][argv_idx])
1980 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
1981 had_minmin = TRUE;
1982 }
1983 if (!want_argument)
1984 argv_idx = -1; /* skip to next argument */
1985 break;
1986
1987 case 'A': /* "-A" start in Arabic mode */
1988#ifdef FEAT_ARABIC
1989 set_option_value((char_u *)"arabic", 1L, NULL, 0);
1990#else
1991 mch_errmsg(_(e_noarabic));
1992 mch_exit(2);
1993#endif
1994 break;
1995
1996 case 'b': /* "-b" binary mode */
Bram Moolenaar231334e2005-07-25 20:46:57 +00001997 /* Needs to be effective before expanding file names, because
1998 * for Win32 this makes us edit a shortcut file itself,
1999 * instead of the file it links to. */
2000 set_options_bin(curbuf->b_p_bin, 1, 0);
2001 curbuf->b_p_bin = 1; /* binary file I/O */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002002 break;
2003
2004 case 'C': /* "-C" Compatible */
2005 change_compatible(TRUE);
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +02002006 has_dash_c_arg = TRUE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002007 break;
2008
2009 case 'e': /* "-e" Ex mode */
2010 exmode_active = EXMODE_NORMAL;
2011 break;
2012
2013 case 'E': /* "-E" Improved Ex mode */
2014 exmode_active = EXMODE_VIM;
2015 break;
2016
2017 case 'f': /* "-f" GUI: run in foreground. Amiga: open
2018 window directly, not with newcli */
2019#ifdef FEAT_GUI
2020 gui.dofork = FALSE; /* don't fork() when starting GUI */
2021#endif
2022 break;
2023
2024 case 'g': /* "-g" start GUI */
2025 main_start_gui();
2026 break;
2027
Bram Moolenaar14184a32019-02-16 15:10:30 +01002028 case 'F': /* "-F" was for Farsi mode */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002029 mch_errmsg(_(e_nofarsi));
2030 mch_exit(2);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002031 break;
2032
Bram Moolenaarc3e81692018-05-05 15:09:51 +02002033 case '?': /* "-?" give help message (for MS-Windows) */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002034 case 'h': /* "-h" give help message */
2035#ifdef FEAT_GUI_GNOME
2036 /* Tell usage() to exit for "gvim". */
2037 gui.starting = FALSE;
2038#endif
2039 usage();
2040 break;
2041
2042 case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */
2043#ifdef FEAT_RIGHTLEFT
Bram Moolenaarc4cd38f2008-01-13 15:18:01 +00002044 p_hkmap = TRUE;
2045 set_option_value((char_u *)"rl", 1L, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002046#else
2047 mch_errmsg(_(e_nohebrew));
2048 mch_exit(2);
2049#endif
2050 break;
2051
2052 case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */
2053#ifdef FEAT_LISP
2054 set_option_value((char_u *)"lisp", 1L, NULL, 0);
2055 p_sm = TRUE;
2056#endif
2057 break;
2058
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002059 case 'M': /* "-M" no changes or writing of files */
2060 reset_modifiable();
2061 /* FALLTHROUGH */
2062
2063 case 'm': /* "-m" no writing of files */
2064 p_write = FALSE;
2065 break;
2066
2067 case 'y': /* "-y" easy mode */
2068#ifdef FEAT_GUI
2069 gui.starting = TRUE; /* start GUI a bit later */
2070#endif
2071 parmp->evim_mode = TRUE;
2072 break;
2073
2074 case 'N': /* "-N" Nocompatible */
2075 change_compatible(FALSE);
2076 break;
2077
2078 case 'n': /* "-n" no swap file */
Bram Moolenaar67c53842010-05-22 18:28:27 +02002079#ifdef FEAT_NETBEANS_INTG
2080 /* checking for "-nb", netbeans parameters */
2081 if (argv[0][argv_idx] == 'b')
2082 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02002083 netbeansArg = argv[0];
2084 argv_idx = -1; /* skip to next argument */
2085 }
2086 else
2087#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002088 parmp->no_swap_file = TRUE;
2089 break;
2090
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002091 case 'p': /* "-p[N]" open N tab pages */
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00002092#ifdef TARGET_API_MAC_OSX
2093 /* For some reason on MacOS X, an argument like:
2094 -psn_0_10223617 is passed in when invoke from Finder
2095 or with the 'open' command */
2096 if (argv[0][argv_idx] == 's')
2097 {
2098 argv_idx = -1; /* bypass full -psn */
2099 main_start_gui();
2100 break;
2101 }
2102#endif
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002103 /* default is 0: open window for each file */
2104 parmp->window_count = get_number_arg((char_u *)argv[0],
2105 &argv_idx, 0);
2106 parmp->window_layout = WIN_TABS;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002107 break;
2108
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002109 case 'o': /* "-o[N]" open N horizontal split windows */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002110 /* default is 0: open window for each file */
Bram Moolenaar231334e2005-07-25 20:46:57 +00002111 parmp->window_count = get_number_arg((char_u *)argv[0],
2112 &argv_idx, 0);
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002113 parmp->window_layout = WIN_HOR;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002114 break;
2115
2116 case 'O': /* "-O[N]" open N vertical split windows */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002117 /* default is 0: open window for each file */
Bram Moolenaar231334e2005-07-25 20:46:57 +00002118 parmp->window_count = get_number_arg((char_u *)argv[0],
2119 &argv_idx, 0);
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002120 parmp->window_layout = WIN_VER;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002121 break;
2122
2123#ifdef FEAT_QUICKFIX
2124 case 'q': /* "-q" QuickFix mode */
2125 if (parmp->edit_type != EDIT_NONE)
2126 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2127 parmp->edit_type = EDIT_QF;
2128 if (argv[0][argv_idx]) /* "-q{errorfile}" */
2129 {
2130 parmp->use_ef = (char_u *)argv[0] + argv_idx;
2131 argv_idx = -1;
2132 }
2133 else if (argc > 1) /* "-q {errorfile}" */
2134 want_argument = TRUE;
2135 break;
2136#endif
2137
2138 case 'R': /* "-R" readonly mode */
2139 readonlymode = TRUE;
2140 curbuf->b_p_ro = TRUE;
2141 p_uc = 10000; /* don't update very often */
2142 break;
2143
2144 case 'r': /* "-r" recovery mode */
2145 case 'L': /* "-L" recovery mode */
2146 recoverymode = 1;
2147 break;
2148
2149 case 's':
2150 if (exmode_active) /* "-s" silent (batch) mode */
2151 silent_mode = TRUE;
2152 else /* "-s {scriptin}" read from script file */
2153 want_argument = TRUE;
2154 break;
2155
2156 case 't': /* "-t {tag}" or "-t{tag}" jump to tag */
2157 if (parmp->edit_type != EDIT_NONE)
2158 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2159 parmp->edit_type = EDIT_TAG;
2160 if (argv[0][argv_idx]) /* "-t{tag}" */
2161 {
2162 parmp->tagname = (char_u *)argv[0] + argv_idx;
2163 argv_idx = -1;
2164 }
2165 else /* "-t {tag}" */
2166 want_argument = TRUE;
2167 break;
2168
2169#ifdef FEAT_EVAL
2170 case 'D': /* "-D" Debugging */
2171 parmp->use_debug_break_level = 9999;
2172 break;
2173#endif
2174#ifdef FEAT_DIFF
2175 case 'd': /* "-d" 'diff' */
2176# ifdef AMIGA
2177 /* check for "-dev {device}" */
2178 if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
2179 want_argument = TRUE;
2180 else
2181# endif
2182 parmp->diff_mode = TRUE;
2183 break;
2184#endif
2185 case 'V': /* "-V{N}" Verbose level */
2186 /* default is 10: a little bit verbose */
2187 p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10);
2188 if (argv[0][argv_idx] != NUL)
2189 {
2190 set_option_value((char_u *)"verbosefile", 0L,
2191 (char_u *)argv[0] + argv_idx, 0);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002192 argv_idx = (int)STRLEN(argv[0]);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002193 }
2194 break;
2195
2196 case 'v': /* "-v" Vi-mode (as if called "vi") */
2197 exmode_active = 0;
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002198#if defined(FEAT_GUI) && !defined(VIMDLL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002199 gui.starting = FALSE; /* don't start GUI */
2200#endif
2201 break;
2202
2203 case 'w': /* "-w{number}" set window height */
2204 /* "-w {scriptout}" write to script */
2205 if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
2206 {
2207 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
2208 set_option_value((char_u *)"window", n, NULL, 0);
2209 break;
2210 }
2211 want_argument = TRUE;
2212 break;
2213
2214#ifdef FEAT_CRYPT
2215 case 'x': /* "-x" encrypted reading/writing of files */
2216 parmp->ask_for_key = TRUE;
2217 break;
2218#endif
2219
2220 case 'X': /* "-X" don't connect to X server */
2221#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
2222 x_no_connect = TRUE;
2223#endif
2224 break;
2225
2226 case 'Z': /* "-Z" restricted mode */
2227 restricted = TRUE;
2228 break;
2229
2230 case 'c': /* "-c{command}" or "-c {command}" execute
2231 command */
2232 if (argv[0][argv_idx] != NUL)
2233 {
2234 if (parmp->n_commands >= MAX_ARG_CMDS)
2235 mainerr(ME_EXTRA_CMD, NULL);
Bram Moolenaar231334e2005-07-25 20:46:57 +00002236 parmp->commands[parmp->n_commands++] = (char_u *)argv[0]
2237 + argv_idx;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002238 argv_idx = -1;
2239 break;
2240 }
Bram Moolenaar2f40d122017-10-24 21:49:36 +02002241 /* FALLTHROUGH */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002242 case 'S': /* "-S {file}" execute Vim script */
2243 case 'i': /* "-i {viminfo}" use for viminfo */
2244#ifndef FEAT_DIFF
2245 case 'd': /* "-d {device}" device (for Amiga) */
2246#endif
2247 case 'T': /* "-T {terminal}" terminal name */
2248 case 'u': /* "-u {vimrc}" vim inits file */
2249 case 'U': /* "-U {gvimrc}" gvim inits file */
2250 case 'W': /* "-W {scriptout}" overwrite */
Bram Moolenaar4f974752019-02-17 17:44:42 +01002251#ifdef FEAT_GUI_MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002252 case 'P': /* "-P {parent title}" MDI parent */
2253#endif
2254 want_argument = TRUE;
2255 break;
2256
2257 default:
2258 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
2259 }
2260
2261 /*
2262 * Handle option arguments with argument.
2263 */
2264 if (want_argument)
2265 {
2266 /*
2267 * Check for garbage immediately after the option letter.
2268 */
2269 if (argv[0][argv_idx] != NUL)
2270 mainerr(ME_GARBAGE, (char_u *)argv[0]);
2271
2272 --argc;
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002273 if (argc < 1 && c != 'S') /* -S has an optional argument */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002274 mainerr_arg_missing((char_u *)argv[0]);
2275 ++argv;
2276 argv_idx = -1;
2277
2278 switch (c)
2279 {
2280 case 'c': /* "-c {command}" execute command */
2281 case 'S': /* "-S {file}" execute Vim script */
2282 if (parmp->n_commands >= MAX_ARG_CMDS)
2283 mainerr(ME_EXTRA_CMD, NULL);
2284 if (c == 'S')
2285 {
2286 char *a;
2287
2288 if (argc < 1)
2289 /* "-S" without argument: use default session file
2290 * name. */
2291 a = SESSION_FILE;
2292 else if (argv[0][0] == '-')
2293 {
2294 /* "-S" followed by another option: use default
2295 * session file name. */
2296 a = SESSION_FILE;
2297 ++argc;
2298 --argv;
2299 }
2300 else
2301 a = argv[0];
2302 p = alloc((unsigned)(STRLEN(a) + 4));
2303 if (p == NULL)
2304 mch_exit(2);
2305 sprintf((char *)p, "so %s", a);
2306 parmp->cmds_tofree[parmp->n_commands] = TRUE;
2307 parmp->commands[parmp->n_commands++] = p;
2308 }
2309 else
Bram Moolenaar231334e2005-07-25 20:46:57 +00002310 parmp->commands[parmp->n_commands++] =
2311 (char_u *)argv[0];
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002312 break;
2313
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002314 case '-':
2315 if (argv[-1][2] == 'c')
2316 {
2317 /* "--cmd {command}" execute command */
2318 if (parmp->n_pre_commands >= MAX_ARG_CMDS)
2319 mainerr(ME_EXTRA_CMD, NULL);
2320 parmp->pre_commands[parmp->n_pre_commands++] =
Bram Moolenaar231334e2005-07-25 20:46:57 +00002321 (char_u *)argv[0];
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002322 }
2323 /* "--startuptime <file>" already handled */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002324 break;
2325
2326 /* case 'd': -d {device} is handled in mch_check_win() for the
2327 * Amiga */
2328
2329#ifdef FEAT_QUICKFIX
2330 case 'q': /* "-q {errorfile}" QuickFix mode */
2331 parmp->use_ef = (char_u *)argv[0];
2332 break;
2333#endif
2334
2335 case 'i': /* "-i {viminfo}" use for viminfo */
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002336 set_option_value((char_u *)"vif", 0L, (char_u *)argv[0], 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002337 break;
2338
2339 case 's': /* "-s {scriptin}" read from script file */
2340 if (scriptin[0] != NULL)
2341 {
2342scripterror:
2343 mch_errmsg(_("Attempt to open script file again: \""));
2344 mch_errmsg(argv[-1]);
2345 mch_errmsg(" ");
2346 mch_errmsg(argv[0]);
2347 mch_errmsg("\"\n");
2348 mch_exit(2);
2349 }
2350 if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
2351 {
2352 mch_errmsg(_("Cannot open for reading: \""));
2353 mch_errmsg(argv[0]);
2354 mch_errmsg("\"\n");
2355 mch_exit(2);
2356 }
2357 if (save_typebuf() == FAIL)
2358 mch_exit(2); /* out of memory */
2359 break;
2360
2361 case 't': /* "-t {tag}" */
2362 parmp->tagname = (char_u *)argv[0];
2363 break;
2364
2365 case 'T': /* "-T {terminal}" terminal name */
2366 /*
2367 * The -T term argument is always available and when
2368 * HAVE_TERMLIB is supported it overrides the environment
2369 * variable TERM.
2370 */
2371#ifdef FEAT_GUI
2372 if (term_is_gui((char_u *)argv[0]))
2373 gui.starting = TRUE; /* start GUI a bit later */
2374 else
2375#endif
2376 parmp->term = (char_u *)argv[0];
2377 break;
2378
2379 case 'u': /* "-u {vimrc}" vim inits file */
2380 parmp->use_vimrc = (char_u *)argv[0];
2381 break;
2382
2383 case 'U': /* "-U {gvimrc}" gvim inits file */
2384#ifdef FEAT_GUI
2385 use_gvimrc = (char_u *)argv[0];
2386#endif
2387 break;
2388
2389 case 'w': /* "-w {nr}" 'window' value */
2390 /* "-w {scriptout}" append to script file */
2391 if (vim_isdigit(*((char_u *)argv[0])))
2392 {
2393 argv_idx = 0;
2394 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
2395 set_option_value((char_u *)"window", n, NULL, 0);
2396 argv_idx = -1;
2397 break;
2398 }
Bram Moolenaar2f40d122017-10-24 21:49:36 +02002399 /* FALLTHROUGH */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002400 case 'W': /* "-W {scriptout}" overwrite script file */
2401 if (scriptout != NULL)
2402 goto scripterror;
2403 if ((scriptout = mch_fopen(argv[0],
2404 c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
2405 {
2406 mch_errmsg(_("Cannot open for script output: \""));
2407 mch_errmsg(argv[0]);
2408 mch_errmsg("\"\n");
2409 mch_exit(2);
2410 }
2411 break;
2412
Bram Moolenaar4f974752019-02-17 17:44:42 +01002413#ifdef FEAT_GUI_MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002414 case 'P': /* "-P {parent title}" MDI parent */
2415 gui_mch_set_parent(argv[0]);
2416 break;
2417#endif
2418 }
2419 }
2420 }
2421
2422 /*
2423 * File name argument.
2424 */
2425 else
2426 {
2427 argv_idx = -1; /* skip to next argument */
2428
2429 /* Check for only one type of editing. */
2430 if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
2431 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2432 parmp->edit_type = EDIT_FILE;
2433
2434#ifdef MSWIN
2435 /* Remember if the argument was a full path before changing
2436 * slashes to backslashes. */
2437 if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
2438 parmp->full_path = TRUE;
2439#endif
2440
2441 /* Add the file to the global argument list. */
2442 if (ga_grow(&global_alist.al_ga, 1) == FAIL
2443 || (p = vim_strsave((char_u *)argv[0])) == NULL)
2444 mch_exit(2);
2445#ifdef FEAT_DIFF
2446 if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
2447 && !mch_isdir(alist_name(&GARGLIST[0])))
2448 {
2449 char_u *r;
2450
2451 r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
2452 if (r != NULL)
2453 {
2454 vim_free(p);
2455 p = r;
2456 }
2457 }
2458#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01002459#if defined(__CYGWIN32__) && !defined(MSWIN)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002460 /*
2461 * If vim is invoked by non-Cygwin tools, convert away any
2462 * DOS paths, so things like .swp files are created correctly.
2463 * Look for evidence of non-Cygwin paths before we bother.
2464 * This is only for when using the Unix files.
2465 */
Bram Moolenaarfe17e762013-06-29 14:17:02 +02002466 if (vim_strpbrk(p, "\\:") != NULL && !path_with_url(p))
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002467 {
Bram Moolenaara9f8ee02017-08-14 23:40:45 +02002468 char posix_path[MAXPATHL];
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002469
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002470# if CYGWIN_VERSION_DLL_MAJOR >= 1007
Bram Moolenaara9f8ee02017-08-14 23:40:45 +02002471 cygwin_conv_path(CCP_WIN_A_TO_POSIX, p, posix_path, MAXPATHL);
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002472# else
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002473 cygwin_conv_to_posix_path(p, posix_path);
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002474# endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002475 vim_free(p);
Bram Moolenaarfe17e762013-06-29 14:17:02 +02002476 p = vim_strsave((char_u *)posix_path);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002477 if (p == NULL)
2478 mch_exit(2);
2479 }
2480#endif
Bram Moolenaarcc016f52005-12-10 20:23:46 +00002481
2482#ifdef USE_FNAME_CASE
2483 /* Make the case of the file name match the actual file. */
2484 fname_case(p, 0);
2485#endif
2486
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002487 alist_add(&global_alist, p,
Bram Moolenaar53076832015-12-31 19:53:21 +01002488#ifdef EXPAND_FILENAMES
Bram Moolenaar231334e2005-07-25 20:46:57 +00002489 parmp->literal ? 2 : 0 /* add buffer nr after exp. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002490#else
2491 2 /* add buffer number now and use curbuf */
2492#endif
2493 );
2494
Bram Moolenaar4f974752019-02-17 17:44:42 +01002495#ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002496 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002497 /* Remember this argument has been added to the argument list.
2498 * Needed when 'encoding' is changed. */
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002499 used_file_arg(argv[0], parmp->literal, parmp->full_path,
Bram Moolenaar688e5f72008-07-24 11:51:40 +00002500# ifdef FEAT_DIFF
2501 parmp->diff_mode
2502# else
2503 FALSE
2504# endif
2505 );
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002506 }
2507#endif
2508 }
2509
2510 /*
2511 * If there are no more letters after the current "-", go to next
2512 * argument. argv_idx is set to -1 when the current argument is to be
2513 * skipped.
2514 */
2515 if (argv_idx <= 0 || argv[0][argv_idx] == NUL)
2516 {
2517 --argc;
2518 ++argv;
2519 argv_idx = 1;
2520 }
2521 }
Bram Moolenaar867a4b72007-03-18 20:51:46 +00002522
2523#ifdef FEAT_EVAL
2524 /* If there is a "+123" or "-c" command, set v:swapcommand to the first
2525 * one. */
2526 if (parmp->n_commands > 0)
2527 {
2528 p = alloc((unsigned)STRLEN(parmp->commands[0]) + 3);
2529 if (p != NULL)
2530 {
2531 sprintf((char *)p, ":%s\r", parmp->commands[0]);
2532 set_vim_var_string(VV_SWAPCOMMAND, p, -1);
2533 vim_free(p);
2534 }
2535 }
2536#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002537}
2538
2539/*
2540 * Print a warning if stdout is not a terminal.
Bram Moolenaar42b23fa2018-02-03 14:46:45 +01002541 * When starting in Ex mode and commands come from a file, set silent_mode.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002542 */
2543 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002544check_tty(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002545{
2546 int input_isatty; /* is active input a terminal? */
2547
2548 input_isatty = mch_input_isatty();
2549 if (exmode_active)
2550 {
2551 if (!input_isatty)
2552 silent_mode = TRUE;
2553 }
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002554 else if (parmp->want_full_screen && (!stdout_isatty || !input_isatty)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002555#ifdef FEAT_GUI
2556 /* don't want the delay when started from the desktop */
2557 && !gui.starting
2558#endif
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01002559 && !parmp->not_a_term)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002560 {
2561#ifdef NBDEBUG
2562 /*
2563 * This shouldn't be necessary. But if I run netbeans with the log
2564 * output coming to the console and XOpenDisplay fails, I get vim
2565 * trying to start with input/output to my console tty. This fills my
2566 * input buffer so fast I can't even kill the process in under 2
Bram Moolenaar49325942007-05-10 19:19:59 +00002567 * minutes (and it beeps continuously the whole time :-)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002568 */
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002569 if (netbeans_active() && (!stdout_isatty || !input_isatty))
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002570 {
2571 mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
2572 exit(1);
2573 }
2574#endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002575#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
2576 if (
2577# ifdef VIMDLL
2578 !gui.starting &&
2579# endif
2580 is_cygpty_used())
Bram Moolenaar97ff9b92016-06-26 20:37:46 +02002581 {
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01002582# if defined(HAVE_BIND_TEXTDOMAIN_CODESET) \
Bram Moolenaar2a027452017-09-26 19:10:37 +02002583 && defined(FEAT_GETTEXT)
2584 char *s, *tofree = NULL;
2585
2586 /* Set the encoding of the error message based on $LC_ALL or
2587 * other environment variables instead of 'encoding'.
2588 * Note that the message is shown on a Cygwin terminal (e.g.
2589 * mintty) which encoding is based on $LC_ALL or etc., not the
2590 * current codepage used by normal Win32 console programs. */
Bram Moolenaar9cf39cc2017-09-27 21:46:19 +02002591 tofree = s = (char *)enc_locale_env(NULL);
Bram Moolenaar2a027452017-09-26 19:10:37 +02002592 if (s == NULL)
2593 s = "utf-8"; /* Use "utf-8" by default. */
2594 (void)bind_textdomain_codeset(VIMPACKAGE, s);
2595 vim_free(tofree);
2596# endif
Bram Moolenaar97ff9b92016-06-26 20:37:46 +02002597 mch_errmsg(_("Vim: Error: This version of Vim does not run in a Cygwin terminal\n"));
2598 exit(1);
2599 }
2600#endif
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002601 if (!stdout_isatty)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002602 mch_errmsg(_("Vim: Warning: Output is not to a terminal\n"));
2603 if (!input_isatty)
2604 mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
2605 out_flush();
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002606 if (parmp->tty_fail && (!stdout_isatty || !input_isatty))
2607 exit(1);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002608 if (scriptin[0] == NULL)
2609 ui_delay(2000L, TRUE);
2610 TIME_MSG("Warning delay");
2611 }
2612}
2613
2614/*
2615 * Read text from stdin.
2616 */
2617 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002618read_stdin(void)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002619{
2620 int i;
2621
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002622 // When getting the ATTENTION prompt here, use a dialog
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002623 swap_exists_action = SEA_DIALOG;
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002624
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002625 no_wait_return = TRUE;
2626 i = msg_didany;
2627 set_buflisted(TRUE);
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002628 (void)open_buffer(TRUE, NULL, 0); // create memfile and read file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002629 no_wait_return = FALSE;
2630 msg_didany = i;
2631 TIME_MSG("reading stdin");
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002632
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002633 check_swap_exists_action();
Bram Moolenaard0573012017-10-28 21:11:06 +02002634#if !(defined(AMIGA) || defined(MACOS_X))
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002635 /*
2636 * Close stdin and dup it from stderr. Required for GPM to work
2637 * properly, and for running external commands.
2638 * Is there any other system that cannot do this?
2639 */
2640 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +02002641 vim_ignored = dup(2);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002642#endif
2643}
2644
2645/*
2646 * Create the requested number of windows and edit buffers in them.
2647 * Also does recovery if "recoverymode" set.
2648 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002649 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002650create_windows(mparm_T *parmp UNUSED)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002651{
Bram Moolenaar89d40322006-08-29 15:30:07 +00002652 int dorewind;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002653 int done = 0;
2654
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002655 /*
2656 * Create the number of windows that was requested.
2657 */
2658 if (parmp->window_count == -1) /* was not set */
2659 parmp->window_count = 1;
2660 if (parmp->window_count == 0)
2661 parmp->window_count = GARGCOUNT;
2662 if (parmp->window_count > 1)
2663 {
2664 /* Don't change the windows if there was a command in .vimrc that
2665 * already split some windows */
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002666 if (parmp->window_layout == 0)
2667 parmp->window_layout = WIN_HOR;
2668 if (parmp->window_layout == WIN_TABS)
2669 {
2670 parmp->window_count = make_tabpages(parmp->window_count);
2671 TIME_MSG("making tab pages");
2672 }
2673 else if (firstwin->w_next == NULL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002674 {
2675 parmp->window_count = make_windows(parmp->window_count,
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002676 parmp->window_layout == WIN_VER);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002677 TIME_MSG("making windows");
2678 }
2679 else
2680 parmp->window_count = win_count();
2681 }
2682 else
2683 parmp->window_count = 1;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002684
2685 if (recoverymode) /* do recover */
2686 {
2687 msg_scroll = TRUE; /* scroll message up */
2688 ml_recover();
2689 if (curbuf->b_ml.ml_mfp == NULL) /* failed */
2690 getout(1);
Bram Moolenaara3227e22006-03-08 21:32:40 +00002691 do_modelines(0); /* do modelines */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002692 }
2693 else
2694 {
2695 /*
2696 * Open a buffer for windows that don't have one yet.
2697 * Commands in the .vimrc might have loaded a file or split the window.
2698 * Watch out for autocommands that delete a window.
2699 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002700 /*
2701 * Don't execute Win/Buf Enter/Leave autocommands here
2702 */
2703 ++autocmd_no_enter;
2704 ++autocmd_no_leave;
Bram Moolenaar89d40322006-08-29 15:30:07 +00002705 dorewind = TRUE;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002706 while (done++ < 1000)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002707 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002708 if (dorewind)
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002709 {
2710 if (parmp->window_layout == WIN_TABS)
2711 goto_tabpage(1);
2712 else
2713 curwin = firstwin;
2714 }
2715 else if (parmp->window_layout == WIN_TABS)
2716 {
2717 if (curtab->tp_next == NULL)
2718 break;
2719 goto_tabpage(0);
2720 }
2721 else
2722 {
2723 if (curwin->w_next == NULL)
2724 break;
2725 curwin = curwin->w_next;
2726 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00002727 dorewind = FALSE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002728 curbuf = curwin->w_buffer;
2729 if (curbuf->b_ml.ml_mfp == NULL)
2730 {
2731#ifdef FEAT_FOLDING
2732 /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
2733 if (p_fdls >= 0)
2734 curwin->w_p_fdl = p_fdls;
2735#endif
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002736 // When getting the ATTENTION prompt here, use a dialog
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002737 swap_exists_action = SEA_DIALOG;
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002738
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002739 set_buflisted(TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02002740
2741 /* create memfile, read file */
2742 (void)open_buffer(FALSE, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002743
Bram Moolenaar84212822006-11-07 21:59:47 +00002744 if (swap_exists_action == SEA_QUIT)
2745 {
2746 if (got_int || only_one_window())
2747 {
2748 /* abort selected or quit and only one window */
2749 did_emsg = FALSE; /* avoid hit-enter prompt */
2750 getout(1);
2751 }
2752 /* We can't close the window, it would disturb what
2753 * happens next. Clear the file name and set the arg
2754 * index to -1 to delete it later. */
2755 setfname(curbuf, NULL, NULL, FALSE);
2756 curwin->w_arg_idx = -1;
2757 swap_exists_action = SEA_NONE;
2758 }
2759 else
2760 handle_swap_exists(NULL);
Bram Moolenaar89d40322006-08-29 15:30:07 +00002761 dorewind = TRUE; /* start again */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002762 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002763 ui_breakcheck();
2764 if (got_int)
2765 {
2766 (void)vgetc(); /* only break the file loading, not the rest */
2767 break;
2768 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002769 }
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002770 if (parmp->window_layout == WIN_TABS)
2771 goto_tabpage(1);
2772 else
2773 curwin = firstwin;
2774 curbuf = curwin->w_buffer;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002775 --autocmd_no_enter;
2776 --autocmd_no_leave;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002777 }
2778}
2779
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002780 /*
2781 * If opened more than one window, start editing files in the other
2782 * windows. make_windows() has already opened the windows.
2783 */
2784 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002785edit_buffers(
2786 mparm_T *parmp,
2787 char_u *cwd) /* current working dir */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002788{
2789 int arg_idx; /* index in argument list */
2790 int i;
Bram Moolenaar84212822006-11-07 21:59:47 +00002791 int advance = TRUE;
Bram Moolenaar74cd6242013-08-22 14:14:27 +02002792 win_T *win;
Bram Moolenaarc75e8122019-04-21 15:55:10 +02002793 char_u *p_shm_save = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002794
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002795 /*
2796 * Don't execute Win/Buf Enter/Leave autocommands here
2797 */
2798 ++autocmd_no_enter;
2799 ++autocmd_no_leave;
Bram Moolenaar84212822006-11-07 21:59:47 +00002800
2801 /* When w_arg_idx is -1 remove the window (see create_windows()). */
2802 if (curwin->w_arg_idx == -1)
2803 {
2804 win_close(curwin, TRUE);
2805 advance = FALSE;
2806 }
2807
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002808 arg_idx = 1;
2809 for (i = 1; i < parmp->window_count; ++i)
2810 {
Bram Moolenaard87c36e2015-04-03 14:56:49 +02002811 if (cwd != NULL)
2812 mch_chdir((char *)cwd);
Bram Moolenaar84212822006-11-07 21:59:47 +00002813 /* When w_arg_idx is -1 remove the window (see create_windows()). */
2814 if (curwin->w_arg_idx == -1)
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002815 {
Bram Moolenaar84212822006-11-07 21:59:47 +00002816 ++arg_idx;
2817 win_close(curwin, TRUE);
2818 advance = FALSE;
2819 continue;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002820 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002821
Bram Moolenaar84212822006-11-07 21:59:47 +00002822 if (advance)
2823 {
2824 if (parmp->window_layout == WIN_TABS)
2825 {
2826 if (curtab->tp_next == NULL) /* just checking */
2827 break;
2828 goto_tabpage(0);
Bram Moolenaarc75e8122019-04-21 15:55:10 +02002829 // Temporarily reset 'shm' option to not print fileinfo when
2830 // loading the other buffers. This would overwrite the already
2831 // existing fileinfo for the first tab.
2832 if (i == 1)
2833 {
2834 char buf[100];
2835
2836 p_shm_save = vim_strsave(p_shm);
2837 vim_snprintf(buf, 100, "F%s", p_shm);
2838 set_option_value((char_u *)"shm", 0L, (char_u *)buf, 0);
2839 }
Bram Moolenaar84212822006-11-07 21:59:47 +00002840 }
2841 else
2842 {
2843 if (curwin->w_next == NULL) /* just checking */
2844 break;
2845 win_enter(curwin->w_next, FALSE);
2846 }
2847 }
2848 advance = TRUE;
2849
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002850 /* Only open the file if there is no file in this window yet (that can
Bram Moolenaar84212822006-11-07 21:59:47 +00002851 * happen when .vimrc contains ":sall"). */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002852 if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL)
2853 {
2854 curwin->w_arg_idx = arg_idx;
Bram Moolenaar84212822006-11-07 21:59:47 +00002855 /* Edit file from arg list, if there is one. When "Quit" selected
2856 * at the ATTENTION prompt close the window. */
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00002857 swap_exists_did_quit = FALSE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002858 (void)do_ecmd(0, arg_idx < GARGCOUNT
2859 ? alist_name(&GARGLIST[arg_idx]) : NULL,
Bram Moolenaar701f7af2008-11-15 13:12:07 +00002860 NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00002861 if (swap_exists_did_quit)
Bram Moolenaar84212822006-11-07 21:59:47 +00002862 {
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00002863 /* abort or quit selected */
Bram Moolenaar84212822006-11-07 21:59:47 +00002864 if (got_int || only_one_window())
2865 {
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00002866 /* abort selected and only one window */
Bram Moolenaar84212822006-11-07 21:59:47 +00002867 did_emsg = FALSE; /* avoid hit-enter prompt */
2868 getout(1);
2869 }
2870 win_close(curwin, TRUE);
2871 advance = FALSE;
2872 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002873 if (arg_idx == GARGCOUNT - 1)
2874 arg_had_last = TRUE;
2875 ++arg_idx;
2876 }
2877 ui_breakcheck();
2878 if (got_int)
2879 {
2880 (void)vgetc(); /* only break the file loading, not the rest */
2881 break;
2882 }
2883 }
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002884
Bram Moolenaarc75e8122019-04-21 15:55:10 +02002885 if (p_shm_save != NULL)
2886 {
2887 set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
2888 vim_free(p_shm_save);
2889 }
2890
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002891 if (parmp->window_layout == WIN_TABS)
2892 goto_tabpage(1);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002893 --autocmd_no_enter;
Bram Moolenaare66f06d2013-06-15 21:54:16 +02002894
Bram Moolenaar74cd6242013-08-22 14:14:27 +02002895 /* make the first window the current window */
2896 win = firstwin;
Bram Moolenaar4033c552017-09-16 20:54:51 +02002897#if defined(FEAT_QUICKFIX)
Bram Moolenaar74cd6242013-08-22 14:14:27 +02002898 /* Avoid making a preview window the current window. */
2899 while (win->w_p_pvw)
2900 {
2901 win = win->w_next;
2902 if (win == NULL)
2903 {
2904 win = firstwin;
2905 break;
2906 }
Bram Moolenaare66f06d2013-06-15 21:54:16 +02002907 }
2908#endif
Bram Moolenaar74cd6242013-08-22 14:14:27 +02002909 win_enter(win, FALSE);
Bram Moolenaare66f06d2013-06-15 21:54:16 +02002910
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002911 --autocmd_no_leave;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002912 TIME_MSG("editing files in windows");
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002913 if (parmp->window_count > 1 && parmp->window_layout != WIN_TABS)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002914 win_equal(curwin, FALSE, 'b'); /* adjust heights */
2915}
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002916
2917/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00002918 * Execute the commands from --cmd arguments "cmds[cnt]".
2919 */
2920 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002921exe_pre_commands(mparm_T *parmp)
Bram Moolenaar58d98232005-07-23 22:25:46 +00002922{
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002923 char_u **cmds = parmp->pre_commands;
2924 int cnt = parmp->n_pre_commands;
Bram Moolenaar58d98232005-07-23 22:25:46 +00002925 int i;
2926
2927 if (cnt > 0)
2928 {
2929 curwin->w_cursor.lnum = 0; /* just in case.. */
2930 sourcing_name = (char_u *)_("pre-vimrc command line");
2931# ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002932 current_sctx.sc_sid = SID_CMDARG;
Bram Moolenaar58d98232005-07-23 22:25:46 +00002933# endif
2934 for (i = 0; i < cnt; ++i)
2935 do_cmdline_cmd(cmds[i]);
2936 sourcing_name = NULL;
2937# ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002938 current_sctx.sc_sid = 0;
Bram Moolenaar58d98232005-07-23 22:25:46 +00002939# endif
2940 TIME_MSG("--cmd commands");
2941 }
2942}
2943
2944/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002945 * Execute "+", "-c" and "-S" arguments.
2946 */
2947 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002948exe_commands(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002949{
2950 int i;
2951
2952 /*
2953 * We start commands on line 0, make "vim +/pat file" match a
2954 * pattern on line 1. But don't move the cursor when an autocommand
2955 * with g`" was used.
2956 */
2957 msg_scroll = TRUE;
2958 if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
2959 curwin->w_cursor.lnum = 0;
2960 sourcing_name = (char_u *)"command line";
2961#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002962 current_sctx.sc_sid = SID_CARG;
Bram Moolenaarded5f1b2018-11-10 17:33:29 +01002963 current_sctx.sc_seq = 0;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002964#endif
2965 for (i = 0; i < parmp->n_commands; ++i)
2966 {
2967 do_cmdline_cmd(parmp->commands[i]);
2968 if (parmp->cmds_tofree[i])
2969 vim_free(parmp->commands[i]);
2970 }
2971 sourcing_name = NULL;
2972#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02002973 current_sctx.sc_sid = 0;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002974#endif
2975 if (curwin->w_cursor.lnum == 0)
2976 curwin->w_cursor.lnum = 1;
2977
2978 if (!exmode_active)
2979 msg_scroll = FALSE;
2980
2981#ifdef FEAT_QUICKFIX
2982 /* When started with "-q errorfile" jump to first error again. */
2983 if (parmp->edit_type == EDIT_QF)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002984 qf_jump(NULL, 0, 0, FALSE);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002985#endif
2986 TIME_MSG("executing command arguments");
2987}
2988
2989/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00002990 * Source startup scripts.
2991 */
2992 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002993source_startup_scripts(mparm_T *parmp)
Bram Moolenaar58d98232005-07-23 22:25:46 +00002994{
2995 int i;
2996
2997 /*
2998 * For "evim" source evim.vim first of all, so that the user can overrule
2999 * any things he doesn't like.
3000 */
3001 if (parmp->evim_mode)
3002 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003003 (void)do_source((char_u *)EVIM_FILE, FALSE, DOSO_NONE);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003004 TIME_MSG("source evim file");
3005 }
3006
3007 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003008 * If -u argument given, use only the initializations from that file and
Bram Moolenaar58d98232005-07-23 22:25:46 +00003009 * nothing else.
3010 */
3011 if (parmp->use_vimrc != NULL)
3012 {
Bram Moolenaarc4da1132017-07-15 19:39:43 +02003013 if (STRCMP(parmp->use_vimrc, "DEFAULTS") == 0)
3014 do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE);
3015 else if (STRCMP(parmp->use_vimrc, "NONE") == 0
Bram Moolenaar231334e2005-07-25 20:46:57 +00003016 || STRCMP(parmp->use_vimrc, "NORC") == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003017 {
3018#ifdef FEAT_GUI
3019 if (use_gvimrc == NULL) /* don't load gvimrc either */
3020 use_gvimrc = parmp->use_vimrc;
3021#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003022 }
3023 else
3024 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003025 if (do_source(parmp->use_vimrc, FALSE, DOSO_NONE) != OK)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003026 semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003027 }
3028 }
3029 else if (!silent_mode)
3030 {
3031#ifdef AMIGA
3032 struct Process *proc = (struct Process *)FindTask(0L);
3033 APTR save_winptr = proc->pr_WindowPtr;
3034
3035 /* Avoid a requester here for a volume that doesn't exist. */
3036 proc->pr_WindowPtr = (APTR)-1L;
3037#endif
3038
3039 /*
3040 * Get system wide defaults, if the file name is defined.
3041 */
3042#ifdef SYS_VIMRC_FILE
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003043 (void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, DOSO_NONE);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003044#endif
Bram Moolenaar1056d982006-03-09 22:37:52 +00003045#ifdef MACOS_X
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003046 (void)do_source((char_u *)"$VIMRUNTIME/macmap.vim", FALSE, DOSO_NONE);
Bram Moolenaar1056d982006-03-09 22:37:52 +00003047#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003048
3049 /*
3050 * Try to read initialization commands from the following places:
3051 * - environment variable VIMINIT
3052 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise)
3053 * - second user vimrc file ($VIM/.vimrc for Dos)
3054 * - environment variable EXINIT
3055 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise)
3056 * - second user exrc file ($VIM/.exrc for Dos)
3057 * The first that exists is used, the rest is ignored.
3058 */
3059 if (process_env((char_u *)"VIMINIT", TRUE) != OK)
3060 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003061 if (do_source((char_u *)USR_VIMRC_FILE, TRUE, DOSO_VIMRC) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003062#ifdef USR_VIMRC_FILE2
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003063 && do_source((char_u *)USR_VIMRC_FILE2, TRUE,
3064 DOSO_VIMRC) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003065#endif
3066#ifdef USR_VIMRC_FILE3
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003067 && do_source((char_u *)USR_VIMRC_FILE3, TRUE,
3068 DOSO_VIMRC) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003069#endif
Bram Moolenaar22971aa2013-06-12 20:35:58 +02003070#ifdef USR_VIMRC_FILE4
3071 && do_source((char_u *)USR_VIMRC_FILE4, TRUE,
3072 DOSO_VIMRC) == FAIL
3073#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003074 && process_env((char_u *)"EXINIT", FALSE) == FAIL
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003075 && do_source((char_u *)USR_EXRC_FILE, FALSE, DOSO_NONE) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003076#ifdef USR_EXRC_FILE2
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003077 && do_source((char_u *)USR_EXRC_FILE2, FALSE, DOSO_NONE) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003078#endif
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +02003079 && !has_dash_c_arg)
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003080 {
3081 /* When no .vimrc file was found: source defaults.vim. */
3082 do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003083 }
3084 }
3085
3086 /*
3087 * Read initialization commands from ".vimrc" or ".exrc" in current
3088 * directory. This is only done if the 'exrc' option is set.
3089 * Because of security reasons we disallow shell and write commands
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003090 * now, except for Unix if the file is owned by the user or 'secure'
Bram Moolenaar58d98232005-07-23 22:25:46 +00003091 * option has been reset in environment of global ".exrc" or ".vimrc".
3092 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or
3093 * SYS_VIMRC_FILE.
3094 */
3095 if (p_exrc)
3096 {
3097#if defined(UNIX) || defined(VMS)
3098 /* If ".vimrc" file is not owned by user, set 'secure' mode. */
3099 if (!file_owned(VIMRC_FILE))
3100#endif
3101 secure = p_secure;
3102
3103 i = FAIL;
3104 if (fullpathcmp((char_u *)USR_VIMRC_FILE,
3105 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
3106#ifdef USR_VIMRC_FILE2
3107 && fullpathcmp((char_u *)USR_VIMRC_FILE2,
3108 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
3109#endif
3110#ifdef USR_VIMRC_FILE3
3111 && fullpathcmp((char_u *)USR_VIMRC_FILE3,
3112 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
3113#endif
3114#ifdef SYS_VIMRC_FILE
3115 && fullpathcmp((char_u *)SYS_VIMRC_FILE,
3116 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
3117#endif
3118 )
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003119 i = do_source((char_u *)VIMRC_FILE, TRUE, DOSO_VIMRC);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003120
3121 if (i == FAIL)
3122 {
3123#if defined(UNIX) || defined(VMS)
3124 /* if ".exrc" is not owned by user set 'secure' mode */
3125 if (!file_owned(EXRC_FILE))
3126 secure = p_secure;
3127 else
3128 secure = 0;
3129#endif
3130 if ( fullpathcmp((char_u *)USR_EXRC_FILE,
3131 (char_u *)EXRC_FILE, FALSE) != FPC_SAME
3132#ifdef USR_EXRC_FILE2
3133 && fullpathcmp((char_u *)USR_EXRC_FILE2,
3134 (char_u *)EXRC_FILE, FALSE) != FPC_SAME
3135#endif
3136 )
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003137 (void)do_source((char_u *)EXRC_FILE, FALSE, DOSO_NONE);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003138 }
3139 }
3140 if (secure == 2)
3141 need_wait_return = TRUE;
3142 secure = 0;
3143#ifdef AMIGA
3144 proc->pr_WindowPtr = save_winptr;
3145#endif
3146 }
3147 TIME_MSG("sourcing vimrc file(s)");
3148}
3149
3150/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003151 * Setup to start using the GUI. Exit with an error when not available.
3152 */
3153 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003154main_start_gui(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003155{
3156#ifdef FEAT_GUI
3157 gui.starting = TRUE; /* start GUI a bit later */
3158#else
3159 mch_errmsg(_(e_nogvim));
3160 mch_errmsg("\n");
3161 mch_exit(2);
3162#endif
3163}
3164
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003165#endif /* NO_VIM_MAIN */
3166
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003167/*
Bram Moolenaar49325942007-05-10 19:19:59 +00003168 * Get an environment variable, and execute it as Ex commands.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003169 * Returns FAIL if the environment variable was not executed, OK otherwise.
3170 */
3171 int
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003172process_env(
3173 char_u *env,
3174 int is_viminit) /* when TRUE, called for VIMINIT */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003175{
3176 char_u *initstr;
3177 char_u *save_sourcing_name;
3178 linenr_T save_sourcing_lnum;
3179#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003180 sctx_T save_current_sctx;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003181#endif
3182
3183 if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL)
3184 {
3185 if (is_viminit)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003186 vimrc_found(NULL, NULL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003187 save_sourcing_name = sourcing_name;
3188 save_sourcing_lnum = sourcing_lnum;
3189 sourcing_name = env;
3190 sourcing_lnum = 0;
3191#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003192 save_current_sctx = current_sctx;
3193 current_sctx.sc_sid = SID_ENV;
Bram Moolenaarded5f1b2018-11-10 17:33:29 +01003194 current_sctx.sc_seq = 0;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003195 current_sctx.sc_lnum = 0;
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02003196 current_sctx.sc_version = 1;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003197#endif
3198 do_cmdline_cmd(initstr);
3199 sourcing_name = save_sourcing_name;
3200 sourcing_lnum = save_sourcing_lnum;
3201#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003202 current_sctx = save_current_sctx;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003203#endif
3204 return OK;
3205 }
3206 return FAIL;
3207}
3208
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003209#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003210/*
3211 * Return TRUE if we are certain the user owns the file "fname".
3212 * Used for ".vimrc" and ".exrc".
3213 * Use both stat() and lstat() for extra security.
3214 */
3215 static int
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003216file_owned(char *fname)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003217{
Bram Moolenaar8767f522016-07-01 17:17:39 +02003218 stat_T s;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003219# ifdef UNIX
3220 uid_t uid = getuid();
3221# else /* VMS */
3222 uid_t uid = ((getgid() << 16) | getuid());
3223# endif
3224
3225 return !(mch_stat(fname, &s) != 0 || s.st_uid != uid
3226# ifdef HAVE_LSTAT
3227 || mch_lstat(fname, &s) != 0 || s.st_uid != uid
3228# endif
3229 );
3230}
3231#endif
3232
3233/*
3234 * Give an error message main_errors["n"] and exit.
3235 */
3236 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003237mainerr(
3238 int n, /* one of the ME_ defines */
3239 char_u *str) /* extra argument or NULL */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003240{
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003241#if defined(UNIX) || defined(VMS)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003242 reset_signals(); /* kill us with CTRL-C here, if you like */
3243#endif
3244
Bram Moolenaar35fb6fb2018-06-23 16:12:21 +02003245 init_longVersion();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003246 mch_errmsg(longVersion);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003247 mch_errmsg("\n");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003248 mch_errmsg(_(main_errors[n]));
3249 if (str != NULL)
3250 {
3251 mch_errmsg(": \"");
3252 mch_errmsg((char *)str);
3253 mch_errmsg("\"");
3254 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003255 mch_errmsg(_("\nMore info with: \"vim -h\"\n"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003256
3257 mch_exit(1);
3258}
3259
3260 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003261mainerr_arg_missing(char_u *str)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003262{
3263 mainerr(ME_ARG_MISSING, str);
3264}
3265
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003266#ifndef NO_VIM_MAIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003267/*
3268 * print a message with three spaces prepended and '\n' appended.
3269 */
3270 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003271main_msg(char *s)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003272{
3273 mch_msg(" ");
3274 mch_msg(s);
3275 mch_msg("\n");
3276}
3277
3278/*
3279 * Print messages for "vim -h" or "vim --help" and exit.
3280 */
3281 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003282usage(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003283{
3284 int i;
3285 static char *(use[]) =
3286 {
3287 N_("[file ..] edit specified file(s)"),
3288 N_("- read text from stdin"),
3289 N_("-t tag edit file where tag is defined"),
3290#ifdef FEAT_QUICKFIX
3291 N_("-q [errorfile] edit file with first error")
3292#endif
3293 };
3294
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003295#if defined(UNIX) || defined(VMS)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003296 reset_signals(); /* kill us with CTRL-C here, if you like */
3297#endif
3298
Bram Moolenaar35fb6fb2018-06-23 16:12:21 +02003299 init_longVersion();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003300 mch_msg(longVersion);
Bram Moolenaar32aaf5a2018-06-21 21:38:33 +02003301 mch_msg(_("\n\nUsage:"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003302 for (i = 0; ; ++i)
3303 {
3304 mch_msg(_(" vim [arguments] "));
3305 mch_msg(_(use[i]));
3306 if (i == (sizeof(use) / sizeof(char_u *)) - 1)
3307 break;
3308 mch_msg(_("\n or:"));
3309 }
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003310#ifdef VMS
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003311 mch_msg(_("\nWhere case is ignored prepend / to make flag upper case"));
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003312#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003313
3314 mch_msg(_("\n\nArguments:\n"));
3315 main_msg(_("--\t\t\tOnly file names after this"));
Bram Moolenaar53076832015-12-31 19:53:21 +01003316#ifdef EXPAND_FILENAMES
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003317 main_msg(_("--literal\t\tDon't expand wildcards"));
3318#endif
3319#ifdef FEAT_OLE
3320 main_msg(_("-register\t\tRegister this gvim for OLE"));
3321 main_msg(_("-unregister\t\tUnregister gvim for OLE"));
3322#endif
3323#ifdef FEAT_GUI
3324 main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")"));
3325 main_msg(_("-f or --nofork\tForeground: Don't fork when starting GUI"));
3326#endif
3327 main_msg(_("-v\t\t\tVi mode (like \"vi\")"));
3328 main_msg(_("-e\t\t\tEx mode (like \"ex\")"));
Bram Moolenaarf99bc6d2012-03-28 17:10:31 +02003329 main_msg(_("-E\t\t\tImproved Ex mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003330 main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")"));
3331#ifdef FEAT_DIFF
3332 main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")"));
3333#endif
3334 main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)"));
3335 main_msg(_("-R\t\t\tReadonly mode (like \"view\")"));
3336 main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")"));
3337 main_msg(_("-m\t\t\tModifications (writing files) not allowed"));
3338 main_msg(_("-M\t\t\tModifications in text not allowed"));
3339 main_msg(_("-b\t\t\tBinary mode"));
3340#ifdef FEAT_LISP
3341 main_msg(_("-l\t\t\tLisp mode"));
3342#endif
3343 main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'"));
3344 main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'"));
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003345 main_msg(_("-V[N][fname]\t\tBe verbose [level N] [log messages to fname]"));
3346#ifdef FEAT_EVAL
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003347 main_msg(_("-D\t\t\tDebugging mode"));
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003348#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003349 main_msg(_("-n\t\t\tNo swap file, use memory only"));
3350 main_msg(_("-r\t\t\tList swap files and exit"));
3351 main_msg(_("-r (with file name)\tRecover crashed session"));
3352 main_msg(_("-L\t\t\tSame as -r"));
3353#ifdef AMIGA
3354 main_msg(_("-f\t\t\tDon't use newcli to open window"));
3355 main_msg(_("-dev <device>\t\tUse <device> for I/O"));
3356#endif
3357#ifdef FEAT_ARABIC
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02003358 main_msg(_("-A\t\t\tStart in Arabic mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003359#endif
3360#ifdef FEAT_RIGHTLEFT
3361 main_msg(_("-H\t\t\tStart in Hebrew mode"));
3362#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003363 main_msg(_("-T <terminal>\tSet terminal type to <terminal>"));
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01003364 main_msg(_("--not-a-term\t\tSkip warning for input/output not being a terminal"));
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01003365 main_msg(_("--ttyfail\t\tExit if input or output is not a terminal"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003366 main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"));
3367#ifdef FEAT_GUI
3368 main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"));
3369#endif
3370 main_msg(_("--noplugin\t\tDon't load plugin scripts"));
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003371 main_msg(_("-p[N]\t\tOpen N tab pages (default: one for each file)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003372 main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)"));
3373 main_msg(_("-O[N]\t\tLike -o but split vertically"));
3374 main_msg(_("+\t\t\tStart at end of file"));
3375 main_msg(_("+<lnum>\t\tStart at line <lnum>"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003376 main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003377 main_msg(_("-c <command>\t\tExecute <command> after loading the first file"));
3378 main_msg(_("-S <session>\t\tSource file <session> after loading the first file"));
3379 main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>"));
3380 main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>"));
3381 main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>"));
3382#ifdef FEAT_CRYPT
3383 main_msg(_("-x\t\t\tEdit encrypted files"));
3384#endif
3385#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
3386# if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)
3387 main_msg(_("-display <display>\tConnect vim to this particular X-server"));
3388# endif
3389 main_msg(_("-X\t\t\tDo not connect to X server"));
3390#endif
3391#ifdef FEAT_CLIENTSERVER
3392 main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible"));
3393 main_msg(_("--remote-silent <files> Same, don't complain if there is no server"));
3394 main_msg(_("--remote-wait <files> As --remote but wait for files to have been edited"));
3395 main_msg(_("--remote-wait-silent <files> Same, don't complain if there is no server"));
Bram Moolenaar82ad3242008-01-11 19:26:36 +00003396 main_msg(_("--remote-tab[-wait][-silent] <files> As --remote but use tab page per file"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003397 main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit"));
3398 main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"));
3399 main_msg(_("--serverlist\t\tList available Vim server names and exit"));
3400 main_msg(_("--servername <name>\tSend to/become the Vim server <name>"));
3401#endif
Bram Moolenaaref94eec2009-11-11 13:22:11 +00003402#ifdef STARTUPTIME
Bram Moolenaar34ef52d2009-11-17 11:31:25 +00003403 main_msg(_("--startuptime <file>\tWrite startup timing messages to <file>"));
Bram Moolenaaref94eec2009-11-11 13:22:11 +00003404#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003405#ifdef FEAT_VIMINFO
3406 main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo"));
3407#endif
Bram Moolenaarc4da1132017-07-15 19:39:43 +02003408 main_msg(_("--clean\t\t'nocompatible', Vim defaults, no plugins, no viminfo"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003409 main_msg(_("-h or --help\tPrint Help (this message) and exit"));
3410 main_msg(_("--version\t\tPrint version information and exit"));
3411
3412#ifdef FEAT_GUI_X11
3413# ifdef FEAT_GUI_MOTIF
3414 mch_msg(_("\nArguments recognised by gvim (Motif version):\n"));
3415# else
3416# ifdef FEAT_GUI_ATHENA
3417# ifdef FEAT_GUI_NEXTAW
3418 mch_msg(_("\nArguments recognised by gvim (neXtaw version):\n"));
3419# else
3420 mch_msg(_("\nArguments recognised by gvim (Athena version):\n"));
3421# endif
3422# endif
3423# endif
3424 main_msg(_("-display <display>\tRun vim on <display>"));
3425 main_msg(_("-iconic\t\tStart vim iconified"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003426 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
3427 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
3428 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
3429 main_msg(_("-boldfont <font>\tUse <font> for bold text"));
3430 main_msg(_("-italicfont <font>\tUse <font> for italic text"));
3431 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
3432 main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)"));
3433 main_msg(_("-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"));
3434# ifdef FEAT_GUI_ATHENA
3435 main_msg(_("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"));
3436# endif
3437 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
3438 main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)"));
3439 main_msg(_("-xrm <resource>\tSet the specified resource"));
3440#endif /* FEAT_GUI_X11 */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003441#ifdef FEAT_GUI_GTK
3442 mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
3443 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
3444 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
3445 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
3446 main_msg(_("-display <display>\tRun vim on <display> (also: --display)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003447 main_msg(_("--role <role>\tSet a unique role to identify the main window"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003448 main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget"));
Bram Moolenaarf99bc6d2012-03-28 17:10:31 +02003449 main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003450#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01003451#ifdef FEAT_GUI_MSWIN
Bram Moolenaarafde13b2019-04-28 19:46:49 +02003452# ifdef VIMDLL
3453 if (gui.starting)
3454# endif
3455 {
3456 main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
3457 main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget"));
3458 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003459#endif
3460
3461#ifdef FEAT_GUI_GNOME
3462 /* Gnome gives extra messages for --help if we continue, but not for -h. */
3463 if (gui.starting)
Bram Moolenaarf4120a82011-12-08 15:57:59 +01003464 {
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003465 mch_msg("\n");
Bram Moolenaarf4120a82011-12-08 15:57:59 +01003466 gui.dofork = FALSE;
3467 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003468 else
3469#endif
3470 mch_exit(0);
3471}
3472
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003473/*
3474 * Check the result of the ATTENTION dialog:
3475 * When "Quit" selected, exit Vim.
3476 * When "Recover" selected, recover the file.
3477 */
3478 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003479check_swap_exists_action(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003480{
3481 if (swap_exists_action == SEA_QUIT)
3482 getout(1);
3483 handle_swap_exists(NULL);
3484}
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003485
Bram Moolenaar08cab962017-03-04 14:37:18 +01003486#endif /* NO_VIM_MAIN */
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003487
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003488#if defined(STARTUPTIME) || defined(PROTO)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003489static struct timeval prev_timeval;
3490
Bram Moolenaar4f974752019-02-17 17:44:42 +01003491# ifdef MSWIN
Bram Moolenaar3f269672009-11-03 11:11:11 +00003492/*
3493 * Windows doesn't have gettimeofday(), although it does have struct timeval.
3494 */
3495 static int
3496gettimeofday(struct timeval *tv, char *dummy)
3497{
3498 long t = clock();
3499 tv->tv_sec = t / CLOCKS_PER_SEC;
3500 tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC;
3501 return 0;
3502}
3503# endif
3504
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003505/*
3506 * Save the previous time before doing something that could nest.
3507 * set "*tv_rel" to the time elapsed so far.
3508 */
3509 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003510time_push(void *tv_rel, void *tv_start)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003511{
3512 *((struct timeval *)tv_rel) = prev_timeval;
3513 gettimeofday(&prev_timeval, NULL);
3514 ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec
3515 - ((struct timeval *)tv_rel)->tv_usec;
3516 ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec
3517 - ((struct timeval *)tv_rel)->tv_sec;
3518 if (((struct timeval *)tv_rel)->tv_usec < 0)
3519 {
3520 ((struct timeval *)tv_rel)->tv_usec += 1000000;
3521 --((struct timeval *)tv_rel)->tv_sec;
3522 }
3523 *(struct timeval *)tv_start = prev_timeval;
3524}
3525
3526/*
3527 * Compute the previous time after doing something that could nest.
3528 * Subtract "*tp" from prev_timeval;
3529 * Note: The arguments are (void *) to avoid trouble with systems that don't
3530 * have struct timeval.
3531 */
3532 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003533time_pop(
3534 void *tp) /* actually (struct timeval *) */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003535{
3536 prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec;
3537 prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec;
3538 if (prev_timeval.tv_usec < 0)
3539 {
3540 prev_timeval.tv_usec += 1000000;
3541 --prev_timeval.tv_sec;
3542 }
3543}
3544
3545 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003546time_diff(struct timeval *then, struct timeval *now)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003547{
3548 long usec;
3549 long msec;
3550
3551 usec = now->tv_usec - then->tv_usec;
3552 msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L,
3553 usec = usec % 1000L;
3554 fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L);
3555}
3556
3557 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003558time_msg(
3559 char *mesg,
3560 void *tv_start) /* only for do_source: start time; actually
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003561 (struct timeval *) */
3562{
3563 static struct timeval start;
3564 struct timeval now;
3565
3566 if (time_fd != NULL)
3567 {
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02003568 if (strstr(mesg, "STARTING") != NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003569 {
3570 gettimeofday(&start, NULL);
3571 prev_timeval = start;
3572 fprintf(time_fd, "\n\ntimes in msec\n");
3573 fprintf(time_fd, " clock self+sourced self: sourced script\n");
3574 fprintf(time_fd, " clock elapsed: other lines\n\n");
3575 }
3576 gettimeofday(&now, NULL);
3577 time_diff(&start, &now);
3578 if (((struct timeval *)tv_start) != NULL)
3579 {
3580 fprintf(time_fd, " ");
3581 time_diff(((struct timeval *)tv_start), &now);
3582 }
3583 fprintf(time_fd, " ");
3584 time_diff(&prev_timeval, &now);
3585 prev_timeval = now;
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02003586 fprintf(time_fd, ": %s\n", mesg);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003587 }
3588}
3589
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003590#endif
3591
Bram Moolenaar595297d2017-03-04 19:11:12 +01003592#if !defined(NO_VIM_MAIN) && defined(FEAT_EVAL)
Bram Moolenaar08cab962017-03-04 14:37:18 +01003593 static void
3594set_progpath(char_u *argv0)
3595{
3596 char_u *val = argv0;
Bram Moolenaar08cab962017-03-04 14:37:18 +01003597
Bram Moolenaar4f974752019-02-17 17:44:42 +01003598# ifdef MSWIN
Bram Moolenaar08cab962017-03-04 14:37:18 +01003599 /* A relative path containing a "/" will become invalid when using ":cd",
3600 * turn it into a full path.
Bram Moolenaar066029e2017-03-05 15:19:32 +01003601 * On MS-Windows "vim" should be expanded to "vim.exe", thus always do
3602 * this. */
Bram Moolenaar066029e2017-03-05 15:19:32 +01003603 char_u *path = NULL;
3604
3605 if (mch_can_exe(argv0, &path, FALSE) && path != NULL)
3606 val = path;
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003607# else
3608 char_u buf[MAXPATHL + 1];
3609# ifdef PROC_EXE_LINK
3610 char linkbuf[MAXPATHL + 1];
3611 ssize_t len;
Bram Moolenaar066029e2017-03-05 15:19:32 +01003612
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003613 len = readlink(PROC_EXE_LINK, linkbuf, MAXPATHL);
3614 if (len > 0)
Bram Moolenaar43663192017-03-05 14:29:12 +01003615 {
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003616 linkbuf[len] = NUL;
3617 val = (char_u *)linkbuf;
Bram Moolenaar43663192017-03-05 14:29:12 +01003618 }
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003619# endif
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003620
3621 if (!mch_isFullName(val))
3622 {
3623 if (gettail(val) != val
3624 && vim_FullName(val, buf, MAXPATHL, TRUE) != FAIL)
3625 val = buf;
3626 }
Bram Moolenaar066029e2017-03-05 15:19:32 +01003627# endif
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003628
Bram Moolenaar08cab962017-03-04 14:37:18 +01003629 set_vim_var_string(VV_PROGPATH, val, -1);
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003630
Bram Moolenaar4f974752019-02-17 17:44:42 +01003631# ifdef MSWIN
Bram Moolenaar43663192017-03-05 14:29:12 +01003632 vim_free(path);
Bram Moolenaar066029e2017-03-05 15:19:32 +01003633# endif
Bram Moolenaar08cab962017-03-04 14:37:18 +01003634}
3635
3636#endif /* NO_VIM_MAIN */
3637
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003638#if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003639
3640/*
3641 * Common code for the X command server and the Win32 command server.
3642 */
3643
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +01003644static char_u *build_drop_cmd(int filec, char **filev, int tabs, int sendReply);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003645
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003646/*
3647 * Do the client-server stuff, unless "--servername ''" was used.
3648 */
3649 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003650exec_on_server(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003651{
3652 if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL)
3653 {
Bram Moolenaar4f974752019-02-17 17:44:42 +01003654# ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003655 /* Initialise the client/server messaging infrastructure. */
3656 serverInitMessaging();
3657# endif
3658
3659 /*
3660 * When a command server argument was found, execute it. This may
3661 * exit Vim when it was successful. Otherwise it's executed further
3662 * on. Remember the encoding used here in "serverStrEnc".
3663 */
3664 if (parmp->serverArg)
3665 {
3666 cmdsrv_main(&parmp->argc, parmp->argv,
3667 parmp->serverName_arg, &parmp->serverStr);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003668 parmp->serverStrEnc = vim_strsave(p_enc);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003669 }
3670
3671 /* If we're still running, get the name to register ourselves.
3672 * On Win32 can register right now, for X11 need to setup the
3673 * clipboard first, it's further down. */
3674 parmp->servername = serverMakeName(parmp->serverName_arg,
3675 parmp->argv[0]);
Bram Moolenaar4f974752019-02-17 17:44:42 +01003676# ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003677 if (parmp->servername != NULL)
3678 {
3679 serverSetName(parmp->servername);
3680 vim_free(parmp->servername);
3681 }
3682# endif
3683 }
3684}
3685
3686/*
3687 * Prepare for running as a Vim server.
3688 */
3689 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003690prepare_server(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003691{
3692# if defined(FEAT_X11)
3693 /*
3694 * Register for remote command execution with :serversend and --remote
3695 * unless there was a -X or a --servername '' on the command line.
Bram Moolenaare42a6d22017-11-12 19:21:51 +01003696 * Only register nongui-vim's with an explicit --servername argument,
3697 * or when compiling with autoservername.
Bram Moolenaar5f402312006-08-15 19:40:35 +00003698 * When running as root --servername is also required.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003699 */
3700 if (X_DISPLAY != NULL && parmp->servername != NULL && (
Bram Moolenaare42a6d22017-11-12 19:21:51 +01003701# if defined(FEAT_AUTOSERVERNAME) || defined(FEAT_GUI)
3702 (
3703# if defined(FEAT_AUTOSERVERNAME)
3704 1
3705# else
3706 gui.in_use
3707# endif
Bram Moolenaar5f402312006-08-15 19:40:35 +00003708# ifdef UNIX
Bram Moolenaar311d9822007-02-27 15:48:28 +00003709 && getuid() != ROOT_UID
Bram Moolenaar5f402312006-08-15 19:40:35 +00003710# endif
3711 ) ||
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003712# endif
3713 parmp->serverName_arg != NULL))
3714 {
3715 (void)serverRegisterName(X_DISPLAY, parmp->servername);
3716 vim_free(parmp->servername);
3717 TIME_MSG("register server name");
3718 }
3719 else
3720 serverDelayedStartName = parmp->servername;
3721# endif
3722
3723 /*
3724 * Execute command ourselves if we're here because the send failed (or
3725 * else we would have exited above).
3726 */
3727 if (parmp->serverStr != NULL)
3728 {
3729 char_u *p;
3730
3731 server_to_input_buf(serverConvert(parmp->serverStrEnc,
3732 parmp->serverStr, &p));
3733 vim_free(p);
3734 }
3735}
3736
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003737 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003738cmdsrv_main(
3739 int *argc,
3740 char **argv,
3741 char_u *serverName_arg,
3742 char_u **serverStr)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003743{
3744 char_u *res;
3745 int i;
3746 char_u *sname;
3747 int ret;
3748 int didone = FALSE;
3749 int exiterr = 0;
3750 char **newArgV = argv + 1;
3751 int newArgC = 1,
3752 Argc = *argc;
3753 int argtype;
3754#define ARGTYPE_OTHER 0
3755#define ARGTYPE_EDIT 1
3756#define ARGTYPE_EDIT_WAIT 2
3757#define ARGTYPE_SEND 3
3758 int silent = FALSE;
Bram Moolenaareb94e552006-03-11 21:35:11 +00003759 int tabs = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003760# ifndef FEAT_X11
3761 HWND srv;
3762# else
3763 Window srv;
3764
3765 setup_term_clip();
3766# endif
3767
3768 sname = serverMakeName(serverName_arg, argv[0]);
3769 if (sname == NULL)
3770 return;
3771
3772 /*
3773 * Execute the command server related arguments and remove them
3774 * from the argc/argv array; We may have to return into main()
3775 */
3776 for (i = 1; i < Argc; i++)
3777 {
3778 res = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003779 if (STRCMP(argv[i], "--") == 0) /* end of option arguments */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003780 {
3781 for (; i < *argc; i++)
3782 {
3783 *newArgV++ = argv[i];
3784 newArgC++;
3785 }
3786 break;
3787 }
3788
Bram Moolenaareb94e552006-03-11 21:35:11 +00003789 if (STRICMP(argv[i], "--remote-send") == 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003790 argtype = ARGTYPE_SEND;
Bram Moolenaareb94e552006-03-11 21:35:11 +00003791 else if (STRNICMP(argv[i], "--remote", 8) == 0)
3792 {
3793 char *p = argv[i] + 8;
3794
3795 argtype = ARGTYPE_EDIT;
3796 while (*p != NUL)
3797 {
3798 if (STRNICMP(p, "-wait", 5) == 0)
3799 {
3800 argtype = ARGTYPE_EDIT_WAIT;
3801 p += 5;
3802 }
3803 else if (STRNICMP(p, "-silent", 7) == 0)
3804 {
3805 silent = TRUE;
3806 p += 7;
3807 }
3808 else if (STRNICMP(p, "-tab", 4) == 0)
3809 {
3810 tabs = TRUE;
3811 p += 4;
3812 }
3813 else
3814 {
3815 argtype = ARGTYPE_OTHER;
3816 break;
3817 }
3818 }
3819 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003820 else
3821 argtype = ARGTYPE_OTHER;
Bram Moolenaareb94e552006-03-11 21:35:11 +00003822
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003823 if (argtype != ARGTYPE_OTHER)
3824 {
3825 if (i == *argc - 1)
3826 mainerr_arg_missing((char_u *)argv[i]);
3827 if (argtype == ARGTYPE_SEND)
3828 {
3829 *serverStr = (char_u *)argv[i + 1];
3830 i++;
3831 }
3832 else
3833 {
3834 *serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1,
Bram Moolenaareb94e552006-03-11 21:35:11 +00003835 tabs, argtype == ARGTYPE_EDIT_WAIT);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003836 if (*serverStr == NULL)
3837 {
3838 /* Probably out of memory, exit. */
3839 didone = TRUE;
3840 exiterr = 1;
3841 break;
3842 }
3843 Argc = i;
3844 }
3845# ifdef FEAT_X11
3846 if (xterm_dpy == NULL)
3847 {
3848 mch_errmsg(_("No display"));
3849 ret = -1;
3850 }
3851 else
3852 ret = serverSendToVim(xterm_dpy, sname, *serverStr,
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003853 NULL, &srv, 0, 0, 0, silent);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003854# else
3855 /* Win32 always works? */
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003856 ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, 0, silent);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003857# endif
3858 if (ret < 0)
3859 {
3860 if (argtype == ARGTYPE_SEND)
3861 {
3862 /* Failed to send, abort. */
3863 mch_errmsg(_(": Send failed.\n"));
3864 didone = TRUE;
3865 exiterr = 1;
3866 }
3867 else if (!silent)
3868 /* Let vim start normally. */
3869 mch_errmsg(_(": Send failed. Trying to execute locally\n"));
3870 break;
3871 }
3872
Bram Moolenaar4f974752019-02-17 17:44:42 +01003873# ifdef FEAT_GUI_MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003874 /* Guess that when the server name starts with "g" it's a GUI
3875 * server, which we can bring to the foreground here.
3876 * Foreground() in the server doesn't work very well. */
3877 if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G')
3878 SetForegroundWindow(srv);
3879# endif
3880
3881 /*
3882 * For --remote-wait: Wait until the server did edit each
3883 * file. Also detect that the server no longer runs.
3884 */
3885 if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT)
3886 {
3887 int numFiles = *argc - i - 1;
3888 int j;
3889 char_u *done = alloc(numFiles);
3890 char_u *p;
Bram Moolenaar4f974752019-02-17 17:44:42 +01003891# ifdef FEAT_GUI_MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003892 NOTIFYICONDATA ni;
3893 int count = 0;
3894 extern HWND message_window;
3895# endif
3896
3897 if (numFiles > 0 && argv[i + 1][0] == '+')
3898 /* Skip "+cmd" argument, don't wait for it to be edited. */
3899 --numFiles;
3900
Bram Moolenaar4f974752019-02-17 17:44:42 +01003901# ifdef FEAT_GUI_MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003902 ni.cbSize = sizeof(ni);
3903 ni.hWnd = message_window;
3904 ni.uID = 0;
3905 ni.uFlags = NIF_ICON|NIF_TIP;
3906 ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM");
3907 sprintf(ni.szTip, _("%d of %d edited"), count, numFiles);
3908 Shell_NotifyIcon(NIM_ADD, &ni);
3909# endif
3910
3911 /* Wait for all files to unload in remote */
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02003912 vim_memset(done, 0, numFiles);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003913 while (memchr(done, 0, numFiles) != NULL)
3914 {
Bram Moolenaar4f974752019-02-17 17:44:42 +01003915# ifdef MSWIN
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003916 p = serverGetReply(srv, NULL, TRUE, TRUE, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003917 if (p == NULL)
3918 break;
3919# else
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003920 if (serverReadReply(xterm_dpy, srv, &p, TRUE, -1) < 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003921 break;
3922# endif
3923 j = atoi((char *)p);
3924 if (j >= 0 && j < numFiles)
3925 {
Bram Moolenaar4f974752019-02-17 17:44:42 +01003926# ifdef FEAT_GUI_MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003927 ++count;
3928 sprintf(ni.szTip, _("%d of %d edited"),
3929 count, numFiles);
3930 Shell_NotifyIcon(NIM_MODIFY, &ni);
3931# endif
3932 done[j] = 1;
3933 }
3934 }
Bram Moolenaar4f974752019-02-17 17:44:42 +01003935# ifdef FEAT_GUI_MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003936 Shell_NotifyIcon(NIM_DELETE, &ni);
3937# endif
3938 }
3939 }
3940 else if (STRICMP(argv[i], "--remote-expr") == 0)
3941 {
3942 if (i == *argc - 1)
3943 mainerr_arg_missing((char_u *)argv[i]);
Bram Moolenaar4f974752019-02-17 17:44:42 +01003944# ifdef MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003945 /* Win32 always works? */
3946 if (serverSendToVim(sname, (char_u *)argv[i + 1],
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003947 &res, NULL, 1, 0, FALSE) < 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003948# else
3949 if (xterm_dpy == NULL)
3950 mch_errmsg(_("No display: Send expression failed.\n"));
3951 else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1],
Bram Moolenaar81b9d0b2017-03-19 21:20:53 +01003952 &res, NULL, 1, 0, 1, FALSE) < 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003953# endif
3954 {
3955 if (res != NULL && *res != NUL)
3956 {
3957 /* Output error from remote */
3958 mch_errmsg((char *)res);
Bram Moolenaard23a8232018-02-10 18:45:26 +01003959 VIM_CLEAR(res);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003960 }
3961 mch_errmsg(_(": Send expression failed.\n"));
3962 }
3963 }
3964 else if (STRICMP(argv[i], "--serverlist") == 0)
3965 {
Bram Moolenaar4f974752019-02-17 17:44:42 +01003966# ifdef MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003967 /* Win32 always works? */
3968 res = serverGetVimNames();
3969# else
3970 if (xterm_dpy != NULL)
3971 res = serverGetVimNames(xterm_dpy);
3972# endif
3973 if (called_emsg)
3974 mch_errmsg("\n");
3975 }
3976 else if (STRICMP(argv[i], "--servername") == 0)
3977 {
Bram Moolenaar5d985b92009-12-16 17:28:07 +00003978 /* Already processed. Take it out of the command line */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003979 i++;
3980 continue;
3981 }
3982 else
3983 {
3984 *newArgV++ = argv[i];
3985 newArgC++;
3986 continue;
3987 }
3988 didone = TRUE;
3989 if (res != NULL && *res != NUL)
3990 {
3991 mch_msg((char *)res);
3992 if (res[STRLEN(res) - 1] != '\n')
3993 mch_msg("\n");
3994 }
3995 vim_free(res);
3996 }
3997
3998 if (didone)
3999 {
4000 display_errors(); /* display any collected messages */
4001 exit(exiterr); /* Mission accomplished - get out */
4002 }
4003
4004 /* Return back into main() */
4005 *argc = newArgC;
4006 vim_free(sname);
4007}
4008
4009/*
4010 * Build a ":drop" command to send to a Vim server.
4011 */
4012 static char_u *
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01004013build_drop_cmd(
4014 int filec,
4015 char **filev,
4016 int tabs, /* Use ":tab drop" instead of ":drop". */
4017 int sendReply)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004018{
4019 garray_T ga;
4020 int i;
4021 char_u *inicmd = NULL;
4022 char_u *p;
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004023 char_u *cdp;
Bram Moolenaard9462e32011-04-11 21:35:11 +02004024 char_u *cwd;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004025
4026 if (filec > 0 && filev[0][0] == '+')
4027 {
4028 inicmd = (char_u *)filev[0] + 1;
4029 filev++;
4030 filec--;
4031 }
4032 /* Check if we have at least one argument. */
4033 if (filec <= 0)
4034 mainerr_arg_missing((char_u *)filev[-1]);
Bram Moolenaar00b78c12010-11-16 16:25:51 +01004035
4036 /* Temporarily cd to the current directory to handle relative file names. */
Bram Moolenaard9462e32011-04-11 21:35:11 +02004037 cwd = alloc(MAXPATHL);
4038 if (cwd == NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004039 return NULL;
Bram Moolenaard9462e32011-04-11 21:35:11 +02004040 if (mch_dirname(cwd, MAXPATHL) != OK)
4041 {
4042 vim_free(cwd);
4043 return NULL;
4044 }
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004045 cdp = vim_strsave_escaped_ext(cwd,
Bram Moolenaar02b06312007-09-06 15:39:22 +00004046#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +01004047 (char_u *)"", /* rem_backslash() will tell what chars to escape */
Bram Moolenaar02b06312007-09-06 15:39:22 +00004048#else
4049 PATH_ESC_CHARS,
4050#endif
Bram Moolenaard9462e32011-04-11 21:35:11 +02004051 '\\', TRUE);
4052 vim_free(cwd);
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004053 if (cdp == NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004054 return NULL;
4055 ga_init2(&ga, 1, 100);
4056 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004057 ga_concat(&ga, cdp);
Bram Moolenaareb94e552006-03-11 21:35:11 +00004058
4059 /* Call inputsave() so that a prompt for an encryption key works. */
4060 ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|");
4061 if (tabs)
4062 ga_concat(&ga, (char_u *)"tab ");
4063 ga_concat(&ga, (char_u *)"drop");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004064 for (i = 0; i < filec; i++)
4065 {
4066 /* On Unix the shell has already expanded the wildcards, don't want to
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00004067 * do it again in the Vim server. On MS-Windows only escape
4068 * non-wildcard characters. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004069 p = vim_strsave_escaped((char_u *)filev[i],
4070#ifdef UNIX
4071 PATH_ESC_CHARS
4072#else
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00004073 (char_u *)" \t%#"
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004074#endif
4075 );
4076 if (p == NULL)
4077 {
4078 vim_free(ga.ga_data);
4079 return NULL;
4080 }
4081 ga_concat(&ga, (char_u *)" ");
4082 ga_concat(&ga, p);
4083 vim_free(p);
4084 }
Bram Moolenaar00b78c12010-11-16 16:25:51 +01004085 ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>");
4086
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004087 /* The :drop commands goes to Insert mode when 'insertmode' is set, use
4088 * CTRL-\ CTRL-N again. */
Bram Moolenaar00b78c12010-11-16 16:25:51 +01004089 ga_concat(&ga, (char_u *)"<C-\\><C-N>");
4090
4091 /* Switch back to the correct current directory (prior to temporary path
4092 * switch) unless 'autochdir' is set, in which case it will already be
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004093 * correct after the :drop command. With line breaks and spaces:
4094 * if !exists('+acd') || !&acd
4095 * if haslocaldir()
4096 * cd -
4097 * lcd -
Bram Moolenaarfafeee62015-07-03 13:33:01 +02004098 * elseif getcwd() ==# 'current path'
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004099 * cd -
4100 * endif
4101 * endif
4102 */
4103 ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|");
Bram Moolenaarfafeee62015-07-03 13:33:01 +02004104 ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '");
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004105 ga_concat(&ga, cdp);
Bram Moolenaarfafeee62015-07-03 13:33:01 +02004106 ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>");
Bram Moolenaarf11ce662015-03-24 16:48:58 +01004107 vim_free(cdp);
Bram Moolenaar00b78c12010-11-16 16:25:51 +01004108
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004109 if (sendReply)
Bram Moolenaar00b78c12010-11-16 16:25:51 +01004110 ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>");
4111 ga_concat(&ga, (char_u *)":");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004112 if (inicmd != NULL)
4113 {
4114 /* Can't use <CR> after "inicmd", because an "startinsert" would cause
4115 * the following commands to be inserted as text. Use a "|",
4116 * hopefully "inicmd" does allow this... */
4117 ga_concat(&ga, inicmd);
4118 ga_concat(&ga, (char_u *)"|");
4119 }
4120 /* Bring the window to the foreground, goto Insert mode when 'im' set and
4121 * clear command line. */
Bram Moolenaar567e4de2004-12-31 21:01:02 +00004122 ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004123 ga_append(&ga, NUL);
4124 return ga.ga_data;
4125}
4126
4127/*
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01004128 * Make our basic server name: use the specified "arg" if given, otherwise use
4129 * the tail of the command "cmd" we were started with.
4130 * Return the name in allocated memory. This doesn't include a serial number.
4131 */
4132 static char_u *
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01004133serverMakeName(char_u *arg, char *cmd)
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01004134{
4135 char_u *p;
4136
4137 if (arg != NULL && *arg != NUL)
4138 p = vim_strsave_up(arg);
4139 else
4140 {
4141 p = vim_strsave_up(gettail((char_u *)cmd));
4142 /* Remove .exe or .bat from the name. */
4143 if (p != NULL && vim_strchr(p, '.') != NULL)
4144 *vim_strchr(p, '.') = NUL;
4145 }
4146 return p;
4147}
4148#endif /* FEAT_CLIENTSERVER */
4149
4150#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
4151/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004152 * Replace termcodes such as <CR> and insert as key presses if there is room.
4153 */
4154 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01004155server_to_input_buf(char_u *str)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004156{
4157 char_u *ptr = NULL;
4158 char_u *cpo_save = p_cpo;
4159
4160 /* Set 'cpoptions' the way we want it.
4161 * B set - backslashes are *not* treated specially
4162 * k set - keycodes are *not* reverse-engineered
4163 * < unset - <Key> sequences *are* interpreted
Bram Moolenaar8b2d9c42006-05-03 21:28:47 +00004164 * The last but one parameter of replace_termcodes() is TRUE so that the
4165 * <lt> sequence is recognised - needed for a real backslash.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004166 */
4167 p_cpo = (char_u *)"Bk";
Bram Moolenaar8b2d9c42006-05-03 21:28:47 +00004168 str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004169 p_cpo = cpo_save;
4170
4171 if (*ptr != NUL) /* trailing CTRL-V results in nothing */
4172 {
4173 /*
4174 * Add the string to the input stream.
4175 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
4176 *
4177 * First clear typed characters from the typeahead buffer, there could
4178 * be half a mapping there. Then append to the existing string, so
4179 * that multiple commands from a client are concatenated.
4180 */
4181 if (typebuf.tb_maplen < typebuf.tb_len)
4182 del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
4183 (void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE);
4184
4185 /* Let input_available() know we inserted text in the typeahead
4186 * buffer. */
Bram Moolenaar4a85b412006-04-23 22:40:29 +00004187 typebuf_was_filled = TRUE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004188 }
4189 vim_free((char_u *)ptr);
4190}
4191
4192/*
4193 * Evaluate an expression that the client sent to a string.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004194 */
4195 char_u *
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01004196eval_client_expr_to_string(char_u *expr)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004197{
4198 char_u *res;
4199 int save_dbl = debug_break_level;
4200 int save_ro = redir_off;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02004201 funccal_entry_T funccal_entry;
4202 int did_save_funccal = FALSE;
Bram Moolenaar7a43cb92017-03-18 18:15:16 +01004203
4204 /* Evaluate the expression at the toplevel, don't use variables local to
Bram Moolenaard99388b2017-10-26 14:28:32 +02004205 * the calling function. Except when in debug mode. */
4206 if (!debug_mode)
Bram Moolenaar27e80c82018-10-14 21:41:01 +02004207 {
4208 save_funccal(&funccal_entry);
4209 did_save_funccal = TRUE;
4210 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004211
Bram Moolenaar1e284f52013-03-13 20:23:22 +01004212 /* Disable debugging, otherwise Vim hangs, waiting for "cont" to be
4213 * typed. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004214 debug_break_level = -1;
4215 redir_off = 0;
Bram Moolenaar1e284f52013-03-13 20:23:22 +01004216 /* Do not display error message, otherwise Vim hangs, waiting for "cont"
4217 * to be typed. Do generate errors so that try/catch works. */
4218 ++emsg_silent;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004219
Bram Moolenaar362e1a32006-03-06 23:29:24 +00004220 res = eval_to_string(expr, NULL, TRUE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004221
4222 debug_break_level = save_dbl;
4223 redir_off = save_ro;
Bram Moolenaar1e284f52013-03-13 20:23:22 +01004224 --emsg_silent;
4225 if (emsg_silent < 0)
4226 emsg_silent = 0;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02004227 if (did_save_funccal)
4228 restore_funccal();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004229
Bram Moolenaar63a121b2005-12-11 21:36:39 +00004230 /* A client can tell us to redraw, but not to display the cursor, so do
4231 * that here. */
4232 setcursor();
Bram Moolenaara338adc2018-01-31 20:51:47 +01004233 out_flush_cursor(FALSE, FALSE);
Bram Moolenaar63a121b2005-12-11 21:36:39 +00004234
Bram Moolenaarb4210b32004-06-13 14:51:16 +00004235 return res;
4236}
4237
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004238/*
Bram Moolenaar7a43cb92017-03-18 18:15:16 +01004239 * Evaluate a command or expression sent to ourselves.
4240 */
4241 int
4242sendToLocalVim(char_u *cmd, int asExpr, char_u **result)
4243{
4244 if (asExpr)
4245 {
4246 char_u *ret;
4247
4248 ret = eval_client_expr_to_string(cmd);
4249 if (result != NULL)
4250 {
4251 if (ret == NULL)
4252 {
4253 char *err = _(e_invexprmsg);
4254 size_t len = STRLEN(cmd) + STRLEN(err) + 5;
4255 char_u *msg;
4256
Bram Moolenaar1662ce12017-03-19 21:47:50 +01004257 msg = alloc((unsigned)len);
Bram Moolenaar7a43cb92017-03-18 18:15:16 +01004258 if (msg != NULL)
4259 vim_snprintf((char *)msg, len, "%s: \"%s\"", err, cmd);
4260 *result = msg;
4261 }
4262 else
4263 *result = ret;
4264 }
4265 else
4266 vim_free(ret);
4267 return ret == NULL ? -1 : 0;
4268 }
4269 server_to_input_buf(cmd);
4270 return 0;
4271}
4272
4273/*
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004274 * If conversion is needed, convert "data" from "client_enc" to 'encoding' and
4275 * return an allocated string. Otherwise return "data".
4276 * "*tofree" is set to the result when it needs to be freed later.
4277 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004278 char_u *
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01004279serverConvert(
4280 char_u *client_enc UNUSED,
4281 char_u *data,
4282 char_u **tofree)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004283{
4284 char_u *res = data;
4285
4286 *tofree = NULL;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004287 if (client_enc != NULL && p_enc != NULL)
4288 {
4289 vimconv_T vimconv;
4290
4291 vimconv.vc_type = CONV_NONE;
4292 if (convert_setup(&vimconv, client_enc, p_enc) != FAIL
4293 && vimconv.vc_type != CONV_NONE)
4294 {
4295 res = string_convert(&vimconv, data, NULL);
4296 if (res == NULL)
4297 res = data;
4298 else
4299 *tofree = res;
4300 }
4301 convert_setup(&vimconv, NULL, NULL);
4302 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004303 return res;
4304}
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01004305#endif