zorat (03/05/83)
I had the same problem regarding the number of lines on my ambassador:
in general I like to use 30 lines, but occasionally I like to have all
60 of them on the screen.
Here was my changes to display.c and the ambassador and vt100 drivers:
(to get 132 columns on screen, you then type
ESC-x columns-on-screen 132)
(to extract the 3 files, edit this message and put the next part,
starting with :Run this through sh (not csh), in some file (say tmp),
possibly in a clean directory. Go to that directory and type
sh tmp
to get the three files.
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
/bin/echo 'Extracting display.c'
sed 's/^X//' <<'//go.sysin dd *' >display.c
X#define ACT
X/* Ultra-hot screen management package
X James Gosling, January 1980 */
X
X/* Copyright (c) 1981,1980 James Gosling */
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
X#include "display.h"
X#include "window.h"
X#include "keyboard.h"
X#include "mlisp.h"
X#include <sgtty.h>
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 (*tt.t_topos)
X#define reset (*tt.t_reset)
X#define INSmode (*tt.t_INSmode)
X#define insertlines (*tt.t_inslines)
X#define deletelines (*tt.t_dellines)
X#define blanks (*tt.t_blanks)
X#define wipeline (*tt.t_wipeline)
X#define wipescreen (*tt.t_wipescreen)
X#define deletechars (*tt.t_delchars)
X#define dumpstring (*tt.t_writechars)
X
X#define MScreenWidth 135
X#define MScreenLength 70
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 char highlighted; /* true iff this line is to be
X highlighted */
X char 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 */
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 */
X
X/* 'newline' returns a pointer to a new line object, either from the
X free list or from the general unix pool */
Xstruct line *newline () {
X register struct line *p = FreeLines;
X
X if (p) {
X FreeLines = p -> next;
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 }
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 -> highlighted = 0;
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 RDdebug, /* line redraw debug switch */
X IDdebug, /* line insertion/deletion debug */
X cursX, /* X and Y coordinates of the cursor */
X cursY, /* between updates. */
X CurrentLine, /* current line for writing to the
X virtual screen. */
X left; /* number of columns left on the current
X line of the virtual screen. */
Xvisible char
X *cursor; /* pointer into a line object, indicates
X where to put the next character */
X
X
X/* 'setpos' positions the cursor at position (row,col) in the virtual
X screen */
Xvisible procedure setpos (row, col)
Xregister row,
X col; {
X register struct line *p;
X register n;
X
X if (CurrentLine >= 0
X && (p = DesiredScreen[CurrentLine]) -> length
X <= (n = ScreenWidth - left))
X p -> length = left > 0 ? n : ScreenWidth;
X if (!DesiredScreen[row])
X DesiredScreen[row] = newline ();
X (p = DesiredScreen[row]) -> hash = 0;
X while (p -> length + 1 < col)
X p -> body[p -> length++] = ' ';
X CurrentLine = row;
X left = ScreenWidth + 1 - col;
X cursor = &DesiredScreen[row] -> body[col - 1];
X}
X
X/* 'clearline' positions the cursor at the beginning of the
X indicated line and clears the line (in the image) */
Xclearline (row) {
X setpos (row, 1);
X DesiredScreen[row] -> length = 0;
X}
X
X/* 'HighLine' causes the current line to be highlighted */
XHighLine () {
X if (CurrentLine >= 0)
X DesiredScreen[CurrentLine] -> highlighted++;
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 char *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 == ' ');
X while (c <= l && *c == ' ')
X c++;
X p -> DrawCost = l - c + 1;
X if (p -> highlighted) {
X p -> hash = -200;
X return;
X }
X while (c <= l)
X h = (h << 5) + h + *c++;
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 += tt.t_ILmf * (ScreenLength - i) + tt.t_ILov;
X if (DesiredScreen[i + 1])
X cost += DesiredScreen[i + 1] -> DrawCost;
X }
X
X fidcost = tt.t_ILmf * (WindowSize + 1) + tt.t_ILov;
X for (i = 1; i <= WindowSize; i++)
X {
X p = &M[i][0];
X fidcost -= 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 = tt.t_ILmf * (WindowSize - i + 1) + 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 register DoneEarly = 0;
X if (old == DesiredScreen[i]) DesiredScreen[i] = 0;
X PhysScreen[i] = 0;
X
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 CalcID (ni, nj, 0);
X if (InputPending && !DoneEarly) {
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 (!DoneEarly && (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 char *op,
X *np,
X *ol,
X *nl;
X int osp,
X nsp,
X m1,
X m2,
X od,
X nd,
X OldHL,
X NewHL,
X t,
X OldLineWipeTo;
X
X if (old == new)
X return;
X if (old) {
X op = old -> body;
X ol = &old -> body[OldLineWipeTo = old -> length];
X OldHL = old -> highlighted;
X }
X else
X op = "", ol = op, OldHL = 0, OldLineWipeTo = 1;
X if (new) {
X np = new -> body;
X nl = &new -> body[new -> length];
X NewHL = new -> highlighted;
X }
X else
X np = "", nl = np, NewHL = 0;
X osp = nsp = m1 = m2 = od = od = 0;
X
X/* calculate the magic parameters */
X if (NewHL == OldHL) {
X while (*--ol == ' ' && ol >= op) --OldLineWipeTo;
X while (*--nl == ' ' && nl >= np);
X while (*op == ' ' && op <= ol)
X op++, osp++;
X while (*np == ' ' && np <= nl)
X np++, nsp++;
X#ifdef ACT
X if (!NewHL && ol < op && !tt.t_needspaces)
X osp = nsp;
X#endif
X while (*op == *np && op <= ol && np <= nl)
X op++, np++, m1++;
X#ifdef ACT
X if (!NewHL && op > ol && !tt.t_needspaces)
X while (*np == ' ' && np <= nl)
X np++, m1++;
X#endif
X while (*ol == *nl && op <= ol && np <= nl)
X ol--, nl--, m2++;
X }
X else {
X ol--;
X nl--;
X osp = 0;
X while (*np == ' ' && np < nl)
X np++, nsp++;
X }
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 ? tt.t_DCov - c1*tt.t_DCmf
X : tt.t_ICov + c1*tt.t_ICmf;
X if (c3 = nd - od)
X c3 = c3<0 ? tt.t_DCov - c3*tt.t_DCmf
X : tt.t_ICov + c3*tt.t_ICmf;
X if (c2 = (nsp + nd) - (osp + od))
X c2 = c2<0 ? tt.t_DCov - c2*tt.t_DCmf
X : tt.t_ICov + c2*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 if (RDdebug && (m1 || m2 || nd || od)) {
X fprintf (stderr, "%2d nsp=%2d osp=%2d m1=%2d nd=%2d od=%2d m2=%2d",
X ln, nsp, osp, m1, nd, od, m2);
X }
X (*tt.t_HLmode) (NewHL);
X if (NewHL != OldHL) {
X topos (ln, 1);
X wipeline (1, OldLineWipeTo);
X OldLineWipeTo = 1;
X }
X if (m1 == 0)
X if (m2 == 0) {
X if (od == 0 && nd == 0)
X goto cleanup;
X#ifndef ACT
X if (od == 0 && !tt.t_needspaces)
X osp = nsp;
X#endif
X topos (ln, (t = min (nsp, osp)) + 1);
X INSmode (0);
X if (nsp > osp)
X blanks (nsp - osp);
X dumpstring (np, nl);
X if (nsp + nd < osp + od)
X wipeline (0, OldLineWipeTo);
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), dumpstring (np, nl - t);
X if (t > 0)
X INSmode (1), dumpstring (nl - t + 1, nl);
X }
X else
X INSmode (0), dumpstring (np, nl), deletechars (-t);
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 blanks (nsp - osp);
X }
X goto cleanup;
X }
X#ifndef ACT
X if (od == 0 && !tt.t_needspaces)
X while (*np==' ') np++, m1++;
X#endif
X topos (ln, lsp + m1 + 1);
X INSmode (0);
X dumpstring (np, nl);
X if (nd < od)
X wipeline (0, OldLineWipeTo);
X if (nsp > osp) {
X topos (ln, 1);
X INSmode (1);
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), dumpstring (np, np + min (nd, od) - 1);
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 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 ioctl (fileno(stdin), TIOCOUTQ, &out1);
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}
X
Xvisible procedure UpdateScreen (SlowUpdate) {
X register n,
X c;
X
X CheckForInput = 999;
X if (ScreenGarbaged) {
X reset ();
X ScreenGarbaged = 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 (!InputPending) ioctl (fileno(stdin), FIONREAD, &InputPending);
X#endif
X if (CurrentLine >= 0
X && DesiredScreen[CurrentLine] -> length <= ScreenWidth - left)
X DesiredScreen[CurrentLine] -> length =
X left > 0 ? ScreenWidth - left : ScreenWidth;
X CurrentLine = -1;
X if (tt.t_ILov == MissingFeature)
X SlowUpdate = 0;
X if (SlowUpdate) {
X for (n = 1; n <= ScreenLength; n++) {
X if (DesiredScreen[n] == 0)
X DesiredScreen[n] = PhysScreen[n];
X else
X hashline (DesiredScreen[n]);
X hashline (PhysScreen[n]);
X }
X/* if(oldhighlights.applied)
X ApplyHighlights(1, oldhighlights.HLbody, 0); */
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 (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 (*tt.t_window) (n);
X }
X else
X WindowSize = ScreenLength;
X calcM ();
X CheckForInput = 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/* if (DoHighlights){
X oldhighlights = newhighlights;
X ApplyHighlights (0,newhighlights.HLbody,1);
X oldhighlights.applied++;
X }
X else oldhighlights.applied = 0; */
X }
X }
X if (!SlowUpdate) { /* fast update */
X for (n = 1; n <= ScreenLength; n++)
X if (DesiredScreen[n]) {
X 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 (*tt.t_HLmode) (0);
X if (!InputPending)
X topos (cursY, cursX);
X}
X
Xstatic 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/* AZ routine to change number of lines on screen */
Xvisible procedure ScreenLines(){
X tt.t_length = getnum (": lines-on-screen ");
X ScreenGarbaged = 1;
X InitWin();
X DoDsp(1);
X}
X/* AZ routine to change number of cols. on screen */
Xvisible procedure ScreenCols(){
X tt.t_width = getnum (": columns-on-screen ");
X ScreenGarbaged = 1;
X DoDsp(1);
X}
X
X/* DJH common routine for a feep */
XDing () { /* BOGUS! this should really be terminal
X type specific! */
X if (VisibleBell && tt.t_flash) (*tt.t_flash) ();
X else putchar (07);
X}
X
X/* DLK routine to make the cursor sit for n/10 secs */
Xhidden procedure SitFor () {
X register num_chars, CharsPerInputCheck;
X
X if(InputPending || stdin->_cnt!= 0) return 0;
X CharsPerInputCheck = baud_rate / 100;
X num_chars = getnum (": sit-for ") * CharsPerInputCheck;
X DoDsp (1); /* Make the screen correct */
X INSmode (0);
X while (num_chars-- && !InputPending){
X#ifdef FIONREAD
X if ( ((num_chars+1) % CharsPerInputCheck) == 0){
X fflush (stdout);
X ioctl (fileno(stdin), FIONREAD, &InputPending);
X }
X#endif
X putchar(tt.t_padc);
X }
X return 0;
X}
X
X/* ACT 18-Oct-1982 sleep for n seconds, do not update display */
Xhidden procedure SleepFor () {
X register t = getnum (": sleep-for ");
X if (t >= 1 && t <= 10) sleep (t);
X return 0;
X}
X
X/* initialize the teminal package */
Xterm_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 struct sgttyb sg;
X extern short ospeed;
X static BeenHere; /* true iff we've been here before (some
X things must only be done once!) */
X
X RDdebug = 0; /* line redraw debug switch */
X IDdebug = 0; /* line insertion/deletion debug */
X cursX = 1; /* X and Y coordinates of the cursor */
X cursY = 1; /* between updates. */
X CurrentLine = -1; /* current line for writing to the
X virtual screen. */
X left = -1; /* number of columns left on the current
X line of the virtual screen. */
X gtty (fileno (stdin), &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 struct termtype *p;
X extern TrmAmb ();
X extern TrmVT100 ();
X/* extern TrmTEK4025 (); */
X/* extern TrmC100 (); */
X/* extern TrmI400 (); */
X/* extern TrmMiniB (); */
X/* extern TrmPERQ (); */
X/* extern TrmBitG (); */
X/* extern TrmGT40 (); */
X/* extern TrmGigi (); */
X static struct termtype termtable[] = {
X "aaa", 3, TrmAmb,
X "amb", 3, TrmAmb,
X "ambassador",99, TrmAmb,
X "VT1", 3, TrmVT100,
X "vt1", 3, TrmVT100,
X/* "4025", 99, TrmTEK4025, */
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/* "X5", 99, TrmTEK4025, */
X 0, 0, 0
X };
X BeenHere++;
X if (tname == 0)
X tname = "concept";
X for (p = termtable; p -> name; p++)
X if (strcmpn (p -> name, tname, p -> cmplen) == 0) {
X (*p -> startup) (tname);
X break;
X }
X if (p -> name == 0)
X TrmTERM (tname);
X defproc (ScreenLines, "lines-on-screen");
X defproc (ScreenCols, "columns-on-screen");
X defproc (SitFor, "sit-for");
X defproc (SleepFor, "sleep-for");
X DefIntVar ("visible-bell", &VisibleBell);
X DefIntVar ("inverse-video", &InverseVideo);
X }
X (*tt.t_init) (baud_rate);
X if (tt.t_length > MScreenLength)
X tt.t_length = MScreenLength;
X if (tt.t_width > MScreenWidth)
X tt.t_width = MScreenWidth;
X (*tt.t_reset) ();
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 () {}
//go.sysin dd *
/bin/chmod 644 display.c
/bin/echo -n ' '; /bin/ls -l display.c
/bin/echo 'Extracting TrmAmb.c'
sed 's/^X//' <<'//go.sysin dd *' >TrmAmb.c
X/* terminal control module for Ann Arbor Ambassadors */
X
X/* ACT 16-Oct-1982: Combined Gosling's version and mine to write this one */
X
X#include <stdio.h>
X#include "Trm.h"
X#include "keyboard.h"
X#define PAD(n,f) if (Baud > 9600) pad(n,f); else
X
Xstatic
Xint curX, curY, Baud, CurHL, DesHL;
X
Xstatic
Xfloat BaudFactor;
X
Xstatic
Xenum IDmode { m_insert = 1, m_overwrite = 0} DesiredMode;
X
Xstatic
XINSmode (new)
Xenum IDmode new; {
X DesiredMode = new;
X}
X
Xstatic
XHLmode (new) {
X DesHL = new;
X}
X
Xstatic
XSetHL (OverRide) {
X register Des = OverRide ? 0 : DesHL;
X if (Des == CurHL)
X return;
X if (InverseVideo) printf ("\033[%cm", Des ? '0' : '7');
X else printf ("\033[%cm", Des ? '7' : '0');
X PAD (1, 0.30);
X CurHL = Des;
X}
X
Xstatic
Xinslines (n) {
X SetHL (1);
X printf (n <= 1 ? "\033[L" : "\033[%dL", n);
X PAD (61-curY, 4.00);
X}
X
Xstatic
Xdellines (n) {
X SetHL (1);
X printf (n <= 1 ? "\033[M" : "\033[%dM", n);
X PAD (61-curY, 4.00);
X if (tt.t_length == 60)
X return;
X if (Baud < 4800) { /* yeesh! */
X topos (tt.t_length-n+1, 1);
X printf ("\033[J");
X }
X else {
X register i;
X for (i=tt.t_length-n+1; i<=tt.t_length; i++) {
X topos (i, 1);
X wipeline ();
X }
X/* i = tt.t_length - n + 1;
X topos (i, 1);
X printf (n <= 1 ? "\033[M" : "\033[%dM", n);
X PAD (60-curY, 4.00); */
X
X }
X}
X
Xstatic
Xwritechars (start, end)
Xregister char *start, *end; {
X register char *p;
X register runlen;
X
X SetHL (0);
X if (DesiredMode == m_insert) {
X printf ("\033[%d@", end - start + 1);
X PAD (80-curX, 0.16);
X }
X while (start <= end) {
X if (*start < 040 || *start >= 0177) {
X printf (InverseVideo ? "\033[m%c\033[7m" : "\033[7m%c\033[m",
X *start < 040 ? (*start & 037) + 0100 : '?');
X /* enter hi-light mode, print char, exit hi-light mode */
X PAD (1, 1.00);
X start++;
X curX++;
X }
X else {
X if (start+5 < end && *start == start[1]) {
X runlen = 0;
X p = start;
X do runlen++; while (*++start == *p && start <= end);
X if (runlen > 5) {
X putchar (*p);
X printf ("\033[%db", runlen - 1);
X PAD (runlen-1, 1.00);
X curX += runlen;
X }
X else {
X start = p;
X goto normal;
X }
X }
X else {
Xnormal:
X putchar (*start++);
X curX++;
X }
X }
X }
X}
X
Xstatic
Xblanks (n) register n; {
X if (n > 0) {
X SetHL (0);
X curX += n;
X if (DesiredMode == m_insert) {
X printf ("\033[%d@", n);
X PAD (80-curX, 0.16);
X }
X if (n > 5) {
X printf (" \033[%db", n-1);
X PAD (n-1, 1.00);
X }
X else while (--n >= 0) putchar (' ');
X }
X}
X
Xstatic
Xpad (n, f)
Xfloat f; {
X register k = n * f * BaudFactor;
X while (--k >= 0)
X putchar (0);
X}
X
Xstatic
Xtopos (row, column) register row, column; {
X if (curY == row) {
X if (curX == column)
X return;
X if (curX == column + 1) {
X putchar (010);
X goto done;
X }
X printf ("\033[%d`", column);
X goto done;
X }
X if (curY+1 == row && (column == 1 || column == curX)) {
X if (column != curX) putchar (015);
X putchar (012);
X goto done;
X }
X if (row == 1 && column == 1) {
X printf ("\033[f");
X goto done;
X }
X if (column == 1) {
X printf ("\033[%df", row);
X goto done;
X }
X if (row == 1) {
X printf ("\033[;%df", column);
X goto done;
X }
X printf ("\033[%d;%df", row, column);
Xdone:
X curX = column;
X curY = row;
X PAD (1, 1.00);
X}
X
Xstatic
Xinit (BaudRate) {
Xchar *tname = (char *) getenv ("TERM");
X MetaFlag = strcmp (tname, "aaamt") ? 0 : 1;
X BaudFactor = BaudRate / 10000.;
X Baud = BaudRate;
X}
X
X#define ScreenLength (tt.t_length)
X#define ScreenWidth (tt.t_width)
X
Xstatic
Xreset () {
X CurHL = -1;
X SetHL (1);
X if (ScreenLength <= 18 ) printf ("\033[60;0;0;18p");
X if (ScreenLength > 18 && ScreenLength <= 22) printf ("\033[60;0;0;22p");
X if (ScreenLength > 22 && ScreenLength <= 24) printf ("\033[60;0;0;24p");
X if (ScreenLength > 24 && ScreenLength <= 26) printf ("\033[60;0;0;26p");
X if (ScreenLength > 26 && ScreenLength <= 28) printf ("\033[60;0;0;28p");
X if (ScreenLength > 28 && ScreenLength <= 30) printf ("\033[60;0;0;30p");
X if (ScreenLength > 30 && ScreenLength <= 36) printf ("\033[60;0;0;36p");
X if (ScreenLength > 36 && ScreenLength <= 40) printf ("\033[60;0;0;40p");
X if (ScreenLength > 40 && ScreenLength <= 48) printf ("\033[60;0;0;48p");
X if (ScreenLength > 48 && ScreenLength <= 60) printf ("\033[60;0;0;60p");
X pad (1, 10.00);
X printf ("\033[>52h"); /* SM meta key */
X printf ("\033[>30;33;34;37;38;39l");
X /* RM(ZDBM,ZWFM,ZWBM,ZAXM,ZAPM,ZSSM) */
X printf ("\033[1Q"); /* SEE */
X printf ("\033[H"); /* CUP */
X printf ("\033[2J"); /* ED */
X pad (1, 350.00);
X/* wipescreen(); */
X curX = curY = 1;
X DesiredMode = m_overwrite;
X}
X
Xstatic
Xcleanup () {
X InverseVideo = 0; /* reset to normal video */
X CurHL = -1;
X SetHL (0);
X topos (tt.t_length, 1);
X printf ("\033[J\033[m");
X pad (10, 1.00);
X printf ("\033[>30;33;34;37h"); /* SM(ZDBM,ZWFM;ZWBM;ZAXM) */
X pad (20, 1.00);
X printf ("\033[>52l"); /* RM Metakey */
X pad (10, 1.00);
X}
X
Xstatic
Xwipeline () {
X SetHL (0);
X printf ("\033[K");
X PAD (80-curX, 0.25);
X}
X
Xstatic
Xwipescreen () {
X SetHL (0);
X printf ("\033[2J");
X pad (1, 350.00);
X}
X
Xstatic
Xdelchars (n) {
X if (n <= 0) return;
X SetHL (0);
X printf (n == 1 ? "\033[P" : "\033[%dP", n);
X PAD (80-curX, 0.20);
X}
X
XTrmAmb () {
X int i; /* get preferred page length from */
X char *p = (char *) getenv ("PL"); /* environment - DCL */
X
X tt.t_length = p == 0 ? 30 : atoi (p); /* default 30 lines */
X tt.t_INSmode = INSmode;
X tt.t_HLmode = HLmode;
X tt.t_inslines = inslines;
X tt.t_dellines = dellines;
X tt.t_blanks = blanks;
X tt.t_init = init;
X tt.t_cleanup = cleanup;
X tt.t_wipeline = wipeline;
X tt.t_wipescreen = wipescreen;
X tt.t_topos = topos;
X tt.t_reset = reset;
X tt.t_delchars = delchars;
X tt.t_writechars = writechars;
X tt.t_window = 0;
X tt.t_ILmf = 0;
X tt.t_ILov = 4;
X tt.t_ICmf = 1;
X tt.t_ICov = 4;
X tt.t_DCmf = 0;
X tt.t_DCov = 5;
X tt.t_width = 80;
X}
//go.sysin dd *
/bin/chmod 644 TrmAmb.c
/bin/echo -n ' '; /bin/ls -l TrmAmb.c
/bin/echo 'Extracting TrmVT100.c'
sed 's/^X//' <<'//go.sysin dd *' >TrmVT100.c
X/* terminal control module for DEC VT100's */
X
X/* Modified version of Gosling's C100 driver -- jpershing@bbn */
X
X/* This is a somewhat primitive driver for the DEC VT100 terminal. The
X terminal is driven in so-called "ansi" mode, using jump scroll. It is
X assumed to have the Control-S misfeature disabled (although this
X shouldn't get in the way -- it does anyway). Specific optimization left
X to be done are (1) deferral of setting the window until necessary (as
X the escape sequence to do this is expensive) and (2) being more clever
X about optimizing motion (as the direct-cursor-motion sequence is also
X quite verbose). Also, something needs to be done about putting the
X terminal back into slow-scroll mode if that's the luser's preference (or
X perhaps having EMACS itself use slow-scroll mode [lose, lose]).
X*/
X
X#include <stdio.h>
X#include "display.h"
X
Xstatic
Xint curX, curY;
Xstatic
Xint WindowSize;
X
Xstatic curHL;
Xstatic
XHLmode (on) register on; {
X if (curHL == on)
X return;
X printf (on ? "\033[7m" : "\033[m" );
X pad (1, 2.0);
X curHL = on;
X}
X
Xstatic
Xinslines (n) register n; {
X printf ("\033[%d;%dr\033[%dH", curY, WindowSize, curY);
X curX = 1;
X while (--n >= 0) {
X printf ("\033M");
X pad (1, 20.); /* DEC sez pad=30, but what do they know? */
X }
X printf ("\033[r");
X pad (1, 2.); /* ACT */
X curX = curY = 1;
X};
X
Xstatic
Xdellines (n) register n; {
X printf ("\033[%d;%dr\033[%dH", curY, WindowSize, WindowSize);
X curX = 1;
X curY = WindowSize;
X while (--n >= 0) {
X printf ("\033E");
X pad (1, 20.); /* [see above comment] */
X }
X printf ("\033[r");
X pad (1, 2.); /* ACT */
X curX = curY = 1;
X};
X
Xstatic Baud;
X
Xstatic
Xwritechars (start, end)
Xregister char *start,
X *end; {
X register count = 0;
X while (start <= end) {
X if (*start < 040 || *start >= 0177) {
X printf (InverseVideo ? "\033[m%c\033[7m" : "\033[7m%c\033[m",
X *start < 040 ? (*start & 037) + 0100 : '?');
X pad (1, 5.0);
X start++;
X curX++;
X }
X else
X putchar (*start++);
X curX++;
X if (count++ > 15 && Baud >= 9600) count = 0, pad (1, 2.5);/* ACT */
X }
X};
X
Xstatic
Xblanks (n) register n; {
X while (--n >= 0) {
X putchar (' ');
X curX++;
X }
X};
X
Xstatic float BaudFactor;
X
Xstatic pad (n,f)
Xregister n;
Xregister float f; {
X register k = n * f * BaudFactor;
X while (--k >= 0)
X putchar (0);
X};
X
Xstatic /* This routine needs lots of work */
Xtopos (row, column) register row, column; {
X register k;
X if (curY == row) {
X k = curX - column;
X if (k) {
X if (k > 0 && k < 4) {
X while (k--) putchar(010);
X goto done;
X }
X }
X else return;
X }
X if (curY + 1 == row && (column == 1 || column==curX)) {
X if(column!=curX) putchar (015);
X putchar (012);
X goto done;
X }
X if (row == 1 && column == 1) {
X printf ("\033[H");
X pad (1, 5.); /* ACT */
X goto done;
X }
X printf ("\033[%d;%dH", row, column );
X pad (1, 10.); /* ACT */
Xdone:
X curX = column;
X curY = row;
X};
X
Xstatic
Xinit (BaudRate) {
X char *getenv();
X static inited = 0;
X if (!inited) {
X static char tbuf[1024]; /* ACT Try for termcap's co# */
X register char *t = getenv ("COL");
X tt.t_width = t ? atoi (t)
X : ((t = getenv ("TERM")) && tgetent (tbuf,t)>0) ? tgetnum ("co") : 80;
X }
X Baud = BaudRate;
X BaudFactor = strcmp (getenv ("TERM"), "vt100") ?
X BaudRate/4000. : BaudRate/10000.; /* AZ: slow it down for vt101 */
X tt.t_ILmf = 0.0;
X tt.t_ILov = 15 + 2+BaudFactor*20.;
X};
X
Xstatic
Xreset () {
X printf ("\033<\033[r\033[m\033[?4;6l\033[2J\033=");/* Whew! */
X if (InverseVideo) printf ("\033[?5h");/* Use inverse video */
X else printf ("\033[?5l");
X pad (1, 60.);
X printf (ScreenWidth <= 80 ? "\033[?3l" : "\033[?3h");
X /* set to 80 or 132 columns */
X pad (1, 150.);
X WindowSize = 24;
X curHL = 0;
X curX = curY = 1;
X};
X
Xstatic
Xcleanup () {
X HLmode (0);
X window (0);
X topos (WindowSize, 1);
X wipeline ();
X};
X
Xstatic
Xwipeline () {
X printf("\033[K");
X pad (1, 10.);
X};
X
Xstatic
Xwipescreen () {
X printf("\033[2J");
X pad (1, 100.); /* ACT was 45. */
X};
X
Xstatic
Xwindow (n) register n; {
X if (n <= 0 || n > 24)
X n = 24;
X WindowSize = n;
X}
X
X/* Visible Bell for DT80/1 -ACT */
Xstatic
Xflash () {
X printf (InverseVideo ? "\033[?5l" : "\033[?5h");
X pad (1, 40.);
X printf (InverseVideo ? "\033[?5h" : "\033[?5l");
X}
X
XTrmVT100 () {
X tt.t_INSmode = NoOperation;
X tt.t_HLmode = HLmode;
X tt.t_inslines = inslines;
X tt.t_dellines = dellines;
X tt.t_blanks = blanks;
X tt.t_init = init;
X tt.t_cleanup = cleanup;
X tt.t_wipeline = wipeline;
X tt.t_wipescreen = wipescreen;
X tt.t_topos = topos;
X tt.t_reset = reset;
X tt.t_delchars = 0;
X tt.t_writechars = writechars;
X tt.t_window = window;
X tt.t_flash = flash;
X tt.t_ILmf = 0;
X tt.t_ILov = 0;
X tt.t_ICmf = MissingFeature;
X tt.t_ICov = MissingFeature;
X tt.t_DCmf = MissingFeature;
X tt.t_DCov = MissingFeature;
X tt.t_length = 24;
X tt.t_width = 80;
X};
//go.sysin dd *
/bin/chmod 644 TrmVT100.c
/bin/echo -n ' '; /bin/ls -l TrmVT100.c