Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 49)
+++ /src/org/openstreetmap/josm/Main.java	(revision 50)
@@ -7,4 +7,6 @@
 import java.awt.Point;
 import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.util.Arrays;
 import java.util.Collection;
@@ -35,4 +37,6 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.ShowModifiers;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 
 /**
@@ -140,4 +144,28 @@
 		
 		getContentPane().add(toolBar, BorderLayout.NORTH);
+	
+		addWindowListener(new WindowAdapter(){
+			@Override
+			public void windowClosing(WindowEvent arg0) {
+				if (mapFrame != null) {
+					boolean changed = false;
+					for (Layer l : mapFrame.mapView.getAllLayers()) {
+						if (l instanceof OsmDataLayer && ((OsmDataLayer)l).isModified()) {
+							changed = true;
+							break;
+						}
+					}
+					if (changed) {
+						int answer = JOptionPane.showConfirmDialog(
+								Main.this, "There are unsaved changes. Really quit?",
+								"Unsaved Changes", JOptionPane.YES_NO_OPTION);
+						if (answer != JOptionPane.YES_OPTION)
+							return;
+					}
+				}
+				System.exit(0);
+			}
+		});
+		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
 	}
 
@@ -174,5 +202,4 @@
 		
 		main = new Main();
-		main.setDefaultCloseOperation(EXIT_ON_CLOSE);
 		main.setVisible(true);
 
Index: /src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 49)
+++ /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 50)
@@ -14,5 +14,4 @@
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
-import javax.swing.JDialog;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
@@ -163,9 +162,7 @@
 		final OsmServerReader osmReader = new OsmServerReader(b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]);
 		
-		final JDialog pleaseWaitDlg = createPleaseWaitDialog("Downloading data");
-		
-		new Thread(){
+		new Thread(new PleaseWaitRunnable("Downloading data"){
 			@Override
-			public void run() {
+			public void realRun() {
 				try {
 					String name = latlon[0].getText() + " "
@@ -181,6 +178,5 @@
 							return; // user cancelled download
 						if (dataSet.nodes.isEmpty()) {
-							pleaseWaitDlg.setVisible(false);
-							pleaseWaitDlg.dispose();
+							closeDialog();
 							JOptionPane.showMessageDialog(Main.main,
 									"No data imported.");
@@ -194,31 +190,20 @@
 					else
 						Main.main.getMapFrame().mapView.addLayer(layer);
-					pleaseWaitDlg.setVisible(false);
 				} catch (JDOMException x) {
-					pleaseWaitDlg.setVisible(false);
-					pleaseWaitDlg.dispose();
+					closeDialog();
 					x.printStackTrace();
 					JOptionPane.showMessageDialog(Main.main, x.getMessage());
 				} catch (FileNotFoundException x) {
-					pleaseWaitDlg.setVisible(false);
-					pleaseWaitDlg.dispose();
+					closeDialog();
 					x.printStackTrace();
 					JOptionPane.showMessageDialog(Main.main,
 							"URL nicht gefunden: " + x.getMessage());
 				} catch (IOException x) {
-					pleaseWaitDlg.setVisible(false);
-					pleaseWaitDlg.dispose();
+					closeDialog();
 					x.printStackTrace();
 					JOptionPane.showMessageDialog(Main.main, x.getMessage());
-				} finally {
-					if (pleaseWaitDlg.isVisible()) {
-						pleaseWaitDlg.setVisible(false);
-						pleaseWaitDlg.dispose();
-					}
-				}
-			}
-		}.start();
-		
-		pleaseWaitDlg.setVisible(true);
+				}
+			}
+		}).start();
 	}
 	
Index: /src/org/openstreetmap/josm/actions/JosmAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/JosmAction.java	(revision 49)
+++ /src/org/openstreetmap/josm/actions/JosmAction.java	(revision 50)
@@ -7,4 +7,5 @@
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.Main;
@@ -17,4 +18,49 @@
 abstract public class JosmAction extends AbstractAction {
 
+	/**
+	 * Instanced of this thread will display a "Please Wait" message in middle of JOSM
+	 * to indicate a progress beeing executed.
+	 *  
+	 * @author Imi
+	 */
+	protected abstract class PleaseWaitRunnable implements Runnable {
+		private String msg;
+		private JDialog pleaseWaitDlg;
+		/**
+		 * Create the runnable object with a given message for the user.
+		 */
+		PleaseWaitRunnable(String msg) {
+			this.msg = msg;
+		}
+		public final void run() {
+			pleaseWaitDlg = new JDialog(Main.main, true);
+			pleaseWaitDlg.setUndecorated(true);
+			JLabel l = new JLabel(msg+". Please Wait.");
+			l.setBorder(BorderFactory.createCompoundBorder(
+					BorderFactory.createEtchedBorder(),
+					BorderFactory.createEmptyBorder(20,20,20,20)));
+			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.setResizable(false);
+			SwingUtilities.invokeLater(new Runnable(){
+				public void run() {
+					pleaseWaitDlg.setVisible(true);
+				}
+			});
+			try {
+				realRun();
+			} finally {
+				closeDialog();
+			}
+		}
+		public abstract void realRun();
+		public void closeDialog() {
+			pleaseWaitDlg.setVisible(false);
+			pleaseWaitDlg.dispose();
+		}
+	}
+	
 	/**
 	 * Construct the action.
@@ -34,21 +80,3 @@
 			putValue(ACCELERATOR_KEY, shortCut);
 	}
-
-	/**
-	 * @return A dialog labeled "... Please Wait." where ... is the message parameter.
-	 */
-	protected JDialog createPleaseWaitDialog(String msg) {
-		final JDialog pleaseWaitDlg = new JDialog(Main.main, true);
-		pleaseWaitDlg.setUndecorated(true);
-		JLabel l = new JLabel(msg+". Please Wait.");
-		l.setBorder(BorderFactory.createCompoundBorder(
-				BorderFactory.createEtchedBorder(),
-				BorderFactory.createEmptyBorder(20,20,20,20)));
-		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.setResizable(false);
-		return pleaseWaitDlg;
-	}
 }
Index: /src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 49)
+++ /src/org/openstreetmap/josm/actions/UploadAction.java	(revision 50)
@@ -8,5 +8,4 @@
 import java.util.LinkedList;
 
-import javax.swing.JDialog;
 import javax.swing.JLabel;
 import javax.swing.JList;
@@ -75,25 +74,16 @@
 		all.addAll(delete);
 		
-		final JDialog dlg = createPleaseWaitDialog("Uploading data");
-		new Thread(){
+		new Thread(new PleaseWaitRunnable("Uploading data"){
 			@Override
-			public void run() {
+			public void realRun() {
 				try {
 					server.uploadOsm(all);
 				} catch (JDOMException x) {
-					dlg.setVisible(false);
-					dlg.dispose();
+					closeDialog();
 					x.printStackTrace();
 					JOptionPane.showMessageDialog(Main.main, x.getMessage());
-				} finally {
-					if (dlg.isVisible()) {
-						dlg.setVisible(false);
-						dlg.dispose();
-					}
 				}
 			}
-		}.start();
-		
-		dlg.setVisible(true);
+		}).start();
 		
 		// finished without errors -> clean dataset
Index: /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 49)
+++ /src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 50)
@@ -166,5 +166,5 @@
 			if (myOsm.keys == null)
 				myOsm.keys = otherOsm.keys;
-			else
+			else if (otherOsm.keys != null)
 				myOsm.keys.putAll(otherOsm.keys);
 			myOsm.modifiedProperties = true;
Index: /src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapView.java	(revision 49)
+++ /src/org/openstreetmap/josm/gui/MapView.java	(revision 50)
@@ -23,4 +23,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer.ModifiedChangedListener;
 
 /**
@@ -100,4 +101,5 @@
 
 		if (layer instanceof OsmDataLayer) {
+			final OsmDataLayer dataLayer = (OsmDataLayer)layer;
 			if (editLayer != null) {
 				// merge the layer into the existing one
@@ -108,5 +110,10 @@
 				return;
 			}
-			editLayer = (OsmDataLayer)layer;
+			editLayer = dataLayer;
+			dataLayer.addModifiedListener(new ModifiedChangedListener(){
+				public void modifiedChanged(boolean value, OsmDataLayer source) {
+					Main.main.setTitle((value?"*":"")+"Java Open Street Map - Editor");
+				}
+			});
 		}
 
Index: /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 49)
+++ /src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 50)
@@ -34,4 +34,8 @@
 public class OsmDataLayer extends Layer {
 
+	public interface ModifiedChangedListener {
+		void modifiedChanged(boolean value, OsmDataLayer source);
+	}
+	
 	private static Icon icon;
 
@@ -42,4 +46,8 @@
 
 	/**
+	 * Whether the data of this layer was modified during the session.
+	 */
+	private boolean modified = false;
+	/**
 	 * All commands that were made on the dataset.
 	 */
@@ -50,4 +58,9 @@
 	private Stack<Command> redoCommands = new Stack<Command>();
 
+	/**
+	 * List of all listeners for changes of modified flag.
+	 */
+	LinkedList<ModifiedChangedListener> listener;
+	
 	/**
 	 * Construct a OsmDataLayer.
@@ -157,4 +170,5 @@
 		Main.main.undoAction.setEnabled(true);
 		Main.main.redoAction.setEnabled(false);
+		setModified(true);
 	}
 
@@ -171,4 +185,6 @@
 		Main.main.undoAction.setEnabled(!commands.isEmpty());
 		Main.main.redoAction.setEnabled(true);
+		if (commands.isEmpty())
+			setModified(false);
 	}
 	/**
@@ -200,4 +216,32 @@
 		for (Iterator<Track> it = data.tracks.iterator(); it.hasNext();)
 			cleanIterator(it);
+		
+		// not modified anymore, since either everything reverted to file state or 
+		// everything uploaded properly.		
+		setModified(false); 
+		
+	}
+
+	public boolean isModified() {
+		return modified;
+	}
+
+	public void setModified(boolean modified) {
+		if (modified == this.modified)
+			return;
+		this.modified = modified;
+		if (listener != null)
+			for (ModifiedChangedListener l : listener)
+				l.modifiedChanged(modified, this);
+	}
+
+	/**
+	 * Add the parameter to the intern list of listener for modified state.
+	 * @param l Listener to add to the list. Must not be null.
+	 */
+	public void addModifiedListener(ModifiedChangedListener l) {
+		if (listener == null)
+			listener = new LinkedList<ModifiedChangedListener>();
+		listener.add(l);
 	}
 
