diff --git a/images/cursor/modifier/rope.png b/images/cursor/modifier/rope.png
new file mode 100644
index 0000000000000000000000000000000000000000..e46cc6e3fe772414beed9777143991b652f95506
GIT binary patch
literal 955
zcmbu7J!@295QWbg#SmCc3K1<NY!qw)!Vplgh`K=oF^2s>JB`Jl1Qk(P1qF#jRwNKC
zgppK!G%MPPMH+3xpf*Z~Y+)mUupm}iIG(wG!3(>WVcz%5bI#oRGt<Y)13L!*lqZi@
zYkUvpufLD~dq=m{fj-PkH6}_xghyC}Mo0v*au2s~4VQ3a(>%<=G)%&fXVpV3R6`{c
zc~v~bLNr7|K&5~OET91iu%I@jsm04YjhvH@xvRUlBge8bb5l2QLsGD*=BlpZiiF}>
zF&A|a7m$%x9p+GnI5?Hm6eBb#iNziVQ=8J%;$@_vtof*!m?8afEGt!0F-6)X1)HKK
zVgkA+6weyeAO_lF9>nBr#zFstphHqqjL@XyQF3rFwJA+4WOCVN%|}#`LDC<`vJz1N
zbEREUu&EFQb7ayCfLuJzpy`%TG7n<%Hsc@@4bvg1DMo1CBo;Y1nA(&^t|(8l&6*Fm
zF$PJ09Lq}hp%h<3+AS8$jpja!B_&jmd#<;LG8v0>a@&RBL@qq!@(ZkVP)wpUwYVjQ
zM^8PV3#<SgpbfNuCQt<`zz{M1quuNEy4~)|%1WoxX}8<0R;$@;R;$%Yr7|>>+Nbt!
zT;;2Dtu|f9__sCU;KF3}aO1}M^`$S{-VXO4o!z8Y?``?CV|j7g`3<N4)Ia=uH#XQ<
z7}+;=^7X>(mD{Cr+vlD%&b*o5HGbgI(>>3ZPSl1UJX~Af-8?w>a<s2D^8Q)h_vO#!
rk1rPMbGIJ<F8z3PdG+SkJAdzPuKgM-_fH+V$f1~=n6AD$a(4b7HS(J{

literal 0
HcmV?d00001

diff --git a/images/mapmode/rope.png b/images/mapmode/rope.png
new file mode 100644
index 0000000000000000000000000000000000000000..1fb5fdd140ad604ab89abd73fc9e1b2246c691e4
GIT binary patch
literal 1544
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

literal 0
HcmV?d00001

diff --git a/src/org/openstreetmap/josm/actions/LassoModeAction.java b/src/org/openstreetmap/josm/actions/LassoModeAction.java
new file mode 100644
index 0000000..fa6de28
--- /dev/null
+++ b/src/org/openstreetmap/josm/actions/LassoModeAction.java
@@ -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();
+    }
+}
diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
index ae2b496..cfe32f0 100644
--- a/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
+++ b/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
@@ -83,6 +83,7 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
         scale("scale", null),
         rotate("rotate", null),
         merge("crosshair", null),
+        lasso("normal", "rope"),
         merge_to_node("crosshair", "joinnode"),
         move(Cursor.MOVE_CURSOR);
 
@@ -98,6 +99,8 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
         }
     }
 
+    private boolean lassoMode = false;
+
     // Cache previous mouse event (needed when only the modifier keys are
     // pressed but the mouse isn't moved)
     private MouseEvent oldEvent = null;
@@ -171,8 +174,7 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
         super.enterMode();
         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
         try {
@@ -240,7 +242,11 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
             c = "scale";
             break;
         case select:
-            c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : ""));
+            if (lassoMode) {
+                c = "lasso";
+            } else {
+                c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : ""));
+            }
             break;
         }
         return SelectActionCursor.valueOf(c).cursor();
@@ -726,7 +732,7 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
             break;
         case select:
         default:
-            selectionManager.register(mv);
+            selectionManager.register(mv, lassoMode);
             selectionManager.mousePressed(e);
             break;
         }
@@ -824,7 +830,8 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
 
     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);
     }
 
     /**
@@ -973,4 +980,10 @@ public class SelectAction extends MapMode implements AWTEventListener, Selection
     public boolean layerIsSupported(Layer l) {
         return l instanceof OsmDataLayer;
     }
+
+    public void setLassoMode(boolean lassoMode) {
+        System.out.println(lassoMode);
+        this.selectionManager.setLassoMode(lassoMode);
+        this.lassoMode = lassoMode;
+    }
 }
diff --git a/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java b/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
index 942ef20..e62dd29 100644
--- a/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
+++ b/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
@@ -59,7 +59,7 @@ public class ZoomAction extends MapMode implements SelectionEnded {
 
     @Override public void enterMode() {
         super.enterMode();
-        selectionManager.register(Main.map.mapView);
+        selectionManager.register(Main.map.mapView, false);
     }
 
     @Override public void exitMode() {
diff --git a/src/org/openstreetmap/josm/gui/MapFrame.java b/src/org/openstreetmap/josm/gui/MapFrame.java
index 70dd5c5..95add75 100644
--- a/src/org/openstreetmap/josm/gui/MapFrame.java
+++ b/src/org/openstreetmap/josm/gui/MapFrame.java
@@ -40,6 +40,7 @@ import javax.swing.plaf.basic.BasicSplitPaneDivider;
 import javax.swing.plaf.basic.BasicSplitPaneUI;
 
 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;
 import org.openstreetmap.josm.actions.mapmode.ExtrudeAction;
@@ -108,7 +109,7 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
     public PropertiesDialog propertiesDialog;
 
     // Map modes
-    private final MapMode mapModeSelect;
+    public final SelectAction mapModeSelect;
     private final MapMode mapModeDraw;
     private final MapMode mapModeZoom;
 
@@ -158,6 +159,7 @@ public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
         // toolbar
         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)));
         addMapMode(new IconToggleButton(new DeleteAction(this), true));
diff --git a/src/org/openstreetmap/josm/gui/SelectionManager.java b/src/org/openstreetmap/josm/gui/SelectionManager.java
index 305d306..5c14f01 100644
--- a/src/org/openstreetmap/josm/gui/SelectionManager.java
+++ b/src/org/openstreetmap/josm/gui/SelectionManager.java
@@ -5,6 +5,7 @@ import java.awt.Color;
 import java.awt.Component;
 import java.awt.Graphics;
 import java.awt.Point;
+import java.awt.Polygon;
 import java.awt.Rectangle;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
@@ -96,6 +97,9 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
      */
     private boolean aspectRatio;
 
+    private boolean lassoMode;
+    private Polygon lasso = new Polygon();
+
     /**
      * Create a new SelectionManager.
      *
@@ -115,7 +119,8 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
      * Register itself at the given event source.
      * @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);
         selectionEndedListener.addPropertyChangeListener(this);
@@ -146,6 +151,9 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
     public void mousePressed(MouseEvent e) {
         if (e.getButton() == MouseEvent.BUTTON1) {
             mousePosStart = mousePos = e.getPoint();
+
+            lasso.reset();
+            lasso.addPoint(mousePosStart.x, mousePosStart.y);
         }
     }
 
@@ -159,12 +167,18 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
             if (mousePosStart == null) {
                 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;
             mousePosStart.y += e.getY()-mousePos.y;
@@ -181,10 +195,17 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
             return;
         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;
 
@@ -208,6 +229,21 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
         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);
+    }
+
     /**
      * Calculate and return the current selection rectangle
      * @return A rectangle that spans from mousePos to mouseStartPos
@@ -260,19 +296,25 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
     }
 
     /**
-     * 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.
+     *
+     * @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> getObjectsInRectangle(Rectangle r, boolean alt) {
+    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) {
                 selection.add(osm);
@@ -280,7 +322,7 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
         } else {
             // 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);
                 }
             }
@@ -292,7 +334,7 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
                 }
                 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;
                         }
@@ -300,7 +342,7 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
                 } else {
                     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;
                         }
@@ -314,6 +356,21 @@ public class SelectionManager implements MouseListener, MouseMotionListener, Pro
         return selection;
     }
 
+    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) {}
     public void mouseExited(MouseEvent e) {}
