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? |