    ! EDWIN driver for Opus board

    from EDWIN include Device, Icodes

    record format Point fm (integer x, y)

    external routine spec DD INIT alias "EDWIN_DD_INIT"(integer name x,y)
    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 POLY alias "EDWIN_DD_POLY" (integer NP,
                                     integer name xpts,ypts)
    external routine spec DD CIRCLE alias "EDWIN_DD_CIRCLE"(integer x,y,rad)
    external integer function spec DD INTCHECK alias "EDWIN_DD_INTCHECK"

    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 byte Smode=0, CCol = 1,CMode = 0

    external routine OPUS alias "EDWIN___B" (integer Com, X, Y)
       own string (127) text = ""
       own short Counter = 0
       own integer WX, WY, Nlines = 0
       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)

    !   %include "Polyfill.OPS"

       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(1),Ypts(1))
          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)
       counter = counter + 1
       if counter & 64 # 0 start
          counter = 0
          signal 13,0 if DD INTCHECK = 1
        finish

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

       -> SW (Com)

    SW(0): ! Initialise
           Point List == New (point list)
           point List_next == Nil
           Dev Data_Name = "a IBM PC-AT with OPUS board system"
           DD INIT(Dev Data_DVX,Dev Data_DVY)
           Dev Data_MVX = Dev Data_DVX
           Dev Data_MVY = Dev Data_DVY
           XR = Dev Data_DVX
           YT = Dev Data_DVY
           return

    SW(1): ! Terminate
           DD TERM
           return

    SW(2): ! Update
           DD UPDATE
           return

    SW(3): ! New frame
           DD CLEAR
           return

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

    SW(5): ! Line
           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<=4
           return
    AS(2): ! Character Size
           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
            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
                Opus (4, wx, wy)
                Opus (5, x, wy)
                Opus (5, x, y)
                Opus (5, wx, y)
                Opus (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 routine draw dots alias  "EDWIN_DRAW_DOTS" ( -
                     integer lx,ly,hx,hy,gap)
       integer active,i
       integer lx1,ly1,hx1,hy1,x,y,y1,x1
       integer scmode = Cmode, scolour = CCol
       integer fmode = Smode

       Cmode = 0 ; CCol = 1 ; Smode = 1
       DD mode(CMode) ; DD Col(CCol)
       DD fill(Smode)

       lx1 = lx ; ly1 = ly ; hx1 = hx ; hy1 = hy
       !
       ! draw vertical lines
       !
       lx = hx1 ; ly = hy1
       map to device coords(lx,ly)
       y1 = ly
       lx = lx1 ; ly = ly1
       map to device coords(lx,ly)
       y = ly
       lx = lx1 ; ly = ly1
       while lx <= hx1 cycle
          hx = lx ; hy = ly
          map to device coords(hx,hy)
          DD LINE(hx,y,hx,y1)
          lx = lx + gap
       repeat
       !
       ! put black boxes on top
       !
       CCol = 0 ; DD Col(CCol)
       lx = lx1 ; ly = ly1
       while ly < hy1 cycle
          hy = ly ; lx = lx1
          map to device coords(lx,hy) ; x = hx1
          y = ly + gap
          map to device coords(x,y)
          DD RECT(lx,hy + 1,x + 1,y - 1)
          ly = ly + gap
       repeat

       !
       ! put the old values in again
       !
       Cmode = scmode ; DD mode(cmode)
       CCol = scolour ; DD col(CCol)
       Smode = fmode  ; DD fill(Smode)
    end

    end of file