screen.c

Go to the documentation of this file.
00001 /*      $OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray Exp $ */
00002 /*      $NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft Exp $       */
00003 
00004 /*-
00005  * Copyright (c) 1992, 1993
00006  *      The Regents of the University of California.  All rights reserved.
00007  *
00008  * This code is derived from software contributed to Berkeley by
00009  * Chris Torek and Darren F. Provine.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright
00017  *    notice, this list of conditions and the following disclaimer in the
00018  *    documentation and/or other materials provided with the distribution.
00019  * 3. Neither the name of the University nor the names of its contributors
00020  *    may be used to endorse or promote products derived from this software
00021  *    without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00033  * SUCH DAMAGE.
00034  *
00035  *      @(#)screen.c    8.1 (Berkeley) 5/31/93
00036  */
00037 
00044 /*
00045  * Tetris screen control.
00046  */
00047 
00048 #include <err.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <str.h>
00052 #include <unistd.h>
00053 #include <vfs/vfs.h>
00054 #include <async.h>
00055 #include <bool.h>
00056 #include <io/console.h>
00057 #include <io/style.h>
00058 #include "screen.h"
00059 #include "tetris.h"
00060 
00061 #define STOP  (B_COLS - 3)
00062 
00063 static cell curscreen[B_SIZE];  /* non-zero => standout (or otherwise marked) */
00064 static int curscore;
00065 static int isset;               /* true => terminal is in game mode */
00066 
00067 static bool use_color;          /* true => use colors */
00068 
00069 static const struct shape *lastshape;
00070 
00071 
00072 /*
00073  * putstr() is for unpadded strings (either as in termcap(5) or
00074  * simply literal strings);
00075  */
00076 static inline void putstr(const char *s)
00077 {
00078         while (*s)
00079                 putchar(*(s++));
00080 }
00081 
00082 static void start_standout(uint32_t color)
00083 {
00084         fflush(stdout);
00085         console_set_rgb_color(fphone(stdout), 0xffffff,
00086             use_color ? color : 0x000000);
00087 }
00088 
00089 static void resume_normal(void)
00090 {
00091         fflush(stdout);
00092         console_set_style(fphone(stdout), STYLE_NORMAL);
00093 }
00094 
00095 void clear_screen(void)
00096 {
00097         console_clear(fphone(stdout));
00098         moveto(0, 0);
00099 }
00100 
00101 /*
00102  * Clear the screen, forgetting the current contents in the process.
00103  */
00104 void scr_clear(void)
00105 {
00106         resume_normal();
00107         console_clear(fphone(stdout));
00108         curscore = -1;
00109         memset(curscreen, 0, sizeof(curscreen));
00110 }
00111 
00112 /*
00113  * Set up screen
00114  */
00115 void scr_init(void)
00116 {
00117         console_cursor_visibility(fphone(stdout), 0);
00118         resume_normal();
00119         scr_clear();
00120 }
00121 
00122 void moveto(sysarg_t r, sysarg_t c)
00123 {
00124         fflush(stdout);
00125         console_set_pos(fphone(stdout), c, r);
00126 }
00127 
00128 winsize_t winsize;
00129 
00130 static int get_display_size(winsize_t *ws)
00131 {
00132         return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row);
00133 }
00134 
00135 static bool get_display_color_sup(void)
00136 {
00137         sysarg_t ccap;
00138         int rc = console_get_color_cap(fphone(stdout), &ccap);
00139         
00140         if (rc != 0)
00141                 return false;
00142         
00143         return (ccap >= CONSOLE_CCAP_RGB);
00144 }
00145 
00146 /*
00147  * Set up screen mode.
00148  */
00149 void scr_set(void)
00150 {
00151         winsize_t ws;
00152         
00153         Rows = 0;
00154         Cols = 0;
00155         
00156         if (get_display_size(&ws) == 0) {
00157                 Rows = ws.ws_row;
00158                 Cols = ws.ws_col;
00159         }
00160 
00161         use_color = get_display_color_sup();
00162         
00163         if ((Rows < MINROWS) || (Cols < MINCOLS)) {
00164                 char smallscr[55];
00165                 
00166                 snprintf(smallscr, sizeof(smallscr),
00167                     "the screen is too small (must be at least %dx%d)",
00168                     MINROWS, MINCOLS);
00169                 stop(smallscr);
00170         }
00171         isset = 1;
00172         
00173         scr_clear();
00174 }
00175 
00176 /*
00177  * End screen mode.
00178  */
00179 void scr_end(void)
00180 {
00181         console_cursor_visibility(fphone(stdout), 1);
00182 }
00183 
00184 void stop(const char *why)
00185 {
00186         if (isset)
00187                 scr_end();
00188         
00189         errx(1, "aborting: %s", why);
00190 }
00191 
00192 /*
00193  * Update the screen.
00194  */
00195 void scr_update(void)
00196 {
00197         cell *bp;
00198         cell *sp;
00199         cell so;
00200         cell cur_so = 0;
00201         int i;
00202         int j;
00203         int ccol;
00204         
00205         /* Always leave cursor after last displayed point */
00206         curscreen[D_LAST * B_COLS - 1] = -1;
00207         
00208         if (score != curscore) {
00209                 moveto(0, 0);
00210                 printf("Score: %d", score);
00211                 curscore = score;
00212         }
00213         
00214         /* Draw preview of next pattern */
00215         if ((showpreview) && (nextshape != lastshape)) {
00216                 int i;
00217                 static int r = 5, c = 2;
00218                 int tr, tc, t;
00219                 
00220                 lastshape = nextshape;
00221                 
00222                 /* Clean */
00223                 resume_normal();
00224                 moveto(r - 1, c - 1);
00225                 putstr("          ");
00226                 moveto(r, c - 1);
00227                 putstr("          ");
00228                 moveto(r + 1, c - 1);
00229                 putstr("          ");
00230                 moveto(r + 2, c - 1);
00231                 putstr("          ");
00232                 
00233                 moveto(r - 3, c - 2);
00234                 putstr("Next shape:");
00235                 
00236                 /* Draw */
00237                 start_standout(nextshape->color);
00238                 moveto(r, 2 * c);
00239                 putstr("  ");
00240                 for (i = 0; i < 3; i++) {
00241                         t = c + r * B_COLS;
00242                         t += nextshape->off[i];
00243                         
00244                         tr = t / B_COLS;
00245                         tc = t % B_COLS;
00246                         
00247                         moveto(tr, 2*tc);
00248                         putstr("  ");
00249                 }
00250                 resume_normal();
00251         }
00252         
00253         bp = &board[D_FIRST * B_COLS];
00254         sp = &curscreen[D_FIRST * B_COLS];
00255         for (j = D_FIRST; j < D_LAST; j++) {
00256                 ccol = -1;
00257                 for (i = 0; i < B_COLS; bp++, sp++, i++) {
00258                         if (*sp == (so = *bp))
00259                                 continue;
00260                         
00261                         *sp = so;
00262                         if (i != ccol) {
00263                                 if (cur_so) {
00264                                         resume_normal();
00265                                         cur_so = 0;
00266                                 }
00267                                 moveto(RTOD(j), CTOD(i));
00268                         }
00269                         
00270                         if (so != cur_so) {
00271                                 if (so)
00272                                         start_standout(so);
00273                                 else
00274                                         resume_normal();
00275                                 cur_so = so;
00276                         }
00277                         putstr("  ");
00278                         
00279                         ccol = i + 1;
00280                         /*
00281                          * Look ahead a bit, to avoid extra motion if
00282                          * we will be redrawing the cell after the next.
00283                          * Motion probably takes four or more characters,
00284                          * so we save even if we rewrite two cells
00285                          * `unnecessarily'.  Skip it all, though, if
00286                          * the next cell is a different color.
00287                          */
00288                         
00289                         if ((i > STOP) || (sp[1] != bp[1]) || (so != bp[1]))
00290                                 continue;
00291                         
00292                         if (sp[2] != bp[2])
00293                                 sp[1] = -1;
00294                         else if ((i < STOP) && (so == bp[2]) && (sp[3] != bp[3])) {
00295                                 sp[2] = -1;
00296                                 sp[1] = -1;
00297                         }
00298                 }
00299         }
00300         
00301         if (cur_so)
00302                 resume_normal();
00303         
00304         fflush(stdout);
00305 }
00306 
00307 /*
00308  * Write a message (set != 0), or clear the same message (set == 0).
00309  * (We need its length in case we have to overwrite with blanks.)
00310  */
00311 void scr_msg(char *s, bool set)
00312 {
00313         int l = str_size(s);
00314         
00315         moveto(Rows - 2, ((Cols - l) >> 1) - 1);
00316         
00317         if (set)
00318                 putstr(s);
00319         else
00320                 while (--l >= 0)
00321                         (void) putchar(' ');
00322 }
00323 

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7