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