xref: /vim-8.2.3635/src/misc1.c (revision fc65cabb)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * misc1.c: functions that didn't seem to fit elsewhere
12  */
13 
14 #include "vim.h"
15 #include "version.h"
16 
17 #if defined(FEAT_CMDL_COMPL) && defined(WIN3264)
18 # include <lm.h>
19 #endif
20 
21 static char_u *vim_version_dir(char_u *vimdir);
22 static char_u *remove_tail(char_u *p, char_u *pend, char_u *name);
23 #if defined(FEAT_CMDL_COMPL)
24 static void init_users(void);
25 #endif
26 static int copy_indent(int size, char_u	*src);
27 
28 /* All user names (for ~user completion as done by shell). */
29 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
30 static garray_T	ga_users;
31 #endif
32 
33 /*
34  * Count the size (in window cells) of the indent in the current line.
35  */
36     int
37 get_indent(void)
38 {
39 #ifdef FEAT_VARTABS
40     return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts,
41 						 curbuf->b_p_vts_array, FALSE);
42 #else
43     return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE);
44 #endif
45 }
46 
47 /*
48  * Count the size (in window cells) of the indent in line "lnum".
49  */
50     int
51 get_indent_lnum(linenr_T lnum)
52 {
53 #ifdef FEAT_VARTABS
54     return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts,
55 						 curbuf->b_p_vts_array, FALSE);
56 #else
57     return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE);
58 #endif
59 }
60 
61 #if defined(FEAT_FOLDING) || defined(PROTO)
62 /*
63  * Count the size (in window cells) of the indent in line "lnum" of buffer
64  * "buf".
65  */
66     int
67 get_indent_buf(buf_T *buf, linenr_T lnum)
68 {
69 #ifdef FEAT_VARTABS
70     return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE),
71 			       (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE);
72 #else
73     return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE);
74 #endif
75 }
76 #endif
77 
78 /*
79  * count the size (in window cells) of the indent in line "ptr", with
80  * 'tabstop' at "ts"
81  */
82     int
83 get_indent_str(
84     char_u	*ptr,
85     int		ts,
86     int		list) /* if TRUE, count only screen size for tabs */
87 {
88     int		count = 0;
89 
90     for ( ; *ptr; ++ptr)
91     {
92 	if (*ptr == TAB)
93 	{
94 	    if (!list || lcs_tab1)    /* count a tab for what it is worth */
95 		count += ts - (count % ts);
96 	    else
97 		/* In list mode, when tab is not set, count screen char width
98 		 * for Tab, displays: ^I */
99 		count += ptr2cells(ptr);
100 	}
101 	else if (*ptr == ' ')
102 	    ++count;		/* count a space for one */
103 	else
104 	    break;
105     }
106     return count;
107 }
108 
109 #ifdef FEAT_VARTABS
110 /*
111  * Count the size (in window cells) of the indent in line "ptr", using
112  * variable tabstops.
113  * if "list" is TRUE, count only screen size for tabs.
114  */
115     int
116 get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
117 {
118     int		count = 0;
119 
120     for ( ; *ptr; ++ptr)
121     {
122 	if (*ptr == TAB)    /* count a tab for what it is worth */
123 	{
124 	    if (!list || lcs_tab1)
125 		count += tabstop_padding(count, ts, vts);
126 	    else
127 		/* In list mode, when tab is not set, count screen char width
128 		 * for Tab, displays: ^I */
129 		count += ptr2cells(ptr);
130 	}
131 	else if (*ptr == ' ')
132 	    ++count;		/* count a space for one */
133 	else
134 	    break;
135     }
136     return count;
137 }
138 #endif
139 
140 /*
141  * Set the indent of the current line.
142  * Leaves the cursor on the first non-blank in the line.
143  * Caller must take care of undo.
144  * "flags":
145  *	SIN_CHANGED:	call changed_bytes() if the line was changed.
146  *	SIN_INSERT:	insert the indent in front of the line.
147  *	SIN_UNDO:	save line for undo before changing it.
148  * Returns TRUE if the line was changed.
149  */
150     int
151 set_indent(
152     int		size,		    /* measured in spaces */
153     int		flags)
154 {
155     char_u	*p;
156     char_u	*newline;
157     char_u	*oldline;
158     char_u	*s;
159     int		todo;
160     int		ind_len;	    /* measured in characters */
161     int		line_len;
162     int		doit = FALSE;
163     int		ind_done = 0;	    /* measured in spaces */
164 #ifdef FEAT_VARTABS
165     int		ind_col = 0;
166 #endif
167     int		tab_pad;
168     int		retval = FALSE;
169     int		orig_char_len = -1; /* number of initial whitespace chars when
170 				       'et' and 'pi' are both set */
171 
172     /*
173      * First check if there is anything to do and compute the number of
174      * characters needed for the indent.
175      */
176     todo = size;
177     ind_len = 0;
178     p = oldline = ml_get_curline();
179 
180     /* Calculate the buffer size for the new indent, and check to see if it
181      * isn't already set */
182 
183     /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and
184      * 'preserveindent' are set count the number of characters at the
185      * beginning of the line to be copied */
186     if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi))
187     {
188 	/* If 'preserveindent' is set then reuse as much as possible of
189 	 * the existing indent structure for the new indent */
190 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
191 	{
192 	    ind_done = 0;
193 
194 	    /* count as many characters as we can use */
195 	    while (todo > 0 && VIM_ISWHITE(*p))
196 	    {
197 		if (*p == TAB)
198 		{
199 #ifdef FEAT_VARTABS
200 		    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
201 							curbuf->b_p_vts_array);
202 #else
203 		    tab_pad = (int)curbuf->b_p_ts
204 					   - (ind_done % (int)curbuf->b_p_ts);
205 #endif
206 		    /* stop if this tab will overshoot the target */
207 		    if (todo < tab_pad)
208 			break;
209 		    todo -= tab_pad;
210 		    ++ind_len;
211 		    ind_done += tab_pad;
212 		}
213 		else
214 		{
215 		    --todo;
216 		    ++ind_len;
217 		    ++ind_done;
218 		}
219 		++p;
220 	    }
221 
222 #ifdef FEAT_VARTABS
223 	    /* These diverge from this point. */
224 	    ind_col = ind_done;
225 #endif
226 	    /* Set initial number of whitespace chars to copy if we are
227 	     * preserving indent but expandtab is set */
228 	    if (curbuf->b_p_et)
229 		orig_char_len = ind_len;
230 
231 	    /* Fill to next tabstop with a tab, if possible */
232 #ifdef FEAT_VARTABS
233 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
234 						curbuf->b_p_vts_array);
235 #else
236 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
237 #endif
238 	    if (todo >= tab_pad && orig_char_len == -1)
239 	    {
240 		doit = TRUE;
241 		todo -= tab_pad;
242 		++ind_len;
243 		/* ind_done += tab_pad; */
244 #ifdef FEAT_VARTABS
245 		ind_col += tab_pad;
246 #endif
247 	    }
248 	}
249 
250 	/* count tabs required for indent */
251 #ifdef FEAT_VARTABS
252 	for (;;)
253 	{
254 	    tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
255 							curbuf->b_p_vts_array);
256 	    if (todo < tab_pad)
257 		break;
258 	    if (*p != TAB)
259 		doit = TRUE;
260 	    else
261 		++p;
262 	    todo -= tab_pad;
263 	    ++ind_len;
264 	    ind_col += tab_pad;
265 	}
266 #else
267 	while (todo >= (int)curbuf->b_p_ts)
268 	{
269 	    if (*p != TAB)
270 		doit = TRUE;
271 	    else
272 		++p;
273 	    todo -= (int)curbuf->b_p_ts;
274 	    ++ind_len;
275 	    /* ind_done += (int)curbuf->b_p_ts; */
276 	}
277 #endif
278     }
279     /* count spaces required for indent */
280     while (todo > 0)
281     {
282 	if (*p != ' ')
283 	    doit = TRUE;
284 	else
285 	    ++p;
286 	--todo;
287 	++ind_len;
288 	/* ++ind_done; */
289     }
290 
291     /* Return if the indent is OK already. */
292     if (!doit && !VIM_ISWHITE(*p) && !(flags & SIN_INSERT))
293 	return FALSE;
294 
295     /* Allocate memory for the new line. */
296     if (flags & SIN_INSERT)
297 	p = oldline;
298     else
299 	p = skipwhite(p);
300     line_len = (int)STRLEN(p) + 1;
301 
302     /* If 'preserveindent' and 'expandtab' are both set keep the original
303      * characters and allocate accordingly.  We will fill the rest with spaces
304      * after the if (!curbuf->b_p_et) below. */
305     if (orig_char_len != -1)
306     {
307 	newline = alloc(orig_char_len + size - ind_done + line_len);
308 	if (newline == NULL)
309 	    return FALSE;
310 	todo = size - ind_done;
311 	ind_len = orig_char_len + todo;    /* Set total length of indent in
312 					    * characters, which may have been
313 					    * undercounted until now  */
314 	p = oldline;
315 	s = newline;
316 	while (orig_char_len > 0)
317 	{
318 	    *s++ = *p++;
319 	    orig_char_len--;
320 	}
321 
322 	/* Skip over any additional white space (useful when newindent is less
323 	 * than old) */
324 	while (VIM_ISWHITE(*p))
325 	    ++p;
326 
327     }
328     else
329     {
330 	todo = size;
331 	newline = alloc(ind_len + line_len);
332 	if (newline == NULL)
333 	    return FALSE;
334 	s = newline;
335     }
336 
337     /* Put the characters in the new line. */
338     /* if 'expandtab' isn't set: use TABs */
339     if (!curbuf->b_p_et)
340     {
341 	/* If 'preserveindent' is set then reuse as much as possible of
342 	 * the existing indent structure for the new indent */
343 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
344 	{
345 	    p = oldline;
346 	    ind_done = 0;
347 
348 	    while (todo > 0 && VIM_ISWHITE(*p))
349 	    {
350 		if (*p == TAB)
351 		{
352 #ifdef FEAT_VARTABS
353 		    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
354 							curbuf->b_p_vts_array);
355 #else
356 		    tab_pad = (int)curbuf->b_p_ts
357 					   - (ind_done % (int)curbuf->b_p_ts);
358 #endif
359 		    /* stop if this tab will overshoot the target */
360 		    if (todo < tab_pad)
361 			break;
362 		    todo -= tab_pad;
363 		    ind_done += tab_pad;
364 		}
365 		else
366 		{
367 		    --todo;
368 		    ++ind_done;
369 		}
370 		*s++ = *p++;
371 	    }
372 
373 	    /* Fill to next tabstop with a tab, if possible */
374 #ifdef FEAT_VARTABS
375 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
376 						curbuf->b_p_vts_array);
377 #else
378 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
379 #endif
380 	    if (todo >= tab_pad)
381 	    {
382 		*s++ = TAB;
383 		todo -= tab_pad;
384 #ifdef FEAT_VARTABS
385 		ind_done += tab_pad;
386 #endif
387 	    }
388 
389 	    p = skipwhite(p);
390 	}
391 
392 #ifdef FEAT_VARTABS
393 	for (;;)
394 	{
395 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
396 							curbuf->b_p_vts_array);
397 	    if (todo < tab_pad)
398 		break;
399 	    *s++ = TAB;
400 	    todo -= tab_pad;
401 	    ind_done += tab_pad;
402 	}
403 #else
404 	while (todo >= (int)curbuf->b_p_ts)
405 	{
406 	    *s++ = TAB;
407 	    todo -= (int)curbuf->b_p_ts;
408 	}
409 #endif
410     }
411     while (todo > 0)
412     {
413 	*s++ = ' ';
414 	--todo;
415     }
416     mch_memmove(s, p, (size_t)line_len);
417 
418     /* Replace the line (unless undo fails). */
419     if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK)
420     {
421 	ml_replace(curwin->w_cursor.lnum, newline, FALSE);
422 	if (flags & SIN_CHANGED)
423 	    changed_bytes(curwin->w_cursor.lnum, 0);
424 	/* Correct saved cursor position if it is in this line. */
425 	if (saved_cursor.lnum == curwin->w_cursor.lnum)
426 	{
427 	    if (saved_cursor.col >= (colnr_T)(p - oldline))
428 		/* cursor was after the indent, adjust for the number of
429 		 * bytes added/removed */
430 		saved_cursor.col += ind_len - (colnr_T)(p - oldline);
431 	    else if (saved_cursor.col >= (colnr_T)(s - newline))
432 		/* cursor was in the indent, and is now after it, put it back
433 		 * at the start of the indent (replacing spaces with TAB) */
434 		saved_cursor.col = (colnr_T)(s - newline);
435 	}
436 	retval = TRUE;
437     }
438     else
439 	vim_free(newline);
440 
441     curwin->w_cursor.col = ind_len;
442     return retval;
443 }
444 
445 /*
446  * Copy the indent from ptr to the current line (and fill to size)
447  * Leaves the cursor on the first non-blank in the line.
448  * Returns TRUE if the line was changed.
449  */
450     static int
451 copy_indent(int size, char_u *src)
452 {
453     char_u	*p = NULL;
454     char_u	*line = NULL;
455     char_u	*s;
456     int		todo;
457     int		ind_len;
458     int		line_len = 0;
459     int		tab_pad;
460     int		ind_done;
461     int		round;
462 #ifdef FEAT_VARTABS
463     int		ind_col;
464 #endif
465 
466     /* Round 1: compute the number of characters needed for the indent
467      * Round 2: copy the characters. */
468     for (round = 1; round <= 2; ++round)
469     {
470 	todo = size;
471 	ind_len = 0;
472 	ind_done = 0;
473 #ifdef FEAT_VARTABS
474 	ind_col = 0;
475 #endif
476 	s = src;
477 
478 	/* Count/copy the usable portion of the source line */
479 	while (todo > 0 && VIM_ISWHITE(*s))
480 	{
481 	    if (*s == TAB)
482 	    {
483 #ifdef FEAT_VARTABS
484 		tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
485 							curbuf->b_p_vts_array);
486 #else
487 		tab_pad = (int)curbuf->b_p_ts
488 					   - (ind_done % (int)curbuf->b_p_ts);
489 #endif
490 		/* Stop if this tab will overshoot the target */
491 		if (todo < tab_pad)
492 		    break;
493 		todo -= tab_pad;
494 		ind_done += tab_pad;
495 #ifdef FEAT_VARTABS
496 		ind_col += tab_pad;
497 #endif
498 	    }
499 	    else
500 	    {
501 		--todo;
502 		++ind_done;
503 #ifdef FEAT_VARTABS
504 		++ind_col;
505 #endif
506 	    }
507 	    ++ind_len;
508 	    if (p != NULL)
509 		*p++ = *s;
510 	    ++s;
511 	}
512 
513 	/* Fill to next tabstop with a tab, if possible */
514 #ifdef FEAT_VARTABS
515 	tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
516 							curbuf->b_p_vts_array);
517 #else
518 	tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
519 #endif
520 	if (todo >= tab_pad && !curbuf->b_p_et)
521 	{
522 	    todo -= tab_pad;
523 	    ++ind_len;
524 #ifdef FEAT_VARTABS
525 	    ind_col += tab_pad;
526 #endif
527 	    if (p != NULL)
528 		*p++ = TAB;
529 	}
530 
531 	/* Add tabs required for indent */
532 	if (!curbuf->b_p_et)
533 	{
534 #ifdef FEAT_VARTABS
535 	    for (;;)
536 	    {
537 		tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
538 							curbuf->b_p_vts_array);
539 		if (todo < tab_pad)
540 		    break;
541 		todo -= tab_pad;
542 		++ind_len;
543 		ind_col += tab_pad;
544 		if (p != NULL)
545 		    *p++ = TAB;
546 	    }
547 #else
548 	    while (todo >= (int)curbuf->b_p_ts)
549 	    {
550 		todo -= (int)curbuf->b_p_ts;
551 		++ind_len;
552 		if (p != NULL)
553 		    *p++ = TAB;
554 	    }
555 #endif
556 	}
557 
558 	/* Count/add spaces required for indent */
559 	while (todo > 0)
560 	{
561 	    --todo;
562 	    ++ind_len;
563 	    if (p != NULL)
564 		*p++ = ' ';
565 	}
566 
567 	if (p == NULL)
568 	{
569 	    /* Allocate memory for the result: the copied indent, new indent
570 	     * and the rest of the line. */
571 	    line_len = (int)STRLEN(ml_get_curline()) + 1;
572 	    line = alloc(ind_len + line_len);
573 	    if (line == NULL)
574 		return FALSE;
575 	    p = line;
576 	}
577     }
578 
579     /* Append the original line */
580     mch_memmove(p, ml_get_curline(), (size_t)line_len);
581 
582     /* Replace the line */
583     ml_replace(curwin->w_cursor.lnum, line, FALSE);
584 
585     /* Put the cursor after the indent. */
586     curwin->w_cursor.col = ind_len;
587     return TRUE;
588 }
589 
590 /*
591  * Return the indent of the current line after a number.  Return -1 if no
592  * number was found.  Used for 'n' in 'formatoptions': numbered list.
593  * Since a pattern is used it can actually handle more than numbers.
594  */
595     int
596 get_number_indent(linenr_T lnum)
597 {
598     colnr_T	col;
599     pos_T	pos;
600 
601     regmatch_T	regmatch;
602     int		lead_len = 0;	/* length of comment leader */
603 
604     if (lnum > curbuf->b_ml.ml_line_count)
605 	return -1;
606     pos.lnum = 0;
607 
608 #ifdef FEAT_COMMENTS
609     /* In format_lines() (i.e. not insert mode), fo+=q is needed too...  */
610     if ((State & INSERT) || has_format_option(FO_Q_COMS))
611 	lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE);
612 #endif
613     regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
614     if (regmatch.regprog != NULL)
615     {
616 	regmatch.rm_ic = FALSE;
617 
618 	/* vim_regexec() expects a pointer to a line.  This lets us
619 	 * start matching for the flp beyond any comment leader...  */
620 	if (vim_regexec(&regmatch, ml_get(lnum) + lead_len, (colnr_T)0))
621 	{
622 	    pos.lnum = lnum;
623 	    pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum));
624 #ifdef FEAT_VIRTUALEDIT
625 	    pos.coladd = 0;
626 #endif
627 	}
628 	vim_regfree(regmatch.regprog);
629     }
630 
631     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
632 	return -1;
633     getvcol(curwin, &pos, &col, NULL, NULL);
634     return (int)col;
635 }
636 
637 #if defined(FEAT_LINEBREAK) || defined(PROTO)
638 /*
639  * Return appropriate space number for breakindent, taking influencing
640  * parameters into account. Window must be specified, since it is not
641  * necessarily always the current one.
642  */
643     int
644 get_breakindent_win(
645     win_T	*wp,
646     char_u	*line) /* start of the line */
647 {
648     static int	    prev_indent = 0;  /* cached indent value */
649     static long	    prev_ts     = 0L; /* cached tabstop value */
650     static char_u   *prev_line = NULL; /* cached pointer to line */
651     static varnumber_T prev_tick = 0;   /* changedtick of cached value */
652 #ifdef FEAT_VARTABS
653     static int      *prev_vts = NULL;    /* cached vartabs values */
654 #endif
655     int		    bri = 0;
656     /* window width minus window margin space, i.e. what rests for text */
657     const int	    eff_wwidth = wp->w_width
658 			    - ((wp->w_p_nu || wp->w_p_rnu)
659 				&& (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
660 						? number_width(wp) + 1 : 0);
661 
662     /* used cached indent, unless pointer or 'tabstop' changed */
663     if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
664 	    || prev_tick != CHANGEDTICK(wp->w_buffer)
665 #ifdef FEAT_VARTABS
666 	    || prev_vts != wp->w_buffer->b_p_vts_array
667 #endif
668 	)
669     {
670 	prev_line = line;
671 	prev_ts = wp->w_buffer->b_p_ts;
672 	prev_tick = CHANGEDTICK(wp->w_buffer);
673 #ifdef FEAT_VARTABS
674 	prev_vts = wp->w_buffer->b_p_vts_array;
675 	prev_indent = get_indent_str_vtab(line,
676 				     (int)wp->w_buffer->b_p_ts,
677 				    wp->w_buffer->b_p_vts_array, wp->w_p_list);
678 #else
679 	prev_indent = get_indent_str(line,
680 				     (int)wp->w_buffer->b_p_ts, wp->w_p_list);
681 #endif
682     }
683     bri = prev_indent + wp->w_p_brishift;
684 
685     /* indent minus the length of the showbreak string */
686     if (wp->w_p_brisbr)
687 	bri -= vim_strsize(p_sbr);
688 
689     /* Add offset for number column, if 'n' is in 'cpoptions' */
690     bri += win_col_off2(wp);
691 
692     /* never indent past left window margin */
693     if (bri < 0)
694 	bri = 0;
695     /* always leave at least bri_min characters on the left,
696      * if text width is sufficient */
697     else if (bri > eff_wwidth - wp->w_p_brimin)
698 	bri = (eff_wwidth - wp->w_p_brimin < 0)
699 			    ? 0 : eff_wwidth - wp->w_p_brimin;
700 
701     return bri;
702 }
703 #endif
704 
705 
706 #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
707 
708 static int cin_is_cinword(char_u *line);
709 
710 /*
711  * Return TRUE if the string "line" starts with a word from 'cinwords'.
712  */
713     static int
714 cin_is_cinword(char_u *line)
715 {
716     char_u	*cinw;
717     char_u	*cinw_buf;
718     int		cinw_len;
719     int		retval = FALSE;
720     int		len;
721 
722     cinw_len = (int)STRLEN(curbuf->b_p_cinw) + 1;
723     cinw_buf = alloc((unsigned)cinw_len);
724     if (cinw_buf != NULL)
725     {
726 	line = skipwhite(line);
727 	for (cinw = curbuf->b_p_cinw; *cinw; )
728 	{
729 	    len = copy_option_part(&cinw, cinw_buf, cinw_len, ",");
730 	    if (STRNCMP(line, cinw_buf, len) == 0
731 		    && (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1])))
732 	    {
733 		retval = TRUE;
734 		break;
735 	    }
736 	}
737 	vim_free(cinw_buf);
738     }
739     return retval;
740 }
741 #endif
742 
743 /*
744  * open_line: Add a new line below or above the current line.
745  *
746  * For VREPLACE mode, we only add a new line when we get to the end of the
747  * file, otherwise we just start replacing the next line.
748  *
749  * Caller must take care of undo.  Since VREPLACE may affect any number of
750  * lines however, it may call u_save_cursor() again when starting to change a
751  * new line.
752  * "flags": OPENLINE_DELSPACES	delete spaces after cursor
753  *	    OPENLINE_DO_COM	format comments
754  *	    OPENLINE_KEEPTRAIL	keep trailing spaces
755  *	    OPENLINE_MARKFIX	adjust mark positions after the line break
756  *	    OPENLINE_COM_LIST	format comments with list or 2nd line indent
757  *
758  * "second_line_indent": indent for after ^^D in Insert mode or if flag
759  *			  OPENLINE_COM_LIST
760  *
761  * Return OK for success, FAIL for failure
762  */
763     int
764 open_line(
765     int		dir,		/* FORWARD or BACKWARD */
766     int		flags,
767     int		second_line_indent)
768 {
769     char_u	*saved_line;		/* copy of the original line */
770     char_u	*next_line = NULL;	/* copy of the next line */
771     char_u	*p_extra = NULL;	/* what goes to next line */
772     int		less_cols = 0;		/* less columns for mark in new line */
773     int		less_cols_off = 0;	/* columns to skip for mark adjust */
774     pos_T	old_cursor;		/* old cursor position */
775     int		newcol = 0;		/* new cursor column */
776     int		newindent = 0;		/* auto-indent of the new line */
777     int		n;
778     int		trunc_line = FALSE;	/* truncate current line afterwards */
779     int		retval = FAIL;		/* return value */
780 #ifdef FEAT_COMMENTS
781     int		extra_len = 0;		/* length of p_extra string */
782     int		lead_len;		/* length of comment leader */
783     char_u	*lead_flags;	/* position in 'comments' for comment leader */
784     char_u	*leader = NULL;		/* copy of comment leader */
785 #endif
786     char_u	*allocated = NULL;	/* allocated memory */
787     char_u	*p;
788     int		saved_char = NUL;	/* init for GCC */
789 #if defined(FEAT_SMARTINDENT) || defined(FEAT_COMMENTS)
790     pos_T	*pos;
791 #endif
792 #ifdef FEAT_SMARTINDENT
793     int		do_si = (!p_paste && curbuf->b_p_si
794 # ifdef FEAT_CINDENT
795 					&& !curbuf->b_p_cin
796 # endif
797 # ifdef FEAT_EVAL
798 					&& *curbuf->b_p_inde == NUL
799 # endif
800 			);
801     int		no_si = FALSE;		/* reset did_si afterwards */
802     int		first_char = NUL;	/* init for GCC */
803 #endif
804 #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
805     int		vreplace_mode;
806 #endif
807     int		did_append;		/* appended a new line */
808     int		saved_pi = curbuf->b_p_pi; /* copy of preserveindent setting */
809 
810     /*
811      * make a copy of the current line so we can mess with it
812      */
813     saved_line = vim_strsave(ml_get_curline());
814     if (saved_line == NULL)	    /* out of memory! */
815 	return FALSE;
816 
817     if (State & VREPLACE_FLAG)
818     {
819 	/*
820 	 * With VREPLACE we make a copy of the next line, which we will be
821 	 * starting to replace.  First make the new line empty and let vim play
822 	 * with the indenting and comment leader to its heart's content.  Then
823 	 * we grab what it ended up putting on the new line, put back the
824 	 * original line, and call ins_char() to put each new character onto
825 	 * the line, replacing what was there before and pushing the right
826 	 * stuff onto the replace stack.  -- webb.
827 	 */
828 	if (curwin->w_cursor.lnum < orig_line_count)
829 	    next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1));
830 	else
831 	    next_line = vim_strsave((char_u *)"");
832 	if (next_line == NULL)	    /* out of memory! */
833 	    goto theend;
834 
835 	/*
836 	 * In VREPLACE mode, a NL replaces the rest of the line, and starts
837 	 * replacing the next line, so push all of the characters left on the
838 	 * line onto the replace stack.  We'll push any other characters that
839 	 * might be replaced at the start of the next line (due to autoindent
840 	 * etc) a bit later.
841 	 */
842 	replace_push(NUL);  /* Call twice because BS over NL expects it */
843 	replace_push(NUL);
844 	p = saved_line + curwin->w_cursor.col;
845 	while (*p != NUL)
846 	{
847 #ifdef FEAT_MBYTE
848 	    if (has_mbyte)
849 		p += replace_push_mb(p);
850 	    else
851 #endif
852 		replace_push(*p++);
853 	}
854 	saved_line[curwin->w_cursor.col] = NUL;
855     }
856 
857     if ((State & INSERT) && !(State & VREPLACE_FLAG))
858     {
859 	p_extra = saved_line + curwin->w_cursor.col;
860 #ifdef FEAT_SMARTINDENT
861 	if (do_si)		/* need first char after new line break */
862 	{
863 	    p = skipwhite(p_extra);
864 	    first_char = *p;
865 	}
866 #endif
867 #ifdef FEAT_COMMENTS
868 	extra_len = (int)STRLEN(p_extra);
869 #endif
870 	saved_char = *p_extra;
871 	*p_extra = NUL;
872     }
873 
874     u_clearline();		/* cannot do "U" command when adding lines */
875 #ifdef FEAT_SMARTINDENT
876     did_si = FALSE;
877 #endif
878     ai_col = 0;
879 
880     /*
881      * If we just did an auto-indent, then we didn't type anything on
882      * the prior line, and it should be truncated.  Do this even if 'ai' is not
883      * set because automatically inserting a comment leader also sets did_ai.
884      */
885     if (dir == FORWARD && did_ai)
886 	trunc_line = TRUE;
887 
888     /*
889      * If 'autoindent' and/or 'smartindent' is set, try to figure out what
890      * indent to use for the new line.
891      */
892     if (curbuf->b_p_ai
893 #ifdef FEAT_SMARTINDENT
894 			|| do_si
895 #endif
896 					    )
897     {
898 	/*
899 	 * count white space on current line
900 	 */
901 #ifdef FEAT_VARTABS
902 	newindent = get_indent_str_vtab(saved_line, curbuf->b_p_ts,
903 						 curbuf->b_p_vts_array, FALSE);
904 #else
905 	newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE);
906 #endif
907 	if (newindent == 0 && !(flags & OPENLINE_COM_LIST))
908 	    newindent = second_line_indent; /* for ^^D command in insert mode */
909 
910 #ifdef FEAT_SMARTINDENT
911 	/*
912 	 * Do smart indenting.
913 	 * In insert/replace mode (only when dir == FORWARD)
914 	 * we may move some text to the next line. If it starts with '{'
915 	 * don't add an indent. Fixes inserting a NL before '{' in line
916 	 *	"if (condition) {"
917 	 */
918 	if (!trunc_line && do_si && *saved_line != NUL
919 				    && (p_extra == NULL || first_char != '{'))
920 	{
921 	    char_u  *ptr;
922 	    char_u  last_char;
923 
924 	    old_cursor = curwin->w_cursor;
925 	    ptr = saved_line;
926 # ifdef FEAT_COMMENTS
927 	    if (flags & OPENLINE_DO_COM)
928 		lead_len = get_leader_len(ptr, NULL, FALSE, TRUE);
929 	    else
930 		lead_len = 0;
931 # endif
932 	    if (dir == FORWARD)
933 	    {
934 		/*
935 		 * Skip preprocessor directives, unless they are
936 		 * recognised as comments.
937 		 */
938 		if (
939 # ifdef FEAT_COMMENTS
940 			lead_len == 0 &&
941 # endif
942 			ptr[0] == '#')
943 		{
944 		    while (ptr[0] == '#' && curwin->w_cursor.lnum > 1)
945 			ptr = ml_get(--curwin->w_cursor.lnum);
946 		    newindent = get_indent();
947 		}
948 # ifdef FEAT_COMMENTS
949 		if (flags & OPENLINE_DO_COM)
950 		    lead_len = get_leader_len(ptr, NULL, FALSE, TRUE);
951 		else
952 		    lead_len = 0;
953 		if (lead_len > 0)
954 		{
955 		    /*
956 		     * This case gets the following right:
957 		     *	    \*
958 		     *	     * A comment (read '\' as '/').
959 		     *	     *\
960 		     * #define IN_THE_WAY
961 		     *	    This should line up here;
962 		     */
963 		    p = skipwhite(ptr);
964 		    if (p[0] == '/' && p[1] == '*')
965 			p++;
966 		    if (p[0] == '*')
967 		    {
968 			for (p++; *p; p++)
969 			{
970 			    if (p[0] == '/' && p[-1] == '*')
971 			    {
972 				/*
973 				 * End of C comment, indent should line up
974 				 * with the line containing the start of
975 				 * the comment
976 				 */
977 				curwin->w_cursor.col = (colnr_T)(p - ptr);
978 				if ((pos = findmatch(NULL, NUL)) != NULL)
979 				{
980 				    curwin->w_cursor.lnum = pos->lnum;
981 				    newindent = get_indent();
982 				}
983 			    }
984 			}
985 		    }
986 		}
987 		else	/* Not a comment line */
988 # endif
989 		{
990 		    /* Find last non-blank in line */
991 		    p = ptr + STRLEN(ptr) - 1;
992 		    while (p > ptr && VIM_ISWHITE(*p))
993 			--p;
994 		    last_char = *p;
995 
996 		    /*
997 		     * find the character just before the '{' or ';'
998 		     */
999 		    if (last_char == '{' || last_char == ';')
1000 		    {
1001 			if (p > ptr)
1002 			    --p;
1003 			while (p > ptr && VIM_ISWHITE(*p))
1004 			    --p;
1005 		    }
1006 		    /*
1007 		     * Try to catch lines that are split over multiple
1008 		     * lines.  eg:
1009 		     *	    if (condition &&
1010 		     *			condition) {
1011 		     *		Should line up here!
1012 		     *	    }
1013 		     */
1014 		    if (*p == ')')
1015 		    {
1016 			curwin->w_cursor.col = (colnr_T)(p - ptr);
1017 			if ((pos = findmatch(NULL, '(')) != NULL)
1018 			{
1019 			    curwin->w_cursor.lnum = pos->lnum;
1020 			    newindent = get_indent();
1021 			    ptr = ml_get_curline();
1022 			}
1023 		    }
1024 		    /*
1025 		     * If last character is '{' do indent, without
1026 		     * checking for "if" and the like.
1027 		     */
1028 		    if (last_char == '{')
1029 		    {
1030 			did_si = TRUE;	/* do indent */
1031 			no_si = TRUE;	/* don't delete it when '{' typed */
1032 		    }
1033 		    /*
1034 		     * Look for "if" and the like, use 'cinwords'.
1035 		     * Don't do this if the previous line ended in ';' or
1036 		     * '}'.
1037 		     */
1038 		    else if (last_char != ';' && last_char != '}'
1039 						       && cin_is_cinword(ptr))
1040 			did_si = TRUE;
1041 		}
1042 	    }
1043 	    else /* dir == BACKWARD */
1044 	    {
1045 		/*
1046 		 * Skip preprocessor directives, unless they are
1047 		 * recognised as comments.
1048 		 */
1049 		if (
1050 # ifdef FEAT_COMMENTS
1051 			lead_len == 0 &&
1052 # endif
1053 			ptr[0] == '#')
1054 		{
1055 		    int was_backslashed = FALSE;
1056 
1057 		    while ((ptr[0] == '#' || was_backslashed) &&
1058 			 curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
1059 		    {
1060 			if (*ptr && ptr[STRLEN(ptr) - 1] == '\\')
1061 			    was_backslashed = TRUE;
1062 			else
1063 			    was_backslashed = FALSE;
1064 			ptr = ml_get(++curwin->w_cursor.lnum);
1065 		    }
1066 		    if (was_backslashed)
1067 			newindent = 0;	    /* Got to end of file */
1068 		    else
1069 			newindent = get_indent();
1070 		}
1071 		p = skipwhite(ptr);
1072 		if (*p == '}')	    /* if line starts with '}': do indent */
1073 		    did_si = TRUE;
1074 		else		    /* can delete indent when '{' typed */
1075 		    can_si_back = TRUE;
1076 	    }
1077 	    curwin->w_cursor = old_cursor;
1078 	}
1079 	if (do_si)
1080 	    can_si = TRUE;
1081 #endif /* FEAT_SMARTINDENT */
1082 
1083 	did_ai = TRUE;
1084     }
1085 
1086 #ifdef FEAT_COMMENTS
1087     /*
1088      * Find out if the current line starts with a comment leader.
1089      * This may then be inserted in front of the new line.
1090      */
1091     end_comment_pending = NUL;
1092     if (flags & OPENLINE_DO_COM)
1093 	lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD, TRUE);
1094     else
1095 	lead_len = 0;
1096     if (lead_len > 0)
1097     {
1098 	char_u	*lead_repl = NULL;	    /* replaces comment leader */
1099 	int	lead_repl_len = 0;	    /* length of *lead_repl */
1100 	char_u	lead_middle[COM_MAX_LEN];   /* middle-comment string */
1101 	char_u	lead_end[COM_MAX_LEN];	    /* end-comment string */
1102 	char_u	*comment_end = NULL;	    /* where lead_end has been found */
1103 	int	extra_space = FALSE;	    /* append extra space */
1104 	int	current_flag;
1105 	int	require_blank = FALSE;	    /* requires blank after middle */
1106 	char_u	*p2;
1107 
1108 	/*
1109 	 * If the comment leader has the start, middle or end flag, it may not
1110 	 * be used or may be replaced with the middle leader.
1111 	 */
1112 	for (p = lead_flags; *p && *p != ':'; ++p)
1113 	{
1114 	    if (*p == COM_BLANK)
1115 	    {
1116 		require_blank = TRUE;
1117 		continue;
1118 	    }
1119 	    if (*p == COM_START || *p == COM_MIDDLE)
1120 	    {
1121 		current_flag = *p;
1122 		if (*p == COM_START)
1123 		{
1124 		    /*
1125 		     * Doing "O" on a start of comment does not insert leader.
1126 		     */
1127 		    if (dir == BACKWARD)
1128 		    {
1129 			lead_len = 0;
1130 			break;
1131 		    }
1132 
1133 		    /* find start of middle part */
1134 		    (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
1135 		    require_blank = FALSE;
1136 		}
1137 
1138 		/*
1139 		 * Isolate the strings of the middle and end leader.
1140 		 */
1141 		while (*p && p[-1] != ':')	/* find end of middle flags */
1142 		{
1143 		    if (*p == COM_BLANK)
1144 			require_blank = TRUE;
1145 		    ++p;
1146 		}
1147 		(void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
1148 
1149 		while (*p && p[-1] != ':')	/* find end of end flags */
1150 		{
1151 		    /* Check whether we allow automatic ending of comments */
1152 		    if (*p == COM_AUTO_END)
1153 			end_comment_pending = -1; /* means we want to set it */
1154 		    ++p;
1155 		}
1156 		n = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
1157 
1158 		if (end_comment_pending == -1)	/* we can set it now */
1159 		    end_comment_pending = lead_end[n - 1];
1160 
1161 		/*
1162 		 * If the end of the comment is in the same line, don't use
1163 		 * the comment leader.
1164 		 */
1165 		if (dir == FORWARD)
1166 		{
1167 		    for (p = saved_line + lead_len; *p; ++p)
1168 			if (STRNCMP(p, lead_end, n) == 0)
1169 			{
1170 			    comment_end = p;
1171 			    lead_len = 0;
1172 			    break;
1173 			}
1174 		}
1175 
1176 		/*
1177 		 * Doing "o" on a start of comment inserts the middle leader.
1178 		 */
1179 		if (lead_len > 0)
1180 		{
1181 		    if (current_flag == COM_START)
1182 		    {
1183 			lead_repl = lead_middle;
1184 			lead_repl_len = (int)STRLEN(lead_middle);
1185 		    }
1186 
1187 		    /*
1188 		     * If we have hit RETURN immediately after the start
1189 		     * comment leader, then put a space after the middle
1190 		     * comment leader on the next line.
1191 		     */
1192 		    if (!VIM_ISWHITE(saved_line[lead_len - 1])
1193 			    && ((p_extra != NULL
1194 				    && (int)curwin->w_cursor.col == lead_len)
1195 				|| (p_extra == NULL
1196 				    && saved_line[lead_len] == NUL)
1197 				|| require_blank))
1198 			extra_space = TRUE;
1199 		}
1200 		break;
1201 	    }
1202 	    if (*p == COM_END)
1203 	    {
1204 		/*
1205 		 * Doing "o" on the end of a comment does not insert leader.
1206 		 * Remember where the end is, might want to use it to find the
1207 		 * start (for C-comments).
1208 		 */
1209 		if (dir == FORWARD)
1210 		{
1211 		    comment_end = skipwhite(saved_line);
1212 		    lead_len = 0;
1213 		    break;
1214 		}
1215 
1216 		/*
1217 		 * Doing "O" on the end of a comment inserts the middle leader.
1218 		 * Find the string for the middle leader, searching backwards.
1219 		 */
1220 		while (p > curbuf->b_p_com && *p != ',')
1221 		    --p;
1222 		for (lead_repl = p; lead_repl > curbuf->b_p_com
1223 					 && lead_repl[-1] != ':'; --lead_repl)
1224 		    ;
1225 		lead_repl_len = (int)(p - lead_repl);
1226 
1227 		/* We can probably always add an extra space when doing "O" on
1228 		 * the comment-end */
1229 		extra_space = TRUE;
1230 
1231 		/* Check whether we allow automatic ending of comments */
1232 		for (p2 = p; *p2 && *p2 != ':'; p2++)
1233 		{
1234 		    if (*p2 == COM_AUTO_END)
1235 			end_comment_pending = -1; /* means we want to set it */
1236 		}
1237 		if (end_comment_pending == -1)
1238 		{
1239 		    /* Find last character in end-comment string */
1240 		    while (*p2 && *p2 != ',')
1241 			p2++;
1242 		    end_comment_pending = p2[-1];
1243 		}
1244 		break;
1245 	    }
1246 	    if (*p == COM_FIRST)
1247 	    {
1248 		/*
1249 		 * Comment leader for first line only:	Don't repeat leader
1250 		 * when using "O", blank out leader when using "o".
1251 		 */
1252 		if (dir == BACKWARD)
1253 		    lead_len = 0;
1254 		else
1255 		{
1256 		    lead_repl = (char_u *)"";
1257 		    lead_repl_len = 0;
1258 		}
1259 		break;
1260 	    }
1261 	}
1262 	if (lead_len)
1263 	{
1264 	    /* allocate buffer (may concatenate p_extra later) */
1265 	    leader = alloc(lead_len + lead_repl_len + extra_space + extra_len
1266 		     + (second_line_indent > 0 ? second_line_indent : 0) + 1);
1267 	    allocated = leader;		    /* remember to free it later */
1268 
1269 	    if (leader == NULL)
1270 		lead_len = 0;
1271 	    else
1272 	    {
1273 		vim_strncpy(leader, saved_line, lead_len);
1274 
1275 		/*
1276 		 * Replace leader with lead_repl, right or left adjusted
1277 		 */
1278 		if (lead_repl != NULL)
1279 		{
1280 		    int		c = 0;
1281 		    int		off = 0;
1282 
1283 		    for (p = lead_flags; *p != NUL && *p != ':'; )
1284 		    {
1285 			if (*p == COM_RIGHT || *p == COM_LEFT)
1286 			    c = *p++;
1287 			else if (VIM_ISDIGIT(*p) || *p == '-')
1288 			    off = getdigits(&p);
1289 			else
1290 			    ++p;
1291 		    }
1292 		    if (c == COM_RIGHT)    /* right adjusted leader */
1293 		    {
1294 			/* find last non-white in the leader to line up with */
1295 			for (p = leader + lead_len - 1; p > leader
1296 						      && VIM_ISWHITE(*p); --p)
1297 			    ;
1298 			++p;
1299 
1300 #ifdef FEAT_MBYTE
1301 			/* Compute the length of the replaced characters in
1302 			 * screen characters, not bytes. */
1303 			{
1304 			    int	    repl_size = vim_strnsize(lead_repl,
1305 							       lead_repl_len);
1306 			    int	    old_size = 0;
1307 			    char_u  *endp = p;
1308 			    int	    l;
1309 
1310 			    while (old_size < repl_size && p > leader)
1311 			    {
1312 				MB_PTR_BACK(leader, p);
1313 				old_size += ptr2cells(p);
1314 			    }
1315 			    l = lead_repl_len - (int)(endp - p);
1316 			    if (l != 0)
1317 				mch_memmove(endp + l, endp,
1318 					(size_t)((leader + lead_len) - endp));
1319 			    lead_len += l;
1320 			}
1321 #else
1322 			if (p < leader + lead_repl_len)
1323 			    p = leader;
1324 			else
1325 			    p -= lead_repl_len;
1326 #endif
1327 			mch_memmove(p, lead_repl, (size_t)lead_repl_len);
1328 			if (p + lead_repl_len > leader + lead_len)
1329 			    p[lead_repl_len] = NUL;
1330 
1331 			/* blank-out any other chars from the old leader. */
1332 			while (--p >= leader)
1333 			{
1334 #ifdef FEAT_MBYTE
1335 			    int l = mb_head_off(leader, p);
1336 
1337 			    if (l > 1)
1338 			    {
1339 				p -= l;
1340 				if (ptr2cells(p) > 1)
1341 				{
1342 				    p[1] = ' ';
1343 				    --l;
1344 				}
1345 				mch_memmove(p + 1, p + l + 1,
1346 				   (size_t)((leader + lead_len) - (p + l + 1)));
1347 				lead_len -= l;
1348 				*p = ' ';
1349 			    }
1350 			    else
1351 #endif
1352 			    if (!VIM_ISWHITE(*p))
1353 				*p = ' ';
1354 			}
1355 		    }
1356 		    else		    /* left adjusted leader */
1357 		    {
1358 			p = skipwhite(leader);
1359 #ifdef FEAT_MBYTE
1360 			/* Compute the length of the replaced characters in
1361 			 * screen characters, not bytes. Move the part that is
1362 			 * not to be overwritten. */
1363 			{
1364 			    int	    repl_size = vim_strnsize(lead_repl,
1365 							       lead_repl_len);
1366 			    int	    i;
1367 			    int	    l;
1368 
1369 			    for (i = 0; i < lead_len && p[i] != NUL; i += l)
1370 			    {
1371 				l = (*mb_ptr2len)(p + i);
1372 				if (vim_strnsize(p, i + l) > repl_size)
1373 				    break;
1374 			    }
1375 			    if (i != lead_repl_len)
1376 			    {
1377 				mch_memmove(p + lead_repl_len, p + i,
1378 				       (size_t)(lead_len - i - (p - leader)));
1379 				lead_len += lead_repl_len - i;
1380 			    }
1381 			}
1382 #endif
1383 			mch_memmove(p, lead_repl, (size_t)lead_repl_len);
1384 
1385 			/* Replace any remaining non-white chars in the old
1386 			 * leader by spaces.  Keep Tabs, the indent must
1387 			 * remain the same. */
1388 			for (p += lead_repl_len; p < leader + lead_len; ++p)
1389 			    if (!VIM_ISWHITE(*p))
1390 			    {
1391 				/* Don't put a space before a TAB. */
1392 				if (p + 1 < leader + lead_len && p[1] == TAB)
1393 				{
1394 				    --lead_len;
1395 				    mch_memmove(p, p + 1,
1396 						     (leader + lead_len) - p);
1397 				}
1398 				else
1399 				{
1400 #ifdef FEAT_MBYTE
1401 				    int	    l = (*mb_ptr2len)(p);
1402 
1403 				    if (l > 1)
1404 				    {
1405 					if (ptr2cells(p) > 1)
1406 					{
1407 					    /* Replace a double-wide char with
1408 					     * two spaces */
1409 					    --l;
1410 					    *p++ = ' ';
1411 					}
1412 					mch_memmove(p + 1, p + l,
1413 						     (leader + lead_len) - p);
1414 					lead_len -= l - 1;
1415 				    }
1416 #endif
1417 				    *p = ' ';
1418 				}
1419 			    }
1420 			*p = NUL;
1421 		    }
1422 
1423 		    /* Recompute the indent, it may have changed. */
1424 		    if (curbuf->b_p_ai
1425 #ifdef FEAT_SMARTINDENT
1426 					|| do_si
1427 #endif
1428 							   )
1429 #ifdef FEAT_VARTABS
1430 			newindent = get_indent_str_vtab(leader, curbuf->b_p_ts,
1431 						 curbuf->b_p_vts_array, FALSE);
1432 #else
1433 			newindent = get_indent_str(leader,
1434 						   (int)curbuf->b_p_ts, FALSE);
1435 #endif
1436 
1437 		    /* Add the indent offset */
1438 		    if (newindent + off < 0)
1439 		    {
1440 			off = -newindent;
1441 			newindent = 0;
1442 		    }
1443 		    else
1444 			newindent += off;
1445 
1446 		    /* Correct trailing spaces for the shift, so that
1447 		     * alignment remains equal. */
1448 		    while (off > 0 && lead_len > 0
1449 					       && leader[lead_len - 1] == ' ')
1450 		    {
1451 			/* Don't do it when there is a tab before the space */
1452 			if (vim_strchr(skipwhite(leader), '\t') != NULL)
1453 			    break;
1454 			--lead_len;
1455 			--off;
1456 		    }
1457 
1458 		    /* If the leader ends in white space, don't add an
1459 		     * extra space */
1460 		    if (lead_len > 0 && VIM_ISWHITE(leader[lead_len - 1]))
1461 			extra_space = FALSE;
1462 		    leader[lead_len] = NUL;
1463 		}
1464 
1465 		if (extra_space)
1466 		{
1467 		    leader[lead_len++] = ' ';
1468 		    leader[lead_len] = NUL;
1469 		}
1470 
1471 		newcol = lead_len;
1472 
1473 		/*
1474 		 * if a new indent will be set below, remove the indent that
1475 		 * is in the comment leader
1476 		 */
1477 		if (newindent
1478 #ifdef FEAT_SMARTINDENT
1479 				|| did_si
1480 #endif
1481 					   )
1482 		{
1483 		    while (lead_len && VIM_ISWHITE(*leader))
1484 		    {
1485 			--lead_len;
1486 			--newcol;
1487 			++leader;
1488 		    }
1489 		}
1490 
1491 	    }
1492 #ifdef FEAT_SMARTINDENT
1493 	    did_si = can_si = FALSE;
1494 #endif
1495 	}
1496 	else if (comment_end != NULL)
1497 	{
1498 	    /*
1499 	     * We have finished a comment, so we don't use the leader.
1500 	     * If this was a C-comment and 'ai' or 'si' is set do a normal
1501 	     * indent to align with the line containing the start of the
1502 	     * comment.
1503 	     */
1504 	    if (comment_end[0] == '*' && comment_end[1] == '/' &&
1505 			(curbuf->b_p_ai
1506 #ifdef FEAT_SMARTINDENT
1507 					|| do_si
1508 #endif
1509 							   ))
1510 	    {
1511 		old_cursor = curwin->w_cursor;
1512 		curwin->w_cursor.col = (colnr_T)(comment_end - saved_line);
1513 		if ((pos = findmatch(NULL, NUL)) != NULL)
1514 		{
1515 		    curwin->w_cursor.lnum = pos->lnum;
1516 		    newindent = get_indent();
1517 		}
1518 		curwin->w_cursor = old_cursor;
1519 	    }
1520 	}
1521     }
1522 #endif
1523 
1524     /* (State == INSERT || State == REPLACE), only when dir == FORWARD */
1525     if (p_extra != NULL)
1526     {
1527 	*p_extra = saved_char;		/* restore char that NUL replaced */
1528 
1529 	/*
1530 	 * When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first
1531 	 * non-blank.
1532 	 *
1533 	 * When in REPLACE mode, put the deleted blanks on the replace stack,
1534 	 * preceded by a NUL, so they can be put back when a BS is entered.
1535 	 */
1536 	if (REPLACE_NORMAL(State))
1537 	    replace_push(NUL);	    /* end of extra blanks */
1538 	if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES))
1539 	{
1540 	    while ((*p_extra == ' ' || *p_extra == '\t')
1541 #ifdef FEAT_MBYTE
1542 		    && (!enc_utf8
1543 			       || !utf_iscomposing(utf_ptr2char(p_extra + 1)))
1544 #endif
1545 		    )
1546 	    {
1547 		if (REPLACE_NORMAL(State))
1548 		    replace_push(*p_extra);
1549 		++p_extra;
1550 		++less_cols_off;
1551 	    }
1552 	}
1553 	if (*p_extra != NUL)
1554 	    did_ai = FALSE;	    /* append some text, don't truncate now */
1555 
1556 	/* columns for marks adjusted for removed columns */
1557 	less_cols = (int)(p_extra - saved_line);
1558     }
1559 
1560     if (p_extra == NULL)
1561 	p_extra = (char_u *)"";		    /* append empty line */
1562 
1563 #ifdef FEAT_COMMENTS
1564     /* concatenate leader and p_extra, if there is a leader */
1565     if (lead_len)
1566     {
1567 	if (flags & OPENLINE_COM_LIST && second_line_indent > 0)
1568 	{
1569 	    int i;
1570 	    int padding = second_line_indent
1571 					  - (newindent + (int)STRLEN(leader));
1572 
1573 	    /* Here whitespace is inserted after the comment char.
1574 	     * Below, set_indent(newindent, SIN_INSERT) will insert the
1575 	     * whitespace needed before the comment char. */
1576 	    for (i = 0; i < padding; i++)
1577 	    {
1578 		STRCAT(leader, " ");
1579 		less_cols--;
1580 		newcol++;
1581 	    }
1582 	}
1583 	STRCAT(leader, p_extra);
1584 	p_extra = leader;
1585 	did_ai = TRUE;	    /* So truncating blanks works with comments */
1586 	less_cols -= lead_len;
1587     }
1588     else
1589 	end_comment_pending = NUL;  /* turns out there was no leader */
1590 #endif
1591 
1592     old_cursor = curwin->w_cursor;
1593     if (dir == BACKWARD)
1594 	--curwin->w_cursor.lnum;
1595     if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count)
1596     {
1597 	if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE)
1598 								      == FAIL)
1599 	    goto theend;
1600 	/* Postpone calling changed_lines(), because it would mess up folding
1601 	 * with markers.
1602 	 * Skip mark_adjust when adding a line after the last one, there can't
1603 	 * be marks there. But still needed in diff mode. */
1604 	if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count
1605 #ifdef FEAT_DIFF
1606 		|| curwin->w_p_diff
1607 #endif
1608 	    )
1609 	    mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
1610 	did_append = TRUE;
1611     }
1612     else
1613     {
1614 	/*
1615 	 * In VREPLACE mode we are starting to replace the next line.
1616 	 */
1617 	curwin->w_cursor.lnum++;
1618 	if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed)
1619 	{
1620 	    /* In case we NL to a new line, BS to the previous one, and NL
1621 	     * again, we don't want to save the new line for undo twice.
1622 	     */
1623 	    (void)u_save_cursor();		    /* errors are ignored! */
1624 	    vr_lines_changed++;
1625 	}
1626 	ml_replace(curwin->w_cursor.lnum, p_extra, TRUE);
1627 	changed_bytes(curwin->w_cursor.lnum, 0);
1628 	curwin->w_cursor.lnum--;
1629 	did_append = FALSE;
1630     }
1631 
1632     if (newindent
1633 #ifdef FEAT_SMARTINDENT
1634 		    || did_si
1635 #endif
1636 				)
1637     {
1638 	++curwin->w_cursor.lnum;
1639 #ifdef FEAT_SMARTINDENT
1640 	if (did_si)
1641 	{
1642 	    int sw = (int)get_sw_value(curbuf);
1643 
1644 	    if (p_sr)
1645 		newindent -= newindent % sw;
1646 	    newindent += sw;
1647 	}
1648 #endif
1649 	/* Copy the indent */
1650 	if (curbuf->b_p_ci)
1651 	{
1652 	    (void)copy_indent(newindent, saved_line);
1653 
1654 	    /*
1655 	     * Set the 'preserveindent' option so that any further screwing
1656 	     * with the line doesn't entirely destroy our efforts to preserve
1657 	     * it.  It gets restored at the function end.
1658 	     */
1659 	    curbuf->b_p_pi = TRUE;
1660 	}
1661 	else
1662 	    (void)set_indent(newindent, SIN_INSERT);
1663 	less_cols -= curwin->w_cursor.col;
1664 
1665 	ai_col = curwin->w_cursor.col;
1666 
1667 	/*
1668 	 * In REPLACE mode, for each character in the new indent, there must
1669 	 * be a NUL on the replace stack, for when it is deleted with BS
1670 	 */
1671 	if (REPLACE_NORMAL(State))
1672 	    for (n = 0; n < (int)curwin->w_cursor.col; ++n)
1673 		replace_push(NUL);
1674 	newcol += curwin->w_cursor.col;
1675 #ifdef FEAT_SMARTINDENT
1676 	if (no_si)
1677 	    did_si = FALSE;
1678 #endif
1679     }
1680 
1681 #ifdef FEAT_COMMENTS
1682     /*
1683      * In REPLACE mode, for each character in the extra leader, there must be
1684      * a NUL on the replace stack, for when it is deleted with BS.
1685      */
1686     if (REPLACE_NORMAL(State))
1687 	while (lead_len-- > 0)
1688 	    replace_push(NUL);
1689 #endif
1690 
1691     curwin->w_cursor = old_cursor;
1692 
1693     if (dir == FORWARD)
1694     {
1695 	if (trunc_line || (State & INSERT))
1696 	{
1697 	    /* truncate current line at cursor */
1698 	    saved_line[curwin->w_cursor.col] = NUL;
1699 	    /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */
1700 	    if (trunc_line && !(flags & OPENLINE_KEEPTRAIL))
1701 		truncate_spaces(saved_line);
1702 	    ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
1703 	    saved_line = NULL;
1704 	    if (did_append)
1705 	    {
1706 		changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
1707 					       curwin->w_cursor.lnum + 1, 1L);
1708 		did_append = FALSE;
1709 
1710 		/* Move marks after the line break to the new line. */
1711 		if (flags & OPENLINE_MARKFIX)
1712 		    mark_col_adjust(curwin->w_cursor.lnum,
1713 					 curwin->w_cursor.col + less_cols_off,
1714 							1L, (long)-less_cols);
1715 	    }
1716 	    else
1717 		changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
1718 	}
1719 
1720 	/*
1721 	 * Put the cursor on the new line.  Careful: the scrollup() above may
1722 	 * have moved w_cursor, we must use old_cursor.
1723 	 */
1724 	curwin->w_cursor.lnum = old_cursor.lnum + 1;
1725     }
1726     if (did_append)
1727 	changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L);
1728 
1729     curwin->w_cursor.col = newcol;
1730 #ifdef FEAT_VIRTUALEDIT
1731     curwin->w_cursor.coladd = 0;
1732 #endif
1733 
1734 #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
1735     /*
1736      * In VREPLACE mode, we are handling the replace stack ourselves, so stop
1737      * fixthisline() from doing it (via change_indent()) by telling it we're in
1738      * normal INSERT mode.
1739      */
1740     if (State & VREPLACE_FLAG)
1741     {
1742 	vreplace_mode = State;	/* So we know to put things right later */
1743 	State = INSERT;
1744     }
1745     else
1746 	vreplace_mode = 0;
1747 #endif
1748 #ifdef FEAT_LISP
1749     /*
1750      * May do lisp indenting.
1751      */
1752     if (!p_paste
1753 # ifdef FEAT_COMMENTS
1754 	    && leader == NULL
1755 # endif
1756 	    && curbuf->b_p_lisp
1757 	    && curbuf->b_p_ai)
1758     {
1759 	fixthisline(get_lisp_indent);
1760 	ai_col = (colnr_T)getwhitecols_curline();
1761     }
1762 #endif
1763 #ifdef FEAT_CINDENT
1764     /*
1765      * May do indenting after opening a new line.
1766      */
1767     if (!p_paste
1768 	    && (curbuf->b_p_cin
1769 #  ifdef FEAT_EVAL
1770 		    || *curbuf->b_p_inde != NUL
1771 #  endif
1772 		)
1773 	    && in_cinkeys(dir == FORWARD
1774 		? KEY_OPEN_FORW
1775 		: KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
1776     {
1777 	do_c_expr_indent();
1778 	ai_col = (colnr_T)getwhitecols_curline();
1779     }
1780 #endif
1781 #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
1782     if (vreplace_mode != 0)
1783 	State = vreplace_mode;
1784 #endif
1785 
1786     /*
1787      * Finally, VREPLACE gets the stuff on the new line, then puts back the
1788      * original line, and inserts the new stuff char by char, pushing old stuff
1789      * onto the replace stack (via ins_char()).
1790      */
1791     if (State & VREPLACE_FLAG)
1792     {
1793 	/* Put new line in p_extra */
1794 	p_extra = vim_strsave(ml_get_curline());
1795 	if (p_extra == NULL)
1796 	    goto theend;
1797 
1798 	/* Put back original line */
1799 	ml_replace(curwin->w_cursor.lnum, next_line, FALSE);
1800 
1801 	/* Insert new stuff into line again */
1802 	curwin->w_cursor.col = 0;
1803 #ifdef FEAT_VIRTUALEDIT
1804 	curwin->w_cursor.coladd = 0;
1805 #endif
1806 	ins_bytes(p_extra);	/* will call changed_bytes() */
1807 	vim_free(p_extra);
1808 	next_line = NULL;
1809     }
1810 
1811     retval = OK;		/* success! */
1812 theend:
1813     curbuf->b_p_pi = saved_pi;
1814     vim_free(saved_line);
1815     vim_free(next_line);
1816     vim_free(allocated);
1817     return retval;
1818 }
1819 
1820 #if defined(FEAT_COMMENTS) || defined(PROTO)
1821 /*
1822  * get_leader_len() returns the length in bytes of the prefix of the given
1823  * string which introduces a comment.  If this string is not a comment then
1824  * 0 is returned.
1825  * When "flags" is not NULL, it is set to point to the flags of the recognized
1826  * comment leader.
1827  * "backward" must be true for the "O" command.
1828  * If "include_space" is set, include trailing whitespace while calculating the
1829  * length.
1830  */
1831     int
1832 get_leader_len(
1833     char_u	*line,
1834     char_u	**flags,
1835     int		backward,
1836     int		include_space)
1837 {
1838     int		i, j;
1839     int		result;
1840     int		got_com = FALSE;
1841     int		found_one;
1842     char_u	part_buf[COM_MAX_LEN];	/* buffer for one option part */
1843     char_u	*string;		/* pointer to comment string */
1844     char_u	*list;
1845     int		middle_match_len = 0;
1846     char_u	*prev_list;
1847     char_u	*saved_flags = NULL;
1848 
1849     result = i = 0;
1850     while (VIM_ISWHITE(line[i]))    /* leading white space is ignored */
1851 	++i;
1852 
1853     /*
1854      * Repeat to match several nested comment strings.
1855      */
1856     while (line[i] != NUL)
1857     {
1858 	/*
1859 	 * scan through the 'comments' option for a match
1860 	 */
1861 	found_one = FALSE;
1862 	for (list = curbuf->b_p_com; *list; )
1863 	{
1864 	    /* Get one option part into part_buf[].  Advance "list" to next
1865 	     * one.  Put "string" at start of string.  */
1866 	    if (!got_com && flags != NULL)
1867 		*flags = list;	    /* remember where flags started */
1868 	    prev_list = list;
1869 	    (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
1870 	    string = vim_strchr(part_buf, ':');
1871 	    if (string == NULL)	    /* missing ':', ignore this part */
1872 		continue;
1873 	    *string++ = NUL;	    /* isolate flags from string */
1874 
1875 	    /* If we found a middle match previously, use that match when this
1876 	     * is not a middle or end. */
1877 	    if (middle_match_len != 0
1878 		    && vim_strchr(part_buf, COM_MIDDLE) == NULL
1879 		    && vim_strchr(part_buf, COM_END) == NULL)
1880 		break;
1881 
1882 	    /* When we already found a nested comment, only accept further
1883 	     * nested comments. */
1884 	    if (got_com && vim_strchr(part_buf, COM_NEST) == NULL)
1885 		continue;
1886 
1887 	    /* When 'O' flag present and using "O" command skip this one. */
1888 	    if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL)
1889 		continue;
1890 
1891 	    /* Line contents and string must match.
1892 	     * When string starts with white space, must have some white space
1893 	     * (but the amount does not need to match, there might be a mix of
1894 	     * TABs and spaces). */
1895 	    if (VIM_ISWHITE(string[0]))
1896 	    {
1897 		if (i == 0 || !VIM_ISWHITE(line[i - 1]))
1898 		    continue;  /* missing white space */
1899 		while (VIM_ISWHITE(string[0]))
1900 		    ++string;
1901 	    }
1902 	    for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
1903 		;
1904 	    if (string[j] != NUL)
1905 		continue;  /* string doesn't match */
1906 
1907 	    /* When 'b' flag used, there must be white space or an
1908 	     * end-of-line after the string in the line. */
1909 	    if (vim_strchr(part_buf, COM_BLANK) != NULL
1910 			   && !VIM_ISWHITE(line[i + j]) && line[i + j] != NUL)
1911 		continue;
1912 
1913 	    /* We have found a match, stop searching unless this is a middle
1914 	     * comment. The middle comment can be a substring of the end
1915 	     * comment in which case it's better to return the length of the
1916 	     * end comment and its flags.  Thus we keep searching with middle
1917 	     * and end matches and use an end match if it matches better. */
1918 	    if (vim_strchr(part_buf, COM_MIDDLE) != NULL)
1919 	    {
1920 		if (middle_match_len == 0)
1921 		{
1922 		    middle_match_len = j;
1923 		    saved_flags = prev_list;
1924 		}
1925 		continue;
1926 	    }
1927 	    if (middle_match_len != 0 && j > middle_match_len)
1928 		/* Use this match instead of the middle match, since it's a
1929 		 * longer thus better match. */
1930 		middle_match_len = 0;
1931 
1932 	    if (middle_match_len == 0)
1933 		i += j;
1934 	    found_one = TRUE;
1935 	    break;
1936 	}
1937 
1938 	if (middle_match_len != 0)
1939 	{
1940 	    /* Use the previously found middle match after failing to find a
1941 	     * match with an end. */
1942 	    if (!got_com && flags != NULL)
1943 		*flags = saved_flags;
1944 	    i += middle_match_len;
1945 	    found_one = TRUE;
1946 	}
1947 
1948 	/* No match found, stop scanning. */
1949 	if (!found_one)
1950 	    break;
1951 
1952 	result = i;
1953 
1954 	/* Include any trailing white space. */
1955 	while (VIM_ISWHITE(line[i]))
1956 	    ++i;
1957 
1958 	if (include_space)
1959 	    result = i;
1960 
1961 	/* If this comment doesn't nest, stop here. */
1962 	got_com = TRUE;
1963 	if (vim_strchr(part_buf, COM_NEST) == NULL)
1964 	    break;
1965     }
1966     return result;
1967 }
1968 
1969 /*
1970  * Return the offset at which the last comment in line starts. If there is no
1971  * comment in the whole line, -1 is returned.
1972  *
1973  * When "flags" is not null, it is set to point to the flags describing the
1974  * recognized comment leader.
1975  */
1976     int
1977 get_last_leader_offset(char_u *line, char_u **flags)
1978 {
1979     int		result = -1;
1980     int		i, j;
1981     int		lower_check_bound = 0;
1982     char_u	*string;
1983     char_u	*com_leader;
1984     char_u	*com_flags;
1985     char_u	*list;
1986     int		found_one;
1987     char_u	part_buf[COM_MAX_LEN];	/* buffer for one option part */
1988 
1989     /*
1990      * Repeat to match several nested comment strings.
1991      */
1992     i = (int)STRLEN(line);
1993     while (--i >= lower_check_bound)
1994     {
1995 	/*
1996 	 * scan through the 'comments' option for a match
1997 	 */
1998 	found_one = FALSE;
1999 	for (list = curbuf->b_p_com; *list; )
2000 	{
2001 	    char_u *flags_save = list;
2002 
2003 	    /*
2004 	     * Get one option part into part_buf[].  Advance list to next one.
2005 	     * put string at start of string.
2006 	     */
2007 	    (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
2008 	    string = vim_strchr(part_buf, ':');
2009 	    if (string == NULL)	/* If everything is fine, this cannot actually
2010 				 * happen. */
2011 	    {
2012 		continue;
2013 	    }
2014 	    *string++ = NUL;	/* Isolate flags from string. */
2015 	    com_leader = string;
2016 
2017 	    /*
2018 	     * Line contents and string must match.
2019 	     * When string starts with white space, must have some white space
2020 	     * (but the amount does not need to match, there might be a mix of
2021 	     * TABs and spaces).
2022 	     */
2023 	    if (VIM_ISWHITE(string[0]))
2024 	    {
2025 		if (i == 0 || !VIM_ISWHITE(line[i - 1]))
2026 		    continue;
2027 		while (VIM_ISWHITE(string[0]))
2028 		    ++string;
2029 	    }
2030 	    for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
2031 		/* do nothing */;
2032 	    if (string[j] != NUL)
2033 		continue;
2034 
2035 	    /*
2036 	     * When 'b' flag used, there must be white space or an
2037 	     * end-of-line after the string in the line.
2038 	     */
2039 	    if (vim_strchr(part_buf, COM_BLANK) != NULL
2040 		    && !VIM_ISWHITE(line[i + j]) && line[i + j] != NUL)
2041 	    {
2042 		continue;
2043 	    }
2044 
2045 	    /*
2046 	     * We have found a match, stop searching.
2047 	     */
2048 	    found_one = TRUE;
2049 
2050 	    if (flags)
2051 		*flags = flags_save;
2052 	    com_flags = flags_save;
2053 
2054 	    break;
2055 	}
2056 
2057 	if (found_one)
2058 	{
2059 	    char_u  part_buf2[COM_MAX_LEN];	/* buffer for one option part */
2060 	    int     len1, len2, off;
2061 
2062 	    result = i;
2063 	    /*
2064 	     * If this comment nests, continue searching.
2065 	     */
2066 	    if (vim_strchr(part_buf, COM_NEST) != NULL)
2067 		continue;
2068 
2069 	    lower_check_bound = i;
2070 
2071 	    /* Let's verify whether the comment leader found is a substring
2072 	     * of other comment leaders. If it is, let's adjust the
2073 	     * lower_check_bound so that we make sure that we have determined
2074 	     * the comment leader correctly.
2075 	     */
2076 
2077 	    while (VIM_ISWHITE(*com_leader))
2078 		++com_leader;
2079 	    len1 = (int)STRLEN(com_leader);
2080 
2081 	    for (list = curbuf->b_p_com; *list; )
2082 	    {
2083 		char_u *flags_save = list;
2084 
2085 		(void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
2086 		if (flags_save == com_flags)
2087 		    continue;
2088 		string = vim_strchr(part_buf2, ':');
2089 		++string;
2090 		while (VIM_ISWHITE(*string))
2091 		    ++string;
2092 		len2 = (int)STRLEN(string);
2093 		if (len2 == 0)
2094 		    continue;
2095 
2096 		/* Now we have to verify whether string ends with a substring
2097 		 * beginning the com_leader. */
2098 		for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;)
2099 		{
2100 		    --off;
2101 		    if (!STRNCMP(string + off, com_leader, len2 - off))
2102 		    {
2103 			if (i - off < lower_check_bound)
2104 			    lower_check_bound = i - off;
2105 		    }
2106 		}
2107 	    }
2108 	}
2109     }
2110     return result;
2111 }
2112 #endif
2113 
2114 /*
2115  * Return the number of window lines occupied by buffer line "lnum".
2116  */
2117     int
2118 plines(linenr_T lnum)
2119 {
2120     return plines_win(curwin, lnum, TRUE);
2121 }
2122 
2123     int
2124 plines_win(
2125     win_T	*wp,
2126     linenr_T	lnum,
2127     int		winheight)	/* when TRUE limit to window height */
2128 {
2129 #if defined(FEAT_DIFF) || defined(PROTO)
2130     /* Check for filler lines above this buffer line.  When folded the result
2131      * is one line anyway. */
2132     return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum);
2133 }
2134 
2135     int
2136 plines_nofill(linenr_T lnum)
2137 {
2138     return plines_win_nofill(curwin, lnum, TRUE);
2139 }
2140 
2141     int
2142 plines_win_nofill(
2143     win_T	*wp,
2144     linenr_T	lnum,
2145     int		winheight)	/* when TRUE limit to window height */
2146 {
2147 #endif
2148     int		lines;
2149 
2150     if (!wp->w_p_wrap)
2151 	return 1;
2152 
2153     if (wp->w_width == 0)
2154 	return 1;
2155 
2156 #ifdef FEAT_FOLDING
2157     /* A folded lines is handled just like an empty line. */
2158     /* NOTE: Caller must handle lines that are MAYBE folded. */
2159     if (lineFolded(wp, lnum) == TRUE)
2160 	return 1;
2161 #endif
2162 
2163     lines = plines_win_nofold(wp, lnum);
2164     if (winheight > 0 && lines > wp->w_height)
2165 	return (int)wp->w_height;
2166     return lines;
2167 }
2168 
2169 /*
2170  * Return number of window lines physical line "lnum" will occupy in window
2171  * "wp".  Does not care about folding, 'wrap' or 'diff'.
2172  */
2173     int
2174 plines_win_nofold(win_T *wp, linenr_T lnum)
2175 {
2176     char_u	*s;
2177     long	col;
2178     int		width;
2179 
2180     s = ml_get_buf(wp->w_buffer, lnum, FALSE);
2181     if (*s == NUL)		/* empty line */
2182 	return 1;
2183     col = win_linetabsize(wp, s, (colnr_T)MAXCOL);
2184 
2185     /*
2186      * If list mode is on, then the '$' at the end of the line may take up one
2187      * extra column.
2188      */
2189     if (wp->w_p_list && lcs_eol != NUL)
2190 	col += 1;
2191 
2192     /*
2193      * Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
2194      */
2195     width = wp->w_width - win_col_off(wp);
2196     if (width <= 0)
2197 	return 32000;
2198     if (col <= width)
2199 	return 1;
2200     col -= width;
2201     width += win_col_off2(wp);
2202     return (col + (width - 1)) / width + 1;
2203 }
2204 
2205 /*
2206  * Like plines_win(), but only reports the number of physical screen lines
2207  * used from the start of the line to the given column number.
2208  */
2209     int
2210 plines_win_col(win_T *wp, linenr_T lnum, long column)
2211 {
2212     long	col;
2213     char_u	*s;
2214     int		lines = 0;
2215     int		width;
2216     char_u	*line;
2217 
2218 #ifdef FEAT_DIFF
2219     /* Check for filler lines above this buffer line.  When folded the result
2220      * is one line anyway. */
2221     lines = diff_check_fill(wp, lnum);
2222 #endif
2223 
2224     if (!wp->w_p_wrap)
2225 	return lines + 1;
2226 
2227     if (wp->w_width == 0)
2228 	return lines + 1;
2229 
2230     line = s = ml_get_buf(wp->w_buffer, lnum, FALSE);
2231 
2232     col = 0;
2233     while (*s != NUL && --column >= 0)
2234     {
2235 	col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL);
2236 	MB_PTR_ADV(s);
2237     }
2238 
2239     /*
2240      * If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
2241      * INSERT mode, then col must be adjusted so that it represents the last
2242      * screen position of the TAB.  This only fixes an error when the TAB wraps
2243      * from one screen line to the next (when 'columns' is not a multiple of
2244      * 'ts') -- webb.
2245      */
2246     if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1))
2247 	col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL) - 1;
2248 
2249     /*
2250      * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
2251      */
2252     width = wp->w_width - win_col_off(wp);
2253     if (width <= 0)
2254 	return 9999;
2255 
2256     lines += 1;
2257     if (col > width)
2258 	lines += (col - width) / (width + win_col_off2(wp)) + 1;
2259     return lines;
2260 }
2261 
2262     int
2263 plines_m_win(win_T *wp, linenr_T first, linenr_T last)
2264 {
2265     int		count = 0;
2266 
2267     while (first <= last)
2268     {
2269 #ifdef FEAT_FOLDING
2270 	int	x;
2271 
2272 	/* Check if there are any really folded lines, but also included lines
2273 	 * that are maybe folded. */
2274 	x = foldedCount(wp, first, NULL);
2275 	if (x > 0)
2276 	{
2277 	    ++count;	    /* count 1 for "+-- folded" line */
2278 	    first += x;
2279 	}
2280 	else
2281 #endif
2282 	{
2283 #ifdef FEAT_DIFF
2284 	    if (first == wp->w_topline)
2285 		count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill;
2286 	    else
2287 #endif
2288 		count += plines_win(wp, first, TRUE);
2289 	    ++first;
2290 	}
2291     }
2292     return (count);
2293 }
2294 
2295 /*
2296  * Insert string "p" at the cursor position.  Stops at a NUL byte.
2297  * Handles Replace mode and multi-byte characters.
2298  */
2299     void
2300 ins_bytes(char_u *p)
2301 {
2302     ins_bytes_len(p, (int)STRLEN(p));
2303 }
2304 
2305 /*
2306  * Insert string "p" with length "len" at the cursor position.
2307  * Handles Replace mode and multi-byte characters.
2308  */
2309     void
2310 ins_bytes_len(char_u *p, int len)
2311 {
2312     int		i;
2313 #ifdef FEAT_MBYTE
2314     int		n;
2315 
2316     if (has_mbyte)
2317 	for (i = 0; i < len; i += n)
2318 	{
2319 	    if (enc_utf8)
2320 		/* avoid reading past p[len] */
2321 		n = utfc_ptr2len_len(p + i, len - i);
2322 	    else
2323 		n = (*mb_ptr2len)(p + i);
2324 	    ins_char_bytes(p + i, n);
2325 	}
2326     else
2327 #endif
2328 	for (i = 0; i < len; ++i)
2329 	    ins_char(p[i]);
2330 }
2331 
2332 /*
2333  * Insert or replace a single character at the cursor position.
2334  * When in REPLACE or VREPLACE mode, replace any existing character.
2335  * Caller must have prepared for undo.
2336  * For multi-byte characters we get the whole character, the caller must
2337  * convert bytes to a character.
2338  */
2339     void
2340 ins_char(int c)
2341 {
2342     char_u	buf[MB_MAXBYTES + 1];
2343     int		n = 1;
2344 
2345 #ifdef FEAT_MBYTE
2346     n = (*mb_char2bytes)(c, buf);
2347 
2348     /* When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte.
2349      * Happens for CTRL-Vu9900. */
2350     if (buf[0] == 0)
2351 	buf[0] = '\n';
2352 #else
2353     buf[0] = c;
2354 #endif
2355 
2356     ins_char_bytes(buf, n);
2357 }
2358 
2359     void
2360 ins_char_bytes(char_u *buf, int charlen)
2361 {
2362     int		c = buf[0];
2363     int		newlen;		/* nr of bytes inserted */
2364     int		oldlen;		/* nr of bytes deleted (0 when not replacing) */
2365     char_u	*p;
2366     char_u	*newp;
2367     char_u	*oldp;
2368     int		linelen;	/* length of old line including NUL */
2369     colnr_T	col;
2370     linenr_T	lnum = curwin->w_cursor.lnum;
2371     int		i;
2372 
2373 #ifdef FEAT_VIRTUALEDIT
2374     /* Break tabs if needed. */
2375     if (virtual_active() && curwin->w_cursor.coladd > 0)
2376 	coladvance_force(getviscol());
2377 #endif
2378 
2379     col = curwin->w_cursor.col;
2380     oldp = ml_get(lnum);
2381     linelen = (int)STRLEN(oldp) + 1;
2382 
2383     /* The lengths default to the values for when not replacing. */
2384     oldlen = 0;
2385     newlen = charlen;
2386 
2387     if (State & REPLACE_FLAG)
2388     {
2389 	if (State & VREPLACE_FLAG)
2390 	{
2391 	    colnr_T	new_vcol = 0;   /* init for GCC */
2392 	    colnr_T	vcol;
2393 	    int		old_list;
2394 #ifndef FEAT_MBYTE
2395 	    char_u	buf[2];
2396 #endif
2397 
2398 	    /*
2399 	     * Disable 'list' temporarily, unless 'cpo' contains the 'L' flag.
2400 	     * Returns the old value of list, so when finished,
2401 	     * curwin->w_p_list should be set back to this.
2402 	     */
2403 	    old_list = curwin->w_p_list;
2404 	    if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
2405 		curwin->w_p_list = FALSE;
2406 
2407 	    /*
2408 	     * In virtual replace mode each character may replace one or more
2409 	     * characters (zero if it's a TAB).  Count the number of bytes to
2410 	     * be deleted to make room for the new character, counting screen
2411 	     * cells.  May result in adding spaces to fill a gap.
2412 	     */
2413 	    getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
2414 #ifndef FEAT_MBYTE
2415 	    buf[0] = c;
2416 	    buf[1] = NUL;
2417 #endif
2418 	    new_vcol = vcol + chartabsize(buf, vcol);
2419 	    while (oldp[col + oldlen] != NUL && vcol < new_vcol)
2420 	    {
2421 		vcol += chartabsize(oldp + col + oldlen, vcol);
2422 		/* Don't need to remove a TAB that takes us to the right
2423 		 * position. */
2424 		if (vcol > new_vcol && oldp[col + oldlen] == TAB)
2425 		    break;
2426 #ifdef FEAT_MBYTE
2427 		oldlen += (*mb_ptr2len)(oldp + col + oldlen);
2428 #else
2429 		++oldlen;
2430 #endif
2431 		/* Deleted a bit too much, insert spaces. */
2432 		if (vcol > new_vcol)
2433 		    newlen += vcol - new_vcol;
2434 	    }
2435 	    curwin->w_p_list = old_list;
2436 	}
2437 	else
2438 	    if (oldp[col] != NUL)
2439 	{
2440 	    /* normal replace */
2441 #ifdef FEAT_MBYTE
2442 	    oldlen = (*mb_ptr2len)(oldp + col);
2443 #else
2444 	    oldlen = 1;
2445 #endif
2446 	}
2447 
2448 
2449 	/* Push the replaced bytes onto the replace stack, so that they can be
2450 	 * put back when BS is used.  The bytes of a multi-byte character are
2451 	 * done the other way around, so that the first byte is popped off
2452 	 * first (it tells the byte length of the character). */
2453 	replace_push(NUL);
2454 	for (i = 0; i < oldlen; ++i)
2455 	{
2456 #ifdef FEAT_MBYTE
2457 	    if (has_mbyte)
2458 		i += replace_push_mb(oldp + col + i) - 1;
2459 	    else
2460 #endif
2461 		replace_push(oldp[col + i]);
2462 	}
2463     }
2464 
2465     newp = alloc_check((unsigned)(linelen + newlen - oldlen));
2466     if (newp == NULL)
2467 	return;
2468 
2469     /* Copy bytes before the cursor. */
2470     if (col > 0)
2471 	mch_memmove(newp, oldp, (size_t)col);
2472 
2473     /* Copy bytes after the changed character(s). */
2474     p = newp + col;
2475     if (linelen > col + oldlen)
2476 	mch_memmove(p + newlen, oldp + col + oldlen,
2477 					    (size_t)(linelen - col - oldlen));
2478 
2479     /* Insert or overwrite the new character. */
2480 #ifdef FEAT_MBYTE
2481     mch_memmove(p, buf, charlen);
2482     i = charlen;
2483 #else
2484     *p = c;
2485     i = 1;
2486 #endif
2487 
2488     /* Fill with spaces when necessary. */
2489     while (i < newlen)
2490 	p[i++] = ' ';
2491 
2492     /* Replace the line in the buffer. */
2493     ml_replace(lnum, newp, FALSE);
2494 
2495     /* mark the buffer as changed and prepare for displaying */
2496     changed_bytes(lnum, col);
2497 
2498     /*
2499      * If we're in Insert or Replace mode and 'showmatch' is set, then briefly
2500      * show the match for right parens and braces.
2501      */
2502     if (p_sm && (State & INSERT)
2503 	    && msg_silent == 0
2504 #ifdef FEAT_INS_EXPAND
2505 	    && !ins_compl_active()
2506 #endif
2507        )
2508     {
2509 #ifdef FEAT_MBYTE
2510 	if (has_mbyte)
2511 	    showmatch(mb_ptr2char(buf));
2512 	else
2513 #endif
2514 	    showmatch(c);
2515     }
2516 
2517 #ifdef FEAT_RIGHTLEFT
2518     if (!p_ri || (State & REPLACE_FLAG))
2519 #endif
2520     {
2521 	/* Normal insert: move cursor right */
2522 #ifdef FEAT_MBYTE
2523 	curwin->w_cursor.col += charlen;
2524 #else
2525 	++curwin->w_cursor.col;
2526 #endif
2527     }
2528     /*
2529      * TODO: should try to update w_row here, to avoid recomputing it later.
2530      */
2531 }
2532 
2533 /*
2534  * Insert a string at the cursor position.
2535  * Note: Does NOT handle Replace mode.
2536  * Caller must have prepared for undo.
2537  */
2538     void
2539 ins_str(char_u *s)
2540 {
2541     char_u	*oldp, *newp;
2542     int		newlen = (int)STRLEN(s);
2543     int		oldlen;
2544     colnr_T	col;
2545     linenr_T	lnum = curwin->w_cursor.lnum;
2546 
2547 #ifdef FEAT_VIRTUALEDIT
2548     if (virtual_active() && curwin->w_cursor.coladd > 0)
2549 	coladvance_force(getviscol());
2550 #endif
2551 
2552     col = curwin->w_cursor.col;
2553     oldp = ml_get(lnum);
2554     oldlen = (int)STRLEN(oldp);
2555 
2556     newp = alloc_check((unsigned)(oldlen + newlen + 1));
2557     if (newp == NULL)
2558 	return;
2559     if (col > 0)
2560 	mch_memmove(newp, oldp, (size_t)col);
2561     mch_memmove(newp + col, s, (size_t)newlen);
2562     mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
2563     ml_replace(lnum, newp, FALSE);
2564     changed_bytes(lnum, col);
2565     curwin->w_cursor.col += newlen;
2566 }
2567 
2568 /*
2569  * Delete one character under the cursor.
2570  * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
2571  * Caller must have prepared for undo.
2572  *
2573  * return FAIL for failure, OK otherwise
2574  */
2575     int
2576 del_char(int fixpos)
2577 {
2578 #ifdef FEAT_MBYTE
2579     if (has_mbyte)
2580     {
2581 	/* Make sure the cursor is at the start of a character. */
2582 	mb_adjust_cursor();
2583 	if (*ml_get_cursor() == NUL)
2584 	    return FAIL;
2585 	return del_chars(1L, fixpos);
2586     }
2587 #endif
2588     return del_bytes(1L, fixpos, TRUE);
2589 }
2590 
2591 #if defined(FEAT_MBYTE) || defined(PROTO)
2592 /*
2593  * Like del_bytes(), but delete characters instead of bytes.
2594  */
2595     int
2596 del_chars(long count, int fixpos)
2597 {
2598     long	bytes = 0;
2599     long	i;
2600     char_u	*p;
2601     int		l;
2602 
2603     p = ml_get_cursor();
2604     for (i = 0; i < count && *p != NUL; ++i)
2605     {
2606 	l = (*mb_ptr2len)(p);
2607 	bytes += l;
2608 	p += l;
2609     }
2610     return del_bytes(bytes, fixpos, TRUE);
2611 }
2612 #endif
2613 
2614 /*
2615  * Delete "count" bytes under the cursor.
2616  * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line.
2617  * Caller must have prepared for undo.
2618  *
2619  * Return FAIL for failure, OK otherwise.
2620  */
2621     int
2622 del_bytes(
2623     long	count,
2624     int		fixpos_arg,
2625     int		use_delcombine UNUSED)	    /* 'delcombine' option applies */
2626 {
2627     char_u	*oldp, *newp;
2628     colnr_T	oldlen;
2629     linenr_T	lnum = curwin->w_cursor.lnum;
2630     colnr_T	col = curwin->w_cursor.col;
2631     int		was_alloced;
2632     long	movelen;
2633     int		fixpos = fixpos_arg;
2634 
2635     oldp = ml_get(lnum);
2636     oldlen = (int)STRLEN(oldp);
2637 
2638     /* Can't do anything when the cursor is on the NUL after the line. */
2639     if (col >= oldlen)
2640 	return FAIL;
2641 
2642     /* If "count" is zero there is nothing to do. */
2643     if (count == 0)
2644 	return OK;
2645 
2646     /* If "count" is negative the caller must be doing something wrong. */
2647     if (count < 1)
2648     {
2649 	IEMSGN("E950: Invalid count for del_bytes(): %ld", count);
2650 	return FAIL;
2651     }
2652 
2653 #ifdef FEAT_MBYTE
2654     /* If 'delcombine' is set and deleting (less than) one character, only
2655      * delete the last combining character. */
2656     if (p_deco && use_delcombine && enc_utf8
2657 					 && utfc_ptr2len(oldp + col) >= count)
2658     {
2659 	int	cc[MAX_MCO];
2660 	int	n;
2661 
2662 	(void)utfc_ptr2char(oldp + col, cc);
2663 	if (cc[0] != NUL)
2664 	{
2665 	    /* Find the last composing char, there can be several. */
2666 	    n = col;
2667 	    do
2668 	    {
2669 		col = n;
2670 		count = utf_ptr2len(oldp + n);
2671 		n += count;
2672 	    } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n));
2673 	    fixpos = 0;
2674 	}
2675     }
2676 #endif
2677 
2678     /*
2679      * When count is too big, reduce it.
2680      */
2681     movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */
2682     if (movelen <= 1)
2683     {
2684 	/*
2685 	 * If we just took off the last character of a non-blank line, and
2686 	 * fixpos is TRUE, we don't want to end up positioned at the NUL,
2687 	 * unless "restart_edit" is set or 'virtualedit' contains "onemore".
2688 	 */
2689 	if (col > 0 && fixpos && restart_edit == 0
2690 #ifdef FEAT_VIRTUALEDIT
2691 					      && (ve_flags & VE_ONEMORE) == 0
2692 #endif
2693 					      )
2694 	{
2695 	    --curwin->w_cursor.col;
2696 #ifdef FEAT_VIRTUALEDIT
2697 	    curwin->w_cursor.coladd = 0;
2698 #endif
2699 #ifdef FEAT_MBYTE
2700 	    if (has_mbyte)
2701 		curwin->w_cursor.col -=
2702 			    (*mb_head_off)(oldp, oldp + curwin->w_cursor.col);
2703 #endif
2704 	}
2705 	count = oldlen - col;
2706 	movelen = 1;
2707     }
2708 
2709     /*
2710      * If the old line has been allocated the deletion can be done in the
2711      * existing line. Otherwise a new line has to be allocated
2712      * Can't do this when using Netbeans, because we would need to invoke
2713      * netbeans_removed(), which deallocates the line.  Let ml_replace() take
2714      * care of notifying Netbeans.
2715      */
2716 #ifdef FEAT_NETBEANS_INTG
2717     if (netbeans_active())
2718 	was_alloced = FALSE;
2719     else
2720 #endif
2721 	was_alloced = ml_line_alloced();    /* check if oldp was allocated */
2722     if (was_alloced)
2723 	newp = oldp;			    /* use same allocated memory */
2724     else
2725     {					    /* need to allocate a new line */
2726 	newp = alloc((unsigned)(oldlen + 1 - count));
2727 	if (newp == NULL)
2728 	    return FAIL;
2729 	mch_memmove(newp, oldp, (size_t)col);
2730     }
2731     mch_memmove(newp + col, oldp + col + count, (size_t)movelen);
2732     if (!was_alloced)
2733 	ml_replace(lnum, newp, FALSE);
2734 
2735     /* mark the buffer as changed and prepare for displaying */
2736     changed_bytes(lnum, curwin->w_cursor.col);
2737 
2738     return OK;
2739 }
2740 
2741 /*
2742  * Delete from cursor to end of line.
2743  * Caller must have prepared for undo.
2744  *
2745  * return FAIL for failure, OK otherwise
2746  */
2747     int
2748 truncate_line(
2749     int		fixpos)	    /* if TRUE fix the cursor position when done */
2750 {
2751     char_u	*newp;
2752     linenr_T	lnum = curwin->w_cursor.lnum;
2753     colnr_T	col = curwin->w_cursor.col;
2754 
2755     if (col == 0)
2756 	newp = vim_strsave((char_u *)"");
2757     else
2758 	newp = vim_strnsave(ml_get(lnum), col);
2759 
2760     if (newp == NULL)
2761 	return FAIL;
2762 
2763     ml_replace(lnum, newp, FALSE);
2764 
2765     /* mark the buffer as changed and prepare for displaying */
2766     changed_bytes(lnum, curwin->w_cursor.col);
2767 
2768     /*
2769      * If "fixpos" is TRUE we don't want to end up positioned at the NUL.
2770      */
2771     if (fixpos && curwin->w_cursor.col > 0)
2772 	--curwin->w_cursor.col;
2773 
2774     return OK;
2775 }
2776 
2777 /*
2778  * Delete "nlines" lines at the cursor.
2779  * Saves the lines for undo first if "undo" is TRUE.
2780  */
2781     void
2782 del_lines(
2783     long	nlines,		/* number of lines to delete */
2784     int		undo)		/* if TRUE, prepare for undo */
2785 {
2786     long	n;
2787     linenr_T	first = curwin->w_cursor.lnum;
2788 
2789     if (nlines <= 0)
2790 	return;
2791 
2792     /* save the deleted lines for undo */
2793     if (undo && u_savedel(first, nlines) == FAIL)
2794 	return;
2795 
2796     for (n = 0; n < nlines; )
2797     {
2798 	if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to delete */
2799 	    break;
2800 
2801 	ml_delete(first, TRUE);
2802 	++n;
2803 
2804 	/* If we delete the last line in the file, stop */
2805 	if (first > curbuf->b_ml.ml_line_count)
2806 	    break;
2807     }
2808 
2809     /* Correct the cursor position before calling deleted_lines_mark(), it may
2810      * trigger a callback to display the cursor. */
2811     curwin->w_cursor.col = 0;
2812     check_cursor_lnum();
2813 
2814     /* adjust marks, mark the buffer as changed and prepare for displaying */
2815     deleted_lines_mark(first, n);
2816 }
2817 
2818     int
2819 gchar_pos(pos_T *pos)
2820 {
2821     char_u	*ptr;
2822 
2823     /* When searching columns is sometimes put at the end of a line. */
2824     if (pos->col == MAXCOL)
2825 	return NUL;
2826     ptr = ml_get_pos(pos);
2827 #ifdef FEAT_MBYTE
2828     if (has_mbyte)
2829 	return (*mb_ptr2char)(ptr);
2830 #endif
2831     return (int)*ptr;
2832 }
2833 
2834     int
2835 gchar_cursor(void)
2836 {
2837 #ifdef FEAT_MBYTE
2838     if (has_mbyte)
2839 	return (*mb_ptr2char)(ml_get_cursor());
2840 #endif
2841     return (int)*ml_get_cursor();
2842 }
2843 
2844 /*
2845  * Write a character at the current cursor position.
2846  * It is directly written into the block.
2847  */
2848     void
2849 pchar_cursor(int c)
2850 {
2851     *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE)
2852 						  + curwin->w_cursor.col) = c;
2853 }
2854 
2855 /*
2856  * When extra == 0: Return TRUE if the cursor is before or on the first
2857  *		    non-blank in the line.
2858  * When extra == 1: Return TRUE if the cursor is before the first non-blank in
2859  *		    the line.
2860  */
2861     int
2862 inindent(int extra)
2863 {
2864     char_u	*ptr;
2865     colnr_T	col;
2866 
2867     for (col = 0, ptr = ml_get_curline(); VIM_ISWHITE(*ptr); ++col)
2868 	++ptr;
2869     if (col >= curwin->w_cursor.col + extra)
2870 	return TRUE;
2871     else
2872 	return FALSE;
2873 }
2874 
2875 /*
2876  * Skip to next part of an option argument: Skip space and comma.
2877  */
2878     char_u *
2879 skip_to_option_part(char_u *p)
2880 {
2881     if (*p == ',')
2882 	++p;
2883     while (*p == ' ')
2884 	++p;
2885     return p;
2886 }
2887 
2888 /*
2889  * Call this function when something in the current buffer is changed.
2890  *
2891  * Most often called through changed_bytes() and changed_lines(), which also
2892  * mark the area of the display to be redrawn.
2893  *
2894  * Careful: may trigger autocommands that reload the buffer.
2895  */
2896     void
2897 changed(void)
2898 {
2899 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
2900     if (p_imst == IM_ON_THE_SPOT)
2901     {
2902 	/* The text of the preediting area is inserted, but this doesn't
2903 	 * mean a change of the buffer yet.  That is delayed until the
2904 	 * text is committed. (this means preedit becomes empty) */
2905 	if (im_is_preediting() && !xim_changed_while_preediting)
2906 	    return;
2907 	xim_changed_while_preediting = FALSE;
2908     }
2909 #endif
2910 
2911     if (!curbuf->b_changed)
2912     {
2913 	int	save_msg_scroll = msg_scroll;
2914 
2915 	/* Give a warning about changing a read-only file.  This may also
2916 	 * check-out the file, thus change "curbuf"! */
2917 	change_warning(0);
2918 
2919 	/* Create a swap file if that is wanted.
2920 	 * Don't do this for "nofile" and "nowrite" buffer types. */
2921 	if (curbuf->b_may_swap
2922 #ifdef FEAT_QUICKFIX
2923 		&& !bt_dontwrite(curbuf)
2924 #endif
2925 		)
2926 	{
2927 	    int save_need_wait_return = need_wait_return;
2928 
2929 	    need_wait_return = FALSE;
2930 	    ml_open_file(curbuf);
2931 
2932 	    /* The ml_open_file() can cause an ATTENTION message.
2933 	     * Wait two seconds, to make sure the user reads this unexpected
2934 	     * message.  Since we could be anywhere, call wait_return() now,
2935 	     * and don't let the emsg() set msg_scroll. */
2936 	    if (need_wait_return && emsg_silent == 0)
2937 	    {
2938 		out_flush();
2939 		ui_delay(2000L, TRUE);
2940 		wait_return(TRUE);
2941 		msg_scroll = save_msg_scroll;
2942 	    }
2943 	    else
2944 		need_wait_return = save_need_wait_return;
2945 	}
2946 	changed_int();
2947     }
2948     ++CHANGEDTICK(curbuf);
2949 }
2950 
2951 /*
2952  * Internal part of changed(), no user interaction.
2953  */
2954     void
2955 changed_int(void)
2956 {
2957     curbuf->b_changed = TRUE;
2958     ml_setflags(curbuf);
2959     check_status(curbuf);
2960     redraw_tabline = TRUE;
2961 #ifdef FEAT_TITLE
2962     need_maketitle = TRUE;	    /* set window title later */
2963 #endif
2964 }
2965 
2966 static void changedOneline(buf_T *buf, linenr_T lnum);
2967 static void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, long xtra);
2968 static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra);
2969 
2970 /*
2971  * Changed bytes within a single line for the current buffer.
2972  * - marks the windows on this buffer to be redisplayed
2973  * - marks the buffer changed by calling changed()
2974  * - invalidates cached values
2975  * Careful: may trigger autocommands that reload the buffer.
2976  */
2977     void
2978 changed_bytes(linenr_T lnum, colnr_T col)
2979 {
2980     changedOneline(curbuf, lnum);
2981     changed_common(lnum, col, lnum + 1, 0L);
2982 
2983 #ifdef FEAT_DIFF
2984     /* Diff highlighting in other diff windows may need to be updated too. */
2985     if (curwin->w_p_diff)
2986     {
2987 	win_T	    *wp;
2988 	linenr_T    wlnum;
2989 
2990 	FOR_ALL_WINDOWS(wp)
2991 	    if (wp->w_p_diff && wp != curwin)
2992 	    {
2993 		redraw_win_later(wp, VALID);
2994 		wlnum = diff_lnum_win(lnum, wp);
2995 		if (wlnum > 0)
2996 		    changedOneline(wp->w_buffer, wlnum);
2997 	    }
2998     }
2999 #endif
3000 }
3001 
3002     static void
3003 changedOneline(buf_T *buf, linenr_T lnum)
3004 {
3005     if (buf->b_mod_set)
3006     {
3007 	/* find the maximum area that must be redisplayed */
3008 	if (lnum < buf->b_mod_top)
3009 	    buf->b_mod_top = lnum;
3010 	else if (lnum >= buf->b_mod_bot)
3011 	    buf->b_mod_bot = lnum + 1;
3012     }
3013     else
3014     {
3015 	/* set the area that must be redisplayed to one line */
3016 	buf->b_mod_set = TRUE;
3017 	buf->b_mod_top = lnum;
3018 	buf->b_mod_bot = lnum + 1;
3019 	buf->b_mod_xlines = 0;
3020     }
3021 }
3022 
3023 /*
3024  * Appended "count" lines below line "lnum" in the current buffer.
3025  * Must be called AFTER the change and after mark_adjust().
3026  * Takes care of marking the buffer to be redrawn and sets the changed flag.
3027  */
3028     void
3029 appended_lines(linenr_T lnum, long count)
3030 {
3031     changed_lines(lnum + 1, 0, lnum + 1, count);
3032 }
3033 
3034 /*
3035  * Like appended_lines(), but adjust marks first.
3036  */
3037     void
3038 appended_lines_mark(linenr_T lnum, long count)
3039 {
3040     /* Skip mark_adjust when adding a line after the last one, there can't
3041      * be marks there. But it's still needed in diff mode. */
3042     if (lnum + count < curbuf->b_ml.ml_line_count
3043 #ifdef FEAT_DIFF
3044 	    || curwin->w_p_diff
3045 #endif
3046 	)
3047 	mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L);
3048     changed_lines(lnum + 1, 0, lnum + 1, count);
3049 }
3050 
3051 /*
3052  * Deleted "count" lines at line "lnum" in the current buffer.
3053  * Must be called AFTER the change and after mark_adjust().
3054  * Takes care of marking the buffer to be redrawn and sets the changed flag.
3055  */
3056     void
3057 deleted_lines(linenr_T lnum, long count)
3058 {
3059     changed_lines(lnum, 0, lnum + count, -count);
3060 }
3061 
3062 /*
3063  * Like deleted_lines(), but adjust marks first.
3064  * Make sure the cursor is on a valid line before calling, a GUI callback may
3065  * be triggered to display the cursor.
3066  */
3067     void
3068 deleted_lines_mark(linenr_T lnum, long count)
3069 {
3070     mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count);
3071     changed_lines(lnum, 0, lnum + count, -count);
3072 }
3073 
3074 /*
3075  * Changed lines for the current buffer.
3076  * Must be called AFTER the change and after mark_adjust().
3077  * - mark the buffer changed by calling changed()
3078  * - mark the windows on this buffer to be redisplayed
3079  * - invalidate cached values
3080  * "lnum" is the first line that needs displaying, "lnume" the first line
3081  * below the changed lines (BEFORE the change).
3082  * When only inserting lines, "lnum" and "lnume" are equal.
3083  * Takes care of calling changed() and updating b_mod_*.
3084  * Careful: may trigger autocommands that reload the buffer.
3085  */
3086     void
3087 changed_lines(
3088     linenr_T	lnum,	    /* first line with change */
3089     colnr_T	col,	    /* column in first line with change */
3090     linenr_T	lnume,	    /* line below last changed line */
3091     long	xtra)	    /* number of extra lines (negative when deleting) */
3092 {
3093     changed_lines_buf(curbuf, lnum, lnume, xtra);
3094 
3095 #ifdef FEAT_DIFF
3096     if (xtra == 0 && curwin->w_p_diff)
3097     {
3098 	/* When the number of lines doesn't change then mark_adjust() isn't
3099 	 * called and other diff buffers still need to be marked for
3100 	 * displaying. */
3101 	win_T	    *wp;
3102 	linenr_T    wlnum;
3103 
3104 	FOR_ALL_WINDOWS(wp)
3105 	    if (wp->w_p_diff && wp != curwin)
3106 	    {
3107 		redraw_win_later(wp, VALID);
3108 		wlnum = diff_lnum_win(lnum, wp);
3109 		if (wlnum > 0)
3110 		    changed_lines_buf(wp->w_buffer, wlnum,
3111 						    lnume - lnum + wlnum, 0L);
3112 	    }
3113     }
3114 #endif
3115 
3116     changed_common(lnum, col, lnume, xtra);
3117 }
3118 
3119     static void
3120 changed_lines_buf(
3121     buf_T	*buf,
3122     linenr_T	lnum,	    /* first line with change */
3123     linenr_T	lnume,	    /* line below last changed line */
3124     long	xtra)	    /* number of extra lines (negative when deleting) */
3125 {
3126     if (buf->b_mod_set)
3127     {
3128 	/* find the maximum area that must be redisplayed */
3129 	if (lnum < buf->b_mod_top)
3130 	    buf->b_mod_top = lnum;
3131 	if (lnum < buf->b_mod_bot)
3132 	{
3133 	    /* adjust old bot position for xtra lines */
3134 	    buf->b_mod_bot += xtra;
3135 	    if (buf->b_mod_bot < lnum)
3136 		buf->b_mod_bot = lnum;
3137 	}
3138 	if (lnume + xtra > buf->b_mod_bot)
3139 	    buf->b_mod_bot = lnume + xtra;
3140 	buf->b_mod_xlines += xtra;
3141     }
3142     else
3143     {
3144 	/* set the area that must be redisplayed */
3145 	buf->b_mod_set = TRUE;
3146 	buf->b_mod_top = lnum;
3147 	buf->b_mod_bot = lnume + xtra;
3148 	buf->b_mod_xlines = xtra;
3149     }
3150 }
3151 
3152 /*
3153  * Common code for when a change is was made.
3154  * See changed_lines() for the arguments.
3155  * Careful: may trigger autocommands that reload the buffer.
3156  */
3157     static void
3158 changed_common(
3159     linenr_T	lnum,
3160     colnr_T	col,
3161     linenr_T	lnume,
3162     long	xtra)
3163 {
3164     win_T	*wp;
3165     tabpage_T	*tp;
3166     int		i;
3167 #ifdef FEAT_JUMPLIST
3168     int		cols;
3169     pos_T	*p;
3170     int		add;
3171 #endif
3172 
3173     /* mark the buffer as modified */
3174     changed();
3175 
3176     /* set the '. mark */
3177     if (!cmdmod.keepjumps)
3178     {
3179 	curbuf->b_last_change.lnum = lnum;
3180 	curbuf->b_last_change.col = col;
3181 
3182 #ifdef FEAT_JUMPLIST
3183 	/* Create a new entry if a new undo-able change was started or we
3184 	 * don't have an entry yet. */
3185 	if (curbuf->b_new_change || curbuf->b_changelistlen == 0)
3186 	{
3187 	    if (curbuf->b_changelistlen == 0)
3188 		add = TRUE;
3189 	    else
3190 	    {
3191 		/* Don't create a new entry when the line number is the same
3192 		 * as the last one and the column is not too far away.  Avoids
3193 		 * creating many entries for typing "xxxxx". */
3194 		p = &curbuf->b_changelist[curbuf->b_changelistlen - 1];
3195 		if (p->lnum != lnum)
3196 		    add = TRUE;
3197 		else
3198 		{
3199 		    cols = comp_textwidth(FALSE);
3200 		    if (cols == 0)
3201 			cols = 79;
3202 		    add = (p->col + cols < col || col + cols < p->col);
3203 		}
3204 	    }
3205 	    if (add)
3206 	    {
3207 		/* This is the first of a new sequence of undo-able changes
3208 		 * and it's at some distance of the last change.  Use a new
3209 		 * position in the changelist. */
3210 		curbuf->b_new_change = FALSE;
3211 
3212 		if (curbuf->b_changelistlen == JUMPLISTSIZE)
3213 		{
3214 		    /* changelist is full: remove oldest entry */
3215 		    curbuf->b_changelistlen = JUMPLISTSIZE - 1;
3216 		    mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1,
3217 					  sizeof(pos_T) * (JUMPLISTSIZE - 1));
3218 		    FOR_ALL_TAB_WINDOWS(tp, wp)
3219 		    {
3220 			/* Correct position in changelist for other windows on
3221 			 * this buffer. */
3222 			if (wp->w_buffer == curbuf && wp->w_changelistidx > 0)
3223 			    --wp->w_changelistidx;
3224 		    }
3225 		}
3226 		FOR_ALL_TAB_WINDOWS(tp, wp)
3227 		{
3228 		    /* For other windows, if the position in the changelist is
3229 		     * at the end it stays at the end. */
3230 		    if (wp->w_buffer == curbuf
3231 			    && wp->w_changelistidx == curbuf->b_changelistlen)
3232 			++wp->w_changelistidx;
3233 		}
3234 		++curbuf->b_changelistlen;
3235 	    }
3236 	}
3237 	curbuf->b_changelist[curbuf->b_changelistlen - 1] =
3238 							curbuf->b_last_change;
3239 	/* The current window is always after the last change, so that "g,"
3240 	 * takes you back to it. */
3241 	curwin->w_changelistidx = curbuf->b_changelistlen;
3242 #endif
3243     }
3244 
3245     FOR_ALL_TAB_WINDOWS(tp, wp)
3246     {
3247 	if (wp->w_buffer == curbuf)
3248 	{
3249 	    /* Mark this window to be redrawn later. */
3250 	    if (wp->w_redr_type < VALID)
3251 		wp->w_redr_type = VALID;
3252 
3253 	    /* Check if a change in the buffer has invalidated the cached
3254 	     * values for the cursor. */
3255 #ifdef FEAT_FOLDING
3256 	    /*
3257 	     * Update the folds for this window.  Can't postpone this, because
3258 	     * a following operator might work on the whole fold: ">>dd".
3259 	     */
3260 	    foldUpdate(wp, lnum, lnume + xtra - 1);
3261 
3262 	    /* The change may cause lines above or below the change to become
3263 	     * included in a fold.  Set lnum/lnume to the first/last line that
3264 	     * might be displayed differently.
3265 	     * Set w_cline_folded here as an efficient way to update it when
3266 	     * inserting lines just above a closed fold. */
3267 	    i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL);
3268 	    if (wp->w_cursor.lnum == lnum)
3269 		wp->w_cline_folded = i;
3270 	    i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL);
3271 	    if (wp->w_cursor.lnum == lnume)
3272 		wp->w_cline_folded = i;
3273 
3274 	    /* If the changed line is in a range of previously folded lines,
3275 	     * compare with the first line in that range. */
3276 	    if (wp->w_cursor.lnum <= lnum)
3277 	    {
3278 		i = find_wl_entry(wp, lnum);
3279 		if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum)
3280 		    changed_line_abv_curs_win(wp);
3281 	    }
3282 #endif
3283 
3284 	    if (wp->w_cursor.lnum > lnum)
3285 		changed_line_abv_curs_win(wp);
3286 	    else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col)
3287 		changed_cline_bef_curs_win(wp);
3288 	    if (wp->w_botline >= lnum)
3289 	    {
3290 		/* Assume that botline doesn't change (inserted lines make
3291 		 * other lines scroll down below botline). */
3292 		approximate_botline_win(wp);
3293 	    }
3294 
3295 	    /* Check if any w_lines[] entries have become invalid.
3296 	     * For entries below the change: Correct the lnums for
3297 	     * inserted/deleted lines.  Makes it possible to stop displaying
3298 	     * after the change. */
3299 	    for (i = 0; i < wp->w_lines_valid; ++i)
3300 		if (wp->w_lines[i].wl_valid)
3301 		{
3302 		    if (wp->w_lines[i].wl_lnum >= lnum)
3303 		    {
3304 			if (wp->w_lines[i].wl_lnum < lnume)
3305 			{
3306 			    /* line included in change */
3307 			    wp->w_lines[i].wl_valid = FALSE;
3308 			}
3309 			else if (xtra != 0)
3310 			{
3311 			    /* line below change */
3312 			    wp->w_lines[i].wl_lnum += xtra;
3313 #ifdef FEAT_FOLDING
3314 			    wp->w_lines[i].wl_lastlnum += xtra;
3315 #endif
3316 			}
3317 		    }
3318 #ifdef FEAT_FOLDING
3319 		    else if (wp->w_lines[i].wl_lastlnum >= lnum)
3320 		    {
3321 			/* change somewhere inside this range of folded lines,
3322 			 * may need to be redrawn */
3323 			wp->w_lines[i].wl_valid = FALSE;
3324 		    }
3325 #endif
3326 		}
3327 
3328 #ifdef FEAT_FOLDING
3329 	    /* Take care of side effects for setting w_topline when folds have
3330 	     * changed.  Esp. when the buffer was changed in another window. */
3331 	    if (hasAnyFolding(wp))
3332 		set_topline(wp, wp->w_topline);
3333 #endif
3334 	    /* relative numbering may require updating more */
3335 	    if (wp->w_p_rnu)
3336 		redraw_win_later(wp, SOME_VALID);
3337 	}
3338     }
3339 
3340     /* Call update_screen() later, which checks out what needs to be redrawn,
3341      * since it notices b_mod_set and then uses b_mod_*. */
3342     if (must_redraw < VALID)
3343 	must_redraw = VALID;
3344 
3345     /* when the cursor line is changed always trigger CursorMoved */
3346     if (lnum <= curwin->w_cursor.lnum
3347 		 && lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum)
3348 	last_cursormoved.lnum = 0;
3349 }
3350 
3351 /*
3352  * unchanged() is called when the changed flag must be reset for buffer 'buf'
3353  */
3354     void
3355 unchanged(
3356     buf_T	*buf,
3357     int		ff)	/* also reset 'fileformat' */
3358 {
3359     if (buf->b_changed || (ff && file_ff_differs(buf, FALSE)))
3360     {
3361 	buf->b_changed = 0;
3362 	ml_setflags(buf);
3363 	if (ff)
3364 	    save_file_ff(buf);
3365 	check_status(buf);
3366 	redraw_tabline = TRUE;
3367 #ifdef FEAT_TITLE
3368 	need_maketitle = TRUE;	    /* set window title later */
3369 #endif
3370     }
3371     ++CHANGEDTICK(buf);
3372 #ifdef FEAT_NETBEANS_INTG
3373     netbeans_unmodified(buf);
3374 #endif
3375 }
3376 
3377 /*
3378  * check_status: called when the status bars for the buffer 'buf'
3379  *		 need to be updated
3380  */
3381     void
3382 check_status(buf_T *buf)
3383 {
3384     win_T	*wp;
3385 
3386     FOR_ALL_WINDOWS(wp)
3387 	if (wp->w_buffer == buf && wp->w_status_height)
3388 	{
3389 	    wp->w_redr_status = TRUE;
3390 	    if (must_redraw < VALID)
3391 		must_redraw = VALID;
3392 	}
3393 }
3394 
3395 /*
3396  * If the file is readonly, give a warning message with the first change.
3397  * Don't do this for autocommands.
3398  * Don't use emsg(), because it flushes the macro buffer.
3399  * If we have undone all changes b_changed will be FALSE, but "b_did_warn"
3400  * will be TRUE.
3401  * Careful: may trigger autocommands that reload the buffer.
3402  */
3403     void
3404 change_warning(
3405     int	    col)		/* column for message; non-zero when in insert
3406 				   mode and 'showmode' is on */
3407 {
3408     static char *w_readonly = N_("W10: Warning: Changing a readonly file");
3409 
3410     if (curbuf->b_did_warn == FALSE
3411 	    && curbufIsChanged() == 0
3412 	    && !autocmd_busy
3413 	    && curbuf->b_p_ro)
3414     {
3415 	++curbuf_lock;
3416 	apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf);
3417 	--curbuf_lock;
3418 	if (!curbuf->b_p_ro)
3419 	    return;
3420 	/*
3421 	 * Do what msg() does, but with a column offset if the warning should
3422 	 * be after the mode message.
3423 	 */
3424 	msg_start();
3425 	if (msg_row == Rows - 1)
3426 	    msg_col = col;
3427 	msg_source(HL_ATTR(HLF_W));
3428 	MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST);
3429 #ifdef FEAT_EVAL
3430 	set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_readonly), -1);
3431 #endif
3432 	msg_clr_eos();
3433 	(void)msg_end();
3434 	if (msg_silent == 0 && !silent_mode
3435 #ifdef FEAT_EVAL
3436 		&& time_for_testing != 1
3437 #endif
3438 		)
3439 	{
3440 	    out_flush();
3441 	    ui_delay(1000L, TRUE); /* give the user time to think about it */
3442 	}
3443 	curbuf->b_did_warn = TRUE;
3444 	redraw_cmdline = FALSE;	/* don't redraw and erase the message */
3445 	if (msg_row < Rows - 1)
3446 	    showmode();
3447     }
3448 }
3449 
3450 /*
3451  * Ask for a reply from the user, a 'y' or a 'n'.
3452  * No other characters are accepted, the message is repeated until a valid
3453  * reply is entered or CTRL-C is hit.
3454  * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
3455  * from any buffers but directly from the user.
3456  *
3457  * return the 'y' or 'n'
3458  */
3459     int
3460 ask_yesno(char_u *str, int direct)
3461 {
3462     int	    r = ' ';
3463     int	    save_State = State;
3464 
3465     if (exiting)		/* put terminal in raw mode for this question */
3466 	settmode(TMODE_RAW);
3467     ++no_wait_return;
3468 #ifdef USE_ON_FLY_SCROLL
3469     dont_scroll = TRUE;		/* disallow scrolling here */
3470 #endif
3471     State = CONFIRM;		/* mouse behaves like with :confirm */
3472 #ifdef FEAT_MOUSE
3473     setmouse();			/* disables mouse for xterm */
3474 #endif
3475     ++no_mapping;
3476     ++allow_keys;		/* no mapping here, but recognize keys */
3477 
3478     while (r != 'y' && r != 'n')
3479     {
3480 	/* same highlighting as for wait_return */
3481 	smsg_attr(HL_ATTR(HLF_R), (char_u *)"%s (y/n)?", str);
3482 	if (direct)
3483 	    r = get_keystroke();
3484 	else
3485 	    r = plain_vgetc();
3486 	if (r == Ctrl_C || r == ESC)
3487 	    r = 'n';
3488 	msg_putchar(r);	    /* show what you typed */
3489 	out_flush();
3490     }
3491     --no_wait_return;
3492     State = save_State;
3493 #ifdef FEAT_MOUSE
3494     setmouse();
3495 #endif
3496     --no_mapping;
3497     --allow_keys;
3498 
3499     return r;
3500 }
3501 
3502 #if defined(FEAT_MOUSE) || defined(PROTO)
3503 /*
3504  * Return TRUE if "c" is a mouse key.
3505  */
3506     int
3507 is_mouse_key(int c)
3508 {
3509     return c == K_LEFTMOUSE
3510 	|| c == K_LEFTMOUSE_NM
3511 	|| c == K_LEFTDRAG
3512 	|| c == K_LEFTRELEASE
3513 	|| c == K_LEFTRELEASE_NM
3514 	|| c == K_MOUSEMOVE
3515 	|| c == K_MIDDLEMOUSE
3516 	|| c == K_MIDDLEDRAG
3517 	|| c == K_MIDDLERELEASE
3518 	|| c == K_RIGHTMOUSE
3519 	|| c == K_RIGHTDRAG
3520 	|| c == K_RIGHTRELEASE
3521 	|| c == K_MOUSEDOWN
3522 	|| c == K_MOUSEUP
3523 	|| c == K_MOUSELEFT
3524 	|| c == K_MOUSERIGHT
3525 	|| c == K_X1MOUSE
3526 	|| c == K_X1DRAG
3527 	|| c == K_X1RELEASE
3528 	|| c == K_X2MOUSE
3529 	|| c == K_X2DRAG
3530 	|| c == K_X2RELEASE;
3531 }
3532 #endif
3533 
3534 /*
3535  * Get a key stroke directly from the user.
3536  * Ignores mouse clicks and scrollbar events, except a click for the left
3537  * button (used at the more prompt).
3538  * Doesn't use vgetc(), because it syncs undo and eats mapped characters.
3539  * Disadvantage: typeahead is ignored.
3540  * Translates the interrupt character for unix to ESC.
3541  */
3542     int
3543 get_keystroke(void)
3544 {
3545     char_u	*buf = NULL;
3546     int		buflen = 150;
3547     int		maxlen;
3548     int		len = 0;
3549     int		n;
3550     int		save_mapped_ctrl_c = mapped_ctrl_c;
3551     int		waited = 0;
3552 
3553     mapped_ctrl_c = FALSE;	/* mappings are not used here */
3554     for (;;)
3555     {
3556 	cursor_on();
3557 	out_flush();
3558 
3559 	/* Leave some room for check_termcode() to insert a key code into (max
3560 	 * 5 chars plus NUL).  And fix_input_buffer() can triple the number of
3561 	 * bytes. */
3562 	maxlen = (buflen - 6 - len) / 3;
3563 	if (buf == NULL)
3564 	    buf = alloc(buflen);
3565 	else if (maxlen < 10)
3566 	{
3567 	    char_u  *t_buf = buf;
3568 
3569 	    /* Need some more space. This might happen when receiving a long
3570 	     * escape sequence. */
3571 	    buflen += 100;
3572 	    buf = vim_realloc(buf, buflen);
3573 	    if (buf == NULL)
3574 		vim_free(t_buf);
3575 	    maxlen = (buflen - 6 - len) / 3;
3576 	}
3577 	if (buf == NULL)
3578 	{
3579 	    do_outofmem_msg((long_u)buflen);
3580 	    return ESC;  /* panic! */
3581 	}
3582 
3583 	/* First time: blocking wait.  Second time: wait up to 100ms for a
3584 	 * terminal code to complete. */
3585 	n = ui_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0);
3586 	if (n > 0)
3587 	{
3588 	    /* Replace zero and CSI by a special key code. */
3589 	    n = fix_input_buffer(buf + len, n);
3590 	    len += n;
3591 	    waited = 0;
3592 	}
3593 	else if (len > 0)
3594 	    ++waited;	    /* keep track of the waiting time */
3595 
3596 	/* Incomplete termcode and not timed out yet: get more characters */
3597 	if ((n = check_termcode(1, buf, buflen, &len)) < 0
3598 	       && (!p_ttimeout || waited * 100L < (p_ttm < 0 ? p_tm : p_ttm)))
3599 	    continue;
3600 
3601 	if (n == KEYLEN_REMOVED)  /* key code removed */
3602 	{
3603 	    if (must_redraw != 0 && !need_wait_return && (State & CMDLINE) == 0)
3604 	    {
3605 		/* Redrawing was postponed, do it now. */
3606 		update_screen(0);
3607 		setcursor(); /* put cursor back where it belongs */
3608 	    }
3609 	    continue;
3610 	}
3611 	if (n > 0)		/* found a termcode: adjust length */
3612 	    len = n;
3613 	if (len == 0)		/* nothing typed yet */
3614 	    continue;
3615 
3616 	/* Handle modifier and/or special key code. */
3617 	n = buf[0];
3618 	if (n == K_SPECIAL)
3619 	{
3620 	    n = TO_SPECIAL(buf[1], buf[2]);
3621 	    if (buf[1] == KS_MODIFIER
3622 		    || n == K_IGNORE
3623 #ifdef FEAT_MOUSE
3624 		    || (is_mouse_key(n) && n != K_LEFTMOUSE)
3625 #endif
3626 #ifdef FEAT_GUI
3627 		    || n == K_VER_SCROLLBAR
3628 		    || n == K_HOR_SCROLLBAR
3629 #endif
3630 	       )
3631 	    {
3632 		if (buf[1] == KS_MODIFIER)
3633 		    mod_mask = buf[2];
3634 		len -= 3;
3635 		if (len > 0)
3636 		    mch_memmove(buf, buf + 3, (size_t)len);
3637 		continue;
3638 	    }
3639 	    break;
3640 	}
3641 #ifdef FEAT_MBYTE
3642 	if (has_mbyte)
3643 	{
3644 	    if (MB_BYTE2LEN(n) > len)
3645 		continue;	/* more bytes to get */
3646 	    buf[len >= buflen ? buflen - 1 : len] = NUL;
3647 	    n = (*mb_ptr2char)(buf);
3648 	}
3649 #endif
3650 #ifdef UNIX
3651 	if (n == intr_char)
3652 	    n = ESC;
3653 #endif
3654 	break;
3655     }
3656     vim_free(buf);
3657 
3658     mapped_ctrl_c = save_mapped_ctrl_c;
3659     return n;
3660 }
3661 
3662 /*
3663  * Get a number from the user.
3664  * When "mouse_used" is not NULL allow using the mouse.
3665  */
3666     int
3667 get_number(
3668     int	    colon,			/* allow colon to abort */
3669     int	    *mouse_used)
3670 {
3671     int	n = 0;
3672     int	c;
3673     int typed = 0;
3674 
3675     if (mouse_used != NULL)
3676 	*mouse_used = FALSE;
3677 
3678     /* When not printing messages, the user won't know what to type, return a
3679      * zero (as if CR was hit). */
3680     if (msg_silent != 0)
3681 	return 0;
3682 
3683 #ifdef USE_ON_FLY_SCROLL
3684     dont_scroll = TRUE;		/* disallow scrolling here */
3685 #endif
3686     ++no_mapping;
3687     ++allow_keys;		/* no mapping here, but recognize keys */
3688     for (;;)
3689     {
3690 	windgoto(msg_row, msg_col);
3691 	c = safe_vgetc();
3692 	if (VIM_ISDIGIT(c))
3693 	{
3694 	    n = n * 10 + c - '0';
3695 	    msg_putchar(c);
3696 	    ++typed;
3697 	}
3698 	else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H)
3699 	{
3700 	    if (typed > 0)
3701 	    {
3702 		MSG_PUTS("\b \b");
3703 		--typed;
3704 	    }
3705 	    n /= 10;
3706 	}
3707 #ifdef FEAT_MOUSE
3708 	else if (mouse_used != NULL && c == K_LEFTMOUSE)
3709 	{
3710 	    *mouse_used = TRUE;
3711 	    n = mouse_row + 1;
3712 	    break;
3713 	}
3714 #endif
3715 	else if (n == 0 && c == ':' && colon)
3716 	{
3717 	    stuffcharReadbuff(':');
3718 	    if (!exmode_active)
3719 		cmdline_row = msg_row;
3720 	    skip_redraw = TRUE;	    /* skip redraw once */
3721 	    do_redraw = FALSE;
3722 	    break;
3723 	}
3724 	else if (c == CAR || c == NL || c == Ctrl_C || c == ESC)
3725 	    break;
3726     }
3727     --no_mapping;
3728     --allow_keys;
3729     return n;
3730 }
3731 
3732 /*
3733  * Ask the user to enter a number.
3734  * When "mouse_used" is not NULL allow using the mouse and in that case return
3735  * the line number.
3736  */
3737     int
3738 prompt_for_number(int *mouse_used)
3739 {
3740     int		i;
3741     int		save_cmdline_row;
3742     int		save_State;
3743 
3744     /* When using ":silent" assume that <CR> was entered. */
3745     if (mouse_used != NULL)
3746 	MSG_PUTS(_("Type number and <Enter> or click with mouse (empty cancels): "));
3747     else
3748 	MSG_PUTS(_("Type number and <Enter> (empty cancels): "));
3749 
3750     // Set the state such that text can be selected/copied/pasted and we still
3751     // get mouse events. redraw_after_callback() will not redraw if cmdline_row
3752     // is zero.
3753     save_cmdline_row = cmdline_row;
3754     cmdline_row = 0;
3755     save_State = State;
3756     State = CMDLINE;
3757 #ifdef FEAT_MOUSE
3758     // May show different mouse shape.
3759     setmouse();
3760 #endif
3761 
3762     i = get_number(TRUE, mouse_used);
3763     if (KeyTyped)
3764     {
3765 	/* don't call wait_return() now */
3766 	/* msg_putchar('\n'); */
3767 	cmdline_row = msg_row - 1;
3768 	need_wait_return = FALSE;
3769 	msg_didany = FALSE;
3770 	msg_didout = FALSE;
3771     }
3772     else
3773 	cmdline_row = save_cmdline_row;
3774     State = save_State;
3775 #ifdef FEAT_MOUSE
3776     // May need to restore mouse shape.
3777     setmouse();
3778 #endif
3779 
3780     return i;
3781 }
3782 
3783     void
3784 msgmore(long n)
3785 {
3786     long pn;
3787 
3788     if (global_busy	    /* no messages now, wait until global is finished */
3789 	    || !messaging())  /* 'lazyredraw' set, don't do messages now */
3790 	return;
3791 
3792     /* We don't want to overwrite another important message, but do overwrite
3793      * a previous "more lines" or "fewer lines" message, so that "5dd" and
3794      * then "put" reports the last action. */
3795     if (keep_msg != NULL && !keep_msg_more)
3796 	return;
3797 
3798     if (n > 0)
3799 	pn = n;
3800     else
3801 	pn = -n;
3802 
3803     if (pn > p_report)
3804     {
3805 	if (n > 0)
3806 	    vim_snprintf((char *)msg_buf, MSG_BUF_LEN,
3807 		    NGETTEXT("%ld more line", "%ld more lines", pn), pn);
3808 	else
3809 	    vim_snprintf((char *)msg_buf, MSG_BUF_LEN,
3810 		    NGETTEXT("%ld line less", "%ld fewer lines", pn), pn);
3811 	if (got_int)
3812 	    vim_strcat(msg_buf, (char_u *)_(" (Interrupted)"), MSG_BUF_LEN);
3813 	if (msg(msg_buf))
3814 	{
3815 	    set_keep_msg(msg_buf, 0);
3816 	    keep_msg_more = TRUE;
3817 	}
3818     }
3819 }
3820 
3821 /*
3822  * flush map and typeahead buffers and give a warning for an error
3823  */
3824     void
3825 beep_flush(void)
3826 {
3827     if (emsg_silent == 0)
3828     {
3829 	flush_buffers(FALSE);
3830 	vim_beep(BO_ERROR);
3831     }
3832 }
3833 
3834 /*
3835  * Give a warning for an error.
3836  */
3837     void
3838 vim_beep(
3839     unsigned val) /* one of the BO_ values, e.g., BO_OPER */
3840 {
3841 #ifdef FEAT_EVAL
3842     called_vim_beep = TRUE;
3843 #endif
3844 
3845     if (emsg_silent == 0)
3846     {
3847 	if (!((bo_flags & val) || (bo_flags & BO_ALL)))
3848 	{
3849 #ifdef ELAPSED_FUNC
3850 	    static int		did_init = FALSE;
3851 	    static ELAPSED_TYPE	start_tv;
3852 
3853 	    /* Only beep once per half a second, otherwise a sequence of beeps
3854 	     * would freeze Vim. */
3855 	    if (!did_init || ELAPSED_FUNC(start_tv) > 500)
3856 	    {
3857 		did_init = TRUE;
3858 		ELAPSED_INIT(start_tv);
3859 #endif
3860 		if (p_vb
3861 #ifdef FEAT_GUI
3862 			/* While the GUI is starting up the termcap is set for
3863 			 * the GUI but the output still goes to a terminal. */
3864 			&& !(gui.in_use && gui.starting)
3865 #endif
3866 			)
3867 		{
3868 		    out_str_cf(T_VB);
3869 #ifdef FEAT_VTP
3870 		    /* No restore color information, refresh the screen. */
3871 		    if (has_vtp_working() != 0
3872 # ifdef FEAT_TERMGUICOLORS
3873 			    && (p_tgc || (!p_tgc && t_colors >= 256))
3874 # endif
3875 			)
3876 		    {
3877 			redraw_later(CLEAR);
3878 			update_screen(0);
3879 			redrawcmd();
3880 		    }
3881 #endif
3882 		}
3883 		else
3884 		    out_char(BELL);
3885 #ifdef ELAPSED_FUNC
3886 	    }
3887 #endif
3888 	}
3889 
3890 	/* When 'debug' contains "beep" produce a message.  If we are sourcing
3891 	 * a script or executing a function give the user a hint where the beep
3892 	 * comes from. */
3893 	if (vim_strchr(p_debug, 'e') != NULL)
3894 	{
3895 	    msg_source(HL_ATTR(HLF_W));
3896 	    msg_attr((char_u *)_("Beep!"), HL_ATTR(HLF_W));
3897 	}
3898     }
3899 }
3900 
3901 /*
3902  * To get the "real" home directory:
3903  * - get value of $HOME
3904  * For Unix:
3905  *  - go to that directory
3906  *  - do mch_dirname() to get the real name of that directory.
3907  *  This also works with mounts and links.
3908  *  Don't do this for MS-DOS, it will change the "current dir" for a drive.
3909  */
3910 static char_u	*homedir = NULL;
3911 
3912     void
3913 init_homedir(void)
3914 {
3915     char_u  *var;
3916 
3917     /* In case we are called a second time (when 'encoding' changes). */
3918     VIM_CLEAR(homedir);
3919 
3920 #ifdef VMS
3921     var = mch_getenv((char_u *)"SYS$LOGIN");
3922 #else
3923     var = mch_getenv((char_u *)"HOME");
3924 #endif
3925 
3926 #ifdef WIN3264
3927     /*
3928      * Typically, $HOME is not defined on Windows, unless the user has
3929      * specifically defined it for Vim's sake.  However, on Windows NT
3930      * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
3931      * each user.  Try constructing $HOME from these.
3932      */
3933     if (var == NULL || *var == NUL)
3934     {
3935 	char_u *homedrive, *homepath;
3936 
3937 	homedrive = mch_getenv((char_u *)"HOMEDRIVE");
3938 	homepath = mch_getenv((char_u *)"HOMEPATH");
3939 	if (homepath == NULL || *homepath == NUL)
3940 	    homepath = (char_u *)"\\";
3941 	if (homedrive != NULL
3942 			   && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
3943 	{
3944 	    sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
3945 	    if (NameBuff[0] != NUL)
3946 		var = NameBuff;
3947 	}
3948     }
3949 
3950     if (var == NULL)
3951 	var = mch_getenv((char_u *)"USERPROFILE");
3952 
3953     /*
3954      * Weird but true: $HOME may contain an indirect reference to another
3955      * variable, esp. "%USERPROFILE%".  Happens when $USERPROFILE isn't set
3956      * when $HOME is being set.
3957      */
3958     if (var != NULL && *var == '%')
3959     {
3960 	char_u	*p;
3961 	char_u	*exp;
3962 
3963 	p = vim_strchr(var + 1, '%');
3964 	if (p != NULL)
3965 	{
3966 	    vim_strncpy(NameBuff, var + 1, p - (var + 1));
3967 	    exp = mch_getenv(NameBuff);
3968 	    if (exp != NULL && *exp != NUL
3969 					&& STRLEN(exp) + STRLEN(p) < MAXPATHL)
3970 	    {
3971 		vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1);
3972 		var = NameBuff;
3973 	    }
3974 	}
3975     }
3976 
3977     if (var != NULL && *var == NUL)	/* empty is same as not set */
3978 	var = NULL;
3979 
3980 # ifdef FEAT_MBYTE
3981     if (enc_utf8 && var != NULL)
3982     {
3983 	int	len;
3984 	char_u  *pp = NULL;
3985 
3986 	/* Convert from active codepage to UTF-8.  Other conversions are
3987 	 * not done, because they would fail for non-ASCII characters. */
3988 	acp_to_enc(var, (int)STRLEN(var), &pp, &len);
3989 	if (pp != NULL)
3990 	{
3991 	    homedir = pp;
3992 	    return;
3993 	}
3994     }
3995 # endif
3996 
3997     /*
3998      * Default home dir is C:/
3999      * Best assumption we can make in such a situation.
4000      */
4001     if (var == NULL)
4002 	var = (char_u *)"C:/";
4003 #endif
4004 
4005     if (var != NULL)
4006     {
4007 #ifdef UNIX
4008 	/*
4009 	 * Change to the directory and get the actual path.  This resolves
4010 	 * links.  Don't do it when we can't return.
4011 	 */
4012 	if (mch_dirname(NameBuff, MAXPATHL) == OK
4013 					  && mch_chdir((char *)NameBuff) == 0)
4014 	{
4015 	    if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK)
4016 		var = IObuff;
4017 	    if (mch_chdir((char *)NameBuff) != 0)
4018 		EMSG(_(e_prev_dir));
4019 	}
4020 #endif
4021 	homedir = vim_strsave(var);
4022     }
4023 }
4024 
4025 #if defined(EXITFREE) || defined(PROTO)
4026     void
4027 free_homedir(void)
4028 {
4029     vim_free(homedir);
4030 }
4031 
4032 # ifdef FEAT_CMDL_COMPL
4033     void
4034 free_users(void)
4035 {
4036     ga_clear_strings(&ga_users);
4037 }
4038 # endif
4039 #endif
4040 
4041 /*
4042  * Call expand_env() and store the result in an allocated string.
4043  * This is not very memory efficient, this expects the result to be freed
4044  * again soon.
4045  */
4046     char_u *
4047 expand_env_save(char_u *src)
4048 {
4049     return expand_env_save_opt(src, FALSE);
4050 }
4051 
4052 /*
4053  * Idem, but when "one" is TRUE handle the string as one file name, only
4054  * expand "~" at the start.
4055  */
4056     char_u *
4057 expand_env_save_opt(char_u *src, int one)
4058 {
4059     char_u	*p;
4060 
4061     p = alloc(MAXPATHL);
4062     if (p != NULL)
4063 	expand_env_esc(src, p, MAXPATHL, FALSE, one, NULL);
4064     return p;
4065 }
4066 
4067 /*
4068  * Expand environment variable with path name.
4069  * "~/" is also expanded, using $HOME.	For Unix "~user/" is expanded.
4070  * Skips over "\ ", "\~" and "\$" (not for Win32 though).
4071  * If anything fails no expansion is done and dst equals src.
4072  */
4073     void
4074 expand_env(
4075     char_u	*src,		/* input string e.g. "$HOME/vim.hlp" */
4076     char_u	*dst,		/* where to put the result */
4077     int		dstlen)		/* maximum length of the result */
4078 {
4079     expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL);
4080 }
4081 
4082     void
4083 expand_env_esc(
4084     char_u	*srcp,		/* input string e.g. "$HOME/vim.hlp" */
4085     char_u	*dst,		/* where to put the result */
4086     int		dstlen,		/* maximum length of the result */
4087     int		esc,		/* escape spaces in expanded variables */
4088     int		one,		/* "srcp" is one file name */
4089     char_u	*startstr)	/* start again after this (can be NULL) */
4090 {
4091     char_u	*src;
4092     char_u	*tail;
4093     int		c;
4094     char_u	*var;
4095     int		copy_char;
4096     int		mustfree;	/* var was allocated, need to free it later */
4097     int		at_start = TRUE; /* at start of a name */
4098     int		startstr_len = 0;
4099 
4100     if (startstr != NULL)
4101 	startstr_len = (int)STRLEN(startstr);
4102 
4103     src = skipwhite(srcp);
4104     --dstlen;		    /* leave one char space for "\," */
4105     while (*src && dstlen > 0)
4106     {
4107 #ifdef FEAT_EVAL
4108 	/* Skip over `=expr`. */
4109 	if (src[0] == '`' && src[1] == '=')
4110 	{
4111 	    size_t len;
4112 
4113 	    var = src;
4114 	    src += 2;
4115 	    (void)skip_expr(&src);
4116 	    if (*src == '`')
4117 		++src;
4118 	    len = src - var;
4119 	    if (len > (size_t)dstlen)
4120 		len = dstlen;
4121 	    vim_strncpy(dst, var, len);
4122 	    dst += len;
4123 	    dstlen -= (int)len;
4124 	    continue;
4125 	}
4126 #endif
4127 	copy_char = TRUE;
4128 	if ((*src == '$'
4129 #ifdef VMS
4130 		    && at_start
4131 #endif
4132 	   )
4133 #if defined(MSWIN)
4134 		|| *src == '%'
4135 #endif
4136 		|| (*src == '~' && at_start))
4137 	{
4138 	    mustfree = FALSE;
4139 
4140 	    /*
4141 	     * The variable name is copied into dst temporarily, because it may
4142 	     * be a string in read-only memory and a NUL needs to be appended.
4143 	     */
4144 	    if (*src != '~')				/* environment var */
4145 	    {
4146 		tail = src + 1;
4147 		var = dst;
4148 		c = dstlen - 1;
4149 
4150 #ifdef UNIX
4151 		/* Unix has ${var-name} type environment vars */
4152 		if (*tail == '{' && !vim_isIDc('{'))
4153 		{
4154 		    tail++;	/* ignore '{' */
4155 		    while (c-- > 0 && *tail && *tail != '}')
4156 			*var++ = *tail++;
4157 		}
4158 		else
4159 #endif
4160 		{
4161 		    while (c-- > 0 && *tail != NUL && ((vim_isIDc(*tail))
4162 #if defined(MSWIN)
4163 			    || (*src == '%' && *tail != '%')
4164 #endif
4165 			    ))
4166 		    {
4167 			*var++ = *tail++;
4168 		    }
4169 		}
4170 
4171 #if defined(MSWIN) || defined(UNIX)
4172 # ifdef UNIX
4173 		if (src[1] == '{' && *tail != '}')
4174 # else
4175 		if (*src == '%' && *tail != '%')
4176 # endif
4177 		    var = NULL;
4178 		else
4179 		{
4180 # ifdef UNIX
4181 		    if (src[1] == '{')
4182 # else
4183 		    if (*src == '%')
4184 #endif
4185 			++tail;
4186 #endif
4187 		    *var = NUL;
4188 		    var = vim_getenv(dst, &mustfree);
4189 #if defined(MSWIN) || defined(UNIX)
4190 		}
4191 #endif
4192 	    }
4193 							/* home directory */
4194 	    else if (  src[1] == NUL
4195 		    || vim_ispathsep(src[1])
4196 		    || vim_strchr((char_u *)" ,\t\n", src[1]) != NULL)
4197 	    {
4198 		var = homedir;
4199 		tail = src + 1;
4200 	    }
4201 	    else					/* user directory */
4202 	    {
4203 #if defined(UNIX) || (defined(VMS) && defined(USER_HOME))
4204 		/*
4205 		 * Copy ~user to dst[], so we can put a NUL after it.
4206 		 */
4207 		tail = src;
4208 		var = dst;
4209 		c = dstlen - 1;
4210 		while (	   c-- > 0
4211 			&& *tail
4212 			&& vim_isfilec(*tail)
4213 			&& !vim_ispathsep(*tail))
4214 		    *var++ = *tail++;
4215 		*var = NUL;
4216 # ifdef UNIX
4217 		/*
4218 		 * If the system supports getpwnam(), use it.
4219 		 * Otherwise, or if getpwnam() fails, the shell is used to
4220 		 * expand ~user.  This is slower and may fail if the shell
4221 		 * does not support ~user (old versions of /bin/sh).
4222 		 */
4223 #  if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
4224 		{
4225 		    /* Note: memory allocated by getpwnam() is never freed.
4226 		     * Calling endpwent() apparently doesn't help. */
4227 		    struct passwd *pw = (*dst == NUL)
4228 					? NULL : getpwnam((char *)dst + 1);
4229 
4230 		    var = (pw == NULL) ? NULL : (char_u *)pw->pw_dir;
4231 		}
4232 		if (var == NULL)
4233 #  endif
4234 		{
4235 		    expand_T	xpc;
4236 
4237 		    ExpandInit(&xpc);
4238 		    xpc.xp_context = EXPAND_FILES;
4239 		    var = ExpandOne(&xpc, dst, NULL,
4240 				WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE);
4241 		    mustfree = TRUE;
4242 		}
4243 
4244 # else	/* !UNIX, thus VMS */
4245 		/*
4246 		 * USER_HOME is a comma-separated list of
4247 		 * directories to search for the user account in.
4248 		 */
4249 		{
4250 		    char_u	test[MAXPATHL], paths[MAXPATHL];
4251 		    char_u	*path, *next_path, *ptr;
4252 		    stat_T	st;
4253 
4254 		    STRCPY(paths, USER_HOME);
4255 		    next_path = paths;
4256 		    while (*next_path)
4257 		    {
4258 			for (path = next_path; *next_path && *next_path != ',';
4259 				next_path++);
4260 			if (*next_path)
4261 			    *next_path++ = NUL;
4262 			STRCPY(test, path);
4263 			STRCAT(test, "/");
4264 			STRCAT(test, dst + 1);
4265 			if (mch_stat(test, &st) == 0)
4266 			{
4267 			    var = alloc(STRLEN(test) + 1);
4268 			    STRCPY(var, test);
4269 			    mustfree = TRUE;
4270 			    break;
4271 			}
4272 		    }
4273 		}
4274 # endif /* UNIX */
4275 #else
4276 		/* cannot expand user's home directory, so don't try */
4277 		var = NULL;
4278 		tail = (char_u *)"";	/* for gcc */
4279 #endif /* UNIX || VMS */
4280 	    }
4281 
4282 #ifdef BACKSLASH_IN_FILENAME
4283 	    /* If 'shellslash' is set change backslashes to forward slashes.
4284 	     * Can't use slash_adjust(), p_ssl may be set temporarily. */
4285 	    if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL)
4286 	    {
4287 		char_u	*p = vim_strsave(var);
4288 
4289 		if (p != NULL)
4290 		{
4291 		    if (mustfree)
4292 			vim_free(var);
4293 		    var = p;
4294 		    mustfree = TRUE;
4295 		    forward_slash(var);
4296 		}
4297 	    }
4298 #endif
4299 
4300 	    /* If "var" contains white space, escape it with a backslash.
4301 	     * Required for ":e ~/tt" when $HOME includes a space. */
4302 	    if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL)
4303 	    {
4304 		char_u	*p = vim_strsave_escaped(var, (char_u *)" \t");
4305 
4306 		if (p != NULL)
4307 		{
4308 		    if (mustfree)
4309 			vim_free(var);
4310 		    var = p;
4311 		    mustfree = TRUE;
4312 		}
4313 	    }
4314 
4315 	    if (var != NULL && *var != NUL
4316 		    && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
4317 	    {
4318 		STRCPY(dst, var);
4319 		dstlen -= (int)STRLEN(var);
4320 		c = (int)STRLEN(var);
4321 		/* if var[] ends in a path separator and tail[] starts
4322 		 * with it, skip a character */
4323 		if (*var != NUL && after_pathsep(dst, dst + c)
4324 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA)
4325 			&& dst[-1] != ':'
4326 #endif
4327 			&& vim_ispathsep(*tail))
4328 		    ++tail;
4329 		dst += c;
4330 		src = tail;
4331 		copy_char = FALSE;
4332 	    }
4333 	    if (mustfree)
4334 		vim_free(var);
4335 	}
4336 
4337 	if (copy_char)	    /* copy at least one char */
4338 	{
4339 	    /*
4340 	     * Recognize the start of a new name, for '~'.
4341 	     * Don't do this when "one" is TRUE, to avoid expanding "~" in
4342 	     * ":edit foo ~ foo".
4343 	     */
4344 	    at_start = FALSE;
4345 	    if (src[0] == '\\' && src[1] != NUL)
4346 	    {
4347 		*dst++ = *src++;
4348 		--dstlen;
4349 	    }
4350 	    else if ((src[0] == ' ' || src[0] == ',') && !one)
4351 		at_start = TRUE;
4352 	    if (dstlen > 0)
4353 	    {
4354 		*dst++ = *src++;
4355 		--dstlen;
4356 
4357 		if (startstr != NULL && src - startstr_len >= srcp
4358 			&& STRNCMP(src - startstr_len, startstr,
4359 							    startstr_len) == 0)
4360 		    at_start = TRUE;
4361 	    }
4362 	}
4363 
4364     }
4365     *dst = NUL;
4366 }
4367 
4368 /*
4369  * Vim's version of getenv().
4370  * Special handling of $HOME, $VIM and $VIMRUNTIME.
4371  * Also does ACP to 'enc' conversion for Win32.
4372  * "mustfree" is set to TRUE when returned is allocated, it must be
4373  * initialized to FALSE by the caller.
4374  */
4375     char_u *
4376 vim_getenv(char_u *name, int *mustfree)
4377 {
4378     char_u	*p;
4379     char_u	*pend;
4380     int		vimruntime;
4381 
4382 #if defined(MSWIN)
4383     /* use "C:/" when $HOME is not set */
4384     if (STRCMP(name, "HOME") == 0)
4385 	return homedir;
4386 #endif
4387 
4388     p = mch_getenv(name);
4389     if (p != NULL && *p == NUL)	    /* empty is the same as not set */
4390 	p = NULL;
4391 
4392     if (p != NULL)
4393     {
4394 #if defined(FEAT_MBYTE) && defined(WIN3264)
4395 	if (enc_utf8)
4396 	{
4397 	    int	    len;
4398 	    char_u  *pp = NULL;
4399 
4400 	    /* Convert from active codepage to UTF-8.  Other conversions are
4401 	     * not done, because they would fail for non-ASCII characters. */
4402 	    acp_to_enc(p, (int)STRLEN(p), &pp, &len);
4403 	    if (pp != NULL)
4404 	    {
4405 		p = pp;
4406 		*mustfree = TRUE;
4407 	    }
4408 	}
4409 #endif
4410 	return p;
4411     }
4412 
4413     vimruntime = (STRCMP(name, "VIMRUNTIME") == 0);
4414     if (!vimruntime && STRCMP(name, "VIM") != 0)
4415 	return NULL;
4416 
4417     /*
4418      * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM.
4419      * Don't do this when default_vimruntime_dir is non-empty.
4420      */
4421     if (vimruntime
4422 #ifdef HAVE_PATHDEF
4423 	    && *default_vimruntime_dir == NUL
4424 #endif
4425        )
4426     {
4427 	p = mch_getenv((char_u *)"VIM");
4428 	if (p != NULL && *p == NUL)	    /* empty is the same as not set */
4429 	    p = NULL;
4430 	if (p != NULL)
4431 	{
4432 	    p = vim_version_dir(p);
4433 	    if (p != NULL)
4434 		*mustfree = TRUE;
4435 	    else
4436 		p = mch_getenv((char_u *)"VIM");
4437 
4438 #if defined(FEAT_MBYTE) && defined(WIN3264)
4439 	    if (enc_utf8)
4440 	    {
4441 		int	len;
4442 		char_u  *pp = NULL;
4443 
4444 		/* Convert from active codepage to UTF-8.  Other conversions
4445 		 * are not done, because they would fail for non-ASCII
4446 		 * characters. */
4447 		acp_to_enc(p, (int)STRLEN(p), &pp, &len);
4448 		if (pp != NULL)
4449 		{
4450 		    if (*mustfree)
4451 			vim_free(p);
4452 		    p = pp;
4453 		    *mustfree = TRUE;
4454 		}
4455 	    }
4456 #endif
4457 	}
4458     }
4459 
4460     /*
4461      * When expanding $VIM or $VIMRUNTIME fails, try using:
4462      * - the directory name from 'helpfile' (unless it contains '$')
4463      * - the executable name from argv[0]
4464      */
4465     if (p == NULL)
4466     {
4467 	if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL)
4468 	    p = p_hf;
4469 #ifdef USE_EXE_NAME
4470 	/*
4471 	 * Use the name of the executable, obtained from argv[0].
4472 	 */
4473 	else
4474 	    p = exe_name;
4475 #endif
4476 	if (p != NULL)
4477 	{
4478 	    /* remove the file name */
4479 	    pend = gettail(p);
4480 
4481 	    /* remove "doc/" from 'helpfile', if present */
4482 	    if (p == p_hf)
4483 		pend = remove_tail(p, pend, (char_u *)"doc");
4484 
4485 #ifdef USE_EXE_NAME
4486 # ifdef MACOS_X
4487 	    /* remove "MacOS" from exe_name and add "Resources/vim" */
4488 	    if (p == exe_name)
4489 	    {
4490 		char_u	*pend1;
4491 		char_u	*pnew;
4492 
4493 		pend1 = remove_tail(p, pend, (char_u *)"MacOS");
4494 		if (pend1 != pend)
4495 		{
4496 		    pnew = alloc((unsigned)(pend1 - p) + 15);
4497 		    if (pnew != NULL)
4498 		    {
4499 			STRNCPY(pnew, p, (pend1 - p));
4500 			STRCPY(pnew + (pend1 - p), "Resources/vim");
4501 			p = pnew;
4502 			pend = p + STRLEN(p);
4503 		    }
4504 		}
4505 	    }
4506 # endif
4507 	    /* remove "src/" from exe_name, if present */
4508 	    if (p == exe_name)
4509 		pend = remove_tail(p, pend, (char_u *)"src");
4510 #endif
4511 
4512 	    /* for $VIM, remove "runtime/" or "vim54/", if present */
4513 	    if (!vimruntime)
4514 	    {
4515 		pend = remove_tail(p, pend, (char_u *)RUNTIME_DIRNAME);
4516 		pend = remove_tail(p, pend, (char_u *)VIM_VERSION_NODOT);
4517 	    }
4518 
4519 	    /* remove trailing path separator */
4520 	    if (pend > p && after_pathsep(p, pend))
4521 		--pend;
4522 
4523 #ifdef MACOS_X
4524 	    if (p == exe_name || p == p_hf)
4525 #endif
4526 		/* check that the result is a directory name */
4527 		p = vim_strnsave(p, (int)(pend - p));
4528 
4529 	    if (p != NULL && !mch_isdir(p))
4530 		VIM_CLEAR(p);
4531 	    else
4532 	    {
4533 #ifdef USE_EXE_NAME
4534 		/* may add "/vim54" or "/runtime" if it exists */
4535 		if (vimruntime && (pend = vim_version_dir(p)) != NULL)
4536 		{
4537 		    vim_free(p);
4538 		    p = pend;
4539 		}
4540 #endif
4541 		*mustfree = TRUE;
4542 	    }
4543 	}
4544     }
4545 
4546 #ifdef HAVE_PATHDEF
4547     /* When there is a pathdef.c file we can use default_vim_dir and
4548      * default_vimruntime_dir */
4549     if (p == NULL)
4550     {
4551 	/* Only use default_vimruntime_dir when it is not empty */
4552 	if (vimruntime && *default_vimruntime_dir != NUL)
4553 	{
4554 	    p = default_vimruntime_dir;
4555 	    *mustfree = FALSE;
4556 	}
4557 	else if (*default_vim_dir != NUL)
4558 	{
4559 	    if (vimruntime && (p = vim_version_dir(default_vim_dir)) != NULL)
4560 		*mustfree = TRUE;
4561 	    else
4562 	    {
4563 		p = default_vim_dir;
4564 		*mustfree = FALSE;
4565 	    }
4566 	}
4567     }
4568 #endif
4569 
4570     /*
4571      * Set the environment variable, so that the new value can be found fast
4572      * next time, and others can also use it (e.g. Perl).
4573      */
4574     if (p != NULL)
4575     {
4576 	if (vimruntime)
4577 	{
4578 	    vim_setenv((char_u *)"VIMRUNTIME", p);
4579 	    didset_vimruntime = TRUE;
4580 	}
4581 	else
4582 	{
4583 	    vim_setenv((char_u *)"VIM", p);
4584 	    didset_vim = TRUE;
4585 	}
4586     }
4587     return p;
4588 }
4589 
4590 /*
4591  * Check if the directory "vimdir/<version>" or "vimdir/runtime" exists.
4592  * Return NULL if not, return its name in allocated memory otherwise.
4593  */
4594     static char_u *
4595 vim_version_dir(char_u *vimdir)
4596 {
4597     char_u	*p;
4598 
4599     if (vimdir == NULL || *vimdir == NUL)
4600 	return NULL;
4601     p = concat_fnames(vimdir, (char_u *)VIM_VERSION_NODOT, TRUE);
4602     if (p != NULL && mch_isdir(p))
4603 	return p;
4604     vim_free(p);
4605     p = concat_fnames(vimdir, (char_u *)RUNTIME_DIRNAME, TRUE);
4606     if (p != NULL && mch_isdir(p))
4607 	return p;
4608     vim_free(p);
4609     return NULL;
4610 }
4611 
4612 /*
4613  * If the string between "p" and "pend" ends in "name/", return "pend" minus
4614  * the length of "name/".  Otherwise return "pend".
4615  */
4616     static char_u *
4617 remove_tail(char_u *p, char_u *pend, char_u *name)
4618 {
4619     int		len = (int)STRLEN(name) + 1;
4620     char_u	*newend = pend - len;
4621 
4622     if (newend >= p
4623 	    && fnamencmp(newend, name, len - 1) == 0
4624 	    && (newend == p || after_pathsep(p, newend)))
4625 	return newend;
4626     return pend;
4627 }
4628 
4629     void
4630 vim_unsetenv(char_u *var)
4631 {
4632 #ifdef HAVE_UNSETENV
4633     unsetenv((char *)var);
4634 #else
4635     vim_setenv(var, (char_u *)"");
4636 #endif
4637 }
4638 
4639 
4640 /*
4641  * Our portable version of setenv.
4642  */
4643     void
4644 vim_setenv(char_u *name, char_u *val)
4645 {
4646 #ifdef HAVE_SETENV
4647     mch_setenv((char *)name, (char *)val, 1);
4648 #else
4649     char_u	*envbuf;
4650 
4651     /*
4652      * Putenv does not copy the string, it has to remain
4653      * valid.  The allocated memory will never be freed.
4654      */
4655     envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2));
4656     if (envbuf != NULL)
4657     {
4658 	sprintf((char *)envbuf, "%s=%s", name, val);
4659 	putenv((char *)envbuf);
4660     }
4661 #endif
4662 #ifdef FEAT_GETTEXT
4663     /*
4664      * When setting $VIMRUNTIME adjust the directory to find message
4665      * translations to $VIMRUNTIME/lang.
4666      */
4667     if (*val != NUL && STRICMP(name, "VIMRUNTIME") == 0)
4668     {
4669 	char_u	*buf = concat_str(val, (char_u *)"/lang");
4670 
4671 	if (buf != NULL)
4672 	{
4673 	    bindtextdomain(VIMPACKAGE, (char *)buf);
4674 	    vim_free(buf);
4675 	}
4676     }
4677 #endif
4678 }
4679 
4680 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4681 /*
4682  * Function given to ExpandGeneric() to obtain an environment variable name.
4683  */
4684     char_u *
4685 get_env_name(
4686     expand_T	*xp UNUSED,
4687     int		idx)
4688 {
4689 # if defined(AMIGA)
4690     /*
4691      * No environ[] on the Amiga.
4692      */
4693     return NULL;
4694 # else
4695 # ifndef __WIN32__
4696     /* Borland C++ 5.2 has this in a header file. */
4697     extern char		**environ;
4698 # endif
4699 # define ENVNAMELEN 100
4700     static char_u	name[ENVNAMELEN];
4701     char_u		*str;
4702     int			n;
4703 
4704     str = (char_u *)environ[idx];
4705     if (str == NULL)
4706 	return NULL;
4707 
4708     for (n = 0; n < ENVNAMELEN - 1; ++n)
4709     {
4710 	if (str[n] == '=' || str[n] == NUL)
4711 	    break;
4712 	name[n] = str[n];
4713     }
4714     name[n] = NUL;
4715     return name;
4716 # endif
4717 }
4718 
4719 /*
4720  * Find all user names for user completion.
4721  * Done only once and then cached.
4722  */
4723     static void
4724 init_users(void)
4725 {
4726     static int	lazy_init_done = FALSE;
4727 
4728     if (lazy_init_done)
4729 	return;
4730 
4731     lazy_init_done = TRUE;
4732     ga_init2(&ga_users, sizeof(char_u *), 20);
4733 
4734 # if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H)
4735     {
4736 	char_u*		user;
4737 	struct passwd*	pw;
4738 
4739 	setpwent();
4740 	while ((pw = getpwent()) != NULL)
4741 	    /* pw->pw_name shouldn't be NULL but just in case... */
4742 	    if (pw->pw_name != NULL)
4743 	    {
4744 		if (ga_grow(&ga_users, 1) == FAIL)
4745 		    break;
4746 		user = vim_strsave((char_u*)pw->pw_name);
4747 		if (user == NULL)
4748 		    break;
4749 		((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user;
4750 	    }
4751 	endpwent();
4752     }
4753 # elif defined(WIN3264)
4754     {
4755 	char_u*		user;
4756 	DWORD		nusers = 0, ntotal = 0, i;
4757 	PUSER_INFO_0	uinfo;
4758 
4759 	if (NetUserEnum(NULL, 0, 0, (LPBYTE *) &uinfo, MAX_PREFERRED_LENGTH,
4760 				       &nusers, &ntotal, NULL) == NERR_Success)
4761 	{
4762 	    for (i = 0; i < nusers; i++)
4763 	    {
4764 		if (ga_grow(&ga_users, 1) == FAIL)
4765 		    break;
4766 		user = utf16_to_enc(uinfo[i].usri0_name, NULL);
4767 		if (user == NULL)
4768 		    break;
4769 		((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user;
4770 	    }
4771 
4772 	    NetApiBufferFree(uinfo);
4773 	}
4774     }
4775 # endif
4776 }
4777 
4778 /*
4779  * Function given to ExpandGeneric() to obtain an user names.
4780  */
4781     char_u*
4782 get_users(expand_T *xp UNUSED, int idx)
4783 {
4784     init_users();
4785     if (idx < ga_users.ga_len)
4786 	return ((char_u **)ga_users.ga_data)[idx];
4787     return NULL;
4788 }
4789 
4790 /*
4791  * Check whether name matches a user name. Return:
4792  * 0 if name does not match any user name.
4793  * 1 if name partially matches the beginning of a user name.
4794  * 2 is name fully matches a user name.
4795  */
4796     int
4797 match_user(char_u *name)
4798 {
4799     int i;
4800     int n = (int)STRLEN(name);
4801     int result = 0;
4802 
4803     init_users();
4804     for (i = 0; i < ga_users.ga_len; i++)
4805     {
4806 	if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0)
4807 	    return 2; /* full match */
4808 	if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0)
4809 	    result = 1; /* partial match */
4810     }
4811     return result;
4812 }
4813 #endif
4814 
4815 /*
4816  * Replace home directory by "~" in each space or comma separated file name in
4817  * 'src'.
4818  * If anything fails (except when out of space) dst equals src.
4819  */
4820     void
4821 home_replace(
4822     buf_T	*buf,	/* when not NULL, check for help files */
4823     char_u	*src,	/* input file name */
4824     char_u	*dst,	/* where to put the result */
4825     int		dstlen,	/* maximum length of the result */
4826     int		one)	/* if TRUE, only replace one file name, include
4827 			   spaces and commas in the file name. */
4828 {
4829     size_t	dirlen = 0, envlen = 0;
4830     size_t	len;
4831     char_u	*homedir_env, *homedir_env_orig;
4832     char_u	*p;
4833 
4834     if (src == NULL)
4835     {
4836 	*dst = NUL;
4837 	return;
4838     }
4839 
4840     /*
4841      * If the file is a help file, remove the path completely.
4842      */
4843     if (buf != NULL && buf->b_help)
4844     {
4845 	vim_snprintf((char *)dst, dstlen, "%s", gettail(src));
4846 	return;
4847     }
4848 
4849     /*
4850      * We check both the value of the $HOME environment variable and the
4851      * "real" home directory.
4852      */
4853     if (homedir != NULL)
4854 	dirlen = STRLEN(homedir);
4855 
4856 #ifdef VMS
4857     homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN");
4858 #else
4859     homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME");
4860 #endif
4861 #ifdef WIN3264
4862     if (homedir_env == NULL)
4863 	homedir_env_orig = homedir_env = mch_getenv((char_u *)"USERPROFILE");
4864 #endif
4865     /* Empty is the same as not set. */
4866     if (homedir_env != NULL && *homedir_env == NUL)
4867 	homedir_env = NULL;
4868 
4869 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL)
4870     if (homedir_env != NULL && vim_strchr(homedir_env, '~') != NULL)
4871     {
4872 	int	usedlen = 0;
4873 	int	flen;
4874 	char_u	*fbuf = NULL;
4875 
4876 	flen = (int)STRLEN(homedir_env);
4877 	(void)modify_fname((char_u *)":p", FALSE, &usedlen,
4878 						  &homedir_env, &fbuf, &flen);
4879 	flen = (int)STRLEN(homedir_env);
4880 	if (flen > 0 && vim_ispathsep(homedir_env[flen - 1]))
4881 	    /* Remove the trailing / that is added to a directory. */
4882 	    homedir_env[flen - 1] = NUL;
4883     }
4884 #endif
4885 
4886     if (homedir_env != NULL)
4887 	envlen = STRLEN(homedir_env);
4888 
4889     if (!one)
4890 	src = skipwhite(src);
4891     while (*src && dstlen > 0)
4892     {
4893 	/*
4894 	 * Here we are at the beginning of a file name.
4895 	 * First, check to see if the beginning of the file name matches
4896 	 * $HOME or the "real" home directory. Check that there is a '/'
4897 	 * after the match (so that if e.g. the file is "/home/pieter/bla",
4898 	 * and the home directory is "/home/piet", the file does not end up
4899 	 * as "~er/bla" (which would seem to indicate the file "bla" in user
4900 	 * er's home directory)).
4901 	 */
4902 	p = homedir;
4903 	len = dirlen;
4904 	for (;;)
4905 	{
4906 	    if (   len
4907 		&& fnamencmp(src, p, len) == 0
4908 		&& (vim_ispathsep(src[len])
4909 		    || (!one && (src[len] == ',' || src[len] == ' '))
4910 		    || src[len] == NUL))
4911 	    {
4912 		src += len;
4913 		if (--dstlen > 0)
4914 		    *dst++ = '~';
4915 
4916 		/*
4917 		 * If it's just the home directory, add  "/".
4918 		 */
4919 		if (!vim_ispathsep(src[0]) && --dstlen > 0)
4920 		    *dst++ = '/';
4921 		break;
4922 	    }
4923 	    if (p == homedir_env)
4924 		break;
4925 	    p = homedir_env;
4926 	    len = envlen;
4927 	}
4928 
4929 	/* if (!one) skip to separator: space or comma */
4930 	while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
4931 	    *dst++ = *src++;
4932 	/* skip separator */
4933 	while ((*src == ' ' || *src == ',') && --dstlen > 0)
4934 	    *dst++ = *src++;
4935     }
4936     /* if (dstlen == 0) out of space, what to do??? */
4937 
4938     *dst = NUL;
4939 
4940     if (homedir_env != homedir_env_orig)
4941 	vim_free(homedir_env);
4942 }
4943 
4944 /*
4945  * Like home_replace, store the replaced string in allocated memory.
4946  * When something fails, NULL is returned.
4947  */
4948     char_u  *
4949 home_replace_save(
4950     buf_T	*buf,	/* when not NULL, check for help files */
4951     char_u	*src)	/* input file name */
4952 {
4953     char_u	*dst;
4954     unsigned	len;
4955 
4956     len = 3;			/* space for "~/" and trailing NUL */
4957     if (src != NULL)		/* just in case */
4958 	len += (unsigned)STRLEN(src);
4959     dst = alloc(len);
4960     if (dst != NULL)
4961 	home_replace(buf, src, dst, len, TRUE);
4962     return dst;
4963 }
4964 
4965 /*
4966  * Compare two file names and return:
4967  * FPC_SAME   if they both exist and are the same file.
4968  * FPC_SAMEX  if they both don't exist and have the same file name.
4969  * FPC_DIFF   if they both exist and are different files.
4970  * FPC_NOTX   if they both don't exist.
4971  * FPC_DIFFX  if one of them doesn't exist.
4972  * For the first name environment variables are expanded
4973  */
4974     int
4975 fullpathcmp(
4976     char_u *s1,
4977     char_u *s2,
4978     int	    checkname)		/* when both don't exist, check file names */
4979 {
4980 #ifdef UNIX
4981     char_u	    exp1[MAXPATHL];
4982     char_u	    full1[MAXPATHL];
4983     char_u	    full2[MAXPATHL];
4984     stat_T	    st1, st2;
4985     int		    r1, r2;
4986 
4987     expand_env(s1, exp1, MAXPATHL);
4988     r1 = mch_stat((char *)exp1, &st1);
4989     r2 = mch_stat((char *)s2, &st2);
4990     if (r1 != 0 && r2 != 0)
4991     {
4992 	/* if mch_stat() doesn't work, may compare the names */
4993 	if (checkname)
4994 	{
4995 	    if (fnamecmp(exp1, s2) == 0)
4996 		return FPC_SAMEX;
4997 	    r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
4998 	    r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
4999 	    if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
5000 		return FPC_SAMEX;
5001 	}
5002 	return FPC_NOTX;
5003     }
5004     if (r1 != 0 || r2 != 0)
5005 	return FPC_DIFFX;
5006     if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
5007 	return FPC_SAME;
5008     return FPC_DIFF;
5009 #else
5010     char_u  *exp1;		/* expanded s1 */
5011     char_u  *full1;		/* full path of s1 */
5012     char_u  *full2;		/* full path of s2 */
5013     int	    retval = FPC_DIFF;
5014     int	    r1, r2;
5015 
5016     /* allocate one buffer to store three paths (alloc()/free() is slow!) */
5017     if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
5018     {
5019 	full1 = exp1 + MAXPATHL;
5020 	full2 = full1 + MAXPATHL;
5021 
5022 	expand_env(s1, exp1, MAXPATHL);
5023 	r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
5024 	r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
5025 
5026 	/* If vim_FullName() fails, the file probably doesn't exist. */
5027 	if (r1 != OK && r2 != OK)
5028 	{
5029 	    if (checkname && fnamecmp(exp1, s2) == 0)
5030 		retval = FPC_SAMEX;
5031 	    else
5032 		retval = FPC_NOTX;
5033 	}
5034 	else if (r1 != OK || r2 != OK)
5035 	    retval = FPC_DIFFX;
5036 	else if (fnamecmp(full1, full2))
5037 	    retval = FPC_DIFF;
5038 	else
5039 	    retval = FPC_SAME;
5040 	vim_free(exp1);
5041     }
5042     return retval;
5043 #endif
5044 }
5045 
5046 /*
5047  * Get the tail of a path: the file name.
5048  * When the path ends in a path separator the tail is the NUL after it.
5049  * Fail safe: never returns NULL.
5050  */
5051     char_u *
5052 gettail(char_u *fname)
5053 {
5054     char_u  *p1, *p2;
5055 
5056     if (fname == NULL)
5057 	return (char_u *)"";
5058     for (p1 = p2 = get_past_head(fname); *p2; )	/* find last part of path */
5059     {
5060 	if (vim_ispathsep_nocolon(*p2))
5061 	    p1 = p2 + 1;
5062 	MB_PTR_ADV(p2);
5063     }
5064     return p1;
5065 }
5066 
5067 #if defined(FEAT_SEARCHPATH)
5068 static char_u *gettail_dir(char_u *fname);
5069 
5070 /*
5071  * Return the end of the directory name, on the first path
5072  * separator:
5073  * "/path/file", "/path/dir/", "/path//dir", "/file"
5074  *	 ^	       ^	     ^	      ^
5075  */
5076     static char_u *
5077 gettail_dir(char_u *fname)
5078 {
5079     char_u	*dir_end = fname;
5080     char_u	*next_dir_end = fname;
5081     int		look_for_sep = TRUE;
5082     char_u	*p;
5083 
5084     for (p = fname; *p != NUL; )
5085     {
5086 	if (vim_ispathsep(*p))
5087 	{
5088 	    if (look_for_sep)
5089 	    {
5090 		next_dir_end = p;
5091 		look_for_sep = FALSE;
5092 	    }
5093 	}
5094 	else
5095 	{
5096 	    if (!look_for_sep)
5097 		dir_end = next_dir_end;
5098 	    look_for_sep = TRUE;
5099 	}
5100 	MB_PTR_ADV(p);
5101     }
5102     return dir_end;
5103 }
5104 #endif
5105 
5106 /*
5107  * Get pointer to tail of "fname", including path separators.  Putting a NUL
5108  * here leaves the directory name.  Takes care of "c:/" and "//".
5109  * Always returns a valid pointer.
5110  */
5111     char_u *
5112 gettail_sep(char_u *fname)
5113 {
5114     char_u	*p;
5115     char_u	*t;
5116 
5117     p = get_past_head(fname);	/* don't remove the '/' from "c:/file" */
5118     t = gettail(fname);
5119     while (t > p && after_pathsep(fname, t))
5120 	--t;
5121 #ifdef VMS
5122     /* path separator is part of the path */
5123     ++t;
5124 #endif
5125     return t;
5126 }
5127 
5128 /*
5129  * get the next path component (just after the next path separator).
5130  */
5131     char_u *
5132 getnextcomp(char_u *fname)
5133 {
5134     while (*fname && !vim_ispathsep(*fname))
5135 	MB_PTR_ADV(fname);
5136     if (*fname)
5137 	++fname;
5138     return fname;
5139 }
5140 
5141 /*
5142  * Get a pointer to one character past the head of a path name.
5143  * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
5144  * If there is no head, path is returned.
5145  */
5146     char_u *
5147 get_past_head(char_u *path)
5148 {
5149     char_u  *retval;
5150 
5151 #if defined(MSWIN)
5152     /* may skip "c:" */
5153     if (isalpha(path[0]) && path[1] == ':')
5154 	retval = path + 2;
5155     else
5156 	retval = path;
5157 #else
5158 # if defined(AMIGA)
5159     /* may skip "label:" */
5160     retval = vim_strchr(path, ':');
5161     if (retval == NULL)
5162 	retval = path;
5163 # else	/* Unix */
5164     retval = path;
5165 # endif
5166 #endif
5167 
5168     while (vim_ispathsep(*retval))
5169 	++retval;
5170 
5171     return retval;
5172 }
5173 
5174 /*
5175  * Return TRUE if 'c' is a path separator.
5176  * Note that for MS-Windows this includes the colon.
5177  */
5178     int
5179 vim_ispathsep(int c)
5180 {
5181 #ifdef UNIX
5182     return (c == '/');	    /* UNIX has ':' inside file names */
5183 #else
5184 # ifdef BACKSLASH_IN_FILENAME
5185     return (c == ':' || c == '/' || c == '\\');
5186 # else
5187 #  ifdef VMS
5188     /* server"user passwd"::device:[full.path.name]fname.extension;version" */
5189     return (c == ':' || c == '[' || c == ']' || c == '/'
5190 	    || c == '<' || c == '>' || c == '"' );
5191 #  else
5192     return (c == ':' || c == '/');
5193 #  endif /* VMS */
5194 # endif
5195 #endif
5196 }
5197 
5198 /*
5199  * Like vim_ispathsep(c), but exclude the colon for MS-Windows.
5200  */
5201     int
5202 vim_ispathsep_nocolon(int c)
5203 {
5204     return vim_ispathsep(c)
5205 #ifdef BACKSLASH_IN_FILENAME
5206 	&& c != ':'
5207 #endif
5208 	;
5209 }
5210 
5211 #if defined(FEAT_SEARCHPATH) || defined(PROTO)
5212 /*
5213  * return TRUE if 'c' is a path list separator.
5214  */
5215     int
5216 vim_ispathlistsep(int c)
5217 {
5218 #ifdef UNIX
5219     return (c == ':');
5220 #else
5221     return (c == ';');	/* might not be right for every system... */
5222 #endif
5223 }
5224 #endif
5225 
5226 /*
5227  * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname"
5228  * It's done in-place.
5229  */
5230     void
5231 shorten_dir(char_u *str)
5232 {
5233     char_u	*tail, *s, *d;
5234     int		skip = FALSE;
5235 
5236     tail = gettail(str);
5237     d = str;
5238     for (s = str; ; ++s)
5239     {
5240 	if (s >= tail)		    /* copy the whole tail */
5241 	{
5242 	    *d++ = *s;
5243 	    if (*s == NUL)
5244 		break;
5245 	}
5246 	else if (vim_ispathsep(*s))	    /* copy '/' and next char */
5247 	{
5248 	    *d++ = *s;
5249 	    skip = FALSE;
5250 	}
5251 	else if (!skip)
5252 	{
5253 	    *d++ = *s;		    /* copy next char */
5254 	    if (*s != '~' && *s != '.') /* and leading "~" and "." */
5255 		skip = TRUE;
5256 # ifdef FEAT_MBYTE
5257 	    if (has_mbyte)
5258 	    {
5259 		int l = mb_ptr2len(s);
5260 
5261 		while (--l > 0)
5262 		    *d++ = *++s;
5263 	    }
5264 # endif
5265 	}
5266     }
5267 }
5268 
5269 /*
5270  * Return TRUE if the directory of "fname" exists, FALSE otherwise.
5271  * Also returns TRUE if there is no directory name.
5272  * "fname" must be writable!.
5273  */
5274     int
5275 dir_of_file_exists(char_u *fname)
5276 {
5277     char_u	*p;
5278     int		c;
5279     int		retval;
5280 
5281     p = gettail_sep(fname);
5282     if (p == fname)
5283 	return TRUE;
5284     c = *p;
5285     *p = NUL;
5286     retval = mch_isdir(fname);
5287     *p = c;
5288     return retval;
5289 }
5290 
5291 /*
5292  * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally
5293  * and deal with 'fileignorecase'.
5294  */
5295     int
5296 vim_fnamecmp(char_u *x, char_u *y)
5297 {
5298 #ifdef BACKSLASH_IN_FILENAME
5299     return vim_fnamencmp(x, y, MAXPATHL);
5300 #else
5301     if (p_fic)
5302 	return MB_STRICMP(x, y);
5303     return STRCMP(x, y);
5304 #endif
5305 }
5306 
5307     int
5308 vim_fnamencmp(char_u *x, char_u *y, size_t len)
5309 {
5310 #ifdef BACKSLASH_IN_FILENAME
5311     char_u	*px = x;
5312     char_u	*py = y;
5313     int		cx = NUL;
5314     int		cy = NUL;
5315 
5316     while (len > 0)
5317     {
5318 	cx = PTR2CHAR(px);
5319 	cy = PTR2CHAR(py);
5320 	if (cx == NUL || cy == NUL
5321 	    || ((p_fic ? MB_TOLOWER(cx) != MB_TOLOWER(cy) : cx != cy)
5322 		&& !(cx == '/' && cy == '\\')
5323 		&& !(cx == '\\' && cy == '/')))
5324 	    break;
5325 	len -= MB_PTR2LEN(px);
5326 	px += MB_PTR2LEN(px);
5327 	py += MB_PTR2LEN(py);
5328     }
5329     if (len == 0)
5330 	return 0;
5331     return (cx - cy);
5332 #else
5333     if (p_fic)
5334 	return MB_STRNICMP(x, y, len);
5335     return STRNCMP(x, y, len);
5336 #endif
5337 }
5338 
5339 /*
5340  * Concatenate file names fname1 and fname2 into allocated memory.
5341  * Only add a '/' or '\\' when 'sep' is TRUE and it is necessary.
5342  */
5343     char_u  *
5344 concat_fnames(char_u *fname1, char_u *fname2, int sep)
5345 {
5346     char_u  *dest;
5347 
5348     dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3));
5349     if (dest != NULL)
5350     {
5351 	STRCPY(dest, fname1);
5352 	if (sep)
5353 	    add_pathsep(dest);
5354 	STRCAT(dest, fname2);
5355     }
5356     return dest;
5357 }
5358 
5359 /*
5360  * Concatenate two strings and return the result in allocated memory.
5361  * Returns NULL when out of memory.
5362  */
5363     char_u  *
5364 concat_str(char_u *str1, char_u *str2)
5365 {
5366     char_u  *dest;
5367     size_t  l = STRLEN(str1);
5368 
5369     dest = alloc((unsigned)(l + STRLEN(str2) + 1L));
5370     if (dest != NULL)
5371     {
5372 	STRCPY(dest, str1);
5373 	STRCPY(dest + l, str2);
5374     }
5375     return dest;
5376 }
5377 
5378 /*
5379  * Add a path separator to a file name, unless it already ends in a path
5380  * separator.
5381  */
5382     void
5383 add_pathsep(char_u *p)
5384 {
5385     if (*p != NUL && !after_pathsep(p, p + STRLEN(p)))
5386 	STRCAT(p, PATHSEPSTR);
5387 }
5388 
5389 /*
5390  * FullName_save - Make an allocated copy of a full file name.
5391  * Returns NULL when out of memory.
5392  */
5393     char_u  *
5394 FullName_save(
5395     char_u	*fname,
5396     int		force)		/* force expansion, even when it already looks
5397 				 * like a full path name */
5398 {
5399     char_u	*buf;
5400     char_u	*new_fname = NULL;
5401 
5402     if (fname == NULL)
5403 	return NULL;
5404 
5405     buf = alloc((unsigned)MAXPATHL);
5406     if (buf != NULL)
5407     {
5408 	if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL)
5409 	    new_fname = vim_strsave(buf);
5410 	else
5411 	    new_fname = vim_strsave(fname);
5412 	vim_free(buf);
5413     }
5414     return new_fname;
5415 }
5416 
5417 #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL)
5418 
5419 static char_u	*skip_string(char_u *p);
5420 static pos_T *ind_find_start_comment(void);
5421 static pos_T *ind_find_start_CORS(linenr_T *is_raw);
5422 static pos_T *find_start_rawstring(int ind_maxcomment);
5423 
5424 /*
5425  * Find the start of a comment, not knowing if we are in a comment right now.
5426  * Search starts at w_cursor.lnum and goes backwards.
5427  * Return NULL when not inside a comment.
5428  */
5429     static pos_T *
5430 ind_find_start_comment(void)	    /* XXX */
5431 {
5432     return find_start_comment(curbuf->b_ind_maxcomment);
5433 }
5434 
5435     pos_T *
5436 find_start_comment(int ind_maxcomment)	/* XXX */
5437 {
5438     pos_T	*pos;
5439     char_u	*line;
5440     char_u	*p;
5441     int		cur_maxcomment = ind_maxcomment;
5442 
5443     for (;;)
5444     {
5445 	pos = findmatchlimit(NULL, '*', FM_BACKWARD, cur_maxcomment);
5446 	if (pos == NULL)
5447 	    break;
5448 
5449 	/*
5450 	 * Check if the comment start we found is inside a string.
5451 	 * If it is then restrict the search to below this line and try again.
5452 	 */
5453 	line = ml_get(pos->lnum);
5454 	for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p)
5455 	    p = skip_string(p);
5456 	if ((colnr_T)(p - line) <= pos->col)
5457 	    break;
5458 	cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1;
5459 	if (cur_maxcomment <= 0)
5460 	{
5461 	    pos = NULL;
5462 	    break;
5463 	}
5464     }
5465     return pos;
5466 }
5467 
5468 /*
5469  * Find the start of a comment or raw string, not knowing if we are in a
5470  * comment or raw string right now.
5471  * Search starts at w_cursor.lnum and goes backwards.
5472  * If is_raw is given and returns start of raw_string, sets it to true.
5473  * Return NULL when not inside a comment or raw string.
5474  * "CORS" -> Comment Or Raw String
5475  */
5476     static pos_T *
5477 ind_find_start_CORS(linenr_T *is_raw)	    /* XXX */
5478 {
5479     static pos_T comment_pos_copy;
5480     pos_T	*comment_pos;
5481     pos_T	*rs_pos;
5482 
5483     comment_pos = find_start_comment(curbuf->b_ind_maxcomment);
5484     if (comment_pos != NULL)
5485     {
5486 	/* Need to make a copy of the static pos in findmatchlimit(),
5487 	 * calling find_start_rawstring() may change it. */
5488 	comment_pos_copy = *comment_pos;
5489 	comment_pos = &comment_pos_copy;
5490     }
5491     rs_pos = find_start_rawstring(curbuf->b_ind_maxcomment);
5492 
5493     /* If comment_pos is before rs_pos the raw string is inside the comment.
5494      * If rs_pos is before comment_pos the comment is inside the raw string. */
5495     if (comment_pos == NULL || (rs_pos != NULL
5496 					     && LT_POS(*rs_pos, *comment_pos)))
5497     {
5498 	if (is_raw != NULL && rs_pos != NULL)
5499 	    *is_raw = rs_pos->lnum;
5500 	return rs_pos;
5501     }
5502     return comment_pos;
5503 }
5504 
5505 /*
5506  * Find the start of a raw string, not knowing if we are in one right now.
5507  * Search starts at w_cursor.lnum and goes backwards.
5508  * Return NULL when not inside a raw string.
5509  */
5510     static pos_T *
5511 find_start_rawstring(int ind_maxcomment)	/* XXX */
5512 {
5513     pos_T	*pos;
5514     char_u	*line;
5515     char_u	*p;
5516     int		cur_maxcomment = ind_maxcomment;
5517 
5518     for (;;)
5519     {
5520 	pos = findmatchlimit(NULL, 'R', FM_BACKWARD, cur_maxcomment);
5521 	if (pos == NULL)
5522 	    break;
5523 
5524 	/*
5525 	 * Check if the raw string start we found is inside a string.
5526 	 * If it is then restrict the search to below this line and try again.
5527 	 */
5528 	line = ml_get(pos->lnum);
5529 	for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p)
5530 	    p = skip_string(p);
5531 	if ((colnr_T)(p - line) <= pos->col)
5532 	    break;
5533 	cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1;
5534 	if (cur_maxcomment <= 0)
5535 	{
5536 	    pos = NULL;
5537 	    break;
5538 	}
5539     }
5540     return pos;
5541 }
5542 
5543 /*
5544  * Skip to the end of a "string" and a 'c' character.
5545  * If there is no string or character, return argument unmodified.
5546  */
5547     static char_u *
5548 skip_string(char_u *p)
5549 {
5550     int	    i;
5551 
5552     /*
5553      * We loop, because strings may be concatenated: "date""time".
5554      */
5555     for ( ; ; ++p)
5556     {
5557 	if (p[0] == '\'')		    /* 'c' or '\n' or '\000' */
5558 	{
5559 	    if (!p[1])			    /* ' at end of line */
5560 		break;
5561 	    i = 2;
5562 	    if (p[1] == '\\')		    /* '\n' or '\000' */
5563 	    {
5564 		++i;
5565 		while (vim_isdigit(p[i - 1]))   /* '\000' */
5566 		    ++i;
5567 	    }
5568 	    if (p[i] == '\'')		    /* check for trailing ' */
5569 	    {
5570 		p += i;
5571 		continue;
5572 	    }
5573 	}
5574 	else if (p[0] == '"')		    /* start of string */
5575 	{
5576 	    for (++p; p[0]; ++p)
5577 	    {
5578 		if (p[0] == '\\' && p[1] != NUL)
5579 		    ++p;
5580 		else if (p[0] == '"')	    /* end of string */
5581 		    break;
5582 	    }
5583 	    if (p[0] == '"')
5584 		continue; /* continue for another string */
5585 	}
5586 	else if (p[0] == 'R' && p[1] == '"')
5587 	{
5588 	    /* Raw string: R"[delim](...)[delim]" */
5589 	    char_u *delim = p + 2;
5590 	    char_u *paren = vim_strchr(delim, '(');
5591 
5592 	    if (paren != NULL)
5593 	    {
5594 		size_t delim_len = paren - delim;
5595 
5596 		for (p += 3; *p; ++p)
5597 		    if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
5598 			    && p[delim_len + 1] == '"')
5599 		    {
5600 			p += delim_len + 1;
5601 			break;
5602 		    }
5603 		if (p[0] == '"')
5604 		    continue; /* continue for another string */
5605 	    }
5606 	}
5607 	break;				    /* no string found */
5608     }
5609     if (!*p)
5610 	--p;				    /* backup from NUL */
5611     return p;
5612 }
5613 #endif /* FEAT_CINDENT || FEAT_SYN_HL */
5614 
5615 #if defined(FEAT_CINDENT) || defined(PROTO)
5616 
5617 /*
5618  * Do C or expression indenting on the current line.
5619  */
5620     void
5621 do_c_expr_indent(void)
5622 {
5623 # ifdef FEAT_EVAL
5624     if (*curbuf->b_p_inde != NUL)
5625 	fixthisline(get_expr_indent);
5626     else
5627 # endif
5628 	fixthisline(get_c_indent);
5629 }
5630 
5631 /* Find result cache for cpp_baseclass */
5632 typedef struct {
5633     int	    found;
5634     lpos_T  lpos;
5635 } cpp_baseclass_cache_T;
5636 
5637 /*
5638  * Functions for C-indenting.
5639  * Most of this originally comes from Eric Fischer.
5640  */
5641 /*
5642  * Below "XXX" means that this function may unlock the current line.
5643  */
5644 
5645 static char_u	*cin_skipcomment(char_u *);
5646 static int	cin_nocode(char_u *);
5647 static pos_T	*find_line_comment(void);
5648 static int	cin_has_js_key(char_u *text);
5649 static int	cin_islabel_skip(char_u **);
5650 static int	cin_isdefault(char_u *);
5651 static char_u	*after_label(char_u *l);
5652 static int	get_indent_nolabel(linenr_T lnum);
5653 static int	skip_label(linenr_T, char_u **pp);
5654 static int	cin_first_id_amount(void);
5655 static int	cin_get_equal_amount(linenr_T lnum);
5656 static int	cin_ispreproc(char_u *);
5657 static int	cin_iscomment(char_u *);
5658 static int	cin_islinecomment(char_u *);
5659 static int	cin_isterminated(char_u *, int, int);
5660 static int	cin_isinit(void);
5661 static int	cin_isfuncdecl(char_u **, linenr_T, linenr_T);
5662 static int	cin_isif(char_u *);
5663 static int	cin_iselse(char_u *);
5664 static int	cin_isdo(char_u *);
5665 static int	cin_iswhileofdo(char_u *, linenr_T);
5666 static int	cin_is_if_for_while_before_offset(char_u *line, int *poffset);
5667 static int	cin_iswhileofdo_end(int terminated);
5668 static int	cin_isbreak(char_u *);
5669 static int	cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached);
5670 static int	get_baseclass_amount(int col);
5671 static int	cin_ends_in(char_u *, char_u *, char_u *);
5672 static int	cin_starts_with(char_u *s, char *word);
5673 static int	cin_skip2pos(pos_T *trypos);
5674 static pos_T	*find_start_brace(void);
5675 static pos_T	*find_match_paren(int);
5676 static pos_T	*find_match_char(int c, int ind_maxparen);
5677 static int	corr_ind_maxparen(pos_T *startpos);
5678 static int	find_last_paren(char_u *l, int start, int end);
5679 static int	find_match(int lookfor, linenr_T ourscope);
5680 static int	cin_is_cpp_namespace(char_u *);
5681 
5682 /*
5683  * Skip over white space and C comments within the line.
5684  * Also skip over Perl/shell comments if desired.
5685  */
5686     static char_u *
5687 cin_skipcomment(char_u *s)
5688 {
5689     while (*s)
5690     {
5691 	char_u *prev_s = s;
5692 
5693 	s = skipwhite(s);
5694 
5695 	/* Perl/shell # comment comment continues until eol.  Require a space
5696 	 * before # to avoid recognizing $#array. */
5697 	if (curbuf->b_ind_hash_comment != 0 && s != prev_s && *s == '#')
5698 	{
5699 	    s += STRLEN(s);
5700 	    break;
5701 	}
5702 	if (*s != '/')
5703 	    break;
5704 	++s;
5705 	if (*s == '/')		/* slash-slash comment continues till eol */
5706 	{
5707 	    s += STRLEN(s);
5708 	    break;
5709 	}
5710 	if (*s != '*')
5711 	    break;
5712 	for (++s; *s; ++s)	/* skip slash-star comment */
5713 	    if (s[0] == '*' && s[1] == '/')
5714 	    {
5715 		s += 2;
5716 		break;
5717 	    }
5718     }
5719     return s;
5720 }
5721 
5722 /*
5723  * Return TRUE if there is no code at *s.  White space and comments are
5724  * not considered code.
5725  */
5726     static int
5727 cin_nocode(char_u *s)
5728 {
5729     return *cin_skipcomment(s) == NUL;
5730 }
5731 
5732 /*
5733  * Check previous lines for a "//" line comment, skipping over blank lines.
5734  */
5735     static pos_T *
5736 find_line_comment(void) /* XXX */
5737 {
5738     static pos_T pos;
5739     char_u	 *line;
5740     char_u	 *p;
5741 
5742     pos = curwin->w_cursor;
5743     while (--pos.lnum > 0)
5744     {
5745 	line = ml_get(pos.lnum);
5746 	p = skipwhite(line);
5747 	if (cin_islinecomment(p))
5748 	{
5749 	    pos.col = (int)(p - line);
5750 	    return &pos;
5751 	}
5752 	if (*p != NUL)
5753 	    break;
5754     }
5755     return NULL;
5756 }
5757 
5758 /*
5759  * Return TRUE if "text" starts with "key:".
5760  */
5761     static int
5762 cin_has_js_key(char_u *text)
5763 {
5764     char_u *s = skipwhite(text);
5765     int	    quote = -1;
5766 
5767     if (*s == '\'' || *s == '"')
5768     {
5769 	/* can be 'key': or "key": */
5770 	quote = *s;
5771 	++s;
5772     }
5773     if (!vim_isIDc(*s))	    /* need at least one ID character */
5774 	return FALSE;
5775 
5776     while (vim_isIDc(*s))
5777 	++s;
5778     if (*s == quote)
5779 	++s;
5780 
5781     s = cin_skipcomment(s);
5782 
5783     /* "::" is not a label, it's C++ */
5784     return (*s == ':' && s[1] != ':');
5785 }
5786 
5787 /*
5788  * Check if string matches "label:"; move to character after ':' if true.
5789  * "*s" must point to the start of the label, if there is one.
5790  */
5791     static int
5792 cin_islabel_skip(char_u **s)
5793 {
5794     if (!vim_isIDc(**s))	    /* need at least one ID character */
5795 	return FALSE;
5796 
5797     while (vim_isIDc(**s))
5798 	(*s)++;
5799 
5800     *s = cin_skipcomment(*s);
5801 
5802     /* "::" is not a label, it's C++ */
5803     return (**s == ':' && *++*s != ':');
5804 }
5805 
5806 /*
5807  * Recognize a label: "label:".
5808  * Note: curwin->w_cursor must be where we are looking for the label.
5809  */
5810     int
5811 cin_islabel(void)		/* XXX */
5812 {
5813     char_u	*s;
5814 
5815     s = cin_skipcomment(ml_get_curline());
5816 
5817     /*
5818      * Exclude "default" from labels, since it should be indented
5819      * like a switch label.  Same for C++ scope declarations.
5820      */
5821     if (cin_isdefault(s))
5822 	return FALSE;
5823     if (cin_isscopedecl(s))
5824 	return FALSE;
5825 
5826     if (cin_islabel_skip(&s))
5827     {
5828 	/*
5829 	 * Only accept a label if the previous line is terminated or is a case
5830 	 * label.
5831 	 */
5832 	pos_T	cursor_save;
5833 	pos_T	*trypos;
5834 	char_u	*line;
5835 
5836 	cursor_save = curwin->w_cursor;
5837 	while (curwin->w_cursor.lnum > 1)
5838 	{
5839 	    --curwin->w_cursor.lnum;
5840 
5841 	    /*
5842 	     * If we're in a comment or raw string now, skip to the start of
5843 	     * it.
5844 	     */
5845 	    curwin->w_cursor.col = 0;
5846 	    if ((trypos = ind_find_start_CORS(NULL)) != NULL) /* XXX */
5847 		curwin->w_cursor = *trypos;
5848 
5849 	    line = ml_get_curline();
5850 	    if (cin_ispreproc(line))	/* ignore #defines, #if, etc. */
5851 		continue;
5852 	    if (*(line = cin_skipcomment(line)) == NUL)
5853 		continue;
5854 
5855 	    curwin->w_cursor = cursor_save;
5856 	    if (cin_isterminated(line, TRUE, FALSE)
5857 		    || cin_isscopedecl(line)
5858 		    || cin_iscase(line, TRUE)
5859 		    || (cin_islabel_skip(&line) && cin_nocode(line)))
5860 		return TRUE;
5861 	    return FALSE;
5862 	}
5863 	curwin->w_cursor = cursor_save;
5864 	return TRUE;		/* label at start of file??? */
5865     }
5866     return FALSE;
5867 }
5868 
5869 /*
5870  * Recognize structure initialization and enumerations:
5871  * "[typedef] [static|public|protected|private] enum"
5872  * "[typedef] [static|public|protected|private] = {"
5873  */
5874     static int
5875 cin_isinit(void)
5876 {
5877     char_u	*s;
5878     static char *skip[] = {"static", "public", "protected", "private"};
5879 
5880     s = cin_skipcomment(ml_get_curline());
5881 
5882     if (cin_starts_with(s, "typedef"))
5883 	s = cin_skipcomment(s + 7);
5884 
5885     for (;;)
5886     {
5887 	int i, l;
5888 
5889 	for (i = 0; i < (int)(sizeof(skip) / sizeof(char *)); ++i)
5890 	{
5891 	    l = (int)strlen(skip[i]);
5892 	    if (cin_starts_with(s, skip[i]))
5893 	    {
5894 		s = cin_skipcomment(s + l);
5895 		l = 0;
5896 		break;
5897 	    }
5898 	}
5899 	if (l != 0)
5900 	    break;
5901     }
5902 
5903     if (cin_starts_with(s, "enum"))
5904 	return TRUE;
5905 
5906     if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
5907 	return TRUE;
5908 
5909     return FALSE;
5910 }
5911 
5912 /*
5913  * Recognize a switch label: "case .*:" or "default:".
5914  */
5915      int
5916 cin_iscase(
5917     char_u *s,
5918     int strict) /* Allow relaxed check of case statement for JS */
5919 {
5920     s = cin_skipcomment(s);
5921     if (cin_starts_with(s, "case"))
5922     {
5923 	for (s += 4; *s; ++s)
5924 	{
5925 	    s = cin_skipcomment(s);
5926 	    if (*s == ':')
5927 	    {
5928 		if (s[1] == ':')	/* skip over "::" for C++ */
5929 		    ++s;
5930 		else
5931 		    return TRUE;
5932 	    }
5933 	    if (*s == '\'' && s[1] && s[2] == '\'')
5934 		s += 2;			/* skip over ':' */
5935 	    else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
5936 		return FALSE;		/* stop at comment */
5937 	    else if (*s == '"')
5938 	    {
5939 		/* JS etc. */
5940 		if (strict)
5941 		    return FALSE;		/* stop at string */
5942 		else
5943 		    return TRUE;
5944 	    }
5945 	}
5946 	return FALSE;
5947     }
5948 
5949     if (cin_isdefault(s))
5950 	return TRUE;
5951     return FALSE;
5952 }
5953 
5954 /*
5955  * Recognize a "default" switch label.
5956  */
5957     static int
5958 cin_isdefault(char_u *s)
5959 {
5960     return (STRNCMP(s, "default", 7) == 0
5961 	    && *(s = cin_skipcomment(s + 7)) == ':'
5962 	    && s[1] != ':');
5963 }
5964 
5965 /*
5966  * Recognize a "public/private/protected" scope declaration label.
5967  */
5968     int
5969 cin_isscopedecl(char_u *s)
5970 {
5971     int		i;
5972 
5973     s = cin_skipcomment(s);
5974     if (STRNCMP(s, "public", 6) == 0)
5975 	i = 6;
5976     else if (STRNCMP(s, "protected", 9) == 0)
5977 	i = 9;
5978     else if (STRNCMP(s, "private", 7) == 0)
5979 	i = 7;
5980     else
5981 	return FALSE;
5982     return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
5983 }
5984 
5985 /* Maximum number of lines to search back for a "namespace" line. */
5986 #define FIND_NAMESPACE_LIM 20
5987 
5988 /*
5989  * Recognize a "namespace" scope declaration.
5990  */
5991     static int
5992 cin_is_cpp_namespace(char_u *s)
5993 {
5994     char_u	*p;
5995     int		has_name = FALSE;
5996     int		has_name_start = FALSE;
5997 
5998     s = cin_skipcomment(s);
5999     if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9])))
6000     {
6001 	p = cin_skipcomment(skipwhite(s + 9));
6002 	while (*p != NUL)
6003 	{
6004 	    if (VIM_ISWHITE(*p))
6005 	    {
6006 		has_name = TRUE; /* found end of a name */
6007 		p = cin_skipcomment(skipwhite(p));
6008 	    }
6009 	    else if (*p == '{')
6010 	    {
6011 		break;
6012 	    }
6013 	    else if (vim_iswordc(*p))
6014 	    {
6015 		has_name_start = TRUE;
6016 		if (has_name)
6017 		    return FALSE; /* word character after skipping past name */
6018 		++p;
6019 	    }
6020 	    else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2]))
6021 	    {
6022 		if (!has_name_start || has_name)
6023 		    return FALSE;
6024 		/* C++ 17 nested namespace */
6025 		p += 3;
6026 	    }
6027 	    else
6028 	    {
6029 		return FALSE;
6030 	    }
6031 	}
6032 	return TRUE;
6033     }
6034     return FALSE;
6035 }
6036 
6037 /*
6038  * Recognize a `extern "C"` or `extern "C++"` linkage specifications.
6039  */
6040     static int
6041 cin_is_cpp_extern_c(char_u *s)
6042 {
6043     char_u	*p;
6044     int		has_string_literal = FALSE;
6045 
6046     s = cin_skipcomment(s);
6047     if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6])))
6048     {
6049 	p = cin_skipcomment(skipwhite(s + 6));
6050 	while (*p != NUL)
6051 	{
6052 	    if (VIM_ISWHITE(*p))
6053 	    {
6054 		p = cin_skipcomment(skipwhite(p));
6055 	    }
6056 	    else if (*p == '{')
6057 	    {
6058 		break;
6059 	    }
6060 	    else if (p[0] == '"' && p[1] == 'C' && p[2] == '"')
6061 	    {
6062 		if (has_string_literal)
6063 		    return FALSE;
6064 		has_string_literal = TRUE;
6065 		p += 3;
6066 	    }
6067 	    else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+'
6068 		    && p[4] == '"')
6069 	    {
6070 		if (has_string_literal)
6071 		    return FALSE;
6072 		has_string_literal = TRUE;
6073 		p += 5;
6074 	    }
6075 	    else
6076 	    {
6077 		return FALSE;
6078 	    }
6079 	}
6080 	return has_string_literal ? TRUE : FALSE;
6081     }
6082     return FALSE;
6083 }
6084 
6085 /*
6086  * Return a pointer to the first non-empty non-comment character after a ':'.
6087  * Return NULL if not found.
6088  *	  case 234:    a = b;
6089  *		       ^
6090  */
6091     static char_u *
6092 after_label(char_u *l)
6093 {
6094     for ( ; *l; ++l)
6095     {
6096 	if (*l == ':')
6097 	{
6098 	    if (l[1] == ':')	    /* skip over "::" for C++ */
6099 		++l;
6100 	    else if (!cin_iscase(l + 1, FALSE))
6101 		break;
6102 	}
6103 	else if (*l == '\'' && l[1] && l[2] == '\'')
6104 	    l += 2;		    /* skip over 'x' */
6105     }
6106     if (*l == NUL)
6107 	return NULL;
6108     l = cin_skipcomment(l + 1);
6109     if (*l == NUL)
6110 	return NULL;
6111     return l;
6112 }
6113 
6114 /*
6115  * Get indent of line "lnum", skipping a label.
6116  * Return 0 if there is nothing after the label.
6117  */
6118     static int
6119 get_indent_nolabel (linenr_T lnum)	/* XXX */
6120 {
6121     char_u	*l;
6122     pos_T	fp;
6123     colnr_T	col;
6124     char_u	*p;
6125 
6126     l = ml_get(lnum);
6127     p = after_label(l);
6128     if (p == NULL)
6129 	return 0;
6130 
6131     fp.col = (colnr_T)(p - l);
6132     fp.lnum = lnum;
6133     getvcol(curwin, &fp, &col, NULL, NULL);
6134     return (int)col;
6135 }
6136 
6137 /*
6138  * Find indent for line "lnum", ignoring any case or jump label.
6139  * Also return a pointer to the text (after the label) in "pp".
6140  *   label:	if (asdf && asdfasdf)
6141  *		^
6142  */
6143     static int
6144 skip_label(linenr_T lnum, char_u **pp)
6145 {
6146     char_u	*l;
6147     int		amount;
6148     pos_T	cursor_save;
6149 
6150     cursor_save = curwin->w_cursor;
6151     curwin->w_cursor.lnum = lnum;
6152     l = ml_get_curline();
6153 				    /* XXX */
6154     if (cin_iscase(l, FALSE) || cin_isscopedecl(l) || cin_islabel())
6155     {
6156 	amount = get_indent_nolabel(lnum);
6157 	l = after_label(ml_get_curline());
6158 	if (l == NULL)		/* just in case */
6159 	    l = ml_get_curline();
6160     }
6161     else
6162     {
6163 	amount = get_indent();
6164 	l = ml_get_curline();
6165     }
6166     *pp = l;
6167 
6168     curwin->w_cursor = cursor_save;
6169     return amount;
6170 }
6171 
6172 /*
6173  * Return the indent of the first variable name after a type in a declaration.
6174  *  int	    a,			indent of "a"
6175  *  static struct foo    b,	indent of "b"
6176  *  enum bla    c,		indent of "c"
6177  * Returns zero when it doesn't look like a declaration.
6178  */
6179     static int
6180 cin_first_id_amount(void)
6181 {
6182     char_u	*line, *p, *s;
6183     int		len;
6184     pos_T	fp;
6185     colnr_T	col;
6186 
6187     line = ml_get_curline();
6188     p = skipwhite(line);
6189     len = (int)(skiptowhite(p) - p);
6190     if (len == 6 && STRNCMP(p, "static", 6) == 0)
6191     {
6192 	p = skipwhite(p + 6);
6193 	len = (int)(skiptowhite(p) - p);
6194     }
6195     if (len == 6 && STRNCMP(p, "struct", 6) == 0)
6196 	p = skipwhite(p + 6);
6197     else if (len == 4 && STRNCMP(p, "enum", 4) == 0)
6198 	p = skipwhite(p + 4);
6199     else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0)
6200 	    || (len == 6 && STRNCMP(p, "signed", 6) == 0))
6201     {
6202 	s = skipwhite(p + len);
6203 	if ((STRNCMP(s, "int", 3) == 0 && VIM_ISWHITE(s[3]))
6204 		|| (STRNCMP(s, "long", 4) == 0 && VIM_ISWHITE(s[4]))
6205 		|| (STRNCMP(s, "short", 5) == 0 && VIM_ISWHITE(s[5]))
6206 		|| (STRNCMP(s, "char", 4) == 0 && VIM_ISWHITE(s[4])))
6207 	    p = s;
6208     }
6209     for (len = 0; vim_isIDc(p[len]); ++len)
6210 	;
6211     if (len == 0 || !VIM_ISWHITE(p[len]) || cin_nocode(p))
6212 	return 0;
6213 
6214     p = skipwhite(p + len);
6215     fp.lnum = curwin->w_cursor.lnum;
6216     fp.col = (colnr_T)(p - line);
6217     getvcol(curwin, &fp, &col, NULL, NULL);
6218     return (int)col;
6219 }
6220 
6221 /*
6222  * Return the indent of the first non-blank after an equal sign.
6223  *       char *foo = "here";
6224  * Return zero if no (useful) equal sign found.
6225  * Return -1 if the line above "lnum" ends in a backslash.
6226  *      foo = "asdf\
6227  *	       asdf\
6228  *	       here";
6229  */
6230     static int
6231 cin_get_equal_amount(linenr_T lnum)
6232 {
6233     char_u	*line;
6234     char_u	*s;
6235     colnr_T	col;
6236     pos_T	fp;
6237 
6238     if (lnum > 1)
6239     {
6240 	line = ml_get(lnum - 1);
6241 	if (*line != NUL && line[STRLEN(line) - 1] == '\\')
6242 	    return -1;
6243     }
6244 
6245     line = s = ml_get(lnum);
6246     while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL)
6247     {
6248 	if (cin_iscomment(s))	/* ignore comments */
6249 	    s = cin_skipcomment(s);
6250 	else
6251 	    ++s;
6252     }
6253     if (*s != '=')
6254 	return 0;
6255 
6256     s = skipwhite(s + 1);
6257     if (cin_nocode(s))
6258 	return 0;
6259 
6260     if (*s == '"')	/* nice alignment for continued strings */
6261 	++s;
6262 
6263     fp.lnum = lnum;
6264     fp.col = (colnr_T)(s - line);
6265     getvcol(curwin, &fp, &col, NULL, NULL);
6266     return (int)col;
6267 }
6268 
6269 /*
6270  * Recognize a preprocessor statement: Any line that starts with '#'.
6271  */
6272     static int
6273 cin_ispreproc(char_u *s)
6274 {
6275     if (*skipwhite(s) == '#')
6276 	return TRUE;
6277     return FALSE;
6278 }
6279 
6280 /*
6281  * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
6282  * continuation line of a preprocessor statement.  Decrease "*lnump" to the
6283  * start and return the line in "*pp".
6284  * Put the amount of indent in "*amount".
6285  */
6286     static int
6287 cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
6288 {
6289     char_u	*line = *pp;
6290     linenr_T	lnum = *lnump;
6291     int		retval = FALSE;
6292     int		candidate_amount = *amount;
6293 
6294     if (*line != NUL && line[STRLEN(line) - 1] == '\\')
6295 	candidate_amount = get_indent_lnum(lnum);
6296 
6297     for (;;)
6298     {
6299 	if (cin_ispreproc(line))
6300 	{
6301 	    retval = TRUE;
6302 	    *lnump = lnum;
6303 	    break;
6304 	}
6305 	if (lnum == 1)
6306 	    break;
6307 	line = ml_get(--lnum);
6308 	if (*line == NUL || line[STRLEN(line) - 1] != '\\')
6309 	    break;
6310     }
6311 
6312     if (lnum != *lnump)
6313 	*pp = ml_get(*lnump);
6314     if (retval)
6315 	*amount = candidate_amount;
6316     return retval;
6317 }
6318 
6319 /*
6320  * Recognize the start of a C or C++ comment.
6321  */
6322     static int
6323 cin_iscomment(char_u *p)
6324 {
6325     return (p[0] == '/' && (p[1] == '*' || p[1] == '/'));
6326 }
6327 
6328 /*
6329  * Recognize the start of a "//" comment.
6330  */
6331     static int
6332 cin_islinecomment(char_u *p)
6333 {
6334     return (p[0] == '/' && p[1] == '/');
6335 }
6336 
6337 /*
6338  * Recognize a line that starts with '{' or '}', or ends with ';', ',', '{' or
6339  * '}'.
6340  * Don't consider "} else" a terminated line.
6341  * If a line begins with an "else", only consider it terminated if no unmatched
6342  * opening braces follow (handle "else { foo();" correctly).
6343  * Return the character terminating the line (ending char's have precedence if
6344  * both apply in order to determine initializations).
6345  */
6346     static int
6347 cin_isterminated(
6348     char_u	*s,
6349     int		incl_open,	/* include '{' at the end as terminator */
6350     int		incl_comma)	/* recognize a trailing comma */
6351 {
6352     char_u	found_start = 0;
6353     unsigned	n_open = 0;
6354     int		is_else = FALSE;
6355 
6356     s = cin_skipcomment(s);
6357 
6358     if (*s == '{' || (*s == '}' && !cin_iselse(s)))
6359 	found_start = *s;
6360 
6361     if (!found_start)
6362 	is_else = cin_iselse(s);
6363 
6364     while (*s)
6365     {
6366 	/* skip over comments, "" strings and 'c'haracters */
6367 	s = skip_string(cin_skipcomment(s));
6368 	if (*s == '}' && n_open > 0)
6369 	    --n_open;
6370 	if ((!is_else || n_open == 0)
6371 		&& (*s == ';' || *s == '}' || (incl_comma && *s == ','))
6372 		&& cin_nocode(s + 1))
6373 	    return *s;
6374 	else if (*s == '{')
6375 	{
6376 	    if (incl_open && cin_nocode(s + 1))
6377 		return *s;
6378 	    else
6379 		++n_open;
6380 	}
6381 
6382 	if (*s)
6383 	    s++;
6384     }
6385     return found_start;
6386 }
6387 
6388 /*
6389  * Recognize the basic picture of a function declaration -- it needs to
6390  * have an open paren somewhere and a close paren at the end of the line and
6391  * no semicolons anywhere.
6392  * When a line ends in a comma we continue looking in the next line.
6393  * "sp" points to a string with the line.  When looking at other lines it must
6394  * be restored to the line.  When it's NULL fetch lines here.
6395  * "first_lnum" is where we start looking.
6396  * "min_lnum" is the line before which we will not be looking.
6397  */
6398     static int
6399 cin_isfuncdecl(
6400     char_u	**sp,
6401     linenr_T	first_lnum,
6402     linenr_T	min_lnum)
6403 {
6404     char_u	*s;
6405     linenr_T	lnum = first_lnum;
6406     linenr_T	save_lnum = curwin->w_cursor.lnum;
6407     int		retval = FALSE;
6408     pos_T	*trypos;
6409     int		just_started = TRUE;
6410 
6411     if (sp == NULL)
6412 	s = ml_get(lnum);
6413     else
6414 	s = *sp;
6415 
6416     curwin->w_cursor.lnum = lnum;
6417     if (find_last_paren(s, '(', ')')
6418 	&& (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
6419     {
6420 	lnum = trypos->lnum;
6421 	if (lnum < min_lnum)
6422 	{
6423 	    curwin->w_cursor.lnum = save_lnum;
6424 	    return FALSE;
6425 	}
6426 
6427 	s = ml_get(lnum);
6428     }
6429     curwin->w_cursor.lnum = save_lnum;
6430 
6431     /* Ignore line starting with #. */
6432     if (cin_ispreproc(s))
6433 	return FALSE;
6434 
6435     while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"')
6436     {
6437 	if (cin_iscomment(s))	/* ignore comments */
6438 	    s = cin_skipcomment(s);
6439 	else if (*s == ':')
6440 	{
6441 	    if (*(s + 1) == ':')
6442 		s += 2;
6443 	    else
6444 		/* To avoid a mistake in the following situation:
6445 		 * A::A(int a, int b)
6446 		 *     : a(0)  // <--not a function decl
6447 		 *     , b(0)
6448 		 * {...
6449 		 */
6450 		return FALSE;
6451 	}
6452 	else
6453 	    ++s;
6454     }
6455     if (*s != '(')
6456 	return FALSE;		/* ';', ' or "  before any () or no '(' */
6457 
6458     while (*s && *s != ';' && *s != '\'' && *s != '"')
6459     {
6460 	if (*s == ')' && cin_nocode(s + 1))
6461 	{
6462 	    /* ')' at the end: may have found a match
6463 	     * Check for he previous line not to end in a backslash:
6464 	     *       #if defined(x) && \
6465 	     *		 defined(y)
6466 	     */
6467 	    lnum = first_lnum - 1;
6468 	    s = ml_get(lnum);
6469 	    if (*s == NUL || s[STRLEN(s) - 1] != '\\')
6470 		retval = TRUE;
6471 	    goto done;
6472 	}
6473 	if ((*s == ',' && cin_nocode(s + 1)) || s[1] == NUL || cin_nocode(s))
6474 	{
6475 	    int comma = (*s == ',');
6476 
6477 	    /* ',' at the end: continue looking in the next line.
6478 	     * At the end: check for ',' in the next line, for this style:
6479 	     * func(arg1
6480 	     *       , arg2) */
6481 	    for (;;)
6482 	    {
6483 		if (lnum >= curbuf->b_ml.ml_line_count)
6484 		    break;
6485 		s = ml_get(++lnum);
6486 		if (!cin_ispreproc(s))
6487 		    break;
6488 	    }
6489 	    if (lnum >= curbuf->b_ml.ml_line_count)
6490 		break;
6491 	    /* Require a comma at end of the line or a comma or ')' at the
6492 	     * start of next line. */
6493 	    s = skipwhite(s);
6494 	    if (!just_started && (!comma && *s != ',' && *s != ')'))
6495 		break;
6496 	    just_started = FALSE;
6497 	}
6498 	else if (cin_iscomment(s))	/* ignore comments */
6499 	    s = cin_skipcomment(s);
6500 	else
6501 	{
6502 	    ++s;
6503 	    just_started = FALSE;
6504 	}
6505     }
6506 
6507 done:
6508     if (lnum != first_lnum && sp != NULL)
6509 	*sp = ml_get(first_lnum);
6510 
6511     return retval;
6512 }
6513 
6514     static int
6515 cin_isif(char_u *p)
6516 {
6517  return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]));
6518 }
6519 
6520     static int
6521 cin_iselse(
6522     char_u  *p)
6523 {
6524     if (*p == '}')	    /* accept "} else" */
6525 	p = cin_skipcomment(p + 1);
6526     return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]));
6527 }
6528 
6529     static int
6530 cin_isdo(char_u *p)
6531 {
6532     return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]));
6533 }
6534 
6535 /*
6536  * Check if this is a "while" that should have a matching "do".
6537  * We only accept a "while (condition) ;", with only white space between the
6538  * ')' and ';'. The condition may be spread over several lines.
6539  */
6540     static int
6541 cin_iswhileofdo (char_u *p, linenr_T lnum)	/* XXX */
6542 {
6543     pos_T	cursor_save;
6544     pos_T	*trypos;
6545     int		retval = FALSE;
6546 
6547     p = cin_skipcomment(p);
6548     if (*p == '}')		/* accept "} while (cond);" */
6549 	p = cin_skipcomment(p + 1);
6550     if (cin_starts_with(p, "while"))
6551     {
6552 	cursor_save = curwin->w_cursor;
6553 	curwin->w_cursor.lnum = lnum;
6554 	curwin->w_cursor.col = 0;
6555 	p = ml_get_curline();
6556 	while (*p && *p != 'w')	/* skip any '}', until the 'w' of the "while" */
6557 	{
6558 	    ++p;
6559 	    ++curwin->w_cursor.col;
6560 	}
6561 	if ((trypos = findmatchlimit(NULL, 0, 0,
6562 					      curbuf->b_ind_maxparen)) != NULL
6563 		&& *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
6564 	    retval = TRUE;
6565 	curwin->w_cursor = cursor_save;
6566     }
6567     return retval;
6568 }
6569 
6570 /*
6571  * Check whether in "p" there is an "if", "for" or "while" before "*poffset".
6572  * Return 0 if there is none.
6573  * Otherwise return !0 and update "*poffset" to point to the place where the
6574  * string was found.
6575  */
6576     static int
6577 cin_is_if_for_while_before_offset(char_u *line, int *poffset)
6578 {
6579     int offset = *poffset;
6580 
6581     if (offset-- < 2)
6582 	return 0;
6583     while (offset > 2 && VIM_ISWHITE(line[offset]))
6584 	--offset;
6585 
6586     offset -= 1;
6587     if (!STRNCMP(line + offset, "if", 2))
6588 	goto probablyFound;
6589 
6590     if (offset >= 1)
6591     {
6592 	offset -= 1;
6593 	if (!STRNCMP(line + offset, "for", 3))
6594 	    goto probablyFound;
6595 
6596 	if (offset >= 2)
6597 	{
6598 	    offset -= 2;
6599 	    if (!STRNCMP(line + offset, "while", 5))
6600 		goto probablyFound;
6601 	}
6602     }
6603     return 0;
6604 
6605 probablyFound:
6606     if (!offset || !vim_isIDc(line[offset - 1]))
6607     {
6608 	*poffset = offset;
6609 	return 1;
6610     }
6611     return 0;
6612 }
6613 
6614 /*
6615  * Return TRUE if we are at the end of a do-while.
6616  *    do
6617  *       nothing;
6618  *    while (foo
6619  *	       && bar);  <-- here
6620  * Adjust the cursor to the line with "while".
6621  */
6622     static int
6623 cin_iswhileofdo_end(int terminated)
6624 {
6625     char_u	*line;
6626     char_u	*p;
6627     char_u	*s;
6628     pos_T	*trypos;
6629     int		i;
6630 
6631     if (terminated != ';')	/* there must be a ';' at the end */
6632 	return FALSE;
6633 
6634     p = line = ml_get_curline();
6635     while (*p != NUL)
6636     {
6637 	p = cin_skipcomment(p);
6638 	if (*p == ')')
6639 	{
6640 	    s = skipwhite(p + 1);
6641 	    if (*s == ';' && cin_nocode(s + 1))
6642 	    {
6643 		/* Found ");" at end of the line, now check there is "while"
6644 		 * before the matching '('.  XXX */
6645 		i = (int)(p - line);
6646 		curwin->w_cursor.col = i;
6647 		trypos = find_match_paren(curbuf->b_ind_maxparen);
6648 		if (trypos != NULL)
6649 		{
6650 		    s = cin_skipcomment(ml_get(trypos->lnum));
6651 		    if (*s == '}')		/* accept "} while (cond);" */
6652 			s = cin_skipcomment(s + 1);
6653 		    if (cin_starts_with(s, "while"))
6654 		    {
6655 			curwin->w_cursor.lnum = trypos->lnum;
6656 			return TRUE;
6657 		    }
6658 		}
6659 
6660 		/* Searching may have made "line" invalid, get it again. */
6661 		line = ml_get_curline();
6662 		p = line + i;
6663 	    }
6664 	}
6665 	if (*p != NUL)
6666 	    ++p;
6667     }
6668     return FALSE;
6669 }
6670 
6671     static int
6672 cin_isbreak(char_u *p)
6673 {
6674     return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]));
6675 }
6676 
6677 /*
6678  * Find the position of a C++ base-class declaration or
6679  * constructor-initialization. eg:
6680  *
6681  * class MyClass :
6682  *	baseClass		<-- here
6683  * class MyClass : public baseClass,
6684  *	anotherBaseClass	<-- here (should probably lineup ??)
6685  * MyClass::MyClass(...) :
6686  *	baseClass(...)		<-- here (constructor-initialization)
6687  *
6688  * This is a lot of guessing.  Watch out for "cond ? func() : foo".
6689  */
6690     static int
6691 cin_is_cpp_baseclass(
6692     cpp_baseclass_cache_T *cached) /* input and output */
6693 {
6694     lpos_T	*pos = &cached->lpos;	    /* find position */
6695     char_u	*s;
6696     int		class_or_struct, lookfor_ctor_init, cpp_base_class;
6697     linenr_T	lnum = curwin->w_cursor.lnum;
6698     char_u	*line = ml_get_curline();
6699 
6700     if (pos->lnum <= lnum)
6701 	return cached->found;	/* Use the cached result */
6702 
6703     pos->col = 0;
6704 
6705     s = skipwhite(line);
6706     if (*s == '#')		/* skip #define FOO x ? (x) : x */
6707 	return FALSE;
6708     s = cin_skipcomment(s);
6709     if (*s == NUL)
6710 	return FALSE;
6711 
6712     cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
6713 
6714     /* Search for a line starting with '#', empty, ending in ';' or containing
6715      * '{' or '}' and start below it.  This handles the following situations:
6716      *	a = cond ?
6717      *	      func() :
6718      *		   asdf;
6719      *	func::foo()
6720      *	      : something
6721      *	{}
6722      *	Foo::Foo (int one, int two)
6723      *		: something(4),
6724      *		somethingelse(3)
6725      *	{}
6726      */
6727     while (lnum > 1)
6728     {
6729 	line = ml_get(lnum - 1);
6730 	s = skipwhite(line);
6731 	if (*s == '#' || *s == NUL)
6732 	    break;
6733 	while (*s != NUL)
6734 	{
6735 	    s = cin_skipcomment(s);
6736 	    if (*s == '{' || *s == '}'
6737 		    || (*s == ';' && cin_nocode(s + 1)))
6738 		break;
6739 	    if (*s != NUL)
6740 		++s;
6741 	}
6742 	if (*s != NUL)
6743 	    break;
6744 	--lnum;
6745     }
6746 
6747     pos->lnum = lnum;
6748     line = ml_get(lnum);
6749     s = line;
6750     for (;;)
6751     {
6752 	if (*s == NUL)
6753 	{
6754 	    if (lnum == curwin->w_cursor.lnum)
6755 		break;
6756 	    /* Continue in the cursor line. */
6757 	    line = ml_get(++lnum);
6758 	    s = line;
6759 	}
6760 	if (s == line)
6761 	{
6762 	    /* don't recognize "case (foo):" as a baseclass */
6763 	    if (cin_iscase(s, FALSE))
6764 		break;
6765 	    s = cin_skipcomment(line);
6766 	    if (*s == NUL)
6767 		continue;
6768 	}
6769 
6770 	if (s[0] == '"' || (s[0] == 'R' && s[1] == '"'))
6771 	    s = skip_string(s) + 1;
6772 	else if (s[0] == ':')
6773 	{
6774 	    if (s[1] == ':')
6775 	    {
6776 		/* skip double colon. It can't be a constructor
6777 		 * initialization any more */
6778 		lookfor_ctor_init = FALSE;
6779 		s = cin_skipcomment(s + 2);
6780 	    }
6781 	    else if (lookfor_ctor_init || class_or_struct)
6782 	    {
6783 		/* we have something found, that looks like the start of
6784 		 * cpp-base-class-declaration or constructor-initialization */
6785 		cpp_base_class = TRUE;
6786 		lookfor_ctor_init = class_or_struct = FALSE;
6787 		pos->col = 0;
6788 		s = cin_skipcomment(s + 1);
6789 	    }
6790 	    else
6791 		s = cin_skipcomment(s + 1);
6792 	}
6793 	else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5]))
6794 		|| (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6])))
6795 	{
6796 	    class_or_struct = TRUE;
6797 	    lookfor_ctor_init = FALSE;
6798 
6799 	    if (*s == 'c')
6800 		s = cin_skipcomment(s + 5);
6801 	    else
6802 		s = cin_skipcomment(s + 6);
6803 	}
6804 	else
6805 	{
6806 	    if (s[0] == '{' || s[0] == '}' || s[0] == ';')
6807 	    {
6808 		cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE;
6809 	    }
6810 	    else if (s[0] == ')')
6811 	    {
6812 		/* Constructor-initialization is assumed if we come across
6813 		 * something like "):" */
6814 		class_or_struct = FALSE;
6815 		lookfor_ctor_init = TRUE;
6816 	    }
6817 	    else if (s[0] == '?')
6818 	    {
6819 		/* Avoid seeing '() :' after '?' as constructor init. */
6820 		return FALSE;
6821 	    }
6822 	    else if (!vim_isIDc(s[0]))
6823 	    {
6824 		/* if it is not an identifier, we are wrong */
6825 		class_or_struct = FALSE;
6826 		lookfor_ctor_init = FALSE;
6827 	    }
6828 	    else if (pos->col == 0)
6829 	    {
6830 		/* it can't be a constructor-initialization any more */
6831 		lookfor_ctor_init = FALSE;
6832 
6833 		/* the first statement starts here: lineup with this one... */
6834 		if (cpp_base_class)
6835 		    pos->col = (colnr_T)(s - line);
6836 	    }
6837 
6838 	    /* When the line ends in a comma don't align with it. */
6839 	    if (lnum == curwin->w_cursor.lnum && *s == ',' && cin_nocode(s + 1))
6840 		pos->col = 0;
6841 
6842 	    s = cin_skipcomment(s + 1);
6843 	}
6844     }
6845 
6846     cached->found = cpp_base_class;
6847     if (cpp_base_class)
6848 	pos->lnum = lnum;
6849     return cpp_base_class;
6850 }
6851 
6852     static int
6853 get_baseclass_amount(int col)
6854 {
6855     int		amount;
6856     colnr_T	vcol;
6857     pos_T	*trypos;
6858 
6859     if (col == 0)
6860     {
6861 	amount = get_indent();
6862 	if (find_last_paren(ml_get_curline(), '(', ')')
6863 		&& (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
6864 	    amount = get_indent_lnum(trypos->lnum); /* XXX */
6865 	if (!cin_ends_in(ml_get_curline(), (char_u *)",", NULL))
6866 	    amount += curbuf->b_ind_cpp_baseclass;
6867     }
6868     else
6869     {
6870 	curwin->w_cursor.col = col;
6871 	getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
6872 	amount = (int)vcol;
6873     }
6874     if (amount < curbuf->b_ind_cpp_baseclass)
6875 	amount = curbuf->b_ind_cpp_baseclass;
6876     return amount;
6877 }
6878 
6879 /*
6880  * Return TRUE if string "s" ends with the string "find", possibly followed by
6881  * white space and comments.  Skip strings and comments.
6882  * Ignore "ignore" after "find" if it's not NULL.
6883  */
6884     static int
6885 cin_ends_in(char_u *s, char_u *find, char_u *ignore)
6886 {
6887     char_u	*p = s;
6888     char_u	*r;
6889     int		len = (int)STRLEN(find);
6890 
6891     while (*p != NUL)
6892     {
6893 	p = cin_skipcomment(p);
6894 	if (STRNCMP(p, find, len) == 0)
6895 	{
6896 	    r = skipwhite(p + len);
6897 	    if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
6898 		r = skipwhite(r + STRLEN(ignore));
6899 	    if (cin_nocode(r))
6900 		return TRUE;
6901 	}
6902 	if (*p != NUL)
6903 	    ++p;
6904     }
6905     return FALSE;
6906 }
6907 
6908 /*
6909  * Return TRUE when "s" starts with "word" and then a non-ID character.
6910  */
6911     static int
6912 cin_starts_with(char_u *s, char *word)
6913 {
6914     int l = (int)STRLEN(word);
6915 
6916     return (STRNCMP(s, word, l) == 0 && !vim_isIDc(s[l]));
6917 }
6918 
6919 /*
6920  * Skip strings, chars and comments until at or past "trypos".
6921  * Return the column found.
6922  */
6923     static int
6924 cin_skip2pos(pos_T *trypos)
6925 {
6926     char_u	*line;
6927     char_u	*p;
6928     char_u	*new_p;
6929 
6930     p = line = ml_get(trypos->lnum);
6931     while (*p && (colnr_T)(p - line) < trypos->col)
6932     {
6933 	if (cin_iscomment(p))
6934 	    p = cin_skipcomment(p);
6935 	else
6936 	{
6937 	    new_p = skip_string(p);
6938 	    if (new_p == p)
6939 		++p;
6940 	    else
6941 		p = new_p;
6942 	}
6943     }
6944     return (int)(p - line);
6945 }
6946 
6947 /*
6948  * Find the '{' at the start of the block we are in.
6949  * Return NULL if no match found.
6950  * Ignore a '{' that is in a comment, makes indenting the next three lines
6951  * work. */
6952 /* foo()    */
6953 /* {	    */
6954 /* }	    */
6955 
6956     static pos_T *
6957 find_start_brace(void)	    /* XXX */
6958 {
6959     pos_T	cursor_save;
6960     pos_T	*trypos;
6961     pos_T	*pos;
6962     static pos_T	pos_copy;
6963 
6964     cursor_save = curwin->w_cursor;
6965     while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
6966     {
6967 	pos_copy = *trypos;	/* copy pos_T, next findmatch will change it */
6968 	trypos = &pos_copy;
6969 	curwin->w_cursor = *trypos;
6970 	pos = NULL;
6971 	/* ignore the { if it's in a // or / *  * / comment */
6972 	if ((colnr_T)cin_skip2pos(trypos) == trypos->col
6973 		       && (pos = ind_find_start_CORS(NULL)) == NULL) /* XXX */
6974 	    break;
6975 	if (pos != NULL)
6976 	    curwin->w_cursor.lnum = pos->lnum;
6977     }
6978     curwin->w_cursor = cursor_save;
6979     return trypos;
6980 }
6981 
6982 /*
6983  * Find the matching '(', ignoring it if it is in a comment.
6984  * Return NULL if no match found.
6985  */
6986     static pos_T *
6987 find_match_paren(int ind_maxparen)	/* XXX */
6988 {
6989     return find_match_char('(', ind_maxparen);
6990 }
6991 
6992     static pos_T *
6993 find_match_char (int c, int ind_maxparen)	/* XXX */
6994 {
6995     pos_T	cursor_save;
6996     pos_T	*trypos;
6997     static pos_T pos_copy;
6998     int		ind_maxp_wk;
6999 
7000     cursor_save = curwin->w_cursor;
7001     ind_maxp_wk = ind_maxparen;
7002 retry:
7003     if ((trypos = findmatchlimit(NULL, c, 0, ind_maxp_wk)) != NULL)
7004     {
7005 	/* check if the ( is in a // comment */
7006 	if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
7007 	{
7008 	    ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum - trypos->lnum);
7009 	    if (ind_maxp_wk > 0)
7010 	    {
7011 		curwin->w_cursor = *trypos;
7012 		curwin->w_cursor.col = 0;	/* XXX */
7013 		goto retry;
7014 	    }
7015 	    trypos = NULL;
7016 	}
7017 	else
7018 	{
7019 	    pos_T	*trypos_wk;
7020 
7021 	    pos_copy = *trypos;	    /* copy trypos, findmatch will change it */
7022 	    trypos = &pos_copy;
7023 	    curwin->w_cursor = *trypos;
7024 	    if ((trypos_wk = ind_find_start_CORS(NULL)) != NULL) /* XXX */
7025 	    {
7026 		ind_maxp_wk = ind_maxparen - (int)(cursor_save.lnum
7027 			- trypos_wk->lnum);
7028 		if (ind_maxp_wk > 0)
7029 		{
7030 		    curwin->w_cursor = *trypos_wk;
7031 		    goto retry;
7032 		}
7033 		trypos = NULL;
7034 	    }
7035 	}
7036     }
7037     curwin->w_cursor = cursor_save;
7038     return trypos;
7039 }
7040 
7041 /*
7042  * Find the matching '(', ignoring it if it is in a comment or before an
7043  * unmatched {.
7044  * Return NULL if no match found.
7045  */
7046     static pos_T *
7047 find_match_paren_after_brace (int ind_maxparen)	    /* XXX */
7048 {
7049     pos_T	*trypos = find_match_paren(ind_maxparen);
7050 
7051     if (trypos != NULL)
7052     {
7053 	pos_T	*tryposBrace = find_start_brace();
7054 
7055 	/* If both an unmatched '(' and '{' is found.  Ignore the '('
7056 	 * position if the '{' is further down. */
7057 	if (tryposBrace != NULL
7058 		&& (trypos->lnum != tryposBrace->lnum
7059 		    ? trypos->lnum < tryposBrace->lnum
7060 		    : trypos->col < tryposBrace->col))
7061 	    trypos = NULL;
7062     }
7063     return trypos;
7064 }
7065 
7066 /*
7067  * Return ind_maxparen corrected for the difference in line number between the
7068  * cursor position and "startpos".  This makes sure that searching for a
7069  * matching paren above the cursor line doesn't find a match because of
7070  * looking a few lines further.
7071  */
7072     static int
7073 corr_ind_maxparen(pos_T *startpos)
7074 {
7075     long	n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
7076 
7077     if (n > 0 && n < curbuf->b_ind_maxparen / 2)
7078 	return curbuf->b_ind_maxparen - (int)n;
7079     return curbuf->b_ind_maxparen;
7080 }
7081 
7082 /*
7083  * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
7084  * line "l".  "l" must point to the start of the line.
7085  */
7086     static int
7087 find_last_paren(char_u *l, int start, int end)
7088 {
7089     int		i;
7090     int		retval = FALSE;
7091     int		open_count = 0;
7092 
7093     curwin->w_cursor.col = 0;		    /* default is start of line */
7094 
7095     for (i = 0; l[i] != NUL; i++)
7096     {
7097 	i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */
7098 	i = (int)(skip_string(l + i) - l);    /* ignore parens in quotes */
7099 	if (l[i] == start)
7100 	    ++open_count;
7101 	else if (l[i] == end)
7102 	{
7103 	    if (open_count > 0)
7104 		--open_count;
7105 	    else
7106 	    {
7107 		curwin->w_cursor.col = i;
7108 		retval = TRUE;
7109 	    }
7110 	}
7111     }
7112     return retval;
7113 }
7114 
7115 /*
7116  * Parse 'cinoptions' and set the values in "curbuf".
7117  * Must be called when 'cinoptions', 'shiftwidth' and/or 'tabstop' changes.
7118  */
7119     void
7120 parse_cino(buf_T *buf)
7121 {
7122     char_u	*p;
7123     char_u	*l;
7124     char_u	*digits;
7125     int		n;
7126     int		divider;
7127     int		fraction = 0;
7128     int		sw = (int)get_sw_value(buf);
7129 
7130     /*
7131      * Set the default values.
7132      */
7133     /* Spaces from a block's opening brace the prevailing indent for that
7134      * block should be. */
7135     buf->b_ind_level = sw;
7136 
7137     /* Spaces from the edge of the line an open brace that's at the end of a
7138      * line is imagined to be. */
7139     buf->b_ind_open_imag = 0;
7140 
7141     /* Spaces from the prevailing indent for a line that is not preceded by
7142      * an opening brace. */
7143     buf->b_ind_no_brace = 0;
7144 
7145     /* Column where the first { of a function should be located }. */
7146     buf->b_ind_first_open = 0;
7147 
7148     /* Spaces from the prevailing indent a leftmost open brace should be
7149      * located. */
7150     buf->b_ind_open_extra = 0;
7151 
7152     /* Spaces from the matching open brace (real location for one at the left
7153      * edge; imaginary location from one that ends a line) the matching close
7154      * brace should be located. */
7155     buf->b_ind_close_extra = 0;
7156 
7157     /* Spaces from the edge of the line an open brace sitting in the leftmost
7158      * column is imagined to be. */
7159     buf->b_ind_open_left_imag = 0;
7160 
7161     /* Spaces jump labels should be shifted to the left if N is non-negative,
7162      * otherwise the jump label will be put to column 1. */
7163     buf->b_ind_jump_label = -1;
7164 
7165     /* Spaces from the switch() indent a "case xx" label should be located. */
7166     buf->b_ind_case = sw;
7167 
7168     /* Spaces from the "case xx:" code after a switch() should be located. */
7169     buf->b_ind_case_code = sw;
7170 
7171     /* Lineup break at end of case in switch() with case label. */
7172     buf->b_ind_case_break = 0;
7173 
7174     /* Spaces from the class declaration indent a scope declaration label
7175      * should be located. */
7176     buf->b_ind_scopedecl = sw;
7177 
7178     /* Spaces from the scope declaration label code should be located. */
7179     buf->b_ind_scopedecl_code = sw;
7180 
7181     /* Amount K&R-style parameters should be indented. */
7182     buf->b_ind_param = sw;
7183 
7184     /* Amount a function type spec should be indented. */
7185     buf->b_ind_func_type = sw;
7186 
7187     /* Amount a cpp base class declaration or constructor initialization
7188      * should be indented. */
7189     buf->b_ind_cpp_baseclass = sw;
7190 
7191     /* additional spaces beyond the prevailing indent a continuation line
7192      * should be located. */
7193     buf->b_ind_continuation = sw;
7194 
7195     /* Spaces from the indent of the line with an unclosed parentheses. */
7196     buf->b_ind_unclosed = sw * 2;
7197 
7198     /* Spaces from the indent of the line with an unclosed parentheses, which
7199      * itself is also unclosed. */
7200     buf->b_ind_unclosed2 = sw;
7201 
7202     /* Suppress ignoring spaces from the indent of a line starting with an
7203      * unclosed parentheses. */
7204     buf->b_ind_unclosed_noignore = 0;
7205 
7206     /* If the opening paren is the last nonwhite character on the line, and
7207      * b_ind_unclosed_wrapped is nonzero, use this indent relative to the outer
7208      * context (for very long lines). */
7209     buf->b_ind_unclosed_wrapped = 0;
7210 
7211     /* Suppress ignoring white space when lining up with the character after
7212      * an unclosed parentheses. */
7213     buf->b_ind_unclosed_whiteok = 0;
7214 
7215     /* Indent a closing parentheses under the line start of the matching
7216      * opening parentheses. */
7217     buf->b_ind_matching_paren = 0;
7218 
7219     /* Indent a closing parentheses under the previous line. */
7220     buf->b_ind_paren_prev = 0;
7221 
7222     /* Extra indent for comments. */
7223     buf->b_ind_comment = 0;
7224 
7225     /* Spaces from the comment opener when there is nothing after it. */
7226     buf->b_ind_in_comment = 3;
7227 
7228     /* Boolean: if non-zero, use b_ind_in_comment even if there is something
7229      * after the comment opener. */
7230     buf->b_ind_in_comment2 = 0;
7231 
7232     /* Max lines to search for an open paren. */
7233     buf->b_ind_maxparen = 20;
7234 
7235     /* Max lines to search for an open comment. */
7236     buf->b_ind_maxcomment = 70;
7237 
7238     /* Handle braces for java code. */
7239     buf->b_ind_java = 0;
7240 
7241     /* Not to confuse JS object properties with labels. */
7242     buf->b_ind_js = 0;
7243 
7244     /* Handle blocked cases correctly. */
7245     buf->b_ind_keep_case_label = 0;
7246 
7247     /* Handle C++ namespace. */
7248     buf->b_ind_cpp_namespace = 0;
7249 
7250     /* Handle continuation lines containing conditions of if(), for() and
7251      * while(). */
7252     buf->b_ind_if_for_while = 0;
7253 
7254     /* indentation for # comments */
7255     buf->b_ind_hash_comment = 0;
7256 
7257     /* Handle C++ extern "C" or "C++" */
7258     buf->b_ind_cpp_extern_c = 0;
7259 
7260     for (p = buf->b_p_cino; *p; )
7261     {
7262 	l = p++;
7263 	if (*p == '-')
7264 	    ++p;
7265 	digits = p;	    /* remember where the digits start */
7266 	n = getdigits(&p);
7267 	divider = 0;
7268 	if (*p == '.')	    /* ".5s" means a fraction */
7269 	{
7270 	    fraction = atol((char *)++p);
7271 	    while (VIM_ISDIGIT(*p))
7272 	    {
7273 		++p;
7274 		if (divider)
7275 		    divider *= 10;
7276 		else
7277 		    divider = 10;
7278 	    }
7279 	}
7280 	if (*p == 's')	    /* "2s" means two times 'shiftwidth' */
7281 	{
7282 	    if (p == digits)
7283 		n = sw;	/* just "s" is one 'shiftwidth' */
7284 	    else
7285 	    {
7286 		n *= sw;
7287 		if (divider)
7288 		    n += (sw * fraction + divider / 2) / divider;
7289 	    }
7290 	    ++p;
7291 	}
7292 	if (l[1] == '-')
7293 	    n = -n;
7294 
7295 	/* When adding an entry here, also update the default 'cinoptions' in
7296 	 * doc/indent.txt, and add explanation for it! */
7297 	switch (*l)
7298 	{
7299 	    case '>': buf->b_ind_level = n; break;
7300 	    case 'e': buf->b_ind_open_imag = n; break;
7301 	    case 'n': buf->b_ind_no_brace = n; break;
7302 	    case 'f': buf->b_ind_first_open = n; break;
7303 	    case '{': buf->b_ind_open_extra = n; break;
7304 	    case '}': buf->b_ind_close_extra = n; break;
7305 	    case '^': buf->b_ind_open_left_imag = n; break;
7306 	    case 'L': buf->b_ind_jump_label = n; break;
7307 	    case ':': buf->b_ind_case = n; break;
7308 	    case '=': buf->b_ind_case_code = n; break;
7309 	    case 'b': buf->b_ind_case_break = n; break;
7310 	    case 'p': buf->b_ind_param = n; break;
7311 	    case 't': buf->b_ind_func_type = n; break;
7312 	    case '/': buf->b_ind_comment = n; break;
7313 	    case 'c': buf->b_ind_in_comment = n; break;
7314 	    case 'C': buf->b_ind_in_comment2 = n; break;
7315 	    case 'i': buf->b_ind_cpp_baseclass = n; break;
7316 	    case '+': buf->b_ind_continuation = n; break;
7317 	    case '(': buf->b_ind_unclosed = n; break;
7318 	    case 'u': buf->b_ind_unclosed2 = n; break;
7319 	    case 'U': buf->b_ind_unclosed_noignore = n; break;
7320 	    case 'W': buf->b_ind_unclosed_wrapped = n; break;
7321 	    case 'w': buf->b_ind_unclosed_whiteok = n; break;
7322 	    case 'm': buf->b_ind_matching_paren = n; break;
7323 	    case 'M': buf->b_ind_paren_prev = n; break;
7324 	    case ')': buf->b_ind_maxparen = n; break;
7325 	    case '*': buf->b_ind_maxcomment = n; break;
7326 	    case 'g': buf->b_ind_scopedecl = n; break;
7327 	    case 'h': buf->b_ind_scopedecl_code = n; break;
7328 	    case 'j': buf->b_ind_java = n; break;
7329 	    case 'J': buf->b_ind_js = n; break;
7330 	    case 'l': buf->b_ind_keep_case_label = n; break;
7331 	    case '#': buf->b_ind_hash_comment = n; break;
7332 	    case 'N': buf->b_ind_cpp_namespace = n; break;
7333 	    case 'k': buf->b_ind_if_for_while = n; break;
7334 	    case 'E': buf->b_ind_cpp_extern_c = n; break;
7335 	}
7336 	if (*p == ',')
7337 	    ++p;
7338     }
7339 }
7340 
7341 /*
7342  * Return the desired indent for C code.
7343  * Return -1 if the indent should be left alone (inside a raw string).
7344  */
7345     int
7346 get_c_indent(void)
7347 {
7348     pos_T	cur_curpos;
7349     int		amount;
7350     int		scope_amount;
7351     int		cur_amount = MAXCOL;
7352     colnr_T	col;
7353     char_u	*theline;
7354     char_u	*linecopy;
7355     pos_T	*trypos;
7356     pos_T	*comment_pos;
7357     pos_T	*tryposBrace = NULL;
7358     pos_T	tryposCopy;
7359     pos_T	our_paren_pos;
7360     char_u	*start;
7361     int		start_brace;
7362 #define BRACE_IN_COL0		1	    /* '{' is in column 0 */
7363 #define BRACE_AT_START		2	    /* '{' is at start of line */
7364 #define BRACE_AT_END		3	    /* '{' is at end of line */
7365     linenr_T	ourscope;
7366     char_u	*l;
7367     char_u	*look;
7368     char_u	terminated;
7369     int		lookfor;
7370 #define LOOKFOR_INITIAL		0
7371 #define LOOKFOR_IF		1
7372 #define LOOKFOR_DO		2
7373 #define LOOKFOR_CASE		3
7374 #define LOOKFOR_ANY		4
7375 #define LOOKFOR_TERM		5
7376 #define LOOKFOR_UNTERM		6
7377 #define LOOKFOR_SCOPEDECL	7
7378 #define LOOKFOR_NOBREAK		8
7379 #define LOOKFOR_CPP_BASECLASS	9
7380 #define LOOKFOR_ENUM_OR_INIT	10
7381 #define LOOKFOR_JS_KEY		11
7382 #define LOOKFOR_COMMA		12
7383 
7384     int		whilelevel;
7385     linenr_T	lnum;
7386     int		n;
7387     int		iscase;
7388     int		lookfor_break;
7389     int		lookfor_cpp_namespace = FALSE;
7390     int		cont_amount = 0;    /* amount for continuation line */
7391     int		original_line_islabel;
7392     int		added_to_amount = 0;
7393     int		js_cur_has_key = 0;
7394     linenr_T	raw_string_start = 0;
7395     cpp_baseclass_cache_T cache_cpp_baseclass = { FALSE, { MAXLNUM, 0 } };
7396 
7397     /* make a copy, value is changed below */
7398     int		ind_continuation = curbuf->b_ind_continuation;
7399 
7400     /* remember where the cursor was when we started */
7401     cur_curpos = curwin->w_cursor;
7402 
7403     /* if we are at line 1 zero indent is fine, right? */
7404     if (cur_curpos.lnum == 1)
7405 	return 0;
7406 
7407     /* Get a copy of the current contents of the line.
7408      * This is required, because only the most recent line obtained with
7409      * ml_get is valid! */
7410     linecopy = vim_strsave(ml_get(cur_curpos.lnum));
7411     if (linecopy == NULL)
7412 	return 0;
7413 
7414     /*
7415      * In insert mode and the cursor is on a ')' truncate the line at the
7416      * cursor position.  We don't want to line up with the matching '(' when
7417      * inserting new stuff.
7418      * For unknown reasons the cursor might be past the end of the line, thus
7419      * check for that.
7420      */
7421     if ((State & INSERT)
7422 	    && curwin->w_cursor.col < (colnr_T)STRLEN(linecopy)
7423 	    && linecopy[curwin->w_cursor.col] == ')')
7424 	linecopy[curwin->w_cursor.col] = NUL;
7425 
7426     theline = skipwhite(linecopy);
7427 
7428     /* move the cursor to the start of the line */
7429 
7430     curwin->w_cursor.col = 0;
7431 
7432     original_line_islabel = cin_islabel();  /* XXX */
7433 
7434     /*
7435      * If we are inside a raw string don't change the indent.
7436      * Ignore a raw string inside a comment.
7437      */
7438     comment_pos = ind_find_start_comment();
7439     if (comment_pos != NULL)
7440     {
7441 	/* findmatchlimit() static pos is overwritten, make a copy */
7442 	tryposCopy = *comment_pos;
7443 	comment_pos = &tryposCopy;
7444     }
7445     trypos = find_start_rawstring(curbuf->b_ind_maxcomment);
7446     if (trypos != NULL && (comment_pos == NULL
7447 					     || LT_POS(*trypos, *comment_pos)))
7448     {
7449 	amount = -1;
7450 	goto laterend;
7451     }
7452 
7453     /*
7454      * #defines and so on always go at the left when included in 'cinkeys'.
7455      */
7456     if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE)))
7457     {
7458 	amount = curbuf->b_ind_hash_comment;
7459 	goto theend;
7460     }
7461 
7462     /*
7463      * Is it a non-case label?	Then that goes at the left margin too unless:
7464      *  - JS flag is set.
7465      *  - 'L' item has a positive value.
7466      */
7467     if (original_line_islabel && !curbuf->b_ind_js
7468 					      && curbuf->b_ind_jump_label < 0)
7469     {
7470 	amount = 0;
7471 	goto theend;
7472     }
7473 
7474     /*
7475      * If we're inside a "//" comment and there is a "//" comment in a
7476      * previous line, lineup with that one.
7477      */
7478     if (cin_islinecomment(theline)
7479 	    && (trypos = find_line_comment()) != NULL) /* XXX */
7480     {
7481 	/* find how indented the line beginning the comment is */
7482 	getvcol(curwin, trypos, &col, NULL, NULL);
7483 	amount = col;
7484 	goto theend;
7485     }
7486 
7487     /*
7488      * If we're inside a comment and not looking at the start of the
7489      * comment, try using the 'comments' option.
7490      */
7491     if (!cin_iscomment(theline) && comment_pos != NULL) /* XXX */
7492     {
7493 	int	lead_start_len = 2;
7494 	int	lead_middle_len = 1;
7495 	char_u	lead_start[COM_MAX_LEN];	/* start-comment string */
7496 	char_u	lead_middle[COM_MAX_LEN];	/* middle-comment string */
7497 	char_u	lead_end[COM_MAX_LEN];		/* end-comment string */
7498 	char_u	*p;
7499 	int	start_align = 0;
7500 	int	start_off = 0;
7501 	int	done = FALSE;
7502 
7503 	/* find how indented the line beginning the comment is */
7504 	getvcol(curwin, comment_pos, &col, NULL, NULL);
7505 	amount = col;
7506 	*lead_start = NUL;
7507 	*lead_middle = NUL;
7508 
7509 	p = curbuf->b_p_com;
7510 	while (*p != NUL)
7511 	{
7512 	    int	align = 0;
7513 	    int	off = 0;
7514 	    int what = 0;
7515 
7516 	    while (*p != NUL && *p != ':')
7517 	    {
7518 		if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE)
7519 		    what = *p++;
7520 		else if (*p == COM_LEFT || *p == COM_RIGHT)
7521 		    align = *p++;
7522 		else if (VIM_ISDIGIT(*p) || *p == '-')
7523 		    off = getdigits(&p);
7524 		else
7525 		    ++p;
7526 	    }
7527 
7528 	    if (*p == ':')
7529 		++p;
7530 	    (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
7531 	    if (what == COM_START)
7532 	    {
7533 		STRCPY(lead_start, lead_end);
7534 		lead_start_len = (int)STRLEN(lead_start);
7535 		start_off = off;
7536 		start_align = align;
7537 	    }
7538 	    else if (what == COM_MIDDLE)
7539 	    {
7540 		STRCPY(lead_middle, lead_end);
7541 		lead_middle_len = (int)STRLEN(lead_middle);
7542 	    }
7543 	    else if (what == COM_END)
7544 	    {
7545 		/* If our line starts with the middle comment string, line it
7546 		 * up with the comment opener per the 'comments' option. */
7547 		if (STRNCMP(theline, lead_middle, lead_middle_len) == 0
7548 			&& STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0)
7549 		{
7550 		    done = TRUE;
7551 		    if (curwin->w_cursor.lnum > 1)
7552 		    {
7553 			/* If the start comment string matches in the previous
7554 			 * line, use the indent of that line plus offset.  If
7555 			 * the middle comment string matches in the previous
7556 			 * line, use the indent of that line.  XXX */
7557 			look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
7558 			if (STRNCMP(look, lead_start, lead_start_len) == 0)
7559 			    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
7560 			else if (STRNCMP(look, lead_middle,
7561 							lead_middle_len) == 0)
7562 			{
7563 			    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
7564 			    break;
7565 			}
7566 			/* If the start comment string doesn't match with the
7567 			 * start of the comment, skip this entry. XXX */
7568 			else if (STRNCMP(ml_get(comment_pos->lnum) + comment_pos->col,
7569 					     lead_start, lead_start_len) != 0)
7570 			    continue;
7571 		    }
7572 		    if (start_off != 0)
7573 			amount += start_off;
7574 		    else if (start_align == COM_RIGHT)
7575 			amount += vim_strsize(lead_start)
7576 						   - vim_strsize(lead_middle);
7577 		    break;
7578 		}
7579 
7580 		/* If our line starts with the end comment string, line it up
7581 		 * with the middle comment */
7582 		if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
7583 			&& STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0)
7584 		{
7585 		    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
7586 								     /* XXX */
7587 		    if (off != 0)
7588 			amount += off;
7589 		    else if (align == COM_RIGHT)
7590 			amount += vim_strsize(lead_start)
7591 						   - vim_strsize(lead_middle);
7592 		    done = TRUE;
7593 		    break;
7594 		}
7595 	    }
7596 	}
7597 
7598 	/* If our line starts with an asterisk, line up with the
7599 	 * asterisk in the comment opener; otherwise, line up
7600 	 * with the first character of the comment text.
7601 	 */
7602 	if (done)
7603 	    ;
7604 	else if (theline[0] == '*')
7605 	    amount += 1;
7606 	else
7607 	{
7608 	    /*
7609 	     * If we are more than one line away from the comment opener, take
7610 	     * the indent of the previous non-empty line.  If 'cino' has "CO"
7611 	     * and we are just below the comment opener and there are any
7612 	     * white characters after it line up with the text after it;
7613 	     * otherwise, add the amount specified by "c" in 'cino'
7614 	     */
7615 	    amount = -1;
7616 	    for (lnum = cur_curpos.lnum - 1; lnum > comment_pos->lnum; --lnum)
7617 	    {
7618 		if (linewhite(lnum))		    /* skip blank lines */
7619 		    continue;
7620 		amount = get_indent_lnum(lnum);	    /* XXX */
7621 		break;
7622 	    }
7623 	    if (amount == -1)			    /* use the comment opener */
7624 	    {
7625 		if (!curbuf->b_ind_in_comment2)
7626 		{
7627 		    start = ml_get(comment_pos->lnum);
7628 		    look = start + comment_pos->col + 2; /* skip / and * */
7629 		    if (*look != NUL)		    /* if something after it */
7630 			comment_pos->col = (colnr_T)(skipwhite(look) - start);
7631 		}
7632 		getvcol(curwin, comment_pos, &col, NULL, NULL);
7633 		amount = col;
7634 		if (curbuf->b_ind_in_comment2 || *look == NUL)
7635 		    amount += curbuf->b_ind_in_comment;
7636 	    }
7637 	}
7638 	goto theend;
7639     }
7640 
7641     /*
7642      * Are we looking at a ']' that has a match?
7643      */
7644     if (*skipwhite(theline) == ']'
7645 	    && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL)
7646     {
7647 	/* align with the line containing the '['. */
7648 	amount = get_indent_lnum(trypos->lnum);
7649 	goto theend;
7650     }
7651 
7652     /*
7653      * Are we inside parentheses or braces?
7654      */						    /* XXX */
7655     if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL
7656 		&& curbuf->b_ind_java == 0)
7657 	    || (tryposBrace = find_start_brace()) != NULL
7658 	    || trypos != NULL)
7659     {
7660       if (trypos != NULL && tryposBrace != NULL)
7661       {
7662 	  /* Both an unmatched '(' and '{' is found.  Use the one which is
7663 	   * closer to the current cursor position, set the other to NULL. */
7664 	  if (trypos->lnum != tryposBrace->lnum
7665 		  ? trypos->lnum < tryposBrace->lnum
7666 		  : trypos->col < tryposBrace->col)
7667 	      trypos = NULL;
7668 	  else
7669 	      tryposBrace = NULL;
7670       }
7671 
7672       if (trypos != NULL)
7673       {
7674 	/*
7675 	 * If the matching paren is more than one line away, use the indent of
7676 	 * a previous non-empty line that matches the same paren.
7677 	 */
7678 	if (theline[0] == ')' && curbuf->b_ind_paren_prev)
7679 	{
7680 	    /* Line up with the start of the matching paren line. */
7681 	    amount = get_indent_lnum(curwin->w_cursor.lnum - 1);  /* XXX */
7682 	}
7683 	else
7684 	{
7685 	    amount = -1;
7686 	    our_paren_pos = *trypos;
7687 	    for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum)
7688 	    {
7689 		l = skipwhite(ml_get(lnum));
7690 		if (cin_nocode(l))		/* skip comment lines */
7691 		    continue;
7692 		if (cin_ispreproc_cont(&l, &lnum, &amount))
7693 		    continue;			/* ignore #define, #if, etc. */
7694 		curwin->w_cursor.lnum = lnum;
7695 
7696 		/* Skip a comment or raw string. XXX */
7697 		if ((trypos = ind_find_start_CORS(NULL)) != NULL)
7698 		{
7699 		    lnum = trypos->lnum + 1;
7700 		    continue;
7701 		}
7702 
7703 		/* XXX */
7704 		if ((trypos = find_match_paren(
7705 			corr_ind_maxparen(&cur_curpos))) != NULL
7706 			&& trypos->lnum == our_paren_pos.lnum
7707 			&& trypos->col == our_paren_pos.col)
7708 		{
7709 			amount = get_indent_lnum(lnum);	/* XXX */
7710 
7711 			if (theline[0] == ')')
7712 			{
7713 			    if (our_paren_pos.lnum != lnum
7714 						       && cur_amount > amount)
7715 				cur_amount = amount;
7716 			    amount = -1;
7717 			}
7718 		    break;
7719 		}
7720 	    }
7721 	}
7722 
7723 	/*
7724 	 * Line up with line where the matching paren is. XXX
7725 	 * If the line starts with a '(' or the indent for unclosed
7726 	 * parentheses is zero, line up with the unclosed parentheses.
7727 	 */
7728 	if (amount == -1)
7729 	{
7730 	    int	    ignore_paren_col = 0;
7731 	    int	    is_if_for_while = 0;
7732 
7733 	    if (curbuf->b_ind_if_for_while)
7734 	    {
7735 		/* Look for the outermost opening parenthesis on this line
7736 		 * and check whether it belongs to an "if", "for" or "while". */
7737 
7738 		pos_T	    cursor_save = curwin->w_cursor;
7739 		pos_T	    outermost;
7740 		char_u	    *line;
7741 
7742 		trypos = &our_paren_pos;
7743 		do {
7744 		    outermost = *trypos;
7745 		    curwin->w_cursor.lnum = outermost.lnum;
7746 		    curwin->w_cursor.col = outermost.col;
7747 
7748 		    trypos = find_match_paren(curbuf->b_ind_maxparen);
7749 		} while (trypos && trypos->lnum == outermost.lnum);
7750 
7751 		curwin->w_cursor = cursor_save;
7752 
7753 		line = ml_get(outermost.lnum);
7754 
7755 		is_if_for_while =
7756 		    cin_is_if_for_while_before_offset(line, &outermost.col);
7757 	    }
7758 
7759 	    amount = skip_label(our_paren_pos.lnum, &look);
7760 	    look = skipwhite(look);
7761 	    if (*look == '(')
7762 	    {
7763 		linenr_T    save_lnum = curwin->w_cursor.lnum;
7764 		char_u	    *line;
7765 		int	    look_col;
7766 
7767 		/* Ignore a '(' in front of the line that has a match before
7768 		 * our matching '('. */
7769 		curwin->w_cursor.lnum = our_paren_pos.lnum;
7770 		line = ml_get_curline();
7771 		look_col = (int)(look - line);
7772 		curwin->w_cursor.col = look_col + 1;
7773 		if ((trypos = findmatchlimit(NULL, ')', 0,
7774 						      curbuf->b_ind_maxparen))
7775 								      != NULL
7776 			  && trypos->lnum == our_paren_pos.lnum
7777 			  && trypos->col < our_paren_pos.col)
7778 		    ignore_paren_col = trypos->col + 1;
7779 
7780 		curwin->w_cursor.lnum = save_lnum;
7781 		look = ml_get(our_paren_pos.lnum) + look_col;
7782 	    }
7783 	    if (theline[0] == ')' || (curbuf->b_ind_unclosed == 0
7784 						      && is_if_for_while == 0)
7785 		    || (!curbuf->b_ind_unclosed_noignore && *look == '('
7786 						    && ignore_paren_col == 0))
7787 	    {
7788 		/*
7789 		 * If we're looking at a close paren, line up right there;
7790 		 * otherwise, line up with the next (non-white) character.
7791 		 * When b_ind_unclosed_wrapped is set and the matching paren is
7792 		 * the last nonwhite character of the line, use either the
7793 		 * indent of the current line or the indentation of the next
7794 		 * outer paren and add b_ind_unclosed_wrapped (for very long
7795 		 * lines).
7796 		 */
7797 		if (theline[0] != ')')
7798 		{
7799 		    cur_amount = MAXCOL;
7800 		    l = ml_get(our_paren_pos.lnum);
7801 		    if (curbuf->b_ind_unclosed_wrapped
7802 				       && cin_ends_in(l, (char_u *)"(", NULL))
7803 		    {
7804 			/* look for opening unmatched paren, indent one level
7805 			 * for each additional level */
7806 			n = 1;
7807 			for (col = 0; col < our_paren_pos.col; ++col)
7808 			{
7809 			    switch (l[col])
7810 			    {
7811 				case '(':
7812 				case '{': ++n;
7813 					  break;
7814 
7815 				case ')':
7816 				case '}': if (n > 1)
7817 					      --n;
7818 					  break;
7819 			    }
7820 			}
7821 
7822 			our_paren_pos.col = 0;
7823 			amount += n * curbuf->b_ind_unclosed_wrapped;
7824 		    }
7825 		    else if (curbuf->b_ind_unclosed_whiteok)
7826 			our_paren_pos.col++;
7827 		    else
7828 		    {
7829 			col = our_paren_pos.col + 1;
7830 			while (VIM_ISWHITE(l[col]))
7831 			    col++;
7832 			if (l[col] != NUL)	/* In case of trailing space */
7833 			    our_paren_pos.col = col;
7834 			else
7835 			    our_paren_pos.col++;
7836 		    }
7837 		}
7838 
7839 		/*
7840 		 * Find how indented the paren is, or the character after it
7841 		 * if we did the above "if".
7842 		 */
7843 		if (our_paren_pos.col > 0)
7844 		{
7845 		    getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
7846 		    if (cur_amount > (int)col)
7847 			cur_amount = col;
7848 		}
7849 	    }
7850 
7851 	    if (theline[0] == ')' && curbuf->b_ind_matching_paren)
7852 	    {
7853 		/* Line up with the start of the matching paren line. */
7854 	    }
7855 	    else if ((curbuf->b_ind_unclosed == 0 && is_if_for_while == 0)
7856 		     || (!curbuf->b_ind_unclosed_noignore
7857 				    && *look == '(' && ignore_paren_col == 0))
7858 	    {
7859 		if (cur_amount != MAXCOL)
7860 		    amount = cur_amount;
7861 	    }
7862 	    else
7863 	    {
7864 		/* Add b_ind_unclosed2 for each '(' before our matching one,
7865 		 * but ignore (void) before the line (ignore_paren_col). */
7866 		col = our_paren_pos.col;
7867 		while ((int)our_paren_pos.col > ignore_paren_col)
7868 		{
7869 		    --our_paren_pos.col;
7870 		    switch (*ml_get_pos(&our_paren_pos))
7871 		    {
7872 			case '(': amount += curbuf->b_ind_unclosed2;
7873 				  col = our_paren_pos.col;
7874 				  break;
7875 			case ')': amount -= curbuf->b_ind_unclosed2;
7876 				  col = MAXCOL;
7877 				  break;
7878 		    }
7879 		}
7880 
7881 		/* Use b_ind_unclosed once, when the first '(' is not inside
7882 		 * braces */
7883 		if (col == MAXCOL)
7884 		    amount += curbuf->b_ind_unclosed;
7885 		else
7886 		{
7887 		    curwin->w_cursor.lnum = our_paren_pos.lnum;
7888 		    curwin->w_cursor.col = col;
7889 		    if (find_match_paren_after_brace(curbuf->b_ind_maxparen)
7890 								      != NULL)
7891 			amount += curbuf->b_ind_unclosed2;
7892 		    else
7893 		    {
7894 			if (is_if_for_while)
7895 			    amount += curbuf->b_ind_if_for_while;
7896 			else
7897 			    amount += curbuf->b_ind_unclosed;
7898 		    }
7899 		}
7900 		/*
7901 		 * For a line starting with ')' use the minimum of the two
7902 		 * positions, to avoid giving it more indent than the previous
7903 		 * lines:
7904 		 *  func_long_name(		    if (x
7905 		 *	arg				    && yy
7906 		 *	)	  ^ not here	       )    ^ not here
7907 		 */
7908 		if (cur_amount < amount)
7909 		    amount = cur_amount;
7910 	    }
7911 	}
7912 
7913 	/* add extra indent for a comment */
7914 	if (cin_iscomment(theline))
7915 	    amount += curbuf->b_ind_comment;
7916       }
7917       else
7918       {
7919 	/*
7920 	 * We are inside braces, there is a { before this line at the position
7921 	 * stored in tryposBrace.
7922 	 * Make a copy of tryposBrace, it may point to pos_copy inside
7923 	 * find_start_brace(), which may be changed somewhere.
7924 	 */
7925 	tryposCopy = *tryposBrace;
7926 	tryposBrace = &tryposCopy;
7927 	trypos = tryposBrace;
7928 	ourscope = trypos->lnum;
7929 	start = ml_get(ourscope);
7930 
7931 	/*
7932 	 * Now figure out how indented the line is in general.
7933 	 * If the brace was at the start of the line, we use that;
7934 	 * otherwise, check out the indentation of the line as
7935 	 * a whole and then add the "imaginary indent" to that.
7936 	 */
7937 	look = skipwhite(start);
7938 	if (*look == '{')
7939 	{
7940 	    getvcol(curwin, trypos, &col, NULL, NULL);
7941 	    amount = col;
7942 	    if (*start == '{')
7943 		start_brace = BRACE_IN_COL0;
7944 	    else
7945 		start_brace = BRACE_AT_START;
7946 	}
7947 	else
7948 	{
7949 	    /* That opening brace might have been on a continuation
7950 	     * line.  if so, find the start of the line. */
7951 	    curwin->w_cursor.lnum = ourscope;
7952 
7953 	    /* Position the cursor over the rightmost paren, so that
7954 	     * matching it will take us back to the start of the line. */
7955 	    lnum = ourscope;
7956 	    if (find_last_paren(start, '(', ')')
7957 			&& (trypos = find_match_paren(curbuf->b_ind_maxparen))
7958 								      != NULL)
7959 		lnum = trypos->lnum;
7960 
7961 	    /* It could have been something like
7962 	     *	   case 1: if (asdf &&
7963 	     *			ldfd) {
7964 	     *		    }
7965 	     */
7966 	    if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label)
7967 			   && cin_iscase(skipwhite(ml_get_curline()), FALSE))
7968 		amount = get_indent();
7969 	    else if (curbuf->b_ind_js)
7970 		amount = get_indent_lnum(lnum);
7971 	    else
7972 		amount = skip_label(lnum, &l);
7973 
7974 	    start_brace = BRACE_AT_END;
7975 	}
7976 
7977 	/* For Javascript check if the line starts with "key:". */
7978 	if (curbuf->b_ind_js)
7979 	    js_cur_has_key = cin_has_js_key(theline);
7980 
7981 	/*
7982 	 * If we're looking at a closing brace, that's where
7983 	 * we want to be.  otherwise, add the amount of room
7984 	 * that an indent is supposed to be.
7985 	 */
7986 	if (theline[0] == '}')
7987 	{
7988 	    /*
7989 	     * they may want closing braces to line up with something
7990 	     * other than the open brace.  indulge them, if so.
7991 	     */
7992 	    amount += curbuf->b_ind_close_extra;
7993 	}
7994 	else
7995 	{
7996 	    /*
7997 	     * If we're looking at an "else", try to find an "if"
7998 	     * to match it with.
7999 	     * If we're looking at a "while", try to find a "do"
8000 	     * to match it with.
8001 	     */
8002 	    lookfor = LOOKFOR_INITIAL;
8003 	    if (cin_iselse(theline))
8004 		lookfor = LOOKFOR_IF;
8005 	    else if (cin_iswhileofdo(theline, cur_curpos.lnum)) /* XXX */
8006 		lookfor = LOOKFOR_DO;
8007 	    if (lookfor != LOOKFOR_INITIAL)
8008 	    {
8009 		curwin->w_cursor.lnum = cur_curpos.lnum;
8010 		if (find_match(lookfor, ourscope) == OK)
8011 		{
8012 		    amount = get_indent();	/* XXX */
8013 		    goto theend;
8014 		}
8015 	    }
8016 
8017 	    /*
8018 	     * We get here if we are not on an "while-of-do" or "else" (or
8019 	     * failed to find a matching "if").
8020 	     * Search backwards for something to line up with.
8021 	     * First set amount for when we don't find anything.
8022 	     */
8023 
8024 	    /*
8025 	     * if the '{' is  _really_ at the left margin, use the imaginary
8026 	     * location of a left-margin brace.  Otherwise, correct the
8027 	     * location for b_ind_open_extra.
8028 	     */
8029 
8030 	    if (start_brace == BRACE_IN_COL0)	    /* '{' is in column 0 */
8031 	    {
8032 		amount = curbuf->b_ind_open_left_imag;
8033 		lookfor_cpp_namespace = TRUE;
8034 	    }
8035 	    else if (start_brace == BRACE_AT_START &&
8036 		    lookfor_cpp_namespace)	  /* '{' is at start */
8037 	    {
8038 
8039 		lookfor_cpp_namespace = TRUE;
8040 	    }
8041 	    else
8042 	    {
8043 		if (start_brace == BRACE_AT_END)    /* '{' is at end of line */
8044 		{
8045 		    amount += curbuf->b_ind_open_imag;
8046 
8047 		    l = skipwhite(ml_get_curline());
8048 		    if (cin_is_cpp_namespace(l))
8049 			amount += curbuf->b_ind_cpp_namespace;
8050 		    else if (cin_is_cpp_extern_c(l))
8051 			amount += curbuf->b_ind_cpp_extern_c;
8052 		}
8053 		else
8054 		{
8055 		    /* Compensate for adding b_ind_open_extra later. */
8056 		    amount -= curbuf->b_ind_open_extra;
8057 		    if (amount < 0)
8058 			amount = 0;
8059 		}
8060 	    }
8061 
8062 	    lookfor_break = FALSE;
8063 
8064 	    if (cin_iscase(theline, FALSE))	/* it's a switch() label */
8065 	    {
8066 		lookfor = LOOKFOR_CASE;	/* find a previous switch() label */
8067 		amount += curbuf->b_ind_case;
8068 	    }
8069 	    else if (cin_isscopedecl(theline))	/* private:, ... */
8070 	    {
8071 		lookfor = LOOKFOR_SCOPEDECL;	/* class decl is this block */
8072 		amount += curbuf->b_ind_scopedecl;
8073 	    }
8074 	    else
8075 	    {
8076 		if (curbuf->b_ind_case_break && cin_isbreak(theline))
8077 		    /* break; ... */
8078 		    lookfor_break = TRUE;
8079 
8080 		lookfor = LOOKFOR_INITIAL;
8081 		/* b_ind_level from start of block */
8082 		amount += curbuf->b_ind_level;
8083 	    }
8084 	    scope_amount = amount;
8085 	    whilelevel = 0;
8086 
8087 	    /*
8088 	     * Search backwards.  If we find something we recognize, line up
8089 	     * with that.
8090 	     *
8091 	     * If we're looking at an open brace, indent
8092 	     * the usual amount relative to the conditional
8093 	     * that opens the block.
8094 	     */
8095 	    curwin->w_cursor = cur_curpos;
8096 	    for (;;)
8097 	    {
8098 		curwin->w_cursor.lnum--;
8099 		curwin->w_cursor.col = 0;
8100 
8101 		/*
8102 		 * If we went all the way back to the start of our scope, line
8103 		 * up with it.
8104 		 */
8105 		if (curwin->w_cursor.lnum <= ourscope)
8106 		{
8107 		    /* We reached end of scope:
8108 		     * If looking for a enum or structure initialization
8109 		     * go further back:
8110 		     * If it is an initializer (enum xxx or xxx =), then
8111 		     * don't add ind_continuation, otherwise it is a variable
8112 		     * declaration:
8113 		     * int x,
8114 		     *     here; <-- add ind_continuation
8115 		     */
8116 		    if (lookfor == LOOKFOR_ENUM_OR_INIT)
8117 		    {
8118 			if (curwin->w_cursor.lnum == 0
8119 				|| curwin->w_cursor.lnum
8120 					  < ourscope - curbuf->b_ind_maxparen)
8121 			{
8122 			    /* nothing found (abuse curbuf->b_ind_maxparen as
8123 			     * limit) assume terminated line (i.e. a variable
8124 			     * initialization) */
8125 			    if (cont_amount > 0)
8126 				amount = cont_amount;
8127 			    else if (!curbuf->b_ind_js)
8128 				amount += ind_continuation;
8129 			    break;
8130 			}
8131 
8132 			l = ml_get_curline();
8133 
8134 			/*
8135 			 * If we're in a comment or raw string now, skip to
8136 			 * the start of it.
8137 			 */
8138 			trypos = ind_find_start_CORS(NULL);
8139 			if (trypos != NULL)
8140 			{
8141 			    curwin->w_cursor.lnum = trypos->lnum + 1;
8142 			    curwin->w_cursor.col = 0;
8143 			    continue;
8144 			}
8145 
8146 			/*
8147 			 * Skip preprocessor directives and blank lines.
8148 			 */
8149 			if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
8150 								    &amount))
8151 			    continue;
8152 
8153 			if (cin_nocode(l))
8154 			    continue;
8155 
8156 			terminated = cin_isterminated(l, FALSE, TRUE);
8157 
8158 			/*
8159 			 * If we are at top level and the line looks like a
8160 			 * function declaration, we are done
8161 			 * (it's a variable declaration).
8162 			 */
8163 			if (start_brace != BRACE_IN_COL0
8164 			     || !cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
8165 			{
8166 			    /* if the line is terminated with another ','
8167 			     * it is a continued variable initialization.
8168 			     * don't add extra indent.
8169 			     * TODO: does not work, if  a function
8170 			     * declaration is split over multiple lines:
8171 			     * cin_isfuncdecl returns FALSE then.
8172 			     */
8173 			    if (terminated == ',')
8174 				break;
8175 
8176 			    /* if it es a enum declaration or an assignment,
8177 			     * we are done.
8178 			     */
8179 			    if (terminated != ';' && cin_isinit())
8180 				break;
8181 
8182 			    /* nothing useful found */
8183 			    if (terminated == 0 || terminated == '{')
8184 				continue;
8185 			}
8186 
8187 			if (terminated != ';')
8188 			{
8189 			    /* Skip parens and braces. Position the cursor
8190 			     * over the rightmost paren, so that matching it
8191 			     * will take us back to the start of the line.
8192 			     */					/* XXX */
8193 			    trypos = NULL;
8194 			    if (find_last_paren(l, '(', ')'))
8195 				trypos = find_match_paren(
8196 						      curbuf->b_ind_maxparen);
8197 
8198 			    if (trypos == NULL && find_last_paren(l, '{', '}'))
8199 				trypos = find_start_brace();
8200 
8201 			    if (trypos != NULL)
8202 			    {
8203 				curwin->w_cursor.lnum = trypos->lnum + 1;
8204 				curwin->w_cursor.col = 0;
8205 				continue;
8206 			    }
8207 			}
8208 
8209 			/* it's a variable declaration, add indentation
8210 			 * like in
8211 			 * int a,
8212 			 *    b;
8213 			 */
8214 			if (cont_amount > 0)
8215 			    amount = cont_amount;
8216 			else
8217 			    amount += ind_continuation;
8218 		    }
8219 		    else if (lookfor == LOOKFOR_UNTERM)
8220 		    {
8221 			if (cont_amount > 0)
8222 			    amount = cont_amount;
8223 			else
8224 			    amount += ind_continuation;
8225 		    }
8226 		    else
8227 		    {
8228 			if (lookfor != LOOKFOR_TERM
8229 					&& lookfor != LOOKFOR_CPP_BASECLASS
8230 					&& lookfor != LOOKFOR_COMMA)
8231 			{
8232 			    amount = scope_amount;
8233 			    if (theline[0] == '{')
8234 			    {
8235 				amount += curbuf->b_ind_open_extra;
8236 				added_to_amount = curbuf->b_ind_open_extra;
8237 			    }
8238 			}
8239 
8240 			if (lookfor_cpp_namespace)
8241 			{
8242 			    /*
8243 			     * Looking for C++ namespace, need to look further
8244 			     * back.
8245 			     */
8246 			    if (curwin->w_cursor.lnum == ourscope)
8247 				continue;
8248 
8249 			    if (curwin->w_cursor.lnum == 0
8250 				    || curwin->w_cursor.lnum
8251 					      < ourscope - FIND_NAMESPACE_LIM)
8252 				break;
8253 
8254 			    l = ml_get_curline();
8255 
8256 			    /* If we're in a comment or raw string now, skip
8257 			     * to the start of it. */
8258 			    trypos = ind_find_start_CORS(NULL);
8259 			    if (trypos != NULL)
8260 			    {
8261 				curwin->w_cursor.lnum = trypos->lnum + 1;
8262 				curwin->w_cursor.col = 0;
8263 				continue;
8264 			    }
8265 
8266 			    /* Skip preprocessor directives and blank lines. */
8267 			    if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
8268 								    &amount))
8269 				continue;
8270 
8271 			    /* Finally the actual check for "namespace". */
8272 			    if (cin_is_cpp_namespace(l))
8273 			    {
8274 				amount += curbuf->b_ind_cpp_namespace
8275 							    - added_to_amount;
8276 				break;
8277 			    }
8278 			    else if (cin_is_cpp_extern_c(l))
8279 			    {
8280 				amount += curbuf->b_ind_cpp_extern_c
8281 							    - added_to_amount;
8282 				break;
8283 			    }
8284 
8285 			    if (cin_nocode(l))
8286 				continue;
8287 			}
8288 		    }
8289 		    break;
8290 		}
8291 
8292 		/*
8293 		 * If we're in a comment or raw string now, skip to the start
8294 		 * of it.
8295 		 */					    /* XXX */
8296 		if ((trypos = ind_find_start_CORS(&raw_string_start)) != NULL)
8297 		{
8298 		    curwin->w_cursor.lnum = trypos->lnum + 1;
8299 		    curwin->w_cursor.col = 0;
8300 		    continue;
8301 		}
8302 
8303 		l = ml_get_curline();
8304 
8305 		/*
8306 		 * If this is a switch() label, may line up relative to that.
8307 		 * If this is a C++ scope declaration, do the same.
8308 		 */
8309 		iscase = cin_iscase(l, FALSE);
8310 		if (iscase || cin_isscopedecl(l))
8311 		{
8312 		    /* we are only looking for cpp base class
8313 		     * declaration/initialization any longer */
8314 		    if (lookfor == LOOKFOR_CPP_BASECLASS)
8315 			break;
8316 
8317 		    /* When looking for a "do" we are not interested in
8318 		     * labels. */
8319 		    if (whilelevel > 0)
8320 			continue;
8321 
8322 		    /*
8323 		     *	case xx:
8324 		     *	    c = 99 +	    <- this indent plus continuation
8325 		     *->	   here;
8326 		     */
8327 		    if (lookfor == LOOKFOR_UNTERM
8328 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
8329 		    {
8330 			if (cont_amount > 0)
8331 			    amount = cont_amount;
8332 			else
8333 			    amount += ind_continuation;
8334 			break;
8335 		    }
8336 
8337 		    /*
8338 		     *	case xx:	<- line up with this case
8339 		     *	    x = 333;
8340 		     *	case yy:
8341 		     */
8342 		    if (       (iscase && lookfor == LOOKFOR_CASE)
8343 			    || (iscase && lookfor_break)
8344 			    || (!iscase && lookfor == LOOKFOR_SCOPEDECL))
8345 		    {
8346 			/*
8347 			 * Check that this case label is not for another
8348 			 * switch()
8349 			 */				    /* XXX */
8350 			if ((trypos = find_start_brace()) == NULL
8351 						  || trypos->lnum == ourscope)
8352 			{
8353 			    amount = get_indent();	/* XXX */
8354 			    break;
8355 			}
8356 			continue;
8357 		    }
8358 
8359 		    n = get_indent_nolabel(curwin->w_cursor.lnum);  /* XXX */
8360 
8361 		    /*
8362 		     *	 case xx: if (cond)	    <- line up with this if
8363 		     *		      y = y + 1;
8364 		     * ->	  s = 99;
8365 		     *
8366 		     *	 case xx:
8367 		     *	     if (cond)		<- line up with this line
8368 		     *		 y = y + 1;
8369 		     * ->    s = 99;
8370 		     */
8371 		    if (lookfor == LOOKFOR_TERM)
8372 		    {
8373 			if (n)
8374 			    amount = n;
8375 
8376 			if (!lookfor_break)
8377 			    break;
8378 		    }
8379 
8380 		    /*
8381 		     *	 case xx: x = x + 1;	    <- line up with this x
8382 		     * ->	  y = y + 1;
8383 		     *
8384 		     *	 case xx: if (cond)	    <- line up with this if
8385 		     * ->	       y = y + 1;
8386 		     */
8387 		    if (n)
8388 		    {
8389 			amount = n;
8390 			l = after_label(ml_get_curline());
8391 			if (l != NULL && cin_is_cinword(l))
8392 			{
8393 			    if (theline[0] == '{')
8394 				amount += curbuf->b_ind_open_extra;
8395 			    else
8396 				amount += curbuf->b_ind_level
8397 						     + curbuf->b_ind_no_brace;
8398 			}
8399 			break;
8400 		    }
8401 
8402 		    /*
8403 		     * Try to get the indent of a statement before the switch
8404 		     * label.  If nothing is found, line up relative to the
8405 		     * switch label.
8406 		     *	    break;		<- may line up with this line
8407 		     *	 case xx:
8408 		     * ->   y = 1;
8409 		     */
8410 		    scope_amount = get_indent() + (iscase    /* XXX */
8411 					? curbuf->b_ind_case_code
8412 					: curbuf->b_ind_scopedecl_code);
8413 		    lookfor = curbuf->b_ind_case_break
8414 					      ? LOOKFOR_NOBREAK : LOOKFOR_ANY;
8415 		    continue;
8416 		}
8417 
8418 		/*
8419 		 * Looking for a switch() label or C++ scope declaration,
8420 		 * ignore other lines, skip {}-blocks.
8421 		 */
8422 		if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL)
8423 		{
8424 		    if (find_last_paren(l, '{', '}')
8425 				     && (trypos = find_start_brace()) != NULL)
8426 		    {
8427 			curwin->w_cursor.lnum = trypos->lnum + 1;
8428 			curwin->w_cursor.col = 0;
8429 		    }
8430 		    continue;
8431 		}
8432 
8433 		/*
8434 		 * Ignore jump labels with nothing after them.
8435 		 */
8436 		if (!curbuf->b_ind_js && cin_islabel())
8437 		{
8438 		    l = after_label(ml_get_curline());
8439 		    if (l == NULL || cin_nocode(l))
8440 			continue;
8441 		}
8442 
8443 		/*
8444 		 * Ignore #defines, #if, etc.
8445 		 * Ignore comment and empty lines.
8446 		 * (need to get the line again, cin_islabel() may have
8447 		 * unlocked it)
8448 		 */
8449 		l = ml_get_curline();
8450 		if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
8451 							     || cin_nocode(l))
8452 		    continue;
8453 
8454 		/*
8455 		 * Are we at the start of a cpp base class declaration or
8456 		 * constructor initialization?
8457 		 */						    /* XXX */
8458 		n = FALSE;
8459 		if (lookfor != LOOKFOR_TERM && curbuf->b_ind_cpp_baseclass > 0)
8460 		{
8461 		    n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
8462 		    l = ml_get_curline();
8463 		}
8464 		if (n)
8465 		{
8466 		    if (lookfor == LOOKFOR_UNTERM)
8467 		    {
8468 			if (cont_amount > 0)
8469 			    amount = cont_amount;
8470 			else
8471 			    amount += ind_continuation;
8472 		    }
8473 		    else if (theline[0] == '{')
8474 		    {
8475 			/* Need to find start of the declaration. */
8476 			lookfor = LOOKFOR_UNTERM;
8477 			ind_continuation = 0;
8478 			continue;
8479 		    }
8480 		    else
8481 								     /* XXX */
8482 			amount = get_baseclass_amount(
8483 						cache_cpp_baseclass.lpos.col);
8484 		    break;
8485 		}
8486 		else if (lookfor == LOOKFOR_CPP_BASECLASS)
8487 		{
8488 		    /* only look, whether there is a cpp base class
8489 		     * declaration or initialization before the opening brace.
8490 		     */
8491 		    if (cin_isterminated(l, TRUE, FALSE))
8492 			break;
8493 		    else
8494 			continue;
8495 		}
8496 
8497 		/*
8498 		 * What happens next depends on the line being terminated.
8499 		 * If terminated with a ',' only consider it terminating if
8500 		 * there is another unterminated statement behind, eg:
8501 		 *   123,
8502 		 *   sizeof
8503 		 *	  here
8504 		 * Otherwise check whether it is a enumeration or structure
8505 		 * initialisation (not indented) or a variable declaration
8506 		 * (indented).
8507 		 */
8508 		terminated = cin_isterminated(l, FALSE, TRUE);
8509 
8510 		if (js_cur_has_key)
8511 		{
8512 		    js_cur_has_key = 0; /* only check the first line */
8513 		    if (curbuf->b_ind_js && terminated == ',')
8514 		    {
8515 			/* For Javascript we might be inside an object:
8516 			 *   key: something,  <- align with this
8517 			 *   key: something
8518 			 * or:
8519 			 *   key: something +  <- align with this
8520 			 *       something,
8521 			 *   key: something
8522 			 */
8523 			lookfor = LOOKFOR_JS_KEY;
8524 		    }
8525 		}
8526 		if (lookfor == LOOKFOR_JS_KEY && cin_has_js_key(l))
8527 		{
8528 		    amount = get_indent();
8529 		    break;
8530 		}
8531 		if (lookfor == LOOKFOR_COMMA)
8532 		{
8533 		    if (tryposBrace != NULL && tryposBrace->lnum
8534 						    >= curwin->w_cursor.lnum)
8535 			break;
8536 		    if (terminated == ',')
8537 			/* line below current line is the one that starts a
8538 			 * (possibly broken) line ending in a comma. */
8539 			break;
8540 		    else
8541 		    {
8542 			amount = get_indent();
8543 			if (curwin->w_cursor.lnum - 1 == ourscope)
8544 			    /* line above is start of the scope, thus current
8545 			     * line is the one that stars a (possibly broken)
8546 			     * line ending in a comma. */
8547 			    break;
8548 		    }
8549 		}
8550 
8551 		if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
8552 							&& terminated == ','))
8553 		{
8554 		    if (lookfor != LOOKFOR_ENUM_OR_INIT &&
8555 			    (*skipwhite(l) == '[' || l[STRLEN(l) - 1] == '['))
8556 			amount += ind_continuation;
8557 		    /*
8558 		     * if we're in the middle of a paren thing,
8559 		     * go back to the line that starts it so
8560 		     * we can get the right prevailing indent
8561 		     *	   if ( foo &&
8562 		     *		    bar )
8563 		     */
8564 		    /*
8565 		     * Position the cursor over the rightmost paren, so that
8566 		     * matching it will take us back to the start of the line.
8567 		     * Ignore a match before the start of the block.
8568 		     */
8569 		    (void)find_last_paren(l, '(', ')');
8570 		    trypos = find_match_paren(corr_ind_maxparen(&cur_curpos));
8571 		    if (trypos != NULL && (trypos->lnum < tryposBrace->lnum
8572 				|| (trypos->lnum == tryposBrace->lnum
8573 				    && trypos->col < tryposBrace->col)))
8574 			trypos = NULL;
8575 
8576 		    /*
8577 		     * If we are looking for ',', we also look for matching
8578 		     * braces.
8579 		     */
8580 		    if (trypos == NULL && terminated == ','
8581 					      && find_last_paren(l, '{', '}'))
8582 			trypos = find_start_brace();
8583 
8584 		    if (trypos != NULL)
8585 		    {
8586 			/*
8587 			 * Check if we are on a case label now.  This is
8588 			 * handled above.
8589 			 *     case xx:  if ( asdf &&
8590 			 *			asdf)
8591 			 */
8592 			curwin->w_cursor = *trypos;
8593 			l = ml_get_curline();
8594 			if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
8595 			{
8596 			    ++curwin->w_cursor.lnum;
8597 			    curwin->w_cursor.col = 0;
8598 			    continue;
8599 			}
8600 		    }
8601 
8602 		    /*
8603 		     * Skip over continuation lines to find the one to get the
8604 		     * indent from
8605 		     * char *usethis = "bla\
8606 		     *		 bla",
8607 		     *      here;
8608 		     */
8609 		    if (terminated == ',')
8610 		    {
8611 			while (curwin->w_cursor.lnum > 1)
8612 			{
8613 			    l = ml_get(curwin->w_cursor.lnum - 1);
8614 			    if (*l == NUL || l[STRLEN(l) - 1] != '\\')
8615 				break;
8616 			    --curwin->w_cursor.lnum;
8617 			    curwin->w_cursor.col = 0;
8618 			}
8619 		    }
8620 
8621 		    /*
8622 		     * Get indent and pointer to text for current line,
8623 		     * ignoring any jump label.	    XXX
8624 		     */
8625 		    if (curbuf->b_ind_js)
8626 			cur_amount = get_indent();
8627 		    else
8628 			cur_amount = skip_label(curwin->w_cursor.lnum, &l);
8629 		    /*
8630 		     * If this is just above the line we are indenting, and it
8631 		     * starts with a '{', line it up with this line.
8632 		     *		while (not)
8633 		     * ->	{
8634 		     *		}
8635 		     */
8636 		    if (terminated != ',' && lookfor != LOOKFOR_TERM
8637 							 && theline[0] == '{')
8638 		    {
8639 			amount = cur_amount;
8640 			/*
8641 			 * Only add b_ind_open_extra when the current line
8642 			 * doesn't start with a '{', which must have a match
8643 			 * in the same line (scope is the same).  Probably:
8644 			 *	{ 1, 2 },
8645 			 * ->	{ 3, 4 }
8646 			 */
8647 			if (*skipwhite(l) != '{')
8648 			    amount += curbuf->b_ind_open_extra;
8649 
8650 			if (curbuf->b_ind_cpp_baseclass && !curbuf->b_ind_js)
8651 			{
8652 			    /* have to look back, whether it is a cpp base
8653 			     * class declaration or initialization */
8654 			    lookfor = LOOKFOR_CPP_BASECLASS;
8655 			    continue;
8656 			}
8657 			break;
8658 		    }
8659 
8660 		    /*
8661 		     * Check if we are after an "if", "while", etc.
8662 		     * Also allow "   } else".
8663 		     */
8664 		    if (cin_is_cinword(l) || cin_iselse(skipwhite(l)))
8665 		    {
8666 			/*
8667 			 * Found an unterminated line after an if (), line up
8668 			 * with the last one.
8669 			 *   if (cond)
8670 			 *	    100 +
8671 			 * ->		here;
8672 			 */
8673 			if (lookfor == LOOKFOR_UNTERM
8674 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
8675 			{
8676 			    if (cont_amount > 0)
8677 				amount = cont_amount;
8678 			    else
8679 				amount += ind_continuation;
8680 			    break;
8681 			}
8682 
8683 			/*
8684 			 * If this is just above the line we are indenting, we
8685 			 * are finished.
8686 			 *	    while (not)
8687 			 * ->		here;
8688 			 * Otherwise this indent can be used when the line
8689 			 * before this is terminated.
8690 			 *	yyy;
8691 			 *	if (stat)
8692 			 *	    while (not)
8693 			 *		xxx;
8694 			 * ->	here;
8695 			 */
8696 			amount = cur_amount;
8697 			if (theline[0] == '{')
8698 			    amount += curbuf->b_ind_open_extra;
8699 			if (lookfor != LOOKFOR_TERM)
8700 			{
8701 			    amount += curbuf->b_ind_level
8702 						     + curbuf->b_ind_no_brace;
8703 			    break;
8704 			}
8705 
8706 			/*
8707 			 * Special trick: when expecting the while () after a
8708 			 * do, line up with the while()
8709 			 *     do
8710 			 *	    x = 1;
8711 			 * ->  here
8712 			 */
8713 			l = skipwhite(ml_get_curline());
8714 			if (cin_isdo(l))
8715 			{
8716 			    if (whilelevel == 0)
8717 				break;
8718 			    --whilelevel;
8719 			}
8720 
8721 			/*
8722 			 * When searching for a terminated line, don't use the
8723 			 * one between the "if" and the matching "else".
8724 			 * Need to use the scope of this "else".  XXX
8725 			 * If whilelevel != 0 continue looking for a "do {".
8726 			 */
8727 			if (cin_iselse(l) && whilelevel == 0)
8728 			{
8729 			    /* If we're looking at "} else", let's make sure we
8730 			     * find the opening brace of the enclosing scope,
8731 			     * not the one from "if () {". */
8732 			    if (*l == '}')
8733 				curwin->w_cursor.col =
8734 					  (colnr_T)(l - ml_get_curline()) + 1;
8735 
8736 			    if ((trypos = find_start_brace()) == NULL
8737 				       || find_match(LOOKFOR_IF, trypos->lnum)
8738 								      == FAIL)
8739 				break;
8740 			}
8741 		    }
8742 
8743 		    /*
8744 		     * If we're below an unterminated line that is not an
8745 		     * "if" or something, we may line up with this line or
8746 		     * add something for a continuation line, depending on
8747 		     * the line before this one.
8748 		     */
8749 		    else
8750 		    {
8751 			/*
8752 			 * Found two unterminated lines on a row, line up with
8753 			 * the last one.
8754 			 *   c = 99 +
8755 			 *	    100 +
8756 			 * ->	    here;
8757 			 */
8758 			if (lookfor == LOOKFOR_UNTERM)
8759 			{
8760 			    /* When line ends in a comma add extra indent */
8761 			    if (terminated == ',')
8762 				amount += ind_continuation;
8763 			    break;
8764 			}
8765 
8766 			if (lookfor == LOOKFOR_ENUM_OR_INIT)
8767 			{
8768 			    /* Found two lines ending in ',', lineup with the
8769 			     * lowest one, but check for cpp base class
8770 			     * declaration/initialization, if it is an
8771 			     * opening brace or we are looking just for
8772 			     * enumerations/initializations. */
8773 			    if (terminated == ',')
8774 			    {
8775 				if (curbuf->b_ind_cpp_baseclass == 0)
8776 				    break;
8777 
8778 				lookfor = LOOKFOR_CPP_BASECLASS;
8779 				continue;
8780 			    }
8781 
8782 			    /* Ignore unterminated lines in between, but
8783 			     * reduce indent. */
8784 			    if (amount > cur_amount)
8785 				amount = cur_amount;
8786 			}
8787 			else
8788 			{
8789 			    /*
8790 			     * Found first unterminated line on a row, may
8791 			     * line up with this line, remember its indent
8792 			     *	    100 +
8793 			     * ->	    here;
8794 			     */
8795 			    l = ml_get_curline();
8796 			    amount = cur_amount;
8797 
8798 			    n = (int)STRLEN(l);
8799 			    if (terminated == ',' && (*skipwhite(l) == ']'
8800 					|| (n >=2 && l[n - 2] == ']')))
8801 				break;
8802 
8803 			    /*
8804 			     * If previous line ends in ',', check whether we
8805 			     * are in an initialization or enum
8806 			     * struct xxx =
8807 			     * {
8808 			     *      sizeof a,
8809 			     *      124 };
8810 			     * or a normal possible continuation line.
8811 			     * but only, of no other statement has been found
8812 			     * yet.
8813 			     */
8814 			    if (lookfor == LOOKFOR_INITIAL && terminated == ',')
8815 			    {
8816 				if (curbuf->b_ind_js)
8817 				{
8818 				    /* Search for a line ending in a comma
8819 				     * and line up with the line below it
8820 				     * (could be the current line).
8821 				     * some = [
8822 				     *     1,     <- line up here
8823 				     *     2,
8824 				     * some = [
8825 				     *     3 +    <- line up here
8826 				     *       4 *
8827 				     *        5,
8828 				     *     6,
8829 				     */
8830 				    if (cin_iscomment(skipwhite(l)))
8831 					break;
8832 				    lookfor = LOOKFOR_COMMA;
8833 				    trypos = find_match_char('[',
8834 						      curbuf->b_ind_maxparen);
8835 				    if (trypos != NULL)
8836 				    {
8837 					if (trypos->lnum
8838 						 == curwin->w_cursor.lnum - 1)
8839 					{
8840 					    /* Current line is first inside
8841 					     * [], line up with it. */
8842 					    break;
8843 					}
8844 					ourscope = trypos->lnum;
8845 				    }
8846 				}
8847 				else
8848 				{
8849 				    lookfor = LOOKFOR_ENUM_OR_INIT;
8850 				    cont_amount = cin_first_id_amount();
8851 				}
8852 			    }
8853 			    else
8854 			    {
8855 				if (lookfor == LOOKFOR_INITIAL
8856 					&& *l != NUL
8857 					&& l[STRLEN(l) - 1] == '\\')
8858 								/* XXX */
8859 				    cont_amount = cin_get_equal_amount(
8860 						       curwin->w_cursor.lnum);
8861 				if (lookfor != LOOKFOR_TERM
8862 						&& lookfor != LOOKFOR_JS_KEY
8863 						&& lookfor != LOOKFOR_COMMA
8864 						&& raw_string_start != curwin->w_cursor.lnum)
8865 				    lookfor = LOOKFOR_UNTERM;
8866 			    }
8867 			}
8868 		    }
8869 		}
8870 
8871 		/*
8872 		 * Check if we are after a while (cond);
8873 		 * If so: Ignore until the matching "do".
8874 		 */
8875 		else if (cin_iswhileofdo_end(terminated)) /* XXX */
8876 		{
8877 		    /*
8878 		     * Found an unterminated line after a while ();, line up
8879 		     * with the last one.
8880 		     *	    while (cond);
8881 		     *	    100 +		<- line up with this one
8882 		     * ->	    here;
8883 		     */
8884 		    if (lookfor == LOOKFOR_UNTERM
8885 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
8886 		    {
8887 			if (cont_amount > 0)
8888 			    amount = cont_amount;
8889 			else
8890 			    amount += ind_continuation;
8891 			break;
8892 		    }
8893 
8894 		    if (whilelevel == 0)
8895 		    {
8896 			lookfor = LOOKFOR_TERM;
8897 			amount = get_indent();	    /* XXX */
8898 			if (theline[0] == '{')
8899 			    amount += curbuf->b_ind_open_extra;
8900 		    }
8901 		    ++whilelevel;
8902 		}
8903 
8904 		/*
8905 		 * We are after a "normal" statement.
8906 		 * If we had another statement we can stop now and use the
8907 		 * indent of that other statement.
8908 		 * Otherwise the indent of the current statement may be used,
8909 		 * search backwards for the next "normal" statement.
8910 		 */
8911 		else
8912 		{
8913 		    /*
8914 		     * Skip single break line, if before a switch label. It
8915 		     * may be lined up with the case label.
8916 		     */
8917 		    if (lookfor == LOOKFOR_NOBREAK
8918 				  && cin_isbreak(skipwhite(ml_get_curline())))
8919 		    {
8920 			lookfor = LOOKFOR_ANY;
8921 			continue;
8922 		    }
8923 
8924 		    /*
8925 		     * Handle "do {" line.
8926 		     */
8927 		    if (whilelevel > 0)
8928 		    {
8929 			l = cin_skipcomment(ml_get_curline());
8930 			if (cin_isdo(l))
8931 			{
8932 			    amount = get_indent();	/* XXX */
8933 			    --whilelevel;
8934 			    continue;
8935 			}
8936 		    }
8937 
8938 		    /*
8939 		     * Found a terminated line above an unterminated line. Add
8940 		     * the amount for a continuation line.
8941 		     *	 x = 1;
8942 		     *	 y = foo +
8943 		     * ->	here;
8944 		     * or
8945 		     *	 int x = 1;
8946 		     *	 int foo,
8947 		     * ->	here;
8948 		     */
8949 		    if (lookfor == LOOKFOR_UNTERM
8950 					   || lookfor == LOOKFOR_ENUM_OR_INIT)
8951 		    {
8952 			if (cont_amount > 0)
8953 			    amount = cont_amount;
8954 			else
8955 			    amount += ind_continuation;
8956 			break;
8957 		    }
8958 
8959 		    /*
8960 		     * Found a terminated line above a terminated line or "if"
8961 		     * etc. line. Use the amount of the line below us.
8962 		     *	 x = 1;				x = 1;
8963 		     *	 if (asdf)		    y = 2;
8964 		     *	     while (asdf)	  ->here;
8965 		     *		here;
8966 		     * ->foo;
8967 		     */
8968 		    if (lookfor == LOOKFOR_TERM)
8969 		    {
8970 			if (!lookfor_break && whilelevel == 0)
8971 			    break;
8972 		    }
8973 
8974 		    /*
8975 		     * First line above the one we're indenting is terminated.
8976 		     * To know what needs to be done look further backward for
8977 		     * a terminated line.
8978 		     */
8979 		    else
8980 		    {
8981 			/*
8982 			 * position the cursor over the rightmost paren, so
8983 			 * that matching it will take us back to the start of
8984 			 * the line.  Helps for:
8985 			 *     func(asdr,
8986 			 *	      asdfasdf);
8987 			 *     here;
8988 			 */
8989 term_again:
8990 			l = ml_get_curline();
8991 			if (find_last_paren(l, '(', ')')
8992 				&& (trypos = find_match_paren(
8993 					   curbuf->b_ind_maxparen)) != NULL)
8994 			{
8995 			    /*
8996 			     * Check if we are on a case label now.  This is
8997 			     * handled above.
8998 			     *	   case xx:  if ( asdf &&
8999 			     *			    asdf)
9000 			     */
9001 			    curwin->w_cursor = *trypos;
9002 			    l = ml_get_curline();
9003 			    if (cin_iscase(l, FALSE) || cin_isscopedecl(l))
9004 			    {
9005 				++curwin->w_cursor.lnum;
9006 				curwin->w_cursor.col = 0;
9007 				continue;
9008 			    }
9009 			}
9010 
9011 			/* When aligning with the case statement, don't align
9012 			 * with a statement after it.
9013 			 *  case 1: {   <-- don't use this { position
9014 			 *	stat;
9015 			 *  }
9016 			 *  case 2:
9017 			 *	stat;
9018 			 * }
9019 			 */
9020 			iscase = (curbuf->b_ind_keep_case_label
9021 						     && cin_iscase(l, FALSE));
9022 
9023 			/*
9024 			 * Get indent and pointer to text for current line,
9025 			 * ignoring any jump label.
9026 			 */
9027 			amount = skip_label(curwin->w_cursor.lnum, &l);
9028 
9029 			if (theline[0] == '{')
9030 			    amount += curbuf->b_ind_open_extra;
9031 			/* See remark above: "Only add b_ind_open_extra.." */
9032 			l = skipwhite(l);
9033 			if (*l == '{')
9034 			    amount -= curbuf->b_ind_open_extra;
9035 			lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
9036 
9037 			/*
9038 			 * When a terminated line starts with "else" skip to
9039 			 * the matching "if":
9040 			 *       else 3;
9041 			 *	     indent this;
9042 			 * Need to use the scope of this "else".  XXX
9043 			 * If whilelevel != 0 continue looking for a "do {".
9044 			 */
9045 			if (lookfor == LOOKFOR_TERM
9046 				&& *l != '}'
9047 				&& cin_iselse(l)
9048 				&& whilelevel == 0)
9049 			{
9050 			    if ((trypos = find_start_brace()) == NULL
9051 				       || find_match(LOOKFOR_IF, trypos->lnum)
9052 								      == FAIL)
9053 				break;
9054 			    continue;
9055 			}
9056 
9057 			/*
9058 			 * If we're at the end of a block, skip to the start of
9059 			 * that block.
9060 			 */
9061 			l = ml_get_curline();
9062 			if (find_last_paren(l, '{', '}') /* XXX */
9063 				     && (trypos = find_start_brace()) != NULL)
9064 			{
9065 			    curwin->w_cursor = *trypos;
9066 			    /* if not "else {" check for terminated again */
9067 			    /* but skip block for "} else {" */
9068 			    l = cin_skipcomment(ml_get_curline());
9069 			    if (*l == '}' || !cin_iselse(l))
9070 				goto term_again;
9071 			    ++curwin->w_cursor.lnum;
9072 			    curwin->w_cursor.col = 0;
9073 			}
9074 		    }
9075 		}
9076 	    }
9077 	}
9078       }
9079 
9080       /* add extra indent for a comment */
9081       if (cin_iscomment(theline))
9082 	  amount += curbuf->b_ind_comment;
9083 
9084       /* subtract extra left-shift for jump labels */
9085       if (curbuf->b_ind_jump_label > 0 && original_line_islabel)
9086 	  amount -= curbuf->b_ind_jump_label;
9087 
9088       goto theend;
9089     }
9090 
9091     /*
9092      * ok -- we're not inside any sort of structure at all!
9093      *
9094      * This means we're at the top level, and everything should
9095      * basically just match where the previous line is, except
9096      * for the lines immediately following a function declaration,
9097      * which are K&R-style parameters and need to be indented.
9098      *
9099      * if our line starts with an open brace, forget about any
9100      * prevailing indent and make sure it looks like the start
9101      * of a function
9102      */
9103 
9104     if (theline[0] == '{')
9105     {
9106 	amount = curbuf->b_ind_first_open;
9107 	goto theend;
9108     }
9109 
9110     /*
9111      * If the NEXT line is a function declaration, the current
9112      * line needs to be indented as a function type spec.
9113      * Don't do this if the current line looks like a comment or if the
9114      * current line is terminated, ie. ends in ';', or if the current line
9115      * contains { or }: "void f() {\n if (1)"
9116      */
9117     if (cur_curpos.lnum < curbuf->b_ml.ml_line_count
9118 	    && !cin_nocode(theline)
9119 	    && vim_strchr(theline, '{') == NULL
9120 	    && vim_strchr(theline, '}') == NULL
9121 	    && !cin_ends_in(theline, (char_u *)":", NULL)
9122 	    && !cin_ends_in(theline, (char_u *)",", NULL)
9123 	    && cin_isfuncdecl(NULL, cur_curpos.lnum + 1,
9124 			      cur_curpos.lnum + 1)
9125 	    && !cin_isterminated(theline, FALSE, TRUE))
9126     {
9127 	amount = curbuf->b_ind_func_type;
9128 	goto theend;
9129     }
9130 
9131     /* search backwards until we find something we recognize */
9132     amount = 0;
9133     curwin->w_cursor = cur_curpos;
9134     while (curwin->w_cursor.lnum > 1)
9135     {
9136 	curwin->w_cursor.lnum--;
9137 	curwin->w_cursor.col = 0;
9138 
9139 	l = ml_get_curline();
9140 
9141 	/*
9142 	 * If we're in a comment or raw string now, skip to the start
9143 	 * of it.
9144 	 */						/* XXX */
9145 	if ((trypos = ind_find_start_CORS(NULL)) != NULL)
9146 	{
9147 	    curwin->w_cursor.lnum = trypos->lnum + 1;
9148 	    curwin->w_cursor.col = 0;
9149 	    continue;
9150 	}
9151 
9152 	/*
9153 	 * Are we at the start of a cpp base class declaration or
9154 	 * constructor initialization?
9155 	 */						    /* XXX */
9156 	n = FALSE;
9157 	if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{')
9158 	{
9159 	    n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
9160 	    l = ml_get_curline();
9161 	}
9162 	if (n)
9163 	{
9164 							     /* XXX */
9165 	    amount = get_baseclass_amount(cache_cpp_baseclass.lpos.col);
9166 	    break;
9167 	}
9168 
9169 	/*
9170 	 * Skip preprocessor directives and blank lines.
9171 	 */
9172 	if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount))
9173 	    continue;
9174 
9175 	if (cin_nocode(l))
9176 	    continue;
9177 
9178 	/*
9179 	 * If the previous line ends in ',', use one level of
9180 	 * indentation:
9181 	 * int foo,
9182 	 *     bar;
9183 	 * do this before checking for '}' in case of eg.
9184 	 * enum foobar
9185 	 * {
9186 	 *   ...
9187 	 * } foo,
9188 	 *   bar;
9189 	 */
9190 	n = 0;
9191 	if (cin_ends_in(l, (char_u *)",", NULL)
9192 		     || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
9193 	{
9194 	    /* take us back to opening paren */
9195 	    if (find_last_paren(l, '(', ')')
9196 		    && (trypos = find_match_paren(
9197 				     curbuf->b_ind_maxparen)) != NULL)
9198 		curwin->w_cursor = *trypos;
9199 
9200 	    /* For a line ending in ',' that is a continuation line go
9201 	     * back to the first line with a backslash:
9202 	     * char *foo = "bla\
9203 	     *		 bla",
9204 	     *      here;
9205 	     */
9206 	    while (n == 0 && curwin->w_cursor.lnum > 1)
9207 	    {
9208 		l = ml_get(curwin->w_cursor.lnum - 1);
9209 		if (*l == NUL || l[STRLEN(l) - 1] != '\\')
9210 		    break;
9211 		--curwin->w_cursor.lnum;
9212 		curwin->w_cursor.col = 0;
9213 	    }
9214 
9215 	    amount = get_indent();	    /* XXX */
9216 
9217 	    if (amount == 0)
9218 		amount = cin_first_id_amount();
9219 	    if (amount == 0)
9220 		amount = ind_continuation;
9221 	    break;
9222 	}
9223 
9224 	/*
9225 	 * If the line looks like a function declaration, and we're
9226 	 * not in a comment, put it the left margin.
9227 	 */
9228 	if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0))  /* XXX */
9229 	    break;
9230 	l = ml_get_curline();
9231 
9232 	/*
9233 	 * Finding the closing '}' of a previous function.  Put
9234 	 * current line at the left margin.  For when 'cino' has "fs".
9235 	 */
9236 	if (*skipwhite(l) == '}')
9237 	    break;
9238 
9239 	/*			    (matching {)
9240 	 * If the previous line ends on '};' (maybe followed by
9241 	 * comments) align at column 0.  For example:
9242 	 * char *string_array[] = { "foo",
9243 	 *     / * x * / "b};ar" }; / * foobar * /
9244 	 */
9245 	if (cin_ends_in(l, (char_u *)"};", NULL))
9246 	    break;
9247 
9248 	/*
9249 	 * If the previous line ends on '[' we are probably in an
9250 	 * array constant:
9251 	 * something = [
9252 	 *     234,  <- extra indent
9253 	 */
9254 	if (cin_ends_in(l, (char_u *)"[", NULL))
9255 	{
9256 	    amount = get_indent() + ind_continuation;
9257 	    break;
9258 	}
9259 
9260 	/*
9261 	 * Find a line only has a semicolon that belongs to a previous
9262 	 * line ending in '}', e.g. before an #endif.  Don't increase
9263 	 * indent then.
9264 	 */
9265 	if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1))
9266 	{
9267 	    pos_T curpos_save = curwin->w_cursor;
9268 
9269 	    while (curwin->w_cursor.lnum > 1)
9270 	    {
9271 		look = ml_get(--curwin->w_cursor.lnum);
9272 		if (!(cin_nocode(look) || cin_ispreproc_cont(
9273 				      &look, &curwin->w_cursor.lnum, &amount)))
9274 		    break;
9275 	    }
9276 	    if (curwin->w_cursor.lnum > 0
9277 			    && cin_ends_in(look, (char_u *)"}", NULL))
9278 		break;
9279 
9280 	    curwin->w_cursor = curpos_save;
9281 	}
9282 
9283 	/*
9284 	 * If the PREVIOUS line is a function declaration, the current
9285 	 * line (and the ones that follow) needs to be indented as
9286 	 * parameters.
9287 	 */
9288 	if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0))
9289 	{
9290 	    amount = curbuf->b_ind_param;
9291 	    break;
9292 	}
9293 
9294 	/*
9295 	 * If the previous line ends in ';' and the line before the
9296 	 * previous line ends in ',' or '\', ident to column zero:
9297 	 * int foo,
9298 	 *     bar;
9299 	 * indent_to_0 here;
9300 	 */
9301 	if (cin_ends_in(l, (char_u *)";", NULL))
9302 	{
9303 	    l = ml_get(curwin->w_cursor.lnum - 1);
9304 	    if (cin_ends_in(l, (char_u *)",", NULL)
9305 		    || (*l != NUL && l[STRLEN(l) - 1] == '\\'))
9306 		break;
9307 	    l = ml_get_curline();
9308 	}
9309 
9310 	/*
9311 	 * Doesn't look like anything interesting -- so just
9312 	 * use the indent of this line.
9313 	 *
9314 	 * Position the cursor over the rightmost paren, so that
9315 	 * matching it will take us back to the start of the line.
9316 	 */
9317 	find_last_paren(l, '(', ')');
9318 
9319 	if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
9320 	    curwin->w_cursor = *trypos;
9321 	amount = get_indent();	    /* XXX */
9322 	break;
9323     }
9324 
9325     /* add extra indent for a comment */
9326     if (cin_iscomment(theline))
9327 	amount += curbuf->b_ind_comment;
9328 
9329     /* add extra indent if the previous line ended in a backslash:
9330      *	      "asdfasdf\
9331      *		  here";
9332      *	    char *foo = "asdf\
9333      *			 here";
9334      */
9335     if (cur_curpos.lnum > 1)
9336     {
9337 	l = ml_get(cur_curpos.lnum - 1);
9338 	if (*l != NUL && l[STRLEN(l) - 1] == '\\')
9339 	{
9340 	    cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
9341 	    if (cur_amount > 0)
9342 		amount = cur_amount;
9343 	    else if (cur_amount == 0)
9344 		amount += ind_continuation;
9345 	}
9346     }
9347 
9348 theend:
9349     if (amount < 0)
9350 	amount = 0;
9351 
9352 laterend:
9353     /* put the cursor back where it belongs */
9354     curwin->w_cursor = cur_curpos;
9355 
9356     vim_free(linecopy);
9357 
9358     return amount;
9359 }
9360 
9361     static int
9362 find_match(int lookfor, linenr_T ourscope)
9363 {
9364     char_u	*look;
9365     pos_T	*theirscope;
9366     char_u	*mightbeif;
9367     int		elselevel;
9368     int		whilelevel;
9369 
9370     if (lookfor == LOOKFOR_IF)
9371     {
9372 	elselevel = 1;
9373 	whilelevel = 0;
9374     }
9375     else
9376     {
9377 	elselevel = 0;
9378 	whilelevel = 1;
9379     }
9380 
9381     curwin->w_cursor.col = 0;
9382 
9383     while (curwin->w_cursor.lnum > ourscope + 1)
9384     {
9385 	curwin->w_cursor.lnum--;
9386 	curwin->w_cursor.col = 0;
9387 
9388 	look = cin_skipcomment(ml_get_curline());
9389 	if (cin_iselse(look)
9390 		|| cin_isif(look)
9391 		|| cin_isdo(look)			    /* XXX */
9392 		|| cin_iswhileofdo(look, curwin->w_cursor.lnum))
9393 	{
9394 	    /*
9395 	     * if we've gone outside the braces entirely,
9396 	     * we must be out of scope...
9397 	     */
9398 	    theirscope = find_start_brace();  /* XXX */
9399 	    if (theirscope == NULL)
9400 		break;
9401 
9402 	    /*
9403 	     * and if the brace enclosing this is further
9404 	     * back than the one enclosing the else, we're
9405 	     * out of luck too.
9406 	     */
9407 	    if (theirscope->lnum < ourscope)
9408 		break;
9409 
9410 	    /*
9411 	     * and if they're enclosed in a *deeper* brace,
9412 	     * then we can ignore it because it's in a
9413 	     * different scope...
9414 	     */
9415 	    if (theirscope->lnum > ourscope)
9416 		continue;
9417 
9418 	    /*
9419 	     * if it was an "else" (that's not an "else if")
9420 	     * then we need to go back to another if, so
9421 	     * increment elselevel
9422 	     */
9423 	    look = cin_skipcomment(ml_get_curline());
9424 	    if (cin_iselse(look))
9425 	    {
9426 		mightbeif = cin_skipcomment(look + 4);
9427 		if (!cin_isif(mightbeif))
9428 		    ++elselevel;
9429 		continue;
9430 	    }
9431 
9432 	    /*
9433 	     * if it was a "while" then we need to go back to
9434 	     * another "do", so increment whilelevel.  XXX
9435 	     */
9436 	    if (cin_iswhileofdo(look, curwin->w_cursor.lnum))
9437 	    {
9438 		++whilelevel;
9439 		continue;
9440 	    }
9441 
9442 	    /* If it's an "if" decrement elselevel */
9443 	    look = cin_skipcomment(ml_get_curline());
9444 	    if (cin_isif(look))
9445 	    {
9446 		elselevel--;
9447 		/*
9448 		 * When looking for an "if" ignore "while"s that
9449 		 * get in the way.
9450 		 */
9451 		if (elselevel == 0 && lookfor == LOOKFOR_IF)
9452 		    whilelevel = 0;
9453 	    }
9454 
9455 	    /* If it's a "do" decrement whilelevel */
9456 	    if (cin_isdo(look))
9457 		whilelevel--;
9458 
9459 	    /*
9460 	     * if we've used up all the elses, then
9461 	     * this must be the if that we want!
9462 	     * match the indent level of that if.
9463 	     */
9464 	    if (elselevel <= 0 && whilelevel <= 0)
9465 	    {
9466 		return OK;
9467 	    }
9468 	}
9469     }
9470     return FAIL;
9471 }
9472 
9473 # if defined(FEAT_EVAL) || defined(PROTO)
9474 /*
9475  * Get indent level from 'indentexpr'.
9476  */
9477     int
9478 get_expr_indent(void)
9479 {
9480     int		indent = -1;
9481     char_u	*inde_copy;
9482     pos_T	save_pos;
9483     colnr_T	save_curswant;
9484     int		save_set_curswant;
9485     int		save_State;
9486     int		use_sandbox = was_set_insecurely((char_u *)"indentexpr",
9487 								   OPT_LOCAL);
9488 
9489     /* Save and restore cursor position and curswant, in case it was changed
9490      * via :normal commands */
9491     save_pos = curwin->w_cursor;
9492     save_curswant = curwin->w_curswant;
9493     save_set_curswant = curwin->w_set_curswant;
9494     set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
9495     if (use_sandbox)
9496 	++sandbox;
9497     ++textlock;
9498 
9499     /* Need to make a copy, the 'indentexpr' option could be changed while
9500      * evaluating it. */
9501     inde_copy = vim_strsave(curbuf->b_p_inde);
9502     if (inde_copy != NULL)
9503     {
9504 	indent = (int)eval_to_number(inde_copy);
9505 	vim_free(inde_copy);
9506     }
9507 
9508     if (use_sandbox)
9509 	--sandbox;
9510     --textlock;
9511 
9512     /* Restore the cursor position so that 'indentexpr' doesn't need to.
9513      * Pretend to be in Insert mode, allow cursor past end of line for "o"
9514      * command. */
9515     save_State = State;
9516     State = INSERT;
9517     curwin->w_cursor = save_pos;
9518     curwin->w_curswant = save_curswant;
9519     curwin->w_set_curswant = save_set_curswant;
9520     check_cursor();
9521     State = save_State;
9522 
9523     /* If there is an error, just keep the current indent. */
9524     if (indent < 0)
9525 	indent = get_indent();
9526 
9527     return indent;
9528 }
9529 # endif
9530 
9531 #endif /* FEAT_CINDENT */
9532 
9533 #if defined(FEAT_LISP) || defined(PROTO)
9534 
9535 static int lisp_match(char_u *p);
9536 
9537     static int
9538 lisp_match(char_u *p)
9539 {
9540     char_u	buf[LSIZE];
9541     int		len;
9542     char_u	*word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
9543 
9544     while (*word != NUL)
9545     {
9546 	(void)copy_option_part(&word, buf, LSIZE, ",");
9547 	len = (int)STRLEN(buf);
9548 	if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
9549 	    return TRUE;
9550     }
9551     return FALSE;
9552 }
9553 
9554 /*
9555  * When 'p' is present in 'cpoptions, a Vi compatible method is used.
9556  * The incompatible newer method is quite a bit better at indenting
9557  * code in lisp-like languages than the traditional one; it's still
9558  * mostly heuristics however -- Dirk van Deun, [email protected]
9559  *
9560  * TODO:
9561  * Findmatch() should be adapted for lisp, also to make showmatch
9562  * work correctly: now (v5.3) it seems all C/C++ oriented:
9563  * - it does not recognize the #\( and #\) notations as character literals
9564  * - it doesn't know about comments starting with a semicolon
9565  * - it incorrectly interprets '(' as a character literal
9566  * All this messes up get_lisp_indent in some rare cases.
9567  * Update from Sergey Khorev:
9568  * I tried to fix the first two issues.
9569  */
9570     int
9571 get_lisp_indent(void)
9572 {
9573     pos_T	*pos, realpos, paren;
9574     int		amount;
9575     char_u	*that;
9576     colnr_T	col;
9577     colnr_T	firsttry;
9578     int		parencount, quotecount;
9579     int		vi_lisp;
9580 
9581     /* Set vi_lisp to use the vi-compatible method */
9582     vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
9583 
9584     realpos = curwin->w_cursor;
9585     curwin->w_cursor.col = 0;
9586 
9587     if ((pos = findmatch(NULL, '(')) == NULL)
9588 	pos = findmatch(NULL, '[');
9589     else
9590     {
9591 	paren = *pos;
9592 	pos = findmatch(NULL, '[');
9593 	if (pos == NULL || LT_POSP(pos, &paren))
9594 	    pos = &paren;
9595     }
9596     if (pos != NULL)
9597     {
9598 	/* Extra trick: Take the indent of the first previous non-white
9599 	 * line that is at the same () level. */
9600 	amount = -1;
9601 	parencount = 0;
9602 
9603 	while (--curwin->w_cursor.lnum >= pos->lnum)
9604 	{
9605 	    if (linewhite(curwin->w_cursor.lnum))
9606 		continue;
9607 	    for (that = ml_get_curline(); *that != NUL; ++that)
9608 	    {
9609 		if (*that == ';')
9610 		{
9611 		    while (*(that + 1) != NUL)
9612 			++that;
9613 		    continue;
9614 		}
9615 		if (*that == '\\')
9616 		{
9617 		    if (*(that + 1) != NUL)
9618 			++that;
9619 		    continue;
9620 		}
9621 		if (*that == '"' && *(that + 1) != NUL)
9622 		{
9623 		    while (*++that && *that != '"')
9624 		    {
9625 			/* skipping escaped characters in the string */
9626 			if (*that == '\\')
9627 			{
9628 			    if (*++that == NUL)
9629 				break;
9630 			    if (that[1] == NUL)
9631 			    {
9632 				++that;
9633 				break;
9634 			    }
9635 			}
9636 		    }
9637 		}
9638 		if (*that == '(' || *that == '[')
9639 		    ++parencount;
9640 		else if (*that == ')' || *that == ']')
9641 		    --parencount;
9642 	    }
9643 	    if (parencount == 0)
9644 	    {
9645 		amount = get_indent();
9646 		break;
9647 	    }
9648 	}
9649 
9650 	if (amount == -1)
9651 	{
9652 	    curwin->w_cursor.lnum = pos->lnum;
9653 	    curwin->w_cursor.col = pos->col;
9654 	    col = pos->col;
9655 
9656 	    that = ml_get_curline();
9657 
9658 	    if (vi_lisp && get_indent() == 0)
9659 		amount = 2;
9660 	    else
9661 	    {
9662 		char_u *line = that;
9663 
9664 		amount = 0;
9665 		while (*that && col)
9666 		{
9667 		    amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
9668 		    col--;
9669 		}
9670 
9671 		/*
9672 		 * Some keywords require "body" indenting rules (the
9673 		 * non-standard-lisp ones are Scheme special forms):
9674 		 *
9675 		 * (let ((a 1))    instead    (let ((a 1))
9676 		 *   (...))	      of	   (...))
9677 		 */
9678 
9679 		if (!vi_lisp && (*that == '(' || *that == '[')
9680 						      && lisp_match(that + 1))
9681 		    amount += 2;
9682 		else
9683 		{
9684 		    that++;
9685 		    amount++;
9686 		    firsttry = amount;
9687 
9688 		    while (VIM_ISWHITE(*that))
9689 		    {
9690 			amount += lbr_chartabsize(line, that, (colnr_T)amount);
9691 			++that;
9692 		    }
9693 
9694 		    if (*that && *that != ';') /* not a comment line */
9695 		    {
9696 			/* test *that != '(' to accommodate first let/do
9697 			 * argument if it is more than one line */
9698 			if (!vi_lisp && *that != '(' && *that != '[')
9699 			    firsttry++;
9700 
9701 			parencount = 0;
9702 			quotecount = 0;
9703 
9704 			if (vi_lisp
9705 				|| (*that != '"'
9706 				    && *that != '\''
9707 				    && *that != '#'
9708 				    && (*that < '0' || *that > '9')))
9709 			{
9710 			    while (*that
9711 				    && (!VIM_ISWHITE(*that)
9712 					|| quotecount
9713 					|| parencount)
9714 				    && (!((*that == '(' || *that == '[')
9715 					    && !quotecount
9716 					    && !parencount
9717 					    && vi_lisp)))
9718 			    {
9719 				if (*that == '"')
9720 				    quotecount = !quotecount;
9721 				if ((*that == '(' || *that == '[')
9722 							       && !quotecount)
9723 				    ++parencount;
9724 				if ((*that == ')' || *that == ']')
9725 							       && !quotecount)
9726 				    --parencount;
9727 				if (*that == '\\' && *(that+1) != NUL)
9728 				    amount += lbr_chartabsize_adv(
9729 						line, &that, (colnr_T)amount);
9730 				amount += lbr_chartabsize_adv(
9731 						line, &that, (colnr_T)amount);
9732 			    }
9733 			}
9734 			while (VIM_ISWHITE(*that))
9735 			{
9736 			    amount += lbr_chartabsize(
9737 						 line, that, (colnr_T)amount);
9738 			    that++;
9739 			}
9740 			if (!*that || *that == ';')
9741 			    amount = firsttry;
9742 		    }
9743 		}
9744 	    }
9745 	}
9746     }
9747     else
9748 	amount = 0;	/* no matching '(' or '[' found, use zero indent */
9749 
9750     curwin->w_cursor = realpos;
9751 
9752     return amount;
9753 }
9754 #endif /* FEAT_LISP */
9755 
9756     void
9757 prepare_to_exit(void)
9758 {
9759 #if defined(SIGHUP) && defined(SIG_IGN)
9760     /* Ignore SIGHUP, because a dropped connection causes a read error, which
9761      * makes Vim exit and then handling SIGHUP causes various reentrance
9762      * problems. */
9763     signal(SIGHUP, SIG_IGN);
9764 #endif
9765 
9766 #ifdef FEAT_GUI
9767     if (gui.in_use)
9768     {
9769 	gui.dying = TRUE;
9770 	out_trash();	/* trash any pending output */
9771     }
9772     else
9773 #endif
9774     {
9775 	windgoto((int)Rows - 1, 0);
9776 
9777 	/*
9778 	 * Switch terminal mode back now, so messages end up on the "normal"
9779 	 * screen (if there are two screens).
9780 	 */
9781 	settmode(TMODE_COOK);
9782 	stoptermcap();
9783 	out_flush();
9784     }
9785 }
9786 
9787 /*
9788  * Preserve files and exit.
9789  * When called IObuff must contain a message.
9790  * NOTE: This may be called from deathtrap() in a signal handler, avoid unsafe
9791  * functions, such as allocating memory.
9792  */
9793     void
9794 preserve_exit(void)
9795 {
9796     buf_T	*buf;
9797 
9798     prepare_to_exit();
9799 
9800     /* Setting this will prevent free() calls.  That avoids calling free()
9801      * recursively when free() was invoked with a bad pointer. */
9802     really_exiting = TRUE;
9803 
9804     out_str(IObuff);
9805     screen_start();		    /* don't know where cursor is now */
9806     out_flush();
9807 
9808     ml_close_notmod();		    /* close all not-modified buffers */
9809 
9810     FOR_ALL_BUFFERS(buf)
9811     {
9812 	if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL)
9813 	{
9814 	    OUT_STR("Vim: preserving files...\n");
9815 	    screen_start();	    /* don't know where cursor is now */
9816 	    out_flush();
9817 	    ml_sync_all(FALSE, FALSE);	/* preserve all swap files */
9818 	    break;
9819 	}
9820     }
9821 
9822     ml_close_all(FALSE);	    /* close all memfiles, without deleting */
9823 
9824     OUT_STR("Vim: Finished.\n");
9825 
9826     getout(1);
9827 }
9828 
9829 /*
9830  * return TRUE if "fname" exists.
9831  */
9832     int
9833 vim_fexists(char_u *fname)
9834 {
9835     stat_T st;
9836 
9837     if (mch_stat((char *)fname, &st))
9838 	return FALSE;
9839     return TRUE;
9840 }
9841 
9842 /*
9843  * Check for CTRL-C pressed, but only once in a while.
9844  * Should be used instead of ui_breakcheck() for functions that check for
9845  * each line in the file.  Calling ui_breakcheck() each time takes too much
9846  * time, because it can be a system call.
9847  */
9848 
9849 #ifndef BREAKCHECK_SKIP
9850 # ifdef FEAT_GUI		    /* assume the GUI only runs on fast computers */
9851 #  define BREAKCHECK_SKIP 200
9852 # else
9853 #  define BREAKCHECK_SKIP 32
9854 # endif
9855 #endif
9856 
9857 static int	breakcheck_count = 0;
9858 
9859     void
9860 line_breakcheck(void)
9861 {
9862     if (++breakcheck_count >= BREAKCHECK_SKIP)
9863     {
9864 	breakcheck_count = 0;
9865 	ui_breakcheck();
9866     }
9867 }
9868 
9869 /*
9870  * Like line_breakcheck() but check 10 times less often.
9871  */
9872     void
9873 fast_breakcheck(void)
9874 {
9875     if (++breakcheck_count >= BREAKCHECK_SKIP * 10)
9876     {
9877 	breakcheck_count = 0;
9878 	ui_breakcheck();
9879     }
9880 }
9881 
9882 /*
9883  * Invoke expand_wildcards() for one pattern.
9884  * Expand items like "%:h" before the expansion.
9885  * Returns OK or FAIL.
9886  */
9887     int
9888 expand_wildcards_eval(
9889     char_u	 **pat,		/* pointer to input pattern */
9890     int		  *num_file,	/* resulting number of files */
9891     char_u	***file,	/* array of resulting files */
9892     int		   flags)	/* EW_DIR, etc. */
9893 {
9894     int		ret = FAIL;
9895     char_u	*eval_pat = NULL;
9896     char_u	*exp_pat = *pat;
9897     char_u      *ignored_msg;
9898     int		usedlen;
9899 
9900     if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<')
9901     {
9902 	++emsg_off;
9903 	eval_pat = eval_vars(exp_pat, exp_pat, &usedlen,
9904 						    NULL, &ignored_msg, NULL);
9905 	--emsg_off;
9906 	if (eval_pat != NULL)
9907 	    exp_pat = concat_str(eval_pat, exp_pat + usedlen);
9908     }
9909 
9910     if (exp_pat != NULL)
9911 	ret = expand_wildcards(1, &exp_pat, num_file, file, flags);
9912 
9913     if (eval_pat != NULL)
9914     {
9915 	vim_free(exp_pat);
9916 	vim_free(eval_pat);
9917     }
9918 
9919     return ret;
9920 }
9921 
9922 /*
9923  * Expand wildcards.  Calls gen_expand_wildcards() and removes files matching
9924  * 'wildignore'.
9925  * Returns OK or FAIL.  When FAIL then "num_files" won't be set.
9926  */
9927     int
9928 expand_wildcards(
9929     int		   num_pat,	/* number of input patterns */
9930     char_u	 **pat,		/* array of input patterns */
9931     int		  *num_files,	/* resulting number of files */
9932     char_u	***files,	/* array of resulting files */
9933     int		   flags)	/* EW_DIR, etc. */
9934 {
9935     int		retval;
9936     int		i, j;
9937     char_u	*p;
9938     int		non_suf_match;	/* number without matching suffix */
9939 
9940     retval = gen_expand_wildcards(num_pat, pat, num_files, files, flags);
9941 
9942     /* When keeping all matches, return here */
9943     if ((flags & EW_KEEPALL) || retval == FAIL)
9944 	return retval;
9945 
9946 #ifdef FEAT_WILDIGN
9947     /*
9948      * Remove names that match 'wildignore'.
9949      */
9950     if (*p_wig)
9951     {
9952 	char_u	*ffname;
9953 
9954 	/* check all files in (*files)[] */
9955 	for (i = 0; i < *num_files; ++i)
9956 	{
9957 	    ffname = FullName_save((*files)[i], FALSE);
9958 	    if (ffname == NULL)		/* out of memory */
9959 		break;
9960 # ifdef VMS
9961 	    vms_remove_version(ffname);
9962 # endif
9963 	    if (match_file_list(p_wig, (*files)[i], ffname))
9964 	    {
9965 		/* remove this matching file from the list */
9966 		vim_free((*files)[i]);
9967 		for (j = i; j + 1 < *num_files; ++j)
9968 		    (*files)[j] = (*files)[j + 1];
9969 		--*num_files;
9970 		--i;
9971 	    }
9972 	    vim_free(ffname);
9973 	}
9974 
9975 	/* If the number of matches is now zero, we fail. */
9976 	if (*num_files == 0)
9977 	{
9978 	    VIM_CLEAR(*files);
9979 	    return FAIL;
9980 	}
9981     }
9982 #endif
9983 
9984     /*
9985      * Move the names where 'suffixes' match to the end.
9986      */
9987     if (*num_files > 1)
9988     {
9989 	non_suf_match = 0;
9990 	for (i = 0; i < *num_files; ++i)
9991 	{
9992 	    if (!match_suffix((*files)[i]))
9993 	    {
9994 		/*
9995 		 * Move the name without matching suffix to the front
9996 		 * of the list.
9997 		 */
9998 		p = (*files)[i];
9999 		for (j = i; j > non_suf_match; --j)
10000 		    (*files)[j] = (*files)[j - 1];
10001 		(*files)[non_suf_match++] = p;
10002 	    }
10003 	}
10004     }
10005 
10006     return retval;
10007 }
10008 
10009 /*
10010  * Return TRUE if "fname" matches with an entry in 'suffixes'.
10011  */
10012     int
10013 match_suffix(char_u *fname)
10014 {
10015     int		fnamelen, setsuflen;
10016     char_u	*setsuf;
10017 #define MAXSUFLEN 30	    /* maximum length of a file suffix */
10018     char_u	suf_buf[MAXSUFLEN];
10019 
10020     fnamelen = (int)STRLEN(fname);
10021     setsuflen = 0;
10022     for (setsuf = p_su; *setsuf; )
10023     {
10024 	setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
10025 	if (setsuflen == 0)
10026 	{
10027 	    char_u *tail = gettail(fname);
10028 
10029 	    /* empty entry: match name without a '.' */
10030 	    if (vim_strchr(tail, '.') == NULL)
10031 	    {
10032 		setsuflen = 1;
10033 		break;
10034 	    }
10035 	}
10036 	else
10037 	{
10038 	    if (fnamelen >= setsuflen
10039 		    && fnamencmp(suf_buf, fname + fnamelen - setsuflen,
10040 						  (size_t)setsuflen) == 0)
10041 		break;
10042 	    setsuflen = 0;
10043 	}
10044     }
10045     return (setsuflen != 0);
10046 }
10047 
10048 #if !defined(NO_EXPANDPATH) || defined(PROTO)
10049 
10050 # ifdef VIM_BACKTICK
10051 static int vim_backtick(char_u *p);
10052 static int expand_backtick(garray_T *gap, char_u *pat, int flags);
10053 # endif
10054 
10055 # if defined(WIN3264)
10056 /*
10057  * File name expansion code for MS-DOS, Win16 and Win32.  It's here because
10058  * it's shared between these systems.
10059  */
10060 # if defined(PROTO)
10061 #  define _cdecl
10062 # else
10063 #  ifdef __BORLANDC__
10064 #   define _cdecl _RTLENTRYF
10065 #  endif
10066 # endif
10067 
10068 /*
10069  * comparison function for qsort in dos_expandpath()
10070  */
10071     static int _cdecl
10072 pstrcmp(const void *a, const void *b)
10073 {
10074     return (pathcmp(*(char **)a, *(char **)b, -1));
10075 }
10076 
10077 /*
10078  * Recursively expand one path component into all matching files and/or
10079  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
10080  * Return the number of matches found.
10081  * "path" has backslashes before chars that are not to be expanded, starting
10082  * at "path[wildoff]".
10083  * Return the number of matches found.
10084  * NOTE: much of this is identical to unix_expandpath(), keep in sync!
10085  */
10086     static int
10087 dos_expandpath(
10088     garray_T	*gap,
10089     char_u	*path,
10090     int		wildoff,
10091     int		flags,		/* EW_* flags */
10092     int		didstar)	/* expanded "**" once already */
10093 {
10094     char_u	*buf;
10095     char_u	*path_end;
10096     char_u	*p, *s, *e;
10097     int		start_len = gap->ga_len;
10098     char_u	*pat;
10099     regmatch_T	regmatch;
10100     int		starts_with_dot;
10101     int		matches;
10102     int		len;
10103     int		starstar = FALSE;
10104     static int	stardepth = 0;	    /* depth for "**" expansion */
10105     WIN32_FIND_DATA	fb;
10106     HANDLE		hFind = (HANDLE)0;
10107 # ifdef FEAT_MBYTE
10108     WIN32_FIND_DATAW    wfb;
10109     WCHAR		*wn = NULL;	/* UCS-2 name, NULL when not used. */
10110 # endif
10111     char_u		*matchname;
10112     int			ok;
10113 
10114     /* Expanding "**" may take a long time, check for CTRL-C. */
10115     if (stardepth > 0)
10116     {
10117 	ui_breakcheck();
10118 	if (got_int)
10119 	    return 0;
10120     }
10121 
10122     /* Make room for file name.  When doing encoding conversion the actual
10123      * length may be quite a bit longer, thus use the maximum possible length. */
10124     buf = alloc((int)MAXPATHL);
10125     if (buf == NULL)
10126 	return 0;
10127 
10128     /*
10129      * Find the first part in the path name that contains a wildcard or a ~1.
10130      * Copy it into buf, including the preceding characters.
10131      */
10132     p = buf;
10133     s = buf;
10134     e = NULL;
10135     path_end = path;
10136     while (*path_end != NUL)
10137     {
10138 	/* May ignore a wildcard that has a backslash before it; it will
10139 	 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
10140 	if (path_end >= path + wildoff && rem_backslash(path_end))
10141 	    *p++ = *path_end++;
10142 	else if (*path_end == '\\' || *path_end == ':' || *path_end == '/')
10143 	{
10144 	    if (e != NULL)
10145 		break;
10146 	    s = p + 1;
10147 	}
10148 	else if (path_end >= path + wildoff
10149 			 && vim_strchr((char_u *)"*?[~", *path_end) != NULL)
10150 	    e = p;
10151 # ifdef FEAT_MBYTE
10152 	if (has_mbyte)
10153 	{
10154 	    len = (*mb_ptr2len)(path_end);
10155 	    STRNCPY(p, path_end, len);
10156 	    p += len;
10157 	    path_end += len;
10158 	}
10159 	else
10160 # endif
10161 	    *p++ = *path_end++;
10162     }
10163     e = p;
10164     *e = NUL;
10165 
10166     /* now we have one wildcard component between s and e */
10167     /* Remove backslashes between "wildoff" and the start of the wildcard
10168      * component. */
10169     for (p = buf + wildoff; p < s; ++p)
10170 	if (rem_backslash(p))
10171 	{
10172 	    STRMOVE(p, p + 1);
10173 	    --e;
10174 	    --s;
10175 	}
10176 
10177     /* Check for "**" between "s" and "e". */
10178     for (p = s; p < e; ++p)
10179 	if (p[0] == '*' && p[1] == '*')
10180 	    starstar = TRUE;
10181 
10182     starts_with_dot = *s == '.';
10183     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
10184     if (pat == NULL)
10185     {
10186 	vim_free(buf);
10187 	return 0;
10188     }
10189 
10190     /* compile the regexp into a program */
10191     if (flags & (EW_NOERROR | EW_NOTWILD))
10192 	++emsg_silent;
10193     regmatch.rm_ic = TRUE;		/* Always ignore case */
10194     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
10195     if (flags & (EW_NOERROR | EW_NOTWILD))
10196 	--emsg_silent;
10197     vim_free(pat);
10198 
10199     if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0)
10200     {
10201 	vim_free(buf);
10202 	return 0;
10203     }
10204 
10205     /* remember the pattern or file name being looked for */
10206     matchname = vim_strsave(s);
10207 
10208     /* If "**" is by itself, this is the first time we encounter it and more
10209      * is following then find matches without any directory. */
10210     if (!didstar && stardepth < 100 && starstar && e - s == 2
10211 							  && *path_end == '/')
10212     {
10213 	STRCPY(s, path_end + 1);
10214 	++stardepth;
10215 	(void)dos_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
10216 	--stardepth;
10217     }
10218 
10219     /* Scan all files in the directory with "dir/ *.*" */
10220     STRCPY(s, "*.*");
10221 # ifdef FEAT_MBYTE
10222     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
10223     {
10224 	/* The active codepage differs from 'encoding'.  Attempt using the
10225 	 * wide function.  If it fails because it is not implemented fall back
10226 	 * to the non-wide version (for Windows 98) */
10227 	wn = enc_to_utf16(buf, NULL);
10228 	if (wn != NULL)
10229 	{
10230 	    hFind = FindFirstFileW(wn, &wfb);
10231 	    if (hFind == INVALID_HANDLE_VALUE
10232 			      && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
10233 		VIM_CLEAR(wn);
10234 	}
10235     }
10236 
10237     if (wn == NULL)
10238 # endif
10239 	hFind = FindFirstFile((LPCSTR)buf, &fb);
10240     ok = (hFind != INVALID_HANDLE_VALUE);
10241 
10242     while (ok)
10243     {
10244 # ifdef FEAT_MBYTE
10245 	if (wn != NULL)
10246 	    p = utf16_to_enc(wfb.cFileName, NULL);   /* p is allocated here */
10247 	else
10248 # endif
10249 	    p = (char_u *)fb.cFileName;
10250 	/* Ignore entries starting with a dot, unless when asked for.  Accept
10251 	 * all entries found with "matchname". */
10252 	if ((p[0] != '.' || starts_with_dot
10253 			 || ((flags & EW_DODOT)
10254 			     && p[1] != NUL && (p[1] != '.' || p[2] != NUL)))
10255 		&& (matchname == NULL
10256 		  || (regmatch.regprog != NULL
10257 				     && vim_regexec(&regmatch, p, (colnr_T)0))
10258 		  || ((flags & EW_NOTWILD)
10259 		     && fnamencmp(path + (s - buf), p, e - s) == 0)))
10260 	{
10261 	    STRCPY(s, p);
10262 	    len = (int)STRLEN(buf);
10263 
10264 	    if (starstar && stardepth < 100)
10265 	    {
10266 		/* For "**" in the pattern first go deeper in the tree to
10267 		 * find matches. */
10268 		STRCPY(buf + len, "/**");
10269 		STRCPY(buf + len + 3, path_end);
10270 		++stardepth;
10271 		(void)dos_expandpath(gap, buf, len + 1, flags, TRUE);
10272 		--stardepth;
10273 	    }
10274 
10275 	    STRCPY(buf + len, path_end);
10276 	    if (mch_has_exp_wildcard(path_end))
10277 	    {
10278 		/* need to expand another component of the path */
10279 		/* remove backslashes for the remaining components only */
10280 		(void)dos_expandpath(gap, buf, len + 1, flags, FALSE);
10281 	    }
10282 	    else
10283 	    {
10284 		/* no more wildcards, check if there is a match */
10285 		/* remove backslashes for the remaining components only */
10286 		if (*path_end != 0)
10287 		    backslash_halve(buf + len + 1);
10288 		if (mch_getperm(buf) >= 0)	/* add existing file */
10289 		    addfile(gap, buf, flags);
10290 	    }
10291 	}
10292 
10293 # ifdef FEAT_MBYTE
10294 	if (wn != NULL)
10295 	{
10296 	    vim_free(p);
10297 	    ok = FindNextFileW(hFind, &wfb);
10298 	}
10299 	else
10300 # endif
10301 	    ok = FindNextFile(hFind, &fb);
10302 
10303 	/* If no more matches and no match was used, try expanding the name
10304 	 * itself.  Finds the long name of a short filename. */
10305 	if (!ok && matchname != NULL && gap->ga_len == start_len)
10306 	{
10307 	    STRCPY(s, matchname);
10308 	    FindClose(hFind);
10309 # ifdef FEAT_MBYTE
10310 	    if (wn != NULL)
10311 	    {
10312 		vim_free(wn);
10313 		wn = enc_to_utf16(buf, NULL);
10314 		if (wn != NULL)
10315 		    hFind = FindFirstFileW(wn, &wfb);
10316 	    }
10317 	    if (wn == NULL)
10318 # endif
10319 		hFind = FindFirstFile((LPCSTR)buf, &fb);
10320 	    ok = (hFind != INVALID_HANDLE_VALUE);
10321 	    VIM_CLEAR(matchname);
10322 	}
10323     }
10324 
10325     FindClose(hFind);
10326 # ifdef FEAT_MBYTE
10327     vim_free(wn);
10328 # endif
10329     vim_free(buf);
10330     vim_regfree(regmatch.regprog);
10331     vim_free(matchname);
10332 
10333     matches = gap->ga_len - start_len;
10334     if (matches > 0)
10335 	qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches,
10336 						   sizeof(char_u *), pstrcmp);
10337     return matches;
10338 }
10339 
10340     int
10341 mch_expandpath(
10342     garray_T	*gap,
10343     char_u	*path,
10344     int		flags)		/* EW_* flags */
10345 {
10346     return dos_expandpath(gap, path, 0, flags, FALSE);
10347 }
10348 # endif /* WIN3264 */
10349 
10350 #if (defined(UNIX) && !defined(VMS)) || defined(USE_UNIXFILENAME) \
10351 	|| defined(PROTO)
10352 /*
10353  * Unix style wildcard expansion code.
10354  * It's here because it's used both for Unix and Mac.
10355  */
10356 static int	pstrcmp(const void *, const void *);
10357 
10358     static int
10359 pstrcmp(const void *a, const void *b)
10360 {
10361     return (pathcmp(*(char **)a, *(char **)b, -1));
10362 }
10363 
10364 /*
10365  * Recursively expand one path component into all matching files and/or
10366  * directories.  Adds matches to "gap".  Handles "*", "?", "[a-z]", "**", etc.
10367  * "path" has backslashes before chars that are not to be expanded, starting
10368  * at "path + wildoff".
10369  * Return the number of matches found.
10370  * NOTE: much of this is identical to dos_expandpath(), keep in sync!
10371  */
10372     int
10373 unix_expandpath(
10374     garray_T	*gap,
10375     char_u	*path,
10376     int		wildoff,
10377     int		flags,		/* EW_* flags */
10378     int		didstar)	/* expanded "**" once already */
10379 {
10380     char_u	*buf;
10381     char_u	*path_end;
10382     char_u	*p, *s, *e;
10383     int		start_len = gap->ga_len;
10384     char_u	*pat;
10385     regmatch_T	regmatch;
10386     int		starts_with_dot;
10387     int		matches;
10388     int		len;
10389     int		starstar = FALSE;
10390     static int	stardepth = 0;	    /* depth for "**" expansion */
10391 
10392     DIR		*dirp;
10393     struct dirent *dp;
10394 
10395     /* Expanding "**" may take a long time, check for CTRL-C. */
10396     if (stardepth > 0)
10397     {
10398 	ui_breakcheck();
10399 	if (got_int)
10400 	    return 0;
10401     }
10402 
10403     /* make room for file name */
10404     buf = alloc((int)STRLEN(path) + BASENAMELEN + 5);
10405     if (buf == NULL)
10406 	return 0;
10407 
10408     /*
10409      * Find the first part in the path name that contains a wildcard.
10410      * When EW_ICASE is set every letter is considered to be a wildcard.
10411      * Copy it into "buf", including the preceding characters.
10412      */
10413     p = buf;
10414     s = buf;
10415     e = NULL;
10416     path_end = path;
10417     while (*path_end != NUL)
10418     {
10419 	/* May ignore a wildcard that has a backslash before it; it will
10420 	 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
10421 	if (path_end >= path + wildoff && rem_backslash(path_end))
10422 	    *p++ = *path_end++;
10423 	else if (*path_end == '/')
10424 	{
10425 	    if (e != NULL)
10426 		break;
10427 	    s = p + 1;
10428 	}
10429 	else if (path_end >= path + wildoff
10430 			 && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL
10431 			     || (!p_fic && (flags & EW_ICASE)
10432 					     && isalpha(PTR2CHAR(path_end)))))
10433 	    e = p;
10434 #ifdef FEAT_MBYTE
10435 	if (has_mbyte)
10436 	{
10437 	    len = (*mb_ptr2len)(path_end);
10438 	    STRNCPY(p, path_end, len);
10439 	    p += len;
10440 	    path_end += len;
10441 	}
10442 	else
10443 #endif
10444 	    *p++ = *path_end++;
10445     }
10446     e = p;
10447     *e = NUL;
10448 
10449     /* Now we have one wildcard component between "s" and "e". */
10450     /* Remove backslashes between "wildoff" and the start of the wildcard
10451      * component. */
10452     for (p = buf + wildoff; p < s; ++p)
10453 	if (rem_backslash(p))
10454 	{
10455 	    STRMOVE(p, p + 1);
10456 	    --e;
10457 	    --s;
10458 	}
10459 
10460     /* Check for "**" between "s" and "e". */
10461     for (p = s; p < e; ++p)
10462 	if (p[0] == '*' && p[1] == '*')
10463 	    starstar = TRUE;
10464 
10465     /* convert the file pattern to a regexp pattern */
10466     starts_with_dot = *s == '.';
10467     pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
10468     if (pat == NULL)
10469     {
10470 	vim_free(buf);
10471 	return 0;
10472     }
10473 
10474     /* compile the regexp into a program */
10475     if (flags & EW_ICASE)
10476 	regmatch.rm_ic = TRUE;		/* 'wildignorecase' set */
10477     else
10478 	regmatch.rm_ic = p_fic;	/* ignore case when 'fileignorecase' is set */
10479     if (flags & (EW_NOERROR | EW_NOTWILD))
10480 	++emsg_silent;
10481     regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
10482     if (flags & (EW_NOERROR | EW_NOTWILD))
10483 	--emsg_silent;
10484     vim_free(pat);
10485 
10486     if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0)
10487     {
10488 	vim_free(buf);
10489 	return 0;
10490     }
10491 
10492     /* If "**" is by itself, this is the first time we encounter it and more
10493      * is following then find matches without any directory. */
10494     if (!didstar && stardepth < 100 && starstar && e - s == 2
10495 							  && *path_end == '/')
10496     {
10497 	STRCPY(s, path_end + 1);
10498 	++stardepth;
10499 	(void)unix_expandpath(gap, buf, (int)(s - buf), flags, TRUE);
10500 	--stardepth;
10501     }
10502 
10503     /* open the directory for scanning */
10504     *s = NUL;
10505     dirp = opendir(*buf == NUL ? "." : (char *)buf);
10506 
10507     /* Find all matching entries */
10508     if (dirp != NULL)
10509     {
10510 	for (;;)
10511 	{
10512 	    dp = readdir(dirp);
10513 	    if (dp == NULL)
10514 		break;
10515 	    if ((dp->d_name[0] != '.' || starts_with_dot
10516 			|| ((flags & EW_DODOT)
10517 			    && dp->d_name[1] != NUL
10518 			    && (dp->d_name[1] != '.' || dp->d_name[2] != NUL)))
10519 		 && ((regmatch.regprog != NULL && vim_regexec(&regmatch,
10520 					     (char_u *)dp->d_name, (colnr_T)0))
10521 		   || ((flags & EW_NOTWILD)
10522 		     && fnamencmp(path + (s - buf), dp->d_name, e - s) == 0)))
10523 	    {
10524 		STRCPY(s, dp->d_name);
10525 		len = STRLEN(buf);
10526 
10527 		if (starstar && stardepth < 100)
10528 		{
10529 		    /* For "**" in the pattern first go deeper in the tree to
10530 		     * find matches. */
10531 		    STRCPY(buf + len, "/**");
10532 		    STRCPY(buf + len + 3, path_end);
10533 		    ++stardepth;
10534 		    (void)unix_expandpath(gap, buf, len + 1, flags, TRUE);
10535 		    --stardepth;
10536 		}
10537 
10538 		STRCPY(buf + len, path_end);
10539 		if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
10540 		{
10541 		    /* need to expand another component of the path */
10542 		    /* remove backslashes for the remaining components only */
10543 		    (void)unix_expandpath(gap, buf, len + 1, flags, FALSE);
10544 		}
10545 		else
10546 		{
10547 		    stat_T  sb;
10548 
10549 		    /* no more wildcards, check if there is a match */
10550 		    /* remove backslashes for the remaining components only */
10551 		    if (*path_end != NUL)
10552 			backslash_halve(buf + len + 1);
10553 		    /* add existing file or symbolic link */
10554 		    if ((flags & EW_ALLLINKS) ? mch_lstat((char *)buf, &sb) >= 0
10555 						      : mch_getperm(buf) >= 0)
10556 		    {
10557 #ifdef MACOS_CONVERT
10558 			size_t precomp_len = STRLEN(buf)+1;
10559 			char_u *precomp_buf =
10560 			    mac_precompose_path(buf, precomp_len, &precomp_len);
10561 
10562 			if (precomp_buf)
10563 			{
10564 			    mch_memmove(buf, precomp_buf, precomp_len);
10565 			    vim_free(precomp_buf);
10566 			}
10567 #endif
10568 			addfile(gap, buf, flags);
10569 		    }
10570 		}
10571 	    }
10572 	}
10573 
10574 	closedir(dirp);
10575     }
10576 
10577     vim_free(buf);
10578     vim_regfree(regmatch.regprog);
10579 
10580     matches = gap->ga_len - start_len;
10581     if (matches > 0)
10582 	qsort(((char_u **)gap->ga_data) + start_len, matches,
10583 						   sizeof(char_u *), pstrcmp);
10584     return matches;
10585 }
10586 #endif
10587 
10588 #if defined(FEAT_SEARCHPATH)
10589 static int find_previous_pathsep(char_u *path, char_u **psep);
10590 static int is_unique(char_u *maybe_unique, garray_T *gap, int i);
10591 static void expand_path_option(char_u *curdir, garray_T	*gap);
10592 static char_u *get_path_cutoff(char_u *fname, garray_T *gap);
10593 static void uniquefy_paths(garray_T *gap, char_u *pattern);
10594 static int expand_in_path(garray_T *gap, char_u	*pattern, int flags);
10595 
10596 /*
10597  * Moves "*psep" back to the previous path separator in "path".
10598  * Returns FAIL is "*psep" ends up at the beginning of "path".
10599  */
10600     static int
10601 find_previous_pathsep(char_u *path, char_u **psep)
10602 {
10603     /* skip the current separator */
10604     if (*psep > path && vim_ispathsep(**psep))
10605 	--*psep;
10606 
10607     /* find the previous separator */
10608     while (*psep > path)
10609     {
10610 	if (vim_ispathsep(**psep))
10611 	    return OK;
10612 	MB_PTR_BACK(path, *psep);
10613     }
10614 
10615     return FAIL;
10616 }
10617 
10618 /*
10619  * Returns TRUE if "maybe_unique" is unique wrt other_paths in "gap".
10620  * "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]".
10621  */
10622     static int
10623 is_unique(char_u *maybe_unique, garray_T *gap, int i)
10624 {
10625     int	    j;
10626     int	    candidate_len;
10627     int	    other_path_len;
10628     char_u  **other_paths = (char_u **)gap->ga_data;
10629     char_u  *rival;
10630 
10631     for (j = 0; j < gap->ga_len; j++)
10632     {
10633 	if (j == i)
10634 	    continue;  /* don't compare it with itself */
10635 
10636 	candidate_len = (int)STRLEN(maybe_unique);
10637 	other_path_len = (int)STRLEN(other_paths[j]);
10638 	if (other_path_len < candidate_len)
10639 	    continue;  /* it's different when it's shorter */
10640 
10641 	rival = other_paths[j] + other_path_len - candidate_len;
10642 	if (fnamecmp(maybe_unique, rival) == 0
10643 		&& (rival == other_paths[j] || vim_ispathsep(*(rival - 1))))
10644 	    return FALSE;  /* match */
10645     }
10646 
10647     return TRUE;  /* no match found */
10648 }
10649 
10650 /*
10651  * Split the 'path' option into an array of strings in garray_T.  Relative
10652  * paths are expanded to their equivalent fullpath.  This includes the "."
10653  * (relative to current buffer directory) and empty path (relative to current
10654  * directory) notations.
10655  *
10656  * TODO: handle upward search (;) and path limiter (**N) notations by
10657  * expanding each into their equivalent path(s).
10658  */
10659     static void
10660 expand_path_option(char_u *curdir, garray_T *gap)
10661 {
10662     char_u	*path_option = *curbuf->b_p_path == NUL
10663 						  ? p_path : curbuf->b_p_path;
10664     char_u	*buf;
10665     char_u	*p;
10666     int		len;
10667 
10668     if ((buf = alloc((int)MAXPATHL)) == NULL)
10669 	return;
10670 
10671     while (*path_option != NUL)
10672     {
10673 	copy_option_part(&path_option, buf, MAXPATHL, " ,");
10674 
10675 	if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1])))
10676 	{
10677 	    /* Relative to current buffer:
10678 	     * "/path/file" + "." -> "/path/"
10679 	     * "/path/file"  + "./subdir" -> "/path/subdir" */
10680 	    if (curbuf->b_ffname == NULL)
10681 		continue;
10682 	    p = gettail(curbuf->b_ffname);
10683 	    len = (int)(p - curbuf->b_ffname);
10684 	    if (len + (int)STRLEN(buf) >= MAXPATHL)
10685 		continue;
10686 	    if (buf[1] == NUL)
10687 		buf[len] = NUL;
10688 	    else
10689 		STRMOVE(buf + len, buf + 2);
10690 	    mch_memmove(buf, curbuf->b_ffname, len);
10691 	    simplify_filename(buf);
10692 	}
10693 	else if (buf[0] == NUL)
10694 	    /* relative to current directory */
10695 	    STRCPY(buf, curdir);
10696 	else if (path_with_url(buf))
10697 	    /* URL can't be used here */
10698 	    continue;
10699 	else if (!mch_isFullName(buf))
10700 	{
10701 	    /* Expand relative path to their full path equivalent */
10702 	    len = (int)STRLEN(curdir);
10703 	    if (len + (int)STRLEN(buf) + 3 > MAXPATHL)
10704 		continue;
10705 	    STRMOVE(buf + len + 1, buf);
10706 	    STRCPY(buf, curdir);
10707 	    buf[len] = PATHSEP;
10708 	    simplify_filename(buf);
10709 	}
10710 
10711 	if (ga_grow(gap, 1) == FAIL)
10712 	    break;
10713 
10714 # if defined(MSWIN)
10715 	/* Avoid the path ending in a backslash, it fails when a comma is
10716 	 * appended. */
10717 	len = (int)STRLEN(buf);
10718 	if (buf[len - 1] == '\\')
10719 	    buf[len - 1] = '/';
10720 # endif
10721 
10722 	p = vim_strsave(buf);
10723 	if (p == NULL)
10724 	    break;
10725 	((char_u **)gap->ga_data)[gap->ga_len++] = p;
10726     }
10727 
10728     vim_free(buf);
10729 }
10730 
10731 /*
10732  * Returns a pointer to the file or directory name in "fname" that matches the
10733  * longest path in "ga"p, or NULL if there is no match. For example:
10734  *
10735  *    path: /foo/bar/baz
10736  *   fname: /foo/bar/baz/quux.txt
10737  * returns:		 ^this
10738  */
10739     static char_u *
10740 get_path_cutoff(char_u *fname, garray_T *gap)
10741 {
10742     int	    i;
10743     int	    maxlen = 0;
10744     char_u  **path_part = (char_u **)gap->ga_data;
10745     char_u  *cutoff = NULL;
10746 
10747     for (i = 0; i < gap->ga_len; i++)
10748     {
10749 	int j = 0;
10750 
10751 	while ((fname[j] == path_part[i][j]
10752 # if defined(MSWIN)
10753 		|| (vim_ispathsep(fname[j]) && vim_ispathsep(path_part[i][j]))
10754 #endif
10755 			     ) && fname[j] != NUL && path_part[i][j] != NUL)
10756 	    j++;
10757 	if (j > maxlen)
10758 	{
10759 	    maxlen = j;
10760 	    cutoff = &fname[j];
10761 	}
10762     }
10763 
10764     /* skip to the file or directory name */
10765     if (cutoff != NULL)
10766 	while (vim_ispathsep(*cutoff))
10767 	    MB_PTR_ADV(cutoff);
10768 
10769     return cutoff;
10770 }
10771 
10772 /*
10773  * Sorts, removes duplicates and modifies all the fullpath names in "gap" so
10774  * that they are unique with respect to each other while conserving the part
10775  * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
10776  */
10777     static void
10778 uniquefy_paths(garray_T *gap, char_u *pattern)
10779 {
10780     int		i;
10781     int		len;
10782     char_u	**fnames = (char_u **)gap->ga_data;
10783     int		sort_again = FALSE;
10784     char_u	*pat;
10785     char_u      *file_pattern;
10786     char_u	*curdir;
10787     regmatch_T	regmatch;
10788     garray_T	path_ga;
10789     char_u	**in_curdir = NULL;
10790     char_u	*short_name;
10791 
10792     remove_duplicates(gap);
10793     ga_init2(&path_ga, (int)sizeof(char_u *), 1);
10794 
10795     /*
10796      * We need to prepend a '*' at the beginning of file_pattern so that the
10797      * regex matches anywhere in the path. FIXME: is this valid for all
10798      * possible patterns?
10799      */
10800     len = (int)STRLEN(pattern);
10801     file_pattern = alloc(len + 2);
10802     if (file_pattern == NULL)
10803 	return;
10804     file_pattern[0] = '*';
10805     file_pattern[1] = NUL;
10806     STRCAT(file_pattern, pattern);
10807     pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, TRUE);
10808     vim_free(file_pattern);
10809     if (pat == NULL)
10810 	return;
10811 
10812     regmatch.rm_ic = TRUE;		/* always ignore case */
10813     regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10814     vim_free(pat);
10815     if (regmatch.regprog == NULL)
10816 	return;
10817 
10818     if ((curdir = alloc((int)(MAXPATHL))) == NULL)
10819 	goto theend;
10820     mch_dirname(curdir, MAXPATHL);
10821     expand_path_option(curdir, &path_ga);
10822 
10823     in_curdir = (char_u **)alloc_clear(gap->ga_len * sizeof(char_u *));
10824     if (in_curdir == NULL)
10825 	goto theend;
10826 
10827     for (i = 0; i < gap->ga_len && !got_int; i++)
10828     {
10829 	char_u	    *path = fnames[i];
10830 	int	    is_in_curdir;
10831 	char_u	    *dir_end = gettail_dir(path);
10832 	char_u	    *pathsep_p;
10833 	char_u	    *path_cutoff;
10834 
10835 	len = (int)STRLEN(path);
10836 	is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0
10837 					     && curdir[dir_end - path] == NUL;
10838 	if (is_in_curdir)
10839 	    in_curdir[i] = vim_strsave(path);
10840 
10841 	/* Shorten the filename while maintaining its uniqueness */
10842 	path_cutoff = get_path_cutoff(path, &path_ga);
10843 
10844 	/* Don't assume all files can be reached without path when search
10845 	 * pattern starts with star star slash, so only remove path_cutoff
10846 	 * when possible. */
10847 	if (pattern[0] == '*' && pattern[1] == '*'
10848 		&& vim_ispathsep_nocolon(pattern[2])
10849 		&& path_cutoff != NULL
10850 		&& vim_regexec(&regmatch, path_cutoff, (colnr_T)0)
10851 		&& is_unique(path_cutoff, gap, i))
10852 	{
10853 	    sort_again = TRUE;
10854 	    mch_memmove(path, path_cutoff, STRLEN(path_cutoff) + 1);
10855 	}
10856 	else
10857 	{
10858 	    /* Here all files can be reached without path, so get shortest
10859 	     * unique path.  We start at the end of the path. */
10860 	    pathsep_p = path + len - 1;
10861 
10862 	    while (find_previous_pathsep(path, &pathsep_p))
10863 		if (vim_regexec(&regmatch, pathsep_p + 1, (colnr_T)0)
10864 			&& is_unique(pathsep_p + 1, gap, i)
10865 			&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff)
10866 		{
10867 		    sort_again = TRUE;
10868 		    mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p));
10869 		    break;
10870 		}
10871 	}
10872 
10873 	if (mch_isFullName(path))
10874 	{
10875 	    /*
10876 	     * Last resort: shorten relative to curdir if possible.
10877 	     * 'possible' means:
10878 	     * 1. It is under the current directory.
10879 	     * 2. The result is actually shorter than the original.
10880 	     *
10881 	     *	    Before		  curdir	After
10882 	     *	    /foo/bar/file.txt	  /foo/bar	./file.txt
10883 	     *	    c:\foo\bar\file.txt   c:\foo\bar	.\file.txt
10884 	     *	    /file.txt		  /		/file.txt
10885 	     *	    c:\file.txt		  c:\		.\file.txt
10886 	     */
10887 	    short_name = shorten_fname(path, curdir);
10888 	    if (short_name != NULL && short_name > path + 1
10889 #if defined(MSWIN)
10890 		    /* On windows,
10891 		     *	    shorten_fname("c:\a\a.txt", "c:\a\b")
10892 		     * returns "\a\a.txt", which is not really the short
10893 		     * name, hence: */
10894 		    && !vim_ispathsep(*short_name)
10895 #endif
10896 		)
10897 	    {
10898 		STRCPY(path, ".");
10899 		add_pathsep(path);
10900 		STRMOVE(path + STRLEN(path), short_name);
10901 	    }
10902 	}
10903 	ui_breakcheck();
10904     }
10905 
10906     /* Shorten filenames in /in/current/directory/{filename} */
10907     for (i = 0; i < gap->ga_len && !got_int; i++)
10908     {
10909 	char_u *rel_path;
10910 	char_u *path = in_curdir[i];
10911 
10912 	if (path == NULL)
10913 	    continue;
10914 
10915 	/* If the {filename} is not unique, change it to ./{filename}.
10916 	 * Else reduce it to {filename} */
10917 	short_name = shorten_fname(path, curdir);
10918 	if (short_name == NULL)
10919 	    short_name = path;
10920 	if (is_unique(short_name, gap, i))
10921 	{
10922 	    STRCPY(fnames[i], short_name);
10923 	    continue;
10924 	}
10925 
10926 	rel_path = alloc((int)(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2));
10927 	if (rel_path == NULL)
10928 	    goto theend;
10929 	STRCPY(rel_path, ".");
10930 	add_pathsep(rel_path);
10931 	STRCAT(rel_path, short_name);
10932 
10933 	vim_free(fnames[i]);
10934 	fnames[i] = rel_path;
10935 	sort_again = TRUE;
10936 	ui_breakcheck();
10937     }
10938 
10939 theend:
10940     vim_free(curdir);
10941     if (in_curdir != NULL)
10942     {
10943 	for (i = 0; i < gap->ga_len; i++)
10944 	    vim_free(in_curdir[i]);
10945 	vim_free(in_curdir);
10946     }
10947     ga_clear_strings(&path_ga);
10948     vim_regfree(regmatch.regprog);
10949 
10950     if (sort_again)
10951 	remove_duplicates(gap);
10952 }
10953 
10954 /*
10955  * Calls globpath() with 'path' values for the given pattern and stores the
10956  * result in "gap".
10957  * Returns the total number of matches.
10958  */
10959     static int
10960 expand_in_path(
10961     garray_T	*gap,
10962     char_u	*pattern,
10963     int		flags)		/* EW_* flags */
10964 {
10965     char_u	*curdir;
10966     garray_T	path_ga;
10967     char_u	*paths = NULL;
10968     int		glob_flags = 0;
10969 
10970     if ((curdir = alloc((unsigned)MAXPATHL)) == NULL)
10971 	return 0;
10972     mch_dirname(curdir, MAXPATHL);
10973 
10974     ga_init2(&path_ga, (int)sizeof(char_u *), 1);
10975     expand_path_option(curdir, &path_ga);
10976     vim_free(curdir);
10977     if (path_ga.ga_len == 0)
10978 	return 0;
10979 
10980     paths = ga_concat_strings(&path_ga, ",");
10981     ga_clear_strings(&path_ga);
10982     if (paths == NULL)
10983 	return 0;
10984 
10985     if (flags & EW_ICASE)
10986 	glob_flags |= WILD_ICASE;
10987     if (flags & EW_ADDSLASH)
10988 	glob_flags |= WILD_ADD_SLASH;
10989     globpath(paths, pattern, gap, glob_flags);
10990     vim_free(paths);
10991 
10992     return gap->ga_len;
10993 }
10994 #endif
10995 
10996 #if defined(FEAT_SEARCHPATH) || defined(FEAT_CMDL_COMPL) || defined(PROTO)
10997 /*
10998  * Sort "gap" and remove duplicate entries.  "gap" is expected to contain a
10999  * list of file names in allocated memory.
11000  */
11001     void
11002 remove_duplicates(garray_T *gap)
11003 {
11004     int	    i;
11005     int	    j;
11006     char_u  **fnames = (char_u **)gap->ga_data;
11007 
11008     sort_strings(fnames, gap->ga_len);
11009     for (i = gap->ga_len - 1; i > 0; --i)
11010 	if (fnamecmp(fnames[i - 1], fnames[i]) == 0)
11011 	{
11012 	    vim_free(fnames[i]);
11013 	    for (j = i + 1; j < gap->ga_len; ++j)
11014 		fnames[j - 1] = fnames[j];
11015 	    --gap->ga_len;
11016 	}
11017 }
11018 #endif
11019 
11020 static int has_env_var(char_u *p);
11021 
11022 /*
11023  * Return TRUE if "p" contains what looks like an environment variable.
11024  * Allowing for escaping.
11025  */
11026     static int
11027 has_env_var(char_u *p)
11028 {
11029     for ( ; *p; MB_PTR_ADV(p))
11030     {
11031 	if (*p == '\\' && p[1] != NUL)
11032 	    ++p;
11033 	else if (vim_strchr((char_u *)
11034 #if defined(MSWIN)
11035 				    "$%"
11036 #else
11037 				    "$"
11038 #endif
11039 					, *p) != NULL)
11040 	    return TRUE;
11041     }
11042     return FALSE;
11043 }
11044 
11045 #ifdef SPECIAL_WILDCHAR
11046 static int has_special_wildchar(char_u *p);
11047 
11048 /*
11049  * Return TRUE if "p" contains a special wildcard character, one that Vim
11050  * cannot expand, requires using a shell.
11051  */
11052     static int
11053 has_special_wildchar(char_u *p)
11054 {
11055     for ( ; *p; MB_PTR_ADV(p))
11056     {
11057 	/* Allow for escaping. */
11058 	if (*p == '\\' && p[1] != NUL)
11059 	    ++p;
11060 	else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL)
11061 	    return TRUE;
11062     }
11063     return FALSE;
11064 }
11065 #endif
11066 
11067 /*
11068  * Generic wildcard expansion code.
11069  *
11070  * Characters in "pat" that should not be expanded must be preceded with a
11071  * backslash. E.g., "/path\ with\ spaces/my\*star*"
11072  *
11073  * Return FAIL when no single file was found.  In this case "num_file" is not
11074  * set, and "file" may contain an error message.
11075  * Return OK when some files found.  "num_file" is set to the number of
11076  * matches, "file" to the array of matches.  Call FreeWild() later.
11077  */
11078     int
11079 gen_expand_wildcards(
11080     int		num_pat,	/* number of input patterns */
11081     char_u	**pat,		/* array of input patterns */
11082     int		*num_file,	/* resulting number of files */
11083     char_u	***file,	/* array of resulting files */
11084     int		flags)		/* EW_* flags */
11085 {
11086     int			i;
11087     garray_T		ga;
11088     char_u		*p;
11089     static int		recursive = FALSE;
11090     int			add_pat;
11091     int			retval = OK;
11092 #if defined(FEAT_SEARCHPATH)
11093     int			did_expand_in_path = FALSE;
11094 #endif
11095 
11096     /*
11097      * expand_env() is called to expand things like "~user".  If this fails,
11098      * it calls ExpandOne(), which brings us back here.  In this case, always
11099      * call the machine specific expansion function, if possible.  Otherwise,
11100      * return FAIL.
11101      */
11102     if (recursive)
11103 #ifdef SPECIAL_WILDCHAR
11104 	return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
11105 #else
11106 	return FAIL;
11107 #endif
11108 
11109 #ifdef SPECIAL_WILDCHAR
11110     /*
11111      * If there are any special wildcard characters which we cannot handle
11112      * here, call machine specific function for all the expansion.  This
11113      * avoids starting the shell for each argument separately.
11114      * For `=expr` do use the internal function.
11115      */
11116     for (i = 0; i < num_pat; i++)
11117     {
11118 	if (has_special_wildchar(pat[i])
11119 # ifdef VIM_BACKTICK
11120 		&& !(vim_backtick(pat[i]) && pat[i][1] == '=')
11121 # endif
11122 	   )
11123 	    return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
11124     }
11125 #endif
11126 
11127     recursive = TRUE;
11128 
11129     /*
11130      * The matching file names are stored in a growarray.  Init it empty.
11131      */
11132     ga_init2(&ga, (int)sizeof(char_u *), 30);
11133 
11134     for (i = 0; i < num_pat; ++i)
11135     {
11136 	add_pat = -1;
11137 	p = pat[i];
11138 
11139 #ifdef VIM_BACKTICK
11140 	if (vim_backtick(p))
11141 	{
11142 	    add_pat = expand_backtick(&ga, p, flags);
11143 	    if (add_pat == -1)
11144 		retval = FAIL;
11145 	}
11146 	else
11147 #endif
11148 	{
11149 	    /*
11150 	     * First expand environment variables, "~/" and "~user/".
11151 	     */
11152 	    if (has_env_var(p) || *p == '~')
11153 	    {
11154 		p = expand_env_save_opt(p, TRUE);
11155 		if (p == NULL)
11156 		    p = pat[i];
11157 #ifdef UNIX
11158 		/*
11159 		 * On Unix, if expand_env() can't expand an environment
11160 		 * variable, use the shell to do that.  Discard previously
11161 		 * found file names and start all over again.
11162 		 */
11163 		else if (has_env_var(p) || *p == '~')
11164 		{
11165 		    vim_free(p);
11166 		    ga_clear_strings(&ga);
11167 		    i = mch_expand_wildcards(num_pat, pat, num_file, file,
11168 							 flags|EW_KEEPDOLLAR);
11169 		    recursive = FALSE;
11170 		    return i;
11171 		}
11172 #endif
11173 	    }
11174 
11175 	    /*
11176 	     * If there are wildcards: Expand file names and add each match to
11177 	     * the list.  If there is no match, and EW_NOTFOUND is given, add
11178 	     * the pattern.
11179 	     * If there are no wildcards: Add the file name if it exists or
11180 	     * when EW_NOTFOUND is given.
11181 	     */
11182 	    if (mch_has_exp_wildcard(p))
11183 	    {
11184 #if defined(FEAT_SEARCHPATH)
11185 		if ((flags & EW_PATH)
11186 			&& !mch_isFullName(p)
11187 			&& !(p[0] == '.'
11188 			    && (vim_ispathsep(p[1])
11189 				|| (p[1] == '.' && vim_ispathsep(p[2]))))
11190 		   )
11191 		{
11192 		    /* :find completion where 'path' is used.
11193 		     * Recursiveness is OK here. */
11194 		    recursive = FALSE;
11195 		    add_pat = expand_in_path(&ga, p, flags);
11196 		    recursive = TRUE;
11197 		    did_expand_in_path = TRUE;
11198 		}
11199 		else
11200 #endif
11201 		    add_pat = mch_expandpath(&ga, p, flags);
11202 	    }
11203 	}
11204 
11205 	if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND)))
11206 	{
11207 	    char_u	*t = backslash_halve_save(p);
11208 
11209 	    /* When EW_NOTFOUND is used, always add files and dirs.  Makes
11210 	     * "vim c:/" work. */
11211 	    if (flags & EW_NOTFOUND)
11212 		addfile(&ga, t, flags | EW_DIR | EW_FILE);
11213 	    else
11214 		addfile(&ga, t, flags);
11215 	    vim_free(t);
11216 	}
11217 
11218 #if defined(FEAT_SEARCHPATH)
11219 	if (did_expand_in_path && ga.ga_len > 0 && (flags & EW_PATH))
11220 	    uniquefy_paths(&ga, p);
11221 #endif
11222 	if (p != pat[i])
11223 	    vim_free(p);
11224     }
11225 
11226     *num_file = ga.ga_len;
11227     *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)"";
11228 
11229     recursive = FALSE;
11230 
11231     return ((flags & EW_EMPTYOK) || ga.ga_data != NULL) ? retval : FAIL;
11232 }
11233 
11234 # ifdef VIM_BACKTICK
11235 
11236 /*
11237  * Return TRUE if we can expand this backtick thing here.
11238  */
11239     static int
11240 vim_backtick(char_u *p)
11241 {
11242     return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`');
11243 }
11244 
11245 /*
11246  * Expand an item in `backticks` by executing it as a command.
11247  * Currently only works when pat[] starts and ends with a `.
11248  * Returns number of file names found, -1 if an error is encountered.
11249  */
11250     static int
11251 expand_backtick(
11252     garray_T	*gap,
11253     char_u	*pat,
11254     int		flags)	/* EW_* flags */
11255 {
11256     char_u	*p;
11257     char_u	*cmd;
11258     char_u	*buffer;
11259     int		cnt = 0;
11260     int		i;
11261 
11262     /* Create the command: lop off the backticks. */
11263     cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
11264     if (cmd == NULL)
11265 	return -1;
11266 
11267 #ifdef FEAT_EVAL
11268     if (*cmd == '=')	    /* `={expr}`: Expand expression */
11269 	buffer = eval_to_string(cmd + 1, &p, TRUE);
11270     else
11271 #endif
11272 	buffer = get_cmd_output(cmd, NULL,
11273 				(flags & EW_SILENT) ? SHELL_SILENT : 0, NULL);
11274     vim_free(cmd);
11275     if (buffer == NULL)
11276 	return -1;
11277 
11278     cmd = buffer;
11279     while (*cmd != NUL)
11280     {
11281 	cmd = skipwhite(cmd);		/* skip over white space */
11282 	p = cmd;
11283 	while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */
11284 	    ++p;
11285 	/* add an entry if it is not empty */
11286 	if (p > cmd)
11287 	{
11288 	    i = *p;
11289 	    *p = NUL;
11290 	    addfile(gap, cmd, flags);
11291 	    *p = i;
11292 	    ++cnt;
11293 	}
11294 	cmd = p;
11295 	while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n'))
11296 	    ++cmd;
11297     }
11298 
11299     vim_free(buffer);
11300     return cnt;
11301 }
11302 # endif /* VIM_BACKTICK */
11303 
11304 /*
11305  * Add a file to a file list.  Accepted flags:
11306  * EW_DIR	add directories
11307  * EW_FILE	add files
11308  * EW_EXEC	add executable files
11309  * EW_NOTFOUND	add even when it doesn't exist
11310  * EW_ADDSLASH	add slash after directory name
11311  * EW_ALLLINKS	add symlink also when the referred file does not exist
11312  */
11313     void
11314 addfile(
11315     garray_T	*gap,
11316     char_u	*f,	/* filename */
11317     int		flags)
11318 {
11319     char_u	*p;
11320     int		isdir;
11321     stat_T	sb;
11322 
11323     /* if the file/dir/link doesn't exist, may not add it */
11324     if (!(flags & EW_NOTFOUND) && ((flags & EW_ALLLINKS)
11325 			? mch_lstat((char *)f, &sb) < 0 : mch_getperm(f) < 0))
11326 	return;
11327 
11328 #ifdef FNAME_ILLEGAL
11329     /* if the file/dir contains illegal characters, don't add it */
11330     if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL)
11331 	return;
11332 #endif
11333 
11334     isdir = mch_isdir(f);
11335     if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE)))
11336 	return;
11337 
11338     /* If the file isn't executable, may not add it.  Do accept directories.
11339      * When invoked from expand_shellcmd() do not use $PATH. */
11340     if (!isdir && (flags & EW_EXEC)
11341 			     && !mch_can_exe(f, NULL, !(flags & EW_SHELLCMD)))
11342 	return;
11343 
11344     /* Make room for another item in the file list. */
11345     if (ga_grow(gap, 1) == FAIL)
11346 	return;
11347 
11348     p = alloc((unsigned)(STRLEN(f) + 1 + isdir));
11349     if (p == NULL)
11350 	return;
11351 
11352     STRCPY(p, f);
11353 #ifdef BACKSLASH_IN_FILENAME
11354     slash_adjust(p);
11355 #endif
11356     /*
11357      * Append a slash or backslash after directory names if none is present.
11358      */
11359 #ifndef DONT_ADD_PATHSEP_TO_DIR
11360     if (isdir && (flags & EW_ADDSLASH))
11361 	add_pathsep(p);
11362 #endif
11363     ((char_u **)gap->ga_data)[gap->ga_len++] = p;
11364 }
11365 #endif /* !NO_EXPANDPATH */
11366 
11367 #if defined(VIM_BACKTICK) || defined(FEAT_EVAL) || defined(PROTO)
11368 
11369 #ifndef SEEK_SET
11370 # define SEEK_SET 0
11371 #endif
11372 #ifndef SEEK_END
11373 # define SEEK_END 2
11374 #endif
11375 
11376 /*
11377  * Get the stdout of an external command.
11378  * If "ret_len" is NULL replace NUL characters with NL.  When "ret_len" is not
11379  * NULL store the length there.
11380  * Returns an allocated string, or NULL for error.
11381  */
11382     char_u *
11383 get_cmd_output(
11384     char_u	*cmd,
11385     char_u	*infile,	/* optional input file name */
11386     int		flags,		/* can be SHELL_SILENT */
11387     int		*ret_len)
11388 {
11389     char_u	*tempname;
11390     char_u	*command;
11391     char_u	*buffer = NULL;
11392     int		len;
11393     int		i = 0;
11394     FILE	*fd;
11395 
11396     if (check_restricted() || check_secure())
11397 	return NULL;
11398 
11399     /* get a name for the temp file */
11400     if ((tempname = vim_tempname('o', FALSE)) == NULL)
11401     {
11402 	EMSG(_(e_notmp));
11403 	return NULL;
11404     }
11405 
11406     /* Add the redirection stuff */
11407     command = make_filter_cmd(cmd, infile, tempname);
11408     if (command == NULL)
11409 	goto done;
11410 
11411     /*
11412      * Call the shell to execute the command (errors are ignored).
11413      * Don't check timestamps here.
11414      */
11415     ++no_check_timestamps;
11416     call_shell(command, SHELL_DOOUT | SHELL_EXPAND | flags);
11417     --no_check_timestamps;
11418 
11419     vim_free(command);
11420 
11421     /*
11422      * read the names from the file into memory
11423      */
11424 # ifdef VMS
11425     /* created temporary file is not always readable as binary */
11426     fd = mch_fopen((char *)tempname, "r");
11427 # else
11428     fd = mch_fopen((char *)tempname, READBIN);
11429 # endif
11430 
11431     if (fd == NULL)
11432     {
11433 	EMSG2(_(e_notopen), tempname);
11434 	goto done;
11435     }
11436 
11437     fseek(fd, 0L, SEEK_END);
11438     len = ftell(fd);		    /* get size of temp file */
11439     fseek(fd, 0L, SEEK_SET);
11440 
11441     buffer = alloc(len + 1);
11442     if (buffer != NULL)
11443 	i = (int)fread((char *)buffer, (size_t)1, (size_t)len, fd);
11444     fclose(fd);
11445     mch_remove(tempname);
11446     if (buffer == NULL)
11447 	goto done;
11448 #ifdef VMS
11449     len = i;	/* VMS doesn't give us what we asked for... */
11450 #endif
11451     if (i != len)
11452     {
11453 	EMSG2(_(e_notread), tempname);
11454 	VIM_CLEAR(buffer);
11455     }
11456     else if (ret_len == NULL)
11457     {
11458 	/* Change NUL into SOH, otherwise the string is truncated. */
11459 	for (i = 0; i < len; ++i)
11460 	    if (buffer[i] == NUL)
11461 		buffer[i] = 1;
11462 
11463 	buffer[len] = NUL;	/* make sure the buffer is terminated */
11464     }
11465     else
11466 	*ret_len = len;
11467 
11468 done:
11469     vim_free(tempname);
11470     return buffer;
11471 }
11472 #endif
11473 
11474 /*
11475  * Free the list of files returned by expand_wildcards() or other expansion
11476  * functions.
11477  */
11478     void
11479 FreeWild(int count, char_u **files)
11480 {
11481     if (count <= 0 || files == NULL)
11482 	return;
11483     while (count--)
11484 	vim_free(files[count]);
11485     vim_free(files);
11486 }
11487 
11488 /*
11489  * Return TRUE when need to go to Insert mode because of 'insertmode'.
11490  * Don't do this when still processing a command or a mapping.
11491  * Don't do this when inside a ":normal" command.
11492  */
11493     int
11494 goto_im(void)
11495 {
11496     return (p_im && stuff_empty() && typebuf_typed());
11497 }
11498 
11499 /*
11500  * Returns the isolated name of the shell in allocated memory:
11501  * - Skip beyond any path.  E.g., "/usr/bin/csh -f" -> "csh -f".
11502  * - Remove any argument.  E.g., "csh -f" -> "csh".
11503  * But don't allow a space in the path, so that this works:
11504  *   "/usr/bin/csh --rcfile ~/.cshrc"
11505  * But don't do that for Windows, it's common to have a space in the path.
11506  */
11507     char_u *
11508 get_isolated_shell_name(void)
11509 {
11510     char_u *p;
11511 
11512 #ifdef WIN3264
11513     p = gettail(p_sh);
11514     p = vim_strnsave(p, (int)(skiptowhite(p) - p));
11515 #else
11516     p = skiptowhite(p_sh);
11517     if (*p == NUL)
11518     {
11519 	/* No white space, use the tail. */
11520 	p = vim_strsave(gettail(p_sh));
11521     }
11522     else
11523     {
11524 	char_u  *p1, *p2;
11525 
11526 	/* Find the last path separator before the space. */
11527 	p1 = p_sh;
11528 	for (p2 = p_sh; p2 < p; MB_PTR_ADV(p2))
11529 	    if (vim_ispathsep(*p2))
11530 		p1 = p2 + 1;
11531 	p = vim_strnsave(p1, (int)(p - p1));
11532     }
11533 #endif
11534     return p;
11535 }
11536