Blame


1 11a5e2cf 2024-01-16 benni /* $NetBSD: input.c,v 1.11 2009/05/25 04:33:53 dholland Exp $ */
2 11a5e2cf 2024-01-16 benni
3 11a5e2cf 2024-01-16 benni /*-
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.
6 11a5e2cf 2024-01-16 benni *
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.
9 11a5e2cf 2024-01-16 benni *
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
12 11a5e2cf 2024-01-16 benni * are met:
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.
21 11a5e2cf 2024-01-16 benni *
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.
33 11a5e2cf 2024-01-16 benni *
34 11a5e2cf 2024-01-16 benni * @(#)input.c 8.1 (Berkeley) 5/31/93
35 11a5e2cf 2024-01-16 benni */
36 11a5e2cf 2024-01-16 benni
37 11a5e2cf 2024-01-16 benni /*
38 11a5e2cf 2024-01-16 benni * Tetris input.
39 11a5e2cf 2024-01-16 benni */
40 11a5e2cf 2024-01-16 benni
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>
44 11a5e2cf 2024-01-16 benni
45 11a5e2cf 2024-01-16 benni #include <errno.h>
46 11a5e2cf 2024-01-16 benni #include <unistd.h>
47 11a5e2cf 2024-01-16 benni
48 11a5e2cf 2024-01-16 benni #include "input.h"
49 11a5e2cf 2024-01-16 benni #include "tetris.h"
50 11a5e2cf 2024-01-16 benni
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))
54 11a5e2cf 2024-01-16 benni
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--; \
62 11a5e2cf 2024-01-16 benni }
63 11a5e2cf 2024-01-16 benni
64 11a5e2cf 2024-01-16 benni /*
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.
69 11a5e2cf 2024-01-16 benni *
70 11a5e2cf 2024-01-16 benni * If tvp is nil, wait forever, but return if poll is interrupted.
71 11a5e2cf 2024-01-16 benni *
72 11a5e2cf 2024-01-16 benni * Return 0 => no input, 1 => can read() from stdin
73 11a5e2cf 2024-01-16 benni */
74 11a5e2cf 2024-01-16 benni int
75 11a5e2cf 2024-01-16 benni rwait(struct timeval *tvp)
76 11a5e2cf 2024-01-16 benni {
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)
81 11a5e2cf 2024-01-16 benni
82 11a5e2cf 2024-01-16 benni if (tvp) {
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;
86 11a5e2cf 2024-01-16 benni } else
87 11a5e2cf 2024-01-16 benni timeout = INFTIM;
88 11a5e2cf 2024-01-16 benni again:
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)) {
92 11a5e2cf 2024-01-16 benni
93 11a5e2cf 2024-01-16 benni case -1:
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 */
100 11a5e2cf 2024-01-16 benni
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;
105 11a5e2cf 2024-01-16 benni }
106 11a5e2cf 2024-01-16 benni return (0);
107 11a5e2cf 2024-01-16 benni }
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 */
113 11a5e2cf 2024-01-16 benni }
114 11a5e2cf 2024-01-16 benni return (1);
115 11a5e2cf 2024-01-16 benni }
116 11a5e2cf 2024-01-16 benni
117 11a5e2cf 2024-01-16 benni /*
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.
120 11a5e2cf 2024-01-16 benni */
121 11a5e2cf 2024-01-16 benni void
122 11a5e2cf 2024-01-16 benni tsleep(void)
123 11a5e2cf 2024-01-16 benni {
124 11a5e2cf 2024-01-16 benni struct timeval tv;
125 11a5e2cf 2024-01-16 benni char c;
126 11a5e2cf 2024-01-16 benni
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)
131 11a5e2cf 2024-01-16 benni break;
132 11a5e2cf 2024-01-16 benni }
133 11a5e2cf 2024-01-16 benni
134 11a5e2cf 2024-01-16 benni /*
135 11a5e2cf 2024-01-16 benni * getchar with timeout.
136 11a5e2cf 2024-01-16 benni */
137 11a5e2cf 2024-01-16 benni int
138 11a5e2cf 2024-01-16 benni tgetchar(void)
139 11a5e2cf 2024-01-16 benni {
140 11a5e2cf 2024-01-16 benni static struct timeval timeleft;
141 11a5e2cf 2024-01-16 benni char c;
142 11a5e2cf 2024-01-16 benni
143 11a5e2cf 2024-01-16 benni /*
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.
149 11a5e2cf 2024-01-16 benni *
150 11a5e2cf 2024-01-16 benni * Most of the hard work is done by rwait().
151 11a5e2cf 2024-01-16 benni */
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;
156 11a5e2cf 2024-01-16 benni }
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);
162 11a5e2cf 2024-01-16 benni }