xref: /vim-8.2.3635/src/misc2.c (revision 7c25a7c0)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * misc2.c: Various functions.
12  */
13 #include "vim.h"
14 
15 static char_u	*username = NULL; // cached result of mch_get_user_name()
16 
17 static int coladvance2(pos_T *pos, int addspaces, int finetune, colnr_T wcol);
18 
19 /*
20  * Return TRUE if in the current mode we need to use virtual.
21  */
22     int
virtual_active(void)23 virtual_active(void)
24 {
25     unsigned int cur_ve_flags = get_ve_flags();
26 
27     // While an operator is being executed we return "virtual_op", because
28     // VIsual_active has already been reset, thus we can't check for "block"
29     // being used.
30     if (virtual_op != MAYBE)
31 	return virtual_op;
32     return (cur_ve_flags == VE_ALL
33 	    || ((cur_ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
34 	    || ((cur_ve_flags & VE_INSERT) && (State & INSERT)));
35 }
36 
37 /*
38  * Get the screen position of the cursor.
39  */
40     int
getviscol(void)41 getviscol(void)
42 {
43     colnr_T	x;
44 
45     getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
46     return (int)x;
47 }
48 
49 /*
50  * Go to column "wcol", and add/insert white space as necessary to get the
51  * cursor in that column.
52  * The caller must have saved the cursor line for undo!
53  */
54     int
coladvance_force(colnr_T wcol)55 coladvance_force(colnr_T wcol)
56 {
57     int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);
58 
59     if (wcol == MAXCOL)
60 	curwin->w_valid &= ~VALID_VIRTCOL;
61     else
62     {
63 	// Virtcol is valid
64 	curwin->w_valid |= VALID_VIRTCOL;
65 	curwin->w_virtcol = wcol;
66     }
67     return rc;
68 }
69 
70 /*
71  * Get the screen position of character col with a coladd in the cursor line.
72  */
73     int
getviscol2(colnr_T col,colnr_T coladd UNUSED)74 getviscol2(colnr_T col, colnr_T coladd UNUSED)
75 {
76     colnr_T	x;
77     pos_T	pos;
78 
79     pos.lnum = curwin->w_cursor.lnum;
80     pos.col = col;
81     pos.coladd = coladd;
82     getvvcol(curwin, &pos, &x, NULL, NULL);
83     return (int)x;
84 }
85 
86 /*
87  * Try to advance the Cursor to the specified screen column.
88  * If virtual editing: fine tune the cursor position.
89  * Note that all virtual positions off the end of a line should share
90  * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
91  * beginning at coladd 0.
92  *
93  * return OK if desired column is reached, FAIL if not
94  */
95     int
coladvance(colnr_T wcol)96 coladvance(colnr_T wcol)
97 {
98     int rc = getvpos(&curwin->w_cursor, wcol);
99 
100     if (wcol == MAXCOL || rc == FAIL)
101 	curwin->w_valid &= ~VALID_VIRTCOL;
102     else if (*ml_get_cursor() != TAB)
103     {
104 	// Virtcol is valid when not on a TAB
105 	curwin->w_valid |= VALID_VIRTCOL;
106 	curwin->w_virtcol = wcol;
107     }
108     return rc;
109 }
110 
111 /*
112  * Return in "pos" the position of the cursor advanced to screen column "wcol".
113  * return OK if desired column is reached, FAIL if not
114  */
115     int
getvpos(pos_T * pos,colnr_T wcol)116 getvpos(pos_T *pos, colnr_T wcol)
117 {
118     return coladvance2(pos, FALSE, virtual_active(), wcol);
119 }
120 
121     static int
coladvance2(pos_T * pos,int addspaces,int finetune,colnr_T wcol_arg)122 coladvance2(
123     pos_T	*pos,
124     int		addspaces,	// change the text to achieve our goal?
125     int		finetune,	// change char offset for the exact column
126     colnr_T	wcol_arg)	// column to move to (can be negative)
127 {
128     colnr_T	wcol = wcol_arg;
129     int		idx;
130     char_u	*ptr;
131     char_u	*line;
132     colnr_T	col = 0;
133     int		csize = 0;
134     int		one_more;
135 #ifdef FEAT_LINEBREAK
136     int		head = 0;
137 #endif
138 
139     one_more = (State & INSERT)
140 		    || restart_edit != NUL
141 		    || (VIsual_active && *p_sel != 'o')
142 		    || ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
143     line = ml_get_buf(curbuf, pos->lnum, FALSE);
144 
145     if (wcol >= MAXCOL)
146     {
147 	    idx = (int)STRLEN(line) - 1 + one_more;
148 	    col = wcol;
149 
150 	    if ((addspaces || finetune) && !VIsual_active)
151 	    {
152 		curwin->w_curswant = linetabsize(line) + one_more;
153 		if (curwin->w_curswant > 0)
154 		    --curwin->w_curswant;
155 	    }
156     }
157     else
158     {
159 	int width = curwin->w_width - win_col_off(curwin);
160 
161 	if (finetune
162 		&& curwin->w_p_wrap
163 		&& curwin->w_width != 0
164 		&& wcol >= (colnr_T)width
165 		&& width > 0)
166 	{
167 	    csize = linetabsize(line);
168 	    if (csize > 0)
169 		csize--;
170 
171 	    if (wcol / width > (colnr_T)csize / width
172 		    && ((State & INSERT) == 0 || (int)wcol > csize + 1))
173 	    {
174 		// In case of line wrapping don't move the cursor beyond the
175 		// right screen edge.  In Insert mode allow going just beyond
176 		// the last character (like what happens when typing and
177 		// reaching the right window edge).
178 		wcol = (csize / width + 1) * width - 1;
179 	    }
180 	}
181 
182 	ptr = line;
183 	while (col <= wcol && *ptr != NUL)
184 	{
185 	    // Count a tab for what it's worth (if list mode not on)
186 #ifdef FEAT_LINEBREAK
187 	    csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
188 	    MB_PTR_ADV(ptr);
189 #else
190 	    csize = lbr_chartabsize_adv(line, &ptr, col);
191 #endif
192 	    col += csize;
193 	}
194 	idx = (int)(ptr - line);
195 	/*
196 	 * Handle all the special cases.  The virtual_active() check
197 	 * is needed to ensure that a virtual position off the end of
198 	 * a line has the correct indexing.  The one_more comparison
199 	 * replaces an explicit add of one_more later on.
200 	 */
201 	if (col > wcol || (!virtual_active() && one_more == 0))
202 	{
203 	    idx -= 1;
204 # ifdef FEAT_LINEBREAK
205 	    // Don't count the chars from 'showbreak'.
206 	    csize -= head;
207 # endif
208 	    col -= csize;
209 	}
210 
211 	if (virtual_active()
212 		&& addspaces
213 		&& wcol >= 0
214 		&& ((col != wcol && col != wcol + 1) || csize > 1))
215 	{
216 	    // 'virtualedit' is set: The difference between wcol and col is
217 	    // filled with spaces.
218 
219 	    if (line[idx] == NUL)
220 	    {
221 		// Append spaces
222 		int	correct = wcol - col;
223 		char_u	*newline = alloc(idx + correct + 1);
224 		int	t;
225 
226 		if (newline == NULL)
227 		    return FAIL;
228 
229 		for (t = 0; t < idx; ++t)
230 		    newline[t] = line[t];
231 
232 		for (t = 0; t < correct; ++t)
233 		    newline[t + idx] = ' ';
234 
235 		newline[idx + correct] = NUL;
236 
237 		ml_replace(pos->lnum, newline, FALSE);
238 		changed_bytes(pos->lnum, (colnr_T)idx);
239 		idx += correct;
240 		col = wcol;
241 	    }
242 	    else
243 	    {
244 		// Break a tab
245 		int	linelen = (int)STRLEN(line);
246 		int	correct = wcol - col - csize + 1; // negative!!
247 		char_u	*newline;
248 		int	t, s = 0;
249 		int	v;
250 
251 		if (-correct > csize)
252 		    return FAIL;
253 
254 		newline = alloc(linelen + csize);
255 		if (newline == NULL)
256 		    return FAIL;
257 
258 		for (t = 0; t < linelen; t++)
259 		{
260 		    if (t != idx)
261 			newline[s++] = line[t];
262 		    else
263 			for (v = 0; v < csize; v++)
264 			    newline[s++] = ' ';
265 		}
266 
267 		newline[linelen + csize - 1] = NUL;
268 
269 		ml_replace(pos->lnum, newline, FALSE);
270 		changed_bytes(pos->lnum, idx);
271 		idx += (csize - 1 + correct);
272 		col += correct;
273 	    }
274 	}
275     }
276 
277     if (idx < 0)
278 	pos->col = 0;
279     else
280 	pos->col = idx;
281 
282     pos->coladd = 0;
283 
284     if (finetune)
285     {
286 	if (wcol == MAXCOL)
287 	{
288 	    // The width of the last character is used to set coladd.
289 	    if (!one_more)
290 	    {
291 		colnr_T	    scol, ecol;
292 
293 		getvcol(curwin, pos, &scol, NULL, &ecol);
294 		pos->coladd = ecol - scol;
295 	    }
296 	}
297 	else
298 	{
299 	    int b = (int)wcol - (int)col;
300 
301 	    // The difference between wcol and col is used to set coladd.
302 	    if (b > 0 && b < (MAXCOL - 2 * curwin->w_width))
303 		pos->coladd = b;
304 
305 	    col += b;
306 	}
307     }
308 
309     // prevent from moving onto a trail byte
310     if (has_mbyte)
311 	mb_adjustpos(curbuf, pos);
312 
313     if (wcol < 0 || col < wcol)
314 	return FAIL;
315     return OK;
316 }
317 
318 /*
319  * Increment the cursor position.  See inc() for return values.
320  */
321     int
inc_cursor(void)322 inc_cursor(void)
323 {
324     return inc(&curwin->w_cursor);
325 }
326 
327 /*
328  * Increment the line pointer "lp" crossing line boundaries as necessary.
329  * Return 1 when going to the next line.
330  * Return 2 when moving forward onto a NUL at the end of the line).
331  * Return -1 when at the end of file.
332  * Return 0 otherwise.
333  */
334     int
inc(pos_T * lp)335 inc(pos_T *lp)
336 {
337     char_u  *p;
338 
339     // when searching position may be set to end of a line
340     if (lp->col != MAXCOL)
341     {
342 	p = ml_get_pos(lp);
343 	if (*p != NUL)	// still within line, move to next char (may be NUL)
344 	{
345 	    if (has_mbyte)
346 	    {
347 		int l = (*mb_ptr2len)(p);
348 
349 		lp->col += l;
350 		return ((p[l] != NUL) ? 0 : 2);
351 	    }
352 	    lp->col++;
353 	    lp->coladd = 0;
354 	    return ((p[1] != NUL) ? 0 : 2);
355 	}
356     }
357     if (lp->lnum != curbuf->b_ml.ml_line_count)     // there is a next line
358     {
359 	lp->col = 0;
360 	lp->lnum++;
361 	lp->coladd = 0;
362 	return 1;
363     }
364     return -1;
365 }
366 
367 /*
368  * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
369  */
370     int
incl(pos_T * lp)371 incl(pos_T *lp)
372 {
373     int	    r;
374 
375     if ((r = inc(lp)) >= 1 && lp->col)
376 	r = inc(lp);
377     return r;
378 }
379 
380 /*
381  * dec(p)
382  *
383  * Decrement the line pointer 'p' crossing line boundaries as necessary.
384  * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
385  */
386     int
dec_cursor(void)387 dec_cursor(void)
388 {
389     return dec(&curwin->w_cursor);
390 }
391 
392     int
dec(pos_T * lp)393 dec(pos_T *lp)
394 {
395     char_u	*p;
396 
397     lp->coladd = 0;
398     if (lp->col == MAXCOL)
399     {
400 	// past end of line
401 	p = ml_get(lp->lnum);
402 	lp->col = (colnr_T)STRLEN(p);
403 	if (has_mbyte)
404 	    lp->col -= (*mb_head_off)(p, p + lp->col);
405 	return 0;
406     }
407 
408     if (lp->col > 0)
409     {
410 	// still within line
411 	lp->col--;
412 	if (has_mbyte)
413 	{
414 	    p = ml_get(lp->lnum);
415 	    lp->col -= (*mb_head_off)(p, p + lp->col);
416 	}
417 	return 0;
418     }
419 
420     if (lp->lnum > 1)
421     {
422 	// there is a prior line
423 	lp->lnum--;
424 	p = ml_get(lp->lnum);
425 	lp->col = (colnr_T)STRLEN(p);
426 	if (has_mbyte)
427 	    lp->col -= (*mb_head_off)(p, p + lp->col);
428 	return 1;
429     }
430 
431     // at start of file
432     return -1;
433 }
434 
435 /*
436  * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
437  */
438     int
decl(pos_T * lp)439 decl(pos_T *lp)
440 {
441     int	    r;
442 
443     if ((r = dec(lp)) == 1 && lp->col)
444 	r = dec(lp);
445     return r;
446 }
447 
448 /*
449  * Get the line number relative to the current cursor position, i.e. the
450  * difference between line number and cursor position. Only look for lines that
451  * can be visible, folded lines don't count.
452  */
453     linenr_T
get_cursor_rel_lnum(win_T * wp,linenr_T lnum)454 get_cursor_rel_lnum(
455     win_T	*wp,
456     linenr_T	lnum)		    // line number to get the result for
457 {
458     linenr_T	cursor = wp->w_cursor.lnum;
459     linenr_T	retval = 0;
460 
461 #ifdef FEAT_FOLDING
462     if (hasAnyFolding(wp))
463     {
464 	if (lnum > cursor)
465 	{
466 	    while (lnum > cursor)
467 	    {
468 		(void)hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
469 		// if lnum and cursor are in the same fold,
470 		// now lnum <= cursor
471 		if (lnum > cursor)
472 		    retval++;
473 		lnum--;
474 	    }
475 	}
476 	else if (lnum < cursor)
477 	{
478 	    while (lnum < cursor)
479 	    {
480 		(void)hasFoldingWin(wp, lnum, NULL, &lnum, TRUE, NULL);
481 		// if lnum and cursor are in the same fold,
482 		// now lnum >= cursor
483 		if (lnum < cursor)
484 		    retval--;
485 		lnum++;
486 	    }
487 	}
488 	// else if (lnum == cursor)
489 	//     retval = 0;
490     }
491     else
492 #endif
493 	retval = lnum - cursor;
494 
495     return retval;
496 }
497 
498 /*
499  * Make sure "pos.lnum" and "pos.col" are valid in "buf".
500  * This allows for the col to be on the NUL byte.
501  */
502     void
check_pos(buf_T * buf,pos_T * pos)503 check_pos(buf_T *buf, pos_T *pos)
504 {
505     char_u *line;
506     colnr_T len;
507 
508     if (pos->lnum > buf->b_ml.ml_line_count)
509 	pos->lnum = buf->b_ml.ml_line_count;
510 
511     if (pos->col > 0)
512     {
513 	line = ml_get_buf(buf, pos->lnum, FALSE);
514 	len = (colnr_T)STRLEN(line);
515 	if (pos->col > len)
516 	    pos->col = len;
517     }
518 }
519 
520 /*
521  * Make sure curwin->w_cursor.lnum is valid.
522  */
523     void
check_cursor_lnum(void)524 check_cursor_lnum(void)
525 {
526     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
527     {
528 #ifdef FEAT_FOLDING
529 	// If there is a closed fold at the end of the file, put the cursor in
530 	// its first line.  Otherwise in the last line.
531 	if (!hasFolding(curbuf->b_ml.ml_line_count,
532 						&curwin->w_cursor.lnum, NULL))
533 #endif
534 	    curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
535     }
536     if (curwin->w_cursor.lnum <= 0)
537 	curwin->w_cursor.lnum = 1;
538 }
539 
540 /*
541  * Make sure curwin->w_cursor.col is valid.
542  */
543     void
check_cursor_col(void)544 check_cursor_col(void)
545 {
546     check_cursor_col_win(curwin);
547 }
548 
549 /*
550  * Make sure win->w_cursor.col is valid.
551  */
552     void
check_cursor_col_win(win_T * win)553 check_cursor_col_win(win_T *win)
554 {
555     colnr_T      len;
556     colnr_T      oldcol = win->w_cursor.col;
557     colnr_T      oldcoladd = win->w_cursor.col + win->w_cursor.coladd;
558     unsigned int cur_ve_flags = get_ve_flags();
559 
560     len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE));
561     if (len == 0)
562 	win->w_cursor.col = 0;
563     else if (win->w_cursor.col >= len)
564     {
565 	// Allow cursor past end-of-line when:
566 	// - in Insert mode or restarting Insert mode
567 	// - in Visual mode and 'selection' isn't "old"
568 	// - 'virtualedit' is set
569 	if ((State & INSERT) || restart_edit
570 		|| (VIsual_active && *p_sel != 'o')
571 		|| (cur_ve_flags & VE_ONEMORE)
572 		|| virtual_active())
573 	    win->w_cursor.col = len;
574 	else
575 	{
576 	    win->w_cursor.col = len - 1;
577 	    // Move the cursor to the head byte.
578 	    if (has_mbyte)
579 		mb_adjustpos(win->w_buffer, &win->w_cursor);
580 	}
581     }
582     else if (win->w_cursor.col < 0)
583 	win->w_cursor.col = 0;
584 
585     // If virtual editing is on, we can leave the cursor on the old position,
586     // only we must set it to virtual.  But don't do it when at the end of the
587     // line.
588     if (oldcol == MAXCOL)
589 	win->w_cursor.coladd = 0;
590     else if (cur_ve_flags == VE_ALL)
591     {
592 	if (oldcoladd > win->w_cursor.col)
593 	{
594 	    win->w_cursor.coladd = oldcoladd - win->w_cursor.col;
595 
596 	    // Make sure that coladd is not more than the char width.
597 	    // Not for the last character, coladd is then used when the cursor
598 	    // is actually after the last character.
599 	    if (win->w_cursor.col + 1 < len && win->w_cursor.coladd > 0)
600 	    {
601 		int cs, ce;
602 
603 		getvcol(win, &win->w_cursor, &cs, NULL, &ce);
604 		if (win->w_cursor.coladd > ce - cs)
605 		    win->w_cursor.coladd = ce - cs;
606 	    }
607 	}
608 	else
609 	    // avoid weird number when there is a miscalculation or overflow
610 	    win->w_cursor.coladd = 0;
611     }
612 }
613 
614 /*
615  * make sure curwin->w_cursor in on a valid character
616  */
617     void
check_cursor(void)618 check_cursor(void)
619 {
620     check_cursor_lnum();
621     check_cursor_col();
622 }
623 
624 #if defined(FEAT_TEXTOBJ) || defined(PROTO)
625 /*
626  * Make sure curwin->w_cursor is not on the NUL at the end of the line.
627  * Allow it when in Visual mode and 'selection' is not "old".
628  */
629     void
adjust_cursor_col(void)630 adjust_cursor_col(void)
631 {
632     if (curwin->w_cursor.col > 0
633 	    && (!VIsual_active || *p_sel == 'o')
634 	    && gchar_cursor() == NUL)
635 	--curwin->w_cursor.col;
636 }
637 #endif
638 
639 /*
640  * When curwin->w_leftcol has changed, adjust the cursor position.
641  * Return TRUE if the cursor was moved.
642  */
643     int
leftcol_changed(void)644 leftcol_changed(void)
645 {
646     long	lastcol;
647     colnr_T	s, e;
648     int		retval = FALSE;
649     long        siso = get_sidescrolloff_value();
650 
651     changed_cline_bef_curs();
652     lastcol = curwin->w_leftcol + curwin->w_width - curwin_col_off() - 1;
653     validate_virtcol();
654 
655     /*
656      * If the cursor is right or left of the screen, move it to last or first
657      * character.
658      */
659     if (curwin->w_virtcol > (colnr_T)(lastcol - siso))
660     {
661 	retval = TRUE;
662 	coladvance((colnr_T)(lastcol - siso));
663     }
664     else if (curwin->w_virtcol < curwin->w_leftcol + siso)
665     {
666 	retval = TRUE;
667 	(void)coladvance((colnr_T)(curwin->w_leftcol + siso));
668     }
669 
670     /*
671      * If the start of the character under the cursor is not on the screen,
672      * advance the cursor one more char.  If this fails (last char of the
673      * line) adjust the scrolling.
674      */
675     getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
676     if (e > (colnr_T)lastcol)
677     {
678 	retval = TRUE;
679 	coladvance(s - 1);
680     }
681     else if (s < curwin->w_leftcol)
682     {
683 	retval = TRUE;
684 	if (coladvance(e + 1) == FAIL)	// there isn't another character
685 	{
686 	    curwin->w_leftcol = s;	// adjust w_leftcol instead
687 	    changed_cline_bef_curs();
688 	}
689     }
690 
691     if (retval)
692 	curwin->w_set_curswant = TRUE;
693     redraw_later(NOT_VALID);
694     return retval;
695 }
696 
697 /*
698  * Isolate one part of a string option where parts are separated with
699  * "sep_chars".
700  * The part is copied into "buf[maxlen]".
701  * "*option" is advanced to the next part.
702  * The length is returned.
703  */
704     int
copy_option_part(char_u ** option,char_u * buf,int maxlen,char * sep_chars)705 copy_option_part(
706     char_u	**option,
707     char_u	*buf,
708     int		maxlen,
709     char	*sep_chars)
710 {
711     int	    len = 0;
712     char_u  *p = *option;
713 
714     // skip '.' at start of option part, for 'suffixes'
715     if (*p == '.')
716 	buf[len++] = *p++;
717     while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL)
718     {
719 	/*
720 	 * Skip backslash before a separator character and space.
721 	 */
722 	if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
723 	    ++p;
724 	if (len < maxlen - 1)
725 	    buf[len++] = *p;
726 	++p;
727     }
728     buf[len] = NUL;
729 
730     if (*p != NUL && *p != ',')	// skip non-standard separator
731 	++p;
732     p = skip_to_option_part(p);	// p points to next file name
733 
734     *option = p;
735     return len;
736 }
737 
738 #ifndef HAVE_MEMSET
739     void *
vim_memset(void * ptr,int c,size_t size)740 vim_memset(void *ptr, int c, size_t size)
741 {
742     char *p = ptr;
743 
744     while (size-- > 0)
745 	*p++ = c;
746     return ptr;
747 }
748 #endif
749 
750 /*
751  * Vim has its own isspace() function, because on some machines isspace()
752  * can't handle characters above 128.
753  */
754     int
vim_isspace(int x)755 vim_isspace(int x)
756 {
757     return ((x >= 9 && x <= 13) || x == ' ');
758 }
759 
760 /************************************************************************
761  * functions that use lookup tables for various things, generally to do with
762  * special key codes.
763  */
764 
765 /*
766  * Some useful tables.
767  */
768 
769 static struct modmasktable
770 {
771     short	mod_mask;	// Bit-mask for particular key modifier
772     short	mod_flag;	// Bit(s) for particular key modifier
773     char_u	name;		// Single letter name of modifier
774 } mod_mask_table[] =
775 {
776     {MOD_MASK_ALT,		MOD_MASK_ALT,		(char_u)'M'},
777     {MOD_MASK_META,		MOD_MASK_META,		(char_u)'T'},
778     {MOD_MASK_CTRL,		MOD_MASK_CTRL,		(char_u)'C'},
779     {MOD_MASK_SHIFT,		MOD_MASK_SHIFT,		(char_u)'S'},
780     {MOD_MASK_MULTI_CLICK,	MOD_MASK_2CLICK,	(char_u)'2'},
781     {MOD_MASK_MULTI_CLICK,	MOD_MASK_3CLICK,	(char_u)'3'},
782     {MOD_MASK_MULTI_CLICK,	MOD_MASK_4CLICK,	(char_u)'4'},
783 #ifdef MACOS_X
784     {MOD_MASK_CMD,		MOD_MASK_CMD,		(char_u)'D'},
785 #endif
786     // 'A' must be the last one
787     {MOD_MASK_ALT,		MOD_MASK_ALT,		(char_u)'A'},
788     {0, 0, NUL}
789     // NOTE: when adding an entry, update MAX_KEY_NAME_LEN!
790 };
791 
792 /*
793  * Shifted key terminal codes and their unshifted equivalent.
794  * Don't add mouse codes here, they are handled separately!
795  */
796 #define MOD_KEYS_ENTRY_SIZE 5
797 
798 static char_u modifier_keys_table[] =
799 {
800 //  mod mask	    with modifier		without modifier
801     MOD_MASK_SHIFT, '&', '9',			'@', '1',	// begin
802     MOD_MASK_SHIFT, '&', '0',			'@', '2',	// cancel
803     MOD_MASK_SHIFT, '*', '1',			'@', '4',	// command
804     MOD_MASK_SHIFT, '*', '2',			'@', '5',	// copy
805     MOD_MASK_SHIFT, '*', '3',			'@', '6',	// create
806     MOD_MASK_SHIFT, '*', '4',			'k', 'D',	// delete char
807     MOD_MASK_SHIFT, '*', '5',			'k', 'L',	// delete line
808     MOD_MASK_SHIFT, '*', '7',			'@', '7',	// end
809     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_END,	'@', '7',	// end
810     MOD_MASK_SHIFT, '*', '9',			'@', '9',	// exit
811     MOD_MASK_SHIFT, '*', '0',			'@', '0',	// find
812     MOD_MASK_SHIFT, '#', '1',			'%', '1',	// help
813     MOD_MASK_SHIFT, '#', '2',			'k', 'h',	// home
814     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_HOME,	'k', 'h',	// home
815     MOD_MASK_SHIFT, '#', '3',			'k', 'I',	// insert
816     MOD_MASK_SHIFT, '#', '4',			'k', 'l',	// left arrow
817     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_LEFT,	'k', 'l',	// left arrow
818     MOD_MASK_SHIFT, '%', 'a',			'%', '3',	// message
819     MOD_MASK_SHIFT, '%', 'b',			'%', '4',	// move
820     MOD_MASK_SHIFT, '%', 'c',			'%', '5',	// next
821     MOD_MASK_SHIFT, '%', 'd',			'%', '7',	// options
822     MOD_MASK_SHIFT, '%', 'e',			'%', '8',	// previous
823     MOD_MASK_SHIFT, '%', 'f',			'%', '9',	// print
824     MOD_MASK_SHIFT, '%', 'g',			'%', '0',	// redo
825     MOD_MASK_SHIFT, '%', 'h',			'&', '3',	// replace
826     MOD_MASK_SHIFT, '%', 'i',			'k', 'r',	// right arr.
827     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_RIGHT,	'k', 'r',	// right arr.
828     MOD_MASK_SHIFT, '%', 'j',			'&', '5',	// resume
829     MOD_MASK_SHIFT, '!', '1',			'&', '6',	// save
830     MOD_MASK_SHIFT, '!', '2',			'&', '7',	// suspend
831     MOD_MASK_SHIFT, '!', '3',			'&', '8',	// undo
832     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP,	'k', 'u',	// up arrow
833     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN,	'k', 'd',	// down arrow
834 
835 								// vt100 F1
836     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1,	KS_EXTRA, (int)KE_XF1,
837     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2,	KS_EXTRA, (int)KE_XF2,
838     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3,	KS_EXTRA, (int)KE_XF3,
839     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4,	KS_EXTRA, (int)KE_XF4,
840 
841     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1,	'k', '1',	// F1
842     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2,	'k', '2',
843     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3,	'k', '3',
844     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4,	'k', '4',
845     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5,	'k', '5',
846     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6,	'k', '6',
847     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7,	'k', '7',
848     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8,	'k', '8',
849     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9,	'k', '9',
850     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10,	'k', ';',	// F10
851 
852     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11,	'F', '1',
853     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12,	'F', '2',
854     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13,	'F', '3',
855     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14,	'F', '4',
856     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15,	'F', '5',
857     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16,	'F', '6',
858     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17,	'F', '7',
859     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18,	'F', '8',
860     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19,	'F', '9',
861     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20,	'F', 'A',
862 
863     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21,	'F', 'B',
864     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22,	'F', 'C',
865     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23,	'F', 'D',
866     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24,	'F', 'E',
867     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25,	'F', 'F',
868     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26,	'F', 'G',
869     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27,	'F', 'H',
870     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28,	'F', 'I',
871     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29,	'F', 'J',
872     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30,	'F', 'K',
873 
874     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31,	'F', 'L',
875     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32,	'F', 'M',
876     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33,	'F', 'N',
877     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34,	'F', 'O',
878     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35,	'F', 'P',
879     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36,	'F', 'Q',
880     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37,	'F', 'R',
881 
882 							    // TAB pseudo code
883     MOD_MASK_SHIFT, 'k', 'B',			KS_EXTRA, (int)KE_TAB,
884 
885     NUL
886 };
887 
888 static struct key_name_entry
889 {
890     int	    key;	// Special key code or ascii value
891     char_u  *name;	// Name of key
892 } key_names_table[] =
893 {
894     {' ',		(char_u *)"Space"},
895     {TAB,		(char_u *)"Tab"},
896     {K_TAB,		(char_u *)"Tab"},
897     {NL,		(char_u *)"NL"},
898     {NL,		(char_u *)"NewLine"},	// Alternative name
899     {NL,		(char_u *)"LineFeed"},	// Alternative name
900     {NL,		(char_u *)"LF"},	// Alternative name
901     {CAR,		(char_u *)"CR"},
902     {CAR,		(char_u *)"Return"},	// Alternative name
903     {CAR,		(char_u *)"Enter"},	// Alternative name
904     {K_BS,		(char_u *)"BS"},
905     {K_BS,		(char_u *)"BackSpace"},	// Alternative name
906     {ESC,		(char_u *)"Esc"},
907     {CSI,		(char_u *)"CSI"},
908     {K_CSI,		(char_u *)"xCSI"},
909     {'|',		(char_u *)"Bar"},
910     {'\\',		(char_u *)"Bslash"},
911     {K_DEL,		(char_u *)"Del"},
912     {K_DEL,		(char_u *)"Delete"},	// Alternative name
913     {K_KDEL,		(char_u *)"kDel"},
914     {K_UP,		(char_u *)"Up"},
915     {K_DOWN,		(char_u *)"Down"},
916     {K_LEFT,		(char_u *)"Left"},
917     {K_RIGHT,		(char_u *)"Right"},
918     {K_XUP,		(char_u *)"xUp"},
919     {K_XDOWN,		(char_u *)"xDown"},
920     {K_XLEFT,		(char_u *)"xLeft"},
921     {K_XRIGHT,		(char_u *)"xRight"},
922     {K_PS,		(char_u *)"PasteStart"},
923     {K_PE,		(char_u *)"PasteEnd"},
924 
925     {K_F1,		(char_u *)"F1"},
926     {K_F2,		(char_u *)"F2"},
927     {K_F3,		(char_u *)"F3"},
928     {K_F4,		(char_u *)"F4"},
929     {K_F5,		(char_u *)"F5"},
930     {K_F6,		(char_u *)"F6"},
931     {K_F7,		(char_u *)"F7"},
932     {K_F8,		(char_u *)"F8"},
933     {K_F9,		(char_u *)"F9"},
934     {K_F10,		(char_u *)"F10"},
935 
936     {K_F11,		(char_u *)"F11"},
937     {K_F12,		(char_u *)"F12"},
938     {K_F13,		(char_u *)"F13"},
939     {K_F14,		(char_u *)"F14"},
940     {K_F15,		(char_u *)"F15"},
941     {K_F16,		(char_u *)"F16"},
942     {K_F17,		(char_u *)"F17"},
943     {K_F18,		(char_u *)"F18"},
944     {K_F19,		(char_u *)"F19"},
945     {K_F20,		(char_u *)"F20"},
946 
947     {K_F21,		(char_u *)"F21"},
948     {K_F22,		(char_u *)"F22"},
949     {K_F23,		(char_u *)"F23"},
950     {K_F24,		(char_u *)"F24"},
951     {K_F25,		(char_u *)"F25"},
952     {K_F26,		(char_u *)"F26"},
953     {K_F27,		(char_u *)"F27"},
954     {K_F28,		(char_u *)"F28"},
955     {K_F29,		(char_u *)"F29"},
956     {K_F30,		(char_u *)"F30"},
957 
958     {K_F31,		(char_u *)"F31"},
959     {K_F32,		(char_u *)"F32"},
960     {K_F33,		(char_u *)"F33"},
961     {K_F34,		(char_u *)"F34"},
962     {K_F35,		(char_u *)"F35"},
963     {K_F36,		(char_u *)"F36"},
964     {K_F37,		(char_u *)"F37"},
965 
966     {K_XF1,		(char_u *)"xF1"},
967     {K_XF2,		(char_u *)"xF2"},
968     {K_XF3,		(char_u *)"xF3"},
969     {K_XF4,		(char_u *)"xF4"},
970 
971     {K_HELP,		(char_u *)"Help"},
972     {K_UNDO,		(char_u *)"Undo"},
973     {K_INS,		(char_u *)"Insert"},
974     {K_INS,		(char_u *)"Ins"},	// Alternative name
975     {K_KINS,		(char_u *)"kInsert"},
976     {K_HOME,		(char_u *)"Home"},
977     {K_KHOME,		(char_u *)"kHome"},
978     {K_XHOME,		(char_u *)"xHome"},
979     {K_ZHOME,		(char_u *)"zHome"},
980     {K_END,		(char_u *)"End"},
981     {K_KEND,		(char_u *)"kEnd"},
982     {K_XEND,		(char_u *)"xEnd"},
983     {K_ZEND,		(char_u *)"zEnd"},
984     {K_PAGEUP,		(char_u *)"PageUp"},
985     {K_PAGEDOWN,	(char_u *)"PageDown"},
986     {K_KPAGEUP,		(char_u *)"kPageUp"},
987     {K_KPAGEDOWN,	(char_u *)"kPageDown"},
988 
989     {K_KPLUS,		(char_u *)"kPlus"},
990     {K_KMINUS,		(char_u *)"kMinus"},
991     {K_KDIVIDE,		(char_u *)"kDivide"},
992     {K_KMULTIPLY,	(char_u *)"kMultiply"},
993     {K_KENTER,		(char_u *)"kEnter"},
994     {K_KPOINT,		(char_u *)"kPoint"},
995 
996     {K_K0,		(char_u *)"k0"},
997     {K_K1,		(char_u *)"k1"},
998     {K_K2,		(char_u *)"k2"},
999     {K_K3,		(char_u *)"k3"},
1000     {K_K4,		(char_u *)"k4"},
1001     {K_K5,		(char_u *)"k5"},
1002     {K_K6,		(char_u *)"k6"},
1003     {K_K7,		(char_u *)"k7"},
1004     {K_K8,		(char_u *)"k8"},
1005     {K_K9,		(char_u *)"k9"},
1006 
1007     {'<',		(char_u *)"lt"},
1008 
1009     {K_MOUSE,		(char_u *)"Mouse"},
1010 #ifdef FEAT_MOUSE_NET
1011     {K_NETTERM_MOUSE,	(char_u *)"NetMouse"},
1012 #endif
1013 #ifdef FEAT_MOUSE_DEC
1014     {K_DEC_MOUSE,	(char_u *)"DecMouse"},
1015 #endif
1016 #ifdef FEAT_MOUSE_JSB
1017     {K_JSBTERM_MOUSE,	(char_u *)"JsbMouse"},
1018 #endif
1019 #ifdef FEAT_MOUSE_PTERM
1020     {K_PTERM_MOUSE,	(char_u *)"PtermMouse"},
1021 #endif
1022 #ifdef FEAT_MOUSE_URXVT
1023     {K_URXVT_MOUSE,	(char_u *)"UrxvtMouse"},
1024 #endif
1025     {K_SGR_MOUSE,	(char_u *)"SgrMouse"},
1026     {K_SGR_MOUSERELEASE, (char_u *)"SgrMouseRelease"},
1027     {K_LEFTMOUSE,	(char_u *)"LeftMouse"},
1028     {K_LEFTMOUSE_NM,	(char_u *)"LeftMouseNM"},
1029     {K_LEFTDRAG,	(char_u *)"LeftDrag"},
1030     {K_LEFTRELEASE,	(char_u *)"LeftRelease"},
1031     {K_LEFTRELEASE_NM,	(char_u *)"LeftReleaseNM"},
1032     {K_MOUSEMOVE,	(char_u *)"MouseMove"},
1033     {K_MIDDLEMOUSE,	(char_u *)"MiddleMouse"},
1034     {K_MIDDLEDRAG,	(char_u *)"MiddleDrag"},
1035     {K_MIDDLERELEASE,	(char_u *)"MiddleRelease"},
1036     {K_RIGHTMOUSE,	(char_u *)"RightMouse"},
1037     {K_RIGHTDRAG,	(char_u *)"RightDrag"},
1038     {K_RIGHTRELEASE,	(char_u *)"RightRelease"},
1039     {K_MOUSEDOWN,	(char_u *)"ScrollWheelUp"},
1040     {K_MOUSEUP,		(char_u *)"ScrollWheelDown"},
1041     {K_MOUSELEFT,	(char_u *)"ScrollWheelRight"},
1042     {K_MOUSERIGHT,	(char_u *)"ScrollWheelLeft"},
1043     {K_MOUSEDOWN,	(char_u *)"MouseDown"}, // OBSOLETE: Use
1044     {K_MOUSEUP,		(char_u *)"MouseUp"},	// ScrollWheelXXX instead
1045     {K_X1MOUSE,		(char_u *)"X1Mouse"},
1046     {K_X1DRAG,		(char_u *)"X1Drag"},
1047     {K_X1RELEASE,		(char_u *)"X1Release"},
1048     {K_X2MOUSE,		(char_u *)"X2Mouse"},
1049     {K_X2DRAG,		(char_u *)"X2Drag"},
1050     {K_X2RELEASE,		(char_u *)"X2Release"},
1051     {K_DROP,		(char_u *)"Drop"},
1052     {K_ZERO,		(char_u *)"Nul"},
1053 #ifdef FEAT_EVAL
1054     {K_SNR,		(char_u *)"SNR"},
1055 #endif
1056     {K_PLUG,		(char_u *)"Plug"},
1057     {K_CURSORHOLD,	(char_u *)"CursorHold"},
1058     {K_IGNORE,		(char_u *)"Ignore"},
1059     {K_COMMAND,		(char_u *)"Cmd"},
1060     {K_FOCUSGAINED,	(char_u *)"FocusGained"},
1061     {K_FOCUSLOST,	(char_u *)"FocusLost"},
1062     {0,			NULL}
1063     // NOTE: When adding a long name update MAX_KEY_NAME_LEN.
1064 };
1065 
1066 #define KEY_NAMES_TABLE_LEN ARRAY_LENGTH(key_names_table)
1067 
1068 /*
1069  * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
1070  * modifier name ('S' for Shift, 'C' for Ctrl etc).
1071  */
1072     static int
name_to_mod_mask(int c)1073 name_to_mod_mask(int c)
1074 {
1075     int	    i;
1076 
1077     c = TOUPPER_ASC(c);
1078     for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
1079 	if (c == mod_mask_table[i].name)
1080 	    return mod_mask_table[i].mod_flag;
1081     return 0;
1082 }
1083 
1084 /*
1085  * Check if if there is a special key code for "key" that includes the
1086  * modifiers specified.
1087  */
1088     int
simplify_key(int key,int * modifiers)1089 simplify_key(int key, int *modifiers)
1090 {
1091     int	    i;
1092     int	    key0;
1093     int	    key1;
1094 
1095     if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
1096     {
1097 	// TAB is a special case
1098 	if (key == TAB && (*modifiers & MOD_MASK_SHIFT))
1099 	{
1100 	    *modifiers &= ~MOD_MASK_SHIFT;
1101 	    return K_S_TAB;
1102 	}
1103 	key0 = KEY2TERMCAP0(key);
1104 	key1 = KEY2TERMCAP1(key);
1105 	for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
1106 	    if (key0 == modifier_keys_table[i + 3]
1107 		    && key1 == modifier_keys_table[i + 4]
1108 		    && (*modifiers & modifier_keys_table[i]))
1109 	    {
1110 		*modifiers &= ~modifier_keys_table[i];
1111 		return TERMCAP2KEY(modifier_keys_table[i + 1],
1112 						   modifier_keys_table[i + 2]);
1113 	    }
1114     }
1115     return key;
1116 }
1117 
1118 /*
1119  * Change <xHome> to <Home>, <xUp> to <Up>, etc.
1120  */
1121     int
handle_x_keys(int key)1122 handle_x_keys(int key)
1123 {
1124     switch (key)
1125     {
1126 	case K_XUP:	return K_UP;
1127 	case K_XDOWN:	return K_DOWN;
1128 	case K_XLEFT:	return K_LEFT;
1129 	case K_XRIGHT:	return K_RIGHT;
1130 	case K_XHOME:	return K_HOME;
1131 	case K_ZHOME:	return K_HOME;
1132 	case K_XEND:	return K_END;
1133 	case K_ZEND:	return K_END;
1134 	case K_XF1:	return K_F1;
1135 	case K_XF2:	return K_F2;
1136 	case K_XF3:	return K_F3;
1137 	case K_XF4:	return K_F4;
1138 	case K_S_XF1:	return K_S_F1;
1139 	case K_S_XF2:	return K_S_F2;
1140 	case K_S_XF3:	return K_S_F3;
1141 	case K_S_XF4:	return K_S_F4;
1142     }
1143     return key;
1144 }
1145 
1146 /*
1147  * Return a string which contains the name of the given key when the given
1148  * modifiers are down.
1149  */
1150     char_u *
get_special_key_name(int c,int modifiers)1151 get_special_key_name(int c, int modifiers)
1152 {
1153     static char_u string[MAX_KEY_NAME_LEN + 1];
1154 
1155     int	    i, idx;
1156     int	    table_idx;
1157     char_u  *s;
1158 
1159     string[0] = '<';
1160     idx = 1;
1161 
1162     // Key that stands for a normal character.
1163     if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
1164 	c = KEY2TERMCAP1(c);
1165 
1166     /*
1167      * Translate shifted special keys into unshifted keys and set modifier.
1168      * Same for CTRL and ALT modifiers.
1169      */
1170     if (IS_SPECIAL(c))
1171     {
1172 	for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
1173 	    if (       KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
1174 		    && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2])
1175 	    {
1176 		modifiers |= modifier_keys_table[i];
1177 		c = TERMCAP2KEY(modifier_keys_table[i + 3],
1178 						   modifier_keys_table[i + 4]);
1179 		break;
1180 	    }
1181     }
1182 
1183     // try to find the key in the special key table
1184     table_idx = find_special_key_in_table(c);
1185 
1186     /*
1187      * When not a known special key, and not a printable character, try to
1188      * extract modifiers.
1189      */
1190     if (c > 0 && (*mb_char2len)(c) == 1)
1191     {
1192 	if (table_idx < 0
1193 		&& (!vim_isprintc(c) || (c & 0x7f) == ' ')
1194 		&& (c & 0x80))
1195 	{
1196 	    c &= 0x7f;
1197 	    modifiers |= MOD_MASK_ALT;
1198 	    // try again, to find the un-alted key in the special key table
1199 	    table_idx = find_special_key_in_table(c);
1200 	}
1201 	if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
1202 	{
1203 #ifdef EBCDIC
1204 	    c = CtrlChar(c);
1205 #else
1206 	    c += '@';
1207 #endif
1208 	    modifiers |= MOD_MASK_CTRL;
1209 	}
1210     }
1211 
1212     // translate the modifier into a string
1213     for (i = 0; mod_mask_table[i].name != 'A'; i++)
1214 	if ((modifiers & mod_mask_table[i].mod_mask)
1215 						== mod_mask_table[i].mod_flag)
1216 	{
1217 	    string[idx++] = mod_mask_table[i].name;
1218 	    string[idx++] = (char_u)'-';
1219 	}
1220 
1221     if (table_idx < 0)		// unknown special key, may output t_xx
1222     {
1223 	if (IS_SPECIAL(c))
1224 	{
1225 	    string[idx++] = 't';
1226 	    string[idx++] = '_';
1227 	    string[idx++] = KEY2TERMCAP0(c);
1228 	    string[idx++] = KEY2TERMCAP1(c);
1229 	}
1230 	// Not a special key, only modifiers, output directly
1231 	else
1232 	{
1233 	    if (has_mbyte && (*mb_char2len)(c) > 1)
1234 		idx += (*mb_char2bytes)(c, string + idx);
1235 	    else if (vim_isprintc(c))
1236 		string[idx++] = c;
1237 	    else
1238 	    {
1239 		s = transchar(c);
1240 		while (*s)
1241 		    string[idx++] = *s++;
1242 	    }
1243 	}
1244     }
1245     else		// use name of special key
1246     {
1247 	size_t len = STRLEN(key_names_table[table_idx].name);
1248 
1249 	if (len + idx + 2 <= MAX_KEY_NAME_LEN)
1250 	{
1251 	    STRCPY(string + idx, key_names_table[table_idx].name);
1252 	    idx += (int)len;
1253 	}
1254     }
1255     string[idx++] = '>';
1256     string[idx] = NUL;
1257     return string;
1258 }
1259 
1260 /*
1261  * Try translating a <> name at (*srcp)[] to dst[].
1262  * Return the number of characters added to dst[], zero for no match.
1263  * If there is a match, srcp is advanced to after the <> name.
1264  * dst[] must be big enough to hold the result (up to six characters)!
1265  */
1266     int
trans_special(char_u ** srcp,char_u * dst,int flags,int * did_simplify)1267 trans_special(
1268     char_u	**srcp,
1269     char_u	*dst,
1270     int		flags,		// FSK_ values
1271     int		*did_simplify)  // FSK_SIMPLIFY and found <C-H> or <A-x>
1272 {
1273     int		modifiers = 0;
1274     int		key;
1275 
1276     key = find_special_key(srcp, &modifiers, flags, did_simplify);
1277     if (key == 0)
1278 	return 0;
1279 
1280     return special_to_buf(key, modifiers, flags & FSK_KEYCODE, dst);
1281 }
1282 
1283 /*
1284  * Put the character sequence for "key" with "modifiers" into "dst" and return
1285  * the resulting length.
1286  * When "keycode" is TRUE prefer key code, e.g. K_DEL instead of DEL.
1287  * The sequence is not NUL terminated.
1288  * This is how characters in a string are encoded.
1289  */
1290     int
special_to_buf(int key,int modifiers,int keycode,char_u * dst)1291 special_to_buf(int key, int modifiers, int keycode, char_u *dst)
1292 {
1293     int		dlen = 0;
1294 
1295     // Put the appropriate modifier in a string
1296     if (modifiers != 0)
1297     {
1298 	dst[dlen++] = K_SPECIAL;
1299 	dst[dlen++] = KS_MODIFIER;
1300 	dst[dlen++] = modifiers;
1301     }
1302 
1303     if (IS_SPECIAL(key))
1304     {
1305 	dst[dlen++] = K_SPECIAL;
1306 	dst[dlen++] = KEY2TERMCAP0(key);
1307 	dst[dlen++] = KEY2TERMCAP1(key);
1308     }
1309     else if (has_mbyte && !keycode)
1310 	dlen += (*mb_char2bytes)(key, dst + dlen);
1311     else if (keycode)
1312 	dlen = (int)(add_char2buf(key, dst + dlen) - dst);
1313     else
1314 	dst[dlen++] = key;
1315 
1316     return dlen;
1317 }
1318 
1319 /*
1320  * Try translating a <> name at (*srcp)[], return the key and modifiers.
1321  * srcp is advanced to after the <> name.
1322  * returns 0 if there is no match.
1323  */
1324     int
find_special_key(char_u ** srcp,int * modp,int flags,int * did_simplify)1325 find_special_key(
1326     char_u	**srcp,
1327     int		*modp,
1328     int		flags,		// FSK_ values
1329     int		*did_simplify)  // found <C-H> or <A-x>
1330 {
1331     char_u	*last_dash;
1332     char_u	*end_of_name;
1333     char_u	*src;
1334     char_u	*bp;
1335     int		in_string = flags & FSK_IN_STRING;
1336     int		modifiers;
1337     int		bit;
1338     int		key;
1339     uvarnumber_T	n;
1340     int		l;
1341 
1342     src = *srcp;
1343     if (src[0] != '<')
1344 	return 0;
1345     if (src[1] == '*')	    // <*xxx>: do not simplify
1346 	++src;
1347 
1348     // Find end of modifier list
1349     last_dash = src;
1350     for (bp = src + 1; *bp == '-' || vim_isNormalIDc(*bp); bp++)
1351     {
1352 	if (*bp == '-')
1353 	{
1354 	    last_dash = bp;
1355 	    if (bp[1] != NUL)
1356 	    {
1357 		if (has_mbyte)
1358 		    l = mb_ptr2len(bp + 1);
1359 		else
1360 		    l = 1;
1361 		// Anything accepted, like <C-?>.
1362 		// <C-"> or <M-"> are not special in strings as " is
1363 		// the string delimiter. With a backslash it works: <M-\">
1364 		if (!(in_string && bp[1] == '"') && bp[l + 1] == '>')
1365 		    bp += l;
1366 		else if (in_string && bp[1] == '\\' && bp[2] == '"'
1367 							   && bp[3] == '>')
1368 		    bp += 2;
1369 	    }
1370 	}
1371 	if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
1372 	    bp += 3;	// skip t_xx, xx may be '-' or '>'
1373 	else if (STRNICMP(bp, "char-", 5) == 0)
1374 	{
1375 	    vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, TRUE);
1376 	    if (l == 0)
1377 	    {
1378 		emsg(_(e_invarg));
1379 		return 0;
1380 	    }
1381 	    bp += l + 5;
1382 	    break;
1383 	}
1384     }
1385 
1386     if (*bp == '>')	// found matching '>'
1387     {
1388 	end_of_name = bp + 1;
1389 
1390 	// Which modifiers are given?
1391 	modifiers = 0x0;
1392 	for (bp = src + 1; bp < last_dash; bp++)
1393 	{
1394 	    if (*bp != '-')
1395 	    {
1396 		bit = name_to_mod_mask(*bp);
1397 		if (bit == 0x0)
1398 		    break;	// Illegal modifier name
1399 		modifiers |= bit;
1400 	    }
1401 	}
1402 
1403 	/*
1404 	 * Legal modifier name.
1405 	 */
1406 	if (bp >= last_dash)
1407 	{
1408 	    if (STRNICMP(last_dash + 1, "char-", 5) == 0
1409 						 && VIM_ISDIGIT(last_dash[6]))
1410 	    {
1411 		// <Char-123> or <Char-033> or <Char-0x33>
1412 		vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
1413 								  &n, 0, TRUE);
1414 		if (l == 0)
1415 		{
1416 		    emsg(_(e_invarg));
1417 		    return 0;
1418 		}
1419 		key = (int)n;
1420 	    }
1421 	    else
1422 	    {
1423 		int off = 1;
1424 
1425 		// Modifier with single letter, or special key name.
1426 		if (in_string && last_dash[1] == '\\' && last_dash[2] == '"')
1427 		    off = 2;
1428 		if (has_mbyte)
1429 		    l = mb_ptr2len(last_dash + off);
1430 		else
1431 		    l = 1;
1432 		if (modifiers != 0 && last_dash[l + off] == '>')
1433 		    key = PTR2CHAR(last_dash + off);
1434 		else
1435 		{
1436 		    key = get_special_key_code(last_dash + off);
1437 		    if (!(flags & FSK_KEEP_X_KEY))
1438 			key = handle_x_keys(key);
1439 		}
1440 	    }
1441 
1442 	    /*
1443 	     * get_special_key_code() may return NUL for invalid
1444 	     * special key name.
1445 	     */
1446 	    if (key != NUL)
1447 	    {
1448 		/*
1449 		 * Only use a modifier when there is no special key code that
1450 		 * includes the modifier.
1451 		 */
1452 		key = simplify_key(key, &modifiers);
1453 
1454 		if (!(flags & FSK_KEYCODE))
1455 		{
1456 		    // don't want keycode, use single byte code
1457 		    if (key == K_BS)
1458 			key = BS;
1459 		    else if (key == K_DEL || key == K_KDEL)
1460 			key = DEL;
1461 		}
1462 
1463 		// Normal Key with modifier: Try to make a single byte code.
1464 		if (!IS_SPECIAL(key))
1465 		    key = extract_modifiers(key, &modifiers,
1466 					   flags & FSK_SIMPLIFY, did_simplify);
1467 
1468 		*modp = modifiers;
1469 		*srcp = end_of_name;
1470 		return key;
1471 	    }
1472 	}
1473     }
1474     return 0;
1475 }
1476 
1477 
1478 /*
1479  * Some keys are used with Ctrl without Shift and are still expected to be
1480  * mapped as if Shift was pressed:
1481  * CTRL-2 is CTRL-@
1482  * CTRL-6 is CTRL-^
1483  * CTRL-- is CTRL-_
1484  * Also, <C-H> and <C-h> mean the same thing, always use "H".
1485  * Returns the possibly adjusted key.
1486  */
1487     int
may_adjust_key_for_ctrl(int modifiers,int key)1488 may_adjust_key_for_ctrl(int modifiers, int key)
1489 {
1490     if (modifiers & MOD_MASK_CTRL)
1491     {
1492 	if (ASCII_ISALPHA(key))
1493 	    return TOUPPER_ASC(key);
1494 	if (key == '2')
1495 	    return '@';
1496 	if (key == '6')
1497 	    return '^';
1498 	if (key == '-')
1499 	    return '_';
1500     }
1501     return key;
1502 }
1503 
1504 /*
1505  * Some keys already have Shift included, pass them as normal keys.
1506  * When Ctrl is also used <C-H> and <C-S-H> are different, but <C-S-{> should
1507  * be <C-{>.  Same for <C-S-}> and <C-S-|>.
1508  * Also for <A-S-a> and <M-S-a>.
1509  * This includes all printable ASCII characters except numbers and a-z.
1510  */
1511     int
may_remove_shift_modifier(int modifiers,int key)1512 may_remove_shift_modifier(int modifiers, int key)
1513 {
1514     if ((modifiers == MOD_MASK_SHIFT
1515 		|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
1516 		|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
1517 	    && ((key >= '!' && key <= '/')
1518 		|| (key >= ':' && key <= 'Z')
1519 		|| (key >= '[' && key <= '`')
1520 		|| (key >= '{' && key <= '~')))
1521 	return modifiers & ~MOD_MASK_SHIFT;
1522 
1523     if (modifiers == (MOD_MASK_SHIFT | MOD_MASK_CTRL)
1524 		&& (key == '{' || key == '}' || key == '|'))
1525 	return modifiers & ~MOD_MASK_SHIFT;
1526 
1527     return modifiers;
1528 }
1529 
1530 /*
1531  * Try to include modifiers in the key.
1532  * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
1533  * When "simplify" is FALSE don't do Ctrl and Alt.
1534  * When "simplify" is TRUE and Ctrl or Alt is removed from modifiers set
1535  * "did_simplify" when it's not NULL.
1536  */
1537     int
extract_modifiers(int key,int * modp,int simplify,int * did_simplify)1538 extract_modifiers(int key, int *modp, int simplify, int *did_simplify)
1539 {
1540     int	modifiers = *modp;
1541 
1542 #ifdef MACOS_X
1543     // Command-key really special, no fancynest
1544     if (!(modifiers & MOD_MASK_CMD))
1545 #endif
1546     if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
1547     {
1548 	key = TOUPPER_ASC(key);
1549 	// With <C-S-a> we keep the shift modifier.
1550 	// With <S-a>, <A-S-a> and <S-A> we don't keep the shift modifier.
1551 	if (simplify || modifiers == MOD_MASK_SHIFT
1552 		|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
1553 		|| modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
1554 	    modifiers &= ~MOD_MASK_SHIFT;
1555     }
1556 
1557     // <C-H> and <C-h> mean the same thing, always use "H"
1558     if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key))
1559 	key = TOUPPER_ASC(key);
1560 
1561     if (simplify && (modifiers & MOD_MASK_CTRL)
1562 #ifdef EBCDIC
1563 	    // TODO: EBCDIC Better use:
1564 	    // && (Ctrl_chr(key) || key == '?')
1565 	    // ???
1566 	    && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
1567 						       != NULL
1568 #else
1569 	    && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
1570 #endif
1571 	    )
1572     {
1573 	key = Ctrl_chr(key);
1574 	modifiers &= ~MOD_MASK_CTRL;
1575 	// <C-@> is <Nul>
1576 	if (key == 0)
1577 	    key = K_ZERO;
1578 	if (did_simplify != NULL)
1579 	    *did_simplify = TRUE;
1580     }
1581 
1582 #ifdef MACOS_X
1583     // Command-key really special, no fancynest
1584     if (!(modifiers & MOD_MASK_CMD))
1585 #endif
1586     if (simplify && (modifiers & MOD_MASK_ALT) && key < 0x80
1587 	    && !enc_dbcs)		// avoid creating a lead byte
1588     {
1589 	key |= 0x80;
1590 	modifiers &= ~MOD_MASK_ALT;	// remove the META modifier
1591 	if (did_simplify != NULL)
1592 	    *did_simplify = TRUE;
1593     }
1594 
1595     *modp = modifiers;
1596     return key;
1597 }
1598 
1599 /*
1600  * Try to find key "c" in the special key table.
1601  * Return the index when found, -1 when not found.
1602  */
1603     int
find_special_key_in_table(int c)1604 find_special_key_in_table(int c)
1605 {
1606     int	    i;
1607 
1608     for (i = 0; key_names_table[i].name != NULL; i++)
1609 	if (c == key_names_table[i].key)
1610 	    break;
1611     if (key_names_table[i].name == NULL)
1612 	i = -1;
1613     return i;
1614 }
1615 
1616 /*
1617  * Find the special key with the given name (the given string does not have to
1618  * end with NUL, the name is assumed to end before the first non-idchar).
1619  * If the name starts with "t_" the next two characters are interpreted as a
1620  * termcap name.
1621  * Return the key code, or 0 if not found.
1622  */
1623     int
get_special_key_code(char_u * name)1624 get_special_key_code(char_u *name)
1625 {
1626     char_u  *table_name;
1627     char_u  string[3];
1628     int	    i, j;
1629 
1630     /*
1631      * If it's <t_xx> we get the code for xx from the termcap
1632      */
1633     if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
1634     {
1635 	string[0] = name[2];
1636 	string[1] = name[3];
1637 	string[2] = NUL;
1638 	if (add_termcap_entry(string, FALSE) == OK)
1639 	    return TERMCAP2KEY(name[2], name[3]);
1640     }
1641     else
1642 	for (i = 0; key_names_table[i].name != NULL; i++)
1643 	{
1644 	    table_name = key_names_table[i].name;
1645 	    for (j = 0; vim_isNormalIDc(name[j]) && table_name[j] != NUL; j++)
1646 		if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
1647 		    break;
1648 	    if (!vim_isNormalIDc(name[j]) && table_name[j] == NUL)
1649 		return key_names_table[i].key;
1650 	}
1651     return 0;
1652 }
1653 
1654     char_u *
get_key_name(int i)1655 get_key_name(int i)
1656 {
1657     if (i >= (int)KEY_NAMES_TABLE_LEN)
1658 	return NULL;
1659     return  key_names_table[i].name;
1660 }
1661 
1662 /*
1663  * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
1664  */
1665     int
get_fileformat(buf_T * buf)1666 get_fileformat(buf_T *buf)
1667 {
1668     int		c = *buf->b_p_ff;
1669 
1670     if (buf->b_p_bin || c == 'u')
1671 	return EOL_UNIX;
1672     if (c == 'm')
1673 	return EOL_MAC;
1674     return EOL_DOS;
1675 }
1676 
1677 /*
1678  * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
1679  * argument.
1680  */
1681     int
get_fileformat_force(buf_T * buf,exarg_T * eap)1682 get_fileformat_force(
1683     buf_T	*buf,
1684     exarg_T	*eap)	    // can be NULL!
1685 {
1686     int		c;
1687 
1688     if (eap != NULL && eap->force_ff != 0)
1689 	c = eap->force_ff;
1690     else
1691     {
1692 	if ((eap != NULL && eap->force_bin != 0)
1693 			       ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin)
1694 	    return EOL_UNIX;
1695 	c = *buf->b_p_ff;
1696     }
1697     if (c == 'u')
1698 	return EOL_UNIX;
1699     if (c == 'm')
1700 	return EOL_MAC;
1701     return EOL_DOS;
1702 }
1703 
1704 /*
1705  * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
1706  * Sets both 'textmode' and 'fileformat'.
1707  * Note: Does _not_ set global value of 'textmode'!
1708  */
1709     void
set_fileformat(int t,int opt_flags)1710 set_fileformat(
1711     int		t,
1712     int		opt_flags)	// OPT_LOCAL and/or OPT_GLOBAL
1713 {
1714     char	*p = NULL;
1715 
1716     switch (t)
1717     {
1718     case EOL_DOS:
1719 	p = FF_DOS;
1720 	curbuf->b_p_tx = TRUE;
1721 	break;
1722     case EOL_UNIX:
1723 	p = FF_UNIX;
1724 	curbuf->b_p_tx = FALSE;
1725 	break;
1726     case EOL_MAC:
1727 	p = FF_MAC;
1728 	curbuf->b_p_tx = FALSE;
1729 	break;
1730     }
1731     if (p != NULL)
1732 	set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
1733 						     OPT_FREE | opt_flags, 0);
1734 
1735     // This may cause the buffer to become (un)modified.
1736     check_status(curbuf);
1737     redraw_tabline = TRUE;
1738 #ifdef FEAT_TITLE
1739     need_maketitle = TRUE;	    // set window title later
1740 #endif
1741 }
1742 
1743 /*
1744  * Return the default fileformat from 'fileformats'.
1745  */
1746     int
default_fileformat(void)1747 default_fileformat(void)
1748 {
1749     switch (*p_ffs)
1750     {
1751 	case 'm':   return EOL_MAC;
1752 	case 'd':   return EOL_DOS;
1753     }
1754     return EOL_UNIX;
1755 }
1756 
1757 /*
1758  * Call shell.	Calls mch_call_shell, with 'shellxquote' added.
1759  */
1760     int
call_shell(char_u * cmd,int opt)1761 call_shell(char_u *cmd, int opt)
1762 {
1763     char_u	*ncmd;
1764     int		retval;
1765 #ifdef FEAT_PROFILE
1766     proftime_T	wait_time;
1767 #endif
1768 
1769     if (p_verbose > 3)
1770     {
1771 	verbose_enter();
1772 	smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd);
1773 	out_char('\n');
1774 	cursor_on();
1775 	verbose_leave();
1776     }
1777 
1778 #ifdef FEAT_PROFILE
1779     if (do_profiling == PROF_YES)
1780 	prof_child_enter(&wait_time);
1781 #endif
1782 
1783     if (*p_sh == NUL)
1784     {
1785 	emsg(_(e_shellempty));
1786 	retval = -1;
1787     }
1788     else
1789     {
1790 #ifdef FEAT_GUI_MSWIN
1791 	// Don't hide the pointer while executing a shell command.
1792 	gui_mch_mousehide(FALSE);
1793 #endif
1794 #ifdef FEAT_GUI
1795 	++hold_gui_events;
1796 #endif
1797 	// The external command may update a tags file, clear cached tags.
1798 	tag_freematch();
1799 
1800 	if (cmd == NULL || *p_sxq == NUL)
1801 	    retval = mch_call_shell(cmd, opt);
1802 	else
1803 	{
1804 	    char_u *ecmd = cmd;
1805 
1806 	    if (*p_sxe != NUL && *p_sxq == '(')
1807 	    {
1808 		ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE);
1809 		if (ecmd == NULL)
1810 		    ecmd = cmd;
1811 	    }
1812 	    ncmd = alloc(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1);
1813 	    if (ncmd != NULL)
1814 	    {
1815 		STRCPY(ncmd, p_sxq);
1816 		STRCAT(ncmd, ecmd);
1817 		// When 'shellxquote' is ( append ).
1818 		// When 'shellxquote' is "( append )".
1819 		STRCAT(ncmd, *p_sxq == '(' ? (char_u *)")"
1820 		    : *p_sxq == '"' && *(p_sxq+1) == '(' ? (char_u *)")\""
1821 		    : p_sxq);
1822 		retval = mch_call_shell(ncmd, opt);
1823 		vim_free(ncmd);
1824 	    }
1825 	    else
1826 		retval = -1;
1827 	    if (ecmd != cmd)
1828 		vim_free(ecmd);
1829 	}
1830 #ifdef FEAT_GUI
1831 	--hold_gui_events;
1832 #endif
1833 	/*
1834 	 * Check the window size, in case it changed while executing the
1835 	 * external command.
1836 	 */
1837 	shell_resized_check();
1838     }
1839 
1840 #ifdef FEAT_EVAL
1841     set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
1842 # ifdef FEAT_PROFILE
1843     if (do_profiling == PROF_YES)
1844 	prof_child_exit(&wait_time);
1845 # endif
1846 #endif
1847 
1848     return retval;
1849 }
1850 
1851 /*
1852  * VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to
1853  * NORMAL State with a condition.  This function returns the real State.
1854  */
1855     int
get_real_state(void)1856 get_real_state(void)
1857 {
1858     if (State & NORMAL)
1859     {
1860 	if (VIsual_active)
1861 	{
1862 	    if (VIsual_select)
1863 		return SELECTMODE;
1864 	    return VISUAL;
1865 	}
1866 	else if (finish_op)
1867 	    return OP_PENDING;
1868     }
1869     return State;
1870 }
1871 
1872 /*
1873  * Return TRUE if "p" points to just after a path separator.
1874  * Takes care of multi-byte characters.
1875  * "b" must point to the start of the file name
1876  */
1877     int
after_pathsep(char_u * b,char_u * p)1878 after_pathsep(char_u *b, char_u *p)
1879 {
1880     return p > b && vim_ispathsep(p[-1])
1881 			     && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0);
1882 }
1883 
1884 /*
1885  * Return TRUE if file names "f1" and "f2" are in the same directory.
1886  * "f1" may be a short name, "f2" must be a full path.
1887  */
1888     int
same_directory(char_u * f1,char_u * f2)1889 same_directory(char_u *f1, char_u *f2)
1890 {
1891     char_u	ffname[MAXPATHL];
1892     char_u	*t1;
1893     char_u	*t2;
1894 
1895     // safety check
1896     if (f1 == NULL || f2 == NULL)
1897 	return FALSE;
1898 
1899     (void)vim_FullName(f1, ffname, MAXPATHL, FALSE);
1900     t1 = gettail_sep(ffname);
1901     t2 = gettail_sep(f2);
1902     return (t1 - ffname == t2 - f2
1903 	     && pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0);
1904 }
1905 
1906 #if defined(FEAT_SESSION) || defined(FEAT_AUTOCHDIR) \
1907 	|| defined(MSWIN) || defined(FEAT_GUI_GTK) \
1908 	|| defined(FEAT_NETBEANS_INTG) \
1909 	|| defined(PROTO)
1910 /*
1911  * Change to a file's directory.
1912  * Caller must call shorten_fnames()!
1913  * Return OK or FAIL.
1914  */
1915     int
vim_chdirfile(char_u * fname,char * trigger_autocmd)1916 vim_chdirfile(char_u *fname, char *trigger_autocmd)
1917 {
1918     char_u	old_dir[MAXPATHL];
1919     char_u	new_dir[MAXPATHL];
1920     int		res;
1921 
1922     if (mch_dirname(old_dir, MAXPATHL) != OK)
1923 	*old_dir = NUL;
1924 
1925     vim_strncpy(new_dir, fname, MAXPATHL - 1);
1926     *gettail_sep(new_dir) = NUL;
1927 
1928     if (pathcmp((char *)old_dir, (char *)new_dir, -1) == 0)
1929 	// nothing to do
1930 	res = OK;
1931     else
1932     {
1933 	res = mch_chdir((char *)new_dir) == 0 ? OK : FAIL;
1934 
1935 	if (res == OK && trigger_autocmd != NULL)
1936 	    apply_autocmds(EVENT_DIRCHANGED, (char_u *)trigger_autocmd,
1937 						       new_dir, FALSE, curbuf);
1938     }
1939     return res;
1940 }
1941 #endif
1942 
1943 #if defined(STAT_IGNORES_SLASH) || defined(PROTO)
1944 /*
1945  * Check if "name" ends in a slash and is not a directory.
1946  * Used for systems where stat() ignores a trailing slash on a file name.
1947  * The Vim code assumes a trailing slash is only ignored for a directory.
1948  */
1949     static int
illegal_slash(const char * name)1950 illegal_slash(const char *name)
1951 {
1952     if (name[0] == NUL)
1953 	return FALSE;	    // no file name is not illegal
1954     if (name[strlen(name) - 1] != '/')
1955 	return FALSE;	    // no trailing slash
1956     if (mch_isdir((char_u *)name))
1957 	return FALSE;	    // trailing slash for a directory
1958     return TRUE;
1959 }
1960 
1961 /*
1962  * Special implementation of mch_stat() for Solaris.
1963  */
1964     int
vim_stat(const char * name,stat_T * stp)1965 vim_stat(const char *name, stat_T *stp)
1966 {
1967     // On Solaris stat() accepts "file/" as if it was "file".  Return -1 if
1968     // the name ends in "/" and it's not a directory.
1969     return illegal_slash(name) ? -1 : stat(name, stp);
1970 }
1971 #endif
1972 
1973 #if defined(CURSOR_SHAPE) || defined(PROTO)
1974 
1975 /*
1976  * Handling of cursor and mouse pointer shapes in various modes.
1977  */
1978 
1979 cursorentry_T shape_table[SHAPE_IDX_COUNT] =
1980 {
1981     // The values will be filled in from the 'guicursor' and 'mouseshape'
1982     // defaults when Vim starts.
1983     // Adjust the SHAPE_IDX_ defines when making changes!
1984     {0,	0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
1985     {0,	0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
1986     {0,	0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
1987     {0,	0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
1988     {0,	0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
1989     {0,	0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
1990     {0,	0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
1991     {0,	0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
1992     {0,	0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
1993     {0,	0, 0,   0L,   0L,   0L, 0, 0, "e", SHAPE_MOUSE},
1994     {0,	0, 0,   0L,   0L,   0L, 0, 0, "s", SHAPE_MOUSE},
1995     {0,	0, 0,   0L,   0L,   0L, 0, 0, "sd", SHAPE_MOUSE},
1996     {0,	0, 0,   0L,   0L,   0L, 0, 0, "vs", SHAPE_MOUSE},
1997     {0,	0, 0,   0L,   0L,   0L, 0, 0, "vd", SHAPE_MOUSE},
1998     {0,	0, 0,   0L,   0L,   0L, 0, 0, "m", SHAPE_MOUSE},
1999     {0,	0, 0,   0L,   0L,   0L, 0, 0, "ml", SHAPE_MOUSE},
2000     {0,	0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
2001 };
2002 
2003 #ifdef FEAT_MOUSESHAPE
2004 /*
2005  * Table with names for mouse shapes.  Keep in sync with all the tables for
2006  * mch_set_mouse_shape()!.
2007  */
2008 static char * mshape_names[] =
2009 {
2010     "arrow",	// default, must be the first one
2011     "blank",	// hidden
2012     "beam",
2013     "updown",
2014     "udsizing",
2015     "leftright",
2016     "lrsizing",
2017     "busy",
2018     "no",
2019     "crosshair",
2020     "hand1",
2021     "hand2",
2022     "pencil",
2023     "question",
2024     "rightup-arrow",
2025     "up-arrow",
2026     NULL
2027 };
2028 #endif
2029 
2030 /*
2031  * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
2032  * ("what" is SHAPE_MOUSE).
2033  * Returns error message for an illegal option, NULL otherwise.
2034  */
2035     char *
parse_shape_opt(int what)2036 parse_shape_opt(int what)
2037 {
2038     char_u	*modep;
2039     char_u	*colonp;
2040     char_u	*commap;
2041     char_u	*slashp;
2042     char_u	*p, *endp;
2043     int		idx = 0;		// init for GCC
2044     int		all_idx;
2045     int		len;
2046     int		i;
2047     long	n;
2048     int		found_ve = FALSE;	// found "ve" flag
2049     int		round;
2050 
2051     /*
2052      * First round: check for errors; second round: do it for real.
2053      */
2054     for (round = 1; round <= 2; ++round)
2055     {
2056 	/*
2057 	 * Repeat for all comma separated parts.
2058 	 */
2059 #ifdef FEAT_MOUSESHAPE
2060 	if (what == SHAPE_MOUSE)
2061 	    modep = p_mouseshape;
2062 	else
2063 #endif
2064 	    modep = p_guicursor;
2065 	while (*modep != NUL)
2066 	{
2067 	    colonp = vim_strchr(modep, ':');
2068 	    commap = vim_strchr(modep, ',');
2069 
2070 	    if (colonp == NULL || (commap != NULL && commap < colonp))
2071 		return N_("E545: Missing colon");
2072 	    if (colonp == modep)
2073 		return N_("E546: Illegal mode");
2074 
2075 	    /*
2076 	     * Repeat for all mode's before the colon.
2077 	     * For the 'a' mode, we loop to handle all the modes.
2078 	     */
2079 	    all_idx = -1;
2080 	    while (modep < colonp || all_idx >= 0)
2081 	    {
2082 		if (all_idx < 0)
2083 		{
2084 		    // Find the mode.
2085 		    if (modep[1] == '-' || modep[1] == ':')
2086 			len = 1;
2087 		    else
2088 			len = 2;
2089 		    if (len == 1 && TOLOWER_ASC(modep[0]) == 'a')
2090 			all_idx = SHAPE_IDX_COUNT - 1;
2091 		    else
2092 		    {
2093 			for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
2094 			    if (STRNICMP(modep, shape_table[idx].name, len)
2095 									 == 0)
2096 				break;
2097 			if (idx == SHAPE_IDX_COUNT
2098 				   || (shape_table[idx].used_for & what) == 0)
2099 			    return N_("E546: Illegal mode");
2100 			if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
2101 			    found_ve = TRUE;
2102 		    }
2103 		    modep += len + 1;
2104 		}
2105 
2106 		if (all_idx >= 0)
2107 		    idx = all_idx--;
2108 		else if (round == 2)
2109 		{
2110 #ifdef FEAT_MOUSESHAPE
2111 		    if (what == SHAPE_MOUSE)
2112 		    {
2113 			// Set the default, for the missing parts
2114 			shape_table[idx].mshape = 0;
2115 		    }
2116 		    else
2117 #endif
2118 		    {
2119 			// Set the defaults, for the missing parts
2120 			shape_table[idx].shape = SHAPE_BLOCK;
2121 			shape_table[idx].blinkwait = 700L;
2122 			shape_table[idx].blinkon = 400L;
2123 			shape_table[idx].blinkoff = 250L;
2124 		    }
2125 		}
2126 
2127 		// Parse the part after the colon
2128 		for (p = colonp + 1; *p && *p != ','; )
2129 		{
2130 #ifdef FEAT_MOUSESHAPE
2131 		    if (what == SHAPE_MOUSE)
2132 		    {
2133 			for (i = 0; ; ++i)
2134 			{
2135 			    if (mshape_names[i] == NULL)
2136 			    {
2137 				if (!VIM_ISDIGIT(*p))
2138 				    return N_("E547: Illegal mouseshape");
2139 				if (round == 2)
2140 				    shape_table[idx].mshape =
2141 					      getdigits(&p) + MSHAPE_NUMBERED;
2142 				else
2143 				    (void)getdigits(&p);
2144 				break;
2145 			    }
2146 			    len = (int)STRLEN(mshape_names[i]);
2147 			    if (STRNICMP(p, mshape_names[i], len) == 0)
2148 			    {
2149 				if (round == 2)
2150 				    shape_table[idx].mshape = i;
2151 				p += len;
2152 				break;
2153 			    }
2154 			}
2155 		    }
2156 		    else // if (what == SHAPE_MOUSE)
2157 #endif
2158 		    {
2159 			/*
2160 			 * First handle the ones with a number argument.
2161 			 */
2162 			i = *p;
2163 			len = 0;
2164 			if (STRNICMP(p, "ver", 3) == 0)
2165 			    len = 3;
2166 			else if (STRNICMP(p, "hor", 3) == 0)
2167 			    len = 3;
2168 			else if (STRNICMP(p, "blinkwait", 9) == 0)
2169 			    len = 9;
2170 			else if (STRNICMP(p, "blinkon", 7) == 0)
2171 			    len = 7;
2172 			else if (STRNICMP(p, "blinkoff", 8) == 0)
2173 			    len = 8;
2174 			if (len != 0)
2175 			{
2176 			    p += len;
2177 			    if (!VIM_ISDIGIT(*p))
2178 				return N_("E548: digit expected");
2179 			    n = getdigits(&p);
2180 			    if (len == 3)   // "ver" or "hor"
2181 			    {
2182 				if (n == 0)
2183 				    return N_("E549: Illegal percentage");
2184 				if (round == 2)
2185 				{
2186 				    if (TOLOWER_ASC(i) == 'v')
2187 					shape_table[idx].shape = SHAPE_VER;
2188 				    else
2189 					shape_table[idx].shape = SHAPE_HOR;
2190 				    shape_table[idx].percentage = n;
2191 				}
2192 			    }
2193 			    else if (round == 2)
2194 			    {
2195 				if (len == 9)
2196 				    shape_table[idx].blinkwait = n;
2197 				else if (len == 7)
2198 				    shape_table[idx].blinkon = n;
2199 				else
2200 				    shape_table[idx].blinkoff = n;
2201 			    }
2202 			}
2203 			else if (STRNICMP(p, "block", 5) == 0)
2204 			{
2205 			    if (round == 2)
2206 				shape_table[idx].shape = SHAPE_BLOCK;
2207 			    p += 5;
2208 			}
2209 			else	// must be a highlight group name then
2210 			{
2211 			    endp = vim_strchr(p, '-');
2212 			    if (commap == NULL)		    // last part
2213 			    {
2214 				if (endp == NULL)
2215 				    endp = p + STRLEN(p);   // find end of part
2216 			    }
2217 			    else if (endp > commap || endp == NULL)
2218 				endp = commap;
2219 			    slashp = vim_strchr(p, '/');
2220 			    if (slashp != NULL && slashp < endp)
2221 			    {
2222 				// "group/langmap_group"
2223 				i = syn_check_group(p, (int)(slashp - p));
2224 				p = slashp + 1;
2225 			    }
2226 			    if (round == 2)
2227 			    {
2228 				shape_table[idx].id = syn_check_group(p,
2229 							     (int)(endp - p));
2230 				shape_table[idx].id_lm = shape_table[idx].id;
2231 				if (slashp != NULL && slashp < endp)
2232 				    shape_table[idx].id = i;
2233 			    }
2234 			    p = endp;
2235 			}
2236 		    } // if (what != SHAPE_MOUSE)
2237 
2238 		    if (*p == '-')
2239 			++p;
2240 		}
2241 	    }
2242 	    modep = p;
2243 	    if (*modep == ',')
2244 		++modep;
2245 	}
2246     }
2247 
2248     // If the 's' flag is not given, use the 'v' cursor for 's'
2249     if (!found_ve)
2250     {
2251 #ifdef FEAT_MOUSESHAPE
2252 	if (what == SHAPE_MOUSE)
2253 	{
2254 	    shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape;
2255 	}
2256 	else
2257 #endif
2258 	{
2259 	    shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
2260 	    shape_table[SHAPE_IDX_VE].percentage =
2261 					 shape_table[SHAPE_IDX_V].percentage;
2262 	    shape_table[SHAPE_IDX_VE].blinkwait =
2263 					  shape_table[SHAPE_IDX_V].blinkwait;
2264 	    shape_table[SHAPE_IDX_VE].blinkon =
2265 					    shape_table[SHAPE_IDX_V].blinkon;
2266 	    shape_table[SHAPE_IDX_VE].blinkoff =
2267 					   shape_table[SHAPE_IDX_V].blinkoff;
2268 	    shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
2269 	    shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
2270 	}
2271     }
2272 
2273     return NULL;
2274 }
2275 
2276 # if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \
2277 	|| defined(FEAT_MOUSESHAPE) || defined(PROTO)
2278 /*
2279  * Return the index into shape_table[] for the current mode.
2280  * When "mouse" is TRUE, consider indexes valid for the mouse pointer.
2281  */
2282     int
get_shape_idx(int mouse)2283 get_shape_idx(int mouse)
2284 {
2285 #ifdef FEAT_MOUSESHAPE
2286     if (mouse && (State == HITRETURN || State == ASKMORE))
2287     {
2288 # ifdef FEAT_GUI
2289 	int x, y;
2290 	gui_mch_getmouse(&x, &y);
2291 	if (Y_2_ROW(y) == Rows - 1)
2292 	    return SHAPE_IDX_MOREL;
2293 # endif
2294 	return SHAPE_IDX_MORE;
2295     }
2296     if (mouse && drag_status_line)
2297 	return SHAPE_IDX_SDRAG;
2298     if (mouse && drag_sep_line)
2299 	return SHAPE_IDX_VDRAG;
2300 #endif
2301     if (!mouse && State == SHOWMATCH)
2302 	return SHAPE_IDX_SM;
2303     if (State & VREPLACE_FLAG)
2304 	return SHAPE_IDX_R;
2305     if (State & REPLACE_FLAG)
2306 	return SHAPE_IDX_R;
2307     if (State & INSERT)
2308 	return SHAPE_IDX_I;
2309     if (State & CMDLINE)
2310     {
2311 	if (cmdline_at_end())
2312 	    return SHAPE_IDX_C;
2313 	if (cmdline_overstrike())
2314 	    return SHAPE_IDX_CR;
2315 	return SHAPE_IDX_CI;
2316     }
2317     if (finish_op)
2318 	return SHAPE_IDX_O;
2319     if (VIsual_active)
2320     {
2321 	if (*p_sel == 'e')
2322 	    return SHAPE_IDX_VE;
2323 	else
2324 	    return SHAPE_IDX_V;
2325     }
2326     return SHAPE_IDX_N;
2327 }
2328 #endif
2329 
2330 # if defined(FEAT_MOUSESHAPE) || defined(PROTO)
2331 static int old_mouse_shape = 0;
2332 
2333 /*
2334  * Set the mouse shape:
2335  * If "shape" is -1, use shape depending on the current mode,
2336  * depending on the current state.
2337  * If "shape" is -2, only update the shape when it's CLINE or STATUS (used
2338  * when the mouse moves off the status or command line).
2339  */
2340     void
update_mouseshape(int shape_idx)2341 update_mouseshape(int shape_idx)
2342 {
2343     int new_mouse_shape;
2344 
2345     // Only works in GUI mode.
2346     if (!gui.in_use || gui.starting)
2347 	return;
2348 
2349     // Postpone the updating when more is to come.  Speeds up executing of
2350     // mappings.
2351     if (shape_idx == -1 && char_avail())
2352     {
2353 	postponed_mouseshape = TRUE;
2354 	return;
2355     }
2356 
2357     // When ignoring the mouse don't change shape on the statusline.
2358     if (*p_mouse == NUL
2359 	    && (shape_idx == SHAPE_IDX_CLINE
2360 		|| shape_idx == SHAPE_IDX_STATUS
2361 		|| shape_idx == SHAPE_IDX_VSEP))
2362 	shape_idx = -2;
2363 
2364     if (shape_idx == -2
2365 	    && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape
2366 	    && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape
2367 	    && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape)
2368 	return;
2369     if (shape_idx < 0)
2370 	new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape;
2371     else
2372 	new_mouse_shape = shape_table[shape_idx].mshape;
2373     if (new_mouse_shape != old_mouse_shape)
2374     {
2375 	mch_set_mouse_shape(new_mouse_shape);
2376 	old_mouse_shape = new_mouse_shape;
2377     }
2378     postponed_mouseshape = FALSE;
2379 }
2380 # endif
2381 
2382 #endif // CURSOR_SHAPE
2383 
2384 
2385 /*
2386  * Change directory to "new_dir".  If FEAT_SEARCHPATH is defined, search
2387  * 'cdpath' for relative directory names, otherwise just mch_chdir().
2388  */
2389     int
vim_chdir(char_u * new_dir)2390 vim_chdir(char_u *new_dir)
2391 {
2392 #ifndef FEAT_SEARCHPATH
2393     return mch_chdir((char *)new_dir);
2394 #else
2395     char_u	*dir_name;
2396     int		r;
2397 
2398     dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
2399 						FNAME_MESS, curbuf->b_ffname);
2400     if (dir_name == NULL)
2401 	return -1;
2402     r = mch_chdir((char *)dir_name);
2403     vim_free(dir_name);
2404     return r;
2405 #endif
2406 }
2407 
2408 /*
2409  * Get user name from machine-specific function.
2410  * Returns the user name in "buf[len]".
2411  * Some systems are quite slow in obtaining the user name (Windows NT), thus
2412  * cache the result.
2413  * Returns OK or FAIL.
2414  */
2415     int
get_user_name(char_u * buf,int len)2416 get_user_name(char_u *buf, int len)
2417 {
2418     if (username == NULL)
2419     {
2420 	if (mch_get_user_name(buf, len) == FAIL)
2421 	    return FAIL;
2422 	username = vim_strsave(buf);
2423     }
2424     else
2425 	vim_strncpy(buf, username, len - 1);
2426     return OK;
2427 }
2428 
2429 /*
2430  * Free the memory allocated by get_user_name()
2431  */
2432     void
free_username(void)2433 free_username(void)
2434 {
2435     vim_free(username);
2436 }
2437 
2438 #ifndef HAVE_QSORT
2439 /*
2440  * Our own qsort(), for systems that don't have it.
2441  * It's simple and slow.  From the K&R C book.
2442  */
2443     void
qsort(void * base,size_t elm_count,size_t elm_size,int (* cmp)(const void *,const void *))2444 qsort(
2445     void	*base,
2446     size_t	elm_count,
2447     size_t	elm_size,
2448     int (*cmp)(const void *, const void *))
2449 {
2450     char_u	*buf;
2451     char_u	*p1;
2452     char_u	*p2;
2453     int		i, j;
2454     int		gap;
2455 
2456     buf = alloc(elm_size);
2457     if (buf == NULL)
2458 	return;
2459 
2460     for (gap = elm_count / 2; gap > 0; gap /= 2)
2461 	for (i = gap; i < elm_count; ++i)
2462 	    for (j = i - gap; j >= 0; j -= gap)
2463 	    {
2464 		// Compare the elements.
2465 		p1 = (char_u *)base + j * elm_size;
2466 		p2 = (char_u *)base + (j + gap) * elm_size;
2467 		if ((*cmp)((void *)p1, (void *)p2) <= 0)
2468 		    break;
2469 		// Exchange the elements.
2470 		mch_memmove(buf, p1, elm_size);
2471 		mch_memmove(p1, p2, elm_size);
2472 		mch_memmove(p2, buf, elm_size);
2473 	    }
2474 
2475     vim_free(buf);
2476 }
2477 #endif
2478 
2479 /*
2480  * The putenv() implementation below comes from the "screen" program.
2481  * Included with permission from Juergen Weigert.
2482  * See pty.c for the copyright notice.
2483  */
2484 
2485 /*
2486  *  putenv  --	put value into environment
2487  *
2488  *  Usage:  i = putenv (string)
2489  *    int i;
2490  *    char  *string;
2491  *
2492  *  where string is of the form <name>=<value>.
2493  *  Putenv returns 0 normally, -1 on error (not enough core for malloc).
2494  *
2495  *  Putenv may need to add a new name into the environment, or to
2496  *  associate a value longer than the current value with a particular
2497  *  name.  So, to make life simpler, putenv() copies your entire
2498  *  environment into the heap (i.e. malloc()) from the stack
2499  *  (i.e. where it resides when your process is initiated) the first
2500  *  time you call it.
2501  *
2502  *  (history removed, not very interesting.  See the "screen" sources.)
2503  */
2504 
2505 #if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
2506 
2507 #define EXTRASIZE 5		// increment to add to env. size
2508 
2509 static int  envsize = -1;	// current size of environment
2510 extern char **environ;		// the global which is your env.
2511 
2512 static int  findenv(char *name); // look for a name in the env.
2513 static int  newenv(void);	// copy env. from stack to heap
2514 static int  moreenv(void);	// incr. size of env.
2515 
2516     int
putenv(const char * string)2517 putenv(const char *string)
2518 {
2519     int	    i;
2520     char    *p;
2521 
2522     if (envsize < 0)
2523     {				// first time putenv called
2524 	if (newenv() < 0)	// copy env. to heap
2525 	    return -1;
2526     }
2527 
2528     i = findenv((char *)string); // look for name in environment
2529 
2530     if (i < 0)
2531     {				// name must be added
2532 	for (i = 0; environ[i]; i++);
2533 	if (i >= (envsize - 1))
2534 	{			// need new slot
2535 	    if (moreenv() < 0)
2536 		return -1;
2537 	}
2538 	p = alloc(strlen(string) + 1);
2539 	if (p == NULL)		// not enough core
2540 	    return -1;
2541 	environ[i + 1] = 0;	// new end of env.
2542     }
2543     else
2544     {				// name already in env.
2545 	p = vim_realloc(environ[i], strlen(string) + 1);
2546 	if (p == NULL)
2547 	    return -1;
2548     }
2549     sprintf(p, "%s", string);	// copy into env.
2550     environ[i] = p;
2551 
2552     return 0;
2553 }
2554 
2555     static int
findenv(char * name)2556 findenv(char *name)
2557 {
2558     char    *namechar, *envchar;
2559     int	    i, found;
2560 
2561     found = 0;
2562     for (i = 0; environ[i] && !found; i++)
2563     {
2564 	envchar = environ[i];
2565 	namechar = name;
2566 	while (*namechar && *namechar != '=' && (*namechar == *envchar))
2567 	{
2568 	    namechar++;
2569 	    envchar++;
2570 	}
2571 	found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
2572     }
2573     return found ? i - 1 : -1;
2574 }
2575 
2576     static int
newenv(void)2577 newenv(void)
2578 {
2579     char    **env, *elem;
2580     int	    i, esize;
2581 
2582     for (i = 0; environ[i]; i++)
2583 	;
2584 
2585     esize = i + EXTRASIZE + 1;
2586     env = ALLOC_MULT(char *, esize);
2587     if (env == NULL)
2588 	return -1;
2589 
2590     for (i = 0; environ[i]; i++)
2591     {
2592 	elem = alloc(strlen(environ[i]) + 1);
2593 	if (elem == NULL)
2594 	    return -1;
2595 	env[i] = elem;
2596 	strcpy(elem, environ[i]);
2597     }
2598 
2599     env[i] = 0;
2600     environ = env;
2601     envsize = esize;
2602     return 0;
2603 }
2604 
2605     static int
moreenv(void)2606 moreenv(void)
2607 {
2608     int	    esize;
2609     char    **env;
2610 
2611     esize = envsize + EXTRASIZE;
2612     env = vim_realloc((char *)environ, esize * sizeof (*env));
2613     if (env == 0)
2614 	return -1;
2615     environ = env;
2616     envsize = esize;
2617     return 0;
2618 }
2619 
2620 # ifdef USE_VIMPTY_GETENV
2621 /*
2622  * Used for mch_getenv() for Mac.
2623  */
2624     char_u *
vimpty_getenv(const char_u * string)2625 vimpty_getenv(const char_u *string)
2626 {
2627     int i;
2628     char_u *p;
2629 
2630     if (envsize < 0)
2631 	return NULL;
2632 
2633     i = findenv((char *)string);
2634 
2635     if (i < 0)
2636 	return NULL;
2637 
2638     p = vim_strchr((char_u *)environ[i], '=');
2639     return (p + 1);
2640 }
2641 # endif
2642 
2643 #endif // !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
2644 
2645 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO)
2646 /*
2647  * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
2648  * rights to write into.
2649  */
2650     int
filewritable(char_u * fname)2651 filewritable(char_u *fname)
2652 {
2653     int		retval = 0;
2654 #if defined(UNIX) || defined(VMS)
2655     int		perm = 0;
2656 #endif
2657 
2658 #if defined(UNIX) || defined(VMS)
2659     perm = mch_getperm(fname);
2660 #endif
2661     if (
2662 # ifdef MSWIN
2663 	    mch_writable(fname) &&
2664 # else
2665 # if defined(UNIX) || defined(VMS)
2666 	    (perm & 0222) &&
2667 #  endif
2668 # endif
2669 	    mch_access((char *)fname, W_OK) == 0
2670        )
2671     {
2672 	++retval;
2673 	if (mch_isdir(fname))
2674 	    ++retval;
2675     }
2676     return retval;
2677 }
2678 #endif
2679 
2680 #if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
2681 /*
2682  * Read 2 bytes from "fd" and turn them into an int, MSB first.
2683  * Returns -1 when encountering EOF.
2684  */
2685     int
get2c(FILE * fd)2686 get2c(FILE *fd)
2687 {
2688     int		c, n;
2689 
2690     n = getc(fd);
2691     if (n == EOF) return -1;
2692     c = getc(fd);
2693     if (c == EOF) return -1;
2694     return (n << 8) + c;
2695 }
2696 
2697 /*
2698  * Read 3 bytes from "fd" and turn them into an int, MSB first.
2699  * Returns -1 when encountering EOF.
2700  */
2701     int
get3c(FILE * fd)2702 get3c(FILE *fd)
2703 {
2704     int		c, n;
2705 
2706     n = getc(fd);
2707     if (n == EOF) return -1;
2708     c = getc(fd);
2709     if (c == EOF) return -1;
2710     n = (n << 8) + c;
2711     c = getc(fd);
2712     if (c == EOF) return -1;
2713     return (n << 8) + c;
2714 }
2715 
2716 /*
2717  * Read 4 bytes from "fd" and turn them into an int, MSB first.
2718  * Returns -1 when encountering EOF.
2719  */
2720     int
get4c(FILE * fd)2721 get4c(FILE *fd)
2722 {
2723     int		c;
2724     // Use unsigned rather than int otherwise result is undefined
2725     // when left-shift sets the MSB.
2726     unsigned	n;
2727 
2728     c = getc(fd);
2729     if (c == EOF) return -1;
2730     n = (unsigned)c;
2731     c = getc(fd);
2732     if (c == EOF) return -1;
2733     n = (n << 8) + (unsigned)c;
2734     c = getc(fd);
2735     if (c == EOF) return -1;
2736     n = (n << 8) + (unsigned)c;
2737     c = getc(fd);
2738     if (c == EOF) return -1;
2739     n = (n << 8) + (unsigned)c;
2740     return (int)n;
2741 }
2742 
2743 /*
2744  * Read a string of length "cnt" from "fd" into allocated memory.
2745  * Returns NULL when out of memory or unable to read that many bytes.
2746  */
2747     char_u *
read_string(FILE * fd,int cnt)2748 read_string(FILE *fd, int cnt)
2749 {
2750     char_u	*str;
2751     int		i;
2752     int		c;
2753 
2754     // allocate memory
2755     str = alloc(cnt + 1);
2756     if (str != NULL)
2757     {
2758 	// Read the string.  Quit when running into the EOF.
2759 	for (i = 0; i < cnt; ++i)
2760 	{
2761 	    c = getc(fd);
2762 	    if (c == EOF)
2763 	    {
2764 		vim_free(str);
2765 		return NULL;
2766 	    }
2767 	    str[i] = c;
2768 	}
2769 	str[i] = NUL;
2770     }
2771     return str;
2772 }
2773 
2774 /*
2775  * Write a number to file "fd", MSB first, in "len" bytes.
2776  */
2777     int
put_bytes(FILE * fd,long_u nr,int len)2778 put_bytes(FILE *fd, long_u nr, int len)
2779 {
2780     int	    i;
2781 
2782     for (i = len - 1; i >= 0; --i)
2783 	if (putc((int)(nr >> (i * 8)), fd) == EOF)
2784 	    return FAIL;
2785     return OK;
2786 }
2787 
2788 #endif
2789 
2790 #ifndef PROTO  // proto is defined in vim.h
2791 # ifdef ELAPSED_TIMEVAL
2792 /*
2793  * Return time in msec since "start_tv".
2794  */
2795     long
elapsed(struct timeval * start_tv)2796 elapsed(struct timeval *start_tv)
2797 {
2798     struct timeval  now_tv;
2799 
2800     gettimeofday(&now_tv, NULL);
2801     return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
2802 	 + (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
2803 }
2804 # endif
2805 
2806 # ifdef ELAPSED_TICKCOUNT
2807 /*
2808  * Return time in msec since "start_tick".
2809  */
2810     long
elapsed(DWORD start_tick)2811 elapsed(DWORD start_tick)
2812 {
2813     DWORD	now = GetTickCount();
2814 
2815     return (long)now - (long)start_tick;
2816 }
2817 # endif
2818 #endif
2819 
2820 #if defined(FEAT_JOB_CHANNEL) \
2821 	|| (defined(UNIX) && (!defined(USE_SYSTEM) \
2822 	|| (defined(FEAT_GUI) && defined(FEAT_TERMINAL)))) \
2823 	|| defined(PROTO)
2824 /*
2825  * Parse "cmd" and put the white-separated parts in "argv".
2826  * "argv" is an allocated array with "argc" entries and room for 4 more.
2827  * Returns FAIL when out of memory.
2828  */
2829     int
mch_parse_cmd(char_u * cmd,int use_shcf,char *** argv,int * argc)2830 mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc)
2831 {
2832     int		i;
2833     char_u	*p, *d;
2834     int		inquote;
2835 
2836     /*
2837      * Do this loop twice:
2838      * 1: find number of arguments
2839      * 2: separate them and build argv[]
2840      */
2841     for (i = 1; i <= 2; ++i)
2842     {
2843 	p = skipwhite(cmd);
2844 	inquote = FALSE;
2845 	*argc = 0;
2846 	while (*p != NUL)
2847 	{
2848 	    if (i == 2)
2849 		(*argv)[*argc] = (char *)p;
2850 	    ++*argc;
2851 	    d = p;
2852 	    while (*p != NUL && (inquote || (*p != ' ' && *p != TAB)))
2853 	    {
2854 		if (p[0] == '"')
2855 		    // quotes surrounding an argument and are dropped
2856 		    inquote = !inquote;
2857 		else
2858 		{
2859 		    if (rem_backslash(p))
2860 		    {
2861 			// First pass: skip over "\ " and "\"".
2862 			// Second pass: Remove the backslash.
2863 			++p;
2864 		    }
2865 		    if (i == 2)
2866 			*d++ = *p;
2867 		}
2868 		++p;
2869 	    }
2870 	    if (*p == NUL)
2871 	    {
2872 		if (i == 2)
2873 		    *d++ = NUL;
2874 		break;
2875 	    }
2876 	    if (i == 2)
2877 		*d++ = NUL;
2878 	    p = skipwhite(p + 1);
2879 	}
2880 	if (*argv == NULL)
2881 	{
2882 	    if (use_shcf)
2883 	    {
2884 		// Account for possible multiple args in p_shcf.
2885 		p = p_shcf;
2886 		for (;;)
2887 		{
2888 		    p = skiptowhite(p);
2889 		    if (*p == NUL)
2890 			break;
2891 		    ++*argc;
2892 		    p = skipwhite(p);
2893 		}
2894 	    }
2895 
2896 	    *argv = ALLOC_MULT(char *, *argc + 4);
2897 	    if (*argv == NULL)	    // out of memory
2898 		return FAIL;
2899 	}
2900     }
2901     return OK;
2902 }
2903 
2904 # if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
2905 /*
2906  * Build "argv[argc]" from the string "cmd".
2907  * "argv[argc]" is set to NULL;
2908  * Return FAIL when out of memory.
2909  */
2910     int
build_argv_from_string(char_u * cmd,char *** argv,int * argc)2911 build_argv_from_string(char_u *cmd, char ***argv, int *argc)
2912 {
2913     char_u	*cmd_copy;
2914     int		i;
2915 
2916     // Make a copy, parsing will modify "cmd".
2917     cmd_copy = vim_strsave(cmd);
2918     if (cmd_copy == NULL
2919 	    || mch_parse_cmd(cmd_copy, FALSE, argv, argc) == FAIL)
2920     {
2921 	vim_free(cmd_copy);
2922 	return FAIL;
2923     }
2924     for (i = 0; i < *argc; i++)
2925 	(*argv)[i] = (char *)vim_strsave((char_u *)(*argv)[i]);
2926     (*argv)[*argc] = NULL;
2927     vim_free(cmd_copy);
2928     return OK;
2929 }
2930 
2931 /*
2932  * Build "argv[argc]" from the list "l".
2933  * "argv[argc]" is set to NULL;
2934  * Return FAIL when out of memory.
2935  */
2936     int
build_argv_from_list(list_T * l,char *** argv,int * argc)2937 build_argv_from_list(list_T *l, char ***argv, int *argc)
2938 {
2939     listitem_T  *li;
2940     char_u	*s;
2941 
2942     // Pass argv[] to mch_call_shell().
2943     *argv = ALLOC_MULT(char *, l->lv_len + 1);
2944     if (*argv == NULL)
2945 	return FAIL;
2946     *argc = 0;
2947     FOR_ALL_LIST_ITEMS(l, li)
2948     {
2949 	s = tv_get_string_chk(&li->li_tv);
2950 	if (s == NULL)
2951 	{
2952 	    int i;
2953 
2954 	    for (i = 0; i < *argc; ++i)
2955 		VIM_CLEAR((*argv)[i]);
2956 	    (*argv)[0] = NULL;
2957 	    return FAIL;
2958 	}
2959 	(*argv)[*argc] = (char *)vim_strsave(s);
2960 	*argc += 1;
2961     }
2962     (*argv)[*argc] = NULL;
2963     return OK;
2964 }
2965 # endif
2966 #endif
2967 
2968 /*
2969  * Change the behavior of vterm.
2970  * 0: As usual.
2971  * 1: Windows 10 version 1809
2972  *      The bug causes unstable handling of ambiguous width character.
2973  * 2: Windows 10 version 1903 & 1909
2974  *      Use the wrong result because each result is different.
2975  * 3: Windows 10 insider preview (current latest logic)
2976  */
2977     int
get_special_pty_type(void)2978 get_special_pty_type(void)
2979 {
2980 #ifdef MSWIN
2981     return get_conpty_type();
2982 #else
2983     return 0;
2984 #endif
2985 }
2986