xref: /vim-8.2.3635/src/misc2.c (revision abfa9efb)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * misc2.c: Various functions.
12  */
13 #include "vim.h"
14 
15 static char_u	*username = NULL; /* cached result of mch_get_user_name() */
16 
17 static char_u	*ff_expand_buffer = NULL; /* used for expanding filenames */
18 
19 #if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
20 static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol));
21 
22 /*
23  * Return TRUE if in the current mode we need to use virtual.
24  */
25     int
26 virtual_active()
27 {
28     /* While an operator is being executed we return "virtual_op", because
29      * VIsual_active has already been reset, thus we can't check for "block"
30      * being used. */
31     if (virtual_op != MAYBE)
32 	return virtual_op;
33     return (ve_flags == VE_ALL
34 	    || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
35 	    || ((ve_flags & VE_INSERT) && (State & INSERT)));
36 }
37 
38 /*
39  * Get the screen position of the cursor.
40  */
41     int
42 getviscol()
43 {
44     colnr_T	x;
45 
46     getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
47     return (int)x;
48 }
49 
50 /*
51  * Get the screen position of character col with a coladd in the cursor line.
52  */
53     int
54 getviscol2(col, coladd)
55     colnr_T	col;
56     colnr_T	coladd;
57 {
58     colnr_T	x;
59     pos_T	pos;
60 
61     pos.lnum = curwin->w_cursor.lnum;
62     pos.col = col;
63     pos.coladd = coladd;
64     getvvcol(curwin, &pos, &x, NULL, NULL);
65     return (int)x;
66 }
67 
68 /*
69  * Go to column "wcol", and add/insert white space as necessary to get the
70  * cursor in that column.
71  * The caller must have saved the cursor line for undo!
72  */
73     int
74 coladvance_force(wcol)
75     colnr_T wcol;
76 {
77     int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);
78 
79     if (wcol == MAXCOL)
80 	curwin->w_valid &= ~VALID_VIRTCOL;
81     else
82     {
83 	/* Virtcol is valid */
84 	curwin->w_valid |= VALID_VIRTCOL;
85 	curwin->w_virtcol = wcol;
86     }
87     return rc;
88 }
89 #endif
90 
91 /*
92  * Try to advance the Cursor to the specified screen column.
93  * If virtual editing: fine tune the cursor position.
94  * Note that all virtual positions off the end of a line should share
95  * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
96  * beginning at coladd 0.
97  *
98  * return OK if desired column is reached, FAIL if not
99  */
100     int
101 coladvance(wcol)
102     colnr_T	wcol;
103 {
104     int rc = getvpos(&curwin->w_cursor, wcol);
105 
106     if (wcol == MAXCOL || rc == FAIL)
107 	curwin->w_valid &= ~VALID_VIRTCOL;
108     else if (*ml_get_cursor() != TAB)
109     {
110 	/* Virtcol is valid when not on a TAB */
111 	curwin->w_valid |= VALID_VIRTCOL;
112 	curwin->w_virtcol = wcol;
113     }
114     return rc;
115 }
116 
117 /*
118  * Return in "pos" the position of the cursor advanced to screen column "wcol".
119  * return OK if desired column is reached, FAIL if not
120  */
121     int
122 getvpos(pos, wcol)
123     pos_T   *pos;
124     colnr_T wcol;
125 {
126 #ifdef FEAT_VIRTUALEDIT
127     return coladvance2(pos, FALSE, virtual_active(), wcol);
128 }
129 
130     static int
131 coladvance2(pos, addspaces, finetune, wcol)
132     pos_T	*pos;
133     int		addspaces;	/* change the text to achieve our goal? */
134     int		finetune;	/* change char offset for the exact column */
135     colnr_T	wcol;		/* column to move to */
136 {
137 #endif
138     int		idx;
139     char_u	*ptr;
140     char_u	*line;
141     colnr_T	col = 0;
142     int		csize = 0;
143     int		one_more;
144 #ifdef FEAT_LINEBREAK
145     int		head = 0;
146 #endif
147 
148     one_more = (State & INSERT)
149 		    || restart_edit != NUL
150 		    || (VIsual_active && *p_sel != 'o')
151 #ifdef FEAT_VIRTUALEDIT
152 		    || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL)
153 #endif
154 		    ;
155     line = ml_get_buf(curbuf, pos->lnum, FALSE);
156 
157     if (wcol >= MAXCOL)
158     {
159 	    idx = (int)STRLEN(line) - 1 + one_more;
160 	    col = wcol;
161 
162 #ifdef FEAT_VIRTUALEDIT
163 	    if ((addspaces || finetune) && !VIsual_active)
164 	    {
165 		curwin->w_curswant = linetabsize(line) + one_more;
166 		if (curwin->w_curswant > 0)
167 		    --curwin->w_curswant;
168 	    }
169 #endif
170     }
171     else
172     {
173 #ifdef FEAT_VIRTUALEDIT
174 	int width = W_WIDTH(curwin) - win_col_off(curwin);
175 
176 	if (finetune
177 		&& curwin->w_p_wrap
178 # ifdef FEAT_VERTSPLIT
179 		&& curwin->w_width != 0
180 # endif
181 		&& wcol >= (colnr_T)width)
182 	{
183 	    csize = linetabsize(line);
184 	    if (csize > 0)
185 		csize--;
186 
187 	    if (wcol / width > (colnr_T)csize / width
188 		    && ((State & INSERT) == 0 || (int)wcol > csize + 1))
189 	    {
190 		/* In case of line wrapping don't move the cursor beyond the
191 		 * right screen edge.  In Insert mode allow going just beyond
192 		 * the last character (like what happens when typing and
193 		 * reaching the right window edge). */
194 		wcol = (csize / width + 1) * width - 1;
195 	    }
196 	}
197 #endif
198 
199 	ptr = line;
200 	while (col <= wcol && *ptr != NUL)
201 	{
202 	    /* Count a tab for what it's worth (if list mode not on) */
203 #ifdef FEAT_LINEBREAK
204 	    csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
205 	    mb_ptr_adv(ptr);
206 #else
207 	    csize = lbr_chartabsize_adv(line, &ptr, col);
208 #endif
209 	    col += csize;
210 	}
211 	idx = (int)(ptr - line);
212 	/*
213 	 * Handle all the special cases.  The virtual_active() check
214 	 * is needed to ensure that a virtual position off the end of
215 	 * a line has the correct indexing.  The one_more comparison
216 	 * replaces an explicit add of one_more later on.
217 	 */
218 	if (col > wcol || (!virtual_active() && one_more == 0))
219 	{
220 	    idx -= 1;
221 # ifdef FEAT_LINEBREAK
222 	    /* Don't count the chars from 'showbreak'. */
223 	    csize -= head;
224 # endif
225 	    col -= csize;
226 	}
227 
228 #ifdef FEAT_VIRTUALEDIT
229 	if (virtual_active()
230 		&& addspaces
231 		&& ((col != wcol && col != wcol + 1) || csize > 1))
232 	{
233 	    /* 'virtualedit' is set: The difference between wcol and col is
234 	     * filled with spaces. */
235 
236 	    if (line[idx] == NUL)
237 	    {
238 		/* Append spaces */
239 		int	correct = wcol - col;
240 		char_u	*newline = alloc(idx + correct + 1);
241 		int	t;
242 
243 		if (newline == NULL)
244 		    return FAIL;
245 
246 		for (t = 0; t < idx; ++t)
247 		    newline[t] = line[t];
248 
249 		for (t = 0; t < correct; ++t)
250 		    newline[t + idx] = ' ';
251 
252 		newline[idx + correct] = NUL;
253 
254 		ml_replace(pos->lnum, newline, FALSE);
255 		changed_bytes(pos->lnum, (colnr_T)idx);
256 		idx += correct;
257 		col = wcol;
258 	    }
259 	    else
260 	    {
261 		/* Break a tab */
262 		int	linelen = (int)STRLEN(line);
263 		int	correct = wcol - col - csize + 1; /* negative!! */
264 		char_u	*newline;
265 		int	t, s = 0;
266 		int	v;
267 
268 		if (-correct > csize)
269 		    return FAIL;
270 
271 		newline = alloc(linelen + csize);
272 		if (newline == NULL)
273 		    return FAIL;
274 
275 		for (t = 0; t < linelen; t++)
276 		{
277 		    if (t != idx)
278 			newline[s++] = line[t];
279 		    else
280 			for (v = 0; v < csize; v++)
281 			    newline[s++] = ' ';
282 		}
283 
284 		newline[linelen + csize - 1] = NUL;
285 
286 		ml_replace(pos->lnum, newline, FALSE);
287 		changed_bytes(pos->lnum, idx);
288 		idx += (csize - 1 + correct);
289 		col += correct;
290 	    }
291 	}
292 #endif
293     }
294 
295     if (idx < 0)
296 	pos->col = 0;
297     else
298 	pos->col = idx;
299 
300 #ifdef FEAT_VIRTUALEDIT
301     pos->coladd = 0;
302 
303     if (finetune)
304     {
305 	if (wcol == MAXCOL)
306 	{
307 	    /* The width of the last character is used to set coladd. */
308 	    if (!one_more)
309 	    {
310 		colnr_T	    scol, ecol;
311 
312 		getvcol(curwin, pos, &scol, NULL, &ecol);
313 		pos->coladd = ecol - scol;
314 	    }
315 	}
316 	else
317 	{
318 	    int b = (int)wcol - (int)col;
319 
320 	    /* The difference between wcol and col is used to set coladd. */
321 	    if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin)))
322 		pos->coladd = b;
323 
324 	    col += b;
325 	}
326     }
327 #endif
328 
329 #ifdef FEAT_MBYTE
330     /* prevent from moving onto a trail byte */
331     if (has_mbyte)
332 	mb_adjustpos(curbuf, pos);
333 #endif
334 
335     if (col < wcol)
336 	return FAIL;
337     return OK;
338 }
339 
340 /*
341  * Increment the cursor position.  See inc() for return values.
342  */
343     int
344 inc_cursor()
345 {
346     return inc(&curwin->w_cursor);
347 }
348 
349 /*
350  * Increment the line pointer "lp" crossing line boundaries as necessary.
351  * Return 1 when going to the next line.
352  * Return 2 when moving forward onto a NUL at the end of the line).
353  * Return -1 when at the end of file.
354  * Return 0 otherwise.
355  */
356     int
357 inc(lp)
358     pos_T  *lp;
359 {
360     char_u  *p = ml_get_pos(lp);
361 
362     if (*p != NUL)	/* still within line, move to next char (may be NUL) */
363     {
364 #ifdef FEAT_MBYTE
365 	if (has_mbyte)
366 	{
367 	    int l = (*mb_ptr2len)(p);
368 
369 	    lp->col += l;
370 	    return ((p[l] != NUL) ? 0 : 2);
371 	}
372 #endif
373 	lp->col++;
374 #ifdef FEAT_VIRTUALEDIT
375 	lp->coladd = 0;
376 #endif
377 	return ((p[1] != NUL) ? 0 : 2);
378     }
379     if (lp->lnum != curbuf->b_ml.ml_line_count)     /* there is a next line */
380     {
381 	lp->col = 0;
382 	lp->lnum++;
383 #ifdef FEAT_VIRTUALEDIT
384 	lp->coladd = 0;
385 #endif
386 	return 1;
387     }
388     return -1;
389 }
390 
391 /*
392  * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
393  */
394     int
395 incl(lp)
396     pos_T    *lp;
397 {
398     int	    r;
399 
400     if ((r = inc(lp)) >= 1 && lp->col)
401 	r = inc(lp);
402     return r;
403 }
404 
405 /*
406  * dec(p)
407  *
408  * Decrement the line pointer 'p' crossing line boundaries as necessary.
409  * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
410  */
411     int
412 dec_cursor()
413 {
414     return dec(&curwin->w_cursor);
415 }
416 
417     int
418 dec(lp)
419     pos_T  *lp;
420 {
421     char_u	*p;
422 
423 #ifdef FEAT_VIRTUALEDIT
424     lp->coladd = 0;
425 #endif
426     if (lp->col > 0)		/* still within line */
427     {
428 	lp->col--;
429 #ifdef FEAT_MBYTE
430 	if (has_mbyte)
431 	{
432 	    p = ml_get(lp->lnum);
433 	    lp->col -= (*mb_head_off)(p, p + lp->col);
434 	}
435 #endif
436 	return 0;
437     }
438     if (lp->lnum > 1)		/* there is a prior line */
439     {
440 	lp->lnum--;
441 	p = ml_get(lp->lnum);
442 	lp->col = (colnr_T)STRLEN(p);
443 #ifdef FEAT_MBYTE
444 	if (has_mbyte)
445 	    lp->col -= (*mb_head_off)(p, p + lp->col);
446 #endif
447 	return 1;
448     }
449     return -1;			/* at start of file */
450 }
451 
452 /*
453  * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
454  */
455     int
456 decl(lp)
457     pos_T    *lp;
458 {
459     int	    r;
460 
461     if ((r = dec(lp)) == 1 && lp->col)
462 	r = dec(lp);
463     return r;
464 }
465 
466 /*
467  * Get the line number relative to the current cursor position, i.e. the
468  * difference between line number and cursor position. Only look for lines that
469  * can be visible, folded lines don't count.
470  */
471     linenr_T
472 get_cursor_rel_lnum(wp, lnum)
473     win_T	*wp;
474     linenr_T	lnum;		    /* line number to get the result for */
475 {
476     linenr_T	cursor = wp->w_cursor.lnum;
477     linenr_T	retval = 0;
478 
479 #ifdef FEAT_FOLDING
480     if (hasAnyFolding(wp))
481     {
482 	if (lnum > cursor)
483 	{
484 	    while (lnum > cursor)
485 	    {
486 		(void)hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
487 		/* if lnum and cursor are in the same fold,
488 		 * now lnum <= cursor */
489 		if (lnum > cursor)
490 		    retval++;
491 		lnum--;
492 	    }
493 	}
494 	else if (lnum < cursor)
495 	{
496 	    while (lnum < cursor)
497 	    {
498 		(void)hasFoldingWin(wp, lnum, NULL, &lnum, TRUE, NULL);
499 		/* if lnum and cursor are in the same fold,
500 		 * now lnum >= cursor */
501 		if (lnum < cursor)
502 		    retval--;
503 		lnum++;
504 	    }
505 	}
506 	/* else if (lnum == cursor)
507 	 *     retval = 0;
508 	 */
509     }
510     else
511 #endif
512 	retval = lnum - cursor;
513 
514     return retval;
515 }
516 
517 /*
518  * Make sure curwin->w_cursor.lnum is valid.
519  */
520     void
521 check_cursor_lnum()
522 {
523     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
524     {
525 #ifdef FEAT_FOLDING
526 	/* If there is a closed fold at the end of the file, put the cursor in
527 	 * its first line.  Otherwise in the last line. */
528 	if (!hasFolding(curbuf->b_ml.ml_line_count,
529 						&curwin->w_cursor.lnum, NULL))
530 #endif
531 	    curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
532     }
533     if (curwin->w_cursor.lnum <= 0)
534 	curwin->w_cursor.lnum = 1;
535 }
536 
537 /*
538  * Make sure curwin->w_cursor.col is valid.
539  */
540     void
541 check_cursor_col()
542 {
543     check_cursor_col_win(curwin);
544 }
545 
546 /*
547  * Make sure win->w_cursor.col is valid.
548  */
549     void
550 check_cursor_col_win(win)
551     win_T *win;
552 {
553     colnr_T len;
554 #ifdef FEAT_VIRTUALEDIT
555     colnr_T oldcol = win->w_cursor.col;
556     colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd;
557 #endif
558 
559     len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE));
560     if (len == 0)
561 	win->w_cursor.col = 0;
562     else if (win->w_cursor.col >= len)
563     {
564 	/* Allow cursor past end-of-line when:
565 	 * - in Insert mode or restarting Insert mode
566 	 * - in Visual mode and 'selection' isn't "old"
567 	 * - 'virtualedit' is set */
568 	if ((State & INSERT) || restart_edit
569 		|| (VIsual_active && *p_sel != 'o')
570 #ifdef FEAT_VIRTUALEDIT
571 		|| (ve_flags & VE_ONEMORE)
572 #endif
573 		|| virtual_active())
574 	    win->w_cursor.col = len;
575 	else
576 	{
577 	    win->w_cursor.col = len - 1;
578 #ifdef FEAT_MBYTE
579 	    /* Move the cursor to the head byte. */
580 	    if (has_mbyte)
581 		mb_adjustpos(win->w_buffer, &win->w_cursor);
582 #endif
583 	}
584     }
585     else if (win->w_cursor.col < 0)
586 	win->w_cursor.col = 0;
587 
588 #ifdef FEAT_VIRTUALEDIT
589     /* If virtual editing is on, we can leave the cursor on the old position,
590      * only we must set it to virtual.  But don't do it when at the end of the
591      * line. */
592     if (oldcol == MAXCOL)
593 	win->w_cursor.coladd = 0;
594     else if (ve_flags == VE_ALL)
595     {
596 	if (oldcoladd > win->w_cursor.col)
597 	    win->w_cursor.coladd = oldcoladd - win->w_cursor.col;
598 	else
599 	    /* avoid weird number when there is a miscalculation or overflow */
600 	    win->w_cursor.coladd = 0;
601     }
602 #endif
603 }
604 
605 /*
606  * make sure curwin->w_cursor in on a valid character
607  */
608     void
609 check_cursor()
610 {
611     check_cursor_lnum();
612     check_cursor_col();
613 }
614 
615 #if defined(FEAT_TEXTOBJ) || defined(PROTO)
616 /*
617  * Make sure curwin->w_cursor is not on the NUL at the end of the line.
618  * Allow it when in Visual mode and 'selection' is not "old".
619  */
620     void
621 adjust_cursor_col()
622 {
623     if (curwin->w_cursor.col > 0
624 	    && (!VIsual_active || *p_sel == 'o')
625 	    && gchar_cursor() == NUL)
626 	--curwin->w_cursor.col;
627 }
628 #endif
629 
630 /*
631  * When curwin->w_leftcol has changed, adjust the cursor position.
632  * Return TRUE if the cursor was moved.
633  */
634     int
635 leftcol_changed()
636 {
637     long	lastcol;
638     colnr_T	s, e;
639     int		retval = FALSE;
640 
641     changed_cline_bef_curs();
642     lastcol = curwin->w_leftcol + W_WIDTH(curwin) - curwin_col_off() - 1;
643     validate_virtcol();
644 
645     /*
646      * If the cursor is right or left of the screen, move it to last or first
647      * character.
648      */
649     if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso))
650     {
651 	retval = TRUE;
652 	coladvance((colnr_T)(lastcol - p_siso));
653     }
654     else if (curwin->w_virtcol < curwin->w_leftcol + p_siso)
655     {
656 	retval = TRUE;
657 	(void)coladvance((colnr_T)(curwin->w_leftcol + p_siso));
658     }
659 
660     /*
661      * If the start of the character under the cursor is not on the screen,
662      * advance the cursor one more char.  If this fails (last char of the
663      * line) adjust the scrolling.
664      */
665     getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
666     if (e > (colnr_T)lastcol)
667     {
668 	retval = TRUE;
669 	coladvance(s - 1);
670     }
671     else if (s < curwin->w_leftcol)
672     {
673 	retval = TRUE;
674 	if (coladvance(e + 1) == FAIL)	/* there isn't another character */
675 	{
676 	    curwin->w_leftcol = s;	/* adjust w_leftcol instead */
677 	    changed_cline_bef_curs();
678 	}
679     }
680 
681     if (retval)
682 	curwin->w_set_curswant = TRUE;
683     redraw_later(NOT_VALID);
684     return retval;
685 }
686 
687 /**********************************************************************
688  * Various routines dealing with allocation and deallocation of memory.
689  */
690 
691 #if defined(MEM_PROFILE) || defined(PROTO)
692 
693 # define MEM_SIZES  8200
694 static long_u mem_allocs[MEM_SIZES];
695 static long_u mem_frees[MEM_SIZES];
696 static long_u mem_allocated;
697 static long_u mem_freed;
698 static long_u mem_peak;
699 static long_u num_alloc;
700 static long_u num_freed;
701 
702 static void mem_pre_alloc_s __ARGS((size_t *sizep));
703 static void mem_pre_alloc_l __ARGS((long_u *sizep));
704 static void mem_post_alloc __ARGS((void **pp, size_t size));
705 static void mem_pre_free __ARGS((void **pp));
706 
707     static void
708 mem_pre_alloc_s(sizep)
709     size_t *sizep;
710 {
711     *sizep += sizeof(size_t);
712 }
713 
714     static void
715 mem_pre_alloc_l(sizep)
716     long_u *sizep;
717 {
718     *sizep += sizeof(size_t);
719 }
720 
721     static void
722 mem_post_alloc(pp, size)
723     void **pp;
724     size_t size;
725 {
726     if (*pp == NULL)
727 	return;
728     size -= sizeof(size_t);
729     *(long_u *)*pp = size;
730     if (size <= MEM_SIZES-1)
731 	mem_allocs[size-1]++;
732     else
733 	mem_allocs[MEM_SIZES-1]++;
734     mem_allocated += size;
735     if (mem_allocated - mem_freed > mem_peak)
736 	mem_peak = mem_allocated - mem_freed;
737     num_alloc++;
738     *pp = (void *)((char *)*pp + sizeof(size_t));
739 }
740 
741     static void
742 mem_pre_free(pp)
743     void **pp;
744 {
745     long_u size;
746 
747     *pp = (void *)((char *)*pp - sizeof(size_t));
748     size = *(size_t *)*pp;
749     if (size <= MEM_SIZES-1)
750 	mem_frees[size-1]++;
751     else
752 	mem_frees[MEM_SIZES-1]++;
753     mem_freed += size;
754     num_freed++;
755 }
756 
757 /*
758  * called on exit via atexit()
759  */
760     void
761 vim_mem_profile_dump()
762 {
763     int i, j;
764 
765     printf("\r\n");
766     j = 0;
767     for (i = 0; i < MEM_SIZES - 1; i++)
768     {
769 	if (mem_allocs[i] || mem_frees[i])
770 	{
771 	    if (mem_frees[i] > mem_allocs[i])
772 		printf("\r\n%s", _("ERROR: "));
773 	    printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]);
774 	    j++;
775 	    if (j > 3)
776 	    {
777 		j = 0;
778 		printf("\r\n");
779 	    }
780 	}
781     }
782 
783     i = MEM_SIZES - 1;
784     if (mem_allocs[i])
785     {
786 	printf("\r\n");
787 	if (mem_frees[i] > mem_allocs[i])
788 	    puts(_("ERROR: "));
789 	printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]);
790     }
791 
792     printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"),
793 	    mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak);
794     printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"),
795 	    num_alloc, num_freed);
796 }
797 
798 #endif /* MEM_PROFILE */
799 
800 #ifdef FEAT_EVAL
801 static int alloc_does_fail __ARGS((long_u size));
802 
803     static int
804 alloc_does_fail(size)
805     long_u size;
806 {
807     if (alloc_fail_countdown == 0)
808     {
809 	if (--alloc_fail_repeat <= 0)
810 	    alloc_fail_id = 0;
811 	do_outofmem_msg(size);
812 	return TRUE;
813     }
814     --alloc_fail_countdown;
815     return FALSE;
816 }
817 #endif
818 
819 /*
820  * Some memory is reserved for error messages and for being able to
821  * call mf_release_all(), which needs some memory for mf_trans_add().
822  */
823 #if defined(MSDOS) && !defined(DJGPP)
824 # define SMALL_MEM
825 # define KEEP_ROOM 8192L
826 #else
827 # define KEEP_ROOM (2 * 8192L)
828 #endif
829 #define KEEP_ROOM_KB (KEEP_ROOM / 1024L)
830 
831 /*
832  * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc().
833  * Use lalloc for larger blocks.
834  */
835     char_u *
836 alloc(size)
837     unsigned	    size;
838 {
839     return (lalloc((long_u)size, TRUE));
840 }
841 
842 /*
843  * alloc() with an ID for alloc_fail().
844  */
845     char_u *
846 alloc_id(size, id)
847     unsigned	size;
848     alloc_id_T	id UNUSED;
849 {
850 #ifdef FEAT_EVAL
851     if (alloc_fail_id == id && alloc_does_fail((long_u)size))
852 	return NULL;
853 #endif
854     return (lalloc((long_u)size, TRUE));
855 }
856 
857 /*
858  * Allocate memory and set all bytes to zero.
859  */
860     char_u *
861 alloc_clear(size)
862     unsigned	    size;
863 {
864     char_u *p;
865 
866     p = lalloc((long_u)size, TRUE);
867     if (p != NULL)
868 	(void)vim_memset(p, 0, (size_t)size);
869     return p;
870 }
871 
872 /*
873  * alloc() with check for maximum line length
874  */
875     char_u *
876 alloc_check(size)
877     unsigned	    size;
878 {
879 #if !defined(UNIX) && !defined(__EMX__)
880     if (sizeof(int) == 2 && size > 0x7fff)
881     {
882 	/* Don't hide this message */
883 	emsg_silent = 0;
884 	EMSG(_("E340: Line is becoming too long"));
885 	return NULL;
886     }
887 #endif
888     return (lalloc((long_u)size, TRUE));
889 }
890 
891 /*
892  * Allocate memory like lalloc() and set all bytes to zero.
893  */
894     char_u *
895 lalloc_clear(size, message)
896     long_u	size;
897     int		message;
898 {
899     char_u *p;
900 
901     p = (lalloc(size, message));
902     if (p != NULL)
903 	(void)vim_memset(p, 0, (size_t)size);
904     return p;
905 }
906 
907 /*
908  * Low level memory allocation function.
909  * This is used often, KEEP IT FAST!
910  */
911     char_u *
912 lalloc(size, message)
913     long_u	size;
914     int		message;
915 {
916     char_u	*p;		    /* pointer to new storage space */
917     static int	releasing = FALSE;  /* don't do mf_release_all() recursive */
918     int		try_again;
919 #if defined(HAVE_AVAIL_MEM) && !defined(SMALL_MEM)
920     static long_u allocated = 0;    /* allocated since last avail check */
921 #endif
922 
923     /* Safety check for allocating zero bytes */
924     if (size == 0)
925     {
926 	/* Don't hide this message */
927 	emsg_silent = 0;
928 	EMSGN(_("E341: Internal error: lalloc(%ld, )"), size);
929 	return NULL;
930     }
931 
932 #ifdef MEM_PROFILE
933     mem_pre_alloc_l(&size);
934 #endif
935 
936 #if defined(MSDOS) && !defined(DJGPP)
937     if (size >= 0xfff0)		/* in MSDOS we can't deal with >64K blocks */
938 	p = NULL;
939     else
940 #endif
941 
942     /*
943      * Loop when out of memory: Try to release some memfile blocks and
944      * if some blocks are released call malloc again.
945      */
946     for (;;)
947     {
948 	/*
949 	 * Handle three kind of systems:
950 	 * 1. No check for available memory: Just return.
951 	 * 2. Slow check for available memory: call mch_avail_mem() after
952 	 *    allocating KEEP_ROOM amount of memory.
953 	 * 3. Strict check for available memory: call mch_avail_mem()
954 	 */
955 	if ((p = (char_u *)malloc((size_t)size)) != NULL)
956 	{
957 #ifndef HAVE_AVAIL_MEM
958 	    /* 1. No check for available memory: Just return. */
959 	    goto theend;
960 #else
961 # ifndef SMALL_MEM
962 	    /* 2. Slow check for available memory: call mch_avail_mem() after
963 	     *    allocating (KEEP_ROOM / 2) amount of memory. */
964 	    allocated += size;
965 	    if (allocated < KEEP_ROOM / 2)
966 		goto theend;
967 	    allocated = 0;
968 # endif
969 	    /* 3. check for available memory: call mch_avail_mem() */
970 	    if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing)
971 	    {
972 		free((char *)p);	/* System is low... no go! */
973 		p = NULL;
974 	    }
975 	    else
976 		goto theend;
977 #endif
978 	}
979 	/*
980 	 * Remember that mf_release_all() is being called to avoid an endless
981 	 * loop, because mf_release_all() may call alloc() recursively.
982 	 */
983 	if (releasing)
984 	    break;
985 	releasing = TRUE;
986 
987 	clear_sb_text();	      /* free any scrollback text */
988 	try_again = mf_release_all(); /* release as many blocks as possible */
989 
990 	releasing = FALSE;
991 	if (!try_again)
992 	    break;
993     }
994 
995     if (message && p == NULL)
996 	do_outofmem_msg(size);
997 
998 theend:
999 #ifdef MEM_PROFILE
1000     mem_post_alloc((void **)&p, (size_t)size);
1001 #endif
1002     return p;
1003 }
1004 
1005 /*
1006  * lalloc() with an ID for alloc_fail().
1007  */
1008     char_u *
1009 lalloc_id(size, message, id)
1010     long_u	size;
1011     int		message;
1012     alloc_id_T	id UNUSED;
1013 {
1014 #ifdef FEAT_EVAL
1015     if (alloc_fail_id == id && alloc_does_fail(size))
1016 	return NULL;
1017 #endif
1018     return (lalloc((long_u)size, message));
1019 }
1020 
1021 #if defined(MEM_PROFILE) || defined(PROTO)
1022 /*
1023  * realloc() with memory profiling.
1024  */
1025     void *
1026 mem_realloc(ptr, size)
1027     void *ptr;
1028     size_t size;
1029 {
1030     void *p;
1031 
1032     mem_pre_free(&ptr);
1033     mem_pre_alloc_s(&size);
1034 
1035     p = realloc(ptr, size);
1036 
1037     mem_post_alloc(&p, size);
1038 
1039     return p;
1040 }
1041 #endif
1042 
1043 /*
1044 * Avoid repeating the error message many times (they take 1 second each).
1045 * Did_outofmem_msg is reset when a character is read.
1046 */
1047     void
1048 do_outofmem_msg(size)
1049     long_u	size;
1050 {
1051     if (!did_outofmem_msg)
1052     {
1053 	/* Don't hide this message */
1054 	emsg_silent = 0;
1055 
1056 	/* Must come first to avoid coming back here when printing the error
1057 	 * message fails, e.g. when setting v:errmsg. */
1058 	did_outofmem_msg = TRUE;
1059 
1060 	EMSGN(_("E342: Out of memory!  (allocating %lu bytes)"), size);
1061     }
1062 }
1063 
1064 #if defined(EXITFREE) || defined(PROTO)
1065 
1066 # if defined(FEAT_SEARCHPATH)
1067 static void free_findfile __ARGS((void));
1068 # endif
1069 
1070 /*
1071  * Free everything that we allocated.
1072  * Can be used to detect memory leaks, e.g., with ccmalloc.
1073  * NOTE: This is tricky!  Things are freed that functions depend on.  Don't be
1074  * surprised if Vim crashes...
1075  * Some things can't be freed, esp. things local to a library function.
1076  */
1077     void
1078 free_all_mem()
1079 {
1080     buf_T	*buf, *nextbuf;
1081     static int	entered = FALSE;
1082 
1083     /* When we cause a crash here it is caught and Vim tries to exit cleanly.
1084      * Don't try freeing everything again. */
1085     if (entered)
1086 	return;
1087     entered = TRUE;
1088 
1089 # ifdef FEAT_AUTOCMD
1090     /* Don't want to trigger autocommands from here on. */
1091     block_autocmds();
1092 # endif
1093 
1094 # ifdef FEAT_WINDOWS
1095     /* Close all tabs and windows.  Reset 'equalalways' to avoid redraws. */
1096     p_ea = FALSE;
1097     if (first_tabpage->tp_next != NULL)
1098 	do_cmdline_cmd((char_u *)"tabonly!");
1099     if (firstwin != lastwin)
1100 	do_cmdline_cmd((char_u *)"only!");
1101 # endif
1102 
1103 # if defined(FEAT_SPELL)
1104     /* Free all spell info. */
1105     spell_free_all();
1106 # endif
1107 
1108 # if defined(FEAT_USR_CMDS)
1109     /* Clear user commands (before deleting buffers). */
1110     ex_comclear(NULL);
1111 # endif
1112 
1113 # ifdef FEAT_MENU
1114     /* Clear menus. */
1115     do_cmdline_cmd((char_u *)"aunmenu *");
1116 #  ifdef FEAT_MULTI_LANG
1117     do_cmdline_cmd((char_u *)"menutranslate clear");
1118 #  endif
1119 # endif
1120 
1121     /* Clear mappings, abbreviations, breakpoints. */
1122     do_cmdline_cmd((char_u *)"lmapclear");
1123     do_cmdline_cmd((char_u *)"xmapclear");
1124     do_cmdline_cmd((char_u *)"mapclear");
1125     do_cmdline_cmd((char_u *)"mapclear!");
1126     do_cmdline_cmd((char_u *)"abclear");
1127 # if defined(FEAT_EVAL)
1128     do_cmdline_cmd((char_u *)"breakdel *");
1129 # endif
1130 # if defined(FEAT_PROFILE)
1131     do_cmdline_cmd((char_u *)"profdel *");
1132 # endif
1133 # if defined(FEAT_KEYMAP)
1134     do_cmdline_cmd((char_u *)"set keymap=");
1135 #endif
1136 
1137 # ifdef FEAT_TITLE
1138     free_titles();
1139 # endif
1140 # if defined(FEAT_SEARCHPATH)
1141     free_findfile();
1142 # endif
1143 
1144     /* Obviously named calls. */
1145 # if defined(FEAT_AUTOCMD)
1146     free_all_autocmds();
1147 # endif
1148     clear_termcodes();
1149     free_all_options();
1150     free_all_marks();
1151     alist_clear(&global_alist);
1152     free_homedir();
1153 # if defined(FEAT_CMDL_COMPL)
1154     free_users();
1155 # endif
1156     free_search_patterns();
1157     free_old_sub();
1158     free_last_insert();
1159     free_prev_shellcmd();
1160     free_regexp_stuff();
1161     free_tag_stuff();
1162     free_cd_dir();
1163 # ifdef FEAT_SIGNS
1164     free_signs();
1165 # endif
1166 # ifdef FEAT_EVAL
1167     set_expr_line(NULL);
1168 # endif
1169 # ifdef FEAT_DIFF
1170     diff_clear(curtab);
1171 # endif
1172     clear_sb_text();	      /* free any scrollback text */
1173 
1174     /* Free some global vars. */
1175     vim_free(username);
1176 # ifdef FEAT_CLIPBOARD
1177     vim_regfree(clip_exclude_prog);
1178 # endif
1179     vim_free(last_cmdline);
1180 # ifdef FEAT_CMDHIST
1181     vim_free(new_last_cmdline);
1182 # endif
1183     set_keep_msg(NULL, 0);
1184     vim_free(ff_expand_buffer);
1185 
1186     /* Clear cmdline history. */
1187     p_hi = 0;
1188 # ifdef FEAT_CMDHIST
1189     init_history();
1190 # endif
1191 
1192 #ifdef FEAT_QUICKFIX
1193     {
1194 	win_T	    *win;
1195 	tabpage_T   *tab;
1196 
1197 	qf_free_all(NULL);
1198 	/* Free all location lists */
1199 	FOR_ALL_TAB_WINDOWS(tab, win)
1200 	    qf_free_all(win);
1201     }
1202 #endif
1203 
1204     /* Close all script inputs. */
1205     close_all_scripts();
1206 
1207 #if defined(FEAT_WINDOWS)
1208     /* Destroy all windows.  Must come before freeing buffers. */
1209     win_free_all();
1210 #endif
1211 
1212     /* Free all buffers.  Reset 'autochdir' to avoid accessing things that
1213      * were freed already. */
1214 #ifdef FEAT_AUTOCHDIR
1215     p_acd = FALSE;
1216 #endif
1217     for (buf = firstbuf; buf != NULL; )
1218     {
1219 	nextbuf = buf->b_next;
1220 	close_buffer(NULL, buf, DOBUF_WIPE, FALSE);
1221 	if (buf_valid(buf))
1222 	    buf = nextbuf;	/* didn't work, try next one */
1223 	else
1224 	    buf = firstbuf;
1225     }
1226 
1227 #ifdef FEAT_ARABIC
1228     free_cmdline_buf();
1229 #endif
1230 
1231     /* Clear registers. */
1232     clear_registers();
1233     ResetRedobuff();
1234     ResetRedobuff();
1235 
1236 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
1237     vim_free(serverDelayedStartName);
1238 #endif
1239 
1240     /* highlight info */
1241     free_highlight();
1242 
1243     reset_last_sourcing();
1244 
1245 #ifdef FEAT_WINDOWS
1246     free_tabpage(first_tabpage);
1247     first_tabpage = NULL;
1248 #endif
1249 
1250 # ifdef UNIX
1251     /* Machine-specific free. */
1252     mch_free_mem();
1253 # endif
1254 
1255     /* message history */
1256     for (;;)
1257 	if (delete_first_msg() == FAIL)
1258 	    break;
1259 
1260 # ifdef FEAT_EVAL
1261     eval_clear();
1262 # endif
1263 
1264     free_termoptions();
1265 
1266     /* screenlines (can't display anything now!) */
1267     free_screenlines();
1268 
1269 #if defined(USE_XSMP)
1270     xsmp_close();
1271 #endif
1272 #ifdef FEAT_GUI_GTK
1273     gui_mch_free_all();
1274 #endif
1275     clear_hl_tables();
1276 
1277     vim_free(IObuff);
1278     vim_free(NameBuff);
1279 }
1280 #endif
1281 
1282 /*
1283  * Copy "string" into newly allocated memory.
1284  */
1285     char_u *
1286 vim_strsave(string)
1287     char_u	*string;
1288 {
1289     char_u	*p;
1290     unsigned	len;
1291 
1292     len = (unsigned)STRLEN(string) + 1;
1293     p = alloc(len);
1294     if (p != NULL)
1295 	mch_memmove(p, string, (size_t)len);
1296     return p;
1297 }
1298 
1299 /*
1300  * Copy up to "len" bytes of "string" into newly allocated memory and
1301  * terminate with a NUL.
1302  * The allocated memory always has size "len + 1", also when "string" is
1303  * shorter.
1304  */
1305     char_u *
1306 vim_strnsave(string, len)
1307     char_u	*string;
1308     int		len;
1309 {
1310     char_u	*p;
1311 
1312     p = alloc((unsigned)(len + 1));
1313     if (p != NULL)
1314     {
1315 	STRNCPY(p, string, len);
1316 	p[len] = NUL;
1317     }
1318     return p;
1319 }
1320 
1321 /*
1322  * Same as vim_strsave(), but any characters found in esc_chars are preceded
1323  * by a backslash.
1324  */
1325     char_u *
1326 vim_strsave_escaped(string, esc_chars)
1327     char_u	*string;
1328     char_u	*esc_chars;
1329 {
1330     return vim_strsave_escaped_ext(string, esc_chars, '\\', FALSE);
1331 }
1332 
1333 /*
1334  * Same as vim_strsave_escaped(), but when "bsl" is TRUE also escape
1335  * characters where rem_backslash() would remove the backslash.
1336  * Escape the characters with "cc".
1337  */
1338     char_u *
1339 vim_strsave_escaped_ext(string, esc_chars, cc, bsl)
1340     char_u	*string;
1341     char_u	*esc_chars;
1342     int		cc;
1343     int		bsl;
1344 {
1345     char_u	*p;
1346     char_u	*p2;
1347     char_u	*escaped_string;
1348     unsigned	length;
1349 #ifdef FEAT_MBYTE
1350     int		l;
1351 #endif
1352 
1353     /*
1354      * First count the number of backslashes required.
1355      * Then allocate the memory and insert them.
1356      */
1357     length = 1;				/* count the trailing NUL */
1358     for (p = string; *p; p++)
1359     {
1360 #ifdef FEAT_MBYTE
1361 	if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1362 	{
1363 	    length += l;		/* count a multibyte char */
1364 	    p += l - 1;
1365 	    continue;
1366 	}
1367 #endif
1368 	if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
1369 	    ++length;			/* count a backslash */
1370 	++length;			/* count an ordinary char */
1371     }
1372     escaped_string = alloc(length);
1373     if (escaped_string != NULL)
1374     {
1375 	p2 = escaped_string;
1376 	for (p = string; *p; p++)
1377 	{
1378 #ifdef FEAT_MBYTE
1379 	    if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1380 	    {
1381 		mch_memmove(p2, p, (size_t)l);
1382 		p2 += l;
1383 		p += l - 1;		/* skip multibyte char  */
1384 		continue;
1385 	    }
1386 #endif
1387 	    if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p)))
1388 		*p2++ = cc;
1389 	    *p2++ = *p;
1390 	}
1391 	*p2 = NUL;
1392     }
1393     return escaped_string;
1394 }
1395 
1396 /*
1397  * Return TRUE when 'shell' has "csh" in the tail.
1398  */
1399     int
1400 csh_like_shell()
1401 {
1402     return (strstr((char *)gettail(p_sh), "csh") != NULL);
1403 }
1404 
1405 /*
1406  * Escape "string" for use as a shell argument with system().
1407  * This uses single quotes, except when we know we need to use double quotes
1408  * (MS-DOS and MS-Windows without 'shellslash' set).
1409  * Escape a newline, depending on the 'shell' option.
1410  * When "do_special" is TRUE also replace "!", "%", "#" and things starting
1411  * with "<" like "<cfile>".
1412  * When "do_newline" is FALSE do not escape newline unless it is csh shell.
1413  * Returns the result in allocated memory, NULL if we have run out.
1414  */
1415     char_u *
1416 vim_strsave_shellescape(string, do_special, do_newline)
1417     char_u	*string;
1418     int		do_special;
1419     int		do_newline;
1420 {
1421     unsigned	length;
1422     char_u	*p;
1423     char_u	*d;
1424     char_u	*escaped_string;
1425     int		l;
1426     int		csh_like;
1427 
1428     /* Only csh and similar shells expand '!' within single quotes.  For sh and
1429      * the like we must not put a backslash before it, it will be taken
1430      * literally.  If do_special is set the '!' will be escaped twice.
1431      * Csh also needs to have "\n" escaped twice when do_special is set. */
1432     csh_like = csh_like_shell();
1433 
1434     /* First count the number of extra bytes required. */
1435     length = (unsigned)STRLEN(string) + 3;  /* two quotes and a trailing NUL */
1436     for (p = string; *p != NUL; mb_ptr_adv(p))
1437     {
1438 # if defined(WIN32) || defined(WIN16) || defined(DOS)
1439 	if (!p_ssl)
1440 	{
1441 	    if (*p == '"')
1442 		++length;		/* " -> "" */
1443 	}
1444 	else
1445 # endif
1446 	if (*p == '\'')
1447 	    length += 3;		/* ' => '\'' */
1448 	if ((*p == '\n' && (csh_like || do_newline))
1449 		|| (*p == '!' && (csh_like || do_special)))
1450 	{
1451 	    ++length;			/* insert backslash */
1452 	    if (csh_like && do_special)
1453 		++length;		/* insert backslash */
1454 	}
1455 	if (do_special && find_cmdline_var(p, &l) >= 0)
1456 	{
1457 	    ++length;			/* insert backslash */
1458 	    p += l - 1;
1459 	}
1460     }
1461 
1462     /* Allocate memory for the result and fill it. */
1463     escaped_string = alloc(length);
1464     if (escaped_string != NULL)
1465     {
1466 	d = escaped_string;
1467 
1468 	/* add opening quote */
1469 # if defined(WIN32) || defined(WIN16) || defined(DOS)
1470 	if (!p_ssl)
1471 	    *d++ = '"';
1472 	else
1473 # endif
1474 	    *d++ = '\'';
1475 
1476 	for (p = string; *p != NUL; )
1477 	{
1478 # if defined(WIN32) || defined(WIN16) || defined(DOS)
1479 	    if (!p_ssl)
1480 	    {
1481 		if (*p == '"')
1482 		{
1483 		    *d++ = '"';
1484 		    *d++ = '"';
1485 		    ++p;
1486 		    continue;
1487 		}
1488 	    }
1489 	    else
1490 # endif
1491 	    if (*p == '\'')
1492 	    {
1493 		*d++ = '\'';
1494 		*d++ = '\\';
1495 		*d++ = '\'';
1496 		*d++ = '\'';
1497 		++p;
1498 		continue;
1499 	    }
1500 	    if ((*p == '\n' && (csh_like || do_newline))
1501 		    || (*p == '!' && (csh_like || do_special)))
1502 	    {
1503 		*d++ = '\\';
1504 		if (csh_like && do_special)
1505 		    *d++ = '\\';
1506 		*d++ = *p++;
1507 		continue;
1508 	    }
1509 	    if (do_special && find_cmdline_var(p, &l) >= 0)
1510 	    {
1511 		*d++ = '\\';		/* insert backslash */
1512 		while (--l >= 0)	/* copy the var */
1513 		    *d++ = *p++;
1514 		continue;
1515 	    }
1516 
1517 	    MB_COPY_CHAR(p, d);
1518 	}
1519 
1520 	/* add terminating quote and finish with a NUL */
1521 # if defined(WIN32) || defined(WIN16) || defined(DOS)
1522 	if (!p_ssl)
1523 	    *d++ = '"';
1524 	else
1525 # endif
1526 	    *d++ = '\'';
1527 	*d = NUL;
1528     }
1529 
1530     return escaped_string;
1531 }
1532 
1533 /*
1534  * Like vim_strsave(), but make all characters uppercase.
1535  * This uses ASCII lower-to-upper case translation, language independent.
1536  */
1537     char_u *
1538 vim_strsave_up(string)
1539     char_u	*string;
1540 {
1541     char_u *p1;
1542 
1543     p1 = vim_strsave(string);
1544     vim_strup(p1);
1545     return p1;
1546 }
1547 
1548 /*
1549  * Like vim_strnsave(), but make all characters uppercase.
1550  * This uses ASCII lower-to-upper case translation, language independent.
1551  */
1552     char_u *
1553 vim_strnsave_up(string, len)
1554     char_u	*string;
1555     int		len;
1556 {
1557     char_u *p1;
1558 
1559     p1 = vim_strnsave(string, len);
1560     vim_strup(p1);
1561     return p1;
1562 }
1563 
1564 /*
1565  * ASCII lower-to-upper case translation, language independent.
1566  */
1567     void
1568 vim_strup(p)
1569     char_u	*p;
1570 {
1571     char_u  *p2;
1572     int	    c;
1573 
1574     if (p != NULL)
1575     {
1576 	p2 = p;
1577 	while ((c = *p2) != NUL)
1578 #ifdef EBCDIC
1579 	    *p2++ = isalpha(c) ? toupper(c) : c;
1580 #else
1581 	    *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20);
1582 #endif
1583     }
1584 }
1585 
1586 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO)
1587 /*
1588  * Make string "s" all upper-case and return it in allocated memory.
1589  * Handles multi-byte characters as well as possible.
1590  * Returns NULL when out of memory.
1591  */
1592     char_u *
1593 strup_save(orig)
1594     char_u	*orig;
1595 {
1596     char_u	*p;
1597     char_u	*res;
1598 
1599     res = p = vim_strsave(orig);
1600 
1601     if (res != NULL)
1602 	while (*p != NUL)
1603 	{
1604 # ifdef FEAT_MBYTE
1605 	    int		l;
1606 
1607 	    if (enc_utf8)
1608 	    {
1609 		int	c, uc;
1610 		int	newl;
1611 		char_u	*s;
1612 
1613 		c = utf_ptr2char(p);
1614 		uc = utf_toupper(c);
1615 
1616 		/* Reallocate string when byte count changes.  This is rare,
1617 		 * thus it's OK to do another malloc()/free(). */
1618 		l = utf_ptr2len(p);
1619 		newl = utf_char2len(uc);
1620 		if (newl != l)
1621 		{
1622 		    s = alloc((unsigned)STRLEN(res) + 1 + newl - l);
1623 		    if (s == NULL)
1624 			break;
1625 		    mch_memmove(s, res, p - res);
1626 		    STRCPY(s + (p - res) + newl, p + l);
1627 		    p = s + (p - res);
1628 		    vim_free(res);
1629 		    res = s;
1630 		}
1631 
1632 		utf_char2bytes(uc, p);
1633 		p += newl;
1634 	    }
1635 	    else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
1636 		p += l;		/* skip multi-byte character */
1637 	    else
1638 # endif
1639 	    {
1640 		*p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
1641 		p++;
1642 	    }
1643 	}
1644 
1645     return res;
1646 }
1647 #endif
1648 
1649 /*
1650  * delete spaces at the end of a string
1651  */
1652     void
1653 del_trailing_spaces(ptr)
1654     char_u	*ptr;
1655 {
1656     char_u	*q;
1657 
1658     q = ptr + STRLEN(ptr);
1659     while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V)
1660 	*q = NUL;
1661 }
1662 
1663 /*
1664  * Like strncpy(), but always terminate the result with one NUL.
1665  * "to" must be "len + 1" long!
1666  */
1667     void
1668 vim_strncpy(to, from, len)
1669     char_u	*to;
1670     char_u	*from;
1671     size_t	len;
1672 {
1673     STRNCPY(to, from, len);
1674     to[len] = NUL;
1675 }
1676 
1677 /*
1678  * Like strcat(), but make sure the result fits in "tosize" bytes and is
1679  * always NUL terminated.
1680  */
1681     void
1682 vim_strcat(to, from, tosize)
1683     char_u	*to;
1684     char_u	*from;
1685     size_t	tosize;
1686 {
1687     size_t tolen = STRLEN(to);
1688     size_t fromlen = STRLEN(from);
1689 
1690     if (tolen + fromlen + 1 > tosize)
1691     {
1692 	mch_memmove(to + tolen, from, tosize - tolen - 1);
1693 	to[tosize - 1] = NUL;
1694     }
1695     else
1696 	STRCPY(to + tolen, from);
1697 }
1698 
1699 /*
1700  * Isolate one part of a string option where parts are separated with
1701  * "sep_chars".
1702  * The part is copied into "buf[maxlen]".
1703  * "*option" is advanced to the next part.
1704  * The length is returned.
1705  */
1706     int
1707 copy_option_part(option, buf, maxlen, sep_chars)
1708     char_u	**option;
1709     char_u	*buf;
1710     int		maxlen;
1711     char	*sep_chars;
1712 {
1713     int	    len = 0;
1714     char_u  *p = *option;
1715 
1716     /* skip '.' at start of option part, for 'suffixes' */
1717     if (*p == '.')
1718 	buf[len++] = *p++;
1719     while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL)
1720     {
1721 	/*
1722 	 * Skip backslash before a separator character and space.
1723 	 */
1724 	if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
1725 	    ++p;
1726 	if (len < maxlen - 1)
1727 	    buf[len++] = *p;
1728 	++p;
1729     }
1730     buf[len] = NUL;
1731 
1732     if (*p != NUL && *p != ',')	/* skip non-standard separator */
1733 	++p;
1734     p = skip_to_option_part(p);	/* p points to next file name */
1735 
1736     *option = p;
1737     return len;
1738 }
1739 
1740 /*
1741  * Replacement for free() that ignores NULL pointers.
1742  * Also skip free() when exiting for sure, this helps when we caught a deadly
1743  * signal that was caused by a crash in free().
1744  */
1745     void
1746 vim_free(x)
1747     void *x;
1748 {
1749     if (x != NULL && !really_exiting)
1750     {
1751 #ifdef MEM_PROFILE
1752 	mem_pre_free(&x);
1753 #endif
1754 	free(x);
1755     }
1756 }
1757 
1758 #ifndef HAVE_MEMSET
1759     void *
1760 vim_memset(ptr, c, size)
1761     void    *ptr;
1762     int	    c;
1763     size_t  size;
1764 {
1765     char *p = ptr;
1766 
1767     while (size-- > 0)
1768 	*p++ = c;
1769     return ptr;
1770 }
1771 #endif
1772 
1773 #ifdef VIM_MEMCMP
1774 /*
1775  * Return zero when "b1" and "b2" are the same for "len" bytes.
1776  * Return non-zero otherwise.
1777  */
1778     int
1779 vim_memcmp(b1, b2, len)
1780     void    *b1;
1781     void    *b2;
1782     size_t  len;
1783 {
1784     char_u  *p1 = (char_u *)b1, *p2 = (char_u *)b2;
1785 
1786     for ( ; len > 0; --len)
1787     {
1788 	if (*p1 != *p2)
1789 	    return 1;
1790 	++p1;
1791 	++p2;
1792     }
1793     return 0;
1794 }
1795 #endif
1796 
1797 #ifdef VIM_MEMMOVE
1798 /*
1799  * Version of memmove() that handles overlapping source and destination.
1800  * For systems that don't have a function that is guaranteed to do that (SYSV).
1801  */
1802     void
1803 mch_memmove(dst_arg, src_arg, len)
1804     void    *src_arg, *dst_arg;
1805     size_t  len;
1806 {
1807     /*
1808      * A void doesn't have a size, we use char pointers.
1809      */
1810     char *dst = dst_arg, *src = src_arg;
1811 
1812 					/* overlap, copy backwards */
1813     if (dst > src && dst < src + len)
1814     {
1815 	src += len;
1816 	dst += len;
1817 	while (len-- > 0)
1818 	    *--dst = *--src;
1819     }
1820     else				/* copy forwards */
1821 	while (len-- > 0)
1822 	    *dst++ = *src++;
1823 }
1824 #endif
1825 
1826 #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
1827 /*
1828  * Compare two strings, ignoring case, using current locale.
1829  * Doesn't work for multi-byte characters.
1830  * return 0 for match, < 0 for smaller, > 0 for bigger
1831  */
1832     int
1833 vim_stricmp(s1, s2)
1834     char	*s1;
1835     char	*s2;
1836 {
1837     int		i;
1838 
1839     for (;;)
1840     {
1841 	i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
1842 	if (i != 0)
1843 	    return i;			    /* this character different */
1844 	if (*s1 == NUL)
1845 	    break;			    /* strings match until NUL */
1846 	++s1;
1847 	++s2;
1848     }
1849     return 0;				    /* strings match */
1850 }
1851 #endif
1852 
1853 #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
1854 /*
1855  * Compare two strings, for length "len", ignoring case, using current locale.
1856  * Doesn't work for multi-byte characters.
1857  * return 0 for match, < 0 for smaller, > 0 for bigger
1858  */
1859     int
1860 vim_strnicmp(s1, s2, len)
1861     char	*s1;
1862     char	*s2;
1863     size_t	len;
1864 {
1865     int		i;
1866 
1867     while (len > 0)
1868     {
1869 	i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
1870 	if (i != 0)
1871 	    return i;			    /* this character different */
1872 	if (*s1 == NUL)
1873 	    break;			    /* strings match until NUL */
1874 	++s1;
1875 	++s2;
1876 	--len;
1877     }
1878     return 0;				    /* strings match */
1879 }
1880 #endif
1881 
1882 /*
1883  * Version of strchr() and strrchr() that handle unsigned char strings
1884  * with characters from 128 to 255 correctly.  It also doesn't return a
1885  * pointer to the NUL at the end of the string.
1886  */
1887     char_u  *
1888 vim_strchr(string, c)
1889     char_u	*string;
1890     int		c;
1891 {
1892     char_u	*p;
1893     int		b;
1894 
1895     p = string;
1896 #ifdef FEAT_MBYTE
1897     if (enc_utf8 && c >= 0x80)
1898     {
1899 	while (*p != NUL)
1900 	{
1901 	    int l = (*mb_ptr2len)(p);
1902 
1903 	    /* Avoid matching an illegal byte here. */
1904 	    if (utf_ptr2char(p) == c && l > 1)
1905 		return p;
1906 	    p += l;
1907 	}
1908 	return NULL;
1909     }
1910     if (enc_dbcs != 0 && c > 255)
1911     {
1912 	int	n2 = c & 0xff;
1913 
1914 	c = ((unsigned)c >> 8) & 0xff;
1915 	while ((b = *p) != NUL)
1916 	{
1917 	    if (b == c && p[1] == n2)
1918 		return p;
1919 	    p += (*mb_ptr2len)(p);
1920 	}
1921 	return NULL;
1922     }
1923     if (has_mbyte)
1924     {
1925 	while ((b = *p) != NUL)
1926 	{
1927 	    if (b == c)
1928 		return p;
1929 	    p += (*mb_ptr2len)(p);
1930 	}
1931 	return NULL;
1932     }
1933 #endif
1934     while ((b = *p) != NUL)
1935     {
1936 	if (b == c)
1937 	    return p;
1938 	++p;
1939     }
1940     return NULL;
1941 }
1942 
1943 /*
1944  * Version of strchr() that only works for bytes and handles unsigned char
1945  * strings with characters above 128 correctly. It also doesn't return a
1946  * pointer to the NUL at the end of the string.
1947  */
1948     char_u  *
1949 vim_strbyte(string, c)
1950     char_u	*string;
1951     int		c;
1952 {
1953     char_u	*p = string;
1954 
1955     while (*p != NUL)
1956     {
1957 	if (*p == c)
1958 	    return p;
1959 	++p;
1960     }
1961     return NULL;
1962 }
1963 
1964 /*
1965  * Search for last occurrence of "c" in "string".
1966  * Return NULL if not found.
1967  * Does not handle multi-byte char for "c"!
1968  */
1969     char_u  *
1970 vim_strrchr(string, c)
1971     char_u	*string;
1972     int		c;
1973 {
1974     char_u	*retval = NULL;
1975     char_u	*p = string;
1976 
1977     while (*p)
1978     {
1979 	if (*p == c)
1980 	    retval = p;
1981 	mb_ptr_adv(p);
1982     }
1983     return retval;
1984 }
1985 
1986 /*
1987  * Vim's version of strpbrk(), in case it's missing.
1988  * Don't generate a prototype for this, causes problems when it's not used.
1989  */
1990 #ifndef PROTO
1991 # ifndef HAVE_STRPBRK
1992 #  ifdef vim_strpbrk
1993 #   undef vim_strpbrk
1994 #  endif
1995     char_u *
1996 vim_strpbrk(s, charset)
1997     char_u	*s;
1998     char_u	*charset;
1999 {
2000     while (*s)
2001     {
2002 	if (vim_strchr(charset, *s) != NULL)
2003 	    return s;
2004 	mb_ptr_adv(s);
2005     }
2006     return NULL;
2007 }
2008 # endif
2009 #endif
2010 
2011 /*
2012  * Vim has its own isspace() function, because on some machines isspace()
2013  * can't handle characters above 128.
2014  */
2015     int
2016 vim_isspace(x)
2017     int	    x;
2018 {
2019     return ((x >= 9 && x <= 13) || x == ' ');
2020 }
2021 
2022 /************************************************************************
2023  * Functions for handling growing arrays.
2024  */
2025 
2026 /*
2027  * Clear an allocated growing array.
2028  */
2029     void
2030 ga_clear(gap)
2031     garray_T *gap;
2032 {
2033     vim_free(gap->ga_data);
2034     ga_init(gap);
2035 }
2036 
2037 /*
2038  * Clear a growing array that contains a list of strings.
2039  */
2040     void
2041 ga_clear_strings(gap)
2042     garray_T *gap;
2043 {
2044     int		i;
2045 
2046     for (i = 0; i < gap->ga_len; ++i)
2047 	vim_free(((char_u **)(gap->ga_data))[i]);
2048     ga_clear(gap);
2049 }
2050 
2051 /*
2052  * Initialize a growing array.	Don't forget to set ga_itemsize and
2053  * ga_growsize!  Or use ga_init2().
2054  */
2055     void
2056 ga_init(gap)
2057     garray_T *gap;
2058 {
2059     gap->ga_data = NULL;
2060     gap->ga_maxlen = 0;
2061     gap->ga_len = 0;
2062 }
2063 
2064     void
2065 ga_init2(gap, itemsize, growsize)
2066     garray_T	*gap;
2067     int		itemsize;
2068     int		growsize;
2069 {
2070     ga_init(gap);
2071     gap->ga_itemsize = itemsize;
2072     gap->ga_growsize = growsize;
2073 }
2074 
2075 /*
2076  * Make room in growing array "gap" for at least "n" items.
2077  * Return FAIL for failure, OK otherwise.
2078  */
2079     int
2080 ga_grow(gap, n)
2081     garray_T	*gap;
2082     int		n;
2083 {
2084     size_t	old_len;
2085     size_t	new_len;
2086     char_u	*pp;
2087 
2088     if (gap->ga_maxlen - gap->ga_len < n)
2089     {
2090 	if (n < gap->ga_growsize)
2091 	    n = gap->ga_growsize;
2092 	new_len = gap->ga_itemsize * (gap->ga_len + n);
2093 	pp = (gap->ga_data == NULL)
2094 	      ? alloc((unsigned)new_len) : vim_realloc(gap->ga_data, new_len);
2095 	if (pp == NULL)
2096 	    return FAIL;
2097 	old_len = gap->ga_itemsize * gap->ga_maxlen;
2098 	vim_memset(pp + old_len, 0, new_len - old_len);
2099 	gap->ga_maxlen = gap->ga_len + n;
2100 	gap->ga_data = pp;
2101     }
2102     return OK;
2103 }
2104 
2105 /*
2106  * For a growing array that contains a list of strings: concatenate all the
2107  * strings with a separating "sep".
2108  * Returns NULL when out of memory.
2109  */
2110     char_u *
2111 ga_concat_strings(gap, sep)
2112     garray_T *gap;
2113     char     *sep;
2114 {
2115     int		i;
2116     int		len = 0;
2117     int		sep_len = (int)STRLEN(sep);
2118     char_u	*s;
2119     char_u	*p;
2120 
2121     for (i = 0; i < gap->ga_len; ++i)
2122 	len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len;
2123 
2124     s = alloc(len + 1);
2125     if (s != NULL)
2126     {
2127 	*s = NUL;
2128 	p = s;
2129 	for (i = 0; i < gap->ga_len; ++i)
2130 	{
2131 	    if (p != s)
2132 	    {
2133 		STRCPY(p, sep);
2134 		p += sep_len;
2135 	    }
2136 	    STRCPY(p, ((char_u **)(gap->ga_data))[i]);
2137 	    p += STRLEN(p);
2138 	}
2139     }
2140     return s;
2141 }
2142 
2143 /*
2144  * Concatenate a string to a growarray which contains characters.
2145  * When "s" is NULL does not do anything.
2146  * Note: Does NOT copy the NUL at the end!
2147  */
2148     void
2149 ga_concat(gap, s)
2150     garray_T	*gap;
2151     char_u	*s;
2152 {
2153     int    len;
2154 
2155     if (s == NULL)
2156 	return;
2157     len = (int)STRLEN(s);
2158     if (ga_grow(gap, len) == OK)
2159     {
2160 	mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
2161 	gap->ga_len += len;
2162     }
2163 }
2164 
2165 /*
2166  * Append one byte to a growarray which contains bytes.
2167  */
2168     void
2169 ga_append(gap, c)
2170     garray_T	*gap;
2171     int		c;
2172 {
2173     if (ga_grow(gap, 1) == OK)
2174     {
2175 	*((char *)gap->ga_data + gap->ga_len) = c;
2176 	++gap->ga_len;
2177     }
2178 }
2179 
2180 #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) \
2181 	|| defined(PROTO)
2182 /*
2183  * Append the text in "gap" below the cursor line and clear "gap".
2184  */
2185     void
2186 append_ga_line(gap)
2187     garray_T	*gap;
2188 {
2189     /* Remove trailing CR. */
2190     if (gap->ga_len > 0
2191 	    && !curbuf->b_p_bin
2192 	    && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
2193 	--gap->ga_len;
2194     ga_append(gap, NUL);
2195     ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
2196     gap->ga_len = 0;
2197 }
2198 #endif
2199 
2200 /************************************************************************
2201  * functions that use lookup tables for various things, generally to do with
2202  * special key codes.
2203  */
2204 
2205 /*
2206  * Some useful tables.
2207  */
2208 
2209 static struct modmasktable
2210 {
2211     short	mod_mask;	/* Bit-mask for particular key modifier */
2212     short	mod_flag;	/* Bit(s) for particular key modifier */
2213     char_u	name;		/* Single letter name of modifier */
2214 } mod_mask_table[] =
2215 {
2216     {MOD_MASK_ALT,		MOD_MASK_ALT,		(char_u)'M'},
2217     {MOD_MASK_META,		MOD_MASK_META,		(char_u)'T'},
2218     {MOD_MASK_CTRL,		MOD_MASK_CTRL,		(char_u)'C'},
2219     {MOD_MASK_SHIFT,		MOD_MASK_SHIFT,		(char_u)'S'},
2220     {MOD_MASK_MULTI_CLICK,	MOD_MASK_2CLICK,	(char_u)'2'},
2221     {MOD_MASK_MULTI_CLICK,	MOD_MASK_3CLICK,	(char_u)'3'},
2222     {MOD_MASK_MULTI_CLICK,	MOD_MASK_4CLICK,	(char_u)'4'},
2223 #ifdef MACOS
2224     {MOD_MASK_CMD,		MOD_MASK_CMD,		(char_u)'D'},
2225 #endif
2226     /* 'A' must be the last one */
2227     {MOD_MASK_ALT,		MOD_MASK_ALT,		(char_u)'A'},
2228     {0, 0, NUL}
2229 };
2230 
2231 /*
2232  * Shifted key terminal codes and their unshifted equivalent.
2233  * Don't add mouse codes here, they are handled separately!
2234  */
2235 #define MOD_KEYS_ENTRY_SIZE 5
2236 
2237 static char_u modifier_keys_table[] =
2238 {
2239 /*  mod mask	    with modifier		without modifier */
2240     MOD_MASK_SHIFT, '&', '9',			'@', '1',	/* begin */
2241     MOD_MASK_SHIFT, '&', '0',			'@', '2',	/* cancel */
2242     MOD_MASK_SHIFT, '*', '1',			'@', '4',	/* command */
2243     MOD_MASK_SHIFT, '*', '2',			'@', '5',	/* copy */
2244     MOD_MASK_SHIFT, '*', '3',			'@', '6',	/* create */
2245     MOD_MASK_SHIFT, '*', '4',			'k', 'D',	/* delete char */
2246     MOD_MASK_SHIFT, '*', '5',			'k', 'L',	/* delete line */
2247     MOD_MASK_SHIFT, '*', '7',			'@', '7',	/* end */
2248     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_END,	'@', '7',	/* end */
2249     MOD_MASK_SHIFT, '*', '9',			'@', '9',	/* exit */
2250     MOD_MASK_SHIFT, '*', '0',			'@', '0',	/* find */
2251     MOD_MASK_SHIFT, '#', '1',			'%', '1',	/* help */
2252     MOD_MASK_SHIFT, '#', '2',			'k', 'h',	/* home */
2253     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_HOME,	'k', 'h',	/* home */
2254     MOD_MASK_SHIFT, '#', '3',			'k', 'I',	/* insert */
2255     MOD_MASK_SHIFT, '#', '4',			'k', 'l',	/* left arrow */
2256     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_LEFT,	'k', 'l',	/* left arrow */
2257     MOD_MASK_SHIFT, '%', 'a',			'%', '3',	/* message */
2258     MOD_MASK_SHIFT, '%', 'b',			'%', '4',	/* move */
2259     MOD_MASK_SHIFT, '%', 'c',			'%', '5',	/* next */
2260     MOD_MASK_SHIFT, '%', 'd',			'%', '7',	/* options */
2261     MOD_MASK_SHIFT, '%', 'e',			'%', '8',	/* previous */
2262     MOD_MASK_SHIFT, '%', 'f',			'%', '9',	/* print */
2263     MOD_MASK_SHIFT, '%', 'g',			'%', '0',	/* redo */
2264     MOD_MASK_SHIFT, '%', 'h',			'&', '3',	/* replace */
2265     MOD_MASK_SHIFT, '%', 'i',			'k', 'r',	/* right arr. */
2266     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_RIGHT,	'k', 'r',	/* right arr. */
2267     MOD_MASK_SHIFT, '%', 'j',			'&', '5',	/* resume */
2268     MOD_MASK_SHIFT, '!', '1',			'&', '6',	/* save */
2269     MOD_MASK_SHIFT, '!', '2',			'&', '7',	/* suspend */
2270     MOD_MASK_SHIFT, '!', '3',			'&', '8',	/* undo */
2271     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP,	'k', 'u',	/* up arrow */
2272     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN,	'k', 'd',	/* down arrow */
2273 
2274 								/* vt100 F1 */
2275     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1,	KS_EXTRA, (int)KE_XF1,
2276     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2,	KS_EXTRA, (int)KE_XF2,
2277     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3,	KS_EXTRA, (int)KE_XF3,
2278     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4,	KS_EXTRA, (int)KE_XF4,
2279 
2280     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1,	'k', '1',	/* F1 */
2281     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2,	'k', '2',
2282     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3,	'k', '3',
2283     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4,	'k', '4',
2284     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5,	'k', '5',
2285     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6,	'k', '6',
2286     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7,	'k', '7',
2287     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8,	'k', '8',
2288     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9,	'k', '9',
2289     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10,	'k', ';',	/* F10 */
2290 
2291     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11,	'F', '1',
2292     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12,	'F', '2',
2293     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13,	'F', '3',
2294     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14,	'F', '4',
2295     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15,	'F', '5',
2296     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16,	'F', '6',
2297     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17,	'F', '7',
2298     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18,	'F', '8',
2299     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19,	'F', '9',
2300     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20,	'F', 'A',
2301 
2302     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21,	'F', 'B',
2303     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22,	'F', 'C',
2304     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23,	'F', 'D',
2305     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24,	'F', 'E',
2306     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25,	'F', 'F',
2307     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26,	'F', 'G',
2308     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27,	'F', 'H',
2309     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28,	'F', 'I',
2310     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29,	'F', 'J',
2311     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30,	'F', 'K',
2312 
2313     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31,	'F', 'L',
2314     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32,	'F', 'M',
2315     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33,	'F', 'N',
2316     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34,	'F', 'O',
2317     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35,	'F', 'P',
2318     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36,	'F', 'Q',
2319     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37,	'F', 'R',
2320 
2321 							    /* TAB pseudo code*/
2322     MOD_MASK_SHIFT, 'k', 'B',			KS_EXTRA, (int)KE_TAB,
2323 
2324     NUL
2325 };
2326 
2327 static struct key_name_entry
2328 {
2329     int	    key;	/* Special key code or ascii value */
2330     char_u  *name;	/* Name of key */
2331 } key_names_table[] =
2332 {
2333     {' ',		(char_u *)"Space"},
2334     {TAB,		(char_u *)"Tab"},
2335     {K_TAB,		(char_u *)"Tab"},
2336     {NL,		(char_u *)"NL"},
2337     {NL,		(char_u *)"NewLine"},	/* Alternative name */
2338     {NL,		(char_u *)"LineFeed"},	/* Alternative name */
2339     {NL,		(char_u *)"LF"},	/* Alternative name */
2340     {CAR,		(char_u *)"CR"},
2341     {CAR,		(char_u *)"Return"},	/* Alternative name */
2342     {CAR,		(char_u *)"Enter"},	/* Alternative name */
2343     {K_BS,		(char_u *)"BS"},
2344     {K_BS,		(char_u *)"BackSpace"},	/* Alternative name */
2345     {ESC,		(char_u *)"Esc"},
2346     {CSI,		(char_u *)"CSI"},
2347     {K_CSI,		(char_u *)"xCSI"},
2348     {'|',		(char_u *)"Bar"},
2349     {'\\',		(char_u *)"Bslash"},
2350     {K_DEL,		(char_u *)"Del"},
2351     {K_DEL,		(char_u *)"Delete"},	/* Alternative name */
2352     {K_KDEL,		(char_u *)"kDel"},
2353     {K_UP,		(char_u *)"Up"},
2354     {K_DOWN,		(char_u *)"Down"},
2355     {K_LEFT,		(char_u *)"Left"},
2356     {K_RIGHT,		(char_u *)"Right"},
2357     {K_XUP,		(char_u *)"xUp"},
2358     {K_XDOWN,		(char_u *)"xDown"},
2359     {K_XLEFT,		(char_u *)"xLeft"},
2360     {K_XRIGHT,		(char_u *)"xRight"},
2361 
2362     {K_F1,		(char_u *)"F1"},
2363     {K_F2,		(char_u *)"F2"},
2364     {K_F3,		(char_u *)"F3"},
2365     {K_F4,		(char_u *)"F4"},
2366     {K_F5,		(char_u *)"F5"},
2367     {K_F6,		(char_u *)"F6"},
2368     {K_F7,		(char_u *)"F7"},
2369     {K_F8,		(char_u *)"F8"},
2370     {K_F9,		(char_u *)"F9"},
2371     {K_F10,		(char_u *)"F10"},
2372 
2373     {K_F11,		(char_u *)"F11"},
2374     {K_F12,		(char_u *)"F12"},
2375     {K_F13,		(char_u *)"F13"},
2376     {K_F14,		(char_u *)"F14"},
2377     {K_F15,		(char_u *)"F15"},
2378     {K_F16,		(char_u *)"F16"},
2379     {K_F17,		(char_u *)"F17"},
2380     {K_F18,		(char_u *)"F18"},
2381     {K_F19,		(char_u *)"F19"},
2382     {K_F20,		(char_u *)"F20"},
2383 
2384     {K_F21,		(char_u *)"F21"},
2385     {K_F22,		(char_u *)"F22"},
2386     {K_F23,		(char_u *)"F23"},
2387     {K_F24,		(char_u *)"F24"},
2388     {K_F25,		(char_u *)"F25"},
2389     {K_F26,		(char_u *)"F26"},
2390     {K_F27,		(char_u *)"F27"},
2391     {K_F28,		(char_u *)"F28"},
2392     {K_F29,		(char_u *)"F29"},
2393     {K_F30,		(char_u *)"F30"},
2394 
2395     {K_F31,		(char_u *)"F31"},
2396     {K_F32,		(char_u *)"F32"},
2397     {K_F33,		(char_u *)"F33"},
2398     {K_F34,		(char_u *)"F34"},
2399     {K_F35,		(char_u *)"F35"},
2400     {K_F36,		(char_u *)"F36"},
2401     {K_F37,		(char_u *)"F37"},
2402 
2403     {K_XF1,		(char_u *)"xF1"},
2404     {K_XF2,		(char_u *)"xF2"},
2405     {K_XF3,		(char_u *)"xF3"},
2406     {K_XF4,		(char_u *)"xF4"},
2407 
2408     {K_HELP,		(char_u *)"Help"},
2409     {K_UNDO,		(char_u *)"Undo"},
2410     {K_INS,		(char_u *)"Insert"},
2411     {K_INS,		(char_u *)"Ins"},	/* Alternative name */
2412     {K_KINS,		(char_u *)"kInsert"},
2413     {K_HOME,		(char_u *)"Home"},
2414     {K_KHOME,		(char_u *)"kHome"},
2415     {K_XHOME,		(char_u *)"xHome"},
2416     {K_ZHOME,		(char_u *)"zHome"},
2417     {K_END,		(char_u *)"End"},
2418     {K_KEND,		(char_u *)"kEnd"},
2419     {K_XEND,		(char_u *)"xEnd"},
2420     {K_ZEND,		(char_u *)"zEnd"},
2421     {K_PAGEUP,		(char_u *)"PageUp"},
2422     {K_PAGEDOWN,	(char_u *)"PageDown"},
2423     {K_KPAGEUP,		(char_u *)"kPageUp"},
2424     {K_KPAGEDOWN,	(char_u *)"kPageDown"},
2425 
2426     {K_KPLUS,		(char_u *)"kPlus"},
2427     {K_KMINUS,		(char_u *)"kMinus"},
2428     {K_KDIVIDE,		(char_u *)"kDivide"},
2429     {K_KMULTIPLY,	(char_u *)"kMultiply"},
2430     {K_KENTER,		(char_u *)"kEnter"},
2431     {K_KPOINT,		(char_u *)"kPoint"},
2432 
2433     {K_K0,		(char_u *)"k0"},
2434     {K_K1,		(char_u *)"k1"},
2435     {K_K2,		(char_u *)"k2"},
2436     {K_K3,		(char_u *)"k3"},
2437     {K_K4,		(char_u *)"k4"},
2438     {K_K5,		(char_u *)"k5"},
2439     {K_K6,		(char_u *)"k6"},
2440     {K_K7,		(char_u *)"k7"},
2441     {K_K8,		(char_u *)"k8"},
2442     {K_K9,		(char_u *)"k9"},
2443 
2444     {'<',		(char_u *)"lt"},
2445 
2446     {K_MOUSE,		(char_u *)"Mouse"},
2447 #ifdef FEAT_MOUSE_NET
2448     {K_NETTERM_MOUSE,	(char_u *)"NetMouse"},
2449 #endif
2450 #ifdef FEAT_MOUSE_DEC
2451     {K_DEC_MOUSE,	(char_u *)"DecMouse"},
2452 #endif
2453 #ifdef FEAT_MOUSE_JSB
2454     {K_JSBTERM_MOUSE,	(char_u *)"JsbMouse"},
2455 #endif
2456 #ifdef FEAT_MOUSE_PTERM
2457     {K_PTERM_MOUSE,	(char_u *)"PtermMouse"},
2458 #endif
2459 #ifdef FEAT_MOUSE_URXVT
2460     {K_URXVT_MOUSE,	(char_u *)"UrxvtMouse"},
2461 #endif
2462 #ifdef FEAT_MOUSE_SGR
2463     {K_SGR_MOUSE,	(char_u *)"SgrMouse"},
2464 #endif
2465     {K_LEFTMOUSE,	(char_u *)"LeftMouse"},
2466     {K_LEFTMOUSE_NM,	(char_u *)"LeftMouseNM"},
2467     {K_LEFTDRAG,	(char_u *)"LeftDrag"},
2468     {K_LEFTRELEASE,	(char_u *)"LeftRelease"},
2469     {K_LEFTRELEASE_NM,	(char_u *)"LeftReleaseNM"},
2470     {K_MIDDLEMOUSE,	(char_u *)"MiddleMouse"},
2471     {K_MIDDLEDRAG,	(char_u *)"MiddleDrag"},
2472     {K_MIDDLERELEASE,	(char_u *)"MiddleRelease"},
2473     {K_RIGHTMOUSE,	(char_u *)"RightMouse"},
2474     {K_RIGHTDRAG,	(char_u *)"RightDrag"},
2475     {K_RIGHTRELEASE,	(char_u *)"RightRelease"},
2476     {K_MOUSEDOWN,	(char_u *)"ScrollWheelUp"},
2477     {K_MOUSEUP,		(char_u *)"ScrollWheelDown"},
2478     {K_MOUSELEFT,	(char_u *)"ScrollWheelRight"},
2479     {K_MOUSERIGHT,	(char_u *)"ScrollWheelLeft"},
2480     {K_MOUSEDOWN,	(char_u *)"MouseDown"}, /* OBSOLETE: Use	  */
2481     {K_MOUSEUP,		(char_u *)"MouseUp"},	/* ScrollWheelXXX instead */
2482     {K_X1MOUSE,		(char_u *)"X1Mouse"},
2483     {K_X1DRAG,		(char_u *)"X1Drag"},
2484     {K_X1RELEASE,		(char_u *)"X1Release"},
2485     {K_X2MOUSE,		(char_u *)"X2Mouse"},
2486     {K_X2DRAG,		(char_u *)"X2Drag"},
2487     {K_X2RELEASE,		(char_u *)"X2Release"},
2488     {K_DROP,		(char_u *)"Drop"},
2489     {K_ZERO,		(char_u *)"Nul"},
2490 #ifdef FEAT_EVAL
2491     {K_SNR,		(char_u *)"SNR"},
2492 #endif
2493     {K_PLUG,		(char_u *)"Plug"},
2494     {K_CURSORHOLD,	(char_u *)"CursorHold"},
2495     {0,			NULL}
2496 };
2497 
2498 #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
2499 
2500 #ifdef FEAT_MOUSE
2501 static struct mousetable
2502 {
2503     int	    pseudo_code;	/* Code for pseudo mouse event */
2504     int	    button;		/* Which mouse button is it? */
2505     int	    is_click;		/* Is it a mouse button click event? */
2506     int	    is_drag;		/* Is it a mouse drag event? */
2507 } mouse_table[] =
2508 {
2509     {(int)KE_LEFTMOUSE,		MOUSE_LEFT,	TRUE,	FALSE},
2510 #ifdef FEAT_GUI
2511     {(int)KE_LEFTMOUSE_NM,	MOUSE_LEFT,	TRUE,	FALSE},
2512 #endif
2513     {(int)KE_LEFTDRAG,		MOUSE_LEFT,	FALSE,	TRUE},
2514     {(int)KE_LEFTRELEASE,	MOUSE_LEFT,	FALSE,	FALSE},
2515 #ifdef FEAT_GUI
2516     {(int)KE_LEFTRELEASE_NM,	MOUSE_LEFT,	FALSE,	FALSE},
2517 #endif
2518     {(int)KE_MIDDLEMOUSE,	MOUSE_MIDDLE,	TRUE,	FALSE},
2519     {(int)KE_MIDDLEDRAG,	MOUSE_MIDDLE,	FALSE,	TRUE},
2520     {(int)KE_MIDDLERELEASE,	MOUSE_MIDDLE,	FALSE,	FALSE},
2521     {(int)KE_RIGHTMOUSE,	MOUSE_RIGHT,	TRUE,	FALSE},
2522     {(int)KE_RIGHTDRAG,		MOUSE_RIGHT,	FALSE,	TRUE},
2523     {(int)KE_RIGHTRELEASE,	MOUSE_RIGHT,	FALSE,	FALSE},
2524     {(int)KE_X1MOUSE,		MOUSE_X1,	TRUE,	FALSE},
2525     {(int)KE_X1DRAG,		MOUSE_X1,	FALSE,	TRUE},
2526     {(int)KE_X1RELEASE,		MOUSE_X1,	FALSE,	FALSE},
2527     {(int)KE_X2MOUSE,		MOUSE_X2,	TRUE,	FALSE},
2528     {(int)KE_X2DRAG,		MOUSE_X2,	FALSE,	TRUE},
2529     {(int)KE_X2RELEASE,		MOUSE_X2,	FALSE,	FALSE},
2530     /* DRAG without CLICK */
2531     {(int)KE_IGNORE,		MOUSE_RELEASE,	FALSE,	TRUE},
2532     /* RELEASE without CLICK */
2533     {(int)KE_IGNORE,		MOUSE_RELEASE,	FALSE,	FALSE},
2534     {0,				0,		0,	0},
2535 };
2536 #endif /* FEAT_MOUSE */
2537 
2538 /*
2539  * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
2540  * modifier name ('S' for Shift, 'C' for Ctrl etc).
2541  */
2542     int
2543 name_to_mod_mask(c)
2544     int	    c;
2545 {
2546     int	    i;
2547 
2548     c = TOUPPER_ASC(c);
2549     for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
2550 	if (c == mod_mask_table[i].name)
2551 	    return mod_mask_table[i].mod_flag;
2552     return 0;
2553 }
2554 
2555 /*
2556  * Check if if there is a special key code for "key" that includes the
2557  * modifiers specified.
2558  */
2559     int
2560 simplify_key(key, modifiers)
2561     int	    key;
2562     int	    *modifiers;
2563 {
2564     int	    i;
2565     int	    key0;
2566     int	    key1;
2567 
2568     if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
2569     {
2570 	/* TAB is a special case */
2571 	if (key == TAB && (*modifiers & MOD_MASK_SHIFT))
2572 	{
2573 	    *modifiers &= ~MOD_MASK_SHIFT;
2574 	    return K_S_TAB;
2575 	}
2576 	key0 = KEY2TERMCAP0(key);
2577 	key1 = KEY2TERMCAP1(key);
2578 	for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
2579 	    if (key0 == modifier_keys_table[i + 3]
2580 		    && key1 == modifier_keys_table[i + 4]
2581 		    && (*modifiers & modifier_keys_table[i]))
2582 	    {
2583 		*modifiers &= ~modifier_keys_table[i];
2584 		return TERMCAP2KEY(modifier_keys_table[i + 1],
2585 						   modifier_keys_table[i + 2]);
2586 	    }
2587     }
2588     return key;
2589 }
2590 
2591 /*
2592  * Change <xHome> to <Home>, <xUp> to <Up>, etc.
2593  */
2594     int
2595 handle_x_keys(key)
2596     int	    key;
2597 {
2598     switch (key)
2599     {
2600 	case K_XUP:	return K_UP;
2601 	case K_XDOWN:	return K_DOWN;
2602 	case K_XLEFT:	return K_LEFT;
2603 	case K_XRIGHT:	return K_RIGHT;
2604 	case K_XHOME:	return K_HOME;
2605 	case K_ZHOME:	return K_HOME;
2606 	case K_XEND:	return K_END;
2607 	case K_ZEND:	return K_END;
2608 	case K_XF1:	return K_F1;
2609 	case K_XF2:	return K_F2;
2610 	case K_XF3:	return K_F3;
2611 	case K_XF4:	return K_F4;
2612 	case K_S_XF1:	return K_S_F1;
2613 	case K_S_XF2:	return K_S_F2;
2614 	case K_S_XF3:	return K_S_F3;
2615 	case K_S_XF4:	return K_S_F4;
2616     }
2617     return key;
2618 }
2619 
2620 /*
2621  * Return a string which contains the name of the given key when the given
2622  * modifiers are down.
2623  */
2624     char_u *
2625 get_special_key_name(c, modifiers)
2626     int	    c;
2627     int	    modifiers;
2628 {
2629     static char_u string[MAX_KEY_NAME_LEN + 1];
2630 
2631     int	    i, idx;
2632     int	    table_idx;
2633     char_u  *s;
2634 
2635     string[0] = '<';
2636     idx = 1;
2637 
2638     /* Key that stands for a normal character. */
2639     if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
2640 	c = KEY2TERMCAP1(c);
2641 
2642     /*
2643      * Translate shifted special keys into unshifted keys and set modifier.
2644      * Same for CTRL and ALT modifiers.
2645      */
2646     if (IS_SPECIAL(c))
2647     {
2648 	for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
2649 	    if (       KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
2650 		    && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2])
2651 	    {
2652 		modifiers |= modifier_keys_table[i];
2653 		c = TERMCAP2KEY(modifier_keys_table[i + 3],
2654 						   modifier_keys_table[i + 4]);
2655 		break;
2656 	    }
2657     }
2658 
2659     /* try to find the key in the special key table */
2660     table_idx = find_special_key_in_table(c);
2661 
2662     /*
2663      * When not a known special key, and not a printable character, try to
2664      * extract modifiers.
2665      */
2666     if (c > 0
2667 #ifdef FEAT_MBYTE
2668 	    && (*mb_char2len)(c) == 1
2669 #endif
2670        )
2671     {
2672 	if (table_idx < 0
2673 		&& (!vim_isprintc(c) || (c & 0x7f) == ' ')
2674 		&& (c & 0x80))
2675 	{
2676 	    c &= 0x7f;
2677 	    modifiers |= MOD_MASK_ALT;
2678 	    /* try again, to find the un-alted key in the special key table */
2679 	    table_idx = find_special_key_in_table(c);
2680 	}
2681 	if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
2682 	{
2683 #ifdef EBCDIC
2684 	    c = CtrlChar(c);
2685 #else
2686 	    c += '@';
2687 #endif
2688 	    modifiers |= MOD_MASK_CTRL;
2689 	}
2690     }
2691 
2692     /* translate the modifier into a string */
2693     for (i = 0; mod_mask_table[i].name != 'A'; i++)
2694 	if ((modifiers & mod_mask_table[i].mod_mask)
2695 						== mod_mask_table[i].mod_flag)
2696 	{
2697 	    string[idx++] = mod_mask_table[i].name;
2698 	    string[idx++] = (char_u)'-';
2699 	}
2700 
2701     if (table_idx < 0)		/* unknown special key, may output t_xx */
2702     {
2703 	if (IS_SPECIAL(c))
2704 	{
2705 	    string[idx++] = 't';
2706 	    string[idx++] = '_';
2707 	    string[idx++] = KEY2TERMCAP0(c);
2708 	    string[idx++] = KEY2TERMCAP1(c);
2709 	}
2710 	/* Not a special key, only modifiers, output directly */
2711 	else
2712 	{
2713 #ifdef FEAT_MBYTE
2714 	    if (has_mbyte && (*mb_char2len)(c) > 1)
2715 		idx += (*mb_char2bytes)(c, string + idx);
2716 	    else
2717 #endif
2718 	    if (vim_isprintc(c))
2719 		string[idx++] = c;
2720 	    else
2721 	    {
2722 		s = transchar(c);
2723 		while (*s)
2724 		    string[idx++] = *s++;
2725 	    }
2726 	}
2727     }
2728     else		/* use name of special key */
2729     {
2730 	STRCPY(string + idx, key_names_table[table_idx].name);
2731 	idx = (int)STRLEN(string);
2732     }
2733     string[idx++] = '>';
2734     string[idx] = NUL;
2735     return string;
2736 }
2737 
2738 /*
2739  * Try translating a <> name at (*srcp)[] to dst[].
2740  * Return the number of characters added to dst[], zero for no match.
2741  * If there is a match, srcp is advanced to after the <> name.
2742  * dst[] must be big enough to hold the result (up to six characters)!
2743  */
2744     int
2745 trans_special(srcp, dst, keycode)
2746     char_u	**srcp;
2747     char_u	*dst;
2748     int		keycode; /* prefer key code, e.g. K_DEL instead of DEL */
2749 {
2750     int		modifiers = 0;
2751     int		key;
2752     int		dlen = 0;
2753 
2754     key = find_special_key(srcp, &modifiers, keycode, FALSE);
2755     if (key == 0)
2756 	return 0;
2757 
2758     /* Put the appropriate modifier in a string */
2759     if (modifiers != 0)
2760     {
2761 	dst[dlen++] = K_SPECIAL;
2762 	dst[dlen++] = KS_MODIFIER;
2763 	dst[dlen++] = modifiers;
2764     }
2765 
2766     if (IS_SPECIAL(key))
2767     {
2768 	dst[dlen++] = K_SPECIAL;
2769 	dst[dlen++] = KEY2TERMCAP0(key);
2770 	dst[dlen++] = KEY2TERMCAP1(key);
2771     }
2772 #ifdef FEAT_MBYTE
2773     else if (has_mbyte && !keycode)
2774 	dlen += (*mb_char2bytes)(key, dst + dlen);
2775 #endif
2776     else if (keycode)
2777 	dlen = (int)(add_char2buf(key, dst + dlen) - dst);
2778     else
2779 	dst[dlen++] = key;
2780 
2781     return dlen;
2782 }
2783 
2784 /*
2785  * Try translating a <> name at (*srcp)[], return the key and modifiers.
2786  * srcp is advanced to after the <> name.
2787  * returns 0 if there is no match.
2788  */
2789     int
2790 find_special_key(srcp, modp, keycode, keep_x_key)
2791     char_u	**srcp;
2792     int		*modp;
2793     int		keycode;     /* prefer key code, e.g. K_DEL instead of DEL */
2794     int		keep_x_key;  /* don't translate xHome to Home key */
2795 {
2796     char_u	*last_dash;
2797     char_u	*end_of_name;
2798     char_u	*src;
2799     char_u	*bp;
2800     int		modifiers;
2801     int		bit;
2802     int		key;
2803     unsigned long n;
2804     int		l;
2805 
2806     src = *srcp;
2807     if (src[0] != '<')
2808 	return 0;
2809 
2810     /* Find end of modifier list */
2811     last_dash = src;
2812     for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++)
2813     {
2814 	if (*bp == '-')
2815 	{
2816 	    last_dash = bp;
2817 	    if (bp[1] != NUL)
2818 	    {
2819 #ifdef FEAT_MBYTE
2820 		if (has_mbyte)
2821 		    l = mb_ptr2len(bp + 1);
2822 		else
2823 #endif
2824 		    l = 1;
2825 		if (bp[l + 1] == '>')
2826 		    bp += l;	/* anything accepted, like <C-?> */
2827 	    }
2828 	}
2829 	if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
2830 	    bp += 3;	/* skip t_xx, xx may be '-' or '>' */
2831 	else if (STRNICMP(bp, "char-", 5) == 0)
2832 	{
2833 	    vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0);
2834 	    bp += l + 5;
2835 	    break;
2836 	}
2837     }
2838 
2839     if (*bp == '>')	/* found matching '>' */
2840     {
2841 	end_of_name = bp + 1;
2842 
2843 	/* Which modifiers are given? */
2844 	modifiers = 0x0;
2845 	for (bp = src + 1; bp < last_dash; bp++)
2846 	{
2847 	    if (*bp != '-')
2848 	    {
2849 		bit = name_to_mod_mask(*bp);
2850 		if (bit == 0x0)
2851 		    break;	/* Illegal modifier name */
2852 		modifiers |= bit;
2853 	    }
2854 	}
2855 
2856 	/*
2857 	 * Legal modifier name.
2858 	 */
2859 	if (bp >= last_dash)
2860 	{
2861 	    if (STRNICMP(last_dash + 1, "char-", 5) == 0
2862 						 && VIM_ISDIGIT(last_dash[6]))
2863 	    {
2864 		/* <Char-123> or <Char-033> or <Char-0x33> */
2865 		vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0);
2866 		key = (int)n;
2867 	    }
2868 	    else
2869 	    {
2870 		/*
2871 		 * Modifier with single letter, or special key name.
2872 		 */
2873 #ifdef FEAT_MBYTE
2874 		if (has_mbyte)
2875 		    l = mb_ptr2len(last_dash + 1);
2876 		else
2877 #endif
2878 		    l = 1;
2879 		if (modifiers != 0 && last_dash[l + 1] == '>')
2880 		    key = PTR2CHAR(last_dash + 1);
2881 		else
2882 		{
2883 		    key = get_special_key_code(last_dash + 1);
2884 		    if (!keep_x_key)
2885 			key = handle_x_keys(key);
2886 		}
2887 	    }
2888 
2889 	    /*
2890 	     * get_special_key_code() may return NUL for invalid
2891 	     * special key name.
2892 	     */
2893 	    if (key != NUL)
2894 	    {
2895 		/*
2896 		 * Only use a modifier when there is no special key code that
2897 		 * includes the modifier.
2898 		 */
2899 		key = simplify_key(key, &modifiers);
2900 
2901 		if (!keycode)
2902 		{
2903 		    /* don't want keycode, use single byte code */
2904 		    if (key == K_BS)
2905 			key = BS;
2906 		    else if (key == K_DEL || key == K_KDEL)
2907 			key = DEL;
2908 		}
2909 
2910 		/*
2911 		 * Normal Key with modifier: Try to make a single byte code.
2912 		 */
2913 		if (!IS_SPECIAL(key))
2914 		    key = extract_modifiers(key, &modifiers);
2915 
2916 		*modp = modifiers;
2917 		*srcp = end_of_name;
2918 		return key;
2919 	    }
2920 	}
2921     }
2922     return 0;
2923 }
2924 
2925 /*
2926  * Try to include modifiers in the key.
2927  * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
2928  */
2929     int
2930 extract_modifiers(key, modp)
2931     int	    key;
2932     int	    *modp;
2933 {
2934     int	modifiers = *modp;
2935 
2936 #ifdef MACOS
2937     /* Command-key really special, no fancynest */
2938     if (!(modifiers & MOD_MASK_CMD))
2939 #endif
2940     if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
2941     {
2942 	key = TOUPPER_ASC(key);
2943 	modifiers &= ~MOD_MASK_SHIFT;
2944     }
2945     if ((modifiers & MOD_MASK_CTRL)
2946 #ifdef EBCDIC
2947 	    /* * TODO: EBCDIC Better use:
2948 	     * && (Ctrl_chr(key) || key == '?')
2949 	     * ???  */
2950 	    && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
2951 						       != NULL
2952 #else
2953 	    && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
2954 #endif
2955 	    )
2956     {
2957 	key = Ctrl_chr(key);
2958 	modifiers &= ~MOD_MASK_CTRL;
2959 	/* <C-@> is <Nul> */
2960 	if (key == 0)
2961 	    key = K_ZERO;
2962     }
2963 #ifdef MACOS
2964     /* Command-key really special, no fancynest */
2965     if (!(modifiers & MOD_MASK_CMD))
2966 #endif
2967     if ((modifiers & MOD_MASK_ALT) && key < 0x80
2968 #ifdef FEAT_MBYTE
2969 	    && !enc_dbcs		/* avoid creating a lead byte */
2970 #endif
2971 	    )
2972     {
2973 	key |= 0x80;
2974 	modifiers &= ~MOD_MASK_ALT;	/* remove the META modifier */
2975     }
2976 
2977     *modp = modifiers;
2978     return key;
2979 }
2980 
2981 /*
2982  * Try to find key "c" in the special key table.
2983  * Return the index when found, -1 when not found.
2984  */
2985     int
2986 find_special_key_in_table(c)
2987     int	    c;
2988 {
2989     int	    i;
2990 
2991     for (i = 0; key_names_table[i].name != NULL; i++)
2992 	if (c == key_names_table[i].key)
2993 	    break;
2994     if (key_names_table[i].name == NULL)
2995 	i = -1;
2996     return i;
2997 }
2998 
2999 /*
3000  * Find the special key with the given name (the given string does not have to
3001  * end with NUL, the name is assumed to end before the first non-idchar).
3002  * If the name starts with "t_" the next two characters are interpreted as a
3003  * termcap name.
3004  * Return the key code, or 0 if not found.
3005  */
3006     int
3007 get_special_key_code(name)
3008     char_u  *name;
3009 {
3010     char_u  *table_name;
3011     char_u  string[3];
3012     int	    i, j;
3013 
3014     /*
3015      * If it's <t_xx> we get the code for xx from the termcap
3016      */
3017     if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
3018     {
3019 	string[0] = name[2];
3020 	string[1] = name[3];
3021 	string[2] = NUL;
3022 	if (add_termcap_entry(string, FALSE) == OK)
3023 	    return TERMCAP2KEY(name[2], name[3]);
3024     }
3025     else
3026 	for (i = 0; key_names_table[i].name != NULL; i++)
3027 	{
3028 	    table_name = key_names_table[i].name;
3029 	    for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
3030 		if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
3031 		    break;
3032 	    if (!vim_isIDc(name[j]) && table_name[j] == NUL)
3033 		return key_names_table[i].key;
3034 	}
3035     return 0;
3036 }
3037 
3038 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3039     char_u *
3040 get_key_name(i)
3041     int	    i;
3042 {
3043     if (i >= (int)KEY_NAMES_TABLE_LEN)
3044 	return NULL;
3045     return  key_names_table[i].name;
3046 }
3047 #endif
3048 
3049 #if defined(FEAT_MOUSE) || defined(PROTO)
3050 /*
3051  * Look up the given mouse code to return the relevant information in the other
3052  * arguments.  Return which button is down or was released.
3053  */
3054     int
3055 get_mouse_button(code, is_click, is_drag)
3056     int	    code;
3057     int	    *is_click;
3058     int	    *is_drag;
3059 {
3060     int	    i;
3061 
3062     for (i = 0; mouse_table[i].pseudo_code; i++)
3063 	if (code == mouse_table[i].pseudo_code)
3064 	{
3065 	    *is_click = mouse_table[i].is_click;
3066 	    *is_drag = mouse_table[i].is_drag;
3067 	    return mouse_table[i].button;
3068 	}
3069     return 0;	    /* Shouldn't get here */
3070 }
3071 
3072 /*
3073  * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
3074  * the given information about which mouse button is down, and whether the
3075  * mouse was clicked, dragged or released.
3076  */
3077     int
3078 get_pseudo_mouse_code(button, is_click, is_drag)
3079     int	    button;	/* eg MOUSE_LEFT */
3080     int	    is_click;
3081     int	    is_drag;
3082 {
3083     int	    i;
3084 
3085     for (i = 0; mouse_table[i].pseudo_code; i++)
3086 	if (button == mouse_table[i].button
3087 	    && is_click == mouse_table[i].is_click
3088 	    && is_drag == mouse_table[i].is_drag)
3089 	{
3090 #ifdef FEAT_GUI
3091 	    /* Trick: a non mappable left click and release has mouse_col -1
3092 	     * or added MOUSE_COLOFF.  Used for 'mousefocus' in
3093 	     * gui_mouse_moved() */
3094 	    if (mouse_col < 0 || mouse_col > MOUSE_COLOFF)
3095 	    {
3096 		if (mouse_col < 0)
3097 		    mouse_col = 0;
3098 		else
3099 		    mouse_col -= MOUSE_COLOFF;
3100 		if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE)
3101 		    return (int)KE_LEFTMOUSE_NM;
3102 		if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE)
3103 		    return (int)KE_LEFTRELEASE_NM;
3104 	    }
3105 #endif
3106 	    return mouse_table[i].pseudo_code;
3107 	}
3108     return (int)KE_IGNORE;	    /* not recognized, ignore it */
3109 }
3110 #endif /* FEAT_MOUSE */
3111 
3112 /*
3113  * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
3114  */
3115     int
3116 get_fileformat(buf)
3117     buf_T	*buf;
3118 {
3119     int		c = *buf->b_p_ff;
3120 
3121     if (buf->b_p_bin || c == 'u')
3122 	return EOL_UNIX;
3123     if (c == 'm')
3124 	return EOL_MAC;
3125     return EOL_DOS;
3126 }
3127 
3128 /*
3129  * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
3130  * argument.
3131  */
3132     int
3133 get_fileformat_force(buf, eap)
3134     buf_T	*buf;
3135     exarg_T	*eap;	    /* can be NULL! */
3136 {
3137     int		c;
3138 
3139     if (eap != NULL && eap->force_ff != 0)
3140 	c = eap->cmd[eap->force_ff];
3141     else
3142     {
3143 	if ((eap != NULL && eap->force_bin != 0)
3144 			       ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin)
3145 	    return EOL_UNIX;
3146 	c = *buf->b_p_ff;
3147     }
3148     if (c == 'u')
3149 	return EOL_UNIX;
3150     if (c == 'm')
3151 	return EOL_MAC;
3152     return EOL_DOS;
3153 }
3154 
3155 /*
3156  * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
3157  * Sets both 'textmode' and 'fileformat'.
3158  * Note: Does _not_ set global value of 'textmode'!
3159  */
3160     void
3161 set_fileformat(t, opt_flags)
3162     int		t;
3163     int		opt_flags;	/* OPT_LOCAL and/or OPT_GLOBAL */
3164 {
3165     char	*p = NULL;
3166 
3167     switch (t)
3168     {
3169     case EOL_DOS:
3170 	p = FF_DOS;
3171 	curbuf->b_p_tx = TRUE;
3172 	break;
3173     case EOL_UNIX:
3174 	p = FF_UNIX;
3175 	curbuf->b_p_tx = FALSE;
3176 	break;
3177     case EOL_MAC:
3178 	p = FF_MAC;
3179 	curbuf->b_p_tx = FALSE;
3180 	break;
3181     }
3182     if (p != NULL)
3183 	set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
3184 						     OPT_FREE | opt_flags, 0);
3185 
3186 #ifdef FEAT_WINDOWS
3187     /* This may cause the buffer to become (un)modified. */
3188     check_status(curbuf);
3189     redraw_tabline = TRUE;
3190 #endif
3191 #ifdef FEAT_TITLE
3192     need_maketitle = TRUE;	    /* set window title later */
3193 #endif
3194 }
3195 
3196 /*
3197  * Return the default fileformat from 'fileformats'.
3198  */
3199     int
3200 default_fileformat()
3201 {
3202     switch (*p_ffs)
3203     {
3204 	case 'm':   return EOL_MAC;
3205 	case 'd':   return EOL_DOS;
3206     }
3207     return EOL_UNIX;
3208 }
3209 
3210 /*
3211  * Call shell.	Calls mch_call_shell, with 'shellxquote' added.
3212  */
3213     int
3214 call_shell(cmd, opt)
3215     char_u	*cmd;
3216     int		opt;
3217 {
3218     char_u	*ncmd;
3219     int		retval;
3220 #ifdef FEAT_PROFILE
3221     proftime_T	wait_time;
3222 #endif
3223 
3224     if (p_verbose > 3)
3225     {
3226 	verbose_enter();
3227 	smsg((char_u *)_("Calling shell to execute: \"%s\""),
3228 						    cmd == NULL ? p_sh : cmd);
3229 	out_char('\n');
3230 	cursor_on();
3231 	verbose_leave();
3232     }
3233 
3234 #ifdef FEAT_PROFILE
3235     if (do_profiling == PROF_YES)
3236 	prof_child_enter(&wait_time);
3237 #endif
3238 
3239     if (*p_sh == NUL)
3240     {
3241 	EMSG(_(e_shellempty));
3242 	retval = -1;
3243     }
3244     else
3245     {
3246 #ifdef FEAT_GUI_MSWIN
3247 	/* Don't hide the pointer while executing a shell command. */
3248 	gui_mch_mousehide(FALSE);
3249 #endif
3250 #ifdef FEAT_GUI
3251 	++hold_gui_events;
3252 #endif
3253 	/* The external command may update a tags file, clear cached tags. */
3254 	tag_freematch();
3255 
3256 	if (cmd == NULL || *p_sxq == NUL)
3257 	    retval = mch_call_shell(cmd, opt);
3258 	else
3259 	{
3260 	    char_u *ecmd = cmd;
3261 
3262 	    if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0)
3263 	    {
3264 		ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE);
3265 		if (ecmd == NULL)
3266 		    ecmd = cmd;
3267 	    }
3268 	    ncmd = alloc((unsigned)(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1));
3269 	    if (ncmd != NULL)
3270 	    {
3271 		STRCPY(ncmd, p_sxq);
3272 		STRCAT(ncmd, ecmd);
3273 		/* When 'shellxquote' is ( append ).
3274 		 * When 'shellxquote' is "( append )". */
3275 		STRCAT(ncmd, STRCMP(p_sxq, "(") == 0 ? (char_u *)")"
3276 			   : STRCMP(p_sxq, "\"(") == 0 ? (char_u *)")\""
3277 			   : p_sxq);
3278 		retval = mch_call_shell(ncmd, opt);
3279 		vim_free(ncmd);
3280 	    }
3281 	    else
3282 		retval = -1;
3283 	    if (ecmd != cmd)
3284 		vim_free(ecmd);
3285 	}
3286 #ifdef FEAT_GUI
3287 	--hold_gui_events;
3288 #endif
3289 	/*
3290 	 * Check the window size, in case it changed while executing the
3291 	 * external command.
3292 	 */
3293 	shell_resized_check();
3294     }
3295 
3296 #ifdef FEAT_EVAL
3297     set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
3298 # ifdef FEAT_PROFILE
3299     if (do_profiling == PROF_YES)
3300 	prof_child_exit(&wait_time);
3301 # endif
3302 #endif
3303 
3304     return retval;
3305 }
3306 
3307 /*
3308  * VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to
3309  * NORMAL State with a condition.  This function returns the real State.
3310  */
3311     int
3312 get_real_state()
3313 {
3314     if (State & NORMAL)
3315     {
3316 	if (VIsual_active)
3317 	{
3318 	    if (VIsual_select)
3319 		return SELECTMODE;
3320 	    return VISUAL;
3321 	}
3322 	else if (finish_op)
3323 	    return OP_PENDING;
3324     }
3325     return State;
3326 }
3327 
3328 #if defined(FEAT_MBYTE) || defined(PROTO)
3329 /*
3330  * Return TRUE if "p" points to just after a path separator.
3331  * Takes care of multi-byte characters.
3332  * "b" must point to the start of the file name
3333  */
3334     int
3335 after_pathsep(b, p)
3336     char_u	*b;
3337     char_u	*p;
3338 {
3339     return p > b && vim_ispathsep(p[-1])
3340 			     && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0);
3341 }
3342 #endif
3343 
3344 /*
3345  * Return TRUE if file names "f1" and "f2" are in the same directory.
3346  * "f1" may be a short name, "f2" must be a full path.
3347  */
3348     int
3349 same_directory(f1, f2)
3350     char_u	*f1;
3351     char_u	*f2;
3352 {
3353     char_u	ffname[MAXPATHL];
3354     char_u	*t1;
3355     char_u	*t2;
3356 
3357     /* safety check */
3358     if (f1 == NULL || f2 == NULL)
3359 	return FALSE;
3360 
3361     (void)vim_FullName(f1, ffname, MAXPATHL, FALSE);
3362     t1 = gettail_sep(ffname);
3363     t2 = gettail_sep(f2);
3364     return (t1 - ffname == t2 - f2
3365 	     && pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0);
3366 }
3367 
3368 #if defined(FEAT_SESSION) || defined(MSWIN) || defined(FEAT_GUI_MAC) \
3369 	|| ((defined(FEAT_GUI_GTK)) \
3370 			&& ( defined(FEAT_WINDOWS) || defined(FEAT_DND)) ) \
3371 	|| defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
3372 	|| defined(PROTO)
3373 /*
3374  * Change to a file's directory.
3375  * Caller must call shorten_fnames()!
3376  * Return OK or FAIL.
3377  */
3378     int
3379 vim_chdirfile(fname)
3380     char_u	*fname;
3381 {
3382     char_u	dir[MAXPATHL];
3383 
3384     vim_strncpy(dir, fname, MAXPATHL - 1);
3385     *gettail_sep(dir) = NUL;
3386     return mch_chdir((char *)dir) == 0 ? OK : FAIL;
3387 }
3388 #endif
3389 
3390 #if defined(STAT_IGNORES_SLASH) || defined(PROTO)
3391 /*
3392  * Check if "name" ends in a slash and is not a directory.
3393  * Used for systems where stat() ignores a trailing slash on a file name.
3394  * The Vim code assumes a trailing slash is only ignored for a directory.
3395  */
3396     int
3397 illegal_slash(name)
3398     char *name;
3399 {
3400     if (name[0] == NUL)
3401 	return FALSE;	    /* no file name is not illegal */
3402     if (name[strlen(name) - 1] != '/')
3403 	return FALSE;	    /* no trailing slash */
3404     if (mch_isdir((char_u *)name))
3405 	return FALSE;	    /* trailing slash for a directory */
3406     return TRUE;
3407 }
3408 #endif
3409 
3410 #if defined(CURSOR_SHAPE) || defined(PROTO)
3411 
3412 /*
3413  * Handling of cursor and mouse pointer shapes in various modes.
3414  */
3415 
3416 cursorentry_T shape_table[SHAPE_IDX_COUNT] =
3417 {
3418     /* The values will be filled in from the 'guicursor' and 'mouseshape'
3419      * defaults when Vim starts.
3420      * Adjust the SHAPE_IDX_ defines when making changes! */
3421     {0,	0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
3422     {0,	0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
3423     {0,	0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
3424     {0,	0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
3425     {0,	0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
3426     {0,	0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
3427     {0,	0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
3428     {0,	0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
3429     {0,	0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
3430     {0,	0, 0,   0L,   0L,   0L, 0, 0, "e", SHAPE_MOUSE},
3431     {0,	0, 0,   0L,   0L,   0L, 0, 0, "s", SHAPE_MOUSE},
3432     {0,	0, 0,   0L,   0L,   0L, 0, 0, "sd", SHAPE_MOUSE},
3433     {0,	0, 0,   0L,   0L,   0L, 0, 0, "vs", SHAPE_MOUSE},
3434     {0,	0, 0,   0L,   0L,   0L, 0, 0, "vd", SHAPE_MOUSE},
3435     {0,	0, 0,   0L,   0L,   0L, 0, 0, "m", SHAPE_MOUSE},
3436     {0,	0, 0,   0L,   0L,   0L, 0, 0, "ml", SHAPE_MOUSE},
3437     {0,	0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
3438 };
3439 
3440 #ifdef FEAT_MOUSESHAPE
3441 /*
3442  * Table with names for mouse shapes.  Keep in sync with all the tables for
3443  * mch_set_mouse_shape()!.
3444  */
3445 static char * mshape_names[] =
3446 {
3447     "arrow",	/* default, must be the first one */
3448     "blank",	/* hidden */
3449     "beam",
3450     "updown",
3451     "udsizing",
3452     "leftright",
3453     "lrsizing",
3454     "busy",
3455     "no",
3456     "crosshair",
3457     "hand1",
3458     "hand2",
3459     "pencil",
3460     "question",
3461     "rightup-arrow",
3462     "up-arrow",
3463     NULL
3464 };
3465 #endif
3466 
3467 /*
3468  * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
3469  * ("what" is SHAPE_MOUSE).
3470  * Returns error message for an illegal option, NULL otherwise.
3471  */
3472     char_u *
3473 parse_shape_opt(what)
3474     int		what;
3475 {
3476     char_u	*modep;
3477     char_u	*colonp;
3478     char_u	*commap;
3479     char_u	*slashp;
3480     char_u	*p, *endp;
3481     int		idx = 0;		/* init for GCC */
3482     int		all_idx;
3483     int		len;
3484     int		i;
3485     long	n;
3486     int		found_ve = FALSE;	/* found "ve" flag */
3487     int		round;
3488 
3489     /*
3490      * First round: check for errors; second round: do it for real.
3491      */
3492     for (round = 1; round <= 2; ++round)
3493     {
3494 	/*
3495 	 * Repeat for all comma separated parts.
3496 	 */
3497 #ifdef FEAT_MOUSESHAPE
3498 	if (what == SHAPE_MOUSE)
3499 	    modep = p_mouseshape;
3500 	else
3501 #endif
3502 	    modep = p_guicursor;
3503 	while (*modep != NUL)
3504 	{
3505 	    colonp = vim_strchr(modep, ':');
3506 	    if (colonp == NULL)
3507 		return (char_u *)N_("E545: Missing colon");
3508 	    if (colonp == modep)
3509 		return (char_u *)N_("E546: Illegal mode");
3510 	    commap = vim_strchr(modep, ',');
3511 
3512 	    /*
3513 	     * Repeat for all mode's before the colon.
3514 	     * For the 'a' mode, we loop to handle all the modes.
3515 	     */
3516 	    all_idx = -1;
3517 	    while (modep < colonp || all_idx >= 0)
3518 	    {
3519 		if (all_idx < 0)
3520 		{
3521 		    /* Find the mode. */
3522 		    if (modep[1] == '-' || modep[1] == ':')
3523 			len = 1;
3524 		    else
3525 			len = 2;
3526 		    if (len == 1 && TOLOWER_ASC(modep[0]) == 'a')
3527 			all_idx = SHAPE_IDX_COUNT - 1;
3528 		    else
3529 		    {
3530 			for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
3531 			    if (STRNICMP(modep, shape_table[idx].name, len)
3532 									 == 0)
3533 				break;
3534 			if (idx == SHAPE_IDX_COUNT
3535 				   || (shape_table[idx].used_for & what) == 0)
3536 			    return (char_u *)N_("E546: Illegal mode");
3537 			if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
3538 			    found_ve = TRUE;
3539 		    }
3540 		    modep += len + 1;
3541 		}
3542 
3543 		if (all_idx >= 0)
3544 		    idx = all_idx--;
3545 		else if (round == 2)
3546 		{
3547 #ifdef FEAT_MOUSESHAPE
3548 		    if (what == SHAPE_MOUSE)
3549 		    {
3550 			/* Set the default, for the missing parts */
3551 			shape_table[idx].mshape = 0;
3552 		    }
3553 		    else
3554 #endif
3555 		    {
3556 			/* Set the defaults, for the missing parts */
3557 			shape_table[idx].shape = SHAPE_BLOCK;
3558 			shape_table[idx].blinkwait = 700L;
3559 			shape_table[idx].blinkon = 400L;
3560 			shape_table[idx].blinkoff = 250L;
3561 		    }
3562 		}
3563 
3564 		/* Parse the part after the colon */
3565 		for (p = colonp + 1; *p && *p != ','; )
3566 		{
3567 #ifdef FEAT_MOUSESHAPE
3568 		    if (what == SHAPE_MOUSE)
3569 		    {
3570 			for (i = 0; ; ++i)
3571 			{
3572 			    if (mshape_names[i] == NULL)
3573 			    {
3574 				if (!VIM_ISDIGIT(*p))
3575 				    return (char_u *)N_("E547: Illegal mouseshape");
3576 				if (round == 2)
3577 				    shape_table[idx].mshape =
3578 					      getdigits(&p) + MSHAPE_NUMBERED;
3579 				else
3580 				    (void)getdigits(&p);
3581 				break;
3582 			    }
3583 			    len = (int)STRLEN(mshape_names[i]);
3584 			    if (STRNICMP(p, mshape_names[i], len) == 0)
3585 			    {
3586 				if (round == 2)
3587 				    shape_table[idx].mshape = i;
3588 				p += len;
3589 				break;
3590 			    }
3591 			}
3592 		    }
3593 		    else /* if (what == SHAPE_MOUSE) */
3594 #endif
3595 		    {
3596 			/*
3597 			 * First handle the ones with a number argument.
3598 			 */
3599 			i = *p;
3600 			len = 0;
3601 			if (STRNICMP(p, "ver", 3) == 0)
3602 			    len = 3;
3603 			else if (STRNICMP(p, "hor", 3) == 0)
3604 			    len = 3;
3605 			else if (STRNICMP(p, "blinkwait", 9) == 0)
3606 			    len = 9;
3607 			else if (STRNICMP(p, "blinkon", 7) == 0)
3608 			    len = 7;
3609 			else if (STRNICMP(p, "blinkoff", 8) == 0)
3610 			    len = 8;
3611 			if (len != 0)
3612 			{
3613 			    p += len;
3614 			    if (!VIM_ISDIGIT(*p))
3615 				return (char_u *)N_("E548: digit expected");
3616 			    n = getdigits(&p);
3617 			    if (len == 3)   /* "ver" or "hor" */
3618 			    {
3619 				if (n == 0)
3620 				    return (char_u *)N_("E549: Illegal percentage");
3621 				if (round == 2)
3622 				{
3623 				    if (TOLOWER_ASC(i) == 'v')
3624 					shape_table[idx].shape = SHAPE_VER;
3625 				    else
3626 					shape_table[idx].shape = SHAPE_HOR;
3627 				    shape_table[idx].percentage = n;
3628 				}
3629 			    }
3630 			    else if (round == 2)
3631 			    {
3632 				if (len == 9)
3633 				    shape_table[idx].blinkwait = n;
3634 				else if (len == 7)
3635 				    shape_table[idx].blinkon = n;
3636 				else
3637 				    shape_table[idx].blinkoff = n;
3638 			    }
3639 			}
3640 			else if (STRNICMP(p, "block", 5) == 0)
3641 			{
3642 			    if (round == 2)
3643 				shape_table[idx].shape = SHAPE_BLOCK;
3644 			    p += 5;
3645 			}
3646 			else	/* must be a highlight group name then */
3647 			{
3648 			    endp = vim_strchr(p, '-');
3649 			    if (commap == NULL)		    /* last part */
3650 			    {
3651 				if (endp == NULL)
3652 				    endp = p + STRLEN(p);   /* find end of part */
3653 			    }
3654 			    else if (endp > commap || endp == NULL)
3655 				endp = commap;
3656 			    slashp = vim_strchr(p, '/');
3657 			    if (slashp != NULL && slashp < endp)
3658 			    {
3659 				/* "group/langmap_group" */
3660 				i = syn_check_group(p, (int)(slashp - p));
3661 				p = slashp + 1;
3662 			    }
3663 			    if (round == 2)
3664 			    {
3665 				shape_table[idx].id = syn_check_group(p,
3666 							     (int)(endp - p));
3667 				shape_table[idx].id_lm = shape_table[idx].id;
3668 				if (slashp != NULL && slashp < endp)
3669 				    shape_table[idx].id = i;
3670 			    }
3671 			    p = endp;
3672 			}
3673 		    } /* if (what != SHAPE_MOUSE) */
3674 
3675 		    if (*p == '-')
3676 			++p;
3677 		}
3678 	    }
3679 	    modep = p;
3680 	    if (*modep == ',')
3681 		++modep;
3682 	}
3683     }
3684 
3685     /* If the 's' flag is not given, use the 'v' cursor for 's' */
3686     if (!found_ve)
3687     {
3688 #ifdef FEAT_MOUSESHAPE
3689 	if (what == SHAPE_MOUSE)
3690 	{
3691 	    shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape;
3692 	}
3693 	else
3694 #endif
3695 	{
3696 	    shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
3697 	    shape_table[SHAPE_IDX_VE].percentage =
3698 					 shape_table[SHAPE_IDX_V].percentage;
3699 	    shape_table[SHAPE_IDX_VE].blinkwait =
3700 					  shape_table[SHAPE_IDX_V].blinkwait;
3701 	    shape_table[SHAPE_IDX_VE].blinkon =
3702 					    shape_table[SHAPE_IDX_V].blinkon;
3703 	    shape_table[SHAPE_IDX_VE].blinkoff =
3704 					   shape_table[SHAPE_IDX_V].blinkoff;
3705 	    shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
3706 	    shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
3707 	}
3708     }
3709 
3710     return NULL;
3711 }
3712 
3713 # if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \
3714 	|| defined(FEAT_MOUSESHAPE) || defined(PROTO)
3715 /*
3716  * Return the index into shape_table[] for the current mode.
3717  * When "mouse" is TRUE, consider indexes valid for the mouse pointer.
3718  */
3719     int
3720 get_shape_idx(mouse)
3721     int	mouse;
3722 {
3723 #ifdef FEAT_MOUSESHAPE
3724     if (mouse && (State == HITRETURN || State == ASKMORE))
3725     {
3726 # ifdef FEAT_GUI
3727 	int x, y;
3728 	gui_mch_getmouse(&x, &y);
3729 	if (Y_2_ROW(y) == Rows - 1)
3730 	    return SHAPE_IDX_MOREL;
3731 # endif
3732 	return SHAPE_IDX_MORE;
3733     }
3734     if (mouse && drag_status_line)
3735 	return SHAPE_IDX_SDRAG;
3736 # ifdef FEAT_VERTSPLIT
3737     if (mouse && drag_sep_line)
3738 	return SHAPE_IDX_VDRAG;
3739 # endif
3740 #endif
3741     if (!mouse && State == SHOWMATCH)
3742 	return SHAPE_IDX_SM;
3743 #ifdef FEAT_VREPLACE
3744     if (State & VREPLACE_FLAG)
3745 	return SHAPE_IDX_R;
3746 #endif
3747     if (State & REPLACE_FLAG)
3748 	return SHAPE_IDX_R;
3749     if (State & INSERT)
3750 	return SHAPE_IDX_I;
3751     if (State & CMDLINE)
3752     {
3753 	if (cmdline_at_end())
3754 	    return SHAPE_IDX_C;
3755 	if (cmdline_overstrike())
3756 	    return SHAPE_IDX_CR;
3757 	return SHAPE_IDX_CI;
3758     }
3759     if (finish_op)
3760 	return SHAPE_IDX_O;
3761     if (VIsual_active)
3762     {
3763 	if (*p_sel == 'e')
3764 	    return SHAPE_IDX_VE;
3765 	else
3766 	    return SHAPE_IDX_V;
3767     }
3768     return SHAPE_IDX_N;
3769 }
3770 #endif
3771 
3772 # if defined(FEAT_MOUSESHAPE) || defined(PROTO)
3773 static int old_mouse_shape = 0;
3774 
3775 /*
3776  * Set the mouse shape:
3777  * If "shape" is -1, use shape depending on the current mode,
3778  * depending on the current state.
3779  * If "shape" is -2, only update the shape when it's CLINE or STATUS (used
3780  * when the mouse moves off the status or command line).
3781  */
3782     void
3783 update_mouseshape(shape_idx)
3784     int	shape_idx;
3785 {
3786     int new_mouse_shape;
3787 
3788     /* Only works in GUI mode. */
3789     if (!gui.in_use || gui.starting)
3790 	return;
3791 
3792     /* Postpone the updating when more is to come.  Speeds up executing of
3793      * mappings. */
3794     if (shape_idx == -1 && char_avail())
3795     {
3796 	postponed_mouseshape = TRUE;
3797 	return;
3798     }
3799 
3800     /* When ignoring the mouse don't change shape on the statusline. */
3801     if (*p_mouse == NUL
3802 	    && (shape_idx == SHAPE_IDX_CLINE
3803 		|| shape_idx == SHAPE_IDX_STATUS
3804 		|| shape_idx == SHAPE_IDX_VSEP))
3805 	shape_idx = -2;
3806 
3807     if (shape_idx == -2
3808 	    && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape
3809 	    && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape
3810 	    && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape)
3811 	return;
3812     if (shape_idx < 0)
3813 	new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape;
3814     else
3815 	new_mouse_shape = shape_table[shape_idx].mshape;
3816     if (new_mouse_shape != old_mouse_shape)
3817     {
3818 	mch_set_mouse_shape(new_mouse_shape);
3819 	old_mouse_shape = new_mouse_shape;
3820     }
3821     postponed_mouseshape = FALSE;
3822 }
3823 # endif
3824 
3825 #endif /* CURSOR_SHAPE */
3826 
3827 
3828 /* TODO: make some #ifdef for this */
3829 /*--------[ file searching ]-------------------------------------------------*/
3830 /*
3831  * File searching functions for 'path', 'tags' and 'cdpath' options.
3832  * External visible functions:
3833  * vim_findfile_init()		creates/initialises the search context
3834  * vim_findfile_free_visited()	free list of visited files/dirs of search
3835  *				context
3836  * vim_findfile()		find a file in the search context
3837  * vim_findfile_cleanup()	cleanup/free search context created by
3838  *				vim_findfile_init()
3839  *
3840  * All static functions and variables start with 'ff_'
3841  *
3842  * In general it works like this:
3843  * First you create yourself a search context by calling vim_findfile_init().
3844  * It is possible to give a search context from a previous call to
3845  * vim_findfile_init(), so it can be reused. After this you call vim_findfile()
3846  * until you are satisfied with the result or it returns NULL. On every call it
3847  * returns the next file which matches the conditions given to
3848  * vim_findfile_init(). If it doesn't find a next file it returns NULL.
3849  *
3850  * It is possible to call vim_findfile_init() again to reinitialise your search
3851  * with some new parameters. Don't forget to pass your old search context to
3852  * it, so it can reuse it and especially reuse the list of already visited
3853  * directories. If you want to delete the list of already visited directories
3854  * simply call vim_findfile_free_visited().
3855  *
3856  * When you are done call vim_findfile_cleanup() to free the search context.
3857  *
3858  * The function vim_findfile_init() has a long comment, which describes the
3859  * needed parameters.
3860  *
3861  *
3862  *
3863  * ATTENTION:
3864  * ==========
3865  *	Also we use an allocated search context here, this functions are NOT
3866  *	thread-safe!!!!!
3867  *
3868  *	To minimize parameter passing (or because I'm to lazy), only the
3869  *	external visible functions get a search context as a parameter. This is
3870  *	then assigned to a static global, which is used throughout the local
3871  *	functions.
3872  */
3873 
3874 /*
3875  * type for the directory search stack
3876  */
3877 typedef struct ff_stack
3878 {
3879     struct ff_stack	*ffs_prev;
3880 
3881     /* the fix part (no wildcards) and the part containing the wildcards
3882      * of the search path
3883      */
3884     char_u		*ffs_fix_path;
3885 #ifdef FEAT_PATH_EXTRA
3886     char_u		*ffs_wc_path;
3887 #endif
3888 
3889     /* files/dirs found in the above directory, matched by the first wildcard
3890      * of wc_part
3891      */
3892     char_u		**ffs_filearray;
3893     int			ffs_filearray_size;
3894     char_u		ffs_filearray_cur;   /* needed for partly handled dirs */
3895 
3896     /* to store status of partly handled directories
3897      * 0: we work on this directory for the first time
3898      * 1: this directory was partly searched in an earlier step
3899      */
3900     int			ffs_stage;
3901 
3902     /* How deep are we in the directory tree?
3903      * Counts backward from value of level parameter to vim_findfile_init
3904      */
3905     int			ffs_level;
3906 
3907     /* Did we already expand '**' to an empty string? */
3908     int			ffs_star_star_empty;
3909 } ff_stack_T;
3910 
3911 /*
3912  * type for already visited directories or files.
3913  */
3914 typedef struct ff_visited
3915 {
3916     struct ff_visited	*ffv_next;
3917 
3918 #ifdef FEAT_PATH_EXTRA
3919     /* Visited directories are different if the wildcard string are
3920      * different. So we have to save it.
3921      */
3922     char_u		*ffv_wc_path;
3923 #endif
3924     /* for unix use inode etc for comparison (needed because of links), else
3925      * use filename.
3926      */
3927 #ifdef UNIX
3928     int			ffv_dev_valid;	/* ffv_dev and ffv_ino were set */
3929     dev_t		ffv_dev;	/* device number */
3930     ino_t		ffv_ino;	/* inode number */
3931 #endif
3932     /* The memory for this struct is allocated according to the length of
3933      * ffv_fname.
3934      */
3935     char_u		ffv_fname[1];	/* actually longer */
3936 } ff_visited_T;
3937 
3938 /*
3939  * We might have to manage several visited lists during a search.
3940  * This is especially needed for the tags option. If tags is set to:
3941  *      "./++/tags,./++/TAGS,++/tags"  (replace + with *)
3942  * So we have to do 3 searches:
3943  *   1) search from the current files directory downward for the file "tags"
3944  *   2) search from the current files directory downward for the file "TAGS"
3945  *   3) search from Vims current directory downwards for the file "tags"
3946  * As you can see, the first and the third search are for the same file, so for
3947  * the third search we can use the visited list of the first search. For the
3948  * second search we must start from a empty visited list.
3949  * The struct ff_visited_list_hdr is used to manage a linked list of already
3950  * visited lists.
3951  */
3952 typedef struct ff_visited_list_hdr
3953 {
3954     struct ff_visited_list_hdr	*ffvl_next;
3955 
3956     /* the filename the attached visited list is for */
3957     char_u			*ffvl_filename;
3958 
3959     ff_visited_T		*ffvl_visited_list;
3960 
3961 } ff_visited_list_hdr_T;
3962 
3963 
3964 /*
3965  * '**' can be expanded to several directory levels.
3966  * Set the default maximum depth.
3967  */
3968 #define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
3969 
3970 /*
3971  * The search context:
3972  *   ffsc_stack_ptr:	the stack for the dirs to search
3973  *   ffsc_visited_list: the currently active visited list
3974  *   ffsc_dir_visited_list: the currently active visited list for search dirs
3975  *   ffsc_visited_lists_list: the list of all visited lists
3976  *   ffsc_dir_visited_lists_list: the list of all visited lists for search dirs
3977  *   ffsc_file_to_search:     the file to search for
3978  *   ffsc_start_dir:	the starting directory, if search path was relative
3979  *   ffsc_fix_path:	the fix part of the given path (without wildcards)
3980  *			Needed for upward search.
3981  *   ffsc_wc_path:	the part of the given path containing wildcards
3982  *   ffsc_level:	how many levels of dirs to search downwards
3983  *   ffsc_stopdirs_v:	array of stop directories for upward search
3984  *   ffsc_find_what:	FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE
3985  *   ffsc_tagfile:	searching for tags file, don't use 'suffixesadd'
3986  */
3987 typedef struct ff_search_ctx_T
3988 {
3989      ff_stack_T			*ffsc_stack_ptr;
3990      ff_visited_list_hdr_T	*ffsc_visited_list;
3991      ff_visited_list_hdr_T	*ffsc_dir_visited_list;
3992      ff_visited_list_hdr_T	*ffsc_visited_lists_list;
3993      ff_visited_list_hdr_T	*ffsc_dir_visited_lists_list;
3994      char_u			*ffsc_file_to_search;
3995      char_u			*ffsc_start_dir;
3996      char_u			*ffsc_fix_path;
3997 #ifdef FEAT_PATH_EXTRA
3998      char_u			*ffsc_wc_path;
3999      int			ffsc_level;
4000      char_u			**ffsc_stopdirs_v;
4001 #endif
4002      int			ffsc_find_what;
4003      int			ffsc_tagfile;
4004 } ff_search_ctx_T;
4005 
4006 /* locally needed functions */
4007 #ifdef FEAT_PATH_EXTRA
4008 static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *));
4009 #else
4010 static int ff_check_visited __ARGS((ff_visited_T **, char_u *));
4011 #endif
4012 static void vim_findfile_free_visited_list __ARGS((ff_visited_list_hdr_T **list_headp));
4013 static void ff_free_visited_list __ARGS((ff_visited_T *vl));
4014 static ff_visited_list_hdr_T* ff_get_visited_list __ARGS((char_u *, ff_visited_list_hdr_T **list_headp));
4015 #ifdef FEAT_PATH_EXTRA
4016 static int ff_wc_equal __ARGS((char_u *s1, char_u *s2));
4017 #endif
4018 
4019 static void ff_push __ARGS((ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr));
4020 static ff_stack_T *ff_pop __ARGS((ff_search_ctx_T *search_ctx));
4021 static void ff_clear __ARGS((ff_search_ctx_T *search_ctx));
4022 static void ff_free_stack_element __ARGS((ff_stack_T *stack_ptr));
4023 #ifdef FEAT_PATH_EXTRA
4024 static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int));
4025 #else
4026 static ff_stack_T *ff_create_stack_element __ARGS((char_u *, int, int));
4027 #endif
4028 #ifdef FEAT_PATH_EXTRA
4029 static int ff_path_in_stoplist __ARGS((char_u *, int, char_u **));
4030 #endif
4031 
4032 static char_u e_pathtoolong[] = N_("E854: path too long for completion");
4033 
4034 #if 0
4035 /*
4036  * if someone likes findfirst/findnext, here are the functions
4037  * NOT TESTED!!
4038  */
4039 
4040 static void *ff_fn_search_context = NULL;
4041 
4042     char_u *
4043 vim_findfirst(path, filename, level)
4044     char_u	*path;
4045     char_u	*filename;
4046     int		level;
4047 {
4048     ff_fn_search_context =
4049 	vim_findfile_init(path, filename, NULL, level, TRUE, FALSE,
4050 		ff_fn_search_context, rel_fname);
4051     if (NULL == ff_fn_search_context)
4052 	return NULL;
4053     else
4054 	return vim_findnext()
4055 }
4056 
4057     char_u *
4058 vim_findnext()
4059 {
4060     char_u *ret = vim_findfile(ff_fn_search_context);
4061 
4062     if (NULL == ret)
4063     {
4064 	vim_findfile_cleanup(ff_fn_search_context);
4065 	ff_fn_search_context = NULL;
4066     }
4067     return ret;
4068 }
4069 #endif
4070 
4071 /*
4072  * Initialization routine for vim_findfile().
4073  *
4074  * Returns the newly allocated search context or NULL if an error occurred.
4075  *
4076  * Don't forget to clean up by calling vim_findfile_cleanup() if you are done
4077  * with the search context.
4078  *
4079  * Find the file 'filename' in the directory 'path'.
4080  * The parameter 'path' may contain wildcards. If so only search 'level'
4081  * directories deep. The parameter 'level' is the absolute maximum and is
4082  * not related to restricts given to the '**' wildcard. If 'level' is 100
4083  * and you use '**200' vim_findfile() will stop after 100 levels.
4084  *
4085  * 'filename' cannot contain wildcards!  It is used as-is, no backslashes to
4086  * escape special characters.
4087  *
4088  * If 'stopdirs' is not NULL and nothing is found downward, the search is
4089  * restarted on the next higher directory level. This is repeated until the
4090  * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the
4091  * format ";*<dirname>*\(;<dirname>\)*;\=$".
4092  *
4093  * If the 'path' is relative, the starting dir for the search is either VIM's
4094  * current dir or if the path starts with "./" the current files dir.
4095  * If the 'path' is absolute, the starting dir is that part of the path before
4096  * the first wildcard.
4097  *
4098  * Upward search is only done on the starting dir.
4099  *
4100  * If 'free_visited' is TRUE the list of already visited files/directories is
4101  * cleared. Set this to FALSE if you just want to search from another
4102  * directory, but want to be sure that no directory from a previous search is
4103  * searched again. This is useful if you search for a file at different places.
4104  * The list of visited files/dirs can also be cleared with the function
4105  * vim_findfile_free_visited().
4106  *
4107  * Set the parameter 'find_what' to FINDFILE_DIR if you want to search for
4108  * directories only, FINDFILE_FILE for files only, FINDFILE_BOTH for both.
4109  *
4110  * A search context returned by a previous call to vim_findfile_init() can be
4111  * passed in the parameter "search_ctx_arg".  This context is reused and
4112  * reinitialized with the new parameters.  The list of already visited
4113  * directories from this context is only deleted if the parameter
4114  * "free_visited" is true.  Be aware that the passed "search_ctx_arg" is freed
4115  * if the reinitialization fails.
4116  *
4117  * If you don't have a search context from a previous call "search_ctx_arg"
4118  * must be NULL.
4119  *
4120  * This function silently ignores a few errors, vim_findfile() will have
4121  * limited functionality then.
4122  */
4123     void *
4124 vim_findfile_init(path, filename, stopdirs, level, free_visited, find_what,
4125 					   search_ctx_arg, tagfile, rel_fname)
4126     char_u	*path;
4127     char_u	*filename;
4128     char_u	*stopdirs UNUSED;
4129     int		level;
4130     int		free_visited;
4131     int		find_what;
4132     void	*search_ctx_arg;
4133     int		tagfile;	/* expanding names of tags files */
4134     char_u	*rel_fname;	/* file name to use for "." */
4135 {
4136 #ifdef FEAT_PATH_EXTRA
4137     char_u		*wc_part;
4138 #endif
4139     ff_stack_T		*sptr;
4140     ff_search_ctx_T	*search_ctx;
4141 
4142     /* If a search context is given by the caller, reuse it, else allocate a
4143      * new one.
4144      */
4145     if (search_ctx_arg != NULL)
4146 	search_ctx = search_ctx_arg;
4147     else
4148     {
4149 	search_ctx = (ff_search_ctx_T*)alloc((unsigned)sizeof(ff_search_ctx_T));
4150 	if (search_ctx == NULL)
4151 	    goto error_return;
4152 	vim_memset(search_ctx, 0, sizeof(ff_search_ctx_T));
4153     }
4154     search_ctx->ffsc_find_what = find_what;
4155     search_ctx->ffsc_tagfile = tagfile;
4156 
4157     /* clear the search context, but NOT the visited lists */
4158     ff_clear(search_ctx);
4159 
4160     /* clear visited list if wanted */
4161     if (free_visited == TRUE)
4162 	vim_findfile_free_visited(search_ctx);
4163     else
4164     {
4165 	/* Reuse old visited lists. Get the visited list for the given
4166 	 * filename. If no list for the current filename exists, creates a new
4167 	 * one. */
4168 	search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
4169 					&search_ctx->ffsc_visited_lists_list);
4170 	if (search_ctx->ffsc_visited_list == NULL)
4171 	    goto error_return;
4172 	search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename,
4173 				    &search_ctx->ffsc_dir_visited_lists_list);
4174 	if (search_ctx->ffsc_dir_visited_list == NULL)
4175 	    goto error_return;
4176     }
4177 
4178     if (ff_expand_buffer == NULL)
4179     {
4180 	ff_expand_buffer = (char_u*)alloc(MAXPATHL);
4181 	if (ff_expand_buffer == NULL)
4182 	    goto error_return;
4183     }
4184 
4185     /* Store information on starting dir now if path is relative.
4186      * If path is absolute, we do that later.  */
4187     if (path[0] == '.'
4188 	    && (vim_ispathsep(path[1]) || path[1] == NUL)
4189 	    && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
4190 	    && rel_fname != NULL)
4191     {
4192 	int	len = (int)(gettail(rel_fname) - rel_fname);
4193 
4194 	if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL)
4195 	{
4196 	    /* Make the start dir an absolute path name. */
4197 	    vim_strncpy(ff_expand_buffer, rel_fname, len);
4198 	    search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE);
4199 	}
4200 	else
4201 	    search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
4202 	if (search_ctx->ffsc_start_dir == NULL)
4203 	    goto error_return;
4204 	if (*++path != NUL)
4205 	    ++path;
4206     }
4207     else if (*path == NUL || !vim_isAbsName(path))
4208     {
4209 #ifdef BACKSLASH_IN_FILENAME
4210 	/* "c:dir" needs "c:" to be expanded, otherwise use current dir */
4211 	if (*path != NUL && path[1] == ':')
4212 	{
4213 	    char_u  drive[3];
4214 
4215 	    drive[0] = path[0];
4216 	    drive[1] = ':';
4217 	    drive[2] = NUL;
4218 	    if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
4219 		goto error_return;
4220 	    path += 2;
4221 	}
4222 	else
4223 #endif
4224 	if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL)
4225 	    goto error_return;
4226 
4227 	search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
4228 	if (search_ctx->ffsc_start_dir == NULL)
4229 	    goto error_return;
4230 
4231 #ifdef BACKSLASH_IN_FILENAME
4232 	/* A path that starts with "/dir" is relative to the drive, not to the
4233 	 * directory (but not for "//machine/dir").  Only use the drive name. */
4234 	if ((*path == '/' || *path == '\\')
4235 		&& path[1] != path[0]
4236 		&& search_ctx->ffsc_start_dir[1] == ':')
4237 	    search_ctx->ffsc_start_dir[2] = NUL;
4238 #endif
4239     }
4240 
4241 #ifdef FEAT_PATH_EXTRA
4242     /*
4243      * If stopdirs are given, split them into an array of pointers.
4244      * If this fails (mem allocation), there is no upward search at all or a
4245      * stop directory is not recognized -> continue silently.
4246      * If stopdirs just contains a ";" or is empty,
4247      * search_ctx->ffsc_stopdirs_v will only contain a  NULL pointer. This
4248      * is handled as unlimited upward search.  See function
4249      * ff_path_in_stoplist() for details.
4250      */
4251     if (stopdirs != NULL)
4252     {
4253 	char_u	*walker = stopdirs;
4254 	int	dircount;
4255 
4256 	while (*walker == ';')
4257 	    walker++;
4258 
4259 	dircount = 1;
4260 	search_ctx->ffsc_stopdirs_v =
4261 				 (char_u **)alloc((unsigned)sizeof(char_u *));
4262 
4263 	if (search_ctx->ffsc_stopdirs_v != NULL)
4264 	{
4265 	    do
4266 	    {
4267 		char_u	*helper;
4268 		void	*ptr;
4269 
4270 		helper = walker;
4271 		ptr = vim_realloc(search_ctx->ffsc_stopdirs_v,
4272 					   (dircount + 1) * sizeof(char_u *));
4273 		if (ptr)
4274 		    search_ctx->ffsc_stopdirs_v = ptr;
4275 		else
4276 		    /* ignore, keep what we have and continue */
4277 		    break;
4278 		walker = vim_strchr(walker, ';');
4279 		if (walker)
4280 		{
4281 		    search_ctx->ffsc_stopdirs_v[dircount-1] =
4282 				 vim_strnsave(helper, (int)(walker - helper));
4283 		    walker++;
4284 		}
4285 		else
4286 		    /* this might be "", which means ascent till top
4287 		     * of directory tree.
4288 		     */
4289 		    search_ctx->ffsc_stopdirs_v[dircount-1] =
4290 							  vim_strsave(helper);
4291 
4292 		dircount++;
4293 
4294 	    } while (walker != NULL);
4295 	    search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
4296 	}
4297     }
4298 #endif
4299 
4300 #ifdef FEAT_PATH_EXTRA
4301     search_ctx->ffsc_level = level;
4302 
4303     /* split into:
4304      *  -fix path
4305      *  -wildcard_stuff (might be NULL)
4306      */
4307     wc_part = vim_strchr(path, '*');
4308     if (wc_part != NULL)
4309     {
4310 	int	llevel;
4311 	int	len;
4312 	char	*errpt;
4313 
4314 	/* save the fix part of the path */
4315 	search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path));
4316 
4317 	/*
4318 	 * copy wc_path and add restricts to the '**' wildcard.
4319 	 * The octet after a '**' is used as a (binary) counter.
4320 	 * So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
4321 	 * or '**76' is transposed to '**N'( 'N' is ASCII value 76).
4322 	 * For EBCDIC you get different character values.
4323 	 * If no restrict is given after '**' the default is used.
4324 	 * Due to this technique the path looks awful if you print it as a
4325 	 * string.
4326 	 */
4327 	len = 0;
4328 	while (*wc_part != NUL)
4329 	{
4330 	    if (len + 5 >= MAXPATHL)
4331 	    {
4332 		EMSG(_(e_pathtoolong));
4333 		break;
4334 	    }
4335 	    if (STRNCMP(wc_part, "**", 2) == 0)
4336 	    {
4337 		ff_expand_buffer[len++] = *wc_part++;
4338 		ff_expand_buffer[len++] = *wc_part++;
4339 
4340 		llevel = strtol((char *)wc_part, &errpt, 10);
4341 		if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255)
4342 		    ff_expand_buffer[len++] = llevel;
4343 		else if ((char_u *)errpt != wc_part && llevel == 0)
4344 		    /* restrict is 0 -> remove already added '**' */
4345 		    len -= 2;
4346 		else
4347 		    ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
4348 		wc_part = (char_u *)errpt;
4349 		if (*wc_part != NUL && !vim_ispathsep(*wc_part))
4350 		{
4351 		    EMSG2(_("E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR);
4352 		    goto error_return;
4353 		}
4354 	    }
4355 	    else
4356 		ff_expand_buffer[len++] = *wc_part++;
4357 	}
4358 	ff_expand_buffer[len] = NUL;
4359 	search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer);
4360 
4361 	if (search_ctx->ffsc_wc_path == NULL)
4362 	    goto error_return;
4363     }
4364     else
4365 #endif
4366 	search_ctx->ffsc_fix_path = vim_strsave(path);
4367 
4368     if (search_ctx->ffsc_start_dir == NULL)
4369     {
4370 	/* store the fix part as startdir.
4371 	 * This is needed if the parameter path is fully qualified.
4372 	 */
4373 	search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path);
4374 	if (search_ctx->ffsc_start_dir == NULL)
4375 	    goto error_return;
4376 	search_ctx->ffsc_fix_path[0] = NUL;
4377     }
4378 
4379     /* create an absolute path */
4380     if (STRLEN(search_ctx->ffsc_start_dir)
4381 			  + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL)
4382     {
4383 	EMSG(_(e_pathtoolong));
4384 	goto error_return;
4385     }
4386     STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir);
4387     add_pathsep(ff_expand_buffer);
4388     {
4389 	int    eb_len = (int)STRLEN(ff_expand_buffer);
4390 	char_u *buf = alloc(eb_len
4391 				+ (int)STRLEN(search_ctx->ffsc_fix_path) + 1);
4392 
4393 	STRCPY(buf, ff_expand_buffer);
4394 	STRCPY(buf + eb_len, search_ctx->ffsc_fix_path);
4395 	if (mch_isdir(buf))
4396 	{
4397 	    STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path);
4398 	    add_pathsep(ff_expand_buffer);
4399 	}
4400 #ifdef FEAT_PATH_EXTRA
4401 	else
4402 	{
4403 	    char_u *p =  gettail(search_ctx->ffsc_fix_path);
4404 	    char_u *wc_path = NULL;
4405 	    char_u *temp = NULL;
4406 	    int    len = 0;
4407 
4408 	    if (p > search_ctx->ffsc_fix_path)
4409 	    {
4410 		len = (int)(p - search_ctx->ffsc_fix_path) - 1;
4411 		STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len);
4412 		add_pathsep(ff_expand_buffer);
4413 	    }
4414 	    else
4415 		len = (int)STRLEN(search_ctx->ffsc_fix_path);
4416 
4417 	    if (search_ctx->ffsc_wc_path != NULL)
4418 	    {
4419 		wc_path = vim_strsave(search_ctx->ffsc_wc_path);
4420 		temp = alloc((int)(STRLEN(search_ctx->ffsc_wc_path)
4421 				 + STRLEN(search_ctx->ffsc_fix_path + len)
4422 				 + 1));
4423 		if (temp == NULL || wc_path == NULL)
4424 		{
4425 		    vim_free(buf);
4426 		    vim_free(temp);
4427 		    vim_free(wc_path);
4428 		    goto error_return;
4429 		}
4430 
4431 		STRCPY(temp, search_ctx->ffsc_fix_path + len);
4432 		STRCAT(temp, search_ctx->ffsc_wc_path);
4433 		vim_free(search_ctx->ffsc_wc_path);
4434 		vim_free(wc_path);
4435 		search_ctx->ffsc_wc_path = temp;
4436 	    }
4437 	}
4438 #endif
4439 	vim_free(buf);
4440     }
4441 
4442     sptr = ff_create_stack_element(ff_expand_buffer,
4443 #ifdef FEAT_PATH_EXTRA
4444 	    search_ctx->ffsc_wc_path,
4445 #endif
4446 	    level, 0);
4447 
4448     if (sptr == NULL)
4449 	goto error_return;
4450 
4451     ff_push(search_ctx, sptr);
4452 
4453     search_ctx->ffsc_file_to_search = vim_strsave(filename);
4454     if (search_ctx->ffsc_file_to_search == NULL)
4455 	goto error_return;
4456 
4457     return search_ctx;
4458 
4459 error_return:
4460     /*
4461      * We clear the search context now!
4462      * Even when the caller gave us a (perhaps valid) context we free it here,
4463      * as we might have already destroyed it.
4464      */
4465     vim_findfile_cleanup(search_ctx);
4466     return NULL;
4467 }
4468 
4469 #if defined(FEAT_PATH_EXTRA) || defined(PROTO)
4470 /*
4471  * Get the stopdir string.  Check that ';' is not escaped.
4472  */
4473     char_u *
4474 vim_findfile_stopdir(buf)
4475     char_u	*buf;
4476 {
4477     char_u	*r_ptr = buf;
4478 
4479     while (*r_ptr != NUL && *r_ptr != ';')
4480     {
4481 	if (r_ptr[0] == '\\' && r_ptr[1] == ';')
4482 	{
4483 	    /* Overwrite the escape char,
4484 	     * use STRLEN(r_ptr) to move the trailing '\0'. */
4485 	    STRMOVE(r_ptr, r_ptr + 1);
4486 	    r_ptr++;
4487 	}
4488 	r_ptr++;
4489     }
4490     if (*r_ptr == ';')
4491     {
4492 	*r_ptr = 0;
4493 	r_ptr++;
4494     }
4495     else if (*r_ptr == NUL)
4496 	r_ptr = NULL;
4497     return r_ptr;
4498 }
4499 #endif
4500 
4501 /*
4502  * Clean up the given search context. Can handle a NULL pointer.
4503  */
4504     void
4505 vim_findfile_cleanup(ctx)
4506     void	*ctx;
4507 {
4508     if (ctx == NULL)
4509 	return;
4510 
4511     vim_findfile_free_visited(ctx);
4512     ff_clear(ctx);
4513     vim_free(ctx);
4514 }
4515 
4516 /*
4517  * Find a file in a search context.
4518  * The search context was created with vim_findfile_init() above.
4519  * Return a pointer to an allocated file name or NULL if nothing found.
4520  * To get all matching files call this function until you get NULL.
4521  *
4522  * If the passed search_context is NULL, NULL is returned.
4523  *
4524  * The search algorithm is depth first. To change this replace the
4525  * stack with a list (don't forget to leave partly searched directories on the
4526  * top of the list).
4527  */
4528     char_u *
4529 vim_findfile(search_ctx_arg)
4530     void	*search_ctx_arg;
4531 {
4532     char_u	*file_path;
4533 #ifdef FEAT_PATH_EXTRA
4534     char_u	*rest_of_wildcards;
4535     char_u	*path_end = NULL;
4536 #endif
4537     ff_stack_T	*stackp;
4538 #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA)
4539     int		len;
4540 #endif
4541     int		i;
4542     char_u	*p;
4543 #ifdef FEAT_SEARCHPATH
4544     char_u	*suf;
4545 #endif
4546     ff_search_ctx_T *search_ctx;
4547 
4548     if (search_ctx_arg == NULL)
4549 	return NULL;
4550 
4551     search_ctx = (ff_search_ctx_T *)search_ctx_arg;
4552 
4553     /*
4554      * filepath is used as buffer for various actions and as the storage to
4555      * return a found filename.
4556      */
4557     if ((file_path = alloc((int)MAXPATHL)) == NULL)
4558 	return NULL;
4559 
4560 #ifdef FEAT_PATH_EXTRA
4561     /* store the end of the start dir -- needed for upward search */
4562     if (search_ctx->ffsc_start_dir != NULL)
4563 	path_end = &search_ctx->ffsc_start_dir[
4564 					  STRLEN(search_ctx->ffsc_start_dir)];
4565 #endif
4566 
4567 #ifdef FEAT_PATH_EXTRA
4568     /* upward search loop */
4569     for (;;)
4570     {
4571 #endif
4572 	/* downward search loop */
4573 	for (;;)
4574 	{
4575 	    /* check if user user wants to stop the search*/
4576 	    ui_breakcheck();
4577 	    if (got_int)
4578 		break;
4579 
4580 	    /* get directory to work on from stack */
4581 	    stackp = ff_pop(search_ctx);
4582 	    if (stackp == NULL)
4583 		break;
4584 
4585 	    /*
4586 	     * TODO: decide if we leave this test in
4587 	     *
4588 	     * GOOD: don't search a directory(-tree) twice.
4589 	     * BAD:  - check linked list for every new directory entered.
4590 	     *       - check for double files also done below
4591 	     *
4592 	     * Here we check if we already searched this directory.
4593 	     * We already searched a directory if:
4594 	     * 1) The directory is the same.
4595 	     * 2) We would use the same wildcard string.
4596 	     *
4597 	     * Good if you have links on same directory via several ways
4598 	     *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
4599 	     *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
4600 	     *
4601 	     * This check is only needed for directories we work on for the
4602 	     * first time (hence stackp->ff_filearray == NULL)
4603 	     */
4604 	    if (stackp->ffs_filearray == NULL
4605 		    && ff_check_visited(&search_ctx->ffsc_dir_visited_list
4606 							  ->ffvl_visited_list,
4607 			stackp->ffs_fix_path
4608 #ifdef FEAT_PATH_EXTRA
4609 			, stackp->ffs_wc_path
4610 #endif
4611 			) == FAIL)
4612 	    {
4613 #ifdef FF_VERBOSE
4614 		if (p_verbose >= 5)
4615 		{
4616 		    verbose_enter_scroll();
4617 		    smsg((char_u *)"Already Searched: %s (%s)",
4618 				   stackp->ffs_fix_path, stackp->ffs_wc_path);
4619 		    /* don't overwrite this either */
4620 		    msg_puts((char_u *)"\n");
4621 		    verbose_leave_scroll();
4622 		}
4623 #endif
4624 		ff_free_stack_element(stackp);
4625 		continue;
4626 	    }
4627 #ifdef FF_VERBOSE
4628 	    else if (p_verbose >= 5)
4629 	    {
4630 		verbose_enter_scroll();
4631 		smsg((char_u *)"Searching: %s (%s)",
4632 				   stackp->ffs_fix_path, stackp->ffs_wc_path);
4633 		/* don't overwrite this either */
4634 		msg_puts((char_u *)"\n");
4635 		verbose_leave_scroll();
4636 	    }
4637 #endif
4638 
4639 	    /* check depth */
4640 	    if (stackp->ffs_level <= 0)
4641 	    {
4642 		ff_free_stack_element(stackp);
4643 		continue;
4644 	    }
4645 
4646 	    file_path[0] = NUL;
4647 
4648 	    /*
4649 	     * If no filearray till now expand wildcards
4650 	     * The function expand_wildcards() can handle an array of paths
4651 	     * and all possible expands are returned in one array. We use this
4652 	     * to handle the expansion of '**' into an empty string.
4653 	     */
4654 	    if (stackp->ffs_filearray == NULL)
4655 	    {
4656 		char_u *dirptrs[2];
4657 
4658 		/* we use filepath to build the path expand_wildcards() should
4659 		 * expand.
4660 		 */
4661 		dirptrs[0] = file_path;
4662 		dirptrs[1] = NULL;
4663 
4664 		/* if we have a start dir copy it in */
4665 		if (!vim_isAbsName(stackp->ffs_fix_path)
4666 						&& search_ctx->ffsc_start_dir)
4667 		{
4668 		    STRCPY(file_path, search_ctx->ffsc_start_dir);
4669 		    add_pathsep(file_path);
4670 		}
4671 
4672 		/* append the fix part of the search path */
4673 		STRCAT(file_path, stackp->ffs_fix_path);
4674 		add_pathsep(file_path);
4675 
4676 #ifdef FEAT_PATH_EXTRA
4677 		rest_of_wildcards = stackp->ffs_wc_path;
4678 		if (*rest_of_wildcards != NUL)
4679 		{
4680 		    len = (int)STRLEN(file_path);
4681 		    if (STRNCMP(rest_of_wildcards, "**", 2) == 0)
4682 		    {
4683 			/* pointer to the restrict byte
4684 			 * The restrict byte is not a character!
4685 			 */
4686 			p = rest_of_wildcards + 2;
4687 
4688 			if (*p > 0)
4689 			{
4690 			    (*p)--;
4691 			    file_path[len++] = '*';
4692 			}
4693 
4694 			if (*p == 0)
4695 			{
4696 			    /* remove '**<numb> from wildcards */
4697 			    STRMOVE(rest_of_wildcards, rest_of_wildcards + 3);
4698 			}
4699 			else
4700 			    rest_of_wildcards += 3;
4701 
4702 			if (stackp->ffs_star_star_empty == 0)
4703 			{
4704 			    /* if not done before, expand '**' to empty */
4705 			    stackp->ffs_star_star_empty = 1;
4706 			    dirptrs[1] = stackp->ffs_fix_path;
4707 			}
4708 		    }
4709 
4710 		    /*
4711 		     * Here we copy until the next path separator or the end of
4712 		     * the path. If we stop at a path separator, there is
4713 		     * still something else left. This is handled below by
4714 		     * pushing every directory returned from expand_wildcards()
4715 		     * on the stack again for further search.
4716 		     */
4717 		    while (*rest_of_wildcards
4718 			    && !vim_ispathsep(*rest_of_wildcards))
4719 			file_path[len++] = *rest_of_wildcards++;
4720 
4721 		    file_path[len] = NUL;
4722 		    if (vim_ispathsep(*rest_of_wildcards))
4723 			rest_of_wildcards++;
4724 		}
4725 #endif
4726 
4727 		/*
4728 		 * Expand wildcards like "*" and "$VAR".
4729 		 * If the path is a URL don't try this.
4730 		 */
4731 		if (path_with_url(dirptrs[0]))
4732 		{
4733 		    stackp->ffs_filearray = (char_u **)
4734 					      alloc((unsigned)sizeof(char *));
4735 		    if (stackp->ffs_filearray != NULL
4736 			    && (stackp->ffs_filearray[0]
4737 				= vim_strsave(dirptrs[0])) != NULL)
4738 			stackp->ffs_filearray_size = 1;
4739 		    else
4740 			stackp->ffs_filearray_size = 0;
4741 		}
4742 		else
4743 		    /* Add EW_NOTWILD because the expanded path may contain
4744 		     * wildcard characters that are to be taken literally.
4745 		     * This is a bit of a hack. */
4746 		    expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
4747 			    &stackp->ffs_filearray_size,
4748 			    &stackp->ffs_filearray,
4749 			    EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD);
4750 
4751 		stackp->ffs_filearray_cur = 0;
4752 		stackp->ffs_stage = 0;
4753 	    }
4754 #ifdef FEAT_PATH_EXTRA
4755 	    else
4756 		rest_of_wildcards = &stackp->ffs_wc_path[
4757 						 STRLEN(stackp->ffs_wc_path)];
4758 #endif
4759 
4760 	    if (stackp->ffs_stage == 0)
4761 	    {
4762 		/* this is the first time we work on this directory */
4763 #ifdef FEAT_PATH_EXTRA
4764 		if (*rest_of_wildcards == NUL)
4765 #endif
4766 		{
4767 		    /*
4768 		     * We don't have further wildcards to expand, so we have to
4769 		     * check for the final file now.
4770 		     */
4771 		    for (i = stackp->ffs_filearray_cur;
4772 					  i < stackp->ffs_filearray_size; ++i)
4773 		    {
4774 			if (!path_with_url(stackp->ffs_filearray[i])
4775 				      && !mch_isdir(stackp->ffs_filearray[i]))
4776 			    continue;   /* not a directory */
4777 
4778 			/* prepare the filename to be checked for existence
4779 			 * below */
4780 			STRCPY(file_path, stackp->ffs_filearray[i]);
4781 			add_pathsep(file_path);
4782 			STRCAT(file_path, search_ctx->ffsc_file_to_search);
4783 
4784 			/*
4785 			 * Try without extra suffix and then with suffixes
4786 			 * from 'suffixesadd'.
4787 			 */
4788 #ifdef FEAT_SEARCHPATH
4789 			len = (int)STRLEN(file_path);
4790 			if (search_ctx->ffsc_tagfile)
4791 			    suf = (char_u *)"";
4792 			else
4793 			    suf = curbuf->b_p_sua;
4794 			for (;;)
4795 #endif
4796 			{
4797 			    /* if file exists and we didn't already find it */
4798 			    if ((path_with_url(file_path)
4799 				  || (mch_getperm(file_path) >= 0
4800 				      && (search_ctx->ffsc_find_what
4801 							      == FINDFILE_BOTH
4802 					  || ((search_ctx->ffsc_find_what
4803 							      == FINDFILE_DIR)
4804 						   == mch_isdir(file_path)))))
4805 #ifndef FF_VERBOSE
4806 				    && (ff_check_visited(
4807 					    &search_ctx->ffsc_visited_list->ffvl_visited_list,
4808 					    file_path
4809 #ifdef FEAT_PATH_EXTRA
4810 					    , (char_u *)""
4811 #endif
4812 					    ) == OK)
4813 #endif
4814 			       )
4815 			    {
4816 #ifdef FF_VERBOSE
4817 				if (ff_check_visited(
4818 					    &search_ctx->ffsc_visited_list->ffvl_visited_list,
4819 					    file_path
4820 #ifdef FEAT_PATH_EXTRA
4821 					    , (char_u *)""
4822 #endif
4823 						    ) == FAIL)
4824 				{
4825 				    if (p_verbose >= 5)
4826 				    {
4827 					verbose_enter_scroll();
4828 					smsg((char_u *)"Already: %s",
4829 								   file_path);
4830 					/* don't overwrite this either */
4831 					msg_puts((char_u *)"\n");
4832 					verbose_leave_scroll();
4833 				    }
4834 				    continue;
4835 				}
4836 #endif
4837 
4838 				/* push dir to examine rest of subdirs later */
4839 				stackp->ffs_filearray_cur = i + 1;
4840 				ff_push(search_ctx, stackp);
4841 
4842 				if (!path_with_url(file_path))
4843 				    simplify_filename(file_path);
4844 				if (mch_dirname(ff_expand_buffer, MAXPATHL)
4845 									== OK)
4846 				{
4847 				    p = shorten_fname(file_path,
4848 							    ff_expand_buffer);
4849 				    if (p != NULL)
4850 					STRMOVE(file_path, p);
4851 				}
4852 #ifdef FF_VERBOSE
4853 				if (p_verbose >= 5)
4854 				{
4855 				    verbose_enter_scroll();
4856 				    smsg((char_u *)"HIT: %s", file_path);
4857 				    /* don't overwrite this either */
4858 				    msg_puts((char_u *)"\n");
4859 				    verbose_leave_scroll();
4860 				}
4861 #endif
4862 				return file_path;
4863 			    }
4864 
4865 #ifdef FEAT_SEARCHPATH
4866 			    /* Not found or found already, try next suffix. */
4867 			    if (*suf == NUL)
4868 				break;
4869 			    copy_option_part(&suf, file_path + len,
4870 							 MAXPATHL - len, ",");
4871 #endif
4872 			}
4873 		    }
4874 		}
4875 #ifdef FEAT_PATH_EXTRA
4876 		else
4877 		{
4878 		    /*
4879 		     * still wildcards left, push the directories for further
4880 		     * search
4881 		     */
4882 		    for (i = stackp->ffs_filearray_cur;
4883 					  i < stackp->ffs_filearray_size; ++i)
4884 		    {
4885 			if (!mch_isdir(stackp->ffs_filearray[i]))
4886 			    continue;	/* not a directory */
4887 
4888 			ff_push(search_ctx,
4889 				ff_create_stack_element(
4890 						     stackp->ffs_filearray[i],
4891 						     rest_of_wildcards,
4892 						     stackp->ffs_level - 1, 0));
4893 		    }
4894 		}
4895 #endif
4896 		stackp->ffs_filearray_cur = 0;
4897 		stackp->ffs_stage = 1;
4898 	    }
4899 
4900 #ifdef FEAT_PATH_EXTRA
4901 	    /*
4902 	     * if wildcards contains '**' we have to descent till we reach the
4903 	     * leaves of the directory tree.
4904 	     */
4905 	    if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0)
4906 	    {
4907 		for (i = stackp->ffs_filearray_cur;
4908 					  i < stackp->ffs_filearray_size; ++i)
4909 		{
4910 		    if (fnamecmp(stackp->ffs_filearray[i],
4911 						   stackp->ffs_fix_path) == 0)
4912 			continue; /* don't repush same directory */
4913 		    if (!mch_isdir(stackp->ffs_filearray[i]))
4914 			continue;   /* not a directory */
4915 		    ff_push(search_ctx,
4916 			    ff_create_stack_element(stackp->ffs_filearray[i],
4917 				stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
4918 		}
4919 	    }
4920 #endif
4921 
4922 	    /* we are done with the current directory */
4923 	    ff_free_stack_element(stackp);
4924 
4925 	}
4926 
4927 #ifdef FEAT_PATH_EXTRA
4928 	/* If we reached this, we didn't find anything downwards.
4929 	 * Let's check if we should do an upward search.
4930 	 */
4931 	if (search_ctx->ffsc_start_dir
4932 		&& search_ctx->ffsc_stopdirs_v != NULL && !got_int)
4933 	{
4934 	    ff_stack_T  *sptr;
4935 
4936 	    /* is the last starting directory in the stop list? */
4937 	    if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
4938 		       (int)(path_end - search_ctx->ffsc_start_dir),
4939 		       search_ctx->ffsc_stopdirs_v) == TRUE)
4940 		break;
4941 
4942 	    /* cut of last dir */
4943 	    while (path_end > search_ctx->ffsc_start_dir
4944 						  && vim_ispathsep(*path_end))
4945 		path_end--;
4946 	    while (path_end > search_ctx->ffsc_start_dir
4947 					      && !vim_ispathsep(path_end[-1]))
4948 		path_end--;
4949 	    *path_end = 0;
4950 	    path_end--;
4951 
4952 	    if (*search_ctx->ffsc_start_dir == 0)
4953 		break;
4954 
4955 	    STRCPY(file_path, search_ctx->ffsc_start_dir);
4956 	    add_pathsep(file_path);
4957 	    STRCAT(file_path, search_ctx->ffsc_fix_path);
4958 
4959 	    /* create a new stack entry */
4960 	    sptr = ff_create_stack_element(file_path,
4961 		    search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
4962 	    if (sptr == NULL)
4963 		break;
4964 	    ff_push(search_ctx, sptr);
4965 	}
4966 	else
4967 	    break;
4968     }
4969 #endif
4970 
4971     vim_free(file_path);
4972     return NULL;
4973 }
4974 
4975 /*
4976  * Free the list of lists of visited files and directories
4977  * Can handle it if the passed search_context is NULL;
4978  */
4979     void
4980 vim_findfile_free_visited(search_ctx_arg)
4981     void	*search_ctx_arg;
4982 {
4983     ff_search_ctx_T *search_ctx;
4984 
4985     if (search_ctx_arg == NULL)
4986 	return;
4987 
4988     search_ctx = (ff_search_ctx_T *)search_ctx_arg;
4989     vim_findfile_free_visited_list(&search_ctx->ffsc_visited_lists_list);
4990     vim_findfile_free_visited_list(&search_ctx->ffsc_dir_visited_lists_list);
4991 }
4992 
4993     static void
4994 vim_findfile_free_visited_list(list_headp)
4995     ff_visited_list_hdr_T	**list_headp;
4996 {
4997     ff_visited_list_hdr_T *vp;
4998 
4999     while (*list_headp != NULL)
5000     {
5001 	vp = (*list_headp)->ffvl_next;
5002 	ff_free_visited_list((*list_headp)->ffvl_visited_list);
5003 
5004 	vim_free((*list_headp)->ffvl_filename);
5005 	vim_free(*list_headp);
5006 	*list_headp = vp;
5007     }
5008     *list_headp = NULL;
5009 }
5010 
5011     static void
5012 ff_free_visited_list(vl)
5013     ff_visited_T *vl;
5014 {
5015     ff_visited_T *vp;
5016 
5017     while (vl != NULL)
5018     {
5019 	vp = vl->ffv_next;
5020 #ifdef FEAT_PATH_EXTRA
5021 	vim_free(vl->ffv_wc_path);
5022 #endif
5023 	vim_free(vl);
5024 	vl = vp;
5025     }
5026     vl = NULL;
5027 }
5028 
5029 /*
5030  * Returns the already visited list for the given filename. If none is found it
5031  * allocates a new one.
5032  */
5033     static ff_visited_list_hdr_T*
5034 ff_get_visited_list(filename, list_headp)
5035     char_u			*filename;
5036     ff_visited_list_hdr_T	**list_headp;
5037 {
5038     ff_visited_list_hdr_T  *retptr = NULL;
5039 
5040     /* check if a visited list for the given filename exists */
5041     if (*list_headp != NULL)
5042     {
5043 	retptr = *list_headp;
5044 	while (retptr != NULL)
5045 	{
5046 	    if (fnamecmp(filename, retptr->ffvl_filename) == 0)
5047 	    {
5048 #ifdef FF_VERBOSE
5049 		if (p_verbose >= 5)
5050 		{
5051 		    verbose_enter_scroll();
5052 		    smsg((char_u *)"ff_get_visited_list: FOUND list for %s",
5053 								    filename);
5054 		    /* don't overwrite this either */
5055 		    msg_puts((char_u *)"\n");
5056 		    verbose_leave_scroll();
5057 		}
5058 #endif
5059 		return retptr;
5060 	    }
5061 	    retptr = retptr->ffvl_next;
5062 	}
5063     }
5064 
5065 #ifdef FF_VERBOSE
5066     if (p_verbose >= 5)
5067     {
5068 	verbose_enter_scroll();
5069 	smsg((char_u *)"ff_get_visited_list: new list for %s", filename);
5070 	/* don't overwrite this either */
5071 	msg_puts((char_u *)"\n");
5072 	verbose_leave_scroll();
5073     }
5074 #endif
5075 
5076     /*
5077      * if we reach this we didn't find a list and we have to allocate new list
5078      */
5079     retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr));
5080     if (retptr == NULL)
5081 	return NULL;
5082 
5083     retptr->ffvl_visited_list = NULL;
5084     retptr->ffvl_filename = vim_strsave(filename);
5085     if (retptr->ffvl_filename == NULL)
5086     {
5087 	vim_free(retptr);
5088 	return NULL;
5089     }
5090     retptr->ffvl_next = *list_headp;
5091     *list_headp = retptr;
5092 
5093     return retptr;
5094 }
5095 
5096 #ifdef FEAT_PATH_EXTRA
5097 /*
5098  * check if two wildcard paths are equal. Returns TRUE or FALSE.
5099  * They are equal if:
5100  *  - both paths are NULL
5101  *  - they have the same length
5102  *  - char by char comparison is OK
5103  *  - the only differences are in the counters behind a '**', so
5104  *    '**\20' is equal to '**\24'
5105  */
5106     static int
5107 ff_wc_equal(s1, s2)
5108     char_u	*s1;
5109     char_u	*s2;
5110 {
5111     int		i, j;
5112     int		c1 = NUL;
5113     int		c2 = NUL;
5114     int		prev1 = NUL;
5115     int		prev2 = NUL;
5116 
5117     if (s1 == s2)
5118 	return TRUE;
5119 
5120     if (s1 == NULL || s2 == NULL)
5121 	return FALSE;
5122 
5123     for (i = 0, j = 0; s1[i] != NUL && s2[j] != NUL;)
5124     {
5125 	c1 = PTR2CHAR(s1 + i);
5126 	c2 = PTR2CHAR(s2 + j);
5127 
5128 	if ((p_fic ? MB_TOLOWER(c1) != MB_TOLOWER(c2) : c1 != c2)
5129 		&& (prev1 != '*' || prev2 != '*'))
5130 	    return FALSE;
5131 	prev2 = prev1;
5132 	prev1 = c1;
5133 
5134         i += MB_PTR2LEN(s1 + i);
5135         j += MB_PTR2LEN(s2 + j);
5136     }
5137     return s1[i] == s2[j];
5138 }
5139 #endif
5140 
5141 /*
5142  * maintains the list of already visited files and dirs
5143  * returns FAIL if the given file/dir is already in the list
5144  * returns OK if it is newly added
5145  *
5146  * TODO: What to do on memory allocation problems?
5147  *	 -> return TRUE - Better the file is found several times instead of
5148  *	    never.
5149  */
5150     static int
5151 ff_check_visited(visited_list, fname
5152 #ifdef FEAT_PATH_EXTRA
5153 	, wc_path
5154 #endif
5155 	)
5156     ff_visited_T	**visited_list;
5157     char_u		*fname;
5158 #ifdef FEAT_PATH_EXTRA
5159     char_u		*wc_path;
5160 #endif
5161 {
5162     ff_visited_T	*vp;
5163 #ifdef UNIX
5164     struct stat		st;
5165     int			url = FALSE;
5166 #endif
5167 
5168     /* For an URL we only compare the name, otherwise we compare the
5169      * device/inode (unix) or the full path name (not Unix). */
5170     if (path_with_url(fname))
5171     {
5172 	vim_strncpy(ff_expand_buffer, fname, MAXPATHL - 1);
5173 #ifdef UNIX
5174 	url = TRUE;
5175 #endif
5176     }
5177     else
5178     {
5179 	ff_expand_buffer[0] = NUL;
5180 #ifdef UNIX
5181 	if (mch_stat((char *)fname, &st) < 0)
5182 #else
5183 	if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
5184 #endif
5185 	    return FAIL;
5186     }
5187 
5188     /* check against list of already visited files */
5189     for (vp = *visited_list; vp != NULL; vp = vp->ffv_next)
5190     {
5191 	if (
5192 #ifdef UNIX
5193 		!url ? (vp->ffv_dev_valid && vp->ffv_dev == st.st_dev
5194 						  && vp->ffv_ino == st.st_ino)
5195 		     :
5196 #endif
5197 		fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0
5198 	   )
5199 	{
5200 #ifdef FEAT_PATH_EXTRA
5201 	    /* are the wildcard parts equal */
5202 	    if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
5203 #endif
5204 		/* already visited */
5205 		return FAIL;
5206 	}
5207     }
5208 
5209     /*
5210      * New file/dir.  Add it to the list of visited files/dirs.
5211      */
5212     vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T)
5213 						 + STRLEN(ff_expand_buffer)));
5214 
5215     if (vp != NULL)
5216     {
5217 #ifdef UNIX
5218 	if (!url)
5219 	{
5220 	    vp->ffv_dev_valid = TRUE;
5221 	    vp->ffv_ino = st.st_ino;
5222 	    vp->ffv_dev = st.st_dev;
5223 	    vp->ffv_fname[0] = NUL;
5224 	}
5225 	else
5226 	{
5227 	    vp->ffv_dev_valid = FALSE;
5228 #endif
5229 	    STRCPY(vp->ffv_fname, ff_expand_buffer);
5230 #ifdef UNIX
5231 	}
5232 #endif
5233 #ifdef FEAT_PATH_EXTRA
5234 	if (wc_path != NULL)
5235 	    vp->ffv_wc_path = vim_strsave(wc_path);
5236 	else
5237 	    vp->ffv_wc_path = NULL;
5238 #endif
5239 
5240 	vp->ffv_next = *visited_list;
5241 	*visited_list = vp;
5242     }
5243 
5244     return OK;
5245 }
5246 
5247 /*
5248  * create stack element from given path pieces
5249  */
5250     static ff_stack_T *
5251 ff_create_stack_element(fix_part,
5252 #ifdef FEAT_PATH_EXTRA
5253 	wc_part,
5254 #endif
5255 	level, star_star_empty)
5256     char_u	*fix_part;
5257 #ifdef FEAT_PATH_EXTRA
5258     char_u	*wc_part;
5259 #endif
5260     int		level;
5261     int		star_star_empty;
5262 {
5263     ff_stack_T	*new;
5264 
5265     new = (ff_stack_T *)alloc((unsigned)sizeof(ff_stack_T));
5266     if (new == NULL)
5267 	return NULL;
5268 
5269     new->ffs_prev	   = NULL;
5270     new->ffs_filearray	   = NULL;
5271     new->ffs_filearray_size = 0;
5272     new->ffs_filearray_cur  = 0;
5273     new->ffs_stage	   = 0;
5274     new->ffs_level	   = level;
5275     new->ffs_star_star_empty = star_star_empty;;
5276 
5277     /* the following saves NULL pointer checks in vim_findfile */
5278     if (fix_part == NULL)
5279 	fix_part = (char_u *)"";
5280     new->ffs_fix_path = vim_strsave(fix_part);
5281 
5282 #ifdef FEAT_PATH_EXTRA
5283     if (wc_part == NULL)
5284 	wc_part  = (char_u *)"";
5285     new->ffs_wc_path = vim_strsave(wc_part);
5286 #endif
5287 
5288     if (new->ffs_fix_path == NULL
5289 #ifdef FEAT_PATH_EXTRA
5290 	    || new->ffs_wc_path == NULL
5291 #endif
5292 	    )
5293     {
5294 	ff_free_stack_element(new);
5295 	new = NULL;
5296     }
5297 
5298     return new;
5299 }
5300 
5301 /*
5302  * Push a dir on the directory stack.
5303  */
5304     static void
5305 ff_push(search_ctx, stack_ptr)
5306     ff_search_ctx_T *search_ctx;
5307     ff_stack_T	    *stack_ptr;
5308 {
5309     /* check for NULL pointer, not to return an error to the user, but
5310      * to prevent a crash */
5311     if (stack_ptr != NULL)
5312     {
5313 	stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr;
5314 	search_ctx->ffsc_stack_ptr = stack_ptr;
5315     }
5316 }
5317 
5318 /*
5319  * Pop a dir from the directory stack.
5320  * Returns NULL if stack is empty.
5321  */
5322     static ff_stack_T *
5323 ff_pop(search_ctx)
5324     ff_search_ctx_T *search_ctx;
5325 {
5326     ff_stack_T  *sptr;
5327 
5328     sptr = search_ctx->ffsc_stack_ptr;
5329     if (search_ctx->ffsc_stack_ptr != NULL)
5330 	search_ctx->ffsc_stack_ptr = search_ctx->ffsc_stack_ptr->ffs_prev;
5331 
5332     return sptr;
5333 }
5334 
5335 /*
5336  * free the given stack element
5337  */
5338     static void
5339 ff_free_stack_element(stack_ptr)
5340     ff_stack_T  *stack_ptr;
5341 {
5342     /* vim_free handles possible NULL pointers */
5343     vim_free(stack_ptr->ffs_fix_path);
5344 #ifdef FEAT_PATH_EXTRA
5345     vim_free(stack_ptr->ffs_wc_path);
5346 #endif
5347 
5348     if (stack_ptr->ffs_filearray != NULL)
5349 	FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray);
5350 
5351     vim_free(stack_ptr);
5352 }
5353 
5354 /*
5355  * Clear the search context, but NOT the visited list.
5356  */
5357     static void
5358 ff_clear(search_ctx)
5359     ff_search_ctx_T *search_ctx;
5360 {
5361     ff_stack_T   *sptr;
5362 
5363     /* clear up stack */
5364     while ((sptr = ff_pop(search_ctx)) != NULL)
5365 	ff_free_stack_element(sptr);
5366 
5367     vim_free(search_ctx->ffsc_file_to_search);
5368     vim_free(search_ctx->ffsc_start_dir);
5369     vim_free(search_ctx->ffsc_fix_path);
5370 #ifdef FEAT_PATH_EXTRA
5371     vim_free(search_ctx->ffsc_wc_path);
5372 #endif
5373 
5374 #ifdef FEAT_PATH_EXTRA
5375     if (search_ctx->ffsc_stopdirs_v != NULL)
5376     {
5377 	int  i = 0;
5378 
5379 	while (search_ctx->ffsc_stopdirs_v[i] != NULL)
5380 	{
5381 	    vim_free(search_ctx->ffsc_stopdirs_v[i]);
5382 	    i++;
5383 	}
5384 	vim_free(search_ctx->ffsc_stopdirs_v);
5385     }
5386     search_ctx->ffsc_stopdirs_v = NULL;
5387 #endif
5388 
5389     /* reset everything */
5390     search_ctx->ffsc_file_to_search = NULL;
5391     search_ctx->ffsc_start_dir = NULL;
5392     search_ctx->ffsc_fix_path = NULL;
5393 #ifdef FEAT_PATH_EXTRA
5394     search_ctx->ffsc_wc_path = NULL;
5395     search_ctx->ffsc_level = 0;
5396 #endif
5397 }
5398 
5399 #ifdef FEAT_PATH_EXTRA
5400 /*
5401  * check if the given path is in the stopdirs
5402  * returns TRUE if yes else FALSE
5403  */
5404     static int
5405 ff_path_in_stoplist(path, path_len, stopdirs_v)
5406     char_u	*path;
5407     int		path_len;
5408     char_u	**stopdirs_v;
5409 {
5410     int		i = 0;
5411 
5412     /* eat up trailing path separators, except the first */
5413     while (path_len > 1 && vim_ispathsep(path[path_len - 1]))
5414 	path_len--;
5415 
5416     /* if no path consider it as match */
5417     if (path_len == 0)
5418 	return TRUE;
5419 
5420     for (i = 0; stopdirs_v[i] != NULL; i++)
5421     {
5422 	if ((int)STRLEN(stopdirs_v[i]) > path_len)
5423 	{
5424 	    /* match for parent directory. So '/home' also matches
5425 	     * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
5426 	     * '/home/r' would also match '/home/rks'
5427 	     */
5428 	    if (fnamencmp(stopdirs_v[i], path, path_len) == 0
5429 		    && vim_ispathsep(stopdirs_v[i][path_len]))
5430 		return TRUE;
5431 	}
5432 	else
5433 	{
5434 	    if (fnamecmp(stopdirs_v[i], path) == 0)
5435 		return TRUE;
5436 	}
5437     }
5438     return FALSE;
5439 }
5440 #endif
5441 
5442 #if defined(FEAT_SEARCHPATH) || defined(PROTO)
5443 /*
5444  * Find the file name "ptr[len]" in the path.  Also finds directory names.
5445  *
5446  * On the first call set the parameter 'first' to TRUE to initialize
5447  * the search.  For repeating calls to FALSE.
5448  *
5449  * Repeating calls will return other files called 'ptr[len]' from the path.
5450  *
5451  * Only on the first call 'ptr' and 'len' are used.  For repeating calls they
5452  * don't need valid values.
5453  *
5454  * If nothing found on the first call the option FNAME_MESS will issue the
5455  * message:
5456  *	    'Can't find file "<file>" in path'
5457  * On repeating calls:
5458  *	    'No more file "<file>" found in path'
5459  *
5460  * options:
5461  * FNAME_MESS	    give error message when not found
5462  *
5463  * Uses NameBuff[]!
5464  *
5465  * Returns an allocated string for the file name.  NULL for error.
5466  *
5467  */
5468     char_u *
5469 find_file_in_path(ptr, len, options, first, rel_fname)
5470     char_u	*ptr;		/* file name */
5471     int		len;		/* length of file name */
5472     int		options;
5473     int		first;		/* use count'th matching file name */
5474     char_u	*rel_fname;	/* file name searching relative to */
5475 {
5476     return find_file_in_path_option(ptr, len, options, first,
5477 	    *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
5478 	    FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
5479 }
5480 
5481 static char_u	*ff_file_to_find = NULL;
5482 static void	*fdip_search_ctx = NULL;
5483 
5484 #if defined(EXITFREE)
5485     static void
5486 free_findfile()
5487 {
5488     vim_free(ff_file_to_find);
5489     vim_findfile_cleanup(fdip_search_ctx);
5490 }
5491 #endif
5492 
5493 /*
5494  * Find the directory name "ptr[len]" in the path.
5495  *
5496  * options:
5497  * FNAME_MESS	    give error message when not found
5498  * FNAME_UNESC	    unescape backslashes.
5499  *
5500  * Uses NameBuff[]!
5501  *
5502  * Returns an allocated string for the file name.  NULL for error.
5503  */
5504     char_u *
5505 find_directory_in_path(ptr, len, options, rel_fname)
5506     char_u	*ptr;		/* file name */
5507     int		len;		/* length of file name */
5508     int		options;
5509     char_u	*rel_fname;	/* file name searching relative to */
5510 {
5511     return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
5512 				       FINDFILE_DIR, rel_fname, (char_u *)"");
5513 }
5514 
5515     char_u *
5516 find_file_in_path_option(ptr, len, options, first, path_option,
5517 			 find_what, rel_fname, suffixes)
5518     char_u	*ptr;		/* file name */
5519     int		len;		/* length of file name */
5520     int		options;
5521     int		first;		/* use count'th matching file name */
5522     char_u	*path_option;	/* p_path or p_cdpath */
5523     int		find_what;	/* FINDFILE_FILE, _DIR or _BOTH */
5524     char_u	*rel_fname;	/* file name we are looking relative to. */
5525     char_u	*suffixes;	/* list of suffixes, 'suffixesadd' option */
5526 {
5527     static char_u	*dir;
5528     static int		did_findfile_init = FALSE;
5529     char_u		save_char;
5530     char_u		*file_name = NULL;
5531     char_u		*buf = NULL;
5532     int			rel_to_curdir;
5533 #ifdef AMIGA
5534     struct Process	*proc = (struct Process *)FindTask(0L);
5535     APTR		save_winptr = proc->pr_WindowPtr;
5536 
5537     /* Avoid a requester here for a volume that doesn't exist. */
5538     proc->pr_WindowPtr = (APTR)-1L;
5539 #endif
5540 
5541     if (first == TRUE)
5542     {
5543 	/* copy file name into NameBuff, expanding environment variables */
5544 	save_char = ptr[len];
5545 	ptr[len] = NUL;
5546 	expand_env(ptr, NameBuff, MAXPATHL);
5547 	ptr[len] = save_char;
5548 
5549 	vim_free(ff_file_to_find);
5550 	ff_file_to_find = vim_strsave(NameBuff);
5551 	if (ff_file_to_find == NULL)	/* out of memory */
5552 	{
5553 	    file_name = NULL;
5554 	    goto theend;
5555 	}
5556 	if (options & FNAME_UNESC)
5557 	{
5558 	    /* Change all "\ " to " ". */
5559 	    for (ptr = ff_file_to_find; *ptr != NUL; ++ptr)
5560 		if (ptr[0] == '\\' && ptr[1] == ' ')
5561 		    mch_memmove(ptr, ptr + 1, STRLEN(ptr));
5562 	}
5563     }
5564 
5565     rel_to_curdir = (ff_file_to_find[0] == '.'
5566 		    && (ff_file_to_find[1] == NUL
5567 			|| vim_ispathsep(ff_file_to_find[1])
5568 			|| (ff_file_to_find[1] == '.'
5569 			    && (ff_file_to_find[2] == NUL
5570 				|| vim_ispathsep(ff_file_to_find[2])))));
5571     if (vim_isAbsName(ff_file_to_find)
5572 	    /* "..", "../path", "." and "./path": don't use the path_option */
5573 	    || rel_to_curdir
5574 #if defined(MSWIN) || defined(MSDOS)
5575 	    /* handle "\tmp" as absolute path */
5576 	    || vim_ispathsep(ff_file_to_find[0])
5577 	    /* handle "c:name" as absolute path */
5578 	    || (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
5579 #endif
5580 #ifdef AMIGA
5581 	    /* handle ":tmp" as absolute path */
5582 	    || ff_file_to_find[0] == ':'
5583 #endif
5584        )
5585     {
5586 	/*
5587 	 * Absolute path, no need to use "path_option".
5588 	 * If this is not a first call, return NULL.  We already returned a
5589 	 * filename on the first call.
5590 	 */
5591 	if (first == TRUE)
5592 	{
5593 	    int		l;
5594 	    int		run;
5595 
5596 	    if (path_with_url(ff_file_to_find))
5597 	    {
5598 		file_name = vim_strsave(ff_file_to_find);
5599 		goto theend;
5600 	    }
5601 
5602 	    /* When FNAME_REL flag given first use the directory of the file.
5603 	     * Otherwise or when this fails use the current directory. */
5604 	    for (run = 1; run <= 2; ++run)
5605 	    {
5606 		l = (int)STRLEN(ff_file_to_find);
5607 		if (run == 1
5608 			&& rel_to_curdir
5609 			&& (options & FNAME_REL)
5610 			&& rel_fname != NULL
5611 			&& STRLEN(rel_fname) + l < MAXPATHL)
5612 		{
5613 		    STRCPY(NameBuff, rel_fname);
5614 		    STRCPY(gettail(NameBuff), ff_file_to_find);
5615 		    l = (int)STRLEN(NameBuff);
5616 		}
5617 		else
5618 		{
5619 		    STRCPY(NameBuff, ff_file_to_find);
5620 		    run = 2;
5621 		}
5622 
5623 		/* When the file doesn't exist, try adding parts of
5624 		 * 'suffixesadd'. */
5625 		buf = suffixes;
5626 		for (;;)
5627 		{
5628 		    if (
5629 #ifdef DJGPP
5630 			    /* "C:" by itself will fail for mch_getperm(),
5631 			     * assume it's always valid. */
5632 			    (find_what != FINDFILE_FILE && NameBuff[0] != NUL
5633 				  && NameBuff[1] == ':'
5634 				  && NameBuff[2] == NUL) ||
5635 #endif
5636 			    (mch_getperm(NameBuff) >= 0
5637 			     && (find_what == FINDFILE_BOTH
5638 				 || ((find_what == FINDFILE_DIR)
5639 						    == mch_isdir(NameBuff)))))
5640 		    {
5641 			file_name = vim_strsave(NameBuff);
5642 			goto theend;
5643 		    }
5644 		    if (*buf == NUL)
5645 			break;
5646 		    copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
5647 		}
5648 	    }
5649 	}
5650     }
5651     else
5652     {
5653 	/*
5654 	 * Loop over all paths in the 'path' or 'cdpath' option.
5655 	 * When "first" is set, first setup to the start of the option.
5656 	 * Otherwise continue to find the next match.
5657 	 */
5658 	if (first == TRUE)
5659 	{
5660 	    /* vim_findfile_free_visited can handle a possible NULL pointer */
5661 	    vim_findfile_free_visited(fdip_search_ctx);
5662 	    dir = path_option;
5663 	    did_findfile_init = FALSE;
5664 	}
5665 
5666 	for (;;)
5667 	{
5668 	    if (did_findfile_init)
5669 	    {
5670 		file_name = vim_findfile(fdip_search_ctx);
5671 		if (file_name != NULL)
5672 		    break;
5673 
5674 		did_findfile_init = FALSE;
5675 	    }
5676 	    else
5677 	    {
5678 		char_u  *r_ptr;
5679 
5680 		if (dir == NULL || *dir == NUL)
5681 		{
5682 		    /* We searched all paths of the option, now we can
5683 		     * free the search context. */
5684 		    vim_findfile_cleanup(fdip_search_ctx);
5685 		    fdip_search_ctx = NULL;
5686 		    break;
5687 		}
5688 
5689 		if ((buf = alloc((int)(MAXPATHL))) == NULL)
5690 		    break;
5691 
5692 		/* copy next path */
5693 		buf[0] = 0;
5694 		copy_option_part(&dir, buf, MAXPATHL, " ,");
5695 
5696 #ifdef FEAT_PATH_EXTRA
5697 		/* get the stopdir string */
5698 		r_ptr = vim_findfile_stopdir(buf);
5699 #else
5700 		r_ptr = NULL;
5701 #endif
5702 		fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
5703 					    r_ptr, 100, FALSE, find_what,
5704 					   fdip_search_ctx, FALSE, rel_fname);
5705 		if (fdip_search_ctx != NULL)
5706 		    did_findfile_init = TRUE;
5707 		vim_free(buf);
5708 	    }
5709 	}
5710     }
5711     if (file_name == NULL && (options & FNAME_MESS))
5712     {
5713 	if (first == TRUE)
5714 	{
5715 	    if (find_what == FINDFILE_DIR)
5716 		EMSG2(_("E344: Can't find directory \"%s\" in cdpath"),
5717 			ff_file_to_find);
5718 	    else
5719 		EMSG2(_("E345: Can't find file \"%s\" in path"),
5720 			ff_file_to_find);
5721 	}
5722 	else
5723 	{
5724 	    if (find_what == FINDFILE_DIR)
5725 		EMSG2(_("E346: No more directory \"%s\" found in cdpath"),
5726 			ff_file_to_find);
5727 	    else
5728 		EMSG2(_("E347: No more file \"%s\" found in path"),
5729 			ff_file_to_find);
5730 	}
5731     }
5732 
5733 theend:
5734 #ifdef AMIGA
5735     proc->pr_WindowPtr = save_winptr;
5736 #endif
5737     return file_name;
5738 }
5739 
5740 #endif /* FEAT_SEARCHPATH */
5741 
5742 /*
5743  * Change directory to "new_dir".  If FEAT_SEARCHPATH is defined, search
5744  * 'cdpath' for relative directory names, otherwise just mch_chdir().
5745  */
5746     int
5747 vim_chdir(new_dir)
5748     char_u	*new_dir;
5749 {
5750 #ifndef FEAT_SEARCHPATH
5751     return mch_chdir((char *)new_dir);
5752 #else
5753     char_u	*dir_name;
5754     int		r;
5755 
5756     dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
5757 						FNAME_MESS, curbuf->b_ffname);
5758     if (dir_name == NULL)
5759 	return -1;
5760     r = mch_chdir((char *)dir_name);
5761     vim_free(dir_name);
5762     return r;
5763 #endif
5764 }
5765 
5766 /*
5767  * Get user name from machine-specific function.
5768  * Returns the user name in "buf[len]".
5769  * Some systems are quite slow in obtaining the user name (Windows NT), thus
5770  * cache the result.
5771  * Returns OK or FAIL.
5772  */
5773     int
5774 get_user_name(buf, len)
5775     char_u	*buf;
5776     int		len;
5777 {
5778     if (username == NULL)
5779     {
5780 	if (mch_get_user_name(buf, len) == FAIL)
5781 	    return FAIL;
5782 	username = vim_strsave(buf);
5783     }
5784     else
5785 	vim_strncpy(buf, username, len - 1);
5786     return OK;
5787 }
5788 
5789 #ifndef HAVE_QSORT
5790 /*
5791  * Our own qsort(), for systems that don't have it.
5792  * It's simple and slow.  From the K&R C book.
5793  */
5794     void
5795 qsort(base, elm_count, elm_size, cmp)
5796     void	*base;
5797     size_t	elm_count;
5798     size_t	elm_size;
5799     int (*cmp) __ARGS((const void *, const void *));
5800 {
5801     char_u	*buf;
5802     char_u	*p1;
5803     char_u	*p2;
5804     int		i, j;
5805     int		gap;
5806 
5807     buf = alloc((unsigned)elm_size);
5808     if (buf == NULL)
5809 	return;
5810 
5811     for (gap = elm_count / 2; gap > 0; gap /= 2)
5812 	for (i = gap; i < elm_count; ++i)
5813 	    for (j = i - gap; j >= 0; j -= gap)
5814 	    {
5815 		/* Compare the elements. */
5816 		p1 = (char_u *)base + j * elm_size;
5817 		p2 = (char_u *)base + (j + gap) * elm_size;
5818 		if ((*cmp)((void *)p1, (void *)p2) <= 0)
5819 		    break;
5820 		/* Exchange the elements. */
5821 		mch_memmove(buf, p1, elm_size);
5822 		mch_memmove(p1, p2, elm_size);
5823 		mch_memmove(p2, buf, elm_size);
5824 	    }
5825 
5826     vim_free(buf);
5827 }
5828 #endif
5829 
5830 /*
5831  * Sort an array of strings.
5832  */
5833 static int
5834 #ifdef __BORLANDC__
5835 _RTLENTRYF
5836 #endif
5837 sort_compare __ARGS((const void *s1, const void *s2));
5838 
5839     static int
5840 #ifdef __BORLANDC__
5841 _RTLENTRYF
5842 #endif
5843 sort_compare(s1, s2)
5844     const void	*s1;
5845     const void	*s2;
5846 {
5847     return STRCMP(*(char **)s1, *(char **)s2);
5848 }
5849 
5850     void
5851 sort_strings(files, count)
5852     char_u	**files;
5853     int		count;
5854 {
5855     qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare);
5856 }
5857 
5858 #if !defined(NO_EXPANDPATH) || defined(PROTO)
5859 /*
5860  * Compare path "p[]" to "q[]".
5861  * If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
5862  * Return value like strcmp(p, q), but consider path separators.
5863  */
5864     int
5865 pathcmp(p, q, maxlen)
5866     const char *p, *q;
5867     int maxlen;
5868 {
5869     int		i, j;
5870     int		c1, c2;
5871     const char	*s = NULL;
5872 
5873     for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);)
5874     {
5875 	c1 = PTR2CHAR((char_u *)p + i);
5876 	c2 = PTR2CHAR((char_u *)q + j);
5877 
5878 	/* End of "p": check if "q" also ends or just has a slash. */
5879 	if (c1 == NUL)
5880 	{
5881 	    if (c2 == NUL)  /* full match */
5882 		return 0;
5883 	    s = q;
5884             i = j;
5885 	    break;
5886 	}
5887 
5888 	/* End of "q": check if "p" just has a slash. */
5889 	if (c2 == NUL)
5890 	{
5891 	    s = p;
5892 	    break;
5893 	}
5894 
5895 	if ((p_fic ? MB_TOUPPER(c1) != MB_TOUPPER(c2) : c1 != c2)
5896 #ifdef BACKSLASH_IN_FILENAME
5897 		/* consider '/' and '\\' to be equal */
5898 		&& !((c1 == '/' && c2 == '\\')
5899 		    || (c1 == '\\' && c2 == '/'))
5900 #endif
5901 		)
5902 	{
5903 	    if (vim_ispathsep(c1))
5904 		return -1;
5905 	    if (vim_ispathsep(c2))
5906 		return 1;
5907 	    return p_fic ? MB_TOUPPER(c1) - MB_TOUPPER(c2)
5908 		    : c1 - c2;  /* no match */
5909 	}
5910 
5911 	i += MB_PTR2LEN((char_u *)p + i);
5912 	j += MB_PTR2LEN((char_u *)q + j);
5913     }
5914     if (s == NULL)	/* "i" or "j" ran into "maxlen" */
5915 	return 0;
5916 
5917     c1 = PTR2CHAR((char_u *)s + i);
5918     c2 = PTR2CHAR((char_u *)s + i + MB_PTR2LEN((char_u *)s + i));
5919     /* ignore a trailing slash, but not "//" or ":/" */
5920     if (c2 == NUL
5921 	    && i > 0
5922 	    && !after_pathsep((char_u *)s, (char_u *)s + i)
5923 #ifdef BACKSLASH_IN_FILENAME
5924 	    && (c1 == '/' || c1 == '\\')
5925 #else
5926 	    && c1 == '/'
5927 #endif
5928        )
5929 	return 0;   /* match with trailing slash */
5930     if (s == q)
5931 	return -1;	    /* no match */
5932     return 1;
5933 }
5934 #endif
5935 
5936 /*
5937  * The putenv() implementation below comes from the "screen" program.
5938  * Included with permission from Juergen Weigert.
5939  * See pty.c for the copyright notice.
5940  */
5941 
5942 /*
5943  *  putenv  --	put value into environment
5944  *
5945  *  Usage:  i = putenv (string)
5946  *    int i;
5947  *    char  *string;
5948  *
5949  *  where string is of the form <name>=<value>.
5950  *  Putenv returns 0 normally, -1 on error (not enough core for malloc).
5951  *
5952  *  Putenv may need to add a new name into the environment, or to
5953  *  associate a value longer than the current value with a particular
5954  *  name.  So, to make life simpler, putenv() copies your entire
5955  *  environment into the heap (i.e. malloc()) from the stack
5956  *  (i.e. where it resides when your process is initiated) the first
5957  *  time you call it.
5958  *
5959  *  (history removed, not very interesting.  See the "screen" sources.)
5960  */
5961 
5962 #if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
5963 
5964 #define EXTRASIZE 5		/* increment to add to env. size */
5965 
5966 static int  envsize = -1;	/* current size of environment */
5967 #ifndef MACOS_CLASSIC
5968 extern
5969 #endif
5970        char **environ;		/* the global which is your env. */
5971 
5972 static int  findenv __ARGS((char *name)); /* look for a name in the env. */
5973 static int  newenv __ARGS((void));	/* copy env. from stack to heap */
5974 static int  moreenv __ARGS((void));	/* incr. size of env. */
5975 
5976     int
5977 putenv(string)
5978     const char *string;
5979 {
5980     int	    i;
5981     char    *p;
5982 
5983     if (envsize < 0)
5984     {				/* first time putenv called */
5985 	if (newenv() < 0)	/* copy env. to heap */
5986 	    return -1;
5987     }
5988 
5989     i = findenv((char *)string); /* look for name in environment */
5990 
5991     if (i < 0)
5992     {				/* name must be added */
5993 	for (i = 0; environ[i]; i++);
5994 	if (i >= (envsize - 1))
5995 	{			/* need new slot */
5996 	    if (moreenv() < 0)
5997 		return -1;
5998 	}
5999 	p = (char *)alloc((unsigned)(strlen(string) + 1));
6000 	if (p == NULL)		/* not enough core */
6001 	    return -1;
6002 	environ[i + 1] = 0;	/* new end of env. */
6003     }
6004     else
6005     {				/* name already in env. */
6006 	p = vim_realloc(environ[i], strlen(string) + 1);
6007 	if (p == NULL)
6008 	    return -1;
6009     }
6010     sprintf(p, "%s", string);	/* copy into env. */
6011     environ[i] = p;
6012 
6013     return 0;
6014 }
6015 
6016     static int
6017 findenv(name)
6018     char *name;
6019 {
6020     char    *namechar, *envchar;
6021     int	    i, found;
6022 
6023     found = 0;
6024     for (i = 0; environ[i] && !found; i++)
6025     {
6026 	envchar = environ[i];
6027 	namechar = name;
6028 	while (*namechar && *namechar != '=' && (*namechar == *envchar))
6029 	{
6030 	    namechar++;
6031 	    envchar++;
6032 	}
6033 	found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
6034     }
6035     return found ? i - 1 : -1;
6036 }
6037 
6038     static int
6039 newenv()
6040 {
6041     char    **env, *elem;
6042     int	    i, esize;
6043 
6044 #ifdef MACOS
6045     /* for Mac a new, empty environment is created */
6046     i = 0;
6047 #else
6048     for (i = 0; environ[i]; i++)
6049 	;
6050 #endif
6051     esize = i + EXTRASIZE + 1;
6052     env = (char **)alloc((unsigned)(esize * sizeof (elem)));
6053     if (env == NULL)
6054 	return -1;
6055 
6056 #ifndef MACOS
6057     for (i = 0; environ[i]; i++)
6058     {
6059 	elem = (char *)alloc((unsigned)(strlen(environ[i]) + 1));
6060 	if (elem == NULL)
6061 	    return -1;
6062 	env[i] = elem;
6063 	strcpy(elem, environ[i]);
6064     }
6065 #endif
6066 
6067     env[i] = 0;
6068     environ = env;
6069     envsize = esize;
6070     return 0;
6071 }
6072 
6073     static int
6074 moreenv()
6075 {
6076     int	    esize;
6077     char    **env;
6078 
6079     esize = envsize + EXTRASIZE;
6080     env = (char **)vim_realloc((char *)environ, esize * sizeof (*env));
6081     if (env == 0)
6082 	return -1;
6083     environ = env;
6084     envsize = esize;
6085     return 0;
6086 }
6087 
6088 # ifdef USE_VIMPTY_GETENV
6089     char_u *
6090 vimpty_getenv(string)
6091     const char_u *string;
6092 {
6093     int i;
6094     char_u *p;
6095 
6096     if (envsize < 0)
6097 	return NULL;
6098 
6099     i = findenv((char *)string);
6100 
6101     if (i < 0)
6102 	return NULL;
6103 
6104     p = vim_strchr((char_u *)environ[i], '=');
6105     return (p + 1);
6106 }
6107 # endif
6108 
6109 #endif /* !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) */
6110 
6111 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO)
6112 /*
6113  * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
6114  * rights to write into.
6115  */
6116     int
6117 filewritable(fname)
6118     char_u	*fname;
6119 {
6120     int		retval = 0;
6121 #if defined(UNIX) || defined(VMS)
6122     int		perm = 0;
6123 #endif
6124 
6125 #if defined(UNIX) || defined(VMS)
6126     perm = mch_getperm(fname);
6127 #endif
6128 #ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
6129     if (
6130 # ifdef WIN3264
6131 	    mch_writable(fname) &&
6132 # else
6133 # if defined(UNIX) || defined(VMS)
6134 	    (perm & 0222) &&
6135 #  endif
6136 # endif
6137 	    mch_access((char *)fname, W_OK) == 0
6138        )
6139 #endif
6140     {
6141 	++retval;
6142 	if (mch_isdir(fname))
6143 	    ++retval;
6144     }
6145     return retval;
6146 }
6147 #endif
6148 
6149 /*
6150  * Print an error message with one or two "%s" and one or two string arguments.
6151  * This is not in message.c to avoid a warning for prototypes.
6152  */
6153     int
6154 emsg3(s, a1, a2)
6155     char_u *s, *a1, *a2;
6156 {
6157     if (emsg_not_now())
6158 	return TRUE;		/* no error messages at the moment */
6159 #ifdef HAVE_STDARG_H
6160     vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2);
6161 #else
6162     vim_snprintf((char *)IObuff, IOSIZE, (char *)s, (long_u)a1, (long_u)a2);
6163 #endif
6164     return emsg(IObuff);
6165 }
6166 
6167 /*
6168  * Print an error message with one "%ld" and one long int argument.
6169  * This is not in message.c to avoid a warning for prototypes.
6170  */
6171     int
6172 emsgn(s, n)
6173     char_u	*s;
6174     long	n;
6175 {
6176     if (emsg_not_now())
6177 	return TRUE;		/* no error messages at the moment */
6178     vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
6179     return emsg(IObuff);
6180 }
6181 
6182 #if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
6183 /*
6184  * Read 2 bytes from "fd" and turn them into an int, MSB first.
6185  */
6186     int
6187 get2c(fd)
6188     FILE	*fd;
6189 {
6190     int		n;
6191 
6192     n = getc(fd);
6193     n = (n << 8) + getc(fd);
6194     return n;
6195 }
6196 
6197 /*
6198  * Read 3 bytes from "fd" and turn them into an int, MSB first.
6199  */
6200     int
6201 get3c(fd)
6202     FILE	*fd;
6203 {
6204     int		n;
6205 
6206     n = getc(fd);
6207     n = (n << 8) + getc(fd);
6208     n = (n << 8) + getc(fd);
6209     return n;
6210 }
6211 
6212 /*
6213  * Read 4 bytes from "fd" and turn them into an int, MSB first.
6214  */
6215     int
6216 get4c(fd)
6217     FILE	*fd;
6218 {
6219     /* Use unsigned rather than int otherwise result is undefined
6220      * when left-shift sets the MSB. */
6221     unsigned	n;
6222 
6223     n = (unsigned)getc(fd);
6224     n = (n << 8) + (unsigned)getc(fd);
6225     n = (n << 8) + (unsigned)getc(fd);
6226     n = (n << 8) + (unsigned)getc(fd);
6227     return (int)n;
6228 }
6229 
6230 /*
6231  * Read 8 bytes from "fd" and turn them into a time_t, MSB first.
6232  */
6233     time_t
6234 get8ctime(fd)
6235     FILE	*fd;
6236 {
6237     time_t	n = 0;
6238     int		i;
6239 
6240     for (i = 0; i < 8; ++i)
6241 	n = (n << 8) + getc(fd);
6242     return n;
6243 }
6244 
6245 /*
6246  * Read a string of length "cnt" from "fd" into allocated memory.
6247  * Returns NULL when out of memory or unable to read that many bytes.
6248  */
6249     char_u *
6250 read_string(fd, cnt)
6251     FILE	*fd;
6252     int		cnt;
6253 {
6254     char_u	*str;
6255     int		i;
6256     int		c;
6257 
6258     /* allocate memory */
6259     str = alloc((unsigned)cnt + 1);
6260     if (str != NULL)
6261     {
6262 	/* Read the string.  Quit when running into the EOF. */
6263 	for (i = 0; i < cnt; ++i)
6264 	{
6265 	    c = getc(fd);
6266 	    if (c == EOF)
6267 	    {
6268 		vim_free(str);
6269 		return NULL;
6270 	    }
6271 	    str[i] = c;
6272 	}
6273 	str[i] = NUL;
6274     }
6275     return str;
6276 }
6277 
6278 /*
6279  * Write a number to file "fd", MSB first, in "len" bytes.
6280  */
6281     int
6282 put_bytes(fd, nr, len)
6283     FILE    *fd;
6284     long_u  nr;
6285     int	    len;
6286 {
6287     int	    i;
6288 
6289     for (i = len - 1; i >= 0; --i)
6290 	if (putc((int)(nr >> (i * 8)), fd) == EOF)
6291 	    return FAIL;
6292     return OK;
6293 }
6294 
6295 #ifdef _MSC_VER
6296 # if (_MSC_VER <= 1200)
6297 /* This line is required for VC6 without the service pack.  Also see the
6298  * matching #pragma below. */
6299  #  pragma optimize("", off)
6300 # endif
6301 #endif
6302 
6303 /*
6304  * Write time_t to file "fd" in 8 bytes.
6305  * Returns FAIL when the write failed.
6306  */
6307     int
6308 put_time(fd, the_time)
6309     FILE	*fd;
6310     time_t	the_time;
6311 {
6312     char_u	buf[8];
6313 
6314     time_to_bytes(the_time, buf);
6315     return fwrite(buf, (size_t)8, (size_t)1, fd) == 1 ? OK : FAIL;
6316 }
6317 
6318 /*
6319  * Write time_t to "buf[8]".
6320  */
6321     void
6322 time_to_bytes(the_time, buf)
6323     time_t	the_time;
6324     char_u	*buf;
6325 {
6326     int		c;
6327     int		i;
6328     int		bi = 0;
6329     time_t	wtime = the_time;
6330 
6331     /* time_t can be up to 8 bytes in size, more than long_u, thus we
6332      * can't use put_bytes() here.
6333      * Another problem is that ">>" may do an arithmetic shift that keeps the
6334      * sign.  This happens for large values of wtime.  A cast to long_u may
6335      * truncate if time_t is 8 bytes.  So only use a cast when it is 4 bytes,
6336      * it's safe to assume that long_u is 4 bytes or more and when using 8
6337      * bytes the top bit won't be set. */
6338     for (i = 7; i >= 0; --i)
6339     {
6340 	if (i + 1 > (int)sizeof(time_t))
6341 	    /* ">>" doesn't work well when shifting more bits than avail */
6342 	    buf[bi++] = 0;
6343 	else
6344 	{
6345 #if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4
6346 	    c = (int)(wtime >> (i * 8));
6347 #else
6348 	    c = (int)((long_u)wtime >> (i * 8));
6349 #endif
6350 	    buf[bi++] = c;
6351 	}
6352     }
6353 }
6354 
6355 #ifdef _MSC_VER
6356 # if (_MSC_VER <= 1200)
6357  #  pragma optimize("", on)
6358 # endif
6359 #endif
6360 
6361 #endif
6362 
6363 #if (defined(FEAT_MBYTE) && defined(FEAT_QUICKFIX)) \
6364 	|| defined(FEAT_SPELL) || defined(PROTO)
6365 /*
6366  * Return TRUE if string "s" contains a non-ASCII character (128 or higher).
6367  * When "s" is NULL FALSE is returned.
6368  */
6369     int
6370 has_non_ascii(s)
6371     char_u	*s;
6372 {
6373     char_u	*p;
6374 
6375     if (s != NULL)
6376 	for (p = s; *p != NUL; ++p)
6377 	    if (*p >= 128)
6378 		return TRUE;
6379     return FALSE;
6380 }
6381 #endif
6382 
6383 #if defined(MESSAGE_QUEUE) || defined(PROTO)
6384 /*
6385  * Process messages that have been queued for netbeans or clientserver.
6386  * These functions can call arbitrary vimscript and should only be called when
6387  * it is safe to do so.
6388  */
6389     void
6390 parse_queued_messages()
6391 {
6392 # ifdef FEAT_NETBEANS_INTG
6393     /* Process the queued netbeans messages. */
6394     netbeans_parse_messages();
6395 # endif
6396 # if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
6397     /* Process the queued clientserver messages. */
6398     server_parse_messages();
6399 # endif
6400 }
6401 #endif
6402