From 4a1a95108dd76c4259fe6c37c4471f7969b17983 Mon Sep 17 00:00:00 2001 From: Rong-En Fan Date: Sat, 20 Jan 2007 07:32:02 +0000 Subject: Import ncurses 5.6-20061217 onto the vender branch Approved by: delphij --- contrib/ncurses/ncurses/tty/lib_twait.c | 213 +++++++++++++++++++++++++++++--- 1 file changed, 194 insertions(+), 19 deletions(-) (limited to 'contrib/ncurses/ncurses/tty/lib_twait.c') diff --git a/contrib/ncurses/ncurses/tty/lib_twait.c b/contrib/ncurses/ncurses/tty/lib_twait.c index 9829a7eec8ef..28e503f331f6 100644 --- a/contrib/ncurses/ncurses/tty/lib_twait.c +++ b/contrib/ncurses/ncurses/tty/lib_twait.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * + * Copyright (c) 1998-2004,2006 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 * @@ -61,7 +61,7 @@ # endif #endif -MODULE_ID("$Id: lib_twait.c,v 1.44 2002/04/21 21:06:29 tom Exp $") +MODULE_ID("$Id: lib_twait.c,v 1.51 2006/05/27 21:57:43 tom Exp $") static long _nc_gettime(bool first) @@ -75,9 +75,16 @@ _nc_gettime(bool first) gettimeofday(&t1, (struct timezone *) 0); if (first) { t0 = t1; + res = 0; + } else { + /* .tv_sec and .tv_usec are unsigned, be careful when subtracting */ + if (t0.tv_usec > t1.tv_usec) { /* Convert 1s in 1e6 microsecs */ + t1.tv_usec += 1000000; + t1.tv_sec--; + } + res = (t1.tv_sec - t0.tv_sec) * 1000 + + (t1.tv_usec - t0.tv_usec) / 1000; } - res = (t1.tv_sec - t0.tv_sec) * 1000 - + (t1.tv_usec - t0.tv_usec) / 1000; #else # define PRECISE_GETTIME 0 static time_t t0; @@ -91,6 +98,29 @@ _nc_gettime(bool first) return res; } +#ifdef NCURSES_WGETCH_EVENTS +NCURSES_EXPORT(int) +_nc_eventlist_timeout(_nc_eventlist * evl) +{ + int event_delay = -1; + int n; + + if (evl != 0) { + + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_TIMEOUT_MSEC) { + event_delay = ev->data.timeout_msec; + if (event_delay < 0) + event_delay = INT_MAX; /* FIXME Is this defined? */ + } + } + } + return event_delay; +} +#endif /* NCURSES_WGETCH_EVENTS */ + /* * Wait a specified number of milliseconds, returning nonzero if the timer * didn't expire before there is activity on the specified file descriptors. @@ -99,21 +129,35 @@ _nc_gettime(bool first) * 1 - ncurses' normal input-descriptor * 2 - mouse descriptor, if any * 3 - either input or mouse. + * + * Experimental: if NCURSES_WGETCH_EVENTS is defined, (mode & 4) determines + * whether to pay attention to evl argument. If set, the smallest of + * millisecond and of timeout of evl is taken. + * * We return a mask that corresponds to the mode (e.g., 2 for mouse activity). * * If the milliseconds given are -1, the wait blocks until activity on the * descriptors. */ NCURSES_EXPORT(int) -_nc_timed_wait(int mode, int milliseconds, int *timeleft) +_nc_timed_wait(int mode, + int milliseconds, + int *timeleft + EVENTLIST_2nd(_nc_eventlist * evl)) { int fd; int count; - int result; +#ifdef NCURSES_WGETCH_EVENTS + int timeout_is_event = 0; + int n; +#endif + #if USE_FUNC_POLL - struct pollfd fds[2]; +#define MIN_FDS 2 + struct pollfd fd_list[MIN_FDS]; + struct pollfd *fds = fd_list; #elif defined(__BEOS__) #elif HAVE_SELECT static fd_set set; @@ -121,11 +165,21 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) long starttime, returntime; - if (milliseconds < 0) - milliseconds = 0; TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d", milliseconds, mode)); +#ifdef NCURSES_WGETCH_EVENTS + if (mode & 4) { + int event_delay = _nc_eventlist_timeout(evl); + + if (event_delay >= 0 + && (milliseconds >= event_delay || milliseconds < 0)) { + milliseconds = event_delay; + timeout_is_event = 1; + } + } +#endif + #if PRECISE_GETTIME retry: #endif @@ -133,8 +187,19 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) count = 0; +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) + evl->result_flags = 0; +#endif + #if USE_FUNC_POLL - memset(fds, 0, sizeof(fds)); + memset(fd_list, 0, sizeof(fd_list)); + +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) + fds = typeMalloc(struct pollfd, MIN_FDS + evl->count); +#endif + if (mode & 1) { fds[count].fd = SP->_ifd; fds[count].events = POLLIN; @@ -146,7 +211,53 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) fds[count].events = POLLIN; count++; } - result = poll(fds, count, milliseconds); +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) { + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_FILE + && (ev->data.fev.flags & _NC_EVENT_FILE_READABLE)) { + fds[count].fd = ev->data.fev.fd; + fds[count].events = POLLIN; + count++; + } + } + } +#endif + + result = poll(fds, (unsigned) count, milliseconds); + +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) { + int c; + + if (!result) + count = 0; + + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_FILE + && (ev->data.fev.flags & _NC_EVENT_FILE_READABLE)) { + ev->data.fev.result = 0; + for (c = 0; c < count; c++) + if (fds[c].fd == ev->data.fev.fd + && fds[c].revents & POLLIN) { + ev->data.fev.result |= _NC_EVENT_FILE_READABLE; + evl->result_flags |= _NC_EVENT_FILE_READABLE; + } + } else if (ev->type == _NC_EVENT_TIMEOUT_MSEC + && !result && timeout_is_event) { + evl->result_flags |= _NC_EVENT_TIMEOUT_MSEC; + } + } + } + + if (fds != fd_list) + free((char *) fds); + +#endif #elif defined(__BEOS__) /* @@ -157,26 +268,34 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) * * FIXME: the return values from the ioctl aren't very clear if we get * interrupted. + * + * FIXME: this assumes mode&1 if milliseconds < 0 (see lib_getch.c). */ result = 0; if (mode & 1) { + int step = (milliseconds < 0) ? 0 : 5000; bigtime_t d; bigtime_t useconds = milliseconds * 1000; int n, howmany; - if (useconds == 0) /* we're here to go _through_ the loop */ + if (useconds <= 0) /* we're here to go _through_ the loop */ useconds = 1; - for (d = 0; d < useconds; d += 5000) { + for (d = 0; d < useconds; d += step) { n = 0; howmany = ioctl(0, 'ichr', &n); if (howmany >= 0 && n > 0) { result = 1; break; } - if (useconds > 1) - snooze(5000); - milliseconds -= 5; + if (useconds > 1 && step > 0) { + snooze(step); + milliseconds -= (step / 1000); + if (milliseconds <= 0) { + milliseconds = 0; + break; + } + } } } else if (milliseconds > 0) { snooze(milliseconds * 1000); @@ -198,6 +317,19 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) FD_SET(fd, &set); count = max(fd, count) + 1; } +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) { + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_FILE + && (ev->data.fev.flags & _NC_EVENT_FILE_READABLE)) { + FD_SET(ev->data.fev.fd, &set); + count = max(ev->data.fev.fd + 1, count); + } + } + } +#endif if (milliseconds >= 0) { struct timeval ntimeout; @@ -207,14 +339,53 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) } else { result = select(count, &set, NULL, NULL, NULL); } + +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl) { + evl->result_flags = 0; + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_FILE + && (ev->data.fev.flags & _NC_EVENT_FILE_READABLE)) { + ev->data.fev.result = 0; + if (FD_ISSET(ev->data.fev.fd, &set)) { + ev->data.fev.result |= _NC_EVENT_FILE_READABLE; + evl->result_flags |= _NC_EVENT_FILE_READABLE; + } + } else if (ev->type == _NC_EVENT_TIMEOUT_MSEC + && !result && timeout_is_event) + evl->result_flags |= _NC_EVENT_TIMEOUT_MSEC; + } + } #endif +#endif /* USE_FUNC_POLL, etc */ + returntime = _nc_gettime(FALSE); if (milliseconds >= 0) milliseconds -= (returntime - starttime); -#if PRECISE_GETTIME +#ifdef NCURSES_WGETCH_EVENTS + if (evl) { + evl->result_flags = 0; + for (n = 0; n < evl->count; ++n) { + _nc_event *ev = evl->events[n]; + + if (ev->type == _NC_EVENT_TIMEOUT_MSEC) { + long diff = (returntime - starttime); + if (ev->data.timeout_msec <= diff) + ev->data.timeout_msec = 0; + else + ev->data.timeout_msec -= diff; + } + + } + } +#endif + +#if PRECISE_GETTIME && HAVE_NANOSLEEP /* * If the timeout hasn't expired, and we've gotten no data, * this is probably a system where 'select()' needs to be left @@ -222,7 +393,7 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) * then come back for more. */ if (result == 0 && milliseconds > 100) { - napms(100); + napms(100); /* FIXME: this won't be right if I recur! */ milliseconds -= 100; goto retry; } @@ -245,7 +416,7 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) if (result > 0) { result = 0; #if USE_FUNC_POLL - for (count = 0; count < 2; count++) { + for (count = 0; count < MIN_FDS; count++) { if ((mode & (1 << count)) && (fds[count].revents & POLLIN)) { result |= (1 << count); @@ -265,6 +436,10 @@ _nc_timed_wait(int mode, int milliseconds, int *timeleft) } else result = 0; } +#ifdef NCURSES_WGETCH_EVENTS + if ((mode & 4) && evl && evl->result_flags) + result |= 4; +#endif return (result); } -- cgit v1.2.3