10e3d5408SPeter Wemm /**************************************************************************** 2d8977eafSRong-En Fan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 324a1a9510SRong-En Fan * and: Thomas E. Dickey 1996-on * 330e3d5408SPeter Wemm ****************************************************************************/ 340e3d5408SPeter Wemm 350e3d5408SPeter Wemm /* 360e3d5408SPeter Wemm ** lib_getch.c 370e3d5408SPeter Wemm ** 380e3d5408SPeter Wemm ** The routine getch(). 390e3d5408SPeter Wemm ** 400e3d5408SPeter Wemm */ 410e3d5408SPeter Wemm 420e3d5408SPeter Wemm #include <curses.priv.h> 430e3d5408SPeter Wemm 44d8977eafSRong-En Fan MODULE_ID("$Id: lib_getch.c,v 1.82 2008/01/19 21:07:30 tom Exp $") 450e3d5408SPeter Wemm 460e3d5408SPeter Wemm #include <fifo_defs.h> 470e3d5408SPeter Wemm 485ca44d1cSRong-En Fan #if USE_REENTRANT 495ca44d1cSRong-En Fan NCURSES_EXPORT(int) 505ca44d1cSRong-En Fan NCURSES_PUBLIC_VAR(ESCDELAY) (void) 515ca44d1cSRong-En Fan { 525ca44d1cSRong-En Fan return SP ? SP->_ESCDELAY : 1000; 535ca44d1cSRong-En Fan } 545ca44d1cSRong-En Fan #else 557a69bbfbSPeter Wemm NCURSES_EXPORT_VAR(int) 567a69bbfbSPeter Wemm ESCDELAY = 1000; /* max interval betw. chars in funkeys, in millisecs */ 575ca44d1cSRong-En Fan #endif 580e3d5408SPeter Wemm 59d8977eafSRong-En Fan #if NCURSES_EXT_FUNCS 60d8977eafSRong-En Fan NCURSES_EXPORT(int) 61d8977eafSRong-En Fan set_escdelay(int value) 62d8977eafSRong-En Fan { 63d8977eafSRong-En Fan int code = OK; 64d8977eafSRong-En Fan #if USE_REENTRANT 65d8977eafSRong-En Fan if (SP) { 66d8977eafSRong-En Fan SP->_ESCDELAY = value; 67d8977eafSRong-En Fan } else { 68d8977eafSRong-En Fan code = ERR; 69d8977eafSRong-En Fan } 70d8977eafSRong-En Fan #else 71d8977eafSRong-En Fan ESCDELAY = value; 72d8977eafSRong-En Fan #endif 73d8977eafSRong-En Fan return code; 74d8977eafSRong-En Fan } 75d8977eafSRong-En Fan #endif 76d8977eafSRong-En Fan 774a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 784a1a9510SRong-En Fan #define TWAIT_MASK 7 794a1a9510SRong-En Fan #else 804a1a9510SRong-En Fan #define TWAIT_MASK 3 814a1a9510SRong-En Fan #endif 824a1a9510SRong-En Fan 834a1a9510SRong-En Fan /* 844a1a9510SRong-En Fan * Check for mouse activity, returning nonzero if we find any. 854a1a9510SRong-En Fan */ 864a1a9510SRong-En Fan static int 874a1a9510SRong-En Fan check_mouse_activity(int delay EVENTLIST_2nd(_nc_eventlist * evl)) 884a1a9510SRong-En Fan { 894a1a9510SRong-En Fan int rc; 904a1a9510SRong-En Fan 914a1a9510SRong-En Fan #if USE_SYSMOUSE 924a1a9510SRong-En Fan if ((SP->_mouse_type == M_SYSMOUSE) 934a1a9510SRong-En Fan && (SP->_sysmouse_head < SP->_sysmouse_tail)) { 944a1a9510SRong-En Fan return 2; 954a1a9510SRong-En Fan } 964a1a9510SRong-En Fan #endif 974a1a9510SRong-En Fan rc = _nc_timed_wait(TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl)); 984a1a9510SRong-En Fan #if USE_SYSMOUSE 994a1a9510SRong-En Fan if ((SP->_mouse_type == M_SYSMOUSE) 1004a1a9510SRong-En Fan && (SP->_sysmouse_head < SP->_sysmouse_tail) 1014a1a9510SRong-En Fan && (rc == 0) 1024a1a9510SRong-En Fan && (errno == EINTR)) { 1034a1a9510SRong-En Fan rc |= 2; 1044a1a9510SRong-En Fan } 1054a1a9510SRong-En Fan #endif 1064a1a9510SRong-En Fan return rc; 1074a1a9510SRong-En Fan } 1084a1a9510SRong-En Fan 1094a1a9510SRong-En Fan static NCURSES_INLINE int 11015589c42SPeter Wemm fifo_peek(void) 1110e3d5408SPeter Wemm { 1120e3d5408SPeter Wemm int ch = SP->_fifo[peek]; 11318259542SPeter Wemm TR(TRACE_IEVENT, ("peeking at %d", peek)); 1140e3d5408SPeter Wemm 1150e3d5408SPeter Wemm p_inc(); 1160e3d5408SPeter Wemm return ch; 1170e3d5408SPeter Wemm } 1180e3d5408SPeter Wemm 1194a1a9510SRong-En Fan static NCURSES_INLINE int 12015589c42SPeter Wemm fifo_pull(void) 1210e3d5408SPeter Wemm { 1220e3d5408SPeter Wemm int ch; 1230e3d5408SPeter Wemm ch = SP->_fifo[head]; 12439f2269fSPeter Wemm TR(TRACE_IEVENT, ("pulling %s from %d", _tracechar(ch), head)); 1250e3d5408SPeter Wemm 12615589c42SPeter Wemm if (peek == head) { 1270e3d5408SPeter Wemm h_inc(); 1280e3d5408SPeter Wemm peek = head; 12915589c42SPeter Wemm } else 1300e3d5408SPeter Wemm h_inc(); 1310e3d5408SPeter Wemm 1320e3d5408SPeter Wemm #ifdef TRACE 1335ca44d1cSRong-En Fan if (USE_TRACEF(TRACE_IEVENT)) { 13415589c42SPeter Wemm _nc_fifo_dump(); 1355ca44d1cSRong-En Fan _nc_unlock_global(tracef); 1365ca44d1cSRong-En Fan } 1370e3d5408SPeter Wemm #endif 1380e3d5408SPeter Wemm return ch; 1390e3d5408SPeter Wemm } 1400e3d5408SPeter Wemm 1414a1a9510SRong-En Fan static NCURSES_INLINE int 1424a1a9510SRong-En Fan fifo_push(EVENTLIST_0th(_nc_eventlist * evl)) 1430e3d5408SPeter Wemm { 1440e3d5408SPeter Wemm int n; 1454a1a9510SRong-En Fan int ch = 0; 1464a1a9510SRong-En Fan int mask = 0; 1470e3d5408SPeter Wemm 1484a1a9510SRong-En Fan (void) mask; 14915589c42SPeter Wemm if (tail == -1) 15015589c42SPeter Wemm return ERR; 1510e3d5408SPeter Wemm 1520e3d5408SPeter Wemm #ifdef HIDE_EINTR 1530e3d5408SPeter Wemm again: 1540e3d5408SPeter Wemm errno = 0; 1550e3d5408SPeter Wemm #endif 1560e3d5408SPeter Wemm 1574a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 1584a1a9510SRong-En Fan if (evl 1594a1a9510SRong-En Fan #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE 1604a1a9510SRong-En Fan || (SP->_mouse_fd >= 0) 1614a1a9510SRong-En Fan #endif 1624a1a9510SRong-En Fan ) { 1634a1a9510SRong-En Fan mask = check_mouse_activity(-1 EVENTLIST_2nd(evl)); 1644a1a9510SRong-En Fan } else 1654a1a9510SRong-En Fan mask = 0; 1664a1a9510SRong-En Fan 1674a1a9510SRong-En Fan if (mask & 4) { 1684a1a9510SRong-En Fan T(("fifo_push: ungetch KEY_EVENT")); 1694a1a9510SRong-En Fan ungetch(KEY_EVENT); 1704a1a9510SRong-En Fan return KEY_EVENT; 1714a1a9510SRong-En Fan } 1724a1a9510SRong-En Fan #elif USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE 1734a1a9510SRong-En Fan if (SP->_mouse_fd >= 0) { 1744a1a9510SRong-En Fan mask = check_mouse_activity(-1 EVENTLIST_2nd(evl)); 1754a1a9510SRong-En Fan } 1764a1a9510SRong-En Fan #endif 1774a1a9510SRong-En Fan 1784a1a9510SRong-En Fan #if USE_GPM_SUPPORT || USE_EMX_MOUSE 1794a1a9510SRong-En Fan if ((SP->_mouse_fd >= 0) && (mask & 2)) { 1800e3d5408SPeter Wemm SP->_mouse_event(SP); 1810e3d5408SPeter Wemm ch = KEY_MOUSE; 1820e3d5408SPeter Wemm n = 1; 1830e3d5408SPeter Wemm } else 1840e3d5408SPeter Wemm #endif 1854a1a9510SRong-En Fan #if USE_SYSMOUSE 1864a1a9510SRong-En Fan if ((SP->_mouse_type == M_SYSMOUSE) 1874a1a9510SRong-En Fan && (SP->_sysmouse_head < SP->_sysmouse_tail)) { 1884a1a9510SRong-En Fan SP->_mouse_event(SP); 1894a1a9510SRong-En Fan ch = KEY_MOUSE; 1904a1a9510SRong-En Fan n = 1; 1914a1a9510SRong-En Fan } else if ((SP->_mouse_type == M_SYSMOUSE) 1924a1a9510SRong-En Fan && (mask <= 0) && errno == EINTR) { 1934a1a9510SRong-En Fan SP->_mouse_event(SP); 1944a1a9510SRong-En Fan ch = KEY_MOUSE; 1954a1a9510SRong-En Fan n = 1; 1964a1a9510SRong-En Fan } else 1974a1a9510SRong-En Fan #endif 1984a1a9510SRong-En Fan { /* Can block... */ 1990e3d5408SPeter Wemm unsigned char c2 = 0; 2000e3d5408SPeter Wemm n = read(SP->_ifd, &c2, 1); 20139f2269fSPeter Wemm ch = c2; 2020e3d5408SPeter Wemm } 2030e3d5408SPeter Wemm 2040e3d5408SPeter Wemm #ifdef HIDE_EINTR 2050e3d5408SPeter Wemm /* 2060e3d5408SPeter Wemm * Under System V curses with non-restarting signals, getch() returns 2070e3d5408SPeter Wemm * with value ERR when a handled signal keeps it from completing. 2080e3d5408SPeter Wemm * If signals restart system calls, OTOH, the signal is invisible 2090e3d5408SPeter Wemm * except to its handler. 2100e3d5408SPeter Wemm * 2110e3d5408SPeter Wemm * We don't want this difference to show. This piece of code 2120e3d5408SPeter Wemm * tries to make it look like we always have restarting signals. 2130e3d5408SPeter Wemm */ 2140e3d5408SPeter Wemm if (n <= 0 && errno == EINTR) 2150e3d5408SPeter Wemm goto again; 2160e3d5408SPeter Wemm #endif 2170e3d5408SPeter Wemm 21815589c42SPeter Wemm if ((n == -1) || (n == 0)) { 21918259542SPeter Wemm TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", SP->_ifd, n, errno)); 22018259542SPeter Wemm ch = ERR; 2210e3d5408SPeter Wemm } 22218259542SPeter Wemm TR(TRACE_IEVENT, ("read %d characters", n)); 2230e3d5408SPeter Wemm 2240e3d5408SPeter Wemm SP->_fifo[tail] = ch; 2250e3d5408SPeter Wemm SP->_fifohold = 0; 2260e3d5408SPeter Wemm if (head == -1) 2270e3d5408SPeter Wemm head = peek = tail; 2280e3d5408SPeter Wemm t_inc(); 22939f2269fSPeter Wemm TR(TRACE_IEVENT, ("pushed %s at %d", _tracechar(ch), tail)); 2300e3d5408SPeter Wemm #ifdef TRACE 2315ca44d1cSRong-En Fan if (USE_TRACEF(TRACE_IEVENT)) { 23215589c42SPeter Wemm _nc_fifo_dump(); 2335ca44d1cSRong-En Fan _nc_unlock_global(tracef); 2345ca44d1cSRong-En Fan } 2350e3d5408SPeter Wemm #endif 2360e3d5408SPeter Wemm return ch; 2370e3d5408SPeter Wemm } 2380e3d5408SPeter Wemm 2394a1a9510SRong-En Fan static NCURSES_INLINE void 24015589c42SPeter Wemm fifo_clear(void) 2410e3d5408SPeter Wemm { 24239f2269fSPeter Wemm memset(SP->_fifo, 0, sizeof(SP->_fifo)); 24315589c42SPeter Wemm head = -1; 24415589c42SPeter Wemm tail = peek = 0; 2450e3d5408SPeter Wemm } 2460e3d5408SPeter Wemm 2474a1a9510SRong-En Fan static int kgetch(EVENTLIST_0th(_nc_eventlist * evl)); 2480e3d5408SPeter Wemm 2490e3d5408SPeter Wemm #define wgetch_should_refresh(win) (\ 2500e3d5408SPeter Wemm (is_wintouched(win) || (win->_flags & _HASMOVED)) \ 2510e3d5408SPeter Wemm && !(win->_flags & _ISPAD)) 2520e3d5408SPeter Wemm 2537a69bbfbSPeter Wemm NCURSES_EXPORT(int) 2544a1a9510SRong-En Fan _nc_wgetch(WINDOW *win, 2554a1a9510SRong-En Fan unsigned long *result, 2564a1a9510SRong-En Fan int use_meta 2574a1a9510SRong-En Fan EVENTLIST_2nd(_nc_eventlist * evl)) 2580e3d5408SPeter Wemm { 2590e3d5408SPeter Wemm int ch; 2604a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 2614a1a9510SRong-En Fan long event_delay = -1; 2624a1a9510SRong-En Fan #endif 2630e3d5408SPeter Wemm 2644a1a9510SRong-En Fan T((T_CALLED("_nc_wgetch(%p)"), win)); 2650e3d5408SPeter Wemm 26639f2269fSPeter Wemm *result = 0; 2675ca44d1cSRong-En Fan if (win == 0 || SP == 0) { 2680e3d5408SPeter Wemm returnCode(ERR); 2695ca44d1cSRong-En Fan } 2700e3d5408SPeter Wemm 27115589c42SPeter Wemm if (cooked_key_in_fifo()) { 2720e3d5408SPeter Wemm if (wgetch_should_refresh(win)) 2730e3d5408SPeter Wemm wrefresh(win); 2740e3d5408SPeter Wemm 27539f2269fSPeter Wemm *result = fifo_pull(); 2765ca44d1cSRong-En Fan returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK); 2770e3d5408SPeter Wemm } 2784a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 2794a1a9510SRong-En Fan if (evl && (evl->count == 0)) 2804a1a9510SRong-En Fan evl = NULL; 2814a1a9510SRong-En Fan event_delay = _nc_eventlist_timeout(evl); 2824a1a9510SRong-En Fan #endif 2830e3d5408SPeter Wemm 2840e3d5408SPeter Wemm /* 2850e3d5408SPeter Wemm * Handle cooked mode. Grab a string from the screen, 2860e3d5408SPeter Wemm * stuff its contents in the FIFO queue, and pop off 2870e3d5408SPeter Wemm * the first character to return it. 2880e3d5408SPeter Wemm */ 2894a1a9510SRong-En Fan if (head == -1 && 2904a1a9510SRong-En Fan !SP->_notty && 2914a1a9510SRong-En Fan !SP->_raw && 2924a1a9510SRong-En Fan !SP->_cbreak && 2934a1a9510SRong-En Fan !SP->_called_wgetch) { 2940e3d5408SPeter Wemm char buf[MAXCOLUMNS], *sp; 2954a1a9510SRong-En Fan int rc; 2960e3d5408SPeter Wemm 29718259542SPeter Wemm TR(TRACE_IEVENT, ("filling queue in cooked mode")); 2980e3d5408SPeter Wemm 2994a1a9510SRong-En Fan SP->_called_wgetch = TRUE; 3004a1a9510SRong-En Fan rc = wgetnstr(win, buf, MAXCOLUMNS); 3014a1a9510SRong-En Fan SP->_called_wgetch = FALSE; 3020e3d5408SPeter Wemm 3030e3d5408SPeter Wemm /* ungetch in reverse order */ 3044a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3054a1a9510SRong-En Fan if (rc != KEY_EVENT) 3064a1a9510SRong-En Fan #endif 3070e3d5408SPeter Wemm ungetch('\n'); 3080e3d5408SPeter Wemm for (sp = buf + strlen(buf); sp > buf; sp--) 3090e3d5408SPeter Wemm ungetch(sp[-1]); 3100e3d5408SPeter Wemm 3114a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3124a1a9510SRong-En Fan /* Return it first */ 3134a1a9510SRong-En Fan if (rc == KEY_EVENT) { 3144a1a9510SRong-En Fan *result = rc; 3155ca44d1cSRong-En Fan } else 3164a1a9510SRong-En Fan #endif 31739f2269fSPeter Wemm *result = fifo_pull(); 3185ca44d1cSRong-En Fan returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK); 3190e3d5408SPeter Wemm } 3200e3d5408SPeter Wemm 32139f2269fSPeter Wemm if (win->_use_keypad != SP->_keypad_on) 32239f2269fSPeter Wemm _nc_keypad(win->_use_keypad); 32339f2269fSPeter Wemm 3240e3d5408SPeter Wemm if (wgetch_should_refresh(win)) 3250e3d5408SPeter Wemm wrefresh(win); 3260e3d5408SPeter Wemm 32715589c42SPeter Wemm if (!win->_notimeout && (win->_delay >= 0 || SP->_cbreak > 1)) { 3284a1a9510SRong-En Fan if (head == -1) { /* fifo is empty */ 3290e3d5408SPeter Wemm int delay; 3304a1a9510SRong-En Fan int rc; 3310e3d5408SPeter Wemm 33218259542SPeter Wemm TR(TRACE_IEVENT, ("timed delay in wgetch()")); 3330e3d5408SPeter Wemm if (SP->_cbreak > 1) 3340e3d5408SPeter Wemm delay = (SP->_cbreak - 1) * 100; 3350e3d5408SPeter Wemm else 3360e3d5408SPeter Wemm delay = win->_delay; 3370e3d5408SPeter Wemm 3384a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3394a1a9510SRong-En Fan if (event_delay >= 0 && delay > event_delay) 3404a1a9510SRong-En Fan delay = event_delay; 3414a1a9510SRong-En Fan #endif 3424a1a9510SRong-En Fan 34318259542SPeter Wemm TR(TRACE_IEVENT, ("delay is %d milliseconds", delay)); 3440e3d5408SPeter Wemm 3454a1a9510SRong-En Fan rc = check_mouse_activity(delay EVENTLIST_2nd(evl)); 3464a1a9510SRong-En Fan 3474a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3484a1a9510SRong-En Fan if (rc & 4) { 3494a1a9510SRong-En Fan *result = KEY_EVENT; 3505ca44d1cSRong-En Fan returnCode(KEY_CODE_YES); 3514a1a9510SRong-En Fan } 3524a1a9510SRong-En Fan #endif 3534a1a9510SRong-En Fan if (!rc) 3540e3d5408SPeter Wemm returnCode(ERR); 3554a1a9510SRong-En Fan } 3560e3d5408SPeter Wemm /* else go on to read data available */ 3570e3d5408SPeter Wemm } 3580e3d5408SPeter Wemm 35915589c42SPeter Wemm if (win->_use_keypad) { 3600e3d5408SPeter Wemm /* 3610e3d5408SPeter Wemm * This is tricky. We only want to get special-key 3620e3d5408SPeter Wemm * events one at a time. But we want to accumulate 3630e3d5408SPeter Wemm * mouse events until either (a) the mouse logic tells 3640e3d5408SPeter Wemm * us it's picked up a complete gesture, or (b) 3650e3d5408SPeter Wemm * there's a detectable time lapse after one. 3660e3d5408SPeter Wemm * 3670e3d5408SPeter Wemm * Note: if the mouse code starts failing to compose 3680e3d5408SPeter Wemm * press/release events into clicks, you should probably 3690e3d5408SPeter Wemm * increase the wait with mouseinterval(). 3700e3d5408SPeter Wemm */ 3710e3d5408SPeter Wemm int runcount = 0; 3724a1a9510SRong-En Fan int rc; 3730e3d5408SPeter Wemm 3740e3d5408SPeter Wemm do { 3754a1a9510SRong-En Fan ch = kgetch(EVENTLIST_1st(evl)); 37615589c42SPeter Wemm if (ch == KEY_MOUSE) { 3770e3d5408SPeter Wemm ++runcount; 3780e3d5408SPeter Wemm if (SP->_mouse_inline(SP)) 3790e3d5408SPeter Wemm break; 3800e3d5408SPeter Wemm } 38139f2269fSPeter Wemm if (SP->_maxclick < 0) 38239f2269fSPeter Wemm break; 3830e3d5408SPeter Wemm } while 3840e3d5408SPeter Wemm (ch == KEY_MOUSE 3854a1a9510SRong-En Fan && (((rc = check_mouse_activity(SP->_maxclick 3864a1a9510SRong-En Fan EVENTLIST_2nd(evl))) != 0 3874a1a9510SRong-En Fan && !(rc & 4)) 3880e3d5408SPeter Wemm || !SP->_mouse_parse(runcount))); 3894a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3904a1a9510SRong-En Fan if ((rc & 4) && !ch == KEY_EVENT) { 3914a1a9510SRong-En Fan ungetch(ch); 3924a1a9510SRong-En Fan ch = KEY_EVENT; 3934a1a9510SRong-En Fan } 3944a1a9510SRong-En Fan #endif 39515589c42SPeter Wemm if (runcount > 0 && ch != KEY_MOUSE) { 3964a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 3974a1a9510SRong-En Fan /* mouse event sequence ended by an event, report event */ 3984a1a9510SRong-En Fan if (ch == KEY_EVENT) { 3994a1a9510SRong-En Fan ungetch(KEY_MOUSE); /* FIXME This interrupts a gesture... */ 4004a1a9510SRong-En Fan } else 4014a1a9510SRong-En Fan #endif 4024a1a9510SRong-En Fan { 4034a1a9510SRong-En Fan /* mouse event sequence ended by keystroke, store keystroke */ 4040e3d5408SPeter Wemm ungetch(ch); 4050e3d5408SPeter Wemm ch = KEY_MOUSE; 4060e3d5408SPeter Wemm } 4074a1a9510SRong-En Fan } 4080e3d5408SPeter Wemm } else { 4090e3d5408SPeter Wemm if (head == -1) 4104a1a9510SRong-En Fan fifo_push(EVENTLIST_1st(evl)); 4110e3d5408SPeter Wemm ch = fifo_pull(); 4120e3d5408SPeter Wemm } 4130e3d5408SPeter Wemm 41415589c42SPeter Wemm if (ch == ERR) { 4150e3d5408SPeter Wemm #if USE_SIZECHANGE 4165ca44d1cSRong-En Fan if (_nc_handle_sigwinch(FALSE)) { 4170e3d5408SPeter Wemm _nc_update_screensize(); 4180e3d5408SPeter Wemm /* resizeterm can push KEY_RESIZE */ 41915589c42SPeter Wemm if (cooked_key_in_fifo()) { 42039f2269fSPeter Wemm *result = fifo_pull(); 421b82face1SPeter Wemm returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK); 4220e3d5408SPeter Wemm } 4230e3d5408SPeter Wemm } 4240e3d5408SPeter Wemm #endif 4250e3d5408SPeter Wemm returnCode(ERR); 4260e3d5408SPeter Wemm } 4270e3d5408SPeter Wemm 4280e3d5408SPeter Wemm /* 42915589c42SPeter Wemm * If echo() is in effect, display the printable version of the 43015589c42SPeter Wemm * key on the screen. Carriage return and backspace are treated 43115589c42SPeter Wemm * specially by Solaris curses: 43215589c42SPeter Wemm * 43315589c42SPeter Wemm * If carriage return is defined as a function key in the 43415589c42SPeter Wemm * terminfo, e.g., kent, then Solaris may return either ^J (or ^M 43515589c42SPeter Wemm * if nonl() is set) or KEY_ENTER depending on the echo() mode. 43615589c42SPeter Wemm * We echo before translating carriage return based on nonl(), 43715589c42SPeter Wemm * since the visual result simply moves the cursor to column 0. 43815589c42SPeter Wemm * 43915589c42SPeter Wemm * Backspace is a different matter. Solaris curses does not 44015589c42SPeter Wemm * translate it to KEY_BACKSPACE if kbs=^H. This does not depend 44115589c42SPeter Wemm * on the stty modes, but appears to be a hardcoded special case. 44215589c42SPeter Wemm * This is a difference from ncurses, which uses the terminfo entry. 44315589c42SPeter Wemm * However, we provide the same visual result as Solaris, moving the 44415589c42SPeter Wemm * cursor to the left. 44515589c42SPeter Wemm */ 44615589c42SPeter Wemm if (SP->_echo && !(win->_flags & _ISPAD)) { 44715589c42SPeter Wemm chtype backup = (ch == KEY_BACKSPACE) ? '\b' : ch; 44815589c42SPeter Wemm if (backup < KEY_MIN) 44915589c42SPeter Wemm wechochar(win, backup); 45015589c42SPeter Wemm } 45115589c42SPeter Wemm 45215589c42SPeter Wemm /* 4530e3d5408SPeter Wemm * Simulate ICRNL mode 4540e3d5408SPeter Wemm */ 4550e3d5408SPeter Wemm if ((ch == '\r') && SP->_nl) 4560e3d5408SPeter Wemm ch = '\n'; 4570e3d5408SPeter Wemm 4580e3d5408SPeter Wemm /* Strip 8th-bit if so desired. We do this only for characters that 4590e3d5408SPeter Wemm * are in the range 128-255, to provide compatibility with terminals 4600e3d5408SPeter Wemm * that display only 7-bit characters. Note that 'ch' may be a 4610e3d5408SPeter Wemm * function key at this point, so we mustn't strip _those_. 4620e3d5408SPeter Wemm */ 46339f2269fSPeter Wemm if (!use_meta) 4640e3d5408SPeter Wemm if ((ch < KEY_MIN) && (ch & 0x80)) 4650e3d5408SPeter Wemm ch &= 0x7f; 4660e3d5408SPeter Wemm 46739f2269fSPeter Wemm T(("wgetch returning : %s", _tracechar(ch))); 4680e3d5408SPeter Wemm 46939f2269fSPeter Wemm *result = ch; 47039f2269fSPeter Wemm returnCode(ch >= KEY_MIN ? KEY_CODE_YES : OK); 47139f2269fSPeter Wemm } 47239f2269fSPeter Wemm 4734a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 4744a1a9510SRong-En Fan NCURSES_EXPORT(int) 4754a1a9510SRong-En Fan wgetch_events(WINDOW *win, _nc_eventlist * evl) 4764a1a9510SRong-En Fan { 4774a1a9510SRong-En Fan int code; 4784a1a9510SRong-En Fan unsigned long value; 4794a1a9510SRong-En Fan 4804a1a9510SRong-En Fan T((T_CALLED("wgetch_events(%p,%p)"), win, evl)); 4814a1a9510SRong-En Fan code = _nc_wgetch(win, 4824a1a9510SRong-En Fan &value, 4834a1a9510SRong-En Fan SP->_use_meta 4844a1a9510SRong-En Fan EVENTLIST_2nd(evl)); 4854a1a9510SRong-En Fan if (code != ERR) 4864a1a9510SRong-En Fan code = value; 4874a1a9510SRong-En Fan returnCode(code); 4884a1a9510SRong-En Fan } 4894a1a9510SRong-En Fan #endif 4904a1a9510SRong-En Fan 49139f2269fSPeter Wemm NCURSES_EXPORT(int) 49239f2269fSPeter Wemm wgetch(WINDOW *win) 49339f2269fSPeter Wemm { 49439f2269fSPeter Wemm int code; 49539f2269fSPeter Wemm unsigned long value; 49639f2269fSPeter Wemm 49739f2269fSPeter Wemm T((T_CALLED("wgetch(%p)"), win)); 4984a1a9510SRong-En Fan code = _nc_wgetch(win, 4994a1a9510SRong-En Fan &value, 5004a1a9510SRong-En Fan (SP ? SP->_use_meta : 0) 5014a1a9510SRong-En Fan EVENTLIST_2nd((_nc_eventlist *) 0)); 50239f2269fSPeter Wemm if (code != ERR) 50339f2269fSPeter Wemm code = value; 50439f2269fSPeter Wemm returnCode(code); 5050e3d5408SPeter Wemm } 5060e3d5408SPeter Wemm 5070e3d5408SPeter Wemm /* 5080e3d5408SPeter Wemm ** int 5090e3d5408SPeter Wemm ** kgetch() 5100e3d5408SPeter Wemm ** 5110e3d5408SPeter Wemm ** Get an input character, but take care of keypad sequences, returning 5120e3d5408SPeter Wemm ** an appropriate code when one matches the input. After each character 5130e3d5408SPeter Wemm ** is received, set an alarm call based on ESCDELAY. If no more of the 5140e3d5408SPeter Wemm ** sequence is received by the time the alarm goes off, pass through 5150e3d5408SPeter Wemm ** the sequence gotten so far. 5160e3d5408SPeter Wemm ** 51739f2269fSPeter Wemm ** This function must be called when there are no cooked keys in queue. 5180e3d5408SPeter Wemm ** (that is head==-1 || peek==head) 5190e3d5408SPeter Wemm ** 5200e3d5408SPeter Wemm */ 5210e3d5408SPeter Wemm 5220e3d5408SPeter Wemm static int 5234a1a9510SRong-En Fan kgetch(EVENTLIST_0th(_nc_eventlist * evl)) 5240e3d5408SPeter Wemm { 5255ca44d1cSRong-En Fan TRIES *ptr; 5260e3d5408SPeter Wemm int ch = 0; 5270e3d5408SPeter Wemm int timeleft = ESCDELAY; 5280e3d5408SPeter Wemm 52939f2269fSPeter Wemm TR(TRACE_IEVENT, ("kgetch() called")); 5300e3d5408SPeter Wemm 5310e3d5408SPeter Wemm ptr = SP->_keytry; 5320e3d5408SPeter Wemm 53315589c42SPeter Wemm for (;;) { 5344a1a9510SRong-En Fan if (cooked_key_in_fifo() && SP->_fifo[head] >= KEY_MIN) { 5354a1a9510SRong-En Fan break; 5364a1a9510SRong-En Fan } else if (!raw_key_in_fifo()) { 5374a1a9510SRong-En Fan ch = fifo_push(EVENTLIST_1st(evl)); 5384a1a9510SRong-En Fan if (ch == ERR) { 5390e3d5408SPeter Wemm peek = head; /* the keys stay uninterpreted */ 5400e3d5408SPeter Wemm return ERR; 5410e3d5408SPeter Wemm } 5424a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 5434a1a9510SRong-En Fan else if (ch == KEY_EVENT) { 5444a1a9510SRong-En Fan peek = head; /* the keys stay uninterpreted */ 5454a1a9510SRong-En Fan return fifo_pull(); /* Remove KEY_EVENT from the queue */ 5460e3d5408SPeter Wemm } 5474a1a9510SRong-En Fan #endif 5484a1a9510SRong-En Fan } 5494a1a9510SRong-En Fan 5500e3d5408SPeter Wemm ch = fifo_peek(); 55115589c42SPeter Wemm if (ch >= KEY_MIN) { 5524a1a9510SRong-En Fan /* If not first in queue, somebody put this key there on purpose in 5534a1a9510SRong-En Fan * emergency. Consider it higher priority than the unfinished 5544a1a9510SRong-En Fan * keysequence we are parsing. 5554a1a9510SRong-En Fan */ 5560e3d5408SPeter Wemm peek = head; 5570e3d5408SPeter Wemm /* assume the key is the last in fifo */ 5580e3d5408SPeter Wemm t_dec(); /* remove the key */ 5590e3d5408SPeter Wemm return ch; 5600e3d5408SPeter Wemm } 5610e3d5408SPeter Wemm 56239f2269fSPeter Wemm TR(TRACE_IEVENT, ("ch: %s", _tracechar((unsigned char) ch))); 5630e3d5408SPeter Wemm while ((ptr != NULL) && (ptr->ch != (unsigned char) ch)) 5640e3d5408SPeter Wemm ptr = ptr->sibling; 56539f2269fSPeter Wemm 56615589c42SPeter Wemm if (ptr == NULL) { 56715589c42SPeter Wemm TR(TRACE_IEVENT, ("ptr is null")); 56839f2269fSPeter Wemm break; 56939f2269fSPeter Wemm } 5700e3d5408SPeter Wemm TR(TRACE_IEVENT, ("ptr=%p, ch=%d, value=%d", 5710e3d5408SPeter Wemm ptr, ptr->ch, ptr->value)); 5720e3d5408SPeter Wemm 5730e3d5408SPeter Wemm if (ptr->value != 0) { /* sequence terminated */ 5740e3d5408SPeter Wemm TR(TRACE_IEVENT, ("end of sequence")); 5750e3d5408SPeter Wemm if (peek == tail) 5760e3d5408SPeter Wemm fifo_clear(); 5770e3d5408SPeter Wemm else 5780e3d5408SPeter Wemm head = peek; 5790e3d5408SPeter Wemm return (ptr->value); 5800e3d5408SPeter Wemm } 5810e3d5408SPeter Wemm 5820e3d5408SPeter Wemm ptr = ptr->child; 5830e3d5408SPeter Wemm 58415589c42SPeter Wemm if (!raw_key_in_fifo()) { 5854a1a9510SRong-En Fan int rc; 5864a1a9510SRong-En Fan 5870e3d5408SPeter Wemm TR(TRACE_IEVENT, ("waiting for rest of sequence")); 5884a1a9510SRong-En Fan rc = check_mouse_activity(timeleft EVENTLIST_2nd(evl)); 5894a1a9510SRong-En Fan #ifdef NCURSES_WGETCH_EVENTS 5904a1a9510SRong-En Fan if (rc & 4) { 5914a1a9510SRong-En Fan TR(TRACE_IEVENT, ("interrupted by a user event")); 5924a1a9510SRong-En Fan /* FIXME Should have preserved remainder timeleft for reuse... */ 5934a1a9510SRong-En Fan peek = head; /* Restart interpreting later */ 5944a1a9510SRong-En Fan return KEY_EVENT; 5954a1a9510SRong-En Fan } 5964a1a9510SRong-En Fan #endif 5974a1a9510SRong-En Fan if (!rc) { 5980e3d5408SPeter Wemm TR(TRACE_IEVENT, ("ran out of time")); 5990e3d5408SPeter Wemm break; 6000e3d5408SPeter Wemm } 6010e3d5408SPeter Wemm } 6020e3d5408SPeter Wemm } 6030e3d5408SPeter Wemm ch = fifo_pull(); 6040e3d5408SPeter Wemm peek = head; 6050e3d5408SPeter Wemm return ch; 6060e3d5408SPeter Wemm } 607