! EDWIN driver for the HP plotter range.

%include "edwina:device.inc"
%include "edwina:icodes.inc"
%include "edwina:consts.inc"
%include "inc:Maths.imp"
!%include "inc:Lognames.imp"
%include "inc:util.imp"

! 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 NEWFRAMED = FALSE; ! TRUE => NEW FRAME done
%own %byte TEXT MODE = FALSE; ! TRUE while in text mode
%own %byte Fill Mode = 0;     ! 0 => Outline
%own %integer Char Size = 250 { Character size, <6 => don't draw characters
%own %integer Char Rot  = 0
%own %integer Char Font = 0
%own %integer Char Mirror = 0
%own %integer Char Qual = 0
%own %integer Char Slant = 0
%own %byte Need Char Size = True
%own %byte Need Char Rot = True
%own %byte Need Char Font = True
%own %byte Need Char Slant = False
%own %byte Need Limits = False
%own %byte Line Mode = 1;     ! Line style
%own %byte Speed     = 36;    ! Speed
%own %byte Rmode     = 0      { shade polygons = 3, Normal lines = 1
%own %byte Escapes     = True { Add escape sequences to HPGL
%own %byte Fill Required = True { Can be used to generally suppress shape fill
%own %integer NLINES  = 0;    ! Number of lines drawn ( = size of polygon)
%own %integer INBUFF = 32;    ! This is the initialisation code
%own %string (255) Temp = "", Str = ""

! Configuration parameters -

%const %integer MAX COLOUR = 16
%const %integer MAX LINE = 6
%const %integer MAX Fill = 7
%const %integer NUM HP = 9
%const %integer HP7221 = 0, HP7220 = 1, HP7580 = 2, HP7585 = 3, HP7440 = 4
%const %integer HP7586 = 5, HP7470 = 6, HP7475 = 7, HP7550 = 8, HP7570 = 9
%own %integer current dev = HP7221
%const %short %array DEV NUMS (0:NUM HP) =  7221,  7220,   7580,   7585,   7440,   7586,   7470,   7475,   7550,  7570
%own   %byte %array  NUM PENS (0:NUM HP) =     4,     4,      8,      8,      8,      8,      2,      6,      8,     8
%own   %integer %array  MAX X (0:NUM HP) = 16000, 16000,  30240,  44380,  10900,  44380,  10900,  16158,  15970, 40000
%own   %integer %array  MAX Y (0:NUM HP) = 11400, 11400,  21520,  31480,   7650,  31480,   7650,  11040,  10870, 33600
%const %byte %array Has Fill  (0:NUM HP) =     0,     0,      0,      1,      1,      1,      1,      1,      1,     1
%const %byte %array Has Poly  (0:NUM HP) =     0,     0,      0,      1,      1,      1,      0,      0,      1,     1
%const %byte %array Has NR    (0:NUM HP) =     0,     0,      1,      1,      0,      1,      0,      0,      0,     1
%const %byte %array True Origin (0:NUM HP) =   1,     1,      0,      0,      1,      0,      1,      1,      1,     0
%own %string (15) %array COLOUR NAME (1:MAX COLOUR) =
   "black", "blue", "green", "red", "magenta", "orange", "cyan", "brown",
   "orange", "violet", "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','4','2','3','5','6'
%const %real %array  LINE STYLE LEN  (0:MAX LINE)   = 0.0, 0.5, 5.0, 1.0, 5.0, 5.0, 5.0
%const %byte %array       Fill style (1:MAX Fill)   = '1','3','3','3','3','4','4'
%const %short %array      Fill Angle (1:MAX Fill)   =  0,  0, 90, 45, -45, 45, 0

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

%external %string (127) %fn TRANSLATE (%string (127) name)
   %string(255) s

   s = name
   %result = s
%end

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

%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
   PATH COUNT = (PATH COUNT + 1) & 7
   %if LAST COM = DEV LINE %start
      TTPUT (',') %if Path Count # 0
   %else
      ADD ('P', 'D')
      %return %if SX=X %and SY=Y; ! Just a point
      ADD ('P', 'R')
      PATH COUNT = 1
   %finish
   TTPUT (NL) %and ADD ('P', 'R') %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)
   %return %if Escapes = False
   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
   %if Viewing # 0 %or %not (CURRENT DEV=HP7221 %or CURRENT DEV=HP7220) %start
       { No action }
   %else
       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
   %finish
%end

%routine PON
   %return %if Viewing # 0
   HP INSTRUCTION ('(')
   PLOT ACTIVE = TRUE
%end

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

%routine SET GRAPHICS LIMITS (%integer LX, LY, HX, HY)
   %integer X Base, Y Base
   RESERVE (25)
   PON %if PLOT ACTIVE # TRUE
   END TEXT MODE %if TEXT MODE = TRUE
   %if CURRENT DEV = HP7221 %start
       TTPUT ('~');   TTPUT ('W');   MBP (LX, LY);   MBP (HX, HY)
       TTPUT ('~');   TTPUT ('S');   MBP (HX-LX, HY-LY); TTPUT ('}')
   %else
       %if True Origin(CURRENT DEV) = True %start
           X Base = 0
           Y Base = 0
       %else
           X Base = MAXX(CURRENT DEV) // 2
           Y Base = MAXY(CURRENT DEV) // 2
       %finish
       TTPUT (NL)
       ADD ('I', 'P')
       HP OUT NUM (LX-X Base); TTPUT (','); HP OUT NUM (LY-Y Base); TTPUT (',')
       HP OUT NUM (HX-X Base); TTPUT (','); HP OUT NUM (HY-Y Base)
       ADD ('S', 'C')
       TTPUT ('0');   TTPUT (',');   HP OUT NUM (HX-LX);   TTPUT (',')
       TTPUT ('0');   TTPUT (',');   HP OUT NUM (HY-LY)
       ADD ('I', 'W')
       %if X Base = 0 %start
          HP OUT NUM (LX); TTPUT (','); HP OUT NUM (LY); TTPUT (',')
          HP OUT NUM (HX); TTPUT (','); HP OUT NUM (HY)
       %else
          HP OUT NUM (0); TTPUT (','); HP OUT NUM (0); TTPUT (',')
          HP OUT NUM (HX-LX); TTPUT (','); HP OUT NUM (HY-LY)
       %finish
       Need Char Size = True
       TTPUT (NL)
   %finish
   Need Limits = False
%end

%routine CHECK PLOTTING AND NO TEXT
   PON %if PLOT ACTIVE # TRUE
   SET GRAPHICS LIMITS (XL, YB, XR, YT) %if Need Limits = True
   END TEXT MODE %if TEXT MODE = TRUE
%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 Viewing = 0 %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)
           TTPUT (',');   HP OUT NUM (SY)
           TTPUT (NL)
       %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

   %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 Has NR (CURRENT DEV) = True %start
       %if NEWFRAMED=TRUE %start
           ADD ('N', 'R');   TTPUT (';');   FLUSH OUTPUT
           OPER MESSAGE ("Press REMOTE on the plotter to continue")
       %finish
   %else %if CURRENT DEV = HP7550 %or Current Dev = HP7586
       ADD ('P','G');   TTPUT (';')
   %else
       %if VIEWING = 0 %start
           UPDATE
           %if HP New Frame Message Str # "" %start
               OPER INTERACT (HP NEW FRAME MESSAGE STR)
           %finish
       %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
   %own %integer input stream = 0;   ! kjc hope
   %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:Att Maximum)
      %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)
          Speed = Y
   SW(*):
   %end

   %routine New HPGL Char settings
      %const %string (5) %array ANGLE (0: 7) =  "1,0",  "1,1",   "0,1", "-1,1",
                                                "-1,0", "-1,-1", "0,-1", "1,-1"
      %real X, Y
      %return %if Char Size < 20 { Text too small to draw }
      %if Need Char Size = True %start
         ADD ('S', 'R')
         TTPUT ('-') %if Char Mirror & Mirror in Y Axis # 0
         ADD STR (Rtos(Char Size*67/(XR-XL),0,3))
         TTPUT (',')
         TTPUT ('-') %if Char Mirror & Mirror in X Axis # 0
         ADD STR (RtoS(Char Size*100/(YT-YB),0,3))
         Need Char Size = False
      %finish
      %if Need Char Rot = True %start
         ADD ('D', 'I')
         %if Char Rot # 0 %start
            %if Rem(Char Rot,45)=0 %start
               ADD STR (ANGLE((Char Rot//45)&7))
            %else
               x = 100*Cos(Char Rot/DtoR)
               y = 100*Sin(Char Rot/DtoR)
               ADD STR (Rtos(x,0,3))
               TTPUT (',')
               ADD STR (Rtos(y,0,3))
            %finish
         %finish
         Need Char Rot = False
      %finish
      %if Need Char Font = True %start
         ADD ('C', 'C') %and TTPUT ('1') %if Dev Nums (Current Dev) > 7500
         ADD ('C', 'A')
         TTPUT ('1') %if Char Qual >= 2
         TTPUT (Char Font + '0')
         ADD ('C', 'S')
         TTPUT ('1') %if Char Qual >= 2
         TTPUT (Char Font + '0')
         Need Char Font = False
      %finish
      %if Need Char Slant = True %start
         ADD ('S', 'L')
         TTPUT ('-') %if Char Slant<0
         ADD STR (RtoS(TAN(|Char Slant| / DtoR), 0, 3)) %if Char Slant#0
         Need Char Slant = False
      %finish
   %end

   %routine NEW HP ATTRIBUTE (%integer X, Y)
      %switch AS (0:Att Maximum)

      -> AS (X)

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

   AS(att Line Style):
          Line mode = Y
          ADD ('L', 'T')
          %if 0<Y<=MAX LINE %start
              TTPUT ('-') %if Dev Nums (CURRENT DEV) > 7500
              TTPUT (LINE STYLE MAP (Y))
              TTPUT (',')
              ADD STR (RtoS(LINE STYLE LEN (Y), 0, 3))
          %finish
          %return

   AS(att Char Size):
          Char Size = Y
          Need char Size = True
          %return

   AS(att char rot):
          Char Rot = Y
          Need Char Rot = True
          %return

   AS(att char quality):
          ! <2 => low quality, 5' tolerance, >2 => highest quality.
          Char Qual = Y
          Need Char Font = True
          %return

   AS(att char font):
          Y = 0 %unless 0 <= Y <= 5
          Char Font = Y
          Need Char Font = True
          %return

   AS(att char slant): ! Char slant
          Char Slant = Y
          Need Char Slant = True
          %return

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

   AS(att shade mode):
          Fill Mode = Y
          %if Fill Required = True %and Has Fill (CURRENT DEV) = True %start
             %if 1<=y<=Max fill %start
                Add ('F', 'T')
                %if y = 1 %and Speed < 30 %start
                   TTPUT ('2')   { High Quality shading }
                %else
                   TTPUT (Fill style(y))
                %finish
                Add Str (",50,".Itos(Fill angle(y),0))
             %else
                Add Str (";FT4,".Itos(Y*10,0).",0")
             %finish
          %else
             Fill Mode = 0
          %finish
          %return

   AS(att char mirror):
          Char Mirror = Y
          Need Char Size = True

   AS(*):
   %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
       Temp = ItoS (X, 0)
       DEV DATA_TYPE = X
       DEV DATA_NAME = "an HP ".Temp." plotter"
       %begin
          %on 3,4 %start
             Oper Message ("Error in HP Plotter Paper size specification")
             %signal 14, 1
          %finish
      
          Str = "EDWIN_".ItoS(X,0)."_X"
          Temp = Translate(Str)
          %if Temp # Str %start
              Max X (Current Dev) = Stoi (Temp) * 40
          %finish
          Str = "EDWIN_".ItoS(X,0)."_Y"
          Temp = Translate (Str)
          %if Temp # Str %start
              Max Y (Current Dev) = Stoi (Temp) * 40
          %finish
          %signal 4 %if Max X (Current Dev) < 1000 %or Max Y (Current Dev) < 1000
       %end       
       DEV DATA_DVX = MAX X (CURRENT DEV)
       DEV DATA_DVY = MAX Y (CURRENT DEV)
       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
       DEV DATA_NUM CHAR ROTS = 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
       Temp = "EDWIN_HP_NOESCAPES"
       %if Translate(Temp) = Temp %start { Check EDWIN_7xxx_ESCAPES as ON or OFF }
          Temp = "EDWIN_".ItoS(Dev Data_Type,0)."_ESCAPES"
          %if Temp = Translate (Temp) %start
             Escapes = True
          %else
             Temp = Translate (Temp)
             To Upper (Temp)
             %if Temp="ON" %start
                Escapes = True
             %else %if Temp="OFF"
                Escapes = False
             %else
                Oper Message ("Unknown setting """.Temp.""" for EDWIN_". -
                              ItoS(DevData_Type,0)."_ESCAPES must be ON or OFF")
                %signal 14, 1
             %finish
          %finish
       %else
          %if Translate(Temp) # Temp %start
             Escapes = False
          %else
             Escapes = True
          %finish
       %finish
       Temp = "EDWIN_HP_FILL"
       %if Translate(Temp) # Temp %start
          Temp = Translate (Temp)
          To Upper (Temp)
          %if Temp = "YES" %start
             Fill Required = True
          %else %if Temp = "NO"
             Fill Required = False
          %else
             Oper Message ("Unknown setting """.Temp.""" for EDWIN_HP_FILL".-
                           " must be YES or NO")
             %signal 14, 1
          %finish
       %else
          Fill Required = True
       %finish
       Temp = "EDWIN_".ItoS(Dev Data_Type,0)
       %if TRANSLATE(Temp)#Temp %and Viewing = 0 %start
          SET DEVICE (Temp)
       %finish
       TTMODE (1)
       %if ESCAPES = TRUE %start
           PON
           HP INSTRUCTION ('J')    { Cancel any current device control info   }
           HP INSTRUCTION ('K')    { Zap anything else which is in the buffer }
           HP INSTRUCTION ('M');   ADD STR ("0;;10;:"); ! Set output mode
           %unless CURRENT DEV = HP7221 %or CURRENT DEV = HP7220 %start
              ! Try this then no ^F reqd from user
              Set terminal mode ( no page )
               ! 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
       Need Limits = True
       POF;   PON
       Temp = Temp."_PEN_MAP"
       %if Translate (Temp)#Temp %start
           Com = Input Stream
           %begin
              %integer I
              %on 9 %start
                 Oper Message ("Cannot open HP PEN MAP file """.Temp.-
                               """ (default pen mapping will be used)")
                 %return
              %finish
              Temp = Translate (Temp)
              Open Input (3, Temp)
              Select Input (3)
              Slot Used (I) = 0 %for I = 1, 1, Max Colour
              %begin
                 %integer I, Slot
                 %on 3,4,9 %start
                    %if Event_Event # 9 %start
                       Oper Message ("Invalid slot number for colour """.temp."""")
                       Read Symbol (I) %until I=Nl
                    %else
                       Close Input
                       Select Input (Com)
                       %return
                    %finish
                 %finish
                 %cycle
                    Read (Temp)
                    To Upper (Temp)
                    Read (Slot)
                    %for I = 1, 1, Max Edwin Colour %cycle
                       %if Edwin Colours (I) = Temp %or Temp = "BLACK" %start
                          I = 1 %if Temp = "BLACK"
                          %if Slot <= Num Pens (Current dev) %start
                             Slot to Use (I) = Slot
                             Slot Used (Slot) = I
                          %else
                             Oper Message ("Slot number ".ItoS(Slot,0). -
                                     " in HP PEN MAP is too large (ignored)")
                          %finish
                          %exit
                       %else %if I=Max Edwin Colour
                          Oper Message ("Unknown Colour """.Temp.-
                                        """ in HP PEN MAP file (ignored)")
                       %finish
                    %repeat
                 %repeat
              %end
           %end
       %finish
       %return

SW(1): ! Terminate
       %if Current Dev = HP7221 %start
          SET GRAPHICS LIMITS (0, 0, 16000, 11400)
       %else
           SET GRAPHICS LIMITS (XL, YB, XR, YT)
           ADD ('D', 'F')
           CUR COL = 0;   PC = TRUE
           RESERVE (10)
           CHECK FOR PENDING COLOURS AND MOVES
           %if Viewing = 0 %and Escapes = True %start
              ! Wait for plot to complete
              POF
              HP INSTRUCTION ('L')
              FLUSH OUTPUT
              COM = TTREAD %until COM > ' '
              COM = TTREAD %until COM < ' '; ! Ignore the response
              PON
           %finish
           %if Has NR (CURRENT DEV) = True %start
              ADD ('N', 'R')
           %else %if Current Dev = HP7550
              ADD ('P','G')
           %finish
           TTPUT (';')
       %finish
       %if Viewing = 0 %start
           POF
           TTMODE (0)
       %else
           TTPUT (NL)
           FLUSH OUTPUT
           CLOSE OUTPUT
       %finish
       %return

SW(2): ! Update
       UPDATE
       %if Viewing = 0 %and Escapes = True %start
          ! Wait for plot to complete
          HP INSTRUCTION ('L')
          FLUSH OUTPUT
          COM = TTREAD %until COM > ' '
          COM = TTREAD %until COM < ' '; ! Ignore the response
       %finish
       %return

SW(3): ! New frame
       SET GRAPHICS LIMITS (XL, YB, XR, YT) %if Need Limits = True
       NEW FRAME
       %return

SW(4): ! Move Abs
       NEW FRAME %if NEW FRAMED # TRUE
       SX = X - XL;   SY = Y - YB;   PM = TRUE
       %if Rmode=3 {polygons} %start
          Add ('L', 'T') %if Line Mode # 0
          Check for Pending Colours and Moves
          Add ('P', 'M') %and TTput ('0') %if Fill Required = True
       %finish
       %return

SW(5): ! Line Abs
       NEW FRAME %if NEW FRAMED # TRUE
       PON %if PLOT ACTIVE # TRUE
       SET GRAPHICS LIMITS (XL, YB, XR, YT) %if Need Limits = True
       RESERVE (30) %if Viewing = 0 %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)
       NLINES = NLINES + 1
       SX = X;   SY = Y
       %return

SW(6): ! Character
       %return %if Char Size < 20
       NEW FRAME %if NEWFRAMED # TRUE
       PON %if PLOT ACTIVE # TRUE
       SET GRAPHICS LIMITS (XL, YB, XR, YT) %if Need Limits = True
       RESERVE (3) %if Viewing = 0 %or TEXT MODE # TRUE
       %if TEXT MODE # TRUE %start
           CHECK FOR PENDING COLOURS AND MOVES
           %if CURRENT DEV = HP7221 %start
              TTPUT ('~') %and TTPUT ('''')
           %else
              NEW HPGL Char Settings {if required}
              TTPUT (NL)
              ADD ('L', 'B')
           %finish
           TEXT MODE = TRUE
       %finish
       TTPUT (X)
       %return

SW(7): ! New attribute
       PON %if PLOT ACTIVE # TRUE
       %return %if X > Att Maximum
       RESERVE (10) %if Viewing = 0
       %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
       Need Limits = True
       %return

SW(10): ! Polygons?
        %if Has Poly (Current Dev) = True %start
           %if RMODE = 3 %start
              %if Fill Required = True %start
                 ADD ('P', 'M');  TTPUT ('2')
                 %if Nlines > 1 %start
                    ADD ('F', 'P');
                    ADD ('E', 'P');
                 %finish
                 Nlines = 0
              %finish
              New HP Attribute (1, Line Mode) %if Line Mode # 0
           %finish
           RMODE = X
        %finish
        %return

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.
        NEW FRAME %if NEW FRAMED # TRUE
        PON %if PLOT ACTIVE # TRUE
        SET GRAPHICS LIMITS (XL, YB, XR, YT) %if Need Limits = True
        RESERVE (30) %if Viewing = 0 %or LAST COM # DEV LINE
        Add ('L','T') %if Line Mode # 0
        %if Fill Mode = 0 %start
            HPPLOT (4, WX, WY)
            HPPLOT (5, X, WY)
            HPPLOT (5, X, Y)
            HPPLOT (5, WX, Y)
            HPPLOT (5, WX, WY)
        %else
            SX = WX - XL;   SY = WY - YB;   PM = TRUE
            CHECK FOR PENDING COLOURS AND MOVES
            SX = X - XL;   SY = Y - YB;   PM = TRUE
            Add ('R','R'); HP Out Num (X-WX); TTput (','); HP Out Num (Y-WY)
            Add ('E','R'); HP Out Num (X-WX); TTput (','); HP Out Num (Y-WY)
        %finish
        New HP Attribute (1, Line Mode) %if Line Mode # 0
        %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 %if Fill Mode # 0
            CHECK FOR PENDING COLOURS AND MOVES
            ADD ('W', 'G');   Add Str (Itos(X,0).",0,360")
            ADD ('E', 'W');   Add Str (Itos(X,0).",0,360")
        %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 Viewing # 0

   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
