1 |
|
|
/* $OpenBSD: key.c,v 1.19 2017/04/18 01:45:35 deraadt Exp $ */ |
2 |
|
|
|
3 |
|
|
/*- |
4 |
|
|
* Copyright (c) 1991, 1993, 1994 |
5 |
|
|
* The Regents of the University of California. All rights reserved. |
6 |
|
|
* Copyright (c) 1991, 1993, 1994, 1995, 1996 |
7 |
|
|
* Keith Bostic. All rights reserved. |
8 |
|
|
* |
9 |
|
|
* See the LICENSE file for redistribution information. |
10 |
|
|
*/ |
11 |
|
|
|
12 |
|
|
#include "config.h" |
13 |
|
|
|
14 |
|
|
#include <sys/queue.h> |
15 |
|
|
#include <sys/time.h> |
16 |
|
|
|
17 |
|
|
#include <bitstring.h> |
18 |
|
|
#include <ctype.h> |
19 |
|
|
#include <errno.h> |
20 |
|
|
#include <limits.h> |
21 |
|
|
#include <locale.h> |
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
#include <unistd.h> |
26 |
|
|
|
27 |
|
|
#include "common.h" |
28 |
|
|
#include "../vi/vi.h" |
29 |
|
|
|
30 |
|
|
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) |
31 |
|
|
|
32 |
|
|
static int v_event_append(SCR *, EVENT *); |
33 |
|
|
static int v_event_grow(SCR *, int); |
34 |
|
|
static int v_key_cmp(const void *, const void *); |
35 |
|
|
static void v_keyval(SCR *, int, scr_keyval_t); |
36 |
|
|
static void v_sync(SCR *, int); |
37 |
|
|
|
38 |
|
|
/* |
39 |
|
|
* !!! |
40 |
|
|
* Historic vi always used: |
41 |
|
|
* |
42 |
|
|
* ^D: autoindent deletion |
43 |
|
|
* ^H: last character deletion |
44 |
|
|
* ^W: last word deletion |
45 |
|
|
* ^Q: quote the next character (if not used in flow control). |
46 |
|
|
* ^V: quote the next character |
47 |
|
|
* |
48 |
|
|
* regardless of the user's choices for these characters. The user's erase |
49 |
|
|
* and kill characters worked in addition to these characters. Nvi wires |
50 |
|
|
* down the above characters, but in addition permits the VEOF, VERASE, VKILL |
51 |
|
|
* and VWERASE characters described by the user's termios structure. |
52 |
|
|
* |
53 |
|
|
* Ex was not consistent with this scheme, as it historically ran in tty |
54 |
|
|
* cooked mode. This meant that the scroll command and autoindent erase |
55 |
|
|
* characters were mapped to the user's EOF character, and the character |
56 |
|
|
* and word deletion characters were the user's tty character and word |
57 |
|
|
* deletion characters. This implementation makes it all consistent, as |
58 |
|
|
* described above for vi. |
59 |
|
|
* |
60 |
|
|
* !!! |
61 |
|
|
* This means that all screens share a special key set. |
62 |
|
|
*/ |
63 |
|
|
KEYLIST keylist[] = { |
64 |
|
|
{K_BACKSLASH, '\\'}, /* \ */ |
65 |
|
|
{K_CARAT, '^'}, /* ^ */ |
66 |
|
|
{K_CNTRLD, '\004'}, /* ^D */ |
67 |
|
|
{K_CNTRLR, '\022'}, /* ^R */ |
68 |
|
|
{K_CNTRLT, '\024'}, /* ^T */ |
69 |
|
|
{K_CNTRLZ, '\032'}, /* ^Z */ |
70 |
|
|
{K_COLON, ':'}, /* : */ |
71 |
|
|
{K_CR, '\r'}, /* \r */ |
72 |
|
|
{K_ESCAPE, '\033'}, /* ^[ */ |
73 |
|
|
{K_FORMFEED, '\f'}, /* \f */ |
74 |
|
|
{K_HEXCHAR, '\030'}, /* ^X */ |
75 |
|
|
{K_NL, '\n'}, /* \n */ |
76 |
|
|
{K_RIGHTBRACE, '}'}, /* } */ |
77 |
|
|
{K_RIGHTPAREN, ')'}, /* ) */ |
78 |
|
|
{K_TAB, '\t'}, /* \t */ |
79 |
|
|
{K_VERASE, '\b'}, /* \b */ |
80 |
|
|
{K_VKILL, '\025'}, /* ^U */ |
81 |
|
|
{K_VLNEXT, '\021'}, /* ^Q */ |
82 |
|
|
{K_VLNEXT, '\026'}, /* ^V */ |
83 |
|
|
{K_VWERASE, '\027'}, /* ^W */ |
84 |
|
|
{K_ZERO, '0'}, /* 0 */ |
85 |
|
|
|
86 |
|
|
#define ADDITIONAL_CHARACTERS 4 |
87 |
|
|
{K_NOTUSED, 0}, /* VEOF, VERASE, VKILL, VWERASE */ |
88 |
|
|
{K_NOTUSED, 0}, |
89 |
|
|
{K_NOTUSED, 0}, |
90 |
|
|
{K_NOTUSED, 0}, |
91 |
|
|
}; |
92 |
|
|
static int nkeylist = |
93 |
|
|
(sizeof(keylist) / sizeof(keylist[0])) - ADDITIONAL_CHARACTERS; |
94 |
|
|
|
95 |
|
|
/* |
96 |
|
|
* v_key_init -- |
97 |
|
|
* Initialize the special key lookup table. |
98 |
|
|
* |
99 |
|
|
* PUBLIC: int v_key_init(SCR *); |
100 |
|
|
*/ |
101 |
|
|
int |
102 |
|
|
v_key_init(SCR *sp) |
103 |
|
|
{ |
104 |
|
|
u_int ch; |
105 |
|
|
GS *gp; |
106 |
|
|
KEYLIST *kp; |
107 |
|
|
int cnt; |
108 |
|
|
|
109 |
|
|
gp = sp->gp; |
110 |
|
|
|
111 |
|
|
/* |
112 |
|
|
* XXX |
113 |
|
|
* 8-bit only, for now. Recompilation should get you any 8-bit |
114 |
|
|
* character set, as long as nul isn't a character. |
115 |
|
|
*/ |
116 |
|
|
(void)setlocale(LC_ALL, ""); |
117 |
|
|
v_key_ilookup(sp); |
118 |
|
|
|
119 |
|
|
v_keyval(sp, K_CNTRLD, KEY_VEOF); |
120 |
|
|
v_keyval(sp, K_VERASE, KEY_VERASE); |
121 |
|
|
v_keyval(sp, K_VKILL, KEY_VKILL); |
122 |
|
|
v_keyval(sp, K_VWERASE, KEY_VWERASE); |
123 |
|
|
|
124 |
|
|
/* Sort the special key list. */ |
125 |
|
|
qsort(keylist, nkeylist, sizeof(keylist[0]), v_key_cmp); |
126 |
|
|
|
127 |
|
|
/* Initialize the fast lookup table. */ |
128 |
|
|
for (gp->max_special = 0, kp = keylist, cnt = nkeylist; cnt--; ++kp) { |
129 |
|
|
if (gp->max_special < kp->value) |
130 |
|
|
gp->max_special = kp->value; |
131 |
|
|
if (kp->ch <= MAX_FAST_KEY) |
132 |
|
|
gp->special_key[kp->ch] = kp->value; |
133 |
|
|
} |
134 |
|
|
|
135 |
|
|
/* Find a non-printable character to use as a message separator. */ |
136 |
|
|
for (ch = 1; ch <= MAX_CHAR_T; ++ch) |
137 |
|
|
if (!isprint(ch)) { |
138 |
|
|
gp->noprint = ch; |
139 |
|
|
break; |
140 |
|
|
} |
141 |
|
|
if (ch != gp->noprint) { |
142 |
|
|
msgq(sp, M_ERR, "No non-printable character found"); |
143 |
|
|
return (1); |
144 |
|
|
} |
145 |
|
|
return (0); |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
/* |
149 |
|
|
* v_keyval -- |
150 |
|
|
* Set key values. |
151 |
|
|
* |
152 |
|
|
* We've left some open slots in the keylist table, and if these values exist, |
153 |
|
|
* we put them into place. Note, they may reset (or duplicate) values already |
154 |
|
|
* in the table, so we check for that first. |
155 |
|
|
*/ |
156 |
|
|
static void |
157 |
|
|
v_keyval(SCR *sp, int val, scr_keyval_t name) |
158 |
|
|
{ |
159 |
|
|
KEYLIST *kp; |
160 |
|
|
CHAR_T ch; |
161 |
|
|
int dne; |
162 |
|
|
|
163 |
|
|
/* Get the key's value from the screen. */ |
164 |
|
|
if (sp->gp->scr_keyval(sp, name, &ch, &dne)) |
165 |
|
|
return; |
166 |
|
|
if (dne) |
167 |
|
|
return; |
168 |
|
|
|
169 |
|
|
/* Check for duplication. */ |
170 |
|
|
for (kp = keylist; kp->value != K_NOTUSED; ++kp) |
171 |
|
|
if (kp->ch == ch) { |
172 |
|
|
kp->value = val; |
173 |
|
|
return; |
174 |
|
|
} |
175 |
|
|
|
176 |
|
|
/* Add a new entry. */ |
177 |
|
|
if (kp->value == K_NOTUSED) { |
178 |
|
|
keylist[nkeylist].ch = ch; |
179 |
|
|
keylist[nkeylist].value = val; |
180 |
|
|
++nkeylist; |
181 |
|
|
} |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
/* |
185 |
|
|
* v_key_ilookup -- |
186 |
|
|
* Build the fast-lookup key display array. |
187 |
|
|
* |
188 |
|
|
* PUBLIC: void v_key_ilookup(SCR *); |
189 |
|
|
*/ |
190 |
|
|
void |
191 |
|
|
v_key_ilookup(SCR *sp) |
192 |
|
|
{ |
193 |
|
|
CHAR_T ch, *p, *t; |
194 |
|
|
GS *gp; |
195 |
|
|
size_t len; |
196 |
|
|
|
197 |
|
|
for (gp = sp->gp, ch = 0; ch <= MAX_FAST_KEY; ++ch) |
198 |
|
|
for (p = gp->cname[ch].name, t = v_key_name(sp, ch), |
199 |
|
|
len = gp->cname[ch].len = sp->clen; len--;) |
200 |
|
|
*p++ = *t++; |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
/* |
204 |
|
|
* v_key_len -- |
205 |
|
|
* Return the length of the string that will display the key. |
206 |
|
|
* This routine is the backup for the KEY_LEN() macro. |
207 |
|
|
* |
208 |
|
|
* PUBLIC: size_t v_key_len(SCR *, CHAR_T); |
209 |
|
|
*/ |
210 |
|
|
size_t |
211 |
|
|
v_key_len(SCR *sp, CHAR_T ch) |
212 |
|
|
{ |
213 |
|
|
(void)v_key_name(sp, ch); |
214 |
|
|
return (sp->clen); |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
/* |
218 |
|
|
* v_key_name -- |
219 |
|
|
* Return the string that will display the key. This routine |
220 |
|
|
* is the backup for the KEY_NAME() macro. |
221 |
|
|
* |
222 |
|
|
* PUBLIC: CHAR_T *v_key_name(SCR *, CHAR_T); |
223 |
|
|
*/ |
224 |
|
|
CHAR_T * |
225 |
|
|
v_key_name(SCR *sp, CHAR_T ch) |
226 |
|
|
{ |
227 |
|
|
static const CHAR_T hexdigit[] = "0123456789abcdef"; |
228 |
|
|
static const CHAR_T octdigit[] = "01234567"; |
229 |
|
|
CHAR_T *chp, mask; |
230 |
|
|
size_t len; |
231 |
|
|
int cnt, shift; |
232 |
|
|
|
233 |
|
|
/* See if the character was explicitly declared printable or not. */ |
234 |
|
|
if ((chp = O_STR(sp, O_PRINT)) != NULL) |
235 |
|
|
for (; *chp != '\0'; ++chp) |
236 |
|
|
if (*chp == ch) |
237 |
|
|
goto pr; |
238 |
|
|
if ((chp = O_STR(sp, O_NOPRINT)) != NULL) |
239 |
|
|
for (; *chp != '\0'; ++chp) |
240 |
|
|
if (*chp == ch) |
241 |
|
|
goto nopr; |
242 |
|
|
|
243 |
|
|
/* |
244 |
|
|
* Historical (ARPA standard) mappings. Printable characters are left |
245 |
|
|
* alone. Control characters less than 0x20 are represented as '^' |
246 |
|
|
* followed by the character offset from the '@' character in the ASCII |
247 |
|
|
* character set. Del (0x7f) is represented as '^' followed by '?'. |
248 |
|
|
* |
249 |
|
|
* XXX |
250 |
|
|
* The following code depends on the current locale being identical to |
251 |
|
|
* the ASCII map from 0x40 to 0x5f (since 0x1f + 0x40 == 0x5f). I'm |
252 |
|
|
* told that this is a reasonable assumption... |
253 |
|
|
* |
254 |
|
|
* XXX |
255 |
|
|
* This code will only work with CHAR_T's that are multiples of 8-bit |
256 |
|
|
* bytes. |
257 |
|
|
* |
258 |
|
|
* XXX |
259 |
|
|
* NB: There's an assumption here that all printable characters take |
260 |
|
|
* up a single column on the screen. This is not always correct. |
261 |
|
|
*/ |
262 |
|
|
if (isprint(ch)) { |
263 |
|
|
pr: sp->cname[0] = ch; |
264 |
|
|
len = 1; |
265 |
|
|
goto done; |
266 |
|
|
} |
267 |
|
|
nopr: if (iscntrl(ch) && (ch < 0x20 || ch == 0x7f)) { |
268 |
|
|
sp->cname[0] = '^'; |
269 |
|
|
sp->cname[1] = ch == 0x7f ? '?' : '@' + ch; |
270 |
|
|
len = 2; |
271 |
|
|
} else if (O_ISSET(sp, O_OCTAL)) { |
272 |
|
|
#define BITS (sizeof(CHAR_T) * 8) |
273 |
|
|
#define SHIFT (BITS - BITS % 3) |
274 |
|
|
#define TOPMASK (BITS % 3 == 2 ? 3 : 1) << (BITS - BITS % 3) |
275 |
|
|
sp->cname[0] = '\\'; |
276 |
|
|
sp->cname[1] = octdigit[(ch & TOPMASK) >> SHIFT]; |
277 |
|
|
shift = SHIFT - 3; |
278 |
|
|
for (len = 2, mask = 7 << (SHIFT - 3), |
279 |
|
|
cnt = BITS / 3; cnt-- > 0; mask >>= 3, shift -= 3) |
280 |
|
|
sp->cname[len++] = octdigit[(ch & mask) >> shift]; |
281 |
|
|
} else { |
282 |
|
|
sp->cname[0] = '\\'; |
283 |
|
|
sp->cname[1] = 'x'; |
284 |
|
|
for (len = 2, chp = (u_int8_t *)&ch, |
285 |
|
|
cnt = sizeof(CHAR_T); cnt-- > 0; ++chp) { |
286 |
|
|
sp->cname[len++] = hexdigit[(*chp & 0xf0) >> 4]; |
287 |
|
|
sp->cname[len++] = hexdigit[*chp & 0x0f]; |
288 |
|
|
} |
289 |
|
|
} |
290 |
|
|
done: sp->cname[sp->clen = len] = '\0'; |
291 |
|
|
return (sp->cname); |
292 |
|
|
} |
293 |
|
|
|
294 |
|
|
/* |
295 |
|
|
* v_key_val -- |
296 |
|
|
* Fill in the value for a key. This routine is the backup |
297 |
|
|
* for the KEY_VAL() macro. |
298 |
|
|
* |
299 |
|
|
* PUBLIC: int v_key_val(SCR *, CHAR_T); |
300 |
|
|
*/ |
301 |
|
|
int |
302 |
|
|
v_key_val(SCR *sp, CHAR_T ch) |
303 |
|
|
{ |
304 |
|
|
KEYLIST k, *kp; |
305 |
|
|
|
306 |
|
|
k.ch = ch; |
307 |
|
|
kp = bsearch(&k, keylist, nkeylist, sizeof(keylist[0]), v_key_cmp); |
308 |
|
|
return (kp == NULL ? K_NOTUSED : kp->value); |
309 |
|
|
} |
310 |
|
|
|
311 |
|
|
/* |
312 |
|
|
* v_event_push -- |
313 |
|
|
* Push events/keys onto the front of the buffer. |
314 |
|
|
* |
315 |
|
|
* There is a single input buffer in ex/vi. Characters are put onto the |
316 |
|
|
* end of the buffer by the terminal input routines, and pushed onto the |
317 |
|
|
* front of the buffer by various other functions in ex/vi. Each key has |
318 |
|
|
* an associated flag value, which indicates if it has already been quoted, |
319 |
|
|
* and if it is the result of a mapping or an abbreviation. |
320 |
|
|
* |
321 |
|
|
* PUBLIC: int v_event_push(SCR *, EVENT *, CHAR_T *, size_t, u_int); |
322 |
|
|
*/ |
323 |
|
|
int |
324 |
|
|
v_event_push(SCR *sp, EVENT *p_evp, CHAR_T *p_s, size_t nitems, u_int flags) |
325 |
|
|
{ |
326 |
|
|
EVENT *evp; |
327 |
|
|
GS *gp; |
328 |
|
|
size_t total; |
329 |
|
|
|
330 |
|
|
/* If we have room, stuff the items into the buffer. */ |
331 |
|
|
gp = sp->gp; |
332 |
|
|
if (nitems <= gp->i_next || |
333 |
|
|
(gp->i_event != NULL && gp->i_cnt == 0 && nitems <= gp->i_nelem)) { |
334 |
|
|
if (gp->i_cnt != 0) |
335 |
|
|
gp->i_next -= nitems; |
336 |
|
|
goto copy; |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
/* |
340 |
|
|
* If there are currently items in the queue, shift them up, |
341 |
|
|
* leaving some extra room. Get enough space plus a little |
342 |
|
|
* extra. |
343 |
|
|
*/ |
344 |
|
|
#define TERM_PUSH_SHIFT 30 |
345 |
|
|
total = gp->i_cnt + gp->i_next + nitems + TERM_PUSH_SHIFT; |
346 |
|
|
if (total >= gp->i_nelem && v_event_grow(sp, MAXIMUM(total, 64))) |
347 |
|
|
return (1); |
348 |
|
|
if (gp->i_cnt) |
349 |
|
|
MEMMOVE(gp->i_event + TERM_PUSH_SHIFT + nitems, |
350 |
|
|
gp->i_event + gp->i_next, gp->i_cnt); |
351 |
|
|
gp->i_next = TERM_PUSH_SHIFT; |
352 |
|
|
|
353 |
|
|
/* Put the new items into the queue. */ |
354 |
|
|
copy: gp->i_cnt += nitems; |
355 |
|
|
for (evp = gp->i_event + gp->i_next; nitems--; ++evp) { |
356 |
|
|
if (p_evp != NULL) |
357 |
|
|
*evp = *p_evp++; |
358 |
|
|
else { |
359 |
|
|
evp->e_event = E_CHARACTER; |
360 |
|
|
evp->e_c = *p_s++; |
361 |
|
|
evp->e_value = KEY_VAL(sp, evp->e_c); |
362 |
|
|
F_INIT(&evp->e_ch, flags); |
363 |
|
|
} |
364 |
|
|
} |
365 |
|
|
return (0); |
366 |
|
|
} |
367 |
|
|
|
368 |
|
|
/* |
369 |
|
|
* v_event_append -- |
370 |
|
|
* Append events onto the tail of the buffer. |
371 |
|
|
*/ |
372 |
|
|
static int |
373 |
|
|
v_event_append(SCR *sp, EVENT *argp) |
374 |
|
|
{ |
375 |
|
|
CHAR_T *s; /* Characters. */ |
376 |
|
|
EVENT *evp; |
377 |
|
|
GS *gp; |
378 |
|
|
size_t nevents; /* Number of events. */ |
379 |
|
|
|
380 |
|
|
/* Grow the buffer as necessary. */ |
381 |
|
|
nevents = argp->e_event == E_STRING ? argp->e_len : 1; |
382 |
|
|
gp = sp->gp; |
383 |
|
|
if (gp->i_event == NULL || |
384 |
|
|
nevents > gp->i_nelem - (gp->i_next + gp->i_cnt)) |
385 |
|
|
v_event_grow(sp, MAXIMUM(nevents, 64)); |
386 |
|
|
evp = gp->i_event + gp->i_next + gp->i_cnt; |
387 |
|
|
gp->i_cnt += nevents; |
388 |
|
|
|
389 |
|
|
/* Transform strings of characters into single events. */ |
390 |
|
|
if (argp->e_event == E_STRING) |
391 |
|
|
for (s = argp->e_csp; nevents--; ++evp) { |
392 |
|
|
evp->e_event = E_CHARACTER; |
393 |
|
|
evp->e_c = *s++; |
394 |
|
|
evp->e_value = KEY_VAL(sp, evp->e_c); |
395 |
|
|
evp->e_flags = 0; |
396 |
|
|
} |
397 |
|
|
else |
398 |
|
|
*evp = *argp; |
399 |
|
|
return (0); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
/* Remove events from the queue. */ |
403 |
|
|
#define QREM(len) { \ |
404 |
|
|
if ((gp->i_cnt -= (len)) == 0) \ |
405 |
|
|
gp->i_next = 0; \ |
406 |
|
|
else \ |
407 |
|
|
gp->i_next += (len); \ |
408 |
|
|
} |
409 |
|
|
|
410 |
|
|
/* |
411 |
|
|
* v_event_get -- |
412 |
|
|
* Return the next event. |
413 |
|
|
* |
414 |
|
|
* !!! |
415 |
|
|
* The flag EC_NODIGIT probably needs some explanation. First, the idea of |
416 |
|
|
* mapping keys is that one or more keystrokes act like a function key. |
417 |
|
|
* What's going on is that vi is reading a number, and the character following |
418 |
|
|
* the number may or may not be mapped (EC_MAPCOMMAND). For example, if the |
419 |
|
|
* user is entering the z command, a valid command is "z40+", and we don't want |
420 |
|
|
* to map the '+', i.e. if '+' is mapped to "xxx", we don't want to change it |
421 |
|
|
* into "z40xxx". However, if the user enters "35x", we want to put all of the |
422 |
|
|
* characters through the mapping code. |
423 |
|
|
* |
424 |
|
|
* Historical practice is a bit muddled here. (Surprise!) It always permitted |
425 |
|
|
* mapping digits as long as they weren't the first character of the map, e.g. |
426 |
|
|
* ":map ^A1 xxx" was okay. It also permitted the mapping of the digits 1-9 |
427 |
|
|
* (the digit 0 was a special case as it doesn't indicate the start of a count) |
428 |
|
|
* as the first character of the map, but then ignored those mappings. While |
429 |
|
|
* it's probably stupid to map digits, vi isn't your mother. |
430 |
|
|
* |
431 |
|
|
* The way this works is that the EC_MAPNODIGIT causes term_key to return the |
432 |
|
|
* end-of-digit without "looking" at the next character, i.e. leaving it as the |
433 |
|
|
* user entered it. Presumably, the next term_key call will tell us how the |
434 |
|
|
* user wants it handled. |
435 |
|
|
* |
436 |
|
|
* There is one more complication. Users might map keys to digits, and, as |
437 |
|
|
* it's described above, the commands: |
438 |
|
|
* |
439 |
|
|
* :map g 1G |
440 |
|
|
* d2g |
441 |
|
|
* |
442 |
|
|
* would return the keys "d2<end-of-digits>1G", when the user probably wanted |
443 |
|
|
* "d21<end-of-digits>G". So, if a map starts off with a digit we continue as |
444 |
|
|
* before, otherwise, we pretend we haven't mapped the character, and return |
445 |
|
|
* <end-of-digits>. |
446 |
|
|
* |
447 |
|
|
* Now that that's out of the way, let's talk about Energizer Bunny macros. |
448 |
|
|
* It's easy to create macros that expand to a loop, e.g. map x 3x. It's |
449 |
|
|
* fairly easy to detect this example, because it's all internal to term_key. |
450 |
|
|
* If we're expanding a macro and it gets big enough, at some point we can |
451 |
|
|
* assume it's looping and kill it. The examples that are tough are the ones |
452 |
|
|
* where the parser is involved, e.g. map x "ayyx"byy. We do an expansion |
453 |
|
|
* on 'x', and get "ayyx"byy. We then return the first 4 characters, and then |
454 |
|
|
* find the looping macro again. There is no way that we can detect this |
455 |
|
|
* without doing a full parse of the command, because the character that might |
456 |
|
|
* cause the loop (in this case 'x') may be a literal character, e.g. the map |
457 |
|
|
* map x "ayy"xyy"byy is perfectly legal and won't cause a loop. |
458 |
|
|
* |
459 |
|
|
* Historic vi tried to detect looping macros by disallowing obvious cases in |
460 |
|
|
* the map command, maps that that ended with the same letter as they started |
461 |
|
|
* (which wrongly disallowed "map x 'x"), and detecting macros that expanded |
462 |
|
|
* too many times before keys were returned to the command parser. It didn't |
463 |
|
|
* get many (most?) of the tricky cases right, however, and it was certainly |
464 |
|
|
* possible to create macros that ran forever. And, even if it did figure out |
465 |
|
|
* what was going on, the user was usually tossed into ex mode. Finally, any |
466 |
|
|
* changes made before vi realized that the macro was recursing were left in |
467 |
|
|
* place. We recover gracefully, but the only recourse the user has in an |
468 |
|
|
* infinite macro loop is to interrupt. |
469 |
|
|
* |
470 |
|
|
* !!! |
471 |
|
|
* It is historic practice that mapping characters to themselves as the first |
472 |
|
|
* part of the mapped string was legal, and did not cause infinite loops, i.e. |
473 |
|
|
* ":map! { {^M^T" and ":map n nz." were known to work. The initial, matching |
474 |
|
|
* characters were returned instead of being remapped. |
475 |
|
|
* |
476 |
|
|
* !!! |
477 |
|
|
* It is also historic practice that the macro "map ] ]]^" caused a single ] |
478 |
|
|
* keypress to behave as the command ]] (the ^ got the map past the vi check |
479 |
|
|
* for "tail recursion"). Conversely, the mapping "map n nn^" went recursive. |
480 |
|
|
* What happened was that, in the historic vi, maps were expanded as the keys |
481 |
|
|
* were retrieved, but not all at once and not centrally. So, the keypress ] |
482 |
|
|
* pushed ]]^ on the stack, and then the first ] from the stack was passed to |
483 |
|
|
* the ]] command code. The ]] command then retrieved a key without entering |
484 |
|
|
* the mapping code. This could bite us anytime a user has a map that depends |
485 |
|
|
* on secondary keys NOT being mapped. I can't see any possible way to make |
486 |
|
|
* this work in here without the complete abandonment of Rationality Itself. |
487 |
|
|
* |
488 |
|
|
* XXX |
489 |
|
|
* The final issue is recovery. It would be possible to undo all of the work |
490 |
|
|
* that was done by the macro if we entered a record into the log so that we |
491 |
|
|
* knew when the macro started, and, in fact, this might be worth doing at some |
492 |
|
|
* point. Given that this might make the log grow unacceptably (consider that |
493 |
|
|
* cursor keys are done with maps), for now we leave any changes made in place. |
494 |
|
|
* |
495 |
|
|
* PUBLIC: int v_event_get(SCR *, EVENT *, int, u_int32_t); |
496 |
|
|
*/ |
497 |
|
|
int |
498 |
|
|
v_event_get(SCR *sp, EVENT *argp, int timeout, u_int32_t flags) |
499 |
|
|
{ |
500 |
|
|
EVENT *evp, ev; |
501 |
|
|
GS *gp; |
502 |
|
|
SEQ *qp; |
503 |
|
|
int init_nomap, ispartial, istimeout, remap_cnt; |
504 |
|
|
|
505 |
|
|
gp = sp->gp; |
506 |
|
|
|
507 |
|
|
/* If simply checking for interrupts, argp may be NULL. */ |
508 |
|
|
if (argp == NULL) |
509 |
|
|
argp = &ev; |
510 |
|
|
|
511 |
|
|
retry: istimeout = remap_cnt = 0; |
512 |
|
|
|
513 |
|
|
/* |
514 |
|
|
* If the queue isn't empty and we're timing out for characters, |
515 |
|
|
* return immediately. |
516 |
|
|
*/ |
517 |
|
|
if (gp->i_cnt != 0 && LF_ISSET(EC_TIMEOUT)) |
518 |
|
|
return (0); |
519 |
|
|
|
520 |
|
|
/* |
521 |
|
|
* If the queue is empty, we're checking for interrupts, or we're |
522 |
|
|
* timing out for characters, get more events. |
523 |
|
|
*/ |
524 |
|
|
if (gp->i_cnt == 0 || LF_ISSET(EC_INTERRUPT | EC_TIMEOUT)) { |
525 |
|
|
/* |
526 |
|
|
* If we're reading new characters, check any scripting |
527 |
|
|
* windows for input. |
528 |
|
|
*/ |
529 |
|
|
if (F_ISSET(gp, G_SCRWIN) && sscr_input(sp)) |
530 |
|
|
return (1); |
531 |
|
|
loop: if (gp->scr_event(sp, argp, |
532 |
|
|
LF_ISSET(EC_INTERRUPT | EC_QUOTED | EC_RAW), timeout)) |
533 |
|
|
return (1); |
534 |
|
|
switch (argp->e_event) { |
535 |
|
|
case E_ERR: |
536 |
|
|
case E_SIGHUP: |
537 |
|
|
case E_SIGTERM: |
538 |
|
|
/* |
539 |
|
|
* Fatal conditions cause the file to be synced to |
540 |
|
|
* disk immediately. |
541 |
|
|
*/ |
542 |
|
|
v_sync(sp, RCV_ENDSESSION | RCV_PRESERVE | |
543 |
|
|
(argp->e_event == E_SIGTERM ? 0: RCV_EMAIL)); |
544 |
|
|
return (1); |
545 |
|
|
case E_TIMEOUT: |
546 |
|
|
istimeout = 1; |
547 |
|
|
break; |
548 |
|
|
case E_INTERRUPT: |
549 |
|
|
/* Set the global interrupt flag. */ |
550 |
|
|
F_SET(sp->gp, G_INTERRUPTED); |
551 |
|
|
|
552 |
|
|
/* |
553 |
|
|
* If the caller was interested in interrupts, return |
554 |
|
|
* immediately. |
555 |
|
|
*/ |
556 |
|
|
if (LF_ISSET(EC_INTERRUPT)) |
557 |
|
|
return (0); |
558 |
|
|
goto append; |
559 |
|
|
default: |
560 |
|
|
append: if (v_event_append(sp, argp)) |
561 |
|
|
return (1); |
562 |
|
|
break; |
563 |
|
|
} |
564 |
|
|
} |
565 |
|
|
|
566 |
|
|
/* |
567 |
|
|
* If the caller was only interested in interrupts or timeouts, return |
568 |
|
|
* immediately. (We may have gotten characters, and that's okay, they |
569 |
|
|
* were queued up for later use.) |
570 |
|
|
*/ |
571 |
|
|
if (LF_ISSET(EC_INTERRUPT | EC_TIMEOUT)) |
572 |
|
|
return (0); |
573 |
|
|
|
574 |
|
|
newmap: evp = &gp->i_event[gp->i_next]; |
575 |
|
|
|
576 |
|
|
/* |
577 |
|
|
* If the next event in the queue isn't a character event, return |
578 |
|
|
* it, we're done. |
579 |
|
|
*/ |
580 |
|
|
if (evp->e_event != E_CHARACTER) { |
581 |
|
|
*argp = *evp; |
582 |
|
|
QREM(1); |
583 |
|
|
return (0); |
584 |
|
|
} |
585 |
|
|
|
586 |
|
|
/* |
587 |
|
|
* If the key isn't mappable because: |
588 |
|
|
* |
589 |
|
|
* + ... the timeout has expired |
590 |
|
|
* + ... it's not a mappable key |
591 |
|
|
* + ... neither the command or input map flags are set |
592 |
|
|
* + ... there are no maps that can apply to it |
593 |
|
|
* |
594 |
|
|
* return it forthwith. |
595 |
|
|
*/ |
596 |
|
|
if (istimeout || F_ISSET(&evp->e_ch, CH_NOMAP) || |
597 |
|
|
!LF_ISSET(EC_MAPCOMMAND | EC_MAPINPUT) || |
598 |
|
|
(evp->e_c < MAX_BIT_SEQ && !bit_test(gp->seqb, evp->e_c))) |
599 |
|
|
goto nomap; |
600 |
|
|
|
601 |
|
|
/* Search the map. */ |
602 |
|
|
qp = seq_find(sp, NULL, evp, NULL, gp->i_cnt, |
603 |
|
|
LF_ISSET(EC_MAPCOMMAND) ? SEQ_COMMAND : SEQ_INPUT, &ispartial); |
604 |
|
|
|
605 |
|
|
/* |
606 |
|
|
* If get a partial match, get more characters and retry the map. |
607 |
|
|
* If time out without further characters, return the characters |
608 |
|
|
* unmapped. |
609 |
|
|
* |
610 |
|
|
* !!! |
611 |
|
|
* <escape> characters are a problem. Cursor keys start with <escape> |
612 |
|
|
* characters, so there's almost always a map in place that begins with |
613 |
|
|
* an <escape> character. If we timeout <escape> keys in the same way |
614 |
|
|
* that we timeout other keys, the user will get a noticeable pause as |
615 |
|
|
* they enter <escape> to terminate input mode. If key timeout is set |
616 |
|
|
* for a slow link, users will get an even longer pause. Nvi used to |
617 |
|
|
* simply timeout <escape> characters at 1/10th of a second, but this |
618 |
|
|
* loses over PPP links where the latency is greater than 100Ms. |
619 |
|
|
*/ |
620 |
|
|
if (ispartial) { |
621 |
|
|
if (O_ISSET(sp, O_TIMEOUT)) |
622 |
|
|
timeout = (evp->e_value == K_ESCAPE ? |
623 |
|
|
O_VAL(sp, O_ESCAPETIME) : |
624 |
|
|
O_VAL(sp, O_KEYTIME)) * 100; |
625 |
|
|
else |
626 |
|
|
timeout = 0; |
627 |
|
|
goto loop; |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
/* If no map, return the character. */ |
631 |
|
|
if (qp == NULL) { |
632 |
|
|
nomap: if (!isdigit(evp->e_c) && LF_ISSET(EC_MAPNODIGIT)) |
633 |
|
|
goto not_digit; |
634 |
|
|
*argp = *evp; |
635 |
|
|
QREM(1); |
636 |
|
|
return (0); |
637 |
|
|
} |
638 |
|
|
|
639 |
|
|
/* |
640 |
|
|
* If looking for the end of a digit string, and the first character |
641 |
|
|
* of the map is it, pretend we haven't seen the character. |
642 |
|
|
*/ |
643 |
|
|
if (LF_ISSET(EC_MAPNODIGIT) && |
644 |
|
|
qp->output != NULL && !isdigit(qp->output[0])) { |
645 |
|
|
not_digit: argp->e_c = CH_NOT_DIGIT; |
646 |
|
|
argp->e_value = K_NOTUSED; |
647 |
|
|
argp->e_event = E_CHARACTER; |
648 |
|
|
F_INIT(&argp->e_ch, 0); |
649 |
|
|
return (0); |
650 |
|
|
} |
651 |
|
|
|
652 |
|
|
/* Find out if the initial segments are identical. */ |
653 |
|
|
init_nomap = !e_memcmp(qp->output, &gp->i_event[gp->i_next], qp->ilen); |
654 |
|
|
|
655 |
|
|
/* Delete the mapped characters from the queue. */ |
656 |
|
|
QREM(qp->ilen); |
657 |
|
|
|
658 |
|
|
/* If keys mapped to nothing, go get more. */ |
659 |
|
|
if (qp->output == NULL) |
660 |
|
|
goto retry; |
661 |
|
|
|
662 |
|
|
/* If remapping characters... */ |
663 |
|
|
if (O_ISSET(sp, O_REMAP)) { |
664 |
|
|
/* |
665 |
|
|
* Periodically check for interrupts. Always check the first |
666 |
|
|
* time through, because it's possible to set up a map that |
667 |
|
|
* will return a character every time, but will expand to more, |
668 |
|
|
* e.g. "map! a aaaa" will always return a 'a', but we'll never |
669 |
|
|
* get anywhere useful. |
670 |
|
|
*/ |
671 |
|
|
if ((++remap_cnt == 1 || remap_cnt % 10 == 0) && |
672 |
|
|
(gp->scr_event(sp, &ev, |
673 |
|
|
EC_INTERRUPT, 0) || ev.e_event == E_INTERRUPT)) { |
674 |
|
|
F_SET(sp->gp, G_INTERRUPTED); |
675 |
|
|
argp->e_event = E_INTERRUPT; |
676 |
|
|
return (0); |
677 |
|
|
} |
678 |
|
|
|
679 |
|
|
/* |
680 |
|
|
* If an initial part of the characters mapped, they are not |
681 |
|
|
* further remapped -- return the first one. Push the rest |
682 |
|
|
* of the characters, or all of the characters if no initial |
683 |
|
|
* part mapped, back on the queue. |
684 |
|
|
*/ |
685 |
|
|
if (init_nomap) { |
686 |
|
|
if (v_event_push(sp, NULL, qp->output + qp->ilen, |
687 |
|
|
qp->olen - qp->ilen, CH_MAPPED)) |
688 |
|
|
return (1); |
689 |
|
|
if (v_event_push(sp, NULL, |
690 |
|
|
qp->output, qp->ilen, CH_NOMAP | CH_MAPPED)) |
691 |
|
|
return (1); |
692 |
|
|
evp = &gp->i_event[gp->i_next]; |
693 |
|
|
goto nomap; |
694 |
|
|
} |
695 |
|
|
if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED)) |
696 |
|
|
return (1); |
697 |
|
|
goto newmap; |
698 |
|
|
} |
699 |
|
|
|
700 |
|
|
/* Else, push the characters on the queue and return one. */ |
701 |
|
|
if (v_event_push(sp, NULL, qp->output, qp->olen, CH_MAPPED | CH_NOMAP)) |
702 |
|
|
return (1); |
703 |
|
|
|
704 |
|
|
goto nomap; |
705 |
|
|
} |
706 |
|
|
|
707 |
|
|
/* |
708 |
|
|
* v_sync -- |
709 |
|
|
* Walk the screen lists, sync'ing files to their backup copies. |
710 |
|
|
*/ |
711 |
|
|
static void |
712 |
|
|
v_sync(SCR *sp, int flags) |
713 |
|
|
{ |
714 |
|
|
GS *gp; |
715 |
|
|
|
716 |
|
|
gp = sp->gp; |
717 |
|
|
TAILQ_FOREACH(sp, &gp->dq, q) |
718 |
|
|
rcv_sync(sp, flags); |
719 |
|
|
TAILQ_FOREACH(sp, &gp->hq, q) |
720 |
|
|
rcv_sync(sp, flags); |
721 |
|
|
} |
722 |
|
|
|
723 |
|
|
/* |
724 |
|
|
* v_event_err -- |
725 |
|
|
* Unexpected event. |
726 |
|
|
* |
727 |
|
|
* PUBLIC: void v_event_err(SCR *, EVENT *); |
728 |
|
|
*/ |
729 |
|
|
void |
730 |
|
|
v_event_err(SCR *sp, EVENT *evp) |
731 |
|
|
{ |
732 |
|
|
switch (evp->e_event) { |
733 |
|
|
case E_CHARACTER: |
734 |
|
|
msgq(sp, M_ERR, "Unexpected character event"); |
735 |
|
|
break; |
736 |
|
|
case E_EOF: |
737 |
|
|
msgq(sp, M_ERR, "Unexpected end-of-file event"); |
738 |
|
|
break; |
739 |
|
|
case E_INTERRUPT: |
740 |
|
|
msgq(sp, M_ERR, "Unexpected interrupt event"); |
741 |
|
|
break; |
742 |
|
|
case E_QUIT: |
743 |
|
|
msgq(sp, M_ERR, "Unexpected quit event"); |
744 |
|
|
break; |
745 |
|
|
case E_REPAINT: |
746 |
|
|
msgq(sp, M_ERR, "Unexpected repaint event"); |
747 |
|
|
break; |
748 |
|
|
case E_STRING: |
749 |
|
|
msgq(sp, M_ERR, "Unexpected string event"); |
750 |
|
|
break; |
751 |
|
|
case E_TIMEOUT: |
752 |
|
|
msgq(sp, M_ERR, "Unexpected timeout event"); |
753 |
|
|
break; |
754 |
|
|
case E_WRESIZE: |
755 |
|
|
msgq(sp, M_ERR, "Unexpected resize event"); |
756 |
|
|
break; |
757 |
|
|
case E_WRITE: |
758 |
|
|
msgq(sp, M_ERR, "Unexpected write event"); |
759 |
|
|
break; |
760 |
|
|
|
761 |
|
|
/* |
762 |
|
|
* Theoretically, none of these can occur, as they're handled at the |
763 |
|
|
* top editor level. |
764 |
|
|
*/ |
765 |
|
|
case E_ERR: |
766 |
|
|
case E_SIGHUP: |
767 |
|
|
case E_SIGTERM: |
768 |
|
|
default: |
769 |
|
|
abort(); |
770 |
|
|
} |
771 |
|
|
|
772 |
|
|
/* Free any allocated memory. */ |
773 |
|
|
free(evp->e_asp); |
774 |
|
|
} |
775 |
|
|
|
776 |
|
|
/* |
777 |
|
|
* v_event_flush -- |
778 |
|
|
* Flush any flagged keys, returning if any keys were flushed. |
779 |
|
|
* |
780 |
|
|
* PUBLIC: int v_event_flush(SCR *, u_int); |
781 |
|
|
*/ |
782 |
|
|
int |
783 |
|
|
v_event_flush(SCR *sp, u_int flags) |
784 |
|
|
{ |
785 |
|
|
GS *gp; |
786 |
|
|
int rval; |
787 |
|
|
|
788 |
|
|
for (rval = 0, gp = sp->gp; gp->i_cnt != 0 && |
789 |
|
|
F_ISSET(&gp->i_event[gp->i_next].e_ch, flags); rval = 1) |
790 |
|
|
QREM(1); |
791 |
|
|
return (rval); |
792 |
|
|
} |
793 |
|
|
|
794 |
|
|
/* |
795 |
|
|
* v_event_grow -- |
796 |
|
|
* Grow the terminal queue. |
797 |
|
|
*/ |
798 |
|
|
static int |
799 |
|
|
v_event_grow(SCR *sp, int add) |
800 |
|
|
{ |
801 |
|
|
GS *gp; |
802 |
|
|
size_t new_nelem, olen; |
803 |
|
|
|
804 |
|
|
gp = sp->gp; |
805 |
|
|
new_nelem = gp->i_nelem + add; |
806 |
|
|
olen = gp->i_nelem * sizeof(gp->i_event[0]); |
807 |
|
|
BINC_RET(sp, gp->i_event, olen, new_nelem * sizeof(gp->i_event[0])); |
808 |
|
|
gp->i_nelem = olen / sizeof(gp->i_event[0]); |
809 |
|
|
return (0); |
810 |
|
|
} |
811 |
|
|
|
812 |
|
|
/* |
813 |
|
|
* v_key_cmp -- |
814 |
|
|
* Compare two keys for sorting. |
815 |
|
|
*/ |
816 |
|
|
static int |
817 |
|
|
v_key_cmp(const void *ap, const void *bp) |
818 |
|
|
{ |
819 |
|
|
return (((KEYLIST *)ap)->ch - ((KEYLIST *)bp)->ch); |
820 |
|
|
} |