1 11a5e2cf 2024-01-16 benni /* $NetBSD: input.c,v 1.11 2009/05/25 04:33:53 dholland Exp $ */
4 11a5e2cf 2024-01-16 benni * Copyright (c) 1992, 1993
5 11a5e2cf 2024-01-16 benni * The Regents of the University of California. All rights reserved.
7 11a5e2cf 2024-01-16 benni * This code is derived from software contributed to Berkeley by
8 11a5e2cf 2024-01-16 benni * Chris Torek and Darren F. Provine.
10 11a5e2cf 2024-01-16 benni * Redistribution and use in source and binary forms, with or without
11 11a5e2cf 2024-01-16 benni * modification, are permitted provided that the following conditions
13 11a5e2cf 2024-01-16 benni * 1. Redistributions of source code must retain the above copyright
14 11a5e2cf 2024-01-16 benni * notice, this list of conditions and the following disclaimer.
15 11a5e2cf 2024-01-16 benni * 2. Redistributions in binary form must reproduce the above copyright
16 11a5e2cf 2024-01-16 benni * notice, this list of conditions and the following disclaimer in the
17 11a5e2cf 2024-01-16 benni * documentation and/or other materials provided with the distribution.
18 11a5e2cf 2024-01-16 benni * 3. Neither the name of the University nor the names of its contributors
19 11a5e2cf 2024-01-16 benni * may be used to endorse or promote products derived from this software
20 11a5e2cf 2024-01-16 benni * without specific prior written permission.
22 11a5e2cf 2024-01-16 benni * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 11a5e2cf 2024-01-16 benni * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 11a5e2cf 2024-01-16 benni * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 11a5e2cf 2024-01-16 benni * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 11a5e2cf 2024-01-16 benni * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 11a5e2cf 2024-01-16 benni * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 11a5e2cf 2024-01-16 benni * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 11a5e2cf 2024-01-16 benni * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 11a5e2cf 2024-01-16 benni * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 11a5e2cf 2024-01-16 benni * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 11a5e2cf 2024-01-16 benni * SUCH DAMAGE.
34 11a5e2cf 2024-01-16 benni * @(#)input.c 8.1 (Berkeley) 5/31/93
38 11a5e2cf 2024-01-16 benni * Tetris input.
41 11a5e2cf 2024-01-16 benni #include <sys/types.h>
42 11a5e2cf 2024-01-16 benni #include <sys/time.h>
43 11a5e2cf 2024-01-16 benni #include <sys/poll.h>
45 11a5e2cf 2024-01-16 benni #include <errno.h>
46 11a5e2cf 2024-01-16 benni #include <unistd.h>
48 11a5e2cf 2024-01-16 benni #include "input.h"
49 11a5e2cf 2024-01-16 benni #include "tetris.h"
51 11a5e2cf 2024-01-16 benni /* return true iff the given timeval is positive */
52 11a5e2cf 2024-01-16 benni #define TV_POS(tv) \
53 11a5e2cf 2024-01-16 benni ((tv)->tv_sec > 0 || ((tv)->tv_sec == 0 && (tv)->tv_usec > 0))
55 11a5e2cf 2024-01-16 benni /* subtract timeval `sub' from `res' */
56 11a5e2cf 2024-01-16 benni #define TV_SUB(res, sub) \
57 11a5e2cf 2024-01-16 benni (res)->tv_sec -= (sub)->tv_sec; \
58 11a5e2cf 2024-01-16 benni (res)->tv_usec -= (sub)->tv_usec; \
59 11a5e2cf 2024-01-16 benni if ((res)->tv_usec < 0) { \
60 11a5e2cf 2024-01-16 benni (res)->tv_usec += 1000000; \
61 11a5e2cf 2024-01-16 benni (res)->tv_sec--; \
65 11a5e2cf 2024-01-16 benni * Do a `read wait': poll for reading from stdin, with timeout *tvp.
66 11a5e2cf 2024-01-16 benni * On return, modify *tvp to reflect the amount of time spent waiting.
67 11a5e2cf 2024-01-16 benni * It will be positive only if input appeared before the time ran out;
68 11a5e2cf 2024-01-16 benni * otherwise it will be zero or perhaps negative.
70 11a5e2cf 2024-01-16 benni * If tvp is nil, wait forever, but return if poll is interrupted.
72 11a5e2cf 2024-01-16 benni * Return 0 => no input, 1 => can read() from stdin
75 11a5e2cf 2024-01-16 benni rwait(struct timeval *tvp)
77 11a5e2cf 2024-01-16 benni struct pollfd set[1];
78 11a5e2cf 2024-01-16 benni struct timeval starttv, endtv;
79 11a5e2cf 2024-01-16 benni int timeout;
80 11a5e2cf 2024-01-16 benni #define NILTZ ((struct timezone *)0)
83 11a5e2cf 2024-01-16 benni (void) gettimeofday(&starttv, NILTZ);
84 11a5e2cf 2024-01-16 benni endtv = *tvp;
85 11a5e2cf 2024-01-16 benni timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
87 11a5e2cf 2024-01-16 benni timeout = INFTIM;
89 11a5e2cf 2024-01-16 benni set[0].fd = STDIN_FILENO;
90 11a5e2cf 2024-01-16 benni set[0].events = POLLIN;
91 11a5e2cf 2024-01-16 benni switch (poll(set, 1, timeout)) {
94 11a5e2cf 2024-01-16 benni if (tvp == 0)
95 11a5e2cf 2024-01-16 benni return (-1);
96 11a5e2cf 2024-01-16 benni if (errno == EINTR)
97 11a5e2cf 2024-01-16 benni goto again;
98 11a5e2cf 2024-01-16 benni stop("poll failed, help");
99 11a5e2cf 2024-01-16 benni /* NOTREACHED */
101 11a5e2cf 2024-01-16 benni case 0: /* timed out */
102 11a5e2cf 2024-01-16 benni if (tvp) {
103 11a5e2cf 2024-01-16 benni tvp->tv_sec = 0;
104 11a5e2cf 2024-01-16 benni tvp->tv_usec = 0;
106 11a5e2cf 2024-01-16 benni return (0);
108 11a5e2cf 2024-01-16 benni if (tvp) {
109 11a5e2cf 2024-01-16 benni /* since there is input, we may not have timed out */
110 11a5e2cf 2024-01-16 benni (void) gettimeofday(&endtv, NILTZ);
111 11a5e2cf 2024-01-16 benni TV_SUB(&endtv, &starttv);
112 11a5e2cf 2024-01-16 benni TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
114 11a5e2cf 2024-01-16 benni return (1);
118 11a5e2cf 2024-01-16 benni * `sleep' for the current turn time.
119 11a5e2cf 2024-01-16 benni * Eat any input that might be available.
122 11a5e2cf 2024-01-16 benni tsleep(void)
124 11a5e2cf 2024-01-16 benni struct timeval tv;
127 11a5e2cf 2024-01-16 benni tv.tv_sec = 0;
128 11a5e2cf 2024-01-16 benni tv.tv_usec = fallrate;
129 11a5e2cf 2024-01-16 benni while (TV_POS(&tv))
130 11a5e2cf 2024-01-16 benni if (rwait(&tv) && read(0, &c, 1) != 1)
135 11a5e2cf 2024-01-16 benni * getchar with timeout.
138 11a5e2cf 2024-01-16 benni tgetchar(void)
140 11a5e2cf 2024-01-16 benni static struct timeval timeleft;
144 11a5e2cf 2024-01-16 benni * Reset timeleft to fallrate whenever it is not positive.
145 11a5e2cf 2024-01-16 benni * In any case, wait to see if there is any input. If so,
146 11a5e2cf 2024-01-16 benni * take it, and update timeleft so that the next call to
147 11a5e2cf 2024-01-16 benni * tgetchar() will not wait as long. If there is no input,
148 11a5e2cf 2024-01-16 benni * make timeleft zero or negative, and return -1.
150 11a5e2cf 2024-01-16 benni * Most of the hard work is done by rwait().
152 11a5e2cf 2024-01-16 benni if (!TV_POS(&timeleft)) {
153 11a5e2cf 2024-01-16 benni faster(); /* go faster */
154 11a5e2cf 2024-01-16 benni timeleft.tv_sec = 0;
155 11a5e2cf 2024-01-16 benni timeleft.tv_usec = fallrate;
157 11a5e2cf 2024-01-16 benni if (!rwait(&timeleft))
158 11a5e2cf 2024-01-16 benni return (-1);
159 11a5e2cf 2024-01-16 benni if (read(0, &c, 1) != 1)
160 11a5e2cf 2024-01-16 benni stop("end of file, help");
161 11a5e2cf 2024-01-16 benni return ((int)(unsigned char)c);