getch.c revision 1.18 1 1.18 blymn /* $NetBSD: getch.c,v 1.18 2000/04/15 13:17:03 blymn Exp $ */
2 1.8 mikel
3 1.1 cgd /*
4 1.7 cgd * Copyright (c) 1981, 1993, 1994
5 1.5 cgd * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.1 cgd * 3. All advertising materials mentioning features or use of this software
16 1.1 cgd * must display the following acknowledgement:
17 1.1 cgd * This product includes software developed by the University of
18 1.1 cgd * California, Berkeley and its contributors.
19 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
20 1.1 cgd * may be used to endorse or promote products derived from this software
21 1.1 cgd * without specific prior written permission.
22 1.1 cgd *
23 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 cgd * SUCH DAMAGE.
34 1.1 cgd */
35 1.1 cgd
36 1.8 mikel #include <sys/cdefs.h>
37 1.1 cgd #ifndef lint
38 1.8 mikel #if 0
39 1.7 cgd static char sccsid[] = "@(#)getch.c 8.2 (Berkeley) 5/4/94";
40 1.8 mikel #else
41 1.18 blymn __RCSID("$NetBSD: getch.c,v 1.18 2000/04/15 13:17:03 blymn Exp $");
42 1.8 mikel #endif
43 1.10 mrg #endif /* not lint */
44 1.1 cgd
45 1.10 mrg #include <string.h>
46 1.10 mrg #include <stdlib.h>
47 1.10 mrg #include <unistd.h>
48 1.10 mrg #include <stdio.h>
49 1.7 cgd #include "curses.h"
50 1.16 blymn #include "curses_private.h"
51 1.1 cgd
52 1.10 mrg #define DEFAULT_DELAY 2 /* default delay for timeout() */
53 1.10 mrg
54 1.10 mrg /*
55 1.10 mrg * Keyboard input handler. Do this by snarfing
56 1.10 mrg * all the info we can out of the termcap entry for TERM and putting it
57 1.10 mrg * into a set of keymaps. A keymap is an array the size of all the possible
58 1.10 mrg * single characters we can get, the contents of the array is a structure
59 1.10 mrg * that contains the type of entry this character is (i.e. part/end of a
60 1.10 mrg * multi-char sequence or a plain char) and either a pointer which will point
61 1.10 mrg * to another keymap (in the case of a multi-char sequence) OR the data value
62 1.10 mrg * that this key should return.
63 1.10 mrg *
64 1.10 mrg */
65 1.10 mrg
66 1.10 mrg /* private data structures for holding the key definitions */
67 1.10 mrg typedef struct keymap keymap_t;
68 1.10 mrg typedef struct key_entry key_entry_t;
69 1.10 mrg
70 1.10 mrg struct key_entry {
71 1.10 mrg short type; /* type of key this is */
72 1.10 mrg union {
73 1.10 mrg keymap_t *next; /* next keymap is key is multi-key sequence */
74 1.16 blymn wchar_t symbol; /* key symbol if key is a leaf entry */
75 1.12 pk } value;
76 1.10 mrg };
77 1.10 mrg /* Types of key structures we can have */
78 1.10 mrg #define KEYMAP_MULTI 1 /* part of a multi char sequence */
79 1.10 mrg #define KEYMAP_LEAF 2 /* key has a symbol associated with it, either
80 1.10 mrg * it is the end of a multi-char sequence or a
81 1.10 mrg * single char key that generates a symbol */
82 1.10 mrg
83 1.10 mrg /* The max number of different chars we can receive */
84 1.10 mrg #define MAX_CHAR 256
85 1.10 mrg
86 1.10 mrg struct keymap {
87 1.12 pk int count; /* count of number of key structs allocated */
88 1.12 pk short mapping[MAX_CHAR]; /* mapping of key to allocated structs */
89 1.10 mrg key_entry_t **key; /* dynamic array of keys */};
90 1.10 mrg
91 1.10 mrg
92 1.10 mrg /* Key buffer */
93 1.10 mrg #define INBUF_SZ 16 /* size of key buffer - must be larger than
94 1.10 mrg * longest multi-key sequence */
95 1.16 blymn static wchar_t inbuf[INBUF_SZ];
96 1.13 simonb static int start, end, working; /* pointers for manipulating inbuf data */
97 1.10 mrg
98 1.12 pk #define INC_POINTER(ptr) do { \
99 1.12 pk (ptr)++; \
100 1.12 pk ptr %= INBUF_SZ; \
101 1.10 mrg } while(/*CONSTCOND*/0)
102 1.10 mrg
103 1.13 simonb static short state; /* state of the inkey function */
104 1.10 mrg
105 1.12 pk #define INKEY_NORM 0 /* no key backlog to process */
106 1.10 mrg #define INKEY_ASSEMBLING 1 /* assembling a multi-key sequence */
107 1.12 pk #define INKEY_BACKOUT 2 /* recovering from an unrecognised key */
108 1.12 pk #define INKEY_TIMEOUT 3 /* multi-key sequence timeout */
109 1.10 mrg
110 1.10 mrg /* The termcap data we are interested in and the symbols they map to */
111 1.10 mrg struct tcdata {
112 1.12 pk char *name; /* name of termcap entry */
113 1.16 blymn wchar_t symbol; /* the symbol associated with it */
114 1.10 mrg };
115 1.10 mrg
116 1.13 simonb static const struct tcdata tc[] = {
117 1.10 mrg {"K1", KEY_A1},
118 1.10 mrg {"K2", KEY_B2},
119 1.10 mrg {"K3", KEY_A3},
120 1.10 mrg {"K4", KEY_C1},
121 1.10 mrg {"K5", KEY_C3},
122 1.10 mrg {"k0", KEY_F0},
123 1.10 mrg {"k1", KEY_F(1)},
124 1.10 mrg {"k2", KEY_F(2)},
125 1.10 mrg {"k3", KEY_F(3)},
126 1.10 mrg {"k4", KEY_F(4)},
127 1.10 mrg {"k5", KEY_F(5)},
128 1.10 mrg {"k6", KEY_F(6)},
129 1.10 mrg {"k7", KEY_F(7)},
130 1.10 mrg {"k8", KEY_F(8)},
131 1.10 mrg {"k9", KEY_F(9)},
132 1.10 mrg {"kA", KEY_IL},
133 1.10 mrg {"ka", KEY_CATAB},
134 1.10 mrg {"kb", KEY_BACKSPACE},
135 1.10 mrg {"kC", KEY_CLEAR},
136 1.10 mrg {"kD", KEY_DC},
137 1.10 mrg {"kd", KEY_DOWN},
138 1.10 mrg {"kE", KEY_EOL},
139 1.10 mrg {"kF", KEY_SF},
140 1.10 mrg {"kH", KEY_LL},
141 1.10 mrg {"kh", KEY_HOME},
142 1.10 mrg {"kI", KEY_IC},
143 1.10 mrg {"kL", KEY_DL},
144 1.10 mrg {"kl", KEY_LEFT},
145 1.10 mrg {"kN", KEY_NPAGE},
146 1.10 mrg {"kP", KEY_PPAGE},
147 1.10 mrg {"kR", KEY_SR},
148 1.10 mrg {"kr", KEY_RIGHT},
149 1.10 mrg {"kS", KEY_EOS},
150 1.10 mrg {"kT", KEY_STAB},
151 1.10 mrg {"kt", KEY_CTAB},
152 1.10 mrg {"ku", KEY_UP}
153 1.10 mrg };
154 1.10 mrg /* Number of TC entries .... */
155 1.13 simonb static const int num_tcs = (sizeof(tc) / sizeof(struct tcdata));
156 1.10 mrg
157 1.10 mrg /* The root keymap */
158 1.10 mrg
159 1.13 simonb static keymap_t *base_keymap;
160 1.10 mrg
161 1.10 mrg /* prototypes for private functions */
162 1.13 simonb static keymap_t *new_keymap(void); /* create a new keymap */
163 1.13 simonb static key_entry_t *new_key(void); /* create a new key entry */
164 1.16 blymn static wchar_t inkey(int, int);
165 1.10 mrg
166 1.10 mrg /*
167 1.10 mrg * Init_getch - initialise all the pointers & structures needed to make
168 1.10 mrg * getch work in keypad mode.
169 1.10 mrg *
170 1.10 mrg */
171 1.10 mrg void
172 1.18 blymn __init_getch(char *sp)
173 1.10 mrg {
174 1.18 blymn static struct tinfo *termcap;
175 1.12 pk char entry[1024], termname[1024], *p;
176 1.12 pk int i, j, length;
177 1.18 blymn size_t limit;
178 1.10 mrg keymap_t *current;
179 1.10 mrg key_entry_t *the_key;
180 1.10 mrg
181 1.10 mrg /* init the inkey state variable */
182 1.10 mrg state = INKEY_NORM;
183 1.10 mrg
184 1.10 mrg /* init the base keymap */
185 1.10 mrg base_keymap = new_keymap();
186 1.10 mrg
187 1.10 mrg /* key input buffer pointers */
188 1.10 mrg start = end = working = 0;
189 1.10 mrg
190 1.10 mrg /* now do the termcap snarfing ... */
191 1.16 blymn (void) strncpy(termname, sp, (size_t) 1022);
192 1.10 mrg termname[1023] = 0;
193 1.10 mrg
194 1.18 blymn if (t_getent(&termcap, termname) <= 0)
195 1.12 pk return;
196 1.12 pk
197 1.12 pk for (i = 0; i < num_tcs; i++) {
198 1.10 mrg
199 1.12 pk p = entry;
200 1.18 blymn limit = 1023;
201 1.18 blymn if (t_getstr(termcap, tc[i].name, &p, &limit) == NULL)
202 1.12 pk continue;
203 1.12 pk
204 1.12 pk current = base_keymap; /* always start with base keymap. */
205 1.16 blymn length = (int) strlen(entry);
206 1.12 pk
207 1.12 pk for (j = 0; j < length - 1; j++) {
208 1.12 pk if (current->mapping[(unsigned) entry[j]] < 0) {
209 1.12 pk /* first time for this char */
210 1.12 pk current->mapping[(unsigned) entry[j]] = current->count; /* map new entry */
211 1.10 mrg the_key = new_key();
212 1.12 pk /* multikey coz we are here */
213 1.12 pk the_key->type = KEYMAP_MULTI;
214 1.10 mrg
215 1.12 pk /* need for next key */
216 1.12 pk the_key->value.next = new_keymap();
217 1.14 simonb
218 1.12 pk /* put into key array */
219 1.12 pk if ((current->key = realloc(current->key, (current->count + 1) * sizeof(key_entry_t *))) == NULL) {
220 1.12 pk fprintf(stderr,
221 1.12 pk "Could not malloc for key entry\n");
222 1.12 pk exit(1);
223 1.12 pk }
224 1.14 simonb
225 1.10 mrg current->key[current->count++] = the_key;
226 1.12 pk
227 1.12 pk }
228 1.12 pk /* next key uses this map... */
229 1.12 pk current = current->key[current->mapping[(unsigned) entry[j]]]->value.next;
230 1.12 pk }
231 1.12 pk
232 1.12 pk /*
233 1.12 pk * This is the last key in the sequence (it may have been
234 1.12 pk * the only one but that does not matter) this means it is
235 1.12 pk * a leaf key and should have a symbol associated with it.
236 1.12 pk */
237 1.12 pk if (current->count > 0) {
238 1.12 pk /*
239 1.12 pk * If there were other keys then we need to
240 1.12 pk * extend the mapping array.
241 1.12 pk */
242 1.12 pk if ((current->key =
243 1.12 pk realloc(current->key,
244 1.12 pk (current->count + 1) *
245 1.12 pk sizeof(key_entry_t *))) == NULL) {
246 1.12 pk
247 1.12 pk fprintf(stderr,
248 1.12 pk "Could not malloc for key entry\n");
249 1.12 pk exit(1);
250 1.10 mrg }
251 1.10 mrg }
252 1.12 pk current->mapping[(unsigned) entry[length - 1]] = current->count;
253 1.12 pk the_key = new_key();
254 1.12 pk the_key->type = KEYMAP_LEAF; /* leaf key */
255 1.12 pk
256 1.12 pk /* the associated symbol */
257 1.12 pk the_key->value.symbol = tc[i].symbol;
258 1.12 pk current->key[current->count++] = the_key;
259 1.10 mrg }
260 1.10 mrg }
261 1.10 mrg
262 1.10 mrg
263 1.10 mrg /*
264 1.10 mrg * new_keymap - allocates & initialises a new keymap structure. This
265 1.10 mrg * function returns a pointer to the new keymap.
266 1.10 mrg *
267 1.10 mrg */
268 1.13 simonb static keymap_t *
269 1.10 mrg new_keymap(void)
270 1.10 mrg {
271 1.10 mrg int i;
272 1.10 mrg keymap_t *new_map;
273 1.10 mrg
274 1.10 mrg if ((new_map = malloc(sizeof(keymap_t))) == NULL) {
275 1.10 mrg perror("Inkey: Cannot allocate new keymap");
276 1.10 mrg exit(2);
277 1.10 mrg }
278 1.12 pk
279 1.12 pk /* Initialise the new map */
280 1.10 mrg new_map->count = 0;
281 1.10 mrg for (i = 0; i < MAX_CHAR; i++) {
282 1.10 mrg new_map->mapping[i] = -1; /* no mapping for char */
283 1.10 mrg }
284 1.10 mrg
285 1.12 pk /* one does assume there will be at least one key mapped.... */
286 1.10 mrg if ((new_map->key = malloc(sizeof(key_entry_t *))) == NULL) {
287 1.10 mrg perror("Could not malloc first key ent");
288 1.10 mrg exit(1);
289 1.10 mrg }
290 1.14 simonb
291 1.12 pk return (new_map);
292 1.10 mrg }
293 1.10 mrg
294 1.10 mrg /*
295 1.10 mrg * new_key - allocates & initialises a new key entry. This function returns
296 1.10 mrg * a pointer to the newly allocated key entry.
297 1.10 mrg *
298 1.10 mrg */
299 1.13 simonb static key_entry_t *
300 1.10 mrg new_key(void)
301 1.10 mrg {
302 1.10 mrg key_entry_t *new_one;
303 1.10 mrg
304 1.10 mrg if ((new_one = malloc(sizeof(key_entry_t))) == NULL) {
305 1.10 mrg perror("inkey: Cannot allocate new key entry");
306 1.10 mrg exit(2);
307 1.10 mrg }
308 1.10 mrg new_one->type = 0;
309 1.10 mrg new_one->value.next = NULL;
310 1.10 mrg
311 1.12 pk return (new_one);
312 1.10 mrg }
313 1.10 mrg
314 1.10 mrg /*
315 1.10 mrg * inkey - do the work to process keyboard input, check for multi-key
316 1.10 mrg * sequences and return the appropriate symbol if we get a match.
317 1.10 mrg *
318 1.10 mrg */
319 1.10 mrg
320 1.16 blymn wchar_t
321 1.10 mrg inkey(to, delay)
322 1.10 mrg int to, delay;
323 1.10 mrg {
324 1.17 jdc wchar_t k;
325 1.17 jdc ssize_t nchar;
326 1.17 jdc unsigned char c;
327 1.17 jdc keymap_t *current = base_keymap;
328 1.10 mrg
329 1.10 mrg for (;;) { /* loop until we get a complete key sequence */
330 1.10 mrg reread:
331 1.10 mrg if (state == INKEY_NORM) {
332 1.10 mrg if (delay && __timeout(delay) == ERR)
333 1.10 mrg return ERR;
334 1.10 mrg if ((nchar = read(STDIN_FILENO, &c, sizeof(char))) < 0)
335 1.10 mrg return ERR;
336 1.10 mrg if (delay && (__notimeout() == ERR))
337 1.10 mrg return ERR;
338 1.10 mrg if (nchar == 0)
339 1.10 mrg return ERR; /* just in case we are nodelay
340 1.10 mrg * mode */
341 1.16 blymn k = (wchar_t) c;
342 1.10 mrg #ifdef DEBUG
343 1.10 mrg __CTRACE("inkey (state normal) got '%s'\n", unctrl(k));
344 1.10 mrg #endif
345 1.10 mrg
346 1.10 mrg working = start;
347 1.10 mrg inbuf[working] = k;
348 1.10 mrg INC_POINTER(working);
349 1.10 mrg end = working;
350 1.10 mrg state = INKEY_ASSEMBLING; /* go to the assembling
351 1.10 mrg * state now */
352 1.12 pk } else if (state == INKEY_BACKOUT) {
353 1.12 pk k = inbuf[working];
354 1.12 pk INC_POINTER(working);
355 1.12 pk if (working == end) { /* see if we have run
356 1.12 pk * out of keys in the
357 1.12 pk * backlog */
358 1.12 pk
359 1.12 pk /* if we have then switch to
360 1.12 pk assembling */
361 1.12 pk state = INKEY_ASSEMBLING;
362 1.12 pk }
363 1.12 pk } else if (state == INKEY_ASSEMBLING) {
364 1.12 pk /* assembling a key sequence */
365 1.12 pk if (delay) {
366 1.12 pk if (__timeout(to ? DEFAULT_DELAY : delay) == ERR)
367 1.10 mrg return ERR;
368 1.12 pk } else {
369 1.12 pk if (to && (__timeout(DEFAULT_DELAY) == ERR))
370 1.10 mrg return ERR;
371 1.12 pk }
372 1.12 pk if ((nchar = read(STDIN_FILENO, &c,
373 1.12 pk sizeof(char))) < 0)
374 1.12 pk return ERR;
375 1.12 pk if ((to || delay) && (__notimeout() == ERR))
376 1.10 mrg return ERR;
377 1.14 simonb
378 1.16 blymn k = (wchar_t) c;
379 1.10 mrg #ifdef DEBUG
380 1.12 pk __CTRACE("inkey (state assembling) got '%s'\n", unctrl(k));
381 1.10 mrg #endif
382 1.12 pk if (nchar == 0) { /* inter-char timeout,
383 1.12 pk * start backing out */
384 1.12 pk if (start == end)
385 1.12 pk /* no chars in the buffer, restart */
386 1.12 pk goto reread;
387 1.12 pk
388 1.12 pk k = inbuf[start];
389 1.12 pk state = INKEY_TIMEOUT;
390 1.10 mrg } else {
391 1.12 pk inbuf[working] = k;
392 1.12 pk INC_POINTER(working);
393 1.12 pk end = working;
394 1.10 mrg }
395 1.12 pk } else {
396 1.12 pk fprintf(stderr, "Inkey state screwed - exiting!!!");
397 1.12 pk exit(2);
398 1.12 pk }
399 1.10 mrg
400 1.10 mrg /* Check key has no special meaning and we have not timed out */
401 1.10 mrg if ((current->mapping[k] < 0) || (state == INKEY_TIMEOUT)) {
402 1.12 pk /* return the first key we know about */
403 1.12 pk k = inbuf[start];
404 1.10 mrg
405 1.10 mrg INC_POINTER(start);
406 1.10 mrg working = start;
407 1.10 mrg
408 1.10 mrg if (start == end) { /* only one char processed */
409 1.10 mrg state = INKEY_NORM;
410 1.10 mrg } else {/* otherwise we must have more than one char
411 1.10 mrg * to backout */
412 1.10 mrg state = INKEY_BACKOUT;
413 1.10 mrg }
414 1.10 mrg return k;
415 1.10 mrg } else { /* must be part of a multikey sequence */
416 1.10 mrg /* check for completed key sequence */
417 1.10 mrg if (current->key[current->mapping[k]]->type == KEYMAP_LEAF) {
418 1.10 mrg start = working; /* eat the key sequence
419 1.10 mrg * in inbuf */
420 1.10 mrg
421 1.12 pk /* check if inbuf empty now */
422 1.12 pk if (start == end) {
423 1.12 pk /* if it is go back to normal */
424 1.12 pk state = INKEY_NORM;
425 1.12 pk } else {
426 1.12 pk /* otherwise go to backout state */
427 1.10 mrg state = INKEY_BACKOUT;
428 1.10 mrg }
429 1.10 mrg
430 1.10 mrg /* return the symbol */
431 1.10 mrg return current->key[current->mapping[k]]->value.symbol;
432 1.10 mrg
433 1.12 pk } else {
434 1.12 pk /*
435 1.12 pk * Step on to next part of the multi-key
436 1.12 pk * sequence.
437 1.12 pk */
438 1.10 mrg current = current->key[current->mapping[k]]->value.next;
439 1.10 mrg }
440 1.10 mrg }
441 1.10 mrg }
442 1.10 mrg }
443 1.10 mrg
444 1.18 blymn #ifndef _CURSES_USE_MACROS
445 1.18 blymn /*
446 1.18 blymn * getch --
447 1.18 blymn * Read in a character from stdscr.
448 1.18 blymn */
449 1.18 blymn int
450 1.18 blymn getch(void)
451 1.18 blymn {
452 1.18 blymn return wgetch(stdscr);
453 1.18 blymn }
454 1.18 blymn
455 1.18 blymn /*
456 1.18 blymn * mvgetch --
457 1.18 blymn * Read in a character from stdscr at the given location.
458 1.18 blymn */
459 1.18 blymn int
460 1.18 blymn mvgetch(int y, int x)
461 1.18 blymn {
462 1.18 blymn return mvwgetch(stdscr, y, x);
463 1.18 blymn }
464 1.18 blymn
465 1.18 blymn /*
466 1.18 blymn * mvwgetch --
467 1.18 blymn * Read in a character from stdscr at the given location in the
468 1.18 blymn * given window.
469 1.18 blymn */
470 1.18 blymn int
471 1.18 blymn mvwgetch(WINDOW *win, int y, int x)
472 1.18 blymn {
473 1.18 blymn if (wmove(win, y, x) == ERR)
474 1.18 blymn return ERR;
475 1.18 blymn
476 1.18 blymn return wgetch(win);
477 1.18 blymn }
478 1.18 blymn
479 1.18 blymn #endif
480 1.18 blymn
481 1.1 cgd /*
482 1.4 mycroft * wgetch --
483 1.4 mycroft * Read in a character from the window.
484 1.1 cgd */
485 1.4 mycroft int
486 1.18 blymn wgetch(WINDOW *win)
487 1.4 mycroft {
488 1.10 mrg int inp, weset;
489 1.16 blymn ssize_t nchar;
490 1.10 mrg char c;
491 1.1 cgd
492 1.5 cgd if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
493 1.10 mrg && win->curx == win->maxx - 1 && win->cury == win->maxy - 1
494 1.10 mrg && __echoit)
495 1.4 mycroft return (ERR);
496 1.4 mycroft #ifdef DEBUG
497 1.5 cgd __CTRACE("wgetch: __echoit = %d, __rawmode = %d\n",
498 1.4 mycroft __echoit, __rawmode);
499 1.4 mycroft #endif
500 1.4 mycroft if (__echoit && !__rawmode) {
501 1.1 cgd cbreak();
502 1.4 mycroft weset = 1;
503 1.4 mycroft } else
504 1.4 mycroft weset = 0;
505 1.4 mycroft
506 1.10 mrg __save_termios();
507 1.10 mrg
508 1.10 mrg if (win->flags & __KEYPAD) {
509 1.10 mrg switch (win->delay)
510 1.10 mrg {
511 1.10 mrg case -1:
512 1.10 mrg inp = inkey (win->flags & __NOTIMEOUT ? 0 : 1, 0);
513 1.10 mrg break;
514 1.10 mrg case 0:
515 1.10 mrg if (__nodelay() == ERR) return ERR;
516 1.10 mrg inp = inkey(0, 0);
517 1.10 mrg break;
518 1.10 mrg default:
519 1.10 mrg inp = inkey(win->flags & __NOTIMEOUT ? 0 : 1, win->delay);
520 1.10 mrg break;
521 1.10 mrg }
522 1.10 mrg } else {
523 1.10 mrg switch (win->delay)
524 1.10 mrg {
525 1.10 mrg case -1:
526 1.10 mrg break;
527 1.10 mrg case 0:
528 1.10 mrg if (__nodelay() == ERR) {
529 1.10 mrg __restore_termios();
530 1.10 mrg return ERR;
531 1.10 mrg }
532 1.10 mrg break;
533 1.10 mrg default:
534 1.10 mrg if (__timeout(win->delay) == ERR) {
535 1.10 mrg __restore_termios();
536 1.10 mrg return ERR;
537 1.10 mrg }
538 1.10 mrg break;
539 1.10 mrg }
540 1.12 pk
541 1.12 pk if ((nchar = read(STDIN_FILENO, &c, sizeof(char))) < 0) {
542 1.10 mrg inp = ERR;
543 1.12 pk } else {
544 1.10 mrg if (nchar == 0) {
545 1.10 mrg __restore_termios();
546 1.10 mrg return ERR; /* we have timed out */
547 1.10 mrg }
548 1.10 mrg inp = (unsigned int) c;
549 1.10 mrg }
550 1.10 mrg }
551 1.4 mycroft #ifdef DEBUG
552 1.15 simonb if (inp > 255)
553 1.16 blymn /* we have a key symbol - treat it differently */
554 1.16 blymn /* XXXX perhaps __unctrl should be expanded to include
555 1.16 blymn * XXXX the keysyms in the table....
556 1.16 blymn */
557 1.15 simonb __CTRACE("wgetch assembled keysym 0x%x\n", inp);
558 1.15 simonb else
559 1.15 simonb __CTRACE("wgetch got '%s'\n", unctrl(inp));
560 1.4 mycroft #endif
561 1.12 pk if (win->delay > -1) {
562 1.10 mrg if (__delay() == ERR) {
563 1.10 mrg __restore_termios();
564 1.10 mrg return ERR;
565 1.10 mrg }
566 1.12 pk }
567 1.12 pk
568 1.10 mrg __restore_termios();
569 1.4 mycroft if (__echoit) {
570 1.4 mycroft mvwaddch(curscr,
571 1.16 blymn (int) (win->cury + win->begy), (int) (win->curx + win->begx), (chtype) inp);
572 1.16 blymn waddch(win, (chtype) inp);
573 1.1 cgd }
574 1.1 cgd if (weset)
575 1.1 cgd nocbreak();
576 1.12 pk
577 1.10 mrg return ((inp < 0) || (inp == ERR) ? ERR : inp);
578 1.1 cgd }
579