Index: src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 101)
+++ src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java	(revision 102)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Segment;
@@ -88,4 +89,16 @@
 				return;
 
+			if ((e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) == 0) {
+				// moving the new point to the perpendicular point
+				EastNorth A = s.from.eastNorth;
+				EastNorth B = s.to.eastNorth;
+				double ab = A.distance(B);
+				double nb = n.eastNorth.distance(B);
+				double na = n.eastNorth.distance(A);
+				double q = (nb-na+ab)/ab/2;
+				n.eastNorth = new EastNorth(B.east() + q*(A.east()-B.east()), B.north() + q*(A.north()-B.north()));
+				n.coor = Main.proj.eastNorth2latlon(n.eastNorth);
+			}
+			
 			Collection<Command> cmds = new LinkedList<Command>();
 			cmds.add(c);
Index: src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 101)
+++ src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 102)
@@ -238,5 +238,5 @@
 	 */
 	private boolean match(Segment ls1, Segment ls2) {
-		if (ls1.id == ls2.id)
+		if (ls1.id == ls2.id && ls1.id != 0)
 			return true;
 		if (ls1.incomplete || ls2.incomplete)
@@ -294,5 +294,5 @@
 			if (my.realEqual(other))
 				return true; // no merge needed.
-			if (my.id == other.id) {
+			if (my.id == other.id && my.id != 0) {
 				if (my instanceof Segment && ((Segment)my).incomplete)
 					return false; // merge always over an incomplete
Index: src/org/openstreetmap/josm/gui/ConflictResolver.java
===================================================================
--- src/org/openstreetmap/josm/gui/ConflictResolver.java	(revision 101)
+++ src/org/openstreetmap/josm/gui/ConflictResolver.java	(revision 102)
@@ -120,17 +120,16 @@
 	}
 
-	public final List<ConflictItem> conflicts;
+	public final List<ConflictItem> conflicts = new ArrayList<ConflictItem>();
 
 	private final ConflictTableModel my = new ConflictTableModel(Resolution.MY);
-	private final JTable myTable = new JTable(my);
+	private final JTable myTable;
 	private final ConflictTableModel their = new ConflictTableModel(Resolution.THEIR);
-	private final JTable theirTable = new JTable(their);
+	private final JTable theirTable;
 	private final ConflictTableModel resolve = new ConflictTableModel(null);
-	private final JTable resolveTable = new JTable(resolve);
+	private final JTable resolveTable;
 
 	
 	public ConflictResolver(Map<OsmPrimitive, OsmPrimitive> conflicts) {
 		super(new GridBagLayout());
-		this.conflicts = new ArrayList<ConflictItem>();
 		Collection<ConflictItem> possibleConflicts = new ArrayList<ConflictItem>();
 		possibleConflicts.add(new DeleteConflict());
@@ -161,4 +160,10 @@
 			throw new RuntimeException("No conflicts but in conflict list:\n" + Arrays.toString(conflicts.entrySet().toArray()));
 
+		// have to initialize the JTables here and not in the declaration, because its constructor
+		// may access this.conflicts (indirectly)
+		myTable = new JTable(my);
+		theirTable = new JTable(their);
+		resolveTable = new JTable(resolve);
+		
 		myTable.setPreferredScrollableViewportSize(new Dimension(250,70));
 		theirTable.setPreferredScrollableViewportSize(new Dimension(250,70));
Index: src/org/openstreetmap/josm/gui/MapMover.java
===================================================================
--- src/org/openstreetmap/josm/gui/MapMover.java	(revision 101)
+++ src/org/openstreetmap/josm/gui/MapMover.java	(revision 102)
@@ -2,4 +2,5 @@
 
 import java.awt.Cursor;
+import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
@@ -32,5 +33,8 @@
 	    public void actionPerformed(ActionEvent e) {
 	    	if (action.equals("+") || action.equals("-")) {
-	    		MouseWheelEvent we = new MouseWheelEvent(nc, e.getID(), e.getWhen(), e.getModifiers(), nc.getMousePosition().x, nc.getMousePosition().y, 0, false, MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, action.equals("+") ? -1 : 1);
+	    		Point mouse = nc.getMousePosition();
+	    		if (mouse == null)
+	    			mouse = new Point((int)nc.getBounds().getCenterX(), (int)nc.getBounds().getCenterY());
+	    		MouseWheelEvent we = new MouseWheelEvent(nc, e.getID(), e.getWhen(), e.getModifiers(), mouse.x, mouse.y, 0, false, MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, action.equals("+") ? -1 : 1);
 	    		mouseWheelMoved(we);
 	    	} else {
Index: src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 101)
+++ src/org/openstreetmap/josm/gui/layer/GeoImageLayer.java	(revision 102)
@@ -53,4 +53,5 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
+import org.openstreetmap.josm.tools.DateParser;
 import org.openstreetmap.josm.tools.ExifReader;
 import org.openstreetmap.josm.tools.GBC;
@@ -97,5 +98,5 @@
 						if (!m.matches())
 							throw new IOException("Cannot read time from point "+p.latlon.lat()+","+p.latlon.lon());
-						Date d = dateFormat.parse(m.group(1)+" "+m.group(2));
+						Date d = DateParser.parse(m.group(1)+" "+m.group(2));
 						gps.add(new TimedPoint(d, p.eastNorth));
 						if (last != null && last.after(d))
@@ -381,5 +382,5 @@
 				return;
 			try {
-				delta = dateFormat.parse(gpsText.getText()).getTime() - exifDate.getTime();
+				delta = DateParser.parse(gpsText.getText()).getTime() - exifDate.getTime();
 				Main.pref.put("tagimages.delta", ""+delta);
 				String time = gpsTimezone.getText();
Index: src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 101)
+++ src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 102)
@@ -10,4 +10,5 @@
 import java.util.LinkedList;
 
+import javax.swing.AbstractAction;
 import javax.swing.Icon;
 import javax.swing.JColorChooser;
@@ -23,4 +24,8 @@
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.gui.MapView;
@@ -36,4 +41,30 @@
  */
 public class RawGpsLayer extends Layer implements PreferenceChangedListener {
+
+	public class ConvertToOsmAction extends AbstractAction {
+		public ConvertToOsmAction() {
+			super("Convert layer to OSM");
+        }
+		public void actionPerformed(ActionEvent e) {
+			DataSet ds = new DataSet();
+			for (Collection<GpsPoint> c : data) {
+				Way w = new Way();
+				Node start = null;
+				for (GpsPoint p : c) {
+					Node end = new Node(p.latlon);
+					ds.nodes.add(end);
+					if (start != null) {
+						Segment segment = new Segment(start,end);
+						w.segments.add(segment);
+						ds.segments.add(segment);
+					}
+					start = end;
+				}
+				ds.ways.add(w);
+			}
+			Main.main.addLayer(new OsmDataLayer(ds, "Data Layer", true));
+			Main.main.removeLayer(RawGpsLayer.this);
+        }
+    }
 
 	public static class GpsPoint {
@@ -184,4 +215,6 @@
 		menu.add(tagimage);
 		
+		menu.add(new JMenuItem(new ConvertToOsmAction()));
+		
 		menu.addSeparator();
 		menu.add(new LayerListPopup.InfoAction(this));
Index: src/org/openstreetmap/josm/test/DateParserTest.java
===================================================================
--- src/org/openstreetmap/josm/test/DateParserTest.java	(revision 102)
+++ src/org/openstreetmap/josm/test/DateParserTest.java	(revision 102)
@@ -0,0 +1,30 @@
+package org.openstreetmap.josm.test;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.openstreetmap.josm.tools.DateParser;
+
+public class DateParserTest extends TestCase {
+
+	public void testWrong() throws Exception {
+	    try {
+	    	DateParser.parse("imi");
+	    	assertTrue(false);
+	    } catch (ParseException pe) {
+	    }
+    }
+	
+	public void testRight() throws Exception {
+		Date d = new SimpleDateFormat("dd MM yyyy HH mm ss SSS Z").parse("23 11 2001 23 05 42 123 +0100");
+		Date d2 = new Date(d.getTime()-123);
+		assertEquals(d2, DateParser.parse("11/23/2001 23:05:42"));
+		assertEquals(d2, DateParser.parse("11/23/2001T23:05:42"));
+		assertEquals(d2, DateParser.parse("11/23/2001T23:05:42+001"));
+        assertEquals(d, DateParser.parse("11/23/2001T23:05:42.123"));
+		assertEquals(d, DateParser.parse("11/23/2001T23:05:42.123+001"));
+    }
+}
Index: src/org/openstreetmap/josm/test/MergeVisitorTest.java
===================================================================
--- src/org/openstreetmap/josm/test/MergeVisitorTest.java	(revision 101)
+++ src/org/openstreetmap/josm/test/MergeVisitorTest.java	(revision 102)
@@ -48,7 +48,8 @@
 		n.modified = true;
 		dsNode.modified = true;
-		v.visit(n);
-		assertEquals(1, v.conflicts.size());
-		assertFalse(n.equals(dsNode));
+		n.id = 1;
+		dsNode.id = 1;
+		v.visit(n);
+		assertEquals(1, v.conflicts.size());
 	}
 	public void testNodesConflict() {
@@ -91,4 +92,27 @@
 	}
 
+	public void testNoConflictNewNodesMerged() {
+		assertEquals(0, n.id);
+		assertEquals(0, dsNode.id);
+		v.visit(n);
+		v.fixReferences();
+		assertEquals(0,v.conflicts.size());
+		assertTrue(ds.nodes.contains(n));
+		assertEquals(2, ds.nodes.size());
+	}
+
+	/**
+	 * Test that two new segments that have different from/to are not merged
+	 */
+	@Bug(101)
+	public void testNewSegmentNotMerged() {
+		v.visit(n);
+		Segment s1 = new Segment(n, dsNode);
+		v.visit(s1);
+		Segment s2 = new Segment(dsNode, n);
+		v.visit(s2);
+		assertEquals(2, ds.segments.size());
+	}
+	
 	public void testFixReferencesConflicts() {
 		// make two nodes mergable
@@ -198,5 +222,5 @@
 		assertSame("Do not import incomplete segments when merging ways.", s, w.segments.iterator().next());
 	}
-	
+		
 	/**
 	 * Create that amount of nodes and add them to the dataset. The id will be 1,2,3,4...
Index: src/org/openstreetmap/josm/tools/DateParser.java
===================================================================
--- src/org/openstreetmap/josm/tools/DateParser.java	(revision 102)
+++ src/org/openstreetmap/josm/tools/DateParser.java	(revision 102)
@@ -0,0 +1,29 @@
+package org.openstreetmap.josm.tools;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Tries to parse a date as good as it can.
+ * 
+ * @author Immanuel.Scholz
+ */
+public class DateParser {
+
+	private static final String[] formats = {
+		"MM/dd/yyyy HH:mm:ss",
+		"MM/dd/yyyy'T'HH:mm:ss.SSSZ",
+		"MM/dd/yyyy'T'HH:mm:ss.SSS",
+		"MM/dd/yyyy'T'HH:mm:ssZ",
+		"MM/dd/yyyy'T'HH:mm:ss",
+	};
+	
+	public static Date parse(String d) throws ParseException {
+		for (String parse : formats) {
+			SimpleDateFormat sdf = new SimpleDateFormat(parse);
+			try {return sdf.parse(d);} catch (ParseException pe) {}
+		}
+		throw new ParseException("No applicable parse format", 0);
+	}
+}
Index: src/org/openstreetmap/josm/tools/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/tools/SearchCompiler.java	(revision 101)
+++ src/org/openstreetmap/josm/tools/SearchCompiler.java	(revision 102)
@@ -20,5 +20,5 @@
 		abstract public boolean match(OsmPrimitive osm);
 	}
-	
+
 	private static class Always extends Match {
 		@Override public boolean match(OsmPrimitive osm) {
@@ -35,5 +35,5 @@
 		@Override public String toString() {return "!"+match;}
 	}
-	
+
 	private static class And extends Match {
 		private Match lhs;
@@ -45,5 +45,5 @@
 		@Override public String toString() {return lhs+" && "+rhs;}
 	}
-	
+
 	private static class Or extends Match {
 		private Match lhs;
@@ -55,5 +55,5 @@
 		@Override public String toString() {return lhs+" || "+rhs;}
 	}
-	
+
 	private static class Id extends Match {
 		private long id;
@@ -64,5 +64,5 @@
 		@Override public String toString() {return "id="+id;}
 	}
-	
+
 	private static class KeyValue extends Match {
 		private String key;
@@ -111,6 +111,12 @@
 		@Override public String toString() {return "type="+type;}
 	}
-
 	
+	private static class Modified extends Match {
+		@Override public boolean match(OsmPrimitive osm) {
+			return osm.modified;
+		}
+		@Override public String toString() {return "modified";}
+	}
+
 	public static Match compile(String searchStr) {
 		return new SearchCompiler().parse(new PushbackReader(new StringReader(searchStr)));
@@ -152,22 +158,22 @@
 			default:
 				s = new StringBuilder();
-				for (;;) {
-					s.append(c);
-					next = search.read();
-					if (next == -1) {
-						if (s.toString().equals("OR"))
-							return "|";
-						return " "+s.toString();
-					}
-					c = (char)next;
-					if (c == ' ' || c == '\t' || c == ':' || c == '"') {
-						if (c == ':')
-							return ":"+s.toString();
-						search.unread(next);
-						if (s.toString().equals("OR"))
-							return "|";
-						return " "+s.toString();
-					}
+			for (;;) {
+				s.append(c);
+				next = search.read();
+				if (next == -1) {
+					if (s.toString().equals("OR"))
+						return "|";
+					return " "+s.toString();
 				}
+				c = (char)next;
+				if (c == ' ' || c == '\t' || c == ':' || c == '"') {
+					if (c == ':')
+						return ":"+s.toString();
+					search.unread(next);
+					if (s.toString().equals("OR"))
+						return "|";
+					return " "+s.toString();
+				}
+			}
 			}
 		} catch (IOException e) {
@@ -175,6 +181,6 @@
 		}		
 	}
-	
-	
+
+
 	private boolean notKey = false;
 	private boolean notValue = false;
@@ -185,5 +191,9 @@
 		String value = token.substring(1);
 		if (key == null) {
-			Match c = new Any(value);
+			Match c = null;
+			if (value.equals("modified"))
+				c = new Modified();
+			else
+				c = new Any(value);
 			if (notValue)
 				return new Not(c);
@@ -207,5 +217,5 @@
 		return c;
 	}
-	
+
 	private Match parse(PushbackReader search) {
 		Match result = null;
@@ -231,8 +241,8 @@
 				else
 					result = or ? new Or(result, current) : new And(result, current);
-				key = null;
-				notKey = false;
-				notValue = false;
-				or = false;
+					key = null;
+					notKey = false;
+					notValue = false;
+					or = false;
 			}
 		}
