Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AddressDialog.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AddressDialog.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AddressDialog.java	(revision 23190)
@@ -20,61 +20,61 @@
 @SuppressWarnings("serial")
 public class AddressDialog extends ExtendedDialog {
-	private static String lhousenum,lstreetname;
-	private static boolean inc = true;
-	private JTextField housenum = new JTextField();
-	private JTextField streetname = new JTextField();
-	private Choice cincdec = new Choice();
+    private static String lhousenum,lstreetname;
+    private static boolean inc = true;
+    private JTextField housenum = new JTextField();
+    private JTextField streetname = new JTextField();
+    private Choice cincdec = new Choice();
 
-	private JPanel panel = new JPanel(new GridBagLayout());
-	private void addLabelled(String str, Component c) {
-		JLabel label = new JLabel(str);
-		panel.add(label, GBC.std());
-		label.setLabelFor(c);
-		panel.add(c, GBC.eol().fill(GBC.HORIZONTAL));
-	}
+    private JPanel panel = new JPanel(new GridBagLayout());
+    private void addLabelled(String str, Component c) {
+        JLabel label = new JLabel(str);
+        panel.add(label, GBC.std());
+        label.setLabelFor(c);
+        panel.add(c, GBC.eol().fill(GBC.HORIZONTAL));
+    }
 
-	public AddressDialog() {
-		super(Main.parent, tr("Building address"), 
-				new String[] { tr("OK"), tr("Cancel") },
-				true);
-		
-		contentInsets = new Insets(15,15,5,15);
-		setButtonIcons(new String[] {"ok.png", "cancel.png" });
-		
-		addLabelled(tr("House number:"),housenum);
-		addLabelled(tr("Street Name:"),streetname);
-		housenum.setText(nextHouseNum());
-		streetname.setText(lstreetname);
+    public AddressDialog() {
+        super(Main.parent, tr("Building address"),
+                new String[] { tr("OK"), tr("Cancel") },
+                true);
 
-		cincdec.add(tr("Increment"));
-		cincdec.add(tr("Decrement"));
-		cincdec.select(inc?0:1);
-		addLabelled(tr("Numbers:"), cincdec);
+        contentInsets = new Insets(15,15,5,15);
+        setButtonIcons(new String[] {"ok.png", "cancel.png" });
 
-		setContent(panel);
-		setupDialog();
-		setVisible(true);
-	}
-	
-	private static String nextHouseNum() {
-		if (lhousenum==null) return "";
-		try {
-			Integer num = NumberFormat.getInstance().parse(lhousenum).intValue();
-			if (inc) num=num+2; else num = num-2;
-			return num.toString();
-		} catch (ParseException e) {			
-			return lhousenum;
-		}
-	}
-	public void saveValues() {
-		lhousenum = housenum.getText();
-		lstreetname = streetname.getText();
-		inc = cincdec.getSelectedIndex() == 0;		
-	}
-	public String getHouseNum() {
-		return housenum.getText();
-	}
-	public String getStreetName() {
-		return streetname.getText();
-	}
+        addLabelled(tr("House number:"),housenum);
+        addLabelled(tr("Street Name:"),streetname);
+        housenum.setText(nextHouseNum());
+        streetname.setText(lstreetname);
+
+        cincdec.add(tr("Increment"));
+        cincdec.add(tr("Decrement"));
+        cincdec.select(inc?0:1);
+        addLabelled(tr("Numbers:"), cincdec);
+
+        setContent(panel);
+        setupDialog();
+        setVisible(true);
+    }
+
+    private static String nextHouseNum() {
+        if (lhousenum==null) return "";
+        try {
+            Integer num = NumberFormat.getInstance().parse(lhousenum).intValue();
+            if (inc) num=num+2; else num = num-2;
+            return num.toString();
+        } catch (ParseException e) {
+            return lhousenum;
+        }
+    }
+    public void saveValues() {
+        lhousenum = housenum.getText();
+        lstreetname = streetname.getText();
+        inc = cincdec.getSelectedIndex() == 0;
+    }
+    public String getHouseNum() {
+        return housenum.getText();
+    }
+    public String getStreetName() {
+        return streetname.getText();
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AdvancedSettingsDialog.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AdvancedSettingsDialog.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AdvancedSettingsDialog.java	(revision 23190)
@@ -18,48 +18,48 @@
 
 public class AdvancedSettingsDialog extends ExtendedDialog {
-	private TagEditorModel tagsModel = new TagEditorModel();
+    private TagEditorModel tagsModel = new TagEditorModel();
 
-	private JCheckBox cBigMode = new JCheckBox(tr("Big buildings mode"));
-	private JCheckBox cSoftCur = new JCheckBox(tr("Rotate crosshair"));
+    private JCheckBox cBigMode = new JCheckBox(tr("Big buildings mode"));
+    private JCheckBox cSoftCur = new JCheckBox(tr("Rotate crosshair"));
 
-	public AdvancedSettingsDialog() {
-		super(Main.parent, tr("Advanced settings"),
-				new String[] { tr("OK"), tr("Cancel") },
-				true);
-		contentInsets = new Insets(15, 15, 5, 15);
-		setButtonIcons(new String[] { "ok.png", "cancel.png" });
+    public AdvancedSettingsDialog() {
+        super(Main.parent, tr("Advanced settings"),
+                new String[] { tr("OK"), tr("Cancel") },
+                true);
+        contentInsets = new Insets(15, 15, 5, 15);
+        setButtonIcons(new String[] { "ok.png", "cancel.png" });
 
-		final JPanel panel = new JPanel(new GridBagLayout());
-		panel.add(new JLabel(tr("Buildings tags:")), GBC.eol().fill(GBC.HORIZONTAL));
+        final JPanel panel = new JPanel(new GridBagLayout());
+        panel.add(new JLabel(tr("Buildings tags:")), GBC.eol().fill(GBC.HORIZONTAL));
 
-		for (Entry<String, String> entry : ToolSettings.getTags().entrySet()) {
-			tagsModel.add(entry.getKey(), entry.getValue());
-		}
-		panel.add(new TagEditorPanel(tagsModel, null), GBC.eop().fill(GBC.BOTH));
+        for (Entry<String, String> entry : ToolSettings.getTags().entrySet()) {
+            tagsModel.add(entry.getKey(), entry.getValue());
+        }
+        panel.add(new TagEditorPanel(tagsModel, null), GBC.eop().fill(GBC.BOTH));
 
-		panel.add(cBigMode, GBC.eol().fill(GBC.HORIZONTAL));
-		panel.add(cSoftCur, GBC.eol().fill(GBC.HORIZONTAL));
+        panel.add(cBigMode, GBC.eol().fill(GBC.HORIZONTAL));
+        panel.add(cSoftCur, GBC.eol().fill(GBC.HORIZONTAL));
 
-		cBigMode.setSelected(ToolSettings.isBBMode());
-		cSoftCur.setSelected(ToolSettings.isSoftCursor());
+        cBigMode.setSelected(ToolSettings.isBBMode());
+        cSoftCur.setSelected(ToolSettings.isSoftCursor());
 
-		setContent(panel);
+        setContent(panel);
 
-		setupDialog();
-		setVisible(true);
-	}
+        setupDialog();
+        setVisible(true);
+    }
 
-	public boolean isBBMode() {
-		return cBigMode.isSelected();
-	}
+    public boolean isBBMode() {
+        return cBigMode.isSelected();
+    }
 
-	public boolean isSoftCursor() {
-		return cSoftCur.isSelected();
-	}
+    public boolean isSoftCursor() {
+        return cSoftCur.isSelected();
+    }
 
-	public void saveSettings() {
-		tagsModel.applyToTags(ToolSettings.getTags());
-		ToolSettings.setBBMode(isBBMode());
-		ToolSettings.setSoftCursor(isSoftCursor());
-	}
+    public void saveSettings() {
+        tagsModel.applyToTags(ToolSettings.getTags());
+        ToolSettings.setBBMode(isBBMode());
+        ToolSettings.setSoftCursor(isSoftCursor());
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AngleSnap.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AngleSnap.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/AngleSnap.java	(revision 23190)
@@ -11,90 +11,90 @@
 
 public class AngleSnap {
-	private static final double PI_2 = Math.PI / 2;
-	TreeSet<Double> snapSet = new TreeSet<Double>();
+    private static final double PI_2 = Math.PI / 2;
+    TreeSet<Double> snapSet = new TreeSet<Double>();
 
-	public void clear() {
-		snapSet.clear();
-	}
+    public void clear() {
+        snapSet.clear();
+    }
 
-	public void addSnap(double snap) {
-		snapSet.add(snap % PI_2);
-	}
+    public void addSnap(double snap) {
+        snapSet.add(snap % PI_2);
+    }
 
-	public Double addSnap(Node[] nodes) {
-		if (nodes.length == 2) {
-			EastNorth p1, p2;
-			p1 = latlon2eastNorth(((Node) nodes[0]).getCoor());
-			p2 = latlon2eastNorth(((Node) nodes[1]).getCoor());
-			double heading = p1.heading(p2);
-			addSnap(heading);
-			addSnap(heading + Math.PI / 4);
-			return heading;
-		} else {
-			return null;
-		}
-	}
+    public Double addSnap(Node[] nodes) {
+        if (nodes.length == 2) {
+            EastNorth p1, p2;
+            p1 = latlon2eastNorth(((Node) nodes[0]).getCoor());
+            p2 = latlon2eastNorth(((Node) nodes[1]).getCoor());
+            double heading = p1.heading(p2);
+            addSnap(heading);
+            addSnap(heading + Math.PI / 4);
+            return heading;
+        } else {
+            return null;
+        }
+    }
 
-	public void addSnap(Way way) {
-		for (Pair<Node, Node> pair : way.getNodePairs(false)) {
-			EastNorth a, b;
-			a = latlon2eastNorth(pair.a.getCoor());
-			b = latlon2eastNorth(pair.b.getCoor());
-			double heading = a.heading(b);
-			addSnap(heading);
-		}
-	}
+    public void addSnap(Way way) {
+        for (Pair<Node, Node> pair : way.getNodePairs(false)) {
+            EastNorth a, b;
+            a = latlon2eastNorth(pair.a.getCoor());
+            b = latlon2eastNorth(pair.b.getCoor());
+            double heading = a.heading(b);
+            addSnap(heading);
+        }
+    }
 
-	public Double getAngle() {
-		if (snapSet.isEmpty()) {
-			return null;
-		}
-		double first = snapSet.first();
-		double last = snapSet.last();
-		if (first < Math.PI / 4 && last > Math.PI / 4) {
-			last -= PI_2;
-		}
-		if (Math.abs(first - last) < 0.001) {
-			double center = (first + last) / 2;
-			if (center < 0)
-				center += PI_2;
-			return center;
-		} else {
-			return null;
-		}
-	}
+    public Double getAngle() {
+        if (snapSet.isEmpty()) {
+            return null;
+        }
+        double first = snapSet.first();
+        double last = snapSet.last();
+        if (first < Math.PI / 4 && last > Math.PI / 4) {
+            last -= PI_2;
+        }
+        if (Math.abs(first - last) < 0.001) {
+            double center = (first + last) / 2;
+            if (center < 0)
+                center += PI_2;
+            return center;
+        } else {
+            return null;
+        }
+    }
 
-	public double snapAngle(double angle) {
-		if (snapSet.isEmpty()) {
-			return angle;
-		}
-		int quadrant = (int) Math.floor(angle / PI_2);
-		double ang = angle % PI_2;
-		Double prev = snapSet.floor(ang);
-		if (prev == null)
-			prev = snapSet.last() - PI_2;
-		Double next = snapSet.ceiling(ang);
-		if (next == null)
-			next = snapSet.first() + PI_2;
+    public double snapAngle(double angle) {
+        if (snapSet.isEmpty()) {
+            return angle;
+        }
+        int quadrant = (int) Math.floor(angle / PI_2);
+        double ang = angle % PI_2;
+        Double prev = snapSet.floor(ang);
+        if (prev == null)
+            prev = snapSet.last() - PI_2;
+        Double next = snapSet.ceiling(ang);
+        if (next == null)
+            next = snapSet.first() + PI_2;
 
-		if (Math.abs(ang - next) > Math.abs(ang - prev)) {
-			if (Math.abs(ang - prev) > Math.PI / 8) {
-				return angle;
-			} else {
-				double ret = prev + PI_2 * quadrant;
-				if (ret < 0)
-					ret += 2 * Math.PI;
-				return ret;
-			}
-		} else {
-			if (Math.abs(ang - next) > Math.PI / 8) {
-				return angle;
-			} else {
-				double ret = next + PI_2 * quadrant;
-				if (ret > 2 * Math.PI)
-					ret -= 2 * Math.PI;
-				return ret;
-			}
-		}
-	}
+        if (Math.abs(ang - next) > Math.abs(ang - prev)) {
+            if (Math.abs(ang - prev) > Math.PI / 8) {
+                return angle;
+            } else {
+                double ret = prev + PI_2 * quadrant;
+                if (ret < 0)
+                    ret += 2 * Math.PI;
+                return ret;
+            }
+        } else {
+            if (Math.abs(ang - next) > Math.PI / 8) {
+                return angle;
+            } else {
+                double ret = next + PI_2 * quadrant;
+                if (ret > 2 * Math.PI)
+                    ret -= 2 * Math.PI;
+                return ret;
+            }
+        }
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/Building.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/Building.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/Building.java	(revision 23190)
@@ -28,234 +28,234 @@
 
 class Building {
-	private static final double eqlen = 40075004; // length of equator in metres
-	private final EastNorth[] en = new EastNorth[4];
-
-	double meter = 0;
-
-	private double len = 0;
-	private double width;
-	private double heading;
-	private AngleSnap angleSnap = new AngleSnap();
-	private Double drawingAngle;
-
-	public void clearAngleSnap() {
-		angleSnap.clear();
-		drawingAngle = null;
-	}
-
-	public void addAngleSnap(Node[] nodes) {
-		drawingAngle = angleSnap.addSnap(nodes);
-	}
-
-	public void addAngleSnap(Way way) {
-		angleSnap.addSnap(way);
-		if (drawingAngle == null) {
-			drawingAngle = angleSnap.getAngle();
-		}
-	}
-
-	public double getLength() {
-		return len;
-	}
-
-	public double getWidth() {
-		return width;
-	}
-
-	public boolean isRectDrawing() {
-		return drawingAngle != null && ToolSettings.getWidth() == 0 && ToolSettings.getLenStep() == 0;
-	}
-
-	public Double getDrawingAngle() {
-		return drawingAngle;
-	}
-
-	public void reset() {
-		len = 0;
-
-		for (int i = 0; i < 4; i++)
-			en[i] = null;
-	}
-
-	public EastNorth getPoint(int num) {
-		return en[num];
-	}
-
-	private void updMetrics() {
-		meter = 2 * Math.PI / (Math.cos(Math.toRadians(eastNorth2latlon(en[0]).lat())) * eqlen);
-		len = 0;
-	}
-
-	public void setBase(EastNorth base) {
-		en[0] = base;
-		updMetrics();
-	}
-
-	public void setBase(Node base) {
-		en[0] = latlon2eastNorth(base.getCoor());
-		updMetrics();
-	}
-
-	/**
-	 * @returns Projection of the point to the heading vector in metres
-	 */
-	private double projection1(EastNorth p) {
-		final EastNorth vec = en[0].sub(p);
-		return (Math.sin(heading) * vec.east() + Math.cos(heading) * vec.north()) / meter;
-	}
-
-	/**
-	 * @returns Projection of the point to the perpendicular of the heading
-	 *          vector in metres
-	 */
-	private double projection2(EastNorth p) {
-		final EastNorth vec = en[0].sub(p);
-		return (Math.cos(heading) * vec.east() - Math.sin(heading) * vec.north()) / meter;
-	}
-
-	private void updatePos() {
-		if (len == 0)
-			return;
-		final EastNorth p1 = en[0];
-		en[1] = new EastNorth(p1.east() + Math.sin(heading) * len * meter, p1.north() + Math.cos(heading) * len * meter);
-		en[2] = new EastNorth(p1.east() + Math.sin(heading) * len * meter + Math.cos(heading) * width * meter,
-				p1.north() + Math.cos(heading) * len * meter - Math.sin(heading) * width * meter);
-		en[3] = new EastNorth(p1.east() + Math.cos(heading) * width * meter,
-				p1.north() - Math.sin(heading) * width * meter);
-	}
-
-	public void setLengthWidth(double length, double width) {
-		this.len = length;
-		this.width = width;
-		updatePos();
-	}
-
-	public void setWidth(EastNorth p3) {
-		this.width = projection2(p3);
-		updatePos();
-	}
-
-	public void setPlace(EastNorth p2, double width, double lenstep, boolean ignoreConstraints) {
-		if (en[0] == null)
-			throw new IllegalStateException("setPlace() called without the base point");
-		this.heading = en[0].heading(p2);
-		if (!ignoreConstraints)
-			this.heading = angleSnap.snapAngle(this.heading);
-
-		this.width = width;
-		this.len = projection1(p2);
-		if (lenstep > 0 && !ignoreConstraints)
-			this.len = Math.round(this.len / lenstep) * lenstep;
-
-		updatePos();
-
-		Main.map.statusLine.setHeading(Math.toDegrees(heading));
-		if (this.drawingAngle != null && !ignoreConstraints) {
-			double ang = Math.toDegrees(heading - this.drawingAngle);
-			if (ang < 0)
-				ang += 360;
-			if (ang > 360)
-				ang -= 360;
-			Main.map.statusLine.setAngle(ang);
-		}
-	}
-
-	public void setPlaceRect(EastNorth p2) {
-		if (en[0] == null)
-			throw new IllegalStateException("SetPlaceRect() called without the base point");
-		if (!isRectDrawing())
-			throw new IllegalStateException("Invalid drawing mode");
-		heading = drawingAngle;
-		setLengthWidth(projection1(p2), projection2(p2));
-		Main.map.statusLine.setHeading(Math.toDegrees(heading));
-	}
-
-	public void angFix(EastNorth point) {
-		EastNorth en3 = en[2];
-		EastNorth mid = en[0].getCenter(en3);
-		double radius = en3.distance(mid);
-		heading = mid.heading(point);
-		heading = en[0].heading(mid.add(Math.sin(heading) * radius, Math.cos(heading) * radius));
-		setLengthWidth(projection1(en3), projection2(en3));
-		en[2] = en3;
-	}
-
-	public void paint(Graphics2D g, MapView mv) {
-		if (len == 0)
-			return;
-		GeneralPath b = new GeneralPath();
-		Point pp1 = mv.getPoint(eastNorth2latlon(en[0]));
-		Point pp2 = mv.getPoint(eastNorth2latlon(en[1]));
-		Point pp3 = mv.getPoint(eastNorth2latlon(en[2]));
-		Point pp4 = mv.getPoint(eastNorth2latlon(en[3]));
-
-		b.moveTo(pp1.x, pp1.y);
-		b.lineTo(pp2.x, pp2.y);
-		b.lineTo(pp3.x, pp3.y);
-		b.lineTo(pp4.x, pp4.y);
-		b.lineTo(pp1.x, pp1.y);
-		g.draw(b);
-	}
-
-	private Node findNode(EastNorth en) {
-		DataSet ds = Main.main.getCurrentDataSet();
-		LatLon l = eastNorth2latlon(en);
-		List<Node> nodes = ds.searchNodes(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001,
-				l.lon() + 0.0000001, l.lat() + 0.0000001));
-		Node bestnode = null;
-		double mindist = 0.0003;
-		for (Node n : nodes) {
-			double dist = n.getCoor().distanceSq(l);
-			if (dist < mindist && OsmPrimitive.isUsablePredicate.evaluate(n)) {
-				bestnode = n;
-				mindist = dist;
-			}
-		}
-		return bestnode;
-	}
-
-	public Way create() {
-		if (len == 0)
-			return null;
-		final boolean[] created = new boolean[4];
-		final Node[] nodes = new Node[4];
-		for (int i = 0; i < 4; i++) {
-
-			Node n = findNode(en[i]);
-			if (n == null) {
-				nodes[i] = new Node(eastNorth2latlon(en[i]));
-				created[i] = true;
-			} else {
-				nodes[i] = n;
-				created[i] = false;
-			}
-			if (nodes[i].getCoor().isOutSideWorld()) {
-				JOptionPane.showMessageDialog(Main.parent,
-						tr("Cannot place building outside of the world."));
-				return null;
-			}
-		}
-		Way w = new Way();
-		w.addNode(nodes[0]);
-		if (projection2(en[2]) > 0 ^ len < 0) {
-			w.addNode(nodes[1]);
-			w.addNode(nodes[2]);
-			w.addNode(nodes[3]);
-		} else {
-			w.addNode(nodes[3]);
-			w.addNode(nodes[2]);
-			w.addNode(nodes[1]);
-		}
-		w.addNode(nodes[0]);
-		w.setKeys(ToolSettings.getTags());
-		Collection<Command> cmds = new LinkedList<Command>();
-		for (int i = 0; i < 4; i++) {
-			if (created[i])
-				cmds.add(new AddCommand(nodes[i]));
-		}
-		cmds.add(new AddCommand(w));
-		Command c = new SequenceCommand(tr("Create building"), cmds);
-		Main.main.undoRedo.add(c);
-		return w;
-	}
+    private static final double eqlen = 40075004; // length of equator in metres
+    private final EastNorth[] en = new EastNorth[4];
+
+    double meter = 0;
+
+    private double len = 0;
+    private double width;
+    private double heading;
+    private AngleSnap angleSnap = new AngleSnap();
+    private Double drawingAngle;
+
+    public void clearAngleSnap() {
+        angleSnap.clear();
+        drawingAngle = null;
+    }
+
+    public void addAngleSnap(Node[] nodes) {
+        drawingAngle = angleSnap.addSnap(nodes);
+    }
+
+    public void addAngleSnap(Way way) {
+        angleSnap.addSnap(way);
+        if (drawingAngle == null) {
+            drawingAngle = angleSnap.getAngle();
+        }
+    }
+
+    public double getLength() {
+        return len;
+    }
+
+    public double getWidth() {
+        return width;
+    }
+
+    public boolean isRectDrawing() {
+        return drawingAngle != null && ToolSettings.getWidth() == 0 && ToolSettings.getLenStep() == 0;
+    }
+
+    public Double getDrawingAngle() {
+        return drawingAngle;
+    }
+
+    public void reset() {
+        len = 0;
+
+        for (int i = 0; i < 4; i++)
+            en[i] = null;
+    }
+
+    public EastNorth getPoint(int num) {
+        return en[num];
+    }
+
+    private void updMetrics() {
+        meter = 2 * Math.PI / (Math.cos(Math.toRadians(eastNorth2latlon(en[0]).lat())) * eqlen);
+        len = 0;
+    }
+
+    public void setBase(EastNorth base) {
+        en[0] = base;
+        updMetrics();
+    }
+
+    public void setBase(Node base) {
+        en[0] = latlon2eastNorth(base.getCoor());
+        updMetrics();
+    }
+
+    /**
+     * @returns Projection of the point to the heading vector in metres
+     */
+    private double projection1(EastNorth p) {
+        final EastNorth vec = en[0].sub(p);
+        return (Math.sin(heading) * vec.east() + Math.cos(heading) * vec.north()) / meter;
+    }
+
+    /**
+     * @returns Projection of the point to the perpendicular of the heading
+     *          vector in metres
+     */
+    private double projection2(EastNorth p) {
+        final EastNorth vec = en[0].sub(p);
+        return (Math.cos(heading) * vec.east() - Math.sin(heading) * vec.north()) / meter;
+    }
+
+    private void updatePos() {
+        if (len == 0)
+            return;
+        final EastNorth p1 = en[0];
+        en[1] = new EastNorth(p1.east() + Math.sin(heading) * len * meter, p1.north() + Math.cos(heading) * len * meter);
+        en[2] = new EastNorth(p1.east() + Math.sin(heading) * len * meter + Math.cos(heading) * width * meter,
+                p1.north() + Math.cos(heading) * len * meter - Math.sin(heading) * width * meter);
+        en[3] = new EastNorth(p1.east() + Math.cos(heading) * width * meter,
+                p1.north() - Math.sin(heading) * width * meter);
+    }
+
+    public void setLengthWidth(double length, double width) {
+        this.len = length;
+        this.width = width;
+        updatePos();
+    }
+
+    public void setWidth(EastNorth p3) {
+        this.width = projection2(p3);
+        updatePos();
+    }
+
+    public void setPlace(EastNorth p2, double width, double lenstep, boolean ignoreConstraints) {
+        if (en[0] == null)
+            throw new IllegalStateException("setPlace() called without the base point");
+        this.heading = en[0].heading(p2);
+        if (!ignoreConstraints)
+            this.heading = angleSnap.snapAngle(this.heading);
+
+        this.width = width;
+        this.len = projection1(p2);
+        if (lenstep > 0 && !ignoreConstraints)
+            this.len = Math.round(this.len / lenstep) * lenstep;
+
+        updatePos();
+
+        Main.map.statusLine.setHeading(Math.toDegrees(heading));
+        if (this.drawingAngle != null && !ignoreConstraints) {
+            double ang = Math.toDegrees(heading - this.drawingAngle);
+            if (ang < 0)
+                ang += 360;
+            if (ang > 360)
+                ang -= 360;
+            Main.map.statusLine.setAngle(ang);
+        }
+    }
+
+    public void setPlaceRect(EastNorth p2) {
+        if (en[0] == null)
+            throw new IllegalStateException("SetPlaceRect() called without the base point");
+        if (!isRectDrawing())
+            throw new IllegalStateException("Invalid drawing mode");
+        heading = drawingAngle;
+        setLengthWidth(projection1(p2), projection2(p2));
+        Main.map.statusLine.setHeading(Math.toDegrees(heading));
+    }
+
+    public void angFix(EastNorth point) {
+        EastNorth en3 = en[2];
+        EastNorth mid = en[0].getCenter(en3);
+        double radius = en3.distance(mid);
+        heading = mid.heading(point);
+        heading = en[0].heading(mid.add(Math.sin(heading) * radius, Math.cos(heading) * radius));
+        setLengthWidth(projection1(en3), projection2(en3));
+        en[2] = en3;
+    }
+
+    public void paint(Graphics2D g, MapView mv) {
+        if (len == 0)
+            return;
+        GeneralPath b = new GeneralPath();
+        Point pp1 = mv.getPoint(eastNorth2latlon(en[0]));
+        Point pp2 = mv.getPoint(eastNorth2latlon(en[1]));
+        Point pp3 = mv.getPoint(eastNorth2latlon(en[2]));
+        Point pp4 = mv.getPoint(eastNorth2latlon(en[3]));
+
+        b.moveTo(pp1.x, pp1.y);
+        b.lineTo(pp2.x, pp2.y);
+        b.lineTo(pp3.x, pp3.y);
+        b.lineTo(pp4.x, pp4.y);
+        b.lineTo(pp1.x, pp1.y);
+        g.draw(b);
+    }
+
+    private Node findNode(EastNorth en) {
+        DataSet ds = Main.main.getCurrentDataSet();
+        LatLon l = eastNorth2latlon(en);
+        List<Node> nodes = ds.searchNodes(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001,
+                l.lon() + 0.0000001, l.lat() + 0.0000001));
+        Node bestnode = null;
+        double mindist = 0.0003;
+        for (Node n : nodes) {
+            double dist = n.getCoor().distanceSq(l);
+            if (dist < mindist && OsmPrimitive.isUsablePredicate.evaluate(n)) {
+                bestnode = n;
+                mindist = dist;
+            }
+        }
+        return bestnode;
+    }
+
+    public Way create() {
+        if (len == 0)
+            return null;
+        final boolean[] created = new boolean[4];
+        final Node[] nodes = new Node[4];
+        for (int i = 0; i < 4; i++) {
+
+            Node n = findNode(en[i]);
+            if (n == null) {
+                nodes[i] = new Node(eastNorth2latlon(en[i]));
+                created[i] = true;
+            } else {
+                nodes[i] = n;
+                created[i] = false;
+            }
+            if (nodes[i].getCoor().isOutSideWorld()) {
+                JOptionPane.showMessageDialog(Main.parent,
+                        tr("Cannot place building outside of the world."));
+                return null;
+            }
+        }
+        Way w = new Way();
+        w.addNode(nodes[0]);
+        if (projection2(en[2]) > 0 ^ len < 0) {
+            w.addNode(nodes[1]);
+            w.addNode(nodes[2]);
+            w.addNode(nodes[3]);
+        } else {
+            w.addNode(nodes[3]);
+            w.addNode(nodes[2]);
+            w.addNode(nodes[1]);
+        }
+        w.addNode(nodes[0]);
+        w.setKeys(ToolSettings.getTags());
+        Collection<Command> cmds = new LinkedList<Command>();
+        for (int i = 0; i < 4; i++) {
+            if (created[i])
+                cmds.add(new AddCommand(nodes[i]));
+        }
+        cmds.add(new AddCommand(w));
+        Command c = new SequenceCommand(tr("Create building"), cmds);
+        Main.main.undoRedo.add(c);
+        return w;
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeAction.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeAction.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeAction.java	(revision 23190)
@@ -12,18 +12,18 @@
 public class BuildingSizeAction extends JosmAction {
 
-	public BuildingSizeAction() {
-		super(tr("Set buildings size"), "mapmode/building", tr("Set buildings size"),
-				Shortcut.registerShortcut("edit:buildingsdialog",
-				tr("Edit: {0}", tr("Set buildings size")),
-				KeyEvent.VK_W, Shortcut.GROUP_EDIT,
-				Shortcut.SHIFT_DEFAULT),
-				true);
-	}
+    public BuildingSizeAction() {
+        super(tr("Set buildings size"), "mapmode/building", tr("Set buildings size"),
+                Shortcut.registerShortcut("edit:buildingsdialog",
+                tr("Edit: {0}", tr("Set buildings size")),
+                KeyEvent.VK_W, Shortcut.GROUP_EDIT,
+                Shortcut.SHIFT_DEFAULT),
+                true);
+    }
 
-	public void actionPerformed(ActionEvent arg0) {
-		BuildingSizeDialog dlg = new BuildingSizeDialog();
-		if (dlg.getValue() == 1) {
-			dlg.saveSettings();
-		}
-	}
+    public void actionPerformed(ActionEvent arg0) {
+        BuildingSizeDialog dlg = new BuildingSizeDialog();
+        if (dlg.getValue() == 1) {
+            dlg.saveSettings();
+        }
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeDialog.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeDialog.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingSizeDialog.java	(revision 23190)
@@ -23,75 +23,75 @@
 @SuppressWarnings("serial")
 public class BuildingSizeDialog extends ExtendedDialog {
-	private JFormattedTextField twidth = new JFormattedTextField(NumberFormat.getInstance());
-	private JFormattedTextField tlenstep = new JFormattedTextField(NumberFormat.getInstance());
-	private JCheckBox caddr = new JCheckBox(tr("Use Address dialog"));
-	private JCheckBox cAutoSelect = new JCheckBox(tr("Auto-select building"));
+    private JFormattedTextField twidth = new JFormattedTextField(NumberFormat.getInstance());
+    private JFormattedTextField tlenstep = new JFormattedTextField(NumberFormat.getInstance());
+    private JCheckBox caddr = new JCheckBox(tr("Use Address dialog"));
+    private JCheckBox cAutoSelect = new JCheckBox(tr("Auto-select building"));
 
-	static void addLabelled(JPanel panel, String str, Component c) {
-		JLabel label = new JLabel(str);
-		panel.add(label, GBC.std());
-		label.setLabelFor(c);
-		panel.add(c, GBC.eol().fill(GBC.HORIZONTAL));
-	}
+    static void addLabelled(JPanel panel, String str, Component c) {
+        JLabel label = new JLabel(str);
+        panel.add(label, GBC.std());
+        label.setLabelFor(c);
+        panel.add(c, GBC.eol().fill(GBC.HORIZONTAL));
+    }
 
-	public BuildingSizeDialog() {
-		super(Main.parent, tr("Set buildings size"),
-				new String[] { tr("OK"), tr("Cancel") },
-				true);
-		contentInsets = new Insets(15, 15, 5, 15);
-		setButtonIcons(new String[] { "ok.png", "cancel.png" });
+    public BuildingSizeDialog() {
+        super(Main.parent, tr("Set buildings size"),
+                new String[] { tr("OK"), tr("Cancel") },
+                true);
+        contentInsets = new Insets(15, 15, 5, 15);
+        setButtonIcons(new String[] { "ok.png", "cancel.png" });
 
-		final JPanel panel = new JPanel(new GridBagLayout());
-		addLabelled(panel, tr("Buildings width:"), twidth);
-		addLabelled(panel, tr("Length step:"), tlenstep);
-		panel.add(caddr, GBC.eol().fill(GBC.HORIZONTAL));
-		panel.add(cAutoSelect, GBC.eol().fill(GBC.HORIZONTAL));
+        final JPanel panel = new JPanel(new GridBagLayout());
+        addLabelled(panel, tr("Buildings width:"), twidth);
+        addLabelled(panel, tr("Length step:"), tlenstep);
+        panel.add(caddr, GBC.eol().fill(GBC.HORIZONTAL));
+        panel.add(cAutoSelect, GBC.eol().fill(GBC.HORIZONTAL));
 
-		twidth.setValue(ToolSettings.getWidth());
-		tlenstep.setValue(ToolSettings.getLenStep());
-		caddr.setSelected(ToolSettings.isUsingAddr());
-		cAutoSelect.setSelected(ToolSettings.isAutoSelect());
+        twidth.setValue(ToolSettings.getWidth());
+        tlenstep.setValue(ToolSettings.getLenStep());
+        caddr.setSelected(ToolSettings.isUsingAddr());
+        cAutoSelect.setSelected(ToolSettings.isAutoSelect());
 
-		JButton bAdv = new JButton(tr("Advanced..."));
-		bAdv.addActionListener(new ActionListener() {
-			@Override
-			public void actionPerformed(ActionEvent arg0) {
-				AdvancedSettingsDialog dlg = new AdvancedSettingsDialog();
-				if (dlg.getValue() == 1) {
-					dlg.saveSettings();
-				}
-			}
-		});
-		panel.add(bAdv, GBC.eol().insets(0, 5, 0, 0).anchor(GBC.EAST));
+        JButton bAdv = new JButton(tr("Advanced..."));
+        bAdv.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                AdvancedSettingsDialog dlg = new AdvancedSettingsDialog();
+                if (dlg.getValue() == 1) {
+                    dlg.saveSettings();
+                }
+            }
+        });
+        panel.add(bAdv, GBC.eol().insets(0, 5, 0, 0).anchor(GBC.EAST));
 
-		setContent(panel);
-		setupDialog();
-		setVisible(true);
-	}
+        setContent(panel);
+        setupDialog();
+        setVisible(true);
+    }
 
-	public double width() {
-		try {
-			return NumberFormat.getInstance().parse(twidth.getText()).doubleValue();
-		} catch (ParseException e) {
-			return 0;
-		}
-	}
+    public double width() {
+        try {
+            return NumberFormat.getInstance().parse(twidth.getText()).doubleValue();
+        } catch (ParseException e) {
+            return 0;
+        }
+    }
 
-	public double lenstep() {
-		try {
-			return NumberFormat.getInstance().parse(tlenstep.getText()).doubleValue();
-		} catch (ParseException e) {
-			return 0;
-		}
-	}
+    public double lenstep() {
+        try {
+            return NumberFormat.getInstance().parse(tlenstep.getText()).doubleValue();
+        } catch (ParseException e) {
+            return 0;
+        }
+    }
 
-	public boolean useAddr() {
-		return caddr.isSelected();
-	}
+    public boolean useAddr() {
+        return caddr.isSelected();
+    }
 
-	public void saveSettings() {
-		ToolSettings.setSizes(width(), lenstep());
-		ToolSettings.setAddrDialog(useAddr());
-		ToolSettings.setAutoSelect(cAutoSelect.isSelected());
-	}
+    public void saveSettings() {
+        ToolSettings.setSizes(width(), lenstep());
+        ToolSettings.setAddrDialog(useAddr());
+        ToolSettings.setAutoSelect(cAutoSelect.isSelected());
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingsToolsPlugin.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingsToolsPlugin.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/BuildingsToolsPlugin.java	(revision 23190)
@@ -12,22 +12,22 @@
 
 public class BuildingsToolsPlugin extends Plugin {
-	public static Mercator proj = new Mercator();
+    public static Mercator proj = new Mercator();
 
-	public static EastNorth latlon2eastNorth(LatLon p) {
-		return proj.latlon2eastNorth(p); 
-	}
-	public static LatLon eastNorth2latlon(EastNorth p) {
-		return proj.eastNorth2latlon(p); 
-	}
+    public static EastNorth latlon2eastNorth(LatLon p) {
+        return proj.latlon2eastNorth(p);
+    }
+    public static LatLon eastNorth2latlon(EastNorth p) {
+        return proj.eastNorth2latlon(p);
+    }
 
-	public BuildingsToolsPlugin(PluginInformation info) {
-		super(info);
-		Main.main.menu.editMenu.addSeparator();
-		MainMenu.add(Main.main.menu.editMenu, new BuildingSizeAction());
-	}
-	@Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-		if (oldFrame==null && newFrame!=null) {
-			Main.map.addMapMode(new IconToggleButton(new DrawBuildingAction(Main.map)));
-		}
-	}
+    public BuildingsToolsPlugin(PluginInformation info) {
+        super(info);
+        Main.main.menu.editMenu.addSeparator();
+        MainMenu.add(Main.main.menu.editMenu, new BuildingSizeAction());
+    }
+    @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+        if (oldFrame==null && newFrame!=null) {
+            Main.map.addMapMode(new IconToggleButton(new DrawBuildingAction(Main.map)));
+        }
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/DrawBuildingAction.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/DrawBuildingAction.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/DrawBuildingAction.java	(revision 23190)
@@ -42,417 +42,417 @@
 @SuppressWarnings("serial")
 public class DrawBuildingAction extends MapMode implements MapViewPaintable, AWTEventListener, SelectionChangedListener {
-	private enum Mode {
-		None, Drawing, DrawingWidth, DrawingAngFix
-	}
-
-	final private Cursor cursorCrosshair;
-	final private Cursor cursorJoinNode;
-	private Cursor currCursor;
-	private Cursor customCursor;
-
-	private Mode mode = Mode.None;
-	private Mode nextMode = Mode.None;
-
-	private Color selectedColor;
-	private Point drawStartPos;
-	private Point mousePos;
-	private boolean isCtrlDown;
-	private boolean isShiftDown;
-
-	Building building = new Building();
-
-	public DrawBuildingAction(MapFrame mapFrame) {
-		super(tr("Draw buildings"), "building", tr("Draw buildings"),
-				Shortcut.registerShortcut("mapmode:buildings",
-						tr("Mode: {0}", tr("Draw buildings")),
-						KeyEvent.VK_W, Shortcut.GROUP_EDIT),
-				mapFrame, getCursor());
-
-		cursorCrosshair = getCursor();
-		cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
-		currCursor = cursorCrosshair;
-
-		selectedColor = Main.pref.getColor(marktr("selected"), Color.red);
-	}
-
-	private static Cursor getCursor() {
-		try {
-			return ImageProvider.getCursor("crosshair", null);
-		} catch (Exception e) {
-		}
-		return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
-	}
-
-	/**
-	 * Displays the given cursor instead of the normal one
-	 * 
-	 * @param Cursors
-	 *            One of the available cursors
-	 */
-	private void setCursor(final Cursor c) {
-		if (currCursor.equals(c))
-			return;
-		try {
-			// We invoke this to prevent strange things from happening
-			EventQueue.invokeLater(new Runnable() {
-				public void run() {
-					// Don't change cursor when mode has changed already
-					if (!(Main.map.mapMode instanceof DrawBuildingAction))
-						return;
-					Main.map.mapView.setCursor(c);
-				}
-			});
-			currCursor = c;
-		} catch (Exception e) {
-		}
-	}
-
-	private static void showAddrDialog(Way w) {
-		AddressDialog dlg = new AddressDialog();
-		int answer = dlg.getValue();
-		if (answer == 1) {
-			dlg.saveValues();
-			String tmp;
-			tmp = dlg.getHouseNum();
-			if (tmp != null && tmp != "")
-				w.put("addr:housenumber", tmp);
-			tmp = dlg.getStreetName();
-			if (tmp != null && tmp != "")
-				w.put("addr:street", tmp);
-		}
-	}
-
-	@Override
-	public void enterMode() {
-		super.enterMode();
-		if (getCurrentDataSet() == null) {
-			Main.map.selectSelectTool(false);
-			return;
-		}
-		currCursor = cursorCrosshair;
-		Main.map.mapView.addMouseListener(this);
-		Main.map.mapView.addMouseMotionListener(this);
-		Main.map.mapView.addTemporaryLayer(this);
-		DataSet.addSelectionListener(this);
-		updateSnap(getCurrentDataSet().getSelected());
-		try {
-			Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
-		} catch (SecurityException ex) {
-		}
-	}
-
-	@Override
-	public void exitMode() {
-		super.exitMode();
-		Main.map.mapView.removeMouseListener(this);
-		Main.map.mapView.removeMouseMotionListener(this);
-		Main.map.mapView.removeTemporaryLayer(this);
-		DataSet.removeSelectionListener(this);
-		try {
-			Toolkit.getDefaultToolkit().removeAWTEventListener(this);
-		} catch (SecurityException ex) {
-		}
-		if (mode != Mode.None)
-			Main.map.mapView.repaint();
-		mode = Mode.None;
-	}
-
-	public void cancelDrawing() {
-		mode = Mode.None;
-		if (Main.map == null || Main.map.mapView == null)
-			return;
-		Main.map.statusLine.setHeading(-1);
-		Main.map.statusLine.setAngle(-1);
-		building.reset();
-		Main.map.mapView.repaint();
-		updateStatusLine();
-	}
-
-	public void eventDispatched(AWTEvent arg0) {
-		if (!(arg0 instanceof KeyEvent))
-			return;
-		KeyEvent ev = (KeyEvent) arg0;
-		int modifiers = ev.getModifiersEx();
-		boolean isCtrlDown = (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0;
-		boolean isShiftDown = (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0;
-		if (this.isCtrlDown != isCtrlDown || this.isShiftDown != isShiftDown) {
-			this.isCtrlDown = isCtrlDown;
-			this.isShiftDown = isShiftDown;
-			processMouseEvent(null);
-			updCursor();
-			if (mode != Mode.None)
-				Main.map.mapView.repaint();
-		}
-
-		if (ev.getKeyCode() == KeyEvent.VK_ESCAPE && ev.getID() == KeyEvent.KEY_PRESSED) {
-			if (mode != Mode.None)
-				ev.consume();
-
-			cancelDrawing();
-		}
-	}
-
-	private EastNorth getEastNorth() {
-		Node n;
-		if (isCtrlDown) {
-			n = null;
-		} else {
-			n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
-		}
-		if (n == null) {
-			return latlon2eastNorth(Main.map.mapView.getLatLon(mousePos.x, mousePos.y));
-		} else {
-			return latlon2eastNorth(n.getCoor());
-		}
-	}
-
-	private boolean isRectDrawing() {
-		return building.isRectDrawing() && (!isShiftDown || ToolSettings.isBBMode());
-	}
-
-	private Mode modeDrawing() {
-		EastNorth p = getEastNorth();
-		if (isRectDrawing()) {
-			building.setPlaceRect(p);
-			return isShiftDown ? Mode.DrawingAngFix : Mode.None;
-		} else {
-			building.setPlace(p, ToolSettings.getWidth(), ToolSettings.getLenStep(), isShiftDown);
-			Main.map.statusLine.setDist(building.getLength());
-			return this.nextMode = ToolSettings.getWidth() == 0 ? Mode.DrawingWidth : Mode.None;
-		}
-	}
-
-	private Mode modeDrawingWidth() {
-		building.setWidth(getEastNorth());
-		Main.map.statusLine.setDist(Math.abs(building.getWidth()));
-		return Mode.None;
-	}
-
-	private Mode modeDrawingAngFix() {
-		building.angFix(getEastNorth());
-		return Mode.None;
-	}
-
-	private void processMouseEvent(MouseEvent e) {
-		if (e != null) {
-			mousePos = e.getPoint();
-			isCtrlDown = e.isControlDown();
-			isShiftDown = e.isShiftDown();
-		}
-		if (mode == Mode.None) {
-			nextMode = Mode.None;
-			return;
-		}
-
-		if (mode == Mode.Drawing) {
-			nextMode = modeDrawing();
-		} else if (mode == Mode.DrawingWidth) {
-			nextMode = modeDrawingWidth();
-		} else if (mode == Mode.DrawingAngFix) {
-			nextMode = modeDrawingAngFix();
-		} else
-			throw new AssertionError("Invalid drawing mode");
-	}
-
-	public void paint(Graphics2D g, MapView mv, Bounds bbox) {
-		if (mode == Mode.None)
-			return;
-		if (building.getLength() == 0)
-			return;
-
-		g.setColor(selectedColor);
-		g.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-
-		building.paint(g, mv);
-
-		g.setStroke(new BasicStroke(1));
-
-	}
-
-	private void drawingStart(MouseEvent e) {
-		mousePos = e.getPoint();
-		drawStartPos = mousePos;
-
-		Node n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
-		if (n == null) {
-			building.setBase(latlon2eastNorth(Main.map.mapView.getLatLon(mousePos.x, mousePos.y)));
-		} else {
-			building.setBase(n);
-		}
-		mode = Mode.Drawing;
-		updateStatusLine();
-	}
-
-	private void drawingAdvance(MouseEvent e) {
-		processMouseEvent(e);
-		if (this.mode != Mode.None && this.nextMode == Mode.None) {
-			drawingFinish();
-		} else {
-			mode = this.nextMode;
-			updateStatusLine();
-		}
-	}
-
-	private void drawingFinish() {
-		if (building.getLength() != 0) {
-			Way w = building.create();
-			if (w != null && ToolSettings.isUsingAddr())
-				showAddrDialog(w);
-			if (ToolSettings.isAutoSelect() &&
-					(Main.main.getCurrentDataSet().getSelected().isEmpty() || isShiftDown)) {
-				Main.main.getCurrentDataSet().setSelected(w);
-			}
-		}
-		cancelDrawing();
-	}
-
-	@Override
-	public void mousePressed(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-		if (!Main.map.mapView.isActiveLayerDrawable())
-			return;
-
-		if (mode == Mode.None)
-			drawingStart(e);
-	}
-
-	@Override
-	public void mouseDragged(MouseEvent e) {
-		processMouseEvent(e);
-		updCursor();
-		if (mode != Mode.None)
-			Main.map.mapView.repaint();
-	}
-
-	@Override
-	public void mouseReleased(MouseEvent e) {
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-		if (!Main.map.mapView.isActiveLayerDrawable())
-			return;
-		boolean dragged = true;
-		if (drawStartPos != null)
-			dragged = e.getPoint().distance(drawStartPos) > 10;
-		drawStartPos = null;
-
-		if (mode == Mode.Drawing && !dragged)
-			return;
-		if (mode == Mode.None)
-			return;
-
-		drawingAdvance(e);
-	}
-
-	private void updCursor() {
-		if (mousePos == null)
-			return;
-		if (!Main.isDisplayingMapView())
-			return;
-		Node n = null;
-		if (!isCtrlDown)
-			n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
-		if (n != null) {
-			setCursor(cursorJoinNode);
-		} else {
-			if (customCursor != null && (!isShiftDown || isRectDrawing()))
-				setCursor(customCursor);
-			else
-				setCursor(cursorCrosshair);
-		}
-
-	}
-
-	@Override
-	public void mouseMoved(MouseEvent e) {
-		if (!Main.map.mapView.isActiveLayerDrawable())
-			return;
-		processMouseEvent(e);
-		updCursor();
-		if (mode != Mode.None)
-			Main.map.mapView.repaint();
-	}
-
-	@Override
-	public String getModeHelpText() {
-		if (mode == Mode.None)
-			return tr("Point on the corner of the building to start drawing");
-		if (mode == Mode.Drawing)
-			return tr("Point on opposite end of the building");
-		if (mode == Mode.DrawingWidth)
-			return tr("Set width of the building");
-		return "";
-	}
-
-	@Override
-	public boolean layerIsSupported(Layer l) {
-		return l instanceof OsmDataLayer;
-	}
-
-	public void updateSnap(Collection<? extends OsmPrimitive> newSelection) {
-		building.clearAngleSnap();
-		// update snap only if selection isn't too big
-		if (newSelection.size() <= 10) {
-			LinkedList<Node> nodes = new LinkedList<Node>();
-			LinkedList<Way> ways = new LinkedList<Way>();
-
-			for (OsmPrimitive p : newSelection) {
-				switch (p.getType()) {
-				case NODE:
-					nodes.add((Node) p);
-					break;
-				case WAY:
-					ways.add((Way) p);
-					break;
-				}
-			}
-
-			building.addAngleSnap(nodes.toArray(new Node[0]));
-			for (Way w : ways) {
-				building.addAngleSnap(w);
-			}
-		}
-		updateCustomCursor();
-	}
-
-	private void updateCustomCursor() {
-		Double angle = building.getDrawingAngle();
-		if (angle == null || !ToolSettings.isSoftCursor()) {
-			customCursor = null;
-			return;
-		}
-		final int R = 9; // crosshair outer radius
-		final int r = 3; // crosshair inner radius
-		BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
-		Graphics2D g = img.createGraphics();
-
-		GeneralPath b = new GeneralPath();
-		b.moveTo(16 - Math.cos(angle) * R, 16 - Math.sin(angle) * R);
-		b.lineTo(16 - Math.cos(angle) * r, 16 - Math.sin(angle) * r);
-		b.moveTo(16 + Math.cos(angle) * R, 16 + Math.sin(angle) * R);
-		b.lineTo(16 + Math.cos(angle) * r, 16 + Math.sin(angle) * r);
-		b.moveTo(16 + Math.sin(angle) * R, 16 - Math.cos(angle) * R);
-		b.lineTo(16 + Math.sin(angle) * r, 16 - Math.cos(angle) * r);
-		b.moveTo(16 - Math.sin(angle) * R, 16 + Math.cos(angle) * R);
-		b.lineTo(16 - Math.sin(angle) * r, 16 + Math.cos(angle) * r);
-
-		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-		g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
-
-		g.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-		g.setColor(Color.WHITE);
-		g.draw(b);
-
-		g.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-		g.setColor(Color.BLACK);
-		g.draw(b);
-
-		customCursor = Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(16, 16), "custom crosshair");
-
-		updCursor();
-	}
-
-	public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
-		updateSnap(newSelection);
-	}
+    private enum Mode {
+        None, Drawing, DrawingWidth, DrawingAngFix
+    }
+
+    final private Cursor cursorCrosshair;
+    final private Cursor cursorJoinNode;
+    private Cursor currCursor;
+    private Cursor customCursor;
+
+    private Mode mode = Mode.None;
+    private Mode nextMode = Mode.None;
+
+    private Color selectedColor;
+    private Point drawStartPos;
+    private Point mousePos;
+    private boolean isCtrlDown;
+    private boolean isShiftDown;
+
+    Building building = new Building();
+
+    public DrawBuildingAction(MapFrame mapFrame) {
+        super(tr("Draw buildings"), "building", tr("Draw buildings"),
+                Shortcut.registerShortcut("mapmode:buildings",
+                        tr("Mode: {0}", tr("Draw buildings")),
+                        KeyEvent.VK_W, Shortcut.GROUP_EDIT),
+                mapFrame, getCursor());
+
+        cursorCrosshair = getCursor();
+        cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
+        currCursor = cursorCrosshair;
+
+        selectedColor = Main.pref.getColor(marktr("selected"), Color.red);
+    }
+
+    private static Cursor getCursor() {
+        try {
+            return ImageProvider.getCursor("crosshair", null);
+        } catch (Exception e) {
+        }
+        return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
+    }
+
+    /**
+     * Displays the given cursor instead of the normal one
+     *
+     * @param Cursors
+     *            One of the available cursors
+     */
+    private void setCursor(final Cursor c) {
+        if (currCursor.equals(c))
+            return;
+        try {
+            // We invoke this to prevent strange things from happening
+            EventQueue.invokeLater(new Runnable() {
+                public void run() {
+                    // Don't change cursor when mode has changed already
+                    if (!(Main.map.mapMode instanceof DrawBuildingAction))
+                        return;
+                    Main.map.mapView.setCursor(c);
+                }
+            });
+            currCursor = c;
+        } catch (Exception e) {
+        }
+    }
+
+    private static void showAddrDialog(Way w) {
+        AddressDialog dlg = new AddressDialog();
+        int answer = dlg.getValue();
+        if (answer == 1) {
+            dlg.saveValues();
+            String tmp;
+            tmp = dlg.getHouseNum();
+            if (tmp != null && tmp != "")
+                w.put("addr:housenumber", tmp);
+            tmp = dlg.getStreetName();
+            if (tmp != null && tmp != "")
+                w.put("addr:street", tmp);
+        }
+    }
+
+    @Override
+    public void enterMode() {
+        super.enterMode();
+        if (getCurrentDataSet() == null) {
+            Main.map.selectSelectTool(false);
+            return;
+        }
+        currCursor = cursorCrosshair;
+        Main.map.mapView.addMouseListener(this);
+        Main.map.mapView.addMouseMotionListener(this);
+        Main.map.mapView.addTemporaryLayer(this);
+        DataSet.addSelectionListener(this);
+        updateSnap(getCurrentDataSet().getSelected());
+        try {
+            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
+        } catch (SecurityException ex) {
+        }
+    }
+
+    @Override
+    public void exitMode() {
+        super.exitMode();
+        Main.map.mapView.removeMouseListener(this);
+        Main.map.mapView.removeMouseMotionListener(this);
+        Main.map.mapView.removeTemporaryLayer(this);
+        DataSet.removeSelectionListener(this);
+        try {
+            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
+        } catch (SecurityException ex) {
+        }
+        if (mode != Mode.None)
+            Main.map.mapView.repaint();
+        mode = Mode.None;
+    }
+
+    public void cancelDrawing() {
+        mode = Mode.None;
+        if (Main.map == null || Main.map.mapView == null)
+            return;
+        Main.map.statusLine.setHeading(-1);
+        Main.map.statusLine.setAngle(-1);
+        building.reset();
+        Main.map.mapView.repaint();
+        updateStatusLine();
+    }
+
+    public void eventDispatched(AWTEvent arg0) {
+        if (!(arg0 instanceof KeyEvent))
+            return;
+        KeyEvent ev = (KeyEvent) arg0;
+        int modifiers = ev.getModifiersEx();
+        boolean isCtrlDown = (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0;
+        boolean isShiftDown = (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0;
+        if (this.isCtrlDown != isCtrlDown || this.isShiftDown != isShiftDown) {
+            this.isCtrlDown = isCtrlDown;
+            this.isShiftDown = isShiftDown;
+            processMouseEvent(null);
+            updCursor();
+            if (mode != Mode.None)
+                Main.map.mapView.repaint();
+        }
+
+        if (ev.getKeyCode() == KeyEvent.VK_ESCAPE && ev.getID() == KeyEvent.KEY_PRESSED) {
+            if (mode != Mode.None)
+                ev.consume();
+
+            cancelDrawing();
+        }
+    }
+
+    private EastNorth getEastNorth() {
+        Node n;
+        if (isCtrlDown) {
+            n = null;
+        } else {
+            n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
+        }
+        if (n == null) {
+            return latlon2eastNorth(Main.map.mapView.getLatLon(mousePos.x, mousePos.y));
+        } else {
+            return latlon2eastNorth(n.getCoor());
+        }
+    }
+
+    private boolean isRectDrawing() {
+        return building.isRectDrawing() && (!isShiftDown || ToolSettings.isBBMode());
+    }
+
+    private Mode modeDrawing() {
+        EastNorth p = getEastNorth();
+        if (isRectDrawing()) {
+            building.setPlaceRect(p);
+            return isShiftDown ? Mode.DrawingAngFix : Mode.None;
+        } else {
+            building.setPlace(p, ToolSettings.getWidth(), ToolSettings.getLenStep(), isShiftDown);
+            Main.map.statusLine.setDist(building.getLength());
+            return this.nextMode = ToolSettings.getWidth() == 0 ? Mode.DrawingWidth : Mode.None;
+        }
+    }
+
+    private Mode modeDrawingWidth() {
+        building.setWidth(getEastNorth());
+        Main.map.statusLine.setDist(Math.abs(building.getWidth()));
+        return Mode.None;
+    }
+
+    private Mode modeDrawingAngFix() {
+        building.angFix(getEastNorth());
+        return Mode.None;
+    }
+
+    private void processMouseEvent(MouseEvent e) {
+        if (e != null) {
+            mousePos = e.getPoint();
+            isCtrlDown = e.isControlDown();
+            isShiftDown = e.isShiftDown();
+        }
+        if (mode == Mode.None) {
+            nextMode = Mode.None;
+            return;
+        }
+
+        if (mode == Mode.Drawing) {
+            nextMode = modeDrawing();
+        } else if (mode == Mode.DrawingWidth) {
+            nextMode = modeDrawingWidth();
+        } else if (mode == Mode.DrawingAngFix) {
+            nextMode = modeDrawingAngFix();
+        } else
+            throw new AssertionError("Invalid drawing mode");
+    }
+
+    public void paint(Graphics2D g, MapView mv, Bounds bbox) {
+        if (mode == Mode.None)
+            return;
+        if (building.getLength() == 0)
+            return;
+
+        g.setColor(selectedColor);
+        g.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+
+        building.paint(g, mv);
+
+        g.setStroke(new BasicStroke(1));
+
+    }
+
+    private void drawingStart(MouseEvent e) {
+        mousePos = e.getPoint();
+        drawStartPos = mousePos;
+
+        Node n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
+        if (n == null) {
+            building.setBase(latlon2eastNorth(Main.map.mapView.getLatLon(mousePos.x, mousePos.y)));
+        } else {
+            building.setBase(n);
+        }
+        mode = Mode.Drawing;
+        updateStatusLine();
+    }
+
+    private void drawingAdvance(MouseEvent e) {
+        processMouseEvent(e);
+        if (this.mode != Mode.None && this.nextMode == Mode.None) {
+            drawingFinish();
+        } else {
+            mode = this.nextMode;
+            updateStatusLine();
+        }
+    }
+
+    private void drawingFinish() {
+        if (building.getLength() != 0) {
+            Way w = building.create();
+            if (w != null && ToolSettings.isUsingAddr())
+                showAddrDialog(w);
+            if (ToolSettings.isAutoSelect() &&
+                    (Main.main.getCurrentDataSet().getSelected().isEmpty() || isShiftDown)) {
+                Main.main.getCurrentDataSet().setSelected(w);
+            }
+        }
+        cancelDrawing();
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+        if (e.getButton() != MouseEvent.BUTTON1)
+            return;
+        if (!Main.map.mapView.isActiveLayerDrawable())
+            return;
+
+        if (mode == Mode.None)
+            drawingStart(e);
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+        processMouseEvent(e);
+        updCursor();
+        if (mode != Mode.None)
+            Main.map.mapView.repaint();
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+        if (e.getButton() != MouseEvent.BUTTON1)
+            return;
+        if (!Main.map.mapView.isActiveLayerDrawable())
+            return;
+        boolean dragged = true;
+        if (drawStartPos != null)
+            dragged = e.getPoint().distance(drawStartPos) > 10;
+        drawStartPos = null;
+
+        if (mode == Mode.Drawing && !dragged)
+            return;
+        if (mode == Mode.None)
+            return;
+
+        drawingAdvance(e);
+    }
+
+    private void updCursor() {
+        if (mousePos == null)
+            return;
+        if (!Main.isDisplayingMapView())
+            return;
+        Node n = null;
+        if (!isCtrlDown)
+            n = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isUsablePredicate);
+        if (n != null) {
+            setCursor(cursorJoinNode);
+        } else {
+            if (customCursor != null && (!isShiftDown || isRectDrawing()))
+                setCursor(customCursor);
+            else
+                setCursor(cursorCrosshair);
+        }
+
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent e) {
+        if (!Main.map.mapView.isActiveLayerDrawable())
+            return;
+        processMouseEvent(e);
+        updCursor();
+        if (mode != Mode.None)
+            Main.map.mapView.repaint();
+    }
+
+    @Override
+    public String getModeHelpText() {
+        if (mode == Mode.None)
+            return tr("Point on the corner of the building to start drawing");
+        if (mode == Mode.Drawing)
+            return tr("Point on opposite end of the building");
+        if (mode == Mode.DrawingWidth)
+            return tr("Set width of the building");
+        return "";
+    }
+
+    @Override
+    public boolean layerIsSupported(Layer l) {
+        return l instanceof OsmDataLayer;
+    }
+
+    public void updateSnap(Collection<? extends OsmPrimitive> newSelection) {
+        building.clearAngleSnap();
+        // update snap only if selection isn't too big
+        if (newSelection.size() <= 10) {
+            LinkedList<Node> nodes = new LinkedList<Node>();
+            LinkedList<Way> ways = new LinkedList<Way>();
+
+            for (OsmPrimitive p : newSelection) {
+                switch (p.getType()) {
+                case NODE:
+                    nodes.add((Node) p);
+                    break;
+                case WAY:
+                    ways.add((Way) p);
+                    break;
+                }
+            }
+
+            building.addAngleSnap(nodes.toArray(new Node[0]));
+            for (Way w : ways) {
+                building.addAngleSnap(w);
+            }
+        }
+        updateCustomCursor();
+    }
+
+    private void updateCustomCursor() {
+        Double angle = building.getDrawingAngle();
+        if (angle == null || !ToolSettings.isSoftCursor()) {
+            customCursor = null;
+            return;
+        }
+        final int R = 9; // crosshair outer radius
+        final int r = 3; // crosshair inner radius
+        BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g = img.createGraphics();
+
+        GeneralPath b = new GeneralPath();
+        b.moveTo(16 - Math.cos(angle) * R, 16 - Math.sin(angle) * R);
+        b.lineTo(16 - Math.cos(angle) * r, 16 - Math.sin(angle) * r);
+        b.moveTo(16 + Math.cos(angle) * R, 16 + Math.sin(angle) * R);
+        b.lineTo(16 + Math.cos(angle) * r, 16 + Math.sin(angle) * r);
+        b.moveTo(16 + Math.sin(angle) * R, 16 - Math.cos(angle) * R);
+        b.lineTo(16 + Math.sin(angle) * r, 16 - Math.cos(angle) * r);
+        b.moveTo(16 - Math.sin(angle) * R, 16 + Math.cos(angle) * R);
+        b.lineTo(16 - Math.sin(angle) * r, 16 + Math.cos(angle) * r);
+
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+
+        g.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+        g.setColor(Color.WHITE);
+        g.draw(b);
+
+        g.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+        g.setColor(Color.BLACK);
+        g.draw(b);
+
+        customCursor = Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(16, 16), "custom crosshair");
+
+        updCursor();
+    }
+
+    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
+        updateSnap(newSelection);
+    }
 }
Index: applications/editors/josm/plugins/buildings_tools/src/buildings_tools/ToolSettings.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/buildings_tools/ToolSettings.java	(revision 23124)
+++ applications/editors/josm/plugins/buildings_tools/src/buildings_tools/ToolSettings.java	(revision 23190)
@@ -7,61 +7,61 @@
 
 public class ToolSettings {
-	private static double width = 0;
-	private static double lenstep = 0;
-	private static boolean useAddr;
-	private static final Map<String, String> tags = new HashMap<String, String>();
-	private static boolean autoSelect;
+    private static double width = 0;
+    private static double lenstep = 0;
+    private static boolean useAddr;
+    private static final Map<String, String> tags = new HashMap<String, String>();
+    private static boolean autoSelect;
 
-	static {
-		tags.put("building", "yes");
-	}
+    static {
+        tags.put("building", "yes");
+    }
 
-	public static void setAddrDialog(boolean _useAddr) {
-		useAddr = _useAddr;
-	}
+    public static void setAddrDialog(boolean _useAddr) {
+        useAddr = _useAddr;
+    }
 
-	public static void setSizes(double newwidth, double newlenstep) {
-		width = newwidth;
-		lenstep = newlenstep;
-	}
+    public static void setSizes(double newwidth, double newlenstep) {
+        width = newwidth;
+        lenstep = newlenstep;
+    }
 
-	public static double getWidth() {
-		return width;
-	}
+    public static double getWidth() {
+        return width;
+    }
 
-	public static double getLenStep() {
-		return lenstep;
-	}
+    public static double getLenStep() {
+        return lenstep;
+    }
 
-	public static boolean isUsingAddr() {
-		return useAddr;
-	}
+    public static boolean isUsingAddr() {
+        return useAddr;
+    }
 
-	public static Map<String, String> getTags() {
-		return tags;
-	}
+    public static Map<String, String> getTags() {
+        return tags;
+    }
 
-	public static void setBBMode(boolean bbmode) {
-		Main.pref.put("buildings_tools.bbmode", bbmode);
-	}
+    public static void setBBMode(boolean bbmode) {
+        Main.pref.put("buildings_tools.bbmode", bbmode);
+    }
 
-	public static boolean isBBMode() {
-		return Main.pref.getBoolean("buildings_tools.bbmode", false);
-	}
+    public static boolean isBBMode() {
+        return Main.pref.getBoolean("buildings_tools.bbmode", false);
+    }
 
-	public static void setSoftCursor(boolean softCursor) {
-		Main.pref.put("buildings_tools.softcursor", softCursor);
-	}
+    public static void setSoftCursor(boolean softCursor) {
+        Main.pref.put("buildings_tools.softcursor", softCursor);
+    }
 
-	public static boolean isSoftCursor() {
-		return Main.pref.getBoolean("buildings_tools.softcursor", false);
-	}
+    public static boolean isSoftCursor() {
+        return Main.pref.getBoolean("buildings_tools.softcursor", false);
+    }
 
-	public static boolean isAutoSelect() {
-		return autoSelect;
-	}
+    public static boolean isAutoSelect() {
+        return autoSelect;
+    }
 
-	public static void setAutoSelect(boolean _autoSelect) {
-		autoSelect = _autoSelect;
-	}
+    public static void setAutoSelect(boolean _autoSelect) {
+        autoSelect = _autoSelect;
+    }
 }
