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++ = c