[net.sources] Window source #7 [of 0-7]: TrmTERM.c

chris@umcp-cs.UUCP (07/04/83)

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'This thing needs to be rewritten, but it works.'
/bin/echo 'Extracting TrmTERM.c'
sed 's/^X//' <<'//go.sysin dd *' >TrmTERM.c
X/* Copyright (c) 1983 University of Maryland Computer Science Department */
X/* terminal control module for terminals described by TERMCAP */
X
X/* This thing needs a complete rewrite but I'm not ready for that yet.
X   30 Jun 1983 ACT */
X
X/*	Origincal code copyright (c) 1981,1980 James Gosling	*/
X
X/*	Modified 1-Dec-80 by Dan Hoey (DJH) to understand C100 underlines
X *	Modified 2-Dec-80 (DJH) to turn off highlighting on insertline
X *	Modified 4 Aug 81 by JQ Johnson:  use "dm","ei","pc","mi"
X *	Modified 24-Aug-81 by Jeff Mogul (JCM) at Stanford
X *		- uses "nl" instead of \n in case \n is destructive
X *	Modified 8-Sept-81 by JCM @ Stanford
X *		- re-integrated changes from Gosling since July '81
X *	Modified by Chris Torek (ACT) @ Umcp-Cs
X *		- can hack terminals without erase-to-eol (12-Aug-81)
X *		- Sets NullsAreSpecial if :in: (12-June-82)
X *		- Uses "cr" instead of \r (13-June-82)
X *		- Rewrote cursor positioning routines, added:
X *			"ms", "ho", "xr", "nc", "xt", "ta", "xn", "ll" (etc)
X *		- Also cleaned up various things that were cleanable
X *		- Rewrote all the cursor positioning stuff around 21-June-82
X *		- Handles :db: (11-Jul-82)
X *		- Secured the cost algorithms from buffer overflow (16-Jul-82)
X *		- Does not use standout if 'sg#' is nonzero.
X *	Modified by Chris Torek (ACT): added %m cursor motion code
X */
X
X/*
X *	Notes on things not normally in TERMCAP:
X *	:rn: indicates that \r acts like \r\n
X *	:nn: indicates that \n doesn't work
X *	:ds=: gives a "don't send" string; these characters will not
X *	be written to the terminal for cursor motion (:cm=:).  If this
X *	is nonempty the terminal MUST have an upline and a backspace.
X *	If defined, it is assumed to also have a null in it.  If not
X *	included in a termcap, it defaults to ^D\t\n\r.  To get
X *	real binary use ":ds=:" to say can send anything.
X *	:bo=: is bold-start string
X *	:be=: is bold-end string
X *	:ws=: is wink-start (ie blink) string
X *	:we=: is wink-end string
X */
X
X#include <stdio.h>
X#include <sgtty.h>
X#include "Trm.h"
X#include "win.h"
X
X/* ACT: This has gotta be at least 800 for some terminals (!!) */
X#define	CMBUFSIZ	1000	/* Cursor motion buffer size */
X
Xstatic
Xint	curX, curY;
X
Xchar *tgetstr (), *getenv ();
Xchar *UP, *BC, PC;
Xshort ospeed;
X
Xstatic char *ILstr, *DLstr, *ICstr, *DCstr, *ELstr, *ESstr, *HLBstr,
X	*HLEstr, *ICPstr, *ICPDstr, *CursStr, *CteoDstr,
X	*TIstr, *TEstr, *VSstr, *VEstr, *HOstr, *TBstr, *LLstr,
X	*ICEstr, *NDstr, *VBstr, *EDstr, *DMstr, *NLstr, *CRstr,
X	*DSstr, *WSstr, *WEstr, *ULstr, *UEstr, *BSstr, *BEstr;
Xstatic int ULflag,	/* DJH -- 1 if terminal has underline */
X	   MIflag,	/* JQJ -- 1 if safe to move while in insert mode */
X	   XRflag,	/* ACT -- if (:xr:nc:) CR's don't work correctly */
X	   XTflag,	/* 1 if can't use tabs for cursor motion */
X	   XNflag,	/* 1 if can't use \n's for cursor motion */
X	   HZflag,	/* 1 if hazeltine, can't print tilde */
X	   RNflag,	/* 1 if \r does a \r\n */
X	   DBflag,	/* 1 if display retained below */
X	   MSflag;	/* 1 if safe to move while in standout */
X
Xstatic	BOLDOFF, BLINKOFF, ULINEOFF, HLOFF;  /* Bits that tell what
X						modes arent independent */
X
Xstatic
Xdumpchar (c) register c; {
X    putchar (c);
X}
X
Xstatic
Xenum IDmode { m_insert = 1, m_overwrite = 0 }
X	CurMode, DesMode;
X
Xstatic
XINSmode (new)
Xregister enum IDmode new; {
X	DesMode = new;
X};
X
Xstatic curmodes, desmodes;
Xstatic
Xmodes (on) {
X    desmodes = on;
X}
X
X/* This routine needs work! */
Xstatic
Xsetmodes () {
X    register char *com;
X    int bold, under, blink, hl;
X    if (curmodes == desmodes)
X	return;
X/* The "end" strings are often the same. All this is to get around that. */
X    bold = desmodes & WBOLD;
X    under = desmodes & WULINE;
X    blink = desmodes & WBLINK;
X    hl = desmodes & WINVERSE;
X    if (bold==0 && (curmodes & WBOLD)) {/* Then turn off bold */
X	if (com = BEstr) tputs (com, 0, dumpchar);
X	curmodes &= ~BOLDOFF;	/* May have turned others off too */
X    }
X    if (under==0 && (curmodes & WULINE)) {/* etc */
X	if (com = UEstr) tputs (com, 0, dumpchar);
X	curmodes &= ~ULINEOFF;
X    }
X    if (blink==0 && (curmodes & WBLINK)) {
X	if (com = WEstr) tputs (com, 0, dumpchar);
X	curmodes &= ~BLINKOFF;
X    }
X    if (hl==0 && (curmodes & WINVERSE)) {
X	if (com = HLEstr) tputs (com, 0, dumpchar);
X	curmodes &= ~HLOFF;
X    }
X    if (bold != 0 && (curmodes & WBOLD) == 0 && (com = BSstr))
X	tputs (com, 0, dumpchar);
X    if (under != 0 && (curmodes & WULINE) == 0 && (com = ULstr))
X	tputs (com, 0, dumpchar);
X    if (blink != 0 && (curmodes & WBLINK) == 0 && (com = WSstr))
X	tputs (com, 0, dumpchar);
X    if (hl != 0 && (curmodes & WINVERSE) == 0 && (com = HLBstr))
X	tputs (com, 0, dumpchar);
X    curmodes = desmodes;
X}
X
Xstatic
Xclearmodes () {
X    if (curmodes) {
X	register oldes = desmodes;
X	desmodes = 0;
X	setmodes ();
X	desmodes = oldes;
X    }
X}
X
Xstatic
Xsetmode () {
X    if (DesMode == CurMode)
X	return;
X    tputs (DesMode==m_insert ? ICstr : ICEstr, 0, dumpchar);
X    CurMode = DesMode;
X};
X
Xstatic
Xinslines (n) {
X    clearmodes ();
X    while (--n >= 0)
X	tputs (ILstr, W_tt.t_length-curY, dumpchar);
X};
X
Xstatic
Xdellines (n) {
X    register save = n;
X    while (--n >= 0)
X	tputs(DLstr, W_tt.t_length-curY, dumpchar);
X    if (DBflag) {	/* Must clear new lines */
X	if (CteoDstr) {
X	    topos (W_tt.t_length - save + 1, 1);
X	    tputs (CteoDstr, W_tt.t_length-curY, dumpchar);
X	}
X	else {
X	    register i;
X	    for (i=W_tt.t_length-save+1;i<=W_tt.t_length;++i) {
X		topos (i, 1);
X		wipeline (0, W_tt.t_width);
X	    }
X	}
X    }
X};
X
Xstatic
Xwritechars (start, end)
Xregister char	*start,
X		*end; {
X    setmode ();
X    setmodes();
X    while (start <= end) {
X	if(CurMode == m_insert && ICPstr)
X	    tputs(ICPstr, W_tt.t_width-curX, dumpchar);
X			/* DJH -- blank out space before underlines */
X	if(*start == '_' && CurMode != m_insert && ULflag) {
X		putchar (' ');
X		putchar (*BC);
X	}
X	if (HZflag && *start == '~') putchar ('`'), ++start;
X	else putchar (*start++);
X	if (CurMode == m_insert && ICPDstr)
X	    tputs(ICPDstr, W_tt.t_width-curX, dumpchar);
X	curX++;
X    }
X};
X
Xstatic
Xblanks (n) {
X    setmode ();
X    setmodes ();
X    while (--n >= 0) {
X	if (CurMode == m_insert && ICPstr)
X	    tputs (ICPstr, W_tt.t_width - curX, dumpchar);
X	putchar (' ');
X	if (CurMode == m_insert && ICPDstr)
X	    tputs (ICPDstr, W_tt.t_width - curX, dumpchar);
X	curX++;
X    }
X};
X
X/* ACT 8-Sep-1982 Commented all the pad stuff out, termlib already takes care
X   of it. */
X
Xstatic float BaudFactor;
X
X/*
Xstatic pad(n,f)
Xfloat   f; {
X    register    k = n * f * BaudFactor;
X    while (--k >= 0)
X	putchar (W_tt.t_padc);
X};
X*/
X
Xstatic char *CM, *bufp, save[CMBUFSIZ], *bufbase;
Xstatic CMcost, FixCM;
X
X#define	SETSTUFF(buf)	bufp=bufbase=buf
X#define SETBASE(buf)	bufbase=buf
X
Xstuffchar (c)
Xregister char c;
X{
X    if (bufp - bufbase < CMBUFSIZ)
X	*bufp++ = c;
X}
X
X/*
X * Compute cost for going from (sy, sx) to (dy, dx) with extra (add)
X * and if less than current least-cost, change current least-cost.
X * Algorithm is:
X * 1.	If we can use tabs, then try that; get as close as possible
X *	without going too far.  Then try using cursor right from there,
X *	and cursor left from one tab stop later.  Be careful not to go
X *	past the end of the line.
X * 2.	Try using cursor right and cursor left.
X * 3.	Use the least length version of 1 & 2
X * 4.	Add in up/down motion(s)
X */
X
Xstatic
Xtestcost (sy, sx, dy, dx, add)
Xregister sy, sx, dy, dx;
Xchar *add;
X{
X    static char tbuf1[CMBUFSIZ], mbuf[CMBUFSIZ];
X				/* Buffers for cursor motion stuff */
X    int tabcost, movecost, tmp, tmp2, tmp3;
X
X    if (sx == dx && sy == dy) {
X	movecost = 0;
X	goto done;
X    }
X    if (dy > sy && !NLstr || dy < sy && !UP)	/* Can't get there from here */
X	return;
X    if (!XTflag && sx < dx) {	/* Try tabs */
X	tmp = sx;
X	SETSTUFF (tbuf1);
X	while ((tmp2 = ((tmp - 1) & ~7) + 9) <= dx)
X	    tputs (TBstr, 0, stuffchar), tmp = tmp2;
X	if (NDstr) {
X	    bcopy (tbuf1, mbuf, movecost = bufp - tbuf1);
X	    tmp3 = tmp;
X	}
X	if (tmp < dx) tputs (TBstr, 0, stuffchar), tmp = tmp2;
X	if (tmp > dx && !BC || tmp > W_tt.t_length)
X	    tabcost = 9999;
X	else {
X	    while (tmp-- > dx) tputs (BC, 0, stuffchar);
X	    tabcost = bufp - tbuf1;
X	}
X	if (NDstr) {
X	    bufp = mbuf + movecost;
X	    SETBASE (mbuf);
X	    tmp = tmp3;
X	    while (tmp++ < dx) tputs (NDstr, 0, stuffchar);
X	    movecost = bufp - mbuf;
X	    if (movecost < tabcost) {
X		bcopy (mbuf, tbuf1, tabcost = movecost);
X	    }
X	}
X    }
X    else tabcost = 9999;
X    if (sx < dx) {
X	if (NDstr) {
X	    SETSTUFF (mbuf);
X	    while (sx++ < dx) tputs (NDstr, 0, stuffchar);
X	    movecost = bufp - mbuf;
X	}
X	else movecost = 9999;
X    }
X    else {
X	if (BC) {
X	    SETSTUFF (mbuf);
X	    while (sx-- > dx) tputs (BC, 0, stuffchar);
X	    movecost = bufp - mbuf;
X	}
X	else movecost = 9999;
X    }
X    if (movecost == 9999 && tabcost == 9999) return;
X    if (tabcost < movecost) bcopy (tbuf1, mbuf, movecost = tabcost);
X    bufp = mbuf + movecost;
X    SETBASE (mbuf);
X    if (sy < dy) while (sy++ < dy) tputs (NLstr, 0, stuffchar);
X    else while (sy-- > dy) tputs (UP, 0, stuffchar);
X    movecost = bufp - mbuf;
Xdone:
X    SETSTUFF (tbuf1);
X    tputs (add, 0, stuffchar);
X    tabcost = bufp - tbuf1;	/* I know, it's the wrong variable name */
X    if (movecost + tabcost < CMcost) {
X	bcopy (tbuf1, save, tabcost);
X	bcopy (mbuf, save + tabcost, movecost);
X	CM = save;
X	CMcost = movecost + tabcost;
X    }
X};
X
X/* Perhaps a word of explanation ... in case we manage to get nulls into the
X   cursor motion string, we change them to 0377s first, or all of the library
X   routines used will stop after the null.  (0377 is just an "unlikely" code,
X   especially because it has the high bit on.)  Anyway, these must be
X   converted back after the library routines are done.  This is a horrible
X   hack and will probably cause someone untold trouble later.  -ACT */
X
Xstatic
Xtopos (row, column) {
X    char *tgoto ();
X
X    if (curY == row && curX == column) return;
X
X    if (CursStr) {
X	CM = tgoto (CursStr, column-1, row-1);
X	SETSTUFF (save);
X	tputs (CM, 0, stuffchar);
X	CM = save;
X	CMcost = bufp - save;
X	if (FixCM) {		/* Must change 0377's to 0's */
X	    register char *s = save;
X	    register len = CMcost;
X	    for (;len--;++s) if ((*s & 0377) == 0377) *s = 0;
X	}
X    }
X    else CMcost = 9999;
X
X    if (HOstr) testcost (1, 1, row, column, HOstr);
X    if (!XRflag) testcost (curY, 1, row, column, CRstr);
X    if (RNflag && curY < W_tt.t_length)
X	testcost (curY + 1, 1, row, column, "\r");
X    testcost (curY, curX, row, column, "");
X    if (LLstr) testcost (W_tt.t_length, 1, row, column, LLstr);
X
X    if (! MSflag)
X	clearmodes ();		/* many terminals can't hack highlighting
X				   around cursor positioning.  Silly twits! */
X    if (CurMode==m_insert && ! MIflag) {
X	tputs(ICEstr, 0, dumpchar);	/* some terminals can't move in */
X	CurMode = m_overwrite;		/* insert mode -- JQJ */
X    }
X    while (CMcost--) putchar (*CM++);	/* Now, wasn't that easy? */
X    curX = column;
X    curY = row;
X};
X
Xstatic
Xflash () {			/* dump a visible bell */
X    tputs (VBstr, 0, dumpchar);
X}
X
Xstatic
Xinit (BaudRate) {
X    static char tbuf[1024];
X    static char combuf[1024];
X    register char *temp;
X    extern  struct sgttyb WOld;
X    extern  int		  WTtyFd;
X    char   *fill = combuf;
X    static  inited;
X    if (!inited)
X	if (tgetent (tbuf, getenv ("TERM")) <= 0) {
X	    return 1;
X/*	    stty (WTtyFd, &WOld);
X	    quit (1,
X"No environment-specified terminal type -- see TSET(1), sh(1)\n"); */
X	}
X    inited = 1;
X    W_tt.t_needspaces = tgetflag ("in");
X    XTflag = ((WOld.sg_flags & TBDELAY) == XTABS) || tgetflag ("xt");
X    XRflag = tgetflag ("nc") || tgetflag ("xr");
X    XNflag = tgetflag ("xn") || tgetflag ("nn");
X    MSflag = tgetflag ("ms");
X    HZflag = tgetflag ("hz");
X    DBflag = tgetflag ("db");
X    RNflag = tgetflag ("rn");
X    DSstr = (temp = tgetstr ("ds", &fill)) ? temp : "\004\t\n\r";
X    if (!*DSstr) DSstr = 0;
X    if (!XRflag) CRstr = (temp = tgetstr ("cr", &fill)) ? temp : "\r";
X    if (!XTflag) TBstr = (temp = tgetstr ("ta", &fill)) ? temp : "\t";
X    ILstr = tgetstr ("al", &fill);
X    HOstr = tgetstr ("ho", &fill);
X    LLstr = tgetstr ("ll", &fill);
X    DLstr = tgetstr ("dl", &fill);
X    ICstr = tgetstr ("im", &fill);
X    ICEstr = tgetstr ("ei", &fill);
X    MIflag = tgetflag ("mi");	/* can move in insert mode */
X    DCstr = tgetstr ("dc", &fill);
X    ELstr = tgetstr ("ce", &fill);
X    ESstr = tgetstr ("cl", &fill);
X    if (tgetnum ("sg") < 1) {
X	HLBstr = tgetstr ("so", &fill);
X	HLEstr = tgetstr ("se", &fill);
X    }
X    if (tgetnum ("ug") < 1) {
X	ULstr = tgetstr ("us", &fill);
X	UEstr = tgetstr ("ue", &fill);
X    }
X    WSstr = tgetstr ("ws", &fill);
X    WEstr = tgetstr ("we", &fill);
X    BSstr = tgetstr ("bo", &fill);
X    BEstr = tgetstr ("be", &fill);
X    ICPstr = tgetstr ("ic", &fill);
X    ICPDstr = tgetstr ("ip", &fill);
X    CursStr = tgetstr ("cm", &fill);
X    if (DBflag) CteoDstr = tgetstr ("cd", &fill);
X    UP = tgetstr ("up", &fill);
X    NDstr = tgetstr ("nd", &fill);
X    VBstr = tgetstr ("vb", &fill);
X    TIstr = tgetstr ("ti", &fill);
X    TEstr = tgetstr ("te", &fill);
X    DMstr = tgetstr ("dm", &fill);/* start delete mode */
X    EDstr = tgetstr ("ed", &fill);/* end delete mode */
X    VSstr = tgetstr ("vs", &fill);
X    VEstr = tgetstr ("ve", &fill);/* ``visual'' start/end -ACT */
X    if (tgetflag ("bs")) BC = "\b";
X    else BC = tgetstr ("bc", &fill);
X    ULflag = tgetflag ("ul");	/* DJH -- Find out about underline */
X    if (!XNflag) NLstr = (temp = tgetstr ("nl", &fill)) ? temp : "\n";
X    PC = W_tt.t_padc = (temp = tgetstr ("pc", &fill)) ? *temp : 0;
X/* Where does he get this weird formula?? ACT */
X/*  BaudFactor = 1 / (1 - (.45 + .3*BaudRate/9600.)) * (BaudRate/10000.);*/
X    BaudFactor = ((float) BaudRate) / 10000.;
X    if (!ESstr || (CursStr	? DSstr && !UP && !BC
X				: !UP || !BC || !NLstr || !NDstr)) {
X	return 1;
X/*	stty (WTtyFd, &WOld);
X	quit (1, "Sorry, this terminal isn't powerful enough to run windows.\n\
XIt is missing some important features.\n"); */
X    }
X    W_tt.t_ILmf = BaudFactor * 0.75;
X    if (ILstr) W_tt.t_ILov = 2;
X    else {
X	W_tt.t_ILov = MissingFeature;
X	W_tt.t_inslines = W_tt.t_dellines = (int (*) ()) - 1;
X    }
X    if (VBstr) W_tt.t_flash = flash;
X    if (ICstr) {
X	W_tt.t_ICmf = 1;
X	W_tt.t_ICov = strlen(ICstr) + (ICEstr ? strlen(ICEstr) : 0) +
X	    (ICPstr ? strlen(ICPstr) : 0) + (ICPDstr ? strlen(ICPDstr) : 0);
X    } else W_tt.t_ICmf = W_tt.t_ICov = MissingFeature;
X    if (DCstr) {
X	W_tt.t_DCmf = strlen (DCstr);
X	W_tt.t_DCov = (DMstr ? strlen(DMstr) : 0) + (EDstr ? strlen(EDstr) : 0);
X    } else W_tt.t_DCmf = W_tt.t_DCov = MissingFeature;
X    temp = getenv ("PL");	/* (ACT) Test for desired page len */
X    W_tt.t_length = temp && atoi (temp) ? atoi (temp) : tgetnum ("li");
X    temp = getenv ("COL");	/* (ACT) Test for desired line len */
X    W_tt.t_width = (temp && atoi (temp) ? atoi (temp) : tgetnum ("co"))
X		 - (tgetflag ("am") ? 1 : 0);
X
X    BOLDOFF = WBOLD;		/* Turning off bold turns off bold */
X    BLINKOFF = WBLINK;		/* Turning off blink turns off blink */
X    ULINEOFF = WULINE;		/* Turning off uline turns off uline */
X    HLOFF = WINVERSE;		/* Turning off hl turns off hl */
X    if (lstrcmp (BEstr, WEstr) == 0) {
X	BOLDOFF |= WBLINK;	/* bold & blink interrelate */
X	BLINKOFF |= WBOLD;
X    }
X    if (lstrcmp (BEstr, UEstr) == 0) {
X	BOLDOFF |= WULINE;	/* bold & under interrelate */
X	ULINEOFF |= WBOLD;
X    }
X    if (lstrcmp (BEstr, HLEstr) == 0) {
X	BOLDOFF |= WINVERSE;	/* etc */
X	HLOFF |= WBOLD;
X    }
X    if (lstrcmp (WEstr, UEstr) == 0) {
X	BLINKOFF |= WULINE;
X	ULINEOFF |= WBLINK;
X    }
X    if (lstrcmp (WEstr, HLEstr) == 0) {
X	BLINKOFF |= WINVERSE;
X	HLOFF |= WBLINK;
X    }
X    if (lstrcmp (UEstr, HLEstr) == 0) {
X	ULINEOFF |= WINVERSE;
X	HLOFF |= WULINE;
X    }
X    return 0;
X};
X
Xstatic
Xlstrcmp (s1, s2)		/* Version of strcmp takes care of NULL */
Xregister char *s1, *s2;
X{
X    if (s1 == 0 || s2 == 0)
X	return 1;		/* Don't bother -- call 'em different */
X    while (*s1 == *s2++)
X    	if (*s1++ == 0)
X	    return 0;
X    return 1;			/* Order not important */
X}
X
Xstatic
Xreset () {
X    if (TIstr) tputs(TIstr, 0, dumpchar);
X    if (VSstr) tputs(VSstr, 0, dumpchar);
X    tputs(ESstr, 0, dumpchar);	/* Also homes cursor: */
X    curX = curY = 1;
X    CurMode = m_insert;
X    DesMode = m_overwrite;
X};
X
Xstatic
Xcleanup () {
X    modes (0); setmodes ();
X    DesMode = m_overwrite;
X    setmode();
X    topos (W_tt.t_length, 1);
X    if (VEstr) tputs(VEstr, 0, dumpchar); 
X    if (TEstr) tputs(TEstr, 0, dumpchar);
X};
X
Xstatic
Xwipeline (z,p) register p; {
X    clearmodes ();
X    if (ELstr) tputs (ELstr, W_tt.t_width-curX, dumpchar);
X    else {
X	register i = p - curX + 1/*, oldX = curX*/;
X	if (i < 1) return;
X	if (CurMode == m_insert) {
X	    tputs(ICEstr, 0, dumpchar);	/* We don't want these inserted */
X	    CurMode = m_overwrite;
X	}
X	while (--i >= 0) putchar(' '), ++curX;
X/*	topos (curY, oldX);	/* This appears to be unnecessary */
X    }
X};
X
Xstatic
Xwipescreen () {
X    tputs(ESstr, 0, dumpchar);
X    curX = curY = 1;
X};
X
Xstatic
Xdelchars (n) {
X    if (DMstr) {	/* we may have delete mode, or delete == insert */
X	if (strcmp(DMstr,ICstr) /*ACT*/ == 0 /*END*/) {
X	    if (CurMode  == m_overwrite) {
X	        tputs(ICstr,0,dumpchar);
X		CurMode = m_insert;	/* we're now in both */
X	    }
X	}
X	else {
X	    if (CurMode == m_insert) {
X		tputs(ICEstr, 0, dumpchar);
X		CurMode = m_overwrite;
X	    }
X	    tputs(DMstr,0,dumpchar);
X        }
X    }
X    while (--n >= 0) {
X	tputs(DCstr, W_tt.t_width-curX, dumpchar);
X    }
X    if (EDstr) {		/* for some, insert mode == delete mode */
X		/* bug!  /etc/termcap pads ICEstr but not EDstr */
X        if (strcmp(DMstr,ICstr) /*ACT*/ == 0 /*END*/)
X	    CurMode = m_insert;	/* (ACT) But you already did this! */
X	else
X	    tputs(EDstr,0,dumpchar);
X    }
X};
X
XTrmTERM () {
X	W_tt.t_INSmode = INSmode;
X	W_tt.t_modes = modes;
X	W_tt.t_inslines = inslines;
X	W_tt.t_dellines = dellines;
X	W_tt.t_blanks = blanks;
X	W_tt.t_init = init;
X	W_tt.t_cleanup = cleanup;
X	W_tt.t_wipeline = wipeline;
X	W_tt.t_wipescreen = wipescreen;
X	W_tt.t_topos = topos;
X	W_tt.t_reset = reset;
X	W_tt.t_delchars = delchars;
X	W_tt.t_writechars = writechars;
X	W_tt.t_window = 0;
X	W_tt.t_ILmf = 0;
X	W_tt.t_ILov = 0;
X	W_tt.t_ICmf = 0;
X	W_tt.t_ICov = 0;
X	W_tt.t_length = 24;
X	W_tt.t_width = 80;
X	return 0;
X};
X
X/*
X * A home-brew "tgoto" with some special mods
X * If termlib ever changes this'll need updating
X *
X *	%d	decimal
X *	%2	%2d
X *	%3	%3d
X *	%.	binary, with "don't send"s
X *	%+x	Adds x, then like binary
X *	%>xy	if >x add y
X *	%r	next is col
X *	%i	Increment row/col
X *	%%	= %
X *	%B	BCD
X *	%D	Backwards BCD
X *	%m	xor with 0177
X *	%<foo>	like %+<foo>
X */
X
Xstatic char *
Xtgoto (CM, col, line)
Xchar	*CM;
Xint	col, line;
X{
X	static char cmbuf[50], add[20];
X	register char *cp = CM, *op = cmbuf;
X	register c;
X	int val = line, toggle = 0;
X
X	if (! cp) return "OOPS";
X	*add = 0;
X	*op = 0;
X	FixCM = 0;
X	while (c = *cp++) {
X		if (c != '%') {
X			*op++ = c;
X			continue;
X		}
X		switch (c = *cp++) {
X		case 'm':
X			col ^= 0177;
X			line ^= 0177;
X			goto setval;
X		case 'n':
X			col ^= 0140;
X			line ^= 0140;
X			goto setval;
X		case 'd':
X			if (val < 10) goto onedigit;
X			if (val < 100) goto twodigit;
X		case '3':
X			*op++ = (val / 100) + '0';
X			val %= 100;
X		case '2':
Xtwodigit:
X			*op++ = (val / 10) + '0';
Xonedigit:
X			*op++ = (val % 10) + '0';
Xswap:
X			toggle = 1 - toggle;
Xsetval:
X			val = toggle ? col : line;
X			continue;
X		case '>':
X			if (val > *cp++) val += *cp++;
X			else cp++;
X			continue;
X		case '+':
X			val += *cp++;
X		case '.':
Xuse:
X			if (DSstr) {
X				while (val == 0 || index (DSstr, val)) {
X					strcat (add, toggle ? BC : UP);
X					++val;
X				}
X			}
X			else if (val == 0) {
X				*op++ = 0377;
X				FixCM = 1;
X				goto swap;
X			}
X			*op++ = val;
X			goto swap;
X		case 'r':
X			toggle = 1;
X			goto setval;
X		case 'i':
X			++col, ++line, ++val;
X			continue;
X		case '%':
X			*op++ = c;
X			continue;
X		case 'B':
X			val = ((val / 10) << 4) + val % 10;
X			continue;
X		case 'D':
X			val = val - 2 * (val % 16);
X			continue;
X		default:
X			val += c;
X			goto use;
X		}
X	}
X	*op = 0;
X	strcat (op, add);
X	return cmbuf;
X}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 TrmTERM.c
	/bin/echo -n '	'; /bin/ls -ld TrmTERM.c
fi
-- 
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs
ARPA:	chris.umcp-cs@UDel-Relay