Subversion Repositories HelenOS-historic

Rev

Rev 1472 | Rev 1524 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1472 Rev 1519
1
/*  $OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray Exp $ */
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 $   */
2
/*  $NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft Exp $   */
3
 
3
 
4
/*-
4
/*-
5
 * Copyright (c) 1992, 1993
5
 * Copyright (c) 1992, 1993
6
 *  The Regents of the University of California.  All rights reserved.
6
 *  The Regents of the University of California.  All rights reserved.
7
 *
7
 *
8
 * This code is derived from software contributed to Berkeley by
8
 * This code is derived from software contributed to Berkeley by
9
 * Chris Torek and Darren F. Provine.
9
 * Chris Torek and Darren F. Provine.
10
 *
10
 *
11
 * Redistribution and use in source and binary forms, with or without
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
12
 * modification, are permitted provided that the following conditions
13
 * are met:
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
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
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
21
 *    without specific prior written permission.
22
 *
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
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
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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
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
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
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
33
 * SUCH DAMAGE.
34
 *
34
 *
35
 *  @(#)screen.c    8.1 (Berkeley) 5/31/93
35
 *  @(#)screen.c    8.1 (Berkeley) 5/31/93
36
 */
36
 */
37
 
37
 
38
/*
38
/*
39
 * Tetris screen control.
39
 * Tetris screen control.
40
 */
40
 */
41
 
41
 
42
#include <sys/ioctl.h>
-
 
43
 
-
 
44
#include <err.h>
42
#include <err.h>
45
//#include <setjmp.h>
-
 
46
//#include <signal.h>
-
 
47
#include <stdio.h>
43
#include <stdio.h>
48
#include <stdlib.h>
44
#include <stdlib.h>
49
#include <string.h>
45
#include <string.h>
50
#include <term.h>
-
 
51
#include <termios.h>
-
 
52
#include <unistd.h>
46
#include <unistd.h>
-
 
47
#include <io/stream.h>
53
 
48
 
54
#include "screen.h"
49
#include "screen.h"
55
#include "tetris.h"
50
#include "tetris.h"
56
 
51
 
57
static cell curscreen[B_SIZE];  /* 1 => standout (or otherwise marked) */
52
static cell curscreen[B_SIZE];  /* 1 => standout (or otherwise marked) */
58
static int curscore;
53
static int curscore;
59
static int isset;       /* true => terminal is in game mode */
54
static int isset;       /* true => terminal is in game mode */
60
static struct termios oldtt;
55
static struct termios oldtt;
61
static void (*tstp)(int);
56
static void (*tstp)(int);
62
 
57
 
63
static void scr_stop(int);
58
static void scr_stop(int);
64
static void stopset(int);
59
static void stopset(int);
65
 
60
 
66
/*
61
/*
67
 * Capabilities from TERMCAP.
62
 * Capabilities from TERMCAP.
68
 */
63
 */
69
char    PC, *BC, *UP;       /* tgoto requires globals: ugh! */
64
char    PC, *BC, *UP;       /* tgoto requires globals: ugh! */
70
 
65
 
71
static char
66
static char
72
    *bcstr,         /* backspace char */
67
    *bcstr,         /* backspace char */
73
    *CEstr,         /* clear to end of line */
68
    *CEstr,         /* clear to end of line */
74
    *CLstr,         /* clear screen */
69
    *CLstr,         /* clear screen */
75
    *CMstr,         /* cursor motion string */
70
    *CMstr,         /* cursor motion string */
76
#ifdef unneeded
71
#ifdef unneeded
77
    *CRstr,         /* "\r" equivalent */
72
    *CRstr,         /* "\r" equivalent */
78
#endif
73
#endif
79
    *HOstr,         /* cursor home */
74
    *HOstr,         /* cursor home */
80
    *LLstr,         /* last line, first column */
75
    *LLstr,         /* last line, first column */
81
    *pcstr,         /* pad character */
76
    *pcstr,         /* pad character */
82
    *TEstr,         /* end cursor motion mode */
77
    *TEstr,         /* end cursor motion mode */
83
    *TIstr;         /* begin cursor motion mode */
78
    *TIstr;         /* begin cursor motion mode */
84
char
79
char
85
    *SEstr,         /* end standout mode */
80
    *SEstr,         /* end standout mode */
86
    *SOstr;         /* begin standout mode */
81
    *SOstr;         /* begin standout mode */
87
static int
82
static int
88
    COnum,          /* co# value */
83
    COnum,          /* co# value */
89
    LInum,          /* li# value */
84
    LInum,          /* li# value */
90
    MSflag;         /* can move in standout mode */
85
    MSflag;         /* can move in standout mode */
91
 
86
 
92
 
87
 
93
struct tcsinfo {        /* termcap string info; some abbrevs above */
88
struct tcsinfo {        /* termcap string info; some abbrevs above */
94
    char tcname[3];
89
    char tcname[3];
95
    char **tcaddr;
90
    char **tcaddr;
96
} tcstrings[] = {
91
} tcstrings[] = {
97
    {"bc", &bcstr},
92
    {"bc", &bcstr},
98
    {"ce", &CEstr},
93
    {"ce", &CEstr},
99
    {"cl", &CLstr},
94
    {"cl", &CLstr},
100
    {"cm", &CMstr},
95
    {"cm", &CMstr},
101
#ifdef unneeded
96
#ifdef unneeded
102
    {"cr", &CRstr},
97
    {"cr", &CRstr},
103
#endif
98
#endif
104
    {"le", &BC},        /* move cursor left one space */
99
    {"le", &BC},        /* move cursor left one space */
105
    {"pc", &pcstr},
100
    {"pc", &pcstr},
106
    {"se", &SEstr},
101
    {"se", &SEstr},
107
    {"so", &SOstr},
102
    {"so", &SOstr},
108
    {"te", &TEstr},
103
    {"te", &TEstr},
109
    {"ti", &TIstr},
104
    {"ti", &TIstr},
110
    {"up", &UP},        /* cursor up */
105
    {"up", &UP},        /* cursor up */
111
    { {0}, NULL}
106
    { {0}, NULL}
112
};
107
};
113
 
108
 
114
/* This is where we will actually stuff the information */
109
/* This is where we will actually stuff the information */
115
 
110
 
116
static char combuf[1024], tbuf[1024];
111
static char combuf[1024], tbuf[1024];
117
 
112
 
118
 
113
 
119
/*
114
/*
120
 * Routine used by tputs().
115
 * Routine used by tputs().
121
 */
116
 */
122
int
117
int
123
put(int c)
118
put(int c)
124
{
119
{
125
 
120
 
126
    return (putchar(c));
121
    return (putchar(c));
127
}
122
}
128
 
123
 
129
/*
124
/*
130
 * putstr() is for unpadded strings (either as in termcap(5) or
125
 * putstr() is for unpadded strings (either as in termcap(5) or
131
 * simply literal strings); putpad() is for padded strings with
126
 * simply literal strings); putpad() is for padded strings with
132
 * count=1.  (See screen.h for putpad().)
127
 * count=1.  (See screen.h for putpad().)
133
 */
128
 */
134
#define putstr(s)   (void)fputs(s, stdout)
129
#define putstr(s)   (void)fputs(s, stdout)
135
#define moveto(r, c)    putpad(tgoto(CMstr, c, r))
130
#define moveto(r, c)    putpad(tgoto(CMstr, c, r))
136
 
131
 
-
 
132
static int con_phone;
-
 
133
 
137
/*
134
/*
138
 * Set up from termcap.
135
 * Set up from termcap.
139
 */
136
 */
140
void
137
void
141
scr_init(void)
138
scr_init(void)
142
{
139
{
143
    static int bsflag, xsflag, sgnum;
-
 
144
#ifdef unneeded
-
 
145
    static int ncflag;
-
 
146
#endif
-
 
147
    char *term, *fill;
-
 
148
    static struct tcninfo { /* termcap numeric and flag info */
-
 
149
        char tcname[3];
-
 
150
        int *tcaddr;
-
 
151
    } tcflags[] = {
-
 
152
        {"bs", &bsflag},
-
 
153
        {"ms", &MSflag},
-
 
154
#ifdef unneeded
-
 
155
        {"nc", &ncflag},
-
 
156
#endif
-
 
157
        {"xs", &xsflag},
-
 
158
        { {0}, NULL}
-
 
159
    }, tcnums[] = {
-
 
160
        {"co", &COnum},
-
 
161
        {"li", &LInum},
-
 
162
        {"sg", &sgnum},
-
 
163
        { {0}, NULL}
-
 
164
    };
-
 
165
   
-
 
166
    if ((term = getenv("TERM")) == NULL)
-
 
167
        stop("you must set the TERM environment variable");
-
 
168
    if (tgetent(tbuf, term) <= 0)
-
 
169
        stop("cannot find your termcap");
-
 
170
    fill = combuf;
-
 
171
    {
-
 
172
        struct tcsinfo *p;
-
 
173
 
-
 
174
        for (p = tcstrings; p->tcaddr; p++)
-
 
175
            *p->tcaddr = tgetstr(p->tcname, &fill);
-
 
176
    }
-
 
177
    if (classic)
-
 
178
        SOstr = SEstr = NULL;
-
 
179
    {
-
 
180
        struct tcninfo *p;
-
 
181
 
-
 
182
        for (p = tcflags; p->tcaddr; p++)
-
 
183
            *p->tcaddr = tgetflag(p->tcname);
-
 
184
        for (p = tcnums; p->tcaddr; p++)
-
 
185
            *p->tcaddr = tgetnum(p->tcname);
140
    con_phone = get_fd_phone(1);
186
    }
-
 
187
    if (bsflag)
-
 
188
        BC = "\b";
-
 
189
    else if (BC == NULL && bcstr != NULL)
-
 
190
        BC = bcstr;
-
 
191
    if (CLstr == NULL)
-
 
192
        stop("cannot clear screen");
-
 
193
    if (CMstr == NULL || UP == NULL || BC == NULL)
-
 
194
        stop("cannot do random cursor positioning via tgoto()");
-
 
195
    PC = pcstr ? *pcstr : 0;
-
 
196
    if (sgnum > 0 || xsflag)
-
 
197
        SOstr = SEstr = NULL;
-
 
198
#ifdef unneeded
-
 
199
    if (ncflag)
-
 
200
        CRstr = NULL;
-
 
201
    else if (CRstr == NULL)
-
 
202
        CRstr = "\r";
-
 
203
#endif
-
 
204
}
141
}
205
 
142
 
206
/* this foolery is needed to modify tty state `atomically' */
-
 
207
//static jmp_buf scr_onstop;
-
 
208
 
-
 
209
/* static void */
-
 
210
/* stopset(int sig) */
-
 
211
/* { */
-
 
212
/*  sigset_t sigset; */
-
 
213
 
-
 
214
/*  (void) signal(sig, SIG_DFL); */
-
 
215
/*  (void) kill(getpid(), sig); */
-
 
216
/*  sigemptyset(&sigset); */
-
 
217
/*  sigaddset(&sigset, sig); */
-
 
218
/*  (void) sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *)0); */
-
 
219
/*  longjmp(scr_onstop, 1); */
-
 
220
/* } */
-
 
221
 
143
 
222
static void
144
static void
223
scr_stop(int sig)
145
scr_stop(int sig)
224
{
146
{
225
//  sigset_t sigset;
-
 
226
 
147
 
227
    scr_end();
148
    scr_end();
228
/*  (void) kill(getpid(), sig); */
-
 
229
/*  sigemptyset(&sigset); */
-
 
230
/*  sigaddset(&sigset, sig); */
-
 
231
/*  (void) sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *)0); */
-
 
232
    scr_set();
149
    scr_set();
233
    scr_msg(key_msg, 1);
150
    scr_msg(key_msg, 1);
234
}
151
}
235
 
152
 
236
/*
153
/*
237
 * Set up screen mode.
154
 * Set up screen mode.
238
 */
155
 */
239
void
156
void
240
scr_set(void)
157
scr_set(void)
241
{
158
{
242
    struct winsize ws;
159
    struct winsize ws;
243
    struct termios newtt;
160
    struct termios newtt;
244
//  sigset_t sigset, osigset;
-
 
245
    void (*ttou)(int);
161
    void (*ttou)(int);
246
 
162
 
247
/*  sigemptyset(&sigset); */
-
 
248
/*  sigaddset(&sigset, SIGTSTP); */
-
 
249
/*  sigaddset(&sigset, SIGTTOU); */
-
 
250
/*  (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); */
-
 
251
/*  if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN) */
-
 
252
/*      (void) signal(SIGTSTP, SIG_IGN); */
-
 
253
/*  if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN) */
-
 
254
/*      (void) signal(SIGTTOU, SIG_IGN); */
-
 
255
/*  /\* */
-
 
256
/*   * At last, we are ready to modify the tty state.  If */
-
 
257
/*   * we stop while at it, stopset() above will longjmp back */
-
 
258
/*   * to the setjmp here and we will start over. */
-
 
259
/*   *\/ */
-
 
260
/*  (void) setjmp(scr_onstop); */
-
 
261
/*  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); */
-
 
262
    Rows = 0, Cols = 0;
163
    Rows = 0, Cols = 0;
263
    if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
164
    if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
264
        Rows = ws.ws_row;
165
        Rows = ws.ws_row;
265
        Cols = ws.ws_col;
166
        Cols = ws.ws_col;
266
    }
167
    }
267
    if (Rows == 0)
168
    if (Rows == 0)
268
        Rows = LInum;
169
        Rows = LInum;
269
    if (Cols == 0)
170
    if (Cols == 0)
270
    Cols = COnum;
171
    Cols = COnum;
271
    if (Rows < MINROWS || Cols < MINCOLS) {
172
    if (Rows < MINROWS || Cols < MINCOLS) {
272
        char smallscr[55];
173
        char smallscr[55];
273
 
174
 
274
        (void)snprintf(smallscr, sizeof(smallscr),
175
        (void)snprintf(smallscr, sizeof(smallscr),
275
            "the screen is too small (must be at least %dx%d)",
176
            "the screen is too small (must be at least %dx%d)",
276
            MINROWS, MINCOLS);
177
            MINROWS, MINCOLS);
277
        stop(smallscr);
178
        stop(smallscr);
278
    }
179
    }
279
    if (tcgetattr(0, &oldtt) < 0)
180
    if (tcgetattr(0, &oldtt) < 0)
280
        stop("tcgetattr() fails");
181
        stop("tcgetattr() fails");
281
    newtt = oldtt;
182
    newtt = oldtt;
282
    newtt.c_lflag &= ~(ICANON|ECHO);
183
    newtt.c_lflag &= ~(ICANON|ECHO);
283
    newtt.c_oflag &= ~OXTABS;
184
    newtt.c_oflag &= ~OXTABS;
284
    if (tcsetattr(0, TCSADRAIN, &newtt) < 0)
185
    if (tcsetattr(0, TCSADRAIN, &newtt) < 0)
285
        stop("tcsetattr() fails");
186
        stop("tcsetattr() fails");
286
/*  (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); */
-
 
287
 
187
 
288
    /*
188
    /*
289
     * We made it.  We are now in screen mode, modulo TIstr
189
     * We made it.  We are now in screen mode, modulo TIstr
290
     * (which we will fix immediately).
190
     * (which we will fix immediately).
291
     */
191
     */
292
    if (TIstr)
192
    if (TIstr)
293
        putstr(TIstr);  /* termcap(5) says this is not padded */
193
        putstr(TIstr);  /* termcap(5) says this is not padded */
294
/*  if (tstp != SIG_IGN) */
-
 
295
/*      (void) signal(SIGTSTP, scr_stop); */
-
 
296
/*  if (ttou != SIG_IGN) */
-
 
297
/*      (void) signal(SIGTTOU, ttou); */
-
 
298
 
194
 
299
    isset = 1;
195
    isset = 1;
300
//  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
-
 
-
 
196
 
301
    scr_clear();
197
    scr_clear();
302
}
198
}
303
 
199
 
304
/*
200
/*
305
 * End screen mode.
201
 * End screen mode.
306
 */
202
 */
307
void
203
void
308
scr_end(void)
204
scr_end(void)
309
{
205
{
310
//  sigset_t sigset, osigset;
-
 
311
 
-
 
312
/*  sigemptyset(&sigset); */
-
 
313
/*  sigaddset(&sigset, SIGTSTP); */
-
 
314
/*  sigaddset(&sigset, SIGTTOU); */
-
 
315
/*  (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); */
-
 
316
    /* move cursor to last line */
-
 
317
    if (LLstr)
-
 
318
        putstr(LLstr);  /* termcap(5) says this is not padded */
-
 
319
    else
-
 
320
        moveto(Rows - 1, 0);
-
 
321
    /* exit screen mode */
-
 
322
    if (TEstr)
-
 
323
        putstr(TEstr);  /* termcap(5) says this is not padded */
-
 
324
//  (void) fflush(stdout);
-
 
325
    (void) tcsetattr(0, TCSADRAIN, &oldtt);
-
 
326
    isset = 0;
-
 
327
    /* restore signals */
-
 
328
/*  (void) signal(SIGTSTP, tstp); */
-
 
329
/*  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); */
-
 
330
}
206
}
331
 
207
 
332
void
208
void
333
stop(char *why)
209
stop(char *why)
334
{
210
{
335
 
211
 
336
    if (isset)
212
    if (isset)
337
        scr_end();
213
        scr_end();
338
    errx(1, "aborting: %s", why);
214
    errx(1, "aborting: %s", why);
339
}
215
}
340
 
216
 
341
/*
217
/*
342
 * Clear the screen, forgetting the current contents in the process.
218
 * Clear the screen, forgetting the current contents in the process.
343
 */
219
 */
344
void
220
void
345
scr_clear(void)
221
scr_clear(void)
346
{
222
{
347
 
223
 
348
    putpad(CLstr);
224
    putpad(CLstr);
349
    curscore = -1;
225
    curscore = -1;
350
    memset((char *)curscreen, 0, sizeof(curscreen));
226
    memset((char *)curscreen, 0, sizeof(curscreen));
351
}
227
}
352
 
228
 
353
#if vax && !__GNUC__
229
#if vax && !__GNUC__
354
typedef int regcell;    /* pcc is bad at `register char', etc */
230
typedef int regcell;    /* pcc is bad at `register char', etc */
355
#else
231
#else
356
typedef cell regcell;
232
typedef cell regcell;
357
#endif
233
#endif
358
 
234
 
359
/*
235
/*
360
 * Update the screen.
236
 * Update the screen.
361
 */
237
 */
362
void
238
void
363
scr_update(void)
239
scr_update(void)
364
{
240
{
365
    cell *bp, *sp;
241
    cell *bp, *sp;
366
    regcell so, cur_so = 0;
242
    regcell so, cur_so = 0;
367
    int i, ccol, j;
243
    int i, ccol, j;
368
//  sigset_t sigset, osigset;
-
 
369
    static const struct shape *lastshape;
244
    static const struct shape *lastshape;
370
 
245
 
371
/*  sigemptyset(&sigset); */
-
 
372
/*  sigaddset(&sigset, SIGTSTP); */
-
 
373
/*  (void) sigprocmask(SIG_BLOCK, &sigset, &osigset); */
-
 
374
 
-
 
375
    /* always leave cursor after last displayed point */
246
    /* always leave cursor after last displayed point */
376
    curscreen[D_LAST * B_COLS - 1] = -1;
247
    curscreen[D_LAST * B_COLS - 1] = -1;
377
 
248
 
378
    if (score != curscore) {
249
    if (score != curscore) {
379
        if (HOstr)
250
        if (HOstr)
380
            putpad(HOstr);
251
            putpad(HOstr);
381
        else
252
        else
382
            moveto(0, 0);
253
            moveto(0, 0);
383
        (void) printf("Score: %d", score);
254
        (void) printf("Score: %d", score);
384
        curscore = score;
255
        curscore = score;
385
    }
256
    }
386
 
257
 
387
    /* draw preview of next pattern */
258
    /* draw preview of next pattern */
388
    if (showpreview && (nextshape != lastshape)) {
259
    if (showpreview && (nextshape != lastshape)) {
389
        int i;
260
        int i;
390
        static int r=5, c=2;
261
        static int r=5, c=2;
391
        int tr, tc, t;
262
        int tr, tc, t;
392
 
263
 
393
        lastshape = nextshape;
264
        lastshape = nextshape;
394
 
265
 
395
        /* clean */
266
        /* clean */
396
        putpad(SEstr);
267
        putpad(SEstr);
397
        moveto(r-1, c-1); putstr("          ");
268
        moveto(r-1, c-1); putstr("          ");
398
        moveto(r,   c-1); putstr("          ");
269
        moveto(r,   c-1); putstr("          ");
399
        moveto(r+1, c-1); putstr("          ");
270
        moveto(r+1, c-1); putstr("          ");
400
        moveto(r+2, c-1); putstr("          ");
271
        moveto(r+2, c-1); putstr("          ");
401
 
272
 
402
        moveto(r-3, c-2);
273
        moveto(r-3, c-2);
403
        putstr("Next shape:");
274
        putstr("Next shape:");
404
 
275
 
405
        /* draw */
276
        /* draw */
406
        if (SOstr)
277
        if (SOstr)
407
            putpad(SOstr);
278
            putpad(SOstr);
408
        moveto(r, 2 * c);
279
        moveto(r, 2 * c);
409
        putstr(SOstr ? "  " : "[]");
280
        putstr(SOstr ? "  " : "[]");
410
        for (i = 0; i < 3; i++) {
281
        for (i = 0; i < 3; i++) {
411
            t = c + r * B_COLS;
282
            t = c + r * B_COLS;
412
            t += nextshape->off[i];
283
            t += nextshape->off[i];
413
 
284
 
414
            tr = t / B_COLS;
285
            tr = t / B_COLS;
415
            tc = t % B_COLS;
286
            tc = t % B_COLS;
416
 
287
 
417
            moveto(tr, 2*tc);
288
            moveto(tr, 2*tc);
418
            putstr(SOstr ? "  " : "[]");
289
            putstr(SOstr ? "  " : "[]");
419
        }
290
        }
420
        putpad(SEstr);
291
        putpad(SEstr);
421
    }
292
    }
422
 
293
 
423
    bp = &board[D_FIRST * B_COLS];
294
    bp = &board[D_FIRST * B_COLS];
424
    sp = &curscreen[D_FIRST * B_COLS];
295
    sp = &curscreen[D_FIRST * B_COLS];
425
    for (j = D_FIRST; j < D_LAST; j++) {
296
    for (j = D_FIRST; j < D_LAST; j++) {
426
        ccol = -1;
297
        ccol = -1;
427
        for (i = 0; i < B_COLS; bp++, sp++, i++) {
298
        for (i = 0; i < B_COLS; bp++, sp++, i++) {
428
            if (*sp == (so = *bp))
299
            if (*sp == (so = *bp))
429
                continue;
300
                continue;
430
            *sp = so;
301
            *sp = so;
431
            if (i != ccol) {
302
            if (i != ccol) {
432
                if (cur_so && MSflag) {
303
                if (cur_so && MSflag) {
433
                    putpad(SEstr);
304
                    putpad(SEstr);
434
                    cur_so = 0;
305
                    cur_so = 0;
435
                }
306
                }
436
                moveto(RTOD(j), CTOD(i));
307
                moveto(RTOD(j), CTOD(i));
437
            }
308
            }
438
            if (SOstr) {
309
            if (SOstr) {
439
                if (so != cur_so) {
310
                if (so != cur_so) {
440
                    putpad(so ? SOstr : SEstr);
311
                    putpad(so ? SOstr : SEstr);
441
                    cur_so = so;
312
                    cur_so = so;
442
                }
313
                }
443
                putstr("  ");
314
                putstr("  ");
444
            } else
315
            } else
445
                putstr(so ? "[]" : "  ");
316
                putstr(so ? "[]" : "  ");
446
            ccol = i + 1;
317
            ccol = i + 1;
447
            /*
318
            /*
448
             * Look ahead a bit, to avoid extra motion if
319
             * Look ahead a bit, to avoid extra motion if
449
             * we will be redrawing the cell after the next.
320
             * we will be redrawing the cell after the next.
450
             * Motion probably takes four or more characters,
321
             * Motion probably takes four or more characters,
451
             * so we save even if we rewrite two cells
322
             * so we save even if we rewrite two cells
452
             * `unnecessarily'.  Skip it all, though, if
323
             * `unnecessarily'.  Skip it all, though, if
453
             * the next cell is a different color.
324
             * the next cell is a different color.
454
             */
325
             */
455
#define STOP (B_COLS - 3)
326
#define STOP (B_COLS - 3)
456
            if (i > STOP || sp[1] != bp[1] || so != bp[1])
327
            if (i > STOP || sp[1] != bp[1] || so != bp[1])
457
                continue;
328
                continue;
458
            if (sp[2] != bp[2])
329
            if (sp[2] != bp[2])
459
                sp[1] = -1;
330
                sp[1] = -1;
460
            else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
331
            else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
461
                sp[2] = -1;
332
                sp[2] = -1;
462
                sp[1] = -1;
333
                sp[1] = -1;
463
            }
334
            }
464
        }
335
        }
465
    }
336
    }
466
    if (cur_so)
337
    if (cur_so)
467
        putpad(SEstr);
338
        putpad(SEstr);
468
/*  (void) fflush(stdout); */
339
/*  (void) fflush(stdout); */
469
/*  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); */
340
/*  (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); */
470
}
341
}
471
 
342
 
472
/*
343
/*
473
 * Write a message (set!=0), or clear the same message (set==0).
344
 * Write a message (set!=0), or clear the same message (set==0).
474
 * (We need its length in case we have to overwrite with blanks.)
345
 * (We need its length in case we have to overwrite with blanks.)
475
 */
346
 */
476
void
347
void
477
scr_msg(char *s, int set)
348
scr_msg(char *s, int set)
478
{
349
{
479
   
350
   
480
    if (set || CEstr == NULL) {
351
    if (set || CEstr == NULL) {
481
        int l = strlen(s);
352
        int l = strlen(s);
482
 
353
 
483
        moveto(Rows - 2, ((Cols - l) >> 1) - 1);
354
        moveto(Rows - 2, ((Cols - l) >> 1) - 1);
484
        if (set)
355
        if (set)
485
            putstr(s);
356
            putstr(s);
486
        else
357
        else
487
            while (--l >= 0)
358
            while (--l >= 0)
488
                (void) putchar(' ');
359
                (void) putchar(' ');
489
    } else {
360
    } else {
490
        moveto(Rows - 2, 0);
361
        moveto(Rows - 2, 0);
491
        putpad(CEstr);
362
        putpad(CEstr);
492
    }
363
    }
493
}
364
}
494
 
365