Index: /trunk/src/org/openstreetmap/josm/actions/LassoModeAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/LassoModeAction.java	(revision 5152)
+++ /trunk/src/org/openstreetmap/josm/actions/LassoModeAction.java	(revision 5152)
@@ -0,0 +1,34 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.mapmode.MapMode;
+
+public class LassoModeAction extends MapMode {
+
+    public LassoModeAction() {
+        super(tr("Lasso Mode"),
+                "rope",
+                tr("Toggle Lasso Mode (in contrast to Rectangle Mode)"),
+                null,
+                null);
+    }
+
+    @Override
+    public void enterMode() {
+        super.enterMode();
+        if (Main.map != null) {
+            Main.map.mapModeSelect.setLassoMode(true);
+            Main.map.mapModeSelect.enterMode();
+        }
+    }
+
+    @Override
+    public void exitMode() {
+        super.exitMode();
+        Main.map.mapModeSelect.setLassoMode(false);
+        Main.map.mapModeSelect.exitMode();
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 5151)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 5152)
@@ -84,4 +84,5 @@
         rotate("rotate", null),
         merge("crosshair", null),
+        lasso("normal", "rope"),
         merge_to_node("crosshair", "joinnode"),
         move(Cursor.MOVE_CURSOR);
@@ -98,4 +99,6 @@
         }
     }
+
+    private boolean lassoMode = false;
 
     // Cache previous mouse event (needed when only the modifier keys are
@@ -172,6 +175,5 @@
         mv.addMouseListener(this);
         mv.addMouseMotionListener(this);
-        mv.setVirtualNodesEnabled(
-                Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0);
+        mv.setVirtualNodesEnabled(Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0);
         drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
         // This is required to update the cursors when ctrl/shift/alt is pressed
@@ -241,5 +243,9 @@
             break;
         case select:
-            c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : ""));
+            if (lassoMode) {
+                c = "lasso";
+            } else {
+                c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : ""));
+            }
             break;
         }
@@ -727,5 +733,5 @@
         case select:
         default:
-            selectionManager.register(mv);
+            selectionManager.register(mv, lassoMode);
             selectionManager.mousePressed(e);
             break;
@@ -825,5 +831,6 @@
     public void selectionEnded(Rectangle r, MouseEvent e) {
         updateKeyModifiers(e);
-        selectPrims(selectionManager.getObjectsInRectangle(r, alt), e, true, true);
+        mv.repaint();
+        selectPrims(selectionManager.getSelectedObjects(alt), e, true, true);
     }
 
@@ -974,3 +981,9 @@
         return l instanceof OsmDataLayer;
     }
+
+    public void setLassoMode(boolean lassoMode) {
+        System.out.println(lassoMode);
+        this.selectionManager.setLassoMode(lassoMode);
+        this.lassoMode = lassoMode;
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 5151)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java	(revision 5152)
@@ -60,5 +60,5 @@
     @Override public void enterMode() {
         super.enterMode();
-        selectionManager.register(Main.map.mapView);
+        selectionManager.register(Main.map.mapView, false);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 5151)
+++ /trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 5152)
@@ -41,4 +41,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.LassoModeAction;
 import org.openstreetmap.josm.actions.mapmode.DeleteAction;
 import org.openstreetmap.josm.actions.mapmode.DrawAction;
@@ -109,5 +110,5 @@
 
     // Map modes
-    private final MapMode mapModeSelect;
+    public final SelectAction mapModeSelect;
     private final MapMode mapModeDraw;
     private final MapMode mapModeZoom;
@@ -159,4 +160,5 @@
         toolBarActions.setFloatable(false);
         addMapMode(new IconToggleButton(mapModeSelect = new SelectAction(this)));
+        addMapMode(new IconToggleButton(new LassoModeAction(), true));
         addMapMode(new IconToggleButton(mapModeDraw = new DrawAction(this)));
         addMapMode(new IconToggleButton(mapModeZoom = new ZoomAction(this)));
Index: /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 5151)
+++ /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 5152)
@@ -6,4 +6,5 @@
 import java.awt.Graphics;
 import java.awt.Point;
+import java.awt.Polygon;
 import java.awt.Rectangle;
 import java.awt.event.InputEvent;
@@ -97,4 +98,7 @@
     private boolean aspectRatio;
 
+    private boolean lassoMode;
+    private Polygon lasso = new Polygon();
+
     /**
      * Create a new SelectionManager.
@@ -116,5 +120,6 @@
      * @param eventSource The emitter of the mouse events.
      */
-    public void register(NavigatableComponent eventSource) {
+    public void register(NavigatableComponent eventSource, boolean lassoMode) {
+       this.lassoMode = lassoMode;
         eventSource.addMouseListener(this);
         eventSource.addMouseMotionListener(this);
@@ -147,4 +152,7 @@
         if (e.getButton() == MouseEvent.BUTTON1) {
             mousePosStart = mousePos = e.getPoint();
+
+            lasso.reset();
+            lasso.addPoint(mousePosStart.x, mousePosStart.y);
         }
     }
@@ -160,10 +168,16 @@
                 mousePosStart = mousePos = e.getPoint();
             }
-            paintRect();
+            if (!lassoMode) {
+                paintRect();
+            }
         }
 
         if (buttonPressed == MouseEvent.BUTTON1_DOWN_MASK) {
             mousePos = e.getPoint();
-            paintRect();
+            if (lassoMode) {
+                paintLasso();
+            } else {
+                paintRect();
+            }
         } else if (buttonPressed == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK)) {
             mousePosStart.x += e.getX()-mousePos.x;
@@ -182,8 +196,15 @@
         if (mousePos == null || mousePosStart == null)
             return; // injected release from outside
-
         // disable the selection rect
-        paintRect();
-        Rectangle r = getSelectionRectangle();
+        Rectangle r;
+        if (!lassoMode) {
+            paintRect();
+            r = getSelectionRectangle();
+
+            lasso = rectToPolygon(r);
+        } else {
+            lasso.addPoint(mousePos.x, mousePos.y);
+            r = lasso.getBounds();
+        }
         mousePosStart = null;
         mousePos = null;
@@ -207,4 +228,19 @@
         Rectangle r = getSelectionRectangle();
         g.drawRect(r.x,r.y,r.width,r.height);
+    }
+
+    private void paintLasso() {
+        if (mousePos == null || mousePosStart == null || mousePos == mousePosStart) {
+            return;
+        }
+
+        Graphics g = nc.getGraphics();
+        g.setColor(Color.WHITE);
+
+        int lastPosX = lasso.xpoints[lasso.npoints - 1];
+        int lastPosY = lasso.ypoints[lasso.npoints - 1];
+        g.drawLine(lastPosX, lastPosY, mousePos.x, mousePos.y);
+
+        lasso.addPoint(mousePos.x, mousePos.y);
     }
 
@@ -261,17 +297,23 @@
 
     /**
-     * Return a list of all objects in the rectangle, respecting the different
+     * Return a list of all objects in the selection, respecting the different
      * modifier.
-     * @param alt Whether the alt key was pressed, which means select all objects
-     *      that are touched, instead those which are completly covered.
-     */
-    public Collection<OsmPrimitive> getObjectsInRectangle(Rectangle r, boolean alt) {
+     *
+     * @param alt Whether the alt key was pressed, which means select all
+     * objects that are touched, instead those which are completely covered.
+     */
+    public Collection<OsmPrimitive> getSelectedObjects(boolean alt) {
+
         Collection<OsmPrimitive> selection = new LinkedList<OsmPrimitive>();
 
         // whether user only clicked, not dragged.
-        boolean clicked = r.width <= 2 && r.height <= 2;
-        Point center = new Point(r.x+r.width/2, r.y+r.height/2);
+        boolean clicked = false;
+        Rectangle bounding = lasso.getBounds();
+        if (bounding.height <= 2 && bounding.width <= 2) {
+            clicked = true;
+        }
 
         if (clicked) {
+            Point center = new Point(lasso.xpoints[0], lasso.ypoints[0]);
             OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate, false);
             if (osm != null) {
@@ -281,5 +323,5 @@
             // nodes
             for (Node n : nc.getCurrentDataSet().getNodes()) {
-                if (n.isSelectable() && r.contains(nc.getPoint(n))) {
+                if (n.isSelectable() && lasso.contains(nc.getPoint(n))) {
                     selection.add(n);
                 }
@@ -293,5 +335,5 @@
                 if (alt) {
                     for (Node n : w.getNodes()) {
-                        if (!n.isIncomplete() && r.contains(nc.getPoint(n))) {
+                        if (!n.isIncomplete() && lasso.contains(nc.getPoint(n))) {
                             selection.add(w);
                             break;
@@ -301,5 +343,5 @@
                     boolean allIn = true;
                     for (Node n : w.getNodes()) {
-                        if (!n.isIncomplete() && !r.contains(nc.getPoint(n))) {
+                        if (!n.isIncomplete() && !lasso.contains(nc.getPoint(n))) {
                             allIn = false;
                             break;
@@ -315,4 +357,19 @@
     }
 
+    private Polygon rectToPolygon(Rectangle r) {
+        Polygon poly = new Polygon();
+
+        poly.addPoint(r.x, r.y);
+        poly.addPoint(r.x, r.y + r.height);
+        poly.addPoint(r.x + r.width, r.y + r.height);
+        poly.addPoint(r.x + r.width, r.y);
+
+        return poly;
+    }
+
+    public void setLassoMode(boolean lassoMode) {
+        this.lassoMode = lassoMode;
+    }
+
     public void mouseClicked(MouseEvent e) {}
     public void mouseEntered(MouseEvent e) {}
