    ! EDWIN driver for X windows

    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_DDX_INIT"
    external routine spec DD TERM   alias "EDWIN_DDX_TERM"
    external routine spec DD UPDATE alias "EDWIN_DDX_UPDATE"
    external routine spec DD CLEAR  alias "EDWIN_DDX_CLEAR"
    external routine spec DD COL    alias "EDWIN_DDX_COL"  (integer Col)
    external routine spec DD MODE   alias "EDWIN_DDX_MODE" (integer Mode)
    external routine spec DD PMODE  alias "EDWIN_DDX_POLYMODE" (integer Mode)
    external routine spec DD FILL   alias "EDWIN_DDX_FILL" (integer Mode)
    external routine spec DD LSTYLE alias "EDWIN_DDX_LSTYLE" (integer Mode)
    external routine spec DD DOT    alias "EDWIN_DDX_DOT"  (integer X, Y)
    external routine spec DD LINE   alias "EDWIN_DDX_LINE" (integer OX, OY, NX, NY)
    external routine spec DD TEXT   alias "EDWIN_DDX_TEXT" (integer X, Y, byte name T)
    external routine spec DD RECT   alias "EDWIN_DDX_RECT" (integer LX, LY, HX, HY)
    external routine spec DD HLINE  alias "EDWIN_DDX_HLINE" (integer xl, xr, y)
    external routine spec DD POLY   alias "EDWIN_DDX_POLY" (integer NP,
                                       integer name xpts,ypts)
    external routine spec Check Interrupt alias "EDWIN_DDX_INTERRUPT"  -
                                        (integer name state)

    own integer SX = 0
    own integer SY = 0
    own integer XL = 0
    own integer YB = 0
    own integer XR = 1023
    own integer YT = 800
    own integer Counter = 0, tempx, tempy

    external routine DDX11 alias "EDWIN___A" (integer Com, X, Y)
       own string (127) text = ""
       own byte Smode=0, CCol = 1
       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)

       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

       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
           Point List == New (point list)
           point List_next == Nil
           Dev Data_Name = "an X window"
           Dev Data_MVX  = 1023
           Dev Data_MVY  = 800
           Dev Data_DVX  = 1023
           Dev Data_DVY  = 800
           Counter = 0
           DD INIT
           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
              if Fname # "DRAFT" start
                 Check Interrupt (Counter)
                 Imp Int Flag = 1 if Counter = Etx or Counter = Del
              finish
              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<=7
           DD L Style (Y)
           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
    AS(13): ! Polygon Rendering
            Y = 0 if Y # 1
            DD P Mode (Y)
            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
               DDX11 (4, wx, wy)
               DDX11 (5, x, wy)
               DDX11 (5, x, y)
               DDX11 (5, wx, y)
               DDX11 (5, wx, wy)
            else
               DD Rect (wx, wy, x, y)
            finish
            counter = counter + 1
            if counter > 25 start
               if Fname # "DRAFT" start
                  Check Interrupt (Counter)
                  Imp Int Flag = 1 if Counter = Etx or Counter = Del
               finish
               counter = 0
            finish
            return

    SW(14): ! Circle
            return

    SW(*):
    end

    end of file