Index: src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java	(working copy)
@@ -5,7 +5,6 @@
 
 import java.awt.AWTEvent;
 import java.awt.Cursor;
-import java.awt.EventQueue;
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
@@ -13,10 +12,13 @@
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.DeleteCommand;
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -44,18 +46,20 @@
  *
  * @author imi
  */
-
-/**
- * This class contains stubs for highlighting affected primitives when affected.
- * However, way segments can be deleted as well, but cannot be highlighted
- * alone. If the highlight feature for this delete action is to be implemented
- * properly, highlighting way segments must be possible first. --xeen, 2009-09-02
- */
 public class DeleteAction extends MapMode implements AWTEventListener {
     // Cache previous mouse event (needed when only the modifier keys are
     // pressed but the mouse isn't moved)
     private MouseEvent oldEvent = null;
 
+    /**
+     * elements that have been highlighted in the previous iteration. Used
+     * to remove the highlight from them again as otherwise the whole data
+     * set would have to be checked.
+     */
+    private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>();
+
+    private boolean drawTargetHighlight;
+
     private enum DeleteMode {
         none("delete"),
         segment("delete_segment"),
@@ -100,6 +104,8 @@
         if (!isEnabled())
             return;
 
+        drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
+
         Main.map.mapView.addMouseListener(this);
         Main.map.mapView.addMouseMotionListener(this);
         // This is required to update the cursors when ctrl/shift/alt is pressed
@@ -119,6 +125,7 @@
         } catch (SecurityException ex) {
             System.out.println(ex);
         }
+        removeHighlighting();
     }
 
     @Override public void actionPerformed(ActionEvent e) {
@@ -156,20 +163,65 @@
      */
     @Override public void mouseMoved(MouseEvent e) {
         oldEvent = e;
-        updateCursor(e, e.getModifiers());
+        giveUserFeedback(e);
     }
 
     /**
+     * removes any highlighting that may have been set beforehand.
+     */
+    private void removeHighlighting() {
+        for(OsmPrimitive prim : oldHighlights) {
+            prim.setHighlighted(false);
+        }
+        oldHighlights = new HashSet<OsmPrimitive>();
+        DataSet ds = getCurrentDataSet();
+        if(ds != null) {
+            ds.clearHighlightedWaySegments();
+        }
+    }
+
+    /**
+     * handles everything related to highlighting primitives and way
+     * segments for the given pointer position (via MouseEvent) and
+     * modifiers.
+     * @param e
+     * @param modifiers
+     */
+    private void addHighlighting(MouseEvent e, int modifiers) {
+        if(!drawTargetHighlight)
+            return;
+        removeHighlighting();
+
+        Command delCmd = buildDeleteCommands(e, modifiers, true);
+        if(delCmd == null) {
+            Main.map.mapView.repaint();
+            return;
+        }
+
+        DeleteParameters parameters = getDeleteParameters(e, modifiers);
+
+        if(parameters.mode == DeleteMode.segment) {
+            // deleting segments is the only action not working on OsmPrimitives
+            // so we have to handle them separately.
+            DataSet ds = getCurrentDataSet();
+            if(ds != null) {
+                ds.setHighlightedWaySegments(Collections.singleton(parameters.nearestSegment));
+            }
+        } else {
+            // all other cases delete OsmPrimitives directly, so we can
+            // safely do the following
+            for(OsmPrimitive osm : delCmd.getParticipatingPrimitives()) {
+                osm.setHighlighted(true);
+                oldHighlights.add(osm);
+            }
+        }
+        Main.map.mapView.repaint();
+    }
+
+    /**
      * This function handles all work related to updating the cursor and
-     * highlights. For now, only the cursor is enabled because highlighting
-     * requires WaySegment to be highlightable.
+     * highlights
      *
-     * Normally the mouse event also contains the modifiers. However, when the
-     * mouse is not moved and only modifier keys are pressed, no mouse event
-     * occurs. We can use AWTEvent to catch those but still lack a proper
-     * mouseevent. Instead we copy the previous event and only update the
-     * modifiers.
-     *
      * @param MouseEvent
      * @param int modifiers
      */
@@ -182,8 +234,32 @@
         DeleteParameters parameters = getDeleteParameters(e, modifiers);
         Main.map.mapView.setNewCursor(parameters.mode.cursor(), this);
     }
+    /**
+     * Gives the user feedback for the action he/she is about to do. Currently
+     * calls the cursor and target highlighting routines. Allows for modifiers
+     * not taken from the given mouse event.
+     * 
+     * Normally the mouse event also contains the modifiers. However, when the
+     * mouse is not moved and only modifier keys are pressed, no mouse event
+     * occurs. We can use AWTEvent to catch those but still lack a proper
+     * mouseevent. Instead we copy the previous event and only update the
+     * modifiers.
+     */
+    private void giveUserFeedback(MouseEvent e, int modifiers) {
+        updateCursor(e, modifiers);
+        addHighlighting(e, modifiers);
+    }
 
     /**
+     * Gives the user feedback for the action he/she is about to do. Currently
+     * calls the cursor and target highlighting routines. Extracts modifiers
+     * from mouse event.
+     */
+    private void giveUserFeedback(MouseEvent e) {
+        giveUserFeedback(e, e.getModifiers());
+    }
+
+    /**
      * If user clicked with the left button, delete the nearest object.
      * position.
      */
@@ -203,6 +279,7 @@
         }
 
         getCurrentDataSet().setSelected();
+        giveUserFeedback(e);
         Main.map.mapView.repaint();
     }
 
@@ -241,11 +318,7 @@
     }
 
     private DeleteParameters getDeleteParameters(MouseEvent e, int modifiers) {
-        // Note: CTRL is the only modifier that is checked in MouseMove, don't
-        // forget updating it there
-        boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
-        boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
-        boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
+        updateKeyModifiers(modifiers);
 
         DeleteParameters result = new DeleteParameters();
 
@@ -307,6 +380,6 @@
     public void eventDispatched(AWTEvent e) {
         // We don't have a mouse event, so we pass the old mouse event but the
         // new modifiers.
-        updateCursor(oldEvent, ((InputEvent)e).getModifiers());
+        giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers());
     }
 }
Index: src/org/openstreetmap/josm/actions/mapmode/MapMode.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/MapMode.java	(working copy)
@@ -3,6 +3,7 @@
 
 import java.awt.Cursor;
 import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
@@ -24,6 +25,9 @@
  */
 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
     protected final Cursor cursor;
+    protected boolean ctrl;
+    protected boolean alt;
+    protected boolean shift;
 
     /**
      * Constructor for mapmodes without an menu
@@ -76,6 +80,20 @@
         return true;
     }
 
+    protected void updateKeyModifiers(InputEvent e) {
+        updateKeyModifiers(e.getModifiers());
+    }
+
+    protected void updateKeyModifiers(MouseEvent e) {
+        updateKeyModifiers(e.getModifiers());
+    }
+
+    protected void updateKeyModifiers(int modifiers) {
+        ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
+        alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
+        shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
+    }
+
     public void mouseReleased(MouseEvent e) {}
     public void mouseExited(MouseEvent e) {}
     public void mousePressed(MouseEvent e) {}
Index: src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/PlayHeadDragMode.java	(working copy)
@@ -5,7 +5,6 @@
 
 import java.awt.Cursor;
 import java.awt.Point;
-import java.awt.event.ActionEvent;
 import java.awt.event.MouseEvent;
 
 import org.openstreetmap.josm.Main;
@@ -27,7 +26,7 @@
 
     public PlayHeadDragMode(PlayHeadMarker m) {
         super(tr("Drag play head"), "playheaddrag", tr("Drag play head"), null,
-        Main.map, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+                Main.map, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
         playHeadMarker = m;
     }
 
@@ -67,7 +66,9 @@
         mouseStart = null;
         if (ev.getButton() != MouseEvent.BUTTON1 || p == null || ! dragging)
             return;
-        boolean shift = (ev.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
+
+        updateKeyModifiers(ev);
+
         EastNorth en = Main.map.mapView.getEastNorth(ev.getX(), ev.getY());
         if (! shift) {
             playHeadMarker.reposition(en);
Index: src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/DrawAction.java	(working copy)
@@ -8,12 +8,10 @@
 import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Cursor;
-import java.awt.EventQueue;
 import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
-import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -65,9 +63,6 @@
     private Node lastUsedNode = null;
     private double PHI=Math.toRadians(90);
 
-    private boolean ctrl;
-    private boolean alt;
-    private boolean shift;
     private Node mouseOnExistingNode;
     private Set<Way> mouseOnExistingWays = new HashSet<Way>();
     private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>();
@@ -512,8 +507,8 @@
 
         getCurrentDataSet().setSelected(newSelection);
 
-        // "viewport following" mode for tracing long features 
-        // from aerial imagery or GPS tracks. 
+        // "viewport following" mode for tracing long features
+        // from aerial imagery or GPS tracks.
         if (n != null && Main.map.mapView.viewportFollowing) {
             Main.map.mapView.smoothScrollTo(n.getEastNorth());
         };
@@ -601,18 +596,6 @@
         redrawIfRequired();
     }
 
-    private void updateKeyModifiers(InputEvent e) {
-        ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-        alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
-        shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
-    }
-
-    private void updateKeyModifiers(MouseEvent e) {
-        ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-        alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
-        shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
-    }
-
     /**
      * This method prepares data required for painting the "helper line" from
      * the last used position to the mouse cursor. It duplicates some code from
Index: src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java	(working copy)
@@ -13,7 +13,6 @@
 import java.awt.Stroke;
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
-import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
@@ -108,10 +107,6 @@
 
     private final MapView mv;
 
-    private boolean ctrl;
-    private boolean alt;
-    private boolean shift;
-
     // Mouse tracking state
     private Point mousePressedPos;
     private boolean mouseIsDown;
@@ -232,9 +227,7 @@
 
     private boolean updateModifiersState(InputEvent e) {
         boolean oldAlt = alt, oldShift = shift, oldCtrl = ctrl;
-        alt = (e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0;
-        ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-        shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
+        updateKeyModifiers(e);
         boolean changed = (oldAlt != alt || oldShift != shift || oldCtrl != ctrl);
         return changed;
     }
@@ -393,9 +386,8 @@
             // event can come quite late
             if (!isModifiersValidForDragMode())
                 return;
-            if (!initParallelWays(mousePressedPos, copyTags)) {
+            if (!initParallelWays(mousePressedPos, copyTags))
                 return;
-            }
             setMode(Mode.dragging);
         }
 
@@ -408,7 +400,7 @@
         double d = enp.distance(nearestPointOnRefLine);
         double realD = mv.getProjection().eastNorth2latlon(enp).greatCircleDistance(mv.getProjection().eastNorth2latlon(nearestPointOnRefLine));
         double snappedRealD = realD;
-        
+
         // TODO: abuse of isToTheRightSideOfLine function.
         boolean toTheRight = Geometry.isToTheRightSideOfLine(referenceSegment.getFirstNode(),
                 referenceSegment.getFirstNode(), referenceSegment.getSecondNode(), new Node(enp));
@@ -430,7 +422,7 @@
             d = -d;
         }
         pWays.changeOffset(d);
-        
+
         Main.map.statusLine.setDist(Math.abs(snappedRealD));
         Main.map.statusLine.repaint();
         mv.repaint();
Index: src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(working copy)
@@ -5,9 +5,12 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trn;
 
+import java.awt.AWTEvent;
 import java.awt.Cursor;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.AWTEventListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
@@ -15,8 +18,10 @@
 import java.awt.geom.Point2D;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.Set;
 
 import javax.swing.JOptionPane;
 
@@ -59,12 +64,44 @@
  *
  * @author imi
  */
-public class SelectAction extends MapMode implements SelectionEnded {
+public class SelectAction extends MapMode implements AWTEventListener, SelectionEnded {
+    // "select" means the selection rectangle and "move" means either dragging
+    // or select if no mouse movement occurs (i.e. just clicking)
     enum Mode { move, rotate, scale, select }
-    
+
+    // contains all possible cases the cursor can be in the SelectAction except the
+    // the move pointer (latter is a system one and not an image)
+    private enum SelectActionCursor {
+        rect("normal", "selection"),
+        rect_add("normal", "select_add"),
+        rect_rm("normal", "select_remove"),
+        way("normal", "select_way"),
+        way_add("normal", "select_way_add"),
+        way_rm("normal", "select_way_remove"),
+        node("normal", "select_node"),
+        node_add("normal", "select_node_add"),
+        node_rm("normal", "select_node_remove"),
+        virtual_node("normal", "addnode"),
+        scale("scale", null),
+        rotate("rotate", null);
+
+        private final Cursor c;
+        private SelectActionCursor(String main, String sub) {
+            c = ImageProvider.getCursor(main, sub);
+        }
+        public Cursor cursor() {
+            return c;
+        }
+    }
+
+    // Cache previous mouse event (needed when only the modifier keys are
+    // pressed but the mouse isn't moved)
+    private MouseEvent oldEvent = null;
+
     private Mode mode = null;
     private SelectionManager selectionManager;
     private boolean cancelDrawMode = false;
+    private boolean drawTargetHighlight;
     private boolean didMouseDrag = false;
     /**
      * The component this SelectAction is associated with.
@@ -95,6 +132,13 @@
     private boolean initialMoveThresholdExceeded = false;
 
     /**
+     * elements that have been highlighted in the previous iteration. Used
+     * to remove the highlight from them again as otherwise the whole data
+     * set would have to be checked.
+     */
+    private Set<OsmPrimitive> oldHighlights = new HashSet<OsmPrimitive>();
+
+    /**
      * Create a new SelectAction
      * @param mapFrame The MapFrame this action belongs to.
      */
@@ -108,6 +152,13 @@
         selectionManager = new SelectionManager(this, false, mv);
         initialMoveDelay = Main.pref.getInteger("edit.initial-move-delay", 200);
         initialMoveThreshold = Main.pref.getInteger("edit.initial-move-threshold", 5);
+        drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
+        // This is required to update the cursors when ctrl/shift/alt is pressed
+        try {
+            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
+        } catch (SecurityException ex) {
+            System.out.println(ex);
+        }
     }
 
     @Override
@@ -126,9 +177,133 @@
         mv.removeMouseListener(this);
         mv.removeMouseMotionListener(this);
         mv.setVirtualNodesEnabled(false);
+        removeHighlighting();
     }
 
     /**
+     * works out which cursor should be displayed for most of SelectAction's
+     * features. The only exception is the "move" cursor when actually dragging
+     * primitives.
+     * @param nearbyStuff  primitives near the cursor
+     * @return the cursor that should be displayed
+     */
+    private Cursor getCursor(Collection<OsmPrimitive> nearbyStuff) {
+        String c = "rect";
+        switch(mode) {
+        case move:
+            if(virtualNode != null) {
+                c = "virtual_node";
+                break;
+            }
+
+            // nearbyStuff cannot be empty as otherwise we would be in
+            // Move.select and not Move.move
+            OsmPrimitive osm = nearbyStuff.iterator().next();
+
+            c = (osm instanceof Node) ? "node" : c;
+            c = (osm instanceof Way) ? "way" : c;
+
+            if(shift)
+                c += "_add";
+            else if(ctrl)
+                c += osm.isSelected() ? "_rm" : "_add";
+            break;
+        case rotate:
+            c = "rotate";
+            break;
+        case scale:
+            c = "scale";
+            break;
+        case select:
+            c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : ""));
+            break;
+        }
+        return SelectActionCursor.valueOf(c).cursor();
+    }
+
+    /**
+     * Removes all existing highlights.
+     * @return true if a repaint is required
+     */
+    private boolean removeHighlighting() {
+        boolean needsRepaint = false;
+        DataSet ds = getCurrentDataSet();
+        if(ds != null && !ds.getHighlightedVirtualNodes().isEmpty()) {
+            needsRepaint = true;
+            ds.clearHighlightedVirtualNodes();
+        }
+        if(oldHighlights.isEmpty())
+            return needsRepaint;
+
+        for(OsmPrimitive prim : oldHighlights) {
+            prim.setHighlighted(false);
+        }
+        oldHighlights = new HashSet<OsmPrimitive>();
+        return true;
+    }
+
+    /**
+     * handles adding highlights and updating the cursor for the given mouse event.
+     * @param MouseEvent which should be used as base for the feedback
+     * @return true if repaint is required
+     */
+    private boolean giveUserFeedback(MouseEvent e) {
+        return giveUserFeedback(e, e.getModifiers());
+    }
+
+    /**
+     * handles adding highlights and updating the cursor for the given mouse event.
+     * @param MouseEvent which should be used as base for the feedback
+     * @param define custom keyboard modifiers if the ones from MouseEvent are outdated or similar
+     * @return true if repaint is required
+     */
+    private boolean giveUserFeedback(MouseEvent e, int modifiers) {
+        boolean needsRepaints = false;
+
+        Collection<OsmPrimitive> c = MapView.asColl(
+                mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true));
+
+        updateKeyModifiers(modifiers);
+        determineMapMode(!c.isEmpty());
+
+        if(drawTargetHighlight)
+            needsRepaints = removeHighlighting();
+
+        virtualWays.clear();
+        virtualNode = null;
+        if(mode == Mode.move && setupVirtual(e)) {
+            DataSet ds = getCurrentDataSet();
+            if (ds != null) {
+                ds.setHighlightedVirtualNodes(virtualWays);
+            }
+            mv.setNewCursor(SelectActionCursor.virtual_node.cursor(), this);
+            // don't highlight anything else if a virtual node will be
+            return true;
+        }
+
+        mv.setNewCursor(getCursor(c), this);
+
+        // return early if there can't be any highlights
+        if(!drawTargetHighlight || mode != Mode.move || c.isEmpty())
+            return needsRepaints;
+
+        oldHighlights = (Set<OsmPrimitive>) c;
+        for(OsmPrimitive x : c) {
+            x.setHighlighted(true);
+        }
+        return true;
+    }
+
+    /**
+     * This is called whenever the keyboard modifier status changes
+     */
+    public void eventDispatched(AWTEvent e) {
+        // We don't have a mouse event, so we pass the old mouse event but the
+        // new modifiers.
+        giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers());
+    }
+
+    /**
      * If the left mouse button is pressed, move all currently selected
      * objects (if one of them is under the mouse) or the current one under the
      * mouse (which will become selected).
@@ -263,11 +438,21 @@
     @Override
     public void mouseMoved(MouseEvent e) {
         // Mac OSX simulates with  ctrl + mouse 1  the second mouse button hence no dragging events get fired.
-        //
         if ((Main.platform instanceof PlatformHookOsx) && (mode == Mode.rotate || mode == Mode.scale)) {
             mouseDragged(e);
+            return;
         }
+        oldEvent = e;
+        if(giveUserFeedback(e))
+            mv.repaint();
     }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+        if(removeHighlighting())
+            mv.repaint();
+    }
+
     private Node virtualNode = null;
     private Collection<WaySegment> virtualWays = new LinkedList<WaySegment>();
 
@@ -338,8 +523,8 @@
 
             Point p = e.getPoint();
             boolean waitForMouseUp = Main.pref.getBoolean("mappaint.select.waits-for-mouse-up", false);
-            boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-            boolean alt = ((e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0 || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false));
+            updateKeyModifiers(e);
+            alt = alt || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false);
 
             if (!alt) {
                 cycleList = MapView.asColl(osm);
@@ -388,6 +573,24 @@
     }
 
     /**
+     * sets the mapmode according to key modifiers and if there are any
+     * selectables nearby. Everything has to be pre-determined for this
+     * function; its main purpose is to centralize what the modifiers do.
+     * @param nearSelectables
+     */
+    private void determineMapMode(boolean hasSelectionNearby) {
+        if (shift && ctrl) {
+            mode = Mode.rotate;
+        } else if (alt && ctrl) {
+            mode = Mode.scale;
+        } else if (hasSelectionNearby) {
+            mode = Mode.move;
+        } else {
+            mode = Mode.select;
+        }
+    }
+
+    /**
      * Look, whether any object is selected. If not, select the nearest node.
      * If there are no nodes in the dataset, do nothing.
      *
@@ -399,16 +602,14 @@
     @Override
     public void mousePressed(MouseEvent e) {
         // return early
-        if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1) {
+        if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1)
             return;
-        }
 
         // request focus in order to enable the expected keyboard shortcuts
         mv.requestFocus();
 
-        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-        boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
-        boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
+        // update which modifiers are pressed (shift, alt, ctrl)
+        updateKeyModifiers(e);
 
         // We don't want to change to draw tool if the user tries to (de)select
         // stuff but accidentally clicks in an empty area when selection is empty
@@ -421,9 +622,10 @@
         Collection<OsmPrimitive> c = MapView.asColl(
                 mv.getNearestNodeOrWay(e.getPoint(), OsmPrimitive.isSelectablePredicate, true));
 
-        if (shift && ctrl) {
-            mode = Mode.rotate;
-
+        determineMapMode(!c.isEmpty());
+        switch(mode) {
+        case rotate:
+        case scale:
             if (getCurrentDataSet().getSelected().isEmpty()) {
                 getCurrentDataSet().setSelected(c);
             }
@@ -431,47 +633,36 @@
             // Mode.select redraws when selectPrims is called
             // Mode.move   redraws when mouseDragged is called
             // Mode.rotate redraws here
-            mv.setNewCursor(ImageProvider.getCursor("rotate", null), this);
-            mv.repaint();
-        } else if (alt && ctrl) {
-            mode = Mode.scale;
-
-            if (getCurrentDataSet().getSelected().isEmpty()) {
-                getCurrentDataSet().setSelected(c);
-            }
-
-            // Mode.select redraws when selectPrims is called
-            // Mode.move   redraws when mouseDragged is called
             // Mode.scale redraws here
-            mv.setNewCursor(ImageProvider.getCursor("scale", null), this);
             mv.repaint();
-        } else if (!c.isEmpty()) {
-            mode = Mode.move;
-
+            break;
+        case move:
             if (!cancelDrawMode && c.iterator().next() instanceof Way) {
                 setupVirtual(e);
             }
 
             selectPrims(cycleSetup(c, e), e, false, false);
-        } else {
-            mode = Mode.select;
-
+            break;
+        case select:
+        default:
             selectionManager.register(mv);
             selectionManager.mousePressed(e);
+            break;
         }
-
+        // this doesn't require repainting since the mouse was only pressed
+        // but not moved, therefore the highlighted elements will still be
+        // the same
+        giveUserFeedback(e);
         updateStatusLine();
     }
 
     @Override
     public void mouseReleased(MouseEvent e) {
-        if (!mv.isActiveLayerVisible()) {
+        if (!mv.isActiveLayerVisible())
             return;
-        }
 
         startingDraggingPos = null;
 
-        mv.setNewCursor(cursor, this);
         if (mode == Mode.select) {
             selectionManager.unregister(mv);
 
@@ -488,7 +679,7 @@
                 virtualWays.clear();
                 virtualNode = null;
 
-                // do nothing if the click was to short to be recognized as a drag,
+                // do nothing if the click was to short too be recognized as a drag,
                 // but the release position is farther than 10px away from the press position
                 if (lastMousePos.distanceSq(e.getPoint()) < 100) {
                     selectPrims(cyclePrims(cycleList, e), e, true, false);
@@ -499,7 +690,6 @@
                         // We need to do it like this as otherwise drawAction will see a double
                         // click and switch back to SelectMode
                         Main.worker.execute(new Runnable() {
-
                             public void run() {
                                 Main.map.selectDrawTool(true);
                             }
@@ -538,14 +728,13 @@
             }
         }
 
-        // I don't see why we need this.
-        //updateStatusLine();
         mode = null;
+        giveUserFeedback(e);
         updateStatusLine();
     }
 
     public void selectionEnded(Rectangle r, MouseEvent e) {
-        boolean alt = (e.getModifiersEx() & (MouseEvent.ALT_DOWN_MASK | MouseEvent.ALT_GRAPH_DOWN_MASK)) != 0;
+        updateKeyModifiers(e);
         selectPrims(selectionManager.getObjectsInRectangle(r, alt), e, true, true);
     }
 
@@ -553,16 +742,14 @@
      * Modifies current selection state and returns the next element in a
      * selection cycle given by <code>prims</code>.
      * @param prims the primitives that form the selection cycle
-     * @param shift whether shift is pressed
-     * @param ctrl whether ctrl is pressed
+     * @param mouse event
      * @return the next element of cycle list <code>prims</code>.
      */
     private Collection<OsmPrimitive> cyclePrims(Collection<OsmPrimitive> prims, MouseEvent e) {
         OsmPrimitive nxt = null;
 
         if (prims.size() > 1) {
-            boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-            boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
+            updateKeyModifiers(e);
 
             DataSet ds = getCurrentDataSet();
             OsmPrimitive first = prims.iterator().next(), foundInDS = null;
@@ -629,14 +816,12 @@
     }
 
     private void selectPrims(Collection<OsmPrimitive> prims, MouseEvent e, boolean released, boolean area) {
-        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
-        boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
+        updateKeyModifiers(e);
         DataSet ds = getCurrentDataSet();
 
         // not allowed together: do not change dataset selection, return early
-        if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty())) {
+        if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty()))
             return;
-        }
 
         if (!released) {
             // Don't replace the selection if the user clicked on a
@@ -665,17 +850,16 @@
 
     @Override
     public String getModeHelpText() {
-        if (mode == Mode.select) {
+        if (mode == Mode.select)
             return tr("Release the mouse button to select the objects in the rectangle.");
-        } else if (mode == Mode.move) {
+        else if (mode == Mode.move)
             return tr("Release the mouse button to stop moving. Ctrl to merge with nearest node.");
-        } else if (mode == Mode.rotate) {
+        else if (mode == Mode.rotate)
             return tr("Release the mouse button to stop rotating.");
-        } else if (mode == Mode.scale) {
+        else if (mode == Mode.scale)
             return tr("Release the mouse button to stop scaling.");
-        } else {
+        else
             return tr("Move objects by dragging; Shift to add to selection (Ctrl to toggle); Shift-Ctrl to rotate selected; Alt-Ctrl to scale selected; or change selection");
-        }
     }
 
     @Override
Index: src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 4320)
+++ src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(working copy)
@@ -184,6 +184,8 @@
         if (e.getButton() != MouseEvent.BUTTON1)
             return;
 
+        updateKeyModifiers(e);
+
         selectedSegment = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate);
 
         if (selectedSegment == null) {
@@ -191,9 +193,9 @@
         } else {
             // Otherwise switch to another mode
 
-            if ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0) {
+            if (ctrl) {
                 mode = Mode.translate;
-            } else if ((e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0) {
+            } else if (alt) {
                 mode = Mode.create_new;
                 // create a new segment and then select and extrude the new segment
                 getCurrentDataSet().setSelected(selectedSegment.way);
@@ -201,7 +203,7 @@
             } else {
                 mode = Mode.extrude;
                 getCurrentDataSet().setSelected(selectedSegment.way);
-                alwaysCreateNodes = ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0);
+                alwaysCreateNodes = shift;
             }
 
             // remember initial positions for segment nodes.
Index: src/org/openstreetmap/josm/data/osm/WaySegment.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/WaySegment.java	(revision 4320)
+++ src/org/openstreetmap/josm/data/osm/WaySegment.java	(working copy)
@@ -29,6 +29,17 @@
         return way.getNode(lowerIndex + 1);
     }
 
+    /**
+     * returns this way segment as complete way.
+     * @return
+     */
+    public Way toWay() {
+        Way w = new Way();
+        w.addNode(getFirstNode());
+        w.addNode(getSecondNode());
+        return w;
+    }
+
     @Override public boolean equals(Object o) {
         return o != null && o instanceof WaySegment
             && ((WaySegment) o).way == way
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 4320)
+++ src/org/openstreetmap/josm/data/osm/DataSet.java	(working copy)
@@ -114,6 +114,10 @@
     private Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new IdHash());
     private CopyOnWriteArrayList<DataSetListener> listeners = new CopyOnWriteArrayList<DataSetListener>();
 
+    // provide means to highlight map elements that are not osm primitives
+    private Collection<WaySegment> highlightedVirtualNodes = new LinkedList<WaySegment>();
+    private Collection<WaySegment> highlightedWaySegments = new LinkedList<WaySegment>();
+
     // Number of open calls to beginUpdate
     private int updateCount;
     // Events that occurred while dataset was locked but should be fired after write lock is released
@@ -430,6 +434,27 @@
     }
 
     /**
+     * returns an unmodifiable collection of *WaySegments* whose virtual
+     * nodes should be highlighted. WaySegements are used to avoid having
+     * to create a VirtualNode class that wouldn't have much purpose otherwise.
+     * 
+     * @return unmodifiable collection of WaySegements
+     */
+    public Collection<WaySegment> getHighlightedVirtualNodes() {
+        return Collections.unmodifiableCollection(highlightedVirtualNodes);
+    }
+
+    /**
+     * returns an unmodifiable collection of WaySegments that should be
+     * highlighted.
+     * 
+     * @return unmodifiable collection of WaySegements
+     */
+    public Collection<WaySegment> getHighlightedWaySegments() {
+        return Collections.unmodifiableCollection(highlightedWaySegments);
+    }
+
+    /**
      * Replies an unmodifiable collection of primitives currently selected
      * in this dataset. May be empty, but not null.
      *
@@ -507,6 +532,34 @@
     }
 
     /**
+     * set what virtual nodes should be highlighted. Requires a Collection of
+     * *WaySegements* to avoid a VirtualNode class that wouldn't have much use
+     * otherwise.
+     * @param Collection of waySegments
+     */
+    public void setHighlightedVirtualNodes(Collection<WaySegment> waySegments) {
+        if(highlightedVirtualNodes.isEmpty() && waySegments.isEmpty())
+            return;
+
+        highlightedVirtualNodes = waySegments;
+        // can't use fireHighlightingChanged because it requires an OsmPrimitive
+        highlightUpdateCount++;
+    }
+
+    /**
+     * set what virtual ways should be highlighted.
+     * @param Collection of waySegments
+     */
+    public void setHighlightedWaySegments(Collection<WaySegment> waySegments) {
+        if(highlightedWaySegments.isEmpty() && waySegments.isEmpty())
+            return;
+
+        highlightedWaySegments = waySegments;
+        // can't use fireHighlightingChanged because it requires an OsmPrimitive
+        highlightUpdateCount++;
+    }
+
+    /**
      * Sets the current selection to the primitives in <code>selection</code>.
      * Notifies all {@see SelectionChangedListener} if <code>fireSelectionChangeEvent</code> is true.
      *
@@ -592,6 +645,20 @@
     }
 
     /**
+     * clear all highlights of virtual nodes
+     */
+    public void clearHighlightedVirtualNodes() {
+        setHighlightedVirtualNodes(new ArrayList<WaySegment>());
+    }
+
+    /**
+     * clear all highlights of way segments
+     */
+    public void clearHighlightedWaySegments() {
+        setHighlightedWaySegments(new ArrayList<WaySegment>());
+    }
+
+    /**
      * Remove the selection from every value in the collection.
      * @param list The collection to remove the selection from.
      */
Index: src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(revision 4320)
+++ src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java	(working copy)
@@ -20,6 +20,7 @@
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
@@ -34,6 +35,7 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
 import org.openstreetmap.josm.gui.NavigatableComponent;
@@ -41,8 +43,8 @@
 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.HorizontalTextAlignment;
 import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.VerticalTextAlignment;
 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
+import org.openstreetmap.josm.gui.mappaint.TextElement;
 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol;
-import org.openstreetmap.josm.gui.mappaint.TextElement;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Pair;
 
@@ -52,6 +54,7 @@
     private final NavigatableComponent nc;
     private final boolean inactive;
     private final MapPaintSettings settings;
+    private final Collection<WaySegment> highlightWaySegments;
 
     private final boolean useStrokes;
     private final boolean showNames;
@@ -63,6 +66,7 @@
     private final Color selectedColor;
     private final Color relationSelectedColor;
     private final Color nodeColor;
+    private final Color highlightColor;
     private final Color backgroundColor;
 
     private final Font orderFont;
@@ -80,11 +84,13 @@
 
     public MapPainter(MapPaintSettings settings, Graphics2D g,
             boolean inactive, NavigatableComponent nc, boolean virtual,
-            double circum, boolean leftHandTraffic){
+            double circum, boolean leftHandTraffic,
+            Collection<WaySegment> highlightWaySegments){
         this.settings = settings;
         this.g = g;
         this.inactive = inactive;
         this.nc = nc;
+        this.highlightWaySegments = highlightWaySegments;
         this.useStrokes = settings.getUseStrokesDistance() > circum;
         this.showNames = settings.getShowNamesDistance() > circum;
         this.showIcons = settings.getShowIconsDistance() > circum;
@@ -95,6 +101,7 @@
         this.selectedColor = PaintColors.SELECTED.get();
         this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
         this.nodeColor = PaintColors.NODE.get();
+        this.highlightColor = PaintColors.HIGHLIGHT.get();
         this.backgroundColor = PaintColors.getBackgroundColor();
 
         this.orderFont = new Font(Main.pref.get("mappaint.font", "Helvetica"), Font.PLAIN, Main.pref.getInteger("mappaint.fontsize", 8));
@@ -130,8 +137,20 @@
         boolean initialMoveToNeeded = true;
         List<Node> wayNodes = way.getNodes();
         if (wayNodes.size() < 2) return;
-        
-        Iterator<Point> it = new OffsetIterator(way.getNodes(), offset);
+
+        Collection<Integer> segmentsToHighlight = new ArrayList<Integer>();
+        // only highlight the segment if the way itself is not highlighted
+        if(!way.isHighlighted()) {
+            for(WaySegment ws : highlightWaySegments) {
+                if(ws.way != way || ws.lowerIndex < offset) {
+                    continue;
+                }
+                segmentsToHighlight.add(ws.lowerIndex+1);
+            }
+        }
+        GeneralPath highlightSegs = segmentsToHighlight.isEmpty() ? null : new GeneralPath();
+
+        Iterator<Point> it = new OffsetIterator(wayNodes, offset);
         while (it.hasNext()) {
             Point p = it.next();
             if (lastPoint != null) {
@@ -153,7 +172,15 @@
                         path.moveTo(p1.x, p1.y);
                     }
                     p2 = clip.getP2();
-                    path.lineTo(p2.x, p2.y);
+                    if(segmentsToHighlight.contains(offset)) {
+                        path.moveTo(p2.x, p2.y);
+                        // it is assumed that highlighted segments are not
+                        // next to each other.
+                        highlightSegs.moveTo(p1.x, p1.y);
+                        highlightSegs.lineTo(p2.x, p2.y);
+                    } else {
+                        path.lineTo(p2.x, p2.y);
+                    }
 
                     /* draw arrow */
                     if (showHeadArrowOnly ? !it.hasNext() : showOrientation) {
@@ -207,8 +234,10 @@
                 }
             }
             lastPoint = p;
+            // have the offset variable point to the current segment
+            offset++;
         }
-        displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor);
+        displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, highlightSegs, color, line, dashes, dashedColor);
     }
 
     /**
@@ -220,11 +249,11 @@
      * perfect way, but it is should not throw an exception.
      */
     public class OffsetIterator implements Iterator<Point> {
-        
+
         private List<Node> nodes;
         private int offset;
         private int idx;
-        
+
         private Point prev = null;
         /* 'prev0' is a point that has distance 'offset' from 'prev' and the
          * line from 'prev' to 'prev0' is perpendicular to the way segment from
@@ -237,7 +266,7 @@
             this.offset = offset;
             idx = 0;
         }
-        
+
         @Override
         public boolean hasNext() {
             return idx < nodes.size();
@@ -246,9 +275,9 @@
         @Override
         public Point next() {
             if (offset == 0) return nc.getPoint(nodes.get(idx++));
-            
+
             Point current = nc.getPoint(nodes.get(idx));
-            
+
             if (idx == nodes.size() - 1) {
                 ++idx;
                 return new Point(x_prev0 + current.x - prev.x, y_prev0 + current.y - prev.y);
@@ -276,11 +305,11 @@
             } else {
                 int dx_prev = current.x - prev.x;
                 int dy_prev = current.y - prev.y;
-                
+
                 // determine intersection of the lines parallel to the two
                 // segments
                 int det = dx_next*dy_prev - dx_prev*dy_next;
-                
+
                 if (det == 0) {
                     ++idx;
                     prev = current;
@@ -306,19 +335,28 @@
             throw new UnsupportedOperationException();
         }
     }
-    
-    private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing,
-            Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
+
+    private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows,
+            GeneralPath onewayArrowsCasing, GeneralPath highlightedSegments, Color color, BasicStroke line,
+            BasicStroke dashes, Color dashedColor) {
         g.setColor(inactive ? inactiveColor : color);
         if (useStrokes) {
             g.setStroke(line);
         }
         g.draw(path);
 
+        if(highlightedSegments != null) {
+            g.setColor(highlightColor);
+            g.draw(highlightedSegments);
+        }
+
         if(!inactive && useStrokes && dashes != null) {
             g.setColor(dashedColor);
             g.setStroke(dashes);
             g.draw(path);
+            if(highlightedSegments != null) {
+                g.draw(highlightedSegments);
+            }
         }
 
         if (orientationArrows != null) {
@@ -997,18 +1035,29 @@
                 pVia, vx, vx2, vy, vy2, iconAngle, r.isSelected());
     }
 
-    public void drawVirtualNodes(Collection<Way> ways) {
-
-        if (virtualNodeSize != 0) {
-            GeneralPath path = new GeneralPath();
-            for (Way osm: ways){
-                if (osm.isUsable() && !osm.isDisabled()) {
-                    visitVirtual(path, osm);
-                }
+    public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) {
+        if (virtualNodeSize == 0)
+            return;
+        // print normal virtual nodes
+        GeneralPath path = new GeneralPath();
+        for (Way osm: ways){
+            if (osm.isUsable() && !osm.isDisabled()) {
+                visitVirtual(path, osm);
             }
-            g.setColor(nodeColor);
-            g.draw(path);
         }
+        g.setColor(nodeColor);
+        g.draw(path);
+        // print highlighted virtual nodes. Since only the color changes, simply
+        // drawing them over the existing ones works fine (at least in their current
+        // simple style)
+        path = new GeneralPath();
+        for (WaySegment wseg: highlightVirtualNodes){
+            if (wseg.way.isUsable() && !wseg.way.isDisabled()) {
+                visitVirtual(path, wseg.toWay());
+            }
+        }
+        g.setColor(highlightColor);
+        g.draw(path);
     }
 
     public void visitVirtual(GeneralPath path, Way w) {
Index: src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java	(revision 4320)
+++ src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java	(working copy)
@@ -24,6 +24,7 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 
@@ -127,6 +128,7 @@
     }
 
     DataSet ds;
+
     public void render(DataSet data, boolean virtual, Bounds bounds) {
         BBox bbox = new BBox(bounds);
         this.ds = data;
@@ -167,7 +169,16 @@
                 osm.visit(this);
             }
         }
-        drawVirtualNodes(data.searchWays(bbox));
+        drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
+
+        // draw highlighted way segments over the already drawn ways. Otherwise each
+        // way would have to be checked if it contains a way segment to highlight when
+        // in most of the cases there won't be more than one segment. Since the wireframe
+        // renderer does not feature any transparency there should be no visual difference.
+        for(final WaySegment wseg : data.getHighlightedWaySegments()) {
+            drawSegment(nc.getPoint(wseg.getFirstNode()), nc.getPoint(wseg.getSecondNode()), highlightColor, false);
+        }
+        displaySegments();
     }
 
     private static final int max(int a, int b, int c, int d) {
@@ -227,18 +238,29 @@
         return (xd+yd > space);
     }
 
-    public void drawVirtualNodes(Collection<Way> ways) {
-
-        if (virtualNodeSize != 0) {
-            GeneralPath path = new GeneralPath();
-            for (Way osm: ways){
-                if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {
-                    visitVirtual(path, osm);
-                }
+    public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) {
+        if (virtualNodeSize == 0)
+            return;
+        // print normal virtual nodes
+        GeneralPath path = new GeneralPath();
+        for (Way osm : ways) {
+            if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {
+                visitVirtual(path, osm);
             }
-            g.setColor(nodeColor);
-            g.draw(path);
         }
+        g.setColor(nodeColor);
+        g.draw(path);
+        // print highlighted virtual nodes. Since only the color changes, simply
+        // drawing them over the existing ones works fine (at least in their current
+        // simple style)
+        path = new GeneralPath();
+        for (WaySegment wseg: highlightVirtualNodes){
+            if (wseg.way.isUsable() && !wseg.way.isDisabled()) {
+                visitVirtual(path, wseg.toWay());
+            }
+        }
+        g.setColor(highlightColor);
+        g.draw(path);
     }
 
     public void visitVirtual(GeneralPath path, Way w) {
@@ -308,6 +330,7 @@
 
     private Stroke relatedWayStroke = new BasicStroke(
             4, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL);
+
     public void visit(Relation r) {
         if (r.isIncomplete()) return;
 
@@ -428,7 +451,7 @@
                 final double sy = l * (p1.y - p2.y);
 
                 path.lineTo (p2.x + (int) Math.round(cosPHI * sx - sinPHI * sy), p2.y + (int) Math.round(sinPHI * sx + cosPHI * sy));
-                path.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(- sinPHI * sx + cosPHI * sy));
+                path.moveTo (p2.x + (int) Math.round(cosPHI * sx + sinPHI * sy), p2.y + (int) Math.round(-sinPHI * sx + cosPHI * sy));
                 path.lineTo(p2.x, p2.y);
             }
         }
Index: src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 4320)
+++ src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(working copy)
@@ -4,6 +4,7 @@
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -15,6 +16,7 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
 import org.openstreetmap.josm.gui.mappaint.ElemStyle;
@@ -219,8 +221,10 @@
                 Main.pref.getBoolean("mappaint.use-antialiasing", true) ?
                         RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
 
-        this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic);
+        Collection<WaySegment> hws = data.getHighlightedWaySegments();
 
+        this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic, hws);
+
         StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction);
         collectNodeStyles(data, sc, bbox);
         collectWayStyles(data, sc, bbox);
@@ -228,7 +232,7 @@
         //long phase1 = System.currentTimeMillis();
         sc.drawAll();
         sc = null;
-        painter.drawVirtualNodes(data.searchWays(bbox));
+        painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
 
         //long now = System.currentTimeMillis();
         //System.err.println(String.format("PAINTING TOOK %d [PHASE1 took %d] (at scale %s)", now - start, phase1 - start, circum));
