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