10e3d5408SPeter Wemm /****************************************************************************
2d8977eafSRong-En Fan * Copyright 2018-2019,2020 Thomas E. Dickey *
30e3d5408SPeter Wemm * Copyright 1998-2015,2016 Free Software Foundation, Inc. *
40e3d5408SPeter Wemm * *
50e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a *
60e3d5408SPeter Wemm * copy of this software and associated documentation files (the *
70e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including *
80e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, *
90e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell *
100e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is *
110e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: *
120e3d5408SPeter Wemm * *
130e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included *
140e3d5408SPeter Wemm * in all copies or substantial portions of the Software. *
150e3d5408SPeter Wemm * *
160e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
170e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
180e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
190e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
200e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
210e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
220e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
230e3d5408SPeter Wemm * *
240e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright *
250e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the *
260e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written *
270e3d5408SPeter Wemm * authorization. *
280e3d5408SPeter Wemm ****************************************************************************/
290e3d5408SPeter Wemm
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
324a1a9510SRong-En Fan * and: Eric S. Raymond <esr@snark.thyrsus.com> *
330e3d5408SPeter Wemm * and: Thomas E. Dickey 1996-on *
340e3d5408SPeter Wemm * and: Juergen Pfeifer 2009 *
350e3d5408SPeter Wemm ****************************************************************************/
360e3d5408SPeter Wemm
370e3d5408SPeter Wemm /*
380e3d5408SPeter Wemm ** lib_getch.c
390e3d5408SPeter Wemm **
400e3d5408SPeter Wemm ** The routine getch().
410e3d5408SPeter Wemm **
420e3d5408SPeter Wemm */
430e3d5408SPeter Wemm
445d08fb1fSRong-En Fan #define NEED_KEY_EVENT
450e3d5408SPeter Wemm #include <curses.priv.h>
460e3d5408SPeter Wemm
470e3d5408SPeter Wemm MODULE_ID("$Id: lib_getch.c,v 1.141 2020/09/05 22:50:47 tom Exp $")
485ca44d1cSRong-En Fan
49aa59d4d4SRong-En Fan #include <fifo_defs.h>
505ca44d1cSRong-En Fan
515ca44d1cSRong-En Fan #if USE_REENTRANT
525ca44d1cSRong-En Fan #define GetEscdelay(sp) *_nc_ptr_Escdelay(sp)
NCURSES_EXPORT(int)53aa59d4d4SRong-En Fan NCURSES_EXPORT(int)
545ca44d1cSRong-En Fan NCURSES_PUBLIC_VAR(ESCDELAY) (void)
555ca44d1cSRong-En Fan {
56aa59d4d4SRong-En Fan return *(_nc_ptr_Escdelay(CURRENT_SCREEN));
577a69bbfbSPeter Wemm }
587a69bbfbSPeter Wemm
595ca44d1cSRong-En Fan NCURSES_EXPORT(int *)
_nc_ptr_Escdelay(SCREEN * sp)600e3d5408SPeter Wemm _nc_ptr_Escdelay(SCREEN *sp)
61d8977eafSRong-En Fan {
62d8977eafSRong-En Fan return ptrEscdelay(sp);
63d8977eafSRong-En Fan }
64d8977eafSRong-En Fan #else
65d8977eafSRong-En Fan #define GetEscdelay(sp) ESCDELAY
66d8977eafSRong-En Fan NCURSES_EXPORT_VAR(int) ESCDELAY = 1000;
67d8977eafSRong-En Fan #endif
68d8977eafSRong-En Fan
69d8977eafSRong-En Fan #if NCURSES_EXT_FUNCS
70d8977eafSRong-En Fan NCURSES_EXPORT(int)
NCURSES_SP_NAME(set_escdelay)71d8977eafSRong-En Fan NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value)
72d8977eafSRong-En Fan {
73d8977eafSRong-En Fan int code = OK;
74d8977eafSRong-En Fan if (value < 0) {
75d8977eafSRong-En Fan code = ERR;
76d8977eafSRong-En Fan } else {
77d8977eafSRong-En Fan #if USE_REENTRANT
78d8977eafSRong-En Fan if (SP_PARM) {
795d08fb1fSRong-En Fan SET_ESCDELAY(value);
805d08fb1fSRong-En Fan } else {
815d08fb1fSRong-En Fan code = ERR;
825d08fb1fSRong-En Fan }
835d08fb1fSRong-En Fan #else
845d08fb1fSRong-En Fan (void) SP_PARM;
855d08fb1fSRong-En Fan ESCDELAY = value;
864a1a9510SRong-En Fan #endif
874a1a9510SRong-En Fan }
884a1a9510SRong-En Fan return code;
894a1a9510SRong-En Fan }
904a1a9510SRong-En Fan
914a1a9510SRong-En Fan #if NCURSES_SP_FUNCS
924a1a9510SRong-En Fan NCURSES_EXPORT(int)
set_escdelay(int value)934a1a9510SRong-En Fan set_escdelay(int value)
944a1a9510SRong-En Fan {
954a1a9510SRong-En Fan int code;
96aa59d4d4SRong-En Fan if (value < 0) {
974a1a9510SRong-En Fan code = ERR;
984a1a9510SRong-En Fan } else {
994a1a9510SRong-En Fan #if USE_REENTRANT
1004a1a9510SRong-En Fan code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value);
101aa59d4d4SRong-En Fan #else
102aa59d4d4SRong-En Fan ESCDELAY = value;
1034a1a9510SRong-En Fan code = OK;
1044a1a9510SRong-En Fan #endif
1054a1a9510SRong-En Fan }
106aa59d4d4SRong-En Fan return code;
1074a1a9510SRong-En Fan }
108aa59d4d4SRong-En Fan #endif
109aa59d4d4SRong-En Fan #endif /* NCURSES_EXT_FUNCS */
1104a1a9510SRong-En Fan
1114a1a9510SRong-En Fan #if NCURSES_EXT_FUNCS
1124a1a9510SRong-En Fan NCURSES_EXPORT(int)
NCURSES_SP_NAME(get_escdelay)1134a1a9510SRong-En Fan NCURSES_SP_NAME(get_escdelay) (NCURSES_SP_DCL0)
1144a1a9510SRong-En Fan {
1154a1a9510SRong-En Fan #if !USE_REENTRANT
1164a1a9510SRong-En Fan (void) SP_PARM;
1174a1a9510SRong-En Fan #endif
1184a1a9510SRong-En Fan return GetEscdelay(SP_PARM);
119aa59d4d4SRong-En Fan }
1200e3d5408SPeter Wemm
121aa59d4d4SRong-En Fan #if NCURSES_SP_FUNCS
12218259542SPeter Wemm NCURSES_EXPORT(int)
get_escdelay(void)1230e3d5408SPeter Wemm get_escdelay(void)
1240e3d5408SPeter Wemm {
1250e3d5408SPeter Wemm return NCURSES_SP_NAME(get_escdelay) (CURRENT_SCREEN);
1260e3d5408SPeter Wemm }
1270e3d5408SPeter Wemm #endif
1284a1a9510SRong-En Fan #endif /* NCURSES_EXT_FUNCS */
129aa59d4d4SRong-En Fan
1300e3d5408SPeter Wemm static int
_nc_use_meta(WINDOW * win)1310e3d5408SPeter Wemm _nc_use_meta(WINDOW *win)
132aa59d4d4SRong-En Fan {
1335d08fb1fSRong-En Fan SCREEN *sp = _nc_screen_of(win);
1340e3d5408SPeter Wemm return (sp ? sp->_use_meta : 0);
13515589c42SPeter Wemm }
1360e3d5408SPeter Wemm
1370e3d5408SPeter Wemm #ifdef USE_TERM_DRIVER
13815589c42SPeter Wemm # if defined(_NC_WINDOWS) && !defined(EXP_WIN32_DRIVER)
1390e3d5408SPeter Wemm static HANDLE
_nc_get_handle(int fd)1400e3d5408SPeter Wemm _nc_get_handle(int fd)
1410e3d5408SPeter Wemm {
1425ca44d1cSRong-En Fan intptr_t value = _get_osfhandle(fd);
143aa59d4d4SRong-En Fan return (HANDLE) value;
1445ca44d1cSRong-En Fan }
1455ca44d1cSRong-En Fan # endif
1460e3d5408SPeter Wemm #endif
1470e3d5408SPeter Wemm
1480e3d5408SPeter Wemm /*
1490e3d5408SPeter Wemm * Check for mouse activity, returning nonzero if we find any.
1504a1a9510SRong-En Fan */
151aa59d4d4SRong-En Fan static int
check_mouse_activity(SCREEN * sp,int delay EVENTLIST_2nd (_nc_eventlist * evl))1520e3d5408SPeter Wemm check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl))
1530e3d5408SPeter Wemm {
1544a1a9510SRong-En Fan int rc;
1554a1a9510SRong-En Fan
1560e3d5408SPeter Wemm #ifdef USE_TERM_DRIVER
1574a1a9510SRong-En Fan TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp);
15815589c42SPeter Wemm rc = TCBOf(sp)->drv->td_testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl));
15915589c42SPeter Wemm # if defined(EXP_WIN32_DRIVER)
1600e3d5408SPeter Wemm /* if we emulate terminfo on console, we have to use the console routine */
1610e3d5408SPeter Wemm if (IsTermInfoOnConsole(sp)) {
1620e3d5408SPeter Wemm rc = _nc_console_testmouse(sp,
1630e3d5408SPeter Wemm _nc_console_handle(sp->_ifd),
1640e3d5408SPeter Wemm delay EVENTLIST_2nd(evl));
1650e3d5408SPeter Wemm } else
1664a1a9510SRong-En Fan # elif defined(_NC_WINDOWS)
1674a1a9510SRong-En Fan /* if we emulate terminfo on console, we have to use the console routine */
1684a1a9510SRong-En Fan if (IsTermInfoOnConsole(sp)) {
169aa59d4d4SRong-En Fan HANDLE fd = _nc_get_handle(sp->_ifd);
1704a1a9510SRong-En Fan rc = _nc_mingw_testmouse(sp, fd, delay EVENTLIST_2nd(evl));
1714a1a9510SRong-En Fan } else
172aa59d4d4SRong-En Fan # endif
1734a1a9510SRong-En Fan rc = TCB->drv->td_testmouse(TCB, delay EVENTLIST_2nd(evl));
1744a1a9510SRong-En Fan #else /* !USE_TERM_DRIVER */
1754a1a9510SRong-En Fan # if USE_SYSMOUSE
1764a1a9510SRong-En Fan if ((sp->_mouse_type == M_SYSMOUSE)
1774a1a9510SRong-En Fan && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
178aa59d4d4SRong-En Fan rc = TW_MOUSE;
1794a1a9510SRong-En Fan } else
1804a1a9510SRong-En Fan # endif
1814a1a9510SRong-En Fan {
182aa59d4d4SRong-En Fan # if defined(EXP_WIN32_DRIVER)
183aa59d4d4SRong-En Fan rc = _nc_console_testmouse(sp,
1844a1a9510SRong-En Fan _nc_console_handle(sp->_ifd),
1854a1a9510SRong-En Fan delay
1864a1a9510SRong-En Fan EVENTLIST_2nd(evl));
1874a1a9510SRong-En Fan # else
188aa59d4d4SRong-En Fan rc = _nc_timed_wait(sp,
189aa59d4d4SRong-En Fan TWAIT_MASK,
1900e3d5408SPeter Wemm delay,
1910e3d5408SPeter Wemm (int *) 0
1920e3d5408SPeter Wemm EVENTLIST_2nd(evl));
1930e3d5408SPeter Wemm # endif
1944a1a9510SRong-En Fan # if USE_SYSMOUSE
195aa59d4d4SRong-En Fan if ((sp->_mouse_type == M_SYSMOUSE)
196aa59d4d4SRong-En Fan && (sp->_sysmouse_head < sp->_sysmouse_tail)
197aa59d4d4SRong-En Fan && (rc == 0)
1984a1a9510SRong-En Fan && (errno == EINTR)) {
1994a1a9510SRong-En Fan rc |= TW_MOUSE;
200aa59d4d4SRong-En Fan }
2014a1a9510SRong-En Fan # endif
202aa59d4d4SRong-En Fan }
2034a1a9510SRong-En Fan #endif /* USE_TERM_DRIVER */
2044a1a9510SRong-En Fan return rc;
2054a1a9510SRong-En Fan }
2064a1a9510SRong-En Fan
2074a1a9510SRong-En Fan static NCURSES_INLINE int
fifo_peek(SCREEN * sp)2080e3d5408SPeter Wemm fifo_peek(SCREEN *sp)
209aa59d4d4SRong-En Fan {
21039f2269fSPeter Wemm int ch = (peek >= 0) ? sp->_fifo[peek] : ERR;
2110e3d5408SPeter Wemm TR(TRACE_IEVENT, ("peeking at %d", peek));
2120e3d5408SPeter Wemm
2130e3d5408SPeter Wemm p_inc();
2140e3d5408SPeter Wemm return ch;
2150e3d5408SPeter Wemm }
2160e3d5408SPeter Wemm
2170e3d5408SPeter Wemm static NCURSES_INLINE int
fifo_pull(SCREEN * sp)2180e3d5408SPeter Wemm fifo_pull(SCREEN *sp)
2190e3d5408SPeter Wemm {
2200e3d5408SPeter Wemm int ch = (head >= 0) ? sp->_fifo[head] : ERR;
2210e3d5408SPeter Wemm
2220e3d5408SPeter Wemm TR(TRACE_IEVENT, ("pulling %s from %d", _nc_tracechar(sp, ch), head));
2230e3d5408SPeter Wemm
2240e3d5408SPeter Wemm if (peek == head) {
2250e3d5408SPeter Wemm h_inc();
2260e3d5408SPeter Wemm peek = head;
22715589c42SPeter Wemm } else {
228aa59d4d4SRong-En Fan h_inc();
22918259542SPeter Wemm }
2300e3d5408SPeter Wemm
23118259542SPeter Wemm #ifdef TRACE
2320e3d5408SPeter Wemm if (USE_TRACEF(TRACE_IEVENT)) {
233aa59d4d4SRong-En Fan _nc_fifo_dump(sp);
234aa59d4d4SRong-En Fan _nc_unlock_global(tracef);
2350e3d5408SPeter Wemm }
2360e3d5408SPeter Wemm #endif
2370e3d5408SPeter Wemm return ch;
2385d08fb1fSRong-En Fan }
2390e3d5408SPeter Wemm
2405ca44d1cSRong-En Fan static NCURSES_INLINE int
fifo_push(SCREEN * sp EVENTLIST_2nd (_nc_eventlist * evl))241aa59d4d4SRong-En Fan fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl))
2425ca44d1cSRong-En Fan {
2435ca44d1cSRong-En Fan int n;
2440e3d5408SPeter Wemm int ch = 0;
2450e3d5408SPeter Wemm int mask = 0;
2460e3d5408SPeter Wemm
2470e3d5408SPeter Wemm (void) mask;
2484a1a9510SRong-En Fan if (tail < 0)
249aa59d4d4SRong-En Fan return ERR;
2500e3d5408SPeter Wemm
251aa59d4d4SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS
25215589c42SPeter Wemm if (evl
25315589c42SPeter Wemm #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
2540e3d5408SPeter Wemm || (sp->_mouse_fd >= 0)
2550e3d5408SPeter Wemm #endif
256aa59d4d4SRong-En Fan ) {
2570e3d5408SPeter Wemm mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl));
2585d08fb1fSRong-En Fan } else
2595d08fb1fSRong-En Fan mask = 0;
2605d08fb1fSRong-En Fan
2615d08fb1fSRong-En Fan if (mask & TW_EVENT) {
2625d08fb1fSRong-En Fan T(("fifo_push: ungetch KEY_EVENT"));
2635d08fb1fSRong-En Fan safe_ungetch(sp, KEY_EVENT);
2645d08fb1fSRong-En Fan return KEY_EVENT;
2655d08fb1fSRong-En Fan }
2665d08fb1fSRong-En Fan #elif USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE
2675d08fb1fSRong-En Fan if (sp->_mouse_fd >= 0) {
2685d08fb1fSRong-En Fan mask = check_mouse_activity(sp, -1 EVENTLIST_2nd(evl));
2695d08fb1fSRong-En Fan }
2705d08fb1fSRong-En Fan #endif
2715d08fb1fSRong-En Fan
2725d08fb1fSRong-En Fan #if USE_GPM_SUPPORT || USE_EMX_MOUSE
2735d08fb1fSRong-En Fan if ((sp->_mouse_fd >= 0) && (mask & TW_MOUSE)) {
2745d08fb1fSRong-En Fan sp->_mouse_event(sp);
2755d08fb1fSRong-En Fan ch = KEY_MOUSE;
2765d08fb1fSRong-En Fan n = 1;
2775d08fb1fSRong-En Fan } else
2785d08fb1fSRong-En Fan #endif
2795d08fb1fSRong-En Fan #if USE_SYSMOUSE
2805d08fb1fSRong-En Fan if ((sp->_mouse_type == M_SYSMOUSE)
2815d08fb1fSRong-En Fan && (sp->_sysmouse_head < sp->_sysmouse_tail)) {
2825d08fb1fSRong-En Fan sp->_mouse_event(sp);
2835d08fb1fSRong-En Fan ch = KEY_MOUSE;
2845d08fb1fSRong-En Fan n = 1;
2855d08fb1fSRong-En Fan } else if ((sp->_mouse_type == M_SYSMOUSE)
2865d08fb1fSRong-En Fan && (mask <= 0) && errno == EINTR) {
2875d08fb1fSRong-En Fan sp->_mouse_event(sp);
2885d08fb1fSRong-En Fan ch = KEY_MOUSE;
2895d08fb1fSRong-En Fan n = 1;
2905d08fb1fSRong-En Fan } else
2915d08fb1fSRong-En Fan #endif
2925d08fb1fSRong-En Fan #ifdef USE_TERM_DRIVER
2935d08fb1fSRong-En Fan if ((sp->_mouse_type == M_TERM_DRIVER)
2945d08fb1fSRong-En Fan && (sp->_drv_mouse_head < sp->_drv_mouse_tail)) {
2955d08fb1fSRong-En Fan sp->_mouse_event(sp);
2965d08fb1fSRong-En Fan ch = KEY_MOUSE;
2975d08fb1fSRong-En Fan n = 1;
2985d08fb1fSRong-En Fan } else
2995d08fb1fSRong-En Fan #endif
3005d08fb1fSRong-En Fan #if USE_KLIBC_KBD
3015d08fb1fSRong-En Fan if (NC_ISATTY(sp->_ifd) && sp->_cbreak) {
3025d08fb1fSRong-En Fan ch = _read_kbd(0, 1, !sp->_raw);
3035d08fb1fSRong-En Fan n = (ch == -1) ? -1 : 1;
3045d08fb1fSRong-En Fan sp->_extended_key = (ch == 0);
3055d08fb1fSRong-En Fan } else
3065d08fb1fSRong-En Fan #endif
3075d08fb1fSRong-En Fan { /* Can block... */
3085d08fb1fSRong-En Fan #if defined(USE_TERM_DRIVER)
3095d08fb1fSRong-En Fan int buf;
3105d08fb1fSRong-En Fan # if defined(EXP_WIN32_DRIVER)
3110e3d5408SPeter Wemm if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && sp->_cbreak) {
3127a69bbfbSPeter Wemm # if USE_PTHREADS_EINTR
3134a1a9510SRong-En Fan if ((pthread_self) && (pthread_kill) && (pthread_equal))
3144a1a9510SRong-En Fan _nc_globals.read_thread = pthread_self();
3154a1a9510SRong-En Fan # endif
3164a1a9510SRong-En Fan n = _nc_console_read(sp,
3170e3d5408SPeter Wemm _nc_console_handle(sp->_ifd),
3185d08fb1fSRong-En Fan &buf);
3190e3d5408SPeter Wemm # if USE_PTHREADS_EINTR
3204a1a9510SRong-En Fan _nc_globals.read_thread = 0;
3214a1a9510SRong-En Fan # endif
3224a1a9510SRong-En Fan } else
3230e3d5408SPeter Wemm # elif defined(_NC_WINDOWS)
3244a1a9510SRong-En Fan if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && sp->_cbreak)
3250e3d5408SPeter Wemm n = _nc_mingw_console_read(sp,
32639f2269fSPeter Wemm _nc_get_handle(sp->_ifd),
3275d08fb1fSRong-En Fan &buf);
3285d08fb1fSRong-En Fan else
329aa59d4d4SRong-En Fan # endif /* EXP_WIN32_DRIVER */
3300e3d5408SPeter Wemm n = CallDriver_1(sp, td_read, &buf);
3315ca44d1cSRong-En Fan ch = buf;
3320e3d5408SPeter Wemm #else /* !USE_TERM_DRIVER */
33315589c42SPeter Wemm #if defined(EXP_WIN32_DRIVER)
3345d08fb1fSRong-En Fan int buf;
335aa59d4d4SRong-En Fan #endif
3365ca44d1cSRong-En Fan unsigned char c2 = 0;
3370e3d5408SPeter Wemm #if USE_PTHREADS_EINTR
3384a1a9510SRong-En Fan #if USE_WEAK_SYMBOLS
3394a1a9510SRong-En Fan if ((pthread_self) && (pthread_kill) && (pthread_equal))
3404a1a9510SRong-En Fan #endif
3414a1a9510SRong-En Fan _nc_globals.read_thread = pthread_self();
3424a1a9510SRong-En Fan #endif
3430e3d5408SPeter Wemm #if defined(EXP_WIN32_DRIVER)
3440e3d5408SPeter Wemm n = _nc_console_read(sp,
3450e3d5408SPeter Wemm _nc_console_handle(sp->_ifd),
3460e3d5408SPeter Wemm &buf);
3470e3d5408SPeter Wemm c2 = buf;
3480e3d5408SPeter Wemm #else
3494a1a9510SRong-En Fan n = (int) read(sp->_ifd, &c2, (size_t) 1);
350aa59d4d4SRong-En Fan #endif
351aa59d4d4SRong-En Fan #if USE_PTHREADS_EINTR
352aa59d4d4SRong-En Fan _nc_globals.read_thread = 0;
353aa59d4d4SRong-En Fan #endif
354aa59d4d4SRong-En Fan ch = c2;
3554a1a9510SRong-En Fan #endif /* USE_TERM_DRIVER */
3560e3d5408SPeter Wemm }
35718259542SPeter Wemm
3580e3d5408SPeter Wemm if ((n == -1) || (n == 0)) {
3595d08fb1fSRong-En Fan TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno));
3600e3d5408SPeter Wemm ch = ERR;
3610e3d5408SPeter Wemm }
3624a1a9510SRong-En Fan TR(TRACE_IEVENT, ("read %d characters", n));
3634a1a9510SRong-En Fan
3644a1a9510SRong-En Fan sp->_fifo[tail] = ch;
365aa59d4d4SRong-En Fan sp->_fifohold = 0;
366aa59d4d4SRong-En Fan if (head == -1)
367aa59d4d4SRong-En Fan head = peek = tail;
3680e3d5408SPeter Wemm t_inc();
3694a1a9510SRong-En Fan TR(TRACE_IEVENT, ("pushed %s at %d", _nc_tracechar(sp, ch), tail));
3704a1a9510SRong-En Fan #ifdef TRACE
3714a1a9510SRong-En Fan if (USE_TRACEF(TRACE_IEVENT)) {
3724a1a9510SRong-En Fan _nc_fifo_dump(sp);
3735ca44d1cSRong-En Fan _nc_unlock_global(tracef);
3744a1a9510SRong-En Fan }
375aa59d4d4SRong-En Fan #endif
3765ca44d1cSRong-En Fan return ch;
3770e3d5408SPeter Wemm }
3780e3d5408SPeter Wemm
379aa59d4d4SRong-En Fan static NCURSES_INLINE void
fifo_clear(SCREEN * sp)380aa59d4d4SRong-En Fan fifo_clear(SCREEN *sp)
38139f2269fSPeter Wemm {
3825d08fb1fSRong-En Fan memset(sp->_fifo, 0, sizeof(sp->_fifo));
3830e3d5408SPeter Wemm head = -1;
3845d08fb1fSRong-En Fan tail = peek = 0;
3854a1a9510SRong-En Fan }
3860e3d5408SPeter Wemm
3874a1a9510SRong-En Fan static int kgetch(SCREEN *, bool EVENTLIST_2nd(_nc_eventlist *));
3880e3d5408SPeter Wemm
38918259542SPeter Wemm static void
recur_wrefresh(WINDOW * win)390aa59d4d4SRong-En Fan recur_wrefresh(WINDOW *win)
391aa59d4d4SRong-En Fan {
3920e3d5408SPeter Wemm #ifdef USE_PTHREADS
3930e3d5408SPeter Wemm SCREEN *sp = _nc_screen_of(win);
3940e3d5408SPeter Wemm if (_nc_use_pthreads && sp != CURRENT_SCREEN) {
3954a1a9510SRong-En Fan SCREEN *save_SP;
3964a1a9510SRong-En Fan
3974a1a9510SRong-En Fan /* temporarily switch to the window's screen to check/refresh */
3984a1a9510SRong-En Fan _nc_lock_global(curses);
3994a1a9510SRong-En Fan save_SP = CURRENT_SCREEN;
40018259542SPeter Wemm _nc_set_screen(sp);
4010e3d5408SPeter Wemm recur_wrefresh(win);
402aa59d4d4SRong-En Fan _nc_set_screen(save_SP);
4034a1a9510SRong-En Fan _nc_unlock_global(curses);
4044a1a9510SRong-En Fan } else
4054a1a9510SRong-En Fan #endif
4064a1a9510SRong-En Fan if ((is_wintouched(win) || (win->_flags & _HASMOVED))
4075ca44d1cSRong-En Fan && !(win->_flags & _ISPAD)) {
4084a1a9510SRong-En Fan wrefresh(win);
4094a1a9510SRong-En Fan }
4105d08fb1fSRong-En Fan }
4110e3d5408SPeter Wemm
4124a1a9510SRong-En Fan static int
recur_wgetnstr(WINDOW * win,char * buf)4135d08fb1fSRong-En Fan recur_wgetnstr(WINDOW *win, char *buf)
4140e3d5408SPeter Wemm {
4150e3d5408SPeter Wemm SCREEN *sp = _nc_screen_of(win);
4160e3d5408SPeter Wemm int rc;
41715589c42SPeter Wemm
4180e3d5408SPeter Wemm if (sp != 0) {
4190e3d5408SPeter Wemm #ifdef USE_PTHREADS
4200e3d5408SPeter Wemm if (_nc_use_pthreads && sp != CURRENT_SCREEN) {
4210e3d5408SPeter Wemm SCREEN *save_SP;
4220e3d5408SPeter Wemm
4230e3d5408SPeter Wemm /* temporarily switch to the window's screen to get cooked input */
4240e3d5408SPeter Wemm _nc_lock_global(curses);
4250e3d5408SPeter Wemm save_SP = CURRENT_SCREEN;
4260e3d5408SPeter Wemm _nc_set_screen(sp);
4270e3d5408SPeter Wemm rc = recur_wgetnstr(win, buf);
4280e3d5408SPeter Wemm _nc_set_screen(save_SP);
4290e3d5408SPeter Wemm _nc_unlock_global(curses);
4304a1a9510SRong-En Fan } else
4310e3d5408SPeter Wemm #endif
4320e3d5408SPeter Wemm {
433aa59d4d4SRong-En Fan sp->_called_wgetch = TRUE;
43415589c42SPeter Wemm rc = wgetnstr(win, buf, MAXCOLUMNS);
4350e3d5408SPeter Wemm sp->_called_wgetch = FALSE;
436aa59d4d4SRong-En Fan }
4370e3d5408SPeter Wemm } else {
4380e3d5408SPeter Wemm rc = ERR;
439aa59d4d4SRong-En Fan }
44039f2269fSPeter Wemm return rc;
4410e3d5408SPeter Wemm }
4420e3d5408SPeter Wemm
443aa59d4d4SRong-En Fan NCURSES_EXPORT(int)
_nc_wgetch(WINDOW * win,int * result,int use_meta EVENTLIST_2nd (_nc_eventlist * evl))4444a1a9510SRong-En Fan _nc_wgetch(WINDOW *win,
4454a1a9510SRong-En Fan int *result,
4465d08fb1fSRong-En Fan int use_meta
4474a1a9510SRong-En Fan EVENTLIST_2nd(_nc_eventlist * evl))
4484a1a9510SRong-En Fan {
449aa59d4d4SRong-En Fan SCREEN *sp;
4504a1a9510SRong-En Fan int ch;
4514a1a9510SRong-En Fan int rc = 0;
4524a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS
45315589c42SPeter Wemm int event_delay = -1;
4544a1a9510SRong-En Fan #endif
4554a1a9510SRong-En Fan
4564a1a9510SRong-En Fan T((T_CALLED("_nc_wgetch(%p)"), (void *) win));
457aa59d4d4SRong-En Fan
4584a1a9510SRong-En Fan *result = 0;
4594a1a9510SRong-En Fan
4604a1a9510SRong-En Fan sp = _nc_screen_of(win);
4614a1a9510SRong-En Fan if (win == 0 || sp == 0) {
462aa59d4d4SRong-En Fan returnCode(ERR);
4630e3d5408SPeter Wemm }
4640e3d5408SPeter Wemm
4654a1a9510SRong-En Fan if (cooked_key_in_fifo()) {
4660e3d5408SPeter Wemm recur_wrefresh(win);
4670e3d5408SPeter Wemm *result = fifo_pull(sp);
468aa59d4d4SRong-En Fan returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
469aa59d4d4SRong-En Fan }
4700e3d5408SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
4710e3d5408SPeter Wemm if (evl && (evl->count == 0))
47215589c42SPeter Wemm evl = NULL;
4730e3d5408SPeter Wemm event_delay = _nc_eventlist_timeout(evl);
474aa59d4d4SRong-En Fan #endif
475aa59d4d4SRong-En Fan
4760e3d5408SPeter Wemm /*
47715589c42SPeter Wemm * Handle cooked mode. Grab a string from the screen,
478aa59d4d4SRong-En Fan * stuff its contents in the FIFO queue, and pop off
4794ee07662SRong-En Fan * the first character to return it.
4804ee07662SRong-En Fan */
4814ee07662SRong-En Fan if (head == -1 &&
4824ee07662SRong-En Fan !sp->_notty &&
4834ee07662SRong-En Fan !sp->_raw &&
4844ee07662SRong-En Fan !sp->_cbreak &&
485b82face1SPeter Wemm !sp->_called_wgetch) {
4860e3d5408SPeter Wemm char buf[MAXCOLUMNS], *bufp;
4870e3d5408SPeter Wemm
4880e3d5408SPeter Wemm TR(TRACE_IEVENT, ("filling queue in cooked mode"));
4890e3d5408SPeter Wemm
4900e3d5408SPeter Wemm /* ungetch in reverse order */
4910e3d5408SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
4920e3d5408SPeter Wemm rc = recur_wgetnstr(win, buf);
49315589c42SPeter Wemm if (rc != KEY_EVENT && rc != ERR)
49415589c42SPeter Wemm safe_ungetch(sp, '\n');
49515589c42SPeter Wemm #else
49615589c42SPeter Wemm if (recur_wgetnstr(win, buf) != ERR)
49715589c42SPeter Wemm safe_ungetch(sp, '\n');
49815589c42SPeter Wemm #endif
49915589c42SPeter Wemm for (bufp = buf + strlen(buf); bufp > buf; bufp--)
50015589c42SPeter Wemm safe_ungetch(sp, bufp[-1]);
50115589c42SPeter Wemm
50215589c42SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
50315589c42SPeter Wemm /* Return it first */
50415589c42SPeter Wemm if (rc == KEY_EVENT) {
50515589c42SPeter Wemm *result = rc;
50615589c42SPeter Wemm } else
50715589c42SPeter Wemm #endif
50815589c42SPeter Wemm *result = fifo_pull(sp);
50915589c42SPeter Wemm returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
510aa59d4d4SRong-En Fan }
51115589c42SPeter Wemm
51215589c42SPeter Wemm if (win->_use_keypad != sp->_keypad_on)
51315589c42SPeter Wemm _nc_keypad(sp, win->_use_keypad);
51415589c42SPeter Wemm
51515589c42SPeter Wemm recur_wrefresh(win);
51615589c42SPeter Wemm
5170e3d5408SPeter Wemm if (win->_notimeout || (win->_delay >= 0) || (sp->_cbreak > 1)) {
5180e3d5408SPeter Wemm if (head == -1) { /* fifo is empty */
519aa59d4d4SRong-En Fan int delay;
5200e3d5408SPeter Wemm
5210e3d5408SPeter Wemm TR(TRACE_IEVENT, ("timed delay in wgetch()"));
5220e3d5408SPeter Wemm if (sp->_cbreak > 1)
5230e3d5408SPeter Wemm delay = (sp->_cbreak - 1) * 100;
5240e3d5408SPeter Wemm else
5250e3d5408SPeter Wemm delay = win->_delay;
5260e3d5408SPeter Wemm
52739f2269fSPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
5280e3d5408SPeter Wemm if (event_delay >= 0 && delay > event_delay)
5290e3d5408SPeter Wemm delay = event_delay;
5300e3d5408SPeter Wemm #endif
5315d08fb1fSRong-En Fan
5320e3d5408SPeter Wemm TR(TRACE_IEVENT, ("delay is %d milliseconds", delay));
53339f2269fSPeter Wemm
53439f2269fSPeter Wemm rc = check_mouse_activity(sp, delay EVENTLIST_2nd(evl));
53539f2269fSPeter Wemm
53639f2269fSPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
5374a1a9510SRong-En Fan if (rc & TW_EVENT) {
5384a1a9510SRong-En Fan *result = KEY_EVENT;
5394a1a9510SRong-En Fan returnCode(KEY_CODE_YES);
5404a1a9510SRong-En Fan }
5414a1a9510SRong-En Fan #endif
5424a1a9510SRong-En Fan if (!rc) {
5434a1a9510SRong-En Fan goto check_sigwinch;
5444a1a9510SRong-En Fan }
5454a1a9510SRong-En Fan }
5464a1a9510SRong-En Fan /* else go on to read data available */
5475d08fb1fSRong-En Fan }
5484a1a9510SRong-En Fan
5494a1a9510SRong-En Fan if (win->_use_keypad) {
5504a1a9510SRong-En Fan /*
5514a1a9510SRong-En Fan * This is tricky. We only want to get special-key
5524a1a9510SRong-En Fan * events one at a time. But we want to accumulate
5534a1a9510SRong-En Fan * mouse events until either (a) the mouse logic tells
5544a1a9510SRong-En Fan * us it's picked up a complete gesture, or (b)
55539f2269fSPeter Wemm * there's a detectable time lapse after one.
55639f2269fSPeter Wemm *
55739f2269fSPeter Wemm * Note: if the mouse code starts failing to compose
55839f2269fSPeter Wemm * press/release events into clicks, you should probably
55939f2269fSPeter Wemm * increase the wait with mouseinterval().
56039f2269fSPeter Wemm */
56139f2269fSPeter Wemm int runcount = 0;
5624a1a9510SRong-En Fan
5634a1a9510SRong-En Fan do {
5645d08fb1fSRong-En Fan ch = kgetch(sp, win->_notimeout EVENTLIST_2nd(evl));
5654a1a9510SRong-En Fan if (ch == KEY_MOUSE) {
56639f2269fSPeter Wemm ++runcount;
56739f2269fSPeter Wemm if (sp->_mouse_inline(sp))
56839f2269fSPeter Wemm break;
5690e3d5408SPeter Wemm }
5700e3d5408SPeter Wemm if (sp->_maxclick < 0)
5710e3d5408SPeter Wemm break;
5720e3d5408SPeter Wemm } while
5730e3d5408SPeter Wemm (ch == KEY_MOUSE
5740e3d5408SPeter Wemm && (((rc = check_mouse_activity(sp, sp->_maxclick
5750e3d5408SPeter Wemm EVENTLIST_2nd(evl))) != 0
5760e3d5408SPeter Wemm && !(rc & TW_EVENT))
5770e3d5408SPeter Wemm || !sp->_mouse_parse(sp, runcount)));
5780e3d5408SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
5790e3d5408SPeter Wemm if ((rc & TW_EVENT) && !(ch == KEY_EVENT)) {
5800e3d5408SPeter Wemm safe_ungetch(sp, ch);
58139f2269fSPeter Wemm ch = KEY_EVENT;
5820e3d5408SPeter Wemm }
5830e3d5408SPeter Wemm #endif
5840e3d5408SPeter Wemm if (runcount > 0 && ch != KEY_MOUSE) {
5850e3d5408SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
5860e3d5408SPeter Wemm /* mouse event sequence ended by an event, report event */
587aa59d4d4SRong-En Fan if (ch == KEY_EVENT) {
5880e3d5408SPeter Wemm safe_ungetch(sp, KEY_MOUSE); /* FIXME This interrupts a gesture... */
5895ca44d1cSRong-En Fan } else
5900e3d5408SPeter Wemm #endif
591aa59d4d4SRong-En Fan {
5920e3d5408SPeter Wemm /* mouse event sequence ended by keystroke, store keystroke */
59339f2269fSPeter Wemm safe_ungetch(sp, ch);
5940e3d5408SPeter Wemm ch = KEY_MOUSE;
595aa59d4d4SRong-En Fan }
5960e3d5408SPeter Wemm }
59715589c42SPeter Wemm } else {
598aa59d4d4SRong-En Fan if (head == -1)
5994a1a9510SRong-En Fan fifo_push(sp EVENTLIST_2nd(evl));
6004a1a9510SRong-En Fan ch = fifo_pull(sp);
601aa59d4d4SRong-En Fan }
6024a1a9510SRong-En Fan
6030e3d5408SPeter Wemm if (ch == ERR) {
6040e3d5408SPeter Wemm check_sigwinch:
6050e3d5408SPeter Wemm #if USE_SIZECHANGE
6064a1a9510SRong-En Fan if (_nc_handle_sigwinch(sp)) {
6074a1a9510SRong-En Fan _nc_update_screensize(sp);
6084a1a9510SRong-En Fan /* resizeterm can push KEY_RESIZE */
609aa59d4d4SRong-En Fan if (cooked_key_in_fifo()) {
6100e3d5408SPeter Wemm *result = fifo_pull(sp);
6114a1a9510SRong-En Fan /*
6124a1a9510SRong-En Fan * Get the ERR from queue -- it is from WINCH,
6134a1a9510SRong-En Fan * so we should take it out, the "error" is handled.
614aa59d4d4SRong-En Fan */
61515589c42SPeter Wemm if (fifo_peek(sp) == -1)
6164a1a9510SRong-En Fan fifo_pull(sp);
6174a1a9510SRong-En Fan returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK);
6184a1a9510SRong-En Fan }
6194a1a9510SRong-En Fan }
6200e3d5408SPeter Wemm #endif
6210e3d5408SPeter Wemm returnCode(ERR);
6220e3d5408SPeter Wemm }
6230e3d5408SPeter Wemm
6240e3d5408SPeter Wemm /*
6250e3d5408SPeter Wemm * If echo() is in effect, display the printable version of the
6265d08fb1fSRong-En Fan * key on the screen. Carriage return and backspace are treated
6270e3d5408SPeter Wemm * specially by Solaris curses:
6280e3d5408SPeter Wemm *
62939f2269fSPeter Wemm * If carriage return is defined as a function key in the
63015589c42SPeter Wemm * terminfo, e.g., kent, then Solaris may return either ^J (or ^M
63115589c42SPeter Wemm * if nonl() is set) or KEY_ENTER depending on the echo() mode.
63239f2269fSPeter Wemm * We echo before translating carriage return based on nonl(),
63339f2269fSPeter Wemm * since the visual result simply moves the cursor to column 0.
6340e3d5408SPeter Wemm *
6350e3d5408SPeter Wemm * Backspace is a different matter. Solaris curses does not
6360e3d5408SPeter Wemm * translate it to KEY_BACKSPACE if kbs=^H. This does not depend
6370e3d5408SPeter Wemm * on the stty modes, but appears to be a hardcoded special case.
6380e3d5408SPeter Wemm * This is a difference from ncurses, which uses the terminfo entry.
6390e3d5408SPeter Wemm * However, we provide the same visual result as Solaris, moving the
640aa59d4d4SRong-En Fan * cursor to the left.
6410e3d5408SPeter Wemm */
6420e3d5408SPeter Wemm if (sp->_echo && !(win->_flags & _ISPAD)) {
6430e3d5408SPeter Wemm chtype backup = (chtype) ((ch == KEY_BACKSPACE) ? '\b' : ch);
6440e3d5408SPeter Wemm if (backup < KEY_MIN)
6450e3d5408SPeter Wemm wechochar(win, backup);
6460e3d5408SPeter Wemm }
6470e3d5408SPeter Wemm
64815589c42SPeter Wemm /*
6494a1a9510SRong-En Fan * Simulate ICRNL mode
6504a1a9510SRong-En Fan */
6510e3d5408SPeter Wemm if ((ch == '\r') && sp->_nl)
652aa59d4d4SRong-En Fan ch = '\n';
6534a1a9510SRong-En Fan
6544a1a9510SRong-En Fan /* Strip 8th-bit if so desired. We do this only for characters that
6554a1a9510SRong-En Fan * are in the range 128-255, to provide compatibility with terminals
6564a1a9510SRong-En Fan * that display only 7-bit characters. Note that 'ch' may be a
6574a1a9510SRong-En Fan * function key at this point, so we mustn't strip _those_.
6584a1a9510SRong-En Fan */
6594a1a9510SRong-En Fan if (!use_meta)
6604a1a9510SRong-En Fan if ((ch < KEY_MIN) && (ch & 0x80))
6614a1a9510SRong-En Fan ch &= 0x7f;
6620e3d5408SPeter Wemm
6630e3d5408SPeter Wemm T(("wgetch returning : %s", _nc_tracechar(sp, ch)));
6640e3d5408SPeter Wemm
6650e3d5408SPeter Wemm *result = ch;
6660e3d5408SPeter Wemm returnCode(ch >= KEY_MIN ? KEY_CODE_YES : OK);
667aa59d4d4SRong-En Fan }
6680e3d5408SPeter Wemm
6690e3d5408SPeter Wemm #ifdef NCURSES_WGETCH_EVENTS
6700e3d5408SPeter Wemm NCURSES_EXPORT(int)
wgetch_events(WINDOW * win,_nc_eventlist * evl)671 wgetch_events(WINDOW *win, _nc_eventlist * evl)
672 {
673 int code;
674 int value;
675
676 T((T_CALLED("wgetch_events(%p,%p)"), (void *) win, (void *) evl));
677 code = _nc_wgetch(win,
678 &value,
679 _nc_use_meta(win)
680 EVENTLIST_2nd(evl));
681 if (code != ERR)
682 code = value;
683 returnCode(code);
684 }
685 #endif
686
687 NCURSES_EXPORT(int)
wgetch(WINDOW * win)688 wgetch(WINDOW *win)
689 {
690 int code;
691 int value;
692
693 T((T_CALLED("wgetch(%p)"), (void *) win));
694 code = _nc_wgetch(win,
695 &value,
696 _nc_use_meta(win)
697 EVENTLIST_2nd((_nc_eventlist *) 0));
698 if (code != ERR)
699 code = value;
700 returnCode(code);
701 }
702
703 /*
704 ** int
705 ** kgetch()
706 **
707 ** Get an input character, but take care of keypad sequences, returning
708 ** an appropriate code when one matches the input. After each character
709 ** is received, set an alarm call based on ESCDELAY. If no more of the
710 ** sequence is received by the time the alarm goes off, pass through
711 ** the sequence gotten so far.
712 **
713 ** This function must be called when there are no cooked keys in queue.
714 ** (that is head==-1 || peek==head)
715 **
716 */
717
718 static int
kgetch(SCREEN * sp,bool forever EVENTLIST_2nd (_nc_eventlist * evl))719 kgetch(SCREEN *sp, bool forever EVENTLIST_2nd(_nc_eventlist * evl))
720 {
721 TRIES *ptr;
722 int ch = 0;
723 int timeleft = forever ? 9999999 : GetEscdelay(sp);
724
725 TR(TRACE_IEVENT, ("kgetch() called"));
726
727 ptr = sp->_keytry;
728
729 for (;;) {
730 if (cooked_key_in_fifo() && sp->_fifo[head] >= KEY_MIN) {
731 break;
732 } else if (!raw_key_in_fifo()) {
733 ch = fifo_push(sp EVENTLIST_2nd(evl));
734 if (ch == ERR) {
735 peek = head; /* the keys stay uninterpreted */
736 return ERR;
737 }
738 #ifdef NCURSES_WGETCH_EVENTS
739 else if (ch == KEY_EVENT) {
740 peek = head; /* the keys stay uninterpreted */
741 return fifo_pull(sp); /* Remove KEY_EVENT from the queue */
742 }
743 #endif
744 }
745
746 ch = fifo_peek(sp);
747 if (ch >= KEY_MIN) {
748 /* If not first in queue, somebody put this key there on purpose in
749 * emergency. Consider it higher priority than the unfinished
750 * keysequence we are parsing.
751 */
752 peek = head;
753 /* assume the key is the last in fifo */
754 t_dec(); /* remove the key */
755 return ch;
756 }
757
758 TR(TRACE_IEVENT, ("ch: %s", _nc_tracechar(sp, (unsigned char) ch)));
759 while ((ptr != NULL) && (ptr->ch != (unsigned char) ch))
760 ptr = ptr->sibling;
761
762 if (ptr == NULL) {
763 TR(TRACE_IEVENT, ("ptr is null"));
764 break;
765 }
766 TR(TRACE_IEVENT, ("ptr=%p, ch=%d, value=%d",
767 (void *) ptr, ptr->ch, ptr->value));
768
769 if (ptr->value != 0) { /* sequence terminated */
770 TR(TRACE_IEVENT, ("end of sequence"));
771 if (peek == tail) {
772 fifo_clear(sp);
773 } else {
774 head = peek;
775 }
776 return (ptr->value);
777 }
778
779 ptr = ptr->child;
780
781 if (!raw_key_in_fifo()) {
782 int rc;
783
784 TR(TRACE_IEVENT, ("waiting for rest of sequence"));
785 rc = check_mouse_activity(sp, timeleft EVENTLIST_2nd(evl));
786 #ifdef NCURSES_WGETCH_EVENTS
787 if (rc & TW_EVENT) {
788 TR(TRACE_IEVENT, ("interrupted by a user event"));
789 /* FIXME Should have preserved remainder timeleft for reuse... */
790 peek = head; /* Restart interpreting later */
791 return KEY_EVENT;
792 }
793 #endif
794 if (!rc) {
795 TR(TRACE_IEVENT, ("ran out of time"));
796 break;
797 }
798 }
799 }
800 ch = fifo_pull(sp);
801 peek = head;
802 return ch;
803 }
804