Index: /src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 34)
+++ /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 35)
@@ -7,4 +7,5 @@
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
@@ -169,4 +170,7 @@
 			x.printStackTrace();
 			JOptionPane.showMessageDialog(Main.main, x.getMessage());
+		} catch (FileNotFoundException x) {
+			x.printStackTrace();
+			JOptionPane.showMessageDialog(Main.main, "URL nicht gefunden: "+x.getMessage());
 		} catch (IOException x) {
 			x.printStackTrace();
Index: /src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 34)
+++ /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 35)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Track;
 import org.openstreetmap.josm.gui.GBC;
 import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
@@ -41,26 +42,24 @@
 		Collection<OsmPrimitive> update = new LinkedList<OsmPrimitive>();
 		Collection<OsmPrimitive> delete = new LinkedList<OsmPrimitive>();
-		for (OsmPrimitive osm : Main.main.ds.nodes)
-			if (osm.id == 0)
+		for (OsmPrimitive osm : Main.main.ds.allPrimitives()) {
+			if (osm instanceof Track) {
+				int answer = JOptionPane.showConfirmDialog(Main.main, 
+						"The server currently does not understand the concept of Tracks.\n" +
+						"All tracks will be ignored on upload. Continue anyway?",
+						"No Track support", JOptionPane.YES_NO_OPTION);
+				if (answer != JOptionPane.YES_OPTION)
+					return;
+			}
+			if (osm.id == 0 && !osm.isDeleted())
 				add.add(osm);
-			else if (osm.modified)
+			else if ((osm.modified || osm.modifiedProperties) && !osm.isDeleted())
 				update.add(osm);
-		for (OsmPrimitive osm : Main.main.ds.lineSegments)
-			if (osm.id == 0)
-				add.add(osm);
-			else if (osm.modified)
-				update.add(osm);
-		for (OsmPrimitive osm : Main.main.ds.tracks)
-			if (osm.id == 0)
-				add.add(osm);
-			else if (osm.modified)
-				update.add(osm);
-		for (OsmPrimitive osm : Main.main.ds.deleted)
-			if (osm.id != 0)
+			else if (osm.isDeleted() && osm.id != 0)
 				delete.add(osm);
+		}
 
 		if (!displayUploadScreen(add, update, delete))
 			return;
-		
+
 		OsmServerWriter server = new OsmServerWriter();
 		try {
@@ -70,4 +69,6 @@
 			all.addAll(delete);
 			server.uploadOsm(all);
+			// finished without errors -> clean dataset
+			Main.main.getMapFrame().mapView.editLayer().cleanData();
 		} catch (JDOMException x) {
 			x.printStackTrace();
@@ -87,5 +88,5 @@
 			return false;
 		}
-		
+
 		JPanel p = new JPanel(new GridBagLayout());
 
Index: /src/org/openstreetmap/josm/command/AddCommand.java
===================================================================
--- /src/org/openstreetmap/josm/command/AddCommand.java	(revision 34)
+++ /src/org/openstreetmap/josm/command/AddCommand.java	(revision 35)
@@ -6,5 +6,4 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
-import org.openstreetmap.josm.data.osm.visitor.DeleteVisitor;
 
 /**
@@ -39,5 +38,5 @@
 
 	public void undoCommand() {
-		osm.visit(new DeleteVisitor(ds));
+		osm.setDeleted(true);
 	}
 
Index: /src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java
===================================================================
--- /src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java	(revision 34)
+++ /src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java	(revision 35)
@@ -55,6 +55,6 @@
 		for (OsmPrimitive osm : objects) {
 			oldProperties.add(osm.keys == null ? null : new HashMap<Key, String>(osm.keys));
-			oldModified.add(osm.modified);
-			osm.modified = true;
+			oldModified.add(osm.modifiedProperties);
+			osm.modifiedProperties = true;
 		}
 
@@ -81,5 +81,5 @@
 		for (OsmPrimitive osm : objects) {
 			osm.keys = it.next();
-			osm.modified = itMod.next();
+			osm.modifiedProperties = itMod.next();
 		}
 	}
Index: /src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- /src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 34)
+++ /src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 35)
@@ -8,5 +8,4 @@
 import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
-import org.openstreetmap.josm.data.osm.visitor.DeleteVisitor;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 
@@ -35,7 +34,6 @@
 	
 	public void executeCommand() {
-		Visitor v = new DeleteVisitor(ds);
 		for (OsmPrimitive osm : data)
-			osm.visit(v);
+			osm.setDeleted(true);
 	}
 
Index: /src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 35)
@@ -2,8 +2,6 @@
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
-import java.util.Map;
 
 import org.openstreetmap.josm.data.Bounds;
@@ -44,8 +42,15 @@
 
 	/**
-	 * All deleted objects goes here.
+	 * @return A collection containing all primitives (except keys) of the
+	 * dataset.
 	 */
-	public Collection<OsmPrimitive> deleted = new LinkedList<OsmPrimitive>();
-
+	public Collection<OsmPrimitive> allPrimitives() {
+		Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
+		o.addAll(nodes);
+		o.addAll(lineSegments);
+		o.addAll(tracks);
+		return o;
+	}
+	
 	/**
 	 * Return the bounds of this DataSet, depending on X/Y values.
@@ -133,83 +138,4 @@
 
 	/**
-	 * Import the given dataset by merging all data with this dataset.
-	 * The objects imported are not cloned, so from now on, these data belong
-	 * to both datasets. So use mergeFrom only if you are about to abandon the
-	 * other dataset.
-	 *
-	 * Elements are tried to merged. 
-	 * Nodes are merged first, if their lat/lon are equal.
-	 * Line segments are merged, if they have the same nodes.
-	 * Tracks are merged, if they consist of the same line segments.
-	 *
-	 * TODO Additional to that, every two objects with the same id are merged.
-	 *
-	 * @param ds	The DataSet to merge into this one.
-	 */
-	public void mergeFrom(DataSet ds) {
-		// merge nodes
-		
-		Map<Node, Node> nodeMap = new HashMap<Node, Node>();
-
-		// find mergable
-		for (Node otherNode : ds.nodes)
-			for (Node myNode : nodes)
-				if (otherNode.coor.equalsLatLon(myNode.coor))
-					nodeMap.put(otherNode, myNode);
-		// add
-		for (Node n : ds.nodes)
-			if (!nodeMap.containsKey(n))
-				nodes.add(n);
-		// reassign
-		for (LineSegment ls : ds.lineSegments) {
-			Node n = nodeMap.get(ls.start);
-			if (n != null)
-				ls.start = n;
-			n = nodeMap.get(ls.end);
-			if (n != null)
-				ls.end = n;
-		}
-
-
-		// merge line segments
-
-		Map<LineSegment, LineSegment> lsMap = new HashMap<LineSegment, LineSegment>();
-		// find mergable
-		for (LineSegment otherLS : ds.lineSegments)
-			for (LineSegment myLS : lineSegments)
-				if (otherLS.start == myLS.start && otherLS.end == myLS.end)
-					lsMap.put(otherLS, myLS);
-		// add ls
-		for (LineSegment ls : ds.lineSegments)
-			if (!lsMap.containsKey(ls))
-				lineSegments.add(ls);
-		// reassign
-		for (Track t : ds.tracks) {
-			for (int i = 0; i < t.segments.size(); ++i) {
-				LineSegment newLS = lsMap.get(t.segments.get(i));
-				if (newLS != null)
-					t.segments.set(i, newLS);
-			}
-		}
-
-
-		// merge tracks
-		
-		LinkedList<Track> trackToAdd = new LinkedList<Track>();
-		for (Track otherTrack : ds.tracks) {
-			boolean found = false;
-			for (Track myTrack : tracks) {
-				if (myTrack.segments.equals(otherTrack.segments)) {
-					found = true;
-					break;
-				}
-			}
-			if (!found)
-				trackToAdd.add(otherTrack);
-		}
-		tracks.addAll(trackToAdd);
-	}
-
-	/**
 	 * Remove the selection from every value in the collection.
 	 * @param list The collection to remove the selection from.
@@ -234,5 +160,5 @@
 			return sel;
 		for (OsmPrimitive osm : list) {
-			if (osm.isSelected())
+			if (osm.isSelected() && !osm.isDeleted())
 				sel.add(osm);
 			if (osm.keys != null)
Index: /src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 35)
@@ -15,4 +15,5 @@
 abstract public class OsmPrimitive {
 
+
 	/**
 	 * The key/value list for this primitive.
@@ -28,11 +29,23 @@
 
 	/**
-	 * <code>true</code>, if the object has been modified since it was loaded from
-	 * the server. In this case, on next upload, this object will be updated. Deleted
-	 * objects are deleted from the server, even if they are modified. If the objects
-	 * are added (id=0), the modified is ignored and the object is added to the server. 
+	 * <code>true</code>, if the objects content (not the properties) has been 
+	 * modified since it was loaded from the server. In this case, on next upload,
+	 * this object will be updated. Deleted objects are deleted from the server.
+	 * If the objects are added (id=0), the modified is ignored and the object is
+	 * added to the server. 
 	 */
 	public boolean modified = false;
+
+	/**
+	 * <code>true</code>, if the object's keys has been changed by JOSM since
+	 * last update.
+	 */
+	public boolean modifiedProperties = false;
 	
+	/**
+	 * <code>true</code>, if the object has been deleted.
+	 */
+	private boolean deleted = false;
+
 	/**
 	 * If set to true, this object is currently selected.
@@ -89,16 +102,22 @@
 
 
+	public void setDeleted(boolean deleted) {
+		this.deleted = deleted;
+		setSelected(false);
+	}
+
+	public boolean isDeleted() {
+		return deleted;
+	}
+
 	/**
-	 * Equal, if the id is equal. If both ids are 0, use the super classes equal
-	 * instead.
+	 * Equal, if the id (and class) is equal. If both ids are 0, use the super classes
+	 * equal instead.
 	 */
 	@Override
 	public boolean equals(Object obj) {
-		if (!(obj instanceof OsmPrimitive))
-			return false;
-		OsmPrimitive osm = (OsmPrimitive)obj;
-		if (id == 0 && osm.id == 0)
+		if (getClass() != obj.getClass() || id == 0 || obj == null || ((OsmPrimitive)obj).id == 0)
 			return super.equals(obj);
-		return id == osm.id;
+		return id == ((OsmPrimitive)obj).id;
 	}
 
Index: /src/org/openstreetmap/josm/data/osm/visitor/AddVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/AddVisitor.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/osm/visitor/AddVisitor.java	(revision 35)
@@ -26,13 +26,13 @@
 	public void visit(Node n) {
 		ds.nodes.add(n);
-		ds.deleted.remove(n); // remove if there.
+		n.setDeleted(false);
 	}
 	public void visit(LineSegment ls) {
 		ds.lineSegments.add(ls);
-		ds.deleted.remove(ls); // remove if there.
+		ls.setDeleted(false);
 	}
 	public void visit(Track t) {
 		ds.tracks.add(t);
-		ds.deleted.remove(t); // remove if there.
+		t.setDeleted(false);
 	}
 	public void visit(Key k) {}
Index: /src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java	(revision 35)
@@ -21,8 +21,8 @@
 	 * Calculate regarding lat/lon or x/y?
 	 */
-	public static enum Type {LATLON, XY};
+	public static enum Type {LATLON, XY}
 	private Type type;
-	
-	
+
+
 	public BoundingVisitor(Type type) {
 		this.type = type;
Index: c/org/openstreetmap/josm/data/osm/visitor/DeleteVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/DeleteVisitor.java	(revision 34)
+++ 	(revision )
@@ -1,39 +1,0 @@
-/**
- */
-package org.openstreetmap.josm.data.osm.visitor;
-
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.Key;
-import org.openstreetmap.josm.data.osm.LineSegment;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.Track;
-
-/**
- * Visitor, that removes the visited object from the dataset given at constructor.
- * 
- * Is not capable of removing keys.
- * 
- * @author imi
- */
-public class DeleteVisitor implements Visitor {
-	
-	private final DataSet ds;
-	
-	public DeleteVisitor(DataSet ds) {
-		this.ds = ds;
-	}
-	
-	public void visit(Node n) {
-		if (ds.nodes.remove(n))
-			ds.deleted.add(n);
-	}
-	public void visit(LineSegment ls) {
-		if (ds.lineSegments.remove(ls))
-			ds.deleted.add(ls);
-	}
-	public void visit(Track t) {
-		if (ds.tracks.remove(t))
-			ds.deleted.add(t);
-	}
-	public void visit(Key k) {}
-}
Index: /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 35)
+++ /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 35)
@@ -0,0 +1,173 @@
+package org.openstreetmap.josm.data.osm.visitor;
+
+import java.util.Iterator;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Key;
+import org.openstreetmap.josm.data.osm.LineSegment;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Track;
+
+/**
+ * A visitor that get a data set at construction time and merge every visited object
+ * into it.
+ * 
+ * @author imi
+ */
+public class MergeVisitor implements Visitor {
+
+	private final DataSet ds;
+	
+	public MergeVisitor(DataSet ds) {
+		this.ds = ds;
+	}
+
+	/**
+	 * Merge the node if the id matches with any of the internal set or if
+	 * either id is zero, merge if lat/lon matches.
+	 */
+	public void visit(Node otherNode) {
+		Node myNode = null;
+		for (Node n : ds.nodes) {
+			if (match(n, otherNode)) {
+				myNode = n;
+				break;
+			}
+		}
+		if (myNode == null)
+			ds.nodes.add(otherNode);
+		else {
+			mergeCommon(myNode, otherNode);
+			if (myNode.modified && !otherNode.modified)
+				return;
+			if (!myNode.coor.equalsLatLon(otherNode.coor)) {
+				myNode.coor = otherNode.coor;
+				myNode.modified = otherNode.modified;
+			}
+		}
+	}
+
+	/**
+	 * Merge the line segment if id matches or if both nodes are the same (and the
+	 * id is zero of either segment). Nodes are equal when they @see match
+	 */
+	public void visit(LineSegment otherLs) {
+		LineSegment myLs = null;
+		for (LineSegment ls : ds.lineSegments) {
+			if (match(otherLs, ls)) {
+				myLs = ls;
+				break;
+			}
+		}
+		if (myLs == null)
+			ds.lineSegments.add(otherLs);
+		else {
+			mergeCommon(myLs, otherLs);
+			if (myLs.modified && !otherLs.modified)
+				return;
+			if (!match(myLs.start, otherLs.start)) {
+				myLs.start = otherLs.start;
+				myLs.modified = otherLs.modified;
+			}
+			if (!match(myLs.end, otherLs.end)) {
+				myLs.end = otherLs.end;
+				myLs.modified = otherLs.modified;
+			}
+		}
+	}
+
+	/**
+	 * Merge the track if id matches or if all line segments matches and the
+	 * id is zero of either track.
+	 */
+	public void visit(Track otherTrack) {
+		Track myTrack = null;
+		for (Track t : ds.tracks) {
+			if (match(otherTrack, t)) {
+				myTrack = t;
+				break;
+			}
+		}
+		if (myTrack == null)
+			ds.tracks.add(otherTrack);
+		else {
+			mergeCommon(myTrack, otherTrack);
+			if (myTrack.modified && !otherTrack.modified)
+				return;
+			boolean same = true;
+			Iterator<LineSegment> it = otherTrack.segments.iterator();
+			for (LineSegment ls : myTrack.segments) {
+				if (!match(ls, it.next())) {
+					same = false;
+				}
+			}
+			if (!same) {
+				myTrack.segments.clear();
+				myTrack.segments.addAll(otherTrack.segments);
+				myTrack.modified = otherTrack.modified;
+			}
+		}
+	}
+
+	public void visit(Key k) {
+		//TODO: Key doesn't really fit the OsmPrimitive concept!
+	}
+	
+	/**
+	 * @return Whether the nodes matches (in sense of "be mergable").
+	 */
+	private boolean match(Node n1, Node n2) {
+		if (n1.id == 0 || n2.id == 0)
+			return n1.coor.equalsLatLon(n2.coor);
+		return n1.id == n2.id;
+	}
+	
+	/**
+	 * @return Whether the line segments matches (in sense of "be mergable").
+	 */
+	private boolean match(LineSegment ls1, LineSegment ls2) {
+		if (ls1.id == 0 || ls2.id == 0)
+			return match(ls1.start, ls2.start) && match(ls1.end, ls2.end);
+		return ls1.id == ls2.id;
+	}
+
+	/**
+	 * @return Whether the tracks matches (in sense of "be mergable").
+	 */
+	private boolean match(Track t1, Track t2) {
+		if (t1.id == 0 || t2.id == 0) {
+			Iterator<LineSegment> it = t1.segments.iterator();
+			for (LineSegment ls : t2.segments)
+				if (!match(ls, it.next()))
+					return false;
+			return true;
+		}
+		return t1.id == t2.id;
+	}
+
+	/**
+	 * Merge the common parts of an osm primitive.
+	 * @param myOsm The object, the information gets merged into
+	 * @param otherOsm The object, the information gets merged from
+	 */
+	private void mergeCommon(OsmPrimitive myOsm, OsmPrimitive otherOsm) {
+		if (otherOsm.modified)
+			myOsm.modified = true;
+		if (otherOsm.isDeleted())
+			myOsm.setDeleted(true);
+		if (!myOsm.modified || otherOsm.modified) {
+			if (otherOsm.id != 0 && myOsm.id == 0)
+				myOsm.id = otherOsm.id; // means not ncessary the object is now modified
+		}
+		if (myOsm.modifiedProperties && !otherOsm.modifiedProperties)
+			return;
+		if (myOsm.keys != null && !myOsm.keys.equals(otherOsm.keys)) {
+			if (myOsm.keys == null)
+				myOsm.keys = otherOsm.keys;
+			else
+				myOsm.keys.putAll(otherOsm.keys);
+			myOsm.modifiedProperties = true;
+		}
+	}
+}
Index: /src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 35)
@@ -30,8 +30,4 @@
 	 */
 	private final MapView mv;
-	/**
-	 * Can be set to non-<code>null</code> and then replace every other color.
-	 */
-	private final Color forceColor;
 	
 	/**
@@ -39,10 +35,8 @@
 	 * @param g   The graphics to draw to.
 	 * @param mv  The view to get screen coordinates from.
-	 * @param forceColor If non-<code>null</code>, always draw with this color.
 	 */
-	public SimplePaintVisitor(Graphics g, MapView mv, Color forceColor) {
+	public SimplePaintVisitor(Graphics g, MapView mv) {
 		this.g = g;
 		this.mv = mv;
-		this.forceColor = forceColor;
 	}
 	
@@ -70,6 +64,8 @@
 	 */
 	public void visit(Track t) {
+		// only to overwrite with blue
 		for (LineSegment ls : t.segments)
-			drawLineSegment(ls, darkblue);
+			if (!ls.isSelected()) // selected already in good color
+				drawLineSegment(ls, t.isSelected() ? Color.WHITE : darkblue);
 	}
 
@@ -88,5 +84,5 @@
 	private void drawNode(Node n, Color color) {
 		Point p = mv.getScreenPoint(n.coor);
-		g.setColor(forceColor != null ? forceColor : color);
+		g.setColor(color);
 		g.drawRect(p.x-1, p.y-1, 2, 2);
 	}
@@ -96,7 +92,5 @@
 	 */
 	private void drawLineSegment(LineSegment ls, Color col) {
-		if (forceColor != null)
-			col = forceColor;
-		else if (ls.isSelected())
+		if (ls.isSelected())
 			col = Color.WHITE;
 		g.setColor(col);
Index: /src/org/openstreetmap/josm/data/projection/UTM.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/UTM.java	(revision 34)
+++ /src/org/openstreetmap/josm/data/projection/UTM.java	(revision 35)
@@ -39,4 +39,6 @@
 	public final static double RAD_TO_DEG = 180 / Math.PI;
 
+	public final static double k0 = 0.9996012717;
+	
 	/**
 	 * A reference ellipsoid used in Projections
@@ -116,6 +118,4 @@
 		// Written by Chuck Gantz- chuck.gantz@globalstar.com
 		// ported to Ruby by Ben Gimpert- ben@somethingmodern.com
-		double k0 = 0.9996012717;
-		
 		double lat_rad = p.lat * DEG_TO_RAD;
 		double long_temp = (p.lon + 180) - (Math.floor((p.lon + 180) / 360) * 360) - 180;
@@ -150,5 +150,4 @@
 		// Written by Chuck Gantz- chuck.gantz@globalstar.com
 		// ported to Ruby by Ben Gimpert- ben@somethingmodern.com
-		double k0 = 0.9996;
 		double e1 = (1-Math.sqrt(1-ellipsoid.ecc_squared))/(1+Math.sqrt(1-ellipsoid.ecc_squared));
 		double x = p.x - 500000.0;
Index: /src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapView.java	(revision 34)
+++ /src/org/openstreetmap/josm/gui/MapView.java	(revision 35)
@@ -253,5 +253,27 @@
 			return minPrimitive;
 		
-		// pending line segments
+		// for whole tracks, try the tracks first
+		minDistanceSq = Double.MAX_VALUE;
+		if (wholeTrack) {
+			for (Track t : Main.main.ds.tracks) {
+				for (LineSegment ls : t.segments) {
+					Point A = getScreenPoint(ls.start.coor);
+					Point B = getScreenPoint(ls.end.coor);
+					double c = A.distanceSq(B);
+					double a = p.distanceSq(B);
+					double b = p.distanceSq(A);
+					double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
+					if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
+						minDistanceSq = perDist;
+						minPrimitive = t;
+					}
+				}			
+			}
+			if (minPrimitive != null)
+				return minPrimitive;
+		}
+		
+		minDistanceSq = Double.MAX_VALUE;
+		// line segments
 		for (LineSegment ls : Main.main.ds.lineSegments) {
 			Point A = getScreenPoint(ls.start.coor);
@@ -267,26 +289,5 @@
 		}
 
-		// tracks & line segments
-		minDistanceSq = Double.MAX_VALUE;
-		for (Track t : Main.main.ds.tracks) {
-			for (LineSegment ls : t.segments) {
-				Point A = getScreenPoint(ls.start.coor);
-				Point B = getScreenPoint(ls.end.coor);
-				double c = A.distanceSq(B);
-				double a = p.distanceSq(B);
-				double b = p.distanceSq(A);
-				double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
-				if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
-					minDistanceSq = perDist;
-					minPrimitive = wholeTrack ? t : ls;
-				}
-			}			
-		}
-		if (minPrimitive != null)
-			return minPrimitive;
-		
-		// TODO areas
-		
-		return null; // nothing found
+		return minPrimitive;
 	}
 
Index: /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 34)
+++ /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 35)
@@ -2,4 +2,5 @@
 
 import java.awt.Graphics;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Stack;
@@ -13,6 +14,8 @@
 import org.openstreetmap.josm.data.osm.LineSegment;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Track;
 import org.openstreetmap.josm.data.osm.visitor.BoundingVisitor;
+import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
 import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
 import org.openstreetmap.josm.data.projection.Projection;
@@ -70,12 +73,14 @@
 	@Override
 	public void paint(Graphics g, MapView mv) {
-		SimplePaintVisitor visitor = new SimplePaintVisitor(g, mv, null);
-
-		for (LineSegment ls : data.lineSegments)
-			visitor.visit(ls);
-		for (Track t : data.tracks)
-			visitor.visit(t);
-		for (Node n : data.nodes)
-			visitor.visit(n);
+		SimplePaintVisitor visitor = new SimplePaintVisitor(g, mv);
+		for (OsmPrimitive osm : data.lineSegments)
+			if (!osm.isDeleted())
+				osm.visit(visitor);
+		for (OsmPrimitive osm : data.tracks)
+			if (!osm.isDeleted())
+				osm.visit(visitor);
+		for (OsmPrimitive osm : data.nodes)
+			if (!osm.isDeleted())
+				osm.visit(visitor);
 	}
 
@@ -87,5 +92,7 @@
 	@Override
 	public void mergeFrom(Layer from) {
-		data.mergeFrom(((OsmDataLayer)from).data);
+		MergeVisitor visitor = new MergeVisitor(data);
+		for (OsmPrimitive osm : ((OsmDataLayer)from).data.allPrimitives())
+			osm.visit(visitor);
 	}
 
@@ -163,3 +170,27 @@
 		Main.main.redoAction.setEnabled(!redoCommands.isEmpty());
 	}
+
+	/**
+	 * Clean out the data behind the layer. This means clearing the redo/undo lists,
+	 * really deleting all deleted objects and reset the modified flags. This is done
+	 * after a successfull upload.
+	 */
+	public void cleanData() {
+		redoCommands.clear();
+		commands.clear();
+		for (Iterator<Node> it = data.nodes.iterator(); it.hasNext();)
+			cleanIterator(it);
+		for (Iterator<LineSegment> it = data.lineSegments.iterator(); it.hasNext();)
+			cleanIterator(it);
+		for (Iterator<Track> it = data.tracks.iterator(); it.hasNext();)
+			cleanIterator(it);
+	}
+
+	private void cleanIterator(Iterator<? extends OsmPrimitive> it) {
+		OsmPrimitive osm = it.next();
+		osm.modified = false;
+		osm.modifiedProperties = false;
+		if (osm.isDeleted())
+			it.remove();
+	}
 }
Index: /src/org/openstreetmap/josm/io/GpxReader.java
===================================================================
--- /src/org/openstreetmap/josm/io/GpxReader.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/GpxReader.java	(revision 35)
@@ -190,4 +190,5 @@
 				osm.id = Long.parseLong(idElement.getText());
 			osm.modified = e.getChild("modified", JOSM) != null;
+			osm.modifiedProperties = e.getChild("modifiedProperties", JOSM) != null;
 		}
 	}
Index: /src/org/openstreetmap/josm/io/GpxWriter.java
===================================================================
--- /src/org/openstreetmap/josm/io/GpxWriter.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/GpxWriter.java	(revision 35)
@@ -242,5 +242,5 @@
 	@SuppressWarnings("unchecked")
 	private void addPropertyExtensions(Element e, Map<Key, String> keys, OsmPrimitive osm) {
-		if ((keys == null || keys.isEmpty()) && osm.id == 0 && !osm.modified)
+		if ((keys == null || keys.isEmpty()) && osm.id == 0 && !osm.modified && !osm.modifiedProperties)
 			return;
 		Element extensions = e.getChild("extensions", GPX);
@@ -255,5 +255,4 @@
 			}
 		}
-		// id
 		if (osm.id != 0) {
 			Element propElement = new Element("uid", JOSM);
@@ -261,9 +260,12 @@
 			extensions.getChildren().add(propElement);
 		}
-		// modified
 		if (osm.modified) {
 			Element modElement = new Element("modified", JOSM);
 			extensions.getChildren().add(modElement);
 		}
+		if (osm.modifiedProperties) {
+			Element modElement = new Element("modifiedProperties", JOSM);
+			extensions.getChildren().add(modElement);
+		}
 	}
 }
Index: /src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmReader.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/OsmReader.java	(revision 35)
@@ -104,8 +104,13 @@
 		for (Object o : e.getChildren()) {
 			Element child = (Element)o;
-			if (child.getName().equals("deleted"))
-				for (Object delObj : child.getChildren())
-					data.deleted.add(parseObject((Element)delObj, data));
-			else {
+			if (child.getName().equals("deleted")) {
+				for (Object delObj : child.getChildren()) {
+					OsmPrimitive osm = parseObject((Element)delObj, data);
+					if (osm != null) {
+						osm.visit(visitor);
+						osm.setDeleted(true);
+					}
+				}
+			} else {
 				OsmPrimitive osm = parseObject(child, data);
 				if (osm != null)
@@ -200,5 +205,5 @@
 		OsmPrimitive osm = findObject(data, id);
 		Key key = Key.get(e.getAttributeValue("key"));
-		String value =e.getAttributeValue("value");
+		String value = e.getAttributeValue("value");
 		if (value != null) {
 			if (osm.keys == null)
@@ -221,7 +226,4 @@
 			if (osm.id == id)
 				return osm;
-		for (OsmPrimitive osm : data.deleted)
-			if (osm.id == id)
-				return osm;
 		throw new JDOMException("Unknown object reference: "+id);
 	}
Index: /src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 35)
@@ -93,5 +93,4 @@
 	private Reader getReader(String urlStr) throws IOException {
 		initAuthentication();
-		System.out.println(urlStr);
 		URL url = new URL(urlStr);
 		HttpURLConnection con = (HttpURLConnection)url.openConnection();
Index: /src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 35)
@@ -27,12 +27,10 @@
  * Class that uploades all changes to the osm server.
  * 
- * This is done like this:
- * - All objects with id = 0 are uploaded as new, except those in deleted, 
- *   which are ignored
- * - All objects in deleted list are deleted.
- * - All remaining objects with modified flag set are updated.
+ * This is done like this: - All objects with id = 0 are uploaded as new, except
+ * those in deleted, which are ignored - All objects in deleted list are
+ * deleted. - All remaining objects with modified flag set are updated.
  * 
- * This class implements visitor and will perform the correct upload action
- * on the visited element. 
+ * This class implements visitor and will perform the correct upload action on
+ * the visited element.
  * 
  * @author imi
@@ -41,6 +39,6 @@
 
 	/**
-	 * Send the dataset to the server. Ask the user first and does nothing if
-	 * he does not want to send the data.
+	 * Send the dataset to the server. Ask the user first and does nothing if he
+	 * does not want to send the data.
 	 */
 	public void uploadOsm(Collection<OsmPrimitive> list) throws JDOMException {
@@ -48,6 +46,6 @@
 
 		try {
-//			for (OsmPrimitive osm : list)
-//				osm.visit(this);
+			for (OsmPrimitive osm : list)
+				osm.visit(this);
 		} catch (RuntimeException e) {
 			throw new JDOMException("An error occoured: ", e);
@@ -60,20 +58,29 @@
 	@SuppressWarnings("unchecked")
 	public void visit(Node n) {
-		if (n.id == 0) {
-			sendRequest("PUT", "newnode", n);
-		} else if (Main.main.ds.deleted.contains(n)) {
-			sendRequest("DELETE", "node/"+n.id, n);
+		if (n.id == 0 && !n.isDeleted()) {
+			sendRequest("PUT", "newnode", n, true);
+		} else if (n.isDeleted()) {
+			sendRequest("DELETE", "node/" + n.id, n, false);
 		} else {
-			sendRequest("PUT", "node/"+n.id, n);
+			sendRequest("PUT", "node/" + n.id, n, true);
 		}
 	}
 
 	public void visit(LineSegment ls) {
+		if (ls.id == 0 && !ls.isDeleted()) {
+			sendRequest("PUT", "newsegment", ls, true);
+		} else if (ls.isDeleted()) {
+			sendRequest("DELETE", "segment/" + ls.id, ls, false);
+		} else {
+			sendRequest("PUT", "segment/" + ls.id, ls, true);
+		}
 	}
 
 	public void visit(Track t) {
+		// not implemented in server
 	}
 
 	public void visit(Key k) {
+		// not implemented in server
 	}
 
@@ -82,5 +89,6 @@
 	 */
 	private long readId(InputStream inputStream) throws IOException {
-		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
+		BufferedReader in = new BufferedReader(new InputStreamReader(
+				inputStream));
 		String s = in.readLine();
 		if (s == null)
@@ -92,29 +100,32 @@
 		}
 	}
-	
+
 	@SuppressWarnings("unchecked")
-	private void sendRequest(String requestMethod, String urlSuffix, OsmPrimitive osm) {
+	private void sendRequest(String requestMethod, String urlSuffix,
+			OsmPrimitive osm, boolean addBody) {
 		try {
 			URL url = new URL(Main.pref.osmDataServer + "/" + urlSuffix);
-			HttpURLConnection con = (HttpURLConnection)url.openConnection();
+			HttpURLConnection con = (HttpURLConnection) url.openConnection();
 			con.setConnectTimeout(20000);
 			con.setRequestMethod(requestMethod);
-			con.setDoOutput(true);
+			if (addBody)
+				con.setDoOutput(true);
 			con.connect();
 
-			OsmXmlVisitor visitor = new OsmXmlVisitor(false);
-			osm.visit(visitor);
-			Element root = new Element("osm");
-			root.setAttribute("version", "0.2");
-			root.getChildren().add(visitor.element);
-			XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat());
-			OutputStream out = con.getOutputStream();
-			Document doc = new Document(root);
-			xmlOut.output(doc, out);
-			xmlOut.output(doc, System.out);
-			out.close();
-			
+			if (addBody) {
+				OsmXmlVisitor visitor = new OsmXmlVisitor(false);
+				osm.visit(visitor);
+				Element root = new Element("osm");
+				root.setAttribute("version", "0.2");
+				root.getChildren().add(visitor.element);
+				XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat());
+				OutputStream out = con.getOutputStream();
+				Document doc = new Document(root);
+				xmlOut.output(doc, out);
+				xmlOut.output(doc, System.out);
+				out.close();
+			}
+
 			int retCode = con.getResponseCode();
-			System.out.println(retCode+" "+con.getResponseMessage());
 			if (retCode == 200 && osm.id == 0)
 				osm.id = readId(con.getInputStream());
Index: /src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmWriter.java	(revision 34)
+++ /src/org/openstreetmap/josm/io/OsmWriter.java	(revision 35)
@@ -63,15 +63,9 @@
 		List<Element> list = root.getChildren();
 		properties = new LinkedList<Element>();
-		for (Node n : ds.nodes) {
-			visit(n);
-			list.add(element);
-		}
-		for (LineSegment ls : ds.lineSegments) {
-			visit(ls);
-			list.add(element);
-		}
-		for (Track t : ds.tracks) {
-			visit(t);
-			list.add(element);
+		for (OsmPrimitive osm : ds.allPrimitives()) {
+			if (!osm.isDeleted()) {
+				osm.visit(this);
+				list.add(element);
+			}
 		}
 		list.addAll(properties);
@@ -79,7 +73,9 @@
 		Element deleted = new Element("deleted");
 		Collection<Element> allDeleted = deleted.getChildren();
-		for (OsmPrimitive osm : ds.deleted) {
-			osm.visit(this);
-			allDeleted.add(element);
+		for (OsmPrimitive osm : ds.allPrimitives()) {
+			if (osm.isDeleted()) {
+				osm.visit(this);
+				allDeleted.add(element);
+			}
 		}
 		allDeleted.addAll(properties);
