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 7b083439 2024-06-06 benni #ifndef INFTIM
52 7b083439 2024-06-06 benni # define INFTIM (-1)
55 11a5e2cf 2024-01-16 benni /* return true iff the given timeval is positive */
56 11a5e2cf 2024-01-16 benni #define TV_POS(tv) \
57 11a5e2cf 2024-01-16 benni ((tv)->tv_sec > 0 || ((tv)->tv_sec == 0 && (tv)->tv_usec > 0))
59 11a5e2cf 2024-01-16 benni /* subtract timeval `sub' from `res' */
60 11a5e2cf 2024-01-16 benni #define TV_SUB(res, sub) \
61 11a5e2cf 2024-01-16 benni (res)->tv_sec -= (sub)->tv_sec; \
62 11a5e2cf 2024-01-16 benni (res)->tv_usec -= (sub)->tv_usec; \
63 11a5e2cf 2024-01-16 benni if ((res)->tv_usec < 0) { \
64 11a5e2cf 2024-01-16 benni (res)->tv_usec += 1000000; \
65 11a5e2cf 2024-01-16 benni (res)->tv_sec--; \
69 11a5e2cf 2024-01-16 benni * Do a `read wait': poll for reading from stdin, with timeout *tvp.
70 11a5e2cf 2024-01-16 benni * On return, modify *tvp to reflect the amount of time spent waiting.
71 11a5e2cf 2024-01-16 benni * It will be positive only if input appeared before the time ran out;
72 11a5e2cf 2024-01-16 benni * otherwise it will be zero or perhaps negative.
74 11a5e2cf 2024-01-16 benni * If tvp is nil, wait forever, but return if poll is interrupted.
76 11a5e2cf 2024-01-16 benni * Return 0 => no input, 1 => can read() from stdin
79 11a5e2cf 2024-01-16 benni rwait(struct timeval *tvp)
81 11a5e2cf 2024-01-16 benni struct pollfd set[1];
82 11a5e2cf 2024-01-16 benni struct timeval starttv, endtv;
83 11a5e2cf 2024-01-16 benni int timeout;
84 11a5e2cf 2024-01-16 benni #define NILTZ ((struct timezone *)0)
87 11a5e2cf 2024-01-16 benni (void) gettimeofday(&starttv, NILTZ);
88 11a5e2cf 2024-01-16 benni endtv = *tvp;
89 11a5e2cf 2024-01-16 benni timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
91 11a5e2cf 2024-01-16 benni timeout = INFTIM;
93 11a5e2cf 2024-01-16 benni set[0].fd = STDIN_FILENO;
94 11a5e2cf 2024-01-16 benni set[0].events = POLLIN;
95 11a5e2cf 2024-01-16 benni switch (poll(set, 1, timeout)) {
98 11a5e2cf 2024-01-16 benni if (tvp == 0)
99 11a5e2cf 2024-01-16 benni return (-1);
100 11a5e2cf 2024-01-16 benni if (errno == EINTR)
101 11a5e2cf 2024-01-16 benni goto again;
102 11a5e2cf 2024-01-16 benni stop("poll failed, help");
103 11a5e2cf 2024-01-16 benni /* NOTREACHED */
105 11a5e2cf 2024-01-16 benni case 0: /* timed out */
106 11a5e2cf 2024-01-16 benni if (tvp) {
107 11a5e2cf 2024-01-16 benni tvp->tv_sec = 0;
108 11a5e2cf 2024-01-16 benni tvp->tv_usec = 0;
110 11a5e2cf 2024-01-16 benni return (0);
112 11a5e2cf 2024-01-16 benni if (tvp) {
113 11a5e2cf 2024-01-16 benni /* since there is input, we may not have timed out */
114 11a5e2cf 2024-01-16 benni (void) gettimeofday(&endtv, NILTZ);
115 11a5e2cf 2024-01-16 benni TV_SUB(&endtv, &starttv);
116 11a5e2cf 2024-01-16 benni TV_SUB(tvp, &endtv); /* adjust *tvp by elapsed time */
118 11a5e2cf 2024-01-16 benni return (1);
122 11a5e2cf 2024-01-16 benni * `sleep' for the current turn time.
123 11a5e2cf 2024-01-16 benni * Eat any input that might be available.
126 11a5e2cf 2024-01-16 benni tsleep(void)
128 11a5e2cf 2024-01-16 benni struct timeval tv;
131 11a5e2cf 2024-01-16 benni tv.tv_sec = 0;
132 11a5e2cf 2024-01-16 benni tv.tv_usec = fallrate;
133 11a5e2cf 2024-01-16 benni while (TV_POS(&tv))
134 11a5e2cf 2024-01-16 benni if (rwait(&tv) && read(0, &c, 1) != 1)
139 11a5e2cf 2024-01-16 benni * getchar with timeout.
142 11a5e2cf 2024-01-16 benni tgetchar(void)
144 11a5e2cf 2024-01-16 benni static struct timeval timeleft;
148 11a5e2cf 2024-01-16 benni * Reset timeleft to fallrate whenever it is not positive.
149 11a5e2cf 2024-01-16 benni * In any case, wait to see if there is any input. If so,
150 11a5e2cf 2024-01-16 benni * take it, and update timeleft so that the next call to
151 11a5e2cf 2024-01-16 benni * tgetchar() will not wait as long. If there is no input,
152 11a5e2cf 2024-01-16 benni * make timeleft zero or negative, and return -1.
154 11a5e2cf 2024-01-16 benni * Most of the hard work is done by rwait().
156 11a5e2cf 2024-01-16 benni if (!TV_POS(&timeleft)) {
157 11a5e2cf 2024-01-16 benni faster(); /* go faster */
158 11a5e2cf 2024-01-16 benni timeleft.tv_sec = 0;
159 11a5e2cf 2024-01-16 benni timeleft.tv_usec = fallrate;
161 11a5e2cf 2024-01-16 benni if (!rwait(&timeleft))
162 11a5e2cf 2024-01-16 benni return (-1);
163 11a5e2cf 2024-01-16 benni if (read(0, &c, 1) != 1)
164 11a5e2cf 2024-01-16 benni stop("end of file, help");
165 11a5e2cf 2024-01-16 benni return ((int)(unsigned char)c);