⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 screen.c

📁 早期freebsd实现
💻 C
字号:
/*- * 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 <sgtty.h>#include <sys/ioctl.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifndef sigmask#define sigmask(s) (1 << ((s) - 1))#endif#include "screen.h"#include "tetris.h"/* * XXX - need a <termcap.h> */int	tgetent __P((char *, const char *));int	tgetflag __P((const char *));int	tgetnum __P((const char *));int	tputs __P((const char *, int, int (*)(int)));static cell curscreen[B_SIZE];	/* 1 => standout (or otherwise marked) */static int curscore;static int isset;		/* true => terminal is in game mode */static struct sgttyb oldtt;static void (*tstp)();char	*tgetstr(), *tgoto();/* * Capabilities from TERMCAP. */char	PC, *BC, *UP;		/* tgoto requires globals: ugh! */short	ospeed;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[] = {	"bc", &bcstr,	"ce", &CEstr,	"cl", &CLstr,	"cm", &CMstr,#ifdef unneeded	"cr", &CRstr,#endif	"le", &BC,		/* move cursor left one space */	"pc", &pcstr,	"se", &SEstr,	"so", &SOstr,	"te", &TEstr,	"ti", &TIstr,	"up", &UP,		/* cursor up */	0};/* This is where we will actually stuff the information */static char combuf[1024], tbuf[1024];/* * Routine used by tputs(). */intput(c)	int c;{	return (putchar(c));}/* * 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)#define	moveto(r, c)	putpad(tgoto(CMstr, c, r))/* * Set up from termcap. */voidscr_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[] = {		"bs", &bsflag,		"ms", &MSflag,#ifdef unneeded		"nc", &ncflag,#endif		"xs", &xsflag,		0	}, tcnums[] = {		"co", &COnum,		"li", &LInum,		"sg", &sgnum,		0	};		if ((term = getenv("TERM")) == NULL)		stop("you must set the TERM environment variable");	if (tgetent(tbuf, term) <= 0)		stop("cannot find your termcap");	fill = combuf;	{		register struct tcsinfo *p;		for (p = tcstrings; p->tcaddr; p++)			*p->tcaddr = tgetstr(p->tcname, &fill);	}	{		register struct tcninfo *p;		for (p = tcflags; p->tcaddr; p++)			*p->tcaddr = tgetflag(p->tcname);		for (p = tcnums; p->tcaddr; p++)			*p->tcaddr = tgetnum(p->tcname);	}	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;#define	sigunblock(mask) sigsetmask(sigblock(0) & ~(mask))static voidstopset(sig)	int sig;{	(void) signal(sig, SIG_DFL);	(void) kill(getpid(), sig);	(void) sigunblock(sigmask(sig));	longjmp(scr_onstop, 1);}static voidscr_stop(){	scr_end();	(void) kill(getpid(), SIGTSTP);	(void) sigunblock(sigmask(SIGTSTP));	scr_set();	scr_msg(key_msg, 1);}/* * Set up screen mode. */voidscr_set(){	struct winsize ws;	struct sgttyb newtt;	volatile int omask;	void (*ttou)();	omask = sigblock(sigmask(SIGTSTP) | sigmask(SIGTTOU));	if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN)		(void) signal(SIGTSTP, SIG_IGN);	if ((ttou = signal(SIGTSTP, stopset)) == SIG_IGN)		(void) signal(SIGTSTP, SIG_IGN);	/*	 * 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);	(void) sigsetmask(omask);	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,		    "the screen is too small: must be at least %d x %d",		    MINROWS, MINCOLS);		stop("");	/* stop() supplies \n */	}	if (ioctl(0, TIOCGETP, &oldtt))		stop("ioctl(TIOCGETP) fails");	newtt = oldtt;	newtt.sg_flags = (newtt.sg_flags | CBREAK) & ~(CRMOD | ECHO);	if ((newtt.sg_flags & TBDELAY) == XTABS)		newtt.sg_flags &= ~TBDELAY;	if (ioctl(0, TIOCSETN, &newtt))		stop("ioctl(TIOCSETN) fails");	ospeed = newtt.sg_ospeed;	omask = sigblock(sigmask(SIGTSTP) | sigmask(SIGTTOU));	/*	 * 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);	(void) signal(SIGTTOU, ttou);	isset = 1;	(void) sigsetmask(omask);	scr_clear();}/* * End screen mode. */voidscr_end(){	int omask = sigblock(sigmask(SIGTSTP) | sigmask(SIGTTOU));	/* 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);	(void) ioctl(0, TIOCSETN, &oldtt);	isset = 0;	/* restore signals */	(void) signal(SIGTSTP, tstp);	(void) sigsetmask(omask);}voidstop(why)	char *why;{	if (isset)		scr_end();	(void) fprintf(stderr, "aborting: %s\n", why);	exit(1);}/* * Clear the screen, forgetting the current contents in the process. */voidscr_clear(){	putpad(CLstr);	curscore = -1;	bzero((char *)curscreen, sizeof(curscreen));}#if vax && !__GNUC__typedef int regcell;	/* pcc is bad at `register char', etc */#elsetypedef cell regcell;#endif/* * Update the screen. */voidscr_update(){	register cell *bp, *sp;	register regcell so, cur_so = 0;	register int i, ccol, j;	int omask = sigblock(sigmask(SIGTSTP));	/* 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);		(void) printf("%d", score);		curscore = score;	}	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);	(void) sigsetmask(omask);}/* * Write a message (set!=0), or clear the same message (set==0). * (We need its length in case we have to overwrite with blanks.) */voidscr_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);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -