blob: 5c767a21b35014e1d7e21499ff8c6c29f89e8c06 [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__
K.Takata972db232022-02-04 10:45:38 +000014# include <cygwin/version.h>
15# include <sys/cygwin.h> // for cygwin_conv_to_posix_path() and/or
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010016 // cygwin_conv_path()
Bram Moolenaarb4210b32004-06-13 14:51:16 +000017# include <limits.h>
18#endif
19
Bram Moolenaarafde13b2019-04-28 19:46:49 +020020#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
Bram Moolenaar97ff9b92016-06-26 20:37:46 +020021# include "iscygpty.h"
22#endif
23
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010024// Values for edit_type.
25#define EDIT_NONE 0 // no edit type yet
26#define EDIT_FILE 1 // file name argument[s] given, use argument list
27#define EDIT_STDIN 2 // read file from stdin
28#define EDIT_TAG 3 // tag name argument given, use tagname
29#define EDIT_QF 4 // start in quickfix mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +000030
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010031#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010032static int file_owned(char *fname);
Bram Moolenaarb4210b32004-06-13 14:51:16 +000033#endif
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010034static void mainerr(int, char_u *);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +020035static void early_arg_scan(mparm_T *parmp);
Bram Moolenaarb05b10a2011-03-22 18:10:45 +010036#ifndef NO_VIM_MAIN
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010037static void usage(void);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010038static void parse_command_name(mparm_T *parmp);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010039static void command_line_scan(mparm_T *parmp);
40static void check_tty(mparm_T *parmp);
41static void read_stdin(void);
42static void create_windows(mparm_T *parmp);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010043static void edit_buffers(mparm_T *parmp, char_u *cwd);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010044static void exe_pre_commands(mparm_T *parmp);
45static void exe_commands(mparm_T *parmp);
46static void source_startup_scripts(mparm_T *parmp);
47static void main_start_gui(void);
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010048static void check_swap_exists_action(void);
Bram Moolenaar08cab962017-03-04 14:37:18 +010049# ifdef FEAT_EVAL
50static void set_progpath(char_u *argv0);
51# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +000052#endif
53
54
Bram Moolenaarb4210b32004-06-13 14:51:16 +000055/*
56 * Different types of error messages.
57 */
58static char *(main_errors[]) =
59{
Bram Moolenaarc013cb62005-07-24 21:18:31 +000060 N_("Unknown option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +000061#define ME_UNKNOWN_OPTION 0
62 N_("Too many edit arguments"),
63#define ME_TOO_MANY_ARGS 1
64 N_("Argument missing after"),
65#define ME_ARG_MISSING 2
Bram Moolenaarc013cb62005-07-24 21:18:31 +000066 N_("Garbage after option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +000067#define ME_GARBAGE 3
68 N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),
69#define ME_EXTRA_CMD 4
70 N_("Invalid argument for"),
71#define ME_INVALID_ARG 5
72};
73
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010074#ifndef PROTO // don't want a prototype for main()
Bram Moolenaara6044292017-04-02 18:19:53 +020075
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010076// Various parameters passed between main() and other functions.
Bram Moolenaara6044292017-04-02 18:19:53 +020077static mparm_T params;
78
K.Takata3c240f62023-05-31 12:47:45 +010079#ifdef _IOLBF
80static void *s_vbuf = NULL; // buffer for setvbuf()
81#endif
82
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010083#ifndef NO_VIM_MAIN // skip this for unittests
Bram Moolenaarf9bde2b2015-04-17 22:08:16 +020084
Bram Moolenaar4ba37b52019-12-04 21:57:43 +010085static char_u *start_dir = NULL; // current working dir on startup
Bram Moolenaarf9bde2b2015-04-17 22:08:16 +020086
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +020087static int has_dash_c_arg = FALSE;
88
Bram Moolenaarafde13b2019-04-28 19:46:49 +020089# ifdef VIMDLL
90__declspec(dllexport)
91# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +000092 int
Bram Moolenaar796cc422019-04-03 20:31:00 +020093# ifdef MSWIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +000094VimMain
95# else
96main
97# endif
Bram Moolenaar52ea13d2016-01-30 18:51:09 +010098(int argc, char **argv)
Bram Moolenaarb4210b32004-06-13 14:51:16 +000099{
Bram Moolenaar77780b62018-03-01 23:10:45 +0100100#if defined(STARTUPTIME) || defined(CLEAN_RUNTIMEPATH)
Bram Moolenaar3f269672009-11-03 11:11:11 +0000101 int i;
102#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000103
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000104 /*
105 * Do any system-specific initialisations. These can NOT use IObuff or
106 * NameBuff. Thus emsg2() cannot be called!
107 */
108 mch_early_init();
109
Bram Moolenaar4f974752019-02-17 17:44:42 +0100110#ifdef MSWIN
Bram Moolenaar14993322014-09-09 12:25:33 +0200111 /*
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200112 * MinGW expands command line arguments, which confuses our code to
Bram Moolenaar14993322014-09-09 12:25:33 +0200113 * convert when 'encoding' changes. Get the unexpanded arguments.
114 */
115 argc = get_cmd_argsW(&argv);
116#endif
117
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100118 // Many variables are in "params" so that we can pass them to invoked
119 // functions without a lot of arguments. "argc" and "argv" are also
120 // copied, so that they can be changed.
Bram Moolenaara80faa82020-04-12 19:37:17 +0200121 CLEAR_FIELD(params);
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000122 params.argc = argc;
123 params.argv = argv;
124 params.want_full_screen = TRUE;
125#ifdef FEAT_EVAL
126 params.use_debug_break_level = -1;
127#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000128 params.window_count = -1;
Bram Moolenaar58d98232005-07-23 22:25:46 +0000129
Bram Moolenaare76062c2022-11-28 18:51:43 +0000130 autocmd_init();
131
Bram Moolenaar99685e62013-05-11 13:56:18 +0200132#ifdef FEAT_RUBY
133 {
134 int ruby_stack_start;
135 vim_ruby_init((void *)&ruby_stack_start);
136 }
137#endif
138
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000139#ifdef FEAT_TCL
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000140 vim_tcl_init(params.argv[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000141#endif
142
143#ifdef MEM_PROFILE
144 atexit(vim_mem_profile_dump);
145#endif
146
Hirohito Higashic5654b82025-02-10 20:55:17 +0100147 /*
148 * Various initialisations #1 shared with tests.
149 */
150 common_init_1();
151
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +0100152#if defined(STARTUPTIME) || defined(FEAT_JOB_CHANNEL)
153 // Need to find "--startuptime" and "--log" before actually parsing
154 // arguments.
Bram Moolenaar07268702018-03-01 21:57:32 +0100155 for (i = 1; i < argc - 1; ++i)
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +0100156 {
157# ifdef STARTUPTIME
158 if (STRICMP(argv[i], "--startuptime") == 0 && time_fd == NULL)
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 ---");
Bram Moolenaar3f269672009-11-03 11:11:11 +0000162 }
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +0100163# endif
Bram Moolenaar4c5678f2022-11-30 18:12:19 +0000164# ifdef FEAT_EVAL
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +0100165 if (STRICMP(argv[i], "--log") == 0)
Bram Moolenaar1d97db32022-06-04 22:15:54 +0100166 ch_logfile((char_u *)(argv[i + 1]), (char_u *)"ao");
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +0100167# endif
168 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000169#endif
170
Bram Moolenaar07268702018-03-01 21:57:32 +0100171#ifdef CLEAN_RUNTIMEPATH
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100172 // Need to find "--clean" before actually parsing arguments.
Bram Moolenaar07268702018-03-01 21:57:32 +0100173 for (i = 1; i < argc; ++i)
174 if (STRICMP(argv[i], "--clean") == 0)
175 {
176 params.clean = TRUE;
177 break;
178 }
179#endif
Bram Moolenaar3d0e7a92021-05-01 17:46:03 +0200180#ifdef MSWIN
Bram Moolenaar4a228972021-05-01 22:41:39 +0200181 // Need to find "-register" and "-unregister" before loading any libraries.
Bram Moolenaar3d0e7a92021-05-01 17:46:03 +0200182 for (i = 1; i < argc; ++i)
Bram Moolenaar4a228972021-05-01 22:41:39 +0200183 if ((STRICMP(argv[i] + 1, "register") == 0
184 || STRICMP(argv[i] + 1, "unregister") == 0)
185 && (argv[i][0] == '-' || argv[i][0] == '/'))
Bram Moolenaar3d0e7a92021-05-01 17:46:03 +0200186 {
187 found_register_arg = TRUE;
188 break;
189 }
190#endif
191
192 /*
Hirohito Higashic5654b82025-02-10 20:55:17 +0100193 * Various initialisations #2 shared with tests.
Bram Moolenaar3d0e7a92021-05-01 17:46:03 +0200194 */
Hirohito Higashic5654b82025-02-10 20:55:17 +0100195 common_init_2(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000196
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200197#ifdef VIMDLL
198 // Check if the current executable file is for the GUI subsystem.
199 gui.starting = mch_is_gui_executable();
Bram Moolenaar0b75f7c2019-05-08 22:28:46 +0200200#elif defined(FEAT_GUI_MSWIN)
201 gui.starting = TRUE;
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200202#endif
203
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000204#ifdef FEAT_CLIENTSERVER
205 /*
206 * Do the client-server stuff, unless "--servername ''" was used.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000207 * This may exit Vim if the command was sent to the server.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000208 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000209 exec_on_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000210#endif
211
212 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000213 * Figure out the way to work from the command name argv[0].
214 * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000215 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000216 parse_command_name(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000217
218 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000219 * Process the command line arguments. File names are put in the global
220 * argument list "global_alist".
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000221 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000222 command_line_scan(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000223 TIME_MSG("parsing arguments");
224
225 /*
226 * On some systems, when we compile with the GUI, we always use it. On Mac
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000227 * there is no terminal version, and on Windows we can't fork one off with
228 * :gui.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000229 */
230#ifdef ALWAYS_USE_GUI
231 gui.starting = TRUE;
232#else
Bram Moolenaar241a8aa2005-12-06 20:04:44 +0000233# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000234 /*
235 * Check if the GUI can be started. Reset gui.starting if not.
236 * Don't know about other systems, stay on the safe side and don't check.
237 */
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000238 if (gui.starting)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000239 {
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000240 if (gui_init_check() == FAIL)
241 {
242 gui.starting = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000243
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100244 // When running "evim" or "gvim -y" we need the menus, exit if we
245 // don't have them.
Bram Moolenaar5d985b92009-12-16 17:28:07 +0000246 if (params.evim_mode)
247 mch_exit(1);
248 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000249 }
250# endif
251#endif
252
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000253 if (GARGCOUNT > 0)
254 {
Bram Moolenaar53076832015-12-31 19:53:21 +0100255#ifdef EXPAND_FILENAMES
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000256 /*
257 * Expand wildcards in file names.
258 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000259 if (!params.literal)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000260 {
Bram Moolenaarf6303872015-04-03 17:59:43 +0200261 start_dir = alloc(MAXPATHL);
262 if (start_dir != NULL)
263 mch_dirname(start_dir, MAXPATHL);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100264 // Temporarily add '(' and ')' to 'isfname'. These are valid
265 // filename characters but are excluded from 'isfname' to make
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000266 // "gf" work on a file name in parentheses (e.g.: see vim.h).
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000267 do_cmdline_cmd((char_u *)":set isf+=(,)");
Bram Moolenaar86b68352004-12-27 21:59:20 +0000268 alist_expand(NULL, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000269 do_cmdline_cmd((char_u *)":set isf&");
Bram Moolenaarf6303872015-04-03 17:59:43 +0200270 if (start_dir != NULL)
271 mch_chdir((char *)start_dir);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000272 }
273#endif
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200274 params.fname = alist_name(&GARGLIST[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000275 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000276
Bram Moolenaar4f974752019-02-17 17:44:42 +0100277#ifdef MSWIN
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000278 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100279 // Remember the number of entries in the argument list. If it changes
280 // we don't react on setting 'encoding'.
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000281 set_alist_count();
282 }
283#endif
284
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000285#ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000286 if (GARGCOUNT == 1 && params.full_path)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000287 {
288 /*
289 * If there is one filename, fully qualified, we have very probably
290 * been invoked from explorer, so change to the file's directory.
291 * Hint: to avoid this when typing a command use a forward slash.
292 * If the cd fails, it doesn't matter.
293 */
Bram Moolenaar05268152021-11-18 18:53:45 +0000294 if (vim_chdirfile(params.fname, "drop") == OK)
295 last_chdir_reason = "drop";
Bram Moolenaarf6303872015-04-03 17:59:43 +0200296 if (start_dir != NULL)
297 mch_dirname(start_dir, MAXPATHL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000298 }
299#endif
300 TIME_MSG("expanding arguments");
301
302#ifdef FEAT_DIFF
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000303 if (params.diff_mode && params.window_count == -1)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100304 params.window_count = 0; // open up to 3 windows
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000305#endif
306
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100307 // Don't redraw until much later.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000308 ++RedrawingDisabled;
309
310 /*
311 * When listing swap file names, don't do cursor positioning et. al.
312 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200313 if (recoverymode && params.fname == NULL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000314 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000315
316 /*
Bram Moolenaarc174c2e2023-03-25 20:06:49 +0000317 * When certain to start the GUI, don't check terminal capabilities.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000318 * For GTK we can't be sure, but when started from the desktop it doesn't
319 * make sense to try using a terminal.
320 */
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200321#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \
322 || defined(VIMDLL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000323 if (gui.starting
324# ifdef FEAT_GUI_GTK
325 && !isatty(2)
326# endif
327 )
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000328 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000329#endif
330
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000331 /*
332 * mch_init() sets up the terminal (window) for use. This must be
Bram Moolenaar48e330a2016-02-23 14:53:34 +0100333 * done after resetting full_screen, otherwise it may move the cursor.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000334 * Note that we may use mch_exit() before mch_init()!
335 */
336 mch_init();
337 TIME_MSG("shell init");
338
339#ifdef USE_XSMP
340 /*
341 * For want of anywhere else to do it, try to connect to xsmp here.
342 * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
343 * Hijacking -X 'no X connection' to also disable XSMP connection as that
344 * has a similar delay upon failure.
345 * Only try if SESSION_MANAGER is set to something non-null.
346 */
347 if (!x_no_connect)
348 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000349 char *p = getenv("SESSION_MANAGER");
350
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000351 if (p != NULL && *p != NUL)
352 {
353 xsmp_init();
354 TIME_MSG("xsmp init");
355 }
356 }
357#endif
358
359 /*
360 * Print a warning if stdout is not a terminal.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000361 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000362 check_tty(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000363
Bram Moolenaar42b23fa2018-02-03 14:46:45 +0100364#ifdef _IOLBF
Bram Moolenaar42b23fa2018-02-03 14:46:45 +0100365 if (silent_mode)
K.Takata3c240f62023-05-31 12:47:45 +0100366 {
367 // Ensure output works usefully without a tty: buffer lines instead of
368 // fully buffered.
369 s_vbuf = malloc(BUFSIZ);
370 if (s_vbuf != NULL)
371 setvbuf(stdout, s_vbuf, _IOLBF, BUFSIZ);
372 }
Bram Moolenaar42b23fa2018-02-03 14:46:45 +0100373#endif
374
Bram Moolenaar9404a182019-05-03 22:25:40 +0200375 // This message comes before term inits, but after setting "silent_mode"
376 // when the input is not a tty. Omit the message with --not-a-term.
377 if (GARGCOUNT > 1 && !silent_mode && !is_not_a_term())
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000378 printf(_("%d files to edit\n"), GARGCOUNT);
379
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000380 if (params.want_full_screen && !silent_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000381 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100382 termcapinit(params.term); // set terminal name and get terminal
383 // capabilities (will set full_screen)
384 screen_start(); // don't know where cursor is now
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000385 TIME_MSG("Termcap init");
386 }
387
388 /*
389 * Set the default values for the options that use Rows and Columns.
390 */
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100391 ui_get_shellsize(); // inits Rows and Columns
Luuk van Baal470a1412022-09-14 01:27:23 +0100392 win_init_size();
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000393#ifdef FEAT_DIFF
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100394 // Set the 'diff' option now, so that it can be checked for in a .vimrc
395 // file. There is no buffer yet though.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000396 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000397 diff_win_options(firstwin, FALSE);
398#endif
399
400 cmdline_row = Rows - p_ch;
401 msg_row = cmdline_row;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100402 screenalloc(FALSE); // allocate screen buffers
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000403 set_init_2();
404 TIME_MSG("inits 2");
405
406 msg_scroll = TRUE;
407 no_wait_return = TRUE;
408
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100409 init_mappings(); // set up initial mappings
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000410
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100411 init_highlight(TRUE, FALSE); // set the default highlight groups
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000412 TIME_MSG("init highlight");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000413
Bram Moolenaar0c0eddd2020-06-13 15:47:25 +0200414#if defined(FEAT_TERMRESPONSE)
415 init_term_props(TRUE);
416#endif
417
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000418#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100419 // Set the break level after the terminal is initialized.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000420 debug_break_level = params.use_debug_break_level;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000421#endif
422
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100423 // Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
424 // Allows for setting 'loadplugins' there.
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200425 if (params.use_vimrc != NULL
426 && (STRCMP(params.use_vimrc, "NONE") == 0
427 || STRCMP(params.use_vimrc, "DEFAULTS") == 0))
428 p_lpl = FALSE;
429
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100430 // Execute --cmd arguments.
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200431 exe_pre_commands(&params);
432
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100433 // Source startup scripts.
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200434 source_startup_scripts(&params);
435
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100436#ifdef FEAT_MZSCHEME
437 /*
438 * Newer version of MzScheme (Racket) require earlier (trampolined)
439 * initialisation via scheme_main_setup.
440 * Implement this by initialising it as early as possible
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200441 * and splitting off remaining Vim main into vim_main2().
Bram Moolenaar2e4cb3b2017-10-22 21:11:17 +0200442 * Do source startup scripts, so that 'mzschemedll' can be set.
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100443 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200444 return mzscheme_main();
445#else
446 return vim_main2();
Bram Moolenaar8866d272012-11-28 15:55:42 +0100447#endif
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200448}
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100449#endif // NO_VIM_MAIN
450#endif // PROTO
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100451
Foxe Chenb90c2392025-06-27 21:10:35 +0200452#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD) && defined(FEAT_CLIPBOARD)
Foxe Chen6924eb82025-04-19 11:25:18 +0200453/*
454 * Restore the state after a fatal X error.
455 */
456 static void
457x_restore_state(void)
458{
459 State = MODE_NORMAL;
460 VIsual_active = FALSE;
461 got_int = TRUE;
462 need_wait_return = FALSE;
463 global_busy = FALSE;
464 exmode_active = 0;
465 skip_redraw = FALSE;
466 RedrawingDisabled = 0;
467 no_wait_return = 0;
468 vgetc_busy = 0;
469# ifdef FEAT_EVAL
470 emsg_skip = 0;
471# endif
472 emsg_off = 0;
473 setmouse();
474 settmode(TMODE_RAW);
475 starttermcap();
476 scroll_start();
477 redraw_later_clear();
Foxe Chenb90c2392025-06-27 21:10:35 +0200478 choose_clipmethod();
Foxe Chen6924eb82025-04-19 11:25:18 +0200479}
480#endif
481
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200482/*
483 * vim_main2() is needed for FEAT_MZSCHEME, but we define it always to keep
484 * things simple.
485 * It is also defined when NO_VIM_MAIN is defined, but then it's empty.
486 */
Bram Moolenaar8866d272012-11-28 15:55:42 +0100487 int
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200488vim_main2(void)
Bram Moolenaarbbc98db2012-02-12 01:55:55 +0100489{
Bram Moolenaar8866d272012-11-28 15:55:42 +0100490#ifndef NO_VIM_MAIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000491#ifdef FEAT_EVAL
492 /*
493 * Read all the plugin files.
494 * Only when compiled with +eval, since most plugins need it.
495 */
496 if (p_lpl)
497 {
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200498 char_u *rtp_copy = NULL;
Bram Moolenaar6ee874d2020-11-27 19:01:31 +0100499 char_u *plugin_pattern = (char_u *)
500# if defined(VMS) || defined(AMIGA) // VMS and Amiga don't handle the "**".
501 "plugin/*.vim"
502# else
503 "plugin/**/*.vim"
504# endif
505 ;
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200506
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100507 // First add all package directories to 'runtimepath', so that their
508 // autoload directories can be found. Only if not done already with a
509 // :packloadall command.
510 // Make a copy of 'runtimepath', so that source_runtime does not use
511 // the pack directories.
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200512 if (!did_source_packages)
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200513 {
514 rtp_copy = vim_strsave(p_rtp);
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200515 add_pack_start_dirs();
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200516 }
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200517
Bram Moolenaar6ee874d2020-11-27 19:01:31 +0100518 source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy, plugin_pattern,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100519 DIP_ALL | DIP_NOAFTER, NULL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000520 TIME_MSG("loading plugins");
Bram Moolenaar07ecfa62017-06-27 14:43:55 +0200521 vim_free(rtp_copy);
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +0100522
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100523 // Only source "start" packages if not done already with a :packloadall
524 // command.
Bram Moolenaarce876aa2017-06-04 17:47:42 +0200525 if (!did_source_packages)
526 load_start_packages();
Bram Moolenaarf6fee0e2016-02-21 23:02:49 +0100527 TIME_MSG("loading packages");
Bram Moolenaar66459b72016-08-06 19:01:55 +0200528
Bram Moolenaar6ee874d2020-11-27 19:01:31 +0100529 source_runtime(plugin_pattern, DIP_ALL | DIP_AFTER);
Bram Moolenaar66459b72016-08-06 19:01:55 +0200530 TIME_MSG("loading after plugins");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000531 }
532#endif
533
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000534#ifdef FEAT_DIFF
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100535 // Decide about window layout for diff mode after reading vimrc.
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000536 if (params.diff_mode && params.window_layout == 0)
537 {
538 if (diffopt_horizontal())
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100539 params.window_layout = WIN_HOR; // use horizontal split
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000540 else
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100541 params.window_layout = WIN_VER; // use vertical split
Bram Moolenaar27dc1952006-03-15 23:06:44 +0000542 }
543#endif
544
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000545 /*
546 * Recovery mode without a file name: List swap files.
547 * This uses the 'dir' option, therefore it must be after the
548 * initializations.
549 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200550 if (recoverymode && params.fname == NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000551 {
Bram Moolenaarc216a7a2022-12-05 13:50:55 +0000552 recover_names(NULL, TRUE, NULL, 0, NULL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000553 mch_exit(0);
554 }
555
556 /*
557 * Set a few option defaults after reading .vimrc files:
558 * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
559 */
560 set_init_3();
561 TIME_MSG("inits 3");
562
563 /*
564 * "-n" argument: Disable swap file by setting 'updatecount' to 0.
565 * Note that this overrides anything from a vimrc file.
566 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000567 if (params.no_swap_file)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000568 p_uc = 0;
569
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000570#ifdef FEAT_GUI
571 if (gui.starting)
572 {
Bram Moolenaarc7226682019-08-17 16:33:23 +0200573# if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100574 // When something caused a message from a vimrc script, need to output
575 // an extra newline before the shell prompt.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000576 if (did_emsg || msg_didout)
577 putchar('\n');
Bram Moolenaarc7226682019-08-17 16:33:23 +0200578# endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000579
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100580 gui_start(NULL); // will set full_screen to TRUE
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000581 TIME_MSG("starting GUI");
582
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100583 // When running "evim" or "gvim -y" we need the menus, exit if we
584 // don't have them.
Bram Moolenaar58d98232005-07-23 22:25:46 +0000585 if (!gui.in_use && params.evim_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000586 mch_exit(1);
Luuk van Baal470a1412022-09-14 01:27:23 +0100587 firstwin->w_prev_height = firstwin->w_height; // may have changed
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000588 }
589#endif
590
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000591#ifdef FEAT_VIMINFO
592 /*
Bram Moolenaard812df62008-11-09 12:46:09 +0000593 * Read in registers, history etc, but not marks, from the viminfo file.
594 * This is where v:oldfiles gets filled.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000595 */
596 if (*p_viminfo != NUL)
597 {
Bram Moolenaard812df62008-11-09 12:46:09 +0000598 read_viminfo(NULL, VIF_WANT_INFO | VIF_GET_OLDFILES);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000599 TIME_MSG("reading viminfo");
600 }
601#endif
Bram Moolenaar2cd36962014-01-14 12:57:05 +0100602#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100603 // It's better to make v:oldfiles an empty list than NULL.
Bram Moolenaar2cd36962014-01-14 12:57:05 +0100604 if (get_vim_var_list(VV_OLDFILES) == NULL)
605 set_vim_var_list(VV_OLDFILES, list_alloc());
606#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000607
608#ifdef FEAT_QUICKFIX
609 /*
610 * "-q errorfile": Load the error file now.
611 * If the error file can't be read, exit before doing anything else.
612 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000613 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000614 {
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100615 char_u *enc = NULL;
616
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100617 enc = p_menc;
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000618 if (params.use_ef != NULL)
619 set_string_option_direct((char_u *)"ef", -1,
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +0000620 params.use_ef, OPT_FREE, SID_CARG);
Bram Moolenaar7fd73202010-07-25 16:58:46 +0200621 vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
Bram Moolenaar2c7292d2017-03-05 17:43:31 +0100622 if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff, enc) < 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000623 {
624 out_char('\n');
625 mch_exit(3);
626 }
627 TIME_MSG("reading errorfile");
628 }
629#endif
630
631 /*
632 * Start putting things on the screen.
633 * Scroll screen down before drawing over it
634 * Clear screen now, so file message will not be cleared.
635 */
636 starting = NO_BUFFERS;
637 no_wait_return = FALSE;
638 if (!exmode_active)
639 msg_scroll = FALSE;
640
641#ifdef FEAT_GUI
642 /*
643 * This seems to be required to make callbacks to be called now, instead
644 * of after things have been put on the screen, which then may be deleted
645 * when getting a resize callback.
646 * For the Mac this handles putting files dropped on the Vim icon to
647 * global_alist.
648 */
649 if (gui.in_use)
650 {
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100651 gui_wait_for_chars(50L, typebuf.tb_change_cnt);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000652 TIME_MSG("GUI delay");
653 }
654#endif
655
656#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
657 qnx_clip_init();
658#endif
659
Bram Moolenaarc8bbaa32010-07-14 16:54:21 +0200660#if defined(MACOS_X) && defined(FEAT_CLIPBOARD)
661 clip_init(TRUE);
662#endif
663
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000664#ifdef FEAT_XCLIPBOARD
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100665 // Start using the X clipboard, unless the GUI was started.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000666# ifdef FEAT_GUI
667 if (!gui.in_use)
668# endif
669 {
670 setup_term_clip();
Foxe Chenb90c2392025-06-27 21:10:35 +0200671 TIME_MSG("setup x11 clipboard");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000672 }
673#endif
674
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000675#ifdef FEAT_CLIENTSERVER
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100676 // Prepare for being a Vim server.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000677 prepare_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000678#endif
679
Foxe Chenb90c2392025-06-27 21:10:35 +0200680#ifdef FEAT_WAYLAND
681# ifdef FEAT_GUI
682 if (!gui.in_use)
683# endif
684 {
685 if (wayland_init_client(wayland_display_name) == OK)
686 {
Hirohito Higashi73b96502025-06-28 18:18:21 +0200687 TIME_MSG("connected to Wayland display");
Foxe Chenb90c2392025-06-27 21:10:35 +0200688
689# ifdef FEAT_WAYLAND_CLIPBOARD
690 if (wayland_cb_init((char*)p_wse) == OK)
Hirohito Higashi73b96502025-06-28 18:18:21 +0200691 TIME_MSG("setup Wayland clipboard");
Foxe Chenb90c2392025-06-27 21:10:35 +0200692 }
693# endif
694 }
695#endif
696
697#ifdef FEAT_CLIPBOARD
698 choose_clipmethod();
699#endif
700
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000701 /*
702 * If "-" argument given: Read file from stdin.
703 * Do this before starting Raw mode, because it may change things that the
704 * writing end of the pipe doesn't like, e.g., in case stdin and stderr
705 * are the same terminal: "cat | vim -".
706 * Using autocommands here may cause trouble...
707 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000708 if (params.edit_type == EDIT_STDIN && !recoverymode)
709 read_stdin();
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000710
711#if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100712 // When switching screens and something caused a message from a vimrc
713 // script, need to output an extra newline on exit.
Abhijit Barik221927b2025-04-06 16:12:06 +0200714 if ((did_emsg || msg_didout) && *T_TI != NUL && params.edit_type != EDIT_STDIN)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000715 newline_on_exit = TRUE;
716#endif
717
718 /*
K.Takataeeec2542021-06-02 13:28:16 +0200719 * When done something that is not allowed or given an error message call
Bram Moolenaar13608d82022-08-29 15:06:50 +0100720 * wait_return(). This must be done before starttermcap(), because it may
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000721 * switch to another screen. It must be done after settmode(TMODE_RAW),
722 * because we want to react on a single key stroke.
723 * Call settmode and starttermcap here, so the T_KS and T_TI may be
Bram Moolenaar49325942007-05-10 19:19:59 +0000724 * defined by termcapinit and redefined in .exrc.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000725 */
726 settmode(TMODE_RAW);
727 TIME_MSG("setting raw mode");
728
729 if (need_wait_return || msg_didany)
730 {
731 wait_return(TRUE);
732 TIME_MSG("waiting for return");
733 }
734
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100735 starttermcap(); // start termcap if not done by wait_return()
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000736 TIME_MSG("start termcap");
737
Bram Moolenaarb20b9e12019-09-21 20:48:04 +0200738 setmouse(); // may start using the mouse
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000739 if (scroll_region)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100740 scroll_region_reset(); // In case Rows changed
741 scroll_start(); // may scroll the screen to the right position
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000742
Bram Moolenaar651fca82021-11-29 20:39:38 +0000743#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar40385db2018-08-07 22:31:44 +0200744 term_push_title(SAVE_RESTORE_BOTH);
745#endif
746
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000747 /*
748 * Don't clear the screen when starting in Ex mode, unless using the GUI.
749 */
750 if (exmode_active
751#ifdef FEAT_GUI
752 && !gui.in_use
753#endif
754 )
Bram Moolenaar471c0fa2022-08-22 15:19:16 +0100755 set_must_redraw(UPD_CLEAR);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000756 else
757 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100758 screenclear(); // clear screen
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000759 TIME_MSG("clearing screen");
760 }
761
762#ifdef FEAT_CRYPT
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000763 if (params.ask_for_key)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000764 {
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100765 crypt_check_current_method();
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200766 (void)crypt_get_key(TRUE, TRUE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000767 TIME_MSG("getting crypt key");
768 }
769#endif
770
771 no_wait_return = TRUE;
772
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000773 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000774 * Create the requested number of windows and edit buffers in them.
775 * Also does recovery if "recoverymode" set.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000776 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000777 create_windows(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000778 TIME_MSG("opening buffers");
779
Bram Moolenaar867a4b72007-03-18 20:51:46 +0000780#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100781 // clear v:swapcommand
Bram Moolenaar867a4b72007-03-18 20:51:46 +0000782 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
783#endif
784
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100785 // Ex starts at last line of the file
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000786 if (exmode_active)
787 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
788
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000789 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
790 TIME_MSG("BufEnter autocommands");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000791 setpcmark();
792
793#ifdef FEAT_QUICKFIX
794 /*
795 * When started with "-q errorfile" jump to first error now.
796 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000797 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000798 {
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000799 qf_jump(NULL, 0, 0, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000800 TIME_MSG("jump to first error");
801 }
802#endif
803
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000804 /*
805 * If opened more than one window, start editing files in the other
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000806 * windows.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000807 */
Bram Moolenaarf6303872015-04-03 17:59:43 +0200808 edit_buffers(&params, start_dir);
Bram Moolenaarf6303872015-04-03 17:59:43 +0200809 vim_free(start_dir);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000810
811#ifdef FEAT_DIFF
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000812 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000813 {
814 win_T *wp;
815
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100816 // set options in each window for "vimdiff".
Bram Moolenaar29323592016-07-24 22:04:11 +0200817 FOR_ALL_WINDOWS(wp)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000818 diff_win_options(wp, TRUE);
819 }
820#endif
821
822 /*
823 * Shorten any of the filenames, but only when absolute.
824 */
825 shorten_fnames(FALSE);
826
827 /*
828 * Need to jump to the tag before executing the '-c command'.
829 * Makes "vim -c '/return' -t main" work.
830 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000831 if (params.tagname != NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000832 {
Bram Moolenaar146522e2005-12-16 21:55:46 +0000833 swap_exists_did_quit = FALSE;
Bram Moolenaar146522e2005-12-16 21:55:46 +0000834
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000835 vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000836 do_cmdline_cmd(IObuff);
837 TIME_MSG("jumping to tag");
Bram Moolenaar146522e2005-12-16 21:55:46 +0000838
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100839 // If the user doesn't want to edit the file then we quit here.
Bram Moolenaar146522e2005-12-16 21:55:46 +0000840 if (swap_exists_did_quit)
841 getout(1);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000842 }
843
Foxe Chen6924eb82025-04-19 11:25:18 +0200844#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
845 // Temporarily set x_jump_env to here in case there is an X11 IO error,
846 // because x_jump_env is only actually set in main_loop(), before
847 // exe_commands(). May not be the best solution since commands passed via
848 // the command line can be very broad like sourcing a file, in which case
849 // an X IO error results in the command being partially done. In theory we
850 // could use SETJMP in RealWaitForChar(), but the stack frame for that may
851 // possibly exit and then LONGJMP is called on it.
852 int jump_result = SETJMP(x_jump_env);
853
854 if (jump_result == 0)
855 {
856#endif
857 // Execute any "+", "-c" and "-S" arguments.
858 if (params.n_commands > 0)
859 exe_commands(&params);
860#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
861 }
862 else
863 // Restore state and continue just like what main_loop() does.
864 x_restore_state();
865#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000866
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100867 // Must come before the may_req_ calls.
Bram Moolenaar6b1da332017-06-09 21:35:47 +0200868 starting = 0;
869
Bram Moolenaarfc3abf42019-01-24 15:54:21 +0100870#if defined(FEAT_TERMRESPONSE)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100871 // Must be done before redrawing, puts a few characters on the screen.
Bram Moolenaara45551a2020-06-09 15:57:37 +0200872 check_terminal_behavior();
Bram Moolenaar976787d2017-06-04 15:45:50 +0200873#endif
874
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000875 RedrawingDisabled = 0;
Bram Moolenaara4d158b2022-08-14 14:17:45 +0100876 redraw_all_later(UPD_NOT_VALID);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000877 no_wait_return = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000878
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100879 // 'autochdir' has been postponed
Bram Moolenaar6f470022018-04-10 18:47:20 +0200880 DO_AUTOCHDIR;
Bram Moolenaarbaec5c12016-04-06 23:06:23 +0200881
Bram Moolenaara40ceaf2006-01-13 22:35:40 +0000882#ifdef FEAT_TERMRESPONSE
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100883 // Requesting the termresponse is postponed until here, so that a "-c q"
884 // argument doesn't make it appear in the shell Vim was started from.
Bram Moolenaara40ceaf2006-01-13 22:35:40 +0000885 may_req_termresponse();
Bram Moolenaarfc8f1112017-04-18 18:51:35 +0200886
Bram Moolenaarfc8f1112017-04-18 18:51:35 +0200887 may_req_bg_color();
Bram Moolenaara40ceaf2006-01-13 22:35:40 +0000888#endif
889
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100890 // start in insert mode
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000891 if (p_im)
892 need_start_insertmode = TRUE;
893
Bram Moolenaar14735512016-03-26 21:00:08 +0100894#ifdef FEAT_EVAL
895 set_vim_var_nr(VV_VIM_DID_ENTER, 1L);
896#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000897 apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
898 TIME_MSG("VimEnter autocommands");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000899
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200900#if defined(FEAT_EVAL) && defined(FEAT_CLIPBOARD)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100901 // Adjust default register name for "unnamed" in 'clipboard'. Can only be
902 // done after the clipboard is available and all initial commands that may
903 // modify the 'clipboard' setting have run; i.e. just before entering the
904 // main loop.
Bram Moolenaar439c0362020-06-06 15:58:03 +0200905 reset_reg_var();
Bram Moolenaarb429cde2012-04-25 18:24:29 +0200906#endif
907
Bram Moolenaar8a3bb562018-03-04 20:14:14 +0100908#if defined(FEAT_DIFF)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100909 // When a startup script or session file setup for diff'ing and
910 // scrollbind, sync the scrollbind now.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000911 if (curwin->w_p_diff && curwin->w_p_scb)
912 {
913 update_topline();
914 check_scrollbind((linenr_T)0, 0L);
915 TIME_MSG("diff scrollbinding");
916 }
917#endif
918
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200919#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
920# ifdef VIMDLL
921 if (!gui.in_use)
922# endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100923 mch_set_winsize_now(); // Allow winsize changes from now on
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000924#endif
925
Bram Moolenaar4033c552017-09-16 20:54:51 +0200926#if defined(FEAT_GUI)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100927 // When tab pages were created, may need to update the tab pages line and
928 // scrollbars. This is skipped while creating them.
h-east6073f132021-12-24 11:57:06 +0000929 if (gui.in_use && first_tabpage->tp_next != NULL)
Bram Moolenaar32466aa2006-02-24 23:53:04 +0000930 {
931 out_flush();
932 gui_init_which_components(NULL);
933 gui_update_scrollbars(TRUE);
934 }
935 need_mouse_correct = TRUE;
936#endif
937
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100938 // If ":startinsert" command used, stuff a dummy command to be able to
939 // call normal_cmd(), which will then start Insert mode.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000940 if (restart_edit != 0)
Bram Moolenaarebefac62005-12-28 22:39:57 +0000941 stuffcharReadbuff(K_NOP);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000942
943#ifdef FEAT_NETBEANS_INTG
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200944 if (netbeansArg != NULL && strncmp("-nb", netbeansArg, 3) == 0)
Bram Moolenaar67c53842010-05-22 18:28:27 +0200945 {
946# ifdef FEAT_GUI
Bram Moolenaar173c9852010-09-29 17:27:01 +0200947# if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \
Bram Moolenaar4f974752019-02-17 17:44:42 +0100948 && !defined(FEAT_GUI_MSWIN)
Bram Moolenaar67c53842010-05-22 18:28:27 +0200949 if (gui.in_use)
950 {
951 mch_errmsg(_("netbeans is not supported with this GUI\n"));
952 mch_exit(2);
953 }
954# endif
955# endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100956 // Tell the client that it can start sending commands.
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200957 netbeans_open(netbeansArg + 3, TRUE);
Bram Moolenaar67c53842010-05-22 18:28:27 +0200958 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000959#endif
960
Bram Moolenaare7ddf4e2020-02-03 21:29:30 +0100961 // Redraw at least once, also when 'lazyredraw' is set, to make sure the
962 // window title gets updated.
963 do_redraw = TRUE;
964
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000965 TIME_MSG("before starting main loop");
966
967 /*
968 * Call the main command loop. This never returns.
Bram Moolenaar92d147b2018-07-29 17:35:23 +0200969 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000970 main_loop(FALSE, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000971
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100972#endif // NO_VIM_MAIN
Bram Moolenaara8e691d2016-08-07 15:19:26 +0200973
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000974 return 0;
975}
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000976
977/*
Hirohito Higashic5654b82025-02-10 20:55:17 +0100978 * Initialisation #1 shared by main() and some tests.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200979 */
980 void
Hirohito Higashic5654b82025-02-10 20:55:17 +0100981common_init_1(void)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200982{
Bram Moolenaar1a47ae32019-12-29 23:04:25 +0100983 estack_init();
Bram Moolenaar438d1762018-09-30 17:11:48 +0200984 cmdline_init();
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200985
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100986 (void)mb_init(); // init mb_bytelen_tab[] to ones
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200987#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100988 eval_init(); // init global variables
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200989#endif
990
991#ifdef __QNXNTO__
Bram Moolenaar4ba37b52019-12-04 21:57:43 +0100992 qnx_init(); // PhAttach() for clipboard, (and gui)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200993#endif
994
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200995 /*
996 * Allocate space for the generic buffers (needed for set_init_1() and
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100997 * emsg()).
Bram Moolenaar502ae4b2016-07-16 19:50:13 +0200998 */
999 if ((IObuff = alloc(IOSIZE)) == NULL
1000 || (NameBuff = alloc(MAXPATHL)) == NULL)
1001 mch_exit(0);
1002 TIME_MSG("Allocated generic buffers");
Hirohito Higashic5654b82025-02-10 20:55:17 +01001003}
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001004
Hirohito Higashic5654b82025-02-10 20:55:17 +01001005
1006/*
1007 * Initialisation #2 shared by main() and some tests.
1008 */
1009 void
1010common_init_2(mparm_T *paramp)
1011{
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001012#ifdef NBDEBUG
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001013 // Wait a moment for debugging NetBeans. Must be after allocating
1014 // NameBuff.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001015 nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
1016 nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
1017 TIME_MSG("NetBeans debug wait");
1018#endif
1019
1020#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
1021 /*
1022 * Setup to use the current locale (for ctype() and many other things).
1023 * NOTE: Translated messages with encodings other than latin1 will not
1024 * work until set_init_1() has been called!
1025 */
1026 init_locale();
1027 TIME_MSG("locale set");
1028#endif
1029
1030#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001031 gui.dofork = TRUE; // default is to use fork()
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001032#endif
1033
1034 /*
1035 * Do a first scan of the arguments in "argv[]":
1036 * -display or --display
1037 * --server...
1038 * --socketid
1039 * --windowid
1040 */
Bram Moolenaara8e691d2016-08-07 15:19:26 +02001041 early_arg_scan(paramp);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001042
Bram Moolenaard0573012017-10-28 21:11:06 +02001043#if defined(FEAT_GUI)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001044 // Prepare for possibly starting GUI sometime
Bram Moolenaara8e691d2016-08-07 15:19:26 +02001045 gui_prepare(&paramp->argc, paramp->argv);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001046 TIME_MSG("GUI prepared");
1047#endif
1048
1049#ifdef FEAT_CLIPBOARD
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001050 clip_init(FALSE); // Initialise clipboard stuff
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001051 TIME_MSG("clipboard setup");
1052#endif
1053
1054 /*
1055 * Check if we have an interactive window.
1056 * On the Amiga: If there is no window, we open one with a newcli command
1057 * (needed for :! to * work). mch_check_win() will also handle the -d or
1058 * -dev argument.
1059 */
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01001060 stdout_isatty = (mch_check_win(paramp->argc, paramp->argv) != FAIL);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001061 TIME_MSG("window checked");
1062
1063 /*
1064 * Allocate the first window and buffer.
1065 * Can't do anything without it, exit when it fails.
1066 */
1067 if (win_alloc_first() == FAIL)
1068 mch_exit(0);
1069
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001070 init_yank(); // init yank buffers
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001071
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001072 alist_init(&global_alist); // Init the argument list to empty.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001073 global_alist.id = 0;
1074
1075 /*
1076 * Set the default values for the options.
1077 * NOTE: Non-latin1 translated messages are working only after this,
1078 * because this is where "has_mbyte" will be set, which is used by
1079 * msg_outtrans_len_attr().
1080 * First find out the home directory, needed to expand "~" in options.
1081 */
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001082 init_homedir(); // find real value of $HOME
Bram Moolenaar07268702018-03-01 21:57:32 +01001083 set_init_1(paramp->clean);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001084 TIME_MSG("inits 1");
1085
1086#ifdef FEAT_EVAL
Bram Moolenaar69bf6342019-10-29 04:16:57 +01001087 // set v:lang and v:ctype
1088 set_lang_var();
1089
1090 // set v:argv
1091 set_argv_var(paramp->argv, paramp->argc);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001092#endif
Bram Moolenaar6436cd82018-12-27 00:28:33 +01001093
1094#ifdef FEAT_SIGNS
1095 init_signs();
1096#endif
64-bitman88d41ab2025-04-06 17:20:39 +02001097
1098#ifdef FEAT_QUICKFIX
Hirohito Higashiadcfb6c2025-04-07 21:19:07 +02001099 // initialize quickfix list
64-bitman88d41ab2025-04-06 17:20:39 +02001100 // don't send an error message when memory allocation fails
1101 // do it when the user tries to access the quickfix list
Hirohito Higashiadcfb6c2025-04-07 21:19:07 +02001102 qf_init_stack();
64-bitman88d41ab2025-04-06 17:20:39 +02001103#endif
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001104}
1105
1106/*
Bram Moolenaar08f88b12017-04-02 17:21:16 +02001107 * Return TRUE when the --not-a-term argument was found.
1108 */
1109 int
Bram Moolenaarf7e73022022-09-24 13:10:04 +01001110is_not_a_term(void)
Bram Moolenaar08f88b12017-04-02 17:21:16 +02001111{
1112 return params.not_a_term;
1113}
1114
Bram Moolenaar7007e312021-03-27 12:11:33 +01001115/*
1116 * Return TRUE when the --not-a-term argument was found or the GUI is in use.
1117 */
Bram Moolenaarf7e73022022-09-24 13:10:04 +01001118 int
1119is_not_a_term_or_gui(void)
Bram Moolenaar7007e312021-03-27 12:11:33 +01001120{
1121 return params.not_a_term
1122#ifdef FEAT_GUI
1123 || gui.in_use
1124#endif
1125 ;
1126}
1127
K.Takata3c240f62023-05-31 12:47:45 +01001128#if defined(EXITFREE) || defined(PROTO)
1129 void
1130free_vbuf(void)
1131{
1132# ifdef _IOLBF
1133 if (s_vbuf != NULL)
1134 {
1135 setvbuf(stdout, NULL, _IONBF, 0);
1136 free(s_vbuf);
1137 s_vbuf = NULL;
1138 }
1139# endif
1140}
1141#endif
1142
Bram Moolenaar2d12c252022-06-13 21:42:45 +01001143#if defined(FEAT_GUI) || defined(PROTO)
1144/*
1145 * If a --gui-dialog-file argument was given return the file name.
1146 * Otherwise return NULL.
1147 */
1148 char_u *
1149get_gui_dialog_file(void)
1150{
1151 return params.gui_dialog_file;
1152}
1153#endif
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001154
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001155// When TRUE in a safe state when starting to wait for a character.
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001156static int was_safe = FALSE;
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001157static oparg_T *current_oap = NULL;
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001158
1159/*
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001160 * Return TRUE if an operator was started but not finished yet.
1161 * Includes typing a count or a register name.
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001162 */
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001163 int
1164op_pending(void)
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001165{
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001166 return !(current_oap != NULL
1167 && !finish_op
1168 && current_oap->prev_opcount == 0
1169 && current_oap->prev_count0 == 0
1170 && current_oap->op_type == OP_NOP
1171 && current_oap->regname == NUL);
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001172}
1173
1174/*
Bram Moolenaard103ee72019-09-18 21:15:31 +02001175 * Return whether currently it is safe, assuming it was safe before (high level
1176 * state didn't change).
1177 */
1178 static int
1179is_safe_now(void)
1180{
1181 return stuff_empty()
1182 && typebuf.tb_len == 0
1183 && scriptin[curscript] == NULL
Bram Moolenaar4fa13462022-02-05 12:39:24 +00001184#ifdef FEAT_EVAL
1185 && !debug_mode
1186#endif
1187 && !global_busy;
Bram Moolenaard103ee72019-09-18 21:15:31 +02001188}
1189
1190/*
zeertzjqc4226622024-04-03 22:38:07 +02001191 * Trigger SafeState if currently in a safe state, that is "safe" is TRUE and
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001192 * there is no typeahead.
1193 */
1194 void
1195may_trigger_safestate(int safe)
1196{
Bram Moolenaard103ee72019-09-18 21:15:31 +02001197 int is_safe = safe && is_safe_now();
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001198
Bram Moolenaar4c5678f2022-11-30 18:12:19 +00001199#ifdef FEAT_EVAL
Bram Moolenaar37d18072019-09-17 20:28:38 +02001200 if (was_safe != is_safe)
1201 // Only log when the state changes, otherwise it happens at nearly
1202 // every key stroke.
Bram Moolenaard103ee72019-09-18 21:15:31 +02001203 ch_log(NULL, is_safe ? "SafeState: Start triggering"
1204 : "SafeState: Stop triggering");
Bram Moolenaar397c6a12019-09-17 20:54:31 +02001205#endif
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001206 if (is_safe)
1207 apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf);
1208 was_safe = is_safe;
1209}
1210
1211/*
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001212 * Something changed which causes the state possibly to be unsafe, e.g. a
1213 * character was typed. It will remain unsafe until the next call to
1214 * may_trigger_safestate().
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001215 */
1216 void
Bram Moolenaard103ee72019-09-18 21:15:31 +02001217state_no_longer_safe(char *reason UNUSED)
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001218{
Bram Moolenaar4c5678f2022-11-30 18:12:19 +00001219#ifdef FEAT_EVAL
Bram Moolenaar37d18072019-09-17 20:28:38 +02001220 if (was_safe)
Bram Moolenaard103ee72019-09-18 21:15:31 +02001221 ch_log(NULL, "SafeState: reset: %s", reason);
Bram Moolenaar397c6a12019-09-17 20:54:31 +02001222#endif
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001223 was_safe = FALSE;
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001224}
1225
Dominique Pelle748b3082022-01-08 12:41:16 +00001226#if defined(FEAT_EVAL) || defined(MESSAGE_QUEUE) || defined(PROTO)
Bram Moolenaard103ee72019-09-18 21:15:31 +02001227 int
1228get_was_safe_state(void)
1229{
1230 return was_safe;
1231}
Dominique Pelle748b3082022-01-08 12:41:16 +00001232#endif
Bram Moolenaard103ee72019-09-18 21:15:31 +02001233
Dominique Pelle748b3082022-01-08 12:41:16 +00001234#if defined(MESSAGE_QUEUE) || defined(PROTO)
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001235/*
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001236 * Invoked when leaving code that invokes callbacks. Then trigger
1237 * SafeStateAgain, if it was safe when starting to wait for a character.
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001238 */
1239 void
Bram Moolenaar37d18072019-09-17 20:28:38 +02001240may_trigger_safestateagain(void)
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001241{
Bram Moolenaard103ee72019-09-18 21:15:31 +02001242 if (!was_safe)
1243 {
1244 // If the safe state was reset in state_no_longer_safe(), e.g. because
1245 // of calling feedkeys(), we check if it's now safe again (all keys
1246 // were consumed).
1247 was_safe = is_safe_now();
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001248# ifdef FEAT_EVAL
Bram Moolenaard103ee72019-09-18 21:15:31 +02001249 if (was_safe)
1250 ch_log(NULL, "SafeState: undo reset");
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001251# endif
Bram Moolenaard103ee72019-09-18 21:15:31 +02001252 }
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001253 if (was_safe)
Bram Moolenaar37d18072019-09-17 20:28:38 +02001254 {
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001255# ifdef FEAT_EVAL
Bram Moolenaar101e9922019-09-25 21:43:11 +02001256 // Only do this message when another message was given, otherwise we
1257 // get lots of them.
1258 if ((did_repeated_msg & REPEATED_MSG_SAFESTATE) == 0)
1259 {
1260 int did = did_repeated_msg;
1261
1262 ch_log(NULL,
1263 "SafeState: back to waiting, triggering SafeStateAgain");
1264 did_repeated_msg = did | REPEATED_MSG_SAFESTATE;
1265 }
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001266# endif
Bram Moolenaar69198cb2019-09-16 21:58:13 +02001267 apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
Bram Moolenaar37d18072019-09-17 20:28:38 +02001268 }
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001269# ifdef FEAT_EVAL
Bram Moolenaar37d18072019-09-17 20:28:38 +02001270 else
Bram Moolenaard103ee72019-09-18 21:15:31 +02001271 ch_log(NULL,
1272 "SafeState: back to waiting, not triggering SafeStateAgain");
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001273# endif
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001274}
Dominique Pelle748b3082022-01-08 12:41:16 +00001275#endif
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001276
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001277/*
1278 * Return TRUE if there is any typeahead, pending operator or command.
1279 */
1280 int
1281work_pending(void)
1282{
1283 return op_pending() || !is_safe_now();
1284}
1285
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001286
Bram Moolenaar08f88b12017-04-02 17:21:16 +02001287/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001288 * Main loop: Execute Normal mode commands until exiting Vim.
1289 * Also used to handle commands in the command-line window, until the window
1290 * is closed.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001291 * Also used to handle ":visual" command after ":global": execute Normal mode
1292 * commands, return when entering Ex mode. "noexmode" is TRUE then.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001293 */
1294 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001295main_loop(
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001296 int cmdwin, // TRUE when working in the command-line window
1297 int noexmode) // TRUE when return on entering Ex mode
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001298{
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001299 oparg_T oa; // operator arguments
1300 oparg_T *prev_oap; // operator arguments
1301 volatile int previous_got_int = FALSE; // "got_int" was TRUE
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001302#ifdef FEAT_CONCEAL
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001303 // these are static to avoid a compiler warning
Bram Moolenaar1db43b12015-07-12 16:21:23 +02001304 static linenr_T conceal_old_cursor_line = 0;
1305 static linenr_T conceal_new_cursor_line = 0;
1306 static int conceal_update_lines = FALSE;
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001307#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001308
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001309 prev_oap = current_oap;
1310 current_oap = &oa;
1311
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001312#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001313 // Setup to catch a terminating error from the X server. Just ignore
1314 // it, restore the state and continue. This might not always work
Foxe Chen6924eb82025-04-19 11:25:18 +02001315 // properly, but at least we hopefully don't exit unexpectedly when the X
1316 // server exits while Vim is running in a console.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001317 if (!cmdwin && !noexmode && SETJMP(x_jump_env))
Foxe Chen6924eb82025-04-19 11:25:18 +02001318 x_restore_state();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001319#endif
1320
1321 clear_oparg(&oa);
Martin Tournoij7904fa42022-10-04 16:28:45 +01001322 while (!cmdwin || cmdwin_result == 0)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001323 {
1324 if (stuff_empty())
1325 {
1326 did_check_timestamps = FALSE;
1327 if (need_check_timestamps)
1328 check_timestamps(FALSE);
Bram Moolenaar13608d82022-08-29 15:06:50 +01001329 if (need_wait_return) // if wait_return() still needed ...
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001330 wait_return(FALSE); // ... call it now
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001331 if (need_start_insertmode && goto_im() && !VIsual_active)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001332 {
1333 need_start_insertmode = FALSE;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001334 stuffReadbuff((char_u *)"i"); // start insert mode next
1335 // skip the fileinfo message now, because it would be shown
1336 // after insert mode finishes!
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001337 need_fileinfo = FALSE;
1338 }
1339 }
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001340
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001341 // Reset "got_int" now that we got back to the main loop. Except when
1342 // inside a ":g/pat/cmd" command, then the "got_int" needs to abort
1343 // the ":g" command.
1344 // For ":g/pat/vi" we reset "got_int" when used once. When used
1345 // a second time we go back to Ex mode and abort the ":g" command.
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001346 if (got_int)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001347 {
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001348 if (noexmode && global_busy && !exmode_active && previous_got_int)
1349 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001350 // Typed two CTRL-C in a row: go back to ex mode as if "Q" was
1351 // used and keep "got_int" set, so that it aborts ":g".
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001352 exmode_active = EXMODE_NORMAL;
Bram Moolenaar24959102022-05-07 20:01:16 +01001353 State = MODE_NORMAL;
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001354 }
1355 else if (!global_busy || !exmode_active)
1356 {
1357 if (!quit_more)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001358 (void)vgetc(); // flush all buffers
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001359 got_int = FALSE;
1360 }
1361 previous_got_int = TRUE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001362 }
Bram Moolenaar225d32b2007-08-10 19:33:47 +00001363 else
1364 previous_got_int = FALSE;
1365
Bram Moolenaar069613c2022-01-15 15:23:44 +00001366#ifdef FEAT_EVAL
1367 // At the toplevel there is no exception handling. Discard any that
1368 // may be hanging around (e.g. from "interrupt" at the debug prompt).
1369 if (did_throw && !ex_normal_busy)
1370 discard_current_exception();
1371#endif
1372
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001373 if (!exmode_active)
1374 msg_scroll = FALSE;
1375 quit_more = FALSE;
1376
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001377 // it's not safe unless may_trigger_safestate_main() is called
1378 was_safe = FALSE;
1379
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001380 /*
1381 * If skip redraw is set (for ":" in wait_return()), don't redraw now.
1382 * If there is nothing in the stuff_buffer or do_redraw is TRUE,
1383 * update cursor and redraw.
1384 */
1385 if (skip_redraw || exmode_active)
Bram Moolenaarc174c2e2023-03-25 20:06:49 +00001386 {
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001387 skip_redraw = FALSE;
Bram Moolenaarc174c2e2023-03-25 20:06:49 +00001388 setcursor();
1389 cursor_on();
1390 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001391 else if (do_redraw || stuff_empty())
1392 {
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001393#ifdef FEAT_GUI
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001394 // If ui_breakcheck() was used a resize may have been postponed.
Bram Moolenaar6b40f302017-02-03 22:01:47 +01001395 gui_may_resize_shell();
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001396#endif
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001397#ifdef HAVE_DROP_FILE
1398 // If files were dropped while text was locked or the curbuf was
1399 // locked, this would be a good time to handle the drop.
1400 handle_any_postponed_drop();
1401#endif
Bram Moolenaarbbee8d52019-01-14 21:51:40 +01001402#ifdef FEAT_CONCEAL
1403 if (curwin->w_p_cole == 0)
1404 conceal_update_lines = FALSE;
1405#endif
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001406
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001407 // Trigger CursorMoved if the cursor moved.
Bram Moolenaar24fe33a2022-11-24 00:09:02 +00001408 if (!finish_op && (has_cursormoved()
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001409#ifdef FEAT_PROP_POPUP
Bram Moolenaar24fe33a2022-11-24 00:09:02 +00001410 || popup_visible
Bram Moolenaar3397f742019-06-02 18:40:06 +02001411#endif
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001412#ifdef FEAT_CONCEAL
Bram Moolenaar24fe33a2022-11-24 00:09:02 +00001413 || curwin->w_p_cole > 0
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001414#endif
Bram Moolenaar24fe33a2022-11-24 00:09:02 +00001415 )
1416 && !EQUAL_POS(last_cursormoved, curwin->w_cursor))
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001417 {
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001418 if (has_cursormoved())
1419 apply_autocmds(EVENT_CURSORMOVED, NULL, NULL,
1420 FALSE, curbuf);
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01001421#ifdef FEAT_PROP_POPUP
Bram Moolenaar3397f742019-06-02 18:40:06 +02001422 if (popup_visible)
1423 popup_check_cursor_pos();
1424#endif
1425#ifdef FEAT_CONCEAL
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001426 if (curwin->w_p_cole > 0)
Bram Moolenaarb2c03502010-07-02 20:20:09 +02001427 {
1428 conceal_old_cursor_line = last_cursormoved.lnum;
1429 conceal_new_cursor_line = curwin->w_cursor.lnum;
1430 conceal_update_lines = TRUE;
1431 }
Bram Moolenaar3397f742019-06-02 18:40:06 +02001432#endif
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001433 last_cursormoved = curwin->w_cursor;
1434 }
Bram Moolenaar3d0a6032006-02-09 23:54:54 +00001435
Bram Moolenaar535d5b62019-01-11 20:45:36 +01001436#if defined(FEAT_CONCEAL)
1437 if (conceal_update_lines
1438 && (conceal_old_cursor_line != conceal_new_cursor_line
1439 || conceal_cursor_line(curwin)
1440 || need_cursor_line_redraw))
1441 {
1442 if (conceal_old_cursor_line != conceal_new_cursor_line
Bram Moolenaarbbee8d52019-01-14 21:51:40 +01001443 && conceal_old_cursor_line != 0
Bram Moolenaar535d5b62019-01-11 20:45:36 +01001444 && conceal_old_cursor_line
1445 <= curbuf->b_ml.ml_line_count)
1446 redrawWinline(curwin, conceal_old_cursor_line);
1447 redrawWinline(curwin, conceal_new_cursor_line);
1448 curwin->w_valid &= ~VALID_CROW;
1449 need_cursor_line_redraw = FALSE;
1450 }
1451#endif
1452
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001453 // Trigger TextChanged if b:changedtick differs.
Bram Moolenaar186628f2013-03-19 13:33:23 +01001454 if (!finish_op && has_textchanged()
Bram Moolenaar5a093432018-02-10 18:15:19 +01001455 && curbuf->b_last_changedtick != CHANGEDTICK(curbuf))
Bram Moolenaar186628f2013-03-19 13:33:23 +01001456 {
Bram Moolenaar5a093432018-02-10 18:15:19 +01001457 apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf);
1458 curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
Bram Moolenaar186628f2013-03-19 13:33:23 +01001459 }
Bram Moolenaar186628f2013-03-19 13:33:23 +01001460
LemonBoy09371822022-04-08 15:18:45 +01001461 // Ensure curwin->w_topline and curwin->w_leftcol are up to date
1462 // before triggering a WinScrolled autocommand.
1463 update_topline();
1464 validate_cursor();
1465
1466 if (!finish_op)
Bram Moolenaar35fc61c2022-11-22 12:40:50 +00001467 may_trigger_win_scrolled_resized();
LemonBoy09371822022-04-08 15:18:45 +01001468
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001469 // If nothing is pending and we are going to wait for the user to
1470 // type a character, trigger SafeState.
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001471 may_trigger_safestate(!op_pending() && restart_edit == 0);
Bram Moolenaar8aeec402019-09-15 23:02:04 +02001472
Bram Moolenaar8a3bb562018-03-04 20:14:14 +01001473#if defined(FEAT_DIFF)
Bram Moolenaare3521d92018-09-16 14:10:31 +02001474 // Updating diffs from changed() does not always work properly,
1475 // esp. updating folds. Do an update just before redrawing if
1476 // needed.
1477 if (curtab->tp_diff_update || curtab->tp_diff_invalid)
1478 {
1479 ex_diffupdate(NULL);
1480 curtab->tp_diff_update = FALSE;
1481 }
1482
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001483 // Scroll-binding for diff mode may have been postponed until
1484 // here. Avoids doing it for every change.
Bram Moolenaar33aec762006-01-22 23:30:12 +00001485 if (diff_need_scrollbind)
1486 {
1487 check_scrollbind((linenr_T)0, 0L);
1488 diff_need_scrollbind = FALSE;
1489 }
1490#endif
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001491#if defined(FEAT_FOLDING)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001492 // Include a closed fold completely in the Visual area.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001493 foldAdjustVisual();
1494#endif
1495#ifdef FEAT_FOLDING
1496 /*
1497 * When 'foldclose' is set, apply 'foldlevel' to folds that don't
1498 * contain the cursor.
1499 * When 'foldopen' is "all", open the fold(s) under the cursor.
1500 * This may mark the window for redrawing.
1501 */
1502 if (hasAnyFolding(curwin) && !char_avail())
1503 {
1504 foldCheckClose();
1505 if (fdo_flags & FDO_ALL)
1506 foldOpenCursor();
1507 }
1508#endif
1509
Bram Moolenaar24fe33a2022-11-24 00:09:02 +00001510 // Before redrawing, make sure w_topline is correct, and w_leftcol
1511 // if lines don't wrap, and w_skipcol if lines wrap.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001512 update_topline();
1513 validate_cursor();
1514
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001515 if (VIsual_active)
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001516 update_curbuf(UPD_INVERTED); // update inverted part
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001517 else if (must_redraw)
Bram Moolenaara338adc2018-01-31 20:51:47 +01001518 {
Bram Moolenaar017ba072019-09-14 21:01:23 +02001519 mch_disable_flush(); // Stop issuing gui_mch_flush().
Bram Moolenaar11a58af2019-10-24 22:32:31 +02001520 update_screen(0);
Bram Moolenaara338adc2018-01-31 20:51:47 +01001521 mch_enable_flush();
1522 }
Bram Moolenaar7a1d3282022-06-16 13:04:45 +01001523 else if (redraw_cmdline || clear_cmdline || redraw_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001524 showmode();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001525 redraw_statuslines();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001526 if (need_maketitle)
1527 maketitle();
Bram Moolenaarab9c89b2016-07-03 17:47:26 +02001528#ifdef FEAT_VIMINFO
1529 curbuf->b_last_used = vim_time();
1530#endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001531 // display message after redraw
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001532 if (keep_msg != NULL)
1533 {
Bram Moolenaare5fbd732019-09-09 20:04:13 +02001534 char_u *p = vim_strsave(keep_msg);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001535
Bram Moolenaare5fbd732019-09-09 20:04:13 +02001536 if (p != NULL)
1537 {
1538 // msg_start() will set keep_msg to NULL, make a copy
1539 // first. Don't reset keep_msg, msg_attr_keep() uses it to
1540 // check for duplicates. Never put this message in
1541 // history.
1542 msg_hist_off = TRUE;
1543 msg_attr((char *)p, keep_msg_attr);
1544 msg_hist_off = FALSE;
1545 vim_free(p);
1546 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001547 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001548 if (need_fileinfo) // show file info after redraw
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001549 {
1550 fileinfo(FALSE, TRUE, FALSE);
1551 need_fileinfo = FALSE;
1552 }
1553
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001554 emsg_on_display = FALSE; // can delete error message now
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001555 did_emsg = FALSE;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001556 msg_didany = FALSE; // reset lines_left in msg_start()
1557 may_clear_sb_text(); // clear scroll-back text on next msg
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001558 showruler(FALSE);
1559
1560 setcursor();
1561 cursor_on();
1562
1563 do_redraw = FALSE;
Bram Moolenaar3f269672009-11-03 11:11:11 +00001564
1565#ifdef STARTUPTIME
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001566 // Now that we have drawn the first screen all the startup stuff
1567 // has been done, close any file for startup messages.
Bram Moolenaar3f269672009-11-03 11:11:11 +00001568 if (time_fd != NULL)
1569 {
1570 TIME_MSG("first screen update");
1571 TIME_MSG("--- VIM STARTED ---");
1572 fclose(time_fd);
1573 time_fd = NULL;
1574 }
1575#endif
Bram Moolenaar0a60f792022-11-19 21:18:11 +00001576 // After the first screen update may start triggering WinScrolled
1577 // autocmd events. Store all the scroll positions and sizes now.
1578 may_make_initial_scroll_size_snapshot();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001579 }
1580#ifdef FEAT_GUI
1581 if (need_mouse_correct)
1582 gui_mouse_correct();
1583#endif
1584
Bram Moolenaar733a69b2022-12-01 12:03:47 +00001585 // May request the keyboard protocol state now.
1586 may_send_t_RK();
1587
1588 // Update w_curswant if w_set_curswant has been set.
1589 // Postponed until here to avoid computing w_virtcol too often.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001590 update_curswant();
1591
Bram Moolenaar9fecb462006-09-05 10:59:47 +00001592#ifdef FEAT_EVAL
1593 /*
1594 * May perform garbage collection when waiting for a character, but
1595 * only at the very toplevel. Otherwise we may be using a List or
1596 * Dict internally somewhere.
1597 * "may_garbage_collect" is reset in vgetc() which is invoked through
1598 * do_exmode() and normal_cmd().
1599 */
1600 may_garbage_collect = (!cmdwin && !noexmode);
1601#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001602 /*
1603 * If we're invoked as ex, do a round of ex commands.
1604 * Otherwise, get and execute a normal mode command.
1605 */
1606 if (exmode_active)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001607 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001608 if (noexmode) // End of ":global/path/visual" commands
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001609 goto theend;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001610 do_exmode(exmode_active == EXMODE_VIM);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001611 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001612 else
Bram Moolenaar938783d2017-07-16 20:13:26 +02001613 {
1614#ifdef FEAT_TERMINAL
Bram Moolenaar6d819742017-08-06 14:57:49 +02001615 if (term_use_loop()
Bram Moolenaaraaa8a352017-08-05 20:17:00 +02001616 && oa.op_type == OP_NOP && oa.regname == NUL
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001617 && !VIsual_active
1618 && !skip_term_loop)
Bram Moolenaar423802d2017-07-30 16:52:24 +02001619 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001620 // If terminal_loop() returns OK we got a key that is handled
Christian Brabandtee17b6f2023-09-09 11:23:50 +02001621 // in Normal mode. With FAIL we first need to position the
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001622 // cursor and the screen needs to be redrawn.
Bram Moolenaar69fbc9e2017-09-14 20:37:57 +02001623 if (terminal_loop(TRUE) == OK)
Bram Moolenaar423802d2017-07-30 16:52:24 +02001624 normal_cmd(&oa, TRUE);
1625 }
1626 else
Bram Moolenaar938783d2017-07-16 20:13:26 +02001627#endif
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001628 {
1629#ifdef FEAT_TERMINAL
1630 skip_term_loop = FALSE;
1631#endif
Bram Moolenaar423802d2017-07-30 16:52:24 +02001632 normal_cmd(&oa, TRUE);
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02001633 }
Bram Moolenaar938783d2017-07-16 20:13:26 +02001634 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001635 }
Bram Moolenaar0e57dd82019-09-16 22:56:03 +02001636
1637theend:
1638 current_oap = prev_oap;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001639}
1640
1641
Bram Moolenaar6d8d8492016-03-19 14:48:31 +01001642#if defined(USE_XSMP) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001643/*
1644 * Exit, but leave behind swap files for modified buffers.
1645 */
1646 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001647getout_preserve_modified(int exitval)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001648{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001649# if defined(SIGHUP) && defined(SIG_IGN)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001650 // Ignore SIGHUP, because a dropped connection causes a read error, which
1651 // makes Vim exit and then handling SIGHUP causes various reentrance
1652 // problems.
ichizok378447f2023-05-11 22:25:42 +01001653 mch_signal(SIGHUP, SIG_IGN);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001654# endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001655
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001656 ml_close_notmod(); // close all not-modified buffers
1657 ml_sync_all(FALSE, FALSE); // preserve all swap files
1658 ml_close_all(FALSE); // close all memfiles, without deleting
1659 getout(exitval); // exit Vim properly
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001660}
1661#endif
1662
1663
Bram Moolenaar6d8d8492016-03-19 14:48:31 +01001664/*
Bram Moolenaarf0068c52020-11-30 17:42:10 +01001665 * Exit properly. This is the only way to exit Vim after startup has
1666 * succeeded. We are certain to exit here, no way to abort it.
Bram Moolenaar6d8d8492016-03-19 14:48:31 +01001667 */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001668 void
Bram Moolenaarb7604cc2016-01-15 21:23:22 +01001669getout(int exitval)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001670{
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001671 exiting = TRUE;
Bram Moolenaar4c5678f2022-11-30 18:12:19 +00001672#if defined(FEAT_EVAL)
Bram Moolenaar0bd052b2018-03-22 20:33:56 +01001673 ch_log(NULL, "Exiting...");
1674#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001675
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001676 // When running in Ex mode an error causes us to exit with a non-zero exit
1677 // code. POSIX requires this, although it's not 100% clear from the
1678 // standard.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001679 if (exmode_active)
1680 exitval += ex_exitval;
1681
Bram Moolenaarf0068c52020-11-30 17:42:10 +01001682#ifdef FEAT_EVAL
1683 set_vim_var_type(VV_EXITING, VAR_NUMBER);
1684 set_vim_var_nr(VV_EXITING, exitval);
1685#endif
1686
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001687 // Position the cursor on the last screen line, below all the text
Bram Moolenaar7007e312021-03-27 12:11:33 +01001688 if (!is_not_a_term_or_gui())
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001689 windgoto((int)Rows - 1, 0);
1690
Bram Moolenaar58779852022-09-06 18:31:14 +01001691#ifdef FEAT_EVAL
1692 // Invoked all deferred functions in the function stack.
1693 invoke_all_defer();
1694#endif
1695
Bram Moolenaar0e21a3f2005-04-17 20:28:32 +00001696#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001697 // Optionally print hashtable efficiency.
Bram Moolenaar0e21a3f2005-04-17 20:28:32 +00001698 hash_debug_results();
1699#endif
1700
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001701#ifdef FEAT_GUI
1702 msg_didany = FALSE;
1703#endif
1704
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001705 if (v_dying <= 1)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001706 {
Bram Moolenaardf2c7742018-04-16 17:06:09 +02001707 tabpage_T *tp;
1708 tabpage_T *next_tp;
1709 buf_T *buf;
1710 win_T *wp;
Bram Moolenaar129d6bf2020-05-16 16:08:35 +02001711 int unblock = 0;
Bram Moolenaardf2c7742018-04-16 17:06:09 +02001712
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001713 // Trigger BufWinLeave for all windows, but only once per buffer.
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001714 for (tp = first_tabpage; tp != NULL; tp = next_tp)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001715 {
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001716 next_tp = tp->tp_next;
Bram Moolenaar29323592016-07-24 22:04:11 +02001717 FOR_ALL_WINDOWS_IN_TAB(tp, wp)
Bram Moolenaarf740b292006-02-16 22:11:02 +00001718 {
Christian Brabandtfc682992023-09-03 20:20:52 +02001719 if (wp->w_buffer == NULL || !buf_valid(wp->w_buffer))
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001720 // Autocmd must have close the buffer already, skip.
Bram Moolenaar802418d2013-01-17 14:00:11 +01001721 continue;
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001722 buf = wp->w_buffer;
Bram Moolenaar95c526e2017-02-25 14:59:34 +01001723 if (CHANGEDTICK(buf) != -1)
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001724 {
Bram Moolenaar606d45c2017-12-18 16:21:44 +01001725 bufref_T bufref;
1726
1727 set_bufref(&bufref, buf);
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001728 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
1729 buf->b_fname, FALSE, buf);
Bram Moolenaar606d45c2017-12-18 16:21:44 +01001730 if (bufref_valid(&bufref))
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001731 CHANGEDTICK(buf) = -1; // note we did it already
Bram Moolenaar606d45c2017-12-18 16:21:44 +01001732
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001733 // start all over, autocommands may mess up the lists
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001734 next_tp = first_tabpage;
1735 break;
1736 }
Bram Moolenaarf740b292006-02-16 22:11:02 +00001737 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001738 }
Bram Moolenaar33aec762006-01-22 23:30:12 +00001739
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001740 // Trigger BufUnload for buffers that are loaded
Bram Moolenaar29323592016-07-24 22:04:11 +02001741 FOR_ALL_BUFFERS(buf)
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001742 if (buf->b_ml.ml_mfp != NULL)
1743 {
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001744 bufref_T bufref;
1745
1746 set_bufref(&bufref, buf);
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001747 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001748 FALSE, buf);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02001749 if (!bufref_valid(&bufref))
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001750 // autocmd deleted the buffer
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001751 break;
1752 }
Bram Moolenaar129d6bf2020-05-16 16:08:35 +02001753
1754 // deathtrap() blocks autocommands, but we do want to trigger
1755 // VimLeavePre.
1756 if (is_autocmd_blocked())
1757 {
1758 unblock_autocmds();
1759 ++unblock;
1760 }
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001761 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
Bram Moolenaar129d6bf2020-05-16 16:08:35 +02001762 if (unblock)
1763 block_autocmds();
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001764 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001765
1766#ifdef FEAT_VIMINFO
Milly6eca04e2024-10-21 22:20:51 +02001767 if (
1768# ifdef EXITFREE
1769 entered_free_all_mem == FALSE &&
1770# endif
1771 *p_viminfo != NUL)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001772 // Write out the registers, history, marks etc, to the viminfo file
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001773 write_viminfo(NULL, FALSE);
1774#endif
1775
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001776 if (v_dying <= 1)
Bram Moolenaarc7226682019-08-17 16:33:23 +02001777 {
1778 int unblock = 0;
1779
1780 // deathtrap() blocks autocommands, but we do want to trigger VimLeave.
1781 if (is_autocmd_blocked())
1782 {
1783 unblock_autocmds();
1784 ++unblock;
1785 }
Bram Moolenaar0e1e25f2010-05-28 21:07:08 +02001786 apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
Bram Moolenaarc7226682019-08-17 16:33:23 +02001787 if (unblock)
1788 block_autocmds();
1789 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001790
Bram Moolenaar05159a02005-02-26 23:04:13 +00001791#ifdef FEAT_PROFILE
1792 profile_dump();
1793#endif
1794
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001795 if (did_emsg
1796#ifdef FEAT_GUI
1797 || (gui.in_use && msg_didany && p_verbose > 0)
1798#endif
1799 )
1800 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001801 // give the user a chance to read the (error) message
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001802 no_wait_return = FALSE;
Volodymyr Kot7f0c4b42021-11-21 12:27:13 +00001803 wait_return(FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001804 }
1805
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001806 // Position the cursor again, the autocommands may have moved it
Bram Moolenaar7007e312021-03-27 12:11:33 +01001807 if (!is_not_a_term_or_gui())
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001808 windgoto((int)Rows - 1, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001809
Bram Moolenaar509ce2a2016-03-11 22:52:15 +01001810#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar65edff82016-02-21 16:40:11 +01001811 job_stop_on_exit();
1812#endif
Bram Moolenaar0ba04292010-07-14 23:23:17 +02001813#ifdef FEAT_LUA
1814 lua_end();
1815#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00001816#ifdef FEAT_MZSCHEME
1817 mzscheme_end();
1818#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001819#ifdef FEAT_TCL
1820 tcl_end();
1821#endif
1822#ifdef FEAT_RUBY
1823 ruby_end();
1824#endif
1825#ifdef FEAT_PYTHON
1826 python_end();
1827#endif
Bram Moolenaarbd5e15f2010-07-17 21:19:38 +02001828#ifdef FEAT_PYTHON3
1829 python3_end();
1830#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001831#ifdef FEAT_PERL
1832 perl_end();
1833#endif
1834#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
1835 iconv_end();
1836#endif
1837#ifdef FEAT_NETBEANS_INTG
1838 netbeans_end();
1839#endif
Bram Moolenaar02b06312007-09-06 15:39:22 +00001840#ifdef FEAT_CSCOPE
1841 cs_end();
1842#endif
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00001843#ifdef FEAT_EVAL
1844 if (garbage_collect_at_exit)
Bram Moolenaarebf7dfa2016-04-14 12:46:51 +02001845 garbage_collect(FALSE);
Bram Moolenaar9d2c8c12007-09-25 16:00:00 +00001846#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01001847#ifdef MSWIN
Bram Moolenaar14993322014-09-09 12:25:33 +02001848 free_cmd_argsW();
1849#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001850
1851 mch_exit(exitval);
1852}
1853
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001854/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00001855 * Get the name of the display, before gui_prepare() removes it from
1856 * argv[]. Used for the xterm-clipboard display.
1857 *
Bram Moolenaar78e17622007-08-30 10:26:19 +00001858 * Also find the --server... arguments and --socketid and --windowid
Bram Moolenaar58d98232005-07-23 22:25:46 +00001859 */
Bram Moolenaar58d98232005-07-23 22:25:46 +00001860 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01001861early_arg_scan(mparm_T *parmp UNUSED)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001862{
Bram Moolenaar03005972008-11-20 13:12:36 +00001863#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER) \
1864 || !defined(FEAT_NETBEANS_INTG)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001865 int argc = parmp->argc;
1866 char **argv = parmp->argv;
Bram Moolenaar58d98232005-07-23 22:25:46 +00001867 int i;
1868
1869 for (i = 1; i < argc; i++)
1870 {
1871 if (STRCMP(argv[i], "--") == 0)
1872 break;
1873# ifdef FEAT_XCLIPBOARD
1874 else if (STRICMP(argv[i], "-display") == 0
Bram Moolenaar241a8aa2005-12-06 20:04:44 +00001875# if defined(FEAT_GUI_GTK)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001876 || STRICMP(argv[i], "--display") == 0
1877# endif
1878 )
1879 {
1880 if (i == argc - 1)
1881 mainerr_arg_missing((char_u *)argv[i]);
1882 xterm_display = argv[++i];
1883 }
1884# endif
1885# ifdef FEAT_CLIENTSERVER
1886 else if (STRICMP(argv[i], "--servername") == 0)
1887 {
1888 if (i == argc - 1)
1889 mainerr_arg_missing((char_u *)argv[i]);
1890 parmp->serverName_arg = (char_u *)argv[++i];
1891 }
Bram Moolenaareb94e552006-03-11 21:35:11 +00001892 else if (STRICMP(argv[i], "--serverlist") == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001893 parmp->serverArg = TRUE;
Bram Moolenaareb94e552006-03-11 21:35:11 +00001894 else if (STRNICMP(argv[i], "--remote", 8) == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001895 {
1896 parmp->serverArg = TRUE;
Bram Moolenaareb94e552006-03-11 21:35:11 +00001897# ifdef FEAT_GUI
1898 if (strstr(argv[i], "-wait") != 0)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001899 // don't fork() when starting the GUI to edit files ourself
Bram Moolenaareb94e552006-03-11 21:35:11 +00001900 gui.dofork = FALSE;
1901# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001902 }
1903# endif
Bram Moolenaar78e17622007-08-30 10:26:19 +00001904
Bram Moolenaar4f974752019-02-17 17:44:42 +01001905# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
1906# ifdef FEAT_GUI_MSWIN
Bram Moolenaar78e17622007-08-30 10:26:19 +00001907 else if (STRICMP(argv[i], "--windowid") == 0)
1908# else
Bram Moolenaar58d98232005-07-23 22:25:46 +00001909 else if (STRICMP(argv[i], "--socketid") == 0)
Bram Moolenaar78e17622007-08-30 10:26:19 +00001910# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001911 {
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001912 long_u id;
1913 int count;
Bram Moolenaar58d98232005-07-23 22:25:46 +00001914
1915 if (i == argc - 1)
1916 mainerr_arg_missing((char_u *)argv[i]);
1917 if (STRNICMP(argv[i+1], "0x", 2) == 0)
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001918 count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id);
Bram Moolenaar58d98232005-07-23 22:25:46 +00001919 else
Bram Moolenaarcb4cef22008-03-16 15:04:34 +00001920 count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id);
Bram Moolenaar58d98232005-07-23 22:25:46 +00001921 if (count != 1)
1922 mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
1923 else
Bram Moolenaar4f974752019-02-17 17:44:42 +01001924# ifdef FEAT_GUI_MSWIN
Bram Moolenaar78e17622007-08-30 10:26:19 +00001925 win_socket_id = id;
1926# else
1927 gtk_socket_id = id;
1928# endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00001929 i++;
1930 }
Bram Moolenaar78e17622007-08-30 10:26:19 +00001931# endif
1932# ifdef FEAT_GUI_GTK
Bram Moolenaar58d98232005-07-23 22:25:46 +00001933 else if (STRICMP(argv[i], "--echo-wid") == 0)
1934 echo_wid_arg = TRUE;
1935# endif
Bram Moolenaar03005972008-11-20 13:12:36 +00001936# ifndef FEAT_NETBEANS_INTG
1937 else if (strncmp(argv[i], "-nb", (size_t)3) == 0)
Bram Moolenaar67c53842010-05-22 18:28:27 +02001938 {
1939 mch_errmsg(_("'-nb' cannot be used: not enabled at compile time\n"));
1940 mch_exit(2);
1941 }
Bram Moolenaar03005972008-11-20 13:12:36 +00001942# endif
1943
Bram Moolenaar58d98232005-07-23 22:25:46 +00001944 }
1945#endif
1946}
1947
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001948#ifndef NO_VIM_MAIN
1949/*
1950 * Get a (optional) count for a Vim argument.
1951 */
1952 static int
1953get_number_arg(
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001954 char_u *p, // pointer to argument
1955 int *idx, // index in argument, is incremented
1956 int def) // default value
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001957{
1958 if (vim_isdigit(p[*idx]))
1959 {
1960 def = atoi((char *)&(p[*idx]));
1961 while (vim_isdigit(p[*idx]))
1962 *idx = *idx + 1;
1963 }
1964 return def;
1965}
1966
1967/*
Bram Moolenaar27e80c82018-10-14 21:41:01 +02001968 * Check for: [r][e][g][vi|vim|view][diff][ex[im]] (sort of)
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001969 * If the executable name starts with "r" we disable shell commands.
1970 * If the next character is "e" we run in Easy mode.
1971 * If the next character is "g" we run the GUI version.
1972 * If the next characters are "view" we start in readonly mode.
1973 * If the next characters are "diff" or "vimdiff" we start in diff mode.
1974 * If the next characters are "ex" we start in Ex mode. If it's followed
1975 * by "im" use improved Ex mode.
1976 */
1977 static void
1978parse_command_name(mparm_T *parmp)
1979{
1980 char_u *initstr;
1981
1982 initstr = gettail((char_u *)parmp->argv[0]);
1983
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001984#ifdef FEAT_EVAL
1985 set_vim_var_string(VV_PROGNAME, initstr, -1);
Bram Moolenaar08cab962017-03-04 14:37:18 +01001986 set_progpath((char_u *)parmp->argv[0]);
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001987#endif
1988
1989 if (TOLOWER_ASC(initstr[0]) == 'r')
1990 {
1991 restricted = TRUE;
1992 ++initstr;
1993 }
1994
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01001995 // Use evim mode for "evim" and "egvim", not for "editor".
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02001996 if (TOLOWER_ASC(initstr[0]) == 'e'
1997 && (TOLOWER_ASC(initstr[1]) == 'v'
1998 || TOLOWER_ASC(initstr[1]) == 'g'))
1999 {
2000#ifdef FEAT_GUI
2001 gui.starting = TRUE;
2002#endif
2003 parmp->evim_mode = TRUE;
2004 ++initstr;
2005 }
2006
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002007 // "gvim" starts the GUI. Also accept "Gvim" for MS-Windows.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002008 if (TOLOWER_ASC(initstr[0]) == 'g')
2009 {
2010 main_start_gui();
2011#ifdef FEAT_GUI
2012 ++initstr;
2013#endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002014#ifdef GUI_MAY_SPAWN
2015 gui.dospawn = FALSE; // No need to spawn a new process.
2016#endif
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002017 }
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002018#ifdef GUI_MAY_SPAWN
2019 else
2020 gui.dospawn = TRUE; // Not "gvim". Need to spawn gvim.exe.
2021#endif
2022
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002023
2024 if (STRNICMP(initstr, "view", 4) == 0)
2025 {
2026 readonlymode = TRUE;
2027 curbuf->b_p_ro = TRUE;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002028 p_uc = 10000; // don't update very often
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002029 initstr += 4;
2030 }
2031 else if (STRNICMP(initstr, "vim", 3) == 0)
2032 initstr += 3;
2033
Bram Moolenaar27e80c82018-10-14 21:41:01 +02002034 // Catch "[r][g]vimdiff" and "[r][g]viewdiff".
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002035 if (STRICMP(initstr, "diff") == 0)
2036 {
2037#ifdef FEAT_DIFF
2038 parmp->diff_mode = TRUE;
2039#else
2040 mch_errmsg(_("This Vim was not compiled with the diff feature."));
2041 mch_errmsg("\n");
2042 mch_exit(2);
2043#endif
2044 }
2045
Bram Moolenaarcde0ff32020-04-04 14:00:39 +02002046 // Checking for "ex" here may catch some weird names, such as "vimex" or
Bram Moolenaar27e80c82018-10-14 21:41:01 +02002047 // "viewex", we assume the user knows that.
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002048 if (STRNICMP(initstr, "ex", 2) == 0)
2049 {
2050 if (STRNICMP(initstr + 2, "im", 2) == 0)
2051 exmode_active = EXMODE_VIM;
2052 else
2053 exmode_active = EXMODE_NORMAL;
Bram Moolenaar27e80c82018-10-14 21:41:01 +02002054 change_compatible(TRUE); // set 'compatible'
Bram Moolenaar502ae4b2016-07-16 19:50:13 +02002055 }
2056}
2057
Bram Moolenaar58d98232005-07-23 22:25:46 +00002058/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002059 * Scan the command line arguments.
2060 */
2061 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002062command_line_scan(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002063{
2064 int argc = parmp->argc;
2065 char **argv = parmp->argv;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002066 int argv_idx; // index in argv[n][]
2067 int had_minmin = FALSE; // found "--" argument
2068 int want_argument; // option argument with argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002069 int c;
Bram Moolenaar231334e2005-07-25 20:46:57 +00002070 char_u *p = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002071 long n;
2072
2073 --argc;
2074 ++argv;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002075 argv_idx = 1; // active option letter is argv[0][argv_idx]
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002076 while (argc > 0)
2077 {
2078 /*
2079 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
2080 */
2081 if (argv[0][0] == '+' && !had_minmin)
2082 {
2083 if (parmp->n_commands >= MAX_ARG_CMDS)
2084 mainerr(ME_EXTRA_CMD, NULL);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002085 argv_idx = -1; // skip to next argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002086 if (argv[0][1] == NUL)
2087 parmp->commands[parmp->n_commands++] = (char_u *)"$";
2088 else
2089 parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]);
2090 }
2091
2092 /*
2093 * Optional argument.
2094 */
2095 else if (argv[0][0] == '-' && !had_minmin)
2096 {
2097 want_argument = FALSE;
2098 c = argv[0][argv_idx++];
2099#ifdef VMS
2100 /*
2101 * VMS only uses upper case command lines. Interpret "-X" as "-x"
2102 * and "-/X" as "-X".
2103 */
2104 if (c == '/')
2105 {
2106 c = argv[0][argv_idx++];
2107 c = TOUPPER_ASC(c);
2108 }
2109 else
2110 c = TOLOWER_ASC(c);
2111#endif
2112 switch (c)
2113 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002114 case NUL: // "vim -" read from stdin
2115 // "ex -" silent mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002116 if (exmode_active)
2117 silent_mode = TRUE;
2118 else
2119 {
2120 if (parmp->edit_type != EDIT_NONE)
2121 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2122 parmp->edit_type = EDIT_STDIN;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002123 read_cmd_fd = 2; // read from stderr instead of stdin
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002124 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002125 argv_idx = -1; // skip to next argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002126 break;
2127
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002128 case '-': // "--" don't take any more option arguments
2129 // "--help" give help message
2130 // "--version" give version message
2131 // "--clean" clean context
2132 // "--literal" take files literally
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +01002133 // "--startuptime fname" write timing info
2134 // "--log fname" start logging early
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002135 // "--nofork" don't fork
2136 // "--not-a-term" don't warn for not a term
Bram Moolenaar2d12c252022-06-13 21:42:45 +01002137 // "--gui-dialog-file fname" write dialog text
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002138 // "--ttyfail" exit if not a term
2139 // "--noplugin[s]" skip plugins
2140 // "--cmd <cmd>" execute cmd before vimrc
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002141 if (STRICMP(argv[0] + argv_idx, "help") == 0)
2142 usage();
2143 else if (STRICMP(argv[0] + argv_idx, "version") == 0)
2144 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002145 Columns = 80; // need to init Columns
2146 info_message = TRUE; // use mch_msg(), not mch_errmsg()
K.Takata33b25d12022-01-13 16:06:45 +00002147#if defined(FEAT_GUI) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL)
Bram Moolenaar3b678042021-02-11 19:08:05 +01002148 gui.starting = FALSE; // not starting GUI, will exit
Bram Moolenaar0bcadf12021-02-11 19:18:58 +01002149#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002150 list_version();
2151 msg_putchar('\n');
2152 msg_didout = FALSE;
2153 mch_exit(0);
2154 }
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002155 else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0)
2156 {
2157 parmp->use_vimrc = (char_u *)"DEFAULTS";
Bram Moolenaar62dd4522018-03-14 21:20:02 +01002158#ifdef FEAT_GUI
2159 use_gvimrc = (char_u *)"NONE";
2160#endif
Bram Moolenaar07268702018-03-01 21:57:32 +01002161 parmp->clean = TRUE;
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002162 set_option_value_give_err((char_u *)"vif",
2163 0L, (char_u *)"NONE", 0);
Bram Moolenaarc4da1132017-07-15 19:39:43 +02002164 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002165 else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
2166 {
Bram Moolenaar53076832015-12-31 19:53:21 +01002167#ifdef EXPAND_FILENAMES
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002168 parmp->literal = TRUE;
2169#endif
2170 }
2171 else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
2172 {
2173#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002174 gui.dofork = FALSE; // don't fork() when starting GUI
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002175#endif
2176 }
2177 else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
2178 p_lpl = FALSE;
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01002179 else if (STRNICMP(argv[0] + argv_idx, "not-a-term", 10) == 0)
2180 parmp->not_a_term = TRUE;
Bram Moolenaar2d12c252022-06-13 21:42:45 +01002181 else if (STRNICMP(argv[0] + argv_idx, "gui-dialog-file", 15)
2182 == 0)
2183 {
2184 want_argument = TRUE;
2185 argv_idx += 15;
2186 }
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002187 else if (STRNICMP(argv[0] + argv_idx, "ttyfail", 7) == 0)
2188 parmp->tty_fail = TRUE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002189 else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
2190 {
2191 want_argument = TRUE;
2192 argv_idx += 3;
2193 }
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002194 else if (STRNICMP(argv[0] + argv_idx, "startuptime", 11) == 0)
2195 {
2196 want_argument = TRUE;
2197 argv_idx += 11;
2198 }
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +01002199 else if (STRNICMP(argv[0] + argv_idx, "log", 3) == 0)
2200 {
2201 want_argument = TRUE;
2202 argv_idx += 3;
2203 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002204#ifdef FEAT_CLIENTSERVER
2205 else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002206 ; // already processed -- no arg
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002207 else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
2208 || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
2209 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002210 // already processed -- snatch the following arg
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002211 if (argc > 1)
2212 {
2213 --argc;
2214 ++argv;
2215 }
2216 }
2217#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01002218#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN)
Bram Moolenaar78e17622007-08-30 10:26:19 +00002219# ifdef FEAT_GUI_GTK
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002220 else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
Bram Moolenaar78e17622007-08-30 10:26:19 +00002221# else
2222 else if (STRNICMP(argv[0] + argv_idx, "windowid", 8) == 0)
2223# endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002224 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002225 // already processed -- snatch the following arg
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002226 if (argc > 1)
2227 {
2228 --argc;
2229 ++argv;
2230 }
2231 }
Bram Moolenaar78e17622007-08-30 10:26:19 +00002232#endif
2233#ifdef FEAT_GUI_GTK
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002234 else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
2235 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002236 // already processed, skip
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002237 }
2238#endif
2239 else
2240 {
2241 if (argv[0][argv_idx])
2242 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
2243 had_minmin = TRUE;
2244 }
2245 if (!want_argument)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002246 argv_idx = -1; // skip to next argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002247 break;
2248
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002249 case 'A': // "-A" start in Arabic mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002250#ifdef FEAT_ARABIC
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002251 set_option_value_give_err((char_u *)"arabic", 1L, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002252#else
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00002253 mch_errmsg(_(e_arabic_cannot_be_used_not_enabled_at_compile_time));
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002254 mch_exit(2);
2255#endif
2256 break;
2257
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002258 case 'b': // "-b" binary mode
2259 // Needs to be effective before expanding file names, because
2260 // for Win32 this makes us edit a shortcut file itself,
2261 // instead of the file it links to.
Bram Moolenaar231334e2005-07-25 20:46:57 +00002262 set_options_bin(curbuf->b_p_bin, 1, 0);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002263 curbuf->b_p_bin = 1; // binary file I/O
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002264 break;
2265
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002266 case 'C': // "-C" Compatible
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002267 change_compatible(TRUE);
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +02002268 has_dash_c_arg = TRUE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002269 break;
2270
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002271 case 'e': // "-e" Ex mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002272 exmode_active = EXMODE_NORMAL;
2273 break;
2274
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002275 case 'E': // "-E" Improved Ex mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002276 exmode_active = EXMODE_VIM;
2277 break;
2278
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002279 case 'f': // "-f" GUI: run in foreground. Amiga: open
2280 // window directly, not with newcli
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002281#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002282 gui.dofork = FALSE; // don't fork() when starting GUI
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002283#endif
2284 break;
2285
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002286 case 'g': // "-g" start GUI
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002287 main_start_gui();
2288 break;
2289
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002290 case 'F': // "-F" was for Farsi mode
Bram Moolenaare29a27f2021-07-20 21:07:36 +02002291 mch_errmsg(_(e_farsi_support_has_been_removed));
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002292 mch_exit(2);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002293 break;
2294
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002295 case '?': // "-?" give help message (for MS-Windows)
2296 case 'h': // "-h" give help message
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002297#ifdef FEAT_GUI_GNOME
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002298 // Tell usage() to exit for "gvim".
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002299 gui.starting = FALSE;
2300#endif
2301 usage();
2302 break;
2303
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002304 case 'H': // "-H" start in Hebrew mode: rl + hkmap set
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002305#ifdef FEAT_RIGHTLEFT
Bram Moolenaarc4cd38f2008-01-13 15:18:01 +00002306 p_hkmap = TRUE;
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002307 set_option_value_give_err((char_u *)"rl", 1L, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002308#else
Bram Moolenaare29a27f2021-07-20 21:07:36 +02002309 mch_errmsg(_(e_hebrew_cannot_be_used_not_enabled_at_compile_time));
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002310 mch_exit(2);
2311#endif
2312 break;
2313
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002314 case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002315 set_option_value_give_err((char_u *)"lisp", 1L, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002316 p_sm = TRUE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002317 break;
2318
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002319 case 'M': // "-M" no changes or writing of files
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002320 reset_modifiable();
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002321 // FALLTHROUGH
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002322
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002323 case 'm': // "-m" no writing of files
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002324 p_write = FALSE;
2325 break;
2326
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002327 case 'y': // "-y" easy mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002328#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002329 gui.starting = TRUE; // start GUI a bit later
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002330#endif
2331 parmp->evim_mode = TRUE;
2332 break;
2333
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002334 case 'N': // "-N" Nocompatible
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002335 change_compatible(FALSE);
2336 break;
2337
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002338 case 'n': // "-n" no swap file
Bram Moolenaar67c53842010-05-22 18:28:27 +02002339#ifdef FEAT_NETBEANS_INTG
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002340 // checking for "-nb", netbeans parameters
Bram Moolenaar67c53842010-05-22 18:28:27 +02002341 if (argv[0][argv_idx] == 'b')
2342 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02002343 netbeansArg = argv[0];
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002344 argv_idx = -1; // skip to next argument
Bram Moolenaar67c53842010-05-22 18:28:27 +02002345 }
2346 else
2347#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002348 parmp->no_swap_file = TRUE;
2349 break;
2350
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002351 case 'p': // "-p[N]" open N tab pages
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00002352#ifdef TARGET_API_MAC_OSX
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002353 // For some reason on MacOS X, an argument like:
2354 // -psn_0_10223617 is passed in when invoke from Finder
2355 // or with the 'open' command
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00002356 if (argv[0][argv_idx] == 's')
2357 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002358 argv_idx = -1; // bypass full -psn
Bram Moolenaar7e8fd632006-02-18 22:14:51 +00002359 main_start_gui();
2360 break;
2361 }
2362#endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002363 // default is 0: open window for each file
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002364 parmp->window_count = get_number_arg((char_u *)argv[0],
2365 &argv_idx, 0);
2366 parmp->window_layout = WIN_TABS;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002367 break;
2368
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002369 case 'o': // "-o[N]" open N horizontal split windows
2370 // default is 0: open window for each file
Bram Moolenaar231334e2005-07-25 20:46:57 +00002371 parmp->window_count = get_number_arg((char_u *)argv[0],
2372 &argv_idx, 0);
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002373 parmp->window_layout = WIN_HOR;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002374 break;
2375
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002376 case 'O': // "-O[N]" open N vertical split windows
2377 // default is 0: open window for each file
Bram Moolenaar231334e2005-07-25 20:46:57 +00002378 parmp->window_count = get_number_arg((char_u *)argv[0],
2379 &argv_idx, 0);
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002380 parmp->window_layout = WIN_VER;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002381 break;
2382
2383#ifdef FEAT_QUICKFIX
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002384 case 'q': // "-q" QuickFix mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002385 if (parmp->edit_type != EDIT_NONE)
2386 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2387 parmp->edit_type = EDIT_QF;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002388 if (argv[0][argv_idx]) // "-q{errorfile}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002389 {
2390 parmp->use_ef = (char_u *)argv[0] + argv_idx;
2391 argv_idx = -1;
2392 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002393 else if (argc > 1) // "-q {errorfile}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002394 want_argument = TRUE;
2395 break;
2396#endif
2397
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002398 case 'R': // "-R" readonly mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002399 readonlymode = TRUE;
2400 curbuf->b_p_ro = TRUE;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002401 p_uc = 10000; // don't update very often
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002402 break;
2403
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002404 case 'r': // "-r" recovery mode
2405 case 'L': // "-L" recovery mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002406 recoverymode = 1;
2407 break;
2408
2409 case 's':
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002410 if (exmode_active) // "-s" silent (batch) mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002411 silent_mode = TRUE;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002412 else // "-s {scriptin}" read from script file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002413 want_argument = TRUE;
2414 break;
2415
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002416 case 't': // "-t {tag}" or "-t{tag}" jump to tag
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002417 if (parmp->edit_type != EDIT_NONE)
2418 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2419 parmp->edit_type = EDIT_TAG;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002420 if (argv[0][argv_idx]) // "-t{tag}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002421 {
2422 parmp->tagname = (char_u *)argv[0] + argv_idx;
2423 argv_idx = -1;
2424 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002425 else // "-t {tag}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002426 want_argument = TRUE;
2427 break;
2428
2429#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002430 case 'D': // "-D" Debugging
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002431 parmp->use_debug_break_level = 9999;
2432 break;
2433#endif
2434#ifdef FEAT_DIFF
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002435 case 'd': // "-d" 'diff'
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002436# ifdef AMIGA
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002437 // check for "-dev {device}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002438 if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
2439 want_argument = TRUE;
2440 else
2441# endif
2442 parmp->diff_mode = TRUE;
2443 break;
2444#endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002445 case 'V': // "-V{N}" Verbose level
2446 // default is 10: a little bit verbose
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002447 p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10);
2448 if (argv[0][argv_idx] != NUL)
2449 {
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002450 set_option_value_give_err((char_u *)"verbosefile",
2451 0L, (char_u *)argv[0] + argv_idx, 0);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +00002452 argv_idx = (int)STRLEN(argv[0]);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002453 }
2454 break;
2455
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002456 case 'v': // "-v" Vi-mode (as if called "vi")
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002457 exmode_active = 0;
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002458#if defined(FEAT_GUI) && !defined(VIMDLL)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002459 gui.starting = FALSE; // don't start GUI
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002460#endif
2461 break;
2462
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002463 case 'w': // "-w{number}" set window height
2464 // "-w {scriptout}" write to script
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002465 if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
2466 {
2467 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002468 set_option_value_give_err((char_u *)"window", n, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002469 break;
2470 }
2471 want_argument = TRUE;
2472 break;
2473
2474#ifdef FEAT_CRYPT
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002475 case 'x': // "-x" encrypted reading/writing of files
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002476 parmp->ask_for_key = TRUE;
2477 break;
2478#endif
2479
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002480 case 'X': // "-X" don't connect to X server
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002481#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
2482 x_no_connect = TRUE;
2483#endif
2484 break;
Hirohito Higashi73b96502025-06-28 18:18:21 +02002485 case 'Y': // "-Y" don't connect to Wayland compositor
Foxe Chenb90c2392025-06-27 21:10:35 +02002486#if defined(FEAT_WAYLAND)
2487 wayland_no_connect = TRUE;
2488#endif
2489 break;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002490
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002491 case 'Z': // "-Z" restricted mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002492 restricted = TRUE;
2493 break;
2494
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002495 case 'c': // "-c{command}" or "-c {command}" execute
2496 // command
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002497 if (argv[0][argv_idx] != NUL)
2498 {
2499 if (parmp->n_commands >= MAX_ARG_CMDS)
2500 mainerr(ME_EXTRA_CMD, NULL);
Bram Moolenaar231334e2005-07-25 20:46:57 +00002501 parmp->commands[parmp->n_commands++] = (char_u *)argv[0]
2502 + argv_idx;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002503 argv_idx = -1;
2504 break;
2505 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002506 // FALLTHROUGH
2507 case 'S': // "-S {file}" execute Vim script
2508 case 'i': // "-i {viminfo}" use for viminfo
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002509#ifndef FEAT_DIFF
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002510 case 'd': // "-d {device}" device (for Amiga)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002511#endif
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002512 case 'T': // "-T {terminal}" terminal name
2513 case 'u': // "-u {vimrc}" vim inits file
2514 case 'U': // "-U {gvimrc}" gvim inits file
2515 case 'W': // "-W {scriptout}" overwrite
Bram Moolenaar4f974752019-02-17 17:44:42 +01002516#ifdef FEAT_GUI_MSWIN
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002517 case 'P': // "-P {parent title}" MDI parent
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002518#endif
2519 want_argument = TRUE;
2520 break;
2521
2522 default:
2523 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
2524 }
2525
2526 /*
2527 * Handle option arguments with argument.
2528 */
2529 if (want_argument)
2530 {
2531 /*
2532 * Check for garbage immediately after the option letter.
2533 */
2534 if (argv[0][argv_idx] != NUL)
2535 mainerr(ME_GARBAGE, (char_u *)argv[0]);
2536
2537 --argc;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002538 if (argc < 1 && c != 'S') // -S has an optional argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002539 mainerr_arg_missing((char_u *)argv[0]);
2540 ++argv;
2541 argv_idx = -1;
2542
2543 switch (c)
2544 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002545 case 'c': // "-c {command}" execute command
2546 case 'S': // "-S {file}" execute Vim script
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002547 if (parmp->n_commands >= MAX_ARG_CMDS)
2548 mainerr(ME_EXTRA_CMD, NULL);
2549 if (c == 'S')
2550 {
2551 char *a;
2552
2553 if (argc < 1)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002554 // "-S" without argument: use default session file
2555 // name.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002556 a = SESSION_FILE;
2557 else if (argv[0][0] == '-')
2558 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002559 // "-S" followed by another option: use default
2560 // session file name.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002561 a = SESSION_FILE;
2562 ++argc;
2563 --argv;
2564 }
2565 else
2566 a = argv[0];
Bram Moolenaar964b3742019-05-24 18:54:09 +02002567 p = alloc(STRLEN(a) + 4);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002568 if (p == NULL)
2569 mch_exit(2);
2570 sprintf((char *)p, "so %s", a);
2571 parmp->cmds_tofree[parmp->n_commands] = TRUE;
2572 parmp->commands[parmp->n_commands++] = p;
2573 }
2574 else
Bram Moolenaar231334e2005-07-25 20:46:57 +00002575 parmp->commands[parmp->n_commands++] =
2576 (char_u *)argv[0];
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002577 break;
2578
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002579 case '-':
2580 if (argv[-1][2] == 'c')
2581 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002582 // "--cmd {command}" execute command
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002583 if (parmp->n_pre_commands >= MAX_ARG_CMDS)
2584 mainerr(ME_EXTRA_CMD, NULL);
2585 parmp->pre_commands[parmp->n_pre_commands++] =
Bram Moolenaar231334e2005-07-25 20:46:57 +00002586 (char_u *)argv[0];
Bram Moolenaaref94eec2009-11-11 13:22:11 +00002587 }
Bram Moolenaar2d12c252022-06-13 21:42:45 +01002588 // --gui-dialog-file fname
2589 if (argv[-1][2] == 'g')
2590 {
2591 // without GUI ignore the argument
2592#ifdef FEAT_GUI
2593 parmp->gui_dialog_file = (char_u *)argv[0];
2594#endif
2595 }
2596
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002597 // "--startuptime <file>" already handled
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +01002598 // "--log <file>" already handled
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002599 break;
2600
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002601 // case 'd': -d {device} is handled in mch_check_win() for the
2602 // Amiga
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002603
2604#ifdef FEAT_QUICKFIX
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002605 case 'q': // "-q {errorfile}" QuickFix mode
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002606 parmp->use_ef = (char_u *)argv[0];
2607 break;
2608#endif
2609
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002610 case 'i': // "-i {viminfo}" use for viminfo
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002611 set_option_value_give_err((char_u *)"vif",
2612 0L, (char_u *)argv[0], 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002613 break;
2614
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002615 case 's': // "-s {scriptin}" read from script file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002616 if (scriptin[0] != NULL)
2617 {
2618scripterror:
2619 mch_errmsg(_("Attempt to open script file again: \""));
2620 mch_errmsg(argv[-1]);
2621 mch_errmsg(" ");
2622 mch_errmsg(argv[0]);
2623 mch_errmsg("\"\n");
2624 mch_exit(2);
2625 }
2626 if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
2627 {
2628 mch_errmsg(_("Cannot open for reading: \""));
2629 mch_errmsg(argv[0]);
2630 mch_errmsg("\"\n");
2631 mch_exit(2);
2632 }
2633 if (save_typebuf() == FAIL)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002634 mch_exit(2); // out of memory
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002635 break;
2636
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002637 case 't': // "-t {tag}"
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002638 parmp->tagname = (char_u *)argv[0];
2639 break;
2640
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002641 case 'T': // "-T {terminal}" terminal name
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002642 /*
2643 * The -T term argument is always available and when
2644 * HAVE_TERMLIB is supported it overrides the environment
2645 * variable TERM.
2646 */
2647#ifdef FEAT_GUI
2648 if (term_is_gui((char_u *)argv[0]))
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002649 gui.starting = TRUE; // start GUI a bit later
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002650 else
2651#endif
2652 parmp->term = (char_u *)argv[0];
2653 break;
2654
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002655 case 'u': // "-u {vimrc}" vim inits file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002656 parmp->use_vimrc = (char_u *)argv[0];
2657 break;
2658
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002659 case 'U': // "-U {gvimrc}" gvim inits file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002660#ifdef FEAT_GUI
2661 use_gvimrc = (char_u *)argv[0];
2662#endif
2663 break;
2664
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002665 case 'w': // "-w {nr}" 'window' value
2666 // "-w {scriptout}" append to script file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002667 if (vim_isdigit(*((char_u *)argv[0])))
2668 {
2669 argv_idx = 0;
2670 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
Bram Moolenaar31e5c602022-04-15 13:53:33 +01002671 set_option_value_give_err((char_u *)"window",
2672 n, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002673 argv_idx = -1;
2674 break;
2675 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002676 // FALLTHROUGH
2677 case 'W': // "-W {scriptout}" overwrite script file
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002678 if (scriptout != NULL)
2679 goto scripterror;
2680 if ((scriptout = mch_fopen(argv[0],
2681 c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
2682 {
2683 mch_errmsg(_("Cannot open for script output: \""));
2684 mch_errmsg(argv[0]);
2685 mch_errmsg("\"\n");
2686 mch_exit(2);
2687 }
2688 break;
2689
Bram Moolenaar4f974752019-02-17 17:44:42 +01002690#ifdef FEAT_GUI_MSWIN
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002691 case 'P': // "-P {parent title}" MDI parent
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002692 gui_mch_set_parent(argv[0]);
2693 break;
2694#endif
2695 }
2696 }
2697 }
2698
2699 /*
2700 * File name argument.
2701 */
2702 else
2703 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002704 argv_idx = -1; // skip to next argument
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002705
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002706 // Check for only one type of editing.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002707 if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
2708 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2709 parmp->edit_type = EDIT_FILE;
2710
2711#ifdef MSWIN
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002712 // Remember if the argument was a full path before changing
2713 // slashes to backslashes.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002714 if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
2715 parmp->full_path = TRUE;
2716#endif
2717
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002718 // Add the file to the global argument list.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002719 if (ga_grow(&global_alist.al_ga, 1) == FAIL
2720 || (p = vim_strsave((char_u *)argv[0])) == NULL)
2721 mch_exit(2);
2722#ifdef FEAT_DIFF
2723 if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
2724 && !mch_isdir(alist_name(&GARGLIST[0])))
2725 {
2726 char_u *r;
2727
2728 r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
2729 if (r != NULL)
2730 {
2731 vim_free(p);
2732 p = r;
2733 }
2734 }
2735#endif
K.Takatab247e062022-02-07 10:45:23 +00002736#ifdef __CYGWIN__
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002737 /*
2738 * If vim is invoked by non-Cygwin tools, convert away any
2739 * DOS paths, so things like .swp files are created correctly.
2740 * Look for evidence of non-Cygwin paths before we bother.
2741 * This is only for when using the Unix files.
2742 */
Bram Moolenaarfe17e762013-06-29 14:17:02 +02002743 if (vim_strpbrk(p, "\\:") != NULL && !path_with_url(p))
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002744 {
Bram Moolenaara9f8ee02017-08-14 23:40:45 +02002745 char posix_path[MAXPATHL];
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002746
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002747# if CYGWIN_VERSION_DLL_MAJOR >= 1007
Bram Moolenaara9f8ee02017-08-14 23:40:45 +02002748 cygwin_conv_path(CCP_WIN_A_TO_POSIX, p, posix_path, MAXPATHL);
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002749# else
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002750 cygwin_conv_to_posix_path(p, posix_path);
Bram Moolenaar0d1498e2008-06-29 12:00:49 +00002751# endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002752 vim_free(p);
Bram Moolenaarfe17e762013-06-29 14:17:02 +02002753 p = vim_strsave((char_u *)posix_path);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002754 if (p == NULL)
2755 mch_exit(2);
2756 }
2757#endif
Bram Moolenaarcc016f52005-12-10 20:23:46 +00002758
2759#ifdef USE_FNAME_CASE
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002760 // Make the case of the file name match the actual file.
Bram Moolenaarcc016f52005-12-10 20:23:46 +00002761 fname_case(p, 0);
2762#endif
2763
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002764 alist_add(&global_alist, p,
Bram Moolenaar53076832015-12-31 19:53:21 +01002765#ifdef EXPAND_FILENAMES
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002766 parmp->literal ? 2 : 0 // add buffer nr after exp.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002767#else
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002768 2 // add buffer number now and use curbuf
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002769#endif
2770 );
2771
Bram Moolenaar4f974752019-02-17 17:44:42 +01002772#ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002773 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002774 // Remember this argument has been added to the argument list.
2775 // Needed when 'encoding' is changed.
Bram Moolenaar910f66f2006-04-05 20:41:53 +00002776 used_file_arg(argv[0], parmp->literal, parmp->full_path,
Bram Moolenaar688e5f72008-07-24 11:51:40 +00002777# ifdef FEAT_DIFF
2778 parmp->diff_mode
2779# else
2780 FALSE
2781# endif
2782 );
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002783 }
2784#endif
2785 }
2786
2787 /*
2788 * If there are no more letters after the current "-", go to next
2789 * argument. argv_idx is set to -1 when the current argument is to be
2790 * skipped.
2791 */
2792 if (argv_idx <= 0 || argv[0][argv_idx] == NUL)
2793 {
2794 --argc;
2795 ++argv;
2796 argv_idx = 1;
2797 }
2798 }
Bram Moolenaar867a4b72007-03-18 20:51:46 +00002799
2800#ifdef FEAT_EVAL
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002801 // If there is a "+123" or "-c" command, set v:swapcommand to the first
2802 // one.
Bram Moolenaar867a4b72007-03-18 20:51:46 +00002803 if (parmp->n_commands > 0)
2804 {
Bram Moolenaar964b3742019-05-24 18:54:09 +02002805 p = alloc(STRLEN(parmp->commands[0]) + 3);
Bram Moolenaar867a4b72007-03-18 20:51:46 +00002806 if (p != NULL)
2807 {
2808 sprintf((char *)p, ":%s\r", parmp->commands[0]);
2809 set_vim_var_string(VV_SWAPCOMMAND, p, -1);
2810 vim_free(p);
2811 }
2812 }
2813#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002814}
2815
2816/*
2817 * Print a warning if stdout is not a terminal.
Bram Moolenaar42b23fa2018-02-03 14:46:45 +01002818 * When starting in Ex mode and commands come from a file, set silent_mode.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002819 */
2820 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002821check_tty(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002822{
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002823 int input_isatty; // is active input a terminal?
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002824
2825 input_isatty = mch_input_isatty();
2826 if (exmode_active)
2827 {
2828 if (!input_isatty)
2829 silent_mode = TRUE;
2830 }
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002831 else if (parmp->want_full_screen && (!stdout_isatty || !input_isatty)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002832#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002833 // don't want the delay when started from the desktop
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002834 && !gui.starting
2835#endif
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01002836 && !parmp->not_a_term)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002837 {
2838#ifdef NBDEBUG
2839 /*
2840 * This shouldn't be necessary. But if I run netbeans with the log
2841 * output coming to the console and XOpenDisplay fails, I get vim
2842 * trying to start with input/output to my console tty. This fills my
2843 * input buffer so fast I can't even kill the process in under 2
Bram Moolenaar49325942007-05-10 19:19:59 +00002844 * minutes (and it beeps continuously the whole time :-)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002845 */
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002846 if (netbeans_active() && (!stdout_isatty || !input_isatty))
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002847 {
2848 mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
2849 exit(1);
2850 }
2851#endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +02002852#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
2853 if (
2854# ifdef VIMDLL
2855 !gui.starting &&
2856# endif
2857 is_cygpty_used())
Bram Moolenaar97ff9b92016-06-26 20:37:46 +02002858 {
Bram Moolenaarfc3abf42019-01-24 15:54:21 +01002859# if defined(HAVE_BIND_TEXTDOMAIN_CODESET) \
Bram Moolenaar2a027452017-09-26 19:10:37 +02002860 && defined(FEAT_GETTEXT)
2861 char *s, *tofree = NULL;
2862
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002863 // Set the encoding of the error message based on $LC_ALL or
2864 // other environment variables instead of 'encoding'.
2865 // Note that the message is shown on a Cygwin terminal (e.g.
2866 // mintty) which encoding is based on $LC_ALL or etc., not the
2867 // current codepage used by normal Win32 console programs.
Bram Moolenaar9cf39cc2017-09-27 21:46:19 +02002868 tofree = s = (char *)enc_locale_env(NULL);
Bram Moolenaar2a027452017-09-26 19:10:37 +02002869 if (s == NULL)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002870 s = "utf-8"; // Use "utf-8" by default.
Bram Moolenaar2a027452017-09-26 19:10:37 +02002871 (void)bind_textdomain_codeset(VIMPACKAGE, s);
2872 vim_free(tofree);
2873# endif
Bram Moolenaar97ff9b92016-06-26 20:37:46 +02002874 mch_errmsg(_("Vim: Error: This version of Vim does not run in a Cygwin terminal\n"));
2875 exit(1);
2876 }
2877#endif
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002878 if (!stdout_isatty)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002879 mch_errmsg(_("Vim: Warning: Output is not to a terminal\n"));
2880 if (!input_isatty)
2881 mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
2882 out_flush();
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01002883 if (parmp->tty_fail && (!stdout_isatty || !input_isatty))
2884 exit(1);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002885 if (scriptin[0] == NULL)
Bram Moolenaareda1da02019-11-17 17:06:33 +01002886 ui_delay(2005L, TRUE);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002887 TIME_MSG("Warning delay");
2888 }
2889}
2890
2891/*
2892 * Read text from stdin.
2893 */
2894 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002895read_stdin(void)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002896{
2897 int i;
2898
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002899 // When getting the ATTENTION prompt here, use a dialog
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002900 swap_exists_action = SEA_DIALOG;
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002901
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002902 no_wait_return = TRUE;
2903 i = msg_didany;
2904 set_buflisted(TRUE);
Bram Moolenaar204ade62020-10-11 14:58:46 +02002905
2906 // Create memfile and read from stdin.
Bram Moolenaar204ade62020-10-11 14:58:46 +02002907 (void)open_buffer(TRUE, NULL, 0);
2908
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002909 no_wait_return = FALSE;
2910 msg_didany = i;
2911 TIME_MSG("reading stdin");
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02002912
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002913 check_swap_exists_action();
Bram Moolenaar8e1cbb52020-12-08 19:36:21 +01002914
2915#if !(defined(AMIGA) || defined(MACOS_X))
2916 // Dup stdin from stderr to read commands from, so that shell commands
2917 // work.
2918 // TODO: why is this needed, even though readfile() has done this?
2919 close(0);
2920 vim_ignored = dup(2);
2921#endif
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002922}
2923
2924/*
2925 * Create the requested number of windows and edit buffers in them.
2926 * Also does recovery if "recoverymode" set.
2927 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002928 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01002929create_windows(mparm_T *parmp UNUSED)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002930{
Bram Moolenaar89d40322006-08-29 15:30:07 +00002931 int dorewind;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002932 int done = 0;
2933
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002934 /*
2935 * Create the number of windows that was requested.
2936 */
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002937 if (parmp->window_count == -1) // was not set
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002938 parmp->window_count = 1;
2939 if (parmp->window_count == 0)
2940 parmp->window_count = GARGCOUNT;
2941 if (parmp->window_count > 1)
2942 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002943 // Don't change the windows if there was a command in .vimrc that
2944 // already split some windows
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002945 if (parmp->window_layout == 0)
2946 parmp->window_layout = WIN_HOR;
2947 if (parmp->window_layout == WIN_TABS)
2948 {
2949 parmp->window_count = make_tabpages(parmp->window_count);
2950 TIME_MSG("making tab pages");
2951 }
2952 else if (firstwin->w_next == NULL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002953 {
2954 parmp->window_count = make_windows(parmp->window_count,
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002955 parmp->window_layout == WIN_VER);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002956 TIME_MSG("making windows");
2957 }
2958 else
2959 parmp->window_count = win_count();
2960 }
2961 else
2962 parmp->window_count = 1;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002963
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002964 if (recoverymode) // do recover
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002965 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002966 msg_scroll = TRUE; // scroll message up
Bram Moolenaar99499b12019-05-23 21:35:48 +02002967 ml_recover(TRUE);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002968 if (curbuf->b_ml.ml_mfp == NULL) // failed
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002969 getout(1);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01002970 do_modelines(0); // do modelines
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002971 }
2972 else
2973 {
2974 /*
2975 * Open a buffer for windows that don't have one yet.
2976 * Commands in the .vimrc might have loaded a file or split the window.
2977 * Watch out for autocommands that delete a window.
2978 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002979 /*
2980 * Don't execute Win/Buf Enter/Leave autocommands here
2981 */
2982 ++autocmd_no_enter;
2983 ++autocmd_no_leave;
Bram Moolenaar89d40322006-08-29 15:30:07 +00002984 dorewind = TRUE;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002985 while (done++ < 1000)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002986 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002987 if (dorewind)
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00002988 {
2989 if (parmp->window_layout == WIN_TABS)
2990 goto_tabpage(1);
2991 else
2992 curwin = firstwin;
2993 }
2994 else if (parmp->window_layout == WIN_TABS)
2995 {
2996 if (curtab->tp_next == NULL)
2997 break;
2998 goto_tabpage(0);
2999 }
3000 else
3001 {
3002 if (curwin->w_next == NULL)
3003 break;
3004 curwin = curwin->w_next;
3005 }
Bram Moolenaar89d40322006-08-29 15:30:07 +00003006 dorewind = FALSE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003007 curbuf = curwin->w_buffer;
3008 if (curbuf->b_ml.ml_mfp == NULL)
3009 {
3010#ifdef FEAT_FOLDING
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003011 // Set 'foldlevel' to 'foldlevelstart' if it's not negative.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003012 if (p_fdls >= 0)
3013 curwin->w_p_fdl = p_fdls;
3014#endif
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02003015 // When getting the ATTENTION prompt here, use a dialog
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003016 swap_exists_action = SEA_DIALOG;
Bram Moolenaar67cf86b2019-04-28 22:25:38 +02003017
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003018 set_buflisted(TRUE);
Bram Moolenaar59f931e2010-07-24 20:27:03 +02003019
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003020 // create memfile, read file
Bram Moolenaar59f931e2010-07-24 20:27:03 +02003021 (void)open_buffer(FALSE, NULL, 0);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003022
Bram Moolenaar84212822006-11-07 21:59:47 +00003023 if (swap_exists_action == SEA_QUIT)
3024 {
3025 if (got_int || only_one_window())
3026 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003027 // abort selected or quit and only one window
3028 did_emsg = FALSE; // avoid hit-enter prompt
Bram Moolenaar84212822006-11-07 21:59:47 +00003029 getout(1);
3030 }
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003031 // We can't close the window, it would disturb what
3032 // happens next. Clear the file name and set the arg
3033 // index to -1 to delete it later.
Bram Moolenaar84212822006-11-07 21:59:47 +00003034 setfname(curbuf, NULL, NULL, FALSE);
3035 curwin->w_arg_idx = -1;
3036 swap_exists_action = SEA_NONE;
3037 }
3038 else
3039 handle_swap_exists(NULL);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003040 dorewind = TRUE; // start again
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003041 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003042 ui_breakcheck();
3043 if (got_int)
3044 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003045 (void)vgetc(); // only break the file loading, not the rest
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003046 break;
3047 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003048 }
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003049 if (parmp->window_layout == WIN_TABS)
3050 goto_tabpage(1);
3051 else
3052 curwin = firstwin;
3053 curbuf = curwin->w_buffer;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003054 --autocmd_no_enter;
3055 --autocmd_no_leave;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003056 }
3057}
3058
Bram Moolenaar9810cfb2019-12-11 21:23:00 +01003059/*
3060 * If opened more than one window, start editing files in the other
3061 * windows. make_windows() has already opened the windows.
3062 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003063 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003064edit_buffers(
3065 mparm_T *parmp,
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003066 char_u *cwd) // current working dir
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003067{
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003068 int arg_idx; // index in argument list
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003069 int i;
Bram Moolenaar84212822006-11-07 21:59:47 +00003070 int advance = TRUE;
Bram Moolenaar74cd6242013-08-22 14:14:27 +02003071 win_T *win;
Bram Moolenaarc75e8122019-04-21 15:55:10 +02003072 char_u *p_shm_save = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003073
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003074 /*
3075 * Don't execute Win/Buf Enter/Leave autocommands here
3076 */
3077 ++autocmd_no_enter;
3078 ++autocmd_no_leave;
Bram Moolenaar84212822006-11-07 21:59:47 +00003079
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003080 // When w_arg_idx is -1 remove the window (see create_windows()).
Bram Moolenaar84212822006-11-07 21:59:47 +00003081 if (curwin->w_arg_idx == -1)
3082 {
3083 win_close(curwin, TRUE);
3084 advance = FALSE;
3085 }
3086
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003087 arg_idx = 1;
3088 for (i = 1; i < parmp->window_count; ++i)
3089 {
Bram Moolenaard87c36e2015-04-03 14:56:49 +02003090 if (cwd != NULL)
3091 mch_chdir((char *)cwd);
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003092 // When w_arg_idx is -1 remove the window (see create_windows()).
Bram Moolenaar84212822006-11-07 21:59:47 +00003093 if (curwin->w_arg_idx == -1)
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003094 {
Bram Moolenaar84212822006-11-07 21:59:47 +00003095 ++arg_idx;
3096 win_close(curwin, TRUE);
3097 advance = FALSE;
3098 continue;
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003099 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003100
Bram Moolenaar84212822006-11-07 21:59:47 +00003101 if (advance)
3102 {
3103 if (parmp->window_layout == WIN_TABS)
3104 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003105 if (curtab->tp_next == NULL) // just checking
Bram Moolenaar84212822006-11-07 21:59:47 +00003106 break;
3107 goto_tabpage(0);
Bram Moolenaarc75e8122019-04-21 15:55:10 +02003108 // Temporarily reset 'shm' option to not print fileinfo when
3109 // loading the other buffers. This would overwrite the already
3110 // existing fileinfo for the first tab.
3111 if (i == 1)
3112 {
3113 char buf[100];
3114
3115 p_shm_save = vim_strsave(p_shm);
3116 vim_snprintf(buf, 100, "F%s", p_shm);
Bram Moolenaar31e5c602022-04-15 13:53:33 +01003117 set_option_value_give_err((char_u *)"shm",
3118 0L, (char_u *)buf, 0);
Bram Moolenaarc75e8122019-04-21 15:55:10 +02003119 }
Bram Moolenaar84212822006-11-07 21:59:47 +00003120 }
3121 else
3122 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003123 if (curwin->w_next == NULL) // just checking
Bram Moolenaar84212822006-11-07 21:59:47 +00003124 break;
3125 win_enter(curwin->w_next, FALSE);
3126 }
3127 }
3128 advance = TRUE;
3129
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003130 // Only open the file if there is no file in this window yet (that can
3131 // happen when .vimrc contains ":sall").
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003132 if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL)
3133 {
3134 curwin->w_arg_idx = arg_idx;
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003135 // Edit file from arg list, if there is one. When "Quit" selected
3136 // at the ATTENTION prompt close the window.
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00003137 swap_exists_did_quit = FALSE;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003138 (void)do_ecmd(0, arg_idx < GARGCOUNT
3139 ? alist_name(&GARGLIST[arg_idx]) : NULL,
Bram Moolenaar701f7af2008-11-15 13:12:07 +00003140 NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
Bram Moolenaar4bfa6082008-07-24 17:34:23 +00003141 if (swap_exists_did_quit)
Bram Moolenaar84212822006-11-07 21:59:47 +00003142 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003143 // abort or quit selected
Bram Moolenaar84212822006-11-07 21:59:47 +00003144 if (got_int || only_one_window())
3145 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003146 // abort selected and only one window
3147 did_emsg = FALSE; // avoid hit-enter prompt
Bram Moolenaar84212822006-11-07 21:59:47 +00003148 getout(1);
3149 }
3150 win_close(curwin, TRUE);
3151 advance = FALSE;
3152 }
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003153 if (arg_idx == GARGCOUNT - 1)
3154 arg_had_last = TRUE;
3155 ++arg_idx;
3156 }
3157 ui_breakcheck();
3158 if (got_int)
3159 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003160 (void)vgetc(); // only break the file loading, not the rest
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003161 break;
3162 }
3163 }
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003164
Bram Moolenaarc75e8122019-04-21 15:55:10 +02003165 if (p_shm_save != NULL)
3166 {
Bram Moolenaar31e5c602022-04-15 13:53:33 +01003167 set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
Bram Moolenaarc75e8122019-04-21 15:55:10 +02003168 vim_free(p_shm_save);
3169 }
3170
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003171 if (parmp->window_layout == WIN_TABS)
3172 goto_tabpage(1);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003173 --autocmd_no_enter;
Bram Moolenaare66f06d2013-06-15 21:54:16 +02003174
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003175 // make the first window the current window
Bram Moolenaar74cd6242013-08-22 14:14:27 +02003176 win = firstwin;
Bram Moolenaar4033c552017-09-16 20:54:51 +02003177#if defined(FEAT_QUICKFIX)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003178 // Avoid making a preview window the current window.
Bram Moolenaar74cd6242013-08-22 14:14:27 +02003179 while (win->w_p_pvw)
3180 {
3181 win = win->w_next;
3182 if (win == NULL)
3183 {
3184 win = firstwin;
3185 break;
3186 }
Bram Moolenaare66f06d2013-06-15 21:54:16 +02003187 }
3188#endif
Bram Moolenaar74cd6242013-08-22 14:14:27 +02003189 win_enter(win, FALSE);
Bram Moolenaare66f06d2013-06-15 21:54:16 +02003190
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003191 --autocmd_no_leave;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003192 TIME_MSG("editing files in windows");
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003193 if (parmp->window_count > 1 && parmp->window_layout != WIN_TABS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003194 win_equal(curwin, FALSE, 'b'); // adjust heights
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003195}
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003196
3197/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00003198 * Execute the commands from --cmd arguments "cmds[cnt]".
3199 */
3200 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003201exe_pre_commands(mparm_T *parmp)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003202{
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003203 char_u **cmds = parmp->pre_commands;
3204 int cnt = parmp->n_pre_commands;
Bram Moolenaar58d98232005-07-23 22:25:46 +00003205 int i;
ichizok7e5fe382023-04-15 13:17:50 +01003206 ESTACK_CHECK_DECLARATION;
Bram Moolenaar58d98232005-07-23 22:25:46 +00003207
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003208 if (cnt <= 0)
3209 return;
3210
3211 curwin->w_cursor.lnum = 0; // just in case..
3212 estack_push(ETYPE_ARGS, (char_u *)_("pre-vimrc command line"), 0);
ichizok7e5fe382023-04-15 13:17:50 +01003213 ESTACK_CHECK_SETUP;
Bram Moolenaar58d98232005-07-23 22:25:46 +00003214# ifdef FEAT_EVAL
ichizok7e5fe382023-04-15 13:17:50 +01003215 current_sctx.sc_sid = SID_CMDARG;
Bram Moolenaar58d98232005-07-23 22:25:46 +00003216# endif
ichizok7e5fe382023-04-15 13:17:50 +01003217 for (i = 0; i < cnt; ++i)
3218 do_cmdline_cmd(cmds[i]);
3219 ESTACK_CHECK_NOW;
3220 estack_pop();
Bram Moolenaar58d98232005-07-23 22:25:46 +00003221# ifdef FEAT_EVAL
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003222 current_sctx.sc_sid = 0;
Bram Moolenaar58d98232005-07-23 22:25:46 +00003223# endif
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003224 TIME_MSG("--cmd commands");
Bram Moolenaar58d98232005-07-23 22:25:46 +00003225}
3226
3227/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003228 * Execute "+", "-c" and "-S" arguments.
3229 */
3230 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003231exe_commands(mparm_T *parmp)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003232{
3233 int i;
ichizok7e5fe382023-04-15 13:17:50 +01003234 ESTACK_CHECK_DECLARATION;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003235
3236 /*
3237 * We start commands on line 0, make "vim +/pat file" match a
3238 * pattern on line 1. But don't move the cursor when an autocommand
3239 * with g`" was used.
3240 */
3241 msg_scroll = TRUE;
3242 if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
3243 curwin->w_cursor.lnum = 0;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01003244 estack_push(ETYPE_ARGS, (char_u *)"command line", 0);
ichizok7e5fe382023-04-15 13:17:50 +01003245 ESTACK_CHECK_SETUP;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003246#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003247 current_sctx.sc_sid = SID_CARG;
Bram Moolenaarded5f1b2018-11-10 17:33:29 +01003248 current_sctx.sc_seq = 0;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003249#endif
3250 for (i = 0; i < parmp->n_commands; ++i)
3251 {
3252 do_cmdline_cmd(parmp->commands[i]);
3253 if (parmp->cmds_tofree[i])
3254 vim_free(parmp->commands[i]);
3255 }
ichizok7e5fe382023-04-15 13:17:50 +01003256 ESTACK_CHECK_NOW;
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01003257 estack_pop();
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003258#ifdef FEAT_EVAL
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003259 current_sctx.sc_sid = 0;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003260#endif
3261 if (curwin->w_cursor.lnum == 0)
3262 curwin->w_cursor.lnum = 1;
3263
3264 if (!exmode_active)
3265 msg_scroll = FALSE;
3266
3267#ifdef FEAT_QUICKFIX
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003268 // When started with "-q errorfile" jump to first error again.
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003269 if (parmp->edit_type == EDIT_QF)
Bram Moolenaard12f5c12006-01-25 22:10:52 +00003270 qf_jump(NULL, 0, 0, FALSE);
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003271#endif
3272 TIME_MSG("executing command arguments");
3273}
3274
3275/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00003276 * Source startup scripts.
3277 */
3278 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003279source_startup_scripts(mparm_T *parmp)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003280{
3281 int i;
3282
3283 /*
3284 * For "evim" source evim.vim first of all, so that the user can overrule
3285 * any things he doesn't like.
3286 */
3287 if (parmp->evim_mode)
3288 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003289 (void)do_source((char_u *)EVIM_FILE, FALSE, DOSO_NONE, NULL);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003290 TIME_MSG("source evim file");
3291 }
3292
3293 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003294 * If -u argument given, use only the initializations from that file and
Bram Moolenaar58d98232005-07-23 22:25:46 +00003295 * nothing else.
3296 */
3297 if (parmp->use_vimrc != NULL)
3298 {
Bram Moolenaarc4da1132017-07-15 19:39:43 +02003299 if (STRCMP(parmp->use_vimrc, "DEFAULTS") == 0)
Christian Brabandt1d3a14e2021-05-29 19:53:50 +02003300 {
3301 if (do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE, NULL)
3302 != OK)
Bram Moolenaar50809a42023-05-20 16:39:07 +01003303 emsg(_(e_failed_to_source_defaults));
Christian Brabandt1d3a14e2021-05-29 19:53:50 +02003304 }
Bram Moolenaarc4da1132017-07-15 19:39:43 +02003305 else if (STRCMP(parmp->use_vimrc, "NONE") == 0
Bram Moolenaar231334e2005-07-25 20:46:57 +00003306 || STRCMP(parmp->use_vimrc, "NORC") == 0)
Bram Moolenaar58d98232005-07-23 22:25:46 +00003307 {
3308#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003309 if (use_gvimrc == NULL) // don't load gvimrc either
Bram Moolenaar58d98232005-07-23 22:25:46 +00003310 use_gvimrc = parmp->use_vimrc;
3311#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003312 }
3313 else
3314 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003315 if (do_source(parmp->use_vimrc, FALSE, DOSO_NONE, NULL) != OK)
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00003316 semsg(_(e_cannot_read_from_str_2), parmp->use_vimrc);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003317 }
3318 }
3319 else if (!silent_mode)
3320 {
3321#ifdef AMIGA
3322 struct Process *proc = (struct Process *)FindTask(0L);
3323 APTR save_winptr = proc->pr_WindowPtr;
3324
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003325 // Avoid a requester here for a volume that doesn't exist.
Bram Moolenaar58d98232005-07-23 22:25:46 +00003326 proc->pr_WindowPtr = (APTR)-1L;
3327#endif
3328
3329 /*
3330 * Get system wide defaults, if the file name is defined.
3331 */
3332#ifdef SYS_VIMRC_FILE
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003333 (void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, DOSO_NONE, NULL);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003334#endif
Bram Moolenaar1056d982006-03-09 22:37:52 +00003335#ifdef MACOS_X
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003336 (void)do_source((char_u *)"$VIMRUNTIME/macmap.vim", FALSE,
3337 DOSO_NONE, NULL);
Bram Moolenaar1056d982006-03-09 22:37:52 +00003338#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003339
3340 /*
3341 * Try to read initialization commands from the following places:
3342 * - environment variable VIMINIT
3343 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise)
3344 * - second user vimrc file ($VIM/.vimrc for Dos)
3345 * - environment variable EXINIT
3346 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise)
3347 * - second user exrc file ($VIM/.exrc for Dos)
3348 * The first that exists is used, the rest is ignored.
3349 */
3350 if (process_env((char_u *)"VIMINIT", TRUE) != OK)
3351 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003352 if (do_source((char_u *)USR_VIMRC_FILE, TRUE,
3353 DOSO_VIMRC, NULL) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003354#ifdef USR_VIMRC_FILE2
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003355 && do_source((char_u *)USR_VIMRC_FILE2, TRUE,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003356 DOSO_VIMRC, NULL) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003357#endif
Luca Saccarolac9df1fb2024-04-14 22:53:22 +02003358#ifdef XDG_VIMRC_FILE
3359 && do_source((char_u *)XDG_VIMRC_FILE, TRUE,
3360 DOSO_VIMRC, NULL) == FAIL
3361#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003362#ifdef USR_VIMRC_FILE3
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003363 && do_source((char_u *)USR_VIMRC_FILE3, TRUE,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003364 DOSO_VIMRC, NULL) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003365#endif
Bram Moolenaar22971aa2013-06-12 20:35:58 +02003366#ifdef USR_VIMRC_FILE4
3367 && do_source((char_u *)USR_VIMRC_FILE4, TRUE,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003368 DOSO_VIMRC, NULL) == FAIL
Bram Moolenaar22971aa2013-06-12 20:35:58 +02003369#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +00003370 && process_env((char_u *)"EXINIT", FALSE) == FAIL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003371 && do_source((char_u *)USR_EXRC_FILE, FALSE,
3372 DOSO_NONE, NULL) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003373#ifdef USR_EXRC_FILE2
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003374 && do_source((char_u *)USR_EXRC_FILE2, FALSE,
3375 DOSO_NONE, NULL) == FAIL
Bram Moolenaar58d98232005-07-23 22:25:46 +00003376#endif
Bram Moolenaarb9a46fe2016-07-29 18:13:42 +02003377 && !has_dash_c_arg)
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003378 {
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003379 // When no .vimrc file was found: source defaults.vim.
Christian Brabandt1d3a14e2021-05-29 19:53:50 +02003380 if (do_source((char_u *)VIM_DEFAULTS_FILE, FALSE, DOSO_NONE,
3381 NULL) == FAIL)
Bram Moolenaar50809a42023-05-20 16:39:07 +01003382 emsg(_(e_failed_to_source_defaults));
Bram Moolenaar58d98232005-07-23 22:25:46 +00003383 }
3384 }
3385
3386 /*
3387 * Read initialization commands from ".vimrc" or ".exrc" in current
3388 * directory. This is only done if the 'exrc' option is set.
3389 * Because of security reasons we disallow shell and write commands
Bram Moolenaar8c08b5b2016-07-28 22:24:15 +02003390 * now, except for Unix if the file is owned by the user or 'secure'
Bram Moolenaar58d98232005-07-23 22:25:46 +00003391 * option has been reset in environment of global ".exrc" or ".vimrc".
3392 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or
3393 * SYS_VIMRC_FILE.
3394 */
3395 if (p_exrc)
3396 {
3397#if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003398 // If ".vimrc" file is not owned by user, set 'secure' mode.
Bram Moolenaar58d98232005-07-23 22:25:46 +00003399 if (!file_owned(VIMRC_FILE))
3400#endif
3401 secure = p_secure;
3402
3403 i = FAIL;
3404 if (fullpathcmp((char_u *)USR_VIMRC_FILE,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003405 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003406#ifdef USR_VIMRC_FILE2
3407 && fullpathcmp((char_u *)USR_VIMRC_FILE2,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003408 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003409#endif
3410#ifdef USR_VIMRC_FILE3
3411 && fullpathcmp((char_u *)USR_VIMRC_FILE3,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003412 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003413#endif
3414#ifdef SYS_VIMRC_FILE
3415 && fullpathcmp((char_u *)SYS_VIMRC_FILE,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003416 (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003417#endif
3418 )
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003419 i = do_source((char_u *)VIMRC_FILE, TRUE, DOSO_VIMRC, NULL);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003420
3421 if (i == FAIL)
3422 {
3423#if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003424 // if ".exrc" is not owned by user set 'secure' mode
Bram Moolenaar58d98232005-07-23 22:25:46 +00003425 if (!file_owned(EXRC_FILE))
3426 secure = p_secure;
3427 else
3428 secure = 0;
3429#endif
3430 if ( fullpathcmp((char_u *)USR_EXRC_FILE,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003431 (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003432#ifdef USR_EXRC_FILE2
3433 && fullpathcmp((char_u *)USR_EXRC_FILE2,
Bram Moolenaar99499b12019-05-23 21:35:48 +02003434 (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME
Bram Moolenaar58d98232005-07-23 22:25:46 +00003435#endif
3436 )
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003437 (void)do_source((char_u *)EXRC_FILE, FALSE,
3438 DOSO_NONE, NULL);
Bram Moolenaar58d98232005-07-23 22:25:46 +00003439 }
3440 }
3441 if (secure == 2)
3442 need_wait_return = TRUE;
3443 secure = 0;
3444#ifdef AMIGA
3445 proc->pr_WindowPtr = save_winptr;
3446#endif
3447 }
3448 TIME_MSG("sourcing vimrc file(s)");
3449}
3450
3451/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003452 * Setup to start using the GUI. Exit with an error when not available.
3453 */
3454 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003455main_start_gui(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003456{
3457#ifdef FEAT_GUI
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003458 gui.starting = TRUE; // start GUI a bit later
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003459#else
Bram Moolenaare29a27f2021-07-20 21:07:36 +02003460 mch_errmsg(_(e_gui_cannot_be_used_not_enabled_at_compile_time));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003461 mch_errmsg("\n");
3462 mch_exit(2);
3463#endif
3464}
3465
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003466#endif // NO_VIM_MAIN
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003467
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003468/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003469 * Get an environment variable and execute it as Ex commands.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003470 * Returns FAIL if the environment variable was not executed, OK otherwise.
3471 */
3472 int
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003473process_env(
3474 char_u *env,
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003475 int is_viminit) // when TRUE, called for VIMINIT
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003476{
3477 char_u *initstr;
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02003478 sctx_T save_current_sctx;
ichizok7e5fe382023-04-15 13:17:50 +01003479 ESTACK_CHECK_DECLARATION;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003480
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003481 if ((initstr = mch_getenv(env)) == NULL || *initstr == NUL)
3482 return FAIL;
3483
3484 if (is_viminit)
3485 vimrc_found(NULL, NULL);
3486 estack_push(ETYPE_ENV, env, 0);
ichizok7e5fe382023-04-15 13:17:50 +01003487 ESTACK_CHECK_SETUP;
3488 save_current_sctx = current_sctx;
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003489 current_sctx.sc_version = 1;
Bram Moolenaar9b8d6222020-12-28 18:26:00 +01003490#ifdef FEAT_EVAL
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003491 current_sctx.sc_sid = SID_ENV;
3492 current_sctx.sc_seq = 0;
3493 current_sctx.sc_lnum = 0;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003494#endif
Bram Moolenaar9b8d6222020-12-28 18:26:00 +01003495
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003496 do_cmdline_cmd(initstr);
Bram Moolenaar1a47ae32019-12-29 23:04:25 +01003497
ichizok7e5fe382023-04-15 13:17:50 +01003498 ESTACK_CHECK_NOW;
3499 estack_pop();
Yegappan Lakshmanane8575982023-01-14 12:32:28 +00003500 current_sctx = save_current_sctx;
3501 return OK;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003502}
3503
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003504#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003505/*
3506 * Return TRUE if we are certain the user owns the file "fname".
3507 * Used for ".vimrc" and ".exrc".
3508 * Use both stat() and lstat() for extra security.
3509 */
3510 static int
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003511file_owned(char *fname)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003512{
Bram Moolenaar8767f522016-07-01 17:17:39 +02003513 stat_T s;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003514# ifdef UNIX
3515 uid_t uid = getuid();
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003516# else // VMS
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003517 uid_t uid = ((getgid() << 16) | getuid());
3518# endif
3519
3520 return !(mch_stat(fname, &s) != 0 || s.st_uid != uid
3521# ifdef HAVE_LSTAT
3522 || mch_lstat(fname, &s) != 0 || s.st_uid != uid
3523# endif
3524 );
3525}
3526#endif
3527
3528/*
3529 * Give an error message main_errors["n"] and exit.
3530 */
3531 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003532mainerr(
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003533 int n, // one of the ME_ defines
3534 char_u *str) // extra argument or NULL
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003535{
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003536#if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003537 reset_signals(); // kill us with CTRL-C here, if you like
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003538#endif
3539
Bram Moolenaar0b75f7c2019-05-08 22:28:46 +02003540 // If this is a Windows GUI executable, show an error dialog box.
3541#ifdef VIMDLL
3542 gui.in_use = mch_is_gui_executable();
3543#endif
3544#ifdef FEAT_GUI_MSWIN
3545 gui.starting = FALSE; // Needed to show as error.
3546#endif
3547
Bram Moolenaar35fb6fb2018-06-23 16:12:21 +02003548 init_longVersion();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003549 mch_errmsg(longVersion);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003550 mch_errmsg("\n");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003551 mch_errmsg(_(main_errors[n]));
3552 if (str != NULL)
3553 {
3554 mch_errmsg(": \"");
3555 mch_errmsg((char *)str);
3556 mch_errmsg("\"");
3557 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00003558 mch_errmsg(_("\nMore info with: \"vim -h\"\n"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003559
3560 mch_exit(1);
3561}
3562
3563 void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003564mainerr_arg_missing(char_u *str)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003565{
3566 mainerr(ME_ARG_MISSING, str);
3567}
3568
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003569#ifndef NO_VIM_MAIN
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003570/*
3571 * print a message with three spaces prepended and '\n' appended.
3572 */
3573 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003574main_msg(char *s)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003575{
3576 mch_msg(" ");
3577 mch_msg(s);
3578 mch_msg("\n");
3579}
3580
3581/*
3582 * Print messages for "vim -h" or "vim --help" and exit.
3583 */
3584 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003585usage(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003586{
3587 int i;
3588 static char *(use[]) =
3589 {
3590 N_("[file ..] edit specified file(s)"),
3591 N_("- read text from stdin"),
3592 N_("-t tag edit file where tag is defined"),
3593#ifdef FEAT_QUICKFIX
3594 N_("-q [errorfile] edit file with first error")
3595#endif
3596 };
3597
Bram Moolenaara06ecab2016-07-16 14:47:36 +02003598#if defined(UNIX) || defined(VMS)
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003599 reset_signals(); // kill us with CTRL-C here, if you like
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003600#endif
3601
Bram Moolenaar35fb6fb2018-06-23 16:12:21 +02003602 init_longVersion();
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003603 mch_msg(longVersion);
Bram Moolenaar32aaf5a2018-06-21 21:38:33 +02003604 mch_msg(_("\n\nUsage:"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003605 for (i = 0; ; ++i)
3606 {
3607 mch_msg(_(" vim [arguments] "));
3608 mch_msg(_(use[i]));
K.Takataeeec2542021-06-02 13:28:16 +02003609 if (i == ARRAY_LENGTH(use) - 1)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003610 break;
3611 mch_msg(_("\n or:"));
3612 }
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003613#ifdef VMS
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003614 mch_msg(_("\nWhere case is ignored prepend / to make flag upper case"));
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003615#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003616
3617 mch_msg(_("\n\nArguments:\n"));
3618 main_msg(_("--\t\t\tOnly file names after this"));
Bram Moolenaar53076832015-12-31 19:53:21 +01003619#ifdef EXPAND_FILENAMES
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003620 main_msg(_("--literal\t\tDon't expand wildcards"));
3621#endif
3622#ifdef FEAT_OLE
3623 main_msg(_("-register\t\tRegister this gvim for OLE"));
3624 main_msg(_("-unregister\t\tUnregister gvim for OLE"));
3625#endif
3626#ifdef FEAT_GUI
3627 main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")"));
3628 main_msg(_("-f or --nofork\tForeground: Don't fork when starting GUI"));
3629#endif
3630 main_msg(_("-v\t\t\tVi mode (like \"vi\")"));
3631 main_msg(_("-e\t\t\tEx mode (like \"ex\")"));
Bram Moolenaarf99bc6d2012-03-28 17:10:31 +02003632 main_msg(_("-E\t\t\tImproved Ex mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003633 main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")"));
3634#ifdef FEAT_DIFF
3635 main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")"));
3636#endif
3637 main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)"));
3638 main_msg(_("-R\t\t\tReadonly mode (like \"view\")"));
3639 main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")"));
3640 main_msg(_("-m\t\t\tModifications (writing files) not allowed"));
3641 main_msg(_("-M\t\t\tModifications in text not allowed"));
3642 main_msg(_("-b\t\t\tBinary mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003643 main_msg(_("-l\t\t\tLisp mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003644 main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'"));
3645 main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'"));
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003646 main_msg(_("-V[N][fname]\t\tBe verbose [level N] [log messages to fname]"));
3647#ifdef FEAT_EVAL
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003648 main_msg(_("-D\t\t\tDebugging mode"));
Bram Moolenaar8cfdc0d2007-05-06 14:12:36 +00003649#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003650 main_msg(_("-n\t\t\tNo swap file, use memory only"));
3651 main_msg(_("-r\t\t\tList swap files and exit"));
3652 main_msg(_("-r (with file name)\tRecover crashed session"));
3653 main_msg(_("-L\t\t\tSame as -r"));
3654#ifdef AMIGA
3655 main_msg(_("-f\t\t\tDon't use newcli to open window"));
3656 main_msg(_("-dev <device>\t\tUse <device> for I/O"));
3657#endif
3658#ifdef FEAT_ARABIC
Bram Moolenaar1d4754f2018-06-19 17:49:24 +02003659 main_msg(_("-A\t\t\tStart in Arabic mode"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003660#endif
3661#ifdef FEAT_RIGHTLEFT
3662 main_msg(_("-H\t\t\tStart in Hebrew mode"));
3663#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003664 main_msg(_("-T <terminal>\tSet terminal type to <terminal>"));
Bram Moolenaar49c39ff2016-02-25 21:21:52 +01003665 main_msg(_("--not-a-term\t\tSkip warning for input/output not being a terminal"));
Bram Moolenaar2d12c252022-06-13 21:42:45 +01003666#ifdef FEAT_GUI
3667 main_msg(_("--gui-dialog-file {fname} For testing: write dialog text"));
3668#endif
Bram Moolenaar2cab0e12016-11-24 15:09:07 +01003669 main_msg(_("--ttyfail\t\tExit if input or output is not a terminal"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003670 main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"));
3671#ifdef FEAT_GUI
3672 main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"));
3673#endif
3674 main_msg(_("--noplugin\t\tDon't load plugin scripts"));
Bram Moolenaar997fb4b2006-02-17 21:53:23 +00003675 main_msg(_("-p[N]\t\tOpen N tab pages (default: one for each file)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003676 main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)"));
3677 main_msg(_("-O[N]\t\tLike -o but split vertically"));
3678 main_msg(_("+\t\t\tStart at end of file"));
3679 main_msg(_("+<lnum>\t\tStart at line <lnum>"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003680 main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003681 main_msg(_("-c <command>\t\tExecute <command> after loading the first file"));
3682 main_msg(_("-S <session>\t\tSource file <session> after loading the first file"));
3683 main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>"));
3684 main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>"));
3685 main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>"));
3686#ifdef FEAT_CRYPT
3687 main_msg(_("-x\t\t\tEdit encrypted files"));
3688#endif
3689#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
3690# if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)
Bram Moolenaar86181df2020-05-11 23:14:04 +02003691 main_msg(_("-display <display>\tConnect Vim to this particular X-server"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003692# endif
3693 main_msg(_("-X\t\t\tDo not connect to X server"));
3694#endif
Foxe Chenb90c2392025-06-27 21:10:35 +02003695#if defined(FEAT_WAYLAND)
Hirohito Higashi73b96502025-06-28 18:18:21 +02003696 main_msg(_("-Y\t\t\tDo not connect to Wayland compositor"));
Foxe Chenb90c2392025-06-27 21:10:35 +02003697#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003698#ifdef FEAT_CLIENTSERVER
3699 main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible"));
3700 main_msg(_("--remote-silent <files> Same, don't complain if there is no server"));
3701 main_msg(_("--remote-wait <files> As --remote but wait for files to have been edited"));
3702 main_msg(_("--remote-wait-silent <files> Same, don't complain if there is no server"));
Bram Moolenaar82ad3242008-01-11 19:26:36 +00003703 main_msg(_("--remote-tab[-wait][-silent] <files> As --remote but use tab page per file"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003704 main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit"));
3705 main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"));
3706 main_msg(_("--serverlist\t\tList available Vim server names and exit"));
3707 main_msg(_("--servername <name>\tSend to/become the Vim server <name>"));
3708#endif
Bram Moolenaaref94eec2009-11-11 13:22:11 +00003709#ifdef STARTUPTIME
Bram Moolenaar34ef52d2009-11-17 11:31:25 +00003710 main_msg(_("--startuptime <file>\tWrite startup timing messages to <file>"));
Bram Moolenaaref94eec2009-11-11 13:22:11 +00003711#endif
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +01003712#ifdef FEAT_JOB_CHANNEL
K.Takata0fd7be72022-11-09 16:29:24 +00003713 main_msg(_("--log <file>\t\tStart logging to <file> early"));
Bram Moolenaarc9a9a0a2022-04-12 15:09:23 +01003714#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003715#ifdef FEAT_VIMINFO
3716 main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo"));
3717#endif
Bram Moolenaarc4da1132017-07-15 19:39:43 +02003718 main_msg(_("--clean\t\t'nocompatible', Vim defaults, no plugins, no viminfo"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003719 main_msg(_("-h or --help\tPrint Help (this message) and exit"));
3720 main_msg(_("--version\t\tPrint version information and exit"));
3721
3722#ifdef FEAT_GUI_X11
3723# ifdef FEAT_GUI_MOTIF
3724 mch_msg(_("\nArguments recognised by gvim (Motif version):\n"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003725# endif
Bram Moolenaar86181df2020-05-11 23:14:04 +02003726 main_msg(_("-display <display>\tRun Vim on <display>"));
Bram Moolenaar9e6ba8c2020-05-12 22:21:26 +02003727 main_msg(_("-iconic\t\tStart Vim iconified"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003728 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
3729 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
3730 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
3731 main_msg(_("-boldfont <font>\tUse <font> for bold text"));
3732 main_msg(_("-italicfont <font>\tUse <font> for italic text"));
3733 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
3734 main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)"));
3735 main_msg(_("-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003736 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
3737 main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)"));
3738 main_msg(_("-xrm <resource>\tSet the specified resource"));
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003739#endif // FEAT_GUI_X11
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003740#ifdef FEAT_GUI_GTK
3741 mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
Bram Moolenaarf8c52e82021-03-17 12:27:23 +01003742 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
3743 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003744 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
3745 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
Bram Moolenaarf8c52e82021-03-17 12:27:23 +01003746 main_msg(_("-iconic\t\tStart Vim iconified"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003747 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
Bram Moolenaar86181df2020-05-11 23:14:04 +02003748 main_msg(_("-display <display>\tRun Vim on <display> (also: --display)"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003749 main_msg(_("--role <role>\tSet a unique role to identify the main window"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003750 main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget"));
Bram Moolenaarf99bc6d2012-03-28 17:10:31 +02003751 main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003752#endif
Bram Moolenaar4f974752019-02-17 17:44:42 +01003753#ifdef FEAT_GUI_MSWIN
Bram Moolenaarafde13b2019-04-28 19:46:49 +02003754# ifdef VIMDLL
3755 if (gui.starting)
3756# endif
3757 {
3758 main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
3759 main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget"));
3760 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003761#endif
3762
3763#ifdef FEAT_GUI_GNOME
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003764 // Gnome gives extra messages for --help if we continue, but not for -h.
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003765 if (gui.starting)
Bram Moolenaarf4120a82011-12-08 15:57:59 +01003766 {
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003767 mch_msg("\n");
Bram Moolenaarf4120a82011-12-08 15:57:59 +01003768 gui.dofork = FALSE;
3769 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003770 else
3771#endif
3772 mch_exit(0);
3773}
3774
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003775/*
3776 * Check the result of the ATTENTION dialog:
3777 * When "Quit" selected, exit Vim.
3778 * When "Recover" selected, recover the file.
3779 */
3780 static void
Bram Moolenaar52ea13d2016-01-30 18:51:09 +01003781check_swap_exists_action(void)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003782{
3783 if (swap_exists_action == SEA_QUIT)
3784 getout(1);
3785 handle_swap_exists(NULL);
3786}
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003787
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003788#endif // NO_VIM_MAIN
Bram Moolenaarb05b10a2011-03-22 18:10:45 +01003789
Bram Moolenaar595297d2017-03-04 19:11:12 +01003790#if !defined(NO_VIM_MAIN) && defined(FEAT_EVAL)
Bram Moolenaar08cab962017-03-04 14:37:18 +01003791 static void
3792set_progpath(char_u *argv0)
3793{
3794 char_u *val = argv0;
Bram Moolenaar08cab962017-03-04 14:37:18 +01003795
Bram Moolenaar4f974752019-02-17 17:44:42 +01003796# ifdef MSWIN
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003797 // A relative path containing a "/" will become invalid when using ":cd",
3798 // turn it into a full path.
3799 // On MS-Windows "vim" should be expanded to "vim.exe", thus always do
3800 // this.
Bram Moolenaar066029e2017-03-05 15:19:32 +01003801 char_u *path = NULL;
3802
3803 if (mch_can_exe(argv0, &path, FALSE) && path != NULL)
3804 val = path;
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003805# else
3806 char_u buf[MAXPATHL + 1];
3807# ifdef PROC_EXE_LINK
3808 char linkbuf[MAXPATHL + 1];
3809 ssize_t len;
Bram Moolenaar066029e2017-03-05 15:19:32 +01003810
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003811 len = readlink(PROC_EXE_LINK, linkbuf, MAXPATHL);
3812 if (len > 0)
Bram Moolenaar43663192017-03-05 14:29:12 +01003813 {
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003814 linkbuf[len] = NUL;
3815 val = (char_u *)linkbuf;
Bram Moolenaar43663192017-03-05 14:29:12 +01003816 }
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003817# endif
Bram Moolenaarbc906e42017-08-17 17:21:05 +02003818
3819 if (!mch_isFullName(val))
3820 {
3821 if (gettail(val) != val
3822 && vim_FullName(val, buf, MAXPATHL, TRUE) != FAIL)
3823 val = buf;
3824 }
Bram Moolenaar066029e2017-03-05 15:19:32 +01003825# endif
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003826
Bram Moolenaar08cab962017-03-04 14:37:18 +01003827 set_vim_var_string(VV_PROGPATH, val, -1);
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01003828
Bram Moolenaar4f974752019-02-17 17:44:42 +01003829# ifdef MSWIN
Bram Moolenaar43663192017-03-05 14:29:12 +01003830 vim_free(path);
Bram Moolenaar066029e2017-03-05 15:19:32 +01003831# endif
Bram Moolenaar08cab962017-03-04 14:37:18 +01003832}
3833
Bram Moolenaar4ba37b52019-12-04 21:57:43 +01003834#endif // NO_VIM_MAIN