Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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