source: mainline/uspace/app/tetris/screen.c@ 5ef16903

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5ef16903 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[79ae36dd]1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
[e9a3c52]4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
[79ae36dd]9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** Attributations
30 *
31 * screen.c 8.1 (Berkeley) 5/31/93
32 * NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft
33 * OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray
34 *
35 * Based upon BSD Tetris
36 *
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California.
39 * Distributed under BSD license.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * Chris Torek and Darren F. Provine.
[e9a3c52]43 *
44 */
45
[b2951e2]46/** @addtogroup tetris
[ebe70f1]47 * @{
[b2951e2]48 */
49/** @file
50 */
51
[e9a3c52]52/*
53 * Tetris screen control.
54 */
55
56#include <stdio.h>
57#include <stdlib.h>
[19f857a]58#include <str.h>
[0c25c10]59#include <vfs/vfs.h>
[f1b4e74]60#include <async.h>
[3e6a98c5]61#include <stdbool.h>
[9f1362d4]62#include <io/console.h>
63#include <io/style.h>
[e9a3c52]64#include "screen.h"
65#include "tetris.h"
66
[ebe70f1]67#define STOP (B_COLS - 3)
68
69static cell curscreen[B_SIZE]; /* non-zero => standout (or otherwise marked) */
[e9a3c52]70static int curscore;
[ebe70f1]71static int isset; /* true => terminal is in game mode */
72
[9f1362d4]73static bool use_color; /* true => use colors */
[50cfa6c]74
[ebe70f1]75static const struct shape *lastshape;
[f1b4e74]76
[79ae36dd]77static suseconds_t timeleft = 0;
78
79console_ctrl_t *console;
80
[f1b4e74]81
[e9a3c52]82/*
[f1b4e74]83 * putstr() is for unpadded strings (either as in termcap(5) or
[0c25c10]84 * simply literal strings);
[e9a3c52]85 */
[a000878c]86static inline void putstr(const char *s)
[59ed572]87{
88 while (*s)
89 putchar(*(s++));
90}
[e9a3c52]91
[ebe70f1]92static void start_standout(uint32_t color)
[e9a3c52]93{
[79ae36dd]94 console_flush(console);
[7c014d1]95 console_set_rgb_color(console, use_color ? color : 0x000000,
96 0xffffff);
[f1b4e74]97}
[e9a3c52]98
[f1b4e74]99static void resume_normal(void)
100{
[79ae36dd]101 console_flush(console);
102 console_set_style(console, STYLE_NORMAL);
[e9a3c52]103}
104
[9996ed5]105void clear_screen(void)
106{
[79ae36dd]107 console_clear(console);
[0cc4313]108 moveto(0, 0);
[9996ed5]109}
110
[e9a3c52]111/*
[f1b4e74]112 * Clear the screen, forgetting the current contents in the process.
[e9a3c52]113 */
[ebe70f1]114void scr_clear(void)
[f1b4e74]115{
[d6cc453]116 resume_normal();
[79ae36dd]117 console_clear(console);
[f1b4e74]118 curscore = -1;
[ebe70f1]119 memset(curscreen, 0, sizeof(curscreen));
[f1b4e74]120}
[b917098]121
[e9a3c52]122/*
[f1b4e74]123 * Set up screen
[e9a3c52]124 */
[ebe70f1]125void scr_init(void)
[e9a3c52]126{
[79ae36dd]127 console_cursor_visibility(console, 0);
[f1b4e74]128 resume_normal();
129 scr_clear();
[e9a3c52]130}
131
[96b02eb9]132void moveto(sysarg_t r, sysarg_t c)
[f1b4e74]133{
[79ae36dd]134 console_flush(console);
135 console_set_pos(console, c, r);
[f1b4e74]136}
137
[9996ed5]138winsize_t winsize;
[f1b4e74]139
[b7fd2a0]140static errno_t get_display_size(winsize_t *ws)
[f1b4e74]141{
[79ae36dd]142 return console_get_size(console, &ws->ws_col, &ws->ws_row);
[f1b4e74]143}
[e9a3c52]144
[9f1362d4]145static bool get_display_color_sup(void)
[50cfa6c]146{
[96b02eb9]147 sysarg_t ccap;
[b7fd2a0]148 errno_t rc = console_get_color_cap(console, &ccap);
[a35b458]149
[a53ed3a]150 if (rc != EOK)
[9f1362d4]151 return false;
[a35b458]152
[7c014d1]153 return ((ccap & CONSOLE_CAP_RGB) == CONSOLE_CAP_RGB);
[50cfa6c]154}
155
[e9a3c52]156/*
157 * Set up screen mode.
158 */
[ebe70f1]159void scr_set(void)
[e9a3c52]160{
[9996ed5]161 winsize_t ws;
[a35b458]162
[ebe70f1]163 Rows = 0;
164 Cols = 0;
[a35b458]165
[f1b4e74]166 if (get_display_size(&ws) == 0) {
[e9a3c52]167 Rows = ws.ws_row;
168 Cols = ws.ws_col;
169 }
[50cfa6c]170
171 use_color = get_display_color_sup();
[a35b458]172
[ebe70f1]173 if ((Rows < MINROWS) || (Cols < MINCOLS)) {
[e9a3c52]174 char smallscr[55];
[a35b458]175
[86029498]176 snprintf(smallscr, sizeof(smallscr),
[e9a3c52]177 "the screen is too small (must be at least %dx%d)",
178 MINROWS, MINCOLS);
179 stop(smallscr);
180 }
181 isset = 1;
[a35b458]182
[e9a3c52]183 scr_clear();
184}
185
186/*
187 * End screen mode.
188 */
[ebe70f1]189void scr_end(void)
[e9a3c52]190{
[79ae36dd]191 console_cursor_visibility(console, 1);
[e9a3c52]192}
193
[a000878c]194void stop(const char *why)
[e9a3c52]195{
196 if (isset)
197 scr_end();
[a35b458]198
[f538ef3]199 fprintf(stderr, "aborting: %s", why);
200 abort();
[e9a3c52]201}
202
203/*
204 * Update the screen.
205 */
[ebe70f1]206void scr_update(void)
[e9a3c52]207{
[ebe70f1]208 cell *bp;
209 cell *sp;
210 cell so;
211 cell cur_so = 0;
212 int i;
213 int j;
214 int ccol;
[a35b458]215
[ebe70f1]216 /* Always leave cursor after last displayed point */
[e9a3c52]217 curscreen[D_LAST * B_COLS - 1] = -1;
[a35b458]218
[e9a3c52]219 if (score != curscore) {
[f1b4e74]220 moveto(0, 0);
[86029498]221 printf("Score: %d", score);
[e9a3c52]222 curscore = score;
223 }
[a35b458]224
[ebe70f1]225 /* Draw preview of next pattern */
226 if ((showpreview) && (nextshape != lastshape)) {
[e9a3c52]227 int i;
[ebe70f1]228 static int r = 5, c = 2;
[e9a3c52]229 int tr, tc, t;
[a35b458]230
[e9a3c52]231 lastshape = nextshape;
[a35b458]232
[ebe70f1]233 /* Clean */
[f1b4e74]234 resume_normal();
[ebe70f1]235 moveto(r - 1, c - 1);
236 putstr(" ");
237 moveto(r, c - 1);
238 putstr(" ");
239 moveto(r + 1, c - 1);
240 putstr(" ");
241 moveto(r + 2, c - 1);
242 putstr(" ");
[a35b458]243
[ebe70f1]244 moveto(r - 3, c - 2);
[e9a3c52]245 putstr("Next shape:");
[a35b458]246
[ebe70f1]247 /* Draw */
248 start_standout(nextshape->color);
[e9a3c52]249 moveto(r, 2 * c);
[f1b4e74]250 putstr(" ");
[e9a3c52]251 for (i = 0; i < 3; i++) {
252 t = c + r * B_COLS;
253 t += nextshape->off[i];
[a35b458]254
[e9a3c52]255 tr = t / B_COLS;
256 tc = t % B_COLS;
[a35b458]257
[e9a3c52]258 moveto(tr, 2*tc);
[f1b4e74]259 putstr(" ");
[e9a3c52]260 }
[f1b4e74]261 resume_normal();
[e9a3c52]262 }
[a35b458]263
[e9a3c52]264 bp = &board[D_FIRST * B_COLS];
265 sp = &curscreen[D_FIRST * B_COLS];
266 for (j = D_FIRST; j < D_LAST; j++) {
267 ccol = -1;
268 for (i = 0; i < B_COLS; bp++, sp++, i++) {
269 if (*sp == (so = *bp))
270 continue;
[a35b458]271
[e9a3c52]272 *sp = so;
273 if (i != ccol) {
[86029498]274 if (cur_so) {
275 resume_normal();
276 cur_so = 0;
277 }
[e9a3c52]278 moveto(RTOD(j), CTOD(i));
279 }
[a35b458]280
[f1b4e74]281 if (so != cur_so) {
282 if (so)
[ebe70f1]283 start_standout(so);
[f1b4e74]284 else
285 resume_normal();
286 cur_so = so;
287 }
288 putstr(" ");
[a35b458]289
[e9a3c52]290 ccol = i + 1;
291 /*
292 * Look ahead a bit, to avoid extra motion if
293 * we will be redrawing the cell after the next.
294 * Motion probably takes four or more characters,
295 * so we save even if we rewrite two cells
296 * `unnecessarily'. Skip it all, though, if
297 * the next cell is a different color.
298 */
[a35b458]299
[ebe70f1]300 if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
[e9a3c52]301 continue;
[a35b458]302
[e9a3c52]303 if (sp[2] != bp[2])
304 sp[1] = -1;
[ebe70f1]305 else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
[e9a3c52]306 sp[2] = -1;
307 sp[1] = -1;
308 }
309 }
310 }
[a35b458]311
[86029498]312 if (cur_so)
313 resume_normal();
[a35b458]314
[79ae36dd]315 console_flush(console);
[e9a3c52]316}
317
318/*
[ebe70f1]319 * Write a message (set != 0), or clear the same message (set == 0).
[e9a3c52]320 * (We need its length in case we have to overwrite with blanks.)
321 */
[9f1362d4]322void scr_msg(char *s, bool set)
[e9a3c52]323{
[92fd52d7]324 int l = str_size(s);
[a35b458]325
[d6cc453]326 moveto(Rows - 2, ((Cols - l) >> 1) - 1);
[a35b458]327
[d6cc453]328 if (set)
329 putstr(s);
330 else
331 while (--l >= 0)
332 (void) putchar(' ');
[e9a3c52]333}
[b2951e2]334
[79ae36dd]335/** Sleep for the current turn time
336 *
337 * Eat any input that might be available.
338 *
339 */
340void tsleep(void)
341{
342 suseconds_t timeout = fallrate;
[a35b458]343
[79ae36dd]344 while (timeout > 0) {
[07b7c48]345 cons_event_t event;
[a35b458]346
[07b7c48]347 if (!console_get_event_timeout(console, &event, &timeout))
[79ae36dd]348 break;
349 }
350}
351
352/** Get char with timeout
353 *
354 */
355int tgetchar(void)
356{
357 /*
358 * Reset timeleft to fallrate whenever it is not positive
359 * and increase speed.
360 */
[a35b458]361
[79ae36dd]362 if (timeleft <= 0) {
363 faster();
364 timeleft = fallrate;
365 }
[a35b458]366
[79ae36dd]367 /*
368 * Wait to see if there is any input. If so, take it and
369 * update timeleft so that the next call to tgetchar()
370 * will not wait as long. If there is no input,
371 * make timeleft zero and return -1.
372 */
[a35b458]373
[79ae36dd]374 wchar_t c = 0;
[a35b458]375
[79ae36dd]376 while (c == 0) {
[07b7c48]377 cons_event_t event;
[a35b458]378
[07b7c48]379 if (!console_get_event_timeout(console, &event, &timeleft)) {
[79ae36dd]380 timeleft = 0;
381 return -1;
382 }
[a35b458]383
[07b7c48]384 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
385 c = event.ev.key.c;
[79ae36dd]386 }
[a35b458]387
[79ae36dd]388 return (int) c;
389}
390
391/** Get char without timeout
392 *
393 */
394int twait(void)
395{
396 wchar_t c = 0;
[a35b458]397
[79ae36dd]398 while (c == 0) {
[07b7c48]399 cons_event_t event;
[a35b458]400
[07b7c48]401 if (!console_get_event(console, &event))
[79ae36dd]402 return -1;
[a35b458]403
[07b7c48]404 if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS)
405 c = event.ev.key.c;
[79ae36dd]406 }
[a35b458]407
[79ae36dd]408 return (int) c;
409}
410
[b2951e2]411/** @}
412 */
Note: See TracBrowser for help on using the repository browser.