Index: src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 65)
+++ src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 66)
@@ -207,5 +207,5 @@
 				}
 				b.name = JOptionPane.showInputDialog(Main.main, "Please enter a name for the location.");
-				if (!b.name.equals("")) {
+				if (b.name != null && !b.name.equals("")) {
 					((DefaultListModel)bookmarks.getModel()).addElement(b);
 					bookmarks.save();
@@ -245,5 +245,5 @@
 
 	/**
-	 * Read the values from the edit fields and start the download.
+	 * Read the values from the edit fields and from the download.
 	 */
 	private DownloadStatus startDownload() {
Index: src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 65)
+++ src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java	(revision 66)
@@ -72,5 +72,5 @@
 
 	/**
-	 * If user clicked on a node, start the dragging with that node. 
+	 * If user clicked on a node, from the dragging with that node. 
 	 */
 	@Override
@@ -138,5 +138,5 @@
 			// try to find a line segment
 			for (LineSegment ls : Main.main.ds.lineSegments)
-				if ((start == ls.start && end == ls.end) || (end == ls.start && start == ls.end))
+				if ((start == ls.from && end == ls.to) || (end == ls.from && start == ls.to))
 					return; // already a line segment here - be happy, do nothing.
 
Index: src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 65)
+++ src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 66)
@@ -50,6 +50,5 @@
 	public void mouseClicked(MouseEvent e) {
 		if (e.getButton() == MouseEvent.BUTTON1) {
-			Node node = new Node();
-			node.coor = mv.getPoint(e.getX(), e.getY(), true);
+			Node node = new Node(mv.getPoint(e.getX(), e.getY(), true));
 			if (node.coor.isOutSideWorld()) {
 				JOptionPane.showMessageDialog(Main.main, "Can not add a node outside of the world.");
Index: src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java	(revision 65)
+++ src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java	(revision 66)
@@ -88,5 +88,5 @@
 		// 0  if no elements in list, quit
 		// 1  taking the first ls as pivot, remove it from list
-		// 2  searching for a connection at start or end of pivot
+		// 2  searching for a connection at from or to of pivot
 		// 3  if found, attach it, remove it from list, goto 2
 		// 4  if not found, save the pivot-string and goto 0
@@ -100,9 +100,11 @@
 				for (Iterator<LineSegment> it = lineSegments.iterator(); it.hasNext();) {
 					LineSegment ls = it.next();
-					if (ls.start == pivotList.getLast().end) {
+					if (ls.incomplete)
+						continue; // incomplete segments are never added to a new way
+					if (ls.from == pivotList.getLast().to) {
 						pivotList.addLast(ls);
 						it.remove();
 						found = true;
-					} else if (ls.end == pivotList.getFirst().start) {
+					} else if (ls.to == pivotList.getFirst().from) {
 						pivotList.addFirst(ls);
 						it.remove();
@@ -115,6 +117,5 @@
 		
 		Way t = new Way();
-		for (LineSegment ls : sortedLineSegments)
-			t.segments.add(ls);
+		t.segments.addAll(sortedLineSegments);
 		mv.editLayer().add(new AddCommand(Main.main.ds, t));
 		Main.main.ds.clearSelection();
Index: src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java
===================================================================
--- src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java	(revision 65)
+++ src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java	(revision 66)
@@ -59,17 +59,9 @@
 
 		if (value == null) {
-			for (OsmPrimitive osm : objects) {
-				if (osm.keys != null) {
-					osm.keys.remove(key);
-					if (osm.keys.isEmpty())
-						osm.keys = null;
-				}
-			}
+			for (OsmPrimitive osm : objects)
+				osm.remove(key);
 		} else {
-			for (OsmPrimitive osm : objects) {
-				if (osm.keys == null)
-					osm.keys = new HashMap<String, String>();
-				osm.keys.put(key, value);
-			}
+			for (OsmPrimitive osm : objects)
+				osm.put(key, value);
 		}
 	}
Index: src/org/openstreetmap/josm/data/osm/LineSegment.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/LineSegment.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/LineSegment.java	(revision 66)
@@ -6,5 +6,5 @@
 
 /**
- * One way line segment consisting of a pair of nodes (start/end) 
+ * One way line segment consisting of a pair of nodes (from/to) 
  *
  * @author imi
@@ -15,19 +15,31 @@
 	 * The starting node of the line segment
 	 */
-	public Node start;
+	public Node from;
 	
 	/**
 	 * The ending node of the line segment
 	 */
-	public Node end;
+	public Node to;
+
+	/**
+	 * If set to true, this object is incomplete, which means only the id
+	 * and type is known (type is the objects instance class)
+	 */
+	public boolean incomplete;
 
 	/**
 	 * Create an line segment from the given starting and ending node
-	 * @param start	Starting node of the line segment.
-	 * @param end	Ending node of the line segment.
+	 * @param from	Starting node of the line segment.
+	 * @param to	Ending node of the line segment.
 	 */
-	public LineSegment(Node start, Node end) {
-		this.start = start;
-		this.end = end;
+	public LineSegment(Node from, Node to) {
+		this.from = from;
+		this.to = to;
+		incomplete = false;
+	}
+
+	public LineSegment(long id) {
+		this.id = id;
+		incomplete = true;
 	}
 
@@ -44,10 +56,29 @@
 		if (equals(ls))
 			return true;
-		GeoPoint s1 = start.coor;
-		GeoPoint s2 = ls.start.coor;
-		GeoPoint e1 = end.coor;
-		GeoPoint e2 = ls.end.coor;
+		if (incomplete || ls.incomplete)
+			return false;
+		GeoPoint s1 = from.coor;
+		GeoPoint s2 = ls.from.coor;
+		GeoPoint e1 = to.coor;
+		GeoPoint e2 = ls.to.coor;
 		return ((s1.equalsLatLon(s2) && e1.equalsLatLon(e2)) ||
 				(s1.equalsLatLon(e2) && e1.equalsLatLon(s2)));
 	}
+
+	@Override
+	public String toString() {
+		String s = "{LineSegment id="+id;
+		if (incomplete)
+			return s+",incomplete}";
+		return s+",from="+from+",to="+to+"}";
+	}
+
+	@Override
+	public void cloneFrom(OsmPrimitive osm) {
+		super.cloneFrom(osm);
+		LineSegment ls = ((LineSegment)osm);
+		from = ls.from;
+		to = ls.to;
+		incomplete = ls.incomplete;
+	}
 }	
Index: src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Node.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/Node.java	(revision 66)
@@ -17,7 +17,23 @@
 	public GeoPoint coor;
 
+	public Node(GeoPoint coor) {
+		this.coor = coor;
+	}
+
 	@Override
 	public void visit(Visitor visitor) {
 		visitor.visit(this);
 	}
+	
+	@Override
+	public String toString() {
+		return "{Node id="+id+",lat="+coor.lat+",lon="+coor.lon+"}";
+	}
+
+	@Override
+	public void cloneFrom(OsmPrimitive osm) {
+		super.cloneFrom(osm);
+		GeoPoint g = ((Node)osm).coor;
+		coor = new GeoPoint(g.lat, g.lon, g.x, g.y); //TODO: Make GeoPoint immutable!
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 66)
@@ -1,6 +1,9 @@
 package org.openstreetmap.josm.data.osm;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.openstreetmap.josm.Main;
@@ -64,5 +67,5 @@
 	 */
 	abstract public void visit(Visitor visitor);
-	
+
 	/**
 	 * Return <code>true</code>, if either <code>this.keys</code> and 
@@ -119,4 +122,6 @@
 	 * Equal, if the id (and class) is equal. If both ids are 0, use the super classes
 	 * equal instead.
+	 * 
+	 * An primitive is equal to its incomplete counter part.
 	 */
 	@Override
@@ -129,4 +134,6 @@
 	/**
 	 * Return the id as hashcode or supers hashcode if 0.
+	 * 
+	 * An primitive has the same hashcode as its incomplete counter part.
 	 */
 	@Override
@@ -145,7 +152,42 @@
 		keys.put(key, value);
 	}
+	/**
+	 * Remove the given key from the list.
+	 */
+	public void remove(String key) {
+		if (keys != null) {
+			keys.remove(key);
+			if (keys.isEmpty())
+				keys = null;
+		}
+	}
+
+	public String get(String key) {
+		return keys == null ? null : keys.get(key);
+	}
 	
-	public String get(String key) {
-		return (keys == null) ? null : keys.get(key);
+	public Collection<Entry<String, String>> entrySet() {
+		if (keys == null)
+			return Collections.emptyList();
+		return keys.entrySet();
+	}
+
+	public Collection<String> keySet() {
+		if (keys == null)
+			return Collections.emptyList();
+		return keys.keySet();
+	}
+
+	/**
+	 * Get and write all attributes from the parameter. Does not fire any listener, so
+	 * use this only in the data initializing phase
+	 */
+	public void cloneFrom(OsmPrimitive osm) {
+		keys = osm.keys;
+		id = osm.id;
+		modified = osm.modified;
+		modifiedProperties = osm.modifiedProperties;
+		deleted = osm.deleted;
+		selected = osm.selected;
 	}
 }
Index: src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/Way.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/Way.java	(revision 66)
@@ -18,58 +18,14 @@
 	public final List<LineSegment> segments = new ArrayList<LineSegment>();
 
-	
-	/**
-	 * Return the last node in the way. This is the node, which no line segment
-	 * has as start, but at least one has it as end. If there are not exact one
-	 * such nodes found, <code>null</code> is returned.
-	 *
-	 * TODO Currently does return just the end node in the list.
-	 *
-	 * @return The ending node, if there is one.
-	 */
-	public Node getEndingNode() {
-		if (segments.isEmpty())
-			return null;
-		return segments.get(segments.size()-1).end;
-	}
-	
-	/**
-	 * Return the last segment.
-	 * @see #getEndingNode()
-	 */
-	public LineSegment getEndingSegment() {
-		if (segments.isEmpty())
-			return null;
-		return segments.get(segments.size()-1);
-	}
-
-	/**
-	 * Return the first node in the way. This is the node, which no line segment
-	 * has as end, but at least one as starting node. If there are not exact one
-	 * such nodes found, <code>null</code> is returned.
-	 * 
-	 * TODO Currently does return just the first node in the list.
-	 * 
-	 * @return The starting node, if there is one.
-	 */
-	public Node getStartingNode() {
-		if (segments.isEmpty())
-			return null;
-		return segments.get(0).start;
-	}
-	
-	/**
-	 * Return the first segment.
-	 * @see #getStartingNode()
-	 */
-	public LineSegment getStartingSegment() {
-		if (segments.isEmpty())
-			return null;
-		return segments.get(0);
-	}
-
 	@Override
 	public void visit(Visitor visitor) {
 		visitor.visit(this);
 	}
+
+	@Override
+	public void cloneFrom(OsmPrimitive osm) {
+		super.cloneFrom(osm);
+		segments.clear();
+		segments.addAll(((Way)osm).segments);
+	}
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java	(revision 66)
@@ -29,9 +29,11 @@
 
 	/**
-	 * Line segments have exactly two nodes: start and end.
+	 * Line segments have exactly two nodes: from and to.
 	 */
 	public void visit(LineSegment ls) {
-		nodes.add(ls.start);
-		nodes.add(ls.end);
+		if (!ls.incomplete) {
+			visit(ls.from);
+			visit(ls.to);
+		}
 	}
 
@@ -40,8 +42,6 @@
 	 */
 	public void visit(Way t) {
-		for (LineSegment ls : t.segments) {
-			nodes.add(ls.start);
-			nodes.add(ls.end);
-		}
+		for (LineSegment ls : t.segments)
+			visit(ls);
 	}
 
Index: src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/BoundingVisitor.java	(revision 66)
@@ -48,6 +48,8 @@
 
 	public void visit(LineSegment ls) {
-		visit(ls.start);
-		visit(ls.end);
+		if (!ls.incomplete) {
+			visit(ls.from);
+			visit(ls.to);
+		}
 	}
 
Index: src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 66)
@@ -41,5 +41,7 @@
 				continue;
 			for (LineSegment ls : t.segments) {
-				if (ls.start == n || ls.end == n) {
+				if (ls.incomplete)
+					continue;
+				if (ls.from == n || ls.to == n) {
 					data.add(t);
 					break;
@@ -48,7 +50,7 @@
 		}
 		for (LineSegment ls : ds.lineSegments) {
-			if (ls.isDeleted())
+			if (ls.isDeleted() || ls.incomplete)
 				continue;
-			if (ls.start == n || ls.end == n)
+			if (ls.from == n || ls.to == n)
 				data.add(ls);
 		}
Index: src/org/openstreetmap/josm/data/osm/visitor/CsvVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/CsvVisitor.java	(revision 65)
+++ 	(revision )
@@ -1,74 +1,0 @@
-package org.openstreetmap.josm.data.osm.visitor;
-
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.Map.Entry;
-
-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.Way;
-
-/**
- * Outputs the visited primitive as comma seperated value.
- * @author imi
- */
-public class CsvVisitor implements Visitor {
-
-	private final PrintWriter out;
-
-	/**
-	 * Construct the visitor.
-	 * @param out The stream, where the output should go to. 
-	 */
-	public CsvVisitor(Writer out) {
-		this.out = new PrintWriter(out);
-	}
-	
-	public void visit(Node n) {
-		out.print("n,"+common(n)+","+n.coor.lat+","+n.coor.lon+","+n.coor.x+","+n.coor.y);
-	}
-
-	public void visit(LineSegment ls) {
-		out.print("ls,"+common(ls)+",");
-		visit(ls.start);
-		out.print(',');
-		visit(ls.end);
-	}
-
-	public void visit(Way t) {
-		out.print("t,"+common(t)+","+t.segments.size());
-		for (LineSegment ls : t.segments) {
-			out.print(',');
-			visit(ls);
-		}
-	}
-
-	/**
-	 * Create a string for all common fields in the primitive
-	 * @param osm The primitive
-	 * @return A string containing the fields as csv.
-	 */
-	private String common(OsmPrimitive osm) {
-		StringBuilder b = new StringBuilder();
-		b.append(osm.id);
-		if (osm.keys != null) {
-			b.append(","+osm.keys.size());
-			for (Entry<String, String> e : osm.keys.entrySet())
-				b.append(e.getKey()+","+encode(e.getValue()));
-		} else
-			b.append(",0");
-		return b.toString();
-	}
-
-	/**
-	 * Encodes the string to be inserted as csv compatible value.
-	 * @param s The string to be inserted
-	 * @return The encoded string
-	 */
-	private String encode(String s) {
-		s = s.replace(",", "\\,");
-		s = s.replace("\n", "\\\n");
-		return s;
-	}
-}
Index: src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 66)
@@ -79,15 +79,18 @@
 		if (myLs == null)
 			ds.lineSegments.add(otherLs);
-		else {
+		else if (myLs.incomplete && !otherLs.incomplete) {
+			mergedLineSegments.put(otherLs, myLs);
+			myLs.cloneFrom(otherLs);
+		} else if (!otherLs.incomplete) {
 			mergedLineSegments.put(otherLs, myLs);
 			mergeCommon(myLs, otherLs);
 			if (myLs.modified && !otherLs.modified)
 				return;
-			if (!match(myLs.start, otherLs.start)) {
-				myLs.start = otherLs.start;
+			if (!match(myLs.from, otherLs.from)) {
+				myLs.from = otherLs.from;
 				myLs.modified = otherLs.modified;
 			}
-			if (!match(myLs.end, otherLs.end)) {
-				myLs.end = otherLs.end;
+			if (!match(myLs.to, otherLs.to)) {
+				myLs.to = otherLs.to;
 				myLs.modified = otherLs.modified;
 			}
@@ -133,8 +136,8 @@
 	public void fixReferences() {
 		for (LineSegment ls : ds.lineSegments) {
-			if (mergedNodes.containsKey(ls.start))
-				ls.start = mergedNodes.get(ls.start);
-			if (mergedNodes.containsKey(ls.end))
-				ls.end = mergedNodes.get(ls.end);
+			if (mergedNodes.containsKey(ls.from))
+				ls.from = mergedNodes.get(ls.from);
+			if (mergedNodes.containsKey(ls.to))
+				ls.to = mergedNodes.get(ls.to);
 		}
 		for (Way t : ds.waies) {
@@ -152,8 +155,8 @@
 			}
 			for (LineSegment ls : t.segments) {
-				if (mergedNodes.containsKey(ls.start))
-					ls.start = mergedNodes.get(ls.start);
-				if (mergedNodes.containsKey(ls.end))
-					ls.end = mergedNodes.get(ls.end);
+				if (mergedNodes.containsKey(ls.from))
+					ls.from = mergedNodes.get(ls.from);
+				if (mergedNodes.containsKey(ls.to))
+					ls.to = mergedNodes.get(ls.to);
 			}
 		}
@@ -173,7 +176,9 @@
 	 */
 	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;
+		if (ls1.id == ls2.id)
+			return true;
+		if (ls1.incomplete || ls2.incomplete)
+			return false;
+		return match(ls1.from, ls2.from) && match(ls1.to, ls2.to);
 	}
 
Index: src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 66)
@@ -3,5 +3,4 @@
 
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 
@@ -36,9 +35,9 @@
 	 */
 	public void visit(LineSegment ls) {
-		String name = getName(ls.keys);
+		name = ls.get("name");
+		if (name == null && ls.incomplete)
+			name = ""+ls.id;
 		if (name == null)
-			name = "("+ls.start.coor.lat+","+ls.start.coor.lon+") -> ("+ls.end.coor.lat+","+ls.end.coor.lon+")";
-			
-		this.name = name;
+			name = "("+ls.from.coor.lat+","+ls.from.coor.lon+") -> ("+ls.to.coor.lat+","+ls.to.coor.lon+")";
 		icon = ImageProvider.get("data", "linesegment");
 	}
@@ -49,9 +48,7 @@
 	 */
 	public void visit(Node n) {
-		String name = getName(n.keys);
+		name = n.get("name");
 		if (name == null)
 			name = "("+n.coor.lat+","+n.coor.lon+")";
-		
-		this.name = name;
 		icon = ImageProvider.get("data", "node");
 	}
@@ -61,34 +58,17 @@
 	 * is displayed with x beeing the number of nodes in the way.
 	 */
-	public void visit(Way t) {
-		String name = getName(t.keys);
+	public void visit(Way w) {
+		name = w.get("name");
 		if (name == null) {
 			Set<Node> nodes = new HashSet<Node>();
-			for (LineSegment ls : t.segments) {
-				nodes.add(ls.start);
-				nodes.add(ls.end);
+			for (LineSegment ls : w.segments) {
+				if (!ls.incomplete) {
+					nodes.add(ls.from);
+					nodes.add(ls.to);
+				}
 			}
 			name = "("+nodes.size()+" nodes)";
 		}
-		
-		this.name = name;
 		icon = ImageProvider.get("data", "way");
 	}
-
-	
-	/**
-	 * Try to read a name from the given properties.
-	 * @param keys The properties to search for a name. Can be <code>null</code>.
-	 * @return If a name could be found, return it here.
-	 */
-	public String getName(Map<String, String> keys) {
-		String name = null;
-		if (keys != null) {
-			name = keys.get("name");
-			if (name == null)
-				name = keys.get("id");
-		}
-		return name;
-	}
-	
 }
Index: src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 66)
@@ -18,4 +18,5 @@
 public class SimplePaintVisitor implements Visitor {
 
+	private final static Color darkerblue = new Color(0,0,96);
 	private final static Color darkblue = new Color(0,0,128);
 	private final static Color darkgreen = new Color(0,128,0);
@@ -64,7 +65,14 @@
 	public void visit(Way t) {
 		// only to overwrite with blue
+		Color wayColor = darkblue;
+		for (LineSegment ls : t.segments) {
+			if (ls.incomplete) {
+				wayColor = darkerblue;
+				break;
+			}
+		}
 		for (LineSegment ls : t.segments)
 			if (!ls.isSelected()) // selected already in good color
-				drawLineSegment(ls, t.isSelected() ? Color.WHITE : darkblue);
+				drawLineSegment(ls, t.isSelected() ? Color.WHITE : wayColor);
 	}
 
@@ -85,9 +93,11 @@
 	 */
 	private void drawLineSegment(LineSegment ls, Color col) {
+		if (ls.incomplete)
+			return;
 		if (ls.isSelected())
 			col = Color.WHITE;
 		g.setColor(col);
-		Point p1 = nc.getScreenPoint(ls.start.coor);
-		Point p2 = nc.getScreenPoint(ls.end.coor);
+		Point p1 = nc.getScreenPoint(ls.from.coor);
+		Point p2 = nc.getScreenPoint(ls.to.coor);
 		g.drawLine(p1.x, p1.y, p2.x, p2.y);
 	}
Index: src/org/openstreetmap/josm/data/osm/visitor/Visitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/Visitor.java	(revision 65)
+++ src/org/openstreetmap/josm/data/osm/visitor/Visitor.java	(revision 66)
@@ -14,4 +14,4 @@
 	void visit(Node n);
 	void visit(LineSegment ls);
-	void visit(Way t);
+	void visit(Way w);
 }
Index: src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapMover.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/MapMover.java	(revision 66)
@@ -83,5 +83,5 @@
 	 * Start movement by setting a new cursor and remember the current mouse
 	 * position.
-	 * @param e The mouse event that leat to the movement start.
+	 * @param e The mouse event that leat to the movement from.
 	 */
 	private void startMovement(MouseEvent e) {
Index: src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapStatus.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/MapStatus.java	(revision 66)
@@ -139,7 +139,6 @@
 							if (osm.id != 0)
 								text.append("<br>id="+osm.id);
-							if (osm.keys != null)
-								for (Entry<String, String> e : osm.keys.entrySet())
-									text.append("<br>"+e.getKey()+"="+e.getValue());
+							for (Entry<String, String> e : osm.entrySet())
+								text.append("<br>"+e.getKey()+"="+e.getValue());
 							final JLabel l = new JLabel("<html>"+text.toString()+"</html>", visitor.icon, JLabel.HORIZONTAL);
 							l.setFont(l.getFont().deriveFont(Font.PLAIN));
Index: src/org/openstreetmap/josm/gui/NavigatableComponent.java
===================================================================
--- src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/NavigatableComponent.java	(revision 66)
@@ -156,8 +156,8 @@
 					continue;
 				for (LineSegment ls : w.segments) {
-					if (ls.isDeleted())
+					if (ls.isDeleted() || ls.incomplete)
 						continue;
-					Point A = getScreenPoint(ls.start.coor);
-					Point B = getScreenPoint(ls.end.coor);
+					Point A = getScreenPoint(ls.from.coor);
+					Point B = getScreenPoint(ls.to.coor);
 					double c = A.distanceSq(B);
 					double a = p.distanceSq(B);
@@ -177,8 +177,8 @@
 		// line segments
 		for (LineSegment ls : Main.main.ds.lineSegments) {
-			if (ls.isDeleted())
+			if (ls.isDeleted() || ls.incomplete)
 				continue;
-			Point A = getScreenPoint(ls.start.coor);
-			Point B = getScreenPoint(ls.end.coor);
+			Point A = getScreenPoint(ls.from.coor);
+			Point B = getScreenPoint(ls.to.coor);
 			double c = A.distanceSq(B);
 			double a = p.distanceSq(B);
@@ -225,5 +225,5 @@
 			for (LineSegment ls : Main.main.ds.lineSegments)
 				// line segments never match nodes, so they are skipped by contains
-				if (!ls.isDeleted() && (c.contains(ls.start) || c.contains(ls.end)))
+				if (!ls.isDeleted() && !ls.incomplete && (c.contains(ls.from) || c.contains(ls.to)))
 					c.add(ls);
 		} 
@@ -239,5 +239,5 @@
 					continue;
 				for (LineSegment ls : t.segments) {
-					if (!ls.isDeleted() && c.contains(ls)) {
+					if (!ls.isDeleted() && !ls.incomplete && c.contains(ls)) {
 						c.add(t);
 						break;
Index: src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 66)
@@ -135,5 +135,5 @@
 
 	/**
-	 * If the correct button, start the "drawing rectangle" mode
+	 * If the correct button, from the "drawing rectangle" mode
 	 */
 	public void mousePressed(MouseEvent e) {
@@ -309,12 +309,14 @@
 	 */
 	private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) {
+		if (ls.incomplete)
+			return false;
 		if (alt) {
-			Point p1 = nc.getScreenPoint(ls.start.coor);
-			Point p2 = nc.getScreenPoint(ls.end.coor);
+			Point p1 = nc.getScreenPoint(ls.from.coor);
+			Point p2 = nc.getScreenPoint(ls.to.coor);
 			if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
 				return true;
 		} else {
-			if (r.contains(nc.getScreenPoint(ls.start.coor))
-					&& r.contains(nc.getScreenPoint(ls.end.coor)))
+			if (r.contains(nc.getScreenPoint(ls.from.coor))
+					&& r.contains(nc.getScreenPoint(ls.to.coor)))
 				return true;
 		}
Index: src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 66)
@@ -14,5 +14,7 @@
 import java.awt.event.WindowFocusListener;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeSet;
@@ -61,5 +63,5 @@
 
 	/**
-	 * Watches for double clicks and start editing or new property, depending on the
+	 * Watches for double clicks and from editing or new property, depending on the
 	 * location, the click was.
 	 * @author imi
@@ -78,5 +80,5 @@
 		}
 	}
-	
+
 	/**
 	 * Edit the value in the table row
@@ -143,6 +145,5 @@
 		Vector<String> allKeys = new Vector<String>();
 		for (OsmPrimitive osm : Main.main.ds.allNonDeletedPrimitives())
-			if (osm.keys != null)
-				allKeys.addAll(osm.keys.keySet());
+			allKeys.addAll(osm.keySet());
 		for (Iterator<String> it = allKeys.iterator(); it.hasNext();) {
 			String s = it.next();
@@ -293,15 +294,16 @@
 			propertyTable.getCellEditor().cancelCellEditing();
 		data.setRowCount(0);
+		
+		Map<String, Integer> valueCount = new HashMap<String, Integer>();
 		TreeMap<String, Collection<String>> props = new TreeMap<String, Collection<String>>();
 		for (OsmPrimitive osm : newSelection) {
-			if (osm.keys != null) {
-				for (Entry<String, String> e : osm.keys.entrySet()) {
-					Collection<String> value = props.get(e.getKey());
-					if (value == null) {
-						value = new TreeSet<String>();
-						props.put(e.getKey(), value);
-					}
-					value.add(e.getValue());
+			for (Entry<String, String> e : osm.entrySet()) {
+				Collection<String> value = props.get(e.getKey());
+				if (value == null) {
+					value = new TreeSet<String>();
+					props.put(e.getKey(), value);
 				}
+				value.add(e.getValue());
+				valueCount.put(e.getKey(), valueCount.containsKey(e.getKey()) ? valueCount.get(e.getKey())+1 : 1);
 			}
 		}
@@ -309,5 +311,5 @@
 			JComboBox value = new JComboBox(e.getValue().toArray());
 			value.setEditable(true);
-			value.getEditor().setItem(e.getValue().size() > 1 ? "<different>" : e.getValue().iterator().next());
+			value.getEditor().setItem(valueCount.get(e.getKey()) != newSelection.size() ? "<different>" : e.getValue().iterator().next());
 			data.addRow(new Object[]{e.getKey(), value});
 		}
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 65)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 66)
@@ -93,10 +93,8 @@
 				Main.main.ds.clearSelection();
 				for (OsmPrimitive osm : Main.main.ds.allNonDeletedPrimitives()) {
-					if (osm.keys != null) {
-						for (Entry<String, String> ent : osm.keys.entrySet()) {
-							if (match(lastSearch, ent.getKey(), ent.getValue())) {
-								osm.setSelected(true);
-								break;
-							}
+					for (Entry<String, String> ent : osm.entrySet()) {
+						if (match(lastSearch, ent.getKey(), ent.getValue())) {
+							osm.setSelected(true);
+							break;
 						}
 					}
Index: src/org/openstreetmap/josm/io/GpxReader.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxReader.java	(revision 65)
+++ src/org/openstreetmap/josm/io/GpxReader.java	(revision 66)
@@ -73,8 +73,7 @@
 	 */
 	private Node parseWaypoint(Element e) {
-		Node data = new Node();
-		data.coor = new GeoPoint(
+		Node data = new Node(new GeoPoint(
 			Double.parseDouble(e.getAttributeValue("lat")),
-			Double.parseDouble(e.getAttributeValue("lon")));
+			Double.parseDouble(e.getAttributeValue("lon"))));
 		
 		for (Object o : e.getChildren()) {
@@ -200,6 +199,4 @@
 		if (e != null) {
 			for (Object o : e.getChildren("property", OSM)) {
-				if (osm.keys == null)
-					osm.keys = new HashMap<String, String>();
 				Element child = (Element)o;
 				String keyname = child.getAttributeValue("key");
@@ -208,5 +205,5 @@
 					if (value == null)
 						value = "";
-					osm.keys.put(keyname, value);
+					osm.put(keyname, value);
 				}
 			}
@@ -251,8 +248,6 @@
 	private void parseKeyValueLink(OsmPrimitive osm, Element e) {
 		if (e != null) {
-			if (osm.keys == null)
-				osm.keys = new HashMap<String, String>();
 			String link = e.getChildText("type") + ";" + e.getChildText("text");
-			osm.keys.put("link", link);
+			osm.put("link", link);
 		}
 	}
Index: src/org/openstreetmap/josm/io/GpxWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxWriter.java	(revision 65)
+++ src/org/openstreetmap/josm/io/GpxWriter.java	(revision 66)
@@ -127,6 +127,6 @@
 			for (LineSegment ls : t.segments) {
 				tElem.getChildren().add(parseLineSegment(ls));
-				unrefNodes.remove(ls.start);
-				unrefNodes.remove(ls.end);
+				unrefNodes.remove(ls.from);
+				unrefNodes.remove(ls.to);
 				unrefLs.remove(ls);
 			}
@@ -141,6 +141,6 @@
 			Element t = new Element("trk", GPX);
 			t.getChildren().add(parseLineSegment(ls));
-			unrefNodes.remove(ls.start);
-			unrefNodes.remove(ls.end);
+			unrefNodes.remove(ls.from);
+			unrefNodes.remove(ls.to);
 			Element ext = new Element("extensions", GPX);
 			ext.getChildren().add(new Element("segment", JOSM));
@@ -180,6 +180,6 @@
 		Element lsElem = new Element("trkseg", GPX);
 		addPropertyExtensions(lsElem, ls.keys, ls);
-		lsElem.getChildren().add(parseWaypoint(ls.start, "trkpt"));
-		lsElem.getChildren().add(parseWaypoint(ls.end, "trkpt"));
+		lsElem.getChildren().add(parseWaypoint(ls.from, "trkpt"));
+		lsElem.getChildren().add(parseWaypoint(ls.to, "trkpt"));
 		return lsElem;
 	}
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 65)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 66)
@@ -15,5 +15,4 @@
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
 import uk.co.wilson.xml.MinML2;
@@ -77,6 +76,5 @@
 					throw new SAXException("Unknown version: "+atts.getValue("version"));
 			} else if (qName.equals("node")) {
-				Node n = new Node();
-				n.coor = new GeoPoint(getDouble(atts, "lat"), getDouble(atts, "lon"));
+				Node n = new Node(new GeoPoint(getDouble(atts, "lat"), getDouble(atts, "lon")));
 				current = n;
 				readCommon(atts);
@@ -94,7 +92,11 @@
 			} else if (qName.equals("seg")) {
 				if (current instanceof Way) {
-					LineSegment ls = lineSegments.get(getLong(atts, "id"));
-					if (ls == null)
-						fatalError(new SAXParseException("Line segment "+getLong(atts, "id")+" has not been transfered before.", null));
+					long id = getLong(atts, "id");
+					LineSegment ls = lineSegments.get(id);
+					if (ls == null) {
+						ls = new LineSegment(id); // incomplete line segment
+						lineSegments.put(id, ls);
+						adder.visit(ls);
+					}
 					((Way)current).segments.add(ls);
 				}
Index: src/org/openstreetmap/josm/io/OsmReaderOld.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReaderOld.java	(revision 65)
+++ src/org/openstreetmap/josm/io/OsmReaderOld.java	(revision 66)
@@ -4,5 +4,4 @@
 import java.io.Reader;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.StringTokenizer;
 
@@ -63,8 +62,7 @@
 	 */
 	private Node parseNode(Element e) throws JDOMException {
-		Node data = new Node();
-		data.coor = new GeoPoint(
+		Node data = new Node(new GeoPoint(
 			Double.parseDouble(e.getAttributeValue("lat")),
-			Double.parseDouble(e.getAttributeValue("lon")));
+			Double.parseDouble(e.getAttributeValue("lon"))));
 		if (Double.isNaN(data.coor.lat) || 
 				data.coor.lat < -90 || data.coor.lat > 90 ||
@@ -175,5 +173,4 @@
 		String propStr = e.getAttributeValue("tags");
 		if (propStr != null && !propStr.equals("")) {
-			data.keys = new HashMap<String, String>();
 			StringTokenizer st = new StringTokenizer(propStr, ";");
 			while (st.hasMoreTokens()) {
@@ -183,8 +180,8 @@
 				int equalPos = next.indexOf('=');
 				if (equalPos == -1)
-					data.keys.put(next, "");
+					data.put(next, "");
 				else {
 					String keyStr = next.substring(0, equalPos);
-					data.keys.put(keyStr, next.substring(equalPos+1));
+					data.put(keyStr, next.substring(equalPos+1));
 				}
 			}
@@ -210,9 +207,6 @@
 		String key = e.getAttributeValue("key");
 		String value = e.getAttributeValue("value");
-		if (value != null) {
-			if (osm.keys == null)
-				osm.keys = new HashMap<String, String>();
-			osm.keys.put(key, value);
-		}
+		if (value != null)
+			osm.put(key, value);
 	}
 
Index: src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 65)
+++ src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 66)
@@ -12,5 +12,4 @@
 import java.net.UnknownHostException;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.LinkedList;
 
@@ -67,5 +66,5 @@
 	public void visit(Node n) {
 		if (n.id == 0 && !n.isDeleted()) {
-			setCredits(n);
+			n.put("created_by", "JOSM");
 			sendRequest("PUT", "node", n, true);
 		} else if (n.isDeleted()) {
@@ -82,5 +81,5 @@
 	public void visit(LineSegment ls) {
 		if (ls.id == 0 && !ls.isDeleted()) {
-			setCredits(ls);
+			ls.put("created_by", "JOSM");
 			sendRequest("PUT", "segment", ls, true);
 		} else if (ls.isDeleted()) {
@@ -97,5 +96,5 @@
 	public void visit(Way w) {
 		if (w.id == 0 && !w.isDeleted()) {
-			setCredits(w);
+			w.put("created_by", "JOSM");
 			sendRequest("PUT", "way", w, true);
 		} else if (w.isDeleted()) {
@@ -106,16 +105,4 @@
 		processed.add(w);
 	}
-
-	/**
-	 * Add the created_by - property to indicate that JOSM was the
-	 * creating application.
-	 * @param osm The primitive to add the credits to
-	 */
-	private void setCredits(OsmPrimitive osm) {
-		if (osm.keys == null)
-			osm.keys = new HashMap<String, String>();
-		osm.keys.put("created_by", "JOSM");
-	}
-
 
 	/**
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 65)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(revision 66)
@@ -104,6 +104,8 @@
 
 	public void visit(LineSegment ls) {
+		if (ls.incomplete)
+			throw new IllegalArgumentException("Cannot write an incomplete LineSegment.");
 		addCommon(ls, "segment");
-		out.print(" from='"+getUsedId(ls.start)+"' to='"+getUsedId(ls.end)+"'");
+		out.print(" from='"+getUsedId(ls.from)+"' to='"+getUsedId(ls.to)+"'");
 		addTags(ls, "segment", true);
 	}
@@ -164,5 +166,5 @@
 
 	/**
-	 * Add the common part as the start of the tag as well as the id or the action tag.
+	 * Add the common part as the from of the tag as well as the id or the action tag.
 	 */
 	private void addCommon(OsmPrimitive osm, String tagname) {
