xref: /vim-8.2.3635/src/ex_docmd.c (revision a6c27c47)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * ex_docmd.c: functions for executing an Ex command line.
12  */
13 
14 #include "vim.h"
15 
16 static int	quitmore = 0;
17 static int	ex_pressedreturn = FALSE;
18 #ifndef FEAT_PRINTER
19 # define ex_hardcopy	ex_ni
20 #endif
21 
22 #ifdef FEAT_EVAL
23 static char_u	*do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie);
24 #else
25 static char_u	*do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie);
26 static int	if_level = 0;		/* depth in :if */
27 #endif
28 static void	free_cmdmod(void);
29 static void	append_command(char_u *cmd);
30 static char_u	*find_command(exarg_T *eap, int *full);
31 
32 static void	ex_abbreviate(exarg_T *eap);
33 static void	ex_map(exarg_T *eap);
34 static void	ex_unmap(exarg_T *eap);
35 static void	ex_mapclear(exarg_T *eap);
36 static void	ex_abclear(exarg_T *eap);
37 #ifndef FEAT_MENU
38 # define ex_emenu		ex_ni
39 # define ex_menu		ex_ni
40 # define ex_menutranslate	ex_ni
41 #endif
42 static void	ex_autocmd(exarg_T *eap);
43 static void	ex_doautocmd(exarg_T *eap);
44 static void	ex_bunload(exarg_T *eap);
45 static void	ex_buffer(exarg_T *eap);
46 static void	ex_bmodified(exarg_T *eap);
47 static void	ex_bnext(exarg_T *eap);
48 static void	ex_bprevious(exarg_T *eap);
49 static void	ex_brewind(exarg_T *eap);
50 static void	ex_blast(exarg_T *eap);
51 static char_u	*getargcmd(char_u **);
52 static char_u	*skip_cmd_arg(char_u *p, int rembs);
53 static int	getargopt(exarg_T *eap);
54 #ifndef FEAT_QUICKFIX
55 # define ex_make		ex_ni
56 # define ex_cbuffer		ex_ni
57 # define ex_cc			ex_ni
58 # define ex_cnext		ex_ni
59 # define ex_cbelow		ex_ni
60 # define ex_cfile		ex_ni
61 # define qf_list		ex_ni
62 # define qf_age			ex_ni
63 # define qf_history		ex_ni
64 # define ex_helpgrep		ex_ni
65 # define ex_vimgrep		ex_ni
66 #endif
67 #if !defined(FEAT_QUICKFIX)
68 # define ex_cclose		ex_ni
69 # define ex_copen		ex_ni
70 # define ex_cwindow		ex_ni
71 # define ex_cbottom		ex_ni
72 #endif
73 #if !defined(FEAT_QUICKFIX) || !defined(FEAT_EVAL)
74 # define ex_cexpr		ex_ni
75 #endif
76 
77 static linenr_T get_address(exarg_T *, char_u **, cmd_addr_T addr_type, int skip, int silent, int to_other_file, int address_count);
78 static void	get_flags(exarg_T *eap);
79 #if !defined(FEAT_PERL) \
80 	|| !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \
81 	|| !defined(FEAT_TCL) \
82 	|| !defined(FEAT_RUBY) \
83 	|| !defined(FEAT_LUA) \
84 	|| !defined(FEAT_MZSCHEME)
85 # define HAVE_EX_SCRIPT_NI
86 static void	ex_script_ni(exarg_T *eap);
87 #endif
88 static char	*invalid_range(exarg_T *eap);
89 static void	correct_range(exarg_T *eap);
90 #ifdef FEAT_QUICKFIX
91 static char_u	*replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep);
92 #endif
93 static char_u	*repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep);
94 static void	ex_highlight(exarg_T *eap);
95 static void	ex_colorscheme(exarg_T *eap);
96 static void	ex_quit(exarg_T *eap);
97 static void	ex_cquit(exarg_T *eap);
98 static void	ex_quit_all(exarg_T *eap);
99 static void	ex_close(exarg_T *eap);
100 static void	ex_win_close(int forceit, win_T *win, tabpage_T *tp);
101 static void	ex_only(exarg_T *eap);
102 static void	ex_resize(exarg_T *eap);
103 static void	ex_stag(exarg_T *eap);
104 static void	ex_tabclose(exarg_T *eap);
105 static void	ex_tabonly(exarg_T *eap);
106 static void	ex_tabnext(exarg_T *eap);
107 static void	ex_tabmove(exarg_T *eap);
108 static void	ex_tabs(exarg_T *eap);
109 #if defined(FEAT_QUICKFIX)
110 static void	ex_pclose(exarg_T *eap);
111 static void	ex_ptag(exarg_T *eap);
112 static void	ex_pedit(exarg_T *eap);
113 #else
114 # define ex_pclose		ex_ni
115 # define ex_ptag		ex_ni
116 # define ex_pedit		ex_ni
117 #endif
118 static void	ex_hide(exarg_T *eap);
119 static void	ex_stop(exarg_T *eap);
120 static void	ex_exit(exarg_T *eap);
121 static void	ex_print(exarg_T *eap);
122 #ifdef FEAT_BYTEOFF
123 static void	ex_goto(exarg_T *eap);
124 #else
125 # define ex_goto		ex_ni
126 #endif
127 static void	ex_shell(exarg_T *eap);
128 static void	ex_preserve(exarg_T *eap);
129 static void	ex_recover(exarg_T *eap);
130 static void	ex_mode(exarg_T *eap);
131 static void	ex_wrongmodifier(exarg_T *eap);
132 static void	ex_find(exarg_T *eap);
133 static void	ex_open(exarg_T *eap);
134 static void	ex_edit(exarg_T *eap);
135 #ifndef FEAT_GUI
136 # define ex_gui			ex_nogui
137 static void	ex_nogui(exarg_T *eap);
138 #endif
139 #if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
140 static void	ex_tearoff(exarg_T *eap);
141 #else
142 # define ex_tearoff		ex_ni
143 #endif
144 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
145 	|| defined(FEAT_TERM_POPUP_MENU)) && defined(FEAT_MENU)
146 static void	ex_popup(exarg_T *eap);
147 #else
148 # define ex_popup		ex_ni
149 #endif
150 #ifndef FEAT_GUI_MSWIN
151 # define ex_simalt		ex_ni
152 #endif
153 #if !defined(FEAT_GUI_MSWIN) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MOTIF)
154 # define gui_mch_find_dialog	ex_ni
155 # define gui_mch_replace_dialog ex_ni
156 #endif
157 #if !defined(FEAT_GUI_GTK)
158 # define ex_helpfind		ex_ni
159 #endif
160 #ifndef FEAT_CSCOPE
161 # define ex_cscope		ex_ni
162 # define ex_scscope		ex_ni
163 # define ex_cstag		ex_ni
164 #endif
165 #ifndef FEAT_SYN_HL
166 # define ex_syntax		ex_ni
167 # define ex_ownsyntax		ex_ni
168 #endif
169 #ifndef FEAT_EVAL
170 # define ex_packadd		ex_ni
171 # define ex_packloadall		ex_ni
172 #endif
173 #if !defined(FEAT_SYN_HL) || !defined(FEAT_PROFILE)
174 # define ex_syntime		ex_ni
175 #endif
176 #ifndef FEAT_SPELL
177 # define ex_spell		ex_ni
178 # define ex_mkspell		ex_ni
179 # define ex_spelldump		ex_ni
180 # define ex_spellinfo		ex_ni
181 # define ex_spellrepall		ex_ni
182 #endif
183 #ifndef FEAT_PERSISTENT_UNDO
184 # define ex_rundo		ex_ni
185 # define ex_wundo		ex_ni
186 #endif
187 #ifndef FEAT_LUA
188 # define ex_lua			ex_script_ni
189 # define ex_luado		ex_ni
190 # define ex_luafile		ex_ni
191 #endif
192 #ifndef FEAT_MZSCHEME
193 # define ex_mzscheme		ex_script_ni
194 # define ex_mzfile		ex_ni
195 #endif
196 #ifndef FEAT_PERL
197 # define ex_perl		ex_script_ni
198 # define ex_perldo		ex_ni
199 #endif
200 #ifndef FEAT_PYTHON
201 # define ex_python		ex_script_ni
202 # define ex_pydo		ex_ni
203 # define ex_pyfile		ex_ni
204 #endif
205 #ifndef FEAT_PYTHON3
206 # define ex_py3			ex_script_ni
207 # define ex_py3do		ex_ni
208 # define ex_py3file		ex_ni
209 #endif
210 #if !defined(FEAT_PYTHON) && !defined(FEAT_PYTHON3)
211 # define ex_pyx			ex_script_ni
212 # define ex_pyxdo		ex_ni
213 # define ex_pyxfile		ex_ni
214 #endif
215 #ifndef FEAT_TCL
216 # define ex_tcl			ex_script_ni
217 # define ex_tcldo		ex_ni
218 # define ex_tclfile		ex_ni
219 #endif
220 #ifndef FEAT_RUBY
221 # define ex_ruby		ex_script_ni
222 # define ex_rubydo		ex_ni
223 # define ex_rubyfile		ex_ni
224 #endif
225 #ifndef FEAT_KEYMAP
226 # define ex_loadkeymap		ex_ni
227 #endif
228 static void	ex_swapname(exarg_T *eap);
229 static void	ex_syncbind(exarg_T *eap);
230 static void	ex_read(exarg_T *eap);
231 static void	ex_pwd(exarg_T *eap);
232 static void	ex_equal(exarg_T *eap);
233 static void	ex_sleep(exarg_T *eap);
234 static void	do_exmap(exarg_T *eap, int isabbrev);
235 static void	ex_winsize(exarg_T *eap);
236 static void	ex_wincmd(exarg_T *eap);
237 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN)
238 static void	ex_winpos(exarg_T *eap);
239 #else
240 # define ex_winpos	    ex_ni
241 #endif
242 static void	ex_operators(exarg_T *eap);
243 static void	ex_put(exarg_T *eap);
244 static void	ex_copymove(exarg_T *eap);
245 static void	ex_submagic(exarg_T *eap);
246 static void	ex_join(exarg_T *eap);
247 static void	ex_at(exarg_T *eap);
248 static void	ex_bang(exarg_T *eap);
249 static void	ex_undo(exarg_T *eap);
250 #ifdef FEAT_PERSISTENT_UNDO
251 static void	ex_wundo(exarg_T *eap);
252 static void	ex_rundo(exarg_T *eap);
253 #endif
254 static void	ex_redo(exarg_T *eap);
255 static void	ex_later(exarg_T *eap);
256 static void	ex_redir(exarg_T *eap);
257 static void	ex_redrawstatus(exarg_T *eap);
258 static void	ex_redrawtabline(exarg_T *eap);
259 static void	close_redir(void);
260 static void	ex_mkrc(exarg_T *eap);
261 static void	ex_mark(exarg_T *eap);
262 static void	ex_startinsert(exarg_T *eap);
263 static void	ex_stopinsert(exarg_T *eap);
264 #ifdef FEAT_FIND_ID
265 static void	ex_checkpath(exarg_T *eap);
266 static void	ex_findpat(exarg_T *eap);
267 #else
268 # define ex_findpat		ex_ni
269 # define ex_checkpath		ex_ni
270 #endif
271 #if defined(FEAT_FIND_ID) && defined(FEAT_QUICKFIX)
272 static void	ex_psearch(exarg_T *eap);
273 #else
274 # define ex_psearch		ex_ni
275 #endif
276 static void	ex_tag(exarg_T *eap);
277 static void	ex_tag_cmd(exarg_T *eap, char_u *name);
278 #ifndef FEAT_EVAL
279 # define ex_scriptnames		ex_ni
280 # define ex_finish		ex_ni
281 # define ex_echo		ex_ni
282 # define ex_echohl		ex_ni
283 # define ex_execute		ex_ni
284 # define ex_call		ex_ni
285 # define ex_if			ex_ni
286 # define ex_endif		ex_ni
287 # define ex_else		ex_ni
288 # define ex_while		ex_ni
289 # define ex_continue		ex_ni
290 # define ex_break		ex_ni
291 # define ex_endwhile		ex_ni
292 # define ex_throw		ex_ni
293 # define ex_try			ex_ni
294 # define ex_catch		ex_ni
295 # define ex_finally		ex_ni
296 # define ex_endtry		ex_ni
297 # define ex_endfunction		ex_ni
298 # define ex_let			ex_ni
299 # define ex_unlet		ex_ni
300 # define ex_lockvar		ex_ni
301 # define ex_unlockvar		ex_ni
302 # define ex_function		ex_ni
303 # define ex_delfunction		ex_ni
304 # define ex_return		ex_ni
305 # define ex_oldfiles		ex_ni
306 #endif
307 static char_u	*arg_all(void);
308 #ifdef FEAT_SESSION
309 static int	makeopens(FILE *fd, char_u *dirnow);
310 static int	put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx);
311 static void	ex_loadview(exarg_T *eap);
312 static char_u	*get_view_file(int c);
313 static int	did_lcd;	/* whether ":lcd" was produced for a session */
314 #else
315 # define ex_loadview		ex_ni
316 #endif
317 #ifndef FEAT_EVAL
318 # define ex_compiler		ex_ni
319 #endif
320 #ifdef FEAT_VIMINFO
321 static void	ex_viminfo(exarg_T *eap);
322 #else
323 # define ex_viminfo		ex_ni
324 #endif
325 static void	ex_behave(exarg_T *eap);
326 static void	ex_filetype(exarg_T *eap);
327 static void	ex_setfiletype(exarg_T *eap);
328 #ifndef FEAT_DIFF
329 # define ex_diffoff		ex_ni
330 # define ex_diffpatch		ex_ni
331 # define ex_diffgetput		ex_ni
332 # define ex_diffsplit		ex_ni
333 # define ex_diffthis		ex_ni
334 # define ex_diffupdate		ex_ni
335 #endif
336 static void	ex_digraphs(exarg_T *eap);
337 static void	ex_set(exarg_T *eap);
338 #if !defined(FEAT_EVAL)
339 # define ex_options		ex_ni
340 #endif
341 #ifdef FEAT_SEARCH_EXTRA
342 static void	ex_nohlsearch(exarg_T *eap);
343 static void	ex_match(exarg_T *eap);
344 #else
345 # define ex_nohlsearch		ex_ni
346 # define ex_match		ex_ni
347 #endif
348 #ifdef FEAT_CRYPT
349 static void	ex_X(exarg_T *eap);
350 #else
351 # define ex_X			ex_ni
352 #endif
353 #ifdef FEAT_FOLDING
354 static void	ex_fold(exarg_T *eap);
355 static void	ex_foldopen(exarg_T *eap);
356 static void	ex_folddo(exarg_T *eap);
357 #else
358 # define ex_fold		ex_ni
359 # define ex_foldopen		ex_ni
360 # define ex_folddo		ex_ni
361 #endif
362 #if !(defined(HAVE_LOCALE_H) || defined(X_LOCALE))
363 # define ex_language		ex_ni
364 #endif
365 #ifndef FEAT_SIGNS
366 # define ex_sign		ex_ni
367 #endif
368 #ifndef FEAT_NETBEANS_INTG
369 # define ex_nbclose		ex_ni
370 # define ex_nbkey		ex_ni
371 # define ex_nbstart		ex_ni
372 #endif
373 
374 #ifndef FEAT_EVAL
375 # define ex_debug		ex_ni
376 # define ex_breakadd		ex_ni
377 # define ex_debuggreedy		ex_ni
378 # define ex_breakdel		ex_ni
379 # define ex_breaklist		ex_ni
380 #endif
381 
382 #ifndef FEAT_CMDHIST
383 # define ex_history		ex_ni
384 #endif
385 #ifndef FEAT_JUMPLIST
386 # define ex_jumps		ex_ni
387 # define ex_clearjumps		ex_ni
388 # define ex_changes		ex_ni
389 #endif
390 
391 #ifndef FEAT_PROFILE
392 # define ex_profile		ex_ni
393 #endif
394 #ifndef FEAT_TERMINAL
395 # define ex_terminal		ex_ni
396 #endif
397 #if !defined(FEAT_X11) || !defined(FEAT_XCLIPBOARD)
398 # define ex_xrestore		ex_ni
399 #endif
400 
401 /*
402  * Declare cmdnames[].
403  */
404 #define DO_DECLARE_EXCMD
405 #include "ex_cmds.h"
406 #include "ex_cmdidxs.h"
407 
408 static char_u dollar_command[2] = {'$', 0};
409 
410 
411 #ifdef FEAT_EVAL
412 /* Struct for storing a line inside a while/for loop */
413 typedef struct
414 {
415     char_u	*line;		/* command line */
416     linenr_T	lnum;		/* sourcing_lnum of the line */
417 } wcmd_T;
418 
419 /*
420  * Structure used to store info for line position in a while or for loop.
421  * This is required, because do_one_cmd() may invoke ex_function(), which
422  * reads more lines that may come from the while/for loop.
423  */
424 struct loop_cookie
425 {
426     garray_T	*lines_gap;		/* growarray with line info */
427     int		current_line;		/* last read line from growarray */
428     int		repeating;		/* TRUE when looping a second time */
429     /* When "repeating" is FALSE use "getline" and "cookie" to get lines */
430     char_u	*(*getline)(int, void *, int);
431     void	*cookie;
432 };
433 
434 static char_u	*get_loop_line(int c, void *cookie, int indent);
435 static int	store_loop_line(garray_T *gap, char_u *line);
436 static void	free_cmdlines(garray_T *gap);
437 
438 /* Struct to save a few things while debugging.  Used in do_cmdline() only. */
439 struct dbg_stuff
440 {
441     int		trylevel;
442     int		force_abort;
443     except_T	*caught_stack;
444     char_u	*vv_exception;
445     char_u	*vv_throwpoint;
446     int		did_emsg;
447     int		got_int;
448     int		did_throw;
449     int		need_rethrow;
450     int		check_cstack;
451     except_T	*current_exception;
452 };
453 
454     static void
455 save_dbg_stuff(struct dbg_stuff *dsp)
456 {
457     dsp->trylevel	= trylevel;		trylevel = 0;
458     dsp->force_abort	= force_abort;		force_abort = FALSE;
459     dsp->caught_stack	= caught_stack;		caught_stack = NULL;
460     dsp->vv_exception	= v_exception(NULL);
461     dsp->vv_throwpoint	= v_throwpoint(NULL);
462 
463     /* Necessary for debugging an inactive ":catch", ":finally", ":endtry" */
464     dsp->did_emsg	= did_emsg;		did_emsg     = FALSE;
465     dsp->got_int	= got_int;		got_int	     = FALSE;
466     dsp->did_throw	= did_throw;		did_throw    = FALSE;
467     dsp->need_rethrow	= need_rethrow;		need_rethrow = FALSE;
468     dsp->check_cstack	= check_cstack;		check_cstack = FALSE;
469     dsp->current_exception = current_exception;	current_exception = NULL;
470 }
471 
472     static void
473 restore_dbg_stuff(struct dbg_stuff *dsp)
474 {
475     suppress_errthrow = FALSE;
476     trylevel = dsp->trylevel;
477     force_abort = dsp->force_abort;
478     caught_stack = dsp->caught_stack;
479     (void)v_exception(dsp->vv_exception);
480     (void)v_throwpoint(dsp->vv_throwpoint);
481     did_emsg = dsp->did_emsg;
482     got_int = dsp->got_int;
483     did_throw = dsp->did_throw;
484     need_rethrow = dsp->need_rethrow;
485     check_cstack = dsp->check_cstack;
486     current_exception = dsp->current_exception;
487 }
488 #endif
489 
490 /*
491  * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
492  * command is given.
493  */
494     void
495 do_exmode(
496     int		improved)	    /* TRUE for "improved Ex" mode */
497 {
498     int		save_msg_scroll;
499     int		prev_msg_row;
500     linenr_T	prev_line;
501     varnumber_T	changedtick;
502 
503     if (improved)
504 	exmode_active = EXMODE_VIM;
505     else
506 	exmode_active = EXMODE_NORMAL;
507     State = NORMAL;
508 
509     /* When using ":global /pat/ visual" and then "Q" we return to continue
510      * the :global command. */
511     if (global_busy)
512 	return;
513 
514     save_msg_scroll = msg_scroll;
515     ++RedrawingDisabled;	    /* don't redisplay the window */
516     ++no_wait_return;		    /* don't wait for return */
517 #ifdef FEAT_GUI
518     /* Ignore scrollbar and mouse events in Ex mode */
519     ++hold_gui_events;
520 #endif
521 
522     msg(_("Entering Ex mode.  Type \"visual\" to go to Normal mode."));
523     while (exmode_active)
524     {
525 	/* Check for a ":normal" command and no more characters left. */
526 	if (ex_normal_busy > 0 && typebuf.tb_len == 0)
527 	{
528 	    exmode_active = FALSE;
529 	    break;
530 	}
531 	msg_scroll = TRUE;
532 	need_wait_return = FALSE;
533 	ex_pressedreturn = FALSE;
534 	ex_no_reprint = FALSE;
535 	changedtick = CHANGEDTICK(curbuf);
536 	prev_msg_row = msg_row;
537 	prev_line = curwin->w_cursor.lnum;
538 	if (improved)
539 	{
540 	    cmdline_row = msg_row;
541 	    do_cmdline(NULL, getexline, NULL, 0);
542 	}
543 	else
544 	    do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
545 	lines_left = Rows - 1;
546 
547 	if ((prev_line != curwin->w_cursor.lnum
548 		   || changedtick != CHANGEDTICK(curbuf)) && !ex_no_reprint)
549 	{
550 	    if (curbuf->b_ml.ml_flags & ML_EMPTY)
551 		emsg(_(e_emptybuf));
552 	    else
553 	    {
554 		if (ex_pressedreturn)
555 		{
556 		    /* go up one line, to overwrite the ":<CR>" line, so the
557 		     * output doesn't contain empty lines. */
558 		    msg_row = prev_msg_row;
559 		    if (prev_msg_row == Rows - 1)
560 			msg_row--;
561 		}
562 		msg_col = 0;
563 		print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE);
564 		msg_clr_eos();
565 	    }
566 	}
567 	else if (ex_pressedreturn && !ex_no_reprint)	/* must be at EOF */
568 	{
569 	    if (curbuf->b_ml.ml_flags & ML_EMPTY)
570 		emsg(_(e_emptybuf));
571 	    else
572 		emsg(_("E501: At end-of-file"));
573 	}
574     }
575 
576 #ifdef FEAT_GUI
577     --hold_gui_events;
578 #endif
579     --RedrawingDisabled;
580     --no_wait_return;
581     update_screen(CLEAR);
582     need_wait_return = FALSE;
583     msg_scroll = save_msg_scroll;
584 }
585 
586 /*
587  * Execute a simple command line.  Used for translated commands like "*".
588  */
589     int
590 do_cmdline_cmd(char_u *cmd)
591 {
592     return do_cmdline(cmd, NULL, NULL,
593 				   DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
594 }
595 
596 /*
597  * do_cmdline(): execute one Ex command line
598  *
599  * 1. Execute "cmdline" when it is not NULL.
600  *    If "cmdline" is NULL, or more lines are needed, fgetline() is used.
601  * 2. Split up in parts separated with '|'.
602  *
603  * This function can be called recursively!
604  *
605  * flags:
606  * DOCMD_VERBOSE  - The command will be included in the error message.
607  * DOCMD_NOWAIT   - Don't call wait_return() and friends.
608  * DOCMD_REPEAT   - Repeat execution until fgetline() returns NULL.
609  * DOCMD_KEYTYPED - Don't reset KeyTyped.
610  * DOCMD_EXCRESET - Reset the exception environment (used for debugging).
611  * DOCMD_KEEPLINE - Store first typed line (for repeating with ".").
612  *
613  * return FAIL if cmdline could not be executed, OK otherwise
614  */
615     int
616 do_cmdline(
617     char_u	*cmdline,
618     char_u	*(*fgetline)(int, void *, int),
619     void	*cookie,		/* argument for fgetline() */
620     int		flags)
621 {
622     char_u	*next_cmdline;		/* next cmd to execute */
623     char_u	*cmdline_copy = NULL;	/* copy of cmd line */
624     int		used_getline = FALSE;	/* used "fgetline" to obtain command */
625     static int	recursive = 0;		/* recursive depth */
626     int		msg_didout_before_start = 0;
627     int		count = 0;		/* line number count */
628     int		did_inc = FALSE;	/* incremented RedrawingDisabled */
629     int		retval = OK;
630 #ifdef FEAT_EVAL
631     struct condstack cstack;		/* conditional stack */
632     garray_T	lines_ga;		/* keep lines for ":while"/":for" */
633     int		current_line = 0;	/* active line in lines_ga */
634     char_u	*fname = NULL;		/* function or script name */
635     linenr_T	*breakpoint = NULL;	/* ptr to breakpoint field in cookie */
636     int		*dbg_tick = NULL;	/* ptr to dbg_tick field in cookie */
637     struct dbg_stuff debug_saved;	/* saved things for debug mode */
638     int		initial_trylevel;
639     struct msglist	**saved_msg_list = NULL;
640     struct msglist	*private_msg_list;
641 
642     /* "fgetline" and "cookie" passed to do_one_cmd() */
643     char_u	*(*cmd_getline)(int, void *, int);
644     void	*cmd_cookie;
645     struct loop_cookie cmd_loop_cookie;
646     void	*real_cookie;
647     int		getline_is_func;
648 #else
649 # define cmd_getline fgetline
650 # define cmd_cookie cookie
651 #endif
652     static int	call_depth = 0;		/* recursiveness */
653 
654 #ifdef FEAT_EVAL
655     /* For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
656      * location for storing error messages to be converted to an exception.
657      * This ensures that the do_errthrow() call in do_one_cmd() does not
658      * combine the messages stored by an earlier invocation of do_one_cmd()
659      * with the command name of the later one.  This would happen when
660      * BufWritePost autocommands are executed after a write error. */
661     saved_msg_list = msg_list;
662     msg_list = &private_msg_list;
663     private_msg_list = NULL;
664 #endif
665 
666     /* It's possible to create an endless loop with ":execute", catch that
667      * here.  The value of 200 allows nested function calls, ":source", etc.
668      * Allow 200 or 'maxfuncdepth', whatever is larger. */
669     if (call_depth >= 200
670 #ifdef FEAT_EVAL
671 	    && call_depth >= p_mfd
672 #endif
673 	    )
674     {
675 	emsg(_("E169: Command too recursive"));
676 #ifdef FEAT_EVAL
677 	/* When converting to an exception, we do not include the command name
678 	 * since this is not an error of the specific command. */
679 	do_errthrow((struct condstack *)NULL, (char_u *)NULL);
680 	msg_list = saved_msg_list;
681 #endif
682 	return FAIL;
683     }
684     ++call_depth;
685 
686 #ifdef FEAT_EVAL
687     cstack.cs_idx = -1;
688     cstack.cs_looplevel = 0;
689     cstack.cs_trylevel = 0;
690     cstack.cs_emsg_silent_list = NULL;
691     cstack.cs_lflags = 0;
692     ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10);
693 
694     real_cookie = getline_cookie(fgetline, cookie);
695 
696     /* Inside a function use a higher nesting level. */
697     getline_is_func = getline_equal(fgetline, cookie, get_func_line);
698     if (getline_is_func && ex_nesting_level == func_level(real_cookie))
699 	++ex_nesting_level;
700 
701     /* Get the function or script name and the address where the next breakpoint
702      * line and the debug tick for a function or script are stored. */
703     if (getline_is_func)
704     {
705 	fname = func_name(real_cookie);
706 	breakpoint = func_breakpoint(real_cookie);
707 	dbg_tick = func_dbg_tick(real_cookie);
708     }
709     else if (getline_equal(fgetline, cookie, getsourceline))
710     {
711 	fname = sourcing_name;
712 	breakpoint = source_breakpoint(real_cookie);
713 	dbg_tick = source_dbg_tick(real_cookie);
714     }
715 
716     /*
717      * Initialize "force_abort"  and "suppress_errthrow" at the top level.
718      */
719     if (!recursive)
720     {
721 	force_abort = FALSE;
722 	suppress_errthrow = FALSE;
723     }
724 
725     /*
726      * If requested, store and reset the global values controlling the
727      * exception handling (used when debugging).  Otherwise clear it to avoid
728      * a bogus compiler warning when the optimizer uses inline functions...
729      */
730     if (flags & DOCMD_EXCRESET)
731 	save_dbg_stuff(&debug_saved);
732     else
733 	vim_memset(&debug_saved, 0, sizeof(debug_saved));
734 
735     initial_trylevel = trylevel;
736 
737     /*
738      * "did_throw" will be set to TRUE when an exception is being thrown.
739      */
740     did_throw = FALSE;
741 #endif
742     /*
743      * "did_emsg" will be set to TRUE when emsg() is used, in which case we
744      * cancel the whole command line, and any if/endif or loop.
745      * If force_abort is set, we cancel everything.
746      */
747     did_emsg = FALSE;
748 
749     /*
750      * KeyTyped is only set when calling vgetc().  Reset it here when not
751      * calling vgetc() (sourced command lines).
752      */
753     if (!(flags & DOCMD_KEYTYPED)
754 			       && !getline_equal(fgetline, cookie, getexline))
755 	KeyTyped = FALSE;
756 
757     /*
758      * Continue executing command lines:
759      * - when inside an ":if", ":while" or ":for"
760      * - for multiple commands on one line, separated with '|'
761      * - when repeating until there are no more lines (for ":source")
762      */
763     next_cmdline = cmdline;
764     do
765     {
766 #ifdef FEAT_EVAL
767 	getline_is_func = getline_equal(fgetline, cookie, get_func_line);
768 #endif
769 
770 	/* stop skipping cmds for an error msg after all endif/while/for */
771 	if (next_cmdline == NULL
772 #ifdef FEAT_EVAL
773 		&& !force_abort
774 		&& cstack.cs_idx < 0
775 		&& !(getline_is_func && func_has_abort(real_cookie))
776 #endif
777 							)
778 	    did_emsg = FALSE;
779 
780 	/*
781 	 * 1. If repeating a line in a loop, get a line from lines_ga.
782 	 * 2. If no line given: Get an allocated line with fgetline().
783 	 * 3. If a line is given: Make a copy, so we can mess with it.
784 	 */
785 
786 #ifdef FEAT_EVAL
787 	/* 1. If repeating, get a previous line from lines_ga. */
788 	if (cstack.cs_looplevel > 0 && current_line < lines_ga.ga_len)
789 	{
790 	    /* Each '|' separated command is stored separately in lines_ga, to
791 	     * be able to jump to it.  Don't use next_cmdline now. */
792 	    VIM_CLEAR(cmdline_copy);
793 
794 	    /* Check if a function has returned or, unless it has an unclosed
795 	     * try conditional, aborted. */
796 	    if (getline_is_func)
797 	    {
798 # ifdef FEAT_PROFILE
799 		if (do_profiling == PROF_YES)
800 		    func_line_end(real_cookie);
801 # endif
802 		if (func_has_ended(real_cookie))
803 		{
804 		    retval = FAIL;
805 		    break;
806 		}
807 	    }
808 #ifdef FEAT_PROFILE
809 	    else if (do_profiling == PROF_YES
810 			    && getline_equal(fgetline, cookie, getsourceline))
811 		script_line_end();
812 #endif
813 
814 	    /* Check if a sourced file hit a ":finish" command. */
815 	    if (source_finished(fgetline, cookie))
816 	    {
817 		retval = FAIL;
818 		break;
819 	    }
820 
821 	    /* If breakpoints have been added/deleted need to check for it. */
822 	    if (breakpoint != NULL && dbg_tick != NULL
823 						   && *dbg_tick != debug_tick)
824 	    {
825 		*breakpoint = dbg_find_breakpoint(
826 				getline_equal(fgetline, cookie, getsourceline),
827 							fname, sourcing_lnum);
828 		*dbg_tick = debug_tick;
829 	    }
830 
831 	    next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
832 	    sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
833 
834 	    /* Did we encounter a breakpoint? */
835 	    if (breakpoint != NULL && *breakpoint != 0
836 					      && *breakpoint <= sourcing_lnum)
837 	    {
838 		dbg_breakpoint(fname, sourcing_lnum);
839 		/* Find next breakpoint. */
840 		*breakpoint = dbg_find_breakpoint(
841 			       getline_equal(fgetline, cookie, getsourceline),
842 							fname, sourcing_lnum);
843 		*dbg_tick = debug_tick;
844 	    }
845 # ifdef FEAT_PROFILE
846 	    if (do_profiling == PROF_YES)
847 	    {
848 		if (getline_is_func)
849 		    func_line_start(real_cookie);
850 		else if (getline_equal(fgetline, cookie, getsourceline))
851 		    script_line_start();
852 	    }
853 # endif
854 	}
855 
856 	if (cstack.cs_looplevel > 0)
857 	{
858 	    /* Inside a while/for loop we need to store the lines and use them
859 	     * again.  Pass a different "fgetline" function to do_one_cmd()
860 	     * below, so that it stores lines in or reads them from
861 	     * "lines_ga".  Makes it possible to define a function inside a
862 	     * while/for loop. */
863 	    cmd_getline = get_loop_line;
864 	    cmd_cookie = (void *)&cmd_loop_cookie;
865 	    cmd_loop_cookie.lines_gap = &lines_ga;
866 	    cmd_loop_cookie.current_line = current_line;
867 	    cmd_loop_cookie.getline = fgetline;
868 	    cmd_loop_cookie.cookie = cookie;
869 	    cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len);
870 	}
871 	else
872 	{
873 	    cmd_getline = fgetline;
874 	    cmd_cookie = cookie;
875 	}
876 #endif
877 
878 	/* 2. If no line given, get an allocated line with fgetline(). */
879 	if (next_cmdline == NULL)
880 	{
881 	    /*
882 	     * Need to set msg_didout for the first line after an ":if",
883 	     * otherwise the ":if" will be overwritten.
884 	     */
885 	    if (count == 1 && getline_equal(fgetline, cookie, getexline))
886 		msg_didout = TRUE;
887 	    if (fgetline == NULL || (next_cmdline = fgetline(':', cookie,
888 #ifdef FEAT_EVAL
889 		    cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2
890 #else
891 		    0
892 #endif
893 			    )) == NULL)
894 	    {
895 		/* Don't call wait_return for aborted command line.  The NULL
896 		 * returned for the end of a sourced file or executed function
897 		 * doesn't do this. */
898 		if (KeyTyped && !(flags & DOCMD_REPEAT))
899 		    need_wait_return = FALSE;
900 		retval = FAIL;
901 		break;
902 	    }
903 	    used_getline = TRUE;
904 
905 	    /*
906 	     * Keep the first typed line.  Clear it when more lines are typed.
907 	     */
908 	    if (flags & DOCMD_KEEPLINE)
909 	    {
910 		vim_free(repeat_cmdline);
911 		if (count == 0)
912 		    repeat_cmdline = vim_strsave(next_cmdline);
913 		else
914 		    repeat_cmdline = NULL;
915 	    }
916 	}
917 
918 	/* 3. Make a copy of the command so we can mess with it. */
919 	else if (cmdline_copy == NULL)
920 	{
921 	    next_cmdline = vim_strsave(next_cmdline);
922 	    if (next_cmdline == NULL)
923 	    {
924 		emsg(_(e_outofmem));
925 		retval = FAIL;
926 		break;
927 	    }
928 	}
929 	cmdline_copy = next_cmdline;
930 
931 #ifdef FEAT_EVAL
932 	/*
933 	 * Save the current line when inside a ":while" or ":for", and when
934 	 * the command looks like a ":while" or ":for", because we may need it
935 	 * later.  When there is a '|' and another command, it is stored
936 	 * separately, because we need to be able to jump back to it from an
937 	 * :endwhile/:endfor.
938 	 */
939 	if (current_line == lines_ga.ga_len
940 		&& (cstack.cs_looplevel || has_loop_cmd(next_cmdline)))
941 	{
942 	    if (store_loop_line(&lines_ga, next_cmdline) == FAIL)
943 	    {
944 		retval = FAIL;
945 		break;
946 	    }
947 	}
948 	did_endif = FALSE;
949 #endif
950 
951 	if (count++ == 0)
952 	{
953 	    /*
954 	     * All output from the commands is put below each other, without
955 	     * waiting for a return. Don't do this when executing commands
956 	     * from a script or when being called recursive (e.g. for ":e
957 	     * +command file").
958 	     */
959 	    if (!(flags & DOCMD_NOWAIT) && !recursive)
960 	    {
961 		msg_didout_before_start = msg_didout;
962 		msg_didany = FALSE; /* no output yet */
963 		msg_start();
964 		msg_scroll = TRUE;  /* put messages below each other */
965 		++no_wait_return;   /* don't wait for return until finished */
966 		++RedrawingDisabled;
967 		did_inc = TRUE;
968 	    }
969 	}
970 
971 	if (p_verbose >= 15 && sourcing_name != NULL)
972 	{
973 	    ++no_wait_return;
974 	    verbose_enter_scroll();
975 
976 	    smsg(_("line %ld: %s"),
977 					   (long)sourcing_lnum, cmdline_copy);
978 	    if (msg_silent == 0)
979 		msg_puts("\n");   /* don't overwrite this */
980 
981 	    verbose_leave_scroll();
982 	    --no_wait_return;
983 	}
984 
985 	/*
986 	 * 2. Execute one '|' separated command.
987 	 *    do_one_cmd() will return NULL if there is no trailing '|'.
988 	 *    "cmdline_copy" can change, e.g. for '%' and '#' expansion.
989 	 */
990 	++recursive;
991 	next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
992 #ifdef FEAT_EVAL
993 				&cstack,
994 #endif
995 				cmd_getline, cmd_cookie);
996 	--recursive;
997 
998 #ifdef FEAT_EVAL
999 	if (cmd_cookie == (void *)&cmd_loop_cookie)
1000 	    /* Use "current_line" from "cmd_loop_cookie", it may have been
1001 	     * incremented when defining a function. */
1002 	    current_line = cmd_loop_cookie.current_line;
1003 #endif
1004 
1005 	if (next_cmdline == NULL)
1006 	{
1007 	    VIM_CLEAR(cmdline_copy);
1008 #ifdef FEAT_CMDHIST
1009 	    /*
1010 	     * If the command was typed, remember it for the ':' register.
1011 	     * Do this AFTER executing the command to make :@: work.
1012 	     */
1013 	    if (getline_equal(fgetline, cookie, getexline)
1014 						  && new_last_cmdline != NULL)
1015 	    {
1016 		vim_free(last_cmdline);
1017 		last_cmdline = new_last_cmdline;
1018 		new_last_cmdline = NULL;
1019 	    }
1020 #endif
1021 	}
1022 	else
1023 	{
1024 	    /* need to copy the command after the '|' to cmdline_copy, for the
1025 	     * next do_one_cmd() */
1026 	    STRMOVE(cmdline_copy, next_cmdline);
1027 	    next_cmdline = cmdline_copy;
1028 	}
1029 
1030 
1031 #ifdef FEAT_EVAL
1032 	/* reset did_emsg for a function that is not aborted by an error */
1033 	if (did_emsg && !force_abort
1034 		&& getline_equal(fgetline, cookie, get_func_line)
1035 					      && !func_has_abort(real_cookie))
1036 	    did_emsg = FALSE;
1037 
1038 	if (cstack.cs_looplevel > 0)
1039 	{
1040 	    ++current_line;
1041 
1042 	    /*
1043 	     * An ":endwhile", ":endfor" and ":continue" is handled here.
1044 	     * If we were executing commands, jump back to the ":while" or
1045 	     * ":for".
1046 	     * If we were not executing commands, decrement cs_looplevel.
1047 	     */
1048 	    if (cstack.cs_lflags & (CSL_HAD_CONT | CSL_HAD_ENDLOOP))
1049 	    {
1050 		cstack.cs_lflags &= ~(CSL_HAD_CONT | CSL_HAD_ENDLOOP);
1051 
1052 		/* Jump back to the matching ":while" or ":for".  Be careful
1053 		 * not to use a cs_line[] from an entry that isn't a ":while"
1054 		 * or ":for": It would make "current_line" invalid and can
1055 		 * cause a crash. */
1056 		if (!did_emsg && !got_int && !did_throw
1057 			&& cstack.cs_idx >= 0
1058 			&& (cstack.cs_flags[cstack.cs_idx]
1059 						      & (CSF_WHILE | CSF_FOR))
1060 			&& cstack.cs_line[cstack.cs_idx] >= 0
1061 			&& (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE))
1062 		{
1063 		    current_line = cstack.cs_line[cstack.cs_idx];
1064 						/* remember we jumped there */
1065 		    cstack.cs_lflags |= CSL_HAD_LOOP;
1066 		    line_breakcheck();		/* check if CTRL-C typed */
1067 
1068 		    /* Check for the next breakpoint at or after the ":while"
1069 		     * or ":for". */
1070 		    if (breakpoint != NULL)
1071 		    {
1072 			*breakpoint = dbg_find_breakpoint(
1073 			       getline_equal(fgetline, cookie, getsourceline),
1074 									fname,
1075 			   ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1);
1076 			*dbg_tick = debug_tick;
1077 		    }
1078 		}
1079 		else
1080 		{
1081 		    /* can only get here with ":endwhile" or ":endfor" */
1082 		    if (cstack.cs_idx >= 0)
1083 			rewind_conditionals(&cstack, cstack.cs_idx - 1,
1084 				   CSF_WHILE | CSF_FOR, &cstack.cs_looplevel);
1085 		}
1086 	    }
1087 
1088 	    /*
1089 	     * For a ":while" or ":for" we need to remember the line number.
1090 	     */
1091 	    else if (cstack.cs_lflags & CSL_HAD_LOOP)
1092 	    {
1093 		cstack.cs_lflags &= ~CSL_HAD_LOOP;
1094 		cstack.cs_line[cstack.cs_idx] = current_line - 1;
1095 	    }
1096 	}
1097 
1098 	/* Check for the next breakpoint after a watchexpression */
1099 	if (breakpoint != NULL && has_watchexpr())
1100 	{
1101 	    *breakpoint = dbg_find_breakpoint(FALSE, fname, sourcing_lnum);
1102 	    *dbg_tick = debug_tick;
1103 	}
1104 
1105 	/*
1106 	 * When not inside any ":while" loop, clear remembered lines.
1107 	 */
1108 	if (cstack.cs_looplevel == 0)
1109 	{
1110 	    if (lines_ga.ga_len > 0)
1111 	    {
1112 		sourcing_lnum =
1113 		       ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
1114 		free_cmdlines(&lines_ga);
1115 	    }
1116 	    current_line = 0;
1117 	}
1118 
1119 	/*
1120 	 * A ":finally" makes did_emsg, got_int, and did_throw pending for
1121 	 * being restored at the ":endtry".  Reset them here and set the
1122 	 * ACTIVE and FINALLY flags, so that the finally clause gets executed.
1123 	 * This includes the case where a missing ":endif", ":endwhile" or
1124 	 * ":endfor" was detected by the ":finally" itself.
1125 	 */
1126 	if (cstack.cs_lflags & CSL_HAD_FINA)
1127 	{
1128 	    cstack.cs_lflags &= ~CSL_HAD_FINA;
1129 	    report_make_pending(cstack.cs_pending[cstack.cs_idx]
1130 		    & (CSTP_ERROR | CSTP_INTERRUPT | CSTP_THROW),
1131 		    did_throw ? (void *)current_exception : NULL);
1132 	    did_emsg = got_int = did_throw = FALSE;
1133 	    cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
1134 	}
1135 
1136 	/* Update global "trylevel" for recursive calls to do_cmdline() from
1137 	 * within this loop. */
1138 	trylevel = initial_trylevel + cstack.cs_trylevel;
1139 
1140 	/*
1141 	 * If the outermost try conditional (across function calls and sourced
1142 	 * files) is aborted because of an error, an interrupt, or an uncaught
1143 	 * exception, cancel everything.  If it is left normally, reset
1144 	 * force_abort to get the non-EH compatible abortion behavior for
1145 	 * the rest of the script.
1146 	 */
1147 	if (trylevel == 0 && !did_emsg && !got_int && !did_throw)
1148 	    force_abort = FALSE;
1149 
1150 	/* Convert an interrupt to an exception if appropriate. */
1151 	(void)do_intthrow(&cstack);
1152 #endif /* FEAT_EVAL */
1153 
1154     }
1155     /*
1156      * Continue executing command lines when:
1157      * - no CTRL-C typed, no aborting error, no exception thrown or try
1158      *   conditionals need to be checked for executing finally clauses or
1159      *   catching an interrupt exception
1160      * - didn't get an error message or lines are not typed
1161      * - there is a command after '|', inside a :if, :while, :for or :try, or
1162      *   looping for ":source" command or function call.
1163      */
1164     while (!((got_int
1165 #ifdef FEAT_EVAL
1166 		    || (did_emsg && force_abort) || did_throw
1167 #endif
1168 	     )
1169 #ifdef FEAT_EVAL
1170 		&& cstack.cs_trylevel == 0
1171 #endif
1172 	    )
1173 	    && !(did_emsg
1174 #ifdef FEAT_EVAL
1175 		/* Keep going when inside try/catch, so that the error can be
1176 		 * deal with, except when it is a syntax error, it may cause
1177 		 * the :endtry to be missed. */
1178 		&& (cstack.cs_trylevel == 0 || did_emsg_syntax)
1179 #endif
1180 		&& used_getline
1181 			    && (getline_equal(fgetline, cookie, getexmodeline)
1182 			       || getline_equal(fgetline, cookie, getexline)))
1183 	    && (next_cmdline != NULL
1184 #ifdef FEAT_EVAL
1185 			|| cstack.cs_idx >= 0
1186 #endif
1187 			|| (flags & DOCMD_REPEAT)));
1188 
1189     vim_free(cmdline_copy);
1190     did_emsg_syntax = FALSE;
1191 #ifdef FEAT_EVAL
1192     free_cmdlines(&lines_ga);
1193     ga_clear(&lines_ga);
1194 
1195     if (cstack.cs_idx >= 0)
1196     {
1197 	/*
1198 	 * If a sourced file or executed function ran to its end, report the
1199 	 * unclosed conditional.
1200 	 */
1201 	if (!got_int && !did_throw
1202 		&& ((getline_equal(fgetline, cookie, getsourceline)
1203 			&& !source_finished(fgetline, cookie))
1204 		    || (getline_equal(fgetline, cookie, get_func_line)
1205 					    && !func_has_ended(real_cookie))))
1206 	{
1207 	    if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY)
1208 		emsg(_(e_endtry));
1209 	    else if (cstack.cs_flags[cstack.cs_idx] & CSF_WHILE)
1210 		emsg(_(e_endwhile));
1211 	    else if (cstack.cs_flags[cstack.cs_idx] & CSF_FOR)
1212 		emsg(_(e_endfor));
1213 	    else
1214 		emsg(_(e_endif));
1215 	}
1216 
1217 	/*
1218 	 * Reset "trylevel" in case of a ":finish" or ":return" or a missing
1219 	 * ":endtry" in a sourced file or executed function.  If the try
1220 	 * conditional is in its finally clause, ignore anything pending.
1221 	 * If it is in a catch clause, finish the caught exception.
1222 	 * Also cleanup any "cs_forinfo" structures.
1223 	 */
1224 	do
1225 	{
1226 	    int idx = cleanup_conditionals(&cstack, 0, TRUE);
1227 
1228 	    if (idx >= 0)
1229 		--idx;	    /* remove try block not in its finally clause */
1230 	    rewind_conditionals(&cstack, idx, CSF_WHILE | CSF_FOR,
1231 							&cstack.cs_looplevel);
1232 	}
1233 	while (cstack.cs_idx >= 0);
1234 	trylevel = initial_trylevel;
1235     }
1236 
1237     /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory
1238      * lack was reported above and the error message is to be converted to an
1239      * exception, do this now after rewinding the cstack. */
1240     do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line)
1241 				  ? (char_u *)"endfunction" : (char_u *)NULL);
1242 
1243     if (trylevel == 0)
1244     {
1245 	/*
1246 	 * When an exception is being thrown out of the outermost try
1247 	 * conditional, discard the uncaught exception, disable the conversion
1248 	 * of interrupts or errors to exceptions, and ensure that no more
1249 	 * commands are executed.
1250 	 */
1251 	if (did_throw)
1252 	{
1253 	    void	*p = NULL;
1254 	    char_u	*saved_sourcing_name;
1255 	    int		saved_sourcing_lnum;
1256 	    struct msglist	*messages = NULL, *next;
1257 
1258 	    /*
1259 	     * If the uncaught exception is a user exception, report it as an
1260 	     * error.  If it is an error exception, display the saved error
1261 	     * message now.  For an interrupt exception, do nothing; the
1262 	     * interrupt message is given elsewhere.
1263 	     */
1264 	    switch (current_exception->type)
1265 	    {
1266 		case ET_USER:
1267 		    vim_snprintf((char *)IObuff, IOSIZE,
1268 			    _("E605: Exception not caught: %s"),
1269 			    current_exception->value);
1270 		    p = vim_strsave(IObuff);
1271 		    break;
1272 		case ET_ERROR:
1273 		    messages = current_exception->messages;
1274 		    current_exception->messages = NULL;
1275 		    break;
1276 		case ET_INTERRUPT:
1277 		    break;
1278 	    }
1279 
1280 	    saved_sourcing_name = sourcing_name;
1281 	    saved_sourcing_lnum = sourcing_lnum;
1282 	    sourcing_name = current_exception->throw_name;
1283 	    sourcing_lnum = current_exception->throw_lnum;
1284 	    current_exception->throw_name = NULL;
1285 
1286 	    discard_current_exception();	/* uses IObuff if 'verbose' */
1287 	    suppress_errthrow = TRUE;
1288 	    force_abort = TRUE;
1289 
1290 	    if (messages != NULL)
1291 	    {
1292 		do
1293 		{
1294 		    next = messages->next;
1295 		    emsg(messages->msg);
1296 		    vim_free(messages->msg);
1297 		    vim_free(messages);
1298 		    messages = next;
1299 		}
1300 		while (messages != NULL);
1301 	    }
1302 	    else if (p != NULL)
1303 	    {
1304 		emsg(p);
1305 		vim_free(p);
1306 	    }
1307 	    vim_free(sourcing_name);
1308 	    sourcing_name = saved_sourcing_name;
1309 	    sourcing_lnum = saved_sourcing_lnum;
1310 	}
1311 
1312 	/*
1313 	 * On an interrupt or an aborting error not converted to an exception,
1314 	 * disable the conversion of errors to exceptions.  (Interrupts are not
1315 	 * converted any more, here.) This enables also the interrupt message
1316 	 * when force_abort is set and did_emsg unset in case of an interrupt
1317 	 * from a finally clause after an error.
1318 	 */
1319 	else if (got_int || (did_emsg && force_abort))
1320 	    suppress_errthrow = TRUE;
1321     }
1322 
1323     /*
1324      * The current cstack will be freed when do_cmdline() returns.  An uncaught
1325      * exception will have to be rethrown in the previous cstack.  If a function
1326      * has just returned or a script file was just finished and the previous
1327      * cstack belongs to the same function or, respectively, script file, it
1328      * will have to be checked for finally clauses to be executed due to the
1329      * ":return" or ":finish".  This is done in do_one_cmd().
1330      */
1331     if (did_throw)
1332 	need_rethrow = TRUE;
1333     if ((getline_equal(fgetline, cookie, getsourceline)
1334 		&& ex_nesting_level > source_level(real_cookie))
1335 	    || (getline_equal(fgetline, cookie, get_func_line)
1336 		&& ex_nesting_level > func_level(real_cookie) + 1))
1337     {
1338 	if (!did_throw)
1339 	    check_cstack = TRUE;
1340     }
1341     else
1342     {
1343 	/* When leaving a function, reduce nesting level. */
1344 	if (getline_equal(fgetline, cookie, get_func_line))
1345 	    --ex_nesting_level;
1346 	/*
1347 	 * Go to debug mode when returning from a function in which we are
1348 	 * single-stepping.
1349 	 */
1350 	if ((getline_equal(fgetline, cookie, getsourceline)
1351 		    || getline_equal(fgetline, cookie, get_func_line))
1352 		&& ex_nesting_level + 1 <= debug_break_level)
1353 	    do_debug(getline_equal(fgetline, cookie, getsourceline)
1354 		    ? (char_u *)_("End of sourced file")
1355 		    : (char_u *)_("End of function"));
1356     }
1357 
1358     /*
1359      * Restore the exception environment (done after returning from the
1360      * debugger).
1361      */
1362     if (flags & DOCMD_EXCRESET)
1363 	restore_dbg_stuff(&debug_saved);
1364 
1365     msg_list = saved_msg_list;
1366 #endif /* FEAT_EVAL */
1367 
1368     /*
1369      * If there was too much output to fit on the command line, ask the user to
1370      * hit return before redrawing the screen. With the ":global" command we do
1371      * this only once after the command is finished.
1372      */
1373     if (did_inc)
1374     {
1375 	--RedrawingDisabled;
1376 	--no_wait_return;
1377 	msg_scroll = FALSE;
1378 
1379 	/*
1380 	 * When just finished an ":if"-":else" which was typed, no need to
1381 	 * wait for hit-return.  Also for an error situation.
1382 	 */
1383 	if (retval == FAIL
1384 #ifdef FEAT_EVAL
1385 		|| (did_endif && KeyTyped && !did_emsg)
1386 #endif
1387 					    )
1388 	{
1389 	    need_wait_return = FALSE;
1390 	    msg_didany = FALSE;		/* don't wait when restarting edit */
1391 	}
1392 	else if (need_wait_return)
1393 	{
1394 	    /*
1395 	     * The msg_start() above clears msg_didout. The wait_return we do
1396 	     * here should not overwrite the command that may be shown before
1397 	     * doing that.
1398 	     */
1399 	    msg_didout |= msg_didout_before_start;
1400 	    wait_return(FALSE);
1401 	}
1402     }
1403 
1404 #ifdef FEAT_EVAL
1405     did_endif = FALSE;  /* in case do_cmdline used recursively */
1406 #else
1407     /*
1408      * Reset if_level, in case a sourced script file contains more ":if" than
1409      * ":endif" (could be ":if x | foo | endif").
1410      */
1411     if_level = 0;
1412 #endif
1413 
1414     --call_depth;
1415     return retval;
1416 }
1417 
1418 #ifdef FEAT_EVAL
1419 /*
1420  * Obtain a line when inside a ":while" or ":for" loop.
1421  */
1422     static char_u *
1423 get_loop_line(int c, void *cookie, int indent)
1424 {
1425     struct loop_cookie	*cp = (struct loop_cookie *)cookie;
1426     wcmd_T		*wp;
1427     char_u		*line;
1428 
1429     if (cp->current_line + 1 >= cp->lines_gap->ga_len)
1430     {
1431 	if (cp->repeating)
1432 	    return NULL;	/* trying to read past ":endwhile"/":endfor" */
1433 
1434 	/* First time inside the ":while"/":for": get line normally. */
1435 	if (cp->getline == NULL)
1436 	    line = getcmdline(c, 0L, indent);
1437 	else
1438 	    line = cp->getline(c, cp->cookie, indent);
1439 	if (line != NULL && store_loop_line(cp->lines_gap, line) == OK)
1440 	    ++cp->current_line;
1441 
1442 	return line;
1443     }
1444 
1445     KeyTyped = FALSE;
1446     ++cp->current_line;
1447     wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line;
1448     sourcing_lnum = wp->lnum;
1449     return vim_strsave(wp->line);
1450 }
1451 
1452 /*
1453  * Store a line in "gap" so that a ":while" loop can execute it again.
1454  */
1455     static int
1456 store_loop_line(garray_T *gap, char_u *line)
1457 {
1458     if (ga_grow(gap, 1) == FAIL)
1459 	return FAIL;
1460     ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line);
1461     ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum;
1462     ++gap->ga_len;
1463     return OK;
1464 }
1465 
1466 /*
1467  * Free the lines stored for a ":while" or ":for" loop.
1468  */
1469     static void
1470 free_cmdlines(garray_T *gap)
1471 {
1472     while (gap->ga_len > 0)
1473     {
1474 	vim_free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
1475 	--gap->ga_len;
1476     }
1477 }
1478 #endif
1479 
1480 /*
1481  * If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals
1482  * "func".  * Otherwise return TRUE when "fgetline" equals "func".
1483  */
1484     int
1485 getline_equal(
1486     char_u	*(*fgetline)(int, void *, int),
1487     void	*cookie UNUSED,		/* argument for fgetline() */
1488     char_u	*(*func)(int, void *, int))
1489 {
1490 #ifdef FEAT_EVAL
1491     char_u		*(*gp)(int, void *, int);
1492     struct loop_cookie *cp;
1493 
1494     /* When "fgetline" is "get_loop_line()" use the "cookie" to find the
1495      * function that's originally used to obtain the lines.  This may be
1496      * nested several levels. */
1497     gp = fgetline;
1498     cp = (struct loop_cookie *)cookie;
1499     while (gp == get_loop_line)
1500     {
1501 	gp = cp->getline;
1502 	cp = cp->cookie;
1503     }
1504     return gp == func;
1505 #else
1506     return fgetline == func;
1507 #endif
1508 }
1509 
1510 /*
1511  * If "fgetline" is get_loop_line(), return the cookie used by the original
1512  * getline function.  Otherwise return "cookie".
1513  */
1514     void *
1515 getline_cookie(
1516     char_u	*(*fgetline)(int, void *, int) UNUSED,
1517     void	*cookie)		/* argument for fgetline() */
1518 {
1519 #ifdef FEAT_EVAL
1520     char_u		*(*gp)(int, void *, int);
1521     struct loop_cookie *cp;
1522 
1523     /* When "fgetline" is "get_loop_line()" use the "cookie" to find the
1524      * cookie that's originally used to obtain the lines.  This may be nested
1525      * several levels. */
1526     gp = fgetline;
1527     cp = (struct loop_cookie *)cookie;
1528     while (gp == get_loop_line)
1529     {
1530 	gp = cp->getline;
1531 	cp = cp->cookie;
1532     }
1533     return cp;
1534 #else
1535     return cookie;
1536 #endif
1537 }
1538 
1539 
1540 /*
1541  * Helper function to apply an offset for buffer commands, i.e. ":bdelete",
1542  * ":bwipeout", etc.
1543  * Returns the buffer number.
1544  */
1545     static int
1546 compute_buffer_local_count(int addr_type, int lnum, int offset)
1547 {
1548     buf_T   *buf;
1549     buf_T   *nextbuf;
1550     int     count = offset;
1551 
1552     buf = firstbuf;
1553     while (buf->b_next != NULL && buf->b_fnum < lnum)
1554 	buf = buf->b_next;
1555     while (count != 0)
1556     {
1557 	count += (offset < 0) ? 1 : -1;
1558 	nextbuf = (offset < 0) ? buf->b_prev : buf->b_next;
1559 	if (nextbuf == NULL)
1560 	    break;
1561 	buf = nextbuf;
1562 	if (addr_type == ADDR_LOADED_BUFFERS)
1563 	    /* skip over unloaded buffers */
1564 	    while (buf->b_ml.ml_mfp == NULL)
1565 	    {
1566 		nextbuf = (offset < 0) ? buf->b_prev : buf->b_next;
1567 		if (nextbuf == NULL)
1568 		    break;
1569 		buf = nextbuf;
1570 	    }
1571     }
1572     /* we might have gone too far, last buffer is not loadedd */
1573     if (addr_type == ADDR_LOADED_BUFFERS)
1574 	while (buf->b_ml.ml_mfp == NULL)
1575 	{
1576 	    nextbuf = (offset >= 0) ? buf->b_prev : buf->b_next;
1577 	    if (nextbuf == NULL)
1578 		break;
1579 	    buf = nextbuf;
1580 	}
1581     return buf->b_fnum;
1582 }
1583 
1584 /*
1585  * Return the window number of "win".
1586  * When "win" is NULL return the number of windows.
1587  */
1588     static int
1589 current_win_nr(win_T *win)
1590 {
1591     win_T	*wp;
1592     int		nr = 0;
1593 
1594     FOR_ALL_WINDOWS(wp)
1595     {
1596 	++nr;
1597 	if (wp == win)
1598 	    break;
1599     }
1600     return nr;
1601 }
1602 
1603     static int
1604 current_tab_nr(tabpage_T *tab)
1605 {
1606     tabpage_T	*tp;
1607     int		nr = 0;
1608 
1609     FOR_ALL_TABPAGES(tp)
1610     {
1611 	++nr;
1612 	if (tp == tab)
1613 	    break;
1614     }
1615     return nr;
1616 }
1617 
1618 # define CURRENT_WIN_NR current_win_nr(curwin)
1619 # define LAST_WIN_NR current_win_nr(NULL)
1620 # define CURRENT_TAB_NR current_tab_nr(curtab)
1621 # define LAST_TAB_NR current_tab_nr(NULL)
1622 
1623 /*
1624  * Execute one Ex command.
1625  *
1626  * If 'sourcing' is TRUE, the command will be included in the error message.
1627  *
1628  * 1. skip comment lines and leading space
1629  * 2. handle command modifiers
1630  * 3. find the command
1631  * 4. parse range
1632  * 5. Parse the command.
1633  * 6. parse arguments
1634  * 7. switch on command name
1635  *
1636  * Note: "fgetline" can be NULL.
1637  *
1638  * This function may be called recursively!
1639  */
1640 #if (_MSC_VER == 1200)
1641 /*
1642  * Avoid optimisation bug in VC++ version 6.0
1643  */
1644  #pragma optimize( "g", off )
1645 #endif
1646     static char_u *
1647 do_one_cmd(
1648     char_u		**cmdlinep,
1649     int			sourcing,
1650 #ifdef FEAT_EVAL
1651     struct condstack	*cstack,
1652 #endif
1653     char_u		*(*fgetline)(int, void *, int),
1654     void		*cookie)		/* argument for fgetline() */
1655 {
1656     char_u		*p;
1657     linenr_T		lnum;
1658     long		n;
1659     char		*errormsg = NULL;	/* error message */
1660     char_u		*after_modifier = NULL;
1661     exarg_T		ea;			/* Ex command arguments */
1662     int			save_msg_scroll = msg_scroll;
1663     cmdmod_T		save_cmdmod;
1664     int			save_reg_executing = reg_executing;
1665     int			ni;			/* set when Not Implemented */
1666     char_u		*cmd;
1667 
1668     vim_memset(&ea, 0, sizeof(ea));
1669     ea.line1 = 1;
1670     ea.line2 = 1;
1671 #ifdef FEAT_EVAL
1672     ++ex_nesting_level;
1673 #endif
1674 
1675     /* When the last file has not been edited :q has to be typed twice. */
1676     if (quitmore
1677 #ifdef FEAT_EVAL
1678 	    /* avoid that a function call in 'statusline' does this */
1679 	    && !getline_equal(fgetline, cookie, get_func_line)
1680 #endif
1681 	    /* avoid that an autocommand, e.g. QuitPre, does this */
1682 	    && !getline_equal(fgetline, cookie, getnextac))
1683 	--quitmore;
1684 
1685     /*
1686      * Reset browse, confirm, etc..  They are restored when returning, for
1687      * recursive calls.
1688      */
1689     save_cmdmod = cmdmod;
1690 
1691     /* "#!anything" is handled like a comment. */
1692     if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!')
1693 	goto doend;
1694 
1695 /*
1696  * 1. Skip comment lines and leading white space and colons.
1697  * 2. Handle command modifiers.
1698  */
1699     // The "ea" structure holds the arguments that can be used.
1700     ea.cmd = *cmdlinep;
1701     ea.cmdlinep = cmdlinep;
1702     ea.getline = fgetline;
1703     ea.cookie = cookie;
1704 #ifdef FEAT_EVAL
1705     ea.cstack = cstack;
1706 #endif
1707     if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
1708 	goto doend;
1709 
1710     after_modifier = ea.cmd;
1711 
1712 #ifdef FEAT_EVAL
1713     ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0
1714 			 && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE));
1715 #else
1716     ea.skip = (if_level > 0);
1717 #endif
1718 
1719 /*
1720  * 3. Skip over the range to find the command.  Let "p" point to after it.
1721  *
1722  * We need the command to know what kind of range it uses.
1723  */
1724     cmd = ea.cmd;
1725     ea.cmd = skip_range(ea.cmd, NULL);
1726     if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
1727 	ea.cmd = skipwhite(ea.cmd + 1);
1728     p = find_command(&ea, NULL);
1729 
1730 #ifdef FEAT_EVAL
1731 # ifdef FEAT_PROFILE
1732     // Count this line for profiling if skip is TRUE.
1733     if (do_profiling == PROF_YES
1734 	    && (!ea.skip || cstack->cs_idx == 0 || (cstack->cs_idx > 0
1735 		     && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE))))
1736     {
1737 	int skip = did_emsg || got_int || did_throw;
1738 
1739 	if (ea.cmdidx == CMD_catch)
1740 	    skip = !skip && !(cstack->cs_idx >= 0
1741 			  && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN)
1742 			  && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT));
1743 	else if (ea.cmdidx == CMD_else || ea.cmdidx == CMD_elseif)
1744 	    skip = skip || !(cstack->cs_idx >= 0
1745 			  && !(cstack->cs_flags[cstack->cs_idx]
1746 						  & (CSF_ACTIVE | CSF_TRUE)));
1747 	else if (ea.cmdidx == CMD_finally)
1748 	    skip = FALSE;
1749 	else if (ea.cmdidx != CMD_endif
1750 		&& ea.cmdidx != CMD_endfor
1751 		&& ea.cmdidx != CMD_endtry
1752 		&& ea.cmdidx != CMD_endwhile)
1753 	    skip = ea.skip;
1754 
1755 	if (!skip)
1756 	{
1757 	    if (getline_equal(fgetline, cookie, get_func_line))
1758 		func_line_exec(getline_cookie(fgetline, cookie));
1759 	    else if (getline_equal(fgetline, cookie, getsourceline))
1760 		script_line_exec();
1761 	}
1762     }
1763 # endif
1764 
1765     /* May go to debug mode.  If this happens and the ">quit" debug command is
1766      * used, throw an interrupt exception and skip the next command. */
1767     dbg_check_breakpoint(&ea);
1768     if (!ea.skip && got_int)
1769     {
1770 	ea.skip = TRUE;
1771 	(void)do_intthrow(cstack);
1772     }
1773 #endif
1774 
1775 /*
1776  * 4. parse a range specifier of the form: addr [,addr] [;addr] ..
1777  *
1778  * where 'addr' is:
1779  *
1780  * %	      (entire file)
1781  * $  [+-NUM]
1782  * 'x [+-NUM] (where x denotes a currently defined mark)
1783  * .  [+-NUM]
1784  * [+-NUM]..
1785  * NUM
1786  *
1787  * The ea.cmd pointer is updated to point to the first character following the
1788  * range spec. If an initial address is found, but no second, the upper bound
1789  * is equal to the lower.
1790  */
1791 
1792     // ea.addr_type for user commands is set by find_ucmd
1793     if (!IS_USER_CMDIDX(ea.cmdidx))
1794     {
1795 	if (ea.cmdidx != CMD_SIZE)
1796 	    ea.addr_type = cmdnames[(int)ea.cmdidx].cmd_addr_type;
1797 	else
1798 	    ea.addr_type = ADDR_LINES;
1799 
1800 	// :wincmd range depends on the argument.
1801 	if (ea.cmdidx == CMD_wincmd && p != NULL)
1802 	    get_wincmd_addr_type(skipwhite(p), &ea);
1803 #ifdef FEAT_QUICKFIX
1804 	// :.cc in quickfix window uses line number
1805 	if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf))
1806 	    ea.addr_type = ADDR_OTHER;
1807 #endif
1808     }
1809 
1810     ea.cmd = cmd;
1811     if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
1812 	goto doend;
1813 
1814 /*
1815  * 5. Parse the command.
1816  */
1817 
1818     /*
1819      * Skip ':' and any white space
1820      */
1821     ea.cmd = skipwhite(ea.cmd);
1822     while (*ea.cmd == ':')
1823 	ea.cmd = skipwhite(ea.cmd + 1);
1824 
1825     /*
1826      * If we got a line, but no command, then go to the line.
1827      * If we find a '|' or '\n' we set ea.nextcmd.
1828      */
1829     if (*ea.cmd == NUL || *ea.cmd == '"'
1830 			      || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
1831     {
1832 	/*
1833 	 * strange vi behaviour:
1834 	 * ":3"		jumps to line 3
1835 	 * ":3|..."	prints line 3
1836 	 * ":|"		prints current line
1837 	 */
1838 	if (ea.skip)	    /* skip this if inside :if */
1839 	    goto doend;
1840 	if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2))
1841 	{
1842 	    ea.cmdidx = CMD_print;
1843 	    ea.argt = RANGE+COUNT+TRLBAR;
1844 	    if ((errormsg = invalid_range(&ea)) == NULL)
1845 	    {
1846 		correct_range(&ea);
1847 		ex_print(&ea);
1848 	    }
1849 	}
1850 	else if (ea.addr_count != 0)
1851 	{
1852 	    if (ea.line2 > curbuf->b_ml.ml_line_count)
1853 	    {
1854 		/* With '-' in 'cpoptions' a line number past the file is an
1855 		 * error, otherwise put it at the end of the file. */
1856 		if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
1857 		    ea.line2 = -1;
1858 		else
1859 		    ea.line2 = curbuf->b_ml.ml_line_count;
1860 	    }
1861 
1862 	    if (ea.line2 < 0)
1863 		errormsg = _(e_invrange);
1864 	    else
1865 	    {
1866 		if (ea.line2 == 0)
1867 		    curwin->w_cursor.lnum = 1;
1868 		else
1869 		    curwin->w_cursor.lnum = ea.line2;
1870 		beginline(BL_SOL | BL_FIX);
1871 	    }
1872 	}
1873 	goto doend;
1874     }
1875 
1876     /* If this looks like an undefined user command and there are CmdUndefined
1877      * autocommands defined, trigger the matching autocommands. */
1878     if (p != NULL && ea.cmdidx == CMD_SIZE && !ea.skip
1879 	    && ASCII_ISUPPER(*ea.cmd)
1880 	    && has_cmdundefined())
1881     {
1882 	int ret;
1883 
1884 	p = ea.cmd;
1885 	while (ASCII_ISALNUM(*p))
1886 	    ++p;
1887 	p = vim_strnsave(ea.cmd, (int)(p - ea.cmd));
1888 	ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, TRUE, NULL);
1889 	vim_free(p);
1890 	/* If the autocommands did something and didn't cause an error, try
1891 	 * finding the command again. */
1892 	p = (ret
1893 #ifdef FEAT_EVAL
1894 		&& !aborting()
1895 #endif
1896 		) ? find_command(&ea, NULL) : ea.cmd;
1897     }
1898 
1899     if (p == NULL)
1900     {
1901 	if (!ea.skip)
1902 	    errormsg = _("E464: Ambiguous use of user-defined command");
1903 	goto doend;
1904     }
1905     // Check for wrong commands.
1906     if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78
1907 	    && !IS_USER_CMDIDX(ea.cmdidx))
1908     {
1909 	errormsg = uc_fun_cmd();
1910 	goto doend;
1911     }
1912 
1913     if (ea.cmdidx == CMD_SIZE)
1914     {
1915 	if (!ea.skip)
1916 	{
1917 	    STRCPY(IObuff, _("E492: Not an editor command"));
1918 	    if (!sourcing)
1919 	    {
1920 		/* If the modifier was parsed OK the error must be in the
1921 		 * following command */
1922 		if (after_modifier != NULL)
1923 		    append_command(after_modifier);
1924 		else
1925 		    append_command(*cmdlinep);
1926 	    }
1927 	    errormsg = (char *)IObuff;
1928 	    did_emsg_syntax = TRUE;
1929 	}
1930 	goto doend;
1931     }
1932 
1933     ni = (!IS_USER_CMDIDX(ea.cmdidx)
1934 	    && (cmdnames[ea.cmdidx].cmd_func == ex_ni
1935 #ifdef HAVE_EX_SCRIPT_NI
1936 	     || cmdnames[ea.cmdidx].cmd_func == ex_script_ni
1937 #endif
1938 	     ));
1939 
1940 #ifndef FEAT_EVAL
1941     /*
1942      * When the expression evaluation is disabled, recognize the ":if" and
1943      * ":endif" commands and ignore everything in between it.
1944      */
1945     if (ea.cmdidx == CMD_if)
1946 	++if_level;
1947     if (if_level)
1948     {
1949 	if (ea.cmdidx == CMD_endif)
1950 	    --if_level;
1951 	goto doend;
1952     }
1953 
1954 #endif
1955 
1956     /* forced commands */
1957     if (*p == '!' && ea.cmdidx != CMD_substitute
1958 	    && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic)
1959     {
1960 	++p;
1961 	ea.forceit = TRUE;
1962     }
1963     else
1964 	ea.forceit = FALSE;
1965 
1966 /*
1967  * 6. Parse arguments.  Then check for errors.
1968  */
1969     if (!IS_USER_CMDIDX(ea.cmdidx))
1970 	ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt;
1971 
1972     if (!ea.skip)
1973     {
1974 #ifdef HAVE_SANDBOX
1975 	if (sandbox != 0 && !(ea.argt & SBOXOK))
1976 	{
1977 	    // Command not allowed in sandbox.
1978 	    errormsg = _(e_sandbox);
1979 	    goto doend;
1980 	}
1981 #endif
1982 	if (restricted != 0 && (ea.argt & RESTRICT))
1983 	{
1984 	    errormsg = _("E981: Command not allowed in rvim");
1985 	    goto doend;
1986 	}
1987 	if (!curbuf->b_p_ma && (ea.argt & MODIFY))
1988 	{
1989 	    /* Command not allowed in non-'modifiable' buffer */
1990 	    errormsg = _(e_modifiable);
1991 	    goto doend;
1992 	}
1993 
1994 	if (text_locked() && !(ea.argt & CMDWIN)
1995 		&& !IS_USER_CMDIDX(ea.cmdidx))
1996 	{
1997 	    /* Command not allowed when editing the command line. */
1998 	    errormsg = _(get_text_locked_msg());
1999 	    goto doend;
2000 	}
2001 
2002 	/* Disallow editing another buffer when "curbuf_lock" is set.
2003 	 * Do allow ":checktime" (it is postponed).
2004 	 * Do allow ":edit" (check for an argument later).
2005 	 * Do allow ":file" with no arguments (check for an argument later). */
2006 	if (!(ea.argt & CMDWIN)
2007 		&& ea.cmdidx != CMD_checktime
2008 		&& ea.cmdidx != CMD_edit
2009 		&& ea.cmdidx != CMD_file
2010 		&& !IS_USER_CMDIDX(ea.cmdidx)
2011 		&& curbuf_locked())
2012 	    goto doend;
2013 
2014 	if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0)
2015 	{
2016 	    /* no range allowed */
2017 	    errormsg = _(e_norange);
2018 	    goto doend;
2019 	}
2020     }
2021 
2022     if (!ni && !(ea.argt & BANG) && ea.forceit)	/* no <!> allowed */
2023     {
2024 	errormsg = _(e_nobang);
2025 	goto doend;
2026     }
2027 
2028     /*
2029      * Don't complain about the range if it is not used
2030      * (could happen if line_count is accidentally set to 0).
2031      */
2032     if (!ea.skip && !ni && (ea.argt & RANGE))
2033     {
2034 	/*
2035 	 * If the range is backwards, ask for confirmation and, if given, swap
2036 	 * ea.line1 & ea.line2 so it's forwards again.
2037 	 * When global command is busy, don't ask, will fail below.
2038 	 */
2039 	if (!global_busy && ea.line1 > ea.line2)
2040 	{
2041 	    if (msg_silent == 0)
2042 	    {
2043 		if (sourcing || exmode_active)
2044 		{
2045 		    errormsg = _("E493: Backwards range given");
2046 		    goto doend;
2047 		}
2048 		if (ask_yesno((char_u *)
2049 			_("Backwards range given, OK to swap"), FALSE) != 'y')
2050 		    goto doend;
2051 	    }
2052 	    lnum = ea.line1;
2053 	    ea.line1 = ea.line2;
2054 	    ea.line2 = lnum;
2055 	}
2056 	if ((errormsg = invalid_range(&ea)) != NULL)
2057 	    goto doend;
2058     }
2059 
2060     if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0)
2061 	// default is 1, not cursor
2062 	ea.line2 = 1;
2063 
2064     correct_range(&ea);
2065 
2066 #ifdef FEAT_FOLDING
2067     if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
2068 	    && ea.addr_type == ADDR_LINES)
2069     {
2070 	/* Put the first line at the start of a closed fold, put the last line
2071 	 * at the end of a closed fold. */
2072 	(void)hasFolding(ea.line1, &ea.line1, NULL);
2073 	(void)hasFolding(ea.line2, NULL, &ea.line2);
2074     }
2075 #endif
2076 
2077 #ifdef FEAT_QUICKFIX
2078     /*
2079      * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
2080      * option here, so things like % get expanded.
2081      */
2082     p = replace_makeprg(&ea, p, cmdlinep);
2083     if (p == NULL)
2084 	goto doend;
2085 #endif
2086 
2087     /*
2088      * Skip to start of argument.
2089      * Don't do this for the ":!" command, because ":!! -l" needs the space.
2090      */
2091     if (ea.cmdidx == CMD_bang)
2092 	ea.arg = p;
2093     else
2094 	ea.arg = skipwhite(p);
2095 
2096     // ":file" cannot be run with an argument when "curbuf_lock" is set
2097     if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked())
2098 	goto doend;
2099 
2100     /*
2101      * Check for "++opt=val" argument.
2102      * Must be first, allow ":w ++enc=utf8 !cmd"
2103      */
2104     if (ea.argt & ARGOPT)
2105 	while (ea.arg[0] == '+' && ea.arg[1] == '+')
2106 	    if (getargopt(&ea) == FAIL && !ni)
2107 	    {
2108 		errormsg = _(e_invarg);
2109 		goto doend;
2110 	    }
2111 
2112     if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
2113     {
2114 	if (*ea.arg == '>')			/* append */
2115 	{
2116 	    if (*++ea.arg != '>')		/* typed wrong */
2117 	    {
2118 		errormsg = _("E494: Use w or w>>");
2119 		goto doend;
2120 	    }
2121 	    ea.arg = skipwhite(ea.arg + 1);
2122 	    ea.append = TRUE;
2123 	}
2124 	else if (*ea.arg == '!' && ea.cmdidx == CMD_write)  /* :w !filter */
2125 	{
2126 	    ++ea.arg;
2127 	    ea.usefilter = TRUE;
2128 	}
2129     }
2130 
2131     if (ea.cmdidx == CMD_read)
2132     {
2133 	if (ea.forceit)
2134 	{
2135 	    ea.usefilter = TRUE;		/* :r! filter if ea.forceit */
2136 	    ea.forceit = FALSE;
2137 	}
2138 	else if (*ea.arg == '!')		/* :r !filter */
2139 	{
2140 	    ++ea.arg;
2141 	    ea.usefilter = TRUE;
2142 	}
2143     }
2144 
2145     if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
2146     {
2147 	ea.amount = 1;
2148 	while (*ea.arg == *ea.cmd)		/* count number of '>' or '<' */
2149 	{
2150 	    ++ea.arg;
2151 	    ++ea.amount;
2152 	}
2153 	ea.arg = skipwhite(ea.arg);
2154     }
2155 
2156     /*
2157      * Check for "+command" argument, before checking for next command.
2158      * Don't do this for ":read !cmd" and ":write !cmd".
2159      */
2160     if ((ea.argt & EDITCMD) && !ea.usefilter)
2161 	ea.do_ecmd_cmd = getargcmd(&ea.arg);
2162 
2163     /*
2164      * Check for '|' to separate commands and '"' to start comments.
2165      * Don't do this for ":read !cmd" and ":write !cmd".
2166      */
2167     if ((ea.argt & TRLBAR) && !ea.usefilter)
2168 	separate_nextcmd(&ea);
2169 
2170     /*
2171      * Check for <newline> to end a shell command.
2172      * Also do this for ":read !cmd", ":write !cmd" and ":global".
2173      * Any others?
2174      */
2175     else if (ea.cmdidx == CMD_bang
2176 	    || ea.cmdidx == CMD_terminal
2177 	    || ea.cmdidx == CMD_global
2178 	    || ea.cmdidx == CMD_vglobal
2179 	    || ea.usefilter)
2180     {
2181 	for (p = ea.arg; *p; ++p)
2182 	{
2183 	    /* Remove one backslash before a newline, so that it's possible to
2184 	     * pass a newline to the shell and also a newline that is preceded
2185 	     * with a backslash.  This makes it impossible to end a shell
2186 	     * command in a backslash, but that doesn't appear useful.
2187 	     * Halving the number of backslashes is incompatible with previous
2188 	     * versions. */
2189 	    if (*p == '\\' && p[1] == '\n')
2190 		STRMOVE(p, p + 1);
2191 	    else if (*p == '\n')
2192 	    {
2193 		ea.nextcmd = p + 1;
2194 		*p = NUL;
2195 		break;
2196 	    }
2197 	}
2198     }
2199 
2200     if ((ea.argt & DFLALL) && ea.addr_count == 0)
2201     {
2202 	buf_T	    *buf;
2203 
2204 	ea.line1 = 1;
2205 	switch (ea.addr_type)
2206 	{
2207 	    case ADDR_LINES:
2208 	    case ADDR_OTHER:
2209 		ea.line2 = curbuf->b_ml.ml_line_count;
2210 		break;
2211 	    case ADDR_LOADED_BUFFERS:
2212 		buf = firstbuf;
2213 		while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
2214 		    buf = buf->b_next;
2215 		ea.line1 = buf->b_fnum;
2216 		buf = lastbuf;
2217 		while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
2218 		    buf = buf->b_prev;
2219 		ea.line2 = buf->b_fnum;
2220 		break;
2221 	    case ADDR_BUFFERS:
2222 		ea.line1 = firstbuf->b_fnum;
2223 		ea.line2 = lastbuf->b_fnum;
2224 		break;
2225 	    case ADDR_WINDOWS:
2226 		ea.line2 = LAST_WIN_NR;
2227 		break;
2228 	    case ADDR_TABS:
2229 		ea.line2 = LAST_TAB_NR;
2230 		break;
2231 	    case ADDR_TABS_RELATIVE:
2232 		ea.line2 = 1;
2233 		break;
2234 	    case ADDR_ARGUMENTS:
2235 		if (ARGCOUNT == 0)
2236 		    ea.line1 = ea.line2 = 0;
2237 		else
2238 		    ea.line2 = ARGCOUNT;
2239 		break;
2240 	    case ADDR_QUICKFIX_VALID:
2241 #ifdef FEAT_QUICKFIX
2242 		ea.line2 = qf_get_valid_size(&ea);
2243 		if (ea.line2 == 0)
2244 		    ea.line2 = 1;
2245 #endif
2246 		break;
2247 	    case ADDR_NONE:
2248 	    case ADDR_UNSIGNED:
2249 	    case ADDR_QUICKFIX:
2250 		iemsg(_("INTERNAL: Cannot use DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
2251 		break;
2252 	}
2253     }
2254 
2255     /* accept numbered register only when no count allowed (:put) */
2256     if (       (ea.argt & REGSTR)
2257 	    && *ea.arg != NUL
2258 	       /* Do not allow register = for user commands */
2259 	    && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
2260 	    && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg)))
2261     {
2262 #ifndef FEAT_CLIPBOARD
2263 	/* check these explicitly for a more specific error message */
2264 	if (*ea.arg == '*' || *ea.arg == '+')
2265 	{
2266 	    errormsg = _(e_invalidreg);
2267 	    goto doend;
2268 	}
2269 #endif
2270 	if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
2271 					      && !IS_USER_CMDIDX(ea.cmdidx))))
2272 	{
2273 	    ea.regname = *ea.arg++;
2274 #ifdef FEAT_EVAL
2275 	    /* for '=' register: accept the rest of the line as an expression */
2276 	    if (ea.arg[-1] == '=' && ea.arg[0] != NUL)
2277 	    {
2278 		set_expr_line(vim_strsave(ea.arg));
2279 		ea.arg += STRLEN(ea.arg);
2280 	    }
2281 #endif
2282 	    ea.arg = skipwhite(ea.arg);
2283 	}
2284     }
2285 
2286     /*
2287      * Check for a count.  When accepting a BUFNAME, don't use "123foo" as a
2288      * count, it's a buffer name.
2289      */
2290     if ((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg)
2291 	    && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
2292 							  || VIM_ISWHITE(*p)))
2293     {
2294 	n = getdigits(&ea.arg);
2295 	ea.arg = skipwhite(ea.arg);
2296 	if (n <= 0 && !ni && (ea.argt & ZEROR) == 0)
2297 	{
2298 	    errormsg = _(e_zerocount);
2299 	    goto doend;
2300 	}
2301 	if (ea.addr_type != ADDR_LINES)	// e.g. :buffer 2, :sleep 3
2302 	{
2303 	    ea.line2 = n;
2304 	    if (ea.addr_count == 0)
2305 		ea.addr_count = 1;
2306 	}
2307 	else
2308 	{
2309 	    ea.line1 = ea.line2;
2310 	    ea.line2 += n - 1;
2311 	    ++ea.addr_count;
2312 	    /*
2313 	     * Be vi compatible: no error message for out of range.
2314 	     */
2315 	    if (ea.line2 > curbuf->b_ml.ml_line_count)
2316 		ea.line2 = curbuf->b_ml.ml_line_count;
2317 	}
2318     }
2319 
2320     /*
2321      * Check for flags: 'l', 'p' and '#'.
2322      */
2323     if (ea.argt & EXFLAGS)
2324 	get_flags(&ea);
2325 						/* no arguments allowed */
2326     if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL
2327 	    && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & TRLBAR) == 0))
2328     {
2329 	errormsg = _(e_trailing);
2330 	goto doend;
2331     }
2332 
2333     if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL)
2334     {
2335 	errormsg = _(e_argreq);
2336 	goto doend;
2337     }
2338 
2339 #ifdef FEAT_EVAL
2340     /*
2341      * Skip the command when it's not going to be executed.
2342      * The commands like :if, :endif, etc. always need to be executed.
2343      * Also make an exception for commands that handle a trailing command
2344      * themselves.
2345      */
2346     if (ea.skip)
2347     {
2348 	switch (ea.cmdidx)
2349 	{
2350 	    /* commands that need evaluation */
2351 	    case CMD_while:
2352 	    case CMD_endwhile:
2353 	    case CMD_for:
2354 	    case CMD_endfor:
2355 	    case CMD_if:
2356 	    case CMD_elseif:
2357 	    case CMD_else:
2358 	    case CMD_endif:
2359 	    case CMD_try:
2360 	    case CMD_catch:
2361 	    case CMD_finally:
2362 	    case CMD_endtry:
2363 	    case CMD_function:
2364 				break;
2365 
2366 	    /* Commands that handle '|' themselves.  Check: A command should
2367 	     * either have the TRLBAR flag, appear in this list or appear in
2368 	     * the list at ":help :bar". */
2369 	    case CMD_aboveleft:
2370 	    case CMD_and:
2371 	    case CMD_belowright:
2372 	    case CMD_botright:
2373 	    case CMD_browse:
2374 	    case CMD_call:
2375 	    case CMD_confirm:
2376 	    case CMD_delfunction:
2377 	    case CMD_djump:
2378 	    case CMD_dlist:
2379 	    case CMD_dsearch:
2380 	    case CMD_dsplit:
2381 	    case CMD_echo:
2382 	    case CMD_echoerr:
2383 	    case CMD_echomsg:
2384 	    case CMD_echon:
2385 	    case CMD_execute:
2386 	    case CMD_filter:
2387 	    case CMD_help:
2388 	    case CMD_hide:
2389 	    case CMD_ijump:
2390 	    case CMD_ilist:
2391 	    case CMD_isearch:
2392 	    case CMD_isplit:
2393 	    case CMD_keepalt:
2394 	    case CMD_keepjumps:
2395 	    case CMD_keepmarks:
2396 	    case CMD_keeppatterns:
2397 	    case CMD_leftabove:
2398 	    case CMD_let:
2399 	    case CMD_lockmarks:
2400 	    case CMD_lua:
2401 	    case CMD_match:
2402 	    case CMD_mzscheme:
2403 	    case CMD_noautocmd:
2404 	    case CMD_noswapfile:
2405 	    case CMD_perl:
2406 	    case CMD_psearch:
2407 	    case CMD_python:
2408 	    case CMD_py3:
2409 	    case CMD_python3:
2410 	    case CMD_return:
2411 	    case CMD_rightbelow:
2412 	    case CMD_ruby:
2413 	    case CMD_silent:
2414 	    case CMD_smagic:
2415 	    case CMD_snomagic:
2416 	    case CMD_substitute:
2417 	    case CMD_syntax:
2418 	    case CMD_tab:
2419 	    case CMD_tcl:
2420 	    case CMD_throw:
2421 	    case CMD_tilde:
2422 	    case CMD_topleft:
2423 	    case CMD_unlet:
2424 	    case CMD_verbose:
2425 	    case CMD_vertical:
2426 	    case CMD_wincmd:
2427 				break;
2428 
2429 	    default:		goto doend;
2430 	}
2431     }
2432 #endif
2433 
2434     if (ea.argt & XFILE)
2435     {
2436 	if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
2437 	    goto doend;
2438     }
2439 
2440     /*
2441      * Accept buffer name.  Cannot be used at the same time with a buffer
2442      * number.  Don't do this for a user command.
2443      */
2444     if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
2445 	    && !IS_USER_CMDIDX(ea.cmdidx))
2446     {
2447 	/*
2448 	 * :bdelete, :bwipeout and :bunload take several arguments, separated
2449 	 * by spaces: find next space (skipping over escaped characters).
2450 	 * The others take one argument: ignore trailing spaces.
2451 	 */
2452 	if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout
2453 						  || ea.cmdidx == CMD_bunload)
2454 	    p = skiptowhite_esc(ea.arg);
2455 	else
2456 	{
2457 	    p = ea.arg + STRLEN(ea.arg);
2458 	    while (p > ea.arg && VIM_ISWHITE(p[-1]))
2459 		--p;
2460 	}
2461 	ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0,
2462 								FALSE, FALSE);
2463 	if (ea.line2 < 0)	    /* failed */
2464 	    goto doend;
2465 	ea.addr_count = 1;
2466 	ea.arg = skipwhite(p);
2467     }
2468 
2469     /* The :try command saves the emsg_silent flag, reset it here when
2470      * ":silent! try" was used, it should only apply to :try itself. */
2471     if (ea.cmdidx == CMD_try && ea.did_esilent > 0)
2472     {
2473 	emsg_silent -= ea.did_esilent;
2474 	if (emsg_silent < 0)
2475 	    emsg_silent = 0;
2476 	ea.did_esilent = 0;
2477     }
2478 
2479 /*
2480  * 7. Execute the command.
2481  */
2482 
2483     if (IS_USER_CMDIDX(ea.cmdidx))
2484     {
2485 	/*
2486 	 * Execute a user-defined command.
2487 	 */
2488 	do_ucmd(&ea);
2489     }
2490     else
2491     {
2492 	/*
2493 	 * Call the function to execute the builtin command.
2494 	 */
2495 	ea.errmsg = NULL;
2496 	(cmdnames[ea.cmdidx].cmd_func)(&ea);
2497 	if (ea.errmsg != NULL)
2498 	    errormsg = _(ea.errmsg);
2499     }
2500 
2501 #ifdef FEAT_EVAL
2502     /*
2503      * If the command just executed called do_cmdline(), any throw or ":return"
2504      * or ":finish" encountered there must also check the cstack of the still
2505      * active do_cmdline() that called this do_one_cmd().  Rethrow an uncaught
2506      * exception, or reanimate a returned function or finished script file and
2507      * return or finish it again.
2508      */
2509     if (need_rethrow)
2510 	do_throw(cstack);
2511     else if (check_cstack)
2512     {
2513 	if (source_finished(fgetline, cookie))
2514 	    do_finish(&ea, TRUE);
2515 	else if (getline_equal(fgetline, cookie, get_func_line)
2516 						   && current_func_returned())
2517 	    do_return(&ea, TRUE, FALSE, NULL);
2518     }
2519     need_rethrow = check_cstack = FALSE;
2520 #endif
2521 
2522 doend:
2523     if (curwin->w_cursor.lnum == 0)	/* can happen with zero line number */
2524     {
2525 	curwin->w_cursor.lnum = 1;
2526 	curwin->w_cursor.col = 0;
2527     }
2528 
2529     if (errormsg != NULL && *errormsg != NUL && !did_emsg)
2530     {
2531 	if (sourcing)
2532 	{
2533 	    if (errormsg != (char *)IObuff)
2534 	    {
2535 		STRCPY(IObuff, errormsg);
2536 		errormsg = (char *)IObuff;
2537 	    }
2538 	    append_command(*cmdlinep);
2539 	}
2540 	emsg(errormsg);
2541     }
2542 #ifdef FEAT_EVAL
2543     do_errthrow(cstack,
2544 	    (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx))
2545 			? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
2546 #endif
2547 
2548     if (ea.verbose_save >= 0)
2549 	p_verbose = ea.verbose_save;
2550 
2551     free_cmdmod();
2552     cmdmod = save_cmdmod;
2553     reg_executing = save_reg_executing;
2554 
2555     if (ea.save_msg_silent != -1)
2556     {
2557 	/* messages could be enabled for a serious error, need to check if the
2558 	 * counters don't become negative */
2559 	if (!did_emsg || msg_silent > ea.save_msg_silent)
2560 	    msg_silent = ea.save_msg_silent;
2561 	emsg_silent -= ea.did_esilent;
2562 	if (emsg_silent < 0)
2563 	    emsg_silent = 0;
2564 	/* Restore msg_scroll, it's set by file I/O commands, even when no
2565 	 * message is actually displayed. */
2566 	msg_scroll = save_msg_scroll;
2567 
2568 	/* "silent reg" or "silent echo x" inside "redir" leaves msg_col
2569 	 * somewhere in the line.  Put it back in the first column. */
2570 	if (redirecting())
2571 	    msg_col = 0;
2572     }
2573 
2574 #ifdef HAVE_SANDBOX
2575     if (ea.did_sandbox)
2576 	--sandbox;
2577 #endif
2578 
2579     if (ea.nextcmd && *ea.nextcmd == NUL)	/* not really a next command */
2580 	ea.nextcmd = NULL;
2581 
2582 #ifdef FEAT_EVAL
2583     --ex_nesting_level;
2584 #endif
2585 
2586     return ea.nextcmd;
2587 }
2588 #if (_MSC_VER == 1200)
2589  #pragma optimize( "", on )
2590 #endif
2591 
2592 /*
2593  * Parse and skip over command modifiers:
2594  * - update eap->cmd
2595  * - store flags in "cmdmod".
2596  * - Set ex_pressedreturn for an empty command line.
2597  * - set msg_silent for ":silent"
2598  * - set 'eventignore' to "all" for ":noautocmd"
2599  * - set p_verbose for ":verbose"
2600  * - Increment "sandbox" for ":sandbox"
2601  * When "skip_only" is TRUE the global variables are not changed, except for
2602  * "cmdmod".
2603  * Return FAIL when the command is not to be executed.
2604  * May set "errormsg" to an error message.
2605  */
2606     int
2607 parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only)
2608 {
2609     char_u *p;
2610 
2611     vim_memset(&cmdmod, 0, sizeof(cmdmod));
2612     eap->verbose_save = -1;
2613     eap->save_msg_silent = -1;
2614 
2615     // Repeat until no more command modifiers are found.
2616     for (;;)
2617     {
2618 	while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':')
2619 	    ++eap->cmd;
2620 
2621 	/* in ex mode, an empty line works like :+ */
2622 	if (*eap->cmd == NUL && exmode_active
2623 		   && (getline_equal(eap->getline, eap->cookie, getexmodeline)
2624 		       || getline_equal(eap->getline, eap->cookie, getexline))
2625 			&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
2626 	{
2627 	    eap->cmd = (char_u *)"+";
2628 	    if (!skip_only)
2629 		ex_pressedreturn = TRUE;
2630 	}
2631 
2632 	/* ignore comment and empty lines */
2633 	if (*eap->cmd == '"')
2634 	    return FAIL;
2635 	if (*eap->cmd == NUL)
2636 	{
2637 	    if (!skip_only)
2638 		ex_pressedreturn = TRUE;
2639 	    return FAIL;
2640 	}
2641 
2642 	p = skip_range(eap->cmd, NULL);
2643 	switch (*p)
2644 	{
2645 	    /* When adding an entry, also modify cmd_exists(). */
2646 	    case 'a':	if (!checkforcmd(&eap->cmd, "aboveleft", 3))
2647 			    break;
2648 			cmdmod.split |= WSP_ABOVE;
2649 			continue;
2650 
2651 	    case 'b':	if (checkforcmd(&eap->cmd, "belowright", 3))
2652 			{
2653 			    cmdmod.split |= WSP_BELOW;
2654 			    continue;
2655 			}
2656 			if (checkforcmd(&eap->cmd, "browse", 3))
2657 			{
2658 #ifdef FEAT_BROWSE_CMD
2659 			    cmdmod.browse = TRUE;
2660 #endif
2661 			    continue;
2662 			}
2663 			if (!checkforcmd(&eap->cmd, "botright", 2))
2664 			    break;
2665 			cmdmod.split |= WSP_BOT;
2666 			continue;
2667 
2668 	    case 'c':	if (!checkforcmd(&eap->cmd, "confirm", 4))
2669 			    break;
2670 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2671 			cmdmod.confirm = TRUE;
2672 #endif
2673 			continue;
2674 
2675 	    case 'k':	if (checkforcmd(&eap->cmd, "keepmarks", 3))
2676 			{
2677 			    cmdmod.keepmarks = TRUE;
2678 			    continue;
2679 			}
2680 			if (checkforcmd(&eap->cmd, "keepalt", 5))
2681 			{
2682 			    cmdmod.keepalt = TRUE;
2683 			    continue;
2684 			}
2685 			if (checkforcmd(&eap->cmd, "keeppatterns", 5))
2686 			{
2687 			    cmdmod.keeppatterns = TRUE;
2688 			    continue;
2689 			}
2690 			if (!checkforcmd(&eap->cmd, "keepjumps", 5))
2691 			    break;
2692 			cmdmod.keepjumps = TRUE;
2693 			continue;
2694 
2695 	    case 'f':	/* only accept ":filter {pat} cmd" */
2696 			{
2697 			    char_u *reg_pat;
2698 
2699 			    if (!checkforcmd(&p, "filter", 4)
2700 						|| *p == NUL || ends_excmd(*p))
2701 				break;
2702 			    if (*p == '!')
2703 			    {
2704 				cmdmod.filter_force = TRUE;
2705 				p = skipwhite(p + 1);
2706 				if (*p == NUL || ends_excmd(*p))
2707 				    break;
2708 			    }
2709 			    if (skip_only)
2710 				p = skip_vimgrep_pat(p, NULL, NULL);
2711 			    else
2712 				// NOTE: This puts a NUL after the pattern.
2713 				p = skip_vimgrep_pat(p, &reg_pat, NULL);
2714 			    if (p == NULL || *p == NUL)
2715 				break;
2716 			    if (!skip_only)
2717 			    {
2718 				cmdmod.filter_regmatch.regprog =
2719 						vim_regcomp(reg_pat, RE_MAGIC);
2720 				if (cmdmod.filter_regmatch.regprog == NULL)
2721 				    break;
2722 			    }
2723 			    eap->cmd = p;
2724 			    continue;
2725 			}
2726 
2727 			/* ":hide" and ":hide | cmd" are not modifiers */
2728 	    case 'h':	if (p != eap->cmd || !checkforcmd(&p, "hide", 3)
2729 					       || *p == NUL || ends_excmd(*p))
2730 			    break;
2731 			eap->cmd = p;
2732 			cmdmod.hide = TRUE;
2733 			continue;
2734 
2735 	    case 'l':	if (checkforcmd(&eap->cmd, "lockmarks", 3))
2736 			{
2737 			    cmdmod.lockmarks = TRUE;
2738 			    continue;
2739 			}
2740 
2741 			if (!checkforcmd(&eap->cmd, "leftabove", 5))
2742 			    break;
2743 			cmdmod.split |= WSP_ABOVE;
2744 			continue;
2745 
2746 	    case 'n':	if (checkforcmd(&eap->cmd, "noautocmd", 3))
2747 			{
2748 			    if (cmdmod.save_ei == NULL && !skip_only)
2749 			    {
2750 				/* Set 'eventignore' to "all". Restore the
2751 				 * existing option value later. */
2752 				cmdmod.save_ei = vim_strsave(p_ei);
2753 				set_string_option_direct((char_u *)"ei", -1,
2754 					 (char_u *)"all", OPT_FREE, SID_NONE);
2755 			    }
2756 			    continue;
2757 			}
2758 			if (!checkforcmd(&eap->cmd, "noswapfile", 3))
2759 			    break;
2760 			cmdmod.noswapfile = TRUE;
2761 			continue;
2762 
2763 	    case 'r':	if (!checkforcmd(&eap->cmd, "rightbelow", 6))
2764 			    break;
2765 			cmdmod.split |= WSP_BELOW;
2766 			continue;
2767 
2768 	    case 's':	if (checkforcmd(&eap->cmd, "sandbox", 3))
2769 			{
2770 #ifdef HAVE_SANDBOX
2771 			    if (!skip_only)
2772 			    {
2773 				if (!eap->did_sandbox)
2774 				    ++sandbox;
2775 				eap->did_sandbox = TRUE;
2776 			    }
2777 #endif
2778 			    continue;
2779 			}
2780 			if (!checkforcmd(&eap->cmd, "silent", 3))
2781 			    break;
2782 			if (!skip_only)
2783 			{
2784 			    if (eap->save_msg_silent == -1)
2785 				eap->save_msg_silent = msg_silent;
2786 			    ++msg_silent;
2787 			}
2788 			if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
2789 			{
2790 			    /* ":silent!", but not "silent !cmd" */
2791 			    eap->cmd = skipwhite(eap->cmd + 1);
2792 			    if (!skip_only)
2793 			    {
2794 				++emsg_silent;
2795 				++eap->did_esilent;
2796 			    }
2797 			}
2798 			continue;
2799 
2800 	    case 't':	if (checkforcmd(&p, "tab", 3))
2801 			{
2802 			    if (!skip_only)
2803 			    {
2804 				long tabnr = get_address(eap, &eap->cmd,
2805 						    ADDR_TABS, eap->skip,
2806 						    skip_only, FALSE, 1);
2807 				if (tabnr == MAXLNUM)
2808 				    cmdmod.tab = tabpage_index(curtab) + 1;
2809 				else
2810 				{
2811 				    if (tabnr < 0 || tabnr > LAST_TAB_NR)
2812 				    {
2813 					*errormsg = _(e_invrange);
2814 					return FAIL;
2815 				    }
2816 				    cmdmod.tab = tabnr + 1;
2817 				}
2818 			    }
2819 			    eap->cmd = p;
2820 			    continue;
2821 			}
2822 			if (!checkforcmd(&eap->cmd, "topleft", 2))
2823 			    break;
2824 			cmdmod.split |= WSP_TOP;
2825 			continue;
2826 
2827 	    case 'u':	if (!checkforcmd(&eap->cmd, "unsilent", 3))
2828 			    break;
2829 			if (!skip_only)
2830 			{
2831 			    if (eap->save_msg_silent == -1)
2832 				eap->save_msg_silent = msg_silent;
2833 			    msg_silent = 0;
2834 			}
2835 			continue;
2836 
2837 	    case 'v':	if (checkforcmd(&eap->cmd, "vertical", 4))
2838 			{
2839 			    cmdmod.split |= WSP_VERT;
2840 			    continue;
2841 			}
2842 			if (!checkforcmd(&p, "verbose", 4))
2843 			    break;
2844 			if (!skip_only)
2845 			{
2846 			    if (eap->verbose_save < 0)
2847 				eap->verbose_save = p_verbose;
2848 			    if (vim_isdigit(*eap->cmd))
2849 				p_verbose = atoi((char *)eap->cmd);
2850 			    else
2851 				p_verbose = 1;
2852 			}
2853 			eap->cmd = p;
2854 			continue;
2855 	}
2856 	break;
2857     }
2858 
2859     return OK;
2860 }
2861 
2862 /*
2863  * Free contents of "cmdmod".
2864  */
2865     static void
2866 free_cmdmod(void)
2867 {
2868     if (cmdmod.save_ei != NULL)
2869     {
2870 	/* Restore 'eventignore' to the value before ":noautocmd". */
2871 	set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
2872 							  OPT_FREE, SID_NONE);
2873 	free_string_option(cmdmod.save_ei);
2874     }
2875 
2876     if (cmdmod.filter_regmatch.regprog != NULL)
2877 	vim_regfree(cmdmod.filter_regmatch.regprog);
2878 }
2879 
2880 /*
2881  * Parse the address range, if any, in "eap".
2882  * May set the last search pattern, unless "silent" is TRUE.
2883  * Return FAIL and set "errormsg" or return OK.
2884  */
2885     int
2886 parse_cmd_address(exarg_T *eap, char **errormsg, int silent)
2887 {
2888     int		address_count = 1;
2889     linenr_T	lnum;
2890 
2891     // Repeat for all ',' or ';' separated addresses.
2892     for (;;)
2893     {
2894 	eap->line1 = eap->line2;
2895 	switch (eap->addr_type)
2896 	{
2897 	    case ADDR_LINES:
2898 	    case ADDR_OTHER:
2899 		// default is current line number
2900 		eap->line2 = curwin->w_cursor.lnum;
2901 		break;
2902 	    case ADDR_WINDOWS:
2903 		eap->line2 = CURRENT_WIN_NR;
2904 		break;
2905 	    case ADDR_ARGUMENTS:
2906 		eap->line2 = curwin->w_arg_idx + 1;
2907 		if (eap->line2 > ARGCOUNT)
2908 		    eap->line2 = ARGCOUNT;
2909 		break;
2910 	    case ADDR_LOADED_BUFFERS:
2911 	    case ADDR_BUFFERS:
2912 		eap->line2 = curbuf->b_fnum;
2913 		break;
2914 	    case ADDR_TABS:
2915 		eap->line2 = CURRENT_TAB_NR;
2916 		break;
2917 	    case ADDR_TABS_RELATIVE:
2918 	    case ADDR_UNSIGNED:
2919 		eap->line2 = 1;
2920 		break;
2921 	    case ADDR_QUICKFIX:
2922 #ifdef FEAT_QUICKFIX
2923 		eap->line2 = qf_get_cur_idx(eap);
2924 #endif
2925 		break;
2926 	    case ADDR_QUICKFIX_VALID:
2927 #ifdef FEAT_QUICKFIX
2928 		eap->line2 = qf_get_cur_valid_idx(eap);
2929 #endif
2930 		break;
2931 	    case ADDR_NONE:
2932 		// Will give an error later if a range is found.
2933 		break;
2934 	}
2935 	eap->cmd = skipwhite(eap->cmd);
2936 	lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
2937 					eap->addr_count == 0, address_count++);
2938 	if (eap->cmd == NULL)	// error detected
2939 	    return FAIL;
2940 	if (lnum == MAXLNUM)
2941 	{
2942 	    if (*eap->cmd == '%')   // '%' - all lines
2943 	    {
2944 		++eap->cmd;
2945 		switch (eap->addr_type)
2946 		{
2947 		    case ADDR_LINES:
2948 		    case ADDR_OTHER:
2949 			eap->line1 = 1;
2950 			eap->line2 = curbuf->b_ml.ml_line_count;
2951 			break;
2952 		    case ADDR_LOADED_BUFFERS:
2953 			{
2954 			    buf_T	*buf = firstbuf;
2955 
2956 			    while (buf->b_next != NULL
2957 						  && buf->b_ml.ml_mfp == NULL)
2958 				buf = buf->b_next;
2959 			    eap->line1 = buf->b_fnum;
2960 			    buf = lastbuf;
2961 			    while (buf->b_prev != NULL
2962 						  && buf->b_ml.ml_mfp == NULL)
2963 				buf = buf->b_prev;
2964 			    eap->line2 = buf->b_fnum;
2965 			    break;
2966 			}
2967 		    case ADDR_BUFFERS:
2968 			eap->line1 = firstbuf->b_fnum;
2969 			eap->line2 = lastbuf->b_fnum;
2970 			break;
2971 		    case ADDR_WINDOWS:
2972 		    case ADDR_TABS:
2973 			if (IS_USER_CMDIDX(eap->cmdidx))
2974 			{
2975 			    eap->line1 = 1;
2976 			    eap->line2 = eap->addr_type == ADDR_WINDOWS
2977 						  ? LAST_WIN_NR : LAST_TAB_NR;
2978 			}
2979 			else
2980 			{
2981 			    // there is no Vim command which uses '%' and
2982 			    // ADDR_WINDOWS or ADDR_TABS
2983 			    *errormsg = _(e_invrange);
2984 			    return FAIL;
2985 			}
2986 			break;
2987 		    case ADDR_TABS_RELATIVE:
2988 		    case ADDR_UNSIGNED:
2989 		    case ADDR_QUICKFIX:
2990 			*errormsg = _(e_invrange);
2991 			return FAIL;
2992 		    case ADDR_ARGUMENTS:
2993 			if (ARGCOUNT == 0)
2994 			    eap->line1 = eap->line2 = 0;
2995 			else
2996 			{
2997 			    eap->line1 = 1;
2998 			    eap->line2 = ARGCOUNT;
2999 			}
3000 			break;
3001 		    case ADDR_QUICKFIX_VALID:
3002 #ifdef FEAT_QUICKFIX
3003 			eap->line1 = 1;
3004 			eap->line2 = qf_get_valid_size(eap);
3005 			if (eap->line2 == 0)
3006 			    eap->line2 = 1;
3007 #endif
3008 			break;
3009 		    case ADDR_NONE:
3010 			// Will give an error later if a range is found.
3011 			break;
3012 		}
3013 		++eap->addr_count;
3014 	    }
3015 	    else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
3016 	    {
3017 		pos_T	    *fp;
3018 
3019 		// '*' - visual area
3020 		if (eap->addr_type != ADDR_LINES)
3021 		{
3022 		    *errormsg = _(e_invrange);
3023 		    return FAIL;
3024 		}
3025 
3026 		++eap->cmd;
3027 		if (!eap->skip)
3028 		{
3029 		    fp = getmark('<', FALSE);
3030 		    if (check_mark(fp) == FAIL)
3031 			return FAIL;
3032 		    eap->line1 = fp->lnum;
3033 		    fp = getmark('>', FALSE);
3034 		    if (check_mark(fp) == FAIL)
3035 			return FAIL;
3036 		    eap->line2 = fp->lnum;
3037 		    ++eap->addr_count;
3038 		}
3039 	    }
3040 	}
3041 	else
3042 	    eap->line2 = lnum;
3043 	eap->addr_count++;
3044 
3045 	if (*eap->cmd == ';')
3046 	{
3047 	    if (!eap->skip)
3048 	    {
3049 		curwin->w_cursor.lnum = eap->line2;
3050 		// don't leave the cursor on an illegal line or column
3051 		check_cursor();
3052 	    }
3053 	}
3054 	else if (*eap->cmd != ',')
3055 	    break;
3056 	++eap->cmd;
3057     }
3058 
3059     // One address given: set start and end lines.
3060     if (eap->addr_count == 1)
3061     {
3062 	eap->line1 = eap->line2;
3063 	// ... but only implicit: really no address given
3064 	if (lnum == MAXLNUM)
3065 	    eap->addr_count = 0;
3066     }
3067     return OK;
3068 }
3069 
3070 /*
3071  * Check for an Ex command with optional tail.
3072  * If there is a match advance "pp" to the argument and return TRUE.
3073  */
3074     int
3075 checkforcmd(
3076     char_u	**pp,		/* start of command */
3077     char	*cmd,		/* name of command */
3078     int		len)		/* required length */
3079 {
3080     int		i;
3081 
3082     for (i = 0; cmd[i] != NUL; ++i)
3083 	if (((char_u *)cmd)[i] != (*pp)[i])
3084 	    break;
3085     if (i >= len && !isalpha((*pp)[i]))
3086     {
3087 	*pp = skipwhite(*pp + i);
3088 	return TRUE;
3089     }
3090     return FALSE;
3091 }
3092 
3093 /*
3094  * Append "cmd" to the error message in IObuff.
3095  * Takes care of limiting the length and handling 0xa0, which would be
3096  * invisible otherwise.
3097  */
3098     static void
3099 append_command(char_u *cmd)
3100 {
3101     char_u *s = cmd;
3102     char_u *d;
3103 
3104     STRCAT(IObuff, ": ");
3105     d = IObuff + STRLEN(IObuff);
3106     while (*s != NUL && d - IObuff < IOSIZE - 7)
3107     {
3108 	if (enc_utf8 ? (s[0] == 0xc2 && s[1] == 0xa0) : *s == 0xa0)
3109 	{
3110 	    s += enc_utf8 ? 2 : 1;
3111 	    STRCPY(d, "<a0>");
3112 	    d += 4;
3113 	}
3114 	else
3115 	    MB_COPY_CHAR(s, d);
3116     }
3117     *d = NUL;
3118 }
3119 
3120 /*
3121  * Find an Ex command by its name, either built-in or user.
3122  * Start of the name can be found at eap->cmd.
3123  * Sets eap->cmdidx and returns a pointer to char after the command name.
3124  * "full" is set to TRUE if the whole command name matched.
3125  * Returns NULL for an ambiguous user command.
3126  */
3127     static char_u *
3128 find_command(exarg_T *eap, int *full UNUSED)
3129 {
3130     int		len;
3131     char_u	*p;
3132     int		i;
3133 
3134     /*
3135      * Isolate the command and search for it in the command table.
3136      * Exceptions:
3137      * - the 'k' command can directly be followed by any character.
3138      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
3139      *	    but :sre[wind] is another command, as are :scr[iptnames],
3140      *	    :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
3141      * - the "d" command can directly be followed by 'l' or 'p' flag.
3142      */
3143     p = eap->cmd;
3144     if (*p == 'k')
3145     {
3146 	eap->cmdidx = CMD_k;
3147 	++p;
3148     }
3149     else if (p[0] == 's'
3150 	    && ((p[1] == 'c' && (p[2] == NUL || (p[2] != 's' && p[2] != 'r'
3151 			&& (p[3] == NUL || (p[3] != 'i' && p[4] != 'p')))))
3152 		|| p[1] == 'g'
3153 		|| (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
3154 		|| p[1] == 'I'
3155 		|| (p[1] == 'r' && p[2] != 'e')))
3156     {
3157 	eap->cmdidx = CMD_substitute;
3158 	++p;
3159     }
3160     else
3161     {
3162 	while (ASCII_ISALPHA(*p))
3163 	    ++p;
3164 	/* for python 3.x support ":py3", ":python3", ":py3file", etc. */
3165 	if (eap->cmd[0] == 'p' && eap->cmd[1] == 'y')
3166 	    while (ASCII_ISALNUM(*p))
3167 		++p;
3168 
3169 	/* check for non-alpha command */
3170 	if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
3171 	    ++p;
3172 	len = (int)(p - eap->cmd);
3173 	if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
3174 	{
3175 	    /* Check for ":dl", ":dell", etc. to ":deletel": that's
3176 	     * :delete with the 'l' flag.  Same for 'p'. */
3177 	    for (i = 0; i < len; ++i)
3178 		if (eap->cmd[i] != ((char_u *)"delete")[i])
3179 		    break;
3180 	    if (i == len - 1)
3181 	    {
3182 		--len;
3183 		if (p[-1] == 'l')
3184 		    eap->flags |= EXFLAG_LIST;
3185 		else
3186 		    eap->flags |= EXFLAG_PRINT;
3187 	    }
3188 	}
3189 
3190 	if (ASCII_ISLOWER(eap->cmd[0]))
3191 	{
3192 	    int c1 = eap->cmd[0];
3193 	    int c2 = eap->cmd[1];
3194 
3195 	    if (command_count != (int)CMD_SIZE)
3196 	    {
3197 		iemsg(_("E943: Command table needs to be updated, run 'make cmdidxs'"));
3198 		getout(1);
3199 	    }
3200 
3201 	    /* Use a precomputed index for fast look-up in cmdnames[]
3202 	     * taking into account the first 2 letters of eap->cmd. */
3203 	    eap->cmdidx = cmdidxs1[CharOrdLow(c1)];
3204 	    if (ASCII_ISLOWER(c2))
3205 		eap->cmdidx += cmdidxs2[CharOrdLow(c1)][CharOrdLow(c2)];
3206 	}
3207 	else
3208 	    eap->cmdidx = CMD_bang;
3209 
3210 	for ( ; (int)eap->cmdidx < (int)CMD_SIZE;
3211 			       eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1))
3212 	    if (STRNCMP(cmdnames[(int)eap->cmdidx].cmd_name, (char *)eap->cmd,
3213 							    (size_t)len) == 0)
3214 	    {
3215 #ifdef FEAT_EVAL
3216 		if (full != NULL
3217 			   && cmdnames[(int)eap->cmdidx].cmd_name[len] == NUL)
3218 		    *full = TRUE;
3219 #endif
3220 		break;
3221 	    }
3222 
3223 	// Look for a user defined command as a last resort.  Let ":Print" be
3224 	// overruled by a user defined command.
3225 	if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print)
3226 		&& *eap->cmd >= 'A' && *eap->cmd <= 'Z')
3227 	{
3228 	    // User defined commands may contain digits.
3229 	    while (ASCII_ISALNUM(*p))
3230 		++p;
3231 	    p = find_ucmd(eap, p, full, NULL, NULL);
3232 	}
3233 	if (p == eap->cmd)
3234 	    eap->cmdidx = CMD_SIZE;
3235     }
3236 
3237     return p;
3238 }
3239 
3240 #if defined(FEAT_EVAL) || defined(PROTO)
3241 static struct cmdmod
3242 {
3243     char	*name;
3244     int		minlen;
3245     int		has_count;  /* :123verbose  :3tab */
3246 } cmdmods[] = {
3247     {"aboveleft", 3, FALSE},
3248     {"belowright", 3, FALSE},
3249     {"botright", 2, FALSE},
3250     {"browse", 3, FALSE},
3251     {"confirm", 4, FALSE},
3252     {"filter", 4, FALSE},
3253     {"hide", 3, FALSE},
3254     {"keepalt", 5, FALSE},
3255     {"keepjumps", 5, FALSE},
3256     {"keepmarks", 3, FALSE},
3257     {"keeppatterns", 5, FALSE},
3258     {"leftabove", 5, FALSE},
3259     {"lockmarks", 3, FALSE},
3260     {"noautocmd", 3, FALSE},
3261     {"noswapfile", 3, FALSE},
3262     {"rightbelow", 6, FALSE},
3263     {"sandbox", 3, FALSE},
3264     {"silent", 3, FALSE},
3265     {"tab", 3, TRUE},
3266     {"topleft", 2, FALSE},
3267     {"unsilent", 3, FALSE},
3268     {"verbose", 4, TRUE},
3269     {"vertical", 4, FALSE},
3270 };
3271 
3272 /*
3273  * Return length of a command modifier (including optional count).
3274  * Return zero when it's not a modifier.
3275  */
3276     int
3277 modifier_len(char_u *cmd)
3278 {
3279     int		i, j;
3280     char_u	*p = cmd;
3281 
3282     if (VIM_ISDIGIT(*cmd))
3283 	p = skipwhite(skipdigits(cmd));
3284     for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i)
3285     {
3286 	for (j = 0; p[j] != NUL; ++j)
3287 	    if (p[j] != cmdmods[i].name[j])
3288 		break;
3289 	if (!ASCII_ISALPHA(p[j]) && j >= cmdmods[i].minlen
3290 					&& (p == cmd || cmdmods[i].has_count))
3291 	    return j + (int)(p - cmd);
3292     }
3293     return 0;
3294 }
3295 
3296 /*
3297  * Return > 0 if an Ex command "name" exists.
3298  * Return 2 if there is an exact match.
3299  * Return 3 if there is an ambiguous match.
3300  */
3301     int
3302 cmd_exists(char_u *name)
3303 {
3304     exarg_T	ea;
3305     int		full = FALSE;
3306     int		i;
3307     int		j;
3308     char_u	*p;
3309 
3310     /* Check command modifiers. */
3311     for (i = 0; i < (int)(sizeof(cmdmods) / sizeof(struct cmdmod)); ++i)
3312     {
3313 	for (j = 0; name[j] != NUL; ++j)
3314 	    if (name[j] != cmdmods[i].name[j])
3315 		break;
3316 	if (name[j] == NUL && j >= cmdmods[i].minlen)
3317 	    return (cmdmods[i].name[j] == NUL ? 2 : 1);
3318     }
3319 
3320     /* Check built-in commands and user defined commands.
3321      * For ":2match" and ":3match" we need to skip the number. */
3322     ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
3323     ea.cmdidx = (cmdidx_T)0;
3324     p = find_command(&ea, &full);
3325     if (p == NULL)
3326 	return 3;
3327     if (vim_isdigit(*name) && ea.cmdidx != CMD_match)
3328 	return 0;
3329     if (*skipwhite(p) != NUL)
3330 	return 0;	/* trailing garbage */
3331     return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
3332 }
3333 #endif
3334 
3335 /*
3336  * This is all pretty much copied from do_one_cmd(), with all the extra stuff
3337  * we don't need/want deleted.	Maybe this could be done better if we didn't
3338  * repeat all this stuff.  The only problem is that they may not stay
3339  * perfectly compatible with each other, but then the command line syntax
3340  * probably won't change that much -- webb.
3341  */
3342     char_u *
3343 set_one_cmd_context(
3344     expand_T	*xp,
3345     char_u	*buff)	    /* buffer for command string */
3346 {
3347     char_u		*p;
3348     char_u		*cmd, *arg;
3349     int			len = 0;
3350     exarg_T		ea;
3351 #ifdef FEAT_CMDL_COMPL
3352     int			compl = EXPAND_NOTHING;
3353     int			delim;
3354 #endif
3355     int			forceit = FALSE;
3356     int			usefilter = FALSE;  /* filter instead of file name */
3357 
3358     ExpandInit(xp);
3359     xp->xp_pattern = buff;
3360     xp->xp_context = EXPAND_COMMANDS;	/* Default until we get past command */
3361     ea.argt = 0;
3362 
3363 /*
3364  * 1. skip comment lines and leading space, colons or bars
3365  */
3366     for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
3367 	;
3368     xp->xp_pattern = cmd;
3369 
3370     if (*cmd == NUL)
3371 	return NULL;
3372     if (*cmd == '"')	    /* ignore comment lines */
3373     {
3374 	xp->xp_context = EXPAND_NOTHING;
3375 	return NULL;
3376     }
3377 
3378 /*
3379  * 3. Skip over the range to find the command.
3380  */
3381     cmd = skip_range(cmd, &xp->xp_context);
3382     xp->xp_pattern = cmd;
3383     if (*cmd == NUL)
3384 	return NULL;
3385     if (*cmd == '"')
3386     {
3387 	xp->xp_context = EXPAND_NOTHING;
3388 	return NULL;
3389     }
3390 
3391     if (*cmd == '|' || *cmd == '\n')
3392 	return cmd + 1;			/* There's another command */
3393 
3394     /*
3395      * Isolate the command and search for it in the command table.
3396      * Exceptions:
3397      * - the 'k' command can directly be followed by any character, but
3398      *   do accept "keepmarks", "keepalt" and "keepjumps".
3399      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
3400      */
3401     if (*cmd == 'k' && cmd[1] != 'e')
3402     {
3403 	ea.cmdidx = CMD_k;
3404 	p = cmd + 1;
3405     }
3406     else
3407     {
3408 	p = cmd;
3409 	while (ASCII_ISALPHA(*p) || *p == '*')    /* Allow * wild card */
3410 	    ++p;
3411 	/* a user command may contain digits */
3412 	if (ASCII_ISUPPER(cmd[0]))
3413 	    while (ASCII_ISALNUM(*p) || *p == '*')
3414 		++p;
3415 	/* for python 3.x: ":py3*" commands completion */
3416 	if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3')
3417 	{
3418 	    ++p;
3419 	    while (ASCII_ISALPHA(*p) || *p == '*')
3420 		++p;
3421 	}
3422 	/* check for non-alpha command */
3423 	if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
3424 	    ++p;
3425 	len = (int)(p - cmd);
3426 
3427 	if (len == 0)
3428 	{
3429 	    xp->xp_context = EXPAND_UNSUCCESSFUL;
3430 	    return NULL;
3431 	}
3432 	for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE;
3433 				   ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1))
3434 	    if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd,
3435 							    (size_t)len) == 0)
3436 		break;
3437 
3438 	if (cmd[0] >= 'A' && cmd[0] <= 'Z')
3439 	    while (ASCII_ISALNUM(*p) || *p == '*')	// Allow * wild card
3440 		++p;
3441     }
3442 
3443     /*
3444      * If the cursor is touching the command, and it ends in an alpha-numeric
3445      * character, complete the command name.
3446      */
3447     if (*p == NUL && ASCII_ISALNUM(p[-1]))
3448 	return NULL;
3449 
3450     if (ea.cmdidx == CMD_SIZE)
3451     {
3452 	if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL)
3453 	{
3454 	    ea.cmdidx = CMD_substitute;
3455 	    p = cmd + 1;
3456 	}
3457 	else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
3458 	{
3459 	    ea.cmd = cmd;
3460 	    p = find_ucmd(&ea, p, NULL, xp,
3461 #if defined(FEAT_CMDL_COMPL)
3462 		    &compl
3463 #else
3464 		    NULL
3465 #endif
3466 		    );
3467 	    if (p == NULL)
3468 		ea.cmdidx = CMD_SIZE;	// ambiguous user command
3469 	}
3470     }
3471     if (ea.cmdidx == CMD_SIZE)
3472     {
3473 	/* Not still touching the command and it was an illegal one */
3474 	xp->xp_context = EXPAND_UNSUCCESSFUL;
3475 	return NULL;
3476     }
3477 
3478     xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */
3479 
3480     if (*p == '!')		    /* forced commands */
3481     {
3482 	forceit = TRUE;
3483 	++p;
3484     }
3485 
3486 /*
3487  * 6. parse arguments
3488  */
3489     if (!IS_USER_CMDIDX(ea.cmdidx))
3490 	ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt;
3491 
3492     arg = skipwhite(p);
3493 
3494     if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
3495     {
3496 	if (*arg == '>')			/* append */
3497 	{
3498 	    if (*++arg == '>')
3499 		++arg;
3500 	    arg = skipwhite(arg);
3501 	}
3502 	else if (*arg == '!' && ea.cmdidx == CMD_write)	/* :w !filter */
3503 	{
3504 	    ++arg;
3505 	    usefilter = TRUE;
3506 	}
3507     }
3508 
3509     if (ea.cmdidx == CMD_read)
3510     {
3511 	usefilter = forceit;			/* :r! filter if forced */
3512 	if (*arg == '!')			/* :r !filter */
3513 	{
3514 	    ++arg;
3515 	    usefilter = TRUE;
3516 	}
3517     }
3518 
3519     if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
3520     {
3521 	while (*arg == *cmd)	    /* allow any number of '>' or '<' */
3522 	    ++arg;
3523 	arg = skipwhite(arg);
3524     }
3525 
3526     /* Does command allow "+command"? */
3527     if ((ea.argt & EDITCMD) && !usefilter && *arg == '+')
3528     {
3529 	/* Check if we're in the +command */
3530 	p = arg + 1;
3531 	arg = skip_cmd_arg(arg, FALSE);
3532 
3533 	/* Still touching the command after '+'? */
3534 	if (*arg == NUL)
3535 	    return p;
3536 
3537 	/* Skip space(s) after +command to get to the real argument */
3538 	arg = skipwhite(arg);
3539     }
3540 
3541     /*
3542      * Check for '|' to separate commands and '"' to start comments.
3543      * Don't do this for ":read !cmd" and ":write !cmd".
3544      */
3545     if ((ea.argt & TRLBAR) && !usefilter)
3546     {
3547 	p = arg;
3548 	/* ":redir @" is not the start of a comment */
3549 	if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
3550 	    p += 2;
3551 	while (*p)
3552 	{
3553 	    if (*p == Ctrl_V)
3554 	    {
3555 		if (p[1] != NUL)
3556 		    ++p;
3557 	    }
3558 	    else if ( (*p == '"' && !(ea.argt & NOTRLCOM))
3559 		    || *p == '|' || *p == '\n')
3560 	    {
3561 		if (*(p - 1) != '\\')
3562 		{
3563 		    if (*p == '|' || *p == '\n')
3564 			return p + 1;
3565 		    return NULL;    /* It's a comment */
3566 		}
3567 	    }
3568 	    MB_PTR_ADV(p);
3569 	}
3570     }
3571 
3572 						/* no arguments allowed */
3573     if (!(ea.argt & EXTRA) && *arg != NUL &&
3574 				    vim_strchr((char_u *)"|\"", *arg) == NULL)
3575 	return NULL;
3576 
3577     /* Find start of last argument (argument just before cursor): */
3578     p = buff;
3579     xp->xp_pattern = p;
3580     len = (int)STRLEN(buff);
3581     while (*p && p < buff + len)
3582     {
3583 	if (*p == ' ' || *p == TAB)
3584 	{
3585 	    /* argument starts after a space */
3586 	    xp->xp_pattern = ++p;
3587 	}
3588 	else
3589 	{
3590 	    if (*p == '\\' && *(p + 1) != NUL)
3591 		++p; /* skip over escaped character */
3592 	    MB_PTR_ADV(p);
3593 	}
3594     }
3595 
3596     if (ea.argt & XFILE)
3597     {
3598 	int	c;
3599 	int	in_quote = FALSE;
3600 	char_u	*bow = NULL;	/* Beginning of word */
3601 
3602 	/*
3603 	 * Allow spaces within back-quotes to count as part of the argument
3604 	 * being expanded.
3605 	 */
3606 	xp->xp_pattern = skipwhite(arg);
3607 	p = xp->xp_pattern;
3608 	while (*p != NUL)
3609 	{
3610 	    if (has_mbyte)
3611 		c = mb_ptr2char(p);
3612 	    else
3613 		c = *p;
3614 	    if (c == '\\' && p[1] != NUL)
3615 		++p;
3616 	    else if (c == '`')
3617 	    {
3618 		if (!in_quote)
3619 		{
3620 		    xp->xp_pattern = p;
3621 		    bow = p + 1;
3622 		}
3623 		in_quote = !in_quote;
3624 	    }
3625 	    /* An argument can contain just about everything, except
3626 	     * characters that end the command and white space. */
3627 	    else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c)
3628 #ifdef SPACE_IN_FILENAME
3629 					 && (!(ea.argt & NOSPC) || usefilter)
3630 #endif
3631 		    ))
3632 	    {
3633 		len = 0;  /* avoid getting stuck when space is in 'isfname' */
3634 		while (*p != NUL)
3635 		{
3636 		    if (has_mbyte)
3637 			c = mb_ptr2char(p);
3638 		    else
3639 			c = *p;
3640 		    if (c == '`' || vim_isfilec_or_wc(c))
3641 			break;
3642 		    if (has_mbyte)
3643 			len = (*mb_ptr2len)(p);
3644 		    else
3645 			len = 1;
3646 		    MB_PTR_ADV(p);
3647 		}
3648 		if (in_quote)
3649 		    bow = p;
3650 		else
3651 		    xp->xp_pattern = p;
3652 		p -= len;
3653 	    }
3654 	    MB_PTR_ADV(p);
3655 	}
3656 
3657 	/*
3658 	 * If we are still inside the quotes, and we passed a space, just
3659 	 * expand from there.
3660 	 */
3661 	if (bow != NULL && in_quote)
3662 	    xp->xp_pattern = bow;
3663 	xp->xp_context = EXPAND_FILES;
3664 
3665 	/* For a shell command more chars need to be escaped. */
3666 	if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal)
3667 	{
3668 #ifndef BACKSLASH_IN_FILENAME
3669 	    xp->xp_shell = TRUE;
3670 #endif
3671 	    /* When still after the command name expand executables. */
3672 	    if (xp->xp_pattern == skipwhite(arg))
3673 		xp->xp_context = EXPAND_SHELLCMD;
3674 	}
3675 
3676 	/* Check for environment variable */
3677 	if (*xp->xp_pattern == '$'
3678 #if defined(MSWIN)
3679 		|| *xp->xp_pattern == '%'
3680 #endif
3681 		)
3682 	{
3683 	    for (p = xp->xp_pattern + 1; *p != NUL; ++p)
3684 		if (!vim_isIDc(*p))
3685 		    break;
3686 	    if (*p == NUL)
3687 	    {
3688 		xp->xp_context = EXPAND_ENV_VARS;
3689 		++xp->xp_pattern;
3690 #if defined(FEAT_CMDL_COMPL)
3691 		/* Avoid that the assignment uses EXPAND_FILES again. */
3692 		if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
3693 		    compl = EXPAND_ENV_VARS;
3694 #endif
3695 	    }
3696 	}
3697 #if defined(FEAT_CMDL_COMPL)
3698 	/* Check for user names */
3699 	if (*xp->xp_pattern == '~')
3700 	{
3701 	    for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p)
3702 		;
3703 	    /* Complete ~user only if it partially matches a user name.
3704 	     * A full match ~user<Tab> will be replaced by user's home
3705 	     * directory i.e. something like ~user<Tab> -> /home/user/ */
3706 	    if (*p == NUL && p > xp->xp_pattern + 1
3707 				       && match_user(xp->xp_pattern + 1) >= 1)
3708 	    {
3709 		xp->xp_context = EXPAND_USER;
3710 		++xp->xp_pattern;
3711 	    }
3712 	}
3713 #endif
3714     }
3715 
3716 /*
3717  * 6. Switch on command name.
3718  */
3719     switch (ea.cmdidx)
3720     {
3721 	case CMD_find:
3722 	case CMD_sfind:
3723 	case CMD_tabfind:
3724 	    if (xp->xp_context == EXPAND_FILES)
3725 		xp->xp_context = EXPAND_FILES_IN_PATH;
3726 	    break;
3727 	case CMD_cd:
3728 	case CMD_chdir:
3729 	case CMD_tcd:
3730 	case CMD_tchdir:
3731 	case CMD_lcd:
3732 	case CMD_lchdir:
3733 	    if (xp->xp_context == EXPAND_FILES)
3734 		xp->xp_context = EXPAND_DIRECTORIES;
3735 	    break;
3736 	case CMD_help:
3737 	    xp->xp_context = EXPAND_HELP;
3738 	    xp->xp_pattern = arg;
3739 	    break;
3740 
3741 	/* Command modifiers: return the argument.
3742 	 * Also for commands with an argument that is a command. */
3743 	case CMD_aboveleft:
3744 	case CMD_argdo:
3745 	case CMD_belowright:
3746 	case CMD_botright:
3747 	case CMD_browse:
3748 	case CMD_bufdo:
3749 	case CMD_cdo:
3750 	case CMD_cfdo:
3751 	case CMD_confirm:
3752 	case CMD_debug:
3753 	case CMD_folddoclosed:
3754 	case CMD_folddoopen:
3755 	case CMD_hide:
3756 	case CMD_keepalt:
3757 	case CMD_keepjumps:
3758 	case CMD_keepmarks:
3759 	case CMD_keeppatterns:
3760 	case CMD_ldo:
3761 	case CMD_leftabove:
3762 	case CMD_lfdo:
3763 	case CMD_lockmarks:
3764 	case CMD_noautocmd:
3765 	case CMD_noswapfile:
3766 	case CMD_rightbelow:
3767 	case CMD_sandbox:
3768 	case CMD_silent:
3769 	case CMD_tab:
3770 	case CMD_tabdo:
3771 	case CMD_topleft:
3772 	case CMD_verbose:
3773 	case CMD_vertical:
3774 	case CMD_windo:
3775 	    return arg;
3776 
3777 	case CMD_filter:
3778 	    if (*arg != NUL)
3779 		arg = skip_vimgrep_pat(arg, NULL, NULL);
3780 	    if (arg == NULL || *arg == NUL)
3781 	    {
3782 		xp->xp_context = EXPAND_NOTHING;
3783 		return NULL;
3784 	    }
3785 	    return skipwhite(arg);
3786 
3787 #ifdef FEAT_CMDL_COMPL
3788 # ifdef FEAT_SEARCH_EXTRA
3789 	case CMD_match:
3790 	    if (*arg == NUL || !ends_excmd(*arg))
3791 	    {
3792 		/* also complete "None" */
3793 		set_context_in_echohl_cmd(xp, arg);
3794 		arg = skipwhite(skiptowhite(arg));
3795 		if (*arg != NUL)
3796 		{
3797 		    xp->xp_context = EXPAND_NOTHING;
3798 		    arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
3799 		}
3800 	    }
3801 	    return find_nextcmd(arg);
3802 # endif
3803 
3804 /*
3805  * All completion for the +cmdline_compl feature goes here.
3806  */
3807 
3808 	case CMD_command:
3809 	    return set_context_in_user_cmd(xp, arg);
3810 
3811 	case CMD_delcommand:
3812 	    xp->xp_context = EXPAND_USER_COMMANDS;
3813 	    xp->xp_pattern = arg;
3814 	    break;
3815 
3816 	case CMD_global:
3817 	case CMD_vglobal:
3818 	    delim = *arg;	    /* get the delimiter */
3819 	    if (delim)
3820 		++arg;		    /* skip delimiter if there is one */
3821 
3822 	    while (arg[0] != NUL && arg[0] != delim)
3823 	    {
3824 		if (arg[0] == '\\' && arg[1] != NUL)
3825 		    ++arg;
3826 		++arg;
3827 	    }
3828 	    if (arg[0] != NUL)
3829 		return arg + 1;
3830 	    break;
3831 	case CMD_and:
3832 	case CMD_substitute:
3833 	    delim = *arg;
3834 	    if (delim)
3835 	    {
3836 		/* skip "from" part */
3837 		++arg;
3838 		arg = skip_regexp(arg, delim, p_magic, NULL);
3839 	    }
3840 	    /* skip "to" part */
3841 	    while (arg[0] != NUL && arg[0] != delim)
3842 	    {
3843 		if (arg[0] == '\\' && arg[1] != NUL)
3844 		    ++arg;
3845 		++arg;
3846 	    }
3847 	    if (arg[0] != NUL)	/* skip delimiter */
3848 		++arg;
3849 	    while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
3850 		++arg;
3851 	    if (arg[0] != NUL)
3852 		return arg;
3853 	    break;
3854 	case CMD_isearch:
3855 	case CMD_dsearch:
3856 	case CMD_ilist:
3857 	case CMD_dlist:
3858 	case CMD_ijump:
3859 	case CMD_psearch:
3860 	case CMD_djump:
3861 	case CMD_isplit:
3862 	case CMD_dsplit:
3863 	    arg = skipwhite(skipdigits(arg));	    /* skip count */
3864 	    if (*arg == '/')	/* Match regexp, not just whole words */
3865 	    {
3866 		for (++arg; *arg && *arg != '/'; arg++)
3867 		    if (*arg == '\\' && arg[1] != NUL)
3868 			arg++;
3869 		if (*arg)
3870 		{
3871 		    arg = skipwhite(arg + 1);
3872 
3873 		    /* Check for trailing illegal characters */
3874 		    if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
3875 			xp->xp_context = EXPAND_NOTHING;
3876 		    else
3877 			return arg;
3878 		}
3879 	    }
3880 	    break;
3881 
3882 	case CMD_autocmd:
3883 	    return set_context_in_autocmd(xp, arg, FALSE);
3884 	case CMD_doautocmd:
3885 	case CMD_doautoall:
3886 	    return set_context_in_autocmd(xp, arg, TRUE);
3887 	case CMD_set:
3888 	    set_context_in_set_cmd(xp, arg, 0);
3889 	    break;
3890 	case CMD_setglobal:
3891 	    set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
3892 	    break;
3893 	case CMD_setlocal:
3894 	    set_context_in_set_cmd(xp, arg, OPT_LOCAL);
3895 	    break;
3896 	case CMD_tag:
3897 	case CMD_stag:
3898 	case CMD_ptag:
3899 	case CMD_ltag:
3900 	case CMD_tselect:
3901 	case CMD_stselect:
3902 	case CMD_ptselect:
3903 	case CMD_tjump:
3904 	case CMD_stjump:
3905 	case CMD_ptjump:
3906 	    if (*p_wop != NUL)
3907 		xp->xp_context = EXPAND_TAGS_LISTFILES;
3908 	    else
3909 		xp->xp_context = EXPAND_TAGS;
3910 	    xp->xp_pattern = arg;
3911 	    break;
3912 	case CMD_augroup:
3913 	    xp->xp_context = EXPAND_AUGROUP;
3914 	    xp->xp_pattern = arg;
3915 	    break;
3916 #ifdef FEAT_SYN_HL
3917 	case CMD_syntax:
3918 	    set_context_in_syntax_cmd(xp, arg);
3919 	    break;
3920 #endif
3921 #ifdef FEAT_EVAL
3922 	case CMD_let:
3923 	case CMD_if:
3924 	case CMD_elseif:
3925 	case CMD_while:
3926 	case CMD_for:
3927 	case CMD_echo:
3928 	case CMD_echon:
3929 	case CMD_execute:
3930 	case CMD_echomsg:
3931 	case CMD_echoerr:
3932 	case CMD_call:
3933 	case CMD_return:
3934 	case CMD_cexpr:
3935 	case CMD_caddexpr:
3936 	case CMD_cgetexpr:
3937 	case CMD_lexpr:
3938 	case CMD_laddexpr:
3939 	case CMD_lgetexpr:
3940 	    set_context_for_expression(xp, arg, ea.cmdidx);
3941 	    break;
3942 
3943 	case CMD_unlet:
3944 	    while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
3945 		arg = xp->xp_pattern + 1;
3946 
3947 	    xp->xp_context = EXPAND_USER_VARS;
3948 	    xp->xp_pattern = arg;
3949 
3950 	    if (*xp->xp_pattern == '$')
3951 	    {
3952 		xp->xp_context = EXPAND_ENV_VARS;
3953 		++xp->xp_pattern;
3954 	    }
3955 
3956 	    break;
3957 
3958 	case CMD_function:
3959 	case CMD_delfunction:
3960 	    xp->xp_context = EXPAND_USER_FUNC;
3961 	    xp->xp_pattern = arg;
3962 	    break;
3963 
3964 	case CMD_echohl:
3965 	    set_context_in_echohl_cmd(xp, arg);
3966 	    break;
3967 #endif
3968 	case CMD_highlight:
3969 	    set_context_in_highlight_cmd(xp, arg);
3970 	    break;
3971 #ifdef FEAT_CSCOPE
3972 	case CMD_cscope:
3973 	case CMD_lcscope:
3974 	case CMD_scscope:
3975 	    set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
3976 	    break;
3977 #endif
3978 #ifdef FEAT_SIGNS
3979 	case CMD_sign:
3980 	    set_context_in_sign_cmd(xp, arg);
3981 	    break;
3982 #endif
3983 	case CMD_bdelete:
3984 	case CMD_bwipeout:
3985 	case CMD_bunload:
3986 	    while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
3987 		arg = xp->xp_pattern + 1;
3988 	    /* FALLTHROUGH */
3989 	case CMD_buffer:
3990 	case CMD_sbuffer:
3991 	case CMD_checktime:
3992 	    xp->xp_context = EXPAND_BUFFERS;
3993 	    xp->xp_pattern = arg;
3994 	    break;
3995 
3996 	case CMD_USER:
3997 	case CMD_USER_BUF:
3998 	    if (compl != EXPAND_NOTHING)
3999 	    {
4000 		// XFILE: file names are handled above
4001 		if (!(ea.argt & XFILE))
4002 		{
4003 #ifdef FEAT_MENU
4004 		    if (compl == EXPAND_MENUS)
4005 			return set_context_in_menu_cmd(xp, cmd, arg, forceit);
4006 #endif
4007 		    if (compl == EXPAND_COMMANDS)
4008 			return arg;
4009 		    if (compl == EXPAND_MAPPINGS)
4010 			return set_context_in_map_cmd(xp, (char_u *)"map",
4011 					 arg, forceit, FALSE, FALSE, CMD_map);
4012 		    // Find start of last argument.
4013 		    p = arg;
4014 		    while (*p)
4015 		    {
4016 			if (*p == ' ')
4017 			    // argument starts after a space
4018 			    arg = p + 1;
4019 			else if (*p == '\\' && *(p + 1) != NUL)
4020 			    ++p; // skip over escaped character
4021 			MB_PTR_ADV(p);
4022 		    }
4023 		    xp->xp_pattern = arg;
4024 		}
4025 		xp->xp_context = compl;
4026 	    }
4027 	    break;
4028 
4029 	case CMD_map:	    case CMD_noremap:
4030 	case CMD_nmap:	    case CMD_nnoremap:
4031 	case CMD_vmap:	    case CMD_vnoremap:
4032 	case CMD_omap:	    case CMD_onoremap:
4033 	case CMD_imap:	    case CMD_inoremap:
4034 	case CMD_cmap:	    case CMD_cnoremap:
4035 	case CMD_lmap:	    case CMD_lnoremap:
4036 	case CMD_smap:	    case CMD_snoremap:
4037 	case CMD_tmap:	    case CMD_tnoremap:
4038 	case CMD_xmap:	    case CMD_xnoremap:
4039 	    return set_context_in_map_cmd(xp, cmd, arg, forceit,
4040 						     FALSE, FALSE, ea.cmdidx);
4041 	case CMD_unmap:
4042 	case CMD_nunmap:
4043 	case CMD_vunmap:
4044 	case CMD_ounmap:
4045 	case CMD_iunmap:
4046 	case CMD_cunmap:
4047 	case CMD_lunmap:
4048 	case CMD_sunmap:
4049 	case CMD_tunmap:
4050 	case CMD_xunmap:
4051 	    return set_context_in_map_cmd(xp, cmd, arg, forceit,
4052 						      FALSE, TRUE, ea.cmdidx);
4053 	case CMD_mapclear:
4054 	case CMD_nmapclear:
4055 	case CMD_vmapclear:
4056 	case CMD_omapclear:
4057 	case CMD_imapclear:
4058 	case CMD_cmapclear:
4059 	case CMD_lmapclear:
4060 	case CMD_smapclear:
4061 	case CMD_tmapclear:
4062 	case CMD_xmapclear:
4063 	    xp->xp_context = EXPAND_MAPCLEAR;
4064 	    xp->xp_pattern = arg;
4065 	    break;
4066 
4067 	case CMD_abbreviate:	case CMD_noreabbrev:
4068 	case CMD_cabbrev:	case CMD_cnoreabbrev:
4069 	case CMD_iabbrev:	case CMD_inoreabbrev:
4070 	    return set_context_in_map_cmd(xp, cmd, arg, forceit,
4071 						      TRUE, FALSE, ea.cmdidx);
4072 	case CMD_unabbreviate:
4073 	case CMD_cunabbrev:
4074 	case CMD_iunabbrev:
4075 	    return set_context_in_map_cmd(xp, cmd, arg, forceit,
4076 						       TRUE, TRUE, ea.cmdidx);
4077 #ifdef FEAT_MENU
4078 	case CMD_menu:	    case CMD_noremenu:	    case CMD_unmenu:
4079 	case CMD_amenu:	    case CMD_anoremenu:	    case CMD_aunmenu:
4080 	case CMD_nmenu:	    case CMD_nnoremenu:	    case CMD_nunmenu:
4081 	case CMD_vmenu:	    case CMD_vnoremenu:	    case CMD_vunmenu:
4082 	case CMD_omenu:	    case CMD_onoremenu:	    case CMD_ounmenu:
4083 	case CMD_imenu:	    case CMD_inoremenu:	    case CMD_iunmenu:
4084 	case CMD_cmenu:	    case CMD_cnoremenu:	    case CMD_cunmenu:
4085 	case CMD_tlmenu:    case CMD_tlnoremenu:    case CMD_tlunmenu:
4086 	case CMD_tmenu:				    case CMD_tunmenu:
4087 	case CMD_popup:	    case CMD_tearoff:	    case CMD_emenu:
4088 	    return set_context_in_menu_cmd(xp, cmd, arg, forceit);
4089 #endif
4090 
4091 	case CMD_colorscheme:
4092 	    xp->xp_context = EXPAND_COLORS;
4093 	    xp->xp_pattern = arg;
4094 	    break;
4095 
4096 	case CMD_compiler:
4097 	    xp->xp_context = EXPAND_COMPILER;
4098 	    xp->xp_pattern = arg;
4099 	    break;
4100 
4101 	case CMD_ownsyntax:
4102 	    xp->xp_context = EXPAND_OWNSYNTAX;
4103 	    xp->xp_pattern = arg;
4104 	    break;
4105 
4106 	case CMD_setfiletype:
4107 	    xp->xp_context = EXPAND_FILETYPE;
4108 	    xp->xp_pattern = arg;
4109 	    break;
4110 
4111 	case CMD_packadd:
4112 	    xp->xp_context = EXPAND_PACKADD;
4113 	    xp->xp_pattern = arg;
4114 	    break;
4115 
4116 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4117 	case CMD_language:
4118 	    p = skiptowhite(arg);
4119 	    if (*p == NUL)
4120 	    {
4121 		xp->xp_context = EXPAND_LANGUAGE;
4122 		xp->xp_pattern = arg;
4123 	    }
4124 	    else
4125 	    {
4126 		if ( STRNCMP(arg, "messages", p - arg) == 0
4127 		  || STRNCMP(arg, "ctype", p - arg) == 0
4128 		  || STRNCMP(arg, "time", p - arg) == 0)
4129 		{
4130 		    xp->xp_context = EXPAND_LOCALES;
4131 		    xp->xp_pattern = skipwhite(p);
4132 		}
4133 		else
4134 		    xp->xp_context = EXPAND_NOTHING;
4135 	    }
4136 	    break;
4137 #endif
4138 #if defined(FEAT_PROFILE)
4139 	case CMD_profile:
4140 	    set_context_in_profile_cmd(xp, arg);
4141 	    break;
4142 #endif
4143 	case CMD_behave:
4144 	    xp->xp_context = EXPAND_BEHAVE;
4145 	    xp->xp_pattern = arg;
4146 	    break;
4147 
4148 	case CMD_messages:
4149 	    xp->xp_context = EXPAND_MESSAGES;
4150 	    xp->xp_pattern = arg;
4151 	    break;
4152 
4153 #if defined(FEAT_CMDHIST)
4154 	case CMD_history:
4155 	    xp->xp_context = EXPAND_HISTORY;
4156 	    xp->xp_pattern = arg;
4157 	    break;
4158 #endif
4159 #if defined(FEAT_PROFILE)
4160 	case CMD_syntime:
4161 	    xp->xp_context = EXPAND_SYNTIME;
4162 	    xp->xp_pattern = arg;
4163 	    break;
4164 #endif
4165 
4166 	case CMD_argdelete:
4167 	    while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
4168 		arg = xp->xp_pattern + 1;
4169 	    xp->xp_context = EXPAND_ARGLIST;
4170 	    xp->xp_pattern = arg;
4171 	    break;
4172 
4173 #endif /* FEAT_CMDL_COMPL */
4174 
4175 	default:
4176 	    break;
4177     }
4178     return NULL;
4179 }
4180 
4181 /*
4182  * Skip a range specifier of the form: addr [,addr] [;addr] ..
4183  *
4184  * Backslashed delimiters after / or ? will be skipped, and commands will
4185  * not be expanded between /'s and ?'s or after "'".
4186  *
4187  * Also skip white space and ":" characters.
4188  * Returns the "cmd" pointer advanced to beyond the range.
4189  */
4190     char_u *
4191 skip_range(
4192     char_u	*cmd,
4193     int		*ctx)	/* pointer to xp_context or NULL */
4194 {
4195     unsigned	delim;
4196 
4197     while (vim_strchr((char_u *)" \t0123456789.$%'/?-+,;\\", *cmd) != NULL)
4198     {
4199 	if (*cmd == '\\')
4200 	{
4201 	    if (cmd[1] == '?' || cmd[1] == '/' || cmd[1] == '&')
4202 		++cmd;
4203 	    else
4204 		break;
4205 	}
4206 	else if (*cmd == '\'')
4207 	{
4208 	    if (*++cmd == NUL && ctx != NULL)
4209 		*ctx = EXPAND_NOTHING;
4210 	}
4211 	else if (*cmd == '/' || *cmd == '?')
4212 	{
4213 	    delim = *cmd++;
4214 	    while (*cmd != NUL && *cmd != delim)
4215 		if (*cmd++ == '\\' && *cmd != NUL)
4216 		    ++cmd;
4217 	    if (*cmd == NUL && ctx != NULL)
4218 		*ctx = EXPAND_NOTHING;
4219 	}
4220 	if (*cmd != NUL)
4221 	    ++cmd;
4222     }
4223 
4224     /* Skip ":" and white space. */
4225     while (*cmd == ':')
4226 	cmd = skipwhite(cmd + 1);
4227 
4228     return cmd;
4229 }
4230 
4231 /*
4232  * Get a single EX address.
4233  *
4234  * Set ptr to the next character after the part that was interpreted.
4235  * Set ptr to NULL when an error is encountered.
4236  * This may set the last used search pattern.
4237  *
4238  * Return MAXLNUM when no Ex address was found.
4239  */
4240     static linenr_T
4241 get_address(
4242     exarg_T	*eap UNUSED,
4243     char_u	**ptr,
4244     cmd_addr_T	addr_type_arg,
4245     int		skip,		// only skip the address, don't use it
4246     int		silent,		// no errors or side effects
4247     int		to_other_file,  // flag: may jump to other file
4248     int		address_count UNUSED) // 1 for first address, >1 after comma
4249 {
4250     cmd_addr_T	addr_type = addr_type_arg;
4251     int		c;
4252     int		i;
4253     long	n;
4254     char_u	*cmd;
4255     pos_T	pos;
4256     pos_T	*fp;
4257     linenr_T	lnum;
4258     buf_T	*buf;
4259 
4260     cmd = skipwhite(*ptr);
4261     lnum = MAXLNUM;
4262     do
4263     {
4264 	switch (*cmd)
4265 	{
4266 	    case '.':			    /* '.' - Cursor position */
4267 		++cmd;
4268 		switch (addr_type)
4269 		{
4270 		    case ADDR_LINES:
4271 		    case ADDR_OTHER:
4272 			lnum = curwin->w_cursor.lnum;
4273 			break;
4274 		    case ADDR_WINDOWS:
4275 			lnum = CURRENT_WIN_NR;
4276 			break;
4277 		    case ADDR_ARGUMENTS:
4278 			lnum = curwin->w_arg_idx + 1;
4279 			break;
4280 		    case ADDR_LOADED_BUFFERS:
4281 		    case ADDR_BUFFERS:
4282 			lnum = curbuf->b_fnum;
4283 			break;
4284 		    case ADDR_TABS:
4285 			lnum = CURRENT_TAB_NR;
4286 			break;
4287 		    case ADDR_TABS_RELATIVE:
4288 		    case ADDR_NONE:
4289 		    case ADDR_UNSIGNED:
4290 			emsg(_(e_invrange));
4291 			cmd = NULL;
4292 			goto error;
4293 			break;
4294 		    case ADDR_QUICKFIX:
4295 #ifdef FEAT_QUICKFIX
4296 			lnum = qf_get_cur_idx(eap);
4297 #endif
4298 			break;
4299 		    case ADDR_QUICKFIX_VALID:
4300 #ifdef FEAT_QUICKFIX
4301 			lnum = qf_get_cur_valid_idx(eap);
4302 #endif
4303 			break;
4304 		}
4305 		break;
4306 
4307 	    case '$':			    /* '$' - last line */
4308 		++cmd;
4309 		switch (addr_type)
4310 		{
4311 		    case ADDR_LINES:
4312 		    case ADDR_OTHER:
4313 			lnum = curbuf->b_ml.ml_line_count;
4314 			break;
4315 		    case ADDR_WINDOWS:
4316 			lnum = LAST_WIN_NR;
4317 			break;
4318 		    case ADDR_ARGUMENTS:
4319 			lnum = ARGCOUNT;
4320 			break;
4321 		    case ADDR_LOADED_BUFFERS:
4322 			buf = lastbuf;
4323 			while (buf->b_ml.ml_mfp == NULL)
4324 			{
4325 			    if (buf->b_prev == NULL)
4326 				break;
4327 			    buf = buf->b_prev;
4328 			}
4329 			lnum = buf->b_fnum;
4330 			break;
4331 		    case ADDR_BUFFERS:
4332 			lnum = lastbuf->b_fnum;
4333 			break;
4334 		    case ADDR_TABS:
4335 			lnum = LAST_TAB_NR;
4336 			break;
4337 		    case ADDR_TABS_RELATIVE:
4338 		    case ADDR_NONE:
4339 		    case ADDR_UNSIGNED:
4340 			emsg(_(e_invrange));
4341 			cmd = NULL;
4342 			goto error;
4343 			break;
4344 		    case ADDR_QUICKFIX:
4345 #ifdef FEAT_QUICKFIX
4346 			lnum = qf_get_size(eap);
4347 			if (lnum == 0)
4348 			    lnum = 1;
4349 #endif
4350 			break;
4351 		    case ADDR_QUICKFIX_VALID:
4352 #ifdef FEAT_QUICKFIX
4353 			lnum = qf_get_valid_size(eap);
4354 			if (lnum == 0)
4355 			    lnum = 1;
4356 #endif
4357 			break;
4358 		}
4359 		break;
4360 
4361 	    case '\'':			    /* ''' - mark */
4362 		if (*++cmd == NUL)
4363 		{
4364 		    cmd = NULL;
4365 		    goto error;
4366 		}
4367 		if (addr_type != ADDR_LINES)
4368 		{
4369 		    emsg(_(e_invaddr));
4370 		    cmd = NULL;
4371 		    goto error;
4372 		}
4373 		if (skip)
4374 		    ++cmd;
4375 		else
4376 		{
4377 		    /* Only accept a mark in another file when it is
4378 		     * used by itself: ":'M". */
4379 		    fp = getmark(*cmd, to_other_file && cmd[1] == NUL);
4380 		    ++cmd;
4381 		    if (fp == (pos_T *)-1)
4382 			/* Jumped to another file. */
4383 			lnum = curwin->w_cursor.lnum;
4384 		    else
4385 		    {
4386 			if (check_mark(fp) == FAIL)
4387 			{
4388 			    cmd = NULL;
4389 			    goto error;
4390 			}
4391 			lnum = fp->lnum;
4392 		    }
4393 		}
4394 		break;
4395 
4396 	    case '/':
4397 	    case '?':			/* '/' or '?' - search */
4398 		c = *cmd++;
4399 		if (addr_type != ADDR_LINES)
4400 		{
4401 		    emsg(_(e_invaddr));
4402 		    cmd = NULL;
4403 		    goto error;
4404 		}
4405 		if (skip)	/* skip "/pat/" */
4406 		{
4407 		    cmd = skip_regexp(cmd, c, (int)p_magic, NULL);
4408 		    if (*cmd == c)
4409 			++cmd;
4410 		}
4411 		else
4412 		{
4413 		    int flags;
4414 
4415 		    pos = curwin->w_cursor; // save curwin->w_cursor
4416 
4417 		    // When '/' or '?' follows another address, start from
4418 		    // there.
4419 		    if (lnum != MAXLNUM)
4420 			curwin->w_cursor.lnum = lnum;
4421 
4422 		    // Start a forward search at the end of the line (unless
4423 		    // before the first line).
4424 		    // Start a backward search at the start of the line.
4425 		    // This makes sure we never match in the current
4426 		    // line, and can match anywhere in the
4427 		    // next/previous line.
4428 		    if (c == '/' && curwin->w_cursor.lnum > 0)
4429 			curwin->w_cursor.col = MAXCOL;
4430 		    else
4431 			curwin->w_cursor.col = 0;
4432 		    searchcmdlen = 0;
4433 		    flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG;
4434 		    if (!do_search(NULL, c, cmd, 1L, flags, NULL, NULL))
4435 		    {
4436 			curwin->w_cursor = pos;
4437 			cmd = NULL;
4438 			goto error;
4439 		    }
4440 		    lnum = curwin->w_cursor.lnum;
4441 		    curwin->w_cursor = pos;
4442 		    /* adjust command string pointer */
4443 		    cmd += searchcmdlen;
4444 		}
4445 		break;
4446 
4447 	    case '\\':		    /* "\?", "\/" or "\&", repeat search */
4448 		++cmd;
4449 		if (addr_type != ADDR_LINES)
4450 		{
4451 		    emsg(_(e_invaddr));
4452 		    cmd = NULL;
4453 		    goto error;
4454 		}
4455 		if (*cmd == '&')
4456 		    i = RE_SUBST;
4457 		else if (*cmd == '?' || *cmd == '/')
4458 		    i = RE_SEARCH;
4459 		else
4460 		{
4461 		    emsg(_(e_backslash));
4462 		    cmd = NULL;
4463 		    goto error;
4464 		}
4465 
4466 		if (!skip)
4467 		{
4468 		    /*
4469 		     * When search follows another address, start from
4470 		     * there.
4471 		     */
4472 		    if (lnum != MAXLNUM)
4473 			pos.lnum = lnum;
4474 		    else
4475 			pos.lnum = curwin->w_cursor.lnum;
4476 
4477 		    /*
4478 		     * Start the search just like for the above
4479 		     * do_search().
4480 		     */
4481 		    if (*cmd != '?')
4482 			pos.col = MAXCOL;
4483 		    else
4484 			pos.col = 0;
4485 		    pos.coladd = 0;
4486 		    if (searchit(curwin, curbuf, &pos, NULL,
4487 				*cmd == '?' ? BACKWARD : FORWARD,
4488 				(char_u *)"", 1L, SEARCH_MSG,
4489 					i, (linenr_T)0, NULL, NULL) != FAIL)
4490 			lnum = pos.lnum;
4491 		    else
4492 		    {
4493 			cmd = NULL;
4494 			goto error;
4495 		    }
4496 		}
4497 		++cmd;
4498 		break;
4499 
4500 	    default:
4501 		if (VIM_ISDIGIT(*cmd))	/* absolute line number */
4502 		    lnum = getdigits(&cmd);
4503 	}
4504 
4505 	for (;;)
4506 	{
4507 	    cmd = skipwhite(cmd);
4508 	    if (*cmd != '-' && *cmd != '+' && !VIM_ISDIGIT(*cmd))
4509 		break;
4510 
4511 	    if (lnum == MAXLNUM)
4512 	    {
4513 		switch (addr_type)
4514 		{
4515 		    case ADDR_LINES:
4516 		    case ADDR_OTHER:
4517 			// "+1" is same as ".+1"
4518 			lnum = curwin->w_cursor.lnum;
4519 			break;
4520 		    case ADDR_WINDOWS:
4521 			lnum = CURRENT_WIN_NR;
4522 			break;
4523 		    case ADDR_ARGUMENTS:
4524 			lnum = curwin->w_arg_idx + 1;
4525 			break;
4526 		    case ADDR_LOADED_BUFFERS:
4527 		    case ADDR_BUFFERS:
4528 			lnum = curbuf->b_fnum;
4529 			break;
4530 		    case ADDR_TABS:
4531 			lnum = CURRENT_TAB_NR;
4532 			break;
4533 		    case ADDR_TABS_RELATIVE:
4534 			lnum = 1;
4535 			break;
4536 		    case ADDR_QUICKFIX:
4537 #ifdef FEAT_QUICKFIX
4538 			lnum = qf_get_cur_idx(eap);
4539 #endif
4540 			break;
4541 		    case ADDR_QUICKFIX_VALID:
4542 #ifdef FEAT_QUICKFIX
4543 			lnum = qf_get_cur_valid_idx(eap);
4544 #endif
4545 			break;
4546 		    case ADDR_NONE:
4547 		    case ADDR_UNSIGNED:
4548 			lnum = 0;
4549 			break;
4550 		}
4551 	    }
4552 
4553 	    if (VIM_ISDIGIT(*cmd))
4554 		i = '+';		/* "number" is same as "+number" */
4555 	    else
4556 		i = *cmd++;
4557 	    if (!VIM_ISDIGIT(*cmd))	/* '+' is '+1', but '+0' is not '+1' */
4558 		n = 1;
4559 	    else
4560 		n = getdigits(&cmd);
4561 
4562 	    if (addr_type == ADDR_TABS_RELATIVE)
4563 	    {
4564 		emsg(_(e_invrange));
4565 		cmd = NULL;
4566 		goto error;
4567 	    }
4568 	    else if (addr_type == ADDR_LOADED_BUFFERS
4569 		    || addr_type == ADDR_BUFFERS)
4570 		lnum = compute_buffer_local_count(
4571 				    addr_type, lnum, (i == '-') ? -1 * n : n);
4572 	    else
4573 	    {
4574 #ifdef FEAT_FOLDING
4575 		/* Relative line addressing, need to adjust for folded lines
4576 		 * now, but only do it after the first address. */
4577 		if (addr_type == ADDR_LINES && (i == '-' || i == '+')
4578 			&& address_count >= 2)
4579 		    (void)hasFolding(lnum, NULL, &lnum);
4580 #endif
4581 		if (i == '-')
4582 		    lnum -= n;
4583 		else
4584 		    lnum += n;
4585 	    }
4586 	}
4587     } while (*cmd == '/' || *cmd == '?');
4588 
4589 error:
4590     *ptr = cmd;
4591     return lnum;
4592 }
4593 
4594 /*
4595  * Get flags from an Ex command argument.
4596  */
4597     static void
4598 get_flags(exarg_T *eap)
4599 {
4600     while (vim_strchr((char_u *)"lp#", *eap->arg) != NULL)
4601     {
4602 	if (*eap->arg == 'l')
4603 	    eap->flags |= EXFLAG_LIST;
4604 	else if (*eap->arg == 'p')
4605 	    eap->flags |= EXFLAG_PRINT;
4606 	else
4607 	    eap->flags |= EXFLAG_NR;
4608 	eap->arg = skipwhite(eap->arg + 1);
4609     }
4610 }
4611 
4612 /*
4613  * Function called for command which is Not Implemented.  NI!
4614  */
4615     void
4616 ex_ni(exarg_T *eap)
4617 {
4618     if (!eap->skip)
4619 	eap->errmsg = N_("E319: Sorry, the command is not available in this version");
4620 }
4621 
4622 #ifdef HAVE_EX_SCRIPT_NI
4623 /*
4624  * Function called for script command which is Not Implemented.  NI!
4625  * Skips over ":perl <<EOF" constructs.
4626  */
4627     static void
4628 ex_script_ni(exarg_T *eap)
4629 {
4630     if (!eap->skip)
4631 	ex_ni(eap);
4632     else
4633 	vim_free(script_get(eap, eap->arg));
4634 }
4635 #endif
4636 
4637 /*
4638  * Check range in Ex command for validity.
4639  * Return NULL when valid, error message when invalid.
4640  */
4641     static char *
4642 invalid_range(exarg_T *eap)
4643 {
4644     buf_T	*buf;
4645 
4646     if (       eap->line1 < 0
4647 	    || eap->line2 < 0
4648 	    || eap->line1 > eap->line2)
4649 	return _(e_invrange);
4650 
4651     if (eap->argt & RANGE)
4652     {
4653 	switch (eap->addr_type)
4654 	{
4655 	    case ADDR_LINES:
4656 		if (eap->line2 > curbuf->b_ml.ml_line_count
4657 #ifdef FEAT_DIFF
4658 			    + (eap->cmdidx == CMD_diffget)
4659 #endif
4660 		   )
4661 		    return _(e_invrange);
4662 		break;
4663 	    case ADDR_ARGUMENTS:
4664 		/* add 1 if ARGCOUNT is 0 */
4665 		if (eap->line2 > ARGCOUNT + (!ARGCOUNT))
4666 		    return _(e_invrange);
4667 		break;
4668 	    case ADDR_BUFFERS:
4669 		if (eap->line1 < firstbuf->b_fnum
4670 			|| eap->line2 > lastbuf->b_fnum)
4671 		    return _(e_invrange);
4672 		break;
4673 	    case ADDR_LOADED_BUFFERS:
4674 		buf = firstbuf;
4675 		while (buf->b_ml.ml_mfp == NULL)
4676 		{
4677 		    if (buf->b_next == NULL)
4678 			return _(e_invrange);
4679 		    buf = buf->b_next;
4680 		}
4681 		if (eap->line1 < buf->b_fnum)
4682 		    return _(e_invrange);
4683 		buf = lastbuf;
4684 		while (buf->b_ml.ml_mfp == NULL)
4685 		{
4686 		    if (buf->b_prev == NULL)
4687 			return _(e_invrange);
4688 		    buf = buf->b_prev;
4689 		}
4690 		if (eap->line2 > buf->b_fnum)
4691 		    return _(e_invrange);
4692 		break;
4693 	    case ADDR_WINDOWS:
4694 		if (eap->line2 > LAST_WIN_NR)
4695 		    return _(e_invrange);
4696 		break;
4697 	    case ADDR_TABS:
4698 		if (eap->line2 > LAST_TAB_NR)
4699 		    return _(e_invrange);
4700 		break;
4701 	    case ADDR_TABS_RELATIVE:
4702 	    case ADDR_OTHER:
4703 		// Any range is OK.
4704 		break;
4705 	    case ADDR_QUICKFIX:
4706 #ifdef FEAT_QUICKFIX
4707 		// No error for value that is too big, will use the last entry.
4708 		if (eap->line2 <= 0)
4709 		    return _(e_invrange);
4710 #endif
4711 		break;
4712 	    case ADDR_QUICKFIX_VALID:
4713 #ifdef FEAT_QUICKFIX
4714 		if ((eap->line2 != 1 && eap->line2 > qf_get_valid_size(eap))
4715 			|| eap->line2 < 0)
4716 		    return _(e_invrange);
4717 #endif
4718 		break;
4719 	    case ADDR_UNSIGNED:
4720 		if (eap->line2 < 0)
4721 		    return _(e_invrange);
4722 		break;
4723 	    case ADDR_NONE:
4724 		// Will give an error elsewhere.
4725 		break;
4726 	}
4727     }
4728     return NULL;
4729 }
4730 
4731 /*
4732  * Correct the range for zero line number, if required.
4733  */
4734     static void
4735 correct_range(exarg_T *eap)
4736 {
4737     if (!(eap->argt & ZEROR))	    /* zero in range not allowed */
4738     {
4739 	if (eap->line1 == 0)
4740 	    eap->line1 = 1;
4741 	if (eap->line2 == 0)
4742 	    eap->line2 = 1;
4743     }
4744 }
4745 
4746 #ifdef FEAT_QUICKFIX
4747 /*
4748  * For a ":vimgrep" or ":vimgrepadd" command return a pointer past the
4749  * pattern.  Otherwise return eap->arg.
4750  */
4751     static char_u *
4752 skip_grep_pat(exarg_T *eap)
4753 {
4754     char_u	*p = eap->arg;
4755 
4756     if (*p != NUL && (eap->cmdidx == CMD_vimgrep || eap->cmdidx == CMD_lvimgrep
4757 		|| eap->cmdidx == CMD_vimgrepadd
4758 		|| eap->cmdidx == CMD_lvimgrepadd
4759 		|| grep_internal(eap->cmdidx)))
4760     {
4761 	p = skip_vimgrep_pat(p, NULL, NULL);
4762 	if (p == NULL)
4763 	    p = eap->arg;
4764     }
4765     return p;
4766 }
4767 
4768 /*
4769  * For the ":make" and ":grep" commands insert the 'makeprg'/'grepprg' option
4770  * in the command line, so that things like % get expanded.
4771  */
4772     static char_u *
4773 replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep)
4774 {
4775     char_u	*new_cmdline;
4776     char_u	*program;
4777     char_u	*pos;
4778     char_u	*ptr;
4779     int		len;
4780     int		i;
4781 
4782     /*
4783      * Don't do it when ":vimgrep" is used for ":grep".
4784      */
4785     if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake
4786 		     || eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep
4787 		     || eap->cmdidx == CMD_grepadd
4788 		     || eap->cmdidx == CMD_lgrepadd)
4789 	    && !grep_internal(eap->cmdidx))
4790     {
4791 	if (eap->cmdidx == CMD_grep || eap->cmdidx == CMD_lgrep
4792 	    || eap->cmdidx == CMD_grepadd || eap->cmdidx == CMD_lgrepadd)
4793 	{
4794 	    if (*curbuf->b_p_gp == NUL)
4795 		program = p_gp;
4796 	    else
4797 		program = curbuf->b_p_gp;
4798 	}
4799 	else
4800 	{
4801 	    if (*curbuf->b_p_mp == NUL)
4802 		program = p_mp;
4803 	    else
4804 		program = curbuf->b_p_mp;
4805 	}
4806 
4807 	p = skipwhite(p);
4808 
4809 	if ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
4810 	{
4811 	    /* replace $* by given arguments */
4812 	    i = 1;
4813 	    while ((pos = (char_u *)strstr((char *)pos + 2, "$*")) != NULL)
4814 		++i;
4815 	    len = (int)STRLEN(p);
4816 	    new_cmdline = alloc((int)(STRLEN(program) + i * (len - 2) + 1));
4817 	    if (new_cmdline == NULL)
4818 		return NULL;			/* out of memory */
4819 	    ptr = new_cmdline;
4820 	    while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL)
4821 	    {
4822 		i = (int)(pos - program);
4823 		STRNCPY(ptr, program, i);
4824 		STRCPY(ptr += i, p);
4825 		ptr += len;
4826 		program = pos + 2;
4827 	    }
4828 	    STRCPY(ptr, program);
4829 	}
4830 	else
4831 	{
4832 	    new_cmdline = alloc((int)(STRLEN(program) + STRLEN(p) + 2));
4833 	    if (new_cmdline == NULL)
4834 		return NULL;			/* out of memory */
4835 	    STRCPY(new_cmdline, program);
4836 	    STRCAT(new_cmdline, " ");
4837 	    STRCAT(new_cmdline, p);
4838 	}
4839 	msg_make(p);
4840 
4841 	/* 'eap->cmd' is not set here, because it is not used at CMD_make */
4842 	vim_free(*cmdlinep);
4843 	*cmdlinep = new_cmdline;
4844 	p = new_cmdline;
4845     }
4846     return p;
4847 }
4848 #endif
4849 
4850 /*
4851  * Expand file name in Ex command argument.
4852  * Return FAIL for failure, OK otherwise.
4853  */
4854     int
4855 expand_filename(
4856     exarg_T	*eap,
4857     char_u	**cmdlinep,
4858     char	**errormsgp)
4859 {
4860     int		has_wildcards;	/* need to expand wildcards */
4861     char_u	*repl;
4862     int		srclen;
4863     char_u	*p;
4864     int		n;
4865     int		escaped;
4866 
4867 #ifdef FEAT_QUICKFIX
4868     /* Skip a regexp pattern for ":vimgrep[add] pat file..." */
4869     p = skip_grep_pat(eap);
4870 #else
4871     p = eap->arg;
4872 #endif
4873 
4874     /*
4875      * Decide to expand wildcards *before* replacing '%', '#', etc.  If
4876      * the file name contains a wildcard it should not cause expanding.
4877      * (it will be expanded anyway if there is a wildcard before replacing).
4878      */
4879     has_wildcards = mch_has_wildcard(p);
4880     while (*p != NUL)
4881     {
4882 #ifdef FEAT_EVAL
4883 	/* Skip over `=expr`, wildcards in it are not expanded. */
4884 	if (p[0] == '`' && p[1] == '=')
4885 	{
4886 	    p += 2;
4887 	    (void)skip_expr(&p);
4888 	    if (*p == '`')
4889 		++p;
4890 	    continue;
4891 	}
4892 #endif
4893 	/*
4894 	 * Quick check if this cannot be the start of a special string.
4895 	 * Also removes backslash before '%', '#' and '<'.
4896 	 */
4897 	if (vim_strchr((char_u *)"%#<", *p) == NULL)
4898 	{
4899 	    ++p;
4900 	    continue;
4901 	}
4902 
4903 	/*
4904 	 * Try to find a match at this position.
4905 	 */
4906 	repl = eval_vars(p, eap->arg, &srclen, &(eap->do_ecmd_lnum),
4907 							 errormsgp, &escaped);
4908 	if (*errormsgp != NULL)		/* error detected */
4909 	    return FAIL;
4910 	if (repl == NULL)		/* no match found */
4911 	{
4912 	    p += srclen;
4913 	    continue;
4914 	}
4915 
4916 	/* Wildcards won't be expanded below, the replacement is taken
4917 	 * literally.  But do expand "~/file", "~user/file" and "$HOME/file". */
4918 	if (vim_strchr(repl, '$') != NULL || vim_strchr(repl, '~') != NULL)
4919 	{
4920 	    char_u *l = repl;
4921 
4922 	    repl = expand_env_save(repl);
4923 	    vim_free(l);
4924 	}
4925 
4926 	/* Need to escape white space et al. with a backslash.
4927 	 * Don't do this for:
4928 	 * - replacement that already has been escaped: "##"
4929 	 * - shell commands (may have to use quotes instead).
4930 	 * - non-unix systems when there is a single argument (spaces don't
4931 	 *   separate arguments then).
4932 	 */
4933 	if (!eap->usefilter
4934 		&& !escaped
4935 		&& eap->cmdidx != CMD_bang
4936 		&& eap->cmdidx != CMD_grep
4937 		&& eap->cmdidx != CMD_grepadd
4938 		&& eap->cmdidx != CMD_hardcopy
4939 		&& eap->cmdidx != CMD_lgrep
4940 		&& eap->cmdidx != CMD_lgrepadd
4941 		&& eap->cmdidx != CMD_lmake
4942 		&& eap->cmdidx != CMD_make
4943 		&& eap->cmdidx != CMD_terminal
4944 #ifndef UNIX
4945 		&& !(eap->argt & NOSPC)
4946 #endif
4947 		)
4948 	{
4949 	    char_u	*l;
4950 #ifdef BACKSLASH_IN_FILENAME
4951 	    /* Don't escape a backslash here, because rem_backslash() doesn't
4952 	     * remove it later. */
4953 	    static char_u *nobslash = (char_u *)" \t\"|";
4954 # define ESCAPE_CHARS nobslash
4955 #else
4956 # define ESCAPE_CHARS escape_chars
4957 #endif
4958 
4959 	    for (l = repl; *l; ++l)
4960 		if (vim_strchr(ESCAPE_CHARS, *l) != NULL)
4961 		{
4962 		    l = vim_strsave_escaped(repl, ESCAPE_CHARS);
4963 		    if (l != NULL)
4964 		    {
4965 			vim_free(repl);
4966 			repl = l;
4967 		    }
4968 		    break;
4969 		}
4970 	}
4971 
4972 	/* For a shell command a '!' must be escaped. */
4973 	if ((eap->usefilter || eap->cmdidx == CMD_bang
4974 						|| eap->cmdidx == CMD_terminal)
4975 			    && vim_strpbrk(repl, (char_u *)"!") != NULL)
4976 	{
4977 	    char_u	*l;
4978 
4979 	    l = vim_strsave_escaped(repl, (char_u *)"!");
4980 	    if (l != NULL)
4981 	    {
4982 		vim_free(repl);
4983 		repl = l;
4984 	    }
4985 	}
4986 
4987 	p = repl_cmdline(eap, p, srclen, repl, cmdlinep);
4988 	vim_free(repl);
4989 	if (p == NULL)
4990 	    return FAIL;
4991     }
4992 
4993     /*
4994      * One file argument: Expand wildcards.
4995      * Don't do this with ":r !command" or ":w !command".
4996      */
4997     if ((eap->argt & NOSPC) && !eap->usefilter)
4998     {
4999 	/*
5000 	 * May do this twice:
5001 	 * 1. Replace environment variables.
5002 	 * 2. Replace any other wildcards, remove backslashes.
5003 	 */
5004 	for (n = 1; n <= 2; ++n)
5005 	{
5006 	    if (n == 2)
5007 	    {
5008 		/*
5009 		 * Halve the number of backslashes (this is Vi compatible).
5010 		 * For Unix and OS/2, when wildcards are expanded, this is
5011 		 * done by ExpandOne() below.
5012 		 */
5013 #if defined(UNIX)
5014 		if (!has_wildcards)
5015 #endif
5016 		    backslash_halve(eap->arg);
5017 	    }
5018 
5019 	    if (has_wildcards)
5020 	    {
5021 		if (n == 1)
5022 		{
5023 		    /*
5024 		     * First loop: May expand environment variables.  This
5025 		     * can be done much faster with expand_env() than with
5026 		     * something else (e.g., calling a shell).
5027 		     * After expanding environment variables, check again
5028 		     * if there are still wildcards present.
5029 		     */
5030 		    if (vim_strchr(eap->arg, '$') != NULL
5031 			    || vim_strchr(eap->arg, '~') != NULL)
5032 		    {
5033 			expand_env_esc(eap->arg, NameBuff, MAXPATHL,
5034 							    TRUE, TRUE, NULL);
5035 			has_wildcards = mch_has_wildcard(NameBuff);
5036 			p = NameBuff;
5037 		    }
5038 		    else
5039 			p = NULL;
5040 		}
5041 		else /* n == 2 */
5042 		{
5043 		    expand_T	xpc;
5044 		    int		options = WILD_LIST_NOTFOUND|WILD_ADD_SLASH;
5045 
5046 		    ExpandInit(&xpc);
5047 		    xpc.xp_context = EXPAND_FILES;
5048 		    if (p_wic)
5049 			options += WILD_ICASE;
5050 		    p = ExpandOne(&xpc, eap->arg, NULL,
5051 						   options, WILD_EXPAND_FREE);
5052 		    if (p == NULL)
5053 			return FAIL;
5054 		}
5055 		if (p != NULL)
5056 		{
5057 		    (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg),
5058 								 p, cmdlinep);
5059 		    if (n == 2)	/* p came from ExpandOne() */
5060 			vim_free(p);
5061 		}
5062 	    }
5063 	}
5064     }
5065     return OK;
5066 }
5067 
5068 /*
5069  * Replace part of the command line, keeping eap->cmd, eap->arg and
5070  * eap->nextcmd correct.
5071  * "src" points to the part that is to be replaced, of length "srclen".
5072  * "repl" is the replacement string.
5073  * Returns a pointer to the character after the replaced string.
5074  * Returns NULL for failure.
5075  */
5076     static char_u *
5077 repl_cmdline(
5078     exarg_T	*eap,
5079     char_u	*src,
5080     int		srclen,
5081     char_u	*repl,
5082     char_u	**cmdlinep)
5083 {
5084     int		len;
5085     int		i;
5086     char_u	*new_cmdline;
5087 
5088     /*
5089      * The new command line is build in new_cmdline[].
5090      * First allocate it.
5091      * Careful: a "+cmd" argument may have been NUL terminated.
5092      */
5093     len = (int)STRLEN(repl);
5094     i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3;
5095     if (eap->nextcmd != NULL)
5096 	i += (int)STRLEN(eap->nextcmd);/* add space for next command */
5097     if ((new_cmdline = alloc((unsigned)i)) == NULL)
5098 	return NULL;			/* out of memory! */
5099 
5100     /*
5101      * Copy the stuff before the expanded part.
5102      * Copy the expanded stuff.
5103      * Copy what came after the expanded part.
5104      * Copy the next commands, if there are any.
5105      */
5106     i = (int)(src - *cmdlinep);	/* length of part before match */
5107     mch_memmove(new_cmdline, *cmdlinep, (size_t)i);
5108 
5109     mch_memmove(new_cmdline + i, repl, (size_t)len);
5110     i += len;				/* remember the end of the string */
5111     STRCPY(new_cmdline + i, src + srclen);
5112     src = new_cmdline + i;		/* remember where to continue */
5113 
5114     if (eap->nextcmd != NULL)		/* append next command */
5115     {
5116 	i = (int)STRLEN(new_cmdline) + 1;
5117 	STRCPY(new_cmdline + i, eap->nextcmd);
5118 	eap->nextcmd = new_cmdline + i;
5119     }
5120     eap->cmd = new_cmdline + (eap->cmd - *cmdlinep);
5121     eap->arg = new_cmdline + (eap->arg - *cmdlinep);
5122     if (eap->do_ecmd_cmd != NULL && eap->do_ecmd_cmd != dollar_command)
5123 	eap->do_ecmd_cmd = new_cmdline + (eap->do_ecmd_cmd - *cmdlinep);
5124     vim_free(*cmdlinep);
5125     *cmdlinep = new_cmdline;
5126 
5127     return src;
5128 }
5129 
5130 /*
5131  * Check for '|' to separate commands and '"' to start comments.
5132  */
5133     void
5134 separate_nextcmd(exarg_T *eap)
5135 {
5136     char_u	*p;
5137 
5138 #ifdef FEAT_QUICKFIX
5139     p = skip_grep_pat(eap);
5140 #else
5141     p = eap->arg;
5142 #endif
5143 
5144     for ( ; *p; MB_PTR_ADV(p))
5145     {
5146 	if (*p == Ctrl_V)
5147 	{
5148 	    if (eap->argt & (USECTRLV | XFILE))
5149 		++p;		/* skip CTRL-V and next char */
5150 	    else
5151 				/* remove CTRL-V and skip next char */
5152 		STRMOVE(p, p + 1);
5153 	    if (*p == NUL)		/* stop at NUL after CTRL-V */
5154 		break;
5155 	}
5156 
5157 #ifdef FEAT_EVAL
5158 	/* Skip over `=expr` when wildcards are expanded. */
5159 	else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE))
5160 	{
5161 	    p += 2;
5162 	    (void)skip_expr(&p);
5163 	}
5164 #endif
5165 
5166 	/* Check for '"': start of comment or '|': next command */
5167 	/* :@" and :*" do not start a comment!
5168 	 * :redir @" doesn't either. */
5169 	else if ((*p == '"' && !(eap->argt & NOTRLCOM)
5170 		    && ((eap->cmdidx != CMD_at && eap->cmdidx != CMD_star)
5171 			|| p != eap->arg)
5172 		    && (eap->cmdidx != CMD_redir
5173 			|| p != eap->arg + 1 || p[-1] != '@'))
5174 		|| *p == '|' || *p == '\n')
5175 	{
5176 	    /*
5177 	     * We remove the '\' before the '|', unless USECTRLV is used
5178 	     * AND 'b' is present in 'cpoptions'.
5179 	     */
5180 	    if ((vim_strchr(p_cpo, CPO_BAR) == NULL
5181 			      || !(eap->argt & USECTRLV)) && *(p - 1) == '\\')
5182 	    {
5183 		STRMOVE(p - 1, p);	/* remove the '\' */
5184 		--p;
5185 	    }
5186 	    else
5187 	    {
5188 		eap->nextcmd = check_nextcmd(p);
5189 		*p = NUL;
5190 		break;
5191 	    }
5192 	}
5193     }
5194 
5195     if (!(eap->argt & NOTRLCOM))	/* remove trailing spaces */
5196 	del_trailing_spaces(eap->arg);
5197 }
5198 
5199 /*
5200  * get + command from ex argument
5201  */
5202     static char_u *
5203 getargcmd(char_u **argp)
5204 {
5205     char_u *arg = *argp;
5206     char_u *command = NULL;
5207 
5208     if (*arg == '+')	    /* +[command] */
5209     {
5210 	++arg;
5211 	if (vim_isspace(*arg) || *arg == NUL)
5212 	    command = dollar_command;
5213 	else
5214 	{
5215 	    command = arg;
5216 	    arg = skip_cmd_arg(command, TRUE);
5217 	    if (*arg != NUL)
5218 		*arg++ = NUL;		/* terminate command with NUL */
5219 	}
5220 
5221 	arg = skipwhite(arg);	/* skip over spaces */
5222 	*argp = arg;
5223     }
5224     return command;
5225 }
5226 
5227 /*
5228  * Find end of "+command" argument.  Skip over "\ " and "\\".
5229  */
5230     static char_u *
5231 skip_cmd_arg(
5232     char_u *p,
5233     int	   rembs)	/* TRUE to halve the number of backslashes */
5234 {
5235     while (*p && !vim_isspace(*p))
5236     {
5237 	if (*p == '\\' && p[1] != NUL)
5238 	{
5239 	    if (rembs)
5240 		STRMOVE(p, p + 1);
5241 	    else
5242 		++p;
5243 	}
5244 	MB_PTR_ADV(p);
5245     }
5246     return p;
5247 }
5248 
5249     int
5250 get_bad_opt(char_u *p, exarg_T *eap)
5251 {
5252     if (STRICMP(p, "keep") == 0)
5253 	eap->bad_char = BAD_KEEP;
5254     else if (STRICMP(p, "drop") == 0)
5255 	eap->bad_char = BAD_DROP;
5256     else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
5257 	eap->bad_char = *p;
5258     else
5259 	return FAIL;
5260     return OK;
5261 }
5262 
5263 /*
5264  * Get "++opt=arg" argument.
5265  * Return FAIL or OK.
5266  */
5267     static int
5268 getargopt(exarg_T *eap)
5269 {
5270     char_u	*arg = eap->arg + 2;
5271     int		*pp = NULL;
5272     int		bad_char_idx;
5273     char_u	*p;
5274 
5275     /* ":edit ++[no]bin[ary] file" */
5276     if (STRNCMP(arg, "bin", 3) == 0 || STRNCMP(arg, "nobin", 5) == 0)
5277     {
5278 	if (*arg == 'n')
5279 	{
5280 	    arg += 2;
5281 	    eap->force_bin = FORCE_NOBIN;
5282 	}
5283 	else
5284 	    eap->force_bin = FORCE_BIN;
5285 	if (!checkforcmd(&arg, "binary", 3))
5286 	    return FAIL;
5287 	eap->arg = skipwhite(arg);
5288 	return OK;
5289     }
5290 
5291     /* ":read ++edit file" */
5292     if (STRNCMP(arg, "edit", 4) == 0)
5293     {
5294 	eap->read_edit = TRUE;
5295 	eap->arg = skipwhite(arg + 4);
5296 	return OK;
5297     }
5298 
5299     if (STRNCMP(arg, "ff", 2) == 0)
5300     {
5301 	arg += 2;
5302 	pp = &eap->force_ff;
5303     }
5304     else if (STRNCMP(arg, "fileformat", 10) == 0)
5305     {
5306 	arg += 10;
5307 	pp = &eap->force_ff;
5308     }
5309     else if (STRNCMP(arg, "enc", 3) == 0)
5310     {
5311 	if (STRNCMP(arg, "encoding", 8) == 0)
5312 	    arg += 8;
5313 	else
5314 	    arg += 3;
5315 	pp = &eap->force_enc;
5316     }
5317     else if (STRNCMP(arg, "bad", 3) == 0)
5318     {
5319 	arg += 3;
5320 	pp = &bad_char_idx;
5321     }
5322 
5323     if (pp == NULL || *arg != '=')
5324 	return FAIL;
5325 
5326     ++arg;
5327     *pp = (int)(arg - eap->cmd);
5328     arg = skip_cmd_arg(arg, FALSE);
5329     eap->arg = skipwhite(arg);
5330     *arg = NUL;
5331 
5332     if (pp == &eap->force_ff)
5333     {
5334 	if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
5335 	    return FAIL;
5336 	eap->force_ff = eap->cmd[eap->force_ff];
5337     }
5338     else if (pp == &eap->force_enc)
5339     {
5340 	/* Make 'fileencoding' lower case. */
5341 	for (p = eap->cmd + eap->force_enc; *p != NUL; ++p)
5342 	    *p = TOLOWER_ASC(*p);
5343     }
5344     else
5345     {
5346 	/* Check ++bad= argument.  Must be a single-byte character, "keep" or
5347 	 * "drop". */
5348 	if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL)
5349 	    return FAIL;
5350     }
5351 
5352     return OK;
5353 }
5354 
5355 /*
5356  * ":abbreviate" and friends.
5357  */
5358     static void
5359 ex_abbreviate(exarg_T *eap)
5360 {
5361     do_exmap(eap, TRUE);	/* almost the same as mapping */
5362 }
5363 
5364 /*
5365  * ":map" and friends.
5366  */
5367     static void
5368 ex_map(exarg_T *eap)
5369 {
5370     /*
5371      * If we are sourcing .exrc or .vimrc in current directory we
5372      * print the mappings for security reasons.
5373      */
5374     if (secure)
5375     {
5376 	secure = 2;
5377 	msg_outtrans(eap->cmd);
5378 	msg_putchar('\n');
5379     }
5380     do_exmap(eap, FALSE);
5381 }
5382 
5383 /*
5384  * ":unmap" and friends.
5385  */
5386     static void
5387 ex_unmap(exarg_T *eap)
5388 {
5389     do_exmap(eap, FALSE);
5390 }
5391 
5392 /*
5393  * ":mapclear" and friends.
5394  */
5395     static void
5396 ex_mapclear(exarg_T *eap)
5397 {
5398     map_clear(eap->cmd, eap->arg, eap->forceit, FALSE);
5399 }
5400 
5401 /*
5402  * ":abclear" and friends.
5403  */
5404     static void
5405 ex_abclear(exarg_T *eap)
5406 {
5407     map_clear(eap->cmd, eap->arg, TRUE, TRUE);
5408 }
5409 
5410     static void
5411 ex_autocmd(exarg_T *eap)
5412 {
5413     /*
5414      * Disallow autocommands from .exrc and .vimrc in current
5415      * directory for security reasons.
5416      */
5417     if (secure)
5418     {
5419 	secure = 2;
5420 	eap->errmsg = e_curdir;
5421     }
5422     else if (eap->cmdidx == CMD_autocmd)
5423 	do_autocmd(eap->arg, eap->forceit);
5424     else
5425 	do_augroup(eap->arg, eap->forceit);
5426 }
5427 
5428 /*
5429  * ":doautocmd": Apply the automatic commands to the current buffer.
5430  */
5431     static void
5432 ex_doautocmd(exarg_T *eap)
5433 {
5434     char_u	*arg = eap->arg;
5435     int		call_do_modelines = check_nomodeline(&arg);
5436     int		did_aucmd;
5437 
5438     (void)do_doautocmd(arg, TRUE, &did_aucmd);
5439     /* Only when there is no <nomodeline>. */
5440     if (call_do_modelines && did_aucmd)
5441 	do_modelines(0);
5442 }
5443 
5444 /*
5445  * :[N]bunload[!] [N] [bufname] unload buffer
5446  * :[N]bdelete[!] [N] [bufname] delete buffer from buffer list
5447  * :[N]bwipeout[!] [N] [bufname] delete buffer really
5448  */
5449     static void
5450 ex_bunload(exarg_T *eap)
5451 {
5452     eap->errmsg = do_bufdel(
5453 	    eap->cmdidx == CMD_bdelete ? DOBUF_DEL
5454 		: eap->cmdidx == CMD_bwipeout ? DOBUF_WIPE
5455 		: DOBUF_UNLOAD, eap->arg,
5456 	    eap->addr_count, (int)eap->line1, (int)eap->line2, eap->forceit);
5457 }
5458 
5459 /*
5460  * :[N]buffer [N]	to buffer N
5461  * :[N]sbuffer [N]	to buffer N
5462  */
5463     static void
5464 ex_buffer(exarg_T *eap)
5465 {
5466     if (*eap->arg)
5467 	eap->errmsg = e_trailing;
5468     else
5469     {
5470 	if (eap->addr_count == 0)	/* default is current buffer */
5471 	    goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0);
5472 	else
5473 	    goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2);
5474 	if (eap->do_ecmd_cmd != NULL)
5475 	    do_cmdline_cmd(eap->do_ecmd_cmd);
5476     }
5477 }
5478 
5479 /*
5480  * :[N]bmodified [N]	to next mod. buffer
5481  * :[N]sbmodified [N]	to next mod. buffer
5482  */
5483     static void
5484 ex_bmodified(exarg_T *eap)
5485 {
5486     goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2);
5487     if (eap->do_ecmd_cmd != NULL)
5488 	do_cmdline_cmd(eap->do_ecmd_cmd);
5489 }
5490 
5491 /*
5492  * :[N]bnext [N]	to next buffer
5493  * :[N]sbnext [N]	split and to next buffer
5494  */
5495     static void
5496 ex_bnext(exarg_T *eap)
5497 {
5498     goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2);
5499     if (eap->do_ecmd_cmd != NULL)
5500 	do_cmdline_cmd(eap->do_ecmd_cmd);
5501 }
5502 
5503 /*
5504  * :[N]bNext [N]	to previous buffer
5505  * :[N]bprevious [N]	to previous buffer
5506  * :[N]sbNext [N]	split and to previous buffer
5507  * :[N]sbprevious [N]	split and to previous buffer
5508  */
5509     static void
5510 ex_bprevious(exarg_T *eap)
5511 {
5512     goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2);
5513     if (eap->do_ecmd_cmd != NULL)
5514 	do_cmdline_cmd(eap->do_ecmd_cmd);
5515 }
5516 
5517 /*
5518  * :brewind		to first buffer
5519  * :bfirst		to first buffer
5520  * :sbrewind		split and to first buffer
5521  * :sbfirst		split and to first buffer
5522  */
5523     static void
5524 ex_brewind(exarg_T *eap)
5525 {
5526     goto_buffer(eap, DOBUF_FIRST, FORWARD, 0);
5527     if (eap->do_ecmd_cmd != NULL)
5528 	do_cmdline_cmd(eap->do_ecmd_cmd);
5529 }
5530 
5531 /*
5532  * :blast		to last buffer
5533  * :sblast		split and to last buffer
5534  */
5535     static void
5536 ex_blast(exarg_T *eap)
5537 {
5538     goto_buffer(eap, DOBUF_LAST, BACKWARD, 0);
5539     if (eap->do_ecmd_cmd != NULL)
5540 	do_cmdline_cmd(eap->do_ecmd_cmd);
5541 }
5542 
5543     int
5544 ends_excmd(int c)
5545 {
5546     return (c == NUL || c == '|' || c == '"' || c == '\n');
5547 }
5548 
5549 #if defined(FEAT_SYN_HL) || defined(FEAT_SEARCH_EXTRA) || defined(FEAT_EVAL) \
5550 	|| defined(PROTO)
5551 /*
5552  * Return the next command, after the first '|' or '\n'.
5553  * Return NULL if not found.
5554  */
5555     char_u *
5556 find_nextcmd(char_u *p)
5557 {
5558     while (*p != '|' && *p != '\n')
5559     {
5560 	if (*p == NUL)
5561 	    return NULL;
5562 	++p;
5563     }
5564     return (p + 1);
5565 }
5566 #endif
5567 
5568 /*
5569  * Check if *p is a separator between Ex commands, skipping over white space.
5570  * Return NULL if it isn't, the following character if it is.
5571  */
5572     char_u *
5573 check_nextcmd(char_u *p)
5574 {
5575     char_u *s = skipwhite(p);
5576 
5577     if (*s == '|' || *s == '\n')
5578 	return (s + 1);
5579     else
5580 	return NULL;
5581 }
5582 
5583 /*
5584  * - if there are more files to edit
5585  * - and this is the last window
5586  * - and forceit not used
5587  * - and not repeated twice on a row
5588  *    return FAIL and give error message if 'message' TRUE
5589  * return OK otherwise
5590  */
5591     static int
5592 check_more(
5593     int message,	    /* when FALSE check only, no messages */
5594     int forceit)
5595 {
5596     int	    n = ARGCOUNT - curwin->w_arg_idx - 1;
5597 
5598     if (!forceit && only_one_window()
5599 	    && ARGCOUNT > 1 && !arg_had_last && n >= 0 && quitmore == 0)
5600     {
5601 	if (message)
5602 	{
5603 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
5604 	    if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL)
5605 	    {
5606 		char_u	buff[DIALOG_MSG_SIZE];
5607 
5608 		vim_snprintf((char *)buff, DIALOG_MSG_SIZE,
5609 			NGETTEXT("%d more file to edit.  Quit anyway?",
5610 			    "%d more files to edit.  Quit anyway?", n), n);
5611 		if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
5612 		    return OK;
5613 		return FAIL;
5614 	    }
5615 #endif
5616 	    semsg(NGETTEXT("E173: %d more file to edit",
5617 			"E173: %d more files to edit", n), n);
5618 	    quitmore = 2;	    /* next try to quit is allowed */
5619 	}
5620 	return FAIL;
5621     }
5622     return OK;
5623 }
5624 
5625 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
5626 /*
5627  * Function given to ExpandGeneric() to obtain the list of command names.
5628  */
5629     char_u *
5630 get_command_name(expand_T *xp UNUSED, int idx)
5631 {
5632     if (idx >= (int)CMD_SIZE)
5633 	return get_user_command_name(idx);
5634     return cmdnames[idx].cmd_name;
5635 }
5636 #endif
5637 
5638     static void
5639 ex_colorscheme(exarg_T *eap)
5640 {
5641     if (*eap->arg == NUL)
5642     {
5643 #ifdef FEAT_EVAL
5644 	char_u *expr = vim_strsave((char_u *)"g:colors_name");
5645 	char_u *p = NULL;
5646 
5647 	if (expr != NULL)
5648 	{
5649 	    ++emsg_off;
5650 	    p = eval_to_string(expr, NULL, FALSE);
5651 	    --emsg_off;
5652 	    vim_free(expr);
5653 	}
5654 	if (p != NULL)
5655 	{
5656 	    msg((char *)p);
5657 	    vim_free(p);
5658 	}
5659 	else
5660 	    msg("default");
5661 #else
5662 	msg(_("unknown"));
5663 #endif
5664     }
5665     else if (load_colors(eap->arg) == FAIL)
5666 	semsg(_("E185: Cannot find color scheme '%s'"), eap->arg);
5667 
5668 #ifdef FEAT_VTP
5669     else if (has_vtp_working())
5670     {
5671 	// background color change requires clear + redraw
5672 	update_screen(CLEAR);
5673 	redrawcmd();
5674     }
5675 #endif
5676 }
5677 
5678     static void
5679 ex_highlight(exarg_T *eap)
5680 {
5681     if (*eap->arg == NUL && eap->cmd[2] == '!')
5682 	msg(_("Greetings, Vim user!"));
5683     do_highlight(eap->arg, eap->forceit, FALSE);
5684 }
5685 
5686 
5687 /*
5688  * Call this function if we thought we were going to exit, but we won't
5689  * (because of an error).  May need to restore the terminal mode.
5690  */
5691     void
5692 not_exiting(void)
5693 {
5694     exiting = FALSE;
5695     settmode(TMODE_RAW);
5696 }
5697 
5698     static int
5699 before_quit_autocmds(win_T *wp, int quit_all, int forceit)
5700 {
5701     apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, wp->w_buffer);
5702 
5703     /* Bail out when autocommands closed the window.
5704      * Refuse to quit when the buffer in the last window is being closed (can
5705      * only happen in autocommands). */
5706     if (!win_valid(wp)
5707 	    || curbuf_locked()
5708 	    || (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0))
5709 	return TRUE;
5710 
5711     if (quit_all || (check_more(FALSE, forceit) == OK && only_one_window()))
5712     {
5713 	apply_autocmds(EVENT_EXITPRE, NULL, NULL, FALSE, curbuf);
5714 	/* Refuse to quit when locked or when the buffer in the last window is
5715 	 * being closed (can only happen in autocommands). */
5716 	if (curbuf_locked()
5717 			  || (curbuf->b_nwindows == 1 && curbuf->b_locked > 0))
5718 	    return TRUE;
5719     }
5720 
5721     return FALSE;
5722 }
5723 
5724 /*
5725  * ":quit": quit current window, quit Vim if the last window is closed.
5726  * ":{nr}quit": quit window {nr}
5727  */
5728     static void
5729 ex_quit(exarg_T *eap)
5730 {
5731     win_T	*wp;
5732 
5733 #ifdef FEAT_CMDWIN
5734     if (cmdwin_type != 0)
5735     {
5736 	cmdwin_result = Ctrl_C;
5737 	return;
5738     }
5739 #endif
5740     /* Don't quit while editing the command line. */
5741     if (text_locked())
5742     {
5743 	text_locked_msg();
5744 	return;
5745     }
5746     if (eap->addr_count > 0)
5747     {
5748 	int	wnr = eap->line2;
5749 
5750 	for (wp = firstwin; wp->w_next != NULL; wp = wp->w_next)
5751 	    if (--wnr <= 0)
5752 		break;
5753     }
5754     else
5755 	wp = curwin;
5756 
5757     /* Refuse to quit when locked. */
5758     if (curbuf_locked())
5759 	return;
5760 
5761     /* Trigger QuitPre and maybe ExitPre */
5762     if (before_quit_autocmds(wp, FALSE, eap->forceit))
5763 	return;
5764 
5765 #ifdef FEAT_NETBEANS_INTG
5766     netbeansForcedQuit = eap->forceit;
5767 #endif
5768 
5769     /*
5770      * If there are more files or windows we won't exit.
5771      */
5772     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
5773 	exiting = TRUE;
5774     if ((!buf_hide(wp->w_buffer)
5775 		&& check_changed(wp->w_buffer, (p_awa ? CCGD_AW : 0)
5776 				       | (eap->forceit ? CCGD_FORCEIT : 0)
5777 				       | CCGD_EXCMD))
5778 	    || check_more(TRUE, eap->forceit) == FAIL
5779 	    || (only_one_window() && check_changed_any(eap->forceit, TRUE)))
5780     {
5781 	not_exiting();
5782     }
5783     else
5784     {
5785 	/* quit last window
5786 	 * Note: only_one_window() returns true, even so a help window is
5787 	 * still open. In that case only quit, if no address has been
5788 	 * specified. Example:
5789 	 * :h|wincmd w|1q     - don't quit
5790 	 * :h|wincmd w|q      - quit
5791 	 */
5792 	if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0))
5793 	    getout(0);
5794 	not_exiting();
5795 #ifdef FEAT_GUI
5796 	need_mouse_correct = TRUE;
5797 #endif
5798 	/* close window; may free buffer */
5799 	win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit);
5800     }
5801 }
5802 
5803 /*
5804  * ":cquit".
5805  */
5806     static void
5807 ex_cquit(exarg_T *eap UNUSED)
5808 {
5809     getout(1);	/* this does not always pass on the exit code to the Manx
5810 		   compiler. why? */
5811 }
5812 
5813 /*
5814  * ":qall": try to quit all windows
5815  */
5816     static void
5817 ex_quit_all(exarg_T *eap)
5818 {
5819 # ifdef FEAT_CMDWIN
5820     if (cmdwin_type != 0)
5821     {
5822 	if (eap->forceit)
5823 	    cmdwin_result = K_XF1;	/* ex_window() takes care of this */
5824 	else
5825 	    cmdwin_result = K_XF2;
5826 	return;
5827     }
5828 # endif
5829 
5830     /* Don't quit while editing the command line. */
5831     if (text_locked())
5832     {
5833 	text_locked_msg();
5834 	return;
5835     }
5836 
5837     if (before_quit_autocmds(curwin, TRUE, eap->forceit))
5838 	return;
5839 
5840     exiting = TRUE;
5841     if (eap->forceit || !check_changed_any(FALSE, FALSE))
5842 	getout(0);
5843     not_exiting();
5844 }
5845 
5846 /*
5847  * ":close": close current window, unless it is the last one
5848  */
5849     static void
5850 ex_close(exarg_T *eap)
5851 {
5852     win_T	*win;
5853     int		winnr = 0;
5854 #ifdef FEAT_CMDWIN
5855     if (cmdwin_type != 0)
5856 	cmdwin_result = Ctrl_C;
5857     else
5858 #endif
5859 	if (!text_locked() && !curbuf_locked())
5860 	{
5861 	    if (eap->addr_count == 0)
5862 		ex_win_close(eap->forceit, curwin, NULL);
5863 	    else
5864 	    {
5865 		FOR_ALL_WINDOWS(win)
5866 		{
5867 		    winnr++;
5868 		    if (winnr == eap->line2)
5869 			break;
5870 		}
5871 		if (win == NULL)
5872 		    win = lastwin;
5873 		ex_win_close(eap->forceit, win, NULL);
5874 	    }
5875 	}
5876 }
5877 
5878 #ifdef FEAT_QUICKFIX
5879 /*
5880  * ":pclose": Close any preview window.
5881  */
5882     static void
5883 ex_pclose(exarg_T *eap)
5884 {
5885     win_T	*win;
5886 
5887     FOR_ALL_WINDOWS(win)
5888 	if (win->w_p_pvw)
5889 	{
5890 	    ex_win_close(eap->forceit, win, NULL);
5891 	    break;
5892 	}
5893 }
5894 #endif
5895 
5896 /*
5897  * Close window "win" and take care of handling closing the last window for a
5898  * modified buffer.
5899  */
5900     static void
5901 ex_win_close(
5902     int		forceit,
5903     win_T	*win,
5904     tabpage_T	*tp)		/* NULL or the tab page "win" is in */
5905 {
5906     int		need_hide;
5907     buf_T	*buf = win->w_buffer;
5908 
5909     need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
5910     if (need_hide && !buf_hide(buf) && !forceit)
5911     {
5912 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
5913 	if ((p_confirm || cmdmod.confirm) && p_write)
5914 	{
5915 	    bufref_T bufref;
5916 
5917 	    set_bufref(&bufref, buf);
5918 	    dialog_changed(buf, FALSE);
5919 	    if (bufref_valid(&bufref) && bufIsChanged(buf))
5920 		return;
5921 	    need_hide = FALSE;
5922 	}
5923 	else
5924 #endif
5925 	{
5926 	    no_write_message();
5927 	    return;
5928 	}
5929     }
5930 
5931 #ifdef FEAT_GUI
5932     need_mouse_correct = TRUE;
5933 #endif
5934 
5935     /* free buffer when not hiding it or when it's a scratch buffer */
5936     if (tp == NULL)
5937 	win_close(win, !need_hide && !buf_hide(buf));
5938     else
5939 	win_close_othertab(win, !need_hide && !buf_hide(buf), tp);
5940 }
5941 
5942 /*
5943  * Handle the argument for a tabpage related ex command.
5944  * Returns a tabpage number.
5945  * When an error is encountered then eap->errmsg is set.
5946  */
5947     static int
5948 get_tabpage_arg(exarg_T *eap)
5949 {
5950     int tab_number;
5951     int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1;
5952 
5953     if (eap->arg && *eap->arg != NUL)
5954     {
5955 	char_u *p = eap->arg;
5956 	char_u *p_save;
5957 	int    relative = 0; /* argument +N/-N means: go to N places to the
5958 			      * right/left relative to the current position. */
5959 
5960 	if (*p == '-')
5961 	{
5962 	    relative = -1;
5963 	    p++;
5964 	}
5965 	else if (*p == '+')
5966 	{
5967 	    relative = 1;
5968 	    p++;
5969 	}
5970 
5971 	p_save = p;
5972 	tab_number = getdigits(&p);
5973 
5974 	if (relative == 0)
5975 	{
5976 	    if (STRCMP(p, "$") == 0)
5977 		tab_number = LAST_TAB_NR;
5978 	    else if (p == p_save || *p_save == '-' || *p != NUL
5979 		    || tab_number > LAST_TAB_NR)
5980 	    {
5981 		/* No numbers as argument. */
5982 		eap->errmsg = e_invarg;
5983 		goto theend;
5984 	    }
5985 	}
5986 	else
5987 	{
5988 	    if (*p_save == NUL)
5989 		tab_number = 1;
5990 	    else if (p == p_save || *p_save == '-' || *p != NUL
5991 		    || tab_number == 0)
5992 	    {
5993 		/* No numbers as argument. */
5994 		eap->errmsg = e_invarg;
5995 		goto theend;
5996 	    }
5997 	    tab_number = tab_number * relative + tabpage_index(curtab);
5998 	    if (!unaccept_arg0 && relative == -1)
5999 		--tab_number;
6000 	}
6001 	if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR)
6002 	    eap->errmsg = e_invarg;
6003     }
6004     else if (eap->addr_count > 0)
6005     {
6006 	if (unaccept_arg0 && eap->line2 == 0)
6007 	{
6008 	    eap->errmsg = e_invrange;
6009 	    tab_number = 0;
6010 	}
6011 	else
6012 	{
6013 	    tab_number = eap->line2;
6014 	    if (!unaccept_arg0 && *skipwhite(*eap->cmdlinep) == '-')
6015 	    {
6016 		--tab_number;
6017 		if (tab_number < unaccept_arg0)
6018 		    eap->errmsg = e_invarg;
6019 	    }
6020 	}
6021     }
6022     else
6023     {
6024 	switch (eap->cmdidx)
6025 	{
6026 	case CMD_tabnext:
6027 	    tab_number = tabpage_index(curtab) + 1;
6028 	    if (tab_number > LAST_TAB_NR)
6029 		tab_number = 1;
6030 	    break;
6031 	case CMD_tabmove:
6032 	    tab_number = LAST_TAB_NR;
6033 	    break;
6034 	default:
6035 	    tab_number = tabpage_index(curtab);
6036 	}
6037     }
6038 
6039 theend:
6040     return tab_number;
6041 }
6042 
6043 /*
6044  * ":tabclose": close current tab page, unless it is the last one.
6045  * ":tabclose N": close tab page N.
6046  */
6047     static void
6048 ex_tabclose(exarg_T *eap)
6049 {
6050     tabpage_T	*tp;
6051     int		tab_number;
6052 
6053 # ifdef FEAT_CMDWIN
6054     if (cmdwin_type != 0)
6055 	cmdwin_result = K_IGNORE;
6056     else
6057 # endif
6058 	if (first_tabpage->tp_next == NULL)
6059 	    emsg(_("E784: Cannot close last tab page"));
6060 	else
6061 	{
6062 	    tab_number = get_tabpage_arg(eap);
6063 	    if (eap->errmsg == NULL)
6064 	    {
6065 		tp = find_tabpage(tab_number);
6066 		if (tp == NULL)
6067 		{
6068 		    beep_flush();
6069 		    return;
6070 		}
6071 		if (tp != curtab)
6072 		{
6073 		    tabpage_close_other(tp, eap->forceit);
6074 		    return;
6075 		}
6076 		else if (!text_locked() && !curbuf_locked())
6077 		    tabpage_close(eap->forceit);
6078 	    }
6079 	}
6080 }
6081 
6082 /*
6083  * ":tabonly": close all tab pages except the current one
6084  */
6085     static void
6086 ex_tabonly(exarg_T *eap)
6087 {
6088     tabpage_T	*tp;
6089     int		done;
6090     int		tab_number;
6091 
6092 # ifdef FEAT_CMDWIN
6093     if (cmdwin_type != 0)
6094 	cmdwin_result = K_IGNORE;
6095     else
6096 # endif
6097 	if (first_tabpage->tp_next == NULL)
6098 	    msg(_("Already only one tab page"));
6099 	else
6100 	{
6101 	    tab_number = get_tabpage_arg(eap);
6102 	    if (eap->errmsg == NULL)
6103 	    {
6104 		goto_tabpage(tab_number);
6105 		/* Repeat this up to a 1000 times, because autocommands may
6106 		 * mess up the lists. */
6107 		for (done = 0; done < 1000; ++done)
6108 		{
6109 		    FOR_ALL_TABPAGES(tp)
6110 			if (tp->tp_topframe != topframe)
6111 			{
6112 			    tabpage_close_other(tp, eap->forceit);
6113 			    /* if we failed to close it quit */
6114 			    if (valid_tabpage(tp))
6115 				done = 1000;
6116 			    /* start over, "tp" is now invalid */
6117 			    break;
6118 			}
6119 		    if (first_tabpage->tp_next == NULL)
6120 			break;
6121 		}
6122 	    }
6123 	}
6124 }
6125 
6126 /*
6127  * Close the current tab page.
6128  */
6129     void
6130 tabpage_close(int forceit)
6131 {
6132     /* First close all the windows but the current one.  If that worked then
6133      * close the last window in this tab, that will close it. */
6134     if (!ONE_WINDOW)
6135 	close_others(TRUE, forceit);
6136     if (ONE_WINDOW)
6137 	ex_win_close(forceit, curwin, NULL);
6138 # ifdef FEAT_GUI
6139     need_mouse_correct = TRUE;
6140 # endif
6141 }
6142 
6143 /*
6144  * Close tab page "tp", which is not the current tab page.
6145  * Note that autocommands may make "tp" invalid.
6146  * Also takes care of the tab pages line disappearing when closing the
6147  * last-but-one tab page.
6148  */
6149     void
6150 tabpage_close_other(tabpage_T *tp, int forceit)
6151 {
6152     int		done = 0;
6153     win_T	*wp;
6154     int		h = tabline_height();
6155 
6156     /* Limit to 1000 windows, autocommands may add a window while we close
6157      * one.  OK, so I'm paranoid... */
6158     while (++done < 1000)
6159     {
6160 	wp = tp->tp_firstwin;
6161 	ex_win_close(forceit, wp, tp);
6162 
6163 	/* Autocommands may delete the tab page under our fingers and we may
6164 	 * fail to close a window with a modified buffer. */
6165 	if (!valid_tabpage(tp) || tp->tp_firstwin == wp)
6166 	    break;
6167     }
6168 
6169     apply_autocmds(EVENT_TABCLOSED, NULL, NULL, FALSE, curbuf);
6170 
6171     redraw_tabline = TRUE;
6172     if (h != tabline_height())
6173 	shell_new_rows();
6174 }
6175 
6176 /*
6177  * ":only".
6178  */
6179     static void
6180 ex_only(exarg_T *eap)
6181 {
6182     win_T   *wp;
6183     int	    wnr;
6184 # ifdef FEAT_GUI
6185     need_mouse_correct = TRUE;
6186 # endif
6187     if (eap->addr_count > 0)
6188     {
6189 	wnr = eap->line2;
6190 	for (wp = firstwin; --wnr > 0; )
6191 	{
6192 	    if (wp->w_next == NULL)
6193 		break;
6194 	    else
6195 		wp = wp->w_next;
6196 	}
6197 	win_goto(wp);
6198     }
6199     close_others(TRUE, eap->forceit);
6200 }
6201 
6202 /*
6203  * ":all" and ":sall".
6204  * Also used for ":tab drop file ..." after setting the argument list.
6205  */
6206     void
6207 ex_all(exarg_T *eap)
6208 {
6209     if (eap->addr_count == 0)
6210 	eap->line2 = 9999;
6211     do_arg_all((int)eap->line2, eap->forceit, eap->cmdidx == CMD_drop);
6212 }
6213 
6214     static void
6215 ex_hide(exarg_T *eap UNUSED)
6216 {
6217     /* ":hide" or ":hide | cmd": hide current window */
6218     if (!eap->skip)
6219     {
6220 #ifdef FEAT_GUI
6221 	need_mouse_correct = TRUE;
6222 #endif
6223 	if (eap->addr_count == 0)
6224 	    win_close(curwin, FALSE);	/* don't free buffer */
6225 	else
6226 	{
6227 	    int	winnr = 0;
6228 	    win_T	*win;
6229 
6230 	    FOR_ALL_WINDOWS(win)
6231 	    {
6232 		winnr++;
6233 		if (winnr == eap->line2)
6234 		    break;
6235 	    }
6236 	    if (win == NULL)
6237 		win = lastwin;
6238 	    win_close(win, FALSE);
6239 	}
6240     }
6241 }
6242 
6243 /*
6244  * ":stop" and ":suspend": Suspend Vim.
6245  */
6246     static void
6247 ex_stop(exarg_T *eap)
6248 {
6249     /*
6250      * Disallow suspending for "rvim".
6251      */
6252     if (!check_restricted())
6253     {
6254 	if (!eap->forceit)
6255 	    autowrite_all();
6256 	windgoto((int)Rows - 1, 0);
6257 	out_char('\n');
6258 	out_flush();
6259 	stoptermcap();
6260 	out_flush();		/* needed for SUN to restore xterm buffer */
6261 #ifdef FEAT_TITLE
6262 	mch_restore_title(SAVE_RESTORE_BOTH);	/* restore window titles */
6263 #endif
6264 	ui_suspend();		/* call machine specific function */
6265 #ifdef FEAT_TITLE
6266 	maketitle();
6267 	resettitle();		/* force updating the title */
6268 #endif
6269 	starttermcap();
6270 	scroll_start();		/* scroll screen before redrawing */
6271 	redraw_later_clear();
6272 	shell_resized();	/* may have resized window */
6273     }
6274 }
6275 
6276 /*
6277  * ":exit", ":xit" and ":wq": Write file and quite the current window.
6278  */
6279     static void
6280 ex_exit(exarg_T *eap)
6281 {
6282 #ifdef FEAT_CMDWIN
6283     if (cmdwin_type != 0)
6284     {
6285 	cmdwin_result = Ctrl_C;
6286 	return;
6287     }
6288 #endif
6289     /* Don't quit while editing the command line. */
6290     if (text_locked())
6291     {
6292 	text_locked_msg();
6293 	return;
6294     }
6295 
6296     if (before_quit_autocmds(curwin, FALSE, eap->forceit))
6297 	return;
6298 
6299     /*
6300      * if more files or windows we won't exit
6301      */
6302     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
6303 	exiting = TRUE;
6304     if (       ((eap->cmdidx == CMD_wq
6305 		    || curbufIsChanged())
6306 		&& do_write(eap) == FAIL)
6307 	    || check_more(TRUE, eap->forceit) == FAIL
6308 	    || (only_one_window() && check_changed_any(eap->forceit, FALSE)))
6309     {
6310 	not_exiting();
6311     }
6312     else
6313     {
6314 	if (only_one_window())	    /* quit last window, exit Vim */
6315 	    getout(0);
6316 	not_exiting();
6317 # ifdef FEAT_GUI
6318 	need_mouse_correct = TRUE;
6319 # endif
6320 	/* Quit current window, may free the buffer. */
6321 	win_close(curwin, !buf_hide(curwin->w_buffer));
6322     }
6323 }
6324 
6325 /*
6326  * ":print", ":list", ":number".
6327  */
6328     static void
6329 ex_print(exarg_T *eap)
6330 {
6331     if (curbuf->b_ml.ml_flags & ML_EMPTY)
6332 	emsg(_(e_emptybuf));
6333     else
6334     {
6335 	for ( ;!got_int; ui_breakcheck())
6336 	{
6337 	    print_line(eap->line1,
6338 		    (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound
6339 						 || (eap->flags & EXFLAG_NR)),
6340 		    eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST));
6341 	    if (++eap->line1 > eap->line2)
6342 		break;
6343 	    out_flush();	    /* show one line at a time */
6344 	}
6345 	setpcmark();
6346 	/* put cursor at last line */
6347 	curwin->w_cursor.lnum = eap->line2;
6348 	beginline(BL_SOL | BL_FIX);
6349     }
6350 
6351     ex_no_reprint = TRUE;
6352 }
6353 
6354 #ifdef FEAT_BYTEOFF
6355     static void
6356 ex_goto(exarg_T *eap)
6357 {
6358     goto_byte(eap->line2);
6359 }
6360 #endif
6361 
6362 /*
6363  * ":shell".
6364  */
6365     static void
6366 ex_shell(exarg_T *eap UNUSED)
6367 {
6368     do_shell(NULL, 0);
6369 }
6370 
6371 #if defined(HAVE_DROP_FILE) || defined(PROTO)
6372 
6373 static int drop_busy = FALSE;
6374 static int drop_filec;
6375 static char_u **drop_filev = NULL;
6376 static int drop_split;
6377 static void (*drop_callback)(void *);
6378 static void *drop_cookie;
6379 
6380     static void
6381 handle_drop_internal(void)
6382 {
6383     exarg_T	ea;
6384     int		save_msg_scroll = msg_scroll;
6385 
6386     // Setting the argument list may cause screen updates and being called
6387     // recursively.  Avoid that by setting drop_busy.
6388     drop_busy = TRUE;
6389 
6390     /* Check whether the current buffer is changed. If so, we will need
6391      * to split the current window or data could be lost.
6392      * We don't need to check if the 'hidden' option is set, as in this
6393      * case the buffer won't be lost.
6394      */
6395     if (!buf_hide(curbuf) && !drop_split)
6396     {
6397 	++emsg_off;
6398 	drop_split = check_changed(curbuf, CCGD_AW);
6399 	--emsg_off;
6400     }
6401     if (drop_split)
6402     {
6403 	if (win_split(0, 0) == FAIL)
6404 	    return;
6405 	RESET_BINDING(curwin);
6406 
6407 	/* When splitting the window, create a new alist.  Otherwise the
6408 	 * existing one is overwritten. */
6409 	alist_unlink(curwin->w_alist);
6410 	alist_new();
6411     }
6412 
6413     /*
6414      * Set up the new argument list.
6415      */
6416     alist_set(ALIST(curwin), drop_filec, drop_filev, FALSE, NULL, 0);
6417 
6418     /*
6419      * Move to the first file.
6420      */
6421     /* Fake up a minimal "next" command for do_argfile() */
6422     vim_memset(&ea, 0, sizeof(ea));
6423     ea.cmd = (char_u *)"next";
6424     do_argfile(&ea, 0);
6425 
6426     /* do_ecmd() may set need_start_insertmode, but since we never left Insert
6427      * mode that is not needed here. */
6428     need_start_insertmode = FALSE;
6429 
6430     /* Restore msg_scroll, otherwise a following command may cause scrolling
6431      * unexpectedly.  The screen will be redrawn by the caller, thus
6432      * msg_scroll being set by displaying a message is irrelevant. */
6433     msg_scroll = save_msg_scroll;
6434 
6435     if (drop_callback != NULL)
6436 	drop_callback(drop_cookie);
6437 
6438     drop_filev = NULL;
6439     drop_busy = FALSE;
6440 }
6441 
6442 /*
6443  * Handle a file drop. The code is here because a drop is *nearly* like an
6444  * :args command, but not quite (we have a list of exact filenames, so we
6445  * don't want to (a) parse a command line, or (b) expand wildcards). So the
6446  * code is very similar to :args and hence needs access to a lot of the static
6447  * functions in this file.
6448  *
6449  * The "filev" list must have been allocated using alloc(), as should each item
6450  * in the list. This function takes over responsibility for freeing the "filev"
6451  * list.
6452  */
6453     void
6454 handle_drop(
6455     int		filec,		// the number of files dropped
6456     char_u	**filev,	// the list of files dropped
6457     int		split,		// force splitting the window
6458     void	(*callback)(void *), // to be called after setting the argument
6459 				     // list
6460     void	*cookie)	// argument for "callback" (allocated)
6461 {
6462     // Cannot handle recursive drops, finish the pending one.
6463     if (drop_busy)
6464     {
6465 	FreeWild(filec, filev);
6466 	vim_free(cookie);
6467 	return;
6468     }
6469 
6470     // When calling handle_drop() more than once in a row we only use the last
6471     // one.
6472     if (drop_filev != NULL)
6473     {
6474 	FreeWild(drop_filec, drop_filev);
6475 	vim_free(drop_cookie);
6476     }
6477 
6478     drop_filec = filec;
6479     drop_filev = filev;
6480     drop_split = split;
6481     drop_callback = callback;
6482     drop_cookie = cookie;
6483 
6484     // Postpone this when:
6485     // - editing the command line
6486     // - not possible to change the current buffer
6487     // - updating the screen
6488     // As it may change buffers and window structures that are in use and cause
6489     // freed memory to be used.
6490     if (text_locked() || curbuf_locked() || updating_screen)
6491 	return;
6492 
6493     handle_drop_internal();
6494 }
6495 
6496 /*
6497  * To be called when text is unlocked, curbuf is unlocked or updating_screen is
6498  * reset: Handle a postponed drop.
6499  */
6500     void
6501 handle_any_postponed_drop(void)
6502 {
6503     if (!drop_busy && drop_filev != NULL
6504 		     && !text_locked() && !curbuf_locked() && !updating_screen)
6505 	handle_drop_internal();
6506 }
6507 #endif
6508 
6509 /*
6510  * Clear an argument list: free all file names and reset it to zero entries.
6511  */
6512     void
6513 alist_clear(alist_T *al)
6514 {
6515     while (--al->al_ga.ga_len >= 0)
6516 	vim_free(AARGLIST(al)[al->al_ga.ga_len].ae_fname);
6517     ga_clear(&al->al_ga);
6518 }
6519 
6520 /*
6521  * Init an argument list.
6522  */
6523     void
6524 alist_init(alist_T *al)
6525 {
6526     ga_init2(&al->al_ga, (int)sizeof(aentry_T), 5);
6527 }
6528 
6529 /*
6530  * Remove a reference from an argument list.
6531  * Ignored when the argument list is the global one.
6532  * If the argument list is no longer used by any window, free it.
6533  */
6534     void
6535 alist_unlink(alist_T *al)
6536 {
6537     if (al != &global_alist && --al->al_refcount <= 0)
6538     {
6539 	alist_clear(al);
6540 	vim_free(al);
6541     }
6542 }
6543 
6544 /*
6545  * Create a new argument list and use it for the current window.
6546  */
6547     void
6548 alist_new(void)
6549 {
6550     curwin->w_alist = (alist_T *)alloc((unsigned)sizeof(alist_T));
6551     if (curwin->w_alist == NULL)
6552     {
6553 	curwin->w_alist = &global_alist;
6554 	++global_alist.al_refcount;
6555     }
6556     else
6557     {
6558 	curwin->w_alist->al_refcount = 1;
6559 	curwin->w_alist->id = ++max_alist_id;
6560 	alist_init(curwin->w_alist);
6561     }
6562 }
6563 
6564 #if !defined(UNIX) || defined(PROTO)
6565 /*
6566  * Expand the file names in the global argument list.
6567  * If "fnum_list" is not NULL, use "fnum_list[fnum_len]" as a list of buffer
6568  * numbers to be re-used.
6569  */
6570     void
6571 alist_expand(int *fnum_list, int fnum_len)
6572 {
6573     char_u	**old_arg_files;
6574     int		old_arg_count;
6575     char_u	**new_arg_files;
6576     int		new_arg_file_count;
6577     char_u	*save_p_su = p_su;
6578     int		i;
6579 
6580     /* Don't use 'suffixes' here.  This should work like the shell did the
6581      * expansion.  Also, the vimrc file isn't read yet, thus the user
6582      * can't set the options. */
6583     p_su = empty_option;
6584     old_arg_files = (char_u **)alloc((unsigned)(sizeof(char_u *) * GARGCOUNT));
6585     if (old_arg_files != NULL)
6586     {
6587 	for (i = 0; i < GARGCOUNT; ++i)
6588 	    old_arg_files[i] = vim_strsave(GARGLIST[i].ae_fname);
6589 	old_arg_count = GARGCOUNT;
6590 	if (expand_wildcards(old_arg_count, old_arg_files,
6591 		    &new_arg_file_count, &new_arg_files,
6592 		    EW_FILE|EW_NOTFOUND|EW_ADDSLASH|EW_NOERROR) == OK
6593 		&& new_arg_file_count > 0)
6594 	{
6595 	    alist_set(&global_alist, new_arg_file_count, new_arg_files,
6596 						   TRUE, fnum_list, fnum_len);
6597 	    FreeWild(old_arg_count, old_arg_files);
6598 	}
6599     }
6600     p_su = save_p_su;
6601 }
6602 #endif
6603 
6604 /*
6605  * Set the argument list for the current window.
6606  * Takes over the allocated files[] and the allocated fnames in it.
6607  */
6608     void
6609 alist_set(
6610     alist_T	*al,
6611     int		count,
6612     char_u	**files,
6613     int		use_curbuf,
6614     int		*fnum_list,
6615     int		fnum_len)
6616 {
6617     int		i;
6618     static int  recursive = 0;
6619 
6620     if (recursive)
6621     {
6622 	emsg(_(e_au_recursive));
6623 	return;
6624     }
6625     ++recursive;
6626 
6627     alist_clear(al);
6628     if (ga_grow(&al->al_ga, count) == OK)
6629     {
6630 	for (i = 0; i < count; ++i)
6631 	{
6632 	    if (got_int)
6633 	    {
6634 		/* When adding many buffers this can take a long time.  Allow
6635 		 * interrupting here. */
6636 		while (i < count)
6637 		    vim_free(files[i++]);
6638 		break;
6639 	    }
6640 
6641 	    /* May set buffer name of a buffer previously used for the
6642 	     * argument list, so that it's re-used by alist_add. */
6643 	    if (fnum_list != NULL && i < fnum_len)
6644 		buf_set_name(fnum_list[i], files[i]);
6645 
6646 	    alist_add(al, files[i], use_curbuf ? 2 : 1);
6647 	    ui_breakcheck();
6648 	}
6649 	vim_free(files);
6650     }
6651     else
6652 	FreeWild(count, files);
6653     if (al == &global_alist)
6654 	arg_had_last = FALSE;
6655 
6656     --recursive;
6657 }
6658 
6659 /*
6660  * Add file "fname" to argument list "al".
6661  * "fname" must have been allocated and "al" must have been checked for room.
6662  */
6663     void
6664 alist_add(
6665     alist_T	*al,
6666     char_u	*fname,
6667     int		set_fnum)	/* 1: set buffer number; 2: re-use curbuf */
6668 {
6669     if (fname == NULL)		/* don't add NULL file names */
6670 	return;
6671 #ifdef BACKSLASH_IN_FILENAME
6672     slash_adjust(fname);
6673 #endif
6674     AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname;
6675     if (set_fnum > 0)
6676 	AARGLIST(al)[al->al_ga.ga_len].ae_fnum =
6677 	    buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0));
6678     ++al->al_ga.ga_len;
6679 }
6680 
6681 #if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6682 /*
6683  * Adjust slashes in file names.  Called after 'shellslash' was set.
6684  */
6685     void
6686 alist_slash_adjust(void)
6687 {
6688     int		i;
6689     win_T	*wp;
6690     tabpage_T	*tp;
6691 
6692     for (i = 0; i < GARGCOUNT; ++i)
6693 	if (GARGLIST[i].ae_fname != NULL)
6694 	    slash_adjust(GARGLIST[i].ae_fname);
6695     FOR_ALL_TAB_WINDOWS(tp, wp)
6696 	if (wp->w_alist != &global_alist)
6697 	    for (i = 0; i < WARGCOUNT(wp); ++i)
6698 		if (WARGLIST(wp)[i].ae_fname != NULL)
6699 		    slash_adjust(WARGLIST(wp)[i].ae_fname);
6700 }
6701 #endif
6702 
6703 /*
6704  * ":preserve".
6705  */
6706     static void
6707 ex_preserve(exarg_T *eap UNUSED)
6708 {
6709     curbuf->b_flags |= BF_PRESERVED;
6710     ml_preserve(curbuf, TRUE);
6711 }
6712 
6713 /*
6714  * ":recover".
6715  */
6716     static void
6717 ex_recover(exarg_T *eap)
6718 {
6719     /* Set recoverymode right away to avoid the ATTENTION prompt. */
6720     recoverymode = TRUE;
6721     if (!check_changed(curbuf, (p_awa ? CCGD_AW : 0)
6722 			     | CCGD_MULTWIN
6723 			     | (eap->forceit ? CCGD_FORCEIT : 0)
6724 			     | CCGD_EXCMD)
6725 
6726 	    && (*eap->arg == NUL
6727 			     || setfname(curbuf, eap->arg, NULL, TRUE) == OK))
6728 	ml_recover();
6729     recoverymode = FALSE;
6730 }
6731 
6732 /*
6733  * Command modifier used in a wrong way.
6734  */
6735     static void
6736 ex_wrongmodifier(exarg_T *eap)
6737 {
6738     eap->errmsg = e_invcmd;
6739 }
6740 
6741 /*
6742  * :sview [+command] file	split window with new file, read-only
6743  * :split [[+command] file]	split window with current or new file
6744  * :vsplit [[+command] file]	split window vertically with current or new file
6745  * :new [[+command] file]	split window with no or new file
6746  * :vnew [[+command] file]	split vertically window with no or new file
6747  * :sfind [+command] file	split window with file in 'path'
6748  *
6749  * :tabedit			open new Tab page with empty window
6750  * :tabedit [+command] file	open new Tab page and edit "file"
6751  * :tabnew [[+command] file]	just like :tabedit
6752  * :tabfind [+command] file	open new Tab page and find "file"
6753  */
6754     void
6755 ex_splitview(exarg_T *eap)
6756 {
6757     win_T	*old_curwin = curwin;
6758 #if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
6759     char_u	*fname = NULL;
6760 #endif
6761 #ifdef FEAT_BROWSE
6762     int		browse_flag = cmdmod.browse;
6763 #endif
6764     int		use_tab = eap->cmdidx == CMD_tabedit
6765 		       || eap->cmdidx == CMD_tabfind
6766 		       || eap->cmdidx == CMD_tabnew;
6767 
6768 #ifdef FEAT_GUI
6769     need_mouse_correct = TRUE;
6770 #endif
6771 
6772 #ifdef FEAT_QUICKFIX
6773     /* A ":split" in the quickfix window works like ":new".  Don't want two
6774      * quickfix windows.  But it's OK when doing ":tab split". */
6775     if (bt_quickfix(curbuf) && cmdmod.tab == 0)
6776     {
6777 	if (eap->cmdidx == CMD_split)
6778 	    eap->cmdidx = CMD_new;
6779 	if (eap->cmdidx == CMD_vsplit)
6780 	    eap->cmdidx = CMD_vnew;
6781     }
6782 #endif
6783 
6784 #ifdef FEAT_SEARCHPATH
6785     if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind)
6786     {
6787 	fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg),
6788 					  FNAME_MESS, TRUE, curbuf->b_ffname);
6789 	if (fname == NULL)
6790 	    goto theend;
6791 	eap->arg = fname;
6792     }
6793 # ifdef FEAT_BROWSE
6794     else
6795 # endif
6796 #endif
6797 #ifdef FEAT_BROWSE
6798     if (cmdmod.browse
6799 	    && eap->cmdidx != CMD_vnew
6800 	    && eap->cmdidx != CMD_new)
6801     {
6802 	if (
6803 # ifdef FEAT_GUI
6804 	    !gui.in_use &&
6805 # endif
6806 		au_has_group((char_u *)"FileExplorer"))
6807 	{
6808 	    /* No browsing supported but we do have the file explorer:
6809 	     * Edit the directory. */
6810 	    if (*eap->arg == NUL || !mch_isdir(eap->arg))
6811 		eap->arg = (char_u *)".";
6812 	}
6813 	else
6814 	{
6815 	    fname = do_browse(0, (char_u *)(use_tab
6816 			? _("Edit File in new tab page")
6817 			: _("Edit File in new window")),
6818 					  eap->arg, NULL, NULL, NULL, curbuf);
6819 	    if (fname == NULL)
6820 		goto theend;
6821 	    eap->arg = fname;
6822 	}
6823     }
6824     cmdmod.browse = FALSE;	/* Don't browse again in do_ecmd(). */
6825 #endif
6826 
6827     /*
6828      * Either open new tab page or split the window.
6829      */
6830     if (use_tab)
6831     {
6832 	if (win_new_tabpage(cmdmod.tab != 0 ? cmdmod.tab
6833 			 : eap->addr_count == 0 ? 0
6834 					       : (int)eap->line2 + 1) != FAIL)
6835 	{
6836 	    do_exedit(eap, old_curwin);
6837 
6838 	    /* set the alternate buffer for the window we came from */
6839 	    if (curwin != old_curwin
6840 		    && win_valid(old_curwin)
6841 		    && old_curwin->w_buffer != curbuf
6842 		    && !cmdmod.keepalt)
6843 		old_curwin->w_alt_fnum = curbuf->b_fnum;
6844 	}
6845     }
6846     else if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0,
6847 				     *eap->cmd == 'v' ? WSP_VERT : 0) != FAIL)
6848     {
6849 	/* Reset 'scrollbind' when editing another file, but keep it when
6850 	 * doing ":split" without arguments. */
6851 	if (*eap->arg != NUL
6852 # ifdef FEAT_BROWSE
6853 		|| cmdmod.browse
6854 # endif
6855 	   )
6856 	    RESET_BINDING(curwin);
6857 	else
6858 	    do_check_scrollbind(FALSE);
6859 	do_exedit(eap, old_curwin);
6860     }
6861 
6862 # ifdef FEAT_BROWSE
6863     cmdmod.browse = browse_flag;
6864 # endif
6865 
6866 # if defined(FEAT_SEARCHPATH) || defined(FEAT_BROWSE)
6867 theend:
6868     vim_free(fname);
6869 # endif
6870 }
6871 
6872 /*
6873  * Open a new tab page.
6874  */
6875     void
6876 tabpage_new(void)
6877 {
6878     exarg_T	ea;
6879 
6880     vim_memset(&ea, 0, sizeof(ea));
6881     ea.cmdidx = CMD_tabnew;
6882     ea.cmd = (char_u *)"tabn";
6883     ea.arg = (char_u *)"";
6884     ex_splitview(&ea);
6885 }
6886 
6887 /*
6888  * :tabnext command
6889  */
6890     static void
6891 ex_tabnext(exarg_T *eap)
6892 {
6893     int tab_number;
6894 
6895     switch (eap->cmdidx)
6896     {
6897 	case CMD_tabfirst:
6898 	case CMD_tabrewind:
6899 	    goto_tabpage(1);
6900 	    break;
6901 	case CMD_tablast:
6902 	    goto_tabpage(9999);
6903 	    break;
6904 	case CMD_tabprevious:
6905 	case CMD_tabNext:
6906 	    if (eap->arg && *eap->arg != NUL)
6907 	    {
6908 		char_u *p = eap->arg;
6909 		char_u *p_save = p;
6910 
6911 		tab_number = getdigits(&p);
6912 		if (p == p_save || *p_save == '-' || *p != NUL
6913 			    || tab_number == 0)
6914 		{
6915 		    /* No numbers as argument. */
6916 		    eap->errmsg = e_invarg;
6917 		    return;
6918 		}
6919 	    }
6920 	    else
6921 	    {
6922 		if (eap->addr_count == 0)
6923 		    tab_number = 1;
6924 		else
6925 		{
6926 		    tab_number = eap->line2;
6927 		    if (tab_number < 1)
6928 		    {
6929 			eap->errmsg = e_invrange;
6930 			return;
6931 		    }
6932 		}
6933 	    }
6934 	    goto_tabpage(-tab_number);
6935 	    break;
6936 	default: /* CMD_tabnext */
6937 	    tab_number = get_tabpage_arg(eap);
6938 	    if (eap->errmsg == NULL)
6939 		goto_tabpage(tab_number);
6940 	    break;
6941     }
6942 }
6943 
6944 /*
6945  * :tabmove command
6946  */
6947     static void
6948 ex_tabmove(exarg_T *eap)
6949 {
6950     int tab_number;
6951 
6952     tab_number = get_tabpage_arg(eap);
6953     if (eap->errmsg == NULL)
6954 	tabpage_move(tab_number);
6955 }
6956 
6957 /*
6958  * :tabs command: List tabs and their contents.
6959  */
6960     static void
6961 ex_tabs(exarg_T *eap UNUSED)
6962 {
6963     tabpage_T	*tp;
6964     win_T	*wp;
6965     int		tabcount = 1;
6966 
6967     msg_start();
6968     msg_scroll = TRUE;
6969     for (tp = first_tabpage; tp != NULL && !got_int; tp = tp->tp_next)
6970     {
6971 	msg_putchar('\n');
6972 	vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++);
6973 	msg_outtrans_attr(IObuff, HL_ATTR(HLF_T));
6974 	out_flush();	    /* output one line at a time */
6975 	ui_breakcheck();
6976 
6977 	if (tp  == curtab)
6978 	    wp = firstwin;
6979 	else
6980 	    wp = tp->tp_firstwin;
6981 	for ( ; wp != NULL && !got_int; wp = wp->w_next)
6982 	{
6983 	    msg_putchar('\n');
6984 	    msg_putchar(wp == curwin ? '>' : ' ');
6985 	    msg_putchar(' ');
6986 	    msg_putchar(bufIsChanged(wp->w_buffer) ? '+' : ' ');
6987 	    msg_putchar(' ');
6988 	    if (buf_spname(wp->w_buffer) != NULL)
6989 		vim_strncpy(IObuff, buf_spname(wp->w_buffer), IOSIZE - 1);
6990 	    else
6991 		home_replace(wp->w_buffer, wp->w_buffer->b_fname,
6992 							IObuff, IOSIZE, TRUE);
6993 	    msg_outtrans(IObuff);
6994 	    out_flush();	    /* output one line at a time */
6995 	    ui_breakcheck();
6996 	}
6997     }
6998 }
6999 
7000 /*
7001  * ":mode": Set screen mode.
7002  * If no argument given, just get the screen size and redraw.
7003  */
7004     static void
7005 ex_mode(exarg_T *eap)
7006 {
7007     if (*eap->arg == NUL)
7008 	shell_resized();
7009     else
7010 	mch_screenmode(eap->arg);
7011 }
7012 
7013 /*
7014  * ":resize".
7015  * set, increment or decrement current window height
7016  */
7017     static void
7018 ex_resize(exarg_T *eap)
7019 {
7020     int		n;
7021     win_T	*wp = curwin;
7022 
7023     if (eap->addr_count > 0)
7024     {
7025 	n = eap->line2;
7026 	for (wp = firstwin; wp->w_next != NULL && --n > 0; wp = wp->w_next)
7027 	    ;
7028     }
7029 
7030 # ifdef FEAT_GUI
7031     need_mouse_correct = TRUE;
7032 # endif
7033     n = atol((char *)eap->arg);
7034     if (cmdmod.split & WSP_VERT)
7035     {
7036 	if (*eap->arg == '-' || *eap->arg == '+')
7037 	    n += curwin->w_width;
7038 	else if (n == 0 && eap->arg[0] == NUL)	/* default is very wide */
7039 	    n = 9999;
7040 	win_setwidth_win((int)n, wp);
7041     }
7042     else
7043     {
7044 	if (*eap->arg == '-' || *eap->arg == '+')
7045 	    n += curwin->w_height;
7046 	else if (n == 0 && eap->arg[0] == NUL)	/* default is very high */
7047 	    n = 9999;
7048 	win_setheight_win((int)n, wp);
7049     }
7050 }
7051 
7052 /*
7053  * ":find [+command] <file>" command.
7054  */
7055     static void
7056 ex_find(exarg_T *eap)
7057 {
7058 #ifdef FEAT_SEARCHPATH
7059     char_u	*fname;
7060     int		count;
7061 
7062     fname = find_file_in_path(eap->arg, (int)STRLEN(eap->arg), FNAME_MESS,
7063 						      TRUE, curbuf->b_ffname);
7064     if (eap->addr_count > 0)
7065     {
7066 	/* Repeat finding the file "count" times.  This matters when it
7067 	 * appears several times in the path. */
7068 	count = eap->line2;
7069 	while (fname != NULL && --count > 0)
7070 	{
7071 	    vim_free(fname);
7072 	    fname = find_file_in_path(NULL, 0, FNAME_MESS,
7073 						     FALSE, curbuf->b_ffname);
7074 	}
7075     }
7076 
7077     if (fname != NULL)
7078     {
7079 	eap->arg = fname;
7080 #endif
7081 	do_exedit(eap, NULL);
7082 #ifdef FEAT_SEARCHPATH
7083 	vim_free(fname);
7084     }
7085 #endif
7086 }
7087 
7088 /*
7089  * ":open" simulation: for now just work like ":visual".
7090  */
7091     static void
7092 ex_open(exarg_T *eap)
7093 {
7094     regmatch_T	regmatch;
7095     char_u	*p;
7096 
7097     curwin->w_cursor.lnum = eap->line2;
7098     beginline(BL_SOL | BL_FIX);
7099     if (*eap->arg == '/')
7100     {
7101 	/* ":open /pattern/": put cursor in column found with pattern */
7102 	++eap->arg;
7103 	p = skip_regexp(eap->arg, '/', p_magic, NULL);
7104 	*p = NUL;
7105 	regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0);
7106 	if (regmatch.regprog != NULL)
7107 	{
7108 	    regmatch.rm_ic = p_ic;
7109 	    p = ml_get_curline();
7110 	    if (vim_regexec(&regmatch, p, (colnr_T)0))
7111 		curwin->w_cursor.col = (colnr_T)(regmatch.startp[0] - p);
7112 	    else
7113 		emsg(_(e_nomatch));
7114 	    vim_regfree(regmatch.regprog);
7115 	}
7116 	/* Move to the NUL, ignore any other arguments. */
7117 	eap->arg += STRLEN(eap->arg);
7118     }
7119     check_cursor();
7120 
7121     eap->cmdidx = CMD_visual;
7122     do_exedit(eap, NULL);
7123 }
7124 
7125 /*
7126  * ":edit", ":badd", ":visual".
7127  */
7128     static void
7129 ex_edit(exarg_T *eap)
7130 {
7131     do_exedit(eap, NULL);
7132 }
7133 
7134 /*
7135  * ":edit <file>" command and alikes.
7136  */
7137     void
7138 do_exedit(
7139     exarg_T	*eap,
7140     win_T	*old_curwin)	    /* curwin before doing a split or NULL */
7141 {
7142     int		n;
7143     int		need_hide;
7144     int		exmode_was = exmode_active;
7145 
7146     /*
7147      * ":vi" command ends Ex mode.
7148      */
7149     if (exmode_active && (eap->cmdidx == CMD_visual
7150 						|| eap->cmdidx == CMD_view))
7151     {
7152 	exmode_active = FALSE;
7153 	if (*eap->arg == NUL)
7154 	{
7155 	    /* Special case:  ":global/pat/visual\NLvi-commands" */
7156 	    if (global_busy)
7157 	    {
7158 		int	rd = RedrawingDisabled;
7159 		int	nwr = no_wait_return;
7160 		int	ms = msg_scroll;
7161 #ifdef FEAT_GUI
7162 		int	he = hold_gui_events;
7163 #endif
7164 
7165 		if (eap->nextcmd != NULL)
7166 		{
7167 		    stuffReadbuff(eap->nextcmd);
7168 		    eap->nextcmd = NULL;
7169 		}
7170 
7171 		if (exmode_was != EXMODE_VIM)
7172 		    settmode(TMODE_RAW);
7173 		RedrawingDisabled = 0;
7174 		no_wait_return = 0;
7175 		need_wait_return = FALSE;
7176 		msg_scroll = 0;
7177 #ifdef FEAT_GUI
7178 		hold_gui_events = 0;
7179 #endif
7180 		must_redraw = CLEAR;
7181 
7182 		main_loop(FALSE, TRUE);
7183 
7184 		RedrawingDisabled = rd;
7185 		no_wait_return = nwr;
7186 		msg_scroll = ms;
7187 #ifdef FEAT_GUI
7188 		hold_gui_events = he;
7189 #endif
7190 	    }
7191 	    return;
7192 	}
7193     }
7194 
7195     if ((eap->cmdidx == CMD_new
7196 		|| eap->cmdidx == CMD_tabnew
7197 		|| eap->cmdidx == CMD_tabedit
7198 		|| eap->cmdidx == CMD_vnew) && *eap->arg == NUL)
7199     {
7200 	/* ":new" or ":tabnew" without argument: edit an new empty buffer */
7201 	setpcmark();
7202 	(void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
7203 		      ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0),
7204 		      old_curwin == NULL ? curwin : NULL);
7205     }
7206     else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
7207 	    || *eap->arg != NUL
7208 #ifdef FEAT_BROWSE
7209 	    || cmdmod.browse
7210 #endif
7211 	    )
7212     {
7213 	/* Can't edit another file when "curbuf_lock" is set.  Only ":edit"
7214 	 * can bring us here, others are stopped earlier. */
7215 	if (*eap->arg != NUL && curbuf_locked())
7216 	    return;
7217 
7218 	n = readonlymode;
7219 	if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
7220 	    readonlymode = TRUE;
7221 	else if (eap->cmdidx == CMD_enew)
7222 	    readonlymode = FALSE;   /* 'readonly' doesn't make sense in an
7223 				       empty buffer */
7224 	setpcmark();
7225 	if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg),
7226 		    NULL, eap,
7227 		    /* ":edit" goes to first line if Vi compatible */
7228 		    (*eap->arg == NUL && eap->do_ecmd_lnum == 0
7229 				      && vim_strchr(p_cpo, CPO_GOTO1) != NULL)
7230 					       ? ECMD_ONE : eap->do_ecmd_lnum,
7231 		    (buf_hide(curbuf) ? ECMD_HIDE : 0)
7232 		    + (eap->forceit ? ECMD_FORCEIT : 0)
7233 		      /* after a split we can use an existing buffer */
7234 		    + (old_curwin != NULL ? ECMD_OLDBUF : 0)
7235 		    + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 )
7236 		    , old_curwin == NULL ? curwin : NULL) == FAIL)
7237 	{
7238 	    /* Editing the file failed.  If the window was split, close it. */
7239 	    if (old_curwin != NULL)
7240 	    {
7241 		need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1);
7242 		if (!need_hide || buf_hide(curbuf))
7243 		{
7244 #if defined(FEAT_EVAL)
7245 		    cleanup_T   cs;
7246 
7247 		    /* Reset the error/interrupt/exception state here so that
7248 		     * aborting() returns FALSE when closing a window. */
7249 		    enter_cleanup(&cs);
7250 #endif
7251 #ifdef FEAT_GUI
7252 		    need_mouse_correct = TRUE;
7253 #endif
7254 		    win_close(curwin, !need_hide && !buf_hide(curbuf));
7255 
7256 #if defined(FEAT_EVAL)
7257 		    /* Restore the error/interrupt/exception state if not
7258 		     * discarded by a new aborting error, interrupt, or
7259 		     * uncaught exception. */
7260 		    leave_cleanup(&cs);
7261 #endif
7262 		}
7263 	    }
7264 	}
7265 	else if (readonlymode && curbuf->b_nwindows == 1)
7266 	{
7267 	    /* When editing an already visited buffer, 'readonly' won't be set
7268 	     * but the previous value is kept.  With ":view" and ":sview" we
7269 	     * want the  file to be readonly, except when another window is
7270 	     * editing the same buffer. */
7271 	    curbuf->b_p_ro = TRUE;
7272 	}
7273 	readonlymode = n;
7274     }
7275     else
7276     {
7277 	if (eap->do_ecmd_cmd != NULL)
7278 	    do_cmdline_cmd(eap->do_ecmd_cmd);
7279 #ifdef FEAT_TITLE
7280 	n = curwin->w_arg_idx_invalid;
7281 #endif
7282 	check_arg_idx(curwin);
7283 #ifdef FEAT_TITLE
7284 	if (n != curwin->w_arg_idx_invalid)
7285 	    maketitle();
7286 #endif
7287     }
7288 
7289     /*
7290      * if ":split file" worked, set alternate file name in old window to new
7291      * file
7292      */
7293     if (old_curwin != NULL
7294 	    && *eap->arg != NUL
7295 	    && curwin != old_curwin
7296 	    && win_valid(old_curwin)
7297 	    && old_curwin->w_buffer != curbuf
7298 	    && !cmdmod.keepalt)
7299 	old_curwin->w_alt_fnum = curbuf->b_fnum;
7300 
7301     ex_no_reprint = TRUE;
7302 }
7303 
7304 #ifndef FEAT_GUI
7305 /*
7306  * ":gui" and ":gvim" when there is no GUI.
7307  */
7308     static void
7309 ex_nogui(exarg_T *eap)
7310 {
7311     eap->errmsg = e_nogvim;
7312 }
7313 #endif
7314 
7315 #if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
7316     static void
7317 ex_tearoff(exarg_T *eap)
7318 {
7319     gui_make_tearoff(eap->arg);
7320 }
7321 #endif
7322 
7323 #if (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \
7324 	|| defined(FEAT_TERM_POPUP_MENU)) && defined(FEAT_MENU)
7325     static void
7326 ex_popup(exarg_T *eap)
7327 {
7328 # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK)
7329     if (gui.in_use)
7330 	gui_make_popup(eap->arg, eap->forceit);
7331 #  ifdef FEAT_TERM_POPUP_MENU
7332     else
7333 #  endif
7334 # endif
7335 # ifdef FEAT_TERM_POPUP_MENU
7336 	pum_make_popup(eap->arg, eap->forceit);
7337 # endif
7338 }
7339 #endif
7340 
7341     static void
7342 ex_swapname(exarg_T *eap UNUSED)
7343 {
7344     if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
7345 	msg(_("No swap file"));
7346     else
7347 	msg((char *)curbuf->b_ml.ml_mfp->mf_fname);
7348 }
7349 
7350 /*
7351  * ":syncbind" forces all 'scrollbind' windows to have the same relative
7352  * offset.
7353  * (1998-11-02 16:21:01  R. Edward Ralston <[email protected]>)
7354  */
7355     static void
7356 ex_syncbind(exarg_T *eap UNUSED)
7357 {
7358     win_T	*wp;
7359     win_T	*save_curwin = curwin;
7360     buf_T	*save_curbuf = curbuf;
7361     long	topline;
7362     long	y;
7363     linenr_T	old_linenr = curwin->w_cursor.lnum;
7364 
7365     setpcmark();
7366 
7367     /*
7368      * determine max topline
7369      */
7370     if (curwin->w_p_scb)
7371     {
7372 	topline = curwin->w_topline;
7373 	FOR_ALL_WINDOWS(wp)
7374 	{
7375 	    if (wp->w_p_scb && wp->w_buffer)
7376 	    {
7377 		y = wp->w_buffer->b_ml.ml_line_count - get_scrolloff_value();
7378 		if (topline > y)
7379 		    topline = y;
7380 	    }
7381 	}
7382 	if (topline < 1)
7383 	    topline = 1;
7384     }
7385     else
7386     {
7387 	topline = 1;
7388     }
7389 
7390 
7391     /*
7392      * Set all scrollbind windows to the same topline.
7393      */
7394     FOR_ALL_WINDOWS(curwin)
7395     {
7396 	if (curwin->w_p_scb)
7397 	{
7398 	    curbuf = curwin->w_buffer;
7399 	    y = topline - curwin->w_topline;
7400 	    if (y > 0)
7401 		scrollup(y, TRUE);
7402 	    else
7403 		scrolldown(-y, TRUE);
7404 	    curwin->w_scbind_pos = topline;
7405 	    redraw_later(VALID);
7406 	    cursor_correct();
7407 	    curwin->w_redr_status = TRUE;
7408 	}
7409     }
7410     curwin = save_curwin;
7411     curbuf = save_curbuf;
7412     if (curwin->w_p_scb)
7413     {
7414 	did_syncbind = TRUE;
7415 	checkpcmark();
7416 	if (old_linenr != curwin->w_cursor.lnum)
7417 	{
7418 	    char_u ctrl_o[2];
7419 
7420 	    ctrl_o[0] = Ctrl_O;
7421 	    ctrl_o[1] = 0;
7422 	    ins_typebuf(ctrl_o, REMAP_NONE, 0, TRUE, FALSE);
7423 	}
7424     }
7425 }
7426 
7427 
7428     static void
7429 ex_read(exarg_T *eap)
7430 {
7431     int		i;
7432     int		empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
7433     linenr_T	lnum;
7434 
7435     if (eap->usefilter)			/* :r!cmd */
7436 	do_bang(1, eap, FALSE, FALSE, TRUE);
7437     else
7438     {
7439 	if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
7440 	    return;
7441 
7442 #ifdef FEAT_BROWSE
7443 	if (cmdmod.browse)
7444 	{
7445 	    char_u *browseFile;
7446 
7447 	    browseFile = do_browse(0, (char_u *)_("Append File"), eap->arg,
7448 						    NULL, NULL, NULL, curbuf);
7449 	    if (browseFile != NULL)
7450 	    {
7451 		i = readfile(browseFile, NULL,
7452 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
7453 		vim_free(browseFile);
7454 	    }
7455 	    else
7456 		i = OK;
7457 	}
7458 	else
7459 #endif
7460 	     if (*eap->arg == NUL)
7461 	{
7462 	    if (check_fname() == FAIL)	/* check for no file name */
7463 		return;
7464 	    i = readfile(curbuf->b_ffname, curbuf->b_fname,
7465 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
7466 	}
7467 	else
7468 	{
7469 	    if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
7470 		(void)setaltfname(eap->arg, eap->arg, (linenr_T)1);
7471 	    i = readfile(eap->arg, NULL,
7472 			  eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
7473 
7474 	}
7475 	if (i != OK)
7476 	{
7477 #if defined(FEAT_EVAL)
7478 	    if (!aborting())
7479 #endif
7480 		semsg(_(e_notopen), eap->arg);
7481 	}
7482 	else
7483 	{
7484 	    if (empty && exmode_active)
7485 	    {
7486 		/* Delete the empty line that remains.  Historically ex does
7487 		 * this but vi doesn't. */
7488 		if (eap->line2 == 0)
7489 		    lnum = curbuf->b_ml.ml_line_count;
7490 		else
7491 		    lnum = 1;
7492 		if (*ml_get(lnum) == NUL && u_savedel(lnum, 1L) == OK)
7493 		{
7494 		    ml_delete(lnum, FALSE);
7495 		    if (curwin->w_cursor.lnum > 1
7496 					     && curwin->w_cursor.lnum >= lnum)
7497 			--curwin->w_cursor.lnum;
7498 		    deleted_lines_mark(lnum, 1L);
7499 		}
7500 	    }
7501 	    redraw_curbuf_later(VALID);
7502 	}
7503     }
7504 }
7505 
7506 static char_u	*prev_dir = NULL;
7507 
7508 #if defined(EXITFREE) || defined(PROTO)
7509     void
7510 free_cd_dir(void)
7511 {
7512     VIM_CLEAR(prev_dir);
7513     VIM_CLEAR(globaldir);
7514 }
7515 #endif
7516 
7517 /*
7518  * Deal with the side effects of changing the current directory.
7519  * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
7520  * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command.
7521  */
7522     void
7523 post_chdir(cdscope_T scope)
7524 {
7525     if (scope != CDSCOPE_WINDOW)
7526 	// Clear tab local directory for both :cd and :tcd
7527 	VIM_CLEAR(curtab->tp_localdir);
7528     VIM_CLEAR(curwin->w_localdir);
7529     if (scope != CDSCOPE_GLOBAL)
7530     {
7531 	/* If still in global directory, need to remember current
7532 	 * directory as global directory. */
7533 	if (globaldir == NULL && prev_dir != NULL)
7534 	    globaldir = vim_strsave(prev_dir);
7535 	/* Remember this local directory for the window. */
7536 	if (mch_dirname(NameBuff, MAXPATHL) == OK)
7537 	{
7538 	    if (scope == CDSCOPE_TABPAGE)
7539 		curtab->tp_localdir = vim_strsave(NameBuff);
7540 	    else
7541 		curwin->w_localdir = vim_strsave(NameBuff);
7542 	}
7543     }
7544     else
7545     {
7546 	/* We are now in the global directory, no need to remember its
7547 	 * name. */
7548 	VIM_CLEAR(globaldir);
7549     }
7550 
7551     shorten_fnames(TRUE);
7552 }
7553 
7554 /*
7555  * Change directory function used by :cd/:tcd/:lcd Ex commands and the
7556  * chdir() function. If 'winlocaldir' is TRUE, then changes the window-local
7557  * directory. If 'tablocaldir' is TRUE, then changes the tab-local directory.
7558  * Otherwise changes the global directory.
7559  * Returns TRUE if the directory is successfully changed.
7560  */
7561     int
7562 changedir_func(
7563 	char_u		*new_dir,
7564 	int		forceit,
7565 	cdscope_T	scope)
7566 {
7567     char_u	*tofree;
7568     int		dir_differs;
7569     int		retval = FALSE;
7570 
7571     if (allbuf_locked())
7572 	return FALSE;
7573 
7574     if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit)
7575     {
7576 	emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
7577 	return FALSE;
7578     }
7579 
7580     // ":cd -": Change to previous directory
7581     if (STRCMP(new_dir, "-") == 0)
7582     {
7583 	if (prev_dir == NULL)
7584 	{
7585 	    emsg(_("E186: No previous directory"));
7586 	    return FALSE;
7587 	}
7588 	new_dir = prev_dir;
7589     }
7590 
7591     // Save current directory for next ":cd -"
7592     tofree = prev_dir;
7593     if (mch_dirname(NameBuff, MAXPATHL) == OK)
7594 	prev_dir = vim_strsave(NameBuff);
7595     else
7596 	prev_dir = NULL;
7597 
7598 #if defined(UNIX) || defined(VMS)
7599     // for UNIX ":cd" means: go to home directory
7600     if (*new_dir == NUL)
7601     {
7602 	// use NameBuff for home directory name
7603 # ifdef VMS
7604 	char_u	*p;
7605 
7606 	p = mch_getenv((char_u *)"SYS$LOGIN");
7607 	if (p == NULL || *p == NUL)	// empty is the same as not set
7608 	    NameBuff[0] = NUL;
7609 	else
7610 	    vim_strncpy(NameBuff, p, MAXPATHL - 1);
7611 # else
7612 	expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
7613 # endif
7614 	new_dir = NameBuff;
7615     }
7616 #endif
7617     dir_differs = new_dir == NULL || prev_dir == NULL
7618 	|| pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0;
7619     if (new_dir == NULL || (dir_differs && vim_chdir(new_dir)))
7620 	emsg(_(e_failed));
7621     else
7622     {
7623 	char_u  *acmd_fname;
7624 
7625 	post_chdir(scope);
7626 
7627 	if (dir_differs)
7628 	{
7629 	    if (scope == CDSCOPE_WINDOW)
7630 		acmd_fname = (char_u *)"window";
7631 	    else if (scope == CDSCOPE_TABPAGE)
7632 		acmd_fname = (char_u *)"tabpage";
7633 	    else
7634 		acmd_fname = (char_u *)"global";
7635 	    apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE,
7636 								curbuf);
7637 	}
7638 	retval = TRUE;
7639     }
7640     vim_free(tofree);
7641 
7642     return retval;
7643 }
7644 
7645 /*
7646  * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
7647  */
7648     void
7649 ex_cd(exarg_T *eap)
7650 {
7651     char_u	*new_dir;
7652 
7653     new_dir = eap->arg;
7654 #if !defined(UNIX) && !defined(VMS)
7655     // for non-UNIX ":cd" means: print current directory
7656     if (*new_dir == NUL)
7657 	ex_pwd(NULL);
7658     else
7659 #endif
7660     {
7661 	cdscope_T	scope = CDSCOPE_GLOBAL;
7662 
7663 	if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
7664 	    scope = CDSCOPE_WINDOW;
7665 	else if (eap->cmdidx == CMD_tcd || eap->cmdidx == CMD_tchdir)
7666 	    scope = CDSCOPE_TABPAGE;
7667 
7668 	if (changedir_func(new_dir, eap->forceit, scope))
7669 	{
7670 	    // Echo the new current directory if the command was typed.
7671 	    if (KeyTyped || p_verbose >= 5)
7672 		ex_pwd(eap);
7673 	}
7674     }
7675 }
7676 
7677 /*
7678  * ":pwd".
7679  */
7680     static void
7681 ex_pwd(exarg_T *eap UNUSED)
7682 {
7683     if (mch_dirname(NameBuff, MAXPATHL) == OK)
7684     {
7685 #ifdef BACKSLASH_IN_FILENAME
7686 	slash_adjust(NameBuff);
7687 #endif
7688 	msg((char *)NameBuff);
7689     }
7690     else
7691 	emsg(_("E187: Unknown"));
7692 }
7693 
7694 /*
7695  * ":=".
7696  */
7697     static void
7698 ex_equal(exarg_T *eap)
7699 {
7700     smsg("%ld", (long)eap->line2);
7701     ex_may_print(eap);
7702 }
7703 
7704     static void
7705 ex_sleep(exarg_T *eap)
7706 {
7707     int		n;
7708     long	len;
7709 
7710     if (cursor_valid())
7711     {
7712 	n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled;
7713 	if (n >= 0)
7714 	    windgoto((int)n, curwin->w_wincol + curwin->w_wcol);
7715     }
7716 
7717     len = eap->line2;
7718     switch (*eap->arg)
7719     {
7720 	case 'm': break;
7721 	case NUL: len *= 1000L; break;
7722 	default: semsg(_(e_invarg2), eap->arg); return;
7723     }
7724     do_sleep(len);
7725 }
7726 
7727 /*
7728  * Sleep for "msec" milliseconds, but keep checking for a CTRL-C every second.
7729  */
7730     void
7731 do_sleep(long msec)
7732 {
7733     long	done;
7734     long	wait_now;
7735 
7736     cursor_on();
7737     out_flush_cursor(FALSE, FALSE);
7738     for (done = 0; !got_int && done < msec; done += wait_now)
7739     {
7740 	wait_now = msec - done > 1000L ? 1000L : msec - done;
7741 #ifdef FEAT_TIMERS
7742 	{
7743 	    long    due_time = check_due_timer();
7744 
7745 	    if (due_time > 0 && due_time < wait_now)
7746 		wait_now = due_time;
7747 	}
7748 #endif
7749 #ifdef FEAT_JOB_CHANNEL
7750 	if (has_any_channel() && wait_now > 100L)
7751 	    wait_now = 100L;
7752 #endif
7753 	ui_delay(wait_now, TRUE);
7754 #ifdef FEAT_JOB_CHANNEL
7755 	if (has_any_channel())
7756 	    ui_breakcheck_force(TRUE);
7757 	else
7758 #endif
7759 	    ui_breakcheck();
7760 #ifdef MESSAGE_QUEUE
7761 	/* Process the netbeans and clientserver messages that may have been
7762 	 * received in the call to ui_breakcheck() when the GUI is in use. This
7763 	 * may occur when running a test case. */
7764 	parse_queued_messages();
7765 #endif
7766     }
7767 
7768     // If CTRL-C was typed to interrupt the sleep, drop the CTRL-C from the
7769     // input buffer, otherwise a following call to input() fails.
7770     if (got_int)
7771 	(void)vpeekc();
7772 }
7773 
7774     static void
7775 do_exmap(exarg_T *eap, int isabbrev)
7776 {
7777     int	    mode;
7778     char_u  *cmdp;
7779 
7780     cmdp = eap->cmd;
7781     mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
7782 
7783     switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
7784 						    eap->arg, mode, isabbrev))
7785     {
7786 	case 1: emsg(_(e_invarg));
7787 		break;
7788 	case 2: emsg((isabbrev ? _(e_noabbr) : _(e_nomap)));
7789 		break;
7790     }
7791 }
7792 
7793 /*
7794  * ":winsize" command (obsolete).
7795  */
7796     static void
7797 ex_winsize(exarg_T *eap)
7798 {
7799     int		w, h;
7800     char_u	*arg = eap->arg;
7801     char_u	*p;
7802 
7803     w = getdigits(&arg);
7804     arg = skipwhite(arg);
7805     p = arg;
7806     h = getdigits(&arg);
7807     if (*p != NUL && *arg == NUL)
7808 	set_shellsize(w, h, TRUE);
7809     else
7810 	emsg(_("E465: :winsize requires two number arguments"));
7811 }
7812 
7813     static void
7814 ex_wincmd(exarg_T *eap)
7815 {
7816     int		xchar = NUL;
7817     char_u	*p;
7818 
7819     if (*eap->arg == 'g' || *eap->arg == Ctrl_G)
7820     {
7821 	/* CTRL-W g and CTRL-W CTRL-G  have an extra command character */
7822 	if (eap->arg[1] == NUL)
7823 	{
7824 	    emsg(_(e_invarg));
7825 	    return;
7826 	}
7827 	xchar = eap->arg[1];
7828 	p = eap->arg + 2;
7829     }
7830     else
7831 	p = eap->arg + 1;
7832 
7833     eap->nextcmd = check_nextcmd(p);
7834     p = skipwhite(p);
7835     if (*p != NUL && *p != '"' && eap->nextcmd == NULL)
7836 	emsg(_(e_invarg));
7837     else if (!eap->skip)
7838     {
7839 	/* Pass flags on for ":vertical wincmd ]". */
7840 	postponed_split_flags = cmdmod.split;
7841 	postponed_split_tab = cmdmod.tab;
7842 	do_window(*eap->arg, eap->addr_count > 0 ? eap->line2 : 0L, xchar);
7843 	postponed_split_flags = 0;
7844 	postponed_split_tab = 0;
7845     }
7846 }
7847 
7848 #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN)
7849 /*
7850  * ":winpos".
7851  */
7852     static void
7853 ex_winpos(exarg_T *eap)
7854 {
7855     int		x, y;
7856     char_u	*arg = eap->arg;
7857     char_u	*p;
7858 
7859     if (*arg == NUL)
7860     {
7861 # if defined(FEAT_GUI) || defined(MSWIN)
7862 #  ifdef VIMDLL
7863 	if (gui.in_use ? gui_mch_get_winpos(&x, &y) != FAIL :
7864 		mch_get_winpos(&x, &y) != FAIL)
7865 #  elif defined(FEAT_GUI)
7866 	if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL)
7867 #  else
7868 	if (mch_get_winpos(&x, &y) != FAIL)
7869 #  endif
7870 	{
7871 	    sprintf((char *)IObuff, _("Window position: X %d, Y %d"), x, y);
7872 	    msg((char *)IObuff);
7873 	}
7874 	else
7875 # endif
7876 	    emsg(_("E188: Obtaining window position not implemented for this platform"));
7877     }
7878     else
7879     {
7880 	x = getdigits(&arg);
7881 	arg = skipwhite(arg);
7882 	p = arg;
7883 	y = getdigits(&arg);
7884 	if (*p == NUL || *arg != NUL)
7885 	{
7886 	    emsg(_("E466: :winpos requires two number arguments"));
7887 	    return;
7888 	}
7889 # ifdef FEAT_GUI
7890 	if (gui.in_use)
7891 	    gui_mch_set_winpos(x, y);
7892 	else if (gui.starting)
7893 	{
7894 	    /* Remember the coordinates for when the window is opened. */
7895 	    gui_win_x = x;
7896 	    gui_win_y = y;
7897 	}
7898 #  if defined(HAVE_TGETENT) || defined(VIMDLL)
7899 	else
7900 #  endif
7901 # endif
7902 # if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
7903 	    mch_set_winpos(x, y);
7904 # endif
7905 # ifdef HAVE_TGETENT
7906 	if (*T_CWP)
7907 	    term_set_winpos(x, y);
7908 # endif
7909     }
7910 }
7911 #endif
7912 
7913 /*
7914  * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
7915  */
7916     static void
7917 ex_operators(exarg_T *eap)
7918 {
7919     oparg_T	oa;
7920 
7921     clear_oparg(&oa);
7922     oa.regname = eap->regname;
7923     oa.start.lnum = eap->line1;
7924     oa.end.lnum = eap->line2;
7925     oa.line_count = eap->line2 - eap->line1 + 1;
7926     oa.motion_type = MLINE;
7927     virtual_op = FALSE;
7928     if (eap->cmdidx != CMD_yank)	/* position cursor for undo */
7929     {
7930 	setpcmark();
7931 	curwin->w_cursor.lnum = eap->line1;
7932 	beginline(BL_SOL | BL_FIX);
7933     }
7934 
7935     if (VIsual_active)
7936 	end_visual_mode();
7937 
7938     switch (eap->cmdidx)
7939     {
7940 	case CMD_delete:
7941 	    oa.op_type = OP_DELETE;
7942 	    op_delete(&oa);
7943 	    break;
7944 
7945 	case CMD_yank:
7946 	    oa.op_type = OP_YANK;
7947 	    (void)op_yank(&oa, FALSE, TRUE);
7948 	    break;
7949 
7950 	default:    /* CMD_rshift or CMD_lshift */
7951 	    if (
7952 #ifdef FEAT_RIGHTLEFT
7953 		(eap->cmdidx == CMD_rshift) ^ curwin->w_p_rl
7954 #else
7955 		eap->cmdidx == CMD_rshift
7956 #endif
7957 						)
7958 		oa.op_type = OP_RSHIFT;
7959 	    else
7960 		oa.op_type = OP_LSHIFT;
7961 	    op_shift(&oa, FALSE, eap->amount);
7962 	    break;
7963     }
7964     virtual_op = MAYBE;
7965     ex_may_print(eap);
7966 }
7967 
7968 /*
7969  * ":put".
7970  */
7971     static void
7972 ex_put(exarg_T *eap)
7973 {
7974     /* ":0put" works like ":1put!". */
7975     if (eap->line2 == 0)
7976     {
7977 	eap->line2 = 1;
7978 	eap->forceit = TRUE;
7979     }
7980     curwin->w_cursor.lnum = eap->line2;
7981     do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
7982 						       PUT_LINE|PUT_CURSLINE);
7983 }
7984 
7985 /*
7986  * Handle ":copy" and ":move".
7987  */
7988     static void
7989 ex_copymove(exarg_T *eap)
7990 {
7991     long	n;
7992 
7993     n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, FALSE, 1);
7994     if (eap->arg == NULL)	    /* error detected */
7995     {
7996 	eap->nextcmd = NULL;
7997 	return;
7998     }
7999     get_flags(eap);
8000 
8001     /*
8002      * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
8003      */
8004     if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
8005     {
8006 	emsg(_(e_invaddr));
8007 	return;
8008     }
8009 
8010     if (eap->cmdidx == CMD_move)
8011     {
8012 	if (do_move(eap->line1, eap->line2, n) == FAIL)
8013 	    return;
8014     }
8015     else
8016 	ex_copy(eap->line1, eap->line2, n);
8017     u_clearline();
8018     beginline(BL_SOL | BL_FIX);
8019     ex_may_print(eap);
8020 }
8021 
8022 /*
8023  * Print the current line if flags were given to the Ex command.
8024  */
8025     void
8026 ex_may_print(exarg_T *eap)
8027 {
8028     if (eap->flags != 0)
8029     {
8030 	print_line(curwin->w_cursor.lnum, (eap->flags & EXFLAG_NR),
8031 						  (eap->flags & EXFLAG_LIST));
8032 	ex_no_reprint = TRUE;
8033     }
8034 }
8035 
8036 /*
8037  * ":smagic" and ":snomagic".
8038  */
8039     static void
8040 ex_submagic(exarg_T *eap)
8041 {
8042     int		magic_save = p_magic;
8043 
8044     p_magic = (eap->cmdidx == CMD_smagic);
8045     do_sub(eap);
8046     p_magic = magic_save;
8047 }
8048 
8049 /*
8050  * ":join".
8051  */
8052     static void
8053 ex_join(exarg_T *eap)
8054 {
8055     curwin->w_cursor.lnum = eap->line1;
8056     if (eap->line1 == eap->line2)
8057     {
8058 	if (eap->addr_count >= 2)   /* :2,2join does nothing */
8059 	    return;
8060 	if (eap->line2 == curbuf->b_ml.ml_line_count)
8061 	{
8062 	    beep_flush();
8063 	    return;
8064 	}
8065 	++eap->line2;
8066     }
8067     (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit, TRUE, TRUE, TRUE);
8068     beginline(BL_WHITE | BL_FIX);
8069     ex_may_print(eap);
8070 }
8071 
8072 /*
8073  * ":[addr]@r" or ":[addr]*r": execute register
8074  */
8075     static void
8076 ex_at(exarg_T *eap)
8077 {
8078     int		c;
8079     int		prev_len = typebuf.tb_len;
8080 
8081     curwin->w_cursor.lnum = eap->line2;
8082     check_cursor_col();
8083 
8084 #ifdef USE_ON_FLY_SCROLL
8085     dont_scroll = TRUE;		/* disallow scrolling here */
8086 #endif
8087 
8088     /* get the register name.  No name means to use the previous one */
8089     c = *eap->arg;
8090     if (c == NUL || (c == '*' && *eap->cmd == '*'))
8091 	c = '@';
8092     /* Put the register in the typeahead buffer with the "silent" flag. */
8093     if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL, TRUE)
8094 								      == FAIL)
8095     {
8096 	beep_flush();
8097     }
8098     else
8099     {
8100 	int	save_efr = exec_from_reg;
8101 
8102 	exec_from_reg = TRUE;
8103 
8104 	/*
8105 	 * Execute from the typeahead buffer.
8106 	 * Continue until the stuff buffer is empty and all added characters
8107 	 * have been consumed.
8108 	 */
8109 	while (!stuff_empty() || typebuf.tb_len > prev_len)
8110 	    (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
8111 
8112 	exec_from_reg = save_efr;
8113     }
8114 }
8115 
8116 /*
8117  * ":!".
8118  */
8119     static void
8120 ex_bang(exarg_T *eap)
8121 {
8122     do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
8123 }
8124 
8125 /*
8126  * ":undo".
8127  */
8128     static void
8129 ex_undo(exarg_T *eap)
8130 {
8131     if (eap->addr_count == 1)	    /* :undo 123 */
8132 	undo_time(eap->line2, FALSE, FALSE, TRUE);
8133     else
8134 	u_undo(1);
8135 }
8136 
8137 #ifdef FEAT_PERSISTENT_UNDO
8138     static void
8139 ex_wundo(exarg_T *eap)
8140 {
8141     char_u hash[UNDO_HASH_SIZE];
8142 
8143     u_compute_hash(hash);
8144     u_write_undo(eap->arg, eap->forceit, curbuf, hash);
8145 }
8146 
8147     static void
8148 ex_rundo(exarg_T *eap)
8149 {
8150     char_u hash[UNDO_HASH_SIZE];
8151 
8152     u_compute_hash(hash);
8153     u_read_undo(eap->arg, hash, NULL);
8154 }
8155 #endif
8156 
8157 /*
8158  * ":redo".
8159  */
8160     static void
8161 ex_redo(exarg_T *eap UNUSED)
8162 {
8163     u_redo(1);
8164 }
8165 
8166 /*
8167  * ":earlier" and ":later".
8168  */
8169     static void
8170 ex_later(exarg_T *eap)
8171 {
8172     long	count = 0;
8173     int		sec = FALSE;
8174     int		file = FALSE;
8175     char_u	*p = eap->arg;
8176 
8177     if (*p == NUL)
8178 	count = 1;
8179     else if (isdigit(*p))
8180     {
8181 	count = getdigits(&p);
8182 	switch (*p)
8183 	{
8184 	    case 's': ++p; sec = TRUE; break;
8185 	    case 'm': ++p; sec = TRUE; count *= 60; break;
8186 	    case 'h': ++p; sec = TRUE; count *= 60 * 60; break;
8187 	    case 'd': ++p; sec = TRUE; count *= 24 * 60 * 60; break;
8188 	    case 'f': ++p; file = TRUE; break;
8189 	}
8190     }
8191 
8192     if (*p != NUL)
8193 	semsg(_(e_invarg2), eap->arg);
8194     else
8195 	undo_time(eap->cmdidx == CMD_earlier ? -count : count,
8196 							    sec, file, FALSE);
8197 }
8198 
8199 /*
8200  * ":redir": start/stop redirection.
8201  */
8202     static void
8203 ex_redir(exarg_T *eap)
8204 {
8205     char	*mode;
8206     char_u	*fname;
8207     char_u	*arg = eap->arg;
8208 
8209 #ifdef FEAT_EVAL
8210     if (redir_execute)
8211     {
8212 	emsg(_("E930: Cannot use :redir inside execute()"));
8213 	return;
8214     }
8215 #endif
8216 
8217     if (STRICMP(eap->arg, "END") == 0)
8218 	close_redir();
8219     else
8220     {
8221 	if (*arg == '>')
8222 	{
8223 	    ++arg;
8224 	    if (*arg == '>')
8225 	    {
8226 		++arg;
8227 		mode = "a";
8228 	    }
8229 	    else
8230 		mode = "w";
8231 	    arg = skipwhite(arg);
8232 
8233 	    close_redir();
8234 
8235 	    /* Expand environment variables and "~/". */
8236 	    fname = expand_env_save(arg);
8237 	    if (fname == NULL)
8238 		return;
8239 #ifdef FEAT_BROWSE
8240 	    if (cmdmod.browse)
8241 	    {
8242 		char_u	*browseFile;
8243 
8244 		browseFile = do_browse(BROWSE_SAVE,
8245 			(char_u *)_("Save Redirection"),
8246 			fname, NULL, NULL,
8247 			(char_u *)_(BROWSE_FILTER_ALL_FILES), curbuf);
8248 		if (browseFile == NULL)
8249 		    return;		/* operation cancelled */
8250 		vim_free(fname);
8251 		fname = browseFile;
8252 		eap->forceit = TRUE;	/* since dialog already asked */
8253 	    }
8254 #endif
8255 
8256 	    redir_fd = open_exfile(fname, eap->forceit, mode);
8257 	    vim_free(fname);
8258 	}
8259 #ifdef FEAT_EVAL
8260 	else if (*arg == '@')
8261 	{
8262 	    /* redirect to a register a-z (resp. A-Z for appending) */
8263 	    close_redir();
8264 	    ++arg;
8265 	    if (ASCII_ISALPHA(*arg)
8266 # ifdef FEAT_CLIPBOARD
8267 		    || *arg == '*'
8268 		    || *arg == '+'
8269 # endif
8270 		    || *arg == '"')
8271 	    {
8272 		redir_reg = *arg++;
8273 		if (*arg == '>' && arg[1] == '>')  /* append */
8274 		    arg += 2;
8275 		else
8276 		{
8277 		    /* Can use both "@a" and "@a>". */
8278 		    if (*arg == '>')
8279 			arg++;
8280 		    /* Make register empty when not using @A-@Z and the
8281 		     * command is valid. */
8282 		    if (*arg == NUL && !isupper(redir_reg))
8283 			write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
8284 		}
8285 	    }
8286 	    if (*arg != NUL)
8287 	    {
8288 		redir_reg = 0;
8289 		semsg(_(e_invarg2), eap->arg);
8290 	    }
8291 	}
8292 	else if (*arg == '=' && arg[1] == '>')
8293 	{
8294 	    int append;
8295 
8296 	    /* redirect to a variable */
8297 	    close_redir();
8298 	    arg += 2;
8299 
8300 	    if (*arg == '>')
8301 	    {
8302 		++arg;
8303 		append = TRUE;
8304 	    }
8305 	    else
8306 		append = FALSE;
8307 
8308 	    if (var_redir_start(skipwhite(arg), append) == OK)
8309 		redir_vname = 1;
8310 	}
8311 #endif
8312 
8313 	/* TODO: redirect to a buffer */
8314 
8315 	else
8316 	    semsg(_(e_invarg2), eap->arg);
8317     }
8318 
8319     /* Make sure redirection is not off.  Can happen for cmdline completion
8320      * that indirectly invokes a command to catch its output. */
8321     if (redir_fd != NULL
8322 #ifdef FEAT_EVAL
8323 			  || redir_reg || redir_vname
8324 #endif
8325 							)
8326 	redir_off = FALSE;
8327 }
8328 
8329 /*
8330  * ":redraw": force redraw
8331  */
8332     void
8333 ex_redraw(exarg_T *eap)
8334 {
8335     int		r = RedrawingDisabled;
8336     int		p = p_lz;
8337 
8338     RedrawingDisabled = 0;
8339     p_lz = FALSE;
8340     validate_cursor();
8341     update_topline();
8342     update_screen(eap->forceit ? CLEAR : VIsual_active ? INVERTED : 0);
8343 #ifdef FEAT_TITLE
8344     if (need_maketitle)
8345 	maketitle();
8346 #endif
8347 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
8348 # ifdef VIMDLL
8349     if (!gui.in_use)
8350 # endif
8351 	resize_console_buf();
8352 #endif
8353     RedrawingDisabled = r;
8354     p_lz = p;
8355 
8356     /* Reset msg_didout, so that a message that's there is overwritten. */
8357     msg_didout = FALSE;
8358     msg_col = 0;
8359 
8360     /* No need to wait after an intentional redraw. */
8361     need_wait_return = FALSE;
8362 
8363     out_flush();
8364 }
8365 
8366 /*
8367  * ":redrawstatus": force redraw of status line(s)
8368  */
8369     static void
8370 ex_redrawstatus(exarg_T *eap UNUSED)
8371 {
8372     int		r = RedrawingDisabled;
8373     int		p = p_lz;
8374 
8375     RedrawingDisabled = 0;
8376     p_lz = FALSE;
8377     if (eap->forceit)
8378 	status_redraw_all();
8379     else
8380 	status_redraw_curbuf();
8381     update_screen(VIsual_active ? INVERTED : 0);
8382     RedrawingDisabled = r;
8383     p_lz = p;
8384     out_flush();
8385 }
8386 
8387 /*
8388  * ":redrawtabline": force redraw of the tabline
8389  */
8390     static void
8391 ex_redrawtabline(exarg_T *eap UNUSED)
8392 {
8393     int		r = RedrawingDisabled;
8394     int		p = p_lz;
8395 
8396     RedrawingDisabled = 0;
8397     p_lz = FALSE;
8398 
8399     draw_tabline();
8400 
8401     RedrawingDisabled = r;
8402     p_lz = p;
8403     out_flush();
8404 }
8405 
8406     static void
8407 close_redir(void)
8408 {
8409     if (redir_fd != NULL)
8410     {
8411 	fclose(redir_fd);
8412 	redir_fd = NULL;
8413     }
8414 #ifdef FEAT_EVAL
8415     redir_reg = 0;
8416     if (redir_vname)
8417     {
8418 	var_redir_stop();
8419 	redir_vname = 0;
8420     }
8421 #endif
8422 }
8423 
8424 #if defined(FEAT_SESSION) && defined(USE_CRNL)
8425 # define MKSESSION_NL
8426 static int mksession_nl = FALSE;    /* use NL only in put_eol() */
8427 #endif
8428 
8429 /*
8430  * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession".
8431  */
8432     static void
8433 ex_mkrc(
8434     exarg_T	*eap)
8435 {
8436     FILE	*fd;
8437     int		failed = FALSE;
8438     char_u	*fname;
8439 #ifdef FEAT_BROWSE
8440     char_u	*browseFile = NULL;
8441 #endif
8442 #ifdef FEAT_SESSION
8443     int		view_session = FALSE;
8444     int		using_vdir = FALSE;	/* using 'viewdir'? */
8445     char_u	*viewFile = NULL;
8446     unsigned	*flagp;
8447 #endif
8448 
8449     if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
8450     {
8451 #ifdef FEAT_SESSION
8452 	view_session = TRUE;
8453 #else
8454 	ex_ni(eap);
8455 	return;
8456 #endif
8457     }
8458 
8459 #ifdef FEAT_SESSION
8460     /* Use the short file name until ":lcd" is used.  We also don't use the
8461      * short file name when 'acd' is set, that is checked later. */
8462     did_lcd = FALSE;
8463 
8464     /* ":mkview" or ":mkview 9": generate file name with 'viewdir' */
8465     if (eap->cmdidx == CMD_mkview
8466 	    && (*eap->arg == NUL
8467 		|| (vim_isdigit(*eap->arg) && eap->arg[1] == NUL)))
8468     {
8469 	eap->forceit = TRUE;
8470 	fname = get_view_file(*eap->arg);
8471 	if (fname == NULL)
8472 	    return;
8473 	viewFile = fname;
8474 	using_vdir = TRUE;
8475     }
8476     else
8477 #endif
8478 	if (*eap->arg != NUL)
8479 	fname = eap->arg;
8480     else if (eap->cmdidx == CMD_mkvimrc)
8481 	fname = (char_u *)VIMRC_FILE;
8482 #ifdef FEAT_SESSION
8483     else if (eap->cmdidx == CMD_mksession)
8484 	fname = (char_u *)SESSION_FILE;
8485 #endif
8486     else
8487 	fname = (char_u *)EXRC_FILE;
8488 
8489 #ifdef FEAT_BROWSE
8490     if (cmdmod.browse)
8491     {
8492 	browseFile = do_browse(BROWSE_SAVE,
8493 # ifdef FEAT_SESSION
8494 		eap->cmdidx == CMD_mkview ? (char_u *)_("Save View") :
8495 		eap->cmdidx == CMD_mksession ? (char_u *)_("Save Session") :
8496 # endif
8497 		(char_u *)_("Save Setup"),
8498 		fname, (char_u *)"vim", NULL,
8499 		(char_u *)_(BROWSE_FILTER_MACROS), NULL);
8500 	if (browseFile == NULL)
8501 	    goto theend;
8502 	fname = browseFile;
8503 	eap->forceit = TRUE;	/* since dialog already asked */
8504     }
8505 #endif
8506 
8507 #if defined(FEAT_SESSION) && defined(vim_mkdir)
8508     /* When using 'viewdir' may have to create the directory. */
8509     if (using_vdir && !mch_isdir(p_vdir))
8510 	vim_mkdir_emsg(p_vdir, 0755);
8511 #endif
8512 
8513     fd = open_exfile(fname, eap->forceit, WRITEBIN);
8514     if (fd != NULL)
8515     {
8516 #ifdef FEAT_SESSION
8517 	if (eap->cmdidx == CMD_mkview)
8518 	    flagp = &vop_flags;
8519 	else
8520 	    flagp = &ssop_flags;
8521 #endif
8522 
8523 #ifdef MKSESSION_NL
8524 	/* "unix" in 'sessionoptions': use NL line separator */
8525 	if (view_session && (*flagp & SSOP_UNIX))
8526 	    mksession_nl = TRUE;
8527 #endif
8528 
8529 	/* Write the version command for :mkvimrc */
8530 	if (eap->cmdidx == CMD_mkvimrc)
8531 	    (void)put_line(fd, "version 6.0");
8532 
8533 #ifdef FEAT_SESSION
8534 	if (eap->cmdidx == CMD_mksession)
8535 	{
8536 	    if (put_line(fd, "let SessionLoad = 1") == FAIL)
8537 		failed = TRUE;
8538 	}
8539 
8540 	if (eap->cmdidx != CMD_mkview)
8541 #endif
8542 	{
8543 	    /* Write setting 'compatible' first, because it has side effects.
8544 	     * For that same reason only do it when needed. */
8545 	    if (p_cp)
8546 		(void)put_line(fd, "if !&cp | set cp | endif");
8547 	    else
8548 		(void)put_line(fd, "if &cp | set nocp | endif");
8549 	}
8550 
8551 #ifdef FEAT_SESSION
8552 	if (!view_session
8553 		|| (eap->cmdidx == CMD_mksession
8554 		    && (*flagp & SSOP_OPTIONS)))
8555 #endif
8556 	    failed |= (makemap(fd, NULL) == FAIL
8557 				   || makeset(fd, OPT_GLOBAL, FALSE) == FAIL);
8558 
8559 #ifdef FEAT_SESSION
8560 	if (!failed && view_session)
8561 	{
8562 	    if (put_line(fd, "let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0") == FAIL)
8563 		failed = TRUE;
8564 	    if (eap->cmdidx == CMD_mksession)
8565 	    {
8566 		char_u *dirnow;	 /* current directory */
8567 
8568 		dirnow = alloc(MAXPATHL);
8569 		if (dirnow == NULL)
8570 		    failed = TRUE;
8571 		else
8572 		{
8573 		    /*
8574 		     * Change to session file's dir.
8575 		     */
8576 		    if (mch_dirname(dirnow, MAXPATHL) == FAIL
8577 					    || mch_chdir((char *)dirnow) != 0)
8578 			*dirnow = NUL;
8579 		    if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
8580 		    {
8581 			if (vim_chdirfile(fname, NULL) == OK)
8582 			    shorten_fnames(TRUE);
8583 		    }
8584 		    else if (*dirnow != NUL
8585 			   && (ssop_flags & SSOP_CURDIR) && globaldir != NULL)
8586 		    {
8587 			if (mch_chdir((char *)globaldir) == 0)
8588 			    shorten_fnames(TRUE);
8589 		    }
8590 
8591 		    failed |= (makeopens(fd, dirnow) == FAIL);
8592 
8593 		    /* restore original dir */
8594 		    if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR)
8595 			|| ((ssop_flags & SSOP_CURDIR) && globaldir != NULL)))
8596 		    {
8597 			if (mch_chdir((char *)dirnow) != 0)
8598 			    emsg(_(e_prev_dir));
8599 			shorten_fnames(TRUE);
8600 		    }
8601 		    vim_free(dirnow);
8602 		}
8603 	    }
8604 	    else
8605 	    {
8606 		failed |= (put_view(fd, curwin, !using_vdir, flagp,
8607 								 -1) == FAIL);
8608 	    }
8609 	    if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
8610 								      == FAIL)
8611 		failed = TRUE;
8612 # ifdef FEAT_SEARCH_EXTRA
8613 	    if (no_hlsearch && put_line(fd, "nohlsearch") == FAIL)
8614 		failed = TRUE;
8615 # endif
8616 	    if (put_line(fd, "doautoall SessionLoadPost") == FAIL)
8617 		failed = TRUE;
8618 	    if (eap->cmdidx == CMD_mksession)
8619 	    {
8620 		if (put_line(fd, "unlet SessionLoad") == FAIL)
8621 		    failed = TRUE;
8622 	    }
8623 	}
8624 #endif
8625 	if (put_line(fd, "\" vim: set ft=vim :") == FAIL)
8626 	    failed = TRUE;
8627 
8628 	failed |= fclose(fd);
8629 
8630 	if (failed)
8631 	    emsg(_(e_write));
8632 #if defined(FEAT_EVAL) && defined(FEAT_SESSION)
8633 	else if (eap->cmdidx == CMD_mksession)
8634 	{
8635 	    /* successful session write - set this_session var */
8636 	    char_u	*tbuf;
8637 
8638 	    tbuf = alloc(MAXPATHL);
8639 	    if (tbuf != NULL)
8640 	    {
8641 		if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK)
8642 		    set_vim_var_string(VV_THIS_SESSION, tbuf, -1);
8643 		vim_free(tbuf);
8644 	    }
8645 	}
8646 #endif
8647 #ifdef MKSESSION_NL
8648 	mksession_nl = FALSE;
8649 #endif
8650     }
8651 
8652 #ifdef FEAT_BROWSE
8653 theend:
8654     vim_free(browseFile);
8655 #endif
8656 #ifdef FEAT_SESSION
8657     vim_free(viewFile);
8658 #endif
8659 }
8660 
8661 #if ((defined(FEAT_SESSION) || defined(FEAT_EVAL)) && defined(vim_mkdir)) \
8662 	|| defined(PROTO)
8663     int
8664 vim_mkdir_emsg(char_u *name, int prot)
8665 {
8666     if (vim_mkdir(name, prot) != 0)
8667     {
8668 	semsg(_("E739: Cannot create directory: %s"), name);
8669 	return FAIL;
8670     }
8671     return OK;
8672 }
8673 #endif
8674 
8675 /*
8676  * Open a file for writing for an Ex command, with some checks.
8677  * Return file descriptor, or NULL on failure.
8678  */
8679     FILE *
8680 open_exfile(
8681     char_u	*fname,
8682     int		forceit,
8683     char	*mode)	    /* "w" for create new file or "a" for append */
8684 {
8685     FILE	*fd;
8686 
8687 #ifdef UNIX
8688     /* with Unix it is possible to open a directory */
8689     if (mch_isdir(fname))
8690     {
8691 	semsg(_(e_isadir2), fname);
8692 	return NULL;
8693     }
8694 #endif
8695     if (!forceit && *mode != 'a' && vim_fexists(fname))
8696     {
8697 	semsg(_("E189: \"%s\" exists (add ! to override)"), fname);
8698 	return NULL;
8699     }
8700 
8701     if ((fd = mch_fopen((char *)fname, mode)) == NULL)
8702 	semsg(_("E190: Cannot open \"%s\" for writing"), fname);
8703 
8704     return fd;
8705 }
8706 
8707 /*
8708  * ":mark" and ":k".
8709  */
8710     static void
8711 ex_mark(exarg_T *eap)
8712 {
8713     pos_T	pos;
8714 
8715     if (*eap->arg == NUL)		/* No argument? */
8716 	emsg(_(e_argreq));
8717     else if (eap->arg[1] != NUL)	/* more than one character? */
8718 	emsg(_(e_trailing));
8719     else
8720     {
8721 	pos = curwin->w_cursor;		/* save curwin->w_cursor */
8722 	curwin->w_cursor.lnum = eap->line2;
8723 	beginline(BL_WHITE | BL_FIX);
8724 	if (setmark(*eap->arg) == FAIL)	/* set mark */
8725 	    emsg(_("E191: Argument must be a letter or forward/backward quote"));
8726 	curwin->w_cursor = pos;		/* restore curwin->w_cursor */
8727     }
8728 }
8729 
8730 /*
8731  * Update w_topline, w_leftcol and the cursor position.
8732  */
8733     void
8734 update_topline_cursor(void)
8735 {
8736     check_cursor();		/* put cursor on valid line */
8737     update_topline();
8738     if (!curwin->w_p_wrap)
8739 	validate_cursor();
8740     update_curswant();
8741 }
8742 
8743 /*
8744  * Save the current State and go to Normal mode.
8745  * Return TRUE if the typeahead could be saved.
8746  */
8747     int
8748 save_current_state(save_state_T *sst)
8749 {
8750     sst->save_msg_scroll = msg_scroll;
8751     sst->save_restart_edit = restart_edit;
8752     sst->save_msg_didout = msg_didout;
8753     sst->save_State = State;
8754     sst->save_insertmode = p_im;
8755     sst->save_finish_op = finish_op;
8756     sst->save_opcount = opcount;
8757     sst->save_reg_executing = reg_executing;
8758 
8759     msg_scroll = FALSE;	    /* no msg scrolling in Normal mode */
8760     restart_edit = 0;	    /* don't go to Insert mode */
8761     p_im = FALSE;	    /* don't use 'insertmode' */
8762 
8763     /*
8764      * Save the current typeahead.  This is required to allow using ":normal"
8765      * from an event handler and makes sure we don't hang when the argument
8766      * ends with half a command.
8767      */
8768     save_typeahead(&sst->tabuf);
8769     return sst->tabuf.typebuf_valid;
8770 }
8771 
8772     void
8773 restore_current_state(save_state_T *sst)
8774 {
8775     /* Restore the previous typeahead. */
8776     restore_typeahead(&sst->tabuf);
8777 
8778     msg_scroll = sst->save_msg_scroll;
8779     restart_edit = sst->save_restart_edit;
8780     p_im = sst->save_insertmode;
8781     finish_op = sst->save_finish_op;
8782     opcount = sst->save_opcount;
8783     reg_executing = sst->save_reg_executing;
8784     msg_didout |= sst->save_msg_didout;	/* don't reset msg_didout now */
8785 
8786     /* Restore the state (needed when called from a function executed for
8787      * 'indentexpr'). Update the mouse and cursor, they may have changed. */
8788     State = sst->save_State;
8789 #ifdef CURSOR_SHAPE
8790     ui_cursor_shape();		/* may show different cursor shape */
8791 #endif
8792 }
8793 
8794 /*
8795  * ":normal[!] {commands}": Execute normal mode commands.
8796  */
8797     void
8798 ex_normal(exarg_T *eap)
8799 {
8800     save_state_T save_state;
8801     char_u	*arg = NULL;
8802     int		l;
8803     char_u	*p;
8804 
8805     if (ex_normal_lock > 0)
8806     {
8807 	emsg(_(e_secure));
8808 	return;
8809     }
8810     if (ex_normal_busy >= p_mmd)
8811     {
8812 	emsg(_("E192: Recursive use of :normal too deep"));
8813 	return;
8814     }
8815 
8816     /*
8817      * vgetc() expects a CSI and K_SPECIAL to have been escaped.  Don't do
8818      * this for the K_SPECIAL leading byte, otherwise special keys will not
8819      * work.
8820      */
8821     if (has_mbyte)
8822     {
8823 	int	len = 0;
8824 
8825 	/* Count the number of characters to be escaped. */
8826 	for (p = eap->arg; *p != NUL; ++p)
8827 	{
8828 #ifdef FEAT_GUI
8829 	    if (*p == CSI)  /* leadbyte CSI */
8830 		len += 2;
8831 #endif
8832 	    for (l = (*mb_ptr2len)(p) - 1; l > 0; --l)
8833 		if (*++p == K_SPECIAL	  /* trailbyte K_SPECIAL or CSI */
8834 #ifdef FEAT_GUI
8835 			|| *p == CSI
8836 #endif
8837 			)
8838 		    len += 2;
8839 	}
8840 	if (len > 0)
8841 	{
8842 	    arg = alloc((unsigned)(STRLEN(eap->arg) + len + 1));
8843 	    if (arg != NULL)
8844 	    {
8845 		len = 0;
8846 		for (p = eap->arg; *p != NUL; ++p)
8847 		{
8848 		    arg[len++] = *p;
8849 #ifdef FEAT_GUI
8850 		    if (*p == CSI)
8851 		    {
8852 			arg[len++] = KS_EXTRA;
8853 			arg[len++] = (int)KE_CSI;
8854 		    }
8855 #endif
8856 		    for (l = (*mb_ptr2len)(p) - 1; l > 0; --l)
8857 		    {
8858 			arg[len++] = *++p;
8859 			if (*p == K_SPECIAL)
8860 			{
8861 			    arg[len++] = KS_SPECIAL;
8862 			    arg[len++] = KE_FILLER;
8863 			}
8864 #ifdef FEAT_GUI
8865 			else if (*p == CSI)
8866 			{
8867 			    arg[len++] = KS_EXTRA;
8868 			    arg[len++] = (int)KE_CSI;
8869 			}
8870 #endif
8871 		    }
8872 		    arg[len] = NUL;
8873 		}
8874 	    }
8875 	}
8876     }
8877 
8878     ++ex_normal_busy;
8879     if (save_current_state(&save_state))
8880     {
8881 	/*
8882 	 * Repeat the :normal command for each line in the range.  When no
8883 	 * range given, execute it just once, without positioning the cursor
8884 	 * first.
8885 	 */
8886 	do
8887 	{
8888 	    if (eap->addr_count != 0)
8889 	    {
8890 		curwin->w_cursor.lnum = eap->line1++;
8891 		curwin->w_cursor.col = 0;
8892 		check_cursor_moved(curwin);
8893 	    }
8894 
8895 	    exec_normal_cmd(arg != NULL
8896 		     ? arg
8897 		     : eap->arg, eap->forceit ? REMAP_NONE : REMAP_YES, FALSE);
8898 	}
8899 	while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
8900     }
8901 
8902     /* Might not return to the main loop when in an event handler. */
8903     update_topline_cursor();
8904 
8905     restore_current_state(&save_state);
8906     --ex_normal_busy;
8907 #ifdef FEAT_MOUSE
8908     setmouse();
8909 #endif
8910 #ifdef CURSOR_SHAPE
8911     ui_cursor_shape();		/* may show different cursor shape */
8912 #endif
8913 
8914     vim_free(arg);
8915 }
8916 
8917 /*
8918  * ":startinsert", ":startreplace" and ":startgreplace"
8919  */
8920     static void
8921 ex_startinsert(exarg_T *eap)
8922 {
8923     if (eap->forceit)
8924     {
8925 	/* cursor line can be zero on startup */
8926 	if (!curwin->w_cursor.lnum)
8927 	    curwin->w_cursor.lnum = 1;
8928 	coladvance((colnr_T)MAXCOL);
8929 	curwin->w_curswant = MAXCOL;
8930 	curwin->w_set_curswant = FALSE;
8931     }
8932 
8933     /* Ignore the command when already in Insert mode.  Inserting an
8934      * expression register that invokes a function can do this. */
8935     if (State & INSERT)
8936 	return;
8937 
8938     if (eap->cmdidx == CMD_startinsert)
8939 	restart_edit = 'a';
8940     else if (eap->cmdidx == CMD_startreplace)
8941 	restart_edit = 'R';
8942     else
8943 	restart_edit = 'V';
8944 
8945     if (!eap->forceit)
8946     {
8947 	if (eap->cmdidx == CMD_startinsert)
8948 	    restart_edit = 'i';
8949 	curwin->w_curswant = 0;	    /* avoid MAXCOL */
8950     }
8951 }
8952 
8953 /*
8954  * ":stopinsert"
8955  */
8956     static void
8957 ex_stopinsert(exarg_T *eap UNUSED)
8958 {
8959     restart_edit = 0;
8960     stop_insert_mode = TRUE;
8961     clearmode();
8962 }
8963 
8964 /*
8965  * Execute normal mode command "cmd".
8966  * "remap" can be REMAP_NONE or REMAP_YES.
8967  */
8968     void
8969 exec_normal_cmd(char_u *cmd, int remap, int silent)
8970 {
8971     /* Stuff the argument into the typeahead buffer. */
8972     ins_typebuf(cmd, remap, 0, TRUE, silent);
8973     exec_normal(FALSE, FALSE, FALSE);
8974 }
8975 
8976 /*
8977  * Execute normal_cmd() until there is no typeahead left.
8978  * When "use_vpeekc" is TRUE use vpeekc() to check for available chars.
8979  */
8980     void
8981 exec_normal(int was_typed, int use_vpeekc, int may_use_terminal_loop UNUSED)
8982 {
8983     oparg_T	oa;
8984     int		c;
8985 
8986     // When calling vpeekc() from feedkeys() it will return Ctrl_C when there
8987     // is nothing to get, so also check for Ctrl_C.
8988     clear_oparg(&oa);
8989     finish_op = FALSE;
8990     while ((!stuff_empty()
8991 		|| ((was_typed || !typebuf_typed()) && typebuf.tb_len > 0)
8992 		|| (use_vpeekc && (c = vpeekc()) != NUL && c != Ctrl_C))
8993 	    && !got_int)
8994     {
8995 	update_topline_cursor();
8996 #ifdef FEAT_TERMINAL
8997 	if (may_use_terminal_loop && term_use_loop()
8998 		&& oa.op_type == OP_NOP && oa.regname == NUL
8999 		&& !VIsual_active)
9000 	{
9001 	    /* If terminal_loop() returns OK we got a key that is handled
9002 	     * in Normal model.  With FAIL we first need to position the
9003 	     * cursor and the screen needs to be redrawn. */
9004 	    if (terminal_loop(TRUE) == OK)
9005 		normal_cmd(&oa, TRUE);
9006 	}
9007 	else
9008 #endif
9009 	    /* execute a Normal mode cmd */
9010 	    normal_cmd(&oa, TRUE);
9011     }
9012 }
9013 
9014 #ifdef FEAT_FIND_ID
9015     static void
9016 ex_checkpath(exarg_T *eap)
9017 {
9018     find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
9019 				   eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
9020 					      (linenr_T)1, (linenr_T)MAXLNUM);
9021 }
9022 
9023 #if defined(FEAT_QUICKFIX)
9024 /*
9025  * ":psearch"
9026  */
9027     static void
9028 ex_psearch(exarg_T *eap)
9029 {
9030     g_do_tagpreview = p_pvh;
9031     ex_findpat(eap);
9032     g_do_tagpreview = 0;
9033 }
9034 #endif
9035 
9036     static void
9037 ex_findpat(exarg_T *eap)
9038 {
9039     int		whole = TRUE;
9040     long	n;
9041     char_u	*p;
9042     int		action;
9043 
9044     switch (cmdnames[eap->cmdidx].cmd_name[2])
9045     {
9046 	case 'e':	/* ":psearch", ":isearch" and ":dsearch" */
9047 		if (cmdnames[eap->cmdidx].cmd_name[0] == 'p')
9048 		    action = ACTION_GOTO;
9049 		else
9050 		    action = ACTION_SHOW;
9051 		break;
9052 	case 'i':	/* ":ilist" and ":dlist" */
9053 		action = ACTION_SHOW_ALL;
9054 		break;
9055 	case 'u':	/* ":ijump" and ":djump" */
9056 		action = ACTION_GOTO;
9057 		break;
9058 	default:	/* ":isplit" and ":dsplit" */
9059 		action = ACTION_SPLIT;
9060 		break;
9061     }
9062 
9063     n = 1;
9064     if (vim_isdigit(*eap->arg))	/* get count */
9065     {
9066 	n = getdigits(&eap->arg);
9067 	eap->arg = skipwhite(eap->arg);
9068     }
9069     if (*eap->arg == '/')   /* Match regexp, not just whole words */
9070     {
9071 	whole = FALSE;
9072 	++eap->arg;
9073 	p = skip_regexp(eap->arg, '/', p_magic, NULL);
9074 	if (*p)
9075 	{
9076 	    *p++ = NUL;
9077 	    p = skipwhite(p);
9078 
9079 	    /* Check for trailing illegal characters */
9080 	    if (!ends_excmd(*p))
9081 		eap->errmsg = e_trailing;
9082 	    else
9083 		eap->nextcmd = check_nextcmd(p);
9084 	}
9085     }
9086     if (!eap->skip)
9087 	find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
9088 			    whole, !eap->forceit,
9089 			    *eap->cmd == 'd' ?	FIND_DEFINE : FIND_ANY,
9090 			    n, action, eap->line1, eap->line2);
9091 }
9092 #endif
9093 
9094 
9095 #ifdef FEAT_QUICKFIX
9096 /*
9097  * ":ptag", ":ptselect", ":ptjump", ":ptnext", etc.
9098  */
9099     static void
9100 ex_ptag(exarg_T *eap)
9101 {
9102     g_do_tagpreview = p_pvh;  /* will be reset to 0 in ex_tag_cmd() */
9103     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
9104 }
9105 
9106 /*
9107  * ":pedit"
9108  */
9109     static void
9110 ex_pedit(exarg_T *eap)
9111 {
9112     win_T	*curwin_save = curwin;
9113 
9114     g_do_tagpreview = p_pvh;
9115     prepare_tagpreview(TRUE);
9116     keep_help_flag = bt_help(curwin_save->w_buffer);
9117     do_exedit(eap, NULL);
9118     keep_help_flag = FALSE;
9119     if (curwin != curwin_save && win_valid(curwin_save))
9120     {
9121 	/* Return cursor to where we were */
9122 	validate_cursor();
9123 	redraw_later(VALID);
9124 	win_enter(curwin_save, TRUE);
9125     }
9126     g_do_tagpreview = 0;
9127 }
9128 #endif
9129 
9130 /*
9131  * ":stag", ":stselect" and ":stjump".
9132  */
9133     static void
9134 ex_stag(exarg_T *eap)
9135 {
9136     postponed_split = -1;
9137     postponed_split_flags = cmdmod.split;
9138     postponed_split_tab = cmdmod.tab;
9139     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1);
9140     postponed_split_flags = 0;
9141     postponed_split_tab = 0;
9142 }
9143 
9144 /*
9145  * ":tag", ":tselect", ":tjump", ":tnext", etc.
9146  */
9147     static void
9148 ex_tag(exarg_T *eap)
9149 {
9150     ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name);
9151 }
9152 
9153     static void
9154 ex_tag_cmd(exarg_T *eap, char_u *name)
9155 {
9156     int		cmd;
9157 
9158     switch (name[1])
9159     {
9160 	case 'j': cmd = DT_JUMP;	/* ":tjump" */
9161 		  break;
9162 	case 's': cmd = DT_SELECT;	/* ":tselect" */
9163 		  break;
9164 	case 'p': cmd = DT_PREV;	/* ":tprevious" */
9165 		  break;
9166 	case 'N': cmd = DT_PREV;	/* ":tNext" */
9167 		  break;
9168 	case 'n': cmd = DT_NEXT;	/* ":tnext" */
9169 		  break;
9170 	case 'o': cmd = DT_POP;		/* ":pop" */
9171 		  break;
9172 	case 'f':			/* ":tfirst" */
9173 	case 'r': cmd = DT_FIRST;	/* ":trewind" */
9174 		  break;
9175 	case 'l': cmd = DT_LAST;	/* ":tlast" */
9176 		  break;
9177 	default:			/* ":tag" */
9178 #ifdef FEAT_CSCOPE
9179 		  if (p_cst && *eap->arg != NUL)
9180 		  {
9181 		      ex_cstag(eap);
9182 		      return;
9183 		  }
9184 #endif
9185 		  cmd = DT_TAG;
9186 		  break;
9187     }
9188 
9189     if (name[0] == 'l')
9190     {
9191 #ifndef FEAT_QUICKFIX
9192 	ex_ni(eap);
9193 	return;
9194 #else
9195 	cmd = DT_LTAG;
9196 #endif
9197     }
9198 
9199     do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
9200 							  eap->forceit, TRUE);
9201 }
9202 
9203 /*
9204  * Check "str" for starting with a special cmdline variable.
9205  * If found return one of the SPEC_ values and set "*usedlen" to the length of
9206  * the variable.  Otherwise return -1 and "*usedlen" is unchanged.
9207  */
9208     int
9209 find_cmdline_var(char_u *src, int *usedlen)
9210 {
9211     int		len;
9212     int		i;
9213     static char *(spec_str[]) = {
9214 		    "%",
9215 #define SPEC_PERC   0
9216 		    "#",
9217 #define SPEC_HASH   (SPEC_PERC + 1)
9218 		    "<cword>",		/* cursor word */
9219 #define SPEC_CWORD  (SPEC_HASH + 1)
9220 		    "<cWORD>",		/* cursor WORD */
9221 #define SPEC_CCWORD (SPEC_CWORD + 1)
9222 		    "<cexpr>",		/* expr under cursor */
9223 #define SPEC_CEXPR  (SPEC_CCWORD + 1)
9224 		    "<cfile>",		/* cursor path name */
9225 #define SPEC_CFILE  (SPEC_CEXPR + 1)
9226 		    "<sfile>",		/* ":so" file name */
9227 #define SPEC_SFILE  (SPEC_CFILE + 1)
9228 		    "<slnum>",		/* ":so" file line number */
9229 #define SPEC_SLNUM  (SPEC_SFILE + 1)
9230 		    "<afile>",		/* autocommand file name */
9231 #define SPEC_AFILE  (SPEC_SLNUM + 1)
9232 		    "<abuf>",		/* autocommand buffer number */
9233 #define SPEC_ABUF   (SPEC_AFILE + 1)
9234 		    "<amatch>",		/* autocommand match name */
9235 #define SPEC_AMATCH (SPEC_ABUF + 1)
9236 		    "<sflnum>",		/* script file line number */
9237 #define SPEC_SFLNUM  (SPEC_AMATCH + 1)
9238 #ifdef FEAT_CLIENTSERVER
9239 		    "<client>"
9240 # define SPEC_CLIENT (SPEC_SFLNUM + 1)
9241 #endif
9242     };
9243 
9244     for (i = 0; i < (int)(sizeof(spec_str) / sizeof(char *)); ++i)
9245     {
9246 	len = (int)STRLEN(spec_str[i]);
9247 	if (STRNCMP(src, spec_str[i], len) == 0)
9248 	{
9249 	    *usedlen = len;
9250 	    return i;
9251 	}
9252     }
9253     return -1;
9254 }
9255 
9256 /*
9257  * Evaluate cmdline variables.
9258  *
9259  * change '%'	    to curbuf->b_ffname
9260  *	  '#'	    to curwin->w_altfile
9261  *	  '<cword>' to word under the cursor
9262  *	  '<cWORD>' to WORD under the cursor
9263  *	  '<cfile>' to path name under the cursor
9264  *	  '<sfile>' to sourced file name
9265  *	  '<slnum>' to sourced file line number
9266  *	  '<afile>' to file name for autocommand
9267  *	  '<abuf>'  to buffer number for autocommand
9268  *	  '<amatch>' to matching name for autocommand
9269  *
9270  * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
9271  * "" for error without a message) and NULL is returned.
9272  * Returns an allocated string if a valid match was found.
9273  * Returns NULL if no match was found.	"usedlen" then still contains the
9274  * number of characters to skip.
9275  */
9276     char_u *
9277 eval_vars(
9278     char_u	*src,		/* pointer into commandline */
9279     char_u	*srcstart,	/* beginning of valid memory for src */
9280     int		*usedlen,	/* characters after src that are used */
9281     linenr_T	*lnump,		/* line number for :e command, or NULL */
9282     char	**errormsg,	/* pointer to error message */
9283     int		*escaped)	/* return value has escaped white space (can
9284 				 * be NULL) */
9285 {
9286     int		i;
9287     char_u	*s;
9288     char_u	*result;
9289     char_u	*resultbuf = NULL;
9290     int		resultlen;
9291     buf_T	*buf;
9292     int		valid = VALID_HEAD + VALID_PATH;    /* assume valid result */
9293     int		spec_idx;
9294 #ifdef FEAT_MODIFY_FNAME
9295     int		tilde_file = FALSE;
9296     int		skip_mod = FALSE;
9297 #endif
9298     char_u	strbuf[30];
9299 
9300     *errormsg = NULL;
9301     if (escaped != NULL)
9302 	*escaped = FALSE;
9303 
9304     /*
9305      * Check if there is something to do.
9306      */
9307     spec_idx = find_cmdline_var(src, usedlen);
9308     if (spec_idx < 0)	/* no match */
9309     {
9310 	*usedlen = 1;
9311 	return NULL;
9312     }
9313 
9314     /*
9315      * Skip when preceded with a backslash "\%" and "\#".
9316      * Note: In "\\%" the % is also not recognized!
9317      */
9318     if (src > srcstart && src[-1] == '\\')
9319     {
9320 	*usedlen = 0;
9321 	STRMOVE(src - 1, src);	/* remove backslash */
9322 	return NULL;
9323     }
9324 
9325     /*
9326      * word or WORD under cursor
9327      */
9328     if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD
9329 						     || spec_idx == SPEC_CEXPR)
9330     {
9331 	resultlen = find_ident_under_cursor(&result,
9332 		spec_idx == SPEC_CWORD ? (FIND_IDENT | FIND_STRING)
9333 	      : spec_idx == SPEC_CEXPR ? (FIND_IDENT | FIND_STRING | FIND_EVAL)
9334 	      : FIND_STRING);
9335 	if (resultlen == 0)
9336 	{
9337 	    *errormsg = "";
9338 	    return NULL;
9339 	}
9340     }
9341 
9342     /*
9343      * '#': Alternate file name
9344      * '%': Current file name
9345      *	    File name under the cursor
9346      *	    File name for autocommand
9347      *	and following modifiers
9348      */
9349     else
9350     {
9351 	switch (spec_idx)
9352 	{
9353 	case SPEC_PERC:		/* '%': current file */
9354 		if (curbuf->b_fname == NULL)
9355 		{
9356 		    result = (char_u *)"";
9357 		    valid = 0;	    /* Must have ":p:h" to be valid */
9358 		}
9359 		else
9360 		{
9361 		    result = curbuf->b_fname;
9362 #ifdef FEAT_MODIFY_FNAME
9363 		    tilde_file = STRCMP(result, "~") == 0;
9364 #endif
9365 		}
9366 		break;
9367 
9368 	case SPEC_HASH:		/* '#' or "#99": alternate file */
9369 		if (src[1] == '#')  /* "##": the argument list */
9370 		{
9371 		    result = arg_all();
9372 		    resultbuf = result;
9373 		    *usedlen = 2;
9374 		    if (escaped != NULL)
9375 			*escaped = TRUE;
9376 #ifdef FEAT_MODIFY_FNAME
9377 		    skip_mod = TRUE;
9378 #endif
9379 		    break;
9380 		}
9381 		s = src + 1;
9382 		if (*s == '<')		/* "#<99" uses v:oldfiles */
9383 		    ++s;
9384 		i = (int)getdigits(&s);
9385 		if (s == src + 2 && src[1] == '-')
9386 		    /* just a minus sign, don't skip over it */
9387 		    s--;
9388 		*usedlen = (int)(s - src); /* length of what we expand */
9389 
9390 		if (src[1] == '<' && i != 0)
9391 		{
9392 		    if (*usedlen < 2)
9393 		    {
9394 			/* Should we give an error message for #<text? */
9395 			*usedlen = 1;
9396 			return NULL;
9397 		    }
9398 #ifdef FEAT_EVAL
9399 		    result = list_find_str(get_vim_var_list(VV_OLDFILES),
9400 								     (long)i);
9401 		    if (result == NULL)
9402 		    {
9403 			*errormsg = "";
9404 			return NULL;
9405 		    }
9406 #else
9407 		    *errormsg = _("E809: #< is not available without the +eval feature");
9408 		    return NULL;
9409 #endif
9410 		}
9411 		else
9412 		{
9413 		    if (i == 0 && src[1] == '<' && *usedlen > 1)
9414 			*usedlen = 1;
9415 		    buf = buflist_findnr(i);
9416 		    if (buf == NULL)
9417 		    {
9418 			*errormsg = _("E194: No alternate file name to substitute for '#'");
9419 			return NULL;
9420 		    }
9421 		    if (lnump != NULL)
9422 			*lnump = ECMD_LAST;
9423 		    if (buf->b_fname == NULL)
9424 		    {
9425 			result = (char_u *)"";
9426 			valid = 0;	    /* Must have ":p:h" to be valid */
9427 		    }
9428 		    else
9429 		    {
9430 			result = buf->b_fname;
9431 #ifdef FEAT_MODIFY_FNAME
9432 			tilde_file = STRCMP(result, "~") == 0;
9433 #endif
9434 		    }
9435 		}
9436 		break;
9437 
9438 #ifdef FEAT_SEARCHPATH
9439 	case SPEC_CFILE:	/* file name under cursor */
9440 		result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
9441 		if (result == NULL)
9442 		{
9443 		    *errormsg = "";
9444 		    return NULL;
9445 		}
9446 		resultbuf = result;	    /* remember allocated string */
9447 		break;
9448 #endif
9449 
9450 	case SPEC_AFILE:	/* file name for autocommand */
9451 		result = autocmd_fname;
9452 		if (result != NULL && !autocmd_fname_full)
9453 		{
9454 		    /* Still need to turn the fname into a full path.  It is
9455 		     * postponed to avoid a delay when <afile> is not used. */
9456 		    autocmd_fname_full = TRUE;
9457 		    result = FullName_save(autocmd_fname, FALSE);
9458 		    vim_free(autocmd_fname);
9459 		    autocmd_fname = result;
9460 		}
9461 		if (result == NULL)
9462 		{
9463 		    *errormsg = _("E495: no autocommand file name to substitute for \"<afile>\"");
9464 		    return NULL;
9465 		}
9466 		result = shorten_fname1(result);
9467 		break;
9468 
9469 	case SPEC_ABUF:		/* buffer number for autocommand */
9470 		if (autocmd_bufnr <= 0)
9471 		{
9472 		    *errormsg = _("E496: no autocommand buffer number to substitute for \"<abuf>\"");
9473 		    return NULL;
9474 		}
9475 		sprintf((char *)strbuf, "%d", autocmd_bufnr);
9476 		result = strbuf;
9477 		break;
9478 
9479 	case SPEC_AMATCH:	/* match name for autocommand */
9480 		result = autocmd_match;
9481 		if (result == NULL)
9482 		{
9483 		    *errormsg = _("E497: no autocommand match name to substitute for \"<amatch>\"");
9484 		    return NULL;
9485 		}
9486 		break;
9487 
9488 	case SPEC_SFILE:	/* file name for ":so" command */
9489 		result = sourcing_name;
9490 		if (result == NULL)
9491 		{
9492 		    *errormsg = _("E498: no :source file name to substitute for \"<sfile>\"");
9493 		    return NULL;
9494 		}
9495 		break;
9496 
9497 	case SPEC_SLNUM:	/* line in file for ":so" command */
9498 		if (sourcing_name == NULL || sourcing_lnum == 0)
9499 		{
9500 		    *errormsg = _("E842: no line number to use for \"<slnum>\"");
9501 		    return NULL;
9502 		}
9503 		sprintf((char *)strbuf, "%ld", (long)sourcing_lnum);
9504 		result = strbuf;
9505 		break;
9506 
9507 #ifdef FEAT_EVAL
9508 	case SPEC_SFLNUM:	/* line in script file */
9509 		if (current_sctx.sc_lnum + sourcing_lnum == 0)
9510 		{
9511 		    *errormsg = _("E961: no line number to use for \"<sflnum>\"");
9512 		    return NULL;
9513 		}
9514 		sprintf((char *)strbuf, "%ld",
9515 				 (long)(current_sctx.sc_lnum + sourcing_lnum));
9516 		result = strbuf;
9517 		break;
9518 #endif
9519 
9520 #ifdef FEAT_CLIENTSERVER
9521 	case SPEC_CLIENT:	/* Source of last submitted input */
9522 		sprintf((char *)strbuf, PRINTF_HEX_LONG_U,
9523 							(long_u)clientWindow);
9524 		result = strbuf;
9525 		break;
9526 #endif
9527 
9528 	default:
9529 		result = (char_u *)""; /* avoid gcc warning */
9530 		break;
9531 	}
9532 
9533 	resultlen = (int)STRLEN(result);	/* length of new string */
9534 	if (src[*usedlen] == '<')	/* remove the file name extension */
9535 	{
9536 	    ++*usedlen;
9537 	    if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
9538 		resultlen = (int)(s - result);
9539 	}
9540 #ifdef FEAT_MODIFY_FNAME
9541 	else if (!skip_mod)
9542 	{
9543 	    valid |= modify_fname(src, tilde_file, usedlen, &result, &resultbuf,
9544 								  &resultlen);
9545 	    if (result == NULL)
9546 	    {
9547 		*errormsg = "";
9548 		return NULL;
9549 	    }
9550 	}
9551 #endif
9552     }
9553 
9554     if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
9555     {
9556 	if (valid != VALID_HEAD + VALID_PATH)
9557 	    /* xgettext:no-c-format */
9558 	    *errormsg = _("E499: Empty file name for '%' or '#', only works with \":p:h\"");
9559 	else
9560 	    *errormsg = _("E500: Evaluates to an empty string");
9561 	result = NULL;
9562     }
9563     else
9564 	result = vim_strnsave(result, resultlen);
9565     vim_free(resultbuf);
9566     return result;
9567 }
9568 
9569 /*
9570  * Concatenate all files in the argument list, separated by spaces, and return
9571  * it in one allocated string.
9572  * Spaces and backslashes in the file names are escaped with a backslash.
9573  * Returns NULL when out of memory.
9574  */
9575     static char_u *
9576 arg_all(void)
9577 {
9578     int		len;
9579     int		idx;
9580     char_u	*retval = NULL;
9581     char_u	*p;
9582 
9583     /*
9584      * Do this loop two times:
9585      * first time: compute the total length
9586      * second time: concatenate the names
9587      */
9588     for (;;)
9589     {
9590 	len = 0;
9591 	for (idx = 0; idx < ARGCOUNT; ++idx)
9592 	{
9593 	    p = alist_name(&ARGLIST[idx]);
9594 	    if (p != NULL)
9595 	    {
9596 		if (len > 0)
9597 		{
9598 		    /* insert a space in between names */
9599 		    if (retval != NULL)
9600 			retval[len] = ' ';
9601 		    ++len;
9602 		}
9603 		for ( ; *p != NUL; ++p)
9604 		{
9605 		    if (*p == ' '
9606 #ifndef BACKSLASH_IN_FILENAME
9607 			    || *p == '\\'
9608 #endif
9609 			    || *p == '`')
9610 		    {
9611 			/* insert a backslash */
9612 			if (retval != NULL)
9613 			    retval[len] = '\\';
9614 			++len;
9615 		    }
9616 		    if (retval != NULL)
9617 			retval[len] = *p;
9618 		    ++len;
9619 		}
9620 	    }
9621 	}
9622 
9623 	/* second time: break here */
9624 	if (retval != NULL)
9625 	{
9626 	    retval[len] = NUL;
9627 	    break;
9628 	}
9629 
9630 	/* allocate memory */
9631 	retval = alloc((unsigned)len + 1);
9632 	if (retval == NULL)
9633 	    break;
9634     }
9635 
9636     return retval;
9637 }
9638 
9639 /*
9640  * Expand the <sfile> string in "arg".
9641  *
9642  * Returns an allocated string, or NULL for any error.
9643  */
9644     char_u *
9645 expand_sfile(char_u *arg)
9646 {
9647     char	*errormsg;
9648     int		len;
9649     char_u	*result;
9650     char_u	*newres;
9651     char_u	*repl;
9652     int		srclen;
9653     char_u	*p;
9654 
9655     result = vim_strsave(arg);
9656     if (result == NULL)
9657 	return NULL;
9658 
9659     for (p = result; *p; )
9660     {
9661 	if (STRNCMP(p, "<sfile>", 7) != 0)
9662 	    ++p;
9663 	else
9664 	{
9665 	    /* replace "<sfile>" with the sourced file name, and do ":" stuff */
9666 	    repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL);
9667 	    if (errormsg != NULL)
9668 	    {
9669 		if (*errormsg)
9670 		    emsg(errormsg);
9671 		vim_free(result);
9672 		return NULL;
9673 	    }
9674 	    if (repl == NULL)		/* no match (cannot happen) */
9675 	    {
9676 		p += srclen;
9677 		continue;
9678 	    }
9679 	    len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1;
9680 	    newres = alloc(len);
9681 	    if (newres == NULL)
9682 	    {
9683 		vim_free(repl);
9684 		vim_free(result);
9685 		return NULL;
9686 	    }
9687 	    mch_memmove(newres, result, (size_t)(p - result));
9688 	    STRCPY(newres + (p - result), repl);
9689 	    len = (int)STRLEN(newres);
9690 	    STRCAT(newres, p + srclen);
9691 	    vim_free(repl);
9692 	    vim_free(result);
9693 	    result = newres;
9694 	    p = newres + len;		/* continue after the match */
9695 	}
9696     }
9697 
9698     return result;
9699 }
9700 
9701 #ifdef FEAT_SESSION
9702 static int ses_winsizes(FILE *fd, int restore_size,
9703 							win_T *tab_firstwin);
9704 static int ses_win_rec(FILE *fd, frame_T *fr);
9705 static frame_T *ses_skipframe(frame_T *fr);
9706 static int ses_do_frame(frame_T *fr);
9707 static int ses_do_win(win_T *wp);
9708 static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp);
9709 static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp);
9710 static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, int add_eol);
9711 
9712 /*
9713  * Write openfile commands for the current buffers to an .exrc file.
9714  * Return FAIL on error, OK otherwise.
9715  */
9716     static int
9717 makeopens(
9718     FILE	*fd,
9719     char_u	*dirnow)	/* Current directory name */
9720 {
9721     buf_T	*buf;
9722     int		only_save_windows = TRUE;
9723     int		nr;
9724     int		restore_size = TRUE;
9725     win_T	*wp;
9726     char_u	*sname;
9727     win_T	*edited_win = NULL;
9728     int		tabnr;
9729     int		restore_stal = FALSE;
9730     win_T	*tab_firstwin;
9731     frame_T	*tab_topframe;
9732     int		cur_arg_idx = 0;
9733     int		next_arg_idx = 0;
9734 
9735     if (ssop_flags & SSOP_BUFFERS)
9736 	only_save_windows = FALSE;		/* Save ALL buffers */
9737 
9738     /*
9739      * Begin by setting the this_session variable, and then other
9740      * sessionable variables.
9741      */
9742 #ifdef FEAT_EVAL
9743     if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL)
9744 	return FAIL;
9745     if (ssop_flags & SSOP_GLOBALS)
9746 	if (store_session_globals(fd) == FAIL)
9747 	    return FAIL;
9748 #endif
9749 
9750     /*
9751      * Close all windows and tabs but one.
9752      */
9753     if (put_line(fd, "silent only") == FAIL)
9754 	return FAIL;
9755     if ((ssop_flags & SSOP_TABPAGES)
9756 	    && put_line(fd, "silent tabonly") == FAIL)
9757 	return FAIL;
9758 
9759     /*
9760      * Now a :cd command to the session directory or the current directory
9761      */
9762     if (ssop_flags & SSOP_SESDIR)
9763     {
9764 	if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')")
9765 								      == FAIL)
9766 	    return FAIL;
9767     }
9768     else if (ssop_flags & SSOP_CURDIR)
9769     {
9770 	sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
9771 	if (sname == NULL
9772 		|| fputs("cd ", fd) < 0
9773 		|| ses_put_fname(fd, sname, &ssop_flags) == FAIL
9774 		|| put_eol(fd) == FAIL)
9775 	{
9776 	    vim_free(sname);
9777 	    return FAIL;
9778 	}
9779 	vim_free(sname);
9780     }
9781 
9782     /*
9783      * If there is an empty, unnamed buffer we will wipe it out later.
9784      * Remember the buffer number.
9785      */
9786     if (put_line(fd, "if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''") == FAIL)
9787 	return FAIL;
9788     if (put_line(fd, "  let s:wipebuf = bufnr('%')") == FAIL)
9789 	return FAIL;
9790     if (put_line(fd, "endif") == FAIL)
9791 	return FAIL;
9792 
9793     /*
9794      * Now save the current files, current buffer first.
9795      */
9796     if (put_line(fd, "set shortmess=aoO") == FAIL)
9797 	return FAIL;
9798 
9799     /* the global argument list */
9800     if (ses_arglist(fd, "argglobal", &global_alist.al_ga,
9801 			    !(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL)
9802 	return FAIL;
9803 
9804     if (ssop_flags & SSOP_RESIZE)
9805     {
9806 	/* Note: after the restore we still check it worked!*/
9807 	if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0
9808 		|| put_eol(fd) == FAIL)
9809 	    return FAIL;
9810     }
9811 
9812 #ifdef FEAT_GUI
9813     if (gui.in_use && (ssop_flags & SSOP_WINPOS))
9814     {
9815 	int	x, y;
9816 
9817 	if (gui_mch_get_winpos(&x, &y) == OK)
9818 	{
9819 	    /* Note: after the restore we still check it worked!*/
9820 	    if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL)
9821 		return FAIL;
9822 	}
9823     }
9824 #endif
9825 
9826     /*
9827      * When there are two or more tabpages and 'showtabline' is 1 the tabline
9828      * will be displayed when creating the next tab.  That resizes the windows
9829      * in the first tab, which may cause problems.  Set 'showtabline' to 2
9830      * temporarily to avoid that.
9831      */
9832     if (p_stal == 1 && first_tabpage->tp_next != NULL)
9833     {
9834 	if (put_line(fd, "set stal=2") == FAIL)
9835 	    return FAIL;
9836 	restore_stal = TRUE;
9837     }
9838 
9839     /*
9840      * May repeat putting Windows for each tab, when "tabpages" is in
9841      * 'sessionoptions'.
9842      * Don't use goto_tabpage(), it may change directory and trigger
9843      * autocommands.
9844      */
9845     tab_firstwin = firstwin;	/* first window in tab page "tabnr" */
9846     tab_topframe = topframe;
9847     if ((ssop_flags & SSOP_TABPAGES))
9848     {
9849 	tabpage_T *tp;
9850 
9851 	// Similar to ses_win_rec() below, populate the tab pages first so
9852 	// later local options won't be copied to the new tabs.
9853 	FOR_ALL_TABPAGES(tp)
9854 	    if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL)
9855 		return FAIL;
9856 	if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL)
9857 	    return FAIL;
9858     }
9859     for (tabnr = 1; ; ++tabnr)
9860     {
9861 	tabpage_T *tp = NULL;
9862 	int	need_tabnext = FALSE;
9863 	int	cnr = 1;
9864 
9865 	if ((ssop_flags & SSOP_TABPAGES))
9866 	{
9867 	    tp = find_tabpage(tabnr);
9868 
9869 	    if (tp == NULL)
9870 		break;		/* done all tab pages */
9871 	    if (tp == curtab)
9872 	    {
9873 		tab_firstwin = firstwin;
9874 		tab_topframe = topframe;
9875 	    }
9876 	    else
9877 	    {
9878 		tab_firstwin = tp->tp_firstwin;
9879 		tab_topframe = tp->tp_topframe;
9880 	    }
9881 	    if (tabnr > 1)
9882 		need_tabnext = TRUE;
9883 	}
9884 
9885 	/*
9886 	 * Before creating the window layout, try loading one file.  If this
9887 	 * is aborted we don't end up with a number of useless windows.
9888 	 * This may have side effects! (e.g., compressed or network file).
9889 	 */
9890 	for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
9891 	{
9892 	    if (ses_do_win(wp)
9893 		    && wp->w_buffer->b_ffname != NULL
9894 		    && !bt_help(wp->w_buffer)
9895 #ifdef FEAT_QUICKFIX
9896 		    && !bt_nofile(wp->w_buffer)
9897 #endif
9898 		    )
9899 	    {
9900 		if (need_tabnext && put_line(fd, "tabnext") == FAIL)
9901 		    return FAIL;
9902 		need_tabnext = FALSE;
9903 
9904 		if (fputs("edit ", fd) < 0
9905 			      || ses_fname(fd, wp->w_buffer, &ssop_flags, TRUE)
9906 								       == FAIL)
9907 		    return FAIL;
9908 		if (!wp->w_arg_idx_invalid)
9909 		    edited_win = wp;
9910 		break;
9911 	    }
9912 	}
9913 
9914 	/* If no file got edited create an empty tab page. */
9915 	if (need_tabnext && put_line(fd, "tabnext") == FAIL)
9916 	    return FAIL;
9917 
9918 	/*
9919 	 * Save current window layout.
9920 	 */
9921 	if (put_line(fd, "set splitbelow splitright") == FAIL)
9922 	    return FAIL;
9923 	if (ses_win_rec(fd, tab_topframe) == FAIL)
9924 	    return FAIL;
9925 	if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL)
9926 	    return FAIL;
9927 	if (!p_spr && put_line(fd, "set nosplitright") == FAIL)
9928 	    return FAIL;
9929 
9930 	/*
9931 	 * Check if window sizes can be restored (no windows omitted).
9932 	 * Remember the window number of the current window after restoring.
9933 	 */
9934 	nr = 0;
9935 	for (wp = tab_firstwin; wp != NULL; wp = W_NEXT(wp))
9936 	{
9937 	    if (ses_do_win(wp))
9938 		++nr;
9939 	    else
9940 		restore_size = FALSE;
9941 	    if (curwin == wp)
9942 		cnr = nr;
9943 	}
9944 
9945 	/* Go to the first window. */
9946 	if (put_line(fd, "wincmd t") == FAIL)
9947 	    return FAIL;
9948 
9949 	/*
9950 	 * If more than one window, see if sizes can be restored.
9951 	 * First set 'winheight' and 'winwidth' to 1 to avoid the windows being
9952 	 * resized when moving between windows.
9953 	 * Do this before restoring the view, so that the topline and the
9954 	 * cursor can be set.  This is done again below.
9955 	 * winminheight and winminwidth need to be set to avoid an error if the
9956 	 * user has set winheight or winwidth.
9957 	 */
9958 	if (put_line(fd, "set winminheight=0") == FAIL
9959 		|| put_line(fd, "set winheight=1") == FAIL
9960 		|| put_line(fd, "set winminwidth=0") == FAIL
9961 		|| put_line(fd, "set winwidth=1") == FAIL)
9962 	    return FAIL;
9963 	if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
9964 	    return FAIL;
9965 
9966 	// Restore the tab-local working directory if specified
9967 	// Do this before the windows, so that the window-local directory can
9968 	// override the tab-local directory.
9969 	if (tp != NULL && tp->tp_localdir != NULL && ssop_flags & SSOP_CURDIR)
9970 	{
9971 	    if (fputs("tcd ", fd) < 0
9972 		    || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
9973 		    || put_eol(fd) == FAIL)
9974 		return FAIL;
9975 	    did_lcd = TRUE;
9976 	}
9977 
9978 	/*
9979 	 * Restore the view of the window (options, file, cursor, etc.).
9980 	 */
9981 	for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
9982 	{
9983 	    if (!ses_do_win(wp))
9984 		continue;
9985 	    if (put_view(fd, wp, wp != edited_win, &ssop_flags,
9986 							 cur_arg_idx) == FAIL)
9987 		return FAIL;
9988 	    if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
9989 		return FAIL;
9990 	    next_arg_idx = wp->w_arg_idx;
9991 	}
9992 
9993 	/* The argument index in the first tab page is zero, need to set it in
9994 	 * each window.  For further tab pages it's the window where we do
9995 	 * "tabedit". */
9996 	cur_arg_idx = next_arg_idx;
9997 
9998 	/*
9999 	 * Restore cursor to the current window if it's not the first one.
10000 	 */
10001 	if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0
10002 						      || put_eol(fd) == FAIL))
10003 	    return FAIL;
10004 
10005 	/*
10006 	 * Restore window sizes again after jumping around in windows, because
10007 	 * the current window has a minimum size while others may not.
10008 	 */
10009 	if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
10010 	    return FAIL;
10011 
10012 	/* Don't continue in another tab page when doing only the current one
10013 	 * or when at the last tab page. */
10014 	if (!(ssop_flags & SSOP_TABPAGES))
10015 	    break;
10016     }
10017 
10018     if (ssop_flags & SSOP_TABPAGES)
10019     {
10020 	if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0
10021 		|| put_eol(fd) == FAIL)
10022 	    return FAIL;
10023     }
10024     if (restore_stal && put_line(fd, "set stal=1") == FAIL)
10025 	return FAIL;
10026 
10027     // Now put the remaining buffers into the buffer list.
10028     // This is near the end, so that when 'hidden' is set we don't create extra
10029     // buffers.  If the buffer was already created with another command the
10030     // ":badd" will have no effect.
10031     FOR_ALL_BUFFERS(buf)
10032     {
10033 	if (!(only_save_windows && buf->b_nwindows == 0)
10034 		&& !(buf->b_help && !(ssop_flags & SSOP_HELP))
10035 #ifdef FEAT_TERMINAL
10036 		// Skip terminal buffers: finished ones are not useful, others
10037 		// will be resurrected and result in a new buffer.
10038 		&& !bt_terminal(buf)
10039 #endif
10040 		&& buf->b_fname != NULL
10041 		&& buf->b_p_bl)
10042 	{
10043 	    if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L
10044 					   : buf->b_wininfo->wi_fpos.lnum) < 0
10045 		    || ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL)
10046 		return FAIL;
10047 	}
10048     }
10049 
10050     /*
10051      * Wipe out an empty unnamed buffer we started in.
10052      */
10053     if (put_line(fd, "if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0")
10054 								       == FAIL)
10055 	return FAIL;
10056     if (put_line(fd, "  silent exe 'bwipe ' . s:wipebuf") == FAIL)
10057 	return FAIL;
10058     if (put_line(fd, "endif") == FAIL)
10059 	return FAIL;
10060     if (put_line(fd, "unlet! s:wipebuf") == FAIL)
10061 	return FAIL;
10062 
10063     /* Re-apply 'winheight', 'winwidth' and 'shortmess'. */
10064     if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s",
10065 			       p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL)
10066 	return FAIL;
10067     /* Re-apply 'winminheight' and 'winminwidth'. */
10068     if (fprintf(fd, "set winminheight=%ld winminwidth=%ld",
10069 				      p_wmh, p_wmw) < 0 || put_eol(fd) == FAIL)
10070 	return FAIL;
10071 
10072     /*
10073      * Lastly, execute the x.vim file if it exists.
10074      */
10075     if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL
10076 	    || put_line(fd, "if file_readable(s:sx)") == FAIL
10077 	    || put_line(fd, "  exe \"source \" . fnameescape(s:sx)") == FAIL
10078 	    || put_line(fd, "endif") == FAIL)
10079 	return FAIL;
10080 
10081     return OK;
10082 }
10083 
10084     static int
10085 ses_winsizes(
10086     FILE	*fd,
10087     int		restore_size,
10088     win_T	*tab_firstwin)
10089 {
10090     int		n = 0;
10091     win_T	*wp;
10092 
10093     if (restore_size && (ssop_flags & SSOP_WINSIZE))
10094     {
10095 	for (wp = tab_firstwin; wp != NULL; wp = wp->w_next)
10096 	{
10097 	    if (!ses_do_win(wp))
10098 		continue;
10099 	    ++n;
10100 
10101 	    /* restore height when not full height */
10102 	    if (wp->w_height + wp->w_status_height < topframe->fr_height
10103 		    && (fprintf(fd,
10104 			  "exe '%dresize ' . ((&lines * %ld + %ld) / %ld)",
10105 			    n, (long)wp->w_height, Rows / 2, Rows) < 0
10106 						  || put_eol(fd) == FAIL))
10107 		return FAIL;
10108 
10109 	    /* restore width when not full width */
10110 	    if (wp->w_width < Columns && (fprintf(fd,
10111 		   "exe 'vert %dresize ' . ((&columns * %ld + %ld) / %ld)",
10112 			    n, (long)wp->w_width, Columns / 2, Columns) < 0
10113 						  || put_eol(fd) == FAIL))
10114 		return FAIL;
10115 	}
10116     }
10117     else
10118     {
10119 	/* Just equalise window sizes */
10120 	if (put_line(fd, "wincmd =") == FAIL)
10121 	    return FAIL;
10122     }
10123     return OK;
10124 }
10125 
10126 /*
10127  * Write commands to "fd" to recursively create windows for frame "fr",
10128  * horizontally and vertically split.
10129  * After the commands the last window in the frame is the current window.
10130  * Returns FAIL when writing the commands to "fd" fails.
10131  */
10132     static int
10133 ses_win_rec(FILE *fd, frame_T *fr)
10134 {
10135     frame_T	*frc;
10136     int		count = 0;
10137 
10138     if (fr->fr_layout != FR_LEAF)
10139     {
10140 	/* Find first frame that's not skipped and then create a window for
10141 	 * each following one (first frame is already there). */
10142 	frc = ses_skipframe(fr->fr_child);
10143 	if (frc != NULL)
10144 	    while ((frc = ses_skipframe(frc->fr_next)) != NULL)
10145 	    {
10146 		/* Make window as big as possible so that we have lots of room
10147 		 * to split. */
10148 		if (put_line(fd, "wincmd _ | wincmd |") == FAIL
10149 			|| put_line(fd, fr->fr_layout == FR_COL
10150 						? "split" : "vsplit") == FAIL)
10151 		    return FAIL;
10152 		++count;
10153 	    }
10154 
10155 	/* Go back to the first window. */
10156 	if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
10157 			? "%dwincmd k" : "%dwincmd h", count) < 0
10158 						      || put_eol(fd) == FAIL))
10159 	    return FAIL;
10160 
10161 	/* Recursively create frames/windows in each window of this column or
10162 	 * row. */
10163 	frc = ses_skipframe(fr->fr_child);
10164 	while (frc != NULL)
10165 	{
10166 	    ses_win_rec(fd, frc);
10167 	    frc = ses_skipframe(frc->fr_next);
10168 	    /* Go to next window. */
10169 	    if (frc != NULL && put_line(fd, "wincmd w") == FAIL)
10170 		return FAIL;
10171 	}
10172     }
10173     return OK;
10174 }
10175 
10176 /*
10177  * Skip frames that don't contain windows we want to save in the Session.
10178  * Returns NULL when there none.
10179  */
10180     static frame_T *
10181 ses_skipframe(frame_T *fr)
10182 {
10183     frame_T	*frc;
10184 
10185     FOR_ALL_FRAMES(frc, fr)
10186 	if (ses_do_frame(frc))
10187 	    break;
10188     return frc;
10189 }
10190 
10191 /*
10192  * Return TRUE if frame "fr" has a window somewhere that we want to save in
10193  * the Session.
10194  */
10195     static int
10196 ses_do_frame(frame_T *fr)
10197 {
10198     frame_T	*frc;
10199 
10200     if (fr->fr_layout == FR_LEAF)
10201 	return ses_do_win(fr->fr_win);
10202     FOR_ALL_FRAMES(frc, fr->fr_child)
10203 	if (ses_do_frame(frc))
10204 	    return TRUE;
10205     return FALSE;
10206 }
10207 
10208 /*
10209  * Return non-zero if window "wp" is to be stored in the Session.
10210  */
10211     static int
10212 ses_do_win(win_T *wp)
10213 {
10214 #ifdef FEAT_TERMINAL
10215     if (bt_terminal(wp->w_buffer))
10216 	return !term_is_finished(wp->w_buffer)
10217 	    && (ssop_flags & SSOP_TERMINAL)
10218 	    && term_should_restore(wp->w_buffer);
10219 #endif
10220     if (wp->w_buffer->b_fname == NULL
10221 #ifdef FEAT_QUICKFIX
10222 	    /* When 'buftype' is "nofile" can't restore the window contents. */
10223 	    || bt_nofile(wp->w_buffer)
10224 #endif
10225        )
10226 	return (ssop_flags & SSOP_BLANK);
10227     if (bt_help(wp->w_buffer))
10228 	return (ssop_flags & SSOP_HELP);
10229     return TRUE;
10230 }
10231 
10232     static int
10233 put_view_curpos(FILE *fd, win_T *wp, char *spaces)
10234 {
10235     int r;
10236 
10237     if (wp->w_curswant == MAXCOL)
10238 	r = fprintf(fd, "%snormal! $", spaces);
10239     else
10240 	r = fprintf(fd, "%snormal! 0%d|", spaces, wp->w_virtcol + 1);
10241     return r < 0 || put_eol(fd) == FAIL ? FALSE : OK;
10242 }
10243 
10244 /*
10245  * Write commands to "fd" to restore the view of a window.
10246  * Caller must make sure 'scrolloff' is zero.
10247  */
10248     static int
10249 put_view(
10250     FILE	*fd,
10251     win_T	*wp,
10252     int		add_edit,	/* add ":edit" command to view */
10253     unsigned	*flagp,		/* vop_flags or ssop_flags */
10254     int		current_arg_idx) /* current argument index of the window, use
10255 				  * -1 if unknown */
10256 {
10257     win_T	*save_curwin;
10258     int		f;
10259     int		do_cursor;
10260     int		did_next = FALSE;
10261 
10262     /* Always restore cursor position for ":mksession".  For ":mkview" only
10263      * when 'viewoptions' contains "cursor". */
10264     do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
10265 
10266     /*
10267      * Local argument list.
10268      */
10269     if (wp->w_alist == &global_alist)
10270     {
10271 	if (put_line(fd, "argglobal") == FAIL)
10272 	    return FAIL;
10273     }
10274     else
10275     {
10276 	if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga,
10277 			flagp == &vop_flags
10278 			|| !(*flagp & SSOP_CURDIR)
10279 			|| wp->w_localdir != NULL, flagp) == FAIL)
10280 	    return FAIL;
10281     }
10282 
10283     /* Only when part of a session: restore the argument index.  Some
10284      * arguments may have been deleted, check if the index is valid. */
10285     if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx < WARGCOUNT(wp)
10286 						      && flagp == &ssop_flags)
10287     {
10288 	if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0
10289 		|| put_eol(fd) == FAIL)
10290 	    return FAIL;
10291 	did_next = TRUE;
10292     }
10293 
10294     /* Edit the file.  Skip this when ":next" already did it. */
10295     if (add_edit && (!did_next || wp->w_arg_idx_invalid))
10296     {
10297 # ifdef FEAT_TERMINAL
10298 	if (bt_terminal(wp->w_buffer))
10299 	{
10300 	    if (term_write_session(fd, wp) == FAIL)
10301 		return FAIL;
10302 	}
10303 	else
10304 # endif
10305 	/*
10306 	 * Load the file.
10307 	 */
10308 	if (wp->w_buffer->b_ffname != NULL
10309 # ifdef FEAT_QUICKFIX
10310 		&& !bt_nofile(wp->w_buffer)
10311 # endif
10312 		)
10313 	{
10314 	    /*
10315 	     * Editing a file in this buffer: use ":edit file".
10316 	     * This may have side effects! (e.g., compressed or network file).
10317 	     *
10318 	     * Note, if a buffer for that file already exists, use :badd to
10319 	     * edit that buffer, to not lose folding information (:edit resets
10320 	     * folds in other buffers)
10321 	     */
10322 	    if (fputs("if bufexists(\"", fd) < 0
10323 		    || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
10324 		    || fputs("\") | buffer ", fd) < 0
10325 		    || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
10326 		    || fputs(" | else | edit ", fd) < 0
10327 		    || ses_fname(fd, wp->w_buffer, flagp, FALSE) == FAIL
10328 		    || fputs(" | endif", fd) < 0
10329 		    || put_eol(fd) == FAIL)
10330 		return FAIL;
10331 	}
10332 	else
10333 	{
10334 	    /* No file in this buffer, just make it empty. */
10335 	    if (put_line(fd, "enew") == FAIL)
10336 		return FAIL;
10337 #ifdef FEAT_QUICKFIX
10338 	    if (wp->w_buffer->b_ffname != NULL)
10339 	    {
10340 		/* The buffer does have a name, but it's not a file name. */
10341 		if (fputs("file ", fd) < 0
10342 			|| ses_fname(fd, wp->w_buffer, flagp, TRUE) == FAIL)
10343 		    return FAIL;
10344 	    }
10345 #endif
10346 	    do_cursor = FALSE;
10347 	}
10348     }
10349 
10350     /*
10351      * Local mappings and abbreviations.
10352      */
10353     if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
10354 					 && makemap(fd, wp->w_buffer) == FAIL)
10355 	return FAIL;
10356 
10357     /*
10358      * Local options.  Need to go to the window temporarily.
10359      * Store only local values when using ":mkview" and when ":mksession" is
10360      * used and 'sessionoptions' doesn't include "options".
10361      * Some folding options are always stored when "folds" is included,
10362      * otherwise the folds would not be restored correctly.
10363      */
10364     save_curwin = curwin;
10365     curwin = wp;
10366     curbuf = curwin->w_buffer;
10367     if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
10368 	f = makeset(fd, OPT_LOCAL,
10369 			     flagp == &vop_flags || !(*flagp & SSOP_OPTIONS));
10370 #ifdef FEAT_FOLDING
10371     else if (*flagp & SSOP_FOLDS)
10372 	f = makefoldset(fd);
10373 #endif
10374     else
10375 	f = OK;
10376     curwin = save_curwin;
10377     curbuf = curwin->w_buffer;
10378     if (f == FAIL)
10379 	return FAIL;
10380 
10381 #ifdef FEAT_FOLDING
10382     /*
10383      * Save Folds when 'buftype' is empty and for help files.
10384      */
10385     if ((*flagp & SSOP_FOLDS)
10386 	    && wp->w_buffer->b_ffname != NULL
10387 	    && (bt_normal(wp->w_buffer) || bt_help(wp->w_buffer)))
10388     {
10389 	if (put_folds(fd, wp) == FAIL)
10390 	    return FAIL;
10391     }
10392 #endif
10393 
10394     /*
10395      * Set the cursor after creating folds, since that moves the cursor.
10396      */
10397     if (do_cursor)
10398     {
10399 
10400 	/* Restore the cursor line in the file and relatively in the
10401 	 * window.  Don't use "G", it changes the jumplist. */
10402 	if (fprintf(fd, "let s:l = %ld - ((%ld * winheight(0) + %ld) / %ld)",
10403 		    (long)wp->w_cursor.lnum,
10404 		    (long)(wp->w_cursor.lnum - wp->w_topline),
10405 		    (long)wp->w_height / 2, (long)wp->w_height) < 0
10406 		|| put_eol(fd) == FAIL
10407 		|| put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL
10408 		|| put_line(fd, "exe s:l") == FAIL
10409 		|| put_line(fd, "normal! zt") == FAIL
10410 		|| fprintf(fd, "%ld", (long)wp->w_cursor.lnum) < 0
10411 		|| put_eol(fd) == FAIL)
10412 	    return FAIL;
10413 	/* Restore the cursor column and left offset when not wrapping. */
10414 	if (wp->w_cursor.col == 0)
10415 	{
10416 	    if (put_line(fd, "normal! 0") == FAIL)
10417 		return FAIL;
10418 	}
10419 	else
10420 	{
10421 	    if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0)
10422 	    {
10423 		if (fprintf(fd,
10424 			  "let s:c = %ld - ((%ld * winwidth(0) + %ld) / %ld)",
10425 			    (long)wp->w_virtcol + 1,
10426 			    (long)(wp->w_virtcol - wp->w_leftcol),
10427 			    (long)wp->w_width / 2, (long)wp->w_width) < 0
10428 			|| put_eol(fd) == FAIL
10429 			|| put_line(fd, "if s:c > 0") == FAIL
10430 			|| fprintf(fd,
10431 			    "  exe 'normal! ' . s:c . '|zs' . %ld . '|'",
10432 			    (long)wp->w_virtcol + 1) < 0
10433 			|| put_eol(fd) == FAIL
10434 			|| put_line(fd, "else") == FAIL
10435 			|| put_view_curpos(fd, wp, "  ") == FAIL
10436 			|| put_line(fd, "endif") == FAIL)
10437 		    return FAIL;
10438 	    }
10439 	    else if (put_view_curpos(fd, wp, "") == FAIL)
10440 		return FAIL;
10441 	}
10442     }
10443 
10444     /*
10445      * Local directory, if the current flag is not view options or the "curdir"
10446      * option is included.
10447      */
10448     if (wp->w_localdir != NULL
10449 			    && (flagp != &vop_flags || (*flagp & SSOP_CURDIR)))
10450     {
10451 	if (fputs("lcd ", fd) < 0
10452 		|| ses_put_fname(fd, wp->w_localdir, flagp) == FAIL
10453 		|| put_eol(fd) == FAIL)
10454 	    return FAIL;
10455 	did_lcd = TRUE;
10456     }
10457 
10458     return OK;
10459 }
10460 
10461 /*
10462  * Write an argument list to the session file.
10463  * Returns FAIL if writing fails.
10464  */
10465     static int
10466 ses_arglist(
10467     FILE	*fd,
10468     char	*cmd,
10469     garray_T	*gap,
10470     int		fullname,	/* TRUE: use full path name */
10471     unsigned	*flagp)
10472 {
10473     int		i;
10474     char_u	*buf = NULL;
10475     char_u	*s;
10476 
10477     if (fputs(cmd, fd) < 0 || put_eol(fd) == FAIL)
10478 	return FAIL;
10479     if (put_line(fd, "%argdel") == FAIL)
10480 	return FAIL;
10481     for (i = 0; i < gap->ga_len; ++i)
10482     {
10483 	/* NULL file names are skipped (only happens when out of memory). */
10484 	s = alist_name(&((aentry_T *)gap->ga_data)[i]);
10485 	if (s != NULL)
10486 	{
10487 	    if (fullname)
10488 	    {
10489 		buf = alloc(MAXPATHL);
10490 		if (buf != NULL)
10491 		{
10492 		    (void)vim_FullName(s, buf, MAXPATHL, FALSE);
10493 		    s = buf;
10494 		}
10495 	    }
10496 	    if (fputs("$argadd ", fd) < 0
10497 		    || ses_put_fname(fd, s, flagp) == FAIL
10498 		    || put_eol(fd) == FAIL)
10499 	    {
10500 		vim_free(buf);
10501 		return FAIL;
10502 	    }
10503 	    vim_free(buf);
10504 	}
10505     }
10506     return OK;
10507 }
10508 
10509 /*
10510  * Write a buffer name to the session file.
10511  * Also ends the line, if "add_eol" is TRUE.
10512  * Returns FAIL if writing fails.
10513  */
10514     static int
10515 ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, int add_eol)
10516 {
10517     char_u	*name;
10518 
10519     /* Use the short file name if the current directory is known at the time
10520      * the session file will be sourced.
10521      * Don't do this for ":mkview", we don't know the current directory.
10522      * Don't do this after ":lcd", we don't keep track of what the current
10523      * directory is. */
10524     if (buf->b_sfname != NULL
10525 	    && flagp == &ssop_flags
10526 	    && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR))
10527 #ifdef FEAT_AUTOCHDIR
10528 	    && !p_acd
10529 #endif
10530 	    && !did_lcd)
10531 	name = buf->b_sfname;
10532     else
10533 	name = buf->b_ffname;
10534     if (ses_put_fname(fd, name, flagp) == FAIL
10535 	    || (add_eol && put_eol(fd) == FAIL))
10536 	return FAIL;
10537     return OK;
10538 }
10539 
10540 /*
10541  * Write a file name to the session file.
10542  * Takes care of the "slash" option in 'sessionoptions' and escapes special
10543  * characters.
10544  * Returns FAIL if writing fails or out of memory.
10545  */
10546     static int
10547 ses_put_fname(FILE *fd, char_u *name, unsigned *flagp)
10548 {
10549     char_u	*sname;
10550     char_u	*p;
10551     int		retval = OK;
10552 
10553     sname = home_replace_save(NULL, name);
10554     if (sname == NULL)
10555 	return FAIL;
10556 
10557     if (*flagp & SSOP_SLASH)
10558     {
10559 	/* change all backslashes to forward slashes */
10560 	for (p = sname; *p != NUL; MB_PTR_ADV(p))
10561 	    if (*p == '\\')
10562 		*p = '/';
10563     }
10564 
10565     /* escape special characters */
10566     p = vim_strsave_fnameescape(sname, FALSE);
10567     vim_free(sname);
10568     if (p == NULL)
10569 	return FAIL;
10570 
10571     /* write the result */
10572     if (fputs((char *)p, fd) < 0)
10573 	retval = FAIL;
10574 
10575     vim_free(p);
10576     return retval;
10577 }
10578 
10579 /*
10580  * ":loadview [nr]"
10581  */
10582     static void
10583 ex_loadview(exarg_T *eap)
10584 {
10585     char_u	*fname;
10586 
10587     fname = get_view_file(*eap->arg);
10588     if (fname != NULL)
10589     {
10590 	do_source(fname, FALSE, DOSO_NONE);
10591 	vim_free(fname);
10592     }
10593 }
10594 
10595 /*
10596  * Get the name of the view file for the current buffer.
10597  */
10598     static char_u *
10599 get_view_file(int c)
10600 {
10601     int		len = 0;
10602     char_u	*p, *s;
10603     char_u	*retval;
10604     char_u	*sname;
10605 
10606     if (curbuf->b_ffname == NULL)
10607     {
10608 	emsg(_(e_noname));
10609 	return NULL;
10610     }
10611     sname = home_replace_save(NULL, curbuf->b_ffname);
10612     if (sname == NULL)
10613 	return NULL;
10614 
10615     /*
10616      * We want a file name without separators, because we're not going to make
10617      * a directory.
10618      * "normal" path separator	-> "=+"
10619      * "="			-> "=="
10620      * ":" path separator	-> "=-"
10621      */
10622     for (p = sname; *p; ++p)
10623 	if (*p == '=' || vim_ispathsep(*p))
10624 	    ++len;
10625     retval = alloc((unsigned)(STRLEN(sname) + len + STRLEN(p_vdir) + 9));
10626     if (retval != NULL)
10627     {
10628 	STRCPY(retval, p_vdir);
10629 	add_pathsep(retval);
10630 	s = retval + STRLEN(retval);
10631 	for (p = sname; *p; ++p)
10632 	{
10633 	    if (*p == '=')
10634 	    {
10635 		*s++ = '=';
10636 		*s++ = '=';
10637 	    }
10638 	    else if (vim_ispathsep(*p))
10639 	    {
10640 		*s++ = '=';
10641 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(VMS)
10642 		if (*p == ':')
10643 		    *s++ = '-';
10644 		else
10645 #endif
10646 		    *s++ = '+';
10647 	    }
10648 	    else
10649 		*s++ = *p;
10650 	}
10651 	*s++ = '=';
10652 	*s++ = c;
10653 	STRCPY(s, ".vim");
10654     }
10655 
10656     vim_free(sname);
10657     return retval;
10658 }
10659 
10660 #endif /* FEAT_SESSION */
10661 
10662 /*
10663  * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession".
10664  * Return FAIL for a write error.
10665  */
10666     int
10667 put_eol(FILE *fd)
10668 {
10669     if (
10670 #ifdef USE_CRNL
10671 	    (
10672 # ifdef MKSESSION_NL
10673 	     !mksession_nl &&
10674 # endif
10675 	     (putc('\r', fd) < 0)) ||
10676 #endif
10677 	    (putc('\n', fd) < 0))
10678 	return FAIL;
10679     return OK;
10680 }
10681 
10682 /*
10683  * Write a line to "fd".
10684  * Return FAIL for a write error.
10685  */
10686     int
10687 put_line(FILE *fd, char *s)
10688 {
10689     if (fputs(s, fd) < 0 || put_eol(fd) == FAIL)
10690 	return FAIL;
10691     return OK;
10692 }
10693 
10694 #ifdef FEAT_VIMINFO
10695 /*
10696  * ":rviminfo" and ":wviminfo".
10697  */
10698     static void
10699 ex_viminfo(
10700     exarg_T	*eap)
10701 {
10702     char_u	*save_viminfo;
10703 
10704     save_viminfo = p_viminfo;
10705     if (*p_viminfo == NUL)
10706 	p_viminfo = (char_u *)"'100";
10707     if (eap->cmdidx == CMD_rviminfo)
10708     {
10709 	if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS
10710 				  | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL)
10711 	    emsg(_("E195: Cannot open viminfo file for reading"));
10712     }
10713     else
10714 	write_viminfo(eap->arg, eap->forceit);
10715     p_viminfo = save_viminfo;
10716 }
10717 #endif
10718 
10719 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO)
10720 /*
10721  * Make a dialog message in "buff[DIALOG_MSG_SIZE]".
10722  * "format" must contain "%s".
10723  */
10724     void
10725 dialog_msg(char_u *buff, char *format, char_u *fname)
10726 {
10727     if (fname == NULL)
10728 	fname = (char_u *)_("Untitled");
10729     vim_snprintf((char *)buff, DIALOG_MSG_SIZE, format, fname);
10730 }
10731 #endif
10732 
10733 /*
10734  * ":behave {mswin,xterm}"
10735  */
10736     static void
10737 ex_behave(exarg_T *eap)
10738 {
10739     if (STRCMP(eap->arg, "mswin") == 0)
10740     {
10741 	set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
10742 	set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
10743 	set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
10744 	set_option_value((char_u *)"keymodel", 0L,
10745 					     (char_u *)"startsel,stopsel", 0);
10746     }
10747     else if (STRCMP(eap->arg, "xterm") == 0)
10748     {
10749 	set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
10750 	set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
10751 	set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
10752 	set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
10753     }
10754     else
10755 	semsg(_(e_invarg2), eap->arg);
10756 }
10757 
10758 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
10759 /*
10760  * Function given to ExpandGeneric() to obtain the possible arguments of the
10761  * ":behave {mswin,xterm}" command.
10762  */
10763     char_u *
10764 get_behave_arg(expand_T *xp UNUSED, int idx)
10765 {
10766     if (idx == 0)
10767 	return (char_u *)"mswin";
10768     if (idx == 1)
10769 	return (char_u *)"xterm";
10770     return NULL;
10771 }
10772 
10773 /*
10774  * Function given to ExpandGeneric() to obtain the possible arguments of the
10775  * ":messages {clear}" command.
10776  */
10777     char_u *
10778 get_messages_arg(expand_T *xp UNUSED, int idx)
10779 {
10780     if (idx == 0)
10781 	return (char_u *)"clear";
10782     return NULL;
10783 }
10784 #endif
10785 
10786 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
10787     char_u *
10788 get_mapclear_arg(expand_T *xp UNUSED, int idx)
10789 {
10790     if (idx == 0)
10791 	return (char_u *)"<buffer>";
10792     return NULL;
10793 }
10794 #endif
10795 
10796 static int filetype_detect = FALSE;
10797 static int filetype_plugin = FALSE;
10798 static int filetype_indent = FALSE;
10799 
10800 /*
10801  * ":filetype [plugin] [indent] {on,off,detect}"
10802  * on: Load the filetype.vim file to install autocommands for file types.
10803  * off: Load the ftoff.vim file to remove all autocommands for file types.
10804  * plugin on: load filetype.vim and ftplugin.vim
10805  * plugin off: load ftplugof.vim
10806  * indent on: load filetype.vim and indent.vim
10807  * indent off: load indoff.vim
10808  */
10809     static void
10810 ex_filetype(exarg_T *eap)
10811 {
10812     char_u	*arg = eap->arg;
10813     int		plugin = FALSE;
10814     int		indent = FALSE;
10815 
10816     if (*eap->arg == NUL)
10817     {
10818 	/* Print current status. */
10819 	smsg("filetype detection:%s  plugin:%s  indent:%s",
10820 		filetype_detect ? "ON" : "OFF",
10821 		filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF",
10822 		filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF");
10823 	return;
10824     }
10825 
10826     /* Accept "plugin" and "indent" in any order. */
10827     for (;;)
10828     {
10829 	if (STRNCMP(arg, "plugin", 6) == 0)
10830 	{
10831 	    plugin = TRUE;
10832 	    arg = skipwhite(arg + 6);
10833 	    continue;
10834 	}
10835 	if (STRNCMP(arg, "indent", 6) == 0)
10836 	{
10837 	    indent = TRUE;
10838 	    arg = skipwhite(arg + 6);
10839 	    continue;
10840 	}
10841 	break;
10842     }
10843     if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0)
10844     {
10845 	if (*arg == 'o' || !filetype_detect)
10846 	{
10847 	    source_runtime((char_u *)FILETYPE_FILE, DIP_ALL);
10848 	    filetype_detect = TRUE;
10849 	    if (plugin)
10850 	    {
10851 		source_runtime((char_u *)FTPLUGIN_FILE, DIP_ALL);
10852 		filetype_plugin = TRUE;
10853 	    }
10854 	    if (indent)
10855 	    {
10856 		source_runtime((char_u *)INDENT_FILE, DIP_ALL);
10857 		filetype_indent = TRUE;
10858 	    }
10859 	}
10860 	if (*arg == 'd')
10861 	{
10862 	    (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE, NULL);
10863 	    do_modelines(0);
10864 	}
10865     }
10866     else if (STRCMP(arg, "off") == 0)
10867     {
10868 	if (plugin || indent)
10869 	{
10870 	    if (plugin)
10871 	    {
10872 		source_runtime((char_u *)FTPLUGOF_FILE, DIP_ALL);
10873 		filetype_plugin = FALSE;
10874 	    }
10875 	    if (indent)
10876 	    {
10877 		source_runtime((char_u *)INDOFF_FILE, DIP_ALL);
10878 		filetype_indent = FALSE;
10879 	    }
10880 	}
10881 	else
10882 	{
10883 	    source_runtime((char_u *)FTOFF_FILE, DIP_ALL);
10884 	    filetype_detect = FALSE;
10885 	}
10886     }
10887     else
10888 	semsg(_(e_invarg2), arg);
10889 }
10890 
10891 /*
10892  * ":setfiletype [FALLBACK] {name}"
10893  */
10894     static void
10895 ex_setfiletype(exarg_T *eap)
10896 {
10897     if (!did_filetype)
10898     {
10899 	char_u *arg = eap->arg;
10900 
10901 	if (STRNCMP(arg, "FALLBACK ", 9) == 0)
10902 	    arg += 9;
10903 
10904 	set_option_value((char_u *)"filetype", 0L, arg, OPT_LOCAL);
10905 	if (arg != eap->arg)
10906 	    did_filetype = FALSE;
10907     }
10908 }
10909 
10910     static void
10911 ex_digraphs(exarg_T *eap UNUSED)
10912 {
10913 #ifdef FEAT_DIGRAPHS
10914     if (*eap->arg != NUL)
10915 	putdigraph(eap->arg);
10916     else
10917 	listdigraphs(eap->forceit);
10918 #else
10919     emsg(_("E196: No digraphs in this version"));
10920 #endif
10921 }
10922 
10923     static void
10924 ex_set(exarg_T *eap)
10925 {
10926     int		flags = 0;
10927 
10928     if (eap->cmdidx == CMD_setlocal)
10929 	flags = OPT_LOCAL;
10930     else if (eap->cmdidx == CMD_setglobal)
10931 	flags = OPT_GLOBAL;
10932 #if defined(FEAT_EVAL) && defined(FEAT_BROWSE)
10933     if (cmdmod.browse && flags == 0)
10934 	ex_options(eap);
10935     else
10936 #endif
10937 	(void)do_set(eap->arg, flags);
10938 }
10939 
10940 #if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
10941     void
10942 set_no_hlsearch(int flag)
10943 {
10944     no_hlsearch = flag;
10945 # ifdef FEAT_EVAL
10946     set_vim_var_nr(VV_HLSEARCH, !no_hlsearch && p_hls);
10947 # endif
10948 }
10949 
10950 /*
10951  * ":nohlsearch"
10952  */
10953     static void
10954 ex_nohlsearch(exarg_T *eap UNUSED)
10955 {
10956     set_no_hlsearch(TRUE);
10957     redraw_all_later(SOME_VALID);
10958 }
10959 
10960 /*
10961  * ":[N]match {group} {pattern}"
10962  * Sets nextcmd to the start of the next command, if any.  Also called when
10963  * skipping commands to find the next command.
10964  */
10965     static void
10966 ex_match(exarg_T *eap)
10967 {
10968     char_u	*p;
10969     char_u	*g = NULL;
10970     char_u	*end;
10971     int		c;
10972     int		id;
10973 
10974     if (eap->line2 <= 3)
10975 	id = eap->line2;
10976     else
10977     {
10978 	emsg(_(e_invcmd));
10979 	return;
10980     }
10981 
10982     /* First clear any old pattern. */
10983     if (!eap->skip)
10984 	match_delete(curwin, id, FALSE);
10985 
10986     if (ends_excmd(*eap->arg))
10987 	end = eap->arg;
10988     else if ((STRNICMP(eap->arg, "none", 4) == 0
10989 		&& (VIM_ISWHITE(eap->arg[4]) || ends_excmd(eap->arg[4]))))
10990 	end = eap->arg + 4;
10991     else
10992     {
10993 	p = skiptowhite(eap->arg);
10994 	if (!eap->skip)
10995 	    g = vim_strnsave(eap->arg, (int)(p - eap->arg));
10996 	p = skipwhite(p);
10997 	if (*p == NUL)
10998 	{
10999 	    /* There must be two arguments. */
11000 	    vim_free(g);
11001 	    semsg(_(e_invarg2), eap->arg);
11002 	    return;
11003 	}
11004 	end = skip_regexp(p + 1, *p, TRUE, NULL);
11005 	if (!eap->skip)
11006 	{
11007 	    if (*end != NUL && !ends_excmd(*skipwhite(end + 1)))
11008 	    {
11009 		vim_free(g);
11010 		eap->errmsg = e_trailing;
11011 		return;
11012 	    }
11013 	    if (*end != *p)
11014 	    {
11015 		vim_free(g);
11016 		semsg(_(e_invarg2), p);
11017 		return;
11018 	    }
11019 
11020 	    c = *end;
11021 	    *end = NUL;
11022 	    match_add(curwin, g, p + 1, 10, id, NULL, NULL);
11023 	    vim_free(g);
11024 	    *end = c;
11025 	}
11026     }
11027     eap->nextcmd = find_nextcmd(end);
11028 }
11029 #endif
11030 
11031 #ifdef FEAT_CRYPT
11032 /*
11033  * ":X": Get crypt key
11034  */
11035     static void
11036 ex_X(exarg_T *eap UNUSED)
11037 {
11038     crypt_check_current_method();
11039     (void)crypt_get_key(TRUE, TRUE);
11040 }
11041 #endif
11042 
11043 #ifdef FEAT_FOLDING
11044     static void
11045 ex_fold(exarg_T *eap)
11046 {
11047     if (foldManualAllowed(TRUE))
11048 	foldCreate(eap->line1, eap->line2);
11049 }
11050 
11051     static void
11052 ex_foldopen(exarg_T *eap)
11053 {
11054     opFoldRange(eap->line1, eap->line2, eap->cmdidx == CMD_foldopen,
11055 							 eap->forceit, FALSE);
11056 }
11057 
11058     static void
11059 ex_folddo(exarg_T *eap)
11060 {
11061     linenr_T	lnum;
11062 
11063 #ifdef FEAT_CLIPBOARD
11064     start_global_changes();
11065 #endif
11066 
11067     /* First set the marks for all lines closed/open. */
11068     for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
11069 	if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
11070 	    ml_setmarked(lnum);
11071 
11072     /* Execute the command on the marked lines. */
11073     global_exe(eap->arg);
11074     ml_clearmarked();	   /* clear rest of the marks */
11075 #ifdef FEAT_CLIPBOARD
11076     end_global_changes();
11077 #endif
11078 }
11079 #endif
11080 
11081 #ifdef FEAT_QUICKFIX
11082 /*
11083  * Returns TRUE if the supplied Ex cmdidx is for a location list command
11084  * instead of a quickfix command.
11085  */
11086     int
11087 is_loclist_cmd(int cmdidx)
11088 {
11089     if (cmdidx < 0 || cmdidx >= CMD_SIZE)
11090 	return FALSE;
11091     return cmdnames[cmdidx].cmd_name[0] == 'l';
11092 }
11093 #endif
11094 
11095 # if defined(FEAT_TIMERS) || defined(PROTO)
11096     int
11097 get_pressedreturn(void)
11098 {
11099     return ex_pressedreturn;
11100 }
11101 
11102     void
11103 set_pressedreturn(int val)
11104 {
11105      ex_pressedreturn = val;
11106 }
11107 #endif
11108