! EDWIN 5.1 Sept 1984 !@16_1160 %real%fn float(%integer i) %include "inc:util.imp" %include "inc:maths.imp" %include "consts.inc" %include "icodes.inc" %include "specs.inc" !%external %integer %fn %spec MULDIV %alias "EDWIN___MUL_DIV" (%integer A, B, C) %include "CHARSPEC" ! Global Data for the EDWIN library - %external %record (DEVICE DATA FM) DEV DATA %alias "EDWIN___DEVICE_DATA" %external %record (DEVICE DATA FM) %map D DATA %alias "EDWIN_DEVICE_DATA" %result == record(addr(DEV DATA)) %end %external %integer VIEWING %alias "EDWIN___VIEWING" = 0 %external %integer STORING %alias "EDWIN___STORING" = -1 %external %integer CLIPPING %alias "EDWIN___CLIPPING" = 0 %include "EDCONFIG" ! control %own %integer VIS = 0; ! Current Char visibility %const %integer %array RA (0:3) = 0, 5, 3, 6 %own %integer %array ATTRIBUTES (0:15) = -1 (*) %const %integer %array DEF ATTRIBUTES (0:15) = { Colour } 1, { Line Style } 0, { Char size } 12, { Char rot } 0, { Char quality } 0, { Char font } 0, { Char slant } 0, { Maker size } 7, { Speed (max) } 0, { Colour mode } 0, { Shade mode } 0, { Chord step } 15, { Att 12 } 0, { Att 13 } 0, { Att 14 } 0, { Aspect ratio } 1 ! Screen information %own %integer XO = 0; ! Origin (bottom left) of device window %own %integer YO = 0 %own %integer XS = 1023; ! Size of device window %own %integer YS = 1023 %own %integer CX = 0; ! Current virtual position %own %integer CY = 0 %own %integer XV = 1023; ! Size of virtual window %own %integer YV = 1023 %own %integer XL = 0; ! Origin of virtual window (Left edge) %own %integer XR = 1023; ! (Right edge) %own %integer YB = 0; ! (Bottom edge) %own %integer YT = 1023; ! (Top edge) %own %integer OWXL=0, OWXR=1023, OWYB=0, OWYT=1023 ! Old Window bounds for aspect ratioing retrospectivly. %routine SWOP (%integer %name A,B) %integer C C=A; A=B; B=C %end %external %routine MAP TO DEVICE COORDS %alias "EDWIN_MAP_TO_DCS" (%integer %name X, Y) X = MUL DIV (X-XL, XS, XV) + XO Y = MUL DIV (Y-YB, YS, YV) + YO %end %external %routine MAP TO VIRTUAL COORDS %alias "EDWIN_MAP_TO_VCS" (%integer %name X, Y) X = MUL DIV (X-XO, XV, XS) + XL Y = MUL DIV (Y-YO, YV, YS) + YB %end %routine VECTOR (%integer FX, FY, TX, TY, V) ! Draw visible line from virtual coordinates (FX,FY) to (TX,TY). ! But if V = 0 just move to (TX,TY). %own %integer OTX = 0, OTY = 0 MAP TO DEVICE COORDS (FX,FY) MAP TO DEVICE COORDS (TX,TY) %if V#0 %start DRIVE DEVICE (4, FX, FY) %if OTX#FX %or OTY#FY DRIVE DEVICE (5, TX, TY) %finish %else DRIVE DEVICE (4, TX, TY) OTX = TX OTY = TY %end %external %routine CLIP %alias "EDWIN___CLIP" (%integer TX, TY, V) ! Draw a vector (visible if V#0) to virtual position (TX,TY) ! but only that part of it (if any) which lies within the virtual window %integer F, T, FX, FY %constinteger LEFT = 1, RIGHT = 2, ABOVE = 4, BELOW = 8 %integer %fn CODE (%integer X, Y) ! Set one bit for each of the conditions that (X,Y) lies ! above, below, to the left, or to the right of window %integer C C = 0 C = LEFT %if XXR C = C + ABOVE %if Y>YT C = C + BELOW %if Y IS (A&15) IS(0): IS(1): IS(2): IS(3): IS(4): IS(5): { Two Values which may be merged %if -128<=X<=127 %and -128<=Y<=127 %start WRITE (A ! 16, 1) WRITE ((X&255)<<8! Y&255, 1) -> Done %finish IS(6): IS(7): IS(8): IS(13): { Output both other values WRITE (A, 1); WRITE (X, 1); WRITE (Y, 1) -> Done IS(14): IS(15): { Output X value WRITE (A, 1); WRITE (X, 1) -> Done IS(9): IS(10): IS(11): IS(12): { No other values WRITE (A, 1) Done: NEWLINE SELECT OUTPUT (OOS) %end %external %routine SET ATTRIBUTE %alias "EDWIN___SET_ATTRIBUTE" (%integer WHAT, TO) %return %if ATTRIBUTES(WHAT) = TO ATTRIBUTES(WHAT) = TO TO = MUL DIV (TO, XS, XV) %if WHAT=2 { Character size } DRIVE DEVICE (7, WHAT, TO) %end %external %routine GET ATTRIBUTE %alias "EDWIN___GET_ATTRIBUTE" (%integer CODE, %integer %name VAL) VAL = ATTRIBUTES (CODE) %end %integer %fn CHAR OFFSET (%integer DIR) ! Dir is X or Y and the result is the current character offset in dir. %const %integer %array RX (0:3) = 1, 0, -1, 0 %const %integer %array RY (0:3) = 0, 1, 0, -1 %integer SIZE, ROT ROT = (ATTRIBUTES (3)//90)&3 SIZE = ATTRIBUTES (2) %result = SIZE * RX(ROT) %if DIR = 'X' %result = SIZE * RY(ROT) %end %routine DO ASPECT %integer MD, MV, N, ARF ARF = DEV DATA_ARF ARF = 100 %if ARF = 0 MD = Int ((Float(100000)*Float(YS)) / (Float(ARF)*Float(XS))) MV = MUL DIV (1000, |YT-YB|, |XR-XL|) %if MD#MV %start %if MD>MV %start N = (MUL DIV(MD,|XR-XL|,1000)+YB - YT)//2 YB = YB - N YT = YT + N %else N = (MUL DIV(1000,|YT-YB|,MD)+XL - XR)//2 XL = XL - N XR = XR + N %finish %finish %end %constinteger ONE=32; ! Internal representation of unity %own %integer MARKER SCALE = 1 %external %routine SET MARKER SIZE %alias "EDWIN_SET_MARK_SIZE" (%integer S) S = 1 %unless 0 < S < 256 PDF INSERT ((ATT MARKER SIZE << 8 ! S) << 4 ! PDF ATTRIBUTE, 0, 0) MARKER SCALE = S %end %routine %spec INTERPRET (%integer PC,SIZE,ROT) %external %routine MARKER %alias "EDWIN___MARKER" (%integer N) %const %integer %array MK(0:10) = '.', 'O', '#', 'A', 'X', '*', '+', '>', '<', 'V', '^' %integer scale ! This draws a marker at the current position. %return %unless 0<=N<=10 DRIVE DEVICE (6, MK(N), 0) %and %return %if DEV DATA_MVX<250 { VDU } SCALE = ONE SCALE = ONE * 10 %if DEV DATA_MVX>4095; ! For calcomps & HP plotters. SCALE = SCALE * MARKER SCALE INTERPRET (CHARPDF(2000-N*2), MUL DIV(SCALE, XV, XS), 0) %end %routine INTERPRET (%integer PC, SIZE, ORIENT) ! Interpret instructions in display file starting ! at (relative) PC until an END instruction is found ! Codes are 0 LINEA 1 MOVEA 2 MARKERA ! 3 LINER 4 MOVER 5 MARKERR ! 6 SUBPIC 7 END 8 WINDOW ! 9 CHAR 10 ATTRIBUTES 11 END %integer WORD, CODE, X, Y, Z, P, SSAVE, LSAVE, CSIZE, ACTIVE, OX, OY %switch C (0:15) ACTIVE = FALSE %cycle WORD = CHARPDF(PC); PC=PC+1 CODE=WORD&15 %if CODE<=5 %start; !Draw, Move, Marker ACTIVE = TRUE X = CHARPDF (PC); PC = PC + 1 %if WORD&16=0 %start; !Long form Y = CHARPDF (PC); PC = PC + 1 %finish%elsestart; !Short form Y=X&255; X=X>>8&255 X=X!!(\255) %if X&128#0 Y=Y!!(\255) %if Y&128#0 %finish %if CODE>=3 %start; !Relative %if ORIENT&4#0 %start; !Coordinate swop Z=X; X=Y; Y=Z %finish X=-X %if ORIENT&1#0; !Y-axis reflection Y=-Y %if ORIENT&2#0; !X-axis reflection !Change relative to absolute coords X = MUL DIV (X,SIZE,ONE) + CX Y = MUL DIV (Y,SIZE,ONE) + CY CODE=CODE-3; !Map to absolute codes %finish %finish ->C(CODE) C(0): CLIP (X, Y, 1); %continue { Line } C(1): CLIP (X, Y, 0); %continue { Move } C(2): CLIP (X, Y, 0); MARKER(WORD>>12&15) %repeat C(*): %signal 14, 5 C(12): %end !******************************************************************* !* * !* U S E R R O U T I N E S * !* * !******************************************************************* %external %routine TERMINATE EDWIN %alias "EDWIN_TERM" DRIVE DEVICE (1, 0, 0); ! Tell the device driver to Terminate PDF INSERT (12, 0, 0); ! Close the PDF if it was in use. VIEWING = 0 DEV DATA_DEV NO = -1 %end %external %routine LINE ABS %alias "EDWIN_LINE_ABS" (%integer X, Y) PDF INSERT(0,X,Y); CLIP(X,Y,1) %end %external %routine MOVE ABS %alias "EDWIN_MOVE_ABS" (%integer X, Y) PDF INSERT(1,X,Y); CLIP(X,Y,0) %end %external %routine MARKER ABS %alias "EDWIN_MARK_ABS" (%integer N, X, Y) PDF INSERT(N<<12!2,X,Y); CLIP(X,Y,0); MARKER (N) %end %external %routine LINE REL %alias "EDWIN_LINE_REL" (%integer DX, DY) PDF INSERT(3,DX,DY); CLIP(DX+CX,DY+CY,1) %end %external %routine MOVE REL %alias "EDWIN_MOVE_REL" (%integer DX, DY) PDF INSERT(4,DX,DY); CLIP(DX+CX,DY+CY,0) %end %external %routine MARKER REL %alias "EDWIN_MARK_REL" (%integer N, DX, DY) PDF INSERT(N<<12!5,DX,DY); CLIP(DX+CX,DY+CY,0); MARKER(N) %end %external %routine CHARACTER %alias "EDWIN_CHAR" (%integer SYM) %const %integer UNIT = 12 %integer SSAVE, LSAVE, SIZE, OX, OY %on 14 %start %signal 14, event_sub %if event_sub # 14 ATTRIBUTES (4) = 1 { software chars } -> resume %finish PDF INSERT (SYM<<4!9,0,0) Resume: { After a hardware character error } %if ATTRIBUTES(4)&1 = 0 %start DRIVE DEVICE (6, SYM, 0) %if VIS=0 CX = CX + CHAR OFFSET ('X'); CY = CY + CHAR OFFSET ('Y') %else %if ATTRIBUTES(1)#0 %start LSAVE = ATTRIBUTES(1) DRIVE DEVICE(7, 1, 0) %finish %else LSAVE = -1 %if ATTRIBUTES(5)=0 %start; ! Normal EDWIN ones SIZE = MUL DIV (ATTRIBUTES(2), ONE, UNIT) %if SIZE > 8 %and 32<=SYM<=127 %start OX = CX; OY = CY INTERPRET(CHARPDF(2000-(SYM-21)<<1), SIZE, RA(ATTRIBUTES(3)//90&3)) CLIP (OX + CHAR OFFSET ('X'), OY + CHAR OFFSET ('Y'), 0) %finish %else; ! GIMMS characters SSAVE = STORING; STORING = -1 DRAW CHAR (SYM, ATTRIBUTES(5), ATTRIBUTES(2), ATTRIBUTES(3)) STORING = SSAVE %finish DRIVE DEVICE (7, 1, LSAVE) %if LSAVE>=0 %finish %end %external %routine NEW FRAME %alias "EDWIN_NEW_FRAME" DRIVE DEVICE (3, 0, 0) PDF INSERT (11, 0, 0) CX = 0; CY = 0 %end %external %routine UPDATE %alias "EDWIN_UPDATE" DRIVE DEVICE (2, 0, 0) { All the work is done by the device driver } %end %external %routine CLIP ON %alias "EDWIN_CLIP_ON" CLIPPING = 0 %end %external %routine CLIP OFF %alias "EDWIN_CLIP_OFF" CLIPPING = DISABLED %end %external %routine STORE ON %alias "EDWIN_STORE_ON" (%integer STREAM) STORING = STREAM %end %external %routine STORE OFF %alias "EDWIN_STORE_OFF" STORING = DISABLED %end %external %routine VIEW ON %alias "EDWIN_VIEW_ON" (%integer STREAM) VIEWING = STREAM %end %external %routine VIEW OFF %alias "EDWIN_VIEW_OFF" VIEWING = DISABLED %end %external %routine WINDOW %alias "EDWIN_WINDOW" (%integer A, B, C, D) %signal 14, 12 %if A>=B %or C>=D XL = A; OWXL = A; XR = B; OWXR = B YB = C; OWYB = C; YT = D; OWYT = D PDF INSERT(8, A, B); PDF INSERT(8, C, D) DO ASPECT %if ATTRIBUTES(15)#0 XV = XR-XL; YV = YT-YB VIS = 0 A = ATTRIBUTES(2) %return %if A <= 0 { No size set up yet, Window having been called from Init } ATTRIBUTES (2) = 0 SET ATTRIBUTE (2, A) { Fix device character size for new window } %end %external %routine VIEWPORT %alias "EDWIN_VIEWPORT" (%integer XL, XR, YB, YT) %integer S %signal 14, 13 %if XL>=XR %or YB>=YT ! Choose the largest value if the upper bound is too large %return %if DEV DATA_DEV NO<=0 XL = 0 %if XL<0 YB = 0 %if YB<0 XR = DEV DATA_MVX %if XR>DEV DATA_MVX YT = DEV DATA_MVY %if YT>DEV DATA_MVY DRIVE DEVICE (8, XL, YB); ! Set lower window bounds DRIVE DEVICE (9, XR, YT); ! Set upper window bounds (If driver req.) XO=XL; XS=XR-XL; YO=YB; YS=YT-YB S = STORING STORING = DISABLED WINDOW (OWXL, OWXR, OWYB, OWYT) STORING = S %end %external %routine ASPECT RATIOING %alias "EDWIN_ASPECT_RATIO" (%integer MODE) %const %integer THIS = 15 %integer S MODE = 1 %unless MODE = 0 PDF INSERT ((THIS<<8 ! MODE) <<4 ! 10, 0, 0) SET ATTRIBUTE (THIS, MODE) S = STORING STORING = DISABLED WINDOW (OWXL, OWXR, OWYB, OWYT) STORING = S %end %external %routine INITIALISE FOR %alias "EDWIN_INIT" (%integer DEVICE TYPE) %integer I DRIVE DEVICE (0, DEVICE TYPE, 0); ! Initialise device driver I = DEV DATA_DEV NO VIEW PORT (0, DEV DATA_DVX, 0, DEV DATA_DVY) %if DEV DATA_DVX#0 WINDOW (0, 1023, 0, 1023) ATTRIBUTES (I) = -1 %for I = 0, 1, ATT MAXIMUM SET ATTRIBUTE (I, DEF ATTRIBUTES(I)) %for I = 0, 1, ATT MAXIMUM %end %external %routine INQUIRE POSITION %alias "EDWIN_INQ_POSITION" (%integer %name X, Y) X = CX; Y = CY %end %external %routine INQUIRE WINDOW %alias "EDWIN_INQ_WINDOW" (%integer %name A, B, C, D) A = XL; B = XR; C = YB; D = YT %end %external %routine INQUIRE VIEWPORT %alias "EDWIN_INQ_VIEWPORT" (%integer %name A, B, C, D) A = XO; B = XS+XO; C = YO; D = YS+YO %end %external %routine REQUEST INPUT %alias "EDWIN_REQUEST" (%integer %name STATE, X, Y) REQUEST DEVICE (STATE, X, Y) MAP TO VIRTUAL COORDS (X, Y) %end %external %routine SAMPLE INPUT %alias "EDWIN_SAMPLE" (%integer %name STATE, X, Y) SAMPLE DEVICE (STATE, X, Y) MAP TO VIRTUAL COORDS (X, Y) %end %external %routine AREA INPUT %alias "EDWIN_AREA" (%integer %name XL, YB, XR, YT) AREA DEVICE (XL, YB, XR, YT) MAP TO VIRTUAL COORDS (XL, YB) MAP TO VIRTUAL COORDS (XR, YT) %end !%end %of %file { Unless you want it all together } %include "EDATTRIB" %include "EDTEXT" %include "EDUTILS" %include "EDERRORS" %record %format POINT FM (%integer X, Y) %include "SHAPES.INC" %include "EDSHAPES" %include "EDREVIEW" %include "EDCIFSUP" %include "EDDEFDEV" %end %of %file