import java.awt.*;
import java.applet.*;
import java.util.*;
/*
 *
 * DLobj
 *
 */
abstract class DLobj extends Canvas
{
	final static int WID = 40;
	final static int HT = 40;
	final static int IWID = 20;
	final static int IHT = 20;
	final static Color INHILITE = Color.red;
	final static Color DISCOL = Color.lightGray;
	final static Color ONCOL = Color.yellow;
	final static Color OFFCOL = Color.blue;
	int state = -1;
	int bx = 0;
	int by = 0;
	DLobj dlin[], dlout[];
	int[] dloutin, dlinout;
	DLSim theApplet;
	boolean[] inHilite;

	DLobj() {this.theApplet = null;}
	DLobj(DLSim theApplet){this.theApplet = theApplet;}
	public void paint(Graphics g) {cpaint(0,0,IWID,IHT,g);}
	void cpaint(Graphics g) {cpaint(bx,by,WID,HT,g);}
	abstract protected void cpaint(int bx, int by, int WID, int HT, Graphics g);

	boolean eval()
	{
		int oldstate = state;
		if (dlin[0] != null) state = dlin[0].state;
		else state = -1;
		return (oldstate != state);
	}

	void init(int vin, int vout) {
		resize(WID,HT); 
		dlin = new DLobj[vin];
		dlout = new DLobj[vout];
		dlinout = new int[vin];
		dloutin = new int[vout];
		inHilite = new boolean[vin];
	}

	int whichIn(int x, int y) 
	{
		for (int j = 0; j < dlin.length; j++)
			if (y <= by+(j+1)*HT/(dlin.length)) return j;
		return -1;
	}

	int whichOut(int x, int y) {return 0;}

	Point cin(int i) {return new Point(bx, by+(i+1)*HT/(dlin.length+1));}
	Point cout(int k) {return new Point(bx+WID, by+HT/2);}

	public boolean mouseDown(Event evt, int x, int y)
	{
		DLobj newobj;
		try {
			newobj = (DLobj)(this.getClass().newInstance());
		} catch (Exception e) {return true;}
		newobj.theApplet = this.theApplet;
		newobj.bx = 0;
		newobj.by = 0;
		theApplet.pegboard.objlist.addElement(newobj);
		theApplet.pegboard.repaint();
		return true;
	}
}

class DLand extends DLobj
{
	DLand(DLSim theApplet) {super(theApplet); init(2,1);}
	DLand(){super(); init(2,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawArc(bx+WID/8,by+HT/8,WID-WID/4,HT-HT/4,-90,180);
		g.drawLine(bx+WID/4, by+HT/8, bx+WID/2, by+HT/8);
		g.drawLine(bx+WID/4, by+HT-HT/8, bx+WID/2, by+HT-HT/8);
		g.drawLine(bx+WID/4, by+HT/8, bx+WID/4, by+HT-HT/8);
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/3, bx+WID/4, by+HT/3);
		g.setColor(hold);
		if (inHilite[1]) g.setColor(INHILITE);
		g.drawLine(bx, by+2*HT/3, bx+WID/4, by+2*HT/3);
		g.setColor(hold);
		g.drawLine(bx+WID-WID/8, by+HT/2, bx+WID, by+HT/2);
	}

	boolean eval()
	{
		int oldstate = state;
		int in0 = (dlin[0] == null) ? -1 : dlin[0].state;
		int in1 = (dlin[1] == null) ? -1 : dlin[1].state;		
		if (in0 == -1 && in1 == -1) state = -1;
		else if (in0 == -1 || in1 == -1) state = 0;
		else state = in0 & in1;
		return (oldstate != state);
	}
}

class DLor extends DLobj
{
	DLor(DLSim theApplet) {super(theApplet); resize(WID,HT); init(2,1);}
	DLor(){super(); init(2,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawArc(bx+WID/8,by+HT/8,WID-WID/4, HT-HT/4,-90,180);
		g.drawLine(bx+WID/4, by+WID/8, bx+WID/2, by+HT/8);
		g.drawLine(bx+WID/4, by+HT-HT/8, bx+WID/2, by+HT-HT/8);
		g.drawLine(bx+WID/4, by+HT/8, bx+3*WID/8, by+HT/3);
		g.drawLine(bx+3*WID/8, by+HT/3, bx+3*WID/8, by+2*HT/3);
		g.drawLine(bx+3*WID/8, by+2*HT/3, bx+HT/4, by+HT-HT/8);
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/3, bx+3*WID/8, by+HT/3);
		g.setColor(hold);
		if (inHilite[1]) g.setColor(INHILITE);
		g.drawLine(bx, by+2*HT/3, bx+3*WID/8, by+2*HT/3);
		g.setColor(hold);
		g.drawLine(bx+WID-WID/8, by+HT/2, bx+WID, by+HT/2);
	}

	boolean eval()
	{
		int oldstate = state;
		int in0 = (dlin[0] == null) ? -1 : dlin[0].state;
		int in1 = (dlin[1] == null) ? -1 : dlin[1].state;		
		if (in0 == -1) state = in1;
		else if (in1 == -1) state = in0;
		else state = in0 | in1;
		return (oldstate != state);
	}
}

class DLnot extends DLobj
{
	DLnot(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,1);}
	DLnot(){super(); init(1,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawLine(bx+WID/4, by+HT/8, bx+WID-WID/3, by+HT/2);
		g.drawLine(bx+WID/4, by+HT-HT/8, bx+WID-WID/3, by+HT/2);
		g.drawOval(bx+WID-WID/3, by-HT/11+HT/2, 2*HT/11, 2*HT/11);
		g.drawLine(bx+WID/4, by+HT/8, bx+WID/4, by+HT-HT/8);
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/2, bx+WID/4, by+HT/2);
		g.setColor(hold);
		g.drawLine(bx+WID-WID/8, by+HT/2, bx+WID, by+HT/2);
	}

	boolean eval()
	{
		int oldstate = state;
		if (dlin[0] != null && dlin[0].state != -1) state = 1-dlin[0].state;
		else state = -1;
		return (oldstate != state);
	}
}

class DLnand extends DLobj
{
	DLnand(DLSim theApplet) {super(theApplet); init(2,1);}
	DLnand(){super(); init(2,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawArc(bx+WID/8,by+HT/8,WID-WID/8-WID/3,HT-HT/4,-90,180);
		g.drawLine(bx+WID/4, by+HT/8, bx+2+WID/3, by+HT/8);
		g.drawLine(bx+WID/4, by+HT-HT/8, bx+2+WID/3, by+HT-HT/8);
		g.drawLine(bx+WID/4, by+HT/8, bx+WID/4, by+HT-HT/8);
		g.drawOval(bx+WID-WID/3, by-HT/11+HT/2, 2*HT/11, 2*HT/11);
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/3, bx+WID/4, by+HT/3);
		g.setColor(hold);
		if (inHilite[1]) g.setColor(INHILITE);
		g.drawLine(bx, by+2*HT/3, bx+WID/4, by+2*HT/3);
		g.setColor(hold);
		g.drawLine(bx+WID-WID/8, by+HT/2, bx+WID, by+HT/2);
	}

	boolean eval()
	{
		int oldstate = state;
		int in0 = (dlin[0] == null) ? -1 : dlin[0].state;
		int in1 = (dlin[1] == null) ? -1 : dlin[1].state;		
		if (in0 == -1 && in1 == -1) state = -1;
		else if (in0 == -1 || in1 == -1) state = 1;
		else state = 1-(in0 & in1);
		return (oldstate != state);
	}
}

class DLnor extends DLobj
{
	DLnor(DLSim theApplet) {super(theApplet); resize(WID,HT); init(2,1);}
	DLnor(){super(); init(2,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawArc(bx+WID/8,by+HT/8,WID-WID/8-WID/3,HT-HT/4,-90,180);
		g.drawLine(bx+WID/4, by+HT/8, bx+2+WID/3, by+HT/8);
		g.drawLine(bx+WID/4, by+HT-HT/8, bx+2+WID/3, by+HT-HT/8);
		g.drawLine(bx+WID/4, by+HT/8, bx+3*WID/8, by+HT/3);
		g.drawLine(bx+3*WID/8, by+HT/3, bx+3*WID/8, by+2*HT/3);
		g.drawLine(bx+3*WID/8, by+2*HT/3, bx+HT/4, by+HT-HT/8);
		g.drawOval(bx+WID-WID/3, by-HT/11+HT/2, 2*HT/11, 2*HT/11);
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/3, bx+3*WID/8, by+HT/3);
		g.setColor(hold);
		if (inHilite[1]) g.setColor(INHILITE);
		g.drawLine(bx, by+2*HT/3, bx+3*WID/8, by+2*HT/3);
		g.setColor(hold);
		g.drawLine(bx+WID-WID/8, by+HT/2, bx+WID, by+HT/2);
	}

	boolean eval()
	{
		int oldstate = state;
		int in0 = (dlin[0] == null) ? -1 : dlin[0].state;
		int in1 = (dlin[1] == null) ? -1 : dlin[1].state;		
		if (in0 == -1 && in1 == -1) state = -1;
		else if (in1 == -1) state = 1-in0;
		else if (in0 == -1) state = 1-in1;
		else state = 1-(in0 | in1);
		return (oldstate != state);
	}
}

class DLext extends DLobj
{
	DLext(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,1);}
	DLext(){super(); init(1,1);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/2, bx+WID/4, by+HT/2);
		g.setColor(hold);
		g.drawLine(bx+WID/4, by+HT/2, bx+WID, by+HT/2);
		if (dlout[0] == null) {
			g.drawLine(bx+WID-WID/8, by-HT/8+HT/2, bx+WID, by+HT/2);
			g.drawLine(bx+WID-WID/8, by+HT/8+HT/2, bx+WID, by+HT/2);
		}
	}

}

class DLbext extends DLobj
{
	DLbext(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,1);}
	DLbext(){super(); init(1,1);}

	Point cin(int i) {return new Point(bx+WID, by+HT/2);}
	Point cout(int i) {return new Point(bx, by+HT/2);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx+WID-WID/4, by+HT/2, bx+WID, by+HT/2);
		g.setColor(hold);
		g.drawLine(bx, by+HT/2, bx+WID-WID/4, by+HT/2);
		if (dlout[0] == null) {
			g.drawLine(bx, by+HT/2, bx+WID/8, by-HT/8+HT/2);
			g.drawLine(bx, by+HT/2, bx+WID/8, by+HT/8+HT/2);
		}
	}

}

class DLutee extends DLobj
{
	DLutee(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,2);}
	DLutee(){super(); init(1,2);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/2, bx+WID/4, by+HT/2);
		g.setColor(hold);
		g.drawLine(bx+WID/4, by+HT/2, bx+WID, by+HT/2);
		g.drawLine(bx+WID/2, by+HT/2, bx+WID/2, by);
		if (dlout[0] == null) {
			g.drawLine(bx+WID-WID/8, by-HT/8+HT/2, bx+WID, by+HT/2);
			g.drawLine(bx+WID-WID/8, by+HT/8+HT/2, bx+WID, by+HT/2);
		}
		if (dlout[1] == null) {
			g.drawLine(bx-WID/8+WID/2, by+HT/8, bx+WID/2, by);
			g.drawLine(bx+WID/8+WID/2, by+HT/8, bx+WID/2, by);
		}

	}

	int whichOut(int x, int y) 
	{
		if (y <= (HT/WID)*(bx - x) + by + HT) return 1;
		return 0;
	}

	Point cout(int k) {
		if (k == 0) return new Point(bx+WID, by+HT/2);
		return new Point(bx+WID/2, by);
	}
}

class DLdtee extends DLobj
{
	DLdtee(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,2);}
	DLdtee(){super(); init(1,2);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		Color hold = g.getColor();
		if (inHilite[0]) g.setColor(INHILITE);
		g.drawLine(bx, by+HT/2, bx+WID/4, by+HT/2);
		g.setColor(hold);
		g.drawLine(bx+WID/4, by+HT/2, bx+WID, by+HT/2);
		g.drawLine(bx+WID/2, by+HT/2, bx+WID/2, by+HT);
		if (dlout[0] == null) {
			g.drawLine(bx+WID-WID/8, by-HT/8+HT/2, bx+WID, by+HT/2);
			g.drawLine(bx+WID-WID/8, by+HT/8+HT/2, bx+WID, by+HT/2);
		}
		if (dlout[1] == null) {
			g.drawLine(bx-WID/8+WID/2, by+HT-HT/8, bx+WID/2, by+HT);
			g.drawLine(bx+WID/8+WID/2, by+HT-HT/8, bx+WID/2, by+HT);
		}

	}

	int whichOut(int x, int y) 
	{
		if (y <= (HT/WID)*(x - bx) + by) return 0;
		return 1;
	}

	Point cout(int k) {
		if (k == 0) return new Point(bx+WID, by+HT/2);
		return new Point(bx+WID/2, by+HT);
	}

}

interface Labelable
{
	public void getLabel();
	public void putLabel(String theLabel);
	public int bx();
	public int by();
}

class DLswitch extends DLobj implements Labelable
{
	String theLabel = null;

	DLswitch(DLSim theApplet) {super(theApplet); resize(WID,HT); init(0,1); state = 0;}
	DLswitch(){super(); init(0,1); state = 0;}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawLine(bx+WID/4, by+HT/4, bx+WID-WID/3, by+HT/4);
		g.drawLine(bx+WID-WID/3, by+HT/4, bx+WID, by+HT/2);
		g.drawLine(bx+WID/4, by+HT-HT/4, bx+WID-WID/3, by+HT-HT/4);
		g.drawLine(bx+WID-WID/3, by+HT-HT/4, bx+WID, by+HT/2);
		g.drawLine(bx+WID/4, by+HT/4, bx+WID/4, by+HT-HT/4);
		Color hold = g.getColor();
		g.setColor((state == 0) ? OFFCOL : ONCOL);
		g.fillOval(bx+WID/3,by+HT/3,WID-2*WID/3+30/WID,HT-2*HT/3+30/HT);
		g.setColor(hold);
		if (theLabel != null) {
			Font OldFnt = g.getFont();
			g.setFont(new Font("Arial", Font.ITALIC, 9));
			g.drawString(theLabel, bx, by+g.getFontMetrics().getAscent());
			g.setFont(OldFnt);
		}
	}

	int whichIn(int x, int y) {return -1;}

	boolean eval(){return false;}
	public int bx(){return bx;}
	public int by(){return by;}

	public void putLabel(String theLabel){this.theLabel = theLabel;}

	public void getLabel()
	{
		try {
			Thread.sleep(200);
		} catch (Exception e) {}
		new LDialog(theApplet, this).show();
	}
}

class DLbulb extends DLobj implements Labelable
{
	String theLabel = null;

	DLbulb(DLSim theApplet) {super(theApplet); resize(WID,HT); init(1,0);}
	DLbulb(){super(); init(1,0);}

	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		g.drawLine(bx+WID/3, by+HT/4, bx+WID-WID/4, by+HT/4);
		g.drawLine(bx, by+HT/2, bx+WID/3, by+HT/4);
		g.drawLine(bx+WID/3, by+HT-HT/4, bx+WID-WID/4, by+HT-HT/4);
		g.drawLine(bx, by+HT/2, bx+WID/3, by+HT-HT/4);
		g.drawLine(bx+WID-WID/4, by+HT/4, bx+WID-WID/4, by+HT-HT/4);
		Color hold = g.getColor();
		g.setColor((state == -1) ? DISCOL : (state == 0) ? OFFCOL : ONCOL);
		g.fillOval(bx+WID/3,by+HT/3,WID-2*WID/3+30/WID,HT-2*HT/3+30/HT);
		g.setColor(hold);
		if (theLabel != null) {
			Font OldFnt = g.getFont();
			g.setFont(new Font("Arial", Font.ITALIC, 9));
			g.drawString(theLabel, bx, by+g.getFontMetrics().getAscent());
			g.setFont(OldFnt);
		}
	}

	int whichOut(int x, int y) {return -1;}

	public int bx(){return bx;}
	public int by(){return by;}

	public void putLabel(String theLabel){this.theLabel = theLabel;}

	public void getLabel()
	{
		try {
			Thread.sleep(200);
		} catch (Exception e) {}
		new LDialog(theApplet, this).show();
	}
}

class DLlabel extends DLobj implements Labelable
{
	String theLabel = "Label";
	LDialog dlg;

	DLlabel(String theLabel, DLSim theApplet)
	{super(theApplet); resize(WID,HT); init(0,0); this.theLabel = theLabel;}
	DLlabel(DLSim theApplet) {super(theApplet); resize(WID,HT); init(0,0);}
	DLlabel(){super(); init(0,0);}

	int whichOut(int x, int y) {return -1;}
	int whichIn(int x, int y) {return -1;}
	boolean eval(){return false;}
	public int bx(){return bx;}
	public int by(){return by;}

	public void putLabel(String theLabel){this.theLabel = theLabel;}

	public void getLabel()
	{
		try {
			Thread.sleep(200);
		} catch (Exception e) {}
		new LDialog(theApplet, this).show();
	}
	
	protected void cpaint(int bx, int by, int WID, int HT, Graphics g)
	{
		if (theLabel == null || theLabel.length() == 0) g.drawRect(bx, by, WID-1, HT-1);
		g.drawString(theLabel, bx+WID/20, by+3*HT/5);
	}
}

class CPanel extends Panel
{
	public void paint(Graphics g)
	{
		super.paint(g);
		g.drawRect(0,0,size().width-1,size().height-1);
	}
}

class DCanvas extends Canvas
{
	final static int NEUTRAL = 0;
	final static int MOVE = 1;
	final static int CONNECT = 2;
	final static Color BKCOL = Color.white;
	final static Color SBKCOL = Color.black;
	int mode;
	Vector objlist;
	DLobj current = null;
	int currentOut = 0;
	DLobj oldInHilite = null;
	int drag_x;
	int drag_y;
	DLSim theApplet;

	DCanvas(DLSim theApplet)
	{
		super();
		setBackground(BKCOL);
		mode = NEUTRAL;
		this.theApplet = theApplet;
		objlist = new Vector();
	}

	public void paint(Graphics g)
	{
		g.drawRect(0,0,size().width-1,size().height-1);
		for (int i = 0; i < objlist.size(); i++) {
			DLobj theobj = (DLobj)objlist.elementAt(i);
			Color hold = g.getColor();
			if (theApplet.simmode == theApplet.SIMON)
				g.setColor((theobj.state == -1) ? DLobj.DISCOL :
						   (theobj.state == 0) ? DLobj.OFFCOL : DLobj.ONCOL);
			theobj.cpaint(g);
			g.setColor(hold);
		}
		for (int i = 0; i < objlist.size(); i++) {
			DLobj source = (DLobj)objlist.elementAt(i);
			for (int j = 0; j < source.dlout.length; j++) {
				DLobj target = source.dlout[j];
				if (target != null) {
					Color hold = g.getColor();
					if (theApplet.simmode == theApplet.SIMON)
						g.setColor((source.state == -1) ? DLobj.DISCOL :
								   (source.state == 0) ? DLobj.OFFCOL : DLobj.ONCOL);
					g.drawLine(source.cout(j).x, source.cout(j).y, 
						       target.cin(source.dloutin[j]).x, target.cin(source.dloutin[j]).y);
					g.setColor(hold);
				}
			}
		}
		if (mode == CONNECT && current != null) {
			Color hold = g.getColor();
			if (theApplet.simmode == theApplet.SIMON) 
				g.setColor((current.state == -1) ? DLobj.DISCOL :
						   (current.state == 0) ? DLobj.OFFCOL : DLobj.ONCOL);
			g.drawLine(current.cout(currentOut).x, current.cout(currentOut).y, drag_x, drag_y);
			g.setColor(hold);
		}
	}

	// MOUSE SUPPORT:
	//		The mouseDown() method is called if the mouse button is pressed
	// while the mouse cursor is over the applet's portion of the screen.
	//--------------------------------------------------------------------------
	public boolean mouseDown(Event evt, int x, int y)
	{
		DLobj theobj;

		if (current != null) return true;
		if ((theobj = dlobjAt(x,y)) == null) return true;
		mode = ((evt.modifiers & Event.META_MASK) != 0) ? CONNECT : MOVE;
		current = theobj;
		drag_x = x;
		drag_y = y;
		if (mode == MOVE && current instanceof DLswitch){
			Rectangle brect = 
				new Rectangle(current.bx+DLobj.WID/3,current.by+DLobj.HT/3,
						      DLobj.WID-2*DLobj.WID/3+30/DLobj.WID,
							  DLobj.HT-2*DLobj.HT/3+30/DLobj.HT);
			if (brect.inside(x,y)) {
				current.state = 1 - current.state;
				mode = NEUTRAL;
				current = null;
				repaint(brect.x, brect.y, brect.width, brect.height);
				Thread m_sim = new Thread(new Simulate(theApplet));
				m_sim.start();
				return true;
			} 
		}
		if (mode == CONNECT) {
			if (current instanceof DLswitch || current instanceof DLbulb) {
				Rectangle lrect = new Rectangle(current.bx, current.by, DLobj.WID, DLobj.HT/3);
				if (lrect.inside(x,y)) {
					if (current instanceof DLswitch) ((DLswitch)current).getLabel();
					else ((DLbulb)current).getLabel();
					current = null;
					mode = NEUTRAL;
					return true;
				}
			}
			if (current instanceof DLlabel) {
				((DLlabel)current).getLabel();
				current = null;
				mode = NEUTRAL;
				return true;
			}
			if ((currentOut = current.whichOut(x, y)) < 0) {
				mode = NEUTRAL;
				current = null;
				return true;
			}
			if (current.dlout[currentOut] != null) {
				DLobj target = current.dlout[currentOut];
				for (int j = 0; j < target.dlin.length; j++)
					if (target.dlin[j] == current) target.dlin[j] = null;
				current.dlout[currentOut] = null;
				Thread m_sim = new Thread(new Simulate(theApplet));
				m_sim.start();
			}
		}
		repaint();
		return true;
	}

	// MOUSE SUPPORT:
	//		The mouseUp() method is called if the mouse button is released
	// while the mouse cursor is over the applet's portion of the screen.
	//--------------------------------------------------------------------------
	public boolean mouseUp(Event evt, int x, int y)
	{
		if (current == null) return true;
		if (mode == CONNECT) {
			killHilite();
			DLobj target = dlobjAt(x,y);
			if (target != null && target != current) {
				int j = target.whichIn(x, y);
				if (j >= 0) {
					current.dlout[currentOut] = target;
					DLobj oldIn;
					if ((oldIn = target.dlin[j]) != null) oldIn.dlout[target.dlinout[j]] = null;
					target.dlin[j] = current;
					current.dloutin[currentOut] = j;
					target.dlinout[j] = currentOut;
				}
				Thread m_sim = new Thread(new Simulate(theApplet));
				m_sim.start();
			}
		}
		current = null;
		mode = NEUTRAL;
		repaint();
		return true;
	}

	DLobj dlobjAt(int x, int y) 
	{
		for (int i = 0; i < objlist.size(); i++) {
			DLobj theobj = (DLobj)objlist.elementAt(i);
			if (x >= theobj.bx && x <= theobj.bx+DLobj.WID
				&& y >= theobj.by && y <= theobj.by+DLobj.HT) 
				return theobj;
		}	
		return null;
	}

	void killHilite()
	{
		if (oldInHilite != null) 
			for (int j = 0; j < oldInHilite.dlin.length; j++)
					oldInHilite.inHilite[j] = false;
	}

	// MOUSE SUPPORT:
	//		The mouseDrag() method is called if the mouse cursor moves over the
	// applet's portion of the screen while the mouse button is being held down.
	//--------------------------------------------------------------------------
	public boolean mouseDrag(Event evt, int x, int y)
	{
		if (current != null){
			if (mode == CONNECT) {
				Rectangle clrect = new Rectangle(current.cout(currentOut));
				clrect.add(new Point(drag_x, drag_y));
				drag_x = x;
				drag_y = y;
				clrect.add(new Point(drag_x, drag_y));
				DLobj target = dlobjAt(x, y);
				killHilite();
				if (target != null && target != current && target.dlin.length > 0) {
					target.inHilite[target.whichIn(x,y)] = true;
					oldInHilite = target;
				}
				repaint(clrect.x-DLobj.WID/2, clrect.y-DLobj.HT/2, 
						clrect.width+DLobj.WID, clrect.height+DLobj.HT);
				return true;
			}
			int dx = x - drag_x;
			int dy = y - drag_y;
			drag_x = x;
			drag_y = y;
			int oldbx = current.bx;
			int oldby = current.by;
			current.bx += dx;
			current.by += dy;
			int sx = Math.min(oldbx, current.bx) - 2;
			int sy = Math.min(oldby, current.by) - 2;
			int lx = Math.max(oldbx, current.bx) + DLobj.WID + 2;
			int ly = Math.max(oldby, current.by) + DLobj.HT + 2;
			Rectangle clrect = new Rectangle(sx, sy, lx-sx, ly-sy);
			for (int i = 0; i < current.dlin.length; i++)
				if (current.dlin[i] != null) 
					clrect.add(current.dlin[i].cout(current.dlinout[i]));
			for (int i = 0; i < current.dlout.length; i++)
				if (current.dlout[i] != null) 
					clrect.add(current.dlout[i].cin(current.dloutin[i]));
			repaint(clrect.x-DLobj.WID/2, clrect.y-DLobj.HT/2, 
						clrect.width+DLobj.WID, clrect.height+DLobj.HT);
		}
		return true;
	}

	

	// MOUSE SUPPORT:
	//		The mouseMove() method is called if the mouse cursor moves over the
	// applet's portion of the screen and the mouse button isn't being held down.
	//--------------------------------------------------------------------------
	public boolean mouseMove(Event evt, int x, int y)
	{
		return false;
	}

	// MOUSE SUPPORT:
	//		The mouseEnter() method is called if the mouse cursor enters the
	// applet's portion of the screen.
	//--------------------------------------------------------------------------
	public boolean mouseEnter(Event evt, int x, int y)
	{
		// TODO: Place applet mouseEnter code here
//		if (current == null) theApplet.myFrame.setCursor(Frame.CROSSHAIR_CURSOR);
//		else theApplet.myFrame.setCursor(Frame.MOVE_CURSOR);
		return true;
	}

	// MOUSE SUPPORT:
	//		The mouseExit() method is called if the mouse cursor leaves the
	// applet's portion of the screen.
 	//--------------------------------------------------------------------------
	public boolean mouseExit(Event evt, int x, int y)
	{
		if (current != null && mode == MOVE) {
			objlist.removeElement(current);
			for (int i = 0; i < objlist.size(); i++) {
				DLobj theobj = (DLobj)objlist.elementAt(i);
				for (int j = 0; j < theobj.dlout.length; j++)
					if (theobj.dlout[j] == current) theobj.dlout[j] = null;
			}
			current = null;
			Thread m_sim = new Thread(new Simulate(theApplet));
			m_sim.start();
			repaint();
		}
		return true;
	}


	// TODO: Place additional applet code here

}
