! EDWIN driver for Cursor Addressable Terminals and line printers. ! 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 %include "Edwin:device.inc" %include "Edwin:icodes.inc" ! Control characters %const %integer BS = 8, TAB = 9, VT = 11, FF = 12, CR = 13, SO = 14, SI = 15 %const %integer DLE = 16, DC1 = 17, ESC = 27, FS = 28, RS = 30, DEL = 127 ! 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 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 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 STYLE = 0 %const %integer dim = '4', bright = '3'; ! Intensity for Visual 200 %const %byte %integer %array AS(0:7) = '*', '-', '#', '+', '*', '$', '&', '@' %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 + 4 bits of code as above %routine ESC PLUS (%integer SYM) TTPUT (ESC) TTPUT ('[') %if MODEL=VT100 TTPUT (SYM) %end %routine GMON ! Enter Graphics mode. %return %if MODE=GON %or (MODEL#VISUAL200 %and MODEL#VT100) %if MODEL=VT100 %then TTPUT (SI) %else ESC PLUS (GON) MODE = GON %end %routine GMOFF ! Come out of graphics mode. %return %if MODE=GOFF %or (MODEL#VISUAL200 %and MODEL#VT100) %if MODEL=VT100 %then TTPUT (SO) %else ESC PLUS (GOFF) MODE = GOFF %end %routine DO MOVE %integer I %switch MS (0:MAX CAT) %return %unless INTERACTS <= MODEL <= MAX CAT -> 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, ST ! 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) SP = ' ' %if SP=0 %if SP&GMODE REQ#0 %start; ! Line ST = SP>>4&7; ! Line style TTPUT (AS(ST)) %finish %else TTPUT (SP) %repeat TTPUT (13) TTPUT (NL) %if I>0 %repeat TTPUT (FF) %if YT<63 %and model=wide LP %else DO MOVE %if model >= interacts GMOFF %if MODEL = VISUAL200 %start ESC PLUS (BRIGHT) { Default intensity } %finish %else %if MODEL = VT100 %start ESC PLUS (0); TTPUT ('m') { Default intensity } %finish %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. ! 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 STY { STYle << 4 } %byte %name SP { screen pointer %if MAXX>=0 %start SP == SCREEN_ROW(SY)_COL(SX) %return %if (SP#0 %and SP&G MODE REQ = 0) { character already in slot } STY = STYLE << 4 %return %if STY=(SP&16_70) %and P&(SP&15)=P { nothing new on screen } P = P ! (SP & 15) { OR in lines crossing in other directions. } SP = GMODEREQ ! STY ! P { Update the screen map } %finish %return %if MODEL nothing to do on Visual 200 or VT100, => optimise. %if model >= interacts %start DO MOVE %if STYLE#0 %then TTPUT (AS(STYLE)) %else %start %if MODEL=Bantam550 %start ESC PLUS (DEL) %finish %else %if MODEL=VISUAL200 %start GMON; TTPUT (CODE 200 (P)) %finish %else %if MODEL=VT100 %start GMON; TTPUT (CODE 100 (P)) %finish %else TTPUT ('*') %finish %finish %end %routine MOVE (%integer X, Y) %const %integer SPLOGE = 15 { line from point in all directions } %if STYLE#0 %or (MODEL#VISUAL200 %and MODEL#VT100) %start ADD (SPLOGE) %if X=0 %start SX = SX + 1 %finish %else %if X=5 %start SX = SX - 1 %finish %if Y=1 %start SY = SY + 1 %finish %else %if Y=2 %start SY = SY - 1 %finish %else %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 %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 STYLE = 0 %and (MODEL=VT100 %or MODEL=VISUAL200) %start %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 } %finish 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 MOVE (TX, TY) %unless (MODEL=VISUAL200 %or MODEL=VT100) %and STYLE=0 %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_ARF = ASPECT (MODEL) DEV DATA_DVX = MAX SXS (MODEL) DEV DATA_DVY = MAX SYS (MODEL) DEV DATA_MVX = MAX SXS (MODEL) DEV DATA_MVY = MAX SYS (MODEL) 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 TTPUT (ESC) %and TTPUT ('(') %and TTPUT ('0') %if MODEL=VT100 { enable graphics characters } INIT = TRUE %return SW(1): !Terminate SX = 0; SY = 0 { -> bottom of screen } UPDATE %if model=vt100 %then %start TTPUT (ESC); TTPUT ('('); TTPUT ('B') { Default char set } %finish !$IF IMP77 DISPOSE (SCREEN) !$FINISH TTMODE (0) %unless MODEL=INTERACTS %start TTPUT (RS) %if MODEL=SOROC 120 ESC PLUS ('H') %if MODEL=VT52 %if MODEL=VT100 %then ESC PLUS ('2') %and TTPUT (ERASE) %c %else ESC PLUS (ERASE) %if MODEL=Bantam550 %start TTPUT (0) %for Y=0,1,20 %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= 0 SX = SX + TCS VIS = FALSE %if SX>XR DIF = TRUE %return SW(7): ! Attribute Change %if X=att line style %start STYLE = Y&7 %finish %else %if X=att colour %start %if MODEL = VISUAL200 %start %if 1MAX SX YT = Y YT = MAX SY %if YT>MAX SY %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= ' '; ! 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