! EDWIN driver for the PRINTRONIX 300 Matrix printer
!############################################################################
!# #
!# 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. #
!# #
!############################################################################
! JGH November 1980, revised for Heap & Dept. program standards May 83
! Note requires though if this is to be moved to a system other than -
! VMS, MOUSES or EMAS
from Edwin include Device
from Edwin include Icodes
!%from Imp %include Predef
external routine P300 alias "EDWIN___P" (integer COM, X, Y)
own integer WX = 0, WY = 0
switch SW(0:MAX COM)
routine SWAP (integer name A, B)
integer C
C = A; A = B; B = C
end
const integer PLOT = 5; ! To indicate that the line is a plot line.
const integer FF = 12; ! Form Feed
! Nb - for MOUSES 664 x 780, for VMS and EMAS 791 x 780
const integer DOTS WIDE = 791 , DOTS HIGH = 779
const integer LINE MAX = DOTS WIDE//8 + 1
record format LINEF (byte integer array X (0:LINE MAX))
!$IF EMAS $START
!%own %record (LINEF) %array PAGE (0:DOTS HIGH)
!$ELSE
record format PAGEF (record(LINEF) array A (0:DOTS HIGH))
own record (PAGEF) name PAGE
!$FINISH
own byte DRAWN = FALSE
own integer SX = 0, SY = 0
own integer XL = 0, XR = Dots Wide, YB = 0, YT = Dots High
routine DRAW PAGE
const integer LINE BUFF LEN = (DOTS WIDE+5)//6 + 4 + 2
const integer LIM = LINE MAX // 3 * 3
string (LINE BUFF LEN) LINE BUFF
integer P, J, LB, I
byte name B
byte array name L
! 3-bit inversion table
constbyteintegerarray inverse(0:7) =
2_000, 2_100, 2_010, 2_110, 2_001, 2_101, 2_011, 2_111
! 0 1 2 3 4 5 6 7
for I = DOTS HIGH, -1, 0 cycle
!$IF EMAS $START
! L == PAGE(I)_X
!$ELSE
L == PAGE_A(I)_X
!$FINISH
LB = ADDR (LINE BUFF)
for J = ADDR(L(0)), 3, ADDR(L(LIM)) cycle
P = (((BYTE INTEGER(J)<< 8) ! BYTE INTEGER(J+1)) << 8) ! BYTE INTEGER (J+2)
BYTE INTEGER (LB + 4) = P&63; P = P >> 6
BYTE INTEGER (LB + 3) = P&63; P = P >> 6
BYTE INTEGER (LB + 2) = P&63; P = P >> 6
BYTE INTEGER (LB + 1) = P&63
LB = LB + 4
repeat
LENGTH(LINE BUFF) = LB - ADDR(LINE BUFF)
if LIM#LINE MAX start
P = 0
for J = LIM+1, 1, LINE MAX cycle
P = (P<<8)!L(J)
repeat
P = P << (8*(3-(LINE MAX - LIM)))
for J = 18, -6, 0 cycle
LINE BUFF = LINE BUFF.TO STRING((P>>J)&63)
repeat
finish
! Strip trailing spaces (represented by binary zero)
B == LENGTH(LINE BUFF)
B = B-1 while B>0 and CHARNO(LINE BUFF, B)=0
! Add various bits and characters required by Printronix printer
for j = addr(line buff)+1,1,lb cycle
p = byte integer(j)
byte integer(j) = inverse(p&7)<<3 ! inverse(p>>3) ! 64
repeat
TTPUT (CHARNO(LINE BUFF,J)) for J = 1, 1, LENGTH(LINE BUFF)
TTPUT (PLOT); TTPUT (NL)
FLUSH OUTPUT
repeat
DRAWN = FALSE
end
routine DRAW LINE (integer TX,TY)
! This is algorithm 162 in the Collected Algorithms from CACM.
! It computes the code string required to move the pen of a
! digital incremental X-Y plotter from an initial point (SX,SY) to
! a terminal point (TX,TY) 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.
integer A,B,D,E,F,T,I,XMOVE,YMOVE,X,Y
const byte integer array XCODE(1:16) = 4,0,0,0,0,0,4,0,4,5,5,5,5,5,4,5
const byte integer array YCODE(1:16) = 1,1,0,1,0,2,2,2,2,2,0,2,0,1,1,1
! 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 MOVE (integer X, Y)
! Move incrementaly over the screen.
SX = SX + 1 if X=0
SX = SX - 1 if X=5
SY = SY + 1 if Y=1
SY = SY - 1 if Y=2
end
routine MARK
! make mark in line buffer - represented as a linear bit string
byte integer name B
!$IF EMAS $START
! B == PAGE(SY)_X(SX>>3)
!$ELSE
b == page_a(sy)_x(sx>>3)
!$FINISH
A label to avert a compiler bug:
b = b ! (16_80 >> (sx&7) )
end
MARK and return if SX=TX and SY=TY
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
MARK
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
MARK
end
routine ZERO PAGE
integer I
!$IF EMAS $START
! PAGE (I) = 0 %for I = 0, 1, DOTS HIGH-1
!$ELSE
PAGE = 0
!$FINISH
SX = 0
SY = 0
end
-> SW (COM)
SW(0): ! Initialise
DEV DATA_NAME = "a Printronix printer"
DEV DATA_DVX = 791
DEV DATA_DVY = 779
DEV DATA_MVX = 791
DEV DATA_MVY = 779
DEV DATA_ARF = 120
if VIEWING = 0 start
VIEWING = NON TERMINAL DEFAULT
!$IF EMAS $START
! OPEN OUTPUT (VIEWING, "LP#LIS")
! %finish
!$ELSE
OPEN OUTPUT (VIEWING, "LP.LIS")
finish
PAGE == NEW (PAGE)
!$FINISH
!$IF EMAS OR MOUSES $START
! TTPUT (FF) { For machines with banners }
!$FINISH
ZERO PAGE
DRAWN = FALSE
return
SW(1): ! Terminate
DRAW PAGE if DRAWN = TRUE
!$UNLESS EMAS $START
DISPOSE (PAGE)
!$FINISH
return
SW(2): ! Update
return
SW(3): ! Newframe
DRAW PAGE if DRAWN = TRUE
ZERO PAGE
DRAWN = TRUE
return
SW(4): ! Move
SX = X
SY = Y
return
SW(5): ! Line
DRAW LINE (X,Y)
DRAWN = TRUE
return
SW(6): ! Character
signal 14, 14 { to get it done as a software character }
SW(8): ! Lower window bounds
XL = X; YB = Y
return
SW(9): ! Upper window bounds
XR = X; YT = Y
return
SW(10): ! ??
return
SW(11): ! Was overwrite mode
return
SW(12): ! Lower box bounds
WX = X; WY = Y
return
SW(13): ! Upper box bounds
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; Draw line (X, SY)
repeat
return
SW(*): ! Ignore all other commands
end
end of file