    ! EDWIN driver for Definicon board
    !
    ! A change from the standard one is that the y coord comversion is
    ! done here rather than in the support routine, because that would
    ! mean converting scrdrive stuff twice (tres complicated for the likes
    ! of me)
    !
    ! Another one is the poly takes a integer array name, rather than just the
    ! first element for C calls
    !

    from EDWIN include Device, Icodes
    from Imp   include Ascii
    external byte spec Imp Int Flag alias "IMP___INT_FLAG"
    external routine spec User Refresh
    external string(31) spec Fname

    record format Point fm (integer x, y)

    ! note the extra parameter (non standard)
    external routine spec DD INIT alias "EDWIN_DD_INIT"(integer name x,y,
                                                            integer device num)
    external routine spec DD TERM alias "EDWIN_DD_TERM"
    external routine spec DD UPDATE alias "EDWIN_DD_UPDATE"
    external routine spec DD CLEAR alias "EDWIN_DD_CLEAR"
    external routine spec DD COL  alias "EDWIN_DD_COL"  (integer Col)
    external routine spec DD CS   alias "EDWIN_DD_CHAR" (integer c)
    external routine spec DD MODE alias "EDWIN_DD_MODE" (integer Mode)
    external routine spec DD FILL alias "EDWIN_DD_FILL" (integer Mode)
    external routine spec DD DOT  alias "EDWIN_DD_DOT"  (integer X, Y)
    external routine spec DD LINE alias "EDWIN_DD_LINE" (integer OX, OY, NX, NY)
    external routine spec DD TEXT alias "EDWIN_DD_TEXT" (integer X, Y, byte name T)
    external routine spec DD RECT alias "EDWIN_DD_RECT" (integer LX, LY, HX, HY)
    external routine spec DD SAM  alias "EDWIN___B_SAM" (integer name C, X, Y)
    !
    ! note the different %array parameter than usual
    !
    external routine spec DD POLY alias "EDWIN_DD_POLY" (integer NP,
                                     integer array name xpts,ypts)
    external routine spec DD CIRCLE alias "EDWIN_DD_CIRCLE"(integer x,y,rad)

    own integer SX = 0
    own integer SY = 0
    own integer XL = 0
    own integer YB = 0
    own integer XR = 32767
    own integer YT = 20479
    own integer First Time = 0

    own byte Smode=0, CCol = 1,CMode = 0

    external routine Definicon alias "EDWIN___B" (integer Com, X, Y)
       own string (127) text = ""
       own short Counter = 0
       own integer WX, WY, Nlines = 0, Char, ordinate
       record format Data Fm (record (point fm) p, record (Data Fm) name Next)
       own record (Data fm) name Point List == 0
       own record (Data fm) name Next point == 0
       switch SW(0:15)
       switch AS(0:att maximum)

       routine SWAP (integer name  A, B)
          integer C
          C = A;   A = B;   B = C
       end

       routine draw lines
          record (Data fm) name PP
          integer array xpts,ypts(1:nlines+1)
          integer i
          return if Point List == Nil
          if nlines <= 1 start
              DD Dot (point list_p_x, point list_p_y)
          else if nlines = 2
              DD Line (point list_p_x, point list_p_y,
                       point list_next_p_x, point list_next_p_y)
          else
              pp == point list
              for I = 1, 1, Nlines cycle
                 xpts(i) = pp_p_x
                 ypts(i) = pp_p_y
                 pp == pp_next
              repeat
              nlines = nlines + 1
              xpts(nlines) = xpts(1)
              ypts(nlines) = ypts(1)
              DD POLY (nlines, Xpts,Ypts)
          finish
          nlines = 0
       end

       routine print text
          text = text.tostring (0)
          dd text (sx, sy, byte(addr (text)+1))
          text = ""
       end

       print text if text # "" and com # 6
       draw lines if nlines # 0 and (com = 10 or COM < 5)

    !   select output(0)
    !   print string("Device driven with ".itos(com,0).itos(x,3).itos(y,3))
    !   newline

       -> SW (Com)

    SW(0): ! Initialise
           ! X is 'D' for definicon screen or 'G' for GEM meta-file
           Point List == New (point list)
           Point List_next == Nil
           Dev Data_TYPE = X
           if X = 'D' start
              Dev Data_Name = "an ES2 Solo PC system"
           else
              Dev Data_Name = "a GEM meta-file"
           finish
           DD INIT(Dev Data_DVX,Dev Data_DVY,X)
           Dev Data_MVX = Dev Data_DVX
           Dev Data_MVY = Dev Data_DVY
           XR = Dev Data_DVX
           YT = Dev Data_DVY
           counter = 0
           if Fname = "DRAFT" start
              if First Time = 0 start
                 First Time = 1
              else
                 User Refresh
              finish
           finish
           return

    SW(1): ! Terminate
           DD TERM
           counter = 0
           return

    SW(2): ! Update
           DD UPDATE
           counter = 0
           return

    SW(3): ! New frame
           DD CLEAR
           counter = 0
           return

    SW(4): ! Move
           SX = X;   SY = Dev Data_DVY - Y
           return

    SW(5): ! Line
           counter = counter + 1
           if counter & 16 # 0 start
              counter = 0
              DD SAM (Char, Ordinate, Ordinate)
              Imp Int Flag = 1 if char = Etx or char = Del or char = esc
           finish
           y = Dev Data_DVY - y
           if Smode = 2 start
               DD Dot (x, y)
           else if Smode = 0
               DD Line (sx, sy, x,y)
           else
               if Nlines = 0 start
                   point list_p_x = sx;   point list_p_y = sy
                   Next point == point list
                   Nlines = 1
               finish
               return if x=sx and y=sy
               Nlines = Nlines + 1
               if Next point_next == Nil start
                   Next point_next == New (Next point)
                   Next point      == Next point_next
                   Next point_next == Nil
               else
                   Next point == next point_next
               finish
               next point_p_x = x;   next point_p_y = y
           finish
           sx = x;   SY = y
           return

    SW(6): ! Char
           length(text) = length(text) + 1
           charno(text,length(text)) = x
           print text if length(text) = 126
           return

    SW(7): ! Attribute
           if 0<=x<=Att maximum start
               -> as(x)
    AS(0): ! Colour
           Y = 1 unless 0 <= y <= 15
           CCol = y
           DD Col (CCol)
           return
    AS(1): ! Line style
           Y = 0 unless 0<=y<=7
           return
    AS(2): ! Character Size
           y=5 if y<5
           DD CS(y)
           return
    AS(9): ! Overwrite mode
           Y = 0 unless 0<=y<=4
           CMode = y
           DD Mode (y)
           return
    AS(10): ! Shade mode
            Smode = Y
            DD Fill(Smode)
            return
           finish
    AS(*): { Ignore the rest }
           return

    SW(8): ! Lower window bounds
           XL = X;   YB = Y
           return

    SW(9): ! Upper window bounds
           XR = X;   YT = Y
           return

    SW(10): ! ??
            return

    SW(11): ! Was overwrite mode
            Y = X
            X = Att Colour mode
            -> SW (7)

    SW(12): ! Lower box bounds
            WX = X;   WY = Y
            return

    SW(13): ! Upper box bounds
            counter = counter + 1
            if counter & 16 # 0 start
               counter = 0
               DD SAM (Char, Ordinate, Ordinate)
               Imp Int Flag = 1 if char = Etx or char = Del or char = esc
            finish
            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
            Y = Dev Data_DVY - Y
            WY = Dev Data_DVY - WY
            ! Box now clipped into the screen.
            if Smode = 0 start
                Definicon  (4, wx, wy)
                Definicon  (5, x, wy)
                Definicon (5, x, y)
                Definicon (5, wx, y)
                Definicon (5, wx, wy)
            else
                DD Rect (wx, wy, x, y)
            finish
            return

    SW(14): ! Circle
            dd circle(sx,sy,x)
            return

    SW(*):
    end

    from Edwin include Specs

    external routine Set Device Viewport (integer x, y)
       Dev Data_MVX  = x
       Dev Data_MVY  = y
       Viewport (0, x, 0, y)
    end

    external integer function B Screen Height alias "EDWIN_SCREEN_HEIGHT"
       result = 24
    end

    ! Rev 1 16/12/86 Ulric Jessop   Edwin command SET CHAR SIZE enabled.
    ! Rev 2  3/ 6/87 Ulric Jessop   EDWIN DRAW DOTS command fixed.
    ! Rev 3  9/ 6/88 JGH            EDWIN SCREEN HEIGHT added
    ! Rev 4 19/01/89 JGH            Clean up & draw dots removed, SCN 330
    end of file