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