! EDWIN driver for the HP plotter range of HP-GL based plotters

!############################################################################
!#                                                                          #
!#  This is a module from the EDWIN Graphics Package, which was developed   #
!#  in the Department of Computer Science, at Edinburgh University, from    #
!#  1978 to the present day, release 5 of EDWIN in October 1984.            #
!#                                                                          #
!#  The principal author of the EDWIN Graphics Package was J Gordon Hughes, #
!#  while working for the Edinburgh University Computer Sceince Department. #
!#  Parts of EDWIN have been produced by many different people, too many    #
!#  too mention, working for different departments of Edinburgh and Leeds   #
!#  Universities.                                                           #
!#                                                                          #
!#  This module is regarded as being in the public domain, and the authors  #
!#  and accept no responsibility regarding the uses to which the software   #
!#  will be put.                                                            #
!#                                                                          #
!############################################################################

from Edwin include device
from Edwin include icodes
from Edwin include consts
from Imp include Maths
from Imp include Lognames
from Imp include Textutils
!%external %string (31) %spec Fname

! 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 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 = ""
own byte Any Speed = False
own byte Any Force = False
own byte Any Acceleration = False
own byte Any Thickness = False

! Configuration parameters -

const integer MAX COLOUR = 16
const integer MAX LINE = 6
const integer MAX Fill = 7
const integer NUM HP = 9
const integer HPunk  = 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 = False
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 Force (0:NUM HP) =     0,     0,      1,      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
own   byte array        PEN SPEED (0:MAX COLOUR) = 0(*)
own   byte array        PEN FORCE (0:MAX COLOUR) = 0(*)
own   byte array PEN ACCELERATION (0:MAX COLOUR) = 0(*)
own   real array    PEN THICKNESS (0:MAX COLOUR) = 0(*)
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

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

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)
   Oper Message ("Please remove the call to HP NEW FRAME MESSAGE!")
end

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 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 (';')
   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 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)
   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)
      ADD ('S', 'P');   TTPUT (I + '0')
      return if I = 0
      if Has Force (Current Dev) = True start
         if Any Acceleration = true start
            Add ('A', 'S')
            Add Str (Itos(Pen Acceleration(Cur Col),0)) if Pen Acceleration(Cur Col)#0
         finish
         if Any Force = true start
            Add ('F', 'S')
            Add Str (Itos(Pen Force(Cur Col),0)) if Pen Force(Cur Col)#0
         finish
         if Any Thickness = true start
            Add ('P', 'T')
            Add Str (Rtos(Pen Thickness(Cur Col),-1,1)) if Pen Thickness(Cur Col) >= 0.1
         finish
      finish
      if Any Speed = true start
         Add ('V', 'S')
         Add Str (Itos(Pen Speed(Cur Col),0)) if Pen Speed(Cur Col)#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')
       COLOUR (SLOT USED (CUR COL))
   finish
   if PC=TRUE or PM=TRUE start
      ADD ('P', 'U')
      ADD ('P', 'A');   HP OUT NUM (SX)
      TTPUT (',');   HP OUT NUM (SY)
      TTPUT (NL)
   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
!           %unless Fname = "DRAFT" %or Fname = "WAVE" %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
   switch SW (0:MAX COM)

   routine SWAP (integer name  A, B)
      integer C
      C = A;   A = B;   B = C
   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 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 0 < Pen Speed (Cur Col) < 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_X UNITS PER CM = 400
       DEV DATA_Y 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
          Oper Message ("EDWIN_HP_NOESCAPES is obsolete definition, use EDWIN_".-
                        ItoS(Dev Data_Type,0)."_ESCAPES")
          signal 14, 1
       finish
       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
       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 = HP7220 start
               ! Place plotter in ^S ^Q mode
               HP INSTRUCTION ('I');   ADD STR (";;17;:")
               HP INSTRUCTION ('N');   ADD STR (";19;:")
           finish
       finish
       ADD ('P', 'U');    ADD ('I', 'N')
       INBUFF = 32
       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
              Any Speed = False
              Any Force = False
              Any Acceleration = False
              Any Thickness = False
              begin
                 string (23) Concept
                 integer I, Slot, Speed, Acceleration, Force
                 real Thickness
                 routine Skip Spaces
                    Skip Symbol while Next Symbol # NL and Next Symbol <= ' '
                 end
                 on 3,4,9 start
                    if Event_Event # 9 start
                       Oper Message ("Invalid ".concept." for colour """.temp."""")
                       Read Symbol (Temp) until Temp=Nl
                    else
                       Close Input
                       Select Input (Com)
                       return
                    finish
                 finish
                 cycle
                    Speed = 0;   Force = 0;   Acceleration = 0;  Thickness = 0
                    Read (Temp)
                    To Upper (Temp)
                    Concept = "slot number"
                    Read (Slot)
                    skip spaces
                    if Next Symbol # NL start
                       Concept = "pen speed"
                       Read (Speed)
                       Any Speed = true if Speed # 0
                       Skip Spaces
                       if Next Symbol # NL start
                          Concept = "pen force"
                          Read (force)
                          Any Force = true if Force # 0
                          Skip Spaces
                          if Next Symbol # NL start
                             Concept = "pen acceleration"
                             Read (acceleration)
                             Any Acceleration = true if acceleration # 0
                             Skip Spaces
                             if Next Symbol # NL start
                                Concept = "pen thickness"
                                Read (thickness)
                                Any Thickness = True
                             finish
                          finish
                       finish
                    finish
                    Skip Symbol while Next Symbol # NL
                    Skip Symbol
                    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
                             Pen Speed (I) = Speed
                             Pen Force (I) = Force
                             Pen Acceleration (I) = Acceleration
                             Pen Thickness (I) = Thickness
                          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
       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 (';')
       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
       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
           NEW HPGL Char Settings {if required}
           TTPUT (NL)
           ADD ('L', 'B')
           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
       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 Fill Mode # 0 start
            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
   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')
   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
   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')
   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
   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 }
   POF
   FLUSH OUTPUT
end

end of file