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