[comp.os.os9] SCREEN for OSK, Part 02 of 03

ocker@lan.informatik.tu-muenchen.dbp.de (Wolfgang Ocker) (01/25/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  ansi.c
# Wrapped by weo@recco on Fri Jan  6 14:32:08 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ansi.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ansi.c'\"
else
echo shar: Extracting \"'ansi.c'\" \(30846 characters\)
sed "s/^X//" >'ansi.c' <<'END_OF_FILE'
X/* Copyright (c) 1987, Oliver Laumann, Technical University of Berlin.
X * Not derived from licensed software.
X *
X * Permission is granted to freely use, copy, modify, and redistribute
X * this software, provided that no attempt is made to gain profit from it,
X * the author is not construed to be liable for any results of using the
X * software, alterations are clearly marked as such, and this notice is
X * not modified.
X *
X * Adapted to OS-9/68000 by reccoware systems, Wolfgang Ocker, Puchheim 1988
X */
X
Xchar AnsiVersion[] = "ansi 1.0g 27-Apr-87";
X
X#include <stdio.h>
X#ifdef	OSK
X#include <types.h>
X#include <time.h>
X#else
X#include <sys/types.h>
X#endif
X#include "screen.h"
X
X#ifdef	OSK
Xchar PC_, *BC, *UP;
Xshort int ospeed;
X#endif
X
X#define A_SO     0x1    /* Standout mode */
X#define A_US     0x2    /* Underscore mode */
X#define A_BL     0x4    /* Blinking */
X#define A_BD     0x8    /* Bold mode */
X#define A_DI    0x10    /* Dim mode */
X#define A_RV    0x20    /* Reverse mode */
X#define A_MAX   0x20
X
X/* Types of movement used by Goto() */
Xenum move_t {
X    M_NONE,
X    M_UP,
X    M_DO,
X    M_LE,
X    M_RI,
X    M_RW,
X    M_CR,
X};
X
X#define MAXARGS      64
X#define EXPENSIVE    1000
X
Xextern char *getenv(), *tgetstr(), *tgoto(), *malloc();
X
Xint rows, cols;
Xint status;
Xint flowctl;
Xchar Term[] = "TERM=screen";
Xchar Termcap[1024];
Xchar *blank;
Xchar PC;
Xtime_t TimeDisplayed;
X
X#ifdef	OSK
X#define	SR SR_
X#endif
X
Xstatic char tbuf[1024], tentry[1024];
Xstatic char *tp = tentry;
X#ifdef	OSK
Xstatic char *TI, *TE, *BL, *VB, *CR, *NL, *CL, *IS, *CM;
X#else
Xstatic char *TI, *TE, *BL, *VB, *BC, *CR, *NL, *CL, *IS, *CM;
X#endif
Xstatic char *US, *UE, *SO, *SE, *CE, *CD, *DO, *SR, *SF, *AL;
X#ifdef	OSK
Xstatic char *CS, *DL, *DC, *IC, *IM, *EI, *ND, *KS, *KE;
X#else
Xstatic char *CS, *DL, *DC, *IC, *IM, *EI, *UP, *ND, *KS, *KE;
X#endif
Xstatic char *MB, *MD, *MH, *MR, *ME;
Xstatic AM;
Xstatic args[MAXARGS];
Xstatic char GotArg[MAXARGS];
Xstatic NumArgs;
Xstatic char GlobalAttr, TmpAttr;
Xstatic char *OldImage, *OldAttr;
Xstatic last_x, last_y;
Xstatic struct win *curr;
Xstatic display = 1;
Xstatic StrCost;
Xstatic UPcost, DOcost, LEcost, NDcost, CRcost, IMcost, EIcost;
Xstatic tcLineLen = 100;
Xstatic char *null;
Xstatic StatLen;
Xstatic insert;
Xstatic keypad;
X
Xstatic char *KeyCaps[] = {
X    "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9",
X    "kb", "kd", "kh", "kl", "ko", "kr", "ku",
X    0
X};
X
Xstatic char TermcapConst[] = "TERMCAP=\
XSC|screen|VT 100/ANSI X3.64 virtual terminal|\\\n\
X\t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
X\t:cd=\\E[J:ce=\\E[K:cl=\\E[2J\\E[H:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
X\t:do=\\E[B:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\E[A:";
X
X#ifdef	OSK
Xvoid bzero(buf, num)
X	register char *buf;
X	register int  num;
X{
X	for (; num > 0; num--)
X		*buf++ = '\0';
X}
X#define bcopy(a,b,c) memcpy(b,a,c)
X#endif
X
X
XInitTerm () {
X    register char *s;
X
X    if ((s = getenv ("TERM")) == 0)
X	Msg (0, "No TERM in environment.");
X    if (tgetent (tbuf, s) != 1)
X	Msg (0, "Cannot find termcap entry for %s.", s);
X    cols = tgetnum ("co");
X    rows = tgetnum ("li");
X    if (cols <= 0)
X	cols = 80;
X    if (rows <= 0)
X	rows = 24;
X    if (tgetflag ("hc"))
X	Msg (0, "You can't run screen on a hardcopy terminal.");
X    if (tgetflag ("os"))
X	Msg (0, "You can't run screen on a terminal that overstrikes.");
X    if (tgetflag ("ns"))
X	Msg (0, "Terminal must support scrolling.");
X    if (!(CL = tgetstr ("cl", &tp)))
X	Msg (0, "Clear screen capability required.");
X    if (!(CM = tgetstr ("cm", &tp)))
X	Msg (0, "Addressable cursor capability required.");
X    if (s = tgetstr ("ps", &tp))
X	PC = s[0];
X    flowctl = !tgetflag ("NF");
X    AM = tgetflag ("am");
X    if (tgetflag ("LP"))
X	AM = 0;
X    TI = tgetstr ("ti", &tp);
X    TE = tgetstr ("te", &tp);
X    if (!(BL = tgetstr ("bl", &tp)))
X	BL = "\007";
X    VB = tgetstr ("vb", &tp);
X    if (!(BC = tgetstr ("bc", &tp))) {
X	if (tgetflag ("bs"))
X	    BC = "\b";
X	else
X	    BC = tgetstr ("le", &tp);
X    }
X    if (!(CR = tgetstr ("cr", &tp)))
X	CR = "\r";
X    if (!(NL = tgetstr ("nl", &tp)))
X#ifdef	OSK
X	NL = "\l";
X#else
X	NL = "\n";
X#endif
X    IS = tgetstr ("is", &tp);
X    if (tgetnum ("sg") <= 0) {
X	US = tgetstr ("us", &tp);
X	UE = tgetstr ("ue", &tp);
X	SO = tgetstr ("so", &tp);
X	SE = tgetstr ("se", &tp);
X	MB = tgetstr ("mb", &tp);
X	MD = tgetstr ("md", &tp);
X	MH = tgetstr ("mh", &tp);
X	MR = tgetstr ("mr", &tp);
X	ME = tgetstr ("me", &tp);
X	/*
X	 * Does ME also reverse the effect of SO and/or US?  This is not
X	 * clearly specified by the termcap manual.
X	 * Anyway, we should at least look whether ME and SE/UE are equal:
X	 */
X	if (SE && UE && ME && (strcmp (SE, UE) == 0 || strcmp (ME, UE) == 0))
X	    UE = 0;
X	if (SE && ME && strcmp (SE, ME) == 0)
X	    SE = 0;
X    }
X    CE = tgetstr ("ce", &tp);
X    CD = tgetstr ("cd", &tp);
X    if (!(DO = tgetstr ("do", &tp)))
X	DO = NL;
X    UP = tgetstr ("up", &tp);
X    ND = tgetstr ("nd", &tp);
X    SR = tgetstr ("sr", &tp);
X    if (!(SF = tgetstr ("sf", &tp)))
X	SF = NL;
X    AL = tgetstr ("al", &tp);
X    DL = tgetstr ("dl", &tp);
X    CS = tgetstr ("cs", &tp);
X    DC = tgetstr ("dc", &tp);
X    IC = tgetstr ("ic", &tp);
X    IM = tgetstr ("im", &tp);
X    EI = tgetstr ("ei", &tp);
X    if (tgetflag ("in"))
X	IC = IM = 0;
X    if (IC && IC[0] == '\0')
X	IC = 0;
X    if (IM && IM[0] == '\0')
X	IM = 0;
X    if (EI && EI[0] == '\0')
X	EI = 0;
X    KS = tgetstr ("ks", &tp);
X    KE = tgetstr ("ke", &tp);
X    blank = malloc (cols);
X    null = malloc (cols);
X    OldImage = malloc (cols);
X    OldAttr = malloc (cols);
X    if (!(blank && null && OldImage && OldAttr))
X	Msg (0, "Out of memory.");
X    MakeBlankLine (blank, cols);
X    bzero (null, cols);
X    UPcost = CalcCost (UP);
X    DOcost = CalcCost (DO);
X    LEcost = CalcCost (BC);
X    NDcost = CalcCost (ND);
X    CRcost = CalcCost (CR);
X    IMcost = CalcCost (IM);
X    EIcost = CalcCost (EI);
X    PutStr (IS);
X    PutStr (TI);
X    PutStr (CL);
X}
X
XFinitTerm () {
X    PutStr (TE);
X    PutStr (IS);
X}
X
Xstatic AddCap (s) char *s; {
X    register n;
X
X    if (tcLineLen + (n = strlen (s)) > 55) {
X	strcat (Termcap, "\\\n\t:");
X	tcLineLen = 0;
X    }
X    strcat (Termcap, s);
X    tcLineLen += n;
X}
X
Xchar *MakeTermcap (aflag) {
X    char buf[1024];
X    register char **pp, *p;
X
X    strcpy (Termcap, TermcapConst);
X    sprintf (buf, "li#%d:co#%d:", rows, cols);
X    AddCap (buf);
X    if (VB)
X	AddCap ("vb=\\E[?5h\\E[?5l:");
X    if (US) {
X	AddCap ("us=\\E[4m:");
X	AddCap ("ue=\\E[24m:");
X    }
X    if (SO) {
X	AddCap ("so=\\E[3m:");
X	AddCap ("se=\\E[23m:");
X    }
X    if (MB)
X	AddCap ("mb=\\E[5m:");
X    if (MD)
X	AddCap ("md=\\E[1m:");
X    if (MH)
X	AddCap ("mh=\\E[2m:");
X    if (MR)
X	AddCap ("mr=\\E[7m:");
X    if (MB || MD || MH || MR)
X	AddCap ("me=\\E[0m:");
X    if ((CS && SR) || AL || aflag) {
X	AddCap ("sr=\\EM:");
X	AddCap ("al=\\E[L:");
X	AddCap ("AL=\\E[%dL:");
X    }
X    if (CS || DL || aflag) {
X	AddCap ("dl=\\E[M:");
X	AddCap ("DL=\\E[%dM:");
X    }
X    if (CS)
X	AddCap ("cs=\\E[%i%d;%dr:");
X    if (DC || aflag) {
X	AddCap ("dc=\\E[P:");
X	AddCap ("DC=\\E[%dP:");
X    }
X    if (IC || IM || aflag) {
X	AddCap ("im=\\E[4h:");
X	AddCap ("ei=\\E[4l:");
X	AddCap ("ic=:");
X	AddCap ("IC=\\E[%d@:");
X    }
X    if (KS)
X	AddCap ("ks=\\E=:");
X    if (KE)
X	AddCap ("ke=\\E>:");
X    for (pp = KeyCaps; *pp; ++pp)
X	if (p = tgetstr (*pp, &tp)) {
X	    MakeString (*pp, buf, p);
X	    AddCap (buf);
X	}
X    return Termcap;
X}
X
XMakeString (cap, buf, s) char *cap, *buf; register char *s; {
X    register char *p = buf;
X    register unsigned c;
X
X    *p++ = *cap++; *p++ = *cap; *p++ = '=';
X    while (c = *s++) {
X	switch (c) {
X	case '\033':
X	    *p++ = '\\'; *p++ = 'E'; break;
X	case ':':
X	    sprintf (p, "\\072"); p += 4; break;
X	case '^': case '\\':
X	    *p++ = '\\'; *p++ = c; break;
X	default:
X	    if (c >= 200) {
X		sprintf (p, "\\%03o", c & 0377); p += 4;
X	    } else if (c < ' ') {
X		*p++ = '^'; *p++ = c + '@';
X	    } else *p++ = c;
X	}
X    }
X    *p++ = ':'; *p = '\0';
X}
X
XActivate (wp) struct win *wp; {
X    RemoveStatus (wp);
X    curr = wp;
X    display = 1;
X    NewRendition (GlobalAttr, curr->LocalAttr);
X    GlobalAttr = curr->LocalAttr;
X    InsertMode (curr->insert);
X    KeypadMode (curr->keypad);
X    if (CS)
X	PutStr (tgoto (CS, curr->bot, curr->top));
X    Redisplay ();
X}
X
XResetScreen (p) register struct win *p; {
X    register i;
X
X    bzero (p->tabs, cols);
X    for (i = 8; i < cols; i += 8)
X	p->tabs[i] = 1;
X    p->wrap = 1;
X    p->origin = 0;
X    p->insert = 0;
X    p->vbwait = 0;
X    p->keypad = 0;
X    p->top = 0;
X    p->bot = rows - 1;
X    p->saved = 0;
X    p->LocalAttr = 0;
X    p->x = p->y = 0;
X    p->state = LIT;
X    p->StringType = NONE;
X}
X
XWriteString (wp, buf, len) struct win *wp; register char *buf; {
X    register c, intermediate = 0;
X
X    if (!len)
X	return;
X    curr = wp;
X    display = curr->active;
X    if (display)
X	RemoveStatus (wp);
X    do {
X	c = *buf++;
X	if (c == '\0' || c == '\177')
X	    continue;
XNextChar:
X	switch (curr->state) {
X	case TERM:
X	    switch (c) {
X		case '\\':
X		    curr->state = LIT;
X		    *(curr->stringp) = '\0';
X		    if (curr->StringType == PM && display) {
X			MakeStatus (curr->string, curr);
X			if (status && len > 1) {
X			    curr->outlen = len-1;
X			    bcopy (buf, curr->outbuf, curr->outlen);
X			    return;
X			}
X		    }
X		    break;
X		default:
X		    curr->state = STR;
X		    AddChar ('\033');
X		    AddChar (c);
X	    }
X	    break;
X	case STR:
X	    switch (c) {
X		case '\0':
X		    break;
X		case '\033':
X		    curr->state = TERM; break;
X		default:
X		    AddChar (c);
X	    }
X	    break;
X	case ESC:
X	    switch (c) {
X	    case '[':
X		NumArgs = 0;
X		intermediate = 0;
X		bzero ((char *)args, MAXARGS * sizeof (int));
X		bzero (GotArg, MAXARGS);
X		curr->state = CSI;
X		break;
X	    case ']':
X		StartString (OSC); break;
X	    case '_':
X		StartString (APC); break;
X	    case 'P':
X		StartString (DCS); break;
X	    case '^':
X		StartString (PM); break;
X	    default:
X		if (Special (c))
X		    break;
X		if (c >= ' ' && c <= '/') {
X		    intermediate = intermediate ? -1 : c;
X		} else if (c >= '0' && c <= '~') {
X		    DoESC (c, intermediate);
X		    curr->state = LIT;
X		} else {
X		    curr->state = LIT;
X		    goto NextChar;
X		}
X	    }
X	    break;
X	case CSI:
X	    switch (c) {
X	    case '0': case '1': case '2': case '3': case '4':
X	    case '5': case '6': case '7': case '8': case '9':
X		if (NumArgs < MAXARGS) {
X		    args[NumArgs] = 10 * args[NumArgs] + c - '0';
X		    GotArg[NumArgs] = 1;
X		}
X		break;
X	    case ';': case ':':
X		NumArgs++; break;
X	    default:
X		if (Special (c))
X		    break;
X		if (c >= '@' && c <= '~') {
X		    NumArgs++;
X		    DoCSI (c, intermediate);
X		    curr->state = LIT;
X		} else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?')) {
X		    intermediate = intermediate ? -1 : c;
X		} else {
X		    curr->state = LIT;
X		    goto NextChar;
X		}
X	    }
X	    break;
X	default:
X	    if (!Special (c)) {
X		if (c == '\033') {
X		    intermediate = 0;
X		    curr->state = ESC;
X		} else if (c < ' ') {
X		    break;
X		} else if (curr->x < cols-1) {
X		    if (curr->insert) {
X			InsertAChar (c);
X		    } else {
X			if (display)
X			    putchar (c);
X			SetChar (c);
X		    }
X		    curr->x++;
X		} else if (curr->x == cols-1) {
X		    SetChar (c);
X		    if (!(AM && curr->y == rows-1)) {
X			if (display)
X			    putchar (c);
X			Goto (-1, -1, curr->y, curr->x);
X		    }
X		    curr->x++;
X		} else {
X		    if (curr->wrap) {
X			Return ();
X			LineFeed ();
X			if (curr->insert) {
X			    InsertAChar (c);
X			} else {
X			    if (display)
X				putchar (c);
X			    SetChar (c);
X			}
X			curr->x = 1;
X		    } else curr->x = cols;
X		}
X	    }
X	}
X    } while (--len);
X    curr->outlen = 0;
X}
X
Xstatic Special (c) register c; {
X    switch (c) {
X    case '\b':
X	BackSpace (); return 1;
X    case '\r':
X	Return (); return 1;
X#ifdef	OSK
X    case '\l':
X#else
X    case '\n':
X#endif
X	LineFeed (); return 1;
X    case '\007':
X	PutStr (BL);
X	if (!display)
X	    curr->bell = 1;
X	return 1;
X    case '\t':
X	ForwardTab (); return 1;
X    }
X    return 0;
X}
X
Xstatic DoESC (c, intermediate) {
X    switch (intermediate) {
X    case 0:
X	switch (c) {
X	case 'E':
X	    Return ();
X	    LineFeed ();
X	    break;
X	case 'D':
X	    LineFeed (); 
X	    break;
X	case 'M':
X	    ReverseLineFeed ();
X	    break;
X	case 'H':
X	    curr->tabs[curr->x] = 1;
X	    break;
X	case '7':
X	    SaveCursor ();
X	    break;
X	case '8':
X	    RestoreCursor ();
X	    break;
X	case 'c':
X	    ClearScreen ();
X	    Goto (curr->y, curr->x, 0, 0);
X	    NewRendition (GlobalAttr, 0);
X	    SetRendition (0);
X	    if (curr->insert)
X		InsertMode (0);
X	    if (curr->keypad)
X		KeypadMode (0);
X	    if (CS)
X		PutStr (tgoto (CS, rows-1, 0));
X	    ResetScreen (curr);
X	    break;
X	case '=':
X	    KeypadMode (1);
X	    curr->keypad = 1;
X	    break;
X	case '>':
X	    KeypadMode (0);
X	    curr->keypad = 0;
X	    break;
X	}
X	break;
X    case '#':
X	switch (c) {
X	case '8':
X	    FillWithEs ();
X	    break;
X	}
X	break;
X    }
X}
X
Xstatic DoCSI (c, intermediate) {
X    register i, a1 = args[0], a2 = args[1];
X
X    if (NumArgs >= MAXARGS)
X	NumArgs = MAXARGS;
X    for (i = 0; i < NumArgs; ++i)
X	if (args[i] == 0)
X	    GotArg[i] = 0;
X    switch (intermediate) {
X    case 0:
X	switch (c) {
X	case 'H': case 'f':
X	    if (!GotArg[0]) a1 = 1;
X	    if (!GotArg[1]) a2 = 1;
X	    if (curr->origin)
X		a1 += curr->top;
X	    if (a1 < 1)
X		a1 = 1;
X	    if (a1 > rows)
X		a1 = rows;
X	    if (a2 < 1)
X		a2 = 1;
X	    if (a2 > cols)
X		a2 = cols;
X	    a1--; a2--;
X	    Goto (curr->y, curr->x, a1, a2);
X	    curr->y = a1;
X	    curr->x = a2;
X	    break;
X	case 'J':
X	    if (!GotArg[0] || a1 < 0 || a1 > 2)
X		a1 = 0;
X	    switch (a1) {
X	    case 0:
X		ClearToEOS (); break;
X	    case 1:
X		ClearFromBOS (); break;
X	    case 2:
X		ClearScreen ();
X		Goto (0, 0, curr->y, curr->x);
X		break;
X	    }
X	    break;
X	case 'K':
X	    if (!GotArg[0] || a1 < 0 || a2 > 2)
X		a1 = 0;
X	    switch (a1) {
X	    case 0:
X		ClearToEOL (); break;
X	    case 1:
X		ClearFromBOL (); break;
X	    case 2:
X		ClearLine (); break;
X	    }
X	    break;
X	case 'A':
X	    CursorUp (GotArg[0] ? a1 : 1);
X	    break;
X	case 'B':
X	    CursorDown (GotArg[0] ? a1 : 1);
X	    break;
X	case 'C':
X	    CursorRight (GotArg[0] ? a1 : 1);
X	    break;
X	case 'D':
X	    CursorLeft (GotArg[0] ? a1 : 1);
X	    break;
X	case 'm':
X	    SelectRendition ();
X	    break;
X	case 'g':
X	    if (!GotArg[0] || a1 == 0)
X		curr->tabs[curr->x] = 0;
X	    else if (a1 == 3)
X		bzero (curr->tabs, cols);
X	    break;
X	case 'r':
X	    if (!CS)
X		break;
X	    if (!GotArg[0]) a1 = 1;
X	    if (!GotArg[1]) a2 = rows;
X	    if (a1 < 1 || a2 > rows || a1 >= a2)
X		break;
X	    curr->top = a1-1;
X	    curr->bot = a2-1;
X	    PutStr (tgoto (CS, curr->bot, curr->top));
X	    if (curr->origin) {
X		Goto (-1, -1, curr->top, 0);
X		curr->y = curr->top;
X		curr->x = 0;
X	    } else {
X		Goto (-1, -1, 0, 0);
X		curr->y = curr->x = 0;
X	    }
X	    break;
X	case 'I':
X	    if (!GotArg[0]) a1 = 1;
X	    while (a1--)
X		ForwardTab ();
X	    break;
X	case 'Z':
X	    if (!GotArg[0]) a1 = 1;
X	    while (a1--)
X		BackwardTab ();
X	    break;
X	case 'L':
X	    InsertLine (GotArg[0] ? a1 : 1);
X	    break;
X	case 'M':
X	    DeleteLine (GotArg[0] ? a1 : 1);
X	    break;
X	case 'P':
X	    DeleteChar (GotArg[0] ? a1 : 1);
X	    break;
X	case '@':
X	    InsertChar (GotArg[0] ? a1 : 1);
X	    break;
X	case 'h':
X	    SetMode (1);
X	    break;
X	case 'l':
X	    SetMode (0);
X	    break;
X	}
X	break;
X    case '?':
X	if (c != 'h' && c != 'l')
X	    break;
X	if (!GotArg[0])
X	    break;
X	i = (c == 'h');
X	if (a1 == 5) {
X	    if (i) {
X		curr->vbwait = 1;
X	    } else {
X		if (curr->vbwait)
X		    PutStr (VB);
X		curr->vbwait = 0;
X	    }
X	} else if (a1 == 6) {
X	    curr->origin = i;
X	    if (curr->origin) {
X		Goto (curr->y, curr->x, curr->top, 0);
X		curr->y = curr->top;
X		curr->x = 0;
X	    } else {
X		Goto (curr->y, curr->x, 0, 0);
X		curr->y = curr->x = 0;
X	    }
X	} else if (a1 == 7) {
X	    curr->wrap = i;
X	}
X	break;
X    }
X}
X
Xstatic PutChar (c) {
X    putchar (c);
X}
X
Xstatic PutStr (s) char *s; {
X    if (display && s)
X	tputs (s, 1, PutChar);
X}
X
Xstatic SetChar (c) register c; {
X    register struct win *p = curr;
X
X    p->image[p->y][p->x] = c;
X    p->attr[p->y][p->x] = p->LocalAttr;
X}
X
Xstatic StartString (type) enum string_t type; {
X    curr->StringType = type;
X    curr->stringp = curr->string;
X    curr->state = STR;
X}
X
Xstatic AddChar (c) {
X    if (curr->stringp > curr->string+MAXSTR-1)
X	curr->state = LIT;
X    else
X	*(curr->stringp)++ = c;
X}
X
X/* Insert mode is a toggle on some terminals, so we need this hack:
X */
XInsertMode (on) {
X    if (on) {
X	if (!insert)
X	    PutStr (IM);
X    } else if (insert)
X	PutStr (EI);
X    insert = on;
X}
X
X/* ...and maybe keypad application mode is a toggle, too:
X */
XKeypadMode (on) {
X    if (on) {
X	if (!keypad)
X	    PutStr (KS);
X    } else if (keypad)
X	PutStr (KE);
X    keypad = on;
X}
X
Xstatic SaveCursor () {
X    curr->saved = 1;
X    curr->Saved_x = curr->x;
X    curr->Saved_y = curr->y;
X    curr->SavedLocalAttr = curr->LocalAttr;
X}
X
Xstatic RestoreCursor () {
X    if (curr->saved) {
X	curr->LocalAttr = curr->SavedLocalAttr;
X	NewRendition (GlobalAttr, curr->LocalAttr);
X	GlobalAttr = curr->LocalAttr;
X	Goto (curr->y, curr->x, curr->Saved_y, curr->Saved_x);
X	curr->x = curr->Saved_x;
X	curr->y = curr->Saved_y;
X    }
X}
X
X/*ARGSUSED*/
XCountChars (c) {
X    StrCost++;
X}
X
XCalcCost (s) register char *s; {
X    if (s) {
X	StrCost = 0;
X	tputs (s, 1, CountChars);
X	return StrCost;
X    } else return EXPENSIVE;
X}
X
Xstatic Goto (y1, x1, y2, x2) {
X    register dy, dx;
X    register cost = 0;
X    register char *s;
X    int CMcost, n, m;
X    enum move_t xm = M_NONE, ym = M_NONE;
X
X    if (!display)
X	return;
X    if (x1 == cols || x2 == cols) {
X	if (x2 == cols) --x2;
X	goto DoCM;
X    }
X    dx = x2 - x1;
X    dy = y2 - y1;
X    if (dy == 0 && dx == 0)
X	return;
X    if (y1 == -1 || x1 == -1) {
XDoCM:
X	PutStr (tgoto (CM, x2, y2));
X	return;
X    }
X    CMcost = CalcCost (tgoto (CM, x2, y2));
X    if (dx > 0) {
X	if ((n = RewriteCost (y1, x1, x2)) < (m = dx * NDcost)) {
X	    cost = n;
X	    xm = M_RW;
X	} else {
X	    cost = m;
X	    xm = M_RI;
X	}
X    } else if (dx < 0) {
X	cost = -dx * LEcost;
X	xm = M_LE;
X    }
X    if (dx && (n = RewriteCost (y1, 0, x2) + CRcost) < cost) {
X	cost = n;
X	xm = M_CR;
X    }
X    if (cost >= CMcost)
X	goto DoCM;
X    if (dy > 0) {
X	cost += dy * DOcost;
X	ym = M_DO;
X    } else if (dy < 0) {
X	cost += -dy * UPcost;
X	ym = M_UP;
X    }
X    if (cost >= CMcost)
X	goto DoCM;
X    if (xm != M_NONE) {
X	if (xm == M_LE || xm == M_RI) {
X	    if (xm == M_LE) {
X		s = BC; dx = -dx;
X	    } else s = ND;
X	    while (dx-- > 0)
X		PutStr (s);
X	} else {
X	    if (xm == M_CR) {
X		PutStr (CR);
X		x1 = 0;
X	    }
X	    if (x1 < x2) {
X		if (curr->insert)
X		    InsertMode (0);
X		for (s = curr->image[y1]+x1; x1 < x2; x1++, s++)
X		    putchar (*s);
X		if (curr->insert)
X		    InsertMode (1);
X	    }
X	}
X    }
X    if (ym != M_NONE) {
X	if (ym == M_UP) {
X	    s = UP; dy = -dy;
X	} else s = DO;
X	while (dy-- > 0)
X	    PutStr (s);
X    }
X}
X
Xstatic RewriteCost (y, x1, x2) {
X    register cost, dx;
X    register char *p = curr->attr[y]+x1;
X
X    if (AM && y == rows-1 && x2 == cols-1)
X	return EXPENSIVE;
X    cost = dx = x2 - x1;
X    if (dx == 0)
X	return 0;
X    if (curr->insert)
X	cost += EIcost + IMcost;
X    do {
X	if (*p++ != GlobalAttr)
X	    return EXPENSIVE;
X    } while (--dx);
X    return cost;
X}
X
Xstatic BackSpace () {
X    if (curr->x > 0) {
X	if (curr->x < cols) {
X	    if (BC)
X		PutStr (BC);
X	    else
X		Goto (curr->y, curr->x, curr->y, curr->x-1);
X	}
X	curr->x--;
X    }
X}
X
Xstatic Return () {
X    if (curr->x > 0) {
X	curr->x = 0;
X	PutStr (CR);
X    }
X}
X
Xstatic LineFeed () {
X    if (curr->y == curr->bot) {
X	ScrollUpMap (curr->image);
X	ScrollUpMap (curr->attr);
X    } else if (curr->y < rows-1) {
X	curr->y++;
X    }
X    PutStr (NL);
X}
X
Xstatic ReverseLineFeed () {
X    if (curr->y == curr->top) {
X	ScrollDownMap (curr->image);
X	ScrollDownMap (curr->attr);
X	if (SR) {
X	    PutStr (SR);
X	} else if (AL) {
X	    Goto (curr->top, curr->x, curr->top, 0);
X	    PutStr (AL);
X	    Goto (curr->top, 0, curr->top, curr->x);
X	} else Redisplay ();
X    } else if (curr->y > 0) {
X	CursorUp (1);
X    }
X}
X
Xstatic InsertAChar (c) {
X    register y = curr->y, x = curr->x;
X
X    if (x == cols)
X	x--;
X    bcopy (curr->image[y], OldImage, cols);
X    bcopy (curr->attr[y], OldAttr, cols);
X    bcopy (curr->image[y]+x, curr->image[y]+x+1, cols-x-1);
X    bcopy (curr->attr[y]+x, curr->attr[y]+x+1, cols-x-1);
X    SetChar (c);
X    if (!display)
X	return;
X    if (IC || IM) {
X	if (!curr->insert)
X	    InsertMode (1);
X	PutStr (IC);
X	putchar (c);
X	if (!curr->insert)
X	    InsertMode (0);
X    } else {
X	RedisplayLine (OldImage, OldAttr, y, x, cols-1);
X	++x;
X	Goto (y, last_x, y, x);
X    }
X}
X
Xstatic InsertChar (n) {
X    register i, y = curr->y, x = curr->x;
X
X    if (x == cols)
X	return;
X    bcopy (curr->image[y], OldImage, cols);
X    bcopy (curr->attr[y], OldAttr, cols);
X    if (n > cols-x)
X	n = cols-x;
X    bcopy (curr->image[y]+x, curr->image[y]+x+n, cols-x-n);
X    bcopy (curr->attr[y]+x, curr->attr[y]+x+n, cols-x-n);
X    ClearInLine (0, y, x, x+n-1);
X    if (!display)
X	return;
X    if (IC || IM) {
X	if (!curr->insert)
X	    InsertMode (1);
X	for (i = n; i; i--) {
X	    PutStr (IC);
X	    putchar (' ');
X	}
X	if (!curr->insert)
X	    InsertMode (0);
X	Goto (y, x+n, y, x);
X    } else {
X	RedisplayLine (OldImage, OldAttr, y, x, cols-1);
X	Goto (y, last_x, y, x);
X    }
X}
X
Xstatic DeleteChar (n) {
X    register i, y = curr->y, x = curr->x;
X
X    if (x == cols)
X	return;
X    bcopy (curr->image[y], OldImage, cols);
X    bcopy (curr->attr[y], OldAttr, cols);
X    if (n > cols-x)
X	n = cols-x;
X    bcopy (curr->image[y]+x+n, curr->image[y]+x, cols-x-n);
X    bcopy (curr->attr[y]+x+n, curr->attr[y]+x, cols-x-n);
X    ClearInLine (0, y, cols-n, cols-1);
X    if (!display)
X	return;
X    if (DC) {
X	for (i = n; i; i--)
X	    PutStr (DC);
X    } else {
X	RedisplayLine (OldImage, OldAttr, y, x, cols-1);
X	Goto (y, last_x, y, x);
X    }
X}
X
Xstatic DeleteLine (n) {
X    register i, old = curr->top;
X
X    if (n > curr->bot-curr->y+1)
X	n = curr->bot-curr->y+1;
X    curr->top = curr->y;
X    for (i = n; i; i--) {
X	ScrollUpMap (curr->image);
X	ScrollUpMap (curr->attr);
X    }
X    if (DL) {
X	Goto (curr->y, curr->x, curr->y, 0);
X	for (i = n; i; i--)
X	    PutStr (DL);
X	Goto (curr->y, 0, curr->y, curr->x);
X    } else if (CS) {
X	PutStr (tgoto (CS, curr->bot, curr->top));
X	Goto (-1, -1, curr->bot, 0);
X	for (i = n; i; i--)
X	    PutStr (SF);
X	PutStr (tgoto (CS, curr->bot, old));
X	Goto (-1, -1, curr->y, curr->x);
X    } else Redisplay ();
X    curr->top = old;
X}
X
Xstatic InsertLine (n) {
X    register i, old = curr->top;
X
X    if (n > curr->bot-curr->y+1)
X	n = curr->bot-curr->y+1;
X    curr->top = curr->y;
X    for (i = n; i; i--) {
X	ScrollDownMap (curr->image);
X	ScrollDownMap (curr->attr);
X    }
X    if (AL) {
X	Goto (curr->y, curr->x, curr->y, 0);
X	for (i = n; i; i--)
X	    PutStr (AL);
X	Goto (curr->y, 0, curr->y, curr->x);
X    } else if (CS && SR) {
X	PutStr (tgoto (CS, curr->bot, curr->top));
X	Goto (-1, -1, curr->y, 0);
X	for (i = n; i; i--)
X	    PutStr (SR);
X	PutStr (tgoto (CS, curr->bot, old));
X	Goto (-1, -1, curr->y, curr->x);
X    } else Redisplay ();
X    curr->top = old;
X}
X
Xstatic ScrollUpMap (pp) char **pp; {
X    register char *tmp = pp[curr->top];
X
X    bcopy (pp+curr->top+1, pp+curr->top,
X	(curr->bot-curr->top) * sizeof (char *));
X    if (pp == curr->image)
X	bclear (tmp, cols);
X    else
X	bzero (tmp, cols);
X    pp[curr->bot] = tmp;
X}
X
Xstatic ScrollDownMap (pp) char **pp; {
X    register char *tmp = pp[curr->bot];
X
X    bcopy (pp+curr->top, pp+curr->top+1,
X	(curr->bot-curr->top) * sizeof (char *));
X    if (pp == curr->image)
X	bclear (tmp, cols);
X    else
X	bzero (tmp, cols);
X    pp[curr->top] = tmp;
X}
X
Xstatic ForwardTab () {
X    register x = curr->x;
X
X    if (curr->tabs[x] && x < cols-1)
X	++x;
X    while (x < cols-1 && !curr->tabs[x])
X	x++;
X    Goto (curr->y, curr->x, curr->y, x);
X    curr->x = x;
X}
X
Xstatic BackwardTab () {
X    register x = curr->x;
X
X    if (curr->tabs[x] && x > 0)
X	x--;
X    while (x > 0 && !curr->tabs[x])
X	x--;
X    Goto (curr->y, curr->x, curr->y, x);
X    curr->x = x;
X}
X
Xstatic ClearScreen () {
X    register i;
X
X    PutStr (CL);
X    for (i = 0; i < rows; ++i) {
X	bclear (curr->image[i], cols);
X	bzero (curr->attr[i], cols);
X    }
X}
X
Xstatic ClearFromBOS () {
X    register n, y = curr->y, x = curr->x;
X
X    for (n = 0; n < y; ++n)
X	ClearInLine (1, n, 0, cols-1);
X    ClearInLine (1, y, 0, x);
X    Goto (curr->y, curr->x, y, x);
X    curr->y = y; curr->x = x;
X}
X
Xstatic ClearToEOS () {
X    register n, y = curr->y, x = curr->x;
X
X    if (CD)
X	PutStr (CD);
X    ClearInLine (!CD, y, x, cols-1);
X    for (n = y+1; n < rows; n++)
X	ClearInLine (!CD, n, 0, cols-1);
X    Goto (curr->y, curr->x, y, x);
X    curr->y = y; curr->x = x;
X}
X
Xstatic ClearLine () {
X    register y = curr->y, x = curr->x;
X
X    ClearInLine (1, y, 0, cols-1);
X    Goto (curr->y, curr->x, y, x);
X    curr->y = y; curr->x = x;
X}
X
Xstatic ClearToEOL () {
X    register y = curr->y, x = curr->x;
X
X    ClearInLine (1, y, x, cols-1);
X    Goto (curr->y, curr->x, y, x);
X    curr->y = y; curr->x = x;
X}
X
Xstatic ClearFromBOL () {
X    register y = curr->y, x = curr->x;
X
X    ClearInLine (1, y, 0, x);
X    Goto (curr->y, curr->x, y, x);
X    curr->y = y; curr->x = x;
X}
X
Xstatic ClearInLine (displ, y, x1, x2) {
X    register i, n;
X
X    if (x1 == cols) x1--;
X    if (x2 == cols) x2--;
X    if (n = x2 - x1 + 1) {
X	bclear (curr->image[y]+x1, n);
X	bzero (curr->attr[y]+x1, n);
X	if (displ && display) {
X	    if (x2 == cols-1 && CE) {
X		Goto (curr->y, curr->x, y, x1);
X		curr->y = y; curr->x = x1;
X		PutStr (CE);
X		return;
X	    }
X	    if (y == rows-1 && AM)
X		--n;
X	    if (n == 0)
X		return;
X	    SaveAttr ();
X	    Goto (curr->y, curr->x, y, x1);
X	    for (i = n; i > 0; i--)
X		putchar (' ');
X	    curr->y = y; curr->x = x1 + n;
X	    RestoreAttr ();
X	}
X    }
X}
X
Xstatic CursorRight (n) register n; {
X    register x = curr->x;
X
X    if (x == cols)
X	return;
X    if ((curr->x += n) >= cols)
X	curr->x = cols-1;
X    Goto (curr->y, x, curr->y, curr->x);
X}
X
Xstatic CursorUp (n) register n; {
X    register y = curr->y;
X
X    if ((curr->y -= n) < curr->top)
X	curr->y = curr->top;
X    Goto (y, curr->x, curr->y, curr->x);
X}
X
Xstatic CursorDown (n) register n; {
X    register y = curr->y;
X
X    if ((curr->y += n) > curr->bot)
X	curr->y = curr->bot;
X    Goto (y, curr->x, curr->y, curr->x);
X}
X
Xstatic CursorLeft (n) register n; {
X    register x = curr->x;
X
X    if ((curr->x -= n) < 0)
X	curr->x = 0;
X    Goto (curr->y, x, curr->y, curr->x);
X}
X
Xstatic SetMode (on) {
X    register i;
X
X    for (i = 0; i < NumArgs; ++i) {
X	switch (args[i]) {
X	case 4:
X	    curr->insert = on;
X	    InsertMode (on);
X	    break;
X	}
X    }
X}
X
Xstatic SelectRendition () {
X    register i, old = GlobalAttr;
X
X    if (NumArgs == 0)
X	SetRendition (0);
X    else for (i = 0; i < NumArgs; ++i)
X	SetRendition (args[i]);
X    NewRendition (old, GlobalAttr);
X}
X
Xstatic SetRendition (n) register n; {
X    switch (n) {
X    case 0:
X	GlobalAttr = 0; break;
X    case 1:
X	GlobalAttr |= A_BD; break;
X    case 2:
X	GlobalAttr |= A_DI; break;
X    case 3:
X	GlobalAttr |= A_SO; break;
X    case 4:
X	GlobalAttr |= A_US; break;
X    case 5:
X	GlobalAttr |= A_BL; break;
X    case 7:
X	GlobalAttr |= A_RV; break;
X    case 22:
X	GlobalAttr &= ~(A_BD|A_SO|A_DI); break;
X    case 23:
X	GlobalAttr &= ~A_SO; break;
X    case 24:
X	GlobalAttr &= ~A_US; break;
X    case 25:
X	GlobalAttr &= ~A_BL; break;
X    case 27:
X	GlobalAttr &= ~A_RV; break;
X    }
X    curr->LocalAttr = GlobalAttr;
X}
X
Xstatic NewRendition (old, new) register old, new; {
X    register i;
X
X    if (old == new)
X	return;
X    for (i = 1; i <= A_MAX; i <<= 1) {
X	if ((old & i) && !(new & i)) {
X	    PutStr (UE);
X	    PutStr (SE);
X	    PutStr (ME);
X	    if (new & A_US) PutStr (US);
X	    if (new & A_SO) PutStr (SO);
X	    if (new & A_BL) PutStr (MB);
X	    if (new & A_BD) PutStr (MD);
X	    if (new & A_DI) PutStr (MH);
X	    if (new & A_RV) PutStr (MR);
X	    return;
X	}
X    }
X    if ((new & A_US) && !(old & A_US))
X	PutStr (US);
X    if ((new & A_SO) && !(old & A_SO))
X	PutStr (SO);
X    if ((new & A_BL) && !(old & A_BL))
X	PutStr (MB);
X    if ((new & A_BD) && !(old & A_BD))
X	PutStr (MD);
X    if ((new & A_DI) && !(old & A_DI))
X	PutStr (MH);
X    if ((new & A_RV) && !(old & A_RV))
X	PutStr (MR);
X}
X
Xstatic SaveAttr () {
X    NewRendition (GlobalAttr, 0);
X    if (curr->insert)
X	InsertMode (0);
X}
X
Xstatic RestoreAttr () {
X    NewRendition (0, GlobalAttr);
X    if (curr->insert)
X	InsertMode (1);
X}
X
Xstatic FillWithEs () {
X    register i;
X    register char *p, *ep;
X
X    curr->y = curr->x = 0;
X    NewRendition (GlobalAttr, 0);
X    SetRendition (0);
X    for (i = 0; i < rows; ++i) {
X	bzero (curr->attr[i], cols);
X	p = curr->image[i];
X	ep = p + cols;
X	for ( ; p < ep; ++p)
X	    *p = 'E';
X    }
X    Redisplay ();
X}
X
Xstatic Redisplay () {
X    register i;
X
X    PutStr (CL);
X    TmpAttr = GlobalAttr;
X    last_x = last_y = 0;
X    for (i = 0; i < rows; ++i)
X	DisplayLine (blank, null, curr->image[i], curr->attr[i], i, 0, cols-1);
X    NewRendition (TmpAttr, GlobalAttr);
X    Goto (last_y, last_x, curr->y, curr->x);
X}
X
Xstatic DisplayLine (os, oa, s, as, y, from, to)
X	register char *os, *oa, *s, *as; {
X    register i, x, a;
X
X    if (to == cols)
X	--to;
X    if (AM && y == rows-1 && to == cols-1)
X	--to;
X    a = TmpAttr;
X    for (x = i = from; i <= to; ++i, ++x) {
X	if (s[i] == os[i] && as[i] == oa[i] && as[i] == a)
X	    continue;
X	Goto (last_y, last_x, y, x);
X	last_y = y;
X	last_x = x;
X	if ((a = as[i]) != TmpAttr) {
X	    NewRendition (TmpAttr, a);
X	    TmpAttr = a;
X	}
X	putchar (s[i]);
X	last_x++;
X    }
X}
X
Xstatic RedisplayLine (os, oa, y, from, to) char *os, *oa; {
X    if (curr->insert)
X	InsertMode (0);
X    NewRendition (GlobalAttr, 0);
X    TmpAttr = 0;
X    last_y = y;
X    last_x = from;
X    DisplayLine (os, oa, curr->image[y], curr->attr[y], y, from, to);
X    NewRendition (TmpAttr, GlobalAttr);
X    if (curr->insert)
X	InsertMode (1);
X}
X
Xstatic MakeBlankLine (p, n) register char *p; register n; {
X    do *p++ = ' ';
X    while (--n);
X}
X
XMakeStatus (msg, wp) char *msg; struct win *wp; {
X    struct win *ocurr = curr;
X    int odisplay = display;
X    register char *s, *t;
X    register max = AM ? cols-1 : cols;
X
X    for (s = t = msg; *s && t - msg < max; ++s)
X	if (*s >= ' ' && *s <= '~')
X	    *t++ = *s;
X    *t = '\0';
X    curr = wp;
X    display = 1;
X    if (status) {
X	if (time ((time_t *)0) - TimeDisplayed < 2)
X	    sleep (1);
X	RemoveStatus (wp);
X    }
X    if (t > msg) {
X	status = 1;
X	StatLen = t - msg;
X	Goto (curr->y, curr->x, rows-1, 0);
X	NewRendition (GlobalAttr, A_SO);
X	if (curr->insert)
X	    InsertMode (0);
X	printf ("%s", msg);
X	if (curr->insert)
X	    InsertMode (1);
X	NewRendition (A_SO, GlobalAttr);
X	fflush (stdout);
X	time (&TimeDisplayed);
X    }
X    curr = ocurr;
X    display = odisplay;
X}
X
XRemoveStatus (p) struct win *p; {
X    struct win *ocurr = curr;
X    int odisplay = display;
X
X    if (!status)
X	return;
X    status = 0;
X    curr = p;
X    display = 1;
X    Goto (-1, -1, rows-1, 0);
X    RedisplayLine (null, null, rows-1, 0, StatLen);
X    Goto (rows-1, last_x, curr->y, curr->x);
X    curr = ocurr;
X    display = odisplay;
X}
END_OF_FILE
if test 30846 -ne `wc -c <'ansi.c'`; then
    echo shar: \"'ansi.c'\" unpacked with wrong size!
fi
# end of 'ansi.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
  |  Wolfgang Ocker          |  ocker@lan.informatik.tu-muenchen.dbp.de  |
  |  Lochhauserstr. 35a      |      pyramid!tmpmbx!recco!weo (home)      |
  |  D-8039 Puchheim         |     Technische Universitaet Muenchen      |
  |  Voice: +49 89 80 77 02  |          Huh, What? Where am I?           |