| @@ -1,429 +1,429 @@ | | | @@ -1,429 +1,429 @@ |
1 | /* $NetBSD: screen.c,v 1.30 2015/07/07 22:53:25 nat Exp $ */ | | 1 | /* $NetBSD: screen.c,v 1.31 2015/11/06 19:53:37 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1992, 1993 | | 4 | * Copyright (c) 1992, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Chris Torek and Darren F. Provine. | | 8 | * Chris Torek and Darren F. Provine. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors | | 18 | * 3. Neither the name of the University nor the names of its contributors |
19 | * may be used to endorse or promote products derived from this software | | 19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. | | 20 | * without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | * | | 33 | * |
34 | * @(#)screen.c 8.1 (Berkeley) 5/31/93 | | 34 | * @(#)screen.c 8.1 (Berkeley) 5/31/93 |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | /* | | 37 | /* |
38 | * Tetris screen control. | | 38 | * Tetris screen control. |
39 | */ | | 39 | */ |
40 | | | 40 | |
41 | #include <sys/cdefs.h> | | 41 | #include <sys/cdefs.h> |
42 | #include <sys/ioctl.h> | | 42 | #include <sys/ioctl.h> |
43 | | | 43 | |
44 | #include <setjmp.h> | | 44 | #include <setjmp.h> |
45 | #include <signal.h> | | 45 | #include <signal.h> |
46 | #include <stdio.h> | | 46 | #include <stdio.h> |
47 | #include <stdlib.h> | | 47 | #include <stdlib.h> |
48 | #include <string.h> | | 48 | #include <string.h> |
49 | #include <term.h> | | 49 | #include <term.h> |
50 | #include <termios.h> | | 50 | #include <termios.h> |
51 | #include <unistd.h> | | 51 | #include <unistd.h> |
52 | | | 52 | |
53 | #ifndef sigmask | | 53 | #ifndef sigmask |
54 | #define sigmask(s) (1 << ((s) - 1)) | | 54 | #define sigmask(s) (1 << ((s) - 1)) |
55 | #endif | | 55 | #endif |
56 | | | 56 | |
57 | #include "screen.h" | | 57 | #include "screen.h" |
58 | #include "tetris.h" | | 58 | #include "tetris.h" |
59 | | | 59 | |
60 | static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ | | 60 | static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ |
61 | static int curscore; | | 61 | static int curscore; |
62 | static int isset; /* true => terminal is in game mode */ | | 62 | static int isset; /* true => terminal is in game mode */ |
63 | static struct termios oldtt; | | 63 | static struct termios oldtt; |
64 | static void (*tstp)(int); | | 64 | static void (*tstp)(int); |
65 | | | 65 | |
66 | static void scr_stop(int); | | 66 | static void scr_stop(int); |
67 | static void stopset(int) __dead; | | 67 | static void stopset(int) __dead; |
68 | | | 68 | |
69 | | | 69 | |
70 | /* | | 70 | /* |
71 | * Routine used by tputs(). | | 71 | * Routine used by tputs(). |
72 | */ | | 72 | */ |
73 | int | | 73 | int |
74 | put(int c) | | 74 | put(int c) |
75 | { | | 75 | { |
76 | | | 76 | |
77 | return (putchar(c)); | | 77 | return (putchar(c)); |
78 | } | | 78 | } |
79 | | | 79 | |
80 | /* | | 80 | /* |
81 | * putstr() is for unpadded strings (either as in termcap(5) or | | 81 | * putstr() is for unpadded strings (either as in termcap(5) or |
82 | * simply literal strings); putpad() is for padded strings with | | 82 | * simply literal strings); putpad() is for padded strings with |
83 | * count=1. (See screen.h for putpad().) | | 83 | * count=1. (See screen.h for putpad().) |
84 | */ | | 84 | */ |
85 | #define putstr(s) (void)fputs(s, stdout) | | 85 | #define putstr(s) (void)fputs(s, stdout) |
86 | | | 86 | |
87 | static void | | 87 | static void |
88 | moveto(int r, int c) | | 88 | moveto(int r, int c) |
89 | { | | 89 | { |
90 | char *buf; | | 90 | char *buf; |
91 | | | 91 | |
92 | buf = tiparm(cursor_address, r, c); | | 92 | buf = tiparm(cursor_address, r, c); |
93 | if (buf != NULL) | | 93 | if (buf != NULL) |
94 | putpad(buf); | | 94 | putpad(buf); |
95 | } | | 95 | } |
96 | | | 96 | |
97 | static void | | 97 | static void |
98 | setcolor(int c) | | 98 | setcolor(int c) |
99 | { | | 99 | { |
100 | char *buf; | | 100 | char *buf; |
101 | char monochrome[] = "\033[0m"; | | 101 | char monochrome[] = "\033[0m"; |
102 | if (nocolor == 1) | | 102 | if (nocolor == 1) |
103 | return; | | 103 | return; |
104 | if (set_a_foreground == NULL) | | 104 | if (set_a_foreground == NULL) |
105 | return; | | 105 | return; |
106 | | | 106 | |
107 | if (c == 0 || c == 7) | | 107 | if (c == 0 || c == 7) |
108 | buf = monochrome; | | 108 | buf = monochrome; |
109 | else | | 109 | else |
110 | buf = tiparm(set_a_foreground, c); | | 110 | buf = tiparm(set_a_foreground, c); |
111 | if (buf != NULL) | | 111 | if (buf != NULL) |
112 | putpad(buf); | | 112 | putpad(buf); |
113 | } | | 113 | } |
114 | | | 114 | |
115 | /* | | 115 | /* |
116 | * Set up from termcap. | | 116 | * Set up from termcap. |
117 | */ | | 117 | */ |
118 | void | | 118 | void |
119 | scr_init(void) | | 119 | scr_init(void) |
120 | { | | 120 | { |
121 | | | 121 | |
122 | setupterm(NULL, 0, NULL); | | 122 | setupterm(NULL, 0, NULL); |
123 | if (clear_screen == NULL) | | 123 | if (clear_screen == NULL) |
124 | stop("cannot clear screen"); | | 124 | stop("cannot clear screen"); |
125 | if (cursor_address == NULL || cursor_up == NULL) | | 125 | if (cursor_address == NULL || cursor_up == NULL) |
126 | stop("cannot do random cursor positioning"); | | 126 | stop("cannot do random cursor positioning"); |
127 | } | | 127 | } |
128 | | | 128 | |
129 | /* this foolery is needed to modify tty state `atomically' */ | | 129 | /* this foolery is needed to modify tty state `atomically' */ |
130 | static jmp_buf scr_onstop; | | 130 | static jmp_buf scr_onstop; |
131 | | | 131 | |
132 | static void | | 132 | static void |
133 | stopset(int sig) | | 133 | stopset(int sig) |
134 | { | | 134 | { |
135 | sigset_t set; | | 135 | sigset_t set; |
136 | | | 136 | |
137 | (void) signal(sig, SIG_DFL); | | 137 | (void) signal(sig, SIG_DFL); |
138 | (void) kill(getpid(), sig); | | 138 | (void) kill(getpid(), sig); |
139 | sigemptyset(&set); | | 139 | sigemptyset(&set); |
140 | sigaddset(&set, sig); | | 140 | sigaddset(&set, sig); |
141 | (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); | | 141 | (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); |
142 | longjmp(scr_onstop, 1); | | 142 | longjmp(scr_onstop, 1); |
143 | } | | 143 | } |
144 | | | 144 | |
145 | static void | | 145 | static void |
146 | scr_stop(int sig) | | 146 | scr_stop(int sig) |
147 | { | | 147 | { |
148 | sigset_t set; | | 148 | sigset_t set; |
149 | | | 149 | |
150 | scr_end(); | | 150 | scr_end(); |
151 | (void) kill(getpid(), sig); | | 151 | (void) kill(getpid(), sig); |
152 | sigemptyset(&set); | | 152 | sigemptyset(&set); |
153 | sigaddset(&set, sig); | | 153 | sigaddset(&set, sig); |
154 | (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); | | 154 | (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); |
155 | scr_set(); | | 155 | scr_set(); |
156 | scr_msg(key_msg, 1); | | 156 | scr_msg(key_msg, 1); |
157 | } | | 157 | } |
158 | | | 158 | |
159 | /* | | 159 | /* |
160 | * Set up screen mode. | | 160 | * Set up screen mode. |
161 | */ | | 161 | */ |
162 | void | | 162 | void |
163 | scr_set(void) | | 163 | scr_set(void) |
164 | { | | 164 | { |
165 | struct winsize ws; | | 165 | struct winsize ws; |
166 | struct termios newtt; | | 166 | struct termios newtt; |
167 | sigset_t nsigset, osigset; | | 167 | sigset_t nsigset, osigset; |
168 | void (*ttou)(int); | | 168 | void (*ttou)(int); |
169 | | | 169 | |
170 | sigemptyset(&nsigset); | | 170 | sigemptyset(&nsigset); |
171 | sigaddset(&nsigset, SIGTSTP); | | 171 | sigaddset(&nsigset, SIGTSTP); |
172 | sigaddset(&nsigset, SIGTTOU); | | 172 | sigaddset(&nsigset, SIGTTOU); |
173 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 173 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
174 | if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN) | | 174 | if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN) |
175 | (void) signal(SIGTSTP, SIG_IGN); | | 175 | (void) signal(SIGTSTP, SIG_IGN); |
176 | if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN) | | 176 | if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN) |
177 | (void) signal(SIGTTOU, SIG_IGN); | | 177 | (void) signal(SIGTTOU, SIG_IGN); |
178 | /* | | 178 | /* |
179 | * At last, we are ready to modify the tty state. If | | 179 | * At last, we are ready to modify the tty state. If |
180 | * we stop while at it, stopset() above will longjmp back | | 180 | * we stop while at it, stopset() above will longjmp back |
181 | * to the setjmp here and we will start over. | | 181 | * to the setjmp here and we will start over. |
182 | */ | | 182 | */ |
183 | (void) setjmp(scr_onstop); | | 183 | (void) setjmp(scr_onstop); |
184 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 184 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
185 | Rows = 0, Cols = 0; | | 185 | Rows = 0, Cols = 0; |
186 | if (ioctl(0, TIOCGWINSZ, &ws) == 0) { | | 186 | if (ioctl(0, TIOCGWINSZ, &ws) == 0) { |
187 | Rows = ws.ws_row; | | 187 | Rows = ws.ws_row; |
188 | Cols = ws.ws_col; | | 188 | Cols = ws.ws_col; |
189 | } | | 189 | } |
190 | if (Rows == 0) | | 190 | if (Rows == 0) |
191 | Rows = lines; | | 191 | Rows = lines; |
192 | if (Cols == 0) | | 192 | if (Cols == 0) |
193 | Cols = columns; | | 193 | Cols = columns; |
194 | if (Rows < MINROWS || Cols < MINCOLS) { | | 194 | if (Rows < MINROWS || Cols < MINCOLS) { |
195 | (void) fprintf(stderr, | | 195 | (void) fprintf(stderr, |
196 | "the screen is too small: must be at least %dx%d, ", | | 196 | "the screen is too small: must be at least %dx%d, ", |
197 | MINCOLS, MINROWS); | | 197 | MINCOLS, MINROWS); |
198 | stop(""); /* stop() supplies \n */ | | 198 | stop(""); /* stop() supplies \n */ |
199 | } | | 199 | } |
200 | if (tcgetattr(0, &oldtt) < 0) | | 200 | if (tcgetattr(0, &oldtt) < 0) |
201 | stop("tcgetattr() fails"); | | 201 | stop("tcgetattr() fails"); |
202 | newtt = oldtt; | | 202 | newtt = oldtt; |
203 | newtt.c_lflag &= ~(ICANON|ECHO); | | 203 | newtt.c_lflag &= ~(ICANON|ECHO); |
204 | newtt.c_oflag &= ~OXTABS; | | 204 | newtt.c_oflag &= ~OXTABS; |
205 | if (tcsetattr(0, TCSADRAIN, &newtt) < 0) | | 205 | if (tcsetattr(0, TCSADRAIN, &newtt) < 0) |
206 | stop("tcsetattr() fails"); | | 206 | stop("tcsetattr() fails"); |
207 | ospeed = cfgetospeed(&newtt); | | 207 | ospeed = cfgetospeed(&newtt); |
208 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 208 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
209 | | | 209 | |
210 | /* | | 210 | /* |
211 | * We made it. We are now in screen mode, modulo TIstr | | 211 | * We made it. We are now in screen mode, modulo TIstr |
212 | * (which we will fix immediately). | | 212 | * (which we will fix immediately). |
213 | */ | | 213 | */ |
214 | if (enter_ca_mode) | | 214 | if (enter_ca_mode) |
215 | putstr(enter_ca_mode); | | 215 | putstr(enter_ca_mode); |
216 | if (cursor_invisible) | | 216 | if (cursor_invisible) |
217 | putstr(cursor_invisible); | | 217 | putstr(cursor_invisible); |
218 | if (tstp != SIG_IGN) | | 218 | if (tstp != SIG_IGN) |
219 | (void) signal(SIGTSTP, scr_stop); | | 219 | (void) signal(SIGTSTP, scr_stop); |
220 | if (ttou != SIG_IGN) | | 220 | if (ttou != SIG_IGN) |
221 | (void) signal(SIGTTOU, ttou); | | 221 | (void) signal(SIGTTOU, ttou); |
222 | | | 222 | |
223 | isset = 1; | | 223 | isset = 1; |
224 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 224 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
225 | scr_clear(); | | 225 | scr_clear(); |
226 | } | | 226 | } |
227 | | | 227 | |
228 | /* | | 228 | /* |
229 | * End screen mode. | | 229 | * End screen mode. |
230 | */ | | 230 | */ |
231 | void | | 231 | void |
232 | scr_end(void) | | 232 | scr_end(void) |
233 | { | | 233 | { |
234 | sigset_t nsigset, osigset; | | 234 | sigset_t nsigset, osigset; |
235 | | | 235 | |
236 | sigemptyset(&nsigset); | | 236 | sigemptyset(&nsigset); |
237 | sigaddset(&nsigset, SIGTSTP); | | 237 | sigaddset(&nsigset, SIGTSTP); |
238 | sigaddset(&nsigset, SIGTTOU); | | 238 | sigaddset(&nsigset, SIGTTOU); |
239 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 239 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
240 | /* move cursor to last line */ | | 240 | /* move cursor to last line */ |
241 | if (cursor_to_ll) | | 241 | if (cursor_to_ll) |
242 | putstr(cursor_to_ll); | | 242 | putstr(cursor_to_ll); |
243 | else | | 243 | else |
244 | moveto(Rows - 1, 0); | | 244 | moveto(Rows - 1, 0); |
245 | /* exit screen mode */ | | 245 | /* exit screen mode */ |
246 | if (exit_ca_mode) | | 246 | if (exit_ca_mode) |
247 | putstr(exit_ca_mode); | | 247 | putstr(exit_ca_mode); |
248 | if (cursor_normal) | | 248 | if (cursor_normal) |
249 | putstr(cursor_normal); | | 249 | putstr(cursor_normal); |
250 | (void) fflush(stdout); | | 250 | (void) fflush(stdout); |
251 | (void) tcsetattr(0, TCSADRAIN, &oldtt); | | 251 | (void) tcsetattr(0, TCSADRAIN, &oldtt); |
252 | isset = 0; | | 252 | isset = 0; |
253 | /* restore signals */ | | 253 | /* restore signals */ |
254 | (void) signal(SIGTSTP, tstp); | | 254 | (void) signal(SIGTSTP, tstp); |
255 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 255 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
256 | } | | 256 | } |
257 | | | 257 | |
258 | void | | 258 | void |
259 | stop(const char *why) | | 259 | stop(const char *why) |
260 | { | | 260 | { |
261 | | | 261 | |
262 | if (isset) | | 262 | if (isset) |
263 | scr_end(); | | 263 | scr_end(); |
264 | (void) fprintf(stderr, "aborting: %s\n", why); | | 264 | (void) fprintf(stderr, "aborting: %s\n", why); |
265 | exit(1); | | 265 | exit(1); |
266 | } | | 266 | } |
267 | | | 267 | |
268 | /* | | 268 | /* |
269 | * Clear the screen, forgetting the current contents in the process. | | 269 | * Clear the screen, forgetting the current contents in the process. |
270 | */ | | 270 | */ |
271 | void | | 271 | void |
272 | scr_clear(void) | | 272 | scr_clear(void) |
273 | { | | 273 | { |
274 | | | 274 | |
275 | putpad(clear_screen); | | 275 | putpad(clear_screen); |
276 | curscore = -1; | | 276 | curscore = -1; |
277 | memset((char *)curscreen, 0, sizeof(curscreen)); | | 277 | memset((char *)curscreen, 0, sizeof(curscreen)); |
278 | } | | 278 | } |
279 | | | 279 | |
280 | #if vax && !__GNUC__ | | 280 | #if vax && !__GNUC__ |
281 | typedef int regcell; /* pcc is bad at `register char', etc */ | | 281 | typedef int regcell; /* pcc is bad at `register char', etc */ |
282 | #else | | 282 | #else |
283 | typedef cell regcell; | | 283 | typedef cell regcell; |
284 | #endif | | 284 | #endif |
285 | | | 285 | |
286 | /* | | 286 | /* |
287 | * Update the screen. | | 287 | * Update the screen. |
288 | */ | | 288 | */ |
289 | void | | 289 | void |
290 | scr_update(void) | | 290 | scr_update(void) |
291 | { | | 291 | { |
292 | cell *bp, *sp; | | 292 | cell *bp, *sp; |
293 | regcell so, cur_so = 0; | | 293 | regcell so, cur_so = 0; |
294 | int i, ccol, j; | | 294 | int i, ccol, j; |
295 | sigset_t nsigset, osigset; | | 295 | sigset_t nsigset, osigset; |
296 | static const struct shape *lastshape; | | 296 | static const struct shape *lastshape; |
297 | | | 297 | |
298 | sigemptyset(&nsigset); | | 298 | sigemptyset(&nsigset); |
299 | sigaddset(&nsigset, SIGTSTP); | | 299 | sigaddset(&nsigset, SIGTSTP); |
300 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 300 | (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
301 | | | 301 | |
302 | /* always leave cursor after last displayed point */ | | 302 | /* always leave cursor after last displayed point */ |
303 | curscreen[D_LAST * B_COLS - 1] = -1; | | 303 | curscreen[D_LAST * B_COLS - 1] = -1; |
304 | | | 304 | |
305 | if (score != curscore) { | | 305 | if (score != curscore) { |
306 | if (cursor_home) | | 306 | if (cursor_home) |
307 | putpad(cursor_home); | | 307 | putpad(cursor_home); |
308 | else | | 308 | else |
309 | moveto(0, 0); | | 309 | moveto(0, 0); |
310 | setcolor(0); | | 310 | setcolor(0); |
311 | (void) printf("Score: %d", score); | | 311 | (void) printf("Score: %d", score); |
312 | curscore = score; | | 312 | curscore = score; |
313 | } | | 313 | } |
314 | | | 314 | |
315 | /* draw preview of nextpattern */ | | 315 | /* draw preview of nextpattern */ |
316 | if (showpreview && (nextshape != lastshape)) { | | 316 | if (showpreview && (nextshape != lastshape)) { |
317 | static int r=5, c=2; | | 317 | static int r=5, c=2; |
318 | int tr, tc, t; | | 318 | int tr, tc, t; |
319 | | | 319 | |
320 | lastshape = nextshape; | | 320 | lastshape = nextshape; |
321 | | | 321 | |
322 | /* clean */ | | 322 | /* clean */ |
323 | putpad(exit_standout_mode); | | 323 | putpad(exit_standout_mode); |
324 | moveto(r-1, c-1); putstr(" "); | | 324 | moveto(r-1, c-1); putstr(" "); |
325 | moveto(r, c-1); putstr(" "); | | 325 | moveto(r, c-1); putstr(" "); |
326 | moveto(r+1, c-1); putstr(" "); | | 326 | moveto(r+1, c-1); putstr(" "); |
327 | moveto(r+2, c-1); putstr(" "); | | 327 | moveto(r+2, c-1); putstr(" "); |
328 | | | 328 | |
329 | moveto(r-3, c-2); | | 329 | moveto(r-3, c-2); |
330 | putstr("Next shape:"); | | 330 | putstr("Next shape:"); |
331 | | | 331 | |
332 | /* draw */ | | 332 | /* draw */ |
333 | putpad(enter_standout_mode); | | | |
334 | setcolor(nextshape->color); | | 333 | setcolor(nextshape->color); |
| | | 334 | putpad(enter_standout_mode); |
335 | moveto(r, 2*c); | | 335 | moveto(r, 2*c); |
336 | putstr(" "); | | 336 | putstr(" "); |
337 | for(i=0; i<3; i++) { | | 337 | for(i=0; i<3; i++) { |
338 | t = c + r*B_COLS; | | 338 | t = c + r*B_COLS; |
339 | t += nextshape->off[i]; | | 339 | t += nextshape->off[i]; |
340 | | | 340 | |
341 | tr = t / B_COLS; | | 341 | tr = t / B_COLS; |
342 | tc = t % B_COLS; | | 342 | tc = t % B_COLS; |
343 | | | 343 | |
344 | moveto(tr, 2*tc); | | 344 | moveto(tr, 2*tc); |
345 | putstr(" "); | | 345 | putstr(" "); |
346 | } | | 346 | } |
347 | putpad(exit_standout_mode); | | 347 | putpad(exit_standout_mode); |
348 | } | | 348 | } |
349 | | | 349 | |
350 | bp = &board[D_FIRST * B_COLS]; | | 350 | bp = &board[D_FIRST * B_COLS]; |
351 | sp = &curscreen[D_FIRST * B_COLS]; | | 351 | sp = &curscreen[D_FIRST * B_COLS]; |
352 | for (j = D_FIRST; j < D_LAST; j++) { | | 352 | for (j = D_FIRST; j < D_LAST; j++) { |
353 | ccol = -1; | | 353 | ccol = -1; |
354 | for (i = 0; i < B_COLS; bp++, sp++, i++) { | | 354 | for (i = 0; i < B_COLS; bp++, sp++, i++) { |
355 | if (*sp == (so = *bp)) | | 355 | if (*sp == (so = *bp)) |
356 | continue; | | 356 | continue; |
357 | *sp = so; | | 357 | *sp = so; |
358 | if (i != ccol) { | | 358 | if (i != ccol) { |
359 | if (cur_so && move_standout_mode) { | | 359 | if (cur_so && move_standout_mode) { |
360 | putpad(exit_standout_mode); | | 360 | putpad(exit_standout_mode); |
361 | cur_so = 0; | | 361 | cur_so = 0; |
362 | } | | 362 | } |
363 | moveto(RTOD(j), CTOD(i)); | | 363 | moveto(RTOD(j), CTOD(i)); |
364 | } | | 364 | } |
365 | if (enter_standout_mode) { | | 365 | if (enter_standout_mode) { |
366 | if (so != cur_so) { | | 366 | if (so != cur_so) { |
367 | setcolor(so); | | 367 | setcolor(so); |
368 | putpad(so ? | | 368 | putpad(so ? |
369 | enter_standout_mode : | | 369 | enter_standout_mode : |
370 | exit_standout_mode); | | 370 | exit_standout_mode); |
371 | cur_so = so; | | 371 | cur_so = so; |
372 | } | | 372 | } |
373 | #ifdef DEBUG | | 373 | #ifdef DEBUG |
374 | char buf[3]; | | 374 | char buf[3]; |
375 | snprintf(buf, sizeof(buf), "%d%d", so, so); | | 375 | snprintf(buf, sizeof(buf), "%d%d", so, so); |
376 | putstr(buf); | | 376 | putstr(buf); |
377 | #else | | 377 | #else |
378 | putstr(" "); | | 378 | putstr(" "); |
379 | #endif | | 379 | #endif |
380 | } else | | 380 | } else |
381 | putstr(so ? "XX" : " "); | | 381 | putstr(so ? "XX" : " "); |
382 | ccol = i + 1; | | 382 | ccol = i + 1; |
383 | /* | | 383 | /* |
384 | * Look ahead a bit, to avoid extra motion if | | 384 | * Look ahead a bit, to avoid extra motion if |
385 | * we will be redrawing the cell after the next. | | 385 | * we will be redrawing the cell after the next. |
386 | * Motion probably takes four or more characters, | | 386 | * Motion probably takes four or more characters, |
387 | * so we save even if we rewrite two cells | | 387 | * so we save even if we rewrite two cells |
388 | * `unnecessarily'. Skip it all, though, if | | 388 | * `unnecessarily'. Skip it all, though, if |
389 | * the next cell is a different color. | | 389 | * the next cell is a different color. |
390 | */ | | 390 | */ |
391 | #define STOP (B_COLS - 3) | | 391 | #define STOP (B_COLS - 3) |
392 | if (i > STOP || sp[1] != bp[1] || so != bp[1]) | | 392 | if (i > STOP || sp[1] != bp[1] || so != bp[1]) |
393 | continue; | | 393 | continue; |
394 | if (sp[2] != bp[2]) | | 394 | if (sp[2] != bp[2]) |
395 | sp[1] = -1; | | 395 | sp[1] = -1; |
396 | else if (i < STOP && so == bp[2] && sp[3] != bp[3]) { | | 396 | else if (i < STOP && so == bp[2] && sp[3] != bp[3]) { |
397 | sp[2] = -1; | | 397 | sp[2] = -1; |
398 | sp[1] = -1; | | 398 | sp[1] = -1; |
399 | } | | 399 | } |
400 | } | | 400 | } |
401 | } | | 401 | } |
402 | if (cur_so) | | 402 | if (cur_so) |
403 | putpad(exit_standout_mode); | | 403 | putpad(exit_standout_mode); |
404 | (void) fflush(stdout); | | 404 | (void) fflush(stdout); |
405 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 405 | (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
406 | } | | 406 | } |
407 | | | 407 | |
408 | /* | | 408 | /* |
409 | * Write a message (set!=0), or clear the same message (set==0). | | 409 | * Write a message (set!=0), or clear the same message (set==0). |
410 | * (We need its length in case we have to overwrite with blanks.) | | 410 | * (We need its length in case we have to overwrite with blanks.) |
411 | */ | | 411 | */ |
412 | void | | 412 | void |
413 | scr_msg(char *s, int set) | | 413 | scr_msg(char *s, int set) |
414 | { | | 414 | { |
415 | | | 415 | |
416 | if (set || clr_eol == NULL) { | | 416 | if (set || clr_eol == NULL) { |
417 | int l = strlen(s); | | 417 | int l = strlen(s); |
418 | | | 418 | |
419 | moveto(Rows - 2, ((Cols - l) >> 1) - 1); | | 419 | moveto(Rows - 2, ((Cols - l) >> 1) - 1); |
420 | if (set) | | 420 | if (set) |
421 | putstr(s); | | 421 | putstr(s); |
422 | else | | 422 | else |
423 | while (--l >= 0) | | 423 | while (--l >= 0) |
424 | (void) putchar(' '); | | 424 | (void) putchar(' '); |
425 | } else { | | 425 | } else { |
426 | moveto(Rows - 2, 0); | | 426 | moveto(Rows - 2, 0); |
427 | putpad(clr_eol); | | 427 | putpad(clr_eol); |
428 | } | | 428 | } |
429 | } | | 429 | } |