xref: /vim-8.2.3635/src/misc2.c (revision 7b0294cb)
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 #if 0
3461 /*
3462  * if someone likes findfirst/findnext, here are the functions
3463  * NOT TESTED!!
3464  */
3465 
3466 static void *ff_fn_search_context = NULL;
3467 
3468     char_u *
3469 vim_findfirst(path, filename, level)
3470     char_u	*path;
3471     char_u	*filename;
3472     int		level;
3473 {
3474     ff_fn_search_context =
3475 	vim_findfile_init(path, filename, NULL, level, TRUE, FALSE,
3476 		ff_fn_search_context, rel_fname);
3477     if (NULL == ff_fn_search_context)
3478 	return NULL;
3479     else
3480 	return vim_findnext()
3481 }
3482 
3483     char_u *
3484 vim_findnext()
3485 {
3486     char_u *ret = vim_findfile(ff_fn_search_context);
3487 
3488     if (NULL == ret)
3489     {
3490 	vim_findfile_cleanup(ff_fn_search_context);
3491 	ff_fn_search_context = NULL;
3492     }
3493     return ret;
3494 }
3495 #endif
3496 
3497 /*
3498  * Initialization routine for vim_findfile.
3499  *
3500  * Returns the newly allocated search context or NULL if an error occured.
3501  *
3502  * Don't forget to clean up by calling vim_findfile_cleanup() if you are done
3503  * with the search context.
3504  *
3505  * Find the file 'filename' in the directory 'path'.
3506  * The parameter 'path' may contain wildcards. If so only search 'level'
3507  * directories deep. The parameter 'level' is the absolute maximum and is
3508  * not related to restricts given to the '**' wildcard. If 'level' is 100
3509  * and you use '**200' vim_findfile() will stop after 100 levels.
3510  *
3511  * If 'stopdirs' is not NULL and nothing is found downward, the search is
3512  * restarted on the next higher directory level. This is repeated until the
3513  * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the
3514  * format ";*<dirname>*\(;<dirname>\)*;\=$".
3515  *
3516  * If the 'path' is relative, the starting dir for the search is either VIM's
3517  * current dir or if the path starts with "./" the current files dir.
3518  * If the 'path' is absolut, the starting dir is that part of the path before
3519  * the first wildcard.
3520  *
3521  * Upward search is only done on the starting dir.
3522  *
3523  * If 'free_visited' is TRUE the list of already visited files/directories is
3524  * cleared. Set this to FALSE if you just want to search from another
3525  * directory, but want to be sure that no directory from a previous search is
3526  * searched again. This is useful if you search for a file at different places.
3527  * The list of visited files/dirs can also be cleared with the function
3528  * vim_findfile_free_visited().
3529  *
3530  * Set the parameter 'need_dir' to TRUE if you want to search for a directory
3531  * instead of a file.
3532  *
3533  * A search context returned by a previous call to vim_findfile_init() can be
3534  * passed in the parameter 'search_ctx'. This context is than reused and
3535  * reinitialized with the new parameters. The list of already viseted
3536  * directories from this context is only deleted if the parameter
3537  * 'free_visited' is true. Be aware that the passed search_context is freed if
3538  * the reinitialization fails.
3539  *
3540  * If you don't have a search context from a previous call 'search_ctx' must be
3541  * NULL.
3542  *
3543  * This function silently ignores a few errors, vim_findfile() will have
3544  * limited functionality then.
3545  */
3546 /*ARGSUSED*/
3547     void *
3548 vim_findfile_init(path, filename, stopdirs, level, free_visited, need_dir,
3549 						search_ctx, tagfile, rel_fname)
3550     char_u	*path;
3551     char_u	*filename;
3552     char_u	*stopdirs;
3553     int		level;
3554     int		free_visited;
3555     int		need_dir;
3556     void	*search_ctx;
3557     int		tagfile;
3558     char_u	*rel_fname;	/* file name to use for "." */
3559 {
3560 #ifdef FEAT_PATH_EXTRA
3561     char_u	*wc_part;
3562 #endif
3563     ff_stack_T	*sptr;
3564 
3565     /* If a search context is given by the caller, reuse it, else allocate a
3566      * new one.
3567      */
3568     if (search_ctx != NULL)
3569 	ff_search_ctx = search_ctx;
3570     else
3571     {
3572 	ff_search_ctx = (ff_search_ctx_T*)alloc(
3573 					   (unsigned)sizeof(ff_search_ctx_T));
3574 	if (ff_search_ctx == NULL)
3575 	    goto error_return;
3576 	memset(ff_search_ctx, 0, sizeof(ff_search_ctx_T));
3577     }
3578 
3579     /* clear the search context, but NOT the visited lists */
3580     ff_clear();
3581 
3582     /* clear visited list if wanted */
3583     if (free_visited == TRUE)
3584 	vim_findfile_free_visited(ff_search_ctx);
3585     else
3586     {
3587 	/* Reuse old visited lists. Get the visited list for the given
3588 	 * filename. If no list for the current filename exists, creates a new
3589 	 * one.
3590 	 */
3591 	ff_search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
3592 				     &ff_search_ctx->ffsc_visited_lists_list);
3593 	if (ff_search_ctx->ffsc_visited_list == NULL)
3594 	    goto error_return;
3595 	ff_search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename,
3596 				 &ff_search_ctx->ffsc_dir_visited_lists_list);
3597 	if (ff_search_ctx->ffsc_dir_visited_list == NULL)
3598 	    goto error_return;
3599     }
3600 
3601     if (ff_expand_buffer == NULL)
3602     {
3603 	ff_expand_buffer = (char_u*)alloc(MAXPATHL);
3604 	if (ff_expand_buffer == NULL)
3605 	    goto error_return;
3606     }
3607 
3608     /* Store information on starting dir now if path is relative.
3609      * If path is absolute, we do that later.  */
3610     if (path[0] == '.'
3611 	    && (vim_ispathsep(path[1]) || path[1] == NUL)
3612 	    && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
3613 	    && rel_fname != NULL)
3614     {
3615 	int	len = (int)(gettail(rel_fname) - rel_fname);
3616 
3617 	if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL)
3618 	{
3619 	    /* Make the start dir an absolute path name. */
3620 	    STRNCPY(ff_expand_buffer, rel_fname, len);
3621 	    ff_expand_buffer[len] = NUL;
3622 	    ff_search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer,
3623 								       FALSE);
3624 	}
3625 	else
3626 	    ff_search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
3627 	if (ff_search_ctx->ffsc_start_dir == NULL)
3628 	    goto error_return;
3629 	if (*++path != NUL)
3630 	    ++path;
3631     }
3632     else if (*path == NUL || !vim_isAbsName(path))
3633     {
3634 #ifdef BACKSLASH_IN_FILENAME
3635 	/* "c:dir" needs "c:" to be expanded, otherwise use current dir */
3636 	if (*path != NUL && path[1] == ':')
3637 	{
3638 	    char_u  drive[3];
3639 
3640 	    drive[0] = path[0];
3641 	    drive[1] = ':';
3642 	    drive[2] = NUL;
3643 	    if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
3644 		goto error_return;
3645 	    path += 2;
3646 	}
3647 	else
3648 #endif
3649 	if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL)
3650 	    goto error_return;
3651 
3652 	ff_search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
3653 	if (ff_search_ctx->ffsc_start_dir == NULL)
3654 	    goto error_return;
3655 
3656 #ifdef BACKSLASH_IN_FILENAME
3657 	/* A path that starts with "/dir" is relative to the drive, not to the
3658 	 * directory (but not for "//machine/dir").  Only use the drive name. */
3659 	if ((*path == '/' || *path == '\\')
3660 		&& path[1] != path[0]
3661 		&& ff_search_ctx->ffsc_start_dir[1] == ':')
3662 	    ff_search_ctx->ffsc_start_dir[2] = NUL;
3663 #endif
3664     }
3665 
3666 #ifdef FEAT_PATH_EXTRA
3667     /*
3668      * If stopdirs are given, split them into an array of pointers.
3669      * If this fails (mem allocation), there is no upward search at all or a
3670      * stop directory is not recognized -> continue silently.
3671      * If stopdirs just contains a ";" or is empty,
3672      * ff_search_ctx->ffsc_stopdirs_v will only contain a  NULL pointer. This
3673      * is handled as unlimited upward search.  See function
3674      * ff_path_in_stoplist() for details.
3675      */
3676     if (stopdirs != NULL)
3677     {
3678 	char_u	*walker = stopdirs;
3679 	int	dircount;
3680 
3681 	while (*walker == ';')
3682 	    walker++;
3683 
3684 	dircount = 1;
3685 	ff_search_ctx->ffsc_stopdirs_v =
3686 	    (char_u **)alloc((unsigned)sizeof(char_u *));
3687 
3688 	if (ff_search_ctx->ffsc_stopdirs_v != NULL)
3689 	{
3690 	    do
3691 	    {
3692 		char_u	*helper;
3693 		void	*ptr;
3694 
3695 		helper = walker;
3696 		ptr = vim_realloc(ff_search_ctx->ffsc_stopdirs_v,
3697 					   (dircount + 1) * sizeof(char_u *));
3698 		if (ptr)
3699 		    ff_search_ctx->ffsc_stopdirs_v = ptr;
3700 		else
3701 		    /* ignore, keep what we have and continue */
3702 		    break;
3703 		walker = vim_strchr(walker, ';');
3704 		if (walker)
3705 		{
3706 		    ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
3707 			vim_strnsave(helper, (int)(walker - helper));
3708 		    walker++;
3709 		}
3710 		else
3711 		    /* this might be "", which means ascent till top
3712 		     * of directory tree.
3713 		     */
3714 		    ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
3715 			vim_strsave(helper);
3716 
3717 		dircount++;
3718 
3719 	    } while (walker != NULL);
3720 	    ff_search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
3721 	}
3722     }
3723 #endif
3724 
3725 #ifdef FEAT_PATH_EXTRA
3726     ff_search_ctx->ffsc_level = level;
3727 
3728     /* split into:
3729      *  -fix path
3730      *  -wildcard_stuff (might be NULL)
3731      */
3732     wc_part = vim_strchr(path, '*');
3733     if (wc_part != NULL)
3734     {
3735 	int	llevel;
3736 	int	len;
3737 	char	*errpt;
3738 
3739 	/* save the fix part of the path */
3740 	ff_search_ctx->ffsc_fix_path = vim_strnsave(path,
3741 						       (int)(wc_part - path));
3742 
3743 	/*
3744 	 * copy wc_path and add restricts to the '**' wildcard.
3745 	 * The octett after a '**' is used as a (binary) counter.
3746 	 * So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
3747 	 * or '**76' is transposed to '**N'( 'N' is ASCII value 76).
3748 	 * For EBCDIC you get different character values.
3749 	 * If no restrict is given after '**' the default is used.
3750 	 * Due to this technic the path looks awful if you print it as a
3751 	 * string.
3752 	 */
3753 	len = 0;
3754 	while (*wc_part != NUL)
3755 	{
3756 	    if (STRNCMP(wc_part, "**", 2) == 0)
3757 	    {
3758 		ff_expand_buffer[len++] = *wc_part++;
3759 		ff_expand_buffer[len++] = *wc_part++;
3760 
3761 		llevel = strtol((char *)wc_part, &errpt, 10);
3762 		if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255)
3763 		    ff_expand_buffer[len++] = llevel;
3764 		else if ((char_u *)errpt != wc_part && llevel == 0)
3765 		    /* restrict is 0 -> remove already added '**' */
3766 		    len -= 2;
3767 		else
3768 		    ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
3769 		wc_part = (char_u *)errpt;
3770 		if (*wc_part != PATHSEP && *wc_part != NUL)
3771 		{
3772 		    EMSG2(_("E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR);
3773 		    goto error_return;
3774 		}
3775 	    }
3776 	    else
3777 		ff_expand_buffer[len++] = *wc_part++;
3778 	}
3779 	ff_expand_buffer[len] = NUL;
3780 	ff_search_ctx->ffsc_wc_path =
3781 	    vim_strsave(ff_expand_buffer);
3782 
3783 	if (ff_search_ctx->ffsc_wc_path == NULL)
3784 	    goto error_return;
3785     }
3786     else
3787 #endif
3788 	ff_search_ctx->ffsc_fix_path = vim_strsave(path);
3789 
3790     if (ff_search_ctx->ffsc_start_dir == NULL)
3791     {
3792 	/* store the fix part as startdir.
3793 	 * This is needed if the parameter path is fully qualified.
3794 	 */
3795 	ff_search_ctx->ffsc_start_dir = vim_strsave(ff_search_ctx->ffsc_fix_path);
3796 	if (ff_search_ctx->ffsc_start_dir)
3797 	    ff_search_ctx->ffsc_fix_path[0] = NUL;
3798     }
3799 
3800     /* create an absolute path */
3801     STRCPY(ff_expand_buffer, ff_search_ctx->ffsc_start_dir);
3802     add_pathsep(ff_expand_buffer);
3803     STRCAT(ff_expand_buffer, ff_search_ctx->ffsc_fix_path);
3804     add_pathsep(ff_expand_buffer);
3805 
3806     sptr = ff_create_stack_element(ff_expand_buffer,
3807 #ifdef FEAT_PATH_EXTRA
3808 	    ff_search_ctx->ffsc_wc_path,
3809 #endif
3810 	    level, 0);
3811 
3812     if (sptr == NULL)
3813 	goto error_return;
3814 
3815     ff_push(sptr);
3816 
3817     ff_search_ctx->ffsc_file_to_search = vim_strsave(filename);
3818     if (ff_search_ctx->ffsc_file_to_search == NULL)
3819 	goto error_return;
3820 
3821     return ff_search_ctx;
3822 
3823 error_return:
3824     /*
3825      * We clear the search context now!
3826      * Even when the caller gave us a (perhaps valid) context we free it here,
3827      * as we might have already destroyed it.
3828      */
3829     vim_findfile_cleanup(ff_search_ctx);
3830     return NULL;
3831 }
3832 
3833 #if defined(FEAT_PATH_EXTRA) || defined(PROTO)
3834 /*
3835  * Get the stopdir string.  Check that ';' is not escaped.
3836  */
3837     char_u *
3838 vim_findfile_stopdir(buf)
3839     char_u	*buf;
3840 {
3841     char_u	*r_ptr = buf;
3842 
3843     while (*r_ptr != NUL && *r_ptr != ';')
3844     {
3845 	if (r_ptr[0] == '\\' && r_ptr[1] == ';')
3846 	{
3847 	    /* overwrite the escape char,
3848 	     * use STRLEN(r_ptr) to move the trailing '\0'
3849 	     */
3850 	    mch_memmove(r_ptr, r_ptr + 1, STRLEN(r_ptr));
3851 	    r_ptr++;
3852 	}
3853 	r_ptr++;
3854     }
3855     if (*r_ptr == ';')
3856     {
3857 	*r_ptr = 0;
3858 	r_ptr++;
3859     }
3860     else if (*r_ptr == NUL)
3861 	r_ptr = NULL;
3862     return r_ptr;
3863 }
3864 #endif
3865 
3866 /* Clean up the given search context. Can handle a NULL pointer */
3867     void
3868 vim_findfile_cleanup(ctx)
3869     void	*ctx;
3870 {
3871     if (NULL == ctx)
3872 	return;
3873 
3874     ff_search_ctx = ctx;
3875 
3876     vim_findfile_free_visited(ctx);
3877     ff_clear();
3878     vim_free(ctx);
3879     ff_search_ctx = NULL;
3880 }
3881 
3882 /*
3883  * Find a file in a search context.
3884  * The search context was created with vim_findfile_init() above.
3885  * Return a pointer to an allocated file name or NULL if nothing found.
3886  * To get all matching files call this function until you get NULL.
3887  *
3888  * If the passed search_context is NULL, NULL is returned.
3889  *
3890  * The search algorithm is depth first. To change this replace the
3891  * stack with a list (don't forget to leave partly searched directories on the
3892  * top of the list).
3893  */
3894     char_u *
3895 vim_findfile(search_ctx)
3896     void	*search_ctx;
3897 {
3898     char_u	*file_path;
3899 #ifdef FEAT_PATH_EXTRA
3900     char_u	*rest_of_wildcards;
3901     char_u	*path_end = NULL;
3902 #endif
3903     ff_stack_T	*ctx;
3904 #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA)
3905     int		len;
3906 #endif
3907     int		i;
3908     char_u	*p;
3909 #ifdef FEAT_SEARCHPATH
3910     char_u	*suf;
3911 #endif
3912 
3913     if (search_ctx == NULL)
3914 	return NULL;
3915 
3916     ff_search_ctx = (ff_search_ctx_T*)search_ctx;
3917 
3918     /*
3919      * filepath is used as buffer for various actions and as the storage to
3920      * return a found filename.
3921      */
3922     if ((file_path = alloc((int)MAXPATHL)) == NULL)
3923 	return NULL;
3924 
3925 #ifdef FEAT_PATH_EXTRA
3926     /* store the end of the start dir -- needed for upward search */
3927     if (ff_search_ctx->ffsc_start_dir != NULL)
3928 	path_end = &ff_search_ctx->ffsc_start_dir[STRLEN(ff_search_ctx->ffsc_start_dir)];
3929 #endif
3930 
3931 #ifdef FEAT_PATH_EXTRA
3932     /* upward search loop */
3933     for (;;)
3934     {
3935 #endif
3936 	/* downward search loop */
3937 	for (;;)
3938 	{
3939 	    /* check if user user wants to stop the search*/
3940 	    ui_breakcheck();
3941 	    if (got_int)
3942 		break;
3943 
3944 	    /* get directory to work on from stack */
3945 	    ctx = ff_pop();
3946 	    if (ctx == NULL)
3947 		break;
3948 
3949 	    /*
3950 	     * TODO: decide if we leave this test in
3951 	     *
3952 	     * GOOD: don't search a directory(-tree) twice.
3953 	     * BAD:  - check linked list for every new directory entered.
3954 	     *       - check for double files also done below
3955 	     *
3956 	     * Here we check if we already searched this directory.
3957 	     * We already searched a directory if:
3958 	     * 1) The directory is the same.
3959 	     * 2) We would use the same wildcard string.
3960 	     *
3961 	     * Good if you have links on same directory via several ways
3962 	     *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
3963 	     *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
3964 	     *
3965 	     * This check is only needed for directories we work on for the
3966 	     * first time (hence ctx->ff_filearray == NULL)
3967 	     */
3968 	    if (ctx->ffs_filearray == NULL
3969 		    && ff_check_visited(&ff_search_ctx->ffsc_dir_visited_list
3970 							  ->ffvl_visited_list,
3971 			ctx->ffs_fix_path
3972 #ifdef FEAT_PATH_EXTRA
3973 			, ctx->ffs_wc_path
3974 #endif
3975 			) == FAIL)
3976 	    {
3977 #ifdef FF_VERBOSE
3978 		if (p_verbose >= 5)
3979 		{
3980 		    /* always scroll up, don't overwrite */
3981 		    msg_scroll = TRUE;
3982 		    smsg((char_u *)"Already Searched: %s (%s)",
3983 					   ctx->ffs_fix_path, ctx->ffs_wc_path);
3984 		    /* don't overwrite this either */
3985 		    msg_puts((char_u *)"\n");
3986 		    cmdline_row = msg_row;
3987 		}
3988 #endif
3989 		ff_free_stack_element(ctx);
3990 		continue;
3991 	    }
3992 #ifdef FF_VERBOSE
3993 	    else if (p_verbose >= 5)
3994 	    {
3995 		/* always scroll up, don't overwrite */
3996 		msg_scroll = TRUE;
3997 		smsg((char_u *)"Searching: %s (%s)", ctx->ffs_fix_path,
3998 			ctx->ffs_wc_path);
3999 		/* don't overwrite this either */
4000 		msg_puts((char_u *)"\n");
4001 		cmdline_row = msg_row;
4002 	    }
4003 #endif
4004 
4005 	    /* check depth */
4006 	    if (ctx->ffs_level <= 0)
4007 	    {
4008 		ff_free_stack_element(ctx);
4009 		continue;
4010 	    }
4011 
4012 	    file_path[0] = NUL;
4013 
4014 	    /*
4015 	     * If no filearray till now expand wildcards
4016 	     * The function expand_wildcards() can handle an array of paths
4017 	     * and all possible expands are returned in one array. We use this
4018 	     * to handle the expansion of '**' into an empty string.
4019 	     */
4020 	    if (ctx->ffs_filearray == NULL)
4021 	    {
4022 		char_u *dirptrs[2];
4023 
4024 		/* we use filepath to build the path expand_wildcards() should
4025 		 * expand.
4026 		 */
4027 		dirptrs[0] = file_path;
4028 		dirptrs[1] = NULL;
4029 
4030 		/* if we have a start dir copy it in */
4031 		if (!vim_isAbsName(ctx->ffs_fix_path)
4032 			&& ff_search_ctx->ffsc_start_dir)
4033 		{
4034 		    STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
4035 		    add_pathsep(file_path);
4036 		}
4037 
4038 		/* append the fix part of the search path */
4039 		STRCAT(file_path, ctx->ffs_fix_path);
4040 		add_pathsep(file_path);
4041 
4042 #ifdef FEAT_PATH_EXTRA
4043 		rest_of_wildcards = ctx->ffs_wc_path;
4044 		if (*rest_of_wildcards != NUL)
4045 		{
4046 		    len = (int)STRLEN(file_path);
4047 		    if (STRNCMP(rest_of_wildcards, "**", 2) == 0)
4048 		    {
4049 			/* pointer to the restrict byte
4050 			 * The restrict byte is not a character!
4051 			 */
4052 			p = rest_of_wildcards + 2;
4053 
4054 			if (*p > 0)
4055 			{
4056 			    (*p)--;
4057 			    file_path[len++] = '*';
4058 			}
4059 
4060 			if (*p == 0)
4061 			{
4062 			    /* remove '**<numb> from wildcards */
4063 			    mch_memmove(rest_of_wildcards,
4064 				    rest_of_wildcards + 3,
4065 				    STRLEN(rest_of_wildcards + 3) + 1);
4066 			}
4067 			else
4068 			    rest_of_wildcards += 3;
4069 
4070 			if (ctx->ffs_star_star_empty == 0)
4071 			{
4072 			    /* if not done before, expand '**' to empty */
4073 			    ctx->ffs_star_star_empty = 1;
4074 			    dirptrs[1] = ctx->ffs_fix_path;
4075 			}
4076 		    }
4077 
4078 		    /*
4079 		     * Here we copy until the next path separator or the end of
4080 		     * the path. If we stop at a path separator, there is
4081 		     * still somthing else left. This is handled below by
4082 		     * pushing every directory returned from expand_wildcards()
4083 		     * on the stack again for further search.
4084 		     */
4085 		    while (*rest_of_wildcards
4086 			    && !vim_ispathsep(*rest_of_wildcards))
4087 			file_path[len++] = *rest_of_wildcards++;
4088 
4089 		    file_path[len] = NUL;
4090 		    if (vim_ispathsep(*rest_of_wildcards))
4091 			rest_of_wildcards++;
4092 		}
4093 #endif
4094 
4095 		/*
4096 		 * Expand wildcards like "*" and "$VAR".
4097 		 * If the path is a URL don't try this.
4098 		 */
4099 		if (path_with_url(dirptrs[0]))
4100 		{
4101 		    ctx->ffs_filearray = (char_u **)
4102 					      alloc((unsigned)sizeof(char *));
4103 		    if (ctx->ffs_filearray != NULL
4104 			    && (ctx->ffs_filearray[0]
4105 				= vim_strsave(dirptrs[0])) != NULL)
4106 			ctx->ffs_filearray_size = 1;
4107 		    else
4108 			ctx->ffs_filearray_size = 0;
4109 		}
4110 		else
4111 		    expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
4112 			    &ctx->ffs_filearray_size,
4113 			    &ctx->ffs_filearray,
4114 			    EW_DIR|EW_ADDSLASH|EW_SILENT);
4115 
4116 		ctx->ffs_filearray_cur = 0;
4117 		ctx->ffs_stage = 0;
4118 	    }
4119 #ifdef FEAT_PATH_EXTRA
4120 	    else
4121 		rest_of_wildcards = &ctx->ffs_wc_path[STRLEN(ctx->ffs_wc_path)];
4122 #endif
4123 
4124 	    if (ctx->ffs_stage == 0)
4125 	    {
4126 		/* this is the first time we work on this directory */
4127 #ifdef FEAT_PATH_EXTRA
4128 		if (*rest_of_wildcards == NUL)
4129 #endif
4130 		{
4131 		    /*
4132 		     * we don't have further wildcards to expand, so we have to
4133 		     * check for the final file now
4134 		     */
4135 		    for (i = ctx->ffs_filearray_cur;
4136 					     i < ctx->ffs_filearray_size; ++i)
4137 		    {
4138 			if (!path_with_url(ctx->ffs_filearray[i])
4139 					 && !mch_isdir(ctx->ffs_filearray[i]))
4140 			    continue;   /* not a directory */
4141 
4142 			/* prepare the filename to be checked for existance
4143 			 * below */
4144 			STRCPY(file_path, ctx->ffs_filearray[i]);
4145 			add_pathsep(file_path);
4146 			STRCAT(file_path, ff_search_ctx->ffsc_file_to_search);
4147 
4148 			/*
4149 			 * Try without extra suffix and then with suffixes
4150 			 * from 'suffixesadd'.
4151 			 */
4152 #ifdef FEAT_SEARCHPATH
4153 			len = (int)STRLEN(file_path);
4154 			suf = curbuf->b_p_sua;
4155 			for (;;)
4156 #endif
4157 			{
4158 			    /* if file exists and we didn't already find it */
4159 			    if ((path_with_url(file_path)
4160 					|| (mch_getperm(file_path) >= 0
4161 					    && (!ff_search_ctx->ffsc_need_dir
4162 						|| mch_isdir(file_path))))
4163 #ifndef FF_VERBOSE
4164 				    && (ff_check_visited(
4165 					    &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
4166 					    file_path
4167 #ifdef FEAT_PATH_EXTRA
4168 					    , (char_u *)""
4169 #endif
4170 					    ) == OK)
4171 #endif
4172 			       )
4173 			    {
4174 #ifdef FF_VERBOSE
4175 				if (ff_check_visited(
4176 					    &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
4177 					    file_path
4178 #ifdef FEAT_PATH_EXTRA
4179 					    , (char_u *)""
4180 #endif
4181 						    ) == FAIL)
4182 				{
4183 				    if (p_verbose >= 5)
4184 				    {
4185 					/* always scroll up, don't overwrite */
4186 					msg_scroll = TRUE;
4187 					msg_str((char_u *)"Already: %s",
4188 								   file_path);
4189 					/* don't overwrite this either */
4190 					msg_puts((char_u *)"\n");
4191 					cmdline_row = msg_row;
4192 				    }
4193 				    continue;
4194 				}
4195 #endif
4196 
4197 				/* push dir to examine rest of subdirs later */
4198 				ctx->ffs_filearray_cur = i + 1;
4199 				ff_push(ctx);
4200 
4201 				simplify_filename(file_path);
4202 				if (mch_dirname(ff_expand_buffer, MAXPATHL)
4203 									== OK)
4204 				{
4205 				    p = shorten_fname(file_path,
4206 							    ff_expand_buffer);
4207 				    if (p != NULL)
4208 					mch_memmove(file_path, p,
4209 							       STRLEN(p) + 1);
4210 				}
4211 #ifdef FF_VERBOSE
4212 				if (p_verbose >= 5)
4213 				{
4214 				    /* always scroll up, don't overwrite */
4215 				    msg_scroll = TRUE;
4216 				    msg_str((char_u *)"HIT: %s", file_path);
4217 				    /* don't overwrite this either */
4218 				    msg_puts((char_u *)"\n");
4219 				    cmdline_row = msg_row;
4220 				}
4221 #endif
4222 				return file_path;
4223 			    }
4224 
4225 #ifdef FEAT_SEARCHPATH
4226 			    /* Not found or found already, try next suffix. */
4227 			    if (*suf == NUL)
4228 				break;
4229 			    copy_option_part(&suf, file_path + len,
4230 							 MAXPATHL - len, ",");
4231 #endif
4232 			}
4233 		    }
4234 		}
4235 #ifdef FEAT_PATH_EXTRA
4236 		else
4237 		{
4238 		    /*
4239 		     * still wildcards left, push the directories for further
4240 		     * search
4241 		     */
4242 		    for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size;
4243 									  ++i)
4244 		    {
4245 			if (!mch_isdir(ctx->ffs_filearray[i]))
4246 			    continue;	/* not a directory */
4247 
4248 			ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
4249 				      rest_of_wildcards, ctx->ffs_level - 1, 0));
4250 		    }
4251 		}
4252 #endif
4253 		ctx->ffs_filearray_cur = 0;
4254 		ctx->ffs_stage = 1;
4255 	    }
4256 
4257 #ifdef FEAT_PATH_EXTRA
4258 	    /*
4259 	     * if wildcards contains '**' we have to descent till we reach the
4260 	     * leaves of the directory tree.
4261 	     */
4262 	    if (STRNCMP(ctx->ffs_wc_path, "**", 2) == 0)
4263 	    {
4264 		for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size; ++i)
4265 		{
4266 		    if (fnamecmp(ctx->ffs_filearray[i], ctx->ffs_fix_path) == 0)
4267 			continue; /* don't repush same directory */
4268 		    if (!mch_isdir(ctx->ffs_filearray[i]))
4269 			continue;   /* not a directory */
4270 		    ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
4271 				ctx->ffs_wc_path, ctx->ffs_level - 1, 1));
4272 		}
4273 	    }
4274 #endif
4275 
4276 	    /* we are done with the current directory */
4277 	    ff_free_stack_element(ctx);
4278 
4279 	}
4280 
4281 #ifdef FEAT_PATH_EXTRA
4282 	/* If we reached this, we didn't find anything downwards.
4283 	 * Let's check if we should do an upward search.
4284 	 */
4285 	if (ff_search_ctx->ffsc_start_dir
4286 		&& ff_search_ctx->ffsc_stopdirs_v != NULL && !got_int)
4287 	{
4288 	    ff_stack_T  *sptr;
4289 
4290 	    /* is the last starting directory in the stop list? */
4291 	    if (ff_path_in_stoplist(ff_search_ctx->ffsc_start_dir,
4292 		       (int)(path_end - ff_search_ctx->ffsc_start_dir),
4293 		       ff_search_ctx->ffsc_stopdirs_v) == TRUE)
4294 		break;
4295 
4296 	    /* cut of last dir */
4297 	    while (path_end > ff_search_ctx->ffsc_start_dir
4298 		    && *path_end == PATHSEP)
4299 		path_end--;
4300 	    while (path_end > ff_search_ctx->ffsc_start_dir
4301 		    && *(path_end-1) != PATHSEP)
4302 		path_end--;
4303 	    *path_end = 0;
4304 	    path_end--;
4305 
4306 	    if (*ff_search_ctx->ffsc_start_dir == 0)
4307 		break;
4308 
4309 	    STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
4310 	    add_pathsep(file_path);
4311 	    STRCAT(file_path, ff_search_ctx->ffsc_fix_path);
4312 
4313 	    /* create a new stack entry */
4314 	    sptr = ff_create_stack_element(file_path,
4315 		    ff_search_ctx->ffsc_wc_path, ff_search_ctx->ffsc_level, 0);
4316 	    if (sptr == NULL)
4317 		break;
4318 	    ff_push(sptr);
4319 	}
4320 	else
4321 	    break;
4322     }
4323 #endif
4324 
4325     vim_free(file_path);
4326     return NULL;
4327 }
4328 
4329 /*
4330  * Free the list of lists of visited files and directories
4331  * Can handle it if the passed search_context is NULL;
4332  */
4333     void
4334 vim_findfile_free_visited(search_ctx)
4335     void	*search_ctx;
4336 {
4337     if (search_ctx == NULL)
4338 	return;
4339 
4340     ff_search_ctx = (ff_search_ctx_T *)search_ctx;
4341 
4342     vim_findfile_free_visited_list(&ff_search_ctx->ffsc_visited_lists_list);
4343     vim_findfile_free_visited_list(&ff_search_ctx->ffsc_dir_visited_lists_list);
4344 }
4345 
4346     static void
4347 vim_findfile_free_visited_list(list_headp)
4348     ff_visited_list_hdr_T	**list_headp;
4349 {
4350     ff_visited_list_hdr_T *vp;
4351 
4352     while (*list_headp != NULL)
4353     {
4354 	vp = (*list_headp)->ffvl_next;
4355 	ff_free_visited_list((*list_headp)->ffvl_visited_list);
4356 
4357 	vim_free((*list_headp)->ffvl_filename);
4358 	vim_free(*list_headp);
4359 	*list_headp = vp;
4360     }
4361     *list_headp = NULL;
4362 }
4363 
4364     static void
4365 ff_free_visited_list(vl)
4366     ff_visited_T *vl;
4367 {
4368     ff_visited_T *vp;
4369 
4370     while (vl != NULL)
4371     {
4372 	vp = vl->ffv_next;
4373 #ifdef FEAT_PATH_EXTRA
4374 	vim_free(vl->ffv_wc_path);
4375 #endif
4376 	vim_free(vl);
4377 	vl = vp;
4378     }
4379     vl = NULL;
4380 }
4381 
4382 /*
4383  * Returns the already visited list for the given filename. If none is found it
4384  * allocates a new one.
4385  */
4386     static ff_visited_list_hdr_T*
4387 ff_get_visited_list(filename, list_headp)
4388     char_u			*filename;
4389     ff_visited_list_hdr_T	**list_headp;
4390 {
4391     ff_visited_list_hdr_T  *retptr = NULL;
4392 
4393     /* check if a visited list for the given filename exists */
4394     if (*list_headp != NULL)
4395     {
4396 	retptr = *list_headp;
4397 	while (retptr != NULL)
4398 	{
4399 	    if (fnamecmp(filename, retptr->ffvl_filename) == 0)
4400 	    {
4401 #ifdef FF_VERBOSE
4402 		if (p_verbose >= 5)
4403 		{
4404 		    /* always scroll up, don't overwrite */
4405 		    msg_scroll = TRUE;
4406 		    msg_str((char_u *)"ff_get_visited_list: FOUND list for %s",
4407 								    filename);
4408 		    /* don't overwrite this either */
4409 		    msg_puts((char_u *)"\n");
4410 		    cmdline_row = msg_row;
4411 		}
4412 #endif
4413 		return retptr;
4414 	    }
4415 	    retptr = retptr->ffvl_next;
4416 	}
4417     }
4418 
4419 #ifdef FF_VERBOSE
4420     if (p_verbose >= 5)
4421     {
4422 	/* always scroll up, don't overwrite */
4423 	msg_scroll = TRUE;
4424 	msg_str((char_u *)"ff_get_visited_list: new list for %s", filename);
4425 	/* don't overwrite this either */
4426 	msg_puts((char_u *)"\n");
4427 	cmdline_row = msg_row;
4428     }
4429 #endif
4430 
4431     /*
4432      * if we reach this we didn't find a list and we have to allocate new list
4433      */
4434     retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr));
4435     if (retptr == NULL)
4436 	return NULL;
4437 
4438     retptr->ffvl_visited_list = NULL;
4439     retptr->ffvl_filename = vim_strsave(filename);
4440     if (retptr->ffvl_filename == NULL)
4441     {
4442 	vim_free(retptr);
4443 	return NULL;
4444     }
4445     retptr->ffvl_next = *list_headp;
4446     *list_headp = retptr;
4447 
4448     return retptr;
4449 }
4450 
4451 #ifdef FEAT_PATH_EXTRA
4452 /*
4453  * check if two wildcard paths are equal. Returns TRUE or FALSE.
4454  * They are equal if:
4455  *  - both paths are NULL
4456  *  - they have the same length
4457  *  - char by char comparison is OK
4458  *  - the only differences are in the counters behind a '**', so
4459  *    '**\20' is equal to '**\24'
4460  */
4461     static int
4462 ff_wc_equal(s1, s2)
4463     char_u	*s1;
4464     char_u	*s2;
4465 {
4466     int		i;
4467 
4468     if (s1 == s2)
4469 	return TRUE;
4470 
4471     if (s1 == NULL || s2 == NULL)
4472 	return FALSE;
4473 
4474     if (STRLEN(s1) != STRLEN(s2))
4475 	return FAIL;
4476 
4477     for (i = 0; s1[i] != NUL && s2[i] != NUL; i++)
4478     {
4479 	if (s1[i] != s2[i]
4480 #ifdef CASE_INSENSITIVE_FILENAME
4481 		&& TOUPPER_LOC(s1[i]) != TOUPPER_LOC(s2[i])
4482 #endif
4483 		)
4484 	{
4485 	    if (i >= 2)
4486 		if (s1[i-1] == '*' && s1[i-2] == '*')
4487 		    continue;
4488 		else
4489 		    return FAIL;
4490 	    else
4491 		return FAIL;
4492 	}
4493     }
4494     return TRUE;
4495 }
4496 #endif
4497 
4498 /*
4499  * maintains the list of already visited files and dirs
4500  * returns FAIL if the given file/dir is already in the list
4501  * returns OK if it is newly added
4502  *
4503  * TODO: What to do on memory allocation problems?
4504  *	 -> return TRUE - Better the file is found several times instead of
4505  *	    never.
4506  */
4507     static int
4508 ff_check_visited(visited_list, fname
4509 #ifdef FEAT_PATH_EXTRA
4510 	, wc_path
4511 #endif
4512 	)
4513     ff_visited_T	**visited_list;
4514     char_u		*fname;
4515 #ifdef FEAT_PATH_EXTRA
4516     char_u		*wc_path;
4517 #endif
4518 {
4519     ff_visited_T	*vp;
4520 #ifdef UNIX
4521     struct stat		st;
4522     int			url = FALSE;
4523 #endif
4524 
4525     /* For an URL we only compare the name, otherwise we compare the
4526      * device/inode (unix) or the full path name (not Unix). */
4527     if (path_with_url(fname))
4528     {
4529 	STRNCPY(ff_expand_buffer, fname, MAXPATHL);
4530 #ifdef UNIX
4531 	url = TRUE;
4532 #endif
4533     }
4534     else
4535     {
4536 	ff_expand_buffer[0] = NUL;
4537 #ifdef UNIX
4538 	if (mch_stat((char *)fname, &st) < 0)
4539 #else
4540 	if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
4541 #endif
4542 	    return FAIL;
4543     }
4544 
4545     /* check against list of already visited files */
4546     for (vp = *visited_list; vp != NULL; vp = vp->ffv_next)
4547     {
4548 	if (
4549 #ifdef UNIX
4550 		!url
4551 		    ? (vp->ffv_dev == st.st_dev
4552 			&& vp->ffv_ino == st.st_ino)
4553 		    :
4554 #endif
4555 		fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0
4556 	   )
4557 	{
4558 #ifdef FEAT_PATH_EXTRA
4559 	    /* are the wildcard parts equal */
4560 	    if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
4561 #endif
4562 		/* already visited */
4563 		return FAIL;
4564 	}
4565     }
4566 
4567     /*
4568      * New file/dir.  Add it to the list of visited files/dirs.
4569      */
4570     vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T)
4571 						 + STRLEN(ff_expand_buffer)));
4572 
4573     if (vp != NULL)
4574     {
4575 #ifdef UNIX
4576 	if (!url)
4577 	{
4578 	    vp->ffv_ino = st.st_ino;
4579 	    vp->ffv_dev = st.st_dev;
4580 	    vp->ffv_fname[0] = NUL;
4581 	}
4582 	else
4583 	{
4584 	    vp->ffv_ino = 0;
4585 	    vp->ffv_dev = -1;
4586 #endif
4587 	    STRCPY(vp->ffv_fname, ff_expand_buffer);
4588 #ifdef UNIX
4589 	}
4590 #endif
4591 #ifdef FEAT_PATH_EXTRA
4592 	if (wc_path != NULL)
4593 	    vp->ffv_wc_path = vim_strsave(wc_path);
4594 	else
4595 	    vp->ffv_wc_path = NULL;
4596 #endif
4597 
4598 	vp->ffv_next = *visited_list;
4599 	*visited_list = vp;
4600     }
4601 
4602     return OK;
4603 }
4604 
4605 /*
4606  * create stack element from given path pieces
4607  */
4608     static ff_stack_T *
4609 ff_create_stack_element(fix_part,
4610 #ifdef FEAT_PATH_EXTRA
4611 	wc_part,
4612 #endif
4613 	level, star_star_empty)
4614     char_u	*fix_part;
4615 #ifdef FEAT_PATH_EXTRA
4616     char_u	*wc_part;
4617 #endif
4618     int		level;
4619     int		star_star_empty;
4620 {
4621     ff_stack_T	*new;
4622 
4623     new = (ff_stack_T *)alloc((unsigned)sizeof(ff_stack_T));
4624     if (new == NULL)
4625 	return NULL;
4626 
4627     new->ffs_prev	   = NULL;
4628     new->ffs_filearray	   = NULL;
4629     new->ffs_filearray_size = 0;
4630     new->ffs_filearray_cur  = 0;
4631     new->ffs_stage	   = 0;
4632     new->ffs_level	   = level;
4633     new->ffs_star_star_empty = star_star_empty;;
4634 
4635     /* the following saves NULL pointer checks in vim_findfile */
4636     if (fix_part == NULL)
4637 	fix_part = (char_u *)"";
4638     new->ffs_fix_path = vim_strsave(fix_part);
4639 
4640 #ifdef FEAT_PATH_EXTRA
4641     if (wc_part == NULL)
4642 	wc_part  = (char_u *)"";
4643     new->ffs_wc_path = vim_strsave(wc_part);
4644 #endif
4645 
4646     if (new->ffs_fix_path == NULL
4647 #ifdef FEAT_PATH_EXTRA
4648 	    || new->ffs_wc_path == NULL
4649 #endif
4650 	    )
4651     {
4652 	ff_free_stack_element(new);
4653 	new = NULL;
4654     }
4655 
4656     return new;
4657 }
4658 
4659 /*
4660  * push a dir on the directory stack
4661  */
4662     static void
4663 ff_push(ctx)
4664     ff_stack_T *ctx;
4665 {
4666     /* check for NULL pointer, not to return an error to the user, but
4667      * to prevent a crash
4668      */
4669     if (ctx != NULL)
4670     {
4671 	ctx->ffs_prev   = ff_search_ctx->ffsc_stack_ptr;
4672 	ff_search_ctx->ffsc_stack_ptr = ctx;
4673     }
4674 }
4675 
4676 /*
4677  * pop a dir from the directory stack
4678  * returns NULL if stack is empty
4679  */
4680     static ff_stack_T *
4681 ff_pop()
4682 {
4683     ff_stack_T  *sptr;
4684 
4685     sptr = ff_search_ctx->ffsc_stack_ptr;
4686     if (ff_search_ctx->ffsc_stack_ptr != NULL)
4687 	ff_search_ctx->ffsc_stack_ptr = ff_search_ctx->ffsc_stack_ptr->ffs_prev;
4688 
4689     return sptr;
4690 }
4691 
4692 /*
4693  * free the given stack element
4694  */
4695     static void
4696 ff_free_stack_element(ctx)
4697     ff_stack_T  *ctx;
4698 {
4699     /* vim_free handles possible NULL pointers */
4700     vim_free(ctx->ffs_fix_path);
4701 #ifdef FEAT_PATH_EXTRA
4702     vim_free(ctx->ffs_wc_path);
4703 #endif
4704 
4705     if (ctx->ffs_filearray != NULL)
4706 	FreeWild(ctx->ffs_filearray_size, ctx->ffs_filearray);
4707 
4708     vim_free(ctx);
4709 }
4710 
4711 /*
4712  * clear the search context
4713  */
4714     static void
4715 ff_clear()
4716 {
4717     ff_stack_T   *sptr;
4718 
4719     /* clear up stack */
4720     while ((sptr = ff_pop()) != NULL)
4721 	ff_free_stack_element(sptr);
4722 
4723     vim_free(ff_search_ctx->ffsc_file_to_search);
4724     vim_free(ff_search_ctx->ffsc_start_dir);
4725     vim_free(ff_search_ctx->ffsc_fix_path);
4726 #ifdef FEAT_PATH_EXTRA
4727     vim_free(ff_search_ctx->ffsc_wc_path);
4728 #endif
4729 
4730 #ifdef FEAT_PATH_EXTRA
4731     if (ff_search_ctx->ffsc_stopdirs_v != NULL)
4732     {
4733 	int  i = 0;
4734 
4735 	while (ff_search_ctx->ffsc_stopdirs_v[i] != NULL)
4736 	{
4737 	    vim_free(ff_search_ctx->ffsc_stopdirs_v[i]);
4738 	    i++;
4739 	}
4740 	vim_free(ff_search_ctx->ffsc_stopdirs_v);
4741     }
4742     ff_search_ctx->ffsc_stopdirs_v = NULL;
4743 #endif
4744 
4745     /* reset everything */
4746     ff_search_ctx->ffsc_file_to_search	= NULL;
4747     ff_search_ctx->ffsc_start_dir	= NULL;
4748     ff_search_ctx->ffsc_fix_path	= NULL;
4749 #ifdef FEAT_PATH_EXTRA
4750     ff_search_ctx->ffsc_wc_path		= NULL;
4751     ff_search_ctx->ffsc_level		= 0;
4752 #endif
4753 }
4754 
4755 #ifdef FEAT_PATH_EXTRA
4756 /*
4757  * check if the given path is in the stopdirs
4758  * returns TRUE if yes else FALSE
4759  */
4760     static int
4761 ff_path_in_stoplist(path, path_len, stopdirs_v)
4762     char_u	*path;
4763     int		path_len;
4764     char_u	**stopdirs_v;
4765 {
4766     int		i = 0;
4767 
4768     /* eat up trailing path separators, except the first */
4769     while (path_len > 1 && path[path_len - 1] == PATHSEP)
4770 	path_len--;
4771 
4772     /* if no path consider it as match */
4773     if (path_len == 0)
4774 	return TRUE;
4775 
4776     for (i = 0; stopdirs_v[i] != NULL; i++)
4777     {
4778 	if ((int)STRLEN(stopdirs_v[i]) > path_len)
4779 	{
4780 	    /* match for parent directory. So '/home' also matches
4781 	     * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
4782 	     * '/home/r' would also match '/home/rks'
4783 	     */
4784 	    if (fnamencmp(stopdirs_v[i], path, path_len) == 0
4785 		    && stopdirs_v[i][path_len] == PATHSEP)
4786 		return TRUE;
4787 	}
4788 	else
4789 	{
4790 	    if (fnamecmp(stopdirs_v[i], path) == 0)
4791 		return TRUE;
4792 	}
4793     }
4794     return FALSE;
4795 }
4796 #endif
4797 
4798 #if defined(FEAT_SEARCHPATH) || defined(PROTO)
4799 /*
4800  * Find the file name "ptr[len]" in the path.
4801  *
4802  * On the first call set the parameter 'first' to TRUE to initialize
4803  * the search.  For repeating calls to FALSE.
4804  *
4805  * Repeating calls will return other files called 'ptr[len]' from the path.
4806  *
4807  * Only on the first call 'ptr' and 'len' are used.  For repeating calls they
4808  * don't need valid values.
4809  *
4810  * If nothing found on the first call the option FNAME_MESS will issue the
4811  * message:
4812  *	    'Can't find file "<file>" in path'
4813  * On repeating calls:
4814  *	    'No more file "<file>" found in path'
4815  *
4816  * options:
4817  * FNAME_MESS	    give error message when not found
4818  *
4819  * Uses NameBuff[]!
4820  *
4821  * Returns an allocated string for the file name.  NULL for error.
4822  *
4823  */
4824     char_u *
4825 find_file_in_path(ptr, len, options, first, rel_fname)
4826     char_u	*ptr;		/* file name */
4827     int		len;		/* length of file name */
4828     int		options;
4829     int		first;		/* use count'th matching file name */
4830     char_u	*rel_fname;	/* file name searching relative to */
4831 {
4832     return find_file_in_path_option(ptr, len, options, first,
4833 	    *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
4834 	    FALSE, rel_fname);
4835 }
4836 
4837 /*
4838  * Find the directory name "ptr[len]" in the path.
4839  *
4840  * options:
4841  * FNAME_MESS	    give error message when not found
4842  *
4843  * Uses NameBuff[]!
4844  *
4845  * Returns an allocated string for the file name.  NULL for error.
4846  */
4847     char_u *
4848 find_directory_in_path(ptr, len, options, rel_fname)
4849     char_u	*ptr;		/* file name */
4850     int		len;		/* length of file name */
4851     int		options;
4852     char_u	*rel_fname;	/* file name searching relative to */
4853 {
4854     return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
4855 							     TRUE, rel_fname);
4856 }
4857 
4858     char_u *
4859 find_file_in_path_option(ptr, len, options, first, path_option, need_dir, rel_fname)
4860     char_u	*ptr;		/* file name */
4861     int		len;		/* length of file name */
4862     int		options;
4863     int		first;		/* use count'th matching file name */
4864     char_u	*path_option;	/* p_path or p_cdpath */
4865     int		need_dir;	/* looking for directory name */
4866     char_u	*rel_fname;	/* file name we are looking relative to. */
4867 {
4868     static void		*search_ctx = NULL;
4869     static char_u	*dir;
4870     static char_u	*file_to_find = NULL;
4871     static int		did_findfile_init = FALSE;
4872     char_u		save_char;
4873     char_u		*file_name = NULL;
4874     char_u		*buf = NULL;
4875     int			rel_to_curdir;
4876 #ifdef AMIGA
4877     struct Process	*proc = (struct Process *)FindTask(0L);
4878     APTR		save_winptr = proc->pr_WindowPtr;
4879 
4880     /* Avoid a requester here for a volume that doesn't exist. */
4881     proc->pr_WindowPtr = (APTR)-1L;
4882 #endif
4883 
4884     if (first == TRUE)
4885     {
4886 	/* copy file name into NameBuff, expanding environment variables */
4887 	save_char = ptr[len];
4888 	ptr[len] = NUL;
4889 	expand_env(ptr, NameBuff, MAXPATHL);
4890 	ptr[len] = save_char;
4891 
4892 	vim_free(file_to_find);
4893 	file_to_find = vim_strsave(NameBuff);
4894 	if (file_to_find == NULL)	/* out of memory */
4895 	{
4896 	    file_name = NULL;
4897 	    goto theend;
4898 	}
4899     }
4900 
4901     rel_to_curdir = (file_to_find[0] == '.'
4902 		    && (file_to_find[1] == NUL
4903 			|| vim_ispathsep(file_to_find[1])
4904 			|| (file_to_find[1] == '.'
4905 			    && (file_to_find[2] == NUL
4906 				|| vim_ispathsep(file_to_find[2])))));
4907     if (vim_isAbsName(file_to_find)
4908 	    /* "..", "../path", "." and "./path": don't use the path_option */
4909 	    || rel_to_curdir
4910 #if defined(MSWIN) || defined(MSDOS) || defined(OS2)
4911 	    /* handle "\tmp" as absolute path */
4912 	    || vim_ispathsep(file_to_find[0])
4913 	    /* handle "c:name" as absulute path */
4914 	    || (file_to_find[0] != NUL && file_to_find[1] == ':')
4915 #endif
4916 #ifdef AMIGA
4917 	    /* handle ":tmp" as absolute path */
4918 	    || file_to_find[0] == ':'
4919 #endif
4920        )
4921     {
4922 	/*
4923 	 * Absolute path, no need to use "path_option".
4924 	 * If this is not a first call, return NULL.  We already returned a
4925 	 * filename on the first call.
4926 	 */
4927 	if (first == TRUE)
4928 	{
4929 	    int		l;
4930 	    int		run;
4931 
4932 	    if (path_with_url(file_to_find))
4933 	    {
4934 		file_name = vim_strsave(file_to_find);
4935 		goto theend;
4936 	    }
4937 
4938 	    /* When FNAME_REL flag given first use the directory of the file.
4939 	     * Otherwise or when this fails use the current directory. */
4940 	    for (run = 1; run <= 2; ++run)
4941 	    {
4942 		l = (int)STRLEN(file_to_find);
4943 		if (run == 1
4944 			&& rel_to_curdir
4945 			&& (options & FNAME_REL)
4946 			&& rel_fname != NULL
4947 			&& STRLEN(rel_fname) + l < MAXPATHL)
4948 		{
4949 		    STRCPY(NameBuff, rel_fname);
4950 		    STRCPY(gettail(NameBuff), file_to_find);
4951 		    l = (int)STRLEN(NameBuff);
4952 		}
4953 		else
4954 		{
4955 		    STRCPY(NameBuff, file_to_find);
4956 		    run = 2;
4957 		}
4958 
4959 		/* When the file doesn't exist, try adding parts of
4960 		 * 'suffixesadd'. */
4961 		buf = curbuf->b_p_sua;
4962 		for (;;)
4963 		{
4964 		    if (
4965 #ifdef DJGPP
4966 			    /* "C:" by itself will fail for mch_getperm(),
4967 			     * assume it's always valid. */
4968 			    (need_dir && NameBuff[0] != NUL
4969 				  && NameBuff[1] == ':'
4970 				  && NameBuff[2] == NUL) ||
4971 #endif
4972 			    (mch_getperm(NameBuff) >= 0
4973 				       && (!need_dir || mch_isdir(NameBuff))))
4974 		    {
4975 			file_name = vim_strsave(NameBuff);
4976 			goto theend;
4977 		    }
4978 		    if (*buf == NUL)
4979 			break;
4980 		    copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
4981 		}
4982 	    }
4983 	}
4984     }
4985     else
4986     {
4987 	/*
4988 	 * Loop over all paths in the 'path' or 'cdpath' option.
4989 	 * When "first" is set, first setup to the start of the option.
4990 	 * Otherwise continue to find the next match.
4991 	 */
4992 	if (first == TRUE)
4993 	{
4994 	    /* vim_findfile_free_visited can handle a possible NULL pointer */
4995 	    vim_findfile_free_visited(search_ctx);
4996 	    dir = path_option;
4997 	    did_findfile_init = FALSE;
4998 	}
4999 
5000 	for (;;)
5001 	{
5002 	    if (did_findfile_init)
5003 	    {
5004 		ff_search_ctx->ffsc_need_dir = need_dir;
5005 		file_name = vim_findfile(search_ctx);
5006 		ff_search_ctx->ffsc_need_dir = FALSE;
5007 		if (file_name != NULL)
5008 		    break;
5009 
5010 		did_findfile_init = FALSE;
5011 	    }
5012 	    else
5013 	    {
5014 		char_u  *r_ptr;
5015 
5016 		if (dir == NULL || *dir == NUL)
5017 		{
5018 		    /* We searched all paths of the option, now we can
5019 		     * free the search context. */
5020 		    vim_findfile_cleanup(search_ctx);
5021 		    search_ctx = NULL;
5022 		    break;
5023 		}
5024 
5025 		if ((buf = alloc((int)(MAXPATHL))) == NULL)
5026 		    break;
5027 
5028 		/* copy next path */
5029 		buf[0] = 0;
5030 		copy_option_part(&dir, buf, MAXPATHL, " ,");
5031 
5032 #ifdef FEAT_PATH_EXTRA
5033 		/* get the stopdir string */
5034 		r_ptr = vim_findfile_stopdir(buf);
5035 #else
5036 		r_ptr = NULL;
5037 #endif
5038 		search_ctx = vim_findfile_init(buf, file_to_find, r_ptr, 100,
5039 				   FALSE, TRUE, search_ctx, FALSE, rel_fname);
5040 		if (search_ctx != NULL)
5041 		    did_findfile_init = TRUE;
5042 		vim_free(buf);
5043 	    }
5044 	}
5045     }
5046     if (file_name == NULL && (options & FNAME_MESS))
5047     {
5048 	if (first == TRUE)
5049 	{
5050 	    if (need_dir)
5051 		EMSG2(_("E344: Can't find directory \"%s\" in cdpath"),
5052 			file_to_find);
5053 	    else
5054 		EMSG2(_("E345: Can't find file \"%s\" in path"),
5055 			file_to_find);
5056 	}
5057 	else
5058 	{
5059 	    if (need_dir)
5060 		EMSG2(_("E346: No more directory \"%s\" found in cdpath"),
5061 			file_to_find);
5062 	    else
5063 		EMSG2(_("E347: No more file \"%s\" found in path"),
5064 			file_to_find);
5065 	}
5066     }
5067 
5068 theend:
5069 #ifdef AMIGA
5070     proc->pr_WindowPtr = save_winptr;
5071 #endif
5072     return file_name;
5073 }
5074 
5075 #endif /* FEAT_SEARCHPATH */
5076 
5077 /*
5078  * Change directory to "new_dir".  If FEAT_SEARCHPATH is defined, search
5079  * 'cdpath' for relative directory names, otherwise just mch_chdir().
5080  */
5081     int
5082 vim_chdir(new_dir)
5083     char_u	*new_dir;
5084 {
5085 #ifndef FEAT_SEARCHPATH
5086     return mch_chdir((char *)new_dir);
5087 #else
5088     char_u	*dir_name;
5089     int		r;
5090 
5091     dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
5092 						FNAME_MESS, curbuf->b_ffname);
5093     if (dir_name == NULL)
5094 	return -1;
5095     r = mch_chdir((char *)dir_name);
5096     vim_free(dir_name);
5097     return r;
5098 #endif
5099 }
5100 
5101 /*
5102  * Get user name from machine-specific function and cache it.
5103  * Returns the user name in "buf[len]".
5104  * Some systems are quite slow in obtaining the user name (Windows NT).
5105  * Returns OK or FAIL.
5106  */
5107     int
5108 get_user_name(buf, len)
5109     char_u	*buf;
5110     int		len;
5111 {
5112     static char_u	*name = NULL;
5113 
5114     if (name == NULL)
5115     {
5116 	if (mch_get_user_name(buf, len) == FAIL)
5117 	    return FAIL;
5118 	name = vim_strsave(buf);
5119     }
5120     else
5121 	STRNCPY(buf, name, len);
5122     return OK;
5123 }
5124 
5125 #ifndef HAVE_QSORT
5126 /*
5127  * Our own qsort(), for systems that don't have it.
5128  * It's simple and slow.  From the K&R C book.
5129  */
5130     void
5131 qsort(base, elm_count, elm_size, cmp)
5132     void	*base;
5133     size_t	elm_count;
5134     size_t	elm_size;
5135     int (*cmp) __ARGS((const void *, const void *));
5136 {
5137     char_u	*buf;
5138     char_u	*p1;
5139     char_u	*p2;
5140     int		i, j;
5141     int		gap;
5142 
5143     buf = alloc((unsigned)elm_size);
5144     if (buf == NULL)
5145 	return;
5146 
5147     for (gap = elm_count / 2; gap > 0; gap /= 2)
5148 	for (i = gap; i < elm_count; ++i)
5149 	    for (j = i - gap; j >= 0; j -= gap)
5150 	    {
5151 		/* Compare the elements. */
5152 		p1 = (char_u *)base + j * elm_size;
5153 		p2 = (char_u *)base + (j + gap) * elm_size;
5154 		if ((*cmp)((void *)p1, (void *)p2) <= 0)
5155 		    break;
5156 		/* Exchange the elemets. */
5157 		mch_memmove(buf, p1, elm_size);
5158 		mch_memmove(p1, p2, elm_size);
5159 		mch_memmove(p2, buf, elm_size);
5160 	    }
5161 
5162     vim_free(buf);
5163 }
5164 #endif
5165 
5166 #if defined(FEAT_EX_EXTRA) || defined(FEAT_CMDL_COMPL) || defined(PROTO)
5167 /*
5168  * Sort an array of strings.
5169  */
5170 static int
5171 #ifdef __BORLANDC__
5172 _RTLENTRYF
5173 #endif
5174 sort_compare __ARGS((const void *s1, const void *s2));
5175 
5176     static int
5177 #ifdef __BORLANDC__
5178 _RTLENTRYF
5179 #endif
5180 sort_compare(s1, s2)
5181     const void	*s1;
5182     const void	*s2;
5183 {
5184     return STRCMP(*(char **)s1, *(char **)s2);
5185 }
5186 
5187     void
5188 sort_strings(files, count)
5189     char_u	**files;
5190     int		count;
5191 {
5192     qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare);
5193 }
5194 #endif
5195 
5196 #if !defined(NO_EXPANDPATH) || defined(PROTO)
5197 /*
5198  * Compare path "p[]" to "q[]".
5199  * Return value like strcmp(p, q), but consider path separators.
5200  */
5201     int
5202 pathcmp(p, q)
5203     const char *p, *q;
5204 {
5205     int		i;
5206     const char	*s;
5207 
5208     for (i = 0; ; ++i)
5209     {
5210 	/* End of "p": check if "q" also ends or just has a slash. */
5211 	if (p[i] == NUL)
5212 	{
5213 	    if (q[i] == NUL)  /* full match */
5214 		return 0;
5215 	    s = q;
5216 	    break;
5217 	}
5218 
5219 	/* End of "q": check if "p" just has a slash. */
5220 	if (q[i] == NUL)
5221 	{
5222 	    s = p;
5223 	    break;
5224 	}
5225 
5226 	if (
5227 #ifdef CASE_INSENSITIVE_FILENAME
5228 		TOUPPER_LOC(p[i]) != TOUPPER_LOC(q[i])
5229 #else
5230 		p[i] != q[i]
5231 #endif
5232 #ifdef BACKSLASH_IN_FILENAME
5233 		/* consider '/' and '\\' to be equal */
5234 		&& !((p[i] == '/' && q[i] == '\\')
5235 		    || (p[i] == '\\' && q[i] == '/'))
5236 #endif
5237 		)
5238 	{
5239 	    if (vim_ispathsep(p[i]))
5240 		return -1;
5241 	    if (vim_ispathsep(q[i]))
5242 		return 1;
5243 	    return ((char_u *)p)[i] - ((char_u *)q)[i];	    /* no match */
5244 	}
5245     }
5246 
5247     /* ignore a trailing slash, but not "//" or ":/" */
5248     if (s[i + 1] == NUL && i > 0 && !vim_ispathsep(s[i - 1])
5249 #ifdef BACKSLASH_IN_FILENAME
5250 	    && (s[i] == '/' || s[i] == '\\')
5251 #else
5252 	    && s[i] == '/'
5253 #endif
5254        )
5255 	return 0;   /* match with trailing slash */
5256     if (s == q)
5257 	return -1;	    /* no match */
5258     return 1;
5259 }
5260 #endif
5261 
5262 #if defined(FEAT_PRINTER) || defined(PROTO)
5263 /*
5264  * Parse a list of options in the form
5265  * option:value,option:value,option:value
5266  *
5267  * "value" can start with a number which is parsed out, e.g.
5268  * margin:12mm
5269  *
5270  * Returns error message for an illegal option, NULL otherwise.
5271  * Only used for the printer at the moment...
5272  */
5273     char_u *
5274 parse_list_options(option_str, table, table_size)
5275     char_u		*option_str;
5276     option_table_T	*table;
5277     int			table_size;
5278 {
5279     char_u	*stringp;
5280     char_u	*colonp;
5281     char_u	*commap;
5282     char_u	*p;
5283     int		idx = 0;		/* init for GCC */
5284     int		len;
5285 
5286     for (idx = 0; idx < table_size; ++idx)
5287 	table[idx].present = FALSE;
5288 
5289     /*
5290      * Repeat for all comma separated parts.
5291      */
5292     stringp = option_str;
5293     while (*stringp)
5294     {
5295 	colonp = vim_strchr(stringp, ':');
5296 	if (colonp == NULL)
5297 	    return (char_u *)N_("E550: Missing colon");
5298 	commap = vim_strchr(stringp, ',');
5299 	if (commap == NULL)
5300 	    commap = option_str + STRLEN(option_str);
5301 
5302 	len = (int)(colonp - stringp);
5303 
5304 	for (idx = 0; idx < table_size; ++idx)
5305 	    if (STRNICMP(stringp, table[idx].name, len) == 0)
5306 		break;
5307 
5308 	if (idx == table_size)
5309 	    return (char_u *)N_("E551: Illegal component");
5310 
5311 	p = colonp + 1;
5312 	table[idx].present = TRUE;
5313 
5314 	if (table[idx].hasnum)
5315 	{
5316 	    if (!VIM_ISDIGIT(*p))
5317 		return (char_u *)N_("E552: digit expected");
5318 
5319 	    table[idx].number = getdigits(&p); /*advances p*/
5320 	}
5321 
5322 	table[idx].string = p;
5323 	table[idx].strlen = (int)(commap - p);
5324 
5325 	stringp = commap;
5326 	if (*stringp == ',')
5327 	    ++stringp;
5328     }
5329 
5330     return NULL;
5331 }
5332 
5333 
5334 #endif /*FEAT_PRINTER*/
5335 
5336 /*
5337  * The putenv() implementation below comes from the "screen" program.
5338  * Included with permission from Juergen Weigert.
5339  * See pty.c for the copyright notice.
5340  */
5341 
5342 /*
5343  *  putenv  --	put value into environment
5344  *
5345  *  Usage:  i = putenv (string)
5346  *    int i;
5347  *    char  *string;
5348  *
5349  *  where string is of the form <name>=<value>.
5350  *  Putenv returns 0 normally, -1 on error (not enough core for malloc).
5351  *
5352  *  Putenv may need to add a new name into the environment, or to
5353  *  associate a value longer than the current value with a particular
5354  *  name.  So, to make life simpler, putenv() copies your entire
5355  *  environment into the heap (i.e. malloc()) from the stack
5356  *  (i.e. where it resides when your process is initiated) the first
5357  *  time you call it.
5358  *
5359  *  (history removed, not very interesting.  See the "screen" sources.)
5360  */
5361 
5362 #if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
5363 
5364 #define EXTRASIZE 5		/* increment to add to env. size */
5365 
5366 static int  envsize = -1;	/* current size of environment */
5367 #ifndef MACOS_CLASSIC
5368 extern
5369 #endif
5370        char **environ;		/* the global which is your env. */
5371 
5372 static int  findenv __ARGS((char *name)); /* look for a name in the env. */
5373 static int  newenv __ARGS((void));	/* copy env. from stack to heap */
5374 static int  moreenv __ARGS((void));	/* incr. size of env. */
5375 
5376     int
5377 putenv(string)
5378     const char *string;
5379 {
5380     int	    i;
5381     char    *p;
5382 
5383     if (envsize < 0)
5384     {				/* first time putenv called */
5385 	if (newenv() < 0)	/* copy env. to heap */
5386 	    return -1;
5387     }
5388 
5389     i = findenv((char *)string); /* look for name in environment */
5390 
5391     if (i < 0)
5392     {				/* name must be added */
5393 	for (i = 0; environ[i]; i++);
5394 	if (i >= (envsize - 1))
5395 	{			/* need new slot */
5396 	    if (moreenv() < 0)
5397 		return -1;
5398 	}
5399 	p = (char *)alloc((unsigned)(strlen(string) + 1));
5400 	if (p == NULL)		/* not enough core */
5401 	    return -1;
5402 	environ[i + 1] = 0;	/* new end of env. */
5403     }
5404     else
5405     {				/* name already in env. */
5406 	p = vim_realloc(environ[i], strlen(string) + 1);
5407 	if (p == NULL)
5408 	    return -1;
5409     }
5410     sprintf(p, "%s", string);	/* copy into env. */
5411     environ[i] = p;
5412 
5413     return 0;
5414 }
5415 
5416     static int
5417 findenv(name)
5418     char *name;
5419 {
5420     char    *namechar, *envchar;
5421     int	    i, found;
5422 
5423     found = 0;
5424     for (i = 0; environ[i] && !found; i++)
5425     {
5426 	envchar = environ[i];
5427 	namechar = name;
5428 	while (*namechar && *namechar != '=' && (*namechar == *envchar))
5429 	{
5430 	    namechar++;
5431 	    envchar++;
5432 	}
5433 	found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
5434     }
5435     return found ? i - 1 : -1;
5436 }
5437 
5438     static int
5439 newenv()
5440 {
5441     char    **env, *elem;
5442     int	    i, esize;
5443 
5444 #ifdef MACOS
5445     /* for Mac a new, empty environment is created */
5446     i = 0;
5447 #else
5448     for (i = 0; environ[i]; i++)
5449 	;
5450 #endif
5451     esize = i + EXTRASIZE + 1;
5452     env = (char **)alloc((unsigned)(esize * sizeof (elem)));
5453     if (env == NULL)
5454 	return -1;
5455 
5456 #ifndef MACOS
5457     for (i = 0; environ[i]; i++)
5458     {
5459 	elem = (char *)alloc((unsigned)(strlen(environ[i]) + 1));
5460 	if (elem == NULL)
5461 	    return -1;
5462 	env[i] = elem;
5463 	strcpy(elem, environ[i]);
5464     }
5465 #endif
5466 
5467     env[i] = 0;
5468     environ = env;
5469     envsize = esize;
5470     return 0;
5471 }
5472 
5473     static int
5474 moreenv()
5475 {
5476     int	    esize;
5477     char    **env;
5478 
5479     esize = envsize + EXTRASIZE;
5480     env = (char **)vim_realloc((char *)environ, esize * sizeof (*env));
5481     if (env == 0)
5482 	return -1;
5483     environ = env;
5484     envsize = esize;
5485     return 0;
5486 }
5487 
5488 # ifdef USE_VIMPTY_GETENV
5489     char_u *
5490 vimpty_getenv(string)
5491     const char_u *string;
5492 {
5493     int i;
5494     char_u *p;
5495 
5496     if (envsize < 0)
5497 	return NULL;
5498 
5499     i = findenv((char *)string);
5500 
5501     if (i < 0)
5502 	return NULL;
5503 
5504     p = vim_strchr((char_u *)environ[i], '=');
5505     return (p + 1);
5506 }
5507 # endif
5508 
5509 #endif /* !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) */
5510 
5511 /*
5512  * Print a message with one string argument.
5513  * Make sure that the result fits in IObuff.
5514  * This is not in message.c, because the prototype for smsg() isn't used
5515  * there.
5516  */
5517     void
5518 msg_str(s, arg)
5519     char_u	*s;
5520     char_u	*arg;
5521 {
5522     int		ls = STRLEN(s);
5523     int		larg = STRLEN(arg);
5524 
5525     if (ls + larg >= IOSIZE)
5526 	smsg(s, arg + (ls + larg - IOSIZE));
5527     else
5528 	smsg(s, arg);
5529 }
5530