Window source #4 [of 0-7]: display.c
chris at umcp-cs.UUCP
chris at umcp-cs.UUCP
Sun Jul 3 17:16:29 AEST 1983
: 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 'Extracting display.c'
sed 's/^X//' <<'//go.sysin dd *' >display.c
X/* Copyright (c) 1983 University of Maryland Computer Science Department */
X
X/* Ultra-hot screen management package
X Original code copyright (c) James Gosling, January 1980 */
X
X/* Severe munging and destruction by Chris Torek, 1982,1983 */
X
X/****************************************************************
X
X
X
X /-------------\
X / \
X / \
X / \
X | XXXX XXXX |
X | XXXX XXXX |
X | XXX XXX |
X \ X /
X --\ XXX /--
X | | XXX | |
X | | | |
X | I I I I I I I |
X | I I I I I I |
X \ /
X -- --
X \-------/
X XXX XXX
X XXXXX XXXXX
X XXXXXXXXX XXXXXXXXXX
X XXXXX XXXXX
X XXXXXXX
X XXXXX XXXXX
X XXXXXXXXX XXXXXXXXXX
X XXXXX XXXXX
X XXX XXX
X
X **************
X * BEWARE!! *
X **************
X
X All ye who enter here:
X Most of the code in this module
X is twisted beyond belief!
X
X Tread carefully.
X
X If you think you understand it,
X You Don't,
X So Look Again.
X
X ****************************************************************/
X
X/* DJH -- Added Ding() for bell */
X
X#include "win.h"
X#include "Trm.h"
X#include <stdio.h>
X#include <sgtty.h>
X
X#ifdef lint
X#undef VAX /* Don't let lint know about Vax dependent stuff */
X#endif
X
X/* the following macros are used to access terminal specific routines.
X Really, no one outside of display.c should be using them, except for
X the initialize/cleanup routines */
X#define topos (*W_tt.t_topos)
X#define reset (*W_tt.t_reset)
X#define INSmode (*W_tt.t_INSmode)
X#define insertlines (*W_tt.t_inslines)
X#define deletelines (*W_tt.t_dellines)
X#define blanks (*W_tt.t_blanks)
X#define wipeline (*W_tt.t_wipeline)
X#define wipescreen (*W_tt.t_wipescreen)
X#define deletechars (*W_tt.t_delchars)
X#define ScreenWidth (W_tt.t_width)
X#define ScreenLength (W_tt.t_length)
X
X#define MScreenWidth 135
X#define MScreenLength 60
X#define min(a,b) (a<b ? a : b)
X#define max(a,b) (a>b ? a : b)
X#define hidden static
X#define visible
X#define procedure
X#define function
X
Xhidden struct line { /* a line as it appears in a list of
X lines (as in the physical and virtual
X display lists) */
X int hash; /* hash value for this line, 0 if not
X known */
X struct line *next; /* pointer to the next line in a list of
X lines */
X short DrawCost; /* the cost of redrawing this line */
X short length; /* the number of valid characters in the
X line */
X short touched; /* true iff UpdateLine should be done */
X Ch body[MScreenWidth]; /* the actual text of the line */
X}
X *FreeLines; /* free space list */
X
Xhidden WindowSize; /* the number of lines on which line ID
X operations should be done */
Xhidden Ch NullStr[MScreenWidth];/* type Ch equivalent of line of blanks */
Xint baud_rate; /* Terminal speed, so we can calculate
X the number of characters required to
X make the cursor sit still for n secs. */
Xhidden CheckForInput; /* -ve iff UpdateLine should bother
X checking for input */
Xhidden char OneLineBuf[MScreenWidth];/* For use by dumpstring and
X UpdateEasyLine */
X
X/* 'newline' returns a pointer to a new line object, either from the
X free list or from the general unix pool */
Xhidden struct line *newline ()
X{
X register struct line *p = FreeLines;
X register Ch *c;
X
X if (p) {
X FreeLines = p -> next;
X#ifdef DEBUG
X if (p -> hash != 12345) {
X/* register FILE *f = fopen ("EMACS_TRACE", "w");
X topos (23, 1);
X printf ("*****Bogus value in display free list"); */
X FreeLines = 0;
X/* if (f) {
X register int *p1 = ((int *) p) - 10;
X register char *p2 = (char *) p1;
X register i;
X fprintf (f, "Bogus value in display free list at %o\n", p);
X for (i=0; i<25; i++) {
X fprintf (f, "%11o: %011o %9d %03o %03o %03o %03o\n",
X p1, *p1, *p1,
X p2[0], p2[1], p2[2], p2[3]);
X p1++; p2 += 4;
X }
X fclose (f);
X } */
X return newline ();
X }
X#endif
X }
X else {
X static Leakage;
X p = (struct line *) malloc (sizeof *p);
X if (++Leakage>(2*MScreenLength)) printf ("*****Display core leakage!");
X }
X p -> length = 0;
X p -> hash = 0;
X p -> touched = 1;
X for (c = &p -> body[ScreenWidth]; c > p -> body;)
X (--c) -> ch_all = ' ';
X return p;
X}
X
X/* 'ReleaseLine' returns a line object to the free list */
Xhidden procedure ReleaseLine (p)
Xregister struct line *p; {
X if (p) {
X if (p -> hash == 12345) {
X printf("\rBogus re-release!");
X fflush(stdout);
X /* abort(); */
X return;
X }
X p -> next = FreeLines;
X p -> hash = 12345;
X FreeLines = p;
X }
X}
X
Xhidden struct line *PhysScreen[MScreenLength + 1];
X /* the current (physical) screen */
Xhidden struct line *DesiredScreen[MScreenLength + 1];
X /* the desired (virtual) screen */
X
Xvisible int
X ScreenGarbaged, /* set to 1 iff screen content is
X uncertain. */
X InputPending, /* true iff input is known to be pending */
X LastRedisplayPaused,/* true iff last redisplay paused */
X#ifdef DEBUG
X RDdebug, /* line redraw debug switch */
X IDdebug, /* line insertion/deletion debug */
X#endif DEBUG
X WDCurrentLine, /* current line for writing to the
X virtual screen. */
X WDleft; /* number of columns left on the current
X line of the virtual screen. */
Xvisible Ch
X *WDcursor; /* pointer into a line object, indicates
X where to put the next character */
X
X/* 'WDCharAt' returns a pointer to the Ch at position (row,col) in the
X virtual screen. This is purely for the grotesque attributes in
X HP264?s where one must know what attribute is desired after the end
X of a string. */
Xvisible Ch *WDCharAt (row, col) {
X register struct line *p;
X
X if ((p = DesiredScreen[row]) == 0 || p -> length < col)
X return &NullStr[0]; /* blank */
X else
X return &p -> body[col - 1];
X}
X
X/* 'WDsetpos' positions the cursor at position (row,col) in the virtual
X screen */
Xvisible procedure WDsetpos (row, col)
Xregister row,
X col; {
X register struct line *p;
X register n;
X
X if (WDCurrentLine >= 0
X && (p = DesiredScreen[WDCurrentLine]) -> length
X <= (n = ScreenWidth - WDleft))
X p -> length = WDleft > 0 ? n : ScreenWidth;
X if (!DesiredScreen[row])
X DesiredScreen[row] = newline ();
X (p = DesiredScreen[row]) -> hash = 0;
X p -> touched = 1;
X WDcursor = &p -> body[col - 1];
X WDCurrentLine = row;
X WDleft = ScreenWidth + 1 - col;
X}
X
X/* 'WDclearline' positions the cursor at the beginning of the
X indicated line and clears the line (in the image) */
Xvisible procedure WDclearline (row) {
X register Ch *c;
X register struct line *p;
X WDsetpos (row, 1);
X (p = DesiredScreen[row]) -> length = 0;
X for (c = &p -> body[ScreenWidth]; c > p -> body;)
X (--c) -> ch_all = ' ';
X}
X
X
X/* 'hashline' computes a hash value for a line, unless the hash value
X is already known. This hash code has a few important properties:
X - it is independant of the number of leading and trailing spaces
X - it will never be zero
X
X As a side effect, an estimate of the cost of redrawing the line is
X calculated */
Xhidden procedure hashline (p)
Xregister struct line *p; {
X register Ch *c,
X *l;
X register h;
X
X if (!p || p -> hash) {
X if (p && p->hash==12345) printf ("****Free line in screen");
X return;
X }
X h = 0;
X c = p -> body;
X l = &p -> body[p -> length];
X while (--l > c && l -> ch_all == ' ');
X while (c <= l && c -> ch_all == ' ')
X c++;
X p -> DrawCost = l - c + 1;
X while (c <= l)
X h = (h << 5) + h + c++ -> ch_all;
X p -> hash = h!=12345 && h ? h : 1;
X}
X
X/* 1 2 3 4 .... Each Mij represents the minumum cost of
X +---+---+---+---+----- rearranging the first i lines to map onto
X 1 | | | | | the first j lines (the j direction
X +---+---+---+---+----- represents the desired contents of a line,
X 2 | | \| ^ | | i the current contents). The algorithm
X +---+---\-|-+---+----- used is a dynamic programming one, where
X 3 | | <-+Mij| | M[i,j] = min( M[i-1,j],
X +---+---+---+---+----- M[i,j-1]+redraw cost for j,2
X 4 | | | | | M[i-1,j-1]+the cost of
X +---+---+---+---+----- converting line i to line j);
X . | | | | | Line i can be converted to line j by either
X . just drawing j, or if they match, by moving
X . line i to line j (with insert/delete line)
X */
X
Xhidden struct Msquare {
X short cost; /* the value of Mij */
X char fromi,
X fromj; /* the coordinates of the square that
X the optimal move comes from */
X} M[MScreenLength + 1][MScreenLength + 1];
X
Xhidden procedure calcM () {
X register struct Msquare *p;
X register i,
X j,
X movecost,
X cost;
X int reDrawCost,
X idcost,
X leftcost;
X double fidcost;
X
X cost = 0;
X movecost = 0;
X for (i = 0; i <= ScreenLength; i++) {
X p = &M[i][0];
X/* M[i][i].cost = 0; */
X p[i].cost = 0;
X M[0][i].cost = cost + movecost;
X/* M[i][0].cost = movecost; */
X p[0].cost = movecost;
X M[0][i].fromi = 0;
X/* M[0][i].fromj = M[i][i].fromj = i - 1; */
X M[0][i].fromj = p[i].fromj = i - 1;
X/* M[i][0].fromi = M[i][i].fromi = i - 1; */
X p[0].fromi = p[i].fromi = i - 1;
X/* M[i][0].fromj = 0; */
X p[0].fromj = 0;
X movecost += W_tt.t_ILmf * (ScreenLength - i) + W_tt.t_ILov;
X if (DesiredScreen[i + 1])
X cost += DesiredScreen[i + 1] -> DrawCost;
X }
X
X fidcost = W_tt.t_ILmf * (WindowSize + 1) + W_tt.t_ILov;
X for (i = 1; i <= WindowSize; i++)
X {
X p = &M[i][0];
X fidcost -= W_tt.t_ILmf;
X idcost = fidcost;
X for (j = 1; j <= WindowSize; j++) {
X p++;
X/* p = &M[i][j]; */
X cost = DesiredScreen[j] ? DesiredScreen[j] -> DrawCost : 0;
X reDrawCost = cost;
X if (PhysScreen[i] && DesiredScreen[j]
X && PhysScreen[i] -> hash == DesiredScreen[j] -> hash)
X cost = 0;
X/* idcost = W_tt.t_ILmf * (WindowSize - i + 1) + W_tt.t_ILov; */
X/* movecost = M[i - 1][j].cost + (j == WindowSize ? 0 : idcost); */
X movecost = p[-MScreenLength-1].cost
X + (j == WindowSize ? 0 : idcost);
X p -> fromi = i - 1; /* now using movecost for */
X p -> fromj = j; /* the minumum cost. */
X if ((
X/* leftcost = M[i][j - 1].cost */
X leftcost = p[-1].cost
X + (i == WindowSize ? 0 : idcost) + reDrawCost
X ) < movecost) {
X movecost = leftcost;
X p -> fromi = i;
X p -> fromj = j - 1;
X }
X/* cost += M[i - 1][j - 1].cost; */
X cost += p[-MScreenLength-2].cost;
X if (cost < movecost)
X movecost = cost,
X p -> fromi = i - 1, p -> fromj = j - 1;
X p -> cost = movecost;
X }
X }
X}
X
X/* calculate and perform the optimal sequence of insertions/deltions
X given the matrix M from routine calcM */
X
Xhidden procedure CalcID (i, j, InsertsDesired)
Xregister i,
X j; {
X register ni,
X nj;
X register struct Msquare *p = &M[i][j];
X if (i > 0 || j > 0) {
X ni = p -> fromi;
X nj = p -> fromj;
X if (ni == i) {
X CalcID (ni, nj, i != WindowSize ? InsertsDesired + 1 : 0);
X InsertsDesired = 0;
X if (InputPending) {
X if (PhysScreen[j] != DesiredScreen[j])
X ReleaseLine (PhysScreen[j]);
X PhysScreen[j] = 0;
X ReleaseLine (DesiredScreen[j]);
X DesiredScreen[j] = 0;
X LastRedisplayPaused++;
X }
X else {
X UpdateLine ((struct line *) 0, DesiredScreen[j], j);
X if (PhysScreen[j] != DesiredScreen[j])
X ReleaseLine (PhysScreen[j]);
X PhysScreen[j] = DesiredScreen[j];
X DesiredScreen[j] = 0;
X }
X }
X else
X if (nj == j) {
X if (j != WindowSize) {
X register nni,
X dlc = 1;
X for (; ni;) {
X p = &M[ni][nj];
X nni = p -> fromi;
X if (p -> fromj == nj) {
X dlc++;
X ni = nni;
X }
X else
X break;
X }
X topos (i - dlc + 1, 1);
X deletelines (dlc);
X }
X CalcID (ni, nj, 0);
X }
X else {
X register struct line *old = PhysScreen[i];
X#ifdef DOEARLY
X register DoneEarly = 0;
X#endif
X if (old == DesiredScreen[i]) DesiredScreen[i] = 0;
X PhysScreen[i] = 0;
X
X#ifdef DOEARLY
X /* The following hack and all following lines involving the
X variable "DoneEarly" cause the bottom line of the screen to
X be redisplayed before any others if it has changed and it
X would be redrawn in-place. This is purely for Emacs,
X people using this package for other things might want to
X lobotomize this section. */
X if (i == ScreenLength && j == ScreenLength
X/* && old != PhysScreen[j]) { */
X && DesiredScreen[j]) {
X DoneEarly++;
X UpdateLine (old, DesiredScreen[j], j);
X }
X#endif
X CalcID (ni, nj, 0);
X if (InputPending
X#ifdef DOEARLY
X && !DoneEarly
X#endif
X ) {
X if (PhysScreen[j] != old)
X ReleaseLine (PhysScreen[j]);
X if (DesiredScreen[j] != old
X && DesiredScreen[j] != PhysScreen[j])
X ReleaseLine (DesiredScreen[j]);
X PhysScreen[j] = old;
X DesiredScreen[j] = 0;
X LastRedisplayPaused++;
X }
X else {
X if (
X#ifdef DOEARLY
X !DoneEarly &&
X#endif
X (DesiredScreen[j] || i != j))
X UpdateLine (old, DesiredScreen[j], j);
X if (PhysScreen[j] != DesiredScreen[j])
X ReleaseLine (PhysScreen[j]);
X if (old != DesiredScreen[j] && old != PhysScreen[j])
X ReleaseLine (old);
X PhysScreen[j] = DesiredScreen[j];
X DesiredScreen[j] = 0;
X }
X }
X }
X if (InsertsDesired) {
X topos (j + 1, 1);
X insertlines (InsertsDesired);
X }
X}
X
X/* modify current screen line 'old' to match desired line 'new',
X the old line is at position ln. Each line
X is scanned and partitioned into 4 regions:
X
X <osp><----m1-----><-od--><----m2----->
X old: " Twas brillig and the slithy toves"
X new: " Twas brillig where a slithy toves"
X <-nsp--><----m1-----><-nd--><----m2----->
X
X nsp, osp - number of leading spaces on each line
X m1 - length of a leading matching sequence
X m2 - length of a trailing matching sequence
X nd, od - length of the differing sequences
X */
Xhidden procedure UpdateLine (old, new, ln)
Xregister struct line *old,
X *new; {
X register Ch *op,
X *np,
X *ol,
X *nl;
X Ch *Iop, *Inp; /* for saving initial values */
X int osp,
X nsp,
X m1,
X m2,
X od,
X nd,
X t,
X OldLineWipeTo,
X rv = 1;
X
X if (old == new)
X return 0; /* did nothing */
X if (old) {
X op = old -> body;
X ol = &old -> body[OldLineWipeTo = old -> length];
X }
X else
X op = NullStr, ol = op, OldLineWipeTo = 1;
X if (new) {
X np = new -> body;
X nl = &new -> body[new -> length];
X }
X else
X np = NullStr, nl = np;
X
X/* ACT 11-Nov-1982 Do cheap update if obvious that fanciness goes nowhere */
X
X if (!W_tt.t_needspaces && np != NullStr && op == NullStr) {
X UpdateEasyLine (ln, np, nl);
X goto cleanup;
X }
X Inp = np, Iop = op;
X osp = 0, nsp = 0, m1 = 0, m2 = 0;
X
X/* calculate the magic parameters */
X while ((--ol) -> ch_all == ' ' && ol >= op)
X --OldLineWipeTo;
X while ((--nl) -> ch_all == ' ' && nl >= np)
X --new -> length;
X while (op -> ch_all == ' ' && op <= ol)
X op++, osp++;
X while (np -> ch_all == ' ' && np <= nl)
X np++, nsp++;
X if (ol < op && !W_tt.t_needspaces)
X osp = nsp;
X while (op -> ch_all == np -> ch_all && op <= ol && np <= nl)
X op++, np++, m1++;
X while (ol -> ch_all == nl -> ch_all && op <= ol && np <= nl)
X ol--, nl--, m2++;
X od = ol - op + 1;
X nd = nl - np + 1;
X
X/* forget matches which would be expensive to capitalize on */
X if (m1 || m2) {
X register int c0,
X c1,
X c2,
X c3;
X c0 = nsp + m1 + m2;
X if (c1 = nsp - osp)
X c1 = c1<0 ? W_tt.t_DCov - c1*W_tt.t_DCmf
X : W_tt.t_ICov + c1*W_tt.t_ICmf;
X if (c3 = nd - od)
X c3 = c3<0 ? W_tt.t_DCov - c3*W_tt.t_DCmf
X : W_tt.t_ICov + c3*W_tt.t_ICmf;
X if (c2 = (nsp + nd) - (osp + od))
X c2 = c2<0 ? W_tt.t_DCov - c2*W_tt.t_DCmf
X : W_tt.t_ICov + c2*W_tt.t_ICmf;
X c3 += c1;
X c1 += m2;
X c2 += m1;
X if (m2 && (c0 < c2 && c0 < c3 || c1 < c2 && c1 < c3)) {
X nd += m2;
X od += m2;
X ol += m2;
X nl += m2;
X m2 = 0;
X }
X if (m1 && (c0 < c1 && c0 < c3 || c2 < c1 && c2 < c3)) {
X nd += m1;
X od += m1;
X np -= m1;
X op -= m1;
X m1 = 0;
X }
X }
X#ifdef DEBUG
X if (RDdebug && (m1 || m2 || nd || od)) {
X fprintf (stderr,"%2d nsp=%2d osp=%2d m1=%2d nd=%2d od=%2d m2=%2d\n",
X ln, nsp, osp, m1, nd, od, m2);
X }
X#endif
X if (m1 == 0)
X if (m2 == 0) {
X if (od == 0 && nd == 0) {
X rv = 0; /* Jackpot! */
X goto cleanup;
X }
X INSmode (0);
X if (W_tt.t_needspaces) {
X if (nsp > osp) {
X topos (ln, min (nsp, osp) + 1);
X (*W_tt.t_modes) (0);
X blanks (nsp - osp);
X }
X dumpstring (np, nl);
X }
X else
X dumps2 (Inp, nl, Iop, ln, 0);
X if (nsp + nd < osp + od) {
X topos (ln, nsp + nd + 1);
X wipeline (0, OldLineWipeTo);
X }
X }
X else { /* m1==0 && m2!=0 && (nd!=0 || od!=0) */
X t = (nsp + nd) - (osp + od);
X topos (ln, min (nsp, osp) + 1);
X if (nsp > osp)
X np -= nsp - osp;
X if (t >= 0) {
X if (nl - t >= np) {
X INSmode (0);
X if (W_tt.t_needspaces)
X dumpstring (np, nl - t);
X else
X dumps2 (Inp, nl - t, Iop, ln, np - Inp);
X if (t > 0)
X topos (ln, nl - t - Inp + 1);
X }
X if (t > 0)
X INSmode (1), dumpstring (nl - t + 1, nl);
X }
X else {
X INSmode (0);
X if (W_tt.t_needspaces)
X dumpstring (np, nl);
X else
X dumps2 (Inp, nl, Iop, ln, np - Inp);
X topos (ln, nsp + nd + 1);
X deletechars (-t);
X }
X }
X else { /* m1!=0 */
X register lsp = osp;
X if (nsp < osp) {
X topos (ln, 1);
X deletechars (osp - nsp);
X lsp = nsp;
X }
X if (m2 == 0) {
X if (nd == 0 && od == 0) {
X if (nsp > osp) {
X topos (ln, 1);
X INSmode (1);
X (*W_tt.t_modes) (0);
X blanks (nsp - osp);
X }
X goto cleanup;
X }
X#ifndef notdef
X if (od == 0 && !W_tt.t_needspaces)
X while (np -> ch_all == ' ' && np <= nl) np++, m1++;
X#endif
X topos (ln, lsp + m1 + 1);
X INSmode (0);
X if (nsp != osp || W_tt.t_needspaces)
X dumpstring (np, nl);
X else
X dumps2 (Inp, nl, Iop, ln, np - Inp);
X if (nd < od) {
X topos (ln, lsp + m1 + nd + 1);
X wipeline (0, OldLineWipeTo);
X }
X if (nsp > osp) {
X topos (ln, 1);
X INSmode (1);
X (*W_tt.t_modes) (0);
X blanks (nsp - osp);
X }
X }
X else { /* m1!=0 && m2!=0 && (nd!=0 || od!=0) */
X topos (ln, lsp + m1 + 1);
X t = nd - od;
X if (nd > 0 && od > 0) {
X INSmode (0);
X if (nsp == osp && !W_tt.t_needspaces) {
X dumps2 (Inp, np + min (nd, od) - 1, Iop, ln, np - Inp);
X if (nd != od)
X topos (ln, lsp + m1 + min (nd, od) + 1);
X }
X else
X dumpstring (np, np + min (nd, od) - 1);
X }
X if (nd < od)
X deletechars (od - nd);
X else
X if (nd > od)
X INSmode (1), dumpstring (np + od, nl);
X if (nsp > osp) {
X topos (ln, 1);
X INSmode (1);
X (*W_tt.t_modes) (0);
X blanks (nsp - osp);
X }
X }
X }
Xcleanup:;
X#ifdef FIONREAD
X if(--CheckForInput<0 && !InputPending &&
X ((stdout->_ptr - stdout->_base) > 20)){
X fflush (stdout);
X#ifdef TIOCOUTQ /* prevent system I/O buffering */
X if (baud_rate < 2400) {
X int out1;
X float outtime;
X if (ioctl (fileno(stdin), TIOCOUTQ, &out1))
X out1 = 0;
X out1 *= 10;
X outtime = ((float) out1) / ((float) baud_rate);
X if (outtime >= 1.5) sleep ((unsigned) (outtime - .5));
X }
X#endif
X ioctl (fileno(stdin), FIONREAD, &InputPending);
X CheckForInput = baud_rate / 2400;
X }
X#endif
X return rv;
X}
X
X/* Update a line that used to be completely blank */
Xhidden procedure UpdateEasyLine (ln, st, en)
Xregister Ch *st, *en;
X{
X register char *p;
X register mode;
X Ch *xstart = st, *ostart;
X
X INSmode (0);
X while (st < en) {
X if (st -> ch_all == ' ' && (st+1) < en && (st+1) -> ch_all == ' ') {
X while (st < en && st -> ch_all == ' ')
X st++;
X continue;
X }
X ostart = st;
X mode = st -> Mode;
X p = OneLineBuf;
X while (st < en && st -> Mode == mode) {
X if (st -> ch_all == ' ' && (st+2) < en && (st+1) -> ch_all == ' '
X && (st+2) -> ch_all == ' ')
X break;
X *p++ = st++ -> Char;
X }
X topos (ln, ostart-xstart+1);
X (*W_tt.t_modes) (mode);
X (*W_tt.t_writechars) (OneLineBuf, p - 1);
X }
X}
X
Xvisible procedure WDUpdateScreen (SlowUpdate, NoInputCheck) {
X register n, /* NOTE: n MUST be first register! */
X c;
X
X CheckForInput = 9999;
X if (ScreenGarbaged) {
X reset ();
X ScreenGarbaged = 0;
X SlowUpdate = 0;
X for (n = 0; n <= ScreenLength; n++) {
X ReleaseLine (PhysScreen[n]);
X PhysScreen[n] = 0;
X }
X }
X#ifdef FIONREAD /* one quick test */
X if (!NoInputCheck && !InputPending)
X ioctl (fileno(stdin), FIONREAD, &InputPending);
X#endif
X if (WDCurrentLine >= 0
X && DesiredScreen[WDCurrentLine] -> length <= ScreenWidth - WDleft)
X DesiredScreen[WDCurrentLine] -> length =
X WDleft > 0 ? ScreenWidth - WDleft : ScreenWidth;
X WDCurrentLine = -1;
X if (W_tt.t_ILov == MissingFeature)
X SlowUpdate = 0;
X if (SlowUpdate) {
X for (n = 1; n <= ScreenLength; n++) {
X/* if (DesiredScreen[n] == 0)/* Fortunately for my current hacking,
X/* this is never true. ACT 24-Mar-83 */
X/* DesiredScreen[n] = PhysScreen[n];
X/* else */
X hashline (DesiredScreen[n]);
X hashline (PhysScreen[n]);
X }
X c = 0;
X for (n = ScreenLength; n >= 1 && c <= 2; n--)
X if (PhysScreen[n] != DesiredScreen[n]
X && PhysScreen[n]
X && DesiredScreen[n] -> hash != PhysScreen[n] -> hash)
X c++;
X if (c <= 2)
X SlowUpdate = 0;
X else {
X if (W_tt.t_window) {
X for (n = ScreenLength;
X n >= 1
X && (PhysScreen[n] == DesiredScreen[n]
X || PhysScreen[n]
X && DesiredScreen[n] -> hash == PhysScreen[n] -> hash);
X n--);
X WindowSize = n;
X (*W_tt.t_window) (n);
X }
X else
X WindowSize = ScreenLength;
X calcM ();
X CheckForInput = NoInputCheck ? 9999 : baud_rate / 2400;
X CalcID (ScreenLength, ScreenLength, 0);
X/* for (n = 1; n <= ScreenLength; n++) {
X if (DesiredScreen[n] != PhysScreen[n]) {
X ReleaseLine (PhysScreen[n]);
X PhysScreen[n] = DesiredScreen[n];
X }
X DesiredScreen[n] = 0;
X } */
X }
X }
X if (!SlowUpdate) { /* fast update */
X for (n = 1; n <= ScreenLength; n++)
X if (DesiredScreen[n] && DesiredScreen[n] -> touched) {
X if (UpdateLine (PhysScreen[n], DesiredScreen[n], n)) {
X/* if (PhysScreen[n] != DesiredScreen[n]) */
X ReleaseLine (PhysScreen[n]);
X PhysScreen[n] = DesiredScreen[n];
X DesiredScreen[n] = 0;
X }
X }
X }
X if (WSetRealCursor && !InputPending)
X topos (WRCurRow + 1, WRCurCol + 1);
X if (W_tt.t_donerefresh)
X (*W_tt.t_donerefresh) ();
X for (n = 1; n <= ScreenLength; n++) {
X if (PhysScreen[n] != 0 && DesiredScreen[n] == 0) {
X DesiredScreen[n] = newline ();
X#ifdef VAX
X /* This bit of trickery helps a LOT. */
X asm ("movl _PhysScreen[r11],r1"); /*r1=from, r0=to*/
X asm ("clrw 12(r0)"); /*r0->touched=0*/
X asm ("movw 10(r1),10(r0)"); /*r0->length=r1->length*/
X asm ("cvtwl 10(r1),r2"); /*r2=2*r1->length*/
X asm ("addl2 r2,r2");
X asm ("movc3 r2,14(r1),14(r0)"); /*bcopy(r1->body,r0->body,r2)*/
X#else
X CopyLine (PhysScreen[n], DesiredScreen[n]);
X#endif
X }
X }
X}
X
X#ifndef VAX
Xhidden procedure CopyLine (from, to)
Xregister struct line *from, *to;
X{
X register Ch *cp = from -> body, *tp = to -> body;
X register n = from -> length;
X to -> touched = 0;
X to -> length = from -> length;
X while (--n>=0) *tp++ = *cp++;
X}
X#endif
X
Xvisible int VisibleBell; /* If true and the terminal will support it
X then the screen will flash instead of
X feeping when an error occurs */
Xvisible int InverseVideo; /* If true and the terminal will support it
X then we will use inverse video */
X
X/* DJH common routine for a feep */
XDing () { /* BOGUS! this should really be terminal
X type specific! */
X if (VisibleBell && W_tt.t_flash) (*W_tt.t_flash) ();
X else putchar (07);
X fflush (stdout); /* 23 May 1983 ACT */
X}
X
X/* initialize the teminal package */
XWDterm_init () {
X static short baud_convert[] =
X {
X 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
X 1800, 2400, 4800, 9600, 19200
X };
X int rv = 0; /* Return value: 0 = OK */
X struct sgttyb sg;
X extern short ospeed;
X extern WTtyFd; /* For gttying on the terminal */
X static BeenHere; /* true iff we've been here before (some
X things must only be done once!) */
X
X#ifdef DEBUG
X RDdebug = 0; /* line redraw debug switch */
X IDdebug = 0; /* line insertion/deletion debug */
X#endif DEBUG
X WDCurrentLine = -1; /* current line for writing to the
X virtual screen. */
X WDleft = -1; /* number of columns left on the current
X line of the virtual screen. */
X gtty (WTtyFd, &sg);
X ospeed = sg.sg_ospeed;
X baud_rate = sg.sg_ospeed == 0 ? 1200
X : sg.sg_ospeed < sizeof baud_convert / sizeof baud_convert[0]
X ? baud_convert[sg.sg_ospeed] : 9600;
X if (!BeenHere) {
X char *tname = (char *) getenv ("TERM");
X struct termtype {
X char *name;
X int cmplen;
X int (*startup) ();
X };
X /* A terminal driver is selected by looking up the value of the
X environment variable TERM in the following table. The string is
X matched against the name, considering at most "cmplen" characters
X to be significant. "startup" points to the function that sets up
X the terminal driver. The driver is called with the terminal type
X as a parameter and is free to use that to specialize itself. */
X /* NOTE: The driver should return 0 if the terminal is useable. For
X now, only the TrmTERM driver does so. */
X struct termtype *p;
X extern TrmTEK4025 ();
X extern TrmAmb ();
X/* extern TrmC100 (); */
X/* extern TrmI400 (); */
X/* extern TrmMiniB (); */
X/* extern TrmPERQ (); */
X extern TrmVT100 ();
X extern TrmBitG ();
X/* extern TrmGT40 (); */
X/* extern TrmGigi (); */
X static struct termtype termtable[] = {
X "4025", 99, TrmTEK4025,
X "aaa", 99, TrmAmb,
X "amb", 99, TrmAmb,
X "ambassador",99, TrmAmb,
X "BG", 99, TrmBitG,
X "Bit", 3, TrmBitG,
X/* "C10", 3, TrmC100, */
X/* "c10", 3, TrmC100, */
X/* "Concept", 7, TrmC100, */
X/* "concept", 7, TrmC100, */
X/* "d4", 99, TrmGT40, */
X "D5", 99, TrmVT100,
X "Dq", 2, TrmVT100,
X "DT80", 99, TrmVT100,
X/* "GG", 99, TrmGigi, */
X/* "Gigi", 4, TrmGigi, */
X/* "gt40", 99, TrmGT40, */
X/* "GT40", 99, TrmGT40, */
X/* "perq", 4, TrmC100, */
X/* "i400", 99, TrmI400, */
X "Mb", 99, TrmAmb,
X/* "minibee", 99, TrmMiniB, */
X "tek4025", 99, TrmTEK4025,
X "VT1", 3, TrmVT100,
X "vt1", 3, TrmVT100,
X "X5", 99, TrmTEK4025,
X 0, 0, 0
X };
X BeenHere++;
X if (tname == 0)
X tname = "sd";
X { /* Initialize NullStr */
X register Ch *p;
X for (p = NullStr; p < &NullStr[MScreenWidth]; )
X p++ -> ch_all = ' ';
X }
X W_tt.t_frames[0] = '+', W_tt.t_frames[2] = '+';
X W_tt.t_frames[5] = '+', W_tt.t_frames[7] = '+';
X W_tt.t_frames[1] = '-', W_tt.t_frames[6] = '-';
X W_tt.t_frames[3] = '|', W_tt.t_frames[4] = '|';
X
X for (p = termtable; p -> name; p++)
X if (strcmpn (p -> name, tname, p -> cmplen) == 0) {
X rv = (*p -> startup) (tname);
X break;
X }
X if (p -> name == 0)
X rv = TrmTERM (tname);
X if (rv)
X return rv;
X }
X rv = (*W_tt.t_init) (baud_rate);
X if (rv)
X return rv;
X if (W_tt.t_length > MScreenLength)
X W_tt.t_length = MScreenLength;
X if (W_tt.t_width > MScreenWidth)
X W_tt.t_width = MScreenWidth;
X (*W_tt.t_reset) ();
X return 0;
X}
X
X/* Debugging routines -- called from sdb only */
X
X/* print out the insert/delete cost matrix */
X#ifdef DEBUG
XPrintM () {
X register i,
X j;
X register struct Msquare *p;
X for (i = 0; i <= ScreenLength; i++) {
X for (j = 0; j <= ScreenLength; j++) {
X p = &M[i][j];
X fprintf (stderr, "%4d%c", p -> cost,
X p -> fromi < i && p -> fromj < j ? '\\' :
X p -> fromi < i ? '^' :
X p -> fromj < j ? '<' : ' ');
X }
X fprintf (stderr, "\n");
X }
X fprintf (stderr, "\014");
X}
X#endif
X
Xvisible procedure
XNoOperation () {}
X
Xhidden procedure dumpstring (start, end)
Xregister Ch *start, *end;
X{
X register char *p;
X register mode;
X
X do {
X mode = start -> Mode;
X p = OneLineBuf;
X while (start <= end && start -> Mode == mode)
X *p++ = start++ -> Char;
X (*W_tt.t_modes) (mode);
X (*W_tt.t_writechars) (OneLineBuf, p - 1);
X } while (start <= end);
X}
X
X/* Update a line that hasn't shifted left or right -- can compare char by
X char and skip over equal chunks */
X/* NOTE: We have carefully guaranteed that whenever st<=en, os<=(the end of
X the line that os pointed to) and that all "extra" chars in a line (ie
X past the "end") are (type Ch) blanks */
Xhidden procedure dumps2 (st, en, os, ln, skip)
Xregister Ch *st, *en, *os;
X{
X register char *p;
X register mode;
X Ch *xstart = st, *ostart;
X
X st += skip;
X os += skip;
X while (st <= en) {
X if (st -> ch_all == os -> ch_all && st+1 <= en &&
X (st+1)->ch_all == (os+1)->ch_all) {
X while (st <= en && st -> ch_all == os -> ch_all)
X st++, os++;
X continue;
X }
X ostart = st;
X mode = st -> Mode;
X p = OneLineBuf;
X while (st <= en && st -> Mode == mode) {
X if (st->ch_all == os->ch_all && st+2 <= en &&
X (st+1)->ch_all == (os+1)->ch_all &&
X (st+2)->ch_all == (os+2)->ch_all)
X break;
X *p++ = st++ -> Char;
X os++;
X }
X topos (ln, ostart-xstart+1);
X (*W_tt.t_modes) (mode);
X (*W_tt.t_writechars) (OneLineBuf, p - 1);
X }
X}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 644 display.c
/bin/echo -n ' '; /bin/ls -ld display.c
fi
--
UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet: chris at umcp-cs
ARPA: chris.umcp-cs at UDel-Relay
More information about the Comp.sources.unix
mailing list