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