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