Subversion Repositories HelenOS

Rev

Rev 1472 | Rev 1524 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1419 jermar 1
/*  $OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray Exp $ */
2
/*  $NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft Exp $   */
3
 
4
/*-
5
 * Copyright (c) 1992, 1993
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Chris Torek and Darren F. Provine.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 *
35
 *  @(#)screen.c    8.1 (Berkeley) 5/31/93
36
 */
37
 
38
/*
39
 * Tetris screen control.
40
 */
41
 
42
#include <err.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
1519 palkovsky 47
#include <io/stream.h>
1419 jermar 48
 
49
#include "screen.h"
50
#include "tetris.h"
51
 
52
static cell curscreen[B_SIZE];  /* 1 => standout (or otherwise marked) */
53
static int curscore;
54
static int isset;       /* true => terminal is in game mode */
55
static struct termios oldtt;
56
static void (*tstp)(int);
57
 
58
static void scr_stop(int);
59
static void stopset(int);
60
 
61
/*
62
 * Capabilities from TERMCAP.
63
 */
64
char    PC, *BC, *UP;       /* tgoto requires globals: ugh! */
65
 
66
static char
67
    *bcstr,         /* backspace char */
68
    *CEstr,         /* clear to end of line */
69
    *CLstr,         /* clear screen */
70
    *CMstr,         /* cursor motion string */
71
#ifdef unneeded
72
    *CRstr,         /* "\r" equivalent */
73
#endif
74
    *HOstr,         /* cursor home */
75
    *LLstr,         /* last line, first column */
76
    *pcstr,         /* pad character */
77
    *TEstr,         /* end cursor motion mode */
78
    *TIstr;         /* begin cursor motion mode */
79
char
80
    *SEstr,         /* end standout mode */
81
    *SOstr;         /* begin standout mode */
82
static int
83
    COnum,          /* co# value */
84
    LInum,          /* li# value */
85
    MSflag;         /* can move in standout mode */
86
 
87
 
88
struct tcsinfo {        /* termcap string info; some abbrevs above */
89
    char tcname[3];
90
    char **tcaddr;
91
} tcstrings[] = {
92
    {"bc", &bcstr},
93
    {"ce", &CEstr},
94
    {"cl", &CLstr},
95
    {"cm", &CMstr},
96
#ifdef unneeded
97
    {"cr", &CRstr},
98
#endif
99
    {"le", &BC},        /* move cursor left one space */
100
    {"pc", &pcstr},
101
    {"se", &SEstr},
102
    {"so", &SOstr},
103
    {"te", &TEstr},
104
    {"ti", &TIstr},
105
    {"up", &UP},        /* cursor up */
106
    { {0}, NULL}
107
};
108
 
109
/* This is where we will actually stuff the information */
110
 
111
static char combuf[1024], tbuf[1024];
112
 
113
 
114
/*
115
 * Routine used by tputs().
116
 */
117
int
118
put(int c)
119
{
120
 
121
    return (putchar(c));
122
}
123
 
124
/*
125
 * putstr() is for unpadded strings (either as in termcap(5) or
126
 * simply literal strings); putpad() is for padded strings with
127
 * count=1.  (See screen.h for putpad().)
128
 */
129
#define putstr(s)   (void)fputs(s, stdout)
130
#define moveto(r, c)    putpad(tgoto(CMstr, c, r))
131
 
1519 palkovsky 132
static int con_phone;
133
 
1419 jermar 134
/*
135
 * Set up from termcap.
136
 */
137
void
138
scr_init(void)
139
{
1519 palkovsky 140
    con_phone = get_fd_phone(1);
1419 jermar 141
}
142
 
143
 
144
static void
145
scr_stop(int sig)
146
{
147
 
148
    scr_end();
149
    scr_set();
150
    scr_msg(key_msg, 1);
151
}
152
 
153
/*
154
 * Set up screen mode.
155
 */
156
void
157
scr_set(void)
158
{
159
    struct winsize ws;
160
    struct termios newtt;
161
    void (*ttou)(int);
162
 
163
    Rows = 0, Cols = 0;
164
    if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
165
        Rows = ws.ws_row;
166
        Cols = ws.ws_col;
167
    }
168
    if (Rows == 0)
169
        Rows = LInum;
170
    if (Cols == 0)
171
    Cols = COnum;
172
    if (Rows < MINROWS || Cols < MINCOLS) {
173
        char smallscr[55];
174
 
175
        (void)snprintf(smallscr, sizeof(smallscr),
176
            "the screen is too small (must be at least %dx%d)",
177
            MINROWS, MINCOLS);
178
        stop(smallscr);
179
    }
180
    if (tcgetattr(0, &oldtt) < 0)
181
        stop("tcgetattr() fails");
182
    newtt = oldtt;
183
    newtt.c_lflag &= ~(ICANON|ECHO);
184
    newtt.c_oflag &= ~OXTABS;
185
    if (tcsetattr(0, TCSADRAIN, &newtt) < 0)
186
        stop("tcsetattr() fails");
187
 
188
    /*
189
     * We made it.  We are now in screen mode, modulo TIstr
190
     * (which we will fix immediately).
191
     */
192
    if (TIstr)
193
        putstr(TIstr);  /* termcap(5) says this is not padded */
194
 
195
    isset = 1;
1519 palkovsky 196
 
1419 jermar 197
    scr_clear();
198
}
199
 
200
/*
201
 * End screen mode.
202
 */
203
void
204
scr_end(void)
205
{
206
}
207
 
208
void
209
stop(char *why)
210
{
211
 
212
    if (isset)
213
        scr_end();
214
    errx(1, "aborting: %s", why);
215
}
216
 
217
/*
218
 * Clear the screen, forgetting the current contents in the process.
219
 */
220
void
221
scr_clear(void)
222
{
223
 
224
    putpad(CLstr);
225
    curscore = -1;
226
    memset((char *)curscreen, 0, sizeof(curscreen));
227
}
228
 
229
#if vax && !__GNUC__
230
typedef int regcell;    /* pcc is bad at `register char', etc */
231
#else
232
typedef cell regcell;
233
#endif
234
 
235
/*
236
 * Update the screen.
237
 */
238
void
239
scr_update(void)
240
{
241
    cell *bp, *sp;
242
    regcell so, cur_so = 0;
243
    int i, ccol, j;
244
    static const struct shape *lastshape;
245
 
246
    /* always leave cursor after last displayed point */
247
    curscreen[D_LAST * B_COLS - 1] = -1;
248
 
249
    if (score != curscore) {
250
        if (HOstr)
251
            putpad(HOstr);
252
        else
253
            moveto(0, 0);
254
        (void) printf("Score: %d", score);
255
        curscore = score;
256
    }
257
 
258
    /* draw preview of next pattern */
259
    if (showpreview && (nextshape != lastshape)) {
260
        int i;
261
        static int r=5, c=2;
262
        int tr, tc, t;
263
 
264
        lastshape = nextshape;
265
 
266
        /* clean */
267
        putpad(SEstr);
268
        moveto(r-1, c-1); putstr("          ");
269
        moveto(r,   c-1); putstr("          ");
270
        moveto(r+1, c-1); putstr("          ");
271
        moveto(r+2, c-1); putstr("          ");
272
 
273
        moveto(r-3, c-2);
274
        putstr("Next shape:");
275
 
276
        /* draw */
277
        if (SOstr)
278
            putpad(SOstr);
279
        moveto(r, 2 * c);
280
        putstr(SOstr ? "  " : "[]");
281
        for (i = 0; i < 3; i++) {
282
            t = c + r * B_COLS;
283
            t += nextshape->off[i];
284
 
285
            tr = t / B_COLS;
286
            tc = t % B_COLS;
287
 
288
            moveto(tr, 2*tc);
289
            putstr(SOstr ? "  " : "[]");
290
        }
291
        putpad(SEstr);
292
    }
293
 
294
    bp = &board[D_FIRST * B_COLS];
295
    sp = &curscreen[D_FIRST * B_COLS];
296
    for (j = D_FIRST; j < D_LAST; j++) {
297
        ccol = -1;
298
        for (i = 0; i < B_COLS; bp++, sp++, i++) {
299
            if (*sp == (so = *bp))
300
                continue;
301
            *sp = so;
302
            if (i != ccol) {
303
                if (cur_so && MSflag) {
304
                    putpad(SEstr);
305
                    cur_so = 0;
306
                }
307
                moveto(RTOD(j), CTOD(i));
308
            }
309
            if (SOstr) {
310
                if (so != cur_so) {
311
                    putpad(so ? SOstr : SEstr);
312
                    cur_so = so;
313
                }
314
                putstr("  ");
315
            } else
316
                putstr(so ? "[]" : "  ");
317
            ccol = i + 1;
318
            /*
319
             * Look ahead a bit, to avoid extra motion if
320
             * we will be redrawing the cell after the next.
321
             * Motion probably takes four or more characters,
322
             * so we save even if we rewrite two cells
323
             * `unnecessarily'.  Skip it all, though, if
324
             * the next cell is a different color.
325
             */
326
#define STOP (B_COLS - 3)
327
            if (i > STOP || sp[1] != bp[1] || so != bp[1])
328
                continue;
329
            if (sp[2] != bp[2])
330
                sp[1] = -1;
331
            else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
332
                sp[2] = -1;
333
                sp[1] = -1;
334
            }
335
        }
336
    }
337
    if (cur_so)
338
        putpad(SEstr);
1472 palkovsky 339
/*  (void) fflush(stdout); */
340
/*  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); */
1419 jermar 341
}
342
 
343
/*
344
 * Write a message (set!=0), or clear the same message (set==0).
345
 * (We need its length in case we have to overwrite with blanks.)
346
 */
347
void
348
scr_msg(char *s, int set)
349
{
350
 
351
    if (set || CEstr == NULL) {
352
        int l = strlen(s);
353
 
354
        moveto(Rows - 2, ((Cols - l) >> 1) - 1);
355
        if (set)
356
            putstr(s);
357
        else
358
            while (--l >= 0)
359
                (void) putchar(' ');
360
    } else {
361
        moveto(Rows - 2, 0);
362
        putpad(CEstr);
363
    }
364
}