Bug Summary

File:src/lib/libcurses/base/lib_getch.c
Warning:line 361, column 2
Value stored to 'rc' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lib_getch.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcurses/obj -resource-dir /usr/local/lib/clang/13.0.0 -I . -I /usr/src/lib/libcurses -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcurses/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libcurses/base/lib_getch.c
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
46MODULE_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
52NCURSES_EXPORT(int)int
53NCURSES_PUBLIC_VAR(ESCDELAY) (void)
54{
55 return SP ? GetEscdelay(SP)ESCDELAY : 1000;
56}
57#else
58#define GetEscdelay(sp)ESCDELAY ESCDELAY
59NCURSES_EXPORT_VAR(int)int
60ESCDELAY = 1000; /* max interval betw. chars in funkeys, in millisecs */
61#endif
62
63#if NCURSES_EXT_FUNCS20081102
64NCURSES_EXPORT(int)int
65set_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
81static 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 */
97static int
98check_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
120static NCURSES_INLINEinline int
121fifo_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
130static NCURSES_INLINEinline int
131fifo_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
152static NCURSES_INLINEinline int
153fifo_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
250static NCURSES_INLINEinline void
251fifo_clear(SCREEN *sp)
252{
253 memset(sp->_fifo, 0, sizeof(sp->_fifo));
254 headsp->_fifohead = -1;
255 tailsp->_fifotail = peeksp->_fifopeek = 0;
256}
257
258static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl));
259
260static void
261recur_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
283static int
284recur_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
314NCURSES_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
534NCURSES_EXPORT(int)int
535wgetch_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
551NCURSES_EXPORT(int)int
552wgetch(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
582static int
583kgetch(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}