X-Git-Url: https://ncurses.scripts.mit.edu/?a=blobdiff_plain;ds=sidebyside;f=ncurses%2Fbase%2Flib_getch.c;h=38537591afc0ab8bda04ed5ec382ba0292453584;hb=HEAD;hp=42eb9cca38e58c7014fee6bf35c4da41fbc3a2ec;hpb=8d00601178f9d92b95a91c93f74547517d93168b;p=ncurses.git diff --git a/ncurses/base/lib_getch.c b/ncurses/base/lib_getch.c index 42eb9cca..8e476791 100644 --- a/ncurses/base/lib_getch.c +++ b/ncurses/base/lib_getch.c @@ -1,5 +1,6 @@ /**************************************************************************** - * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,9 +41,10 @@ ** */ +#define NEED_KEY_EVENT #include -MODULE_ID("$Id: lib_getch.c,v 1.132 2015/05/09 17:10:41 tom Exp $") +MODULE_ID("$Id: lib_getch.c,v 1.146 2023/04/29 18:57:12 tom Exp $") #include @@ -69,16 +71,20 @@ NCURSES_EXPORT(int) NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value) { int code = OK; -#if USE_REENTRANT - if (SP_PARM) { - SET_ESCDELAY(value); - } else { + if (value < 0) { code = ERR; - } + } else { +#if USE_REENTRANT + if (SP_PARM) { + SET_ESCDELAY(value); + } else { + code = ERR; + } #else - (void) SP_PARM; - ESCDELAY = value; + (void) SP_PARM; + ESCDELAY = value; #endif + } return code; } @@ -87,12 +93,16 @@ NCURSES_EXPORT(int) set_escdelay(int value) { int code; + if (value < 0) { + code = ERR; + } else { #if USE_REENTRANT - code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value); + code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value); #else - ESCDELAY = value; - code = OK; + ESCDELAY = value; + code = OK; #endif + } return code; } #endif @@ -125,7 +135,7 @@ _nc_use_meta(WINDOW *win) } #ifdef USE_TERM_DRIVER -# ifdef __MINGW32__ +# if defined(_NC_WINDOWS) && !defined(EXP_WIN32_DRIVER) static HANDLE _nc_get_handle(int fd) { @@ -146,7 +156,14 @@ check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl)) #ifdef USE_TERM_DRIVER TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp); rc = TCBOf(sp)->drv->td_testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl)); -# ifdef __MINGW32__ +# if defined(EXP_WIN32_DRIVER) + /* if we emulate terminfo on console, we have to use the console routine */ + if (IsTermInfoOnConsole(sp)) { + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay EVENTLIST_2nd(evl)); + } else +# elif defined(_NC_WINDOWS) /* if we emulate terminfo on console, we have to use the console routine */ if (IsTermInfoOnConsole(sp)) { HANDLE fd = _nc_get_handle(sp->_ifd); @@ -154,29 +171,36 @@ check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl)) } else # endif rc = TCB->drv->td_testmouse(TCB, delay EVENTLIST_2nd(evl)); -#else -#if USE_SYSMOUSE +#else /* !USE_TERM_DRIVER */ +# if USE_SYSMOUSE if ((sp->_mouse_type == M_SYSMOUSE) && (sp->_sysmouse_head < sp->_sysmouse_tail)) { rc = TW_MOUSE; } else -#endif +# endif { +# if defined(EXP_WIN32_DRIVER) + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay + EVENTLIST_2nd(evl)); +# else rc = _nc_timed_wait(sp, TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl)); -#if USE_SYSMOUSE +# endif +# if USE_SYSMOUSE if ((sp->_mouse_type == M_SYSMOUSE) && (sp->_sysmouse_head < sp->_sysmouse_tail) && (rc == 0) && (errno == EINTR)) { rc |= TW_MOUSE; } -#endif +# endif } -#endif +#endif /* USE_TERM_DRIVER */ return rc; } @@ -224,11 +248,6 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) if (tail < 0) return ERR; -#ifdef HIDE_EINTR - again: - errno = 0; -#endif - #ifdef NCURSES_WGETCH_EVENTS if (evl #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE @@ -279,58 +298,52 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) } else #endif #if USE_KLIBC_KBD - if (NC_ISATTY(sp->_ifd) && sp->_cbreak) { - ch = _read_kbd(0, 1, !sp->_raw); + if (NC_ISATTY(sp->_ifd) && IsCbreak(sp)) { + ch = _read_kbd(0, 1, !IsRaw(sp)); n = (ch == -1) ? -1 : 1; sp->_extended_key = (ch == 0); } else #endif { /* Can block... */ -#ifdef USE_TERM_DRIVER +#if defined(USE_TERM_DRIVER) int buf; -#ifdef __MINGW32__ - if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && sp->_cbreak) +# if defined(EXP_WIN32_DRIVER) + if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp)) { + _nc_set_read_thread(TRUE); + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + &buf); + _nc_set_read_thread(FALSE); + } else +# elif defined(_NC_WINDOWS) + if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp)) n = _nc_mingw_console_read(sp, _nc_get_handle(sp->_ifd), &buf); else -#endif +# endif /* EXP_WIN32_DRIVER */ n = CallDriver_1(sp, td_read, &buf); ch = buf; -#else +#else /* !USE_TERM_DRIVER */ +#if defined(EXP_WIN32_DRIVER) + int buf; +#endif unsigned char c2 = 0; -# if USE_PTHREADS_EINTR -# if USE_WEAK_SYMBOLS - if ((pthread_self) && (pthread_kill) && (pthread_equal)) -# endif - _nc_globals.read_thread = pthread_self(); -# endif + + _nc_set_read_thread(TRUE); +#if defined(EXP_WIN32_DRIVER) + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + &buf); + c2 = buf; +#else n = (int) read(sp->_ifd, &c2, (size_t) 1); -#if USE_PTHREADS_EINTR - _nc_globals.read_thread = 0; #endif + _nc_set_read_thread(FALSE); ch = c2; -#endif +#endif /* USE_TERM_DRIVER */ } -#ifdef HIDE_EINTR - /* - * Under System V curses with non-restarting signals, getch() returns - * with value ERR when a handled signal keeps it from completing. - * If signals restart system calls, OTOH, the signal is invisible - * except to its handler. - * - * We don't want this difference to show. This piece of code - * tries to make it look like we always have restarting signals. - */ - if (n <= 0 && errno == EINTR -# if USE_PTHREADS_EINTR - && (_nc_globals.have_sigwinch == 0) -# endif - ) - goto again; -#endif - if ((n == -1) || (n == 0)) { TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno)); ch = ERR; @@ -360,14 +373,24 @@ fifo_clear(SCREEN *sp) tail = peek = 0; } -static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl)); +static int kgetch(SCREEN *, bool EVENTLIST_2nd(_nc_eventlist *)); static void recur_wrefresh(WINDOW *win) { #ifdef USE_PTHREADS SCREEN *sp = _nc_screen_of(win); - if (_nc_use_pthreads && sp != CURRENT_SCREEN) { + bool same_sp; + + if (_nc_use_pthreads) { + _nc_lock_global(curses); + same_sp = (sp == CURRENT_SCREEN); + _nc_unlock_global(curses); + } else { + same_sp = (sp == CURRENT_SCREEN); + } + + if (_nc_use_pthreads && !same_sp) { SCREEN *save_SP; /* temporarily switch to the window's screen to check/refresh */ @@ -380,7 +403,7 @@ recur_wrefresh(WINDOW *win) } else #endif if ((is_wintouched(win) || (win->_flags & _HASMOVED)) - && !(win->_flags & _ISPAD)) { + && !IS_PAD(win)) { wrefresh(win); } } @@ -456,8 +479,8 @@ _nc_wgetch(WINDOW *win, */ if (head == -1 && !sp->_notty && - !sp->_raw && - !sp->_cbreak && + !IsRaw(sp) && + !IsCbreak(sp) && !sp->_called_wgetch) { char buf[MAXCOLUMNS], *bufp; @@ -490,13 +513,13 @@ _nc_wgetch(WINDOW *win, recur_wrefresh(win); - if (win->_notimeout || (win->_delay >= 0) || (sp->_cbreak > 1)) { + if (win->_notimeout || (win->_delay >= 0) || (IsCbreak(sp) > 1)) { if (head == -1) { /* fifo is empty */ int delay; TR(TRACE_IEVENT, ("timed delay in wgetch()")); - if (sp->_cbreak > 1) - delay = (sp->_cbreak - 1) * 100; + if (IsCbreak(sp) > 1) + delay = (IsCbreak(sp) - 1) * 100; else delay = win->_delay; @@ -527,7 +550,7 @@ _nc_wgetch(WINDOW *win, * This is tricky. We only want to get special-key * events one at a time. But we want to accumulate * mouse events until either (a) the mouse logic tells - * us it's picked up a complete gesture, or (b) + * us it has picked up a complete gesture, or (b) * there's a detectable time lapse after one. * * Note: if the mouse code starts failing to compose @@ -537,7 +560,7 @@ _nc_wgetch(WINDOW *win, int runcount = 0; do { - ch = kgetch(sp EVENTLIST_2nd(evl)); + ch = kgetch(sp, win->_notimeout EVENTLIST_2nd(evl)); if (ch == KEY_MOUSE) { ++runcount; if (sp->_mouse_inline(sp)) @@ -615,7 +638,7 @@ _nc_wgetch(WINDOW *win, * However, we provide the same visual result as Solaris, moving the * cursor to the left. */ - if (sp->_echo && !(win->_flags & _ISPAD)) { + if (IsEcho(sp) && !IS_PAD(win)) { chtype backup = (chtype) ((ch == KEY_BACKSPACE) ? '\b' : ch); if (backup < KEY_MIN) wechochar(win, backup); @@ -624,7 +647,7 @@ _nc_wgetch(WINDOW *win, /* * Simulate ICRNL mode */ - if ((ch == '\r') && sp->_nl) + if ((ch == '\r') && IsNl(sp)) ch = '\n'; /* Strip 8th-bit if so desired. We do this only for characters that @@ -649,7 +672,7 @@ wgetch_events(WINDOW *win, _nc_eventlist * evl) int code; int value; - T((T_CALLED("wgetch_events(%p,%p)"), win, evl)); + T((T_CALLED("wgetch_events(%p,%p)"), (void *) win, (void *) evl)); code = _nc_wgetch(win, &value, _nc_use_meta(win) @@ -692,11 +715,11 @@ wgetch(WINDOW *win) */ static int -kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) +kgetch(SCREEN *sp, bool forever EVENTLIST_2nd(_nc_eventlist * evl)) { TRIES *ptr; int ch = 0; - int timeleft = GetEscdelay(sp); + int timeleft = forever ? 9999999 : GetEscdelay(sp); TR(TRACE_IEVENT, ("kgetch() called"));