if no messages waiting, always display the file status line on
[nvi.git] / common / key.c
blob8a09cdebfdc77b308bac7d88b7f7776ab3e2eb22
1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: key.c,v 8.25 1993/11/27 15:52:11 bostic Exp $ (Berkeley) $Date: 1993/11/27 15:52:11 $";
10 #endif /* not lint */
12 #include <sys/types.h>
13 #include <sys/time.h>
15 #include <ctype.h>
16 #include <curses.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
22 #include "vi.h"
23 #include "seq.h"
26 * There are two sets of input buffers used by ex/vi. The first is the input
27 * from the user, either via the tty or an initial command supplied with the
28 * ex or edit commands or similar mechanism. The second is the the keys from
29 * the first after mapping has been done. Also, executable buffer expansions
30 * are pushed into this second buffer. The reason that there are two is that
31 * we only want to flush the latter buffer if a command fails, i.e. if the user
32 * enters "@a1G", we don't want to flush the "1G" keys because "@a" failed.
33 */
35 typedef struct _klist {
36 char *ts; /* Key's termcap string. */
37 char *output; /* Corresponding vi command. */
38 char *name; /* Name. */
39 } KLIST;
41 static KLIST const klist[] = {
42 {"kA", "O", "insert line"},
43 {"kD", "x", "delete character"},
44 {"kd", "j", "cursor down"},
45 {"kE", "D", "delete to eol"},
46 {"kF", "\004", "scroll down"},
47 {"kH", "$", "go to eol"},
48 {"kh", "^", "go to sol"},
49 {"kI", "i", "insert at cursor"},
50 {"kL", "dd", "delete line"},
51 {"kl", "h", "cursor left"},
52 {"kN", "\006", "page down"},
53 {"kP", "\002", "page up"},
54 {"kR", "\025", "scroll up"},
55 {"kS", "dG", "delete to end of screen"},
56 {"kr", "l", "cursor right"},
57 {"ku", "k", "cursor up"},
58 {NULL},
62 * term_init --
63 * Initialize the special array and special keys. The special array
64 * has a value for each special character that we can use in a switch
65 * statement.
67 int
68 term_init(sp)
69 SCR *sp;
71 KLIST const *kp;
72 cc_t ch;
73 char *sbp, *t, buf[2 * 1024], sbuf[128];
75 /* Keys that are treated specially. */
76 sp->special['^'] = K_CARAT;
77 sp->special['\022'] = K_CNTRLR;
78 sp->special['\024'] = K_CNTRLT;
79 sp->special['\032'] = K_CNTRLZ;
80 sp->special[':'] = K_COLON;
81 sp->special['\r'] = K_CR;
82 sp->special['\033'] = K_ESCAPE;
83 sp->special['\f'] = K_FORMFEED;
84 sp->special['\n'] = K_NL;
85 sp->special[')'] = K_RIGHTPAREN;
86 sp->special['}'] = K_RIGHTBRACE;
87 sp->special['\t'] = K_TAB;
88 if ((ch = sp->gp->original_termios.c_cc[VEOF]) == _POSIX_VDISABLE)
89 ch = '\004';
90 sp->special[ch] = K_VEOF;
91 if ((ch = sp->gp->original_termios.c_cc[VERASE]) == _POSIX_VDISABLE)
92 ch = '\b';
93 sp->special[ch] = K_VERASE;
94 if ((ch = sp->gp->original_termios.c_cc[VKILL]) == _POSIX_VDISABLE)
95 ch = '\025';
96 sp->special[ch] = K_VKILL;
97 if ((ch = sp->gp->original_termios.c_cc[VLNEXT]) == _POSIX_VDISABLE)
98 ch = '\026';
99 sp->special[ch] = K_VLNEXT;
100 if ((ch = sp->gp->original_termios.c_cc[VWERASE]) == _POSIX_VDISABLE)
101 ch = '\027';
102 sp->special[ch] = K_VWERASE;
103 sp->special['0'] = K_ZERO;
105 /* Special terminal keys, from the termcap entry. */
106 switch (tgetent(buf, O_STR(sp, O_TERM))) {
107 case -1:
108 msgq(sp, M_ERR, "%s tgetent: %s.",
109 O_STR(sp, O_TERM), strerror(errno));
110 return (1);
111 case 0:
112 msgq(sp, M_ERR, "%s: unknown terminal type.",
113 O_STR(sp, O_TERM), strerror(errno));
114 return (1);
117 for (kp = klist; kp->name != NULL; ++kp) {
118 sbp = sbuf;
119 if ((t = tgetstr(kp->ts, &sbp)) == NULL)
120 continue;
121 if (seq_set(sp, kp->name, t, kp->output, SEQ_COMMAND, 0))
122 return (1);
124 return (0);
128 * term_push --
129 * Push keys onto the front of a buffer.
132 term_push(sp, ibp, s, len)
133 SCR *sp;
134 IBUF *ibp;
135 char *s;
136 size_t len;
138 size_t nlen;
140 /* If we have room, stuff the keys into the buffer. */
141 if (len <= ibp->next) {
142 ibp->next -= len;
143 ibp->cnt += len;
144 memmove(ibp->buf + ibp->next, s, len);
145 return (0);
148 /* Get enough space plus a little extra. */
149 nlen = ibp->cnt + len;
150 BINC(sp, ibp->buf, ibp->len, nlen + 64);
153 * If there is currently characters in the buffer,
154 * shift them up, and leave a little extra room.
156 #define TERM_PUSH_SHIFT 20
157 if (ibp->cnt)
158 memmove(ibp->buf + len + TERM_PUSH_SHIFT,
159 ibp->buf + ibp->next, ibp->cnt);
160 if (len == 1)
161 ibp->buf[TERM_PUSH_SHIFT] = *s;
162 else
163 memmove(ibp->buf + TERM_PUSH_SHIFT, s, len);
164 ibp->next = TERM_PUSH_SHIFT;
165 ibp->cnt += len;
166 return (0);
169 /* Remove characters from a queue. */
170 #define QREM(q, len) { \
171 if (((q)->cnt -= len) == 0) \
172 (q)->next = 0; \
173 else \
174 (q)->next += len; \
178 * term_key --
179 * Get the next key.
181 * !!!
182 * The flag TXT_MAPNODIGIT probably needs some explanation. First, the idea
183 * of mapping keys is that one or more keystrokes behave like a function key.
184 * What's going on is that vi is reading a number, and the character following
185 * the number may or may not be mapped (TXT_MAPCOMMAND). For example, if the
186 * user is entering the z command, a valid command is "z40+", and we don't want
187 * to map the '+', i.e. if '+' is mapped to "xxx", we don't want to change it
188 * into "z40xxx". However, if the user is entering "35x", we want to put all
189 * of the characters through the mapping code.
191 * Historical practice is a bit muddled here. (Surprise!) It always permitted
192 * mapping digits as long as they weren't the first character of the map, e.g.
193 * ":map ^A1 xxx" was okay. It also permitted the mapping of the digits 1-9
194 * (the digit 0 was a special case as it doesn't indicate the start of a count)
195 * as the first character of the map, but then ignored those mappings. While
196 * it's probably stupid to map digits, vi isn't your mother.
198 * The way this works is that the TXT_MAPNODIGIT causes term_key to return the
199 * end-of-digit without "looking" at the next character, i.e. leaving it as the
200 * user entered it. Presumably, the next term_key call will tell us how the
201 * user wants it handled.
203 * There is one more complication. Users might map keys to digits, and, as
204 * it's described above, the commands "map g 1G|d2g" would return the keys
205 * "d2<end-of-digits>1G", when the user probably wanted "d21<end-of-digits>G".
206 * So, if a map starts off with a digit we continue as before, otherwise, we
207 * pretend that we haven't mapped the character and return <end-of-digits>.
209 * Now that that's out of the way, let's talk about Energizer Bunny macros.
210 * It's easy to create macros that expand to a loop, e.g. map x 3x. It's
211 * fairly easy to detect this example, because it's all internal to term_key.
212 * If we're expanding a macro and it gets big enough, at some point we can
213 * assume it's looping and kill it. The examples that are tough are the ones
214 * where the parser is involved, e.g. map x "ayyx"byy. We do an expansion
215 * on 'x', and get "ayyx"byy. We then return the first 4 characters, and then
216 * find the looping macro again. There is no way that we can detect this
217 * without doing a full parse of the command, because the character that might
218 * cause the loop (in this case 'x') may be a literal character, e.g. the map
219 * map x "ayy"xyy"byy is perfectly legal and won't cause a loop.
221 * Historic vi tried to detect looping macros by disallowing obvious cases in
222 * the map command, maps that that ended with the same letter as they started
223 * (which wrongly disallowed map x 'x), and detecting macros that expanded too
224 * many times before keys were returned to the command parser. It didn't get
225 * many of the tricky cases right, however, and it was certainly possible to
226 * create macros that ran forever. Finally, changes made before vi realized
227 * that the macro was recursing were left in place.
229 * We handle the problem by returning no more than MAX_KEYS_WITHOUT_READ keys
230 * without reading from the terminal. If we hit the boundary, we return an
231 * error and flush both terminal buffers. This handles all of the cases, with
232 * the exception of macros that loop without returning a character. We simply
233 * count those cases and error if there are more than MAX_MACRO_EXP expansions.
235 * XXX
236 * The final issue is recovery. It would be possible to undo all of the work
237 * that was done by the macro if we entered a record into the log so that we
238 * knew when the macro started, and, in fact, this might be worth doing at some
239 * point. For now we just flush the keys and leave any changes made in place.
241 enum input
242 term_key(sp, chp, flags)
243 SCR *sp;
244 CHAR_T *chp;
245 u_int flags;
247 enum input rval;
248 GS *gp;
249 IBUF *keyp, *ttyp;
250 SEQ *qp;
251 int ch, ispartial, ml_cnt, nr;
253 /* If we have expanded keys, return the next one. */
254 gp = sp->gp;
255 keyp = gp->key;
256 ttyp = gp->tty;
257 loop: if (keyp->cnt) {
258 ch = keyp->buf[keyp->next];
259 if (LF_ISSET(TXT_MAPNODIGIT) && !isdigit(ch)) {
260 *chp = NOT_DIGIT_CH;
261 return (INP_OK);
263 QREM(keyp, 1);
264 goto ret;
268 * Read in more keys if none in the queue. Since no timeout
269 * is requested, s_key_read will either return 1 or will read
270 * some number of characters.
272 if (ttyp->cnt == 0) {
273 gp->key_cnt = 0;
274 if (rval = sp->s_key_read(sp, &nr, 0))
275 return (rval);
277 * If there's something on the mode line that we wanted
278 * the user to see, they just entered a character so we
279 * can presume they saw it. Clear the bit before doing
280 * the refresh, the refresh routine is probably checking.
282 if (F_ISSET(sp, S_UPDATE_MODE)) {
283 F_CLR(sp, S_UPDATE_MODE);
284 if (sp->s_refresh(sp, sp->ep))
285 return (INP_ERR);
289 /* Check for mapped keys. */
290 if (LF_ISSET(TXT_MAPCOMMAND | TXT_MAPINPUT)) {
291 ml_cnt = 0;
292 newmap: ch = ttyp->buf[ttyp->next];
293 if (ch < MAX_BIT_SEQ && !bit_test(gp->seqb, ch))
294 goto nomap;
295 remap: qp = seq_find(sp, NULL, &ttyp->buf[ttyp->next], ttyp->cnt,
296 LF_ISSET(TXT_MAPCOMMAND) ? SEQ_COMMAND : SEQ_INPUT,
297 &ispartial);
299 /* If get a partial match, keep trying. */
300 if (ispartial) {
301 if (rval = sp->s_key_read(sp, &nr, 1))
302 return (rval);
303 if (nr)
304 goto remap;
305 goto nomap;
308 if (qp == NULL)
309 goto nomap;
311 #define MAX_MACRO_EXP 40
312 if (++ml_cnt > MAX_MACRO_EXP)
313 goto rec_err;
315 if (LF_ISSET(TXT_MAPNODIGIT) && !isdigit(qp->output[0])) {
316 *chp = NOT_DIGIT_CH;
317 return (INP_OK);
320 QREM(ttyp, qp->ilen);
321 if (O_ISSET(sp, O_REMAP)) {
322 if (term_push(sp, ttyp, qp->output, qp->olen))
323 goto err;
324 goto newmap;
326 if (term_push(sp, keyp, qp->output, qp->olen)) {
327 err: msgq(sp, M_SYSERR, "Error: key deleted");
328 return (INP_ERR);
330 goto loop;
333 nomap: ch = ttyp->buf[ttyp->next];
334 if (LF_ISSET(TXT_MAPNODIGIT) && !isdigit(ch)) {
335 *chp = NOT_DIGIT_CH;
336 return (INP_OK);
338 QREM(ttyp, 1);
340 #define MAX_KEYS_WITHOUT_READ 1000
341 ret: if (++gp->key_cnt > MAX_KEYS_WITHOUT_READ) {
342 rec_err: gp->key_cnt = 0;
343 TERM_FLUSH(keyp);
344 TERM_FLUSH(ttyp);
345 msgq(sp, M_ERR,
346 "Error: command expansion too long; keys flushed.");
347 return (INP_ERR);
351 * O_BEAUTIFY eliminates all control characters except
352 * escape, form-feed, newline and tab.
354 if (LF_ISSET(TXT_BEAUTIFY) && O_ISSET(sp, O_BEAUTIFY)) {
355 if (isprint(ch) ||
356 sp->special[ch] == K_ESCAPE ||
357 sp->special[ch] == K_FORMFEED ||
358 sp->special[ch] == K_NL ||
359 sp->special[ch] == K_TAB) {
360 *chp = ch;
361 return (INP_OK);
363 goto loop;
365 *chp = ch;
366 return (INP_OK);