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