! Old EDWIN driver for Cursor Addressable Terminals and line printers.
from Edwin include Device
from Edwin include Icodes
from Edwin include Iprocs
from Edwin include Specs
from Imp include Ascii
const integer MAX X = 131, MAX Y = 23
! Control for Visual 200
const integer G ON = 'F', G OFF = 'G'
const integer G MODE REQ = 16_80
! The array holds the code symbols for edges with the codes -
const integer TOP=1, XLEFT=2, BOT=4, XRIGHT=8
const byte array CODE 200 (0:15) = '_', '_', '_', 'm', '_', 'a', 'l', 'o',
'_', 'e', '`', 'c', 's', 'n', 'd', 'b'
const byte array CODE 100 (0:15) = '_', '_', '_', 'j', '_', 'x', 'k', 'u',
'_', 'm', 'q', 'v', 'l', 't', 'w', 'n'
! Device configuration data -
const integer INTERACTS = 0; ! Terminal >= interacts => terminal has Graphics capabitility.
const integer Visual 200 = 0
!%const %integer Bantam 550 = 1
!%const %integer Soroc 120 = 2
!%const %integer HazeltineE = 3
const integer VT52 = 4
const integer VT131 = 5
const integer MAX CAT = 5
const integer array ERASES (INTERACTS:MAX CAT) = 'v', 'K', '*', FS, 'J', 'J'
const integer array CURS U (INTERACTS:MAX CAT) = 'A', DEL, VT, DEL, 'A', 'A'
const integer array CURS D (INTERACTS:MAX CAT) = 'B', NL, NL, NL, 'B', 'B'
const integer array CURS R (INTERACTS:MAX CAT) = 'C', TAB, FF, TAB, 'C', 'C'
const integer array CURS L (INTERACTS:MAX CAT) = 'D', BS, BS, BS, 'D', 'D'
const integer array UPS (INTERACTS:MAX CAT) = 'A', 'A', VT, FF, 'A', 'A'
const integer array DOWNS (INTERACTS:MAX CAT) = 'B', 'B', NL, VT, 'B', 'B'
const integer array RIGHTS (INTERACTS:MAX CAT) = 'C', 'C', CR, DLE, 'C', 'C'
const integer array LEFTS (INTERACTS:MAX CAT) = 'D', 'D', BS, BS, 'D', 'D'
own integer UP, DOWN, LEFT, RIGHT, CUR U, CUR D, CUR R, CUR L
own integer ERASE, MAX SX=79
const byte MAX SY=23
own integer MODEL = -1
own integer XL, YB, YT, XR ; ! Current Max Window bound
! device information
own integer MODE = 0; ! 0 if alphamode, 1 if Graph mode, -1 if unknown
own integer SX = 0, SY = 0; ! Current device position
own byte VIS = TRUE; ! TRUE if the current position is in the device window
own byte DIF = TRUE; ! TRUE if an UPDATE has just been done
own byte INIT = FALSE; ! Indicates if the driver is initialised
const integer TCS = 1; ! True char size.
record format COLF (byte integer array COL (0:MAXX))
record format ROWF (record (COLF) array ROW (0:MAXY))
!$IF ERCC compiler $START
!%own %record (ROWF) SCREEN
!$ELSE $IF IMP77 compiler
own record (ROWF) name SCREEN
!$FINISH
! The codes are held in SCREEN in the forms -
! 0 + 7 bits of char
! 1 + 3 bits of line style (no longer used!!) + 4 bits of code as above
routine ESC PLUS (integer SYM)
TTPUT (ESC)
TTPUT ('[') if MODEL=VT131
TTPUT (SYM)
end
routine GMON
! Enter Graphics mode.
return if MODE=GON or (MODEL#VISUAL200 and MODEL#VT131)
if MODEL=VT131 start
TTPUT (ESC); TTPUT ('('); TTPUT ('0')
else
ESC PLUS (GON)
finish
MODE = GON
end
routine GMOFF
! Come out of graphics mode.
return if MODE=GOFF or (MODEL#VISUAL200 and MODEL#VT131)
if MODEL=VT131 start
TTPUT (ESC); TTPUT ('('); TTPUT ('B')
else
ESC PLUS (GOFF)
finish
MODE = GOFF
end
routine DO MOVE
integer I
switch MS (0:MAX CAT)
-> MS (MODEL)
MS(Visual 200):
ESC PLUS ('Y'); TTPUT (23-SY+32); TTPUT (SX+32)
return
MS(VT131):
I = (24-SY)//10
if I=0 start { Suppress leading 0 }
ESC PLUS (REM(24-SY,10)+'0')
else
ESC PLUS (I+'0')
TTPUT (REM(24-SY,10)+'0')
finish
TTPUT (';')
I = SX + 1
if I > 99 start
TTPUT ((I//100) + '0')
I = Rem (I, 100)
TTPUT ((I//10) + '0')
TTPUT (Rem(I, 10) + '0')
else if I > 9
TTPUT ((I//10) + '0')
TTPUT (Rem(I, 10) + '0')
else
TTPUT (I+'0')
finish
TTPUT ('H')
end
external routine Yawn alias "EDWIN___Y" (integer COM, X, Y)
own integer WX, WY
routine UPDATE
DO MOVE if model >= interacts
GMOFF
FLUSH OUTPUT
MODE= 0
DIF = FALSE
end
routine SWAP (integer name A, B)
integer C
C = A; A = B; B = C
end
routine DRAW LINE (integer TX,TY)
! This is algorithm 162 in the Collected Algorithms from CACM.
!
! XYMOVE computes the code string required to move the pen of a
! digital incremental X-Y plotter from an initial point (XZ,YZ) to
! a terminal point (XN,YN) by the "best" approximation to the
! straight line between the points. The permitted elemental pen
! movement is to an adjacent point in a plane Cartesian point latice,
! diagonal moves permitted.
! The Algorithm has been modded to draw lines on Visual 200s.
! Using horisontal & vertical lines where possible, otherwise '+'.
! or on other terminals by filling character positions.
const integer LX = 5, RX = 4, UY = 1, DY = 2
integer A,B,D,E,F,T,I,XMOVE,YMOVE,X,Y
own integer array XCODE(1:16) = RX,0,0,0,0,0,RX,0,RX,LX,LX,LX,LX,LX,RX,LX
own integer array YCODE(1:16) = UY,UY,0,UY,0,DY,DY,DY,DY,DY,0,DY,0,UY,UY,UY
! PY,PX+PY,PX,PX+PY,PX,PX+NY,NY,PX+NY,NY,NY+NX,NX,NX+NY,NX,NX+PY,PY,NX+PY
routine ADD (integer P)
byte name SP { screen pointer
return unless 0<=SX<=MAX SX and 0<=SY<=MAX SY
SP == SCREEN_ROW(SY)_COL(SX)
return if (SP#0 and SP&G MODE REQ = 0) { character already in slot }
return if P&(SP&15)=P { nothing new on screen }
P = P ! (SP & 15) { OR in lines crossing in other directions. }
SP = GMODEREQ ! P { Update the screen map }
return if CODE200(P)=95
! CODE200(P)=95 => nothing to do on Visual 200 or VT131, => optimise.
DO MOVE
GMON
if MODEL=VISUAL200 start
TTPUT (CODE 200 (P))
else { %if MODEL=VT131
TTPUT (CODE 100 (P))
finish
end
routine MOVE (integer X, Y)
if X=0 start
ADD(XRIGHT); SX = SX + 1; ADD(XLEFT)
finish else if X=5 start
ADD(XLEFT); SX = SX - 1; ADD(XRIGHT)
finish
if Y=1 start
ADD(TOP); SY = SY + 1; ADD(BOT)
finish else if Y=2 start
ADD(BOT); SY = SY - 1; ADD(TOP)
finish
end
SWAP (SX, TX) and SWAP (SY, TY) if SX > TX; ! Optimise mode.
MOVE (SX, SY) and return if SX=TX and SY=TY
if SY = TY start { Horisonal Line }
ADD (XRIGHT)
SX = SX + 1 and ADD (XRIGHT+XLEFT) while SX < TX-1
SX = TX
ADD (XLEFT)
return
finish else if SX = TX start { Vertical line }
if SY > TY start
ADD (BOT)
SY = SY - 1 and ADD (BOT+TOP) while SY > TY+1
SY = TY
ADD (TOP)
else { SY < TY }
ADD (TOP)
SY = SY + 1 and ADD (BOT+TOP) while SY < TY-1
SY = TY
ADD (BOT)
finish
return
finish
{ Otherwise the general line code must be used }
A = TX - SX
B = TY - SY
D = A + B
T = B - A
I = 0
if B>=0 then I=2
if D>=0 then I=I+2
if T>=0 then I=I+2
if A>=0 then I=8-I else I=I+10
A = -A if A<0
B = -B if B<0
F = A + B
D = B - A
if D>=0 then T=A and D=-D else T= B
E = 0
XMOVE = XCODE (I-1)
YMOVE = YCODE (I-1)
X = XCODE (I)
Y = YCODE (I)
cycle
A = D + E
B = T + E + A
if B>=0 start
E = A
F = F - 2
MOVE (X, Y)
finish else start
E = E + T
F = F - 1
MOVE (XMOVE, YMOVE)
finish
exit if F<=0
repeat
MOVE (TX, TY) unless (MODEL=VISUAL200 or MODEL=VT131)
end
switch SW(0:MAX COM)
signal 14, 0 if INIT#TRUE and COM#0
-> SW(COM)
SW(0): ! Initialise
MAX SX = 79
DEV DATA_DVY = 23
DEV DATA_MVY = 23
DEV DATA_ARF = 45
DEV DATA_NUM CHAR SIZES = 255
DEV DATA_NUM CHAR ROTS = 255
X = 131 if X=220 { VT220 = VT100 for present }
if X=200 start
DEVICE DATA_NAME = "a Visual 200 terminal"
MODEL = VISUAL 200
else if X=131
DEVICE DATA_NAME = "a VT100 terminal"
MODEL = VT131
TTPUT (esc); TTPUT ('['); TTPUT ('?'); TTPUT ('3'); TTPUT ('h')
DEV DATA_ARF = 30
MAX SX = 130
else
signal 14, 0
finish
DEV DATA_DVX = MAX SX
DEV DATA_MVX = MAX SX
ERASE = ERASES (MODEL)
CUR U = CURS U (MODEL)
CUR D = CURS D (MODEL)
CUR R = CURS R (MODEL)
CUR L = CURS L (MODEL)
UP = UPS (MODEL)
DOWN = DOWNS (MODEL)
RIGHT = RIGHTS (MODEL)
LEFT = LEFTS (MODEL)
SCREEN == NIL
SCREEN == NEW (SCREEN)
SCREEN = 0
TTMODE (1)
TTPUT (ESC) and TTPUT ('(') and TTPUT ('0') if MODEL=VT131 { enable graphics characters }
INIT = TRUE
return
SW(1): !Terminate
if MODEL = VT131 start
TTPUT (ESC); TTPUT ('('); TTPUT ('B') { Default char set }
TTPUT (esc); TTPUT ('['); TTPUT ('?'); TTPUT ('3'); TTPUT ('l')
finish
SX = 0; SY = 0 { -> bottom of screen }
UPDATE
DISPOSE (SCREEN)
TTMODE (0)
return
SW(2): ! Update
UPDATE
return
SW(3): ! New frame
X = 0
ESC PLUS ('H') if MODEL=VT52
if MODEL=VT131 then ESC PLUS ('2') and TTPUT (ERASE) c
else ESC PLUS (ERASE)
Y = 22
UPDATE
SCREEN = 0
Y = 0
-> SW(4)
SW(5): ! Line Abs
DRAW LINE (X, Y)
SW(4): ! Move Abs
VIS = False and return unless 0<=X<=MAX SX and 0<=Y<=MAX SY
SX = X; SY = Y
DO MOVE
VIS = TRUE
DIF = TRUE
return
SW(6): ! Character
return unless VIS=TRUE
GMOFF
TTPUT (X)
X = 0 if X = ' '
SCREEN_ROW(SY)_COL(SX) = X
SX = SX + TCS
VIS = FALSE if SX>XR
DIF = TRUE
Inquire Position (x, y)
Clip (x, y, 0)
return
SW(7): ! Attribute Change
return
SW(8): ! Set lower window bounds
XL = X; YB = Y
return
SW(9): ! Set upper device window bounds
XR = X
XR = MAX SX if XR>MAX SX
YT = Y
YT = MAX SY if YT>MAX SY
return
SW(12): ! Lower Box bounds
WX = X; WY = Y
return
SW(13): ! Upper Box bounds & Draw the box
SWAP (WX, X) if WX > X
SWAP (WY, Y) if WY > Y
return if WX > XR or X < XL or WY > YT or Y < YB
WX = XL if WX < XL
WY = YB if WY < YB
X = XR if X > XR
Y = YT if Y > YT
! Box now clipped into the screen.
Yawn (4, wx, wy)
Yawn (5, wx, y)
Yawn (5, x, y)
Yawn (5, x, wy)
Yawn (5, wx, wy)
return
SW(*):
end
external routine VCURSOR alias "EDWIN___Y_REQ" (integer name CH,X,Y)
routine ESCAPE
TTPUT (ESC)
if MODEL=VT131 start
TTPUT ('[')
TTPUT ('1')
finish
end
signal 14,8 if MODEL<INTERACTS
TTPUT (7)
DO MOVE; FLUSH OUTPUT; MODE = 0; ! Update (in line).
X = SX; Y = SY;
cycle
CH = TTGET
exit if CH >= ' '; ! Key hit, => return
continue if CH#ESC
CH = TTGET; ! The significant character of the ESC sequence.
if MODEL=VT131 start
CH = TTGET until 'A'<=CH<='D'
finish
if CH=CUR U start
Y =Y+1 if Y<23
ESCAPE; TTPUT (UP)
finish else start
if CH=CUR R start
X =X+1 if X<MAX SX
ESCAPE; TTPUT (RIGHT)
finish else start
if CH=CUR L start
X =X-1 if X>0
ESCAPE; TTPUT (LEFT)
finish else start
if CH=CURD start
Y =Y-1 if Y>0
ESCAPE; TTPUT (DOWN)
finish else continue
finish
finish
finish
FLUSH OUTPUT
repeat
end
end of file