C*ACDRIV -- PGPLOT device driver for Acorn Archimedes machines C+ SUBROUTINE ACDRIV (IFUNC, RBUF, NBUF, CHR, LCHR, MTYPE) INTEGER IFUNC, NBUF, LCHR, MTYPE REAL RBUF(*) CHARACTER*(*) CHR, DEFNAM C C PGPLOT driver for Acorn Archimedes C This driver will cause the system to leave the Desktop, but leave the C screen mode provided it has the normal 16 colours C C This routine must be compiled with Acorn Fortran release 2 C and linked with the Fortran Friends graphics, utils and spriteop libraries. C C 26 January 1996 : Version 1.10 C 16 May 1996 : Version 1.11 allows concurrent /ARCF and ARCV C C Resolution: Depends on graphics mode. Ensure that the current mode is C suitable before running the PGPLOT program. C C version 1.10 also allows the making of the pictures into sprite files C the default sprite size is the screen size but you may alter the C number of pixels in x and y with the variables: C PGPLOT_ARC_WIDTH and PGPLOT_ARC_HEIGHT C the file names will be sprite/01, sprite/02 etc. PARAMETER (DEFNAM = 'sprite/01') C C 26 April 1996 : Version 1.11 (changes to /ARCV) C - small corrections to the initial screen clearing C - allows standard PGPLOT rubber-banded cursors C--- C common for communicating with rubber banding GRARC3 COMMON /GRARCC/ MAXX(2), MAXY(2), I4X0, I4Y0, I4X1, I4Y1, I4MODE INTEGER MAXX, MAXY, I4X0, I4Y0, I4X1, I4Y1, I4MODE C INTEGER NXPIX(2), NYPIX(2), MULTX(2), MULTY(2), IXSTEP(2) SAVE NXPIX, NYPIX, MULTX, MULTY, IXSTEP INTEGER NCOLR, NEEDSP, KOLNOW(2), KOLOUR(0:255) SAVE NCOLR, NEEDSP, KOLNOW, KOLOUR LOGICAL INIT, APPEND, FIRSTO, INPICT(2), STATE(2) SAVE INIT, APPEND, FIRSTO, INPICT, STATE INTEGER IERR, I4X2, I4Y2, MBUF(2), IREGS(0:9), ISCRR(4) LOGICAL SWIERR, SWIF77, SPOP08, SPOP15, LOGDUM CHARACTER ANS*4, INSTR*10, SPNAME*9 DATA INIT/.TRUE./, STATE/2*.FALSE./ DATA KOLOUR/?I00000000, ?IFFFFFF00, ?I0000FF00, ?I00FF0000, 1 ?IFF000000, ?IFFFF0000, ?IFF00FF00, ?I00FFFF00, 2 ?I0080FF00, ?I00FF8000, ?I80FF0000, ?IFF800000, 3 ?IFF008000, ?I8000FF00, ?I50505000, ?IA0A0A000, 4 240*0/ IF(INIT .AND. IFUNC.GT.1) THEN C check for 16-colour mode NCOLR = MODEVAR(-1, 3) IF(NCOLR.EQ.63) NCOLR = 255 IF(NCOLR.EQ.-1) NCOLR = ?IFFFFFF IF(NCOLR.LT.15) THEN CALL GRWARN('Archimedes driver needs at least 16 colours') NBUF = -1 RETURN ENDIF INIT = .FALSE. C get screen characteristics DO 8 MTP = 1, 2 NXPIX(MTP) = MODEVAR(-1, 11) + 1 NYPIX(MTP) = MODEVAR(-1, 12) + 1 IF(MTP.EQ.1) THEN MULTX(1) = MODEVAR(-1, 4) MULTY(1) = MODEVAR(-1, 5) ELSE SPNAME = DEFNAM CALL GRGENV('ARC_WIDTH', INSTR, L) IF(L.GT.0) READ(INSTR, 4)NXPIX(2) 4 FORMAT(BN, I10) CALL GRGENV('ARC_HEIGHT', INSTR, L) IF(L.GT.0) READ(INSTR, 4)NYPIX(2) MULTX(2) = 1 MULTY(2) = 1 ENDIF IXSTEP(MTP) = ISHFT(1, MULTX(MTP)) MAXX(MTP) = ISHFT(NXPIX(MTP), MULTX(MTP)) MAXY(MTP) = ISHFT(NYPIX(MTP), MULTY(MTP)) INPICT(MTP) = .FALSE. 8 CONTINUE ENDIF IF(IFUNC.GT.9 .AND. .NOT.STATE(MTYPE)) THEN CALL GRWARN('Device is not open') NBUF = -1 RETURN ENDIF GOTO( 10, 20, 30, 40, 50, 60, 70, 80, 90,100, 1 110,120,130,140,150,160,170,180,190,200, 2 210,220,230,240,250,260,270,280,290) IFUNC C unknown driver function, so just return NBUF = -1 RETURN C C--- IFUNC = 1, Return device name.------------------------------------- C 10 IF(MTYPE.EQ.1) THEN CHR = 'ARCV (screen viewer for Acorn Archimedes machines)' LCHR = LNBLNK(CHR) ELSEIF(MTYPE.EQ.2) THEN CHR = 'ARCF (sprite file for Acorn Archimedes machines)' LCHR = LNBLNK(CHR) ELSE CALL GRWARN('Requested MODE not implemented in Archi driver') LCHR = 0 NBUF = -1 ENDIF RETURN C C--- IFUNC = 2, Return physical min and max for plot device, and range C of color indices.--------------------------------------- C 20 CONTINUE RBUF(1) = 0 RBUF(2) = MAXX(MTYPE) RBUF(3) = 0 RBUF(4) = MAXY(MTYPE) RBUF(5) = 0 RBUF(6) = MIN(255, NCOLR) NBUF = 6 RETURN C C--- IFUNC = 3, Return device resolution. ------------------------------ C Divide the number of pixels on screen by a typical screen size in C inches. C 30 continue RBUF(1) = MAXX(MTYPE)/10.0 RBUF(2) = RBUF(1) RBUF(3) = FLOAT(ISHFT(1, MULTX(MTYPE))) NBUF = 3 RETURN C C--- IFUNC = 4, Return misc device info. ------------------------------- C (This device is Interactive, cursor, No dashed lines, No area fill, C No thick lines, rectangle fill) C 40 IF(MTYPE.EQ.1) THEN CHR = 'ICNNNRPVYN' ELSE CHR = 'HNNNNRPNYN' ENDIF LCHR = 10 NBUF = 0 RETURN C C--- IFUNC = 5, Return default file name. ------------------------------ C 50 IF(MTYPE.EQ.1) THEN CHR = ' ' LCHR = 1 ELSE CHR = SPNAME LCHR = 9 ENDIF RETURN C C--- IFUNC = 6, Return default physical size of plot. ------------------ C 60 CONTINUE RBUF(1) = 0 RBUF(2) = MAXX(MTYPE) RBUF(3) = 0 RBUF(4) = MAXY(MTYPE) NBUF = 4 RETURN C C--- IFUNC = 7, Return misc defaults. ---------------------------------- C 70 RBUF(1) = 1 NBUF = 1 RETURN C C--- IFUNC = 8, Select plot. ------------------------------------------- C 80 CONTINUE RETURN C C--- IFUNC = 9, Open workstation. -------------------------------------- C 90 CONTINUE C -- check for concurrent access IF (STATE(MTYPE)) THEN CALL GRWARN('Device is already open') RBUF(2) = 0 ELSE IF(MTYPE.EQ.1) THEN C flag to erase screen on next picture FIRSTO = .TRUE. C set append flag to suppress screen clearing on subsequent pictures APPEND = RBUF(3).NE.0. ENDIF C flag the workstation active STATE(MTYPE) = .TRUE. C but not generating picture yet INPICT(MTYPE) = .FALSE. C RBUF(2) = 1 END IF RBUF(1) = 0 NBUF = 2 RETURN C C--- IFUNC = 10, Close workstation. ------------------------------------ C 100 CONTINUE C flag the workstation inactive STATE(MTYPE) = .FALSE. IF(MTYPE.EQ.1) THEN C reset the 16 colour palette IF(NCOLR.EQ.15) CALL VDU(20) C clear the screen CALL CLS ENDIF RETURN C C--- IFUNC = 11, Begin picture. ---------------------------------------- C 110 CONTINUE IF(MTYPE.EQ.1 .AND. (.NOT.APPEND .OR. FIRSTO)) THEN CALL GRARC2(0, 0, -NCOLR, KOLOUR) C remove viewports and clear screen to background colour CALL VDU(26) CALL CLG C home the text cursor CALL VDU(30) C set foreground text colour IF(NCOLR.EQ.15) CALL COLOUR(1) C remove pointer CALL OSCLI('Pointer 0') ENDIF FIRSTO = .FALSE. IERR=0 IF(MTYPE.EQ.2) THEN C create sprite LBPPIX = MODEVAR(-1, 9) NBYTES = ISHFT(NXPIX(2)*NYPIX(2), LBPPIX)/8 + 64 C first ensure there is space in system sprite area IF(.NOT.SPOP08(0, ISPSIZ, NSPRIT, ISPR1, IFREE)) THEN C case 1, no system sprite area yet NEEDSP = NBYTES + 16 + 44 ELSE C case 2, system sprite area exists C remove any of our sprites which may have been left by accident 112 DO 114 ISPRIT = 1, NSPRIT CALL SPOP13(0, ISPRIT, INSTR,LENG) IF(INSTR(1:7).EQ.'sprite/'.AND.LENG.EQ.9) THEN CALL SPOP25(0, INSTR(1:9)) NSPRIT = NSPRIT -1 GO TO 112 ENDIF 114 CONTINUE LOGDUM = SPOP08(0, ISPSIZ, NSPRIT, ISPR1, IFREE) NEEDSP = NBYTES + 44 - ISPSIZ + IFREE ENDIF IERR = 0 IF(NEEDSP.GT.0) THEN IREGS(0) = 3 IREGS(1) = NEEDSP IF(SWIF77(?I2A, IREGS, IFLAG)) IERR = 100 IF(IERR.EQ.0) THEN IF(IREGS(1).GE.NEEDSP) THEN C successfully assigned memory NEEDSP = IREGS(1) ELSE IERR = 101 ENDIF ENDIF ENDIF C create sprite IF(IERR.EQ.0) THEN IF(NCOLR.EQ.15) THEN C create it with palette in 16 colour mode SWIERR = SPOP15(0, SPNAME, 1, NXPIX(2), NYPIX(2), 27) ELSEIF(NCOLR.EQ.255) THEN SWIERR = SPOP15(0, SPNAME, 0, NXPIX(2), NYPIX(2), 28) ELSE C create sprite 'mode word' (PRM 5-87) MODEW = IOR(?I1680B5, ISHFT(LBPPIX + 1, 27)) SWIERR = SPOP15(0, SPNAME, 0, NXPIX(2), NYPIX(2), MODEW) ENDIF IF(SWIERR) IERR = 103 IF(IERR.EQ.0) CALL GRWARN('creating sprite '//SPNAME) ENDIF IF(IERR.NE.0) THEN CALL GRGMSG(IERR) CALL GRWARN('Failed to allocate plot buffer.') C failed to get enough memory so return it IF(IERR.GT.100) THEN IREGS(1) = -IREGS(1) IF(SWIF77(?I2A, IREGS, IFLAG)) THEN IERR = 101 ELSE IERR = 102 ENDIF ENDIF ENDIF ENDIF C set up colours IF(IERR.EQ.0) THEN IF(NCOLR.EQ.15) THEN DO 118 I = 0, 15 IF(MTYPE.EQ.2) THEN CALL GRARC1(SPNAME, I, KOLOUR(I)) ELSE CALL VDU19(I, 16, 1 IAND(ISHFT(KOLOUR(I), -8), 255), 2 IAND(ISHFT(KOLOUR(I), -16), 255), 3 ISHFT(KOLOUR(I), -24)) ENDIF 118 CONTINUE ELSEIF(MTYPE.EQ.2) THEN C clear 255 colour sprite to background colour CALL SPOP60(0, SPNAME, 0, ISCRR) CALL GRARC2(0, 0, -NCOLR, KOLOUR) CALL CLG CALL NPOP60(ISCRR) ENDIF ENDIF IF(IERR.EQ.0) INPICT(MTYPE) = .TRUE. RETURN C C--- IFUNC = 12, Draw line. -------------------------------------------- C 120 CONTINUE IF(INPICT(MTYPE)) THEN IF(MTYPE.EQ.2) CALL SPOP60(0, SPNAME, 0, ISCRR) CALL GRARC2(0, KOLNOW(MTYPE), NCOLR, KOLOUR) CALL LINE(NINT(RBUF(1)), NINT(RBUF(2)), 1 NINT(RBUF(3)), NINT(RBUF(4))) IF(MTYPE.EQ.2) CALL NPOP60(ISCRR) ENDIF RETURN C C--- IFUNC = 13, Draw dot. --------------------------------------------- C 130 CONTINUE IF(INPICT(MTYPE)) THEN IF(MTYPE.EQ.2) CALL SPOP60(0, SPNAME, 0, ISCRR) CALL GRARC2(0, KOLNOW(MTYPE), NCOLR, KOLOUR) CALL SPOT(NINT(RBUF(1)), NINT(RBUF(2))) IF(MTYPE.EQ.2) CALL NPOP60(ISCRR) ENDIF RETURN C C--- IFUNC = 14, End picture. ------------------------------------------ C 140 CONTINUE IF(INPICT(MTYPE).AND.MTYPE.EQ.2) THEN C write out sprite CALL SPOP12(0, SPNAME) C delete sprite CALL SPOP25(0, SPNAME) C update sprite name I = ICHAR(SPNAME(9:9)) + 1 IF(I.LT.58) THEN SPNAME(9:9) = CHAR(I) ELSE SPNAME(8:9) = CHAR(ICHAR(SPNAME(8:8)) + 1)//'0' ENDIF C give back memory IF(NEEDSP.GT.0) THEN IREGS(0) = 3 IREGS(1) = -NEEDSP IF(SWIF77(?I2A, IREGS, IFLAG)) THEN CALL GRGMSG(104) CALL GRWARN('Failed to deallocate plot buffer.') ENDIF ENDIF ENDIF INPICT(MTYPE) = .FALSE. RETURN C C--- IFUNC = 15, Select color index. ----------------------------------- 150 CONTINUE KOLNOW(MTYPE) = NINT(RBUF(1)) RETURN C C--- IFUNC = 16, Flush buffer. ----------------------------------------- C 160 CONTINUE RETURN C C--- IFUNC = 17, Read cursor. ------------------------------------------ C 170 CONTINUE IF(MTYPE.EQ.2) RETURN C display pointer CALL OSCLI('Pointer') C wait until button(s) and keys are released 172 CALL MOUSE(I4X0, I4Y0, I4B) IF(I4B.NE.0 .OR. INKEY(0).GT.0) GO TO 172 C move to desired place I4X0 = NINT(RBUF(1)) I4Y0 = NINT(RBUF(2)) MBUF(1) = 5 + IOR(ISHFT(I4X0, 8), ISHFT(I4Y0, 24)) MBUF(2) = ISHFT(I4Y0, -8) CALL OSWORD(21, MBUF) C anchor position I4X1 = NINT(RBUF(3)) I4Y1 = NINT(RBUF(4)) C band mode I4MODE = NINT(RBUF(5)) C initial band IF(I4MODE.GT.0) THEN C set colour of banding CALL GRARC2(3, KOLNOW(MTYPE), NCOLR, KOLOUR) CALL GRARC3 ENDIF C loop and wait for keystroke/button click 174 CONTINUE C get mouse pointer status CALL MOUSE(I4X2, I4Y2, I4B) C check for key press KEY = INKEY(0) C 'select' = 'A' IF(I4B.EQ.4) KEY = 65 C 'menu' = 'D' IF(I4B.EQ.2) KEY = 68 C 'adjust' = 'X' IF(I4B.EQ.1) KEY = 88 IF(I4MODE.GT.0) THEN IF(I4X2.NE.I4X0 .OR. I4Y2.NE.I4Y0) THEN C wait for frame scan CALL OSBYTE(19,0,0) C clear the old band CALL GRARC3 C move the band I4X0 = I4X2 I4Y0 = I4Y2 C draw the new band CALL GRARC3 ENDIF ENDIF IF(KEY.LE.0) GO TO 174 C erase final band IF(I4MODE.GT.0) CALL GRARC3 C return current position RBUF(1) = FLOAT(I4X2) RBUF(2) = FLOAT(I4Y2) NBUF = 2 C and character CHR(1:1) = CHAR(KEY) LCHR = 1 RETURN C C--- IFUNC = 18, Erase alpha screen. ----------------------------------- C 180 CONTINUE RETURN C C--- IFUNC = 19, Set line style. --------------------------------------- C 190 CONTINUE RETURN C C--- IFUNC = 20, Polygon fill. ----------------------------------------- C 200 CONTINUE RETURN C C--- IFUNC = 21, Set color representation. ----------------------------- C 210 CONTINUE ICOL = NINT(RBUF(1)) IRED = NINT(RBUF(2)*255.) IGRN = NINT(RBUF(3)*255.) IBLU = NINT(RBUF(4)*255.) KOLOUR(ICOL) = ISHFT(IBLU, 24) + ISHFT(IGRN, 16) + ISHFT(IRED, 8) IF(NCOLR.EQ.15.AND.INPICT(MTYPE)) THEN IF(MTYPE.EQ.2) THEN CALL GRARC1(SPNAME, ICOL, KOLOUR(ICOL)) ELSE CALL VDU19(ICOL, 16, IRED, IGRN, IBLU) ENDIF ENDIF RETURN C C--- IFUNC = 22, Set line width. --------------------------------------- C 220 CONTINUE RETURN C C--- IFUNC = 23, Escape. ----------------------------------------------- C 230 CONTINUE RETURN C C--- IFUNC = 24, Rectangle fill. --------------------------------------- C 240 CONTINUE IF(INPICT(MTYPE)) THEN IF(MTYPE.EQ.2) CALL SPOP60(0, SPNAME, 0, ISCRR) CALL GRARC2(0, KOLNOW(MTYPE), NCOLR, KOLOUR) CALL RECTAN(NINT(RBUF(1)), NINT(RBUF(2)), 1 NINT(RBUF(3)), NINT(RBUF(4)), .TRUE.) IF(MTYPE.EQ.2) CALL NPOP60(ISCRR) ENDIF RETURN C C--- IFUNC = 25, Set fill pattern. ------------------------------------- C 250 CONTINUE RETURN C C--- IFUNC = 26, Line of pixels. --------------------------------------- C 260 CONTINUE IF(.NOT.INPICT(MTYPE)) RETURN IF(MTYPE.EQ.2) CALL SPOP60(0, SPNAME, 0, ISCRR) IX = NINT(RBUF(1)) IY = NINT(RBUF(2)) K1 = NINT(RBUF(3)) IX1 = IX DO 264 I = 3 + IXSTEP(MTYPE), NBUF, IXSTEP(MTYPE) K2 = NINT(RBUF(I)) IF(K1.NE.K2) THEN CALL GRARC2(0, K1, NCOLR, KOLOUR) IF(IX.EQ.IX1) THEN CALL SPOT(IX, IY) ELSE CALL LINE(IX1, IY, IX, IY) ENDIF K1 = K2 IX1 = IX + IXSTEP(MTYPE) ENDIF IX = IX + IXSTEP(MTYPE) 264 CONTINUE CALL GRARC2(0, K2, NCOLR, KOLOUR) IF(IX.EQ.IX1) THEN CALL SPOT(IX, IY) ELSE CALL LINE(IX1, IY, IX, IY) ENDIF IF(MTYPE.EQ.2) CALL NPOP60(ISCRR) RETURN C C--- IFUNC = 27, Not implemented --------------------------------------- C 270 CONTINUE RETURN C C--- IFUNC = 28, Not implemented --------------------------------------- C 280 CONTINUE RETURN C C--- IFUNC = 29, Query color representation. --------------------------- C 290 CONTINUE I = RBUF(1) RBUF(2) = IAND(ISHFT(KOLOUR(I), -8), 255)/255.0 RBUF(3) = IAND(ISHFT(KOLOUR(I), -16), 255)/255.0 RBUF(4) = IAND(ISHFT(KOLOUR(I), -24), 255)/255.0 NBUF = 4 RETURN C----------------------------------------------------------------------- END C SUBROUTINE GRARC1(SPNAME, I, KOL) DIMENSION IREGS(0:9) CHARACTER *(*) SPNAME, NAME*12 EQUIVALENCE(IPP, IREGS(4)) LOGICAL SWIF77 C set sprite palette I to KOL (Only in RISC-OS 3) NAME = SPNAME L = LNBLNK(NAME) NAME(L+1:L+1) = CHAR(0) IREGS(0) = 37 IREGS(1) = 0 IREGS(2) = LOCC(NAME) IREGS(3) = -1 C do SpriteOp 37 IF(SWIF77(?I2E, IREGS, IFLAG))RETURN IF(IPP.EQ.0) RETURN IOFF = (IPP - LOC(IREGS))/4 C address of palette is now IREGS(IOFF) KK = IOR(16, IAND(KOL, ?IFFFFFF00)) IREGS(IOFF+I+I) = KK IREGS(IOFF+I+I+1) = KK RETURN END C SUBROUTINE GRARC2(IACT, KOLNOW, NCOLR, KOLOUR) C set up currrent graphics colour and action DIMENSION IREGS(0:9), KOLOUR(0:255) IF(IABS(NCOLR).EQ.15) THEN IF(NCOLR.GT.0) THEN CALL GCOL(IACT, KOLNOW) ELSE CALL GCOL(IACT, KOLNOW + 128) ENDIF ELSE IREGS(0) = KOLOUR(KOLNOW) IREGS(3) = 0 IF(NCOLR.LT.0) IREGS(3)=128 IREGS(4) = IACT C do ColourTrans_SetGCOL CALL SWIF77(?I040743, IREGS, IFLAG) ENDIF RETURN END C SUBROUTINE GRARC3 C common for communicating with rubber banding GRARC3 COMMON /GRARCC/ MAXX(2), MAXY(2), I4X0, I4Y0, I4X1, I4Y1, I4MODE INTEGER MAXX, MAXY, I4X0, I4Y0, I4X1, I4Y1, I4MODE C only used for MTYPE=1, i.e. MAXX(1) and MAXY(1) C C draw band of type I4MODE from (I4X1,I4Y1) to (I4X0,I4Y0) C I4MODE = 1: ordinary rubber band C 2: rectangular box C 3: horizontal lines C 4: vertical lines C 5: horizontal line through (I4X0,I4Y0) only C 6: vertical line through (I4X0,I4Y0) only C 7: vertical and horizontal lines through (I4X0,I4Y0) only C GO TO (10, 20, 30, 40, 32, 42, 70), I4MODE RETURN C ordinary rubber band 10 CALL LINE(I4X1, I4Y1, I4X0, I4Y0) RETURN C rectangular box 20 CALL RECTAN(I4X1, I4Y1, I4X0, I4Y0, .FALSE.) RETURN C horizontal lines 30 CALL LINE(0, I4Y1, MAXX, I4Y1) 32 CALL LINE(0, I4Y0, MAXX, I4Y0) RETURN C vertical lines 40 CALL LINE(I4X1, 0, I4X1, MAXY) 42 CALL LINE(I4X0, 0, I4X0, MAXY) RETURN C vertical and horizontal lines through (I4X0,I4Y0) only 70 CALL LINE(0, I4Y0, MAXX, I4Y0) GO TO 42 END