! 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