blob: 1beaca47f95bcc413794d28771d23c6dd45c6591 [file] [log] [blame]
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10#if defined(MSDOS) || defined(WIN32) || defined(_WIN64)
11# include <io.h> /* for close() and dup() */
12#endif
13
14#define EXTERN
15#include "vim.h"
16
17#ifdef SPAWNO
Bram Moolenaar0e21a3f2005-04-17 20:28:32 +000018# include <spawno.h> /* special MS-DOS swapping library */
Bram Moolenaarb4210b32004-06-13 14:51:16 +000019#endif
20
21#ifdef HAVE_FCNTL_H
22# include <fcntl.h>
23#endif
24
25#ifdef __CYGWIN__
26# ifndef WIN32
27# include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() */
28# endif
29# include <limits.h>
30#endif
31
Bram Moolenaarc013cb62005-07-24 21:18:31 +000032/* Maximum number of commands from + or -c arguments. */
33#define MAX_ARG_CMDS 10
34
Bram Moolenaar58d98232005-07-23 22:25:46 +000035/* Struct for various parameters passed between main() and other functions. */
36typedef struct
37{
Bram Moolenaarc013cb62005-07-24 21:18:31 +000038 int argc;
39 char **argv;
40
41 int evim_mode; /* started as "evim" */
42 int bin_mode; /* -b argument used */
43 char_u *use_vimrc; /* vimrc from -u argument */
44
45 int n_commands; /* no. of commands from + or -c */
46 char_u *commands[MAX_ARG_CMDS]; /* commands from + or -c arg. */
47 char_u cmds_tofree[MAX_ARG_CMDS]; /* commands that need free() */
48 int n_pre_commands; /* no. of commands from --cmd */
49 char_u *pre_commands[MAX_ARG_CMDS]; /* commands from --cmd argument */
50
51 int edit_type; /* type of editing to do */
52 char_u *tagname; /* tag from -t argument */
53#ifdef FEAT_QUICKFIX
54 char_u *use_ef; /* 'errorfile' from -q argument */
55#endif
56
57 int want_full_screen;
58 int stdout_isatty; /* is stdout a terminal? */
59 char_u *term; /* specified terminal name */
60#ifdef FEAT_CRYPT
61 int ask_for_key; /* -x argument */
62#endif
63 int no_swap_file; /* "-n" argument used */
64#ifdef FEAT_EVAL
65 int use_debug_break_level;
66#endif
67#ifdef FEAT_WINDOWS
68 int window_count; /* number of windows to use */
69 int vert_windows; /* "-O" used instead of "-o" */
70#endif
71
72#ifdef FEAT_CLIENTSERVER
Bram Moolenaar58d98232005-07-23 22:25:46 +000073 int serverArg; /* TRUE when argument for a server */
74 char_u *serverName_arg; /* cmdline arg for server name */
Bram Moolenaarc013cb62005-07-24 21:18:31 +000075 char_u *serverStr; /* remote server command */
76 char_u *serverStrEnc; /* encoding of serverStr */
77 char_u *servername; /* allocated name for our server */
78#endif
79#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
80 int literal; /* don't expand file names */
81#endif
82#ifdef MSWIN
83 int full_path; /* file name argument was full path */
84#endif
85#ifdef FEAT_DIFF
86 int diff_mode; /* start with 'diff' set */
87#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +000088} mparm_T;
89
Bram Moolenaarc013cb62005-07-24 21:18:31 +000090/* Values for edit_type. */
91#define EDIT_NONE 0 /* no edit type yet */
92#define EDIT_FILE 1 /* file name argument[s] given, use argument list */
93#define EDIT_STDIN 2 /* read file from stdin */
94#define EDIT_TAG 3 /* tag name argument given, use tagname */
95#define EDIT_QF 4 /* start in quickfix mode */
96
Bram Moolenaarb4210b32004-06-13 14:51:16 +000097#if defined(UNIX) || defined(VMS)
98static int file_owned __ARGS((char *fname));
99#endif
100static void mainerr __ARGS((int, char_u *));
101static void main_msg __ARGS((char *s));
102static void usage __ARGS((void));
103static int get_number_arg __ARGS((char_u *p, int *idx, int def));
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000104#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
105static void init_locale __ARGS((void));
106#endif
107static void parse_command_name __ARGS((mparm_T *parmp));
108static void early_arg_scan __ARGS((mparm_T *parmp));
109static void command_line_scan __ARGS((mparm_T *parmp));
110static void check_tty __ARGS((mparm_T *parmp));
111static void read_stdin __ARGS((void));
112static void create_windows __ARGS((mparm_T *parmp));
113#ifdef FEAT_WINDOWS
114static void edit_buffers __ARGS((mparm_T *parmp));
115#endif
116static void exe_pre_commands __ARGS((mparm_T *parmp));
117static void exe_commands __ARGS((mparm_T *parmp));
Bram Moolenaar58d98232005-07-23 22:25:46 +0000118static void source_startup_scripts __ARGS((mparm_T *parmp));
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000119static void main_start_gui __ARGS((void));
120#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
121static void check_swap_exists_action __ARGS((void));
122#endif
123#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000124static void exec_on_server __ARGS((mparm_T *parmp));
125static void prepare_server __ARGS((mparm_T *parmp));
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000126static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));
127static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));
128#endif
129
130
131#ifdef STARTUPTIME
132static FILE *time_fd = NULL;
133#endif
134
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000135/*
136 * Different types of error messages.
137 */
138static char *(main_errors[]) =
139{
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000140 N_("Unknown option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000141#define ME_UNKNOWN_OPTION 0
142 N_("Too many edit arguments"),
143#define ME_TOO_MANY_ARGS 1
144 N_("Argument missing after"),
145#define ME_ARG_MISSING 2
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000146 N_("Garbage after option argument"),
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000147#define ME_GARBAGE 3
148 N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),
149#define ME_EXTRA_CMD 4
150 N_("Invalid argument for"),
151#define ME_INVALID_ARG 5
152};
153
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000154#ifndef PROTO /* don't want a prototype for main() */
155 int
156# ifdef VIMDLL
157_export
158# endif
159# ifdef FEAT_GUI_MSWIN
160# ifdef __BORLANDC__
161_cdecl
162# endif
163VimMain
164# else
165main
166# endif
167(argc, argv)
168 int argc;
169 char **argv;
170{
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000171 char_u *fname = NULL; /* file name from command line */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000172 mparm_T params; /* various parameters passed between
173 * main() and other functions. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000174
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000175 /*
176 * Do any system-specific initialisations. These can NOT use IObuff or
177 * NameBuff. Thus emsg2() cannot be called!
178 */
179 mch_early_init();
180
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000181 /* Many variables are in "params" so that we can pass them to invoked
182 * functions without a lot of arguments. "argc" and "argv" are also
183 * copied, so that they can be changed. */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000184 vim_memset(&params, 0, sizeof(params));
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000185 params.argc = argc;
186 params.argv = argv;
187 params.want_full_screen = TRUE;
188#ifdef FEAT_EVAL
189 params.use_debug_break_level = -1;
190#endif
191#ifdef FEAT_WINDOWS
192 params.window_count = -1;
193 params.vert_windows = MAYBE;
194#endif
Bram Moolenaar58d98232005-07-23 22:25:46 +0000195
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000196#ifdef FEAT_TCL
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000197 vim_tcl_init(params.argv[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000198#endif
199
200#ifdef MEM_PROFILE
201 atexit(vim_mem_profile_dump);
202#endif
203
204#ifdef STARTUPTIME
205 time_fd = fopen(STARTUPTIME, "a");
206 TIME_MSG("--- VIM STARTING ---");
207#endif
208
209#ifdef __EMX__
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000210 _wildcard(&params.argc, &params.argv);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000211#endif
212
213#ifdef FEAT_MBYTE
214 (void)mb_init(); /* init mb_bytelen_tab[] to ones */
215#endif
Bram Moolenaardcaf10e2005-01-21 11:55:25 +0000216#ifdef FEAT_EVAL
217 eval_init(); /* init global variables */
218#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000219
220#ifdef __QNXNTO__
221 qnx_init(); /* PhAttach() for clipboard, (and gui) */
222#endif
223
224#ifdef MAC_OS_CLASSIC
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000225 /* Prepare for possibly starting GUI sometime */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000226 /* Macintosh needs this before any memory is allocated. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000227 gui_prepare(&params.argc, params.argv);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000228 TIME_MSG("GUI prepared");
229#endif
230
231 /* Init the table of Normal mode commands. */
232 init_normal_cmds();
233
234#if defined(HAVE_DATE_TIME) && defined(VMS) && defined(VAXC)
Bram Moolenaar58d98232005-07-23 22:25:46 +0000235 make_version(); /* Construct the long version string. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000236#endif
237
238 /*
239 * Allocate space for the generic buffers (needed for set_init_1() and
240 * EMSG2()).
241 */
242 if ((IObuff = alloc(IOSIZE)) == NULL
243 || (NameBuff = alloc(MAXPATHL)) == NULL)
244 mch_exit(0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000245 TIME_MSG("Allocated generic buffers");
246
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000247#ifdef NBDEBUG
248 /* Wait a moment for debugging NetBeans. Must be after allocating
249 * NameBuff. */
250 nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
251 nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000252 TIME_MSG("NetBeans debug wait");
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000253#endif
254
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000255#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
256 /*
257 * Setup to use the current locale (for ctype() and many other things).
258 * NOTE: Translated messages with encodings other than latin1 will not
259 * work until set_init_1() has been called!
260 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000261 init_locale();
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000262 TIME_MSG("locale set");
263#endif
264
265#ifdef FEAT_GUI
266 gui.dofork = TRUE; /* default is to use fork() */
267#endif
268
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000269 /*
Bram Moolenaar58d98232005-07-23 22:25:46 +0000270 * Do a first scan of the arguments in "argv[]":
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000271 * -display or --display
Bram Moolenaar58d98232005-07-23 22:25:46 +0000272 * --server...
273 * --socketid
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000274 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000275 early_arg_scan(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000276
277#ifdef FEAT_SUN_WORKSHOP
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000278 findYourself(params.argv[0]);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000279#endif
280#if defined(FEAT_GUI) && !defined(MAC_OS_CLASSIC)
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000281 /* Prepare for possibly starting GUI sometime */
282 gui_prepare(&params.argc, params.argv);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000283 TIME_MSG("GUI prepared");
284#endif
285
286#ifdef FEAT_CLIPBOARD
287 clip_init(FALSE); /* Initialise clipboard stuff */
288 TIME_MSG("clipboard setup");
289#endif
290
291 /*
292 * Check if we have an interactive window.
293 * On the Amiga: If there is no window, we open one with a newcli command
294 * (needed for :! to * work). mch_check_win() will also handle the -d or
295 * -dev argument.
296 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000297 params.stdout_isatty = (mch_check_win(params.argc, params.argv) != FAIL);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000298 TIME_MSG("window checked");
299
300 /*
301 * Allocate the first window and buffer. Can't do much without it.
302 */
303 win_alloc_first();
304
305 init_yank(); /* init yank buffers */
306
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000307 alist_init(&global_alist); /* Init the argument list to empty. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000308
309 /*
310 * Set the default values for the options.
311 * NOTE: Non-latin1 translated messages are working only after this,
312 * because this is where "has_mbyte" will be set, which is used by
313 * msg_outtrans_len_attr().
314 * First find out the home directory, needed to expand "~" in options.
315 */
316 init_homedir(); /* find real value of $HOME */
317 set_init_1();
318 TIME_MSG("inits 1");
319
320#ifdef FEAT_EVAL
321 set_lang_var(); /* set v:lang and v:ctype */
322#endif
323
324#ifdef FEAT_CLIENTSERVER
325 /*
326 * Do the client-server stuff, unless "--servername ''" was used.
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000327 * This may exit Vim if the command was sent to the server.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000328 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000329 exec_on_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000330#endif
331
332 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000333 * Figure out the way to work from the command name argv[0].
334 * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000335 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000336 parse_command_name(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000337
338 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000339 * Process the command line arguments. File names are put in the global
340 * argument list "global_alist".
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000341 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000342 command_line_scan(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000343 TIME_MSG("parsing arguments");
344
345 /*
346 * On some systems, when we compile with the GUI, we always use it. On Mac
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000347 * there is no terminal version, and on Windows we can't fork one off with
348 * :gui.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000349 */
350#ifdef ALWAYS_USE_GUI
351 gui.starting = TRUE;
352#else
Bram Moolenaar843ee412004-06-30 16:16:41 +0000353# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000354 /*
355 * Check if the GUI can be started. Reset gui.starting if not.
356 * Don't know about other systems, stay on the safe side and don't check.
357 */
358 if (gui.starting && gui_init_check() == FAIL)
359 {
360 gui.starting = FALSE;
361
362 /* When running "evim" or "gvim -y" we need the menus, exit if we
363 * don't have them. */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000364 if (params.evim_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000365 mch_exit(1);
366 }
367# endif
368#endif
369
370 /* "-b" argument used. Check before expanding file names, because for
371 * Win32 this makes us edit a shortcut file itself, instead of the file it
372 * links to. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000373 if (params.bin_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000374 {
375 set_options_bin(curbuf->b_p_bin, 1, 0);
376 curbuf->b_p_bin = 1; /* binary file I/O */
377 }
378
379 if (GARGCOUNT > 0)
380 {
381#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
382 /*
383 * Expand wildcards in file names.
384 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000385 if (!params.literal)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000386 {
387 /* Temporarily add '(' and ')' to 'isfname'. These are valid
388 * filename characters but are excluded from 'isfname' to make
389 * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
390 do_cmdline_cmd((char_u *)":set isf+=(,)");
Bram Moolenaar86b68352004-12-27 21:59:20 +0000391 alist_expand(NULL, 0);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000392 do_cmdline_cmd((char_u *)":set isf&");
393 }
394#endif
395 fname = alist_name(&GARGLIST[0]);
396 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000397
398#if defined(WIN32) && defined(FEAT_MBYTE)
399 {
400 extern void set_alist_count(void);
401
402 /* Remember the number of entries in the argument list. If it changes
403 * we don't react on setting 'encoding'. */
404 set_alist_count();
405 }
406#endif
407
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000408#ifdef MSWIN
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000409 if (GARGCOUNT == 1 && params.full_path)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000410 {
411 /*
412 * If there is one filename, fully qualified, we have very probably
413 * been invoked from explorer, so change to the file's directory.
414 * Hint: to avoid this when typing a command use a forward slash.
415 * If the cd fails, it doesn't matter.
416 */
417 (void)vim_chdirfile(fname);
418 }
419#endif
420 TIME_MSG("expanding arguments");
421
422#ifdef FEAT_DIFF
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000423 if (params.diff_mode && params.window_count == -1)
424 params.window_count = 0; /* open up to 3 files in a window */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000425#endif
426
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000427 /* Don't redraw until much later. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000428 ++RedrawingDisabled;
429
430 /*
431 * When listing swap file names, don't do cursor positioning et. al.
432 */
433 if (recoverymode && fname == NULL)
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000434 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000435
436 /*
437 * When certain to start the GUI, don't check capabilities of terminal.
438 * For GTK we can't be sure, but when started from the desktop it doesn't
439 * make sense to try using a terminal.
440 */
Bram Moolenaar843ee412004-06-30 16:16:41 +0000441#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000442 if (gui.starting
443# ifdef FEAT_GUI_GTK
444 && !isatty(2)
445# endif
446 )
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000447 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000448#endif
449
450#if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX)
451 /* When the GUI is started from Finder, need to display messages in a
452 * message box. isatty(2) returns TRUE anyway, thus we need to check the
453 * name to know we're not started from a terminal. */
454 if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000455 params.want_full_screen = FALSE;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000456#endif
457
458 /*
459 * mch_init() sets up the terminal (window) for use. This must be
460 * done after resetting full_screen, otherwise it may move the cursor
461 * (MSDOS).
462 * Note that we may use mch_exit() before mch_init()!
463 */
464 mch_init();
465 TIME_MSG("shell init");
466
467#ifdef USE_XSMP
468 /*
469 * For want of anywhere else to do it, try to connect to xsmp here.
470 * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
471 * Hijacking -X 'no X connection' to also disable XSMP connection as that
472 * has a similar delay upon failure.
473 * Only try if SESSION_MANAGER is set to something non-null.
474 */
475 if (!x_no_connect)
476 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000477 char *p = getenv("SESSION_MANAGER");
478
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000479 if (p != NULL && *p != NUL)
480 {
481 xsmp_init();
482 TIME_MSG("xsmp init");
483 }
484 }
485#endif
486
487 /*
488 * Print a warning if stdout is not a terminal.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000489 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000490 check_tty(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000491
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000492 /* This message comes before term inits, but after setting "silent_mode"
493 * when the input is not a tty. */
494 if (GARGCOUNT > 1 && !silent_mode)
495 printf(_("%d files to edit\n"), GARGCOUNT);
496
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000497 if (params.want_full_screen && !silent_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000498 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000499 termcapinit(params.term); /* set terminal name and get terminal
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000500 capabilities (will set full_screen) */
501 screen_start(); /* don't know where cursor is now */
502 TIME_MSG("Termcap init");
503 }
504
505 /*
506 * Set the default values for the options that use Rows and Columns.
507 */
508 ui_get_shellsize(); /* inits Rows and Columns */
509#ifdef FEAT_NETBEANS_INTG
510 if (usingNetbeans)
511 Columns += 2; /* leave room for glyph gutter */
512#endif
513 firstwin->w_height = Rows - p_ch;
514 topframe->fr_height = Rows - p_ch;
515#ifdef FEAT_VERTSPLIT
516 firstwin->w_width = Columns;
517 topframe->fr_width = Columns;
518#endif
519#ifdef FEAT_DIFF
520 /* Set the 'diff' option now, so that it can be checked for in a .vimrc
521 * file. There is no buffer yet though. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000522 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000523 diff_win_options(firstwin, FALSE);
524#endif
525
526 cmdline_row = Rows - p_ch;
527 msg_row = cmdline_row;
528 screenalloc(FALSE); /* allocate screen buffers */
529 set_init_2();
530 TIME_MSG("inits 2");
531
532 msg_scroll = TRUE;
533 no_wait_return = TRUE;
534
535 init_mappings(); /* set up initial mappings */
536
537 init_highlight(TRUE, FALSE); /* set the default highlight groups */
538 TIME_MSG("init highlight");
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000539
540#ifdef FEAT_EVAL
541 /* Set the break level after the terminal is initialized. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000542 debug_break_level = params.use_debug_break_level;
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000543#endif
544
Bram Moolenaar58d98232005-07-23 22:25:46 +0000545 /* Execute --cmd arguments. */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000546 exe_pre_commands(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000547
Bram Moolenaar58d98232005-07-23 22:25:46 +0000548 /* Source startup scripts. */
549 source_startup_scripts(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000550
551#ifdef FEAT_EVAL
552 /*
553 * Read all the plugin files.
554 * Only when compiled with +eval, since most plugins need it.
555 */
556 if (p_lpl)
557 {
558 cmd_runtime((char_u *)"plugin/*.vim", TRUE);
559 TIME_MSG("loading plugins");
560 }
561#endif
562
563 /*
564 * Recovery mode without a file name: List swap files.
565 * This uses the 'dir' option, therefore it must be after the
566 * initializations.
567 */
568 if (recoverymode && fname == NULL)
569 {
570 recover_names(NULL, TRUE, 0);
571 mch_exit(0);
572 }
573
574 /*
575 * Set a few option defaults after reading .vimrc files:
576 * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
577 */
578 set_init_3();
579 TIME_MSG("inits 3");
580
581 /*
582 * "-n" argument: Disable swap file by setting 'updatecount' to 0.
583 * Note that this overrides anything from a vimrc file.
584 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000585 if (params.no_swap_file)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000586 p_uc = 0;
587
588#ifdef FEAT_FKMAP
589 if (curwin->w_p_rl && p_altkeymap)
590 {
591 p_hkmap = FALSE; /* Reset the Hebrew keymap mode */
592# ifdef FEAT_ARABIC
593 curwin->w_p_arab = FALSE; /* Reset the Arabic keymap mode */
594# endif
595 p_fkmap = TRUE; /* Set the Farsi keymap mode */
596 }
597#endif
598
599#ifdef FEAT_GUI
600 if (gui.starting)
601 {
602#if defined(UNIX) || defined(VMS)
603 /* When something caused a message from a vimrc script, need to output
604 * an extra newline before the shell prompt. */
605 if (did_emsg || msg_didout)
606 putchar('\n');
607#endif
608
609 gui_start(); /* will set full_screen to TRUE */
610 TIME_MSG("starting GUI");
611
612 /* When running "evim" or "gvim -y" we need the menus, exit if we
613 * don't have them. */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000614 if (!gui.in_use && params.evim_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000615 mch_exit(1);
616 }
617#endif
618
619#ifdef SPAWNO /* special MSDOS swapping library */
620 init_SPAWNO("", SWAP_ANY);
621#endif
622
623#ifdef FEAT_VIMINFO
624 /*
625 * Read in registers, history etc, but not marks, from the viminfo file
626 */
627 if (*p_viminfo != NUL)
628 {
629 read_viminfo(NULL, TRUE, FALSE, FALSE);
630 TIME_MSG("reading viminfo");
631 }
632#endif
633
634#ifdef FEAT_QUICKFIX
635 /*
636 * "-q errorfile": Load the error file now.
637 * If the error file can't be read, exit before doing anything else.
638 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000639 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000640 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000641 if (params.use_ef != NULL)
642 set_string_option_direct((char_u *)"ef", -1,
643 params.use_ef, OPT_FREE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000644 if (qf_init(p_ef, p_efm, TRUE) < 0)
645 {
646 out_char('\n');
647 mch_exit(3);
648 }
649 TIME_MSG("reading errorfile");
650 }
651#endif
652
653 /*
654 * Start putting things on the screen.
655 * Scroll screen down before drawing over it
656 * Clear screen now, so file message will not be cleared.
657 */
658 starting = NO_BUFFERS;
659 no_wait_return = FALSE;
660 if (!exmode_active)
661 msg_scroll = FALSE;
662
663#ifdef FEAT_GUI
664 /*
665 * This seems to be required to make callbacks to be called now, instead
666 * of after things have been put on the screen, which then may be deleted
667 * when getting a resize callback.
668 * For the Mac this handles putting files dropped on the Vim icon to
669 * global_alist.
670 */
671 if (gui.in_use)
672 {
673# ifdef FEAT_SUN_WORKSHOP
674 if (!usingSunWorkShop)
675# endif
676 gui_wait_for_chars(50L);
677 TIME_MSG("GUI delay");
678 }
679#endif
680
681#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
682 qnx_clip_init();
683#endif
684
685#ifdef FEAT_XCLIPBOARD
686 /* Start using the X clipboard, unless the GUI was started. */
687# ifdef FEAT_GUI
688 if (!gui.in_use)
689# endif
690 {
691 setup_term_clip();
692 TIME_MSG("setup clipboard");
693 }
694#endif
695
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000696#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000697 /* Prepare for being a Vim server. */
698 prepare_server(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000699#endif
700
701 /*
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)
712 /* When switching screens and something caused a message from a vimrc
713 * script, need to output an extra newline on exit. */
714 if ((did_emsg || msg_didout) && *T_TI != NUL)
715 newline_on_exit = TRUE;
716#endif
717
718 /*
719 * When done something that is not allowed or error message call
720 * wait_return. This must be done before starttermcap(), because it may
721 * 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
724 * defined by termcapinit and redifined in .exrc.
725 */
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
735 starttermcap(); /* start termcap if not done by wait_return() */
736 TIME_MSG("start termcap");
737
738#ifdef FEAT_MOUSE
739 setmouse(); /* may start using the mouse */
740#endif
741 if (scroll_region)
742 scroll_region_reset(); /* In case Rows changed */
Bram Moolenaar58d98232005-07-23 22:25:46 +0000743 scroll_start(); /* may scroll the screen to the right position */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000744
745 /*
746 * Don't clear the screen when starting in Ex mode, unless using the GUI.
747 */
748 if (exmode_active
749#ifdef FEAT_GUI
750 && !gui.in_use
751#endif
752 )
753 must_redraw = CLEAR;
754 else
755 {
756 screenclear(); /* clear screen */
757 TIME_MSG("clearing screen");
758 }
759
760#ifdef FEAT_CRYPT
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000761 if (params.ask_for_key)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000762 {
763 (void)get_crypt_key(TRUE, TRUE);
764 TIME_MSG("getting crypt key");
765 }
766#endif
767
768 no_wait_return = TRUE;
769
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000770 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000771 * Create the requested number of windows and edit buffers in them.
772 * Also does recovery if "recoverymode" set.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000773 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000774 create_windows(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000775 TIME_MSG("opening buffers");
776
777 /* Ex starts at last line of the file */
778 if (exmode_active)
779 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
780
781#ifdef FEAT_AUTOCMD
782 apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
783 TIME_MSG("BufEnter autocommands");
784#endif
785 setpcmark();
786
787#ifdef FEAT_QUICKFIX
788 /*
789 * When started with "-q errorfile" jump to first error now.
790 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000791 if (params.edit_type == EDIT_QF)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000792 {
793 qf_jump(0, 0, FALSE);
794 TIME_MSG("jump to first error");
795 }
796#endif
797
798#ifdef FEAT_WINDOWS
799 /*
800 * If opened more than one window, start editing files in the other
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000801 * windows.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000802 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000803 edit_buffers(&params);
804#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000805
806#ifdef FEAT_DIFF
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000807 if (params.diff_mode)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000808 {
809 win_T *wp;
810
811 /* set options in each window for "vimdiff". */
812 for (wp = firstwin; wp != NULL; wp = wp->w_next)
813 diff_win_options(wp, TRUE);
814 }
815#endif
816
817 /*
818 * Shorten any of the filenames, but only when absolute.
819 */
820 shorten_fnames(FALSE);
821
822 /*
823 * Need to jump to the tag before executing the '-c command'.
824 * Makes "vim -c '/return' -t main" work.
825 */
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000826 if (params.tagname != NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000827 {
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000828 vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000829 do_cmdline_cmd(IObuff);
830 TIME_MSG("jumping to tag");
831 }
832
Bram Moolenaarc013cb62005-07-24 21:18:31 +0000833 /* Execute any "+", "-c" and "-S" arguments. */
834 if (params.n_commands > 0)
835 exe_commands(&params);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000836
837 RedrawingDisabled = 0;
838 redraw_all_later(NOT_VALID);
839 no_wait_return = FALSE;
840 starting = 0;
841
842 /* start in insert mode */
843 if (p_im)
844 need_start_insertmode = TRUE;
845
846#ifdef FEAT_AUTOCMD
847 apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
848 TIME_MSG("VimEnter autocommands");
849#endif
850
851#if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND)
852 /* When a startup script or session file setup for diff'ing and
853 * scrollbind, sync the scrollbind now. */
854 if (curwin->w_p_diff && curwin->w_p_scb)
855 {
856 update_topline();
857 check_scrollbind((linenr_T)0, 0L);
858 TIME_MSG("diff scrollbinding");
859 }
860#endif
861
862#if defined(WIN3264) && !defined(FEAT_GUI_W32)
863 mch_set_winsize_now(); /* Allow winsize changes from now on */
864#endif
865
866 /* If ":startinsert" command used, stuff a dummy command to be able to
867 * call normal_cmd(), which will then start Insert mode. */
868 if (restart_edit != 0)
869 stuffcharReadbuff(K_IGNORE);
870
871#ifdef FEAT_NETBEANS_INTG
872 if (usingNetbeans)
873 /* Tell the client that it can start sending commands. */
874 netbeans_startup_done();
875#endif
876
877 TIME_MSG("before starting main loop");
878
879 /*
880 * Call the main command loop. This never returns.
881 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000882 main_loop(FALSE, FALSE);
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000883
884 return 0;
885}
886#endif /* PROTO */
887
888/*
889 * Main loop: Execute Normal mode commands until exiting Vim.
890 * Also used to handle commands in the command-line window, until the window
891 * is closed.
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000892 * Also used to handle ":visual" command after ":global": execute Normal mode
893 * commands, return when entering Ex mode. "noexmode" is TRUE then.
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000894 */
895 void
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000896main_loop(cmdwin, noexmode)
897 int cmdwin; /* TRUE when working in the command-line window */
898 int noexmode; /* TRUE when return on entering Ex mode */
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000899{
900 oparg_T oa; /* operator arguments */
901
902#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
903 /* Setup to catch a terminating error from the X server. Just ignore
904 * it, restore the state and continue. This might not always work
905 * properly, but at least we don't exit unexpectedly when the X server
906 * exists while Vim is running in a console. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000907 if (!cmdwin && !noexmode && SETJMP(x_jump_env))
Bram Moolenaarb4210b32004-06-13 14:51:16 +0000908 {
909 State = NORMAL;
910# ifdef FEAT_VISUAL
911 VIsual_active = FALSE;
912# endif
913 got_int = TRUE;
914 need_wait_return = FALSE;
915 global_busy = FALSE;
916 exmode_active = 0;
917 skip_redraw = FALSE;
918 RedrawingDisabled = 0;
919 no_wait_return = 0;
920# ifdef FEAT_EVAL
921 emsg_skip = 0;
922# endif
923 emsg_off = 0;
924# ifdef FEAT_MOUSE
925 setmouse();
926# endif
927 settmode(TMODE_RAW);
928 starttermcap();
929 scroll_start();
930 redraw_later_clear();
931 }
932#endif
933
934 clear_oparg(&oa);
935 while (!cmdwin
936#ifdef FEAT_CMDWIN
937 || cmdwin_result == 0
938#endif
939 )
940 {
941 if (stuff_empty())
942 {
943 did_check_timestamps = FALSE;
944 if (need_check_timestamps)
945 check_timestamps(FALSE);
946 if (need_wait_return) /* if wait_return still needed ... */
947 wait_return(FALSE); /* ... call it now */
948 if (need_start_insertmode && goto_im()
949#ifdef FEAT_VISUAL
950 && !VIsual_active
951#endif
952 )
953 {
954 need_start_insertmode = FALSE;
955 stuffReadbuff((char_u *)"i"); /* start insert mode next */
956 /* skip the fileinfo message now, because it would be shown
957 * after insert mode finishes! */
958 need_fileinfo = FALSE;
959 }
960 }
961 if (got_int && !global_busy)
962 {
963 if (!quit_more)
964 (void)vgetc(); /* flush all buffers */
965 got_int = FALSE;
966 }
967 if (!exmode_active)
968 msg_scroll = FALSE;
969 quit_more = FALSE;
970
971 /*
972 * If skip redraw is set (for ":" in wait_return()), don't redraw now.
973 * If there is nothing in the stuff_buffer or do_redraw is TRUE,
974 * update cursor and redraw.
975 */
976 if (skip_redraw || exmode_active)
977 skip_redraw = FALSE;
978 else if (do_redraw || stuff_empty())
979 {
980#if defined(FEAT_FOLDING) && defined(FEAT_VISUAL)
981 /* Include a closed fold completely in the Visual area. */
982 foldAdjustVisual();
983#endif
984#ifdef FEAT_FOLDING
985 /*
986 * When 'foldclose' is set, apply 'foldlevel' to folds that don't
987 * contain the cursor.
988 * When 'foldopen' is "all", open the fold(s) under the cursor.
989 * This may mark the window for redrawing.
990 */
991 if (hasAnyFolding(curwin) && !char_avail())
992 {
993 foldCheckClose();
994 if (fdo_flags & FDO_ALL)
995 foldOpenCursor();
996 }
997#endif
998
999 /*
1000 * Before redrawing, make sure w_topline is correct, and w_leftcol
1001 * if lines don't wrap, and w_skipcol if lines wrap.
1002 */
1003 update_topline();
1004 validate_cursor();
1005
1006#ifdef FEAT_VISUAL
1007 if (VIsual_active)
1008 update_curbuf(INVERTED);/* update inverted part */
1009 else
1010#endif
1011 if (must_redraw)
1012 update_screen(0);
1013 else if (redraw_cmdline || clear_cmdline)
1014 showmode();
1015#ifdef FEAT_WINDOWS
1016 redraw_statuslines();
1017#endif
1018#ifdef FEAT_TITLE
1019 if (need_maketitle)
1020 maketitle();
1021#endif
1022 /* display message after redraw */
1023 if (keep_msg != NULL)
1024 {
1025 char_u *p;
1026
1027 /* msg_attr_keep() will set keep_msg to NULL, must free the
1028 * string here. */
1029 p = keep_msg;
1030 msg_attr(p, keep_msg_attr);
1031 vim_free(p);
1032 }
1033 if (need_fileinfo) /* show file info after redraw */
1034 {
1035 fileinfo(FALSE, TRUE, FALSE);
1036 need_fileinfo = FALSE;
1037 }
1038
1039 emsg_on_display = FALSE; /* can delete error message now */
1040 did_emsg = FALSE;
1041 msg_didany = FALSE; /* reset lines_left in msg_start() */
1042 showruler(FALSE);
1043
1044 setcursor();
1045 cursor_on();
1046
1047 do_redraw = FALSE;
1048 }
1049#ifdef FEAT_GUI
1050 if (need_mouse_correct)
1051 gui_mouse_correct();
1052#endif
1053
1054 /*
1055 * Update w_curswant if w_set_curswant has been set.
1056 * Postponed until here to avoid computing w_virtcol too often.
1057 */
1058 update_curswant();
1059
1060 /*
1061 * If we're invoked as ex, do a round of ex commands.
1062 * Otherwise, get and execute a normal mode command.
1063 */
1064 if (exmode_active)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001065 {
1066 if (noexmode) /* End of ":global/path/visual" commands */
1067 return;
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001068 do_exmode(exmode_active == EXMODE_VIM);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001069 }
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001070 else
1071 normal_cmd(&oa, TRUE);
1072 }
1073}
1074
1075
1076#if defined(USE_XSMP) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
1077/*
1078 * Exit, but leave behind swap files for modified buffers.
1079 */
1080 void
1081getout_preserve_modified(exitval)
1082 int exitval;
1083{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001084# if defined(SIGHUP) && defined(SIG_IGN)
1085 /* Ignore SIGHUP, because a dropped connection causes a read error, which
1086 * makes Vim exit and then handling SIGHUP causes various reentrance
1087 * problems. */
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001088 signal(SIGHUP, SIG_IGN);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001089# endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001090
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001091 ml_close_notmod(); /* close all not-modified buffers */
1092 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
1093 ml_close_all(FALSE); /* close all memfiles, without deleting */
1094 getout(exitval); /* exit Vim properly */
1095}
1096#endif
1097
1098
1099/* Exit properly */
1100 void
1101getout(exitval)
1102 int exitval;
1103{
1104#ifdef FEAT_AUTOCMD
1105 buf_T *buf;
1106 win_T *wp;
1107#endif
1108
1109 exiting = TRUE;
1110
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00001111 /* When running in Ex mode an error causes us to exit with a non-zero exit
1112 * code. POSIX requires this, although it's not 100% clear from the
1113 * standard. */
1114 if (exmode_active)
1115 exitval += ex_exitval;
1116
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001117 /* Position the cursor on the last screen line, below all the text */
1118#ifdef FEAT_GUI
1119 if (!gui.in_use)
1120#endif
1121 windgoto((int)Rows - 1, 0);
1122
Bram Moolenaar0e21a3f2005-04-17 20:28:32 +00001123#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
1124 /* Optionally print hashtable efficiency. */
1125 hash_debug_results();
1126#endif
1127
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001128#ifdef FEAT_GUI
1129 msg_didany = FALSE;
1130#endif
1131
1132#ifdef FEAT_AUTOCMD
1133 /* Trigger BufWinLeave for all windows, but only once per buffer. */
1134 for (wp = firstwin; wp != NULL; )
1135 {
1136 buf = wp->w_buffer;
1137 if (buf->b_changedtick != -1)
1138 {
1139 apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
1140 FALSE, buf);
1141 buf->b_changedtick = -1; /* note that we did it already */
1142 wp = firstwin; /* restart, window may be closed */
1143 }
1144 else
1145 wp = wp->w_next;
1146 }
1147 /* Trigger BufUnload for buffers that are loaded */
1148 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1149 if (buf->b_ml.ml_mfp != NULL)
1150 {
1151 apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
1152 FALSE, buf);
1153 if (!buf_valid(buf)) /* autocmd may delete the buffer */
1154 break;
1155 }
1156 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
1157#endif
1158
1159#ifdef FEAT_VIMINFO
1160 if (*p_viminfo != NUL)
1161 /* Write out the registers, history, marks etc, to the viminfo file */
1162 write_viminfo(NULL, FALSE);
1163#endif
1164
1165#ifdef FEAT_AUTOCMD
1166 apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
1167#endif
1168
Bram Moolenaar05159a02005-02-26 23:04:13 +00001169#ifdef FEAT_PROFILE
1170 profile_dump();
1171#endif
1172
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001173 if (did_emsg
1174#ifdef FEAT_GUI
1175 || (gui.in_use && msg_didany && p_verbose > 0)
1176#endif
1177 )
1178 {
1179 /* give the user a chance to read the (error) message */
1180 no_wait_return = FALSE;
1181 wait_return(FALSE);
1182 }
1183
1184#ifdef FEAT_AUTOCMD
1185 /* Position the cursor again, the autocommands may have moved it */
1186# ifdef FEAT_GUI
1187 if (!gui.in_use)
1188# endif
1189 windgoto((int)Rows - 1, 0);
1190#endif
1191
Bram Moolenaar325b7a22004-07-05 15:58:32 +00001192#ifdef FEAT_MZSCHEME
1193 mzscheme_end();
1194#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001195#ifdef FEAT_TCL
1196 tcl_end();
1197#endif
1198#ifdef FEAT_RUBY
1199 ruby_end();
1200#endif
1201#ifdef FEAT_PYTHON
1202 python_end();
1203#endif
1204#ifdef FEAT_PERL
1205 perl_end();
1206#endif
1207#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
1208 iconv_end();
1209#endif
1210#ifdef FEAT_NETBEANS_INTG
1211 netbeans_end();
1212#endif
1213
1214 mch_exit(exitval);
1215}
1216
1217/*
1218 * Get a (optional) count for a Vim argument.
1219 */
1220 static int
1221get_number_arg(p, idx, def)
1222 char_u *p; /* pointer to argument */
1223 int *idx; /* index in argument, is incremented */
1224 int def; /* default value */
1225{
1226 if (vim_isdigit(p[*idx]))
1227 {
1228 def = atoi((char *)&(p[*idx]));
1229 while (vim_isdigit(p[*idx]))
1230 *idx = *idx + 1;
1231 }
1232 return def;
1233}
1234
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001235#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
1236/*
1237 * Setup to use the current locale (for ctype() and many other things).
1238 */
1239 static void
1240init_locale()
1241{
1242 setlocale(LC_ALL, "");
1243
1244# ifdef FEAT_GETTEXT
1245 {
1246 int mustfree = FALSE;
1247 char_u *p;
1248
1249# ifdef DYNAMIC_GETTEXT
1250 /* Initialize the gettext library */
1251 dyn_libintl_init(NULL);
1252# endif
1253 /* expand_env() doesn't work yet, because chartab[] is not initialized
1254 * yet, call vim_getenv() directly */
1255 p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
1256 if (p != NULL && *p != NUL)
1257 {
1258 STRCPY(NameBuff, p);
1259 STRCAT(NameBuff, "/lang");
1260 bindtextdomain(VIMPACKAGE, (char *)NameBuff);
1261 }
1262 if (mustfree)
1263 vim_free(p);
1264 textdomain(VIMPACKAGE);
1265 }
1266# endif
1267}
1268#endif
1269
1270/*
1271 * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
1272 * If the executable name starts with "r" we disable shell commands.
1273 * If the next character is "e" we run in Easy mode.
1274 * If the next character is "g" we run the GUI version.
1275 * If the next characters are "view" we start in readonly mode.
1276 * If the next characters are "diff" or "vimdiff" we start in diff mode.
1277 * If the next characters are "ex" we start in Ex mode. If it's followed
1278 * by "im" use improved Ex mode.
1279 */
1280 static void
1281parse_command_name(parmp)
1282 mparm_T *parmp;
1283{
1284 char_u *initstr;
1285
1286 initstr = gettail((char_u *)parmp->argv[0]);
1287
1288#ifdef MACOS_X_UNIX
1289 /* An issue has been seen when launching Vim in such a way that
1290 * $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the
1291 * executable or a symbolic link of it. Until this issue is resolved
1292 * we prohibit the GUI from being used.
1293 */
1294 if (STRCMP(initstr, parmp->argv[0]) == 0)
1295 disallow_gui = TRUE;
1296
1297 /* TODO: On MacOS X default to gui if argv[0] ends in:
1298 * /vim.app/Contents/MacOS/Vim */
1299#endif
1300
1301#ifdef FEAT_EVAL
1302 set_vim_var_string(VV_PROGNAME, initstr, -1);
1303#endif
1304
1305 if (TOLOWER_ASC(initstr[0]) == 'r')
1306 {
1307 restricted = TRUE;
1308 ++initstr;
1309 }
1310
1311 /* Avoid using evim mode for "editor". */
1312 if (TOLOWER_ASC(initstr[0]) == 'e'
1313 && (TOLOWER_ASC(initstr[1]) == 'v'
1314 || TOLOWER_ASC(initstr[1]) == 'g'))
1315 {
1316#ifdef FEAT_GUI
1317 gui.starting = TRUE;
1318#endif
1319 parmp->evim_mode = TRUE;
1320 ++initstr;
1321 }
1322
1323 if (TOLOWER_ASC(initstr[0]) == 'g' || initstr[0] == 'k')
1324 {
1325 main_start_gui();
1326#ifdef FEAT_GUI
1327 ++initstr;
1328#endif
1329 }
1330
1331 if (STRNICMP(initstr, "view", 4) == 0)
1332 {
1333 readonlymode = TRUE;
1334 curbuf->b_p_ro = TRUE;
1335 p_uc = 10000; /* don't update very often */
1336 initstr += 4;
1337 }
1338 else if (STRNICMP(initstr, "vim", 3) == 0)
1339 initstr += 3;
1340
1341 /* Catch "[r][g]vimdiff" and "[r][g]viewdiff". */
1342 if (STRICMP(initstr, "diff") == 0)
1343 {
1344#ifdef FEAT_DIFF
1345 parmp->diff_mode = TRUE;
1346#else
1347 mch_errmsg(_("This Vim was not compiled with the diff feature."));
1348 mch_errmsg("\n");
1349 mch_exit(2);
1350#endif
1351 }
1352
1353 if (STRNICMP(initstr, "ex", 2) == 0)
1354 {
1355 if (STRNICMP(initstr + 2, "im", 2) == 0)
1356 exmode_active = EXMODE_VIM;
1357 else
1358 exmode_active = EXMODE_NORMAL;
1359 change_compatible(TRUE); /* set 'compatible' */
1360 }
1361}
1362
Bram Moolenaarb4210b32004-06-13 14:51:16 +00001363/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00001364 * Get the name of the display, before gui_prepare() removes it from
1365 * argv[]. Used for the xterm-clipboard display.
1366 *
1367 * Also find the --server... arguments and --socketid
1368 */
1369/*ARGSUSED*/
1370 static void
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001371early_arg_scan(parmp)
Bram Moolenaar58d98232005-07-23 22:25:46 +00001372 mparm_T *parmp;
1373{
1374#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER)
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001375 int argc = parmp->argc;
1376 char **argv = parmp->argv;
Bram Moolenaar58d98232005-07-23 22:25:46 +00001377 int i;
1378
1379 for (i = 1; i < argc; i++)
1380 {
1381 if (STRCMP(argv[i], "--") == 0)
1382 break;
1383# ifdef FEAT_XCLIPBOARD
1384 else if (STRICMP(argv[i], "-display") == 0
1385# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
1386 || STRICMP(argv[i], "--display") == 0
1387# endif
1388 )
1389 {
1390 if (i == argc - 1)
1391 mainerr_arg_missing((char_u *)argv[i]);
1392 xterm_display = argv[++i];
1393 }
1394# endif
1395# ifdef FEAT_CLIENTSERVER
1396 else if (STRICMP(argv[i], "--servername") == 0)
1397 {
1398 if (i == argc - 1)
1399 mainerr_arg_missing((char_u *)argv[i]);
1400 parmp->serverName_arg = (char_u *)argv[++i];
1401 }
1402 else if (STRICMP(argv[i], "--serverlist") == 0
1403 || STRICMP(argv[i], "--remote-send") == 0
1404 || STRICMP(argv[i], "--remote-expr") == 0
1405 || STRICMP(argv[i], "--remote") == 0
1406 || STRICMP(argv[i], "--remote-silent") == 0)
1407 parmp->serverArg = TRUE;
1408 else if (STRICMP(argv[i], "--remote-wait") == 0
1409 || STRICMP(argv[i], "--remote-wait-silent") == 0)
1410 {
1411 parmp->serverArg = TRUE;
1412#ifdef FEAT_GUI
1413 /* don't fork() when starting the GUI to edit the files ourself */
1414 gui.dofork = FALSE;
1415#endif
1416 }
1417# endif
1418# ifdef FEAT_GUI_GTK
1419 else if (STRICMP(argv[i], "--socketid") == 0)
1420 {
1421 unsigned int socket_id;
1422 int count;
1423
1424 if (i == argc - 1)
1425 mainerr_arg_missing((char_u *)argv[i]);
1426 if (STRNICMP(argv[i+1], "0x", 2) == 0)
1427 count = sscanf(&(argv[i + 1][2]), "%x", &socket_id);
1428 else
1429 count = sscanf(argv[i+1], "%u", &socket_id);
1430 if (count != 1)
1431 mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
1432 else
1433 gtk_socket_id = socket_id;
1434 i++;
1435 }
1436 else if (STRICMP(argv[i], "--echo-wid") == 0)
1437 echo_wid_arg = TRUE;
1438# endif
1439 }
1440#endif
1441}
1442
1443/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00001444 * Scan the command line arguments.
1445 */
1446 static void
1447command_line_scan(parmp)
1448 mparm_T *parmp;
1449{
1450 int argc = parmp->argc;
1451 char **argv = parmp->argv;
1452 int argv_idx; /* index in argv[n][] */
1453 int had_minmin = FALSE; /* found "--" argument */
1454 int want_argument; /* option argument with argument */
1455 int c;
1456 char_u *p;
1457 long n;
1458
1459 --argc;
1460 ++argv;
1461 argv_idx = 1; /* active option letter is argv[0][argv_idx] */
1462 while (argc > 0)
1463 {
1464 /*
1465 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
1466 */
1467 if (argv[0][0] == '+' && !had_minmin)
1468 {
1469 if (parmp->n_commands >= MAX_ARG_CMDS)
1470 mainerr(ME_EXTRA_CMD, NULL);
1471 argv_idx = -1; /* skip to next argument */
1472 if (argv[0][1] == NUL)
1473 parmp->commands[parmp->n_commands++] = (char_u *)"$";
1474 else
1475 parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]);
1476 }
1477
1478 /*
1479 * Optional argument.
1480 */
1481 else if (argv[0][0] == '-' && !had_minmin)
1482 {
1483 want_argument = FALSE;
1484 c = argv[0][argv_idx++];
1485#ifdef VMS
1486 /*
1487 * VMS only uses upper case command lines. Interpret "-X" as "-x"
1488 * and "-/X" as "-X".
1489 */
1490 if (c == '/')
1491 {
1492 c = argv[0][argv_idx++];
1493 c = TOUPPER_ASC(c);
1494 }
1495 else
1496 c = TOLOWER_ASC(c);
1497#endif
1498 switch (c)
1499 {
1500 case NUL: /* "vim -" read from stdin */
1501 /* "ex -" silent mode */
1502 if (exmode_active)
1503 silent_mode = TRUE;
1504 else
1505 {
1506 if (parmp->edit_type != EDIT_NONE)
1507 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
1508 parmp->edit_type = EDIT_STDIN;
1509 read_cmd_fd = 2; /* read from stderr instead of stdin */
1510 }
1511 argv_idx = -1; /* skip to next argument */
1512 break;
1513
1514 case '-': /* "--" don't take any more option arguments */
1515 /* "--help" give help message */
1516 /* "--version" give version message */
1517 /* "--literal" take files literally */
1518 /* "--nofork" don't fork */
1519 /* "--noplugin[s]" skip plugins */
1520 /* "--cmd <cmd>" execute cmd before vimrc */
1521 if (STRICMP(argv[0] + argv_idx, "help") == 0)
1522 usage();
1523 else if (STRICMP(argv[0] + argv_idx, "version") == 0)
1524 {
1525 Columns = 80; /* need to init Columns */
1526 info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
1527 list_version();
1528 msg_putchar('\n');
1529 msg_didout = FALSE;
1530 mch_exit(0);
1531 }
1532 else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
1533 {
1534#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
1535 parmp->literal = TRUE;
1536#endif
1537 }
1538 else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
1539 {
1540#ifdef FEAT_GUI
1541 gui.dofork = FALSE; /* don't fork() when starting GUI */
1542#endif
1543 }
1544 else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
1545 p_lpl = FALSE;
1546 else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
1547 {
1548 want_argument = TRUE;
1549 argv_idx += 3;
1550 }
1551#ifdef FEAT_CLIENTSERVER
1552 else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
1553 ; /* already processed -- no arg */
1554 else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
1555 || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
1556 {
1557 /* already processed -- snatch the following arg */
1558 if (argc > 1)
1559 {
1560 --argc;
1561 ++argv;
1562 }
1563 }
1564#endif
1565#ifdef FEAT_GUI_GTK
1566 else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
1567 {
1568 /* already processed -- snatch the following arg */
1569 if (argc > 1)
1570 {
1571 --argc;
1572 ++argv;
1573 }
1574 }
1575 else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
1576 {
1577 /* already processed, skip */
1578 }
1579#endif
1580 else
1581 {
1582 if (argv[0][argv_idx])
1583 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
1584 had_minmin = TRUE;
1585 }
1586 if (!want_argument)
1587 argv_idx = -1; /* skip to next argument */
1588 break;
1589
1590 case 'A': /* "-A" start in Arabic mode */
1591#ifdef FEAT_ARABIC
1592 set_option_value((char_u *)"arabic", 1L, NULL, 0);
1593#else
1594 mch_errmsg(_(e_noarabic));
1595 mch_exit(2);
1596#endif
1597 break;
1598
1599 case 'b': /* "-b" binary mode */
1600 parmp->bin_mode = TRUE; /* postpone to after reading .exrc files */
1601 break;
1602
1603 case 'C': /* "-C" Compatible */
1604 change_compatible(TRUE);
1605 break;
1606
1607 case 'e': /* "-e" Ex mode */
1608 exmode_active = EXMODE_NORMAL;
1609 break;
1610
1611 case 'E': /* "-E" Improved Ex mode */
1612 exmode_active = EXMODE_VIM;
1613 break;
1614
1615 case 'f': /* "-f" GUI: run in foreground. Amiga: open
1616 window directly, not with newcli */
1617#ifdef FEAT_GUI
1618 gui.dofork = FALSE; /* don't fork() when starting GUI */
1619#endif
1620 break;
1621
1622 case 'g': /* "-g" start GUI */
1623 main_start_gui();
1624 break;
1625
1626 case 'F': /* "-F" start in Farsi mode: rl + fkmap set */
1627#ifdef FEAT_FKMAP
1628 curwin->w_p_rl = p_fkmap = TRUE;
1629#else
1630 mch_errmsg(_(e_nofarsi));
1631 mch_exit(2);
1632#endif
1633 break;
1634
1635 case 'h': /* "-h" give help message */
1636#ifdef FEAT_GUI_GNOME
1637 /* Tell usage() to exit for "gvim". */
1638 gui.starting = FALSE;
1639#endif
1640 usage();
1641 break;
1642
1643 case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */
1644#ifdef FEAT_RIGHTLEFT
1645 curwin->w_p_rl = p_hkmap = TRUE;
1646#else
1647 mch_errmsg(_(e_nohebrew));
1648 mch_exit(2);
1649#endif
1650 break;
1651
1652 case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */
1653#ifdef FEAT_LISP
1654 set_option_value((char_u *)"lisp", 1L, NULL, 0);
1655 p_sm = TRUE;
1656#endif
1657 break;
1658
1659#ifdef TARGET_API_MAC_OSX
1660 /* For some reason on MacOS X, an argument like:
1661 -psn_0_10223617 is passed in when invoke from Finder
1662 or with the 'open' command */
1663 case 'p':
1664 argv_idx = -1; /* bypass full -psn */
1665 main_start_gui();
1666 break;
1667#endif
1668 case 'M': /* "-M" no changes or writing of files */
1669 reset_modifiable();
1670 /* FALLTHROUGH */
1671
1672 case 'm': /* "-m" no writing of files */
1673 p_write = FALSE;
1674 break;
1675
1676 case 'y': /* "-y" easy mode */
1677#ifdef FEAT_GUI
1678 gui.starting = TRUE; /* start GUI a bit later */
1679#endif
1680 parmp->evim_mode = TRUE;
1681 break;
1682
1683 case 'N': /* "-N" Nocompatible */
1684 change_compatible(FALSE);
1685 break;
1686
1687 case 'n': /* "-n" no swap file */
1688 parmp->no_swap_file = TRUE;
1689 break;
1690
1691 case 'o': /* "-o[N]" open N horizontal split windows */
1692#ifdef FEAT_WINDOWS
1693 /* default is 0: open window for each file */
1694 parmp->window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
1695 parmp->vert_windows = FALSE;
1696#endif
1697 break;
1698
1699 case 'O': /* "-O[N]" open N vertical split windows */
1700#if defined(FEAT_VERTSPLIT) && defined(FEAT_WINDOWS)
1701 /* default is 0: open window for each file */
1702 parmp->window_count = get_number_arg((char_u *)argv[0], &argv_idx, 0);
1703 parmp->vert_windows = TRUE;
1704#endif
1705 break;
1706
1707#ifdef FEAT_QUICKFIX
1708 case 'q': /* "-q" QuickFix mode */
1709 if (parmp->edit_type != EDIT_NONE)
1710 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
1711 parmp->edit_type = EDIT_QF;
1712 if (argv[0][argv_idx]) /* "-q{errorfile}" */
1713 {
1714 parmp->use_ef = (char_u *)argv[0] + argv_idx;
1715 argv_idx = -1;
1716 }
1717 else if (argc > 1) /* "-q {errorfile}" */
1718 want_argument = TRUE;
1719 break;
1720#endif
1721
1722 case 'R': /* "-R" readonly mode */
1723 readonlymode = TRUE;
1724 curbuf->b_p_ro = TRUE;
1725 p_uc = 10000; /* don't update very often */
1726 break;
1727
1728 case 'r': /* "-r" recovery mode */
1729 case 'L': /* "-L" recovery mode */
1730 recoverymode = 1;
1731 break;
1732
1733 case 's':
1734 if (exmode_active) /* "-s" silent (batch) mode */
1735 silent_mode = TRUE;
1736 else /* "-s {scriptin}" read from script file */
1737 want_argument = TRUE;
1738 break;
1739
1740 case 't': /* "-t {tag}" or "-t{tag}" jump to tag */
1741 if (parmp->edit_type != EDIT_NONE)
1742 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
1743 parmp->edit_type = EDIT_TAG;
1744 if (argv[0][argv_idx]) /* "-t{tag}" */
1745 {
1746 parmp->tagname = (char_u *)argv[0] + argv_idx;
1747 argv_idx = -1;
1748 }
1749 else /* "-t {tag}" */
1750 want_argument = TRUE;
1751 break;
1752
1753#ifdef FEAT_EVAL
1754 case 'D': /* "-D" Debugging */
1755 parmp->use_debug_break_level = 9999;
1756 break;
1757#endif
1758#ifdef FEAT_DIFF
1759 case 'd': /* "-d" 'diff' */
1760# ifdef AMIGA
1761 /* check for "-dev {device}" */
1762 if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
1763 want_argument = TRUE;
1764 else
1765# endif
1766 parmp->diff_mode = TRUE;
1767 break;
1768#endif
1769 case 'V': /* "-V{N}" Verbose level */
1770 /* default is 10: a little bit verbose */
1771 p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10);
1772 if (argv[0][argv_idx] != NUL)
1773 {
1774 set_option_value((char_u *)"verbosefile", 0L,
1775 (char_u *)argv[0] + argv_idx, 0);
1776 argv_idx = STRLEN(argv[0]);
1777 }
1778 break;
1779
1780 case 'v': /* "-v" Vi-mode (as if called "vi") */
1781 exmode_active = 0;
1782#ifdef FEAT_GUI
1783 gui.starting = FALSE; /* don't start GUI */
1784#endif
1785 break;
1786
1787 case 'w': /* "-w{number}" set window height */
1788 /* "-w {scriptout}" write to script */
1789 if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
1790 {
1791 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
1792 set_option_value((char_u *)"window", n, NULL, 0);
1793 break;
1794 }
1795 want_argument = TRUE;
1796 break;
1797
1798#ifdef FEAT_CRYPT
1799 case 'x': /* "-x" encrypted reading/writing of files */
1800 parmp->ask_for_key = TRUE;
1801 break;
1802#endif
1803
1804 case 'X': /* "-X" don't connect to X server */
1805#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
1806 x_no_connect = TRUE;
1807#endif
1808 break;
1809
1810 case 'Z': /* "-Z" restricted mode */
1811 restricted = TRUE;
1812 break;
1813
1814 case 'c': /* "-c{command}" or "-c {command}" execute
1815 command */
1816 if (argv[0][argv_idx] != NUL)
1817 {
1818 if (parmp->n_commands >= MAX_ARG_CMDS)
1819 mainerr(ME_EXTRA_CMD, NULL);
1820 parmp->commands[parmp->n_commands++] = (char_u *)argv[0] + argv_idx;
1821 argv_idx = -1;
1822 break;
1823 }
1824 /*FALLTHROUGH*/
1825 case 'S': /* "-S {file}" execute Vim script */
1826 case 'i': /* "-i {viminfo}" use for viminfo */
1827#ifndef FEAT_DIFF
1828 case 'd': /* "-d {device}" device (for Amiga) */
1829#endif
1830 case 'T': /* "-T {terminal}" terminal name */
1831 case 'u': /* "-u {vimrc}" vim inits file */
1832 case 'U': /* "-U {gvimrc}" gvim inits file */
1833 case 'W': /* "-W {scriptout}" overwrite */
1834#ifdef FEAT_GUI_W32
1835 case 'P': /* "-P {parent title}" MDI parent */
1836#endif
1837 want_argument = TRUE;
1838 break;
1839
1840 default:
1841 mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
1842 }
1843
1844 /*
1845 * Handle option arguments with argument.
1846 */
1847 if (want_argument)
1848 {
1849 /*
1850 * Check for garbage immediately after the option letter.
1851 */
1852 if (argv[0][argv_idx] != NUL)
1853 mainerr(ME_GARBAGE, (char_u *)argv[0]);
1854
1855 --argc;
1856 if (argc < 1 && c != 'S')
1857 mainerr_arg_missing((char_u *)argv[0]);
1858 ++argv;
1859 argv_idx = -1;
1860
1861 switch (c)
1862 {
1863 case 'c': /* "-c {command}" execute command */
1864 case 'S': /* "-S {file}" execute Vim script */
1865 if (parmp->n_commands >= MAX_ARG_CMDS)
1866 mainerr(ME_EXTRA_CMD, NULL);
1867 if (c == 'S')
1868 {
1869 char *a;
1870
1871 if (argc < 1)
1872 /* "-S" without argument: use default session file
1873 * name. */
1874 a = SESSION_FILE;
1875 else if (argv[0][0] == '-')
1876 {
1877 /* "-S" followed by another option: use default
1878 * session file name. */
1879 a = SESSION_FILE;
1880 ++argc;
1881 --argv;
1882 }
1883 else
1884 a = argv[0];
1885 p = alloc((unsigned)(STRLEN(a) + 4));
1886 if (p == NULL)
1887 mch_exit(2);
1888 sprintf((char *)p, "so %s", a);
1889 parmp->cmds_tofree[parmp->n_commands] = TRUE;
1890 parmp->commands[parmp->n_commands++] = p;
1891 }
1892 else
1893 parmp->commands[parmp->n_commands++] = (char_u *)argv[0];
1894 break;
1895
1896 case '-': /* "--cmd {command}" execute command */
1897 if (parmp->n_pre_commands >= MAX_ARG_CMDS)
1898 mainerr(ME_EXTRA_CMD, NULL);
1899 parmp->pre_commands[parmp->n_pre_commands++] = (char_u *)argv[0];
1900 break;
1901
1902 /* case 'd': -d {device} is handled in mch_check_win() for the
1903 * Amiga */
1904
1905#ifdef FEAT_QUICKFIX
1906 case 'q': /* "-q {errorfile}" QuickFix mode */
1907 parmp->use_ef = (char_u *)argv[0];
1908 break;
1909#endif
1910
1911 case 'i': /* "-i {viminfo}" use for viminfo */
1912 use_viminfo = (char_u *)argv[0];
1913 break;
1914
1915 case 's': /* "-s {scriptin}" read from script file */
1916 if (scriptin[0] != NULL)
1917 {
1918scripterror:
1919 mch_errmsg(_("Attempt to open script file again: \""));
1920 mch_errmsg(argv[-1]);
1921 mch_errmsg(" ");
1922 mch_errmsg(argv[0]);
1923 mch_errmsg("\"\n");
1924 mch_exit(2);
1925 }
1926 if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
1927 {
1928 mch_errmsg(_("Cannot open for reading: \""));
1929 mch_errmsg(argv[0]);
1930 mch_errmsg("\"\n");
1931 mch_exit(2);
1932 }
1933 if (save_typebuf() == FAIL)
1934 mch_exit(2); /* out of memory */
1935 break;
1936
1937 case 't': /* "-t {tag}" */
1938 parmp->tagname = (char_u *)argv[0];
1939 break;
1940
1941 case 'T': /* "-T {terminal}" terminal name */
1942 /*
1943 * The -T term argument is always available and when
1944 * HAVE_TERMLIB is supported it overrides the environment
1945 * variable TERM.
1946 */
1947#ifdef FEAT_GUI
1948 if (term_is_gui((char_u *)argv[0]))
1949 gui.starting = TRUE; /* start GUI a bit later */
1950 else
1951#endif
1952 parmp->term = (char_u *)argv[0];
1953 break;
1954
1955 case 'u': /* "-u {vimrc}" vim inits file */
1956 parmp->use_vimrc = (char_u *)argv[0];
1957 break;
1958
1959 case 'U': /* "-U {gvimrc}" gvim inits file */
1960#ifdef FEAT_GUI
1961 use_gvimrc = (char_u *)argv[0];
1962#endif
1963 break;
1964
1965 case 'w': /* "-w {nr}" 'window' value */
1966 /* "-w {scriptout}" append to script file */
1967 if (vim_isdigit(*((char_u *)argv[0])))
1968 {
1969 argv_idx = 0;
1970 n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
1971 set_option_value((char_u *)"window", n, NULL, 0);
1972 argv_idx = -1;
1973 break;
1974 }
1975 /*FALLTHROUGH*/
1976 case 'W': /* "-W {scriptout}" overwrite script file */
1977 if (scriptout != NULL)
1978 goto scripterror;
1979 if ((scriptout = mch_fopen(argv[0],
1980 c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
1981 {
1982 mch_errmsg(_("Cannot open for script output: \""));
1983 mch_errmsg(argv[0]);
1984 mch_errmsg("\"\n");
1985 mch_exit(2);
1986 }
1987 break;
1988
1989#ifdef FEAT_GUI_W32
1990 case 'P': /* "-P {parent title}" MDI parent */
1991 gui_mch_set_parent(argv[0]);
1992 break;
1993#endif
1994 }
1995 }
1996 }
1997
1998 /*
1999 * File name argument.
2000 */
2001 else
2002 {
2003 argv_idx = -1; /* skip to next argument */
2004
2005 /* Check for only one type of editing. */
2006 if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
2007 mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
2008 parmp->edit_type = EDIT_FILE;
2009
2010#ifdef MSWIN
2011 /* Remember if the argument was a full path before changing
2012 * slashes to backslashes. */
2013 if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
2014 parmp->full_path = TRUE;
2015#endif
2016
2017 /* Add the file to the global argument list. */
2018 if (ga_grow(&global_alist.al_ga, 1) == FAIL
2019 || (p = vim_strsave((char_u *)argv[0])) == NULL)
2020 mch_exit(2);
2021#ifdef FEAT_DIFF
2022 if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
2023 && !mch_isdir(alist_name(&GARGLIST[0])))
2024 {
2025 char_u *r;
2026
2027 r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
2028 if (r != NULL)
2029 {
2030 vim_free(p);
2031 p = r;
2032 }
2033 }
2034#endif
2035#if defined(__CYGWIN32__) && !defined(WIN32)
2036 /*
2037 * If vim is invoked by non-Cygwin tools, convert away any
2038 * DOS paths, so things like .swp files are created correctly.
2039 * Look for evidence of non-Cygwin paths before we bother.
2040 * This is only for when using the Unix files.
2041 */
2042 if (strpbrk(p, "\\:") != NULL)
2043 {
2044 char posix_path[PATH_MAX];
2045
2046 cygwin_conv_to_posix_path(p, posix_path);
2047 vim_free(p);
2048 p = vim_strsave(posix_path);
2049 if (p == NULL)
2050 mch_exit(2);
2051 }
2052#endif
2053 alist_add(&global_alist, p,
2054#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
2055 parmp->literal ? 2 : 0 /* add buffer number after expanding */
2056#else
2057 2 /* add buffer number now and use curbuf */
2058#endif
2059 );
2060
2061#if defined(FEAT_MBYTE) && defined(WIN32)
2062 {
2063 extern void used_file_arg(char *, int, int);
2064
2065 /* Remember this argument has been added to the argument list.
2066 * Needed when 'encoding' is changed. */
2067 used_file_arg(argv[0], parmp->literal, parmp->full_path);
2068 }
2069#endif
2070 }
2071
2072 /*
2073 * If there are no more letters after the current "-", go to next
2074 * argument. argv_idx is set to -1 when the current argument is to be
2075 * skipped.
2076 */
2077 if (argv_idx <= 0 || argv[0][argv_idx] == NUL)
2078 {
2079 --argc;
2080 ++argv;
2081 argv_idx = 1;
2082 }
2083 }
2084}
2085
2086/*
2087 * Print a warning if stdout is not a terminal.
2088 * When starting in Ex mode and commands come from a file, set Silent mode.
2089 */
2090 static void
2091check_tty(parmp)
2092 mparm_T *parmp;
2093{
2094 int input_isatty; /* is active input a terminal? */
2095
2096 input_isatty = mch_input_isatty();
2097 if (exmode_active)
2098 {
2099 if (!input_isatty)
2100 silent_mode = TRUE;
2101 }
2102 else if (parmp->want_full_screen && (!parmp->stdout_isatty || !input_isatty)
2103#ifdef FEAT_GUI
2104 /* don't want the delay when started from the desktop */
2105 && !gui.starting
2106#endif
2107 )
2108 {
2109#ifdef NBDEBUG
2110 /*
2111 * This shouldn't be necessary. But if I run netbeans with the log
2112 * output coming to the console and XOpenDisplay fails, I get vim
2113 * trying to start with input/output to my console tty. This fills my
2114 * input buffer so fast I can't even kill the process in under 2
2115 * minutes (and it beeps continuosly the whole time :-)
2116 */
2117 if (usingNetbeans && (!parmp->stdout_isatty || !input_isatty))
2118 {
2119 mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
2120 exit(1);
2121 }
2122#endif
2123 if (!parmp->stdout_isatty)
2124 mch_errmsg(_("Vim: Warning: Output is not to a terminal\n"));
2125 if (!input_isatty)
2126 mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
2127 out_flush();
2128 if (scriptin[0] == NULL)
2129 ui_delay(2000L, TRUE);
2130 TIME_MSG("Warning delay");
2131 }
2132}
2133
2134/*
2135 * Read text from stdin.
2136 */
2137 static void
2138read_stdin()
2139{
2140 int i;
2141
2142#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2143 /* When getting the ATTENTION prompt here, use a dialog */
2144 swap_exists_action = SEA_DIALOG;
2145#endif
2146 no_wait_return = TRUE;
2147 i = msg_didany;
2148 set_buflisted(TRUE);
2149 (void)open_buffer(TRUE, NULL); /* create memfile and read file */
2150 no_wait_return = FALSE;
2151 msg_didany = i;
2152 TIME_MSG("reading stdin");
2153#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2154 check_swap_exists_action();
2155#endif
2156#if !(defined(AMIGA) || defined(MACOS))
2157 /*
2158 * Close stdin and dup it from stderr. Required for GPM to work
2159 * properly, and for running external commands.
2160 * Is there any other system that cannot do this?
2161 */
2162 close(0);
2163 dup(2);
2164#endif
2165}
2166
2167/*
2168 * Create the requested number of windows and edit buffers in them.
2169 * Also does recovery if "recoverymode" set.
2170 */
2171/*ARGSUSED*/
2172 static void
2173create_windows(parmp)
2174 mparm_T *parmp;
2175{
2176#ifdef FEAT_WINDOWS
2177 /*
2178 * Create the number of windows that was requested.
2179 */
2180 if (parmp->window_count == -1) /* was not set */
2181 parmp->window_count = 1;
2182 if (parmp->window_count == 0)
2183 parmp->window_count = GARGCOUNT;
2184 if (parmp->window_count > 1)
2185 {
2186 /* Don't change the windows if there was a command in .vimrc that
2187 * already split some windows */
2188 if (parmp->vert_windows == MAYBE)
2189 parmp->vert_windows = FALSE;
2190 if (firstwin->w_next == NULL)
2191 {
2192 parmp->window_count = make_windows(parmp->window_count,
2193 parmp->vert_windows);
2194 TIME_MSG("making windows");
2195 }
2196 else
2197 parmp->window_count = win_count();
2198 }
2199 else
2200 parmp->window_count = 1;
2201#endif
2202
2203 if (recoverymode) /* do recover */
2204 {
2205 msg_scroll = TRUE; /* scroll message up */
2206 ml_recover();
2207 if (curbuf->b_ml.ml_mfp == NULL) /* failed */
2208 getout(1);
2209 do_modelines(FALSE); /* do modelines */
2210 }
2211 else
2212 {
2213 /*
2214 * Open a buffer for windows that don't have one yet.
2215 * Commands in the .vimrc might have loaded a file or split the window.
2216 * Watch out for autocommands that delete a window.
2217 */
2218#ifdef FEAT_AUTOCMD
2219 /*
2220 * Don't execute Win/Buf Enter/Leave autocommands here
2221 */
2222 ++autocmd_no_enter;
2223 ++autocmd_no_leave;
2224#endif
2225#ifdef FEAT_WINDOWS
2226 for (curwin = firstwin; curwin != NULL; curwin = W_NEXT(curwin))
2227#endif
2228 {
2229 curbuf = curwin->w_buffer;
2230 if (curbuf->b_ml.ml_mfp == NULL)
2231 {
2232#ifdef FEAT_FOLDING
2233 /* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
2234 if (p_fdls >= 0)
2235 curwin->w_p_fdl = p_fdls;
2236#endif
2237#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2238 /* When getting the ATTENTION prompt here, use a dialog */
2239 swap_exists_action = SEA_DIALOG;
2240#endif
2241 set_buflisted(TRUE);
2242 (void)open_buffer(FALSE, NULL); /* create memfile, read file */
2243
2244#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2245 check_swap_exists_action();
2246#endif
2247#ifdef FEAT_AUTOCMD
2248 curwin = firstwin; /* start again */
2249#endif
2250 }
2251#ifdef FEAT_WINDOWS
2252 ui_breakcheck();
2253 if (got_int)
2254 {
2255 (void)vgetc(); /* only break the file loading, not the rest */
2256 break;
2257 }
2258#endif
2259 }
2260#ifdef FEAT_AUTOCMD
2261 --autocmd_no_enter;
2262 --autocmd_no_leave;
2263#endif
2264#ifdef FEAT_WINDOWS
2265 curwin = firstwin;
2266 curbuf = curwin->w_buffer;
2267#endif
2268 }
2269}
2270
2271#ifdef FEAT_WINDOWS
2272 /*
2273 * If opened more than one window, start editing files in the other
2274 * windows. make_windows() has already opened the windows.
2275 */
2276 static void
2277edit_buffers(parmp)
2278 mparm_T *parmp;
2279{
2280 int arg_idx; /* index in argument list */
2281 int i;
2282
2283# ifdef FEAT_AUTOCMD
2284 /*
2285 * Don't execute Win/Buf Enter/Leave autocommands here
2286 */
2287 ++autocmd_no_enter;
2288 ++autocmd_no_leave;
2289# endif
2290 arg_idx = 1;
2291 for (i = 1; i < parmp->window_count; ++i)
2292 {
2293 if (curwin->w_next == NULL) /* just checking */
2294 break;
2295 win_enter(curwin->w_next, FALSE);
2296
2297 /* Only open the file if there is no file in this window yet (that can
2298 * happen when .vimrc contains ":sall") */
2299 if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL)
2300 {
2301 curwin->w_arg_idx = arg_idx;
2302 /* edit file from arg list, if there is one */
2303 (void)do_ecmd(0, arg_idx < GARGCOUNT
2304 ? alist_name(&GARGLIST[arg_idx]) : NULL,
2305 NULL, NULL, ECMD_LASTL, ECMD_HIDE);
2306 if (arg_idx == GARGCOUNT - 1)
2307 arg_had_last = TRUE;
2308 ++arg_idx;
2309 }
2310 ui_breakcheck();
2311 if (got_int)
2312 {
2313 (void)vgetc(); /* only break the file loading, not the rest */
2314 break;
2315 }
2316 }
2317# ifdef FEAT_AUTOCMD
2318 --autocmd_no_enter;
2319# endif
2320 win_enter(firstwin, FALSE); /* back to first window */
2321# ifdef FEAT_AUTOCMD
2322 --autocmd_no_leave;
2323# endif
2324 TIME_MSG("editing files in windows");
2325 if (parmp->window_count > 1)
2326 win_equal(curwin, FALSE, 'b'); /* adjust heights */
2327}
2328#endif /* FEAT_WINDOWS */
2329
2330/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00002331 * Execute the commands from --cmd arguments "cmds[cnt]".
2332 */
2333 static void
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002334exe_pre_commands(parmp)
2335 mparm_T *parmp;
Bram Moolenaar58d98232005-07-23 22:25:46 +00002336{
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002337 char_u **cmds = parmp->pre_commands;
2338 int cnt = parmp->n_pre_commands;
Bram Moolenaar58d98232005-07-23 22:25:46 +00002339 int i;
2340
2341 if (cnt > 0)
2342 {
2343 curwin->w_cursor.lnum = 0; /* just in case.. */
2344 sourcing_name = (char_u *)_("pre-vimrc command line");
2345# ifdef FEAT_EVAL
2346 current_SID = SID_CMDARG;
2347# endif
2348 for (i = 0; i < cnt; ++i)
2349 do_cmdline_cmd(cmds[i]);
2350 sourcing_name = NULL;
2351# ifdef FEAT_EVAL
2352 current_SID = 0;
2353# endif
2354 TIME_MSG("--cmd commands");
2355 }
2356}
2357
2358/*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002359 * Execute "+", "-c" and "-S" arguments.
2360 */
2361 static void
2362exe_commands(parmp)
2363 mparm_T *parmp;
2364{
2365 int i;
2366
2367 /*
2368 * We start commands on line 0, make "vim +/pat file" match a
2369 * pattern on line 1. But don't move the cursor when an autocommand
2370 * with g`" was used.
2371 */
2372 msg_scroll = TRUE;
2373 if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
2374 curwin->w_cursor.lnum = 0;
2375 sourcing_name = (char_u *)"command line";
2376#ifdef FEAT_EVAL
2377 current_SID = SID_CARG;
2378#endif
2379 for (i = 0; i < parmp->n_commands; ++i)
2380 {
2381 do_cmdline_cmd(parmp->commands[i]);
2382 if (parmp->cmds_tofree[i])
2383 vim_free(parmp->commands[i]);
2384 }
2385 sourcing_name = NULL;
2386#ifdef FEAT_EVAL
2387 current_SID = 0;
2388#endif
2389 if (curwin->w_cursor.lnum == 0)
2390 curwin->w_cursor.lnum = 1;
2391
2392 if (!exmode_active)
2393 msg_scroll = FALSE;
2394
2395#ifdef FEAT_QUICKFIX
2396 /* When started with "-q errorfile" jump to first error again. */
2397 if (parmp->edit_type == EDIT_QF)
2398 qf_jump(0, 0, FALSE);
2399#endif
2400 TIME_MSG("executing command arguments");
2401}
2402
2403/*
Bram Moolenaar58d98232005-07-23 22:25:46 +00002404 * Source startup scripts.
2405 */
2406 static void
2407source_startup_scripts(parmp)
2408 mparm_T *parmp;
2409{
2410 int i;
2411
2412 /*
2413 * For "evim" source evim.vim first of all, so that the user can overrule
2414 * any things he doesn't like.
2415 */
2416 if (parmp->evim_mode)
2417 {
2418 (void)do_source((char_u *)EVIM_FILE, FALSE, FALSE);
2419 TIME_MSG("source evim file");
2420 }
2421
2422 /*
Bram Moolenaarc013cb62005-07-24 21:18:31 +00002423 * If -u argument given, use only the initializations from that file and
Bram Moolenaar58d98232005-07-23 22:25:46 +00002424 * nothing else.
2425 */
2426 if (parmp->use_vimrc != NULL)
2427 {
2428 if (STRCMP(parmp->use_vimrc, "NONE") == 0 || STRCMP(parmp->use_vimrc, "NORC") == 0)
2429 {
2430#ifdef FEAT_GUI
2431 if (use_gvimrc == NULL) /* don't load gvimrc either */
2432 use_gvimrc = parmp->use_vimrc;
2433#endif
2434 if (parmp->use_vimrc[2] == 'N')
2435 p_lpl = FALSE; /* don't load plugins either */
2436 }
2437 else
2438 {
2439 if (do_source(parmp->use_vimrc, FALSE, FALSE) != OK)
2440 EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
2441 }
2442 }
2443 else if (!silent_mode)
2444 {
2445#ifdef AMIGA
2446 struct Process *proc = (struct Process *)FindTask(0L);
2447 APTR save_winptr = proc->pr_WindowPtr;
2448
2449 /* Avoid a requester here for a volume that doesn't exist. */
2450 proc->pr_WindowPtr = (APTR)-1L;
2451#endif
2452
2453 /*
2454 * Get system wide defaults, if the file name is defined.
2455 */
2456#ifdef SYS_VIMRC_FILE
2457 (void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, FALSE);
2458#endif
2459
2460 /*
2461 * Try to read initialization commands from the following places:
2462 * - environment variable VIMINIT
2463 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise)
2464 * - second user vimrc file ($VIM/.vimrc for Dos)
2465 * - environment variable EXINIT
2466 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise)
2467 * - second user exrc file ($VIM/.exrc for Dos)
2468 * The first that exists is used, the rest is ignored.
2469 */
2470 if (process_env((char_u *)"VIMINIT", TRUE) != OK)
2471 {
2472 if (do_source((char_u *)USR_VIMRC_FILE, TRUE, TRUE) == FAIL
2473#ifdef USR_VIMRC_FILE2
2474 && do_source((char_u *)USR_VIMRC_FILE2, TRUE, TRUE) == FAIL
2475#endif
2476#ifdef USR_VIMRC_FILE3
2477 && do_source((char_u *)USR_VIMRC_FILE3, TRUE, TRUE) == FAIL
2478#endif
2479 && process_env((char_u *)"EXINIT", FALSE) == FAIL
2480 && do_source((char_u *)USR_EXRC_FILE, FALSE, FALSE) == FAIL)
2481 {
2482#ifdef USR_EXRC_FILE2
2483 (void)do_source((char_u *)USR_EXRC_FILE2, FALSE, FALSE);
2484#endif
2485 }
2486 }
2487
2488 /*
2489 * Read initialization commands from ".vimrc" or ".exrc" in current
2490 * directory. This is only done if the 'exrc' option is set.
2491 * Because of security reasons we disallow shell and write commands
2492 * now, except for unix if the file is owned by the user or 'secure'
2493 * option has been reset in environment of global ".exrc" or ".vimrc".
2494 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or
2495 * SYS_VIMRC_FILE.
2496 */
2497 if (p_exrc)
2498 {
2499#if defined(UNIX) || defined(VMS)
2500 /* If ".vimrc" file is not owned by user, set 'secure' mode. */
2501 if (!file_owned(VIMRC_FILE))
2502#endif
2503 secure = p_secure;
2504
2505 i = FAIL;
2506 if (fullpathcmp((char_u *)USR_VIMRC_FILE,
2507 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
2508#ifdef USR_VIMRC_FILE2
2509 && fullpathcmp((char_u *)USR_VIMRC_FILE2,
2510 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
2511#endif
2512#ifdef USR_VIMRC_FILE3
2513 && fullpathcmp((char_u *)USR_VIMRC_FILE3,
2514 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
2515#endif
2516#ifdef SYS_VIMRC_FILE
2517 && fullpathcmp((char_u *)SYS_VIMRC_FILE,
2518 (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
2519#endif
2520 )
2521 i = do_source((char_u *)VIMRC_FILE, TRUE, TRUE);
2522
2523 if (i == FAIL)
2524 {
2525#if defined(UNIX) || defined(VMS)
2526 /* if ".exrc" is not owned by user set 'secure' mode */
2527 if (!file_owned(EXRC_FILE))
2528 secure = p_secure;
2529 else
2530 secure = 0;
2531#endif
2532 if ( fullpathcmp((char_u *)USR_EXRC_FILE,
2533 (char_u *)EXRC_FILE, FALSE) != FPC_SAME
2534#ifdef USR_EXRC_FILE2
2535 && fullpathcmp((char_u *)USR_EXRC_FILE2,
2536 (char_u *)EXRC_FILE, FALSE) != FPC_SAME
2537#endif
2538 )
2539 (void)do_source((char_u *)EXRC_FILE, FALSE, FALSE);
2540 }
2541 }
2542 if (secure == 2)
2543 need_wait_return = TRUE;
2544 secure = 0;
2545#ifdef AMIGA
2546 proc->pr_WindowPtr = save_winptr;
2547#endif
2548 }
2549 TIME_MSG("sourcing vimrc file(s)");
2550}
2551
2552/*
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002553 * Setup to start using the GUI. Exit with an error when not available.
2554 */
2555 static void
2556main_start_gui()
2557{
2558#ifdef FEAT_GUI
2559 gui.starting = TRUE; /* start GUI a bit later */
2560#else
2561 mch_errmsg(_(e_nogvim));
2562 mch_errmsg("\n");
2563 mch_exit(2);
2564#endif
2565}
2566
2567/*
2568 * Get an evironment variable, and execute it as Ex commands.
2569 * Returns FAIL if the environment variable was not executed, OK otherwise.
2570 */
2571 int
2572process_env(env, is_viminit)
2573 char_u *env;
2574 int is_viminit; /* when TRUE, called for VIMINIT */
2575{
2576 char_u *initstr;
2577 char_u *save_sourcing_name;
2578 linenr_T save_sourcing_lnum;
2579#ifdef FEAT_EVAL
2580 scid_T save_sid;
2581#endif
2582
2583 if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL)
2584 {
2585 if (is_viminit)
2586 vimrc_found();
2587 save_sourcing_name = sourcing_name;
2588 save_sourcing_lnum = sourcing_lnum;
2589 sourcing_name = env;
2590 sourcing_lnum = 0;
2591#ifdef FEAT_EVAL
2592 save_sid = current_SID;
2593 current_SID = SID_ENV;
2594#endif
2595 do_cmdline_cmd(initstr);
2596 sourcing_name = save_sourcing_name;
2597 sourcing_lnum = save_sourcing_lnum;
2598#ifdef FEAT_EVAL
2599 current_SID = save_sid;;
2600#endif
2601 return OK;
2602 }
2603 return FAIL;
2604}
2605
2606#if defined(UNIX) || defined(VMS)
2607/*
2608 * Return TRUE if we are certain the user owns the file "fname".
2609 * Used for ".vimrc" and ".exrc".
2610 * Use both stat() and lstat() for extra security.
2611 */
2612 static int
2613file_owned(fname)
2614 char *fname;
2615{
2616 struct stat s;
2617# ifdef UNIX
2618 uid_t uid = getuid();
2619# else /* VMS */
2620 uid_t uid = ((getgid() << 16) | getuid());
2621# endif
2622
2623 return !(mch_stat(fname, &s) != 0 || s.st_uid != uid
2624# ifdef HAVE_LSTAT
2625 || mch_lstat(fname, &s) != 0 || s.st_uid != uid
2626# endif
2627 );
2628}
2629#endif
2630
2631/*
2632 * Give an error message main_errors["n"] and exit.
2633 */
2634 static void
2635mainerr(n, str)
2636 int n; /* one of the ME_ defines */
2637 char_u *str; /* extra argument or NULL */
2638{
2639#if defined(UNIX) || defined(__EMX__) || defined(VMS)
2640 reset_signals(); /* kill us with CTRL-C here, if you like */
2641#endif
2642
2643 mch_errmsg(longVersion);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002644 mch_errmsg("\n");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002645 mch_errmsg(_(main_errors[n]));
2646 if (str != NULL)
2647 {
2648 mch_errmsg(": \"");
2649 mch_errmsg((char *)str);
2650 mch_errmsg("\"");
2651 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002652 mch_errmsg(_("\nMore info with: \"vim -h\"\n"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002653
2654 mch_exit(1);
2655}
2656
2657 void
2658mainerr_arg_missing(str)
2659 char_u *str;
2660{
2661 mainerr(ME_ARG_MISSING, str);
2662}
2663
2664/*
2665 * print a message with three spaces prepended and '\n' appended.
2666 */
2667 static void
2668main_msg(s)
2669 char *s;
2670{
2671 mch_msg(" ");
2672 mch_msg(s);
2673 mch_msg("\n");
2674}
2675
2676/*
2677 * Print messages for "vim -h" or "vim --help" and exit.
2678 */
2679 static void
2680usage()
2681{
2682 int i;
2683 static char *(use[]) =
2684 {
2685 N_("[file ..] edit specified file(s)"),
2686 N_("- read text from stdin"),
2687 N_("-t tag edit file where tag is defined"),
2688#ifdef FEAT_QUICKFIX
2689 N_("-q [errorfile] edit file with first error")
2690#endif
2691 };
2692
2693#if defined(UNIX) || defined(__EMX__) || defined(VMS)
2694 reset_signals(); /* kill us with CTRL-C here, if you like */
2695#endif
2696
2697 mch_msg(longVersion);
2698 mch_msg(_("\n\nusage:"));
2699 for (i = 0; ; ++i)
2700 {
2701 mch_msg(_(" vim [arguments] "));
2702 mch_msg(_(use[i]));
2703 if (i == (sizeof(use) / sizeof(char_u *)) - 1)
2704 break;
2705 mch_msg(_("\n or:"));
2706 }
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002707#ifdef VMS
2708 mch_msg(_("where case is ignored prepend / to make flag upper case"));
2709#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002710
2711 mch_msg(_("\n\nArguments:\n"));
2712 main_msg(_("--\t\t\tOnly file names after this"));
2713#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
2714 main_msg(_("--literal\t\tDon't expand wildcards"));
2715#endif
2716#ifdef FEAT_OLE
2717 main_msg(_("-register\t\tRegister this gvim for OLE"));
2718 main_msg(_("-unregister\t\tUnregister gvim for OLE"));
2719#endif
2720#ifdef FEAT_GUI
2721 main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")"));
2722 main_msg(_("-f or --nofork\tForeground: Don't fork when starting GUI"));
2723#endif
2724 main_msg(_("-v\t\t\tVi mode (like \"vi\")"));
2725 main_msg(_("-e\t\t\tEx mode (like \"ex\")"));
2726 main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")"));
2727#ifdef FEAT_DIFF
2728 main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")"));
2729#endif
2730 main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)"));
2731 main_msg(_("-R\t\t\tReadonly mode (like \"view\")"));
2732 main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")"));
2733 main_msg(_("-m\t\t\tModifications (writing files) not allowed"));
2734 main_msg(_("-M\t\t\tModifications in text not allowed"));
2735 main_msg(_("-b\t\t\tBinary mode"));
2736#ifdef FEAT_LISP
2737 main_msg(_("-l\t\t\tLisp mode"));
2738#endif
2739 main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'"));
2740 main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'"));
2741 main_msg(_("-V[N]\t\tVerbose level"));
2742 main_msg(_("-D\t\t\tDebugging mode"));
2743 main_msg(_("-n\t\t\tNo swap file, use memory only"));
2744 main_msg(_("-r\t\t\tList swap files and exit"));
2745 main_msg(_("-r (with file name)\tRecover crashed session"));
2746 main_msg(_("-L\t\t\tSame as -r"));
2747#ifdef AMIGA
2748 main_msg(_("-f\t\t\tDon't use newcli to open window"));
2749 main_msg(_("-dev <device>\t\tUse <device> for I/O"));
2750#endif
2751#ifdef FEAT_ARABIC
2752 main_msg(_("-A\t\t\tstart in Arabic mode"));
2753#endif
2754#ifdef FEAT_RIGHTLEFT
2755 main_msg(_("-H\t\t\tStart in Hebrew mode"));
2756#endif
2757#ifdef FEAT_FKMAP
2758 main_msg(_("-F\t\t\tStart in Farsi mode"));
2759#endif
2760 main_msg(_("-T <terminal>\tSet terminal type to <terminal>"));
2761 main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"));
2762#ifdef FEAT_GUI
2763 main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"));
2764#endif
2765 main_msg(_("--noplugin\t\tDon't load plugin scripts"));
2766 main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)"));
2767 main_msg(_("-O[N]\t\tLike -o but split vertically"));
2768 main_msg(_("+\t\t\tStart at end of file"));
2769 main_msg(_("+<lnum>\t\tStart at line <lnum>"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002770 main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file"));
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002771 main_msg(_("-c <command>\t\tExecute <command> after loading the first file"));
2772 main_msg(_("-S <session>\t\tSource file <session> after loading the first file"));
2773 main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>"));
2774 main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>"));
2775 main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>"));
2776#ifdef FEAT_CRYPT
2777 main_msg(_("-x\t\t\tEdit encrypted files"));
2778#endif
2779#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
2780# if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)
2781 main_msg(_("-display <display>\tConnect vim to this particular X-server"));
2782# endif
2783 main_msg(_("-X\t\t\tDo not connect to X server"));
2784#endif
2785#ifdef FEAT_CLIENTSERVER
2786 main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible"));
2787 main_msg(_("--remote-silent <files> Same, don't complain if there is no server"));
2788 main_msg(_("--remote-wait <files> As --remote but wait for files to have been edited"));
2789 main_msg(_("--remote-wait-silent <files> Same, don't complain if there is no server"));
2790 main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit"));
2791 main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"));
2792 main_msg(_("--serverlist\t\tList available Vim server names and exit"));
2793 main_msg(_("--servername <name>\tSend to/become the Vim server <name>"));
2794#endif
2795#ifdef FEAT_VIMINFO
2796 main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo"));
2797#endif
2798 main_msg(_("-h or --help\tPrint Help (this message) and exit"));
2799 main_msg(_("--version\t\tPrint version information and exit"));
2800
2801#ifdef FEAT_GUI_X11
2802# ifdef FEAT_GUI_MOTIF
2803 mch_msg(_("\nArguments recognised by gvim (Motif version):\n"));
2804# else
2805# ifdef FEAT_GUI_ATHENA
2806# ifdef FEAT_GUI_NEXTAW
2807 mch_msg(_("\nArguments recognised by gvim (neXtaw version):\n"));
2808# else
2809 mch_msg(_("\nArguments recognised by gvim (Athena version):\n"));
2810# endif
2811# endif
2812# endif
2813 main_msg(_("-display <display>\tRun vim on <display>"));
2814 main_msg(_("-iconic\t\tStart vim iconified"));
2815# if 0
2816 main_msg(_("-name <name>\t\tUse resource as if vim was <name>"));
2817 mch_msg(_("\t\t\t (Unimplemented)\n"));
2818# endif
2819 main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
2820 main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
2821 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
2822 main_msg(_("-boldfont <font>\tUse <font> for bold text"));
2823 main_msg(_("-italicfont <font>\tUse <font> for italic text"));
2824 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
2825 main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)"));
2826 main_msg(_("-scrollbarwidth <width> Use a scrollbar width of <width> (also: -sw)"));
2827# ifdef FEAT_GUI_ATHENA
2828 main_msg(_("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"));
2829# endif
2830 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
2831 main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)"));
2832 main_msg(_("-xrm <resource>\tSet the specified resource"));
2833#endif /* FEAT_GUI_X11 */
2834#if defined(FEAT_GUI) && defined(RISCOS)
2835 mch_msg(_("\nArguments recognised by gvim (RISC OS version):\n"));
2836 main_msg(_("--columns <number>\tInitial width of window in columns"));
2837 main_msg(_("--rows <number>\tInitial height of window in rows"));
2838#endif
2839#ifdef FEAT_GUI_GTK
2840 mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
2841 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
2842 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
2843 main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
2844 main_msg(_("-display <display>\tRun vim on <display> (also: --display)"));
2845# ifdef HAVE_GTK2
2846 main_msg(_("--role <role>\tSet a unique role to identify the main window"));
2847# endif
2848 main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget"));
2849#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00002850#ifdef FEAT_GUI_KDE
2851 mch_msg(_("\nArguments recognised by kvim (KDE version):\n"));
2852 main_msg(_("-black\t\tUse reverse video"));
2853#if QT_VERSION>=300
2854 main_msg(_("-tip\t\t\tDisplay the tip dialog on startup"));
2855 main_msg(_("-notip\t\tDisable the tip dialog"));
2856#endif
2857 main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
2858 main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
2859 main_msg(_("--display <display>\tRun vim on <display>"));
2860#endif
Bram Moolenaarb4210b32004-06-13 14:51:16 +00002861#ifdef FEAT_GUI_W32
2862 main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
2863#endif
2864
2865#ifdef FEAT_GUI_GNOME
2866 /* Gnome gives extra messages for --help if we continue, but not for -h. */
2867 if (gui.starting)
2868 mch_msg("\n");
2869 else
2870#endif
2871 mch_exit(0);
2872}
2873
2874#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2875/*
2876 * Check the result of the ATTENTION dialog:
2877 * When "Quit" selected, exit Vim.
2878 * When "Recover" selected, recover the file.
2879 */
2880 static void
2881check_swap_exists_action()
2882{
2883 if (swap_exists_action == SEA_QUIT)
2884 getout(1);
2885 handle_swap_exists(NULL);
2886}
2887#endif
2888
2889#if defined(STARTUPTIME) || defined(PROTO)
2890static void time_diff __ARGS((struct timeval *then, struct timeval *now));
2891
2892static struct timeval prev_timeval;
2893
2894/*
2895 * Save the previous time before doing something that could nest.
2896 * set "*tv_rel" to the time elapsed so far.
2897 */
2898 void
2899time_push(tv_rel, tv_start)
2900 void *tv_rel, *tv_start;
2901{
2902 *((struct timeval *)tv_rel) = prev_timeval;
2903 gettimeofday(&prev_timeval, NULL);
2904 ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec
2905 - ((struct timeval *)tv_rel)->tv_usec;
2906 ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec
2907 - ((struct timeval *)tv_rel)->tv_sec;
2908 if (((struct timeval *)tv_rel)->tv_usec < 0)
2909 {
2910 ((struct timeval *)tv_rel)->tv_usec += 1000000;
2911 --((struct timeval *)tv_rel)->tv_sec;
2912 }
2913 *(struct timeval *)tv_start = prev_timeval;
2914}
2915
2916/*
2917 * Compute the previous time after doing something that could nest.
2918 * Subtract "*tp" from prev_timeval;
2919 * Note: The arguments are (void *) to avoid trouble with systems that don't
2920 * have struct timeval.
2921 */
2922 void
2923time_pop(tp)
2924 void *tp; /* actually (struct timeval *) */
2925{
2926 prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec;
2927 prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec;
2928 if (prev_timeval.tv_usec < 0)
2929 {
2930 prev_timeval.tv_usec += 1000000;
2931 --prev_timeval.tv_sec;
2932 }
2933}
2934
2935 static void
2936time_diff(then, now)
2937 struct timeval *then;
2938 struct timeval *now;
2939{
2940 long usec;
2941 long msec;
2942
2943 usec = now->tv_usec - then->tv_usec;
2944 msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L,
2945 usec = usec % 1000L;
2946 fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L);
2947}
2948
2949 void
2950time_msg(msg, tv_start)
2951 char *msg;
2952 void *tv_start; /* only for do_source: start time; actually
2953 (struct timeval *) */
2954{
2955 static struct timeval start;
2956 struct timeval now;
2957
2958 if (time_fd != NULL)
2959 {
2960 if (strstr(msg, "STARTING") != NULL)
2961 {
2962 gettimeofday(&start, NULL);
2963 prev_timeval = start;
2964 fprintf(time_fd, "\n\ntimes in msec\n");
2965 fprintf(time_fd, " clock self+sourced self: sourced script\n");
2966 fprintf(time_fd, " clock elapsed: other lines\n\n");
2967 }
2968 gettimeofday(&now, NULL);
2969 time_diff(&start, &now);
2970 if (((struct timeval *)tv_start) != NULL)
2971 {
2972 fprintf(time_fd, " ");
2973 time_diff(((struct timeval *)tv_start), &now);
2974 }
2975 fprintf(time_fd, " ");
2976 time_diff(&prev_timeval, &now);
2977 prev_timeval = now;
2978 fprintf(time_fd, ": %s\n", msg);
2979 }
2980}
2981
2982# ifdef WIN3264
2983/*
2984 * Windows doesn't have gettimeofday(), although it does have struct timeval.
2985 */
2986 int
2987gettimeofday(struct timeval *tv, char *dummy)
2988{
2989 long t = clock();
2990 tv->tv_sec = t / CLOCKS_PER_SEC;
2991 tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC;
2992 return 0;
2993}
2994# endif
2995
2996#endif
2997
2998#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
2999
3000/*
3001 * Common code for the X command server and the Win32 command server.
3002 */
3003
3004static char_u *build_drop_cmd __ARGS((int filec, char **filev, int sendReply));
3005
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003006/*
3007 * Do the client-server stuff, unless "--servername ''" was used.
3008 */
3009 static void
3010exec_on_server(parmp)
3011 mparm_T *parmp;
3012{
3013 if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL)
3014 {
3015# ifdef WIN32
3016 /* Initialise the client/server messaging infrastructure. */
3017 serverInitMessaging();
3018# endif
3019
3020 /*
3021 * When a command server argument was found, execute it. This may
3022 * exit Vim when it was successful. Otherwise it's executed further
3023 * on. Remember the encoding used here in "serverStrEnc".
3024 */
3025 if (parmp->serverArg)
3026 {
3027 cmdsrv_main(&parmp->argc, parmp->argv,
3028 parmp->serverName_arg, &parmp->serverStr);
3029# ifdef FEAT_MBYTE
3030 parmp->serverStrEnc = vim_strsave(p_enc);
3031# endif
3032 }
3033
3034 /* If we're still running, get the name to register ourselves.
3035 * On Win32 can register right now, for X11 need to setup the
3036 * clipboard first, it's further down. */
3037 parmp->servername = serverMakeName(parmp->serverName_arg,
3038 parmp->argv[0]);
3039# ifdef WIN32
3040 if (parmp->servername != NULL)
3041 {
3042 serverSetName(parmp->servername);
3043 vim_free(parmp->servername);
3044 }
3045# endif
3046 }
3047}
3048
3049/*
3050 * Prepare for running as a Vim server.
3051 */
3052 static void
3053prepare_server(parmp)
3054 mparm_T *parmp;
3055{
3056# if defined(FEAT_X11)
3057 /*
3058 * Register for remote command execution with :serversend and --remote
3059 * unless there was a -X or a --servername '' on the command line.
3060 * Only register nongui-vim's with an explicit --servername argument.
3061 */
3062 if (X_DISPLAY != NULL && parmp->servername != NULL && (
3063# ifdef FEAT_GUI
3064 gui.in_use ||
3065# endif
3066 parmp->serverName_arg != NULL))
3067 {
3068 (void)serverRegisterName(X_DISPLAY, parmp->servername);
3069 vim_free(parmp->servername);
3070 TIME_MSG("register server name");
3071 }
3072 else
3073 serverDelayedStartName = parmp->servername;
3074# endif
3075
3076 /*
3077 * Execute command ourselves if we're here because the send failed (or
3078 * else we would have exited above).
3079 */
3080 if (parmp->serverStr != NULL)
3081 {
3082 char_u *p;
3083
3084 server_to_input_buf(serverConvert(parmp->serverStrEnc,
3085 parmp->serverStr, &p));
3086 vim_free(p);
3087 }
3088}
3089
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003090 static void
3091cmdsrv_main(argc, argv, serverName_arg, serverStr)
3092 int *argc;
3093 char **argv;
3094 char_u *serverName_arg;
3095 char_u **serverStr;
3096{
3097 char_u *res;
3098 int i;
3099 char_u *sname;
3100 int ret;
3101 int didone = FALSE;
3102 int exiterr = 0;
3103 char **newArgV = argv + 1;
3104 int newArgC = 1,
3105 Argc = *argc;
3106 int argtype;
3107#define ARGTYPE_OTHER 0
3108#define ARGTYPE_EDIT 1
3109#define ARGTYPE_EDIT_WAIT 2
3110#define ARGTYPE_SEND 3
3111 int silent = FALSE;
3112# ifndef FEAT_X11
3113 HWND srv;
3114# else
3115 Window srv;
3116
3117 setup_term_clip();
3118# endif
3119
3120 sname = serverMakeName(serverName_arg, argv[0]);
3121 if (sname == NULL)
3122 return;
3123
3124 /*
3125 * Execute the command server related arguments and remove them
3126 * from the argc/argv array; We may have to return into main()
3127 */
3128 for (i = 1; i < Argc; i++)
3129 {
3130 res = NULL;
Bram Moolenaarc013cb62005-07-24 21:18:31 +00003131 if (STRCMP(argv[i], "--") == 0) /* end of option arguments */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003132 {
3133 for (; i < *argc; i++)
3134 {
3135 *newArgV++ = argv[i];
3136 newArgC++;
3137 }
3138 break;
3139 }
3140
3141 if (STRICMP(argv[i], "--remote") == 0)
3142 argtype = ARGTYPE_EDIT;
3143 else if (STRICMP(argv[i], "--remote-silent") == 0)
3144 {
3145 argtype = ARGTYPE_EDIT;
3146 silent = TRUE;
3147 }
3148 else if (STRICMP(argv[i], "--remote-wait") == 0)
3149 argtype = ARGTYPE_EDIT_WAIT;
3150 else if (STRICMP(argv[i], "--remote-wait-silent") == 0)
3151 {
3152 argtype = ARGTYPE_EDIT_WAIT;
3153 silent = TRUE;
3154 }
3155 else if (STRICMP(argv[i], "--remote-send") == 0)
3156 argtype = ARGTYPE_SEND;
3157 else
3158 argtype = ARGTYPE_OTHER;
3159 if (argtype != ARGTYPE_OTHER)
3160 {
3161 if (i == *argc - 1)
3162 mainerr_arg_missing((char_u *)argv[i]);
3163 if (argtype == ARGTYPE_SEND)
3164 {
3165 *serverStr = (char_u *)argv[i + 1];
3166 i++;
3167 }
3168 else
3169 {
3170 *serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1,
3171 argtype == ARGTYPE_EDIT_WAIT);
3172 if (*serverStr == NULL)
3173 {
3174 /* Probably out of memory, exit. */
3175 didone = TRUE;
3176 exiterr = 1;
3177 break;
3178 }
3179 Argc = i;
3180 }
3181# ifdef FEAT_X11
3182 if (xterm_dpy == NULL)
3183 {
3184 mch_errmsg(_("No display"));
3185 ret = -1;
3186 }
3187 else
3188 ret = serverSendToVim(xterm_dpy, sname, *serverStr,
3189 NULL, &srv, 0, 0, silent);
3190# else
3191 /* Win32 always works? */
3192 ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, silent);
3193# endif
3194 if (ret < 0)
3195 {
3196 if (argtype == ARGTYPE_SEND)
3197 {
3198 /* Failed to send, abort. */
3199 mch_errmsg(_(": Send failed.\n"));
3200 didone = TRUE;
3201 exiterr = 1;
3202 }
3203 else if (!silent)
3204 /* Let vim start normally. */
3205 mch_errmsg(_(": Send failed. Trying to execute locally\n"));
3206 break;
3207 }
3208
3209# ifdef FEAT_GUI_W32
3210 /* Guess that when the server name starts with "g" it's a GUI
3211 * server, which we can bring to the foreground here.
3212 * Foreground() in the server doesn't work very well. */
3213 if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G')
3214 SetForegroundWindow(srv);
3215# endif
3216
3217 /*
3218 * For --remote-wait: Wait until the server did edit each
3219 * file. Also detect that the server no longer runs.
3220 */
3221 if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT)
3222 {
3223 int numFiles = *argc - i - 1;
3224 int j;
3225 char_u *done = alloc(numFiles);
3226 char_u *p;
3227# ifdef FEAT_GUI_W32
3228 NOTIFYICONDATA ni;
3229 int count = 0;
3230 extern HWND message_window;
3231# endif
3232
3233 if (numFiles > 0 && argv[i + 1][0] == '+')
3234 /* Skip "+cmd" argument, don't wait for it to be edited. */
3235 --numFiles;
3236
3237# ifdef FEAT_GUI_W32
3238 ni.cbSize = sizeof(ni);
3239 ni.hWnd = message_window;
3240 ni.uID = 0;
3241 ni.uFlags = NIF_ICON|NIF_TIP;
3242 ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM");
3243 sprintf(ni.szTip, _("%d of %d edited"), count, numFiles);
3244 Shell_NotifyIcon(NIM_ADD, &ni);
3245# endif
3246
3247 /* Wait for all files to unload in remote */
3248 memset(done, 0, numFiles);
3249 while (memchr(done, 0, numFiles) != NULL)
3250 {
3251# ifdef WIN32
3252 p = serverGetReply(srv, NULL, TRUE, TRUE);
3253 if (p == NULL)
3254 break;
3255# else
3256 if (serverReadReply(xterm_dpy, srv, &p, TRUE) < 0)
3257 break;
3258# endif
3259 j = atoi((char *)p);
3260 if (j >= 0 && j < numFiles)
3261 {
3262# ifdef FEAT_GUI_W32
3263 ++count;
3264 sprintf(ni.szTip, _("%d of %d edited"),
3265 count, numFiles);
3266 Shell_NotifyIcon(NIM_MODIFY, &ni);
3267# endif
3268 done[j] = 1;
3269 }
3270 }
3271# ifdef FEAT_GUI_W32
3272 Shell_NotifyIcon(NIM_DELETE, &ni);
3273# endif
3274 }
3275 }
3276 else if (STRICMP(argv[i], "--remote-expr") == 0)
3277 {
3278 if (i == *argc - 1)
3279 mainerr_arg_missing((char_u *)argv[i]);
3280# ifdef WIN32
3281 /* Win32 always works? */
3282 if (serverSendToVim(sname, (char_u *)argv[i + 1],
3283 &res, NULL, 1, FALSE) < 0)
3284# else
3285 if (xterm_dpy == NULL)
3286 mch_errmsg(_("No display: Send expression failed.\n"));
3287 else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1],
3288 &res, NULL, 1, 1, FALSE) < 0)
3289# endif
3290 {
3291 if (res != NULL && *res != NUL)
3292 {
3293 /* Output error from remote */
3294 mch_errmsg((char *)res);
3295 vim_free(res);
3296 res = NULL;
3297 }
3298 mch_errmsg(_(": Send expression failed.\n"));
3299 }
3300 }
3301 else if (STRICMP(argv[i], "--serverlist") == 0)
3302 {
3303# ifdef WIN32
3304 /* Win32 always works? */
3305 res = serverGetVimNames();
3306# else
3307 if (xterm_dpy != NULL)
3308 res = serverGetVimNames(xterm_dpy);
3309# endif
3310 if (called_emsg)
3311 mch_errmsg("\n");
3312 }
3313 else if (STRICMP(argv[i], "--servername") == 0)
3314 {
3315 /* Alredy processed. Take it out of the command line */
3316 i++;
3317 continue;
3318 }
3319 else
3320 {
3321 *newArgV++ = argv[i];
3322 newArgC++;
3323 continue;
3324 }
3325 didone = TRUE;
3326 if (res != NULL && *res != NUL)
3327 {
3328 mch_msg((char *)res);
3329 if (res[STRLEN(res) - 1] != '\n')
3330 mch_msg("\n");
3331 }
3332 vim_free(res);
3333 }
3334
3335 if (didone)
3336 {
3337 display_errors(); /* display any collected messages */
3338 exit(exiterr); /* Mission accomplished - get out */
3339 }
3340
3341 /* Return back into main() */
3342 *argc = newArgC;
3343 vim_free(sname);
3344}
3345
3346/*
3347 * Build a ":drop" command to send to a Vim server.
3348 */
3349 static char_u *
3350build_drop_cmd(filec, filev, sendReply)
3351 int filec;
3352 char **filev;
3353 int sendReply;
3354{
3355 garray_T ga;
3356 int i;
3357 char_u *inicmd = NULL;
3358 char_u *p;
3359 char_u cwd[MAXPATHL];
3360
3361 if (filec > 0 && filev[0][0] == '+')
3362 {
3363 inicmd = (char_u *)filev[0] + 1;
3364 filev++;
3365 filec--;
3366 }
3367 /* Check if we have at least one argument. */
3368 if (filec <= 0)
3369 mainerr_arg_missing((char_u *)filev[-1]);
3370 if (mch_dirname(cwd, MAXPATHL) != OK)
3371 return NULL;
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00003372 if ((p = vim_strsave_escaped_ext(cwd, PATH_ESC_CHARS, '\\', TRUE)) == NULL)
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003373 return NULL;
3374 ga_init2(&ga, 1, 100);
3375 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
3376 ga_concat(&ga, p);
3377 /* Call inputsave() so that a prompt for an encryption key works. */
3378 ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|drop");
3379 vim_free(p);
3380 for (i = 0; i < filec; i++)
3381 {
3382 /* On Unix the shell has already expanded the wildcards, don't want to
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00003383 * do it again in the Vim server. On MS-Windows only escape
3384 * non-wildcard characters. */
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003385 p = vim_strsave_escaped((char_u *)filev[i],
3386#ifdef UNIX
3387 PATH_ESC_CHARS
3388#else
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00003389 (char_u *)" \t%#"
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003390#endif
3391 );
3392 if (p == NULL)
3393 {
3394 vim_free(ga.ga_data);
3395 return NULL;
3396 }
3397 ga_concat(&ga, (char_u *)" ");
3398 ga_concat(&ga, p);
3399 vim_free(p);
3400 }
3401 /* The :drop commands goes to Insert mode when 'insertmode' is set, use
3402 * CTRL-\ CTRL-N again. */
3403 ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>");
3404 ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd -");
3405 if (sendReply)
3406 ga_concat(&ga, (char_u *)"<CR>:call SetupRemoteReplies()");
3407 ga_concat(&ga, (char_u *)"<CR>:");
3408 if (inicmd != NULL)
3409 {
3410 /* Can't use <CR> after "inicmd", because an "startinsert" would cause
3411 * the following commands to be inserted as text. Use a "|",
3412 * hopefully "inicmd" does allow this... */
3413 ga_concat(&ga, inicmd);
3414 ga_concat(&ga, (char_u *)"|");
3415 }
3416 /* Bring the window to the foreground, goto Insert mode when 'im' set and
3417 * clear command line. */
Bram Moolenaar567e4de2004-12-31 21:01:02 +00003418 ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>");
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003419 ga_append(&ga, NUL);
3420 return ga.ga_data;
3421}
3422
3423/*
3424 * Replace termcodes such as <CR> and insert as key presses if there is room.
3425 */
3426 void
3427server_to_input_buf(str)
3428 char_u *str;
3429{
3430 char_u *ptr = NULL;
3431 char_u *cpo_save = p_cpo;
3432
3433 /* Set 'cpoptions' the way we want it.
3434 * B set - backslashes are *not* treated specially
3435 * k set - keycodes are *not* reverse-engineered
3436 * < unset - <Key> sequences *are* interpreted
3437 * The last parameter of replace_termcodes() is TRUE so that the <lt>
3438 * sequence is recognised - needed for a real backslash.
3439 */
3440 p_cpo = (char_u *)"Bk";
3441 str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE);
3442 p_cpo = cpo_save;
3443
3444 if (*ptr != NUL) /* trailing CTRL-V results in nothing */
3445 {
3446 /*
3447 * Add the string to the input stream.
3448 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
3449 *
3450 * First clear typed characters from the typeahead buffer, there could
3451 * be half a mapping there. Then append to the existing string, so
3452 * that multiple commands from a client are concatenated.
3453 */
3454 if (typebuf.tb_maplen < typebuf.tb_len)
3455 del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
3456 (void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE);
3457
3458 /* Let input_available() know we inserted text in the typeahead
3459 * buffer. */
3460 received_from_client = TRUE;
3461 }
3462 vim_free((char_u *)ptr);
3463}
3464
3465/*
3466 * Evaluate an expression that the client sent to a string.
3467 * Handles disabling error messages and disables debugging, otherwise Vim
3468 * hangs, waiting for "cont" to be typed.
3469 */
3470 char_u *
3471eval_client_expr_to_string(expr)
3472 char_u *expr;
3473{
3474 char_u *res;
3475 int save_dbl = debug_break_level;
3476 int save_ro = redir_off;
3477
3478 debug_break_level = -1;
3479 redir_off = 0;
3480 ++emsg_skip;
3481
3482 res = eval_to_string(expr, NULL);
3483
3484 debug_break_level = save_dbl;
3485 redir_off = save_ro;
3486 --emsg_skip;
3487
3488 return res;
3489}
3490
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003491/*
3492 * If conversion is needed, convert "data" from "client_enc" to 'encoding' and
3493 * return an allocated string. Otherwise return "data".
3494 * "*tofree" is set to the result when it needs to be freed later.
3495 */
3496/*ARGSUSED*/
3497 char_u *
3498serverConvert(client_enc, data, tofree)
3499 char_u *client_enc;
3500 char_u *data;
3501 char_u **tofree;
3502{
3503 char_u *res = data;
3504
3505 *tofree = NULL;
3506# ifdef FEAT_MBYTE
3507 if (client_enc != NULL && p_enc != NULL)
3508 {
3509 vimconv_T vimconv;
3510
3511 vimconv.vc_type = CONV_NONE;
3512 if (convert_setup(&vimconv, client_enc, p_enc) != FAIL
3513 && vimconv.vc_type != CONV_NONE)
3514 {
3515 res = string_convert(&vimconv, data, NULL);
3516 if (res == NULL)
3517 res = data;
3518 else
3519 *tofree = res;
3520 }
3521 convert_setup(&vimconv, NULL, NULL);
3522 }
3523# endif
3524 return res;
3525}
3526
Bram Moolenaarb4210b32004-06-13 14:51:16 +00003527
3528/*
3529 * Make our basic server name: use the specified "arg" if given, otherwise use
3530 * the tail of the command "cmd" we were started with.
3531 * Return the name in allocated memory. This doesn't include a serial number.
3532 */
3533 static char_u *
3534serverMakeName(arg, cmd)
3535 char_u *arg;
3536 char *cmd;
3537{
3538 char_u *p;
3539
3540 if (arg != NULL && *arg != NUL)
3541 p = vim_strsave_up(arg);
3542 else
3543 {
3544 p = vim_strsave_up(gettail((char_u *)cmd));
3545 /* Remove .exe or .bat from the name. */
3546 if (p != NULL && vim_strchr(p, '.') != NULL)
3547 *vim_strchr(p, '.') = NUL;
3548 }
3549 return p;
3550}
3551#endif /* FEAT_CLIENTSERVER */
3552
3553/*
3554 * When FEAT_FKMAP is defined, also compile the Farsi source code.
3555 */
3556#if defined(FEAT_FKMAP) || defined(PROTO)
3557# include "farsi.c"
3558#endif
3559
3560/*
3561 * When FEAT_ARABIC is defined, also compile the Arabic source code.
3562 */
3563#if defined(FEAT_ARABIC) || defined(PROTO)
3564# include "arabic.c"
3565#endif