! EDWIN driver for Cursor Addressable Terminals and line printers.
!############################################################################
!# #
!# This is a module from the EDWIN Graphics Package, which was developed #
!# in the Department of Computer Science, at Edinburgh University, from #
!# 1978 to the present day, release 5 of EDWIN in October 1984. #
!# #
!# The principal author of the EDWIN Graphics Package was J Gordon Hughes, #
!# while working for the Edinburgh University Computer Sceince Department. #
!# Parts of EDWIN have been produced by many different people, too many #
!# too mention, working for different departments of Edinburgh and Leeds #
!# Universities. #
!# #
!# This module is regarded as being in the public domain, and the authors #
!# and accept no responsibility regarding the uses to which the software #
!# will be put. #
!# #
!############################################################################
! For systems where memory is a precious resource, the following constants
! can be set to -1, and the driver can still drive most CATs.
const integer MAX X = 131, MAX Y = 63
from Edwin include Device
from Edwin include Icodes
from Imp include Ascii
! Device configuration data -
const integer MIN CAT = -3
const integer Wide LP = -3
const integer Narr LP = -2
const integer Video = -1
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 VT100 = 5
const integer MAX CAT = 5
const integer array MODELS (MIN CAT:MAX CAT) = 'L', 'H', 'V', 200, 550, 120, 'E', 52, 100
const byte array ASPECT (MIN CAT:MAX CAT) = 50, 50, 45, 45, 45, 45, 45, 45, 45
const integer array MAXSXS (MIN CAT:MAX CAT) = 131, 72, 79, 79, 79, 79, 79, 79, 79
const integer array MAXSYS (MIN CAT:MAX CAT) = 63, 63, 23, 23, 23, 23, 23, 23, 23
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, MAX SY
own integer MODEL = MIN CAT - 1
own integer WX, WY, 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
own byte Had Newframe = False { Screen cleared on Terminate for bad emulators
own byte CURRENT COLOUR = 15, OVERWRITE MODE = 0, Fill Mode = 0
const byte array COLOUR (0:15) = ' ', '|', '=', '#', 'o', '$', '0', '@',
'.', ':', '"', '^', '%', '&', '+', '*'
const byte integer array EDWIN COLS (0:15) = 0, 15, 4, 1, 2, 6, 8, 5, 3, 7, 9, 10, 11, 12, 13, 14
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
const integer Char bit = 16_80
! The codes are held in SCREEN in the forms -
! 1 + 7 bits of char
! 0 - 4 bits of colour info.
routine ESC PLUS (integer SYM)
TTPUT (ESC)
TTPUT ('[') if MODEL=VT100
TTPUT (SYM)
end
routine DO MOVE
integer I
switch MS (0:MAX CAT)
return unless INTERACTS <= MODEL <= MAX CAT
return unless 0<=SX<=MAX SX and 0<=SY<=MAX SY
-> MS (MODEL)
MS(Visual 200):
MS(VT 52):
! GMOFF
ESC PLUS ('Y'); TTPUT (23-SY+32); TTPUT (SX+32)
return
MS(Bantam 550):
ESC PLUS ('Y'); TTPUT (SX+32)
ESC PLUS ('X'); TTPUT (23-SY+32)
return
MS(Soroc 120):
ESC PLUS ('='); TTPUT (32+23-SY); TTPUT (SX+32)
return
MS(HazeltineE): ESC PLUS (DC1)
if SX=0 then TTPUT ('`') else TTPUT (SX)
TTPUT ('w' - SY)
return
MS(VT100):
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)//10
TTPUT (I+'0') if I#0 { Suppress leading 0 }
TTPUT (REM(SX+1,10)+'0'); TTPUT ('H')
end
external routine VIDEOS alias "EDWIN___V" (integer COM, X, Y)
routine UPDATE
byte integer SP
integer I, J, K
! Draw the screen
if model < interacts and maxx>=0 and DIF=TRUE start
for I=YT,-1,0 cycle
for J=XR,-1, 0 cycle
exit if SCREEN_ROW(I)_COL(J)#0
repeat
for K=0,1,J cycle
SP = SCREEN_ROW(I)_COL(K)
if SP&Char Bit # 0 start; ! Character
TTPUT (SP&16_7F)
else
TTPUT (COLOUR (SP&15))
finish
repeat
TTPUT (13)
TTPUT (NL) if I>0
repeat
TTPUT (FF) if YT<63 and model=wide LP
else
DO MOVE if model >= interacts
finish
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.
const integer LX = -1, RX = 0, UY = 1, DY = -1, Z = 1 {Zero in X}
integer A,B,D,E,F,T,I,XMOVE,YMOVE,X,Y
own short array XCODE(1:16) = RX,Z,Z,Z,Z,Z,RX,Z,RX,LX,LX,LX,LX,LX,RX,LX
own short 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
integer fn New Cell (integer old)
! Combine the current colour with OLD, under the current overwrite mode
switch MS (0:4)
-> MS (Overwrite mode)
MS (0): result = Current Colour
MS (1): result = OLD & Current Colour
MS (2): result = OLD ! Current Colour
MS (3): result = OLD !! Current Colour
MS (4): result = ¬OLD
end
routine ADD
byte Old contents
byte name SP { screen pointer
if 0<=SX<=MAXX and 0<=SY<=MAXY start
SP == SCREEN_ROW(SY)_COL(SX)
Old contents = SP
return if SP&CHAR BIT#0 and overwrite mode#0 { character already in slot }
! Find out new contents of the screen
sp = New cell (sp)
return if MODEL<INTERACTS or Old Contents = sp
DO MOVE
TTPUT (COLOUR(SP))
finish
end
routine MOVE (integer X, Y)
ADD
SX = SX + X
SY = SY + Y
end
SWAP (SX, TX) and SWAP (SY, TY) if SX > TX; ! Optimise direction.
MOVE (0, 0) and return if SX=TX and SY=TY
if SY = TY start { Horisonal Line }
MOVE (1, 0) while SX <= TX
return
finish else if SX = TX start { Vertical line }
if SY > TY start
MOVE (0, -1) while SY >= TY
else { SY < TY }
MOVE (0, 1) while SY <= TY
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)
else
E = E + T
F = F - 1
MOVE (XMOVE, YMOVE)
finish
exit if F<=0
repeat
SX = TX; SY = TY; ADD
end
switch SW(0:MAX COM)
signal 14, 0 if INIT#TRUE and COM#0
-> SW(COM)
SW(0): ! Initialise
DEV DATA_NAME = "a type ".Itos(X,0)." terminal"
X = 200 if X=55
MODEL = MIN CAT - 1
for COM = MIN CAT, 1, MAX CAT cycle
MODEL = COM and exit if X=MODELS(COM)
repeat
signal 14, 0 if model=MIN CAT - 1
DEV DATA_DVX = MAX SXS (MODEL)
DEV DATA_DVY = MAX SYS (MODEL)
DEV DATA_MVX = MAX SXS (MODEL)
DEV DATA_MVY = MAX SYS (MODEL)
DEV DATA_ARF = ASPECT (MODEL)
DEV DATA_MAX COLOUR = 15
DEV DATA_NUM CHAR SIZES = 255
DEV DATA_NUM CHAR ROTS = 255
MAXSX = MAXSXS (MODEL)
MAXSY = MAXSYS (MODEL)
if model>=interacts start
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)
finish
!$IF IMP77
SCREEN == NIL
SCREEN == NEW (SCREEN)
!$FINISH
SCREEN = 0
TTMODE (1) unless model < interacts
INIT = TRUE
Had Newframe = False
return
SW(1): !Terminate
Videos (3, 0, 0) if Had Newframe # True
SX = 0; SY = 0 { -> bottom of screen }
UPDATE
!$IF IMP77
DISPOSE (SCREEN)
!$FINISH
TTMODE (0) unless MODEL<interacts
return
SW(2): ! Update
UPDATE
return
SW(3): ! New frame
Had Newframe = True
if MODEL>=INTERACTS start
TTPUT (RS) if MODEL=SOROC 120
ESC PLUS ('H') if MODEL=VT52
if MODEL=VT100 start
ESC PLUS ('2') and TTPUT (ERASE)
else
ESC PLUS (ERASE)
if MODEL=Bantam550 start
TTPUT (0) for Y=0,1,20
finish
finish
FLUSH OUTPUT
finish
SCREEN = 0
X = 0; Y = 0
-> SW(4)
SW(5): ! Line Abs
DRAW LINE (X, Y)
SW(4): ! Move Abs
SX = X; SY = Y
DO MOVE unless MODEL<INTERACTS
VIS = TRUE
DIF = TRUE
return
SW(6): ! Character
return unless VIS=TRUE
TTPUT (X) unless model < interacts and 0<=SX<MAXX
X = 0 if X = ' '
SCREEN_ROW(SY)_COL(SX) = X!CHAR BIT if MAX X >= 0
SX = SX + TCS
VIS = FALSE if SX>XR
DIF = TRUE
return
SW(7): ! Attribute Change
if X=att colour start
Y = 15 unless 0<=Y<=15
Current Colour = Edwin Cols (Y)
finish else if X = Att Colour mode start
Y = 0 unless 0<=Y<=4
Overwrite mode = Y
finish else if X = Att Shade mode start
Fill Mode = Y
finish
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.
for COM = Y, -1, WY cycle
SX = WX; SY = COM; DO MOVE; Draw line (X, SY)
repeat
return
SW(*):
end
external routine V REQ alias "EDWIN___V_REQ" (integer name CH,X,Y)
routine ESCAPE
TTPUT (ESC)
if MODEL=VT100 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 and MODEL=VISUAL200
CH = TTGET; ! The significant character of the ESC sequence.
if MODEL=VT100 start
CH = TTGET until 'A'<=CH<='D'
finish
if CH=CUR U start
Y =Y+1 if Y<23
ESCAPE; TTPUT (UP)
else
if CH=CUR R start
X =X+1 if X<79
ESCAPE; TTPUT (RIGHT)
else
if CH=CUR L start
X =X-1 if X>0
ESCAPE; TTPUT (LEFT)
else
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