Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 80)
+++ src/org/openstreetmap/josm/Main.java	(revision 81)
@@ -14,4 +14,6 @@
 import java.util.LinkedList;
 import java.util.StringTokenizer;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 
 import javax.swing.Action;
@@ -58,4 +60,12 @@
 	public static Main main;
 
+	/**
+	 * The worker thread slave. This is for executing all long and intensive
+	 * calculations. The executed runnables are guaranteed to be executed seperatly
+	 * and sequenciel.
+	 */
+	public static Executor worker = Executors.newSingleThreadExecutor();
+	
+	
 	public static Projection proj;
 
Index: src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 80)
+++ src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 81)
@@ -10,6 +10,6 @@
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
-import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -41,4 +41,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.RawGpsDataLayer;
+import org.openstreetmap.josm.gui.layer.RawGpsDataLayer.GpsPoint;
 import org.openstreetmap.josm.io.OsmServerReader;
 import org.openstreetmap.josm.tools.GBC;
@@ -55,5 +56,68 @@
 public class DownloadAction extends JosmAction {
 
-    /**
+	/**
+	 * Open the download dialog and download the data.
+	 * Run in the worker thread.
+	 */
+    private final class DownloadOsmTask extends PleaseWaitRunnable {
+	    private final OsmServerReader reader;
+		private DataSet dataSet;
+
+	    private DownloadOsmTask(OsmServerReader reader) {
+		    super("Downloading data");
+		    this.reader = reader;
+	    }
+
+	    @Override
+	    public void realRun() throws IOException, SAXException {
+    		dataSet = reader.parseOsm();
+    		if (dataSet.nodes.isEmpty())
+    			JOptionPane.showMessageDialog(Main.main, "No data imported.");
+	    }
+
+		@Override
+        protected void finish() {
+			if (dataSet == null)
+				return; // user cancelled download or error occoured
+			Layer layer = new OsmDataLayer(dataSet, "Data Layer", false);
+	    	if (Main.main.getMapFrame() == null)
+	    		Main.main.setMapFrame(new MapFrame(layer));
+	    	else
+	    		Main.main.getMapFrame().mapView.addLayer(layer);
+		}
+	    
+    }
+
+
+    private final class DownloadGpsTask extends PleaseWaitRunnable {
+	    private final OsmServerReader reader;
+		private Collection<Collection<GpsPoint>> rawData;
+
+	    private DownloadGpsTask(OsmServerReader reader) {
+		    super("Downloading GPS data");
+		    this.reader = reader;
+	    }
+
+	    @Override
+	    public void realRun() throws IOException, JDOMException {
+    		rawData = reader.parseRawGps();
+	    }
+
+		@Override
+        protected void finish() {
+			if (rawData == null)
+				return;
+			String name = latlon[0].getText() + " " + latlon[1].getText() + " x " + latlon[2].getText() + " " + latlon[3].getText();
+			Layer layer = new RawGpsDataLayer(rawData, name);
+	    	if (Main.main.getMapFrame() == null)
+	    		Main.main.setMapFrame(new MapFrame(layer));
+	    	else
+	    		Main.main.getMapFrame().mapView.addLayer(layer);
+		}
+	    
+    }
+    
+    
+	/**
      * minlat, minlon, maxlat, maxlon
      */
@@ -231,24 +295,14 @@
 		
 		// Finally: the dialog
-		while(true) {
+		Bookmark b;
+		do {
 			int r = JOptionPane.showConfirmDialog(Main.main, dlg, "Choose an area", 
 					JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
 			if (r != JOptionPane.OK_OPTION)
 				return;
-			if (startDownload()) 
-				break;
-		}
-	}
-
-	/**
-	 * Read the values from the edit fields and from the download.
-	 * @return <code>true</code> for a success, <code>false</code> redisplay
-	 */
-	private boolean startDownload() {
-		Bookmark b = readBookmark();
-		if (b == null) {
-			JOptionPane.showMessageDialog(Main.main, "Please enter the desired coordinates or click on a bookmark.");
-			return false;
-		}
+			b = readBookmark();
+			if (b == null)
+				JOptionPane.showMessageDialog(Main.main, "Please enter the desired coordinates or click on a bookmark.");
+		} while (b == null);
 
 		double minlon = b.latlon[0];
@@ -257,7 +311,6 @@
 		double maxlat = b.latlon[3];
 		download(rawGps.isSelected(), minlon, minlat, maxlon, maxlat);
-		return true;
-	}
-	
+	}
+
 	/**
 	 * Read a bookmark from the current set edit fields. If one of the fields is
@@ -325,51 +378,9 @@
 	 * Do the download for the given area.
 	 */
-	public void download(final boolean rawGps, double minlat, double minlon, double maxlat, double maxlon) {
-		final OsmServerReader osmReader = new OsmServerReader(minlat, minlon, maxlat, maxlon);
-		new Thread(new PleaseWaitRunnable("Downloading data"){
-			@Override
-			public void realRun() {
-				try {
-					String name = latlon[0].getText() + " " + latlon[1].getText() + " x " + latlon[2].getText() + " " + latlon[3].getText();
-
-					Layer layer = null;
-					if (rawGps) {
-						layer = new RawGpsDataLayer(osmReader.parseRawGps(), name);
-					} else {
-						DataSet dataSet = osmReader.parseOsm();
-						if (dataSet == null)
-							return; // user cancelled download
-						if (dataSet.nodes.isEmpty()) {
-							closeDialog();
-							JOptionPane.showMessageDialog(Main.main,
-							"No data imported.");
-						}
-
-						layer = new OsmDataLayer(dataSet, "Data Layer", false);
-					}
-
-					if (Main.main.getMapFrame() == null)
-						Main.main.setMapFrame(new MapFrame(layer));
-					else
-						Main.main.getMapFrame().mapView.addLayer(layer);
-				} catch (SAXException x) {
-					closeDialog();
-					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
-				} catch (JDOMException x) {
-					closeDialog();
-					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
-				} catch (FileNotFoundException x) {
-					closeDialog();
-					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, "URL not found: " + x.getMessage());
-				} catch (IOException x) {
-					closeDialog();
-					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, x.getMessage());
-				}
-			}
-		}).start();
+	public void download(boolean rawGps, double minlat, double minlon, double maxlat, double maxlon) {
+		OsmServerReader reader = new OsmServerReader(minlat, minlon, maxlat, maxlon);
+		PleaseWaitRunnable task = rawGps ? new DownloadGpsTask(reader) : new DownloadOsmTask(reader);
+		Main.worker.execute(task);
+		task.pleaseWaitDlg.setVisible(true);
 	}
 }
Index: src/org/openstreetmap/josm/actions/JosmAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/JosmAction.java	(revision 80)
+++ src/org/openstreetmap/josm/actions/JosmAction.java	(revision 81)
@@ -1,3 +1,7 @@
 package org.openstreetmap.josm.actions;
+
+import java.awt.EventQueue;
+import java.io.FileNotFoundException;
+import java.io.IOException;
 
 import javax.swing.AbstractAction;
@@ -6,9 +10,11 @@
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
 
+import org.jdom.JDOMException;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.xml.sax.SAXException;
 
 /**
@@ -25,13 +31,10 @@
 	 */
 	protected abstract class PleaseWaitRunnable implements Runnable {
-		private String msg;
-		private JDialog pleaseWaitDlg;
+		public final JDialog pleaseWaitDlg;
+		private String errorMessage;
 		/**
 		 * Create the runnable object with a given message for the user.
 		 */
-		PleaseWaitRunnable(String msg) {
-			this.msg = msg;
-		}
-		public final void run() {
+		public PleaseWaitRunnable(String msg) {
 			pleaseWaitDlg = new JDialog(Main.main, true);
 			pleaseWaitDlg.setUndecorated(true);
@@ -42,22 +45,50 @@
 			pleaseWaitDlg.getContentPane().add(l);
 			pleaseWaitDlg.pack();
-			pleaseWaitDlg.setLocation(Main.main.getX()+Main.main.getWidth()/2-pleaseWaitDlg.getWidth()/2,
-					Main.main.getY()+Main.main.getHeight()/2-pleaseWaitDlg.getHeight()/2);
+			pleaseWaitDlg.setLocationRelativeTo(Main.main);
 			pleaseWaitDlg.setResizable(false);
-			SwingUtilities.invokeLater(new Runnable(){
-				public void run() {
-					pleaseWaitDlg.setVisible(true);
-				}
-			});
+		}
+		public final void run() {
 			try {
 				realRun();
+	    	} catch (SAXException x) {
+	    		x.printStackTrace();
+	    		errorMessage = "Error while parsing: "+x.getMessage();
+	    	} catch (JDOMException x) {
+	    		x.printStackTrace();
+	    		errorMessage = "Error while parsing: "+x.getMessage();
+	    	} catch (FileNotFoundException x) {
+	    		x.printStackTrace();
+	    		errorMessage = "URL not found: " + x.getMessage();
+	    	} catch (IOException x) {
+	    		x.printStackTrace();
+	    		errorMessage = x.getMessage();
 			} finally {
 				closeDialog();
 			}
 		}
-		public abstract void realRun();
+		/**
+		 * Called in the worker thread to do the actual work. When any of the
+		 * exception is thrown, a message box will be displayed and closeDialog
+		 * is called. finish() is called in any case.
+		 */
+		protected abstract void realRun() throws SAXException, JDOMException, IOException;
+		/**
+		 * Finish up the data work. Is guaranteed to be called if realRun is called.
+		 * Finish is called in the gui thread just after the dialog disappeared.
+		 */
+		protected void finish() {}
+		/**
+		 * Close the dialog. Usually called from worker thread.
+		 */
 		public void closeDialog() {
-			pleaseWaitDlg.setVisible(false);
-			pleaseWaitDlg.dispose();
+			EventQueue.invokeLater(new Runnable(){
+				public void run() {
+					finish();
+					pleaseWaitDlg.setVisible(false);
+					pleaseWaitDlg.dispose();
+					if (errorMessage != null)
+						JOptionPane.showMessageDialog(Main.main, errorMessage);
+                }
+			});
 		}
 	}
Index: src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/UploadAction.java	(revision 80)
+++ src/org/openstreetmap/josm/actions/UploadAction.java	(revision 81)
@@ -76,17 +76,17 @@
 		all.addAll(delete);
 		
-		new Thread(new PleaseWaitRunnable("Uploading data"){
-			@Override
-			public void realRun() {
-				try {
-					server.uploadOsm(all);
-				} catch (JDOMException x) {
-					closeDialog();
-					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, x.getMessage());
-				}
-				Main.main.getMapFrame().mapView.editLayer().cleanData(server.processed, !add.isEmpty());
-			}
-		}).start();
+		PleaseWaitRunnable uploadTask = new PleaseWaitRunnable("Uploading data"){
+        			@Override
+        			protected void realRun() throws JDOMException {
+        				server.uploadOsm(all);
+        			}
+        			@Override
+                    protected void finish() {
+        				Main.main.getMapFrame().mapView.editLayer().cleanData(server.processed, !add.isEmpty());
+                    }
+        			
+        		};
+		Main.worker.execute(uploadTask);
+		uploadTask.pleaseWaitDlg.setVisible(true);
 	}
 
Index: src/org/openstreetmap/josm/data/SelectionTracker.java
===================================================================
--- src/org/openstreetmap/josm/data/SelectionTracker.java	(revision 80)
+++ src/org/openstreetmap/josm/data/SelectionTracker.java	(revision 81)
@@ -91,5 +91,5 @@
 			listeners.remove(listener);
 	}
-	
+
 	/**
 	 * Remember to fire an selection changed event. A call to this will not fire
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 80)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 81)
@@ -3,4 +3,5 @@
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -62,4 +63,11 @@
 
 	/**
+	 * Time of last modification to this object. This is not set by JOSM but
+	 * read from the server and delivered back to the server unmodified. It is
+	 * used to check against edit conflicts.
+	 */
+	public Date lastModified = null;
+
+	/**
 	 * Implementation of the visitor scheme. Subclases have to call the correct
 	 * visitor function.
@@ -190,4 +198,5 @@
 		deleted = osm.deleted;
 		selected = osm.selected;
+		lastModified = osm.lastModified;
 	}
 }
Index: src/org/openstreetmap/josm/gui/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 80)
+++ src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 81)
@@ -335,6 +335,5 @@
 		setModal(true);
 		pack();
-		Dimension s = Main.main.getSize();
-		setLocation(Main.main.getX()+s.width/2-getWidth()/2, Main.main.getY()+s.height/2-getHeight()/2);
+		setLocationRelativeTo(Main.main);
 	}
 
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 80)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 81)
@@ -3,4 +3,5 @@
 import java.awt.BorderLayout;
 import java.awt.Dimension;
+import java.awt.GridBagLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
@@ -11,4 +12,5 @@
 import java.util.Collection;
 
+import javax.swing.ButtonGroup;
 import javax.swing.DefaultListModel;
 import javax.swing.JButton;
@@ -17,5 +19,7 @@
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
+import javax.swing.JTextField;
 import javax.swing.ListSelectionModel;
 
@@ -25,4 +29,5 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
+import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.SearchCompiler;
@@ -82,6 +87,7 @@
 			private String lastSearch = "";
 			public void actionPerformed(ActionEvent e) {
-				JLabel l = new JLabel("Please enter a search string.");
-				l.setToolTipText("<html>Fulltext search.<ul>" +
+				JLabel label = new JLabel("Please enter a search string.");
+				final JTextField input = new JTextField(lastSearch);
+				input.setToolTipText("<html>Fulltext search.<ul>" +
 						"<li><code>Baker Street</code>  - 'Baker' and 'Street' in any key or name.</li>" +
 						"<li><code>\"Baker Street\"</code>  - 'Baker Street' in any key or name.</li>" +
@@ -90,10 +96,38 @@
 						"<li><code>foot:</code>  - key=foot set to any value." +
 						"</ul></html>");
-				lastSearch = (String)JOptionPane.showInputDialog(Main.main,l,"Search",JOptionPane.INFORMATION_MESSAGE,null,null,lastSearch);
-				if (lastSearch == null)
+
+				JRadioButton replace = new JRadioButton("replace selection", true);
+				JRadioButton add = new JRadioButton("add to selection", false);
+				JRadioButton remove = new JRadioButton("remove from selection", false);
+				ButtonGroup bg = new ButtonGroup();
+				bg.add(replace);
+				bg.add(add);
+				bg.add(remove);
+
+				JPanel p = new JPanel(new GridBagLayout());
+				p.add(label, GBC.eop());
+				p.add(input, GBC.eop().fill(GBC.HORIZONTAL));
+				p.add(replace, GBC.eol());
+				p.add(add, GBC.eol());
+				p.add(remove, GBC.eol());
+				JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null){
+					@Override public void selectInitialValue() {
+						input.requestFocusInWindow();
+                    }
+				};
+				pane.createDialog(Main.main, "Search").setVisible(true);
+				System.out.println(pane.getValue());
+				if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
 					return;
+				lastSearch = input.getText();
 				SearchCompiler.Match matcher = SearchCompiler.compile(lastSearch);
-				for (OsmPrimitive osm : Main.main.ds.allNonDeletedPrimitives())
-					osm.setSelected(matcher.match(osm));
+				for (OsmPrimitive osm : Main.main.ds.allNonDeletedPrimitives()) {
+					if (replace.isSelected())
+						osm.setSelected(matcher.match(osm));
+					else if (add.isSelected() && !osm.isSelected() && matcher.match(osm))
+						osm.setSelected(true);
+					else if (remove.isSelected() && osm.isSelected() && matcher.match(osm))
+						osm.setSelected(false);
+				}
 				selectionChanged(Main.main.ds.getSelected());
 				Main.main.getMapFrame().repaint();
Index: src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 80)
+++ src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 81)
@@ -44,5 +44,4 @@
 			}
 		};
-		
 		setLayout(new BorderLayout());
 		add(new JLabel(title), BorderLayout.NORTH);
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 80)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 81)
@@ -3,4 +3,6 @@
 import java.io.IOException;
 import java.io.Reader;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.HashMap;
 import java.util.Map;
@@ -82,7 +84,9 @@
 				nodes.put(n.id, n);
 			} else if (qName.equals("segment")) {
-				current = new LineSegment(
-						nodes.get(getLong(atts, "from")), 
-						nodes.get(getLong(atts, "to")));
+				Node from = nodes.get(getLong(atts, "from"));
+				Node to = nodes.get(getLong(atts, "to"));
+				if (from == null || to == null)
+					throw new SAXException("Segment "+atts.getValue("id")+" is missing its nodes.");
+				current = new LineSegment(from, to);
 				readCommon(atts);
 				lineSegments.put(current.id, (LineSegment)current);
@@ -103,7 +107,6 @@
 					((Way)current).segments.add(ls);
 				}
-			} else if (qName.equals("tag")) {
+			} else if (qName.equals("tag"))
 				current.put(atts.getValue("k"), atts.getValue("v"));
-			}
 		} catch (NumberFormatException x) {
             x.printStackTrace(); // SAXException does not chain correctly
@@ -129,4 +132,15 @@
 		if (current.id == 0)
 			throw new SAXException("Illegal object with id=0");
+		
+		String time = atts.getValue("timestamp");
+		if (time != null && time.length() != 0) {
+			try {
+	            current.lastModified = SimpleDateFormat.getDateTimeInstance().parse(time);
+            } catch (ParseException e) {
+	            e.printStackTrace();
+	            throw new SAXException("Couldn't read time format '"+time+"'.");
+            }
+		}
+		
 		String action = atts.getValue("action");
 		if ("delete".equals(action))
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 80)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(revision 81)
@@ -3,4 +3,5 @@
 import java.io.PrintWriter;
 import java.io.Writer;
+import java.text.SimpleDateFormat;
 import java.util.HashMap;
 import java.util.Map.Entry;
@@ -140,4 +141,8 @@
 				out.print(" action='"+action+"'");
 		}
+		if (osm.lastModified != null) {
+			String time = SimpleDateFormat.getDateTimeInstance().format(osm.lastModified);
+			out.print(" timestamp='"+time+"'");
+		}
 	}
 }
Index: src/org/openstreetmap/josm/tools/TileCache.java
===================================================================
--- src/org/openstreetmap/josm/tools/TileCache.java	(revision 80)
+++ src/org/openstreetmap/josm/tools/TileCache.java	(revision 81)
@@ -174,6 +174,5 @@
                 currentlyLoading.add(tileId*256+zoom);
                 // load from network
-                new Thread(){
-                    @Override
+                Main.worker.execute(new Runnable(){
                     public void run() {
                         try {
@@ -195,5 +194,5 @@
                         }        
                     }
-                }.start();
+                });
             }
         } else {
