! EDWIN driver for the HP plotter range.

!VAX!%include "Edwin_dir:device.inc"
!VAX!%include "Edwin_dir:icodes.inc"
!VAX!%include "Imp_include:maths.inc"

{APM} %Include "Edwin:device.inc"
{APM} %Include "Edwin:icodes.inc"
{APM} %include "inc:maths.imp"
{APM} %Include "inc:util.imp"

!VAX!%external %string (127) %fn %spec TRANSLATE (%string (127) name)
!%const %real D TO R = 57.2958; ! Magic number converts degrees to rads.

{APM}%systemstring(127)%fn newrtos(%real r,%integer n,m)
{APM}  %constreal pmax = 2147483647.0
{APM}  %real y,z
{APM}  %integer i=0,l,count=0,sign
{APM}  %string(127) result = ""
{APM}  !
{APM}  sign = ' '
{APM}  sign = '-' %if r < 0
{APM}  y = |r|+0.5/10.0\{^}m;  !modulus, rounded
{APM}  %if y > pmax %start
{APM}    count = count+1 %and y = y/10.0 %until y < 10.0
{APM}  %finish
{APM}  z = 1.0
{APM}  %cycle
{APM}    i = i+1;  z = z*10.0
{APM}  %repeat %until z > y
{APM}{}  %If n-i > 0 %Start
{APM}     result = result." " %for l = 1,1,n-i;  !l not used before here
{APM}{}  %Finish
{APM}  result = result.tostring(sign) %unless sign = ' ' %and n <= 0
{APM}  %cycle
{APM}    z = z/10.0
{APM}    l = int pt(y/z)
{APM}    y = y-l*z
{APM}    result = result.tostring(l+'0')
{APM}    i = i-1
{APM}    %exit %if i+m <= 0
{APM}    result = result."." %if i = 0
{APM}  %repeat
{APM}  result = result."@".itos(count,0) %if count # 0
{APM}  %result = result
{APM}%end;  !newrtos

! Control characters
%const %integer ETX = 3
%const %integer ESC =27
%const %integer DEL = 127
! The following should be an external integer spec to the UTILITY module.
%const %integer BUFF SIZE = 251

! Screen information
%own %integer PLOT ACTIVE = FALSE;  ! FALSE => using terminal, TRUE => PLOTTER active
%own %integer LAST COM = 0;   ! Used to optimise lines in the HP protocol
%own %integer SX = 0;         ! Current device position
%own %integer SY = 0
%own %integer XL = 0, YB = 0; ! Lower window bounds.
%own %integer YT = 25 * 400;  ! Upper device window bound.
%own %integer XR = 40 * 400;  ! Right hand side of device window
%own %byte CUR COL = 1;       ! Current colour.
%own %byte PM = FALSE;        ! Pending move.
%own %byte PC = FALSE;        ! Pending colour change.
%own %byte LOW QUAL = TRUE;   ! Character Quality, FALSE => proportional spaced sets
%own %byte NEWFRAMED = FALSE; ! TRUE => NEW FRAME done
%own %byte TEXT MODE = FALSE; ! TRUE while in text mode
%own %byte INTERACTIVE = TRUE { Set up when device is initailised
%own %byte ERCC HP = FALSE    { True => Off set Y values by 700 for paper feed
%own %integer INBUFF = 32;    ! This is the initialisation code

! Configuration parameters -

%const %integer MAX ATTRIBUTE = 8
%const %integer MAX COLOUR = 16
%const %integer MAX LINE = 6
%const %integer NUM HP = 7
%const %integer HP7221 = 0, HP7220 = 1, HP7580 = 2, HP7585 = 3, HP7500 = 4
%const %integer HP7586 = 5, HP7470 = 6, HP7475 = 7 
%own %integer current dev = HP7221
%const %short %array DEV NUMS (0:NUM HP) =  7221,  7220,   7580,   7585,   7500,   7586,   7470,   7475
%own   %byte %array  NUM PENS (0:NUM HP) =     4,     4,      8,      8,      8,      8,      2,      6
%const %byte %array INTERACTS (0:NUM HP) =  TRUE,  TRUE,   TRUE,   TRUE,  FALSE,   TRUE,   TRUE,   TRUE
%own %integer %array   X BASE (0:NUM HP) =     0,     0,  -7600,  -7600,  -7500,  -7600,      0,      0
%own %integer %array   Y BASE (0:NUM HP) =     0,     0,  -5700,  -5700,  -7500,  -5700,      0,      0
%const %integer %array  MAX X (0:NUM HP) = 16000, 16000, 90*400,119*400,119*400,119*400,  10900,  16000
%const %integer %array  MAX Y (0:NUM HP) = 11400, 11400, 60*400, 90*400, 90*400, 90*400,   7650,  11040
! The following line is for VAX only, if the plotter is an independant device
%const %string (4) %array TERMS (0:NUM HP) =    "7221", "7220", "7580", "7585","","7586", "7470", "7475"
%own %string (15) %array COLOUR NAME (1:MAX COLOUR) =
   "black", "blue", "green", "red", "purple", "orange", "lime green", "brown",
   "turquoise", "gold", "pen 11", "pen 12", "pen 13", "pen 14", "pen 15", "pen 16"
%own %byte %array          SLOT USED (0:MAX COLOUR) = 0, 4, 3, 2, 1, 0 (*)
%own %byte %array        SLOT TO USE (0:MAX COLOUR) = 0, 4, 3, 2, 1, 3, 1, 2, 4, 3, 4, 1 (*)
%const %byte %array  TWO SLOT TO USE (0:MAX COLOUR) = 0, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2
%const %byte %array FOUR SLOT TO USE (0:MAX COLOUR) = 0, 4, 3, 2, 1, 3, 1, 2, 4, 3, 4, 3, 2, 1, 4, 3, 2
%const %byte %array  SIX SLOT TO USE (0:MAX COLOUR) = 0, 4, 3, 2, 1, 5, 6, 2, 4, 3, 6, 5, 4, 3, 2, 1, 6
%const %byte %array EIGHTSLOT TO USE (0:MAX COLOUR) = 0, 4, 3, 2, 1, 5, 6, 7, 8, 3, 6, 5, 4, 3, 2, 1, 7
%const %byte %array  LINE STYLE MAP  (0:MAX LINE)   = '0', '1', '5', '2', '3', '4', '6'
%const %real %array  LINE STYLE LEN  (0:MAX LINE)   = 0.0, 0.4, 2.5, 1.0, 1.5, 2.0, 2.0

%own %string (127) HP NEW FRAME MESSAGE STR = "Enter a sheet of paper, type YES to go on: "
%own %byte HP NEW FRAME MODE = 'Y'

%external %routine HP SET PEN %alias "EDWIN_HP_SETPEN" (%string (15) NAME, %integer LOG NO, SLOT NO)
   %return %unless 1<=LOGNO<=MAX COLOUR
   COLOUR NAME (LOG NO) = NAME
   SLOT TO USE (LOG NO) = SLOT NO
%end

%external %routine HP NEW FRAME MESSAGE %alias "EDWIN_HP_MESSAGE" (%string (127) MESSAGE)
   HP NEW FRAME MESSAGE STR = MESSAGE
%end

! Routines for the model 7221 protocol

%routine SBN (%integer N)
   ! This sends a single byte number to the plotter
   N = N+64 %if N&32 = 0
   TTPUT (N)
%end

%routine MBN (%integer N)
   ! A three byte number is sent to the plotter
   %integer NN


   TTPUT (96+N//4096)

   NN = (N//64)&63
   NN = NN + 64 %unless NN>31
   TTPUT (NN)

   NN = N&63
   NN = NN + 64 %unless NN>31
   TTPUT (NN)
%end

%routine MBP (%integer X, Y)
   ! Multiple byte pair of numbers (5 bytes)
   %integer N


   TTPUT (96+X//1024)

   N = (X//16)&63
   N = N + 64 %unless N>31
   TTPUT (N)

   N = (X&15)*4 + (Y//4096)
   N = N + 64 %unless N>31
   TTPUT (N)

   N = (Y//64)&63
   N = N + 64 %unless N>31
   TTPUT (N)

   N = Y&63
   N = N + 64 %unless N>31
   TTPUT (N)
%end

%routine MBA (%integer A)
   ! Gives a multi byte angle
   MBN (INT(2\15*(A/180)))
%end

! Routines for the non-7221 plotters

%routine ADD (%integer ONE, TWO)
   TTPUT (';')
   TTPUT (ONE)
   TTPUT (TWO)
%end

%routine ADD STR (%string (255) STR)
   %integer I
   TTPUT (CHARNO(STR,I)) %for I = 1, 1, LENGTH(STR)
%end

%routine HP OUT NUM (%integer I)
   ADD STR (ITOS (I, 0))
%end

%routine HP LINE (%integer X, Y);     ! Go the the current X Y point
   %own %byte PATH COUNT = 0
   %if LAST COM = DEV LINE %then TTPUT (',') %else %start
       ADD ('P', 'D')
       %return %if SX=X %and SY=Y; ! Just a point
       ADD ('P', 'R')
       PATH COUNT = 0
   %finish
   PATH COUNT = (PATH COUNT + 1) & 7
   TTPUT (NL) %if PATH COUNT = 0
   HP OUT NUM (X - SX)
   TTPUT (',')
   HP OUT NUM (Y - SY)
   LAST COM = DEV LINE
%end

! Protocol Handling routines

%routine HP INSTRUCTION (%integer WHICH)
   TTPUT (ESC);   TTPUT ('.');   TTPUT (WHICH)
%end

%routine END TEXT MODE
   TTPUT (ETX)
   TEXT MODE = FALSE
%end

%routine RESERVE (%integer N)
   ! Test to see if N chars. will fit in the buffer
   TTPUT (NL) %and %return %if INTERACTIVE#TRUE
   %return %unless CURRENT DEV=HP7221 %or CURRENT DEV=HP7220
   IN BUFF = IN BUFF + N
   %if IN BUFF>BUFF SIZE %start
       END TEXT MODE %if TEXT MODE = TRUE
       HP INSTRUCTION ('L')
       FLUSH OUTPUT
       N = TTREAD %until N > ' '
       N = TTREAD %until N < ' '; ! Ignore the response
       IN BUFF = 0
   %finish
%end

%routine PON
   %return %if INTERACTIVE#TRUE
   %if CURRENT DEV = HP7580 %start
       TTPUT (ESC) %and TTPUT ('*') %if TERMS(CURRENT DEV)=""
   %finish
   ! The above line assumes that the plotter will be connected through an
   ! Esprit terminal if it can't be connected directly.  (see also POF)
   HP INSTRUCTION ('(')
   PLOT ACTIVE = TRUE
%end

%routine POF
   RESERVE (BUFF SIZE); ! force out anything which is present.
   TTPUT (';') %if CURRENT DEV # HP7221
   HP INSTRUCTION (')')
   TTPUT (13)
   %if CURRENT DEV = HP7580 %start
       TTPUT (ESC) %and TTPUT ('?') %if TERMS(CURRENT DEV)=""
   %finish
   FLUSH OUTPUT
   PLOT ACTIVE = FALSE
%end

%routine CHECK PLOTTING AND NO TEXT
   PON %if PLOT ACTIVE # TRUE
   END TEXT MODE %if TEXT MODE = TRUE
%end

%routine SET GRAPHICS LIMITS (%integer LX, LY, HX, HY)
   RESERVE (25)
   CHECK PLOTTING and NO TEXT
   %if CURRENT DEV = HP7221 %start
       TTPUT ('~');   TTPUT ('W');   MBP (LX, LY);   MBP (HX, HY)
       TTPUT ('~');   TTPUT ('S');   MBP (HX-LX, HY-LY); TTPUT ('}')
   %else
       ADD ('I', 'P')
       HP OUT NUM (LX);   TTPUT (',');   HP OUT NUM (LY);   TTPUT (',')
       HP OUT NUM (HX);   TTPUT (',');   HP OUT NUM (HY)
       ADD ('S', 'C')
       %if CURRENT DEV = HP7220 %or CURRENT DEV = HP7475 %start
           TTPUT ('0');   TTPUT (',');   HP OUT NUM (HX-LX);   TTPUT (',')
           TTPUT ('0');   TTPUT (',');   HP OUT NUM (HY-LY)
       %finish
       ADD ('I', 'W')
       HP OUT NUM (LX);   TTPUT (',');   HP OUT NUM (LY);   TTPUT (',')
       HP OUT NUM (HX);   TTPUT (',');   HP OUT NUM (HY)
   %finish
%end

%routine FULL GRAPHICS LIMITS
   SET GRAPHICS LIMITS (XBASE(CURRENT DEV), YBASE(CURRENT DEV),
      MAX X(CURRENT DEV)+XBASE(CURRENT DEV), MAX Y(CURRENT DEV)+YBASE(CURRENT DEV))
%end

%routine CHECK FOR PENDING COLOURS AND MOVES
   %integer I

   %routine COLOUR (%integer I)
      I = I - NUM PENS (CURRENT DEV) %while I > NUM PENS (CURRENT DEV)
      %if CURRENT DEV = HP 7221 %start
          TTPUT ('v');   SBN (I)
      %else
          ADD ('S', 'P');   TTPUT (I + '0')
      %finish
   %end

   PON %if PLOT ACTIVE # TRUE
   %if PC = TRUE %start
       %if INTERACTIVE=TRUE %and CUR COL > 0 %and SLOT USED(CUR COL)=0 %start
           ! Ask the user to change to a new pen
           COLOUR (0)
           POF
           OPER INTERACT ("Enter a ".COLOUR NAME(CUR COL)." pen in slot ".ITOS(SLOT TO USE (CUR COL),0).", YES to go on: ")
           %for I = 1, 1, MAX COLOUR %cycle
                SLOT USED (I) = 0 %if SLOT USED (I) = SLOT TO USE (CUR COL)
           %repeat
           SLOT USED (CUR COL) = SLOT TO USE (CUR COL)
           PON
       %finish
       ADD ('P', 'U') %if CURRENT DEV # HP7221
       COLOUR (SLOT USED (CUR COL))
   %finish
   %if PC=TRUE %or PM=TRUE %start
       %if CURRENT DEV = HP7221 %start
           TTPUT ('p');   MBP (SX, SY)
       %else
           ADD ('P', 'U')
           ADD ('P', 'A');   HP OUT NUM (SX+xbase(current dev))
           TTPUT (',');   HP OUT NUM (SY+ybase(current dev))
       %finish
   %finish
   COLOUR (SLOT USED (CUR COL)) %if PC=TRUE
   PC = FALSE
   PM = FALSE
%end

%routine UPDATE
   %if PLOT ACTIVE=TRUE %start
       RESERVE (10)
       PC = TRUE
       PM = TRUE
       CHECK FOR PENDING COLOURS AND MOVES
       POF
   %finish
%end

%routine NEW FRAME
   %integer OLD COL, SYM

   %on 9 %start
       CUR COL = OLD COL;   SX = XL;   SY = YB;   PM = TRUE;   PC = TRUE
       %signal 9
   %finish

   PON %if PLOT ACTIVE # TRUE
   SX = XR;   SY = YT;   PM = TRUE; ! Goto the edge.
   OLD COL = CUR COL;               ! remember current colour.
   PC = TRUE;  CUR COL = 0;         ! Drop pen
   %if CURRENT DEV = HP7580 %or CURRENT DEV = HP7585 %c
   %or CURRENT DEV = HP7500 %or CURRENT DEV = HP7586 %start
       %if NEWFRAMED=TRUE %start
           ADD ('N', 'R');   FLUSH OUTPUT
           %if CURRENT DEV#HP7500 %start
               OPER MESSAGE ("Press REMOTE on the plotter to continue")
           %finish
       %finish
   %else
       %if VIEWING = 0 %start
           UPDATE
           OPER INTERACT (HP NEW FRAME MESSAGE STR)
       %finish
   %finish
   NEW FRAMED = TRUE
   ! Restore default state after newframe.
   CUR COL = OLD COL;   SX = XL;   SY = YB;   PM = TRUE;   PC = TRUE
%end

%external %routine HPPLOT %alias "EDWIN___H" (%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

   %routine NEW 7221 ATTRIBUTE (%integer X, Y)
      %switch SW(0:MAX ATTRIBUTE)
      %const %integer DASH = 32

      -> SW(X)

   SW(0): Y=1 %unless 0<=Y<=MAX COLOUR
          PC = TRUE
          CUR COL = Y
          %return

   SW(1): TTPUT('~');  TTPUT ('Q')
          %if Y=1 %start
              SBN(DASH + 2); SBN(4); MBN(60)
          %finish
          %if Y=2 %start
              SBN(DASH + 14);  SBN(4);  SBN(DASH + 2); SBN(4); MBN(240)
          %finish
          %if Y=3 %start
              SBN(DASH + 8);  SBN(4);  MBN(120)
          %finish
          %if Y=4 %start
              SBN(DASH + 16);  SBN(4);  MBN(200)
          %finish
          %return

   SW(2): Y = 16000 %if Y>16000
          TTPUT('~');  TTPUT('%');  Y=Y*100//98;   MBP(Y, Y+Y)
          ! Note that the 100//98 scales the H/W chars to same scale as S/W ones.
          %return

   SW(3): TTPUT ('w');   TTPUT ('w');   MBA (Y);   ! Char rot
          %return

   SW(4): %return;   ! Ignore attempts to change quality

   SW(5): Y = 0 %unless 0<=Y<=5
          TTPUT ('~');   TTPUT ('P');   MBP (Y,Y); ! Char font
          %return

   SW(6): TTPUT ('~');   TTPUT ('/');   MBA (90-Y);   ! Char slant
          %return

   SW(7): ! Ignore any attempts to change intensity.
          %return

   SW(8): ! Speed
          Y = 36 %unless 1<=Y<=36
          TTPUT ('~');   TTPUT ('V');   SBN (Y)
   %end

   %routine NEW HP ATTRIBUTE (%integer X, Y)
      %const %string (5) %array ANGLE (0: 7) =  "1,0",  "1,1",   "0,1", "-1,1", "-1,0", "-1,-1", "0,-1", "1,-1"
      %switch AS (0:MAX ATTRIBUTE)

      -> AS (X)

   AS(0): ! Colour
          Y = 1 %unless 0<=Y<=MAX COLOUR
          CUR COL = Y
          PC = TRUE
          %return

   AS(1): ! Line style
          ADD ('L', 'T')
          %if 0<Y<=MAX LINE %start
              TTPUT ('-') %if CURRENT DEV = HP7580 %or CURRENT DEV = HP7585 %c
                                                   %or CURRENT DEV = HP7586
              TTPUT (LINE STYLE MAP (Y))
              TTPUT (',')
!VAX!         ADD STR (RtoS(LINE STYLE LEN (Y), 0, 3))
{APM}         ADD STR (Newrtos(Line Style Len(Y),0,3))
          %finish
          %return

   AS(2): ! Char size
!VAX!     ADD ('S', 'I');   ADD STR (Rtos(Y/600,0,3).",".RtoS (Y/450,0,3))
{APM}     ADD ('S', 'I');   ADD STR (Newrtos(Y/600,0,3).",".Newrtos(y/450,0,3))
          %return

   AS(3): ! Char rot
          ADD ('D', 'I');   ADD STR (ANGLE(((Y+22)//45)&7))
          %return

   AS(4): ! Char Quality   (<2 => low quality, 5' tolerance, >2 => highest quality.
          ! Note this only works on fonts 6 - 11.
          %return %unless CURRENT DEV = HP7585 %or CURRENT DEV = HP7585 %or CURRENT DEV=HP7586
          %if Y<2 %then LOW QUAL = TRUE %else LOW QUAL = FALSE
          ADD ('C', 'C');   TTPUT ('1')
          %return

   AS(5): ! Char Font
          Y = 0 %unless 0 <= Y <= 5
          ADD ('C', 'A')
          TTPUT ('1') %if LOW QUAL # TRUE
          TTPUT (Y + '0')
          ADD ('C', 'S')
          TTPUT ('1') %if LOW QUAL # TRUE
          TTPUT (Y + '0')
          %return

   AS(6): ! Char slant
!VAX!     ADD ('S', 'L')
!VAX!     TTPUT ('-') %if Y<0
!VAX!     ADD STR (RtoS(TAN(MOD(Y) / DtoR), 0, 3)) %if Y#0
          %return

   AS(7): ! Intensity
          %return

   AS(8): ! Speed
          %if CURRENT DEV = HP7220 %start
              Y = 36 %unless 1<=Y<=36
          %else
              Y = 0 %unless 1<=Y<=60
          %finish
          ADD ('V', 'S');   HP OUT NUM (Y) %if Y#0
   %end

   END TEXT MODE %if LAST COM = DEV CHAR %and COM#DEV CHAR
   LAST COM = COM %if COM # DEV LINE
!   select output (0); write (com,1); write (x,1); write (y,1); newline
   -> SW (COM)

SW(0): ! Initialise
       CURRENT DEV = -1
       Y = 0
       Y = 8 %and X=X//10 %if REM(X,10)=8
       %for COM = 0, 1, NUM HP %cycle
            CURRENT DEV = COM %if DEV NUMS (COM) = X
       %repeat
       %signal 14, 0 %if CURRENT DEV < 0
       NUM PENS (CURRENT DEV)=8 %if Y=8
       DEV DATA_NAME = "an HP ".ItoS(X,0)." plotter"
       DEV DATA_DVX = 40*400
       DEV DATA_DVY = 28*400
       DEV DATA_MVX = MAX X (CURRENT DEV)
       DEV DATA_MVY = MAX Y (CURRENT DEV)
       DEV DATA_UNITS PER CM = 400
       DEV DATA_MAX COLOUR = NUM PENS (CURRENT DEV)
       DEV DATA_NUM CHAR SIZES = 255
       %if NUM PENS(CURRENT DEV)=2 %start
           SLOT USED (Y) = 0 %and SLOT TO USE (Y) = TWO SLOT TO USE (Y) %for Y = 3,1,8
       %finish %else %if NUM PENS (CURRENT DEV) = 4 %start
           SLOT USED (Y) = 0 %and SLOT TO USE (Y) = FOUR SLOT TO USE (Y) %for Y = 5,1,8
       %finish %else %if NUM PENS (CURRENT DEV) = 6 %start
           SLOT USED (Y) = 0 %and SLOT TO USE (Y) = SIX SLOT TO USE (Y) %for Y = 5,1,8
           SLOT USED (Y) = SLOT TO USE (Y) %for Y = 5,1,6
       %finish %else %if NUM PENS (CURRENT DEV) = 8 %start
           SLOT USED (Y) = 0 %and SLOT TO USE (Y) = EIGHT SLOT TO USE (Y) %for Y = 5,1,8
           SLOT USED (Y) = SLOT TO USE (Y) %for Y=5,1,8
       %finish
!VAX!  INTERACTIVE = INTERACTS (CURRENT DEV)
{APM}  INTERACTIVE = TRUE
       %if INTERACTIVE = TRUE %start
!VAX!      %if TRANSLATE(TERMS(CURRENT DEV))#TERMS(CURRENT DEV) %start
!VAX!          SET DEVICE (TERMS(CURRENT DEV))
!VAX!      %finish
           TTMODE (1);   PON
           HP INSTRUCTION ('J')    { Cancel any current device control info   }
           HP INSTRUCTION ('K')    { Zap anything else which is in the buffer }
!VAX!      HP INSTRUCTION ('M');   ADD STR ("0;;10;:"); ! Set output mode
{APM}      HP INSTRUCTION ('M');   ADD STR ("0;;;:"); ! set output mode
           %unless CURRENT DEV = HP7221 %or CURRENT DEV = HP7220 %start
               ! Place plotter in ^S ^Q mode
               HP INSTRUCTION ('I');   ADD STR (";;17;:")
               HP INSTRUCTION ('N');   ADD STR (";19;:")
           %finish
       %finish
       %if CURRENT DEV=HP7221 %start
           TTPUT ('~');   TTPUT ('_')
           IN BUFF = 20
       %else
           ADD ('P', 'U');    ADD ('I', 'N')
           INBUFF = 32
       %finish
       SX = XL;   SY = YB;   PM = TRUE
       NEW FRAMED = FALSE
       %return

SW(1): ! Terminate
       FULL GRAPHICS LIMITS
       %if INTERACTIVE=TRUE %start
           SX = MAXX (CURRENT DEV);   SY = MAXY (CURRENT DEV);   PM = TRUE
           SX = XL %and SY = YB %if HP7221#CURRENT DEV#HP7220
           CUR COL = 0;   PC = TRUE
           RESERVE (10)
           CHECK FOR PENDING COLOURS AND MOVES
           ADD ('N', 'R') %if CURRENT DEV = HP7580 %or CURRENT DEV = HP7585 %or CURRENT DEV = HP7586 %or CURRENT DEV = HP7500
           POF
           TTMODE (0)
       %else
           ADD STR (";PU;PA16000,0;")
           TTPUT (NL)
           FLUSH OUTPUT
           CLOSE OUTPUT
       %finish
       %return

SW(2): ! Update
       UPDATE
       %return

SW(3): ! New frame
       NEW FRAME
       %return

SW(4): ! Move Abs
       NEW FRAME %if NEW FRAMED # TRUE
       SX = X - XL;   SY = Y - YB;   PM = TRUE
       %return

SW(5): ! Line Abs
       NEW FRAME %if NEW FRAMED # TRUE
       PON %if PLOT ACTIVE # TRUE
       RESERVE (30) %if INTERACTIVE=TRUE %or LAST COM # DEV LINE
       CHECK FOR PENDING COLOURS AND MOVES
       X = X - XL;   Y = Y - YB
       %if CURRENT DEV = HP7221 %then TTPUT ('q') %and MBP (X, Y) %else HP LINE (X, Y)
       SX = X;   SY = Y
       %return

SW(6): ! Character
       NEW FRAME %if NEWFRAMED # TRUE
       PON %if PLOT ACTIVE # TRUE
       RESERVE (3) %if INTERACTIVE=TRUE %or TEXT MODE # TRUE
       %if TEXT MODE # TRUE %start
           CHECK FOR PENDING COLOURS AND MOVES
           %if CURRENT DEV = HP7221 %then TTPUT ('~') %and TTPUT ('''') %else ADD ('L', 'B')
           TEXT MODE = TRUE
       %finish
       TTPUT (X)
       %return

SW(7): ! New attribute
       PON %if PLOT ACTIVE # TRUE
       %return %if X > MAX ATTRIBUTE
       RESERVE (10) %if INTERACTIVE=TRUE
       %if CURRENT DEV = HP7221 %then NEW 7221 ATTRIBUTE (X, Y) %else NEW HP ATTRIBUTE (X, Y)
       %return

SW(8): ! Lower window bounds
       X = 0 %if X<0
       XL = X
       Y = 0 %if Y<0
       YB = Y
       %return

SW(9): ! Upper window bounds
       X = MAXX (CURRENT DEV) %if X > MAXX (CURRENT DEV)
       XR = X
       Y = MAXY (CURRENT DEV) %if Y > MAXY (CURRENT DEV)
       YT = Y
       %if HP7580=CURRENT DEV %or CURRENT DEV=HP7585 %or CURRENT DEV=HP7500 %c
                              %or CURRENT DEV=HP7586 %start
           XBASE (CURRENT DEV) = (XL-X)//2;   YBASE (CURRENT DEV) = (YB-Y)//2
       %finish
       SET GRAPHICS LIMITS (XL+XBASE(CURRENT DEV), YB+YBASE(CURRENT DEV),
                            X+XBASE(CURRENT DEV), Y+YBASE(CURRENT DEV))
       %return

SW(10): SW(11): %return { ignore mode settings }
SW(12): ! Lower box bounds
        WX = X;   WY = Y
        %return

SW(13): ! Upper box bounds, and do box
        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.
        HPPLOT (4, WX, WY)
        HPPLOT (5, X, WY)
        HPPLOT (5, X, Y)
        HPPLOT (5, WX, Y)
        HPPLOT (5, WX, WY)
        %return

SW(14): { Hardware circles }
        { X is the Radius, and Y is used as a temp }
        RESERVE (20)
        %if CURRENT DEV = HP7221 %start
            Y = SX
            SX = SX + X;   PM = TRUE
            CHECK FOR PENDING COLOURS AND MOVES
            TTPUT ('t');   MBN (X)
            SX = Y;   PM = TRUE
        %else
            CHECK FOR PENDING COLOURS AND MOVES
            ADD ('C', 'I');   HP OUT NUM (X)
        %finish
        %return

SW(15): %return
%end

%external %routine HP C ARC %alias "EDWIN_HP_C_ARC" (%integer RAD, %integer IA, FA)
   %integer OX, OY
   RESERVE (20)
   OX = SX;   OY = SY
   SX = SX + INT (RAD * COS (IA / DtoR));  SY = SY + INT (RAD * SIN (IA / DtoR));   PM = TRUE
   NEWFRAME %if NEWFRAMED # TRUE
   CHECK PLOTTING AND NO TEXT
   CHECK FOR PENDING COLOURS AND MOVES
   %if current dev = HP7221 %start
       TTPUT ('t');   MBN (RAD);   MBA (IA);   MBA (FA)
   %else
       ADD ('P', 'D')
       ADD ('A', 'R')
       HP OUT NUM (OX-SX);   TTPUT (',');   HP OUT NUM (OY-SY);   TTPUT (',')
       FA = FA - 360 %if FA > IA
       HP OUT NUM (FA-IA)
       ADD ('P', 'U')
   %finish
   SX = OX;   SY = OY;   PM = TRUE
%end

%external %routine HP AC ARC %alias "EDWIN_HP_AC_ARC" (%integer RAD, %integer IA, FA)
   %integer OX, OY
   RESERVE (20)
   OX = SX;   OY = SY
   SX = SX + INT (RAD * COS (IA / DtoR));  SY = SY + INT ( RAD * SIN (IA / DtoR));   PM = TRUE
   NEWFRAME %if NEWFRAMED # TRUE
   CHECK PLOTTING AND NO TEXT
   CHECK FOR PENDING COLOURS AND MOVES
   %if CURRENT DEV = HP7221 %start
       TTPUT ('u');   MBN (RAD);   MBA (IA);   MBA (FA)
   %else
       ADD ('P', 'D')
       ADD ('A', 'R')
       HP OUT NUM (OX-SX);   TTPUT (',');   HP OUT NUM (OY-SY);   TTPUT (',')
       FA = FA + 360 %if FA<IA
       HP OUT NUM (FA-IA)
       ADD ('P', 'U')
   %finish
   SX = OX;   SY = OY;   PM = TRUE
%end

%external %routine H REQ %alias "EDWIN___H_REQ" (%integer %name STATE, X, Y)
   %integer I, S

   %on 1,2,3,4,5,6,7,8 %start
       %signal 14, 4
   %finish

   %routine RAS (%integer %name V)
      ! Read and Skip symbol
      %integer I
      V = 0
      I = TTREAD
      %if I='-' %then S=-1 %and I=0 %else S=1
      %cycle
         V = V*10+(I-'0')
         I = TTREAD
         %exit %unless '0'<=I<='9'
      %repeat
      V = V * S
   %end

   %signal 14, 8 %if INTERACTIVE#TRUE

   CHECK PLOTTING AND NO TEXT
   CHECK FOR PENDING COLOURS AND MOVES
   %if CURRENT DEV = HP7221 %start
       HP INSTRUCTION ('D')
       FLUSH OUTPUT
       RAS (X);   RAS (Y);   RAS (I);   RAS (STATE)
       STATE = I<<4!STATE
       ! State is 'pen up/down flag'<<4! Current pen.
   %else
       ADD ('D', 'P')
       %cycle
          ADD ('O', 'S');   TTPUT (';');   FLUSH OUTPUT
          RAS (I)
       %repeat %until I&4#0
       ADD ('O', 'D');   TTPUT (';');   FLUSH OUTPUT
       RAS (X);   RAS (Y);   RAS (STATE)
       STATE = STATE << 4       { for compatability }
   %finish
   POF
   FLUSH OUTPUT
%end

%end %of %file
