Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/17/84 chuqui version 1.7 9/23/84; site nsc.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!ihnp4!nsc!chongo From: chongo@nsc.UUCP (Landon Noll) Newsgroups: net.sources Subject: REPORTING for DBell - DPY (Part 2 of 3) Message-ID: <2589@nsc.UUCP> Date: Fri, 12-Apr-85 05:00:56 EST Article-I.D.: nsc.2589 Posted: Fri Apr 12 05:00:56 1985 Date-Received: Sat, 13-Apr-85 06:04:34 EST References: <2588@nsc.UUCP> Distribution: net Organization: Rational Swamiconductor, Sanivale Lines: 1255 In net.sources: I am reposting DBell's DPY sources in response to all the folks who needed them for his LIFE and WAR progs. DBell is no longer on the net (in fact in a few days he will no longer be in this hemisphere) otherwise he would have done this himself. In net.sources.games: I am reposting DBell's LIFE sources complete with the changes for the new DPY. Both LIFE and WAR (which was posted by DBell not long ago) require the use of DPY so be sure and GRAB IT FROM net.sources NOW!!! #---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 /* standard I/O */ X#include /* 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 * 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, <chars) == 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 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 -- no comment is a comment.