File: | src/lib/libcurses/base/lib_getch.c |
Warning: | line 361, column 2 Value stored to 'rc' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: lib_getch.c,v 1.11 2010/01/12 23:22:05 nicm Exp $ */ |
2 | |
3 | /**************************************************************************** |
4 | * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * |
5 | * * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a * |
7 | * copy of this software and associated documentation files (the * |
8 | * "Software"), to deal in the Software without restriction, including * |
9 | * without limitation the rights to use, copy, modify, merge, publish, * |
10 | * distribute, distribute with modifications, sublicense, and/or sell * |
11 | * copies of the Software, and to permit persons to whom the Software is * |
12 | * furnished to do so, subject to the following conditions: * |
13 | * * |
14 | * The above copyright notice and this permission notice shall be included * |
15 | * in all copies or substantial portions of the Software. * |
16 | * * |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
20 | * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
21 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
22 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
23 | * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
24 | * * |
25 | * Except as contained in this notice, the name(s) of the above copyright * |
26 | * holders shall not be used in advertising or otherwise to promote the * |
27 | * sale, use or other dealings in this Software without prior written * |
28 | * authorization. * |
29 | ****************************************************************************/ |
30 | |
31 | /**************************************************************************** |
32 | * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * |
33 | * and: Eric S. Raymond <esr@snark.thyrsus.com> * |
34 | * and: Thomas E. Dickey 1996-on * |
35 | ****************************************************************************/ |
36 | |
37 | /* |
38 | ** lib_getch.c |
39 | ** |
40 | ** The routine getch(). |
41 | ** |
42 | */ |
43 | |
44 | #include <curses.priv.h> |
45 | |
46 | MODULE_ID("$Id: lib_getch.c,v 1.11 2010/01/12 23:22:05 nicm Exp $") |
47 | |
48 | #include <fifo_defs.h> |
49 | |
50 | #if USE_REENTRANT0 |
51 | #define GetEscdelay(sp)ESCDELAY (sp)->_ESCDELAY |
52 | NCURSES_EXPORT(int)int |
53 | NCURSES_PUBLIC_VAR(ESCDELAY) (void) |
54 | { |
55 | return SP ? GetEscdelay(SP)ESCDELAY : 1000; |
56 | } |
57 | #else |
58 | #define GetEscdelay(sp)ESCDELAY ESCDELAY |
59 | NCURSES_EXPORT_VAR(int)int |
60 | ESCDELAY = 1000; /* max interval betw. chars in funkeys, in millisecs */ |
61 | #endif |
62 | |
63 | #if NCURSES_EXT_FUNCS20081102 |
64 | NCURSES_EXPORT(int)int |
65 | set_escdelay(int value) |
66 | { |
67 | int code = OK(0); |
68 | #if USE_REENTRANT0 |
69 | if (SP) { |
70 | SP->_ESCDELAY = value; |
71 | } else { |
72 | code = ERR(-1); |
73 | } |
74 | #else |
75 | ESCDELAY = value; |
76 | #endif |
77 | return code; |
78 | } |
79 | #endif |
80 | |
81 | static int |
82 | _nc_use_meta(WINDOW *win) |
83 | { |
84 | SCREEN *sp = _nc_screen_of(win); |
85 | return (sp ? sp->_use_meta : 0); |
86 | } |
87 | |
88 | #ifdef NCURSES_WGETCH_EVENTS |
89 | #define TWAIT_MASK3 7 |
90 | #else |
91 | #define TWAIT_MASK3 3 |
92 | #endif |
93 | |
94 | /* |
95 | * Check for mouse activity, returning nonzero if we find any. |
96 | */ |
97 | static int |
98 | check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl)) |
99 | { |
100 | int rc; |
101 | |
102 | #if USE_SYSMOUSE0 |
103 | if ((sp->_mouse_type == M_SYSMOUSE) |
104 | && (sp->_sysmouse_head < sp->_sysmouse_tail)) { |
105 | return 2; |
106 | } |
107 | #endif |
108 | rc = _nc_timed_wait(sp, TWAIT_MASK3, delay, (int *) 0 EVENTLIST_2nd(evl)); |
109 | #if USE_SYSMOUSE0 |
110 | if ((sp->_mouse_type == M_SYSMOUSE) |
111 | && (sp->_sysmouse_head < sp->_sysmouse_tail) |
112 | && (rc == 0) |
113 | && (errno(*__errno()) == EINTR4)) { |
114 | rc |= 2; |
115 | } |
116 | #endif |
117 | return rc; |
118 | } |
119 | |
120 | static NCURSES_INLINEinline int |
121 | fifo_peek(SCREEN *sp) |
122 | { |
123 | int ch = sp->_fifo[peeksp->_fifopeek]; |
124 | TR(TRACE_IEVENT, ("peeking at %d", peek)); |
125 | |
126 | p_inc(){ sp->_fifopeek == 135 +2 -1 ? sp->_fifopeek = 0 : sp-> _fifopeek++;}; |
127 | return ch; |
128 | } |
129 | |
130 | static NCURSES_INLINEinline int |
131 | fifo_pull(SCREEN *sp) |
132 | { |
133 | int ch; |
134 | ch = sp->_fifo[headsp->_fifohead]; |
135 | TR(TRACE_IEVENT, ("pulling %s from %d", _nc_tracechar(sp, ch), head)); |
136 | |
137 | if (peeksp->_fifopeek == headsp->_fifohead) { |
138 | h_inc(){ sp->_fifohead == 135 +2 -1 ? sp->_fifohead = 0 : sp-> _fifohead++; if (sp->_fifohead == sp->_fifotail) sp-> _fifohead = -1, sp->_fifotail = 0;}; |
139 | peeksp->_fifopeek = headsp->_fifohead; |
140 | } else |
141 | h_inc(){ sp->_fifohead == 135 +2 -1 ? sp->_fifohead = 0 : sp-> _fifohead++; if (sp->_fifohead == sp->_fifotail) sp-> _fifohead = -1, sp->_fifotail = 0;}; |
142 | |
143 | #ifdef TRACE |
144 | if (USE_TRACEF(TRACE_IEVENT0x0080)) { |
145 | _nc_fifo_dump(sp); |
146 | _nc_unlock_global(tracef); |
147 | } |
148 | #endif |
149 | return ch; |
150 | } |
151 | |
152 | static NCURSES_INLINEinline int |
153 | fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) |
154 | { |
155 | int n; |
156 | int ch = 0; |
157 | int mask = 0; |
158 | |
159 | (void) mask; |
160 | if (tailsp->_fifotail == -1) |
161 | return ERR(-1); |
162 | |
163 | #ifdef HIDE_EINTR |
164 | again: |
165 | errno(*__errno()) = 0; |
166 | #endif |
167 | |
168 | #ifdef NCURSES_WGETCH_EVENTS |
169 | if (evl |
170 | #if USE_GPM_SUPPORT0 || USE_EMX_MOUSE0 || USE_SYSMOUSE0 |
171 | || (sp->_mouse_fd >= 0) |
172 | #endif |
173 | ) { |
174 | mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl)); |
175 | } else |
176 | mask = 0; |
177 | |
178 | if (mask & 4) { |
179 | T(("fifo_push: ungetch KEY_EVENT")); |
180 | _nc_ungetch(sp, KEY_EVENT0633); |
181 | return KEY_EVENT0633; |
182 | } |
183 | #elif USE_GPM_SUPPORT0 || USE_EMX_MOUSE0 || USE_SYSMOUSE0 |
184 | if (sp->_mouse_fd >= 0) { |
185 | mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl)); |
186 | } |
187 | #endif |
188 | |
189 | #if USE_GPM_SUPPORT0 || USE_EMX_MOUSE0 |
190 | if ((sp->_mouse_fd >= 0) && (mask & 2)) { |
191 | sp->_mouse_event(sp); |
192 | ch = KEY_MOUSE0631; |
193 | n = 1; |
194 | } else |
195 | #endif |
196 | #if USE_SYSMOUSE0 |
197 | if ((sp->_mouse_type == M_SYSMOUSE) |
198 | && (sp->_sysmouse_head < sp->_sysmouse_tail)) { |
199 | sp->_mouse_event(sp); |
200 | ch = KEY_MOUSE0631; |
201 | n = 1; |
202 | } else if ((sp->_mouse_type == M_SYSMOUSE) |
203 | && (mask <= 0) && errno(*__errno()) == EINTR4) { |
204 | sp->_mouse_event(sp); |
205 | ch = KEY_MOUSE0631; |
206 | n = 1; |
207 | } else |
208 | #endif |
209 | { /* Can block... */ |
210 | unsigned char c2 = 0; |
211 | n = read(sp->_ifd, &c2, 1); |
212 | ch = c2; |
213 | } |
214 | |
215 | #ifdef HIDE_EINTR |
216 | /* |
217 | * Under System V curses with non-restarting signals, getch() returns |
218 | * with value ERR when a handled signal keeps it from completing. |
219 | * If signals restart system calls, OTOH, the signal is invisible |
220 | * except to its handler. |
221 | * |
222 | * We don't want this difference to show. This piece of code |
223 | * tries to make it look like we always have restarting signals. |
224 | */ |
225 | if (n <= 0 && errno(*__errno()) == EINTR4) |
226 | goto again; |
227 | #endif |
228 | |
229 | if ((n == -1) || (n == 0)) { |
230 | TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno)); |
231 | ch = ERR(-1); |
232 | } |
233 | TR(TRACE_IEVENT, ("read %d characters", n)); |
234 | |
235 | sp->_fifo[tailsp->_fifotail] = ch; |
236 | sp->_fifohold = 0; |
237 | if (headsp->_fifohead == -1) |
238 | headsp->_fifohead = peeksp->_fifopeek = tailsp->_fifotail; |
239 | t_inc(){ sp->_fifotail == 135 +2 -1 ? sp->_fifotail = 0 : sp-> _fifotail++; if (sp->_fifotail == sp->_fifohead) sp-> _fifotail = -1;}; |
240 | TR(TRACE_IEVENT, ("pushed %s at %d", _nc_tracechar(sp, ch), tail)); |
241 | #ifdef TRACE |
242 | if (USE_TRACEF(TRACE_IEVENT0x0080)) { |
243 | _nc_fifo_dump(sp); |
244 | _nc_unlock_global(tracef); |
245 | } |
246 | #endif |
247 | return ch; |
248 | } |
249 | |
250 | static NCURSES_INLINEinline void |
251 | fifo_clear(SCREEN *sp) |
252 | { |
253 | memset(sp->_fifo, 0, sizeof(sp->_fifo)); |
254 | headsp->_fifohead = -1; |
255 | tailsp->_fifotail = peeksp->_fifopeek = 0; |
256 | } |
257 | |
258 | static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl)); |
259 | |
260 | static void |
261 | recur_wrefresh(WINDOW *win) |
262 | { |
263 | #ifdef USE_PTHREADS |
264 | SCREEN *sp = _nc_screen_of(win); |
265 | if (_nc_use_pthreads && sp != SP) { |
266 | SCREEN *save_SP; |
267 | |
268 | /* temporarily switch to the window's screen to check/refresh */ |
269 | _nc_lock_global(curses); |
270 | save_SP = SP; |
271 | _nc_set_screen(sp)SP = sp; |
272 | recur_wrefresh(win); |
273 | _nc_set_screen(save_SP)SP = save_SP; |
274 | _nc_unlock_global(curses); |
275 | } else |
276 | #endif |
277 | if ((is_wintouched(win) || (win->_flags & _HASMOVED0x20)) |
278 | && !(win->_flags & _ISPAD0x10)) { |
279 | wrefresh(win); |
280 | } |
281 | } |
282 | |
283 | static int |
284 | recur_wgetnstr(WINDOW *win, char *buf) |
285 | { |
286 | SCREEN *sp = _nc_screen_of(win); |
287 | int rc; |
288 | |
289 | if (sp != 0) { |
290 | #ifdef USE_PTHREADS |
291 | if (_nc_use_pthreads && sp != SP) { |
292 | SCREEN *save_SP; |
293 | |
294 | /* temporarily switch to the window's screen to get cooked input */ |
295 | _nc_lock_global(curses); |
296 | save_SP = SP; |
297 | _nc_set_screen(sp)SP = sp; |
298 | rc = recur_wgetnstr(win, buf); |
299 | _nc_set_screen(save_SP)SP = save_SP; |
300 | _nc_unlock_global(curses); |
301 | } else |
302 | #endif |
303 | { |
304 | sp->_called_wgetch = TRUE1; |
305 | rc = wgetnstr(win, buf, MAXCOLUMNS135); |
306 | sp->_called_wgetch = FALSE0; |
307 | } |
308 | } else { |
309 | rc = ERR(-1); |
310 | } |
311 | return rc; |
312 | } |
313 | |
314 | NCURSES_EXPORT(int)int |
315 | _nc_wgetch(WINDOW *win, |
316 | unsigned long *result, |
317 | int use_meta |
318 | EVENTLIST_2nd(_nc_eventlist * evl)) |
319 | { |
320 | SCREEN *sp; |
321 | int ch; |
322 | #ifdef NCURSES_WGETCH_EVENTS |
323 | long event_delay = -1; |
324 | #endif |
325 | |
326 | T((T_CALLED("_nc_wgetch(%p)"), win)); |
327 | |
328 | *result = 0; |
329 | |
330 | sp = _nc_screen_of(win); |
331 | if (win == 0 || sp == 0) { |
332 | returnCode(ERR)return (-1); |
333 | } |
334 | |
335 | if (cooked_key_in_fifo()((sp->_fifohead != -1) && (sp->_fifopeek != sp-> _fifohead))) { |
336 | recur_wrefresh(win); |
337 | *result = fifo_pull(sp); |
338 | returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK)return *result >= 0401 ? 0400 : (0); |
339 | } |
340 | #ifdef NCURSES_WGETCH_EVENTS |
341 | if (evl && (evl->count == 0)) |
342 | evl = NULL((void*)0); |
343 | event_delay = _nc_eventlist_timeout(evl); |
344 | #endif |
345 | |
346 | /* |
347 | * Handle cooked mode. Grab a string from the screen, |
348 | * stuff its contents in the FIFO queue, and pop off |
349 | * the first character to return it. |
350 | */ |
351 | if (headsp->_fifohead == -1 && |
352 | !sp->_notty && |
353 | !sp->_raw && |
354 | !sp->_cbreak && |
355 | !sp->_called_wgetch) { |
356 | char buf[MAXCOLUMNS135], *bufp; |
357 | int rc; |
358 | |
359 | TR(TRACE_IEVENT, ("filling queue in cooked mode")); |
360 | |
361 | rc = recur_wgetnstr(win, buf); |
Value stored to 'rc' is never read | |
362 | |
363 | /* ungetch in reverse order */ |
364 | #ifdef NCURSES_WGETCH_EVENTS |
365 | if (rc != KEY_EVENT0633) |
366 | #endif |
367 | _nc_ungetch(sp, '\n'); |
368 | for (bufp = buf + strlen(buf); bufp > buf; bufp--) |
369 | _nc_ungetch(sp, bufp[-1]); |
370 | |
371 | #ifdef NCURSES_WGETCH_EVENTS |
372 | /* Return it first */ |
373 | if (rc == KEY_EVENT0633) { |
374 | *result = rc; |
375 | } else |
376 | #endif |
377 | *result = fifo_pull(sp); |
378 | returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK)return *result >= 0401 ? 0400 : (0); |
379 | } |
380 | |
381 | if (win->_use_keypad != sp->_keypad_on) |
382 | _nc_keypad(sp, win->_use_keypad); |
383 | |
384 | recur_wrefresh(win); |
385 | |
386 | if (win->_notimeout || (win->_delay >= 0) || (sp->_cbreak > 1)) { |
387 | if (headsp->_fifohead == -1) { /* fifo is empty */ |
388 | int delay; |
389 | int rc; |
390 | |
391 | TR(TRACE_IEVENT, ("timed delay in wgetch()")); |
392 | if (sp->_cbreak > 1) |
393 | delay = (sp->_cbreak - 1) * 100; |
394 | else |
395 | delay = win->_delay; |
396 | |
397 | #ifdef NCURSES_WGETCH_EVENTS |
398 | if (event_delay >= 0 && delay > event_delay) |
399 | delay = event_delay; |
400 | #endif |
401 | |
402 | TR(TRACE_IEVENT, ("delay is %d milliseconds", delay)); |
403 | |
404 | rc = check_mouse_activity(sp, delay EVENTLIST_2nd(evl)); |
405 | |
406 | #ifdef NCURSES_WGETCH_EVENTS |
407 | if (rc & 4) { |
408 | *result = KEY_EVENT0633; |
409 | returnCode(KEY_CODE_YES)return 0400; |
410 | } |
411 | #endif |
412 | if (!rc) { |
413 | returnCode(ERR)return (-1); |
414 | } |
415 | } |
416 | /* else go on to read data available */ |
417 | } |
418 | |
419 | if (win->_use_keypad) { |
420 | /* |
421 | * This is tricky. We only want to get special-key |
422 | * events one at a time. But we want to accumulate |
423 | * mouse events until either (a) the mouse logic tells |
424 | * us it's picked up a complete gesture, or (b) |
425 | * there's a detectable time lapse after one. |
426 | * |
427 | * Note: if the mouse code starts failing to compose |
428 | * press/release events into clicks, you should probably |
429 | * increase the wait with mouseinterval(). |
430 | */ |
431 | int runcount = 0; |
432 | int rc; |
433 | |
434 | do { |
435 | ch = kgetch(sp EVENTLIST_2nd(evl)); |
436 | if (ch == KEY_MOUSE0631) { |
437 | ++runcount; |
438 | if (sp->_mouse_inline(sp)) |
439 | break; |
440 | } |
441 | if (sp->_maxclick < 0) |
442 | break; |
443 | } while |
444 | (ch == KEY_MOUSE0631 |
445 | && (((rc = check_mouse_activity(sp, sp->_maxclick |
446 | EVENTLIST_2nd(evl))) != 0 |
447 | && !(rc & 4)) |
448 | || !sp->_mouse_parse(sp, runcount))); |
449 | #ifdef NCURSES_WGETCH_EVENTS |
450 | if ((rc & 4) && !ch == KEY_EVENT0633) { |
451 | _nc_ungetch(sp, ch); |
452 | ch = KEY_EVENT0633; |
453 | } |
454 | #endif |
455 | if (runcount > 0 && ch != KEY_MOUSE0631) { |
456 | #ifdef NCURSES_WGETCH_EVENTS |
457 | /* mouse event sequence ended by an event, report event */ |
458 | if (ch == KEY_EVENT0633) { |
459 | _nc_ungetch(sp, KEY_MOUSE0631); /* FIXME This interrupts a gesture... */ |
460 | } else |
461 | #endif |
462 | { |
463 | /* mouse event sequence ended by keystroke, store keystroke */ |
464 | _nc_ungetch(sp, ch); |
465 | ch = KEY_MOUSE0631; |
466 | } |
467 | } |
468 | } else { |
469 | if (headsp->_fifohead == -1) |
470 | fifo_push(sp EVENTLIST_2nd(evl)); |
471 | ch = fifo_pull(sp); |
472 | } |
473 | |
474 | if (ch == ERR(-1)) { |
475 | #if USE_SIZECHANGE1 |
476 | if (_nc_handle_sigwinch(sp)) { |
477 | _nc_update_screensize(sp); |
478 | /* resizeterm can push KEY_RESIZE */ |
479 | if (cooked_key_in_fifo()((sp->_fifohead != -1) && (sp->_fifopeek != sp-> _fifohead))) { |
480 | *result = fifo_pull(sp); |
481 | returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK)return *result >= 0401 ? 0400 : (0); |
482 | } |
483 | } |
484 | #endif |
485 | returnCode(ERR)return (-1); |
486 | } |
487 | |
488 | /* |
489 | * If echo() is in effect, display the printable version of the |
490 | * key on the screen. Carriage return and backspace are treated |
491 | * specially by Solaris curses: |
492 | * |
493 | * If carriage return is defined as a function key in the |
494 | * terminfo, e.g., kent, then Solaris may return either ^J (or ^M |
495 | * if nonl() is set) or KEY_ENTER depending on the echo() mode. |
496 | * We echo before translating carriage return based on nonl(), |
497 | * since the visual result simply moves the cursor to column 0. |
498 | * |
499 | * Backspace is a different matter. Solaris curses does not |
500 | * translate it to KEY_BACKSPACE if kbs=^H. This does not depend |
501 | * on the stty modes, but appears to be a hardcoded special case. |
502 | * This is a difference from ncurses, which uses the terminfo entry. |
503 | * However, we provide the same visual result as Solaris, moving the |
504 | * cursor to the left. |
505 | */ |
506 | if (sp->_echo && !(win->_flags & _ISPAD0x10)) { |
507 | chtype backup = (ch == KEY_BACKSPACE0407) ? '\b' : ch; |
508 | if (backup < KEY_MIN0401) |
509 | wechochar(win, backup); |
510 | } |
511 | |
512 | /* |
513 | * Simulate ICRNL mode |
514 | */ |
515 | if ((ch == '\r') && sp->_nl) |
516 | ch = '\n'; |
517 | |
518 | /* Strip 8th-bit if so desired. We do this only for characters that |
519 | * are in the range 128-255, to provide compatibility with terminals |
520 | * that display only 7-bit characters. Note that 'ch' may be a |
521 | * function key at this point, so we mustn't strip _those_. |
522 | */ |
523 | if (!use_meta) |
524 | if ((ch < KEY_MIN0401) && (ch & 0x80)) |
525 | ch &= 0x7f; |
526 | |
527 | T(("wgetch returning : %s", _nc_tracechar(sp, ch))); |
528 | |
529 | *result = ch; |
530 | returnCode(ch >= KEY_MIN ? KEY_CODE_YES : OK)return ch >= 0401 ? 0400 : (0); |
531 | } |
532 | |
533 | #ifdef NCURSES_WGETCH_EVENTS |
534 | NCURSES_EXPORT(int)int |
535 | wgetch_events(WINDOW *win, _nc_eventlist * evl)wgetch(WINDOW *win) |
536 | { |
537 | int code; |
538 | unsigned long value; |
539 | |
540 | T((T_CALLED("wgetch_events(%p,%p)"), win, evl)); |
541 | code = _nc_wgetch(win, |
542 | &value, |
543 | _nc_use_meta(win) |
544 | EVENTLIST_2nd(evl)); |
545 | if (code != ERR(-1)) |
546 | code = value; |
547 | returnCode(code)return code; |
548 | } |
549 | #endif |
550 | |
551 | NCURSES_EXPORT(int)int |
552 | wgetch(WINDOW *win) |
553 | { |
554 | int code; |
555 | unsigned long value; |
556 | |
557 | T((T_CALLED("wgetch(%p)"), win)); |
558 | code = _nc_wgetch(win, |
559 | &value, |
560 | _nc_use_meta(win) |
561 | EVENTLIST_2nd((_nc_eventlist *) 0)); |
562 | if (code != ERR(-1)) |
563 | code = value; |
564 | returnCode(code)return code; |
565 | } |
566 | |
567 | /* |
568 | ** int |
569 | ** kgetch() |
570 | ** |
571 | ** Get an input character, but take care of keypad sequences, returning |
572 | ** an appropriate code when one matches the input. After each character |
573 | ** is received, set an alarm call based on ESCDELAY. If no more of the |
574 | ** sequence is received by the time the alarm goes off, pass through |
575 | ** the sequence gotten so far. |
576 | ** |
577 | ** This function must be called when there are no cooked keys in queue. |
578 | ** (that is head==-1 || peek==head) |
579 | ** |
580 | */ |
581 | |
582 | static int |
583 | kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) |
584 | { |
585 | TRIES *ptr; |
586 | int ch = 0; |
587 | int timeleft = GetEscdelay(sp)ESCDELAY; |
588 | |
589 | TR(TRACE_IEVENT, ("kgetch() called")); |
590 | |
591 | ptr = sp->_keytry; |
592 | |
593 | for (;;) { |
594 | if (cooked_key_in_fifo()((sp->_fifohead != -1) && (sp->_fifopeek != sp-> _fifohead)) && sp->_fifo[headsp->_fifohead] >= KEY_MIN0401) { |
595 | break; |
596 | } else if (!raw_key_in_fifo()((sp->_fifohead != -1) && (sp->_fifopeek != sp-> _fifotail))) { |
597 | ch = fifo_push(sp EVENTLIST_2nd(evl)); |
598 | if (ch == ERR(-1)) { |
599 | peeksp->_fifopeek = headsp->_fifohead; /* the keys stay uninterpreted */ |
600 | return ERR(-1); |
601 | } |
602 | #ifdef NCURSES_WGETCH_EVENTS |
603 | else if (ch == KEY_EVENT0633) { |
604 | peeksp->_fifopeek = headsp->_fifohead; /* the keys stay uninterpreted */ |
605 | return fifo_pull(sp); /* Remove KEY_EVENT from the queue */ |
606 | } |
607 | #endif |
608 | } |
609 | |
610 | ch = fifo_peek(sp); |
611 | if (ch >= KEY_MIN0401) { |
612 | /* If not first in queue, somebody put this key there on purpose in |
613 | * emergency. Consider it higher priority than the unfinished |
614 | * keysequence we are parsing. |
615 | */ |
616 | peeksp->_fifopeek = headsp->_fifohead; |
617 | /* assume the key is the last in fifo */ |
618 | t_dec(){ sp->_fifotail == 0 ? sp->_fifotail = 135 +2 -1 : sp-> _fifotail--; if (sp->_fifohead == sp->_fifotail) fifo_clear (sp);}; /* remove the key */ |
619 | return ch; |
620 | } |
621 | |
622 | TR(TRACE_IEVENT, ("ch: %s", _nc_tracechar(sp, (unsigned char) ch))); |
623 | while ((ptr != NULL((void*)0)) && (ptr->ch != (unsigned char) ch)) |
624 | ptr = ptr->sibling; |
625 | |
626 | if (ptr == NULL((void*)0)) { |
627 | TR(TRACE_IEVENT, ("ptr is null")); |
628 | break; |
629 | } |
630 | TR(TRACE_IEVENT, ("ptr=%p, ch=%d, value=%d", |
631 | ptr, ptr->ch, ptr->value)); |
632 | |
633 | if (ptr->value != 0) { /* sequence terminated */ |
634 | TR(TRACE_IEVENT, ("end of sequence")); |
635 | if (peeksp->_fifopeek == tailsp->_fifotail) |
636 | fifo_clear(sp); |
637 | else |
638 | headsp->_fifohead = peeksp->_fifopeek; |
639 | return (ptr->value); |
640 | } |
641 | |
642 | ptr = ptr->child; |
643 | |
644 | if (!raw_key_in_fifo()((sp->_fifohead != -1) && (sp->_fifopeek != sp-> _fifotail))) { |
645 | int rc; |
646 | |
647 | TR(TRACE_IEVENT, ("waiting for rest of sequence")); |
648 | rc = check_mouse_activity(sp, timeleft EVENTLIST_2nd(evl)); |
649 | #ifdef NCURSES_WGETCH_EVENTS |
650 | if (rc & 4) { |
651 | TR(TRACE_IEVENT, ("interrupted by a user event")); |
652 | /* FIXME Should have preserved remainder timeleft for reuse... */ |
653 | peeksp->_fifopeek = headsp->_fifohead; /* Restart interpreting later */ |
654 | return KEY_EVENT0633; |
655 | } |
656 | #endif |
657 | if (!rc) { |
658 | TR(TRACE_IEVENT, ("ran out of time")); |
659 | break; |
660 | } |
661 | } |
662 | } |
663 | ch = fifo_pull(sp); |
664 | peeksp->_fifopeek = headsp->_fifohead; |
665 | return ch; |
666 | } |