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