New DPY sources for 4.2 BSD and System V (part 2 of 2)

David I. Bell dbell at daisy.UUCP
Fri Mar 1 13:51:42 AEST 1985


#---Cut here and place in it's own directory, then feed to Bourne shell---
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
# This archive contains:
#   dpy.c (22206 chars)
#   dpyget.c (1117 chars)
#   dpymove.c (1069 chars)
#   dpyplace.c (1297 chars)
#   dpyread.c (3564 chars)
#   dpywindow.c (1170 chars)
#   gensubs.c (1183 chars)
#   vaxsubs.s (332 chars)
#   ns32ksubs.s (812 chars)
#
echo x - dpy.c
sed -e 's/^X//' > "dpy.c" << '//E*O*F dpy.c//'
Xstatic char *sccsid = "@(#)dpy.c	1.46	2/27/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X
X
X/*
X * Different curses package (by David I. Bell).
X * Modified to run under System V by Alan P.W. Hewett.
X * These dpy module sources are in the public domain, and can be copied
X * or used as desired, with the following restrictions:
X * 1.	All copyright notices (and this notice) must be preserved.
X * 2.	The dpy sources (even if modified) cannot be sold for profit.
X * 3.	If any sources are modified, a sentence must exist by the
X *	copyright notice of each modified source file which says that
X *	the file has been modified.
X */
X
X
X#include <stdio.h>		/* standard I/O */
X#include <signal.h>		/* signals */
X#include "dpy.h"		/* window definitions */
X
X#define	DEL	0177		/* delete character */
X#define	EOL	'\n'		/* end of line character */
X#define	RET	'\r'		/* return character */
X#define	BS	'\b'		/* backspace character */
X#define	TAB	'\t'		/* tab character */
X#define	SPACE	' '		/* space character */
X#define	TRUE	1		/* true value */
X#define	FALSE	0		/* false value */
X#define	INTSIZ	(sizeof(int))	/* size of an integer */
X
Xextern	short	ospeed;		/* output speed for tputs to use */
Xextern	char	PC;		/* pad character for tputs to use */
Xstruct	window	window;		/* the window */
Xstatic	int	dpytputs();	/* called by tputs to type to terminal */
Xstatic	int	dpysputs();	/* called by tputs to save characters */
Xint	dpystop();		/* stop routine */
Xchar	*tgetstr();		/* return termcap string */
Xchar	*malloc();		/* allocate memory */
Xchar	*getenv();		/* return environment variable */
X
X
X/*
X * Initialize the window structure.  Returns nonzero on failure with a
X * message already typed.  The ttytype argument is the terminal type string,
X * or NULL if the TERM environment variable is to be used.  Modes is a
X * string whose characters describe the desired state of the terminal.
X * These are:
X * 	+	turn on mode indicated by next character (default)
X *	-	turn off mode indicated by next character.
X *	c	cbreak mode (return each character as typed, without waiting
X *		for an end of line, and leave signal processing on).
X *	e	echoing of typed-in characters is enabled.
X *	r	raw mode (return each character as typed, no canonical or
X *		signal processing of any kind).
X *	<SP>	spaces are ignored
X * So the terminal modes before dpy runs are normally "e -c -r".
X * A NULL modes pointer defaults the modes to "-e c".
X */
Xdpyinit(ttytype, modes)
X	register char	*ttytype;	/* terminal type, or NULL for default */
X	char	*modes;			/* terminal modes */
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* character pointer */
X	register char	*sp;		/* pointer for spaces */
X	register int	size;		/* size of character array */
X	int on;				/* whether or not mode is on */
X#ifdef BSD
X	struct	ltchars	ltchars;	/* local terminal characters */
X	struct	tchars	tchars;		/* terminal characters */
X#endif BSD
X
X	wp = &window;
X	wp->inited = FALSE;
X	wp->output = FALSE;
X	if (ttytype == NULL) {
X		ttytype = getenv("TERM");
X		if (ttytype == NULL) {
X			fprintf(stderr, "dpyinit: TERM not defined\n");
X			return(1);
X		}
X	}
X	size = tgetent(wp->tdata, ttytype);
X	if (size <= 0) {
X		fprintf(stderr, size ? "dpyinit: cannot open termcap file\n"
X			: "dpyinit: unknown terminal type %s\n", ttytype);
X		return(1);
X	}
X	/*
X	 * Collect current tty modes, and remember editing characters
X	 */
X	wp->c_kill = CKILL;		/* init in case stdin is not a tty */
X	wp->c_erase = CERASE;
X	wp->c_werase = CWERASE;
X	wp->c_lnext = CLNEXT;
X	wp->c_rprnt = CRPRNT;
X	wp->c_eof = CEOF;
X#ifdef	BSD
X	if (ioctl(STDIN, TIOCGETP, &wp->old0ttyblk) == 0) {
X		wp->c_erase = wp->old0ttyblk.sg_erase;
X		wp->c_kill = wp->old0ttyblk.sg_kill;
X	}
X	if (ioctl(STDIN, TIOCGLTC, &ltchars) == 0) {
X		wp->c_werase = ltchars.t_werasc;
X		wp->c_rprnt = ltchars.t_rprntc;
X		wp->c_lnext = ltchars.t_lnextc;
X	}
X	if (ioctl(STDIN, TIOCGETC, &tchars) == 0) {
X		wp->c_eof = tchars.t_eofc;
X	}
X	wp->old1ttyblk.sg_ospeed = 0;
X	ioctl(STDOUT, TIOCGETP, &wp->old1ttyblk);
X	ospeed = wp->old1ttyblk.sg_ospeed;	/* save speed for tputs */
X#endif	BSD
X#ifdef	USG
X	if (ioctl(STDIN, TCGETA, &wp->old0ttyblk) == 0) {
X		wp->c_erase = wp->old0ttyblk.c_cc[VERASE];
X		wp->c_kill = wp->old0ttyblk.c_cc[VKILL];
X		wp->c_eof = wp->old0ttyblk.c_cc[VEOF];
X	}
X	ioctl(STDOUT, TCGETA, &wp->old1ttyblk);
X#endif	USG
X	/*
X	 * Collect terminal capability strings
X	 */
X	wp->nrows = tgetnum("li");
X	wp->ncols = tgetnum("co");
X	wp->tc_am = tgetflag("am");
X	wp->tbuf[0] = '\0';
X	wp->tptr = wp->tbuf;
X	(void) tgetstr("pc", &wp->tptr);
X	PC = wp->tbuf[0];
X	wp->tptr = wp->tbuf;
X	wp->tc_ho = tgetstr("ho", &wp->tptr);
X	wp->tc_hocc = wp->tptr - wp->tbuf - 1;
X	wp->tc_ce = tgetstr("ce", &wp->tptr);
X	wp->tc_cd = tgetstr("cd", &wp->tptr);
X	wp->tc_cm = tgetstr("cm", &wp->tptr);
X	if ((wp->nrows <= 0) || (wp->ncols <= 0) || (wp->tc_ce == NULL)
X		|| (wp->tc_cd == NULL) || (wp->tc_cm == NULL)) {
X			fprintf(stderr, "dpyinit: missing termcap entry\n");
X			return(1);
X	}
X	sp = wp->tptr;			/* apply padding to clear screen */
X	tputs(wp->tc_cd, wp->nrows, dpysputs);
X	wp->tc_cd = sp;
X	wp->tc_cdcc = wp->tptr - sp;
X	sp = wp->tptr;			/* and to clear line string */
X	tputs(wp->tc_ce, 1, dpysputs);
X	wp->tc_ce = sp;
X	wp->tc_cecc = wp->tptr - sp;
X	if (wp->tc_ho == NULL) {	/* make home up string if not defined */
X		sp = wp->tptr;
X		tputs(tgoto(wp->tc_cm, 0, 0), 1, dpysputs);
X		wp->tc_ho = sp;
X		wp->tc_hocc = wp->tptr - sp;
X	}
X	wp->delta = (wp->ncols + INTSIZ) &~ (INTSIZ-1);	/* round up */
X	size = wp->nrows * wp->delta;
X	cp = malloc(2 * (size + INTSIZ));
X	if (cp == NULL) {
X		fprintf(stderr, "dpyinit: failed to allocate memory\n");
X		return(1);
X	}
X	wp->begdata = cp;
X	wp->enddata = cp + size;
X	wp->begwin = cp;
X	wp->endwin = cp + size - wp->delta;
X	wp->begrow = cp;
X	wp->endrow = cp + wp->ncols;
X	wp->cp = cp;
X	wp->screen = cp + size + INTSIZ;
X	for (sp = cp + (2 * (size + INTSIZ)) - 1; sp >= cp; sp--) *sp = SPACE;
X	*((int *)(cp + size)) = 0;	/* terminate end of screens */
X	*((int *)(wp->screen + size)) = 0;
X	wp->currow = 0;
X	wp->curcol = 0;
X	wp->noctrl = 0;
X	wp->nocrlf = 0;
X	wp->nomove = 0;
X	wp->scroll = 0;
X	wp->full = 0;
X	wp->tabsize = 8;
X	wp->begchange = wp->enddata;
X	wp->endchange = wp->begdata;
X	/*
X	 * Copy old tty modes to new ones, and modify them as specified
X	 */
X	wp->new0ttyblk = wp->old0ttyblk;
X	wp->new1ttyblk = wp->old1ttyblk;
X	if (modes == (char*)NULL) modes = "-e c";
X	on = TRUE;
X	for (cp = modes; *cp ; cp++) {		/* scan mode string */
X		switch (*cp) {
X		case ' ':			/* spaces (ignored) */
X			continue;
X		case '+':			/* turn on next mode */
X			on = TRUE;
X			continue;
X		case '-':			/* turn off next mode */
X			on = FALSE;
X			continue;
X#ifdef	BSD
X		case 'e':			/* enable echoing */
X			if (on) {
X				wp->new0ttyblk.sg_flags |= ECHO;
X				wp->new1ttyblk.sg_flags |= ECHO;
X			} else {
X				wp->new0ttyblk.sg_flags &= ~ECHO;
X				wp->new1ttyblk.sg_flags &= ~ECHO;
X			}
X			break;
X
X		case 'c':			/* enable character mode */
X			if (on) {
X				wp->new0ttyblk.sg_flags |= CBREAK;
X				wp->new1ttyblk.sg_flags |= CBREAK;
X			} else {
X				wp->new0ttyblk.sg_flags &= ~CBREAK;
X				wp->new1ttyblk.sg_flags &= ~CBREAK;
X			}
X			break;
X
X		case 'r':			/* enable raw mode */
X			if (on) {
X				wp->new0ttyblk.sg_flags |= RAW;
X				wp->new1ttyblk.sg_flags |= RAW;
X			} else {
X				wp->new0ttyblk.sg_flags &= ~RAW;
X				wp->new1ttyblk.sg_flags &= ~RAW;
X			}
X			break;
X#endif	BSD
X#ifdef	USG
X		case 'e':			/* enable echoing */
X			if (on) {
X				wp->new0ttyblk.c_lflag |= ECHO | ECHOE | ECHOK ;
X				wp->new1ttyblk.c_lflag |= ECHO | ECHOE | ECHOK ;
X			} else {
X				wp->new0ttyblk.c_lflag &= ~(ECHO|ECHOE|ECHOK) ;
X				wp->new1ttyblk.c_lflag &= ~(ECHO|ECHOE|ECHOK) ;
X			}
X			break ;
X
X		case 'c':			/* enable character mode */
X			if (on) {
X				wp->new0ttyblk.c_iflag |= ISTRIP ;
X				wp->new0ttyblk.c_lflag &= ~ICANON ;
X				wp->new0ttyblk.c_cc[VMIN] = 1 ;
X				wp->new0ttyblk.c_cc[VTIME] = 0 ;
X				wp->new1ttyblk.c_iflag |= ISTRIP ;
X				wp->new1ttyblk.c_lflag &= ~ICANON ;
X				wp->new1ttyblk.c_cc[VMIN] = 1 ;
X				wp->new1ttyblk.c_cc[VTIME] = 0 ;
X			} else {
X	    			wp->new0ttyblk.c_iflag |= (ICRNL|IUCLC) ;
X	    			wp->new0ttyblk.c_lflag |= ICANON ;
X	    			wp->new0ttyblk.c_cc[VEOF] =
X					wp->old0ttyblk.c_cc[VEOF] ;
X	    			wp->new0ttyblk.c_cc[VEOL] =
X					wp->old0ttyblk.c_cc[VEOL] ;
X	    			wp->new1ttyblk.c_iflag |= (ICRNL|IUCLC) ;
X	    			wp->new1ttyblk.c_lflag |= ICANON ;
X	    			wp->new1ttyblk.c_cc[VEOF] =
X					wp->old1ttyblk.c_cc[VEOF] ;
X	    			wp->new1ttyblk.c_cc[VEOL] =
X					wp->old1ttyblk.c_cc[VEOL] ;
X			}
X			break ;
X
X		case 'r':			/* enable raw mode */
X			if (on) {
X	    			wp->new0ttyblk.c_iflag &=
X					~(BRKINT|IGNPAR|ISTRIP|IXON|IXANY) ;
X	    			wp->new0ttyblk.c_oflag &= ~OPOST ;
X	    			wp->new0ttyblk.c_cflag =
X					(wp->new0ttyblk.c_cflag|CS8) & ~PARENB ;
X	    			wp->new0ttyblk.c_lflag &= ~ICANON ;
X	    			wp->new0ttyblk.c_cc[VMIN] = 1 ;
X	    			wp->new0ttyblk.c_cc[VTIME] = 0 ;
X	    			wp->new1ttyblk.c_iflag &=
X					~(BRKINT|IGNPAR|ISTRIP|IXON|IXANY) ;
X	    			wp->new1ttyblk.c_oflag &= ~OPOST ;
X	    			wp->new1ttyblk.c_cflag =
X					(wp->new1ttyblk.c_cflag|CS8) & ~PARENB ;
X	    			wp->new1ttyblk.c_lflag &= ~ICANON ;
X	    			wp->new1ttyblk.c_cc[VMIN] = 1 ;
X	    			wp->new1ttyblk.c_cc[VTIME] = 0 ;
X			} else {
X	    			wp->new0ttyblk.c_iflag |=
X					(BRKINT|IGNPAR|ISTRIP|IXON
X					|IXANY|ICRNL|IUCLC) ;
X	    			wp->new0ttyblk.c_oflag |= OPOST ;
X	    			wp->new0ttyblk.c_cflag =
X					(wp->new0ttyblk.c_cflag & ~CSIZE) |
X					CS7 | PARENB ;
X	    			wp->new0ttyblk.c_lflag |= ICANON | ISIG ;
X	    			wp->new0ttyblk.c_cc[VEOF] = CEOF ;
X	    			wp->new0ttyblk.c_cc[VEOL] = 0 ;
X	    			wp->new0ttyblk.c_cc[VEOL2] = 0 ;
X	    			wp->new1ttyblk.c_iflag |=
X					(BRKINT|IGNPAR|ISTRIP|IXON|
X					IXANY|ICRNL|IUCLC) ;
X	    			wp->new1ttyblk.c_oflag |= OPOST ;
X	    			wp->new1ttyblk.c_cflag =
X					(wp->new1ttyblk.c_cflag & ~CSIZE) |
X					CS7 | PARENB ;
X	    			wp->new1ttyblk.c_lflag |= ICANON | ISIG ;
X	    			wp->new1ttyblk.c_cc[VEOF] = CEOF ;
X	    			wp->new1ttyblk.c_cc[VEOL] = 0 ;
X	    			wp->new1ttyblk.c_cc[VEOL2] = 0 ;
X			}
X			break;
X#endif	USG
X		default:
X			fprintf(stderr, "dpyinit: illegal flag: %c%c\n",
X				(on ? '+' : '-'), *cp);
X			return(1);
X		}
X		on = TRUE;		/* reset mode */
X	}
X	/*
X	 * Set the new modes for real
X	 */
X#ifdef	BSD
X	wp->new1ttyblk.sg_flags &= ~XTABS;
X	signal(SIGTSTP, dpystop);
X	ioctl(STDIN, TIOCSETP, &wp->new0ttyblk);
X	ioctl(STDOUT, TIOCSETP, &wp->new1ttyblk);
X#endif	BSD
X#ifdef	USG
X	wp->new1ttyblk.c_oflag &= ~TAB3 ;
X	ioctl(STDIN,TCSETAW,&wp->new0ttyblk) ;
X	ioctl(STDOUT,TCSETAW,&wp->new1ttyblk) ;
X#endif	USG	
X	wp->inited = TRUE;
X	return(0);
X}
X
X
X/*
X * Terminate the window, home down to the bottom of the screen, and reset
X * the terminal modes to their original state.
X */
Xdpyclose()
X{
X	register struct	window	*wp;	/* window pointer */
X
X	wp = &window;
X	if (wp->inited) {
X		wp->inited = FALSE;
X		if (wp->output) {
X			domove(wp->nrows - 1, 0, (char *)NULL);
X			fwrite(wp->tc_ce, 1, wp->tc_cecc, stdout);
X			fflush(stdout);
X		}
X		free(wp->begdata);
X#ifdef	BSD
X		ioctl(STDIN, TIOCSETP, &wp->old0ttyblk);
X		ioctl(STDOUT, TIOCSETP, &wp->old1ttyblk);
X#endif	BSD
X#ifdef	USG
X		ioctl(STDIN, TCSETAW, &wp->old0ttyblk);
X		ioctl(STDOUT, TCSETAW, &wp->old1ttyblk);
X#endif	USG
X	}
X	return(0);
X}
X
X
X/*
X * Put a given number of characters to the window at the current write location.
X * Certain control characters have effects, others print as ^X or are ignored.
X * Automatic wrapping to the next line is possible, and scrolling when the last
X * line is full. Returns nonzero if the window cannot hold the whole buffer.
X */
Xdpywrite(buf, count)
X	register char	*buf;		/* buffer address */
X	int	count;			/* number of characters */
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*endbuf;	/* end of buffer to write */
X	register char	*cp;		/* current character pointer */
X	register int	ch;		/* character to store */
X
X	wp = &window;
X	if (wp->full) return(1);
X	cp = wp->cp;
X	if (cp < wp->begchange) wp->begchange = cp;
X	for (endbuf = buf + count; buf < endbuf; buf++) {
X		ch = *buf;
X		if (ch < ' ') {			/* control character */
X			if (ch == EOL) {	/* new line */
X				clear(cp, wp->endrow);
X				if (cp >= wp->endwin) {	/* window full */
X					wp->endchange = wp->endrow;
X					if (wp->scroll == 0) {
X						wp->full = 1;
X						wp->cp = wp->begrow;
X						return(1);
X					}
X					wp->cp = cp;
X					dpyscroll();
X					cp = wp->begrow;
X					continue;
X				}
X				wp->begrow += wp->delta;
X				wp->endrow += wp->delta;
X				cp = wp->begrow;
X				continue;
X			}
X			if (ch == TAB) {	/* tab */
X				wp->cp = cp;
X				do {
X					if (dpywrite(" ", 1)) return(1);
X				} while ((wp->cp - wp->begrow) % wp->tabsize);
X				cp = wp->cp;
X				continue;
X			}
X			if (ch == BS) {		/* backspace */
X				if (cp > wp->begrow) cp--;
X				continue;
X			}
X			if (ch == RET) {	/* return character */
X				cp = wp->begrow;
X				continue;
X			}
X			/*
X			 * Obscure control character, show as ^X
X			 */
X			if (wp->noctrl) continue;
X			wp->cp = cp;
X			if (dpywrite("^", 1) || dpychar(ch + '@')) return(1);
X			cp = wp->cp;
X			continue;
X		}
X		if (ch == DEL) {		/* delete character */
X			if (wp->noctrl) continue;
X			wp->cp = cp;
X			if (dpywrite("^?", 2)) return(1);
X			cp = wp->cp;
X			continue;
X		}
X		/*
X		 * Normal printing character
X		 */
X		if (cp >= wp->endrow) {		/* end of row, see if do crlf */
X			wp->cp = cp;
X			if (cp > wp->endchange) wp->endchange = cp;
X			if (wp->nocrlf) return(1);
X			if (cp >= wp->endwin) {
X				if (wp->scroll == 0) return(1);
X				dpyscroll();
X				cp = wp->begrow;
X				*cp++ = ch;
X				continue;
X			}
X			wp->begrow += wp->delta;
X			wp->endrow += wp->delta;
X			cp = wp->begrow;
X		}
X		*cp++ = ch;
X	}
X	wp->cp = cp;
X	if (cp > wp->endchange) wp->endchange = cp;
X	return(0);
X}
X
X
X/*
X * Put a single character to the window.
X * Returns nonzero if full.
X */
Xdpychar(ch)
X	char	ch;
X{
X	return(dpywrite(&ch, 1));
X}
X
X
X/*
X * Put a null-terminated string to the window.
X * Returns nonzero if full.
X */
Xdpystr(str)
X	char	*str;
X{
X	return(dpywrite(str, strlen(str)));
X}
X
X
X
X/*
X * Print a formatted string to the window.  Returns nonzero if full.
X * This routine is a ripped off version of sprintf.  This routine is
X * machine-dependent!!
X */
X#ifdef	BSD
Xdpyprintf(fmt, args)
X	char	*fmt;			/* format string */
X{
X	FILE	_strbuf;		/* file header */
X	char	buf[5000];		/* data storage */
X
X	_strbuf._flag = _IOWRT+_IOSTRG;
X	_strbuf._ptr = buf;
X	_strbuf._cnt = 32767;
X	_doprnt(fmt, &args, &_strbuf);
X	return(dpywrite(buf, _strbuf._ptr - buf));
X}
X#endif	BSD
X#ifdef	USG
X
X#include <varargs.h>
X
Xdpyprintf(format, va_alist)
Xchar *format;
Xva_dcl
X{
X	register int count;
X	FILE siop;
X	va_list ap;
X	unsigned char	buf[5000];		/* data storage */
X
X	siop._cnt = sizeof(buf) ;
X	siop._base = siop._ptr = &buf[0] ;
X	siop._flag = _IOWRT;
X	siop._file = _NFILE;
X	va_start(ap);
X	count = _doprnt(format, ap, &siop);
X	va_end(ap);
X	*siop._ptr = '\0'; /* plant terminating null character */
X	return(dpywrite(buf, siop._ptr - buf));
X}
X#endif	USG
X
X
X/* Clear to the end of the current row without changing the write location */
Xdpyclrline()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* current character */
X	register char	*endcp;		/* ending character */
X
X	wp = &window;
X	if (wp->full) return;
X	cp = wp->cp;
X	endcp = wp->endrow;
X	if (cp < wp->begchange) wp->begchange = cp;
X	if (endcp > wp->endchange) wp->endchange = cp;
X	clear(cp, endcp);
X}
X
X
X/* Clear to the end of the window without changing the write location */
Xdpyclrwindow()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*begcp;		/* beginning character */
X	register char	*cp;		/* current character */
X	register char	*endcp;		/* ending character */
X
X	wp = &window;
X	if (wp->full) return;
X	begcp = wp->begrow;
X	endcp = wp->endrow;
X	cp = wp->cp;
X	if (cp < wp->begchange) wp->begchange = cp;
X	while (1) {
X		clear(cp, endcp);
X		if (begcp >= wp->endwin) break;
X		begcp += wp->delta;
X		endcp += wp->delta;
X		cp = begcp;
X	}
X	if (endcp > wp->endchange) wp->endchange = endcp;
X}
X
X
X/* Set the current write position to the top left corner of the window */
Xdpyhome()
X{
X	register struct	window	*wp;	/* window pointer */
X
X	wp = &window;
X	wp->endrow += wp->begwin - wp->begrow;
X	wp->begrow = wp->begwin;
X	wp->cp = wp->begrow;
X	wp->full = 0;
X}
X
X
X/* Scroll the current window upwards a line to make room for more data. */
Xdpyscroll()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*currow;	/* beginning of current row */
X	register char	*nextrow;	/* beginning of next row */
X	register int	cols;		/* columns in window */
X
X	wp = &window;
X	cols = wp->endrow - wp->begrow;
X	currow = wp->begwin;
X	nextrow = currow + wp->delta;
X	while (currow < wp->endwin) {		/* move each line up */
X		bcopy(nextrow, currow, cols);
X		currow += wp->delta;
X		nextrow += wp->delta;
X	}
X	clear(currow, currow + cols);		/* clear last line */
X	wp->begchange = wp->begwin;
X	wp->endchange = wp->endwin + cols;
X}
X
X
X/*
X * Return the row number being written to, or -1 if out of the window.
X * The row number is relative to the beginning of the window.
X */
Xdpygetrow()
X{
X	register struct	window	*wp;	/* window pointer */
X
X	wp = &window;
X	if (wp->full) return(-1);
X	return((wp->cp - wp->begwin) / wp->delta);
X}
X
X
X/*
X * Return the column number being written to, or -1 if out of the window.
X * The column number is relative to the current window.
X */
Xdpygetcol()
X{
X	register struct	window	*wp;	/* window pointer */
X
X	wp = &window;
X	if (wp->full) return(-1);
X	if (wp->cp < wp->endrow) return(wp->cp - wp->begrow);
X	if (wp->nocrlf) return(-1);
X	return(0);
X}
X
X
X/* Make the screen match the data as previously written by the user */
Xdpyupdate()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*scp;		/* screen character pointer */
X	register char	*cp;		/* current character */
X	register char	*spcp;		/* cp where spaces remain in row */
X	register char	*endrow;	/* end of row */
X	register char	*begrow;	/* beginning of row */
X	register int	row;		/* current row number */
X	int	diff;
X
X	wp = &window;
X	if (wp->output == 0) {		/* first output, clear screen */
X		wp->output = TRUE;
X		fwrite(wp->tc_ho, 1, wp->tc_hocc, stdout);
X		fwrite(wp->tc_cd, 1, wp->tc_cdcc, stdout);
X	}
X	cp = wp->begchange;
X	scp = wp->screen + (cp - wp->begdata);
X	endrow = 0;
X	while (cp < wp->endchange) {	/* look for a difference */
X		diff = strdif(cp, scp, wp->endchange - cp);
X		cp += diff;
X		scp += diff;
X		if (cp >= wp->endchange) break;
X		if (cp >= endrow) {
X			row = (cp - wp->begdata) / wp->delta;
X			begrow = wp->begdata + (row * wp->delta);
X			endrow = begrow + wp->ncols;
X			spcp = endrow - 1;
X			while ((spcp >= begrow) && (*spcp == SPACE))
X				spcp--;
X			spcp++;
X		}
X		domove(row, cp - begrow, begrow);
X		if (cp >= spcp) {		/* clear rest of line */
X			fwrite(wp->tc_ce, 1, wp->tc_cecc, stdout);
X			while (cp < endrow) {
X				*scp++ = SPACE;
X				cp++;
X			}
X			continue;
X		}
X		putchar(*cp);
X		*scp++ = *cp++;
X		if (++wp->curcol >= wp->ncols) {	/* fixup last column */
X			wp->curcol--;
X			if (wp->tc_am) {
X				wp->currow++;
X				wp->curcol = 0;
X			}
X		}
X	}
X	wp->begchange = wp->enddata;
X	wp->endchange = wp->begdata;
X	if (wp->nomove == 0) dpycursor();
X	fflush(stdout);
X}
X
X
X/*
X * Set the terminal cursor at the current write location.
X * If the window is full, the cursor is placed at the front of the
X * last line in the window.  If lines are not being wrapped and the
X * line is full, the cursor is placed at the end of the line.
X * Otherwise, the cursor is placed at the location being written to next.
X */
Xstatic
Xdpycursor()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* current write location */
X	register char	*begrow;	/* beginning of current row */
X	register int	row;		/* row number */
X
X	wp = &window;
X	cp = wp->cp;
X	if (wp->full)
X		cp = wp->endwin;
X	else if (cp >= wp->endrow) {
X		if (wp->nocrlf || (wp->begrow >= wp->endwin))
X			cp = wp->endrow - 1;
X		else
X			cp = wp->begrow + wp->delta;
X	}
X	row = (cp - wp->begdata) / wp->delta;
X	begrow = wp->begdata + (row * wp->delta);
X	domove(row, cp - begrow, begrow);
X}
X
X
X/*
X * Subroutine to move to the given location on the screen.  The third argument
X * is a pointer to beginning of the desired row in case we find it is faster
X * to type the intervening characters.  If NULL, we must use addressing.
X */
Xstatic
Xdomove(row, col, cp)
X	register int	row;		/* desired row */
X	register int	col;		/* desired column */
X	register char	*cp;		/* data on desired row */
X{
X	register struct	window	*wp;	/* window structure */
X
X	wp = &window;
X	if (cp && (row == wp->currow) && (col >= wp->curcol)
X		&& (col < wp->curcol + 6)) {		/* a few ahead */
X			cp += wp->curcol;
X			while (wp->curcol < col) {
X				putchar(*cp);
X				cp++;
X				wp->curcol++;
X			}
X			return;
X	}
X	if ((col == 0) && (row == wp->currow + 1)) {	/* next row */
X		putchar('\n');
X		wp->currow++;
X		wp->curcol = 0;
X		return;
X	}
X	tputs(tgoto(wp->tc_cm, col, row), 1, dpytputs);	/* arbitrary */
X	wp->currow = row;
X	wp->curcol = col;
X}
X
X
X/* Local routine called by tputs to print a character */
Xstatic
Xdpytputs(ch)
X	char	ch;
X{
X	putchar(ch);
X}
X
X
X/* Local routine called by tputs to save a character */
Xstatic
Xdpysputs(ch)
X	char	ch;
X{
X	*window.tptr++ = ch;
X}
X
X
X/* Redraw the screen to fix glitches */
Xdpyredraw()
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* current character */
X	register char	*endcp;		/* ending character */
X
X	wp = &window;
X	cp = wp->screen;
X	endcp = cp + (wp->nrows * wp->delta);
X	clear(cp, endcp);
X	wp->currow = 0;
X	wp->curcol = 0;
X	wp->begchange = wp->begdata;
X	wp->endchange = wp->enddata;
X	fwrite(wp->tc_ho, 1, wp->tc_hocc, stdout);
X	fwrite(wp->tc_cd, 1, wp->tc_cdcc, stdout);
X	dpyupdate();
X}
X
X
X/*
X * Routine called on a terminal stop signal.  Restore the original terminal
X * state, home down to the bottom, and really stop.  If continued, restore
X * the new terminal state and redraw the screen.
X */
Xdpystop()
X{
X#ifdef	BSD
X	register struct	window	*wp;	/* window pointer */
X
X	wp = &window;
X	if (wp->output) {
X		domove(wp->nrows - 1, 0, (char *)NULL);
X		fflush(stdout);
X	}
X	ioctl(STDIN, TIOCSETP, &wp->old0ttyblk);
X	ioctl(STDOUT, TIOCSETP, &wp->old1ttyblk);
X	kill(getpid(), SIGSTOP);	/* really stop */
X	ioctl(STDIN, TIOCSETP, &wp->new0ttyblk);
X	ioctl(STDOUT, TIOCSETP, &wp->new1ttyblk);
X	if (wp->output) dpyredraw();
X#endif	BSD
X}
//E*O*F dpy.c//
echo x - dpyget.c
sed -e 's/^X//' > "dpyget.c" << '//E*O*F dpyget.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)dpyget.c	1.1	1/28/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X#include "dpy.h"
X
X/* Return the character which is at the specified location in the current
X * window.  The character returned is the one in our internal screen image,
X * not what is actually on the screen (these will be identical if dpyupdate
X * was just called).  Returns negative if the coordinates are illegal.
X */
Xdpyget(row, col)
X	register int	row;		/* row to get character from */
X	register int	col;		/* column to get character from */
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* character pointer */
X	register int	winrows;	/* number of rows in window */
X	register int	wincols;	/* number of columns in window */
X
X	wp = &window;
X	winrows = ((wp->endwin - wp->begwin) / wp->delta) + 1;
X	wincols = wp->endrow - wp->begrow;
X	if (row < 0) row += winrows;
X	if (col < 0) col += wincols;
X	if (((unsigned)row >= winrows) || ((unsigned)col >= wincols)) {
X		return(-1);		/* out of window */
X	}
X	cp = wp->begwin + (row * wp->delta) + col;
X	return(*cp & 0xff);
X}
//E*O*F dpyget.c//
echo x - dpymove.c
sed -e 's/^X//' > "dpymove.c" << '//E*O*F dpymove.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)dpymove.c	1.3	1/17/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X#include "dpy.h"
X
X/* Set the current write location to the given row and column.
X * The position given is relative to the current window.
X * Negative numbers indicate backwards from last row or column.
X * Returns nonzero if arguments are out of bounds.
X */
Xdpymove(row, col)
X	register int	row;		/* desired row number */
X	register int	col;		/* desired column number */
X{
X	register struct	window	*wp;	/* window pointer */
X	register int	winrows;	/* number of rows in window */
X	register int	wincols;	/* number of columns in window */
X
X	wp = &window;
X	winrows = ((wp->endwin - wp->begwin) / wp->delta) + 1;
X	wincols = wp->endrow - wp->begrow;
X	if (row < 0) row += winrows;
X	if (col < 0) col += wincols;
X	if (((unsigned)row >= winrows) || ((unsigned)col >= wincols)) {
X		return(1);		/* out of window */
X	}
X	wp->begrow = wp->begwin + (row * wp->delta);
X	wp->endrow = wp->begrow + wincols;
X	wp->cp = wp->begrow + col;
X	wp->full = 0;
X	return(0);
X}
//E*O*F dpymove.c//
echo x - dpyplace.c
sed -e 's/^X//' > "dpyplace.c" << '//E*O*F dpyplace.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)dpyplace.c	1.5	1/28/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X#include "dpy.h"
X
X/* Place a single character to the window at a particular location.
X * The change will not be seen until a call to dpyupdate.
X * The current write location is unaffected.
X * Returns nonzero if coordinates are illegal.
X * The coordinates are relative to the current window.
X */
Xdpyplace(row, col, ch)
X	register int	row;		/* row to place character at */
X	register int	col;		/* column to place character at */
X	char	ch;			/* character to be placed */
X{
X	register struct	window	*wp;	/* window pointer */
X	register char	*cp;		/* character pointer */
X	register int	winrows;	/* number of rows in window */
X	register int	wincols;	/* number of columns in window */
X
X	wp = &window;
X	winrows = ((wp->endwin - wp->begwin) / wp->delta) + 1;
X	wincols = wp->endrow - wp->begrow;
X	if (row < 0) row += winrows;
X	if (col < 0) col += wincols;
X	if (((unsigned)row >= winrows) || ((unsigned)col >= wincols)) {
X		return(1);		/* out of window */
X	}
X	cp = wp->begwin + (row * wp->delta) + col;
X	if (*cp != ch) {		/* do only if char needs changing */
X		if (cp < wp->begchange) wp->begchange = cp;
X		*cp++ = ch;
X		if (cp > wp->endchange) wp->endchange = cp;
X	}
X	return(0);
X}
//E*O*F dpyplace.c//
echo x - dpyread.c
sed -e 's/^X//' > "dpyread.c" << '//E*O*F dpyread.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)dpyread.c	1.13	2/16/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X#include "dpy.h"		/* window definitions */
X
Xstatic int readline();		/* default read routine */
X
X/* Read some input while possibly showing it in the current window.
X * If the prompt string is NULL, then editing is performed without
X * any windowing activity (useful when reading commands from scripts).
X * Otherwise, the prompt is shown in the window along with any input.
X * The given routine is called for each character, with an argument
X * which is the previous character (or -1 on the first call).
X * The routine returns the next input character, or -1 to stop reading.
X * A null routine defaults to one which reads until an end of line.
X * Scrolling of the window is automatically performed when necessary.
X * Editing of the input is handled.  If the buffer fills up, the user
X * is warned with beeps and further input is ignored.
X * Returns number of bytes of data read.
X */
Xdpyread(prompt, routine, buf, count)
X	register char	*prompt;	/* prompt string (if any) */
X	int	(*routine)();		/* routine to call to get character */
X	register char	*buf;		/* address of the storage buffer */
X	int	count;			/* maximum number of bytes allowed */
X{
X	register struct	window	*wp;	/* window pointer */
X	register int	ch;		/* character which was read */
X	register char	*bp;		/* current buffer pointer location */
X	char	*endbp;			/* end of buffer */
X	char	redraw;			/* need to redisplay input */
X	char	oldscroll;		/* old scrolling flag */
X	int	promptlen;		/* length of prompt string */
X
X	wp = &window;
X	promptlen = 0;
X	if (prompt) promptlen = strlen(prompt);
X	if ((int)routine == 0) routine = readline;
X	bp = buf;
X	endbp = bp + count - 1;
X	redraw = 1;
X	ch = -1;
X	oldscroll = wp->scroll;
X	wp->scroll = 1;
X	while (1) {
X		if (prompt && redraw) {		/* recompute window data */
X			redraw = 0;
X			dpyhome();
X			dpywrite(prompt, promptlen);
X			dpywrite(buf, bp - buf);
X			dpyclrwindow();
X		}
X		if (prompt) dpyupdate();
X		ch = routine(ch);
X		if (ch < 0) {				/* end of file */
X			wp->scroll = oldscroll;
X			return(bp - buf);
X		}
X		if (ch == wp->c_lnext) {		/* literal input */
X			ch = routine(ch);
X			if (ch < 0) {
X				wp->scroll = oldscroll;
X				return(bp - buf);
X			}
X			if (bp >= endbp) {		/* buffer is full */
X				write(STDERR, "\07", 1);
X				continue;
X			}
X			*bp = ch;
X			if (prompt) dpywrite(bp, 1);
X			bp++;
X			continue;
X		}
X		if (ch == wp->c_eof) {			/* end of file */
X			wp->scroll = oldscroll;
X			return(bp - buf);
X		}
X		if (ch == wp->c_erase) {		/* character erase */
X			if (bp <= buf) continue;
X			bp--;
X			redraw = 1;
X			continue;
X		}
X		if (ch == wp->c_werase) {		/* word erase */
X			if (bp <= buf) continue;
X			while ((bp > buf) && ((bp[-1] == '\n')
X				|| (bp[-1] == ' ') || (bp[-1] == '\t'))) bp--;
X			while ((bp > buf) && (bp[-1] != '\n')
X				&& (bp[-1] != ' ') && (bp[-1] != '\t')) bp--;
X			redraw = 1;
X			continue;
X		}
X		if (ch == wp->c_kill) {			/* line erase */
X			if (bp <= buf) continue;
X			if (bp[-1] == '\n') bp--;
X			while ((bp > buf) && (bp[-1] != '\n')) bp--;
X			redraw = 1;
X			continue;
X		}
X		if (ch == wp->c_rprnt) {		/* retype line */
X			if (prompt) dpyredraw();
X			continue;
X		}
X		if (bp >= endbp) {			/* buffer is full */
X			write(STDERR, "\07", 1);
X			continue;
X		}
X		*bp = ch;				/* normal character */
X		if (prompt) dpywrite(bp, 1);
X		bp++;
X	}
X}
X
X
X/* Local routine to read until end of line character is reached */
Xstatic
Xreadline(ch)
X{
X	if ((ch == '\n') || (read(STDIN, &ch, 1) < 1)) return(-1);
X	return(ch & 0xff);
X}
//E*O*F dpyread.c//
echo x - dpywindow.c
sed -e 's/^X//' > "dpywindow.c" << '//E*O*F dpywindow.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)dpywindow.c	1.3	1/17/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X#include "dpy.h"
X
X/* Set the row and column boundaries of the current window.
X * Negative numbers indicate backwards from last row or column.
X * The write location is set to the top left of the window.
X * Returns nonzero if arguments are out of bounds.
X */
Xdpywindow(minrow, maxrow, mincol, maxcol)
X	register int	minrow, maxrow;		/* range of rows */
X	register int	mincol, maxcol;		/* range of columns */
X{
X	register struct	window	*wp;		/* window pointer */
X
X	wp = &window;
X	if (minrow < 0) minrow += wp->nrows;
X	if (maxrow < 0) maxrow += wp->nrows;
X	if (mincol < 0) mincol += wp->ncols;
X	if (maxcol < 0) maxcol += wp->ncols;
X	if (((unsigned) minrow > maxrow)
X		|| ((unsigned) maxrow >= wp->nrows)
X		|| ((unsigned) mincol > maxcol)
X		|| (maxcol >= wp->ncols)) {
X			return(1);		/* illegal */
X	}
X	wp->begwin = wp->begdata + (minrow * wp->delta) + mincol;
X	wp->endwin = wp->begwin + ((maxrow - minrow) * wp->delta);
X	wp->begrow = wp->begwin;
X	wp->endrow = wp->begrow + (maxcol - mincol + 1);
X	wp->cp = wp->begrow;
X	wp->full = 0;
X	return(0);
X}
//E*O*F dpywindow.c//
echo x - gensubs.c
sed -e 's/^X//' > "gensubs.c" << '//E*O*F gensubs.c//'
X#ifdef SCCS
Xstatic char *sccsid = "@(#)gensubs.c	1.3	1/17/85";
Xstatic char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
X#endif
X
X/*
X * Generic subroutines usable on any machine.  These subroutines should
X * be replaced by assembly-level routines if possible, to make dpy run
X * as fast as possible.
X */
X
X
X/*
X * Compare two strings of a given length, and return the number of leading
X * bytes which are identical, or the length if the strings are identical.
X * Nulls are not treated specially.  Examples:
X *	strdif("hi mom", "hi pop", 6) returns 3.
X *	strdif("aaaa1", "aaaa2", 2) returns 2.
X */
Xstrdif(s1, s2, len)
X	register char	*s1;		/* first string */
X	register char	*s2;		/* second string */
X{
X	register char	*end;		/* ending character */
X	char	*beg;			/* beginning character */
X
X	beg = s1;
X	end = s1 + len;
X	while ((s1 < end) && (*s1 == *s2)) {
X		s1++;
X		s2++;
X	}
X	return(s1 - beg);
X}
X
X
X
X/*
X * Clear a number of bytes to spaces, from the original character location
X * up to but not including the ending location.
X */
Xclear(beg, end)
X	register char	*beg;		/* beginning of string to clear */
X	register char	*end;		/* end of string to clear */
X{
X	while (beg < end) *beg++ = ' ';
X}
//E*O*F gensubs.c//
echo x - vaxsubs.s
sed -e 's/^X//' > "vaxsubs.s" << '//E*O*F vaxsubs.s//'
X# @(#)vaxsubs.s	1.5	1/17/85
X# @(#)Copyright (C) 1985 by D Bell
X
X
X	.text
X	.globl	_strdif
X	.globl	_clear
X
X_strdif:
X	.word	0x0
X	cmpc3	12(ap),*4(ap),*8(ap)	#compare the strings
X	subl3	4(ap),r1,r0		#return difference
X	ret
X
X_clear:
X	.word	0x0
X	subl3	4(ap),8(ap),r0		#number of bytes to fill
X	movc5	$0,0,$32,r0,*4(ap)	#fill the bytes
X	ret
//E*O*F vaxsubs.s//
echo x - ns32ksubs.s
sed -e 's/^X//' > "ns32ksubs.s" << '//E*O*F ns32ksubs.s//'
X; @(#)m16subs.s	1.4	1/28/85
X; @(#)Copyright (C) 1985 by D Bell
X;
X;machine dependent subroutines for the National 32032 microprocessor.
X;strdif - return number of bytes until two strings differ or count is reached.
X;clear	- from first address up till last address, make memory spaces.
X
X	.program
X
X_strdif::
X	movd	16(sp),r0	;byte count
X	movd	8(sp),r1	;first string
X	movd	12(sp),r2	;second string
X	cmpsb			;compare bytes
X	subd	8(sp),r1	;get length of search
X	movd	r1,r0		;make return value
X	rxp	0		;return
X
X
X_clear::
X	movd	12(sp),r0	;ending address
X	movd	8(sp),r1	;beginning address
X	subd	r1,r0		;compute byte count
X	cmpqd	0,r0		;see if any to do
X	bge	done		;nope
X	addqd	-1,r0		;fix count
X	addr	1(r1),r2	;destination address
X	movb	32,0(r1)	;start with a blank
X	movsb			;fill rest too
Xdone:	rxp	0		;return
X
X	.endseg
//E*O*F ns32ksubs.s//
echo done



More information about the Comp.sources.unix mailing list