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