Index: src/org/openstreetmap/josm/actions/ReorderAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/ReorderAction.java	(revision 318)
+++ src/org/openstreetmap/josm/actions/ReorderAction.java	(revision 319)
@@ -1,3 +1,3 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
+//License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.actions;
 
@@ -10,4 +10,5 @@
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.HashMap;
 
 import javax.swing.JOptionPane;
@@ -27,6 +28,6 @@
 	public ReorderAction() {
 		super(tr("Reorder Segments"), "reorder", tr("Try to reorder segments of a way so that they are in a line. May try to flip segments around to match a line."), KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK, true);
-    }
-	
+	}
+
 	/**
 	 * This method first sorts all the segments in a way, then makes sure that all 
@@ -38,14 +39,14 @@
 			if (osm instanceof Way)
 				ways.add((Way)osm);
-		
+
 		if (ways.size() < 1) {
 			JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way."));
 			return;
 		}
-		
+
 		if (ways.size() > 1) {
 			int answer = JOptionPane.showConfirmDialog(Main.parent, 
-				trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()), 
-				tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION);
+					trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()), 
+					tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION);
 			if (answer != JOptionPane.OK_OPTION)
 				return;
@@ -75,80 +76,80 @@
 	 * the segments are facing the same direction as the first one.
 	 * @param way The way to reorder
-     * @return The command needed to reorder the way
-     */
-    public static Command reorderWay(Way way) {
-	    final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false));   	
-
-	    Collection<Command> c = new LinkedList<Command>();
-
-	    boolean direction = false;
-	    // work out the "average" direction of the way, we use this to direct the rest of the segments
-	    int dirCounter = 0;
-	    for(int i = 0; i < sel.size() - 1; i++)
-	    {
-	    	Segment firstSegment = sel.get(i);
-	    	Segment secondSegment = sel.get(i+1);
-	    	if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way
-	    		dirCounter++;
-	    	else
-	    		dirCounter--;
-	    }
-	    if ( dirCounter <= 0 )
-	    	direction = false;
-	    else
-	    	direction = true;
-	    
-	    Node lastNode = null;
-
-	    // we need to calculate what the first node in the way is, we work from there
-	    Segment firstSegment = sel.getFirst();
-	    Segment secondSegment = sel.get(1);
-	    if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to)
-	    	lastNode = firstSegment.from;
-	    else
-	    	lastNode = firstSegment.to;
-	    
-	    // go through each segment and flip them if required
-	    for (Segment s : sel) {
-	    	Segment snew = new Segment(s);
-	    	boolean segDirection = s.from == lastNode;
-	    	// segDirection = true when the 'from' node occurs before the 'to' node in the Way 
-	    	if (direction != segDirection)
-	    	{    			
-	    		// reverse the segment's direction
-	    		Node n = snew.from;
-	    		snew.from = snew.to;
-	    		snew.to = n;
-	    		c.add(new ChangeCommand(s, snew));
-	    	}	
-	    	
-	    	if (direction) // if its facing forwards,
-	    		lastNode = snew.to; // our next node is the 'to' one
-	    	else
-	    		lastNode = snew.from; // otherwise its the 'from' one
-	    }
-
-	    LinkedList<Segment> segments = new LinkedList<Segment>();
-	    
-	    // Now we recreate the segment list, in the correct order of the direction
-	    for (Segment s : sel) 
-	    	if (!direction) 
-	    		segments.addFirst(s);
-	    	else
-	    		segments.addLast(s);
-	    	
-	    // Check if the new segment list is actually different from the old one
-	    // before we go and add a change command for it
-	    for(int i = 0; i < segments.size(); i++)
-	    	if (way.segments.get(i) != segments.get(i))
-	    	{
-	        	Way newWay = new Way(way);
-	        	newWay.segments.clear();
-	    		newWay.segments.addAll(segments);
-	    		c.add(new ChangeCommand(way, newWay));
-	    		break;
-	    	}
-	    
-	    // Check we've got some change commands before we add a sequence command
+	 * @return The command needed to reorder the way
+	 */
+	public static Command reorderWay(Way way) {
+		final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false));   	
+
+		Collection<Command> c = new LinkedList<Command>();
+
+		boolean direction = false;
+		// work out the "average" direction of the way, we use this to direct the rest of the segments
+		int dirCounter = 0;
+		for(int i = 0; i < sel.size() - 1; i++)
+		{
+			Segment firstSegment = sel.get(i);
+			Segment secondSegment = sel.get(i+1);
+			if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way
+				dirCounter++;
+			else
+				dirCounter--;
+		}
+		if ( dirCounter <= 0 )
+			direction = false;
+		else
+			direction = true;
+
+		Node lastNode = null;
+
+		// we need to calculate what the first node in the way is, we work from there
+		Segment firstSegment = sel.getFirst();
+		Segment secondSegment = sel.get(1);
+		if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to)
+			lastNode = firstSegment.from;
+		else
+			lastNode = firstSegment.to;
+
+		// go through each segment and flip them if required
+		for (Segment s : sel) {
+			Segment snew = new Segment(s);
+			boolean segDirection = s.from == lastNode;
+			// segDirection = true when the 'from' node occurs before the 'to' node in the Way 
+			if (direction != segDirection)
+			{    			
+				// reverse the segment's direction
+				Node n = snew.from;
+				snew.from = snew.to;
+				snew.to = n;
+				c.add(new ChangeCommand(s, snew));
+			}	
+
+			if (direction) // if its facing forwards,
+				lastNode = snew.to; // our next node is the 'to' one
+			else
+				lastNode = snew.from; // otherwise its the 'from' one
+		}
+
+		LinkedList<Segment> segments = new LinkedList<Segment>();
+
+		// Now we recreate the segment list, in the correct order of the direction
+		for (Segment s : sel) 
+			if (!direction) 
+				segments.addFirst(s);
+			else
+				segments.addLast(s);
+
+		// Check if the new segment list is actually different from the old one
+		// before we go and add a change command for it
+		for(int i = 0; i < segments.size(); i++)
+			if (way.segments.get(i) != segments.get(i))
+			{
+				Way newWay = new Way(way);
+				newWay.segments.clear();
+				newWay.segments.addAll(segments);
+				c.add(new ChangeCommand(way, newWay));
+				break;
+			}
+
+		// Check we've got some change commands before we add a sequence command
 		if (c.size() != 0) {
 			NameVisitor v = new NameVisitor();
@@ -157,5 +158,5 @@
 		}
 		return null;
-    }
+	}
 
 	/**
@@ -168,26 +169,39 @@
 	 */
 	public static LinkedList<Segment> sortSegments(LinkedList<Segment> segments, boolean strict) {
-		
+
 		LinkedList<Segment> sortedSegments = new LinkedList<Segment>();
-		
+
 		while (!segments.isEmpty()) {
 			LinkedList<Segment> pivotList = new LinkedList<Segment>();
-			pivotList.add(segments.getFirst());
-			segments.removeFirst();
+			pivotList.add(firstSegment(segments));
+			segments.remove(pivotList.getLast());
 			boolean found;
 			do {
 				found = false;
+				//try working forwards first
 				for (Iterator<Segment> it = segments.iterator(); it.hasNext();) {
 					Segment ls = it.next();
 					if (ls.incomplete)
 						continue; // incomplete segments are never added to a new way
-					if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) {
+					if (ls.from == pivotList.getLast().to) {
 						pivotList.addLast(ls);
 						it.remove();
 						found = true;
-					} else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) {
-						pivotList.addFirst(ls);
-						it.remove(); 
-						found = true;
+					}
+				}
+				if(!found){
+					for (Iterator<Segment> it = segments.iterator(); it.hasNext();) {
+						Segment ls = it.next();
+						if (ls.incomplete)
+							continue; // incomplete segments are never added to a new way
+						if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) {
+							pivotList.addLast(ls);
+							it.remove();
+							found = true;
+						} else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) {
+							pivotList.addFirst(ls);
+							it.remove(); 
+							found = true;
+						}
 					}
 				}
@@ -195,5 +209,44 @@
 			sortedSegments.addAll(pivotList);
 		}
-	    return sortedSegments;
-	}
+		return sortedSegments;
+	}
+
+	/**
+	 * This method searches for a good segment to start a reorder from.
+	 * In most cases this will be a segment with a start node that occurs only
+	 * once in the way. In cases with loops, this could be any odd number. If no nodes
+	 * are referenced an odd number of times, then any segment is a good start point.
+	 */
+	public static Segment firstSegment(Collection<Segment> segments) {
+		HashMap<Node, Integer> refCount = new HashMap<Node, Integer>(segments.size()*2);
+		//loop through all segments and count up how many times each node is referenced
+		for (Segment seg : segments) {
+			if (!refCount.containsKey(seg.from))
+				refCount.put(seg.from, 0);
+			refCount.put(seg.from,refCount.get(seg.from)+1);
+
+			if (!refCount.containsKey(seg.to))
+				refCount.put(seg.to, 0);
+			refCount.put(seg.to,refCount.get(seg.to)+1);
+		}
+
+		//now look for start nodes that are referenced only once
+		for (Segment seg : segments)
+			if (refCount.get(seg.from) == 1)
+				return seg;
+		//now look for start nodes that are referenced only (2n+1)
+		for (Segment seg : segments)
+			if (refCount.get(seg.from) % 2 == 1)
+				return seg;
+		//now look for end nodes that are referenced only once
+		for (Segment seg : segments)
+			if (refCount.get(seg.to) == 1)
+				return seg;
+		//now look for end nodes that are referenced only (2n+1)
+		for (Segment seg : segments)
+			if (refCount.get(seg.to) % 2 == 1)
+				return seg;
+
+		return segments.iterator().next();
+	}    
 }
Index: src/org/openstreetmap/josm/actions/SaveActionBase.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 318)
+++ src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 319)
@@ -1,3 +1,3 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
+//License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.actions;
 
@@ -7,4 +7,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
@@ -37,5 +39,5 @@
 			return;
 
-		
+
 		File file = getFile(layer);
 		if (file == null)
@@ -48,5 +50,5 @@
 		Main.parent.repaint();
 	}
-	
+
 	protected abstract File getFile(OsmDataLayer layer);
 
@@ -57,44 +59,73 @@
 	 */
 	public boolean checkSaveConditions(OsmDataLayer layer) {
-        if (Main.map == null) {
-    		JOptionPane.showMessageDialog(Main.parent, tr("No document open so nothing to save."));
-    		return false;
-    	}
-    	if (isDataSetEmpty(layer) && JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(Main.parent,tr("The document contains no data. Save anyway?"), tr("Empty document"), JOptionPane.YES_NO_OPTION))
-    		return false;
-    	if (!Main.map.conflictDialog.conflicts.isEmpty()) {
-    		int answer = JOptionPane.showConfirmDialog(Main.parent, 
-    				tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),tr("Conflicts"), JOptionPane.YES_NO_OPTION);
-    		if (answer != JOptionPane.YES_OPTION)
-    			return false;
-    	}
-    	return true;
-    }
+		if (Main.map == null) {
+			JOptionPane.showMessageDialog(Main.parent, tr("No document open so nothing to save."));
+			return false;
+		}
+		if (isDataSetEmpty(layer) && JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog(Main.parent,tr("The document contains no data. Save anyway?"), tr("Empty document"), JOptionPane.YES_NO_OPTION))
+			return false;
+		if (!Main.map.conflictDialog.conflicts.isEmpty()) {
+			int answer = JOptionPane.showConfirmDialog(Main.parent, 
+					tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),tr("Conflicts"), JOptionPane.YES_NO_OPTION);
+			if (answer != JOptionPane.YES_OPTION)
+				return false;
+		}
+		return true;
+	}
 
 	public static File openFileDialog() {
-        JFileChooser fc = createAndOpenFileChooser(false, false);
-    	if (fc == null)
-    		return null;
-    
-    	File file = fc.getSelectedFile();
-    
-    	String fn = file.getPath();
-    	if (fn.indexOf('.') == -1) {
-    		FileFilter ff = fc.getFileFilter();
-    		if (ff instanceof ExtensionFileFilter)
-    			fn = "." + ((ExtensionFileFilter)ff).defaultExtension;
-    		else
-    			fn += ".osm";
-    		file = new File(fn);
-    	}
-        return file;
-    }
-	
+		JFileChooser fc = createAndOpenFileChooser(false, false);
+		if (fc == null)
+			return null;
+
+		File file = fc.getSelectedFile();
+
+		String fn = file.getPath();
+		if (fn.indexOf('.') == -1) {
+			FileFilter ff = fc.getFileFilter();
+			if (ff instanceof ExtensionFileFilter)
+				fn = "." + ((ExtensionFileFilter)ff).defaultExtension;
+			else
+				fn += ".osm";
+			file = new File(fn);
+		}
+		return file;
+	}
+
+	private static void copy(File src, File dst) throws IOException {
+		FileInputStream srcStream;
+		FileOutputStream dstStream;
+		try {
+			srcStream = new FileInputStream(src);
+			dstStream = new FileOutputStream(dst);
+		} catch (FileNotFoundException e) {
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not back up file.")+"\n"+e.getMessage());
+			return;
+		}
+		byte buf[] = new byte[1<<16];
+		int len;
+		while ((len = srcStream.read(buf)) != -1) {
+			dstStream.write(buf, 0, len);
+		}
+		srcStream.close();
+		dstStream.close();
+	}
+
 	public static void save(File file, OsmDataLayer layer) {
-	    try {
+		File tmpFile = null;
+		try {
 			if (ExtensionFileFilter.filters[ExtensionFileFilter.GPX].acceptName(file.getPath())) {
 				GpxExportAction.exportGpx(file, layer);
 			} else if (ExtensionFileFilter.filters[ExtensionFileFilter.OSM].acceptName(file.getPath())) {
+				// use a tmp file because if something errors out in the
+				// process of writing the file, we might just end up with
+				// a truncated file.  That can destroy lots of work.
+				if (file.exists()) {
+					tmpFile = new File(file.getPath() + "~");
+					copy(file, tmpFile);
+				}
 				OsmWriter.output(new FileOutputStream(file), new OsmWriter.All(layer.data, false));
+				if (!Main.pref.getBoolean("save.keepbackup"))
+					tmpFile.delete();
 			} else if (ExtensionFileFilter.filters[ExtensionFileFilter.CSV].acceptName(file.getPath())) {
 				JOptionPane.showMessageDialog(Main.parent, tr("CSV output not supported yet."));
@@ -109,6 +140,16 @@
 			JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
 		}
-    }
-	
+		try {
+			// if the file save failed, then the tempfile will not
+			// be deleted.  So, restore the backup if we made one.
+			if (tmpFile != null && tmpFile.exists()) {
+				copy(tmpFile, file);
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e.getMessage());
+		}
+	}
+
 	/**
 	 * Check the data set if it would be empty on save. It is empty, if it contains
Index: src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 318)
+++ src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 319)
@@ -94,9 +94,16 @@
 			if (osm.keys == null)
 				return s.equals("");
+			String search = caseSensitive ? s : s.toLowerCase();
 			for (Entry<String, String> e : osm.keys.entrySet()) {
 				String key = caseSensitive ? e.getKey() : e.getKey().toLowerCase();
 				String value = caseSensitive ? e.getValue() : e.getValue().toLowerCase();
-				String search = caseSensitive ? s : s.toLowerCase();
 				if (key.indexOf(search) != -1 || value.indexOf(search) != -1)
+					return true;
+			}
+			if (osm.user != null) {
+				String name = osm.user.name;
+				if (!caseSensitive)
+					name = name.toLowerCase();
+				if (name.indexOf(search) != -1)
 					return true;
 			}
Index: src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 318)
+++ src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 319)
@@ -6,5 +6,4 @@
 import java.awt.Graphics2D;
 import java.awt.Point;
-import java.awt.Polygon;
 import java.awt.Rectangle;
 import java.awt.geom.GeneralPath;
Index: src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 318)
+++ src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 319)
@@ -1,3 +1,3 @@
-// License: GPL. Copyright 2007 by Immanuel Scholz and others
+//License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.gui.layer;
 
@@ -104,9 +104,9 @@
 						throw new IOException(tr("No time for point {0} x {1}",p.latlon.lat(),p.latlon.lon()));
 					Date d = null;
-                    try {
-                        d = DateParser.parse(p.time);
-                    } catch (ParseException e) {
-                    	throw new IOException(tr("Cannot read time \"{0}\" from point {1} x {2}",p.time,p.latlon.lat(),p.latlon.lon()));
-                    }
+					try {
+						d = DateParser.parse(p.time);
+					} catch (ParseException e) {
+						throw new IOException(tr("Cannot read time \"{0}\" from point {1} x {2}",p.time,p.latlon.lat(),p.latlon.lon()));
+					}
 					gps.add(new TimedPoint(d, p.eastNorth));
 				}
@@ -130,8 +130,8 @@
 				ImageEntry e = new ImageEntry();
 				try {
-	                e.time = ExifReader.readTime(f);
-                } catch (ParseException e1) {
-                	continue;
-                }
+					e.time = ExifReader.readTime(f);
+				} catch (ParseException e1) {
+					continue;
+				}
 				if (e.time == null)
 					continue;
@@ -163,6 +163,6 @@
 	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
 	private MouseAdapter mouseAdapter;
-    private int currentImage;
-    
+	private int currentImage;
+
 	public static final class GpsTimeIncorrect extends Exception {
 		public GpsTimeIncorrect(String message, Throwable cause) {
@@ -218,6 +218,5 @@
 					Rectangle r = new Rectangle(p.x-e.icon.getIconWidth()/2, p.y-e.icon.getIconHeight()/2, e.icon.getIconWidth(), e.icon.getIconHeight());
 					if (r.contains(ev.getPoint())) {
-					    //						showImage(e);
-					    showImage(i-1);
+						showImage(i-1);
 						break;
 					}
@@ -236,7 +235,6 @@
 	}
 
-    //	private void showImage(final ImageEntry e) {
 	private void showImage(int i) {
-	    currentImage = i;
+		currentImage = i;
 		final JPanel p = new JPanel(new BorderLayout());
 		final ImageEntry e = data.get(currentImage);
@@ -273,34 +271,34 @@
 		cent.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent ev) {
-			    final ImageEntry e = data.get(currentImage);
-			    if (cent.getModel().isSelected())
-				Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
-			}
-		    });
+				final ImageEntry e = data.get(currentImage);
+				if (cent.getModel().isSelected())
+					Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
+			}
+		});
 
 		ActionListener nextprevAction = new ActionListener(){
 			public void actionPerformed(ActionEvent ev) {			    
-			    p.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
-			    if (ev.getActionCommand().equals("Next")) {
-				currentImage++; 
-				if(currentImage>=data.size()-1) next.setEnabled(false);
-				prev.setEnabled(true);
-			    } else {
-				currentImage--;
-				if(currentImage<=0) prev.setEnabled(false);
-				next.setEnabled(true);
-			    }
-			    
-			    final ImageEntry e = data.get(currentImage);
-			    if (scale.getModel().isSelected())
-				((JLabel)vp.getView()).setIcon(loadScaledImage(e.image, Math.max(vp.getWidth(), vp.getHeight())));
-			    else
-				((JLabel)vp.getView()).setIcon(new ImageIcon(e.image.getPath()));
-			    dlg.setTitle(e.image+" ("+e.coor.toDisplayString()+")");
-			    if (cent.getModel().isSelected())
-				Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
-			    p.setCursor(Cursor.getDefaultCursor());
-			}
-		    };
+				p.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+				if (ev.getActionCommand().equals("Next")) {
+					currentImage++; 
+					if(currentImage>=data.size()-1) next.setEnabled(false);
+					prev.setEnabled(true);
+				} else {
+					currentImage--;
+					if(currentImage<=0) prev.setEnabled(false);
+					next.setEnabled(true);
+				}
+
+				final ImageEntry e = data.get(currentImage);
+				if (scale.getModel().isSelected())
+					((JLabel)vp.getView()).setIcon(loadScaledImage(e.image, Math.max(vp.getWidth(), vp.getHeight())));
+				else
+					((JLabel)vp.getView()).setIcon(new ImageIcon(e.image.getPath()));
+				dlg.setTitle(e.image+" ("+e.coor.toDisplayString()+")");
+				if (cent.getModel().isSelected())
+					Main.map.mapView.zoomTo(e.pos, Main.map.mapView.getScale());
+				p.setCursor(Cursor.getDefaultCursor());
+			}
+		};
 		next.setActionCommand("Next");
 		prev.setActionCommand("Previous");
@@ -453,10 +451,10 @@
 	private void sync(File f) {
 		Date exifDate;
-        try {
-	        exifDate = ExifReader.readTime(f);
-        } catch (ParseException e) {
-        	JOptionPane.showMessageDialog(Main.parent, tr("The date in file \"{0}\" could not be parsed.", f.getName()));
-        	return;
-        }
+		try {
+			exifDate = ExifReader.readTime(f);
+		} catch (ParseException e) {
+			JOptionPane.showMessageDialog(Main.parent, tr("The date in file \"{0}\" could not be parsed.", f.getName()));
+			return;
+		}
 		if (exifDate == null) {
 			JOptionPane.showMessageDialog(Main.parent, tr("There is no EXIF time within the file \"{0}\".", f.getName()));
@@ -489,5 +487,5 @@
 				gpstimezone = Long.valueOf(time)*60*60*1000;
 				Main.pref.put("tagimages.delta", ""+delta);
-                Main.pref.put("tagimages.gpstimezone", time);
+				Main.pref.put("tagimages.gpstimezone", time);
 				calculatePosition();
 				return;
Index: src/org/openstreetmap/josm/gui/preferences/CsvPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/CsvPreference.java	(revision 318)
+++ src/org/openstreetmap/josm/gui/preferences/CsvPreference.java	(revision 319)
@@ -4,5 +4,4 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import javax.swing.Box;
 import javax.swing.JLabel;
 import javax.swing.JTextField;
@@ -31,5 +30,4 @@
 		gui.connection.add(new JLabel(tr("CSV import specification (empty: read from first line in data)")), GBC.eol());
 		gui.connection.add(csvImportString, GBC.eop().fill(GBC.HORIZONTAL));
-		gui.connection.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
     }
 
Index: src/org/openstreetmap/josm/gui/preferences/FilePreferences.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/FilePreferences.java	(revision 319)
+++ src/org/openstreetmap/josm/gui/preferences/FilePreferences.java	(revision 319)
@@ -0,0 +1,32 @@
+// License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.gui.preferences;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.GBC;
+
+/**
+ * Out of pure laziness, I add the file stuff to connection tab.
+ * Feel free to fix this.
+ * 
+ * @author imi
+ */
+public class FilePreferences implements PreferenceSetting {
+
+	private JCheckBox keepBackup = new JCheckBox(tr("Keep backup files"));
+	
+	public void addGui(PreferenceDialog gui) {
+		keepBackup.setSelected(Main.pref.getBoolean("save.keepbackup"));
+		keepBackup.setToolTipText(tr("When saving, keep backup files ending with a ~"));
+		gui.connection.add(keepBackup, GBC.eol().insets(20,0,0,0));
+		gui.connection.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
+    }
+
+	public void ok() {
+		Main.pref.put("save.keepbackup", keepBackup.isSelected());
+    }
+}
Index: src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 318)
+++ src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 319)
@@ -103,4 +103,5 @@
 		settings.add(new ServerAccessPreference());
 		settings.add(new CsvPreference());
+		settings.add(new FilePreferences());
 		settings.add(new ProjectionPreference());
 		settings.add(new TaggingPresetPreference());
Index: src/org/openstreetmap/josm/io/IncompleteDownloader.java
===================================================================
--- src/org/openstreetmap/josm/io/IncompleteDownloader.java	(revision 318)
+++ src/org/openstreetmap/josm/io/IncompleteDownloader.java	(revision 319)
@@ -10,8 +10,15 @@
 import java.io.InputStreamReader;
 import java.io.StringReader;
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.ArrayList;
+
+import javax.swing.JOptionPane;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
@@ -20,12 +27,7 @@
 import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-
-import javax.swing.JOptionPane;
-import org.openstreetmap.josm.command.ChangeCommand;
-import org.openstreetmap.josm.command.Command;
-import org.openstreetmap.josm.command.SequenceCommand;
-
-import uk.co.wilson.xml.MinML2;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -80,5 +82,5 @@
 	}
 
-	private static class SegmentParser extends MinML2 {
+	private static class SegmentParser extends DefaultHandler {
 		public long from, to;
 		@Override public void startElement(String ns, String lname, String qname, Attributes a) {
@@ -133,5 +135,10 @@
 				segBuilder.append(line+"\n");
 			SegmentParser segmentParser = new SegmentParser();
-			segmentParser.parse(new StringReader(segBuilder.toString()));
+			try {
+		        SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(new StringReader(segBuilder.toString())), segmentParser);
+	        } catch (ParserConfigurationException e1) {
+	        	e1.printStackTrace(); // broken SAXException chaining
+	        	throw new SAXException(e1);
+	        }
 			if (segmentParser.from == 0 || segmentParser.to == 0)
 				throw new SAXException("Invalid segment response.");
Index: src/org/openstreetmap/josm/io/OsmIdReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmIdReader.java	(revision 318)
+++ src/org/openstreetmap/josm/io/OsmIdReader.java	(revision 319)
@@ -11,8 +11,11 @@
 import java.util.Map;
 
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-
-import uk.co.wilson.xml.MinML2;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -21,5 +24,5 @@
  * @author Imi
  */
-public class OsmIdReader extends MinML2 {
+public class OsmIdReader extends DefaultHandler {
 
 	private boolean cancel;
@@ -41,5 +44,10 @@
         this.in = new InputStreamReader(in, "UTF-8");
 		try {
-	        parse(this.in);
+	        SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(this.in), this);
+        } catch (ParserConfigurationException e) {
+        	if (!cancel) {
+        		e.printStackTrace(); // broken SAXException chaining
+        		throw new SAXException(e);
+        	}
         } catch (SAXException e) {
         	if (!cancel)
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 318)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(revision 319)
@@ -15,4 +15,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
 
 import org.openstreetmap.josm.Main;
@@ -31,7 +34,7 @@
 import org.openstreetmap.josm.tools.DateParser;
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-
-import uk.co.wilson.xml.MinML2;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -103,5 +106,5 @@
 	private HashSet<String> allowedVersions = new HashSet<String>();
 
-	private class Parser extends MinML2 {
+	private class Parser extends DefaultHandler {
 		/**
 		 * The current osm primitive to be read.
@@ -296,5 +299,11 @@
 
 		// phase 1: Parse nodes and read in raw segments and ways
-		osm.new Parser().parse(new InputStreamReader(source, "UTF-8"));
+		InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
+		try {
+	        SAXParserFactory.newInstance().newSAXParser().parse(inputSource, osm.new Parser());
+        } catch (ParserConfigurationException e1) {
+        	e1.printStackTrace(); // broken SAXException chaining
+        	throw new SAXException(e1);
+        }
 		if (pleaseWaitDlg != null) {
 			pleaseWaitDlg.progress.setValue(0);
Index: src/org/openstreetmap/josm/io/RawGpsReader.java
===================================================================
--- src/org/openstreetmap/josm/io/RawGpsReader.java	(revision 318)
+++ src/org/openstreetmap/josm/io/RawGpsReader.java	(revision 319)
@@ -14,4 +14,7 @@
 import java.util.Stack;
 
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
@@ -19,7 +22,7 @@
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerProducers;
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-
-import uk.co.wilson.xml.MinML2;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -46,5 +49,5 @@
 	public Collection<Marker> markerData = new ArrayList<Marker>();
 
-	private class Parser extends MinML2 {
+	private class Parser extends DefaultHandler {
 		/**
 		 * Current track to be read. The last entry is the current trkpt.
@@ -127,5 +130,11 @@
 		this.relativeMarkerPath = relativeMarkerPath;
 		Parser parser = new Parser();
-		parser.parse(new InputStreamReader(source, "UTF-8"));
+		InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
+		try {
+			SAXParserFactory.newInstance().newSAXParser().parse(inputSource, parser);
+        } catch (ParserConfigurationException e) {
+        	e.printStackTrace(); // broken SAXException chaining
+        	throw new SAXException(e);
+        }
 	}
 }
Index: src/org/openstreetmap/josm/plugins/PluginDownloader.java
===================================================================
--- src/org/openstreetmap/josm/plugins/PluginDownloader.java	(revision 318)
+++ src/org/openstreetmap/josm/plugins/PluginDownloader.java	(revision 319)
@@ -65,5 +65,5 @@
 	}
 
-	private static final Pattern wiki = Pattern.compile("^</td></tr><tr><td><a class=\"ext-link\" href=\"([^\"]*)\"><span class=\"icon\">([^<]*)</span></a></td><td>[^<]*</td><td>([^<]*)</td><td>(.*)");
+	private static final Pattern wiki = Pattern.compile("^</td></tr><tr><td><a class=\"ext-link\" href=\"([^\"]*)\"><span class=\"icon\">([^<]*)</span></a></td><td>([^<]*)</td><td>([^<].*)</td><td>(.*)");
 
 	public static int downloadDescription() {
@@ -109,6 +109,7 @@
 			b.append("    <name>"+escape(m.group(2))+"</name>\n");
 			b.append("    <resource>"+escape(m.group(1))+"</resource>\n");
-			b.append("    <description>"+escape(m.group(3))+"</description>\n");
-			b.append("    <version>"+escape(m.group(4))+"</version>\n");
+			b.append("    <author>"+escape(m.group(3))+"</author>\n");
+			b.append("    <description>"+escape(m.group(4))+"</description>\n");
+			b.append("    <version>"+escape(m.group(5))+"</version>\n");
 			b.append("  </plugin>\n");
 		}
Index: src/org/openstreetmap/josm/tools/XmlObjectParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 318)
+++ src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 319)
@@ -14,8 +14,10 @@
 import java.util.concurrent.BlockingQueue;
 
+import javax.xml.parsers.SAXParserFactory;
+
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-
-import uk.co.wilson.xml.MinML2;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -47,5 +49,5 @@
 	}
 
-	private class Parser extends MinML2 {
+	private class Parser extends DefaultHandler {
 		Stack<Object> current = new Stack<Object>();
 		String characters = "";
@@ -169,5 +171,5 @@
 			@Override public void run() {
 				try {
-					parser.parse(in);
+			        SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(in), parser);
 				} catch (Exception e) {
 					try {
