    ! EDWIN driver for Whitechapel MG1 board

    from EDWIN include Device, Icodes

    record format Point fm (integer x, y)

    dynamic routine spec DD INIT alias "EDWIN_DD_INIT"(integer name x,y)
    dynamic routine spec DD TERM alias "EDWIN_DD_TERM"
    dynamic routine spec DD UPDATE alias "EDWIN_DD_UPDATE"
    dynamic routine spec DD CLEAR alias "EDWIN_DD_CLEAR"
    dynamic routine spec DD COL  alias "EDWIN_DD_COL"  (integer Col)
    dynamic routine spec DD MODE alias "EDWIN_DD_MODE" (integer Mode)
    dynamic routine spec DD FILL alias "EDWIN_DD_FILL" (integer Mode)
    dynamic routine spec DD DOT  alias "EDWIN_DD_DOT"  (integer X, Y)
    dynamic routine spec DD LINE alias "EDWIN_DD_LINE" (integer OX, OY, NX, NY)
    dynamic routine spec DD TEXT alias "EDWIN_DD_TEXT" (integer X, Y, byte name T)
    dynamic routine spec DD RECT alias "EDWIN_DD_RECT" (integer LX, LY, HX, HY)
    dynamic routine spec DD HLINE alias "EDWIN_DD_HLINE" (integer xl, xr, y)
    dynamic routine spec DD POLY alias "EDWIN_DD_POLY" (integer NP,
                                     record(point fm) name fp)
    dynamic 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 = 1023
    own integer YT = 799
    own byte Smode=0, CCol = 1,Cmode = 0

    external routine MG 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.mg1"

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

       routine draw lines
          record (Data fm) name PP
          record (point fm) array pts(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
                 pts(i)_x = pp_p_x
                 pts(i)_y = pp_p_y
                 pp == pp_next
              repeat
              nlines = nlines + 1
              pts(nlines) = pts(1)
              Poly Fill (Nlines, pts)
              DD POLY(Nlines,pts(1)) unless CCol = 0 and Smode # 0
          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 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 Whitechapel Mg-1 workstation"
           DD INIT(Dev Data_MVX,Dev Data_MVY)
           Dev Data_DVX = Dev Data_MVX
           Dev Data_DVY = Dev Data_MVY
           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 <= 1
           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
            Y = 1 unless 0 <= y <= 79
            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
                Mg (4, wx, wy)
                Mg (5, x, wy)
                Mg (5, x, y)
                Mg (5, wx, y)
                Mg (5, wx, wy)
            else
                DD Rect (wx, wy, x, y)
            finish
            return

    SW(14): ! Circle
            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 smode = Cmode, scolour = CCol

       from edwin include specs

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

       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 = smode ; DD mode(cmode)
       CCol = scolour ; DD col(CCol)
    end
    end of file