Index: trunk/src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 357)
+++ 	(revision )
@@ -1,242 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.actions.mapmode;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Cursor;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.GroupAction;
-import org.openstreetmap.josm.command.AddCommand;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.SequenceCommand;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * This mode adds a new node to the dataset. The user clicks on a place to add
- * and there is it. Nothing more, nothing less.
- *
- * FIXME: "nothing more, nothing less" is a bit out-of-date
- *
- * Newly created nodes are selected. Shift modifier does not cancel the old
- * selection as usual.
- *
- * @author imi
- *
- */
-public class AddNodeAction extends MapMode {
-
-	enum Mode {node, nodeway, autonode}
-	private final Mode mode;
-
-	public static class AddNodeGroup extends GroupAction {
-		public AddNodeGroup(MapFrame mf) {
-			super(KeyEvent.VK_N,0);
-			putValue("help", "Action/AddNode");
-			actions.add(new AddNodeAction(mf,tr("Add node"), Mode.node, tr("Add a new node to the map")));
-			actions.add(new AddNodeAction(mf, tr("Add node into way"), Mode.nodeway,tr( "Add a node into an existing way")));
-			actions.add(new AddNodeAction(mf, tr("Add node and connect"), Mode.autonode,tr( "Add a node and connect it to the selected node (with CTRL: add node into way; with SHIFT: re-use existing node)")));
-			setCurrent(0);
-		}
-	}
-
-	public AddNodeAction(MapFrame mapFrame, String name, Mode mode, String desc) {
-		super(name, "node/"+mode, desc, mapFrame, getCursor());
-		this.mode = mode;
-		putValue("help", "Action/AddNode/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1));
-	}
-
-	private static Cursor getCursor() {
-		try {
-	        return ImageProvider.getCursor("crosshair", null);
-        } catch (Exception e) {
-        }
-	    return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
-    }
-
-	@Override public void enterMode() {
-		super.enterMode();
-		Main.map.mapView.addMouseListener(this);
-	}
-
-	@Override public void exitMode() {
-		super.exitMode();
-		Main.map.mapView.removeMouseListener(this);
-	}
-
-	/**
-	 * If user clicked with the left button, add a node at the current mouse
-	 * position.
-	 *
-	 * If in nodeway mode, insert the node into the way. 
-	 */
-	@Override public void mouseClicked(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-
-		Node n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY()));
-		if (n.coor.isOutSideWorld()) {
-			JOptionPane.showMessageDialog(Main.parent,tr("Cannot add a node outside of the world."));
-			return;
-		}
-
-		Command c = new AddCommand(n);
-		if (mode == Mode.nodeway) {
-			WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint());
-			if (ws == null)
-				return;
-			
-			// see if another segment is also near
-			WaySegment other = Main.map.mapView.getNearestWaySegment(e.getPoint(),
-				Collections.singleton(ws));
-
-			Node n1 = ws.way.nodes.get(ws.lowerIndex),
-				n2 = ws.way.nodes.get(ws.lowerIndex + 1);
-
-			if (other == null && (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) == 0) {
-				// moving the new point to the perpendicular point
-				// FIXME: when two way segments are split, should move the new point to the
-				// intersection point!
-				EastNorth A = n1.eastNorth;
-				EastNorth B = n2.eastNorth;
-				double ab = A.distance(B);
-				double nb = n.eastNorth.distance(B);
-				double na = n.eastNorth.distance(A);
-				double q = (nb-na+ab)/ab/2;
-				n.eastNorth = new EastNorth(B.east() + q*(A.east()-B.east()), B.north() + q*(A.north()-B.north()));
-				n.coor = Main.proj.eastNorth2latlon(n.eastNorth);
-			}
-
-			Collection<Command> cmds = new LinkedList<Command>();
-			cmds.add(c);
-			
-			// split the first segment
-			splitWaySegmentAtNode(ws, n, cmds);
-			
-			// if a second segment was found, split that as well
-			if (other != null) splitWaySegmentAtNode(other, n, cmds);
-
-			c = new SequenceCommand(tr((other == null) ? 
-				"Add node into way" : "Add common node into two ways"), cmds);
-		}
-
-		// Add a node and connecting segment.
-		if (mode == Mode.autonode) {
-
-			WaySegment insertInto = null;
-			Node reuseNode = null;
-			
-			// If CTRL is held, insert the node into a potentially existing way segment
-			if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) {
-				insertInto = Main.map.mapView.getNearestWaySegment(e.getPoint());
-				if (insertInto == null) System.err.println("Couldn't find nearby way segment");
-				if (insertInto == null)
-					return;
-			} 
-			// If SHIFT is held, instead of creating a new node, re-use an existing
-			// node (making this action identical to AddSegmentAction with the
-			// small difference that the node used will then be selected to allow
-			// continuation of the "add node and connect" stuff)
-			else if ((e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0) {
-				OsmPrimitive clicked = Main.map.mapView.getNearest(e.getPoint());
-				if (clicked == null || !(clicked instanceof Node))
-					return;
-				reuseNode = (Node) clicked;
-			}
-			
-			Collection<OsmPrimitive> selection = Main.ds.getSelected();
-			if (selection.size() == 1 && selection.iterator().next() instanceof Node) {
-				Node n1 = (Node)selection.iterator().next();
-
-				Collection<Command> cmds = new LinkedList<Command>();
-				
-				if (reuseNode != null) {
-					// in re-use node mode, n1 must not be identical to clicked node
-					if (n1 == reuseNode) System.err.println("n1 == reuseNode");
-					if (n1 == reuseNode) return;
-					// replace newly created node with existing node
-					n = reuseNode;
-				} else {
-					// only add the node creation command if we're not re-using
-					cmds.add(c);
-				}
-				
-				/* Keep track of the way we change, it might be the same into
-				 * which we insert the node.
-				 */
-				Way wayInsertedInto = null;
-				if (insertInto != null)
-					wayInsertedInto = splitWaySegmentAtNode(insertInto, n, cmds);
-
-				Way way = getWayForNode(n1);
-				if (way == null) {
-					way = new Way();
-					way.nodes.add(n1);
-					cmds.add(new AddCommand(way));
-				} else {
-					if (insertInto != null && way == insertInto.way) {
-						way = wayInsertedInto;
-					} else {
-						Way wnew = new Way(way);
-						cmds.add(new ChangeCommand(way, wnew));
-						way = wnew;
-					}
-				}
-
-				if (way.nodes.get(way.nodes.size() - 1) == n1) {
-					way.nodes.add(n);
-				} else {
-					way.nodes.add(0, n);
-				}
-
-				c = new SequenceCommand(tr((insertInto == null) ? "Add node and connect" : "Add node into way and connect"), cmds);
-			}	
-		}		
-	
-		Main.main.undoRedo.add(c);
-		Main.ds.setSelected(n);
-		Main.map.mapView.repaint();
-	}
-	
-	/**
-	 * @return If the node is the end of exactly one way, return this. 
-	 * 	<code>null</code> otherwise.
-	 */
-	public static Way getWayForNode(Node n) {
-		Way way = null;
-		for (Way w : Main.ds.ways) {
-			if (w.nodes.size() < 1) continue;
-			Node firstNode = w.nodes.get(0);
-			Node lastNode = w.nodes.get(w.nodes.size() - 1);
-			if ((firstNode == n || lastNode == n) && (firstNode != lastNode)) {
-				if (way != null)
-					return null;
-				way = w;
-			}
-		}
-		return way;
-	}
-	
-	private Way splitWaySegmentAtNode(WaySegment ws, Node n, Collection<Command> cmds) {
-		Way wnew = new Way(ws.way);
-		wnew.nodes.add(ws.lowerIndex + 1, n);
-		cmds.add(new ChangeCommand(ws.way, wnew));
-		return wnew;
-	}
-}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java	(revision 357)
+++ 	(revision )
@@ -1,193 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.actions.mapmode;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Point;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.util.Collection;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.command.AddCommand;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * The user can add a new segment between two nodes by pressing on the 
- * starting node and dragging to the ending node. 
- * 
- * No segment can be created if there is already a segment containing
- * both nodes.
- * 
- * @author imi
- */
-public class AddSegmentAction extends MapMode implements MouseListener {
-
-	/**
-	 * The first node the user pressed the button onto.
-	 */
-	private Node first;
-	/**
-	 * The second node used if the user releases the button.
-	 */
-	private Node second;
-
-	/**
-	 * Whether the hint is currently drawn on screen.
-	 */
-	private boolean hintDrawn = false;
-	
-	/**
-	 * Create a new AddSegmentAction.
-	 * @param mapFrame The MapFrame this action belongs to.
-	 */
-	public AddSegmentAction(MapFrame mapFrame) {
-		super(tr("Connect two nodes"), 
-				"addsegment", 
-				tr("Connect two nodes using ways."), 
-				KeyEvent.VK_G, 
-				mapFrame, 
-				ImageProvider.getCursor("normal", "segment"));
-	}
-
-	@Override public void enterMode() {
-		super.enterMode();
-		Main.map.mapView.addMouseListener(this);
-		Main.map.mapView.addMouseMotionListener(this);
-	}
-
-	@Override public void exitMode() {
-		super.exitMode();
-		Main.map.mapView.removeMouseListener(this);
-		Main.map.mapView.removeMouseMotionListener(this);
-		drawHint(false);
-	}
-
-	/**
-	 * Called when user hits space bar while dragging.
-	 */
-	@Override public void actionPerformed(ActionEvent e) {
-		super.actionPerformed(e);
-		makeSegment();
-	}
-
-	/**
-	 * If user clicked on a node, from the dragging with that node. 
-	 */
-	@Override public void mousePressed(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-
-		Node clicked = Main.map.mapView.getNearestNode(e.getPoint());
-		if (clicked == null) return;
-
-		drawHint(false);
-		first = second = clicked;
-	}
-
-	/**
-	 * Draw a hint which nodes will get connected if the user release
-	 * the mouse button now.
-	 */
-	@Override public void mouseDragged(MouseEvent e) {
-		if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
-			return;
-
-		Node hovered = Main.map.mapView.getNearestNode(e.getPoint());
-		if (hovered == second) return;
-
-		drawHint(false);
-		second = hovered;
-		drawHint(true);
-	}
-
-	/**
-	 * If left button was released, try to create the segment.
-	 */
-	@Override public void mouseReleased(MouseEvent e) {
-		if (e.getButton() == MouseEvent.BUTTON1) {
-			drawHint(false);
-			makeSegment();
-			first = null;
-		}
-	}
-
-	/**
-	 * Create the segment if first and second are different and there is
-	 * not already a segment.
-	 */
-	private void makeSegment() {
-		Node n1 = first;
-		Node n2 = second;
-		
-		// this is to allow continued segment drawing by hitting the space bar
-		// at every intermediate node
-		first = second;
-		second = null;
-
-		if (n1 == null || n2 == null || n1 == n2) return;
-
-		Way w = AddNodeAction.getWayForNode(n1);
-		Way wnew;
-		Collection<OsmPrimitive> sel = Main.ds.getSelected();
-		
-		if (w == null) {
-			// create a new way and add it to the current selection.
-			wnew = new Way();
-			wnew.nodes.add(n1);
-			wnew.nodes.add(n2);
-			Main.main.undoRedo.add(new AddCommand(wnew));
-			sel.add(wnew);
-			Main.ds.setSelected(sel);
-		} else {
-			// extend an existing way; only add to current selection if
-			// it is not already in there.
-			wnew = new Way(w);
-			if (wnew.nodes.get(wnew.nodes.size() - 1) == n1) {
-				wnew.nodes.add(n2);
-			} else {
-				wnew.nodes.add(0, n2);
-			}
-			Main.main.undoRedo.add(new ChangeCommand(w, wnew));
-			// do not use wnew below; ChangeCommand only uses wnew as a
-			// message about changes to be done to w but will not replace w!
-			if (!sel.contains(w)) {
-				sel.add(w);
-			}
-			// do not move this into the if block above since it also
-			// fires the selection change event which is desired.
-			Main.ds.setSelected(sel);
-		}
-
-		Main.map.mapView.repaint();
-	}
-
-	/**
-	 * Draw or remove the hint line, depending on the parameter.
-	 */
-	private void drawHint(boolean draw) {
-		if (draw == hintDrawn)
-			return;
-		if (first == null || second == null)
-			return;
-		if (second == first)
-			return;
-
-		Graphics g = Main.map.mapView.getGraphics();
-		g.setColor(Color.BLACK);
-		g.setXORMode(Color.WHITE);
-		Point firstDrawn = Main.map.mapView.getPoint(first.eastNorth);
-		Point secondDrawn = Main.map.mapView.getPoint(second.eastNorth);
-		g.drawLine(firstDrawn.x, firstDrawn.y, secondDrawn.x, secondDrawn.y);
-		hintDrawn = !hintDrawn;
-	}
-}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 357)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 358)
@@ -13,4 +13,5 @@
 import java.util.HashSet;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map.Entry;
 
@@ -18,4 +19,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.AddCommand;
 import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.Command;
@@ -25,4 +27,6 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
+import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
 import org.openstreetmap.josm.gui.MapFrame;
@@ -74,8 +78,15 @@
 		super.actionPerformed(e);
 		boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-		if (ctrl)
-			deleteWithReferences(Main.ds.getSelected());
-		else
-			delete(Main.ds.getSelected(), false, false);
+
+		Command c;
+		if (ctrl) {
+			c = deleteWithReferences(Main.ds.getSelected());
+		} else {
+			c = delete(Main.ds.getSelected());
+		}
+		if (c != null) {
+			Main.main.undoRedo.add(c);
+		}
+
 		Main.map.repaint();
 	}
@@ -88,13 +99,19 @@
 		if (e.getButton() != MouseEvent.BUTTON1)
 			return;
+		boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
 		
-		OsmPrimitive sel = Main.map.mapView.getNearest(e.getPoint());
-		if (sel == null)
-			return;
-
-		if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0)
-			deleteWithReferences(Collections.singleton(sel));
-		else
-			delete(Collections.singleton(sel), true, true);
+		OsmPrimitive sel = Main.map.mapView.getNearestNode(e.getPoint());
+		Command c;
+		if (sel == null) {
+			WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint());
+			c = deleteWaySegment(ws);
+		} else if (ctrl) {
+			c = deleteWithReferences(Collections.singleton(sel));
+		} else {
+			c = delete(Collections.singleton(sel));
+		}
+		if (c != null) {
+			Main.main.undoRedo.add(c);
+		}
 
 		Main.map.mapView.repaint();
@@ -112,84 +129,115 @@
 	 * 
 	 * @param selection The list of all object to be deleted.
-	 */
-	private void deleteWithReferences(Collection<OsmPrimitive> selection) {
+	 * @return command A command to perform the deletions, or null of there is
+	 * nothing to delete.
+	 */
+	private Command deleteWithReferences(Collection<OsmPrimitive> selection) {
 		CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
 		for (OsmPrimitive osm : selection)
 			osm.visit(v);
 		v.data.addAll(selection);
-		if (!v.data.isEmpty())
-			Main.main.undoRedo.add(new DeleteCommand(v.data));
-	}
-
-	/**
-	 * Try to delete all given primitives. If a primitive is
-	 * used somewhere and that "somewhere" is not going to be deleted,
-	 * inform the user and do not delete.
-	 * 
-	 * If a node is to be deleted which is in the middle of exactly one way,
-	 * the node is removed from the way's node list and after that removed
-	 * itself.
+		if (v.data.isEmpty()) {
+			return null;
+		} else {
+			return new DeleteCommand(v.data);
+		}
+	}
+
+	/**
+	 * Try to delete all given primitives.
+	 *
+	 * If a node is used by a way, it's removed from that way.  If a node or a
+	 * way is used by a relation, inform the user and do not delete.
+	 *
+	 * If this would cause ways with less than 2 nodes to be created, delete
+	 * these ways instead.  If they are part of a relation, inform the user
+	 * and do not delete.
 	 * 
 	 * @param selection The objects to delete.
-	 * @param msgBox Whether a message box for errors should be shown
-	 */
-	private void delete(Collection<OsmPrimitive> selection, boolean msgBox, boolean joinIfPossible) {
-		Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>();
-		for (OsmPrimitive osm : selection) {
-			CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
+	 * @return command A command to perform the deletions, or null of there is
+	 * nothing to delete.
+	 */
+	private Command delete(Collection<OsmPrimitive> selection) {
+		if (selection.isEmpty()) return null;
+
+		Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
+		Collection<Way> waysToBeChanged = new HashSet<Way>();
+		for (OsmPrimitive osm : del) {
+			CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
 			osm.visit(v);
-			if (!selection.containsAll(v.data)) {
-				if (osm instanceof Node && joinIfPossible) {
-					String reason = deleteNodeAndJoinWay((Node)osm);
-					if (reason != null && msgBox) {
-						JOptionPane.showMessageDialog(Main.parent,tr("Cannot delete node.")+" "+reason);
-						return;
+			for (OsmPrimitive ref : v.data) {
+				if (del.contains(ref)) continue;
+				if (ref instanceof Way) {
+					waysToBeChanged.add((Way) ref);
+				} else if (ref instanceof Relation) {
+					JOptionPane.showMessageDialog(Main.parent,
+						tr("Cannot delete: Selection is used by relation"));
+					return null;
+				} else {
+					return null;
+				}
+			}
+		}
+
+		Collection<Command> cmds = new LinkedList<Command>();
+		for (Way w : waysToBeChanged) {
+			Way wnew = new Way(w);
+			wnew.nodes.removeAll(del);
+			if (wnew.nodes.size() < 2) {
+				del.add(w);
+
+				CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
+				w.visit(v);
+				for (OsmPrimitive ref : v.data) {
+					if (del.contains(ref)) continue;
+					if (ref instanceof Relation) {
+						JOptionPane.showMessageDialog(Main.parent,
+							tr("Cannot delete: Selection is used by relation"));
+					} else {
+						return null;
 					}
-				} else if (msgBox) {
-					JOptionPane.showMessageDialog(Main.parent, tr("This object is in use."));
-					return;
 				}
 			} else {
-				del.addAll(v.data);
-				del.add(osm);
+				cmds.add(new ChangeCommand(w, wnew));
 			}
 		}
-		if (!del.isEmpty())
-			Main.main.undoRedo.add(new DeleteCommand(del));
-	}
-
-	private String deleteNodeAndJoinWay(Node n) {
-		ArrayList<Way> ways = new ArrayList<Way>(1);
-		for (Way w : Main.ds.ways) {
-			if (!w.deleted && w.nodes.contains(n)) {
-				ways.add(w);
-		}
-		}
-
-		if (ways.size() > 1)
-			return tr("Used by more than one way.");
-		
-		if (ways.size() == 1) {
-			// node in way
-			Way w = ways.get(0);
-
-			int i = w.nodes.indexOf(n);
-			if (w.nodes.lastIndexOf(n) != i)
-				return tr("Occurs more than once in the same way.");
-			if (i == 0 || i == w.nodes.size() - 1)
-				return tr("Is at the end of a way");
-
-			Way wnew = new Way(w);
-			wnew.nodes.remove(i);
-
-			Collection<Command> cmds = new LinkedList<Command>();
-			cmds.add(new ChangeCommand(w, wnew));
-			cmds.add(new DeleteCommand(Collections.singleton(n)));
-			Main.main.undoRedo.add(new SequenceCommand(tr("Delete Node"), cmds));
-		} else {
-			// unwayed node
-			Main.main.undoRedo.add(new DeleteCommand(Collections.singleton(n)));	
-		}
-		return null;
-    }
+
+		if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
+
+		return new SequenceCommand(tr("Delete"), cmds);
+	}
+
+	private Command deleteWaySegment(WaySegment ws) {
+		List<Node> n1 = new ArrayList<Node>(),
+			n2 = new ArrayList<Node>();
+
+		n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
+		n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
+
+		if (n1.size() < 2 && n2.size() < 2) {
+			return new DeleteCommand(Collections.singleton(ws.way));
+		} else {
+			Way wnew = new Way(ws.way);
+			wnew.nodes.clear();
+
+			if (n1.size() < 2) {
+				wnew.nodes.addAll(n2);
+				return new ChangeCommand(ws.way, wnew);
+			} else if (n2.size() < 2) {
+				wnew.nodes.addAll(n1);
+				return new ChangeCommand(ws.way, wnew);
+			} else {
+				Collection<Command> cmds = new LinkedList<Command>();
+
+				wnew.nodes.addAll(n1);
+				cmds.add(new ChangeCommand(ws.way, wnew));
+
+				Way wnew2 = new Way();
+				wnew2.nodes.addAll(n2);
+				cmds.add(new AddCommand(wnew2));
+
+				return new SequenceCommand(tr("Split way segment"), cmds);
+			}
+		}
+	}
 }
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 358)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 358)
@@ -0,0 +1,180 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Cursor;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.GroupAction;
+import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * This mode adds a new node to the dataset. The user clicks on a place to add
+ * and there is it. Nothing more, nothing less.
+ *
+ * FIXME: "nothing more, nothing less" is a bit out-of-date
+ *
+ * Newly created nodes are selected. Shift modifier does not cancel the old
+ * selection as usual.
+ *
+ * @author imi
+ *
+ */
+public class DrawAction extends MapMode {
+
+	public DrawAction(MapFrame mapFrame) {
+		super(tr("Draw"), "node/autonode", tr("Draw nodes"),
+			KeyEvent.VK_N, mapFrame, getCursor());
+		//putValue("help", "Action/AddNode/Autnode");
+	}
+
+	private static Cursor getCursor() {
+		try {
+	        return ImageProvider.getCursor("crosshair", null);
+        } catch (Exception e) {
+        }
+	    return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+    }
+
+	@Override public void enterMode() {
+		super.enterMode();
+		Main.map.mapView.addMouseListener(this);
+	}
+
+	@Override public void exitMode() {
+		super.exitMode();
+		Main.map.mapView.removeMouseListener(this);
+	}
+
+	/**
+	 * If user clicked with the left button, add a node at the current mouse
+	 * position.
+	 *
+	 * If in nodeway mode, insert the node into the way. 
+	 */
+	@Override public void mouseClicked(MouseEvent e) {
+		if (e.getButton() != MouseEvent.BUTTON1)
+			return;
+
+		Collection<OsmPrimitive> selection = Main.ds.getSelected();
+		Collection<Command> cmds = new LinkedList<Command>();
+
+		Way reuseWay = null, replacedWay = null;
+		boolean newNode = false;
+		Node n = Main.map.mapView.getNearestNode(e.getPoint());
+		if (n == null) {
+			n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY()));
+			if (n.coor.isOutSideWorld()) {
+				JOptionPane.showMessageDialog(Main.parent,
+					tr("Cannot add a node outside of the world."));
+				return;
+			}
+			newNode = true;
+
+			cmds.add(new AddCommand(n));
+
+			WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint());
+			if (ws != null) {
+				replacedWay = ws.way;
+				reuseWay = splitWaySegmentAtNode(ws, n, cmds);
+			}
+		}
+
+		boolean extendedWay = false;
+		if (selection.size() == 1 && selection.iterator().next() instanceof Node) {
+			Node n0 = (Node) selection.iterator().next();
+
+			Way way = getWayForNode(n0);
+			if (way == null) {
+				way = new Way();
+				way.nodes.add(n0);
+				cmds.add(new AddCommand(way));
+			} else {
+				if (way == replacedWay) {
+					way = reuseWay;
+				} else {
+					Way wnew = new Way(way);
+					cmds.add(new ChangeCommand(way, wnew));
+					way = wnew;
+				}
+			}
+
+			if (way.nodes.get(way.nodes.size() - 1) == n0) {
+				way.nodes.add(n);
+			} else {
+				way.nodes.add(0, n);
+			}
+
+			extendedWay = true;
+		}
+
+		String title;
+		if (!extendedWay && !newNode) {
+			return; // We didn't do anything.
+		} else if (!extendedWay) {
+			if (reuseWay == null) {
+				title = tr("Add node");
+			} else {
+				title = tr("Add node into way");
+			}
+		} else if (!newNode) {
+			title = tr("Connect existing way to node");
+		} else if (reuseWay == null) {
+			title = tr("Add a new node to an existing way");
+		} else {
+			title = tr("Add node into way and connect");
+		}
+
+		Command c = new SequenceCommand(title, cmds);
+	
+		Main.main.undoRedo.add(c);
+		Main.ds.setSelected(n);
+		Main.map.mapView.repaint();
+	}
+	
+	/**
+	 * @return If the node is the end of exactly one way, return this. 
+	 * 	<code>null</code> otherwise.
+	 */
+	public static Way getWayForNode(Node n) {
+		Way way = null;
+		for (Way w : Main.ds.ways) {
+			if (w.nodes.size() < 1) continue;
+			Node firstNode = w.nodes.get(0);
+			Node lastNode = w.nodes.get(w.nodes.size() - 1);
+			if ((firstNode == n || lastNode == n) && (firstNode != lastNode)) {
+				if (way != null)
+					return null;
+				way = w;
+			}
+		}
+		return way;
+	}
+	
+	private Way splitWaySegmentAtNode(WaySegment ws, Node n, Collection<Command> cmds) {
+		Way wnew = new Way(ws.way);
+		wnew.nodes.add(ws.lowerIndex + 1, n);
+		cmds.add(new ChangeCommand(ws.way, wnew));
+		return wnew;
+	}
+}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/MoveAction.java	(revision 357)
+++ 	(revision )
@@ -1,200 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.actions.mapmode;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Cursor;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.util.Collection;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.GroupAction;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.MoveCommand;
-import org.openstreetmap.josm.command.RotateCommand;
-import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.SelectionManager;
-import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
-import org.openstreetmap.josm.tools.ImageProvider;
-/**
- * Move is an action that can move all kind of OsmPrimitives (except Keys for now).
- *
- * If an selected object is under the mouse when dragging, move all selected objects.
- * If an unselected object is under the mouse when dragging, it becomes selected
- * and will be moved.
- * If no object is under the mouse, move all selected objects (if any)
- * 
- * @author imi
- */
-public class MoveAction extends MapMode implements SelectionEnded {
-	
-	enum Mode {move, rotate}
-	private final Mode mode;
-
-	public static class MoveGroup extends GroupAction {
-		public MoveGroup(MapFrame mf) {
-			super(KeyEvent.VK_M,0);
-			putValue("help", "Action/Move");
-			actions.add(new MoveAction(mf, tr("Move"), Mode.move, tr("Move around objects that are under the mouse or selected.")));
-			actions.add(new MoveAction(mf, tr("Rotate"), Mode.rotate, tr("Rotate selected nodes around centre")));
-			setCurrent(0);
-		}
-	}
-	
-	/**
-	 * The old cursor before the user pressed the mouse button.
-	 */
-	private Cursor oldCursor;
-	/**
-	 * The position of the mouse before the user moves a node.
-	 */
-	private Point mousePos;
-	private SelectionManager selectionManager;
-	private boolean selectionMode = false;
-
-	/**
-	 * Create a new MoveAction
-	 * @param mapFrame The MapFrame, this action belongs to.
-	 */
-	public MoveAction(MapFrame mapFrame, String name, Mode mode, String desc) {
-		super(name, "move/"+mode, desc, mapFrame, getCursor());
-		this.mode = mode;
-		putValue("help", "Action/Move/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1));
-		selectionManager = new SelectionManager(this, false, mapFrame.mapView);
-	}
-
-	private static Cursor getCursor() {
-		try {
-	        return ImageProvider.getCursor("crosshair", null);
-        } catch (Exception e) {
-        }
-	    return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
-    }
-	
-	@Override public void enterMode() {
-		super.enterMode();
-		Main.map.mapView.addMouseListener(this);
-		Main.map.mapView.addMouseMotionListener(this);
-	}
-
-	@Override public void exitMode() {
-		super.exitMode();
-		Main.map.mapView.removeMouseListener(this);
-		Main.map.mapView.removeMouseMotionListener(this);
-	}
-
-	/**
-	 * If the left mouse button is pressed, move all currently selected
-	 * objects (if one of them is under the mouse) or the current one under the
-	 * mouse (which will become selected).
-	 */
-	@Override public void mouseDragged(MouseEvent e) {
-		if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
-			return;
-
-		if (selectionMode)
-			return;
-
-		if (mousePos == null)
-			mousePos = e.getPoint();
-		
-		EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
-		EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
-		double dx = mouseEN.east() - mouseStartEN.east();
-		double dy = mouseEN.north() - mouseStartEN.north();
-		if (dx == 0 && dy == 0)
-			return;
-
-		Collection<OsmPrimitive> selection = Main.ds.getSelected();
-		Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
-		
-		// when rotating, having only one node makes no sense - quit silently
-		if (mode == Mode.rotate && affectedNodes.size() < 2) 
-			return;
-		
-
-		// check if any coordinate would be outside the world
-		for (OsmPrimitive osm : affectedNodes) {
-			if (osm instanceof Node && ((Node)osm).coor.isOutSideWorld()) {
-				JOptionPane.showMessageDialog(Main.parent,tr("Cannot move objects outside of the world."));
-				return;
-			}
-		}
-		Command c = !Main.main.undoRedo.commands.isEmpty() ? Main.main.undoRedo.commands.getLast() : null;
-
-		if (mode == Mode.move) {
-			if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
-				((MoveCommand)c).moveAgain(dx,dy);
-			else
-				Main.main.undoRedo.add(new MoveCommand(selection, dx, dy));
-		} else if (mode == Mode.rotate) {
-			if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
-				((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
-			else
-				Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
-		}
-
-		Main.map.mapView.repaint();
-		mousePos = e.getPoint();
-	}
-
-	/**
-	 * Look, whether any object is selected. If not, select the nearest node.
-	 * If there are no nodes in the dataset, do nothing.
-	 * 
-	 * If the user did not press the left mouse button, do nothing.
-	 * 
-	 * Also remember the starting position of the movement and change the mouse 
-	 * cursor to movement.
-	 */
-	@Override public void mousePressed(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-
-		Collection<OsmPrimitive> sel = Main.ds.getSelected();
-		OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint());
-		if (osm != null) {
-			if (!sel.contains(osm))
-				Main.ds.setSelected(osm);
-			oldCursor = Main.map.mapView.getCursor();
-			
-			if (mode == Mode.move) {
-				Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
-			} else {
-				Main.map.mapView.setCursor(ImageProvider.getCursor("rotate", null));
-			}
-		} else {
-			selectionMode = true;
-			selectionManager.register(Main.map.mapView);
-		}
-
-		Main.map.mapView.repaint();
-
-		mousePos = e.getPoint();
-	}
-
-	/**
-	 * Restore the old mouse cursor.
-	 */
-	@Override public void mouseReleased(MouseEvent e) {
-		if (selectionMode) {
-			selectionManager.unregister(Main.map.mapView);
-			selectionMode = false;
-		} else
-			Main.map.mapView.setCursor(oldCursor);
-	}
-
-
-	public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
-		SelectionAction.selectEverythingInRectangle(selectionManager, r, alt, shift, ctrl);
-	}
-}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 358)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 358)
@@ -0,0 +1,223 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.actions.mapmode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.Collection;
+import java.util.LinkedList;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.GroupAction;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.MoveCommand;
+import org.openstreetmap.josm.command.RotateCommand;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.SelectionManager;
+import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
+import org.openstreetmap.josm.tools.ImageProvider;
+/**
+ * Move is an action that can move all kind of OsmPrimitives (except Keys for now).
+ *
+ * If an selected object is under the mouse when dragging, move all selected objects.
+ * If an unselected object is under the mouse when dragging, it becomes selected
+ * and will be moved.
+ * If no object is under the mouse, move all selected objects (if any)
+ * 
+ * @author imi
+ */
+public class SelectAction extends MapMode implements SelectionEnded {
+	
+	enum Mode {move, rotate}
+	private final Mode mode;
+
+	public static class SelectGroup extends GroupAction {
+		public SelectGroup(MapFrame mf) {
+			super(KeyEvent.VK_S,0);
+			putValue("help", "Action/Move");
+			actions.add(new SelectAction(mf, tr("Select/Move"), Mode.move, tr("Select and move around objects that are under the mouse or selected.")));
+			actions.add(new SelectAction(mf, tr("Rotate"), Mode.rotate, tr("Rotate selected nodes around centre")));
+			setCurrent(0);
+		}
+	}
+	
+	/**
+	 * The old cursor before the user pressed the mouse button.
+	 */
+	private Cursor oldCursor;
+	/**
+	 * The position of the mouse before the user moves a node.
+	 */
+	private Point mousePos;
+	private SelectionManager selectionManager;
+	private boolean selectionMode = false;
+
+	/**
+	 * Create a new MoveAction
+	 * @param mapFrame The MapFrame, this action belongs to.
+	 */
+	public SelectAction(MapFrame mapFrame, String name, Mode mode, String desc) {
+		super(name, "move/"+mode, desc, mapFrame, getCursor());
+		this.mode = mode;
+		putValue("help", "Action/Move/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1));
+		selectionManager = new SelectionManager(this, false, mapFrame.mapView);
+	}
+
+	private static Cursor getCursor() {
+		try {
+	        return ImageProvider.getCursor("crosshair", null);
+        } catch (Exception e) {
+        }
+	    return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+    }
+	
+	@Override public void enterMode() {
+		super.enterMode();
+		Main.map.mapView.addMouseListener(this);
+		Main.map.mapView.addMouseMotionListener(this);
+	}
+
+	@Override public void exitMode() {
+		super.exitMode();
+		Main.map.mapView.removeMouseListener(this);
+		Main.map.mapView.removeMouseMotionListener(this);
+	}
+
+	/**
+	 * If the left mouse button is pressed, move all currently selected
+	 * objects (if one of them is under the mouse) or the current one under the
+	 * mouse (which will become selected).
+	 */
+	@Override public void mouseDragged(MouseEvent e) {
+		if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
+			return;
+
+		if (selectionMode)
+			return;
+
+		if (mousePos == null)
+			mousePos = e.getPoint();
+		
+		EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
+		EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
+		double dx = mouseEN.east() - mouseStartEN.east();
+		double dy = mouseEN.north() - mouseStartEN.north();
+		if (dx == 0 && dy == 0)
+			return;
+
+		Collection<OsmPrimitive> selection = Main.ds.getSelected();
+		Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
+		
+		// when rotating, having only one node makes no sense - quit silently
+		if (mode == Mode.rotate && affectedNodes.size() < 2) 
+			return;
+		
+
+		// check if any coordinate would be outside the world
+		for (OsmPrimitive osm : affectedNodes) {
+			if (osm instanceof Node && ((Node)osm).coor.isOutSideWorld()) {
+				JOptionPane.showMessageDialog(Main.parent,tr("Cannot move objects outside of the world."));
+				return;
+			}
+		}
+		Command c = !Main.main.undoRedo.commands.isEmpty() ? Main.main.undoRedo.commands.getLast() : null;
+
+		if (mode == Mode.move) {
+			if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
+				((MoveCommand)c).moveAgain(dx,dy);
+			else
+				Main.main.undoRedo.add(new MoveCommand(selection, dx, dy));
+		} else if (mode == Mode.rotate) {
+			if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
+				((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
+			else
+				Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
+		}
+
+		Main.map.mapView.repaint();
+		mousePos = e.getPoint();
+	}
+
+	/**
+	 * Look, whether any object is selected. If not, select the nearest node.
+	 * If there are no nodes in the dataset, do nothing.
+	 * 
+	 * If the user did not press the left mouse button, do nothing.
+	 * 
+	 * Also remember the starting position of the movement and change the mouse 
+	 * cursor to movement.
+	 */
+	@Override public void mousePressed(MouseEvent e) {
+		if (e.getButton() != MouseEvent.BUTTON1)
+			return;
+
+		Collection<OsmPrimitive> sel = Main.ds.getSelected();
+		OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint());
+		if (osm != null) {
+			if (!sel.contains(osm))
+				Main.ds.setSelected(osm);
+			oldCursor = Main.map.mapView.getCursor();
+			
+			if (mode == Mode.move) {
+				Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+			} else {
+				Main.map.mapView.setCursor(ImageProvider.getCursor("rotate", null));
+			}
+		} else {
+			selectionMode = true;
+			selectionManager.register(Main.map.mapView);
+			selectionManager.mousePressed(e);
+		}
+
+		Main.map.mapView.repaint();
+
+		mousePos = e.getPoint();
+	}
+
+	/**
+	 * Restore the old mouse cursor.
+	 */
+	@Override public void mouseReleased(MouseEvent e) {
+		if (selectionMode) {
+			selectionManager.unregister(Main.map.mapView);
+			selectionMode = false;
+		} else
+			Main.map.mapView.setCursor(oldCursor);
+	}
+
+	public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
+		SelectionAction.selectEverythingInRectangle(selectionManager, r, alt, shift, ctrl);
+	}
+
+	public static void selectEverythingInRectangle(
+			SelectionManager selectionManager, Rectangle r,
+			boolean alt, boolean shift, boolean ctrl) {
+	    if (shift && ctrl)
+			return; // not allowed together
+
+		Collection<OsmPrimitive> curSel;
+		if (!ctrl && !shift)
+			curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
+		else
+			curSel = Main.ds.getSelected();
+
+		Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
+		for (OsmPrimitive osm : selectionList)
+			if (ctrl)
+				curSel.remove(osm);
+			else
+				curSel.add(osm);
+		Main.ds.setSelected(curSel);
+		Main.map.mapView.repaint();
+    }
+}
Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java	(revision 357)
+++ 	(revision )
@@ -1,128 +1,0 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
-package org.openstreetmap.josm.actions.mapmode;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Rectangle;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.GroupAction;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.gui.MapFrame;
-import org.openstreetmap.josm.gui.SelectionManager;
-import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
-import org.openstreetmap.josm.tools.ImageProvider;
-
-/**
- * This MapMode enables the user to easy make a selection of different objects.
- *
- * The selected objects are drawn in a different style.
- *
- * Holding and dragging the left mouse button draws an selection rectangle.
- * When releasing the left mouse button, all objects within the rectangle get
- * selected.
- *
- * When releasing the left mouse button while the right mouse button pressed,
- * nothing happens (the selection rectangle will be cleared, however).
- *
- * When releasing the mouse button and one of the following keys was hold:
- *
- * If Alt key was hold, select all objects that are touched by the
- * selection rectangle. If the Alt key was not hold, select only those objects
- * completly within (e.g. for ways mean: only if all nodes of the way are
- * within).
- *
- * If Shift key was hold, the objects are added to the current selection. If
- * Shift key wasn't hold, the current selection get replaced.
- *
- * If Ctrl key was hold, remove all objects under the current rectangle from
- * the active selection (if there were any). Nothing is added to the current
- * selection.
- *
- * Alt can be combined with Ctrl or Shift. Ctrl and Shift cannot be combined.
- * If both are pressed, nothing happens when releasing the mouse button.
- *
- * The user can also only click on the map. All total movements of 2 or less
- * pixel are considered "only click". If that happens, the nearest Node will
- * be selected if there is any within 10 pixel range. If there is no Node within
- * 10 pixel, the nearest Way within 10 pixel range is selected. If there is no
- * Way within 10 pixel and the user clicked in or 10 pixel away from an area,
- * this area is selected.  If there is even no area, nothing is selected.
- * Shift and Ctrl key applies to this as usual. For more,
- * @see MapView#getNearest(Point)
- *
- * @author imi
- */
-public class SelectionAction extends MapMode implements SelectionEnded {
-
-	public static class Group extends GroupAction {
-		public Group(MapFrame mf) {
-			super(KeyEvent.VK_S,0);
-			putValue("help", "Action/Selection");
-			actions.add(new SelectionAction(mf, tr("Selection"), tr("Select objects by dragging or clicking.")));
-			setCurrent(0);
-		}
-	}
-
-
-	/**
-	 * The SelectionManager that manages the selection rectangle.
-	 */
-	private SelectionManager selectionManager;
-
-	/**
-	 * Create a new SelectionAction in the given frame.
-	 * @param mapFrame The frame this action belongs to
-	 */
-	public SelectionAction(MapFrame mapFrame, String name, String desc) {
-		super(name, "selection/select", desc, mapFrame, ImageProvider.getCursor("normal", "selection"));
-		putValue("help", "Action/Selection");
-		this.selectionManager = new SelectionManager(this, false, mapFrame.mapView);
-	}
-
-	@Override public void enterMode() {
-		super.enterMode();
-			selectionManager.register(Main.map.mapView);
-	}
-
-	@Override public void exitMode() {
-		super.exitMode();
-			selectionManager.unregister(Main.map.mapView);
-	}
-
-
-	/**
-	 * Check the state of the keys and buttons and set the selection accordingly.
-	 */
-	public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
-		selectEverythingInRectangle(selectionManager, r, alt, shift, ctrl);
-	}
-
-	public static void selectEverythingInRectangle(SelectionManager selectionManager, Rectangle r, boolean alt, boolean shift, boolean ctrl) {
-	    if (shift && ctrl)
-			return; // not allowed together
-
-		Collection<OsmPrimitive> curSel;
-		if (!ctrl && !shift)
-			curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
-		else
-			curSel = Main.ds.getSelected();
-
-		Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
-		for (OsmPrimitive osm : selectionList)
-			if (ctrl)
-				curSel.remove(osm);
-			else
-				curSel.add(osm);
-		Main.ds.setSelected(curSel);
-		Main.map.mapView.repaint();
-    }
-}
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 357)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 358)
@@ -22,4 +22,5 @@
 
 	private final DataSet ds;
+	private final boolean indirectRefs;
 
 	/**
@@ -35,4 +36,10 @@
 	public CollectBackReferencesVisitor(DataSet ds) {
 		this.ds = ds;
+		this.indirectRefs = true;
+	}
+
+	public CollectBackReferencesVisitor(DataSet ds, boolean indirectRefs) {
+		this.ds = ds;
+		this.indirectRefs = indirectRefs;
 	}
 
@@ -44,4 +51,7 @@
 				if (n == n2) {
 					data.add(w);
+					if (indirectRefs) {
+						visit(w);
+					}
 				}
 			}
@@ -65,8 +75,12 @@
 			for (RelationMember m : r.members) {
 				if (m.member == p) {
-					data.add(r);
-					// move up the tree (there might be relations
-					// referring to this relation)
-					checkRelationMembership(r);
+					if (!data.contains(r)) {
+						data.add(r);
+						if (indirectRefs) {
+							// move up the tree (there might be relations
+							// referring to this relation)
+							checkRelationMembership(r);
+						}
+					}
 					break;
 				}
Index: trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 357)
+++ trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 358)
@@ -14,11 +14,9 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.mapmode.AddSegmentAction;
 import org.openstreetmap.josm.actions.mapmode.DeleteAction;
+import org.openstreetmap.josm.actions.mapmode.DrawAction;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
-import org.openstreetmap.josm.actions.mapmode.SelectionAction;
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
-import org.openstreetmap.josm.actions.mapmode.AddNodeAction.AddNodeGroup;
-import org.openstreetmap.josm.actions.mapmode.MoveAction.MoveGroup;
+import org.openstreetmap.josm.actions.mapmode.SelectAction.SelectGroup;
 import org.openstreetmap.josm.gui.dialogs.CommandStackDialog;
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
@@ -80,9 +78,6 @@
 		toolBarActions.setFloatable(false);
 		toolBarActions.add(new IconToggleButton(new ZoomAction(this)));
-		final Action selectionAction = new SelectionAction.Group(this);
-		toolBarActions.add(new IconToggleButton(selectionAction));
-		toolBarActions.add(new IconToggleButton(new MoveGroup(this)));
-		toolBarActions.add(new IconToggleButton(new AddNodeGroup(this)));
-		toolBarActions.add(new IconToggleButton(new AddSegmentAction(this)));
+		toolBarActions.add(new IconToggleButton(new SelectGroup(this)));
+		toolBarActions.add(new IconToggleButton(new DrawAction(this)));
 		toolBarActions.add(new IconToggleButton(new DeleteAction(this)));
 
