xref: /vim-8.2.3635/src/ex_cmds.c (revision fcfe1a9b)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * ex_cmds.c: some functions for command line commands
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 #ifdef FEAT_FLOAT
18 # include <float.h>
19 #endif
20 
21 static int linelen(int *has_tab);
22 static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out);
23 
24 static int check_readonly(int *forceit, buf_T *buf);
25 static void delbuf_msg(char_u *name);
26 static int help_compare(const void *s1, const void *s2);
27 static void prepare_help_buffer(void);
28 
29 /*
30  * ":ascii" and "ga".
31  */
32     void
33 do_ascii(exarg_T *eap UNUSED)
34 {
35     int		c;
36     int		cval;
37     char	buf1[20];
38     char	buf2[20];
39     char_u	buf3[7];
40 #ifdef FEAT_DIGRAPHS
41     char_u      *dig;
42 #endif
43     int		cc[MAX_MCO];
44     int		ci = 0;
45     int		len;
46 
47     if (enc_utf8)
48 	c = utfc_ptr2char(ml_get_cursor(), cc);
49     else
50 	c = gchar_cursor();
51     if (c == NUL)
52     {
53 	msg("NUL");
54 	return;
55     }
56 
57     IObuff[0] = NUL;
58     if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80)
59     {
60 	if (c == NL)	    /* NUL is stored as NL */
61 	    c = NUL;
62 	if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
63 	    cval = NL;	    /* NL is stored as CR */
64 	else
65 	    cval = c;
66 	if (vim_isprintc_strict(c) && (c < ' '
67 #ifndef EBCDIC
68 		    || c > '~'
69 #endif
70 			       ))
71 	{
72 	    transchar_nonprint(buf3, c);
73 	    vim_snprintf(buf1, sizeof(buf1), "  <%s>", (char *)buf3);
74 	}
75 	else
76 	    buf1[0] = NUL;
77 #ifndef EBCDIC
78 	if (c >= 0x80)
79 	    vim_snprintf(buf2, sizeof(buf2), "  <M-%s>",
80 						 (char *)transchar(c & 0x7f));
81 	else
82 #endif
83 	    buf2[0] = NUL;
84 #ifdef FEAT_DIGRAPHS
85 	dig = get_digraph_for_char(cval);
86 	if (dig != NULL)
87 	    vim_snprintf((char *)IObuff, IOSIZE,
88 		_("<%s>%s%s  %d,  Hex %02x,  Oct %03o, Digr %s"),
89 			      transchar(c), buf1, buf2, cval, cval, cval, dig);
90 	else
91 #endif
92 	    vim_snprintf((char *)IObuff, IOSIZE,
93 		_("<%s>%s%s  %d,  Hex %02x,  Octal %03o"),
94 				  transchar(c), buf1, buf2, cval, cval, cval);
95 	if (enc_utf8)
96 	    c = cc[ci++];
97 	else
98 	    c = 0;
99     }
100 
101     /* Repeat for combining characters. */
102     while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80)))
103     {
104 	len = (int)STRLEN(IObuff);
105 	/* This assumes every multi-byte char is printable... */
106 	if (len > 0)
107 	    IObuff[len++] = ' ';
108 	IObuff[len++] = '<';
109 	if (enc_utf8 && utf_iscomposing(c)
110 # ifdef USE_GUI
111 		&& !gui.in_use
112 # endif
113 		)
114 	    IObuff[len++] = ' '; /* draw composing char on top of a space */
115 	len += (*mb_char2bytes)(c, IObuff + len);
116 #ifdef FEAT_DIGRAPHS
117 	dig = get_digraph_for_char(c);
118 	if (dig != NULL)
119 	    vim_snprintf((char *)IObuff + len, IOSIZE - len,
120 			c < 0x10000 ? _("> %d, Hex %04x, Oct %o, Digr %s")
121 				    : _("> %d, Hex %08x, Oct %o, Digr %s"),
122 					c, c, c, dig);
123 	else
124 #endif
125 	    vim_snprintf((char *)IObuff + len, IOSIZE - len,
126 			 c < 0x10000 ? _("> %d, Hex %04x, Octal %o")
127 				     : _("> %d, Hex %08x, Octal %o"),
128 				     c, c, c);
129 	if (ci == MAX_MCO)
130 	    break;
131 	if (enc_utf8)
132 	    c = cc[ci++];
133 	else
134 	    c = 0;
135     }
136 
137     msg((char *)IObuff);
138 }
139 
140 /*
141  * ":left", ":center" and ":right": align text.
142  */
143     void
144 ex_align(exarg_T *eap)
145 {
146     pos_T	save_curpos;
147     int		len;
148     int		indent = 0;
149     int		new_indent;
150     int		has_tab;
151     int		width;
152 
153 #ifdef FEAT_RIGHTLEFT
154     if (curwin->w_p_rl)
155     {
156 	/* switch left and right aligning */
157 	if (eap->cmdidx == CMD_right)
158 	    eap->cmdidx = CMD_left;
159 	else if (eap->cmdidx == CMD_left)
160 	    eap->cmdidx = CMD_right;
161     }
162 #endif
163 
164     width = atoi((char *)eap->arg);
165     save_curpos = curwin->w_cursor;
166     if (eap->cmdidx == CMD_left)    /* width is used for new indent */
167     {
168 	if (width >= 0)
169 	    indent = width;
170     }
171     else
172     {
173 	/*
174 	 * if 'textwidth' set, use it
175 	 * else if 'wrapmargin' set, use it
176 	 * if invalid value, use 80
177 	 */
178 	if (width <= 0)
179 	    width = curbuf->b_p_tw;
180 	if (width == 0 && curbuf->b_p_wm > 0)
181 	    width = curwin->w_width - curbuf->b_p_wm;
182 	if (width <= 0)
183 	    width = 80;
184     }
185 
186     if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
187 	return;
188 
189     for (curwin->w_cursor.lnum = eap->line1;
190 		 curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum)
191     {
192 	if (eap->cmdidx == CMD_left)		/* left align */
193 	    new_indent = indent;
194 	else
195 	{
196 	    has_tab = FALSE;	/* avoid uninit warnings */
197 	    len = linelen(eap->cmdidx == CMD_right ? &has_tab
198 						   : NULL) - get_indent();
199 
200 	    if (len <= 0)			/* skip blank lines */
201 		continue;
202 
203 	    if (eap->cmdidx == CMD_center)
204 		new_indent = (width - len) / 2;
205 	    else
206 	    {
207 		new_indent = width - len;	/* right align */
208 
209 		/*
210 		 * Make sure that embedded TABs don't make the text go too far
211 		 * to the right.
212 		 */
213 		if (has_tab)
214 		    while (new_indent > 0)
215 		    {
216 			(void)set_indent(new_indent, 0);
217 			if (linelen(NULL) <= width)
218 			{
219 			    /*
220 			     * Now try to move the line as much as possible to
221 			     * the right.  Stop when it moves too far.
222 			     */
223 			    do
224 				(void)set_indent(++new_indent, 0);
225 			    while (linelen(NULL) <= width);
226 			    --new_indent;
227 			    break;
228 			}
229 			--new_indent;
230 		    }
231 	    }
232 	}
233 	if (new_indent < 0)
234 	    new_indent = 0;
235 	(void)set_indent(new_indent, 0);		/* set indent */
236     }
237     changed_lines(eap->line1, 0, eap->line2 + 1, 0L);
238     curwin->w_cursor = save_curpos;
239     beginline(BL_WHITE | BL_FIX);
240 }
241 
242 /*
243  * Get the length of the current line, excluding trailing white space.
244  */
245     static int
246 linelen(int *has_tab)
247 {
248     char_u  *line;
249     char_u  *first;
250     char_u  *last;
251     int	    save;
252     int	    len;
253 
254     /* find the first non-blank character */
255     line = ml_get_curline();
256     first = skipwhite(line);
257 
258     /* find the character after the last non-blank character */
259     for (last = first + STRLEN(first);
260 				last > first && VIM_ISWHITE(last[-1]); --last)
261 	;
262     save = *last;
263     *last = NUL;
264     len = linetabsize(line);		/* get line length */
265     if (has_tab != NULL)		/* check for embedded TAB */
266 	*has_tab = (vim_strchr(first, TAB) != NULL);
267     *last = save;
268 
269     return len;
270 }
271 
272 /* Buffer for two lines used during sorting.  They are allocated to
273  * contain the longest line being sorted. */
274 static char_u	*sortbuf1;
275 static char_u	*sortbuf2;
276 
277 static int	sort_ic;	/* ignore case */
278 static int	sort_nr;	/* sort on number */
279 static int	sort_rx;	/* sort on regex instead of skipping it */
280 #ifdef FEAT_FLOAT
281 static int	sort_flt;	/* sort on floating number */
282 #endif
283 
284 static int	sort_abort;	/* flag to indicate if sorting has been interrupted */
285 
286 /* Struct to store info to be sorted. */
287 typedef struct
288 {
289     linenr_T	lnum;			// line number
290     union {
291 	struct
292 	{
293 	    varnumber_T	start_col_nr;	// starting column number
294 	    varnumber_T	end_col_nr;	// ending column number
295 	} line;
296 	struct
297 	{
298 	    varnumber_T	value;		// value if sorting by integer
299 	    int is_number;		// TRUE when line contains a number
300 	} num;
301 #ifdef FEAT_FLOAT
302 	float_T value_flt;		// value if sorting by float
303 #endif
304     } st_u;
305 } sorti_T;
306 
307 static int sort_compare(const void *s1, const void *s2);
308 
309     static int
310 sort_compare(const void *s1, const void *s2)
311 {
312     sorti_T	l1 = *(sorti_T *)s1;
313     sorti_T	l2 = *(sorti_T *)s2;
314     int		result = 0;
315 
316     /* If the user interrupts, there's no way to stop qsort() immediately, but
317      * if we return 0 every time, qsort will assume it's done sorting and
318      * exit. */
319     if (sort_abort)
320 	return 0;
321     fast_breakcheck();
322     if (got_int)
323 	sort_abort = TRUE;
324 
325     if (sort_nr)
326     {
327 	if (l1.st_u.num.is_number != l2.st_u.num.is_number)
328 	    result = l1.st_u.num.is_number - l2.st_u.num.is_number;
329 	else
330 	    result = l1.st_u.num.value == l2.st_u.num.value ? 0
331 			     : l1.st_u.num.value > l2.st_u.num.value ? 1 : -1;
332     }
333 #ifdef FEAT_FLOAT
334     else if (sort_flt)
335 	result = l1.st_u.value_flt == l2.st_u.value_flt ? 0
336 			     : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1;
337 #endif
338     else
339     {
340 	/* We need to copy one line into "sortbuf1", because there is no
341 	 * guarantee that the first pointer becomes invalid when obtaining the
342 	 * second one. */
343 	STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr,
344 		     l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1);
345 	sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0;
346 	STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr,
347 		     l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
348 	sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0;
349 
350 	result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
351 						 : STRCMP(sortbuf1, sortbuf2);
352     }
353 
354     /* If two lines have the same value, preserve the original line order. */
355     if (result == 0)
356 	return (int)(l1.lnum - l2.lnum);
357     return result;
358 }
359 
360 /*
361  * ":sort".
362  */
363     void
364 ex_sort(exarg_T *eap)
365 {
366     regmatch_T	regmatch;
367     int		len;
368     linenr_T	lnum;
369     long	maxlen = 0;
370     sorti_T	*nrs;
371     size_t	count = (size_t)(eap->line2 - eap->line1 + 1);
372     size_t	i;
373     char_u	*p;
374     char_u	*s;
375     char_u	*s2;
376     char_u	c;			/* temporary character storage */
377     int		unique = FALSE;
378     long	deleted;
379     colnr_T	start_col;
380     colnr_T	end_col;
381     int		sort_what = 0;
382     int		format_found = 0;
383     int		change_occurred = FALSE; // Buffer contents changed.
384 
385     /* Sorting one line is really quick! */
386     if (count <= 1)
387 	return;
388 
389     if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
390 	return;
391     sortbuf1 = NULL;
392     sortbuf2 = NULL;
393     regmatch.regprog = NULL;
394     nrs = ALLOC_MULT(sorti_T, count);
395     if (nrs == NULL)
396 	goto sortend;
397 
398     sort_abort = sort_ic = sort_rx = sort_nr = 0;
399 #ifdef FEAT_FLOAT
400     sort_flt = 0;
401 #endif
402 
403     for (p = eap->arg; *p != NUL; ++p)
404     {
405 	if (VIM_ISWHITE(*p))
406 	    ;
407 	else if (*p == 'i')
408 	    sort_ic = TRUE;
409 	else if (*p == 'r')
410 	    sort_rx = TRUE;
411 	else if (*p == 'n')
412 	{
413 	    sort_nr = 1;
414 	    ++format_found;
415 	}
416 #ifdef FEAT_FLOAT
417 	else if (*p == 'f')
418 	{
419 	    sort_flt = 1;
420 	    ++format_found;
421 	}
422 #endif
423 	else if (*p == 'b')
424 	{
425 	    sort_what = STR2NR_BIN + STR2NR_FORCE;
426 	    ++format_found;
427 	}
428 	else if (*p == 'o')
429 	{
430 	    sort_what = STR2NR_OCT + STR2NR_FORCE;
431 	    ++format_found;
432 	}
433 	else if (*p == 'x')
434 	{
435 	    sort_what = STR2NR_HEX + STR2NR_FORCE;
436 	    ++format_found;
437 	}
438 	else if (*p == 'u')
439 	    unique = TRUE;
440 	else if (*p == '"')	/* comment start */
441 	    break;
442 	else if (check_nextcmd(p) != NULL)
443 	{
444 	    eap->nextcmd = check_nextcmd(p);
445 	    break;
446 	}
447 	else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL)
448 	{
449 	    s = skip_regexp(p + 1, *p, TRUE, NULL);
450 	    if (*s != *p)
451 	    {
452 		emsg(_(e_invalpat));
453 		goto sortend;
454 	    }
455 	    *s = NUL;
456 	    /* Use last search pattern if sort pattern is empty. */
457 	    if (s == p + 1)
458 	    {
459 		if (last_search_pat() == NULL)
460 		{
461 		    emsg(_(e_noprevre));
462 		    goto sortend;
463 		}
464 		regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
465 	    }
466 	    else
467 		regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
468 	    if (regmatch.regprog == NULL)
469 		goto sortend;
470 	    p = s;		/* continue after the regexp */
471 	    regmatch.rm_ic = p_ic;
472 	}
473 	else
474 	{
475 	    semsg(_(e_invarg2), p);
476 	    goto sortend;
477 	}
478     }
479 
480     /* Can only have one of 'n', 'b', 'o' and 'x'. */
481     if (format_found > 1)
482     {
483 	emsg(_(e_invarg));
484 	goto sortend;
485     }
486 
487     /* From here on "sort_nr" is used as a flag for any integer number
488      * sorting. */
489     sort_nr += sort_what;
490 
491     /*
492      * Make an array with all line numbers.  This avoids having to copy all
493      * the lines into allocated memory.
494      * When sorting on strings "start_col_nr" is the offset in the line, for
495      * numbers sorting it's the number to sort on.  This means the pattern
496      * matching and number conversion only has to be done once per line.
497      * Also get the longest line length for allocating "sortbuf".
498      */
499     for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
500     {
501 	s = ml_get(lnum);
502 	len = (int)STRLEN(s);
503 	if (maxlen < len)
504 	    maxlen = len;
505 
506 	start_col = 0;
507 	end_col = len;
508 	if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0))
509 	{
510 	    if (sort_rx)
511 	    {
512 		start_col = (colnr_T)(regmatch.startp[0] - s);
513 		end_col = (colnr_T)(regmatch.endp[0] - s);
514 	    }
515 	    else
516 		start_col = (colnr_T)(regmatch.endp[0] - s);
517 	}
518 	else
519 	    if (regmatch.regprog != NULL)
520 		end_col = 0;
521 
522 	if (sort_nr
523 #ifdef FEAT_FLOAT
524 		|| sort_flt
525 #endif
526 		)
527 	{
528 	    /* Make sure vim_str2nr doesn't read any digits past the end
529 	     * of the match, by temporarily terminating the string there */
530 	    s2 = s + end_col;
531 	    c = *s2;
532 	    *s2 = NUL;
533 	    /* Sorting on number: Store the number itself. */
534 	    p = s + start_col;
535 	    if (sort_nr)
536 	    {
537 		if (sort_what & STR2NR_HEX)
538 		    s = skiptohex(p);
539 		else if (sort_what & STR2NR_BIN)
540 		    s = skiptobin(p);
541 		else
542 		    s = skiptodigit(p);
543 		if (s > p && s[-1] == '-')
544 		    --s;  /* include preceding negative sign */
545 		if (*s == NUL)
546 		{
547 		    /* line without number should sort before any number */
548 		    nrs[lnum - eap->line1].st_u.num.is_number = FALSE;
549 		    nrs[lnum - eap->line1].st_u.num.value = 0;
550 		}
551 		else
552 		{
553 		    nrs[lnum - eap->line1].st_u.num.is_number = TRUE;
554 		    vim_str2nr(s, NULL, NULL, sort_what,
555 			&nrs[lnum - eap->line1].st_u.num.value,
556 			NULL, 0, FALSE);
557 		}
558 	    }
559 #ifdef FEAT_FLOAT
560 	    else
561 	    {
562 		s = skipwhite(p);
563 		if (*s == '+')
564 		    s = skipwhite(s + 1);
565 
566 		if (*s == NUL)
567 		    /* empty line should sort before any number */
568 		    nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX;
569 		else
570 		    nrs[lnum - eap->line1].st_u.value_flt =
571 						      strtod((char *)s, NULL);
572 	    }
573 #endif
574 	    *s2 = c;
575 	}
576 	else
577 	{
578 	    /* Store the column to sort at. */
579 	    nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col;
580 	    nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col;
581 	}
582 
583 	nrs[lnum - eap->line1].lnum = lnum;
584 
585 	if (regmatch.regprog != NULL)
586 	    fast_breakcheck();
587 	if (got_int)
588 	    goto sortend;
589     }
590 
591     /* Allocate a buffer that can hold the longest line. */
592     sortbuf1 = alloc(maxlen + 1);
593     if (sortbuf1 == NULL)
594 	goto sortend;
595     sortbuf2 = alloc(maxlen + 1);
596     if (sortbuf2 == NULL)
597 	goto sortend;
598 
599     /* Sort the array of line numbers.  Note: can't be interrupted! */
600     qsort((void *)nrs, count, sizeof(sorti_T), sort_compare);
601 
602     if (sort_abort)
603 	goto sortend;
604 
605     /* Insert the lines in the sorted order below the last one. */
606     lnum = eap->line2;
607     for (i = 0; i < count; ++i)
608     {
609 	linenr_T get_lnum = nrs[eap->forceit ? count - i - 1 : i].lnum;
610 
611 	// If the original line number of the line being placed is not the same
612 	// as "lnum" (accounting for offset), we know that the buffer changed.
613 	if (get_lnum + ((linenr_T)count - 1) != lnum)
614 	    change_occurred = TRUE;
615 
616 	s = ml_get(get_lnum);
617 	if (!unique || i == 0
618 		|| (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0)
619 	{
620 	    // Copy the line into a buffer, it may become invalid in
621 	    // ml_append(). And it's needed for "unique".
622 	    STRCPY(sortbuf1, s);
623 	    if (ml_append(lnum++, sortbuf1, (colnr_T)0, FALSE) == FAIL)
624 		break;
625 	}
626 	fast_breakcheck();
627 	if (got_int)
628 	    goto sortend;
629     }
630 
631     /* delete the original lines if appending worked */
632     if (i == count)
633 	for (i = 0; i < count; ++i)
634 	    ml_delete(eap->line1, FALSE);
635     else
636 	count = 0;
637 
638     /* Adjust marks for deleted (or added) lines and prepare for displaying. */
639     deleted = (long)(count - (lnum - eap->line2));
640     if (deleted > 0)
641     {
642 	mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted);
643 	msgmore(-deleted);
644     }
645     else if (deleted < 0)
646 	mark_adjust(eap->line2, MAXLNUM, -deleted, 0L);
647 
648     if (change_occurred || deleted != 0)
649 	changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
650 
651     curwin->w_cursor.lnum = eap->line1;
652     beginline(BL_WHITE | BL_FIX);
653 
654 sortend:
655     vim_free(nrs);
656     vim_free(sortbuf1);
657     vim_free(sortbuf2);
658     vim_regfree(regmatch.regprog);
659     if (got_int)
660 	emsg(_(e_interr));
661 }
662 
663 /*
664  * ":retab".
665  */
666     void
667 ex_retab(exarg_T *eap)
668 {
669     linenr_T	lnum;
670     int		got_tab = FALSE;
671     long	num_spaces = 0;
672     long	num_tabs;
673     long	len;
674     long	col;
675     long	vcol;
676     long	start_col = 0;		/* For start of white-space string */
677     long	start_vcol = 0;		/* For start of white-space string */
678     long	old_len;
679     char_u	*ptr;
680     char_u	*new_line = (char_u *)1;    /* init to non-NULL */
681     int		did_undo;		/* called u_save for current line */
682 #ifdef FEAT_VARTABS
683     int		*new_vts_array = NULL;
684     char_u	*new_ts_str;		/* string value of tab argument */
685 #else
686     int		temp;
687     int		new_ts;
688 #endif
689     int		save_list;
690     linenr_T	first_line = 0;		/* first changed line */
691     linenr_T	last_line = 0;		/* last changed line */
692 
693     save_list = curwin->w_p_list;
694     curwin->w_p_list = 0;	    /* don't want list mode here */
695 
696 #ifdef FEAT_VARTABS
697     new_ts_str = eap->arg;
698     if (!tabstop_set(eap->arg, &new_vts_array))
699 	return;
700     while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
701 	++(eap->arg);
702 
703     // This ensures that either new_vts_array and new_ts_str are freshly
704     // allocated, or new_vts_array points to an existing array and new_ts_str
705     // is null.
706     if (new_vts_array == NULL)
707     {
708 	new_vts_array = curbuf->b_p_vts_array;
709 	new_ts_str = NULL;
710     }
711     else
712 	new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str);
713 #else
714     new_ts = getdigits(&(eap->arg));
715     if (new_ts < 0)
716     {
717 	emsg(_(e_positive));
718 	return;
719     }
720     if (new_ts == 0)
721 	new_ts = curbuf->b_p_ts;
722 #endif
723     for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
724     {
725 	ptr = ml_get(lnum);
726 	col = 0;
727 	vcol = 0;
728 	did_undo = FALSE;
729 	for (;;)
730 	{
731 	    if (VIM_ISWHITE(ptr[col]))
732 	    {
733 		if (!got_tab && num_spaces == 0)
734 		{
735 		    /* First consecutive white-space */
736 		    start_vcol = vcol;
737 		    start_col = col;
738 		}
739 		if (ptr[col] == ' ')
740 		    num_spaces++;
741 		else
742 		    got_tab = TRUE;
743 	    }
744 	    else
745 	    {
746 		if (got_tab || (eap->forceit && num_spaces > 1))
747 		{
748 		    /* Retabulate this string of white-space */
749 
750 		    /* len is virtual length of white string */
751 		    len = num_spaces = vcol - start_vcol;
752 		    num_tabs = 0;
753 		    if (!curbuf->b_p_et)
754 		    {
755 #ifdef FEAT_VARTABS
756 			int t, s;
757 
758 			tabstop_fromto(start_vcol, vcol,
759 					curbuf->b_p_ts, new_vts_array, &t, &s);
760 			num_tabs = t;
761 			num_spaces = s;
762 #else
763 			temp = new_ts - (start_vcol % new_ts);
764 			if (num_spaces >= temp)
765 			{
766 			    num_spaces -= temp;
767 			    num_tabs++;
768 			}
769 			num_tabs += num_spaces / new_ts;
770 			num_spaces -= (num_spaces / new_ts) * new_ts;
771 #endif
772 		    }
773 		    if (curbuf->b_p_et || got_tab ||
774 					(num_spaces + num_tabs < len))
775 		    {
776 			if (did_undo == FALSE)
777 			{
778 			    did_undo = TRUE;
779 			    if (u_save((linenr_T)(lnum - 1),
780 						(linenr_T)(lnum + 1)) == FAIL)
781 			    {
782 				new_line = NULL;	/* flag out-of-memory */
783 				break;
784 			    }
785 			}
786 
787 			/* len is actual number of white characters used */
788 			len = num_spaces + num_tabs;
789 			old_len = (long)STRLEN(ptr);
790 			new_line = alloc(old_len - col + start_col + len + 1);
791 			if (new_line == NULL)
792 			    break;
793 			if (start_col > 0)
794 			    mch_memmove(new_line, ptr, (size_t)start_col);
795 			mch_memmove(new_line + start_col + len,
796 				      ptr + col, (size_t)(old_len - col + 1));
797 			ptr = new_line + start_col;
798 			for (col = 0; col < len; col++)
799 			    ptr[col] = (col < num_tabs) ? '\t' : ' ';
800 			ml_replace(lnum, new_line, FALSE);
801 			if (first_line == 0)
802 			    first_line = lnum;
803 			last_line = lnum;
804 			ptr = new_line;
805 			col = start_col + len;
806 		    }
807 		}
808 		got_tab = FALSE;
809 		num_spaces = 0;
810 	    }
811 	    if (ptr[col] == NUL)
812 		break;
813 	    vcol += chartabsize(ptr + col, (colnr_T)vcol);
814 	    if (has_mbyte)
815 		col += (*mb_ptr2len)(ptr + col);
816 	    else
817 		++col;
818 	}
819 	if (new_line == NULL)		    /* out of memory */
820 	    break;
821 	line_breakcheck();
822     }
823     if (got_int)
824 	emsg(_(e_interr));
825 
826 #ifdef FEAT_VARTABS
827     // If a single value was given then it can be considered equal to
828     // either the value of 'tabstop' or the value of 'vartabstop'.
829     if (tabstop_count(curbuf->b_p_vts_array) == 0
830 	&& tabstop_count(new_vts_array) == 1
831 	&& curbuf->b_p_ts == tabstop_first(new_vts_array))
832 	; /* not changed */
833     else if (tabstop_count(curbuf->b_p_vts_array) > 0
834         && tabstop_eq(curbuf->b_p_vts_array, new_vts_array))
835 	; /* not changed */
836     else
837 	redraw_curbuf_later(NOT_VALID);
838 #else
839     if (curbuf->b_p_ts != new_ts)
840 	redraw_curbuf_later(NOT_VALID);
841 #endif
842     if (first_line != 0)
843 	changed_lines(first_line, 0, last_line + 1, 0L);
844 
845     curwin->w_p_list = save_list;	/* restore 'list' */
846 
847 #ifdef FEAT_VARTABS
848     if (new_ts_str != NULL)		/* set the new tabstop */
849     {
850 	// If 'vartabstop' is in use or if the value given to retab has more
851 	// than one tabstop then update 'vartabstop'.
852 	int *old_vts_ary = curbuf->b_p_vts_array;
853 
854 	if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1)
855 	{
856 	    set_string_option_direct((char_u *)"vts", -1, new_ts_str,
857 							OPT_FREE|OPT_LOCAL, 0);
858 	    curbuf->b_p_vts_array = new_vts_array;
859 	    vim_free(old_vts_ary);
860 	}
861 	else
862 	{
863 	    // 'vartabstop' wasn't in use and a single value was given to
864 	    // retab then update 'tabstop'.
865 	    curbuf->b_p_ts = tabstop_first(new_vts_array);
866 	    vim_free(new_vts_array);
867 	}
868 	vim_free(new_ts_str);
869     }
870 #else
871     curbuf->b_p_ts = new_ts;
872 #endif
873     coladvance(curwin->w_curswant);
874 
875     u_clearline();
876 }
877 
878 /*
879  * :move command - move lines line1-line2 to line dest
880  *
881  * return FAIL for failure, OK otherwise
882  */
883     int
884 do_move(linenr_T line1, linenr_T line2, linenr_T dest)
885 {
886     char_u	*str;
887     linenr_T	l;
888     linenr_T	extra;	    // Num lines added before line1
889     linenr_T	num_lines;  // Num lines moved
890     linenr_T	last_line;  // Last line in file after adding new text
891 #ifdef FEAT_FOLDING
892     win_T	*win;
893     tabpage_T	*tp;
894 #endif
895 
896     if (dest >= line1 && dest < line2)
897     {
898 	emsg(_("E134: Cannot move a range of lines into itself"));
899 	return FAIL;
900     }
901 
902     // Do nothing if we are not actually moving any lines.  This will prevent
903     // the 'modified' flag from being set without cause.
904     if (dest == line1 - 1 || dest == line2)
905     {
906 	// Move the cursor as if lines were moved (see below) to be backwards
907 	// compatible.
908 	if (dest >= line1)
909 	    curwin->w_cursor.lnum = dest;
910 	else
911 	    curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
912 
913 	return OK;
914     }
915 
916     num_lines = line2 - line1 + 1;
917 
918     /*
919      * First we copy the old text to its new location -- webb
920      * Also copy the flag that ":global" command uses.
921      */
922     if (u_save(dest, dest + 1) == FAIL)
923 	return FAIL;
924     for (extra = 0, l = line1; l <= line2; l++)
925     {
926 	str = vim_strsave(ml_get(l + extra));
927 	if (str != NULL)
928 	{
929 	    ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
930 	    vim_free(str);
931 	    if (dest < line1)
932 		extra++;
933 	}
934     }
935 
936     /*
937      * Now we must be careful adjusting our marks so that we don't overlap our
938      * mark_adjust() calls.
939      *
940      * We adjust the marks within the old text so that they refer to the
941      * last lines of the file (temporarily), because we know no other marks
942      * will be set there since these line numbers did not exist until we added
943      * our new lines.
944      *
945      * Then we adjust the marks on lines between the old and new text positions
946      * (either forwards or backwards).
947      *
948      * And Finally we adjust the marks we put at the end of the file back to
949      * their final destination at the new text position -- webb
950      */
951     last_line = curbuf->b_ml.ml_line_count;
952     mark_adjust_nofold(line1, line2, last_line - line2, 0L);
953     if (dest >= line2)
954     {
955 	mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L);
956 #ifdef FEAT_FOLDING
957 	FOR_ALL_TAB_WINDOWS(tp, win) {
958 	    if (win->w_buffer == curbuf)
959 		foldMoveRange(&win->w_folds, line1, line2, dest);
960 	}
961 #endif
962 	curbuf->b_op_start.lnum = dest - num_lines + 1;
963 	curbuf->b_op_end.lnum = dest;
964     }
965     else
966     {
967 	mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L);
968 #ifdef FEAT_FOLDING
969 	FOR_ALL_TAB_WINDOWS(tp, win) {
970 	    if (win->w_buffer == curbuf)
971 		foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2);
972 	}
973 #endif
974 	curbuf->b_op_start.lnum = dest + 1;
975 	curbuf->b_op_end.lnum = dest + num_lines;
976     }
977     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
978     mark_adjust_nofold(last_line - num_lines + 1, last_line,
979 					     -(last_line - dest - extra), 0L);
980 
981     /*
982      * Now we delete the original text -- webb
983      */
984     if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
985 	return FAIL;
986 
987     for (l = line1; l <= line2; l++)
988 	ml_delete(line1 + extra, TRUE);
989 
990     if (!global_busy && num_lines > p_report)
991 	smsg(NGETTEXT("%ld line moved", "%ld lines moved", num_lines),
992 			(long)num_lines);
993 
994     /*
995      * Leave the cursor on the last of the moved lines.
996      */
997     if (dest >= line1)
998 	curwin->w_cursor.lnum = dest;
999     else
1000 	curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
1001 
1002     if (line1 < dest)
1003     {
1004 	dest += num_lines + 1;
1005 	last_line = curbuf->b_ml.ml_line_count;
1006 	if (dest > last_line + 1)
1007 	    dest = last_line + 1;
1008 	changed_lines(line1, 0, dest, 0L);
1009     }
1010     else
1011 	changed_lines(dest + 1, 0, line1 + num_lines, 0L);
1012 
1013     return OK;
1014 }
1015 
1016 /*
1017  * ":copy"
1018  */
1019     void
1020 ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
1021 {
1022     linenr_T	count;
1023     char_u	*p;
1024 
1025     count = line2 - line1 + 1;
1026     curbuf->b_op_start.lnum = n + 1;
1027     curbuf->b_op_end.lnum = n + count;
1028     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
1029 
1030     /*
1031      * there are three situations:
1032      * 1. destination is above line1
1033      * 2. destination is between line1 and line2
1034      * 3. destination is below line2
1035      *
1036      * n = destination (when starting)
1037      * curwin->w_cursor.lnum = destination (while copying)
1038      * line1 = start of source (while copying)
1039      * line2 = end of source (while copying)
1040      */
1041     if (u_save(n, n + 1) == FAIL)
1042 	return;
1043 
1044     curwin->w_cursor.lnum = n;
1045     while (line1 <= line2)
1046     {
1047 	/* need to use vim_strsave() because the line will be unlocked within
1048 	 * ml_append() */
1049 	p = vim_strsave(ml_get(line1));
1050 	if (p != NULL)
1051 	{
1052 	    ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
1053 	    vim_free(p);
1054 	}
1055 	/* situation 2: skip already copied lines */
1056 	if (line1 == n)
1057 	    line1 = curwin->w_cursor.lnum;
1058 	++line1;
1059 	if (curwin->w_cursor.lnum < line1)
1060 	    ++line1;
1061 	if (curwin->w_cursor.lnum < line2)
1062 	    ++line2;
1063 	++curwin->w_cursor.lnum;
1064     }
1065 
1066     appended_lines_mark(n, count);
1067 
1068     msgmore((long)count);
1069 }
1070 
1071 static char_u	*prevcmd = NULL;	/* the previous command */
1072 
1073 #if defined(EXITFREE) || defined(PROTO)
1074     void
1075 free_prev_shellcmd(void)
1076 {
1077     vim_free(prevcmd);
1078 }
1079 #endif
1080 
1081 /*
1082  * Handle the ":!cmd" command.	Also for ":r !cmd" and ":w !cmd"
1083  * Bangs in the argument are replaced with the previously entered command.
1084  * Remember the argument.
1085  */
1086     void
1087 do_bang(
1088     int		addr_count,
1089     exarg_T	*eap,
1090     int		forceit,
1091     int		do_in,
1092     int		do_out)
1093 {
1094     char_u		*arg = eap->arg;	/* command */
1095     linenr_T		line1 = eap->line1;	/* start of range */
1096     linenr_T		line2 = eap->line2;	/* end of range */
1097     char_u		*newcmd = NULL;		/* the new command */
1098     int			free_newcmd = FALSE;    /* need to free() newcmd */
1099     int			ins_prevcmd;
1100     char_u		*t;
1101     char_u		*p;
1102     char_u		*trailarg;
1103     int			len;
1104     int			scroll_save = msg_scroll;
1105 
1106     /*
1107      * Disallow shell commands for "rvim".
1108      * Disallow shell commands from .exrc and .vimrc in current directory for
1109      * security reasons.
1110      */
1111     if (check_restricted() || check_secure())
1112 	return;
1113 
1114     if (addr_count == 0)		/* :! */
1115     {
1116 	msg_scroll = FALSE;	    /* don't scroll here */
1117 	autowrite_all();
1118 	msg_scroll = scroll_save;
1119     }
1120 
1121     /*
1122      * Try to find an embedded bang, like in :!<cmd> ! [args]
1123      * (:!! is indicated by the 'forceit' variable)
1124      */
1125     ins_prevcmd = forceit;
1126     trailarg = arg;
1127     do
1128     {
1129 	len = (int)STRLEN(trailarg) + 1;
1130 	if (newcmd != NULL)
1131 	    len += (int)STRLEN(newcmd);
1132 	if (ins_prevcmd)
1133 	{
1134 	    if (prevcmd == NULL)
1135 	    {
1136 		emsg(_(e_noprev));
1137 		vim_free(newcmd);
1138 		return;
1139 	    }
1140 	    len += (int)STRLEN(prevcmd);
1141 	}
1142 	if ((t = alloc(len)) == NULL)
1143 	{
1144 	    vim_free(newcmd);
1145 	    return;
1146 	}
1147 	*t = NUL;
1148 	if (newcmd != NULL)
1149 	    STRCAT(t, newcmd);
1150 	if (ins_prevcmd)
1151 	    STRCAT(t, prevcmd);
1152 	p = t + STRLEN(t);
1153 	STRCAT(t, trailarg);
1154 	vim_free(newcmd);
1155 	newcmd = t;
1156 
1157 	/*
1158 	 * Scan the rest of the argument for '!', which is replaced by the
1159 	 * previous command.  "\!" is replaced by "!" (this is vi compatible).
1160 	 */
1161 	trailarg = NULL;
1162 	while (*p)
1163 	{
1164 	    if (*p == '!')
1165 	    {
1166 		if (p > newcmd && p[-1] == '\\')
1167 		    STRMOVE(p - 1, p);
1168 		else
1169 		{
1170 		    trailarg = p;
1171 		    *trailarg++ = NUL;
1172 		    ins_prevcmd = TRUE;
1173 		    break;
1174 		}
1175 	    }
1176 	    ++p;
1177 	}
1178     } while (trailarg != NULL);
1179 
1180     vim_free(prevcmd);
1181     prevcmd = newcmd;
1182 
1183     if (bangredo)	    /* put cmd in redo buffer for ! command */
1184     {
1185 	/* If % or # appears in the command, it must have been escaped.
1186 	 * Reescape them, so that redoing them does not substitute them by the
1187 	 * buffername. */
1188 	char_u *cmd = vim_strsave_escaped(prevcmd, (char_u *)"%#");
1189 
1190 	if (cmd != NULL)
1191 	{
1192 	    AppendToRedobuffLit(cmd, -1);
1193 	    vim_free(cmd);
1194 	}
1195 	else
1196 	    AppendToRedobuffLit(prevcmd, -1);
1197 	AppendToRedobuff((char_u *)"\n");
1198 	bangredo = FALSE;
1199     }
1200     /*
1201      * Add quotes around the command, for shells that need them.
1202      */
1203     if (*p_shq != NUL)
1204     {
1205 	newcmd = alloc(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1);
1206 	if (newcmd == NULL)
1207 	    return;
1208 	STRCPY(newcmd, p_shq);
1209 	STRCAT(newcmd, prevcmd);
1210 	STRCAT(newcmd, p_shq);
1211 	free_newcmd = TRUE;
1212     }
1213     if (addr_count == 0)		/* :! */
1214     {
1215 	/* echo the command */
1216 	msg_start();
1217 	msg_putchar(':');
1218 	msg_putchar('!');
1219 	msg_outtrans(newcmd);
1220 	msg_clr_eos();
1221 	windgoto(msg_row, msg_col);
1222 
1223 	do_shell(newcmd, 0);
1224     }
1225     else				/* :range! */
1226     {
1227 	/* Careful: This may recursively call do_bang() again! (because of
1228 	 * autocommands) */
1229 	do_filter(line1, line2, eap, newcmd, do_in, do_out);
1230 	apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, FALSE, curbuf);
1231     }
1232     if (free_newcmd)
1233 	vim_free(newcmd);
1234 }
1235 
1236 /*
1237  * do_filter: filter lines through a command given by the user
1238  *
1239  * We mostly use temp files and the call_shell() routine here. This would
1240  * normally be done using pipes on a UNIX machine, but this is more portable
1241  * to non-unix machines. The call_shell() routine needs to be able
1242  * to deal with redirection somehow, and should handle things like looking
1243  * at the PATH env. variable, and adding reasonable extensions to the
1244  * command name given by the user. All reasonable versions of call_shell()
1245  * do this.
1246  * Alternatively, if on Unix and redirecting input or output, but not both,
1247  * and the 'shelltemp' option isn't set, use pipes.
1248  * We use input redirection if do_in is TRUE.
1249  * We use output redirection if do_out is TRUE.
1250  */
1251     static void
1252 do_filter(
1253     linenr_T	line1,
1254     linenr_T	line2,
1255     exarg_T	*eap,		/* for forced 'ff' and 'fenc' */
1256     char_u	*cmd,
1257     int		do_in,
1258     int		do_out)
1259 {
1260     char_u	*itmp = NULL;
1261     char_u	*otmp = NULL;
1262     linenr_T	linecount;
1263     linenr_T	read_linecount;
1264     pos_T	cursor_save;
1265     char_u	*cmd_buf;
1266     buf_T	*old_curbuf = curbuf;
1267     int		shell_flags = 0;
1268 
1269     if (*cmd == NUL)	    /* no filter command */
1270 	return;
1271 
1272     cursor_save = curwin->w_cursor;
1273     linecount = line2 - line1 + 1;
1274     curwin->w_cursor.lnum = line1;
1275     curwin->w_cursor.col = 0;
1276     changed_line_abv_curs();
1277     invalidate_botline();
1278 
1279     /*
1280      * When using temp files:
1281      * 1. * Form temp file names
1282      * 2. * Write the lines to a temp file
1283      * 3.   Run the filter command on the temp file
1284      * 4. * Read the output of the command into the buffer
1285      * 5. * Delete the original lines to be filtered
1286      * 6. * Remove the temp files
1287      *
1288      * When writing the input with a pipe or when catching the output with a
1289      * pipe only need to do 3.
1290      */
1291 
1292     if (do_out)
1293 	shell_flags |= SHELL_DOOUT;
1294 
1295 #ifdef FEAT_FILTERPIPE
1296     if (!do_in && do_out && !p_stmp)
1297     {
1298 	/* Use a pipe to fetch stdout of the command, do not use a temp file. */
1299 	shell_flags |= SHELL_READ;
1300 	curwin->w_cursor.lnum = line2;
1301     }
1302     else if (do_in && !do_out && !p_stmp)
1303     {
1304 	/* Use a pipe to write stdin of the command, do not use a temp file. */
1305 	shell_flags |= SHELL_WRITE;
1306 	curbuf->b_op_start.lnum = line1;
1307 	curbuf->b_op_end.lnum = line2;
1308     }
1309     else if (do_in && do_out && !p_stmp)
1310     {
1311 	/* Use a pipe to write stdin and fetch stdout of the command, do not
1312 	 * use a temp file. */
1313 	shell_flags |= SHELL_READ|SHELL_WRITE;
1314 	curbuf->b_op_start.lnum = line1;
1315 	curbuf->b_op_end.lnum = line2;
1316 	curwin->w_cursor.lnum = line2;
1317     }
1318     else
1319 #endif
1320 	if ((do_in && (itmp = vim_tempname('i', FALSE)) == NULL)
1321 		|| (do_out && (otmp = vim_tempname('o', FALSE)) == NULL))
1322 	{
1323 	    emsg(_(e_notmp));
1324 	    goto filterend;
1325 	}
1326 
1327 /*
1328  * The writing and reading of temp files will not be shown.
1329  * Vi also doesn't do this and the messages are not very informative.
1330  */
1331     ++no_wait_return;		/* don't call wait_return() while busy */
1332     if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap,
1333 					   FALSE, FALSE, FALSE, TRUE) == FAIL)
1334     {
1335 	msg_putchar('\n');		/* keep message from buf_write() */
1336 	--no_wait_return;
1337 #if defined(FEAT_EVAL)
1338 	if (!aborting())
1339 #endif
1340 	    (void)semsg(_(e_notcreate), itmp);	/* will call wait_return */
1341 	goto filterend;
1342     }
1343     if (curbuf != old_curbuf)
1344 	goto filterend;
1345 
1346     if (!do_out)
1347 	msg_putchar('\n');
1348 
1349     /* Create the shell command in allocated memory. */
1350     cmd_buf = make_filter_cmd(cmd, itmp, otmp);
1351     if (cmd_buf == NULL)
1352 	goto filterend;
1353 
1354     windgoto((int)Rows - 1, 0);
1355     cursor_on();
1356 
1357     /*
1358      * When not redirecting the output the command can write anything to the
1359      * screen. If 'shellredir' is equal to ">", screen may be messed up by
1360      * stderr output of external command. Clear the screen later.
1361      * If do_in is FALSE, this could be something like ":r !cat", which may
1362      * also mess up the screen, clear it later.
1363      */
1364     if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
1365 	redraw_later_clear();
1366 
1367     if (do_out)
1368     {
1369 	if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
1370 	{
1371 	    vim_free(cmd_buf);
1372 	    goto error;
1373 	}
1374 	redraw_curbuf_later(VALID);
1375     }
1376     read_linecount = curbuf->b_ml.ml_line_count;
1377 
1378     /*
1379      * When call_shell() fails wait_return() is called to give the user a
1380      * chance to read the error messages. Otherwise errors are ignored, so you
1381      * can see the error messages from the command that appear on stdout; use
1382      * 'u' to fix the text
1383      * Switch to cooked mode when not redirecting stdin, avoids that something
1384      * like ":r !cat" hangs.
1385      * Pass on the SHELL_DOOUT flag when the output is being redirected.
1386      */
1387     if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED | shell_flags))
1388     {
1389 	redraw_later_clear();
1390 	wait_return(FALSE);
1391     }
1392     vim_free(cmd_buf);
1393 
1394     did_check_timestamps = FALSE;
1395     need_check_timestamps = TRUE;
1396 
1397     /* When interrupting the shell command, it may still have produced some
1398      * useful output.  Reset got_int here, so that readfile() won't cancel
1399      * reading. */
1400     ui_breakcheck();
1401     got_int = FALSE;
1402 
1403     if (do_out)
1404     {
1405 	if (otmp != NULL)
1406 	{
1407 	    if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM,
1408 						    eap, READ_FILTER) != OK)
1409 	    {
1410 #if defined(FEAT_EVAL)
1411 		if (!aborting())
1412 #endif
1413 		{
1414 		    msg_putchar('\n');
1415 		    semsg(_(e_notread), otmp);
1416 		}
1417 		goto error;
1418 	    }
1419 	    if (curbuf != old_curbuf)
1420 		goto filterend;
1421 	}
1422 
1423 	read_linecount = curbuf->b_ml.ml_line_count - read_linecount;
1424 
1425 	if (shell_flags & SHELL_READ)
1426 	{
1427 	    curbuf->b_op_start.lnum = line2 + 1;
1428 	    curbuf->b_op_end.lnum = curwin->w_cursor.lnum;
1429 	    appended_lines_mark(line2, read_linecount);
1430 	}
1431 
1432 	if (do_in)
1433 	{
1434 	    if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL)
1435 	    {
1436 		if (read_linecount >= linecount)
1437 		    /* move all marks from old lines to new lines */
1438 		    mark_adjust(line1, line2, linecount, 0L);
1439 		else
1440 		{
1441 		    /* move marks from old lines to new lines, delete marks
1442 		     * that are in deleted lines */
1443 		    mark_adjust(line1, line1 + read_linecount - 1,
1444 								linecount, 0L);
1445 		    mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L);
1446 		}
1447 	    }
1448 
1449 	    /*
1450 	     * Put cursor on first filtered line for ":range!cmd".
1451 	     * Adjust '[ and '] (set by buf_write()).
1452 	     */
1453 	    curwin->w_cursor.lnum = line1;
1454 	    del_lines(linecount, TRUE);
1455 	    curbuf->b_op_start.lnum -= linecount;	/* adjust '[ */
1456 	    curbuf->b_op_end.lnum -= linecount;		/* adjust '] */
1457 	    write_lnum_adjust(-linecount);		/* adjust last line
1458 							   for next write */
1459 #ifdef FEAT_FOLDING
1460 	    foldUpdate(curwin, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum);
1461 #endif
1462 	}
1463 	else
1464 	{
1465 	    /*
1466 	     * Put cursor on last new line for ":r !cmd".
1467 	     */
1468 	    linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
1469 	    curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
1470 	}
1471 
1472 	beginline(BL_WHITE | BL_FIX);	    /* cursor on first non-blank */
1473 	--no_wait_return;
1474 
1475 	if (linecount > p_report)
1476 	{
1477 	    if (do_in)
1478 	    {
1479 		vim_snprintf(msg_buf, sizeof(msg_buf),
1480 				    _("%ld lines filtered"), (long)linecount);
1481 		if (msg(msg_buf) && !msg_scroll)
1482 		    /* save message to display it after redraw */
1483 		    set_keep_msg((char_u *)msg_buf, 0);
1484 	    }
1485 	    else
1486 		msgmore((long)linecount);
1487 	}
1488     }
1489     else
1490     {
1491 error:
1492 	/* put cursor back in same position for ":w !cmd" */
1493 	curwin->w_cursor = cursor_save;
1494 	--no_wait_return;
1495 	wait_return(FALSE);
1496     }
1497 
1498 filterend:
1499 
1500     if (curbuf != old_curbuf)
1501     {
1502 	--no_wait_return;
1503 	emsg(_("E135: *Filter* Autocommands must not change current buffer"));
1504     }
1505     if (itmp != NULL)
1506 	mch_remove(itmp);
1507     if (otmp != NULL)
1508 	mch_remove(otmp);
1509     vim_free(itmp);
1510     vim_free(otmp);
1511 }
1512 
1513 /*
1514  * Call a shell to execute a command.
1515  * When "cmd" is NULL start an interactive shell.
1516  */
1517     void
1518 do_shell(
1519     char_u	*cmd,
1520     int		flags)	/* may be SHELL_DOOUT when output is redirected */
1521 {
1522     buf_T	*buf;
1523 #if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
1524     int		save_nwr;
1525 #endif
1526 #ifdef MSWIN
1527     int		winstart = FALSE;
1528     int		keep_termcap = FALSE;
1529 #endif
1530 
1531     /*
1532      * Disallow shell commands for "rvim".
1533      * Disallow shell commands from .exrc and .vimrc in current directory for
1534      * security reasons.
1535      */
1536     if (check_restricted() || check_secure())
1537     {
1538 	msg_end();
1539 	return;
1540     }
1541 
1542 #ifdef MSWIN
1543     /*
1544      * Check if ":!start" is used.  This implies not stopping termcap mode.
1545      */
1546     if (cmd != NULL)
1547 	keep_termcap = winstart = (STRNICMP(cmd, "start ", 6) == 0);
1548 
1549 # if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
1550     // Don't stop termcap mode when using a terminal window for the shell.
1551     if (gui.in_use && vim_strchr(p_go, GO_TERMINAL) != NULL)
1552 	keep_termcap = TRUE;
1553 # endif
1554 #endif
1555 
1556     /*
1557      * For autocommands we want to get the output on the current screen, to
1558      * avoid having to type return below.
1559      */
1560     msg_putchar('\r');			// put cursor at start of line
1561     if (!autocmd_busy)
1562     {
1563 #ifdef MSWIN
1564 	if (!keep_termcap)
1565 #endif
1566 	    stoptermcap();
1567     }
1568 #ifdef MSWIN
1569     if (!winstart)
1570 #endif
1571 	msg_putchar('\n');		// may shift screen one line up
1572 
1573     // warning message before calling the shell
1574     if (p_warn && !autocmd_busy && msg_silent == 0)
1575 	FOR_ALL_BUFFERS(buf)
1576 	    if (bufIsChangedNotTerm(buf))
1577 	    {
1578 #ifdef FEAT_GUI_MSWIN
1579 		if (!keep_termcap)
1580 		    starttermcap();	// don't want a message box here
1581 #endif
1582 		msg_puts(_("[No write since last change]\n"));
1583 #ifdef FEAT_GUI_MSWIN
1584 		if (!keep_termcap)
1585 		    stoptermcap();
1586 #endif
1587 		break;
1588 	    }
1589 
1590     // This windgoto is required for when the '\n' resulted in a "delete line
1591     // 1" command to the terminal.
1592     if (!swapping_screen())
1593 	windgoto(msg_row, msg_col);
1594     cursor_on();
1595     (void)call_shell(cmd, SHELL_COOKED | flags);
1596     did_check_timestamps = FALSE;
1597     need_check_timestamps = TRUE;
1598 
1599     /*
1600      * put the message cursor at the end of the screen, avoids wait_return()
1601      * to overwrite the text that the external command showed
1602      */
1603     if (!swapping_screen())
1604     {
1605 	msg_row = Rows - 1;
1606 	msg_col = 0;
1607     }
1608 
1609     if (autocmd_busy)
1610     {
1611 	if (msg_silent == 0)
1612 	    redraw_later_clear();
1613     }
1614     else
1615     {
1616 	/*
1617 	 * For ":sh" there is no need to call wait_return(), just redraw.
1618 	 * Also for the Win32 GUI (the output is in a console window).
1619 	 * Otherwise there is probably text on the screen that the user wants
1620 	 * to read before redrawing, so call wait_return().
1621 	 */
1622 #if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
1623 # ifdef VIMDLL
1624 	if (!gui.in_use)
1625 # endif
1626 	{
1627 	    if (cmd == NULL
1628 # ifdef MSWIN
1629 		    || (keep_termcap && !need_wait_return)
1630 # endif
1631 	       )
1632 	    {
1633 		if (msg_silent == 0)
1634 		    redraw_later_clear();
1635 		need_wait_return = FALSE;
1636 	    }
1637 	    else
1638 	    {
1639 		/*
1640 		 * If we switch screens when starttermcap() is called, we
1641 		 * really want to wait for "hit return to continue".
1642 		 */
1643 		save_nwr = no_wait_return;
1644 		if (swapping_screen())
1645 		    no_wait_return = FALSE;
1646 # ifdef AMIGA
1647 		wait_return(term_console ? -1 : msg_silent == 0); // see below
1648 # else
1649 		wait_return(msg_silent == 0);
1650 # endif
1651 		no_wait_return = save_nwr;
1652 	    }
1653 	}
1654 #endif /* FEAT_GUI_MSWIN */
1655 
1656 #ifdef MSWIN
1657 	if (!keep_termcap)	// if keep_termcap is TRUE didn't stop termcap
1658 #endif
1659 	    starttermcap();	// start termcap if not done by wait_return()
1660 
1661 	/*
1662 	 * In an Amiga window redrawing is caused by asking the window size.
1663 	 * If we got an interrupt this will not work. The chance that the
1664 	 * window size is wrong is very small, but we need to redraw the
1665 	 * screen.  Don't do this if ':' hit in wait_return().	THIS IS UGLY
1666 	 * but it saves an extra redraw.
1667 	 */
1668 #ifdef AMIGA
1669 	if (skip_redraw)		/* ':' hit in wait_return() */
1670 	{
1671 	    if (msg_silent == 0)
1672 		redraw_later_clear();
1673 	}
1674 	else if (term_console)
1675 	{
1676 	    OUT_STR(IF_EB("\033[0 q", ESC_STR "[0 q"));	/* get window size */
1677 	    if (got_int && msg_silent == 0)
1678 		redraw_later_clear();	/* if got_int is TRUE, redraw needed */
1679 	    else
1680 		must_redraw = 0;	/* no extra redraw needed */
1681 	}
1682 #endif
1683     }
1684 
1685     /* display any error messages now */
1686     display_errors();
1687 
1688     apply_autocmds(EVENT_SHELLCMDPOST, NULL, NULL, FALSE, curbuf);
1689 }
1690 
1691 #if !defined(UNIX)
1692     static char_u *
1693 find_pipe(char_u *cmd)
1694 {
1695     char_u  *p;
1696     int	    inquote = FALSE;
1697 
1698     for (p = cmd; *p != NUL; ++p)
1699     {
1700 	if (!inquote && *p == '|')
1701 	    return p;
1702 	if (*p == '"')
1703 	    inquote = !inquote;
1704 	else if (rem_backslash(p))
1705 	    ++p;
1706     }
1707     return NULL;
1708 }
1709 #endif
1710 
1711 /*
1712  * Create a shell command from a command string, input redirection file and
1713  * output redirection file.
1714  * Returns an allocated string with the shell command, or NULL for failure.
1715  */
1716     char_u *
1717 make_filter_cmd(
1718     char_u	*cmd,		/* command */
1719     char_u	*itmp,		/* NULL or name of input file */
1720     char_u	*otmp)		/* NULL or name of output file */
1721 {
1722     char_u	*buf;
1723     long_u	len;
1724 
1725 #if defined(UNIX)
1726     int		is_fish_shell;
1727     char_u	*shell_name = get_isolated_shell_name();
1728 
1729     /* Account for fish's different syntax for subshells */
1730     is_fish_shell = (fnamecmp(shell_name, "fish") == 0);
1731     vim_free(shell_name);
1732     if (is_fish_shell)
1733 	len = (long_u)STRLEN(cmd) + 13;		/* "begin; " + "; end" + NUL */
1734     else
1735 #endif
1736 	len = (long_u)STRLEN(cmd) + 3;			/* "()" + NUL */
1737     if (itmp != NULL)
1738 	len += (long_u)STRLEN(itmp) + 9;		/* " { < " + " } " */
1739     if (otmp != NULL)
1740 	len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; /* "  " */
1741     buf = alloc(len);
1742     if (buf == NULL)
1743 	return NULL;
1744 
1745 #if defined(UNIX)
1746     /*
1747      * Put braces around the command (for concatenated commands) when
1748      * redirecting input and/or output.
1749      */
1750     if (itmp != NULL || otmp != NULL)
1751     {
1752 	if (is_fish_shell)
1753 	    vim_snprintf((char *)buf, len, "begin; %s; end", (char *)cmd);
1754 	else
1755 	    vim_snprintf((char *)buf, len, "(%s)", (char *)cmd);
1756     }
1757     else
1758 	STRCPY(buf, cmd);
1759     if (itmp != NULL)
1760     {
1761 	STRCAT(buf, " < ");
1762 	STRCAT(buf, itmp);
1763     }
1764 #else
1765     /*
1766      * For shells that don't understand braces around commands, at least allow
1767      * the use of commands in a pipe.
1768      */
1769     STRCPY(buf, cmd);
1770     if (itmp != NULL)
1771     {
1772 	char_u	*p;
1773 
1774 	/*
1775 	 * If there is a pipe, we have to put the '<' in front of it.
1776 	 * Don't do this when 'shellquote' is not empty, otherwise the
1777 	 * redirection would be inside the quotes.
1778 	 */
1779 	if (*p_shq == NUL)
1780 	{
1781 	    p = find_pipe(buf);
1782 	    if (p != NULL)
1783 		*p = NUL;
1784 	}
1785 	STRCAT(buf, " <");	/* " < " causes problems on Amiga */
1786 	STRCAT(buf, itmp);
1787 	if (*p_shq == NUL)
1788 	{
1789 	    p = find_pipe(cmd);
1790 	    if (p != NULL)
1791 	    {
1792 		STRCAT(buf, " ");   /* insert a space before the '|' for DOS */
1793 		STRCAT(buf, p);
1794 	    }
1795 	}
1796     }
1797 #endif
1798     if (otmp != NULL)
1799 	append_redir(buf, (int)len, p_srr, otmp);
1800 
1801     return buf;
1802 }
1803 
1804 /*
1805  * Append output redirection for file "fname" to the end of string buffer
1806  * "buf[buflen]"
1807  * Works with the 'shellredir' and 'shellpipe' options.
1808  * The caller should make sure that there is enough room:
1809  *	STRLEN(opt) + STRLEN(fname) + 3
1810  */
1811     void
1812 append_redir(
1813     char_u	*buf,
1814     int		buflen,
1815     char_u	*opt,
1816     char_u	*fname)
1817 {
1818     char_u	*p;
1819     char_u	*end;
1820 
1821     end = buf + STRLEN(buf);
1822     /* find "%s" */
1823     for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p)
1824     {
1825 	if (p[1] == 's') /* found %s */
1826 	    break;
1827 	if (p[1] == '%') /* skip %% */
1828 	    ++p;
1829     }
1830     if (p != NULL)
1831     {
1832 	*end = ' '; /* not really needed? Not with sh, ksh or bash */
1833 	vim_snprintf((char *)end + 1, (size_t)(buflen - (end + 1 - buf)),
1834 						  (char *)opt, (char *)fname);
1835     }
1836     else
1837 	vim_snprintf((char *)end, (size_t)(buflen - (end - buf)),
1838 #ifdef FEAT_QUICKFIX
1839 		" %s %s",
1840 #else
1841 		" %s%s",	/* " > %s" causes problems on Amiga */
1842 #endif
1843 		(char *)opt, (char *)fname);
1844 }
1845 
1846 /*
1847  * Return the current time in seconds.  Calls time(), unless test_settime()
1848  * was used.
1849  */
1850     time_T
1851 vim_time(void)
1852 {
1853 # ifdef FEAT_EVAL
1854     return time_for_testing == 0 ? time(NULL) : time_for_testing;
1855 # else
1856     return time(NULL);
1857 # endif
1858 }
1859 
1860 /*
1861  * Implementation of ":fixdel", also used by get_stty().
1862  *  <BS>    resulting <Del>
1863  *   ^?		^H
1864  * not ^?	^?
1865  */
1866     void
1867 do_fixdel(exarg_T *eap UNUSED)
1868 {
1869     char_u  *p;
1870 
1871     p = find_termcode((char_u *)"kb");
1872     add_termcode((char_u *)"kD", p != NULL
1873 	    && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE);
1874 }
1875 
1876     void
1877 print_line_no_prefix(
1878     linenr_T	lnum,
1879     int		use_number,
1880     int		list)
1881 {
1882     char	numbuf[30];
1883 
1884     if (curwin->w_p_nu || use_number)
1885     {
1886 	vim_snprintf(numbuf, sizeof(numbuf),
1887 				   "%*ld ", number_width(curwin), (long)lnum);
1888 	msg_puts_attr(numbuf, HL_ATTR(HLF_N));	/* Highlight line nrs */
1889     }
1890     msg_prt_line(ml_get(lnum), list);
1891 }
1892 
1893 /*
1894  * Print a text line.  Also in silent mode ("ex -s").
1895  */
1896     void
1897 print_line(linenr_T lnum, int use_number, int list)
1898 {
1899     int		save_silent = silent_mode;
1900 
1901     /* apply :filter /pat/ */
1902     if (message_filtered(ml_get(lnum)))
1903 	return;
1904 
1905     msg_start();
1906     silent_mode = FALSE;
1907     info_message = TRUE;	/* use mch_msg(), not mch_errmsg() */
1908     print_line_no_prefix(lnum, use_number, list);
1909     if (save_silent)
1910     {
1911 	msg_putchar('\n');
1912 	cursor_on();		/* msg_start() switches it off */
1913 	out_flush();
1914 	silent_mode = save_silent;
1915     }
1916     info_message = FALSE;
1917 }
1918 
1919     int
1920 rename_buffer(char_u *new_fname)
1921 {
1922     char_u	*fname, *sfname, *xfname;
1923     buf_T	*buf;
1924 
1925     buf = curbuf;
1926     apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
1927     /* buffer changed, don't change name now */
1928     if (buf != curbuf)
1929 	return FAIL;
1930 #ifdef FEAT_EVAL
1931     if (aborting())	    /* autocmds may abort script processing */
1932 	return FAIL;
1933 #endif
1934     /*
1935      * The name of the current buffer will be changed.
1936      * A new (unlisted) buffer entry needs to be made to hold the old file
1937      * name, which will become the alternate file name.
1938      * But don't set the alternate file name if the buffer didn't have a
1939      * name.
1940      */
1941     fname = curbuf->b_ffname;
1942     sfname = curbuf->b_sfname;
1943     xfname = curbuf->b_fname;
1944     curbuf->b_ffname = NULL;
1945     curbuf->b_sfname = NULL;
1946     if (setfname(curbuf, new_fname, NULL, TRUE) == FAIL)
1947     {
1948 	curbuf->b_ffname = fname;
1949 	curbuf->b_sfname = sfname;
1950 	return FAIL;
1951     }
1952     curbuf->b_flags |= BF_NOTEDITED;
1953     if (xfname != NULL && *xfname != NUL)
1954     {
1955 	buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
1956 	if (buf != NULL && !cmdmod.keepalt)
1957 	    curwin->w_alt_fnum = buf->b_fnum;
1958     }
1959     vim_free(fname);
1960     vim_free(sfname);
1961     apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
1962 
1963     /* Change directories when the 'acd' option is set. */
1964     DO_AUTOCHDIR;
1965     return OK;
1966 }
1967 
1968 /*
1969  * ":file[!] [fname]".
1970  */
1971     void
1972 ex_file(exarg_T *eap)
1973 {
1974     /* ":0file" removes the file name.  Check for illegal uses ":3file",
1975      * "0file name", etc. */
1976     if (eap->addr_count > 0
1977 	    && (*eap->arg != NUL
1978 		|| eap->line2 > 0
1979 		|| eap->addr_count > 1))
1980     {
1981 	emsg(_(e_invarg));
1982 	return;
1983     }
1984 
1985     if (*eap->arg != NUL || eap->addr_count == 1)
1986     {
1987 	if (rename_buffer(eap->arg) == FAIL)
1988 	    return;
1989 	redraw_tabline = TRUE;
1990     }
1991 
1992     // print file name if no argument or 'F' is not in 'shortmess'
1993     if (*eap->arg == NUL || !shortmess(SHM_FILEINFO))
1994 	fileinfo(FALSE, FALSE, eap->forceit);
1995 }
1996 
1997 /*
1998  * ":update".
1999  */
2000     void
2001 ex_update(exarg_T *eap)
2002 {
2003     if (curbufIsChanged())
2004 	(void)do_write(eap);
2005 }
2006 
2007 /*
2008  * ":write" and ":saveas".
2009  */
2010     void
2011 ex_write(exarg_T *eap)
2012 {
2013     if (eap->cmdidx == CMD_saveas)
2014     {
2015 	// :saveas does not take a range, uses all lines.
2016 	eap->line1 = 1;
2017 	eap->line2 = curbuf->b_ml.ml_line_count;
2018     }
2019 
2020     if (eap->usefilter)		/* input lines to shell command */
2021 	do_bang(1, eap, FALSE, TRUE, FALSE);
2022     else
2023 	(void)do_write(eap);
2024 }
2025 
2026 /*
2027  * write current buffer to file 'eap->arg'
2028  * if 'eap->append' is TRUE, append to the file
2029  *
2030  * if *eap->arg == NUL write to current file
2031  *
2032  * return FAIL for failure, OK otherwise
2033  */
2034     int
2035 do_write(exarg_T *eap)
2036 {
2037     int		other;
2038     char_u	*fname = NULL;		/* init to shut up gcc */
2039     char_u	*ffname;
2040     int		retval = FAIL;
2041     char_u	*free_fname = NULL;
2042 #ifdef FEAT_BROWSE
2043     char_u	*browse_file = NULL;
2044 #endif
2045     buf_T	*alt_buf = NULL;
2046     int		name_was_missing;
2047 
2048     if (not_writing())		/* check 'write' option */
2049 	return FAIL;
2050 
2051     ffname = eap->arg;
2052 #ifdef FEAT_BROWSE
2053     if (cmdmod.browse && !exiting)
2054     {
2055 	browse_file = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), ffname,
2056 						    NULL, NULL, NULL, curbuf);
2057 	if (browse_file == NULL)
2058 	    goto theend;
2059 	ffname = browse_file;
2060     }
2061 #endif
2062     if (*ffname == NUL)
2063     {
2064 	if (eap->cmdidx == CMD_saveas)
2065 	{
2066 	    emsg(_(e_argreq));
2067 	    goto theend;
2068 	}
2069 	other = FALSE;
2070     }
2071     else
2072     {
2073 	fname = ffname;
2074 	free_fname = fix_fname(ffname);
2075 	/*
2076 	 * When out-of-memory, keep unexpanded file name, because we MUST be
2077 	 * able to write the file in this situation.
2078 	 */
2079 	if (free_fname != NULL)
2080 	    ffname = free_fname;
2081 	other = otherfile(ffname);
2082     }
2083 
2084     /*
2085      * If we have a new file, put its name in the list of alternate file names.
2086      */
2087     if (other)
2088     {
2089 	if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
2090 						 || eap->cmdidx == CMD_saveas)
2091 	    alt_buf = setaltfname(ffname, fname, (linenr_T)1);
2092 	else
2093 	    alt_buf = buflist_findname(ffname);
2094 	if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL)
2095 	{
2096 	    /* Overwriting a file that is loaded in another buffer is not a
2097 	     * good idea. */
2098 	    emsg(_(e_bufloaded));
2099 	    goto theend;
2100 	}
2101     }
2102 
2103     /*
2104      * Writing to the current file is not allowed in readonly mode
2105      * and a file name is required.
2106      * "nofile" and "nowrite" buffers cannot be written implicitly either.
2107      */
2108     if (!other && (
2109 #ifdef FEAT_QUICKFIX
2110 		bt_dontwrite_msg(curbuf) ||
2111 #endif
2112 		check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
2113 	goto theend;
2114 
2115     if (!other)
2116     {
2117 	ffname = curbuf->b_ffname;
2118 	fname = curbuf->b_fname;
2119 	/*
2120 	 * Not writing the whole file is only allowed with '!'.
2121 	 */
2122 	if (	   (eap->line1 != 1
2123 		    || eap->line2 != curbuf->b_ml.ml_line_count)
2124 		&& !eap->forceit
2125 		&& !eap->append
2126 		&& !p_wa)
2127 	{
2128 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2129 	    if (p_confirm || cmdmod.confirm)
2130 	    {
2131 		if (vim_dialog_yesno(VIM_QUESTION, NULL,
2132 			       (char_u *)_("Write partial file?"), 2) != VIM_YES)
2133 		    goto theend;
2134 		eap->forceit = TRUE;
2135 	    }
2136 	    else
2137 #endif
2138 	    {
2139 		emsg(_("E140: Use ! to write partial buffer"));
2140 		goto theend;
2141 	    }
2142 	}
2143     }
2144 
2145     if (check_overwrite(eap, curbuf, fname, ffname, other) == OK)
2146     {
2147 	if (eap->cmdidx == CMD_saveas && alt_buf != NULL)
2148 	{
2149 	    buf_T	*was_curbuf = curbuf;
2150 
2151 	    apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
2152 	    apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, alt_buf);
2153 #ifdef FEAT_EVAL
2154 	    if (curbuf != was_curbuf || aborting())
2155 #else
2156 	    if (curbuf != was_curbuf)
2157 #endif
2158 	    {
2159 		/* buffer changed, don't change name now */
2160 		retval = FAIL;
2161 		goto theend;
2162 	    }
2163 	    /* Exchange the file names for the current and the alternate
2164 	     * buffer.  This makes it look like we are now editing the buffer
2165 	     * under the new name.  Must be done before buf_write(), because
2166 	     * if there is no file name and 'cpo' contains 'F', it will set
2167 	     * the file name. */
2168 	    fname = alt_buf->b_fname;
2169 	    alt_buf->b_fname = curbuf->b_fname;
2170 	    curbuf->b_fname = fname;
2171 	    fname = alt_buf->b_ffname;
2172 	    alt_buf->b_ffname = curbuf->b_ffname;
2173 	    curbuf->b_ffname = fname;
2174 	    fname = alt_buf->b_sfname;
2175 	    alt_buf->b_sfname = curbuf->b_sfname;
2176 	    curbuf->b_sfname = fname;
2177 	    buf_name_changed(curbuf);
2178 
2179 	    apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
2180 	    apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, alt_buf);
2181 	    if (!alt_buf->b_p_bl)
2182 	    {
2183 		alt_buf->b_p_bl = TRUE;
2184 		apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, alt_buf);
2185 	    }
2186 #ifdef FEAT_EVAL
2187 	    if (curbuf != was_curbuf || aborting())
2188 #else
2189 	    if (curbuf != was_curbuf)
2190 #endif
2191 	    {
2192 		/* buffer changed, don't write the file */
2193 		retval = FAIL;
2194 		goto theend;
2195 	    }
2196 
2197 	    /* If 'filetype' was empty try detecting it now. */
2198 	    if (*curbuf->b_p_ft == NUL)
2199 	    {
2200 		if (au_has_group((char_u *)"filetypedetect"))
2201 		    (void)do_doautocmd((char_u *)"filetypedetect BufRead",
2202 								  TRUE, NULL);
2203 		do_modelines(0);
2204 	    }
2205 
2206 	    /* Autocommands may have changed buffer names, esp. when
2207 	     * 'autochdir' is set. */
2208 	    fname = curbuf->b_sfname;
2209 	}
2210 
2211 	name_was_missing = curbuf->b_ffname == NULL;
2212 
2213 	retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
2214 				 eap, eap->append, eap->forceit, TRUE, FALSE);
2215 
2216 	/* After ":saveas fname" reset 'readonly'. */
2217 	if (eap->cmdidx == CMD_saveas)
2218 	{
2219 	    if (retval == OK)
2220 	    {
2221 		curbuf->b_p_ro = FALSE;
2222 		redraw_tabline = TRUE;
2223 	    }
2224 	}
2225 
2226 	/* Change directories when the 'acd' option is set and the file name
2227 	 * got changed or set. */
2228 	if (eap->cmdidx == CMD_saveas || name_was_missing)
2229 	    DO_AUTOCHDIR;
2230     }
2231 
2232 theend:
2233 #ifdef FEAT_BROWSE
2234     vim_free(browse_file);
2235 #endif
2236     vim_free(free_fname);
2237     return retval;
2238 }
2239 
2240 /*
2241  * Check if it is allowed to overwrite a file.  If b_flags has BF_NOTEDITED,
2242  * BF_NEW or BF_READERR, check for overwriting current file.
2243  * May set eap->forceit if a dialog says it's OK to overwrite.
2244  * Return OK if it's OK, FAIL if it is not.
2245  */
2246     int
2247 check_overwrite(
2248     exarg_T	*eap,
2249     buf_T	*buf,
2250     char_u	*fname,	    /* file name to be used (can differ from
2251 			       buf->ffname) */
2252     char_u	*ffname,    /* full path version of fname */
2253     int		other)	    /* writing under other name */
2254 {
2255     /*
2256      * write to other file or b_flags set or not writing the whole file:
2257      * overwriting only allowed with '!'
2258      */
2259     if (       (other
2260 		|| (buf->b_flags & BF_NOTEDITED)
2261 		|| ((buf->b_flags & BF_NEW)
2262 		    && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
2263 		|| (buf->b_flags & BF_READERR))
2264 	    && !p_wa
2265 #ifdef FEAT_QUICKFIX
2266 	    && !bt_nofilename(buf)
2267 #endif
2268 	    && vim_fexists(ffname))
2269     {
2270 	if (!eap->forceit && !eap->append)
2271 	{
2272 #ifdef UNIX
2273 	    /* with UNIX it is possible to open a directory */
2274 	    if (mch_isdir(ffname))
2275 	    {
2276 		semsg(_(e_isadir2), ffname);
2277 		return FAIL;
2278 	    }
2279 #endif
2280 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2281 	    if (p_confirm || cmdmod.confirm)
2282 	    {
2283 		char_u	buff[DIALOG_MSG_SIZE];
2284 
2285 		dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname);
2286 		if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES)
2287 		    return FAIL;
2288 		eap->forceit = TRUE;
2289 	    }
2290 	    else
2291 #endif
2292 	    {
2293 		emsg(_(e_exists));
2294 		return FAIL;
2295 	    }
2296 	}
2297 
2298 	/* For ":w! filename" check that no swap file exists for "filename". */
2299 	if (other && !emsg_silent)
2300 	{
2301 	    char_u	*dir;
2302 	    char_u	*p;
2303 	    int		r;
2304 	    char_u	*swapname;
2305 
2306 	    /* We only try the first entry in 'directory', without checking if
2307 	     * it's writable.  If the "." directory is not writable the write
2308 	     * will probably fail anyway.
2309 	     * Use 'shortname' of the current buffer, since there is no buffer
2310 	     * for the written file. */
2311 	    if (*p_dir == NUL)
2312 	    {
2313 		dir = alloc(5);
2314 		if (dir == NULL)
2315 		    return FAIL;
2316 		STRCPY(dir, ".");
2317 	    }
2318 	    else
2319 	    {
2320 		dir = alloc(MAXPATHL);
2321 		if (dir == NULL)
2322 		    return FAIL;
2323 		p = p_dir;
2324 		copy_option_part(&p, dir, MAXPATHL, ",");
2325 	    }
2326 	    swapname = makeswapname(fname, ffname, curbuf, dir);
2327 	    vim_free(dir);
2328 	    r = vim_fexists(swapname);
2329 	    if (r)
2330 	    {
2331 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2332 		if (p_confirm || cmdmod.confirm)
2333 		{
2334 		    char_u	buff[DIALOG_MSG_SIZE];
2335 
2336 		    dialog_msg(buff,
2337 			    _("Swap file \"%s\" exists, overwrite anyway?"),
2338 								    swapname);
2339 		    if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2)
2340 								   != VIM_YES)
2341 		    {
2342 			vim_free(swapname);
2343 			return FAIL;
2344 		    }
2345 		    eap->forceit = TRUE;
2346 		}
2347 		else
2348 #endif
2349 		{
2350 		    semsg(_("E768: Swap file exists: %s (:silent! overrides)"),
2351 								    swapname);
2352 		    vim_free(swapname);
2353 		    return FAIL;
2354 		}
2355 	    }
2356 	    vim_free(swapname);
2357 	}
2358     }
2359     return OK;
2360 }
2361 
2362 /*
2363  * Handle ":wnext", ":wNext" and ":wprevious" commands.
2364  */
2365     void
2366 ex_wnext(exarg_T *eap)
2367 {
2368     int		i;
2369 
2370     if (eap->cmd[1] == 'n')
2371 	i = curwin->w_arg_idx + (int)eap->line2;
2372     else
2373 	i = curwin->w_arg_idx - (int)eap->line2;
2374     eap->line1 = 1;
2375     eap->line2 = curbuf->b_ml.ml_line_count;
2376     if (do_write(eap) != FAIL)
2377 	do_argfile(eap, i);
2378 }
2379 
2380 /*
2381  * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
2382  */
2383     void
2384 do_wqall(exarg_T *eap)
2385 {
2386     buf_T	*buf;
2387     int		error = 0;
2388     int		save_forceit = eap->forceit;
2389 
2390     if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall)
2391 	exiting = TRUE;
2392 
2393     FOR_ALL_BUFFERS(buf)
2394     {
2395 #ifdef FEAT_TERMINAL
2396 	if (exiting && term_job_running(buf->b_term))
2397 	{
2398 	    no_write_message_nobang(buf);
2399 	    ++error;
2400 	}
2401 	else
2402 #endif
2403 	if (bufIsChanged(buf) && !bt_dontwrite(buf))
2404 	{
2405 	    /*
2406 	     * Check if there is a reason the buffer cannot be written:
2407 	     * 1. if the 'write' option is set
2408 	     * 2. if there is no file name (even after browsing)
2409 	     * 3. if the 'readonly' is set (even after a dialog)
2410 	     * 4. if overwriting is allowed (even after a dialog)
2411 	     */
2412 	    if (not_writing())
2413 	    {
2414 		++error;
2415 		break;
2416 	    }
2417 #ifdef FEAT_BROWSE
2418 	    /* ":browse wall": ask for file name if there isn't one */
2419 	    if (buf->b_ffname == NULL && cmdmod.browse)
2420 		browse_save_fname(buf);
2421 #endif
2422 	    if (buf->b_ffname == NULL)
2423 	    {
2424 		semsg(_("E141: No file name for buffer %ld"), (long)buf->b_fnum);
2425 		++error;
2426 	    }
2427 	    else if (check_readonly(&eap->forceit, buf)
2428 		    || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname,
2429 							       FALSE) == FAIL)
2430 	    {
2431 		++error;
2432 	    }
2433 	    else
2434 	    {
2435 		bufref_T bufref;
2436 
2437 		set_bufref(&bufref, buf);
2438 		if (buf_write_all(buf, eap->forceit) == FAIL)
2439 		    ++error;
2440 		/* an autocommand may have deleted the buffer */
2441 		if (!bufref_valid(&bufref))
2442 		    buf = firstbuf;
2443 	    }
2444 	    eap->forceit = save_forceit;    /* check_overwrite() may set it */
2445 	}
2446     }
2447     if (exiting)
2448     {
2449 	if (!error)
2450 	    getout(0);		/* exit Vim */
2451 	not_exiting();
2452     }
2453 }
2454 
2455 /*
2456  * Check the 'write' option.
2457  * Return TRUE and give a message when it's not set.
2458  */
2459     int
2460 not_writing(void)
2461 {
2462     if (p_write)
2463 	return FALSE;
2464     emsg(_("E142: File not written: Writing is disabled by 'write' option"));
2465     return TRUE;
2466 }
2467 
2468 /*
2469  * Check if a buffer is read-only (either 'readonly' option is set or file is
2470  * read-only). Ask for overruling in a dialog. Return TRUE and give an error
2471  * message when the buffer is readonly.
2472  */
2473     static int
2474 check_readonly(int *forceit, buf_T *buf)
2475 {
2476     stat_T	st;
2477 
2478     /* Handle a file being readonly when the 'readonly' option is set or when
2479      * the file exists and permissions are read-only.
2480      * We will send 0777 to check_file_readonly(), as the "perm" variable is
2481      * important for device checks but not here. */
2482     if (!*forceit && (buf->b_p_ro
2483 		|| (mch_stat((char *)buf->b_ffname, &st) >= 0
2484 		    && check_file_readonly(buf->b_ffname, 0777))))
2485     {
2486 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2487 	if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL)
2488 	{
2489 	    char_u	buff[DIALOG_MSG_SIZE];
2490 
2491 	    if (buf->b_p_ro)
2492 		dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
2493 		    buf->b_fname);
2494 	    else
2495 		dialog_msg(buff, _("File permissions of \"%s\" are read-only.\nIt may still be possible to write it.\nDo you wish to try?"),
2496 		    buf->b_fname);
2497 
2498 	    if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES)
2499 	    {
2500 		/* Set forceit, to force the writing of a readonly file */
2501 		*forceit = TRUE;
2502 		return FALSE;
2503 	    }
2504 	    else
2505 		return TRUE;
2506 	}
2507 	else
2508 #endif
2509 	if (buf->b_p_ro)
2510 	    emsg(_(e_readonly));
2511 	else
2512 	    semsg(_("E505: \"%s\" is read-only (add ! to override)"),
2513 		    buf->b_fname);
2514 	return TRUE;
2515     }
2516 
2517     return FALSE;
2518 }
2519 
2520 /*
2521  * Try to abandon the current file and edit a new or existing file.
2522  * "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg".
2523  * "lnum" is the line number for the cursor in the new file (if non-zero).
2524  *
2525  * Return:
2526  * GETFILE_ERROR for "normal" error,
2527  * GETFILE_NOT_WRITTEN for "not written" error,
2528  * GETFILE_SAME_FILE for success
2529  * GETFILE_OPEN_OTHER for successfully opening another file.
2530  */
2531     int
2532 getfile(
2533     int		fnum,
2534     char_u	*ffname_arg,
2535     char_u	*sfname_arg,
2536     int		setpm,
2537     linenr_T	lnum,
2538     int		forceit)
2539 {
2540     char_u	*ffname = ffname_arg;
2541     char_u	*sfname = sfname_arg;
2542     int		other;
2543     int		retval;
2544     char_u	*free_me = NULL;
2545 
2546     if (text_locked())
2547 	return GETFILE_ERROR;
2548     if (curbuf_locked())
2549 	return GETFILE_ERROR;
2550 
2551     if (fnum == 0)
2552     {
2553 					/* make ffname full path, set sfname */
2554 	fname_expand(curbuf, &ffname, &sfname);
2555 	other = otherfile(ffname);
2556 	free_me = ffname;		/* has been allocated, free() later */
2557     }
2558     else
2559 	other = (fnum != curbuf->b_fnum);
2560 
2561     if (other)
2562 	++no_wait_return;	    /* don't wait for autowrite message */
2563     if (other && !forceit && curbuf->b_nwindows == 1 && !buf_hide(curbuf)
2564 		   && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
2565     {
2566 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2567 	if (p_confirm && p_write)
2568 	    dialog_changed(curbuf, FALSE);
2569 	if (curbufIsChanged())
2570 #endif
2571 	{
2572 	    if (other)
2573 		--no_wait_return;
2574 	    no_write_message();
2575 	    retval = GETFILE_NOT_WRITTEN;	/* file has been changed */
2576 	    goto theend;
2577 	}
2578     }
2579     if (other)
2580 	--no_wait_return;
2581     if (setpm)
2582 	setpcmark();
2583     if (!other)
2584     {
2585 	if (lnum != 0)
2586 	    curwin->w_cursor.lnum = lnum;
2587 	check_cursor_lnum();
2588 	beginline(BL_SOL | BL_FIX);
2589 	retval = GETFILE_SAME_FILE;	/* it's in the same file */
2590     }
2591     else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
2592 	     (buf_hide(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0),
2593 		curwin) == OK)
2594 	retval = GETFILE_OPEN_OTHER;	/* opened another file */
2595     else
2596 	retval = GETFILE_ERROR;		/* error encountered */
2597 
2598 theend:
2599     vim_free(free_me);
2600     return retval;
2601 }
2602 
2603 /*
2604  * start editing a new file
2605  *
2606  *     fnum: file number; if zero use ffname/sfname
2607  *   ffname: the file name
2608  *		- full path if sfname used,
2609  *		- any file name if sfname is NULL
2610  *		- empty string to re-edit with the same file name (but may be
2611  *		    in a different directory)
2612  *		- NULL to start an empty buffer
2613  *   sfname: the short file name (or NULL)
2614  *	eap: contains the command to be executed after loading the file and
2615  *	     forced 'ff' and 'fenc'
2616  *  newlnum: if > 0: put cursor on this line number (if possible)
2617  *	     if ECMD_LASTL: use last position in loaded file
2618  *	     if ECMD_LAST: use last position in all files
2619  *	     if ECMD_ONE: use first line
2620  *    flags:
2621  *	   ECMD_HIDE: if TRUE don't free the current buffer
2622  *     ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
2623  *	 ECMD_OLDBUF: use existing buffer if it exists
2624  *	ECMD_FORCEIT: ! used for Ex command
2625  *	 ECMD_ADDBUF: don't edit, just add to buffer list
2626  *   oldwin: Should be "curwin" when editing a new buffer in the current
2627  *	     window, NULL when splitting the window first.  When not NULL info
2628  *	     of the previous buffer for "oldwin" is stored.
2629  *
2630  * return FAIL for failure, OK otherwise
2631  */
2632     int
2633 do_ecmd(
2634     int		fnum,
2635     char_u	*ffname,
2636     char_u	*sfname,
2637     exarg_T	*eap,			/* can be NULL! */
2638     linenr_T	newlnum,
2639     int		flags,
2640     win_T	*oldwin)
2641 {
2642     int		other_file;		/* TRUE if editing another file */
2643     int		oldbuf;			/* TRUE if using existing buffer */
2644     int		auto_buf = FALSE;	/* TRUE if autocommands brought us
2645 					   into the buffer unexpectedly */
2646     char_u	*new_name = NULL;
2647 #if defined(FEAT_EVAL)
2648     int		did_set_swapcommand = FALSE;
2649 #endif
2650     buf_T	*buf;
2651     bufref_T	bufref;
2652     bufref_T	old_curbuf;
2653     char_u	*free_fname = NULL;
2654 #ifdef FEAT_BROWSE
2655     char_u	*browse_file = NULL;
2656 #endif
2657     int		retval = FAIL;
2658     long	n;
2659     pos_T	orig_pos;
2660     linenr_T	topline = 0;
2661     int		newcol = -1;
2662     int		solcol = -1;
2663     pos_T	*pos;
2664     char_u	*command = NULL;
2665 #ifdef FEAT_SPELL
2666     int		did_get_winopts = FALSE;
2667 #endif
2668     int		readfile_flags = 0;
2669     int		did_inc_redrawing_disabled = FALSE;
2670     long        *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
2671 
2672     if (eap != NULL)
2673 	command = eap->do_ecmd_cmd;
2674     set_bufref(&old_curbuf, curbuf);
2675 
2676     if (fnum != 0)
2677     {
2678 	if (fnum == curbuf->b_fnum)	/* file is already being edited */
2679 	    return OK;			/* nothing to do */
2680 	other_file = TRUE;
2681     }
2682     else
2683     {
2684 #ifdef FEAT_BROWSE
2685 	if (cmdmod.browse && !exiting)
2686 	{
2687 	    if (
2688 # ifdef FEAT_GUI
2689 		!gui.in_use &&
2690 # endif
2691 		    au_has_group((char_u *)"FileExplorer"))
2692 	    {
2693 		/* No browsing supported but we do have the file explorer:
2694 		 * Edit the directory. */
2695 		if (ffname == NULL || !mch_isdir(ffname))
2696 		    ffname = (char_u *)".";
2697 	    }
2698 	    else
2699 	    {
2700 		browse_file = do_browse(0, (char_u *)_("Edit File"), ffname,
2701 						    NULL, NULL, NULL, curbuf);
2702 		if (browse_file == NULL)
2703 		    goto theend;
2704 		ffname = browse_file;
2705 	    }
2706 	}
2707 #endif
2708 	/* if no short name given, use ffname for short name */
2709 	if (sfname == NULL)
2710 	    sfname = ffname;
2711 #ifdef USE_FNAME_CASE
2712 	if (sfname != NULL)
2713 	    fname_case(sfname, 0);   /* set correct case for sfname */
2714 #endif
2715 
2716 	if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
2717 	    goto theend;
2718 
2719 	if (ffname == NULL)
2720 	    other_file = TRUE;
2721 					    /* there is no file name */
2722 	else if (*ffname == NUL && curbuf->b_ffname == NULL)
2723 	    other_file = FALSE;
2724 	else
2725 	{
2726 	    if (*ffname == NUL)		    /* re-edit with same file name */
2727 	    {
2728 		ffname = curbuf->b_ffname;
2729 		sfname = curbuf->b_fname;
2730 	    }
2731 	    free_fname = fix_fname(ffname); /* may expand to full path name */
2732 	    if (free_fname != NULL)
2733 		ffname = free_fname;
2734 	    other_file = otherfile(ffname);
2735 	}
2736     }
2737 
2738     /*
2739      * if the file was changed we may not be allowed to abandon it
2740      * - if we are going to re-edit the same file
2741      * - or if we are the only window on this file and if ECMD_HIDE is FALSE
2742      */
2743     if (  ((!other_file && !(flags & ECMD_OLDBUF))
2744 	    || (curbuf->b_nwindows == 1
2745 		&& !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
2746 	&& check_changed(curbuf, (p_awa ? CCGD_AW : 0)
2747 			       | (other_file ? 0 : CCGD_MULTWIN)
2748 			       | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0)
2749 			       | (eap == NULL ? 0 : CCGD_EXCMD)))
2750     {
2751 	if (fnum == 0 && other_file && ffname != NULL)
2752 	    (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
2753 	goto theend;
2754     }
2755 
2756     /*
2757      * End Visual mode before switching to another buffer, so the text can be
2758      * copied into the GUI selection buffer.
2759      */
2760     reset_VIsual();
2761 
2762 #if defined(FEAT_EVAL)
2763     if ((command != NULL || newlnum > (linenr_T)0)
2764 	    && *get_vim_var_str(VV_SWAPCOMMAND) == NUL)
2765     {
2766 	int	len;
2767 	char_u	*p;
2768 
2769 	/* Set v:swapcommand for the SwapExists autocommands. */
2770 	if (command != NULL)
2771 	    len = (int)STRLEN(command) + 3;
2772 	else
2773 	    len = 30;
2774 	p = alloc(len);
2775 	if (p != NULL)
2776 	{
2777 	    if (command != NULL)
2778 		vim_snprintf((char *)p, len, ":%s\r", command);
2779 	    else
2780 		vim_snprintf((char *)p, len, "%ldG", (long)newlnum);
2781 	    set_vim_var_string(VV_SWAPCOMMAND, p, -1);
2782 	    did_set_swapcommand = TRUE;
2783 	    vim_free(p);
2784 	}
2785     }
2786 #endif
2787 
2788     /*
2789      * If we are starting to edit another file, open a (new) buffer.
2790      * Otherwise we re-use the current buffer.
2791      */
2792     if (other_file)
2793     {
2794 	if (!(flags & ECMD_ADDBUF))
2795 	{
2796 	    if (!cmdmod.keepalt)
2797 		curwin->w_alt_fnum = curbuf->b_fnum;
2798 	    if (oldwin != NULL)
2799 		buflist_altfpos(oldwin);
2800 	}
2801 
2802 	if (fnum)
2803 	    buf = buflist_findnr(fnum);
2804 	else
2805 	{
2806 	    if (flags & ECMD_ADDBUF)
2807 	    {
2808 		linenr_T	tlnum = 1L;
2809 
2810 		if (command != NULL)
2811 		{
2812 		    tlnum = atol((char *)command);
2813 		    if (tlnum <= 0)
2814 			tlnum = 1L;
2815 		}
2816 		(void)buflist_new(ffname, sfname, tlnum, BLN_LISTED);
2817 		goto theend;
2818 	    }
2819 	    buf = buflist_new(ffname, sfname, 0L,
2820 		    BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
2821 
2822 	    /* autocommands may change curwin and curbuf */
2823 	    if (oldwin != NULL)
2824 		oldwin = curwin;
2825 	    set_bufref(&old_curbuf, curbuf);
2826 	}
2827 	if (buf == NULL)
2828 	    goto theend;
2829 	if (buf->b_ml.ml_mfp == NULL)		/* no memfile yet */
2830 	{
2831 	    oldbuf = FALSE;
2832 	}
2833 	else					/* existing memfile */
2834 	{
2835 	    oldbuf = TRUE;
2836 	    set_bufref(&bufref, buf);
2837 	    (void)buf_check_timestamp(buf, FALSE);
2838 	    /* Check if autocommands made the buffer invalid or changed the
2839 	     * current buffer. */
2840 	    if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf)
2841 		goto theend;
2842 #ifdef FEAT_EVAL
2843 	    if (aborting())	    /* autocmds may abort script processing */
2844 		goto theend;
2845 #endif
2846 	}
2847 
2848 	/* May jump to last used line number for a loaded buffer or when asked
2849 	 * for explicitly */
2850 	if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST)
2851 	{
2852 	    pos = buflist_findfpos(buf);
2853 	    newlnum = pos->lnum;
2854 	    solcol = pos->col;
2855 	}
2856 
2857 	/*
2858 	 * Make the (new) buffer the one used by the current window.
2859 	 * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
2860 	 * If the current buffer was empty and has no file name, curbuf
2861 	 * is returned by buflist_new(), nothing to do here.
2862 	 */
2863 	if (buf != curbuf)
2864 	{
2865 	    /*
2866 	     * Be careful: The autocommands may delete any buffer and change
2867 	     * the current buffer.
2868 	     * - If the buffer we are going to edit is deleted, give up.
2869 	     * - If the current buffer is deleted, prefer to load the new
2870 	     *   buffer when loading a buffer is required.  This avoids
2871 	     *   loading another buffer which then must be closed again.
2872 	     * - If we ended up in the new buffer already, need to skip a few
2873 	     *	 things, set auto_buf.
2874 	     */
2875 	    if (buf->b_fname != NULL)
2876 		new_name = vim_strsave(buf->b_fname);
2877 	    set_bufref(&au_new_curbuf, buf);
2878 	    apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
2879 	    if (!bufref_valid(&au_new_curbuf))
2880 	    {
2881 		/* new buffer has been deleted */
2882 		delbuf_msg(new_name);	/* frees new_name */
2883 		goto theend;
2884 	    }
2885 #ifdef FEAT_EVAL
2886 	    if (aborting())	    /* autocmds may abort script processing */
2887 	    {
2888 		vim_free(new_name);
2889 		goto theend;
2890 	    }
2891 #endif
2892 	    if (buf == curbuf)		/* already in new buffer */
2893 		auto_buf = TRUE;
2894 	    else
2895 	    {
2896 		win_T	    *the_curwin = curwin;
2897 
2898 		/* Set the w_closing flag to avoid that autocommands close the
2899 		 * window.  And set b_locked for the same reason. */
2900 		the_curwin->w_closing = TRUE;
2901 		++buf->b_locked;
2902 
2903 		if (curbuf == old_curbuf.br_buf)
2904 		    buf_copy_options(buf, BCO_ENTER);
2905 
2906 		/* Close the link to the current buffer. This will set
2907 		 * oldwin->w_buffer to NULL. */
2908 		u_sync(FALSE);
2909 		close_buffer(oldwin, curbuf,
2910 			       (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE);
2911 
2912 		the_curwin->w_closing = FALSE;
2913 		--buf->b_locked;
2914 
2915 #ifdef FEAT_EVAL
2916 		/* autocmds may abort script processing */
2917 		if (aborting() && curwin->w_buffer != NULL)
2918 		{
2919 		    vim_free(new_name);
2920 		    goto theend;
2921 		}
2922 #endif
2923 		/* Be careful again, like above. */
2924 		if (!bufref_valid(&au_new_curbuf))
2925 		{
2926 		    /* new buffer has been deleted */
2927 		    delbuf_msg(new_name);	/* frees new_name */
2928 		    goto theend;
2929 		}
2930 		if (buf == curbuf)		/* already in new buffer */
2931 		    auto_buf = TRUE;
2932 		else
2933 		{
2934 #ifdef FEAT_SYN_HL
2935 		    /*
2936 		     * <VN> We could instead free the synblock
2937 		     * and re-attach to buffer, perhaps.
2938 		     */
2939 		    if (curwin->w_buffer == NULL
2940 			    || curwin->w_s == &(curwin->w_buffer->b_s))
2941 			curwin->w_s = &(buf->b_s);
2942 #endif
2943 		    curwin->w_buffer = buf;
2944 		    curbuf = buf;
2945 		    ++curbuf->b_nwindows;
2946 
2947 		    /* Set 'fileformat', 'binary' and 'fenc' when forced. */
2948 		    if (!oldbuf && eap != NULL)
2949 		    {
2950 			set_file_options(TRUE, eap);
2951 			set_forced_fenc(eap);
2952 		    }
2953 		}
2954 
2955 		/* May get the window options from the last time this buffer
2956 		 * was in this window (or another window).  If not used
2957 		 * before, reset the local window options to the global
2958 		 * values.  Also restores old folding stuff. */
2959 		get_winopts(curbuf);
2960 #ifdef FEAT_SPELL
2961 		did_get_winopts = TRUE;
2962 #endif
2963 	    }
2964 	    vim_free(new_name);
2965 	    au_new_curbuf.br_buf = NULL;
2966 	    au_new_curbuf.br_buf_free_count = 0;
2967 	}
2968 
2969 	curwin->w_pcmark.lnum = 1;
2970 	curwin->w_pcmark.col = 0;
2971     }
2972     else /* !other_file */
2973     {
2974 	if ((flags & ECMD_ADDBUF) || check_fname() == FAIL)
2975 	    goto theend;
2976 
2977 	oldbuf = (flags & ECMD_OLDBUF);
2978     }
2979 
2980     /* Don't redraw until the cursor is in the right line, otherwise
2981      * autocommands may cause ml_get errors. */
2982     ++RedrawingDisabled;
2983     did_inc_redrawing_disabled = TRUE;
2984 
2985     buf = curbuf;
2986     if ((flags & ECMD_SET_HELP) || keep_help_flag)
2987     {
2988 	prepare_help_buffer();
2989     }
2990     else
2991     {
2992 	/* Don't make a buffer listed if it's a help buffer.  Useful when
2993 	 * using CTRL-O to go back to a help file. */
2994 	if (!curbuf->b_help)
2995 	    set_buflisted(TRUE);
2996     }
2997 
2998     /* If autocommands change buffers under our fingers, forget about
2999      * editing the file. */
3000     if (buf != curbuf)
3001 	goto theend;
3002 #ifdef FEAT_EVAL
3003     if (aborting())	    /* autocmds may abort script processing */
3004 	goto theend;
3005 #endif
3006 
3007     /* Since we are starting to edit a file, consider the filetype to be
3008      * unset.  Helps for when an autocommand changes files and expects syntax
3009      * highlighting to work in the other file. */
3010     did_filetype = FALSE;
3011 
3012 /*
3013  * other_file	oldbuf
3014  *  FALSE	FALSE	    re-edit same file, buffer is re-used
3015  *  FALSE	TRUE	    re-edit same file, nothing changes
3016  *  TRUE	FALSE	    start editing new file, new buffer
3017  *  TRUE	TRUE	    start editing in existing buffer (nothing to do)
3018  */
3019     if (!other_file && !oldbuf)		/* re-use the buffer */
3020     {
3021 	set_last_cursor(curwin);	/* may set b_last_cursor */
3022 	if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL)
3023 	{
3024 	    newlnum = curwin->w_cursor.lnum;
3025 	    solcol = curwin->w_cursor.col;
3026 	}
3027 	buf = curbuf;
3028 	if (buf->b_fname != NULL)
3029 	    new_name = vim_strsave(buf->b_fname);
3030 	else
3031 	    new_name = NULL;
3032 	set_bufref(&bufref, buf);
3033 
3034 	if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)
3035 	{
3036 	    /* Save all the text, so that the reload can be undone.
3037 	     * Sync first so that this is a separate undo-able action. */
3038 	    u_sync(FALSE);
3039 	    if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE)
3040 								     == FAIL)
3041 	    {
3042 		vim_free(new_name);
3043 		goto theend;
3044 	    }
3045 	    u_unchanged(curbuf);
3046 	    buf_freeall(curbuf, BFA_KEEP_UNDO);
3047 
3048 	    /* tell readfile() not to clear or reload undo info */
3049 	    readfile_flags = READ_KEEP_UNDO;
3050 	}
3051 	else
3052 	    buf_freeall(curbuf, 0);   /* free all things for buffer */
3053 
3054 	/* If autocommands deleted the buffer we were going to re-edit, give
3055 	 * up and jump to the end. */
3056 	if (!bufref_valid(&bufref))
3057 	{
3058 	    delbuf_msg(new_name);	/* frees new_name */
3059 	    goto theend;
3060 	}
3061 	vim_free(new_name);
3062 
3063 	/* If autocommands change buffers under our fingers, forget about
3064 	 * re-editing the file.  Should do the buf_clear_file(), but perhaps
3065 	 * the autocommands changed the buffer... */
3066 	if (buf != curbuf)
3067 	    goto theend;
3068 #ifdef FEAT_EVAL
3069 	if (aborting())	    /* autocmds may abort script processing */
3070 	    goto theend;
3071 #endif
3072 	buf_clear_file(curbuf);
3073 	curbuf->b_op_start.lnum = 0;	/* clear '[ and '] marks */
3074 	curbuf->b_op_end.lnum = 0;
3075     }
3076 
3077 /*
3078  * If we get here we are sure to start editing
3079  */
3080     /* Assume success now */
3081     retval = OK;
3082 
3083     /*
3084      * Check if we are editing the w_arg_idx file in the argument list.
3085      */
3086     check_arg_idx(curwin);
3087 
3088     if (!auto_buf)
3089     {
3090 	/*
3091 	 * Set cursor and init window before reading the file and executing
3092 	 * autocommands.  This allows for the autocommands to position the
3093 	 * cursor.
3094 	 */
3095 	curwin_init();
3096 
3097 #ifdef FEAT_FOLDING
3098 	/* It's possible that all lines in the buffer changed.  Need to update
3099 	 * automatic folding for all windows where it's used. */
3100 	{
3101 	    win_T	    *win;
3102 	    tabpage_T	    *tp;
3103 
3104 	    FOR_ALL_TAB_WINDOWS(tp, win)
3105 		if (win->w_buffer == curbuf)
3106 		    foldUpdateAll(win);
3107 	}
3108 #endif
3109 
3110 	/* Change directories when the 'acd' option is set. */
3111 	DO_AUTOCHDIR;
3112 
3113 	/*
3114 	 * Careful: open_buffer() and apply_autocmds() may change the current
3115 	 * buffer and window.
3116 	 */
3117 	orig_pos = curwin->w_cursor;
3118 	topline = curwin->w_topline;
3119 	if (!oldbuf)			    /* need to read the file */
3120 	{
3121 #ifdef FEAT_TEXT_PROP
3122 	    // Don't use the swap-exists dialog for a popup window, can't edit
3123 	    // the buffer.
3124 	    if (WIN_IS_POPUP(curwin))
3125 		curbuf->b_flags |= BF_NO_SEA;
3126 #endif
3127 	    swap_exists_action = SEA_DIALOG;
3128 	    curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
3129 
3130 	    /*
3131 	     * Open the buffer and read the file.
3132 	     */
3133 #if defined(FEAT_EVAL)
3134 	    if (should_abort(open_buffer(FALSE, eap, readfile_flags)))
3135 		retval = FAIL;
3136 #else
3137 	    (void)open_buffer(FALSE, eap, readfile_flags);
3138 #endif
3139 
3140 #ifdef FEAT_TEXT_PROP
3141 	    curbuf->b_flags &= ~BF_NO_SEA;
3142 #endif
3143 	    if (swap_exists_action == SEA_QUIT)
3144 		retval = FAIL;
3145 	    handle_swap_exists(&old_curbuf);
3146 	}
3147 	else
3148 	{
3149 	    /* Read the modelines, but only to set window-local options.  Any
3150 	     * buffer-local options have already been set and may have been
3151 	     * changed by the user. */
3152 	    do_modelines(OPT_WINONLY);
3153 
3154 	    apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf,
3155 								    &retval);
3156 	    apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
3157 								    &retval);
3158 	}
3159 	check_arg_idx(curwin);
3160 
3161 	/* If autocommands change the cursor position or topline, we should
3162 	 * keep it.  Also when it moves within a line. But not when it moves
3163 	 * to the first non-blank. */
3164 	if (!EQUAL_POS(curwin->w_cursor, orig_pos))
3165 	{
3166 	    char_u *text = ml_get_curline();
3167 
3168 	    if (curwin->w_cursor.lnum != orig_pos.lnum
3169 		    || curwin->w_cursor.col != (int)(skipwhite(text) - text))
3170 	    {
3171 		newlnum = curwin->w_cursor.lnum;
3172 		newcol = curwin->w_cursor.col;
3173 	    }
3174 	}
3175 	if (curwin->w_topline == topline)
3176 	    topline = 0;
3177 
3178 	/* Even when cursor didn't move we need to recompute topline. */
3179 	changed_line_abv_curs();
3180 
3181 #ifdef FEAT_TITLE
3182 	maketitle();
3183 #endif
3184 #ifdef FEAT_TEXT_PROP
3185 	if (WIN_IS_POPUP(curwin) && curwin->w_p_pvw && retval != FAIL)
3186 	    popup_set_title(curwin);
3187 #endif
3188     }
3189 
3190 #ifdef FEAT_DIFF
3191     /* Tell the diff stuff that this buffer is new and/or needs updating.
3192      * Also needed when re-editing the same buffer, because unloading will
3193      * have removed it as a diff buffer. */
3194     if (curwin->w_p_diff)
3195     {
3196 	diff_buf_add(curbuf);
3197 	diff_invalidate(curbuf);
3198     }
3199 #endif
3200 
3201 #ifdef FEAT_SPELL
3202     /* If the window options were changed may need to set the spell language.
3203      * Can only do this after the buffer has been properly setup. */
3204     if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
3205 	(void)did_set_spelllang(curwin);
3206 #endif
3207 
3208     if (command == NULL)
3209     {
3210 	if (newcol >= 0)	/* position set by autocommands */
3211 	{
3212 	    curwin->w_cursor.lnum = newlnum;
3213 	    curwin->w_cursor.col = newcol;
3214 	    check_cursor();
3215 	}
3216 	else if (newlnum > 0)	/* line number from caller or old position */
3217 	{
3218 	    curwin->w_cursor.lnum = newlnum;
3219 	    check_cursor_lnum();
3220 	    if (solcol >= 0 && !p_sol)
3221 	    {
3222 		/* 'sol' is off: Use last known column. */
3223 		curwin->w_cursor.col = solcol;
3224 		check_cursor_col();
3225 		curwin->w_cursor.coladd = 0;
3226 		curwin->w_set_curswant = TRUE;
3227 	    }
3228 	    else
3229 		beginline(BL_SOL | BL_FIX);
3230 	}
3231 	else			/* no line number, go to last line in Ex mode */
3232 	{
3233 	    if (exmode_active)
3234 		curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
3235 	    beginline(BL_WHITE | BL_FIX);
3236 	}
3237     }
3238 
3239     /* Check if cursors in other windows on the same buffer are still valid */
3240     check_lnums(FALSE);
3241 
3242     /*
3243      * Did not read the file, need to show some info about the file.
3244      * Do this after setting the cursor.
3245      */
3246     if (oldbuf && !auto_buf)
3247     {
3248 	int	msg_scroll_save = msg_scroll;
3249 
3250 	/* Obey the 'O' flag in 'cpoptions': overwrite any previous file
3251 	 * message. */
3252 	if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
3253 	    msg_scroll = FALSE;
3254 	if (!msg_scroll)	/* wait a bit when overwriting an error msg */
3255 	    check_for_delay(FALSE);
3256 	msg_start();
3257 	msg_scroll = msg_scroll_save;
3258 	msg_scrolled_ign = TRUE;
3259 
3260 	if (!shortmess(SHM_FILEINFO))
3261 	    fileinfo(FALSE, TRUE, FALSE);
3262 
3263 	msg_scrolled_ign = FALSE;
3264     }
3265 
3266 #ifdef FEAT_VIMINFO
3267     curbuf->b_last_used = vim_time();
3268 #endif
3269 
3270     if (command != NULL)
3271 	do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
3272 
3273 #ifdef FEAT_KEYMAP
3274     if (curbuf->b_kmap_state & KEYMAP_INIT)
3275 	(void)keymap_init();
3276 #endif
3277 
3278     --RedrawingDisabled;
3279     did_inc_redrawing_disabled = FALSE;
3280     if (!skip_redraw)
3281     {
3282 	n = *so_ptr;
3283 	if (topline == 0 && command == NULL)
3284 	    *so_ptr = 9999;		// force cursor halfway the window
3285 	update_topline();
3286 	curwin->w_scbind_pos = curwin->w_topline;
3287 	*so_ptr = n;
3288 	redraw_curbuf_later(NOT_VALID);	/* redraw this buffer later */
3289     }
3290 
3291     if (p_im)
3292 	need_start_insertmode = TRUE;
3293 
3294 #ifdef FEAT_AUTOCHDIR
3295     /* Change directories when the 'acd' option is set and we aren't already in
3296      * that directory (should already be done above). Expect getcwd() to be
3297      * faster than calling shorten_fnames() unnecessarily. */
3298     if (p_acd && curbuf->b_ffname != NULL)
3299     {
3300 	char_u	curdir[MAXPATHL];
3301 	char_u	filedir[MAXPATHL];
3302 
3303 	vim_strncpy(filedir, curbuf->b_ffname, MAXPATHL - 1);
3304 	*gettail_sep(filedir) = NUL;
3305 	if (mch_dirname(curdir, MAXPATHL) != FAIL
3306 		&& vim_fnamecmp(curdir, filedir) != 0)
3307 	    do_autochdir();
3308     }
3309 #endif
3310 
3311 #if defined(FEAT_NETBEANS_INTG)
3312     if (curbuf->b_ffname != NULL)
3313     {
3314 # ifdef FEAT_NETBEANS_INTG
3315 	if ((flags & ECMD_SET_HELP) != ECMD_SET_HELP)
3316 	    netbeans_file_opened(curbuf);
3317 # endif
3318     }
3319 #endif
3320 
3321 theend:
3322     if (did_inc_redrawing_disabled)
3323 	--RedrawingDisabled;
3324 #if defined(FEAT_EVAL)
3325     if (did_set_swapcommand)
3326 	set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
3327 #endif
3328 #ifdef FEAT_BROWSE
3329     vim_free(browse_file);
3330 #endif
3331     vim_free(free_fname);
3332     return retval;
3333 }
3334 
3335     static void
3336 delbuf_msg(char_u *name)
3337 {
3338     semsg(_("E143: Autocommands unexpectedly deleted new buffer %s"),
3339 	    name == NULL ? (char_u *)"" : name);
3340     vim_free(name);
3341     au_new_curbuf.br_buf = NULL;
3342     au_new_curbuf.br_buf_free_count = 0;
3343 }
3344 
3345 static int append_indent = 0;	    /* autoindent for first line */
3346 
3347 /*
3348  * ":insert" and ":append", also used by ":change"
3349  */
3350     void
3351 ex_append(exarg_T *eap)
3352 {
3353     char_u	*theline;
3354     int		did_undo = FALSE;
3355     linenr_T	lnum = eap->line2;
3356     int		indent = 0;
3357     char_u	*p;
3358     int		vcol;
3359     int		empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
3360 
3361     /* the ! flag toggles autoindent */
3362     if (eap->forceit)
3363 	curbuf->b_p_ai = !curbuf->b_p_ai;
3364 
3365     /* First autoindent comes from the line we start on */
3366     if (eap->cmdidx != CMD_change && curbuf->b_p_ai && lnum > 0)
3367 	append_indent = get_indent_lnum(lnum);
3368 
3369     if (eap->cmdidx != CMD_append)
3370 	--lnum;
3371 
3372     /* when the buffer is empty need to delete the dummy line */
3373     if (empty && lnum == 1)
3374 	lnum = 0;
3375 
3376     State = INSERT;		    /* behave like in Insert mode */
3377     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
3378 	State |= LANGMAP;
3379 
3380     for (;;)
3381     {
3382 	msg_scroll = TRUE;
3383 	need_wait_return = FALSE;
3384 	if (curbuf->b_p_ai)
3385 	{
3386 	    if (append_indent >= 0)
3387 	    {
3388 		indent = append_indent;
3389 		append_indent = -1;
3390 	    }
3391 	    else if (lnum > 0)
3392 		indent = get_indent_lnum(lnum);
3393 	}
3394 	ex_keep_indent = FALSE;
3395 	if (eap->getline == NULL)
3396 	{
3397 	    /* No getline() function, use the lines that follow. This ends
3398 	     * when there is no more. */
3399 	    if (eap->nextcmd == NULL || *eap->nextcmd == NUL)
3400 		break;
3401 	    p = vim_strchr(eap->nextcmd, NL);
3402 	    if (p == NULL)
3403 		p = eap->nextcmd + STRLEN(eap->nextcmd);
3404 	    theline = vim_strnsave(eap->nextcmd, (int)(p - eap->nextcmd));
3405 	    if (*p != NUL)
3406 		++p;
3407 	    eap->nextcmd = p;
3408 	}
3409 	else
3410 	{
3411 	    int save_State = State;
3412 
3413 	    /* Set State to avoid the cursor shape to be set to INSERT mode
3414 	     * when getline() returns. */
3415 	    State = CMDLINE;
3416 	    theline = eap->getline(
3417 #ifdef FEAT_EVAL
3418 		    eap->cstack->cs_looplevel > 0 ? -1 :
3419 #endif
3420 		    NUL, eap->cookie, indent, TRUE);
3421 	    State = save_State;
3422 	}
3423 	lines_left = Rows - 1;
3424 	if (theline == NULL)
3425 	    break;
3426 
3427 	/* Using ^ CTRL-D in getexmodeline() makes us repeat the indent. */
3428 	if (ex_keep_indent)
3429 	    append_indent = indent;
3430 
3431 	/* Look for the "." after automatic indent. */
3432 	vcol = 0;
3433 	for (p = theline; indent > vcol; ++p)
3434 	{
3435 	    if (*p == ' ')
3436 		++vcol;
3437 	    else if (*p == TAB)
3438 		vcol += 8 - vcol % 8;
3439 	    else
3440 		break;
3441 	}
3442 	if ((p[0] == '.' && p[1] == NUL)
3443 		|| (!did_undo && u_save(lnum, lnum + 1 + (empty ? 1 : 0))
3444 								     == FAIL))
3445 	{
3446 	    vim_free(theline);
3447 	    break;
3448 	}
3449 
3450 	/* don't use autoindent if nothing was typed. */
3451 	if (p[0] == NUL)
3452 	    theline[0] = NUL;
3453 
3454 	did_undo = TRUE;
3455 	ml_append(lnum, theline, (colnr_T)0, FALSE);
3456 	appended_lines_mark(lnum + (empty ? 1 : 0), 1L);
3457 
3458 	vim_free(theline);
3459 	++lnum;
3460 
3461 	if (empty)
3462 	{
3463 	    ml_delete(2L, FALSE);
3464 	    empty = FALSE;
3465 	}
3466     }
3467     State = NORMAL;
3468 
3469     if (eap->forceit)
3470 	curbuf->b_p_ai = !curbuf->b_p_ai;
3471 
3472     /* "start" is set to eap->line2+1 unless that position is invalid (when
3473      * eap->line2 pointed to the end of the buffer and nothing was appended)
3474      * "end" is set to lnum when something has been appended, otherwise
3475      * it is the same than "start"  -- Acevedo */
3476     curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
3477 	eap->line2 + 1 : curbuf->b_ml.ml_line_count;
3478     if (eap->cmdidx != CMD_append)
3479 	--curbuf->b_op_start.lnum;
3480     curbuf->b_op_end.lnum = (eap->line2 < lnum)
3481 					     ? lnum : curbuf->b_op_start.lnum;
3482     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
3483     curwin->w_cursor.lnum = lnum;
3484     check_cursor_lnum();
3485     beginline(BL_SOL | BL_FIX);
3486 
3487     need_wait_return = FALSE;	/* don't use wait_return() now */
3488     ex_no_reprint = TRUE;
3489 }
3490 
3491 /*
3492  * ":change"
3493  */
3494     void
3495 ex_change(exarg_T *eap)
3496 {
3497     linenr_T	lnum;
3498 
3499     if (eap->line2 >= eap->line1
3500 	    && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
3501 	return;
3502 
3503     /* the ! flag toggles autoindent */
3504     if (eap->forceit ? !curbuf->b_p_ai : curbuf->b_p_ai)
3505 	append_indent = get_indent_lnum(eap->line1);
3506 
3507     for (lnum = eap->line2; lnum >= eap->line1; --lnum)
3508     {
3509 	if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to delete */
3510 	    break;
3511 	ml_delete(eap->line1, FALSE);
3512     }
3513 
3514     /* make sure the cursor is not beyond the end of the file now */
3515     check_cursor_lnum();
3516     deleted_lines_mark(eap->line1, (long)(eap->line2 - lnum));
3517 
3518     /* ":append" on the line above the deleted lines. */
3519     eap->line2 = eap->line1;
3520     ex_append(eap);
3521 }
3522 
3523     void
3524 ex_z(exarg_T *eap)
3525 {
3526     char_u	*x;
3527     long	bigness;
3528     char_u	*kind;
3529     int		minus = 0;
3530     linenr_T	start, end, curs, i;
3531     int		j;
3532     linenr_T	lnum = eap->line2;
3533 
3534     /* Vi compatible: ":z!" uses display height, without a count uses
3535      * 'scroll' */
3536     if (eap->forceit)
3537 	bigness = curwin->w_height;
3538     else if (!ONE_WINDOW)
3539 	bigness = curwin->w_height - 3;
3540     else
3541 	bigness = curwin->w_p_scr * 2;
3542     if (bigness < 1)
3543 	bigness = 1;
3544 
3545     x = eap->arg;
3546     kind = x;
3547     if (*kind == '-' || *kind == '+' || *kind == '='
3548 					      || *kind == '^' || *kind == '.')
3549 	++x;
3550     while (*x == '-' || *x == '+')
3551 	++x;
3552 
3553     if (*x != 0)
3554     {
3555 	if (!VIM_ISDIGIT(*x))
3556 	{
3557 	    emsg(_("E144: non-numeric argument to :z"));
3558 	    return;
3559 	}
3560 	else
3561 	{
3562 	    bigness = atol((char *)x);
3563 
3564 	    /* bigness could be < 0 if atol(x) overflows. */
3565 	    if (bigness > 2 * curbuf->b_ml.ml_line_count || bigness < 0)
3566 		bigness = 2 * curbuf->b_ml.ml_line_count;
3567 
3568 	    p_window = bigness;
3569 	    if (*kind == '=')
3570 		bigness += 2;
3571 	}
3572     }
3573 
3574     /* the number of '-' and '+' multiplies the distance */
3575     if (*kind == '-' || *kind == '+')
3576 	for (x = kind + 1; *x == *kind; ++x)
3577 	    ;
3578 
3579     switch (*kind)
3580     {
3581 	case '-':
3582 	    start = lnum - bigness * (linenr_T)(x - kind) + 1;
3583 	    end = start + bigness - 1;
3584 	    curs = end;
3585 	    break;
3586 
3587 	case '=':
3588 	    start = lnum - (bigness + 1) / 2 + 1;
3589 	    end = lnum + (bigness + 1) / 2 - 1;
3590 	    curs = lnum;
3591 	    minus = 1;
3592 	    break;
3593 
3594 	case '^':
3595 	    start = lnum - bigness * 2;
3596 	    end = lnum - bigness;
3597 	    curs = lnum - bigness;
3598 	    break;
3599 
3600 	case '.':
3601 	    start = lnum - (bigness + 1) / 2 + 1;
3602 	    end = lnum + (bigness + 1) / 2 - 1;
3603 	    curs = end;
3604 	    break;
3605 
3606 	default:  /* '+' */
3607 	    start = lnum;
3608 	    if (*kind == '+')
3609 		start += bigness * (linenr_T)(x - kind - 1) + 1;
3610 	    else if (eap->addr_count == 0)
3611 		++start;
3612 	    end = start + bigness - 1;
3613 	    curs = end;
3614 	    break;
3615     }
3616 
3617     if (start < 1)
3618 	start = 1;
3619 
3620     if (end > curbuf->b_ml.ml_line_count)
3621 	end = curbuf->b_ml.ml_line_count;
3622 
3623     if (curs > curbuf->b_ml.ml_line_count)
3624 	curs = curbuf->b_ml.ml_line_count;
3625     else if (curs < 1)
3626 	curs = 1;
3627 
3628     for (i = start; i <= end; i++)
3629     {
3630 	if (minus && i == lnum)
3631 	{
3632 	    msg_putchar('\n');
3633 
3634 	    for (j = 1; j < Columns; j++)
3635 		msg_putchar('-');
3636 	}
3637 
3638 	print_line(i, eap->flags & EXFLAG_NR, eap->flags & EXFLAG_LIST);
3639 
3640 	if (minus && i == lnum)
3641 	{
3642 	    msg_putchar('\n');
3643 
3644 	    for (j = 1; j < Columns; j++)
3645 		msg_putchar('-');
3646 	}
3647     }
3648 
3649     if (curwin->w_cursor.lnum != curs)
3650     {
3651 	curwin->w_cursor.lnum = curs;
3652 	curwin->w_cursor.col = 0;
3653     }
3654     ex_no_reprint = TRUE;
3655 }
3656 
3657 /*
3658  * Check if the restricted flag is set.
3659  * If so, give an error message and return TRUE.
3660  * Otherwise, return FALSE.
3661  */
3662     int
3663 check_restricted(void)
3664 {
3665     if (restricted)
3666     {
3667 	emsg(_("E145: Shell commands and some functionality not allowed in rvim"));
3668 	return TRUE;
3669     }
3670     return FALSE;
3671 }
3672 
3673 /*
3674  * Check if the secure flag is set (.exrc or .vimrc in current directory).
3675  * If so, give an error message and return TRUE.
3676  * Otherwise, return FALSE.
3677  */
3678     int
3679 check_secure(void)
3680 {
3681     if (secure)
3682     {
3683 	secure = 2;
3684 	emsg(_(e_curdir));
3685 	return TRUE;
3686     }
3687 #ifdef HAVE_SANDBOX
3688     /*
3689      * In the sandbox more things are not allowed, including the things
3690      * disallowed in secure mode.
3691      */
3692     if (sandbox != 0)
3693     {
3694 	emsg(_(e_sandbox));
3695 	return TRUE;
3696     }
3697 #endif
3698     return FALSE;
3699 }
3700 
3701 static char_u	*old_sub = NULL;	/* previous substitute pattern */
3702 static int	global_need_beginline;	/* call beginline() after ":g" */
3703 
3704 /*
3705  * Flags that are kept between calls to :substitute.
3706  */
3707 typedef struct {
3708     int	do_all;		/* do multiple substitutions per line */
3709     int	do_ask;		/* ask for confirmation */
3710     int	do_count;	/* count only */
3711     int	do_error;	/* if false, ignore errors */
3712     int	do_print;	/* print last line with subs. */
3713     int	do_list;	/* list last line with subs. */
3714     int	do_number;	/* list last line with line nr*/
3715     int	do_ic;		/* ignore case flag */
3716 } subflags_T;
3717 
3718 /* do_sub()
3719  *
3720  * Perform a substitution from line eap->line1 to line eap->line2 using the
3721  * command pointed to by eap->arg which should be of the form:
3722  *
3723  * /pattern/substitution/{flags}
3724  *
3725  * The usual escapes are supported as described in the regexp docs.
3726  */
3727     void
3728 do_sub(exarg_T *eap)
3729 {
3730     linenr_T	lnum;
3731     long	i = 0;
3732     regmmatch_T regmatch;
3733     static subflags_T subflags = {FALSE, FALSE, FALSE, TRUE, FALSE,
3734 							      FALSE, FALSE, 0};
3735 #ifdef FEAT_EVAL
3736     subflags_T	subflags_save;
3737 #endif
3738     int		save_do_all;		/* remember user specified 'g' flag */
3739     int		save_do_ask;		/* remember user specified 'c' flag */
3740     char_u	*pat = NULL, *sub = NULL;	/* init for GCC */
3741     int		delimiter;
3742     int		sublen;
3743     int		got_quit = FALSE;
3744     int		got_match = FALSE;
3745     int		temp;
3746     int		which_pat;
3747     char_u	*cmd;
3748     int		save_State;
3749     linenr_T	first_line = 0;		/* first changed line */
3750     linenr_T	last_line= 0;		/* below last changed line AFTER the
3751 					 * change */
3752     linenr_T	old_line_count = curbuf->b_ml.ml_line_count;
3753     linenr_T	line2;
3754     long	nmatch;			/* number of lines in match */
3755     char_u	*sub_firstline;		/* allocated copy of first sub line */
3756     int		endcolumn = FALSE;	/* cursor in last column when done */
3757     pos_T	old_cursor = curwin->w_cursor;
3758     int		start_nsubs;
3759 #ifdef FEAT_EVAL
3760     int		save_ma = 0;
3761 #endif
3762 
3763     cmd = eap->arg;
3764     if (!global_busy)
3765     {
3766 	sub_nsubs = 0;
3767 	sub_nlines = 0;
3768     }
3769     start_nsubs = sub_nsubs;
3770 
3771     if (eap->cmdidx == CMD_tilde)
3772 	which_pat = RE_LAST;	/* use last used regexp */
3773     else
3774 	which_pat = RE_SUBST;	/* use last substitute regexp */
3775 
3776 				/* new pattern and substitution */
3777     if (eap->cmd[0] == 's' && *cmd != NUL && !VIM_ISWHITE(*cmd)
3778 		&& vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL)
3779     {
3780 				/* don't accept alphanumeric for separator */
3781 	if (isalpha(*cmd))
3782 	{
3783 	    emsg(_("E146: Regular expressions can't be delimited by letters"));
3784 	    return;
3785 	}
3786 	/*
3787 	 * undocumented vi feature:
3788 	 *  "\/sub/" and "\?sub?" use last used search pattern (almost like
3789 	 *  //sub/r).  "\&sub&" use last substitute pattern (like //sub/).
3790 	 */
3791 	if (*cmd == '\\')
3792 	{
3793 	    ++cmd;
3794 	    if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
3795 	    {
3796 		emsg(_(e_backslash));
3797 		return;
3798 	    }
3799 	    if (*cmd != '&')
3800 		which_pat = RE_SEARCH;	    /* use last '/' pattern */
3801 	    pat = (char_u *)"";		    /* empty search pattern */
3802 	    delimiter = *cmd++;		    /* remember delimiter character */
3803 	}
3804 	else		/* find the end of the regexp */
3805 	{
3806 	    which_pat = RE_LAST;	    /* use last used regexp */
3807 	    delimiter = *cmd++;		    /* remember delimiter character */
3808 	    pat = cmd;			    /* remember start of search pat */
3809 	    cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
3810 	    if (cmd[0] == delimiter)	    /* end delimiter found */
3811 		*cmd++ = NUL;		    /* replace it with a NUL */
3812 	}
3813 
3814 	/*
3815 	 * Small incompatibility: vi sees '\n' as end of the command, but in
3816 	 * Vim we want to use '\n' to find/substitute a NUL.
3817 	 */
3818 	sub = cmd;	    /* remember the start of the substitution */
3819 
3820 	while (cmd[0])
3821 	{
3822 	    if (cmd[0] == delimiter)		/* end delimiter found */
3823 	    {
3824 		*cmd++ = NUL;			/* replace it with a NUL */
3825 		break;
3826 	    }
3827 	    if (cmd[0] == '\\' && cmd[1] != 0)	/* skip escaped characters */
3828 		++cmd;
3829 	    MB_PTR_ADV(cmd);
3830 	}
3831 
3832 	if (!eap->skip)
3833 	{
3834 	    /* In POSIX vi ":s/pat/%/" uses the previous subst. string. */
3835 	    if (STRCMP(sub, "%") == 0
3836 				 && vim_strchr(p_cpo, CPO_SUBPERCENT) != NULL)
3837 	    {
3838 		if (old_sub == NULL)	/* there is no previous command */
3839 		{
3840 		    emsg(_(e_nopresub));
3841 		    return;
3842 		}
3843 		sub = old_sub;
3844 	    }
3845 	    else
3846 	    {
3847 		vim_free(old_sub);
3848 		old_sub = vim_strsave(sub);
3849 	    }
3850 	}
3851     }
3852     else if (!eap->skip)	/* use previous pattern and substitution */
3853     {
3854 	if (old_sub == NULL)	/* there is no previous command */
3855 	{
3856 	    emsg(_(e_nopresub));
3857 	    return;
3858 	}
3859 	pat = NULL;		/* search_regcomp() will use previous pattern */
3860 	sub = old_sub;
3861 
3862 	/* Vi compatibility quirk: repeating with ":s" keeps the cursor in the
3863 	 * last column after using "$". */
3864 	endcolumn = (curwin->w_curswant == MAXCOL);
3865     }
3866 
3867     /* Recognize ":%s/\n//" and turn it into a join command, which is much
3868      * more efficient.
3869      * TODO: find a generic solution to make line-joining operations more
3870      * efficient, avoid allocating a string that grows in size.
3871      */
3872     if (pat != NULL && STRCMP(pat, "\\n") == 0
3873 	    && *sub == NUL
3874 	    && (*cmd == NUL || (cmd[1] == NUL && (*cmd == 'g' || *cmd == 'l'
3875 					     || *cmd == 'p' || *cmd == '#'))))
3876     {
3877 	linenr_T    joined_lines_count;
3878 
3879 	curwin->w_cursor.lnum = eap->line1;
3880 	if (*cmd == 'l')
3881 	    eap->flags = EXFLAG_LIST;
3882 	else if (*cmd == '#')
3883 	    eap->flags = EXFLAG_NR;
3884 	else if (*cmd == 'p')
3885 	    eap->flags = EXFLAG_PRINT;
3886 
3887 	/* The number of lines joined is the number of lines in the range plus
3888 	 * one.  One less when the last line is included. */
3889 	joined_lines_count = eap->line2 - eap->line1 + 1;
3890 	if (eap->line2 < curbuf->b_ml.ml_line_count)
3891 	    ++joined_lines_count;
3892 	if (joined_lines_count > 1)
3893 	{
3894 	    (void)do_join(joined_lines_count, FALSE, TRUE, FALSE, TRUE);
3895 	    sub_nsubs = joined_lines_count - 1;
3896 	    sub_nlines = 1;
3897 	    (void)do_sub_msg(FALSE);
3898 	    ex_may_print(eap);
3899 	}
3900 
3901 	if (!cmdmod.keeppatterns)
3902 	    save_re_pat(RE_SUBST, pat, p_magic);
3903 #ifdef FEAT_CMDHIST
3904 	/* put pattern in history */
3905 	add_to_history(HIST_SEARCH, pat, TRUE, NUL);
3906 #endif
3907 
3908 	return;
3909     }
3910 
3911     /*
3912      * Find trailing options.  When '&' is used, keep old options.
3913      */
3914     if (*cmd == '&')
3915 	++cmd;
3916     else
3917     {
3918 	if (!p_ed)
3919 	{
3920 	    if (p_gd)		/* default is global on */
3921 		subflags.do_all = TRUE;
3922 	    else
3923 		subflags.do_all = FALSE;
3924 	    subflags.do_ask = FALSE;
3925 	}
3926 	subflags.do_error = TRUE;
3927 	subflags.do_print = FALSE;
3928 	subflags.do_list = FALSE;
3929 	subflags.do_count = FALSE;
3930 	subflags.do_number = FALSE;
3931 	subflags.do_ic = 0;
3932     }
3933     while (*cmd)
3934     {
3935 	/*
3936 	 * Note that 'g' and 'c' are always inverted, also when p_ed is off.
3937 	 * 'r' is never inverted.
3938 	 */
3939 	if (*cmd == 'g')
3940 	    subflags.do_all = !subflags.do_all;
3941 	else if (*cmd == 'c')
3942 	    subflags.do_ask = !subflags.do_ask;
3943 	else if (*cmd == 'n')
3944 	    subflags.do_count = TRUE;
3945 	else if (*cmd == 'e')
3946 	    subflags.do_error = !subflags.do_error;
3947 	else if (*cmd == 'r')	    /* use last used regexp */
3948 	    which_pat = RE_LAST;
3949 	else if (*cmd == 'p')
3950 	    subflags.do_print = TRUE;
3951 	else if (*cmd == '#')
3952 	{
3953 	    subflags.do_print = TRUE;
3954 	    subflags.do_number = TRUE;
3955 	}
3956 	else if (*cmd == 'l')
3957 	{
3958 	    subflags.do_print = TRUE;
3959 	    subflags.do_list = TRUE;
3960 	}
3961 	else if (*cmd == 'i')	    /* ignore case */
3962 	    subflags.do_ic = 'i';
3963 	else if (*cmd == 'I')	    /* don't ignore case */
3964 	    subflags.do_ic = 'I';
3965 	else
3966 	    break;
3967 	++cmd;
3968     }
3969     if (subflags.do_count)
3970 	subflags.do_ask = FALSE;
3971 
3972     save_do_all = subflags.do_all;
3973     save_do_ask = subflags.do_ask;
3974 
3975     /*
3976      * check for a trailing count
3977      */
3978     cmd = skipwhite(cmd);
3979     if (VIM_ISDIGIT(*cmd))
3980     {
3981 	i = getdigits(&cmd);
3982 	if (i <= 0 && !eap->skip && subflags.do_error)
3983 	{
3984 	    emsg(_(e_zerocount));
3985 	    return;
3986 	}
3987 	eap->line1 = eap->line2;
3988 	eap->line2 += i - 1;
3989 	if (eap->line2 > curbuf->b_ml.ml_line_count)
3990 	    eap->line2 = curbuf->b_ml.ml_line_count;
3991     }
3992 
3993     /*
3994      * check for trailing command or garbage
3995      */
3996     cmd = skipwhite(cmd);
3997     if (*cmd && *cmd != '"')	    /* if not end-of-line or comment */
3998     {
3999 	eap->nextcmd = check_nextcmd(cmd);
4000 	if (eap->nextcmd == NULL)
4001 	{
4002 	    emsg(_(e_trailing));
4003 	    return;
4004 	}
4005     }
4006 
4007     if (eap->skip)	    /* not executing commands, only parsing */
4008 	return;
4009 
4010     if (!subflags.do_count && !curbuf->b_p_ma)
4011     {
4012 	/* Substitution is not allowed in non-'modifiable' buffer */
4013 	emsg(_(e_modifiable));
4014 	return;
4015     }
4016 
4017     if (search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS, &regmatch) == FAIL)
4018     {
4019 	if (subflags.do_error)
4020 	    emsg(_(e_invcmd));
4021 	return;
4022     }
4023 
4024     /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
4025     if (subflags.do_ic == 'i')
4026 	regmatch.rmm_ic = TRUE;
4027     else if (subflags.do_ic == 'I')
4028 	regmatch.rmm_ic = FALSE;
4029 
4030     sub_firstline = NULL;
4031 
4032     /*
4033      * ~ in the substitute pattern is replaced with the old pattern.
4034      * We do it here once to avoid it to be replaced over and over again.
4035      * But don't do it when it starts with "\=", then it's an expression.
4036      */
4037     if (!(sub[0] == '\\' && sub[1] == '='))
4038 	sub = regtilde(sub, p_magic);
4039 
4040     /*
4041      * Check for a match on each line.
4042      */
4043     line2 = eap->line2;
4044     for (lnum = eap->line1; lnum <= line2 && !(got_quit
4045 #if defined(FEAT_EVAL)
4046 		|| aborting()
4047 #endif
4048 		); ++lnum)
4049     {
4050 	nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
4051 						       (colnr_T)0, NULL, NULL);
4052 	if (nmatch)
4053 	{
4054 	    colnr_T	copycol;
4055 	    colnr_T	matchcol;
4056 	    colnr_T	prev_matchcol = MAXCOL;
4057 	    char_u	*new_end, *new_start = NULL;
4058 	    unsigned	new_start_len = 0;
4059 	    char_u	*p1;
4060 	    int		did_sub = FALSE;
4061 	    int		lastone;
4062 	    int		len, copy_len, needed_len;
4063 	    long	nmatch_tl = 0;	/* nr of lines matched below lnum */
4064 	    int		do_again;	/* do it again after joining lines */
4065 	    int		skip_match = FALSE;
4066 	    linenr_T	sub_firstlnum;	/* nr of first sub line */
4067 #ifdef FEAT_TEXT_PROP
4068 	    int		apc_flags = APC_SAVE_FOR_UNDO | APC_SUBSTITUTE;
4069 #endif
4070 
4071 	    /*
4072 	     * The new text is build up step by step, to avoid too much
4073 	     * copying.  There are these pieces:
4074 	     * sub_firstline	The old text, unmodified.
4075 	     * copycol		Column in the old text where we started
4076 	     *			looking for a match; from here old text still
4077 	     *			needs to be copied to the new text.
4078 	     * matchcol		Column number of the old text where to look
4079 	     *			for the next match.  It's just after the
4080 	     *			previous match or one further.
4081 	     * prev_matchcol	Column just after the previous match (if any).
4082 	     *			Mostly equal to matchcol, except for the first
4083 	     *			match and after skipping an empty match.
4084 	     * regmatch.*pos	Where the pattern matched in the old text.
4085 	     * new_start	The new text, all that has been produced so
4086 	     *			far.
4087 	     * new_end		The new text, where to append new text.
4088 	     *
4089 	     * lnum		The line number where we found the start of
4090 	     *			the match.  Can be below the line we searched
4091 	     *			when there is a \n before a \zs in the
4092 	     *			pattern.
4093 	     * sub_firstlnum	The line number in the buffer where to look
4094 	     *			for a match.  Can be different from "lnum"
4095 	     *			when the pattern or substitute string contains
4096 	     *			line breaks.
4097 	     *
4098 	     * Special situations:
4099 	     * - When the substitute string contains a line break, the part up
4100 	     *   to the line break is inserted in the text, but the copy of
4101 	     *   the original line is kept.  "sub_firstlnum" is adjusted for
4102 	     *   the inserted lines.
4103 	     * - When the matched pattern contains a line break, the old line
4104 	     *   is taken from the line at the end of the pattern.  The lines
4105 	     *   in the match are deleted later, "sub_firstlnum" is adjusted
4106 	     *   accordingly.
4107 	     *
4108 	     * The new text is built up in new_start[].  It has some extra
4109 	     * room to avoid using alloc()/free() too often.  new_start_len is
4110 	     * the length of the allocated memory at new_start.
4111 	     *
4112 	     * Make a copy of the old line, so it won't be taken away when
4113 	     * updating the screen or handling a multi-line match.  The "old_"
4114 	     * pointers point into this copy.
4115 	     */
4116 	    sub_firstlnum = lnum;
4117 	    copycol = 0;
4118 	    matchcol = 0;
4119 
4120 	    /* At first match, remember current cursor position. */
4121 	    if (!got_match)
4122 	    {
4123 		setpcmark();
4124 		got_match = TRUE;
4125 	    }
4126 
4127 	    /*
4128 	     * Loop until nothing more to replace in this line.
4129 	     * 1. Handle match with empty string.
4130 	     * 2. If do_ask is set, ask for confirmation.
4131 	     * 3. substitute the string.
4132 	     * 4. if do_all is set, find next match
4133 	     * 5. break if there isn't another match in this line
4134 	     */
4135 	    for (;;)
4136 	    {
4137 		/* Advance "lnum" to the line where the match starts.  The
4138 		 * match does not start in the first line when there is a line
4139 		 * break before \zs. */
4140 		if (regmatch.startpos[0].lnum > 0)
4141 		{
4142 		    lnum += regmatch.startpos[0].lnum;
4143 		    sub_firstlnum += regmatch.startpos[0].lnum;
4144 		    nmatch -= regmatch.startpos[0].lnum;
4145 		    VIM_CLEAR(sub_firstline);
4146 		}
4147 
4148 		if (sub_firstline == NULL)
4149 		{
4150 		    sub_firstline = vim_strsave(ml_get(sub_firstlnum));
4151 		    if (sub_firstline == NULL)
4152 		    {
4153 			vim_free(new_start);
4154 			goto outofmem;
4155 		    }
4156 		}
4157 
4158 		/* Save the line number of the last change for the final
4159 		 * cursor position (just like Vi). */
4160 		curwin->w_cursor.lnum = lnum;
4161 		do_again = FALSE;
4162 
4163 		/*
4164 		 * 1. Match empty string does not count, except for first
4165 		 * match.  This reproduces the strange vi behaviour.
4166 		 * This also catches endless loops.
4167 		 */
4168 		if (matchcol == prev_matchcol
4169 			&& regmatch.endpos[0].lnum == 0
4170 			&& matchcol == regmatch.endpos[0].col)
4171 		{
4172 		    if (sub_firstline[matchcol] == NUL)
4173 			/* We already were at the end of the line.  Don't look
4174 			 * for a match in this line again. */
4175 			skip_match = TRUE;
4176 		    else
4177 		    {
4178 			 /* search for a match at next column */
4179 			if (has_mbyte)
4180 			    matchcol += mb_ptr2len(sub_firstline + matchcol);
4181 			else
4182 			    ++matchcol;
4183 		    }
4184 		    goto skip;
4185 		}
4186 
4187 		/* Normally we continue searching for a match just after the
4188 		 * previous match. */
4189 		matchcol = regmatch.endpos[0].col;
4190 		prev_matchcol = matchcol;
4191 
4192 		/*
4193 		 * 2. If do_count is set only increase the counter.
4194 		 *    If do_ask is set, ask for confirmation.
4195 		 */
4196 		if (subflags.do_count)
4197 		{
4198 		    /* For a multi-line match, put matchcol at the NUL at
4199 		     * the end of the line and set nmatch to one, so that
4200 		     * we continue looking for a match on the next line.
4201 		     * Avoids that ":s/\nB\@=//gc" get stuck. */
4202 		    if (nmatch > 1)
4203 		    {
4204 			matchcol = (colnr_T)STRLEN(sub_firstline);
4205 			nmatch = 1;
4206 			skip_match = TRUE;
4207 		    }
4208 		    sub_nsubs++;
4209 		    did_sub = TRUE;
4210 #ifdef FEAT_EVAL
4211 		    /* Skip the substitution, unless an expression is used,
4212 		     * then it is evaluated in the sandbox. */
4213 		    if (!(sub[0] == '\\' && sub[1] == '='))
4214 #endif
4215 			goto skip;
4216 		}
4217 
4218 		if (subflags.do_ask)
4219 		{
4220 		    int typed = 0;
4221 
4222 		    /* change State to CONFIRM, so that the mouse works
4223 		     * properly */
4224 		    save_State = State;
4225 		    State = CONFIRM;
4226 #ifdef FEAT_MOUSE
4227 		    setmouse();		/* disable mouse in xterm */
4228 #endif
4229 		    curwin->w_cursor.col = regmatch.startpos[0].col;
4230 		    if (curwin->w_p_crb)
4231 			do_check_cursorbind();
4232 
4233 		    /* When 'cpoptions' contains "u" don't sync undo when
4234 		     * asking for confirmation. */
4235 		    if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
4236 			++no_u_sync;
4237 
4238 		    /*
4239 		     * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
4240 		     */
4241 		    while (subflags.do_ask)
4242 		    {
4243 			if (exmode_active)
4244 			{
4245 			    char_u	*resp;
4246 			    colnr_T	sc, ec;
4247 
4248 			    print_line_no_prefix(lnum,
4249 					 subflags.do_number, subflags.do_list);
4250 
4251 			    getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL);
4252 			    curwin->w_cursor.col = regmatch.endpos[0].col - 1;
4253 			    if (curwin->w_cursor.col < 0)
4254 				curwin->w_cursor.col = 0;
4255 			    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec);
4256 			    if (subflags.do_number || curwin->w_p_nu)
4257 			    {
4258 				int numw = number_width(curwin) + 1;
4259 				sc += numw;
4260 				ec += numw;
4261 			    }
4262 			    msg_start();
4263 			    for (i = 0; i < (long)sc; ++i)
4264 				msg_putchar(' ');
4265 			    for ( ; i <= (long)ec; ++i)
4266 				msg_putchar('^');
4267 
4268 			    resp = getexmodeline('?', NULL, 0, TRUE);
4269 			    if (resp != NULL)
4270 			    {
4271 				typed = *resp;
4272 				vim_free(resp);
4273 			    }
4274 			}
4275 			else
4276 			{
4277 			    char_u *orig_line = NULL;
4278 			    int    len_change = 0;
4279 #ifdef FEAT_FOLDING
4280 			    int save_p_fen = curwin->w_p_fen;
4281 
4282 			    curwin->w_p_fen = FALSE;
4283 #endif
4284 			    /* Invert the matched string.
4285 			     * Remove the inversion afterwards. */
4286 			    temp = RedrawingDisabled;
4287 			    RedrawingDisabled = 0;
4288 
4289 			    if (new_start != NULL)
4290 			    {
4291 				/* There already was a substitution, we would
4292 				 * like to show this to the user.  We cannot
4293 				 * really update the line, it would change
4294 				 * what matches.  Temporarily replace the line
4295 				 * and change it back afterwards. */
4296 				orig_line = vim_strsave(ml_get(lnum));
4297 				if (orig_line != NULL)
4298 				{
4299 				    char_u *new_line = concat_str(new_start,
4300 						     sub_firstline + copycol);
4301 
4302 				    if (new_line == NULL)
4303 					VIM_CLEAR(orig_line);
4304 				    else
4305 				    {
4306 					/* Position the cursor relative to the
4307 					 * end of the line, the previous
4308 					 * substitute may have inserted or
4309 					 * deleted characters before the
4310 					 * cursor. */
4311 					len_change = (int)STRLEN(new_line)
4312 						     - (int)STRLEN(orig_line);
4313 					curwin->w_cursor.col += len_change;
4314 					ml_replace(lnum, new_line, FALSE);
4315 				    }
4316 				}
4317 			    }
4318 
4319 			    search_match_lines = regmatch.endpos[0].lnum
4320 						  - regmatch.startpos[0].lnum;
4321 			    search_match_endcol = regmatch.endpos[0].col
4322 								 + len_change;
4323 			    highlight_match = TRUE;
4324 
4325 			    update_topline();
4326 			    validate_cursor();
4327 			    update_screen(SOME_VALID);
4328 			    highlight_match = FALSE;
4329 			    redraw_later(SOME_VALID);
4330 
4331 #ifdef FEAT_FOLDING
4332 			    curwin->w_p_fen = save_p_fen;
4333 #endif
4334 			    if (msg_row == Rows - 1)
4335 				msg_didout = FALSE;	/* avoid a scroll-up */
4336 			    msg_starthere();
4337 			    i = msg_scroll;
4338 			    msg_scroll = 0;		/* truncate msg when
4339 							   needed */
4340 			    msg_no_more = TRUE;
4341 			    /* write message same highlighting as for
4342 			     * wait_return */
4343 			    smsg_attr(HL_ATTR(HLF_R),
4344 				_("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
4345 			    msg_no_more = FALSE;
4346 			    msg_scroll = i;
4347 			    showruler(TRUE);
4348 			    windgoto(msg_row, msg_col);
4349 			    RedrawingDisabled = temp;
4350 
4351 #ifdef USE_ON_FLY_SCROLL
4352 			    dont_scroll = FALSE; /* allow scrolling here */
4353 #endif
4354 			    ++no_mapping;	/* don't map this key */
4355 			    ++allow_keys;	/* allow special keys */
4356 			    typed = plain_vgetc();
4357 			    --allow_keys;
4358 			    --no_mapping;
4359 
4360 			    /* clear the question */
4361 			    msg_didout = FALSE;	/* don't scroll up */
4362 			    msg_col = 0;
4363 			    gotocmdline(TRUE);
4364 
4365 			    /* restore the line */
4366 			    if (orig_line != NULL)
4367 				ml_replace(lnum, orig_line, FALSE);
4368 			}
4369 
4370 			need_wait_return = FALSE; /* no hit-return prompt */
4371 			if (typed == 'q' || typed == ESC || typed == Ctrl_C
4372 #ifdef UNIX
4373 				|| typed == intr_char
4374 #endif
4375 				)
4376 			{
4377 			    got_quit = TRUE;
4378 			    break;
4379 			}
4380 			if (typed == 'n')
4381 			    break;
4382 			if (typed == 'y')
4383 			    break;
4384 			if (typed == 'l')
4385 			{
4386 			    /* last: replace and then stop */
4387 			    subflags.do_all = FALSE;
4388 			    line2 = lnum;
4389 			    break;
4390 			}
4391 			if (typed == 'a')
4392 			{
4393 			    subflags.do_ask = FALSE;
4394 			    break;
4395 			}
4396 #ifdef FEAT_INS_EXPAND
4397 			if (typed == Ctrl_E)
4398 			    scrollup_clamp();
4399 			else if (typed == Ctrl_Y)
4400 			    scrolldown_clamp();
4401 #endif
4402 		    }
4403 		    State = save_State;
4404 #ifdef FEAT_MOUSE
4405 		    setmouse();
4406 #endif
4407 		    if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
4408 			--no_u_sync;
4409 
4410 		    if (typed == 'n')
4411 		    {
4412 			/* For a multi-line match, put matchcol at the NUL at
4413 			 * the end of the line and set nmatch to one, so that
4414 			 * we continue looking for a match on the next line.
4415 			 * Avoids that ":%s/\nB\@=//gc" and ":%s/\n/,\r/gc"
4416 			 * get stuck when pressing 'n'. */
4417 			if (nmatch > 1)
4418 			{
4419 			    matchcol = (colnr_T)STRLEN(sub_firstline);
4420 			    skip_match = TRUE;
4421 			}
4422 			goto skip;
4423 		    }
4424 		    if (got_quit)
4425 			goto skip;
4426 		}
4427 
4428 		/* Move the cursor to the start of the match, so that we can
4429 		 * use "\=col("."). */
4430 		curwin->w_cursor.col = regmatch.startpos[0].col;
4431 
4432 		/*
4433 		 * 3. substitute the string.
4434 		 */
4435 #ifdef FEAT_EVAL
4436 		save_ma = curbuf->b_p_ma;
4437 		if (subflags.do_count)
4438 		{
4439 		    // prevent accidentally changing the buffer by a function
4440 		    curbuf->b_p_ma = FALSE;
4441 		    sandbox++;
4442 		}
4443 		// Save flags for recursion.  They can change for e.g.
4444 		// :s/^/\=execute("s#^##gn")
4445 		subflags_save = subflags;
4446 #endif
4447 		// get length of substitution part
4448 		sublen = vim_regsub_multi(&regmatch,
4449 				    sub_firstlnum - regmatch.startpos[0].lnum,
4450 				    sub, sub_firstline, FALSE, p_magic, TRUE);
4451 #ifdef FEAT_EVAL
4452 		// If getting the substitute string caused an error, don't do
4453 		// the replacement.
4454 		// Don't keep flags set by a recursive call.
4455 		subflags = subflags_save;
4456 		if (aborting() || subflags.do_count)
4457 		{
4458 		    curbuf->b_p_ma = save_ma;
4459 		    if (sandbox > 0)
4460 			sandbox--;
4461 		    goto skip;
4462 		}
4463 #endif
4464 
4465 		/* When the match included the "$" of the last line it may
4466 		 * go beyond the last line of the buffer. */
4467 		if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1)
4468 		{
4469 		    nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
4470 		    skip_match = TRUE;
4471 		}
4472 
4473 		/* Need room for:
4474 		 * - result so far in new_start (not for first sub in line)
4475 		 * - original text up to match
4476 		 * - length of substituted part
4477 		 * - original text after match
4478 		 * Adjust text properties here, since we have all information
4479 		 * needed.
4480 		 */
4481 		if (nmatch == 1)
4482 		{
4483 		    p1 = sub_firstline;
4484 #ifdef FEAT_TEXT_PROP
4485 		    if (curbuf->b_has_textprop)
4486 		    {
4487 			// When text properties are changed, need to save for
4488 			// undo first, unless done already.
4489 			if (adjust_prop_columns(lnum, regmatch.startpos[0].col,
4490 			      sublen - 1 - (regmatch.endpos[0].col
4491 						   - regmatch.startpos[0].col),
4492 								    apc_flags))
4493 			    apc_flags &= ~APC_SAVE_FOR_UNDO;
4494 		    }
4495 #endif
4496 		}
4497 		else
4498 		{
4499 		    p1 = ml_get(sub_firstlnum + nmatch - 1);
4500 		    nmatch_tl += nmatch - 1;
4501 		}
4502 		copy_len = regmatch.startpos[0].col - copycol;
4503 		needed_len = copy_len + ((unsigned)STRLEN(p1)
4504 				       - regmatch.endpos[0].col) + sublen + 1;
4505 		if (new_start == NULL)
4506 		{
4507 		    /*
4508 		     * Get some space for a temporary buffer to do the
4509 		     * substitution into (and some extra space to avoid
4510 		     * too many calls to alloc()/free()).
4511 		     */
4512 		    new_start_len = needed_len + 50;
4513 		    if ((new_start = alloc(new_start_len)) == NULL)
4514 			goto outofmem;
4515 		    *new_start = NUL;
4516 		    new_end = new_start;
4517 		}
4518 		else
4519 		{
4520 		    /*
4521 		     * Check if the temporary buffer is long enough to do the
4522 		     * substitution into.  If not, make it larger (with a bit
4523 		     * extra to avoid too many calls to alloc()/free()).
4524 		     */
4525 		    len = (unsigned)STRLEN(new_start);
4526 		    needed_len += len;
4527 		    if (needed_len > (int)new_start_len)
4528 		    {
4529 			new_start_len = needed_len + 50;
4530 			if ((p1 = alloc(new_start_len)) == NULL)
4531 			{
4532 			    vim_free(new_start);
4533 			    goto outofmem;
4534 			}
4535 			mch_memmove(p1, new_start, (size_t)(len + 1));
4536 			vim_free(new_start);
4537 			new_start = p1;
4538 		    }
4539 		    new_end = new_start + len;
4540 		}
4541 
4542 		/*
4543 		 * copy the text up to the part that matched
4544 		 */
4545 		mch_memmove(new_end, sub_firstline + copycol, (size_t)copy_len);
4546 		new_end += copy_len;
4547 
4548 		(void)vim_regsub_multi(&regmatch,
4549 				    sub_firstlnum - regmatch.startpos[0].lnum,
4550 					   sub, new_end, TRUE, p_magic, TRUE);
4551 		sub_nsubs++;
4552 		did_sub = TRUE;
4553 
4554 		/* Move the cursor to the start of the line, to avoid that it
4555 		 * is beyond the end of the line after the substitution. */
4556 		curwin->w_cursor.col = 0;
4557 
4558 		/* For a multi-line match, make a copy of the last matched
4559 		 * line and continue in that one. */
4560 		if (nmatch > 1)
4561 		{
4562 		    sub_firstlnum += nmatch - 1;
4563 		    vim_free(sub_firstline);
4564 		    sub_firstline = vim_strsave(ml_get(sub_firstlnum));
4565 		    /* When going beyond the last line, stop substituting. */
4566 		    if (sub_firstlnum <= line2)
4567 			do_again = TRUE;
4568 		    else
4569 			subflags.do_all = FALSE;
4570 		}
4571 
4572 		/* Remember next character to be copied. */
4573 		copycol = regmatch.endpos[0].col;
4574 
4575 		if (skip_match)
4576 		{
4577 		    /* Already hit end of the buffer, sub_firstlnum is one
4578 		     * less than what it ought to be. */
4579 		    vim_free(sub_firstline);
4580 		    sub_firstline = vim_strsave((char_u *)"");
4581 		    copycol = 0;
4582 		}
4583 
4584 		/*
4585 		 * Now the trick is to replace CTRL-M chars with a real line
4586 		 * break.  This would make it impossible to insert a CTRL-M in
4587 		 * the text.  The line break can be avoided by preceding the
4588 		 * CTRL-M with a backslash.  To be able to insert a backslash,
4589 		 * they must be doubled in the string and are halved here.
4590 		 * That is Vi compatible.
4591 		 */
4592 		for (p1 = new_end; *p1; ++p1)
4593 		{
4594 		    if (p1[0] == '\\' && p1[1] != NUL)  /* remove backslash */
4595 		    {
4596 			STRMOVE(p1, p1 + 1);
4597 #ifdef FEAT_TEXT_PROP
4598 			if (curbuf->b_has_textprop)
4599 			{
4600 			    // When text properties are changed, need to save
4601 			    // for undo first, unless done already.
4602 			    if (adjust_prop_columns(lnum,
4603 					(colnr_T)(p1 - new_start), -1,
4604 					apc_flags))
4605 				apc_flags &= ~APC_SAVE_FOR_UNDO;
4606 			}
4607 #endif
4608 		    }
4609 		    else if (*p1 == CAR)
4610 		    {
4611 			if (u_inssub(lnum) == OK)   // prepare for undo
4612 			{
4613 			    colnr_T	plen = (colnr_T)(p1 - new_start + 1);
4614 
4615 			    *p1 = NUL;		    // truncate up to the CR
4616 			    ml_append(lnum - 1, new_start, plen, FALSE);
4617 			    mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
4618 			    if (subflags.do_ask)
4619 				appended_lines(lnum - 1, 1L);
4620 			    else
4621 			    {
4622 				if (first_line == 0)
4623 				    first_line = lnum;
4624 				last_line = lnum + 1;
4625 			    }
4626 #ifdef FEAT_TEXT_PROP
4627 			    adjust_props_for_split(lnum + 1, lnum, plen, 1);
4628 #endif
4629 			    // all line numbers increase
4630 			    ++sub_firstlnum;
4631 			    ++lnum;
4632 			    ++line2;
4633 			    // move the cursor to the new line, like Vi
4634 			    ++curwin->w_cursor.lnum;
4635 			    // copy the rest
4636 			    STRMOVE(new_start, p1 + 1);
4637 			    p1 = new_start - 1;
4638 			}
4639 		    }
4640 		    else if (has_mbyte)
4641 			p1 += (*mb_ptr2len)(p1) - 1;
4642 		}
4643 
4644 		/*
4645 		 * 4. If do_all is set, find next match.
4646 		 * Prevent endless loop with patterns that match empty
4647 		 * strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
4648 		 * But ":s/\n/#/" is OK.
4649 		 */
4650 skip:
4651 		/* We already know that we did the last subst when we are at
4652 		 * the end of the line, except that a pattern like
4653 		 * "bar\|\nfoo" may match at the NUL.  "lnum" can be below
4654 		 * "line2" when there is a \zs in the pattern after a line
4655 		 * break. */
4656 		lastone = (skip_match
4657 			|| got_int
4658 			|| got_quit
4659 			|| lnum > line2
4660 			|| !(subflags.do_all || do_again)
4661 			|| (sub_firstline[matchcol] == NUL && nmatch <= 1
4662 					 && !re_multiline(regmatch.regprog)));
4663 		nmatch = -1;
4664 
4665 		/*
4666 		 * Replace the line in the buffer when needed.  This is
4667 		 * skipped when there are more matches.
4668 		 * The check for nmatch_tl is needed for when multi-line
4669 		 * matching must replace the lines before trying to do another
4670 		 * match, otherwise "\@<=" won't work.
4671 		 * When the match starts below where we start searching also
4672 		 * need to replace the line first (using \zs after \n).
4673 		 */
4674 		if (lastone
4675 			|| nmatch_tl > 0
4676 			|| (nmatch = vim_regexec_multi(&regmatch, curwin,
4677 							curbuf, sub_firstlnum,
4678 						    matchcol, NULL, NULL)) == 0
4679 			|| regmatch.startpos[0].lnum > 0)
4680 		{
4681 		    if (new_start != NULL)
4682 		    {
4683 			/*
4684 			 * Copy the rest of the line, that didn't match.
4685 			 * "matchcol" has to be adjusted, we use the end of
4686 			 * the line as reference, because the substitute may
4687 			 * have changed the number of characters.  Same for
4688 			 * "prev_matchcol".
4689 			 */
4690 			STRCAT(new_start, sub_firstline + copycol);
4691 			matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
4692 			prev_matchcol = (colnr_T)STRLEN(sub_firstline)
4693 							      - prev_matchcol;
4694 
4695 			if (u_savesub(lnum) != OK)
4696 			    break;
4697 			ml_replace(lnum, new_start, TRUE);
4698 
4699 			if (nmatch_tl > 0)
4700 			{
4701 			    /*
4702 			     * Matched lines have now been substituted and are
4703 			     * useless, delete them.  The part after the match
4704 			     * has been appended to new_start, we don't need
4705 			     * it in the buffer.
4706 			     */
4707 			    ++lnum;
4708 			    if (u_savedel(lnum, nmatch_tl) != OK)
4709 				break;
4710 			    for (i = 0; i < nmatch_tl; ++i)
4711 				ml_delete(lnum, (int)FALSE);
4712 			    mark_adjust(lnum, lnum + nmatch_tl - 1,
4713 						   (long)MAXLNUM, -nmatch_tl);
4714 			    if (subflags.do_ask)
4715 				deleted_lines(lnum, nmatch_tl);
4716 			    --lnum;
4717 			    line2 -= nmatch_tl; /* nr of lines decreases */
4718 			    nmatch_tl = 0;
4719 			}
4720 
4721 			/* When asking, undo is saved each time, must also set
4722 			 * changed flag each time. */
4723 			if (subflags.do_ask)
4724 			    changed_bytes(lnum, 0);
4725 			else
4726 			{
4727 			    if (first_line == 0)
4728 				first_line = lnum;
4729 			    last_line = lnum + 1;
4730 			}
4731 
4732 			sub_firstlnum = lnum;
4733 			vim_free(sub_firstline);    /* free the temp buffer */
4734 			sub_firstline = new_start;
4735 			new_start = NULL;
4736 			matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
4737 			prev_matchcol = (colnr_T)STRLEN(sub_firstline)
4738 							      - prev_matchcol;
4739 			copycol = 0;
4740 		    }
4741 		    if (nmatch == -1 && !lastone)
4742 			nmatch = vim_regexec_multi(&regmatch, curwin, curbuf,
4743 					  sub_firstlnum, matchcol, NULL, NULL);
4744 
4745 		    /*
4746 		     * 5. break if there isn't another match in this line
4747 		     */
4748 		    if (nmatch <= 0)
4749 		    {
4750 			/* If the match found didn't start where we were
4751 			 * searching, do the next search in the line where we
4752 			 * found the match. */
4753 			if (nmatch == -1)
4754 			    lnum -= regmatch.startpos[0].lnum;
4755 			break;
4756 		    }
4757 		}
4758 
4759 		line_breakcheck();
4760 	    }
4761 
4762 	    if (did_sub)
4763 		++sub_nlines;
4764 	    vim_free(new_start);	/* for when substitute was cancelled */
4765 	    VIM_CLEAR(sub_firstline);	/* free the copy of the original line */
4766 	}
4767 
4768 	line_breakcheck();
4769     }
4770 
4771     if (first_line != 0)
4772     {
4773 	/* Need to subtract the number of added lines from "last_line" to get
4774 	 * the line number before the change (same as adding the number of
4775 	 * deleted lines). */
4776 	i = curbuf->b_ml.ml_line_count - old_line_count;
4777 	changed_lines(first_line, 0, last_line - i, i);
4778     }
4779 
4780 outofmem:
4781     vim_free(sub_firstline); /* may have to free allocated copy of the line */
4782 
4783     /* ":s/pat//n" doesn't move the cursor */
4784     if (subflags.do_count)
4785 	curwin->w_cursor = old_cursor;
4786 
4787     if (sub_nsubs > start_nsubs)
4788     {
4789 	/* Set the '[ and '] marks. */
4790 	curbuf->b_op_start.lnum = eap->line1;
4791 	curbuf->b_op_end.lnum = line2;
4792 	curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
4793 
4794 	if (!global_busy)
4795 	{
4796 	    /* when interactive leave cursor on the match */
4797 	    if (!subflags.do_ask)
4798 	    {
4799 		if (endcolumn)
4800 		    coladvance((colnr_T)MAXCOL);
4801 		else
4802 		    beginline(BL_WHITE | BL_FIX);
4803 	    }
4804 	    if (!do_sub_msg(subflags.do_count) && subflags.do_ask)
4805 		msg("");
4806 	}
4807 	else
4808 	    global_need_beginline = TRUE;
4809 	if (subflags.do_print)
4810 	    print_line(curwin->w_cursor.lnum,
4811 					 subflags.do_number, subflags.do_list);
4812     }
4813     else if (!global_busy)
4814     {
4815 	if (got_int)		/* interrupted */
4816 	    emsg(_(e_interr));
4817 	else if (got_match)	/* did find something but nothing substituted */
4818 	    msg("");
4819 	else if (subflags.do_error)	/* nothing found */
4820 	    semsg(_(e_patnotf2), get_search_pat());
4821     }
4822 
4823 #ifdef FEAT_FOLDING
4824     if (subflags.do_ask && hasAnyFolding(curwin))
4825 	/* Cursor position may require updating */
4826 	changed_window_setting();
4827 #endif
4828 
4829     vim_regfree(regmatch.regprog);
4830 
4831     /* Restore the flag values, they can be used for ":&&". */
4832     subflags.do_all = save_do_all;
4833     subflags.do_ask = save_do_ask;
4834 }
4835 
4836 /*
4837  * Give message for number of substitutions.
4838  * Can also be used after a ":global" command.
4839  * Return TRUE if a message was given.
4840  */
4841     int
4842 do_sub_msg(
4843     int	    count_only)		/* used 'n' flag for ":s" */
4844 {
4845     /*
4846      * Only report substitutions when:
4847      * - more than 'report' substitutions
4848      * - command was typed by user, or number of changed lines > 'report'
4849      * - giving messages is not disabled by 'lazyredraw'
4850      */
4851     if (((sub_nsubs > p_report && (KeyTyped || sub_nlines > 1 || p_report < 1))
4852 		|| count_only)
4853 	    && messaging())
4854     {
4855 	char	*msg_single;
4856 	char	*msg_plural;
4857 
4858 	if (got_int)
4859 	    STRCPY(msg_buf, _("(Interrupted) "));
4860 	else
4861 	    *msg_buf = NUL;
4862 
4863 	msg_single = count_only
4864 		    ? NGETTEXT("%ld match on %ld line",
4865 					  "%ld matches on %ld line", sub_nsubs)
4866 		    : NGETTEXT("%ld substitution on %ld line",
4867 				   "%ld substitutions on %ld line", sub_nsubs);
4868 	msg_plural = count_only
4869 		    ? NGETTEXT("%ld match on %ld lines",
4870 					 "%ld matches on %ld lines", sub_nsubs)
4871 		    : NGETTEXT("%ld substitution on %ld lines",
4872 				  "%ld substitutions on %ld lines", sub_nsubs);
4873 
4874 	vim_snprintf_add(msg_buf, sizeof(msg_buf),
4875 				 NGETTEXT(msg_single, msg_plural, sub_nlines),
4876 				 sub_nsubs, (long)sub_nlines);
4877 
4878 	if (msg(msg_buf))
4879 	    /* save message to display it after redraw */
4880 	    set_keep_msg((char_u *)msg_buf, 0);
4881 	return TRUE;
4882     }
4883     if (got_int)
4884     {
4885 	emsg(_(e_interr));
4886 	return TRUE;
4887     }
4888     return FALSE;
4889 }
4890 
4891     static void
4892 global_exe_one(char_u *cmd, linenr_T lnum)
4893 {
4894     curwin->w_cursor.lnum = lnum;
4895     curwin->w_cursor.col = 0;
4896     if (*cmd == NUL || *cmd == '\n')
4897 	do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
4898     else
4899 	do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
4900 }
4901 
4902 /*
4903  * Execute a global command of the form:
4904  *
4905  * g/pattern/X : execute X on all lines where pattern matches
4906  * v/pattern/X : execute X on all lines where pattern does not match
4907  *
4908  * where 'X' is an EX command
4909  *
4910  * The command character (as well as the trailing slash) is optional, and
4911  * is assumed to be 'p' if missing.
4912  *
4913  * This is implemented in two passes: first we scan the file for the pattern and
4914  * set a mark for each line that (not) matches. Secondly we execute the command
4915  * for each line that has a mark. This is required because after deleting
4916  * lines we do not know where to search for the next match.
4917  */
4918     void
4919 ex_global(exarg_T *eap)
4920 {
4921     linenr_T	lnum;		/* line number according to old situation */
4922     int		ndone = 0;
4923     int		type;		/* first char of cmd: 'v' or 'g' */
4924     char_u	*cmd;		/* command argument */
4925 
4926     char_u	delim;		/* delimiter, normally '/' */
4927     char_u	*pat;
4928     regmmatch_T	regmatch;
4929     int		match;
4930     int		which_pat;
4931 
4932     /* When nesting the command works on one line.  This allows for
4933      * ":g/found/v/notfound/command". */
4934     if (global_busy && (eap->line1 != 1
4935 				  || eap->line2 != curbuf->b_ml.ml_line_count))
4936     {
4937 	/* will increment global_busy to break out of the loop */
4938 	emsg(_("E147: Cannot do :global recursive with a range"));
4939 	return;
4940     }
4941 
4942     if (eap->forceit)		    /* ":global!" is like ":vglobal" */
4943 	type = 'v';
4944     else
4945 	type = *eap->cmd;
4946     cmd = eap->arg;
4947     which_pat = RE_LAST;	    /* default: use last used regexp */
4948 
4949     /*
4950      * undocumented vi feature:
4951      *	"\/" and "\?": use previous search pattern.
4952      *		 "\&": use previous substitute pattern.
4953      */
4954     if (*cmd == '\\')
4955     {
4956 	++cmd;
4957 	if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
4958 	{
4959 	    emsg(_(e_backslash));
4960 	    return;
4961 	}
4962 	if (*cmd == '&')
4963 	    which_pat = RE_SUBST;	/* use previous substitute pattern */
4964 	else
4965 	    which_pat = RE_SEARCH;	/* use previous search pattern */
4966 	++cmd;
4967 	pat = (char_u *)"";
4968     }
4969     else if (*cmd == NUL)
4970     {
4971 	emsg(_("E148: Regular expression missing from global"));
4972 	return;
4973     }
4974     else
4975     {
4976 	delim = *cmd;		/* get the delimiter */
4977 	if (delim)
4978 	    ++cmd;		/* skip delimiter if there is one */
4979 	pat = cmd;		/* remember start of pattern */
4980 	cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
4981 	if (cmd[0] == delim)		    /* end delimiter found */
4982 	    *cmd++ = NUL;		    /* replace it with a NUL */
4983     }
4984 
4985     if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, &regmatch) == FAIL)
4986     {
4987 	emsg(_(e_invcmd));
4988 	return;
4989     }
4990 
4991     if (global_busy)
4992     {
4993 	lnum = curwin->w_cursor.lnum;
4994 	match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
4995 						       (colnr_T)0, NULL, NULL);
4996 	if ((type == 'g' && match) || (type == 'v' && !match))
4997 	    global_exe_one(cmd, lnum);
4998     }
4999     else
5000     {
5001 	/*
5002 	 * pass 1: set marks for each (not) matching line
5003 	 */
5004 	for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
5005 	{
5006 	    /* a match on this line? */
5007 	    match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
5008 						       (colnr_T)0, NULL, NULL);
5009 	    if ((type == 'g' && match) || (type == 'v' && !match))
5010 	    {
5011 		ml_setmarked(lnum);
5012 		ndone++;
5013 	    }
5014 	    line_breakcheck();
5015 	}
5016 
5017 	/*
5018 	 * pass 2: execute the command for each line that has been marked
5019 	 */
5020 	if (got_int)
5021 	    msg(_(e_interr));
5022 	else if (ndone == 0)
5023 	{
5024 	    if (type == 'v')
5025 		smsg(_("Pattern found in every line: %s"), pat);
5026 	    else
5027 		smsg(_("Pattern not found: %s"), pat);
5028 	}
5029 	else
5030 	{
5031 #ifdef FEAT_CLIPBOARD
5032 	    start_global_changes();
5033 #endif
5034 	    global_exe(cmd);
5035 #ifdef FEAT_CLIPBOARD
5036 	    end_global_changes();
5037 #endif
5038 	}
5039 
5040 	ml_clearmarked();	   /* clear rest of the marks */
5041     }
5042 
5043     vim_regfree(regmatch.regprog);
5044 }
5045 
5046 /*
5047  * Execute "cmd" on lines marked with ml_setmarked().
5048  */
5049     void
5050 global_exe(char_u *cmd)
5051 {
5052     linenr_T old_lcount;	/* b_ml.ml_line_count before the command */
5053     buf_T    *old_buf = curbuf;	/* remember what buffer we started in */
5054     linenr_T lnum;		/* line number according to old situation */
5055 
5056     /*
5057      * Set current position only once for a global command.
5058      * If global_busy is set, setpcmark() will not do anything.
5059      * If there is an error, global_busy will be incremented.
5060      */
5061     setpcmark();
5062 
5063     /* When the command writes a message, don't overwrite the command. */
5064     msg_didout = TRUE;
5065 
5066     sub_nsubs = 0;
5067     sub_nlines = 0;
5068     global_need_beginline = FALSE;
5069     global_busy = 1;
5070     old_lcount = curbuf->b_ml.ml_line_count;
5071     while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
5072     {
5073 	global_exe_one(cmd, lnum);
5074 	ui_breakcheck();
5075     }
5076 
5077     global_busy = 0;
5078     if (global_need_beginline)
5079 	beginline(BL_WHITE | BL_FIX);
5080     else
5081 	check_cursor();	/* cursor may be beyond the end of the line */
5082 
5083     /* the cursor may not have moved in the text but a change in a previous
5084      * line may move it on the screen */
5085     changed_line_abv_curs();
5086 
5087     /* If it looks like no message was written, allow overwriting the
5088      * command with the report for number of changes. */
5089     if (msg_col == 0 && msg_scrolled == 0)
5090 	msg_didout = FALSE;
5091 
5092     /* If substitutes done, report number of substitutes, otherwise report
5093      * number of extra or deleted lines.
5094      * Don't report extra or deleted lines in the edge case where the buffer
5095      * we are in after execution is different from the buffer we started in. */
5096     if (!do_sub_msg(FALSE) && curbuf == old_buf)
5097 	msgmore(curbuf->b_ml.ml_line_count - old_lcount);
5098 }
5099 
5100 #ifdef FEAT_VIMINFO
5101 /*
5102  * Get the previous substitute pattern.
5103  */
5104     char_u *
5105 get_old_sub(void)
5106 {
5107     return old_sub;
5108 }
5109 
5110 /*
5111  * Set the previous substitute pattern.  "val" must be allocated.
5112  */
5113     void
5114 set_old_sub(char_u *val)
5115 {
5116     vim_free(old_sub);
5117     old_sub = val;
5118 }
5119 #endif // FEAT_VIMINFO
5120 
5121 #if defined(EXITFREE) || defined(PROTO)
5122     void
5123 free_old_sub(void)
5124 {
5125     vim_free(old_sub);
5126 }
5127 #endif
5128 
5129 #if defined(FEAT_QUICKFIX) || defined(PROTO)
5130 /*
5131  * Set up for a tagpreview.
5132  * Return TRUE when it was created.
5133  */
5134     int
5135 prepare_tagpreview(
5136     int		undo_sync)	/* sync undo when leaving the window */
5137 {
5138     win_T	*wp;
5139 
5140 # ifdef FEAT_GUI
5141     need_mouse_correct = TRUE;
5142 # endif
5143 
5144     /*
5145      * If there is already a preview window open, use that one.
5146      */
5147     if (!curwin->w_p_pvw)
5148     {
5149 # ifdef FEAT_TEXT_PROP
5150 	if (*p_pvp != NUL)
5151 	{
5152 	    wp = popup_find_preview_window();
5153 	    if (wp != NULL)
5154 		popup_set_wantpos(wp, wp->w_minwidth);
5155 	}
5156 	else
5157 # endif
5158 	{
5159 	    FOR_ALL_WINDOWS(wp)
5160 		if (wp->w_p_pvw)
5161 		    break;
5162 	}
5163 	if (wp != NULL)
5164 	    win_enter(wp, undo_sync);
5165 	else
5166 	{
5167 	    /*
5168 	     * There is no preview window open yet.  Create one.
5169 	     */
5170 # ifdef FEAT_TEXT_PROP
5171 	    if (*p_pvp != NUL)
5172 		return popup_create_preview_window();
5173 # endif
5174 	    if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0) == FAIL)
5175 		return FALSE;
5176 	    curwin->w_p_pvw = TRUE;
5177 	    curwin->w_p_wfh = TRUE;
5178 	    RESET_BINDING(curwin);	    // don't take over 'scrollbind'
5179 	    // and 'cursorbind'
5180 # ifdef FEAT_DIFF
5181 	    curwin->w_p_diff = FALSE;	    // no 'diff'
5182 # endif
5183 # ifdef FEAT_FOLDING
5184 	    curwin->w_p_fdc = 0;	    // no 'foldcolumn'
5185 # endif
5186 	    return TRUE;
5187 	}
5188     }
5189     return FALSE;
5190 }
5191 
5192 #endif
5193 
5194 
5195 /*
5196  * ":help": open a read-only window on a help file
5197  */
5198     void
5199 ex_help(exarg_T *eap)
5200 {
5201     char_u	*arg;
5202     char_u	*tag;
5203     FILE	*helpfd;	/* file descriptor of help file */
5204     int		n;
5205     int		i;
5206     win_T	*wp;
5207     int		num_matches;
5208     char_u	**matches;
5209     char_u	*p;
5210     int		empty_fnum = 0;
5211     int		alt_fnum = 0;
5212     buf_T	*buf;
5213 #ifdef FEAT_MULTI_LANG
5214     int		len;
5215     char_u	*lang;
5216 #endif
5217 #ifdef FEAT_FOLDING
5218     int		old_KeyTyped = KeyTyped;
5219 #endif
5220 
5221     if (eap != NULL)
5222     {
5223 	/*
5224 	 * A ":help" command ends at the first LF, or at a '|' that is
5225 	 * followed by some text.  Set nextcmd to the following command.
5226 	 */
5227 	for (arg = eap->arg; *arg; ++arg)
5228 	{
5229 	    if (*arg == '\n' || *arg == '\r'
5230 		    || (*arg == '|' && arg[1] != NUL && arg[1] != '|'))
5231 	    {
5232 		*arg++ = NUL;
5233 		eap->nextcmd = arg;
5234 		break;
5235 	    }
5236 	}
5237 	arg = eap->arg;
5238 
5239 	if (eap->forceit && *arg == NUL && !curbuf->b_help)
5240 	{
5241 	    emsg(_("E478: Don't panic!"));
5242 	    return;
5243 	}
5244 
5245 	if (eap->skip)	    /* not executing commands */
5246 	    return;
5247     }
5248     else
5249 	arg = (char_u *)"";
5250 
5251     /* remove trailing blanks */
5252     p = arg + STRLEN(arg) - 1;
5253     while (p > arg && VIM_ISWHITE(*p) && p[-1] != '\\')
5254 	*p-- = NUL;
5255 
5256 #ifdef FEAT_MULTI_LANG
5257     /* Check for a specified language */
5258     lang = check_help_lang(arg);
5259 #endif
5260 
5261     /* When no argument given go to the index. */
5262     if (*arg == NUL)
5263 	arg = (char_u *)"help.txt";
5264 
5265     /*
5266      * Check if there is a match for the argument.
5267      */
5268     n = find_help_tags(arg, &num_matches, &matches,
5269 						 eap != NULL && eap->forceit);
5270 
5271     i = 0;
5272 #ifdef FEAT_MULTI_LANG
5273     if (n != FAIL && lang != NULL)
5274 	/* Find first item with the requested language. */
5275 	for (i = 0; i < num_matches; ++i)
5276 	{
5277 	    len = (int)STRLEN(matches[i]);
5278 	    if (len > 3 && matches[i][len - 3] == '@'
5279 				  && STRICMP(matches[i] + len - 2, lang) == 0)
5280 		break;
5281 	}
5282 #endif
5283     if (i >= num_matches || n == FAIL)
5284     {
5285 #ifdef FEAT_MULTI_LANG
5286 	if (lang != NULL)
5287 	    semsg(_("E661: Sorry, no '%s' help for %s"), lang, arg);
5288 	else
5289 #endif
5290 	    semsg(_("E149: Sorry, no help for %s"), arg);
5291 	if (n != FAIL)
5292 	    FreeWild(num_matches, matches);
5293 	return;
5294     }
5295 
5296     /* The first match (in the requested language) is the best match. */
5297     tag = vim_strsave(matches[i]);
5298     FreeWild(num_matches, matches);
5299 
5300 #ifdef FEAT_GUI
5301     need_mouse_correct = TRUE;
5302 #endif
5303 
5304     /*
5305      * Re-use an existing help window or open a new one.
5306      * Always open a new one for ":tab help".
5307      */
5308     if (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)
5309     {
5310 	if (cmdmod.tab != 0)
5311 	    wp = NULL;
5312 	else
5313 	    FOR_ALL_WINDOWS(wp)
5314 		if (bt_help(wp->w_buffer))
5315 		    break;
5316 	if (wp != NULL && wp->w_buffer->b_nwindows > 0)
5317 	    win_enter(wp, TRUE);
5318 	else
5319 	{
5320 	    /*
5321 	     * There is no help window yet.
5322 	     * Try to open the file specified by the "helpfile" option.
5323 	     */
5324 	    if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL)
5325 	    {
5326 		smsg(_("Sorry, help file \"%s\" not found"), p_hf);
5327 		goto erret;
5328 	    }
5329 	    fclose(helpfd);
5330 
5331 	    /* Split off help window; put it at far top if no position
5332 	     * specified, the current window is vertically split and
5333 	     * narrow. */
5334 	    n = WSP_HELP;
5335 	    if (cmdmod.split == 0 && curwin->w_width != Columns
5336 						  && curwin->w_width < 80)
5337 		n |= WSP_TOP;
5338 	    if (win_split(0, n) == FAIL)
5339 		goto erret;
5340 
5341 	    if (curwin->w_height < p_hh)
5342 		win_setheight((int)p_hh);
5343 
5344 	    /*
5345 	     * Open help file (do_ecmd() will set b_help flag, readfile() will
5346 	     * set b_p_ro flag).
5347 	     * Set the alternate file to the previously edited file.
5348 	     */
5349 	    alt_fnum = curbuf->b_fnum;
5350 	    (void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
5351 			  ECMD_HIDE + ECMD_SET_HELP,
5352 			  NULL);  /* buffer is still open, don't store info */
5353 	    if (!cmdmod.keepalt)
5354 		curwin->w_alt_fnum = alt_fnum;
5355 	    empty_fnum = curbuf->b_fnum;
5356 	}
5357     }
5358 
5359     if (!p_im)
5360 	restart_edit = 0;	    /* don't want insert mode in help file */
5361 
5362 #ifdef FEAT_FOLDING
5363     /* Restore KeyTyped, setting 'filetype=help' may reset it.
5364      * It is needed for do_tag top open folds under the cursor. */
5365     KeyTyped = old_KeyTyped;
5366 #endif
5367 
5368     if (tag != NULL)
5369 	do_tag(tag, DT_HELP, 1, FALSE, TRUE);
5370 
5371     /* Delete the empty buffer if we're not using it.  Careful: autocommands
5372      * may have jumped to another window, check that the buffer is not in a
5373      * window. */
5374     if (empty_fnum != 0 && curbuf->b_fnum != empty_fnum)
5375     {
5376 	buf = buflist_findnr(empty_fnum);
5377 	if (buf != NULL && buf->b_nwindows == 0)
5378 	    wipe_buffer(buf, TRUE);
5379     }
5380 
5381     /* keep the previous alternate file */
5382     if (alt_fnum != 0 && curwin->w_alt_fnum == empty_fnum && !cmdmod.keepalt)
5383 	curwin->w_alt_fnum = alt_fnum;
5384 
5385 erret:
5386     vim_free(tag);
5387 }
5388 
5389 /*
5390  * ":helpclose": Close one help window
5391  */
5392     void
5393 ex_helpclose(exarg_T *eap UNUSED)
5394 {
5395     win_T *win;
5396 
5397     FOR_ALL_WINDOWS(win)
5398     {
5399 	if (bt_help(win->w_buffer))
5400 	{
5401 	    win_close(win, FALSE);
5402 	    return;
5403 	}
5404     }
5405 }
5406 
5407 #if defined(FEAT_MULTI_LANG) || defined(PROTO)
5408 /*
5409  * In an argument search for a language specifiers in the form "@xx".
5410  * Changes the "@" to NUL if found, and returns a pointer to "xx".
5411  * Returns NULL if not found.
5412  */
5413     char_u *
5414 check_help_lang(char_u *arg)
5415 {
5416     int len = (int)STRLEN(arg);
5417 
5418     if (len >= 3 && arg[len - 3] == '@' && ASCII_ISALPHA(arg[len - 2])
5419 					       && ASCII_ISALPHA(arg[len - 1]))
5420     {
5421 	arg[len - 3] = NUL;		/* remove the '@' */
5422 	return arg + len - 2;
5423     }
5424     return NULL;
5425 }
5426 #endif
5427 
5428 /*
5429  * Return a heuristic indicating how well the given string matches.  The
5430  * smaller the number, the better the match.  This is the order of priorities,
5431  * from best match to worst match:
5432  *	- Match with least alpha-numeric characters is better.
5433  *	- Match with least total characters is better.
5434  *	- Match towards the start is better.
5435  *	- Match starting with "+" is worse (feature instead of command)
5436  * Assumption is made that the matched_string passed has already been found to
5437  * match some string for which help is requested.  webb.
5438  */
5439     int
5440 help_heuristic(
5441     char_u	*matched_string,
5442     int		offset,			/* offset for match */
5443     int		wrong_case)		/* no matching case */
5444 {
5445     int		num_letters;
5446     char_u	*p;
5447 
5448     num_letters = 0;
5449     for (p = matched_string; *p; p++)
5450 	if (ASCII_ISALNUM(*p))
5451 	    num_letters++;
5452 
5453     /*
5454      * Multiply the number of letters by 100 to give it a much bigger
5455      * weighting than the number of characters.
5456      * If there only is a match while ignoring case, add 5000.
5457      * If the match starts in the middle of a word, add 10000 to put it
5458      * somewhere in the last half.
5459      * If the match is more than 2 chars from the start, multiply by 200 to
5460      * put it after matches at the start.
5461      */
5462     if (ASCII_ISALNUM(matched_string[offset]) && offset > 0
5463 				 && ASCII_ISALNUM(matched_string[offset - 1]))
5464 	offset += 10000;
5465     else if (offset > 2)
5466 	offset *= 200;
5467     if (wrong_case)
5468 	offset += 5000;
5469     /* Features are less interesting than the subjects themselves, but "+"
5470      * alone is not a feature. */
5471     if (matched_string[0] == '+' && matched_string[1] != NUL)
5472 	offset += 100;
5473     return (int)(100 * num_letters + STRLEN(matched_string) + offset);
5474 }
5475 
5476 /*
5477  * Compare functions for qsort() below, that checks the help heuristics number
5478  * that has been put after the tagname by find_tags().
5479  */
5480     static int
5481 help_compare(const void *s1, const void *s2)
5482 {
5483     char    *p1;
5484     char    *p2;
5485 
5486     p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
5487     p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
5488     return strcmp(p1, p2);
5489 }
5490 
5491 /*
5492  * Find all help tags matching "arg", sort them and return in matches[], with
5493  * the number of matches in num_matches.
5494  * The matches will be sorted with a "best" match algorithm.
5495  * When "keep_lang" is TRUE try keeping the language of the current buffer.
5496  */
5497     int
5498 find_help_tags(
5499     char_u	*arg,
5500     int		*num_matches,
5501     char_u	***matches,
5502     int		keep_lang)
5503 {
5504     char_u	*s, *d;
5505     int		i;
5506     static char *(mtable[]) = {"*", "g*", "[*", "]*", ":*",
5507 			       "/*", "/\\*", "\"*", "**",
5508 			       "cpo-*", "/\\(\\)", "/\\%(\\)",
5509 			       "?", ":?", "?<CR>", "g?", "g?g?", "g??",
5510 			       "-?", "q?", "v_g?",
5511 			       "/\\?", "/\\z(\\)", "\\=", ":s\\=",
5512 			       "[count]", "[quotex]",
5513 			       "[range]", ":[range]",
5514 			       "[pattern]", "\\|", "\\%$",
5515 			       "s/\\~", "s/\\U", "s/\\L",
5516 			       "s/\\1", "s/\\2", "s/\\3", "s/\\9"};
5517     static char *(rtable[]) = {"star", "gstar", "[star", "]star", ":star",
5518 			       "/star", "/\\\\star", "quotestar", "starstar",
5519 			       "cpo-star", "/\\\\(\\\\)", "/\\\\%(\\\\)",
5520 			       "?", ":?", "?<CR>", "g?", "g?g?", "g??",
5521 			       "-?", "q?", "v_g?",
5522 			       "/\\\\?", "/\\\\z(\\\\)", "\\\\=", ":s\\\\=",
5523 			       "\\[count]", "\\[quotex]",
5524 			       "\\[range]", ":\\[range]",
5525 			       "\\[pattern]", "\\\\bar", "/\\\\%\\$",
5526 			       "s/\\\\\\~", "s/\\\\U", "s/\\\\L",
5527 			       "s/\\\\1", "s/\\\\2", "s/\\\\3", "s/\\\\9"};
5528     static char *(expr_table[]) = {"!=?", "!~?", "<=?", "<?", "==?", "=~?",
5529 				">=?", ">?", "is?", "isnot?"};
5530     int flags;
5531 
5532     d = IObuff;		    /* assume IObuff is long enough! */
5533 
5534     if (STRNICMP(arg, "expr-", 5) == 0)
5535     {
5536 	// When the string starting with "expr-" and containing '?' and matches
5537 	// the table, it is taken literally.  Otherwise '?' is recognized as a
5538 	// wildcard.
5539 	for (i = (int)(sizeof(expr_table) / sizeof(char *)); --i >= 0; )
5540 	    if (STRCMP(arg + 5, expr_table[i]) == 0)
5541 	    {
5542 		STRCPY(d, arg);
5543 		break;
5544 	    }
5545     }
5546     else
5547     {
5548 	// Recognize a few exceptions to the rule.  Some strings that contain
5549 	// '*' with "star".  Otherwise '*' is recognized as a wildcard.
5550 	for (i = (int)(sizeof(mtable) / sizeof(char *)); --i >= 0; )
5551 	    if (STRCMP(arg, mtable[i]) == 0)
5552 	    {
5553 		STRCPY(d, rtable[i]);
5554 		break;
5555 	    }
5556     }
5557 
5558     if (i < 0)	/* no match in table */
5559     {
5560 	/* Replace "\S" with "/\\S", etc.  Otherwise every tag is matched.
5561 	 * Also replace "\%^" and "\%(", they match every tag too.
5562 	 * Also "\zs", "\z1", etc.
5563 	 * Also "\@<", "\@=", "\@<=", etc.
5564 	 * And also "\_$" and "\_^". */
5565 	if (arg[0] == '\\'
5566 		&& ((arg[1] != NUL && arg[2] == NUL)
5567 		    || (vim_strchr((char_u *)"%_z@", arg[1]) != NULL
5568 							   && arg[2] != NUL)))
5569 	{
5570 	    STRCPY(d, "/\\\\");
5571 	    STRCPY(d + 3, arg + 1);
5572 	    /* Check for "/\\_$", should be "/\\_\$" */
5573 	    if (d[3] == '_' && d[4] == '$')
5574 		STRCPY(d + 4, "\\$");
5575 	}
5576 	else
5577 	{
5578 	  /* Replace:
5579 	   * "[:...:]" with "\[:...:]"
5580 	   * "[++...]" with "\[++...]"
5581 	   * "\{" with "\\{"		   -- matching "} \}"
5582 	   */
5583 	    if ((arg[0] == '[' && (arg[1] == ':'
5584 			 || (arg[1] == '+' && arg[2] == '+')))
5585 		    || (arg[0] == '\\' && arg[1] == '{'))
5586 	      *d++ = '\\';
5587 
5588 	  /*
5589 	   * If tag starts with "('", skip the "(". Fixes CTRL-] on ('option'.
5590 	   */
5591 	  if (*arg == '(' && arg[1] == '\'')
5592 	      arg++;
5593 	  for (s = arg; *s; ++s)
5594 	  {
5595 	    /*
5596 	     * Replace "|" with "bar" and '"' with "quote" to match the name of
5597 	     * the tags for these commands.
5598 	     * Replace "*" with ".*" and "?" with "." to match command line
5599 	     * completion.
5600 	     * Insert a backslash before '~', '$' and '.' to avoid their
5601 	     * special meaning.
5602 	     */
5603 	    if (d - IObuff > IOSIZE - 10)	/* getting too long!? */
5604 		break;
5605 	    switch (*s)
5606 	    {
5607 		case '|':   STRCPY(d, "bar");
5608 			    d += 3;
5609 			    continue;
5610 		case '"':   STRCPY(d, "quote");
5611 			    d += 5;
5612 			    continue;
5613 		case '*':   *d++ = '.';
5614 			    break;
5615 		case '?':   *d++ = '.';
5616 			    continue;
5617 		case '$':
5618 		case '.':
5619 		case '~':   *d++ = '\\';
5620 			    break;
5621 	    }
5622 
5623 	    /*
5624 	     * Replace "^x" by "CTRL-X". Don't do this for "^_" to make
5625 	     * ":help i_^_CTRL-D" work.
5626 	     * Insert '-' before and after "CTRL-X" when applicable.
5627 	     */
5628 	    if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1])
5629 			   || vim_strchr((char_u *)"?@[\\]^", s[1]) != NULL)))
5630 	    {
5631 		if (d > IObuff && d[-1] != '_' && d[-1] != '\\')
5632 		    *d++ = '_';		/* prepend a '_' to make x_CTRL-x */
5633 		STRCPY(d, "CTRL-");
5634 		d += 5;
5635 		if (*s < ' ')
5636 		{
5637 #ifdef EBCDIC
5638 		    *d++ = CtrlChar(*s);
5639 #else
5640 		    *d++ = *s + '@';
5641 #endif
5642 		    if (d[-1] == '\\')
5643 			*d++ = '\\';	/* double a backslash */
5644 		}
5645 		else
5646 		    *d++ = *++s;
5647 		if (s[1] != NUL && s[1] != '_')
5648 		    *d++ = '_';		/* append a '_' */
5649 		continue;
5650 	    }
5651 	    else if (*s == '^')		/* "^" or "CTRL-^" or "^_" */
5652 		*d++ = '\\';
5653 
5654 	    /*
5655 	     * Insert a backslash before a backslash after a slash, for search
5656 	     * pattern tags: "/\|" --> "/\\|".
5657 	     */
5658 	    else if (s[0] == '\\' && s[1] != '\\'
5659 					       && *arg == '/' && s == arg + 1)
5660 		*d++ = '\\';
5661 
5662 	    /* "CTRL-\_" -> "CTRL-\\_" to avoid the special meaning of "\_" in
5663 	     * "CTRL-\_CTRL-N" */
5664 	    if (STRNICMP(s, "CTRL-\\_", 7) == 0)
5665 	    {
5666 		STRCPY(d, "CTRL-\\\\");
5667 		d += 7;
5668 		s += 6;
5669 	    }
5670 
5671 	    *d++ = *s;
5672 
5673 	    /*
5674 	     * If tag contains "({" or "([", tag terminates at the "(".
5675 	     * This is for help on functions, e.g.: abs({expr}).
5676 	     */
5677 	    if (*s == '(' && (s[1] == '{' || s[1] =='['))
5678 		break;
5679 
5680 	    /*
5681 	     * If tag starts with ', toss everything after a second '. Fixes
5682 	     * CTRL-] on 'option'. (would include the trailing '.').
5683 	     */
5684 	    if (*s == '\'' && s > arg && *arg == '\'')
5685 		break;
5686 	    /* Also '{' and '}'. */
5687 	    if (*s == '}' && s > arg && *arg == '{')
5688 		break;
5689 	  }
5690 	  *d = NUL;
5691 
5692 	  if (*IObuff == '`')
5693 	  {
5694 	      if (d > IObuff + 2 && d[-1] == '`')
5695 	      {
5696 		  /* remove the backticks from `command` */
5697 		  mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff));
5698 		  d[-2] = NUL;
5699 	      }
5700 	      else if (d > IObuff + 3 && d[-2] == '`' && d[-1] == ',')
5701 	      {
5702 		  /* remove the backticks and comma from `command`, */
5703 		  mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff));
5704 		  d[-3] = NUL;
5705 	      }
5706 	      else if (d > IObuff + 4 && d[-3] == '`'
5707 					     && d[-2] == '\\' && d[-1] == '.')
5708 	      {
5709 		  /* remove the backticks and dot from `command`\. */
5710 		  mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff));
5711 		  d[-4] = NUL;
5712 	      }
5713 	  }
5714 	}
5715     }
5716 
5717     *matches = (char_u **)"";
5718     *num_matches = 0;
5719     flags = TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE | TAG_NO_TAGFUNC;
5720     if (keep_lang)
5721 	flags |= TAG_KEEP_LANG;
5722     if (find_tags(IObuff, num_matches, matches, flags, (int)MAXCOL, NULL) == OK
5723 	    && *num_matches > 0)
5724     {
5725 	/* Sort the matches found on the heuristic number that is after the
5726 	 * tag name. */
5727 	qsort((void *)*matches, (size_t)*num_matches,
5728 					      sizeof(char_u *), help_compare);
5729 	/* Delete more than TAG_MANY to reduce the size of the listing. */
5730 	while (*num_matches > TAG_MANY)
5731 	    vim_free((*matches)[--*num_matches]);
5732     }
5733     return OK;
5734 }
5735 
5736 /*
5737  * Called when starting to edit a buffer for a help file.
5738  */
5739     static void
5740 prepare_help_buffer(void)
5741 {
5742     char_u	*p;
5743 
5744     curbuf->b_help = TRUE;
5745 #ifdef FEAT_QUICKFIX
5746     set_string_option_direct((char_u *)"buftype", -1,
5747 				     (char_u *)"help", OPT_FREE|OPT_LOCAL, 0);
5748 #endif
5749 
5750     /*
5751      * Always set these options after jumping to a help tag, because the
5752      * user may have an autocommand that gets in the way.
5753      * Accept all ASCII chars for keywords, except ' ', '*', '"', '|', and
5754      * latin1 word characters (for translated help files).
5755      * Only set it when needed, buf_init_chartab() is some work.
5756      */
5757     p =
5758 #ifdef EBCDIC
5759 	    (char_u *)"65-255,^*,^|,^\"";
5760 #else
5761 	    (char_u *)"!-~,^*,^|,^\",192-255";
5762 #endif
5763     if (STRCMP(curbuf->b_p_isk, p) != 0)
5764     {
5765 	set_string_option_direct((char_u *)"isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
5766 	check_buf_options(curbuf);
5767 	(void)buf_init_chartab(curbuf, FALSE);
5768     }
5769 
5770 #ifdef FEAT_FOLDING
5771     /* Don't use the global foldmethod.*/
5772     set_string_option_direct((char_u *)"fdm", -1, (char_u *)"manual",
5773 						       OPT_FREE|OPT_LOCAL, 0);
5774 #endif
5775 
5776     curbuf->b_p_ts = 8;		/* 'tabstop' is 8 */
5777     curwin->w_p_list = FALSE;	/* no list mode */
5778 
5779     curbuf->b_p_ma = FALSE;		/* not modifiable */
5780     curbuf->b_p_bin = FALSE;	/* reset 'bin' before reading file */
5781     curwin->w_p_nu = 0;		/* no line numbers */
5782     curwin->w_p_rnu = 0;		/* no relative line numbers */
5783     RESET_BINDING(curwin);		/* no scroll or cursor binding */
5784 #ifdef FEAT_ARABIC
5785     curwin->w_p_arab = FALSE;	/* no arabic mode */
5786 #endif
5787 #ifdef FEAT_RIGHTLEFT
5788     curwin->w_p_rl  = FALSE;	/* help window is left-to-right */
5789 #endif
5790 #ifdef FEAT_FOLDING
5791     curwin->w_p_fen = FALSE;	/* No folding in the help window */
5792 #endif
5793 #ifdef FEAT_DIFF
5794     curwin->w_p_diff = FALSE;	/* No 'diff' */
5795 #endif
5796 #ifdef FEAT_SPELL
5797     curwin->w_p_spell = FALSE;	/* No spell checking */
5798 #endif
5799 
5800     set_buflisted(FALSE);
5801 }
5802 
5803 /*
5804  * After reading a help file: May cleanup a help buffer when syntax
5805  * highlighting is not used.
5806  */
5807     void
5808 fix_help_buffer(void)
5809 {
5810     linenr_T	lnum;
5811     char_u	*line;
5812     int		in_example = FALSE;
5813     int		len;
5814     char_u	*fname;
5815     char_u	*p;
5816     char_u	*rt;
5817     int		mustfree;
5818 
5819     /* Set filetype to "help" if still needed. */
5820     if (STRCMP(curbuf->b_p_ft, "help") != 0)
5821     {
5822 	++curbuf_lock;
5823 	set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
5824 	--curbuf_lock;
5825     }
5826 
5827 #ifdef FEAT_SYN_HL
5828     if (!syntax_present(curwin))
5829 #endif
5830     {
5831 	for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
5832 	{
5833 	    line = ml_get_buf(curbuf, lnum, FALSE);
5834 	    len = (int)STRLEN(line);
5835 	    if (in_example && len > 0 && !VIM_ISWHITE(line[0]))
5836 	    {
5837 		/* End of example: non-white or '<' in first column. */
5838 		if (line[0] == '<')
5839 		{
5840 		    /* blank-out a '<' in the first column */
5841 		    line = ml_get_buf(curbuf, lnum, TRUE);
5842 		    line[0] = ' ';
5843 		}
5844 		in_example = FALSE;
5845 	    }
5846 	    if (!in_example && len > 0)
5847 	    {
5848 		if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' '))
5849 		{
5850 		    /* blank-out a '>' in the last column (start of example) */
5851 		    line = ml_get_buf(curbuf, lnum, TRUE);
5852 		    line[len - 1] = ' ';
5853 		    in_example = TRUE;
5854 		}
5855 		else if (line[len - 1] == '~')
5856 		{
5857 		    /* blank-out a '~' at the end of line (header marker) */
5858 		    line = ml_get_buf(curbuf, lnum, TRUE);
5859 		    line[len - 1] = ' ';
5860 		}
5861 	    }
5862 	}
5863     }
5864 
5865     /*
5866      * In the "help.txt" and "help.abx" file, add the locally added help
5867      * files.  This uses the very first line in the help file.
5868      */
5869     fname = gettail(curbuf->b_fname);
5870     if (fnamecmp(fname, "help.txt") == 0
5871 #ifdef FEAT_MULTI_LANG
5872 	|| (fnamencmp(fname, "help.", 5) == 0
5873 	    && ASCII_ISALPHA(fname[5])
5874 	    && ASCII_ISALPHA(fname[6])
5875 	    && TOLOWER_ASC(fname[7]) == 'x'
5876 	    && fname[8] == NUL)
5877 #endif
5878 	)
5879     {
5880 	for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum)
5881 	{
5882 	    line = ml_get_buf(curbuf, lnum, FALSE);
5883 	    if (strstr((char *)line, "*local-additions*") == NULL)
5884 		continue;
5885 
5886 	    /* Go through all directories in 'runtimepath', skipping
5887 	     * $VIMRUNTIME. */
5888 	    p = p_rtp;
5889 	    while (*p != NUL)
5890 	    {
5891 		copy_option_part(&p, NameBuff, MAXPATHL, ",");
5892 		mustfree = FALSE;
5893 		rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
5894 		if (rt != NULL &&
5895 			    fullpathcmp(rt, NameBuff, FALSE, TRUE) != FPC_SAME)
5896 		{
5897 		    int		fcount;
5898 		    char_u	**fnames;
5899 		    FILE	*fd;
5900 		    char_u	*s;
5901 		    int		fi;
5902 		    vimconv_T	vc;
5903 		    char_u	*cp;
5904 
5905 		    /* Find all "doc/ *.txt" files in this directory. */
5906 		    add_pathsep(NameBuff);
5907 #ifdef FEAT_MULTI_LANG
5908 		    STRCAT(NameBuff, "doc/*.??[tx]");
5909 #else
5910 		    STRCAT(NameBuff, "doc/*.txt");
5911 #endif
5912 		    if (gen_expand_wildcards(1, &NameBuff, &fcount,
5913 					 &fnames, EW_FILE|EW_SILENT) == OK
5914 			    && fcount > 0)
5915 		    {
5916 #ifdef FEAT_MULTI_LANG
5917 			int	i1, i2;
5918 			char_u	*f1, *f2;
5919 			char_u	*t1, *t2;
5920 			char_u	*e1, *e2;
5921 
5922 			/* If foo.abx is found use it instead of foo.txt in
5923 			 * the same directory. */
5924 			for (i1 = 0; i1 < fcount; ++i1)
5925 			{
5926 			    for (i2 = 0; i2 < fcount; ++i2)
5927 			    {
5928 				if (i1 == i2)
5929 				    continue;
5930 				if (fnames[i1] == NULL || fnames[i2] == NULL)
5931 				    continue;
5932 				f1 = fnames[i1];
5933 				f2 = fnames[i2];
5934 				t1 = gettail(f1);
5935 				t2 = gettail(f2);
5936 				e1 = vim_strrchr(t1, '.');
5937 				e2 = vim_strrchr(t2, '.');
5938 				if (e1 == NULL || e2 == NULL)
5939 				    continue;
5940 				if (fnamecmp(e1, ".txt") != 0
5941 				    && fnamecmp(e1, fname + 4) != 0)
5942 				{
5943 				    /* Not .txt and not .abx, remove it. */
5944 				    VIM_CLEAR(fnames[i1]);
5945 				    continue;
5946 				}
5947 				if (e1 - f1 != e2 - f2
5948 					    || fnamencmp(f1, f2, e1 - f1) != 0)
5949 				    continue;
5950 				if (fnamecmp(e1, ".txt") == 0
5951 				    && fnamecmp(e2, fname + 4) == 0)
5952 				    /* use .abx instead of .txt */
5953 				    VIM_CLEAR(fnames[i1]);
5954 			    }
5955 			}
5956 #endif
5957 			for (fi = 0; fi < fcount; ++fi)
5958 			{
5959 			    if (fnames[fi] == NULL)
5960 				continue;
5961 			    fd = mch_fopen((char *)fnames[fi], "r");
5962 			    if (fd != NULL)
5963 			    {
5964 				vim_fgets(IObuff, IOSIZE, fd);
5965 				if (IObuff[0] == '*'
5966 					&& (s = vim_strchr(IObuff + 1, '*'))
5967 								  != NULL)
5968 				{
5969 				    int	this_utf = MAYBE;
5970 
5971 				    /* Change tag definition to a
5972 				     * reference and remove <CR>/<NL>. */
5973 				    IObuff[0] = '|';
5974 				    *s = '|';
5975 				    while (*s != NUL)
5976 				    {
5977 					if (*s == '\r' || *s == '\n')
5978 					    *s = NUL;
5979 					/* The text is utf-8 when a byte
5980 					 * above 127 is found and no
5981 					 * illegal byte sequence is found.
5982 					 */
5983 					if (*s >= 0x80 && this_utf != FALSE)
5984 					{
5985 					    int	l;
5986 
5987 					    this_utf = TRUE;
5988 					    l = utf_ptr2len(s);
5989 					    if (l == 1)
5990 						this_utf = FALSE;
5991 					    s += l - 1;
5992 					}
5993 					++s;
5994 				    }
5995 
5996 				    /* The help file is latin1 or utf-8;
5997 				     * conversion to the current
5998 				     * 'encoding' may be required. */
5999 				    vc.vc_type = CONV_NONE;
6000 				    convert_setup(&vc, (char_u *)(
6001 						this_utf == TRUE ? "utf-8"
6002 						      : "latin1"), p_enc);
6003 				    if (vc.vc_type == CONV_NONE)
6004 					/* No conversion needed. */
6005 					cp = IObuff;
6006 				    else
6007 				    {
6008 					/* Do the conversion.  If it fails
6009 					 * use the unconverted text. */
6010 					cp = string_convert(&vc, IObuff,
6011 								    NULL);
6012 					if (cp == NULL)
6013 					    cp = IObuff;
6014 				    }
6015 				    convert_setup(&vc, NULL, NULL);
6016 
6017 				    ml_append(lnum, cp, (colnr_T)0, FALSE);
6018 				    if (cp != IObuff)
6019 					vim_free(cp);
6020 				    ++lnum;
6021 				}
6022 				fclose(fd);
6023 			    }
6024 			}
6025 			FreeWild(fcount, fnames);
6026 		    }
6027 		}
6028 		if (mustfree)
6029 		    vim_free(rt);
6030 	    }
6031 	    break;
6032 	}
6033     }
6034 }
6035 
6036 /*
6037  * ":exusage"
6038  */
6039     void
6040 ex_exusage(exarg_T *eap UNUSED)
6041 {
6042     do_cmdline_cmd((char_u *)"help ex-cmd-index");
6043 }
6044 
6045 /*
6046  * ":viusage"
6047  */
6048     void
6049 ex_viusage(exarg_T *eap UNUSED)
6050 {
6051     do_cmdline_cmd((char_u *)"help normal-index");
6052 }
6053 
6054 /*
6055  * Generate tags in one help directory.
6056  */
6057     static void
6058 helptags_one(
6059     char_u	*dir,		/* doc directory */
6060     char_u	*ext,		/* suffix, ".txt", ".itx", ".frx", etc. */
6061     char_u	*tagfname,	/* "tags" for English, "tags-fr" for French. */
6062     int		add_help_tags)	/* add "help-tags" tag */
6063 {
6064     FILE	*fd_tags;
6065     FILE	*fd;
6066     garray_T	ga;
6067     int		filecount;
6068     char_u	**files;
6069     char_u	*p1, *p2;
6070     int		fi;
6071     char_u	*s;
6072     int		i;
6073     char_u	*fname;
6074     int		dirlen;
6075     int		utf8 = MAYBE;
6076     int		this_utf8;
6077     int		firstline;
6078     int		mix = FALSE;	/* detected mixed encodings */
6079 
6080     /*
6081      * Find all *.txt files.
6082      */
6083     dirlen = (int)STRLEN(dir);
6084     STRCPY(NameBuff, dir);
6085     STRCAT(NameBuff, "/**/*");
6086     STRCAT(NameBuff, ext);
6087     if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
6088 						    EW_FILE|EW_SILENT) == FAIL
6089 	    || filecount == 0)
6090     {
6091 	if (!got_int)
6092 	    semsg(_("E151: No match: %s"), NameBuff);
6093 	return;
6094     }
6095 
6096     /*
6097      * Open the tags file for writing.
6098      * Do this before scanning through all the files.
6099      */
6100     STRCPY(NameBuff, dir);
6101     add_pathsep(NameBuff);
6102     STRCAT(NameBuff, tagfname);
6103     fd_tags = mch_fopen((char *)NameBuff, "w");
6104     if (fd_tags == NULL)
6105     {
6106 	semsg(_("E152: Cannot open %s for writing"), NameBuff);
6107 	FreeWild(filecount, files);
6108 	return;
6109     }
6110 
6111     /*
6112      * If using the "++t" argument or generating tags for "$VIMRUNTIME/doc"
6113      * add the "help-tags" tag.
6114      */
6115     ga_init2(&ga, (int)sizeof(char_u *), 100);
6116     if (add_help_tags || fullpathcmp((char_u *)"$VIMRUNTIME/doc",
6117 						dir, FALSE, TRUE) == FPC_SAME)
6118     {
6119 	if (ga_grow(&ga, 1) == FAIL)
6120 	    got_int = TRUE;
6121 	else
6122 	{
6123 	    s = alloc(18 + (unsigned)STRLEN(tagfname));
6124 	    if (s == NULL)
6125 		got_int = TRUE;
6126 	    else
6127 	    {
6128 		sprintf((char *)s, "help-tags\t%s\t1\n", tagfname);
6129 		((char_u **)ga.ga_data)[ga.ga_len] = s;
6130 		++ga.ga_len;
6131 	    }
6132 	}
6133     }
6134 
6135     /*
6136      * Go over all the files and extract the tags.
6137      */
6138     for (fi = 0; fi < filecount && !got_int; ++fi)
6139     {
6140 	fd = mch_fopen((char *)files[fi], "r");
6141 	if (fd == NULL)
6142 	{
6143 	    semsg(_("E153: Unable to open %s for reading"), files[fi]);
6144 	    continue;
6145 	}
6146 	fname = files[fi] + dirlen + 1;
6147 
6148 	firstline = TRUE;
6149 	while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
6150 	{
6151 	    if (firstline)
6152 	    {
6153 		/* Detect utf-8 file by a non-ASCII char in the first line. */
6154 		this_utf8 = MAYBE;
6155 		for (s = IObuff; *s != NUL; ++s)
6156 		    if (*s >= 0x80)
6157 		    {
6158 			int l;
6159 
6160 			this_utf8 = TRUE;
6161 			l = utf_ptr2len(s);
6162 			if (l == 1)
6163 			{
6164 			    /* Illegal UTF-8 byte sequence. */
6165 			    this_utf8 = FALSE;
6166 			    break;
6167 			}
6168 			s += l - 1;
6169 		    }
6170 		if (this_utf8 == MAYBE)	    /* only ASCII characters found */
6171 		    this_utf8 = FALSE;
6172 		if (utf8 == MAYBE)	    /* first file */
6173 		    utf8 = this_utf8;
6174 		else if (utf8 != this_utf8)
6175 		{
6176 		    semsg(_("E670: Mix of help file encodings within a language: %s"), files[fi]);
6177 		    mix = !got_int;
6178 		    got_int = TRUE;
6179 		}
6180 		firstline = FALSE;
6181 	    }
6182 	    p1 = vim_strchr(IObuff, '*');	/* find first '*' */
6183 	    while (p1 != NULL)
6184 	    {
6185 		/* Use vim_strbyte() instead of vim_strchr() so that when
6186 		 * 'encoding' is dbcs it still works, don't find '*' in the
6187 		 * second byte. */
6188 		p2 = vim_strbyte(p1 + 1, '*');	/* find second '*' */
6189 		if (p2 != NULL && p2 > p1 + 1)	/* skip "*" and "**" */
6190 		{
6191 		    for (s = p1 + 1; s < p2; ++s)
6192 			if (*s == ' ' || *s == '\t' || *s == '|')
6193 			    break;
6194 
6195 		    /*
6196 		     * Only accept a *tag* when it consists of valid
6197 		     * characters, there is white space before it and is
6198 		     * followed by a white character or end-of-line.
6199 		     */
6200 		    if (s == p2
6201 			    && (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
6202 			    && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL
6203 				|| s[1] == '\0'))
6204 		    {
6205 			*p2 = '\0';
6206 			++p1;
6207 			if (ga_grow(&ga, 1) == FAIL)
6208 			{
6209 			    got_int = TRUE;
6210 			    break;
6211 			}
6212 			s = alloc(p2 - p1 + STRLEN(fname) + 2);
6213 			if (s == NULL)
6214 			{
6215 			    got_int = TRUE;
6216 			    break;
6217 			}
6218 			((char_u **)ga.ga_data)[ga.ga_len] = s;
6219 			++ga.ga_len;
6220 			sprintf((char *)s, "%s\t%s", p1, fname);
6221 
6222 			/* find next '*' */
6223 			p2 = vim_strchr(p2 + 1, '*');
6224 		    }
6225 		}
6226 		p1 = p2;
6227 	    }
6228 	    line_breakcheck();
6229 	}
6230 
6231 	fclose(fd);
6232     }
6233 
6234     FreeWild(filecount, files);
6235 
6236     if (!got_int)
6237     {
6238 	/*
6239 	 * Sort the tags.
6240 	 */
6241 	if (ga.ga_data != NULL)
6242 	    sort_strings((char_u **)ga.ga_data, ga.ga_len);
6243 
6244 	/*
6245 	 * Check for duplicates.
6246 	 */
6247 	for (i = 1; i < ga.ga_len; ++i)
6248 	{
6249 	    p1 = ((char_u **)ga.ga_data)[i - 1];
6250 	    p2 = ((char_u **)ga.ga_data)[i];
6251 	    while (*p1 == *p2)
6252 	    {
6253 		if (*p2 == '\t')
6254 		{
6255 		    *p2 = NUL;
6256 		    vim_snprintf((char *)NameBuff, MAXPATHL,
6257 			    _("E154: Duplicate tag \"%s\" in file %s/%s"),
6258 				     ((char_u **)ga.ga_data)[i], dir, p2 + 1);
6259 		    emsg((char *)NameBuff);
6260 		    *p2 = '\t';
6261 		    break;
6262 		}
6263 		++p1;
6264 		++p2;
6265 	    }
6266 	}
6267 
6268 	if (utf8 == TRUE)
6269 	    fprintf(fd_tags, "!_TAG_FILE_ENCODING\tutf-8\t//\n");
6270 
6271 	/*
6272 	 * Write the tags into the file.
6273 	 */
6274 	for (i = 0; i < ga.ga_len; ++i)
6275 	{
6276 	    s = ((char_u **)ga.ga_data)[i];
6277 	    if (STRNCMP(s, "help-tags\t", 10) == 0)
6278 		/* help-tags entry was added in formatted form */
6279 		fputs((char *)s, fd_tags);
6280 	    else
6281 	    {
6282 		fprintf(fd_tags, "%s\t/*", s);
6283 		for (p1 = s; *p1 != '\t'; ++p1)
6284 		{
6285 		    /* insert backslash before '\\' and '/' */
6286 		    if (*p1 == '\\' || *p1 == '/')
6287 			putc('\\', fd_tags);
6288 		    putc(*p1, fd_tags);
6289 		}
6290 		fprintf(fd_tags, "*\n");
6291 	    }
6292 	}
6293     }
6294     if (mix)
6295 	got_int = FALSE;    /* continue with other languages */
6296 
6297     for (i = 0; i < ga.ga_len; ++i)
6298 	vim_free(((char_u **)ga.ga_data)[i]);
6299     ga_clear(&ga);
6300     fclose(fd_tags);	    /* there is no check for an error... */
6301 }
6302 
6303 /*
6304  * Generate tags in one help directory, taking care of translations.
6305  */
6306     static void
6307 do_helptags(char_u *dirname, int add_help_tags)
6308 {
6309 #ifdef FEAT_MULTI_LANG
6310     int		len;
6311     int		i, j;
6312     garray_T	ga;
6313     char_u	lang[2];
6314     char_u	ext[5];
6315     char_u	fname[8];
6316     int		filecount;
6317     char_u	**files;
6318 
6319     /* Get a list of all files in the help directory and in subdirectories. */
6320     STRCPY(NameBuff, dirname);
6321     add_pathsep(NameBuff);
6322     STRCAT(NameBuff, "**");
6323     if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
6324 						    EW_FILE|EW_SILENT) == FAIL
6325 	    || filecount == 0)
6326     {
6327 	semsg(_("E151: No match: %s"), NameBuff);
6328 	return;
6329     }
6330 
6331     /* Go over all files in the directory to find out what languages are
6332      * present. */
6333     ga_init2(&ga, 1, 10);
6334     for (i = 0; i < filecount; ++i)
6335     {
6336 	len = (int)STRLEN(files[i]);
6337 	if (len > 4)
6338 	{
6339 	    if (STRICMP(files[i] + len - 4, ".txt") == 0)
6340 	    {
6341 		/* ".txt" -> language "en" */
6342 		lang[0] = 'e';
6343 		lang[1] = 'n';
6344 	    }
6345 	    else if (files[i][len - 4] == '.'
6346 		    && ASCII_ISALPHA(files[i][len - 3])
6347 		    && ASCII_ISALPHA(files[i][len - 2])
6348 		    && TOLOWER_ASC(files[i][len - 1]) == 'x')
6349 	    {
6350 		/* ".abx" -> language "ab" */
6351 		lang[0] = TOLOWER_ASC(files[i][len - 3]);
6352 		lang[1] = TOLOWER_ASC(files[i][len - 2]);
6353 	    }
6354 	    else
6355 		continue;
6356 
6357 	    /* Did we find this language already? */
6358 	    for (j = 0; j < ga.ga_len; j += 2)
6359 		if (STRNCMP(lang, ((char_u *)ga.ga_data) + j, 2) == 0)
6360 		    break;
6361 	    if (j == ga.ga_len)
6362 	    {
6363 		/* New language, add it. */
6364 		if (ga_grow(&ga, 2) == FAIL)
6365 		    break;
6366 		((char_u *)ga.ga_data)[ga.ga_len++] = lang[0];
6367 		((char_u *)ga.ga_data)[ga.ga_len++] = lang[1];
6368 	    }
6369 	}
6370     }
6371 
6372     /*
6373      * Loop over the found languages to generate a tags file for each one.
6374      */
6375     for (j = 0; j < ga.ga_len; j += 2)
6376     {
6377 	STRCPY(fname, "tags-xx");
6378 	fname[5] = ((char_u *)ga.ga_data)[j];
6379 	fname[6] = ((char_u *)ga.ga_data)[j + 1];
6380 	if (fname[5] == 'e' && fname[6] == 'n')
6381 	{
6382 	    /* English is an exception: use ".txt" and "tags". */
6383 	    fname[4] = NUL;
6384 	    STRCPY(ext, ".txt");
6385 	}
6386 	else
6387 	{
6388 	    /* Language "ab" uses ".abx" and "tags-ab". */
6389 	    STRCPY(ext, ".xxx");
6390 	    ext[1] = fname[5];
6391 	    ext[2] = fname[6];
6392 	}
6393 	helptags_one(dirname, ext, fname, add_help_tags);
6394     }
6395 
6396     ga_clear(&ga);
6397     FreeWild(filecount, files);
6398 
6399 #else
6400     /* No language support, just use "*.txt" and "tags". */
6401     helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags);
6402 #endif
6403 }
6404 
6405     static void
6406 helptags_cb(char_u *fname, void *cookie)
6407 {
6408     do_helptags(fname, *(int *)cookie);
6409 }
6410 
6411 /*
6412  * ":helptags"
6413  */
6414     void
6415 ex_helptags(exarg_T *eap)
6416 {
6417     expand_T	xpc;
6418     char_u	*dirname;
6419     int		add_help_tags = FALSE;
6420 
6421     /* Check for ":helptags ++t {dir}". */
6422     if (STRNCMP(eap->arg, "++t", 3) == 0 && VIM_ISWHITE(eap->arg[3]))
6423     {
6424 	add_help_tags = TRUE;
6425 	eap->arg = skipwhite(eap->arg + 3);
6426     }
6427 
6428     if (STRCMP(eap->arg, "ALL") == 0)
6429     {
6430 	do_in_path(p_rtp, (char_u *)"doc", DIP_ALL + DIP_DIR,
6431 						 helptags_cb, &add_help_tags);
6432     }
6433     else
6434     {
6435 	ExpandInit(&xpc);
6436 	xpc.xp_context = EXPAND_DIRECTORIES;
6437 	dirname = ExpandOne(&xpc, eap->arg, NULL,
6438 			    WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
6439 	if (dirname == NULL || !mch_isdir(dirname))
6440 	    semsg(_("E150: Not a directory: %s"), eap->arg);
6441 	else
6442 	    do_helptags(dirname, add_help_tags);
6443 	vim_free(dirname);
6444     }
6445 }
6446 
6447 /*
6448  * Make the user happy.
6449  */
6450     void
6451 ex_smile(exarg_T *eap UNUSED)
6452 {
6453     static char *code[] = {
6454 	"\34 \4o\14$\4ox\30 \2o\30$\1ox\25 \2o\36$\1o\11 \1o\1$\3 \2$\1 \1o\1$x\5 \1o\1 \1$\1 \2o\10 \1o\44$\1o\7 \2$\1 \2$\1 \2$\1o\1$x\2 \2o\1 \1$\1 \1$\1 \1\"\1$\6 \1o\11$\4 \15$\4 \11$\1o\7 \3$\1o\2$\1o\1$x\2 \1\"\6$\1o\1$\5 \1o\11$\6 \13$\6 \12$\1o\4 \10$x\4 \7$\4 \13$\6 \13$\6 \27$x\4 \27$\4 \15$\4 \16$\2 \3\"\3$x\5 \1\"\3$\4\"\61$\5 \1\"\3$x\6 \3$\3 \1o\62$\5 \1\"\3$\1ox\5 \1o\2$\1\"\3 \63$\7 \3$\1ox\5 \3$\4 \55$\1\"\1 \1\"\6$",
6455 	"\5o\4$\1ox\4 \1o\3$\4o\5$\2 \45$\3 \1o\21$x\4 \10$\1\"\4$\3 \42$\5 \4$\10\"x\3 \4\"\7 \4$\4 \1\"\34$\1\"\6 \1o\3$x\16 \1\"\3$\1o\5 \3\"\22$\1\"\2$\1\"\11 \3$x\20 \3$\1o\12 \1\"\2$\2\"\6$\4\"\13 \1o\3$x\21 \4$\1o\40 \1o\3$\1\"x\22 \1\"\4$\1o\6 \1o\6$\1o\1\"\4$\1o\10 \1o\4$x\24 \1\"\5$\2o\5 \2\"\4$\1o\5$\1o\3 \1o\4$\2\"x\27 \2\"\5$\4o\2 \1\"\3$\1o\11$\3\"x\32 \2\"\7$\2o\1 \12$x\42 \4\"\13$x\46 \14$x\47 \12$\1\"x\50 \1\"\3$\4\"x"
6456     };
6457     char *p;
6458     int n;
6459     int i;
6460 
6461     msg_start();
6462     msg_putchar('\n');
6463     for (i = 0; i < 2; ++i)
6464 	for (p = code[i]; *p != NUL; ++p)
6465 	    if (*p == 'x')
6466 		msg_putchar('\n');
6467 	    else
6468 		for (n = *p++; n > 0; --n)
6469 		    if (*p == 'o' || *p == '$')
6470 			msg_putchar_attr(*p, HL_ATTR(HLF_L));
6471 		    else
6472 			msg_putchar(*p);
6473     msg_clr_eos();
6474 }
6475 
6476 /*
6477  * ":drop"
6478  * Opens the first argument in a window.  When there are two or more arguments
6479  * the argument list is redefined.
6480  */
6481     void
6482 ex_drop(exarg_T *eap)
6483 {
6484     int		split = FALSE;
6485     win_T	*wp;
6486     buf_T	*buf;
6487     tabpage_T	*tp;
6488 
6489     /*
6490      * Check if the first argument is already being edited in a window.  If
6491      * so, jump to that window.
6492      * We would actually need to check all arguments, but that's complicated
6493      * and mostly only one file is dropped.
6494      * This also ignores wildcards, since it is very unlikely the user is
6495      * editing a file name with a wildcard character.
6496      */
6497     set_arglist(eap->arg);
6498 
6499     /*
6500      * Expanding wildcards may result in an empty argument list.  E.g. when
6501      * editing "foo.pyc" and ".pyc" is in 'wildignore'.  Assume that we
6502      * already did an error message for this.
6503      */
6504     if (ARGCOUNT == 0)
6505 	return;
6506 
6507     if (cmdmod.tab)
6508     {
6509 	/* ":tab drop file ...": open a tab for each argument that isn't
6510 	 * edited in a window yet.  It's like ":tab all" but without closing
6511 	 * windows or tabs. */
6512 	ex_all(eap);
6513     }
6514     else
6515     {
6516 	/* ":drop file ...": Edit the first argument.  Jump to an existing
6517 	 * window if possible, edit in current window if the current buffer
6518 	 * can be abandoned, otherwise open a new window. */
6519 	buf = buflist_findnr(ARGLIST[0].ae_fnum);
6520 
6521 	FOR_ALL_TAB_WINDOWS(tp, wp)
6522 	{
6523 	    if (wp->w_buffer == buf)
6524 	    {
6525 		goto_tabpage_win(tp, wp);
6526 		curwin->w_arg_idx = 0;
6527 		return;
6528 	    }
6529 	}
6530 
6531 	/*
6532 	 * Check whether the current buffer is changed. If so, we will need
6533 	 * to split the current window or data could be lost.
6534 	 * Skip the check if the 'hidden' option is set, as in this case the
6535 	 * buffer won't be lost.
6536 	 */
6537 	if (!buf_hide(curbuf))
6538 	{
6539 	    ++emsg_off;
6540 	    split = check_changed(curbuf, CCGD_AW | CCGD_EXCMD);
6541 	    --emsg_off;
6542 	}
6543 
6544 	/* Fake a ":sfirst" or ":first" command edit the first argument. */
6545 	if (split)
6546 	{
6547 	    eap->cmdidx = CMD_sfirst;
6548 	    eap->cmd[0] = 's';
6549 	}
6550 	else
6551 	    eap->cmdidx = CMD_first;
6552 	ex_rewind(eap);
6553     }
6554 }
6555 
6556 /*
6557  * Skip over the pattern argument of ":vimgrep /pat/[g][j]".
6558  * Put the start of the pattern in "*s", unless "s" is NULL.
6559  * If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
6560  * If "s" is not NULL terminate the pattern with a NUL.
6561  * Return a pointer to the char just past the pattern plus flags.
6562  */
6563     char_u *
6564 skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
6565 {
6566     int		c;
6567 
6568     if (vim_isIDc(*p))
6569     {
6570 	/* ":vimgrep pattern fname" */
6571 	if (s != NULL)
6572 	    *s = p;
6573 	p = skiptowhite(p);
6574 	if (s != NULL && *p != NUL)
6575 	    *p++ = NUL;
6576     }
6577     else
6578     {
6579 	/* ":vimgrep /pattern/[g][j] fname" */
6580 	if (s != NULL)
6581 	    *s = p + 1;
6582 	c = *p;
6583 	p = skip_regexp(p + 1, c, TRUE, NULL);
6584 	if (*p != c)
6585 	    return NULL;
6586 
6587 	/* Truncate the pattern. */
6588 	if (s != NULL)
6589 	    *p = NUL;
6590 	++p;
6591 
6592 	/* Find the flags */
6593 	while (*p == 'g' || *p == 'j')
6594 	{
6595 	    if (flags != NULL)
6596 	    {
6597 		if (*p == 'g')
6598 		    *flags |= VGR_GLOBAL;
6599 		else
6600 		    *flags |= VGR_NOJUMP;
6601 	    }
6602 	    ++p;
6603 	}
6604     }
6605     return p;
6606 }
6607 
6608 #if defined(FEAT_EVAL) || defined(PROTO)
6609 /*
6610  * List v:oldfiles in a nice way.
6611  */
6612     void
6613 ex_oldfiles(exarg_T *eap UNUSED)
6614 {
6615     list_T	*l = get_vim_var_list(VV_OLDFILES);
6616     listitem_T	*li;
6617     int		nr = 0;
6618     char_u	*fname;
6619 
6620     if (l == NULL)
6621 	msg(_("No old files"));
6622     else
6623     {
6624 	msg_start();
6625 	msg_scroll = TRUE;
6626 	for (li = l->lv_first; li != NULL && !got_int; li = li->li_next)
6627 	{
6628 	    ++nr;
6629 	    fname = tv_get_string(&li->li_tv);
6630 	    if (!message_filtered(fname))
6631 	    {
6632 		msg_outnum((long)nr);
6633 		msg_puts(": ");
6634 		msg_outtrans(fname);
6635 		msg_clr_eos();
6636 		msg_putchar('\n');
6637 		out_flush();	    /* output one line at a time */
6638 		ui_breakcheck();
6639 	    }
6640 	}
6641 
6642 	/* Assume "got_int" was set to truncate the listing. */
6643 	got_int = FALSE;
6644 
6645 # ifdef FEAT_BROWSE_CMD
6646 	if (cmdmod.browse)
6647 	{
6648 	    quit_more = FALSE;
6649 	    nr = prompt_for_number(FALSE);
6650 	    msg_starthere();
6651 	    if (nr > 0)
6652 	    {
6653 		char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES),
6654 								    (long)nr);
6655 
6656 		if (p != NULL)
6657 		{
6658 		    p = expand_env_save(p);
6659 		    eap->arg = p;
6660 		    eap->cmdidx = CMD_edit;
6661 		    cmdmod.browse = FALSE;
6662 		    do_exedit(eap, NULL);
6663 		    vim_free(p);
6664 		}
6665 	    }
6666 	}
6667 # endif
6668     }
6669 }
6670 #endif
6671