2000-05-24 18:43:00 +04:00
|
|
|
/* $NetBSD: screen.c,v 1.15 2000/05/24 14:43:00 blymn Exp $ */
|
1995-04-22 11:42:31 +04:00
|
|
|
|
1994-05-06 10:50:50 +04:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 1992, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Chris Torek and Darren F. Provine.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @(#)screen.c 8.1 (Berkeley) 5/31/93
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tetris screen control.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1997-10-14 05:14:20 +04:00
|
|
|
#include <termcap.h>
|
1995-04-29 02:09:25 +04:00
|
|
|
#include <termios.h>
|
1994-05-06 10:50:50 +04:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#ifndef sigmask
|
|
|
|
#define sigmask(s) (1 << ((s) - 1))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "screen.h"
|
|
|
|
#include "tetris.h"
|
|
|
|
|
|
|
|
static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */
|
|
|
|
static int curscore;
|
|
|
|
static int isset; /* true => terminal is in game mode */
|
1995-04-29 02:09:25 +04:00
|
|
|
static struct termios oldtt;
|
1997-10-12 06:03:45 +04:00
|
|
|
static void (*tstp) __P((int));
|
1994-05-06 10:50:50 +04:00
|
|
|
|
1997-10-12 06:03:45 +04:00
|
|
|
static void scr_stop __P((int));
|
1999-09-09 01:45:25 +04:00
|
|
|
static void stopset __P((int)) __attribute__((__noreturn__));
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Capabilities from TERMCAP.
|
|
|
|
*/
|
1999-08-14 20:38:45 +04:00
|
|
|
short ospeed;
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
static char
|
|
|
|
*bcstr, /* backspace char */
|
|
|
|
*CEstr, /* clear to end of line */
|
|
|
|
*CLstr, /* clear screen */
|
|
|
|
*CMstr, /* cursor motion string */
|
|
|
|
#ifdef unneeded
|
|
|
|
*CRstr, /* "\r" equivalent */
|
|
|
|
#endif
|
|
|
|
*HOstr, /* cursor home */
|
|
|
|
*LLstr, /* last line, first column */
|
|
|
|
*pcstr, /* pad character */
|
|
|
|
*TEstr, /* end cursor motion mode */
|
|
|
|
*TIstr; /* begin cursor motion mode */
|
|
|
|
char
|
|
|
|
*SEstr, /* end standout mode */
|
|
|
|
*SOstr; /* begin standout mode */
|
|
|
|
static int
|
|
|
|
COnum, /* co# value */
|
|
|
|
LInum, /* li# value */
|
|
|
|
MSflag; /* can move in standout mode */
|
|
|
|
|
|
|
|
|
|
|
|
struct tcsinfo { /* termcap string info; some abbrevs above */
|
|
|
|
char tcname[3];
|
|
|
|
char **tcaddr;
|
|
|
|
} tcstrings[] = {
|
1997-10-12 06:03:45 +04:00
|
|
|
{"bc", &bcstr},
|
|
|
|
{"ce", &CEstr},
|
|
|
|
{"cl", &CLstr},
|
|
|
|
{"cm", &CMstr},
|
1994-05-06 10:50:50 +04:00
|
|
|
#ifdef unneeded
|
1997-10-12 06:03:45 +04:00
|
|
|
{"cr", &CRstr},
|
1994-05-06 10:50:50 +04:00
|
|
|
#endif
|
1997-10-12 06:03:45 +04:00
|
|
|
{"le", &BC}, /* move cursor left one space */
|
|
|
|
{"pc", &pcstr},
|
|
|
|
{"se", &SEstr},
|
|
|
|
{"so", &SOstr},
|
|
|
|
{"te", &TEstr},
|
|
|
|
{"ti", &TIstr},
|
|
|
|
{"up", &UP}, /* cursor up */
|
|
|
|
{ {0}, NULL}
|
1994-05-06 10:50:50 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
/* This is where we will actually stuff the information */
|
|
|
|
|
2000-05-22 16:42:46 +04:00
|
|
|
static char *combuf;
|
|
|
|
static struct tinfo *info;
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Routine used by tputs().
|
|
|
|
*/
|
1999-10-05 03:26:59 +04:00
|
|
|
int
|
1994-05-06 10:50:50 +04:00
|
|
|
put(c)
|
|
|
|
int c;
|
|
|
|
{
|
|
|
|
|
1999-10-05 03:26:59 +04:00
|
|
|
return (putchar(c));
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* putstr() is for unpadded strings (either as in termcap(5) or
|
|
|
|
* simply literal strings); putpad() is for padded strings with
|
|
|
|
* count=1. (See screen.h for putpad().)
|
|
|
|
*/
|
|
|
|
#define putstr(s) (void)fputs(s, stdout)
|
2000-05-22 16:42:46 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
moveto(int r, int c)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
if (t_goto(info, CMstr, c, r, buf, 255) == 0)
|
|
|
|
putpad(buf);
|
|
|
|
}
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up from termcap.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_init()
|
|
|
|
{
|
|
|
|
static int bsflag, xsflag, sgnum;
|
|
|
|
#ifdef unneeded
|
|
|
|
static int ncflag;
|
|
|
|
#endif
|
|
|
|
char *term, *fill;
|
|
|
|
static struct tcninfo { /* termcap numeric and flag info */
|
|
|
|
char tcname[3];
|
|
|
|
int *tcaddr;
|
|
|
|
} tcflags[] = {
|
1997-10-12 06:03:45 +04:00
|
|
|
{"bs", &bsflag},
|
|
|
|
{"ms", &MSflag},
|
1994-05-06 10:50:50 +04:00
|
|
|
#ifdef unneeded
|
1997-10-12 06:03:45 +04:00
|
|
|
{"nc", &ncflag},
|
1994-05-06 10:50:50 +04:00
|
|
|
#endif
|
1997-10-12 06:03:45 +04:00
|
|
|
{"xs", &xsflag},
|
|
|
|
{ {0}, NULL}
|
1994-05-06 10:50:50 +04:00
|
|
|
}, tcnums[] = {
|
1997-10-12 06:03:45 +04:00
|
|
|
{"co", &COnum},
|
|
|
|
{"li", &LInum},
|
|
|
|
{"sg", &sgnum},
|
|
|
|
{ {0}, NULL}
|
1994-05-06 10:50:50 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
if ((term = getenv("TERM")) == NULL)
|
|
|
|
stop("you must set the TERM environment variable");
|
2000-05-22 16:42:46 +04:00
|
|
|
if (t_getent(&info, term) <= 0)
|
1994-05-06 10:50:50 +04:00
|
|
|
stop("cannot find your termcap");
|
2000-05-24 18:43:00 +04:00
|
|
|
combuf = NULL;
|
1994-05-06 10:50:50 +04:00
|
|
|
{
|
|
|
|
register struct tcsinfo *p;
|
|
|
|
|
|
|
|
for (p = tcstrings; p->tcaddr; p++)
|
2000-05-22 16:42:46 +04:00
|
|
|
*p->tcaddr = t_agetstr(info, p->tcname, &combuf,
|
|
|
|
&fill);
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
{
|
|
|
|
register struct tcninfo *p;
|
|
|
|
|
|
|
|
for (p = tcflags; p->tcaddr; p++)
|
2000-05-22 16:42:46 +04:00
|
|
|
*p->tcaddr = t_getflag(info, p->tcname);
|
1994-05-06 10:50:50 +04:00
|
|
|
for (p = tcnums; p->tcaddr; p++)
|
2000-05-22 16:42:46 +04:00
|
|
|
*p->tcaddr = t_getnum(info, p->tcname);
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
if (bsflag)
|
|
|
|
BC = "\b";
|
|
|
|
else if (BC == NULL && bcstr != NULL)
|
|
|
|
BC = bcstr;
|
|
|
|
if (CLstr == NULL)
|
|
|
|
stop("cannot clear screen");
|
|
|
|
if (CMstr == NULL || UP == NULL || BC == NULL)
|
|
|
|
stop("cannot do random cursor positioning via tgoto()");
|
|
|
|
PC = pcstr ? *pcstr : 0;
|
|
|
|
if (sgnum >= 0 || xsflag)
|
|
|
|
SOstr = SEstr = NULL;
|
|
|
|
#ifdef unneeded
|
|
|
|
if (ncflag)
|
|
|
|
CRstr = NULL;
|
|
|
|
else if (CRstr == NULL)
|
|
|
|
CRstr = "\r";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this foolery is needed to modify tty state `atomically' */
|
|
|
|
static jmp_buf scr_onstop;
|
|
|
|
|
|
|
|
static void
|
|
|
|
stopset(sig)
|
|
|
|
int sig;
|
|
|
|
{
|
1995-04-29 02:09:25 +04:00
|
|
|
sigset_t sigset;
|
|
|
|
|
1994-05-06 10:50:50 +04:00
|
|
|
(void) signal(sig, SIG_DFL);
|
|
|
|
(void) kill(getpid(), sig);
|
1995-04-29 02:09:25 +04:00
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, sig);
|
|
|
|
(void) sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
longjmp(scr_onstop, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1995-04-29 02:09:25 +04:00
|
|
|
scr_stop(sig)
|
|
|
|
int sig;
|
1994-05-06 10:50:50 +04:00
|
|
|
{
|
1995-04-29 02:09:25 +04:00
|
|
|
sigset_t sigset;
|
|
|
|
|
1994-05-06 10:50:50 +04:00
|
|
|
scr_end();
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) kill(getpid(), sig);
|
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, sig);
|
|
|
|
(void) sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
scr_set();
|
|
|
|
scr_msg(key_msg, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up screen mode.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_set()
|
|
|
|
{
|
|
|
|
struct winsize ws;
|
1995-04-29 02:09:25 +04:00
|
|
|
struct termios newtt;
|
|
|
|
sigset_t sigset, osigset;
|
1997-10-12 06:03:45 +04:00
|
|
|
void (*ttou) __P((int));
|
1994-05-06 10:50:50 +04:00
|
|
|
|
1995-04-29 02:09:25 +04:00
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, SIGTSTP);
|
|
|
|
sigaddset(&sigset, SIGTTOU);
|
|
|
|
(void) sigprocmask(SIG_BLOCK, &sigset, &osigset);
|
1994-05-06 10:50:50 +04:00
|
|
|
if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN)
|
|
|
|
(void) signal(SIGTSTP, SIG_IGN);
|
1995-04-29 02:09:25 +04:00
|
|
|
if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN)
|
|
|
|
(void) signal(SIGTTOU, SIG_IGN);
|
1994-05-06 10:50:50 +04:00
|
|
|
/*
|
|
|
|
* At last, we are ready to modify the tty state. If
|
|
|
|
* we stop while at it, stopset() above will longjmp back
|
|
|
|
* to the setjmp here and we will start over.
|
|
|
|
*/
|
|
|
|
(void) setjmp(scr_onstop);
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
Rows = 0, Cols = 0;
|
|
|
|
if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
|
|
|
|
Rows = ws.ws_row;
|
|
|
|
Cols = ws.ws_col;
|
|
|
|
}
|
|
|
|
if (Rows == 0)
|
|
|
|
Rows = LInum;
|
|
|
|
if (Cols == 0)
|
|
|
|
Cols = COnum;
|
|
|
|
if (Rows < MINROWS || Cols < MINCOLS) {
|
|
|
|
(void) fprintf(stderr,
|
1999-01-03 05:00:17 +03:00
|
|
|
"the screen is too small: must be at least %dx%d, ",
|
|
|
|
MINCOLS, MINROWS);
|
1994-05-06 10:50:50 +04:00
|
|
|
stop(""); /* stop() supplies \n */
|
|
|
|
}
|
1995-04-29 02:09:25 +04:00
|
|
|
if (tcgetattr(0, &oldtt) < 0)
|
|
|
|
stop("tcgetattr() fails");
|
1994-05-06 10:50:50 +04:00
|
|
|
newtt = oldtt;
|
1995-04-29 02:09:25 +04:00
|
|
|
newtt.c_lflag &= ~(ICANON|ECHO);
|
|
|
|
newtt.c_oflag &= ~OXTABS;
|
|
|
|
if (tcsetattr(0, TCSADRAIN, &newtt) < 0)
|
|
|
|
stop("tcsetattr() fails");
|
|
|
|
ospeed = cfgetospeed(&newtt);
|
|
|
|
(void) sigprocmask(SIG_BLOCK, &sigset, &osigset);
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We made it. We are now in screen mode, modulo TIstr
|
|
|
|
* (which we will fix immediately).
|
|
|
|
*/
|
|
|
|
if (TIstr)
|
|
|
|
putstr(TIstr); /* termcap(5) says this is not padded */
|
|
|
|
if (tstp != SIG_IGN)
|
|
|
|
(void) signal(SIGTSTP, scr_stop);
|
1995-04-29 02:09:25 +04:00
|
|
|
if (ttou != SIG_IGN)
|
|
|
|
(void) signal(SIGTTOU, ttou);
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
isset = 1;
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
scr_clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* End screen mode.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_end()
|
|
|
|
{
|
1995-04-29 02:09:25 +04:00
|
|
|
sigset_t sigset, osigset;
|
1994-05-06 10:50:50 +04:00
|
|
|
|
1995-04-29 02:09:25 +04:00
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, SIGTSTP);
|
|
|
|
sigaddset(&sigset, SIGTTOU);
|
|
|
|
(void) sigprocmask(SIG_BLOCK, &sigset, &osigset);
|
1994-05-06 10:50:50 +04:00
|
|
|
/* move cursor to last line */
|
|
|
|
if (LLstr)
|
|
|
|
putstr(LLstr); /* termcap(5) says this is not padded */
|
|
|
|
else
|
|
|
|
moveto(Rows - 1, 0);
|
|
|
|
/* exit screen mode */
|
|
|
|
if (TEstr)
|
|
|
|
putstr(TEstr); /* termcap(5) says this is not padded */
|
|
|
|
(void) fflush(stdout);
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) tcsetattr(0, TCSADRAIN, &oldtt);
|
1994-05-06 10:50:50 +04:00
|
|
|
isset = 0;
|
|
|
|
/* restore signals */
|
|
|
|
(void) signal(SIGTSTP, tstp);
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
stop(why)
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
const char *why;
|
1994-05-06 10:50:50 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
if (isset)
|
|
|
|
scr_end();
|
|
|
|
(void) fprintf(stderr, "aborting: %s\n", why);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the screen, forgetting the current contents in the process.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_clear()
|
|
|
|
{
|
|
|
|
|
|
|
|
putpad(CLstr);
|
|
|
|
curscore = -1;
|
1998-08-10 06:23:45 +04:00
|
|
|
memset((char *)curscreen, 0, sizeof(curscreen));
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if vax && !__GNUC__
|
|
|
|
typedef int regcell; /* pcc is bad at `register char', etc */
|
|
|
|
#else
|
|
|
|
typedef cell regcell;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the screen.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_update()
|
|
|
|
{
|
|
|
|
register cell *bp, *sp;
|
|
|
|
register regcell so, cur_so = 0;
|
|
|
|
register int i, ccol, j;
|
1995-04-29 02:09:25 +04:00
|
|
|
sigset_t sigset, osigset;
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
static const struct shape *lastshape;
|
1995-04-29 02:09:25 +04:00
|
|
|
|
|
|
|
sigemptyset(&sigset);
|
|
|
|
sigaddset(&sigset, SIGTSTP);
|
|
|
|
(void) sigprocmask(SIG_BLOCK, &sigset, &osigset);
|
1994-05-06 10:50:50 +04:00
|
|
|
|
|
|
|
/* always leave cursor after last displayed point */
|
|
|
|
curscreen[D_LAST * B_COLS - 1] = -1;
|
|
|
|
|
|
|
|
if (score != curscore) {
|
|
|
|
if (HOstr)
|
|
|
|
putpad(HOstr);
|
|
|
|
else
|
|
|
|
moveto(0, 0);
|
1999-01-03 05:00:17 +03:00
|
|
|
(void) printf("Score: %d", score);
|
1994-05-06 10:50:50 +04:00
|
|
|
curscore = score;
|
|
|
|
}
|
|
|
|
|
1999-01-03 05:00:17 +03:00
|
|
|
/* draw preview of nextpattern */
|
1999-01-03 20:13:51 +03:00
|
|
|
if (showpreview && (nextshape != lastshape)) {
|
1999-01-03 05:00:17 +03:00
|
|
|
int i;
|
|
|
|
static int r=5, c=2;
|
|
|
|
int tr, tc, t;
|
|
|
|
|
|
|
|
lastshape = nextshape;
|
|
|
|
|
|
|
|
/* clean */
|
|
|
|
putpad(SEstr);
|
|
|
|
moveto(r-1, c-1); putstr(" ");
|
|
|
|
moveto(r, c-1); putstr(" ");
|
|
|
|
moveto(r+1, c-1); putstr(" ");
|
|
|
|
moveto(r+2, c-1); putstr(" ");
|
|
|
|
|
|
|
|
moveto(r-3, c-2);
|
|
|
|
putstr("Next shape:");
|
|
|
|
|
|
|
|
/* draw */
|
|
|
|
putpad(SOstr);
|
|
|
|
moveto(r, 2*c);
|
|
|
|
putstr(" ");
|
|
|
|
for(i=0; i<3; i++) {
|
|
|
|
t = c + r*B_COLS;
|
|
|
|
t += nextshape->off[i];
|
|
|
|
|
|
|
|
tr = t / B_COLS;
|
|
|
|
tc = t % B_COLS;
|
|
|
|
|
|
|
|
moveto(tr, 2*tc);
|
|
|
|
putstr(" ");
|
|
|
|
}
|
|
|
|
putpad(SEstr);
|
|
|
|
}
|
|
|
|
|
1994-05-06 10:50:50 +04:00
|
|
|
bp = &board[D_FIRST * B_COLS];
|
|
|
|
sp = &curscreen[D_FIRST * B_COLS];
|
|
|
|
for (j = D_FIRST; j < D_LAST; j++) {
|
|
|
|
ccol = -1;
|
|
|
|
for (i = 0; i < B_COLS; bp++, sp++, i++) {
|
|
|
|
if (*sp == (so = *bp))
|
|
|
|
continue;
|
|
|
|
*sp = so;
|
|
|
|
if (i != ccol) {
|
|
|
|
if (cur_so && MSflag) {
|
|
|
|
putpad(SEstr);
|
|
|
|
cur_so = 0;
|
|
|
|
}
|
|
|
|
moveto(RTOD(j), CTOD(i));
|
|
|
|
}
|
|
|
|
if (SOstr) {
|
|
|
|
if (so != cur_so) {
|
|
|
|
putpad(so ? SOstr : SEstr);
|
|
|
|
cur_so = so;
|
|
|
|
}
|
|
|
|
putstr(" ");
|
|
|
|
} else
|
|
|
|
putstr(so ? "XX" : " ");
|
|
|
|
ccol = i + 1;
|
|
|
|
/*
|
|
|
|
* Look ahead a bit, to avoid extra motion if
|
|
|
|
* we will be redrawing the cell after the next.
|
|
|
|
* Motion probably takes four or more characters,
|
|
|
|
* so we save even if we rewrite two cells
|
|
|
|
* `unnecessarily'. Skip it all, though, if
|
|
|
|
* the next cell is a different color.
|
|
|
|
*/
|
|
|
|
#define STOP (B_COLS - 3)
|
|
|
|
if (i > STOP || sp[1] != bp[1] || so != bp[1])
|
|
|
|
continue;
|
|
|
|
if (sp[2] != bp[2])
|
|
|
|
sp[1] = -1;
|
|
|
|
else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
|
|
|
|
sp[2] = -1;
|
|
|
|
sp[1] = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cur_so)
|
|
|
|
putpad(SEstr);
|
|
|
|
(void) fflush(stdout);
|
1995-04-29 02:09:25 +04:00
|
|
|
(void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
|
1994-05-06 10:50:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write a message (set!=0), or clear the same message (set==0).
|
|
|
|
* (We need its length in case we have to overwrite with blanks.)
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
scr_msg(s, set)
|
|
|
|
register char *s;
|
|
|
|
int set;
|
|
|
|
{
|
|
|
|
|
|
|
|
if (set || CEstr == NULL) {
|
|
|
|
register int l = strlen(s);
|
|
|
|
|
|
|
|
moveto(Rows - 2, ((Cols - l) >> 1) - 1);
|
|
|
|
if (set)
|
|
|
|
putstr(s);
|
|
|
|
else
|
|
|
|
while (--l >= 0)
|
|
|
|
(void) putchar(' ');
|
|
|
|
} else {
|
|
|
|
moveto(Rows - 2, 0);
|
|
|
|
putpad(CEstr);
|
|
|
|
}
|
|
|
|
}
|