! EDWIN driver for SUN workstations

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

record format Point fm (integer x, y)

external routine spec DD INIT   alias "EDWIN_DD_INIT" (integer As, Ac, Dev)
external routine spec DD REINIT alias "EDWIN_DD_REINIT"
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 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 HLINE  alias "EDWIN_DD_HLINE" (integer xl, xr, y)
external routine spec DD POLY   alias "EDWIN_DD_POLY" (integer NP,
                                   integer name xpts,ypts)
external routine spec Check Interrupt alias "EDWIN_DD_INTERRUPT"  -
                                    (integer name state)

own integer SX = 0
own integer SY = 0
own integer XL = 0
own integer YB = 0
own integer XR = 1150
own integer YT = 900
own integer Counter = 0, tempx, tempy

external routine SUN alias "EDWIN___B" (integer Com, X, Y)
   own integer Initialised = 0
   own string (127) text = ""
   own byte Smode=0, CCol = 1
   own integer WX, WY, Nlines = 0
   const integer    Max Args = 3 
   integer           I, P
   integer    array Ptrs (0 : Max Args - 1)
   string(15) array Vals (0 : Max Args - 1)

   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
      record (pointfm) array pts (1:nlines+1)
      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
             pts(i) = pp_p
             pp == pp_next
          repeat
          nlines = nlines + 1
          xpts(nlines) = xpts(1)
          ypts(nlines) = ypts(1)
          pts(nlines) = pts(1)
          DD POLY (nlines, Xpts(1),Ypts(1))
      finish
      nlines = 0
   end

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

   routine Poke S ( string(255) S1, S2 )
      if (Length(S1) > 14) or (Length(S2) > 14) start
         OPER Message ("DDSUN: Poke S - strings too large")
         signal 14, 1
      finish

      Vals(P)     = S1
      CharNo(Vals(P), Length(Vals(P)) + 1) = 0
      P           = P + 1
      Vals(P)     = S2
      CharNo(Vals(P), Length(Vals(P)) + 1) = 0
      P           = P + 1
   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 = X&95 { Upper case W or S is passed on to the C code }
       Point List == New (point list)
       point List_next == Nil
       Dev Data_Name = "a Sun Workstation"
       ! The following numbers should match the window size in ddsunsup.c
       Dev Data_MVX  = 1150
       Dev Data_MVY  = 900
       Dev Data_DVX  = 1150
       Dev Data_DVY  = 900
       Counter = 0
       if Initialised = False start
          Initialised = True
          for I = 0, 1, Max Args - 1 cycle
             Vals(I)  = "" 
             Ptrs(I)  = Addr(CharNo(Vals(I), 1))
          repeat
          P = 0
          Poke S(Fname, Fname)
          P = 1
          Poke S("WINDOW_NAME", Translate("WINDOW_ME"))
          DD INIT (P, Addr(Ptrs(0)), X)
       else
         DD REINIT
       finish
       return

SW(1): ! Terminate
       DD TERM
       return

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

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

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

SW(5): ! Line
       counter = counter + 1
       if counter > 25 start
          Check Interrupt (Counter)
          Imp Int Flag = 1 if Counter = Etx or Counter = Del
          counter = 0
       finish
       if Smode = 0 start
          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<=4
       return
AS(2): ! Character Size
       return
AS(9): ! Overwrite mode
       Y = 0 unless 0<=y<=4
       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
        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.
        if Smode = 0 start
           Sun (4, wx, wy)
           Sun (5, x, wy)
           Sun (5, x, y)
           Sun (5, wx, y)
           Sun (5, wx, wy)
        else
           DD Rect (wx, wy, x, y)
        finish
        counter = counter + 1
        if counter > 25 start
           Check Interrupt (Counter)
           Imp Int Flag = 1 if Counter = Etx or Counter = Del
           counter = 0
        finish
        return

SW(14): ! Circle
        return

SW(*):
end

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

end of file