1edf3f97aSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2071d4279SBram Moolenaar *
3071d4279SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar
4071d4279SBram Moolenaar *
5071d4279SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions.
6071d4279SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed.
7071d4279SBram Moolenaar * See README.txt for an overview of the Vim source code.
8071d4279SBram Moolenaar */
9071d4279SBram Moolenaar
10071d4279SBram Moolenaar /*
11071d4279SBram Moolenaar * misc2.c: Various functions.
12071d4279SBram Moolenaar */
13071d4279SBram Moolenaar #include "vim.h"
14071d4279SBram Moolenaar
1585a2002aSBram Moolenaar static char_u *username = NULL; // cached result of mch_get_user_name()
16f461c8e7SBram Moolenaar
1792b8b2d3SBram Moolenaar static int coladvance2(pos_T *pos, int addspaces, int finetune, colnr_T wcol);
18071d4279SBram Moolenaar
19071d4279SBram Moolenaar /*
20071d4279SBram Moolenaar * Return TRUE if in the current mode we need to use virtual.
21071d4279SBram Moolenaar */
22071d4279SBram Moolenaar int
virtual_active(void)239b57814dSBram Moolenaar virtual_active(void)
24071d4279SBram Moolenaar {
2553ba05b0SGary Johnson unsigned int cur_ve_flags = get_ve_flags();
2653ba05b0SGary Johnson
2785a2002aSBram Moolenaar // While an operator is being executed we return "virtual_op", because
2885a2002aSBram Moolenaar // VIsual_active has already been reset, thus we can't check for "block"
2985a2002aSBram Moolenaar // being used.
30071d4279SBram Moolenaar if (virtual_op != MAYBE)
31071d4279SBram Moolenaar return virtual_op;
3253ba05b0SGary Johnson return (cur_ve_flags == VE_ALL
3353ba05b0SGary Johnson || ((cur_ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
3453ba05b0SGary Johnson || ((cur_ve_flags & VE_INSERT) && (State & INSERT)));
35071d4279SBram Moolenaar }
36071d4279SBram Moolenaar
37071d4279SBram Moolenaar /*
38071d4279SBram Moolenaar * Get the screen position of the cursor.
39071d4279SBram Moolenaar */
40071d4279SBram Moolenaar int
getviscol(void)419b57814dSBram Moolenaar getviscol(void)
42071d4279SBram Moolenaar {
43071d4279SBram Moolenaar colnr_T x;
44071d4279SBram Moolenaar
45071d4279SBram Moolenaar getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);
46071d4279SBram Moolenaar return (int)x;
47071d4279SBram Moolenaar }
48071d4279SBram Moolenaar
49071d4279SBram Moolenaar /*
507aa9f6a0SBram Moolenaar * Go to column "wcol", and add/insert white space as necessary to get the
51071d4279SBram Moolenaar * cursor in that column.
52071d4279SBram Moolenaar * The caller must have saved the cursor line for undo!
53071d4279SBram Moolenaar */
54071d4279SBram Moolenaar int
coladvance_force(colnr_T wcol)559b57814dSBram Moolenaar coladvance_force(colnr_T wcol)
56071d4279SBram Moolenaar {
57071d4279SBram Moolenaar int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);
58071d4279SBram Moolenaar
59071d4279SBram Moolenaar if (wcol == MAXCOL)
60071d4279SBram Moolenaar curwin->w_valid &= ~VALID_VIRTCOL;
61071d4279SBram Moolenaar else
62071d4279SBram Moolenaar {
6385a2002aSBram Moolenaar // Virtcol is valid
64071d4279SBram Moolenaar curwin->w_valid |= VALID_VIRTCOL;
65071d4279SBram Moolenaar curwin->w_virtcol = wcol;
66071d4279SBram Moolenaar }
67071d4279SBram Moolenaar return rc;
68071d4279SBram Moolenaar }
69071d4279SBram Moolenaar
70071d4279SBram Moolenaar /*
71977239efSBram Moolenaar * Get the screen position of character col with a coladd in the cursor line.
72977239efSBram Moolenaar */
73977239efSBram Moolenaar int
getviscol2(colnr_T col,colnr_T coladd UNUSED)74fc3abf47SBram Moolenaar getviscol2(colnr_T col, colnr_T coladd UNUSED)
75977239efSBram Moolenaar {
76977239efSBram Moolenaar colnr_T x;
77977239efSBram Moolenaar pos_T pos;
78977239efSBram Moolenaar
79977239efSBram Moolenaar pos.lnum = curwin->w_cursor.lnum;
80977239efSBram Moolenaar pos.col = col;
81977239efSBram Moolenaar pos.coladd = coladd;
82977239efSBram Moolenaar getvvcol(curwin, &pos, &x, NULL, NULL);
83977239efSBram Moolenaar return (int)x;
84977239efSBram Moolenaar }
85977239efSBram Moolenaar
86977239efSBram Moolenaar /*
87071d4279SBram Moolenaar * Try to advance the Cursor to the specified screen column.
88071d4279SBram Moolenaar * If virtual editing: fine tune the cursor position.
89071d4279SBram Moolenaar * Note that all virtual positions off the end of a line should share
90071d4279SBram Moolenaar * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
91071d4279SBram Moolenaar * beginning at coladd 0.
92071d4279SBram Moolenaar *
93071d4279SBram Moolenaar * return OK if desired column is reached, FAIL if not
94071d4279SBram Moolenaar */
95071d4279SBram Moolenaar int
coladvance(colnr_T wcol)969b57814dSBram Moolenaar coladvance(colnr_T wcol)
97071d4279SBram Moolenaar {
98071d4279SBram Moolenaar int rc = getvpos(&curwin->w_cursor, wcol);
99071d4279SBram Moolenaar
100071d4279SBram Moolenaar if (wcol == MAXCOL || rc == FAIL)
101071d4279SBram Moolenaar curwin->w_valid &= ~VALID_VIRTCOL;
102dfccaf0fSBram Moolenaar else if (*ml_get_cursor() != TAB)
103071d4279SBram Moolenaar {
10485a2002aSBram Moolenaar // Virtcol is valid when not on a TAB
105071d4279SBram Moolenaar curwin->w_valid |= VALID_VIRTCOL;
106071d4279SBram Moolenaar curwin->w_virtcol = wcol;
107071d4279SBram Moolenaar }
108071d4279SBram Moolenaar return rc;
109071d4279SBram Moolenaar }
110071d4279SBram Moolenaar
111071d4279SBram Moolenaar /*
112071d4279SBram Moolenaar * Return in "pos" the position of the cursor advanced to screen column "wcol".
113071d4279SBram Moolenaar * return OK if desired column is reached, FAIL if not
114071d4279SBram Moolenaar */
115071d4279SBram Moolenaar int
getvpos(pos_T * pos,colnr_T wcol)1169b57814dSBram Moolenaar getvpos(pos_T *pos, colnr_T wcol)
117071d4279SBram Moolenaar {
118071d4279SBram Moolenaar return coladvance2(pos, FALSE, virtual_active(), wcol);
119071d4279SBram Moolenaar }
120071d4279SBram Moolenaar
121071d4279SBram Moolenaar static int
coladvance2(pos_T * pos,int addspaces,int finetune,colnr_T wcol_arg)1229b57814dSBram Moolenaar coladvance2(
1239b57814dSBram Moolenaar pos_T *pos,
124ceba3dd5SBram Moolenaar int addspaces, // change the text to achieve our goal?
125ceba3dd5SBram Moolenaar int finetune, // change char offset for the exact column
126ceba3dd5SBram Moolenaar colnr_T wcol_arg) // column to move to (can be negative)
127071d4279SBram Moolenaar {
128ceba3dd5SBram Moolenaar colnr_T wcol = wcol_arg;
129071d4279SBram Moolenaar int idx;
130071d4279SBram Moolenaar char_u *ptr;
131071d4279SBram Moolenaar char_u *line;
132071d4279SBram Moolenaar colnr_T col = 0;
133071d4279SBram Moolenaar int csize = 0;
134071d4279SBram Moolenaar int one_more;
135071d4279SBram Moolenaar #ifdef FEAT_LINEBREAK
136071d4279SBram Moolenaar int head = 0;
137071d4279SBram Moolenaar #endif
138071d4279SBram Moolenaar
139efd2bf15SBram Moolenaar one_more = (State & INSERT)
140efd2bf15SBram Moolenaar || restart_edit != NUL
141071d4279SBram Moolenaar || (VIsual_active && *p_sel != 'o')
14253ba05b0SGary Johnson || ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
143a1381de5SBram Moolenaar line = ml_get_buf(curbuf, pos->lnum, FALSE);
144071d4279SBram Moolenaar
145071d4279SBram Moolenaar if (wcol >= MAXCOL)
146071d4279SBram Moolenaar {
147071d4279SBram Moolenaar idx = (int)STRLEN(line) - 1 + one_more;
148071d4279SBram Moolenaar col = wcol;
149071d4279SBram Moolenaar
150071d4279SBram Moolenaar if ((addspaces || finetune) && !VIsual_active)
151071d4279SBram Moolenaar {
152071d4279SBram Moolenaar curwin->w_curswant = linetabsize(line) + one_more;
153071d4279SBram Moolenaar if (curwin->w_curswant > 0)
154071d4279SBram Moolenaar --curwin->w_curswant;
155071d4279SBram Moolenaar }
156071d4279SBram Moolenaar }
157071d4279SBram Moolenaar else
158071d4279SBram Moolenaar {
1590263146bSBram Moolenaar int width = curwin->w_width - win_col_off(curwin);
160071d4279SBram Moolenaar
161ebefac63SBram Moolenaar if (finetune
162071d4279SBram Moolenaar && curwin->w_p_wrap
163071d4279SBram Moolenaar && curwin->w_width != 0
16402f8694aSBram Moolenaar && wcol >= (colnr_T)width
16502f8694aSBram Moolenaar && width > 0)
166071d4279SBram Moolenaar {
167071d4279SBram Moolenaar csize = linetabsize(line);
168071d4279SBram Moolenaar if (csize > 0)
169071d4279SBram Moolenaar csize--;
170071d4279SBram Moolenaar
171ebefac63SBram Moolenaar if (wcol / width > (colnr_T)csize / width
172ebefac63SBram Moolenaar && ((State & INSERT) == 0 || (int)wcol > csize + 1))
173071d4279SBram Moolenaar {
17485a2002aSBram Moolenaar // In case of line wrapping don't move the cursor beyond the
17585a2002aSBram Moolenaar // right screen edge. In Insert mode allow going just beyond
17685a2002aSBram Moolenaar // the last character (like what happens when typing and
17785a2002aSBram Moolenaar // reaching the right window edge).
178071d4279SBram Moolenaar wcol = (csize / width + 1) * width - 1;
179071d4279SBram Moolenaar }
180071d4279SBram Moolenaar }
181071d4279SBram Moolenaar
182071d4279SBram Moolenaar ptr = line;
183071d4279SBram Moolenaar while (col <= wcol && *ptr != NUL)
184071d4279SBram Moolenaar {
18585a2002aSBram Moolenaar // Count a tab for what it's worth (if list mode not on)
186071d4279SBram Moolenaar #ifdef FEAT_LINEBREAK
187597a4224SBram Moolenaar csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
18891acfffcSBram Moolenaar MB_PTR_ADV(ptr);
189071d4279SBram Moolenaar #else
190597a4224SBram Moolenaar csize = lbr_chartabsize_adv(line, &ptr, col);
191071d4279SBram Moolenaar #endif
192071d4279SBram Moolenaar col += csize;
193071d4279SBram Moolenaar }
194071d4279SBram Moolenaar idx = (int)(ptr - line);
195071d4279SBram Moolenaar /*
196071d4279SBram Moolenaar * Handle all the special cases. The virtual_active() check
197071d4279SBram Moolenaar * is needed to ensure that a virtual position off the end of
198071d4279SBram Moolenaar * a line has the correct indexing. The one_more comparison
199071d4279SBram Moolenaar * replaces an explicit add of one_more later on.
200071d4279SBram Moolenaar */
201071d4279SBram Moolenaar if (col > wcol || (!virtual_active() && one_more == 0))
202071d4279SBram Moolenaar {
203071d4279SBram Moolenaar idx -= 1;
204071d4279SBram Moolenaar # ifdef FEAT_LINEBREAK
20585a2002aSBram Moolenaar // Don't count the chars from 'showbreak'.
206071d4279SBram Moolenaar csize -= head;
207071d4279SBram Moolenaar # endif
208071d4279SBram Moolenaar col -= csize;
209071d4279SBram Moolenaar }
210071d4279SBram Moolenaar
211071d4279SBram Moolenaar if (virtual_active()
212071d4279SBram Moolenaar && addspaces
213ceba3dd5SBram Moolenaar && wcol >= 0
214071d4279SBram Moolenaar && ((col != wcol && col != wcol + 1) || csize > 1))
215071d4279SBram Moolenaar {
21685a2002aSBram Moolenaar // 'virtualedit' is set: The difference between wcol and col is
21785a2002aSBram Moolenaar // filled with spaces.
218071d4279SBram Moolenaar
219071d4279SBram Moolenaar if (line[idx] == NUL)
220071d4279SBram Moolenaar {
22185a2002aSBram Moolenaar // Append spaces
222071d4279SBram Moolenaar int correct = wcol - col;
223071d4279SBram Moolenaar char_u *newline = alloc(idx + correct + 1);
224071d4279SBram Moolenaar int t;
225071d4279SBram Moolenaar
226071d4279SBram Moolenaar if (newline == NULL)
227071d4279SBram Moolenaar return FAIL;
228071d4279SBram Moolenaar
229071d4279SBram Moolenaar for (t = 0; t < idx; ++t)
230071d4279SBram Moolenaar newline[t] = line[t];
231071d4279SBram Moolenaar
232071d4279SBram Moolenaar for (t = 0; t < correct; ++t)
233071d4279SBram Moolenaar newline[t + idx] = ' ';
234071d4279SBram Moolenaar
235071d4279SBram Moolenaar newline[idx + correct] = NUL;
236071d4279SBram Moolenaar
237071d4279SBram Moolenaar ml_replace(pos->lnum, newline, FALSE);
238071d4279SBram Moolenaar changed_bytes(pos->lnum, (colnr_T)idx);
239071d4279SBram Moolenaar idx += correct;
240071d4279SBram Moolenaar col = wcol;
241071d4279SBram Moolenaar }
242071d4279SBram Moolenaar else
243071d4279SBram Moolenaar {
24485a2002aSBram Moolenaar // Break a tab
245071d4279SBram Moolenaar int linelen = (int)STRLEN(line);
24685a2002aSBram Moolenaar int correct = wcol - col - csize + 1; // negative!!
247eb3593b3SBram Moolenaar char_u *newline;
248071d4279SBram Moolenaar int t, s = 0;
249071d4279SBram Moolenaar int v;
250071d4279SBram Moolenaar
251eb3593b3SBram Moolenaar if (-correct > csize)
252eb3593b3SBram Moolenaar return FAIL;
253eb3593b3SBram Moolenaar
254eb3593b3SBram Moolenaar newline = alloc(linelen + csize);
255eb3593b3SBram Moolenaar if (newline == NULL)
256071d4279SBram Moolenaar return FAIL;
257071d4279SBram Moolenaar
258071d4279SBram Moolenaar for (t = 0; t < linelen; t++)
259071d4279SBram Moolenaar {
260071d4279SBram Moolenaar if (t != idx)
261071d4279SBram Moolenaar newline[s++] = line[t];
262071d4279SBram Moolenaar else
263071d4279SBram Moolenaar for (v = 0; v < csize; v++)
264071d4279SBram Moolenaar newline[s++] = ' ';
265071d4279SBram Moolenaar }
266071d4279SBram Moolenaar
267071d4279SBram Moolenaar newline[linelen + csize - 1] = NUL;
268071d4279SBram Moolenaar
269071d4279SBram Moolenaar ml_replace(pos->lnum, newline, FALSE);
270071d4279SBram Moolenaar changed_bytes(pos->lnum, idx);
271071d4279SBram Moolenaar idx += (csize - 1 + correct);
272071d4279SBram Moolenaar col += correct;
273071d4279SBram Moolenaar }
274071d4279SBram Moolenaar }
275071d4279SBram Moolenaar }
276071d4279SBram Moolenaar
277071d4279SBram Moolenaar if (idx < 0)
278071d4279SBram Moolenaar pos->col = 0;
279071d4279SBram Moolenaar else
280071d4279SBram Moolenaar pos->col = idx;
281071d4279SBram Moolenaar
282071d4279SBram Moolenaar pos->coladd = 0;
283071d4279SBram Moolenaar
284071d4279SBram Moolenaar if (finetune)
285071d4279SBram Moolenaar {
286071d4279SBram Moolenaar if (wcol == MAXCOL)
287071d4279SBram Moolenaar {
28885a2002aSBram Moolenaar // The width of the last character is used to set coladd.
289071d4279SBram Moolenaar if (!one_more)
290071d4279SBram Moolenaar {
291071d4279SBram Moolenaar colnr_T scol, ecol;
292071d4279SBram Moolenaar
293071d4279SBram Moolenaar getvcol(curwin, pos, &scol, NULL, &ecol);
294071d4279SBram Moolenaar pos->coladd = ecol - scol;
295071d4279SBram Moolenaar }
296071d4279SBram Moolenaar }
297071d4279SBram Moolenaar else
298071d4279SBram Moolenaar {
299071d4279SBram Moolenaar int b = (int)wcol - (int)col;
300071d4279SBram Moolenaar
30185a2002aSBram Moolenaar // The difference between wcol and col is used to set coladd.
3020263146bSBram Moolenaar if (b > 0 && b < (MAXCOL - 2 * curwin->w_width))
303071d4279SBram Moolenaar pos->coladd = b;
304071d4279SBram Moolenaar
305071d4279SBram Moolenaar col += b;
306071d4279SBram Moolenaar }
307071d4279SBram Moolenaar }
308071d4279SBram Moolenaar
30985a2002aSBram Moolenaar // prevent from moving onto a trail byte
310071d4279SBram Moolenaar if (has_mbyte)
31103a807aaSBram Moolenaar mb_adjustpos(curbuf, pos);
312071d4279SBram Moolenaar
313ceba3dd5SBram Moolenaar if (wcol < 0 || col < wcol)
314071d4279SBram Moolenaar return FAIL;
315071d4279SBram Moolenaar return OK;
316071d4279SBram Moolenaar }
317071d4279SBram Moolenaar
318071d4279SBram Moolenaar /*
319446cb837SBram Moolenaar * Increment the cursor position. See inc() for return values.
320071d4279SBram Moolenaar */
321071d4279SBram Moolenaar int
inc_cursor(void)3229b57814dSBram Moolenaar inc_cursor(void)
323071d4279SBram Moolenaar {
324071d4279SBram Moolenaar return inc(&curwin->w_cursor);
325071d4279SBram Moolenaar }
326071d4279SBram Moolenaar
327446cb837SBram Moolenaar /*
328446cb837SBram Moolenaar * Increment the line pointer "lp" crossing line boundaries as necessary.
329446cb837SBram Moolenaar * Return 1 when going to the next line.
330446cb837SBram Moolenaar * Return 2 when moving forward onto a NUL at the end of the line).
331446cb837SBram Moolenaar * Return -1 when at the end of file.
332446cb837SBram Moolenaar * Return 0 otherwise.
333446cb837SBram Moolenaar */
334071d4279SBram Moolenaar int
inc(pos_T * lp)3359b57814dSBram Moolenaar inc(pos_T *lp)
336071d4279SBram Moolenaar {
3378ada6aa9SBram Moolenaar char_u *p;
338071d4279SBram Moolenaar
33985a2002aSBram Moolenaar // when searching position may be set to end of a line
3408ada6aa9SBram Moolenaar if (lp->col != MAXCOL)
3418ada6aa9SBram Moolenaar {
3428ada6aa9SBram Moolenaar p = ml_get_pos(lp);
34385a2002aSBram Moolenaar if (*p != NUL) // still within line, move to next char (may be NUL)
344071d4279SBram Moolenaar {
345071d4279SBram Moolenaar if (has_mbyte)
346071d4279SBram Moolenaar {
3470fa313a7SBram Moolenaar int l = (*mb_ptr2len)(p);
348071d4279SBram Moolenaar
349071d4279SBram Moolenaar lp->col += l;
350071d4279SBram Moolenaar return ((p[l] != NUL) ? 0 : 2);
351071d4279SBram Moolenaar }
352071d4279SBram Moolenaar lp->col++;
353071d4279SBram Moolenaar lp->coladd = 0;
354071d4279SBram Moolenaar return ((p[1] != NUL) ? 0 : 2);
355071d4279SBram Moolenaar }
3568ada6aa9SBram Moolenaar }
35785a2002aSBram Moolenaar if (lp->lnum != curbuf->b_ml.ml_line_count) // there is a next line
358071d4279SBram Moolenaar {
359071d4279SBram Moolenaar lp->col = 0;
360071d4279SBram Moolenaar lp->lnum++;
361071d4279SBram Moolenaar lp->coladd = 0;
362071d4279SBram Moolenaar return 1;
363071d4279SBram Moolenaar }
364071d4279SBram Moolenaar return -1;
365071d4279SBram Moolenaar }
366071d4279SBram Moolenaar
367071d4279SBram Moolenaar /*
368071d4279SBram Moolenaar * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
369071d4279SBram Moolenaar */
370071d4279SBram Moolenaar int
incl(pos_T * lp)3719b57814dSBram Moolenaar incl(pos_T *lp)
372071d4279SBram Moolenaar {
373071d4279SBram Moolenaar int r;
374071d4279SBram Moolenaar
375071d4279SBram Moolenaar if ((r = inc(lp)) >= 1 && lp->col)
376071d4279SBram Moolenaar r = inc(lp);
377071d4279SBram Moolenaar return r;
378071d4279SBram Moolenaar }
379071d4279SBram Moolenaar
380071d4279SBram Moolenaar /*
381071d4279SBram Moolenaar * dec(p)
382071d4279SBram Moolenaar *
383071d4279SBram Moolenaar * Decrement the line pointer 'p' crossing line boundaries as necessary.
384071d4279SBram Moolenaar * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
385071d4279SBram Moolenaar */
386071d4279SBram Moolenaar int
dec_cursor(void)3879b57814dSBram Moolenaar dec_cursor(void)
388071d4279SBram Moolenaar {
389071d4279SBram Moolenaar return dec(&curwin->w_cursor);
390071d4279SBram Moolenaar }
391071d4279SBram Moolenaar
392071d4279SBram Moolenaar int
dec(pos_T * lp)3939b57814dSBram Moolenaar dec(pos_T *lp)
394071d4279SBram Moolenaar {
395071d4279SBram Moolenaar char_u *p;
396071d4279SBram Moolenaar
397071d4279SBram Moolenaar lp->coladd = 0;
3981bd999f9SBram Moolenaar if (lp->col == MAXCOL)
399071d4279SBram Moolenaar {
40085a2002aSBram Moolenaar // past end of line
4011bd999f9SBram Moolenaar p = ml_get(lp->lnum);
4021bd999f9SBram Moolenaar lp->col = (colnr_T)STRLEN(p);
4031bd999f9SBram Moolenaar if (has_mbyte)
4041bd999f9SBram Moolenaar lp->col -= (*mb_head_off)(p, p + lp->col);
4051bd999f9SBram Moolenaar return 0;
4061bd999f9SBram Moolenaar }
4071bd999f9SBram Moolenaar
4081bd999f9SBram Moolenaar if (lp->col > 0)
4091bd999f9SBram Moolenaar {
41085a2002aSBram Moolenaar // still within line
411071d4279SBram Moolenaar lp->col--;
412071d4279SBram Moolenaar if (has_mbyte)
413071d4279SBram Moolenaar {
414071d4279SBram Moolenaar p = ml_get(lp->lnum);
415071d4279SBram Moolenaar lp->col -= (*mb_head_off)(p, p + lp->col);
416071d4279SBram Moolenaar }
417071d4279SBram Moolenaar return 0;
418071d4279SBram Moolenaar }
4191bd999f9SBram Moolenaar
4201bd999f9SBram Moolenaar if (lp->lnum > 1)
421071d4279SBram Moolenaar {
42285a2002aSBram Moolenaar // there is a prior line
423071d4279SBram Moolenaar lp->lnum--;
424071d4279SBram Moolenaar p = ml_get(lp->lnum);
425071d4279SBram Moolenaar lp->col = (colnr_T)STRLEN(p);
426071d4279SBram Moolenaar if (has_mbyte)
427071d4279SBram Moolenaar lp->col -= (*mb_head_off)(p, p + lp->col);
428071d4279SBram Moolenaar return 1;
429071d4279SBram Moolenaar }
4301bd999f9SBram Moolenaar
43185a2002aSBram Moolenaar // at start of file
4321bd999f9SBram Moolenaar return -1;
433071d4279SBram Moolenaar }
434071d4279SBram Moolenaar
435071d4279SBram Moolenaar /*
436071d4279SBram Moolenaar * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
437071d4279SBram Moolenaar */
438071d4279SBram Moolenaar int
decl(pos_T * lp)4399b57814dSBram Moolenaar decl(pos_T *lp)
440071d4279SBram Moolenaar {
441071d4279SBram Moolenaar int r;
442071d4279SBram Moolenaar
443071d4279SBram Moolenaar if ((r = dec(lp)) == 1 && lp->col)
444071d4279SBram Moolenaar r = dec(lp);
445071d4279SBram Moolenaar return r;
446071d4279SBram Moolenaar }
447071d4279SBram Moolenaar
448071d4279SBram Moolenaar /*
44964486671SBram Moolenaar * Get the line number relative to the current cursor position, i.e. the
45064486671SBram Moolenaar * difference between line number and cursor position. Only look for lines that
45164486671SBram Moolenaar * can be visible, folded lines don't count.
45264486671SBram Moolenaar */
45364486671SBram Moolenaar linenr_T
get_cursor_rel_lnum(win_T * wp,linenr_T lnum)4549b57814dSBram Moolenaar get_cursor_rel_lnum(
4559b57814dSBram Moolenaar win_T *wp,
45685a2002aSBram Moolenaar linenr_T lnum) // line number to get the result for
45764486671SBram Moolenaar {
45864486671SBram Moolenaar linenr_T cursor = wp->w_cursor.lnum;
45964486671SBram Moolenaar linenr_T retval = 0;
46064486671SBram Moolenaar
46164486671SBram Moolenaar #ifdef FEAT_FOLDING
46264486671SBram Moolenaar if (hasAnyFolding(wp))
46364486671SBram Moolenaar {
46464486671SBram Moolenaar if (lnum > cursor)
46564486671SBram Moolenaar {
46664486671SBram Moolenaar while (lnum > cursor)
46764486671SBram Moolenaar {
4680bd7b3f4SBram Moolenaar (void)hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL);
46985a2002aSBram Moolenaar // if lnum and cursor are in the same fold,
47085a2002aSBram Moolenaar // now lnum <= cursor
47164486671SBram Moolenaar if (lnum > cursor)
47264486671SBram Moolenaar retval++;
47364486671SBram Moolenaar lnum--;
47464486671SBram Moolenaar }
47564486671SBram Moolenaar }
47664486671SBram Moolenaar else if (lnum < cursor)
47764486671SBram Moolenaar {
47864486671SBram Moolenaar while (lnum < cursor)
47964486671SBram Moolenaar {
4800bd7b3f4SBram Moolenaar (void)hasFoldingWin(wp, lnum, NULL, &lnum, TRUE, NULL);
48185a2002aSBram Moolenaar // if lnum and cursor are in the same fold,
48285a2002aSBram Moolenaar // now lnum >= cursor
48364486671SBram Moolenaar if (lnum < cursor)
48464486671SBram Moolenaar retval--;
48564486671SBram Moolenaar lnum++;
48664486671SBram Moolenaar }
48764486671SBram Moolenaar }
48885a2002aSBram Moolenaar // else if (lnum == cursor)
48985a2002aSBram Moolenaar // retval = 0;
49064486671SBram Moolenaar }
49164486671SBram Moolenaar else
49264486671SBram Moolenaar #endif
49364486671SBram Moolenaar retval = lnum - cursor;
49464486671SBram Moolenaar
49564486671SBram Moolenaar return retval;
49664486671SBram Moolenaar }
49764486671SBram Moolenaar
49864486671SBram Moolenaar /*
499d5824ce1SBram Moolenaar * Make sure "pos.lnum" and "pos.col" are valid in "buf".
500d5824ce1SBram Moolenaar * This allows for the col to be on the NUL byte.
501d5824ce1SBram Moolenaar */
502d5824ce1SBram Moolenaar void
check_pos(buf_T * buf,pos_T * pos)503d5824ce1SBram Moolenaar check_pos(buf_T *buf, pos_T *pos)
504d5824ce1SBram Moolenaar {
505d5824ce1SBram Moolenaar char_u *line;
506d5824ce1SBram Moolenaar colnr_T len;
507d5824ce1SBram Moolenaar
508d5824ce1SBram Moolenaar if (pos->lnum > buf->b_ml.ml_line_count)
509d5824ce1SBram Moolenaar pos->lnum = buf->b_ml.ml_line_count;
510d5824ce1SBram Moolenaar
511d5824ce1SBram Moolenaar if (pos->col > 0)
512d5824ce1SBram Moolenaar {
513d5824ce1SBram Moolenaar line = ml_get_buf(buf, pos->lnum, FALSE);
514d5824ce1SBram Moolenaar len = (colnr_T)STRLEN(line);
515d5824ce1SBram Moolenaar if (pos->col > len)
516d5824ce1SBram Moolenaar pos->col = len;
517d5824ce1SBram Moolenaar }
518d5824ce1SBram Moolenaar }
519d5824ce1SBram Moolenaar
520d5824ce1SBram Moolenaar /*
521071d4279SBram Moolenaar * Make sure curwin->w_cursor.lnum is valid.
522071d4279SBram Moolenaar */
523071d4279SBram Moolenaar void
check_cursor_lnum(void)5249b57814dSBram Moolenaar check_cursor_lnum(void)
525071d4279SBram Moolenaar {
526071d4279SBram Moolenaar if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
527071d4279SBram Moolenaar {
528071d4279SBram Moolenaar #ifdef FEAT_FOLDING
52985a2002aSBram Moolenaar // If there is a closed fold at the end of the file, put the cursor in
53085a2002aSBram Moolenaar // its first line. Otherwise in the last line.
531071d4279SBram Moolenaar if (!hasFolding(curbuf->b_ml.ml_line_count,
532071d4279SBram Moolenaar &curwin->w_cursor.lnum, NULL))
533071d4279SBram Moolenaar #endif
534071d4279SBram Moolenaar curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
535071d4279SBram Moolenaar }
536071d4279SBram Moolenaar if (curwin->w_cursor.lnum <= 0)
537071d4279SBram Moolenaar curwin->w_cursor.lnum = 1;
538071d4279SBram Moolenaar }
539071d4279SBram Moolenaar
540071d4279SBram Moolenaar /*
541071d4279SBram Moolenaar * Make sure curwin->w_cursor.col is valid.
542071d4279SBram Moolenaar */
543071d4279SBram Moolenaar void
check_cursor_col(void)5449b57814dSBram Moolenaar check_cursor_col(void)
545071d4279SBram Moolenaar {
54603a807aaSBram Moolenaar check_cursor_col_win(curwin);
54703a807aaSBram Moolenaar }
54803a807aaSBram Moolenaar
54903a807aaSBram Moolenaar /*
55003a807aaSBram Moolenaar * Make sure win->w_cursor.col is valid.
55103a807aaSBram Moolenaar */
55203a807aaSBram Moolenaar void
check_cursor_col_win(win_T * win)5539b57814dSBram Moolenaar check_cursor_col_win(win_T *win)
55403a807aaSBram Moolenaar {
555071d4279SBram Moolenaar colnr_T len;
55603a807aaSBram Moolenaar colnr_T oldcol = win->w_cursor.col;
55703a807aaSBram Moolenaar colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd;
55853ba05b0SGary Johnson unsigned int cur_ve_flags = get_ve_flags();
559071d4279SBram Moolenaar
56003a807aaSBram Moolenaar len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE));
561071d4279SBram Moolenaar if (len == 0)
56203a807aaSBram Moolenaar win->w_cursor.col = 0;
56303a807aaSBram Moolenaar else if (win->w_cursor.col >= len)
564071d4279SBram Moolenaar {
56585a2002aSBram Moolenaar // Allow cursor past end-of-line when:
56685a2002aSBram Moolenaar // - in Insert mode or restarting Insert mode
56785a2002aSBram Moolenaar // - in Visual mode and 'selection' isn't "old"
56885a2002aSBram Moolenaar // - 'virtualedit' is set
569ebefac63SBram Moolenaar if ((State & INSERT) || restart_edit
570071d4279SBram Moolenaar || (VIsual_active && *p_sel != 'o')
57153ba05b0SGary Johnson || (cur_ve_flags & VE_ONEMORE)
572071d4279SBram Moolenaar || virtual_active())
57303a807aaSBram Moolenaar win->w_cursor.col = len;
574071d4279SBram Moolenaar else
57587c19964SBram Moolenaar {
57603a807aaSBram Moolenaar win->w_cursor.col = len - 1;
57785a2002aSBram Moolenaar // Move the cursor to the head byte.
57887c19964SBram Moolenaar if (has_mbyte)
57903a807aaSBram Moolenaar mb_adjustpos(win->w_buffer, &win->w_cursor);
58087c19964SBram Moolenaar }
581071d4279SBram Moolenaar }
58203a807aaSBram Moolenaar else if (win->w_cursor.col < 0)
58303a807aaSBram Moolenaar win->w_cursor.col = 0;
584071d4279SBram Moolenaar
58585a2002aSBram Moolenaar // If virtual editing is on, we can leave the cursor on the old position,
58685a2002aSBram Moolenaar // only we must set it to virtual. But don't do it when at the end of the
58785a2002aSBram Moolenaar // line.
588071d4279SBram Moolenaar if (oldcol == MAXCOL)
58903a807aaSBram Moolenaar win->w_cursor.coladd = 0;
59053ba05b0SGary Johnson else if (cur_ve_flags == VE_ALL)
591552c8a56SBram Moolenaar {
59203a807aaSBram Moolenaar if (oldcoladd > win->w_cursor.col)
5939aa15691SBram Moolenaar {
59403a807aaSBram Moolenaar win->w_cursor.coladd = oldcoladd - win->w_cursor.col;
595d41babefSBram Moolenaar
59685a2002aSBram Moolenaar // Make sure that coladd is not more than the char width.
59785a2002aSBram Moolenaar // Not for the last character, coladd is then used when the cursor
59885a2002aSBram Moolenaar // is actually after the last character.
599d41babefSBram Moolenaar if (win->w_cursor.col + 1 < len && win->w_cursor.coladd > 0)
6009aa15691SBram Moolenaar {
6019aa15691SBram Moolenaar int cs, ce;
6029aa15691SBram Moolenaar
6039aa15691SBram Moolenaar getvcol(win, &win->w_cursor, &cs, NULL, &ce);
6049aa15691SBram Moolenaar if (win->w_cursor.coladd > ce - cs)
6059aa15691SBram Moolenaar win->w_cursor.coladd = ce - cs;
6069aa15691SBram Moolenaar }
6079aa15691SBram Moolenaar }
608552c8a56SBram Moolenaar else
60985a2002aSBram Moolenaar // avoid weird number when there is a miscalculation or overflow
61003a807aaSBram Moolenaar win->w_cursor.coladd = 0;
611552c8a56SBram Moolenaar }
612071d4279SBram Moolenaar }
613071d4279SBram Moolenaar
614071d4279SBram Moolenaar /*
615071d4279SBram Moolenaar * make sure curwin->w_cursor in on a valid character
616071d4279SBram Moolenaar */
617071d4279SBram Moolenaar void
check_cursor(void)6189b57814dSBram Moolenaar check_cursor(void)
619071d4279SBram Moolenaar {
620071d4279SBram Moolenaar check_cursor_lnum();
621071d4279SBram Moolenaar check_cursor_col();
622071d4279SBram Moolenaar }
623071d4279SBram Moolenaar
624071d4279SBram Moolenaar #if defined(FEAT_TEXTOBJ) || defined(PROTO)
625071d4279SBram Moolenaar /*
626071d4279SBram Moolenaar * Make sure curwin->w_cursor is not on the NUL at the end of the line.
627071d4279SBram Moolenaar * Allow it when in Visual mode and 'selection' is not "old".
628071d4279SBram Moolenaar */
629071d4279SBram Moolenaar void
adjust_cursor_col(void)6309b57814dSBram Moolenaar adjust_cursor_col(void)
631071d4279SBram Moolenaar {
632071d4279SBram Moolenaar if (curwin->w_cursor.col > 0
633071d4279SBram Moolenaar && (!VIsual_active || *p_sel == 'o')
634071d4279SBram Moolenaar && gchar_cursor() == NUL)
635071d4279SBram Moolenaar --curwin->w_cursor.col;
636071d4279SBram Moolenaar }
637071d4279SBram Moolenaar #endif
638071d4279SBram Moolenaar
639071d4279SBram Moolenaar /*
640071d4279SBram Moolenaar * When curwin->w_leftcol has changed, adjust the cursor position.
641071d4279SBram Moolenaar * Return TRUE if the cursor was moved.
642071d4279SBram Moolenaar */
643071d4279SBram Moolenaar int
leftcol_changed(void)6449b57814dSBram Moolenaar leftcol_changed(void)
645071d4279SBram Moolenaar {
646071d4279SBram Moolenaar long lastcol;
647071d4279SBram Moolenaar colnr_T s, e;
648071d4279SBram Moolenaar int retval = FALSE;
649375e3390SBram Moolenaar long siso = get_sidescrolloff_value();
650071d4279SBram Moolenaar
651071d4279SBram Moolenaar changed_cline_bef_curs();
6520263146bSBram Moolenaar lastcol = curwin->w_leftcol + curwin->w_width - curwin_col_off() - 1;
653071d4279SBram Moolenaar validate_virtcol();
654071d4279SBram Moolenaar
655071d4279SBram Moolenaar /*
656071d4279SBram Moolenaar * If the cursor is right or left of the screen, move it to last or first
657071d4279SBram Moolenaar * character.
658071d4279SBram Moolenaar */
659375e3390SBram Moolenaar if (curwin->w_virtcol > (colnr_T)(lastcol - siso))
660071d4279SBram Moolenaar {
661071d4279SBram Moolenaar retval = TRUE;
662375e3390SBram Moolenaar coladvance((colnr_T)(lastcol - siso));
663071d4279SBram Moolenaar }
664375e3390SBram Moolenaar else if (curwin->w_virtcol < curwin->w_leftcol + siso)
665071d4279SBram Moolenaar {
666071d4279SBram Moolenaar retval = TRUE;
667375e3390SBram Moolenaar (void)coladvance((colnr_T)(curwin->w_leftcol + siso));
668071d4279SBram Moolenaar }
669071d4279SBram Moolenaar
670071d4279SBram Moolenaar /*
671071d4279SBram Moolenaar * If the start of the character under the cursor is not on the screen,
672071d4279SBram Moolenaar * advance the cursor one more char. If this fails (last char of the
673071d4279SBram Moolenaar * line) adjust the scrolling.
674071d4279SBram Moolenaar */
675071d4279SBram Moolenaar getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
676071d4279SBram Moolenaar if (e > (colnr_T)lastcol)
677071d4279SBram Moolenaar {
678071d4279SBram Moolenaar retval = TRUE;
679071d4279SBram Moolenaar coladvance(s - 1);
680071d4279SBram Moolenaar }
681071d4279SBram Moolenaar else if (s < curwin->w_leftcol)
682071d4279SBram Moolenaar {
683071d4279SBram Moolenaar retval = TRUE;
68485a2002aSBram Moolenaar if (coladvance(e + 1) == FAIL) // there isn't another character
685071d4279SBram Moolenaar {
68685a2002aSBram Moolenaar curwin->w_leftcol = s; // adjust w_leftcol instead
687071d4279SBram Moolenaar changed_cline_bef_curs();
688071d4279SBram Moolenaar }
689071d4279SBram Moolenaar }
690071d4279SBram Moolenaar
691071d4279SBram Moolenaar if (retval)
692071d4279SBram Moolenaar curwin->w_set_curswant = TRUE;
693071d4279SBram Moolenaar redraw_later(NOT_VALID);
694071d4279SBram Moolenaar return retval;
695071d4279SBram Moolenaar }
696071d4279SBram Moolenaar
697c1a9bc1aSBram Moolenaar /*
698071d4279SBram Moolenaar * Isolate one part of a string option where parts are separated with
699071d4279SBram Moolenaar * "sep_chars".
70083bab71bSBram Moolenaar * The part is copied into "buf[maxlen]".
701071d4279SBram Moolenaar * "*option" is advanced to the next part.
702071d4279SBram Moolenaar * The length is returned.
703071d4279SBram Moolenaar */
704071d4279SBram Moolenaar int
copy_option_part(char_u ** option,char_u * buf,int maxlen,char * sep_chars)7059b57814dSBram Moolenaar copy_option_part(
7069b57814dSBram Moolenaar char_u **option,
7079b57814dSBram Moolenaar char_u *buf,
7089b57814dSBram Moolenaar int maxlen,
7099b57814dSBram Moolenaar char *sep_chars)
710071d4279SBram Moolenaar {
711071d4279SBram Moolenaar int len = 0;
712071d4279SBram Moolenaar char_u *p = *option;
713071d4279SBram Moolenaar
71485a2002aSBram Moolenaar // skip '.' at start of option part, for 'suffixes'
715071d4279SBram Moolenaar if (*p == '.')
716071d4279SBram Moolenaar buf[len++] = *p++;
717071d4279SBram Moolenaar while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL)
718071d4279SBram Moolenaar {
719071d4279SBram Moolenaar /*
720071d4279SBram Moolenaar * Skip backslash before a separator character and space.
721071d4279SBram Moolenaar */
722071d4279SBram Moolenaar if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
723071d4279SBram Moolenaar ++p;
724071d4279SBram Moolenaar if (len < maxlen - 1)
725071d4279SBram Moolenaar buf[len++] = *p;
726071d4279SBram Moolenaar ++p;
727071d4279SBram Moolenaar }
728071d4279SBram Moolenaar buf[len] = NUL;
729071d4279SBram Moolenaar
73085a2002aSBram Moolenaar if (*p != NUL && *p != ',') // skip non-standard separator
731071d4279SBram Moolenaar ++p;
73285a2002aSBram Moolenaar p = skip_to_option_part(p); // p points to next file name
733071d4279SBram Moolenaar
734071d4279SBram Moolenaar *option = p;
735071d4279SBram Moolenaar return len;
736071d4279SBram Moolenaar }
737071d4279SBram Moolenaar
738071d4279SBram Moolenaar #ifndef HAVE_MEMSET
739071d4279SBram Moolenaar void *
vim_memset(void * ptr,int c,size_t size)7409b57814dSBram Moolenaar vim_memset(void *ptr, int c, size_t size)
741071d4279SBram Moolenaar {
742071d4279SBram Moolenaar char *p = ptr;
743071d4279SBram Moolenaar
744071d4279SBram Moolenaar while (size-- > 0)
745071d4279SBram Moolenaar *p++ = c;
746071d4279SBram Moolenaar return ptr;
747071d4279SBram Moolenaar }
748071d4279SBram Moolenaar #endif
749071d4279SBram Moolenaar
750071d4279SBram Moolenaar /*
751071d4279SBram Moolenaar * Vim has its own isspace() function, because on some machines isspace()
752071d4279SBram Moolenaar * can't handle characters above 128.
753071d4279SBram Moolenaar */
754071d4279SBram Moolenaar int
vim_isspace(int x)7559b57814dSBram Moolenaar vim_isspace(int x)
756071d4279SBram Moolenaar {
757071d4279SBram Moolenaar return ((x >= 9 && x <= 13) || x == ' ');
758071d4279SBram Moolenaar }
759071d4279SBram Moolenaar
760071d4279SBram Moolenaar /************************************************************************
761071d4279SBram Moolenaar * functions that use lookup tables for various things, generally to do with
762071d4279SBram Moolenaar * special key codes.
763071d4279SBram Moolenaar */
764071d4279SBram Moolenaar
765071d4279SBram Moolenaar /*
766071d4279SBram Moolenaar * Some useful tables.
767071d4279SBram Moolenaar */
768071d4279SBram Moolenaar
769071d4279SBram Moolenaar static struct modmasktable
770071d4279SBram Moolenaar {
77185a2002aSBram Moolenaar short mod_mask; // Bit-mask for particular key modifier
77285a2002aSBram Moolenaar short mod_flag; // Bit(s) for particular key modifier
77385a2002aSBram Moolenaar char_u name; // Single letter name of modifier
774071d4279SBram Moolenaar } mod_mask_table[] =
775071d4279SBram Moolenaar {
776071d4279SBram Moolenaar {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M'},
77719a09a18SBram Moolenaar {MOD_MASK_META, MOD_MASK_META, (char_u)'T'},
778071d4279SBram Moolenaar {MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C'},
779071d4279SBram Moolenaar {MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S'},
780071d4279SBram Moolenaar {MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'},
781071d4279SBram Moolenaar {MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'},
782071d4279SBram Moolenaar {MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'},
783d057301bSBram Moolenaar #ifdef MACOS_X
784071d4279SBram Moolenaar {MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D'},
785071d4279SBram Moolenaar #endif
78685a2002aSBram Moolenaar // 'A' must be the last one
787071d4279SBram Moolenaar {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A'},
788071d4279SBram Moolenaar {0, 0, NUL}
78985a2002aSBram Moolenaar // NOTE: when adding an entry, update MAX_KEY_NAME_LEN!
790071d4279SBram Moolenaar };
791071d4279SBram Moolenaar
792071d4279SBram Moolenaar /*
793071d4279SBram Moolenaar * Shifted key terminal codes and their unshifted equivalent.
7947aa9f6a0SBram Moolenaar * Don't add mouse codes here, they are handled separately!
795071d4279SBram Moolenaar */
796071d4279SBram Moolenaar #define MOD_KEYS_ENTRY_SIZE 5
797071d4279SBram Moolenaar
798071d4279SBram Moolenaar static char_u modifier_keys_table[] =
799071d4279SBram Moolenaar {
80085a2002aSBram Moolenaar // mod mask with modifier without modifier
80185a2002aSBram Moolenaar MOD_MASK_SHIFT, '&', '9', '@', '1', // begin
80285a2002aSBram Moolenaar MOD_MASK_SHIFT, '&', '0', '@', '2', // cancel
80385a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '1', '@', '4', // command
80485a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '2', '@', '5', // copy
80585a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '3', '@', '6', // create
80685a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '4', 'k', 'D', // delete char
80785a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '5', 'k', 'L', // delete line
80885a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '7', '@', '7', // end
80985a2002aSBram Moolenaar MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', // end
81085a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '9', '@', '9', // exit
81185a2002aSBram Moolenaar MOD_MASK_SHIFT, '*', '0', '@', '0', // find
81285a2002aSBram Moolenaar MOD_MASK_SHIFT, '#', '1', '%', '1', // help
81385a2002aSBram Moolenaar MOD_MASK_SHIFT, '#', '2', 'k', 'h', // home
81485a2002aSBram Moolenaar MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', // home
81585a2002aSBram Moolenaar MOD_MASK_SHIFT, '#', '3', 'k', 'I', // insert
81685a2002aSBram Moolenaar MOD_MASK_SHIFT, '#', '4', 'k', 'l', // left arrow
81785a2002aSBram Moolenaar MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', // left arrow
81885a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'a', '%', '3', // message
81985a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'b', '%', '4', // move
82085a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'c', '%', '5', // next
82185a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'd', '%', '7', // options
82285a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'e', '%', '8', // previous
82385a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'f', '%', '9', // print
82485a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'g', '%', '0', // redo
82585a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'h', '&', '3', // replace
82685a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'i', 'k', 'r', // right arr.
82785a2002aSBram Moolenaar MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', // right arr.
82885a2002aSBram Moolenaar MOD_MASK_SHIFT, '%', 'j', '&', '5', // resume
82985a2002aSBram Moolenaar MOD_MASK_SHIFT, '!', '1', '&', '6', // save
83085a2002aSBram Moolenaar MOD_MASK_SHIFT, '!', '2', '&', '7', // suspend
83185a2002aSBram Moolenaar MOD_MASK_SHIFT, '!', '3', '&', '8', // undo
83285a2002aSBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', // up arrow
83385a2002aSBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', // down arrow
834071d4279SBram Moolenaar
83585a2002aSBram Moolenaar // vt100 F1
836071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1,
837071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2,
838071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3,
839071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4,
840071d4279SBram Moolenaar
84185a2002aSBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', // F1
842071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2',
843071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3',
844071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4',
845071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5',
846071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6',
847071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7',
848071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8',
849071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9',
85085a2002aSBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', // F10
851071d4279SBram Moolenaar
852071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1',
853071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2',
854071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3',
855071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4',
856071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5',
857071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6',
858071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7',
859071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8',
860071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9',
861071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A',
862071d4279SBram Moolenaar
863071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B',
864071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C',
865071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D',
866071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E',
867071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F',
868071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G',
869071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H',
870071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I',
871071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J',
872071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K',
873071d4279SBram Moolenaar
874071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L',
875071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M',
876071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N',
877071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O',
878071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P',
879071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q',
880071d4279SBram Moolenaar MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R',
881071d4279SBram Moolenaar
88285a2002aSBram Moolenaar // TAB pseudo code
883071d4279SBram Moolenaar MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB,
884071d4279SBram Moolenaar
885071d4279SBram Moolenaar NUL
886071d4279SBram Moolenaar };
887071d4279SBram Moolenaar
888071d4279SBram Moolenaar static struct key_name_entry
889071d4279SBram Moolenaar {
89085a2002aSBram Moolenaar int key; // Special key code or ascii value
89185a2002aSBram Moolenaar char_u *name; // Name of key
892071d4279SBram Moolenaar } key_names_table[] =
893071d4279SBram Moolenaar {
894071d4279SBram Moolenaar {' ', (char_u *)"Space"},
895071d4279SBram Moolenaar {TAB, (char_u *)"Tab"},
896071d4279SBram Moolenaar {K_TAB, (char_u *)"Tab"},
897071d4279SBram Moolenaar {NL, (char_u *)"NL"},
89885a2002aSBram Moolenaar {NL, (char_u *)"NewLine"}, // Alternative name
89985a2002aSBram Moolenaar {NL, (char_u *)"LineFeed"}, // Alternative name
90085a2002aSBram Moolenaar {NL, (char_u *)"LF"}, // Alternative name
901071d4279SBram Moolenaar {CAR, (char_u *)"CR"},
90285a2002aSBram Moolenaar {CAR, (char_u *)"Return"}, // Alternative name
90385a2002aSBram Moolenaar {CAR, (char_u *)"Enter"}, // Alternative name
904071d4279SBram Moolenaar {K_BS, (char_u *)"BS"},
90585a2002aSBram Moolenaar {K_BS, (char_u *)"BackSpace"}, // Alternative name
906071d4279SBram Moolenaar {ESC, (char_u *)"Esc"},
907071d4279SBram Moolenaar {CSI, (char_u *)"CSI"},
908071d4279SBram Moolenaar {K_CSI, (char_u *)"xCSI"},
909071d4279SBram Moolenaar {'|', (char_u *)"Bar"},
910071d4279SBram Moolenaar {'\\', (char_u *)"Bslash"},
911071d4279SBram Moolenaar {K_DEL, (char_u *)"Del"},
91285a2002aSBram Moolenaar {K_DEL, (char_u *)"Delete"}, // Alternative name
913071d4279SBram Moolenaar {K_KDEL, (char_u *)"kDel"},
914071d4279SBram Moolenaar {K_UP, (char_u *)"Up"},
915071d4279SBram Moolenaar {K_DOWN, (char_u *)"Down"},
916071d4279SBram Moolenaar {K_LEFT, (char_u *)"Left"},
917071d4279SBram Moolenaar {K_RIGHT, (char_u *)"Right"},
918bc7aa85dSBram Moolenaar {K_XUP, (char_u *)"xUp"},
919bc7aa85dSBram Moolenaar {K_XDOWN, (char_u *)"xDown"},
920bc7aa85dSBram Moolenaar {K_XLEFT, (char_u *)"xLeft"},
921bc7aa85dSBram Moolenaar {K_XRIGHT, (char_u *)"xRight"},
922ec2da36cSBram Moolenaar {K_PS, (char_u *)"PasteStart"},
923ec2da36cSBram Moolenaar {K_PE, (char_u *)"PasteEnd"},
924071d4279SBram Moolenaar
925071d4279SBram Moolenaar {K_F1, (char_u *)"F1"},
926071d4279SBram Moolenaar {K_F2, (char_u *)"F2"},
927071d4279SBram Moolenaar {K_F3, (char_u *)"F3"},
928071d4279SBram Moolenaar {K_F4, (char_u *)"F4"},
929071d4279SBram Moolenaar {K_F5, (char_u *)"F5"},
930071d4279SBram Moolenaar {K_F6, (char_u *)"F6"},
931071d4279SBram Moolenaar {K_F7, (char_u *)"F7"},
932071d4279SBram Moolenaar {K_F8, (char_u *)"F8"},
933071d4279SBram Moolenaar {K_F9, (char_u *)"F9"},
934071d4279SBram Moolenaar {K_F10, (char_u *)"F10"},
935071d4279SBram Moolenaar
936071d4279SBram Moolenaar {K_F11, (char_u *)"F11"},
937071d4279SBram Moolenaar {K_F12, (char_u *)"F12"},
938071d4279SBram Moolenaar {K_F13, (char_u *)"F13"},
939071d4279SBram Moolenaar {K_F14, (char_u *)"F14"},
940071d4279SBram Moolenaar {K_F15, (char_u *)"F15"},
941071d4279SBram Moolenaar {K_F16, (char_u *)"F16"},
942071d4279SBram Moolenaar {K_F17, (char_u *)"F17"},
943071d4279SBram Moolenaar {K_F18, (char_u *)"F18"},
944071d4279SBram Moolenaar {K_F19, (char_u *)"F19"},
945071d4279SBram Moolenaar {K_F20, (char_u *)"F20"},
946071d4279SBram Moolenaar
947071d4279SBram Moolenaar {K_F21, (char_u *)"F21"},
948071d4279SBram Moolenaar {K_F22, (char_u *)"F22"},
949071d4279SBram Moolenaar {K_F23, (char_u *)"F23"},
950071d4279SBram Moolenaar {K_F24, (char_u *)"F24"},
951071d4279SBram Moolenaar {K_F25, (char_u *)"F25"},
952071d4279SBram Moolenaar {K_F26, (char_u *)"F26"},
953071d4279SBram Moolenaar {K_F27, (char_u *)"F27"},
954071d4279SBram Moolenaar {K_F28, (char_u *)"F28"},
955071d4279SBram Moolenaar {K_F29, (char_u *)"F29"},
956071d4279SBram Moolenaar {K_F30, (char_u *)"F30"},
957071d4279SBram Moolenaar
958071d4279SBram Moolenaar {K_F31, (char_u *)"F31"},
959071d4279SBram Moolenaar {K_F32, (char_u *)"F32"},
960071d4279SBram Moolenaar {K_F33, (char_u *)"F33"},
961071d4279SBram Moolenaar {K_F34, (char_u *)"F34"},
962071d4279SBram Moolenaar {K_F35, (char_u *)"F35"},
963071d4279SBram Moolenaar {K_F36, (char_u *)"F36"},
964071d4279SBram Moolenaar {K_F37, (char_u *)"F37"},
965071d4279SBram Moolenaar
966071d4279SBram Moolenaar {K_XF1, (char_u *)"xF1"},
967071d4279SBram Moolenaar {K_XF2, (char_u *)"xF2"},
968071d4279SBram Moolenaar {K_XF3, (char_u *)"xF3"},
969071d4279SBram Moolenaar {K_XF4, (char_u *)"xF4"},
970071d4279SBram Moolenaar
971071d4279SBram Moolenaar {K_HELP, (char_u *)"Help"},
972071d4279SBram Moolenaar {K_UNDO, (char_u *)"Undo"},
973071d4279SBram Moolenaar {K_INS, (char_u *)"Insert"},
97485a2002aSBram Moolenaar {K_INS, (char_u *)"Ins"}, // Alternative name
975071d4279SBram Moolenaar {K_KINS, (char_u *)"kInsert"},
976071d4279SBram Moolenaar {K_HOME, (char_u *)"Home"},
977071d4279SBram Moolenaar {K_KHOME, (char_u *)"kHome"},
978071d4279SBram Moolenaar {K_XHOME, (char_u *)"xHome"},
97968b76a69SBram Moolenaar {K_ZHOME, (char_u *)"zHome"},
980071d4279SBram Moolenaar {K_END, (char_u *)"End"},
981071d4279SBram Moolenaar {K_KEND, (char_u *)"kEnd"},
982071d4279SBram Moolenaar {K_XEND, (char_u *)"xEnd"},
98368b76a69SBram Moolenaar {K_ZEND, (char_u *)"zEnd"},
984071d4279SBram Moolenaar {K_PAGEUP, (char_u *)"PageUp"},
985071d4279SBram Moolenaar {K_PAGEDOWN, (char_u *)"PageDown"},
986071d4279SBram Moolenaar {K_KPAGEUP, (char_u *)"kPageUp"},
987071d4279SBram Moolenaar {K_KPAGEDOWN, (char_u *)"kPageDown"},
988071d4279SBram Moolenaar
989071d4279SBram Moolenaar {K_KPLUS, (char_u *)"kPlus"},
990071d4279SBram Moolenaar {K_KMINUS, (char_u *)"kMinus"},
991071d4279SBram Moolenaar {K_KDIVIDE, (char_u *)"kDivide"},
992071d4279SBram Moolenaar {K_KMULTIPLY, (char_u *)"kMultiply"},
993071d4279SBram Moolenaar {K_KENTER, (char_u *)"kEnter"},
994071d4279SBram Moolenaar {K_KPOINT, (char_u *)"kPoint"},
995071d4279SBram Moolenaar
996071d4279SBram Moolenaar {K_K0, (char_u *)"k0"},
997071d4279SBram Moolenaar {K_K1, (char_u *)"k1"},
998071d4279SBram Moolenaar {K_K2, (char_u *)"k2"},
999071d4279SBram Moolenaar {K_K3, (char_u *)"k3"},
1000071d4279SBram Moolenaar {K_K4, (char_u *)"k4"},
1001071d4279SBram Moolenaar {K_K5, (char_u *)"k5"},
1002071d4279SBram Moolenaar {K_K6, (char_u *)"k6"},
1003071d4279SBram Moolenaar {K_K7, (char_u *)"k7"},
1004071d4279SBram Moolenaar {K_K8, (char_u *)"k8"},
1005071d4279SBram Moolenaar {K_K9, (char_u *)"k9"},
1006071d4279SBram Moolenaar
1007071d4279SBram Moolenaar {'<', (char_u *)"lt"},
1008071d4279SBram Moolenaar
1009071d4279SBram Moolenaar {K_MOUSE, (char_u *)"Mouse"},
10105af7d712SBram Moolenaar #ifdef FEAT_MOUSE_NET
1011071d4279SBram Moolenaar {K_NETTERM_MOUSE, (char_u *)"NetMouse"},
10125af7d712SBram Moolenaar #endif
10135af7d712SBram Moolenaar #ifdef FEAT_MOUSE_DEC
1014071d4279SBram Moolenaar {K_DEC_MOUSE, (char_u *)"DecMouse"},
10155af7d712SBram Moolenaar #endif
10165af7d712SBram Moolenaar #ifdef FEAT_MOUSE_JSB
1017071d4279SBram Moolenaar {K_JSBTERM_MOUSE, (char_u *)"JsbMouse"},
10185af7d712SBram Moolenaar #endif
10195af7d712SBram Moolenaar #ifdef FEAT_MOUSE_PTERM
1020071d4279SBram Moolenaar {K_PTERM_MOUSE, (char_u *)"PtermMouse"},
10215af7d712SBram Moolenaar #endif
10225af7d712SBram Moolenaar #ifdef FEAT_MOUSE_URXVT
10235af7d712SBram Moolenaar {K_URXVT_MOUSE, (char_u *)"UrxvtMouse"},
10245af7d712SBram Moolenaar #endif
10252b9578f0SBram Moolenaar {K_SGR_MOUSE, (char_u *)"SgrMouse"},
102621a83bd5SBram Moolenaar {K_SGR_MOUSERELEASE, (char_u *)"SgrMouseRelease"},
1027071d4279SBram Moolenaar {K_LEFTMOUSE, (char_u *)"LeftMouse"},
1028071d4279SBram Moolenaar {K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"},
1029071d4279SBram Moolenaar {K_LEFTDRAG, (char_u *)"LeftDrag"},
1030071d4279SBram Moolenaar {K_LEFTRELEASE, (char_u *)"LeftRelease"},
1031071d4279SBram Moolenaar {K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"},
103251b0f370SBram Moolenaar {K_MOUSEMOVE, (char_u *)"MouseMove"},
1033071d4279SBram Moolenaar {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
1034071d4279SBram Moolenaar {K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
1035071d4279SBram Moolenaar {K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
1036071d4279SBram Moolenaar {K_RIGHTMOUSE, (char_u *)"RightMouse"},
1037071d4279SBram Moolenaar {K_RIGHTDRAG, (char_u *)"RightDrag"},
1038071d4279SBram Moolenaar {K_RIGHTRELEASE, (char_u *)"RightRelease"},
10398d9b40e7SBram Moolenaar {K_MOUSEDOWN, (char_u *)"ScrollWheelUp"},
10408d9b40e7SBram Moolenaar {K_MOUSEUP, (char_u *)"ScrollWheelDown"},
10418d9b40e7SBram Moolenaar {K_MOUSELEFT, (char_u *)"ScrollWheelRight"},
10428d9b40e7SBram Moolenaar {K_MOUSERIGHT, (char_u *)"ScrollWheelLeft"},
104385a2002aSBram Moolenaar {K_MOUSEDOWN, (char_u *)"MouseDown"}, // OBSOLETE: Use
104485a2002aSBram Moolenaar {K_MOUSEUP, (char_u *)"MouseUp"}, // ScrollWheelXXX instead
1045071d4279SBram Moolenaar {K_X1MOUSE, (char_u *)"X1Mouse"},
1046071d4279SBram Moolenaar {K_X1DRAG, (char_u *)"X1Drag"},
1047071d4279SBram Moolenaar {K_X1RELEASE, (char_u *)"X1Release"},
1048071d4279SBram Moolenaar {K_X2MOUSE, (char_u *)"X2Mouse"},
1049071d4279SBram Moolenaar {K_X2DRAG, (char_u *)"X2Drag"},
1050071d4279SBram Moolenaar {K_X2RELEASE, (char_u *)"X2Release"},
1051071d4279SBram Moolenaar {K_DROP, (char_u *)"Drop"},
1052071d4279SBram Moolenaar {K_ZERO, (char_u *)"Nul"},
1053071d4279SBram Moolenaar #ifdef FEAT_EVAL
1054071d4279SBram Moolenaar {K_SNR, (char_u *)"SNR"},
1055071d4279SBram Moolenaar #endif
1056071d4279SBram Moolenaar {K_PLUG, (char_u *)"Plug"},
10571db60c47SBram Moolenaar {K_CURSORHOLD, (char_u *)"CursorHold"},
10582f10658bSBram Moolenaar {K_IGNORE, (char_u *)"Ignore"},
1059957cf67dSBram Moolenaar {K_COMMAND, (char_u *)"Cmd"},
1060ccb47a28SBram Moolenaar {K_FOCUSGAINED, (char_u *)"FocusGained"},
1061ccb47a28SBram Moolenaar {K_FOCUSLOST, (char_u *)"FocusLost"},
1062071d4279SBram Moolenaar {0, NULL}
106385a2002aSBram Moolenaar // NOTE: When adding a long name update MAX_KEY_NAME_LEN.
1064071d4279SBram Moolenaar };
1065071d4279SBram Moolenaar
1066eeec2548SK.Takata #define KEY_NAMES_TABLE_LEN ARRAY_LENGTH(key_names_table)
1067071d4279SBram Moolenaar
1068071d4279SBram Moolenaar /*
1069071d4279SBram Moolenaar * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
1070071d4279SBram Moolenaar * modifier name ('S' for Shift, 'C' for Ctrl etc).
1071071d4279SBram Moolenaar */
10725843f5f3SBram Moolenaar static int
name_to_mod_mask(int c)10739b57814dSBram Moolenaar name_to_mod_mask(int c)
1074071d4279SBram Moolenaar {
1075071d4279SBram Moolenaar int i;
1076071d4279SBram Moolenaar
1077071d4279SBram Moolenaar c = TOUPPER_ASC(c);
1078071d4279SBram Moolenaar for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
1079071d4279SBram Moolenaar if (c == mod_mask_table[i].name)
1080071d4279SBram Moolenaar return mod_mask_table[i].mod_flag;
1081071d4279SBram Moolenaar return 0;
1082071d4279SBram Moolenaar }
1083071d4279SBram Moolenaar
1084071d4279SBram Moolenaar /*
1085071d4279SBram Moolenaar * Check if if there is a special key code for "key" that includes the
1086071d4279SBram Moolenaar * modifiers specified.
1087071d4279SBram Moolenaar */
1088071d4279SBram Moolenaar int
simplify_key(int key,int * modifiers)10899b57814dSBram Moolenaar simplify_key(int key, int *modifiers)
1090071d4279SBram Moolenaar {
1091071d4279SBram Moolenaar int i;
1092071d4279SBram Moolenaar int key0;
1093071d4279SBram Moolenaar int key1;
1094071d4279SBram Moolenaar
1095071d4279SBram Moolenaar if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
1096071d4279SBram Moolenaar {
109785a2002aSBram Moolenaar // TAB is a special case
1098071d4279SBram Moolenaar if (key == TAB && (*modifiers & MOD_MASK_SHIFT))
1099071d4279SBram Moolenaar {
1100071d4279SBram Moolenaar *modifiers &= ~MOD_MASK_SHIFT;
1101071d4279SBram Moolenaar return K_S_TAB;
1102071d4279SBram Moolenaar }
1103071d4279SBram Moolenaar key0 = KEY2TERMCAP0(key);
1104071d4279SBram Moolenaar key1 = KEY2TERMCAP1(key);
1105071d4279SBram Moolenaar for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
1106071d4279SBram Moolenaar if (key0 == modifier_keys_table[i + 3]
1107071d4279SBram Moolenaar && key1 == modifier_keys_table[i + 4]
1108071d4279SBram Moolenaar && (*modifiers & modifier_keys_table[i]))
1109071d4279SBram Moolenaar {
1110071d4279SBram Moolenaar *modifiers &= ~modifier_keys_table[i];
1111071d4279SBram Moolenaar return TERMCAP2KEY(modifier_keys_table[i + 1],
1112071d4279SBram Moolenaar modifier_keys_table[i + 2]);
1113071d4279SBram Moolenaar }
1114071d4279SBram Moolenaar }
1115071d4279SBram Moolenaar return key;
1116071d4279SBram Moolenaar }
1117071d4279SBram Moolenaar
1118071d4279SBram Moolenaar /*
1119bc7aa85dSBram Moolenaar * Change <xHome> to <Home>, <xUp> to <Up>, etc.
1120bc7aa85dSBram Moolenaar */
1121bc7aa85dSBram Moolenaar int
handle_x_keys(int key)11229b57814dSBram Moolenaar handle_x_keys(int key)
1123bc7aa85dSBram Moolenaar {
1124bc7aa85dSBram Moolenaar switch (key)
1125bc7aa85dSBram Moolenaar {
1126bc7aa85dSBram Moolenaar case K_XUP: return K_UP;
1127bc7aa85dSBram Moolenaar case K_XDOWN: return K_DOWN;
1128bc7aa85dSBram Moolenaar case K_XLEFT: return K_LEFT;
1129bc7aa85dSBram Moolenaar case K_XRIGHT: return K_RIGHT;
1130bc7aa85dSBram Moolenaar case K_XHOME: return K_HOME;
113168b76a69SBram Moolenaar case K_ZHOME: return K_HOME;
1132bc7aa85dSBram Moolenaar case K_XEND: return K_END;
113368b76a69SBram Moolenaar case K_ZEND: return K_END;
1134bc7aa85dSBram Moolenaar case K_XF1: return K_F1;
1135bc7aa85dSBram Moolenaar case K_XF2: return K_F2;
1136bc7aa85dSBram Moolenaar case K_XF3: return K_F3;
1137bc7aa85dSBram Moolenaar case K_XF4: return K_F4;
1138bc7aa85dSBram Moolenaar case K_S_XF1: return K_S_F1;
1139bc7aa85dSBram Moolenaar case K_S_XF2: return K_S_F2;
1140bc7aa85dSBram Moolenaar case K_S_XF3: return K_S_F3;
1141bc7aa85dSBram Moolenaar case K_S_XF4: return K_S_F4;
1142bc7aa85dSBram Moolenaar }
1143bc7aa85dSBram Moolenaar return key;
1144bc7aa85dSBram Moolenaar }
1145bc7aa85dSBram Moolenaar
1146bc7aa85dSBram Moolenaar /*
1147071d4279SBram Moolenaar * Return a string which contains the name of the given key when the given
1148071d4279SBram Moolenaar * modifiers are down.
1149071d4279SBram Moolenaar */
1150071d4279SBram Moolenaar char_u *
get_special_key_name(int c,int modifiers)11519b57814dSBram Moolenaar get_special_key_name(int c, int modifiers)
1152071d4279SBram Moolenaar {
1153071d4279SBram Moolenaar static char_u string[MAX_KEY_NAME_LEN + 1];
1154071d4279SBram Moolenaar
1155071d4279SBram Moolenaar int i, idx;
1156071d4279SBram Moolenaar int table_idx;
1157071d4279SBram Moolenaar char_u *s;
1158071d4279SBram Moolenaar
1159071d4279SBram Moolenaar string[0] = '<';
1160071d4279SBram Moolenaar idx = 1;
1161071d4279SBram Moolenaar
116285a2002aSBram Moolenaar // Key that stands for a normal character.
1163071d4279SBram Moolenaar if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
1164071d4279SBram Moolenaar c = KEY2TERMCAP1(c);
1165071d4279SBram Moolenaar
1166071d4279SBram Moolenaar /*
1167071d4279SBram Moolenaar * Translate shifted special keys into unshifted keys and set modifier.
1168071d4279SBram Moolenaar * Same for CTRL and ALT modifiers.
1169071d4279SBram Moolenaar */
1170071d4279SBram Moolenaar if (IS_SPECIAL(c))
1171071d4279SBram Moolenaar {
1172071d4279SBram Moolenaar for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
1173071d4279SBram Moolenaar if ( KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1]
1174071d4279SBram Moolenaar && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2])
1175071d4279SBram Moolenaar {
1176071d4279SBram Moolenaar modifiers |= modifier_keys_table[i];
1177071d4279SBram Moolenaar c = TERMCAP2KEY(modifier_keys_table[i + 3],
1178071d4279SBram Moolenaar modifier_keys_table[i + 4]);
1179071d4279SBram Moolenaar break;
1180071d4279SBram Moolenaar }
1181071d4279SBram Moolenaar }
1182071d4279SBram Moolenaar
118385a2002aSBram Moolenaar // try to find the key in the special key table
1184071d4279SBram Moolenaar table_idx = find_special_key_in_table(c);
1185071d4279SBram Moolenaar
1186071d4279SBram Moolenaar /*
1187071d4279SBram Moolenaar * When not a known special key, and not a printable character, try to
1188071d4279SBram Moolenaar * extract modifiers.
1189071d4279SBram Moolenaar */
1190fc3abf47SBram Moolenaar if (c > 0 && (*mb_char2len)(c) == 1)
1191071d4279SBram Moolenaar {
1192071d4279SBram Moolenaar if (table_idx < 0
1193071d4279SBram Moolenaar && (!vim_isprintc(c) || (c & 0x7f) == ' ')
1194071d4279SBram Moolenaar && (c & 0x80))
1195071d4279SBram Moolenaar {
1196071d4279SBram Moolenaar c &= 0x7f;
1197071d4279SBram Moolenaar modifiers |= MOD_MASK_ALT;
119885a2002aSBram Moolenaar // try again, to find the un-alted key in the special key table
1199071d4279SBram Moolenaar table_idx = find_special_key_in_table(c);
1200071d4279SBram Moolenaar }
1201071d4279SBram Moolenaar if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
1202071d4279SBram Moolenaar {
1203071d4279SBram Moolenaar #ifdef EBCDIC
1204071d4279SBram Moolenaar c = CtrlChar(c);
1205071d4279SBram Moolenaar #else
1206071d4279SBram Moolenaar c += '@';
1207071d4279SBram Moolenaar #endif
1208071d4279SBram Moolenaar modifiers |= MOD_MASK_CTRL;
1209071d4279SBram Moolenaar }
1210071d4279SBram Moolenaar }
1211071d4279SBram Moolenaar
121285a2002aSBram Moolenaar // translate the modifier into a string
1213071d4279SBram Moolenaar for (i = 0; mod_mask_table[i].name != 'A'; i++)
1214071d4279SBram Moolenaar if ((modifiers & mod_mask_table[i].mod_mask)
1215071d4279SBram Moolenaar == mod_mask_table[i].mod_flag)
1216071d4279SBram Moolenaar {
1217071d4279SBram Moolenaar string[idx++] = mod_mask_table[i].name;
1218071d4279SBram Moolenaar string[idx++] = (char_u)'-';
1219071d4279SBram Moolenaar }
1220071d4279SBram Moolenaar
122185a2002aSBram Moolenaar if (table_idx < 0) // unknown special key, may output t_xx
1222071d4279SBram Moolenaar {
1223071d4279SBram Moolenaar if (IS_SPECIAL(c))
1224071d4279SBram Moolenaar {
1225071d4279SBram Moolenaar string[idx++] = 't';
1226071d4279SBram Moolenaar string[idx++] = '_';
1227071d4279SBram Moolenaar string[idx++] = KEY2TERMCAP0(c);
1228071d4279SBram Moolenaar string[idx++] = KEY2TERMCAP1(c);
1229071d4279SBram Moolenaar }
123085a2002aSBram Moolenaar // Not a special key, only modifiers, output directly
1231071d4279SBram Moolenaar else
1232071d4279SBram Moolenaar {
1233071d4279SBram Moolenaar if (has_mbyte && (*mb_char2len)(c) > 1)
1234071d4279SBram Moolenaar idx += (*mb_char2bytes)(c, string + idx);
1235fc3abf47SBram Moolenaar else if (vim_isprintc(c))
1236071d4279SBram Moolenaar string[idx++] = c;
1237071d4279SBram Moolenaar else
1238071d4279SBram Moolenaar {
1239071d4279SBram Moolenaar s = transchar(c);
1240071d4279SBram Moolenaar while (*s)
1241071d4279SBram Moolenaar string[idx++] = *s++;
1242071d4279SBram Moolenaar }
1243071d4279SBram Moolenaar }
1244071d4279SBram Moolenaar }
124585a2002aSBram Moolenaar else // use name of special key
1246071d4279SBram Moolenaar {
1247423977d3SBram Moolenaar size_t len = STRLEN(key_names_table[table_idx].name);
1248423977d3SBram Moolenaar
1249423977d3SBram Moolenaar if (len + idx + 2 <= MAX_KEY_NAME_LEN)
1250423977d3SBram Moolenaar {
1251071d4279SBram Moolenaar STRCPY(string + idx, key_names_table[table_idx].name);
1252423977d3SBram Moolenaar idx += (int)len;
1253423977d3SBram Moolenaar }
1254071d4279SBram Moolenaar }
1255071d4279SBram Moolenaar string[idx++] = '>';
1256071d4279SBram Moolenaar string[idx] = NUL;
1257071d4279SBram Moolenaar return string;
1258071d4279SBram Moolenaar }
1259071d4279SBram Moolenaar
1260071d4279SBram Moolenaar /*
1261071d4279SBram Moolenaar * Try translating a <> name at (*srcp)[] to dst[].
1262071d4279SBram Moolenaar * Return the number of characters added to dst[], zero for no match.
1263071d4279SBram Moolenaar * If there is a match, srcp is advanced to after the <> name.
1264071d4279SBram Moolenaar * dst[] must be big enough to hold the result (up to six characters)!
1265071d4279SBram Moolenaar */
1266071d4279SBram Moolenaar int
trans_special(char_u ** srcp,char_u * dst,int flags,int * did_simplify)12679b57814dSBram Moolenaar trans_special(
12689b57814dSBram Moolenaar char_u **srcp,
12699b57814dSBram Moolenaar char_u *dst,
1270ebe9d34aSBram Moolenaar int flags, // FSK_ values
1271ebe9d34aSBram Moolenaar int *did_simplify) // FSK_SIMPLIFY and found <C-H> or <A-x>
1272071d4279SBram Moolenaar {
1273071d4279SBram Moolenaar int modifiers = 0;
1274071d4279SBram Moolenaar int key;
1275071d4279SBram Moolenaar
1276ebe9d34aSBram Moolenaar key = find_special_key(srcp, &modifiers, flags, did_simplify);
1277071d4279SBram Moolenaar if (key == 0)
1278071d4279SBram Moolenaar return 0;
1279071d4279SBram Moolenaar
1280ebe9d34aSBram Moolenaar return special_to_buf(key, modifiers, flags & FSK_KEYCODE, dst);
1281bf0eff0bSBram Moolenaar }
1282bf0eff0bSBram Moolenaar
1283bf0eff0bSBram Moolenaar /*
1284bf0eff0bSBram Moolenaar * Put the character sequence for "key" with "modifiers" into "dst" and return
1285bf0eff0bSBram Moolenaar * the resulting length.
1286bf0eff0bSBram Moolenaar * When "keycode" is TRUE prefer key code, e.g. K_DEL instead of DEL.
1287bf0eff0bSBram Moolenaar * The sequence is not NUL terminated.
1288bf0eff0bSBram Moolenaar * This is how characters in a string are encoded.
1289bf0eff0bSBram Moolenaar */
1290bf0eff0bSBram Moolenaar int
special_to_buf(int key,int modifiers,int keycode,char_u * dst)1291bf0eff0bSBram Moolenaar special_to_buf(int key, int modifiers, int keycode, char_u *dst)
1292bf0eff0bSBram Moolenaar {
1293bf0eff0bSBram Moolenaar int dlen = 0;
1294bf0eff0bSBram Moolenaar
129585a2002aSBram Moolenaar // Put the appropriate modifier in a string
1296071d4279SBram Moolenaar if (modifiers != 0)
1297071d4279SBram Moolenaar {
1298071d4279SBram Moolenaar dst[dlen++] = K_SPECIAL;
1299071d4279SBram Moolenaar dst[dlen++] = KS_MODIFIER;
1300071d4279SBram Moolenaar dst[dlen++] = modifiers;
1301071d4279SBram Moolenaar }
1302071d4279SBram Moolenaar
1303071d4279SBram Moolenaar if (IS_SPECIAL(key))
1304071d4279SBram Moolenaar {
1305071d4279SBram Moolenaar dst[dlen++] = K_SPECIAL;
1306071d4279SBram Moolenaar dst[dlen++] = KEY2TERMCAP0(key);
1307071d4279SBram Moolenaar dst[dlen++] = KEY2TERMCAP1(key);
1308071d4279SBram Moolenaar }
1309071d4279SBram Moolenaar else if (has_mbyte && !keycode)
1310071d4279SBram Moolenaar dlen += (*mb_char2bytes)(key, dst + dlen);
1311071d4279SBram Moolenaar else if (keycode)
1312071d4279SBram Moolenaar dlen = (int)(add_char2buf(key, dst + dlen) - dst);
1313071d4279SBram Moolenaar else
1314071d4279SBram Moolenaar dst[dlen++] = key;
1315071d4279SBram Moolenaar
1316071d4279SBram Moolenaar return dlen;
1317071d4279SBram Moolenaar }
1318071d4279SBram Moolenaar
1319071d4279SBram Moolenaar /*
1320071d4279SBram Moolenaar * Try translating a <> name at (*srcp)[], return the key and modifiers.
1321071d4279SBram Moolenaar * srcp is advanced to after the <> name.
1322071d4279SBram Moolenaar * returns 0 if there is no match.
1323071d4279SBram Moolenaar */
1324071d4279SBram Moolenaar int
find_special_key(char_u ** srcp,int * modp,int flags,int * did_simplify)13259b57814dSBram Moolenaar find_special_key(
13269b57814dSBram Moolenaar char_u **srcp,
13279b57814dSBram Moolenaar int *modp,
1328ebe9d34aSBram Moolenaar int flags, // FSK_ values
1329459fd785SBram Moolenaar int *did_simplify) // found <C-H> or <A-x>
1330071d4279SBram Moolenaar {
1331071d4279SBram Moolenaar char_u *last_dash;
1332071d4279SBram Moolenaar char_u *end_of_name;
1333071d4279SBram Moolenaar char_u *src;
1334071d4279SBram Moolenaar char_u *bp;
1335ebe9d34aSBram Moolenaar int in_string = flags & FSK_IN_STRING;
1336071d4279SBram Moolenaar int modifiers;
1337071d4279SBram Moolenaar int bit;
1338071d4279SBram Moolenaar int key;
133922fcfad2SBram Moolenaar uvarnumber_T n;
1340b8bf541fSBram Moolenaar int l;
1341071d4279SBram Moolenaar
1342071d4279SBram Moolenaar src = *srcp;
1343fccd93f0SBram Moolenaar if (src[0] != '<')
1344071d4279SBram Moolenaar return 0;
1345fccd93f0SBram Moolenaar if (src[1] == '*') // <*xxx>: do not simplify
1346fccd93f0SBram Moolenaar ++src;
1347071d4279SBram Moolenaar
134885a2002aSBram Moolenaar // Find end of modifier list
1349071d4279SBram Moolenaar last_dash = src;
1350e3d1f4c9SBram Moolenaar for (bp = src + 1; *bp == '-' || vim_isNormalIDc(*bp); bp++)
1351071d4279SBram Moolenaar {
1352071d4279SBram Moolenaar if (*bp == '-')
1353071d4279SBram Moolenaar {
1354071d4279SBram Moolenaar last_dash = bp;
1355b8bf541fSBram Moolenaar if (bp[1] != NUL)
1356b8bf541fSBram Moolenaar {
1357b8bf541fSBram Moolenaar if (has_mbyte)
1358b8bf541fSBram Moolenaar l = mb_ptr2len(bp + 1);
1359b8bf541fSBram Moolenaar else
1360b8bf541fSBram Moolenaar l = 1;
1361c8fd33d1SBram Moolenaar // Anything accepted, like <C-?>.
1362c8fd33d1SBram Moolenaar // <C-"> or <M-"> are not special in strings as " is
1363c8fd33d1SBram Moolenaar // the string delimiter. With a backslash it works: <M-\">
1364fccd93f0SBram Moolenaar if (!(in_string && bp[1] == '"') && bp[l + 1] == '>')
13651d90a5a5SBram Moolenaar bp += l;
136635a4cfa2SBram Moolenaar else if (in_string && bp[1] == '\\' && bp[2] == '"'
1367fccd93f0SBram Moolenaar && bp[3] == '>')
136835a4cfa2SBram Moolenaar bp += 2;
1369b8bf541fSBram Moolenaar }
1370071d4279SBram Moolenaar }
1371071d4279SBram Moolenaar if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
1372fccd93f0SBram Moolenaar bp += 3; // skip t_xx, xx may be '-' or '>'
1373792826c0SBram Moolenaar else if (STRNICMP(bp, "char-", 5) == 0)
1374792826c0SBram Moolenaar {
137516e9b851SBram Moolenaar vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, TRUE);
137616e9b851SBram Moolenaar if (l == 0)
137716e9b851SBram Moolenaar {
137816e9b851SBram Moolenaar emsg(_(e_invarg));
137916e9b851SBram Moolenaar return 0;
138016e9b851SBram Moolenaar }
1381792826c0SBram Moolenaar bp += l + 5;
1382792826c0SBram Moolenaar break;
1383792826c0SBram Moolenaar }
1384071d4279SBram Moolenaar }
1385071d4279SBram Moolenaar
1386fccd93f0SBram Moolenaar if (*bp == '>') // found matching '>'
1387071d4279SBram Moolenaar {
1388071d4279SBram Moolenaar end_of_name = bp + 1;
1389071d4279SBram Moolenaar
139085a2002aSBram Moolenaar // Which modifiers are given?
1391071d4279SBram Moolenaar modifiers = 0x0;
1392071d4279SBram Moolenaar for (bp = src + 1; bp < last_dash; bp++)
1393071d4279SBram Moolenaar {
1394071d4279SBram Moolenaar if (*bp != '-')
1395071d4279SBram Moolenaar {
1396071d4279SBram Moolenaar bit = name_to_mod_mask(*bp);
1397071d4279SBram Moolenaar if (bit == 0x0)
139885a2002aSBram Moolenaar break; // Illegal modifier name
1399071d4279SBram Moolenaar modifiers |= bit;
1400071d4279SBram Moolenaar }
1401071d4279SBram Moolenaar }
1402071d4279SBram Moolenaar
1403071d4279SBram Moolenaar /*
1404071d4279SBram Moolenaar * Legal modifier name.
1405071d4279SBram Moolenaar */
1406071d4279SBram Moolenaar if (bp >= last_dash)
1407071d4279SBram Moolenaar {
1408b8bf541fSBram Moolenaar if (STRNICMP(last_dash + 1, "char-", 5) == 0
1409b8bf541fSBram Moolenaar && VIM_ISDIGIT(last_dash[6]))
1410b8bf541fSBram Moolenaar {
141185a2002aSBram Moolenaar // <Char-123> or <Char-033> or <Char-0x33>
1412459fd785SBram Moolenaar vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
1413459fd785SBram Moolenaar &n, 0, TRUE);
141416e9b851SBram Moolenaar if (l == 0)
141516e9b851SBram Moolenaar {
141616e9b851SBram Moolenaar emsg(_(e_invarg));
141716e9b851SBram Moolenaar return 0;
141816e9b851SBram Moolenaar }
1419792826c0SBram Moolenaar key = (int)n;
1420b8bf541fSBram Moolenaar }
1421792826c0SBram Moolenaar else
1422792826c0SBram Moolenaar {
142335a4cfa2SBram Moolenaar int off = 1;
142435a4cfa2SBram Moolenaar
142585a2002aSBram Moolenaar // Modifier with single letter, or special key name.
142635a4cfa2SBram Moolenaar if (in_string && last_dash[1] == '\\' && last_dash[2] == '"')
142735a4cfa2SBram Moolenaar off = 2;
1428b8bf541fSBram Moolenaar if (has_mbyte)
142935a4cfa2SBram Moolenaar l = mb_ptr2len(last_dash + off);
1430b8bf541fSBram Moolenaar else
1431b8bf541fSBram Moolenaar l = 1;
1432fccd93f0SBram Moolenaar if (modifiers != 0 && last_dash[l + off] == '>')
143335a4cfa2SBram Moolenaar key = PTR2CHAR(last_dash + off);
1434071d4279SBram Moolenaar else
1435bc7aa85dSBram Moolenaar {
143635a4cfa2SBram Moolenaar key = get_special_key_code(last_dash + off);
1437ebe9d34aSBram Moolenaar if (!(flags & FSK_KEEP_X_KEY))
1438bc7aa85dSBram Moolenaar key = handle_x_keys(key);
1439bc7aa85dSBram Moolenaar }
1440792826c0SBram Moolenaar }
1441071d4279SBram Moolenaar
1442071d4279SBram Moolenaar /*
1443071d4279SBram Moolenaar * get_special_key_code() may return NUL for invalid
1444071d4279SBram Moolenaar * special key name.
1445071d4279SBram Moolenaar */
1446071d4279SBram Moolenaar if (key != NUL)
1447071d4279SBram Moolenaar {
1448071d4279SBram Moolenaar /*
1449071d4279SBram Moolenaar * Only use a modifier when there is no special key code that
1450071d4279SBram Moolenaar * includes the modifier.
1451071d4279SBram Moolenaar */
1452071d4279SBram Moolenaar key = simplify_key(key, &modifiers);
1453071d4279SBram Moolenaar
1454ebe9d34aSBram Moolenaar if (!(flags & FSK_KEYCODE))
1455071d4279SBram Moolenaar {
145685a2002aSBram Moolenaar // don't want keycode, use single byte code
1457071d4279SBram Moolenaar if (key == K_BS)
1458071d4279SBram Moolenaar key = BS;
1459071d4279SBram Moolenaar else if (key == K_DEL || key == K_KDEL)
1460071d4279SBram Moolenaar key = DEL;
1461071d4279SBram Moolenaar }
1462071d4279SBram Moolenaar
1463459fd785SBram Moolenaar // Normal Key with modifier: Try to make a single byte code.
1464071d4279SBram Moolenaar if (!IS_SPECIAL(key))
1465459fd785SBram Moolenaar key = extract_modifiers(key, &modifiers,
1466ebe9d34aSBram Moolenaar flags & FSK_SIMPLIFY, did_simplify);
1467071d4279SBram Moolenaar
1468071d4279SBram Moolenaar *modp = modifiers;
1469071d4279SBram Moolenaar *srcp = end_of_name;
1470071d4279SBram Moolenaar return key;
1471071d4279SBram Moolenaar }
1472071d4279SBram Moolenaar }
1473071d4279SBram Moolenaar }
1474071d4279SBram Moolenaar return 0;
1475071d4279SBram Moolenaar }
1476071d4279SBram Moolenaar
1477ef6746f6SBram Moolenaar
1478ef6746f6SBram Moolenaar /*
14794e2114e9SBram Moolenaar * Some keys are used with Ctrl without Shift and are still expected to be
14804e2114e9SBram Moolenaar * mapped as if Shift was pressed:
14814e2114e9SBram Moolenaar * CTRL-2 is CTRL-@
14824e2114e9SBram Moolenaar * CTRL-6 is CTRL-^
14834e2114e9SBram Moolenaar * CTRL-- is CTRL-_
14844e2114e9SBram Moolenaar * Also, <C-H> and <C-h> mean the same thing, always use "H".
14854e2114e9SBram Moolenaar * Returns the possibly adjusted key.
14864e2114e9SBram Moolenaar */
14874e2114e9SBram Moolenaar int
may_adjust_key_for_ctrl(int modifiers,int key)14884e2114e9SBram Moolenaar may_adjust_key_for_ctrl(int modifiers, int key)
14894e2114e9SBram Moolenaar {
14904e2114e9SBram Moolenaar if (modifiers & MOD_MASK_CTRL)
14914e2114e9SBram Moolenaar {
14924e2114e9SBram Moolenaar if (ASCII_ISALPHA(key))
14934e2114e9SBram Moolenaar return TOUPPER_ASC(key);
14944e2114e9SBram Moolenaar if (key == '2')
14954e2114e9SBram Moolenaar return '@';
14964e2114e9SBram Moolenaar if (key == '6')
14974e2114e9SBram Moolenaar return '^';
14984e2114e9SBram Moolenaar if (key == '-')
14994e2114e9SBram Moolenaar return '_';
15004e2114e9SBram Moolenaar }
15014e2114e9SBram Moolenaar return key;
15024e2114e9SBram Moolenaar }
15034e2114e9SBram Moolenaar
15044e2114e9SBram Moolenaar /*
1505ef6746f6SBram Moolenaar * Some keys already have Shift included, pass them as normal keys.
15069a033d7bSBram Moolenaar * When Ctrl is also used <C-H> and <C-S-H> are different, but <C-S-{> should
15079a033d7bSBram Moolenaar * be <C-{>. Same for <C-S-}> and <C-S-|>.
1508ef6746f6SBram Moolenaar * Also for <A-S-a> and <M-S-a>.
1509daff0fb7SBram Moolenaar * This includes all printable ASCII characters except numbers and a-z.
1510ef6746f6SBram Moolenaar */
1511ef6746f6SBram Moolenaar int
may_remove_shift_modifier(int modifiers,int key)1512ef6746f6SBram Moolenaar may_remove_shift_modifier(int modifiers, int key)
1513ef6746f6SBram Moolenaar {
1514ef6746f6SBram Moolenaar if ((modifiers == MOD_MASK_SHIFT
1515ef6746f6SBram Moolenaar || modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
1516ef6746f6SBram Moolenaar || modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
1517daff0fb7SBram Moolenaar && ((key >= '!' && key <= '/')
1518daff0fb7SBram Moolenaar || (key >= ':' && key <= 'Z')
1519daff0fb7SBram Moolenaar || (key >= '[' && key <= '`')
1520ef6746f6SBram Moolenaar || (key >= '{' && key <= '~')))
1521ef6746f6SBram Moolenaar return modifiers & ~MOD_MASK_SHIFT;
15229a033d7bSBram Moolenaar
15239a033d7bSBram Moolenaar if (modifiers == (MOD_MASK_SHIFT | MOD_MASK_CTRL)
15249a033d7bSBram Moolenaar && (key == '{' || key == '}' || key == '|'))
15259a033d7bSBram Moolenaar return modifiers & ~MOD_MASK_SHIFT;
15269a033d7bSBram Moolenaar
1527ef6746f6SBram Moolenaar return modifiers;
1528ef6746f6SBram Moolenaar }
1529ef6746f6SBram Moolenaar
1530071d4279SBram Moolenaar /*
1531071d4279SBram Moolenaar * Try to include modifiers in the key.
1532071d4279SBram Moolenaar * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
1533459fd785SBram Moolenaar * When "simplify" is FALSE don't do Ctrl and Alt.
1534459fd785SBram Moolenaar * When "simplify" is TRUE and Ctrl or Alt is removed from modifiers set
1535459fd785SBram Moolenaar * "did_simplify" when it's not NULL.
1536071d4279SBram Moolenaar */
1537071d4279SBram Moolenaar int
extract_modifiers(int key,int * modp,int simplify,int * did_simplify)1538459fd785SBram Moolenaar extract_modifiers(int key, int *modp, int simplify, int *did_simplify)
1539071d4279SBram Moolenaar {
1540071d4279SBram Moolenaar int modifiers = *modp;
1541071d4279SBram Moolenaar
1542d057301bSBram Moolenaar #ifdef MACOS_X
1543459fd785SBram Moolenaar // Command-key really special, no fancynest
1544071d4279SBram Moolenaar if (!(modifiers & MOD_MASK_CMD))
1545071d4279SBram Moolenaar #endif
1546071d4279SBram Moolenaar if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
1547071d4279SBram Moolenaar {
1548071d4279SBram Moolenaar key = TOUPPER_ASC(key);
154920298ce6SBram Moolenaar // With <C-S-a> we keep the shift modifier.
155020298ce6SBram Moolenaar // With <S-a>, <A-S-a> and <S-A> we don't keep the shift modifier.
155120298ce6SBram Moolenaar if (simplify || modifiers == MOD_MASK_SHIFT
155220298ce6SBram Moolenaar || modifiers == (MOD_MASK_SHIFT | MOD_MASK_ALT)
155320298ce6SBram Moolenaar || modifiers == (MOD_MASK_SHIFT | MOD_MASK_META))
1554071d4279SBram Moolenaar modifiers &= ~MOD_MASK_SHIFT;
1555071d4279SBram Moolenaar }
1556459fd785SBram Moolenaar
1557459fd785SBram Moolenaar // <C-H> and <C-h> mean the same thing, always use "H"
1558459fd785SBram Moolenaar if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key))
1559459fd785SBram Moolenaar key = TOUPPER_ASC(key);
1560459fd785SBram Moolenaar
1561459fd785SBram Moolenaar if (simplify && (modifiers & MOD_MASK_CTRL)
1562071d4279SBram Moolenaar #ifdef EBCDIC
1563459fd785SBram Moolenaar // TODO: EBCDIC Better use:
1564459fd785SBram Moolenaar // && (Ctrl_chr(key) || key == '?')
1565459fd785SBram Moolenaar // ???
1566071d4279SBram Moolenaar && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
1567071d4279SBram Moolenaar != NULL
1568071d4279SBram Moolenaar #else
1569071d4279SBram Moolenaar && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
1570071d4279SBram Moolenaar #endif
1571071d4279SBram Moolenaar )
1572071d4279SBram Moolenaar {
1573071d4279SBram Moolenaar key = Ctrl_chr(key);
1574071d4279SBram Moolenaar modifiers &= ~MOD_MASK_CTRL;
157585a2002aSBram Moolenaar // <C-@> is <Nul>
1576071d4279SBram Moolenaar if (key == 0)
1577071d4279SBram Moolenaar key = K_ZERO;
1578459fd785SBram Moolenaar if (did_simplify != NULL)
1579459fd785SBram Moolenaar *did_simplify = TRUE;
1580071d4279SBram Moolenaar }
1581459fd785SBram Moolenaar
1582d057301bSBram Moolenaar #ifdef MACOS_X
158385a2002aSBram Moolenaar // Command-key really special, no fancynest
1584071d4279SBram Moolenaar if (!(modifiers & MOD_MASK_CMD))
1585071d4279SBram Moolenaar #endif
1586459fd785SBram Moolenaar if (simplify && (modifiers & MOD_MASK_ALT) && key < 0x80
1587fc3abf47SBram Moolenaar && !enc_dbcs) // avoid creating a lead byte
1588071d4279SBram Moolenaar {
1589071d4279SBram Moolenaar key |= 0x80;
159085a2002aSBram Moolenaar modifiers &= ~MOD_MASK_ALT; // remove the META modifier
1591459fd785SBram Moolenaar if (did_simplify != NULL)
1592459fd785SBram Moolenaar *did_simplify = TRUE;
1593071d4279SBram Moolenaar }
1594071d4279SBram Moolenaar
1595071d4279SBram Moolenaar *modp = modifiers;
1596071d4279SBram Moolenaar return key;
1597071d4279SBram Moolenaar }
1598071d4279SBram Moolenaar
1599071d4279SBram Moolenaar /*
1600071d4279SBram Moolenaar * Try to find key "c" in the special key table.
1601071d4279SBram Moolenaar * Return the index when found, -1 when not found.
1602071d4279SBram Moolenaar */
1603071d4279SBram Moolenaar int
find_special_key_in_table(int c)16049b57814dSBram Moolenaar find_special_key_in_table(int c)
1605071d4279SBram Moolenaar {
1606071d4279SBram Moolenaar int i;
1607071d4279SBram Moolenaar
1608071d4279SBram Moolenaar for (i = 0; key_names_table[i].name != NULL; i++)
1609071d4279SBram Moolenaar if (c == key_names_table[i].key)
1610071d4279SBram Moolenaar break;
1611071d4279SBram Moolenaar if (key_names_table[i].name == NULL)
1612071d4279SBram Moolenaar i = -1;
1613071d4279SBram Moolenaar return i;
1614071d4279SBram Moolenaar }
1615071d4279SBram Moolenaar
1616071d4279SBram Moolenaar /*
1617071d4279SBram Moolenaar * Find the special key with the given name (the given string does not have to
1618071d4279SBram Moolenaar * end with NUL, the name is assumed to end before the first non-idchar).
1619071d4279SBram Moolenaar * If the name starts with "t_" the next two characters are interpreted as a
1620071d4279SBram Moolenaar * termcap name.
1621071d4279SBram Moolenaar * Return the key code, or 0 if not found.
1622071d4279SBram Moolenaar */
1623071d4279SBram Moolenaar int
get_special_key_code(char_u * name)16249b57814dSBram Moolenaar get_special_key_code(char_u *name)
1625071d4279SBram Moolenaar {
1626071d4279SBram Moolenaar char_u *table_name;
1627071d4279SBram Moolenaar char_u string[3];
1628071d4279SBram Moolenaar int i, j;
1629071d4279SBram Moolenaar
1630071d4279SBram Moolenaar /*
1631071d4279SBram Moolenaar * If it's <t_xx> we get the code for xx from the termcap
1632071d4279SBram Moolenaar */
1633071d4279SBram Moolenaar if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
1634071d4279SBram Moolenaar {
1635071d4279SBram Moolenaar string[0] = name[2];
1636071d4279SBram Moolenaar string[1] = name[3];
1637071d4279SBram Moolenaar string[2] = NUL;
1638071d4279SBram Moolenaar if (add_termcap_entry(string, FALSE) == OK)
1639071d4279SBram Moolenaar return TERMCAP2KEY(name[2], name[3]);
1640071d4279SBram Moolenaar }
1641071d4279SBram Moolenaar else
1642071d4279SBram Moolenaar for (i = 0; key_names_table[i].name != NULL; i++)
1643071d4279SBram Moolenaar {
1644071d4279SBram Moolenaar table_name = key_names_table[i].name;
1645e3d1f4c9SBram Moolenaar for (j = 0; vim_isNormalIDc(name[j]) && table_name[j] != NUL; j++)
1646071d4279SBram Moolenaar if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
1647071d4279SBram Moolenaar break;
1648e3d1f4c9SBram Moolenaar if (!vim_isNormalIDc(name[j]) && table_name[j] == NUL)
1649071d4279SBram Moolenaar return key_names_table[i].key;
1650071d4279SBram Moolenaar }
1651071d4279SBram Moolenaar return 0;
1652071d4279SBram Moolenaar }
1653071d4279SBram Moolenaar
1654071d4279SBram Moolenaar char_u *
get_key_name(int i)16559b57814dSBram Moolenaar get_key_name(int i)
1656071d4279SBram Moolenaar {
1657e1fbddcdSBram Moolenaar if (i >= (int)KEY_NAMES_TABLE_LEN)
1658071d4279SBram Moolenaar return NULL;
1659071d4279SBram Moolenaar return key_names_table[i].name;
1660071d4279SBram Moolenaar }
1661071d4279SBram Moolenaar
1662071d4279SBram Moolenaar /*
1663071d4279SBram Moolenaar * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
1664071d4279SBram Moolenaar */
1665071d4279SBram Moolenaar int
get_fileformat(buf_T * buf)16669b57814dSBram Moolenaar get_fileformat(buf_T *buf)
1667071d4279SBram Moolenaar {
1668071d4279SBram Moolenaar int c = *buf->b_p_ff;
1669071d4279SBram Moolenaar
1670071d4279SBram Moolenaar if (buf->b_p_bin || c == 'u')
1671071d4279SBram Moolenaar return EOL_UNIX;
1672071d4279SBram Moolenaar if (c == 'm')
1673071d4279SBram Moolenaar return EOL_MAC;
1674071d4279SBram Moolenaar return EOL_DOS;
1675071d4279SBram Moolenaar }
1676071d4279SBram Moolenaar
1677071d4279SBram Moolenaar /*
1678071d4279SBram Moolenaar * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
1679071d4279SBram Moolenaar * argument.
1680071d4279SBram Moolenaar */
1681071d4279SBram Moolenaar int
get_fileformat_force(buf_T * buf,exarg_T * eap)16829b57814dSBram Moolenaar get_fileformat_force(
16839b57814dSBram Moolenaar buf_T *buf,
168485a2002aSBram Moolenaar exarg_T *eap) // can be NULL!
1685071d4279SBram Moolenaar {
1686071d4279SBram Moolenaar int c;
1687071d4279SBram Moolenaar
1688071d4279SBram Moolenaar if (eap != NULL && eap->force_ff != 0)
1689333b80acSBram Moolenaar c = eap->force_ff;
1690071d4279SBram Moolenaar else
1691071d4279SBram Moolenaar {
1692071d4279SBram Moolenaar if ((eap != NULL && eap->force_bin != 0)
1693071d4279SBram Moolenaar ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin)
1694071d4279SBram Moolenaar return EOL_UNIX;
1695071d4279SBram Moolenaar c = *buf->b_p_ff;
1696071d4279SBram Moolenaar }
1697071d4279SBram Moolenaar if (c == 'u')
1698071d4279SBram Moolenaar return EOL_UNIX;
1699071d4279SBram Moolenaar if (c == 'm')
1700071d4279SBram Moolenaar return EOL_MAC;
1701071d4279SBram Moolenaar return EOL_DOS;
1702071d4279SBram Moolenaar }
1703071d4279SBram Moolenaar
1704071d4279SBram Moolenaar /*
1705071d4279SBram Moolenaar * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
1706071d4279SBram Moolenaar * Sets both 'textmode' and 'fileformat'.
1707071d4279SBram Moolenaar * Note: Does _not_ set global value of 'textmode'!
1708071d4279SBram Moolenaar */
1709071d4279SBram Moolenaar void
set_fileformat(int t,int opt_flags)17109b57814dSBram Moolenaar set_fileformat(
17119b57814dSBram Moolenaar int t,
171285a2002aSBram Moolenaar int opt_flags) // OPT_LOCAL and/or OPT_GLOBAL
1713071d4279SBram Moolenaar {
1714071d4279SBram Moolenaar char *p = NULL;
1715071d4279SBram Moolenaar
1716071d4279SBram Moolenaar switch (t)
1717071d4279SBram Moolenaar {
1718071d4279SBram Moolenaar case EOL_DOS:
1719071d4279SBram Moolenaar p = FF_DOS;
1720071d4279SBram Moolenaar curbuf->b_p_tx = TRUE;
1721071d4279SBram Moolenaar break;
1722071d4279SBram Moolenaar case EOL_UNIX:
1723071d4279SBram Moolenaar p = FF_UNIX;
1724071d4279SBram Moolenaar curbuf->b_p_tx = FALSE;
1725071d4279SBram Moolenaar break;
1726071d4279SBram Moolenaar case EOL_MAC:
1727071d4279SBram Moolenaar p = FF_MAC;
1728071d4279SBram Moolenaar curbuf->b_p_tx = FALSE;
1729071d4279SBram Moolenaar break;
1730071d4279SBram Moolenaar }
1731071d4279SBram Moolenaar if (p != NULL)
1732071d4279SBram Moolenaar set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
17335e3cb7e8SBram Moolenaar OPT_FREE | opt_flags, 0);
17345e3cb7e8SBram Moolenaar
173585a2002aSBram Moolenaar // This may cause the buffer to become (un)modified.
1736071d4279SBram Moolenaar check_status(curbuf);
1737997fb4baSBram Moolenaar redraw_tabline = TRUE;
1738071d4279SBram Moolenaar #ifdef FEAT_TITLE
173985a2002aSBram Moolenaar need_maketitle = TRUE; // set window title later
1740071d4279SBram Moolenaar #endif
1741071d4279SBram Moolenaar }
1742071d4279SBram Moolenaar
1743071d4279SBram Moolenaar /*
1744071d4279SBram Moolenaar * Return the default fileformat from 'fileformats'.
1745071d4279SBram Moolenaar */
1746071d4279SBram Moolenaar int
default_fileformat(void)17479b57814dSBram Moolenaar default_fileformat(void)
1748071d4279SBram Moolenaar {
1749071d4279SBram Moolenaar switch (*p_ffs)
1750071d4279SBram Moolenaar {
1751071d4279SBram Moolenaar case 'm': return EOL_MAC;
1752071d4279SBram Moolenaar case 'd': return EOL_DOS;
1753071d4279SBram Moolenaar }
1754071d4279SBram Moolenaar return EOL_UNIX;
1755071d4279SBram Moolenaar }
1756071d4279SBram Moolenaar
1757071d4279SBram Moolenaar /*
1758071d4279SBram Moolenaar * Call shell. Calls mch_call_shell, with 'shellxquote' added.
1759071d4279SBram Moolenaar */
1760071d4279SBram Moolenaar int
call_shell(char_u * cmd,int opt)17619b57814dSBram Moolenaar call_shell(char_u *cmd, int opt)
1762071d4279SBram Moolenaar {
1763071d4279SBram Moolenaar char_u *ncmd;
1764071d4279SBram Moolenaar int retval;
176505159a0cSBram Moolenaar #ifdef FEAT_PROFILE
176605159a0cSBram Moolenaar proftime_T wait_time;
176705159a0cSBram Moolenaar #endif
1768071d4279SBram Moolenaar
1769071d4279SBram Moolenaar if (p_verbose > 3)
1770071d4279SBram Moolenaar {
17715c06f8b0SBram Moolenaar verbose_enter();
177206f0853cSBram Moolenaar smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd);
1773071d4279SBram Moolenaar out_char('\n');
1774071d4279SBram Moolenaar cursor_on();
17755c06f8b0SBram Moolenaar verbose_leave();
1776071d4279SBram Moolenaar }
1777071d4279SBram Moolenaar
177805159a0cSBram Moolenaar #ifdef FEAT_PROFILE
17790126585dSBram Moolenaar if (do_profiling == PROF_YES)
178005159a0cSBram Moolenaar prof_child_enter(&wait_time);
178105159a0cSBram Moolenaar #endif
178205159a0cSBram Moolenaar
1783071d4279SBram Moolenaar if (*p_sh == NUL)
1784071d4279SBram Moolenaar {
1785f9e3e09fSBram Moolenaar emsg(_(e_shellempty));
1786071d4279SBram Moolenaar retval = -1;
1787071d4279SBram Moolenaar }
1788071d4279SBram Moolenaar else
1789071d4279SBram Moolenaar {
1790071d4279SBram Moolenaar #ifdef FEAT_GUI_MSWIN
179185a2002aSBram Moolenaar // Don't hide the pointer while executing a shell command.
1792071d4279SBram Moolenaar gui_mch_mousehide(FALSE);
1793071d4279SBram Moolenaar #endif
1794071d4279SBram Moolenaar #ifdef FEAT_GUI
1795071d4279SBram Moolenaar ++hold_gui_events;
1796071d4279SBram Moolenaar #endif
179785a2002aSBram Moolenaar // The external command may update a tags file, clear cached tags.
1798071d4279SBram Moolenaar tag_freematch();
1799071d4279SBram Moolenaar
180001257a7aSBram Moolenaar if (cmd == NULL || *p_sxq == NUL)
1801071d4279SBram Moolenaar retval = mch_call_shell(cmd, opt);
1802071d4279SBram Moolenaar else
1803071d4279SBram Moolenaar {
1804f66b3fcfSBram Moolenaar char_u *ecmd = cmd;
1805f66b3fcfSBram Moolenaar
18061a613398SBram Moolenaar if (*p_sxe != NUL && *p_sxq == '(')
1807f66b3fcfSBram Moolenaar {
1808f66b3fcfSBram Moolenaar ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE);
1809f66b3fcfSBram Moolenaar if (ecmd == NULL)
1810f66b3fcfSBram Moolenaar ecmd = cmd;
1811f66b3fcfSBram Moolenaar }
1812964b3746SBram Moolenaar ncmd = alloc(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1);
1813071d4279SBram Moolenaar if (ncmd != NULL)
1814071d4279SBram Moolenaar {
1815071d4279SBram Moolenaar STRCPY(ncmd, p_sxq);
1816f66b3fcfSBram Moolenaar STRCAT(ncmd, ecmd);
18171a613398SBram Moolenaar // When 'shellxquote' is ( append ).
18181a613398SBram Moolenaar // When 'shellxquote' is "( append )".
18191a613398SBram Moolenaar STRCAT(ncmd, *p_sxq == '(' ? (char_u *)")"
18201a613398SBram Moolenaar : *p_sxq == '"' && *(p_sxq+1) == '(' ? (char_u *)")\""
1821034b1155SBram Moolenaar : p_sxq);
1822071d4279SBram Moolenaar retval = mch_call_shell(ncmd, opt);
1823071d4279SBram Moolenaar vim_free(ncmd);
1824071d4279SBram Moolenaar }
1825071d4279SBram Moolenaar else
1826071d4279SBram Moolenaar retval = -1;
1827f66b3fcfSBram Moolenaar if (ecmd != cmd)
1828f66b3fcfSBram Moolenaar vim_free(ecmd);
1829071d4279SBram Moolenaar }
1830071d4279SBram Moolenaar #ifdef FEAT_GUI
1831071d4279SBram Moolenaar --hold_gui_events;
1832071d4279SBram Moolenaar #endif
1833071d4279SBram Moolenaar /*
1834071d4279SBram Moolenaar * Check the window size, in case it changed while executing the
1835071d4279SBram Moolenaar * external command.
1836071d4279SBram Moolenaar */
1837071d4279SBram Moolenaar shell_resized_check();
1838071d4279SBram Moolenaar }
1839071d4279SBram Moolenaar
1840071d4279SBram Moolenaar #ifdef FEAT_EVAL
1841071d4279SBram Moolenaar set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
184205159a0cSBram Moolenaar # ifdef FEAT_PROFILE
18430126585dSBram Moolenaar if (do_profiling == PROF_YES)
184405159a0cSBram Moolenaar prof_child_exit(&wait_time);
184505159a0cSBram Moolenaar # endif
1846071d4279SBram Moolenaar #endif
1847071d4279SBram Moolenaar
1848071d4279SBram Moolenaar return retval;
1849071d4279SBram Moolenaar }
1850071d4279SBram Moolenaar
1851071d4279SBram Moolenaar /*
18520126585dSBram Moolenaar * VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to
18530126585dSBram Moolenaar * NORMAL State with a condition. This function returns the real State.
1854071d4279SBram Moolenaar */
1855071d4279SBram Moolenaar int
get_real_state(void)18569b57814dSBram Moolenaar get_real_state(void)
1857071d4279SBram Moolenaar {
1858071d4279SBram Moolenaar if (State & NORMAL)
1859071d4279SBram Moolenaar {
1860071d4279SBram Moolenaar if (VIsual_active)
18610126585dSBram Moolenaar {
18620126585dSBram Moolenaar if (VIsual_select)
18630126585dSBram Moolenaar return SELECTMODE;
1864071d4279SBram Moolenaar return VISUAL;
18650126585dSBram Moolenaar }
1866f7ff6e85SBram Moolenaar else if (finish_op)
1867071d4279SBram Moolenaar return OP_PENDING;
1868071d4279SBram Moolenaar }
1869071d4279SBram Moolenaar return State;
1870071d4279SBram Moolenaar }
1871071d4279SBram Moolenaar
18721cd871b5SBram Moolenaar /*
18731cd871b5SBram Moolenaar * Return TRUE if "p" points to just after a path separator.
1874b5ce04ddSBram Moolenaar * Takes care of multi-byte characters.
18751cd871b5SBram Moolenaar * "b" must point to the start of the file name
18761cd871b5SBram Moolenaar */
18771cd871b5SBram Moolenaar int
after_pathsep(char_u * b,char_u * p)18789b57814dSBram Moolenaar after_pathsep(char_u *b, char_u *p)
18791cd871b5SBram Moolenaar {
1880b5ce04ddSBram Moolenaar return p > b && vim_ispathsep(p[-1])
18811cd871b5SBram Moolenaar && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0);
18821cd871b5SBram Moolenaar }
18831cd871b5SBram Moolenaar
18841cd871b5SBram Moolenaar /*
18851cd871b5SBram Moolenaar * Return TRUE if file names "f1" and "f2" are in the same directory.
18861cd871b5SBram Moolenaar * "f1" may be a short name, "f2" must be a full path.
18871cd871b5SBram Moolenaar */
18881cd871b5SBram Moolenaar int
same_directory(char_u * f1,char_u * f2)18899b57814dSBram Moolenaar same_directory(char_u *f1, char_u *f2)
18901cd871b5SBram Moolenaar {
18911cd871b5SBram Moolenaar char_u ffname[MAXPATHL];
18921cd871b5SBram Moolenaar char_u *t1;
18931cd871b5SBram Moolenaar char_u *t2;
18941cd871b5SBram Moolenaar
189585a2002aSBram Moolenaar // safety check
18961cd871b5SBram Moolenaar if (f1 == NULL || f2 == NULL)
18971cd871b5SBram Moolenaar return FALSE;
18981cd871b5SBram Moolenaar
18991cd871b5SBram Moolenaar (void)vim_FullName(f1, ffname, MAXPATHL, FALSE);
19001cd871b5SBram Moolenaar t1 = gettail_sep(ffname);
19011cd871b5SBram Moolenaar t2 = gettail_sep(f2);
19021cd871b5SBram Moolenaar return (t1 - ffname == t2 - f2
19031cd871b5SBram Moolenaar && pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0);
19041cd871b5SBram Moolenaar }
19051cd871b5SBram Moolenaar
19067c365fb1SBram Moolenaar #if defined(FEAT_SESSION) || defined(FEAT_AUTOCHDIR) \
1907097148e8SBram Moolenaar || defined(MSWIN) || defined(FEAT_GUI_GTK) \
1908bb1969b6SBram Moolenaar || defined(FEAT_NETBEANS_INTG) \
1909071d4279SBram Moolenaar || defined(PROTO)
1910071d4279SBram Moolenaar /*
1911071d4279SBram Moolenaar * Change to a file's directory.
1912071d4279SBram Moolenaar * Caller must call shorten_fnames()!
1913071d4279SBram Moolenaar * Return OK or FAIL.
1914071d4279SBram Moolenaar */
1915071d4279SBram Moolenaar int
vim_chdirfile(char_u * fname,char * trigger_autocmd)19162caad3fbSBram Moolenaar vim_chdirfile(char_u *fname, char *trigger_autocmd)
1917071d4279SBram Moolenaar {
19182caad3fbSBram Moolenaar char_u old_dir[MAXPATHL];
19192caad3fbSBram Moolenaar char_u new_dir[MAXPATHL];
1920b5cb65baSBram Moolenaar int res;
1921071d4279SBram Moolenaar
19222caad3fbSBram Moolenaar if (mch_dirname(old_dir, MAXPATHL) != OK)
19232caad3fbSBram Moolenaar *old_dir = NUL;
19242caad3fbSBram Moolenaar
19252caad3fbSBram Moolenaar vim_strncpy(new_dir, fname, MAXPATHL - 1);
19262caad3fbSBram Moolenaar *gettail_sep(new_dir) = NUL;
19272caad3fbSBram Moolenaar
19289eb76af4SBram Moolenaar if (pathcmp((char *)old_dir, (char *)new_dir, -1) == 0)
19292caad3fbSBram Moolenaar // nothing to do
19302caad3fbSBram Moolenaar res = OK;
19312caad3fbSBram Moolenaar else
19322caad3fbSBram Moolenaar {
19332caad3fbSBram Moolenaar res = mch_chdir((char *)new_dir) == 0 ? OK : FAIL;
19342caad3fbSBram Moolenaar
1935b5cb65baSBram Moolenaar if (res == OK && trigger_autocmd != NULL)
1936b5cb65baSBram Moolenaar apply_autocmds(EVENT_DIRCHANGED, (char_u *)trigger_autocmd,
19372caad3fbSBram Moolenaar new_dir, FALSE, curbuf);
19382caad3fbSBram Moolenaar }
1939b5cb65baSBram Moolenaar return res;
1940071d4279SBram Moolenaar }
1941071d4279SBram Moolenaar #endif
1942071d4279SBram Moolenaar
1943071d4279SBram Moolenaar #if defined(STAT_IGNORES_SLASH) || defined(PROTO)
1944071d4279SBram Moolenaar /*
1945071d4279SBram Moolenaar * Check if "name" ends in a slash and is not a directory.
1946071d4279SBram Moolenaar * Used for systems where stat() ignores a trailing slash on a file name.
1947071d4279SBram Moolenaar * The Vim code assumes a trailing slash is only ignored for a directory.
1948071d4279SBram Moolenaar */
194991acfffcSBram Moolenaar static int
illegal_slash(const char * name)1950d8492792SBram Moolenaar illegal_slash(const char *name)
1951071d4279SBram Moolenaar {
1952071d4279SBram Moolenaar if (name[0] == NUL)
195385a2002aSBram Moolenaar return FALSE; // no file name is not illegal
1954071d4279SBram Moolenaar if (name[strlen(name) - 1] != '/')
195585a2002aSBram Moolenaar return FALSE; // no trailing slash
1956071d4279SBram Moolenaar if (mch_isdir((char_u *)name))
195785a2002aSBram Moolenaar return FALSE; // trailing slash for a directory
1958071d4279SBram Moolenaar return TRUE;
1959071d4279SBram Moolenaar }
196091acfffcSBram Moolenaar
196191acfffcSBram Moolenaar /*
196291acfffcSBram Moolenaar * Special implementation of mch_stat() for Solaris.
196391acfffcSBram Moolenaar */
196491acfffcSBram Moolenaar int
vim_stat(const char * name,stat_T * stp)196591acfffcSBram Moolenaar vim_stat(const char *name, stat_T *stp)
196691acfffcSBram Moolenaar {
196785a2002aSBram Moolenaar // On Solaris stat() accepts "file/" as if it was "file". Return -1 if
196885a2002aSBram Moolenaar // the name ends in "/" and it's not a directory.
1969d8492792SBram Moolenaar return illegal_slash(name) ? -1 : stat(name, stp);
197091acfffcSBram Moolenaar }
1971071d4279SBram Moolenaar #endif
1972071d4279SBram Moolenaar
1973071d4279SBram Moolenaar #if defined(CURSOR_SHAPE) || defined(PROTO)
1974071d4279SBram Moolenaar
1975071d4279SBram Moolenaar /*
1976071d4279SBram Moolenaar * Handling of cursor and mouse pointer shapes in various modes.
1977071d4279SBram Moolenaar */
1978071d4279SBram Moolenaar
1979071d4279SBram Moolenaar cursorentry_T shape_table[SHAPE_IDX_COUNT] =
1980071d4279SBram Moolenaar {
198185a2002aSBram Moolenaar // The values will be filled in from the 'guicursor' and 'mouseshape'
198285a2002aSBram Moolenaar // defaults when Vim starts.
198385a2002aSBram Moolenaar // Adjust the SHAPE_IDX_ defines when making changes!
1984071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
1985071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
1986071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
1987071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
1988071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
1989071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
1990071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
1991071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
1992071d4279SBram Moolenaar {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
1993071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE},
1994071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE},
1995071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE},
1996071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE},
1997071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE},
1998071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE},
1999071d4279SBram Moolenaar {0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE},
2000071d4279SBram Moolenaar {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
2001071d4279SBram Moolenaar };
2002071d4279SBram Moolenaar
2003071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2004071d4279SBram Moolenaar /*
2005071d4279SBram Moolenaar * Table with names for mouse shapes. Keep in sync with all the tables for
2006071d4279SBram Moolenaar * mch_set_mouse_shape()!.
2007071d4279SBram Moolenaar */
2008071d4279SBram Moolenaar static char * mshape_names[] =
2009071d4279SBram Moolenaar {
201085a2002aSBram Moolenaar "arrow", // default, must be the first one
201185a2002aSBram Moolenaar "blank", // hidden
2012071d4279SBram Moolenaar "beam",
2013071d4279SBram Moolenaar "updown",
2014071d4279SBram Moolenaar "udsizing",
2015071d4279SBram Moolenaar "leftright",
2016071d4279SBram Moolenaar "lrsizing",
2017071d4279SBram Moolenaar "busy",
2018071d4279SBram Moolenaar "no",
2019071d4279SBram Moolenaar "crosshair",
2020071d4279SBram Moolenaar "hand1",
2021071d4279SBram Moolenaar "hand2",
2022071d4279SBram Moolenaar "pencil",
2023071d4279SBram Moolenaar "question",
2024071d4279SBram Moolenaar "rightup-arrow",
2025071d4279SBram Moolenaar "up-arrow",
2026071d4279SBram Moolenaar NULL
2027071d4279SBram Moolenaar };
2028071d4279SBram Moolenaar #endif
2029071d4279SBram Moolenaar
2030071d4279SBram Moolenaar /*
2031071d4279SBram Moolenaar * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
2032071d4279SBram Moolenaar * ("what" is SHAPE_MOUSE).
2033071d4279SBram Moolenaar * Returns error message for an illegal option, NULL otherwise.
2034071d4279SBram Moolenaar */
2035f9e3e09fSBram Moolenaar char *
parse_shape_opt(int what)20369b57814dSBram Moolenaar parse_shape_opt(int what)
2037071d4279SBram Moolenaar {
2038071d4279SBram Moolenaar char_u *modep;
2039071d4279SBram Moolenaar char_u *colonp;
2040071d4279SBram Moolenaar char_u *commap;
2041071d4279SBram Moolenaar char_u *slashp;
2042071d4279SBram Moolenaar char_u *p, *endp;
204385a2002aSBram Moolenaar int idx = 0; // init for GCC
2044071d4279SBram Moolenaar int all_idx;
2045071d4279SBram Moolenaar int len;
2046071d4279SBram Moolenaar int i;
2047071d4279SBram Moolenaar long n;
204885a2002aSBram Moolenaar int found_ve = FALSE; // found "ve" flag
2049071d4279SBram Moolenaar int round;
2050071d4279SBram Moolenaar
2051071d4279SBram Moolenaar /*
2052071d4279SBram Moolenaar * First round: check for errors; second round: do it for real.
2053071d4279SBram Moolenaar */
2054071d4279SBram Moolenaar for (round = 1; round <= 2; ++round)
2055071d4279SBram Moolenaar {
2056071d4279SBram Moolenaar /*
2057071d4279SBram Moolenaar * Repeat for all comma separated parts.
2058071d4279SBram Moolenaar */
2059071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2060071d4279SBram Moolenaar if (what == SHAPE_MOUSE)
2061071d4279SBram Moolenaar modep = p_mouseshape;
2062071d4279SBram Moolenaar else
2063071d4279SBram Moolenaar #endif
2064071d4279SBram Moolenaar modep = p_guicursor;
2065071d4279SBram Moolenaar while (*modep != NUL)
2066071d4279SBram Moolenaar {
2067071d4279SBram Moolenaar colonp = vim_strchr(modep, ':');
206824922ec2SBram Moolenaar commap = vim_strchr(modep, ',');
206924922ec2SBram Moolenaar
207024922ec2SBram Moolenaar if (colonp == NULL || (commap != NULL && commap < colonp))
2071f9e3e09fSBram Moolenaar return N_("E545: Missing colon");
2072071d4279SBram Moolenaar if (colonp == modep)
2073f9e3e09fSBram Moolenaar return N_("E546: Illegal mode");
2074071d4279SBram Moolenaar
2075071d4279SBram Moolenaar /*
2076071d4279SBram Moolenaar * Repeat for all mode's before the colon.
2077071d4279SBram Moolenaar * For the 'a' mode, we loop to handle all the modes.
2078071d4279SBram Moolenaar */
2079071d4279SBram Moolenaar all_idx = -1;
2080071d4279SBram Moolenaar while (modep < colonp || all_idx >= 0)
2081071d4279SBram Moolenaar {
2082071d4279SBram Moolenaar if (all_idx < 0)
2083071d4279SBram Moolenaar {
208485a2002aSBram Moolenaar // Find the mode.
2085071d4279SBram Moolenaar if (modep[1] == '-' || modep[1] == ':')
2086071d4279SBram Moolenaar len = 1;
2087071d4279SBram Moolenaar else
2088071d4279SBram Moolenaar len = 2;
2089071d4279SBram Moolenaar if (len == 1 && TOLOWER_ASC(modep[0]) == 'a')
2090071d4279SBram Moolenaar all_idx = SHAPE_IDX_COUNT - 1;
2091071d4279SBram Moolenaar else
2092071d4279SBram Moolenaar {
2093071d4279SBram Moolenaar for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
2094071d4279SBram Moolenaar if (STRNICMP(modep, shape_table[idx].name, len)
2095071d4279SBram Moolenaar == 0)
2096071d4279SBram Moolenaar break;
2097071d4279SBram Moolenaar if (idx == SHAPE_IDX_COUNT
2098071d4279SBram Moolenaar || (shape_table[idx].used_for & what) == 0)
2099f9e3e09fSBram Moolenaar return N_("E546: Illegal mode");
2100071d4279SBram Moolenaar if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
2101071d4279SBram Moolenaar found_ve = TRUE;
2102071d4279SBram Moolenaar }
2103071d4279SBram Moolenaar modep += len + 1;
2104071d4279SBram Moolenaar }
2105071d4279SBram Moolenaar
2106071d4279SBram Moolenaar if (all_idx >= 0)
2107071d4279SBram Moolenaar idx = all_idx--;
2108071d4279SBram Moolenaar else if (round == 2)
2109071d4279SBram Moolenaar {
2110071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2111071d4279SBram Moolenaar if (what == SHAPE_MOUSE)
2112071d4279SBram Moolenaar {
211385a2002aSBram Moolenaar // Set the default, for the missing parts
2114071d4279SBram Moolenaar shape_table[idx].mshape = 0;
2115071d4279SBram Moolenaar }
2116071d4279SBram Moolenaar else
2117071d4279SBram Moolenaar #endif
2118071d4279SBram Moolenaar {
211985a2002aSBram Moolenaar // Set the defaults, for the missing parts
2120071d4279SBram Moolenaar shape_table[idx].shape = SHAPE_BLOCK;
2121071d4279SBram Moolenaar shape_table[idx].blinkwait = 700L;
2122071d4279SBram Moolenaar shape_table[idx].blinkon = 400L;
2123071d4279SBram Moolenaar shape_table[idx].blinkoff = 250L;
2124071d4279SBram Moolenaar }
2125071d4279SBram Moolenaar }
2126071d4279SBram Moolenaar
212785a2002aSBram Moolenaar // Parse the part after the colon
2128071d4279SBram Moolenaar for (p = colonp + 1; *p && *p != ','; )
2129071d4279SBram Moolenaar {
2130071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2131071d4279SBram Moolenaar if (what == SHAPE_MOUSE)
2132071d4279SBram Moolenaar {
2133071d4279SBram Moolenaar for (i = 0; ; ++i)
2134071d4279SBram Moolenaar {
2135071d4279SBram Moolenaar if (mshape_names[i] == NULL)
2136071d4279SBram Moolenaar {
2137071d4279SBram Moolenaar if (!VIM_ISDIGIT(*p))
2138f9e3e09fSBram Moolenaar return N_("E547: Illegal mouseshape");
2139071d4279SBram Moolenaar if (round == 2)
2140071d4279SBram Moolenaar shape_table[idx].mshape =
2141071d4279SBram Moolenaar getdigits(&p) + MSHAPE_NUMBERED;
2142071d4279SBram Moolenaar else
2143071d4279SBram Moolenaar (void)getdigits(&p);
2144071d4279SBram Moolenaar break;
2145071d4279SBram Moolenaar }
2146071d4279SBram Moolenaar len = (int)STRLEN(mshape_names[i]);
2147071d4279SBram Moolenaar if (STRNICMP(p, mshape_names[i], len) == 0)
2148071d4279SBram Moolenaar {
2149071d4279SBram Moolenaar if (round == 2)
2150071d4279SBram Moolenaar shape_table[idx].mshape = i;
2151071d4279SBram Moolenaar p += len;
2152071d4279SBram Moolenaar break;
2153071d4279SBram Moolenaar }
2154071d4279SBram Moolenaar }
2155071d4279SBram Moolenaar }
215685a2002aSBram Moolenaar else // if (what == SHAPE_MOUSE)
2157071d4279SBram Moolenaar #endif
2158071d4279SBram Moolenaar {
2159071d4279SBram Moolenaar /*
2160071d4279SBram Moolenaar * First handle the ones with a number argument.
2161071d4279SBram Moolenaar */
2162071d4279SBram Moolenaar i = *p;
2163071d4279SBram Moolenaar len = 0;
2164071d4279SBram Moolenaar if (STRNICMP(p, "ver", 3) == 0)
2165071d4279SBram Moolenaar len = 3;
2166071d4279SBram Moolenaar else if (STRNICMP(p, "hor", 3) == 0)
2167071d4279SBram Moolenaar len = 3;
2168071d4279SBram Moolenaar else if (STRNICMP(p, "blinkwait", 9) == 0)
2169071d4279SBram Moolenaar len = 9;
2170071d4279SBram Moolenaar else if (STRNICMP(p, "blinkon", 7) == 0)
2171071d4279SBram Moolenaar len = 7;
2172071d4279SBram Moolenaar else if (STRNICMP(p, "blinkoff", 8) == 0)
2173071d4279SBram Moolenaar len = 8;
2174071d4279SBram Moolenaar if (len != 0)
2175071d4279SBram Moolenaar {
2176071d4279SBram Moolenaar p += len;
2177071d4279SBram Moolenaar if (!VIM_ISDIGIT(*p))
2178f9e3e09fSBram Moolenaar return N_("E548: digit expected");
2179071d4279SBram Moolenaar n = getdigits(&p);
218085a2002aSBram Moolenaar if (len == 3) // "ver" or "hor"
2181071d4279SBram Moolenaar {
2182071d4279SBram Moolenaar if (n == 0)
2183f9e3e09fSBram Moolenaar return N_("E549: Illegal percentage");
2184071d4279SBram Moolenaar if (round == 2)
2185071d4279SBram Moolenaar {
2186071d4279SBram Moolenaar if (TOLOWER_ASC(i) == 'v')
2187071d4279SBram Moolenaar shape_table[idx].shape = SHAPE_VER;
2188071d4279SBram Moolenaar else
2189071d4279SBram Moolenaar shape_table[idx].shape = SHAPE_HOR;
2190071d4279SBram Moolenaar shape_table[idx].percentage = n;
2191071d4279SBram Moolenaar }
2192071d4279SBram Moolenaar }
2193071d4279SBram Moolenaar else if (round == 2)
2194071d4279SBram Moolenaar {
2195071d4279SBram Moolenaar if (len == 9)
2196071d4279SBram Moolenaar shape_table[idx].blinkwait = n;
2197071d4279SBram Moolenaar else if (len == 7)
2198071d4279SBram Moolenaar shape_table[idx].blinkon = n;
2199071d4279SBram Moolenaar else
2200071d4279SBram Moolenaar shape_table[idx].blinkoff = n;
2201071d4279SBram Moolenaar }
2202071d4279SBram Moolenaar }
2203071d4279SBram Moolenaar else if (STRNICMP(p, "block", 5) == 0)
2204071d4279SBram Moolenaar {
2205071d4279SBram Moolenaar if (round == 2)
2206071d4279SBram Moolenaar shape_table[idx].shape = SHAPE_BLOCK;
2207071d4279SBram Moolenaar p += 5;
2208071d4279SBram Moolenaar }
220985a2002aSBram Moolenaar else // must be a highlight group name then
2210071d4279SBram Moolenaar {
2211071d4279SBram Moolenaar endp = vim_strchr(p, '-');
221285a2002aSBram Moolenaar if (commap == NULL) // last part
2213071d4279SBram Moolenaar {
2214071d4279SBram Moolenaar if (endp == NULL)
221585a2002aSBram Moolenaar endp = p + STRLEN(p); // find end of part
2216071d4279SBram Moolenaar }
2217071d4279SBram Moolenaar else if (endp > commap || endp == NULL)
2218071d4279SBram Moolenaar endp = commap;
2219071d4279SBram Moolenaar slashp = vim_strchr(p, '/');
2220071d4279SBram Moolenaar if (slashp != NULL && slashp < endp)
2221071d4279SBram Moolenaar {
222285a2002aSBram Moolenaar // "group/langmap_group"
2223071d4279SBram Moolenaar i = syn_check_group(p, (int)(slashp - p));
2224071d4279SBram Moolenaar p = slashp + 1;
2225071d4279SBram Moolenaar }
2226071d4279SBram Moolenaar if (round == 2)
2227071d4279SBram Moolenaar {
2228071d4279SBram Moolenaar shape_table[idx].id = syn_check_group(p,
2229071d4279SBram Moolenaar (int)(endp - p));
2230071d4279SBram Moolenaar shape_table[idx].id_lm = shape_table[idx].id;
2231071d4279SBram Moolenaar if (slashp != NULL && slashp < endp)
2232071d4279SBram Moolenaar shape_table[idx].id = i;
2233071d4279SBram Moolenaar }
2234071d4279SBram Moolenaar p = endp;
2235071d4279SBram Moolenaar }
223685a2002aSBram Moolenaar } // if (what != SHAPE_MOUSE)
2237071d4279SBram Moolenaar
2238071d4279SBram Moolenaar if (*p == '-')
2239071d4279SBram Moolenaar ++p;
2240071d4279SBram Moolenaar }
2241071d4279SBram Moolenaar }
2242071d4279SBram Moolenaar modep = p;
2243071d4279SBram Moolenaar if (*modep == ',')
2244071d4279SBram Moolenaar ++modep;
2245071d4279SBram Moolenaar }
2246071d4279SBram Moolenaar }
2247071d4279SBram Moolenaar
224885a2002aSBram Moolenaar // If the 's' flag is not given, use the 'v' cursor for 's'
2249071d4279SBram Moolenaar if (!found_ve)
2250071d4279SBram Moolenaar {
2251071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2252071d4279SBram Moolenaar if (what == SHAPE_MOUSE)
2253071d4279SBram Moolenaar {
2254071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape;
2255071d4279SBram Moolenaar }
2256071d4279SBram Moolenaar else
2257071d4279SBram Moolenaar #endif
2258071d4279SBram Moolenaar {
2259071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
2260071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].percentage =
2261071d4279SBram Moolenaar shape_table[SHAPE_IDX_V].percentage;
2262071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].blinkwait =
2263071d4279SBram Moolenaar shape_table[SHAPE_IDX_V].blinkwait;
2264071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].blinkon =
2265071d4279SBram Moolenaar shape_table[SHAPE_IDX_V].blinkon;
2266071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].blinkoff =
2267071d4279SBram Moolenaar shape_table[SHAPE_IDX_V].blinkoff;
2268071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
2269071d4279SBram Moolenaar shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
2270071d4279SBram Moolenaar }
2271071d4279SBram Moolenaar }
2272071d4279SBram Moolenaar
2273071d4279SBram Moolenaar return NULL;
2274071d4279SBram Moolenaar }
2275071d4279SBram Moolenaar
2276ac6e65f8SBram Moolenaar # if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \
2277ac6e65f8SBram Moolenaar || defined(FEAT_MOUSESHAPE) || defined(PROTO)
2278071d4279SBram Moolenaar /*
2279071d4279SBram Moolenaar * Return the index into shape_table[] for the current mode.
2280071d4279SBram Moolenaar * When "mouse" is TRUE, consider indexes valid for the mouse pointer.
2281071d4279SBram Moolenaar */
2282071d4279SBram Moolenaar int
get_shape_idx(int mouse)22839b57814dSBram Moolenaar get_shape_idx(int mouse)
2284071d4279SBram Moolenaar {
2285071d4279SBram Moolenaar #ifdef FEAT_MOUSESHAPE
2286071d4279SBram Moolenaar if (mouse && (State == HITRETURN || State == ASKMORE))
2287071d4279SBram Moolenaar {
2288071d4279SBram Moolenaar # ifdef FEAT_GUI
22899588a0f7SBram Moolenaar int x, y;
22909588a0f7SBram Moolenaar gui_mch_getmouse(&x, &y);
22919588a0f7SBram Moolenaar if (Y_2_ROW(y) == Rows - 1)
2292071d4279SBram Moolenaar return SHAPE_IDX_MOREL;
2293071d4279SBram Moolenaar # endif
2294071d4279SBram Moolenaar return SHAPE_IDX_MORE;
2295071d4279SBram Moolenaar }
2296071d4279SBram Moolenaar if (mouse && drag_status_line)
2297071d4279SBram Moolenaar return SHAPE_IDX_SDRAG;
2298071d4279SBram Moolenaar if (mouse && drag_sep_line)
2299071d4279SBram Moolenaar return SHAPE_IDX_VDRAG;
2300071d4279SBram Moolenaar #endif
2301071d4279SBram Moolenaar if (!mouse && State == SHOWMATCH)
2302071d4279SBram Moolenaar return SHAPE_IDX_SM;
2303071d4279SBram Moolenaar if (State & VREPLACE_FLAG)
2304071d4279SBram Moolenaar return SHAPE_IDX_R;
2305071d4279SBram Moolenaar if (State & REPLACE_FLAG)
2306071d4279SBram Moolenaar return SHAPE_IDX_R;
2307071d4279SBram Moolenaar if (State & INSERT)
2308071d4279SBram Moolenaar return SHAPE_IDX_I;
2309071d4279SBram Moolenaar if (State & CMDLINE)
2310071d4279SBram Moolenaar {
2311071d4279SBram Moolenaar if (cmdline_at_end())
2312071d4279SBram Moolenaar return SHAPE_IDX_C;
2313071d4279SBram Moolenaar if (cmdline_overstrike())
2314071d4279SBram Moolenaar return SHAPE_IDX_CR;
2315071d4279SBram Moolenaar return SHAPE_IDX_CI;
2316071d4279SBram Moolenaar }
2317071d4279SBram Moolenaar if (finish_op)
2318071d4279SBram Moolenaar return SHAPE_IDX_O;
2319071d4279SBram Moolenaar if (VIsual_active)
2320071d4279SBram Moolenaar {
2321071d4279SBram Moolenaar if (*p_sel == 'e')
2322071d4279SBram Moolenaar return SHAPE_IDX_VE;
2323071d4279SBram Moolenaar else
2324071d4279SBram Moolenaar return SHAPE_IDX_V;
2325071d4279SBram Moolenaar }
2326071d4279SBram Moolenaar return SHAPE_IDX_N;
2327071d4279SBram Moolenaar }
2328ac6e65f8SBram Moolenaar #endif
2329071d4279SBram Moolenaar
2330071d4279SBram Moolenaar # if defined(FEAT_MOUSESHAPE) || defined(PROTO)
2331071d4279SBram Moolenaar static int old_mouse_shape = 0;
2332071d4279SBram Moolenaar
2333071d4279SBram Moolenaar /*
2334071d4279SBram Moolenaar * Set the mouse shape:
2335071d4279SBram Moolenaar * If "shape" is -1, use shape depending on the current mode,
2336071d4279SBram Moolenaar * depending on the current state.
2337071d4279SBram Moolenaar * If "shape" is -2, only update the shape when it's CLINE or STATUS (used
2338071d4279SBram Moolenaar * when the mouse moves off the status or command line).
2339071d4279SBram Moolenaar */
2340071d4279SBram Moolenaar void
update_mouseshape(int shape_idx)23419b57814dSBram Moolenaar update_mouseshape(int shape_idx)
2342071d4279SBram Moolenaar {
2343071d4279SBram Moolenaar int new_mouse_shape;
2344071d4279SBram Moolenaar
234585a2002aSBram Moolenaar // Only works in GUI mode.
23466bb68366SBram Moolenaar if (!gui.in_use || gui.starting)
2347071d4279SBram Moolenaar return;
2348071d4279SBram Moolenaar
234985a2002aSBram Moolenaar // Postpone the updating when more is to come. Speeds up executing of
235085a2002aSBram Moolenaar // mappings.
2351071d4279SBram Moolenaar if (shape_idx == -1 && char_avail())
2352071d4279SBram Moolenaar {
2353071d4279SBram Moolenaar postponed_mouseshape = TRUE;
2354071d4279SBram Moolenaar return;
2355071d4279SBram Moolenaar }
2356071d4279SBram Moolenaar
235785a2002aSBram Moolenaar // When ignoring the mouse don't change shape on the statusline.
235814716817SBram Moolenaar if (*p_mouse == NUL
235914716817SBram Moolenaar && (shape_idx == SHAPE_IDX_CLINE
236014716817SBram Moolenaar || shape_idx == SHAPE_IDX_STATUS
236114716817SBram Moolenaar || shape_idx == SHAPE_IDX_VSEP))
236214716817SBram Moolenaar shape_idx = -2;
236314716817SBram Moolenaar
2364071d4279SBram Moolenaar if (shape_idx == -2
2365071d4279SBram Moolenaar && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape
2366071d4279SBram Moolenaar && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape
2367071d4279SBram Moolenaar && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape)
2368071d4279SBram Moolenaar return;
2369071d4279SBram Moolenaar if (shape_idx < 0)
2370071d4279SBram Moolenaar new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape;
2371071d4279SBram Moolenaar else
2372071d4279SBram Moolenaar new_mouse_shape = shape_table[shape_idx].mshape;
2373071d4279SBram Moolenaar if (new_mouse_shape != old_mouse_shape)
2374071d4279SBram Moolenaar {
2375071d4279SBram Moolenaar mch_set_mouse_shape(new_mouse_shape);
2376071d4279SBram Moolenaar old_mouse_shape = new_mouse_shape;
2377071d4279SBram Moolenaar }
2378071d4279SBram Moolenaar postponed_mouseshape = FALSE;
2379071d4279SBram Moolenaar }
2380071d4279SBram Moolenaar # endif
2381071d4279SBram Moolenaar
238285a2002aSBram Moolenaar #endif // CURSOR_SHAPE
2383071d4279SBram Moolenaar
2384071d4279SBram Moolenaar
2385071d4279SBram Moolenaar /*
2386071d4279SBram Moolenaar * Change directory to "new_dir". If FEAT_SEARCHPATH is defined, search
2387071d4279SBram Moolenaar * 'cdpath' for relative directory names, otherwise just mch_chdir().
2388071d4279SBram Moolenaar */
2389071d4279SBram Moolenaar int
vim_chdir(char_u * new_dir)23909b57814dSBram Moolenaar vim_chdir(char_u *new_dir)
2391071d4279SBram Moolenaar {
2392071d4279SBram Moolenaar #ifndef FEAT_SEARCHPATH
2393071d4279SBram Moolenaar return mch_chdir((char *)new_dir);
2394071d4279SBram Moolenaar #else
2395071d4279SBram Moolenaar char_u *dir_name;
2396071d4279SBram Moolenaar int r;
2397071d4279SBram Moolenaar
2398071d4279SBram Moolenaar dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
2399071d4279SBram Moolenaar FNAME_MESS, curbuf->b_ffname);
2400071d4279SBram Moolenaar if (dir_name == NULL)
2401071d4279SBram Moolenaar return -1;
2402071d4279SBram Moolenaar r = mch_chdir((char *)dir_name);
2403071d4279SBram Moolenaar vim_free(dir_name);
2404071d4279SBram Moolenaar return r;
2405071d4279SBram Moolenaar #endif
2406071d4279SBram Moolenaar }
2407071d4279SBram Moolenaar
2408071d4279SBram Moolenaar /*
2409bbebc857SBram Moolenaar * Get user name from machine-specific function.
2410071d4279SBram Moolenaar * Returns the user name in "buf[len]".
2411bbebc857SBram Moolenaar * Some systems are quite slow in obtaining the user name (Windows NT), thus
2412bbebc857SBram Moolenaar * cache the result.
2413071d4279SBram Moolenaar * Returns OK or FAIL.
2414071d4279SBram Moolenaar */
2415071d4279SBram Moolenaar int
get_user_name(char_u * buf,int len)24169b57814dSBram Moolenaar get_user_name(char_u *buf, int len)
2417071d4279SBram Moolenaar {
2418f461c8e7SBram Moolenaar if (username == NULL)
2419071d4279SBram Moolenaar {
2420071d4279SBram Moolenaar if (mch_get_user_name(buf, len) == FAIL)
2421071d4279SBram Moolenaar return FAIL;
2422f461c8e7SBram Moolenaar username = vim_strsave(buf);
2423071d4279SBram Moolenaar }
2424071d4279SBram Moolenaar else
2425bbebc857SBram Moolenaar vim_strncpy(buf, username, len - 1);
2426071d4279SBram Moolenaar return OK;
2427071d4279SBram Moolenaar }
2428071d4279SBram Moolenaar
2429cbae5802SYegappan Lakshmanan /*
2430cbae5802SYegappan Lakshmanan * Free the memory allocated by get_user_name()
2431cbae5802SYegappan Lakshmanan */
2432cbae5802SYegappan Lakshmanan void
free_username(void)2433cbae5802SYegappan Lakshmanan free_username(void)
2434cbae5802SYegappan Lakshmanan {
2435cbae5802SYegappan Lakshmanan vim_free(username);
2436cbae5802SYegappan Lakshmanan }
2437cbae5802SYegappan Lakshmanan
2438071d4279SBram Moolenaar #ifndef HAVE_QSORT
2439071d4279SBram Moolenaar /*
2440071d4279SBram Moolenaar * Our own qsort(), for systems that don't have it.
2441071d4279SBram Moolenaar * It's simple and slow. From the K&R C book.
2442071d4279SBram Moolenaar */
2443071d4279SBram Moolenaar void
qsort(void * base,size_t elm_count,size_t elm_size,int (* cmp)(const void *,const void *))24449b57814dSBram Moolenaar qsort(
24459b57814dSBram Moolenaar void *base,
24469b57814dSBram Moolenaar size_t elm_count,
24479b57814dSBram Moolenaar size_t elm_size,
24489b57814dSBram Moolenaar int (*cmp)(const void *, const void *))
2449071d4279SBram Moolenaar {
2450071d4279SBram Moolenaar char_u *buf;
2451071d4279SBram Moolenaar char_u *p1;
2452071d4279SBram Moolenaar char_u *p2;
2453071d4279SBram Moolenaar int i, j;
2454071d4279SBram Moolenaar int gap;
2455071d4279SBram Moolenaar
2456964b3746SBram Moolenaar buf = alloc(elm_size);
2457071d4279SBram Moolenaar if (buf == NULL)
2458071d4279SBram Moolenaar return;
2459071d4279SBram Moolenaar
2460071d4279SBram Moolenaar for (gap = elm_count / 2; gap > 0; gap /= 2)
2461071d4279SBram Moolenaar for (i = gap; i < elm_count; ++i)
2462071d4279SBram Moolenaar for (j = i - gap; j >= 0; j -= gap)
2463071d4279SBram Moolenaar {
246485a2002aSBram Moolenaar // Compare the elements.
2465071d4279SBram Moolenaar p1 = (char_u *)base + j * elm_size;
2466071d4279SBram Moolenaar p2 = (char_u *)base + (j + gap) * elm_size;
2467071d4279SBram Moolenaar if ((*cmp)((void *)p1, (void *)p2) <= 0)
2468071d4279SBram Moolenaar break;
246985a2002aSBram Moolenaar // Exchange the elements.
2470071d4279SBram Moolenaar mch_memmove(buf, p1, elm_size);
2471071d4279SBram Moolenaar mch_memmove(p1, p2, elm_size);
2472071d4279SBram Moolenaar mch_memmove(p2, buf, elm_size);
2473071d4279SBram Moolenaar }
2474071d4279SBram Moolenaar
2475071d4279SBram Moolenaar vim_free(buf);
2476071d4279SBram Moolenaar }
2477071d4279SBram Moolenaar #endif
2478071d4279SBram Moolenaar
2479071d4279SBram Moolenaar /*
2480071d4279SBram Moolenaar * The putenv() implementation below comes from the "screen" program.
2481071d4279SBram Moolenaar * Included with permission from Juergen Weigert.
2482071d4279SBram Moolenaar * See pty.c for the copyright notice.
2483071d4279SBram Moolenaar */
2484071d4279SBram Moolenaar
2485071d4279SBram Moolenaar /*
2486071d4279SBram Moolenaar * putenv -- put value into environment
2487071d4279SBram Moolenaar *
2488071d4279SBram Moolenaar * Usage: i = putenv (string)
2489071d4279SBram Moolenaar * int i;
2490071d4279SBram Moolenaar * char *string;
2491071d4279SBram Moolenaar *
2492071d4279SBram Moolenaar * where string is of the form <name>=<value>.
2493071d4279SBram Moolenaar * Putenv returns 0 normally, -1 on error (not enough core for malloc).
2494071d4279SBram Moolenaar *
2495071d4279SBram Moolenaar * Putenv may need to add a new name into the environment, or to
2496071d4279SBram Moolenaar * associate a value longer than the current value with a particular
2497071d4279SBram Moolenaar * name. So, to make life simpler, putenv() copies your entire
2498071d4279SBram Moolenaar * environment into the heap (i.e. malloc()) from the stack
2499071d4279SBram Moolenaar * (i.e. where it resides when your process is initiated) the first
2500071d4279SBram Moolenaar * time you call it.
2501071d4279SBram Moolenaar *
2502071d4279SBram Moolenaar * (history removed, not very interesting. See the "screen" sources.)
2503071d4279SBram Moolenaar */
2504071d4279SBram Moolenaar
2505071d4279SBram Moolenaar #if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
2506071d4279SBram Moolenaar
250785a2002aSBram Moolenaar #define EXTRASIZE 5 // increment to add to env. size
2508071d4279SBram Moolenaar
250985a2002aSBram Moolenaar static int envsize = -1; // current size of environment
251085a2002aSBram Moolenaar extern char **environ; // the global which is your env.
2511071d4279SBram Moolenaar
251285a2002aSBram Moolenaar static int findenv(char *name); // look for a name in the env.
251385a2002aSBram Moolenaar static int newenv(void); // copy env. from stack to heap
251485a2002aSBram Moolenaar static int moreenv(void); // incr. size of env.
2515071d4279SBram Moolenaar
2516071d4279SBram Moolenaar int
putenv(const char * string)25179b57814dSBram Moolenaar putenv(const char *string)
2518071d4279SBram Moolenaar {
2519071d4279SBram Moolenaar int i;
2520071d4279SBram Moolenaar char *p;
2521071d4279SBram Moolenaar
2522071d4279SBram Moolenaar if (envsize < 0)
252385a2002aSBram Moolenaar { // first time putenv called
252485a2002aSBram Moolenaar if (newenv() < 0) // copy env. to heap
2525071d4279SBram Moolenaar return -1;
2526071d4279SBram Moolenaar }
2527071d4279SBram Moolenaar
252885a2002aSBram Moolenaar i = findenv((char *)string); // look for name in environment
2529071d4279SBram Moolenaar
2530071d4279SBram Moolenaar if (i < 0)
253185a2002aSBram Moolenaar { // name must be added
2532071d4279SBram Moolenaar for (i = 0; environ[i]; i++);
2533071d4279SBram Moolenaar if (i >= (envsize - 1))
253485a2002aSBram Moolenaar { // need new slot
2535071d4279SBram Moolenaar if (moreenv() < 0)
2536071d4279SBram Moolenaar return -1;
2537071d4279SBram Moolenaar }
2538c799fe20SBram Moolenaar p = alloc(strlen(string) + 1);
253985a2002aSBram Moolenaar if (p == NULL) // not enough core
2540071d4279SBram Moolenaar return -1;
254185a2002aSBram Moolenaar environ[i + 1] = 0; // new end of env.
2542071d4279SBram Moolenaar }
2543071d4279SBram Moolenaar else
254485a2002aSBram Moolenaar { // name already in env.
2545071d4279SBram Moolenaar p = vim_realloc(environ[i], strlen(string) + 1);
2546071d4279SBram Moolenaar if (p == NULL)
2547071d4279SBram Moolenaar return -1;
2548071d4279SBram Moolenaar }
254985a2002aSBram Moolenaar sprintf(p, "%s", string); // copy into env.
2550071d4279SBram Moolenaar environ[i] = p;
2551071d4279SBram Moolenaar
2552071d4279SBram Moolenaar return 0;
2553071d4279SBram Moolenaar }
2554071d4279SBram Moolenaar
2555071d4279SBram Moolenaar static int
findenv(char * name)25569b57814dSBram Moolenaar findenv(char *name)
2557071d4279SBram Moolenaar {
2558071d4279SBram Moolenaar char *namechar, *envchar;
2559071d4279SBram Moolenaar int i, found;
2560071d4279SBram Moolenaar
2561071d4279SBram Moolenaar found = 0;
2562071d4279SBram Moolenaar for (i = 0; environ[i] && !found; i++)
2563071d4279SBram Moolenaar {
2564071d4279SBram Moolenaar envchar = environ[i];
2565071d4279SBram Moolenaar namechar = name;
2566071d4279SBram Moolenaar while (*namechar && *namechar != '=' && (*namechar == *envchar))
2567071d4279SBram Moolenaar {
2568071d4279SBram Moolenaar namechar++;
2569071d4279SBram Moolenaar envchar++;
2570071d4279SBram Moolenaar }
2571071d4279SBram Moolenaar found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
2572071d4279SBram Moolenaar }
2573071d4279SBram Moolenaar return found ? i - 1 : -1;
2574071d4279SBram Moolenaar }
2575071d4279SBram Moolenaar
2576071d4279SBram Moolenaar static int
newenv(void)25779b57814dSBram Moolenaar newenv(void)
2578071d4279SBram Moolenaar {
2579071d4279SBram Moolenaar char **env, *elem;
2580071d4279SBram Moolenaar int i, esize;
2581071d4279SBram Moolenaar
2582071d4279SBram Moolenaar for (i = 0; environ[i]; i++)
2583071d4279SBram Moolenaar ;
2584d057301bSBram Moolenaar
2585071d4279SBram Moolenaar esize = i + EXTRASIZE + 1;
2586c799fe20SBram Moolenaar env = ALLOC_MULT(char *, esize);
2587071d4279SBram Moolenaar if (env == NULL)
2588071d4279SBram Moolenaar return -1;
2589071d4279SBram Moolenaar
2590071d4279SBram Moolenaar for (i = 0; environ[i]; i++)
2591071d4279SBram Moolenaar {
2592c799fe20SBram Moolenaar elem = alloc(strlen(environ[i]) + 1);
2593071d4279SBram Moolenaar if (elem == NULL)
2594071d4279SBram Moolenaar return -1;
2595071d4279SBram Moolenaar env[i] = elem;
2596071d4279SBram Moolenaar strcpy(elem, environ[i]);
2597071d4279SBram Moolenaar }
2598071d4279SBram Moolenaar
2599071d4279SBram Moolenaar env[i] = 0;
2600071d4279SBram Moolenaar environ = env;
2601071d4279SBram Moolenaar envsize = esize;
2602071d4279SBram Moolenaar return 0;
2603071d4279SBram Moolenaar }
2604071d4279SBram Moolenaar
2605071d4279SBram Moolenaar static int
moreenv(void)26069b57814dSBram Moolenaar moreenv(void)
2607071d4279SBram Moolenaar {
2608071d4279SBram Moolenaar int esize;
2609071d4279SBram Moolenaar char **env;
2610071d4279SBram Moolenaar
2611071d4279SBram Moolenaar esize = envsize + EXTRASIZE;
2612c799fe20SBram Moolenaar env = vim_realloc((char *)environ, esize * sizeof (*env));
2613071d4279SBram Moolenaar if (env == 0)
2614071d4279SBram Moolenaar return -1;
2615071d4279SBram Moolenaar environ = env;
2616071d4279SBram Moolenaar envsize = esize;
2617071d4279SBram Moolenaar return 0;
2618071d4279SBram Moolenaar }
2619071d4279SBram Moolenaar
2620071d4279SBram Moolenaar # ifdef USE_VIMPTY_GETENV
2621613fe7adSBram Moolenaar /*
2622613fe7adSBram Moolenaar * Used for mch_getenv() for Mac.
2623613fe7adSBram Moolenaar */
2624071d4279SBram Moolenaar char_u *
vimpty_getenv(const char_u * string)26259b57814dSBram Moolenaar vimpty_getenv(const char_u *string)
2626071d4279SBram Moolenaar {
2627071d4279SBram Moolenaar int i;
2628071d4279SBram Moolenaar char_u *p;
2629071d4279SBram Moolenaar
2630071d4279SBram Moolenaar if (envsize < 0)
2631071d4279SBram Moolenaar return NULL;
2632071d4279SBram Moolenaar
2633071d4279SBram Moolenaar i = findenv((char *)string);
2634071d4279SBram Moolenaar
2635071d4279SBram Moolenaar if (i < 0)
2636071d4279SBram Moolenaar return NULL;
2637071d4279SBram Moolenaar
2638071d4279SBram Moolenaar p = vim_strchr((char_u *)environ[i], '=');
2639071d4279SBram Moolenaar return (p + 1);
2640071d4279SBram Moolenaar }
2641071d4279SBram Moolenaar # endif
2642071d4279SBram Moolenaar
264385a2002aSBram Moolenaar #endif // !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
2644c4a06d34SBram Moolenaar
2645c4956c8dSBram Moolenaar #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO)
2646c4a06d34SBram Moolenaar /*
2647c4a06d34SBram Moolenaar * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
2648c4a06d34SBram Moolenaar * rights to write into.
2649c4a06d34SBram Moolenaar */
2650c4a06d34SBram Moolenaar int
filewritable(char_u * fname)26519b57814dSBram Moolenaar filewritable(char_u *fname)
2652c4a06d34SBram Moolenaar {
2653c4a06d34SBram Moolenaar int retval = 0;
2654c4a06d34SBram Moolenaar #if defined(UNIX) || defined(VMS)
2655c4a06d34SBram Moolenaar int perm = 0;
2656c4a06d34SBram Moolenaar #endif
2657c4a06d34SBram Moolenaar
2658c4a06d34SBram Moolenaar #if defined(UNIX) || defined(VMS)
2659c4a06d34SBram Moolenaar perm = mch_getperm(fname);
2660c4a06d34SBram Moolenaar #endif
2661c4a06d34SBram Moolenaar if (
26624f97475dSBram Moolenaar # ifdef MSWIN
2663c4a06d34SBram Moolenaar mch_writable(fname) &&
2664c4a06d34SBram Moolenaar # else
2665c4a06d34SBram Moolenaar # if defined(UNIX) || defined(VMS)
2666c4a06d34SBram Moolenaar (perm & 0222) &&
2667c4a06d34SBram Moolenaar # endif
2668c4a06d34SBram Moolenaar # endif
2669c4a06d34SBram Moolenaar mch_access((char *)fname, W_OK) == 0
2670c4a06d34SBram Moolenaar )
2671c4a06d34SBram Moolenaar {
2672c4a06d34SBram Moolenaar ++retval;
2673c4a06d34SBram Moolenaar if (mch_isdir(fname))
2674c4a06d34SBram Moolenaar ++retval;
2675c4a06d34SBram Moolenaar }
2676c4a06d34SBram Moolenaar return retval;
2677c4a06d34SBram Moolenaar }
2678c4a06d34SBram Moolenaar #endif
26796bab4d1fSBram Moolenaar
2680cdf04208SBram Moolenaar #if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
2681cdf04208SBram Moolenaar /*
2682cdf04208SBram Moolenaar * Read 2 bytes from "fd" and turn them into an int, MSB first.
2683e26e0d2bSBram Moolenaar * Returns -1 when encountering EOF.
2684cdf04208SBram Moolenaar */
2685cdf04208SBram Moolenaar int
get2c(FILE * fd)26869b57814dSBram Moolenaar get2c(FILE *fd)
2687cdf04208SBram Moolenaar {
2688e26e0d2bSBram Moolenaar int c, n;
2689cdf04208SBram Moolenaar
2690cdf04208SBram Moolenaar n = getc(fd);
2691e26e0d2bSBram Moolenaar if (n == EOF) return -1;
2692e26e0d2bSBram Moolenaar c = getc(fd);
2693e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2694e26e0d2bSBram Moolenaar return (n << 8) + c;
2695cdf04208SBram Moolenaar }
2696cdf04208SBram Moolenaar
2697cdf04208SBram Moolenaar /*
2698cdf04208SBram Moolenaar * Read 3 bytes from "fd" and turn them into an int, MSB first.
2699e26e0d2bSBram Moolenaar * Returns -1 when encountering EOF.
2700cdf04208SBram Moolenaar */
2701cdf04208SBram Moolenaar int
get3c(FILE * fd)27029b57814dSBram Moolenaar get3c(FILE *fd)
2703cdf04208SBram Moolenaar {
2704e26e0d2bSBram Moolenaar int c, n;
2705cdf04208SBram Moolenaar
2706cdf04208SBram Moolenaar n = getc(fd);
2707e26e0d2bSBram Moolenaar if (n == EOF) return -1;
2708e26e0d2bSBram Moolenaar c = getc(fd);
2709e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2710e26e0d2bSBram Moolenaar n = (n << 8) + c;
2711e26e0d2bSBram Moolenaar c = getc(fd);
2712e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2713e26e0d2bSBram Moolenaar return (n << 8) + c;
2714cdf04208SBram Moolenaar }
2715cdf04208SBram Moolenaar
2716cdf04208SBram Moolenaar /*
2717cdf04208SBram Moolenaar * Read 4 bytes from "fd" and turn them into an int, MSB first.
2718e26e0d2bSBram Moolenaar * Returns -1 when encountering EOF.
2719cdf04208SBram Moolenaar */
2720cdf04208SBram Moolenaar int
get4c(FILE * fd)27219b57814dSBram Moolenaar get4c(FILE *fd)
2722cdf04208SBram Moolenaar {
2723e26e0d2bSBram Moolenaar int c;
272485a2002aSBram Moolenaar // Use unsigned rather than int otherwise result is undefined
272585a2002aSBram Moolenaar // when left-shift sets the MSB.
272695235e64SBram Moolenaar unsigned n;
2727cdf04208SBram Moolenaar
2728e26e0d2bSBram Moolenaar c = getc(fd);
2729e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2730e26e0d2bSBram Moolenaar n = (unsigned)c;
2731e26e0d2bSBram Moolenaar c = getc(fd);
2732e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2733e26e0d2bSBram Moolenaar n = (n << 8) + (unsigned)c;
2734e26e0d2bSBram Moolenaar c = getc(fd);
2735e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2736e26e0d2bSBram Moolenaar n = (n << 8) + (unsigned)c;
2737e26e0d2bSBram Moolenaar c = getc(fd);
2738e26e0d2bSBram Moolenaar if (c == EOF) return -1;
2739e26e0d2bSBram Moolenaar n = (n << 8) + (unsigned)c;
274095235e64SBram Moolenaar return (int)n;
2741cdf04208SBram Moolenaar }
2742cdf04208SBram Moolenaar
2743cdf04208SBram Moolenaar /*
2744cdf04208SBram Moolenaar * Read a string of length "cnt" from "fd" into allocated memory.
2745cdf04208SBram Moolenaar * Returns NULL when out of memory or unable to read that many bytes.
2746cdf04208SBram Moolenaar */
2747cdf04208SBram Moolenaar char_u *
read_string(FILE * fd,int cnt)27489b57814dSBram Moolenaar read_string(FILE *fd, int cnt)
2749cdf04208SBram Moolenaar {
2750cdf04208SBram Moolenaar char_u *str;
2751cdf04208SBram Moolenaar int i;
2752cdf04208SBram Moolenaar int c;
2753cdf04208SBram Moolenaar
275485a2002aSBram Moolenaar // allocate memory
2755964b3746SBram Moolenaar str = alloc(cnt + 1);
2756cdf04208SBram Moolenaar if (str != NULL)
2757cdf04208SBram Moolenaar {
275885a2002aSBram Moolenaar // Read the string. Quit when running into the EOF.
2759cdf04208SBram Moolenaar for (i = 0; i < cnt; ++i)
2760cdf04208SBram Moolenaar {
2761cdf04208SBram Moolenaar c = getc(fd);
2762cdf04208SBram Moolenaar if (c == EOF)
2763cdf04208SBram Moolenaar {
2764cdf04208SBram Moolenaar vim_free(str);
2765cdf04208SBram Moolenaar return NULL;
2766cdf04208SBram Moolenaar }
2767cdf04208SBram Moolenaar str[i] = c;
2768cdf04208SBram Moolenaar }
2769cdf04208SBram Moolenaar str[i] = NUL;
2770cdf04208SBram Moolenaar }
2771cdf04208SBram Moolenaar return str;
2772cdf04208SBram Moolenaar }
2773cdf04208SBram Moolenaar
2774cdf04208SBram Moolenaar /*
2775cdf04208SBram Moolenaar * Write a number to file "fd", MSB first, in "len" bytes.
2776cdf04208SBram Moolenaar */
2777cdf04208SBram Moolenaar int
put_bytes(FILE * fd,long_u nr,int len)27789b57814dSBram Moolenaar put_bytes(FILE *fd, long_u nr, int len)
2779cdf04208SBram Moolenaar {
2780cdf04208SBram Moolenaar int i;
2781cdf04208SBram Moolenaar
2782cdf04208SBram Moolenaar for (i = len - 1; i >= 0; --i)
2783cdf04208SBram Moolenaar if (putc((int)(nr >> (i * 8)), fd) == EOF)
2784cdf04208SBram Moolenaar return FAIL;
2785cdf04208SBram Moolenaar return OK;
2786cdf04208SBram Moolenaar }
2787cdf04208SBram Moolenaar
2788cdf04208SBram Moolenaar #endif
278910b7b39bSBram Moolenaar
279085a2002aSBram Moolenaar #ifndef PROTO // proto is defined in vim.h
279151628229SBram Moolenaar # ifdef ELAPSED_TIMEVAL
2792833eb1d7SBram Moolenaar /*
2793833eb1d7SBram Moolenaar * Return time in msec since "start_tv".
2794833eb1d7SBram Moolenaar */
2795833eb1d7SBram Moolenaar long
elapsed(struct timeval * start_tv)2796833eb1d7SBram Moolenaar elapsed(struct timeval *start_tv)
2797833eb1d7SBram Moolenaar {
2798833eb1d7SBram Moolenaar struct timeval now_tv;
2799833eb1d7SBram Moolenaar
2800833eb1d7SBram Moolenaar gettimeofday(&now_tv, NULL);
2801833eb1d7SBram Moolenaar return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
2802833eb1d7SBram Moolenaar + (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
2803833eb1d7SBram Moolenaar }
2804833eb1d7SBram Moolenaar # endif
2805833eb1d7SBram Moolenaar
2806833eb1d7SBram Moolenaar # ifdef ELAPSED_TICKCOUNT
2807833eb1d7SBram Moolenaar /*
2808833eb1d7SBram Moolenaar * Return time in msec since "start_tick".
2809833eb1d7SBram Moolenaar */
2810833eb1d7SBram Moolenaar long
elapsed(DWORD start_tick)2811833eb1d7SBram Moolenaar elapsed(DWORD start_tick)
2812833eb1d7SBram Moolenaar {
2813833eb1d7SBram Moolenaar DWORD now = GetTickCount();
2814833eb1d7SBram Moolenaar
2815833eb1d7SBram Moolenaar return (long)now - (long)start_tick;
2816833eb1d7SBram Moolenaar }
2817833eb1d7SBram Moolenaar # endif
281851628229SBram Moolenaar #endif
281920608920SBram Moolenaar
282020608920SBram Moolenaar #if defined(FEAT_JOB_CHANNEL) \
282120608920SBram Moolenaar || (defined(UNIX) && (!defined(USE_SYSTEM) \
282220608920SBram Moolenaar || (defined(FEAT_GUI) && defined(FEAT_TERMINAL)))) \
282320608920SBram Moolenaar || defined(PROTO)
282420608920SBram Moolenaar /*
282520608920SBram Moolenaar * Parse "cmd" and put the white-separated parts in "argv".
282620608920SBram Moolenaar * "argv" is an allocated array with "argc" entries and room for 4 more.
282720608920SBram Moolenaar * Returns FAIL when out of memory.
282820608920SBram Moolenaar */
282920608920SBram Moolenaar int
mch_parse_cmd(char_u * cmd,int use_shcf,char *** argv,int * argc)283020608920SBram Moolenaar mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc)
283120608920SBram Moolenaar {
283220608920SBram Moolenaar int i;
283320608920SBram Moolenaar char_u *p, *d;
283420608920SBram Moolenaar int inquote;
283520608920SBram Moolenaar
283620608920SBram Moolenaar /*
283720608920SBram Moolenaar * Do this loop twice:
283820608920SBram Moolenaar * 1: find number of arguments
283920608920SBram Moolenaar * 2: separate them and build argv[]
284020608920SBram Moolenaar */
28417851b1caSBram Moolenaar for (i = 1; i <= 2; ++i)
284220608920SBram Moolenaar {
284320608920SBram Moolenaar p = skipwhite(cmd);
284420608920SBram Moolenaar inquote = FALSE;
284520608920SBram Moolenaar *argc = 0;
28467851b1caSBram Moolenaar while (*p != NUL)
284720608920SBram Moolenaar {
28487851b1caSBram Moolenaar if (i == 2)
284920608920SBram Moolenaar (*argv)[*argc] = (char *)p;
285020608920SBram Moolenaar ++*argc;
285120608920SBram Moolenaar d = p;
285220608920SBram Moolenaar while (*p != NUL && (inquote || (*p != ' ' && *p != TAB)))
285320608920SBram Moolenaar {
285420608920SBram Moolenaar if (p[0] == '"')
28551df2fa47SBram Moolenaar // quotes surrounding an argument and are dropped
285620608920SBram Moolenaar inquote = !inquote;
285720608920SBram Moolenaar else
285820608920SBram Moolenaar {
28591df2fa47SBram Moolenaar if (rem_backslash(p))
286020608920SBram Moolenaar {
28611df2fa47SBram Moolenaar // First pass: skip over "\ " and "\"".
28621df2fa47SBram Moolenaar // Second pass: Remove the backslash.
286320608920SBram Moolenaar ++p;
286420608920SBram Moolenaar }
28657851b1caSBram Moolenaar if (i == 2)
286620608920SBram Moolenaar *d++ = *p;
286720608920SBram Moolenaar }
286820608920SBram Moolenaar ++p;
286920608920SBram Moolenaar }
287020608920SBram Moolenaar if (*p == NUL)
287120608920SBram Moolenaar {
28727851b1caSBram Moolenaar if (i == 2)
287320608920SBram Moolenaar *d++ = NUL;
287420608920SBram Moolenaar break;
287520608920SBram Moolenaar }
28767851b1caSBram Moolenaar if (i == 2)
287720608920SBram Moolenaar *d++ = NUL;
287820608920SBram Moolenaar p = skipwhite(p + 1);
287920608920SBram Moolenaar }
288020608920SBram Moolenaar if (*argv == NULL)
288120608920SBram Moolenaar {
288220608920SBram Moolenaar if (use_shcf)
288320608920SBram Moolenaar {
288485a2002aSBram Moolenaar // Account for possible multiple args in p_shcf.
288520608920SBram Moolenaar p = p_shcf;
288620608920SBram Moolenaar for (;;)
288720608920SBram Moolenaar {
288820608920SBram Moolenaar p = skiptowhite(p);
288920608920SBram Moolenaar if (*p == NUL)
289020608920SBram Moolenaar break;
289120608920SBram Moolenaar ++*argc;
289220608920SBram Moolenaar p = skipwhite(p);
289320608920SBram Moolenaar }
289420608920SBram Moolenaar }
289520608920SBram Moolenaar
2896c799fe20SBram Moolenaar *argv = ALLOC_MULT(char *, *argc + 4);
289785a2002aSBram Moolenaar if (*argv == NULL) // out of memory
289820608920SBram Moolenaar return FAIL;
289920608920SBram Moolenaar }
290020608920SBram Moolenaar }
290120608920SBram Moolenaar return OK;
290220608920SBram Moolenaar }
2903ebe74b73SBram Moolenaar
2904ebe74b73SBram Moolenaar # if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
2905ebe74b73SBram Moolenaar /*
2906ebe74b73SBram Moolenaar * Build "argv[argc]" from the string "cmd".
2907ebe74b73SBram Moolenaar * "argv[argc]" is set to NULL;
2908ebe74b73SBram Moolenaar * Return FAIL when out of memory.
2909ebe74b73SBram Moolenaar */
2910ebe74b73SBram Moolenaar int
build_argv_from_string(char_u * cmd,char *** argv,int * argc)2911ebe74b73SBram Moolenaar build_argv_from_string(char_u *cmd, char ***argv, int *argc)
2912ebe74b73SBram Moolenaar {
2913ebe74b73SBram Moolenaar char_u *cmd_copy;
2914ebe74b73SBram Moolenaar int i;
2915ebe74b73SBram Moolenaar
291685a2002aSBram Moolenaar // Make a copy, parsing will modify "cmd".
2917ebe74b73SBram Moolenaar cmd_copy = vim_strsave(cmd);
2918ebe74b73SBram Moolenaar if (cmd_copy == NULL
2919ebe74b73SBram Moolenaar || mch_parse_cmd(cmd_copy, FALSE, argv, argc) == FAIL)
2920ebe74b73SBram Moolenaar {
2921ebe74b73SBram Moolenaar vim_free(cmd_copy);
2922ebe74b73SBram Moolenaar return FAIL;
2923ebe74b73SBram Moolenaar }
2924ebe74b73SBram Moolenaar for (i = 0; i < *argc; i++)
2925ebe74b73SBram Moolenaar (*argv)[i] = (char *)vim_strsave((char_u *)(*argv)[i]);
2926ebe74b73SBram Moolenaar (*argv)[*argc] = NULL;
2927ebe74b73SBram Moolenaar vim_free(cmd_copy);
2928ebe74b73SBram Moolenaar return OK;
2929ebe74b73SBram Moolenaar }
2930ebe74b73SBram Moolenaar
2931ebe74b73SBram Moolenaar /*
2932ebe74b73SBram Moolenaar * Build "argv[argc]" from the list "l".
2933ebe74b73SBram Moolenaar * "argv[argc]" is set to NULL;
2934ebe74b73SBram Moolenaar * Return FAIL when out of memory.
2935ebe74b73SBram Moolenaar */
2936ebe74b73SBram Moolenaar int
build_argv_from_list(list_T * l,char *** argv,int * argc)2937ebe74b73SBram Moolenaar build_argv_from_list(list_T *l, char ***argv, int *argc)
2938ebe74b73SBram Moolenaar {
2939ebe74b73SBram Moolenaar listitem_T *li;
2940ebe74b73SBram Moolenaar char_u *s;
2941ebe74b73SBram Moolenaar
294285a2002aSBram Moolenaar // Pass argv[] to mch_call_shell().
2943c799fe20SBram Moolenaar *argv = ALLOC_MULT(char *, l->lv_len + 1);
2944ebe74b73SBram Moolenaar if (*argv == NULL)
2945ebe74b73SBram Moolenaar return FAIL;
2946ebe74b73SBram Moolenaar *argc = 0;
2947aeea7215SBram Moolenaar FOR_ALL_LIST_ITEMS(l, li)
2948ebe74b73SBram Moolenaar {
2949d155d7a8SBram Moolenaar s = tv_get_string_chk(&li->li_tv);
2950ebe74b73SBram Moolenaar if (s == NULL)
2951ebe74b73SBram Moolenaar {
2952ebe74b73SBram Moolenaar int i;
2953ebe74b73SBram Moolenaar
2954ebe74b73SBram Moolenaar for (i = 0; i < *argc; ++i)
2955df195607SBram Moolenaar VIM_CLEAR((*argv)[i]);
2956*7c25a7c0SBram Moolenaar (*argv)[0] = NULL;
2957ebe74b73SBram Moolenaar return FAIL;
2958ebe74b73SBram Moolenaar }
2959ebe74b73SBram Moolenaar (*argv)[*argc] = (char *)vim_strsave(s);
2960ebe74b73SBram Moolenaar *argc += 1;
2961ebe74b73SBram Moolenaar }
2962ebe74b73SBram Moolenaar (*argv)[*argc] = NULL;
2963ebe74b73SBram Moolenaar return OK;
2964ebe74b73SBram Moolenaar }
2965ebe74b73SBram Moolenaar # endif
296620608920SBram Moolenaar #endif
296757da6981SBram Moolenaar
296857da6981SBram Moolenaar /*
296957da6981SBram Moolenaar * Change the behavior of vterm.
297057da6981SBram Moolenaar * 0: As usual.
297157da6981SBram Moolenaar * 1: Windows 10 version 1809
297257da6981SBram Moolenaar * The bug causes unstable handling of ambiguous width character.
297336e7a823SBram Moolenaar * 2: Windows 10 version 1903 & 1909
297457da6981SBram Moolenaar * Use the wrong result because each result is different.
297557da6981SBram Moolenaar * 3: Windows 10 insider preview (current latest logic)
297657da6981SBram Moolenaar */
297757da6981SBram Moolenaar int
get_special_pty_type(void)297857da6981SBram Moolenaar get_special_pty_type(void)
297957da6981SBram Moolenaar {
298057da6981SBram Moolenaar #ifdef MSWIN
298157da6981SBram Moolenaar return get_conpty_type();
298257da6981SBram Moolenaar #else
298357da6981SBram Moolenaar return 0;
298457da6981SBram Moolenaar #endif
298557da6981SBram Moolenaar }
2986