############################################################################
#
#	File:     etch.icn
#
#	Subject:  Program for distributed Etch-A-Sketch
#
#	Author:   Clinton L. Jeffery
#
#	Date:     June 17, 1994
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#  
# A drawing program.  Invoked with one optional argument, the
# name of a remote host on which to share the drawing surface.
#
# Dragging the left button draws black dots
# The middle button draws a line from button press to the release point
# The right button draws white dots
# Control-L clears the screen
# The Escape character exits the program
#
############################################################################
#
#  Requires:  Version 9 graphics
#
############################################################################
#
#  Links:  wopen, xcompat
#
############################################################################

link wopen
link xcompat

procedure main(av)
   local w1, w2, w3, w4, w5, w6, w, x1, xa, x2, xb, y1, ya, y2, yb, dragging,
      da, xc, xd, yc, yd, dc, e
   #
   # open an etch window.  If there was a command line argument,
   # attempt to open a second window on another display.  For
   # each window, create a binding with reverse video for erasing.
   #
   w1 := WOpen("label=etch", "size=300,300") | stop("can't open window")
   w2 := XBind(w1,"drawop=xor") | stop("can't XBind w2")
   w3 := XBind(w1,"reverse=on") | stop("can't XBind w3")
   if *av>0 then {
      w4 := WOpen("label=etch", "display="||av[1]||":0","size=300,300") |
	  stop("can't open window, display=",av[1])
      w5 := XBind(w4,"drawop=xor") | stop("Can't XBind w5")
      w6 := XBind(w4,"reverse=on") | stop("Can't XBind w6")
  }
  repeat {
      #
      # wait for an available event on either display
      #
      w := Active() | stop("Active fails")
      if (w === (w1|w2)) then {
	  x1 := xa
	  x2 := xb
	  y1 := ya
	  y2 := yb
	  dragging := da
      } else {
	  x1 := xc
	  x2 := xd
	  y1 := yc
	  y2 := yd
	  dragging := dc
      }
      
      case e := Event(w) of {
	  #
	  # Mouse down events specify an (x1,y1) point for later drawing.
	  # (x2,y2) is set to null; each down event starts a new draw command.
	  #
	  &lpress | &mpress | &rpress: {
	      x1 := &x
	      y1 := &y
	      x2 := y2 := &null
	  }
	  #
	  # Mouse up events obtain second point (x2,y2), and draw a line.
	  #
	  &lrelease: {
	      DrawLine(w1,\x1,\y1,&x,&y)
	      DrawLine(\w4,\x1,\y1,&x,&y)
	  }
	  &mrelease: {
	      DrawLine(w1,x1,y1,&x,&y)
	      DrawLine(\w4,x1,y1,&x,&y)
	      dragging := &null
	  }
	  &rrelease: {
	      DrawLine(w3,x1,y1,&x,&y)
	      DrawLine(\w6,x1,y1,&x,&y)
	  }
	  #
	  # Drag events obtain a second point, (x2,y2), and draw a line
	  # If we are drawing points, we update (x1,y1); if we are
	  # drawing lines, we erase the "rubberband" line and draw a new
	  # one at each drag event; a permanent line will be drawn when
	  # the button comes up.
	  #
	  &ldrag : {
	      DrawLine(w1,x1,y1,&x,&y)
	      DrawLine(\w4,x1,y1,&x,&y)
	      # left and right buttons use current position
	      x1 := &x   # for subsequent operations
	      y1 := &y
	  }
	  &rdrag : {
	      DrawLine(w3,x1,y1,&x,&y)
	      DrawLine(\w6,x1,y1,&x,&y)
	      # left and right buttons use current position
	      x1 := &x   # for subsequent operations
	      y1 := &y
	  }
	  &mdrag: {
	      if /dragging then dragging := 1
	      else { # erase previous line, if any
		  DrawLine(w2,x1,y1,\x2,\y2)
		  DrawLine(\w5,x1,y1,\x2,\y2)
	      }
	      x2 := &x
	      y2 := &y
	      DrawLine(w2,x1,y1,x2,y2)
	      DrawLine(\w5,x1,y1,x2,y2)
	  }
	  "\^l": {
	      EraseArea(w1)
	      EraseArea(\w4)
	  }
	  "\e": break
      }
      if (w === (w1|w2)) then {
	  xa := x1
	  xb := x2
	  ya := y1
	  yb := y2
	  da := dragging
      } else {
	  xc := x1
	  xd := x2
	  yc := y1
	  yd := y2
	  dc := dragging
      }
  }
end
