xref: /vim-8.2.3635/src/misc1.c (revision d5cdbeb8)
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  * misc1.c: functions that didn't seem to fit elsewhere
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 #ifdef HAVE_FCNTL_H
18 # include <fcntl.h>		/* for chdir() */
19 #endif
20 
21 static char_u *vim_version_dir __ARGS((char_u *vimdir));
22 static char_u *remove_tail __ARGS((char_u *p, char_u *pend, char_u *name));
23 #if defined(USE_EXE_NAME) && defined(MACOS_X)
24 static char_u *remove_tail_with_ext __ARGS((char_u *p, char_u *pend, char_u *ext));
25 #endif
26 static int copy_indent __ARGS((int size, char_u	*src));
27 
28 /*
29  * Count the size (in window cells) of the indent in the current line.
30  */
31     int
32 get_indent()
33 {
34     return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts);
35 }
36 
37 /*
38  * Count the size (in window cells) of the indent in line "lnum".
39  */
40     int
41 get_indent_lnum(lnum)
42     linenr_T	lnum;
43 {
44     return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts);
45 }
46 
47 #if defined(FEAT_FOLDING) || defined(PROTO)
48 /*
49  * Count the size (in window cells) of the indent in line "lnum" of buffer
50  * "buf".
51  */
52     int
53 get_indent_buf(buf, lnum)
54     buf_T	*buf;
55     linenr_T	lnum;
56 {
57     return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts);
58 }
59 #endif
60 
61 /*
62  * count the size (in window cells) of the indent in line "ptr", with
63  * 'tabstop' at "ts"
64  */
65     int
66 get_indent_str(ptr, ts)
67     char_u	*ptr;
68     int		ts;
69 {
70     int		count = 0;
71 
72     for ( ; *ptr; ++ptr)
73     {
74 	if (*ptr == TAB)    /* count a tab for what it is worth */
75 	    count += ts - (count % ts);
76 	else if (*ptr == ' ')
77 	    ++count;		/* count a space for one */
78 	else
79 	    break;
80     }
81     return count;
82 }
83 
84 /*
85  * Set the indent of the current line.
86  * Leaves the cursor on the first non-blank in the line.
87  * Caller must take care of undo.
88  * "flags":
89  *	SIN_CHANGED:	call changed_bytes() if the line was changed.
90  *	SIN_INSERT:	insert the indent in front of the line.
91  *	SIN_UNDO:	save line for undo before changing it.
92  * Returns TRUE if the line was changed.
93  */
94     int
95 set_indent(size, flags)
96     int		size;
97     int		flags;
98 {
99     char_u	*p;
100     char_u	*newline;
101     char_u	*oldline;
102     char_u	*s;
103     int		todo;
104     int		ind_len;
105     int		line_len;
106     int		doit = FALSE;
107     int		ind_done;
108     int		tab_pad;
109     int		retval = FALSE;
110 
111     /*
112      * First check if there is anything to do and compute the number of
113      * characters needed for the indent.
114      */
115     todo = size;
116     ind_len = 0;
117     p = oldline = ml_get_curline();
118 
119     /* Calculate the buffer size for the new indent, and check to see if it
120      * isn't already set */
121 
122     /* if 'expandtab' isn't set: use TABs */
123     if (!curbuf->b_p_et)
124     {
125 	/* If 'preserveindent' is set then reuse as much as possible of
126 	 * the existing indent structure for the new indent */
127 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
128 	{
129 	    ind_done = 0;
130 
131 	    /* count as many characters as we can use */
132 	    while (todo > 0 && vim_iswhite(*p))
133 	    {
134 		if (*p == TAB)
135 		{
136 		    tab_pad = (int)curbuf->b_p_ts
137 					   - (ind_done % (int)curbuf->b_p_ts);
138 		    /* stop if this tab will overshoot the target */
139 		    if (todo < tab_pad)
140 			break;
141 		    todo -= tab_pad;
142 		    ++ind_len;
143 		    ind_done += tab_pad;
144 		}
145 		else
146 		{
147 		    --todo;
148 		    ++ind_len;
149 		    ++ind_done;
150 		}
151 		++p;
152 	    }
153 
154 	    /* Fill to next tabstop with a tab, if possible */
155 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
156 	    if (todo >= tab_pad)
157 	    {
158 		doit = TRUE;
159 		todo -= tab_pad;
160 		++ind_len;
161 		/* ind_done += tab_pad; */
162 	    }
163 	}
164 
165 	/* count tabs required for indent */
166 	while (todo >= (int)curbuf->b_p_ts)
167 	{
168 	    if (*p != TAB)
169 		doit = TRUE;
170 	    else
171 		++p;
172 	    todo -= (int)curbuf->b_p_ts;
173 	    ++ind_len;
174 	    /* ind_done += (int)curbuf->b_p_ts; */
175 	}
176     }
177     /* count spaces required for indent */
178     while (todo > 0)
179     {
180 	if (*p != ' ')
181 	    doit = TRUE;
182 	else
183 	    ++p;
184 	--todo;
185 	++ind_len;
186 	/* ++ind_done; */
187     }
188 
189     /* Return if the indent is OK already. */
190     if (!doit && !vim_iswhite(*p) && !(flags & SIN_INSERT))
191 	return FALSE;
192 
193     /* Allocate memory for the new line. */
194     if (flags & SIN_INSERT)
195 	p = oldline;
196     else
197 	p = skipwhite(p);
198     line_len = (int)STRLEN(p) + 1;
199     newline = alloc(ind_len + line_len);
200     if (newline == NULL)
201 	return FALSE;
202 
203     /* Put the characters in the new line. */
204     s = newline;
205     todo = size;
206     /* if 'expandtab' isn't set: use TABs */
207     if (!curbuf->b_p_et)
208     {
209 	/* If 'preserveindent' is set then reuse as much as possible of
210 	 * the existing indent structure for the new indent */
211 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
212 	{
213 	    p = oldline;
214 	    ind_done = 0;
215 
216 	    while (todo > 0 && vim_iswhite(*p))
217 	    {
218 		if (*p == TAB)
219 		{
220 		    tab_pad = (int)curbuf->b_p_ts
221 					   - (ind_done % (int)curbuf->b_p_ts);
222 		    /* stop if this tab will overshoot the target */
223 		    if (todo < tab_pad)
224 			break;
225 		    todo -= tab_pad;
226 		    ind_done += tab_pad;
227 		}
228 		else
229 		{
230 		    --todo;
231 		    ++ind_done;
232 		}
233 		*s++ = *p++;
234 	    }
235 
236 	    /* Fill to next tabstop with a tab, if possible */
237 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
238 	    if (todo >= tab_pad)
239 	    {
240 		*s++ = TAB;
241 		todo -= tab_pad;
242 	    }
243 
244 	    p = skipwhite(p);
245 	}
246 
247 	while (todo >= (int)curbuf->b_p_ts)
248 	{
249 	    *s++ = TAB;
250 	    todo -= (int)curbuf->b_p_ts;
251 	}
252     }
253     while (todo > 0)
254     {
255 	*s++ = ' ';
256 	--todo;
257     }
258     mch_memmove(s, p, (size_t)line_len);
259 
260     /* Replace the line (unless undo fails). */
261     if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK)
262     {
263 	ml_replace(curwin->w_cursor.lnum, newline, FALSE);
264 	if (flags & SIN_CHANGED)
265 	    changed_bytes(curwin->w_cursor.lnum, 0);
266 	/* Correct saved cursor position if it's after the indent. */
267 	if (saved_cursor.lnum == curwin->w_cursor.lnum
268 				&& saved_cursor.col >= (colnr_T)(p - oldline))
269 	    saved_cursor.col += ind_len - (p - oldline);
270 	retval = TRUE;
271     }
272     else
273 	vim_free(newline);
274 
275     curwin->w_cursor.col = ind_len;
276     return retval;
277 }
278 
279 /*
280  * Copy the indent from ptr to the current line (and fill to size)
281  * Leaves the cursor on the first non-blank in the line.
282  * Returns TRUE if the line was changed.
283  */
284     static int
285 copy_indent(size, src)
286     int		size;
287     char_u	*src;
288 {
289     char_u	*p = NULL;
290     char_u	*line = NULL;
291     char_u	*s;
292     int		todo;
293     int		ind_len;
294     int		line_len = 0;
295     int		tab_pad;
296     int		ind_done;
297     int		round;
298 
299     /* Round 1: compute the number of characters needed for the indent
300      * Round 2: copy the characters. */
301     for (round = 1; round <= 2; ++round)
302     {
303 	todo = size;
304 	ind_len = 0;
305 	ind_done = 0;
306 	s = src;
307 
308 	/* Count/copy the usable portion of the source line */
309 	while (todo > 0 && vim_iswhite(*s))
310 	{
311 	    if (*s == TAB)
312 	    {
313 		tab_pad = (int)curbuf->b_p_ts
314 					   - (ind_done % (int)curbuf->b_p_ts);
315 		/* Stop if this tab will overshoot the target */
316 		if (todo < tab_pad)
317 		    break;
318 		todo -= tab_pad;
319 		ind_done += tab_pad;
320 	    }
321 	    else
322 	    {
323 		--todo;
324 		++ind_done;
325 	    }
326 	    ++ind_len;
327 	    if (round == 2)
328 		*p++ = *s;
329 	    ++s;
330 	}
331 
332 	/* Fill to next tabstop with a tab, if possible */
333 	tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
334 	if (todo >= tab_pad)
335 	{
336 	    todo -= tab_pad;
337 	    ++ind_len;
338 	    if (round == 2)
339 		*p++ = TAB;
340 	}
341 
342 	/* Add tabs required for indent */
343 	while (todo >= (int)curbuf->b_p_ts)
344 	{
345 	    todo -= (int)curbuf->b_p_ts;
346 	    ++ind_len;
347 	    if (round == 2)
348 		*p++ = TAB;
349 	}
350 
351 	/* Count/add spaces required for indent */
352 	while (todo > 0)
353 	{
354 	    --todo;
355 	    ++ind_len;
356 	    if (round == 2)
357 		*p++ = ' ';
358 	}
359 
360 	if (round == 1)
361 	{
362 	    /* Allocate memory for the result: the copied indent, new indent
363 	     * and the rest of the line. */
364 	    line_len = (int)STRLEN(ml_get_curline()) + 1;
365 	    line = alloc(ind_len + line_len);
366 	    if (line == NULL)
367 		return FALSE;
368 	    p = line;
369 	}
370     }
371 
372     /* Append the original line */
373     mch_memmove(p, ml_get_curline(), (size_t)line_len);
374 
375     /* Replace the line */
376     ml_replace(curwin->w_cursor.lnum, line, FALSE);
377 
378     /* Put the cursor after the indent. */
379     curwin->w_cursor.col = ind_len;
380     return TRUE;
381 }
382 
383 /*
384  * Return the indent of the current line after a number.  Return -1 if no
385  * number was found.  Used for 'n' in 'formatoptions': numbered list.
386  * Since a pattern is used it can actually handle more than numbers.
387  */
388     int
389 get_number_indent(lnum)
390     linenr_T	lnum;
391 {
392     colnr_T	col;
393     pos_T	pos;
394     regmmatch_T	regmatch;
395 
396     if (lnum > curbuf->b_ml.ml_line_count)
397 	return -1;
398     pos.lnum = 0;
399     regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
400     if (regmatch.regprog != NULL)
401     {
402 	regmatch.rmm_ic = FALSE;
403 	regmatch.rmm_maxcol = 0;
404 	if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0))
405 	{
406 	    pos.lnum = regmatch.endpos[0].lnum + lnum;
407 	    pos.col = regmatch.endpos[0].col;
408 #ifdef FEAT_VIRTUALEDIT
409 	    pos.coladd = 0;
410 #endif
411 	}
412 	vim_free(regmatch.regprog);
413     }
414 
415     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
416 	return -1;
417     getvcol(curwin, &pos, &col, NULL, NULL);
418     return (int)col;
419 }
420 
421 #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
422 
423 static int cin_is_cinword __ARGS((char_u *line));
424 
425 /*
426  * Return TRUE if the string "line" starts with a word from 'cinwords'.
427  */
428     static int
429 cin_is_cinword(line)
430     char_u	*line;
431 {
432     char_u	*cinw;
433     char_u	*cinw_buf;
434     int		cinw_len;
435     int		retval = FALSE;
436     int		len;
437 
438     cinw_len = (int)STRLEN(curbuf->b_p_cinw) + 1;
439     cinw_buf = alloc((unsigned)cinw_len);
440     if (cinw_buf != NULL)
441     {
442 	line = skipwhite(line);
443 	for (cinw = curbuf->b_p_cinw; *cinw; )
444 	{
445 	    len = copy_option_part(&cinw, cinw_buf, cinw_len, ",");
446 	    if (STRNCMP(line, cinw_buf, len) == 0
447 		    && (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1])))
448 	    {
449 		retval = TRUE;
450 		break;
451 	    }
452 	}
453 	vim_free(cinw_buf);
454     }
455     return retval;
456 }
457 #endif
458 
459 /*
460  * open_line: Add a new line below or above the current line.
461  *
462  * For VREPLACE mode, we only add a new line when we get to the end of the
463  * file, otherwise we just start replacing the next line.
464  *
465  * Caller must take care of undo.  Since VREPLACE may affect any number of
466  * lines however, it may call u_save_cursor() again when starting to change a
467  * new line.
468  * "flags": OPENLINE_DELSPACES	delete spaces after cursor
469  *	    OPENLINE_DO_COM	format comments
470  *	    OPENLINE_KEEPTRAIL	keep trailing spaces
471  *	    OPENLINE_MARKFIX	adjust mark positions after the line break
472  *
473  * Return TRUE for success, FALSE for failure
474  */
475     int
476 open_line(dir, flags, old_indent)
477     int		dir;		/* FORWARD or BACKWARD */
478     int		flags;
479     int		old_indent;	/* indent for after ^^D in Insert mode */
480 {
481     char_u	*saved_line;		/* copy of the original line */
482     char_u	*next_line = NULL;	/* copy of the next line */
483     char_u	*p_extra = NULL;	/* what goes to next line */
484     int		less_cols = 0;		/* less columns for mark in new line */
485     int		less_cols_off = 0;	/* columns to skip for mark adjust */
486     pos_T	old_cursor;		/* old cursor position */
487     int		newcol = 0;		/* new cursor column */
488     int		newindent = 0;		/* auto-indent of the new line */
489     int		n;
490     int		trunc_line = FALSE;	/* truncate current line afterwards */
491     int		retval = FALSE;		/* return value, default is FAIL */
492 #ifdef FEAT_COMMENTS
493     int		extra_len = 0;		/* length of p_extra string */
494     int		lead_len;		/* length of comment leader */
495     char_u	*lead_flags;	/* position in 'comments' for comment leader */
496     char_u	*leader = NULL;		/* copy of comment leader */
497 #endif
498     char_u	*allocated = NULL;	/* allocated memory */
499 #if defined(FEAT_SMARTINDENT) || defined(FEAT_VREPLACE) || defined(FEAT_LISP) \
500 	|| defined(FEAT_CINDENT) || defined(FEAT_COMMENTS)
501     char_u	*p;
502 #endif
503     int		saved_char = NUL;	/* init for GCC */
504 #if defined(FEAT_SMARTINDENT) || defined(FEAT_COMMENTS)
505     pos_T	*pos;
506 #endif
507 #ifdef FEAT_SMARTINDENT
508     int		do_si = (!p_paste && curbuf->b_p_si
509 # ifdef FEAT_CINDENT
510 					&& !curbuf->b_p_cin
511 # endif
512 			);
513     int		no_si = FALSE;		/* reset did_si afterwards */
514     int		first_char = NUL;	/* init for GCC */
515 #endif
516 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
517     int		vreplace_mode;
518 #endif
519     int		did_append;		/* appended a new line */
520     int		saved_pi = curbuf->b_p_pi; /* copy of preserveindent setting */
521 
522     /*
523      * make a copy of the current line so we can mess with it
524      */
525     saved_line = vim_strsave(ml_get_curline());
526     if (saved_line == NULL)	    /* out of memory! */
527 	return FALSE;
528 
529 #ifdef FEAT_VREPLACE
530     if (State & VREPLACE_FLAG)
531     {
532 	/*
533 	 * With VREPLACE we make a copy of the next line, which we will be
534 	 * starting to replace.  First make the new line empty and let vim play
535 	 * with the indenting and comment leader to its heart's content.  Then
536 	 * we grab what it ended up putting on the new line, put back the
537 	 * original line, and call ins_char() to put each new character onto
538 	 * the line, replacing what was there before and pushing the right
539 	 * stuff onto the replace stack.  -- webb.
540 	 */
541 	if (curwin->w_cursor.lnum < orig_line_count)
542 	    next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
543 	else
544 	    next_line = vim_strsave((char_u *)"");
545 	if (next_line == NULL)	    /* out of memory! */
546 	    goto theend;
547 
548 	/*
549 	 * In VREPLACE mode, a NL replaces the rest of the line, and starts
550 	 * replacing the next line, so push all of the characters left on the
551 	 * line onto the replace stack.  We'll push any other characters that
552 	 * might be replaced at the start of the next line (due to autoindent
553 	 * etc) a bit later.
554 	 */
555 	replace_push(NUL);  /* Call twice because BS over NL expects it */
556 	replace_push(NUL);
557 	p = saved_line + curwin->w_cursor.col;
558 	while (*p != NUL)
559 	    replace_push(*p++);
560 	saved_line[curwin->w_cursor.col] = NUL;
561     }
562 #endif
563 
564     if ((State & INSERT)
565 #ifdef FEAT_VREPLACE
566 	    && !(State & VREPLACE_FLAG)
567 #endif
568 	    )
569     {
570 	p_extra = saved_line + curwin->w_cursor.col;
571 #ifdef FEAT_SMARTINDENT
572 	if (do_si)		/* need first char after new line break */
573 	{
574 	    p = skipwhite(p_extra);
575 	    first_char = *p;
576 	}
577 #endif
578 #ifdef FEAT_COMMENTS
579 	extra_len = (int)STRLEN(p_extra);
580 #endif
581 	saved_char = *p_extra;
582 	*p_extra = NUL;
583     }
584 
585     u_clearline();		/* cannot do "U" command when adding lines */
586 #ifdef FEAT_SMARTINDENT
587     did_si = FALSE;
588 #endif
589     ai_col = 0;
590 
591     /*
592      * If we just did an auto-indent, then we didn't type anything on
593      * the prior line, and it should be truncated.  Do this even if 'ai' is not
594      * set because automatically inserting a comment leader also sets did_ai.
595      */
596     if (dir == FORWARD && did_ai)
597 	trunc_line = TRUE;
598 
599     /*
600      * If 'autoindent' and/or 'smartindent' is set, try to figure out what
601      * indent to use for the new line.
602      */
603     if (curbuf->b_p_ai
604 #ifdef FEAT_SMARTINDENT
605 			|| do_si
606 #endif
607 					    )
608     {
609 	/*
610 	 * count white space on current line
611 	 */
612 	newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts);
613 	if (newindent == 0)
614 	    newindent = old_indent;	/* for ^^D command in insert mode */
615 
616 #ifdef FEAT_SMARTINDENT
617 	/*
618 	 * Do smart indenting.
619 	 * In insert/replace mode (only when dir == FORWARD)
620 	 * we may move some text to the next line. If it starts with '{'
621 	 * don't add an indent. Fixes inserting a NL before '{' in line
622 	 *	"if (condition) {"
623 	 */
624 	if (!trunc_line && do_si && *saved_line != NUL
625 				    && (p_extra == NULL || first_char != '{'))
626 	{
627 	    char_u  *ptr;
628 	    char_u  last_char;
629 
630 	    old_cursor = curwin->w_cursor;
631 	    ptr = saved_line;
632 # ifdef FEAT_COMMENTS
633 	    if (flags & OPENLINE_DO_COM)
634 		lead_len = get_leader_len(ptr, NULL, FALSE);
635 	    else
636 		lead_len = 0;
637 # endif
638 	    if (dir == FORWARD)
639 	    {
640 		/*
641 		 * Skip preprocessor directives, unless they are
642 		 * recognised as comments.
643 		 */
644 		if (
645 # ifdef FEAT_COMMENTS
646 			lead_len == 0 &&
647 # endif
648 			ptr[0] == '#')
649 		{
650 		    while (ptr[0] == '#' && curwin->w_cursor.lnum > 1)
651 			ptr = ml_get(--curwin->w_cursor.lnum);
652 		    newindent = get_indent();
653 		}
654 # ifdef FEAT_COMMENTS
655 		if (flags & OPENLINE_DO_COM)
656 		    lead_len = get_leader_len(ptr, NULL, FALSE);
657 		else
658 		    lead_len = 0;
659 		if (lead_len > 0)
660 		{
661 		    /*
662 		     * This case gets the following right:
663 		     *	    \*
664 		     *	     * A comment (read '\' as '/').
665 		     *	     *\
666 		     * #define IN_THE_WAY
667 		     *	    This should line up here;
668 		     */
669 		    p = skipwhite(ptr);
670 		    if (p[0] == '/' && p[1] == '*')
671 			p++;
672 		    if (p[0] == '*')
673 		    {
674 			for (p++; *p; p++)
675 			{
676 			    if (p[0] == '/' && p[-1] == '*')
677 			    {
678 				/*
679 				 * End of C comment, indent should line up
680 				 * with the line containing the start of
681 				 * the comment
682 				 */
683 				curwin->w_cursor.col = (colnr_T)(p - ptr);
684 				if ((pos = findmatch(NULL, NUL)) != NULL)
685 				{
686 				    curwin->w_cursor.lnum = pos->lnum;
687 				    newindent = get_indent();
688 				}
689 			    }
690 			}
691 		    }
692 		}
693 		else	/* Not a comment line */
694 # endif
695 		{
696 		    /* Find last non-blank in line */
697 		    p = ptr + STRLEN(ptr) - 1;
698 		    while (p > ptr && vim_iswhite(*p))
699 			--p;
700 		    last_char = *p;
701 
702 		    /*
703 		     * find the character just before the '{' or ';'
704 		     */
705 		    if (last_char == '{' || last_char == ';')
706 		    {
707 			if (p > ptr)
708 			    --p;
709 			while (p > ptr && vim_iswhite(*p))
710 			    --p;
711 		    }
712 		    /*
713 		     * Try to catch lines that are split over multiple
714 		     * lines.  eg:
715 		     *	    if (condition &&
716 		     *			condition) {
717 		     *		Should line up here!
718 		     *	    }
719 		     */
720 		    if (*p == ')')
721 		    {
722 			curwin->w_cursor.col = (colnr_T)(p - ptr);
723 			if ((pos = findmatch(NULL, '(')) != NULL)
724 			{
725 			    curwin->w_cursor.lnum = pos->lnum;
726 			    newindent = get_indent();
727 			    ptr = ml_get_curline();
728 			}
729 		    }
730 		    /*
731 		     * If last character is '{' do indent, without
732 		     * checking for "if" and the like.
733 		     */
734 		    if (last_char == '{')
735 		    {
736 			did_si = TRUE;	/* do indent */
737 			no_si = TRUE;	/* don't delete it when '{' typed */
738 		    }
739 		    /*
740 		     * Look for "if" and the like, use 'cinwords'.
741 		     * Don't do this if the previous line ended in ';' or
742 		     * '}'.
743 		     */
744 		    else if (last_char != ';' && last_char != '}'
745 						       && cin_is_cinword(ptr))
746 			did_si = TRUE;
747 		}
748 	    }
749 	    else /* dir == BACKWARD */
750 	    {
751 		/*
752 		 * Skip preprocessor directives, unless they are
753 		 * recognised as comments.
754 		 */
755 		if (
756 # ifdef FEAT_COMMENTS
757 			lead_len == 0 &&
758 # endif
759 			ptr[0] == '#')
760 		{
761 		    int was_backslashed = FALSE;
762 
763 		    while ((ptr[0] == '#' || was_backslashed) &&
764 			 curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
765 		    {
766 			if (*ptr && ptr[STRLEN(ptr) - 1] == '\\')
767 			    was_backslashed = TRUE;
768 			else
769 			    was_backslashed = FALSE;
770 			ptr = ml_get(++curwin->w_cursor.lnum);
771 		    }
772 		    if (was_backslashed)
773 			newindent = 0;	    /* Got to end of file */
774 		    else
775 			newindent = get_indent();
776 		}
777 		p = skipwhite(ptr);
778 		if (*p == '}')	    /* if line starts with '}': do indent */
779 		    did_si = TRUE;
780 		else		    /* can delete indent when '{' typed */
781 		    can_si_back = TRUE;
782 	    }
783 	    curwin->w_cursor = old_cursor;
784 	}
785 	if (do_si)
786 	    can_si = TRUE;
787 #endif /* FEAT_SMARTINDENT */
788 
789 	did_ai = TRUE;
790     }
791 
792 #ifdef FEAT_COMMENTS
793     /*
794      * Find out if the current line starts with a comment leader.
795      * This may then be inserted in front of the new line.
796      */
797     end_comment_pending = NUL;
798     if (flags & OPENLINE_DO_COM)
799 	lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD);
800     else
801 	lead_len = 0;
802     if (lead_len > 0)
803     {
804 	char_u	*lead_repl = NULL;	    /* replaces comment leader */
805 	int	lead_repl_len = 0;	    /* length of *lead_repl */
806 	char_u	lead_middle[COM_MAX_LEN];   /* middle-comment string */
807 	char_u	lead_end[COM_MAX_LEN];	    /* end-comment string */
808 	char_u	*comment_end = NULL;	    /* where lead_end has been found */
809 	int	extra_space = FALSE;	    /* append extra space */
810 	int	current_flag;
811 	int	require_blank = FALSE;	    /* requires blank after middle */
812 	char_u	*p2;
813 
814 	/*
815 	 * If the comment leader has the start, middle or end flag, it may not
816 	 * be used or may be replaced with the middle leader.
817 	 */
818 	for (p = lead_flags; *p && *p != ':'; ++p)
819 	{
820 	    if (*p == COM_BLANK)
821 	    {
822 		require_blank = TRUE;
823 		continue;
824 	    }
825 	    if (*p == COM_START || *p == COM_MIDDLE)
826 	    {
827 		current_flag = *p;
828 		if (*p == COM_START)
829 		{
830 		    /*
831 		     * Doing "O" on a start of comment does not insert leader.
832 		     */
833 		    if (dir == BACKWARD)
834 		    {
835 			lead_len = 0;
836 			break;
837 		    }
838 
839 		    /* find start of middle part */
840 		    (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
841 		    require_blank = FALSE;
842 		}
843 
844 		/*
845 		 * Isolate the strings of the middle and end leader.
846 		 */
847 		while (*p && p[-1] != ':')	/* find end of middle flags */
848 		{
849 		    if (*p == COM_BLANK)
850 			require_blank = TRUE;
851 		    ++p;
852 		}
853 		(void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
854 
855 		while (*p && p[-1] != ':')	/* find end of end flags */
856 		{
857 		    /* Check whether we allow automatic ending of comments */
858 		    if (*p == COM_AUTO_END)
859 			end_comment_pending = -1; /* means we want to set it */
860 		    ++p;
861 		}
862 		n = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
863 
864 		if (end_comment_pending == -1)	/* we can set it now */
865 		    end_comment_pending = lead_end[n - 1];
866 
867 		/*
868 		 * If the end of the comment is in the same line, don't use
869 		 * the comment leader.
870 		 */
871 		if (dir == FORWARD)
872 		{
873 		    for (p = saved_line + lead_len; *p; ++p)
874 			if (STRNCMP(p, lead_end, n) == 0)
875 			{
876 			    comment_end = p;
877 			    lead_len = 0;
878 			    break;
879 			}
880 		}
881 
882 		/*
883 		 * Doing "o" on a start of comment inserts the middle leader.
884 		 */
885 		if (lead_len > 0)
886 		{
887 		    if (current_flag == COM_START)
888 		    {
889 			lead_repl = lead_middle;
890 			lead_repl_len = (int)STRLEN(lead_middle);
891 		    }
892 
893 		    /*
894 		     * If we have hit RETURN immediately after the start
895 		     * comment leader, then put a space after the middle
896 		     * comment leader on the next line.
897 		     */
898 		    if (!vim_iswhite(saved_line[lead_len - 1])
899 			    && ((p_extra != NULL
900 				    && (int)curwin->w_cursor.col == lead_len)
901 				|| (p_extra == NULL
902 				    && saved_line[lead_len] == NUL)
903 				|| require_blank))
904 			extra_space = TRUE;
905 		}
906 		break;
907 	    }
908 	    if (*p == COM_END)
909 	    {
910 		/*
911 		 * Doing "o" on the end of a comment does not insert leader.
912 		 * Remember where the end is, might want to use it to find the
913 		 * start (for C-comments).
914 		 */
915 		if (dir == FORWARD)
916 		{
917 		    comment_end = skipwhite(saved_line);
918 		    lead_len = 0;
919 		    break;
920 		}
921 
922 		/*
923 		 * Doing "O" on the end of a comment inserts the middle leader.
924 		 * Find the string for the middle leader, searching backwards.
925 		 */
926 		while (p > curbuf->b_p_com && *p != ',')
927 		    --p;
928 		for (lead_repl = p; lead_repl > curbuf->b_p_com
929 					 && lead_repl[-1] != ':'; --lead_repl)
930 		    ;
931 		lead_repl_len = (int)(p - lead_repl);
932 
933 		/* We can probably always add an extra space when doing "O" on
934 		 * the comment-end */
935 		extra_space = TRUE;
936 
937 		/* Check whether we allow automatic ending of comments */
938 		for (p2 = p; *p2 && *p2 != ':'; p2++)
939 		{
940 		    if (*p2 == COM_AUTO_END)
941 			end_comment_pending = -1; /* means we want to set it */
942 		}
943 		if (end_comment_pending == -1)
944 		{
945 		    /* Find last character in end-comment string */
946 		    while (*p2 && *p2 != ',')
947 			p2++;
948 		    end_comment_pending = p2[-1];
949 		}
950 		break;
951 	    }
952 	    if (*p == COM_FIRST)
953 	    {
954 		/*
955 		 * Comment leader for first line only:	Don't repeat leader
956 		 * when using "O", blank out leader when using "o".
957 		 */
958 		if (dir == BACKWARD)
959 		    lead_len = 0;
960 		else
961 		{
962 		    lead_repl = (char_u *)"";
963 		    lead_repl_len = 0;
964 		}
965 		break;
966 	    }
967 	}
968 	if (lead_len)
969 	{
970 	    /* allocate buffer (may concatenate p_exta later) */
971 	    leader = alloc(lead_len + lead_repl_len + extra_space +
972 							      extra_len + 1);
973 	    allocated = leader;		    /* remember to free it later */
974 
975 	    if (leader == NULL)
976 		lead_len = 0;
977 	    else
978 	    {
979 		vim_strncpy(leader, saved_line, lead_len);
980 
981 		/*
982 		 * Replace leader with lead_repl, right or left adjusted
983 		 */
984 		if (lead_repl != NULL)
985 		{
986 		    int		c = 0;
987 		    int		off = 0;
988 
989 		    for (p = lead_flags; *p && *p != ':'; ++p)
990 		    {
991 			if (*p == COM_RIGHT || *p == COM_LEFT)
992 			    c = *p;
993 			else if (VIM_ISDIGIT(*p) || *p == '-')
994 			    off = getdigits(&p);
995 		    }
996 		    if (c == COM_RIGHT)    /* right adjusted leader */
997 		    {
998 			/* find last non-white in the leader to line up with */
999 			for (p = leader + lead_len - 1; p > leader
1000 						      && vim_iswhite(*p); --p)
1001 			    ;
1002 			++p;
1003 
1004 #ifdef FEAT_MBYTE
1005 			/* Compute the length of the replaced characters in
1006 			 * screen characters, not bytes. */
1007 			{
1008 			    int	    repl_size = vim_strnsize(lead_repl,
1009 							       lead_repl_len);
1010 			    int	    old_size = 0;
1011 			    char_u  *endp = p;
1012 			    int	    l;
1013 
1014 			    while (old_size < repl_size && p > leader)
1015 			    {
1016 				mb_ptr_back(leader, p);
1017 				old_size += ptr2cells(p);
1018 			    }
1019 			    l = lead_repl_len - (endp - p);
1020 			    if (l != 0)
1021 				mch_memmove(endp + l, endp,
1022 					(size_t)((leader + lead_len) - endp));
1023 			    lead_len += l;
1024 			}
1025 #else
1026 			if (p < leader + lead_repl_len)
1027 			    p = leader;
1028 			else
1029 			    p -= lead_repl_len;
1030 #endif
1031 			mch_memmove(p, lead_repl, (size_t)lead_repl_len);
1032 			if (p + lead_repl_len > leader + lead_len)
1033 			    p[lead_repl_len] = NUL;
1034 
1035 			/* blank-out any other chars from the old leader. */
1036 			while (--p >= leader)
1037 			{
1038 #ifdef FEAT_MBYTE
1039 			    int l = mb_head_off(leader, p);
1040 
1041 			    if (l > 1)
1042 			    {
1043 				p -= l;
1044 				if (ptr2cells(p) > 1)
1045 				{
1046 				    p[1] = ' ';
1047 				    --l;
1048 				}
1049 				mch_memmove(p + 1, p + l + 1,
1050 				   (size_t)((leader + lead_len) - (p + l + 1)));
1051 				lead_len -= l;
1052 				*p = ' ';
1053 			    }
1054 			    else
1055 #endif
1056 			    if (!vim_iswhite(*p))
1057 				*p = ' ';
1058 			}
1059 		    }
1060 		    else		    /* left adjusted leader */
1061 		    {
1062 			p = skipwhite(leader);
1063 #ifdef FEAT_MBYTE
1064 			/* Compute the length of the replaced characters in
1065 			 * screen characters, not bytes. Move the part that is
1066 			 * not to be overwritten. */
1067 			{
1068 			    int	    repl_size = vim_strnsize(lead_repl,
1069 							       lead_repl_len);
1070 			    int	    i;
1071 			    int	    l;
1072 
1073 			    for (i = 0; p[i] != NUL && i < lead_len; i += l)
1074 			    {
1075 				l = (*mb_ptr2len)(p + i);
1076 				if (vim_strnsize(p, i + l) > repl_size)
1077 				    break;
1078 			    }
1079 			    if (i != lead_repl_len)
1080 			    {
1081 				mch_memmove(p + lead_repl_len, p + i,
1082 				       (size_t)(lead_len - i - (leader - p)));
1083 				lead_len += lead_repl_len - i;
1084 			    }
1085 			}
1086 #endif
1087 			mch_memmove(p, lead_repl, (size_t)lead_repl_len);
1088 
1089 			/* Replace any remaining non-white chars in the old
1090 			 * leader by spaces.  Keep Tabs, the indent must
1091 			 * remain the same. */
1092 			for (p += lead_repl_len; p < leader + lead_len; ++p)
1093 			    if (!vim_iswhite(*p))
1094 			    {
1095 				/* Don't put a space before a TAB. */
1096 				if (p + 1 < leader + lead_len && p[1] == TAB)
1097 				{
1098 				    --lead_len;
1099 				    mch_memmove(p, p + 1,
1100 						     (leader + lead_len) - p);
1101 				}
1102 				else
1103 				{
1104 #ifdef FEAT_MBYTE
1105 				    int	    l = (*mb_ptr2len)(p);
1106 
1107 				    if (l > 1)
1108 				    {
1109 					if (ptr2cells(p) > 1)
1110 					{
1111 					    /* Replace a double-wide char with
1112 					     * two spaces */
1113 					    --l;
1114 					    *p++ = ' ';
1115 					}
1116 					mch_memmove(p + 1, p + l,
1117 						     (leader + lead_len) - p);
1118 					lead_len -= l - 1;
1119 				    }
1120 #endif
1121 				    *p = ' ';
1122 				}
1123 			    }
1124 			*p = NUL;
1125 		    }
1126 
1127 		    /* Recompute the indent, it may have changed. */
1128 		    if (curbuf->b_p_ai
1129 #ifdef FEAT_SMARTINDENT
1130 					|| do_si
1131 #endif
1132 							   )
1133 			newindent = get_indent_str(leader, (int)curbuf->b_p_ts);
1134 
1135 		    /* Add the indent offset */
1136 		    if (newindent + off < 0)
1137 		    {
1138 			off = -newindent;
1139 			newindent = 0;
1140 		    }
1141 		    else
1142 			newindent += off;
1143 
1144 		    /* Correct trailing spaces for the shift, so that
1145 		     * alignment remains equal. */
1146 		    while (off > 0 && lead_len > 0
1147 					       && leader[lead_len - 1] == ' ')
1148 		    {
1149 			/* Don't do it when there is a tab before the space */
1150 			if (vim_strchr(skipwhite(leader), '\t') != NULL)
1151 			    break;
1152 			--lead_len;
1153 			--off;
1154 		    }
1155 
1156 		    /* If the leader ends in white space, don't add an
1157 		     * extra space */
1158 		    if (lead_len > 0 && vim_iswhite(leader[lead_len - 1]))
1159 			extra_space = FALSE;
1160 		    leader[lead_len] = NUL;
1161 		}
1162 
1163 		if (extra_space)
1164 		{
1165 		    leader[lead_len++] = ' ';
1166 		    leader[lead_len] = NUL;
1167 		}
1168 
1169 		newcol = lead_len;
1170 
1171 		/*
1172 		 * if a new indent will be set below, remove the indent that
1173 		 * is in the comment leader
1174 		 */
1175 		if (newindent
1176 #ifdef FEAT_SMARTINDENT
1177 				|| did_si
1178 #endif
1179 					   )
1180 		{
1181 		    while (lead_len && vim_iswhite(*leader))
1182 		    {
1183 			--lead_len;
1184 			--newcol;
1185 			++leader;
1186 		    }
1187 		}
1188 
1189 	    }
1190 #ifdef FEAT_SMARTINDENT
1191 	    did_si = can_si = FALSE;
1192 #endif
1193 	}
1194 	else if (comment_end != NULL)
1195 	{
1196 	    /*
1197 	     * We have finished a comment, so we don't use the leader.
1198 	     * If this was a C-comment and 'ai' or 'si' is set do a normal
1199 	     * indent to align with the line containing the start of the
1200 	     * comment.
1201 	     */
1202 	    if (comment_end[0] == '*' && comment_end[1] == '/' &&
1203 			(curbuf->b_p_ai
1204 #ifdef FEAT_SMARTINDENT
1205 					|| do_si
1206 #endif
1207 							   ))
1208 	    {
1209 		old_cursor = curwin->w_cursor;
1210 		curwin->w_cursor.col = (colnr_T)(comment_end - saved_line);
1211 		if ((pos = findmatch(NULL, NUL)) != NULL)
1212 		{
1213 		    curwin->w_cursor.lnum = pos->lnum;
1214 		    newindent = get_indent();
1215 		}
1216 		curwin->w_cursor = old_cursor;
1217 	    }
1218 	}
1219     }
1220 #endif
1221 
1222     /* (State == INSERT || State == REPLACE), only when dir == FORWARD */
1223     if (p_extra != NULL)
1224     {
1225 	*p_extra = saved_char;		/* restore char that NUL replaced */
1226 
1227 	/*
1228 	 * When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first
1229 	 * non-blank.
1230 	 *
1231 	 * When in REPLACE mode, put the deleted blanks on the replace stack,
1232 	 * preceded by a NUL, so they can be put back when a BS is entered.
1233 	 */
1234 	if (REPLACE_NORMAL(State))
1235 	    replace_push(NUL);	    /* end of extra blanks */
1236 	if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES))
1237 	{
1238 	    while ((*p_extra == ' ' || *p_extra == '\t')
1239 #ifdef FEAT_MBYTE
1240 		    && (!enc_utf8
1241 			       || !utf_iscomposing(utf_ptr2char(p_extra + 1)))
1242 #endif
1243 		    )
1244 	    {
1245 		if (REPLACE_NORMAL(State))
1246 		    replace_push(*p_extra);
1247 		++p_extra;
1248 		++less_cols_off;
1249 	    }
1250 	}
1251 	if (*p_extra != NUL)
1252 	    did_ai = FALSE;	    /* append some text, don't truncate now */
1253 
1254 	/* columns for marks adjusted for removed columns */
1255 	less_cols = (int)(p_extra - saved_line);
1256     }
1257 
1258     if (p_extra == NULL)
1259 	p_extra = (char_u *)"";		    /* append empty line */
1260 
1261 #ifdef FEAT_COMMENTS
1262     /* concatenate leader and p_extra, if there is a leader */
1263     if (lead_len)
1264     {
1265 	STRCAT(leader, p_extra);
1266 	p_extra = leader;
1267 	did_ai = TRUE;	    /* So truncating blanks works with comments */
1268 	less_cols -= lead_len;
1269     }
1270     else
1271 	end_comment_pending = NUL;  /* turns out there was no leader */
1272 #endif
1273 
1274     old_cursor = curwin->w_cursor;
1275     if (dir == BACKWARD)
1276 	--curwin->w_cursor.lnum;
1277 #ifdef FEAT_VREPLACE
1278     if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count)
1279 #endif
1280     {
1281 	if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE)
1282 								      == FAIL)
1283 	    goto theend;
1284 	/* Postpone calling changed_lines(), because it would mess up folding
1285 	 * with markers. */
1286 	mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
1287 	did_append = TRUE;
1288     }
1289 #ifdef FEAT_VREPLACE
1290     else
1291     {
1292 	/*
1293 	 * In VREPLACE mode we are starting to replace the next line.
1294 	 */
1295 	curwin->w_cursor.lnum++;
1296 	if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed)
1297 	{
1298 	    /* In case we NL to a new line, BS to the previous one, and NL
1299 	     * again, we don't want to save the new line for undo twice.
1300 	     */
1301 	    (void)u_save_cursor();		    /* errors are ignored! */
1302 	    vr_lines_changed++;
1303 	}
1304 	ml_replace(curwin->w_cursor.lnum, p_extra, TRUE);
1305 	changed_bytes(curwin->w_cursor.lnum, 0);
1306 	curwin->w_cursor.lnum--;
1307 	did_append = FALSE;
1308     }
1309 #endif
1310 
1311     if (newindent
1312 #ifdef FEAT_SMARTINDENT
1313 		    || did_si
1314 #endif
1315 				)
1316     {
1317 	++curwin->w_cursor.lnum;
1318 #ifdef FEAT_SMARTINDENT
1319 	if (did_si)
1320 	{
1321 	    if (p_sr)
1322 		newindent -= newindent % (int)curbuf->b_p_sw;
1323 	    newindent += (int)curbuf->b_p_sw;
1324 	}
1325 #endif
1326 	/* Copy the indent only if expand tab is disabled */
1327 	if (curbuf->b_p_ci && !curbuf->b_p_et)
1328 	{
1329 	    (void)copy_indent(newindent, saved_line);
1330 
1331 	    /*
1332 	     * Set the 'preserveindent' option so that any further screwing
1333 	     * with the line doesn't entirely destroy our efforts to preserve
1334 	     * it.  It gets restored at the function end.
1335 	     */
1336 	    curbuf->b_p_pi = TRUE;
1337 	}
1338 	else
1339 	    (void)set_indent(newindent, SIN_INSERT);
1340 	less_cols -= curwin->w_cursor.col;
1341 
1342 	ai_col = curwin->w_cursor.col;
1343 
1344 	/*
1345 	 * In REPLACE mode, for each character in the new indent, there must
1346 	 * be a NUL on the replace stack, for when it is deleted with BS
1347 	 */
1348 	if (REPLACE_NORMAL(State))
1349 	    for (n = 0; n < (int)curwin->w_cursor.col; ++n)
1350 		replace_push(NUL);
1351 	newcol += curwin->w_cursor.col;
1352 #ifdef FEAT_SMARTINDENT
1353 	if (no_si)
1354 	    did_si = FALSE;
1355 #endif
1356     }
1357 
1358 #ifdef FEAT_COMMENTS
1359     /*
1360      * In REPLACE mode, for each character in the extra leader, there must be
1361      * a NUL on the replace stack, for when it is deleted with BS.
1362      */
1363     if (REPLACE_NORMAL(State))
1364 	while (lead_len-- > 0)
1365 	    replace_push(NUL);
1366 #endif
1367 
1368     curwin->w_cursor = old_cursor;
1369 
1370     if (dir == FORWARD)
1371     {
1372 	if (trunc_line || (State & INSERT))
1373 	{
1374 	    /* truncate current line at cursor */
1375 	    saved_line[curwin->w_cursor.col] = NUL;
1376 	    /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */
1377 	    if (trunc_line && !(flags & OPENLINE_KEEPTRAIL))
1378 		truncate_spaces(saved_line);
1379 	    ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
1380 	    saved_line = NULL;
1381 	    if (did_append)
1382 	    {
1383 		changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
1384 					       curwin->w_cursor.lnum + 1, 1L);
1385 		did_append = FALSE;
1386 
1387 		/* Move marks after the line break to the new line. */
1388 		if (flags & OPENLINE_MARKFIX)
1389 		    mark_col_adjust(curwin->w_cursor.lnum,
1390 					 curwin->w_cursor.col + less_cols_off,
1391 							1L, (long)-less_cols);
1392 	    }
1393 	    else
1394 		changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
1395 	}
1396 
1397 	/*
1398 	 * Put the cursor on the new line.  Careful: the scrollup() above may
1399 	 * have moved w_cursor, we must use old_cursor.
1400 	 */
1401 	curwin->w_cursor.lnum = old_cursor.lnum + 1;
1402     }
1403     if (did_append)
1404 	changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L);
1405 
1406     curwin->w_cursor.col = newcol;
1407 #ifdef FEAT_VIRTUALEDIT
1408     curwin->w_cursor.coladd = 0;
1409 #endif
1410 
1411 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
1412     /*
1413      * In VREPLACE mode, we are handling the replace stack ourselves, so stop
1414      * fixthisline() from doing it (via change_indent()) by telling it we're in
1415      * normal INSERT mode.
1416      */
1417     if (State & VREPLACE_FLAG)
1418     {
1419 	vreplace_mode = State;	/* So we know to put things right later */
1420 	State = INSERT;
1421     }
1422     else
1423 	vreplace_mode = 0;
1424 #endif
1425 #ifdef FEAT_LISP
1426     /*
1427      * May do lisp indenting.
1428      */
1429     if (!p_paste
1430 # ifdef FEAT_COMMENTS
1431 	    && leader == NULL
1432 # endif
1433 	    && curbuf->b_p_lisp
1434 	    && curbuf->b_p_ai)
1435     {
1436 	fixthisline(get_lisp_indent);
1437 	p = ml_get_curline();
1438 	ai_col = (colnr_T)(skipwhite(p) - p);
1439     }
1440 #endif
1441 #ifdef FEAT_CINDENT
1442     /*
1443      * May do indenting after opening a new line.
1444      */
1445     if (!p_paste
1446 	    && (curbuf->b_p_cin
1447 #  ifdef FEAT_EVAL
1448 		    || *curbuf->b_p_inde != NUL
1449 #  endif
1450 		)
1451 	    && in_cinkeys(dir == FORWARD
1452 		? KEY_OPEN_FORW
1453 		: KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
1454     {
1455 	do_c_expr_indent();
1456 	p = ml_get_curline();
1457 	ai_col = (colnr_T)(skipwhite(p) - p);
1458     }
1459 #endif
1460 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
1461     if (vreplace_mode != 0)
1462 	State = vreplace_mode;
1463 #endif
1464 
1465 #ifdef FEAT_VREPLACE
1466     /*
1467      * Finally, VREPLACE gets the stuff on the new line, then puts back the
1468      * original line, and inserts the new stuff char by char, pushing old stuff
1469      * onto the replace stack (via ins_char()).
1470      */
1471     if (State & VREPLACE_FLAG)
1472     {
1473 	/* Put new line in p_extra */
1474 	p_extra = vim_strsave(ml_get_curline());
1475 	if (p_extra == NULL)
1476 	    goto theend;
1477 
1478 	/* Put back original line */
1479 	ml_replace(curwin->w_cursor.lnum, next_line, FALSE);
1480 
1481 	/* Insert new stuff into line again */
1482 	curwin->w_cursor.col = 0;
1483 #ifdef FEAT_VIRTUALEDIT
1484 	curwin->w_cursor.coladd = 0;
1485 #endif
1486 	ins_bytes(p_extra);	/* will call changed_bytes() */
1487 	vim_free(p_extra);
1488 	next_line = NULL;
1489     }
1490 #endif
1491 
1492     retval = TRUE;		/* success! */
1493 theend:
1494     curbuf->b_p_pi = saved_pi;
1495     vim_free(saved_line);
1496     vim_free(next_line);
1497     vim_free(allocated);
1498     return retval;
1499 }
1500 
1501 #if defined(FEAT_COMMENTS) || defined(PROTO)
1502 /*
1503  * get_leader_len() returns the length of the prefix of the given string
1504  * which introduces a comment.	If this string is not a comment then 0 is
1505  * returned.
1506  * When "flags" is not NULL, it is set to point to the flags of the recognized
1507  * comment leader.
1508  * "backward" must be true for the "O" command.
1509  */
1510     int
1511 get_leader_len(line, flags, backward)
1512     char_u	*line;
1513     char_u	**flags;
1514     int		backward;
1515 {
1516     int		i, j;
1517     int		got_com = FALSE;
1518     int		found_one;
1519     char_u	part_buf[COM_MAX_LEN];	/* buffer for one option part */
1520     char_u	*string;		/* pointer to comment string */
1521     char_u	*list;
1522 
1523     i = 0;
1524     while (vim_iswhite(line[i]))    /* leading white space is ignored */
1525 	++i;
1526 
1527     /*
1528      * Repeat to match several nested comment strings.
1529      */
1530     while (line[i])
1531     {
1532 	/*
1533 	 * scan through the 'comments' option for a match
1534 	 */
1535 	found_one = FALSE;
1536 	for (list = curbuf->b_p_com; *list; )
1537 	{
1538 	    /*
1539 	     * Get one option part into part_buf[].  Advance list to next one.
1540 	     * put string at start of string.
1541 	     */
1542 	    if (!got_com && flags != NULL)  /* remember where flags started */
1543 		*flags = list;
1544 	    (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
1545 	    string = vim_strchr(part_buf, ':');
1546 	    if (string == NULL)	    /* missing ':', ignore this part */
1547 		continue;
1548 	    *string++ = NUL;	    /* isolate flags from string */
1549 
1550 	    /*
1551 	     * When already found a nested comment, only accept further
1552 	     * nested comments.
1553 	     */
1554 	    if (got_com && vim_strchr(part_buf, COM_NEST) == NULL)
1555 		continue;
1556 
1557 	    /* When 'O' flag used don't use for "O" command */
1558 	    if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL)
1559 		continue;
1560 
1561 	    /*
1562 	     * Line contents and string must match.
1563 	     * When string starts with white space, must have some white space
1564 	     * (but the amount does not need to match, there might be a mix of
1565 	     * TABs and spaces).
1566 	     */
1567 	    if (vim_iswhite(string[0]))
1568 	    {
1569 		if (i == 0 || !vim_iswhite(line[i - 1]))
1570 		    continue;
1571 		while (vim_iswhite(string[0]))
1572 		    ++string;
1573 	    }
1574 	    for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
1575 		;
1576 	    if (string[j] != NUL)
1577 		continue;
1578 
1579 	    /*
1580 	     * When 'b' flag used, there must be white space or an
1581 	     * end-of-line after the string in the line.
1582 	     */
1583 	    if (vim_strchr(part_buf, COM_BLANK) != NULL
1584 			   && !vim_iswhite(line[i + j]) && line[i + j] != NUL)
1585 		continue;
1586 
1587 	    /*
1588 	     * We have found a match, stop searching.
1589 	     */
1590 	    i += j;
1591 	    got_com = TRUE;
1592 	    found_one = TRUE;
1593 	    break;
1594 	}
1595 
1596 	/*
1597 	 * No match found, stop scanning.
1598 	 */
1599 	if (!found_one)
1600 	    break;
1601 
1602 	/*
1603 	 * Include any trailing white space.
1604 	 */
1605 	while (vim_iswhite(line[i]))
1606 	    ++i;
1607 
1608 	/*
1609 	 * If this comment doesn't nest, stop here.
1610 	 */
1611 	if (vim_strchr(part_buf, COM_NEST) == NULL)
1612 	    break;
1613     }
1614     return (got_com ? i : 0);
1615 }
1616 #endif
1617 
1618 /*
1619  * Return the number of window lines occupied by buffer line "lnum".
1620  */
1621     int
1622 plines(lnum)
1623     linenr_T	lnum;
1624 {
1625     return plines_win(curwin, lnum, TRUE);
1626 }
1627 
1628     int
1629 plines_win(wp, lnum, winheight)
1630     win_T	*wp;
1631     linenr_T	lnum;
1632     int		winheight;	/* when TRUE limit to window height */
1633 {
1634 #if defined(FEAT_DIFF) || defined(PROTO)
1635     /* Check for filler lines above this buffer line.  When folded the result
1636      * is one line anyway. */
1637     return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
1638 }
1639 
1640     int
1641 plines_nofill(lnum)
1642     linenr_T	lnum;
1643 {
1644     return plines_win_nofill(curwin, lnum, TRUE);
1645 }
1646 
1647     int
1648 plines_win_nofill(wp, lnum, winheight)
1649     win_T	*wp;
1650     linenr_T	lnum;
1651     int		winheight;	/* when TRUE limit to window height */
1652 {
1653 #endif
1654     int		lines;
1655 
1656     if (!wp->w_p_wrap)
1657 	return 1;
1658 
1659 #ifdef FEAT_VERTSPLIT
1660     if (wp->w_width == 0)
1661 	return 1;
1662 #endif
1663 
1664 #ifdef FEAT_FOLDING
1665     /* A folded lines is handled just like an empty line. */
1666     /* NOTE: Caller must handle lines that are MAYBE folded. */
1667     if (lineFolded(wp, lnum) == TRUE)
1668 	return 1;
1669 #endif
1670 
1671     lines = plines_win_nofold(wp, lnum);
1672     if (winheight > 0 && lines > wp->w_height)
1673 	return (int)wp->w_height;
1674     return lines;
1675 }
1676 
1677 /*
1678  * Return number of window lines physical line "lnum" will occupy in window
1679  * "wp".  Does not care about folding, 'wrap' or 'diff'.
1680  */
1681     int
1682 plines_win_nofold(wp, lnum)
1683     win_T	*wp;
1684     linenr_T	lnum;
1685 {
1686     char_u	*s;
1687     long	col;
1688     int		width;
1689 
1690     s = ml_get_buf(wp->w_buffer, lnum, FALSE);
1691     if (*s == NUL)		/* empty line */
1692 	return 1;
1693     col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
1694 
1695     /*
1696      * If list mode is on, then the '$' at the end of the line may take up one
1697      * extra column.
1698      */
1699     if (wp->w_p_list && lcs_eol != NUL)
1700 	col += 1;
1701 
1702     /*
1703      * Add column offset for 'number' and 'foldcolumn'.
1704      */
1705     width = W_WIDTH(wp) - win_col_off(wp);
1706     if (width <= 0)
1707 	return 32000;
1708     if (col <= width)
1709 	return 1;
1710     col -= width;
1711     width += win_col_off2(wp);
1712     return (col + (width - 1)) / width + 1;
1713 }
1714 
1715 /*
1716  * Like plines_win(), but only reports the number of physical screen lines
1717  * used from the start of the line to the given column number.
1718  */
1719     int
1720 plines_win_col(wp, lnum, column)
1721     win_T	*wp;
1722     linenr_T	lnum;
1723     long	column;
1724 {
1725     long	col;
1726     char_u	*s;
1727     int		lines = 0;
1728     int		width;
1729 
1730 #ifdef FEAT_DIFF
1731     /* Check for filler lines above this buffer line.  When folded the result
1732      * is one line anyway. */
1733     lines = diff_check_fill(wp, lnum);
1734 #endif
1735 
1736     if (!wp->w_p_wrap)
1737 	return lines + 1;
1738 
1739 #ifdef FEAT_VERTSPLIT
1740     if (wp->w_width == 0)
1741 	return lines + 1;
1742 #endif
1743 
1744     s = ml_get_buf(wp->w_buffer, lnum, FALSE);
1745 
1746     col = 0;
1747     while (*s != NUL && --column >= 0)
1748     {
1749 	col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL);
1750 	mb_ptr_adv(s);
1751     }
1752 
1753     /*
1754      * If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
1755      * INSERT mode, then col must be adjusted so that it represents the last
1756      * screen position of the TAB.  This only fixes an error when the TAB wraps
1757      * from one screen line to the next (when 'columns' is not a multiple of
1758      * 'ts') -- webb.
1759      */
1760     if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1))
1761 	col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
1762 
1763     /*
1764      * Add column offset for 'number', 'foldcolumn', etc.
1765      */
1766     width = W_WIDTH(wp) - win_col_off(wp);
1767     if (width > 0)
1768     {
1769 	lines += 1;
1770 	if (col >= width)
1771 	    lines += (col - width) / (width + win_col_off2(wp));
1772 	if (lines <= wp->w_height)
1773 	    return lines;
1774     }
1775     return (int)(wp->w_height);	    /* maximum length */
1776 }
1777 
1778     int
1779 plines_m_win(wp, first, last)
1780     win_T	*wp;
1781     linenr_T	first, last;
1782 {
1783     int		count = 0;
1784 
1785     while (first <= last)
1786     {
1787 #ifdef FEAT_FOLDING
1788 	int	x;
1789 
1790 	/* Check if there are any really folded lines, but also included lines
1791 	 * that are maybe folded. */
1792 	x = foldedCount(wp, first, NULL);
1793 	if (x > 0)
1794 	{
1795 	    ++count;	    /* count 1 for "+-- folded" line */
1796 	    first += x;
1797 	}
1798 	else
1799 #endif
1800 	{
1801 #ifdef FEAT_DIFF
1802 	    if (first == wp->w_topline)
1803 		count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill;
1804 	    else
1805 #endif
1806 		count += plines_win(wp, first, TRUE);
1807 	    ++first;
1808 	}
1809     }
1810     return (count);
1811 }
1812 
1813 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) || defined(PROTO)
1814 /*
1815  * Insert string "p" at the cursor position.  Stops at a NUL byte.
1816  * Handles Replace mode and multi-byte characters.
1817  */
1818     void
1819 ins_bytes(p)
1820     char_u	*p;
1821 {
1822     ins_bytes_len(p, (int)STRLEN(p));
1823 }
1824 #endif
1825 
1826 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
1827 	|| defined(FEAT_COMMENTS) || defined(FEAT_MBYTE) || defined(PROTO)
1828 /*
1829  * Insert string "p" with length "len" at the cursor position.
1830  * Handles Replace mode and multi-byte characters.
1831  */
1832     void
1833 ins_bytes_len(p, len)
1834     char_u	*p;
1835     int		len;
1836 {
1837     int		i;
1838 # ifdef FEAT_MBYTE
1839     int		n;
1840 
1841     for (i = 0; i < len; i += n)
1842     {
1843 	n = (*mb_ptr2len)(p + i);
1844 	ins_char_bytes(p + i, n);
1845     }
1846 # else
1847     for (i = 0; i < len; ++i)
1848 	ins_char(p[i]);
1849 # endif
1850 }
1851 #endif
1852 
1853 /*
1854  * Insert or replace a single character at the cursor position.
1855  * When in REPLACE or VREPLACE mode, replace any existing character.
1856  * Caller must have prepared for undo.
1857  * For multi-byte characters we get the whole character, the caller must
1858  * convert bytes to a character.
1859  */
1860     void
1861 ins_char(c)
1862     int		c;
1863 {
1864 #if defined(FEAT_MBYTE) || defined(PROTO)
1865     char_u	buf[MB_MAXBYTES];
1866     int		n;
1867 
1868     n = (*mb_char2bytes)(c, buf);
1869 
1870     /* When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte.
1871      * Happens for CTRL-Vu9900. */
1872     if (buf[0] == 0)
1873 	buf[0] = '\n';
1874 
1875     ins_char_bytes(buf, n);
1876 }
1877 
1878     void
1879 ins_char_bytes(buf, charlen)
1880     char_u	*buf;
1881     int		charlen;
1882 {
1883     int		c = buf[0];
1884     int		l, j;
1885 #endif
1886     int		newlen;		/* nr of bytes inserted */
1887     int		oldlen;		/* nr of bytes deleted (0 when not replacing) */
1888     char_u	*p;
1889     char_u	*newp;
1890     char_u	*oldp;
1891     int		linelen;	/* length of old line including NUL */
1892     colnr_T	col;
1893     linenr_T	lnum = curwin->w_cursor.lnum;
1894     int		i;
1895 
1896 #ifdef FEAT_VIRTUALEDIT
1897     /* Break tabs if needed. */
1898     if (virtual_active() && curwin->w_cursor.coladd > 0)
1899 	coladvance_force(getviscol());
1900 #endif
1901 
1902     col = curwin->w_cursor.col;
1903     oldp = ml_get(lnum);
1904     linelen = (int)STRLEN(oldp) + 1;
1905 
1906     /* The lengths default to the values for when not replacing. */
1907     oldlen = 0;
1908 #ifdef FEAT_MBYTE
1909     newlen = charlen;
1910 #else
1911     newlen = 1;
1912 #endif
1913 
1914     if (State & REPLACE_FLAG)
1915     {
1916 #ifdef FEAT_VREPLACE
1917 	if (State & VREPLACE_FLAG)
1918 	{
1919 	    colnr_T	new_vcol = 0;   /* init for GCC */
1920 	    colnr_T	vcol;
1921 	    int		old_list;
1922 #ifndef FEAT_MBYTE
1923 	    char_u	buf[2];
1924 #endif
1925 
1926 	    /*
1927 	     * Disable 'list' temporarily, unless 'cpo' contains the 'L' flag.
1928 	     * Returns the old value of list, so when finished,
1929 	     * curwin->w_p_list should be set back to this.
1930 	     */
1931 	    old_list = curwin->w_p_list;
1932 	    if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
1933 		curwin->w_p_list = FALSE;
1934 
1935 	    /*
1936 	     * In virtual replace mode each character may replace one or more
1937 	     * characters (zero if it's a TAB).  Count the number of bytes to
1938 	     * be deleted to make room for the new character, counting screen
1939 	     * cells.  May result in adding spaces to fill a gap.
1940 	     */
1941 	    getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
1942 #ifndef FEAT_MBYTE
1943 	    buf[0] = c;
1944 	    buf[1] = NUL;
1945 #endif
1946 	    new_vcol = vcol + chartabsize(buf, vcol);
1947 	    while (oldp[col + oldlen] != NUL && vcol < new_vcol)
1948 	    {
1949 		vcol += chartabsize(oldp + col + oldlen, vcol);
1950 		/* Don't need to remove a TAB that takes us to the right
1951 		 * position. */
1952 		if (vcol > new_vcol && oldp[col + oldlen] == TAB)
1953 		    break;
1954 #ifdef FEAT_MBYTE
1955 		oldlen += (*mb_ptr2len)(oldp + col + oldlen);
1956 #else
1957 		++oldlen;
1958 #endif
1959 		/* Deleted a bit too much, insert spaces. */
1960 		if (vcol > new_vcol)
1961 		    newlen += vcol - new_vcol;
1962 	    }
1963 	    curwin->w_p_list = old_list;
1964 	}
1965 	else
1966 #endif
1967 	    if (oldp[col] != NUL)
1968 	{
1969 	    /* normal replace */
1970 #ifdef FEAT_MBYTE
1971 	    oldlen = (*mb_ptr2len)(oldp + col);
1972 #else
1973 	    oldlen = 1;
1974 #endif
1975 	}
1976 
1977 
1978 	/* Push the replaced bytes onto the replace stack, so that they can be
1979 	 * put back when BS is used.  The bytes of a multi-byte character are
1980 	 * done the other way around, so that the first byte is popped off
1981 	 * first (it tells the byte length of the character). */
1982 	replace_push(NUL);
1983 	for (i = 0; i < oldlen; ++i)
1984 	{
1985 #ifdef FEAT_MBYTE
1986 	    l = (*mb_ptr2len)(oldp + col + i) - 1;
1987 	    for (j = l; j >= 0; --j)
1988 		replace_push(oldp[col + i + j]);
1989 	    i += l;
1990 #else
1991 	    replace_push(oldp[col + i]);
1992 #endif
1993 	}
1994     }
1995 
1996     newp = alloc_check((unsigned)(linelen + newlen - oldlen));
1997     if (newp == NULL)
1998 	return;
1999 
2000     /* Copy bytes before the cursor. */
2001     if (col > 0)
2002 	mch_memmove(newp, oldp, (size_t)col);
2003 
2004     /* Copy bytes after the changed character(s). */
2005     p = newp + col;
2006     mch_memmove(p + newlen, oldp + col + oldlen,
2007 					    (size_t)(linelen - col - oldlen));
2008 
2009     /* Insert or overwrite the new character. */
2010 #ifdef FEAT_MBYTE
2011     mch_memmove(p, buf, charlen);
2012     i = charlen;
2013 #else
2014     *p = c;
2015     i = 1;
2016 #endif
2017 
2018     /* Fill with spaces when necessary. */
2019     while (i < newlen)
2020 	p[i++] = ' ';
2021 
2022     /* Replace the line in the buffer. */
2023     ml_replace(lnum, newp, FALSE);
2024 
2025     /* mark the buffer as changed and prepare for displaying */
2026     changed_bytes(lnum, col);
2027 
2028     /*
2029      * If we're in Insert or Replace mode and 'showmatch' is set, then briefly
2030      * show the match for right parens and braces.
2031      */
2032     if (p_sm && (State & INSERT)
2033 	    && msg_silent == 0
2034 #ifdef FEAT_MBYTE
2035 	    && charlen == 1
2036 #endif
2037        )
2038 	showmatch(c);
2039 
2040 #ifdef FEAT_RIGHTLEFT
2041     if (!p_ri || (State & REPLACE_FLAG))
2042 #endif
2043     {
2044 	/* Normal insert: move cursor right */
2045 #ifdef FEAT_MBYTE
2046 	curwin->w_cursor.col += charlen;
2047 #else
2048 	++curwin->w_cursor.col;
2049 #endif
2050     }
2051     /*
2052      * TODO: should try to update w_row here, to avoid recomputing it later.
2053      */
2054 }
2055 
2056 /*
2057  * Insert a string at the cursor position.
2058  * Note: Does NOT handle Replace mode.
2059  * Caller must have prepared for undo.
2060  */
2061     void
2062 ins_str(s)
2063     char_u	*s;
2064 {
2065     char_u	*oldp, *newp;
2066     int		newlen = (int)STRLEN(s);
2067     int		oldlen;
2068     colnr_T	col;
2069     linenr_T	lnum = curwin->w_cursor.lnum;
2070 
2071 #ifdef FEAT_VIRTUALEDIT
2072     if (virtual_active() && curwin->w_cursor.coladd > 0)
2073 	coladvance_force(getviscol());
2074 #endif
2075 
2076     col = curwin->w_cursor.col;
2077     oldp = ml_get(lnum);
2078     oldlen = (int)STRLEN(oldp);
2079 
2080     newp = alloc_check((unsigned)(oldlen + newlen + 1));
2081     if (newp == NULL)
2082 	return;
2083     if (col > 0)
2084 	mch_memmove(newp, oldp, (size_t)col);
2085     mch_memmove(newp + col, s, (size_t)newlen);
2086     mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
2087     ml_replace(lnum, newp, FALSE);
2088     changed_bytes(lnum, col);
2089     curwin->w_cursor.col += newlen;
2090 }
2091 
2092 /*
2093  * Delete one character under the cursor.
2094  * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
2095  * Caller must have prepared for undo.
2096  *
2097  * return FAIL for failure, OK otherwise
2098  */
2099     int
2100 del_char(fixpos)
2101     int		fixpos;
2102 {
2103 #ifdef FEAT_MBYTE
2104     if (has_mbyte)
2105     {
2106 	/* Make sure the cursor is at the start of a character. */
2107 	mb_adjust_cursor();
2108 	if (*ml_get_cursor() == NUL)
2109 	    return FAIL;
2110 	return del_chars(1L, fixpos);
2111     }
2112 #endif
2113     return del_bytes(1L, fixpos);
2114 }
2115 
2116 #if defined(FEAT_MBYTE) || defined(PROTO)
2117 /*
2118  * Like del_bytes(), but delete characters instead of bytes.
2119  */
2120     int
2121 del_chars(count, fixpos)
2122     long	count;
2123     int		fixpos;
2124 {
2125     long	bytes = 0;
2126     long	i;
2127     char_u	*p;
2128     int		l;
2129 
2130     p = ml_get_cursor();
2131     for (i = 0; i < count && *p != NUL; ++i)
2132     {
2133 	l = (*mb_ptr2len)(p);
2134 	bytes += l;
2135 	p += l;
2136     }
2137     return del_bytes(bytes, fixpos);
2138 }
2139 #endif
2140 
2141 /*
2142  * Delete "count" bytes under the cursor.
2143  * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
2144  * Caller must have prepared for undo.
2145  *
2146  * return FAIL for failure, OK otherwise
2147  */
2148     int
2149 del_bytes(count, fixpos)
2150     long	count;
2151     int		fixpos;
2152 {
2153     char_u	*oldp, *newp;
2154     colnr_T	oldlen;
2155     linenr_T	lnum = curwin->w_cursor.lnum;
2156     colnr_T	col = curwin->w_cursor.col;
2157     int		was_alloced;
2158     long	movelen;
2159 
2160     oldp = ml_get(lnum);
2161     oldlen = (int)STRLEN(oldp);
2162 
2163     /*
2164      * Can't do anything when the cursor is on the NUL after the line.
2165      */
2166     if (col >= oldlen)
2167 	return FAIL;
2168 
2169 #ifdef FEAT_MBYTE
2170     /* If 'delcombine' is set and deleting (less than) one character, only
2171      * delete the last combining character. */
2172     if (p_deco && enc_utf8 && utfc_ptr2len(oldp + col) >= count)
2173     {
2174 	int	c1, c2;
2175 	int	n;
2176 
2177 	(void)utfc_ptr2char(oldp + col, &c1, &c2);
2178 	if (c1 != NUL)
2179 	{
2180 	    /* Find the last composing char, there can be several. */
2181 	    n = col;
2182 	    do
2183 	    {
2184 		col = n;
2185 		count = utf_ptr2len(oldp + n);
2186 		n += count;
2187 	    } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n));
2188 	    fixpos = 0;
2189 	}
2190     }
2191 #endif
2192 
2193     /*
2194      * When count is too big, reduce it.
2195      */
2196     movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */
2197     if (movelen <= 1)
2198     {
2199 	/*
2200 	 * If we just took off the last character of a non-blank line, and
2201 	 * fixpos is TRUE, we don't want to end up positioned at the NUL.
2202 	 */
2203 	if (col > 0 && fixpos)
2204 	{
2205 	    --curwin->w_cursor.col;
2206 #ifdef FEAT_VIRTUALEDIT
2207 	    curwin->w_cursor.coladd = 0;
2208 #endif
2209 #ifdef FEAT_MBYTE
2210 	    if (has_mbyte)
2211 		curwin->w_cursor.col -=
2212 			    (*mb_head_off)(oldp, oldp + curwin->w_cursor.col);
2213 #endif
2214 	}
2215 	count = oldlen - col;
2216 	movelen = 1;
2217     }
2218 
2219     /*
2220      * If the old line has been allocated the deletion can be done in the
2221      * existing line. Otherwise a new line has to be allocated
2222      */
2223     was_alloced = ml_line_alloced();	    /* check if oldp was allocated */
2224 #ifdef FEAT_NETBEANS_INTG
2225     if (was_alloced && usingNetbeans)
2226 	netbeans_removed(curbuf, lnum, col, count);
2227     /* else is handled by ml_replace() */
2228 #endif
2229     if (was_alloced)
2230 	newp = oldp;			    /* use same allocated memory */
2231     else
2232     {					    /* need to allocate a new line */
2233 	newp = alloc((unsigned)(oldlen + 1 - count));
2234 	if (newp == NULL)
2235 	    return FAIL;
2236 	mch_memmove(newp, oldp, (size_t)col);
2237     }
2238     mch_memmove(newp + col, oldp + col + count, (size_t)movelen);
2239     if (!was_alloced)
2240 	ml_replace(lnum, newp, FALSE);
2241 
2242     /* mark the buffer as changed and prepare for displaying */
2243     changed_bytes(lnum, curwin->w_cursor.col);
2244 
2245     return OK;
2246 }
2247 
2248 /*
2249  * Delete from cursor to end of line.
2250  * Caller must have prepared for undo.
2251  *
2252  * return FAIL for failure, OK otherwise
2253  */
2254     int
2255 truncate_line(fixpos)
2256     int		fixpos;	    /* if TRUE fix the cursor position when done */
2257 {
2258     char_u	*newp;
2259     linenr_T	lnum = curwin->w_cursor.lnum;
2260     colnr_T	col = curwin->w_cursor.col;
2261 
2262     if (col == 0)
2263 	newp = vim_strsave((char_u *)"");
2264     else
2265 	newp = vim_strnsave(ml_get(lnum), col);
2266 
2267     if (newp == NULL)
2268 	return FAIL;
2269 
2270     ml_replace(lnum, newp, FALSE);
2271 
2272     /* mark the buffer as changed and prepare for displaying */
2273     changed_bytes(lnum, curwin->w_cursor.col);
2274 
2275     /*
2276      * If "fixpos" is TRUE we don't want to end up positioned at the NUL.
2277      */
2278     if (fixpos && curwin->w_cursor.col > 0)
2279 	--curwin->w_cursor.col;
2280 
2281     return OK;
2282 }
2283 
2284 /*
2285  * Delete "nlines" lines at the cursor.
2286  * Saves the lines for undo first if "undo" is TRUE.
2287  */
2288     void
2289 del_lines(nlines, undo)
2290     long	nlines;		/* number of lines to delete */
2291     int		undo;		/* if TRUE, prepare for undo */
2292 {
2293     long	n;
2294 
2295     if (nlines <= 0)
2296 	return;
2297 
2298     /* save the deleted lines for undo */
2299     if (undo && u_savedel(curwin->w_cursor.lnum, nlines) == FAIL)
2300 	return;
2301 
2302     for (n = 0; n < nlines; )
2303     {
2304 	if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to delete */
2305 	    break;
2306 
2307 	ml_delete(curwin->w_cursor.lnum, TRUE);
2308 	++n;
2309 
2310 	/* If we delete the last line in the file, stop */
2311 	if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
2312 	    break;
2313     }
2314     /* adjust marks, mark the buffer as changed and prepare for displaying */
2315     deleted_lines_mark(curwin->w_cursor.lnum, n);
2316 
2317     curwin->w_cursor.col = 0;
2318     check_cursor_lnum();
2319 }
2320 
2321     int
2322 gchar_pos(pos)
2323     pos_T *pos;
2324 {
2325     char_u	*ptr = ml_get_pos(pos);
2326 
2327 #ifdef FEAT_MBYTE
2328     if (has_mbyte)
2329 	return (*mb_ptr2char)(ptr);
2330 #endif
2331     return (int)*ptr;
2332 }
2333 
2334     int
2335 gchar_cursor()
2336 {
2337 #ifdef FEAT_MBYTE
2338     if (has_mbyte)
2339 	return (*mb_ptr2char)(ml_get_cursor());
2340 #endif
2341     return (int)*ml_get_cursor();
2342 }
2343 
2344 /*
2345  * Write a character at the current cursor position.
2346  * It is directly written into the block.
2347  */
2348     void
2349 pchar_cursor(c)
2350     int c;
2351 {
2352     *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE)
2353 						  + curwin->w_cursor.col) = c;
2354 }
2355 
2356 #if 0 /* not used */
2357 /*
2358  * Put *pos at end of current buffer
2359  */
2360     void
2361 goto_endofbuf(pos)
2362     pos_T    *pos;
2363 {
2364     char_u  *p;
2365 
2366     pos->lnum = curbuf->b_ml.ml_line_count;
2367     pos->col = 0;
2368     p = ml_get(pos->lnum);
2369     while (*p++)
2370 	++pos->col;
2371 }
2372 #endif
2373 
2374 /*
2375  * When extra == 0: Return TRUE if the cursor is before or on the first
2376  *		    non-blank in the line.
2377  * When extra == 1: Return TRUE if the cursor is before the first non-blank in
2378  *		    the line.
2379  */
2380     int
2381 inindent(extra)
2382     int	    extra;
2383 {
2384     char_u	*ptr;
2385     colnr_T	col;
2386 
2387     for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col)
2388 	++ptr;
2389     if (col >= curwin->w_cursor.col + extra)
2390 	return TRUE;
2391     else
2392 	return FALSE;
2393 }
2394 
2395 /*
2396  * Skip to next part of an option argument: Skip space and comma.
2397  */
2398     char_u *
2399 skip_to_option_part(p)
2400     char_u  *p;
2401 {
2402     if (*p == ',')
2403 	++p;
2404     while (*p == ' ')
2405 	++p;
2406     return p;
2407 }
2408 
2409 /*
2410  * changed() is called when something in the current buffer is changed.
2411  *
2412  * Most often called through changed_bytes() and changed_lines(), which also
2413  * mark the area of the display to be redrawn.
2414  */
2415     void
2416 changed()
2417 {
2418 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
2419     /* The text of the preediting area is inserted, but this doesn't
2420      * mean a change of the buffer yet.  That is delayed until the
2421      * text is committed. (this means preedit becomes empty) */
2422     if (im_is_preediting() && !xim_changed_while_preediting)
2423 	return;
2424     xim_changed_while_preediting = FALSE;
2425 #endif
2426 
2427     if (!curbuf->b_changed)
2428     {
2429 	int	save_msg_scroll = msg_scroll;
2430 
2431 	change_warning(0);
2432 	/* Create a swap file if that is wanted.
2433 	 * Don't do this for "nofile" and "nowrite" buffer types. */
2434 	if (curbuf->b_may_swap
2435 #ifdef FEAT_QUICKFIX
2436 		&& !bt_dontwrite(curbuf)
2437 #endif
2438 		)
2439 	{
2440 	    ml_open_file(curbuf);
2441 
2442 	    /* The ml_open_file() can cause an ATTENTION message.
2443 	     * Wait two seconds, to make sure the user reads this unexpected
2444 	     * message.  Since we could be anywhere, call wait_return() now,
2445 	     * and don't let the emsg() set msg_scroll. */
2446 	    if (need_wait_return && emsg_silent == 0)
2447 	    {
2448 		out_flush();
2449 		ui_delay(2000L, TRUE);
2450 		wait_return(TRUE);
2451 		msg_scroll = save_msg_scroll;
2452 	    }
2453 	}
2454 	curbuf->b_changed = TRUE;
2455 	ml_setflags(curbuf);
2456 #ifdef FEAT_WINDOWS
2457 	check_status(curbuf);
2458 #endif
2459 #ifdef FEAT_TITLE
2460 	need_maketitle = TRUE;	    /* set window title later */
2461 #endif
2462     }
2463     ++curbuf->b_changedtick;
2464 }
2465 
2466 static void changedOneline __ARGS((buf_T *buf, linenr_T lnum));
2467 static void changed_lines_buf __ARGS((buf_T *buf, linenr_T lnum, linenr_T lnume, long xtra));
2468 static void changed_common __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra));
2469 
2470 /*
2471  * Changed bytes within a single line for the current buffer.
2472  * - marks the windows on this buffer to be redisplayed
2473  * - marks the buffer changed by calling changed()
2474  * - invalidates cached values
2475  */
2476     void
2477 changed_bytes(lnum, col)
2478     linenr_T	lnum;
2479     colnr_T	col;
2480 {
2481     changedOneline(curbuf, lnum);
2482     changed_common(lnum, col, lnum + 1, 0L);
2483 
2484 #ifdef FEAT_DIFF
2485     /* Diff highlighting in other diff windows may need to be updated too. */
2486     if (curwin->w_p_diff)
2487     {
2488 	win_T	    *wp;
2489 	linenr_T    wlnum;
2490 
2491 	for (wp = firstwin; wp != NULL; wp = wp->w_next)
2492 	    if (wp->w_p_diff && wp != curwin)
2493 	    {
2494 		redraw_win_later(wp, VALID);
2495 		wlnum = diff_lnum_win(lnum, wp);
2496 		if (wlnum > 0)
2497 		    changedOneline(wp->w_buffer, wlnum);
2498 	    }
2499     }
2500 #endif
2501 }
2502 
2503     static void
2504 changedOneline(buf, lnum)
2505     buf_T	*buf;
2506     linenr_T	lnum;
2507 {
2508     if (buf->b_mod_set)
2509     {
2510 	/* find the maximum area that must be redisplayed */
2511 	if (lnum < buf->b_mod_top)
2512 	    buf->b_mod_top = lnum;
2513 	else if (lnum >= buf->b_mod_bot)
2514 	    buf->b_mod_bot = lnum + 1;
2515     }
2516     else
2517     {
2518 	/* set the area that must be redisplayed to one line */
2519 	buf->b_mod_set = TRUE;
2520 	buf->b_mod_top = lnum;
2521 	buf->b_mod_bot = lnum + 1;
2522 	buf->b_mod_xlines = 0;
2523     }
2524 }
2525 
2526 /*
2527  * Appended "count" lines below line "lnum" in the current buffer.
2528  * Must be called AFTER the change and after mark_adjust().
2529  * Takes care of marking the buffer to be redrawn and sets the changed flag.
2530  */
2531     void
2532 appended_lines(lnum, count)
2533     linenr_T	lnum;
2534     long	count;
2535 {
2536     changed_lines(lnum + 1, 0, lnum + 1, count);
2537 }
2538 
2539 /*
2540  * Like appended_lines(), but adjust marks first.
2541  */
2542     void
2543 appended_lines_mark(lnum, count)
2544     linenr_T	lnum;
2545     long	count;
2546 {
2547     mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L);
2548     changed_lines(lnum + 1, 0, lnum + 1, count);
2549 }
2550 
2551 /*
2552  * Deleted "count" lines at line "lnum" in the current buffer.
2553  * Must be called AFTER the change and after mark_adjust().
2554  * Takes care of marking the buffer to be redrawn and sets the changed flag.
2555  */
2556     void
2557 deleted_lines(lnum, count)
2558     linenr_T	lnum;
2559     long	count;
2560 {
2561     changed_lines(lnum, 0, lnum + count, -count);
2562 }
2563 
2564 /*
2565  * Like deleted_lines(), but adjust marks first.
2566  */
2567     void
2568 deleted_lines_mark(lnum, count)
2569     linenr_T	lnum;
2570     long	count;
2571 {
2572     mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count);
2573     changed_lines(lnum, 0, lnum + count, -count);
2574 }
2575 
2576 /*
2577  * Changed lines for the current buffer.
2578  * Must be called AFTER the change and after mark_adjust().
2579  * - mark the buffer changed by calling changed()
2580  * - mark the windows on this buffer to be redisplayed
2581  * - invalidate cached values
2582  * "lnum" is the first line that needs displaying, "lnume" the first line
2583  * below the changed lines (BEFORE the change).
2584  * When only inserting lines, "lnum" and "lnume" are equal.
2585  * Takes care of calling changed() and updating b_mod_*.
2586  */
2587     void
2588 changed_lines(lnum, col, lnume, xtra)
2589     linenr_T	lnum;	    /* first line with change */
2590     colnr_T	col;	    /* column in first line with change */
2591     linenr_T	lnume;	    /* line below last changed line */
2592     long	xtra;	    /* number of extra lines (negative when deleting) */
2593 {
2594     changed_lines_buf(curbuf, lnum, lnume, xtra);
2595 
2596 #ifdef FEAT_DIFF
2597     if (xtra == 0 && curwin->w_p_diff)
2598     {
2599 	/* When the number of lines doesn't change then mark_adjust() isn't
2600 	 * called and other diff buffers still need to be marked for
2601 	 * displaying. */
2602 	win_T	    *wp;
2603 	linenr_T    wlnum;
2604 
2605 	for (wp = firstwin; wp != NULL; wp = wp->w_next)
2606 	    if (wp->w_p_diff && wp != curwin)
2607 	    {
2608 		redraw_win_later(wp, VALID);
2609 		wlnum = diff_lnum_win(lnum, wp);
2610 		if (wlnum > 0)
2611 		    changed_lines_buf(wp->w_buffer, wlnum,
2612 						    lnume - lnum + wlnum, 0L);
2613 	    }
2614     }
2615 #endif
2616 
2617     changed_common(lnum, col, lnume, xtra);
2618 }
2619 
2620     static void
2621 changed_lines_buf(buf, lnum, lnume, xtra)
2622     buf_T	*buf;
2623     linenr_T	lnum;	    /* first line with change */
2624     linenr_T	lnume;	    /* line below last changed line */
2625     long	xtra;	    /* number of extra lines (negative when deleting) */
2626 {
2627     if (buf->b_mod_set)
2628     {
2629 	/* find the maximum area that must be redisplayed */
2630 	if (lnum < buf->b_mod_top)
2631 	    buf->b_mod_top = lnum;
2632 	if (lnum < buf->b_mod_bot)
2633 	{
2634 	    /* adjust old bot position for xtra lines */
2635 	    buf->b_mod_bot += xtra;
2636 	    if (buf->b_mod_bot < lnum)
2637 		buf->b_mod_bot = lnum;
2638 	}
2639 	if (lnume + xtra > buf->b_mod_bot)
2640 	    buf->b_mod_bot = lnume + xtra;
2641 	buf->b_mod_xlines += xtra;
2642     }
2643     else
2644     {
2645 	/* set the area that must be redisplayed */
2646 	buf->b_mod_set = TRUE;
2647 	buf->b_mod_top = lnum;
2648 	buf->b_mod_bot = lnume + xtra;
2649 	buf->b_mod_xlines = xtra;
2650     }
2651 }
2652 
2653     static void
2654 changed_common(lnum, col, lnume, xtra)
2655     linenr_T	lnum;
2656     colnr_T	col;
2657     linenr_T	lnume;
2658     long	xtra;
2659 {
2660     win_T	*wp;
2661     int		i;
2662 #ifdef FEAT_JUMPLIST
2663     int		cols;
2664     pos_T	*p;
2665     int		add;
2666 #endif
2667 
2668     /* mark the buffer as modified */
2669     changed();
2670 
2671     /* set the '. mark */
2672     if (!cmdmod.keepjumps)
2673     {
2674 	curbuf->b_last_change.lnum = lnum;
2675 	curbuf->b_last_change.col = col;
2676 
2677 #ifdef FEAT_JUMPLIST
2678 	/* Create a new entry if a new undo-able change was started or we
2679 	 * don't have an entry yet. */
2680 	if (curbuf->b_new_change || curbuf->b_changelistlen == 0)
2681 	{
2682 	    if (curbuf->b_changelistlen == 0)
2683 		add = TRUE;
2684 	    else
2685 	    {
2686 		/* Don't create a new entry when the line number is the same
2687 		 * as the last one and the column is not too far away.  Avoids
2688 		 * creating many entries for typing "xxxxx". */
2689 		p = &curbuf->b_changelist[curbuf->b_changelistlen - 1];
2690 		if (p->lnum != lnum)
2691 		    add = TRUE;
2692 		else
2693 		{
2694 		    cols = comp_textwidth(FALSE);
2695 		    if (cols == 0)
2696 			cols = 79;
2697 		    add = (p->col + cols < col || col + cols < p->col);
2698 		}
2699 	    }
2700 	    if (add)
2701 	    {
2702 		/* This is the first of a new sequence of undo-able changes
2703 		 * and it's at some distance of the last change.  Use a new
2704 		 * position in the changelist. */
2705 		curbuf->b_new_change = FALSE;
2706 
2707 		if (curbuf->b_changelistlen == JUMPLISTSIZE)
2708 		{
2709 		    /* changelist is full: remove oldest entry */
2710 		    curbuf->b_changelistlen = JUMPLISTSIZE - 1;
2711 		    mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1,
2712 					  sizeof(pos_T) * (JUMPLISTSIZE - 1));
2713 		    FOR_ALL_WINDOWS(wp)
2714 		    {
2715 			/* Correct position in changelist for other windows on
2716 			 * this buffer. */
2717 			if (wp->w_buffer == curbuf && wp->w_changelistidx > 0)
2718 			    --wp->w_changelistidx;
2719 		    }
2720 		}
2721 		FOR_ALL_WINDOWS(wp)
2722 		{
2723 		    /* For other windows, if the position in the changelist is
2724 		     * at the end it stays at the end. */
2725 		    if (wp->w_buffer == curbuf
2726 			    && wp->w_changelistidx == curbuf->b_changelistlen)
2727 			++wp->w_changelistidx;
2728 		}
2729 		++curbuf->b_changelistlen;
2730 	    }
2731 	}
2732 	curbuf->b_changelist[curbuf->b_changelistlen - 1] =
2733 							curbuf->b_last_change;
2734 	/* The current window is always after the last change, so that "g,"
2735 	 * takes you back to it. */
2736 	curwin->w_changelistidx = curbuf->b_changelistlen;
2737 #endif
2738     }
2739 
2740     FOR_ALL_WINDOWS(wp)
2741     {
2742 	if (wp->w_buffer == curbuf)
2743 	{
2744 	    /* Mark this window to be redrawn later. */
2745 	    if (wp->w_redr_type < VALID)
2746 		wp->w_redr_type = VALID;
2747 
2748 	    /* Check if a change in the buffer has invalidated the cached
2749 	     * values for the cursor. */
2750 #ifdef FEAT_FOLDING
2751 	    /*
2752 	     * Update the folds for this window.  Can't postpone this, because
2753 	     * a following operator might work on the whole fold: ">>dd".
2754 	     */
2755 	    foldUpdate(wp, lnum, lnume + xtra - 1);
2756 
2757 	    /* The change may cause lines above or below the change to become
2758 	     * included in a fold.  Set lnum/lnume to the first/last line that
2759 	     * might be displayed differently.
2760 	     * Set w_cline_folded here as an efficient way to update it when
2761 	     * inserting lines just above a closed fold. */
2762 	    i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL);
2763 	    if (wp->w_cursor.lnum == lnum)
2764 		wp->w_cline_folded = i;
2765 	    i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL);
2766 	    if (wp->w_cursor.lnum == lnume)
2767 		wp->w_cline_folded = i;
2768 
2769 	    /* If the changed line is in a range of previously folded lines,
2770 	     * compare with the first line in that range. */
2771 	    if (wp->w_cursor.lnum <= lnum)
2772 	    {
2773 		i = find_wl_entry(wp, lnum);
2774 		if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum)
2775 		    changed_line_abv_curs_win(wp);
2776 	    }
2777 #endif
2778 
2779 	    if (wp->w_cursor.lnum > lnum)
2780 		changed_line_abv_curs_win(wp);
2781 	    else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col)
2782 		changed_cline_bef_curs_win(wp);
2783 	    if (wp->w_botline >= lnum)
2784 	    {
2785 		/* Assume that botline doesn't change (inserted lines make
2786 		 * other lines scroll down below botline). */
2787 		approximate_botline_win(wp);
2788 	    }
2789 
2790 	    /* Check if any w_lines[] entries have become invalid.
2791 	     * For entries below the change: Correct the lnums for
2792 	     * inserted/deleted lines.  Makes it possible to stop displaying
2793 	     * after the change. */
2794 	    for (i = 0; i < wp->w_lines_valid; ++i)
2795 		if (wp->w_lines[i].wl_valid)
2796 		{
2797 		    if (wp->w_lines[i].wl_lnum >= lnum)
2798 		    {
2799 			if (wp->w_lines[i].wl_lnum < lnume)
2800 			{
2801 			    /* line included in change */
2802 			    wp->w_lines[i].wl_valid = FALSE;
2803 			}
2804 			else if (xtra != 0)
2805 			{
2806 			    /* line below change */
2807 			    wp->w_lines[i].wl_lnum += xtra;
2808 #ifdef FEAT_FOLDING
2809 			    wp->w_lines[i].wl_lastlnum += xtra;
2810 #endif
2811 			}
2812 		    }
2813 #ifdef FEAT_FOLDING
2814 		    else if (wp->w_lines[i].wl_lastlnum >= lnum)
2815 		    {
2816 			/* change somewhere inside this range of folded lines,
2817 			 * may need to be redrawn */
2818 			wp->w_lines[i].wl_valid = FALSE;
2819 		    }
2820 #endif
2821 		}
2822 	}
2823     }
2824 
2825     /* Call update_screen() later, which checks out what needs to be redrawn,
2826      * since it notices b_mod_set and then uses b_mod_*. */
2827     if (must_redraw < VALID)
2828 	must_redraw = VALID;
2829 }
2830 
2831 /*
2832  * unchanged() is called when the changed flag must be reset for buffer 'buf'
2833  */
2834     void
2835 unchanged(buf, ff)
2836     buf_T	*buf;
2837     int		ff;	/* also reset 'fileformat' */
2838 {
2839     if (buf->b_changed || (ff && file_ff_differs(buf)))
2840     {
2841 	buf->b_changed = 0;
2842 	ml_setflags(buf);
2843 	if (ff)
2844 	    save_file_ff(buf);
2845 #ifdef FEAT_WINDOWS
2846 	check_status(buf);
2847 #endif
2848 #ifdef FEAT_TITLE
2849 	need_maketitle = TRUE;	    /* set window title later */
2850 #endif
2851     }
2852     ++buf->b_changedtick;
2853 #ifdef FEAT_NETBEANS_INTG
2854     netbeans_unmodified(buf);
2855 #endif
2856 }
2857 
2858 #if defined(FEAT_WINDOWS) || defined(PROTO)
2859 /*
2860  * check_status: called when the status bars for the buffer 'buf'
2861  *		 need to be updated
2862  */
2863     void
2864 check_status(buf)
2865     buf_T	*buf;
2866 {
2867     win_T	*wp;
2868 
2869     for (wp = firstwin; wp != NULL; wp = wp->w_next)
2870 	if (wp->w_buffer == buf && wp->w_status_height)
2871 	{
2872 	    wp->w_redr_status = TRUE;
2873 	    if (must_redraw < VALID)
2874 		must_redraw = VALID;
2875 	}
2876 }
2877 #endif
2878 
2879 /*
2880  * If the file is readonly, give a warning message with the first change.
2881  * Don't do this for autocommands.
2882  * Don't use emsg(), because it flushes the macro buffer.
2883  * If we have undone all changes b_changed will be FALSE, but "b_did_warn"
2884  * will be TRUE.
2885  */
2886     void
2887 change_warning(col)
2888     int	    col;		/* column for message; non-zero when in insert
2889 				   mode and 'showmode' is on */
2890 {
2891     if (curbuf->b_did_warn == FALSE
2892 	    && curbufIsChanged() == 0
2893 #ifdef FEAT_AUTOCMD
2894 	    && !autocmd_busy
2895 #endif
2896 	    && curbuf->b_p_ro)
2897     {
2898 #ifdef FEAT_AUTOCMD
2899 	apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf);
2900 	if (!curbuf->b_p_ro)
2901 	    return;
2902 #endif
2903 	/*
2904 	 * Do what msg() does, but with a column offset if the warning should
2905 	 * be after the mode message.
2906 	 */
2907 	msg_start();
2908 	if (msg_row == Rows - 1)
2909 	    msg_col = col;
2910 	msg_source(hl_attr(HLF_W));
2911 	MSG_PUTS_ATTR(_("W10: Warning: Changing a readonly file"),
2912 						   hl_attr(HLF_W) | MSG_HIST);
2913 	msg_clr_eos();
2914 	(void)msg_end();
2915 	if (msg_silent == 0 && !silent_mode)
2916 	{
2917 	    out_flush();
2918 	    ui_delay(1000L, TRUE); /* give the user time to think about it */
2919 	}
2920 	curbuf->b_did_warn = TRUE;
2921 	redraw_cmdline = FALSE;	/* don't redraw and erase the message */
2922 	if (msg_row < Rows - 1)
2923 	    showmode();
2924     }
2925 }
2926 
2927 /*
2928  * Ask for a reply from the user, a 'y' or a 'n'.
2929  * No other characters are accepted, the message is repeated until a valid
2930  * reply is entered or CTRL-C is hit.
2931  * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
2932  * from any buffers but directly from the user.
2933  *
2934  * return the 'y' or 'n'
2935  */
2936     int
2937 ask_yesno(str, direct)
2938     char_u  *str;
2939     int	    direct;
2940 {
2941     int	    r = ' ';
2942     int	    save_State = State;
2943 
2944     if (exiting)		/* put terminal in raw mode for this question */
2945 	settmode(TMODE_RAW);
2946     ++no_wait_return;
2947 #ifdef USE_ON_FLY_SCROLL
2948     dont_scroll = TRUE;		/* disallow scrolling here */
2949 #endif
2950     State = CONFIRM;		/* mouse behaves like with :confirm */
2951 #ifdef FEAT_MOUSE
2952     setmouse();			/* disables mouse for xterm */
2953 #endif
2954     ++no_mapping;
2955     ++allow_keys;		/* no mapping here, but recognize keys */
2956 
2957     while (r != 'y' && r != 'n')
2958     {
2959 	/* same highlighting as for wait_return */
2960 	smsg_attr(hl_attr(HLF_R), (char_u *)"%s (y/n)?", str);
2961 	if (direct)
2962 	    r = get_keystroke();
2963 	else
2964 	    r = safe_vgetc();
2965 	if (r == Ctrl_C || r == ESC)
2966 	    r = 'n';
2967 	msg_putchar(r);	    /* show what you typed */
2968 	out_flush();
2969     }
2970     --no_wait_return;
2971     State = save_State;
2972 #ifdef FEAT_MOUSE
2973     setmouse();
2974 #endif
2975     --no_mapping;
2976     --allow_keys;
2977 
2978     return r;
2979 }
2980 
2981 /*
2982  * Get a key stroke directly from the user.
2983  * Ignores mouse clicks and scrollbar events, except a click for the left
2984  * button (used at the more prompt).
2985  * Doesn't use vgetc(), because it syncs undo and eats mapped characters.
2986  * Disadvantage: typeahead is ignored.
2987  * Translates the interrupt character for unix to ESC.
2988  */
2989     int
2990 get_keystroke()
2991 {
2992 #define CBUFLEN 151
2993     char_u	buf[CBUFLEN];
2994     int		len = 0;
2995     int		n;
2996     int		save_mapped_ctrl_c = mapped_ctrl_c;
2997 
2998     mapped_ctrl_c = FALSE;	/* mappings are not used here */
2999     for (;;)
3000     {
3001 	cursor_on();
3002 	out_flush();
3003 
3004 	/* First time: blocking wait.  Second time: wait up to 100ms for a
3005 	 * terminal code to complete.  Leave some room for check_termcode() to
3006 	 * insert a key code into (max 5 chars plus NUL).  And
3007 	 * fix_input_buffer() can triple the number of bytes. */
3008 	n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3,
3009 						    len == 0 ? -1L : 100L, 0);
3010 	if (n > 0)
3011 	{
3012 	    /* Replace zero and CSI by a special key code. */
3013 	    n = fix_input_buffer(buf + len, n, FALSE);
3014 	    len += n;
3015 	}
3016 
3017 	/* incomplete termcode: get more characters */
3018 	if ((n = check_termcode(1, buf, len)) < 0)
3019 	    continue;
3020 	/* found a termcode: adjust length */
3021 	if (n > 0)
3022 	    len = n;
3023 	if (len == 0)	    /* nothing typed yet */
3024 	    continue;
3025 
3026 	/* Handle modifier and/or special key code. */
3027 	n = buf[0];
3028 	if (n == K_SPECIAL)
3029 	{
3030 	    n = TO_SPECIAL(buf[1], buf[2]);
3031 	    if (buf[1] == KS_MODIFIER
3032 		    || n == K_IGNORE
3033 #ifdef FEAT_MOUSE
3034 		    || n == K_LEFTMOUSE_NM
3035 		    || n == K_LEFTDRAG
3036 		    || n == K_LEFTRELEASE
3037 		    || n == K_LEFTRELEASE_NM
3038 		    || n == K_MIDDLEMOUSE
3039 		    || n == K_MIDDLEDRAG
3040 		    || n == K_MIDDLERELEASE
3041 		    || n == K_RIGHTMOUSE
3042 		    || n == K_RIGHTDRAG
3043 		    || n == K_RIGHTRELEASE
3044 		    || n == K_MOUSEDOWN
3045 		    || n == K_MOUSEUP
3046 		    || n == K_X1MOUSE
3047 		    || n == K_X1DRAG
3048 		    || n == K_X1RELEASE
3049 		    || n == K_X2MOUSE
3050 		    || n == K_X2DRAG
3051 		    || n == K_X2RELEASE
3052 # ifdef FEAT_GUI
3053 		    || n == K_VER_SCROLLBAR
3054 		    || n == K_HOR_SCROLLBAR
3055 # endif
3056 #endif
3057 	       )
3058 	    {
3059 		if (buf[1] == KS_MODIFIER)
3060 		    mod_mask = buf[2];
3061 		len -= 3;
3062 		if (len > 0)
3063 		    mch_memmove(buf, buf + 3, (size_t)len);
3064 		continue;
3065 	    }
3066 	}
3067 #ifdef FEAT_MBYTE
3068 	if (has_mbyte)
3069 	{
3070 	    if (MB_BYTE2LEN(n) > len)
3071 		continue;	/* more bytes to get */
3072 	    buf[len >= CBUFLEN ? CBUFLEN - 1 : len] = NUL;
3073 	    n = (*mb_ptr2char)(buf);
3074 	}
3075 #endif
3076 #ifdef UNIX
3077 	if (n == intr_char)
3078 	    n = ESC;
3079 #endif
3080 	break;
3081     }
3082 
3083     mapped_ctrl_c = save_mapped_ctrl_c;
3084     return n;
3085 }
3086 
3087 /*
3088  * Get a number from the user.
3089  * When "mouse_used" is not NULL allow using the mouse.
3090  */
3091     int
3092 get_number(colon, mouse_used)
3093     int	    colon;			/* allow colon to abort */
3094     int	    *mouse_used;
3095 {
3096     int	n = 0;
3097     int	c;
3098 
3099     if (mouse_used != NULL)
3100 	*mouse_used = FALSE;
3101 
3102     /* When not printing messages, the user won't know what to type, return a
3103      * zero (as if CR was hit). */
3104     if (msg_silent != 0)
3105 	return 0;
3106 
3107 #ifdef USE_ON_FLY_SCROLL
3108     dont_scroll = TRUE;		/* disallow scrolling here */
3109 #endif
3110     ++no_mapping;
3111     ++allow_keys;		/* no mapping here, but recognize keys */
3112     for (;;)
3113     {
3114 	windgoto(msg_row, msg_col);
3115 	c = safe_vgetc();
3116 	if (VIM_ISDIGIT(c))
3117 	{
3118 	    n = n * 10 + c - '0';
3119 	    msg_putchar(c);
3120 	}
3121 	else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H)
3122 	{
3123 	    n /= 10;
3124 	    MSG_PUTS("\b \b");
3125 	}
3126 #ifdef FEAT_MOUSE
3127 	else if (mouse_used != NULL && c == K_LEFTMOUSE)
3128 	{
3129 	    *mouse_used = TRUE;
3130 	    n = mouse_row + 1;
3131 	    break;
3132 	}
3133 #endif
3134 	else if (n == 0 && c == ':' && colon)
3135 	{
3136 	    stuffcharReadbuff(':');
3137 	    if (!exmode_active)
3138 		cmdline_row = msg_row;
3139 	    skip_redraw = TRUE;	    /* skip redraw once */
3140 	    do_redraw = FALSE;
3141 	    break;
3142 	}
3143 	else if (c == CAR || c == NL || c == Ctrl_C || c == ESC)
3144 	    break;
3145     }
3146     --no_mapping;
3147     --allow_keys;
3148     return n;
3149 }
3150 
3151 /*
3152  * Ask the user to enter a number.
3153  * When "mouse_used" is not NULL allow using the mouse and in that case return
3154  * the line number.
3155  */
3156     int
3157 prompt_for_number(mouse_used)
3158     int		*mouse_used;
3159 {
3160     int		i;
3161     int		save_cmdline_row;
3162     int		save_State;
3163 
3164     /* When using ":silent" assume that <CR> was entered. */
3165     if (mouse_used != NULL)
3166 	MSG_PUTS(_("Type number or click with mouse (<Enter> cancels): "));
3167     else
3168 	MSG_PUTS(_("Choice number (<Enter> cancels): "));
3169 
3170     /* Set the state such that text can be selected/copied/pasted. */
3171     save_cmdline_row = cmdline_row;
3172     cmdline_row = Rows - 1;
3173     save_State = State;
3174     if (mouse_used == NULL)
3175 	State = CMDLINE;
3176     else
3177 	State = NORMAL;
3178 
3179     i = get_number(TRUE, mouse_used);
3180     if (KeyTyped)
3181     {
3182 	/* don't call wait_return() now */
3183 	/* msg_putchar('\n'); */
3184 	cmdline_row = msg_row - 1;
3185 	need_wait_return = FALSE;
3186 	msg_didany = FALSE;
3187     }
3188     else
3189 	cmdline_row = save_cmdline_row;
3190     State = save_State;
3191 
3192     return i;
3193 }
3194 
3195     void
3196 msgmore(n)
3197     long n;
3198 {
3199     long pn;
3200 
3201     if (global_busy	    /* no messages now, wait until global is finished */
3202 	    || !messaging())  /* 'lazyredraw' set, don't do messages now */
3203 	return;
3204 
3205     /* We don't want to overwrite another important message, but do overwrite
3206      * a previous "more lines" or "fewer lines" message, so that "5dd" and
3207      * then "put" reports the last action. */
3208     if (keep_msg != NULL && !keep_msg_more)
3209 	return;
3210 
3211     if (n > 0)
3212 	pn = n;
3213     else
3214 	pn = -n;
3215 
3216     if (pn > p_report)
3217     {
3218 	if (pn == 1)
3219 	{
3220 	    if (n > 0)
3221 		STRCPY(msg_buf, _("1 more line"));
3222 	    else
3223 		STRCPY(msg_buf, _("1 line less"));
3224 	}
3225 	else
3226 	{
3227 	    if (n > 0)
3228 		sprintf((char *)msg_buf, _("%ld more lines"), pn);
3229 	    else
3230 		sprintf((char *)msg_buf, _("%ld fewer lines"), pn);
3231 	}
3232 	if (got_int)
3233 	    STRCAT(msg_buf, _(" (Interrupted)"));
3234 	if (msg(msg_buf))
3235 	{
3236 	    set_keep_msg(msg_buf);
3237 	    keep_msg_attr = 0;
3238 	    keep_msg_more = TRUE;
3239 	}
3240     }
3241 }
3242 
3243 /*
3244  * flush map and typeahead buffers and give a warning for an error
3245  */
3246     void
3247 beep_flush()
3248 {
3249     if (emsg_silent == 0)
3250     {
3251 	flush_buffers(FALSE);
3252 	vim_beep();
3253     }
3254 }
3255 
3256 /*
3257  * give a warning for an error
3258  */
3259     void
3260 vim_beep()
3261 {
3262     if (emsg_silent == 0)
3263     {
3264 	if (p_vb
3265 #ifdef FEAT_GUI
3266 		/* While the GUI is starting up the termcap is set for the GUI
3267 		 * but the output still goes to a terminal. */
3268 		&& !(gui.in_use && gui.starting)
3269 #endif
3270 		)
3271 	{
3272 	    out_str(T_VB);
3273 	}
3274 	else
3275 	{
3276 #ifdef MSDOS
3277 	    /*
3278 	     * The number of beeps outputted is reduced to avoid having to wait
3279 	     * for all the beeps to finish. This is only a problem on systems
3280 	     * where the beeps don't overlap.
3281 	     */
3282 	    if (beep_count == 0 || beep_count == 10)
3283 	    {
3284 		out_char(BELL);
3285 		beep_count = 1;
3286 	    }
3287 	    else
3288 		++beep_count;
3289 #else
3290 	    out_char(BELL);
3291 #endif
3292 	}
3293 
3294 	/* When 'verbose' is set and we are sourcing a script or executing a
3295 	 * function give the user a hint where the beep comes from. */
3296 	if (vim_strchr(p_debug, 'e') != NULL)
3297 	{
3298 	    msg_source(hl_attr(HLF_W));
3299 	    msg_attr((char_u *)_("Beep!"), hl_attr(HLF_W));
3300 	}
3301     }
3302 }
3303 
3304 /*
3305  * To get the "real" home directory:
3306  * - get value of $HOME
3307  * For Unix:
3308  *  - go to that directory
3309  *  - do mch_dirname() to get the real name of that directory.
3310  *  This also works with mounts and links.
3311  *  Don't do this for MS-DOS, it will change the "current dir" for a drive.
3312  */
3313 static char_u	*homedir = NULL;
3314 
3315     void
3316 init_homedir()
3317 {
3318     char_u  *var;
3319 
3320     /* In case we are called a second time (when 'encoding' changes). */
3321     vim_free(homedir);
3322     homedir = NULL;
3323 
3324 #ifdef VMS
3325     var = mch_getenv((char_u *)"SYS$LOGIN");
3326 #else
3327     var = mch_getenv((char_u *)"HOME");
3328 #endif
3329 
3330     if (var != NULL && *var == NUL)	/* empty is same as not set */
3331 	var = NULL;
3332 
3333 #ifdef WIN3264
3334     /*
3335      * Weird but true: $HOME may contain an indirect reference to another
3336      * variable, esp. "%USERPROFILE%".  Happens when $USERPROFILE isn't set
3337      * when $HOME is being set.
3338      */
3339     if (var != NULL && *var == '%')
3340     {
3341 	char_u	*p;
3342 	char_u	*exp;
3343 
3344 	p = vim_strchr(var + 1, '%');
3345 	if (p != NULL)
3346 	{
3347 	    vim_strncpy(NameBuff, var + 1, p - (var + 1));
3348 	    exp = mch_getenv(NameBuff);
3349 	    if (exp != NULL && *exp != NUL
3350 					&& STRLEN(exp) + STRLEN(p) < MAXPATHL)
3351 	    {
3352 		vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1);
3353 		var = NameBuff;
3354 		/* Also set $HOME, it's needed for _viminfo. */
3355 		vim_setenv((char_u *)"HOME", NameBuff);
3356 	    }
3357 	}
3358     }
3359 
3360     /*
3361      * Typically, $HOME is not defined on Windows, unless the user has
3362      * specifically defined it for Vim's sake.  However, on Windows NT
3363      * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
3364      * each user.  Try constructing $HOME from these.
3365      */
3366     if (var == NULL)
3367     {
3368 	char_u *homedrive, *homepath;
3369 
3370 	homedrive = mch_getenv((char_u *)"HOMEDRIVE");
3371 	homepath = mch_getenv((char_u *)"HOMEPATH");
3372 	if (homedrive != NULL && homepath != NULL
3373 			   && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
3374 	{
3375 	    sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
3376 	    if (NameBuff[0] != NUL)
3377 	    {
3378 		var = NameBuff;
3379 		/* Also set $HOME, it's needed for _viminfo. */
3380 		vim_setenv((char_u *)"HOME", NameBuff);
3381 	    }
3382 	}
3383     }
3384 
3385 # if defined(FEAT_MBYTE)
3386     if (enc_utf8 && var != NULL)
3387     {
3388 	int	len;
3389 	char_u  *pp;
3390 
3391 	/* Convert from active codepage to UTF-8.  Other conversions are
3392 	 * not done, because they would fail for non-ASCII characters. */
3393 	acp_to_enc(var, STRLEN(var), &pp, &len);
3394 	if (pp != NULL)
3395 	{
3396 	    homedir = pp;
3397 	    return;
3398 	}
3399     }
3400 # endif
3401 #endif
3402 
3403 #if defined(OS2) || defined(MSDOS) || defined(MSWIN)
3404     /*
3405      * Default home dir is C:/
3406      * Best assumption we can make in such a situation.
3407      */
3408     if (var == NULL)
3409 	var = "C:/";
3410 #endif
3411     if (var != NULL)
3412     {
3413 #ifdef UNIX
3414 	/*
3415 	 * Change to the directory and get the actual path.  This resolves
3416 	 * links.  Don't do it when we can't return.
3417 	 */
3418 	if (mch_dirname(NameBuff, MAXPATHL) == OK
3419 					  && mch_chdir((char *)NameBuff) == 0)
3420 	{
3421 	    if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK)
3422 		var = IObuff;
3423 	    if (mch_chdir((char *)NameBuff) != 0)
3424 		EMSG(_(e_prev_dir));
3425 	}
3426 #endif
3427 	homedir = vim_strsave(var);
3428     }
3429 }
3430 
3431 #if defined(EXITFREE) || defined(PROTO)
3432     void
3433 free_homedir()
3434 {
3435     vim_free(homedir);
3436 }
3437 #endif
3438 
3439 /*
3440  * Expand environment variable with path name.
3441  * "~/" is also expanded, using $HOME.	For Unix "~user/" is expanded.
3442  * Skips over "\ ", "\~" and "\$".
3443  * If anything fails no expansion is done and dst equals src.
3444  */
3445     void
3446 expand_env(src, dst, dstlen)
3447     char_u	*src;		/* input string e.g. "$HOME/vim.hlp" */
3448     char_u	*dst;		/* where to put the result */
3449     int		dstlen;		/* maximum length of the result */
3450 {
3451     expand_env_esc(src, dst, dstlen, FALSE, NULL);
3452 }
3453 
3454     void
3455 expand_env_esc(srcp, dst, dstlen, esc, startstr)
3456     char_u	*srcp;		/* input string e.g. "$HOME/vim.hlp" */
3457     char_u	*dst;		/* where to put the result */
3458     int		dstlen;		/* maximum length of the result */
3459     int		esc;		/* escape spaces in expanded variables */
3460     char_u	*startstr;	/* start again after this (can be NULL) */
3461 {
3462     char_u	*src;
3463     char_u	*tail;
3464     int		c;
3465     char_u	*var;
3466     int		copy_char;
3467     int		mustfree;	/* var was allocated, need to free it later */
3468     int		at_start = TRUE; /* at start of a name */
3469     int		startstr_len = 0;
3470 
3471     if (startstr != NULL)
3472 	startstr_len = STRLEN(startstr);
3473 
3474     src = skipwhite(srcp);
3475     --dstlen;		    /* leave one char space for "\," */
3476     while (*src && dstlen > 0)
3477     {
3478 	copy_char = TRUE;
3479 	if ((*src == '$'
3480 #ifdef VMS
3481 		    && at_start
3482 #endif
3483 	   )
3484 #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
3485 		|| *src == '%'
3486 #endif
3487 		|| (*src == '~' && at_start))
3488 	{
3489 	    mustfree = FALSE;
3490 
3491 	    /*
3492 	     * The variable name is copied into dst temporarily, because it may
3493 	     * be a string in read-only memory and a NUL needs to be appended.
3494 	     */
3495 	    if (*src != '~')				/* environment var */
3496 	    {
3497 		tail = src + 1;
3498 		var = dst;
3499 		c = dstlen - 1;
3500 
3501 #ifdef UNIX
3502 		/* Unix has ${var-name} type environment vars */
3503 		if (*tail == '{' && !vim_isIDc('{'))
3504 		{
3505 		    tail++;	/* ignore '{' */
3506 		    while (c-- > 0 && *tail && *tail != '}')
3507 			*var++ = *tail++;
3508 		}
3509 		else
3510 #endif
3511 		{
3512 		    while (c-- > 0 && *tail != NUL && ((vim_isIDc(*tail))
3513 #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
3514 			    || (*src == '%' && *tail != '%')
3515 #endif
3516 			    ))
3517 		    {
3518 #ifdef OS2		/* env vars only in uppercase */
3519 			*var++ = TOUPPER_LOC(*tail);
3520 			tail++;	    /* toupper() may be a macro! */
3521 #else
3522 			*var++ = *tail++;
3523 #endif
3524 		    }
3525 		}
3526 
3527 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX)
3528 # ifdef UNIX
3529 		if (src[1] == '{' && *tail != '}')
3530 # else
3531 		if (*src == '%' && *tail != '%')
3532 # endif
3533 		    var = NULL;
3534 		else
3535 		{
3536 # ifdef UNIX
3537 		    if (src[1] == '{')
3538 # else
3539 		    if (*src == '%')
3540 #endif
3541 			++tail;
3542 #endif
3543 		    *var = NUL;
3544 		    var = vim_getenv(dst, &mustfree);
3545 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX)
3546 		}
3547 #endif
3548 	    }
3549 							/* home directory */
3550 	    else if (  src[1] == NUL
3551 		    || vim_ispathsep(src[1])
3552 		    || vim_strchr((char_u *)" ,\t\n", src[1]) != NULL)
3553 	    {
3554 		var = homedir;
3555 		tail = src + 1;
3556 	    }
3557 	    else					/* user directory */
3558 	    {
3559 #if defined(UNIX) || (defined(VMS) && defined(USER_HOME))
3560 		/*
3561 		 * Copy ~user to dst[], so we can put a NUL after it.
3562 		 */
3563 		tail = src;
3564 		var = dst;
3565 		c = dstlen - 1;
3566 		while (	   c-- > 0
3567 			&& *tail
3568 			&& vim_isfilec(*tail)
3569 			&& !vim_ispathsep(*tail))
3570 		    *var++ = *tail++;
3571 		*var = NUL;
3572 # ifdef UNIX
3573 		/*
3574 		 * If the system supports getpwnam(), use it.
3575 		 * Otherwise, or if getpwnam() fails, the shell is used to
3576 		 * expand ~user.  This is slower and may fail if the shell
3577 		 * does not support ~user (old versions of /bin/sh).
3578 		 */
3579 #  if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
3580 		{
3581 		    struct passwd *pw;
3582 
3583 		    pw = getpwnam((char *)dst + 1);
3584 		    if (pw != NULL)
3585 			var = (char_u *)pw->pw_dir;
3586 		    else
3587 			var = NULL;
3588 		}
3589 		if (var == NULL)
3590 #  endif
3591 		{
3592 		    expand_T	xpc;
3593 
3594 		    ExpandInit(&xpc);
3595 		    xpc.xp_context = EXPAND_FILES;
3596 		    var = ExpandOne(&xpc, dst, NULL,
3597 				WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE);
3598 		    ExpandCleanup(&xpc);
3599 		    mustfree = TRUE;
3600 		}
3601 
3602 # else	/* !UNIX, thus VMS */
3603 		/*
3604 		 * USER_HOME is a comma-separated list of
3605 		 * directories to search for the user account in.
3606 		 */
3607 		{
3608 		    char_u	test[MAXPATHL], paths[MAXPATHL];
3609 		    char_u	*path, *next_path, *ptr;
3610 		    struct stat	st;
3611 
3612 		    STRCPY(paths, USER_HOME);
3613 		    next_path = paths;
3614 		    while (*next_path)
3615 		    {
3616 			for (path = next_path; *next_path && *next_path != ',';
3617 				next_path++);
3618 			if (*next_path)
3619 			    *next_path++ = NUL;
3620 			STRCPY(test, path);
3621 			STRCAT(test, "/");
3622 			STRCAT(test, dst + 1);
3623 			if (mch_stat(test, &st) == 0)
3624 			{
3625 			    var = alloc(STRLEN(test) + 1);
3626 			    STRCPY(var, test);
3627 			    mustfree = TRUE;
3628 			    break;
3629 			}
3630 		    }
3631 		}
3632 # endif /* UNIX */
3633 #else
3634 		/* cannot expand user's home directory, so don't try */
3635 		var = NULL;
3636 		tail = (char_u *)"";	/* for gcc */
3637 #endif /* UNIX || VMS */
3638 	    }
3639 
3640 #ifdef BACKSLASH_IN_FILENAME
3641 	    /* If 'shellslash' is set change backslashes to forward slashes.
3642 	     * Can't use slash_adjust(), p_ssl may be set temporarily. */
3643 	    if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL)
3644 	    {
3645 		char_u	*p = vim_strsave(var);
3646 
3647 		if (p != NULL)
3648 		{
3649 		    if (mustfree)
3650 			vim_free(var);
3651 		    var = p;
3652 		    mustfree = TRUE;
3653 		    forward_slash(var);
3654 		}
3655 	    }
3656 #endif
3657 
3658 	    /* If "var" contains white space, escape it with a backslash.
3659 	     * Required for ":e ~/tt" when $HOME includes a space. */
3660 	    if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL)
3661 	    {
3662 		char_u	*p = vim_strsave_escaped(var, (char_u *)" \t");
3663 
3664 		if (p != NULL)
3665 		{
3666 		    if (mustfree)
3667 			vim_free(var);
3668 		    var = p;
3669 		    mustfree = TRUE;
3670 		}
3671 	    }
3672 
3673 	    if (var != NULL && *var != NUL
3674 		    && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
3675 	    {
3676 		STRCPY(dst, var);
3677 		dstlen -= (int)STRLEN(var);
3678 		c = STRLEN(var);
3679 		/* if var[] ends in a path separator and tail[] starts
3680 		 * with it, skip a character */
3681 		if (*var != NUL && after_pathsep(dst, dst + c)
3682 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
3683 			&& dst[-1] != ':'
3684 #endif
3685 			&& vim_ispathsep(*tail))
3686 		    ++tail;
3687 		dst += c;
3688 		src = tail;
3689 		copy_char = FALSE;
3690 	    }
3691 	    if (mustfree)
3692 		vim_free(var);
3693 	}
3694 
3695 	if (copy_char)	    /* copy at least one char */
3696 	{
3697 	    /*
3698 	     * Recogize the start of a new name, for '~'.
3699 	     */
3700 	    at_start = FALSE;
3701 	    if (src[0] == '\\' && src[1] != NUL)
3702 	    {
3703 		*dst++ = *src++;
3704 		--dstlen;
3705 	    }
3706 	    else if (src[0] == ' ' || src[0] == ',')
3707 		at_start = TRUE;
3708 	    *dst++ = *src++;
3709 	    --dstlen;
3710 
3711 	    if (startstr != NULL && src - startstr_len >= srcp
3712 		    && STRNCMP(src - startstr_len, startstr, startstr_len) == 0)
3713 		at_start = TRUE;
3714 	}
3715     }
3716     *dst = NUL;
3717 }
3718 
3719 /*
3720  * Vim's version of getenv().
3721  * Special handling of $HOME, $VIM and $VIMRUNTIME.
3722  * Also does ACP to 'enc' conversion for Win32.
3723  */
3724     char_u *
3725 vim_getenv(name, mustfree)
3726     char_u	*name;
3727     int		*mustfree;	/* set to TRUE when returned is allocated */
3728 {
3729     char_u	*p;
3730     char_u	*pend;
3731     int		vimruntime;
3732 
3733 #if defined(OS2) || defined(MSDOS) || defined(MSWIN)
3734     /* use "C:/" when $HOME is not set */
3735     if (STRCMP(name, "HOME") == 0)
3736 	return homedir;
3737 #endif
3738 
3739     p = mch_getenv(name);
3740     if (p != NULL && *p == NUL)	    /* empty is the same as not set */
3741 	p = NULL;
3742 
3743     if (p != NULL)
3744     {
3745 #if defined(FEAT_MBYTE) && defined(WIN3264)
3746 	if (enc_utf8)
3747 	{
3748 	    int	    len;
3749 	    char_u  *pp;
3750 
3751 	    /* Convert from active codepage to UTF-8.  Other conversions are
3752 	     * not done, because they would fail for non-ASCII characters. */
3753 	    acp_to_enc(p, STRLEN(p), &pp, &len);
3754 	    if (pp != NULL)
3755 	    {
3756 		p = pp;
3757 		*mustfree = TRUE;
3758 	    }
3759 	}
3760 #endif
3761 	return p;
3762     }
3763 
3764     vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
3765     if (!vimruntime && STRCMP(name, "VIM") != 0)
3766 	return NULL;
3767 
3768     /*
3769      * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM.
3770      * Don't do this when default_vimruntime_dir is non-empty.
3771      */
3772     if (vimruntime
3773 #ifdef HAVE_PATHDEF
3774 	    && *default_vimruntime_dir == NUL
3775 #endif
3776        )
3777     {
3778 	p = mch_getenv((char_u *)"VIM");
3779 	if (p != NULL && *p == NUL)	    /* empty is the same as not set */
3780 	    p = NULL;
3781 	if (p != NULL)
3782 	{
3783 	    p = vim_version_dir(p);
3784 	    if (p != NULL)
3785 		*mustfree = TRUE;
3786 	    else
3787 		p = mch_getenv((char_u *)"VIM");
3788 
3789 #if defined(FEAT_MBYTE) && defined(WIN3264)
3790 	    if (enc_utf8)
3791 	    {
3792 		int	len;
3793 		char_u  *pp;
3794 
3795 		/* Convert from active codepage to UTF-8.  Other conversions
3796 		 * are not done, because they would fail for non-ASCII
3797 		 * characters. */
3798 		acp_to_enc(p, STRLEN(p), &pp, &len);
3799 		if (pp != NULL)
3800 		{
3801 		    if (mustfree)
3802 			vim_free(p);
3803 		    p = pp;
3804 		    *mustfree = TRUE;
3805 		}
3806 	    }
3807 #endif
3808 	}
3809     }
3810 
3811     /*
3812      * When expanding $VIM or $VIMRUNTIME fails, try using:
3813      * - the directory name from 'helpfile' (unless it contains '$')
3814      * - the executable name from argv[0]
3815      */
3816     if (p == NULL)
3817     {
3818 	if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL)
3819 	    p = p_hf;
3820 #ifdef USE_EXE_NAME
3821 	/*
3822 	 * Use the name of the executable, obtained from argv[0].
3823 	 */
3824 	else
3825 	    p = exe_name;
3826 #endif
3827 	if (p != NULL)
3828 	{
3829 	    /* remove the file name */
3830 	    pend = gettail(p);
3831 
3832 	    /* remove "doc/" from 'helpfile', if present */
3833 	    if (p == p_hf)
3834 		pend = remove_tail(p, pend, (char_u *)"doc");
3835 
3836 #ifdef USE_EXE_NAME
3837 # ifdef MACOS_X
3838 	    /* remove "build/..." from exe_name, if present */
3839 	    if (p == exe_name)
3840 	    {
3841 		char_u	*pend1;
3842 		char_u  *pend2;
3843 
3844 		pend1 = remove_tail(p, pend, (char_u *)"Contents/MacOS");
3845 		pend2 = remove_tail_with_ext(p, pend1, (char_u *)".app");
3846 		pend = remove_tail(p, pend2, (char_u *)"build");
3847 		/* When runnig from project builder get rid of the
3848 		 * build/???.app, otherwise keep the ???.app */
3849 		if (pend2 == pend)
3850 		    pend = pend1;
3851 	    }
3852 # endif
3853 	    /* remove "src/" from exe_name, if present */
3854 	    if (p == exe_name)
3855 		pend = remove_tail(p, pend, (char_u *)"src");
3856 #endif
3857 
3858 	    /* for $VIM, remove "runtime/" or "vim54/", if present */
3859 	    if (!vimruntime)
3860 	    {
3861 		pend = remove_tail(p, pend, (char_u *)RUNTIME_DIRNAME);
3862 		pend = remove_tail(p, pend, (char_u *)VIM_VERSION_NODOT);
3863 	    }
3864 
3865 	    /* remove trailing path separator */
3866 #ifndef MACOS_CLASSIC
3867 	    /* With MacOS path (with  colons) the final colon is required */
3868 	    /* to avoid confusion between absoulute and relative path */
3869 	    if (pend > p && after_pathsep(p, pend))
3870 		--pend;
3871 #endif
3872 
3873 	    /* check that the result is a directory name */
3874 	    p = vim_strnsave(p, (int)(pend - p));
3875 
3876 	    if (p != NULL && !mch_isdir(p))
3877 	    {
3878 		vim_free(p);
3879 		p = NULL;
3880 	    }
3881 	    else
3882 	    {
3883 #ifdef USE_EXE_NAME
3884 		/* may add "/vim54" or "/runtime" if it exists */
3885 		if (vimruntime && (pend = vim_version_dir(p)) != NULL)
3886 		{
3887 		    vim_free(p);
3888 		    p = pend;
3889 		}
3890 #endif
3891 		*mustfree = TRUE;
3892 	    }
3893 	}
3894     }
3895 
3896 #ifdef HAVE_PATHDEF
3897     /* When there is a pathdef.c file we can use default_vim_dir and
3898      * default_vimruntime_dir */
3899     if (p == NULL)
3900     {
3901 	/* Only use default_vimruntime_dir when it is not empty */
3902 	if (vimruntime && *default_vimruntime_dir != NUL)
3903 	{
3904 	    p = default_vimruntime_dir;
3905 	    *mustfree = FALSE;
3906 	}
3907 	else if (*default_vim_dir != NUL)
3908 	{
3909 	    if (vimruntime && (p = vim_version_dir(default_vim_dir)) != NULL)
3910 		*mustfree = TRUE;
3911 	    else
3912 	    {
3913 		p = default_vim_dir;
3914 		*mustfree = FALSE;
3915 	    }
3916 	}
3917     }
3918 #endif
3919 
3920     /*
3921      * Set the environment variable, so that the new value can be found fast
3922      * next time, and others can also use it (e.g. Perl).
3923      */
3924     if (p != NULL)
3925     {
3926 	if (vimruntime)
3927 	{
3928 	    vim_setenv((char_u *)"VIMRUNTIME", p);
3929 	    didset_vimruntime = TRUE;
3930 #ifdef FEAT_GETTEXT
3931 	    {
3932 		char_u	*buf = concat_str(p, (char_u *)"/lang");
3933 
3934 		if (buf != NULL)
3935 		{
3936 		    bindtextdomain(VIMPACKAGE, (char *)buf);
3937 		    vim_free(buf);
3938 		}
3939 	    }
3940 #endif
3941 	}
3942 	else
3943 	{
3944 	    vim_setenv((char_u *)"VIM", p);
3945 	    didset_vim = TRUE;
3946 	}
3947     }
3948     return p;
3949 }
3950 
3951 /*
3952  * Check if the directory "vimdir/<version>" or "vimdir/runtime" exists.
3953  * Return NULL if not, return its name in allocated memory otherwise.
3954  */
3955     static char_u *
3956 vim_version_dir(vimdir)
3957     char_u	*vimdir;
3958 {
3959     char_u	*p;
3960 
3961     if (vimdir == NULL || *vimdir == NUL)
3962 	return NULL;
3963     p = concat_fnames(vimdir, (char_u *)VIM_VERSION_NODOT, TRUE);
3964     if (p != NULL && mch_isdir(p))
3965 	return p;
3966     vim_free(p);
3967     p = concat_fnames(vimdir, (char_u *)RUNTIME_DIRNAME, TRUE);
3968     if (p != NULL && mch_isdir(p))
3969 	return p;
3970     vim_free(p);
3971     return NULL;
3972 }
3973 
3974 /*
3975  * If the string between "p" and "pend" ends in "name/", return "pend" minus
3976  * the length of "name/".  Otherwise return "pend".
3977  */
3978     static char_u *
3979 remove_tail(p, pend, name)
3980     char_u	*p;
3981     char_u	*pend;
3982     char_u	*name;
3983 {
3984     int		len = (int)STRLEN(name) + 1;
3985     char_u	*newend = pend - len;
3986 
3987     if (newend >= p
3988 	    && fnamencmp(newend, name, len - 1) == 0
3989 	    && (newend == p || after_pathsep(p, newend)))
3990 	return newend;
3991     return pend;
3992 }
3993 
3994 #if defined(USE_EXE_NAME) && defined(MACOS_X)
3995 /*
3996  * If the string between "p" and "pend" ends in "???.ext/", return "pend"
3997  * minus the length of "???.ext/".  Otherwise return "pend".
3998  */
3999     static char_u *
4000 remove_tail_with_ext(p, pend, ext)
4001     char_u	*p;
4002     char_u	*pend;
4003     char_u	*ext;
4004 {
4005     int		len = (int)STRLEN(ext) + 1;
4006     char_u	*newend = pend - len;
4007 
4008     if (newend >= p && fnamencmp(newend, ext, len - 1) == 0)
4009 	while (newend > p && !after_pathsep(p, newend))
4010 	    mb_ptr_back(p, newend);
4011     if (newend == p || after_pathsep(p, newend))
4012 	return newend;
4013     return pend;
4014 }
4015 #endif
4016 
4017 /*
4018  * Call expand_env() and store the result in an allocated string.
4019  * This is not very memory efficient, this expects the result to be freed
4020  * again soon.
4021  */
4022     char_u *
4023 expand_env_save(src)
4024     char_u	*src;
4025 {
4026     char_u	*p;
4027 
4028     p = alloc(MAXPATHL);
4029     if (p != NULL)
4030 	expand_env(src, p, MAXPATHL);
4031     return p;
4032 }
4033 
4034 /*
4035  * Our portable version of setenv.
4036  */
4037     void
4038 vim_setenv(name, val)
4039     char_u	*name;
4040     char_u	*val;
4041 {
4042 #ifdef HAVE_SETENV
4043     mch_setenv((char *)name, (char *)val, 1);
4044 #else
4045     char_u	*envbuf;
4046 
4047     /*
4048      * Putenv does not copy the string, it has to remain
4049      * valid.  The allocated memory will never be freed.
4050      */
4051     envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2));
4052     if (envbuf != NULL)
4053     {
4054 	sprintf((char *)envbuf, "%s=%s", name, val);
4055 	putenv((char *)envbuf);
4056     }
4057 #endif
4058 }
4059 
4060 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4061 /*
4062  * Function given to ExpandGeneric() to obtain an environment variable name.
4063  */
4064 /*ARGSUSED*/
4065     char_u *
4066 get_env_name(xp, idx)
4067     expand_T	*xp;
4068     int		idx;
4069 {
4070 # if defined(AMIGA) || defined(__MRC__) || defined(__SC__)
4071     /*
4072      * No environ[] on the Amiga and on the Mac (using MPW).
4073      */
4074     return NULL;
4075 # else
4076 # ifndef __WIN32__
4077     /* Borland C++ 5.2 has this in a header file. */
4078     extern char		**environ;
4079 # endif
4080 # define ENVNAMELEN 100
4081     static char_u	name[ENVNAMELEN];
4082     char_u		*str;
4083     int			n;
4084 
4085     str = (char_u *)environ[idx];
4086     if (str == NULL)
4087 	return NULL;
4088 
4089     for (n = 0; n < ENVNAMELEN - 1; ++n)
4090     {
4091 	if (str[n] == '=' || str[n] == NUL)
4092 	    break;
4093 	name[n] = str[n];
4094     }
4095     name[n] = NUL;
4096     return name;
4097 # endif
4098 }
4099 #endif
4100 
4101 /*
4102  * Replace home directory by "~" in each space or comma separated file name in
4103  * 'src'.
4104  * If anything fails (except when out of space) dst equals src.
4105  */
4106     void
4107 home_replace(buf, src, dst, dstlen, one)
4108     buf_T	*buf;	/* when not NULL, check for help files */
4109     char_u	*src;	/* input file name */
4110     char_u	*dst;	/* where to put the result */
4111     int		dstlen;	/* maximum length of the result */
4112     int		one;	/* if TRUE, only replace one file name, include
4113 			   spaces and commas in the file name. */
4114 {
4115     size_t	dirlen = 0, envlen = 0;
4116     size_t	len;
4117     char_u	*homedir_env;
4118     char_u	*p;
4119 
4120     if (src == NULL)
4121     {
4122 	*dst = NUL;
4123 	return;
4124     }
4125 
4126     /*
4127      * If the file is a help file, remove the path completely.
4128      */
4129     if (buf != NULL && buf->b_help)
4130     {
4131 	STRCPY(dst, gettail(src));
4132 	return;
4133     }
4134 
4135     /*
4136      * We check both the value of the $HOME environment variable and the
4137      * "real" home directory.
4138      */
4139     if (homedir != NULL)
4140 	dirlen = STRLEN(homedir);
4141 
4142 #ifdef VMS
4143     homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
4144 #else
4145     homedir_env = mch_getenv((char_u *)"HOME");
4146 #endif
4147 
4148     if (homedir_env != NULL && *homedir_env == NUL)
4149 	homedir_env = NULL;
4150     if (homedir_env != NULL)
4151 	envlen = STRLEN(homedir_env);
4152 
4153     if (!one)
4154 	src = skipwhite(src);
4155     while (*src && dstlen > 0)
4156     {
4157 	/*
4158 	 * Here we are at the beginning of a file name.
4159 	 * First, check to see if the beginning of the file name matches
4160 	 * $HOME or the "real" home directory. Check that there is a '/'
4161 	 * after the match (so that if e.g. the file is "/home/pieter/bla",
4162 	 * and the home directory is "/home/piet", the file does not end up
4163 	 * as "~er/bla" (which would seem to indicate the file "bla" in user
4164 	 * er's home directory)).
4165 	 */
4166 	p = homedir;
4167 	len = dirlen;
4168 	for (;;)
4169 	{
4170 	    if (   len
4171 		&& fnamencmp(src, p, len) == 0
4172 		&& (vim_ispathsep(src[len])
4173 		    || (!one && (src[len] == ',' || src[len] == ' '))
4174 		    || src[len] == NUL))
4175 	    {
4176 		src += len;
4177 		if (--dstlen > 0)
4178 		    *dst++ = '~';
4179 
4180 		/*
4181 		 * If it's just the home directory, add  "/".
4182 		 */
4183 		if (!vim_ispathsep(src[0]) && --dstlen > 0)
4184 		    *dst++ = '/';
4185 		break;
4186 	    }
4187 	    if (p == homedir_env)
4188 		break;
4189 	    p = homedir_env;
4190 	    len = envlen;
4191 	}
4192 
4193 	/* if (!one) skip to separator: space or comma */
4194 	while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
4195 	    *dst++ = *src++;
4196 	/* skip separator */
4197 	while ((*src == ' ' || *src == ',') && --dstlen > 0)
4198 	    *dst++ = *src++;
4199     }
4200     /* if (dstlen == 0) out of space, what to do??? */
4201 
4202     *dst = NUL;
4203 }
4204 
4205 /*
4206  * Like home_replace, store the replaced string in allocated memory.
4207  * When something fails, NULL is returned.
4208  */
4209     char_u  *
4210 home_replace_save(buf, src)
4211     buf_T	*buf;	/* when not NULL, check for help files */
4212     char_u	*src;	/* input file name */
4213 {
4214     char_u	*dst;
4215     unsigned	len;
4216 
4217     len = 3;			/* space for "~/" and trailing NUL */
4218     if (src != NULL)		/* just in case */
4219 	len += (unsigned)STRLEN(src);
4220     dst = alloc(len);
4221     if (dst != NULL)
4222 	home_replace(buf, src, dst, len, TRUE);
4223     return dst;
4224 }
4225 
4226 /*
4227  * Compare two file names and return:
4228  * FPC_SAME   if they both exist and are the same file.
4229  * FPC_SAMEX  if they both don't exist and have the same file name.
4230  * FPC_DIFF   if they both exist and are different files.
4231  * FPC_NOTX   if they both don't exist.
4232  * FPC_DIFFX  if one of them doesn't exist.
4233  * For the first name environment variables are expanded
4234  */
4235     int
4236 fullpathcmp(s1, s2, checkname)
4237     char_u *s1, *s2;
4238     int	    checkname;		/* when both don't exist, check file names */
4239 {
4240 #ifdef UNIX
4241     char_u	    exp1[MAXPATHL];
4242     char_u	    full1[MAXPATHL];
4243     char_u	    full2[MAXPATHL];
4244     struct stat	    st1, st2;
4245     int		    r1, r2;
4246 
4247     expand_env(s1, exp1, MAXPATHL);
4248     r1 = mch_stat((char *)exp1, &st1);
4249     r2 = mch_stat((char *)s2, &st2);
4250     if (r1 != 0 && r2 != 0)
4251     {
4252 	/* if mch_stat() doesn't work, may compare the names */
4253 	if (checkname)
4254 	{
4255 	    if (fnamecmp(exp1, s2) == 0)
4256 		return FPC_SAMEX;
4257 	    r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
4258 	    r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
4259 	    if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
4260 		return FPC_SAMEX;
4261 	}
4262 	return FPC_NOTX;
4263     }
4264     if (r1 != 0 || r2 != 0)
4265 	return FPC_DIFFX;
4266     if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
4267 	return FPC_SAME;
4268     return FPC_DIFF;
4269 #else
4270     char_u  *exp1;		/* expanded s1 */
4271     char_u  *full1;		/* full path of s1 */
4272     char_u  *full2;		/* full path of s2 */
4273     int	    retval = FPC_DIFF;
4274     int	    r1, r2;
4275 
4276     /* allocate one buffer to store three paths (alloc()/free() is slow!) */
4277     if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
4278     {
4279 	full1 = exp1 + MAXPATHL;
4280 	full2 = full1 + MAXPATHL;
4281 
4282 	expand_env(s1, exp1, MAXPATHL);
4283 	r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
4284 	r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
4285 
4286 	/* If vim_FullName() fails, the file probably doesn't exist. */
4287 	if (r1 != OK && r2 != OK)
4288 	{
4289 	    if (checkname && fnamecmp(exp1, s2) == 0)
4290 		retval = FPC_SAMEX;
4291 	    else
4292 		retval = FPC_NOTX;
4293 	}
4294 	else if (r1 != OK || r2 != OK)
4295 	    retval = FPC_DIFFX;
4296 	else if (fnamecmp(full1, full2))
4297 	    retval = FPC_DIFF;
4298 	else
4299 	    retval = FPC_SAME;
4300 	vim_free(exp1);
4301     }
4302     return retval;
4303 #endif
4304 }
4305 
4306 /*
4307  * Get the tail of a path: the file name.
4308  * Fail safe: never returns NULL.
4309  */
4310     char_u *
4311 gettail(fname)
4312     char_u *fname;
4313 {
4314     char_u  *p1, *p2;
4315 
4316     if (fname == NULL)
4317 	return (char_u *)"";
4318     for (p1 = p2 = fname; *p2; )	/* find last part of path */
4319     {
4320 	if (vim_ispathsep(*p2))
4321 	    p1 = p2 + 1;
4322 	mb_ptr_adv(p2);
4323     }
4324     return p1;
4325 }
4326 
4327 /*
4328  * Get pointer to tail of "fname", including path separators.  Putting a NUL
4329  * here leaves the directory name.  Takes care of "c:/" and "//".
4330  * Always returns a valid pointer.
4331  */
4332     char_u *
4333 gettail_sep(fname)
4334     char_u	*fname;
4335 {
4336     char_u	*p;
4337     char_u	*t;
4338 
4339     p = get_past_head(fname);	/* don't remove the '/' from "c:/file" */
4340     t = gettail(fname);
4341     while (t > p && after_pathsep(fname, t))
4342 	--t;
4343 #ifdef VMS
4344     /* path separator is part of the path */
4345     ++t;
4346 #endif
4347     return t;
4348 }
4349 
4350 /*
4351  * get the next path component (just after the next path separator).
4352  */
4353     char_u *
4354 getnextcomp(fname)
4355     char_u *fname;
4356 {
4357     while (*fname && !vim_ispathsep(*fname))
4358 	mb_ptr_adv(fname);
4359     if (*fname)
4360 	++fname;
4361     return fname;
4362 }
4363 
4364 /*
4365  * Get a pointer to one character past the head of a path name.
4366  * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
4367  * If there is no head, path is returned.
4368  */
4369     char_u *
4370 get_past_head(path)
4371     char_u  *path;
4372 {
4373     char_u  *retval;
4374 
4375 #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
4376     /* may skip "c:" */
4377     if (isalpha(path[0]) && path[1] == ':')
4378 	retval = path + 2;
4379     else
4380 	retval = path;
4381 #else
4382 # if defined(AMIGA)
4383     /* may skip "label:" */
4384     retval = vim_strchr(path, ':');
4385     if (retval == NULL)
4386 	retval = path;
4387 # else	/* Unix */
4388     retval = path;
4389 # endif
4390 #endif
4391 
4392     while (vim_ispathsep(*retval))
4393 	++retval;
4394 
4395     return retval;
4396 }
4397 
4398 /*
4399  * return TRUE if 'c' is a path separator.
4400  */
4401     int
4402 vim_ispathsep(c)
4403     int c;
4404 {
4405 #ifdef RISCOS
4406     return (c == '.' || c == ':');
4407 #else
4408 # ifdef UNIX
4409     return (c == '/');	    /* UNIX has ':' inside file names */
4410 # else
4411 #  ifdef BACKSLASH_IN_FILENAME
4412     return (c == ':' || c == '/' || c == '\\');
4413 #  else
4414 #   ifdef VMS
4415     /* server"user passwd"::device:[full.path.name]fname.extension;version" */
4416     return (c == ':' || c == '[' || c == ']' || c == '/'
4417 	    || c == '<' || c == '>' || c == '"' );
4418 #   else
4419 #    ifdef COLON_AS_PATHSEP
4420     return (c == ':');
4421 #    else		/* Amiga */
4422     return (c == ':' || c == '/');
4423 #    endif
4424 #   endif /* VMS */
4425 #  endif
4426 # endif
4427 #endif /* RISC OS */
4428 }
4429 
4430 #if defined(FEAT_SEARCHPATH) || defined(PROTO)
4431 /*
4432  * return TRUE if 'c' is a path list separator.
4433  */
4434     int
4435 vim_ispathlistsep(c)
4436     int c;
4437 {
4438 #ifdef UNIX
4439     return (c == ':');
4440 #else
4441     return (c == ';');	/* might not be rigth for every system... */
4442 #endif
4443 }
4444 #endif
4445 
4446 #if (defined(CASE_INSENSITIVE_FILENAME) && defined(BACKSLASH_IN_FILENAME)) \
4447 	|| defined(PROTO)
4448 /*
4449  * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally.
4450  */
4451     int
4452 vim_fnamecmp(x, y)
4453     char_u	*x, *y;
4454 {
4455     return vim_fnamencmp(x, y, MAXPATHL);
4456 }
4457 
4458     int
4459 vim_fnamencmp(x, y, len)
4460     char_u	*x, *y;
4461     size_t	len;
4462 {
4463     while (len > 0 && *x && *y)
4464     {
4465 	if (TOLOWER_LOC(*x) != TOLOWER_LOC(*y)
4466 		&& !(*x == '/' && *y == '\\')
4467 		&& !(*x == '\\' && *y == '/'))
4468 	    break;
4469 	++x;
4470 	++y;
4471 	--len;
4472     }
4473     if (len == 0)
4474 	return 0;
4475     return (*x - *y);
4476 }
4477 #endif
4478 
4479 /*
4480  * Concatenate file names fname1 and fname2 into allocated memory.
4481  * Only add a '/' or '\\' when 'sep' is TRUE and it is neccesary.
4482  */
4483     char_u  *
4484 concat_fnames(fname1, fname2, sep)
4485     char_u  *fname1;
4486     char_u  *fname2;
4487     int	    sep;
4488 {
4489     char_u  *dest;
4490 
4491     dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3));
4492     if (dest != NULL)
4493     {
4494 	STRCPY(dest, fname1);
4495 	if (sep)
4496 	    add_pathsep(dest);
4497 	STRCAT(dest, fname2);
4498     }
4499     return dest;
4500 }
4501 
4502 #if defined(FEAT_EVAL) || defined(FEAT_GETTEXT) || defined(PROTO)
4503 /*
4504  * Concatenate two strings and return the result in allocated memory.
4505  * Returns NULL when out of memory.
4506  */
4507     char_u  *
4508 concat_str(str1, str2)
4509     char_u  *str1;
4510     char_u  *str2;
4511 {
4512     char_u  *dest;
4513     size_t  l = STRLEN(str1);
4514 
4515     dest = alloc((unsigned)(l + STRLEN(str2) + 1L));
4516     if (dest != NULL)
4517     {
4518 	STRCPY(dest, str1);
4519 	STRCPY(dest + l, str2);
4520     }
4521     return dest;
4522 }
4523 #endif
4524 
4525 /*
4526  * Add a path separator to a file name, unless it already ends in a path
4527  * separator.
4528  */
4529     void
4530 add_pathsep(p)
4531     char_u	*p;
4532 {
4533     if (*p != NUL && !after_pathsep(p, p + STRLEN(p)))
4534 	STRCAT(p, PATHSEPSTR);
4535 }
4536 
4537 /*
4538  * FullName_save - Make an allocated copy of a full file name.
4539  * Returns NULL when out of memory.
4540  */
4541     char_u  *
4542 FullName_save(fname, force)
4543     char_u	*fname;
4544     int		force;	    /* force expansion, even when it already looks
4545 			       like a full path name */
4546 {
4547     char_u	*buf;
4548     char_u	*new_fname = NULL;
4549 
4550     if (fname == NULL)
4551 	return NULL;
4552 
4553     buf = alloc((unsigned)MAXPATHL);
4554     if (buf != NULL)
4555     {
4556 	if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL)
4557 	    new_fname = vim_strsave(buf);
4558 	else
4559 	    new_fname = vim_strsave(fname);
4560 	vim_free(buf);
4561     }
4562     return new_fname;
4563 }
4564 
4565 #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL)
4566 
4567 static char_u	*skip_string __ARGS((char_u *p));
4568 
4569 /*
4570  * Find the start of a comment, not knowing if we are in a comment right now.
4571  * Search starts at w_cursor.lnum and goes backwards.
4572  */
4573     pos_T *
4574 find_start_comment(ind_maxcomment)	    /* XXX */
4575     int		ind_maxcomment;
4576 {
4577     pos_T	*pos;
4578     char_u	*line;
4579     char_u	*p;
4580 
4581     if ((pos = findmatchlimit(NULL, '*', FM_BACKWARD, ind_maxcomment)) == NULL)
4582 	return NULL;
4583 
4584     /*
4585      * Check if the comment start we found is inside a string.
4586      */
4587     line = ml_get(pos->lnum);
4588     for (p = line; *p && (unsigned)(p - line) < pos->col; ++p)
4589 	p = skip_string(p);
4590     if ((unsigned)(p - line) > pos->col)
4591 	return NULL;
4592     return pos;
4593 }
4594 
4595 /*
4596  * Skip to the end of a "string" and a 'c' character.
4597  * If there is no string or character, return argument unmodified.
4598  */
4599     static char_u *
4600 skip_string(p)
4601     char_u  *p;
4602 {
4603     int	    i;
4604 
4605     /*
4606      * We loop, because strings may be concatenated: "date""time".
4607      */
4608     for ( ; ; ++p)
4609     {
4610 	if (p[0] == '\'')		    /* 'c' or '\n' or '\000' */
4611 	{
4612 	    if (!p[1])			    /* ' at end of line */
4613 		break;
4614 	    i = 2;
4615 	    if (p[1] == '\\')		    /* '\n' or '\000' */
4616 	    {
4617 		++i;
4618 		while (vim_isdigit(p[i - 1]))   /* '\000' */
4619 		    ++i;
4620 	    }
4621 	    if (p[i] == '\'')		    /* check for trailing ' */
4622 	    {
4623 		p += i;
4624 		continue;
4625 	    }
4626 	}
4627 	else if (p[0] == '"')		    /* start of string */
4628 	{
4629 	    for (++p; p[0]; ++p)
4630 	    {
4631 		if (p[0] == '\\' && p[1] != NUL)
4632 		    ++p;
4633 		else if (p[0] == '"')	    /* end of string */
4634 		    break;
4635 	    }
4636 	    if (p[0] == '"')
4637 		continue;
4638 	}
4639 	break;				    /* no string found */
4640     }
4641     if (!*p)
4642 	--p;				    /* backup from NUL */
4643     return p;
4644 }
4645 #endif /* FEAT_CINDENT || FEAT_SYN_HL */
4646 
4647 #if defined(FEAT_CINDENT) || defined(PROTO)
4648 
4649 /*
4650  * Do C or expression indenting on the current line.
4651  */
4652     void
4653 do_c_expr_indent()
4654 {
4655 # ifdef FEAT_EVAL
4656     if (*curbuf->b_p_inde != NUL)
4657 	fixthisline(get_expr_indent);
4658     else
4659 # endif
4660 	fixthisline(get_c_indent);
4661 }
4662 
4663 /*
4664  * Functions for C-indenting.
4665  * Most of this originally comes from Eric Fischer.
4666  */
4667 /*
4668  * Below "XXX" means that this function may unlock the current line.
4669  */
4670 
4671 static char_u	*cin_skipcomment __ARGS((char_u *));
4672 static int	cin_nocode __ARGS((char_u *));
4673 static pos_T	*find_line_comment __ARGS((void));
4674 static int	cin_islabel_skip __ARGS((char_u **));
4675 static int	cin_isdefault __ARGS((char_u *));
4676 static char_u	*after_label __ARGS((char_u *l));
4677 static int	get_indent_nolabel __ARGS((linenr_T lnum));
4678 static int	skip_label __ARGS((linenr_T, char_u **pp, int ind_maxcomment));
4679 static int	cin_first_id_amount __ARGS((void));
4680 static int	cin_get_equal_amount __ARGS((linenr_T lnum));
4681 static int	cin_ispreproc __ARGS((char_u *));
4682 static int	cin_ispreproc_cont __ARGS((char_u **pp, linenr_T *lnump));
4683 static int	cin_iscomment __ARGS((char_u *));
4684 static int	cin_islinecomment __ARGS((char_u *));
4685 static int	cin_isterminated __ARGS((char_u *, int, int));
4686 static int	cin_isinit __ARGS((void));
4687 static int	cin_isfuncdecl __ARGS((char_u **, linenr_T));
4688 static int	cin_isif __ARGS((char_u *));
4689 static int	cin_iselse __ARGS((char_u *));
4690 static int	cin_isdo __ARGS((char_u *));
4691 static int	cin_iswhileofdo __ARGS((char_u *, linenr_T, int));
4692 static int	cin_isbreak __ARGS((char_u *));
4693 static int	cin_is_cpp_baseclass __ARGS((char_u *line, colnr_T *col));
4694 static int	cin_ends_in __ARGS((char_u *, char_u *, char_u *));
4695 static int	cin_skip2pos __ARGS((pos_T *trypos));
4696 static pos_T	*find_start_brace __ARGS((int));
4697 static pos_T	*find_match_paren __ARGS((int, int));
4698 static int	corr_ind_maxparen __ARGS((int ind_maxparen, pos_T *startpos));
4699 static int	find_last_paren __ARGS((char_u *l, int start, int end));
4700 static int	find_match __ARGS((int lookfor, linenr_T ourscope, int ind_maxparen, int ind_maxcomment));
4701 
4702 /*
4703  * Skip over white space and C comments within the line.
4704  */
4705     static char_u *
4706 cin_skipcomment(s)
4707     char_u	*s;
4708 {
4709     while (*s)
4710     {
4711 	s = skipwhite(s);
4712 	if (*s != '/')
4713 	    break;
4714 	++s;
4715 	if (*s == '/')		/* slash-slash comment continues till eol */
4716 	{
4717 	    s += STRLEN(s);
4718 	    break;
4719 	}
4720 	if (*s != '*')
4721 	    break;
4722 	for (++s; *s; ++s)	/* skip slash-star comment */
4723 	    if (s[0] == '*' && s[1] == '/')
4724 	    {
4725 		s += 2;
4726 		break;
4727 	    }
4728     }
4729     return s;
4730 }
4731 
4732 /*
4733  * Return TRUE if there there is no code at *s.  White space and comments are
4734  * not considered code.
4735  */
4736     static int
4737 cin_nocode(s)
4738     char_u	*s;
4739 {
4740     return *cin_skipcomment(s) == NUL;
4741 }
4742 
4743 /*
4744  * Check previous lines for a "//" line comment, skipping over blank lines.
4745  */
4746     static pos_T *
4747 find_line_comment() /* XXX */
4748 {
4749     static pos_T pos;
4750     char_u	 *line;
4751     char_u	 *p;
4752 
4753     pos = curwin->w_cursor;
4754     while (--pos.lnum > 0)
4755     {
4756 	line = ml_get(pos.lnum);
4757 	p = skipwhite(line);
4758 	if (cin_islinecomment(p))
4759 	{
4760 	    pos.col = (int)(p - line);
4761 	    return &pos;
4762 	}
4763 	if (*p != NUL)
4764 	    break;
4765     }
4766     return NULL;
4767 }
4768 
4769 /*
4770  * Check if string matches "label:"; move to character after ':' if true.
4771  */
4772     static int
4773 cin_islabel_skip(s)
4774     char_u	**s;
4775 {
4776     if (!vim_isIDc(**s))	    /* need at least one ID character */
4777 	return FALSE;
4778 
4779     while (vim_isIDc(**s))
4780 	(*s)++;
4781 
4782     *s = cin_skipcomment(*s);
4783 
4784     /* "::" is not a label, it's C++ */
4785     return (**s == ':' && *++*s != ':');
4786 }
4787 
4788 /*
4789  * Recognize a label: "label:".
4790  * Note: curwin->w_cursor must be where we are looking for the label.
4791  */
4792     int
4793 cin_islabel(ind_maxcomment)		/* XXX */
4794     int		ind_maxcomment;
4795 {
4796     char_u	*s;
4797 
4798     s = cin_skipcomment(ml_get_curline());
4799 
4800     /*
4801      * Exclude "default" from labels, since it should be indented
4802      * like a switch label.  Same for C++ scope declarations.
4803      */
4804     if (cin_isdefault(s))
4805 	return FALSE;
4806     if (cin_isscopedecl(s))
4807 	return FALSE;
4808 
4809     if (cin_islabel_skip(&s))
4810     {
4811 	/*
4812 	 * Only accept a label if the previous line is terminated or is a case
4813 	 * label.
4814 	 */
4815 	pos_T	cursor_save;
4816 	pos_T	*trypos;
4817 	char_u	*line;
4818 
4819 	cursor_save = curwin->w_cursor;
4820 	while (curwin->w_cursor.lnum > 1)
4821 	{
4822 	    --curwin->w_cursor.lnum;
4823 
4824 	    /*
4825 	     * If we're in a comment now, skip to the start of the comment.
4826 	     */
4827 	    curwin->w_cursor.col = 0;
4828 	    if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
4829 		curwin->w_cursor = *trypos;
4830 
4831 	    line = ml_get_curline();
4832 	    if (cin_ispreproc(line))	/* ignore #defines, #if, etc. */
4833 		continue;
4834 	    if (*(line = cin_skipcomment(line)) == NUL)
4835 		continue;
4836 
4837 	    curwin->w_cursor = cursor_save;
4838 	    if (cin_isterminated(line, TRUE, FALSE)
4839 		    || cin_isscopedecl(line)
4840 		    || cin_iscase(line)
4841 		    || (cin_islabel_skip(&line) && cin_nocode(line)))
4842 		return TRUE;
4843 	    return FALSE;
4844 	}
4845 	curwin->w_cursor = cursor_save;
4846 	return TRUE;		/* label at start of file??? */
4847     }
4848     return FALSE;
4849 }
4850 
4851 /*
4852  * Recognize structure initialization and enumerations.
4853  * Q&D-Implementation:
4854  * check for "=" at end or "[typedef] enum" at beginning of line.
4855  */
4856     static int
4857 cin_isinit(void)
4858 {
4859     char_u	*s;
4860 
4861     s = cin_skipcomment(ml_get_curline());
4862 
4863     if (STRNCMP(s, "typedef", 7) == 0 && !vim_isIDc(s[7]))
4864 	s = cin_skipcomment(s + 7);
4865 
4866     if (STRNCMP(s, "enum", 4) == 0 && !vim_isIDc(s[4]))
4867 	return TRUE;
4868 
4869     if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
4870 	return TRUE;
4871 
4872     return FALSE;
4873 }
4874 
4875 /*
4876  * Recognize a switch label: "case .*:" or "default:".
4877  */
4878      int
4879 cin_iscase(s)
4880     char_u *s;
4881 {
4882     s = cin_skipcomment(s);
4883     if (STRNCMP(s, "case", 4) == 0 && !vim_isIDc(s[4]))
4884     {
4885 	for (s += 4; *s; ++s)
4886 	{
4887 	    s = cin_skipcomment(s);
4888 	    if (*s == ':')
4889 	    {
4890 		if (s[1] == ':')	/* skip over "::" for C++ */
4891 		    ++s;
4892 		else
4893 		    return TRUE;
4894 	    }
4895 	    if (*s == '\'' && s[1] && s[2] == '\'')
4896 		s += 2;			/* skip over '.' */
4897 	    else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
4898 		return FALSE;		/* stop at comment */
4899 	    else if (*s == '"')
4900 		return FALSE;		/* stop at string */
4901 	}
4902 	return FALSE;
4903     }
4904 
4905     if (cin_isdefault(s))
4906 	return TRUE;
4907     return FALSE;
4908 }
4909 
4910 /*
4911  * Recognize a "default" switch label.
4912  */
4913     static int
4914 cin_isdefault(s)
4915     char_u  *s;
4916 {
4917     return (STRNCMP(s, "default", 7) == 0
4918 	    && *(s = cin_skipcomment(s + 7)) == ':'
4919 	    && s[1] != ':');
4920 }
4921 
4922 /*
4923  * Recognize a "public/private/proctected" scope declaration label.
4924  */
4925     int
4926 cin_isscopedecl(s)
4927     char_u	*s;
4928 {
4929     int		i;
4930 
4931     s = cin_skipcomment(s);
4932     if (STRNCMP(s, "public", 6) == 0)
4933 	i = 6;
4934     else if (STRNCMP(s, "protected", 9) == 0)
4935 	i = 9;
4936     else if (STRNCMP(s, "private", 7) == 0)
4937 	i = 7;
4938     else
4939 	return FALSE;
4940     return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
4941 }
4942 
4943 /*
4944  * Return a pointer to the first non-empty non-comment character after a ':'.
4945  * Return NULL if not found.
4946  *	  case 234:    a = b;
4947  *		       ^
4948  */
4949     static char_u *
4950 after_label(l)
4951     char_u  *l;
4952 {
4953     for ( ; *l; ++l)
4954     {
4955 	if (*l == ':')
4956 	{
4957 	    if (l[1] == ':')	    /* skip over "::" for C++ */
4958 		++l;
4959 	    else if (!cin_iscase(l + 1))
4960 		break;
4961 	}
4962 	else if (*l == '\'' && l[1] && l[2] == '\'')
4963 	    l += 2;		    /* skip over 'x' */
4964     }
4965     if (*l == NUL)
4966 	return NULL;
4967     l = cin_skipcomment(l + 1);
4968     if (*l == NUL)
4969 	return NULL;
4970     return l;
4971 }
4972 
4973 /*
4974  * Get indent of line "lnum", skipping a label.
4975  * Return 0 if there is nothing after the label.
4976  */
4977     static int
4978 get_indent_nolabel(lnum)		/* XXX */
4979     linenr_T	lnum;
4980 {
4981     char_u	*l;
4982     pos_T	fp;
4983     colnr_T	col;
4984     char_u	*p;
4985 
4986     l = ml_get(lnum);
4987     p = after_label(l);
4988     if (p == NULL)
4989 	return 0;
4990 
4991     fp.col = (colnr_T)(p - l);
4992     fp.lnum = lnum;
4993     getvcol(curwin, &fp, &col, NULL, NULL);
4994     return (int)col;
4995 }
4996 
4997 /*
4998  * Find indent for line "lnum", ignoring any case or jump label.
4999  * Also return a pointer to the text (after the label).
5000  *   label:	if (asdf && asdfasdf)
5001  *		^
5002  */
5003     static int
5004 skip_label(lnum, pp, ind_maxcomment)
5005     linenr_T	lnum;
5006     char_u	**pp;
5007     int		ind_maxcomment;
5008 {
5009     char_u	*l;
5010     int		amount;
5011     pos_T	cursor_save;
5012 
5013     cursor_save = curwin->w_cursor;
5014     curwin->w_cursor.lnum = lnum;
5015     l = ml_get_curline();
5016 				    /* XXX */
5017     if (cin_iscase(l) || cin_isscopedecl(l) || cin_islabel(ind_maxcomment))
5018     {
5019 	amount = get_indent_nolabel(lnum);
5020 	l = after_label(ml_get_curline());
5021 	if (l == NULL)		/* just in case */
5022 	    l = ml_get_curline();
5023     }
5024     else
5025     {
5026 	amount = get_indent();
5027 	l = ml_get_curline();
5028     }
5029     *pp = l;
5030 
5031     curwin->w_cursor = cursor_save;
5032     return amount;
5033 }
5034 
5035 /*
5036  * Return the indent of the first variable name after a type in a declaration.
5037  *  int	    a,			indent of "a"
5038  *  static struct foo    b,	indent of "b"
5039  *  enum bla    c,		indent of "c"
5040  * Returns zero when it doesn't look like a declaration.
5041  */
5042     static int
5043 cin_first_id_amount()
5044 {
5045     char_u	*line, *p, *s;
5046     int		len;
5047     pos_T	fp;
5048     colnr_T	col;
5049 
5050     line = ml_get_curline();
5051     p = skipwhite(line);
5052     len = skiptowhite(p) - p;
5053     if (len == 6 && STRNCMP(p, "static", 6) == 0)
5054     {
5055 	p = skipwhite(p + 6);
5056 	len = skiptowhite(p) - p;
5057     }
5058     if (len == 6 && STRNCMP(p, "struct", 6) == 0)
5059 	p = skipwhite(p + 6);
5060     else if (len == 4 && STRNCMP(p, "enum", 4) == 0)
5061 	p = skipwhite(p + 4);
5062     else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0)
5063 	    || (len == 6 && STRNCMP(p, "signed", 6) == 0))
5064     {
5065 	s = skipwhite(p + len);
5066 	if ((STRNCMP(s, "int", 3) == 0 && vim_iswhite(s[3]))
5067 		|| (STRNCMP(s, "long", 4) == 0 && vim_iswhite(s[4]))
5068 		|| (STRNCMP(s, "short", 5) == 0 && vim_iswhite(s[5]))
5069 		|| (STRNCMP(s, "char", 4) == 0 && vim_iswhite(s[4])))
5070 	    p = s;
5071     }
5072     for (len = 0; vim_isIDc(p[len]); ++len)
5073 	;
5074     if (len == 0 || !vim_iswhite(p[len]) || cin_nocode(p))
5075 	return 0;
5076 
5077     p = skipwhite(p + len);
5078     fp.lnum = curwin->w_cursor.lnum;
5079     fp.col = (colnr_T)(p - line);
5080     getvcol(curwin, &fp, &col, NULL, NULL);
5081     return (int)col;
5082 }
5083 
5084 /*
5085  * Return the indent of the first non-blank after an equal sign.
5086  *       char *foo = "here";
5087  * Return zero if no (useful) equal sign found.
5088  * Return -1 if the line above "lnum" ends in a backslash.
5089  *      foo = "asdf\
5090  *	       asdf\
5091  *	       here";
5092  */
5093     static int
5094 cin_get_equal_amount(lnum)
5095     linenr_T	lnum;
5096 {
5097     char_u	*line;
5098     char_u	*s;
5099     colnr_T	col;
5100     pos_T	fp;
5101 
5102     if (lnum > 1)
5103     {
5104 	line = ml_get(lnum - 1);
5105 	if (*line != NUL && line[STRLEN(line) - 1] == '\\')
5106 	    return -1;
5107     }
5108 
5109     line = s = ml_get(lnum);
5110     while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL)
5111     {
5112 	if (cin_iscomment(s))	/* ignore comments */
5113 	    s = cin_skipcomment(s);
5114 	else
5115 	    ++s;
5116     }
5117     if (*s != '=')
5118 	return 0;
5119 
5120     s = skipwhite(s + 1);
5121     if (cin_nocode(s))
5122 	return 0;
5123 
5124     if (*s == '"')	/* nice alignment for continued strings */
5125 	++s;
5126 
5127     fp.lnum = lnum;
5128     fp.col = (colnr_T)(s - line);
5129     getvcol(curwin, &fp, &col, NULL, NULL);
5130     return (int)col;
5131 }
5132 
5133 /*
5134  * Recognize a preprocessor statement: Any line that starts with '#'.
5135  */
5136     static int
5137 cin_ispreproc(s)
5138     char_u *s;
5139 {
5140     s = skipwhite(s);
5141     if (*s == '#')
5142 	return TRUE;
5143     return FALSE;
5144 }
5145 
5146 /*
5147  * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
5148  * continuation line of a preprocessor statement.  Decrease "*lnump" to the
5149  * start and return the line in "*pp".
5150  */
5151     static int
5152 cin_ispreproc_cont(pp, lnump)
5153     char_u	**pp;
5154     linenr_T	*lnump;
5155 {
5156     char_u	*line = *pp;
5157     linenr_T	lnum = *lnump;
5158     int		retval = FALSE;
5159 
5160     for (;;)
5161     {
5162 	if (cin_ispreproc(line))
5163 	{
5164 	    retval = TRUE;
5165 	    *lnump = lnum;
5166 	    break;
5167 	}
5168 	if (lnum == 1)
5169 	    break;
5170 	line = ml_get(--lnum);
5171 	if (*line == NUL || line[STRLEN(line) - 1] != '\\')
5172 	    break;
5173     }
5174 
5175     if (lnum != *lnump)
5176 	*pp = ml_get(*lnump);
5177     return retval;
5178 }
5179 
5180 /*
5181  * Recognize the start of a C or C++ comment.
5182  */
5183     static int
5184 cin_iscomment(p)
5185     char_u  *p;
5186 {
5187     return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
5188 }
5189 
5190 /*
5191  * Recognize the start of a "//" comment.
5192  */
5193     static int
5194 cin_islinecomment(p)
5195     char_u *p;
5196 {
5197     return (p[0] == '/' && p[1] == '/');
5198 }
5199 
5200 /*
5201  * Recognize a line that starts with '{' or '}', or ends with ';', '{' or '}'.
5202  * Don't consider "} else" a terminated line.
5203  * Return the character terminating the line (ending char's have precedence if
5204  * both apply in order to determine initializations).
5205  */
5206     static int
5207 cin_isterminated(s, incl_open, incl_comma)
5208     char_u	*s;
5209     int		incl_open;	/* include '{' at the end as terminator */
5210     int		incl_comma;	/* recognize a trailing comma */
5211 {
5212     char_u found_start = 0;
5213 
5214     s = cin_skipcomment(s);
5215 
5216     if (*s == '{' || (*s == '}' && !cin_iselse(s)))
5217 	found_start = *s;
5218 
5219     while (*s)
5220     {
5221 	/* skip over comments, "" strings and 'c'haracters */
5222 	s = skip_string(cin_skipcomment(s));
5223 	if ((*s == ';' || (incl_open && *s == '{') || *s == '}'
5224 						 || (incl_comma && *s == ','))
5225 		&& cin_nocode(s + 1))
5226 	    return *s;
5227 
5228 	if (*s)
5229 	    s++;
5230     }
5231     return found_start;
5232 }
5233 
5234 /*
5235  * Recognize the basic picture of a function declaration -- it needs to
5236  * have an open paren somewhere and a close paren at the end of the line and
5237  * no semicolons anywhere.
5238  * When a line ends in a comma we continue looking in the next line.
5239  * "sp" points to a string with the line.  When looking at other lines it must
5240  * be restored to the line.  When it's NULL fetch lines here.
5241  * "lnum" is where we start looking.
5242  */
5243     static int
5244 cin_isfuncdecl(sp, first_lnum)
5245     char_u	**sp;
5246     linenr_T	first_lnum;
5247 {
5248     char_u	*s;
5249     linenr_T	lnum = first_lnum;
5250     int		retval = FALSE;
5251 
5252     if (sp == NULL)
5253 	s = ml_get(lnum);
5254     else
5255 	s = *sp;
5256 
5257     while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"')
5258     {
5259 	if (cin_iscomment(s))	/* ignore comments */
5260 	    s = cin_skipcomment(s);
5261 	else
5262 	    ++s;
5263     }
5264     if (*s != '(')
5265 	return FALSE;		/* ';', ' or "  before any () or no '(' */
5266 
5267     while (*s && *s != ';' && *s != '\'' && *s != '"')
5268     {
5269 	if (*s == ')' && cin_nocode(s + 1))
5270 	{
5271 	    /* ')' at the end: may have found a match
5272 	     * Check for he previous line not to end in a backslash:
5273 	     *       #if defined(x) && \
5274 	     *		 defined(y)
5275 	     */
5276 	    lnum = first_lnum - 1;
5277 	    s = ml_get(lnum);
5278 	    if (*s == NUL || s[STRLEN(s) - 1] != '\\')
5279 		retval = TRUE;
5280 	    goto done;
5281 	}
5282 	if (*s == ',' && cin_nocode(s + 1))
5283 	{
5284 	    /* ',' at the end: continue looking in the next line */
5285 	    if (lnum >= curbuf->b_ml.ml_line_count)
5286 		break;
5287 
5288 	    s = ml_get(++lnum);
5289 	}
5290 	else if (cin_iscomment(s))	/* ignore comments */
5291 	    s = cin_skipcomment(s);
5292 	else
5293 	    ++s;
5294     }
5295 
5296 done:
5297     if (lnum != first_lnum && sp != NULL)
5298 	*sp = ml_get(first_lnum);
5299 
5300     return retval;
5301 }
5302 
5303     static int
5304 cin_isif(p)
5305     char_u  *p;
5306 {
5307     return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]));
5308 }
5309 
5310     static int
5311 cin_iselse(p)
5312     char_u  *p;
5313 {
5314     if (*p == '}')	    /* accept "} else" */
5315 	p = cin_skipcomment(p + 1);
5316     return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]));
5317 }
5318 
5319     static int
5320 cin_isdo(p)
5321     char_u  *p;
5322 {
5323     return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]));
5324 }
5325 
5326 /*
5327  * Check if this is a "while" that should have a matching "do".
5328  * We only accept a "while (condition) ;", with only white space between the
5329  * ')' and ';'. The condition may be spread over several lines.
5330  */
5331     static int
5332 cin_iswhileofdo(p, lnum, ind_maxparen)	    /* XXX */
5333     char_u	*p;
5334     linenr_T	lnum;
5335     int		ind_maxparen;
5336 {
5337     pos_T	cursor_save;
5338     pos_T	*trypos;
5339     int		retval = FALSE;
5340 
5341     p = cin_skipcomment(p);
5342     if (*p == '}')		/* accept "} while (cond);" */
5343 	p = cin_skipcomment(p + 1);
5344     if (STRNCMP(p, "while", 5) == 0 && !vim_isIDc(p[5]))
5345     {
5346 	cursor_save = curwin->w_cursor;
5347 	curwin->w_cursor.lnum = lnum;
5348 	curwin->w_cursor.col = 0;
5349 	p = ml_get_curline();
5350 	while (*p && *p != 'w')	/* skip any '}', until the 'w' of the "while" */
5351 	{
5352 	    ++p;
5353 	    ++curwin->w_cursor.col;
5354 	}
5355 	if ((trypos = findmatchlimit(NULL, 0, 0, ind_maxparen)) != NULL
5356 		&& *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
5357 	    retval = TRUE;
5358 	curwin->w_cursor = cursor_save;
5359     }
5360     return retval;
5361 }
5362 
5363     static int
5364 cin_isbreak(p)
5365     char_u  *p;
5366 {
5367     return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]));
5368 }
5369 
5370 /* Find the position of a C++ base-class declaration or
5371  * constructor-initialization. eg:
5372  *
5373  * class MyClass :
5374  *	baseClass		<-- here
5375  * class MyClass : public baseClass,
5376  *	anotherBaseClass	<-- here (should probably lineup ??)
5377  * MyClass::MyClass(...) :
5378  *	baseClass(...)		<-- here (constructor-initialization)
5379  */
5380     static int
5381 cin_is_cpp_baseclass(line, col)
5382     char_u	*line;
5383     colnr_T	*col;
5384 {
5385     char_u	*s;
5386     int		class_or_struct, lookfor_ctor_init, cpp_base_class;
5387 
5388     *col = 0;
5389 
5390     s = skipwhite(line);
5391     if (*s == '#')		/* skip #define FOO x ? (x) : x */
5392 	return FALSE;
5393     s = cin_skipcomment(s);
5394     if (*s == NUL)
5395 	return FALSE;
5396 
5397     cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
5398 
5399     while(*s != NUL)
5400     {
5401 	if (s[0] == ':')
5402 	{
5403 	    if (s[1] == ':')
5404 	    {
5405 		/* skip double colon. It can't be a constructor
5406 		 * initialization any more */
5407 		lookfor_ctor_init = FALSE;
5408 		s = cin_skipcomment(s + 2);
5409 	    }
5410 	    else if (lookfor_ctor_init || class_or_struct)
5411 	    {
5412 		/* we have something found, that looks like the start of
5413 		 * cpp-base-class-declaration or contructor-initialization */
5414 		cpp_base_class = TRUE;
5415 		lookfor_ctor_init = class_or_struct = FALSE;
5416 		*col = 0;
5417 		s = cin_skipcomment(s + 1);
5418 	    }
5419 	    else
5420 		s = cin_skipcomment(s + 1);
5421 	}
5422 	else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
5423 		|| (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6])))
5424 	{
5425 	    class_or_struct = TRUE;
5426 	    lookfor_ctor_init = FALSE;
5427 
5428 	    if (*s == 'c')
5429 		s = cin_skipcomment(s + 5);
5430 	    else
5431 		s = cin_skipcomment(s + 6);
5432 	}
5433 	else
5434 	{
5435 	    if (s[0] == '{' || s[0] == '}' || s[0] == ';')
5436 	    {
5437 		cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
5438 	    }
5439 	    else if (s[0] == ')')
5440 	    {
5441 		/* Constructor-initialization is assumed if we come across
5442 		 * something like "):" */
5443 		class_or_struct = FALSE;
5444 		lookfor_ctor_init = TRUE;
5445 	    }
5446 	    else if (!vim_isIDc(s[0]))
5447 	    {
5448 		/* if it is not an identifier, we are wrong */
5449 		class_or_struct = FALSE;
5450 		lookfor_ctor_init = FALSE;
5451 	    }
5452 	    else if (*col == 0)
5453 	    {
5454 		/* it can't be a constructor-initialization any more */
5455 		lookfor_ctor_init = FALSE;
5456 
5457 		/* the first statement starts here: lineup with this one... */
5458 		if (cpp_base_class && *col == 0)
5459 		    *col = (colnr_T)(s - line);
5460 	    }
5461 
5462 	    s = cin_skipcomment(s + 1);
5463 	}
5464     }
5465 
5466     return cpp_base_class;
5467 }
5468 
5469 /*
5470  * Return TRUE if string "s" ends with the string "find", possibly followed by
5471  * white space and comments.  Skip strings and comments.
5472  * Ignore "ignore" after "find" if it's not NULL.
5473  */
5474     static int
5475 cin_ends_in(s, find, ignore)
5476     char_u	*s;
5477     char_u	*find;
5478     char_u	*ignore;
5479 {
5480     char_u	*p = s;
5481     char_u	*r;
5482     int		len = (int)STRLEN(find);
5483 
5484     while (*p != NUL)
5485     {
5486 	p = cin_skipcomment(p);
5487 	if (STRNCMP(p, find, len) == 0)
5488 	{
5489 	    r = skipwhite(p + len);
5490 	    if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
5491 		r = skipwhite(r + STRLEN(ignore));
5492 	    if (cin_nocode(r))
5493 		return TRUE;
5494 	}
5495 	if (*p != NUL)
5496 	    ++p;
5497     }
5498     return FALSE;
5499 }
5500 
5501 /*
5502  * Skip strings, chars and comments until at or past "trypos".
5503  * Return the column found.
5504  */
5505     static int
5506 cin_skip2pos(trypos)
5507     pos_T	*trypos;
5508 {
5509     char_u	*line;
5510     char_u	*p;
5511 
5512     p = line = ml_get(trypos->lnum);
5513     while (*p && (colnr_T)(p - line) < trypos->col)
5514     {
5515 	if (cin_iscomment(p))
5516 	    p = cin_skipcomment(p);
5517 	else
5518 	{
5519 	    p = skip_string(p);
5520 	    ++p;
5521 	}
5522     }
5523     return (int)(p - line);
5524 }
5525 
5526 /*
5527  * Find the '{' at the start of the block we are in.
5528  * Return NULL if no match found.
5529  * Ignore a '{' that is in a comment, makes indenting the next three lines
5530  * work. */
5531 /* foo()    */
5532 /* {	    */
5533 /* }	    */
5534 
5535     static pos_T *
5536 find_start_brace(ind_maxcomment)	    /* XXX */
5537     int		ind_maxcomment;
5538 {
5539     pos_T	cursor_save;
5540     pos_T	*trypos;
5541     pos_T	*pos;
5542     static pos_T	pos_copy;
5543 
5544     cursor_save = curwin->w_cursor;
5545     while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
5546     {
5547 	pos_copy = *trypos;	/* copy pos_T, next findmatch will change it */
5548 	trypos = &pos_copy;
5549 	curwin->w_cursor = *trypos;
5550 	pos = NULL;
5551 	/* ignore the { if it's in a // comment */
5552 	if ((colnr_T)cin_skip2pos(trypos) == trypos->col
5553 		&& (pos = find_start_comment(ind_maxcomment)) == NULL) /* XXX */
5554 	    break;
5555 	if (pos != NULL)
5556 	    curwin->w_cursor.lnum = pos->lnum;
5557     }
5558     curwin->w_cursor = cursor_save;
5559     return trypos;
5560 }
5561 
5562 /*
5563  * Find the matching '(', failing if it is in a comment.
5564  * Return NULL of no match found.
5565  */
5566     static pos_T *
5567 find_match_paren(ind_maxparen, ind_maxcomment)	    /* XXX */
5568     int		ind_maxparen;
5569     int		ind_maxcomment;
5570 {
5571     pos_T	cursor_save;
5572     pos_T	*trypos;
5573     static pos_T	pos_copy;
5574 
5575     cursor_save = curwin->w_cursor;
5576     if ((trypos = findmatchlimit(NULL, '(', 0, ind_maxparen)) != NULL)
5577     {
5578 	/* check if the ( is in a // comment */
5579 	if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
5580 	    trypos = NULL;
5581 	else
5582 	{
5583 	    pos_copy = *trypos;	    /* copy trypos, findmatch will change it */
5584 	    trypos = &pos_copy;
5585 	    curwin->w_cursor = *trypos;
5586 	    if (find_start_comment(ind_maxcomment) != NULL) /* XXX */
5587 		trypos = NULL;
5588 	}
5589     }
5590     curwin->w_cursor = cursor_save;
5591     return trypos;
5592 }
5593 
5594 /*
5595  * Return ind_maxparen corrected for the difference in line number between the
5596  * cursor position and "startpos".  This makes sure that searching for a
5597  * matching paren above the cursor line doesn't find a match because of
5598  * looking a few lines further.
5599  */
5600     static int
5601 corr_ind_maxparen(ind_maxparen, startpos)
5602     int		ind_maxparen;
5603     pos_T	*startpos;
5604 {
5605     long	n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
5606 
5607     if (n > 0 && n < ind_maxparen / 2)
5608 	return ind_maxparen - (int)n;
5609     return ind_maxparen;
5610 }
5611 
5612 /*
5613  * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
5614  * line "l".
5615  */
5616     static int
5617 find_last_paren(l, start, end)
5618     char_u	*l;
5619     int		start, end;
5620 {
5621     int		i;
5622     int		retval = FALSE;
5623     int		open_count = 0;
5624 
5625     curwin->w_cursor.col = 0;		    /* default is start of line */
5626 
5627     for (i = 0; l[i]; i++)
5628     {
5629 	i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */
5630 	i = (int)(skip_string(l + i) - l);    /* ignore parens in quotes */
5631 	if (l[i] == start)
5632 	    ++open_count;
5633 	else if (l[i] == end)
5634 	{
5635 	    if (open_count > 0)
5636 		--open_count;
5637 	    else
5638 	    {
5639 		curwin->w_cursor.col = i;
5640 		retval = TRUE;
5641 	    }
5642 	}
5643     }
5644     return retval;
5645 }
5646 
5647     int
5648 get_c_indent()
5649 {
5650     /*
5651      * spaces from a block's opening brace the prevailing indent for that
5652      * block should be
5653      */
5654     int ind_level = curbuf->b_p_sw;
5655 
5656     /*
5657      * spaces from the edge of the line an open brace that's at the end of a
5658      * line is imagined to be.
5659      */
5660     int ind_open_imag = 0;
5661 
5662     /*
5663      * spaces from the prevailing indent for a line that is not precededof by
5664      * an opening brace.
5665      */
5666     int ind_no_brace = 0;
5667 
5668     /*
5669      * column where the first { of a function should be located }
5670      */
5671     int ind_first_open = 0;
5672 
5673     /*
5674      * spaces from the prevailing indent a leftmost open brace should be
5675      * located
5676      */
5677     int ind_open_extra = 0;
5678 
5679     /*
5680      * spaces from the matching open brace (real location for one at the left
5681      * edge; imaginary location from one that ends a line) the matching close
5682      * brace should be located
5683      */
5684     int ind_close_extra = 0;
5685 
5686     /*
5687      * spaces from the edge of the line an open brace sitting in the leftmost
5688      * column is imagined to be
5689      */
5690     int ind_open_left_imag = 0;
5691 
5692     /*
5693      * spaces from the switch() indent a "case xx" label should be located
5694      */
5695     int ind_case = curbuf->b_p_sw;
5696 
5697     /*
5698      * spaces from the "case xx:" code after a switch() should be located
5699      */
5700     int ind_case_code = curbuf->b_p_sw;
5701 
5702     /*
5703      * lineup break at end of case in switch() with case label
5704      */
5705     int ind_case_break = 0;
5706 
5707     /*
5708      * spaces from the class declaration indent a scope declaration label
5709      * should be located
5710      */
5711     int ind_scopedecl = curbuf->b_p_sw;
5712 
5713     /*
5714      * spaces from the scope declaration label code should be located
5715      */
5716     int ind_scopedecl_code = curbuf->b_p_sw;
5717 
5718     /*
5719      * amount K&R-style parameters should be indented
5720      */
5721     int ind_param = curbuf->b_p_sw;
5722 
5723     /*
5724      * amount a function type spec should be indented
5725      */
5726     int ind_func_type = curbuf->b_p_sw;
5727 
5728     /*
5729      * amount a cpp base class declaration or constructor initialization
5730      * should be indented
5731      */
5732     int ind_cpp_baseclass = curbuf->b_p_sw;
5733 
5734     /*
5735      * additional spaces beyond the prevailing indent a continuation line
5736      * should be located
5737      */
5738     int ind_continuation = curbuf->b_p_sw;
5739 
5740     /*
5741      * spaces from the indent of the line with an unclosed parentheses
5742      */
5743     int ind_unclosed = curbuf->b_p_sw * 2;
5744 
5745     /*
5746      * spaces from the indent of the line with an unclosed parentheses, which
5747      * itself is also unclosed
5748      */
5749     int ind_unclosed2 = curbuf->b_p_sw;
5750 
5751     /*
5752      * suppress ignoring spaces from the indent of a line starting with an
5753      * unclosed parentheses.
5754      */
5755     int ind_unclosed_noignore = 0;
5756 
5757     /*
5758      * If the opening paren is the last nonwhite character on the line, and
5759      * ind_unclosed_wrapped is nonzero, use this indent relative to the outer
5760      * context (for very long lines).
5761      */
5762     int ind_unclosed_wrapped = 0;
5763 
5764     /*
5765      * suppress ignoring white space when lining up with the character after
5766      * an unclosed parentheses.
5767      */
5768     int ind_unclosed_whiteok = 0;
5769 
5770     /*
5771      * indent a closing parentheses under the line start of the matching
5772      * opening parentheses.
5773      */
5774     int ind_matching_paren = 0;
5775 
5776     /*
5777      * Extra indent for comments.
5778      */
5779     int ind_comment = 0;
5780 
5781     /*
5782      * spaces from the comment opener when there is nothing after it.
5783      */
5784     int ind_in_comment = 3;
5785 
5786     /*
5787      * boolean: if non-zero, use ind_in_comment even if there is something
5788      * after the comment opener.
5789      */
5790     int ind_in_comment2 = 0;
5791 
5792     /*
5793      * max lines to search for an open paren
5794      */
5795     int ind_maxparen = 20;
5796 
5797     /*
5798      * max lines to search for an open comment
5799      */
5800     int ind_maxcomment = 70;
5801 
5802     /*
5803      * handle braces for java code
5804      */
5805     int	ind_java = 0;
5806 
5807     /*
5808      * handle blocked cases correctly
5809      */
5810     int ind_keep_case_label = 0;
5811 
5812     pos_T	cur_curpos;
5813     int		amount;
5814     int		scope_amount;
5815     int		cur_amount;
5816     colnr_T	col;
5817     char_u	*theline;
5818     char_u	*linecopy;
5819     pos_T	*trypos;
5820     pos_T	*tryposBrace = NULL;
5821     pos_T	our_paren_pos;
5822     char_u	*start;
5823     int		start_brace;
5824 #define BRACE_IN_COL0		1	    /* '{' is in comumn 0 */
5825 #define BRACE_AT_START		2	    /* '{' is at start of line */
5826 #define BRACE_AT_END		3	    /* '{' is at end of line */
5827     linenr_T	ourscope;
5828     char_u	*l;
5829     char_u	*look;
5830     char_u	terminated;
5831     int		lookfor;
5832 #define LOOKFOR_INITIAL		0
5833 #define LOOKFOR_IF		1
5834 #define LOOKFOR_DO		2
5835 #define LOOKFOR_CASE		3
5836 #define LOOKFOR_ANY		4
5837 #define LOOKFOR_TERM		5
5838 #define LOOKFOR_UNTERM		6
5839 #define LOOKFOR_SCOPEDECL	7
5840 #define LOOKFOR_NOBREAK		8
5841 #define LOOKFOR_CPP_BASECLASS	9
5842 #define LOOKFOR_ENUM_OR_INIT	10
5843 
5844     int		whilelevel;
5845     linenr_T	lnum;
5846     char_u	*options;
5847     int		fraction = 0;	    /* init for GCC */
5848     int		divider;
5849     int		n;
5850     int		iscase;
5851     int		lookfor_break;
5852     int		cont_amount = 0;    /* amount for continuation line */
5853 
5854     for (options = curbuf->b_p_cino; *options; )
5855     {
5856 	l = options++;
5857 	if (*options == '-')
5858 	    ++options;
5859 	n = getdigits(&options);
5860 	divider = 0;
5861 	if (*options == '.')	    /* ".5s" means a fraction */
5862 	{
5863 	    fraction = atol((char *)++options);
5864 	    while (VIM_ISDIGIT(*options))
5865 	    {
5866 		++options;
5867 		if (divider)
5868 		    divider *= 10;
5869 		else
5870 		    divider = 10;
5871 	    }
5872 	}
5873 	if (*options == 's')	    /* "2s" means two times 'shiftwidth' */
5874 	{
5875 	    if (n == 0 && fraction == 0)
5876 		n = curbuf->b_p_sw;	/* just "s" is one 'shiftwidth' */
5877 	    else
5878 	    {
5879 		n *= curbuf->b_p_sw;
5880 		if (divider)
5881 		    n += (curbuf->b_p_sw * fraction + divider / 2) / divider;
5882 	    }
5883 	    ++options;
5884 	}
5885 	if (l[1] == '-')
5886 	    n = -n;
5887 	/* When adding an entry here, also update the default 'cinoptions' in
5888 	 * change.txt, and add explanation for it! */
5889 	switch (*l)
5890 	{
5891 	    case '>': ind_level = n; break;
5892 	    case 'e': ind_open_imag = n; break;
5893 	    case 'n': ind_no_brace = n; break;
5894 	    case 'f': ind_first_open = n; break;
5895 	    case '{': ind_open_extra = n; break;
5896 	    case '}': ind_close_extra = n; break;
5897 	    case '^': ind_open_left_imag = n; break;
5898 	    case ':': ind_case = n; break;
5899 	    case '=': ind_case_code = n; break;
5900 	    case 'b': ind_case_break = n; break;
5901 	    case 'p': ind_param = n; break;
5902 	    case 't': ind_func_type = n; break;
5903 	    case '/': ind_comment = n; break;
5904 	    case 'c': ind_in_comment = n; break;
5905 	    case 'C': ind_in_comment2 = n; break;
5906 	    case 'i': ind_cpp_baseclass = n; break;
5907 	    case '+': ind_continuation = n; break;
5908 	    case '(': ind_unclosed = n; break;
5909 	    case 'u': ind_unclosed2 = n; break;
5910 	    case 'U': ind_unclosed_noignore = n; break;
5911 	    case 'W': ind_unclosed_wrapped = n; break;
5912 	    case 'w': ind_unclosed_whiteok = n; break;
5913 	    case 'm': ind_matching_paren = n; break;
5914 	    case ')': ind_maxparen = n; break;
5915 	    case '*': ind_maxcomment = n; break;
5916 	    case 'g': ind_scopedecl = n; break;
5917 	    case 'h': ind_scopedecl_code = n; break;
5918 	    case 'j': ind_java = n; break;
5919 	    case 'l': ind_keep_case_label = n; break;
5920 	}
5921     }
5922 
5923     /* remember where the cursor was when we started */
5924     cur_curpos = curwin->w_cursor;
5925 
5926     /* Get a copy of the current contents of the line.
5927      * This is required, because only the most recent line obtained with
5928      * ml_get is valid! */
5929     linecopy = vim_strsave(ml_get(cur_curpos.lnum));
5930     if (linecopy == NULL)
5931 	return 0;
5932 
5933     /*
5934      * In insert mode and the cursor is on a ')' truncate the line at the
5935      * cursor position.  We don't want to line up with the matching '(' when
5936      * inserting new stuff.
5937      * For unknown reasons the cursor might be past the end of the line, thus
5938      * check for that.
5939      */
5940     if ((State & INSERT)
5941 	    && curwin->w_cursor.col < STRLEN(linecopy)
5942 	    && linecopy[curwin->w_cursor.col] == ')')
5943 	linecopy[curwin->w_cursor.col] = NUL;
5944 
5945     theline = skipwhite(linecopy);
5946 
5947     /* move the cursor to the start of the line */
5948 
5949     curwin->w_cursor.col = 0;
5950 
5951     /*
5952      * #defines and so on always go at the left when included in 'cinkeys'.
5953      */
5954     if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE)))
5955     {
5956 	amount = 0;
5957     }
5958 
5959     /*
5960      * Is it a non-case label?	Then that goes at the left margin too.
5961      */
5962     else if (cin_islabel(ind_maxcomment))	    /* XXX */
5963     {
5964 	amount = 0;
5965     }
5966 
5967     /*
5968      * If we're inside a "//" comment and there is a "//" comment in a
5969      * previous line, lineup with that one.
5970      */
5971     else if (cin_islinecomment(theline)
5972 	    && (trypos = find_line_comment()) != NULL) /* XXX */
5973     {
5974 	/* find how indented the line beginning the comment is */
5975 	getvcol(curwin, trypos, &col, NULL, NULL);
5976 	amount = col;
5977     }
5978 
5979     /*
5980      * If we're inside a comment and not looking at the start of the
5981      * comment, try using the 'comments' option.
5982      */
5983     else if (!cin_iscomment(theline)
5984 	    && (trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
5985     {
5986 	int	lead_start_len = 2;
5987 	int	lead_middle_len = 1;
5988 	char_u	lead_start[COM_MAX_LEN];	/* start-comment string */
5989 	char_u	lead_middle[COM_MAX_LEN];	/* middle-comment string */
5990 	char_u	lead_end[COM_MAX_LEN];		/* end-comment string */
5991 	char_u	*p;
5992 	int	start_align = 0;
5993 	int	start_off = 0;
5994 	int	done = FALSE;
5995 
5996 	/* find how indented the line beginning the comment is */
5997 	getvcol(curwin, trypos, &col, NULL, NULL);
5998 	amount = col;
5999 
6000 	p = curbuf->b_p_com;
6001 	while (*p != NUL)
6002 	{
6003 	    int	align = 0;
6004 	    int	off = 0;
6005 	    int what = 0;
6006 
6007 	    while (*p != NUL && *p != ':')
6008 	    {
6009 		if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE)
6010 		    what = *p++;
6011 		else if (*p == COM_LEFT || *p == COM_RIGHT)
6012 		    align = *p++;
6013 		else if (VIM_ISDIGIT(*p) || *p == '-')
6014 		    off = getdigits(&p);
6015 		else
6016 		    ++p;
6017 	    }
6018 
6019 	    if (*p == ':')
6020 		++p;
6021 	    (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
6022 	    if (what == COM_START)
6023 	    {
6024 		STRCPY(lead_start, lead_end);
6025 		lead_start_len = (int)STRLEN(lead_start);
6026 		start_off = off;
6027 		start_align = align;
6028 	    }
6029 	    else if (what == COM_MIDDLE)
6030 	    {
6031 		STRCPY(lead_middle, lead_end);
6032 		lead_middle_len = (int)STRLEN(lead_middle);
6033 	    }
6034 	    else if (what == COM_END)
6035 	    {
6036 		/* If our line starts with the middle comment string, line it
6037 		 * up with the comment opener per the 'comments' option. */
6038 		if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
6039 			&& STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0)
6040 		{
6041 		    done = TRUE;
6042 		    if (curwin->w_cursor.lnum > 1)
6043 		    {
6044 			/* If the start comment string matches in the previous
6045 			 * line, use the indent of that line pluss offset.  If
6046 			 * the middle comment string matches in the previous
6047 			 * line, use the indent of that line.  XXX */
6048 			look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
6049 			if (STRNCMP(look, lead_start, lead_start_len) == 0)
6050 			    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
6051 			else if (STRNCMP(look, lead_middle,
6052 							lead_middle_len) == 0)
6053 			{
6054 			    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
6055 			    break;
6056 			}
6057 			/* If the start comment string doesn't match with the
6058 			 * start of the comment, skip this entry. XXX */
6059 			else if (STRNCMP(ml_get(trypos->lnum) + trypos->col,
6060 					     lead_start, lead_start_len) != 0)
6061 			    continue;
6062 		    }
6063 		    if (start_off != 0)
6064 			amount += start_off;
6065 		    else if (start_align == COM_RIGHT)
6066 			amount += vim_strsize(lead_start)
6067 						   - vim_strsize(lead_middle);
6068 		    break;
6069 		}
6070 
6071 		/* If our line starts with the end comment string, line it up
6072 		 * with the middle comment */
6073 		if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
6074 			&& STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0)
6075 		{
6076 		    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
6077 								     /* XXX */
6078 		    if (off != 0)
6079 			amount += off;
6080 		    else if (align == COM_RIGHT)
6081 			amount += vim_strsize(lead_start)
6082 						   - vim_strsize(lead_middle);
6083 		    done = TRUE;
6084 		    break;
6085 		}
6086 	    }
6087 	}
6088 
6089 	/* If our line starts with an asterisk, line up with the
6090 	 * asterisk in the comment opener; otherwise, line up
6091 	 * with the first character of the comment text.
6092 	 */
6093 	if (done)
6094 	    ;
6095 	else if (theline[0] == '*')
6096 	    amount += 1;
6097 	else
6098 	{
6099 	    /*
6100 	     * If we are more than one line away from the comment opener, take
6101 	     * the indent of the previous non-empty line.  If 'cino' has "CO"
6102 	     * and we are just below the comment opener and there are any
6103 	     * white characters after it line up with the text after it;
6104 	     * otherwise, add the amount specified by "c" in 'cino'
6105 	     */
6106 	    amount = -1;
6107 	    for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum)
6108 	    {
6109 		if (linewhite(lnum))		    /* skip blank lines */
6110 		    continue;
6111 		amount = get_indent_lnum(lnum);	    /* XXX */
6112 		break;
6113 	    }
6114 	    if (amount == -1)			    /* use the comment opener */
6115 	    {
6116 		if (!ind_in_comment2)
6117 		{
6118 		    start = ml_get(trypos->lnum);
6119 		    look = start + trypos->col + 2; /* skip / and * */
6120 		    if (*look != NUL)		    /* if something after it */
6121 			trypos->col = (colnr_T)(skipwhite(look) - start);
6122 		}
6123 		getvcol(curwin, trypos, &col, NULL, NULL);
6124 		amount = col;
6125 		if (ind_in_comment2 || *look == NUL)
6126 		    amount += ind_in_comment;
6127 	    }
6128 	}
6129     }
6130 
6131     /*
6132      * Are we inside parentheses or braces?
6133      */						    /* XXX */
6134     else if (((trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL
6135 		&& ind_java == 0)
6136 	    || (tryposBrace = find_start_brace(ind_maxcomment)) != NULL
6137 	    || trypos != NULL)
6138     {
6139       if (trypos != NULL && tryposBrace != NULL)
6140       {
6141 	  /* Both an unmatched '(' and '{' is found.  Use the one which is
6142 	   * closer to the current cursor position, set the other to NULL. */
6143 	  if (trypos->lnum != tryposBrace->lnum
6144 		  ? trypos->lnum < tryposBrace->lnum
6145 		  : trypos->col < tryposBrace->col)
6146 	      trypos = NULL;
6147 	  else
6148 	      tryposBrace = NULL;
6149       }
6150 
6151       if (trypos != NULL)
6152       {
6153 	/*
6154 	 * If the matching paren is more than one line away, use the indent of
6155 	 * a previous non-empty line that matches the same paren.
6156 	 */
6157 	amount = -1;
6158 	cur_amount = MAXCOL;
6159 	our_paren_pos = *trypos;
6160 	for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
6161 	{
6162 	    l = skipwhite(ml_get(lnum));
6163 	    if (cin_nocode(l))		/* skip comment lines */
6164 		continue;
6165 	    if (cin_ispreproc_cont(&l, &lnum))	/* ignore #defines, #if, etc. */
6166 		continue;
6167 	    curwin->w_cursor.lnum = lnum;
6168 
6169 	    /* Skip a comment. XXX */
6170 	    if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
6171 	    {
6172 		lnum = trypos->lnum + 1;
6173 		continue;
6174 	    }
6175 
6176 	    /* XXX */
6177 	    if ((trypos = find_match_paren(
6178 			    corr_ind_maxparen(ind_maxparen, &cur_curpos),
6179 						      ind_maxcomment)) != NULL
6180 		    && trypos->lnum == our_paren_pos.lnum
6181 		    && trypos->col == our_paren_pos.col)
6182 	    {
6183 		    amount = get_indent_lnum(lnum);	/* XXX */
6184 
6185 		    if (theline[0] == ')')
6186 		    {
6187 			if (our_paren_pos.lnum != lnum && cur_amount > amount)
6188 			    cur_amount = amount;
6189 			amount = -1;
6190 		    }
6191 		break;
6192 	    }
6193 	}
6194 
6195 	/*
6196 	 * Line up with line where the matching paren is. XXX
6197 	 * If the line starts with a '(' or the indent for unclosed
6198 	 * parentheses is zero, line up with the unclosed parentheses.
6199 	 */
6200 	if (amount == -1)
6201 	{
6202 	    amount = skip_label(our_paren_pos.lnum, &look, ind_maxcomment);
6203 	    if (theline[0] == ')' || ind_unclosed == 0
6204 		       || (!ind_unclosed_noignore && *skipwhite(look) == '('))
6205 	    {
6206 		/*
6207 		 * If we're looking at a close paren, line up right there;
6208 		 * otherwise, line up with the next (non-white) character.
6209 		 * When ind_unclosed_wrapped is set and the matching paren is
6210 		 * the last nonwhite character of the line, use either the
6211 		 * indent of the current line or the indentation of the next
6212 		 * outer paren and add ind_unclosed_wrapped (for very long
6213 		 * lines).
6214 		 */
6215 		if (theline[0] != ')')
6216 		{
6217 		    cur_amount = MAXCOL;
6218 		    l = ml_get(our_paren_pos.lnum);
6219 		    if (ind_unclosed_wrapped
6220 				       && cin_ends_in(l, (char_u *)"(", NULL))
6221 		    {
6222 			/* look for opening unmatched paren, indent one level
6223 			 * for each additional level */
6224 			n = 1;
6225 			for (col = 0; col < our_paren_pos.col; ++col)
6226 			{
6227 			    switch (l[col])
6228 			    {
6229 				case '(':
6230 				case '{': ++n;
6231 					  break;
6232 
6233 				case ')':
6234 				case '}': if (n > 1)
6235 					      --n;
6236 					  break;
6237 			    }
6238 			}
6239 
6240 			our_paren_pos.col = 0;
6241 			amount += n * ind_unclosed_wrapped;
6242 		    }
6243 		    else if (ind_unclosed_whiteok)
6244 			our_paren_pos.col++;
6245 		    else
6246 		    {
6247 			col = our_paren_pos.col + 1;
6248 			while (vim_iswhite(l[col]))
6249 			    col++;
6250 			if (l[col] != NUL)	/* In case of trailing space */
6251 			    our_paren_pos.col = col;
6252 			else
6253 			    our_paren_pos.col++;
6254 		    }
6255 		}
6256 
6257 		/*
6258 		 * Find how indented the paren is, or the character after it
6259 		 * if we did the above "if".
6260 		 */
6261 		if (our_paren_pos.col > 0)
6262 		{
6263 		    getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
6264 		    if (cur_amount > (int)col)
6265 			cur_amount = col;
6266 		}
6267 	    }
6268 
6269 	    if (theline[0] == ')' && ind_matching_paren)
6270 	    {
6271 		/* Line up with the start of the matching paren line. */
6272 	    }
6273 	    else if (ind_unclosed == 0 || (!ind_unclosed_noignore
6274 						  && *skipwhite(look) == '('))
6275 	    {
6276 		if (cur_amount != MAXCOL)
6277 		    amount = cur_amount;
6278 	    }
6279 	    else
6280 	    {
6281 		/* add ind_unclosed2 for each '(' before our matching one */
6282 		col = our_paren_pos.col;
6283 		while (our_paren_pos.col > 0)
6284 		{
6285 		    --our_paren_pos.col;
6286 		    switch (*ml_get_pos(&our_paren_pos))
6287 		    {
6288 			case '(': amount += ind_unclosed2;
6289 				  col = our_paren_pos.col;
6290 				  break;
6291 			case ')': amount -= ind_unclosed2;
6292 				  col = MAXCOL;
6293 				  break;
6294 		    }
6295 		}
6296 
6297 		/* Use ind_unclosed once, when the first '(' is not inside
6298 		 * braces */
6299 		if (col == MAXCOL)
6300 		    amount += ind_unclosed;
6301 		else
6302 		{
6303 		    curwin->w_cursor.lnum = our_paren_pos.lnum;
6304 		    curwin->w_cursor.col = col;
6305 		    if ((trypos = find_match_paren(ind_maxparen,
6306 						     ind_maxcomment)) != NULL)
6307 			amount += ind_unclosed2;
6308 		    else
6309 			amount += ind_unclosed;
6310 		}
6311 		/*
6312 		 * For a line starting with ')' use the minimum of the two
6313 		 * positions, to avoid giving it more indent than the previous
6314 		 * lines:
6315 		 *  func_long_name(		    if (x
6316 		 *	arg				    && yy
6317 		 *	)	  ^ not here	       )    ^ not here
6318 		 */
6319 		if (cur_amount < amount)
6320 		    amount = cur_amount;
6321 	    }
6322 	}
6323 
6324 	/* add extra indent for a comment */
6325 	if (cin_iscomment(theline))
6326 	    amount += ind_comment;
6327       }
6328 
6329       /*
6330        * Are we at least inside braces, then?
6331        */
6332       else
6333       {
6334 	trypos = tryposBrace;
6335 
6336 	ourscope = trypos->lnum;
6337 	start = ml_get(ourscope);
6338 
6339 	/*
6340 	 * Now figure out how indented the line is in general.
6341 	 * If the brace was at the start of the line, we use that;
6342 	 * otherwise, check out the indentation of the line as
6343 	 * a whole and then add the "imaginary indent" to that.
6344 	 */
6345 	look = skipwhite(start);
6346 	if (*look == '{')
6347 	{
6348 	    getvcol(curwin, trypos, &col, NULL, NULL);
6349 	    amount = col;
6350 	    if (*start == '{')
6351 		start_brace = BRACE_IN_COL0;
6352 	    else
6353 		start_brace = BRACE_AT_START;
6354 	}
6355 	else
6356 	{
6357 	    /*
6358 	     * that opening brace might have been on a continuation
6359 	     * line.  if so, find the start of the line.
6360 	     */
6361 	    curwin->w_cursor.lnum = ourscope;
6362 
6363 	    /*
6364 	     * position the cursor over the rightmost paren, so that
6365 	     * matching it will take us back to the start of the line.
6366 	     */
6367 	    lnum = ourscope;
6368 	    if (find_last_paren(start, '(', ')')
6369 		    && (trypos = find_match_paren(ind_maxparen,
6370 						     ind_maxcomment)) != NULL)
6371 		lnum = trypos->lnum;
6372 
6373 	    /*
6374 	     * It could have been something like
6375 	     *	   case 1: if (asdf &&
6376 	     *			ldfd) {
6377 	     *		    }
6378 	     */
6379 	    if (ind_keep_case_label && cin_iscase(skipwhite(ml_get_curline())))
6380 		amount = get_indent();
6381 	    else
6382 		amount = skip_label(lnum, &l, ind_maxcomment);
6383 
6384 	    start_brace = BRACE_AT_END;
6385 	}
6386 
6387 	/*
6388 	 * if we're looking at a closing brace, that's where
6389 	 * we want to be.  otherwise, add the amount of room
6390 	 * that an indent is supposed to be.
6391 	 */
6392 	if (theline[0] == '}')
6393 	{
6394 	    /*
6395 	     * they may want closing braces to line up with something
6396 	     * other than the open brace.  indulge them, if so.
6397 	     */
6398 	    amount += ind_close_extra;
6399 	}
6400 	else
6401 	{
6402 	    /*
6403 	     * If we're looking at an "else", try to find an "if"
6404 	     * to match it with.
6405 	     * If we're looking at a "while", try to find a "do"
6406 	     * to match it with.
6407 	     */
6408 	    lookfor = LOOKFOR_INITIAL;
6409 	    if (cin_iselse(theline))
6410 		lookfor = LOOKFOR_IF;
6411 	    else if (cin_iswhileofdo(theline, cur_curpos.lnum, ind_maxparen))
6412 								    /* XXX */
6413 		lookfor = LOOKFOR_DO;
6414 	    if (lookfor != LOOKFOR_INITIAL)
6415 	    {
6416 		curwin->w_cursor.lnum = cur_curpos.lnum;
6417 		if (find_match(lookfor, ourscope, ind_maxparen,
6418 							ind_maxcomment) == OK)
6419 		{
6420 		    amount = get_indent();	/* XXX */
6421 		    goto theend;
6422 		}
6423 	    }
6424 
6425 	    /*
6426 	     * We get here if we are not on an "while-of-do" or "else" (or
6427 	     * failed to find a matching "if").
6428 	     * Search backwards for something to line up with.
6429 	     * First set amount for when we don't find anything.
6430 	     */
6431 
6432 	    /*
6433 	     * if the '{' is  _really_ at the left margin, use the imaginary
6434 	     * location of a left-margin brace.  Otherwise, correct the
6435 	     * location for ind_open_extra.
6436 	     */
6437 
6438 	    if (start_brace == BRACE_IN_COL0)	    /* '{' is in column 0 */
6439 	    {
6440 		amount = ind_open_left_imag;
6441 	    }
6442 	    else
6443 	    {
6444 		if (start_brace == BRACE_AT_END)    /* '{' is at end of line */
6445 		    amount += ind_open_imag;
6446 		else
6447 		{
6448 		    /* Compensate for adding ind_open_extra later. */
6449 		    amount -= ind_open_extra;
6450 		    if (amount < 0)
6451 			amount = 0;
6452 		}
6453 	    }
6454 
6455 	    lookfor_break = FALSE;
6456 
6457 	    if (cin_iscase(theline))	/* it's a switch() label */
6458 	    {
6459 		lookfor = LOOKFOR_CASE;	/* find a previous switch() label */
6460 		amount += ind_case;
6461 	    }
6462 	    else if (cin_isscopedecl(theline))	/* private:, ... */
6463 	    {
6464 		lookfor = LOOKFOR_SCOPEDECL;	/* class decl is this block */
6465 		amount += ind_scopedecl;
6466 	    }
6467 	    else
6468 	    {
6469 		if (ind_case_break && cin_isbreak(theline))	/* break; ... */
6470 		    lookfor_break = TRUE;
6471 
6472 		lookfor = LOOKFOR_INITIAL;
6473 		amount += ind_level;	/* ind_level from start of block */
6474 	    }
6475 	    scope_amount = amount;
6476 	    whilelevel = 0;
6477 
6478 	    /*
6479 	     * Search backwards.  If we find something we recognize, line up
6480 	     * with that.
6481 	     *
6482 	     * if we're looking at an open brace, indent
6483 	     * the usual amount relative to the conditional
6484 	     * that opens the block.
6485 	     */
6486 	    curwin->w_cursor = cur_curpos;
6487 	    for (;;)
6488 	    {
6489 		curwin->w_cursor.lnum--;
6490 		curwin->w_cursor.col = 0;
6491 
6492 		/*
6493 		 * If we went all the way back to the start of our scope, line
6494 		 * up with it.
6495 		 */
6496 		if (curwin->w_cursor.lnum <= ourscope)
6497 		{
6498 		    /* we reached end of scope:
6499 		     * if looking for a enum or structure initialization
6500 		     * go further back:
6501 		     * if it is an initializer (enum xxx or xxx =), then
6502 		     * don't add ind_continuation, otherwise it is a variable
6503 		     * declaration:
6504 		     * int x,
6505 		     *     here; <-- add ind_continuation
6506 		     */
6507 		    if (lookfor == LOOKFOR_ENUM_OR_INIT)
6508 		    {
6509 			if (curwin->w_cursor.lnum == 0
6510 				|| curwin->w_cursor.lnum
6511 						    < ourscope - ind_maxparen)
6512 			{
6513 			    /* nothing found (abuse ind_maxparen as limit)
6514 			     * assume terminated line (i.e. a variable
6515 			     * initialization) */
6516 			    if (cont_amount > 0)
6517 				amount = cont_amount;
6518 			    else
6519 				amount += ind_continuation;
6520 			    break;
6521 			}
6522 
6523 			l = ml_get_curline();
6524 
6525 			/*
6526 			 * If we're in a comment now, skip to the start of the
6527 			 * comment.
6528 			 */
6529 			trypos = find_start_comment(ind_maxcomment);
6530 			if (trypos != NULL)
6531 			{
6532 			    curwin->w_cursor.lnum = trypos->lnum + 1;
6533 			    continue;
6534 			}
6535 
6536 			/*
6537 			 * Skip preprocessor directives and blank lines.
6538 			 */
6539 			if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
6540 			    continue;
6541 
6542 			if (cin_nocode(l))
6543 			    continue;
6544 
6545 			terminated = cin_isterminated(l, FALSE, TRUE);
6546 
6547 			/*
6548 			 * If we are at top level and the line looks like a
6549 			 * function declaration, we are done
6550 			 * (it's a variable declaration).
6551 			 */
6552 			if (start_brace != BRACE_IN_COL0
6553 				|| !cin_isfuncdecl(&l, curwin->w_cursor.lnum))
6554 			{
6555 			    /* if the line is terminated with another ','
6556 			     * it is a continued variable initialization.
6557 			     * don't add extra indent.
6558 			     * TODO: does not work, if  a function
6559 			     * declaration is split over multiple lines:
6560 			     * cin_isfuncdecl returns FALSE then.
6561 			     */
6562 			    if (terminated == ',')
6563 				break;
6564 
6565 			    /* if it es a enum declaration or an assignment,
6566 			     * we are done.
6567 			     */
6568 			    if (terminated != ';' && cin_isinit())
6569 				break;
6570 
6571 			    /* nothing useful found */
6572 			    if (terminated == 0 || terminated == '{')
6573 				continue;
6574 			}
6575 
6576 			if (terminated != ';')
6577 			{
6578 			    /* Skip parens and braces. Position the cursor
6579 			     * over the rightmost paren, so that matching it
6580 			     * will take us back to the start of the line.
6581 			     */					/* XXX */
6582 			    trypos = NULL;
6583 			    if (find_last_paren(l, '(', ')'))
6584 				trypos = find_match_paren(ind_maxparen,
6585 					ind_maxcomment);
6586 
6587 			    if (trypos == NULL && find_last_paren(l, '{', '}'))
6588 				trypos = find_start_brace(ind_maxcomment);
6589 
6590 			    if (trypos != NULL)
6591 			    {
6592 				curwin->w_cursor.lnum = trypos->lnum + 1;
6593 				continue;
6594 			    }
6595 			}
6596 
6597 			/* it's a variable declaration, add indentation
6598 			 * like in
6599 			 * int a,
6600 			 *    b;
6601 			 */
6602 			if (cont_amount > 0)
6603 			    amount = cont_amount;
6604 			else
6605 			    amount += ind_continuation;
6606 		    }
6607 		    else if (lookfor == LOOKFOR_UNTERM)
6608 		    {
6609 			if (cont_amount > 0)
6610 			    amount = cont_amount;
6611 			else
6612 			    amount += ind_continuation;
6613 		    }
6614 		    else if (lookfor != LOOKFOR_TERM
6615 					  && lookfor != LOOKFOR_CPP_BASECLASS)
6616 		    {
6617 			amount = scope_amount;
6618 			if (theline[0] == '{')
6619 			    amount += ind_open_extra;
6620 		    }
6621 		    break;
6622 		}
6623 
6624 		/*
6625 		 * If we're in a comment now, skip to the start of the comment.
6626 		 */					    /* XXX */
6627 		if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
6628 		{
6629 		    curwin->w_cursor.lnum = trypos->lnum + 1;
6630 		    continue;
6631 		}
6632 
6633 		l = ml_get_curline();
6634 
6635 		/*
6636 		 * If this is a switch() label, may line up relative to that.
6637 		 * if this is a C++ scope declaration, do the same.
6638 		 */
6639 		iscase = cin_iscase(l);
6640 		if (iscase || cin_isscopedecl(l))
6641 		{
6642 		    /* we are only looking for cpp base class
6643 		     * declaration/initialization any longer */
6644 		    if (lookfor == LOOKFOR_CPP_BASECLASS)
6645 			break;
6646 
6647 		    /* When looking for a "do" we are not interested in
6648 		     * labels. */
6649 		    if (whilelevel > 0)
6650 			continue;
6651 
6652 		    /*
6653 		     *	case xx:
6654 		     *	    c = 99 +	    <- this indent plus continuation
6655 		     *->	   here;
6656 		     */
6657 		    if (lookfor == LOOKFOR_UNTERM
6658 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
6659 		    {
6660 			if (cont_amount > 0)
6661 			    amount = cont_amount;
6662 			else
6663 			    amount += ind_continuation;
6664 			break;
6665 		    }
6666 
6667 		    /*
6668 		     *	case xx:	<- line up with this case
6669 		     *	    x = 333;
6670 		     *	case yy:
6671 		     */
6672 		    if (       (iscase && lookfor == LOOKFOR_CASE)
6673 			    || (iscase && lookfor_break)
6674 			    || (!iscase && lookfor == LOOKFOR_SCOPEDECL))
6675 		    {
6676 			/*
6677 			 * Check that this case label is not for another
6678 			 * switch()
6679 			 */				    /* XXX */
6680 			if ((trypos = find_start_brace(ind_maxcomment)) ==
6681 					     NULL || trypos->lnum == ourscope)
6682 			{
6683 			    amount = get_indent();	/* XXX */
6684 			    break;
6685 			}
6686 			continue;
6687 		    }
6688 
6689 		    n = get_indent_nolabel(curwin->w_cursor.lnum);  /* XXX */
6690 
6691 		    /*
6692 		     *	 case xx: if (cond)	    <- line up with this if
6693 		     *		      y = y + 1;
6694 		     * ->	  s = 99;
6695 		     *
6696 		     *	 case xx:
6697 		     *	     if (cond)		<- line up with this line
6698 		     *		 y = y + 1;
6699 		     * ->    s = 99;
6700 		     */
6701 		    if (lookfor == LOOKFOR_TERM)
6702 		    {
6703 			if (n)
6704 			    amount = n;
6705 
6706 			if (!lookfor_break)
6707 			    break;
6708 		    }
6709 
6710 		    /*
6711 		     *	 case xx: x = x + 1;	    <- line up with this x
6712 		     * ->	  y = y + 1;
6713 		     *
6714 		     *	 case xx: if (cond)	    <- line up with this if
6715 		     * ->	       y = y + 1;
6716 		     */
6717 		    if (n)
6718 		    {
6719 			amount = n;
6720 			l = after_label(ml_get_curline());
6721 			if (l != NULL && cin_is_cinword(l))
6722 			    amount += ind_level + ind_no_brace;
6723 			break;
6724 		    }
6725 
6726 		    /*
6727 		     * Try to get the indent of a statement before the switch
6728 		     * label.  If nothing is found, line up relative to the
6729 		     * switch label.
6730 		     *	    break;		<- may line up with this line
6731 		     *	 case xx:
6732 		     * ->   y = 1;
6733 		     */
6734 		    scope_amount = get_indent() + (iscase    /* XXX */
6735 					? ind_case_code : ind_scopedecl_code);
6736 		    lookfor = ind_case_break ? LOOKFOR_NOBREAK : LOOKFOR_ANY;
6737 		    continue;
6738 		}
6739 
6740 		/*
6741 		 * Looking for a switch() label or C++ scope declaration,
6742 		 * ignore other lines, skip {}-blocks.
6743 		 */
6744 		if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL)
6745 		{
6746 		    if (find_last_paren(l, '{', '}') && (trypos =
6747 				    find_start_brace(ind_maxcomment)) != NULL)
6748 			curwin->w_cursor.lnum = trypos->lnum + 1;
6749 		    continue;
6750 		}
6751 
6752 		/*
6753 		 * Ignore jump labels with nothing after them.
6754 		 */
6755 		if (cin_islabel(ind_maxcomment))
6756 		{
6757 		    l = after_label(ml_get_curline());
6758 		    if (l == NULL || cin_nocode(l))
6759 			continue;
6760 		}
6761 
6762 		/*
6763 		 * Ignore #defines, #if, etc.
6764 		 * Ignore comment and empty lines.
6765 		 * (need to get the line again, cin_islabel() may have
6766 		 * unlocked it)
6767 		 */
6768 		l = ml_get_curline();
6769 		if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)
6770 							     || cin_nocode(l))
6771 		    continue;
6772 
6773 		/*
6774 		 * Are we at the start of a cpp base class declaration or
6775 		 * constructor initialization?
6776 		 */						    /* XXX */
6777 		if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass
6778 					     && cin_is_cpp_baseclass(l, &col))
6779 		{
6780 		    if (lookfor == LOOKFOR_UNTERM)
6781 		    {
6782 			if (cont_amount > 0)
6783 			    amount = cont_amount;
6784 			else
6785 			    amount += ind_continuation;
6786 		    }
6787 		    else if (col == 0 || theline[0] == '{')
6788 		    {
6789 			amount = get_indent();
6790 			if (find_last_paren(l, '(', ')')
6791 				&& (trypos = find_match_paren(ind_maxparen,
6792 					ind_maxcomment)) != NULL)
6793 			    amount = get_indent_lnum(trypos->lnum); /* XXX */
6794 			if (theline[0] != '{')
6795 			    amount += ind_cpp_baseclass;
6796 		    }
6797 		    else
6798 		    {
6799 			curwin->w_cursor.col = col;
6800 			getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
6801 			amount = (int)col;
6802 		    }
6803 		    break;
6804 		}
6805 		else if (lookfor == LOOKFOR_CPP_BASECLASS)
6806 		{
6807 		    /* only look, whether there is a cpp base class
6808 		     * declaration or initialization before the opening brace. */
6809 		    if (cin_isterminated(l, TRUE, FALSE))
6810 			break;
6811 		    else
6812 			continue;
6813 		}
6814 
6815 		/*
6816 		 * What happens next depends on the line being terminated.
6817 		 * If terminated with a ',' only consider it terminating if
6818 		 * there is anoter unterminated statement behind, eg:
6819 		 *   123,
6820 		 *   sizeof
6821 		 *	  here
6822 		 * Otherwise check whether it is a enumeration or structure
6823 		 * initialisation (not indented) or a variable declaration
6824 		 * (indented).
6825 		 */
6826 		terminated = cin_isterminated(l, FALSE, TRUE);
6827 
6828 		if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
6829 							&& terminated == ','))
6830 		{
6831 		    /*
6832 		     * if we're in the middle of a paren thing,
6833 		     * go back to the line that starts it so
6834 		     * we can get the right prevailing indent
6835 		     *	   if ( foo &&
6836 		     *		    bar )
6837 		     */
6838 		    /*
6839 		     * position the cursor over the rightmost paren, so that
6840 		     * matching it will take us back to the start of the line.
6841 		     */
6842 		    (void)find_last_paren(l, '(', ')');
6843 		    trypos = find_match_paren(
6844 				 corr_ind_maxparen(ind_maxparen, &cur_curpos),
6845 							      ind_maxcomment);
6846 
6847 		    /*
6848 		     * If we are looking for ',', we also look for matching
6849 		     * braces.
6850 		     */
6851 		    if (trypos == NULL && find_last_paren(l, '{', '}'))
6852 			trypos = find_start_brace(ind_maxcomment);
6853 
6854 		    if (trypos != NULL)
6855 		    {
6856 			/*
6857 			 * Check if we are on a case label now.  This is
6858 			 * handled above.
6859 			 *     case xx:  if ( asdf &&
6860 			 *			asdf)
6861 			 */
6862 			curwin->w_cursor.lnum = trypos->lnum;
6863 			l = ml_get_curline();
6864 			if (cin_iscase(l) || cin_isscopedecl(l))
6865 			{
6866 			    ++curwin->w_cursor.lnum;
6867 			    continue;
6868 			}
6869 		    }
6870 
6871 		    /*
6872 		     * Skip over continuation lines to find the one to get the
6873 		     * indent from
6874 		     * char *usethis = "bla\
6875 		     *		 bla",
6876 		     *      here;
6877 		     */
6878 		    if (terminated == ',')
6879 		    {
6880 			while (curwin->w_cursor.lnum > 1)
6881 			{
6882 			    l = ml_get(curwin->w_cursor.lnum - 1);
6883 			    if (*l == NUL || l[STRLEN(l) - 1] != '\\')
6884 				break;
6885 			    --curwin->w_cursor.lnum;
6886 			}
6887 		    }
6888 
6889 		    /*
6890 		     * Get indent and pointer to text for current line,
6891 		     * ignoring any jump label.	    XXX
6892 		     */
6893 		    cur_amount = skip_label(curwin->w_cursor.lnum,
6894 							  &l, ind_maxcomment);
6895 
6896 		    /*
6897 		     * If this is just above the line we are indenting, and it
6898 		     * starts with a '{', line it up with this line.
6899 		     *		while (not)
6900 		     * ->	{
6901 		     *		}
6902 		     */
6903 		    if (terminated != ',' && lookfor != LOOKFOR_TERM
6904 							 && theline[0] == '{')
6905 		    {
6906 			amount = cur_amount;
6907 			/*
6908 			 * Only add ind_open_extra when the current line
6909 			 * doesn't start with a '{', which must have a match
6910 			 * in the same line (scope is the same).  Probably:
6911 			 *	{ 1, 2 },
6912 			 * ->	{ 3, 4 }
6913 			 */
6914 			if (*skipwhite(l) != '{')
6915 			    amount += ind_open_extra;
6916 
6917 			if (ind_cpp_baseclass)
6918 			{
6919 			    /* have to look back, whether it is a cpp base
6920 			     * class declaration or initialization */
6921 			    lookfor = LOOKFOR_CPP_BASECLASS;
6922 			    continue;
6923 			}
6924 			break;
6925 		    }
6926 
6927 		    /*
6928 		     * Check if we are after an "if", "while", etc.
6929 		     * Also allow "   } else".
6930 		     */
6931 		    if (cin_is_cinword(l) || cin_iselse(skipwhite(l)))
6932 		    {
6933 			/*
6934 			 * Found an unterminated line after an if (), line up
6935 			 * with the last one.
6936 			 *   if (cond)
6937 			 *	    100 +
6938 			 * ->		here;
6939 			 */
6940 			if (lookfor == LOOKFOR_UNTERM
6941 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
6942 			{
6943 			    if (cont_amount > 0)
6944 				amount = cont_amount;
6945 			    else
6946 				amount += ind_continuation;
6947 			    break;
6948 			}
6949 
6950 			/*
6951 			 * If this is just above the line we are indenting, we
6952 			 * are finished.
6953 			 *	    while (not)
6954 			 * ->		here;
6955 			 * Otherwise this indent can be used when the line
6956 			 * before this is terminated.
6957 			 *	yyy;
6958 			 *	if (stat)
6959 			 *	    while (not)
6960 			 *		xxx;
6961 			 * ->	here;
6962 			 */
6963 			amount = cur_amount;
6964 			if (theline[0] == '{')
6965 			    amount += ind_open_extra;
6966 			if (lookfor != LOOKFOR_TERM)
6967 			{
6968 			    amount += ind_level + ind_no_brace;
6969 			    break;
6970 			}
6971 
6972 			/*
6973 			 * Special trick: when expecting the while () after a
6974 			 * do, line up with the while()
6975 			 *     do
6976 			 *	    x = 1;
6977 			 * ->  here
6978 			 */
6979 			l = skipwhite(ml_get_curline());
6980 			if (cin_isdo(l))
6981 			{
6982 			    if (whilelevel == 0)
6983 				break;
6984 			    --whilelevel;
6985 			}
6986 
6987 			/*
6988 			 * When searching for a terminated line, don't use the
6989 			 * one between the "if" and the "else".
6990 			 * Need to use the scope of this "else".  XXX
6991 			 * If whilelevel != 0 continue looking for a "do {".
6992 			 */
6993 			if (cin_iselse(l)
6994 				&& whilelevel == 0
6995 				&& ((trypos = find_start_brace(ind_maxcomment))
6996 								    == NULL
6997 				    || find_match(LOOKFOR_IF, trypos->lnum,
6998 					ind_maxparen, ind_maxcomment) == FAIL))
6999 			    break;
7000 		    }
7001 
7002 		    /*
7003 		     * If we're below an unterminated line that is not an
7004 		     * "if" or something, we may line up with this line or
7005 		     * add someting for a continuation line, depending on
7006 		     * the line before this one.
7007 		     */
7008 		    else
7009 		    {
7010 			/*
7011 			 * Found two unterminated lines on a row, line up with
7012 			 * the last one.
7013 			 *   c = 99 +
7014 			 *	    100 +
7015 			 * ->	    here;
7016 			 */
7017 			if (lookfor == LOOKFOR_UNTERM)
7018 			{
7019 			    /* When line ends in a comma add extra indent */
7020 			    if (terminated == ',')
7021 				amount += ind_continuation;
7022 			    break;
7023 			}
7024 
7025 			if (lookfor == LOOKFOR_ENUM_OR_INIT)
7026 			{
7027 			    /* Found two lines ending in ',', lineup with the
7028 			     * lowest one, but check for cpp base class
7029 			     * declaration/initialization, if it is an
7030 			     * opening brace or we are looking just for
7031 			     * enumerations/initializations. */
7032 			    if (terminated == ',')
7033 			    {
7034 				if (ind_cpp_baseclass == 0)
7035 				    break;
7036 
7037 				lookfor = LOOKFOR_CPP_BASECLASS;
7038 				continue;
7039 			    }
7040 
7041 			    /* Ignore unterminated lines in between, but
7042 			     * reduce indent. */
7043 			    if (amount > cur_amount)
7044 				amount = cur_amount;
7045 			}
7046 			else
7047 			{
7048 			    /*
7049 			     * Found first unterminated line on a row, may
7050 			     * line up with this line, remember its indent
7051 			     *	    100 +
7052 			     * ->	    here;
7053 			     */
7054 			    amount = cur_amount;
7055 
7056 			    /*
7057 			     * If previous line ends in ',', check whether we
7058 			     * are in an initialization or enum
7059 			     * struct xxx =
7060 			     * {
7061 			     *      sizeof a,
7062 			     *      124 };
7063 			     * or a normal possible continuation line.
7064 			     * but only, of no other statement has been found
7065 			     * yet.
7066 			     */
7067 			    if (lookfor == LOOKFOR_INITIAL && terminated == ',')
7068 			    {
7069 				lookfor = LOOKFOR_ENUM_OR_INIT;
7070 				cont_amount = cin_first_id_amount();
7071 			    }
7072 			    else
7073 			    {
7074 				if (lookfor == LOOKFOR_INITIAL
7075 					&& *l != NUL
7076 					&& l[STRLEN(l) - 1] == '\\')
7077 								/* XXX */
7078 				    cont_amount = cin_get_equal_amount(
7079 						       curwin->w_cursor.lnum);
7080 				if (lookfor != LOOKFOR_TERM)
7081 				    lookfor = LOOKFOR_UNTERM;
7082 			    }
7083 			}
7084 		    }
7085 		}
7086 
7087 		/*
7088 		 * Check if we are after a while (cond);
7089 		 * If so: Ignore until the matching "do".
7090 		 */
7091 							/* XXX */
7092 		else if (cin_iswhileofdo(l,
7093 					 curwin->w_cursor.lnum, ind_maxparen))
7094 		{
7095 		    /*
7096 		     * Found an unterminated line after a while ();, line up
7097 		     * with the last one.
7098 		     *	    while (cond);
7099 		     *	    100 +		<- line up with this one
7100 		     * ->	    here;
7101 		     */
7102 		    if (lookfor == LOOKFOR_UNTERM
7103 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
7104 		    {
7105 			if (cont_amount > 0)
7106 			    amount = cont_amount;
7107 			else
7108 			    amount += ind_continuation;
7109 			break;
7110 		    }
7111 
7112 		    if (whilelevel == 0)
7113 		    {
7114 			lookfor = LOOKFOR_TERM;
7115 			amount = get_indent();	    /* XXX */
7116 			if (theline[0] == '{')
7117 			    amount += ind_open_extra;
7118 		    }
7119 		    ++whilelevel;
7120 		}
7121 
7122 		/*
7123 		 * We are after a "normal" statement.
7124 		 * If we had another statement we can stop now and use the
7125 		 * indent of that other statement.
7126 		 * Otherwise the indent of the current statement may be used,
7127 		 * search backwards for the next "normal" statement.
7128 		 */
7129 		else
7130 		{
7131 		    /*
7132 		     * Skip single break line, if before a switch label. It
7133 		     * may be lined up with the case label.
7134 		     */
7135 		    if (lookfor == LOOKFOR_NOBREAK
7136 				  && cin_isbreak(skipwhite(ml_get_curline())))
7137 		    {
7138 			lookfor = LOOKFOR_ANY;
7139 			continue;
7140 		    }
7141 
7142 		    /*
7143 		     * Handle "do {" line.
7144 		     */
7145 		    if (whilelevel > 0)
7146 		    {
7147 			l = cin_skipcomment(ml_get_curline());
7148 			if (cin_isdo(l))
7149 			{
7150 			    amount = get_indent();	/* XXX */
7151 			    --whilelevel;
7152 			    continue;
7153 			}
7154 		    }
7155 
7156 		    /*
7157 		     * Found a terminated line above an unterminated line. Add
7158 		     * the amount for a continuation line.
7159 		     *	 x = 1;
7160 		     *	 y = foo +
7161 		     * ->	here;
7162 		     * or
7163 		     *	 int x = 1;
7164 		     *	 int foo,
7165 		     * ->	here;
7166 		     */
7167 		    if (lookfor == LOOKFOR_UNTERM
7168 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
7169 		    {
7170 			if (cont_amount > 0)
7171 			    amount = cont_amount;
7172 			else
7173 			    amount += ind_continuation;
7174 			break;
7175 		    }
7176 
7177 		    /*
7178 		     * Found a terminated line above a terminated line or "if"
7179 		     * etc. line. Use the amount of the line below us.
7180 		     *	 x = 1;				x = 1;
7181 		     *	 if (asdf)		    y = 2;
7182 		     *	     while (asdf)	  ->here;
7183 		     *		here;
7184 		     * ->foo;
7185 		     */
7186 		    if (lookfor == LOOKFOR_TERM)
7187 		    {
7188 			if (!lookfor_break && whilelevel == 0)
7189 			    break;
7190 		    }
7191 
7192 		    /*
7193 		     * First line above the one we're indenting is terminated.
7194 		     * To know what needs to be done look further backward for
7195 		     * a terminated line.
7196 		     */
7197 		    else
7198 		    {
7199 			/*
7200 			 * position the cursor over the rightmost paren, so
7201 			 * that matching it will take us back to the start of
7202 			 * the line.  Helps for:
7203 			 *     func(asdr,
7204 			 *	      asdfasdf);
7205 			 *     here;
7206 			 */
7207 term_again:
7208 			l = ml_get_curline();
7209 			if (find_last_paren(l, '(', ')')
7210 				&& (trypos = find_match_paren(ind_maxparen,
7211 						     ind_maxcomment)) != NULL)
7212 			{
7213 			    /*
7214 			     * Check if we are on a case label now.  This is
7215 			     * handled above.
7216 			     *	   case xx:  if ( asdf &&
7217 			     *			    asdf)
7218 			     */
7219 			    curwin->w_cursor.lnum = trypos->lnum;
7220 			    l = ml_get_curline();
7221 			    if (cin_iscase(l) || cin_isscopedecl(l))
7222 			    {
7223 				++curwin->w_cursor.lnum;
7224 				continue;
7225 			    }
7226 			}
7227 
7228 			/* When aligning with the case statement, don't align
7229 			 * with a statement after it.
7230 			 *  case 1: {   <-- don't use this { position
7231 			 *	stat;
7232 			 *  }
7233 			 *  case 2:
7234 			 *	stat;
7235 			 * }
7236 			 */
7237 			iscase = (ind_keep_case_label && cin_iscase(l));
7238 
7239 			/*
7240 			 * Get indent and pointer to text for current line,
7241 			 * ignoring any jump label.
7242 			 */
7243 			amount = skip_label(curwin->w_cursor.lnum,
7244 							  &l, ind_maxcomment);
7245 
7246 			if (theline[0] == '{')
7247 			    amount += ind_open_extra;
7248 			/* See remark above: "Only add ind_open_extra.." */
7249 			if (*skipwhite(l) == '{')
7250 			    amount -= ind_open_extra;
7251 			lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
7252 
7253 			/*
7254 			 * If we're at the end of a block, skip to the start of
7255 			 * that block.
7256 			 */
7257 			curwin->w_cursor.col = 0;
7258 			if (*cin_skipcomment(l) == '}'
7259 				&& (trypos = find_start_brace(ind_maxcomment))
7260 							    != NULL) /* XXX */
7261 			{
7262 			    curwin->w_cursor.lnum = trypos->lnum;
7263 			    /* if not "else {" check for terminated again */
7264 			    /* but skip block for "} else {" */
7265 			    l = cin_skipcomment(ml_get_curline());
7266 			    if (*l == '}' || !cin_iselse(l))
7267 				goto term_again;
7268 			    ++curwin->w_cursor.lnum;
7269 			}
7270 		    }
7271 		}
7272 	    }
7273 	}
7274       }
7275 
7276       /* add extra indent for a comment */
7277       if (cin_iscomment(theline))
7278 	  amount += ind_comment;
7279     }
7280 
7281     /*
7282      * ok -- we're not inside any sort of structure at all!
7283      *
7284      * this means we're at the top level, and everything should
7285      * basically just match where the previous line is, except
7286      * for the lines immediately following a function declaration,
7287      * which are K&R-style parameters and need to be indented.
7288      */
7289     else
7290     {
7291 	/*
7292 	 * if our line starts with an open brace, forget about any
7293 	 * prevailing indent and make sure it looks like the start
7294 	 * of a function
7295 	 */
7296 
7297 	if (theline[0] == '{')
7298 	{
7299 	    amount = ind_first_open;
7300 	}
7301 
7302 	/*
7303 	 * If the NEXT line is a function declaration, the current
7304 	 * line needs to be indented as a function type spec.
7305 	 * Don't do this if the current line looks like a comment
7306 	 * or if the current line is terminated, ie. ends in ';'.
7307 	 */
7308 	else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count
7309 		&& !cin_nocode(theline)
7310 		&& !cin_ends_in(theline, (char_u *)":", NULL)
7311 		&& !cin_ends_in(theline, (char_u *)",", NULL)
7312 		&& cin_isfuncdecl(NULL, cur_curpos.lnum + 1)
7313 		&& !cin_isterminated(theline, FALSE, TRUE))
7314 	{
7315 	    amount = ind_func_type;
7316 	}
7317 	else
7318 	{
7319 	    amount = 0;
7320 	    curwin->w_cursor = cur_curpos;
7321 
7322 	    /* search backwards until we find something we recognize */
7323 
7324 	    while (curwin->w_cursor.lnum > 1)
7325 	    {
7326 		curwin->w_cursor.lnum--;
7327 		curwin->w_cursor.col = 0;
7328 
7329 		l = ml_get_curline();
7330 
7331 		/*
7332 		 * If we're in a comment now, skip to the start of the comment.
7333 		 */						/* XXX */
7334 		if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
7335 		{
7336 		    curwin->w_cursor.lnum = trypos->lnum + 1;
7337 		    continue;
7338 		}
7339 
7340 		/*
7341 		 * Are we at the start of a cpp base class declaration or constructor
7342 		 * initialization?
7343 		 */						    /* XXX */
7344 		if (ind_cpp_baseclass != 0 && theline[0] != '{'
7345 					     && cin_is_cpp_baseclass(l, &col))
7346 		{
7347 		    if (col == 0)
7348 		    {
7349 			amount = get_indent() + ind_cpp_baseclass;  /* XXX */
7350 			if (find_last_paren(l, '(', ')')
7351 				&& (trypos = find_match_paren(ind_maxparen,
7352 					ind_maxcomment)) != NULL)
7353 			    amount = get_indent_lnum(trypos->lnum)
7354 					   + ind_cpp_baseclass;	    /* XXX */
7355 		    }
7356 		    else
7357 		    {
7358 			curwin->w_cursor.col = col;
7359 			getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
7360 			amount = (int)col;
7361 		    }
7362 		    break;
7363 		}
7364 
7365 		/*
7366 		 * Skip preprocessor directives and blank lines.
7367 		 */
7368 		if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
7369 		    continue;
7370 
7371 		if (cin_nocode(l))
7372 		    continue;
7373 
7374 		/*
7375 		 * If the previous line ends in ',', use one level of
7376 		 * indentation:
7377 		 * int foo,
7378 		 *     bar;
7379 		 * do this before checking for '}' in case of eg.
7380 		 * enum foobar
7381 		 * {
7382 		 *   ...
7383 		 * } foo,
7384 		 *   bar;
7385 		 */
7386 		n = 0;
7387 		if (cin_ends_in(l, (char_u *)",", NULL)
7388 			     || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
7389 		{
7390 		    /* take us back to opening paren */
7391 		    if (find_last_paren(l, '(', ')')
7392 			    && (trypos = find_match_paren(ind_maxparen,
7393 						     ind_maxcomment)) != NULL)
7394 			curwin->w_cursor.lnum = trypos->lnum;
7395 
7396 		    /* For a line ending in ',' that is a continuation line go
7397 		     * back to the first line with a backslash:
7398 		     * char *foo = "bla\
7399 		     *		 bla",
7400 		     *      here;
7401 		     */
7402 		    while (n == 0 && curwin->w_cursor.lnum > 1)
7403 		    {
7404 			l = ml_get(curwin->w_cursor.lnum - 1);
7405 			if (*l == NUL || l[STRLEN(l) - 1] != '\\')
7406 			    break;
7407 			--curwin->w_cursor.lnum;
7408 		    }
7409 
7410 		    amount = get_indent();	    /* XXX */
7411 
7412 		    if (amount == 0)
7413 			amount = cin_first_id_amount();
7414 		    if (amount == 0)
7415 			amount = ind_continuation;
7416 		    break;
7417 		}
7418 
7419 		/*
7420 		 * If the line looks like a function declaration, and we're
7421 		 * not in a comment, put it the left margin.
7422 		 */
7423 		if (cin_isfuncdecl(NULL, cur_curpos.lnum))  /* XXX */
7424 		    break;
7425 		l = ml_get_curline();
7426 
7427 		/*
7428 		 * Finding the closing '}' of a previous function.  Put
7429 		 * current line at the left margin.  For when 'cino' has "fs".
7430 		 */
7431 		if (*skipwhite(l) == '}')
7432 		    break;
7433 
7434 		/*			    (matching {)
7435 		 * If the previous line ends on '};' (maybe followed by
7436 		 * comments) align at column 0.  For example:
7437 		 * char *string_array[] = { "foo",
7438 		 *     / * x * / "b};ar" }; / * foobar * /
7439 		 */
7440 		if (cin_ends_in(l, (char_u *)"};", NULL))
7441 		    break;
7442 
7443 		/*
7444 		 * If the PREVIOUS line is a function declaration, the current
7445 		 * line (and the ones that follow) needs to be indented as
7446 		 * parameters.
7447 		 */
7448 		if (cin_isfuncdecl(&l, curwin->w_cursor.lnum))
7449 		{
7450 		    amount = ind_param;
7451 		    break;
7452 		}
7453 
7454 		/*
7455 		 * If the previous line ends in ';' and the line before the
7456 		 * previous line ends in ',' or '\', ident to column zero:
7457 		 * int foo,
7458 		 *     bar;
7459 		 * indent_to_0 here;
7460 		 */
7461 		if (cin_ends_in(l, (char_u*)";", NULL))
7462 		{
7463 		    l = ml_get(curwin->w_cursor.lnum - 1);
7464 		    if (cin_ends_in(l, (char_u *)",", NULL)
7465 			    || (*l != NUL && l[STRLEN(l) - 1] == '\\'))
7466 			break;
7467 		    l = ml_get_curline();
7468 		}
7469 
7470 		/*
7471 		 * Doesn't look like anything interesting -- so just
7472 		 * use the indent of this line.
7473 		 *
7474 		 * Position the cursor over the rightmost paren, so that
7475 		 * matching it will take us back to the start of the line.
7476 		 */
7477 		find_last_paren(l, '(', ')');
7478 
7479 		if ((trypos = find_match_paren(ind_maxparen,
7480 						     ind_maxcomment)) != NULL)
7481 		    curwin->w_cursor.lnum = trypos->lnum;
7482 		amount = get_indent();	    /* XXX */
7483 		break;
7484 	    }
7485 
7486 	    /* add extra indent for a comment */
7487 	    if (cin_iscomment(theline))
7488 		amount += ind_comment;
7489 
7490 	    /* add extra indent if the previous line ended in a backslash:
7491 	     *	      "asdfasdf\
7492 	     *		  here";
7493 	     *	    char *foo = "asdf\
7494 	     *			 here";
7495 	     */
7496 	    if (cur_curpos.lnum > 1)
7497 	    {
7498 		l = ml_get(cur_curpos.lnum - 1);
7499 		if (*l != NUL && l[STRLEN(l) - 1] == '\\')
7500 		{
7501 		    cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
7502 		    if (cur_amount > 0)
7503 			amount = cur_amount;
7504 		    else if (cur_amount == 0)
7505 			amount += ind_continuation;
7506 		}
7507 	    }
7508 	}
7509     }
7510 
7511 theend:
7512     /* put the cursor back where it belongs */
7513     curwin->w_cursor = cur_curpos;
7514 
7515     vim_free(linecopy);
7516 
7517     if (amount < 0)
7518 	return 0;
7519     return amount;
7520 }
7521 
7522     static int
7523 find_match(lookfor, ourscope, ind_maxparen, ind_maxcomment)
7524     int		lookfor;
7525     linenr_T	ourscope;
7526     int		ind_maxparen;
7527     int		ind_maxcomment;
7528 {
7529     char_u	*look;
7530     pos_T	*theirscope;
7531     char_u	*mightbeif;
7532     int		elselevel;
7533     int		whilelevel;
7534 
7535     if (lookfor == LOOKFOR_IF)
7536     {
7537 	elselevel = 1;
7538 	whilelevel = 0;
7539     }
7540     else
7541     {
7542 	elselevel = 0;
7543 	whilelevel = 1;
7544     }
7545 
7546     curwin->w_cursor.col = 0;
7547 
7548     while (curwin->w_cursor.lnum > ourscope + 1)
7549     {
7550 	curwin->w_cursor.lnum--;
7551 	curwin->w_cursor.col = 0;
7552 
7553 	look = cin_skipcomment(ml_get_curline());
7554 	if (cin_iselse(look)
7555 		|| cin_isif(look)
7556 		|| cin_isdo(look)			    /* XXX */
7557 		|| cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))
7558 	{
7559 	    /*
7560 	     * if we've gone outside the braces entirely,
7561 	     * we must be out of scope...
7562 	     */
7563 	    theirscope = find_start_brace(ind_maxcomment);  /* XXX */
7564 	    if (theirscope == NULL)
7565 		break;
7566 
7567 	    /*
7568 	     * and if the brace enclosing this is further
7569 	     * back than the one enclosing the else, we're
7570 	     * out of luck too.
7571 	     */
7572 	    if (theirscope->lnum < ourscope)
7573 		break;
7574 
7575 	    /*
7576 	     * and if they're enclosed in a *deeper* brace,
7577 	     * then we can ignore it because it's in a
7578 	     * different scope...
7579 	     */
7580 	    if (theirscope->lnum > ourscope)
7581 		continue;
7582 
7583 	    /*
7584 	     * if it was an "else" (that's not an "else if")
7585 	     * then we need to go back to another if, so
7586 	     * increment elselevel
7587 	     */
7588 	    look = cin_skipcomment(ml_get_curline());
7589 	    if (cin_iselse(look))
7590 	    {
7591 		mightbeif = cin_skipcomment(look + 4);
7592 		if (!cin_isif(mightbeif))
7593 		    ++elselevel;
7594 		continue;
7595 	    }
7596 
7597 	    /*
7598 	     * if it was a "while" then we need to go back to
7599 	     * another "do", so increment whilelevel.  XXX
7600 	     */
7601 	    if (cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen))
7602 	    {
7603 		++whilelevel;
7604 		continue;
7605 	    }
7606 
7607 	    /* If it's an "if" decrement elselevel */
7608 	    look = cin_skipcomment(ml_get_curline());
7609 	    if (cin_isif(look))
7610 	    {
7611 		elselevel--;
7612 		/*
7613 		 * When looking for an "if" ignore "while"s that
7614 		 * get in the way.
7615 		 */
7616 		if (elselevel == 0 && lookfor == LOOKFOR_IF)
7617 		    whilelevel = 0;
7618 	    }
7619 
7620 	    /* If it's a "do" decrement whilelevel */
7621 	    if (cin_isdo(look))
7622 		whilelevel--;
7623 
7624 	    /*
7625 	     * if we've used up all the elses, then
7626 	     * this must be the if that we want!
7627 	     * match the indent level of that if.
7628 	     */
7629 	    if (elselevel <= 0 && whilelevel <= 0)
7630 	    {
7631 		return OK;
7632 	    }
7633 	}
7634     }
7635     return FAIL;
7636 }
7637 
7638 # if defined(FEAT_EVAL) || defined(PROTO)
7639 /*
7640  * Get indent level from 'indentexpr'.
7641  */
7642     int
7643 get_expr_indent()
7644 {
7645     int		indent;
7646     pos_T	pos;
7647     int		save_State;
7648 
7649     pos = curwin->w_cursor;
7650     set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
7651     ++sandbox;
7652     indent = eval_to_number(curbuf->b_p_inde);
7653     --sandbox;
7654 
7655     /* Restore the cursor position so that 'indentexpr' doesn't need to.
7656      * Pretend to be in Insert mode, allow cursor past end of line for "o"
7657      * command. */
7658     save_State = State;
7659     State = INSERT;
7660     curwin->w_cursor = pos;
7661     check_cursor();
7662     State = save_State;
7663 
7664     /* If there is an error, just keep the current indent. */
7665     if (indent < 0)
7666 	indent = get_indent();
7667 
7668     return indent;
7669 }
7670 # endif
7671 
7672 #endif /* FEAT_CINDENT */
7673 
7674 #if defined(FEAT_LISP) || defined(PROTO)
7675 
7676 static int lisp_match __ARGS((char_u *p));
7677 
7678     static int
7679 lisp_match(p)
7680     char_u	*p;
7681 {
7682     char_u	buf[LSIZE];
7683     int		len;
7684     char_u	*word = p_lispwords;
7685 
7686     while (*word != NUL)
7687     {
7688 	(void)copy_option_part(&word, buf, LSIZE, ",");
7689 	len = (int)STRLEN(buf);
7690 	if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
7691 	    return TRUE;
7692     }
7693     return FALSE;
7694 }
7695 
7696 /*
7697  * When 'p' is present in 'cpoptions, a Vi compatible method is used.
7698  * The incompatible newer method is quite a bit better at indenting
7699  * code in lisp-like languages than the traditional one; it's still
7700  * mostly heuristics however -- Dirk van Deun, [email protected]
7701  *
7702  * TODO:
7703  * Findmatch() should be adapted for lisp, also to make showmatch
7704  * work correctly: now (v5.3) it seems all C/C++ oriented:
7705  * - it does not recognize the #\( and #\) notations as character literals
7706  * - it doesn't know about comments starting with a semicolon
7707  * - it incorrectly interprets '(' as a character literal
7708  * All this messes up get_lisp_indent in some rare cases.
7709  * Update from Sergey Khorev:
7710  * I tried to fix the first two issues.
7711  */
7712     int
7713 get_lisp_indent()
7714 {
7715     pos_T	*pos, realpos, paren;
7716     int		amount;
7717     char_u	*that;
7718     colnr_T	col;
7719     colnr_T	firsttry;
7720     int		parencount, quotecount;
7721     int		vi_lisp;
7722 
7723     /* Set vi_lisp to use the vi-compatible method */
7724     vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
7725 
7726     realpos = curwin->w_cursor;
7727     curwin->w_cursor.col = 0;
7728 
7729     if ((pos = findmatch(NULL, '(')) == NULL)
7730 	pos = findmatch(NULL, '[');
7731     else
7732     {
7733 	paren = *pos;
7734 	pos = findmatch(NULL, '[');
7735 	if (pos == NULL || ltp(pos, &paren))
7736 	    pos = &paren;
7737     }
7738     if (pos != NULL)
7739     {
7740 	/* Extra trick: Take the indent of the first previous non-white
7741 	 * line that is at the same () level. */
7742 	amount = -1;
7743 	parencount = 0;
7744 
7745 	while (--curwin->w_cursor.lnum >= pos->lnum)
7746 	{
7747 	    if (linewhite(curwin->w_cursor.lnum))
7748 		continue;
7749 	    for (that = ml_get_curline(); *that != NUL; ++that)
7750 	    {
7751 		if (*that == ';')
7752 		{
7753 		    while (*(that + 1) != NUL)
7754 			++that;
7755 		    continue;
7756 		}
7757 		if (*that == '\\')
7758 		{
7759 		    if (*(that + 1) != NUL)
7760 			++that;
7761 		    continue;
7762 		}
7763 		if (*that == '"' && *(that + 1) != NUL)
7764 		{
7765 		    that++;
7766 		    while (*that && (*that != '"' || *(that - 1) == '\\'))
7767 			++that;
7768 		}
7769 		if (*that == '(' || *that == '[')
7770 		    ++parencount;
7771 		else if (*that == ')' || *that == ']')
7772 		    --parencount;
7773 	    }
7774 	    if (parencount == 0)
7775 	    {
7776 		amount = get_indent();
7777 		break;
7778 	    }
7779 	}
7780 
7781 	if (amount == -1)
7782 	{
7783 	    curwin->w_cursor.lnum = pos->lnum;
7784 	    curwin->w_cursor.col = pos->col;
7785 	    col = pos->col;
7786 
7787 	    that = ml_get_curline();
7788 
7789 	    if (vi_lisp && get_indent() == 0)
7790 		amount = 2;
7791 	    else
7792 	    {
7793 		amount = 0;
7794 		while (*that && col)
7795 		{
7796 		    amount += lbr_chartabsize_adv(&that, (colnr_T)amount);
7797 		    col--;
7798 		}
7799 
7800 		/*
7801 		 * Some keywords require "body" indenting rules (the
7802 		 * non-standard-lisp ones are Scheme special forms):
7803 		 *
7804 		 * (let ((a 1))    instead    (let ((a 1))
7805 		 *   (...))	      of	   (...))
7806 		 */
7807 
7808 		if (!vi_lisp && (*that == '(' || *that == '[')
7809 						      && lisp_match(that + 1))
7810 		    amount += 2;
7811 		else
7812 		{
7813 		    that++;
7814 		    amount++;
7815 		    firsttry = amount;
7816 
7817 		    while (vim_iswhite(*that))
7818 		    {
7819 			amount += lbr_chartabsize(that, (colnr_T)amount);
7820 			++that;
7821 		    }
7822 
7823 		    if (*that && *that != ';') /* not a comment line */
7824 		    {
7825 			/* test *that != '(' to accomodate first let/do
7826 			 * argument if it is more than one line */
7827 			if (!vi_lisp && *that != '(' && *that != '[')
7828 			    firsttry++;
7829 
7830 			parencount = 0;
7831 			quotecount = 0;
7832 
7833 			if (vi_lisp
7834 				|| (*that != '"'
7835 				    && *that != '\''
7836 				    && *that != '#'
7837 				    && (*that < '0' || *that > '9')))
7838 			{
7839 			    while (*that
7840 				    && (!vim_iswhite(*that)
7841 					|| quotecount
7842 					|| parencount)
7843 				    && (!((*that == '(' || *that == '[')
7844 					    && !quotecount
7845 					    && !parencount
7846 					    && vi_lisp)))
7847 			    {
7848 				if (*that == '"')
7849 				    quotecount = !quotecount;
7850 				if ((*that == '(' || *that == '[')
7851 							       && !quotecount)
7852 				    ++parencount;
7853 				if ((*that == ')' || *that == ']')
7854 							       && !quotecount)
7855 				    --parencount;
7856 				if (*that == '\\' && *(that+1) != NUL)
7857 				    amount += lbr_chartabsize_adv(&that,
7858 							     (colnr_T)amount);
7859 				amount += lbr_chartabsize_adv(&that,
7860 							     (colnr_T)amount);
7861 			    }
7862 			}
7863 			while (vim_iswhite(*that))
7864 			{
7865 			    amount += lbr_chartabsize(that, (colnr_T)amount);
7866 			    that++;
7867 			}
7868 			if (!*that || *that == ';')
7869 			    amount = firsttry;
7870 		    }
7871 		}
7872 	    }
7873 	}
7874     }
7875     else
7876 	amount = 0;	/* no matching '(' or '[' found, use zero indent */
7877 
7878     curwin->w_cursor = realpos;
7879 
7880     return amount;
7881 }
7882 #endif /* FEAT_LISP */
7883 
7884     void
7885 prepare_to_exit()
7886 {
7887 #if defined(SIGHUP) && defined(SIG_IGN)
7888     /* Ignore SIGHUP, because a dropped connection causes a read error, which
7889      * makes Vim exit and then handling SIGHUP causes various reentrance
7890      * problems. */
7891     signal(SIGHUP, SIG_IGN);
7892 #endif
7893 
7894 #ifdef FEAT_GUI
7895     if (gui.in_use)
7896     {
7897 	gui.dying = TRUE;
7898 	out_trash();	/* trash any pending output */
7899     }
7900     else
7901 #endif
7902     {
7903 	windgoto((int)Rows - 1, 0);
7904 
7905 	/*
7906 	 * Switch terminal mode back now, so messages end up on the "normal"
7907 	 * screen (if there are two screens).
7908 	 */
7909 	settmode(TMODE_COOK);
7910 #ifdef WIN3264
7911 	if (can_end_termcap_mode(FALSE) == TRUE)
7912 #endif
7913 	    stoptermcap();
7914 	out_flush();
7915     }
7916 }
7917 
7918 /*
7919  * Preserve files and exit.
7920  * When called IObuff must contain a message.
7921  */
7922     void
7923 preserve_exit()
7924 {
7925     buf_T	*buf;
7926 
7927     prepare_to_exit();
7928 
7929     out_str(IObuff);
7930     screen_start();		    /* don't know where cursor is now */
7931     out_flush();
7932 
7933     ml_close_notmod();		    /* close all not-modified buffers */
7934 
7935     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7936     {
7937 	if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL)
7938 	{
7939 	    OUT_STR(_("Vim: preserving files...\n"));
7940 	    screen_start();	    /* don't know where cursor is now */
7941 	    out_flush();
7942 	    ml_sync_all(FALSE, FALSE);	/* preserve all swap files */
7943 	    break;
7944 	}
7945     }
7946 
7947     ml_close_all(FALSE);	    /* close all memfiles, without deleting */
7948 
7949     OUT_STR(_("Vim: Finished.\n"));
7950 
7951     getout(1);
7952 }
7953 
7954 /*
7955  * return TRUE if "fname" exists.
7956  */
7957     int
7958 vim_fexists(fname)
7959     char_u  *fname;
7960 {
7961     struct stat st;
7962 
7963     if (mch_stat((char *)fname, &st))
7964 	return FALSE;
7965     return TRUE;
7966 }
7967 
7968 /*
7969  * Check for CTRL-C pressed, but only once in a while.
7970  * Should be used instead of ui_breakcheck() for functions that check for
7971  * each line in the file.  Calling ui_breakcheck() each time takes too much
7972  * time, because it can be a system call.
7973  */
7974 
7975 #ifndef BREAKCHECK_SKIP
7976 # ifdef FEAT_GUI		    /* assume the GUI only runs on fast computers */
7977 #  define BREAKCHECK_SKIP 200
7978 # else
7979 #  define BREAKCHECK_SKIP 32
7980 # endif
7981 #endif
7982 
7983 static int	breakcheck_count = 0;
7984 
7985     void
7986 line_breakcheck()
7987 {
7988     if (++breakcheck_count >= BREAKCHECK_SKIP)
7989     {
7990 	breakcheck_count = 0;
7991 	ui_breakcheck();
7992     }
7993 }
7994 
7995 /*
7996  * Like line_breakcheck() but check 10 times less often.
7997  */
7998     void
7999 fast_breakcheck()
8000 {
8001     if (++breakcheck_count >= BREAKCHECK_SKIP * 10)
8002     {
8003 	breakcheck_count = 0;
8004 	ui_breakcheck();
8005     }
8006 }
8007 
8008 /*
8009  * Expand wildcards.  Calls gen_expand_wildcards() and removes files matching
8010  * 'wildignore'.
8011  */
8012     int
8013 expand_wildcards(num_pat, pat, num_file, file, flags)
8014     int		   num_pat;	/* number of input patterns */
8015     char_u	 **pat;		/* array of input patterns */
8016     int		  *num_file;	/* resulting number of files */
8017     char_u	***file;	/* array of resulting files */
8018     int		   flags;	/* EW_DIR, etc. */
8019 {
8020     int		retval;
8021     int		i, j;
8022     char_u	*p;
8023     int		non_suf_match;	/* number without matching suffix */
8024 
8025     retval = gen_expand_wildcards(num_pat, pat, num_file, file, flags);
8026 
8027     /* When keeping all matches, return here */
8028     if (flags & EW_KEEPALL)
8029 	return retval;
8030 
8031 #ifdef FEAT_WILDIGN
8032     /*
8033      * Remove names that match 'wildignore'.
8034      */
8035     if (*p_wig)
8036     {
8037 	char_u	*ffname;
8038 
8039 	/* check all files in (*file)[] */
8040 	for (i = 0; i < *num_file; ++i)
8041 	{
8042 	    ffname = FullName_save((*file)[i], FALSE);
8043 	    if (ffname == NULL)		/* out of memory */
8044 		break;
8045 # ifdef VMS
8046 	    vms_remove_version(ffname);
8047 # endif
8048 	    if (match_file_list(p_wig, (*file)[i], ffname))
8049 	    {
8050 		/* remove this matching file from the list */
8051 		vim_free((*file)[i]);
8052 		for (j = i; j + 1 < *num_file; ++j)
8053 		    (*file)[j] = (*file)[j + 1];
8054 		--*num_file;
8055 		--i;
8056 	    }
8057 	    vim_free(ffname);
8058 	}
8059     }
8060 #endif
8061 
8062     /*
8063      * Move the names where 'suffixes' match to the end.
8064      */
8065     if (*num_file > 1)
8066     {
8067 	non_suf_match = 0;
8068 	for (i = 0; i < *num_file; ++i)
8069 	{
8070 	    if (!match_suffix((*file)[i]))
8071 	    {
8072 		/*
8073 		 * Move the name without matching suffix to the front
8074 		 * of the list.
8075 		 */
8076 		p = (*file)[i];
8077 		for (j = i; j > non_suf_match; --j)
8078 		    (*file)[j] = (*file)[j - 1];
8079 		(*file)[non_suf_match++] = p;
8080 	    }
8081 	}
8082     }
8083 
8084     return retval;
8085 }
8086 
8087 /*
8088  * Return TRUE if "fname" matches with an entry in 'suffixes'.
8089  */
8090     int
8091 match_suffix(fname)
8092     char_u	*fname;
8093 {
8094     int		fnamelen, setsuflen;
8095     char_u	*setsuf;
8096 #define MAXSUFLEN 30	    /* maximum length of a file suffix */
8097     char_u	suf_buf[MAXSUFLEN];
8098 
8099     fnamelen = (int)STRLEN(fname);
8100     setsuflen = 0;
8101     for (setsuf = p_su; *setsuf; )
8102     {
8103 	setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
8104 	if (fnamelen >= setsuflen
8105 		&& fnamencmp(suf_buf, fname + fnamelen - setsuflen,
8106 					      (size_t)setsuflen) == 0)
8107 	    break;
8108 	setsuflen = 0;
8109     }
8110     return (setsuflen != 0);
8111 }
8112 
8113 #if !defined(NO_EXPANDPATH) || defined(PROTO)
8114 
8115 # ifdef VIM_BACKTICK
8116 static int vim_backtick __ARGS((char_u *p));
8117 static int expand_backtick __ARGS((garray_T *gap, char_u *pat, int flags));
8118 # endif
8119 
8120 # if defined(MSDOS) || defined(FEAT_GUI_W16) || defined(WIN3264)
8121 /*
8122  * File name expansion code for MS-DOS, Win16 and Win32.  It's here because
8123  * it's shared between these systems.
8124  */
8125 # if defined(DJGPP) || defined(PROTO)
8126 #  define _cdecl	    /* DJGPP doesn't have this */
8127 # else
8128 #  ifdef __BORLANDC__
8129 #   define _cdecl _RTLENTRYF
8130 #  endif
8131 # endif
8132 
8133 /*
8134  * comparison function for qsort in dos_expandpath()
8135  */
8136     static int _cdecl
8137 pstrcmp(const void *a, const void *b)
8138 {
8139     return (pathcmp(*(char **)a, *(char **)b, -1));
8140 }
8141 
8142 # ifndef WIN3264
8143     static void
8144 namelowcpy(
8145     char_u *d,
8146     char_u *s)
8147 {
8148 #  ifdef DJGPP
8149     if (USE_LONG_FNAME)	    /* don't lower case on Windows 95/NT systems */
8150 	while (*s)
8151 	    *d++ = *s++;
8152     else
8153 #  endif
8154 	while (*s)
8155 	    *d++ = TOLOWER_LOC(*s++);
8156     *d = NUL;
8157 }
8158 # endif
8159 
8160 /*
8161  * Recursively expand one path component into all matching files and/or
8162  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
8163  * Return the number of matches found.
8164  * "path" has backslashes before chars that are not to be expanded, starting
8165  * at "path[wildoff]".
8166  * Return the number of matches found.
8167  * NOTE: much of this is identical to unix_expandpath(), keep in sync!
8168  */
8169     static int
8170 dos_expandpath(
8171     garray_T	*gap,
8172     char_u	*path,
8173     int		wildoff,
8174     int		flags,		/* EW_* flags */
8175     int		didstar)	/* expaneded "**" once already */
8176 {
8177     char_u	*buf;
8178     char_u	*path_end;
8179     char_u	*p, *s, *e;
8180     int		start_len = gap->ga_len;
8181     char_u	*pat;
8182     regmatch_T	regmatch;
8183     int		starts_with_dot;
8184     int		matches;
8185     int		len;
8186     int		starstar = FALSE;
8187     static int	stardepth = 0;	    /* depth for "**" expansion */
8188 #ifdef WIN3264
8189     WIN32_FIND_DATA	fb;
8190     HANDLE		hFind = (HANDLE)0;
8191 # ifdef FEAT_MBYTE
8192     WIN32_FIND_DATAW    wfb;
8193     WCHAR		*wn = NULL;	/* UCS-2 name, NULL when not used. */
8194 # endif
8195 #else
8196     struct ffblk	fb;
8197 #endif
8198     char_u		*matchname;
8199     int			ok;
8200 
8201     /* Expanding "**" may take a long time, check for CTRL-C. */
8202     if (stardepth > 0)
8203     {
8204 	ui_breakcheck();
8205 	if (got_int)
8206 	    return 0;
8207     }
8208 
8209     /* make room for file name */
8210     buf = alloc((int)STRLEN(path) + BASENAMELEN + 5);
8211     if (buf == NULL)
8212 	return 0;
8213 
8214     /*
8215      * Find the first part in the path name that contains a wildcard or a ~1.
8216      * Copy it into buf, including the preceding characters.
8217      */
8218     p = buf;
8219     s = buf;
8220     e = NULL;
8221     path_end = path;
8222     while (*path_end != NUL)
8223     {
8224 	/* May ignore a wildcard that has a backslash before it; it will
8225 	 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
8226 	if (path_end >= path + wildoff && rem_backslash(path_end))
8227 	    *p++ = *path_end++;
8228 	else if (*path_end == '\\' || *path_end == ':' || *path_end == '/')
8229 	{
8230 	    if (e != NULL)
8231 		break;
8232 	    s = p + 1;
8233 	}
8234 	else if (path_end >= path + wildoff
8235 			 && vim_strchr((char_u *)"*?[~", *path_end) != NULL)
8236 	    e = p;
8237 #ifdef FEAT_MBYTE
8238 	if (has_mbyte)
8239 	{
8240 	    len = (*mb_ptr2len)(path_end);
8241 	    STRNCPY(p, path_end, len);
8242 	    p += len;
8243 	    path_end += len;
8244 	}
8245 	else
8246 #endif
8247 	    *p++ = *path_end++;
8248     }
8249     e = p;
8250     *e = NUL;
8251 
8252     /* now we have one wildcard component between s and e */
8253     /* Remove backslashes between "wildoff" and the start of the wildcard
8254      * component. */
8255     for (p = buf + wildoff; p < s; ++p)
8256 	if (rem_backslash(p))
8257 	{
8258 	    STRCPY(p, p + 1);
8259 	    --e;
8260 	    --s;
8261 	}
8262 
8263     /* Check for "**" between "s" and "e". */
8264     for (p = s; p < e; ++p)
8265 	if (p[0] == '*' && p[1] == '*')
8266 	    starstar = TRUE;
8267 
8268     starts_with_dot = (*s == '.');
8269     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
8270     if (pat == NULL)
8271     {
8272 	vim_free(buf);
8273 	return 0;
8274     }
8275 
8276     /* compile the regexp into a program */
8277     regmatch.rm_ic = TRUE;		/* Always ignore case */
8278     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
8279     vim_free(pat);
8280 
8281     if (regmatch.regprog == NULL)
8282     {
8283 	vim_free(buf);
8284 	return 0;
8285     }
8286 
8287     /* remember the pattern or file name being looked for */
8288     matchname = vim_strsave(s);
8289 
8290     /* If "**" is by itself, this is the first time we encounter it and more
8291      * is following then find matches without any directory. */
8292     if (!didstar && stardepth < 100 && starstar && e - s == 2
8293 							  && *path_end == '/')
8294     {
8295 	STRCPY(s, path_end + 1);
8296 	++stardepth;
8297 	(void)dos_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
8298 	--stardepth;
8299     }
8300 
8301     /* Scan all files in the directory with "dir/ *.*" */
8302     STRCPY(s, "*.*");
8303 #ifdef WIN3264
8304 # ifdef FEAT_MBYTE
8305     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
8306     {
8307 	/* The active codepage differs from 'encoding'.  Attempt using the
8308 	 * wide function.  If it fails because it is not implemented fall back
8309 	 * to the non-wide version (for Windows 98) */
8310 	wn = enc_to_ucs2(buf, NULL);
8311 	if (wn != NULL)
8312 	{
8313 	    hFind = FindFirstFileW(wn, &wfb);
8314 	    if (hFind == INVALID_HANDLE_VALUE
8315 			      && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
8316 	    {
8317 		vim_free(wn);
8318 		wn = NULL;
8319 	    }
8320 	}
8321     }
8322 
8323     if (wn == NULL)
8324 # endif
8325 	hFind = FindFirstFile(buf, &fb);
8326     ok = (hFind != INVALID_HANDLE_VALUE);
8327 #else
8328     /* If we are expanding wildcards we try both files and directories */
8329     ok = (findfirst((char *)buf, &fb,
8330 		(*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0);
8331 #endif
8332 
8333     while (ok)
8334     {
8335 #ifdef WIN3264
8336 # ifdef FEAT_MBYTE
8337 	if (wn != NULL)
8338 	    p = ucs2_to_enc(wfb.cFileName, NULL);   /* p is allocated here */
8339 	else
8340 # endif
8341 	    p = (char_u *)fb.cFileName;
8342 #else
8343 	p = (char_u *)fb.ff_name;
8344 #endif
8345 	/* Ignore entries starting with a dot, unless when asked for.  Accept
8346 	 * all entries found with "matchname". */
8347 	if ((p[0] != '.' || starts_with_dot)
8348 		&& (matchname == NULL
8349 		    || vim_regexec(&regmatch, p, (colnr_T)0)))
8350 	{
8351 #ifdef WIN3264
8352 	    STRCPY(s, p);
8353 #else
8354 	    namelowcpy(s, p);
8355 #endif
8356 	    len = (int)STRLEN(buf);
8357 
8358 	    if (starstar && stardepth < 100)
8359 	    {
8360 		/* For "**" in the pattern first go deeper in the tree to
8361 		 * find matches. */
8362 		STRCPY(buf + len, "/**");
8363 		STRCPY(buf + len + 3, path_end);
8364 		++stardepth;
8365 		(void)dos_expandpath(gap, buf, len + 1, flags, TRUE);
8366 		--stardepth;
8367 	    }
8368 
8369 	    STRCPY(buf + len, path_end);
8370 	    if (mch_has_exp_wildcard(path_end))
8371 	    {
8372 		/* need to expand another component of the path */
8373 		/* remove backslashes for the remaining components only */
8374 		(void)dos_expandpath(gap, buf, len + 1, flags, FALSE);
8375 	    }
8376 	    else
8377 	    {
8378 		/* no more wildcards, check if there is a match */
8379 		/* remove backslashes for the remaining components only */
8380 		if (*path_end != 0)
8381 		    backslash_halve(buf + len + 1);
8382 		if (mch_getperm(buf) >= 0)	/* add existing file */
8383 		    addfile(gap, buf, flags);
8384 	    }
8385 	}
8386 
8387 #ifdef WIN3264
8388 # ifdef FEAT_MBYTE
8389 	if (wn != NULL)
8390 	{
8391 	    vim_free(p);
8392 	    ok = FindNextFileW(hFind, &wfb);
8393 	}
8394 	else
8395 # endif
8396 	    ok = FindNextFile(hFind, &fb);
8397 #else
8398 	ok = (findnext(&fb) == 0);
8399 #endif
8400 
8401 	/* If no more matches and no match was used, try expanding the name
8402 	 * itself.  Finds the long name of a short filename. */
8403 	if (!ok && matchname != NULL && gap->ga_len == start_len)
8404 	{
8405 	    STRCPY(s, matchname);
8406 #ifdef WIN3264
8407 	    FindClose(hFind);
8408 # ifdef FEAT_MBYTE
8409 	    if (wn != NULL)
8410 	    {
8411 		vim_free(wn);
8412 		wn = enc_to_ucs2(buf, NULL);
8413 		if (wn != NULL)
8414 		    hFind = FindFirstFileW(wn, &wfb);
8415 	    }
8416 	    if (wn == NULL)
8417 # endif
8418 		hFind = FindFirstFile(buf, &fb);
8419 	    ok = (hFind != INVALID_HANDLE_VALUE);
8420 #else
8421 	    ok = (findfirst((char *)buf, &fb,
8422 		 (*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0);
8423 #endif
8424 	    vim_free(matchname);
8425 	    matchname = NULL;
8426 	}
8427     }
8428 
8429 #ifdef WIN3264
8430     FindClose(hFind);
8431 # ifdef FEAT_MBYTE
8432     vim_free(wn);
8433 # endif
8434 #endif
8435     vim_free(buf);
8436     vim_free(regmatch.regprog);
8437     vim_free(matchname);
8438 
8439     matches = gap->ga_len - start_len;
8440     if (matches > 0)
8441 	qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches,
8442 						   sizeof(char_u *), pstrcmp);
8443     return matches;
8444 }
8445 
8446     int
8447 mch_expandpath(
8448     garray_T	*gap,
8449     char_u	*path,
8450     int		flags)		/* EW_* flags */
8451 {
8452     return dos_expandpath(gap, path, 0, flags, FALSE);
8453 }
8454 # endif /* MSDOS || FEAT_GUI_W16 || WIN3264 */
8455 
8456 #if (defined(UNIX) && !defined(VMS)) || defined(USE_UNIXFILENAME) \
8457 	|| defined(PROTO)
8458 /*
8459  * Unix style wildcard expansion code.
8460  * It's here because it's used both for Unix and Mac.
8461  */
8462 static int	pstrcmp __ARGS((const void *, const void *));
8463 
8464     static int
8465 pstrcmp(a, b)
8466     const void *a, *b;
8467 {
8468     return (pathcmp(*(char **)a, *(char **)b, -1));
8469 }
8470 
8471 /*
8472  * Recursively expand one path component into all matching files and/or
8473  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
8474  * "path" has backslashes before chars that are not to be expanded, starting
8475  * at "path + wildoff".
8476  * Return the number of matches found.
8477  * NOTE: much of this is identical to dos_expandpath(), keep in sync!
8478  */
8479     int
8480 unix_expandpath(gap, path, wildoff, flags, didstar)
8481     garray_T	*gap;
8482     char_u	*path;
8483     int		wildoff;
8484     int		flags;		/* EW_* flags */
8485     int		didstar;	/* expanded "**" once already */
8486 {
8487     char_u	*buf;
8488     char_u	*path_end;
8489     char_u	*p, *s, *e;
8490     int		start_len = gap->ga_len;
8491     char_u	*pat;
8492     regmatch_T	regmatch;
8493     int		starts_with_dot;
8494     int		matches;
8495     int		len;
8496     int		starstar = FALSE;
8497     static int	stardepth = 0;	    /* depth for "**" expansion */
8498 
8499     DIR		*dirp;
8500     struct dirent *dp;
8501 
8502     /* Expanding "**" may take a long time, check for CTRL-C. */
8503     if (stardepth > 0)
8504     {
8505 	ui_breakcheck();
8506 	if (got_int)
8507 	    return 0;
8508     }
8509 
8510     /* make room for file name */
8511     buf = alloc((int)STRLEN(path) + BASENAMELEN + 5);
8512     if (buf == NULL)
8513 	return 0;
8514 
8515     /*
8516      * Find the first part in the path name that contains a wildcard.
8517      * Copy it into "buf", including the preceding characters.
8518      */
8519     p = buf;
8520     s = buf;
8521     e = NULL;
8522     path_end = path;
8523     while (*path_end != NUL)
8524     {
8525 	/* May ignore a wildcard that has a backslash before it; it will
8526 	 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
8527 	if (path_end >= path + wildoff && rem_backslash(path_end))
8528 	    *p++ = *path_end++;
8529 	else if (*path_end == '/')
8530 	{
8531 	    if (e != NULL)
8532 		break;
8533 	    s = p + 1;
8534 	}
8535 	else if (path_end >= path + wildoff
8536 			 && vim_strchr((char_u *)"*?[{~$", *path_end) != NULL)
8537 	    e = p;
8538 #ifdef FEAT_MBYTE
8539 	if (has_mbyte)
8540 	{
8541 	    len = (*mb_ptr2len)(path_end);
8542 	    STRNCPY(p, path_end, len);
8543 	    p += len;
8544 	    path_end += len;
8545 	}
8546 	else
8547 #endif
8548 	    *p++ = *path_end++;
8549     }
8550     e = p;
8551     *e = NUL;
8552 
8553     /* now we have one wildcard component between "s" and "e" */
8554     /* Remove backslashes between "wildoff" and the start of the wildcard
8555      * component. */
8556     for (p = buf + wildoff; p < s; ++p)
8557 	if (rem_backslash(p))
8558 	{
8559 	    STRCPY(p, p + 1);
8560 	    --e;
8561 	    --s;
8562 	}
8563 
8564     /* Check for "**" between "s" and "e". */
8565     for (p = s; p < e; ++p)
8566 	if (p[0] == '*' && p[1] == '*')
8567 	    starstar = TRUE;
8568 
8569     /* convert the file pattern to a regexp pattern */
8570     starts_with_dot = (*s == '.');
8571     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
8572     if (pat == NULL)
8573     {
8574 	vim_free(buf);
8575 	return 0;
8576     }
8577 
8578     /* compile the regexp into a program */
8579 #ifdef MACOS_X /* Can/Should we use CASE_INSENSITIVE_FILENAME instead ?*/
8580     regmatch.rm_ic = TRUE;		/* Behave like Terminal.app */
8581 #else
8582     regmatch.rm_ic = FALSE;		/* Don't ever ignore case */
8583 #endif
8584     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
8585     vim_free(pat);
8586 
8587     if (regmatch.regprog == NULL)
8588     {
8589 	vim_free(buf);
8590 	return 0;
8591     }
8592 
8593     /* If "**" is by itself, this is the first time we encounter it and more
8594      * is following then find matches without any directory. */
8595     if (!didstar && stardepth < 100 && starstar && e - s == 2
8596 							  && *path_end == '/')
8597     {
8598 	STRCPY(s, path_end + 1);
8599 	++stardepth;
8600 	(void)unix_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
8601 	--stardepth;
8602     }
8603 
8604     /* open the directory for scanning */
8605     *s = NUL;
8606     dirp = opendir(*buf == NUL ? "." : (char *)buf);
8607 
8608     /* Find all matching entries */
8609     if (dirp != NULL)
8610     {
8611 	for (;;)
8612 	{
8613 	    dp = readdir(dirp);
8614 	    if (dp == NULL)
8615 		break;
8616 	    if ((dp->d_name[0] != '.' || starts_with_dot)
8617 		    && vim_regexec(&regmatch, (char_u *)dp->d_name, (colnr_T)0))
8618 	    {
8619 		STRCPY(s, dp->d_name);
8620 		len = STRLEN(buf);
8621 
8622 		if (starstar && stardepth < 100)
8623 		{
8624 		    /* For "**" in the pattern first go deeper in the tree to
8625 		     * find matches. */
8626 		    STRCPY(buf + len, "/**");
8627 		    STRCPY(buf + len + 3, path_end);
8628 		    ++stardepth;
8629 		    (void)unix_expandpath(gap, buf, len + 1, flags, TRUE);
8630 		    --stardepth;
8631 		}
8632 
8633 		STRCPY(buf + len, path_end);
8634 		if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
8635 		{
8636 		    /* need to expand another component of the path */
8637 		    /* remove backslashes for the remaining components only */
8638 		    (void)unix_expandpath(gap, buf, len + 1, flags, FALSE);
8639 		}
8640 		else
8641 		{
8642 		    /* no more wildcards, check if there is a match */
8643 		    /* remove backslashes for the remaining components only */
8644 		    if (*path_end != NUL)
8645 			backslash_halve(buf + len + 1);
8646 		    if (mch_getperm(buf) >= 0)	/* add existing file */
8647 		    {
8648 #if defined(MACOS_X) && defined(FEAT_MBYTE)
8649 			size_t precomp_len = STRLEN(buf)+1;
8650 			char_u *precomp_buf =
8651 			    mac_precompose_path(buf, precomp_len, &precomp_len);
8652 			if (precomp_buf)
8653 			{
8654 			    mch_memmove(buf, precomp_buf, precomp_len);
8655 			    vim_free(precomp_buf);
8656 			}
8657 #endif
8658 			addfile(gap, buf, flags);
8659 		    }
8660 		}
8661 	    }
8662 	}
8663 
8664 	closedir(dirp);
8665     }
8666 
8667     vim_free(buf);
8668     vim_free(regmatch.regprog);
8669 
8670     matches = gap->ga_len - start_len;
8671     if (matches > 0)
8672 	qsort(((char_u **)gap->ga_data) + start_len, matches,
8673 						   sizeof(char_u *), pstrcmp);
8674     return matches;
8675 }
8676 #endif
8677 
8678 /*
8679  * Generic wildcard expansion code.
8680  *
8681  * Characters in "pat" that should not be expanded must be preceded with a
8682  * backslash. E.g., "/path\ with\ spaces/my\*star*"
8683  *
8684  * Return FAIL when no single file was found.  In this case "num_file" is not
8685  * set, and "file" may contain an error message.
8686  * Return OK when some files found.  "num_file" is set to the number of
8687  * matches, "file" to the array of matches.  Call FreeWild() later.
8688  */
8689     int
8690 gen_expand_wildcards(num_pat, pat, num_file, file, flags)
8691     int		num_pat;	/* number of input patterns */
8692     char_u	**pat;		/* array of input patterns */
8693     int		*num_file;	/* resulting number of files */
8694     char_u	***file;	/* array of resulting files */
8695     int		flags;		/* EW_* flags */
8696 {
8697     int			i;
8698     garray_T		ga;
8699     char_u		*p;
8700     static int		recursive = FALSE;
8701     int			add_pat;
8702 
8703     /*
8704      * expand_env() is called to expand things like "~user".  If this fails,
8705      * it calls ExpandOne(), which brings us back here.  In this case, always
8706      * call the machine specific expansion function, if possible.  Otherwise,
8707      * return FAIL.
8708      */
8709     if (recursive)
8710 #ifdef SPECIAL_WILDCHAR
8711 	return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
8712 #else
8713 	return FAIL;
8714 #endif
8715 
8716 #ifdef SPECIAL_WILDCHAR
8717     /*
8718      * If there are any special wildcard characters which we cannot handle
8719      * here, call machine specific function for all the expansion.  This
8720      * avoids starting the shell for each argument separately.
8721      * For `=expr` do use the internal function.
8722      */
8723     for (i = 0; i < num_pat; i++)
8724     {
8725 	if (vim_strpbrk(pat[i], (char_u *)SPECIAL_WILDCHAR) != NULL
8726 # ifdef VIM_BACKTICK
8727 		&& !(vim_backtick(pat[i]) && pat[i][1] == '=')
8728 # endif
8729 	   )
8730 	    return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
8731     }
8732 #endif
8733 
8734     recursive = TRUE;
8735 
8736     /*
8737      * The matching file names are stored in a growarray.  Init it empty.
8738      */
8739     ga_init2(&ga, (int)sizeof(char_u *), 30);
8740 
8741     for (i = 0; i < num_pat; ++i)
8742     {
8743 	add_pat = -1;
8744 	p = pat[i];
8745 
8746 #ifdef VIM_BACKTICK
8747 	if (vim_backtick(p))
8748 	    add_pat = expand_backtick(&ga, p, flags);
8749 	else
8750 #endif
8751 	{
8752 	    /*
8753 	     * First expand environment variables, "~/" and "~user/".
8754 	     */
8755 	    if (vim_strpbrk(p, (char_u *)"$~") != NULL)
8756 	    {
8757 		p = expand_env_save(p);
8758 		if (p == NULL)
8759 		    p = pat[i];
8760 #ifdef UNIX
8761 		/*
8762 		 * On Unix, if expand_env() can't expand an environment
8763 		 * variable, use the shell to do that.  Discard previously
8764 		 * found file names and start all over again.
8765 		 */
8766 		else if (vim_strpbrk(p, (char_u *)"$~") != NULL)
8767 		{
8768 		    vim_free(p);
8769 		    ga_clear(&ga);
8770 		    i = mch_expand_wildcards(num_pat, pat, num_file, file,
8771 								       flags);
8772 		    recursive = FALSE;
8773 		    return i;
8774 		}
8775 #endif
8776 	    }
8777 
8778 	    /*
8779 	     * If there are wildcards: Expand file names and add each match to
8780 	     * the list.  If there is no match, and EW_NOTFOUND is given, add
8781 	     * the pattern.
8782 	     * If there are no wildcards: Add the file name if it exists or
8783 	     * when EW_NOTFOUND is given.
8784 	     */
8785 	    if (mch_has_exp_wildcard(p))
8786 		add_pat = mch_expandpath(&ga, p, flags);
8787 	}
8788 
8789 	if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND)))
8790 	{
8791 	    char_u	*t = backslash_halve_save(p);
8792 
8793 #if defined(MACOS_CLASSIC)
8794 	    slash_to_colon(t);
8795 #endif
8796 	    /* When EW_NOTFOUND is used, always add files and dirs.  Makes
8797 	     * "vim c:/" work. */
8798 	    if (flags & EW_NOTFOUND)
8799 		addfile(&ga, t, flags | EW_DIR | EW_FILE);
8800 	    else if (mch_getperm(t) >= 0)
8801 		addfile(&ga, t, flags);
8802 	    vim_free(t);
8803 	}
8804 
8805 	if (p != pat[i])
8806 	    vim_free(p);
8807     }
8808 
8809     *num_file = ga.ga_len;
8810     *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)"";
8811 
8812     recursive = FALSE;
8813 
8814     return (ga.ga_data != NULL) ? OK : FAIL;
8815 }
8816 
8817 # ifdef VIM_BACKTICK
8818 
8819 /*
8820  * Return TRUE if we can expand this backtick thing here.
8821  */
8822     static int
8823 vim_backtick(p)
8824     char_u	*p;
8825 {
8826     return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`');
8827 }
8828 
8829 /*
8830  * Expand an item in `backticks` by executing it as a command.
8831  * Currently only works when pat[] starts and ends with a `.
8832  * Returns number of file names found.
8833  */
8834     static int
8835 expand_backtick(gap, pat, flags)
8836     garray_T	*gap;
8837     char_u	*pat;
8838     int		flags;	/* EW_* flags */
8839 {
8840     char_u	*p;
8841     char_u	*cmd;
8842     char_u	*buffer;
8843     int		cnt = 0;
8844     int		i;
8845 
8846     /* Create the command: lop off the backticks. */
8847     cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
8848     if (cmd == NULL)
8849 	return 0;
8850 
8851 #ifdef FEAT_EVAL
8852     if (*cmd == '=')	    /* `={expr}`: Expand expression */
8853 	buffer = eval_to_string(cmd + 1, &p);
8854     else
8855 #endif
8856 	buffer = get_cmd_output(cmd, NULL,
8857 				      (flags & EW_SILENT) ? SHELL_SILENT : 0);
8858     vim_free(cmd);
8859     if (buffer == NULL)
8860 	return 0;
8861 
8862     cmd = buffer;
8863     while (*cmd != NUL)
8864     {
8865 	cmd = skipwhite(cmd);		/* skip over white space */
8866 	p = cmd;
8867 	while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */
8868 	    ++p;
8869 	/* add an entry if it is not empty */
8870 	if (p > cmd)
8871 	{
8872 	    i = *p;
8873 	    *p = NUL;
8874 	    addfile(gap, cmd, flags);
8875 	    *p = i;
8876 	    ++cnt;
8877 	}
8878 	cmd = p;
8879 	while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n'))
8880 	    ++cmd;
8881     }
8882 
8883     vim_free(buffer);
8884     return cnt;
8885 }
8886 # endif /* VIM_BACKTICK */
8887 
8888 /*
8889  * Add a file to a file list.  Accepted flags:
8890  * EW_DIR	add directories
8891  * EW_FILE	add files
8892  * EW_NOTFOUND	add even when it doesn't exist
8893  * EW_ADDSLASH	add slash after directory name
8894  */
8895     void
8896 addfile(gap, f, flags)
8897     garray_T	*gap;
8898     char_u	*f;	/* filename */
8899     int		flags;
8900 {
8901     char_u	*p;
8902     int		isdir;
8903 
8904     /* if the file/dir doesn't exist, may not add it */
8905     if (!(flags & EW_NOTFOUND) && mch_getperm(f) < 0)
8906 	return;
8907 
8908 #ifdef FNAME_ILLEGAL
8909     /* if the file/dir contains illegal characters, don't add it */
8910     if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL)
8911 	return;
8912 #endif
8913 
8914     isdir = mch_isdir(f);
8915     if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE)))
8916 	return;
8917 
8918     /* Make room for another item in the file list. */
8919     if (ga_grow(gap, 1) == FAIL)
8920 	return;
8921 
8922     p = alloc((unsigned)(STRLEN(f) + 1 + isdir));
8923     if (p == NULL)
8924 	return;
8925 
8926     STRCPY(p, f);
8927 #ifdef BACKSLASH_IN_FILENAME
8928     slash_adjust(p);
8929 #endif
8930     /*
8931      * Append a slash or backslash after directory names if none is present.
8932      */
8933 #ifndef DONT_ADD_PATHSEP_TO_DIR
8934     if (isdir && (flags & EW_ADDSLASH))
8935 	add_pathsep(p);
8936 #endif
8937     ((char_u **)gap->ga_data)[gap->ga_len++] = p;
8938 }
8939 #endif /* !NO_EXPANDPATH */
8940 
8941 #if defined(VIM_BACKTICK) || defined(FEAT_EVAL) || defined(PROTO)
8942 
8943 #ifndef SEEK_SET
8944 # define SEEK_SET 0
8945 #endif
8946 #ifndef SEEK_END
8947 # define SEEK_END 2
8948 #endif
8949 
8950 /*
8951  * Get the stdout of an external command.
8952  * Returns an allocated string, or NULL for error.
8953  */
8954     char_u *
8955 get_cmd_output(cmd, infile, flags)
8956     char_u	*cmd;
8957     char_u	*infile;	/* optional input file name */
8958     int		flags;		/* can be SHELL_SILENT */
8959 {
8960     char_u	*tempname;
8961     char_u	*command;
8962     char_u	*buffer = NULL;
8963     int		len;
8964     int		i = 0;
8965     FILE	*fd;
8966 
8967     if (check_restricted() || check_secure())
8968 	return NULL;
8969 
8970     /* get a name for the temp file */
8971     if ((tempname = vim_tempname('o')) == NULL)
8972     {
8973 	EMSG(_(e_notmp));
8974 	return NULL;
8975     }
8976 
8977     /* Add the redirection stuff */
8978     command = make_filter_cmd(cmd, infile, tempname);
8979     if (command == NULL)
8980 	goto done;
8981 
8982     /*
8983      * Call the shell to execute the command (errors are ignored).
8984      * Don't check timestamps here.
8985      */
8986     ++no_check_timestamps;
8987     call_shell(command, SHELL_DOOUT | SHELL_EXPAND | flags);
8988     --no_check_timestamps;
8989 
8990     vim_free(command);
8991 
8992     /*
8993      * read the names from the file into memory
8994      */
8995 # ifdef VMS
8996     /* created temporary file is not allways readable as binary */
8997     fd = mch_fopen((char *)tempname, "r");
8998 # else
8999     fd = mch_fopen((char *)tempname, READBIN);
9000 # endif
9001 
9002     if (fd == NULL)
9003     {
9004 	EMSG2(_(e_notopen), tempname);
9005 	goto done;
9006     }
9007 
9008     fseek(fd, 0L, SEEK_END);
9009     len = ftell(fd);		    /* get size of temp file */
9010     fseek(fd, 0L, SEEK_SET);
9011 
9012     buffer = alloc(len + 1);
9013     if (buffer != NULL)
9014 	i = (int)fread((char *)buffer, (size_t)1, (size_t)len, fd);
9015     fclose(fd);
9016     mch_remove(tempname);
9017     if (buffer == NULL)
9018 	goto done;
9019 #ifdef VMS
9020     len = i;	/* VMS doesn't give us what we asked for... */
9021 #endif
9022     if (i != len)
9023     {
9024 	EMSG2(_(e_notread), tempname);
9025 	vim_free(buffer);
9026 	buffer = NULL;
9027     }
9028     else
9029 	buffer[len] = '\0';	/* make sure the buffer is terminated */
9030 
9031 done:
9032     vim_free(tempname);
9033     return buffer;
9034 }
9035 #endif
9036 
9037 /*
9038  * Free the list of files returned by expand_wildcards() or other expansion
9039  * functions.
9040  */
9041     void
9042 FreeWild(count, files)
9043     int	    count;
9044     char_u  **files;
9045 {
9046     if (files == NULL || count <= 0)
9047 	return;
9048 #if defined(__EMX__) && defined(__ALWAYS_HAS_TRAILING_NULL_POINTER) /* XXX */
9049     /*
9050      * Is this still OK for when other functions than expand_wildcards() have
9051      * been used???
9052      */
9053     _fnexplodefree((char **)files);
9054 #else
9055     while (count--)
9056 	vim_free(files[count]);
9057     vim_free(files);
9058 #endif
9059 }
9060 
9061 /*
9062  * return TRUE when need to go to Insert mode because of 'insertmode'.
9063  * Don't do this when still processing a command or a mapping.
9064  * Don't do this when inside a ":normal" command.
9065  */
9066     int
9067 goto_im()
9068 {
9069     return (p_im && stuff_empty() && typebuf_typed());
9070 }
9071