lib_twait.c revision 50276
1/**************************************************************************** 2 * Copyright (c) 1998 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29/**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 ****************************************************************************/ 33 34/* 35** lib_twait.c 36** 37** The routine _nc_timed_wait(). 38** 39** (This file was originally written by Eric Raymond; however except for 40** comments, none of the original code remains - T.Dickey). 41*/ 42 43#include <curses.priv.h> 44 45#if USE_FUNC_POLL 46# include <stropts.h> 47# include <poll.h> 48# if HAVE_SYS_TIME_H 49# include <sys/time.h> 50# endif 51#elif HAVE_SELECT 52# if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT 53# include <sys/time.h> 54# endif 55# if HAVE_SYS_SELECT_H 56# include <sys/select.h> 57# endif 58#endif 59 60#ifdef __BEOS__ 61/* BeOS select() only works on sockets. Use the tty hack instead */ 62#include <socket.h> 63#define select check_select 64#endif 65 66MODULE_ID("$Id: lib_twait.c,v 1.32 1998/06/06 22:44:14 tom Exp $") 67 68static int _nc_gettime(void) 69{ 70 int res; 71 72#if HAVE_GETTIMEOFDAY 73# define PRECISE_GETTIME 1 74 struct timeval t; 75 gettimeofday(&t, (struct timezone *)0); 76 res = t.tv_sec*1000 + t.tv_usec/1000; 77#else 78# define PRECISE_GETTIME 0 79 res = time(0)*1000; 80#endif 81 T(("time: %d msec", res)); 82 return res; 83} 84 85/* 86 * Wait a specified number of milliseconds, returning nonzero if the timer 87 * didn't expire before there is activity on the specified file descriptors. 88 * The file-descriptors are specified by the mode: 89 * 0 - none (absolute time) 90 * 1 - ncurses' normal input-descriptor 91 * 2 - mouse descriptor, if any 92 * 3 - either input or mouse. 93 * We return a mask that corresponds to the mode (e.g., 2 for mouse activity). 94 * 95 * If the milliseconds given are -1, the wait blocks until activity on the 96 * descriptors. 97 */ 98int _nc_timed_wait(int mode, int milliseconds, int *timeleft) 99{ 100int fd; 101int count; 102 103int result; 104 105#if USE_FUNC_POLL 106struct pollfd fds[2]; 107#elif HAVE_SELECT 108static fd_set set; 109#endif 110 111int starttime, returntime; 112 113 T(("start twait: %d milliseconds, mode: %d", milliseconds, mode)); 114 115#if PRECISE_GETTIME 116retry: 117#endif 118 starttime = _nc_gettime(); 119 120 count = 0; 121 122#if USE_FUNC_POLL 123 if (mode & 1) { 124 fds[count].fd = SP->_ifd; 125 fds[count].events = POLLIN; 126 count++; 127 } 128 if ((mode & 2) 129 && (fd = SP->_mouse_fd) >= 0) { 130 fds[count].fd = fd; 131 fds[count].events = POLLIN; 132 count++; 133 } 134 result = poll(fds, count, milliseconds); 135 136#elif HAVE_SELECT 137 /* 138 * select() modifies the fd_set arguments; do this in the 139 * loop. 140 */ 141 FD_ZERO(&set); 142 143 if (mode & 1) { 144 FD_SET(SP->_ifd, &set); 145 count = SP->_ifd + 1; 146 } 147 if ((mode & 2) 148 && (fd = SP->_mouse_fd) >= 0) { 149 FD_SET(fd, &set); 150 count = max(fd, count) + 1; 151 } 152 153 if (milliseconds >= 0) { 154 struct timeval ntimeout; 155 ntimeout.tv_sec = milliseconds / 1000; 156 ntimeout.tv_usec = (milliseconds % 1000) * 1000; 157 result = select(count, &set, NULL, NULL, &ntimeout); 158 } else { 159 result = select(count, &set, NULL, NULL, NULL); 160 } 161#endif 162 163 returntime = _nc_gettime(); 164 165 if (milliseconds >= 0) 166 milliseconds -= returntime-starttime; 167 168#if PRECISE_GETTIME 169 /* 170 * If the timeout hasn't expired, and we've gotten no data, 171 * this is probably a system where 'select()' needs to be left 172 * alone so that it can complete. Make this process sleep, 173 * then come back for more. 174 */ 175 if (result == 0 && milliseconds > 100) { 176 napms(100); 177 milliseconds -= 100; 178 goto retry; 179 } 180#endif 181 182 /* return approximate time left in milliseconds */ 183 if (timeleft) 184 *timeleft = milliseconds; 185 186 T(("end twait: returned %d (%d), remaining time %d msec", 187 result, errno, milliseconds)); 188 189 /* 190 * Both 'poll()' and 'select()' return the number of file descriptors 191 * that are active. Translate this back to the mask that denotes which 192 * file-descriptors, so that we don't need all of this system-specific 193 * code everywhere. 194 */ 195 if (result != 0) { 196 if (result > 0) { 197 result = 0; 198#if USE_FUNC_POLL 199 for (count = 0; count < 2; count++) { 200 if ((mode & (1 << count)) 201 && (fds[count].revents & POLLIN)) { 202 result |= (1 << count); 203 count++; 204 } 205 } 206#elif HAVE_SELECT 207 if ((mode & 2) 208 && (fd = SP->_mouse_fd) >= 0 209 && FD_ISSET(fd, &set)) 210 result |= 2; 211 if ((mode & 1) 212 && FD_ISSET(SP->_ifd, &set)) 213 result |= 1; 214#endif 215 } 216 else 217 result = 0; 218 } 219 220 return (result); 221} 222