! 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